-Bug-Debian: http://bugs.debian.org/685983
-
-
---- a/java/com/lowagie/text/pdf/PdfWriter.java
-+++ b/java/com/lowagie/text/pdf/PdfWriter.java
-@@ -325,7 +325,7 @@
-
- int getIndirectReferenceNumber() {
- int n = refnum++;
-- xrefs.add(new PdfCrossReference(n, 0, 65536));
-+ xrefs.add(new PdfCrossReference(n, 0, 65535));
- return n;
- }
-
diff -Nru pdftk-1.45/debian/patches/overwrite_more_lc_environ_variables pdftk-2.01/debian/patches/overwrite_more_lc_environ_variables
--- pdftk-1.45/debian/patches/overwrite_more_lc_environ_variables 2013-02-03 17:33:23.000000000 +0000
+++ pdftk-2.01/debian/patches/overwrite_more_lc_environ_variables 2013-06-17 22:21:53.000000000 +0000
@@ -9,7 +9,7 @@
--- a/pdftk/pdftk.cc
+++ b/pdftk/pdftk.cc
-@@ -3308,6 +3308,11 @@
+@@ -3650,6 +3650,11 @@
*/
static char my_lang[]="LANG=C";
putenv(my_lang);
diff -Nru pdftk-1.45/debian/patches/series pdftk-2.01/debian/patches/series
--- pdftk-1.45/debian/patches/series 2013-02-03 17:52:19.000000000 +0000
+++ pdftk-2.01/debian/patches/series 2013-06-30 23:20:22.000000000 +0000
@@ -1,7 +1,4 @@
customise_build_parameters
-fix_double_pw_prompt_bug
drm_fix
-fix_pdfwriter_nullpointerexception
overwrite_more_lc_environ_variables
-fix_pdfwriter_wrong_xref_entries
-fix_objstm_ends_with_number
+fix_hyphen_pdftk.1_man
diff -Nru pdftk-1.45/java/Makefile pdftk-2.01/java/Makefile
--- pdftk-1.45/java/Makefile 2010-10-12 13:31:00.000000000 +0000
+++ pdftk-2.01/java/Makefile 2013-06-05 14:08:22.000000000 +0000
@@ -1,5 +1,5 @@
# -*- Mode: Makefile -*-
-# Copyright 2003, 2004, 2010 Sid Steward
+# Copyright (c) 2003-2013 Sid Steward
# This is part of pdftk
#
# Visit: www.pdftk.com for pdftk information and articles
@@ -9,54 +9,32 @@
# Include "pdftk" in the subject line to ensure successful delivery:
# sid.steward at pdflabs dot com
#
-# Skipping RTF package because gcjh is complaining that
-# a static member has the same name as a method, but doesn't
-# tell me where the ambiguity is. Since it isn't needed for
-# pdftk, I left it out until I have time to find the trouble.
-#
-# also omitting hyphenation, html, since they aren't needed by pdftk
JAVALIBPATH= $(CURDIR)
-# preprocess this file so it might include our local copies of library objects: libgcj_local
-com/lowagie/text/pdf/PdfEncryption.java : com/lowagie/text/pdf/PdfEncryption.java.c
-ifdef USE_LOCAL_LIBGCJ
- cpp -C -P -DPDFTK_JAVA_LOCAL com/lowagie/text/pdf/PdfEncryption.java.c com/lowagie/text/pdf/PdfEncryption.java
-else
- cpp -C -P com/lowagie/text/pdf/PdfEncryption.java.c com/lowagie/text/pdf/PdfEncryption.java
-endif
-
#
export GCJFLAGS+= --encoding=UTF-8 --classpath="$(LIBGCJ):$(JAVALIBPATH):."
export GCJHFLAGS+= --classpath="$(LIBGCJ):$(JAVALIBPATH):."
-sources= $(wildcard com/lowagie/text/*.java)
-sources+= $(wildcard com/lowagie/text/markup/*.java)
-sources+= $(wildcard com/lowagie/text/pdf/*.java)
-sources+= com/lowagie/text/pdf/PdfEncryption.java
-#sources+= $(wildcard com/lowagie/text/pdf/codec/*.java)
-#sources+= $(wildcard com/lowagie/text/pdf/codec/wmf/*.java)
-#sources+= $(wildcard com/lowagie/text/pdf/codec/postscript/*.java)
-sources+= $(wildcard com/lowagie/text/pdf/fonts/*.java)
-sources+= $(wildcard com/lowagie/text/xml/xmp/*.java)
-#sources+= $(wildcard com/lowagie/bc/asn1/*.java)
-sources+= $(wildcard org/bouncycastle/util/*.java)
-sources+= $(wildcard org/bouncycastle/util/encoders/*.java)
-sources+= $(wildcard org/bouncycastle/util/io/*.java)
-sources+= $(wildcard org/bouncycastle/asn1/*.java)
+sources = $(wildcard pdftk/com/lowagie/text/*.java)
+sources+= $(wildcard pdftk/com/lowagie/text/exceptions/*.java)
+sources+= $(wildcard pdftk/com/lowagie/text/pdf/*.java)
+sources+= $(wildcard pdftk/com/lowagie/text/pdf/crypto/*.java)
+sources+= $(wildcard pdftk/com/lowagie/text/pdf/fonts/*.java)
+sources+= $(wildcard pdftk/com/lowagie/text/pdf/interfaces/*.java)
+sources+= $(wildcard pdftk/com/lowagie/text/pdf/internal/*.java)
+#
+sources+= $(wildcard pdftk/com/lowagie/text/markup/*.java)
+sources+= $(wildcard pdftk/com/lowagie/text/xml/xmp/*.java)
+
+# this next line isn't necessary for newer build tools
+# regen Makefile.bc_sources after upgrading bouncycastle
+include Makefile.bc_sources
headers= $(patsubst %.java, %.h, $(sources))
# for afm resources
-afms= $(wildcard com/lowagie/text/pdf/fonts/*.afm)
-
-ifdef GCJ_LOCAL_LIB
-libgcj_local_sources= $(wildcard gnu_local/java/security/*.java)
-libgcj_local_sources+= $(wildcard gnu_local/java/security/provider/*.java)
-libgcj_local_sources+= $(wildcard java_local/security/*.java)
-#
-libgcj_local_classes= $(patsubst %.java, %.class, $(libgcj_local_sources))
-endif
+afms= $(wildcard pdftk/com/lowagie/text/pdf/fonts/*.afm)
# don't automatically delete intermediate class files
.PRECIOUS : %.class
@@ -69,37 +47,31 @@
# don't create class list from java filenames because it omits local classes
java_lib.o : $(headers) $(sources)
- $(GJAR) -cf java_lib.jar com/lowagie/*/*/*/*.class com/lowagie/*/*/*.class com/lowagie/*/*.class org/bouncycastle/*/*.class org/bouncycastle/*/*/*.class $(afms)
+ $(GJAR) -cf java_lib.jar pdftk/com/lowagie/*/*/*/*.class pdftk/com/lowagie/*/*/*.class pdftk/com/lowagie/*/*.class pdftk/org/bouncycastle/*/*.class pdftk/org/bouncycastle/*/*/*.class $(afms)
$(GCJ) $(GCJFLAGS) -c java_lib.jar
-ifdef GCJ_LOCAL_LIB
-$(GCJ_LOCAL_LIB) : $(libgcj_local_classes)
- $(GJAR) -cf gcj_local_lib.jar gnu_local/java/security/*.class gnu_local/java/security/provider/*.class java_local/security/*.class
- $(GCJ) $(GCJFLAGS) -c gcj_local_lib.jar
+
+ifdef LIBGCJ_SUPPLEMENT
+libgcj_supplement_sources = $(wildcard java/security/*.java)
+libgcj_supplement_classes = $(patsubst %.java, %.class, $(libgcj_supplement_sources))
+
+LIBGCJ_SUPPLEMENT_O= $(LIBGCJ_SUPPLEMENT).o
+LIBGCJ_SUPPLEMENT_JAR= $(LIBGCJ_SUPPLEMENT).jar
+
+# don't use class list from java filenames because it omits local classes
+$(LIBGCJ_SUPPLEMENT_O) : $(libgcj_supplement_classes) $(libgcj_supplement_sources)
+ $(GJAR) -cf $(LIBGCJ_SUPPLEMENT_JAR) java/security/*.class
+ $(GCJ) $(GCJFLAGS) -c $(LIBGCJ_SUPPLEMENT_JAR)
endif
-all : com/lowagie/text/pdf/PdfEncryption.java java_lib.o $(GCJ_LOCAL_LIB)
-clean : itext_clean libgcj_local_clean
+all : java_lib.o $(LIBGCJ_SUPPLEMENT_O)
-itext_clean :
+clean :
$(RM) $(RMFLAGS) java_lib.jar java_lib.o;
- $(RM) $(RMFLAGS) com/lowagie/text/pdf/PdfEncryption.java;
- $(MAKE) -iC "$(JAVALIBPATH)/com/lowagie/text" clean;
- $(MAKE) -iC "$(JAVALIBPATH)/com/lowagie/text/markup" clean;
- $(MAKE) -iC "$(JAVALIBPATH)/com/lowagie/text/pdf" clean;
-# $(MAKE) -iC "$(JAVALIBPATH)/com/lowagie/text/pdf/codec" clean;
-# $(MAKE) -iC "$(JAVALIBPATH)/com/lowagie/text/pdf/codec/wmf" clean;
-# $(MAKE) -iC "$(JAVALIBPATH)/com/lowagie/text/pdf/codec/postscript" clean;
- $(MAKE) -iC "$(JAVALIBPATH)/com/lowagie/text/pdf/fonts" clean;
- $(MAKE) -iC "$(JAVALIBPATH)/com/lowagie/text/xml/xmp" clean;
-# $(MAKE) -iC "$(JAVALIBPATH)/com/lowagie/bc/asn1" clean;
- $(MAKE) -iC "$(JAVALIBPATH)/org/bouncycastle/util" clean;
- $(MAKE) -iC "$(JAVALIBPATH)/org/bouncycastle/util/encoders" clean;
- $(MAKE) -iC "$(JAVALIBPATH)/org/bouncycastle/util/io" clean;
- $(MAKE) -iC "$(JAVALIBPATH)/org/bouncycastle/asn1" clean;
-
-libgcj_local_clean :
- $(MAKE) -iC "$(JAVALIBPATH)/gnu_local/java/security" clean;
- $(MAKE) -iC "$(JAVALIBPATH)/gnu_local/java/security/provider" clean;
- $(MAKE) -iC "$(JAVALIBPATH)/java_local/security" clean;
\ No newline at end of file
+ $(RM) $(RMFLAGS) pdftk/com/lowagie/*/*/*/*.class pdftk/com/lowagie/*/*/*.class pdftk/com/lowagie/*/*.class pdftk/org/bouncycastle/*/*.class pdftk/org/bouncycastle/*/*/*.class;
+ $(RM) $(RMFLAGS) $(headers);
+ifdef LIBGCJ_SUPPLEMENT
+ $(RM) $(RMFLAGS) $(LIBGCJ_SUPPLEMENT_JAR) $(LIBGCJ_SUPPLEMENT_O);
+ $(RM) $(RMFLAGS) java/security/*.class
+endif
\ No newline at end of file
diff -Nru pdftk-1.45/java/Makefile.bc_sources pdftk-2.01/java/Makefile.bc_sources
--- pdftk-1.45/java/Makefile.bc_sources 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/Makefile.bc_sources 2013-05-02 06:41:02.000000000 +0000
@@ -0,0 +1,107 @@
+sources+= pdftk/org/bouncycastle/asn1/DERBoolean.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1Encodable.java
+sources+= pdftk/org/bouncycastle/asn1/BEROctetStringParser.java
+sources+= pdftk/org/bouncycastle/asn1/DERGeneralizedTime.java
+sources+= pdftk/org/bouncycastle/asn1/DERApplicationSpecific.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1Set.java
+sources+= pdftk/org/bouncycastle/asn1/DERSet.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1Sequence.java
+sources+= pdftk/org/bouncycastle/asn1/DERExternal.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1OctetStringParser.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1OutputStream.java
+sources+= pdftk/org/bouncycastle/asn1/DERBMPString.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1InputStream.java
+sources+= pdftk/org/bouncycastle/asn1/DERTaggedObject.java
+sources+= pdftk/org/bouncycastle/asn1/DERNumericString.java
+sources+= pdftk/org/bouncycastle/asn1/DEROctetStringParser.java
+sources+= pdftk/org/bouncycastle/asn1/DERSequence.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1TaggedObject.java
+sources+= pdftk/org/bouncycastle/asn1/DERUTF8String.java
+sources+= pdftk/org/bouncycastle/asn1/InMemoryRepresentable.java
+sources+= pdftk/org/bouncycastle/asn1/DERObjectIdentifier.java
+sources+= pdftk/org/bouncycastle/asn1/DERInteger.java
+sources+= pdftk/org/bouncycastle/asn1/DERSetParser.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1TaggedObjectParser.java
+sources+= pdftk/org/bouncycastle/asn1/DERNull.java
+sources+= pdftk/org/bouncycastle/asn1/BERTags.java
+sources+= pdftk/org/bouncycastle/asn1/DERUniversalString.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1SetParser.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1Object.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1Integer.java
+sources+= pdftk/org/bouncycastle/asn1/DefiniteLengthInputStream.java
+sources+= pdftk/org/bouncycastle/asn1/BERApplicationSpecific.java
+sources+= pdftk/org/bouncycastle/asn1/DERUTCTime.java
+sources+= pdftk/org/bouncycastle/asn1/BERSetParser.java
+sources+= pdftk/org/bouncycastle/asn1/DERFactory.java
+sources+= pdftk/org/bouncycastle/asn1/BERSequenceParser.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1Choice.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1Null.java
+sources+= pdftk/org/bouncycastle/asn1/BERSet.java
+sources+= pdftk/org/bouncycastle/asn1/DERBitString.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1Exception.java
+sources+= pdftk/org/bouncycastle/asn1/OIDTokenizer.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1ParsingException.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1Encoding.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1StreamParser.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1Primitive.java
+sources+= pdftk/org/bouncycastle/asn1/DERPrintableString.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1SequenceParser.java
+sources+= pdftk/org/bouncycastle/asn1/DERSequenceParser.java
+sources+= pdftk/org/bouncycastle/asn1/DERIA5String.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1OctetString.java
+sources+= pdftk/org/bouncycastle/asn1/BERFactory.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1Boolean.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1GeneralizedTime.java
+sources+= pdftk/org/bouncycastle/asn1/BERTaggedObject.java
+sources+= pdftk/org/bouncycastle/asn1/BERApplicationSpecificParser.java
+sources+= pdftk/org/bouncycastle/asn1/DERGeneralString.java
+sources+= pdftk/org/bouncycastle/asn1/DLSet.java
+sources+= pdftk/org/bouncycastle/asn1/DLTaggedObject.java
+sources+= pdftk/org/bouncycastle/asn1/DERExternalParser.java
+sources+= pdftk/org/bouncycastle/asn1/DEROutputStream.java
+sources+= pdftk/org/bouncycastle/asn1/BERSequence.java
+sources+= pdftk/org/bouncycastle/asn1/DLSequence.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1String.java
+sources+= pdftk/org/bouncycastle/asn1/DERT61String.java
+sources+= pdftk/org/bouncycastle/asn1/LimitedInputStream.java
+sources+= pdftk/org/bouncycastle/asn1/DEROctetString.java
+sources+= pdftk/org/bouncycastle/asn1/ConstructedOctetStream.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1EncodableVector.java
+sources+= pdftk/org/bouncycastle/asn1/DLOutputStream.java
+sources+= pdftk/org/bouncycastle/asn1/DEREnumerated.java
+sources+= pdftk/org/bouncycastle/asn1/LazyEncodedSequence.java
+sources+= pdftk/org/bouncycastle/asn1/DERVisibleString.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1Enumerated.java
+sources+= pdftk/org/bouncycastle/asn1/StreamUtil.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
+sources+= pdftk/org/bouncycastle/asn1/BEROctetString.java
+sources+= pdftk/org/bouncycastle/asn1/LazyConstructionEnumeration.java
+sources+= pdftk/org/bouncycastle/asn1/BERTaggedObjectParser.java
+sources+= pdftk/org/bouncycastle/asn1/ASN1UTCTime.java
+sources+= pdftk/org/bouncycastle/asn1/IndefiniteLengthInputStream.java
+sources+= pdftk/org/bouncycastle/util/io/StreamOverflowException.java
+sources+= pdftk/org/bouncycastle/util/io/Streams.java
+sources+= pdftk/org/bouncycastle/util/Arrays.java
+sources+= pdftk/org/bouncycastle/util/Strings.java
+sources+= pdftk/org/bouncycastle/util/encoders/HexEncoder.java
+sources+= pdftk/org/bouncycastle/util/encoders/EncoderException.java
+sources+= pdftk/org/bouncycastle/util/encoders/DecoderException.java
+sources+= pdftk/org/bouncycastle/util/encoders/Encoder.java
+sources+= pdftk/org/bouncycastle/util/encoders/Hex.java
+sources+= pdftk/org/bouncycastle/crypto/CipherParameters.java
+sources+= pdftk/org/bouncycastle/crypto/BufferedBlockCipher.java
+sources+= pdftk/org/bouncycastle/crypto/CryptoException.java
+sources+= pdftk/org/bouncycastle/crypto/modes/CBCBlockCipher.java
+sources+= pdftk/org/bouncycastle/crypto/params/KeyParameter.java
+sources+= pdftk/org/bouncycastle/crypto/params/ParametersWithRandom.java
+sources+= pdftk/org/bouncycastle/crypto/params/ParametersWithIV.java
+sources+= pdftk/org/bouncycastle/crypto/OutputLengthException.java
+sources+= pdftk/org/bouncycastle/crypto/BlockCipher.java
+sources+= pdftk/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java
+sources+= pdftk/org/bouncycastle/crypto/paddings/PKCS7Padding.java
+sources+= pdftk/org/bouncycastle/crypto/paddings/BlockCipherPadding.java
+sources+= pdftk/org/bouncycastle/crypto/engines/AESFastEngine.java
+sources+= pdftk/org/bouncycastle/crypto/RuntimeCryptoException.java
+sources+= pdftk/org/bouncycastle/crypto/InvalidCipherTextException.java
+sources+= pdftk/org/bouncycastle/crypto/DataLengthException.java
diff -Nru pdftk-1.45/java/com/itext_lgpl_header.txt pdftk-2.01/java/com/itext_lgpl_header.txt
--- pdftk-1.45/java/com/itext_lgpl_header.txt 2010-09-22 15:06:26.000000000 +0000
+++ pdftk-2.01/java/com/itext_lgpl_header.txt 1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
diff -Nru pdftk-1.45/java/com/itext_replace_mpl_text_with_lgpl.sh pdftk-2.01/java/com/itext_replace_mpl_text_with_lgpl.sh
--- pdftk-1.45/java/com/itext_replace_mpl_text_with_lgpl.sh 2012-12-06 14:05:52.000000000 +0000
+++ pdftk-2.01/java/com/itext_replace_mpl_text_with_lgpl.sh 1970-01-01 00:00:00.000000000 +0000
@@ -1,63 +0,0 @@
-#!/bin/sh
-#
-# The original iText (itext-paulo-155) library files included these sections:
-
-#* The contents of this file are subject to the Mozilla Public License Version 1.1
-#* (the "License"); you may not use this file except in compliance with the License.
-#* You may obtain a copy of the License at http://www.mozilla.org/MPL/
-#*
-#* Software distributed under the License is distributed on an "AS IS" basis,
-#* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-#* for the specific language governing rights and limitations under the License.
-
-#* Alternatively, the contents of this file may be used under the terms of the
-#* LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
-#* provisions of LGPL are applicable instead of those above. If you wish to
-#* allow use of your version of this file only under the terms of the LGPL
-#* License and not to allow others to use your version of this file under
-#* the MPL, indicate your decision by deleting the provisions above and
-#* replace them with the notice and other provisions required by the LGPL.
-#* If you do not delete the provisions above, a recipient may use your version
-#* of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
-#*
-#* This library is free software; you can redistribute it and/or modify it
-#* under the terms of the MPL as stated above or under the terms of the GNU
-#* Library General Public License as published by the Free Software Foundation;
-#* either version 2 of the License, or any later version.
-#*
-#* This library is distributed in the hope that it will be useful, but WITHOUT
-#* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-#* FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
-#* details.
-
-# The pdftk code is distributed with a GPL, and it links with the iText library.
-# What is more, I have read many places that the GPL is incompatible with the
-# MPL. So I have replaced the above MPL/LGPL boilerplate with LGPL boilerplate
-# in all iText java files as described in this original MPL/LGPL boilerplate.
-#
-# This is the script I used for that purpose. You can find the LGPL boilerplate
-# I used in itext_lgpl_header.txt. This was copied from:
-# http://www.gnu.org/licenses/lgpl-2.0.html#SEC4
-#
-# If you have any questions, please contact me, Sid Steward, at:
-# sid.steward (at) pdflabs (dot) com
-#
-
-for file in `find . -name "*.java"`
-do
-echo $file
-sed -n -e '/ * The contents of this file are subject to the Mozilla Public License Version 1.1/,/limitations under the License.$/!p' $file | \
-sed -n -e '/ * Alternatively, the contents of this file may be used under the terms of the/,/ * details.$/!p' | \
-sed '/ * where applicable./r itext_lgpl_header.txt' > $file.foo
-mv $file.foo $file
-done
-
-# run again for special file
-for file in `find . -name "*.java.c"`
-do
-echo $file
-sed -n -e '/ * The contents of this file are subject to the Mozilla Public License Version 1.1/,/limitations under the License.$/!p' $file | \
-sed -n -e '/ * Alternatively, the contents of this file may be used under the terms of the/,/ * details.$/!p' | \
-sed '/ * where applicable./r itext_lgpl_header.txt' > $file.foo
-mv $file.foo $file
-done
diff -Nru pdftk-1.45/java/com/lowagie/text/Anchor.java pdftk-2.01/java/com/lowagie/text/Anchor.java
--- pdftk-1.45/java/com/lowagie/text/Anchor.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Anchor.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,371 +0,0 @@
-/*
- * $Id: Anchor.java,v 1.84 2005/05/03 13:03:49 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.net.URL;
-import java.net.MalformedURLException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Properties;
-
-import com.lowagie.text.markup.MarkupTags;
-import com.lowagie.text.markup.MarkupParser;
-
-/**
- * An Anchor
can be a reference or a destination of a reference.
- *
- * An Anchor
is a special kind of Phrase
.
- * It is constructed in the same way.
- *
- * Example:
- *
- * Anchor anchor = new Anchor("this is a link");
- * anchor.setName("LINK");
- * anchor.setReference("http://www.lowagie.com");
- *
- *
- * @see Element
- * @see Phrase
- */
-
-public class Anchor extends Phrase implements TextElementArray, MarkupAttributes {
-
- // membervariables
-
-/** This is the anchor tag. */
- public static final String ANCHOR = "anchor";
-
-/** This is the name of the Anchor
. */
- protected String name = null;
-
-/** This is the reference of the Anchor
. */
- protected String reference = null;
-
- // constructors
-
-/**
- * Constructs an Anchor
without specifying a leading.
- */
-
- public Anchor() {
- super(16);
- }
-
-/**
- * Constructs an Anchor
with a certain leading.
- *
- * @param leading the leading
- */
-
- public Anchor(float leading) {
- super(leading);
- }
-
-/**
- * Constructs an Anchor
with a certain Chunk
.
- *
- * @param chunk a Chunk
- */
-
- public Anchor(Chunk chunk) {
- super(chunk);
- }
-
-/**
- * Constructs an Anchor
with a certain String
.
- *
- * @param string a String
- */
-
- public Anchor(String string) {
- super(string);
- }
-
-/**
- * Constructs an Anchor
with a certain String
- * and a certain Font
.
- *
- * @param string a String
- * @param font a Font
- */
-
- public Anchor(String string, Font font) {
- super(string, font);
- }
-
-/**
- * Constructs an Anchor
with a certain Chunk
- * and a certain leading.
- *
- * @param leading the leading
- * @param chunk a Chunk
- */
-
- public Anchor(float leading, Chunk chunk) {
- super(leading, chunk);
- }
-
-/**
- * Constructs an Anchor
with a certain leading
- * and a certain String
.
- *
- * @param leading the leading
- * @param string a String
- */
-
- public Anchor(float leading, String string) {
- super(leading, string);
- }
-
-/**
- * Constructs an Anchor
with a certain leading,
- * a certain String
and a certain Font
.
- *
- * @param leading the leading
- * @param string a String
- * @param font a Font
- */
-
- public Anchor(float leading, String string, Font font) {
- super(leading, string, font);
- }
-
-/**
- * Returns an Anchor
that has been constructed taking in account
- * the value of some attributes .
- *
- * @param attributes Some attributes
- */
-
- public Anchor(Properties attributes) {
- this("", FontFactory.getFont(attributes));
- String value;
- if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
- Chunk chunk = new Chunk(value);
- if ((value = (String)attributes.remove(ElementTags.GENERICTAG)) != null) {
- chunk.setGenericTag(value);
- }
- add(chunk);
- }
- if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
- setLeading(Float.valueOf(value + "f").floatValue());
- }
- else if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_LINEHEIGHT)) != null) {
- setLeading(MarkupParser.parseLength(value));
- }
- if ((value = (String)attributes.remove(ElementTags.NAME)) != null) {
- setName(value);
- }
- if ((value = (String)attributes.remove(ElementTags.REFERENCE)) != null) {
- setReference(value);
- }
- if (attributes.size() > 0) setMarkupAttributes(attributes);
- }
-
- // implementation of the Element-methods
-
-/**
- * Processes the element by adding it (or the different parts) to an
- * ElementListener
.
- *
- * @param listener an ElementListener
- * @return true
if the element was processed successfully
- */
-
- public boolean process(ElementListener listener) {
- try {
- Chunk chunk;
- Iterator i = getChunks().iterator();
- boolean localDestination = (reference != null && reference.startsWith("#"));
- boolean notGotoOK = true;
- while (i.hasNext()) {
- chunk = (Chunk) i.next();
- if (name != null && notGotoOK && !chunk.isEmpty()) {
- chunk.setLocalDestination(name);
- notGotoOK = false;
- }
- if (localDestination) {
- chunk.setLocalGoto(reference.substring(1));
- }
- listener.add(chunk);
- }
- return true;
- }
- catch(DocumentException de) {
- return false;
- }
- }
-
-/**
- * Gets all the chunks in this element.
- *
- * @return an ArrayList
- */
-
- public ArrayList getChunks() {
- ArrayList tmp = new ArrayList();
- Chunk chunk;
- Iterator i = iterator();
- boolean localDestination = (reference != null && reference.startsWith("#"));
- boolean notGotoOK = true;
- while (i.hasNext()) {
- chunk = (Chunk) i.next();
- if (name != null && notGotoOK && !chunk.isEmpty()) {
- chunk.setLocalDestination(name);
- notGotoOK = false;
- }
- if (localDestination) {
- chunk.setLocalGoto(reference.substring(1));
- }
- else if (reference != null)
- chunk.setAnchor(reference);
- tmp.add(chunk);
- }
- return tmp;
- }
-
-/**
- * Gets the type of the text element.
- *
- * @return a type
- */
-
- public int type() {
- return Element.ANCHOR;
- }
-
- // methods
-
-/**
- * Gets an iterator of Element
s.
- *
- * @return an Iterator
- */
-
- // suggestion by by Curt Thompson
- public Iterator getElements() {
- return this.iterator();
- }
-
-/**
- * Sets the name of this Anchor
.
- *
- * @param name a new name
- */
-
- public void setName(String name) {
- this.name = name;
- }
-
-/**
- * Sets the reference of this Anchor
.
- *
- * @param reference a new reference
- */
-
- public void setReference(String reference) {
- this.reference = reference;
- }
-
- // methods to retrieve information
-
-/**
- * Returns the name of this Anchor
.
- *
- * @return a name
- */
-
- public String name() {
- return name;
- }
-
-/**
- * Gets the reference of this Anchor
.
- *
- * @return a reference
- */
-
- public String reference() {
- return reference;
- }
-
-/**
- * Gets the reference of this Anchor
.
- *
- * @return an URL
- */
-
- public URL url() {
- try {
- return new URL(reference);
- }
- catch(MalformedURLException mue) {
- return null;
- }
- }
-
-/**
- * Checks if a given tag corresponds with this object.
- *
- * @param tag the given tag
- * @return true if the tag corresponds
- */
-
- public static boolean isTag(String tag) {
- return ElementTags.ANCHOR.equals(tag);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/Annotation.java pdftk-2.01/java/com/lowagie/text/Annotation.java
--- pdftk-1.45/java/com/lowagie/text/Annotation.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Annotation.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,743 +0,0 @@
-/*
- * $Id: Annotation.java,v 1.70 2005/04/13 09:17:09 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.net.URL;
-import java.util.HashMap;
-import java.util.ArrayList;
-import java.util.Properties;
-import java.util.Set;
-
-/**
- * An Annotation
is a little note that can be added to a page on
- * a document.
- *
- * @see Element
- * @see Anchor
- */
-
-public class Annotation implements Element, MarkupAttributes {
-
- // membervariables
-
- /** This is a possible annotation type. */
- public static final int TEXT = 0;
-
- /** This is a possible annotation type. */
- public static final int URL_NET = 1;
-
- /** This is a possible annotation type. */
- public static final int URL_AS_STRING = 2;
-
- /** This is a possible annotation type. */
- public static final int FILE_DEST = 3;
-
- /** This is a possible annotation type. */
- public static final int FILE_PAGE = 4;
-
- /** This is a possible annotation type. */
- public static final int NAMED_DEST = 5;
-
- /** This is a possible annotation type. */
- public static final int LAUNCH = 6;
-
- /** This is a possible annotation type. */
- public static final int SCREEN = 7;
-
- /** This is a possible attribute. */
- public static String TITLE = "title";
-
- /** This is a possible attribute. */
- public static String CONTENT = "content";
-
- /** This is a possible attribute. */
- public static String URL = "url";
-
- /** This is a possible attribute. */
- public static String FILE = "file";
-
- /** This is a possible attribute. */
- public static String DESTINATION = "destination";
-
- /** This is a possible attribute. */
- public static String PAGE = "page";
-
- /** This is a possible attribute. */
- public static String NAMED = "named";
-
- /** This is a possible attribute. */
- public static String APPLICATION = "application";
-
- /** This is a possible attribute. */
- public static String PARAMETERS = "parameters";
-
- /** This is a possible attribute. */
- public static String OPERATION = "operation";
-
- /** This is a possible attribute. */
- public static String DEFAULTDIR = "defaultdir";
-
- /** This is a possible attribute. */
- public static String LLX = "llx";
-
- /** This is a possible attribute. */
- public static String LLY = "lly";
-
- /** This is a possible attribute. */
- public static String URX = "urx";
-
- /** This is a possible attribute. */
- public static String URY = "ury";
-
- /** This is a possible attribute. */
- public static String MIMETYPE = "mime";
-
- /** This is the type of annotation. */
- protected int annotationtype;
-
- /** This is the title of the Annotation
. */
- protected HashMap annotationAttributes = new HashMap();
-
- /** Contains extra markupAttributes */
- protected Properties markupAttributes = null;
-
- /** This is the lower left x-value */
- protected float llx = Float.NaN;
-
- /** This is the lower left y-value */
- protected float lly = Float.NaN;
-
- /** This is the upper right x-value */
- protected float urx = Float.NaN;
-
- /** This is the upper right y-value */
- protected float ury = Float.NaN;
-
- // constructors
-
- /**
- * Constructs an Annotation
with a certain title and some
- * text.
- *
- * @param llx
- * lower left x coordinate
- * @param lly
- * lower left y coordinate
- * @param urx
- * upper right x coordinate
- * @param ury
- * upper right y coordinate
- */
-
- private Annotation(float llx, float lly, float urx, float ury) {
- this.llx = llx;
- this.lly = lly;
- this.urx = urx;
- this.ury = ury;
- }
-
- public Annotation(Annotation an) {
- annotationtype = an.annotationtype;
- annotationAttributes = an.annotationAttributes;
- markupAttributes = an.markupAttributes;
- llx = an.llx;
- lly = an.lly;
- urx = an.urx;
- ury = an.ury;
- }
-
- /**
- * Constructs an Annotation
with a certain title and some
- * text.
- *
- * @param title
- * the title of the annotation
- * @param text
- * the content of the annotation
- */
-
- public Annotation(String title, String text) {
- annotationtype = TEXT;
- annotationAttributes.put(TITLE, title);
- annotationAttributes.put(CONTENT, text);
- }
-
- /**
- * Constructs an Annotation
with a certain title and some
- * text.
- *
- * @param title
- * the title of the annotation
- * @param text
- * the content of the annotation
- * @param llx
- * the lower left x-value
- * @param lly
- * the lower left y-value
- * @param urx
- * the upper right x-value
- * @param ury
- * the upper right y-value
- */
-
- public Annotation(String title, String text, float llx, float lly,
- float urx, float ury) {
- this(llx, lly, urx, ury);
- annotationtype = TEXT;
- annotationAttributes.put(TITLE, title);
- annotationAttributes.put(CONTENT, text);
- }
-
- /**
- * Constructs an Annotation
.
- *
- * @param llx
- * the lower left x-value
- * @param lly
- * the lower left y-value
- * @param urx
- * the upper right x-value
- * @param ury
- * the upper right y-value
- * @param url
- * the external reference
- */
-
- public Annotation(float llx, float lly, float urx, float ury, URL url) {
- this(llx, lly, urx, ury);
- annotationtype = URL_NET;
- annotationAttributes.put(URL, url);
- }
-
- /**
- * Constructs an Annotation
.
- *
- * @param llx
- * the lower left x-value
- * @param lly
- * the lower left y-value
- * @param urx
- * the upper right x-value
- * @param ury
- * the upper right y-value
- * @param url
- * the external reference
- */
-
- public Annotation(float llx, float lly, float urx, float ury, String url) {
- this(llx, lly, urx, ury);
- annotationtype = URL_AS_STRING;
- annotationAttributes.put(FILE, url);
- }
-
- /**
- * Constructs an Annotation
.
- *
- * @param llx
- * the lower left x-value
- * @param lly
- * the lower left y-value
- * @param urx
- * the upper right x-value
- * @param ury
- * the upper right y-value
- * @param file
- * an external PDF file
- * @param dest
- * the destination in this file
- */
-
- public Annotation(float llx, float lly, float urx, float ury, String file,
- String dest) {
- this(llx, lly, urx, ury);
- annotationtype = FILE_DEST;
- annotationAttributes.put(FILE, file);
- annotationAttributes.put(DESTINATION, dest);
- }
-
- /**
- * Creates a Screen anotation to embed media clips
- *
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @param moviePath
- * path to the media clip file
- * @param mimeType
- * mime type of the media
- * @param showOnDisplay
- * if true play on display of the page
- */
- public Annotation(float llx, float lly, float urx, float ury,
- String moviePath, String mimeType, boolean showOnDisplay) {
- this(llx, lly, urx, ury);
- annotationtype = SCREEN;
- annotationAttributes.put(FILE, moviePath);
- annotationAttributes.put(MIMETYPE, mimeType);
- annotationAttributes.put(PARAMETERS, new boolean[] {
- false /* embedded */, showOnDisplay });
- }
-
- /**
- * Constructs an Annotation
.
- *
- * @param llx
- * the lower left x-value
- * @param lly
- * the lower left y-value
- * @param urx
- * the upper right x-value
- * @param ury
- * the upper right y-value
- * @param file
- * an external PDF file
- * @param page
- * a page number in this file
- */
-
- public Annotation(float llx, float lly, float urx, float ury, String file,
- int page) {
- this(llx, lly, urx, ury);
- annotationtype = FILE_PAGE;
- annotationAttributes.put(FILE, file);
- annotationAttributes.put(PAGE, new Integer(page));
- }
-
- /**
- * Constructs an Annotation
.
- *
- * @param llx
- * the lower left x-value
- * @param lly
- * the lower left y-value
- * @param urx
- * the upper right x-value
- * @param ury
- * the upper right y-value
- * @param named
- * a named destination in this file
- */
-
- public Annotation(float llx, float lly, float urx, float ury, int named) {
- this(llx, lly, urx, ury);
- annotationtype = NAMED_DEST;
- annotationAttributes.put(NAMED, new Integer(named));
- }
-
- /**
- * Constructs an Annotation
.
- *
- * @param llx
- * the lower left x-value
- * @param lly
- * the lower left y-value
- * @param urx
- * the upper right x-value
- * @param ury
- * the upper right y-value
- * @param application
- * an external application
- * @param parameters
- * parameters to pass to this application
- * @param operation
- * the operation to pass to this application
- * @param defaultdir
- * the default directory to run this application in
- */
-
- public Annotation(float llx, float lly, float urx, float ury,
- String application, String parameters, String operation,
- String defaultdir) {
- this(llx, lly, urx, ury);
- annotationtype = LAUNCH;
- annotationAttributes.put(APPLICATION, application);
- annotationAttributes.put(PARAMETERS, parameters);
- annotationAttributes.put(OPERATION, operation);
- annotationAttributes.put(DEFAULTDIR, defaultdir);
- }
-
- /**
- * Returns an Annotation
that has been constructed taking in
- * account the value of some attributes .
- *
- * @param attributes
- * Some attributes
- */
-
- public Annotation(Properties attributes) {
- String value = (String) attributes.remove(ElementTags.LLX);
- if (value != null) {
- llx = Float.valueOf(value + "f").floatValue();
- }
- value = (String) attributes.remove(ElementTags.LLY);
- if (value != null) {
- lly = Float.valueOf(value + "f").floatValue();
- }
- value = (String) attributes.remove(ElementTags.URX);
- if (value != null) {
- urx = Float.valueOf(value + "f").floatValue();
- }
- value = (String) attributes.remove(ElementTags.URY);
- if (value != null) {
- ury = Float.valueOf(value + "f").floatValue();
- }
- String title = (String) attributes.remove(ElementTags.TITLE);
- String text = (String) attributes.remove(ElementTags.CONTENT);
- if (title != null || text != null) {
- annotationtype = TEXT;
- } else if ((value = (String) attributes.remove(ElementTags.URL)) != null) {
- annotationtype = URL_AS_STRING;
- annotationAttributes.put(FILE, value);
- } else if ((value = (String) attributes.remove(ElementTags.NAMED)) != null) {
- annotationtype = NAMED_DEST;
- annotationAttributes.put(NAMED, Integer.valueOf(value));
- } else {
- String file = (String) attributes.remove(ElementTags.FILE);
- String destination = (String) attributes
- .remove(ElementTags.DESTINATION);
- String page = (String) attributes.remove(ElementTags.PAGE);
- if (file != null) {
- annotationAttributes.put(FILE, file);
- if (destination != null) {
- annotationtype = FILE_DEST;
- annotationAttributes.put(DESTINATION, destination);
- } else if (page != null) {
- annotationtype = FILE_PAGE;
- annotationAttributes.put(FILE, file);
- annotationAttributes.put(PAGE, Integer.valueOf(page));
- }
- } else if ((value = (String) attributes.remove(ElementTags.NAMED)) != null) {
- annotationtype = LAUNCH;
- annotationAttributes.put(APPLICATION, value);
- annotationAttributes.put(PARAMETERS, attributes
- .remove(ElementTags.PARAMETERS));
- annotationAttributes.put(OPERATION, attributes
- .remove(ElementTags.OPERATION));
- annotationAttributes.put(DEFAULTDIR, attributes
- .remove(ElementTags.DEFAULTDIR));
- }
- }
- if (annotationtype == TEXT) {
- if (title == null)
- title = "";
- if (text == null)
- text = "";
- annotationAttributes.put(TITLE, title);
- annotationAttributes.put(CONTENT, text);
- }
- if (attributes.size() > 0)
- setMarkupAttributes(attributes);
- }
-
- // implementation of the Element-methods
-
- /**
- * Gets the type of the text element.
- *
- * @return a type
- */
-
- public int type() {
- return Element.ANNOTATION;
- }
-
- // methods
-
- /**
- * Processes the element by adding it (or the different parts) to an
- * ElementListener
.
- *
- * @param listener
- * an ElementListener
- * @return true
if the element was processed successfully
- */
-
- public boolean process(ElementListener listener) {
- try {
- return listener.add(this);
- } catch (DocumentException de) {
- return false;
- }
- }
-
- /**
- * Gets all the chunks in this element.
- *
- * @return an ArrayList
- */
-
- public ArrayList getChunks() {
- return new ArrayList();
- }
-
- // methods
-
- /**
- * Sets the dimensions of this annotation.
- *
- * @param llx
- * the lower left x-value
- * @param lly
- * the lower left y-value
- * @param urx
- * the upper right x-value
- * @param ury
- * the upper right y-value
- */
-
- public void setDimensions(float llx, float lly, float urx, float ury) {
- this.llx = llx;
- this.lly = lly;
- this.urx = urx;
- this.ury = ury;
- }
-
- // methods to retrieve information
-
- /**
- * Returns the lower left x-value.
- *
- * @return a value
- */
-
- public float llx() {
- return llx;
- }
-
- /**
- * Returns the lower left y-value.
- *
- * @return a value
- */
-
- public float lly() {
- return lly;
- }
-
- /**
- * Returns the uppper right x-value.
- *
- * @return a value
- */
-
- public float urx() {
- return urx;
- }
-
- /**
- * Returns the uppper right y-value.
- *
- * @return a value
- */
-
- public float ury() {
- return ury;
- }
-
- /**
- * Returns the lower left x-value.
- *
- * @param def
- * the default value
- * @return a value
- */
-
- public float llx(float def) {
- if (Float.isNaN(llx))
- return def;
- return llx;
- }
-
- /**
- * Returns the lower left y-value.
- *
- * @param def
- * the default value
- * @return a value
- */
-
- public float lly(float def) {
- if (Float.isNaN(lly))
- return def;
- return lly;
- }
-
- /**
- * Returns the upper right x-value.
- *
- * @param def
- * the default value
- * @return a value
- */
-
- public float urx(float def) {
- if (Float.isNaN(urx))
- return def;
- return urx;
- }
-
- /**
- * Returns the upper right y-value.
- *
- * @param def
- * the default value
- * @return a value
- */
-
- public float ury(float def) {
- if (Float.isNaN(ury))
- return def;
- return ury;
- }
-
- /**
- * Returns the type of this Annotation
.
- *
- * @return a type
- */
-
- public int annotationType() {
- return annotationtype;
- }
-
- /**
- * Returns the title of this Annotation
.
- *
- * @return a name
- */
-
- public String title() {
- String s = (String) annotationAttributes.get(TITLE);
- if (s == null)
- s = "";
- return s;
- }
-
- /**
- * Gets the content of this Annotation
.
- *
- * @return a reference
- */
-
- public String content() {
- String s = (String) annotationAttributes.get(CONTENT);
- if (s == null)
- s = "";
- return s;
- }
-
- /**
- * Gets the content of this Annotation
.
- *
- * @return a reference
- */
-
- public HashMap attributes() {
- return annotationAttributes;
- }
-
- /**
- * Checks if a given tag corresponds with this object.
- *
- * @param tag
- * the given tag
- * @return true if the tag corresponds
- */
-
- public static boolean isTag(String tag) {
- return ElementTags.ANNOTATION.equals(tag);
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String,
- * java.lang.String)
- */
- public void setMarkupAttribute(String name, String value) {
- if (markupAttributes == null) markupAttributes = new Properties();
- markupAttributes.put(name, value);
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
- */
- public void setMarkupAttributes(Properties markupAttributes) {
- this.markupAttributes = markupAttributes;
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
- */
- public String getMarkupAttribute(String name) {
- return (markupAttributes == null) ? null : String
- .valueOf(markupAttributes.get(name));
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
- */
- public Set getMarkupAttributeNames() {
- return Chunk.getKeySet(markupAttributes);
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
- */
- public Properties getMarkupAttributes() {
- return markupAttributes;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/BadElementException.java pdftk-2.01/java/com/lowagie/text/BadElementException.java
--- pdftk-1.45/java/com/lowagie/text/BadElementException.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/BadElementException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,95 +0,0 @@
-/*
- * $Id: BadElementException.java,v 1.50 2004/12/14 11:33:49 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-/**
- * Signals an attempt to create an Element
that hasn't got the right form.
- *
- * @see DocumentException
- * @see Cell
- * @see Table
- */
-
-public class BadElementException extends DocumentException {
-
- // constructors
- /**
- * Constructs a BadElementException
- * @param ex an Exception object that has to be turned into a BadElementException
- */
- public BadElementException(Exception ex) {
- super(ex);
- }
-
-/**
- * Constructs a BadElementException
whithout a message.
- */
-
- BadElementException() {
- super();
- }
-
-/**
- * Constructs a BadElementException
with a message.
- *
- * @param message a message describing the exception
- */
-
- public BadElementException(String message) {
- super(message);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/Chunk.java pdftk-2.01/java/com/lowagie/text/Chunk.java
--- pdftk-1.45/java/com/lowagie/text/Chunk.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Chunk.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,924 +0,0 @@
-/*
- * $Id: Chunk.java,v 1.112 2005/10/05 07:23:47 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Properties;
-import java.util.Set;
-import java.net.URL;
-
-import com.lowagie.text.pdf.PdfAction;
-import com.lowagie.text.pdf.PdfAnnotation;
-import com.lowagie.text.pdf.HyphenationEvent;
-import com.lowagie.text.pdf.PdfContentByte;
-import com.lowagie.text.markup.MarkupTags;
-import com.lowagie.text.markup.MarkupParser;
-
-/**
- * This is the smallest significant part of text that can be added to a
- * document.
- *
- * Most elements can be divided in one or more Chunk
s. A chunk
- * is a String
with a certain Font
. all other
- * layoutparameters should be defined in the object to which this chunk of text
- * is added.
- *
- * Example:
- *
- *
- *
- * Chunk chunk = new Chunk("Hello world",
- * FontFactory.getFont(FontFactory.COURIER, 20, Font.ITALIC, new Color(255, 0,
- * 0))); document.add(chunk);
- *
- *
- *
- *
- */
-
-public class Chunk implements Element, MarkupAttributes {
-
- // public static membervariables
-
- /**
- * The character stand in for an image.
- */
- public static final String OBJECT_REPLACEMENT_CHARACTER = "\ufffc";
-
- /** This is a Chunk containing a newline. */
- public static final Chunk NEWLINE = new Chunk("\n");
-
- /** This is a Chunk containing a newpage. */
- public static final Chunk NEXTPAGE = new Chunk("");
- static {
- NEXTPAGE.setNewPage();
- }
-
- /** Key for sub/superscript. */
- public static final String SUBSUPSCRIPT = "SUBSUPSCRIPT";
-
- /** Key for underline. */
- public static final String UNDERLINE = "UNDERLINE";
-
- /** Key for color. */
- public static final String COLOR = "COLOR";
-
- /** Key for encoding. */
- public static final String ENCODING = "ENCODING";
-
- /** Key for remote goto. */
- public static final String REMOTEGOTO = "REMOTEGOTO";
-
- /** Key for local goto. */
- public static final String LOCALGOTO = "LOCALGOTO";
-
- /** Key for local destination. */
- public static final String LOCALDESTINATION = "LOCALDESTINATION";
-
- /** Key for image. */
- public static final String IMAGE = "IMAGE";
-
- /** Key for generic tag. */
- public static final String GENERICTAG = "GENERICTAG";
-
- /** Key for newpage. */
- public static final String NEWPAGE = "NEWPAGE";
-
- /** Key for split character. */
- public static final String SPLITCHARACTER = "SPLITCHARACTER";
-
- /** Key for Action. */
- public static final String ACTION = "ACTION";
-
- /** Key for background. */
- public static final String BACKGROUND = "BACKGROUND";
-
- /** Key for annotation. */
- public static final String PDFANNOTATION = "PDFANNOTATION";
-
- /** Key for hyphenation. */
- public static final String HYPHENATION = "HYPHENATION";
-
- /** Key for text rendering mode. */
- public static final String TEXTRENDERMODE = "TEXTRENDERMODE";
-
- /** Key for text skewing. */
- public static final String SKEW = "SKEW";
-
- /** Key for text horizontal scaling. */
- public static final String HSCALE = "HSCALE";
-
- // member variables
-
- /** This is the content of this chunk of text. */
- protected StringBuffer content = null;
-
- /** This is the Font
of this chunk of text. */
- protected Font font = null;
-
- /** Contains some of the attributes for this Chunk. */
- protected HashMap attributes = null;
-
- /** Contains extra markupAttributes */
- protected Properties markupAttributes = null;
-
- // constructors
-
- /**
- * Empty constructor.
- */
- protected Chunk() {
- }
-
- /**
- * Constructs a chunk of text with a certain content and a certain
- * Font
.
- *
- * @param content
- * the content
- * @param font
- * the font
- */
-
- public Chunk(String content, Font font) {
- this.content = new StringBuffer(content);
- this.font = font;
- }
-
- /**
- * Constructs a chunk of text with a certain content, without specifying a
- * Font
.
- *
- * @param content
- * the content
- */
- public Chunk(String content) {
- this(content, new Font());
- }
-
- /**
- * Constructs a chunk of text with a char and a certain Font
.
- *
- * @param c
- * the content
- * @param font
- * the font
- */
- public Chunk(char c, Font font) {
- this.content = new StringBuffer();
- this.content.append(c);
- this.font = font;
- }
-
- /**
- * Constructs a chunk of text with a char, without specifying a Font
- *
.
- *
- * @param c
- * the content
- */
- public Chunk(char c) {
- this(c, new Font());
- }
-
- /**
- * Constructs a chunk containing an Image
.
- *
- * @param image
- * the image
- * @param offsetX
- * the image offset in the x direction
- * @param offsetY
- * the image offset in the y direction
- */
- /* ssteward: dropped in 1.44
- public Chunk(Image image, float offsetX, float offsetY) {
- this(OBJECT_REPLACEMENT_CHARACTER, new Font());
- Image copyImage = Image.getInstance(image);
- copyImage.setAbsolutePosition(Float.NaN, Float.NaN);
- setAttribute(IMAGE, new Object[] { copyImage, new Float(offsetX),
- new Float(offsetY), new Boolean(false) });
- }
- */
-
- /**
- * Constructs a chunk containing an Image
.
- *
- * @param image
- * the image
- * @param offsetX
- * the image offset in the x direction
- * @param offsetY
- * the image offset in the y direction
- * @param changeLeading
- * true if the leading has to be adapted to the image
- */
- /* ssteward: dropped in 1.44
- public Chunk(Image image, float offsetX, float offsetY,
- boolean changeLeading) {
- this(OBJECT_REPLACEMENT_CHARACTER, new Font());
- setAttribute(IMAGE, new Object[] { image, new Float(offsetX),
- new Float(offsetY), new Boolean(changeLeading) });
- }
- */
- /**
- * Returns a Chunk
that has been constructed taking in
- * account the value of some attributes .
- *
- * @param attributes
- * Some attributes
- */
-
- public Chunk(Properties attributes) {
- this("", FontFactory.getFont(attributes));
- String value;
- if ((value = (String) attributes.remove(ElementTags.ITEXT)) != null) {
- append(value);
- }
- if ((value = (String) attributes.remove(ElementTags.LOCALGOTO)) != null) {
- setLocalGoto(value);
- }
- if ((value = (String) attributes.remove(ElementTags.REMOTEGOTO)) != null) {
- String destination = (String) attributes
- .remove(ElementTags.DESTINATION);
- String page = (String) attributes.remove(ElementTags.PAGE);
- if (page != null) {
- setRemoteGoto(value, Integer.valueOf(page).intValue());
- } else if (destination != null) {
- setRemoteGoto(value, destination);
- }
- }
- if ((value = (String) attributes.remove(ElementTags.LOCALDESTINATION)) != null) {
- setLocalDestination(value);
- }
- if ((value = (String) attributes.remove(ElementTags.SUBSUPSCRIPT)) != null) {
- setTextRise(Float.valueOf(value + "f").floatValue());
- }
- if ((value = (String) attributes
- .remove(MarkupTags.CSS_KEY_VERTICALALIGN)) != null
- && value.endsWith("%")) {
- float p = Float.valueOf(
- value.substring(0, value.length() - 1) + "f").floatValue() / 100f;
- setTextRise(p * font.size());
- }
- if ((value = (String) attributes.remove(ElementTags.GENERICTAG)) != null) {
- setGenericTag(value);
- }
- if ((value = (String) attributes.remove(ElementTags.BACKGROUNDCOLOR)) != null) {
- setBackground(MarkupParser.decodeColor(value));
- }
- if (attributes.size() > 0)
- setMarkupAttributes(attributes);
- }
-
- // implementation of the Element-methods
-
- /**
- * Processes the element by adding it (or the different parts) to an
- * ElementListener
.
- *
- * @param listener
- * an ElementListener
- * @return true
if the element was processed successfully
- */
-
- public boolean process(ElementListener listener) {
- try {
- return listener.add(this);
- } catch (DocumentException de) {
- return false;
- }
- }
-
- /**
- * Gets the type of the text element.
- *
- * @return a type
- */
-
- public int type() {
- return Element.CHUNK;
- }
-
- /**
- * Gets all the chunks in this element.
- *
- * @return an ArrayList
- */
-
- public ArrayList getChunks() {
- ArrayList tmp = new ArrayList();
- tmp.add(this);
- return tmp;
- }
-
- // methods
-
- /**
- * appends some text to this Chunk
.
- *
- * @param string
- * String
- * @return a StringBuffer
- */
-
- public StringBuffer append(String string) {
- return content.append(string);
- }
-
- // methods to retrieve information
-
- /**
- * Gets the font of this Chunk
.
- *
- * @return a Font
- */
-
- public Font font() {
- return font;
- }
-
- /**
- * Sets the font of this Chunk
.
- *
- * @param font
- * a Font
- */
-
- public void setFont(Font font) {
- this.font = font;
- }
-
- /**
- * Returns the content of this Chunk
.
- *
- * @return a String
- */
-
- public String content() {
- return content.toString();
- }
-
- /**
- * Returns the content of this Chunk
.
- *
- * @return a String
- */
-
- public String toString() {
- return content.toString();
- }
-
- /**
- * Checks is this Chunk
is empty.
- *
- * @return false
if the Chunk contains other characters than
- * space.
- */
-
- public boolean isEmpty() {
- return (content.toString().trim().length() == 0)
- && (content.toString().indexOf("\n") == -1)
- && (attributes == null);
- }
-
- /**
- * Gets the width of the Chunk in points.
- *
- * @return a width in points
- */
- public float getWidthPoint() {
- /* ssteward: dropped in 1.44
- if (getImage() != null) {
- return getImage().scaledWidth();
- }
- */
- return font.getCalculatedBaseFont(true).getWidthPoint(content(),
- font.getCalculatedSize())
- * getHorizontalScaling();
- }
-
- /**
- * Sets the text displacement relative to the baseline. Positive values rise
- * the text, negative values lower the text.
- *
- * It can be used to implement sub/superscript.
- *
- * @param rise
- * the displacement in points
- * @return this Chunk
- */
-
- public Chunk setTextRise(float rise) {
- return setAttribute(SUBSUPSCRIPT, new Float(rise));
- }
-
- /**
- * Gets the text displacement relatiev to the baseline.
- *
- * @return a displacement in points
- */
- public float getTextRise() {
- if (attributes.containsKey(SUBSUPSCRIPT)) {
- Float f = (Float) attributes.get(SUBSUPSCRIPT);
- return f.floatValue();
- }
- return 0.0f;
- }
-
- /**
- * Sets the text rendering mode. It can outline text, simulate bold and make
- * text invisible.
- *
- * @param mode
- * the text rendering mode. It can be
- * PdfContentByte.TEXT_RENDER_MODE_FILL
,
- * PdfContentByte.TEXT_RENDER_MODE_STROKE
,
- * PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE
and
- * PdfContentByte.TEXT_RENDER_MODE_INVISIBLE
.
- * @param strokeWidth
- * the stroke line width for the modes
- * PdfContentByte.TEXT_RENDER_MODE_STROKE
and
- * PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE
.
- * @param strokeColor
- * the stroke color or null
to follow the text
- * color
- * @return this Chunk
- */
- public Chunk setTextRenderMode(int mode, float strokeWidth,
- Color strokeColor) {
- return setAttribute(TEXTRENDERMODE, new Object[] { new Integer(mode),
- new Float(strokeWidth), strokeColor });
- }
-
- /**
- * Skews the text to simulate italic and other effects. Try alpha=0
- *
and beta=12
.
- *
- * @param alpha
- * the first angle in degrees
- * @param beta
- * the second angle in degrees
- * @return this Chunk
- */
- public Chunk setSkew(float alpha, float beta) {
- alpha = (float) Math.tan(alpha * Math.PI / 180);
- beta = (float) Math.tan(beta * Math.PI / 180);
- return setAttribute(SKEW, new float[] { alpha, beta });
- }
-
- /**
- * Sets the text horizontal scaling. A value of 1 is normal and a value of
- * 0.5f shrinks the text to half it's width.
- *
- * @param scale
- * the horizontal scaling factor
- * @return this Chunk
- */
- public Chunk setHorizontalScaling(float scale) {
- return setAttribute(HSCALE, new Float(scale));
- }
-
- /**
- * Gets the horizontal scaling.
- *
- * @return a percentage in float
- */
- public float getHorizontalScaling() {
- if (attributes == null)
- return 1f;
- Float f = (Float) attributes.get(HSCALE);
- if (f == null)
- return 1f;
- return f.floatValue();
- }
-
- /**
- * Sets an action for this Chunk
.
- *
- * @param action
- * the action
- * @return this Chunk
- */
-
- public Chunk setAction(PdfAction action) {
- return setAttribute(ACTION, action);
- }
-
- /**
- * Sets an anchor for this Chunk
.
- *
- * @param url
- * the URL
to link to
- * @return this Chunk
- */
-
- public Chunk setAnchor(URL url) {
- return setAttribute(ACTION, new PdfAction(url.toExternalForm()));
- }
-
- /**
- * Sets an anchor for this Chunk
.
- *
- * @param url
- * the url to link to
- * @return this Chunk
- */
-
- public Chunk setAnchor(String url) {
- return setAttribute(ACTION, new PdfAction(url));
- }
-
- /**
- * Sets a local goto for this Chunk
.
- *
- * There must be a local destination matching the name.
- *
- * @param name
- * the name of the destination to go to
- * @return this Chunk
- */
-
- public Chunk setLocalGoto(String name) {
- return setAttribute(LOCALGOTO, name);
- }
-
- /**
- * Sets the color of the background Chunk
.
- *
- * @param color
- * the color of the background
- * @return this Chunk
- */
- public Chunk setBackground(Color color) {
- return setBackground(color, 0, 0, 0, 0);
- }
-
- /**
- * Sets the color and the size of the background Chunk
.
- *
- * @param color
- * the color of the background
- * @param extraLeft
- * increase the size of the rectangle in the left
- * @param extraBottom
- * increase the size of the rectangle in the bottom
- * @param extraRight
- * increase the size of the rectangle in the right
- * @param extraTop
- * increase the size of the rectangle in the top
- * @return this Chunk
- */
- public Chunk setBackground(Color color, float extraLeft, float extraBottom,
- float extraRight, float extraTop) {
- return setAttribute(BACKGROUND, new Object[] { color,
- new float[] { extraLeft, extraBottom, extraRight, extraTop } });
- }
-
- /**
- * Sets an horizontal line that can be an underline or a strikethrough.
- * Actually, the line can be anywhere vertically and has always the
- * Chunk
width. Multiple call to this method will produce multiple
- * lines.
- *
- * @param thickness
- * the absolute thickness of the line
- * @param yPosition
- * the absolute y position relative to the baseline
- * @return this Chunk
- */
- public Chunk setUnderline(float thickness, float yPosition) {
- return setUnderline(null, thickness, 0f, yPosition, 0f,
- PdfContentByte.LINE_CAP_BUTT);
- }
-
- /**
- * Sets an horizontal line that can be an underline or a strikethrough.
- * Actually, the line can be anywhere vertically and has always the
- * Chunk
width. Multiple call to this method will produce multiple
- * lines.
- *
- * @param color
- * the color of the line or null
to follow the
- * text color
- * @param thickness
- * the absolute thickness of the line
- * @param thicknessMul
- * the thickness multiplication factor with the font size
- * @param yPosition
- * the absolute y position relative to the baseline
- * @param yPositionMul
- * the position multiplication factor with the font size
- * @param cap
- * the end line cap. Allowed values are
- * PdfContentByte.LINE_CAP_BUTT, PdfContentByte.LINE_CAP_ROUND
- * and PdfContentByte.LINE_CAP_PROJECTING_SQUARE
- * @return this Chunk
- */
- public Chunk setUnderline(Color color, float thickness, float thicknessMul,
- float yPosition, float yPositionMul, int cap) {
- if (attributes == null)
- attributes = new HashMap();
- Object obj[] = {
- color,
- new float[] { thickness, thicknessMul, yPosition, yPositionMul, cap } };
- Object unders[][] = addToArray((Object[][]) attributes.get(UNDERLINE),
- obj);
- return setAttribute(UNDERLINE, unders);
- }
-
- /**
- * Utility method to extend an array.
- *
- * @param original
- * the original array or null
- * @param item
- * the item to be added to the array
- * @return a new array with the item appended
- */
- public static Object[][] addToArray(Object original[][], Object item[]) {
- if (original == null) {
- original = new Object[1][];
- original[0] = item;
- return original;
- } else {
- Object original2[][] = new Object[original.length + 1][];
- System.arraycopy(original, 0, original2, 0, original.length);
- original2[original.length] = item;
- return original2;
- }
- }
-
- /**
- * Sets a generic annotation to this Chunk
.
- *
- * @param annotation
- * the annotation
- * @return this Chunk
- */
- public Chunk setAnnotation(PdfAnnotation annotation) {
- return setAttribute(PDFANNOTATION, annotation);
- }
-
- /**
- * sets the hyphenation engine to this Chunk
.
- *
- * @param hyphenation
- * the hyphenation engine
- * @return this Chunk
- */
- public Chunk setHyphenation(HyphenationEvent hyphenation) {
- return setAttribute(HYPHENATION, hyphenation);
- }
-
- /**
- * Sets a goto for a remote destination for this Chunk
.
- *
- * @param filename
- * the file name of the destination document
- * @param name
- * the name of the destination to go to
- * @return this Chunk
- */
-
- public Chunk setRemoteGoto(String filename, String name) {
- return setAttribute(REMOTEGOTO, new Object[] { filename, name });
- }
-
- /**
- * Sets a goto for a remote destination for this Chunk
.
- *
- * @param filename
- * the file name of the destination document
- * @param page
- * the page of the destination to go to. First page is 1
- * @return this Chunk
- */
-
- public Chunk setRemoteGoto(String filename, int page) {
- return setAttribute(REMOTEGOTO, new Object[] { filename,
- new Integer(page) });
- }
-
- /**
- * Sets a local destination for this Chunk
.
- *
- * @param name
- * the name for this destination
- * @return this Chunk
- */
- public Chunk setLocalDestination(String name) {
- return setAttribute(LOCALDESTINATION, name);
- }
-
- /**
- * Sets the generic tag Chunk
.
- *
- * The text for this tag can be retrieved with PdfPageEvent
.
- *
- * @param text
- * the text for the tag
- * @return this Chunk
- */
-
- public Chunk setGenericTag(String text) {
- return setAttribute(GENERICTAG, text);
- }
-
- /**
- * Sets the split characters.
- *
- * @param splitCharacter
- * the SplitCharacter
interface
- * @return this Chunk
- */
- public Chunk setSplitCharacter(SplitCharacter splitCharacter) {
- return setAttribute(SPLITCHARACTER, splitCharacter);
- }
-
- /**
- * Sets a new page tag..
- *
- * @return this Chunk
- */
-
- public Chunk setNewPage() {
- return setAttribute(NEWPAGE, null);
- }
-
- /**
- * Sets an arbitrary attribute.
- *
- * @param name
- * the key for the attribute
- * @param obj
- * the value of the attribute
- * @return this Chunk
- */
-
- private Chunk setAttribute(String name, Object obj) {
- if (attributes == null)
- attributes = new HashMap();
- attributes.put(name, obj);
- return this;
- }
-
- /**
- * Gets the attributes for this Chunk
.
- *
- * It may be null.
- *
- * @return the attributes for this Chunk
- */
-
- public HashMap getAttributes() {
- return attributes;
- }
-
- /**
- * Checks the attributes of this Chunk
.
- *
- * @return false if there aren't any.
- */
-
- public boolean hasAttributes() {
- return attributes != null;
- }
-
- /**
- * Returns the image.
- *
- * @return the image
- */
- /* ssteward: dropped in 1.44
- public Image getImage() {
- if (attributes == null)
- return null;
- Object obj[] = (Object[]) attributes.get(Chunk.IMAGE);
- if (obj == null)
- return null;
- else {
- return (Image) obj[0];
- }
- }
- */
- /**
- * Checks if a given tag corresponds with this object.
- *
- * @param tag
- * the given tag
- * @return true if the tag corresponds
- */
-
- public static boolean isTag(String tag) {
- return ElementTags.CHUNK.equals(tag);
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String,
- * java.lang.String)
- */
- public void setMarkupAttribute(String name, String value) {
- if (markupAttributes == null)
- markupAttributes = new Properties();
- markupAttributes.put(name, value);
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
- */
- public void setMarkupAttributes(Properties markupAttributes) {
- this.markupAttributes = markupAttributes;
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
- */
- public String getMarkupAttribute(String name) {
- return (markupAttributes == null) ? null : String
- .valueOf(markupAttributes.get(name));
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
- */
- public Set getMarkupAttributeNames() {
- return getKeySet(markupAttributes);
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
- */
- public Properties getMarkupAttributes() {
- return markupAttributes;
- }
-
- /**
- * Gets the keys of a Hashtable
- *
- * @param table
- * a Hashtable
- * @return the keyset of a Hashtable (or an empty set if table is null)
- */
- public static Set getKeySet(Hashtable table) {
- return (table == null) ? Collections.EMPTY_SET : table.keySet();
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/DocListener.java pdftk-2.01/java/com/lowagie/text/DocListener.java
--- pdftk-1.45/java/com/lowagie/text/DocListener.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/DocListener.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,188 +0,0 @@
-/*
- * $Id: DocListener.java,v 1.52 2004/12/14 11:52:47 blowagie Exp $
- * $Name: $
- *
- * Copyright (c) 1999, 2000, 2001, 2002 Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-/**
- * A class that implements DocListener
will perform some
- * actions when some actions are performed on a Document
.
- *
- * @see ElementListener
- * @see Document
- * @see DocWriter
- */
-
-public interface DocListener extends ElementListener {
-
- // methods
-
-/**
- * Signals that the Document
has been opened and that
- * Elements
can be added.
- */
-
- public void open();
-
-/**
- * Sets the pagesize.
- *
- * @param pageSize the new pagesize
- * @return a boolean
- */
-
- public boolean setPageSize(Rectangle pageSize);
-
-/**
- * Signals that a Watermark
was added to the Document
.
- *
- * @param watermark the Watermark object
- * @return true
if the element was added, false
if not.
- */
-
- // public boolean add(Watermark watermark); ssteward: dropped in 1.44
-
-/**
- * Signals that a Watermark
was removed from the Document
.
- */
-
- // public void removeWatermark(); ssteward: dropped in 1.44
-
-/**
- * Sets the margins.
- *
- * @param marginLeft the margin on the left
- * @param marginRight the margin on the right
- * @param marginTop the margin on the top
- * @param marginBottom the margin on the bottom
- * @return a boolean
- */
-
- public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom);
-
- /**
- * Parameter that allows you to do margin mirroring (odd/even pages)
- * @param marginMirroring
- * @return true if succesfull
- */
- public boolean setMarginMirroring(boolean marginMirroring);
-
-/**
- * Signals that an new page has to be started.
- *
- * @return true
if the page was added, false
if not.
- * @throws DocumentException when a document isn't open yet, or has been closed
- */
-
- public boolean newPage() throws DocumentException;
-
-/**
- * Changes the header of this document.
- *
- * @param header the new header
- */
-
- // public void setHeader(HeaderFooter header); ssteward: dropped in 1.44
-
-/**
- * Resets the header of this document.
- */
-
- // public void resetHeader(); ssteward: dropped in 1.44
-
-/**
- * Changes the footer of this document.
- *
- * @param footer the new footer
- */
-
- // public void setFooter(HeaderFooter footer); ssteward: dropped in 1.44
-
-/**
- * Resets the footer of this document.
- */
-
- // public void resetFooter(); ssteward: dropped in 1.44
-
-/**
- * Sets the page number to 0.
- */
-
- public void resetPageCount();
-
-/**
- * Sets the page number.
- *
- * @param pageN the new page number
- */
-
- public void setPageCount(int pageN);
-
-/**
- * Clears text wrapping around images (if applicable).
- * Method suggested by Pelikan Stephan
- * @throws DocumentException
- */
- public void clearTextWrap() throws DocumentException;
-
-/**
- * Signals that the Document
was closed and that no other
- * Elements
will be added.
- *
- * The outputstream of every writer implementing DocListener
will be closed.
- */
-
- public void close();
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/DocWriter.java pdftk-2.01/java/com/lowagie/text/DocWriter.java
--- pdftk-1.45/java/com/lowagie/text/DocWriter.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/DocWriter.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,521 +0,0 @@
-/*
- * $Id: DocWriter.java,v 1.70 2004/12/14 11:52:47 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.io.BufferedOutputStream;
-import java.io.OutputStream;
-import java.io.IOException;
-import java.util.Iterator;
-import com.lowagie.text.pdf.OutputStreamCounter;
-
-/**
- * An abstract Writer
class for documents.
- *
- * DocWriter
is the abstract class of several writers such
- * as PdfWriter
and HtmlWriter
.
- * A DocWriter
can be added as a DocListener
- * to a certain Document
by getting an instance (see method
- * getInstance()
in the specific writer-classes).
- * Every Element
added to the original Document
- * will be written to the OutputStream
of the listening
- * DocWriter
.
- *
- * @see Document
- * @see DocListener
- */
-
-public abstract class DocWriter implements DocListener {
-
-/** This is some byte that is often used. */
- public static final byte NEWLINE = (byte)'\n';
-
-/** This is some byte that is often used. */
- public static final byte TAB = (byte)'\t';
-
-/** This is some byte that is often used. */
- public static final byte LT = (byte)'<';
-
-/** This is some byte that is often used. */
- public static final byte SPACE = (byte)' ';
-
-/** This is some byte that is often used. */
- public static final byte EQUALS = (byte)'=';
-
-/** This is some byte that is often used. */
- public static final byte QUOTE = (byte)'\"';
-
-/** This is some byte that is often used. */
- public static final byte GT = (byte)'>';
-
-/** This is some byte that is often used. */
- public static final byte FORWARD = (byte)'/';
-
- // membervariables
-
-/** The pageSize. */
- protected Rectangle pageSize;
-
-/** This is the document that has to be written. */
- protected Document document;
-
-/** The outputstream of this writer. */
- protected OutputStreamCounter os;
-
-/** Is the writer open for writing? */
- protected boolean open = false;
-
-/** Do we have to pause all writing actions? */
- // ssteward: changed from "pause" to "m_pause" to
- // remove gcj complaints over ambiguity with pause()
- protected boolean m_pause = false;
-
-/** Closes the stream on document close */
- protected boolean closeStream = true;
-
- // constructor
-
- protected DocWriter() {
- }
-
-/**
- * Constructs a DocWriter
.
- *
- * @param document The Document
that has to be written
- * @param os The OutputStream
the writer has to write to.
- */
-
- protected DocWriter(Document document, OutputStream os) {
- this.document = document;
- this.os = new OutputStreamCounter(new BufferedOutputStream(os));
- }
-
- // implementation of the DocListener methods
-
-/**
- * Signals that an Element
was added to the Document
.
- *
- * This method should be overriden in the specific DocWriter classes
- * derived from this abstract class.
- *
- * @param element A high level object to add
- * @return false
- * @throws DocumentException when a document isn't open yet, or has been closed
- */
-
- public boolean add(Element element) throws DocumentException {
- return false;
- }
-
-/**
- * Signals that the Document
was opened.
- */
-
- public void open() {
- open = true;
- }
-
-/**
- * Sets the pagesize.
- *
- * @param pageSize the new pagesize
- * @return a boolean
- */
-
- public boolean setPageSize(Rectangle pageSize) {
- this.pageSize = pageSize;
- return true;
- }
-
-/**
- * Sets the Watermark
.
- *
- * This method should be overriden in the specific DocWriter classes
- * derived from this abstract class if they actually support the use of
- * a Watermark
.
- *
- * @param watermark A watermark object
- * @return false
(because watermarks aren't supported by default).
- */
-/* ssteward: dropped in 1.44
- public boolean add(Watermark watermark) {
- return false;
- }
-*/
-/**
- * Removes the Watermark
(if there is one).
- */
-/* ssteward: dropped in 1.44
- public void removeWatermark() {
- }
-*/
-/**
- * Sets the margins.
- *
- * This does nothing. Has to be overridden if needed.
- *
- * @param marginLeft the margin on the left
- * @param marginRight the margin on the right
- * @param marginTop the margin on the top
- * @param marginBottom the margin on the bottom
- * @return false
- */
-
- public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom) {
- return false;
- }
-
-/**
- * Signals that an new page has to be started.
- *
- * This does nothing. Has to be overridden if needed.
- *
- * @return true
if the page was added, false
if not.
- * @throws DocumentException when a document isn't open yet, or has been closed
- */
-
- public boolean newPage() throws DocumentException {
- if (!open) {
- return false;
- }
- return true;
- }
-
-/**
- * Changes the header of this document.
- *
- * This method should be overriden in the specific DocWriter classes
- * derived from this abstract class if they actually support the use of
- * headers.
- *
- * @param header the new header
- */
-/* ssteward: dropped in 1.44
- public void setHeader(HeaderFooter header) {
- }
-*/
-
-/**
- * Resets the header of this document.
- *
- * This method should be overriden in the specific DocWriter classes
- * derived from this abstract class if they actually support the use of
- * headers.
- */
-
- public void resetHeader() {
- }
-
-/**
- * Changes the footer of this document.
- *
- * This method should be overriden in the specific DocWriter classes
- * derived from this abstract class if they actually support the use of
- * footers.
- *
- * @param footer the new footer
- */
-/* ssteward: dropped in 1.44
- public void setFooter(HeaderFooter footer) {
- }
-*/
-
-/**
- * Resets the footer of this document.
- *
- * This method should be overriden in the specific DocWriter classes
- * derived from this abstract class if they actually support the use of
- * footers.
- */
-
- public void resetFooter() {
- }
-
-/**
- * Sets the page number to 0.
- *
- * This method should be overriden in the specific DocWriter classes
- * derived from this abstract class if they actually support the use of
- * pagenumbers.
- */
-
- public void resetPageCount() {
- }
-
-/**
- * Sets the page number.
- *
- * This method should be overriden in the specific DocWriter classes
- * derived from this abstract class if they actually support the use of
- * pagenumbers.
- *
- * @param pageN the new page number
- */
-
- public void setPageCount(int pageN) {
- }
-
-/**
- * Signals that the Document
was closed and that no other
- * Elements
will be added.
- */
-
- public void close() {
- open = false;
- try {
- os.flush();
- if (closeStream)
- os.close();
- }
- catch(IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- }
-
- // methods
-
-/** Converts a String
into a Byte
array
- * according to the ISO-8859-1 codepage.
- * @param text the text to be converted
- * @return the conversion result
- */
-
- public static final byte[] getISOBytes(String text)
- {
- if (text == null)
- return null;
- int len = text.length();
- byte b[] = new byte[len];
- for (int k = 0; k < len; ++k)
- b[k] = (byte)text.charAt(k);
- return b;
- }
-
-/**
- * Let the writer know that all writing has to be paused.
- */
-
- public void pause() {
- // ssteward
- m_pause = true;
- }
-
-/**
- * Let the writer know that writing may be resumed.
- */
-
- public void resume() {
- // ssteward
- m_pause = false;
- }
-
-/**
- * Flushes the BufferedOutputStream
.
- */
-
- public void flush() {
- try {
- os.flush();
- }
- catch(IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- }
-
-/**
- * Writes a String
to the OutputStream
.
- *
- * @param string the String
to write
- * @throws IOException
- */
-
- protected void write(String string) throws IOException {
- os.write(getISOBytes(string));
- }
-
-/**
- * Writes a number of tabs.
- *
- * @param indent the number of tabs to add
- * @throws IOException
- */
-
- protected void addTabs(int indent) throws IOException {
- os.write(NEWLINE);
- for (int i = 0; i < indent; i++) {
- os.write(TAB);
- }
- }
-
-/**
- * Writes a key-value pair to the outputstream.
- *
- * @param key the name of an attribute
- * @param value the value of an attribute
- * @throws IOException
- */
-
- protected void write(String key, String value)
- throws IOException {
- os.write(SPACE);
- write(key);
- os.write(EQUALS);
- os.write(QUOTE);
- write(value);
- os.write(QUOTE);
- }
-
-/**
- * Writes a starttag to the outputstream.
- *
- * @param tag the name of the tag
- * @throws IOException
- */
-
- protected void writeStart(String tag)
- throws IOException {
- os.write(LT);
- write(tag);
- }
-
-/**
- * Writes an endtag to the outputstream.
- *
- * @param tag the name of the tag
- * @throws IOException
- */
-
- protected void writeEnd(String tag)
- throws IOException {
- os.write(LT);
- os.write(FORWARD);
- write(tag);
- os.write(GT);
- }
-
-/**
- * Writes an endtag to the outputstream.
- * @throws IOException
- */
-
- protected void writeEnd()
- throws IOException {
- os.write(SPACE);
- os.write(FORWARD);
- os.write(GT);
- }
-
-/**
- * Writes the markup attributes of the specified MarkupAttributes
- * object to the OutputStream
.
- * @param mAtt the MarkupAttributes
to write.
- * @return true, if writing the markup attributes succeeded
- * @throws IOException
- */
- protected boolean writeMarkupAttributes(MarkupAttributes mAtt)
- throws IOException
- {
- Iterator attributeIterator = mAtt.getMarkupAttributeNames().iterator();
- boolean result = attributeIterator.hasNext();
- while (attributeIterator.hasNext()) {
- String name = String.valueOf(attributeIterator.next());
- write(name, mAtt.getMarkupAttribute(name));
- }
- return result;
- }
-
-/**
- * Returns true
if the specified Element
implements
- * MarkupAttributes
and has one or more attributes to write.
- * @param element the Element
to check.
- * @return boolean
.
- */
- protected static boolean hasMarkupAttributes(Element element) {
- return (element instanceof MarkupAttributes &&
- !(((MarkupAttributes)element).getMarkupAttributeNames().isEmpty()));
- }
-
- /** Checks if the stream is to be closed on document close
- * @return true if the stream is closed on documnt close
- *
- */
- public boolean isCloseStream() {
- return closeStream;
- }
-
- /** Sets the close state of the stream after document close
- * @param closeStream true if the stream is closed on document close
- *
- */
- public void setCloseStream(boolean closeStream) {
- this.closeStream = closeStream;
- }
-
-
- /**
- * @see com.lowagie.text.DocListener#clearTextWrap()
- */
- public void clearTextWrap() throws DocumentException {
- // do nothing
- }
- /**
- * @see com.lowagie.text.DocListener#setMarginMirroring(boolean)
- */
- public boolean setMarginMirroring(boolean MarginMirroring) {
- return false;
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/Document.java pdftk-2.01/java/com/lowagie/text/Document.java
--- pdftk-1.45/java/com/lowagie/text/Document.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Document.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,928 +0,0 @@
-/*
- * $Id: Document.java,v 1.100 2005/07/17 14:45:30 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-import java.util.Date;
-
-/**
- * A generic Document class.
- *
- * All kinds of Text-elements can be added to a HTMLDocument
.
- * The Document
signals all the listeners when an element has
- * been added.
- *
- * Remark:
- *
- * Once a document is created you can add some meta information.
- * You can also set the headers/footers.
- * You have to open the document before you can write content.
- * You can only write content (no more meta-formation!) once a document is
- * opened.
- * When you change the header/footer on a certain page, this will be
- * effective starting on the next page.
- * Ater closing the document, every listener (as well as its
- * OutputStream
) is closed too.
- *
- * Example:
- *
- * // creation of the document with a certain size and certain margins
- * Document document = new Document(PageSize.A4, 50, 50, 50, 50);
- * try { // creation of the different writers HtmlWriter.getInstance(
- * document , System.out); PdfWriter.getInstance(
- * document , new FileOutputStream("text.pdf"));
- * // we add some meta information to the document
- * document.addAuthor("Bruno Lowagie");
- * document.addSubject("This is the result of a Test.");
- * // we define a header and a footer HeaderFooter header = new
- * HeaderFooter(new Phrase("This is a header."), false); HeaderFooter footer =
- * new HeaderFooter(new Phrase("This is page "), new Phrase("."));
- * footer.setAlignment(Element.ALIGN_CENTER);
- * document.setHeader(header);
- * document.setFooter(footer); // we open the document for
- * writing document.open(); document.add(new
- * Paragraph("Hello world")); } catch(DocumentException de) {
- * System.err.println(de.getMessage()); } document.close();
- *
- *
- *
- *
- */
-
-public class Document implements DocListener {
-
- // membervariables
-
- /** This constant may only be changed by Paulo Soares and/or Bruno Lowagie. */
- private static final String ITEXT_VERSION = "itext-paulo-155 (itextpdf.sf.net-lowagie.com)";
-
- /**
- * Allows the pdf documents to be produced without compression for debugging
- * purposes.
- */
- public static boolean compress = true;
-
- /** The DocListener. */
- private ArrayList listeners = new ArrayList();
-
- /** Is the document open or not? */
- protected boolean open;
-
- /** Has the document already been closed? */
- protected boolean close;
-
- // membervariables concerning the layout
-
- /** The size of the page. */
- protected Rectangle pageSize;
-
- /** The watermark on the pages. */
- // protected Watermark watermark = null; ssteward: dropped in 1.44
-
- /** margin in x direction starting from the left */
- protected float marginLeft = 0;
-
- /** margin in x direction starting from the right */
- protected float marginRight = 0;
-
- /** margin in y direction starting from the top */
- protected float marginTop = 0;
-
- /** margin in y direction starting from the bottom */
- protected float marginBottom = 0;
-
- protected boolean marginMirroring = false;
-
- /** Content of JavaScript onLoad function */
- protected String javaScript_onLoad = null;
-
- /** Content of JavaScript onUnLoad function */
- protected String javaScript_onUnLoad = null;
-
- /** Style class in HTML body tag */
- protected String htmlStyleClass = null;
-
- // headers, footers
-
- /** Current pagenumber */
- protected int pageN = 0;
-
- /** This is the textual part of a Page; it can contain a header */
- // protected HeaderFooter header = null; ssteward: dropped in 1.44
-
- /** This is the textual part of the footer */
- // protected HeaderFooter footer = null; ssteward: dropped in 1.44
-
- // constructor
-
- /**
- * Constructs a new Document
-object.
- */
-
- public Document() {
- this(PageSize.A4);
- }
-
- /**
- * Constructs a new Document
-object.
- *
- * @param pageSize
- * the pageSize
- */
-
- public Document(Rectangle pageSize) {
- this(pageSize, 36, 36, 36, 36);
- }
-
- /**
- * Constructs a new Document
-object.
- *
- * @param pageSize
- * the pageSize
- * @param marginLeft
- * the margin on the left
- * @param marginRight
- * the margin on the right
- * @param marginTop
- * the margin on the top
- * @param marginBottom
- * the margin on the bottom
- */
-
- public Document(Rectangle pageSize, float marginLeft, float marginRight,
- float marginTop, float marginBottom) {
- this.pageSize = pageSize;
- this.marginLeft = marginLeft;
- this.marginRight = marginRight;
- this.marginTop = marginTop;
- this.marginBottom = marginBottom;
- }
-
- // listener methods
-
- /**
- * Adds a DocListener
to the Document
.
- *
- * @param listener
- * the new DocListener.
- */
-
- public void addDocListener(DocListener listener) {
- listeners.add(listener);
- }
-
- /**
- * Removes a DocListener
from the Document
.
- *
- * @param listener
- * the DocListener that has to be removed.
- */
-
- public void removeDocListener(DocListener listener) {
- listeners.remove(listener);
- }
-
- // methods implementing the DocListener interface
-
- /**
- * Adds an Element
to the Document
.
- *
- * @param element
- * the Element
to add
- * @return true
if the element was added, false
- *
if not
- * @throws DocumentException
- * when a document isn't open yet, or has been closed
- */
-
- public boolean add(Element element) throws DocumentException {
- if (close) {
- throw new DocumentException(
- "The document has been closed. You can't add any Elements.");
- }
- int type = element.type();
- if (open) {
- if (!(type == Element.CHUNK || type == Element.PHRASE
- || type == Element.PARAGRAPH || type == Element.TABLE
- || type == Element.PTABLE
- || type == Element.MULTI_COLUMN_TEXT
- || type == Element.ANCHOR || type == Element.ANNOTATION
- || type == Element.CHAPTER || type == Element.SECTION
- || type == Element.LIST || type == Element.LISTITEM
- || type == Element.RECTANGLE || type == Element.JPEG
- || type == Element.IMGRAW || type == Element.IMGTEMPLATE || type == Element.GRAPHIC)) {
- throw new DocumentException(
- "The document is open; you can only add Elements with content.");
- }
- } else {
- if (!(type == Element.HEADER || type == Element.TITLE
- || type == Element.SUBJECT || type == Element.KEYWORDS
- || type == Element.AUTHOR || type == Element.PRODUCER
- || type == Element.CREATOR || type == Element.CREATIONDATE)) {
- throw new DocumentException(
- "The document is not open yet; you can only add Meta information.");
- }
- }
- boolean success = false;
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- success |= listener.add(element);
- }
- return success;
- }
-
- /**
- * Opens the document.
- *
- * Once the document is opened, you can't write any Header- or
- * Meta-information anymore. You have to open the document before you can
- * begin to add content to the body of the document.
- */
-
- public void open() {
- if (!close) {
- open = true;
- }
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.setPageSize(pageSize);
- listener.setMargins(marginLeft, marginRight, marginTop,
- marginBottom);
- listener.open();
- }
- }
-
- /**
- * Sets the pagesize.
- *
- * @param pageSize
- * the new pagesize
- * @return a boolean
- */
-
- public boolean setPageSize(Rectangle pageSize) {
- this.pageSize = pageSize;
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.setPageSize(pageSize);
- }
- return true;
- }
-
- /**
- * Sets the Watermark
.
- *
- * @param watermark
- * the watermark to add
- * @return true
if the element was added, false
- *
if not.
- */
- /* ssteward: dropped in 1.44
- public boolean add(Watermark watermark) {
- this.watermark = watermark;
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.add(watermark);
- }
- return true;
- }
- */
-
- /**
- * Removes the Watermark
.
- */
- /* ssteward: dropped in 1.44
- public void removeWatermark() {
- this.watermark = null;
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.removeWatermark();
- }
- }
- */
-
- /**
- * Sets the margins.
- *
- * @param marginLeft
- * the margin on the left
- * @param marginRight
- * the margin on the right
- * @param marginTop
- * the margin on the top
- * @param marginBottom
- * the margin on the bottom
- * @return a boolean
- */
-
- public boolean setMargins(float marginLeft, float marginRight,
- float marginTop, float marginBottom) {
- this.marginLeft = marginLeft;
- this.marginRight = marginRight;
- this.marginTop = marginTop;
- this.marginBottom = marginBottom;
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.setMargins(marginLeft, marginRight, marginTop,
- marginBottom);
- }
- return true;
- }
-
- /**
- * Signals that an new page has to be started.
- *
- * @return true
if the page was added, false
- * if not.
- * @throws DocumentException
- * when a document isn't open yet, or has been closed
- */
-
- public boolean newPage() throws DocumentException {
- if (!open || close) {
- return false;
- }
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.newPage();
- }
- return true;
- }
-
- /**
- * Changes the header of this document.
- *
- * @param header
- * the new header
- */
- /* ssteward: dropped in 1.44
- public void setHeader(HeaderFooter header) {
- this.header = header;
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.setHeader(header);
- }
- }
- */
-
- /**
- * Resets the header of this document.
- */
- /* ssteward: dropped in 1.44
- public void resetHeader() {
- this.header = null;
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.resetHeader();
- }
- }
- */
-
- /**
- * Changes the footer of this document.
- *
- * @param footer
- * the new footer
- */
- /* ssteward: dropped in 1.44
- public void setFooter(HeaderFooter footer) {
- this.footer = footer;
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.setFooter(footer);
- }
- }
- */
-
- /**
- * Resets the footer of this document.
- */
- /* ssteward: dropped in 1.44
- public void resetFooter() {
- this.footer = null;
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.resetFooter();
- }
- }
- */
-
- /**
- * Sets the page number to 0.
- */
-
- public void resetPageCount() {
- pageN = 0;
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.resetPageCount();
- }
- }
-
- /**
- * Sets the page number.
- *
- * @param pageN
- * the new page number
- */
-
- public void setPageCount(int pageN) {
- this.pageN = pageN;
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.setPageCount(pageN);
- }
- }
-
- /**
- * Returns the current page number.
- *
- * @return the current page number
- */
-
- public int getPageNumber() {
- return this.pageN;
- }
-
- /**
- * Closes the document.
- *
- * Once all the content has been written in the body, you have to close the
- * body. After that nothing can be written to the body anymore.
- */
-
- public void close() {
- if (!close) {
- open = false;
- close = true;
- }
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.close();
- }
- }
-
- // methods concerning the header or some meta information
-
- /**
- * Adds a user defined header to the document.
- *
- * @param name
- * the name of the header
- * @param content
- * the content of the header
- * @return true
if successful, false
otherwise
- */
-
- public boolean addHeader(String name, String content) {
- try {
- return add(new Header(name, content));
- } catch (DocumentException de) {
- throw new ExceptionConverter(de);
- }
- }
-
- /**
- * Adds the title to a Document.
- *
- * @param title
- * the title
- * @return true
if successful, false
otherwise
- */
-
- public boolean addTitle(String title) {
- try {
- return add(new Meta(Element.TITLE, title));
- } catch (DocumentException de) {
- throw new ExceptionConverter(de);
- }
- }
-
- /**
- * Adds the subject to a Document.
- *
- * @param subject
- * the subject
- * @return true
if successful, false
otherwise
- */
-
- public boolean addSubject(String subject) {
- try {
- return add(new Meta(Element.SUBJECT, subject));
- } catch (DocumentException de) {
- throw new ExceptionConverter(de);
- }
- }
-
- /**
- * Adds the keywords to a Document.
- *
- * @param keywords
- * adds the keywords to the document
- * @return true
if successful, false
otherwise
- */
-
- public boolean addKeywords(String keywords) {
- try {
- return add(new Meta(Element.KEYWORDS, keywords));
- } catch (DocumentException de) {
- throw new ExceptionConverter(de);
- }
- }
-
- /**
- * Adds the author to a Document.
- *
- * @param author
- * the name of the author
- * @return true
if successful, false
otherwise
- */
-
- public boolean addAuthor(String author) {
- try {
- return add(new Meta(Element.AUTHOR, author));
- } catch (DocumentException de) {
- throw new ExceptionConverter(de);
- }
- }
-
- /**
- * Adds the creator to a Document.
- *
- * @param creator
- * the name of the creator
- * @return true
if successful, false
otherwise
- */
-
- public boolean addCreator(String creator) {
- try {
- return add(new Meta(Element.CREATOR, creator));
- } catch (DocumentException de) {
- throw new ExceptionConverter(de);
- }
- }
-
- /**
- * Adds the producer to a Document.
- *
- * @return true
if successful, false
otherwise
- */
-
- public boolean addProducer() {
- try {
- return add(new Meta(Element.PRODUCER, "iText by lowagie.com"));
- } catch (DocumentException de) {
- throw new ExceptionConverter(de);
- }
- }
-
- /**
- * Adds the current date and time to a Document.
- *
- * @return true
if successful, false
otherwise
- */
-
- public boolean addCreationDate() {
- try {
- /* bugfix by 'taqua' (Thomas) */
- final SimpleDateFormat sdf = new SimpleDateFormat(
- "EEE MMM dd HH:mm:ss zzz yyyy");
- return add(new Meta(Element.CREATIONDATE, sdf.format(new Date())));
- } catch (DocumentException de) {
- throw new ExceptionConverter(de);
- }
- }
-
- // methods to get the layout of the document.
-
- /**
- * Returns the left margin.
- *
- * @return the left margin
- */
-
- public float leftMargin() {
- return marginLeft;
- }
-
- /**
- * Return the right margin.
- *
- * @return the right margin
- */
-
- public float rightMargin() {
- return marginRight;
- }
-
- /**
- * Returns the top margin.
- *
- * @return the top margin
- */
-
- public float topMargin() {
- return marginTop;
- }
-
- /**
- * Returns the bottom margin.
- *
- * @return the bottom margin
- */
-
- public float bottomMargin() {
- return marginBottom;
- }
-
- /**
- * Returns the lower left x-coordinate.
- *
- * @return the lower left x-coordinate
- */
-
- public float left() {
- return pageSize.left(marginLeft);
- }
-
- /**
- * Returns the upper right x-coordinate.
- *
- * @return the upper right x-coordinate
- */
-
- public float right() {
- return pageSize.right(marginRight);
- }
-
- /**
- * Returns the upper right y-coordinate.
- *
- * @return the upper right y-coordinate
- */
-
- public float top() {
- return pageSize.top(marginTop);
- }
-
- /**
- * Returns the lower left y-coordinate.
- *
- * @return the lower left y-coordinate
- */
-
- public float bottom() {
- return pageSize.bottom(marginBottom);
- }
-
- /**
- * Returns the lower left x-coordinate considering a given margin.
- *
- * @param margin
- * a margin
- * @return the lower left x-coordinate
- */
-
- public float left(float margin) {
- return pageSize.left(marginLeft + margin);
- }
-
- /**
- * Returns the upper right x-coordinate, considering a given margin.
- *
- * @param margin
- * a margin
- * @return the upper right x-coordinate
- */
-
- public float right(float margin) {
- return pageSize.right(marginRight + margin);
- }
-
- /**
- * Returns the upper right y-coordinate, considering a given margin.
- *
- * @param margin
- * a margin
- * @return the upper right y-coordinate
- */
-
- public float top(float margin) {
- return pageSize.top(marginTop + margin);
- }
-
- /**
- * Returns the lower left y-coordinate, considering a given margin.
- *
- * @param margin
- * a margin
- * @return the lower left y-coordinate
- */
-
- public float bottom(float margin) {
- return pageSize.bottom(marginBottom + margin);
- }
-
- /**
- * Gets the pagesize.
- *
- * @return the page size
- */
-
- public Rectangle getPageSize() {
- return this.pageSize;
- }
-
- /**
- * Checks if the document is open.
- *
- * @return true
if the document is open
- */
- public boolean isOpen() {
- return open;
- }
-
- /**
- * Gets the iText version.
- * This method may only be changed by Paulo Soares and/or Bruno Lowagie.
- * @return iText version
- */
- public static final String getVersion() {
- return ITEXT_VERSION;
- }
-
- /**
- * Adds a JavaScript onLoad function to the HTML body tag
- *
- * @param code
- * the JavaScript code to be executed on load of the HTML page
- */
-
- public void setJavaScript_onLoad(String code) {
- this.javaScript_onLoad = code;
- }
-
- /**
- * Gets the JavaScript onLoad command.
- *
- * @return the JavaScript onLoad command
- */
-
- public String getJavaScript_onLoad() {
- return this.javaScript_onLoad;
- }
-
- /**
- * Adds a JavaScript onUnLoad function to the HTML body tag
- *
- * @param code
- * the JavaScript code to be executed on unload of the HTML page
- */
-
- public void setJavaScript_onUnLoad(String code) {
- this.javaScript_onUnLoad = code;
- }
-
- /**
- * Gets the JavaScript onUnLoad command.
- *
- * @return the JavaScript onUnLoad command
- */
-
- public String getJavaScript_onUnLoad() {
- return this.javaScript_onUnLoad;
- }
-
- /**
- * Adds a style class to the HTML body tag
- *
- * @param htmlStyleClass
- * the style class for the HTML body tag
- */
-
- public void setHtmlStyleClass(String htmlStyleClass) {
- this.htmlStyleClass = htmlStyleClass;
- }
-
- /**
- * Gets the style class of the HTML body tag
- *
- * @return the style class of the HTML body tag
- */
-
- public String getHtmlStyleClass() {
- return this.htmlStyleClass;
- }
-
- /**
- * @see com.lowagie.text.DocListener#clearTextWrap()
- */
- public void clearTextWrap() throws DocumentException {
- if (open && !close) {
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.clearTextWrap();
- }
- }
- }
-
- /**
- * Set the margin mirroring. It will mirror margins for odd/even pages.
- *
- * Note: it will not work with {@link Table}.
- *
- * @param marginMirroring
- * true
to mirror the margins
- * @return always true
- */
- public boolean setMarginMirroring(boolean marginMirroring) {
- this.marginMirroring = marginMirroring;
- DocListener listener;
- for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
- listener = (DocListener) iterator.next();
- listener.setMarginMirroring(marginMirroring);
- }
- return true;
- }
-
- /**
- * Gets the margin mirroring flag.
- *
- * @return the margin mirroring flag
- */
- public boolean isMarginMirroring() {
- return marginMirroring;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/DocumentException.java pdftk-2.01/java/com/lowagie/text/DocumentException.java
--- pdftk-1.45/java/com/lowagie/text/DocumentException.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/DocumentException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,192 +0,0 @@
-/*
- * $Id: DocumentException.java,v 1.50 2004/12/14 11:52:46 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- *
- */
-
-package com.lowagie.text;
-
-/**
- * Signals that an error has occurred in a Document
.
- *
- * @see BadElementException
- * @see Document
- * @see DocWriter
- * @see DocListener
- */
-
-public class DocumentException extends Exception {
- private Exception ex;
-
- /**
- * Creates a Document exception.
- * @param ex an exception that has to be turned into a DocumentException
- */
- public DocumentException(Exception ex) {
- this.ex = ex;
- }
-
- // constructors
-
-/**
- * Constructs a DocumentException
whithout a message.
- */
-
- public DocumentException() {
- super();
- }
-
-/**
- * Constructs a DocumentException
with a message.
- *
- * @param message a message describing the exception
- */
-
- public DocumentException(String message) {
- super(message);
- }
-
- /**
- * We print the message of the checked exception
- * @return the error message
- */
- public String getMessage() {
- if (ex == null)
- return super.getMessage();
- else
- return ex.getMessage();
- }
-
- /**
- * and make sure we also produce a localized version
- * @return a localized message
- */
- public String getLocalizedMessage() {
- if (ex == null)
- return super.getLocalizedMessage();
- else
- return ex.getLocalizedMessage();
- }
-
- /**
- * The toString() is changed to be prefixed with ExceptionConverter
- * @return the String version of the exception
- */
- public String toString() {
- if (ex == null)
- return super.toString();
- else
- return split(getClass().getName()) + ": " + ex;
- }
-
- /** we have to override this as well */
- public void printStackTrace() {
- printStackTrace(System.err);
- }
-
- /**
- * here we prefix, with s.print(), not s.println(), the stack
- * trace with "ExceptionConverter:"
- * @param s a printstream object
- */
- public void printStackTrace(java.io.PrintStream s) {
- if (ex == null)
- super.printStackTrace(s);
- else {
- synchronized (s) {
- s.print(split(getClass().getName()) + ": ");
- ex.printStackTrace(s);
- }
- }
- }
-
- /**
- * Again, we prefix the stack trace with "ExceptionConverter:"
- * @param s A PrintWriter object
- */
- public void printStackTrace(java.io.PrintWriter s) {
- if (ex == null)
- super.printStackTrace(s);
- else {
- synchronized (s) {
- s.print(split(getClass().getName()) + ": ");
- ex.printStackTrace(s);
- }
- }
- }
-
- /**
- * Removes everything in a String that comes before a '.'
- * @param s the original string
- * @return the part that comes after the dot
- */
- private static String split(String s) {
- int i = s.lastIndexOf('.');
- if (i < 0)
- return s;
- else
- return s.substring(i + 1);
- }
-
- /** requests to fill in the stack trace we will have to ignore.
- * We can't throw an exception here, because this method
- * is called by the constructor of Throwable */
-// public Throwable fillInStackTrace() {
-// if (ex == null)
-// return super.fillInStackTrace();
-// else
-// return this;
-// }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/Element.java pdftk-2.01/java/com/lowagie/text/Element.java
--- pdftk-1.45/java/com/lowagie/text/Element.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Element.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,331 +0,0 @@
-/*
- * $Id: Element.java,v 1.66 2005/05/04 14:41:15 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.util.ArrayList;
-
-/**
- * Interface for a text element.
- *
- * Remark: I looked at the interface javax.swing.text.Element, but I decided to
- * write my own text-classes for two reasons:
- *
- * The javax.swing.text-classes may be very generic, I think they are
- * overkill: they are to heavy for what they have to do.
- * A lot of people using iText (formerly known as rugPdf), still use
- * JDK1.1.x. I try to keep the Java2 requirements limited to the Collection
- * classes (I think they're really great). However, if I use the
- * javax.swing.text classes, it will become very difficult to downgrade rugPdf.
- *
- *
- * @see Anchor
- * @see Cell
- * @see Chapter
- * @see Chunk
- * @see Graphic
- * @see Header
- * @see Image
- * @see Jpeg
- * @see List
- * @see ListItem
- * @see Meta
- * @see Paragraph
- * @see Phrase
- * @see Rectangle
- * @see Row
- * @see Section
- * @see Table
- */
-
-public interface Element {
-
- // static membervariables (meta information)
-
- /** This is a possible type of Element
. */
- public static final int HEADER = 0;
-
- /** This is a possible type of Element
. */
- public static final int TITLE = 1;
-
- /** This is a possible type of Element
. */
- public static final int SUBJECT = 2;
-
- /** This is a possible type of Element
. */
- public static final int KEYWORDS = 3;
-
- /** This is a possible type of Element . */
- public static final int AUTHOR = 4;
-
- /** This is a possible type of Element . */
- public static final int PRODUCER = 5;
-
- /** This is a possible type of Element . */
- public static final int CREATIONDATE = 6;
-
- /** This is a possible type of Element . */
- public static final int CREATOR = 7;
-
- // static membervariables (content)
-
- /** This is a possible type of Element
. */
- public static final int CHUNK = 10;
-
- /** This is a possible type of Element
. */
- public static final int PHRASE = 11;
-
- /** This is a possible type of Element
. */
- public static final int PARAGRAPH = 12;
-
- /** This is a possible type of Element
*/
- public static final int SECTION = 13;
-
- /** This is a possible type of Element
*/
- public static final int LIST = 14;
-
- /** This is a possible type of Element
*/
- public static final int LISTITEM = 15;
-
- /** This is a possible type of Element
*/
- public static final int CHAPTER = 16;
-
- /** This is a possible type of Element
*/
- public static final int ANCHOR = 17;
-
- // static membervariables (tables)
-
- /** This is a possible type of Element
. */
- public static final int CELL = 20;
-
- /** This is a possible type of Element
. */
- public static final int ROW = 21;
-
- /** This is a possible type of Element
. */
- public static final int TABLE = 22;
-
- /** This is a possible type of Element
. */
- public static final int PTABLE = 23;
-
- // static membervariables (annotations)
-
- /** This is a possible type of Element
. */
- public static final int ANNOTATION = 29;
-
- // static membervariables (geometric figures)
-
- /** This is a possible type of Element
. */
- public static final int RECTANGLE = 30;
-
- /** This is a possible type of Element
. */
- public static final int JPEG = 32;
-
- /** This is a possible type of Element
. */
- public static final int IMGRAW = 34;
-
- /** This is a possible type of Element
. */
- public static final int IMGTEMPLATE = 35;
-
- /** This is a possible type of Element
. */
- public static final int GRAPHIC = 39;
-
- /** This is a possible type of Element
. */
- public static final int MULTI_COLUMN_TEXT = 40;
-
- // static membervariables (alignment)
-
- /**
- * A possible value for paragraph alignment. This specifies that the text is
- * aligned to the left indent and extra whitespace should be placed on the
- * right.
- */
- public static final int ALIGN_UNDEFINED = -1;
-
- /**
- * A possible value for paragraph alignment. This specifies that the text is
- * aligned to the left indent and extra whitespace should be placed on the
- * right.
- */
- public static final int ALIGN_LEFT = 0;
-
- /**
- * A possible value for paragraph alignment. This specifies that the text is
- * aligned to the center and extra whitespace should be placed equally on
- * the left and right.
- */
- public static final int ALIGN_CENTER = 1;
-
- /**
- * A possible value for paragraph alignment. This specifies that the text is
- * aligned to the right indent and extra whitespace should be placed on the
- * left.
- */
- public static final int ALIGN_RIGHT = 2;
-
- /**
- * A possible value for paragraph alignment. This specifies that extra
- * whitespace should be spread out through the rows of the paragraph with
- * the text lined up with the left and right indent except on the last line
- * which should be aligned to the left.
- */
- public static final int ALIGN_JUSTIFIED = 3;
-
- /**
- * A possible value for vertical alignment.
- */
-
- public static final int ALIGN_TOP = 4;
-
- /**
- * A possible value for vertical alignment.
- */
-
- public static final int ALIGN_MIDDLE = 5;
-
- /**
- * A possible value for vertical alignment.
- */
-
- public static final int ALIGN_BOTTOM = 6;
-
- /**
- * A possible value for vertical alignment.
- */
- public static final int ALIGN_BASELINE = 7;
-
- /**
- * Does the same as ALIGN_JUSTIFIED but the last line is also spread out.
- */
- public static final int ALIGN_JUSTIFIED_ALL = 8;
-
- // static member variables for CCITT compression
-
- /**
- * Pure two-dimensional encoding (Group 4)
- */
- public static final int CCITTG4 = 0x100;
-
- /**
- * Pure one-dimensional encoding (Group 3, 1-D)
- */
- public static final int CCITTG3_1D = 0x101;
-
- /**
- * Mixed one- and two-dimensional encoding (Group 3, 2-D)
- */
- public static final int CCITTG3_2D = 0x102;
-
- /**
- * A flag indicating whether 1-bits are to be interpreted as black pixels
- * and 0-bits as white pixels,
- */
- public static final int CCITT_BLACKIS1 = 1;
-
- /**
- * A flag indicating whether the filter expects extra 0-bits before each
- * encoded line so that the line begins on a byte boundary.
- */
- public static final int CCITT_ENCODEDBYTEALIGN = 2;
-
- /**
- * A flag indicating whether end-of-line bit patterns are required to be
- * present in the encoding.
- */
- public static final int CCITT_ENDOFLINE = 4;
-
- /**
- * A flag indicating whether the filter expects the encoded data to be
- * terminated by an end-of-block pattern, overriding the Rows parameter. The
- * use of this flag will set the key /EndOfBlock to false.
- */
- public static final int CCITT_ENDOFBLOCK = 8;
-
- // methods
-
- /**
- * Processes the element by adding it (or the different parts) to an
- * ElementListener
.
- *
- * @param listener
- * an ElementListener
- * @return true
if the element was processed successfully
- */
-
- public boolean process(ElementListener listener);
-
- /**
- * Gets the type of the text element.
- *
- * @return a type
- */
-
- public int type();
-
- /**
- * Gets all the chunks in this element.
- *
- * @return an ArrayList
- */
-
- public ArrayList getChunks();
-
- /**
- * Gets the content of the text element.
- *
- * @return a type
- */
-
- public String toString();
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/ElementListener.java pdftk-2.01/java/com/lowagie/text/ElementListener.java
--- pdftk-1.45/java/com/lowagie/text/ElementListener.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/ElementListener.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,81 +0,0 @@
-/*
- * $Id: ElementListener.java,v 1.48 2004/12/14 11:52:46 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.util.EventListener;
-
-/**
- * A class that implements ElementListener
will perform some
- * actions when an Element
is added.
- *
- * @see DocListener
- */
-
-public interface ElementListener extends EventListener {
-
- // methods
-
-/**
- * Signals that an Element
was added to the Document
.
- *
- * @param element a high level object
- * @return true
if the element was added, false
if not.
- * @throws DocumentException when a document isn't open yet, or has been closed
- */
-
- public boolean add(Element element) throws DocumentException;
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/ElementTags.java pdftk-2.01/java/com/lowagie/text/ElementTags.java
--- pdftk-1.45/java/com/lowagie/text/ElementTags.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/ElementTags.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,467 +0,0 @@
-/*
- * $Id: ElementTags.java,v 1.84 2005/04/06 07:01:18 blowagie Exp $
- * $Name: $
- *
- * Copyright (c) 2001, 2002 Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-/**
- * A class that contains all the possible tagnames and their attributes.
- */
-
-public class ElementTags {
-
-/** the root tag. */
- public static final String ITEXT = "itext";
-
-/** attribute of the root and annotation tag (also a special tag within a chapter or section) */
- public static final String TITLE = "title";
-
-/** attribute of the root tag */
- public static final String SUBJECT = "subject";
-
-/** attribute of the root tag */
- public static final String KEYWORDS = "keywords";
-
-/** attribute of the root tag */
- public static final String AUTHOR = "author";
-
-/** attribute of the root tag */
- public static final String CREATIONDATE = "creationdate";
-
-/** attribute of the root tag */
- public static final String PRODUCER = "producer";
-
- // Chapters and Sections
-
-/** the chapter tag */
- public static final String CHAPTER = "chapter";
-
-/** the section tag */
- public static final String SECTION = "section";
-
-/** attribute of section/chapter tag */
- public static final String NUMBERDEPTH = "numberdepth";
-
-/** attribute of section/chapter tag */
- public static final String DEPTH = "depth";
-
-/** attribute of section/chapter tag */
- public static final String NUMBER = "number";
-
-/** attribute of section/chapter tag */
- public static final String INDENT = "indent";
-
-/** attribute of chapter/section/paragraph/table/cell tag */
- public static final String LEFT = "left";
-
-/** attribute of chapter/section/paragraph/table/cell tag */
- public static final String RIGHT = "right";
-
- // Phrases, Anchors, Lists and Paragraphs
-
-/** the phrase tag */
- public static final String PHRASE = "phrase";
-
-/** the anchor tag */
- public static final String ANCHOR = "anchor";
-
-/** the list tag */
- public static final String LIST = "list";
-
-/** the listitem tag */
- public static final String LISTITEM = "listitem";
-
-/** the paragraph tag */
- public static final String PARAGRAPH = "paragraph";
-
-/** attribute of phrase/paragraph/cell tag */
- public static final String LEADING = "leading";
-
-/** attribute of paragraph/image/table tag */
- public static final String ALIGN = "align";
-
-/** attribute of paragraph */
- public static final String KEEPTOGETHER = "keeptogether";
-
-/** attribute of anchor tag */
- public static final String NAME = "name";
-
-/** attribute of anchor tag */
- public static final String REFERENCE = "reference";
-
-/** attribute of list tag */
- public static final String LISTSYMBOL = "listsymbol";
-
-/** attribute of list tag */
- public static final String NUMBERED = "numbered";
-
-/** attribute of the list tag */
- public static final String LETTERED = "lettered";
-
-/** attribute of list tag */
- public static final String FIRST = "first";
-
-/** attribute of list tag */
- public static final String SYMBOLINDENT = "symbolindent";
-
-/** attribute of list tag */
- public static final String INDENTATIONLEFT = "indentationleft";
-
-/** attribute of list tag */
- public static final String INDENTATIONRIGHT = "indentationright";
-
- // Chunks
-
-/** the chunk tag */
- public static final String IGNORE = "ignore";
-
-/** the chunk tag */
- public static final String ENTITY = "entity";
-
-/** the chunk tag */
- public static final String ID = "id";
-
-/** the chunk tag */
- public static final String CHUNK = "chunk";
-
-/** attribute of the chunk tag */
- public static final String ENCODING = "encoding";
-
-/** attribute of the chunk tag */
- public static final String EMBEDDED = "embedded";
-
-/** attribute of the chunk/table/cell tag */
- public static final String COLOR = "color";
-
-/** attribute of the chunk/table/cell tag */
- public static final String RED = "red";
-
-/** attribute of the chunk/table/cell tag */
- public static final String GREEN = "green";
-
-/** attribute of the chunk/table/cell tag */
- public static final String BLUE = "blue";
-
-/** attribute of the chunk tag */
- public static final String SUBSUPSCRIPT = Chunk.SUBSUPSCRIPT.toLowerCase();
-
-/** attribute of the chunk tag */
- public static final String LOCALGOTO = Chunk.LOCALGOTO.toLowerCase();
-
-/** attribute of the chunk tag */
- public static final String REMOTEGOTO = Chunk.REMOTEGOTO.toLowerCase();
-
-/** attribute of the chunk tag */
- public static final String LOCALDESTINATION = Chunk.LOCALDESTINATION.toLowerCase();
-
-/** attribute of the chunk tag */
- public static final String GENERICTAG = Chunk.GENERICTAG.toLowerCase();
-
- // tables/cells
-
-/** the table tag */
- public static final String TABLE = "table";
-
-/** the cell tag */
- public static final String ROW = "row";
-
-/** the cell tag */
- public static final String CELL = "cell";
-
-/** attribute of the table tag */
- public static final String COLUMNS = "columns";
-
-/** attribute of the table tag */
- public static final String LASTHEADERROW = "lastHeaderRow";
-
-/** attribute of the table tag */
- public static final String CELLPADDING = "cellpadding";
-
-/** attribute of the table tag */
- public static final String CELLSPACING = "cellspacing";
-
-/** attribute of the table tag */
- public static final String OFFSET = "offset";
-
-/** attribute of the table tag */
- public static final String WIDTHS = "widths";
-
-/** attribute of the table tag */
- public static final String TABLEFITSPAGE = "tablefitspage";
-
-/** attribute of the table tag */
- public static final String CELLSFITPAGE = "cellsfitpage";
-
-/** attribute of the cell tag */
- public static final String HORIZONTALALIGN = "horizontalalign";
-
-/** attribute of the cell tag */
- public static final String VERTICALALIGN = "verticalalign";
-
-/** attribute of the cell tag */
- public static final String COLSPAN = "colspan";
-
-/** attribute of the cell tag */
- public static final String ROWSPAN = "rowspan";
-
-/** attribute of the cell tag */
- public static final String HEADER = "header";
-
-/** attribute of the cell tag */
- public static final String NOWRAP = "nowrap";
-
-/** attribute of the table/cell tag */
- public static final String BORDERWIDTH = "borderwidth";
-
-/** attribute of the table/cell tag */
- public static final String TOP = "top";
-
-/** attribute of the table/cell tag */
- public static final String BOTTOM = "bottom";
-
-/** attribute of the table/cell tag */
- public static final String WIDTH = "width";
-
-/** attribute of the table/cell tag */
- public static final String BORDERCOLOR = "bordercolor";
-
-/** attribute of the table/cell tag */
- public static final String BACKGROUNDCOLOR = "backgroundcolor";
-
-/** attribute of the table/cell tag */
- public static final String BGRED = "bgred";
-
-/** attribute of the table/cell tag */
- public static final String BGGREEN = "bggreen";
-
-/** attribute of the table/cell tag */
- public static final String BGBLUE = "bgblue";
-
-/** attribute of the table/cell tag */
- public static final String GRAYFILL = "grayfill";
-
- // Misc
-
-/** the image tag */
- public static final String IMAGE = "image";
-
-/** attribute of the image and annotation tag */
- public static final String URL = "url";
-
-/** attribute of the image tag */
- public static final String UNDERLYING = "underlying";
-
-/** attribute of the image tag */
- public static final String TEXTWRAP = "textwrap";
-
-/** attribute of the image tag */
- public static final String ALT = "alt";
-
-/** attribute of the image tag */
- public static final String ABSOLUTEX = "absolutex";
-
-/** attribute of the image tag */
- public static final String ABSOLUTEY = "absolutey";
-
-/** attribute of the image tag */
- public static final String PLAINWIDTH = "plainwidth";
-
-/** attribute of the image tag */
- public static final String PLAINHEIGHT = "plainheight";
-
-/** attribute of the image tag */
- public static final String SCALEDWIDTH = "scaledwidth";
-
-/** attribute of the image tag */
- public static final String SCALEDHEIGHT = "scaledheight";
-
-/** attribute of the image tag */
- public static final String ROTATION = "rotation";
-
-/** the newpage tag */
- public static final String NEWPAGE = "newpage";
-
-/** the newpage tag */
- public static final String NEWLINE = "newline";
-
-/** the annotation tag */
- public static final String ANNOTATION = "annotation";
-
-/** attribute of the annotation tag */
- public static String FILE = "file";
-
-/** attribute of the annotation tag */
- public static String DESTINATION = "destination";
-
-/** attribute of the annotation tag */
- public static String PAGE = "page";
-
-/** attribute of the annotation tag */
- public static String NAMED = "named";
-
-/** attribute of the annotation tag */
- public static String APPLICATION = "application";
-
-/** attribute of the annotation tag */
- public static String PARAMETERS = "parameters";
-
-/** attribute of the annotation tag */
- public static String OPERATION = "operation";
-
-/** attribute of the annotation tag */
- public static String DEFAULTDIR = "defaultdir";
-
-/** attribute of the annotation tag */
- public static String LLX = "llx";
-
-/** attribute of the annotation tag */
- public static String LLY = "lly";
-
-/** attribute of the annotation tag */
- public static String URX = "urx";
-
-/** attribute of the annotation tag */
- public static String URY = "ury";
-
-/** attribute of the annotation tag */
- public static final String CONTENT = "content";
-
- // alignment attribute values
-
-/** the possible value of an alignment attribute */
- public static final String ALIGN_LEFT = "Left";
-
-/** the possible value of an alignment attribute */
- public static final String ALIGN_CENTER = "Center";
-
-/** the possible value of an alignment attribute */
- public static final String ALIGN_RIGHT = "Right";
-
-/** the possible value of an alignment attribute */
- public static final String ALIGN_JUSTIFIED = "Justify";
-
-/** the possible value of an alignment attribute */
- public static final String ALIGN_JUSTIFIED_ALL = "JustifyAll";
-
-/** the possible value of an alignment attribute */
- public static final String ALIGN_TOP = "Top";
-
-/** the possible value of an alignment attribute */
- public static final String ALIGN_MIDDLE = "Middle";
-
-/** the possible value of an alignment attribute */
- public static final String ALIGN_BOTTOM = "Bottom";
-
-/** the possible value of an alignment attribute */
- public static final String ALIGN_BASELINE = "Baseline";
-
-/** the possible value of an alignment attribute */
- public static final String DEFAULT = "Default";
-
-/** the possible value of an alignment attribute */
- public static final String UNKNOWN = "unknown";
-
-/** the possible value of an alignment attribute */
- public static final String FONT = "font";
-
-/** the possible value of an alignment attribute */
- public static final String SIZE = "size";
-
-/** the possible value of an alignment attribute */
- public static final String STYLE = "fontstyle";
-
-/** the possible value of a tag */
- public static final String HORIZONTALRULE = "horizontalrule";
-
- /** the possible value of a tag */
- public static final String PAGE_SIZE = "pagesize";
-
- /** the possible value of a tag */
- public static final String ORIENTATION = "orientation";
-
- // methods
-
-/**
- * Translates the alignment value.
- *
- * @param alignment the alignment value
- * @return the translated value
- */
-
- public static String getAlignment(int alignment) {
- switch(alignment) {
- case Element.ALIGN_LEFT:
- return ALIGN_LEFT;
- case Element.ALIGN_CENTER:
- return ALIGN_CENTER;
- case Element.ALIGN_RIGHT:
- return ALIGN_RIGHT;
- case Element.ALIGN_JUSTIFIED:
- case Element.ALIGN_JUSTIFIED_ALL:
- return ALIGN_JUSTIFIED;
- case Element.ALIGN_TOP:
- return ALIGN_TOP;
- case Element.ALIGN_MIDDLE:
- return ALIGN_MIDDLE;
- case Element.ALIGN_BOTTOM:
- return ALIGN_BOTTOM;
- case Element.ALIGN_BASELINE:
- return ALIGN_BASELINE;
- default:
- return DEFAULT;
- }
- }
-
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/Entities.java pdftk-2.01/java/com/lowagie/text/Entities.java
--- pdftk-1.45/java/com/lowagie/text/Entities.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Entities.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,393 +0,0 @@
-/*
- * $Id: Entities.java,v 1.43 2004/12/14 11:52:46 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.util.HashMap;
-
-/**
- * This class contains entities that can be used in an entity tag.
- */
-
-public class Entities {
-
- /** This is a map that contains all possible id values of the entity tag. */
- public static final HashMap map;
-
- static {
- map = new HashMap();
- map.put("169", new Integer(227));
- map.put("172", new Integer(216));
- map.put("174", new Integer(210));
- map.put("177", new Integer(177));
- map.put("215", new Integer(180));
- map.put("247", new Integer(184));
- map.put("8230", new Integer(188));
- map.put("8242", new Integer(162));
- map.put("8243", new Integer(178));
- map.put("8260", new Integer(164));
- map.put("8364", new Integer(240));
- map.put("8465", new Integer(193));
- map.put("8472", new Integer(195));
- map.put("8476", new Integer(194));
- map.put("8482", new Integer(212));
- map.put("8501", new Integer(192));
- map.put("8592", new Integer(172));
- map.put("8593", new Integer(173));
- map.put("8594", new Integer(174));
- map.put("8595", new Integer(175));
- map.put("8596", new Integer(171));
- map.put("8629", new Integer(191));
- map.put("8656", new Integer(220));
- map.put("8657", new Integer(221));
- map.put("8658", new Integer(222));
- map.put("8659", new Integer(223));
- map.put("8660", new Integer(219));
- map.put("8704", new Integer(34));
- map.put("8706", new Integer(182));
- map.put("8707", new Integer(36));
- map.put("8709", new Integer(198));
- map.put("8711", new Integer(209));
- map.put("8712", new Integer(206));
- map.put("8713", new Integer(207));
- map.put("8717", new Integer(39));
- map.put("8719", new Integer(213));
- map.put("8721", new Integer(229));
- map.put("8722", new Integer(45));
- map.put("8727", new Integer(42));
- map.put("8729", new Integer(183));
- map.put("8730", new Integer(214));
- map.put("8733", new Integer(181));
- map.put("8734", new Integer(165));
- map.put("8736", new Integer(208));
- map.put("8743", new Integer(217));
- map.put("8744", new Integer(218));
- map.put("8745", new Integer(199));
- map.put("8746", new Integer(200));
- map.put("8747", new Integer(242));
- map.put("8756", new Integer(92));
- map.put("8764", new Integer(126));
- map.put("8773", new Integer(64));
- map.put("8776", new Integer(187));
- map.put("8800", new Integer(185));
- map.put("8801", new Integer(186));
- map.put("8804", new Integer(163));
- map.put("8805", new Integer(179));
- map.put("8834", new Integer(204));
- map.put("8835", new Integer(201));
- map.put("8836", new Integer(203));
- map.put("8838", new Integer(205));
- map.put("8839", new Integer(202));
- map.put("8853", new Integer(197));
- map.put("8855", new Integer(196));
- map.put("8869", new Integer(94));
- map.put("8901", new Integer(215));
- map.put("8992", new Integer(243));
- map.put("8993", new Integer(245));
- map.put("9001", new Integer(225));
- map.put("9002", new Integer(241));
- map.put("913", new Integer(65));
- map.put("914", new Integer(66));
- map.put("915", new Integer(71));
- map.put("916", new Integer(68));
- map.put("917", new Integer(69));
- map.put("918", new Integer(90));
- map.put("919", new Integer(72));
- map.put("920", new Integer(81));
- map.put("921", new Integer(73));
- map.put("922", new Integer(75));
- map.put("923", new Integer(76));
- map.put("924", new Integer(77));
- map.put("925", new Integer(78));
- map.put("926", new Integer(88));
- map.put("927", new Integer(79));
- map.put("928", new Integer(80));
- map.put("929", new Integer(82));
- map.put("931", new Integer(83));
- map.put("932", new Integer(84));
- map.put("933", new Integer(85));
- map.put("934", new Integer(70));
- map.put("935", new Integer(67));
- map.put("936", new Integer(89));
- map.put("937", new Integer(87));
- map.put("945", new Integer(97));
- map.put("946", new Integer(98));
- map.put("947", new Integer(103));
- map.put("948", new Integer(100));
- map.put("949", new Integer(101));
- map.put("950", new Integer(122));
- map.put("951", new Integer(104));
- map.put("952", new Integer(113));
- map.put("953", new Integer(105));
- map.put("954", new Integer(107));
- map.put("955", new Integer(108));
- map.put("956", new Integer(109));
- map.put("957", new Integer(110));
- map.put("958", new Integer(120));
- map.put("959", new Integer(111));
- map.put("960", new Integer(112));
- map.put("961", new Integer(114));
- map.put("962", new Integer(86));
- map.put("963", new Integer(115));
- map.put("964", new Integer(116));
- map.put("965", new Integer(117));
- map.put("966", new Integer(102));
- map.put("967", new Integer(99));
- map.put("9674", new Integer(224));
- map.put("968", new Integer(121));
- map.put("969", new Integer(119));
- map.put("977", new Integer(74));
- map.put("978", new Integer(161));
- map.put("981", new Integer(106));
- map.put("982", new Integer(118));
- map.put("9824", new Integer(170));
- map.put("9827", new Integer(167));
- map.put("9829", new Integer(169));
- map.put("9830", new Integer(168));
- map.put("Alpha", new Integer(65));
- map.put("Beta", new Integer(66));
- map.put("Chi", new Integer(67));
- map.put("Delta", new Integer(68));
- map.put("Epsilon", new Integer(69));
- map.put("Eta", new Integer(72));
- map.put("Gamma", new Integer(71));
- map.put("Iota", new Integer(73));
- map.put("Kappa", new Integer(75));
- map.put("Lambda", new Integer(76));
- map.put("Mu", new Integer(77));
- map.put("Nu", new Integer(78));
- map.put("Omega", new Integer(87));
- map.put("Omicron", new Integer(79));
- map.put("Phi", new Integer(70));
- map.put("Pi", new Integer(80));
- map.put("Prime", new Integer(178));
- map.put("Psi", new Integer(89));
- map.put("Rho", new Integer(82));
- map.put("Sigma", new Integer(83));
- map.put("Tau", new Integer(84));
- map.put("Theta", new Integer(81));
- map.put("Upsilon", new Integer(85));
- map.put("Xi", new Integer(88));
- map.put("Zeta", new Integer(90));
- map.put("alefsym", new Integer(192));
- map.put("alpha", new Integer(97));
- map.put("and", new Integer(217));
- map.put("ang", new Integer(208));
- map.put("asymp", new Integer(187));
- map.put("beta", new Integer(98));
- map.put("cap", new Integer(199));
- map.put("chi", new Integer(99));
- map.put("clubs", new Integer(167));
- map.put("cong", new Integer(64));
- map.put("copy", new Integer(211));
- map.put("crarr", new Integer(191));
- map.put("cup", new Integer(200));
- map.put("dArr", new Integer(223));
- map.put("darr", new Integer(175));
- map.put("delta", new Integer(100));
- map.put("diams", new Integer(168));
- map.put("divide", new Integer(184));
- map.put("empty", new Integer(198));
- map.put("epsilon", new Integer(101));
- map.put("equiv", new Integer(186));
- map.put("eta", new Integer(104));
- map.put("euro", new Integer(240));
- map.put("exist", new Integer(36));
- map.put("forall", new Integer(34));
- map.put("frasl", new Integer(164));
- map.put("gamma", new Integer(103));
- map.put("ge", new Integer(179));
- map.put("hArr", new Integer(219));
- map.put("harr", new Integer(171));
- map.put("hearts", new Integer(169));
- map.put("hellip", new Integer(188));
- map.put("horizontal arrow extender", new Integer(190));
- map.put("image", new Integer(193));
- map.put("infin", new Integer(165));
- map.put("int", new Integer(242));
- map.put("iota", new Integer(105));
- map.put("isin", new Integer(206));
- map.put("kappa", new Integer(107));
- map.put("lArr", new Integer(220));
- map.put("lambda", new Integer(108));
- map.put("lang", new Integer(225));
- map.put("large brace extender", new Integer(239));
- map.put("large integral extender", new Integer(244));
- map.put("large left brace (bottom)", new Integer(238));
- map.put("large left brace (middle)", new Integer(237));
- map.put("large left brace (top)", new Integer(236));
- map.put("large left bracket (bottom)", new Integer(235));
- map.put("large left bracket (extender)", new Integer(234));
- map.put("large left bracket (top)", new Integer(233));
- map.put("large left parenthesis (bottom)", new Integer(232));
- map.put("large left parenthesis (extender)", new Integer(231));
- map.put("large left parenthesis (top)", new Integer(230));
- map.put("large right brace (bottom)", new Integer(254));
- map.put("large right brace (middle)", new Integer(253));
- map.put("large right brace (top)", new Integer(252));
- map.put("large right bracket (bottom)", new Integer(251));
- map.put("large right bracket (extender)", new Integer(250));
- map.put("large right bracket (top)", new Integer(249));
- map.put("large right parenthesis (bottom)", new Integer(248));
- map.put("large right parenthesis (extender)", new Integer(247));
- map.put("large right parenthesis (top)", new Integer(246));
- map.put("larr", new Integer(172));
- map.put("le", new Integer(163));
- map.put("lowast", new Integer(42));
- map.put("loz", new Integer(224));
- map.put("minus", new Integer(45));
- map.put("mu", new Integer(109));
- map.put("nabla", new Integer(209));
- map.put("ne", new Integer(185));
- map.put("not", new Integer(216));
- map.put("notin", new Integer(207));
- map.put("nsub", new Integer(203));
- map.put("nu", new Integer(110));
- map.put("omega", new Integer(119));
- map.put("omicron", new Integer(111));
- map.put("oplus", new Integer(197));
- map.put("or", new Integer(218));
- map.put("otimes", new Integer(196));
- map.put("part", new Integer(182));
- map.put("perp", new Integer(94));
- map.put("phi", new Integer(102));
- map.put("pi", new Integer(112));
- map.put("piv", new Integer(118));
- map.put("plusmn", new Integer(177));
- map.put("prime", new Integer(162));
- map.put("prod", new Integer(213));
- map.put("prop", new Integer(181));
- map.put("psi", new Integer(121));
- map.put("rArr", new Integer(222));
- map.put("radic", new Integer(214));
- map.put("radical extender", new Integer(96));
- map.put("rang", new Integer(241));
- map.put("rarr", new Integer(174));
- map.put("real", new Integer(194));
- map.put("reg", new Integer(210));
- map.put("rho", new Integer(114));
- map.put("sdot", new Integer(215));
- map.put("sigma", new Integer(115));
- map.put("sigmaf", new Integer(86));
- map.put("sim", new Integer(126));
- map.put("spades", new Integer(170));
- map.put("sub", new Integer(204));
- map.put("sube", new Integer(205));
- map.put("sum", new Integer(229));
- map.put("sup", new Integer(201));
- map.put("supe", new Integer(202));
- map.put("tau", new Integer(116));
- map.put("there4", new Integer(92));
- map.put("theta", new Integer(113));
- map.put("thetasym", new Integer(74));
- map.put("times", new Integer(180));
- map.put("trade", new Integer(212));
- map.put("uArr", new Integer(221));
- map.put("uarr", new Integer(173));
- map.put("upsih", new Integer(161));
- map.put("upsilon", new Integer(117));
- map.put("vertical arrow extender", new Integer(189));
- map.put("weierp", new Integer(195));
- map.put("xi", new Integer(120));
- map.put("zeta", new Integer(122));
- }
-
- /**
- * Gets a chunk with a symbol character.
- * @param e a symbol value (see Entities class: alfa is greek alfa,...)
- * @param font the font if the symbol isn't found (otherwise Font.SYMBIL)
- * @return a Chunk
- */
- public static Chunk get(String e, Font font) {
- int s = getCorrespondingSymbol(e);
- if (s == -1) {
- try {
- return new Chunk(String.valueOf((char)Integer.parseInt(e)), font);
- }
- catch(Exception exception) {
- return new Chunk(e, font);
- }
- }
- Font symbol = new Font(Font.SYMBOL, font.size(), font.style(), font.color());
- return new Chunk(String.valueOf((char)s), symbol);
- }
-
-/**
- * Looks for the corresponding symbol in the font Symbol.
- *
- * @param c the original ASCII-char
- * @return the corresponding symbol in font Symbol
- */
-
- public static int getCorrespondingSymbol(String c) {
- Integer integer = (Integer) map.get(c);
- if (integer == null) {
- return -1;
- }
- return integer.intValue();
- }
-
-/**
- * Checks if a given tag corresponds with this object.
- *
- * @param tag the given tag
- * @return true if the tag corresponds
- */
-
- public static boolean isTag(String tag) {
- return ElementTags.ENTITY.equals(tag);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/ExceptionConverter.java pdftk-2.01/java/com/lowagie/text/ExceptionConverter.java
--- pdftk-1.45/java/com/lowagie/text/ExceptionConverter.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/ExceptionConverter.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,141 +0,0 @@
-/*
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text;
-
-/**
- * The ExceptionConverter changes a checked exception into an
- * unchecked exception.
- */
-public class ExceptionConverter extends RuntimeException {
- /** we keep a handle to the wrapped exception */
- private Exception ex;
- /** prefix for the exception */
- private String prefix;
-
- /**
- * Construct a RuntimeException based on another Exception
- * @param ex the exception that has to be turned into a RuntimeException
- */
- public ExceptionConverter(Exception ex) {
- this.ex = ex;
- prefix = (ex instanceof RuntimeException) ? "" : "ExceptionConverter: ";
- }
-
- /**
- * and allow the user of ExceptionConverter to get a handle to it.
- * @return the original exception
- */
- public Exception getException() {
- return ex;
- }
-
- /**
- * We print the message of the checked exception
- * @return message of the original exception
- */
- public String getMessage() {
- return ex.getMessage();
- }
-
- /**
- * and make sure we also produce a localized version
- * @return localized version of the message
- */
- public String getLocalizedMessage() {
- return ex.getLocalizedMessage();
- }
-
- /**
- * The toString() is changed to be prefixed with ExceptionConverter
- * @return Stringversion of the exception
- */
- public String toString() {
- return prefix + ex;
- }
-
- /** we have to override this as well */
- public void printStackTrace() {
- printStackTrace(System.err);
- }
-
- /**
- * here we prefix, with s.print(), not s.println(), the stack
- * trace with "ExceptionConverter:"
- * @param s
- */
- public void printStackTrace(java.io.PrintStream s) {
- synchronized (s) {
- s.print(prefix);
- ex.printStackTrace(s);
- }
- }
-
- /**
- * Again, we prefix the stack trace with "ExceptionConverter:"
- * @param s
- */
- public void printStackTrace(java.io.PrintWriter s) {
- synchronized (s) {
- s.print(prefix);
- ex.printStackTrace(s);
- }
- }
-
- /**
- * requests to fill in the stack trace we will have to ignore.
- * We can't throw an exception here, because this method
- * is called by the constructor of Throwable
- * @return a Throwable
- */
- public Throwable fillInStackTrace() {
- return this;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/Font.java pdftk-2.01/java/com/lowagie/text/Font.java
--- pdftk-1.45/java/com/lowagie/text/Font.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Font.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,812 +0,0 @@
-/*
- * $Id: Font.java,v 1.94 2005/10/05 14:16:04 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.awt.Color;
-
-import com.lowagie.text.pdf.BaseFont;
-import com.lowagie.text.markup.MarkupTags;
-
-/**
- * Contains all the specifications of a font: fontfamily, size, style and color.
- *
- * Example:
- *
- *
- *
- * Paragraph p = new Paragraph("This is a paragraph", new
- * Font(Font.HELVETICA, 18, Font.BOLDITALIC, new Color(0, 0, 255)) );
- *
- *
- *
- *
- */
-
-public class Font implements Comparable {
-
- // static membervariables for the different families
-
- /** a possible value of a font family. */
- public static final int COURIER = 0;
-
- /** a possible value of a font family. */
- public static final int HELVETICA = 1;
-
- /** a possible value of a font family. */
- public static final int TIMES_ROMAN = 2;
-
- /** a possible value of a font family. */
- public static final int SYMBOL = 3;
-
- /** a possible value of a font family. */
- public static final int ZAPFDINGBATS = 4;
-
- // static membervariables for the different styles
-
- /** this is a possible style. */
- public static final int NORMAL = 0;
-
- /** this is a possible style. */
- public static final int BOLD = 1;
-
- /** this is a possible style. */
- public static final int ITALIC = 2;
-
- /** this is a possible style. */
- public static final int UNDERLINE = 4;
-
- /** this is a possible style. */
- public static final int STRIKETHRU = 8;
-
- /** this is a possible style. */
- public static final int BOLDITALIC = BOLD | ITALIC;
-
- // static membervariables
-
- /** the value of an undefined attribute. */
- public static final int UNDEFINED = -1;
-
- /** the value of the default size. */
- public static final int DEFAULTSIZE = 12;
-
- // membervariables
-
- /** the value of the fontfamily. */
- private int family = UNDEFINED;
-
- /** the value of the fontsize. */
- private float size = UNDEFINED;
-
- /** the value of the style. */
- private int style = UNDEFINED;
-
- /** the value of the color. */
- private Color color = null;
-
- /** the external font */
- private BaseFont baseFont = null;
-
- // constructors
-
- /**
- * Copy constructor of a Font
- *
- * @param other
- * the font that has to be copied
- */
- public Font(Font other) {
- this.color = other.color;
- this.family = other.family;
- this.size = other.size;
- this.style = other.style;
- this.baseFont = other.baseFont;
- }
-
- /**
- * Constructs a Font.
- *
- * @param family
- * the family to which this font belongs
- * @param size
- * the size of this font
- * @param style
- * the style of this font
- * @param color
- * the Color
of this font.
- */
-
- public Font(int family, float size, int style, Color color) {
- this.family = family;
- this.size = size;
- this.style = style;
- this.color = color;
- }
-
- /**
- * Constructs a Font.
- *
- * @param bf
- * the external font
- * @param size
- * the size of this font
- * @param style
- * the style of this font
- * @param color
- * the Color
of this font.
- */
-
- public Font(BaseFont bf, float size, int style, Color color) {
- this.baseFont = bf;
- this.size = size;
- this.style = style;
- this.color = color;
- }
-
- /**
- * Constructs a Font.
- *
- * @param bf
- * the external font
- * @param size
- * the size of this font
- * @param style
- * the style of this font
- */
- public Font(BaseFont bf, float size, int style) {
- this(bf, size, style, null);
- }
-
- /**
- * Constructs a Font.
- *
- * @param bf
- * the external font
- * @param size
- * the size of this font
- */
- public Font(BaseFont bf, float size) {
- this(bf, size, UNDEFINED, null);
- }
-
- /**
- * Constructs a Font.
- *
- * @param bf
- * the external font
- */
- public Font(BaseFont bf) {
- this(bf, UNDEFINED, UNDEFINED, null);
- }
-
- /**
- * Constructs a Font.
- *
- * @param family
- * the family to which this font belongs
- * @param size
- * the size of this font
- * @param style
- * the style of this font
- */
-
- public Font(int family, float size, int style) {
- this(family, size, style, null);
- }
-
- /**
- * Constructs a Font.
- *
- * @param family
- * the family to which this font belongs
- * @param size
- * the size of this font
- */
-
- public Font(int family, float size) {
- this(family, size, UNDEFINED, null);
- }
-
- /**
- * Constructs a Font.
- *
- * @param family
- * the family to which this font belongs
- */
-
- public Font(int family) {
- this(family, UNDEFINED, UNDEFINED, null);
- }
-
- /**
- * Constructs a Font.
- */
-
- public Font() {
- this(UNDEFINED, UNDEFINED, UNDEFINED, null);
- }
-
- // implementation of the Comparable interface
-
- /**
- * Compares this Font
with another
- *
- * @param object
- * the other Font
- * @return a value
- */
-
- public int compareTo(Object object) {
- if (object == null) {
- return -1;
- }
- Font font;
- try {
- font = (Font) object;
- if (baseFont != null && !baseFont.equals(font.getBaseFont())) {
- return -2;
- }
- if (this.family != font.family()) {
- return 1;
- }
- if (this.size != font.size()) {
- return 2;
- }
- if (this.style != font.style()) {
- return 3;
- }
- if (this.color == null) {
- if (font.color == null) {
- return 0;
- }
- return 4;
- }
- if (font.color == null) {
- return 4;
- }
- if (this.color.equals(font.color())) {
- return 0;
- }
- return 4;
- } catch (ClassCastException cce) {
- return -3;
- }
- }
-
- // methods
-
- /**
- * Sets the family using a String
("Courier", "Helvetica",
- * "Times New Roman", "Symbol" or "ZapfDingbats").
- *
- * @param family
- * A String
representing a certain font-family.
- */
-
- public void setFamily(String family) {
- this.family = getFamilyIndex(family);
- }
-
- /**
- * Translates a String
-value of a certain family into the
- * index that is used for this family in this class.
- *
- * @param family
- * A String
representing a certain font-family
- * @return the corresponding index
- */
-
- public static int getFamilyIndex(String family) {
- if (family.equalsIgnoreCase(FontFactory.COURIER)) {
- return COURIER;
- }
- if (family.equalsIgnoreCase(FontFactory.HELVETICA)) {
- return HELVETICA;
- }
- if (family.equalsIgnoreCase(FontFactory.TIMES_ROMAN)) {
- return TIMES_ROMAN;
- }
- if (family.equalsIgnoreCase(FontFactory.SYMBOL)) {
- return SYMBOL;
- }
- if (family.equalsIgnoreCase(FontFactory.ZAPFDINGBATS)) {
- return ZAPFDINGBATS;
- }
- return UNDEFINED;
- }
-
- /**
- * Gets the familyname as a String.
- *
- * @return the familyname
- */
-
- public String getFamilyname() {
- String tmp = "unknown";
- switch (family()) {
- case Font.COURIER:
- return FontFactory.COURIER;
- case Font.HELVETICA:
- return FontFactory.HELVETICA;
- case Font.TIMES_ROMAN:
- return FontFactory.TIMES_ROMAN;
- case Font.SYMBOL:
- return FontFactory.SYMBOL;
- case Font.ZAPFDINGBATS:
- return FontFactory.ZAPFDINGBATS;
- default:
- if (baseFont != null) {
- String[][] names = baseFont.getFamilyFontName();
- for (int i = 0; i < names.length; i++) {
- if ("0".equals(names[i][2])) {
- return names[i][3];
- }
- if ("1033".equals(names[i][2])) {
- tmp = names[i][3];
- }
- if ("".equals(names[i][2])) {
- tmp = names[i][3];
- }
- }
- }
- }
- return tmp;
- }
-
- /**
- * Sets the size.
- *
- * @param size
- * The new size of the font.
- */
-
- public void setSize(float size) {
- this.size = size;
- }
-
- /**
- * Sets the style using a String
containing one of more of
- * the following values: normal, bold, italic, underline, strike.
- *
- * @param style
- * A String
representing a certain style.
- */
-
- public void setStyle(String style) {
- if (this.style == UNDEFINED)
- this.style = NORMAL;
- this.style |= getStyleValue(style);
- }
-
- /**
- * Sets the style.
- *
- * @param style
- * the style.
- */
-
- public void setStyle(int style) {
- if (this.style == UNDEFINED)
- this.style = NORMAL;
- this.style |= style;
- }
-
- /**
- * Translates a String
-value of a certain style into the
- * index value is used for this style in this class.
- *
- * @param style
- * A String
- * @return the corresponding value
- */
-
- public static int getStyleValue(String style) {
- int s = 0;
- if (style.indexOf(MarkupTags.CSS_VALUE_NORMAL) != -1) {
- s |= NORMAL;
- }
- if (style.indexOf(MarkupTags.CSS_VALUE_BOLD) != -1) {
- s |= BOLD;
- }
- if (style.indexOf(MarkupTags.CSS_VALUE_ITALIC) != -1) {
- s |= ITALIC;
- }
- if (style.indexOf(MarkupTags.CSS_VALUE_OBLIQUE) != -1) {
- s |= ITALIC;
- }
- if (style.indexOf(MarkupTags.CSS_VALUE_UNDERLINE) != -1) {
- s |= UNDERLINE;
- }
- if (style.indexOf(MarkupTags.CSS_VALUE_LINETHROUGH) != -1) {
- s |= STRIKETHRU;
- }
- return s;
- }
-
- /**
- * Sets the color.
- *
- * @param color
- * the new color of the font
- */
-
- public void setColor(Color color) {
- this.color = color;
- }
-
- /**
- * Sets the color.
- *
- * @param red
- * the red-value of the new color
- * @param green
- * the green-value of the new color
- * @param blue
- * the blue-value of the new color
- */
-
- public void setColor(int red, int green, int blue) {
- this.color = new Color(red, green, blue);
- }
-
- /**
- * Gets the leading that can be used with this font.
- *
- * @param linespacing
- * a certain linespacing
- * @return the height of a line
- */
-
- public float leading(float linespacing) {
- if (size == UNDEFINED) {
- return linespacing * DEFAULTSIZE;
- }
- return linespacing * size;
- }
-
- /**
- * Checks if the properties of this font are undefined or null.
- *
- * If so, the standard should be used.
- *
- * @return a boolean
- */
-
- public boolean isStandardFont() {
- return (family == UNDEFINED && size == UNDEFINED && style == UNDEFINED
- && color == null && baseFont == null);
- }
-
- /**
- * Replaces the attributes that are equal to null with the
- * attributes of a given font.
- *
- * @param font
- * the font of a bigger element class
- * @return a Font
- */
-
- public Font difference(Font font) {
- // size
- float dSize = font.size;
- if (dSize == UNDEFINED) {
- dSize = this.size;
- }
- // style
- int dStyle = UNDEFINED;
- int style1 = this.style;
- int style2 = font.style();
- if (style1 != UNDEFINED || style2 != UNDEFINED) {
- if (style1 == UNDEFINED)
- style1 = 0;
- if (style2 == UNDEFINED)
- style2 = 0;
- dStyle = style1 | style2;
- }
- // color
- Color dColor = font.color;
- if (dColor == null) {
- dColor = this.color;
- }
- // family
- if (font.baseFont != null) {
- return new Font(font.baseFont, dSize, dStyle, dColor);
- }
- if (font.family() != UNDEFINED) {
- return new Font(font.family, dSize, dStyle, dColor);
- }
- if (this.baseFont != null) {
- if (dStyle == style1) {
- return new Font(this.baseFont, dSize, dStyle, dColor);
- } else {
- return FontFactory.getFont(this.getFamilyname(), dSize, dStyle,
- dColor);
- }
- }
- return new Font(this.family, dSize, dStyle, dColor);
- }
-
- // methods to retrieve the membervariables
-
- /**
- * Gets the family of this font.
- *
- * @return the value of the family
- */
-
- public int family() {
- return family;
- }
-
- /**
- * Gets the size of this font.
- *
- * @return a size
- */
-
- public float size() {
- return size;
- }
-
- /**
- * Gets the style of this font.
- *
- * @return a size
- */
-
- public int style() {
- return style;
- }
-
- /**
- * checks if this font is Bold.
- *
- * @return a boolean
- */
-
- public boolean isBold() {
- if (style == UNDEFINED) {
- return false;
- }
- return (style & BOLD) == BOLD;
- }
-
- /**
- * checks if this font is Bold.
- *
- * @return a boolean
- */
-
- public boolean isItalic() {
- if (style == UNDEFINED) {
- return false;
- }
- return (style & ITALIC) == ITALIC;
- }
-
- /**
- * checks if this font is underlined.
- *
- * @return a boolean
- */
-
- public boolean isUnderlined() {
- if (style == UNDEFINED) {
- return false;
- }
- return (style & UNDERLINE) == UNDERLINE;
- }
-
- /**
- * checks if the style of this font is STRIKETHRU.
- *
- * @return a boolean
- */
-
- public boolean isStrikethru() {
- if (style == UNDEFINED) {
- return false;
- }
- return (style & STRIKETHRU) == STRIKETHRU;
- }
-
- /**
- * Gets the color of this font.
- *
- * @return a color
- */
-
- public Color color() {
- return color;
- }
-
- /**
- * Gets the BaseFont
inside this object.
- *
- * @return the BaseFont
- */
-
- public BaseFont getBaseFont() {
- return baseFont;
- }
-
- /**
- * Gets the BaseFont
this class represents. For the built-in
- * fonts a BaseFont
is calculated.
- *
- * @param specialEncoding
- * true
to use the special encoding for Symbol and
- * ZapfDingbats, false
to always use Cp1252
- *
- * @return the BaseFont
this class represents
- */
- public BaseFont getCalculatedBaseFont(boolean specialEncoding) {
- if (baseFont != null)
- return baseFont;
- int style = this.style;
- if (style == UNDEFINED) {
- style = NORMAL;
- }
- String fontName = BaseFont.HELVETICA;
- String encoding = BaseFont.WINANSI;
- BaseFont cfont = null;
- switch (family) {
- case COURIER:
- switch (style & BOLDITALIC) {
- case BOLD:
- fontName = BaseFont.COURIER_BOLD;
- break;
- case ITALIC:
- fontName = BaseFont.COURIER_OBLIQUE;
- break;
- case BOLDITALIC:
- fontName = BaseFont.COURIER_BOLDOBLIQUE;
- break;
- default:
- //case NORMAL:
- fontName = BaseFont.COURIER;
- break;
- }
- break;
- case TIMES_ROMAN:
- switch (style & BOLDITALIC) {
- case BOLD:
- fontName = BaseFont.TIMES_BOLD;
- break;
- case ITALIC:
- fontName = BaseFont.TIMES_ITALIC;
- break;
- case BOLDITALIC:
- fontName = BaseFont.TIMES_BOLDITALIC;
- break;
- default:
- case NORMAL:
- fontName = BaseFont.TIMES_ROMAN;
- break;
- }
- break;
- case SYMBOL:
- fontName = BaseFont.SYMBOL;
- if (specialEncoding)
- encoding = BaseFont.SYMBOL;
- break;
- case ZAPFDINGBATS:
- fontName = BaseFont.ZAPFDINGBATS;
- if (specialEncoding)
- encoding = BaseFont.ZAPFDINGBATS;
- break;
- default:
- case Font.HELVETICA:
- switch (style & BOLDITALIC) {
- case BOLD:
- fontName = BaseFont.HELVETICA_BOLD;
- break;
- case ITALIC:
- fontName = BaseFont.HELVETICA_OBLIQUE;
- break;
- case BOLDITALIC:
- fontName = BaseFont.HELVETICA_BOLDOBLIQUE;
- break;
- default:
- case NORMAL:
- fontName = BaseFont.HELVETICA;
- break;
- }
- break;
- }
- try {
- cfont = BaseFont.createFont(fontName, encoding, false);
- } catch (Exception ee) {
- throw new ExceptionConverter(ee);
- }
- return cfont;
- }
-
- /**
- * Gets the style that can be used with the calculated BaseFont
- *
.
- *
- * @return the style that can be used with the calculated BaseFont
- *
- */
- public int getCalculatedStyle() {
- int style = this.style;
- if (style == UNDEFINED) {
- style = NORMAL;
- }
- if (baseFont != null)
- return style;
- if (family == SYMBOL || family == ZAPFDINGBATS)
- return style;
- else
- return style & (~BOLDITALIC);
- }
-
- /**
- * Gets the size that can be used with the calculated BaseFont
- *
.
- *
- * @return the size that can be used with the calculated BaseFont
- *
- */
- public float getCalculatedSize() {
- float s = this.size;
- if (s == UNDEFINED) {
- s = DEFAULTSIZE;
- }
- return s;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/FontFactory.java pdftk-2.01/java/com/lowagie/text/FontFactory.java
--- pdftk-1.45/java/com/lowagie/text/FontFactory.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/FontFactory.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,690 +0,0 @@
-/*
- * $Id: FontFactory.java,v 1.65 2005/05/03 13:03:47 blowagie Exp $
- * $Name: $
- *
- * Copyright 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.awt.Color;
-import java.io.IOException;
-import java.util.Hashtable;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Properties;
-import java.util.Set;
-import java.util.Enumeration;
-import java.io.File;
-import com.lowagie.text.pdf.BaseFont;
-import com.lowagie.text.markup.MarkupTags;
-import com.lowagie.text.markup.MarkupParser;
-
-/**
- * If you are using True Type fonts, you can declare the paths of the different ttf- and ttc-files
- * to this static class first and then create fonts in your code using one of the static getFont-method
- * without having to enter a path as parameter.
- *
- * @author Bruno Lowagie
- */
-
-public class FontFactory extends java.lang.Object {
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String COURIER = BaseFont.COURIER;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String COURIER_BOLD = BaseFont.COURIER_BOLD;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String COURIER_OBLIQUE = BaseFont.COURIER_OBLIQUE;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String COURIER_BOLDOBLIQUE = BaseFont.COURIER_BOLDOBLIQUE;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String HELVETICA = BaseFont.HELVETICA;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String HELVETICA_BOLD = BaseFont.HELVETICA_BOLD;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String HELVETICA_OBLIQUE = BaseFont.HELVETICA_OBLIQUE;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String HELVETICA_BOLDOBLIQUE = BaseFont.HELVETICA_BOLDOBLIQUE;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String SYMBOL = BaseFont.SYMBOL;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String TIMES = "Times";
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String TIMES_ROMAN = BaseFont.TIMES_ROMAN;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String TIMES_BOLD = BaseFont.TIMES_BOLD;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String TIMES_ITALIC = BaseFont.TIMES_ITALIC;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String TIMES_BOLDITALIC = BaseFont.TIMES_BOLDITALIC;
-
-/** This is a possible value of a base 14 type 1 font */
- public static final String ZAPFDINGBATS = BaseFont.ZAPFDINGBATS;
-
-/** This is a map of postscriptfontnames of True Type fonts and the path of their ttf- or ttc-file. */
- private static Properties trueTypeFonts = new Properties();
-
- private static String[] TTFamilyOrder = {
- "3", "1", "1033",
- "3", "0", "1033",
- "1", "0", "0",
- "0", "3", "0"
- };
-
- static {
- trueTypeFonts.setProperty(COURIER.toLowerCase(), COURIER);
- trueTypeFonts.setProperty(COURIER_BOLD.toLowerCase(), COURIER_BOLD);
- trueTypeFonts.setProperty(COURIER_OBLIQUE.toLowerCase(), COURIER_OBLIQUE);
- trueTypeFonts.setProperty(COURIER_BOLDOBLIQUE.toLowerCase(), COURIER_BOLDOBLIQUE);
- trueTypeFonts.setProperty(HELVETICA.toLowerCase(), HELVETICA);
- trueTypeFonts.setProperty(HELVETICA_BOLD.toLowerCase(), HELVETICA_BOLD);
- trueTypeFonts.setProperty(HELVETICA_OBLIQUE.toLowerCase(), HELVETICA_OBLIQUE);
- trueTypeFonts.setProperty(HELVETICA_BOLDOBLIQUE.toLowerCase(), HELVETICA_BOLDOBLIQUE);
- trueTypeFonts.setProperty(SYMBOL.toLowerCase(), SYMBOL);
- trueTypeFonts.setProperty(TIMES_ROMAN.toLowerCase(), TIMES_ROMAN);
- trueTypeFonts.setProperty(TIMES_BOLD.toLowerCase(), TIMES_BOLD);
- trueTypeFonts.setProperty(TIMES_ITALIC.toLowerCase(), TIMES_ITALIC);
- trueTypeFonts.setProperty(TIMES_BOLDITALIC.toLowerCase(), TIMES_BOLDITALIC);
- trueTypeFonts.setProperty(ZAPFDINGBATS.toLowerCase(), ZAPFDINGBATS);
- }
-
-/** This is a map of fontfamilies. */
- private static Hashtable fontFamilies = new Hashtable();
-
- static {
- ArrayList tmp;
- tmp = new ArrayList();
- tmp.add(COURIER);
- tmp.add(COURIER_BOLD);
- tmp.add(COURIER_OBLIQUE);
- tmp.add(COURIER_BOLDOBLIQUE);
- fontFamilies.put(COURIER.toLowerCase(), tmp);
- tmp = new ArrayList();
- tmp.add(HELVETICA);
- tmp.add(HELVETICA_BOLD);
- tmp.add(HELVETICA_OBLIQUE);
- tmp.add(HELVETICA_BOLDOBLIQUE);
- fontFamilies.put(HELVETICA.toLowerCase(), tmp);
- tmp = new ArrayList();
- tmp.add(SYMBOL);
- fontFamilies.put(SYMBOL.toLowerCase(), tmp);
- tmp = new ArrayList();
- tmp.add(TIMES_ROMAN);
- tmp.add(TIMES_BOLD);
- tmp.add(TIMES_ITALIC);
- tmp.add(TIMES_BOLDITALIC);
- fontFamilies.put(TIMES.toLowerCase(), tmp);
- fontFamilies.put(TIMES_ROMAN.toLowerCase(), tmp);
- tmp = new ArrayList();
- tmp.add(ZAPFDINGBATS);
- fontFamilies.put(ZAPFDINGBATS.toLowerCase(), tmp);
- }
-
-
-/** This is the default encoding to use. */
- public static String defaultEncoding = BaseFont.WINANSI;
-
-/** This is the default value of the embedded variable. */
- public static boolean defaultEmbedding = BaseFont.NOT_EMBEDDED;
-
-/** Creates new FontFactory */
- private FontFactory() {
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param fontname the name of the font
- * @param encoding the encoding of the font
- * @param embedded true if the font is to be embedded in the PDF
- * @param size the size of this font
- * @param style the style of this font
- * @param color the Color
of this font.
- * @return the Font constructed based on the parameters
- */
-
- public static Font getFont(String fontname, String encoding, boolean embedded, float size, int style, Color color) {
- if (fontname == null) return new Font(Font.UNDEFINED, size, style, color);
- String lowercasefontname = fontname.toLowerCase();
- ArrayList tmp = (ArrayList) fontFamilies.get(lowercasefontname);
- if (tmp != null) {
- // some bugs were fixed here by Daniel Marczisovszky
- int s = style == Font.UNDEFINED ? Font.NORMAL : style;
- int fs = Font.NORMAL;
- boolean found = false;
- for (Iterator i = tmp.iterator(); i.hasNext(); ) {
- String f = (String) i.next();
- String lcf = f.toLowerCase();
- fs = Font.NORMAL;
- if (lcf.toLowerCase().indexOf("bold") != -1) fs |= Font.BOLD;
- if (lcf.toLowerCase().indexOf("italic") != -1 || lcf.toLowerCase().indexOf("oblique") != -1) fs |= Font.ITALIC;
- if ((s & Font.BOLDITALIC) == fs) {
- fontname = f;
- found = true;
- break;
- }
- }
- if (style != Font.UNDEFINED && found) {
- style &= ~fs;
- }
- }
- BaseFont basefont = null;
- try {
- try {
- // the font is a type 1 font or CJK font
- basefont = BaseFont.createFont(fontname, encoding, embedded);
- }
- catch(DocumentException de) {
- // the font is a true type font or an unknown font
- fontname = trueTypeFonts.getProperty(fontname.toLowerCase());
- // the font is not registered as truetype font
- if (fontname == null) return new Font(Font.UNDEFINED, size, style, color);
- // the font is registered as truetype font
- basefont = BaseFont.createFont(fontname, encoding, embedded);
- }
- }
- catch(DocumentException de) {
- // this shouldn't happen
- throw new ExceptionConverter(de);
- }
- catch(IOException ioe) {
- // the font is registered as a true type font, but the path was wrong
- return new Font(Font.UNDEFINED, size, style, color);
- }
- catch(NullPointerException npe) {
- // null was entered as fontname and/or encoding
- return new Font(Font.UNDEFINED, size, style, color);
- }
- return new Font(basefont, size, style, color);
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param attributes the attributes of a Font
object.
- * @return the Font constructed based on the attributes
- */
-
- public static Font getFont(Properties attributes) {
- String fontname = null;
- String encoding = defaultEncoding;
- boolean embedded = defaultEmbedding;
- float size = Font.UNDEFINED;
- int style = Font.NORMAL;
- Color color = null;
- String value = (String) attributes.remove(MarkupTags.HTML_ATTR_STYLE);
- if (value != null && value.length() > 0) {
- Properties styleAttributes = MarkupParser.parseAttributes(value);
- if (styleAttributes.size() == 0) {
- attributes.put(MarkupTags.HTML_ATTR_STYLE, value);
- }
- else {
- fontname = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTFAMILY);
- if (fontname != null) {
- String tmp;
- while (fontname.indexOf(",") != -1) {
- tmp = fontname.substring(0, fontname.indexOf(","));
- if (isRegistered(tmp)) {
- fontname = tmp;
- }
- else {
- fontname = fontname.substring(fontname.indexOf(",") + 1);
- }
- }
- }
- if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTSIZE)) != null) {
- size = MarkupParser.parseLength(value);
- }
- if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTWEIGHT)) != null) {
- style |= Font.getStyleValue(value);
- }
- if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTSTYLE)) != null) {
- style |= Font.getStyleValue(value);
- }
- if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_COLOR)) != null) {
- color = MarkupParser.decodeColor(value);
- }
- attributes.putAll(styleAttributes);
- for (Enumeration e = styleAttributes.keys(); e.hasMoreElements();) {
- Object o = e.nextElement();
- attributes.put(o, styleAttributes.get(o));
- }
- }
- }
- if ((value = (String)attributes.remove(ElementTags.ENCODING)) != null) {
- encoding = value;
- }
- if ("true".equals(attributes.remove(ElementTags.EMBEDDED))) {
- embedded = true;
- }
- if ((value = (String)attributes.remove(ElementTags.FONT)) != null) {
- fontname = value;
- }
- if ((value = (String)attributes.remove(ElementTags.SIZE)) != null) {
- size = Float.valueOf(value + "f").floatValue();
- }
- if ((value = (String)attributes.remove(MarkupTags.HTML_ATTR_STYLE)) != null) {
- style |= Font.getStyleValue(value);
- }
- if ((value = (String)attributes.remove(ElementTags.STYLE)) != null) {
- style |= Font.getStyleValue(value);
- }
- String r = (String)attributes.remove(ElementTags.RED);
- String g = (String)attributes.remove(ElementTags.GREEN);
- String b = (String)attributes.remove(ElementTags.BLUE);
- if (r != null || g != null || b != null) {
- int red = 0;
- int green = 0;
- int blue = 0;
- if (r != null) red = Integer.parseInt(r);
- if (g != null) green = Integer.parseInt(g);
- if (b != null) blue = Integer.parseInt(b);
- color = new Color(red, green, blue);
- }
- else if ((value = (String)attributes.remove(ElementTags.COLOR)) != null) {
- color = MarkupParser.decodeColor(value);
- }
- if (fontname == null) {
- return getFont(null, encoding, embedded, size, style, color);
- }
- return getFont(fontname, encoding, embedded, size, style, color);
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param fontname the name of the font
- * @param encoding the encoding of the font
- * @param embedded true if the font is to be embedded in the PDF
- * @param size the size of this font
- * @param style the style of this font
- * @return the Font constructed based on the parameters
- */
-
- public static Font getFont(String fontname, String encoding, boolean embedded, float size, int style) {
- return getFont(fontname, encoding, embedded, size, style, null);
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param fontname the name of the font
- * @param encoding the encoding of the font
- * @param embedded true if the font is to be embedded in the PDF
- * @param size the size of this font
- * @return the Font constructed based on the parameters
- */
-
- public static Font getFont(String fontname, String encoding, boolean embedded, float size) {
- return getFont(fontname, encoding, embedded, size, Font.UNDEFINED, null);
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param fontname the name of the font
- * @param encoding the encoding of the font
- * @param embedded true if the font is to be embedded in the PDF
- * @return the Font constructed based on the parameters
- */
-
- public static Font getFont(String fontname, String encoding, boolean embedded) {
- return getFont(fontname, encoding, embedded, Font.UNDEFINED, Font.UNDEFINED, null);
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param fontname the name of the font
- * @param encoding the encoding of the font
- * @param size the size of this font
- * @param style the style of this font
- * @param color the Color
of this font.
- * @return the Font constructed based on the parameters
- */
-
- public static Font getFont(String fontname, String encoding, float size, int style, Color color) {
- return getFont(fontname, encoding, defaultEmbedding, size, style, color);
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param fontname the name of the font
- * @param encoding the encoding of the font
- * @param size the size of this font
- * @param style the style of this font
- * @return the Font constructed based on the parameters
- */
-
- public static Font getFont(String fontname, String encoding, float size, int style) {
- return getFont(fontname, encoding, defaultEmbedding, size, style, null);
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param fontname the name of the font
- * @param encoding the encoding of the font
- * @param size the size of this font
- * @return the Font constructed based on the parameters
- */
-
- public static Font getFont(String fontname, String encoding, float size) {
- return getFont(fontname, encoding, defaultEmbedding, size, Font.UNDEFINED, null);
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param fontname the name of the font
- * @param encoding the encoding of the font
- * @return the Font constructed based on the parameters
- */
-
- public static Font getFont(String fontname, String encoding) {
- return getFont(fontname, encoding, defaultEmbedding, Font.UNDEFINED, Font.UNDEFINED, null);
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param fontname the name of the font
- * @param size the size of this font
- * @param style the style of this font
- * @param color the Color
of this font.
- * @return the Font constructed based on the parameters
- */
-
- public static Font getFont(String fontname, float size, int style, Color color) {
- return getFont(fontname, defaultEncoding, defaultEmbedding, size, style, color);
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param fontname the name of the font
- * @param size the size of this font
- * @param style the style of this font
- * @return the Font constructed based on the parameters
- */
-
- public static Font getFont(String fontname, float size, int style) {
- return getFont(fontname, defaultEncoding, defaultEmbedding, size, style, null);
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param fontname the name of the font
- * @param size the size of this font
- * @return the Font constructed based on the parameters
- */
-
- public static Font getFont(String fontname, float size) {
- return getFont(fontname, defaultEncoding, defaultEmbedding, size, Font.UNDEFINED, null);
- }
-
-/**
- * Constructs a Font
-object.
- *
- * @param fontname the name of the font
- * @return the Font constructed based on the parameters
- */
-
- public static Font getFont(String fontname) {
- return getFont(fontname, defaultEncoding, defaultEmbedding, Font.UNDEFINED, Font.UNDEFINED, null);
- }
-
-/**
- * Register a ttf- or a ttc-file.
- *
- * @param path the path to a ttf- or ttc-file
- */
-
- public static void register(String path) {
- register(path, null);
- }
-
-/**
- * Register a font file and use an alias for the font contained in it.
- *
- * @param path the path to a font file
- * @param alias the alias you want to use for the font
- */
-
- public static void register(String path, String alias) {
- try {
- if (path.toLowerCase().endsWith(".ttf") || path.toLowerCase().endsWith(".otf") || path.toLowerCase().indexOf(".ttc,") > 0) {
- Object allNames[] = BaseFont.getAllFontNames(path, BaseFont.WINANSI, null);
- trueTypeFonts.setProperty(((String)allNames[0]).toLowerCase(), path);
- if (alias != null) {
- trueTypeFonts.setProperty(alias, path);
- }
- // register all the font names with all the locales
- String[][] names = (String[][])allNames[2]; //full name
- for (int i = 0; i < names.length; i++) {
- trueTypeFonts.setProperty(names[i][3].toLowerCase(), path);
- }
- String fullName = null;
- String familyName = null;
- names = (String[][])allNames[1]; //family name
- for (int k = 0; k < TTFamilyOrder.length; k += 3) {
- for (int i = 0; i < names.length; i++) {
- if (TTFamilyOrder[k].equals(names[i][0]) && TTFamilyOrder[k + 1].equals(names[i][1]) && TTFamilyOrder[k + 2].equals(names[i][2])) {
- familyName = names[i][3].toLowerCase();
- k = TTFamilyOrder.length;
- break;
- }
- }
- }
- if (familyName != null) {
- String lastName = "";
- names = (String[][])allNames[2]; //full name
- for (int i = 0; i < names.length; i++) {
- for (int k = 0; k < TTFamilyOrder.length; k += 3) {
- if (TTFamilyOrder[k].equals(names[i][0]) && TTFamilyOrder[k + 1].equals(names[i][1]) && TTFamilyOrder[k + 2].equals(names[i][2])) {
- fullName = names[i][3];
- if (fullName.equals(lastName))
- continue;
- lastName = fullName;
- ArrayList tmp = (ArrayList) fontFamilies.get(familyName);
- if (tmp == null) {
- tmp = new ArrayList();
- tmp.add(fullName);
- fontFamilies.put(familyName, tmp);
- }
- else {
- int fullNameLength = fullName.length();
- boolean inserted = false;
- for (int j = 0; j < tmp.size(); ++j) {
- if (((String)tmp.get(j)).length() >= fullNameLength) {
- tmp.add(j, fullName);
- inserted = true;
- break;
- }
- }
- if (!inserted)
- tmp.add(fullName);
- }
- break;
- }
- }
- }
- }
- }
- else if (path.toLowerCase().endsWith(".ttc")) {
- if (alias != null)
- System.err.println("class FontFactory: You can't define an alias for a true type collection.");
- String[] names = BaseFont.enumerateTTCNames(path);
- for (int i = 0; i < names.length; i++) {
- register(path + "," + i);
- }
- }
- else if (path.toLowerCase().endsWith(".afm")) {
- BaseFont bf = BaseFont.createFont(path, BaseFont.CP1252, false);
- trueTypeFonts.setProperty(bf.getPostscriptFontName().toLowerCase(), path);
- trueTypeFonts.setProperty((bf.getFullFontName()[0][3]).toLowerCase(), path);
- }
- }
- catch(DocumentException de) {
- // this shouldn't happen
- throw new ExceptionConverter(de);
- }
- catch(IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- }
-
- /** Register all the fonts in a directory.
- * @param dir the directory
- * @return the number of fonts registered
- */
- public static int registerDirectory(String dir) {
- int count = 0;
- try {
- File file = new File(dir);
- if (!file.exists() || !file.isDirectory())
- return 0;
- String files[] = file.list();
- if (files == null)
- return 0;
- for (int k = 0; k < files.length; ++k) {
- try {
- file = new File(dir, files[k]);
- String name = file.getPath().toLowerCase();
- if (name.endsWith(".ttf") || name.endsWith(".otf") || name.endsWith(".afm") || name.endsWith(".ttc")) {
- register(file.getPath(), null);
- ++count;
- }
- }
- catch (Exception e) {
- //empty on purpose
- }
- }
- }
- catch (Exception e) {
- //empty on purpose
- }
- return count;
- }
-
- /** Register fonts in some probable directories. It usually works in Windows,
- * Linux and Solaris.
- * @return the number of fonts registered
- */
- public static int registerDirectories() {
- int count = 0;
- count += registerDirectory("c:/windows/fonts");
- count += registerDirectory("c:/winnt/fonts");
- count += registerDirectory("d:/windows/fonts");
- count += registerDirectory("d:/winnt/fonts");
- count += registerDirectory("/usr/X/lib/X11/fonts/TrueType");
- count += registerDirectory("/usr/openwin/lib/X11/fonts/TrueType");
- count += registerDirectory("/usr/share/fonts/default/TrueType");
- count += registerDirectory("/usr/X11R6/lib/X11/fonts/ttf");
- return count;
- }
-
-/**
- * Gets a set of registered fontnames.
- * @return a set of registered fonts
- */
-
- public static Set getRegisteredFonts() {
- return Chunk.getKeySet(trueTypeFonts);
- }
-
-/**
- * Gets a set of registered fontnames.
- * @return a set of registered font families
- */
-
- public static Set getRegisteredFamilies() {
- return Chunk.getKeySet(fontFamilies);
- }
-
-/**
- * Gets a set of registered fontnames.
- * @param fontname of a font that may or may not be registered
- * @return true if a given font is registered
- */
-
- public static boolean contains(String fontname) {
- return trueTypeFonts.containsKey(fontname.toLowerCase());
- }
-
-/**
- * Checks if a certain font is registered.
- *
- * @param fontname the name of the font that has to be checked.
- * @return true if the font is found
- */
-
- public static boolean isRegistered(String fontname) {
- return trueTypeFonts.containsKey(fontname.toLowerCase());
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/Greek.java pdftk-2.01/java/com/lowagie/text/Greek.java
--- pdftk-1.45/java/com/lowagie/text/Greek.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Greek.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,216 +0,0 @@
-/*
- * $Id: Greek.java,v 1.29 2002/06/20 13:30:24 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-/**
- * This class contains the symbols that correspond with Greek letters.
- *
- * When you construct a Phrase
(or a derived object) using a String
,
- * this String
can contain Greek Symbols. These are characters with an int value
- * between 913 and 937 (except 930) and between 945 and 969. With this class the value of the
- * corresponding character of the Font Symbol, can be retrieved.
- *
- * @see Phrase
- *
- * @author Bruno Lowagie
- * @author Evelyne De Cordier
- */
-
-public class Greek {
-
-/**
- * Returns the first occurrence of a Greek symbol in a String
.
- *
- * @param string a String
- * @return an index of -1 if no Greek symbol was found
- */
-
- public static int index(String string) {
- int length = string.length();
- for (int i = 0; i < length; i++) {
- if (getCorrespondingSymbol(string.charAt(i)) != ' ') {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Gets a chunk with a symbol character.
- */
- public static Chunk get(char c, Font font) {
- char greek = Greek.getCorrespondingSymbol(c);
- if (greek == ' ') {
- return new Chunk(String.valueOf(c), font);
- }
- Font symbol = new Font(Font.SYMBOL, font.size(), font.style(), font.color());
- String s = String.valueOf(greek);
- return new Chunk(s, symbol);
- }
-
-/**
- * Looks for the corresponding symbol in the font Symbol.
- *
- * @param c the original ASCII-char
- * @return the corresponding symbol in font Symbol
- */
-
- public static char getCorrespondingSymbol(char c) {
- switch(c) {
- case 913:
- return 'A'; // ALFA
- case 914:
- return 'B'; // BETA
- case 915:
- return 'G'; // GAMMA
- case 916:
- return 'D'; // DELTA
- case 917:
- return 'E'; // EPSILON
- case 918:
- return 'Z'; // ZETA
- case 919:
- return 'H'; // ETA
- case 920:
- return 'Q'; // THETA
- case 921:
- return 'I'; // IOTA
- case 922:
- return 'K'; // KAPPA
- case 923:
- return 'L'; // LAMBDA
- case 924:
- return 'M'; // MU
- case 925:
- return 'N'; // NU
- case 926:
- return 'X'; // XI
- case 927:
- return 'O'; // OMICRON
- case 928:
- return 'P'; // PI
- case 929:
- return 'R'; // RHO
- case 931:
- return 'S'; // SIGMA
- case 932:
- return 'T'; // TAU
- case 933:
- return 'U'; // UPSILON
- case 934:
- return 'J'; // PHI
- case 935:
- return 'C'; // CHI
- case 936:
- return 'Y'; // PSI
- case 937:
- return 'W'; // OMEGA
- case 945:
- return 'a'; // alfa
- case 946:
- return 'b'; // beta
- case 947:
- return 'g'; // gamma
- case 948:
- return 'd'; // delta
- case 949:
- return 'e'; // epsilon
- case 950:
- return 'z'; // zeta
- case 951:
- return 'h'; // eta
- case 952:
- return 'q'; // theta
- case 953:
- return 'i'; // iota
- case 954:
- return 'k'; // kappa
- case 955:
- return 'l'; // lambda
- case 956:
- return 'm'; // mu
- case 957:
- return 'n'; // nu
- case 958:
- return 'x'; // xi
- case 959:
- return 'o'; // omicron
- case 960:
- return 'p'; // pi
- case 961:
- return 'r'; // rho
- case 962:
- return 's'; // sigma
- case 963:
- return 's'; // sigma
- case 964:
- return 't'; // tau
- case 965:
- return 'u'; // upsilon
- case 966:
- return 'j'; // phi
- case 967:
- return 'c'; // chi
- case 968:
- return 'y'; // psi
- case 969:
- return 'w'; // omega
- default:
- return ' ';
- }
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/Header.java pdftk-2.01/java/com/lowagie/text/Header.java
--- pdftk-1.45/java/com/lowagie/text/Header.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Header.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,104 +0,0 @@
-/*
- * $Id: Header.java,v 1.29 2002/07/09 10:41:33 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-/**
- * This is an Element
that contains
- * some userdefined meta information about the document.
- *
- * Example:
- *
- * Header header = new Header("inspired by", "William Shakespeare");
- *
- *
- * @see Element
- * @see Meta
- */
-
-public class Header extends Meta implements Element {
-
- // membervariables
-
-/** This is the content of this chunk of text. */
- private StringBuffer name;
-
- // constructors
-
-/**
- * Constructs a Meta
.
- *
- * @param name the name of the meta-information
- * @param content the content
- */
-
- public Header(String name, String content) {
- super(Element.HEADER, content);
- this.name = new StringBuffer(name);
- }
-
- // methods to retrieve information
-
-/**
- * Returns the name of the meta information.
- *
- * @return a String
- */
-
- public String name() {
- return name.toString();
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/List.java pdftk-2.01/java/com/lowagie/text/List.java
--- pdftk-1.45/java/com/lowagie/text/List.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/List.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,564 +0,0 @@
-/*
- * $Id: List.java,v 1.74 2005/04/13 09:17:14 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Properties;
-import java.util.Set;
-
-/**
- * A List
contains several ListItem
s.
- *
- * Example 1:
- *
- * List list = new List(true, 20);
- * list.add(new ListItem("First line"));
- * list.add(new ListItem("The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?"));
- * list.add(new ListItem("Third line"));
- *
- *
- * The result of this code looks like this:
- *
- *
- * First line
- *
- *
- * The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?
- *
- *
- * Third line
- *
- *
- *
- * Example 2:
- *
- * List overview = new List(false, 10);
- * overview.add(new ListItem("This is an item"));
- * overview.add("This is another item");
- *
- *
- * The result of this code looks like this:
- *
- *
- * This is an item
- *
- *
- * This is another item
- *
- *
- *
- * @see Element
- * @see ListItem
- */
-
-public class List implements TextElementArray, MarkupAttributes {
-
- // membervariables
- /** a possible value for the numbered parameter */
- public static final boolean ORDERED = true;
- /** a possible value for the numbered parameter */
- public static final boolean UNORDERED = false;
- /** a possible value for the lettered parameter */
- public static final boolean NUMBERICAL = false;
- /** a possible value for the lettered parameter */
- public static final boolean ALPHABETICAL = true;
-
-
-/** This is the ArrayList
containing the different ListItem
s. */
- protected ArrayList list = new ArrayList();
-
-/** This variable indicates if the list has to be numbered. */
- protected boolean numbered;
- protected boolean lettered;
-
-/** This variable indicates the first number of a numbered list. */
- protected int first = 1;
- protected char firstCh = 'A';
- protected char lastCh = 'Z';
-
-/** This is the listsymbol of a list that is not numbered. */
- protected Chunk symbol = new Chunk("-");
-
-/** The indentation of this list on the left side. */
- protected float indentationLeft = 0;
-
-/** The indentation of this list on the right side. */
- protected float indentationRight = 0;
-
-/** The indentation of the listitems. */
- protected float symbolIndent;
-
-/** Contains extra markupAttributes */
- protected Properties markupAttributes;
-
- // constructors
-
-/**
- * Constructs a List
.
- *
- * Remark: the parameter symbolIndent is important for instance when
- * generating PDF-documents; it indicates the indentation of the listsymbol.
- * It is not important for HTML-documents.
- *
- * @param numbered a boolean
- * @param symbolIndent the indentation that has to be used for the listsymbol
- */
-
- public List(boolean numbered, float symbolIndent) {
- this.numbered = numbered;
- this.lettered = false;
- this.symbolIndent = symbolIndent;
- }
-
- /**
- * Creates a list
- * @param numbered has the list to be numbered?
- * @param lettered has the list to be 'numbered' with letters
- * @param symbolIndent the indentation of the symbol
- */
- public List(boolean numbered, boolean lettered, float symbolIndent ) {
- this.numbered = numbered;
- this.lettered = lettered;
- this.symbolIndent = symbolIndent;
- }
-
- /**
- * Returns a List
that has been constructed taking in account
- * the value of some attributes .
- *
- * @param attributes Some attributes
- */
-
- public List(Properties attributes) {
- String value= (String)attributes.remove(ElementTags.LISTSYMBOL);
- if (value == null) {
- value = "-";
- }
- symbol = new Chunk(value, FontFactory.getFont(attributes));
-
- this.numbered = false;
- if ((value = (String)attributes.remove(ElementTags.NUMBERED)) != null) {
- this.numbered = new Boolean(value).booleanValue();
- if ( this.lettered && this.numbered )
- this.lettered = false;
- }
- if ((value = (String)attributes.remove(ElementTags.LETTERED)) != null) {
- this.lettered = new Boolean(value).booleanValue();
- if ( this.numbered && this.lettered )
- this.numbered = false;
- }
- this.symbolIndent = 0;
- if ((value = (String)attributes.remove(ElementTags.SYMBOLINDENT)) != null) {
- this.symbolIndent = Float.parseFloat(value);
- }
-
- if ((value = (String)attributes.remove(ElementTags.FIRST)) != null) {
- char khar = value.charAt(0);
- if ( Character.isLetter( khar ) ) {
- setFirst( khar );
- }
- else {
- setFirst(Integer.parseInt(value));
- }
- }
- if ((value = (String)attributes.remove(ElementTags.INDENTATIONLEFT)) != null) {
- setIndentationLeft(Float.valueOf(value + "f").floatValue());
- }
- if ((value = (String)attributes.remove(ElementTags.INDENTATIONRIGHT)) != null) {
- setIndentationRight(Float.valueOf(value + "f").floatValue());
- }
- if (attributes.size() > 0) setMarkupAttributes(attributes);
- }
-
- // implementation of the Element-methods
-
-/**
- * Processes the element by adding it (or the different parts) to an
- * ElementListener
.
- *
- * @param listener an ElementListener
- * @return true
if the element was processed successfully
- */
-
- public boolean process(ElementListener listener) {
- try {
- for (Iterator i = list.iterator(); i.hasNext(); ) {
- listener.add((Element) i.next());
- }
- return true;
- }
- catch(DocumentException de) {
- return false;
- }
- }
-
-/**
- * Gets the type of the text element.
- *
- * @return a type
- */
-
- public int type() {
- return Element.LIST;
- }
-
-/**
- * Gets all the chunks in this element.
- *
- * @return an ArrayList
- */
-
- public ArrayList getChunks() {
- ArrayList tmp = new ArrayList();
- for (Iterator i = list.iterator(); i.hasNext(); ) {
- tmp.addAll(((Element) i.next()).getChunks());
- }
- return tmp;
- }
-
- // methods to set the membervariables
-
-/**
- * Adds an Object
to the List
.
- *
- * @param o the object to add.
- * @return true if adding the object succeeded
- */
-
- public boolean add(Object o) {
- if (o instanceof ListItem) {
- ListItem item = (ListItem) o;
- if (numbered || lettered) {
- Chunk chunk;
- if ( lettered )
- chunk = new Chunk(nextLetter(), symbol.font());
- else
- chunk = new Chunk(String.valueOf(first + list.size()), symbol.font());
- chunk.append(".");
- item.setListSymbol(chunk);
- }
- else {
- item.setListSymbol(symbol);
- }
- item.setIndentationLeft(symbolIndent);
- item.setIndentationRight(0);
- list.add(item);
- }
- else if (o instanceof List) {
- List nested = (List) o;
- nested.setIndentationLeft(nested.indentationLeft() + symbolIndent);
- first--;
- return list.add(nested);
- }
- else if (o instanceof String) {
- return this.add(new ListItem((String) o));
- }
- return false;
- }
-
-/**
- * Sets the indentation of this paragraph on the left side.
- *
- * @param indentation the new indentation
- */
-
- public void setIndentationLeft(float indentation) {
- this.indentationLeft = indentation;
- }
-
-/**
- * Sets the indentation of this paragraph on the right side.
- *
- * @param indentation the new indentation
- */
-
- public void setIndentationRight(float indentation) {
- this.indentationRight = indentation;
- }
-
-/**
- * Sets the number that has to come first in the list.
- *
- * @param first a number
- */
-
- public void setFirst(int first) {
- this.first = first;
- }
-
-
-/**
- * Sets the Letter that has to come first in the list.
- *
- * @param first a letter
- */
-
- public void setFirst(char first) {
- this.firstCh = first;
- if ( Character.isLowerCase( this.firstCh )) {
- this.lastCh = 'z';
- }
- else {
- this.lastCh = 'Z';
- }
- }
-
-/**
- * Sets the listsymbol.
- *
- * @param symbol a Chunk
- */
-
- public void setListSymbol(Chunk symbol) {
- this.symbol = symbol;
- }
-
-/**
- * Sets the listsymbol.
- *
- * This is a shortcut for setListSymbol(Chunk symbol)
.
- *
- * @param symbol a String
- */
-
- public void setListSymbol(String symbol) {
- this.symbol = new Chunk(symbol);
- }
-
- // methods to retrieve information
-
-/**
- * Gets all the items in the list.
- *
- * @return an ArrayList
containing ListItem
s.
- */
-
- public ArrayList getItems() {
- return list;
- }
-
-/**
- * Gets the size of the list.
- *
- * @return a size
- */
-
- public int size() {
- return list.size();
- }
-
-/**
- * Gets the leading of the first listitem.
- *
- * @return a leading
- */
-
- public float leading() {
- if (list.size() < 1) {
- return -1;
- }
- ListItem item = (ListItem) list.get(0);
- return item.leading();
- }
-
-/**
- * Checks if the list is numbered.
- *
- * @return true
if the list is numbered, false
otherwise.
- */
-
- public boolean isNumbered() {
- return numbered;
- }
-
-/**
- * Gets the symbol indentation.
- * @return the symbol indentation
- */
-
- public float symbolIndent() {
- return symbolIndent;
- }
-
-/**
- * Gets the Chunk containing the symbol.
- * @return a Chunk with a symbol
- */
-
- public Chunk symbol() {
- return symbol;
- }
-
-/**
- * Gets the first number .
- * @return a number
- */
-
- public int first() {
- return first;
- }
-
-/**
- * Gets the indentation of this paragraph on the left side.
- *
- * @return the indentation
- */
-
- public float indentationLeft() {
- return indentationLeft;
- }
-
-/**
- * Gets the indentation of this paragraph on the right side.
- *
- * @return the indentation
- */
-
- public float indentationRight() {
- return indentationRight;
- }
-
-/**
- * Checks if a given tag corresponds with the listsymbol tag of this object.
- *
- * @param tag the given tag
- * @return true if the tag corresponds
- */
-
- public static boolean isSymbol(String tag) {
- return ElementTags.LISTSYMBOL.equals(tag);
- }
-
-/**
- * Checks if a given tag corresponds with this object.
- *
- * @param tag the given tag
- * @return true if the tag corresponds
- */
-
- public static boolean isTag(String tag) {
- return ElementTags.LIST.equals(tag);
- }
-
-/**
- * Retrieves the next letter in the sequence
- *
- * @return String contains the next character (A-Z or a-z)
- */
- private String nextLetter() {
- int num_in_list = listItemsInList(); //list.size();
- int max_ival = (lastCh + 0);
- int ival = (firstCh + num_in_list);
- while ( ival > max_ival ) {
- ival -= 26;
- }
- char[] new_char = new char[1];
- new_char[0] = (char) ival;
- String ret = new String( new_char );
- return ret;
- }
-
- /**
- * Counts the number of ListItems in the list ommiting nested lists
- *
- * @return Integer number of ListItems in the list
- */
- private int listItemsInList() {
- int result = 0;
- for (Iterator i = list.iterator(); i.hasNext(); ) {
- if (!(i.next() instanceof List)) result++;
- }
- return result;
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String, java.lang.String)
- */
- public void setMarkupAttribute(String name, String value) {
- if (markupAttributes == null) markupAttributes = new Properties();
- markupAttributes.put(name, value);
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
- */
- public void setMarkupAttributes(Properties markupAttributes) {
- this.markupAttributes = markupAttributes;
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
- */
- public String getMarkupAttribute(String name) {
- return (markupAttributes == null) ? null : String.valueOf(markupAttributes.get(name));
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
- */
- public Set getMarkupAttributeNames() {
- return Chunk.getKeySet(markupAttributes);
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
- */
- public Properties getMarkupAttributes() {
- return markupAttributes;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/ListItem.java pdftk-2.01/java/com/lowagie/text/ListItem.java
--- pdftk-1.45/java/com/lowagie/text/ListItem.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/ListItem.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,297 +0,0 @@
-/*
- * $Id: ListItem.java,v 1.78 2005/05/03 13:03:48 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.util.Properties;
-
-import com.lowagie.text.markup.MarkupTags;
-import com.lowagie.text.markup.MarkupParser;
-
-/**
- * A ListItem
is a Paragraph
- * that can be added to a List
.
- *
- * Example 1:
- *
- * List list = new List(true, 20);
- * list.add(new ListItem("First line") );
- * list.add(new ListItem("The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?") );
- * list.add(new ListItem("Third line") );
- *
- *
- * The result of this code looks like this:
- *
- *
- * First line
- *
- *
- * The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?
- *
- *
- * Third line
- *
- *
- *
- * Example 2:
- *
- * List overview = new List(false, 10);
- * overview.add(new ListItem("This is an item") );
- * overview.add("This is another item");
- *
- *
- * The result of this code looks like this:
- *
- *
- * This is an item
- *
- *
- * This is another item
- *
- *
- *
- * @see Element
- * @see List
- * @see Paragraph
- */
-
-public class ListItem extends Paragraph implements TextElementArray, MarkupAttributes {
-
- // membervariables
-
-/** this is the symbol that wil proceed the listitem. */
- private Chunk symbol;
-
- // constructors
-
-/**
- * Constructs a ListItem
.
- */
-
- public ListItem() {
- super();
- }
-
-/**
- * Constructs a ListItem
with a certain leading.
- *
- * @param leading the leading
- */
-
- public ListItem(float leading) {
- super(leading);
- }
-
-/**
- * Constructs a ListItem
with a certain Chunk
.
- *
- * @param chunk a Chunk
- */
-
- public ListItem(Chunk chunk) {
- super(chunk);
- }
-
-/**
- * Constructs a ListItem
with a certain String
.
- *
- * @param string a String
- */
-
- public ListItem(String string) {
- super(string);
- }
-
-/**
- * Constructs a ListItem
with a certain String
- * and a certain Font
.
- *
- * @param string a String
- * @param font a String
- */
-
- public ListItem(String string, Font font) {
- super(string, font);
- }
-
-/**
- * Constructs a ListItem
with a certain Chunk
- * and a certain leading.
- *
- * @param leading the leading
- * @param chunk a Chunk
- */
-
- public ListItem(float leading, Chunk chunk) {
- super(leading, chunk);
- }
-
-/**
- * Constructs a ListItem
with a certain String
- * and a certain leading.
- *
- * @param leading the leading
- * @param string a String
- */
-
- public ListItem(float leading, String string) {
- super(leading, string);
- }
-
-/**
- * Constructs a ListItem
with a certain leading, String
- * and Font
.
- *
- * @param leading the leading
- * @param string a String
- * @param font a Font
- */
-
- public ListItem(float leading, String string, Font font) {
- super(leading, string, font);
- }
-
-/**
- * Constructs a ListItem
with a certain Phrase
.
- *
- * @param phrase a Phrase
- */
-
- public ListItem(Phrase phrase) {
- super(phrase);
- }
-
- /**
- * Returns a ListItem
that has been constructed taking in account
- * the value of some attributes .
- *
- * @param attributes Some attributes
- */
-
- public ListItem(Properties attributes) {
- super("", FontFactory.getFont(attributes));
- String value;
- if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
- add(new Chunk(value));
- }
- if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
- setLeading(Float.valueOf(value + "f").floatValue());
- }
- else if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_LINEHEIGHT)) != null) {
- setLeading(MarkupParser.parseLength(value));
- }
- if ((value = (String)attributes.remove(ElementTags.INDENTATIONLEFT)) != null) {
- setIndentationLeft(Float.valueOf(value + "f").floatValue());
- }
- if ((value = (String)attributes.remove(ElementTags.INDENTATIONRIGHT)) != null) {
- setIndentationRight(Float.valueOf(value + "f").floatValue());
- }
- if ((value = (String)attributes.remove(ElementTags.ALIGN)) != null) {
- setAlignment(value);
- }
- if (attributes.size() > 0) setMarkupAttributes(attributes);
- }
-
- // implementation of the Element-methods
-
-/**
- * Gets the type of the text element.
- *
- * @return a type
- */
-
- public int type() {
- return Element.LISTITEM;
- }
-
- // methods
-
-/**
- * Sets the listsymbol.
- *
- * @param symbol a Chunk
- */
-
- public void setListSymbol(Chunk symbol) {
- this.symbol = symbol;
- if (this.symbol.font().isStandardFont()) {
- this.symbol.setFont(font);
- }
- }
-
- // methods to retrieve information
-
-/**
- * Returns the listsymbol.
- *
- * @return a Chunk
- */
-
- public Chunk listSymbol() {
- return symbol;
- }
-
-/**
- * Checks if a given tag corresponds with this object.
- *
- * @param tag the given tag
- * @return true if the tag corresponds
- */
-
- public static boolean isTag(String tag) {
- return ElementTags.LISTITEM.equals(tag);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/Makefile pdftk-2.01/java/com/lowagie/text/Makefile
--- pdftk-1.45/java/com/lowagie/text/Makefile 2010-09-15 09:42:04.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-library= text.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-all : $(library) $(headers)
-
-$(library) : $(objects)
- $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/com/lowagie/text/MarkupAttributes.java pdftk-2.01/java/com/lowagie/text/MarkupAttributes.java
--- pdftk-1.45/java/com/lowagie/text/MarkupAttributes.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/MarkupAttributes.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,108 +0,0 @@
-/*
- * Copyright 2002 by Matt Benson.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-
-import java.util.Properties;
-import java.util.Set;
-
-
-/**
- * Defines the interface for an Element
with markup attributes--
- * that is, random String-to-String properties for representation in markup
- * languages such as HTML and XML.
- *
- * @author Matt Benson
- */
-public interface MarkupAttributes extends com.lowagie.text.Element {
-
-/**
- * Sets the specified attribute.
- *
- * @param name String
attribute name.
- * @param value String
attribute value.
- */
- public void setMarkupAttribute(String name, String value);
-
-/**
- * Sets the markupAttributes.
- *
- * @param markupAttributes a Properties
-object containing markupattributes
- */
- public void setMarkupAttributes(Properties markupAttributes);
-
-/**
- * Returns the value of the specified attribute.
- *
- * @param name String
attribute name.
- * @return String
.
- */
- public String getMarkupAttribute(String name);
-
-/**
- * Returns a Set
of String
attribute names for the
- * MarkupAttributes
implementor.
- *
- * @return Set
.
- */
- public Set getMarkupAttributeNames(); // ssteward: dropped in 1.44
-
-/**
- * Return a Properties
-object containing all the markupAttributes.
- *
- * @return Properties
- */
- public Properties getMarkupAttributes();
-
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/Meta.java pdftk-2.01/java/com/lowagie/text/Meta.java
--- pdftk-1.45/java/com/lowagie/text/Meta.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Meta.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,268 +0,0 @@
-/*
- * $Id: Meta.java,v 1.65 2005/04/13 09:17:11 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.util.ArrayList;
-import java.util.Properties;
-import java.util.Set;
-
-/**
- * This is an Element
that contains
- * some meta information about the document.
- *
- * An object of type Meta
can not be constructed by the user.
- * Userdefined meta information should be placed in a Header
-object.
- * Meta
is reserved for: Subject, Keywords, Author, Title, Producer
- * and Creationdate information.
- *
- * @see Element
- * @see Header
- */
-
-public class Meta implements Element, MarkupAttributes {
-
- // membervariables
-
-/** This is the type of Meta-information this object contains. */
- private int type;
-
-/** This is the content of the Meta-information. */
- private StringBuffer content;
-
-/** Contains extra markupAttributes */
- protected Properties markupAttributes;
-
- // constructors
-
-/**
- * Constructs a Meta
.
- *
- * @param type the type of meta-information
- * @param content the content
- */
-
- Meta(int type, String content) {
- this.type = type;
- this.content = new StringBuffer(content);
- }
-
-/**
- * Constructs a Meta
.
- *
- * @param tag the tagname of the meta-information
- * @param content the content
- */
-
- public Meta(String tag, String content) {
- this.type = Meta.getType(tag);
- this.content = new StringBuffer(content);
- }
-
- // implementation of the Element-methods
-
-/**
- * Processes the element by adding it (or the different parts) to a
- * ElementListener
.
- *
- * @param listener the ElementListener
- * @return true
if the element was processed successfully
- */
-
- public boolean process(ElementListener listener) {
- try {
- return listener.add(this);
- }
- catch(DocumentException de) {
- return false;
- }
- }
-
-/**
- * Gets the type of the text element.
- *
- * @return a type
- */
-
- public int type() {
- return type;
- }
-
-/**
- * Gets all the chunks in this element.
- *
- * @return an ArrayList
- */
- public ArrayList getChunks() {
- return new ArrayList();
- }
-
- // methods
-
-/**
- * appends some text to this Meta
.
- *
- * @param string a String
- * @return a StringBuffer
- */
-
- public StringBuffer append(String string) {
- return content.append(string);
- }
-
- // methods to retrieve information
-
-/**
- * Returns the content of the meta information.
- *
- * @return a String
- */
-
- public String content() {
- return content.toString();
- }
-
-/**
- * Returns the name of the meta information.
- *
- * @return a String
- */
-
- public String name() {
- switch (type) {
- case Element.SUBJECT:
- return ElementTags.SUBJECT;
- case Element.KEYWORDS:
- return ElementTags.KEYWORDS;
- case Element.AUTHOR:
- return ElementTags.AUTHOR;
- case Element.TITLE:
- return ElementTags.TITLE;
- case Element.PRODUCER:
- return ElementTags.PRODUCER;
- case Element.CREATIONDATE:
- return ElementTags.CREATIONDATE;
- default:
- return ElementTags.UNKNOWN;
- }
- }
-
-/**
- * Returns the name of the meta information.
- *
- * @param tag iText tag for meta information
- * @return the Element value corresponding with the given tag
- */
-
- public static int getType(String tag) {
- if (ElementTags.SUBJECT.equals(tag)) {
- return Element.SUBJECT;
- }
- if (ElementTags.KEYWORDS.equals(tag)) {
- return Element.KEYWORDS;
- }
- if (ElementTags.AUTHOR.equals(tag)) {
- return Element.AUTHOR;
- }
- if (ElementTags.TITLE.equals(tag)) {
- return Element.TITLE;
- }
- if (ElementTags.PRODUCER.equals(tag)) {
- return Element.PRODUCER;
- }
- if (ElementTags.CREATIONDATE.equals(tag)) {
- return Element.CREATIONDATE;
- }
- return Element.HEADER;
- }
-
-
-/**
- * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String, java.lang.String)
- */
- public void setMarkupAttribute(String name, String value) {
- if (markupAttributes == null) markupAttributes = new Properties();
- markupAttributes.put(name, value);
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
- */
- public void setMarkupAttributes(Properties markupAttributes) {
- this.markupAttributes = markupAttributes;
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
- */
- public String getMarkupAttribute(String name) {
- return (markupAttributes == null) ? null : String.valueOf(markupAttributes.get(name));
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
- */
- public Set getMarkupAttributeNames() {
- return Chunk.getKeySet(markupAttributes);
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
- */
- public Properties getMarkupAttributes() {
- return markupAttributes;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/PageSize.java pdftk-2.01/java/com/lowagie/text/PageSize.java
--- pdftk-1.45/java/com/lowagie/text/PageSize.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/PageSize.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,158 +0,0 @@
-/*
- * $Id: PageSize.java,v 1.26 2002/06/20 13:30:24 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-/**
- * The PageSize
-object contains a number of rectangles representing the most common papersizes.
- *
- * @see Rectangle
- */
-
-public class PageSize {
-
- // membervariables
-
-/** This is the letter format */
- public static final Rectangle LETTER = new Rectangle(612,792);
-
-/** This is the note format */
- public static final Rectangle NOTE = new Rectangle(540,720);
-
-/** This is the legal format */
- public static final Rectangle LEGAL = new Rectangle(612,1008);
-
-/** This is the a0 format */
- public static final Rectangle A0 = new Rectangle(2384,3370);
-
-/** This is the a1 format */
- public static final Rectangle A1 = new Rectangle(1684,2384);
-
-/** This is the a2 format */
- public static final Rectangle A2 = new Rectangle(1190,1684);
-
-/** This is the a3 format */
- public static final Rectangle A3 = new Rectangle(842,1190);
-
-/** This is the a4 format */
- public static final Rectangle A4 = new Rectangle(595,842);
-
-/** This is the a5 format */
- public static final Rectangle A5 = new Rectangle(421,595);
-
-/** This is the a6 format */
- public static final Rectangle A6 = new Rectangle(297,421);
-
-/** This is the a7 format */
- public static final Rectangle A7 = new Rectangle(210,297);
-
-/** This is the a8 format */
- public static final Rectangle A8 = new Rectangle(148,210);
-
-/** This is the a9 format */
- public static final Rectangle A9 = new Rectangle(105,148);
-
-/** This is the a10 format */
- public static final Rectangle A10 = new Rectangle(74,105);
-
-/** This is the b0 format */
- public static final Rectangle B0 = new Rectangle(2836,4008);
-
-/** This is the b1 format */
- public static final Rectangle B1 = new Rectangle(2004,2836);
-
-/** This is the b2 format */
- public static final Rectangle B2 = new Rectangle(1418,2004);
-
-/** This is the b3 format */
- public static final Rectangle B3 = new Rectangle(1002,1418);
-
-/** This is the b4 format */
- public static final Rectangle B4 = new Rectangle(709,1002);
-
-/** This is the b5 format */
- public static final Rectangle B5 = new Rectangle(501,709);
-
-/** This is the archE format */
- public static final Rectangle ARCH_E = new Rectangle(2592,3456);
-
-/** This is the archD format */
- public static final Rectangle ARCH_D = new Rectangle(1728,2592);
-
-/** This is the archC format */
- public static final Rectangle ARCH_C = new Rectangle(1296,1728);
-
-/** This is the archB format */
- public static final Rectangle ARCH_B = new Rectangle(864,1296);
-
-/** This is the archA format */
- public static final Rectangle ARCH_A = new Rectangle(648,864);
-
-/** This is the flsa format */
- public static final Rectangle FLSA = new Rectangle(612,936);
-
-/** This is the flse format */
- public static final Rectangle FLSE = new Rectangle(612,936);
-
-/** This is the halfletter format */
- public static final Rectangle HALFLETTER = new Rectangle(396,612);
-
-/** This is the 11x17 format */
- public static final Rectangle _11X17 = new Rectangle(792,1224);
-
-/** This is the ledger format */
- public static final Rectangle LEDGER = new Rectangle(1224,792);
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/Paragraph.java pdftk-2.01/java/com/lowagie/text/Paragraph.java
--- pdftk-1.45/java/com/lowagie/text/Paragraph.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Paragraph.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,524 +0,0 @@
-/*
- * $Id: Paragraph.java,v 1.83 2005/05/03 13:03:48 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.util.Properties;
-
-import com.lowagie.text.markup.MarkupTags;
-import com.lowagie.text.markup.MarkupParser;
-
-/**
- * A Paragraph
is a series of Chunk
s and/or Phrases
.
- *
- * A Paragraph
has the same qualities of a Phrase
, but also
- * some additional layout-parameters:
- *
- * the indentation
- * the alignment of the text
- *
- *
- * Example:
- *
- * Paragraph p = new Paragraph("This is a paragraph",
- * FontFactory.getFont(FontFactory.HELVETICA, 18, Font.BOLDITALIC, new Color(0, 0, 255)));
- *
- *
- * @see Element
- * @see Phrase
- * @see ListItem
- */
-
-public class Paragraph extends Phrase implements TextElementArray, MarkupAttributes {
-
- // membervariables
-
-/** The alignment of the text. */
- protected int alignment = Element.ALIGN_UNDEFINED;
-
-/** The indentation of this paragraph on the left side. */
- protected float indentationLeft;
-
-/** The indentation of this paragraph on the right side. */
- protected float indentationRight;
-
-/** The spacing before the paragraph. */
- protected float spacingBefore;
-
-/** The spacing after the paragraph. */
- protected float spacingAfter;
-
-/** Does the paragraph has to be kept together on 1 page. */
- protected boolean keeptogether = false;
-
- /** The text leading that is multiplied by the biggest font size in the line. */
- protected float multipliedLeading = 0;
-
- /**
- * Holds value of property firstLineIndent.
- */
- private float firstLineIndent = 0;
-
- /**
- * Holds value of property extraParagraphSpace.
- */
- private float extraParagraphSpace = 0;
-
- // constructors
-
-/**
- * Constructs a Paragraph
.
- */
-
- public Paragraph() {
- super();
- }
-
-/**
- * Constructs a Paragraph
with a certain leading.
- *
- * @param leading the leading
- */
-
- public Paragraph(float leading) {
- super(leading);
- }
-
-/**
- * Constructs a Paragraph
with a certain Chunk
.
- *
- * @param chunk a Chunk
- */
-
- public Paragraph(Chunk chunk) {
- super(chunk);
- }
-
-/**
- * Constructs a Paragraph
with a certain Chunk
- * and a certain leading.
- *
- * @param leading the leading
- * @param chunk a Chunk
- */
-
- public Paragraph(float leading, Chunk chunk) {
- super(leading, chunk);
- }
-
-/**
- * Constructs a Paragraph
with a certain String
.
- *
- * @param string a String
- */
-
- public Paragraph(String string) {
- super(string);
- }
-
-/**
- * Constructs a Paragraph
with a certain String
- * and a certain Font
.
- *
- * @param string a String
- * @param font a Font
- */
-
- public Paragraph(String string, Font font) {
- super(string, font);
- }
-
-/**
- * Constructs a Paragraph
with a certain String
- * and a certain leading.
- *
- * @param leading the leading
- * @param string a String
- */
-
- public Paragraph(float leading, String string) {
- super(leading, string);
- }
-
-/**
- * Constructs a Paragraph
with a certain leading, String
- * and Font
.
- *
- * @param leading the leading
- * @param string a String
- * @param font a Font
- */
-
- public Paragraph(float leading, String string, Font font) {
- super(leading, string, font);
- }
-
-/**
- * Constructs a Paragraph
with a certain Phrase
.
- *
- * @param phrase a Phrase
- */
-
- public Paragraph(Phrase phrase) {
- super(phrase.leading, "", phrase.font());
- super.add(phrase);
- }
-
-/**
- * Returns a Paragraph
that has been constructed taking in account
- * the value of some attributes .
- *
- * @param attributes Some attributes
- */
-
- public Paragraph(Properties attributes) {
- this("", FontFactory.getFont(attributes));
- String value;
- if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
- Chunk chunk = new Chunk(value);
- if ((value = (String)attributes.remove(ElementTags.GENERICTAG)) != null) {
- chunk.setGenericTag(value);
- }
- add(chunk);
- }
- if ((value = (String)attributes.remove(ElementTags.ALIGN)) != null) {
- setAlignment(value);
- }
- if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
- setLeading(Float.valueOf(value + "f").floatValue());
- }
- else if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_LINEHEIGHT)) != null) {
- setLeading(MarkupParser.parseLength(value));
- }
- else {
- setLeading(16);
- }
- if ((value = (String)attributes.remove(ElementTags.INDENTATIONLEFT)) != null) {
- setIndentationLeft(Float.valueOf(value + "f").floatValue());
- }
- if ((value = (String)attributes.remove(ElementTags.INDENTATIONRIGHT)) != null) {
- setIndentationRight(Float.valueOf(value + "f").floatValue());
- }
- if ((value = (String)attributes.remove(ElementTags.KEEPTOGETHER)) != null) {
- keeptogether = new Boolean(value).booleanValue();
- }
- if (attributes.size() > 0) setMarkupAttributes(attributes);
- }
-
- // implementation of the Element-methods
-
-/**
- * Gets the type of the text element.
- *
- * @return a type
- */
-
- public int type() {
- return Element.PARAGRAPH;
- }
-
- // methods
-
-/**
- * Adds an Object
to the Paragraph
.
- *
- * @param o object the object to add.
- * @return true is adding the object succeeded
- */
-
- public boolean add(Object o) {
- if (o instanceof List) {
- List list = (List) o;
- list.setIndentationLeft(list.indentationLeft() + indentationLeft);
- list.setIndentationRight(indentationRight);
- return super.add(list);
- }
- /* ssteward: dropped in 1.44
- else if (o instanceof Image) {
- super.addSpecial((Image) o);
- return true;
- }
- */
- else if (o instanceof Paragraph) {
- super.add(o);
- super.add(Chunk.NEWLINE);
- return true;
- }
- return super.add(o);
- }
-
- // setting the membervariables
-
-/**
- * Sets the alignment of this paragraph.
- *
- * @param alignment the new alignment
- */
-
- public void setAlignment(int alignment) {
- this.alignment = alignment;
- }
-
-/**
- * Sets the alignment of this paragraph.
- *
- * @param alignment the new alignment as a String
- */
-
- public void setAlignment(String alignment) {
- if (ElementTags.ALIGN_CENTER.equalsIgnoreCase(alignment)) {
- this.alignment = Element.ALIGN_CENTER;
- return;
- }
- if (ElementTags.ALIGN_RIGHT.equalsIgnoreCase(alignment)) {
- this.alignment = Element.ALIGN_RIGHT;
- return;
- }
- if (ElementTags.ALIGN_JUSTIFIED.equalsIgnoreCase(alignment)) {
- this.alignment = Element.ALIGN_JUSTIFIED;
- return;
- }
- if (ElementTags.ALIGN_JUSTIFIED_ALL.equalsIgnoreCase(alignment)) {
- this.alignment = Element.ALIGN_JUSTIFIED_ALL;
- return;
- }
- this.alignment = Element.ALIGN_LEFT;
- }
-
-/**
- * Sets the indentation of this paragraph on the left side.
- *
- * @param indentation the new indentation
- */
-
- public void setIndentationLeft(float indentation) {
- this.indentationLeft = indentation;
- }
-
-/**
- * Sets the indentation of this paragraph on the right side.
- *
- * @param indentation the new indentation
- */
-
- public void setIndentationRight(float indentation) {
- this.indentationRight = indentation;
- }
-
-/**
- * Sets the spacing before this paragraph.
- *
- * @param spacing the new spacing
- */
-
- public void setSpacingBefore(float spacing) {
- this.spacingBefore = spacing;
- }
-
-/**
- * Sets the spacing after this paragraph.
- *
- * @param spacing the new spacing
- */
-
- public void setSpacingAfter(float spacing) {
- this.spacingAfter = spacing;
- }
-
-/**
- * Indicates that the paragraph has to be kept together on one page.
- *
- * @param keeptogether true of the paragraph may not be split over 2 pages
- */
-
- public void setKeepTogether(boolean keeptogether) {
- this.keeptogether = keeptogether;
- }
-
-/**
- * Checks if this paragraph has to be kept together on one page.
- *
- * @return true if the paragraph may not be split over 2 pages.
- */
-
- public boolean getKeepTogether() {
- return keeptogether;
- }
-
- // methods to retrieve information
-
-/**
- * Gets the alignment of this paragraph.
- *
- * @return alignment
- */
-
- public int alignment() {
- return alignment;
- }
-
-/**
- * Gets the indentation of this paragraph on the left side.
- *
- * @return the indentation
- */
-
- public float indentationLeft() {
- return indentationLeft;
- }
-
-/**
- * Gets the indentation of this paragraph on the right side.
- *
- * @return the indentation
- */
-
- public float indentationRight() {
- return indentationRight;
- }
-
-/**
- * Gets the spacing before this paragraph.
- *
- * @return the spacing
- */
-
- public float spacingBefore() {
- return spacingBefore;
- }
-
-/**
- * Gets the spacing before this paragraph.
- *
- * @return the spacing
- */
-
- public float spacingAfter() {
- return spacingAfter;
- }
-
-/**
- * Checks if a given tag corresponds with this object.
- *
- * @param tag the given tag
- * @return true if the tag corresponds
- */
-
- public static boolean isTag(String tag) {
- return ElementTags.PARAGRAPH.equals(tag);
- }
-
- /**
- * Sets the leading fixed and variable. The resultant leading will be
- * fixedLeading+multipliedLeading*maxFontSize where maxFontSize is the
- * size of the bigest font in the line.
- * @param fixedLeading the fixed leading
- * @param multipliedLeading the variable leading
- */
- public void setLeading(float fixedLeading, float multipliedLeading) {
- this.leading = fixedLeading;
- this.multipliedLeading = multipliedLeading;
- }
-
- /**
- * @see com.lowagie.text.Phrase#setLeading(float)
- */
- public void setLeading(float fixedLeading) {
- this.leading = fixedLeading;
- this.multipliedLeading = 0;
- }
-
- /**
- * Gets the variable leading
- * @return the leading
- */
- public float getMultipliedLeading() {
- return multipliedLeading;
- }
-
- /**
- * Getter for property firstLineIndent.
- * @return Value of property firstLineIndent.
- */
- public float getFirstLineIndent() {
- return this.firstLineIndent;
- }
-
- /**
- * Setter for property firstLineIndent.
- * @param firstLineIndent New value of property firstLineIndent.
- */
- public void setFirstLineIndent(float firstLineIndent) {
- this.firstLineIndent = firstLineIndent;
- }
-
- /**
- * Getter for property extraParagraphSpace.
- * @return Value of property extraParagraphSpace.
- */
- public float getExtraParagraphSpace() {
- return this.extraParagraphSpace;
- }
-
- /**
- * Setter for property extraParagraphSpace.
- * @param extraParagraphSpace New value of property extraParagraphSpace.
- */
- public void setExtraParagraphSpace(float extraParagraphSpace) {
- this.extraParagraphSpace = extraParagraphSpace;
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/Phrase.java pdftk-2.01/java/com/lowagie/text/Phrase.java
--- pdftk-1.45/java/com/lowagie/text/Phrase.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Phrase.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,610 +0,0 @@
-/*
- * $Id: Phrase.java,v 1.104 2005/09/05 08:04:55 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Properties;
-import java.util.Set;
-
-import com.lowagie.text.markup.MarkupTags;
-import com.lowagie.text.markup.MarkupParser;
-
-/**
- * A Phrase
is a series of Chunk
s.
- *
- * A Phrase
has a main Font
, but some chunks
- * within the phrase can have a Font
that differs from the
- * main Font
. All the Chunk
s in a Phrase
- * have the same leading
.
- *
- * Example:
- *
- * // When no parameters are passed, the default leading = 16
- * Phrase phrase0 = new Phrase();
- * Phrase phrase1 = new Phrase("this is a phrase");
- * // In this example the leading is passed as a parameter
- * Phrase phrase2 = new Phrase(16, "this is a phrase with leading 16");
- * // When a Font is passed (explicitely or embedded in a chunk), the default leading = 1.5 * size of the font
- * Phrase phrase3 = new Phrase("this is a phrase with a red, normal font Courier, size 12", FontFactory.getFont(FontFactory.COURIER, 12, Font.NORMAL, new Color(255, 0, 0)));
- * Phrase phrase4 = new Phrase(new Chunk("this is a phrase"));
- * Phrase phrase5 = new Phrase(18, new Chunk("this is a phrase", FontFactory.getFont(FontFactory.HELVETICA, 16, Font.BOLD, new Color(255, 0, 0)));
- *
- *
- * @see Element
- * @see Chunk
- * @see Paragraph
- * @see Anchor
- */
-
-public class Phrase extends ArrayList implements TextElementArray, MarkupAttributes {
-
- // membervariables
-
-/** This is the leading of this phrase. */
- protected float leading = Float.NaN;
-
-/** This is the font of this phrase. */
- protected Font font = new Font();
-
-/** Contains extra markupAttributes */
- protected Properties markupAttributes;
-
- // constructors
-
-/**
- * Constructs a Phrase that can be used in the static getInstance() method.
- * @param dummy a dummy parameter
- */
- private Phrase(boolean dummy) {
- }
-
-/**
- * Constructs a Phrase
without specifying a leading.
- */
-
- public Phrase() {
- this(16);
- }
-
-/**
- * Constructs a Phrase
with a certain leading.
- *
- * @param leading the leading
- */
-
- public Phrase(float leading) {
- this.leading = leading;
- }
-
-/**
- * Constructs a Phrase
with a certain Chunk
.
- *
- * @param chunk a Chunk
- */
-
- public Phrase(Chunk chunk) {
- super.add(chunk);
- }
-
-/**
- * Constructs a Phrase
with a certain Chunk
- * and a certain leading.
- *
- * @param leading the leading
- * @param chunk a Chunk
- */
-
- public Phrase(float leading, Chunk chunk) {
- this(leading);
- super.add(chunk);
- }
-
-/**
- * Constructs a Phrase
with a certain String
.
- *
- * @param string a String
- */
-
- public Phrase(String string) {
- this(Float.NaN, string, new Font());
- }
-
-/**
- * Constructs a Phrase
with a certain String
and a certain Font
.
- *
- * @param string a String
- * @param font a Font
- */
-
- public Phrase(String string, Font font) {
- this(Float.NaN, string, font);
- this.font = font;
- }
-
-/**
- * Constructs a Phrase
with a certain leading and a certain String
.
- *
- * @param leading the leading
- * @param string a String
- */
-
- public Phrase(float leading, String string) {
- this(leading, string, new Font());
- }
-
-/**
- * Constructs a Phrase
with a certain leading, a certain String
- * and a certain Font
.
- *
- * @param leading the leading
- * @param string a String
- * @param font a Font
- */
-
- public Phrase(float leading, String string, Font font) {
- this(leading);
- this.font = font;
- /* bugfix by August Detlefsen */
- if (string != null && string.length() != 0) {
- super.add(new Chunk(string, font));
- }
- }
-
- /**
- * Gets a special kind of Phrase that changes some characters into corresponding symbols.
- * @param string
- * @return a newly constructed Phrase
- */
- public static final Phrase getInstance(String string) {
- return getInstance(16, string, new Font());
- }
-
- /**
- * Gets a special kind of Phrase that changes some characters into corresponding symbols.
- * @param leading
- * @param string
- * @return a newly constructed Phrase
- */
- public static final Phrase getInstance(int leading, String string) {
- return getInstance(leading, string, new Font());
- }
-
- /**
- * Gets a special kind of Phrase that changes some characters into corresponding symbols.
- * @param leading
- * @param string
- * @param font
- * @return a newly constructed Phrase
- */
- public static final Phrase getInstance(int leading, String string, Font font) {
- Phrase p = new Phrase(true);
- p.setLeading(leading);
- p.font = font;
- if (font.family() != Font.SYMBOL && font.family() != Font.ZAPFDINGBATS && font.getBaseFont() == null) {
- int index;
- while((index = SpecialSymbol.index(string)) > -1) {
- if (index > 0) {
- String firstPart = string.substring(0, index);
- /* bugfix [ #461272 ] CODE CHANGE REQUIRED IN Phrase.java
- by Arekh Nambiar */
- ((ArrayList)p).add(new Chunk(firstPart, font));
- string = string.substring(index);
- }
- Font symbol = new Font(Font.SYMBOL, font.size(), font.style(), font.color());
- StringBuffer buf = new StringBuffer();
- buf.append(SpecialSymbol.getCorrespondingSymbol(string.charAt(0)));
- string = string.substring(1);
- while (SpecialSymbol.index(string) == 0) {
- buf.append(SpecialSymbol.getCorrespondingSymbol(string.charAt(0)));
- string = string.substring(1);
- }
- ((ArrayList)p).add(new Chunk(buf.toString(), symbol));
- }
- }
- /* bugfix by August Detlefsen */
- if (string != null && string.length() != 0) {
- ((ArrayList)p).add(new Chunk(string, font));
- }
- return p;
- }
-
-/**
- * Returns a Phrase
that has been constructed taking in account
- * the value of some attributes .
- *
- * @param attributes Some attributes
- */
-
- public Phrase(Properties attributes) {
- this("", FontFactory.getFont(attributes));
- clear();
- String value;
- if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
- setLeading(Float.valueOf(value + "f").floatValue());
- }
- else if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_LINEHEIGHT)) != null) {
- setLeading(MarkupParser.parseLength(value));
- }
- if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
- Chunk chunk = new Chunk(value);
- if ((value = (String)attributes.remove(ElementTags.GENERICTAG)) != null) {
- chunk.setGenericTag(value);
- }
- add(chunk);
- }
- if (attributes.size() > 0) setMarkupAttributes(attributes);
- }
-
- // implementation of the Element-methods
-
-/**
- * Processes the element by adding it (or the different parts) to an
- * ElementListener
.
- *
- * @param listener an ElementListener
- * @return true
if the element was processed successfully
- */
-
- public boolean process(ElementListener listener) {
- try {
- for (Iterator i = iterator(); i.hasNext(); ) {
- listener.add((Element) i.next());
- }
- return true;
- }
- catch(DocumentException de) {
- return false;
- }
- }
-
-/**
- * Gets the type of the text element.
- *
- * @return a type
- */
-
- public int type() {
- return Element.PHRASE;
- }
-
-/**
- * Gets all the chunks in this element.
- *
- * @return an ArrayList
- */
-
- public ArrayList getChunks() {
- ArrayList tmp = new ArrayList();
- for (Iterator i = iterator(); i.hasNext(); ) {
- tmp.addAll(((Element) i.next()).getChunks());
- }
- return tmp;
- }
-
- // overriding some of the ArrayList-methods
-
-/**
- * Adds a Chunk
, an Anchor
or another Phrase
- * to this Phrase
.
- *
- * @param index index at which the specified element is to be inserted
- * @param o an object of type Chunk
, Anchor
or Phrase
- * @throws ClassCastException when you try to add something that isn't a Chunk
, Anchor
or Phrase
- */
-
- public void add(int index, Object o) {
- if (o == null) return;
- try {
- Element element = (Element) o;
- if (element.type() == Element.CHUNK) {
- Chunk chunk = (Chunk) element;
- if (!font.isStandardFont()) {
- chunk.setFont(font.difference(chunk.font()));
- }
- super.add(index, chunk);
- }
- else if (element.type() == Element.PHRASE ||
- element.type() == Element.ANCHOR ||
- element.type() == Element.ANNOTATION ||
- element.type() == Element.TABLE || // line added by David Freels
- element.type() == Element.GRAPHIC) {
- super.add(index, element);
- }
- else {
- throw new ClassCastException(String.valueOf(element.type()));
- }
- }
- catch(ClassCastException cce) {
- throw new ClassCastException("Insertion of illegal Element: " + cce.getMessage());
- }
- }
-
-/**
- * Adds a Chunk
, Anchor
or another Phrase
- * to this Phrase
.
- *
- * @param o an object of type Chunk
, Anchor
or Phrase
- * @return a boolean
- * @throws ClassCastException when you try to add something that isn't a Chunk
, Anchor
or Phrase
- */
-
- public boolean add(Object o) {
- if (o == null) return false;
- if (o instanceof String) {
- return super.add(new Chunk((String) o, font));
- }
- try {
- Element element = (Element) o;
- switch(element.type()) {
- case Element.CHUNK:
- return addChunk((Chunk) o);
- case Element.PHRASE:
- case Element.PARAGRAPH:
- Phrase phrase = (Phrase) o;
- boolean success = true;
- Element e;
- for (Iterator i = phrase.iterator(); i.hasNext(); ) {
- e = (Element) i.next();
- if (e instanceof Chunk) {
- success &= addChunk((Chunk)e);
- }
- else {
- success &= this.add(e);
- }
- }
- return success;
- case Element.ANCHOR:
- return super.add(o);
- case Element.ANNOTATION:
- return super.add(o);
- /* ssteward: dropped in 1.44
- case Element.TABLE: // case added by David Freels
- return super.add((Table) o);
- case Element.PTABLE: // case added by mr. Karen Vardanyan
- // This will only work for PDF!!! Not for RTF/HTML
- return super.add((com.lowagie.text.pdf.PdfPTable) o);
- */
- case Element.LIST:
- return super.add(o);
- /*
- case Element.GRAPHIC: // suggested by Steven Balthazor
- return super.add((Graphic) o);
- */
- default:
- throw new ClassCastException(String.valueOf(element.type()));
- }
- }
- catch(ClassCastException cce) {
- throw new ClassCastException("Insertion of illegal Element: " + cce.getMessage());
- }
- }
-
-/**
- * Adds a Chunk.
- *
- * This method is a hack to solve a problem I had with phrases that were split between chunks
- * in the wrong place.
- * @param chunk a Chunk to add to the Phrase
- * @return true if adding the Chunk succeeded
- */
-
- private synchronized boolean addChunk(Chunk chunk) {
- if (!font.isStandardFont()) {
- chunk.setFont(font.difference(chunk.font()));
- }
- if (size() > 0 && !chunk.hasAttributes()) {
- try {
- Chunk previous = (Chunk) get(size() - 1);
- if (!previous.hasAttributes() && previous.font().compareTo(chunk.font()) == 0 && !"".equals(previous.content().trim()) && !"".equals(chunk.content().trim())) {
- previous.append(chunk.content());
- return true;
- }
- }
- catch(ClassCastException cce) {
- }
- }
- return super.add(chunk);
- }
-
-/**
- * Adds a collection of Chunk
s
- * to this Phrase
.
- *
- * @param collection a collection of Chunk
s, Anchor
s and Phrase
s.
- * @return true
if the action succeeded, false
if not.
- * @throws ClassCastException when you try to add something that isn't a Chunk
, Anchor
or Phrase
- */
-
- public boolean addAll(Collection collection) {
- for (Iterator iterator = collection.iterator(); iterator.hasNext(); ) {
- this.add(iterator.next());
- }
- return true;
- }
-
-/**
- * Adds a Object
to the Paragraph
.
- *
- * @param object the object to add.
- */
-
- protected void addSpecial(Object object) {
- super.add(object);
- }
-
- // methods
-
-/**
- * Sets the leading of this phrase.
- *
- * @param leading the new leading
- */
-
- public void setLeading(float leading) {
- this.leading = leading;
- }
-
- // methods to retrieve information
-
-/**
- * Checks is this Phrase
contains no or 1 empty Chunk
.
- *
- * @return false
if the Phrase
- * contains more than one or more non-emptyChunk
s.
- */
-
- public boolean isEmpty() {
- switch(size()) {
- case 0:
- return true;
- case 1:
- Element element = (Element) get(0);
- if (element.type() == Element.CHUNK && ((Chunk) element).isEmpty()) {
- return true;
- }
- return false;
- default:
- return false;
- }
- }
-
-/**
- * Checks you if the leading of this phrase is defined.
- *
- * @return true if the leading is defined
- */
-
- public boolean leadingDefined() {
- if (Float.isNaN(leading)) {
- return false;
- }
- return true;
- }
-
-/**
- * Gets the leading of this phrase.
- *
- * @return the linespacing
- */
-
- public float leading() {
- if (Float.isNaN(leading)) {
- return font.leading(1.5f);
- }
- return leading;
- }
-
-/**
- * Gets the font of the first Chunk
that appears in this Phrase
.
- *
- * @return a Font
- */
-
- public Font font() {
- return font;
- }
-
-/**
- * Checks if a given tag corresponds with this object.
- *
- * @param tag the given tag
- * @return true if the tag corresponds
- */
-
- public static boolean isTag(String tag) {
- return ElementTags.PHRASE.equals(tag);
- }
-
-
-/**
- * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String, java.lang.String)
- */
- public void setMarkupAttribute(String name, String value) {
- if (markupAttributes == null) markupAttributes = new Properties();
- markupAttributes.put(name, value);
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
- */
- public void setMarkupAttributes(Properties markupAttributes) {
- this.markupAttributes = markupAttributes;
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
- */
- public String getMarkupAttribute(String name) {
- return (markupAttributes == null) ? null : String.valueOf(markupAttributes.get(name));
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
- */
- public Set getMarkupAttributeNames() {
- return Chunk.getKeySet(markupAttributes);
- }
-
-/**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
- */
- public Properties getMarkupAttributes() {
- return markupAttributes;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/Rectangle.java pdftk-2.01/java/com/lowagie/text/Rectangle.java
--- pdftk-1.45/java/com/lowagie/text/Rectangle.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/Rectangle.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,960 +0,0 @@
-/*
- * $Id: Rectangle.java,v 1.70 2005/08/09 14:07:29 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.Properties;
-import java.util.Set;
-
-/**
- * A Rectangle
is the representation of a geometric figure.
- *
- * Rectangles support constant width borders using
- * {@link #setBorderWidth(float)}and {@link #setBorder(int)}. They also
- * support borders that vary in width/color on each side using methods like
- * {@link #setBorderWidthLeft(float)}or
- * {@link #setBorderColorLeft(java.awt.Color)}.
- *
- * @see Element
- * @see Table
- * @see Cell
- * @see HeaderFooter
- */
-
-public class Rectangle implements Element, MarkupAttributes {
-
- // static membervariables (concerning the presence of borders)
-
- /** This is the value that will be used as undefined . */
- public static final int UNDEFINED = -1;
-
- /** This represents one side of the border of the Rectangle
. */
- public static final int TOP = 1;
-
- /** This represents one side of the border of the Rectangle
. */
- public static final int BOTTOM = 2;
-
- /** This represents one side of the border of the Rectangle
. */
- public static final int LEFT = 4;
-
- /** This represents one side of the border of the Rectangle
. */
- public static final int RIGHT = 8;
-
- /** This represents a rectangle without borders. */
- public static final int NO_BORDER = 0;
-
- /** This represents a type of border. */
- public static final int BOX = TOP + BOTTOM + LEFT + RIGHT;
-
- // membervariables
-
- /** the lower left x-coordinate. */
- protected float llx;
-
- /** the lower left y-coordinate. */
- protected float lly;
-
- /** the upper right x-coordinate. */
- protected float urx;
-
- /** the upper right y-coordinate. */
- protected float ury;
-
- /** This represents the status of the 4 sides of the rectangle. */
- protected int border = UNDEFINED;
-
- /** This is the width of the border around this rectangle. */
- protected float borderWidth = UNDEFINED;
-
- /** The color of the border of this rectangle. */
- protected Color color = null;
-
- /** The color of the left border of this rectangle. */
- protected Color borderColorLeft = null;
-
- /** The color of the right border of this rectangle. */
- protected Color borderColorRight = null;
-
- /** The color of the top border of this rectangle. */
- protected Color borderColorTop = null;
-
- /** The color of the bottom border of this rectangle. */
- protected Color borderColorBottom = null;
-
- /** The width of the left border of this rectangle. */
- protected float borderWidthLeft = UNDEFINED;
-
- /** The width of the right border of this rectangle. */
- protected float borderWidthRight = UNDEFINED;
-
- /** The width of the top border of this rectangle. */
- protected float borderWidthTop = UNDEFINED;
-
- /** The width of the bottom border of this rectangle. */
- protected float borderWidthBottom = UNDEFINED;
-
- /** Whether variable width borders are used. */
- protected boolean useVariableBorders = false;
-
- /** This is the color of the background of this rectangle. */
- protected Color background = null;
-
- /** This is the grayscale value of the background of this rectangle. */
- protected float grayFill = 0;
-
- protected int rotation = 0;
-
- /** Contains extra markupAttributes */
- protected Properties markupAttributes;
-
- // constructors
-
- /**
- * Constructs a Rectangle
-object.
- *
- * @param llx
- * lower left x
- * @param lly
- * lower left y
- * @param urx
- * upper right x
- * @param ury
- * upper right y
- */
-
- public Rectangle(float llx, float lly, float urx, float ury) {
- this.llx = llx;
- this.lly = lly;
- this.urx = urx;
- this.ury = ury;
- }
-
- /**
- * Constructs a Rectangle
-object starting from the origin
- * (0, 0).
- *
- * @param urx
- * upper right x
- * @param ury
- * upper right y
- */
-
- public Rectangle(float urx, float ury) {
- this(0, 0, urx, ury);
- }
-
- /**
- * Constructs a Rectangle
-object.
- *
- * @param rect
- * another Rectangle
- */
-
- public Rectangle(Rectangle rect) {
- this(rect.llx, rect.lly, rect.urx, rect.ury);
- cloneNonPositionParameters(rect);
- }
-
- /**
- * Copies all of the parameters from a Rectangle
object
- * except the position.
- *
- * @param rect
- * Rectangle
to copy from
- */
-
- public void cloneNonPositionParameters(Rectangle rect) {
- this.rotation = rect.rotation;
- this.border = rect.border;
- this.borderWidth = rect.borderWidth;
- this.color = rect.color;
- this.background = rect.background;
- this.grayFill = rect.grayFill;
- this.borderColorLeft = rect.borderColorLeft;
- this.borderColorRight = rect.borderColorRight;
- this.borderColorTop = rect.borderColorTop;
- this.borderColorBottom = rect.borderColorBottom;
- this.borderWidthLeft = rect.borderWidthLeft;
- this.borderWidthRight = rect.borderWidthRight;
- this.borderWidthTop = rect.borderWidthTop;
- this.borderWidthBottom = rect.borderWidthBottom;
- this.useVariableBorders = rect.useVariableBorders;
- }
-
- /**
- * Copies all of the parameters from a Rectangle
object
- * except the position.
- *
- * @param rect
- * Rectangle
to copy from
- */
-
- public void softCloneNonPositionParameters(Rectangle rect) {
- if (rect.rotation != 0)
- this.rotation = rect.rotation;
- if (rect.border != UNDEFINED)
- this.border = rect.border;
- if (rect.borderWidth != UNDEFINED)
- this.borderWidth = rect.borderWidth;
- if (rect.color != null)
- this.color = rect.color;
- if (rect.background != null)
- this.background = rect.background;
- if (rect.grayFill != 0)
- this.grayFill = rect.grayFill;
- if (rect.borderColorLeft != null)
- this.borderColorLeft = rect.borderColorLeft;
- if (rect.borderColorRight != null)
- this.borderColorRight = rect.borderColorRight;
- if (rect.borderColorTop != null)
- this.borderColorTop = rect.borderColorTop;
- if (rect.borderColorBottom != null)
- this.borderColorBottom = rect.borderColorBottom;
- if (rect.borderWidthLeft != UNDEFINED)
- this.borderWidthLeft = rect.borderWidthLeft;
- if (rect.borderWidthRight != UNDEFINED)
- this.borderWidthRight = rect.borderWidthRight;
- if (rect.borderWidthTop != UNDEFINED)
- this.borderWidthTop = rect.borderWidthTop;
- if (rect.borderWidthBottom != UNDEFINED)
- this.borderWidthBottom = rect.borderWidthBottom;
- if (useVariableBorders)
- this.useVariableBorders = rect.useVariableBorders;
- }
-
- // implementation of the Element interface
-
- /**
- * Processes the element by adding it (or the different parts) to an
- * ElementListener
.
- *
- * @param listener
- * an ElementListener
- * @return true
if the element was processed successfully
- */
-
- public boolean process(ElementListener listener) {
- try {
- return listener.add(this);
- } catch (DocumentException de) {
- return false;
- }
- }
-
- /**
- * Gets the type of the text element.
- *
- * @return a type
- */
-
- public int type() {
- return Element.RECTANGLE;
- }
-
- /**
- * Gets all the chunks in this element.
- *
- * @return an ArrayList
- */
- public ArrayList getChunks() {
- return new ArrayList();
- }
-
- // methods
-
- /**
- * Switches lowerleft with upperright
- */
- public void normalize() {
- if (llx > urx) {
- float a = llx;
- llx = urx;
- urx = a;
- }
- if (lly > ury) {
- float a = lly;
- lly = ury;
- ury = a;
- }
- }
-
- /**
- * Gets a Rectangle that is altered to fit on the page.
- *
- * @param top
- * the top position
- * @param bottom
- * the bottom position
- * @return a Rectangle
- */
-
- public Rectangle rectangle(float top, float bottom) {
- Rectangle tmp = new Rectangle(this);
- if (top() > top) {
- tmp.setTop(top);
- tmp.setBorder(border - (border & TOP));
- }
- if (bottom() < bottom) {
- tmp.setBottom(bottom);
- tmp.setBorder(border - (border & BOTTOM));
- }
- return tmp;
- }
-
- /**
- * Swaps the values of urx and ury and of lly and llx in order to rotate the
- * rectangle.
- *
- * @return a Rectangle
- */
-
- public Rectangle rotate() {
- Rectangle rect = new Rectangle(lly, llx, ury, urx);
- rect.rotation = rotation + 90;
- rect.rotation %= 360;
- return rect;
- }
-
- // methods to set the membervariables
-
- /**
- * Sets the lower left x-coordinate.
- *
- * @param value
- * the new value
- */
-
- public void setLeft(float value) {
- llx = value;
- }
-
- /**
- * Sets the upper right x-coordinate.
- *
- * @param value
- * the new value
- */
-
- public void setRight(float value) {
- urx = value;
- }
-
- /**
- * Sets the upper right y-coordinate.
- *
- * @param value
- * the new value
- */
-
- public void setTop(float value) {
- ury = value;
- }
-
- /**
- * Sets the lower left y-coordinate.
- *
- * @param value
- * the new value
- */
-
- public void setBottom(float value) {
- lly = value;
- }
-
- /**
- * Enables/Disables the border on the specified sides. The border is
- * specified as an integer bitwise combination of the constants:
- * LEFT, RIGHT, TOP, BOTTOM
.
- *
- * @see #enableBorderSide(int)
- * @see #disableBorderSide(int)
- * @param value
- * the new value
- */
-
- public void setBorder(int value) {
- border = value;
- }
-
- /**
- * Enables the border on the specified side.
- *
- * @param side
- * the side to enable. One of LEFT, RIGHT, TOP, BOTTOM
- *
- */
- public void enableBorderSide(int side) {
- if (border == UNDEFINED) {
- border = 0;
- }
- border |= side;
- }
-
- /**
- * Disables the border on the specified side.
- *
- * @param side
- * the side to disable. One of LEFT, RIGHT, TOP, BOTTOM
- *
- */
- public void disableBorderSide(int side) {
- if (border == UNDEFINED) {
- border = 0;
- }
- border &= ~side;
- }
-
- /**
- * Sets the borderwidth of the table.
- *
- * @param value
- * the new value
- */
-
- public void setBorderWidth(float value) {
- borderWidth = value;
- }
-
- /**
- * Sets the color of the border.
- *
- * @param value
- * the new value
- */
-
- public void setBorderColor(Color value) {
- color = value;
- }
-
- /**
- * Sets the value of the border color
- *
- * @param value
- * a color value
- */
- public void setBorderColorRight(Color value) {
- borderColorRight = value;
- }
-
- /**
- * Sets the value of the border color
- *
- * @param value
- * a color value
- */
- public void setBorderColorLeft(Color value) {
- borderColorLeft = value;
- }
-
- /**
- * Sets the value of the border color
- *
- * @param value
- * a color value
- */
- public void setBorderColorTop(Color value) {
- borderColorTop = value;
- }
-
- /**
- * Sets the value of the border color
- *
- * @param value
- * a color value
- */
- public void setBorderColorBottom(Color value) {
- borderColorBottom = value;
- }
-
- /**
- * Sets the backgroundcolor of the rectangle.
- *
- * @param value
- * the new value
- */
-
- public void setBackgroundColor(Color value) {
- background = value;
- }
-
- /**
- * Sets the grayscale of the rectangle.
- *
- * @param value
- * the new value
- */
-
- public void setGrayFill(float value) {
- if (value >= 0 && value <= 1.0) {
- grayFill = value;
- }
- }
-
- // methods to get the membervariables
-
- /**
- * Returns the lower left x-coordinate.
- *
- * @return the lower left x-coordinate
- */
-
- public float left() {
- return llx;
- }
-
- /**
- * Returns the upper right x-coordinate.
- *
- * @return the upper right x-coordinate
- */
-
- public float right() {
- return urx;
- }
-
- /**
- * Returns the upper right y-coordinate.
- *
- * @return the upper right y-coordinate
- */
-
- public float top() {
- return ury;
- }
-
- /**
- * Returns the lower left y-coordinate.
- *
- * @return the lower left y-coordinate
- */
-
- public float bottom() {
- return lly;
- }
-
- /**
- * Returns the lower left x-coordinate, considering a given margin.
- *
- * @param margin
- * a margin
- * @return the lower left x-coordinate
- */
-
- public float left(float margin) {
- return llx + margin;
- }
-
- /**
- * Returns the upper right x-coordinate, considering a given margin.
- *
- * @param margin
- * a margin
- * @return the upper right x-coordinate
- */
-
- public float right(float margin) {
- return urx - margin;
- }
-
- /**
- * Returns the upper right y-coordinate, considering a given margin.
- *
- * @param margin
- * a margin
- * @return the upper right y-coordinate
- */
-
- public float top(float margin) {
- return ury - margin;
- }
-
- /**
- * Returns the lower left y-coordinate, considering a given margin.
- *
- * @param margin
- * a margin
- * @return the lower left y-coordinate
- */
-
- public float bottom(float margin) {
- return lly + margin;
- }
-
- /**
- * Returns the width of the rectangle.
- *
- * @return a width
- */
-
- public float width() {
- return urx - llx;
- }
-
- /**
- * Returns the height of the rectangle.
- *
- * @return a height
- */
-
- public float height() {
- return ury - lly;
- }
-
- /**
- * Indicates if the table has borders.
- *
- * @return a boolean
- */
-
- public boolean hasBorders() {
- return (border > 0)
- && ((borderWidth > 0) || (borderWidthLeft > 0)
- || (borderWidthRight > 0) || (borderWidthTop > 0) || (borderWidthBottom > 0));
- }
-
- /**
- * Indicates if the table has a some type of border.
- *
- * @param type
- * the type of border
- * @return a boolean
- */
-
- public boolean hasBorder(int type) {
- return border != UNDEFINED && (border & type) == type;
- }
-
- /**
- * Returns the exact type of the border.
- *
- * @return a value
- */
-
- public int border() {
- return border;
- }
-
- /**
- * Gets the borderwidth.
- *
- * @return a value
- */
-
- public float borderWidth() {
- return borderWidth;
- }
-
- /**
- * Gets the color of the border.
- *
- * @return a value
- */
-
- public Color borderColor() {
- return color;
- }
-
- /**
- * Gets the backgroundcolor.
- *
- * @return a value
- */
-
- public Color backgroundColor() {
- return background;
- }
-
- /**
- * Gets the grayscale.
- *
- * @return a value
- */
-
- public float grayFill() {
- return grayFill;
- }
-
- /**
- * Gets the rotation of the rectangle
- *
- * @return a rotation value
- */
- public int getRotation() {
- return rotation;
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String,
- * java.lang.String)
- */
- public void setMarkupAttribute(String name, String value) {
- if (markupAttributes == null)
- markupAttributes = new Properties();
- markupAttributes.put(name, value);
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
- */
- public void setMarkupAttributes(Properties markupAttributes) {
- this.markupAttributes = markupAttributes;
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
- */
- public String getMarkupAttribute(String name) {
- return (markupAttributes == null) ? null : String
- .valueOf(markupAttributes.get(name));
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
- */
- public Set getMarkupAttributeNames() {
- return Chunk.getKeySet(markupAttributes);
- }
-
- /**
- * @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
- */
- public Properties getMarkupAttributes() {
- return markupAttributes;
- }
-
- /**
- * Gets the color of a border.
- *
- * @return a color value
- */
- public Color getBorderColorLeft() {
- return borderColorLeft;
- }
-
- /**
- * Gets the color of a border.
- *
- * @return a color value
- */
- public Color getBorderColorRight() {
- return borderColorRight;
- }
-
- /**
- * Gets the color of a border.
- *
- * @return a color value
- */
- public Color getBorderColorTop() {
- return borderColorTop;
- }
-
- /**
- * Gets the color of a border.
- *
- * @return a color value
- */
- public Color getBorderColorBottom() {
- return borderColorBottom;
- }
-
- /**
- * Gets the width of a border.
- *
- * @return a width
- */
- public float getBorderWidthLeft() {
- return getVariableBorderWidth(borderWidthLeft, LEFT);
- }
-
- /**
- * Sets the width of a border
- *
- * @param borderWidthLeft
- * a width
- */
- public void setBorderWidthLeft(float borderWidthLeft) {
- this.borderWidthLeft = borderWidthLeft;
- updateBorderBasedOnWidth(borderWidthLeft, LEFT);
- }
-
- /**
- * Gets the width of a border.
- *
- * @return a width
- */
- public float getBorderWidthRight() {
- return getVariableBorderWidth(borderWidthRight, RIGHT);
- }
-
- /**
- * Sets the width of a border
- *
- * @param borderWidthRight
- * a width
- */
- public void setBorderWidthRight(float borderWidthRight) {
- this.borderWidthRight = borderWidthRight;
- updateBorderBasedOnWidth(borderWidthRight, RIGHT);
- }
-
- /**
- * Gets the width of a border.
- *
- * @return a width
- */
- public float getBorderWidthTop() {
- return getVariableBorderWidth(borderWidthTop, TOP);
- }
-
- /**
- * Sets the width of a border
- *
- * @param borderWidthTop
- * a width
- */
- public void setBorderWidthTop(float borderWidthTop) {
- this.borderWidthTop = borderWidthTop;
- updateBorderBasedOnWidth(borderWidthTop, TOP);
- }
-
- /**
- * Gets the width of a border.
- *
- * @return a width
- */
- public float getBorderWidthBottom() {
- return getVariableBorderWidth(borderWidthBottom, BOTTOM);
- }
-
- /**
- * Sets the width of a border
- *
- * @param borderWidthBottom
- * a width
- */
- public void setBorderWidthBottom(float borderWidthBottom) {
- this.borderWidthBottom = borderWidthBottom;
- updateBorderBasedOnWidth(borderWidthBottom, BOTTOM);
- }
-
- /**
- * Updates the border flag for a side based on the specified width. A width
- * of 0 will disable the border on that side. Any other width enables it.
- *
- * @param width
- * width of border
- * @param side
- * border side constant
- */
-
- private void updateBorderBasedOnWidth(float width, int side) {
- useVariableBorders = true;
- if (width > 0) {
- enableBorderSide(side);
- } else {
- disableBorderSide(side);
- }
- }
-
- private float getVariableBorderWidth(float variableWidthValue, int side) {
- if ((border & side) != 0) {
- return variableWidthValue != UNDEFINED ? variableWidthValue
- : borderWidth;
- } else {
- return 0;
- }
- }
-
- /**
- * Indicates whether variable width borders are being used. Returns true if
- * setBorderWidthLeft, setBorderWidthRight, setBorderWidthTop, or
- * setBorderWidthBottom
has been called.
- *
- * @return true if variable width borders are in use
- *
- */
- public boolean isUseVariableBorders() {
- return useVariableBorders;
- }
-
- /**
- * Sets a parameter indicating if the rectangle has variable borders
- *
- * @param useVariableBorders
- * indication if the rectangle has variable borders
- */
- public void setUseVariableBorders(boolean useVariableBorders) {
- this.useVariableBorders = useVariableBorders;
- }
-
- /**
- * @see java.lang.Object#toString()
- */
- public String toString() {
- StringBuffer buf = new StringBuffer("Rectangle: ");
- buf.append(width());
- buf.append("x");
- buf.append(height());
- buf.append(" (rot: ");
- buf.append(rotation);
- buf.append(" degrees)");
- return buf.toString();
- }
-
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/SpecialSymbol.java pdftk-2.01/java/com/lowagie/text/SpecialSymbol.java
--- pdftk-1.45/java/com/lowagie/text/SpecialSymbol.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/SpecialSymbol.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,220 +0,0 @@
-/*
- * $Id: SpecialSymbol.java,v 1.1 2004/12/23 09:14:47 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-/**
- * This class contains the symbols that correspond with special symbols.
- *
- * When you construct a Phrase
with Phrase.getInstance using a String
,
- * this String
can contain special Symbols. These are characters with an int value
- * between 913 and 937 (except 930) and between 945 and 969. With this class the value of the
- * corresponding character of the Font Symbol, can be retrieved.
- *
- * @see Phrase
- *
- * @author Bruno Lowagie
- * @author Evelyne De Cordier
- */
-
-public class SpecialSymbol {
-
-/**
- * Returns the first occurrence of a special symbol in a String
.
- *
- * @param string a String
- * @return an index of -1 if no special symbol was found
- */
-
- public static int index(String string) {
- int length = string.length();
- for (int i = 0; i < length; i++) {
- if (getCorrespondingSymbol(string.charAt(i)) != ' ') {
- return i;
- }
- }
- return -1;
- }
-
-/**
- * Gets a chunk with a symbol character.
- * @param c a character that has to be changed into a symbol
- * @param font Font if there is no SYMBOL character corresponding with c
- * @return a SYMBOL version of a character
- */
-
- public static Chunk get(char c, Font font) {
- char greek = SpecialSymbol.getCorrespondingSymbol(c);
- if (greek == ' ') {
- return new Chunk(String.valueOf(c), font);
- }
- Font symbol = new Font(Font.SYMBOL, font.size(), font.style(), font.color());
- String s = String.valueOf(greek);
- return new Chunk(s, symbol);
- }
-
-/**
- * Looks for the corresponding symbol in the font Symbol.
- *
- * @param c the original ASCII-char
- * @return the corresponding symbol in font Symbol
- */
-
- public static char getCorrespondingSymbol(char c) {
- switch(c) {
- case 913:
- return 'A'; // ALFA
- case 914:
- return 'B'; // BETA
- case 915:
- return 'G'; // GAMMA
- case 916:
- return 'D'; // DELTA
- case 917:
- return 'E'; // EPSILON
- case 918:
- return 'Z'; // ZETA
- case 919:
- return 'H'; // ETA
- case 920:
- return 'Q'; // THETA
- case 921:
- return 'I'; // IOTA
- case 922:
- return 'K'; // KAPPA
- case 923:
- return 'L'; // LAMBDA
- case 924:
- return 'M'; // MU
- case 925:
- return 'N'; // NU
- case 926:
- return 'X'; // XI
- case 927:
- return 'O'; // OMICRON
- case 928:
- return 'P'; // PI
- case 929:
- return 'R'; // RHO
- case 931:
- return 'S'; // SIGMA
- case 932:
- return 'T'; // TAU
- case 933:
- return 'U'; // UPSILON
- case 934:
- return 'J'; // PHI
- case 935:
- return 'C'; // CHI
- case 936:
- return 'Y'; // PSI
- case 937:
- return 'W'; // OMEGA
- case 945:
- return 'a'; // alfa
- case 946:
- return 'b'; // beta
- case 947:
- return 'g'; // gamma
- case 948:
- return 'd'; // delta
- case 949:
- return 'e'; // epsilon
- case 950:
- return 'z'; // zeta
- case 951:
- return 'h'; // eta
- case 952:
- return 'q'; // theta
- case 953:
- return 'i'; // iota
- case 954:
- return 'k'; // kappa
- case 955:
- return 'l'; // lambda
- case 956:
- return 'm'; // mu
- case 957:
- return 'n'; // nu
- case 958:
- return 'x'; // xi
- case 959:
- return 'o'; // omicron
- case 960:
- return 'p'; // pi
- case 961:
- return 'r'; // rho
- case 962:
- return 's'; // sigma
- case 963:
- return 's'; // sigma
- case 964:
- return 't'; // tau
- case 965:
- return 'u'; // upsilon
- case 966:
- return 'j'; // phi
- case 967:
- return 'c'; // chi
- case 968:
- return 'y'; // psi
- case 969:
- return 'w'; // omega
- default:
- return ' ';
- }
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/SplitCharacter.java pdftk-2.01/java/com/lowagie/text/SplitCharacter.java
--- pdftk-1.45/java/com/lowagie/text/SplitCharacter.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/SplitCharacter.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,104 +0,0 @@
-/*
- * $Id: SplitCharacter.java,v 1.12 2002/06/20 13:30:25 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import com.lowagie.text.pdf.PdfChunk;
-
-/** Interface for customizing the split character.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-
-public interface SplitCharacter {
-
- /**
- * Returns true
if the character can split a line. The splitting implementation
- * is free to look ahead or look behind characters to make a decision.
- *
- * The default implementation is:
- *
- *
- * public boolean isSplitCharacter(int start, int current, int end, char[] cc, PdfChunk[] ck) {
- * char c;
- * if (ck == null)
- * c = cc[current];
- * else
- * c = ck[Math.min(current, ck.length - 1)].getUnicodeEquivalent(cc[current]);
- * if (c <= ' ' || c == '-') {
- * return true;
- * }
- * if (c < 0x2e80)
- * return false;
- * return ((c >= 0x2e80 && c < 0xd7a0)
- * || (c >= 0xf900 && c < 0xfb00)
- * || (c >= 0xfe30 && c < 0xfe50)
- * || (c >= 0xff61 && c < 0xffa0));
- * }
- *
- * @param start the lower limit of cc
inclusive
- * @param current the pointer to the character in cc
- * @param end the upper limit of cc
exclusive
- * @param cc an array of characters at least end
sized
- * @param ck an array of PdfChunk
. The main use is to be able to call
- * {@link PdfChunk#getUnicodeEquivalent(char)}. It may be null
- * or shorter than end
. If null
no convertion takes place.
- * If shorter than end
the last element is used
- * @return true
if the character(s) can split a line
- */
-
- public boolean isSplitCharacter(int start, int current, int end, char cc[], PdfChunk ck[]);
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/StringCompare.java pdftk-2.01/java/com/lowagie/text/StringCompare.java
--- pdftk-1.45/java/com/lowagie/text/StringCompare.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/StringCompare.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,83 +0,0 @@
-/*
- * $Id: StringCompare.java,v 1.22 2002/07/09 10:41:40 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * Copyright (c) 2000 Volker Richert
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-import java.util.Comparator;
-
-/**
- * This class was used in the 1.1-version of iText (by Volker Richert).
- * Paulo Soares suggested I should add it to the original library, so
- * that in the future it would be easier to port it to the JDK1.1.x.
- */
-
-public class StringCompare implements Comparator {
-
-/**
- * Compares 2 objects.
- *
- * @param o1 a first object
- * @param o2 a second object
- * @return a value
- * @throws ClassCastException if the objects aren't Strings
- */
-
- public int compare(Object o1, Object o2) {
- return ((String)o1).compareTo((String)o2);
- }
-
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/TextElementArray.java pdftk-2.01/java/com/lowagie/text/TextElementArray.java
--- pdftk-1.45/java/com/lowagie/text/TextElementArray.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/TextElementArray.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,81 +0,0 @@
-/*
- * $Id: TextElementArray.java,v 1.27 2002/06/20 13:30:25 blowagie Exp $
- * $Name: $
- *
- * Copyright (c) 1999, 2000, 2001, 2002 Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text;
-
-/**
- * Interface for a text element to which other objects can be added.
- *
- * @see Phrase
- * @see Paragraph
- * @see Section
- * @see ListItem
- * @see Chapter
- * @see Anchor
- * @see Cell
- */
-
-public interface TextElementArray extends Element {
-
- /**
- * Adds an object to the TextElementArray
.
- *
- * @param o an object that has to be added
- * @return true
if the addition succeeded; false
otherwise
- */
-
- public boolean add(Object o);
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/markup/Makefile pdftk-2.01/java/com/lowagie/text/markup/Makefile
--- pdftk-1.45/java/com/lowagie/text/markup/Makefile 2010-09-15 09:42:12.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/markup/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-library= markup.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-all : $(library) $(headers)
-
-$(library) : $(objects)
- $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/com/lowagie/text/markup/MarkupParser.java pdftk-2.01/java/com/lowagie/text/markup/MarkupParser.java
--- pdftk-1.45/java/com/lowagie/text/markup/MarkupParser.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/markup/MarkupParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,749 +0,0 @@
-/*
- * $Id: MarkupParser.java,v 1.53 2005/05/09 08:40:41 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.markup;
-
-import java.awt.Color;
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.util.HashMap;
-import java.util.Properties;
-import java.util.StringTokenizer;
-
-import com.lowagie.text.Element;
-import com.lowagie.text.ExceptionConverter;
-import com.lowagie.text.Font;
-import com.lowagie.text.FontFactory;
-import com.lowagie.text.ListItem;
-import com.lowagie.text.Paragraph;
-import com.lowagie.text.Phrase;
-import com.lowagie.text.Rectangle;
-// import com.lowagie.text.SimpleCell; ssteward: dropped in 1.44
-// import com.lowagie.text.SimpleTable; ssteward: dropped in 1.44
-
-/**
- * This class is a HashMap that contains selectors (String) and styles (a
- * Properties object). Given a tag and its attributes (id/class), this class can
- * return an iText object with the according style.
- *
- * @author blowagie
- */
-public class MarkupParser extends HashMap {
- /**
- * HashMap with styles for each known combination of tag/id/class. The key
- * is a String-combination, the value a Properties object.
- */
- protected HashMap stylecache = new HashMap();
-
- /**
- * HashMap with fonts for each known combination of tag/id/class. The key is
- * the same String-combination used for the stylecache.
- */
- protected HashMap fontcache = new HashMap();
-
- // processing CSS
-
- /**
- * Creates new MarkupParser
- *
- * @param file
- * the path to a CSS file.
- */
- public MarkupParser(String file) {
- super();
- try {
- FileReader reader = new FileReader(file);
- BufferedReader br = new BufferedReader(reader);
- StringBuffer buf = new StringBuffer();
- String line;
- while ((line = br.readLine()) != null) {
- buf.append(line.trim());
- }
- String string = buf.toString();
- string = removeComment(string, "/*", "*/");
- StringTokenizer tokenizer = new StringTokenizer(string, "}");
- String tmp;
- int pos;
- String selector;
- String attributes;
- while (tokenizer.hasMoreTokens()) {
- tmp = tokenizer.nextToken();
- pos = tmp.indexOf("{");
- if (pos > 0) {
- selector = tmp.substring(0, pos).trim();
- attributes = tmp.substring(pos + 1).trim();
- if (attributes.endsWith("}"))
- attributes = attributes.substring(0, attributes
- .length() - 1);
- put(selector, parseAttributes(attributes));
- }
- }
- } catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Removes the comments sections of a String.
- *
- * @param string
- * the original String
- * @param startComment
- * the String that marks the start of a Comment section
- * @param endComment
- * the String that marks the end of a Comment section.
- * @return the String stripped of its comment section
- */
- public static String removeComment(String string, String startComment,
- String endComment) {
- StringBuffer result = new StringBuffer();
- int pos = 0;
- int end = endComment.length();
- int start = string.indexOf(startComment, pos);
- while (start > -1) {
- result.append(string.substring(pos, start));
- pos = string.indexOf(endComment, start) + end;
- start = string.indexOf(startComment, pos);
- }
- result.append(string.substring(pos));
- return result.toString();
- }
-
- /**
- * This method parses a String with attributes and returns a Properties
- * object.
- *
- * @param string
- * a String of this form: 'key1="value1"; key2="value2";...
- * keyN="valueN" '
- * @return a Properties object
- */
- public static Properties parseAttributes(String string) {
- Properties result = new Properties();
- if (string == null)
- return result;
- StringTokenizer keyValuePairs = new StringTokenizer(string, ";");
- StringTokenizer keyValuePair;
- String key;
- String value;
- while (keyValuePairs.hasMoreTokens()) {
- keyValuePair = new StringTokenizer(keyValuePairs.nextToken(), ":");
- if (keyValuePair.hasMoreTokens())
- key = keyValuePair.nextToken().trim();
- else
- continue;
- if (keyValuePair.hasMoreTokens())
- value = keyValuePair.nextToken().trim();
- else
- continue;
- if (value.startsWith("\""))
- value = value.substring(1);
- if (value.endsWith("\""))
- value = value.substring(0, value.length() - 1);
- result.setProperty(key, value);
- }
- return result;
- }
-
- // reading attributevalues
-
- /**
- * Parses a length.
- *
- * @param string
- * a length in the form of an optional + or -, followed by a
- * number and a unit.
- * @return a float
- */
-
- public static float parseLength(String string) {
- int pos = 0;
- int length = string.length();
- boolean ok = true;
- while (ok && pos < length) {
- switch (string.charAt(pos)) {
- case '+':
- case '-':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '.':
- pos++;
- break;
- default:
- ok = false;
- }
- }
- if (pos == 0)
- return 0f;
- if (pos == length)
- return Float.valueOf(string + "f").floatValue();
- float f = Float.valueOf(string.substring(0, pos) + "f").floatValue();
- string = string.substring(pos);
- // inches
- if (string.startsWith("in")) {
- return f * 72f;
- }
- // centimeters
- if (string.startsWith("cm")) {
- return (f / 2.54f) * 72f;
- }
- // millimeters
- if (string.startsWith("mm")) {
- return (f / 25.4f) * 72f;
- }
- // picas
- if (string.startsWith("pc")) {
- return f * 12f;
- }
- // default: we assume the length was measured in points
- return f;
- }
-
- /**
- * Converts a Color
into a HTML representation of this
- * Color
.
- *
- * @param color
- * the Color
that has to be converted.
- * @return the HTML representation of this Color
- */
-
- public static Color decodeColor(String color) {
- int red = 0;
- int green = 0;
- int blue = 0;
- try {
- red = Integer.parseInt(color.substring(1, 3), 16);
- green = Integer.parseInt(color.substring(3, 5), 16);
- blue = Integer.parseInt(color.substring(5), 16);
- } catch (Exception sioobe) {
- // empty on purpose
- }
- return new Color(red, green, blue);
- }
-
- // helper methods
-
- /**
- * Generates a key for an tag/id/class combination and adds the style
- * attributes to the stylecache.
- *
- * @param attributes
- * a Properties object with the tagname and the attributes of the
- * tag.
- * @return a key
- */
- private String getKey(Properties attributes) {
- String tag = attributes.getProperty(MarkupTags.ITEXT_TAG);
- String id = attributes.getProperty(MarkupTags.HTML_ATTR_CSS_ID);
- String cl = attributes.getProperty(MarkupTags.HTML_ATTR_CSS_CLASS);
- if (id == null) {
- id = "";
- } else {
- id = "#" + id;
- }
- if (cl == null) {
- cl = "";
- } else {
- cl = "." + cl;
- }
- String key = tag + id + cl;
- if (!stylecache.containsKey(key) && key.length() > 0) {
- Properties props = new Properties();
- Properties tagprops = (Properties) get(tag);
- Properties idprops = (Properties) get(id);
- Properties clprops = (Properties) get(cl);
- Properties tagidprops = (Properties) get(tag + id);
- Properties tagclprops = (Properties) get(tag + cl);
- if (tagprops != null)
- props.putAll(tagprops);
- if (idprops != null)
- props.putAll(idprops);
- if (clprops != null)
- props.putAll(clprops);
- if (tagidprops != null)
- props.putAll(tagidprops);
- if (tagclprops != null)
- props.putAll(tagclprops);
- stylecache.put(key, props);
- }
- return key;
- }
-
- // getting the objects based on the tag and its attributes
-
- /**
- * Returns pagebreak information.
- *
- * @param attributes
- * @return true if a page break is needed before the tag
- */
- public boolean getPageBreakBefore(Properties attributes) {
- String key = getKey(attributes);
- Properties styleattributes = (Properties) stylecache.get(key);
- if (styleattributes != null
- && MarkupTags.CSS_VALUE_ALWAYS.equals(styleattributes
- .getProperty(MarkupTags.CSS_KEY_PAGE_BREAK_BEFORE))) {
- return true;
- }
- return false;
- }
-
- /**
- * Returns pagebreak information.
- *
- * @param attributes
- * @return true if a page break is needed after the tag
- */
- public boolean getPageBreakAfter(Properties attributes) {
- String key = getKey(attributes);
- Properties styleattributes = (Properties) stylecache.get(key);
- if (styleattributes != null
- && MarkupTags.CSS_VALUE_ALWAYS.equals(styleattributes
- .getProperty(MarkupTags.CSS_KEY_PAGE_BREAK_AFTER))) {
- return true;
- }
- return false;
- }
-
- /**
- * Returns an object based on a tag and its attributes.
- *
- * @param attributes
- * a Properties object with the tagname and the attributes of the
- * tag.
- * @return an iText object
- */
- public Element getObject(Properties attributes) {
- String key = getKey(attributes);
- Properties styleattributes = (Properties) stylecache.get(key);
- if (styleattributes != null
- && MarkupTags.CSS_VALUE_HIDDEN.equals(styleattributes
- .get(MarkupTags.CSS_KEY_VISIBILITY))) {
- return null;
- }
- String display = styleattributes
- .getProperty(MarkupTags.CSS_KEY_DISPLAY);
- Element element = null;
- if (MarkupTags.CSS_VALUE_INLINE.equals(display)) {
- element = retrievePhrase(getFont(attributes), styleattributes);
- } else if (MarkupTags.CSS_VALUE_BLOCK.equals(display)) {
- element = retrieveParagraph(getFont(attributes), styleattributes);
- } else if (MarkupTags.CSS_VALUE_LISTITEM.equals(display)) {
- element = retrieveListItem(getFont(attributes), styleattributes);
- } /* ssteward: dropped in pdftk 1.44:
- else if (MarkupTags.CSS_VALUE_TABLECELL.equals(display)) {
- element = retrieveTableCell(attributes, styleattributes);
- } else if (MarkupTags.CSS_VALUE_TABLEROW.equals(display)) {
- element = retrieveTableRow(attributes, styleattributes);
- } else if (MarkupTags.CSS_VALUE_TABLE.equals(display)) {
- element = retrieveTable(attributes, styleattributes);
- } */
- return element;
- }
-
- /**
- * Returns a font based on the ID and CLASS attributes of a tag.
- *
- * @param attributes
- * a Properties object with the tagname and the attributes of the
- * tag.
- * @return an iText Font;
- */
- public Font getFont(Properties attributes) {
- String key = getKey(attributes);
- Font f = (Font) fontcache.get(key);
- if (f != null) {
- return f;
- } else {
- Properties styleattributes = (Properties) stylecache.get(key);
- f = retrieveFont(styleattributes);
- fontcache.put(key, f);
- }
- return f;
- }
-
- /**
- * Returns a rectangle based on the width and height attributes of a tag,
- * can be overridden by the ID and CLASS attributes.
- *
- * @param attrs
- * the attributes that came with the tag
- * @return an iText Rectangle object
- */
- public Rectangle getRectangle(Properties attrs) {
- String width = null;
- String height = null;
- String key = getKey(attrs);
- Properties styleattributes = (Properties) stylecache.get(key);
- if (styleattributes != null) {
- width = styleattributes.getProperty(MarkupTags.HTML_ATTR_WIDTH);
- height = styleattributes.getProperty(MarkupTags.HTML_ATTR_HEIGHT);
- }
- if (width == null)
- width = attrs.getProperty(MarkupTags.HTML_ATTR_WIDTH);
- if (height == null)
- height = attrs.getProperty(MarkupTags.HTML_ATTR_HEIGHT);
- if (width == null || height == null)
- return null;
- return new Rectangle(parseLength(width), parseLength(height));
- }
-
- // retrieving objects based on the styleAttributes
-
- /**
- * Retrieves a Phrase based on some style attributes.
- *
- * @param font
- * @param styleattributes
- * a Properties object containing keys and values
- * @return an iText Phrase object
- */
- public Element retrievePhrase(Font font, Properties styleattributes) {
- Phrase p = new Phrase("", font);
- if (styleattributes == null)
- return p;
- String leading = styleattributes
- .getProperty(MarkupTags.CSS_KEY_LINEHEIGHT);
- if (leading != null) {
- if (leading.endsWith("%")) {
- p.setLeading(p.font().size() * (parseLength(leading) / 100f));
- } else {
- p.setLeading(parseLength(leading));
- }
- }
- return p;
- }
-
- /**
- * Retrieves a Paragraph based on some style attributes.
- *
- * @param font
- * @param styleattributes
- * a Properties object containing keys and values
- * @return an iText Paragraph object
- */
- public Element retrieveParagraph(Font font, Properties styleattributes) {
- Paragraph p = new Paragraph((Phrase) retrievePhrase(font,
- styleattributes));
- if (styleattributes == null)
- return p;
- String margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGIN);
- float f;
- if (margin != null) {
- f = parseLength(margin);
- p.setIndentationLeft(f);
- p.setIndentationRight(f);
- p.setSpacingBefore(f);
- p.setSpacingAfter(f);
- }
- margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINLEFT);
- if (margin != null) {
- f = parseLength(margin);
- p.setIndentationLeft(f);
- }
- margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINRIGHT);
- if (margin != null) {
- f = parseLength(margin);
- p.setIndentationRight(f);
- }
- margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINTOP);
- if (margin != null) {
- f = parseLength(margin);
- p.setSpacingBefore(f);
- }
- margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINBOTTOM);
- if (margin != null) {
- f = parseLength(margin);
- p.setSpacingAfter(f);
- }
- String align = styleattributes
- .getProperty(MarkupTags.CSS_KEY_TEXTALIGN);
- if (MarkupTags.CSS_VALUE_TEXTALIGNLEFT.equals(align)) {
- p.setAlignment(Element.ALIGN_LEFT);
- } else if (MarkupTags.CSS_VALUE_TEXTALIGNRIGHT.equals(align)) {
- p.setAlignment(Element.ALIGN_RIGHT);
- } else if (MarkupTags.CSS_VALUE_TEXTALIGNCENTER.equals(align)) {
- p.setAlignment(Element.ALIGN_CENTER);
- } else if (MarkupTags.CSS_VALUE_TEXTALIGNJUSTIFY.equals(align)) {
- p.setAlignment(Element.ALIGN_JUSTIFIED);
- }
- return p;
- }
-
- /**
- * Gets a table based on the styleattributes.
- *
- * @param attributes
- * @param styleattributes
- * @return an iText Table
- */
- /* ssteward: dropped in 1.44
- private Element retrieveTable(Properties attributes,
- Properties styleattributes) {
- SimpleTable table = new SimpleTable();
- applyBordersColors(table, attributes, styleattributes);
- return table;
- }
- */
-
- /**
- * Returns a Cell based on the styleattributes.
- *
- * @param attributes
- * @param styleattributes
- * @return an iText Cell
- */
- /* ssteward: dropped in 1.44
- private Element retrieveTableRow(Properties attributes,
- Properties styleattributes) {
- SimpleCell row = new SimpleCell(SimpleCell.ROW);
- applyBordersColors(row, attributes, styleattributes);
- String width = null;
- if (attributes != null)
- width = attributes.getProperty(MarkupTags.HTML_ATTR_WIDTH);
- if (width == null)
- width = styleattributes.getProperty(MarkupTags.HTML_ATTR_WIDTH);
- if (width != null) {
- if (width.endsWith("%")) {
- row.setWidthpercentage(parseLength(width));
- } else {
- row.setWidth(parseLength(width));
- }
- }
- String margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGIN);
- float f;
- if (margin != null) {
- f = parseLength(margin);
- row.setSpacing(f);
- }
- margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINLEFT);
- if (margin != null) {
- f = parseLength(margin);
- row.setSpacing_left(f);
- }
- margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINRIGHT);
- if (margin != null) {
- f = parseLength(margin);
- row.setSpacing_right(f);
- }
- margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINTOP);
- if (margin != null) {
- f = parseLength(margin);
- row.setSpacing_top(f);
- }
- margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINBOTTOM);
- if (margin != null) {
- f = parseLength(margin);
- row.setSpacing_bottom(f);
- }
- String padding = styleattributes.getProperty(MarkupTags.CSS_KEY_PADDING);
- if (padding != null) {
- f = parseLength(padding);
- row.setPadding(f);
- }
- padding = styleattributes.getProperty(MarkupTags.CSS_KEY_PADDINGLEFT);
- if (padding != null) {
- f = parseLength(padding);
- row.setSpacing_left(f);
- }
- padding = styleattributes.getProperty(MarkupTags.CSS_KEY_PADDINGRIGHT);
- if (padding != null) {
- f = parseLength(padding);
- row.setSpacing_right(f);
- }
- padding = styleattributes.getProperty(MarkupTags.CSS_KEY_PADDINGTOP);
- if (padding != null) {
- f = parseLength(padding);
- row.setSpacing_top(f);
- }
- padding = styleattributes.getProperty(MarkupTags.CSS_KEY_PADDINGBOTTOM);
- if (padding != null) {
- f = parseLength(padding);
- row.setSpacing_bottom(f);
- }
- return row;
- }
- */
-
- /**
- * Returns a Cell based on the styleattributes.
- *
- * @param attributes
- * @param styleattributes
- * @return an iText Cell
- */
- /* ssteward: dropped in 1.44
- private Element retrieveTableCell(Properties attributes,
- Properties styleattributes) {
- SimpleCell cell = (SimpleCell) retrieveTableRow(attributes,
- styleattributes);
- cell.setCellgroup(false);
- return cell;
- }
- */
-
- /**
- * Returns a ListItem based on the styleattributes.
- *
- * @param font
- * @param styleattributes
- * @return an iText ListItem
- */
- private Element retrieveListItem(Font font, Properties styleattributes) {
- ListItem li = new ListItem();
- return li;
- }
-
- /**
- * Applies colors to a Rectangle object.
- * @param rect
- * @param attributes
- * @param styleattributes
- */
- private void applyBordersColors(Rectangle rect, Properties attributes, Properties styleattributes) {
- String s = styleattributes.getProperty(MarkupTags.CSS_KEY_BORDERWIDTH);
- float f;
- if (s != null) {
- f = parseLength(s);
- rect.setBorderWidth(f);
- }
- s = styleattributes.getProperty(MarkupTags.CSS_KEY_BORDERWIDTHLEFT);
- if (s != null) {
- f = parseLength(s);
- rect.setBorderWidthLeft(f);
- }
- s = styleattributes.getProperty(MarkupTags.CSS_KEY_BORDERWIDTHRIGHT);
- if (s != null) {
- f = parseLength(s);
- rect.setBorderWidthRight(f);
- }
- s = styleattributes.getProperty(MarkupTags.CSS_KEY_BORDERWIDTHTOP);
- if (s != null) {
- f = parseLength(s);
- rect.setBorderWidthTop(f);
- }
- s = styleattributes.getProperty(MarkupTags.CSS_KEY_BORDERWIDTHBOTTOM);
- if (s != null) {
- f = parseLength(s);
- rect.setBorderWidthBottom(f);
- }
- s = styleattributes.getProperty(MarkupTags.CSS_KEY_BORDERCOLOR);
- if (s != null) {
- rect.setBorderColor(decodeColor(s));
- }
- }
-
- /**
- * Retrieves a font from the FontFactory based on some style attributes.
- * Looks for the font-family, font-size, font-weight, font-style and color.
- * Takes the default encoding and embedded value.
- *
- * @param styleAttributes
- * a Properties object containing keys and values
- * @return an iText Font object
- */
-
- public Font retrieveFont(Properties styleAttributes) {
- String fontname = null;
- String encoding = FontFactory.defaultEncoding;
- boolean embedded = FontFactory.defaultEmbedding;
- float size = Font.UNDEFINED;
- int style = Font.NORMAL;
- Color color = null;
- String value = (String) styleAttributes
- .get(MarkupTags.CSS_KEY_FONTFAMILY);
- if (value != null) {
- if (value.indexOf(",") == -1) {
- fontname = value.trim();
- } else {
- String tmp;
- while (value.indexOf(",") != -1) {
- tmp = value.substring(0, value.indexOf(",")).trim();
- if (FontFactory.isRegistered(tmp)) {
- fontname = tmp;
- break;
- } else {
- value = value.substring(value.indexOf(",") + 1);
- }
- }
- }
- }
- if ((value = (String) styleAttributes.get(MarkupTags.CSS_KEY_FONTSIZE)) != null) {
- size = MarkupParser.parseLength(value);
- }
- if ((value = (String) styleAttributes
- .get(MarkupTags.CSS_KEY_FONTWEIGHT)) != null) {
- style |= Font.getStyleValue(value);
- }
- if ((value = (String) styleAttributes.get(MarkupTags.CSS_KEY_FONTSTYLE)) != null) {
- style |= Font.getStyleValue(value);
- }
- if ((value = (String) styleAttributes.get(MarkupTags.CSS_KEY_COLOR)) != null) {
- color = MarkupParser.decodeColor(value);
- }
- return FontFactory.getFont(fontname, encoding, embedded, size, style,
- color);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/markup/MarkupTags.java pdftk-2.01/java/com/lowagie/text/markup/MarkupTags.java
--- pdftk-1.45/java/com/lowagie/text/markup/MarkupTags.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/markup/MarkupTags.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,272 +0,0 @@
-/*
- * $Id: MarkupTags.java,v 1.50 2005/05/03 14:44:38 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.markup;
-
-/**
- * A class that contains all the possible tagnames and their attributes.
- */
-
-public class MarkupTags {
-
- // iText specific
-
- /** the key for any tag */
- public static final String ITEXT_TAG = "tag";
-
- // HTML tags
-
- /** the markup for the body part of a file */
- public static final String HTML_TAG_BODY = "body";
-
- /** The DIV tag. */
- public static final String HTML_TAG_DIV = "div";
-
- /** This is a possible HTML-tag. */
- public static final String HTML_TAG_LINK = "link";
-
- /** The SPAN tag. */
- public static final String HTML_TAG_SPAN = "span";
-
- // HTML attributes
-
- /** the height attribute. */
- public static final String HTML_ATTR_HEIGHT = "height";
-
- /** the hyperlink reference attribute. */
- public static final String HTML_ATTR_HREF = "href";
-
- /** This is a possible HTML attribute for the LINK tag. */
- public static final String HTML_ATTR_REL = "rel";
-
- /** This is used for inline css style information */
- public static final String HTML_ATTR_STYLE = "style";
-
- /** This is a possible HTML attribute for the LINK tag. */
- public static final String HTML_ATTR_TYPE = "type";
-
- /** This is a possible HTML attribute. */
- public static final String HTML_ATTR_STYLESHEET = "stylesheet";
-
- /** the width attribute. */
- public static final String HTML_ATTR_WIDTH = "width";
-
- /** attribute for specifying externally defined CSS class */
- public static final String HTML_ATTR_CSS_CLASS = "class";
-
- /** The ID attribute. */
- public static final String HTML_ATTR_CSS_ID = "id";
-
- // HTML values
-
- /** This is a possible value for the language attribute (SCRIPT tag). */
- public static final String HTML_VALUE_JAVASCRIPT = "text/javascript";
-
- /** This is a possible HTML attribute for the LINK tag. */
- public static final String HTML_VALUE_CSS = "text/css";
-
- // CSS keys
-
- /** the CSS tag for background color */
- public static final String CSS_KEY_BGCOLOR = "background-color";
-
- /** the CSS tag for text color */
- public static final String CSS_KEY_COLOR = "color";
-
- /** CSS key that indicate the way something has to be displayed */
- public static final String CSS_KEY_DISPLAY = "display";
-
- /** the CSS tag for the font family */
- public static final String CSS_KEY_FONTFAMILY = "font-family";
-
- /** the CSS tag for the font size */
- public static final String CSS_KEY_FONTSIZE = "font-size";
-
- /** the CSS tag for the font style */
- public static final String CSS_KEY_FONTSTYLE = "font-style";
-
- /** the CSS tag for the font weight */
- public static final String CSS_KEY_FONTWEIGHT = "font-weight";
-
- /** the CSS tag for text decorations */
- public static final String CSS_KEY_LINEHEIGHT = "line-height";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_MARGIN = "margin";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_MARGINLEFT = "margin-left";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_MARGINRIGHT = "margin-right";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_MARGINTOP = "margin-top";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_MARGINBOTTOM = "margin-bottom";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_PADDING = "padding";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_PADDINGLEFT = "padding-left";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_PADDINGRIGHT = "padding-right";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_PADDINGTOP = "padding-top";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_PADDINGBOTTOM = "padding-bottom";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_BORDERCOLOR = "border-color";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_BORDERWIDTH = "border-width";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_BORDERWIDTHLEFT = "border-left-width";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_BORDERWIDTHRIGHT = "border-right-width";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_BORDERWIDTHTOP = "border-top-width";
-
- /** the CSS tag for the margin of an object */
- public static final String CSS_KEY_BORDERWIDTHBOTTOM = "border-bottom-width";
-
- /** the CSS tag for adding a page break when the document is printed */
- public static final String CSS_KEY_PAGE_BREAK_AFTER = "page-break-after";
-
- /** the CSS tag for adding a page break when the document is printed */
- public static final String CSS_KEY_PAGE_BREAK_BEFORE = "page-break-before";
-
- /** the CSS tag for the horizontal alignment of an object */
- public static final String CSS_KEY_TEXTALIGN = "text-align";
-
- /** the CSS tag for text decorations */
- public static final String CSS_KEY_TEXTDECORATION = "text-decoration";
-
- /** the CSS tag for text decorations */
- public static final String CSS_KEY_VERTICALALIGN = "vertical-align";
-
- /** the CSS tag for the visibility of objects */
- public static final String CSS_KEY_VISIBILITY = "visibility";
-
- // CSS values
-
- /** value for the CSS tag for adding a page break when the document is printed */
- public static final String CSS_VALUE_ALWAYS = "always";
-
- /** A possible value for the DISPLAY key */
- public static final String CSS_VALUE_BLOCK = "block";
-
- /** a CSS value for text font weight */
- public static final String CSS_VALUE_BOLD = "bold";
-
- /** the value if you want to hide objects. */
- public static final String CSS_VALUE_HIDDEN = "hidden";
-
- /** A possible value for the DISPLAY key */
- public static final String CSS_VALUE_INLINE = "inline";
-
- /** a CSS value for text font style */
- public static final String CSS_VALUE_ITALIC = "italic";
-
- /** a CSS value for text decoration */
- public static final String CSS_VALUE_LINETHROUGH = "line-through";
-
- /** A possible value for the DISPLAY key */
- public static final String CSS_VALUE_LISTITEM = "list-item";
-
- /** a CSS value */
- public static final String CSS_VALUE_NONE = "none";
-
- /** a CSS value */
- public static final String CSS_VALUE_NORMAL = "normal";
-
- /** a CSS value for text font style */
- public static final String CSS_VALUE_OBLIQUE = "oblique";
-
- /** A possible value for the DISPLAY key */
- public static final String CSS_VALUE_TABLE = "table";
-
- /** A possible value for the DISPLAY key */
- public static final String CSS_VALUE_TABLEROW = "table-row";
-
- /** A possible value for the DISPLAY key */
- public static final String CSS_VALUE_TABLECELL = "table-cell";
-
- /** the CSS value for a horizontal alignment of an object */
- public static final String CSS_VALUE_TEXTALIGNLEFT = "left";
-
- /** the CSS value for a horizontal alignment of an object */
- public static final String CSS_VALUE_TEXTALIGNRIGHT = "right";
-
- /** the CSS value for a horizontal alignment of an object */
- public static final String CSS_VALUE_TEXTALIGNCENTER = "center";
-
- /** the CSS value for a horizontal alignment of an object */
- public static final String CSS_VALUE_TEXTALIGNJUSTIFY = "justify";
-
- /** a CSS value for text decoration */
- public static final String CSS_VALUE_UNDERLINE = "underline";
-
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/AcroFields.java pdftk-2.01/java/com/lowagie/text/pdf/AcroFields.java
--- pdftk-1.45/java/com/lowagie/text/pdf/AcroFields.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/AcroFields.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,1761 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * Copyright 2003 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Iterator;
-import java.util.Comparator;
-import java.util.Collections;
-import com.lowagie.text.Rectangle;
-import com.lowagie.text.Element;
-import com.lowagie.text.ExceptionConverter;
-import com.lowagie.text.DocumentException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.awt.Color;
-
-/** Query and change fields in existing documents either by method
- * calls or by FDF merging.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class AcroFields {
-
- PdfReader reader;
- PdfWriter writer;
- HashMap fields;
- private int topFirst;
- private HashMap sigNames;
- private boolean append;
- static private final int DA_FONT = 0;
- static private final int DA_SIZE = 1;
- static private final int DA_COLOR = 2;
- /**
- * A field type invalid or not found.
- */
- public static final int FIELD_TYPE_NONE = 0;
- /**
- * A field type.
- */
- public static final int FIELD_TYPE_PUSHBUTTON = 1;
- /**
- * A field type.
- */
- public static final int FIELD_TYPE_CHECKBOX = 2;
- /**
- * A field type.
- */
- public static final int FIELD_TYPE_RADIOBUTTON = 3;
- /**
- * A field type.
- */
- public static final int FIELD_TYPE_TEXT = 4;
- /**
- * A field type.
- */
- public static final int FIELD_TYPE_LIST = 5;
- /**
- * A field type.
- */
- public static final int FIELD_TYPE_COMBO = 6;
- /**
- * A field type.
- */
- public static final int FIELD_TYPE_SIGNATURE = 7;
-
- private boolean lastWasString;
-
- /** Holds value of property generateAppearances. */
- private boolean generateAppearances = true;
-
- private HashMap localFonts = new HashMap();
-
- private float extraMarginLeft;
- private float extraMarginTop;
-
- AcroFields(PdfReader reader, PdfWriter writer) {
- this.reader = reader;
- this.writer = writer;
- if (writer instanceof PdfStamperImp) {
- append = ((PdfStamperImp)writer).isAppend();
- }
- fill();
- }
-
- void fill() {
- fields = new HashMap();
- PdfDictionary top = (PdfDictionary)PdfReader.getPdfObjectRelease(reader.getCatalog().get(PdfName.ACROFORM));
- if (top == null)
- return;
- PdfArray arrfds = (PdfArray)PdfReader.getPdfObjectRelease(top.get(PdfName.FIELDS));
- if (arrfds == null || arrfds.size() == 0)
- return;
- arrfds = null;
- for (int k = 1; k <= reader.getNumberOfPages(); ++k) {
- if ((k % 100) == 0)
- System.out.println(k);
- PdfDictionary page = reader.getPageNRelease(k);
- PdfArray annots = (PdfArray)PdfReader.getPdfObjectRelease(page.get(PdfName.ANNOTS), page);
- if (annots == null)
- continue;
- ArrayList arr = annots.getArrayList();
- for (int j = 0; j < arr.size(); ++j) {
- PdfObject annoto = PdfReader.getPdfObject((PdfObject)arr.get(j), annots);
- if ((annoto instanceof PdfIndirectReference) && !annoto.isIndirect()) {
- PdfReader.releaseLastXrefPartial((PdfObject)arr.get(j));
- continue;
- }
- PdfDictionary annot = (PdfDictionary)annoto;
- if (!PdfName.WIDGET.equals(annot.get(PdfName.SUBTYPE))) {
- PdfReader.releaseLastXrefPartial((PdfObject)arr.get(j));
- continue;
- }
- PdfDictionary widget = annot;
- PdfDictionary dic = new PdfDictionary();
- dic.putAll(annot);
- String name = "";
- PdfDictionary value = null;
- PdfObject lastV = null;
- while (annot != null) {
- dic.mergeDifferent(annot);
- PdfString t = (PdfString)PdfReader.getPdfObject(annot.get(PdfName.T));
- if (t != null)
- name = t.toUnicodeString() + "." + name;
- if (lastV == null && annot.get(PdfName.V) != null)
- lastV = PdfReader.getPdfObjectRelease(annot.get(PdfName.V));
- if (value == null && t != null) {
- value = annot;
- if (annot.get(PdfName.V) == null && lastV != null)
- value.put(PdfName.V, lastV);
- }
- annot = (PdfDictionary)PdfReader.getPdfObject(annot.get(PdfName.PARENT), annot);
- }
- if (name.length() > 0)
- name = name.substring(0, name.length() - 1);
- Item item = (Item)fields.get(name);
- if (item == null) {
- item = new Item();
- fields.put(name, item);
- }
- if (value == null)
- item.values.add(widget);
- else
- item.values.add(value);
- item.widgets.add(widget);
- item.widget_refs.add(arr.get(j)); // must be a reference
- if (top != null)
- dic.mergeDifferent(top);
- item.merged.add(dic);
- item.page.add(new Integer(k));
- item.tabOrder.add(new Integer(j));
- }
- }
- }
-
- /** Gets the list of appearance names. Use it to get the names allowed
- * with radio and checkbox fields. If the /Opt key exists the values will
- * also be included. The name 'Off' may also be valid
- * even if not returned in the list.
- * @param fieldName the fully qualified field name
- * @return the list of names or null
if the field does not exist
- */
- public String[] getAppearanceStates(String fieldName) {
- Item fd = (Item)fields.get(fieldName);
- if (fd == null)
- return null;
- HashMap names = new HashMap();
- PdfDictionary vals = (PdfDictionary)fd.values.get(0);
- PdfObject opts = PdfReader.getPdfObject(vals.get(PdfName.OPT));
- if (opts != null) {
- if (opts.isString())
- names.put(((PdfString)opts).toUnicodeString(), null);
- else if (opts.isArray()) {
- ArrayList list = ((PdfArray)opts).getArrayList();
- for (int k = 0; k < list.size(); ++k) {
- PdfObject v = PdfReader.getPdfObject((PdfObject)list.get(k));
- if (v != null && v.isString())
- names.put(((PdfString)v).toUnicodeString(), null);
- }
- }
- }
- ArrayList wd = fd.widgets;
- for (int k = 0; k < wd.size(); ++k) {
- PdfDictionary dic = (PdfDictionary)wd.get(k);
- dic = (PdfDictionary)PdfReader.getPdfObject(dic.get(PdfName.AP));
- if (dic == null)
- continue;
- PdfObject ob = PdfReader.getPdfObject(dic.get(PdfName.N));
- if (ob == null || !ob.isDictionary())
- continue;
- dic = (PdfDictionary)ob;
- for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
- String name = PdfName.decodeName(((PdfName)it.next()).toString());
- names.put(name, null);
- }
- }
- String out[] = new String[names.size()];
- return (String[])names.keySet().toArray(out);
- }
-
- /**
- * Gets the field type. The type can be one of: FIELD_TYPE_PUSHBUTTON
,
- * FIELD_TYPE_CHECKBOX
, FIELD_TYPE_RADIOBUTTON
,
- * FIELD_TYPE_TEXT
, FIELD_TYPE_LIST
,
- * FIELD_TYPE_COMBO
or FIELD_TYPE_SIGNATURE
.
- *
- * If the field does not exist or is invalid it returns
- * FIELD_TYPE_NONE
.
- * @param fieldName the field name
- * @return the field type
- */
- public int getFieldType(String fieldName) {
- Item fd = (Item)fields.get(fieldName);
- if (fd == null)
- return FIELD_TYPE_NONE;
- PdfObject type = PdfReader.getPdfObject(((PdfDictionary)fd.merged.get(0)).get(PdfName.FT));
- if (type == null)
- return FIELD_TYPE_NONE;
- int ff = 0;
- PdfObject ffo = PdfReader.getPdfObject(((PdfDictionary)fd.merged.get(0)).get(PdfName.FF));
- if (ffo != null && ffo.type() == PdfObject.NUMBER)
- ff = ((PdfNumber)ffo).intValue();
- if (PdfName.BTN.equals(type)) {
- if ((ff & PdfFormField.FF_PUSHBUTTON) != 0)
- return FIELD_TYPE_PUSHBUTTON;
- if ((ff & PdfFormField.FF_RADIO) != 0)
- return FIELD_TYPE_RADIOBUTTON;
- else
- return FIELD_TYPE_CHECKBOX;
- }
- else if (PdfName.TX.equals(type)) {
- return FIELD_TYPE_TEXT;
- }
- else if (PdfName.CH.equals(type)) {
- if ((ff & PdfFormField.FF_COMBO) != 0)
- return FIELD_TYPE_COMBO;
- else
- return FIELD_TYPE_LIST;
- }
- else if (PdfName.SIG.equals(type)) {
- return FIELD_TYPE_SIGNATURE;
- }
- return FIELD_TYPE_NONE;
- }
-
- /**
- * Export the fields as a FDF.
- * @param writer the FDF writer
- */
- public void exportAsFdf(FdfWriter writer) {
- for (Iterator it = fields.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry)it.next();
- Item item = (Item)entry.getValue();
- String name = (String)entry.getKey();
- // PdfObject v = PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.V));
- // ssteward: moved this logic to getField, where lastWasString is set;
- // we also want to output empty fields, too;
- //if (v != null)
- String value = getField(name);
- if (lastWasString)
- writer.setFieldAsString(name, value);
- else
- writer.setFieldAsName(name, value);
- }
- }
-
- /**
- * Renames a field. Only the last part of the name can be renamed. For example,
- * if the original field is "ab.cd.ef" only the "ef" part can be renamed.
- * @param oldName the old field name
- * @param newName the new field name
- * @return true
if the renaming was successful, false
- * otherwise
- */
- public boolean renameField(String oldName, String newName) {
- int idx1 = oldName.lastIndexOf('.') + 1;
- int idx2 = newName.lastIndexOf('.') + 1;
- if (idx1 != idx2)
- return false;
- if (!oldName.substring(0, idx1).equals(newName.substring(0, idx2)))
- return false;
- if (fields.containsKey(newName))
- return false;
- Item item = (Item)fields.get(oldName);
- if (item == null)
- return false;
- newName = newName.substring(idx2);
- PdfString ss = new PdfString(newName, PdfObject.TEXT_UNICODE);
- for (int k = 0; k < item.merged.size(); ++k) {
- PdfDictionary dic = (PdfDictionary)item.values.get(k);
- dic.put(PdfName.T, ss);
- markUsed(dic);
- dic = (PdfDictionary)item.merged.get(k);
- dic.put(PdfName.T, ss);
- }
- fields.remove(oldName);
- fields.put(newName, item);
- return true;
- }
-
- static private Object[] splitDAelements(String da) {
- try {
- PRTokeniser tk = new PRTokeniser(PdfEncodings.convertToBytes(da, null));
- ArrayList stack = new ArrayList();
- Object ret[] = new Object[3];
- while (tk.nextToken()) {
- if (tk.getTokenType() == PRTokeniser.TK_COMMENT)
- continue;
- if (tk.getTokenType() == PRTokeniser.TK_OTHER) {
- String operator = tk.getStringValue();
- if (operator.equals("Tf")) {
- if (stack.size() >= 2) {
- ret[DA_FONT] = stack.get(stack.size() - 2);
- ret[DA_SIZE] = new Float((String)stack.get(stack.size() - 1));
- }
- }
- else if (operator.equals("g")) {
- if (stack.size() >= 1) {
- float gray = new Float((String)stack.get(stack.size() - 1)).floatValue();
- if (gray != 0)
- ret[DA_COLOR] = new GrayColor(gray);
- }
- }
- else if (operator.equals("rg")) {
- if (stack.size() >= 3) {
- float red = new Float((String)stack.get(stack.size() - 3)).floatValue();
- float green = new Float((String)stack.get(stack.size() - 2)).floatValue();
- float blue = new Float((String)stack.get(stack.size() - 1)).floatValue();
- ret[DA_COLOR] = new Color(red, green, blue);
- }
- }
- else if (operator.equals("k")) {
- if (stack.size() >= 4) {
- float cyan = new Float((String)stack.get(stack.size() - 4)).floatValue();
- float magenta = new Float((String)stack.get(stack.size() - 3)).floatValue();
- float yellow = new Float((String)stack.get(stack.size() - 2)).floatValue();
- float black = new Float((String)stack.get(stack.size() - 1)).floatValue();
- ret[DA_COLOR] = new CMYKColor(cyan, magenta, yellow, black);
- }
- }
- stack.clear();
- }
- else
- stack.add(tk.getStringValue());
- }
- return ret;
- }
- catch (IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- }
-
- PdfAppearance getAppearance(PdfDictionary merged, String text, String fieldName) throws IOException, DocumentException {
- topFirst = 0;
- int flags = 0;
- TextField tx = null;
- if (fieldCache == null || !fieldCache.containsKey(fieldName)) {
- tx = new TextField(writer, null, null);
- tx.setExtraMargin(extraMarginLeft, extraMarginTop);
- tx.setBorderWidth(0);
- // the text size and color
- PdfString da = (PdfString)PdfReader.getPdfObject(merged.get(PdfName.DA));
- if (da != null) {
- Object dab[] = splitDAelements(da.toUnicodeString());
- if (dab[DA_SIZE] != null)
- tx.setFontSize(((Float)dab[DA_SIZE]).floatValue());
- if (dab[DA_COLOR] != null)
- tx.setTextColor((Color)dab[DA_COLOR]);
- if (dab[DA_FONT] != null) {
- PdfDictionary font = (PdfDictionary)PdfReader.getPdfObject(merged.get(PdfName.DR));
- if (font != null) {
- font = (PdfDictionary)PdfReader.getPdfObject(font.get(PdfName.FONT));
- if (font != null) {
- PdfObject po = font.get(new PdfName((String)dab[DA_FONT]));
- if (po != null && po.type() == PdfObject.INDIRECT)
- tx.setFont(new DocumentFont((PRIndirectReference)po));
- else {
- BaseFont bf = (BaseFont)localFonts.get(dab[DA_FONT]);
- if (bf == null) {
- String fn[] = (String[])stdFieldFontNames.get(dab[DA_FONT]);
- if (fn != null) {
- try {
- String enc = "winansi";
- if (fn.length > 1)
- enc = fn[1];
- bf = BaseFont.createFont(fn[0], enc, false);
- tx.setFont(bf);
- }
- catch (Exception e) {
- // empty
- }
- }
- }
- else
- tx.setFont(bf);
- }
- }
- }
- }
- }
- //rotation, border and backgound color
- PdfDictionary mk = (PdfDictionary)PdfReader.getPdfObject(merged.get(PdfName.MK));
- if (mk != null) {
- PdfArray ar = (PdfArray)PdfReader.getPdfObject(mk.get(PdfName.BC));
- Color border = getMKColor(ar);
- tx.setBorderColor(border);
- if (border != null)
- tx.setBorderWidth(1);
- ar = (PdfArray)PdfReader.getPdfObject(mk.get(PdfName.BG));
- tx.setBackgroundColor(getMKColor(ar));
- PdfNumber rotation = (PdfNumber)PdfReader.getPdfObject(mk.get(PdfName.R));
- if (rotation != null)
- tx.setRotation(rotation.intValue());
- }
- //multiline
- PdfNumber nfl = (PdfNumber)PdfReader.getPdfObject(merged.get(PdfName.FF));
- if (nfl != null)
- flags = nfl.intValue();
- tx.setOptions(((flags & PdfFormField.FF_MULTILINE) == 0 ? 0 : TextField.MULTILINE) | ((flags & PdfFormField.FF_COMB) == 0 ? 0 : TextField.COMB));
- if ((flags & PdfFormField.FF_COMB) != 0) {
- PdfNumber maxLen = (PdfNumber)PdfReader.getPdfObject(merged.get(PdfName.MAXLEN));
- int len = 0;
- if (maxLen != null)
- len = maxLen.intValue();
- tx.setMaxCharacterLength(len);
- }
- //alignment
- nfl = (PdfNumber)PdfReader.getPdfObject(merged.get(PdfName.Q));
- if (nfl != null) {
- if (nfl.intValue() == PdfFormField.Q_CENTER)
- tx.setAlignment(Element.ALIGN_CENTER);
- else if (nfl.intValue() == PdfFormField.Q_RIGHT)
- tx.setAlignment(Element.ALIGN_RIGHT);
- }
- //border styles
- PdfDictionary bs = (PdfDictionary)PdfReader.getPdfObject(merged.get(PdfName.BS));
- if (bs != null) {
- PdfNumber w = (PdfNumber)PdfReader.getPdfObject(bs.get(PdfName.W));
- if (w != null)
- tx.setBorderWidth(w.floatValue());
- PdfName s = (PdfName)PdfReader.getPdfObject(bs.get(PdfName.S));
- if (PdfName.D.equals(s))
- tx.setBorderStyle(PdfBorderDictionary.STYLE_DASHED);
- else if (PdfName.B.equals(s))
- tx.setBorderStyle(PdfBorderDictionary.STYLE_BEVELED);
- else if (PdfName.I.equals(s))
- tx.setBorderStyle(PdfBorderDictionary.STYLE_INSET);
- else if (PdfName.U.equals(s))
- tx.setBorderStyle(PdfBorderDictionary.STYLE_UNDERLINE);
- }
- else {
- PdfArray bd = (PdfArray)PdfReader.getPdfObject(merged.get(PdfName.BORDER));
- if (bd != null) {
- ArrayList ar = bd.getArrayList();
- if (ar.size() >= 3)
- tx.setBorderWidth(((PdfNumber)ar.get(2)).floatValue());
- if (ar.size() >= 4)
- tx.setBorderStyle(PdfBorderDictionary.STYLE_DASHED);
- }
- }
- //rect
- PdfArray rect = (PdfArray)PdfReader.getPdfObject(merged.get(PdfName.RECT));
- Rectangle box = PdfReader.getNormalizedRectangle(rect);
- if (tx.getRotation() == 90 || tx.getRotation() == 270)
- box = box.rotate();
- tx.setBox(box);
- if (fieldCache != null)
- fieldCache.put(fieldName, tx);
- }
- else {
- tx = (TextField)fieldCache.get(fieldName);
- tx.setWriter(writer);
- }
- PdfName fieldType = (PdfName)PdfReader.getPdfObject(merged.get(PdfName.FT));
- if (PdfName.TX.equals(fieldType)) {
- tx.setText(text);
- return tx.getAppearance();
- }
- if (!PdfName.CH.equals(fieldType))
- throw new DocumentException("An appearance was requested without a variable text field.");
- PdfArray opt = (PdfArray)PdfReader.getPdfObject(merged.get(PdfName.OPT));
- if ((flags & PdfFormField.FF_COMBO) != 0 && opt == null) {
- tx.setText(text);
- return tx.getAppearance();
- }
- if (opt != null) {
- ArrayList op = opt.getArrayList();
- String choices[] = new String[op.size()];
- String choicesExp[] = new String[op.size()];
- for (int k = 0; k < op.size(); ++k) {
- PdfObject obj = (PdfObject)op.get(k);
- if (obj.isString()) {
- choices[k] = choicesExp[k] = ((PdfString)obj).toUnicodeString();
- }
- else {
- ArrayList opar = ((PdfArray)obj).getArrayList();
- choicesExp[k] = ((PdfString)opar.get(0)).toUnicodeString();
- choices[k] = ((PdfString)opar.get(1)).toUnicodeString();
- }
- }
- if ((flags & PdfFormField.FF_COMBO) != 0) {
- for (int k = 0; k < choices.length; ++k) {
- if (text.equals(choicesExp[k])) {
- text = choices[k];
- break;
- }
- }
- tx.setText(text);
- return tx.getAppearance();
- }
- int idx = 0;
- for (int k = 0; k < choicesExp.length; ++k) {
- if (text.equals(choicesExp[k])) {
- idx = k;
- break;
- }
- }
- tx.setChoices(choices);
- tx.setChoiceExports(choicesExp);
- tx.setChoiceSelection(idx);
- }
- PdfAppearance app = tx.getListAppearance();
- topFirst = tx.getTopFirst();
- return app;
- }
-
- Color getMKColor(PdfArray ar) {
- if (ar == null)
- return null;
- ArrayList cc = ar.getArrayList();
- switch (cc.size()) {
- case 1:
- return new GrayColor(((PdfNumber)cc.get(0)).floatValue());
- case 3:
- return new Color(((PdfNumber)cc.get(0)).floatValue(), ((PdfNumber)cc.get(1)).floatValue(), ((PdfNumber)cc.get(2)).floatValue());
- case 4:
- return new CMYKColor(((PdfNumber)cc.get(0)).floatValue(), ((PdfNumber)cc.get(1)).floatValue(), ((PdfNumber)cc.get(2)).floatValue(), ((PdfNumber)cc.get(3)).floatValue());
- default:
- return null;
- }
- }
-
- /** Gets the field value.
- * @param name the fully qualified field name
- * @return the field value
- */
- public String getField(String name) {
- Item item = (Item)fields.get(name);
- if (item == null)
- return null;
- lastWasString = true; // ssteward: default was false
- PdfObject v = PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.V));
- // ssteward: test VT before returning
- //if (v == null)
- // return "";
- PdfName type = (PdfName)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.FT));
- if (PdfName.BTN.equals(type)) {
- lastWasString = false; // ssteward
- PdfNumber ff = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.FF));
- int flags = 0;
- if (ff != null)
- flags = ff.intValue();
- if ((flags & PdfFormField.FF_PUSHBUTTON) != 0)
- return "";
- String value = "";
- if (v != null) { // ssteward
- if (v.isName())
- value = PdfName.decodeName(v.toString());
- else if (v.isString())
- value = ((PdfString)v).toUnicodeString();
- }
- PdfObject opts = PdfReader.getPdfObject(((PdfDictionary)item.values.get(0)).get(PdfName.OPT));
- if (opts != null && opts.isArray()) {
- ArrayList list = ((PdfArray)opts).getArrayList();
- int idx = 0;
- try {
- idx = Integer.parseInt(value);
- PdfString ps = (PdfString)list.get(idx);
- value = ps.toUnicodeString();
- lastWasString = true;
- }
- catch (Exception e) {
- }
- }
- return value;
- }
-
- if (v == null) { // ssteward
- return "";
- }
- if (v.isString()) {
- return ((PdfString)v).toUnicodeString();
- }
- lastWasString = false;
- return PdfName.decodeName(v.toString());
- }
-
- /**
- * Sets a field property. Valid property names are:
- *
- *
- * textfont - sets the text font. The value for this entry is a BaseFont
.
- * textcolor - sets the text color. The value for this entry is a java.awt.Color
.
- * textsize - sets the text size. The value for this entry is a Float
.
- * bgcolor - sets the background color. The value for this entry is a java.awt.Color
.
- * If null
removes the background.
- * bordercolor - sets the border color. The value for this entry is a java.awt.Color
.
- * If null
removes the border.
- *
- * @param field the field name
- * @param name the property name
- * @param value the property value
- * @param inst an array of int
indexing into AcroField.Item.merged
elements to process.
- * Set to null
to process all
- * @return true
if the property exists, false
otherwise
- */
- public boolean setFieldProperty(String field, String name, Object value, int inst[]) {
- if (writer == null)
- throw new RuntimeException("This AcroFields instance is read-only.");
- try {
- Item item = (Item)fields.get(field);
- if (item == null)
- return false;
- InstHit hit = new InstHit(inst);
- if (name.equalsIgnoreCase("textfont")) {
- for (int k = 0; k < item.merged.size(); ++k) {
- if (hit.isHit(k)) {
- PdfString da = (PdfString)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(k)).get(PdfName.DA));
- PdfDictionary dr = (PdfDictionary)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(k)).get(PdfName.DR));
- if (da != null && dr != null) {
- Object dao[] = splitDAelements(da.toUnicodeString());
- PdfAppearance cb = new PdfAppearance();
- if (dao[DA_FONT] != null) {
- BaseFont bf = (BaseFont)value;
- PdfName psn = (PdfName)PdfAppearance.stdFieldFontNames.get(bf.getPostscriptFontName());
- if (psn == null) {
- psn = new PdfName(bf.getPostscriptFontName());
- }
- PdfDictionary fonts = (PdfDictionary)PdfReader.getPdfObject(dr.get(PdfName.FONT));
- if (fonts == null) {
- fonts = new PdfDictionary();
- dr.put(PdfName.FONT, fonts);
- }
- PdfIndirectReference fref = (PdfIndirectReference)fonts.get(psn);
- PdfDictionary top = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM));
- markUsed(top);
- dr = (PdfDictionary)PdfReader.getPdfObject(top.get(PdfName.DR));
- if (dr == null) {
- dr = new PdfDictionary();
- top.put(PdfName.DR, dr);
- }
- markUsed(dr);
- PdfDictionary fontsTop = (PdfDictionary)PdfReader.getPdfObject(dr.get(PdfName.FONT));
- if (fontsTop == null) {
- fontsTop = new PdfDictionary();
- dr.put(PdfName.FONT, fontsTop);
- }
- markUsed(fontsTop);
- PdfIndirectReference frefTop = (PdfIndirectReference)fontsTop.get(psn);
- if (frefTop != null) {
- if (fref == null)
- fonts.put(psn, frefTop);
- }
- else if (fref == null) {
- FontDetails fd;
- if (bf.getFontType() == BaseFont.FONT_TYPE_DOCUMENT) {
- fd = new FontDetails(null, ((DocumentFont)bf).getIndirectReference(), bf);
- }
- else {
- bf.setSubset(false);
- fd = writer.addSimple(bf);
- localFonts.put(psn.toString().substring(1), bf);
- }
- fontsTop.put(psn, fd.getIndirectReference());
- fonts.put(psn, fd.getIndirectReference());
- }
- ByteBuffer buf = cb.getInternalBuffer();
- buf.append(psn.getBytes()).append(' ').append(((Float)dao[DA_SIZE]).floatValue()).append(" Tf ");
- if (dao[DA_COLOR] != null)
- cb.setColorFill((Color)dao[DA_COLOR]);
- PdfString s = new PdfString(cb.toString());
- ((PdfDictionary)item.merged.get(k)).put(PdfName.DA, s);
- ((PdfDictionary)item.widgets.get(k)).put(PdfName.DA, s);
- markUsed((PdfDictionary)item.widgets.get(k));
- }
- }
- }
- }
- }
- else if (name.equalsIgnoreCase("textcolor")) {
- for (int k = 0; k < item.merged.size(); ++k) {
- if (hit.isHit(k)) {
- PdfString da = (PdfString)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(k)).get(PdfName.DA));
- if (da != null) {
- Object dao[] = splitDAelements(da.toUnicodeString());
- PdfAppearance cb = new PdfAppearance();
- if (dao[DA_FONT] != null) {
- ByteBuffer buf = cb.getInternalBuffer();
- buf.append(new PdfName((String)dao[DA_FONT]).getBytes()).append(' ').append(((Float)dao[DA_SIZE]).floatValue()).append(" Tf ");
- cb.setColorFill((Color)value);
- PdfString s = new PdfString(cb.toString());
- ((PdfDictionary)item.merged.get(k)).put(PdfName.DA, s);
- ((PdfDictionary)item.widgets.get(k)).put(PdfName.DA, s);
- markUsed((PdfDictionary)item.widgets.get(k));
- }
- }
- }
- }
- }
- else if (name.equalsIgnoreCase("textsize")) {
- for (int k = 0; k < item.merged.size(); ++k) {
- if (hit.isHit(k)) {
- PdfString da = (PdfString)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(k)).get(PdfName.DA));
- if (da != null) {
- Object dao[] = splitDAelements(da.toUnicodeString());
- PdfAppearance cb = new PdfAppearance();
- if (dao[DA_FONT] != null) {
- ByteBuffer buf = cb.getInternalBuffer();
- buf.append(new PdfName((String)dao[DA_FONT]).getBytes()).append(' ').append(((Float)value).floatValue()).append(" Tf ");
- if (dao[DA_COLOR] != null)
- cb.setColorFill((Color)dao[DA_COLOR]);
- PdfString s = new PdfString(cb.toString());
- ((PdfDictionary)item.merged.get(k)).put(PdfName.DA, s);
- ((PdfDictionary)item.widgets.get(k)).put(PdfName.DA, s);
- markUsed((PdfDictionary)item.widgets.get(k));
- }
- }
- }
- }
- }
- else if (name.equalsIgnoreCase("bgcolor") || name.equalsIgnoreCase("bordercolor")) {
- PdfName dname = (name.equalsIgnoreCase("bgcolor") ? PdfName.BG : PdfName.BC);
- for (int k = 0; k < item.merged.size(); ++k) {
- if (hit.isHit(k)) {
- PdfObject obj = PdfReader.getPdfObject(((PdfDictionary)item.merged.get(k)).get(PdfName.MK));
- markUsed(obj);
- PdfDictionary mk = (PdfDictionary)obj;
- if (mk == null) {
- if (value == null)
- return true;
- mk = new PdfDictionary();
- ((PdfDictionary)item.merged.get(k)).put(PdfName.MK, mk);
- ((PdfDictionary)item.widgets.get(k)).put(PdfName.MK, mk);
- markUsed((PdfDictionary)item.widgets.get(k));
- }
- if (value == null)
- mk.remove(dname);
- else
- mk.put(dname, PdfFormField.getMKColor((Color)value));
- }
- }
- }
- else
- return false;
- return true;
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Sets a field property. Valid property names are:
- *
- *
- * flags - a set of flags specifying various characteristics of the field's widget annotation.
- * The value of this entry replaces that of the F entry in the form's corresponding annotation dictionary.
- * setflags - a set of flags to be set (turned on) in the F entry of the form's corresponding
- * widget annotation dictionary. Bits equal to 1 cause the corresponding bits in F to be set to 1.
- * clrflags - a set of flags to be cleared (turned off) in the F entry of the form's corresponding
- * widget annotation dictionary. Bits equal to 1 cause the corresponding
- * bits in F to be set to 0.
- * fflags - a set of flags specifying various characteristics of the field. The value
- * of this entry replaces that of the Ff entry in the form's corresponding field dictionary.
- * setfflags - a set of flags to be set (turned on) in the Ff entry of the form's corresponding
- * field dictionary. Bits equal to 1 cause the corresponding bits in Ff to be set to 1.
- * clrfflags - a set of flags to be cleared (turned off) in the Ff entry of the form's corresponding
- * field dictionary. Bits equal to 1 cause the corresponding bits in Ff
- * to be set to 0.
- *
- * @param field the field name
- * @param name the property name
- * @param value the property value
- * @param inst an array of int
indexing into AcroField.Item.merged
elements to process.
- * Set to null
to process all
- * @return true
if the property exists, false
otherwise
- */
- public boolean setFieldProperty(String field, String name, int value, int inst[]) {
- if (writer == null)
- throw new RuntimeException("This AcroFields instance is read-only.");
- Item item = (Item)fields.get(field);
- if (item == null)
- return false;
- InstHit hit = new InstHit(inst);
- if (name.equalsIgnoreCase("flags")) {
- PdfNumber num = new PdfNumber(value);
- for (int k = 0; k < item.merged.size(); ++k) {
- if (hit.isHit(k)) {
- ((PdfDictionary)item.merged.get(k)).put(PdfName.F, num);
- ((PdfDictionary)item.widgets.get(k)).put(PdfName.F, num);
- markUsed((PdfDictionary)item.widgets.get(k));
- }
- }
- }
- else if (name.equalsIgnoreCase("setflags")) {
- for (int k = 0; k < item.merged.size(); ++k) {
- if (hit.isHit(k)) {
- PdfNumber num = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.widgets.get(k)).get(PdfName.F));
- int val = 0;
- if (num != null)
- val = num.intValue();
- num = new PdfNumber(val | value);
- ((PdfDictionary)item.merged.get(k)).put(PdfName.F, num);
- ((PdfDictionary)item.widgets.get(k)).put(PdfName.F, num);
- markUsed((PdfDictionary)item.widgets.get(k));
- }
- }
- }
- else if (name.equalsIgnoreCase("clrflags")) {
- for (int k = 0; k < item.merged.size(); ++k) {
- if (hit.isHit(k)) {
- PdfNumber num = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.widgets.get(k)).get(PdfName.F));
- int val = 0;
- if (num != null)
- val = num.intValue();
- num = new PdfNumber(val & (~value));
- ((PdfDictionary)item.merged.get(k)).put(PdfName.F, num);
- ((PdfDictionary)item.widgets.get(k)).put(PdfName.F, num);
- markUsed((PdfDictionary)item.widgets.get(k));
- }
- }
- }
- else if (name.equalsIgnoreCase("fflags")) {
- PdfNumber num = new PdfNumber(value);
- for (int k = 0; k < item.merged.size(); ++k) {
- if (hit.isHit(k)) {
- ((PdfDictionary)item.merged.get(k)).put(PdfName.FF, num);
- ((PdfDictionary)item.values.get(k)).put(PdfName.FF, num);
- markUsed((PdfDictionary)item.values.get(k));
- }
- }
- }
- else if (name.equalsIgnoreCase("setfflags")) {
- for (int k = 0; k < item.merged.size(); ++k) {
- if (hit.isHit(k)) {
- PdfNumber num = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.values.get(k)).get(PdfName.FF));
- int val = 0;
- if (num != null)
- val = num.intValue();
- num = new PdfNumber(val | value);
- ((PdfDictionary)item.merged.get(k)).put(PdfName.FF, num);
- ((PdfDictionary)item.values.get(k)).put(PdfName.FF, num);
- markUsed((PdfDictionary)item.values.get(k));
- }
- }
- }
- else if (name.equalsIgnoreCase("clrfflags")) {
- for (int k = 0; k < item.merged.size(); ++k) {
- if (hit.isHit(k)) {
- PdfNumber num = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.values.get(k)).get(PdfName.FF));
- int val = 0;
- if (num != null)
- val = num.intValue();
- num = new PdfNumber(val & (~value));
- ((PdfDictionary)item.merged.get(k)).put(PdfName.FF, num);
- ((PdfDictionary)item.values.get(k)).put(PdfName.FF, num);
- markUsed((PdfDictionary)item.values.get(k));
- }
- }
- }
- else
- return false;
- return true;
- }
-
- /** Sets the fields by FDF merging.
- * @param fdf the FDF form
- * @throws IOException on error
- * @throws DocumentException on error
- */
- public boolean setFields(FdfReader fdf) throws IOException, DocumentException {
- boolean ret_val_b= false; // ssteward
- fdf.getFields();
- for (Iterator i = fields.keySet().iterator(); i.hasNext();) {
- String f = (String)i.next();
- String v = fdf.getFieldValue(f);
- String rv = fdf.getFieldRichValue(f); // ssteward
- if (rv != null)
- ret_val_b= true;
- if (v != null)
- setField(f, v, v, rv); // ssteward
- }
- return ret_val_b; // ssteward
- }
-
- /** Sets the fields by XFDF merging.
- * @param xfdf the XFDF form
- * @throws IOException on error
- * @throws DocumentException on error
- */
- public boolean setFields(XfdfReader xfdf) throws IOException, DocumentException {
- boolean ret_val_b= false; // ssteward
- xfdf.getFields();
- for (Iterator i = fields.keySet().iterator(); i.hasNext();) {
- String f = (String)i.next();
- String v = xfdf.getFieldValue(f);
- String rv = xfdf.getFieldRichValue(f); // ssteward
- if (rv != null)
- ret_val_b= true;
- if (v != null)
- setField(f, v, v, rv); // ssteward
- }
- return ret_val_b; // ssteward
- }
-
- /** Sets the field value.
- * @param name the fully qualified field name
- * @param value the field value
- * @throws IOException on error
- * @throws DocumentException on error
- * @return true
if the field was found and changed,
- * false
otherwise
- */
- public boolean setField(String name, String value) throws IOException, DocumentException {
- return setField(name, value, value, null); // ssteward
- }
- // ssteward; added for backward compatibility
- public boolean setField(String name, String value, String display) throws IOException, DocumentException {
- return setField(name, value, display, null);
- }
-
- /** Sets the field value and the display string. The display string
- * is used to build the appearance in the cases where the value
- * is modified by Acrobat with JavaScript and the algorithm is
- * known.
- * @param name the fully qualified field name
- * @param value the field value
- * @param display the string that is used for the appearance
- * @param rich_value (ssteward)
- * @return true
if the field was found and changed,
- * false
otherwise
- * @throws IOException on error
- * @throws DocumentException on error
- */
- public boolean setField(String name, String value, String display, String rich_value) throws IOException, DocumentException {
- if (writer == null)
- throw new DocumentException("This AcroFields instance is read-only.");
- Item item = (Item)fields.get(name);
- if (item == null)
- return false;
- PdfName type = (PdfName)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.FT));
- if (PdfName.TX.equals(type)) {
- PdfNumber maxLen = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.MAXLEN));
- int len = 0;
- if (maxLen != null)
- len = maxLen.intValue();
- if (len > 0)
- value = value.substring(0, Math.min(len, value.length()));
- }
- if (PdfName.TX.equals(type) || PdfName.CH.equals(type)) {
- PdfString v = new PdfString(value, PdfObject.TEXT_UNICODE);
- // ssteward
- PdfString rv = null;
- if( rich_value != null )
- rv = new PdfString(rich_value, PdfObject.TEXT_UNICODE); // ssteward
- for (int idx = 0; idx < item.values.size(); ++idx) {
-
- PdfDictionary item_value= (PdfDictionary)item.values.get(idx);
- item_value.put(PdfName.V, v);
- markUsed(item_value);
- if( rich_value != null ) // ssteward
- item_value.put(PdfName.RV, rv);
- item_value.remove(PdfName.I); // ssteward; it might disagree w/ V in a Ch widget
- // PDF spec this shouldn't matter, but Reader 9 gives I precedence over V
-
- PdfDictionary merged = (PdfDictionary)item.merged.get(idx);
- merged.put(PdfName.V, v);
- if( rich_value != null ) // ssteward
- merged.put(PdfName.RV, rv);
- merged.remove(PdfName.I); // ssteward
-
- PdfDictionary widget = (PdfDictionary)item.widgets.get(idx);
- if (generateAppearances) {
- PdfAppearance app = getAppearance(merged, display, name);
- if (PdfName.CH.equals(type)) {
- PdfNumber n = new PdfNumber(topFirst);
- widget.put(PdfName.TI, n);
- merged.put(PdfName.TI, n);
- }
- PdfDictionary appDic = (PdfDictionary)PdfReader.getPdfObject(widget.get(PdfName.AP));
- if (appDic == null) {
- appDic = new PdfDictionary();
- widget.put(PdfName.AP, appDic);
- merged.put(PdfName.AP, appDic);
- }
- appDic.put(PdfName.N, app.getIndirectReference());
- writer.releaseTemplate(app);
- }
- else {
- widget.remove(PdfName.AP);
- merged.remove(PdfName.AP);
- }
- markUsed(widget);
- }
- return true;
- }
- else if (PdfName.BTN.equals(type)) {
- PdfNumber ff = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.FF));
- int flags = 0;
- if (ff != null)
- flags = ff.intValue();
- if ((flags & PdfFormField.FF_PUSHBUTTON) != 0)
- return true;
- PdfName v = new PdfName(value);
- if ((flags & PdfFormField.FF_RADIO) == 0) {
- for (int idx = 0; idx < item.values.size(); ++idx) {
- ((PdfDictionary)item.values.get(idx)).put(PdfName.V, v);
- markUsed((PdfDictionary)item.values.get(idx));
- PdfDictionary merged = (PdfDictionary)item.merged.get(idx);
- merged.put(PdfName.V, v);
- merged.put(PdfName.AS, v);
- PdfDictionary widget = (PdfDictionary)item.widgets.get(idx);
- if (isInAP(widget, v))
- widget.put(PdfName.AS, v);
- else
- widget.put(PdfName.AS, PdfName.Off);
- markUsed(widget);
- }
- }
- else {
- ArrayList lopt = new ArrayList();
- PdfObject opts = PdfReader.getPdfObject(((PdfDictionary)item.values.get(0)).get(PdfName.OPT));
- if (opts != null && opts.isArray()) {
- ArrayList list = ((PdfArray)opts).getArrayList();
- for (int k = 0; k < list.size(); ++k) {
- PdfObject vv = PdfReader.getPdfObject((PdfObject)list.get(k));
- if (vv != null && vv.isString())
- lopt.add(((PdfString)vv).toUnicodeString());
- else
- lopt.add(null);
- }
- }
- int vidx = lopt.indexOf(value);
- PdfName valt = null;
- PdfName vt;
- if (vidx >= 0) {
- vt = valt = new PdfName(String.valueOf(vidx));
- }
- else
- vt = v;
- for (int idx = 0; idx < item.values.size(); ++idx) {
- PdfDictionary merged = (PdfDictionary)item.merged.get(idx);
- PdfDictionary widget = (PdfDictionary)item.widgets.get(idx);
- markUsed((PdfDictionary)item.values.get(idx));
- if (valt != null) {
- PdfString ps = new PdfString(value, PdfObject.TEXT_UNICODE);
- ((PdfDictionary)item.values.get(idx)).put(PdfName.V, ps);
- merged.put(PdfName.V, ps);
- }
- else {
- ((PdfDictionary)item.values.get(idx)).put(PdfName.V, v);
- merged.put(PdfName.V, v);
- }
- markUsed(widget);
- if (isInAP(widget, vt)) {
- merged.put(PdfName.AS, vt);
- widget.put(PdfName.AS, vt);
- }
- else {
- merged.put(PdfName.AS, PdfName.Off);
- widget.put(PdfName.AS, PdfName.Off);
- }
- }
- }
- return true;
- }
- return false;
- }
-
- boolean isInAP(PdfDictionary dic, PdfName check) {
- PdfDictionary appDic = (PdfDictionary)PdfReader.getPdfObject(dic.get(PdfName.AP));
- if (appDic == null)
- return false;
- PdfDictionary NDic = (PdfDictionary)PdfReader.getPdfObject(appDic.get(PdfName.N));
- return (NDic != null && NDic.get(check) != null);
- }
-
- /** Gets all the fields. The fields are keyed by the fully qualified field name and
- * the value is an instance of AcroFields.Item
.
- * @return all the fields
- */
- public HashMap getFields() {
- return fields;
- }
-
- /**
- * Gets the field structure.
- * @param name the name of the field
- * @return the field structure or null
if the field
- * does not exist
- */
- public Item getFieldItem(String name) {
- return (Item)fields.get(name);
- }
-
- /**
- * Gets the field box positions in the document. The return is an array of float
- * multiple of 5. For each of this groups the values are: [page, llx, lly, urx,
- * ury].
- * @param name the field name
- * @return the positions or null
if field does not exist
- */
- public float[] getFieldPositions(String name) {
- Item item = (Item)fields.get(name);
- if (item == null)
- return null;
- float ret[] = new float[item.page.size() * 5];
- int ptr = 0;
- for (int k = 0; k < item.page.size(); ++k) {
- try {
- PdfDictionary wd = (PdfDictionary)item.widgets.get(k);
- PdfArray rect = (PdfArray)wd.get(PdfName.RECT);
- if (rect == null)
- continue;
- Rectangle r = PdfReader.getNormalizedRectangle(rect);
- ret[ptr] = ((Integer)item.page.get(k)).floatValue();
- ++ptr;
- ret[ptr++] = r.left();
- ret[ptr++] = r.bottom();
- ret[ptr++] = r.right();
- ret[ptr++] = r.top();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- if (ptr < ret.length) {
- float ret2[] = new float[ptr];
- System.arraycopy(ret, 0, ret2, 0, ptr);
- return ret2;
- }
- return ret;
- }
-
- private int removeRefFromArray(PdfArray array, PdfObject refo) {
- ArrayList ar = array.getArrayList();
- if (refo == null || !refo.isIndirect())
- return ar.size();
- PdfIndirectReference ref = (PdfIndirectReference)refo;
- for (int j = 0; j < ar.size(); ++j) {
- PdfObject obj = (PdfObject)ar.get(j);
- if (!obj.isIndirect())
- continue;
- if (((PdfIndirectReference)obj).getNumber() == ref.getNumber())
- ar.remove(j--);
- }
- return ar.size();
- }
-
- /**
- * Removes all the fields from page
.
- * @param page the page to remove the fields from
- * @return true
if any field was removed, false otherwise
- */
- public boolean removeFieldsFromPage(int page) {
- if (page < 1)
- return false;
- String names[] = new String[fields.size()];
- fields.keySet().toArray(names);
- boolean found = false;
- for (int k = 0; k < names.length; ++k) {
- boolean fr = removeField(names[k], page);
- found = (found || fr);
- }
- return found;
- }
-
- /**
- * Removes a field from the document. If page equals -1 all the fields with this
- * name
are removed from the document otherwise only the fields in
- * that particular page are removed.
- * @param name the field name
- * @param page the page to remove the field from or -1 to remove it from all the pages
- * @return true
if the field exists, false otherwise
- */
- public boolean removeField(String name, int page) {
- Item item = (Item)fields.get(name);
- if (item == null)
- return false;
- PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM), reader.getCatalog());
-
- if (acroForm == null)
- return false;
- PdfArray arrayf = (PdfArray)PdfReader.getPdfObject(acroForm.get(PdfName.FIELDS), acroForm);
- if (arrayf == null)
- return false;
- for (int k = 0; k < item.widget_refs.size(); ++k) {
- int pageV = ((Integer)item.page.get(k)).intValue();
- if (page != -1 && page != pageV)
- continue;
- PdfIndirectReference ref = (PdfIndirectReference)item.widget_refs.get(k);
- PdfDictionary wd = (PdfDictionary)PdfReader.getPdfObject(ref);
- PdfDictionary pageDic = reader.getPageN(pageV);
- PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS), pageDic);
- if (annots != null) {
- if (removeRefFromArray(annots, ref) == 0) {
- pageDic.remove(PdfName.ANNOTS);
- markUsed(pageDic);
- }
- else
- markUsed(annots);
- }
- PdfReader.killIndirect(ref);
- PdfIndirectReference kid = ref;
- while ((ref = (PdfIndirectReference)wd.get(PdfName.PARENT)) != null) {
- wd = (PdfDictionary)PdfReader.getPdfObject(ref);
- PdfArray kids = (PdfArray)PdfReader.getPdfObject(wd.get(PdfName.KIDS));
- if (removeRefFromArray(kids, kid) != 0)
- break;
- kid = ref;
- PdfReader.killIndirect(ref);
- }
- if (ref == null) {
- removeRefFromArray(arrayf, kid);
- markUsed(arrayf);
- }
- if (page != -1) {
- item.merged.remove(k);
- item.page.remove(k);
- item.values.remove(k);
- item.widget_refs.remove(k);
- item.widgets.remove(k);
- --k;
- }
- }
- if (page == -1 || item.merged.size() == 0)
- fields.remove(name);
- return true;
- }
-
- /**
- * Removes a field from the document.
- * @param name the field name
- * @return true
if the field exists, false otherwise
- */
- public boolean removeField(String name) {
- return removeField(name, -1);
- }
-
- /** Gets the property generateAppearances.
- * @return the property generateAppearances
- */
- public boolean isGenerateAppearances() {
- return this.generateAppearances;
- }
-
- /** Sets the option to generate appearances. Not generating apperances
- * will speed-up form filling but the results can be
- * unexpected in Acrobat. Don't use it unless your environment is well
- * controlled. The default is true
.
- * @param generateAppearances the option to generate appearances
- */
- public void setGenerateAppearances(boolean generateAppearances) {
- this.generateAppearances = generateAppearances;
- PdfDictionary top = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM));
- if (generateAppearances)
- top.remove(PdfName.NEEDAPPEARANCES);
- else
- top.put(PdfName.NEEDAPPEARANCES, PdfBoolean.PDFTRUE);
- }
-
- /** The field representations for retrieval and modification. */
- public static class Item {
- /** An array of PdfDictionary
where the value tag /V
- * is present.
- */
- public ArrayList values = new ArrayList();
- /** An array of PdfDictionary
with the widgets.
- */
- public ArrayList widgets = new ArrayList();
- /** An array of PdfDictionary
with the widget references.
- */
- public ArrayList widget_refs = new ArrayList();
- /** An array of PdfDictionary
with all the field
- * and widget tags merged.
- */
- public ArrayList merged = new ArrayList();
- /** An array of Integer
with the page numbers where
- * the widgets are displayed.
- */
- public ArrayList page = new ArrayList();
- /** An array of Integer
with the tab order of the field in the page.
- */
- public ArrayList tabOrder = new ArrayList();
- }
-
- private static class InstHit {
- IntHashtable hits;
- public InstHit(int inst[]) {
- if (inst == null)
- return;
- hits = new IntHashtable();
- for (int k = 0; k < inst.length; ++k)
- hits.put(inst[k], 1);
- }
-
- public boolean isHit(int n) {
- if (hits == null)
- return true;
- return hits.containsKey(n);
- }
- }
-
- /**
- * Gets the field names that have signatures and are signed.
- * @return the field names that have signatures and are signed
- */
- public ArrayList getSignatureNames() {
- if (sigNames != null)
- return new ArrayList(sigNames.keySet());
- sigNames = new HashMap();
- ArrayList sorter = new ArrayList();
- for (Iterator it = fields.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry)it.next();
- Item item = (Item)entry.getValue();
- PdfDictionary merged = (PdfDictionary)item.merged.get(0);
- if (!PdfName.SIG.equals(merged.get(PdfName.FT)))
- continue;
- PdfObject vo = PdfReader.getPdfObject(merged.get(PdfName.V));
- if (vo == null || vo.type() != PdfObject.DICTIONARY)
- continue;
- PdfDictionary v = (PdfDictionary)vo;
- PdfObject contents = v.get(PdfName.CONTENTS);
- if (contents == null || contents.type() != PdfObject.STRING)
- continue;
- PdfObject ro = v.get(PdfName.BYTERANGE);
- if (ro == null || ro.type() != PdfObject.ARRAY)
- continue;
- ArrayList ra = ((PdfArray)ro).getArrayList();
- if (ra.size() < 2)
- continue;
- int length = ((PdfNumber)ra.get(ra.size() - 1)).intValue() + ((PdfNumber)ra.get(ra.size() - 2)).intValue();
- sorter.add(new Object[]{entry.getKey(), new int[]{length, 0}});
- }
- Collections.sort(sorter, new AcroFields.SorterComparator());
- if (sorter.size() > 0) {
- if (((int[])((Object[])sorter.get(sorter.size() - 1))[1])[0] == reader.getFileLength())
- totalRevisions = sorter.size();
- else
- totalRevisions = sorter.size() + 1;
- for (int k = 0; k < sorter.size(); ++k) {
- Object objs[] = (Object[])sorter.get(k);
- String name = (String)objs[0];
- int p[] = (int[])objs[1];
- p[1] = k + 1;
- sigNames.put(name, p);
- }
- }
- return new ArrayList(sigNames.keySet());
- }
-
- /**
- * Gets the field names that have blank signatures.
- * @return the field names that have blank signatures
- */
- public ArrayList getBlankSignatureNames() {
- getSignatureNames();
- ArrayList sigs = new ArrayList();
- for (Iterator it = fields.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry)it.next();
- Item item = (Item)entry.getValue();
- PdfDictionary merged = (PdfDictionary)item.merged.get(0);
- if (!PdfName.SIG.equals(merged.get(PdfName.FT)))
- continue;
- if (sigNames.containsKey(entry.getKey()))
- continue;
- sigs.add(entry.getKey());
- }
- return sigs;
- }
-
- /**
- * Gets the signature dictionary, the one keyed by /V.
- * @param name the field name
- * @return the signature dictionary keyed by /V or null
if the field is not
- * a signature
- */
- public PdfDictionary getSignatureDictionary(String name) {
- getSignatureNames();
- if (!sigNames.containsKey(name))
- return null;
- Item item = (Item)fields.get(name);
- PdfDictionary merged = (PdfDictionary)item.merged.get(0);
- // PdfObject vo = PdfReader.getPdfObject(merged.get(PdfName.V));
- return (PdfDictionary)PdfReader.getPdfObject(merged.get(PdfName.V));
- }
-
- /**
- * Checks is the signature covers the entire document or just part of it.
- * @param name the signature field name
- * @return true
if the signature covers the entire document,
- * false
otherwise
- */
- public boolean signatureCoversWholeDocument(String name) {
- getSignatureNames();
- if (!sigNames.containsKey(name))
- return false;
- return ((int[])sigNames.get(name))[0] == reader.getFileLength();
- }
-
- /**
- * Verifies a signature. An example usage is:
- *
- *
- * KeyStore kall = PdfPKCS7.loadCacertsKeyStore();
- * PdfReader reader = new PdfReader("my_signed_doc.pdf");
- * AcroFields af = reader.getAcroFields();
- * ArrayList names = af.getSignatureNames();
- * for (int k = 0; k < names.size(); ++k) {
- * String name = (String)names.get(k);
- * System.out.println("Signature name: " + name);
- * System.out.println("Signature covers whole document: " + af.signatureCoversWholeDocument(name));
- * PdfPKCS7 pk = af.verifySignature(name);
- * Calendar cal = pk.getSignDate();
- * Certificate pkc[] = pk.getCertificates();
- * System.out.println("Subject: " + PdfPKCS7.getSubjectFields(pk.getSigningCertificate()));
- * System.out.println("Document modified: " + !pk.verify());
- * Object fails[] = PdfPKCS7.verifyCertificates(pkc, kall, null, cal);
- * if (fails == null)
- * System.out.println("Certificates verified against the KeyStore");
- * else
- * System.out.println("Certificate failed: " + fails[1]);
- * }
- *
- * @param name the signature field name
- * @return a PdfPKCS7
class to continue the verification
- */
- public PdfPKCS7 verifySignature(String name) {
- return verifySignature(name, null);
- }
-
- /**
- * Verifies a signature. An example usage is:
- *
- *
- * KeyStore kall = PdfPKCS7.loadCacertsKeyStore();
- * PdfReader reader = new PdfReader("my_signed_doc.pdf");
- * AcroFields af = reader.getAcroFields();
- * ArrayList names = af.getSignatureNames();
- * for (int k = 0; k < names.size(); ++k) {
- * String name = (String)names.get(k);
- * System.out.println("Signature name: " + name);
- * System.out.println("Signature covers whole document: " + af.signatureCoversWholeDocument(name));
- * PdfPKCS7 pk = af.verifySignature(name);
- * Calendar cal = pk.getSignDate();
- * Certificate pkc[] = pk.getCertificates();
- * System.out.println("Subject: " + PdfPKCS7.getSubjectFields(pk.getSigningCertificate()));
- * System.out.println("Document modified: " + !pk.verify());
- * Object fails[] = PdfPKCS7.verifyCertificates(pkc, kall, null, cal);
- * if (fails == null)
- * System.out.println("Certificates verified against the KeyStore");
- * else
- * System.out.println("Certificate failed: " + fails[1]);
- * }
- *
- * @param name the signature field name
- * @param provider the provider or null
for the default provider
- * @return a PdfPKCS7
class to continue the verification
- */
- public PdfPKCS7 verifySignature(String name, String provider) {
- PdfDictionary v = getSignatureDictionary(name);
- if (v == null)
- return null;
- try {
- PdfName sub = (PdfName)PdfReader.getPdfObject(v.get(PdfName.SUBFILTER));
- PdfString contents = (PdfString)PdfReader.getPdfObject(v.get(PdfName.CONTENTS));
- PdfPKCS7 pk = null;
- if (sub.equals(PdfName.ADBE_X509_RSA_SHA1)) {
- PdfString cert = (PdfString)PdfReader.getPdfObject(v.get(PdfName.CERT));
- pk = new PdfPKCS7(contents.getOriginalBytes(), cert.getBytes(), provider);
- }
- else
- pk = new PdfPKCS7(contents.getOriginalBytes(), provider);
- updateByteRange(pk, v);
- PdfString str = (PdfString)PdfReader.getPdfObject(v.get(PdfName.M));
- if (str != null)
- pk.setSignDate(PdfDate.decode(str.toString()));
- str = (PdfString)PdfReader.getPdfObject(v.get(PdfName.NAME));
- if (str != null)
- pk.setSignName(str.toUnicodeString());
- str = (PdfString)PdfReader.getPdfObject(v.get(PdfName.REASON));
- if (str != null)
- pk.setReason(str.toUnicodeString());
- str = (PdfString)PdfReader.getPdfObject(v.get(PdfName.LOCATION));
- if (str != null)
- pk.setLocation(str.toUnicodeString());
- return pk;
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- private void updateByteRange(PdfPKCS7 pkcs7, PdfDictionary v) {
- PdfArray b = (PdfArray)PdfReader.getPdfObject(v.get(PdfName.BYTERANGE));
- RandomAccessFileOrArray rf = reader.getSafeFile();
- try {
- rf.reOpen();
- byte buf[] = new byte[8192];
- ArrayList ar = b.getArrayList();
- for (int k = 0; k < ar.size(); ++k) {
- int start = ((PdfNumber)ar.get(k)).intValue();
- int length = ((PdfNumber)ar.get(++k)).intValue();
- rf.seek(start);
- while (length > 0) {
- int rd = rf.read(buf, 0, Math.min(length, buf.length));
- if (rd <= 0)
- break;
- length -= rd;
- pkcs7.update(buf, 0, rd);
- }
- }
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- finally {
- try{rf.close();}catch(Exception e){}
- }
- }
-
- private void markUsed(PdfObject obj) {
- if (!append)
- return;
- ((PdfStamperImp)writer).markUsed(obj);
- }
-
- /**
- * Gets the total number of revisions this document has.
- * @return the total number of revisions
- */
- public int getTotalRevisions() {
- getSignatureNames();
- return this.totalRevisions;
- }
-
- /**
- * Gets this field
revision.
- * @param field the signature field name
- * @return the revision or zero if it's not a signature field
- */
- public int getRevision(String field) {
- getSignatureNames();
- if (!sigNames.containsKey(field))
- return 0;
- return ((int[])sigNames.get(field))[1];
- }
-
- /**
- * Extracts a revision from the document.
- * @param field the signature field name
- * @return an InputStream
covering the revision. Returns null
if
- * it's not a signature field
- * @throws IOException on error
- */
- public InputStream extractRevision(String field) throws IOException {
- getSignatureNames();
- int length = ((int[])sigNames.get(field))[0];
- RandomAccessFileOrArray raf = reader.getSafeFile();
- raf.reOpen();
- raf.seek(0);
- return new RevisionStream(raf, length);
- }
-
- /**
- * Gets the appearances cache.
- * @return the appearances cache
- */
- public HashMap getFieldCache() {
- return this.fieldCache;
- }
-
- /**
- * Sets a cache for field appearances. Parsing the existing PDF to
- * create a new TextField is time expensive. For those tasks that repeatedly
- * fill the same PDF with different field values the use of the cache has dramatic
- * speed advantages. An example usage:
- *
- *
- * String pdfFile = ...;// the pdf file used as template
- * ArrayList xfdfFiles = ...;// the xfdf file names
- * ArrayList pdfOutFiles = ...;// the output file names, one for each element in xpdfFiles
- * HashMap cache = new HashMap();// the appearances cache
- * PdfReader originalReader = new PdfReader(pdfFile);
- * for (int k = 0; k < xfdfFiles.size(); ++k) {
- * PdfReader reader = new PdfReader(originalReader);
- * XfdfReader xfdf = new XfdfReader((String)xfdfFiles.get(k));
- * PdfStamper stp = new PdfStamper(reader, new FileOutputStream((String)pdfOutFiles.get(k)));
- * AcroFields af = stp.getAcroFields();
- * af.setFieldCache(cache);
- * af.setFields(xfdf);
- * stp.close();
- * }
- *
- * @param fieldCache an HasMap that will carry the cached appearances
- */
- public void setFieldCache(HashMap fieldCache) {
- this.fieldCache = fieldCache;
- }
-
- /**
- * Sets extra margins in text fields to better mimic the Acrobat layout.
- * @param extraMarginLeft the extra marging left
- * @param extraMarginTop the extra margin top
- */
- public void setExtraMargin(float extraMarginLeft, float extraMarginTop) {
- this.extraMarginLeft = extraMarginLeft;
- this.extraMarginTop = extraMarginTop;
- }
-
- private static final HashMap stdFieldFontNames = new HashMap();
-
- /**
- * Holds value of property totalRevisions.
- */
- private int totalRevisions;
-
- /**
- * Holds value of property fieldCache.
- */
- private HashMap fieldCache;
-
- static {
- stdFieldFontNames.put("CoBO", new String[]{"Courier-BoldOblique"});
- stdFieldFontNames.put("CoBo", new String[]{"Courier-Bold"});
- stdFieldFontNames.put("CoOb", new String[]{"Courier-Oblique"});
- stdFieldFontNames.put("Cour", new String[]{"Courier"});
- stdFieldFontNames.put("HeBO", new String[]{"Helvetica-BoldOblique"});
- stdFieldFontNames.put("HeBo", new String[]{"Helvetica-Bold"});
- stdFieldFontNames.put("HeOb", new String[]{"Helvetica-Oblique"});
- stdFieldFontNames.put("Helv", new String[]{"Helvetica"});
- stdFieldFontNames.put("Symb", new String[]{"Symbol"});
- stdFieldFontNames.put("TiBI", new String[]{"Times-BoldItalic"});
- stdFieldFontNames.put("TiBo", new String[]{"Times-Bold"});
- stdFieldFontNames.put("TiIt", new String[]{"Times-Italic"});
- stdFieldFontNames.put("TiRo", new String[]{"Times-Roman"});
- stdFieldFontNames.put("ZaDb", new String[]{"ZapfDingbats"});
- stdFieldFontNames.put("HySm", new String[]{"HYSMyeongJo-Medium", "UniKS-UCS2-H"});
- stdFieldFontNames.put("HyGo", new String[]{"HYGoThic-Medium", "UniKS-UCS2-H"});
- stdFieldFontNames.put("KaGo", new String[]{"HeiseiKakuGo-W5", "UniKS-UCS2-H"});
- stdFieldFontNames.put("KaMi", new String[]{"HeiseiMin-W3", "UniJIS-UCS2-H"});
- stdFieldFontNames.put("MHei", new String[]{"MHei-Medium", "UniCNS-UCS2-H"});
- stdFieldFontNames.put("MSun", new String[]{"MSung-Light", "UniCNS-UCS2-H"});
- stdFieldFontNames.put("STSo", new String[]{"STSong-Light", "UniGB-UCS2-H"});
- }
-
- private static class RevisionStream extends InputStream {
- private byte b[] = new byte[1];
- private RandomAccessFileOrArray raf;
- private int length;
- private int rangePosition = 0;
- private boolean closed;
-
- private RevisionStream(RandomAccessFileOrArray raf, int length) {
- this.raf = raf;
- this.length = length;
- }
-
- public int read() throws IOException {
- int n = read(b);
- if (n != 1)
- return -1;
- return b[0] & 0xff;
- }
-
- public int read(byte[] b, int off, int len) throws IOException {
- if (b == null) {
- throw new NullPointerException();
- } else if ((off < 0) || (off > b.length) || (len < 0) ||
- ((off + len) > b.length) || ((off + len) < 0)) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return 0;
- }
- if (rangePosition >= length) {
- close();
- return -1;
- }
- int elen = Math.min(len, length - rangePosition);
- raf.readFully(b, off, elen);
- rangePosition += elen;
- return elen;
- }
-
- public void close() throws IOException {
- if (!closed) {
- raf.close();
- closed = true;
- }
- }
- }
-
- private static class SorterComparator implements Comparator {
- public int compare(Object o1, Object o2) {
- int n1 = ((int[])((Object[])o1)[1])[0];
- int n2 = ((int[])((Object[])o2)[1])[0];
- return n1 - n2;
- }
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/ArabicLigaturizer.java pdftk-2.01/java/com/lowagie/text/pdf/ArabicLigaturizer.java
--- pdftk-1.45/java/com/lowagie/text/pdf/ArabicLigaturizer.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/ArabicLigaturizer.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,777 +0,0 @@
-/*
- * Copyright 2003 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-/** Shape arabic characters. This code was converted from a C version
- * at www.pango.org.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class ArabicLigaturizer {
-
- static boolean isVowel(char s) {
- return ((s >= 0x064B) && (s <= 0x0655)) || (s == 0x0670);
- }
-
- static char charshape(char s, int which)
- /* which 0=isolated 1=final 2=initial 3=medial */
- {
- int l, r, m;
- if ((s >= 0x0621) && (s <= 0x06D3)) {
- l = 0;
- r = chartable.length - 1;
- while (l <= r) {
- m = (l + r) / 2;
- if (s == chartable[m][0]) {
- return chartable[m][which + 1];
- }
- else if (s < chartable[m][0]) {
- r = m - 1;
- }
- else {
- l = m + 1;
- }
- }
- }
- else if (s >= 0xfef5 && s <= 0xfefb)
- return (char)(s + which);
- return s;
- }
-
- static int shapecount(char s) {
- int l, r, m;
- if ((s >= 0x0621) && (s <= 0x06D3) && !isVowel(s)) {
- l = 0;
- r = chartable.length - 1;
- while (l <= r) {
- m = (l + r) / 2;
- if (s == chartable[m][0]) {
- return chartable[m].length - 1;
- }
- else if (s < chartable[m][0]) {
- r = m - 1;
- }
- else {
- l = m + 1;
- }
- }
- }
- else if (s == ZWJ) {
- return 4;
- }
- return 1;
- }
-
- static int ligature(char newchar, charstruct oldchar) {
- /* 0 == no ligature possible; 1 == vowel; 2 == two chars; 3 == Lam+Alef */
- int retval = 0;
-
- if (oldchar.basechar == 0)
- return 0;
- if (isVowel(newchar)) {
- retval = 1;
- if ((oldchar.vowel != 0) && (newchar != SHADDA)) {
- retval = 2; /* we eliminate the old vowel .. */
- }
- switch (newchar) {
- case SHADDA:
- if (oldchar.mark1 == 0) {
- oldchar.mark1 = SHADDA;
- }
- else {
- return 0; /* no ligature possible */
- }
- break;
- case HAMZABELOW:
- switch (oldchar.basechar) {
- case ALEF:
- oldchar.basechar = ALEFHAMZABELOW;
- retval = 2;
- break;
- case LAM_ALEF:
- oldchar.basechar = LAM_ALEFHAMZABELOW;
- retval = 2;
- break;
- default:
- oldchar.mark1 = HAMZABELOW;
- break;
- }
- break;
- case HAMZAABOVE:
- switch (oldchar.basechar) {
- case ALEF:
- oldchar.basechar = ALEFHAMZA;
- retval = 2;
- break;
- case LAM_ALEF:
- oldchar.basechar = LAM_ALEFHAMZA;
- retval = 2;
- break;
- case WAW:
- oldchar.basechar = WAWHAMZA;
- retval = 2;
- break;
- case YEH:
- case ALEFMAKSURA:
- case FARSIYEH:
- oldchar.basechar = YEHHAMZA;
- retval = 2;
- break;
- default: /* whatever sense this may make .. */
- oldchar.mark1 = HAMZAABOVE;
- break;
- }
- break;
- case MADDA:
- switch (oldchar.basechar) {
- case ALEF:
- oldchar.basechar = ALEFMADDA;
- retval = 2;
- break;
- }
- break;
- default:
- oldchar.vowel = newchar;
- break;
- }
- if (retval == 1) {
- oldchar.lignum++;
- }
- return retval;
- }
- if (oldchar.vowel != 0) { /* if we already joined a vowel, we can't join a Hamza */
- return 0;
- }
-
- switch (oldchar.basechar) {
- case LAM:
- switch (newchar) {
- case ALEF:
- oldchar.basechar = LAM_ALEF;
- oldchar.numshapes = 2;
- retval = 3;
- break;
- case ALEFHAMZA:
- oldchar.basechar = LAM_ALEFHAMZA;
- oldchar.numshapes = 2;
- retval = 3;
- break;
- case ALEFHAMZABELOW:
- oldchar.basechar = LAM_ALEFHAMZABELOW;
- oldchar.numshapes = 2;
- retval = 3;
- break;
- case ALEFMADDA:
- oldchar.basechar = LAM_ALEFMADDA;
- oldchar.numshapes = 2;
- retval = 3;
- break;
- }
- break;
- case 0:
- oldchar.basechar = newchar;
- oldchar.numshapes = shapecount(newchar);
- retval = 1;
- break;
- }
- return retval;
- }
-
- static void copycstostring(StringBuffer string, charstruct s, int level) {
- /* s is a shaped charstruct; i is the index into the string */
- if (s.basechar == 0)
- return;
-
- string.append(s.basechar);
- s.lignum--;
- if (s.mark1 != 0) {
- if ((level & ar_novowel) == 0) {
- string.append(s.mark1);
- s.lignum--;
- }
- else {
- s.lignum--;
- }
- }
- if (s.vowel != 0) {
- if ((level & ar_novowel) == 0) {
- string.append(s.vowel);
- s.lignum--;
- }
- else { /* vowel elimination */
- s.lignum--;
- }
- }
-// while (s.lignum > 0) { /* NULL-insertion for Langbox-font */
-// string[i] = 0;
-// i++;
-// (s.lignum)--;
-// }
-// return i;
- }
-
- // return len
- static void doublelig(StringBuffer string, int level)
- /* Ok. We have presentation ligatures in our font. */
- {
- int len;
- int olen = len = string.length();
- int j = 0, si = 1;
- char lapresult;
-
- while (si < olen) {
- lapresult = 0;
- if ((level & ar_composedtashkeel) != 0) {
- switch (string.charAt(j)) {
- case SHADDA:
- switch (string.charAt(si)) {
- case KASRA:
- lapresult = 0xFC62;
- break;
- case FATHA:
- lapresult = 0xFC60;
- break;
- case DAMMA:
- lapresult = 0xFC61;
- break;
- case 0x064C:
- lapresult = 0xFC5E;
- break;
- case 0x064D:
- lapresult = 0xFC5F;
- break;
- }
- break;
- case KASRA:
- if (string.charAt(si) == SHADDA)
- lapresult = 0xFC62;
- break;
- case FATHA:
- if (string.charAt(si) == SHADDA)
- lapresult = 0xFC60;
- break;
- case DAMMA:
- if (string.charAt(si) == SHADDA)
- lapresult = 0xFC61;
- break;
- }
- }
-
- if ((level & ar_lig) != 0) {
- switch (string.charAt(j)) {
- case 0xFEDF: /* LAM initial */
- switch (string.charAt(si)) {
- case 0xFE9E:
- lapresult = 0xFC3F;
- break; /* JEEM final */
- case 0xFEA0:
- lapresult = 0xFCC9;
- break; /* JEEM medial */
- case 0xFEA2:
- lapresult = 0xFC40;
- break; /* HAH final */
- case 0xFEA4:
- lapresult = 0xFCCA;
- break; /* HAH medial */
- case 0xFEA6:
- lapresult = 0xFC41;
- break; /* KHAH final */
- case 0xFEA8:
- lapresult = 0xFCCB;
- break; /* KHAH medial */
- case 0xFEE2:
- lapresult = 0xFC42;
- break; /* MEEM final */
- case 0xFEE4:
- lapresult = 0xFCCC;
- break; /* MEEM medial */
- }
- break;
- case 0xFE97: /* TEH inital */
- switch (string.charAt(si)) {
- case 0xFEA0:
- lapresult = 0xFCA1;
- break; /* JEEM medial */
- case 0xFEA4:
- lapresult = 0xFCA2;
- break; /* HAH medial */
- case 0xFEA8:
- lapresult = 0xFCA3;
- break; /* KHAH medial */
- }
- break;
- case 0xFE91: /* BEH inital */
- switch (string.charAt(si)) {
- case 0xFEA0:
- lapresult = 0xFC9C;
- break; /* JEEM medial */
- case 0xFEA4:
- lapresult = 0xFC9D;
- break; /* HAH medial */
- case 0xFEA8:
- lapresult = 0xFC9E;
- break; /* KHAH medial */
- }
- break;
- case 0xFEE7: /* NOON inital */
- switch (string.charAt(si)) {
- case 0xFEA0:
- lapresult = 0xFCD2;
- break; /* JEEM initial */
- case 0xFEA4:
- lapresult = 0xFCD3;
- break; /* HAH medial */
- case 0xFEA8:
- lapresult = 0xFCD4;
- break; /* KHAH medial */
- }
- break;
-
- case 0xFEE8: /* NOON medial */
- switch (string.charAt(si)) {
- case 0xFEAE:
- lapresult = 0xFC8A;
- break; /* REH final */
- case 0xFEB0:
- lapresult = 0xFC8B;
- break; /* ZAIN final */
- }
- break;
- case 0xFEE3: /* MEEM initial */
- switch (string.charAt(si)) {
- case 0xFEA0:
- lapresult = 0xFCCE;
- break; /* JEEM medial */
- case 0xFEA4:
- lapresult = 0xFCCF;
- break; /* HAH medial */
- case 0xFEA8:
- lapresult = 0xFCD0;
- break; /* KHAH medial */
- case 0xFEE4:
- lapresult = 0xFCD1;
- break; /* MEEM medial */
- }
- break;
-
- case 0xFED3: /* FEH initial */
- switch (string.charAt(si)) {
- case 0xFEF2:
- lapresult = 0xFC32;
- break; /* YEH final */
- }
- break;
-
- default:
- break;
- } /* end switch string[si] */
- }
- if (lapresult != 0) {
- string.setCharAt(j, lapresult);
- len--;
- si++; /* jump over one character */
- /* we'll have to change this, too. */
- }
- else {
- j++;
- string.setCharAt(j, string.charAt(si));
- si++;
- }
- }
- string.setLength(len);
- }
-
- static boolean connects_to_left(charstruct a) {
- return a.numshapes > 2;
- }
-
- static void shape(char text[], StringBuffer string, int level) {
- /* string is assumed to be empty and big enough.
- * text is the original text.
- * This routine does the basic arabic reshaping.
- * *len the number of non-null characters.
- *
- * Note: We have to unshape each character first!
- */
- int join;
- int which;
- char nextletter;
-
- int p = 0; /* initialize for output */
- charstruct oldchar = new charstruct();
- charstruct curchar = new charstruct();
- while (p < text.length) {
- nextletter = text[p++];
- //nextletter = unshape (nextletter);
-
- join = ligature(nextletter, curchar);
- if (join == 0) { /* shape curchar */
- int nc = shapecount(nextletter);
- //(*len)++;
- if (nc == 1) {
- which = 0; /* final or isolated */
- }
- else {
- which = 2; /* medial or initial */
- }
- if (connects_to_left(oldchar)) {
- which++;
- }
-
- which = which % (curchar.numshapes);
- curchar.basechar = charshape(curchar.basechar, which);
-
- /* get rid of oldchar */
- copycstostring(string, oldchar, level);
- oldchar = curchar; /* new values in oldchar */
-
- /* init new curchar */
- curchar = new charstruct();
- curchar.basechar = nextletter;
- curchar.numshapes = nc;
- curchar.lignum++;
- // (*len) += unligature (&curchar, level);
- }
- else if (join == 1) {
- }
- // else
- // {
- // (*len) += unligature (&curchar, level);
- // }
- // p = g_utf8_next_char (p);
- }
-
- /* Handle last char */
- if (connects_to_left(oldchar))
- which = 1;
- else
- which = 0;
- which = which % (curchar.numshapes);
- curchar.basechar = charshape(curchar.basechar, which);
-
- /* get rid of oldchar */
- copycstostring(string, oldchar, level);
- copycstostring(string, curchar, level);
- }
-
- static int arabic_shape(char src[], int srcoffset, int srclength, char dest[], int destoffset, int destlength, int level) {
- char str[] = new char[srclength];
- for (int k = srclength + srcoffset - 1; k >= srcoffset; --k)
- str[k - srcoffset] = src[k];
- StringBuffer string = new StringBuffer(srclength);
- shape(str, string, level);
- if ((level & (ar_composedtashkeel | ar_lig)) != 0)
- doublelig(string, level);
-// string.reverse();
- System.arraycopy(string.toString().toCharArray(), 0, dest, destoffset, string.length());
- return string.length();
- }
-
- static void processNumbers(char text[], int offset, int length, int options) {
- int limit = offset + length;
- if ((options & DIGITS_MASK) != 0) {
- char digitBase = '\u0030'; // European digits
- switch (options & DIGIT_TYPE_MASK) {
- case DIGIT_TYPE_AN:
- digitBase = '\u0660'; // Arabic-Indic digits
- break;
-
- case DIGIT_TYPE_AN_EXTENDED:
- digitBase = '\u06f0'; // Eastern Arabic-Indic digits (Persian and Urdu)
- break;
-
- default:
- break;
- }
-
- switch (options & DIGITS_MASK) {
- case DIGITS_EN2AN: {
- int digitDelta = digitBase - '\u0030';
- for (int i = offset; i < limit; ++i) {
- char ch = text[i];
- if (ch <= '\u0039' && ch >= '\u0030') {
- text[i] += digitDelta;
- }
- }
- }
- break;
-
- case DIGITS_AN2EN: {
- char digitTop = (char)(digitBase + 9);
- int digitDelta = '\u0030' - digitBase;
- for (int i = offset; i < limit; ++i) {
- char ch = text[i];
- if (ch <= digitTop && ch >= digitBase) {
- text[i] += digitDelta;
- }
- }
- }
- break;
-
- case DIGITS_EN2AN_INIT_LR:
- shapeToArabicDigitsWithContext(text, 0, length, digitBase, false);
- break;
-
- case DIGITS_EN2AN_INIT_AL:
- shapeToArabicDigitsWithContext(text, 0, length, digitBase, true);
- break;
-
- default:
- break;
- }
- }
- }
-
- static void shapeToArabicDigitsWithContext(char[] dest, int start, int length, char digitBase, boolean lastStrongWasAL) {
- digitBase -= '0'; // move common adjustment out of loop
-
- int limit = start + length;
- for(int i = start; i < limit; ++i) {
- char ch = dest[i];
- switch (BidiOrder.getDirection(ch)) {
- case BidiOrder.L:
- case BidiOrder.R:
- lastStrongWasAL = false;
- break;
- case BidiOrder.AL:
- lastStrongWasAL = true;
- break;
- case BidiOrder.EN:
- if (lastStrongWasAL && ch <= '\u0039') {
- dest[i] = (char)(ch + digitBase);
- }
- break;
- default:
- break;
- }
- }
- }
-
- private static final char ALEF = 0x0627;
- private static final char ALEFHAMZA = 0x0623;
- private static final char ALEFHAMZABELOW = 0x0625;
- private static final char ALEFMADDA = 0x0622;
- private static final char LAM = 0x0644;
- private static final char HAMZA = 0x0621;
- private static final char TATWEEL = 0x0640;
- private static final char ZWJ = 0x200D;
-
- private static final char HAMZAABOVE = 0x0654;
- private static final char HAMZABELOW = 0x0655;
-
- private static final char WAWHAMZA = 0x0624;
- private static final char YEHHAMZA = 0x0626;
- private static final char WAW = 0x0648;
- private static final char ALEFMAKSURA = 0x0649;
- private static final char YEH = 0x064A;
- private static final char FARSIYEH = 0x06CC;
-
- private static final char SHADDA = 0x0651;
- private static final char KASRA = 0x0650;
- private static final char FATHA = 0x064E;
- private static final char DAMMA = 0x064F;
- private static final char MADDA = 0x0653;
-
- private static final char LAM_ALEF = 0xFEFB;
- private static final char LAM_ALEFHAMZA = 0xFEF7;
- private static final char LAM_ALEFHAMZABELOW = 0xFEF9;
- private static final char LAM_ALEFMADDA = 0xFEF5;
-
- private static final char chartable[][] = {
- {0x0621, 0xFE80}, /* HAMZA */
- {0x0622, 0xFE81, 0xFE82}, /* ALEF WITH MADDA ABOVE */
- {0x0623, 0xFE83, 0xFE84}, /* ALEF WITH HAMZA ABOVE */
- {0x0624, 0xFE85, 0xFE86}, /* WAW WITH HAMZA ABOVE */
- {0x0625, 0xFE87, 0xFE88}, /* ALEF WITH HAMZA BELOW */
- {0x0626, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C}, /* YEH WITH HAMZA ABOVE */
- {0x0627, 0xFE8D, 0xFE8E}, /* ALEF */
- {0x0628, 0xFE8F, 0xFE90, 0xFE91, 0xFE92}, /* BEH */
- {0x0629, 0xFE93, 0xFE94}, /* TEH MARBUTA */
- {0x062A, 0xFE95, 0xFE96, 0xFE97, 0xFE98}, /* TEH */
- {0x062B, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C}, /* THEH */
- {0x062C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0}, /* JEEM */
- {0x062D, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4}, /* HAH */
- {0x062E, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8}, /* KHAH */
- {0x062F, 0xFEA9, 0xFEAA}, /* DAL */
- {0x0630, 0xFEAB, 0xFEAC}, /* THAL */
- {0x0631, 0xFEAD, 0xFEAE}, /* REH */
- {0x0632, 0xFEAF, 0xFEB0}, /* ZAIN */
- {0x0633, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4}, /* SEEN */
- {0x0634, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8}, /* SHEEN */
- {0x0635, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC}, /* SAD */
- {0x0636, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0}, /* DAD */
- {0x0637, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4}, /* TAH */
- {0x0638, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8}, /* ZAH */
- {0x0639, 0xFEC9, 0xFECA, 0xFECB, 0xFECC}, /* AIN */
- {0x063A, 0xFECD, 0xFECE, 0xFECF, 0xFED0}, /* GHAIN */
- {0x0640, 0x0640, 0x0640, 0x0640, 0x0640}, /* TATWEEL */
- {0x0641, 0xFED1, 0xFED2, 0xFED3, 0xFED4}, /* FEH */
- {0x0642, 0xFED5, 0xFED6, 0xFED7, 0xFED8}, /* QAF */
- {0x0643, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC}, /* KAF */
- {0x0644, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0}, /* LAM */
- {0x0645, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4}, /* MEEM */
- {0x0646, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8}, /* NOON */
- {0x0647, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC}, /* HEH */
- {0x0648, 0xFEED, 0xFEEE}, /* WAW */
- {0x0649, 0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9}, /* ALEF MAKSURA */
- {0x064A, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4}, /* YEH */
- {0x0671, 0xFB50, 0xFB51}, /* ALEF WASLA */
- {0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69}, /* TTEH */
- {0x067A, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61}, /* TTEHEH */
- {0x067B, 0xFB52, 0xFB53, 0xFB54, 0xFB55}, /* BEEH */
- {0x067E, 0xFB56, 0xFB57, 0xFB58, 0xFB59}, /* PEH */
- {0x067F, 0xFB62, 0xFB63, 0xFB64, 0xFB65}, /* TEHEH */
- {0x0680, 0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D}, /* BEHEH */
- {0x0683, 0xFB76, 0xFB77, 0xFB78, 0xFB79}, /* NYEH */
- {0x0684, 0xFB72, 0xFB73, 0xFB74, 0xFB75}, /* DYEH */
- {0x0686, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D}, /* TCHEH */
- {0x0687, 0xFB7E, 0xFB7F, 0xFB80, 0xFB81}, /* TCHEHEH */
- {0x0688, 0xFB88, 0xFB89}, /* DDAL */
- {0x068C, 0xFB84, 0xFB85}, /* DAHAL */
- {0x068D, 0xFB82, 0xFB83}, /* DDAHAL */
- {0x068E, 0xFB86, 0xFB87}, /* DUL */
- {0x0691, 0xFB8C, 0xFB8D}, /* RREH */
- {0x0698, 0xFB8A, 0xFB8B}, /* JEH */
- {0x06A4, 0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D}, /* VEH */
- {0x06A6, 0xFB6E, 0xFB6F, 0xFB70, 0xFB71}, /* PEHEH */
- {0x06A9, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91}, /* KEHEH */
- {0x06AD, 0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6}, /* NG */
- {0x06AF, 0xFB92, 0xFB93, 0xFB94, 0xFB95}, /* GAF */
- {0x06B1, 0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D}, /* NGOEH */
- {0x06B3, 0xFB96, 0xFB97, 0xFB98, 0xFB99}, /* GUEH */
- {0x06BA, 0xFB9E, 0xFB9F}, /* NOON GHUNNA */
- {0x06BB, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3}, /* RNOON */
- {0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD}, /* HEH DOACHASHMEE */
- {0x06C0, 0xFBA4, 0xFBA5}, /* HEH WITH YEH ABOVE */
- {0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9}, /* HEH GOAL */
- {0x06C5, 0xFBE0, 0xFBE1}, /* KIRGHIZ OE */
- {0x06C6, 0xFBD9, 0xFBDA}, /* OE */
- {0x06C7, 0xFBD7, 0xFBD8}, /* U */
- {0x06C8, 0xFBDB, 0xFBDC}, /* YU */
- {0x06C9, 0xFBE2, 0xFBE3}, /* KIRGHIZ YU */
- {0x06CB, 0xFBDE, 0xFBDF}, /* VE */
- {0x06CC, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF}, /* FARSI YEH */
- {0x06D0, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7}, /* E */
- {0x06D2, 0xFBAE, 0xFBAF}, /* YEH BARREE */
- {0x06D3, 0xFBB0, 0xFBB1} /* YEH BARREE WITH HAMZA ABOVE */
- };
-
- public static final int ar_nothing = 0x0;
- public static final int ar_novowel = 0x1;
- public static final int ar_composedtashkeel = 0x4;
- public static final int ar_lig = 0x8;
- /**
- * Digit shaping option: Replace European digits (U+0030...U+0039) by Arabic-Indic digits.
- */
- public static final int DIGITS_EN2AN = 0x20;
-
- /**
- * Digit shaping option: Replace Arabic-Indic digits by European digits (U+0030...U+0039).
- */
- public static final int DIGITS_AN2EN = 0x40;
-
- /**
- * Digit shaping option:
- * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
- * if the most recent strongly directional character
- * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
- * The initial state at the start of the text is assumed to be not an Arabic,
- * letter, so European digits at the start of the text will not change.
- * Compare to DIGITS_ALEN2AN_INIT_AL.
- */
- public static final int DIGITS_EN2AN_INIT_LR = 0x60;
-
- /**
- * Digit shaping option:
- * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
- * if the most recent strongly directional character
- * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
- * The initial state at the start of the text is assumed to be an Arabic,
- * letter, so European digits at the start of the text will change.
- * Compare to DIGITS_ALEN2AN_INT_LR.
- */
- public static final int DIGITS_EN2AN_INIT_AL = 0x80;
-
- /** Not a valid option value. */
- private static final int DIGITS_RESERVED = 0xa0;
-
- /**
- * Bit mask for digit shaping options.
- */
- public static final int DIGITS_MASK = 0xe0;
-
- /**
- * Digit type option: Use Arabic-Indic digits (U+0660...U+0669).
- */
- public static final int DIGIT_TYPE_AN = 0;
-
- /**
- * Digit type option: Use Eastern (Extended) Arabic-Indic digits (U+06f0...U+06f9).
- */
- public static final int DIGIT_TYPE_AN_EXTENDED = 0x100;
-
- /**
- * Bit mask for digit type options.
- */
- public static final int DIGIT_TYPE_MASK = 0x0100; // 0x3f00?
-
- static class charstruct {
- char basechar;
- char mark1; /* has to be initialized to zero */
- char vowel;
- int lignum; /* is a ligature with lignum aditional characters */
- int numshapes = 1;
- };
-
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/AsianFontMapper.java pdftk-2.01/java/com/lowagie/text/pdf/AsianFontMapper.java
--- pdftk-1.45/java/com/lowagie/text/pdf/AsianFontMapper.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/AsianFontMapper.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright 2004 by Takenori.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.awt.Font;
-
-import com.lowagie.text.pdf.BaseFont;
-import com.lowagie.text.pdf.DefaultFontMapper;
-
-public class AsianFontMapper extends DefaultFontMapper {
-
- public static String ChineseSimplifiedFont = "STSong-Light";
- public static String ChineseSimplifiedEncoding_H = "UniGB-UCS2-H";
- public static String ChineseSimplifiedEncoding_V = "UniGB-UCS2-V";
-
- public static String ChineseTraditionalFont_MHei = "MHei-Medium";
- public static String ChineseTraditionalFont_MSung = "MSung-Light";
- public static String ChineseTraditionalEncoding_H = "UniCNS-UCS2-H";
- public static String ChineseTraditionalEncoding_V = "UniCNS-UCS2-V";
-
- public static String JapaneseFont_Go = "HeiseiKakuGo-W5";
- public static String JapaneseFont_Min = "HeiseiMin-W3";
- public static String JapaneseEncoding_H = "UniJIS-UCS2-H";
- public static String JapaneseEncoding_V = "UniJIS-UCS2-V";
- public static String JapaneseEncoding_HW_H = "UniJIS-UCS2-HW-H";
- public static String JapaneseEncoding_HW_V = "UniJIS-UCS2-HW-V";
-
- public static String KoreanFont_GoThic = "HYGoThic-Medium";
- public static String KoreanFont_SMyeongJo = "HYSMyeongJo-Medium";
- public static String KoreanEncoding_H = "UniKS-UCS2-H";
- public static String KoreanEncoding_V = "UniKS-UCS2-V";
-
- private String defaultFont;
- private String encoding;
-
- public AsianFontMapper(String font, String encoding) {
- super();
-
- this.defaultFont = font;
- this.encoding = encoding;
- }
-
- public BaseFont awtToPdf(Font font) {
- try {
- BaseFontParameters p = getBaseFontParameters(font.getFontName());
- if (p != null){
- return BaseFont.createFont(p.fontName, p.encoding, p.embedded, p.cached, p.ttfAfm, p.pfb);
- }else{
- return BaseFont.createFont(defaultFont, encoding, true);
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- return null;
-
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/BadPdfFormatException.java pdftk-2.01/java/com/lowagie/text/pdf/BadPdfFormatException.java
--- pdftk-1.45/java/com/lowagie/text/pdf/BadPdfFormatException.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/BadPdfFormatException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,92 +0,0 @@
-/*
- * $Id: BadPdfFormatException.java,v 1.22 2002/06/18 13:59:39 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * Signals that a bad PDF format has been used to construct a PdfObject
.
- *
- * @see PdfException
- * @see PdfBoolean
- * @see PdfNumber
- * @see PdfString
- * @see PdfName
- * @see PdfDictionary
- * @see PdfFont
- */
-
-public class BadPdfFormatException extends PdfException {
-
- // constructors
-
-/**
- * Constructs a BadPdfFormatException
whithout a message.
- */
-
- BadPdfFormatException() {
- super();
- }
-
-/**
- * Constructs a BadPdfFormatException
with a message.
- *
- * @param message a message describing the exception
- */
-
- BadPdfFormatException(String message) {
- super(message);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/Barcode.java pdftk-2.01/java/com/lowagie/text/pdf/Barcode.java
--- pdftk-1.45/java/com/lowagie/text/pdf/Barcode.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/Barcode.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,460 +0,0 @@
-/*
- * Copyright 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.Rectangle;
-// import com.lowagie.text.Image; ssteward: dropped in 1.44
-import java.awt.Color;
-/** Base class containing properties and methods commom to all
- * barcode types.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public abstract class Barcode {
- /** A type of barcode */
- public static final int EAN13 = 1;
- /** A type of barcode */
- public static final int EAN8 = 2;
- /** A type of barcode */
- public static final int UPCA = 3;
- /** A type of barcode */
- public static final int UPCE = 4;
- /** A type of barcode */
- public static final int SUPP2 = 5;
- /** A type of barcode */
- public static final int SUPP5 = 6;
- /** A type of barcode */
- public static final int POSTNET = 7;
- /** A type of barcode */
- public static final int PLANET = 8;
- /** A type of barcode */
- public static final int CODE128 = 9;
- /** A type of barcode */
- public static final int CODE128_UCC = 10;
- /** A type of barcode */
- public static final int CODE128_RAW = 11;
- /** A type of barcode */
- public static final int CODABAR = 12;
-
- /** The minimum bar width.
- */
- protected float x;
-
- /** The bar multiplier for wide bars or the distance between
- * bars for Postnet and Planet.
- */
- protected float n;
-
- /** The text font. null
if no text.
- */
- protected BaseFont font;
-
- /** The size of the text or the height of the shorter bar
- * in Postnet.
- */
- protected float size;
-
- /** If positive, the text distance under the bars. If zero or negative,
- * the text distance above the bars.
- */
- protected float baseline;
-
- /** The height of the bars.
- */
- protected float barHeight;
-
- /** The text alignment. Can be Element.ALIGN_LEFT
,
- * Element.ALIGN_CENTER
or Element.ALIGN_RIGHT
.
- */
- protected int textAlignment;
-
- /** The optional checksum generation.
- */
- protected boolean generateChecksum;
-
- /** Shows the generated checksum in the the text.
- */
- protected boolean checksumText;
-
- /** Show the start and stop character '*' in the text for
- * the barcode 39 or 'ABCD' for codabar.
- */
- protected boolean startStopText;
-
- /** Generates extended barcode 39.
- */
- protected boolean extended;
-
- /** The code to generate.
- */
- protected String code = "";
-
- /** Show the guard bars for barcode EAN.
- */
- protected boolean guardBars;
-
- /** The code type.
- */
- protected int codeType;
-
- /** The ink spreading. */
- protected float inkSpreading = 0;
-
- /** Gets the minimum bar width.
- * @return the minimum bar width
- */
- public float getX() {
- return x;
- }
-
- /** Sets the minimum bar width.
- * @param x the minimum bar width
- */
- public void setX(float x) {
- this.x = x;
- }
-
- /** Gets the bar multiplier for wide bars.
- * @return the bar multiplier for wide bars
- */
- public float getN() {
- return n;
- }
-
- /** Sets the bar multiplier for wide bars.
- * @param n the bar multiplier for wide bars
- */
- public void setN(float n) {
- this.n = n;
- }
-
- /** Gets the text font. null
if no text.
- * @return the text font. null
if no text
- */
- public BaseFont getFont() {
- return font;
- }
-
- /** Sets the text font.
- * @param font the text font. Set to null
to suppress any text
- */
- public void setFont(BaseFont font) {
- this.font = font;
- }
-
- /** Gets the size of the text.
- * @return the size of the text
- */
- public float getSize() {
- return size;
- }
-
- /** Sets the size of the text.
- * @param size the size of the text
- */
- public void setSize(float size) {
- this.size = size;
- }
-
- /** Gets the text baseline.
- * If positive, the text distance under the bars. If zero or negative,
- * the text distance above the bars.
- * @return the baseline.
- */
- public float getBaseline() {
- return baseline;
- }
-
- /** Sets the text baseline.
- * If positive, the text distance under the bars. If zero or negative,
- * the text distance above the bars.
- * @param baseline the baseline.
- */
- public void setBaseline(float baseline) {
- this.baseline = baseline;
- }
-
- /** Gets the height of the bars.
- * @return the height of the bars
- */
- public float getBarHeight() {
- return barHeight;
- }
-
- /** Sets the height of the bars.
- * @param barHeight the height of the bars
- */
- public void setBarHeight(float barHeight) {
- this.barHeight = barHeight;
- }
-
- /** Gets the text alignment. Can be Element.ALIGN_LEFT
,
- * Element.ALIGN_CENTER
or Element.ALIGN_RIGHT
.
- * @return the text alignment
- */
- public int getTextAlignment() {
- return textAlignment;
- }
-
- /** Sets the text alignment. Can be Element.ALIGN_LEFT
,
- * Element.ALIGN_CENTER
or Element.ALIGN_RIGHT
.
- * @param textAlignment the text alignment
- */
- public void setTextAlignment(int textAlignment) {
- this.textAlignment = textAlignment;
- }
-
- /** Gets the optional checksum generation.
- * @return the optional checksum generation
- */
- public boolean isGenerateChecksum() {
- return generateChecksum;
- }
-
- /** Setter for property generateChecksum.
- * @param generateChecksum New value of property generateChecksum.
- */
- public void setGenerateChecksum(boolean generateChecksum) {
- this.generateChecksum = generateChecksum;
- }
-
- /** Gets the property to show the generated checksum in the the text.
- * @return value of property checksumText
- */
- public boolean isChecksumText() {
- return checksumText;
- }
-
- /** Sets the property to show the generated checksum in the the text.
- * @param checksumText new value of property checksumText
- */
- public void setChecksumText(boolean checksumText) {
- this.checksumText = checksumText;
- }
-
- /** Sets the property to show the start and stop character '*' in the text for
- * the barcode 39.
- * @return value of property startStopText
- */
- public boolean isStartStopText() {
- return startStopText;
- }
-
- /** Gets the property to show the start and stop character '*' in the text for
- * the barcode 39.
- * @param startStopText new value of property startStopText
- */
- public void setStartStopText(boolean startStopText) {
- this.startStopText = startStopText;
- }
-
- /** Gets the property to generate extended barcode 39.
- * @return value of property extended.
- */
- public boolean isExtended() {
- return extended;
- }
-
- /** Sets the property to generate extended barcode 39.
- * @param extended new value of property extended
- */
- public void setExtended(boolean extended) {
- this.extended = extended;
- }
-
- /** Gets the code to generate.
- * @return the code to generate
- */
- public String getCode() {
- return code;
- }
-
- /** Sets the code to generate.
- * @param code the code to generate
- */
- public void setCode(String code) {
- this.code = code;
- }
-
- /** Gets the property to show the guard bars for barcode EAN.
- * @return value of property guardBars
- */
- public boolean isGuardBars() {
- return guardBars;
- }
-
- /** Sets the property to show the guard bars for barcode EAN.
- * @param guardBars new value of property guardBars
- */
- public void setGuardBars(boolean guardBars) {
- this.guardBars = guardBars;
- }
-
- /** Gets the code type.
- * @return the code type
- */
- public int getCodeType() {
- return codeType;
- }
-
- /** Sets the code type.
- * @param codeType the code type
- */
- public void setCodeType(int codeType) {
- this.codeType = codeType;
- }
-
- /** Gets the maximum area that the barcode and the text, if
- * any, will occupy. The lower left corner is always (0, 0).
- * @return the size the barcode occupies.
- */
- public abstract Rectangle getBarcodeSize();
-
- /** Places the barcode in a PdfContentByte
. The
- * barcode is always placed at coodinates (0, 0). Use the
- * translation matrix to move it elsewhere.
- * The bars and text are written in the following colors:
- *
- *
- * barColor
- * textColor
- * Result
- *
- *
- * null
- * null
- * bars and text painted with current fill color
- *
- *
- * barColor
- * null
- * bars and text painted with barColor
- *
- *
- * null
- * textColor
- * bars painted with current color text painted with textColor
- *
- *
- * barColor
- * textColor
- * bars painted with barColor
text painted with textColor
- *
- *
- * @param cb the PdfContentByte
where the barcode will be placed
- * @param barColor the color of the bars. It can be null
- * @param textColor the color of the text. It can be null
- * @return the dimensions the barcode occupies
- */
- public abstract Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor);
-
- /** Creates a template with the barcode.
- * @param cb the PdfContentByte
to create the template. It
- * serves no other use
- * @param barColor the color of the bars. It can be null
- * @param textColor the color of the text. It can be null
- * @return the template
- * @see #placeBarcode(PdfContentByte cb, Color barColor, Color textColor)
- */
- public PdfTemplate createTemplateWithBarcode(PdfContentByte cb, Color barColor, Color textColor) {
- PdfTemplate tp = cb.createTemplate(0, 0);
- Rectangle rect = placeBarcode(tp, barColor, textColor);
- tp.setBoundingBox(rect);
- return tp;
- }
-
- /** Creates an Image
with the barcode.
- * @param cb the PdfContentByte
to create the Image
. It
- * serves no other use
- * @param barColor the color of the bars. It can be null
- * @param textColor the color of the text. It can be null
- * @return the Image
- * @see #placeBarcode(PdfContentByte cb, Color barColor, Color textColor)
- */
- /* ssteward: dropped in 1.44
- public Image createImageWithBarcode(PdfContentByte cb, Color barColor, Color textColor) {
- try {
- return Image.getInstance(createTemplateWithBarcode(cb, barColor, textColor));
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
- */
-
- /** Creates a java.awt.Image
. This image only
- * contains the bars without any text.
- * @param foreground the color of the bars
- * @param background the color of the background
- * @return the image
- */
- public abstract java.awt.Image createAwtImage(Color foreground, Color background);
-
- /** Gets the amount of ink spreading.
- * @return the ink spreading
- *
- */
- public float getInkSpreading() {
- return this.inkSpreading;
- }
-
- /** Sets the amount of ink spreading. This value will be subtracted
- * to the width of each bar. The actual value will depend on the ink
- * and the printing medium.
- * @param inkSpreading the ink spreading
- *
- */
- public void setInkSpreading(float inkSpreading) {
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/Barcode128.java pdftk-2.01/java/com/lowagie/text/pdf/Barcode128.java
--- pdftk-1.45/java/com/lowagie/text/pdf/Barcode128.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/Barcode128.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,829 +0,0 @@
-/*
- * Copyright 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-import com.lowagie.text.Rectangle;
-import com.lowagie.text.Element;
-import com.lowagie.text.ExceptionConverter;
-import java.awt.Color;
-import java.awt.Image;
-import java.awt.Canvas;
-import java.awt.image.MemoryImageSource;
-
-/**
- * Implements the code 128 and UCC/EAN-128. Other symbologies are allowed in raw mode.
- * The code types allowed are:
- *
- * CODE128 - plain barcode 128.
- * CODE128_UCC - support for UCC/EAN-128 with a full list of AI.
- * CODE128_RAW - raw mode. The code attribute has the actual codes from 0
- * to 105 followed by '\uffff' and the human readable text.
- *
- * The default parameters are:
- *
- * x = 0.8f;
- * font = BaseFont.createFont("Helvetica", "winansi", false);
- * size = 8;
- * baseline = size;
- * barHeight = size * 3;
- * textAlignment = Element.ALIGN_CENTER;
- * codeType = CODE128;
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class Barcode128 extends Barcode{
-
- /** The bars to generate the code.
- */
- static byte BARS[][] =
- {
- {2, 1, 2, 2, 2, 2},
- {2, 2, 2, 1, 2, 2},
- {2, 2, 2, 2, 2, 1},
- {1, 2, 1, 2, 2, 3},
- {1, 2, 1, 3, 2, 2},
- {1, 3, 1, 2, 2, 2},
- {1, 2, 2, 2, 1, 3},
- {1, 2, 2, 3, 1, 2},
- {1, 3, 2, 2, 1, 2},
- {2, 2, 1, 2, 1, 3},
- {2, 2, 1, 3, 1, 2},
- {2, 3, 1, 2, 1, 2},
- {1, 1, 2, 2, 3, 2},
- {1, 2, 2, 1, 3, 2},
- {1, 2, 2, 2, 3, 1},
- {1, 1, 3, 2, 2, 2},
- {1, 2, 3, 1, 2, 2},
- {1, 2, 3, 2, 2, 1},
- {2, 2, 3, 2, 1, 1},
- {2, 2, 1, 1, 3, 2},
- {2, 2, 1, 2, 3, 1},
- {2, 1, 3, 2, 1, 2},
- {2, 2, 3, 1, 1, 2},
- {3, 1, 2, 1, 3, 1},
- {3, 1, 1, 2, 2, 2},
- {3, 2, 1, 1, 2, 2},
- {3, 2, 1, 2, 2, 1},
- {3, 1, 2, 2, 1, 2},
- {3, 2, 2, 1, 1, 2},
- {3, 2, 2, 2, 1, 1},
- {2, 1, 2, 1, 2, 3},
- {2, 1, 2, 3, 2, 1},
- {2, 3, 2, 1, 2, 1},
- {1, 1, 1, 3, 2, 3},
- {1, 3, 1, 1, 2, 3},
- {1, 3, 1, 3, 2, 1},
- {1, 1, 2, 3, 1, 3},
- {1, 3, 2, 1, 1, 3},
- {1, 3, 2, 3, 1, 1},
- {2, 1, 1, 3, 1, 3},
- {2, 3, 1, 1, 1, 3},
- {2, 3, 1, 3, 1, 1},
- {1, 1, 2, 1, 3, 3},
- {1, 1, 2, 3, 3, 1},
- {1, 3, 2, 1, 3, 1},
- {1, 1, 3, 1, 2, 3},
- {1, 1, 3, 3, 2, 1},
- {1, 3, 3, 1, 2, 1},
- {3, 1, 3, 1, 2, 1},
- {2, 1, 1, 3, 3, 1},
- {2, 3, 1, 1, 3, 1},
- {2, 1, 3, 1, 1, 3},
- {2, 1, 3, 3, 1, 1},
- {2, 1, 3, 1, 3, 1},
- {3, 1, 1, 1, 2, 3},
- {3, 1, 1, 3, 2, 1},
- {3, 3, 1, 1, 2, 1},
- {3, 1, 2, 1, 1, 3},
- {3, 1, 2, 3, 1, 1},
- {3, 3, 2, 1, 1, 1},
- {3, 1, 4, 1, 1, 1},
- {2, 2, 1, 4, 1, 1},
- {4, 3, 1, 1, 1, 1},
- {1, 1, 1, 2, 2, 4},
- {1, 1, 1, 4, 2, 2},
- {1, 2, 1, 1, 2, 4},
- {1, 2, 1, 4, 2, 1},
- {1, 4, 1, 1, 2, 2},
- {1, 4, 1, 2, 2, 1},
- {1, 1, 2, 2, 1, 4},
- {1, 1, 2, 4, 1, 2},
- {1, 2, 2, 1, 1, 4},
- {1, 2, 2, 4, 1, 1},
- {1, 4, 2, 1, 1, 2},
- {1, 4, 2, 2, 1, 1},
- {2, 4, 1, 2, 1, 1},
- {2, 2, 1, 1, 1, 4},
- {4, 1, 3, 1, 1, 1},
- {2, 4, 1, 1, 1, 2},
- {1, 3, 4, 1, 1, 1},
- {1, 1, 1, 2, 4, 2},
- {1, 2, 1, 1, 4, 2},
- {1, 2, 1, 2, 4, 1},
- {1, 1, 4, 2, 1, 2},
- {1, 2, 4, 1, 1, 2},
- {1, 2, 4, 2, 1, 1},
- {4, 1, 1, 2, 1, 2},
- {4, 2, 1, 1, 1, 2},
- {4, 2, 1, 2, 1, 1},
- {2, 1, 2, 1, 4, 1},
- {2, 1, 4, 1, 2, 1},
- {4, 1, 2, 1, 2, 1},
- {1, 1, 1, 1, 4, 3},
- {1, 1, 1, 3, 4, 1},
- {1, 3, 1, 1, 4, 1},
- {1, 1, 4, 1, 1, 3},
- {1, 1, 4, 3, 1, 1},
- {4, 1, 1, 1, 1, 3},
- {4, 1, 1, 3, 1, 1},
- {1, 1, 3, 1, 4, 1},
- {1, 1, 4, 1, 3, 1},
- {3, 1, 1, 1, 4, 1},
- {4, 1, 1, 1, 3, 1},
- {2, 1, 1, 4, 1, 2},
- {2, 1, 1, 2, 1, 4},
- {2, 1, 1, 2, 3, 2}
- };
-
- /** The stop bars.
- */
- static byte BARS_STOP[] = {2, 3, 3, 1, 1, 1, 2};
- /** The charset code change.
- */
- public static final char CODE_AB_TO_C = 99;
- /** The charset code change.
- */
- public static final char CODE_AC_TO_B = 100;
- /** The charset code change.
- */
- public static final char CODE_BC_TO_A = 101;
- /** The code for UCC/EAN-128.
- */
- public static final char FNC1_INDEX = 102;
- /** The start code.
- */
- public static final char START_A = 103;
- /** The start code.
- */
- public static final char START_B = 104;
- /** The start code.
- */
- public static final char START_C = 105;
-
- public static final char FNC1 = '\u00ca';
- public static final char DEL = '\u00c3';
- public static final char FNC3 = '\u00c4';
- public static final char FNC2 = '\u00c5';
- public static final char SHIFT = '\u00c6';
- public static final char CODE_C = '\u00c7';
- public static final char CODE_A = '\u00c8';
- public static final char FNC4 = '\u00c8';
- public static final char STARTA = '\u00cb';
- public static final char STARTB = '\u00cc';
- public static final char STARTC = '\u00cd';
-
- private static final IntHashtable ais = new IntHashtable();
- /** Creates new Barcode128 */
- public Barcode128() {
- try {
- x = 0.8f;
- font = BaseFont.createFont("Helvetica", "winansi", false);
- size = 8;
- baseline = size;
- barHeight = size * 3;
- textAlignment = Element.ALIGN_CENTER;
- codeType = CODE128;
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Removes the FNC1 codes in the text.
- * @param code the text to clean
- * @return the cleaned text
- */
- public static String removeFNC1(String code) {
- int len = code.length();
- StringBuffer buf = new StringBuffer(len);
- for (int k = 0; k < len; ++k) {
- char c = code.charAt(k);
- if (c >= 32 && c <= 126)
- buf.append(c);
- }
- return buf.toString();
- }
-
- /**
- * Gets the human readable text of a sequence of AI.
- * @param code the text
- * @return the human readable text
- */
- public static String getHumanReadableUCCEAN(String code) {
- StringBuffer buf = new StringBuffer();
- String fnc1 = String.valueOf(FNC1);
- try {
- while (true) {
- if (code.startsWith(fnc1)) {
- code = code.substring(1);
- continue;
- }
- int n = 0;
- int idlen = 0;
- for (int k = 2; k < 5; ++k) {
- if (code.length() < k)
- break;
- if ((n = ais.get(Integer.parseInt(code.substring(0, k)))) != 0) {
- idlen = k;
- break;
- }
- }
- if (idlen == 0)
- break;
- buf.append('(').append(code.substring(0, idlen)).append(')');
- code = code.substring(idlen);
- if (n > 0) {
- n -= idlen;
- if (code.length() <= n)
- break;
- buf.append(removeFNC1(code.substring(0, n)));
- code = code.substring(n);
- }
- else {
- int idx = code.indexOf(FNC1);
- if (idx < 0)
- break;
- buf.append(code.substring(0,idx));
- code = code.substring(idx + 1);
- }
- }
- }
- catch (Exception e) {
- //empty
- }
- buf.append(removeFNC1(code));
- return buf.toString();
- }
-
- /** Returns true
if the next numDigits
- * starting from index textIndex
are numeric skipping any FNC1.
- * @param text the text to check
- * @param textIndex where to check from
- * @param numDigits the number of digits to check
- * @return the check result
- */
- static boolean isNextDigits(String text, int textIndex, int numDigits) {
- int len = text.length();
- while (textIndex < len && numDigits > 0) {
- if (text.charAt(textIndex) == FNC1) {
- ++textIndex;
- continue;
- }
- int n = Math.min(2, numDigits);
- if (textIndex + n > len)
- return false;
- while (n-- > 0) {
- char c = text.charAt(textIndex++);
- if (c < '0' || c > '9')
- return false;
- --numDigits;
- }
- }
- return numDigits == 0;
- }
-
- /** Packs the digits for charset C also considering FNC1. It assumes that all the parameters
- * are valid.
- * @param text the text to pack
- * @param textIndex where to pack from
- * @param numDigits the number of digits to pack. It is always an even number
- * @return the packed digits, two digits per character
- */
- static String getPackedRawDigits(String text, int textIndex, int numDigits) {
- String out = "";
- int start = textIndex;
- while (numDigits > 0) {
- if (text.charAt(textIndex) == FNC1) {
- out += FNC1_INDEX;
- ++textIndex;
- continue;
- }
- numDigits -= 2;
- int c1 = text.charAt(textIndex++) - '0';
- int c2 = text.charAt(textIndex++) - '0';
- out += (char)(c1 * 10 + c2);
- }
- return (char)(textIndex - start) + out;
- }
-
- /** Converts the human readable text to the characters needed to
- * create a barcode. Some optimization is done to get the shortest code.
- * @param text the text to convert
- * @param ucc true
if it is an UCC/EAN-128. In this case
- * the character FNC1 is added
- * @return the code ready to be fed to getBarsCode128Raw()
- */
- public static String getRawText(String text, boolean ucc) {
- String out = "";
- int tLen = text.length();
- if (tLen == 0) {
- out += START_B;
- if (ucc)
- out += FNC1_INDEX;
- return out;
- }
- int c = 0;
- for (int k = 0; k < tLen; ++k) {
- c = text.charAt(k);
- if (c > 127 && c != FNC1)
- throw new RuntimeException("There are illegal characters for barcode 128 in '" + text + "'.");
- }
- c = text.charAt(0);
- char currentCode = START_B;
- int index = 0;
- if (isNextDigits(text, index, 2)) {
- currentCode = START_C;
- out += currentCode;
- if (ucc)
- out += FNC1_INDEX;
- String out2 = getPackedRawDigits(text, index, 2);
- index += (int)out2.charAt(0);
- out += out2.substring(1);
- }
- else if (c < ' ') {
- currentCode = START_A;
- out += currentCode;
- if (ucc)
- out += FNC1_INDEX;
- out += (char)(c + 64);
- ++index;
- }
- else {
- out += currentCode;
- if (ucc)
- out += FNC1_INDEX;
- if (c == FNC1)
- out += FNC1_INDEX;
- else
- out += (char)(c - ' ');
- ++index;
- }
- while (index < tLen) {
- switch (currentCode) {
- case START_A:
- {
- if (isNextDigits(text, index, 4)) {
- currentCode = START_C;
- out += CODE_AB_TO_C;
- String out2 = getPackedRawDigits(text, index, 4);
- index += (int)out2.charAt(0);
- out += out2.substring(1);
- }
- else {
- c = text.charAt(index++);
- if (c == FNC1)
- out += FNC1_INDEX;
- else if (c > '_') {
- currentCode = START_B;
- out += CODE_AC_TO_B;
- out += (char)(c - ' ');
- }
- else if (c < ' ')
- out += (char)(c + 64);
- else
- out += (char)(c - ' ');
- }
- }
- break;
- case START_B:
- {
- if (isNextDigits(text, index, 4)) {
- currentCode = START_C;
- out += CODE_AB_TO_C;
- String out2 = getPackedRawDigits(text, index, 4);
- index += (int)out2.charAt(0);
- out += out2.substring(1);
- }
- else {
- c = text.charAt(index++);
- if (c == FNC1)
- out += FNC1_INDEX;
- else if (c < ' ') {
- currentCode = START_A;
- out += CODE_BC_TO_A;
- out += (char)(c + 64);
- }
- else {
- out += (char)(c - ' ');
- }
- }
- }
- break;
- case START_C:
- {
- if (isNextDigits(text, index, 2)) {
- String out2 = getPackedRawDigits(text, index, 2);
- index += (int)out2.charAt(0);
- out += out2.substring(1);
- }
- else {
- c = text.charAt(index++);
- if (c == FNC1)
- out += FNC1_INDEX;
- else if (c < ' ') {
- currentCode = START_A;
- out += CODE_BC_TO_A;
- out += (char)(c + 64);
- }
- else {
- currentCode = START_B;
- out += CODE_AC_TO_B;
- out += (char)(c - ' ');
- }
- }
- }
- break;
- }
- }
- return out;
- }
-
- /** Generates the bars. The input has the actual barcodes, not
- * the human readable text.
- * @param text the barcode
- * @return the bars
- */
- public static byte[] getBarsCode128Raw(String text) {
- int idx = text.indexOf('\uffff');
- if (idx >= 0)
- text = text.substring(0, idx);
- int chk = text.charAt(0);
- for (int k = 1; k < text.length(); ++k)
- chk += k * text.charAt(k);
- chk = chk % 103;
- text += (char)chk;
- byte bars[] = new byte[(text.length() + 1) * 6 + 7];
- int k;
- for (k = 0; k < text.length(); ++k)
- System.arraycopy(BARS[text.charAt(k)], 0, bars, k * 6, 6);
- System.arraycopy(BARS_STOP, 0, bars, k * 6, 7);
- return bars;
- }
-
- /** Gets the maximum area that the barcode and the text, if
- * any, will occupy. The lower left corner is always (0, 0).
- * @return the size the barcode occupies.
- */
- public Rectangle getBarcodeSize() {
- float fontX = 0;
- float fontY = 0;
- String fullCode;
- if (font != null) {
- if (baseline > 0)
- fontY = baseline - font.getFontDescriptor(BaseFont.DESCENT, size);
- else
- fontY = -baseline + size;
- if (codeType == CODE128_RAW) {
- int idx = code.indexOf('\uffff');
- if (idx < 0)
- fullCode = "";
- else
- fullCode = code.substring(idx + 1);
- }
- else if (codeType == CODE128_UCC)
- fullCode = getHumanReadableUCCEAN(code);
- else
- fullCode = removeFNC1(code);
- fontX = font.getWidthPoint(fullCode, size);
- }
- if (codeType == CODE128_RAW) {
- int idx = code.indexOf('\uffff');
- if (idx >= 0)
- fullCode = code.substring(0, idx);
- else
- fullCode = code;
- }
- else {
- fullCode = getRawText(code, codeType == CODE128_UCC);
- }
- int len = fullCode.length();
- float fullWidth = (len + 2) * 11 * x + 2 * x;
- fullWidth = Math.max(fullWidth, fontX);
- float fullHeight = barHeight + fontY;
- return new Rectangle(fullWidth, fullHeight);
- }
-
- /** Places the barcode in a PdfContentByte
. The
- * barcode is always placed at coodinates (0, 0). Use the
- * translation matrix to move it elsewhere.
- * The bars and text are written in the following colors:
- *
- *
- * barColor
- * textColor
- * Result
- *
- *
- * null
- * null
- * bars and text painted with current fill color
- *
- *
- * barColor
- * null
- * bars and text painted with barColor
- *
- *
- * null
- * textColor
- * bars painted with current color text painted with textColor
- *
- *
- * barColor
- * textColor
- * bars painted with barColor
text painted with textColor
- *
- *
- * @param cb the PdfContentByte
where the barcode will be placed
- * @param barColor the color of the bars. It can be null
- * @param textColor the color of the text. It can be null
- * @return the dimensions the barcode occupies
- */
- public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
- String fullCode;
- if (codeType == CODE128_RAW) {
- int idx = code.indexOf('\uffff');
- if (idx < 0)
- fullCode = "";
- else
- fullCode = code.substring(idx + 1);
- }
- else if (codeType == CODE128_UCC)
- fullCode = getHumanReadableUCCEAN(code);
- else
- fullCode = removeFNC1(code);
- float fontX = 0;
- if (font != null) {
- fontX = font.getWidthPoint(fullCode, size);
- }
- String bCode;
- if (codeType == CODE128_RAW) {
- int idx = code.indexOf('\uffff');
- if (idx >= 0)
- bCode = code.substring(0, idx);
- else
- bCode = code;
- }
- else {
- bCode = getRawText(code, codeType == CODE128_UCC);
- }
- int len = bCode.length();
- float fullWidth = (len + 2) * 11 * x + 2 * x;
- float barStartX = 0;
- float textStartX = 0;
- switch (textAlignment) {
- case Element.ALIGN_LEFT:
- break;
- case Element.ALIGN_RIGHT:
- if (fontX > fullWidth)
- barStartX = fontX - fullWidth;
- else
- textStartX = fullWidth - fontX;
- break;
- default:
- if (fontX > fullWidth)
- barStartX = (fontX - fullWidth) / 2;
- else
- textStartX = (fullWidth - fontX) / 2;
- break;
- }
- float barStartY = 0;
- float textStartY = 0;
- if (font != null) {
- if (baseline <= 0)
- textStartY = barHeight - baseline;
- else {
- textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size);
- barStartY = textStartY + baseline;
- }
- }
- byte bars[] = getBarsCode128Raw(bCode);
- boolean print = true;
- if (barColor != null)
- cb.setColorFill(barColor);
- for (int k = 0; k < bars.length; ++k) {
- float w = bars[k] * x;
- if (print)
- cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight);
- print = !print;
- barStartX += w;
- }
- cb.fill();
- if (font != null) {
- if (textColor != null)
- cb.setColorFill(textColor);
- cb.beginText();
- cb.setFontAndSize(font, size);
- cb.setTextMatrix(textStartX, textStartY);
- cb.showText(fullCode);
- cb.endText();
- }
- return getBarcodeSize();
- }
-
- /** Creates a java.awt.Image
. This image only
- * contains the bars without any text.
- * @param foreground the color of the bars
- * @param background the color of the background
- * @return the image
- */
- public java.awt.Image createAwtImage(Color foreground, Color background) {
- int f = foreground.getRGB();
- int g = background.getRGB();
- Canvas canvas = new Canvas();
- String bCode;
- if (codeType == CODE128_RAW) {
- int idx = code.indexOf('\uffff');
- if (idx >= 0)
- bCode = code.substring(0, idx);
- else
- bCode = code;
- }
- else {
- bCode = getRawText(code, codeType == CODE128_UCC);
- }
- int len = bCode.length();
- int fullWidth = (len + 2) * 11 + 2;
- byte bars[] = getBarsCode128Raw(bCode);
-
- boolean print = true;
- int ptr = 0;
- int height = (int)barHeight;
- int pix[] = new int[fullWidth * height];
- for (int k = 0; k < bars.length; ++k) {
- int w = bars[k];
- int c = g;
- if (print)
- c = f;
- print = !print;
- for (int j = 0; j < w; ++j)
- pix[ptr++] = c;
- }
- for (int k = fullWidth; k < pix.length; k += fullWidth) {
- System.arraycopy(pix, 0, pix, k, fullWidth);
- }
- Image img = canvas.createImage(new MemoryImageSource(fullWidth, height, pix, 0, fullWidth));
-
- return img;
- }
-
- /**
- * Sets the code to generate. If it's an UCC code and starts with '(' it will
- * be split by the AI. This code in UCC mode is valid:
- *
- * (01)00000090311314(10)ABC123(15)060916
- * @param code the code to generate
- */
- public void setCode(String code) {
- if (getCodeType() == Barcode128.CODE128_UCC && code.startsWith("(")) {
- int idx = 0;
- String ret = "";
- while (idx >= 0) {
- int end = code.indexOf(')', idx);
- if (end < 0)
- throw new IllegalArgumentException("Badly formed UCC string: " + code);
- String sai = code.substring(idx + 1, end);
- if (sai.length() < 2)
- throw new IllegalArgumentException("AI too short: (" + sai + ")");
- int ai = Integer.parseInt(sai);
- int len = ais.get(ai);
- if (len == 0)
- throw new IllegalArgumentException("AI not found: (" + sai + ")");
- sai = String.valueOf(ai);
- if (sai.length() == 1)
- sai = "0" + sai;
- idx = code.indexOf('(', end);
- int next = (idx < 0 ? code.length() : idx);
- ret += sai + code.substring(end + 1, next);
- if (len < 0) {
- if (idx >= 0)
- ret += FNC1;
- }
- else if (next - end - 1 + sai.length() != len)
- throw new IllegalArgumentException("Invalid AI length: (" + sai + ")");
- }
- super.setCode(ret);
- }
- else
- super.setCode(code);
- }
-
- static {
- ais.put(0, 20);
- ais.put(1, 16);
- ais.put(2, 16);
- ais.put(10, -1);
- ais.put(11, 9);
- ais.put(12, 8);
- ais.put(13, 8);
- ais.put(15, 8);
- ais.put(17, 8);
- ais.put(20, 4);
- ais.put(21, -1);
- ais.put(22, -1);
- ais.put(23, -1);
- ais.put(240, -1);
- ais.put(241, -1);
- ais.put(250, -1);
- ais.put(251, -1);
- ais.put(252, -1);
- ais.put(30, -1);
- for (int k = 3100; k < 3700; ++k)
- ais.put(k, 10);
- ais.put(37, -1);
- for (int k = 3900; k < 3940; ++k)
- ais.put(k, -1);
- ais.put(400, -1);
- ais.put(401, -1);
- ais.put(402, 20);
- ais.put(403, -1);
- for (int k = 410; k < 416; ++k)
- ais.put(k, 16);
- ais.put(420, -1);
- ais.put(421, -1);
- ais.put(422, 6);
- ais.put(423, -1);
- ais.put(424, 6);
- ais.put(425, 6);
- ais.put(426, 6);
- ais.put(7001, 17);
- ais.put(7002, -1);
- for (int k = 7030; k < 704; ++k)
- ais.put(k, -1);
- ais.put(8001, 18);
- ais.put(8002, -1);
- ais.put(8003, -1);
- ais.put(8004, -1);
- ais.put(8005, 10);
- ais.put(8006, 22);
- ais.put(8007, -1);
- ais.put(8008, -1);
- ais.put(8018, 22);
- ais.put(8020, -1);
- ais.put(8100, 10);
- ais.put(8101, 14);
- ais.put(8102, 6);
- for (int k = 90; k < 100; ++k)
- ais.put(k, -1);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/Barcode39.java pdftk-2.01/java/com/lowagie/text/pdf/Barcode39.java
--- pdftk-1.45/java/com/lowagie/text/pdf/Barcode39.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/Barcode39.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,396 +0,0 @@
-/*
- * Copyright 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.ExceptionConverter;
-import com.lowagie.text.Element;
-import com.lowagie.text.Rectangle;
-import java.awt.Color;
-import java.awt.Image;
-import java.awt.Canvas;
-import java.awt.image.MemoryImageSource;
-
-/** Implements the code 39 and code 39 extended. The default parameters are:
- *
- *x = 0.8f;
- *n = 2;
- *font = BaseFont.createFont("Helvetica", "winansi", false);
- *size = 8;
- *baseline = size;
- *barHeight = size * 3;
- *textAlignment = Element.ALIGN_CENTER;
- *generateChecksum = false;
- *checksumText = false;
- *startStopText = true;
- *extended = false;
- *
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class Barcode39 extends Barcode{
-
- /** The bars to generate the code.
- */
- static byte BARS[][] =
- {
- {0,0,0,1,1,0,1,0,0},
- {1,0,0,1,0,0,0,0,1},
- {0,0,1,1,0,0,0,0,1},
- {1,0,1,1,0,0,0,0,0},
- {0,0,0,1,1,0,0,0,1},
- {1,0,0,1,1,0,0,0,0},
- {0,0,1,1,1,0,0,0,0},
- {0,0,0,1,0,0,1,0,1},
- {1,0,0,1,0,0,1,0,0},
- {0,0,1,1,0,0,1,0,0},
- {1,0,0,0,0,1,0,0,1},
- {0,0,1,0,0,1,0,0,1},
- {1,0,1,0,0,1,0,0,0},
- {0,0,0,0,1,1,0,0,1},
- {1,0,0,0,1,1,0,0,0},
- {0,0,1,0,1,1,0,0,0},
- {0,0,0,0,0,1,1,0,1},
- {1,0,0,0,0,1,1,0,0},
- {0,0,1,0,0,1,1,0,0},
- {0,0,0,0,1,1,1,0,0},
- {1,0,0,0,0,0,0,1,1},
- {0,0,1,0,0,0,0,1,1},
- {1,0,1,0,0,0,0,1,0},
- {0,0,0,0,1,0,0,1,1},
- {1,0,0,0,1,0,0,1,0},
- {0,0,1,0,1,0,0,1,0},
- {0,0,0,0,0,0,1,1,1},
- {1,0,0,0,0,0,1,1,0},
- {0,0,1,0,0,0,1,1,0},
- {0,0,0,0,1,0,1,1,0},
- {1,1,0,0,0,0,0,0,1},
- {0,1,1,0,0,0,0,0,1},
- {1,1,1,0,0,0,0,0,0},
- {0,1,0,0,1,0,0,0,1},
- {1,1,0,0,1,0,0,0,0},
- {0,1,1,0,1,0,0,0,0},
- {0,1,0,0,0,0,1,0,1},
- {1,1,0,0,0,0,1,0,0},
- {0,1,1,0,0,0,1,0,0},
- {0,1,0,1,0,1,0,0,0},
- {0,1,0,1,0,0,0,1,0},
- {0,1,0,0,0,1,0,1,0},
- {0,0,0,1,0,1,0,1,0},
- {0,1,0,0,1,0,1,0,0}
- };
-
- /** The index chars to BARS
.
- */
- static String CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*";
-
- /** The character combinations to make the code 39 extended.
- */
- static String EXTENDED = "%U" +
- "$A$B$C$D$E$F$G$H$I$J$K$L$M$N$O$P$Q$R$S$T$U$V$W$X$Y$Z" +
- "%A%B%C%D%E /A/B/C/D/E/F/G/H/I/J/K/L - ./O" +
- " 0 1 2 3 4 5 6 7 8 9/Z%F%G%H%I%J%V" +
- " A B C D E F G H I J K L M N O P Q R S T U V W X Y Z" +
- "%K%L%M%N%O%W" +
- "+A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+Z" +
- "%P%Q%R%S%T";
-
- /** Creates a new Barcode39.
- */
- public Barcode39() {
- try {
- x = 0.8f;
- n = 2;
- font = BaseFont.createFont("Helvetica", "winansi", false);
- size = 8;
- baseline = size;
- barHeight = size * 3;
- textAlignment = Element.ALIGN_CENTER;
- generateChecksum = false;
- checksumText = false;
- startStopText = true;
- extended = false;
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /** Creates the bars.
- * @param text the text to create the bars. This text does not include the start and
- * stop characters
- * @return the bars
- */
- public static byte[] getBarsCode39(String text) {
- text = "*" + text + "*";
- byte bars[] = new byte[text.length() * 10 - 1];
- for (int k = 0; k < text.length(); ++k) {
- int idx = CHARS.indexOf(text.charAt(k));
- if (idx < 0)
- throw new IllegalArgumentException("The character '" + text.charAt(k) + "' is illegal in code 39.");
- System.arraycopy(BARS[idx], 0, bars, k * 10, 9);
- }
- return bars;
- }
-
- /** Converts the extended text into a normal, escaped text,
- * ready to generate bars.
- * @param text the extended text
- * @return the escaped text
- */
- public static String getCode39Ex(String text) {
- String out = "";
- for (int k = 0; k < text.length(); ++k) {
- char c = text.charAt(k);
- if (c > 127)
- throw new IllegalArgumentException("The character '" + c + "' is illegal in code 39 extended.");
- char c1 = EXTENDED.charAt(c * 2);
- char c2 = EXTENDED.charAt(c * 2 + 1);
- if (c1 != ' ')
- out += c1;
- out += c2;
- }
- return out;
- }
-
- /** Calculates the checksum.
- * @param text the text
- * @return the checksum
- */
- static char getChecksum(String text) {
- int chk = 0;
- for (int k = 0; k < text.length(); ++k) {
- int idx = CHARS.indexOf(text.charAt(k));
- if (idx < 0)
- throw new IllegalArgumentException("The character '" + text.charAt(k) + "' is illegal in code 39.");
- chk += idx;
- }
- return CHARS.charAt(chk % 43);
- }
-
- /** Gets the maximum area that the barcode and the text, if
- * any, will occupy. The lower left corner is always (0, 0).
- * @return the size the barcode occupies.
- */
- public Rectangle getBarcodeSize() {
- float fontX = 0;
- float fontY = 0;
- if (font != null) {
- if (baseline > 0)
- fontY = baseline - font.getFontDescriptor(BaseFont.DESCENT, size);
- else
- fontY = -baseline + size;
- String fullCode = code;
- if (generateChecksum && checksumText)
- fullCode += getChecksum(fullCode);
- if (startStopText)
- fullCode = "*" + fullCode + "*";
- fontX = font.getWidthPoint(fullCode, size);
- }
- String fullCode = code;
- if (extended)
- fullCode = getCode39Ex(code);
- int len = fullCode.length() + 2;
- if (generateChecksum)
- ++len;
- float fullWidth = len * (6 * x + 3 * x * n) + (len - 1) * x;
- fullWidth = Math.max(fullWidth, fontX);
- float fullHeight = barHeight + fontY;
- return new Rectangle(fullWidth, fullHeight);
- }
-
- /** Places the barcode in a PdfContentByte
. The
- * barcode is always placed at coodinates (0, 0). Use the
- * translation matrix to move it elsewhere.
- * The bars and text are written in the following colors:
- *
- *
- * barColor
- * textColor
- * Result
- *
- *
- * null
- * null
- * bars and text painted with current fill color
- *
- *
- * barColor
- * null
- * bars and text painted with barColor
- *
- *
- * null
- * textColor
- * bars painted with current color text painted with textColor
- *
- *
- * barColor
- * textColor
- * bars painted with barColor
text painted with textColor
- *
- *
- * @param cb the PdfContentByte
where the barcode will be placed
- * @param barColor the color of the bars. It can be null
- * @param textColor the color of the text. It can be null
- * @return the dimensions the barcode occupies
- */
- public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
- String fullCode = code;
- float fontX = 0;
- if (font != null) {
- if (generateChecksum && checksumText)
- fullCode += getChecksum(fullCode);
- if (startStopText)
- fullCode = "*" + fullCode + "*";
- fontX = font.getWidthPoint(fullCode, size);
- }
- String bCode = code;
- if (extended)
- bCode = getCode39Ex(code);
- if (generateChecksum)
- bCode += getChecksum(bCode);
- int len = bCode.length() + 2;
- float fullWidth = len * (6 * x + 3 * x * n) + (len - 1) * x;
- float barStartX = 0;
- float textStartX = 0;
- switch (textAlignment) {
- case Element.ALIGN_LEFT:
- break;
- case Element.ALIGN_RIGHT:
- if (fontX > fullWidth)
- barStartX = fontX - fullWidth;
- else
- textStartX = fullWidth - fontX;
- break;
- default:
- if (fontX > fullWidth)
- barStartX = (fontX - fullWidth) / 2;
- else
- textStartX = (fullWidth - fontX) / 2;
- break;
- }
- float barStartY = 0;
- float textStartY = 0;
- if (font != null) {
- if (baseline <= 0)
- textStartY = barHeight - baseline;
- else {
- textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size);
- barStartY = textStartY + baseline;
- }
- }
- byte bars[] = getBarsCode39(bCode);
- boolean print = true;
- if (barColor != null)
- cb.setColorFill(barColor);
- for (int k = 0; k < bars.length; ++k) {
- float w = (bars[k] == 0 ? x : x * n);
- if (print)
- cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight);
- print = !print;
- barStartX += w;
- }
- cb.fill();
- if (font != null) {
- if (textColor != null)
- cb.setColorFill(textColor);
- cb.beginText();
- cb.setFontAndSize(font, size);
- cb.setTextMatrix(textStartX, textStartY);
- cb.showText(fullCode);
- cb.endText();
- }
- return getBarcodeSize();
- }
-
- /** Creates a java.awt.Image
. This image only
- * contains the bars without any text.
- * @param foreground the color of the bars
- * @param background the color of the background
- * @return the image
- */
- public java.awt.Image createAwtImage(Color foreground, Color background) {
- int f = foreground.getRGB();
- int g = background.getRGB();
- Canvas canvas = new Canvas();
-
- String bCode = code;
- if (extended)
- bCode = getCode39Ex(code);
- if (generateChecksum)
- bCode += getChecksum(bCode);
- int len = bCode.length() + 2;
- int nn = (int)n;
- int fullWidth = len * (6 + 3 * nn) + (len - 1);
- byte bars[] = getBarsCode39(bCode);
- boolean print = true;
- int ptr = 0;
- int height = (int)barHeight;
- int pix[] = new int[fullWidth * height];
- for (int k = 0; k < bars.length; ++k) {
- int w = (bars[k] == 0 ? 1 : nn);
- int c = g;
- if (print)
- c = f;
- print = !print;
- for (int j = 0; j < w; ++j)
- pix[ptr++] = c;
- }
- for (int k = fullWidth; k < pix.length; k += fullWidth) {
- System.arraycopy(pix, 0, pix, k, fullWidth);
- }
- Image img = canvas.createImage(new MemoryImageSource(fullWidth, height, pix, 0, fullWidth));
-
- return img;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/BarcodeCodabar.java pdftk-2.01/java/com/lowagie/text/pdf/BarcodeCodabar.java
--- pdftk-1.45/java/com/lowagie/text/pdf/BarcodeCodabar.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/BarcodeCodabar.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,349 +0,0 @@
-/*
- * Copyright 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.ExceptionConverter;
-import com.lowagie.text.Element;
-import com.lowagie.text.Rectangle;
-import java.awt.Color;
-import java.awt.Image;
-import java.awt.Canvas;
-import java.awt.image.MemoryImageSource;
-
-/** Implements the code codabar. The default parameters are:
- *
- *x = 0.8f;
- *n = 2;
- *font = BaseFont.createFont("Helvetica", "winansi", false);
- *size = 8;
- *baseline = size;
- *barHeight = size * 3;
- *textAlignment = Element.ALIGN_CENTER;
- *generateChecksum = false;
- *checksumText = false;
- *startStopText = false;
- *
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class BarcodeCodabar extends Barcode{
-
- /** The bars to generate the code.
- */
- static byte BARS[][] =
- {
- {0,0,0,0,0,1,1}, // 0
- {0,0,0,0,1,1,0}, // 1
- {0,0,0,1,0,0,1}, // 2
- {1,1,0,0,0,0,0}, // 3
- {0,0,1,0,0,1,0}, // 4
- {1,0,0,0,0,1,0}, // 5
- {0,1,0,0,0,0,1}, // 6
- {0,1,0,0,1,0,0}, // 7
- {0,1,1,0,0,0,0}, // 8
- {1,0,0,1,0,0,0}, // 9
- {0,0,0,1,1,0,0}, // -
- {0,0,1,1,0,0,0}, // $
- {1,0,0,0,1,0,1}, // :
- {1,0,1,0,0,0,1}, // /
- {1,0,1,0,1,0,0}, // .
- {0,0,1,0,1,0,1}, // +
- {0,0,1,1,0,1,0}, // a
- {0,1,0,1,0,0,1}, // b
- {0,0,0,1,0,1,1}, // c
- {0,0,0,1,1,1,0} // d
- };
-
- /** The index chars to BARS
.
- */
- static String CHARS = "0123456789-$:/.+ABCD";
-
- static final int START_STOP_IDX = 16;
- /** Creates a new BarcodeCodabar.
- */
- public BarcodeCodabar() {
- try {
- x = 0.8f;
- n = 2;
- font = BaseFont.createFont("Helvetica", "winansi", false);
- size = 8;
- baseline = size;
- barHeight = size * 3;
- textAlignment = Element.ALIGN_CENTER;
- generateChecksum = false;
- checksumText = false;
- startStopText = false;
- codeType = CODABAR;
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /** Creates the bars.
- * @param text the text to create the bars
- * @return the bars
- */
- public static byte[] getBarsCodabar(String text) {
- text = text.toUpperCase();
- int len = text.length();
- if (len < 2)
- throw new IllegalArgumentException("Codabar must have at least a start and stop character.");
- if (CHARS.indexOf(text.charAt(0)) < START_STOP_IDX || CHARS.indexOf(text.charAt(len - 1)) < START_STOP_IDX)
- throw new IllegalArgumentException("Codabar must have one of 'ABCD' as start/stop character.");
- byte bars[] = new byte[text.length() * 8 - 1];
- for (int k = 0; k < len; ++k) {
- int idx = CHARS.indexOf(text.charAt(k));
- if (idx >= START_STOP_IDX && k > 0 && k < len - 1)
- throw new IllegalArgumentException("In codabar, start/stop characters are only allowed at the extremes.");
- if (idx < 0)
- throw new IllegalArgumentException("The character '" + text.charAt(k) + "' is illegal in codabar.");
- System.arraycopy(BARS[idx], 0, bars, k * 8, 7);
- }
- return bars;
- }
-
- public static String calculateChecksum(String code) {
- if (code.length() < 2)
- return code;
- String text = code.toUpperCase();
- int sum = 0;
- int len = text.length();
- for (int k = 0; k < len; ++k)
- sum += CHARS.indexOf(text.charAt(k));
- sum = (sum + 15) / 16 * 16 - sum;
- return code.substring(0, len - 1) + CHARS.charAt(sum) + code.substring(len - 1);
- }
-
- /** Gets the maximum area that the barcode and the text, if
- * any, will occupy. The lower left corner is always (0, 0).
- * @return the size the barcode occupies.
- */
- public Rectangle getBarcodeSize() {
- float fontX = 0;
- float fontY = 0;
- String text = code;
- if (generateChecksum && checksumText)
- text = calculateChecksum(code);
- if (!startStopText)
- text = text.substring(1, text.length() - 1);
- if (font != null) {
- if (baseline > 0)
- fontY = baseline - font.getFontDescriptor(BaseFont.DESCENT, size);
- else
- fontY = -baseline + size;
- fontX = font.getWidthPoint(text, size);
- }
- text = code;
- if (generateChecksum)
- text = calculateChecksum(code);
- byte bars[] = getBarsCodabar(text);
- int wide = 0;
- for (int k = 0; k < bars.length; ++k) {
- wide += (int)bars[k];
- }
- int narrow = bars.length - wide;
- float fullWidth = x * (narrow + wide * n);
- fullWidth = Math.max(fullWidth, fontX);
- float fullHeight = barHeight + fontY;
- return new Rectangle(fullWidth, fullHeight);
- }
-
- /** Places the barcode in a PdfContentByte
. The
- * barcode is always placed at coodinates (0, 0). Use the
- * translation matrix to move it elsewhere.
- * The bars and text are written in the following colors:
- *
- *
- * barColor
- * textColor
- * Result
- *
- *
- * null
- * null
- * bars and text painted with current fill color
- *
- *
- * barColor
- * null
- * bars and text painted with barColor
- *
- *
- * null
- * textColor
- * bars painted with current color text painted with textColor
- *
- *
- * barColor
- * textColor
- * bars painted with barColor
text painted with textColor
- *
- *
- * @param cb the PdfContentByte
where the barcode will be placed
- * @param barColor the color of the bars. It can be null
- * @param textColor the color of the text. It can be null
- * @return the dimensions the barcode occupies
- */
- public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
- String fullCode = code;
- if (generateChecksum && checksumText)
- fullCode = calculateChecksum(code);
- if (!startStopText)
- fullCode = fullCode.substring(1, fullCode.length() - 1);
- float fontX = 0;
- if (font != null) {
- fontX = font.getWidthPoint(fullCode, size);
- }
- byte bars[] = getBarsCodabar(generateChecksum ? calculateChecksum(code) : code);
- int wide = 0;
- for (int k = 0; k < bars.length; ++k) {
- wide += (int)bars[k];
- }
- int narrow = bars.length - wide;
- float fullWidth = x * (narrow + wide * n);
- float barStartX = 0;
- float textStartX = 0;
- switch (textAlignment) {
- case Element.ALIGN_LEFT:
- break;
- case Element.ALIGN_RIGHT:
- if (fontX > fullWidth)
- barStartX = fontX - fullWidth;
- else
- textStartX = fullWidth - fontX;
- break;
- default:
- if (fontX > fullWidth)
- barStartX = (fontX - fullWidth) / 2;
- else
- textStartX = (fullWidth - fontX) / 2;
- break;
- }
- float barStartY = 0;
- float textStartY = 0;
- if (font != null) {
- if (baseline <= 0)
- textStartY = barHeight - baseline;
- else {
- textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size);
- barStartY = textStartY + baseline;
- }
- }
- boolean print = true;
- if (barColor != null)
- cb.setColorFill(barColor);
- for (int k = 0; k < bars.length; ++k) {
- float w = (bars[k] == 0 ? x : x * n);
- if (print)
- cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight);
- print = !print;
- barStartX += w;
- }
- cb.fill();
- if (font != null) {
- if (textColor != null)
- cb.setColorFill(textColor);
- cb.beginText();
- cb.setFontAndSize(font, size);
- cb.setTextMatrix(textStartX, textStartY);
- cb.showText(fullCode);
- cb.endText();
- }
- return getBarcodeSize();
- }
-
- /** Creates a java.awt.Image
. This image only
- * contains the bars without any text.
- * @param foreground the color of the bars
- * @param background the color of the background
- * @return the image
- */
- public java.awt.Image createAwtImage(Color foreground, Color background) {
- int f = foreground.getRGB();
- int g = background.getRGB();
- Canvas canvas = new Canvas();
-
- String fullCode = code;
- if (generateChecksum && checksumText)
- fullCode = calculateChecksum(code);
- if (!startStopText)
- fullCode = fullCode.substring(1, fullCode.length() - 1);
- byte bars[] = getBarsCodabar(generateChecksum ? calculateChecksum(code) : code);
- int wide = 0;
- for (int k = 0; k < bars.length; ++k) {
- wide += (int)bars[k];
- }
- int narrow = bars.length - wide;
- int fullWidth = narrow + wide * (int)n;
- boolean print = true;
- int ptr = 0;
- int height = (int)barHeight;
- int pix[] = new int[fullWidth * height];
- for (int k = 0; k < bars.length; ++k) {
- int w = (bars[k] == 0 ? 1 : (int)n);
- int c = g;
- if (print)
- c = f;
- print = !print;
- for (int j = 0; j < w; ++j)
- pix[ptr++] = c;
- }
- for (int k = fullWidth; k < pix.length; k += fullWidth) {
- System.arraycopy(pix, 0, pix, k, fullWidth);
- }
- Image img = canvas.createImage(new MemoryImageSource(fullWidth, height, pix, 0, fullWidth));
-
- return img;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/BarcodeEAN.java pdftk-2.01/java/com/lowagie/text/pdf/BarcodeEAN.java
--- pdftk-1.45/java/com/lowagie/text/pdf/BarcodeEAN.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/BarcodeEAN.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,724 +0,0 @@
-/*
- * Copyright 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.Rectangle;
-import com.lowagie.text.ExceptionConverter;
-import java.util.Arrays;
-import java.awt.Color;
-import java.awt.Image;
-import java.awt.Canvas;
-import java.awt.image.MemoryImageSource;
-
-/** Generates barcodes in several formats: EAN13, EAN8, UPCA, UPCE,
- * supplemental 2 and 5. The default parameters are:
- *
- *x = 0.8f;
- *font = BaseFont.createFont("Helvetica", "winansi", false);
- *size = 8;
- *baseline = size;
- *barHeight = size * 3;
- *guardBars = true;
- *codeType = EAN13;
- *code = "";
- *
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class BarcodeEAN extends Barcode{
-
- /** The bar positions that are guard bars.*/
- static int GUARD_EMPTY[] = {};
- /** The bar positions that are guard bars.*/
- static int GUARD_UPCA[] = {0, 2, 4, 6, 28, 30, 52, 54, 56, 58};
- /** The bar positions that are guard bars.*/
- static int GUARD_EAN13[] = {0, 2, 28, 30, 56, 58};
- /** The bar positions that are guard bars.*/
- static int GUARD_EAN8[] = {0, 2, 20, 22, 40, 42};
- /** The bar positions that are guard bars.*/
- static int GUARD_UPCE[] = {0, 2, 28, 30, 32};
- /** The x coordinates to place the text.*/
- static float TEXTPOS_EAN13[] = {6.5f, 13.5f, 20.5f, 27.5f, 34.5f, 41.5f, 53.5f, 60.5f, 67.5f, 74.5f, 81.5f, 88.5f};
- /** The x coordinates to place the text.*/
- static float TEXTPOS_EAN8[] = {6.5f, 13.5f, 20.5f, 27.5f, 39.5f, 46.5f, 53.5f, 60.5f};
- /** The basic bar widths.*/
- static byte BARS[][] =
- {
- {3, 2, 1, 1}, // 0
- {2, 2, 2, 1}, // 1
- {2, 1, 2, 2}, // 2
- {1, 4, 1, 1}, // 3
- {1, 1, 3, 2}, // 4
- {1, 2, 3, 1}, // 5
- {1, 1, 1, 4}, // 6
- {1, 3, 1, 2}, // 7
- {1, 2, 1, 3}, // 8
- {3, 1, 1, 2} // 9
- };
-
- /** The total number of bars for EAN13.*/
- static final int TOTALBARS_EAN13 = 11 + 12 * 4;
- /** The total number of bars for EAN8.*/
- static final int TOTALBARS_EAN8 = 11 + 8 * 4;
- /** The total number of bars for UPCE.*/
- static final int TOTALBARS_UPCE = 9 + 6 * 4;
- /** The total number of bars for supplemental 2.*/
- static final int TOTALBARS_SUPP2 = 13;
- /** The total number of bars for supplemental 5.*/
- static final int TOTALBARS_SUPP5 = 31;
- /** Marker for odd parity.*/
- static final int ODD = 0;
- /** Marker for even parity.*/
- static final int EVEN = 1;
-
- /** Sequence of parities to be used with EAN13.*/
- static byte PARITY13[][] =
- {
- {ODD, ODD, ODD, ODD, ODD, ODD}, // 0
- {ODD, ODD, EVEN, ODD, EVEN, EVEN}, // 1
- {ODD, ODD, EVEN, EVEN, ODD, EVEN}, // 2
- {ODD, ODD, EVEN, EVEN, EVEN, ODD}, // 3
- {ODD, EVEN, ODD, ODD, EVEN, EVEN}, // 4
- {ODD, EVEN, EVEN, ODD, ODD, EVEN}, // 5
- {ODD, EVEN, EVEN, EVEN, ODD, ODD}, // 6
- {ODD, EVEN, ODD, EVEN, ODD, EVEN}, // 7
- {ODD, EVEN, ODD, EVEN, EVEN, ODD}, // 8
- {ODD, EVEN, EVEN, ODD, EVEN, ODD} // 9
- };
-
- /** Sequence of parities to be used with supplemental 2.*/
- static byte PARITY2[][] =
- {
- {ODD, ODD}, // 0
- {ODD, EVEN}, // 1
- {EVEN, ODD}, // 2
- {EVEN, EVEN} // 3
- };
-
- /** Sequence of parities to be used with supplemental 2.*/
- static byte PARITY5[][] =
- {
- {EVEN, EVEN, ODD, ODD, ODD}, // 0
- {EVEN, ODD, EVEN, ODD, ODD}, // 1
- {EVEN, ODD, ODD, EVEN, ODD}, // 2
- {EVEN, ODD, ODD, ODD, EVEN}, // 3
- {ODD, EVEN, EVEN, ODD, ODD}, // 4
- {ODD, ODD, EVEN, EVEN, ODD}, // 5
- {ODD, ODD, ODD, EVEN, EVEN}, // 6
- {ODD, EVEN, ODD, EVEN, ODD}, // 7
- {ODD, EVEN, ODD, ODD, EVEN}, // 8
- {ODD, ODD, EVEN, ODD, EVEN} // 9
- };
-
- /** Sequence of parities to be used with UPCE.*/
- static byte PARITYE[][] =
- {
- {EVEN, EVEN, EVEN, ODD, ODD, ODD}, // 0
- {EVEN, EVEN, ODD, EVEN, ODD, ODD}, // 1
- {EVEN, EVEN, ODD, ODD, EVEN, ODD}, // 2
- {EVEN, EVEN, ODD, ODD, ODD, EVEN}, // 3
- {EVEN, ODD, EVEN, EVEN, ODD, ODD}, // 4
- {EVEN, ODD, ODD, EVEN, EVEN, ODD}, // 5
- {EVEN, ODD, ODD, ODD, EVEN, EVEN}, // 6
- {EVEN, ODD, EVEN, ODD, EVEN, ODD}, // 7
- {EVEN, ODD, EVEN, ODD, ODD, EVEN}, // 8
- {EVEN, ODD, ODD, EVEN, ODD, EVEN} // 9
- };
-
- /** Creates new BarcodeEAN */
- public BarcodeEAN() {
- try {
- x = 0.8f;
- font = BaseFont.createFont("Helvetica", "winansi", false);
- size = 8;
- baseline = size;
- barHeight = size * 3;
- guardBars = true;
- codeType = EAN13;
- code = "";
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /** Calculates the EAN parity character.
- * @param code the code
- * @return the parity character
- */
- public static int calculateEANParity(String code) {
- int mul = 3;
- int total = 0;
- for (int k = code.length() - 1; k >= 0; --k) {
- int n = code.charAt(k) - '0';
- total += mul * n;
- mul ^= 2;
- }
- return (10 - (total % 10)) % 10;
- }
-
- /** Converts an UPCA code into an UPCE code. If the code can not
- * be converted a null
is returned.
- * @param text the code to convert. It must have 12 numeric characters
- * @return the 8 converted digits or null
if the
- * code could not be converted
- */
- static public String convertUPCAtoUPCE(String text) {
- if (text.length() != 12 || !(text.startsWith("0") || text.startsWith("1")))
- return null;
- if (text.substring(3, 6).equals("000") || text.substring(3, 6).equals("100")
- || text.substring(3, 6).equals("200")) {
- if (text.substring(6, 8).equals("00"))
- return text.substring(0, 1) + text.substring(1, 3) + text.substring(8, 11) + text.substring(3, 4) + text.substring(11);
- }
- else if (text.substring(4, 6).equals("00")) {
- if (text.substring(6, 9).equals("000"))
- return text.substring(0, 1) + text.substring(1, 4) + text.substring(9, 11) + "3" + text.substring(11);
- }
- else if (text.substring(5, 6).equals("0")) {
- if (text.substring(6, 10).equals("0000"))
- return text.substring(0, 1) + text.substring(1, 5) + text.substring(10, 11) + "4" + text.substring(11);
- }
- else if (text.charAt(10) >= '5') {
- if (text.substring(6, 10).equals("0000"))
- return text.substring(0, 1) + text.substring(1, 6) + text.substring(10, 11) + text.substring(11);
- }
- return null;
- }
-
- /** Creates the bars for the barcode EAN13 and UPCA.
- * @param _code the text with 13 digits
- * @return the barcode
- */
- public static byte[] getBarsEAN13(String _code) {
- int code[] = new int[_code.length()];
- for (int k = 0; k < code.length; ++k)
- code[k] = _code.charAt(k) - '0';
- byte bars[] = new byte[TOTALBARS_EAN13];
- int pb = 0;
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- byte sequence[] = PARITY13[code[0]];
- for (int k = 0; k < sequence.length; ++k) {
- int c = code[k + 1];
- byte stripes[] = BARS[c];
- if (sequence[k] == ODD) {
- bars[pb++] = stripes[0];
- bars[pb++] = stripes[1];
- bars[pb++] = stripes[2];
- bars[pb++] = stripes[3];
- }
- else {
- bars[pb++] = stripes[3];
- bars[pb++] = stripes[2];
- bars[pb++] = stripes[1];
- bars[pb++] = stripes[0];
- }
- }
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- for (int k = 7; k < 13; ++k) {
- int c = code[k];
- byte stripes[] = BARS[c];
- bars[pb++] = stripes[0];
- bars[pb++] = stripes[1];
- bars[pb++] = stripes[2];
- bars[pb++] = stripes[3];
- }
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- return bars;
- }
-
- /** Creates the bars for the barcode EAN8.
- * @param _code the text with 8 digits
- * @return the barcode
- */
- public static byte[] getBarsEAN8(String _code) {
- int code[] = new int[_code.length()];
- for (int k = 0; k < code.length; ++k)
- code[k] = _code.charAt(k) - '0';
- byte bars[] = new byte[TOTALBARS_EAN8];
- int pb = 0;
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- for (int k = 0; k < 4; ++k) {
- int c = code[k];
- byte stripes[] = BARS[c];
- bars[pb++] = stripes[0];
- bars[pb++] = stripes[1];
- bars[pb++] = stripes[2];
- bars[pb++] = stripes[3];
- }
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- for (int k = 4; k < 8; ++k) {
- int c = code[k];
- byte stripes[] = BARS[c];
- bars[pb++] = stripes[0];
- bars[pb++] = stripes[1];
- bars[pb++] = stripes[2];
- bars[pb++] = stripes[3];
- }
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- return bars;
- }
-
- /** Creates the bars for the barcode UPCE.
- * @param _code the text with 8 digits
- * @return the barcode
- */
- public static byte[] getBarsUPCE(String _code) {
- int code[] = new int[_code.length()];
- for (int k = 0; k < code.length; ++k)
- code[k] = _code.charAt(k) - '0';
- byte bars[] = new byte[TOTALBARS_UPCE];
- boolean flip = (code[0] != 0);
- int pb = 0;
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- byte sequence[] = PARITYE[code[code.length - 1]];
- for (int k = 1; k < code.length - 1; ++k) {
- int c = code[k];
- byte stripes[] = BARS[c];
- if (sequence[k - 1] == (flip ? EVEN : ODD)) {
- bars[pb++] = stripes[0];
- bars[pb++] = stripes[1];
- bars[pb++] = stripes[2];
- bars[pb++] = stripes[3];
- }
- else {
- bars[pb++] = stripes[3];
- bars[pb++] = stripes[2];
- bars[pb++] = stripes[1];
- bars[pb++] = stripes[0];
- }
- }
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 1;
- return bars;
- }
-
- /** Creates the bars for the barcode supplemental 2.
- * @param _code the text with 2 digits
- * @return the barcode
- */
- public static byte[] getBarsSupplemental2(String _code) {
- int code[] = new int[2];
- for (int k = 0; k < code.length; ++k)
- code[k] = _code.charAt(k) - '0';
- byte bars[] = new byte[TOTALBARS_SUPP2];
- int pb = 0;
- int parity = (code[0] * 10 + code[1]) % 4;
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 2;
- byte sequence[] = PARITY2[parity];
- for (int k = 0; k < sequence.length; ++k) {
- if (k == 1) {
- bars[pb++] = 1;
- bars[pb++] = 1;
- }
- int c = code[k];
- byte stripes[] = BARS[c];
- if (sequence[k] == ODD) {
- bars[pb++] = stripes[0];
- bars[pb++] = stripes[1];
- bars[pb++] = stripes[2];
- bars[pb++] = stripes[3];
- }
- else {
- bars[pb++] = stripes[3];
- bars[pb++] = stripes[2];
- bars[pb++] = stripes[1];
- bars[pb++] = stripes[0];
- }
- }
- return bars;
- }
-
- /** Creates the bars for the barcode supplemental 5.
- * @param _code the text with 5 digits
- * @return the barcode
- */
- public static byte[] getBarsSupplemental5(String _code) {
- int code[] = new int[5];
- for (int k = 0; k < code.length; ++k)
- code[k] = _code.charAt(k) - '0';
- byte bars[] = new byte[TOTALBARS_SUPP5];
- int pb = 0;
- int parity = (((code[0] + code[2] + code[4]) * 3) + ((code[1] + code[3]) * 9)) % 10;
- bars[pb++] = 1;
- bars[pb++] = 1;
- bars[pb++] = 2;
- byte sequence[] = PARITY5[parity];
- for (int k = 0; k < sequence.length; ++k) {
- if (k != 0) {
- bars[pb++] = 1;
- bars[pb++] = 1;
- }
- int c = code[k];
- byte stripes[] = BARS[c];
- if (sequence[k] == ODD) {
- bars[pb++] = stripes[0];
- bars[pb++] = stripes[1];
- bars[pb++] = stripes[2];
- bars[pb++] = stripes[3];
- }
- else {
- bars[pb++] = stripes[3];
- bars[pb++] = stripes[2];
- bars[pb++] = stripes[1];
- bars[pb++] = stripes[0];
- }
- }
- return bars;
- }
-
- /** Gets the maximum area that the barcode and the text, if
- * any, will occupy. The lower left corner is always (0, 0).
- * @return the size the barcode occupies.
- */
- public Rectangle getBarcodeSize() {
- float width = 0;
- float height = barHeight;
- if (font != null) {
- if (baseline <= 0)
- height += -baseline + size;
- else
- height += baseline - font.getFontDescriptor(BaseFont.DESCENT, size);
- }
- switch (codeType) {
- case EAN13:
- width = x * (11 + 12 * 7);
- if (font != null) {
- width += font.getWidthPoint(code.charAt(0), size);
- }
- break;
- case EAN8:
- width = x * (11 + 8 * 7);
- break;
- case UPCA:
- width = x * (11 + 12 * 7);
- if (font != null) {
- width += font.getWidthPoint(code.charAt(0), size) + font.getWidthPoint(code.charAt(11), size);
- }
- break;
- case UPCE:
- width = x * (9 + 6 * 7);
- if (font != null) {
- width += font.getWidthPoint(code.charAt(0), size) + font.getWidthPoint(code.charAt(7), size);
- }
- break;
- case SUPP2:
- width = x * (6 + 2 * 7);
- break;
- case SUPP5:
- width = x * (4 + 5 * 7 + 4 * 2);
- break;
- default:
- throw new RuntimeException("Invalid code type.");
- }
- return new Rectangle(width, height);
- }
-
- /** Places the barcode in a PdfContentByte
. The
- * barcode is always placed at coodinates (0, 0). Use the
- * translation matrix to move it elsewhere.
- * The bars and text are written in the following colors:
- *
- *
- * barColor
- * textColor
- * Result
- *
- *
- * null
- * null
- * bars and text painted with current fill color
- *
- *
- * barColor
- * null
- * bars and text painted with barColor
- *
- *
- * null
- * textColor
- * bars painted with current color text painted with textColor
- *
- *
- * barColor
- * textColor
- * bars painted with barColor
text painted with textColor
- *
- *
- * @param cb the PdfContentByte
where the barcode will be placed
- * @param barColor the color of the bars. It can be null
- * @param textColor the color of the text. It can be null
- * @return the dimensions the barcode occupies
- */
- public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
- Rectangle rect = getBarcodeSize();
- float barStartX = 0;
- float barStartY = 0;
- float textStartY = 0;
- if (font != null) {
- if (baseline <= 0)
- textStartY = barHeight - baseline;
- else {
- textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size);
- barStartY = textStartY + baseline;
- }
- }
- switch (codeType) {
- case EAN13:
- case UPCA:
- case UPCE:
- if (font != null)
- barStartX += font.getWidthPoint(code.charAt(0), size);
- break;
- }
- byte bars[] = null;
- int guard[] = GUARD_EMPTY;
- switch (codeType) {
- case EAN13:
- bars = getBarsEAN13(code);
- guard = GUARD_EAN13;
- break;
- case EAN8:
- bars = getBarsEAN8(code);
- guard = GUARD_EAN8;
- break;
- case UPCA:
- bars = getBarsEAN13("0" + code);
- guard = GUARD_UPCA;
- break;
- case UPCE:
- bars = getBarsUPCE(code);
- guard = GUARD_UPCE;
- break;
- case SUPP2:
- bars = getBarsSupplemental2(code);
- break;
- case SUPP5:
- bars = getBarsSupplemental5(code);
- break;
- }
- float keepBarX = barStartX;
- boolean print = true;
- float gd = 0;
- if (font != null && baseline > 0 && guardBars) {
- gd = baseline / 2;
- }
- if (barColor != null)
- cb.setColorFill(barColor);
- for (int k = 0; k < bars.length; ++k) {
- float w = bars[k] * x;
- if (print) {
- if (Arrays.binarySearch(guard, k) >= 0)
- cb.rectangle(barStartX, barStartY - gd, w - inkSpreading, barHeight + gd);
- else
- cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight);
- }
- print = !print;
- barStartX += w;
- }
- cb.fill();
- if (font != null) {
- if (textColor != null)
- cb.setColorFill(textColor);
- cb.beginText();
- cb.setFontAndSize(font, size);
- switch (codeType) {
- case EAN13:
- cb.setTextMatrix(0, textStartY);
- cb.showText(code.substring(0, 1));
- for (int k = 1; k < 13; ++k) {
- String c = code.substring(k, k + 1);
- float len = font.getWidthPoint(c, size);
- float pX = keepBarX + TEXTPOS_EAN13[k - 1] * x - len / 2;
- cb.setTextMatrix(pX, textStartY);
- cb.showText(c);
- }
- break;
- case EAN8:
- for (int k = 0; k < 8; ++k) {
- String c = code.substring(k, k + 1);
- float len = font.getWidthPoint(c, size);
- float pX = TEXTPOS_EAN8[k] * x - len / 2;
- cb.setTextMatrix(pX, textStartY);
- cb.showText(c);
- }
- break;
- case UPCA:
- cb.setTextMatrix(0, textStartY);
- cb.showText(code.substring(0, 1));
- for (int k = 1; k < 11; ++k) {
- String c = code.substring(k, k + 1);
- float len = font.getWidthPoint(c, size);
- float pX = keepBarX + TEXTPOS_EAN13[k] * x - len / 2;
- cb.setTextMatrix(pX, textStartY);
- cb.showText(c);
- }
- cb.setTextMatrix(keepBarX + x * (11 + 12 * 7), textStartY);
- cb.showText(code.substring(11, 12));
- break;
- case UPCE:
- cb.setTextMatrix(0, textStartY);
- cb.showText(code.substring(0, 1));
- for (int k = 1; k < 7; ++k) {
- String c = code.substring(k, k + 1);
- float len = font.getWidthPoint(c, size);
- float pX = keepBarX + TEXTPOS_EAN13[k - 1] * x - len / 2;
- cb.setTextMatrix(pX, textStartY);
- cb.showText(c);
- }
- cb.setTextMatrix(keepBarX + x * (9 + 6 * 7), textStartY);
- cb.showText(code.substring(7, 8));
- break;
- case SUPP2:
- case SUPP5:
- for (int k = 0; k < code.length(); ++k) {
- String c = code.substring(k, k + 1);
- float len = font.getWidthPoint(c, size);
- float pX = (7.5f + (9 * k)) * x - len / 2;
- cb.setTextMatrix(pX, textStartY);
- cb.showText(c);
- }
- break;
- }
- cb.endText();
- }
- return rect;
- }
-
- /** Creates a java.awt.Image
. This image only
- * contains the bars without any text.
- * @param foreground the color of the bars
- * @param background the color of the background
- * @return the image
- */
- public java.awt.Image createAwtImage(Color foreground, Color background) {
- int f = foreground.getRGB();
- int g = background.getRGB();
- Canvas canvas = new Canvas();
-
- int width = 0;
- byte bars[] = null;
- switch (codeType) {
- case EAN13:
- bars = getBarsEAN13(code);
- width = 11 + 12 * 7;
- break;
- case EAN8:
- bars = getBarsEAN8(code);
- width = 11 + 8 * 7;
- break;
- case UPCA:
- bars = getBarsEAN13("0" + code);
- width = 11 + 12 * 7;
- break;
- case UPCE:
- bars = getBarsUPCE(code);
- width = 9 + 6 * 7;
- break;
- case SUPP2:
- bars = getBarsSupplemental2(code);
- width = 6 + 2 * 7;
- break;
- case SUPP5:
- bars = getBarsSupplemental5(code);
- width = 4 + 5 * 7 + 4 * 2;
- break;
- default:
- throw new RuntimeException("Invalid code type.");
- }
-
- boolean print = true;
- int ptr = 0;
- int height = (int)barHeight;
- int pix[] = new int[width * height];
- for (int k = 0; k < bars.length; ++k) {
- int w = bars[k];
- int c = g;
- if (print)
- c = f;
- print = !print;
- for (int j = 0; j < w; ++j)
- pix[ptr++] = c;
- }
- for (int k = width; k < pix.length; k += width) {
- System.arraycopy(pix, 0, pix, k, width);
- }
- Image img = canvas.createImage(new MemoryImageSource(width, height, pix, 0, width));
-
- return img;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/BarcodeEANSUPP.java pdftk-2.01/java/com/lowagie/text/pdf/BarcodeEANSUPP.java
--- pdftk-1.45/java/com/lowagie/text/pdf/BarcodeEANSUPP.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/BarcodeEANSUPP.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,159 +0,0 @@
-/*
- * Copyright 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-import com.lowagie.text.Rectangle;
-import java.awt.Color;
-
-/** This class takes 2 barcodes, an EAN/UPC and a supplemental
- * and creates a single barcode with both combined in the
- * expected layout. The UPC/EAN should have a positive text
- * baseline and the supplemental a negative one (in the supplemental
- * the text is on the top of the barcode.
- * The default parameters are:
- *
- *n = 8; // horizontal distance between the two barcodes
- *
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class BarcodeEANSUPP extends Barcode{
-
- /** The barcode with the EAN/UPC.
- */
- protected Barcode ean;
- /** The barcode with the supplemental.
- */
- protected Barcode supp;
-
- /** Creates new combined barcode.
- * @param ean the EAN/UPC barcode
- * @param supp the supplemental barcode
- */
- public BarcodeEANSUPP(Barcode ean, Barcode supp) {
- n = 8; // horizontal distance between the two barcodes
- this.ean = ean;
- this.supp = supp;
- }
-
- /** Gets the maximum area that the barcode and the text, if
- * any, will occupy. The lower left corner is always (0, 0).
- * @return the size the barcode occupies.
- */
- public Rectangle getBarcodeSize() {
- Rectangle rect = ean.getBarcodeSize();
- rect.setRight(rect.width() + supp.getBarcodeSize().width() + n);
- return rect;
- }
-
- /** Places the barcode in a PdfContentByte
. The
- * barcode is always placed at coodinates (0, 0). Use the
- * translation matrix to move it elsewhere.
- * The bars and text are written in the following colors:
- *
- *
- * barColor
- * textColor
- * Result
- *
- *
- * null
- * null
- * bars and text painted with current fill color
- *
- *
- * barColor
- * null
- * bars and text painted with barColor
- *
- *
- * null
- * textColor
- * bars painted with current color text painted with textColor
- *
- *
- * barColor
- * textColor
- * bars painted with barColor
text painted with textColor
- *
- *
- * @param cb the PdfContentByte
where the barcode will be placed
- * @param barColor the color of the bars. It can be null
- * @param textColor the color of the text. It can be null
- * @return the dimensions the barcode occupies
- */
- public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
- if (supp.getFont() != null)
- supp.setBarHeight(ean.getBarHeight() + supp.getBaseline() - supp.getFont().getFontDescriptor(BaseFont.CAPHEIGHT, supp.getSize()));
- else
- supp.setBarHeight(ean.getBarHeight());
- Rectangle eanR = ean.getBarcodeSize();
- cb.saveState();
- ean.placeBarcode(cb, barColor, textColor);
- cb.restoreState();
- cb.saveState();
- cb.concatCTM(1, 0, 0, 1, eanR.width() + n, eanR.height() - ean.getBarHeight());
- supp.placeBarcode(cb, barColor, textColor);
- cb.restoreState();
- return getBarcodeSize();
- }
-
- /** Creates a java.awt.Image
. This image only
- * contains the bars without any text.
- * @param foreground the color of the bars
- * @param background the color of the background
- * @return the image
- */
- public java.awt.Image createAwtImage(Color foreground, Color background) {
- throw new UnsupportedOperationException("The two barcodes must be composed externally.");
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/BarcodeInter25.java pdftk-2.01/java/com/lowagie/text/pdf/BarcodeInter25.java
--- pdftk-1.45/java/com/lowagie/text/pdf/BarcodeInter25.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/BarcodeInter25.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,342 +0,0 @@
-/*
- * Copyright 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.ExceptionConverter;
-import com.lowagie.text.Element;
-import com.lowagie.text.Rectangle;
-import java.awt.Color;
-import java.awt.Image;
-import java.awt.Canvas;
-import java.awt.image.MemoryImageSource;
-
-/** Implements the code interleaved 2 of 5. The text can include
- * non numeric characters that are printed but do not generate bars.
- * The default parameters are:
- *
- *x = 0.8f;
- *n = 2;
- *font = BaseFont.createFont("Helvetica", "winansi", false);
- *size = 8;
- *baseline = size;
- *barHeight = size * 3;
- *textAlignment = Element.ALIGN_CENTER;
- *generateChecksum = false;
- *checksumText = false;
- *
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class BarcodeInter25 extends Barcode{
-
- /** The bars to generate the code.
- */
- static byte BARS[][] =
- {
- {0,0,1,1,0},
- {1,0,0,0,1},
- {0,1,0,0,1},
- {1,1,0,0,0},
- {0,0,1,0,1},
- {1,0,1,0,0},
- {0,1,1,0,0},
- {0,0,0,1,1},
- {1,0,0,1,0},
- {0,1,0,1,0}
- };
-
- /** Creates new BarcodeInter25 */
- public BarcodeInter25() {
- try {
- x = 0.8f;
- n = 2;
- font = BaseFont.createFont("Helvetica", "winansi", false);
- size = 8;
- baseline = size;
- barHeight = size * 3;
- textAlignment = Element.ALIGN_CENTER;
- generateChecksum = false;
- checksumText = false;
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /** Deletes all the non numeric characters from text
.
- * @param text the text
- * @return a String
with only numeric characters
- */
- public static String keepNumbers(String text) {
- StringBuffer sb = new StringBuffer();
- for (int k = 0; k < text.length(); ++k) {
- char c = text.charAt(k);
- if (c >= '0' && c <= '9')
- sb.append(c);
- }
- return sb.toString();
- }
-
- /** Calculates the checksum.
- * @param text the numeric text
- * @return the checksum
- */
- public static char getChecksum(String text) {
- int mul = 3;
- int total = 0;
- for (int k = text.length() - 1; k >= 0; --k) {
- int n = text.charAt(k) - '0';
- total += mul * n;
- mul ^= 2;
- }
- return (char)(((10 - (total % 10)) % 10) + '0');
- }
-
- /** Creates the bars for the barcode.
- * @param text the text. It can contain non numeric characters
- * @return the barcode
- */
- public static byte[] getBarsInter25(String text) {
- text = keepNumbers(text);
- if ((text.length() & 1) != 0)
- throw new IllegalArgumentException("The text length must be even.");
- byte bars[] = new byte[text.length() * 5 + 7];
- int pb = 0;
- bars[pb++] = 0;
- bars[pb++] = 0;
- bars[pb++] = 0;
- bars[pb++] = 0;
- int len = text.length() / 2;
- for (int k = 0; k < len; ++k) {
- int c1 = text.charAt(k * 2) - '0';
- int c2 = text.charAt(k * 2 + 1) - '0';
- byte b1[] = BARS[c1];
- byte b2[] = BARS[c2];
- for (int j = 0; j < 5; ++j) {
- bars[pb++] = b1[j];
- bars[pb++] = b2[j];
- }
- }
- bars[pb++] = 1;
- bars[pb++] = 0;
- bars[pb++] = 0;
- return bars;
- }
-
- /** Gets the maximum area that the barcode and the text, if
- * any, will occupy. The lower left corner is always (0, 0).
- * @return the size the barcode occupies.
- */
- public Rectangle getBarcodeSize() {
- float fontX = 0;
- float fontY = 0;
- if (font != null) {
- if (baseline > 0)
- fontY = baseline - font.getFontDescriptor(BaseFont.DESCENT, size);
- else
- fontY = -baseline + size;
- String fullCode = code;
- if (generateChecksum && checksumText)
- fullCode += getChecksum(fullCode);
- fontX = font.getWidthPoint(fullCode, size);
- }
- String fullCode = keepNumbers(code);
- int len = fullCode.length();
- if (generateChecksum)
- ++len;
- float fullWidth = len * (3 * x + 2 * x * n) + (6 + n ) * x;
- fullWidth = Math.max(fullWidth, fontX);
- float fullHeight = barHeight + fontY;
- return new Rectangle(fullWidth, fullHeight);
- }
-
- /** Places the barcode in a PdfContentByte
. The
- * barcode is always placed at coodinates (0, 0). Use the
- * translation matrix to move it elsewhere.
- * The bars and text are written in the following colors:
- *
- *
- * barColor
- * textColor
- * Result
- *
- *
- * null
- * null
- * bars and text painted with current fill color
- *
- *
- * barColor
- * null
- * bars and text painted with barColor
- *
- *
- * null
- * textColor
- * bars painted with current color text painted with textColor
- *
- *
- * barColor
- * textColor
- * bars painted with barColor
text painted with textColor
- *
- *
- * @param cb the PdfContentByte
where the barcode will be placed
- * @param barColor the color of the bars. It can be null
- * @param textColor the color of the text. It can be null
- * @return the dimensions the barcode occupies
- */
- public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
- String fullCode = code;
- float fontX = 0;
- if (font != null) {
- if (generateChecksum && checksumText)
- fullCode += getChecksum(fullCode);
- fontX = font.getWidthPoint(fullCode, size);
- }
- String bCode = keepNumbers(code);
- if (generateChecksum)
- bCode += getChecksum(bCode);
- int len = bCode.length();
- float fullWidth = len * (3 * x + 2 * x * n) + (6 + n ) * x;
- float barStartX = 0;
- float textStartX = 0;
- switch (textAlignment) {
- case Element.ALIGN_LEFT:
- break;
- case Element.ALIGN_RIGHT:
- if (fontX > fullWidth)
- barStartX = fontX - fullWidth;
- else
- textStartX = fullWidth - fontX;
- break;
- default:
- if (fontX > fullWidth)
- barStartX = (fontX - fullWidth) / 2;
- else
- textStartX = (fullWidth - fontX) / 2;
- break;
- }
- float barStartY = 0;
- float textStartY = 0;
- if (font != null) {
- if (baseline <= 0)
- textStartY = barHeight - baseline;
- else {
- textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size);
- barStartY = textStartY + baseline;
- }
- }
- byte bars[] = getBarsInter25(bCode);
- boolean print = true;
- if (barColor != null)
- cb.setColorFill(barColor);
- for (int k = 0; k < bars.length; ++k) {
- float w = (bars[k] == 0 ? x : x * n);
- if (print)
- cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight);
- print = !print;
- barStartX += w;
- }
- cb.fill();
- if (font != null) {
- if (textColor != null)
- cb.setColorFill(textColor);
- cb.beginText();
- cb.setFontAndSize(font, size);
- cb.setTextMatrix(textStartX, textStartY);
- cb.showText(fullCode);
- cb.endText();
- }
- return getBarcodeSize();
- }
-
- /** Creates a java.awt.Image
. This image only
- * contains the bars without any text.
- * @param foreground the color of the bars
- * @param background the color of the background
- * @return the image
- */
- public java.awt.Image createAwtImage(Color foreground, Color background) {
- int f = foreground.getRGB();
- int g = background.getRGB();
- Canvas canvas = new Canvas();
-
- String bCode = keepNumbers(code);
- if (generateChecksum)
- bCode += getChecksum(bCode);
- int len = bCode.length();
- int nn = (int)n;
- int fullWidth = len * (3 + 2 * nn) + (6 + nn );
- byte bars[] = getBarsInter25(bCode);
- boolean print = true;
- int ptr = 0;
- int height = (int)barHeight;
- int pix[] = new int[fullWidth * height];
- for (int k = 0; k < bars.length; ++k) {
- int w = (bars[k] == 0 ? 1 : nn);
- int c = g;
- if (print)
- c = f;
- print = !print;
- for (int j = 0; j < w; ++j)
- pix[ptr++] = c;
- }
- for (int k = fullWidth; k < pix.length; k += fullWidth) {
- System.arraycopy(pix, 0, pix, k, fullWidth);
- }
- Image img = canvas.createImage(new MemoryImageSource(fullWidth, height, pix, 0, fullWidth));
-
- return img;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/BarcodePDF417.java pdftk-2.01/java/com/lowagie/text/pdf/BarcodePDF417.java
--- pdftk-1.45/java/com/lowagie/text/pdf/BarcodePDF417.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/BarcodePDF417.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,1604 +0,0 @@
-/*
- *
- * Copyright 2003 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-// import com.lowagie.text.Image; ssteward: dropped in 1.44
-// import com.lowagie.text.BadElementException;
-import java.util.ArrayList;
-// import com.lowagie.text.pdf.codec.CCITTG4Encoder; ssteward: dropped in 1.44
-import java.awt.Color;
-import java.awt.Canvas;
-import java.awt.image.MemoryImageSource;
-
-/** Generates the 2D barcode PDF417. Supports dimensioning auto-sizing, fixed
- * and variable sizes, automatic and manual error levels, raw codeword input,
- * codeword size optimization and bitmap inversion. The output can
- * be a CCITT G4 Image
or a raw bitmap.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class BarcodePDF417 {
-
- /** Auto-size is made based on aspectRatio
and yHeight
. */
- public static final int PDF417_USE_ASPECT_RATIO = 0;
- /** The size of the barcode will be at least codeColumns*codeRows
. */
- public static final int PDF417_FIXED_RECTANGLE = 1;
- /** The size will be at least codeColumns
- * with a variable number of codeRows
.
- */
- public static final int PDF417_FIXED_COLUMNS = 2;
- /** The size will be at least codeRows
- * with a variable number of codeColumns
.
- */
- public static final int PDF417_FIXED_ROWS = 4;
- /** The error level correction is set automatically according
- * to ISO 15438 recomendations.
- */
- public static final int PDF417_AUTO_ERROR_LEVEL = 0;
- /** The error level correction is set by the user. It can be 0 to 8. */
- public static final int PDF417_USE_ERROR_LEVEL = 16;
- /** No text
interpretation is done and the content of codewords
- * is used directly.
- */
- public static final int PDF417_USE_RAW_CODEWORDS = 64;
- /** Inverts the output bits of the raw bitmap that is normally
- * bit one for black. It has only effect for the raw bitmap.
- */
- public static final int PDF417_INVERT_BITMAP = 128;
- /** Use Macro PDF417 Encoding
- * @see #setMacroFileId(String)
- * @see #setMacroSegmentId(int)
- * @see #setMacroSegmentCount(int)
- */
- public static final int PDF417_USE_MACRO = 256;
-
-
- private int macroSegmentCount=0;
- private int macroSegmentId=-1;
- private String macroFileId;
- protected int bitPtr;
- protected int cwPtr;
- protected SegmentList segmentList;
-
- /** Creates a new BarcodePDF417
with the default settings. */
- public BarcodePDF417() {
- setDefaultParameters();
- }
-
- /**
- * Sets the segment id for macro PDF417 encoding
- * @param id the id (starting at 0)
- * @see #setMacroSegmentCount(int)
- */
- public void setMacroSegmentId(int id) {
- this.macroSegmentId = id;
- }
-
- /**
- * Sets the segment count for macro PDF417 encoding
- * @param cnt the number of macro segments
- * @see #setMacroSegmentId(int)
- */
- public void setMacroSegmentCount(int cnt) {
- this.macroSegmentCount = cnt;
- }
-
- /**
- * Sets the File ID for macro PDF417 encoding
- * @param id the file id
- */
- public void setMacroFileId(String id) {
- this.macroFileId = id;
- }
-
- protected boolean checkSegmentType(Segment segment, char type) {
- if (segment == null)
- return false;
- return segment.type == type;
- }
-
- protected int getSegmentLength(Segment segment) {
- if (segment == null)
- return 0;
- return segment.end - segment.start;
- }
-
- /** Set the default settings that correspond to PDF417_USE_ASPECT_RATIO
- * and PDF417_AUTO_ERROR_LEVEL
.
- */
- public void setDefaultParameters() {
- options = 0;
- outBits = null;
- text = new byte[0];
- yHeight = 3;
- aspectRatio = 0.5f;
- }
-
- protected void outCodeword17(int codeword) {
- int bytePtr = bitPtr / 8;
- int bit = bitPtr - bytePtr * 8;
- outBits[bytePtr++] |= codeword >> (9 + bit);
- outBits[bytePtr++] |= codeword >> (1 + bit);
- codeword <<= 8;
- outBits[bytePtr] |= codeword >> (1 + bit);
- bitPtr += 17;
- }
-
- protected void outCodeword18(int codeword) {
- int bytePtr = bitPtr / 8;
- int bit = bitPtr - bytePtr * 8;
- outBits[bytePtr++] |= codeword >> (10 + bit);
- outBits[bytePtr++] |= codeword >> (2 + bit);
- codeword <<= 8;
- outBits[bytePtr] |= codeword >> (2 + bit);
- if (bit == 7)
- outBits[++bytePtr] |= 0x80;
- bitPtr += 18;
- }
-
- protected void outCodeword(int codeword) {
- outCodeword17(codeword);
- }
-
- protected void outStopPattern() {
- outCodeword18(STOP_PATTERN);
- }
-
- protected void outStartPattern() {
- outCodeword17(START_PATTERN);
- }
-
- protected void outPaintCode() {
- int codePtr = 0;
- bitColumns = START_CODE_SIZE * (codeColumns + 3) + STOP_SIZE;
- int lenBits = ((bitColumns - 1) / 8 + 1) * codeRows;
- outBits = new byte[lenBits];
- for (int row = 0; row < codeRows; ++row) {
- bitPtr = ((bitColumns - 1) / 8 + 1) * 8 * row;
- int rowMod = row % 3;
- int cluster[] = CLUSTERS[rowMod];
- outStartPattern();
- int edge = 0;
- switch (rowMod) {
- case 0:
- edge = 30 * (row / 3) + ((codeRows - 1) / 3);
- break;
- case 1:
- edge = 30 * (row / 3) + errorLevel * 3 + ((codeRows - 1) % 3);
- break;
- default:
- edge = 30 * (row / 3) + codeColumns - 1;
- break;
- }
- outCodeword(cluster[edge]);
-
- for (int column = 0; column < codeColumns; ++column) {
- outCodeword(cluster[codewords[codePtr++]]);
- }
-
- switch (rowMod) {
- case 0:
- edge = 30 * (row / 3) + codeColumns - 1;
- break;
- case 1:
- edge = 30 * (row / 3) + ((codeRows - 1) / 3);
- break;
- default:
- edge = 30 * (row / 3) + errorLevel * 3 + ((codeRows - 1) % 3);
- break;
- }
- outCodeword(cluster[edge]);
- outStopPattern();
- }
- if ((options & PDF417_INVERT_BITMAP) != 0) {
- for (int k = 0; k < outBits.length; ++k)
- outBits[k] ^= 0xff;
- }
- }
-
- protected void calculateErrorCorrection(int dest) {
- if (errorLevel < 0 || errorLevel > 8)
- errorLevel = 0;
- int A[] = ERROR_LEVEL[errorLevel];
- int Alength = 2 << errorLevel;
- for (int k = 0; k < Alength; ++k)
- codewords[dest + k] = 0;
- int lastE = Alength - 1;
- for (int k = 0; k < lenCodewords; ++k) {
- int t1 = codewords[k] + codewords[dest];
- for (int e = 0; e <= lastE; ++e) {
- int t2 = (t1 * A[lastE - e]) % MOD;
- int t3 = MOD - t2;
- codewords[dest + e] = ((e == lastE ? 0 : codewords[dest + e + 1]) + t3) % MOD;
- }
- }
- for (int k = 0; k < Alength; ++k)
- codewords[dest + k] = (MOD - codewords[dest + k]) % MOD;
- }
-
- private static int getTextTypeAndValue(byte[] input, int maxLength, int idx) {
- if (idx >= maxLength)
- return 0;
- char c = (char)(input[idx] & 0xff);
- if (c >= 'A' && c <= 'Z')
- return (ALPHA + c - 'A');
- if (c >= 'a' && c <= 'z')
- return (LOWER + c - 'a');
- if (c == ' ')
- return (ALPHA + LOWER + MIXED + SPACE);
- int ms = MIXED_SET.indexOf(c);
- int ps = PUNCTUATION_SET.indexOf(c);
- if (ms < 0 && ps < 0)
- return (ISBYTE + c);
- if (ms == ps)
- return (MIXED + PUNCTUATION + ms);
- if (ms >= 0)
- return (MIXED + ms);
- return (PUNCTUATION + ps);
- }
-
- protected int getTextTypeAndValue(int maxLength, int idx) {
- return getTextTypeAndValue(text, maxLength,idx);
- }
-
- private void textCompaction(byte[] input, int start, int length) {
- int dest[] = new int[ABSOLUTE_MAX_TEXT_SIZE * 2];
- int mode = ALPHA;
- int ptr = 0;
- int fullBytes = 0;
- int v = 0;
- int k;
- int size;
- length += start;
- for (k = start; k < length; ++k) {
- v = getTextTypeAndValue(input, length, k);
- if ((v & mode) != 0) {
- dest[ptr++] = v & 0xff;
- continue;
- }
- if ((v & ISBYTE) != 0) {
- if ((ptr & 1) != 0) {
- dest[ptr++] = (mode & PUNCTUATION) != 0 ? PAL : PS;
- mode = (mode & PUNCTUATION) != 0 ? ALPHA : mode;
- }
- dest[ptr++] = BYTESHIFT;
- dest[ptr++] = v & 0xff;
- fullBytes += 2;
- continue;
- }
- switch (mode) {
- case ALPHA:
- if ((v & LOWER) != 0) {
- dest[ptr++] = LL;
- dest[ptr++] = v & 0xff;
- mode = LOWER;
- }
- else if ((v & MIXED) != 0) {
- dest[ptr++] = ML;
- dest[ptr++] = v & 0xff;
- mode = MIXED;
- }
- else if ((getTextTypeAndValue(input, length, k + 1) & getTextTypeAndValue(input, length, k + 2) & PUNCTUATION) != 0) {
- dest[ptr++] = ML;
- dest[ptr++] = PL;
- dest[ptr++] = v & 0xff;
- mode = PUNCTUATION;
- }
- else {
- dest[ptr++] = PS;
- dest[ptr++] = v & 0xff;
- }
- break;
- case LOWER:
- if ((v & ALPHA) != 0) {
- if ((getTextTypeAndValue(input, length, k + 1) & getTextTypeAndValue(input, length, k + 2) & ALPHA) != 0) {
- dest[ptr++] = ML;
- dest[ptr++] = AL;
- mode = ALPHA;
- }
- else {
- dest[ptr++] = AS;
- }
- dest[ptr++] = v & 0xff;
- }
- else if ((v & MIXED) != 0) {
- dest[ptr++] = ML;
- dest[ptr++] = v & 0xff;
- mode = MIXED;
- }
- else if ((getTextTypeAndValue(input, length, k + 1) & getTextTypeAndValue(input, length, k + 2) & PUNCTUATION) != 0) {
- dest[ptr++] = ML;
- dest[ptr++] = PL;
- dest[ptr++] = v & 0xff;
- mode = PUNCTUATION;
- }
- else {
- dest[ptr++] = PS;
- dest[ptr++] = v & 0xff;
- }
- break;
- case MIXED:
- if ((v & LOWER) != 0) {
- dest[ptr++] = LL;
- dest[ptr++] = v & 0xff;
- mode = LOWER;
- }
- else if ((v & ALPHA) != 0) {
- dest[ptr++] = AL;
- dest[ptr++] = v & 0xff;
- mode = ALPHA;
- }
- else if ((getTextTypeAndValue(input, length, k + 1) & getTextTypeAndValue(input, length, k + 2) & PUNCTUATION) != 0) {
- dest[ptr++] = PL;
- dest[ptr++] = v & 0xff;
- mode = PUNCTUATION;
- }
- else {
- dest[ptr++] = PS;
- dest[ptr++] = v & 0xff;
- }
- break;
- case PUNCTUATION:
- dest[ptr++] = PAL;
- mode = ALPHA;
- --k;
- break;
- }
- }
- if ((ptr & 1) != 0)
- dest[ptr++] = PS;
- size = (ptr + fullBytes) / 2;
- if (size + cwPtr > MAX_DATA_CODEWORDS) {
- throw new IndexOutOfBoundsException("The text is too big.");
- }
- length = ptr;
- ptr = 0;
- while (ptr < length) {
- v = dest[ptr++];
- if (v >= 30) {
- codewords[cwPtr++] = v;
- codewords[cwPtr++] = dest[ptr++];
- }
- else
- codewords[cwPtr++] = v * 30 + dest[ptr++];
- }
- }
- protected void textCompaction(int start, int length) {
- textCompaction(text, start, length);
- }
-
- protected void basicNumberCompaction(int start, int length) {
- basicNumberCompaction(text, start, length);
- }
-
- private void basicNumberCompaction(byte[] input, int start, int length) {
- int ret = cwPtr;
- int retLast = length / 3;
- int ni, k;
- cwPtr += retLast + 1;
- for (k = 0; k <= retLast; ++k)
- codewords[ret + k] = 0;
- codewords[ret + retLast] = 1;
- length += start;
- for (ni = start; ni < length; ++ni) {
- // multiply by 10
- for (k = retLast; k >= 0; --k)
- codewords[ret + k] *= 10;
- // add the digit
- codewords[ret + retLast] += input[ni] - '0';
- // propagate carry
- for (k = retLast; k > 0; --k) {
- codewords[ret + k - 1] += codewords[ret + k] / 900;
- codewords[ret + k] %= 900;
- }
- }
- }
-
- private void numberCompaction(byte[] input, int start, int length) {
- int full = (length / 44) * 15;
- int size = length % 44;
- int k;
- if (size == 0)
- size = full;
- else
- size = full + size / 3 + 1;
- if (size + cwPtr > MAX_DATA_CODEWORDS) {
- throw new IndexOutOfBoundsException("The text is too big.");
- }
- length += start;
- for (k = start; k < length; k += 44) {
- size = length - k < 44 ? length - k : 44;
- basicNumberCompaction(input, k, size);
- }
- }
-
- protected void numberCompaction(int start, int length) {
- numberCompaction(text, start, length);
- }
-
- protected void byteCompaction6(int start) {
- int length = 6;
- int ret = cwPtr;
- int retLast = 4;
- int ni, k;
- cwPtr += retLast + 1;
- for (k = 0; k <= retLast ; ++k)
- codewords[ret + k] = 0;
- length += start;
- for (ni = start; ni < length; ++ni) {
- // multiply by 256
- for (k = retLast; k >= 0; --k)
- codewords[ret + k] *= 256;
- // add the digit
- codewords[ret + retLast] += (int)text[ni] & 0xff;
- // propagate carry
- for (k = retLast; k > 0; --k) {
- codewords[ret + k - 1] += codewords[ret + k] / 900;
- codewords[ret + k] %= 900;
- }
- }
- }
-
- void byteCompaction(int start, int length) {
- int k, j;
- int size = (length / 6) * 5 + (length % 6);
- if (size + cwPtr > MAX_DATA_CODEWORDS) {
- throw new IndexOutOfBoundsException("The text is too big.");
- }
- length += start;
- for (k = start; k < length; k += 6) {
- size = length - k < 44 ? length - k : 6;
- if (size < 6) {
- for (j = 0; j < size; ++j)
- codewords[cwPtr++] = (int)text[k + j] & 0xff;
- }
- else {
- byteCompaction6(k);
- }
- }
- }
-
- void breakString() {
- int textLength = text.length;
- int lastP = 0;
- int startN = 0;
- int nd = 0;
- char c = 0;
- int k, j;
- boolean lastTxt, txt;
- Segment v;
- Segment vp;
- Segment vn;
- for (k = 0; k < textLength; ++k) {
- c = (char)(text[k] & 0xff);
- if (c >= '0' && c <= '9') {
- if (nd == 0)
- startN = k;
- ++nd;
- continue;
- }
- if (nd >= 13) {
- if (lastP != startN) {
- c = (char)(text[lastP] & 0xff);
- // ptrS = lastP;
- lastTxt = (c >= ' ' && c < 127) || c == '\r' || c == '\n' || c == '\t';
- for (j = lastP; j < startN; ++j) {
- c = (char)(text[j] & 0xff);
- txt = (c >= ' ' && c < 127) || c == '\r' || c == '\n' || c == '\t';
- if (txt != lastTxt) {
- segmentList.add(lastTxt ? 'T' : 'B', lastP, j);
- lastP = j;
- lastTxt = txt;
- }
- }
- segmentList.add(lastTxt ? 'T' : 'B', lastP, startN);
- }
- segmentList.add('N', startN, k);
- lastP = k;
- }
- nd = 0;
- }
- if (nd < 13)
- startN = textLength;
- if (lastP != startN) {
- c = (char)(text[lastP] & 0xff);
- // ptrS = lastP;
- lastTxt = (c >= ' ' && c < 127) || c == '\r' || c == '\n' || c == '\t';
- for (j = lastP; j < startN; ++j) {
- c = (char)(text[j] & 0xff);
- txt = (c >= ' ' && c < 127) || c == '\r' || c == '\n' || c == '\t';
- if (txt != lastTxt) {
- segmentList.add(lastTxt ? 'T' : 'B', lastP, j);
- lastP = j;
- lastTxt = txt;
- }
- }
- segmentList.add(lastTxt ? 'T' : 'B', lastP, startN);
- }
- if (nd >= 13)
- segmentList.add('N', startN, textLength);
- //optimize
- //merge short binary
- for (k = 0; k < segmentList.size(); ++k) {
- v = segmentList.get(k);
- vp = segmentList.get(k - 1);
- vn = segmentList.get(k + 1);;
- if (checkSegmentType(v, 'B') && getSegmentLength(v) == 1) {
- if (checkSegmentType(vp, 'T') && checkSegmentType(vn, 'T')
- && getSegmentLength(vp) + getSegmentLength(vn) >= 3) {
- vp.end = vn.end;
- segmentList.remove(k);
- segmentList.remove(k);
- k = -1;
- continue;
- }
- }
- }
- //merge text sections
- for (k = 0; k < segmentList.size(); ++k) {
- v = segmentList.get(k);
- vp = segmentList.get(k - 1);
- vn = segmentList.get(k + 1);;
- if (checkSegmentType(v, 'T') && getSegmentLength(v) >= 5) {
- boolean redo = false;
- if ((checkSegmentType(vp, 'B') && getSegmentLength(vp) == 1) || checkSegmentType(vp, 'T')) {
- redo = true;
- v.start = vp.start;
- segmentList.remove(k - 1);
- --k;
- }
- if ((checkSegmentType(vn, 'B') && getSegmentLength(vn) == 1) || checkSegmentType(vn, 'T')) {
- redo = true;
- v.end = vn.end;
- segmentList.remove(k + 1);
- }
- if (redo) {
- k = -1;
- continue;
- }
- }
- }
- //merge binary sections
- for (k = 0; k < segmentList.size(); ++k) {
- v = segmentList.get(k);
- vp = segmentList.get(k - 1);
- vn = segmentList.get(k + 1);;
- if (checkSegmentType(v, 'B')) {
- boolean redo = false;
- if ((checkSegmentType(vp, 'T') && getSegmentLength(vp) < 5) || checkSegmentType(vp, 'B')) {
- redo = true;
- v.start = vp.start;
- segmentList.remove(k - 1);
- --k;
- }
- if ((checkSegmentType(vn, 'T') && getSegmentLength(vn) < 5) || checkSegmentType(vn, 'B')) {
- redo = true;
- v.end = vn.end;
- segmentList.remove(k + 1);
- }
- if (redo) {
- k = -1;
- continue;
- }
- }
- }
- // check if all numbers
- if (segmentList.size() == 1 && (v = segmentList.get(0)).type == 'T' && getSegmentLength(v) >= 8) {
- for (k = v.start; k < v.end; ++k) {
- c = (char)(text[k] & 0xff);
- if (c < '0' || c > '9')
- break;
- }
- if (k == v.end)
- v.type = 'N';
- }
- }
-
- protected void assemble() {
- int k;
- if (segmentList.size() == 0)
- return;
- cwPtr = 1;
- for (k = 0; k < segmentList.size(); ++k) {
- Segment v = segmentList.get(k);
- switch (v.type) {
- case 'T':
- if (k != 0)
- codewords[cwPtr++] = TEXT_MODE;
- textCompaction(v.start, getSegmentLength(v));
- break;
- case 'N':
- codewords[cwPtr++] = NUMERIC_MODE;
- numberCompaction(v.start, getSegmentLength(v));
- break;
- case 'B':
- codewords[cwPtr++] = (getSegmentLength(v) % 6) != 0 ? BYTE_MODE : BYTE_MODE_6;
- byteCompaction(v.start, getSegmentLength(v));
- break;
- }
- }
-
- if ((options & PDF417_USE_MACRO) != 0) {
- macroCodes();
- }
-
- }
-
- private void macroCodes() {
- if (macroSegmentId < 0) {
- throw new IllegalStateException("macroSegmentId must be >=0");
- }
- if (macroSegmentId >= macroSegmentCount) {
- throw new IllegalStateException("macroSegmentId must be < macroSemgentCount");
- }
- if (macroSegmentCount < 1) {
- throw new IllegalStateException("macroSemgentCount must be > 0");
- }
-
- codewords[cwPtr++] = MACRO_SEGMENT_ID;
- append(macroSegmentId, 5);
-
- if (macroFileId != null) {
- append(macroFileId);
- }
-
- codewords[cwPtr++] = MACRO_SEGMENT_COUNT;
- codewords[cwPtr++] = 1;
- append(macroSegmentCount, 5);
-
- if (macroSegmentId >= macroSegmentCount-1) {
- codewords[cwPtr++] = MACRO_LAST_SEGMENT;
- }
-
- }
-
- private void append(int in, int len) {
- StringBuffer sb = new StringBuffer(len+1);
- sb.append(Integer.toString(in));
- for(int i = sb.length(); i < len; i++) {
- sb.insert(0, "0");
- }
-
- byte[] bytes = PdfEncodings.convertToBytes(sb.toString(), "cp437");
- numberCompaction(bytes, 0, bytes.length);
- }
-
- private void append(String s) {
- byte[] bytes = PdfEncodings.convertToBytes(s, "cp437");
- textCompaction(bytes, 0, bytes.length);
- }
-
-
- protected static int maxPossibleErrorLevel(int remain) {
- int level = 8;
- int size = 512;
- while (level > 0) {
- if (remain >= size)
- return level;
- --level;
- size >>= 1;
- }
- return 0;
- }
-
- protected void dumpList() {
- if (segmentList.size() == 0)
- return;
- for (int k = 0; k < segmentList.size(); ++k) {
- Segment v = segmentList.get(k);
- int len = getSegmentLength(v);
- char c[] = new char[len];
- for (int j = 0; j < len; ++j) {
- c[j] = (char)(text[v.start + j] & 0xff);
- if (c[j] == '\r')
- c[j] = '\n';
- }
- System.out.println("" + v.type + new String(c));
- }
- }
-
- protected int getMaxSquare() {
- if (codeColumns > 21) {
- codeColumns = 29;
- codeRows = 32;
- }
- else {
- codeColumns = 16;
- codeRows = 58;
- }
- return MAX_DATA_CODEWORDS + 2;
- }
-
- /** Paints the barcode. If no exception was thrown a valid barcode is available. */
- public void paintCode() {
- int maxErr, lenErr, tot, pad;
- if ((options & PDF417_USE_RAW_CODEWORDS) != 0) {
- if (lenCodewords > MAX_DATA_CODEWORDS || lenCodewords < 1 || lenCodewords != codewords[0]) {
- throw new IllegalArgumentException("Invalid codeword size.");
- }
- }
- else {
- if (text == null)
- throw new NullPointerException("Text cannot be null.");
- if (text.length > ABSOLUTE_MAX_TEXT_SIZE) {
- throw new IndexOutOfBoundsException("The text is too big.");
- }
- segmentList = new SegmentList();
- breakString();
- //dumpList();
- assemble();
- segmentList = null;
- codewords[0] = lenCodewords = cwPtr;
- }
- maxErr = maxPossibleErrorLevel(MAX_DATA_CODEWORDS + 2 - lenCodewords);
- if ((options & PDF417_USE_ERROR_LEVEL) == 0) {
- if (lenCodewords < 41)
- errorLevel = 2;
- else if (lenCodewords < 161)
- errorLevel = 3;
- else if (lenCodewords < 321)
- errorLevel = 4;
- else
- errorLevel = 5;
- }
- if (errorLevel < 0)
- errorLevel = 0;
- else if (errorLevel > maxErr)
- errorLevel = maxErr;
- if (codeColumns < 1)
- codeColumns = 1;
- else if (codeColumns > 30)
- codeColumns = 30;
- if (codeRows < 3)
- codeRows = 3;
- else if (codeRows > 90)
- codeRows = 90;
- lenErr = 2 << errorLevel;
- boolean fixedColumn = (options & PDF417_FIXED_ROWS) == 0;
- boolean skipRowColAdjust = false;
- tot = lenCodewords + lenErr;
- if ((options & PDF417_FIXED_RECTANGLE) != 0) {
- tot = codeColumns * codeRows;
- if (tot > MAX_DATA_CODEWORDS + 2) {
- tot = getMaxSquare();
- }
- if (tot < lenCodewords + lenErr)
- tot = lenCodewords + lenErr;
- else
- skipRowColAdjust = true;
- }
- else if ((options & (PDF417_FIXED_COLUMNS | PDF417_FIXED_ROWS)) == 0) {
- double c, b;
- fixedColumn = true;
- if (aspectRatio < 0.001)
- aspectRatio = 0.001f;
- else if (aspectRatio > 1000)
- aspectRatio = 1000;
- b = 73 * aspectRatio - 4;
- c = (-b + Math.sqrt(b * b + 4 * 17 * aspectRatio * (lenCodewords + lenErr) * yHeight)) / (2 * 17 * aspectRatio);
- codeColumns = (int)(c + 0.5);
- if (codeColumns < 1)
- codeColumns = 1;
- else if (codeColumns > 30)
- codeColumns = 30;
- }
- if (!skipRowColAdjust) {
- if (fixedColumn) {
- codeRows = (tot - 1) / codeColumns + 1;
- if (codeRows < 3)
- codeRows = 3;
- else if (codeRows > 90) {
- codeRows = 90;
- codeColumns = (tot - 1) / 90 + 1;
- }
- }
- else {
- codeColumns = (tot - 1) / codeRows + 1;
- if (codeColumns > 30) {
- codeColumns = 30;
- codeRows = (tot - 1) / 30 + 1;
- }
- }
- tot = codeRows * codeColumns;
- }
- if (tot > MAX_DATA_CODEWORDS + 2) {
- tot = getMaxSquare();
- }
- errorLevel = maxPossibleErrorLevel(tot - lenCodewords);
- lenErr = 2 << errorLevel;
- pad = tot - lenErr - lenCodewords;
- cwPtr = lenCodewords;
- while (pad-- != 0)
- codewords[cwPtr++] = TEXT_MODE;
- codewords[0] = lenCodewords = cwPtr;
- calculateErrorCorrection(lenCodewords);
- lenCodewords = tot;
- outPaintCode();
- }
-
- /** Gets an Image
with the barcode. The image will have to be
- * scaled in the Y direction by yHeight
for the barcode
- * to have the right printing aspect.
- * @return the barcode Image
- * @throws BadElementException on error
- */
- /* ssteward: dropped in 1.44
- public Image getImage() throws BadElementException {
- paintCode();
- byte g4[] = CCITTG4Encoder.compress(outBits, bitColumns, codeRows);
- return Image.getInstance(bitColumns, codeRows, false, Image.CCITTG4, (options & PDF417_INVERT_BITMAP) == 0 ? 0 : Image.CCITT_BLACKIS1, g4, null);
- }
- */
-
- /** Creates a java.awt.Image
.
- * @param foreground the color of the bars
- * @param background the color of the background
- * @return the image
- */
- public java.awt.Image createAwtImage(Color foreground, Color background) {
- int f = foreground.getRGB();
- int g = background.getRGB();
- Canvas canvas = new Canvas();
-
- paintCode();
- int h = (int)yHeight;
- int pix[] = new int[bitColumns * codeRows * h];
- int stride = (bitColumns + 7) / 8;
- int ptr = 0;
- for (int k = 0; k < codeRows; ++k) {
- int p = k * stride;
- for (int j = 0; j < bitColumns; ++j) {
- int b = outBits[p + (j / 8)] & 0xff;
- b <<= j % 8;
- pix[ptr++] = (b & 0x80) == 0 ? g : f;
- }
- for (int j = 1; j < h; ++j) {
- System.arraycopy(pix, ptr - bitColumns, pix, ptr + bitColumns * (j - 1), bitColumns);
- }
- ptr += bitColumns * (h - 1);
- }
-
- java.awt.Image img = canvas.createImage(new MemoryImageSource(bitColumns, codeRows * h, pix, 0, bitColumns));
- return img;
- }
-
- /** Gets the raw image bits of the barcode. The image will have to
- * be scaled in the Y direction by yHeight
.
- * @return The raw barcode image
- */
- public byte[] getOutBits() {
- return this.outBits;
- }
-
- /** Gets the number of X pixels of outBits
.
- * @return the number of X pixels of outBits
- */
- public int getBitColumns() {
- return this.bitColumns;
- }
-
- /** Gets the number of Y pixels of outBits
.
- * It is also the number of rows in the barcode.
- * @return the number of Y pixels of outBits
- */
- public int getCodeRows() {
- return this.codeRows;
- }
-
- /** Sets the number of barcode rows. This number may be changed
- * to keep the barcode valid.
- * @param codeRows the number of barcode rows
- */
- public void setCodeRows(int codeRows) {
- this.codeRows = codeRows;
- }
-
- /** Gets the number of barcode data columns.
- * @return he number of barcode data columns
- */
- public int getCodeColumns() {
- return this.codeColumns;
- }
-
- /** Sets the number of barcode data columns.
- * This number may be changed to keep the barcode valid.
- * @param codeColumns the number of barcode data columns
- */
- public void setCodeColumns(int codeColumns) {
- this.codeColumns = codeColumns;
- }
-
- /** Gets the codeword array. This array is always 928 elements long.
- * It can be writen to if the option PDF417_USE_RAW_CODEWORDS
- * is set.
- * @return the codeword array
- */
- public int[] getCodewords() {
- return this.codewords;
- }
-
- /** Gets the length of the codewords.
- * @return the length of the codewords
- */
- public int getLenCodewords() {
- return this.lenCodewords;
- }
-
- /** Sets the length of the codewords.
- * @param lenCodewords the length of the codewords
- */
- public void setLenCodewords(int lenCodewords) {
- this.lenCodewords = lenCodewords;
- }
-
- /** Gets the error level correction used for the barcode. It may different
- * from the previously set value.
- * @return the error level correction used for the barcode
- */
- public int getErrorLevel() {
- return this.errorLevel;
- }
-
- /** Sets the error level correction for the barcode.
- * @param errorLevel the error level correction for the barcode
- */
- public void setErrorLevel(int errorLevel) {
- this.errorLevel = errorLevel;
- }
-
- /** Gets the bytes that form the barcode. This bytes should
- * be interpreted in the codepage Cp437.
- * @return the bytes that form the barcode
- */
- public byte[] getText() {
- return this.text;
- }
-
- /** Sets the bytes that form the barcode. This bytes should
- * be interpreted in the codepage Cp437.
- * @param text the bytes that form the barcode
- */
- public void setText(byte[] text) {
- this.text = text;
- }
-
- /** Sets the text that will form the barcode. This text is converted
- * to bytes using the encoding Cp437.
- * @param s the text that will form the barcode
- * @throws UnsupportedEncodingException if the encoding Cp437 is not supported
- */
- public void setText(String s) {
- this.text = PdfEncodings.convertToBytes(s, "cp437");
- }
-
- /** Gets the options to generate the barcode.
- * @return the options to generate the barcode
- */
- public int getOptions() {
- return this.options;
- }
-
- /** Sets the options to generate the barcode. This can be all
- * the PDF417_*
constants.
- * @param options the options to generate the barcode
- */
- public void setOptions(int options) {
- this.options = options;
- }
-
- /** Gets the barcode aspect ratio.
- * @return the barcode aspect ratio
- */
- public float getAspectRatio() {
- return this.aspectRatio;
- }
-
- /** Sets the barcode aspect ratio. A ratio or 0.5 will make the
- * barcode width twice as large as the height.
- * @param aspectRatio the barcode aspect ratio
- */
- public void setAspectRatio(float aspectRatio) {
- this.aspectRatio = aspectRatio;
- }
-
- /** Gets the Y pixel height relative to X.
- * @return the Y pixel height relative to X
- */
- public float getYHeight() {
- return this.yHeight;
- }
-
- /** Sets the Y pixel height relative to X. It is usually 3.
- * @param yHeight the Y pixel height relative to X
- */
- public void setYHeight(float yHeight) {
- this.yHeight = yHeight;
- }
-
- protected static final int START_PATTERN = 0x1fea8;
- protected static final int STOP_PATTERN = 0x3fa29;
- protected static final int START_CODE_SIZE = 17;
- protected static final int STOP_SIZE = 18;
- protected static final int MOD = 929;
- protected static final int ALPHA = 0x10000;
- protected static final int LOWER = 0x20000;
- protected static final int MIXED = 0x40000;
- protected static final int PUNCTUATION = 0x80000;
- protected static final int ISBYTE = 0x100000;
- protected static final int BYTESHIFT = 913;
- protected static final int PL = 25;
- protected static final int LL = 27;
- protected static final int AS = 27;
- protected static final int ML = 28;
- protected static final int AL = 28;
- protected static final int PS = 29;
- protected static final int PAL = 29;
- protected static final int SPACE = 26;
- protected static final int TEXT_MODE = 900;
- protected static final int BYTE_MODE_6 = 924;
- protected static final int BYTE_MODE = 901;
- protected static final int NUMERIC_MODE = 902;
- protected static final int ABSOLUTE_MAX_TEXT_SIZE = 5420;
- protected static final int MAX_DATA_CODEWORDS = 926;
- protected static final int MACRO_SEGMENT_ID=928;
- protected static final int MACRO_SEGMENT_COUNT=923;
- protected static final int MACRO_LAST_SEGMENT=922;
-
- static String MIXED_SET = "0123456789&\r\t,:#-.$/+%*=^";
- static String PUNCTUATION_SET = ";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'";
-
- static int CLUSTERS[][] =
- {{
- 0x1d5c0, 0x1eaf0, 0x1f57c, 0x1d4e0, 0x1ea78, 0x1f53e, 0x1a8c0, 0x1d470,
- 0x1a860, 0x15040, 0x1a830, 0x15020, 0x1adc0, 0x1d6f0, 0x1eb7c, 0x1ace0,
- 0x1d678, 0x1eb3e, 0x158c0, 0x1ac70, 0x15860, 0x15dc0, 0x1aef0, 0x1d77c,
- 0x15ce0, 0x1ae78, 0x1d73e, 0x15c70, 0x1ae3c, 0x15ef0, 0x1af7c, 0x15e78,
- 0x1af3e, 0x15f7c, 0x1f5fa, 0x1d2e0, 0x1e978, 0x1f4be, 0x1a4c0, 0x1d270,
- 0x1e93c, 0x1a460, 0x1d238, 0x14840, 0x1a430, 0x1d21c, 0x14820, 0x1a418,
- 0x14810, 0x1a6e0, 0x1d378, 0x1e9be, 0x14cc0, 0x1a670, 0x1d33c, 0x14c60,
- 0x1a638, 0x1d31e, 0x14c30, 0x1a61c, 0x14ee0, 0x1a778, 0x1d3be, 0x14e70,
- 0x1a73c, 0x14e38, 0x1a71e, 0x14f78, 0x1a7be, 0x14f3c, 0x14f1e, 0x1a2c0,
- 0x1d170, 0x1e8bc, 0x1a260, 0x1d138, 0x1e89e, 0x14440, 0x1a230, 0x1d11c,
- 0x14420, 0x1a218, 0x14410, 0x14408, 0x146c0, 0x1a370, 0x1d1bc, 0x14660,
- 0x1a338, 0x1d19e, 0x14630, 0x1a31c, 0x14618, 0x1460c, 0x14770, 0x1a3bc,
- 0x14738, 0x1a39e, 0x1471c, 0x147bc, 0x1a160, 0x1d0b8, 0x1e85e, 0x14240,
- 0x1a130, 0x1d09c, 0x14220, 0x1a118, 0x1d08e, 0x14210, 0x1a10c, 0x14208,
- 0x1a106, 0x14360, 0x1a1b8, 0x1d0de, 0x14330, 0x1a19c, 0x14318, 0x1a18e,
- 0x1430c, 0x14306, 0x1a1de, 0x1438e, 0x14140, 0x1a0b0, 0x1d05c, 0x14120,
- 0x1a098, 0x1d04e, 0x14110, 0x1a08c, 0x14108, 0x1a086, 0x14104, 0x141b0,
- 0x14198, 0x1418c, 0x140a0, 0x1d02e, 0x1a04c, 0x1a046, 0x14082, 0x1cae0,
- 0x1e578, 0x1f2be, 0x194c0, 0x1ca70, 0x1e53c, 0x19460, 0x1ca38, 0x1e51e,
- 0x12840, 0x19430, 0x12820, 0x196e0, 0x1cb78, 0x1e5be, 0x12cc0, 0x19670,
- 0x1cb3c, 0x12c60, 0x19638, 0x12c30, 0x12c18, 0x12ee0, 0x19778, 0x1cbbe,
- 0x12e70, 0x1973c, 0x12e38, 0x12e1c, 0x12f78, 0x197be, 0x12f3c, 0x12fbe,
- 0x1dac0, 0x1ed70, 0x1f6bc, 0x1da60, 0x1ed38, 0x1f69e, 0x1b440, 0x1da30,
- 0x1ed1c, 0x1b420, 0x1da18, 0x1ed0e, 0x1b410, 0x1da0c, 0x192c0, 0x1c970,
- 0x1e4bc, 0x1b6c0, 0x19260, 0x1c938, 0x1e49e, 0x1b660, 0x1db38, 0x1ed9e,
- 0x16c40, 0x12420, 0x19218, 0x1c90e, 0x16c20, 0x1b618, 0x16c10, 0x126c0,
- 0x19370, 0x1c9bc, 0x16ec0, 0x12660, 0x19338, 0x1c99e, 0x16e60, 0x1b738,
- 0x1db9e, 0x16e30, 0x12618, 0x16e18, 0x12770, 0x193bc, 0x16f70, 0x12738,
- 0x1939e, 0x16f38, 0x1b79e, 0x16f1c, 0x127bc, 0x16fbc, 0x1279e, 0x16f9e,
- 0x1d960, 0x1ecb8, 0x1f65e, 0x1b240, 0x1d930, 0x1ec9c, 0x1b220, 0x1d918,
- 0x1ec8e, 0x1b210, 0x1d90c, 0x1b208, 0x1b204, 0x19160, 0x1c8b8, 0x1e45e,
- 0x1b360, 0x19130, 0x1c89c, 0x16640, 0x12220, 0x1d99c, 0x1c88e, 0x16620,
- 0x12210, 0x1910c, 0x16610, 0x1b30c, 0x19106, 0x12204, 0x12360, 0x191b8,
- 0x1c8de, 0x16760, 0x12330, 0x1919c, 0x16730, 0x1b39c, 0x1918e, 0x16718,
- 0x1230c, 0x12306, 0x123b8, 0x191de, 0x167b8, 0x1239c, 0x1679c, 0x1238e,
- 0x1678e, 0x167de, 0x1b140, 0x1d8b0, 0x1ec5c, 0x1b120, 0x1d898, 0x1ec4e,
- 0x1b110, 0x1d88c, 0x1b108, 0x1d886, 0x1b104, 0x1b102, 0x12140, 0x190b0,
- 0x1c85c, 0x16340, 0x12120, 0x19098, 0x1c84e, 0x16320, 0x1b198, 0x1d8ce,
- 0x16310, 0x12108, 0x19086, 0x16308, 0x1b186, 0x16304, 0x121b0, 0x190dc,
- 0x163b0, 0x12198, 0x190ce, 0x16398, 0x1b1ce, 0x1638c, 0x12186, 0x16386,
- 0x163dc, 0x163ce, 0x1b0a0, 0x1d858, 0x1ec2e, 0x1b090, 0x1d84c, 0x1b088,
- 0x1d846, 0x1b084, 0x1b082, 0x120a0, 0x19058, 0x1c82e, 0x161a0, 0x12090,
- 0x1904c, 0x16190, 0x1b0cc, 0x19046, 0x16188, 0x12084, 0x16184, 0x12082,
- 0x120d8, 0x161d8, 0x161cc, 0x161c6, 0x1d82c, 0x1d826, 0x1b042, 0x1902c,
- 0x12048, 0x160c8, 0x160c4, 0x160c2, 0x18ac0, 0x1c570, 0x1e2bc, 0x18a60,
- 0x1c538, 0x11440, 0x18a30, 0x1c51c, 0x11420, 0x18a18, 0x11410, 0x11408,
- 0x116c0, 0x18b70, 0x1c5bc, 0x11660, 0x18b38, 0x1c59e, 0x11630, 0x18b1c,
- 0x11618, 0x1160c, 0x11770, 0x18bbc, 0x11738, 0x18b9e, 0x1171c, 0x117bc,
- 0x1179e, 0x1cd60, 0x1e6b8, 0x1f35e, 0x19a40, 0x1cd30, 0x1e69c, 0x19a20,
- 0x1cd18, 0x1e68e, 0x19a10, 0x1cd0c, 0x19a08, 0x1cd06, 0x18960, 0x1c4b8,
- 0x1e25e, 0x19b60, 0x18930, 0x1c49c, 0x13640, 0x11220, 0x1cd9c, 0x1c48e,
- 0x13620, 0x19b18, 0x1890c, 0x13610, 0x11208, 0x13608, 0x11360, 0x189b8,
- 0x1c4de, 0x13760, 0x11330, 0x1cdde, 0x13730, 0x19b9c, 0x1898e, 0x13718,
- 0x1130c, 0x1370c, 0x113b8, 0x189de, 0x137b8, 0x1139c, 0x1379c, 0x1138e,
- 0x113de, 0x137de, 0x1dd40, 0x1eeb0, 0x1f75c, 0x1dd20, 0x1ee98, 0x1f74e,
- 0x1dd10, 0x1ee8c, 0x1dd08, 0x1ee86, 0x1dd04, 0x19940, 0x1ccb0, 0x1e65c,
- 0x1bb40, 0x19920, 0x1eedc, 0x1e64e, 0x1bb20, 0x1dd98, 0x1eece, 0x1bb10,
- 0x19908, 0x1cc86, 0x1bb08, 0x1dd86, 0x19902, 0x11140, 0x188b0, 0x1c45c,
- 0x13340, 0x11120, 0x18898, 0x1c44e, 0x17740, 0x13320, 0x19998, 0x1ccce,
- 0x17720, 0x1bb98, 0x1ddce, 0x18886, 0x17710, 0x13308, 0x19986, 0x17708,
- 0x11102, 0x111b0, 0x188dc, 0x133b0, 0x11198, 0x188ce, 0x177b0, 0x13398,
- 0x199ce, 0x17798, 0x1bbce, 0x11186, 0x13386, 0x111dc, 0x133dc, 0x111ce,
- 0x177dc, 0x133ce, 0x1dca0, 0x1ee58, 0x1f72e, 0x1dc90, 0x1ee4c, 0x1dc88,
- 0x1ee46, 0x1dc84, 0x1dc82, 0x198a0, 0x1cc58, 0x1e62e, 0x1b9a0, 0x19890,
- 0x1ee6e, 0x1b990, 0x1dccc, 0x1cc46, 0x1b988, 0x19884, 0x1b984, 0x19882,
- 0x1b982, 0x110a0, 0x18858, 0x1c42e, 0x131a0, 0x11090, 0x1884c, 0x173a0,
- 0x13190, 0x198cc, 0x18846, 0x17390, 0x1b9cc, 0x11084, 0x17388, 0x13184,
- 0x11082, 0x13182, 0x110d8, 0x1886e, 0x131d8, 0x110cc, 0x173d8, 0x131cc,
- 0x110c6, 0x173cc, 0x131c6, 0x110ee, 0x173ee, 0x1dc50, 0x1ee2c, 0x1dc48,
- 0x1ee26, 0x1dc44, 0x1dc42, 0x19850, 0x1cc2c, 0x1b8d0, 0x19848, 0x1cc26,
- 0x1b8c8, 0x1dc66, 0x1b8c4, 0x19842, 0x1b8c2, 0x11050, 0x1882c, 0x130d0,
- 0x11048, 0x18826, 0x171d0, 0x130c8, 0x19866, 0x171c8, 0x1b8e6, 0x11042,
- 0x171c4, 0x130c2, 0x171c2, 0x130ec, 0x171ec, 0x171e6, 0x1ee16, 0x1dc22,
- 0x1cc16, 0x19824, 0x19822, 0x11028, 0x13068, 0x170e8, 0x11022, 0x13062,
- 0x18560, 0x10a40, 0x18530, 0x10a20, 0x18518, 0x1c28e, 0x10a10, 0x1850c,
- 0x10a08, 0x18506, 0x10b60, 0x185b8, 0x1c2de, 0x10b30, 0x1859c, 0x10b18,
- 0x1858e, 0x10b0c, 0x10b06, 0x10bb8, 0x185de, 0x10b9c, 0x10b8e, 0x10bde,
- 0x18d40, 0x1c6b0, 0x1e35c, 0x18d20, 0x1c698, 0x18d10, 0x1c68c, 0x18d08,
- 0x1c686, 0x18d04, 0x10940, 0x184b0, 0x1c25c, 0x11b40, 0x10920, 0x1c6dc,
- 0x1c24e, 0x11b20, 0x18d98, 0x1c6ce, 0x11b10, 0x10908, 0x18486, 0x11b08,
- 0x18d86, 0x10902, 0x109b0, 0x184dc, 0x11bb0, 0x10998, 0x184ce, 0x11b98,
- 0x18dce, 0x11b8c, 0x10986, 0x109dc, 0x11bdc, 0x109ce, 0x11bce, 0x1cea0,
- 0x1e758, 0x1f3ae, 0x1ce90, 0x1e74c, 0x1ce88, 0x1e746, 0x1ce84, 0x1ce82,
- 0x18ca0, 0x1c658, 0x19da0, 0x18c90, 0x1c64c, 0x19d90, 0x1cecc, 0x1c646,
- 0x19d88, 0x18c84, 0x19d84, 0x18c82, 0x19d82, 0x108a0, 0x18458, 0x119a0,
- 0x10890, 0x1c66e, 0x13ba0, 0x11990, 0x18ccc, 0x18446, 0x13b90, 0x19dcc,
- 0x10884, 0x13b88, 0x11984, 0x10882, 0x11982, 0x108d8, 0x1846e, 0x119d8,
- 0x108cc, 0x13bd8, 0x119cc, 0x108c6, 0x13bcc, 0x119c6, 0x108ee, 0x119ee,
- 0x13bee, 0x1ef50, 0x1f7ac, 0x1ef48, 0x1f7a6, 0x1ef44, 0x1ef42, 0x1ce50,
- 0x1e72c, 0x1ded0, 0x1ef6c, 0x1e726, 0x1dec8, 0x1ef66, 0x1dec4, 0x1ce42,
- 0x1dec2, 0x18c50, 0x1c62c, 0x19cd0, 0x18c48, 0x1c626, 0x1bdd0, 0x19cc8,
- 0x1ce66, 0x1bdc8, 0x1dee6, 0x18c42, 0x1bdc4, 0x19cc2, 0x1bdc2, 0x10850,
- 0x1842c, 0x118d0, 0x10848, 0x18426, 0x139d0, 0x118c8, 0x18c66, 0x17bd0,
- 0x139c8, 0x19ce6, 0x10842, 0x17bc8, 0x1bde6, 0x118c2, 0x17bc4, 0x1086c,
- 0x118ec, 0x10866, 0x139ec, 0x118e6, 0x17bec, 0x139e6, 0x17be6, 0x1ef28,
- 0x1f796, 0x1ef24, 0x1ef22, 0x1ce28, 0x1e716, 0x1de68, 0x1ef36, 0x1de64,
- 0x1ce22, 0x1de62, 0x18c28, 0x1c616, 0x19c68, 0x18c24, 0x1bce8, 0x19c64,
- 0x18c22, 0x1bce4, 0x19c62, 0x1bce2, 0x10828, 0x18416, 0x11868, 0x18c36,
- 0x138e8, 0x11864, 0x10822, 0x179e8, 0x138e4, 0x11862, 0x179e4, 0x138e2,
- 0x179e2, 0x11876, 0x179f6, 0x1ef12, 0x1de34, 0x1de32, 0x19c34, 0x1bc74,
- 0x1bc72, 0x11834, 0x13874, 0x178f4, 0x178f2, 0x10540, 0x10520, 0x18298,
- 0x10510, 0x10508, 0x10504, 0x105b0, 0x10598, 0x1058c, 0x10586, 0x105dc,
- 0x105ce, 0x186a0, 0x18690, 0x1c34c, 0x18688, 0x1c346, 0x18684, 0x18682,
- 0x104a0, 0x18258, 0x10da0, 0x186d8, 0x1824c, 0x10d90, 0x186cc, 0x10d88,
- 0x186c6, 0x10d84, 0x10482, 0x10d82, 0x104d8, 0x1826e, 0x10dd8, 0x186ee,
- 0x10dcc, 0x104c6, 0x10dc6, 0x104ee, 0x10dee, 0x1c750, 0x1c748, 0x1c744,
- 0x1c742, 0x18650, 0x18ed0, 0x1c76c, 0x1c326, 0x18ec8, 0x1c766, 0x18ec4,
- 0x18642, 0x18ec2, 0x10450, 0x10cd0, 0x10448, 0x18226, 0x11dd0, 0x10cc8,
- 0x10444, 0x11dc8, 0x10cc4, 0x10442, 0x11dc4, 0x10cc2, 0x1046c, 0x10cec,
- 0x10466, 0x11dec, 0x10ce6, 0x11de6, 0x1e7a8, 0x1e7a4, 0x1e7a2, 0x1c728,
- 0x1cf68, 0x1e7b6, 0x1cf64, 0x1c722, 0x1cf62, 0x18628, 0x1c316, 0x18e68,
- 0x1c736, 0x19ee8, 0x18e64, 0x18622, 0x19ee4, 0x18e62, 0x19ee2, 0x10428,
- 0x18216, 0x10c68, 0x18636, 0x11ce8, 0x10c64, 0x10422, 0x13de8, 0x11ce4,
- 0x10c62, 0x13de4, 0x11ce2, 0x10436, 0x10c76, 0x11cf6, 0x13df6, 0x1f7d4,
- 0x1f7d2, 0x1e794, 0x1efb4, 0x1e792, 0x1efb2, 0x1c714, 0x1cf34, 0x1c712,
- 0x1df74, 0x1cf32, 0x1df72, 0x18614, 0x18e34, 0x18612, 0x19e74, 0x18e32,
- 0x1bef4
- }, {
- 0x1f560, 0x1fab8, 0x1ea40, 0x1f530, 0x1fa9c, 0x1ea20, 0x1f518, 0x1fa8e,
- 0x1ea10, 0x1f50c, 0x1ea08, 0x1f506, 0x1ea04, 0x1eb60, 0x1f5b8, 0x1fade,
- 0x1d640, 0x1eb30, 0x1f59c, 0x1d620, 0x1eb18, 0x1f58e, 0x1d610, 0x1eb0c,
- 0x1d608, 0x1eb06, 0x1d604, 0x1d760, 0x1ebb8, 0x1f5de, 0x1ae40, 0x1d730,
- 0x1eb9c, 0x1ae20, 0x1d718, 0x1eb8e, 0x1ae10, 0x1d70c, 0x1ae08, 0x1d706,
- 0x1ae04, 0x1af60, 0x1d7b8, 0x1ebde, 0x15e40, 0x1af30, 0x1d79c, 0x15e20,
- 0x1af18, 0x1d78e, 0x15e10, 0x1af0c, 0x15e08, 0x1af06, 0x15f60, 0x1afb8,
- 0x1d7de, 0x15f30, 0x1af9c, 0x15f18, 0x1af8e, 0x15f0c, 0x15fb8, 0x1afde,
- 0x15f9c, 0x15f8e, 0x1e940, 0x1f4b0, 0x1fa5c, 0x1e920, 0x1f498, 0x1fa4e,
- 0x1e910, 0x1f48c, 0x1e908, 0x1f486, 0x1e904, 0x1e902, 0x1d340, 0x1e9b0,
- 0x1f4dc, 0x1d320, 0x1e998, 0x1f4ce, 0x1d310, 0x1e98c, 0x1d308, 0x1e986,
- 0x1d304, 0x1d302, 0x1a740, 0x1d3b0, 0x1e9dc, 0x1a720, 0x1d398, 0x1e9ce,
- 0x1a710, 0x1d38c, 0x1a708, 0x1d386, 0x1a704, 0x1a702, 0x14f40, 0x1a7b0,
- 0x1d3dc, 0x14f20, 0x1a798, 0x1d3ce, 0x14f10, 0x1a78c, 0x14f08, 0x1a786,
- 0x14f04, 0x14fb0, 0x1a7dc, 0x14f98, 0x1a7ce, 0x14f8c, 0x14f86, 0x14fdc,
- 0x14fce, 0x1e8a0, 0x1f458, 0x1fa2e, 0x1e890, 0x1f44c, 0x1e888, 0x1f446,
- 0x1e884, 0x1e882, 0x1d1a0, 0x1e8d8, 0x1f46e, 0x1d190, 0x1e8cc, 0x1d188,
- 0x1e8c6, 0x1d184, 0x1d182, 0x1a3a0, 0x1d1d8, 0x1e8ee, 0x1a390, 0x1d1cc,
- 0x1a388, 0x1d1c6, 0x1a384, 0x1a382, 0x147a0, 0x1a3d8, 0x1d1ee, 0x14790,
- 0x1a3cc, 0x14788, 0x1a3c6, 0x14784, 0x14782, 0x147d8, 0x1a3ee, 0x147cc,
- 0x147c6, 0x147ee, 0x1e850, 0x1f42c, 0x1e848, 0x1f426, 0x1e844, 0x1e842,
- 0x1d0d0, 0x1e86c, 0x1d0c8, 0x1e866, 0x1d0c4, 0x1d0c2, 0x1a1d0, 0x1d0ec,
- 0x1a1c8, 0x1d0e6, 0x1a1c4, 0x1a1c2, 0x143d0, 0x1a1ec, 0x143c8, 0x1a1e6,
- 0x143c4, 0x143c2, 0x143ec, 0x143e6, 0x1e828, 0x1f416, 0x1e824, 0x1e822,
- 0x1d068, 0x1e836, 0x1d064, 0x1d062, 0x1a0e8, 0x1d076, 0x1a0e4, 0x1a0e2,
- 0x141e8, 0x1a0f6, 0x141e4, 0x141e2, 0x1e814, 0x1e812, 0x1d034, 0x1d032,
- 0x1a074, 0x1a072, 0x1e540, 0x1f2b0, 0x1f95c, 0x1e520, 0x1f298, 0x1f94e,
- 0x1e510, 0x1f28c, 0x1e508, 0x1f286, 0x1e504, 0x1e502, 0x1cb40, 0x1e5b0,
- 0x1f2dc, 0x1cb20, 0x1e598, 0x1f2ce, 0x1cb10, 0x1e58c, 0x1cb08, 0x1e586,
- 0x1cb04, 0x1cb02, 0x19740, 0x1cbb0, 0x1e5dc, 0x19720, 0x1cb98, 0x1e5ce,
- 0x19710, 0x1cb8c, 0x19708, 0x1cb86, 0x19704, 0x19702, 0x12f40, 0x197b0,
- 0x1cbdc, 0x12f20, 0x19798, 0x1cbce, 0x12f10, 0x1978c, 0x12f08, 0x19786,
- 0x12f04, 0x12fb0, 0x197dc, 0x12f98, 0x197ce, 0x12f8c, 0x12f86, 0x12fdc,
- 0x12fce, 0x1f6a0, 0x1fb58, 0x16bf0, 0x1f690, 0x1fb4c, 0x169f8, 0x1f688,
- 0x1fb46, 0x168fc, 0x1f684, 0x1f682, 0x1e4a0, 0x1f258, 0x1f92e, 0x1eda0,
- 0x1e490, 0x1fb6e, 0x1ed90, 0x1f6cc, 0x1f246, 0x1ed88, 0x1e484, 0x1ed84,
- 0x1e482, 0x1ed82, 0x1c9a0, 0x1e4d8, 0x1f26e, 0x1dba0, 0x1c990, 0x1e4cc,
- 0x1db90, 0x1edcc, 0x1e4c6, 0x1db88, 0x1c984, 0x1db84, 0x1c982, 0x1db82,
- 0x193a0, 0x1c9d8, 0x1e4ee, 0x1b7a0, 0x19390, 0x1c9cc, 0x1b790, 0x1dbcc,
- 0x1c9c6, 0x1b788, 0x19384, 0x1b784, 0x19382, 0x1b782, 0x127a0, 0x193d8,
- 0x1c9ee, 0x16fa0, 0x12790, 0x193cc, 0x16f90, 0x1b7cc, 0x193c6, 0x16f88,
- 0x12784, 0x16f84, 0x12782, 0x127d8, 0x193ee, 0x16fd8, 0x127cc, 0x16fcc,
- 0x127c6, 0x16fc6, 0x127ee, 0x1f650, 0x1fb2c, 0x165f8, 0x1f648, 0x1fb26,
- 0x164fc, 0x1f644, 0x1647e, 0x1f642, 0x1e450, 0x1f22c, 0x1ecd0, 0x1e448,
- 0x1f226, 0x1ecc8, 0x1f666, 0x1ecc4, 0x1e442, 0x1ecc2, 0x1c8d0, 0x1e46c,
- 0x1d9d0, 0x1c8c8, 0x1e466, 0x1d9c8, 0x1ece6, 0x1d9c4, 0x1c8c2, 0x1d9c2,
- 0x191d0, 0x1c8ec, 0x1b3d0, 0x191c8, 0x1c8e6, 0x1b3c8, 0x1d9e6, 0x1b3c4,
- 0x191c2, 0x1b3c2, 0x123d0, 0x191ec, 0x167d0, 0x123c8, 0x191e6, 0x167c8,
- 0x1b3e6, 0x167c4, 0x123c2, 0x167c2, 0x123ec, 0x167ec, 0x123e6, 0x167e6,
- 0x1f628, 0x1fb16, 0x162fc, 0x1f624, 0x1627e, 0x1f622, 0x1e428, 0x1f216,
- 0x1ec68, 0x1f636, 0x1ec64, 0x1e422, 0x1ec62, 0x1c868, 0x1e436, 0x1d8e8,
- 0x1c864, 0x1d8e4, 0x1c862, 0x1d8e2, 0x190e8, 0x1c876, 0x1b1e8, 0x1d8f6,
- 0x1b1e4, 0x190e2, 0x1b1e2, 0x121e8, 0x190f6, 0x163e8, 0x121e4, 0x163e4,
- 0x121e2, 0x163e2, 0x121f6, 0x163f6, 0x1f614, 0x1617e, 0x1f612, 0x1e414,
- 0x1ec34, 0x1e412, 0x1ec32, 0x1c834, 0x1d874, 0x1c832, 0x1d872, 0x19074,
- 0x1b0f4, 0x19072, 0x1b0f2, 0x120f4, 0x161f4, 0x120f2, 0x161f2, 0x1f60a,
- 0x1e40a, 0x1ec1a, 0x1c81a, 0x1d83a, 0x1903a, 0x1b07a, 0x1e2a0, 0x1f158,
- 0x1f8ae, 0x1e290, 0x1f14c, 0x1e288, 0x1f146, 0x1e284, 0x1e282, 0x1c5a0,
- 0x1e2d8, 0x1f16e, 0x1c590, 0x1e2cc, 0x1c588, 0x1e2c6, 0x1c584, 0x1c582,
- 0x18ba0, 0x1c5d8, 0x1e2ee, 0x18b90, 0x1c5cc, 0x18b88, 0x1c5c6, 0x18b84,
- 0x18b82, 0x117a0, 0x18bd8, 0x1c5ee, 0x11790, 0x18bcc, 0x11788, 0x18bc6,
- 0x11784, 0x11782, 0x117d8, 0x18bee, 0x117cc, 0x117c6, 0x117ee, 0x1f350,
- 0x1f9ac, 0x135f8, 0x1f348, 0x1f9a6, 0x134fc, 0x1f344, 0x1347e, 0x1f342,
- 0x1e250, 0x1f12c, 0x1e6d0, 0x1e248, 0x1f126, 0x1e6c8, 0x1f366, 0x1e6c4,
- 0x1e242, 0x1e6c2, 0x1c4d0, 0x1e26c, 0x1cdd0, 0x1c4c8, 0x1e266, 0x1cdc8,
- 0x1e6e6, 0x1cdc4, 0x1c4c2, 0x1cdc2, 0x189d0, 0x1c4ec, 0x19bd0, 0x189c8,
- 0x1c4e6, 0x19bc8, 0x1cde6, 0x19bc4, 0x189c2, 0x19bc2, 0x113d0, 0x189ec,
- 0x137d0, 0x113c8, 0x189e6, 0x137c8, 0x19be6, 0x137c4, 0x113c2, 0x137c2,
- 0x113ec, 0x137ec, 0x113e6, 0x137e6, 0x1fba8, 0x175f0, 0x1bafc, 0x1fba4,
- 0x174f8, 0x1ba7e, 0x1fba2, 0x1747c, 0x1743e, 0x1f328, 0x1f996, 0x132fc,
- 0x1f768, 0x1fbb6, 0x176fc, 0x1327e, 0x1f764, 0x1f322, 0x1767e, 0x1f762,
- 0x1e228, 0x1f116, 0x1e668, 0x1e224, 0x1eee8, 0x1f776, 0x1e222, 0x1eee4,
- 0x1e662, 0x1eee2, 0x1c468, 0x1e236, 0x1cce8, 0x1c464, 0x1dde8, 0x1cce4,
- 0x1c462, 0x1dde4, 0x1cce2, 0x1dde2, 0x188e8, 0x1c476, 0x199e8, 0x188e4,
- 0x1bbe8, 0x199e4, 0x188e2, 0x1bbe4, 0x199e2, 0x1bbe2, 0x111e8, 0x188f6,
- 0x133e8, 0x111e4, 0x177e8, 0x133e4, 0x111e2, 0x177e4, 0x133e2, 0x177e2,
- 0x111f6, 0x133f6, 0x1fb94, 0x172f8, 0x1b97e, 0x1fb92, 0x1727c, 0x1723e,
- 0x1f314, 0x1317e, 0x1f734, 0x1f312, 0x1737e, 0x1f732, 0x1e214, 0x1e634,
- 0x1e212, 0x1ee74, 0x1e632, 0x1ee72, 0x1c434, 0x1cc74, 0x1c432, 0x1dcf4,
- 0x1cc72, 0x1dcf2, 0x18874, 0x198f4, 0x18872, 0x1b9f4, 0x198f2, 0x1b9f2,
- 0x110f4, 0x131f4, 0x110f2, 0x173f4, 0x131f2, 0x173f2, 0x1fb8a, 0x1717c,
- 0x1713e, 0x1f30a, 0x1f71a, 0x1e20a, 0x1e61a, 0x1ee3a, 0x1c41a, 0x1cc3a,
- 0x1dc7a, 0x1883a, 0x1987a, 0x1b8fa, 0x1107a, 0x130fa, 0x171fa, 0x170be,
- 0x1e150, 0x1f0ac, 0x1e148, 0x1f0a6, 0x1e144, 0x1e142, 0x1c2d0, 0x1e16c,
- 0x1c2c8, 0x1e166, 0x1c2c4, 0x1c2c2, 0x185d0, 0x1c2ec, 0x185c8, 0x1c2e6,
- 0x185c4, 0x185c2, 0x10bd0, 0x185ec, 0x10bc8, 0x185e6, 0x10bc4, 0x10bc2,
- 0x10bec, 0x10be6, 0x1f1a8, 0x1f8d6, 0x11afc, 0x1f1a4, 0x11a7e, 0x1f1a2,
- 0x1e128, 0x1f096, 0x1e368, 0x1e124, 0x1e364, 0x1e122, 0x1e362, 0x1c268,
- 0x1e136, 0x1c6e8, 0x1c264, 0x1c6e4, 0x1c262, 0x1c6e2, 0x184e8, 0x1c276,
- 0x18de8, 0x184e4, 0x18de4, 0x184e2, 0x18de2, 0x109e8, 0x184f6, 0x11be8,
- 0x109e4, 0x11be4, 0x109e2, 0x11be2, 0x109f6, 0x11bf6, 0x1f9d4, 0x13af8,
- 0x19d7e, 0x1f9d2, 0x13a7c, 0x13a3e, 0x1f194, 0x1197e, 0x1f3b4, 0x1f192,
- 0x13b7e, 0x1f3b2, 0x1e114, 0x1e334, 0x1e112, 0x1e774, 0x1e332, 0x1e772,
- 0x1c234, 0x1c674, 0x1c232, 0x1cef4, 0x1c672, 0x1cef2, 0x18474, 0x18cf4,
- 0x18472, 0x19df4, 0x18cf2, 0x19df2, 0x108f4, 0x119f4, 0x108f2, 0x13bf4,
- 0x119f2, 0x13bf2, 0x17af0, 0x1bd7c, 0x17a78, 0x1bd3e, 0x17a3c, 0x17a1e,
- 0x1f9ca, 0x1397c, 0x1fbda, 0x17b7c, 0x1393e, 0x17b3e, 0x1f18a, 0x1f39a,
- 0x1f7ba, 0x1e10a, 0x1e31a, 0x1e73a, 0x1ef7a, 0x1c21a, 0x1c63a, 0x1ce7a,
- 0x1defa, 0x1843a, 0x18c7a, 0x19cfa, 0x1bdfa, 0x1087a, 0x118fa, 0x139fa,
- 0x17978, 0x1bcbe, 0x1793c, 0x1791e, 0x138be, 0x179be, 0x178bc, 0x1789e,
- 0x1785e, 0x1e0a8, 0x1e0a4, 0x1e0a2, 0x1c168, 0x1e0b6, 0x1c164, 0x1c162,
- 0x182e8, 0x1c176, 0x182e4, 0x182e2, 0x105e8, 0x182f6, 0x105e4, 0x105e2,
- 0x105f6, 0x1f0d4, 0x10d7e, 0x1f0d2, 0x1e094, 0x1e1b4, 0x1e092, 0x1e1b2,
- 0x1c134, 0x1c374, 0x1c132, 0x1c372, 0x18274, 0x186f4, 0x18272, 0x186f2,
- 0x104f4, 0x10df4, 0x104f2, 0x10df2, 0x1f8ea, 0x11d7c, 0x11d3e, 0x1f0ca,
- 0x1f1da, 0x1e08a, 0x1e19a, 0x1e3ba, 0x1c11a, 0x1c33a, 0x1c77a, 0x1823a,
- 0x1867a, 0x18efa, 0x1047a, 0x10cfa, 0x11dfa, 0x13d78, 0x19ebe, 0x13d3c,
- 0x13d1e, 0x11cbe, 0x13dbe, 0x17d70, 0x1bebc, 0x17d38, 0x1be9e, 0x17d1c,
- 0x17d0e, 0x13cbc, 0x17dbc, 0x13c9e, 0x17d9e, 0x17cb8, 0x1be5e, 0x17c9c,
- 0x17c8e, 0x13c5e, 0x17cde, 0x17c5c, 0x17c4e, 0x17c2e, 0x1c0b4, 0x1c0b2,
- 0x18174, 0x18172, 0x102f4, 0x102f2, 0x1e0da, 0x1c09a, 0x1c1ba, 0x1813a,
- 0x1837a, 0x1027a, 0x106fa, 0x10ebe, 0x11ebc, 0x11e9e, 0x13eb8, 0x19f5e,
- 0x13e9c, 0x13e8e, 0x11e5e, 0x13ede, 0x17eb0, 0x1bf5c, 0x17e98, 0x1bf4e,
- 0x17e8c, 0x17e86, 0x13e5c, 0x17edc, 0x13e4e, 0x17ece, 0x17e58, 0x1bf2e,
- 0x17e4c, 0x17e46, 0x13e2e, 0x17e6e, 0x17e2c, 0x17e26, 0x10f5e, 0x11f5c,
- 0x11f4e, 0x13f58, 0x19fae, 0x13f4c, 0x13f46, 0x11f2e, 0x13f6e, 0x13f2c,
- 0x13f26
- }, {
- 0x1abe0, 0x1d5f8, 0x153c0, 0x1a9f0, 0x1d4fc, 0x151e0, 0x1a8f8, 0x1d47e,
- 0x150f0, 0x1a87c, 0x15078, 0x1fad0, 0x15be0, 0x1adf8, 0x1fac8, 0x159f0,
- 0x1acfc, 0x1fac4, 0x158f8, 0x1ac7e, 0x1fac2, 0x1587c, 0x1f5d0, 0x1faec,
- 0x15df8, 0x1f5c8, 0x1fae6, 0x15cfc, 0x1f5c4, 0x15c7e, 0x1f5c2, 0x1ebd0,
- 0x1f5ec, 0x1ebc8, 0x1f5e6, 0x1ebc4, 0x1ebc2, 0x1d7d0, 0x1ebec, 0x1d7c8,
- 0x1ebe6, 0x1d7c4, 0x1d7c2, 0x1afd0, 0x1d7ec, 0x1afc8, 0x1d7e6, 0x1afc4,
- 0x14bc0, 0x1a5f0, 0x1d2fc, 0x149e0, 0x1a4f8, 0x1d27e, 0x148f0, 0x1a47c,
- 0x14878, 0x1a43e, 0x1483c, 0x1fa68, 0x14df0, 0x1a6fc, 0x1fa64, 0x14cf8,
- 0x1a67e, 0x1fa62, 0x14c7c, 0x14c3e, 0x1f4e8, 0x1fa76, 0x14efc, 0x1f4e4,
- 0x14e7e, 0x1f4e2, 0x1e9e8, 0x1f4f6, 0x1e9e4, 0x1e9e2, 0x1d3e8, 0x1e9f6,
- 0x1d3e4, 0x1d3e2, 0x1a7e8, 0x1d3f6, 0x1a7e4, 0x1a7e2, 0x145e0, 0x1a2f8,
- 0x1d17e, 0x144f0, 0x1a27c, 0x14478, 0x1a23e, 0x1443c, 0x1441e, 0x1fa34,
- 0x146f8, 0x1a37e, 0x1fa32, 0x1467c, 0x1463e, 0x1f474, 0x1477e, 0x1f472,
- 0x1e8f4, 0x1e8f2, 0x1d1f4, 0x1d1f2, 0x1a3f4, 0x1a3f2, 0x142f0, 0x1a17c,
- 0x14278, 0x1a13e, 0x1423c, 0x1421e, 0x1fa1a, 0x1437c, 0x1433e, 0x1f43a,
- 0x1e87a, 0x1d0fa, 0x14178, 0x1a0be, 0x1413c, 0x1411e, 0x141be, 0x140bc,
- 0x1409e, 0x12bc0, 0x195f0, 0x1cafc, 0x129e0, 0x194f8, 0x1ca7e, 0x128f0,
- 0x1947c, 0x12878, 0x1943e, 0x1283c, 0x1f968, 0x12df0, 0x196fc, 0x1f964,
- 0x12cf8, 0x1967e, 0x1f962, 0x12c7c, 0x12c3e, 0x1f2e8, 0x1f976, 0x12efc,
- 0x1f2e4, 0x12e7e, 0x1f2e2, 0x1e5e8, 0x1f2f6, 0x1e5e4, 0x1e5e2, 0x1cbe8,
- 0x1e5f6, 0x1cbe4, 0x1cbe2, 0x197e8, 0x1cbf6, 0x197e4, 0x197e2, 0x1b5e0,
- 0x1daf8, 0x1ed7e, 0x169c0, 0x1b4f0, 0x1da7c, 0x168e0, 0x1b478, 0x1da3e,
- 0x16870, 0x1b43c, 0x16838, 0x1b41e, 0x1681c, 0x125e0, 0x192f8, 0x1c97e,
- 0x16de0, 0x124f0, 0x1927c, 0x16cf0, 0x1b67c, 0x1923e, 0x16c78, 0x1243c,
- 0x16c3c, 0x1241e, 0x16c1e, 0x1f934, 0x126f8, 0x1937e, 0x1fb74, 0x1f932,
- 0x16ef8, 0x1267c, 0x1fb72, 0x16e7c, 0x1263e, 0x16e3e, 0x1f274, 0x1277e,
- 0x1f6f4, 0x1f272, 0x16f7e, 0x1f6f2, 0x1e4f4, 0x1edf4, 0x1e4f2, 0x1edf2,
- 0x1c9f4, 0x1dbf4, 0x1c9f2, 0x1dbf2, 0x193f4, 0x193f2, 0x165c0, 0x1b2f0,
- 0x1d97c, 0x164e0, 0x1b278, 0x1d93e, 0x16470, 0x1b23c, 0x16438, 0x1b21e,
- 0x1641c, 0x1640e, 0x122f0, 0x1917c, 0x166f0, 0x12278, 0x1913e, 0x16678,
- 0x1b33e, 0x1663c, 0x1221e, 0x1661e, 0x1f91a, 0x1237c, 0x1fb3a, 0x1677c,
- 0x1233e, 0x1673e, 0x1f23a, 0x1f67a, 0x1e47a, 0x1ecfa, 0x1c8fa, 0x1d9fa,
- 0x191fa, 0x162e0, 0x1b178, 0x1d8be, 0x16270, 0x1b13c, 0x16238, 0x1b11e,
- 0x1621c, 0x1620e, 0x12178, 0x190be, 0x16378, 0x1213c, 0x1633c, 0x1211e,
- 0x1631e, 0x121be, 0x163be, 0x16170, 0x1b0bc, 0x16138, 0x1b09e, 0x1611c,
- 0x1610e, 0x120bc, 0x161bc, 0x1209e, 0x1619e, 0x160b8, 0x1b05e, 0x1609c,
- 0x1608e, 0x1205e, 0x160de, 0x1605c, 0x1604e, 0x115e0, 0x18af8, 0x1c57e,
- 0x114f0, 0x18a7c, 0x11478, 0x18a3e, 0x1143c, 0x1141e, 0x1f8b4, 0x116f8,
- 0x18b7e, 0x1f8b2, 0x1167c, 0x1163e, 0x1f174, 0x1177e, 0x1f172, 0x1e2f4,
- 0x1e2f2, 0x1c5f4, 0x1c5f2, 0x18bf4, 0x18bf2, 0x135c0, 0x19af0, 0x1cd7c,
- 0x134e0, 0x19a78, 0x1cd3e, 0x13470, 0x19a3c, 0x13438, 0x19a1e, 0x1341c,
- 0x1340e, 0x112f0, 0x1897c, 0x136f0, 0x11278, 0x1893e, 0x13678, 0x19b3e,
- 0x1363c, 0x1121e, 0x1361e, 0x1f89a, 0x1137c, 0x1f9ba, 0x1377c, 0x1133e,
- 0x1373e, 0x1f13a, 0x1f37a, 0x1e27a, 0x1e6fa, 0x1c4fa, 0x1cdfa, 0x189fa,
- 0x1bae0, 0x1dd78, 0x1eebe, 0x174c0, 0x1ba70, 0x1dd3c, 0x17460, 0x1ba38,
- 0x1dd1e, 0x17430, 0x1ba1c, 0x17418, 0x1ba0e, 0x1740c, 0x132e0, 0x19978,
- 0x1ccbe, 0x176e0, 0x13270, 0x1993c, 0x17670, 0x1bb3c, 0x1991e, 0x17638,
- 0x1321c, 0x1761c, 0x1320e, 0x1760e, 0x11178, 0x188be, 0x13378, 0x1113c,
- 0x17778, 0x1333c, 0x1111e, 0x1773c, 0x1331e, 0x1771e, 0x111be, 0x133be,
- 0x177be, 0x172c0, 0x1b970, 0x1dcbc, 0x17260, 0x1b938, 0x1dc9e, 0x17230,
- 0x1b91c, 0x17218, 0x1b90e, 0x1720c, 0x17206, 0x13170, 0x198bc, 0x17370,
- 0x13138, 0x1989e, 0x17338, 0x1b99e, 0x1731c, 0x1310e, 0x1730e, 0x110bc,
- 0x131bc, 0x1109e, 0x173bc, 0x1319e, 0x1739e, 0x17160, 0x1b8b8, 0x1dc5e,
- 0x17130, 0x1b89c, 0x17118, 0x1b88e, 0x1710c, 0x17106, 0x130b8, 0x1985e,
- 0x171b8, 0x1309c, 0x1719c, 0x1308e, 0x1718e, 0x1105e, 0x130de, 0x171de,
- 0x170b0, 0x1b85c, 0x17098, 0x1b84e, 0x1708c, 0x17086, 0x1305c, 0x170dc,
- 0x1304e, 0x170ce, 0x17058, 0x1b82e, 0x1704c, 0x17046, 0x1302e, 0x1706e,
- 0x1702c, 0x17026, 0x10af0, 0x1857c, 0x10a78, 0x1853e, 0x10a3c, 0x10a1e,
- 0x10b7c, 0x10b3e, 0x1f0ba, 0x1e17a, 0x1c2fa, 0x185fa, 0x11ae0, 0x18d78,
- 0x1c6be, 0x11a70, 0x18d3c, 0x11a38, 0x18d1e, 0x11a1c, 0x11a0e, 0x10978,
- 0x184be, 0x11b78, 0x1093c, 0x11b3c, 0x1091e, 0x11b1e, 0x109be, 0x11bbe,
- 0x13ac0, 0x19d70, 0x1cebc, 0x13a60, 0x19d38, 0x1ce9e, 0x13a30, 0x19d1c,
- 0x13a18, 0x19d0e, 0x13a0c, 0x13a06, 0x11970, 0x18cbc, 0x13b70, 0x11938,
- 0x18c9e, 0x13b38, 0x1191c, 0x13b1c, 0x1190e, 0x13b0e, 0x108bc, 0x119bc,
- 0x1089e, 0x13bbc, 0x1199e, 0x13b9e, 0x1bd60, 0x1deb8, 0x1ef5e, 0x17a40,
- 0x1bd30, 0x1de9c, 0x17a20, 0x1bd18, 0x1de8e, 0x17a10, 0x1bd0c, 0x17a08,
- 0x1bd06, 0x17a04, 0x13960, 0x19cb8, 0x1ce5e, 0x17b60, 0x13930, 0x19c9c,
- 0x17b30, 0x1bd9c, 0x19c8e, 0x17b18, 0x1390c, 0x17b0c, 0x13906, 0x17b06,
- 0x118b8, 0x18c5e, 0x139b8, 0x1189c, 0x17bb8, 0x1399c, 0x1188e, 0x17b9c,
- 0x1398e, 0x17b8e, 0x1085e, 0x118de, 0x139de, 0x17bde, 0x17940, 0x1bcb0,
- 0x1de5c, 0x17920, 0x1bc98, 0x1de4e, 0x17910, 0x1bc8c, 0x17908, 0x1bc86,
- 0x17904, 0x17902, 0x138b0, 0x19c5c, 0x179b0, 0x13898, 0x19c4e, 0x17998,
- 0x1bcce, 0x1798c, 0x13886, 0x17986, 0x1185c, 0x138dc, 0x1184e, 0x179dc,
- 0x138ce, 0x179ce, 0x178a0, 0x1bc58, 0x1de2e, 0x17890, 0x1bc4c, 0x17888,
- 0x1bc46, 0x17884, 0x17882, 0x13858, 0x19c2e, 0x178d8, 0x1384c, 0x178cc,
- 0x13846, 0x178c6, 0x1182e, 0x1386e, 0x178ee, 0x17850, 0x1bc2c, 0x17848,
- 0x1bc26, 0x17844, 0x17842, 0x1382c, 0x1786c, 0x13826, 0x17866, 0x17828,
- 0x1bc16, 0x17824, 0x17822, 0x13816, 0x17836, 0x10578, 0x182be, 0x1053c,
- 0x1051e, 0x105be, 0x10d70, 0x186bc, 0x10d38, 0x1869e, 0x10d1c, 0x10d0e,
- 0x104bc, 0x10dbc, 0x1049e, 0x10d9e, 0x11d60, 0x18eb8, 0x1c75e, 0x11d30,
- 0x18e9c, 0x11d18, 0x18e8e, 0x11d0c, 0x11d06, 0x10cb8, 0x1865e, 0x11db8,
- 0x10c9c, 0x11d9c, 0x10c8e, 0x11d8e, 0x1045e, 0x10cde, 0x11dde, 0x13d40,
- 0x19eb0, 0x1cf5c, 0x13d20, 0x19e98, 0x1cf4e, 0x13d10, 0x19e8c, 0x13d08,
- 0x19e86, 0x13d04, 0x13d02, 0x11cb0, 0x18e5c, 0x13db0, 0x11c98, 0x18e4e,
- 0x13d98, 0x19ece, 0x13d8c, 0x11c86, 0x13d86, 0x10c5c, 0x11cdc, 0x10c4e,
- 0x13ddc, 0x11cce, 0x13dce, 0x1bea0, 0x1df58, 0x1efae, 0x1be90, 0x1df4c,
- 0x1be88, 0x1df46, 0x1be84, 0x1be82, 0x13ca0, 0x19e58, 0x1cf2e, 0x17da0,
- 0x13c90, 0x19e4c, 0x17d90, 0x1becc, 0x19e46, 0x17d88, 0x13c84, 0x17d84,
- 0x13c82, 0x17d82, 0x11c58, 0x18e2e, 0x13cd8, 0x11c4c, 0x17dd8, 0x13ccc,
- 0x11c46, 0x17dcc, 0x13cc6, 0x17dc6, 0x10c2e, 0x11c6e, 0x13cee, 0x17dee,
- 0x1be50, 0x1df2c, 0x1be48, 0x1df26, 0x1be44, 0x1be42, 0x13c50, 0x19e2c,
- 0x17cd0, 0x13c48, 0x19e26, 0x17cc8, 0x1be66, 0x17cc4, 0x13c42, 0x17cc2,
- 0x11c2c, 0x13c6c, 0x11c26, 0x17cec, 0x13c66, 0x17ce6, 0x1be28, 0x1df16,
- 0x1be24, 0x1be22, 0x13c28, 0x19e16, 0x17c68, 0x13c24, 0x17c64, 0x13c22,
- 0x17c62, 0x11c16, 0x13c36, 0x17c76, 0x1be14, 0x1be12, 0x13c14, 0x17c34,
- 0x13c12, 0x17c32, 0x102bc, 0x1029e, 0x106b8, 0x1835e, 0x1069c, 0x1068e,
- 0x1025e, 0x106de, 0x10eb0, 0x1875c, 0x10e98, 0x1874e, 0x10e8c, 0x10e86,
- 0x1065c, 0x10edc, 0x1064e, 0x10ece, 0x11ea0, 0x18f58, 0x1c7ae, 0x11e90,
- 0x18f4c, 0x11e88, 0x18f46, 0x11e84, 0x11e82, 0x10e58, 0x1872e, 0x11ed8,
- 0x18f6e, 0x11ecc, 0x10e46, 0x11ec6, 0x1062e, 0x10e6e, 0x11eee, 0x19f50,
- 0x1cfac, 0x19f48, 0x1cfa6, 0x19f44, 0x19f42, 0x11e50, 0x18f2c, 0x13ed0,
- 0x19f6c, 0x18f26, 0x13ec8, 0x11e44, 0x13ec4, 0x11e42, 0x13ec2, 0x10e2c,
- 0x11e6c, 0x10e26, 0x13eec, 0x11e66, 0x13ee6, 0x1dfa8, 0x1efd6, 0x1dfa4,
- 0x1dfa2, 0x19f28, 0x1cf96, 0x1bf68, 0x19f24, 0x1bf64, 0x19f22, 0x1bf62,
- 0x11e28, 0x18f16, 0x13e68, 0x11e24, 0x17ee8, 0x13e64, 0x11e22, 0x17ee4,
- 0x13e62, 0x17ee2, 0x10e16, 0x11e36, 0x13e76, 0x17ef6, 0x1df94, 0x1df92,
- 0x19f14, 0x1bf34, 0x19f12, 0x1bf32, 0x11e14, 0x13e34, 0x11e12, 0x17e74,
- 0x13e32, 0x17e72, 0x1df8a, 0x19f0a, 0x1bf1a, 0x11e0a, 0x13e1a, 0x17e3a,
- 0x1035c, 0x1034e, 0x10758, 0x183ae, 0x1074c, 0x10746, 0x1032e, 0x1076e,
- 0x10f50, 0x187ac, 0x10f48, 0x187a6, 0x10f44, 0x10f42, 0x1072c, 0x10f6c,
- 0x10726, 0x10f66, 0x18fa8, 0x1c7d6, 0x18fa4, 0x18fa2, 0x10f28, 0x18796,
- 0x11f68, 0x18fb6, 0x11f64, 0x10f22, 0x11f62, 0x10716, 0x10f36, 0x11f76,
- 0x1cfd4, 0x1cfd2, 0x18f94, 0x19fb4, 0x18f92, 0x19fb2, 0x10f14, 0x11f34,
- 0x10f12, 0x13f74, 0x11f32, 0x13f72, 0x1cfca, 0x18f8a, 0x19f9a, 0x10f0a,
- 0x11f1a, 0x13f3a, 0x103ac, 0x103a6, 0x107a8, 0x183d6, 0x107a4, 0x107a2,
- 0x10396, 0x107b6, 0x187d4, 0x187d2, 0x10794, 0x10fb4, 0x10792, 0x10fb2,
- 0x1c7ea
- }};
-
- static int ERROR_LEVEL[][] =
- {{
- 27, 917
- }, {
- 522, 568, 723, 809
- }, {
- 237, 308, 436, 284, 646, 653, 428, 379
- }, {
- 274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, 42, 176, 65
- }, {
- 361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517,
- 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410
- }, {
- 539, 422, 6, 93, 862, 771, 453, 106, 610, 287, 107, 505, 733, 877, 381, 612,
- 723, 476, 462, 172, 430, 609, 858, 822, 543, 376, 511, 400, 672, 762, 283, 184,
- 440, 35, 519, 31, 460, 594, 225, 535, 517, 352, 605, 158, 651, 201, 488, 502,
- 648, 733, 717, 83, 404, 97, 280, 771, 840, 629, 4, 381, 843, 623, 264, 543
- }, {
- 521, 310, 864, 547, 858, 580, 296, 379, 53, 779, 897, 444, 400, 925, 749, 415,
- 822, 93, 217, 208, 928, 244, 583, 620, 246, 148, 447, 631, 292, 908, 490, 704,
- 516, 258, 457, 907, 594, 723, 674, 292, 272, 96, 684, 432, 686, 606, 860, 569,
- 193, 219, 129, 186, 236, 287, 192, 775, 278, 173, 40, 379, 712, 463, 646, 776,
- 171, 491, 297, 763, 156, 732, 95, 270, 447, 90, 507, 48, 228, 821, 808, 898,
- 784, 663, 627, 378, 382, 262, 380, 602, 754, 336, 89, 614, 87, 432, 670, 616,
- 157, 374, 242, 726, 600, 269, 375, 898, 845, 454, 354, 130, 814, 587, 804, 34,
- 211, 330, 539, 297, 827, 865, 37, 517, 834, 315, 550, 86, 801, 4, 108, 539
- }, {
- 524, 894, 75, 766, 882, 857, 74, 204, 82, 586, 708, 250, 905, 786, 138, 720,
- 858, 194, 311, 913, 275, 190, 375, 850, 438, 733, 194, 280, 201, 280, 828, 757,
- 710, 814, 919, 89, 68, 569, 11, 204, 796, 605, 540, 913, 801, 700, 799, 137,
- 439, 418, 592, 668, 353, 859, 370, 694, 325, 240, 216, 257, 284, 549, 209, 884,
- 315, 70, 329, 793, 490, 274, 877, 162, 749, 812, 684, 461, 334, 376, 849, 521,
- 307, 291, 803, 712, 19, 358, 399, 908, 103, 511, 51, 8, 517, 225, 289, 470,
- 637, 731, 66, 255, 917, 269, 463, 830, 730, 433, 848, 585, 136, 538, 906, 90,
- 2, 290, 743, 199, 655, 903, 329, 49, 802, 580, 355, 588, 188, 462, 10, 134,
- 628, 320, 479, 130, 739, 71, 263, 318, 374, 601, 192, 605, 142, 673, 687, 234,
- 722, 384, 177, 752, 607, 640, 455, 193, 689, 707, 805, 641, 48, 60, 732, 621,
- 895, 544, 261, 852, 655, 309, 697, 755, 756, 60, 231, 773, 434, 421, 726, 528,
- 503, 118, 49, 795, 32, 144, 500, 238, 836, 394, 280, 566, 319, 9, 647, 550,
- 73, 914, 342, 126, 32, 681, 331, 792, 620, 60, 609, 441, 180, 791, 893, 754,
- 605, 383, 228, 749, 760, 213, 54, 297, 134, 54, 834, 299, 922, 191, 910, 532,
- 609, 829, 189, 20, 167, 29, 872, 449, 83, 402, 41, 656, 505, 579, 481, 173,
- 404, 251, 688, 95, 497, 555, 642, 543, 307, 159, 924, 558, 648, 55, 497, 10
- }, {
- 352, 77, 373, 504, 35, 599, 428, 207, 409, 574, 118, 498, 285, 380, 350, 492,
- 197, 265, 920, 155, 914, 299, 229, 643, 294, 871, 306, 88, 87, 193, 352, 781,
- 846, 75, 327, 520, 435, 543, 203, 666, 249, 346, 781, 621, 640, 268, 794, 534,
- 539, 781, 408, 390, 644, 102, 476, 499, 290, 632, 545, 37, 858, 916, 552, 41,
- 542, 289, 122, 272, 383, 800, 485, 98, 752, 472, 761, 107, 784, 860, 658, 741,
- 290, 204, 681, 407, 855, 85, 99, 62, 482, 180, 20, 297, 451, 593, 913, 142,
- 808, 684, 287, 536, 561, 76, 653, 899, 729, 567, 744, 390, 513, 192, 516, 258,
- 240, 518, 794, 395, 768, 848, 51, 610, 384, 168, 190, 826, 328, 596, 786, 303,
- 570, 381, 415, 641, 156, 237, 151, 429, 531, 207, 676, 710, 89, 168, 304, 402,
- 40, 708, 575, 162, 864, 229, 65, 861, 841, 512, 164, 477, 221, 92, 358, 785,
- 288, 357, 850, 836, 827, 736, 707, 94, 8, 494, 114, 521, 2, 499, 851, 543,
- 152, 729, 771, 95, 248, 361, 578, 323, 856, 797, 289, 51, 684, 466, 533, 820,
- 669, 45, 902, 452, 167, 342, 244, 173, 35, 463, 651, 51, 699, 591, 452, 578,
- 37, 124, 298, 332, 552, 43, 427, 119, 662, 777, 475, 850, 764, 364, 578, 911,
- 283, 711, 472, 420, 245, 288, 594, 394, 511, 327, 589, 777, 699, 688, 43, 408,
- 842, 383, 721, 521, 560, 644, 714, 559, 62, 145, 873, 663, 713, 159, 672, 729,
- 624, 59, 193, 417, 158, 209, 563, 564, 343, 693, 109, 608, 563, 365, 181, 772,
- 677, 310, 248, 353, 708, 410, 579, 870, 617, 841, 632, 860, 289, 536, 35, 777,
- 618, 586, 424, 833, 77, 597, 346, 269, 757, 632, 695, 751, 331, 247, 184, 45,
- 787, 680, 18, 66, 407, 369, 54, 492, 228, 613, 830, 922, 437, 519, 644, 905,
- 789, 420, 305, 441, 207, 300, 892, 827, 141, 537, 381, 662, 513, 56, 252, 341,
- 242, 797, 838, 837, 720, 224, 307, 631, 61, 87, 560, 310, 756, 665, 397, 808,
- 851, 309, 473, 795, 378, 31, 647, 915, 459, 806, 590, 731, 425, 216, 548, 249,
- 321, 881, 699, 535, 673, 782, 210, 815, 905, 303, 843, 922, 281, 73, 469, 791,
- 660, 162, 498, 308, 155, 422, 907, 817, 187, 62, 16, 425, 535, 336, 286, 437,
- 375, 273, 610, 296, 183, 923, 116, 667, 751, 353, 62, 366, 691, 379, 687, 842,
- 37, 357, 720, 742, 330, 5, 39, 923, 311, 424, 242, 749, 321, 54, 669, 316,
- 342, 299, 534, 105, 667, 488, 640, 672, 576, 540, 316, 486, 721, 610, 46, 656,
- 447, 171, 616, 464, 190, 531, 297, 321, 762, 752, 533, 175, 134, 14, 381, 433,
- 717, 45, 111, 20, 596, 284, 736, 138, 646, 411, 877, 669, 141, 919, 45, 780,
- 407, 164, 332, 899, 165, 726, 600, 325, 498, 655, 357, 752, 768, 223, 849, 647,
- 63, 310, 863, 251, 366, 304, 282, 738, 675, 410, 389, 244, 31, 121, 303, 263
- }};
-
- /** Holds value of property outBits. */
- private byte[] outBits;
-
- /** Holds value of property bitColumns. */
- private int bitColumns;
-
- /** Holds value of property codeRows. */
- private int codeRows;
-
- /** Holds value of property codeColumns. */
- private int codeColumns;
-
- /** Holds value of property codewords. */
- private int[] codewords = new int[MAX_DATA_CODEWORDS + 2];
-
- /** Holds value of property lenCodewords. */
- private int lenCodewords;
-
- /** Holds value of property errorLevel. */
- private int errorLevel;
-
- /** Holds value of property text. */
- private byte[] text;
-
- /** Holds value of property options. */
- private int options;
-
- /** Holds value of property aspectRatio. */
- private float aspectRatio;
-
- /** Holds value of property yHeight. */
- private float yHeight;
-
- protected static class Segment {
- public char type;
- public int start;
- public int end;
-
- public Segment(char type, int start, int end) {
- this.type = type;
- this.start = start;
- this.end = end;
- }
- }
-
- protected static class SegmentList {
- protected ArrayList list = new ArrayList();
-
- public void add(char type, int start, int end) {
- list.add(new Segment(type, start, end));
- }
-
- public Segment get(int idx) {
- if (idx < 0 || idx >= list.size())
- return null;
- return (Segment)list.get(idx);
- }
-
- public void remove(int idx) {
- if (idx < 0 || idx >= list.size())
- return;
- list.remove(idx);
- }
-
- public int size() {
- return list.size();
- }
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/BarcodePostnet.java pdftk-2.01/java/com/lowagie/text/pdf/BarcodePostnet.java
--- pdftk-1.45/java/com/lowagie/text/pdf/BarcodePostnet.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/BarcodePostnet.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,239 +0,0 @@
-/*
- * Copyright 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-import com.lowagie.text.Rectangle;
-import java.awt.Color;
-import java.awt.Image;
-import java.awt.Canvas;
-import java.awt.image.MemoryImageSource;
-
-/** Implements the Postnet and Planet barcodes. The default parameters are:
- *
- *n = 72f / 22f; // distance between bars
- *x = 0.02f * 72f; // bar width
- *barHeight = 0.125f * 72f; // height of the tall bars
- *size = 0.05f * 72f; // height of the short bars
- *codeType = POSTNET; // type of code
- *
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class BarcodePostnet extends Barcode{
-
- /** The bars for each character.
- */
- static byte BARS[][] =
- {
- {1,1,0,0,0},
- {0,0,0,1,1},
- {0,0,1,0,1},
- {0,0,1,1,0},
- {0,1,0,0,1},
- {0,1,0,1,0},
- {0,1,1,0,0},
- {1,0,0,0,1},
- {1,0,0,1,0},
- {1,0,1,0,0}
- };
-
- /** Creates new BarcodePostnet */
- public BarcodePostnet() {
- n = 72f / 22f; // distance between bars
- x = 0.02f * 72f; // bar width
- barHeight = 0.125f * 72f; // height of the tall bars
- size = 0.05f * 72f; // height of the short bars
- codeType = POSTNET; // type of code
- }
-
- /** Creates the bars for Postnet.
- * @param text the code to be created without checksum
- * @return the bars
- */
- public static byte[] getBarsPostnet(String text) {
- int total = 0;
- for (int k = text.length() - 1; k >= 0; --k) {
- int n = text.charAt(k) - '0';
- total += n;
- }
- text += (char)(((10 - (total % 10)) % 10) + '0');
- byte bars[] = new byte[text.length() * 5 + 2];
- bars[0] = 1;
- bars[bars.length - 1] = 1;
- for (int k = 0; k < text.length(); ++k) {
- int c = text.charAt(k) - '0';
- System.arraycopy(BARS[c], 0, bars, k * 5 + 1, 5);
- }
- return bars;
- }
-
- /** Gets the maximum area that the barcode and the text, if
- * any, will occupy. The lower left corner is always (0, 0).
- * @return the size the barcode occupies.
- */
- public Rectangle getBarcodeSize() {
- float width = ((code.length() + 1) * 5 + 1) * n + x;
- return new Rectangle(width, barHeight);
- }
-
- /** Places the barcode in a PdfContentByte
. The
- * barcode is always placed at coodinates (0, 0). Use the
- * translation matrix to move it elsewhere.
- * The bars and text are written in the following colors:
- *
- *
- * barColor
- * textColor
- * Result
- *
- *
- * null
- * null
- * bars and text painted with current fill color
- *
- *
- * barColor
- * null
- * bars and text painted with barColor
- *
- *
- * null
- * textColor
- * bars painted with current color text painted with textColor
- *
- *
- * barColor
- * textColor
- * bars painted with barColor
text painted with textColor
- *
- *
- * @param cb the PdfContentByte
where the barcode will be placed
- * @param barColor the color of the bars. It can be null
- * @param textColor the color of the text. It can be null
- * @return the dimensions the barcode occupies
- */
- public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
- if (barColor != null)
- cb.setColorFill(barColor);
- byte bars[] = getBarsPostnet(code);
- byte flip = 1;
- if (codeType == PLANET) {
- flip = 0;
- bars[0] = 0;
- bars[bars.length - 1] = 0;
- }
- float startX = 0;
- for (int k = 0; k < bars.length; ++k) {
- cb.rectangle(startX, 0, x - inkSpreading, bars[k] == flip ? barHeight : size);
- startX += n;
- }
- cb.fill();
- return getBarcodeSize();
- }
-
- /** Creates a java.awt.Image
. This image only
- * contains the bars without any text.
- * @param foreground the color of the bars
- * @param background the color of the background
- * @return the image
- *
- */
- public java.awt.Image createAwtImage(Color foreground, Color background) {
- int f = foreground.getRGB();
- int g = background.getRGB();
- Canvas canvas = new Canvas();
- int barWidth = (int)x;
- if (barWidth <= 0)
- barWidth = 1;
- int barDistance = (int)n;
- if (barDistance <= barWidth)
- barDistance = barWidth + 1;
- int barShort = (int)size;
- if (barShort <= 0)
- barShort = 1;
- int barTall = (int)barHeight;
- if (barTall <= barShort)
- barTall = barShort + 1;
- int width = ((code.length() + 1) * 5 + 1) * barDistance + barWidth;
- int pix[] = new int[width * barTall];
- byte bars[] = getBarsPostnet(code);
- byte flip = 1;
- if (codeType == PLANET) {
- flip = 0;
- bars[0] = 0;
- bars[bars.length - 1] = 0;
- }
- int idx = 0;
- for (int k = 0; k < bars.length; ++k) {
- boolean dot = (bars[k] == flip);
- for (int j = 0; j < barDistance; ++j) {
- pix[idx + j] = ((dot && j < barWidth) ? f : g);
- }
- idx += barDistance;
- }
- int limit = width * (barTall - barShort);
- for (int k = width; k < limit; k += width)
- System.arraycopy(pix, 0, pix, k, width);
- idx = limit;
- for (int k = 0; k < bars.length; ++k) {
- for (int j = 0; j < barDistance; ++j) {
- pix[idx + j] = ((j < barWidth) ? f : g);
- }
- idx += barDistance;
- }
- for (int k = limit + width; k < pix.length; k += width)
- System.arraycopy(pix, limit, pix, k, width);
- Image img = canvas.createImage(new MemoryImageSource(width, barTall, pix, 0, width));
-
- return img;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/BaseField.java pdftk-2.01/java/com/lowagie/text/pdf/BaseField.java
--- pdftk-1.45/java/com/lowagie/text/pdf/BaseField.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/BaseField.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,671 +0,0 @@
-/*
- * Copyright 2005 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.awt.Color;
-import com.lowagie.text.Element;
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.Rectangle;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.HashMap;
-
-/** Common field variables.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public abstract class BaseField {
-
- /** A thin border with 1 point width. */
- public static final float BORDER_WIDTH_THIN = 1;
- /** A medium border with 2 point width. */
- public static final float BORDER_WIDTH_MEDIUM = 2;
- /** A thick border with 3 point width. */
- public static final float BORDER_WIDTH_THICK = 3;
- /** The field is visible. */
- public static final int VISIBLE = 0;
- /** The field is hidden. */
- public static final int HIDDEN = 1;
- /** The field is visible but does not print. */
- public static final int VISIBLE_BUT_DOES_NOT_PRINT = 2;
- /** The field is hidden but is printable. */
- public static final int HIDDEN_BUT_PRINTABLE = 3;
- /** The user may not change the value of the field. */
- public static final int READ_ONLY = 1;
- /** The field must have a value at the time it is exported by a submit-form
- * action.
- */
- public static final int REQUIRED = 2;
- /** The field may contain multiple lines of text.
- * This flag is only meaningful with text fields.
- */
- public static final int MULTILINE = 4;
- /** The field will not scroll (horizontally for single-line
- * fields, vertically for multiple-line fields) to accommodate more text
- * than will fit within its annotation rectangle. Once the field is full, no
- * further text will be accepted.
- */
- public static final int DO_NOT_SCROLL = 8;
- /** The field is intended for entering a secure password that should
- * not be echoed visibly to the screen.
- */
- public static final int PASSWORD = 16;
- /** The text entered in the field represents the pathname of
- * a file whose contents are to be submitted as the value of the field.
- */
- public static final int FILE_SELECTION = 32;
- /** The text entered in the field will not be spell-checked.
- * This flag is meaningful only in text fields and in combo
- * fields with the EDIT
flag set.
- */
- public static final int DO_NOT_SPELL_CHECK = 64;
- /** If set the combo box includes an editable text box as well as a drop list; if
- * clear, it includes only a drop list.
- * This flag is only meaningful with combo fields.
- */
- public static final int EDIT = 128;
-
- /**
- * combo box flag.
- */
- public static final int COMB = 256;
-
- protected float borderWidth = BORDER_WIDTH_THIN;
- protected int borderStyle = PdfBorderDictionary.STYLE_SOLID;
- protected Color borderColor;
- protected Color backgroundColor;
- protected Color textColor;
- protected BaseFont font;
- protected float fontSize = 0;
- protected int alignment = Element.ALIGN_LEFT;
- protected PdfWriter writer;
- protected String text;
- protected Rectangle box;
-
- /** Holds value of property rotation. */
- protected int rotation = 0;
-
- /** Holds value of property visibility. */
- protected int visibility;
-
- /** Holds value of property fieldName. */
- protected String fieldName;
-
- /** Holds value of property options. */
- protected int options;
-
- /** Holds value of property maxCharacterLength. */
- protected int maxCharacterLength;
-
- private final static HashMap fieldKeys = new HashMap();
-
- static {
- fieldKeys.putAll(PdfCopyFieldsImp.fieldKeys);
- fieldKeys.put(PdfName.T, new Integer(1));
- }
- /** Creates a new TextField
.
- * @param writer the document PdfWriter
- * @param box the field location and dimensions
- * @param fieldName the field name. If null
only the widget keys
- * will be included in the field allowing it to be used as a kid field.
- */
- public BaseField(PdfWriter writer, Rectangle box, String fieldName) {
- this.writer = writer;
- this.box = box;
- this.fieldName = fieldName;
- }
-
- protected BaseFont getRealFont() throws IOException, DocumentException {
- if (font == null)
- return BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, false);
- else
- return font;
- }
-
- protected PdfAppearance getBorderAppearance() throws IOException, DocumentException {
- PdfAppearance app = writer.getDirectContent().createAppearance(box.width(), box.height());
- switch (rotation) {
- case 90:
- app.setMatrix(0, 1, -1, 0, box.height(), 0);
- break;
- case 180:
- app.setMatrix(-1, 0, 0, -1, box.width(), box.height());
- break;
- case 270:
- app.setMatrix(0, -1, 1, 0, 0, box.width());
- break;
- }
- // background
- if (backgroundColor != null) {
- app.setColorFill(backgroundColor);
- app.rectangle(0, 0, box.width(), box.height());
- app.fill();
- }
- // border
- if (borderStyle == PdfBorderDictionary.STYLE_UNDERLINE) {
- if (borderWidth != 0 && borderColor != null) {
- app.setColorStroke(borderColor);
- app.setLineWidth(borderWidth);
- app.moveTo(0, borderWidth / 2);
- app.lineTo(box.width(), borderWidth / 2);
- app.stroke();
- }
- }
- else if (borderStyle == PdfBorderDictionary.STYLE_BEVELED) {
- if (borderWidth != 0 && borderColor != null) {
- app.setColorStroke(borderColor);
- app.setLineWidth(borderWidth);
- app.rectangle(borderWidth / 2, borderWidth / 2, box.width() - borderWidth, box.height() - borderWidth);
- app.stroke();
- }
- // beveled
- Color actual = backgroundColor;
- if (actual == null)
- actual = Color.white;
- app.setGrayFill(1);
- drawTopFrame(app);
- app.setColorFill(actual.darker());
- drawBottomFrame(app);
- }
- else if (borderStyle == PdfBorderDictionary.STYLE_INSET) {
- if (borderWidth != 0 && borderColor != null) {
- app.setColorStroke(borderColor);
- app.setLineWidth(borderWidth);
- app.rectangle(borderWidth / 2, borderWidth / 2, box.width() - borderWidth, box.height() - borderWidth);
- app.stroke();
- }
- // inset
- app.setGrayFill(0.5f);
- drawTopFrame(app);
- app.setGrayFill(0.75f);
- drawBottomFrame(app);
- }
- else {
- if (borderWidth != 0 && borderColor != null) {
- if (borderStyle == PdfBorderDictionary.STYLE_DASHED)
- app.setLineDash(3, 0);
- app.setColorStroke(borderColor);
- app.setLineWidth(borderWidth);
- app.rectangle(borderWidth / 2, borderWidth / 2, box.width() - borderWidth, box.height() - borderWidth);
- app.stroke();
- if ((options & COMB) != 0 && maxCharacterLength > 1) {
- float step = box.width() / maxCharacterLength;
- float yb = borderWidth / 2;
- float yt = box.height() - borderWidth / 2;
- for (int k = 1; k < maxCharacterLength; ++k) {
- float x = step * k;
- app.moveTo(x, yb);
- app.lineTo(x, yt);
- }
- app.stroke();
- }
- }
- }
- return app;
- }
-
- protected static ArrayList getHardBreaks(String text) {
- ArrayList arr = new ArrayList();
- char cs[] = text.toCharArray();
- int len = cs.length;
- StringBuffer buf = new StringBuffer();
- for (int k = 0; k < len; ++k) {
- char c = cs[k];
- if (c == '\r') {
- if (k + 1 < len && cs[k + 1] == '\n')
- ++k;
- arr.add(buf.toString());
- buf = new StringBuffer();
- }
- else if (c == '\n') {
- arr.add(buf.toString());
- buf = new StringBuffer();
- }
- else
- buf.append(c);
- }
- arr.add(buf.toString());
- return arr;
- }
-
- protected static void trimRight(StringBuffer buf) {
- int len = buf.length();
- while (true) {
- if (len == 0)
- return;
- if (buf.charAt(--len) != ' ')
- return;
- buf.setLength(len);
- }
- }
-
- protected static ArrayList breakLines(ArrayList breaks, BaseFont font, float fontSize, float width) {
- ArrayList lines = new ArrayList();
- StringBuffer buf = new StringBuffer();
- for (int ck = 0; ck < breaks.size(); ++ck) {
- buf.setLength(0);
- float w = 0;
- char cs[] = ((String)breaks.get(ck)).toCharArray();
- int len = cs.length;
- // 0 inline first, 1 inline, 2 spaces
- int state = 0;
- int lastspace = -1;
- char c = 0;
- int refk = 0;
- for (int k = 0; k < len; ++k) {
- c = cs[k];
- switch (state) {
- case 0:
- w += font.getWidthPoint(c, fontSize);
- buf.append(c);
- if (w > width) {
- w = 0;
- if (buf.length() > 1) {
- --k;
- buf.setLength(buf.length() - 1);
- }
- lines.add(buf.toString());
- buf.setLength(0);
- refk = k;
- if (c == ' ')
- state = 2;
- else
- state = 1;
- }
- else {
- if (c != ' ')
- state = 1;
- }
- break;
- case 1:
- w += font.getWidthPoint(c, fontSize);
- buf.append(c);
- if (c == ' ')
- lastspace = k;
- if (w > width) {
- w = 0;
- if (lastspace >= 0) {
- k = lastspace;
- buf.setLength(lastspace - refk);
- trimRight(buf);
- lines.add(buf.toString());
- buf.setLength(0);
- refk = k;
- lastspace = -1;
- state = 2;
- }
- else {
- if (buf.length() > 1) {
- --k;
- buf.setLength(buf.length() - 1);
- }
- lines.add(buf.toString());
- buf.setLength(0);
- refk = k;
- if (c == ' ')
- state = 2;
- }
- }
- break;
- case 2:
- if (c != ' ') {
- w = 0;
- --k;
- state = 1;
- }
- break;
- }
- }
- trimRight(buf);
- lines.add(buf.toString());
- }
- return lines;
- }
-
- private void drawTopFrame(PdfAppearance app) {
- app.moveTo(borderWidth, borderWidth);
- app.lineTo(borderWidth, box.height() - borderWidth);
- app.lineTo(box.width() - borderWidth, box.height() - borderWidth);
- app.lineTo(box.width() - 2 * borderWidth, box.height() - 2 * borderWidth);
- app.lineTo(2 * borderWidth, box.height() - 2 * borderWidth);
- app.lineTo(2 * borderWidth, 2 * borderWidth);
- app.lineTo(borderWidth, borderWidth);
- app.fill();
- }
-
- private void drawBottomFrame(PdfAppearance app) {
- app.moveTo(borderWidth, borderWidth);
- app.lineTo(box.width() - borderWidth, borderWidth);
- app.lineTo(box.width() - borderWidth, box.height() - borderWidth);
- app.lineTo(box.width() - 2 * borderWidth, box.height() - 2 * borderWidth);
- app.lineTo(box.width() - 2 * borderWidth, 2 * borderWidth);
- app.lineTo(2 * borderWidth, 2 * borderWidth);
- app.lineTo(borderWidth, borderWidth);
- app.fill();
- }
- /** Gets the border width in points.
- * @return the border width in points
- */
- public float getBorderWidth() {
- return this.borderWidth;
- }
-
- /** Sets the border width in points. To eliminate the border
- * set the border color to null
.
- * @param borderWidth the border width in points
- */
- public void setBorderWidth(float borderWidth) {
- this.borderWidth = borderWidth;
- }
-
- /** Gets the border style.
- * @return the border style
- */
- public int getBorderStyle() {
- return this.borderStyle;
- }
-
- /** Sets the border style. The styles are found in PdfBorderDictionary
- * and can be STYLE_SOLID
, STYLE_DASHED
,
- * STYLE_BEVELED
, STYLE_INSET
and
- * STYLE_UNDERLINE
.
- * @param borderStyle the border style
- */
- public void setBorderStyle(int borderStyle) {
- this.borderStyle = borderStyle;
- }
-
- /** Gets the border color.
- * @return the border color
- */
- public Color getBorderColor() {
- return this.borderColor;
- }
-
- /** Sets the border color. Set to null
to remove
- * the border.
- * @param borderColor the border color
- */
- public void setBorderColor(Color borderColor) {
- this.borderColor = borderColor;
- }
-
- /** Gets the background color.
- * @return the background color
- */
- public Color getBackgroundColor() {
- return this.backgroundColor;
- }
-
- /** Sets the background color. Set to null
for
- * transparent background.
- * @param backgroundColor the background color
- */
- public void setBackgroundColor(Color backgroundColor) {
- this.backgroundColor = backgroundColor;
- }
-
- /** Gets the text color.
- * @return the text color
- */
- public Color getTextColor() {
- return this.textColor;
- }
-
- /** Sets the text color. If null
the color used
- * will be black.
- * @param textColor the text color
- */
- public void setTextColor(Color textColor) {
- this.textColor = textColor;
- }
-
- /** Gets the text font.
- * @return the text font
- */
- public BaseFont getFont() {
- return this.font;
- }
-
- /** Sets the text font. If null
then Helvetica
- * will be used.
- * @param font the text font
- */
- public void setFont(BaseFont font) {
- this.font = font;
- }
-
- /** Gets the font size.
- * @return the font size
- */
- public float getFontSize() {
- return this.fontSize;
- }
-
- /** Sets the font size. If 0 then auto-sizing will be used but
- * only for text fields.
- * @param fontSize the font size
- */
- public void setFontSize(float fontSize) {
- this.fontSize = fontSize;
- }
-
- /** Gets the text horizontal alignment.
- * @return the text horizontal alignment
- */
- public int getAlignment() {
- return this.alignment;
- }
-
- /** Sets the text horizontal alignment. It can be Element.ALIGN_LEFT
,
- * Element.ALIGN_CENTER
and Element.ALIGN_RIGHT
.
- * @param alignment the text horizontal alignment
- */
- public void setAlignment(int alignment) {
- this.alignment = alignment;
- }
-
- /** Gets the text.
- * @return the text
- */
- public String getText() {
- return this.text;
- }
-
- /** Sets the text for text fields.
- * @param text the text
- */
- public void setText(String text) {
- this.text = text;
- }
-
- /** Gets the field dimension and position.
- * @return the field dimension and position
- */
- public Rectangle getBox() {
- return this.box;
- }
-
- /** Sets the field dimension and position.
- * @param box the field dimension and position
- */
- public void setBox(Rectangle box) {
- this.box = box;
- }
-
- /** Gets the field rotation.
- * @return the field rotation
- */
- public int getRotation() {
- return this.rotation;
- }
-
- /** Sets the field rotation. This value should be the same as
- * the page rotation where the field will be shown.
- * @param rotation the field rotation
- */
- public void setRotation(int rotation) {
- if (rotation % 90 != 0)
- throw new IllegalArgumentException("Rotation must be a multiple of 90.");
- rotation %= 360;
- if (rotation < 0)
- rotation += 360;
- this.rotation = rotation;
- }
-
- /** Convenience method to set the field rotation the same as the
- * page rotation.
- * @param page the page
- */
- public void setRotationFromPage(Rectangle page) {
- setRotation(page.getRotation());
- }
-
- /** Gets the field visibility flag.
- * @return the field visibility flag
- */
- public int getVisibility() {
- return this.visibility;
- }
-
- /** Sets the field visibility flag. This flags can be one of
- * VISIBLE
, HIDDEN
, VISIBLE_BUT_DOES_NOT_PRINT
- * and HIDDEN_BUT_PRINTABLE
.
- * @param visibility field visibility flag
- */
- public void setVisibility(int visibility) {
- this.visibility = visibility;
- }
-
- /** Gets the field name.
- * @return the field name
- */
- public String getFieldName() {
- return this.fieldName;
- }
-
- /** Sets the field name.
- * @param fieldName the field name. If null
only the widget keys
- * will be included in the field allowing it to be used as a kid field.
- */
- public void setFieldName(String fieldName) {
- this.fieldName = fieldName;
- }
-
- /** Gets the option flags.
- * @return the option flags
- */
- public int getOptions() {
- return this.options;
- }
-
- /** Sets the option flags. The option flags can be a combination by oring of
- * READ_ONLY
, REQUIRED
,
- * MULTILINE
, DO_NOT_SCROLL
,
- * PASSWORD
, FILE_SELECTION
,
- * DO_NOT_SPELL_CHECK
and EDIT
.
- * @param options the option flags
- */
- public void setOptions(int options) {
- this.options = options;
- }
-
- /** Gets the maximum length of the field's text, in characters.
- * @return the maximum length of the field's text, in characters.
- */
- public int getMaxCharacterLength() {
- return this.maxCharacterLength;
- }
-
- /** Sets the maximum length of the field's text, in characters.
- * It is only meaningful for text fields.
- * @param maxCharacterLength the maximum length of the field's text, in characters
- */
- public void setMaxCharacterLength(int maxCharacterLength) {
- this.maxCharacterLength = maxCharacterLength;
- }
-
- /**
- * Getter for property writer.
- * @return Value of property writer.
- */
- public PdfWriter getWriter() {
- return writer;
- }
-
- /**
- * Setter for property writer.
- * @param writer New value of property writer.
- */
- public void setWriter(PdfWriter writer) {
- this.writer = writer;
- }
-
- /**
- * Moves the field keys from from
to to
. The moved keys
- * are removed from from
.
- * @param from the source
- * @param to the destination. It may be null
- */
- public static void moveFields(PdfDictionary from, PdfDictionary to) {
- for (Iterator i = from.getKeys().iterator(); i.hasNext();) {
- PdfName key = (PdfName)i.next();
- if (fieldKeys.containsKey(key)) {
- if (to != null)
- to.put(key, from.get(key));
- i.remove();
- }
- }
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/BaseFont.java pdftk-2.01/java/com/lowagie/text/pdf/BaseFont.java
--- pdftk-1.45/java/com/lowagie/text/pdf/BaseFont.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/BaseFont.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,1124 +0,0 @@
-/*
- * $Id: BaseFont.java,v 1.67 2005/07/26 17:32:39 psoares33 Exp $
- * $Name: $
- *
- * Copyright 2000, 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import java.io.*;
-import com.lowagie.text.DocumentException;
-import java.util.HashMap;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * Base class for the several font types supported
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-
-public abstract class BaseFont {
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String COURIER = "Courier";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String COURIER_BOLD = "Courier-Bold";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String COURIER_OBLIQUE = "Courier-Oblique";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String COURIER_BOLDOBLIQUE = "Courier-BoldOblique";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String HELVETICA = "Helvetica";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String HELVETICA_BOLD = "Helvetica-Bold";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String HELVETICA_OBLIQUE = "Helvetica-Oblique";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String HELVETICA_BOLDOBLIQUE = "Helvetica-BoldOblique";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String SYMBOL = "Symbol";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String TIMES_ROMAN = "Times-Roman";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String TIMES_BOLD = "Times-Bold";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String TIMES_ITALIC = "Times-Italic";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String TIMES_BOLDITALIC = "Times-BoldItalic";
-
- /** This is a possible value of a base 14 type 1 font */
- public static final String ZAPFDINGBATS = "ZapfDingbats";
-
- /** The maximum height above the baseline reached by glyphs in this
- * font, excluding the height of glyphs for accented characters.
- */
- public static final int ASCENT = 1;
- /** The y coordinate of the top of flat capital letters, measured from
- * the baseline.
- */
- public static final int CAPHEIGHT = 2;
- /** The maximum depth below the baseline reached by glyphs in this
- * font. The value is a negative number.
- */
- public static final int DESCENT = 3;
- /** The angle, expressed in degrees counterclockwise from the vertical,
- * of the dominant vertical strokes of the font. The value is
- * negative for fonts that slope to the right, as almost all italic fonts do.
- */
- public static final int ITALICANGLE = 4;
- /** The lower left x glyph coordinate.
- */
- public static final int BBOXLLX = 5;
- /** The lower left y glyph coordinate.
- */
- public static final int BBOXLLY = 6;
- /** The upper right x glyph coordinate.
- */
- public static final int BBOXURX = 7;
- /** The upper right y glyph coordinate.
- */
- public static final int BBOXURY = 8;
-
- /** java.awt.Font property */
- public static final int AWT_ASCENT = 9;
- /** java.awt.Font property */
- public static final int AWT_DESCENT = 10;
- /** java.awt.Font property */
- public static final int AWT_LEADING = 11;
- /** java.awt.Font property */
- public static final int AWT_MAXADVANCE = 12;
-
- /** The font is Type 1.
- */
- public static final int FONT_TYPE_T1 = 0;
- /** The font is True Type with a standard encoding.
- */
- public static final int FONT_TYPE_TT = 1;
- /** The font is CJK.
- */
- public static final int FONT_TYPE_CJK = 2;
- /** The font is True Type with a Unicode encoding.
- */
- public static final int FONT_TYPE_TTUNI = 3;
- /** A font already inside the document.
- */
- public static final int FONT_TYPE_DOCUMENT = 4;
- /** A Type3 font.
- */
- public static final int FONT_TYPE_T3 = 5;
- /** The Unicode encoding with horizontal writing.
- */
- public static final String IDENTITY_H = "Identity-H";
- /** The Unicode encoding with vertical writing.
- */
- public static final String IDENTITY_V = "Identity-V";
-
- /** A possible encoding. */
- public static final String CP1250 = "Cp1250";
-
- /** A possible encoding. */
- public static final String CP1252 = "Cp1252";
-
- /** A possible encoding. */
- public static final String CP1257 = "Cp1257";
-
- /** A possible encoding. */
- public static final String WINANSI = "Cp1252";
-
- /** A possible encoding. */
- public static final String MACROMAN = "MacRoman";
-
-
-/** if the font has to be embedded */
- public static final boolean EMBEDDED = true;
-
-/** if the font doesn't have to be embedded */
- public static final boolean NOT_EMBEDDED = false;
-/** if the font has to be cached */
- public static final boolean CACHED = true;
-/** if the font doesn't have to be cached */
- public static final boolean NOT_CACHED = false;
-
- /** The path to the font resources. */
- public static final String RESOURCE_PATH = "com/lowagie/text/pdf/fonts/";
- /** The fake CID code that represents a newline. */
- public static final char CID_NEWLINE = '\u7fff';
-
- /** The font type.
- */
- int fontType;
-/** a not defined character in a custom PDF encoding */
- public static final String notdef = ".notdef";
-
-/** table of characters widths for this encoding */
- protected int widths[] = new int[256];
-
-/** encoding names */
- protected String differences[] = new String[256];
-/** same as differences but with the unicode codes */
- protected char unicodeDifferences[] = new char[256];
-
- protected int charBBoxes[][] = new int[256][];
-/** encoding used with this font */
- protected String encoding;
-
-/** true if the font is to be embedded in the PDF */
- protected boolean embedded;
-
-/**
- * true if the font must use it's built in encoding. In that case the
- * encoding
is only used to map a char to the position inside
- * the font, not to the expected char name.
- */
- protected boolean fontSpecific = true;
-
-/** cache for the fonts already used. */
- protected static HashMap fontCache = new HashMap();
-
-/** list of the 14 built in fonts. */
- protected static final HashMap BuiltinFonts14 = new HashMap();
-
- /** Forces the output of the width array. Only matters for the 14
- * built-in fonts.
- */
- protected boolean forceWidthsOutput = false;
-
- /** Converts char
directly to byte
- * by casting.
- */
- protected boolean directTextToByte = false;
-
- /** Indicates if all the glyphs and widths for that particular
- * encoding should be included in the document.
- */
- protected boolean subset = true;
-
- protected boolean fastWinansi = false;
-
- static {
- BuiltinFonts14.put(COURIER, PdfName.COURIER);
- BuiltinFonts14.put(COURIER_BOLD, PdfName.COURIER_BOLD);
- BuiltinFonts14.put(COURIER_BOLDOBLIQUE, PdfName.COURIER_BOLDOBLIQUE);
- BuiltinFonts14.put(COURIER_OBLIQUE, PdfName.COURIER_OBLIQUE);
- BuiltinFonts14.put(HELVETICA, PdfName.HELVETICA);
- BuiltinFonts14.put(HELVETICA_BOLD, PdfName.HELVETICA_BOLD);
- BuiltinFonts14.put(HELVETICA_BOLDOBLIQUE, PdfName.HELVETICA_BOLDOBLIQUE);
- BuiltinFonts14.put(HELVETICA_OBLIQUE, PdfName.HELVETICA_OBLIQUE);
- BuiltinFonts14.put(SYMBOL, PdfName.SYMBOL);
- BuiltinFonts14.put(TIMES_ROMAN, PdfName.TIMES_ROMAN);
- BuiltinFonts14.put(TIMES_BOLD, PdfName.TIMES_BOLD);
- BuiltinFonts14.put(TIMES_BOLDITALIC, PdfName.TIMES_BOLDITALIC);
- BuiltinFonts14.put(TIMES_ITALIC, PdfName.TIMES_ITALIC);
- BuiltinFonts14.put(ZAPFDINGBATS, PdfName.ZAPFDINGBATS);
- }
-
- /** Generates the PDF stream with the Type1 and Truetype fonts returning
- * a PdfStream.
- */
- static class StreamFont extends PdfStream {
-
- /** Generates the PDF stream with the Type1 and Truetype fonts returning
- * a PdfStream.
- * @param contents the content of the stream
- * @param lengths an array of int that describes the several lengths of each part of the font
- * @throws DocumentException error in the stream compression
- */
- public StreamFont(byte contents[], int lengths[]) throws DocumentException {
- try {
- bytes = contents;
- put(PdfName.LENGTH, new PdfNumber(bytes.length));
- for (int k = 0; k < lengths.length; ++k) {
- put(new PdfName("Length" + (k + 1)), new PdfNumber(lengths[k]));
- }
- flateCompress();
- }
- catch (Exception e) {
- throw new DocumentException(e);
- }
- }
-
- /**
- * Generates the PDF stream for a font.
- * @param contents the content of a stream
- * @param subType the subtype of the font.
- * @throws DocumentException
- */
- public StreamFont(byte contents[], String subType) throws DocumentException {
- try {
- bytes = contents;
- put(PdfName.LENGTH, new PdfNumber(bytes.length));
- if (subType != null)
- put(PdfName.SUBTYPE, new PdfName(subType));
- flateCompress();
- }
- catch (Exception e) {
- throw new DocumentException(e);
- }
- }
- }
-
- /**
- *Creates new BaseFont
- */
- protected BaseFont() {
- }
-
- /** Creates a new font. This font can be one of the 14 built in types,
- * a Type1 font referred by an AFM file, a TrueType font (simple or collection) or a CJK font from the
- * Adobe Asian Font Pack. TrueType fonts and CJK fonts can have an optional style modifier
- * appended to the name. These modifiers are: Bold, Italic and BoldItalic. An
- * example would be "STSong-Light,Bold". Note that this modifiers do not work if
- * the font is embedded. Fonts in TrueType collections are addressed by index such as "msgothic.ttc,1".
- * This would get the second font (indexes start at 0), in this case "MS PGothic".
- *
- * The fonts are cached and if they already exist they are extracted from the cache,
- * not parsed again.
- *
- * This method calls:
- *
- * createFont(name, encoding, embedded, true, null, null);
- *
- * @param name the name of the font or it's location on file
- * @param encoding the encoding to be applied to this font
- * @param embedded true if the font is to be embedded in the PDF
- * @return returns a new font. This font may come from the cache
- * @throws DocumentException the font is invalid
- * @throws IOException the font file could not be read
- */
- public static BaseFont createFont(String name, String encoding, boolean embedded) throws DocumentException, IOException {
- return createFont(name, encoding, embedded, true, null, null);
- }
-
- /** Creates a new font. This font can be one of the 14 built in types,
- * a Type1 font referred by an AFM file, a TrueType font (simple or collection) or a CJK font from the
- * Adobe Asian Font Pack. TrueType fonts and CJK fonts can have an optional style modifier
- * appended to the name. These modifiers are: Bold, Italic and BoldItalic. An
- * example would be "STSong-Light,Bold". Note that this modifiers do not work if
- * the font is embedded. Fonts in TrueType collections are addressed by index such as "msgothic.ttc,1".
- * This would get the second font (indexes start at 0), in this case "MS PGothic".
- *
- * The fonts may or may not be cached depending on the flag cached
.
- * If the byte
arrays are present the font will be
- * read from them instead of the name. The name is still required to identify
- * the font type.
- * @param name the name of the font or it's location on file
- * @param encoding the encoding to be applied to this font
- * @param embedded true if the font is to be embedded in the PDF
- * @param cached true if the font comes from the cache or is added to
- * the cache if new, false if the font is always created new
- * @param ttfAfm the true type font or the afm in a byte array
- * @param pfb the pfb in a byte array
- * @return returns a new font. This font may come from the cache but only if cached
- * is true, otherwise it will always be created new
- * @throws DocumentException the font is invalid
- * @throws IOException the font file could not be read
- */
- public static BaseFont createFont(String name, String encoding, boolean embedded, boolean cached, byte ttfAfm[], byte pfb[]) throws DocumentException, IOException {
- String nameBase = getBaseName(name);
- encoding = normalizeEncoding(encoding);
- boolean isBuiltinFonts14 = BuiltinFonts14.containsKey(name);
- boolean isCJKFont = isBuiltinFonts14 ? false : CJKFont.isCJKFont(nameBase, encoding);
- if (isBuiltinFonts14 || isCJKFont)
- embedded = false;
- else if (encoding.equals(IDENTITY_H) || encoding.equals(IDENTITY_V))
- embedded = true;
- BaseFont fontFound = null;
- BaseFont fontBuilt = null;
- String key = name + "\n" + encoding + "\n" + embedded;
- if (cached) {
- synchronized (fontCache) {
- fontFound = (BaseFont)fontCache.get(key);
- }
- if (fontFound != null)
- return fontFound;
- }
- if (isBuiltinFonts14 || name.toLowerCase().endsWith(".afm") || name.toLowerCase().endsWith(".pfm")) {
- fontBuilt = new Type1Font(name, encoding, embedded, ttfAfm, pfb);
- fontBuilt.fastWinansi = encoding.equals(CP1252);
- }
- else if (nameBase.toLowerCase().endsWith(".ttf") || nameBase.toLowerCase().endsWith(".otf") || nameBase.toLowerCase().indexOf(".ttc,") > 0) {
- if (encoding.equals(IDENTITY_H) || encoding.equals(IDENTITY_V))
- fontBuilt = new TrueTypeFontUnicode(name, encoding, embedded, ttfAfm);
- else {
- fontBuilt = new TrueTypeFont(name, encoding, embedded, ttfAfm);
- fontBuilt.fastWinansi = encoding.equals(CP1252);
- }
- }
- else if (isCJKFont)
- fontBuilt = new CJKFont(name, encoding, embedded);
- else
- throw new DocumentException("Font '" + name + "' with '" + encoding + "' is not recognized.");
- if (cached) {
- synchronized (fontCache) {
- fontFound = (BaseFont)fontCache.get(key);
- if (fontFound != null)
- return fontFound;
- fontCache.put(key, fontBuilt);
- }
- }
- return fontBuilt;
- }
-
- /**
- * Creates a font based on an existing document font. The created font font may not
- * behave as expected, depending on the encoding or subset.
- * @param fontRef the reference to the document font
- * @return the font
- */
- public static BaseFont createFont(PRIndirectReference fontRef) {
- return new DocumentFont(fontRef);
- }
-
- /**
- * Gets the name without the modifiers Bold, Italic or BoldItalic.
- * @param name the full name of the font
- * @return the name without the modifiers Bold, Italic or BoldItalic
- */
- protected static String getBaseName(String name) {
- if (name.endsWith(",Bold"))
- return name.substring(0, name.length() - 5);
- else if (name.endsWith(",Italic"))
- return name.substring(0, name.length() - 7);
- else if (name.endsWith(",BoldItalic"))
- return name.substring(0, name.length() - 11);
- else
- return name;
- }
-
- /**
- * Normalize the encoding names. "winansi" is changed to "Cp1252" and
- * "macroman" is changed to "MacRoman".
- * @param enc the encoding to be normalized
- * @return the normalized encoding
- */
- protected static String normalizeEncoding(String enc) {
- if (enc.equals("winansi") || enc.equals(""))
- return CP1252;
- else if (enc.equals("macroman"))
- return MACROMAN;
- else
- return enc;
- }
-
- /**
- * Creates the widths
and the differences
arrays
- */
- protected void createEncoding() {
- if (fontSpecific) {
- for (int k = 0; k < 256; ++k) {
- widths[k] = getRawWidth(k, null);
- charBBoxes[k] = getRawCharBBox(k, null);
- }
- }
- else {
- String s;
- String name;
- char c;
- byte b[] = new byte[1];
- for (int k = 0; k < 256; ++k) {
- b[0] = (byte)k;
- s = PdfEncodings.convertToString(b, encoding);
- if (s.length() > 0) {
- c = s.charAt(0);
- }
- else {
- c = '?';
- }
- name = GlyphList.unicodeToName(c);
- if (name == null)
- name = notdef;
- differences[k] = name;
- unicodeDifferences[k] = c;
- widths[k] = getRawWidth(c, name);
- charBBoxes[k] = getRawCharBBox(c, name);
- }
- }
- }
-
- /**
- * Gets the width from the font according to the Unicode char c
- * or the name
. If the name
is null it's a symbolic font.
- * @param c the unicode char
- * @param name the glyph name
- * @return the width of the char
- */
- abstract int getRawWidth(int c, String name);
-
- /**
- * Gets the kerning between two Unicode chars.
- * @param char1 the first char
- * @param char2 the second char
- * @return the kerning to be applied in normalized 1000 units
- */
- public abstract int getKerning(char char1, char char2);
-
- /**
- * Sets the kerning between two Unicode chars.
- * @param char1 the first char
- * @param char2 the second char
- * @param kern the kerning to apply in normalized 1000 units
- * @return true
if the kerning was applied, false
otherwise
- */
- public abstract boolean setKerning(char char1, char char2, int kern);
-
- /**
- * Gets the width of a char
in normalized 1000 units.
- * @param char1 the unicode char
to get the width of
- * @return the width in normalized 1000 units
- */
- public int getWidth(char char1) {
- if (fastWinansi) {
- if (char1 < 128 || (char1 >= 160 && char1 <= 255))
- return widths[char1];
- return widths[PdfEncodings.winansi.get(char1)];
- }
- return getWidth(new String(new char[]{char1}));
- }
-
- /**
- * Gets the width of a String
in normalized 1000 units.
- * @param text the String
to get the witdth of
- * @return the width in normalized 1000 units
- */
- public int getWidth(String text) {
- int total = 0;
- if (fastWinansi) {
- int len = text.length();
- for (int k = 0; k < len; ++k) {
- char char1 = text.charAt(k);
- if (char1 < 128 || (char1 >= 160 && char1 <= 255))
- total += widths[char1];
- else
- total += widths[PdfEncodings.winansi.get(char1)];
- }
- return total;
- }
- else {
- byte mbytes[] = convertToBytes(text);
- for (int k = 0; k < mbytes.length; ++k)
- total += widths[0xff & mbytes[k]];
- }
- return total;
- }
-
-/**
- * Gets the descent of a String
in normalized 1000 units. The descent will always be
- * less than or equal to zero even if all the characters have an higher descent.
- * @param text the String
to get the descent of
- * @return the dexcent in normalized 1000 units
- */
- public int getDescent(String text) {
- int min = 0;
- char chars[] = text.toCharArray();
- for (int k = 0; k < chars.length; ++k) {
- int bbox[] = getCharBBox(chars[k]);
- if (bbox != null && bbox[1] < min)
- min = bbox[1];
- }
- return min;
- }
-
-/**
- * Gets the ascent of a String
in normalized 1000 units. The ascent will always be
- * greater than or equal to zero even if all the characters have a lower ascent.
- * @param text the String
to get the ascent of
- * @return the ascent in normalized 1000 units
- */
- public int getAscent(String text) {
- int max = 0;
- char chars[] = text.toCharArray();
- for (int k = 0; k < chars.length; ++k) {
- int bbox[] = getCharBBox(chars[k]);
- if (bbox != null && bbox[3] > max)
- max = bbox[3];
- }
- return max;
- }
-
-/**
- * Gets the descent of a String
in points. The descent will always be
- * less than or equal to zero even if all the characters have an higher descent.
- * @param text the String
to get the descent of
- * @param fontSize the size of the font
- * @return the dexcent in points
- */
- public float getDescentPoint(String text, float fontSize)
- {
- return 0.001f * getDescent(text) * fontSize;
- }
-
-/**
- * Gets the ascent of a String
in points. The ascent will always be
- * greater than or equal to zero even if all the characters have a lower ascent.
- * @param text the String
to get the ascent of
- * @param fontSize the size of the font
- * @return the ascent in points
- */
- public float getAscentPoint(String text, float fontSize)
- {
- return 0.001f * getAscent(text) * fontSize;
- }
-// ia>
-
- /**
- * Gets the width of a String
in points taking kerning
- * into account.
- * @param text the String
to get the witdth of
- * @param fontSize the font size
- * @return the width in points
- */
- public float getWidthPointKerned(String text, float fontSize) {
- float size = 0.001f * getWidth(text) * fontSize;
- if (!hasKernPairs())
- return size;
- int len = text.length() - 1;
- int kern = 0;
- char c[] = text.toCharArray();
- for (int k = 0; k < len; ++k) {
- kern += getKerning(c[k], c[k + 1]);
- }
- return size + kern * 0.001f * fontSize;
- }
-
- /**
- * Gets the width of a String
in points.
- * @param text the String
to get the witdth of
- * @param fontSize the font size
- * @return the width in points
- */
- public float getWidthPoint(String text, float fontSize) {
- return 0.001f * getWidth(text) * fontSize;
- }
-
- /**
- * Gets the width of a char
in points.
- * @param char1 the char
to get the witdth of
- * @param fontSize the font size
- * @return the width in points
- */
- public float getWidthPoint(char char1, float fontSize) {
- return getWidth(char1) * 0.001f * fontSize;
- }
-
- /**
- * Converts a String
to a
byte
array according
- * to the font's encoding.
- * @param text the String
to be converted
- * @return an array of byte
representing the conversion according to the font's encoding
- */
- byte[] convertToBytes(String text) {
- if (directTextToByte)
- return PdfEncodings.convertToBytes(text, null);
- return PdfEncodings.convertToBytes(text, encoding);
- }
-
- /** Outputs to the writer the font dictionaries and streams.
- * @param writer the writer for this document
- * @param ref the font indirect reference
- * @param params several parameters that depend on the font type
- * @throws IOException on error
- * @throws DocumentException error in generating the object
- */
- abstract void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException;
-
- /** Gets the encoding used to convert String
into byte[]
.
- * @return the encoding name
- */
- public String getEncoding() {
- return encoding;
- }
-
- /** Gets the font parameter identified by key
. Valid values
- * for key
are ASCENT
, AWT_ASCENT
, CAPHEIGHT
,
- * DESCENT
, AWT_DESCENT
,
- * ITALICANGLE
, BBOXLLX
, BBOXLLY
, BBOXURX
- * and BBOXURY
.
- * @param key the parameter to be extracted
- * @param fontSize the font size in points
- * @return the parameter in points
- */
- public abstract float getFontDescriptor(int key, float fontSize);
-
- /** Gets the font type. The font types can be: FONT_TYPE_T1,
- * FONT_TYPE_TT, FONT_TYPE_CJK and FONT_TYPE_TTUNI.
- * @return the font type
- */
- public int getFontType() {
- return fontType;
- }
-
- /** Gets the embedded flag.
- * @return true
if the font is embedded.
- */
- public boolean isEmbedded() {
- return embedded;
- }
-
- /** Gets the symbolic flag of the font.
- * @return true
if the font is symbolic
- */
- public boolean isFontSpecific() {
- return fontSpecific;
- }
-
- /** Creates a unique subset prefix to be added to the font name when the font is embedded and subset.
- * @return the subset prefix
- */
- public static String createSubsetPrefix() {
- String s = "";
- for (int k = 0; k < 6; ++k)
- s += (char)(Math.random() * 26 + 'A');
- return s + "+";
- }
-
- /** Gets the Unicode character corresponding to the byte output to the pdf stream.
- * @param index the byte index
- * @return the Unicode character
- */
- char getUnicodeDifferences(int index) {
- return unicodeDifferences[index];
- }
-
- /** Gets the postscript font name.
- * @return the postscript font name
- */
- public abstract String getPostscriptFontName();
-
- /**
- * Sets the font name that will appear in the pdf font dictionary.
- * Use with care as it can easily make a font unreadable if not embedded.
- * @param name the new font name
- */
- public abstract void setPostscriptFontName(String name);
-
- /** Gets the full name of the font. If it is a True Type font
- * each array element will have {Platform ID, Platform Encoding ID,
- * Language ID, font name}. The interpretation of this values can be
- * found in the Open Type specification, chapter 2, in the 'name' table.
- * For the other fonts the array has a single element with {"", "", "",
- * font name}.
- * @return the full name of the font
- */
- public abstract String[][] getFullFontName();
-
- /** Gets the full name of the font. If it is a True Type font
- * each array element will have {Platform ID, Platform Encoding ID,
- * Language ID, font name}. The interpretation of this values can be
- * found in the Open Type specification, chapter 2, in the 'name' table.
- * For the other fonts the array has a single element with {"", "", "",
- * font name}.
- * @param name the name of the font
- * @param encoding the encoding of the font
- * @param ttfAfm the true type font or the afm in a byte array
- * @throws DocumentException on error
- * @throws IOException on error
- * @return the full name of the font
- */
- public static String[][] getFullFontName(String name, String encoding, byte ttfAfm[]) throws DocumentException, IOException {
- String nameBase = getBaseName(name);
- BaseFont fontBuilt = null;
- if (nameBase.toLowerCase().endsWith(".ttf") || nameBase.toLowerCase().endsWith(".otf") || nameBase.toLowerCase().indexOf(".ttc,") > 0)
- fontBuilt = new TrueTypeFont(name, CP1252, false, ttfAfm, true);
- else
- fontBuilt = createFont(name, encoding, false, false, ttfAfm, null);
- return fontBuilt.getFullFontName();
- }
-
- /** Gets all the names from the font. Only the required tables are read.
- * @param name the name of the font
- * @param encoding the encoding of the font
- * @param ttfAfm the true type font or the afm in a byte array
- * @throws DocumentException on error
- * @throws IOException on error
- * @return an array of Object[] built with {getPostscriptFontName(), getFamilyFontName(), getFullFontName()}
- */
- public static Object[] getAllFontNames(String name, String encoding, byte ttfAfm[]) throws DocumentException, IOException {
- String nameBase = getBaseName(name);
- BaseFont fontBuilt = null;
- if (nameBase.toLowerCase().endsWith(".ttf") || nameBase.toLowerCase().endsWith(".otf") || nameBase.toLowerCase().indexOf(".ttc,") > 0)
- fontBuilt = new TrueTypeFont(name, CP1252, false, ttfAfm, true);
- else
- fontBuilt = createFont(name, encoding, false, false, ttfAfm, null);
- return new Object[]{fontBuilt.getPostscriptFontName(), fontBuilt.getFamilyFontName(), fontBuilt.getFullFontName()};
- }
-
- /** Gets the family name of the font. If it is a True Type font
- * each array element will have {Platform ID, Platform Encoding ID,
- * Language ID, font name}. The interpretation of this values can be
- * found in the Open Type specification, chapter 2, in the 'name' table.
- * For the other fonts the array has a single element with {"", "", "",
- * font name}.
- * @return the family name of the font
- */
- public abstract String[][] getFamilyFontName();
-
- /** Gets the code pages supported by the font. This has only meaning
- * with True Type fonts.
- * @return the code pages supported by the font
- */
- public String[] getCodePagesSupported() {
- return new String[0];
- }
-
- /** Enumerates the postscript font names present inside a
- * True Type Collection.
- * @param ttcFile the file name of the font
- * @throws DocumentException on error
- * @throws IOException on error
- * @return the postscript font names
- */
- public static String[] enumerateTTCNames(String ttcFile) throws DocumentException, IOException {
- return new EnumerateTTC(ttcFile).getNames();
- }
-
- /** Enumerates the postscript font names present inside a
- * True Type Collection.
- * @param ttcArray the font as a byte
array
- * @throws DocumentException on error
- * @throws IOException on error
- * @return the postscript font names
- */
- public static String[] enumerateTTCNames(byte ttcArray[]) throws DocumentException, IOException {
- return new EnumerateTTC(ttcArray).getNames();
- }
-
- /** Gets the font width array.
- * @return the font width array
- */
- public int[] getWidths() {
- return widths;
- }
-
- /** Gets the array with the names of the characters.
- * @return the array with the names of the characters
- */
- public String[] getDifferences() {
- return differences;
- }
-
- /** Gets the array with the unicode characters.
- * @return the array with the unicode characters
- */
- public char[] getUnicodeDifferences() {
- return unicodeDifferences;
- }
-
- /** Gets the state of the property.
- * @return value of property forceWidthsOutput
- */
- public boolean isForceWidthsOutput() {
- return forceWidthsOutput;
- }
-
- /** Set to true
to force the generation of the
- * widths array.
- * @param forceWidthsOutput true
to force the generation of the
- * widths array
- */
- public void setForceWidthsOutput(boolean forceWidthsOutput) {
- this.forceWidthsOutput = forceWidthsOutput;
- }
-
- /** Gets the direct conversion of char
to byte
.
- * @return value of property directTextToByte.
- * @see #setDirectTextToByte(boolean directTextToByte)
- */
- public boolean isDirectTextToByte() {
- return directTextToByte;
- }
-
- /** Sets the conversion of char
directly to byte
- * by casting. This is a low level feature to put the bytes directly in
- * the content stream without passing through String.getBytes().
- * @param directTextToByte New value of property directTextToByte.
- */
- public void setDirectTextToByte(boolean directTextToByte) {
- this.directTextToByte = directTextToByte;
- }
-
- /** Indicates if all the glyphs and widths for that particular
- * encoding should be included in the document.
- * @return false
to include all the glyphs and widths.
- */
- public boolean isSubset() {
- return subset;
- }
-
- /** Indicates if all the glyphs and widths for that particular
- * encoding should be included in the document. Set to false
- * to include all.
- * @param subset new value of property subset
- */
- public void setSubset(boolean subset) {
- this.subset = subset;
- }
-
- /** Gets the font resources.
- * @param key the full name of the resource
- * @return the InputStream
to get the resource or
- * null
if not found
- */
- public static InputStream getResourceStream(String key) {
- return getResourceStream(key, null);
- }
-
- /** Gets the font resources.
- * @param key the full name of the resource
- * @param loader the ClassLoader to load the resource or null to try the ones available
- * @return the InputStream
to get the resource or
- * null
if not found
- */
- public static InputStream getResourceStream(String key, ClassLoader loader) {
- if (key.startsWith("/"))
- key = key.substring(1);
- InputStream is = null;
- if (loader != null) {
- is = loader.getResourceAsStream(key);
- if (is != null)
- return is;
- }
- // Try to use Context Class Loader to load the properties file.
- try {
- java.lang.reflect.Method getCCL =
- Thread.class.getMethod("getContextClassLoader", new Class[0]);
- if (getCCL != null) {
- ClassLoader contextClassLoader =
- (ClassLoader)getCCL.invoke(Thread.currentThread(),
- new Object[0]);
- if (contextClassLoader != null)
- is = contextClassLoader.getResourceAsStream(key);
- }
- } catch (Throwable e) {}
-
- if (is == null) {
- is = BaseFont.class.getResourceAsStream("/" + key);
- }
- if (is == null) {
- is = ClassLoader.getSystemResourceAsStream(key);
- }
- return is;
- }
-
- /** Gets the Unicode equivalent to a CID.
- * The (inexistent) CID is translated as '\n'.
- * It has only meaning with CJK fonts with Identity encoding.
- * @param c the CID code
- * @return the Unicode equivalent
- */
- public char getUnicodeEquivalent(char c) {
- return c;
- }
-
- /** Gets the CID code given an Unicode.
- * It has only meaning with CJK fonts.
- * @param c the Unicode
- * @return the CID equivalent
- */
- public char getCidCode(char c) {
- return c;
- }
-
- /** Checks if the font has any kerning pairs.
- * @return true
if the font has any kerning pairs
- */
- public abstract boolean hasKernPairs();
-
- /**
- * Checks if a character exists in this font.
- * @param c the character to check
- * @return true
if the character has a glyph,
- * false
otherwise
- */
- public boolean charExists(char c) {
- byte b[] = convertToBytes(new String(new char[]{c}));
- return b.length > 0;
- }
-
- /**
- * Sets the character advance.
- * @param c the character
- * @param advance the character advance normalized to 1000 units
- * @return true
if the advance was set,
- * false
otherwise
- */
- public boolean setCharAdvance(char c, int advance) {
- byte b[] = convertToBytes(new String(new char[]{c}));
- if (b.length == 0)
- return false;
- widths[0xff & b[0]] = advance;
- return true;
- }
-
- private static void addFont(PRIndirectReference fontRef, IntHashtable hits, ArrayList fonts) {
- PdfObject obj = PdfReader.getPdfObject(fontRef);
- if (!obj.isDictionary())
- return;
- PdfDictionary font = (PdfDictionary)obj;
- PdfName subtype = (PdfName)PdfReader.getPdfObject(font.get(PdfName.SUBTYPE));
- if (!PdfName.TYPE1.equals(subtype) && !PdfName.TRUETYPE.equals(subtype))
- return;
- PdfName name = (PdfName)PdfReader.getPdfObject(font.get(PdfName.BASEFONT));
- fonts.add(new Object[]{PdfName.decodeName(name.toString()), fontRef});
- hits.put(fontRef.getNumber(), 1);
- }
-
- private static void recourseFonts(PdfDictionary page, IntHashtable hits, ArrayList fonts, int level) {
- ++level;
- if (level > 50) // in case we have an endless loop
- return;
- PdfDictionary resources = (PdfDictionary)PdfReader.getPdfObject(page.get(PdfName.RESOURCES));
- if (resources == null)
- return;
- PdfDictionary font = (PdfDictionary)PdfReader.getPdfObject(resources.get(PdfName.FONT));
- if (font != null) {
- for (Iterator it = font.getKeys().iterator(); it.hasNext();) {
- PdfObject ft = font.get((PdfName)it.next());
- if (ft == null || !ft.isIndirect())
- continue;
- int hit = ((PRIndirectReference)ft).getNumber();
- if (hits.containsKey(hit))
- continue;
- addFont((PRIndirectReference)ft, hits, fonts);
- }
- }
- PdfDictionary xobj = (PdfDictionary)PdfReader.getPdfObject(resources.get(PdfName.XOBJECT));
- if (xobj != null) {
- for (Iterator it = xobj.getKeys().iterator(); it.hasNext();) {
- recourseFonts((PdfDictionary)PdfReader.getPdfObject(xobj.get((PdfName)it.next())), hits, fonts, level);
- }
- }
- }
-
- /**
- * Gets a list of all document fonts. Each element of the ArrayList
- * contains a Object[]{String,PRIndirectReference}
with the font name
- * and the indirect reference to it.
- * @param reader the document where the fonts are to be listed from
- * @return the list of fonts and references
- */
- public static ArrayList getDocumentFonts(PdfReader reader) {
- IntHashtable hits = new IntHashtable();
- ArrayList fonts = new ArrayList();
- int npages = reader.getNumberOfPages();
- for (int k = 1; k <= npages; ++k)
- recourseFonts(reader.getPageN(k), hits, fonts, 1);
- return fonts;
- }
-
- /**
- * Gets a list of the document fonts in a particular page. Each element of the ArrayList
- * contains a Object[]{String,PRIndirectReference}
with the font name
- * and the indirect reference to it.
- * @param reader the document where the fonts are to be listed from
- * @param page the page to list the fonts from
- * @return the list of fonts and references
- */
- public static ArrayList getDocumentFonts(PdfReader reader, int page) {
- IntHashtable hits = new IntHashtable();
- ArrayList fonts = new ArrayList();
- recourseFonts(reader.getPageN(page), hits, fonts, 1);
- return fonts;
- }
-
- /**
- * Gets the smallest box enclosing the character contours. It will return
- * null
if the font has not the information or the character has no
- * contours, as in the case of the space, for example. Characters with no contours may
- * also return [0,0,0,0].
- * @param c the character to get the contour bounding box from
- * @return an array of four floats with the bounding box in the format [llx,lly,urx,ury] or
- * null
- */
- public int[] getCharBBox(char c) {
- byte b[] = convertToBytes(new String(new char[]{c}));
- if (b.length == 0)
- return null;
- else
- return charBBoxes[b[0] & 0xff];
- }
-
- protected abstract int[] getRawCharBBox(int c, String name);
-
- /**
- * iText expects Arabic Diactrics (tashkeel) to have zero advance but some fonts,
- * most notably those that come with Windows, like times.ttf, have non-zero
- * advance for those characters. This method makes those character to have zero
- * width advance and work correctly in the iText Arabic shaping and reordering
- * context.
- */
- public void correctArabicAdvance() {
- for (char c = '\u064b'; c <= '\u0658'; ++c)
- setCharAdvance(c, 0);
- setCharAdvance('\u0670', 0);
- for (char c = '\u06d6'; c <= '\u06dc'; ++c)
- setCharAdvance(c, 0);
- for (char c = '\u06df'; c <= '\u06e4'; ++c)
- setCharAdvance(c, 0);
- for (char c = '\u06e7'; c <= '\u06e8'; ++c)
- setCharAdvance(c, 0);
- for (char c = '\u06ea'; c <= '\u06ed'; ++c)
- setCharAdvance(c, 0);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/BidiLine.java pdftk-2.01/java/com/lowagie/text/pdf/BidiLine.java
--- pdftk-1.45/java/com/lowagie/text/pdf/BidiLine.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/BidiLine.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,925 +0,0 @@
-/*
- *
- * Copyright 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.util.ArrayList;
-
-import com.lowagie.text.Chunk;
-
-/** Does all the line bidirectional processing with PdfChunk assembly.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class BidiLine {
-
- protected int runDirection;
- protected int pieceSize = 2048;
- protected char text[] = new char[pieceSize];
- protected PdfChunk detailChunks[] = new PdfChunk[pieceSize];
- protected int totalTextLength = 0;
-
- protected byte orderLevels[] = new byte[pieceSize];
- protected int indexChars[] = new int[pieceSize];
-
- protected ArrayList chunks = new ArrayList();
- protected int indexChunk = 0;
- protected int indexChunkChar = 0;
- protected int currentChar = 0;
-
- protected int storedRunDirection;
- protected char storedText[] = new char[0];
- protected PdfChunk storedDetailChunks[] = new PdfChunk[0];
- protected int storedTotalTextLength = 0;
-
- protected byte storedOrderLevels[] = new byte[0];
- protected int storedIndexChars[] = new int[0];
-
- protected int storedIndexChunk = 0;
- protected int storedIndexChunkChar = 0;
- protected int storedCurrentChar = 0;
-
- protected boolean shortStore;
-// protected ArabicShaping arabic = new ArabicShaping(ArabicShaping.LETTERS_SHAPE | ArabicShaping.LENGTH_GROW_SHRINK | ArabicShaping.TEXT_DIRECTION_LOGICAL);
- protected static final IntHashtable mirrorChars = new IntHashtable();
- protected int arabicOptions;
-
- /** Creates new BidiLine */
- public BidiLine() {
- }
-
- public BidiLine(BidiLine org) {
- runDirection = org.runDirection;
- pieceSize = org.pieceSize;
- text = (char[])org.text.clone();
- detailChunks = (PdfChunk[])org.detailChunks.clone();
- totalTextLength = org.totalTextLength;
-
- orderLevels = (byte[])org.orderLevels.clone();
- indexChars = (int[])org.indexChars.clone();
-
- chunks = new ArrayList(org.chunks);
- indexChunk = org.indexChunk;
- indexChunkChar = org.indexChunkChar;
- currentChar = org.currentChar;
-
- storedRunDirection = org.storedRunDirection;
- storedText = (char[])org.storedText.clone();
- storedDetailChunks = (PdfChunk[])org.storedDetailChunks.clone();
- storedTotalTextLength = org.storedTotalTextLength;
-
- storedOrderLevels = (byte[])org.storedOrderLevels.clone();
- storedIndexChars = (int[])org.storedIndexChars.clone();
-
- storedIndexChunk = org.storedIndexChunk;
- storedIndexChunkChar = org.storedIndexChunkChar;
- storedCurrentChar = org.storedCurrentChar;
-
- shortStore = org.shortStore;
- arabicOptions = org.arabicOptions;
- }
-
- public boolean isEmpty() {
- return (currentChar >= totalTextLength && indexChunk >= chunks.size());
- }
-
- public void clearChunks() {
- chunks.clear();
- totalTextLength = 0;
- currentChar = 0;
- }
-
- public boolean getParagraph(int runDirection) {
- this.runDirection = runDirection;
- currentChar = 0;
- totalTextLength = 0;
- boolean hasText = false;
- char c;
- char uniC;
- BaseFont bf;
- for (; indexChunk < chunks.size(); ++indexChunk) {
- PdfChunk ck = (PdfChunk)chunks.get(indexChunk);
- bf = ck.font().getFont();
- String s = ck.toString();
- int len = s.length();
- for (; indexChunkChar < len; ++indexChunkChar) {
- c = s.charAt(indexChunkChar);
- uniC = bf.getUnicodeEquivalent(c);
- if (uniC == '\r' || uniC == '\n') {
- // next condition is never true for CID
- if (uniC == '\r' && indexChunkChar + 1 < len && s.charAt(indexChunkChar + 1) == '\n')
- ++indexChunkChar;
- ++indexChunkChar;
- if (indexChunkChar >= len) {
- indexChunkChar = 0;
- ++indexChunk;
- }
- hasText = true;
- if (totalTextLength == 0)
- detailChunks[0] = ck;
- break;
- }
- addPiece(c, ck);
- }
- if (hasText)
- break;
- indexChunkChar = 0;
- }
- if (totalTextLength == 0)
- return hasText;
-
- // remove trailing WS
- totalTextLength = trimRight(0, totalTextLength - 1) + 1;
- if (totalTextLength == 0)
- return true;
-
- if (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
- if (orderLevels.length < totalTextLength) {
- orderLevels = new byte[pieceSize];
- indexChars = new int[pieceSize];
- }
- ArabicLigaturizer.processNumbers(text, 0, totalTextLength, arabicOptions);
- BidiOrder order = new BidiOrder(text, 0, totalTextLength, (byte)(runDirection == PdfWriter.RUN_DIRECTION_RTL ? 1 : 0));
- byte od[] = order.getLevels();
- for (int k = 0; k < totalTextLength; ++k) {
- orderLevels[k] = od[k];
- indexChars[k] = k;
- }
- doArabicShapping();
- mirrorGlyphs();
- }
- totalTextLength = trimRightEx(0, totalTextLength - 1) + 1;
- return true;
- }
-
- public void addChunk(PdfChunk chunk) {
- chunks.add(chunk);
- }
-
- public void addChunks(ArrayList chunks) {
- this.chunks.addAll(chunks);
- }
-
- public void addPiece(char c, PdfChunk chunk) {
- if (totalTextLength >= pieceSize) {
- char tempText[] = text;
- PdfChunk tempDetailChunks[] = detailChunks;
- pieceSize *= 2;
- text = new char[pieceSize];
- detailChunks = new PdfChunk[pieceSize];
- System.arraycopy(tempText, 0, text, 0, totalTextLength);
- System.arraycopy(tempDetailChunks, 0, detailChunks, 0, totalTextLength);
- }
- text[totalTextLength] = c;
- detailChunks[totalTextLength++] = chunk;
- }
-
- public void save() {
- if (indexChunk > 0) {
- if (indexChunk >= chunks.size())
- chunks.clear();
- else {
- for (--indexChunk; indexChunk >= 0; --indexChunk)
- chunks.remove(indexChunk);
- }
- indexChunk = 0;
- }
- storedRunDirection = runDirection;
- storedTotalTextLength = totalTextLength;
- storedIndexChunk = indexChunk;
- storedIndexChunkChar = indexChunkChar;
- storedCurrentChar = currentChar;
- shortStore = (currentChar < totalTextLength);
- if (!shortStore) {
- // long save
- if (storedText.length < totalTextLength) {
- storedText = new char[totalTextLength];
- storedDetailChunks = new PdfChunk[totalTextLength];
- }
- System.arraycopy(text, 0, storedText, 0, totalTextLength);
- System.arraycopy(detailChunks, 0, storedDetailChunks, 0, totalTextLength);
- }
- if (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
- if (storedOrderLevels.length < totalTextLength) {
- storedOrderLevels = new byte[totalTextLength];
- storedIndexChars = new int[totalTextLength];
- }
- System.arraycopy(orderLevels, currentChar, storedOrderLevels, currentChar, totalTextLength - currentChar);
- System.arraycopy(indexChars, currentChar, storedIndexChars, currentChar, totalTextLength - currentChar);
- }
- }
-
- public void restore() {
- runDirection = storedRunDirection;
- totalTextLength = storedTotalTextLength;
- indexChunk = storedIndexChunk;
- indexChunkChar = storedIndexChunkChar;
- currentChar = storedCurrentChar;
- if (!shortStore) {
- // long restore
- System.arraycopy(storedText, 0, text, 0, totalTextLength);
- System.arraycopy(storedDetailChunks, 0, detailChunks, 0, totalTextLength);
- }
- if (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
- System.arraycopy(storedOrderLevels, currentChar, orderLevels, currentChar, totalTextLength - currentChar);
- System.arraycopy(storedIndexChars, currentChar, indexChars, currentChar, totalTextLength - currentChar);
- }
- }
-
- public void mirrorGlyphs() {
- for (int k = 0; k < totalTextLength; ++k) {
- if ((orderLevels[k] & 1) == 1) {
- int mirror = mirrorChars.get(text[k]);
- if (mirror != 0)
- text[k] = (char)mirror;
- }
- }
- }
-
- public void doArabicShapping() {
- int src = 0;
- int dest = 0;
- for (;;) {
- while (src < totalTextLength) {
- char c = text[src];
- if (c >= 0x0600 && c <= 0x06ff)
- break;
- if (src != dest) {
- text[dest] = text[src];
- detailChunks[dest] = detailChunks[src];
- orderLevels[dest] = orderLevels[src];
- }
- ++src;
- ++dest;
- }
- if (src >= totalTextLength) {
- totalTextLength = dest;
- return;
- }
- int startArabicIdx = src;
- ++src;
- while (src < totalTextLength) {
- char c = text[src];
- if (c < 0x0600 || c > 0x06ff)
- break;
- ++src;
- }
- int arabicWordSize = src - startArabicIdx;
- int size = ArabicLigaturizer.arabic_shape(text, startArabicIdx, arabicWordSize, text, dest, arabicWordSize, arabicOptions /*PangoArabicShapping.ar_novowel PangoArabicShapping.ar_lig | PangoArabicShapping.ar_composedtashkeel*/);
- if (startArabicIdx != dest) {
- for (int k = 0; k < size; ++k) {
- detailChunks[dest] = detailChunks[startArabicIdx];
- orderLevels[dest++] = orderLevels[startArabicIdx++];
- }
- }
- else
- dest += size;
- }
- }
-
- public PdfLine processLine(float width, int alignment, int runDirection, int arabicOptions) {
- this.arabicOptions = arabicOptions;
- save();
- boolean isRTL = (runDirection == PdfWriter.RUN_DIRECTION_RTL);
- if (currentChar >= totalTextLength) {
- boolean hasText = getParagraph(runDirection);
- if (!hasText)
- return null;
- if (totalTextLength == 0) {
- ArrayList ar = new ArrayList();
- PdfChunk ck = new PdfChunk("", detailChunks[0]);
- ar.add(ck);
- return new PdfLine(0, 0, alignment, true, ar, isRTL);
- }
- }
- float originalWidth = width;
- int lastSplit = -1;
- if (currentChar != 0)
- currentChar = trimLeftEx(currentChar, totalTextLength - 1);
- int oldCurrentChar = currentChar;
- char c = 0;
- char uniC = 0;
- PdfChunk ck = null;
- float charWidth = 0;
- PdfChunk lastValidChunk = null;
- for (; currentChar < totalTextLength; ++currentChar) {
- c = text[currentChar];
- ck = detailChunks[currentChar];
- uniC = ck.getUnicodeEquivalent(c);
- if (PdfChunk.noPrint(uniC))
- continue;
- charWidth = ck.getCharWidth(c);
- if (ck.isExtSplitCharacter(oldCurrentChar, currentChar, totalTextLength, text, detailChunks))
- lastSplit = currentChar;
- if (width - charWidth < 0)
- break;
- width -= charWidth;
- lastValidChunk = ck;
- }
- if (lastValidChunk == null) {
- // not even a single char fit; must output the first char
- ++currentChar;
- return new PdfLine(0, 0, alignment, false, createArrayOfPdfChunks(currentChar - 1, currentChar - 1), isRTL);
- }
- if (currentChar >= totalTextLength) {
- // there was more line than text
- return new PdfLine(0, width, alignment, true, createArrayOfPdfChunks(oldCurrentChar, totalTextLength - 1), isRTL);
- }
- int newCurrentChar = trimRightEx(oldCurrentChar, currentChar - 1);
- if (newCurrentChar < oldCurrentChar) {
- // only WS
- return new PdfLine(0, width, alignment, false, createArrayOfPdfChunks(oldCurrentChar, currentChar - 1), isRTL);
- }
- if (newCurrentChar == currentChar - 1) { // middle of word
- HyphenationEvent he = (HyphenationEvent)lastValidChunk.getAttribute(Chunk.HYPHENATION);
- if (he != null) {
- int word[] = getWord(oldCurrentChar, newCurrentChar);
- if (word != null) {
- float testWidth = width + getWidth(word[0], currentChar - 1);
- String pre = he.getHyphenatedWordPre(new String(text, word[0], word[1] - word[0]), lastValidChunk.font().getFont(), lastValidChunk.font().size(), testWidth);
- String post = he.getHyphenatedWordPost();
- if (pre.length() > 0) {
- PdfChunk extra = new PdfChunk(pre, lastValidChunk);
- currentChar = word[1] - post.length();
- return new PdfLine(0, testWidth - lastValidChunk.font().width(pre), alignment, false, createArrayOfPdfChunks(oldCurrentChar, word[0] - 1, extra), isRTL);
- }
- }
- }
- }
- if (lastSplit == -1 || lastSplit >= newCurrentChar) {
- // no split point or split point ahead of end
- return new PdfLine(0, width + getWidth(newCurrentChar + 1, currentChar - 1), alignment, false, createArrayOfPdfChunks(oldCurrentChar, newCurrentChar), isRTL);
- }
- // standard split
- currentChar = lastSplit + 1;
- newCurrentChar = trimRightEx(oldCurrentChar, lastSplit);
- if (newCurrentChar < oldCurrentChar) {
- // only WS again
- newCurrentChar = currentChar - 1;
- }
- return new PdfLine(0, originalWidth - getWidth(oldCurrentChar, newCurrentChar), alignment, false, createArrayOfPdfChunks(oldCurrentChar, newCurrentChar), isRTL);
- }
-
- /** Gets the width of a range of characters.
- * @param startIdx the first index to calculate
- * @param lastIdx the last inclusive index to calculate
- * @return the sum of all widths
- */
- public float getWidth(int startIdx, int lastIdx) {
- char c = 0;
- char uniC;
- PdfChunk ck = null;
- float width = 0;
- for (; startIdx <= lastIdx; ++startIdx) {
- c = text[startIdx];
- ck = detailChunks[startIdx];
- uniC = ck.getUnicodeEquivalent(c);
- if (PdfChunk.noPrint(uniC))
- continue;
- width += detailChunks[startIdx].getCharWidth(c);
- }
- return width;
- }
-
- public ArrayList createArrayOfPdfChunks(int startIdx, int endIdx) {
- return createArrayOfPdfChunks(startIdx, endIdx, null);
- }
-
- public ArrayList createArrayOfPdfChunks(int startIdx, int endIdx, PdfChunk extraPdfChunk) {
- boolean bidi = (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL);
- if (bidi)
- reorder(startIdx, endIdx);
- ArrayList ar = new ArrayList();
- PdfChunk refCk = detailChunks[startIdx];
- PdfChunk ck = null;
- StringBuffer buf = new StringBuffer();
- char c;
- int idx = 0;
- for (; startIdx <= endIdx; ++startIdx) {
- idx = bidi ? indexChars[startIdx] : startIdx;
- c = text[idx];
- ck = detailChunks[idx];
- if (PdfChunk.noPrint(ck.getUnicodeEquivalent(c)))
- continue;
- /* ssteward: dropped in 1.44
- if (ck.isImage()) {
- if (buf.length() > 0) {
- ar.add(new PdfChunk(buf.toString(), refCk));
- buf = new StringBuffer();
- }
- ar.add(ck);
- }
- else */
- if (ck == refCk) {
- buf.append(c);
- }
- else {
- if (buf.length() > 0) {
- ar.add(new PdfChunk(buf.toString(), refCk));
- buf = new StringBuffer();
- }
- /* ssteward: dropped in 1.44
- if (!ck.isImage())
- buf.append(c);
- refCk = ck;
- */
- }
- }
- if (buf.length() > 0) {
- ar.add(new PdfChunk(buf.toString(), refCk));
- }
- if (extraPdfChunk != null)
- ar.add(extraPdfChunk);
- return ar;
- }
-
- public int[] getWord(int startIdx, int idx) {
- int last = idx;
- int first = idx;
- // forward
- for (; last < totalTextLength; ++last) {
- if (!Character.isLetter(text[last]))
- break;
- }
- if (last == idx)
- return null;
- // backward
- for (; first >= startIdx; --first) {
- if (!Character.isLetter(text[first]))
- break;
- }
- ++first;
- return new int[]{first, last};
- }
-
- public int trimRight(int startIdx, int endIdx) {
- int idx = endIdx;
- char c;
- for (; idx >= startIdx; --idx) {
- c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
- if (!isWS(c))
- break;
- }
- return idx;
- }
-
- public int trimLeft(int startIdx, int endIdx) {
- int idx = startIdx;
- char c;
- for (; idx <= endIdx; ++idx) {
- c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
- if (!isWS(c))
- break;
- }
- return idx;
- }
-
- public int trimRightEx(int startIdx, int endIdx) {
- int idx = endIdx;
- char c = 0;
- for (; idx >= startIdx; --idx) {
- c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
- if (!isWS(c) && !PdfChunk.noPrint(c))
- break;
- }
- return idx;
- }
-
- public int trimLeftEx(int startIdx, int endIdx) {
- int idx = startIdx;
- char c = 0;
- for (; idx <= endIdx; ++idx) {
- c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
- if (!isWS(c) && !PdfChunk.noPrint(c))
- break;
- }
- return idx;
- }
-
- public void reorder(int start, int end) {
- byte maxLevel = orderLevels[start];
- byte minLevel = maxLevel;
- byte onlyOddLevels = maxLevel;
- byte onlyEvenLevels = maxLevel;
- for (int k = start + 1; k <= end; ++k) {
- byte b = orderLevels[k];
- if (b > maxLevel)
- maxLevel = b;
- else if (b < minLevel)
- minLevel = b;
- onlyOddLevels &= b;
- onlyEvenLevels |= b;
- }
- if ((onlyEvenLevels & 1) == 0) // nothing to do
- return;
- if ((onlyOddLevels & 1) == 1) { // single inversion
- flip(start, end + 1);
- return;
- }
- minLevel |= 1;
- for (; maxLevel >= minLevel; --maxLevel) {
- int pstart = start;
- for (;;) {
- for (;pstart <= end; ++pstart) {
- if (orderLevels[pstart] >= maxLevel)
- break;
- }
- if (pstart > end)
- break;
- int pend = pstart + 1;
- for (; pend <= end; ++pend) {
- if (orderLevels[pend] < maxLevel)
- break;
- }
- flip(pstart, pend);
- pstart = pend + 1;
- }
- }
- }
-
- public void flip(int start, int end) {
- int mid = (start + end) / 2;
- --end;
- for (; start < mid; ++start, --end) {
- int temp = indexChars[start];
- indexChars[start] = indexChars[end];
- indexChars[end] = temp;
- }
- }
-
- public static boolean isWS(char c) {
- return (c <= ' ');
- }
-
- static {
- mirrorChars.put(0x0028, 0x0029); // LEFT PARENTHESIS
- mirrorChars.put(0x0029, 0x0028); // RIGHT PARENTHESIS
- mirrorChars.put(0x003C, 0x003E); // LESS-THAN SIGN
- mirrorChars.put(0x003E, 0x003C); // GREATER-THAN SIGN
- mirrorChars.put(0x005B, 0x005D); // LEFT SQUARE BRACKET
- mirrorChars.put(0x005D, 0x005B); // RIGHT SQUARE BRACKET
- mirrorChars.put(0x007B, 0x007D); // LEFT CURLY BRACKET
- mirrorChars.put(0x007D, 0x007B); // RIGHT CURLY BRACKET
- mirrorChars.put(0x00AB, 0x00BB); // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
- mirrorChars.put(0x00BB, 0x00AB); // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
- mirrorChars.put(0x2039, 0x203A); // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
- mirrorChars.put(0x203A, 0x2039); // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
- mirrorChars.put(0x2045, 0x2046); // LEFT SQUARE BRACKET WITH QUILL
- mirrorChars.put(0x2046, 0x2045); // RIGHT SQUARE BRACKET WITH QUILL
- mirrorChars.put(0x207D, 0x207E); // SUPERSCRIPT LEFT PARENTHESIS
- mirrorChars.put(0x207E, 0x207D); // SUPERSCRIPT RIGHT PARENTHESIS
- mirrorChars.put(0x208D, 0x208E); // SUBSCRIPT LEFT PARENTHESIS
- mirrorChars.put(0x208E, 0x208D); // SUBSCRIPT RIGHT PARENTHESIS
- mirrorChars.put(0x2208, 0x220B); // ELEMENT OF
- mirrorChars.put(0x2209, 0x220C); // NOT AN ELEMENT OF
- mirrorChars.put(0x220A, 0x220D); // SMALL ELEMENT OF
- mirrorChars.put(0x220B, 0x2208); // CONTAINS AS MEMBER
- mirrorChars.put(0x220C, 0x2209); // DOES NOT CONTAIN AS MEMBER
- mirrorChars.put(0x220D, 0x220A); // SMALL CONTAINS AS MEMBER
- mirrorChars.put(0x2215, 0x29F5); // DIVISION SLASH
- mirrorChars.put(0x223C, 0x223D); // TILDE OPERATOR
- mirrorChars.put(0x223D, 0x223C); // REVERSED TILDE
- mirrorChars.put(0x2243, 0x22CD); // ASYMPTOTICALLY EQUAL TO
- mirrorChars.put(0x2252, 0x2253); // APPROXIMATELY EQUAL TO OR THE IMAGE OF
- mirrorChars.put(0x2253, 0x2252); // IMAGE OF OR APPROXIMATELY EQUAL TO
- mirrorChars.put(0x2254, 0x2255); // COLON EQUALS
- mirrorChars.put(0x2255, 0x2254); // EQUALS COLON
- mirrorChars.put(0x2264, 0x2265); // LESS-THAN OR EQUAL TO
- mirrorChars.put(0x2265, 0x2264); // GREATER-THAN OR EQUAL TO
- mirrorChars.put(0x2266, 0x2267); // LESS-THAN OVER EQUAL TO
- mirrorChars.put(0x2267, 0x2266); // GREATER-THAN OVER EQUAL TO
- mirrorChars.put(0x2268, 0x2269); // [BEST FIT] LESS-THAN BUT NOT EQUAL TO
- mirrorChars.put(0x2269, 0x2268); // [BEST FIT] GREATER-THAN BUT NOT EQUAL TO
- mirrorChars.put(0x226A, 0x226B); // MUCH LESS-THAN
- mirrorChars.put(0x226B, 0x226A); // MUCH GREATER-THAN
- mirrorChars.put(0x226E, 0x226F); // [BEST FIT] NOT LESS-THAN
- mirrorChars.put(0x226F, 0x226E); // [BEST FIT] NOT GREATER-THAN
- mirrorChars.put(0x2270, 0x2271); // [BEST FIT] NEITHER LESS-THAN NOR EQUAL TO
- mirrorChars.put(0x2271, 0x2270); // [BEST FIT] NEITHER GREATER-THAN NOR EQUAL TO
- mirrorChars.put(0x2272, 0x2273); // [BEST FIT] LESS-THAN OR EQUIVALENT TO
- mirrorChars.put(0x2273, 0x2272); // [BEST FIT] GREATER-THAN OR EQUIVALENT TO
- mirrorChars.put(0x2274, 0x2275); // [BEST FIT] NEITHER LESS-THAN NOR EQUIVALENT TO
- mirrorChars.put(0x2275, 0x2274); // [BEST FIT] NEITHER GREATER-THAN NOR EQUIVALENT TO
- mirrorChars.put(0x2276, 0x2277); // LESS-THAN OR GREATER-THAN
- mirrorChars.put(0x2277, 0x2276); // GREATER-THAN OR LESS-THAN
- mirrorChars.put(0x2278, 0x2279); // NEITHER LESS-THAN NOR GREATER-THAN
- mirrorChars.put(0x2279, 0x2278); // NEITHER GREATER-THAN NOR LESS-THAN
- mirrorChars.put(0x227A, 0x227B); // PRECEDES
- mirrorChars.put(0x227B, 0x227A); // SUCCEEDS
- mirrorChars.put(0x227C, 0x227D); // PRECEDES OR EQUAL TO
- mirrorChars.put(0x227D, 0x227C); // SUCCEEDS OR EQUAL TO
- mirrorChars.put(0x227E, 0x227F); // [BEST FIT] PRECEDES OR EQUIVALENT TO
- mirrorChars.put(0x227F, 0x227E); // [BEST FIT] SUCCEEDS OR EQUIVALENT TO
- mirrorChars.put(0x2280, 0x2281); // [BEST FIT] DOES NOT PRECEDE
- mirrorChars.put(0x2281, 0x2280); // [BEST FIT] DOES NOT SUCCEED
- mirrorChars.put(0x2282, 0x2283); // SUBSET OF
- mirrorChars.put(0x2283, 0x2282); // SUPERSET OF
- mirrorChars.put(0x2284, 0x2285); // [BEST FIT] NOT A SUBSET OF
- mirrorChars.put(0x2285, 0x2284); // [BEST FIT] NOT A SUPERSET OF
- mirrorChars.put(0x2286, 0x2287); // SUBSET OF OR EQUAL TO
- mirrorChars.put(0x2287, 0x2286); // SUPERSET OF OR EQUAL TO
- mirrorChars.put(0x2288, 0x2289); // [BEST FIT] NEITHER A SUBSET OF NOR EQUAL TO
- mirrorChars.put(0x2289, 0x2288); // [BEST FIT] NEITHER A SUPERSET OF NOR EQUAL TO
- mirrorChars.put(0x228A, 0x228B); // [BEST FIT] SUBSET OF WITH NOT EQUAL TO
- mirrorChars.put(0x228B, 0x228A); // [BEST FIT] SUPERSET OF WITH NOT EQUAL TO
- mirrorChars.put(0x228F, 0x2290); // SQUARE IMAGE OF
- mirrorChars.put(0x2290, 0x228F); // SQUARE ORIGINAL OF
- mirrorChars.put(0x2291, 0x2292); // SQUARE IMAGE OF OR EQUAL TO
- mirrorChars.put(0x2292, 0x2291); // SQUARE ORIGINAL OF OR EQUAL TO
- mirrorChars.put(0x2298, 0x29B8); // CIRCLED DIVISION SLASH
- mirrorChars.put(0x22A2, 0x22A3); // RIGHT TACK
- mirrorChars.put(0x22A3, 0x22A2); // LEFT TACK
- mirrorChars.put(0x22A6, 0x2ADE); // ASSERTION
- mirrorChars.put(0x22A8, 0x2AE4); // TRUE
- mirrorChars.put(0x22A9, 0x2AE3); // FORCES
- mirrorChars.put(0x22AB, 0x2AE5); // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
- mirrorChars.put(0x22B0, 0x22B1); // PRECEDES UNDER RELATION
- mirrorChars.put(0x22B1, 0x22B0); // SUCCEEDS UNDER RELATION
- mirrorChars.put(0x22B2, 0x22B3); // NORMAL SUBGROUP OF
- mirrorChars.put(0x22B3, 0x22B2); // CONTAINS AS NORMAL SUBGROUP
- mirrorChars.put(0x22B4, 0x22B5); // NORMAL SUBGROUP OF OR EQUAL TO
- mirrorChars.put(0x22B5, 0x22B4); // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
- mirrorChars.put(0x22B6, 0x22B7); // ORIGINAL OF
- mirrorChars.put(0x22B7, 0x22B6); // IMAGE OF
- mirrorChars.put(0x22C9, 0x22CA); // LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
- mirrorChars.put(0x22CA, 0x22C9); // RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
- mirrorChars.put(0x22CB, 0x22CC); // LEFT SEMIDIRECT PRODUCT
- mirrorChars.put(0x22CC, 0x22CB); // RIGHT SEMIDIRECT PRODUCT
- mirrorChars.put(0x22CD, 0x2243); // REVERSED TILDE EQUALS
- mirrorChars.put(0x22D0, 0x22D1); // DOUBLE SUBSET
- mirrorChars.put(0x22D1, 0x22D0); // DOUBLE SUPERSET
- mirrorChars.put(0x22D6, 0x22D7); // LESS-THAN WITH DOT
- mirrorChars.put(0x22D7, 0x22D6); // GREATER-THAN WITH DOT
- mirrorChars.put(0x22D8, 0x22D9); // VERY MUCH LESS-THAN
- mirrorChars.put(0x22D9, 0x22D8); // VERY MUCH GREATER-THAN
- mirrorChars.put(0x22DA, 0x22DB); // LESS-THAN EQUAL TO OR GREATER-THAN
- mirrorChars.put(0x22DB, 0x22DA); // GREATER-THAN EQUAL TO OR LESS-THAN
- mirrorChars.put(0x22DC, 0x22DD); // EQUAL TO OR LESS-THAN
- mirrorChars.put(0x22DD, 0x22DC); // EQUAL TO OR GREATER-THAN
- mirrorChars.put(0x22DE, 0x22DF); // EQUAL TO OR PRECEDES
- mirrorChars.put(0x22DF, 0x22DE); // EQUAL TO OR SUCCEEDS
- mirrorChars.put(0x22E0, 0x22E1); // [BEST FIT] DOES NOT PRECEDE OR EQUAL
- mirrorChars.put(0x22E1, 0x22E0); // [BEST FIT] DOES NOT SUCCEED OR EQUAL
- mirrorChars.put(0x22E2, 0x22E3); // [BEST FIT] NOT SQUARE IMAGE OF OR EQUAL TO
- mirrorChars.put(0x22E3, 0x22E2); // [BEST FIT] NOT SQUARE ORIGINAL OF OR EQUAL TO
- mirrorChars.put(0x22E4, 0x22E5); // [BEST FIT] SQUARE IMAGE OF OR NOT EQUAL TO
- mirrorChars.put(0x22E5, 0x22E4); // [BEST FIT] SQUARE ORIGINAL OF OR NOT EQUAL TO
- mirrorChars.put(0x22E6, 0x22E7); // [BEST FIT] LESS-THAN BUT NOT EQUIVALENT TO
- mirrorChars.put(0x22E7, 0x22E6); // [BEST FIT] GREATER-THAN BUT NOT EQUIVALENT TO
- mirrorChars.put(0x22E8, 0x22E9); // [BEST FIT] PRECEDES BUT NOT EQUIVALENT TO
- mirrorChars.put(0x22E9, 0x22E8); // [BEST FIT] SUCCEEDS BUT NOT EQUIVALENT TO
- mirrorChars.put(0x22EA, 0x22EB); // [BEST FIT] NOT NORMAL SUBGROUP OF
- mirrorChars.put(0x22EB, 0x22EA); // [BEST FIT] DOES NOT CONTAIN AS NORMAL SUBGROUP
- mirrorChars.put(0x22EC, 0x22ED); // [BEST FIT] NOT NORMAL SUBGROUP OF OR EQUAL TO
- mirrorChars.put(0x22ED, 0x22EC); // [BEST FIT] DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
- mirrorChars.put(0x22F0, 0x22F1); // UP RIGHT DIAGONAL ELLIPSIS
- mirrorChars.put(0x22F1, 0x22F0); // DOWN RIGHT DIAGONAL ELLIPSIS
- mirrorChars.put(0x22F2, 0x22FA); // ELEMENT OF WITH LONG HORIZONTAL STROKE
- mirrorChars.put(0x22F3, 0x22FB); // ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
- mirrorChars.put(0x22F4, 0x22FC); // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
- mirrorChars.put(0x22F6, 0x22FD); // ELEMENT OF WITH OVERBAR
- mirrorChars.put(0x22F7, 0x22FE); // SMALL ELEMENT OF WITH OVERBAR
- mirrorChars.put(0x22FA, 0x22F2); // CONTAINS WITH LONG HORIZONTAL STROKE
- mirrorChars.put(0x22FB, 0x22F3); // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
- mirrorChars.put(0x22FC, 0x22F4); // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
- mirrorChars.put(0x22FD, 0x22F6); // CONTAINS WITH OVERBAR
- mirrorChars.put(0x22FE, 0x22F7); // SMALL CONTAINS WITH OVERBAR
- mirrorChars.put(0x2308, 0x2309); // LEFT CEILING
- mirrorChars.put(0x2309, 0x2308); // RIGHT CEILING
- mirrorChars.put(0x230A, 0x230B); // LEFT FLOOR
- mirrorChars.put(0x230B, 0x230A); // RIGHT FLOOR
- mirrorChars.put(0x2329, 0x232A); // LEFT-POINTING ANGLE BRACKET
- mirrorChars.put(0x232A, 0x2329); // RIGHT-POINTING ANGLE BRACKET
- mirrorChars.put(0x2768, 0x2769); // MEDIUM LEFT PARENTHESIS ORNAMENT
- mirrorChars.put(0x2769, 0x2768); // MEDIUM RIGHT PARENTHESIS ORNAMENT
- mirrorChars.put(0x276A, 0x276B); // MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT
- mirrorChars.put(0x276B, 0x276A); // MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT
- mirrorChars.put(0x276C, 0x276D); // MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT
- mirrorChars.put(0x276D, 0x276C); // MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT
- mirrorChars.put(0x276E, 0x276F); // HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT
- mirrorChars.put(0x276F, 0x276E); // HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT
- mirrorChars.put(0x2770, 0x2771); // HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT
- mirrorChars.put(0x2771, 0x2770); // HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT
- mirrorChars.put(0x2772, 0x2773); // LIGHT LEFT TORTOISE SHELL BRACKET
- mirrorChars.put(0x2773, 0x2772); // LIGHT RIGHT TORTOISE SHELL BRACKET
- mirrorChars.put(0x2774, 0x2775); // MEDIUM LEFT CURLY BRACKET ORNAMENT
- mirrorChars.put(0x2775, 0x2774); // MEDIUM RIGHT CURLY BRACKET ORNAMENT
- mirrorChars.put(0x27D5, 0x27D6); // LEFT OUTER JOIN
- mirrorChars.put(0x27D6, 0x27D5); // RIGHT OUTER JOIN
- mirrorChars.put(0x27DD, 0x27DE); // LONG RIGHT TACK
- mirrorChars.put(0x27DE, 0x27DD); // LONG LEFT TACK
- mirrorChars.put(0x27E2, 0x27E3); // WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK
- mirrorChars.put(0x27E3, 0x27E2); // WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK
- mirrorChars.put(0x27E4, 0x27E5); // WHITE SQUARE WITH LEFTWARDS TICK
- mirrorChars.put(0x27E5, 0x27E4); // WHITE SQUARE WITH RIGHTWARDS TICK
- mirrorChars.put(0x27E6, 0x27E7); // MATHEMATICAL LEFT WHITE SQUARE BRACKET
- mirrorChars.put(0x27E7, 0x27E6); // MATHEMATICAL RIGHT WHITE SQUARE BRACKET
- mirrorChars.put(0x27E8, 0x27E9); // MATHEMATICAL LEFT ANGLE BRACKET
- mirrorChars.put(0x27E9, 0x27E8); // MATHEMATICAL RIGHT ANGLE BRACKET
- mirrorChars.put(0x27EA, 0x27EB); // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
- mirrorChars.put(0x27EB, 0x27EA); // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
- mirrorChars.put(0x2983, 0x2984); // LEFT WHITE CURLY BRACKET
- mirrorChars.put(0x2984, 0x2983); // RIGHT WHITE CURLY BRACKET
- mirrorChars.put(0x2985, 0x2986); // LEFT WHITE PARENTHESIS
- mirrorChars.put(0x2986, 0x2985); // RIGHT WHITE PARENTHESIS
- mirrorChars.put(0x2987, 0x2988); // Z NOTATION LEFT IMAGE BRACKET
- mirrorChars.put(0x2988, 0x2987); // Z NOTATION RIGHT IMAGE BRACKET
- mirrorChars.put(0x2989, 0x298A); // Z NOTATION LEFT BINDING BRACKET
- mirrorChars.put(0x298A, 0x2989); // Z NOTATION RIGHT BINDING BRACKET
- mirrorChars.put(0x298B, 0x298C); // LEFT SQUARE BRACKET WITH UNDERBAR
- mirrorChars.put(0x298C, 0x298B); // RIGHT SQUARE BRACKET WITH UNDERBAR
- mirrorChars.put(0x298D, 0x2990); // LEFT SQUARE BRACKET WITH TICK IN TOP CORNER
- mirrorChars.put(0x298E, 0x298F); // RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
- mirrorChars.put(0x298F, 0x298E); // LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
- mirrorChars.put(0x2990, 0x298D); // RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER
- mirrorChars.put(0x2991, 0x2992); // LEFT ANGLE BRACKET WITH DOT
- mirrorChars.put(0x2992, 0x2991); // RIGHT ANGLE BRACKET WITH DOT
- mirrorChars.put(0x2993, 0x2994); // LEFT ARC LESS-THAN BRACKET
- mirrorChars.put(0x2994, 0x2993); // RIGHT ARC GREATER-THAN BRACKET
- mirrorChars.put(0x2995, 0x2996); // DOUBLE LEFT ARC GREATER-THAN BRACKET
- mirrorChars.put(0x2996, 0x2995); // DOUBLE RIGHT ARC LESS-THAN BRACKET
- mirrorChars.put(0x2997, 0x2998); // LEFT BLACK TORTOISE SHELL BRACKET
- mirrorChars.put(0x2998, 0x2997); // RIGHT BLACK TORTOISE SHELL BRACKET
- mirrorChars.put(0x29B8, 0x2298); // CIRCLED REVERSE SOLIDUS
- mirrorChars.put(0x29C0, 0x29C1); // CIRCLED LESS-THAN
- mirrorChars.put(0x29C1, 0x29C0); // CIRCLED GREATER-THAN
- mirrorChars.put(0x29C4, 0x29C5); // SQUARED RISING DIAGONAL SLASH
- mirrorChars.put(0x29C5, 0x29C4); // SQUARED FALLING DIAGONAL SLASH
- mirrorChars.put(0x29CF, 0x29D0); // LEFT TRIANGLE BESIDE VERTICAL BAR
- mirrorChars.put(0x29D0, 0x29CF); // VERTICAL BAR BESIDE RIGHT TRIANGLE
- mirrorChars.put(0x29D1, 0x29D2); // BOWTIE WITH LEFT HALF BLACK
- mirrorChars.put(0x29D2, 0x29D1); // BOWTIE WITH RIGHT HALF BLACK
- mirrorChars.put(0x29D4, 0x29D5); // TIMES WITH LEFT HALF BLACK
- mirrorChars.put(0x29D5, 0x29D4); // TIMES WITH RIGHT HALF BLACK
- mirrorChars.put(0x29D8, 0x29D9); // LEFT WIGGLY FENCE
- mirrorChars.put(0x29D9, 0x29D8); // RIGHT WIGGLY FENCE
- mirrorChars.put(0x29DA, 0x29DB); // LEFT DOUBLE WIGGLY FENCE
- mirrorChars.put(0x29DB, 0x29DA); // RIGHT DOUBLE WIGGLY FENCE
- mirrorChars.put(0x29F5, 0x2215); // REVERSE SOLIDUS OPERATOR
- mirrorChars.put(0x29F8, 0x29F9); // BIG SOLIDUS
- mirrorChars.put(0x29F9, 0x29F8); // BIG REVERSE SOLIDUS
- mirrorChars.put(0x29FC, 0x29FD); // LEFT-POINTING CURVED ANGLE BRACKET
- mirrorChars.put(0x29FD, 0x29FC); // RIGHT-POINTING CURVED ANGLE BRACKET
- mirrorChars.put(0x2A2B, 0x2A2C); // MINUS SIGN WITH FALLING DOTS
- mirrorChars.put(0x2A2C, 0x2A2B); // MINUS SIGN WITH RISING DOTS
- mirrorChars.put(0x2A2D, 0x2A2C); // PLUS SIGN IN LEFT HALF CIRCLE
- mirrorChars.put(0x2A2E, 0x2A2D); // PLUS SIGN IN RIGHT HALF CIRCLE
- mirrorChars.put(0x2A34, 0x2A35); // MULTIPLICATION SIGN IN LEFT HALF CIRCLE
- mirrorChars.put(0x2A35, 0x2A34); // MULTIPLICATION SIGN IN RIGHT HALF CIRCLE
- mirrorChars.put(0x2A3C, 0x2A3D); // INTERIOR PRODUCT
- mirrorChars.put(0x2A3D, 0x2A3C); // RIGHTHAND INTERIOR PRODUCT
- mirrorChars.put(0x2A64, 0x2A65); // Z NOTATION DOMAIN ANTIRESTRICTION
- mirrorChars.put(0x2A65, 0x2A64); // Z NOTATION RANGE ANTIRESTRICTION
- mirrorChars.put(0x2A79, 0x2A7A); // LESS-THAN WITH CIRCLE INSIDE
- mirrorChars.put(0x2A7A, 0x2A79); // GREATER-THAN WITH CIRCLE INSIDE
- mirrorChars.put(0x2A7D, 0x2A7E); // LESS-THAN OR SLANTED EQUAL TO
- mirrorChars.put(0x2A7E, 0x2A7D); // GREATER-THAN OR SLANTED EQUAL TO
- mirrorChars.put(0x2A7F, 0x2A80); // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
- mirrorChars.put(0x2A80, 0x2A7F); // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
- mirrorChars.put(0x2A81, 0x2A82); // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
- mirrorChars.put(0x2A82, 0x2A81); // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
- mirrorChars.put(0x2A83, 0x2A84); // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT
- mirrorChars.put(0x2A84, 0x2A83); // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT
- mirrorChars.put(0x2A8B, 0x2A8C); // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN
- mirrorChars.put(0x2A8C, 0x2A8B); // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
- mirrorChars.put(0x2A91, 0x2A92); // LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL
- mirrorChars.put(0x2A92, 0x2A91); // GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL
- mirrorChars.put(0x2A93, 0x2A94); // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL
- mirrorChars.put(0x2A94, 0x2A93); // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL
- mirrorChars.put(0x2A95, 0x2A96); // SLANTED EQUAL TO OR LESS-THAN
- mirrorChars.put(0x2A96, 0x2A95); // SLANTED EQUAL TO OR GREATER-THAN
- mirrorChars.put(0x2A97, 0x2A98); // SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE
- mirrorChars.put(0x2A98, 0x2A97); // SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE
- mirrorChars.put(0x2A99, 0x2A9A); // DOUBLE-LINE EQUAL TO OR LESS-THAN
- mirrorChars.put(0x2A9A, 0x2A99); // DOUBLE-LINE EQUAL TO OR GREATER-THAN
- mirrorChars.put(0x2A9B, 0x2A9C); // DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN
- mirrorChars.put(0x2A9C, 0x2A9B); // DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN
- mirrorChars.put(0x2AA1, 0x2AA2); // DOUBLE NESTED LESS-THAN
- mirrorChars.put(0x2AA2, 0x2AA1); // DOUBLE NESTED GREATER-THAN
- mirrorChars.put(0x2AA6, 0x2AA7); // LESS-THAN CLOSED BY CURVE
- mirrorChars.put(0x2AA7, 0x2AA6); // GREATER-THAN CLOSED BY CURVE
- mirrorChars.put(0x2AA8, 0x2AA9); // LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
- mirrorChars.put(0x2AA9, 0x2AA8); // GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
- mirrorChars.put(0x2AAA, 0x2AAB); // SMALLER THAN
- mirrorChars.put(0x2AAB, 0x2AAA); // LARGER THAN
- mirrorChars.put(0x2AAC, 0x2AAD); // SMALLER THAN OR EQUAL TO
- mirrorChars.put(0x2AAD, 0x2AAC); // LARGER THAN OR EQUAL TO
- mirrorChars.put(0x2AAF, 0x2AB0); // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
- mirrorChars.put(0x2AB0, 0x2AAF); // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
- mirrorChars.put(0x2AB3, 0x2AB4); // PRECEDES ABOVE EQUALS SIGN
- mirrorChars.put(0x2AB4, 0x2AB3); // SUCCEEDS ABOVE EQUALS SIGN
- mirrorChars.put(0x2ABB, 0x2ABC); // DOUBLE PRECEDES
- mirrorChars.put(0x2ABC, 0x2ABB); // DOUBLE SUCCEEDS
- mirrorChars.put(0x2ABD, 0x2ABE); // SUBSET WITH DOT
- mirrorChars.put(0x2ABE, 0x2ABD); // SUPERSET WITH DOT
- mirrorChars.put(0x2ABF, 0x2AC0); // SUBSET WITH PLUS SIGN BELOW
- mirrorChars.put(0x2AC0, 0x2ABF); // SUPERSET WITH PLUS SIGN BELOW
- mirrorChars.put(0x2AC1, 0x2AC2); // SUBSET WITH MULTIPLICATION SIGN BELOW
- mirrorChars.put(0x2AC2, 0x2AC1); // SUPERSET WITH MULTIPLICATION SIGN BELOW
- mirrorChars.put(0x2AC3, 0x2AC4); // SUBSET OF OR EQUAL TO WITH DOT ABOVE
- mirrorChars.put(0x2AC4, 0x2AC3); // SUPERSET OF OR EQUAL TO WITH DOT ABOVE
- mirrorChars.put(0x2AC5, 0x2AC6); // SUBSET OF ABOVE EQUALS SIGN
- mirrorChars.put(0x2AC6, 0x2AC5); // SUPERSET OF ABOVE EQUALS SIGN
- mirrorChars.put(0x2ACD, 0x2ACE); // SQUARE LEFT OPEN BOX OPERATOR
- mirrorChars.put(0x2ACE, 0x2ACD); // SQUARE RIGHT OPEN BOX OPERATOR
- mirrorChars.put(0x2ACF, 0x2AD0); // CLOSED SUBSET
- mirrorChars.put(0x2AD0, 0x2ACF); // CLOSED SUPERSET
- mirrorChars.put(0x2AD1, 0x2AD2); // CLOSED SUBSET OR EQUAL TO
- mirrorChars.put(0x2AD2, 0x2AD1); // CLOSED SUPERSET OR EQUAL TO
- mirrorChars.put(0x2AD3, 0x2AD4); // SUBSET ABOVE SUPERSET
- mirrorChars.put(0x2AD4, 0x2AD3); // SUPERSET ABOVE SUBSET
- mirrorChars.put(0x2AD5, 0x2AD6); // SUBSET ABOVE SUBSET
- mirrorChars.put(0x2AD6, 0x2AD5); // SUPERSET ABOVE SUPERSET
- mirrorChars.put(0x2ADE, 0x22A6); // SHORT LEFT TACK
- mirrorChars.put(0x2AE3, 0x22A9); // DOUBLE VERTICAL BAR LEFT TURNSTILE
- mirrorChars.put(0x2AE4, 0x22A8); // VERTICAL BAR DOUBLE LEFT TURNSTILE
- mirrorChars.put(0x2AE5, 0x22AB); // DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE
- mirrorChars.put(0x2AEC, 0x2AED); // DOUBLE STROKE NOT SIGN
- mirrorChars.put(0x2AED, 0x2AEC); // REVERSED DOUBLE STROKE NOT SIGN
- mirrorChars.put(0x2AF7, 0x2AF8); // TRIPLE NESTED LESS-THAN
- mirrorChars.put(0x2AF8, 0x2AF7); // TRIPLE NESTED GREATER-THAN
- mirrorChars.put(0x2AF9, 0x2AFA); // DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO
- mirrorChars.put(0x2AFA, 0x2AF9); // DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO
- mirrorChars.put(0x3008, 0x3009); // LEFT ANGLE BRACKET
- mirrorChars.put(0x3009, 0x3008); // RIGHT ANGLE BRACKET
- mirrorChars.put(0x300A, 0x300B); // LEFT DOUBLE ANGLE BRACKET
- mirrorChars.put(0x300B, 0x300A); // RIGHT DOUBLE ANGLE BRACKET
- mirrorChars.put(0x300C, 0x300D); // [BEST FIT] LEFT CORNER BRACKET
- mirrorChars.put(0x300D, 0x300C); // [BEST FIT] RIGHT CORNER BRACKET
- mirrorChars.put(0x300E, 0x300F); // [BEST FIT] LEFT WHITE CORNER BRACKET
- mirrorChars.put(0x300F, 0x300E); // [BEST FIT] RIGHT WHITE CORNER BRACKET
- mirrorChars.put(0x3010, 0x3011); // LEFT BLACK LENTICULAR BRACKET
- mirrorChars.put(0x3011, 0x3010); // RIGHT BLACK LENTICULAR BRACKET
- mirrorChars.put(0x3014, 0x3015); // LEFT TORTOISE SHELL BRACKET
- mirrorChars.put(0x3015, 0x3014); // RIGHT TORTOISE SHELL BRACKET
- mirrorChars.put(0x3016, 0x3017); // LEFT WHITE LENTICULAR BRACKET
- mirrorChars.put(0x3017, 0x3016); // RIGHT WHITE LENTICULAR BRACKET
- mirrorChars.put(0x3018, 0x3019); // LEFT WHITE TORTOISE SHELL BRACKET
- mirrorChars.put(0x3019, 0x3018); // RIGHT WHITE TORTOISE SHELL BRACKET
- mirrorChars.put(0x301A, 0x301B); // LEFT WHITE SQUARE BRACKET
- mirrorChars.put(0x301B, 0x301A); // RIGHT WHITE SQUARE BRACKET
- mirrorChars.put(0xFF08, 0xFF09); // FULLWIDTH LEFT PARENTHESIS
- mirrorChars.put(0xFF09, 0xFF08); // FULLWIDTH RIGHT PARENTHESIS
- mirrorChars.put(0xFF1C, 0xFF1E); // FULLWIDTH LESS-THAN SIGN
- mirrorChars.put(0xFF1E, 0xFF1C); // FULLWIDTH GREATER-THAN SIGN
- mirrorChars.put(0xFF3B, 0xFF3D); // FULLWIDTH LEFT SQUARE BRACKET
- mirrorChars.put(0xFF3D, 0xFF3B); // FULLWIDTH RIGHT SQUARE BRACKET
- mirrorChars.put(0xFF5B, 0xFF5D); // FULLWIDTH LEFT CURLY BRACKET
- mirrorChars.put(0xFF5D, 0xFF5B); // FULLWIDTH RIGHT CURLY BRACKET
- mirrorChars.put(0xFF5F, 0xFF60); // FULLWIDTH LEFT WHITE PARENTHESIS
- mirrorChars.put(0xFF60, 0xFF5F); // FULLWIDTH RIGHT WHITE PARENTHESIS
- mirrorChars.put(0xFF62, 0xFF63); // [BEST FIT] HALFWIDTH LEFT CORNER BRACKET
- mirrorChars.put(0xFF63, 0xFF62); // [BEST FIT] HALFWIDTH RIGHT CORNER BRACKET
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/BidiOrder.java pdftk-2.01/java/com/lowagie/text/pdf/BidiOrder.java
--- pdftk-1.45/java/com/lowagie/text/pdf/BidiOrder.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/BidiOrder.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,1246 +0,0 @@
-package com.lowagie.text.pdf;
-
-/*
- *
- * Copyright 2003 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-/*
- * (C) Copyright IBM Corp. 1999, All Rights Reserved
- *
- * version 1.1
- */
-
-/**
- * Reference implementation of the Unicode 3.0 Bidi algorithm.
- *
- *
- * This implementation is not optimized for performance. It is intended
- * as a reference implementation that closely follows the specification
- * of the Bidirectional Algorithm in The Unicode Standard version 3.0.
- *
- * Input:
- * There are two levels of input to the algorithm, since clients may prefer
- * to supply some information from out-of-band sources rather than relying on
- * the default behavior.
- *
- * unicode type array
- * unicode type array, with externally supplied base line direction
- *
- * Output:
- * Output is separated into several stages as well, to better enable clients
- * to evaluate various aspects of implementation conformance.
- *
- * levels array over entire paragraph
- * reordering array over entire paragraph
- * levels array over line
- * reordering array over line
- *
- * Note that for conformance, algorithms are only required to generate correct
- * reordering and character directionality (odd or even levels) over a line.
- * Generating identical level arrays over a line is not required. Bidi
- * explicit format codes (LRE, RLE, LRO, RLO, PDF) and BN can be assigned
- * arbitrary levels and positions as long as the other text matches.
- *
- * As the algorithm is defined to operate on a single paragraph at a time,
- * this implementation is written to handle single paragraphs. Thus
- * rule P1 is presumed by this implementation-- the data provided to the
- * implementation is assumed to be a single paragraph, and either contains no
- * 'B' codes, or a single 'B' code at the end of the input. 'B' is allowed
- * as input to illustrate how the algorithm assigns it a level.
- *
- * Also note that rules L3 and L4 depend on the rendering engine that uses
- * the result of the bidi algorithm. This implementation assumes that the
- * rendering engine expects combining marks in visual order (e.g. to the
- * left of their base character in RTL runs) and that it adjust the glyphs
- * used to render mirrored characters that are in RTL runs so that they
- * render appropriately.
- *
- * @author Doug Felt
- */
-
-public final class BidiOrder {
- private byte[] initialTypes;
- private byte[] embeddings; // generated from processing format codes
- private byte paragraphEmbeddingLevel = -1; // undefined
-
- private int textLength; // for convenience
- private byte[] resultTypes; // for paragraph, not lines
- private byte[] resultLevels; // for paragraph, not lines
-
- // The bidi types
-
- /** Left-to-right*/
- public static final byte L = 0;
-
- /** Left-to-Right Embedding */
- public static final byte LRE = 1;
-
- /** Left-to-Right Override */
- public static final byte LRO = 2;
-
- /** Right-to-Left */
- public static final byte R = 3;
-
- /** Right-to-Left Arabic */
- public static final byte AL = 4;
-
- /** Right-to-Left Embedding */
- public static final byte RLE = 5;
-
- /** Right-to-Left Override */
- public static final byte RLO = 6;
-
- /** Pop Directional Format */
- public static final byte PDF = 7;
-
- /** European Number */
- public static final byte EN = 8;
-
- /** European Number Separator */
- public static final byte ES = 9;
-
- /** European Number Terminator */
- public static final byte ET = 10;
-
- /** Arabic Number */
- public static final byte AN = 11;
-
- /** Common Number Separator */
- public static final byte CS = 12;
-
- /** Non-Spacing Mark */
- public static final byte NSM = 13;
-
- /** Boundary Neutral */
- public static final byte BN = 14;
-
- /** Paragraph Separator */
- public static final byte B = 15;
-
- /** Segment Separator */
- public static final byte S = 16;
-
- /** Whitespace */
- public static final byte WS = 17;
-
- /** Other Neutrals */
- public static final byte ON = 18;
-
- /** Minimum bidi type value. */
- public static final byte TYPE_MIN = 0;
-
- /** Maximum bidi type value. */
- public static final byte TYPE_MAX = 18;
-
- //
- // Input
- //
-
- /**
- * Initialize using an array of direction types. Types range from TYPE_MIN to TYPE_MAX inclusive
- * and represent the direction codes of the characters in the text.
- *
- * @param types the types array
- */
- public BidiOrder(byte[] types) {
- validateTypes(types);
-
- this.initialTypes = (byte[])types.clone(); // client type array remains unchanged
-
- runAlgorithm();
- }
-
- /**
- * Initialize using an array of direction types and an externally supplied paragraph embedding level.
- * The embedding level may be -1, 0, or 1. -1 means to apply the default algorithm (rules P2 and P3),
- * 0 is for LTR paragraphs, and 1 is for RTL paragraphs.
- *
- * @param types the types array
- * @param paragraphEmbeddingLevel the externally supplied paragraph embedding level.
- */
- public BidiOrder(byte[] types, byte paragraphEmbeddingLevel) {
- validateTypes(types);
- validateParagraphEmbeddingLevel(paragraphEmbeddingLevel);
-
- this.initialTypes = (byte[])types.clone(); // client type array remains unchanged
- this.paragraphEmbeddingLevel = paragraphEmbeddingLevel;
-
- runAlgorithm();
- }
-
- public BidiOrder(char text[], int offset, int length, byte paragraphEmbeddingLevel) {
- initialTypes = new byte[length];
- for (int k = 0; k < length; ++k) {
- initialTypes[k] = rtypes[text[offset + k]];
- }
- validateParagraphEmbeddingLevel(paragraphEmbeddingLevel);
-
- this.paragraphEmbeddingLevel = paragraphEmbeddingLevel;
-
- runAlgorithm();
- }
-
- public final static byte getDirection(char c) {
- return rtypes[c];
- }
-
- /**
- * The algorithm.
- * Does not include line-based processing (Rules L1, L2).
- * These are applied later in the line-based phase of the algorithm.
- */
- private void runAlgorithm() {
- textLength = initialTypes.length;
-
- // Initialize output types.
- // Result types initialized to input types.
- resultTypes = (byte[])initialTypes.clone();
-
-
- // 1) determining the paragraph level
- // Rule P1 is the requirement for entering this algorithm.
- // Rules P2, P3.
- // If no externally supplied paragraph embedding level, use default.
- if (paragraphEmbeddingLevel == -1) {
- determineParagraphEmbeddingLevel();
- }
-
- // Initialize result levels to paragraph embedding level.
- resultLevels = new byte[textLength];
- setLevels(0, textLength, paragraphEmbeddingLevel);
-
- // 2) Explicit levels and directions
- // Rules X1-X8.
- determineExplicitEmbeddingLevels();
-
- // Rule X9.
- textLength = removeExplicitCodes();
-
- // Rule X10.
- // Run remainder of algorithm one level run at a time
- byte prevLevel = paragraphEmbeddingLevel;
- int start = 0;
- while (start < textLength) {
- byte level = resultLevels[start];
- byte prevType = typeForLevel(Math.max(prevLevel, level));
-
- int limit = start + 1;
- while (limit < textLength && resultLevels[limit] == level) {
- ++limit;
- }
-
- byte succLevel = limit < textLength ? resultLevels[limit] : paragraphEmbeddingLevel;
- byte succType = typeForLevel(Math.max(succLevel, level));
-
- // 3) resolving weak types
- // Rules W1-W7.
- resolveWeakTypes(start, limit, level, prevType, succType);
-
- // 4) resolving neutral types
- // Rules N1-N3.
- resolveNeutralTypes(start, limit, level, prevType, succType);
-
- // 5) resolving implicit embedding levels
- // Rules I1, I2.
- resolveImplicitLevels(start, limit, level, prevType, succType);
-
- prevLevel = level;
- start = limit;
- }
-
- // Reinsert explicit codes and assign appropriate levels to 'hide' them.
- // This is for convenience, so the resulting level array maps 1-1
- // with the initial array.
- // See the implementation suggestions section of TR#9 for guidelines on
- // how to implement the algorithm without removing and reinserting the codes.
- textLength = reinsertExplicitCodes(textLength);
- }
-
- /**
- * 1) determining the paragraph level.
- *
- * Rules P2, P3.
- *
- * At the end of this function, the member variable paragraphEmbeddingLevel is set to either 0 or 1.
- */
- private void determineParagraphEmbeddingLevel() {
- byte strongType = -1; // unknown
-
- // Rule P2.
- for (int i = 0; i < textLength; ++i) {
- byte t = resultTypes[i];
- if (t == L || t == AL || t == R) {
- strongType = t;
- break;
- }
- }
-
- // Rule P3.
- if (strongType == -1) { // none found
- // default embedding level when no strong types found is 0.
- paragraphEmbeddingLevel = 0;
- } else if (strongType == L) {
- paragraphEmbeddingLevel = 0;
- } else { // AL, R
- paragraphEmbeddingLevel = 1;
- }
- }
-
- /**
- * Process embedding format codes.
- *
- * Calls processEmbeddings to generate an embedding array from the explicit format codes. The
- * embedding overrides in the array are then applied to the result types, and the result levels are
- * initialized.
- * @see #processEmbeddings
- */
- private void determineExplicitEmbeddingLevels() {
- embeddings = processEmbeddings(resultTypes, paragraphEmbeddingLevel);
-
- for (int i = 0; i < textLength; ++i) {
- byte level = embeddings[i];
- if ((level & 0x80) != 0) {
- level &= 0x7f;
- resultTypes[i] = typeForLevel(level);
- }
- resultLevels[i] = level;
- }
- }
-
- /**
- * Rules X9.
- * Remove explicit codes so that they may be ignored during the remainder
- * of the main portion of the algorithm. The length of the resulting text
- * is returned.
- * @return the length of the data excluding explicit codes and BN.
- */
- private int removeExplicitCodes() {
- int w = 0;
- for (int i = 0; i < textLength; ++i) {
- byte t = initialTypes[i];
- if (!(t == LRE || t == RLE || t == LRO || t == RLO || t == PDF || t == BN)) {
- embeddings[w] = embeddings[i];
- resultTypes[w] = resultTypes[i];
- resultLevels[w] = resultLevels[i];
- w++;
- }
- }
- return w; // new textLength while explicit levels are removed
- }
-
- /**
- * Reinsert levels information for explicit codes.
- * This is for ease of relating the level information
- * to the original input data. Note that the levels
- * assigned to these codes are arbitrary, they're
- * chosen so as to avoid breaking level runs.
- * @param textLength the length of the data after compression
- * @return the length of the data (original length of
- * types array supplied to constructor)
- */
- private int reinsertExplicitCodes(int textLength) {
- for (int i = initialTypes.length; --i >= 0;) {
- byte t = initialTypes[i];
- if (t == LRE || t == RLE || t == LRO || t == RLO || t == PDF || t == BN) {
- embeddings[i] = 0;
- resultTypes[i] = t;
- resultLevels[i] = -1;
- } else {
- --textLength;
- embeddings[i] = embeddings[textLength];
- resultTypes[i] = resultTypes[textLength];
- resultLevels[i] = resultLevels[textLength];
- }
- }
-
- // now propagate forward the levels information (could have
- // propagated backward, the main thing is not to introduce a level
- // break where one doesn't already exist).
-
- if (resultLevels[0] == -1) {
- resultLevels[0] = paragraphEmbeddingLevel;
- }
- for (int i = 1; i < initialTypes.length; ++i) {
- if (resultLevels[i] == -1) {
- resultLevels[i] = resultLevels[i-1];
- }
- }
-
- // Embedding information is for informational purposes only
- // so need not be adjusted.
-
- return initialTypes.length;
- }
-
- /**
- * 2) determining explicit levels
- * Rules X1 - X8
- *
- * The interaction of these rules makes handling them a bit complex.
- * This examines resultTypes but does not modify it. It returns embedding and
- * override information in the result array. The low 7 bits are the level, the high
- * bit is set if the level is an override, and clear if it is an embedding.
- */
- private static byte[] processEmbeddings(byte[] resultTypes, byte paragraphEmbeddingLevel) {
- final int EXPLICIT_LEVEL_LIMIT = 62;
-
- int textLength = resultTypes.length;
- byte[] embeddings = new byte[textLength];
-
- // This stack will store the embedding levels and override status in a single byte
- // as described above.
- byte[] embeddingValueStack = new byte[EXPLICIT_LEVEL_LIMIT];
- int stackCounter = 0;
-
- // An LRE or LRO at level 60 is invalid, since the new level 62 is invalid. But
- // an RLE at level 60 is valid, since the new level 61 is valid. The current wording
- // of the rules requires that the RLE remain valid even if a previous LRE is invalid.
- // This keeps track of ignored LRE or LRO codes at level 60, so that the matching PDFs
- // will not try to pop the stack.
- int overflowAlmostCounter = 0;
-
- // This keeps track of ignored pushes at level 61 or higher, so that matching PDFs will
- // not try to pop the stack.
- int overflowCounter = 0;
-
- // Rule X1.
-
- // Keep the level separate from the value (level | override status flag) for ease of access.
- byte currentEmbeddingLevel = paragraphEmbeddingLevel;
- byte currentEmbeddingValue = paragraphEmbeddingLevel;
-
- // Loop through types, handling all remaining rules
- for (int i = 0; i < textLength; ++i) {
-
- embeddings[i] = currentEmbeddingValue;
-
- byte t = resultTypes[i];
-
- // Rules X2, X3, X4, X5
- switch (t) {
- case RLE:
- case LRE:
- case RLO:
- case LRO:
- // Only need to compute new level if current level is valid
- if (overflowCounter == 0) {
- byte newLevel;
- if (t == RLE || t == RLO) {
- newLevel = (byte)((currentEmbeddingLevel + 1) | 1); // least greater odd
- } else { // t == LRE || t == LRO
- newLevel = (byte)((currentEmbeddingLevel + 2) & ~1); // least greater even
- }
-
- // If the new level is valid, push old embedding level and override status
- // No check for valid stack counter, since the level check suffices.
- if (newLevel < EXPLICIT_LEVEL_LIMIT) {
- embeddingValueStack[stackCounter] = currentEmbeddingValue;
- stackCounter++;
-
- currentEmbeddingLevel = newLevel;
- if (t == LRO || t == RLO) { // override
- currentEmbeddingValue = (byte)(newLevel | 0x80);
- } else {
- currentEmbeddingValue = newLevel;
- }
-
- // Adjust level of format mark (for expositional purposes only, this gets
- // removed later).
- embeddings[i] = currentEmbeddingValue;
- break;
- }
-
- // Otherwise new level is invalid, but a valid level can still be achieved if this
- // level is 60 and we encounter an RLE or RLO further on. So record that we
- // 'almost' overflowed.
- if (currentEmbeddingLevel == 60) {
- overflowAlmostCounter++;
- break;
- }
- }
-
- // Otherwise old or new level is invalid.
- overflowCounter++;
- break;
-
- case PDF:
- // The only case where this did not actually overflow but may have almost overflowed
- // is when there was an RLE or RLO on level 60, which would result in level 61. So we
- // only test the almost overflow condition in that case.
- //
- // Also note that there may be a PDF without any pushes at all.
-
- if (overflowCounter > 0) {
- --overflowCounter;
- } else if (overflowAlmostCounter > 0 && currentEmbeddingLevel != 61) {
- --overflowAlmostCounter;
- } else if (stackCounter > 0) {
- --stackCounter;
- currentEmbeddingValue = embeddingValueStack[stackCounter];
- currentEmbeddingLevel = (byte)(currentEmbeddingValue & 0x7f);
- }
- break;
-
- case B:
- // Rule X8.
-
- // These values are reset for clarity, in this implementation B can only
- // occur as the last code in the array.
- stackCounter = 0;
- overflowCounter = 0;
- overflowAlmostCounter = 0;
- currentEmbeddingLevel = paragraphEmbeddingLevel;
- currentEmbeddingValue = paragraphEmbeddingLevel;
-
- embeddings[i] = paragraphEmbeddingLevel;
- break;
-
- default:
- break;
- }
- }
-
- return embeddings;
- }
-
-
- /**
- * 3) resolving weak types
- * Rules W1-W7.
- *
- * Note that some weak types (EN, AN) remain after this processing is complete.
- */
- private void resolveWeakTypes(int start, int limit, byte level, byte sor, byte eor) {
-
- // Rule W1.
- // Changes all NSMs.
- byte preceedingCharacterType = sor;
- for (int i = start; i < limit; ++i) {
- byte t = resultTypes[i];
- if (t == NSM) {
- resultTypes[i] = preceedingCharacterType;
- } else {
- preceedingCharacterType = t;
- }
- }
-
- // Rule W2.
- // EN does not change at the start of the run, because sor != AL.
- for (int i = start; i < limit; ++i) {
- if (resultTypes[i] == EN) {
- for (int j = i - 1; j >= start; --j) {
- byte t = resultTypes[j];
- if (t == L || t == R || t == AL) {
- if (t == AL) {
- resultTypes[i] = AN;
- }
- break;
- }
- }
- }
- }
-
- // Rule W3.
- for (int i = start; i < limit; ++i) {
- if (resultTypes[i] == AL) {
- resultTypes[i] = R;
- }
- }
-
- // Rule W4.
- // Since there must be values on both sides for this rule to have an
- // effect, the scan skips the first and last value.
- //
- // Although the scan proceeds left to right, and changes the type values
- // in a way that would appear to affect the computations later in the scan,
- // there is actually no problem. A change in the current value can only
- // affect the value to its immediate right, and only affect it if it is
- // ES or CS. But the current value can only change if the value to its
- // right is not ES or CS. Thus either the current value will not change,
- // or its change will have no effect on the remainder of the analysis.
-
- for (int i = start + 1; i < limit - 1; ++i) {
- if (resultTypes[i] == ES || resultTypes[i] == CS) {
- byte prevSepType = resultTypes[i-1];
- byte succSepType = resultTypes[i+1];
- if (prevSepType == EN && succSepType == EN) {
- resultTypes[i] = EN;
- } else if (resultTypes[i] == CS && prevSepType == AN && succSepType == AN) {
- resultTypes[i] = AN;
- }
- }
- }
-
- // Rule W5.
- for (int i = start; i < limit; ++i) {
- if (resultTypes[i] == ET) {
- // locate end of sequence
- int runstart = i;
- int runlimit = findRunLimit(runstart, limit, new byte[] { ET });
-
- // check values at ends of sequence
- byte t = runstart == start ? sor : resultTypes[runstart - 1];
-
- if (t != EN) {
- t = runlimit == limit ? eor : resultTypes[runlimit];
- }
-
- if (t == EN) {
- setTypes(runstart, runlimit, EN);
- }
-
- // continue at end of sequence
- i = runlimit;
- }
- }
-
- // Rule W6.
- for (int i = start; i < limit; ++i) {
- byte t = resultTypes[i];
- if (t == ES || t == ET || t == CS) {
- resultTypes[i] = ON;
- }
- }
-
- // Rule W7.
- for (int i = start; i < limit; ++i) {
- if (resultTypes[i] == EN) {
- // set default if we reach start of run
- byte prevStrongType = sor;
- for (int j = i - 1; j >= start; --j) {
- byte t = resultTypes[j];
- if (t == L || t == R) { // AL's have been removed
- prevStrongType = t;
- break;
- }
- }
- if (prevStrongType == L) {
- resultTypes[i] = L;
- }
- }
- }
- }
-
- /**
- * 6) resolving neutral types
- * Rules N1-N2.
- */
- private void resolveNeutralTypes(int start, int limit, byte level, byte sor, byte eor) {
-
- for (int i = start; i < limit; ++i) {
- byte t = resultTypes[i];
- if (t == WS || t == ON || t == B || t == S) {
- // find bounds of run of neutrals
- int runstart = i;
- int runlimit = findRunLimit(runstart, limit, new byte[] {B, S, WS, ON});
-
- // determine effective types at ends of run
- byte leadingType;
- byte trailingType;
-
- if (runstart == start) {
- leadingType = sor;
- } else {
- leadingType = resultTypes[runstart - 1];
- if (leadingType == L || leadingType == R) {
- // found the strong type
- } else if (leadingType == AN) {
- leadingType = R;
- } else if (leadingType == EN) {
- // Since EN's with previous strong L types have been changed
- // to L in W7, the leadingType must be R.
- leadingType = R;
- }
- }
-
- if (runlimit == limit) {
- trailingType = eor;
- } else {
- trailingType = resultTypes[runlimit];
- if (trailingType == L || trailingType == R) {
- // found the strong type
- } else if (trailingType == AN) {
- trailingType = R;
- } else if (trailingType == EN) {
- trailingType = R;
- }
- }
-
- byte resolvedType;
- if (leadingType == trailingType) {
- // Rule N1.
- resolvedType = leadingType;
- } else {
- // Rule N2.
- // Notice the embedding level of the run is used, not
- // the paragraph embedding level.
- resolvedType = typeForLevel(level);
- }
-
- setTypes(runstart, runlimit, resolvedType);
-
- // skip over run of (former) neutrals
- i = runlimit;
- }
- }
- }
-
- /**
- * 7) resolving implicit embedding levels
- * Rules I1, I2.
- */
- private void resolveImplicitLevels(int start, int limit, byte level, byte sor, byte eor) {
- if ((level & 1) == 0) { // even level
- for (int i = start; i < limit; ++i) {
- byte t = resultTypes[i];
- // Rule I1.
- if (t == L ) {
- // no change
- } else if (t == R) {
- resultLevels[i] += 1;
- } else { // t == AN || t == EN
- resultLevels[i] += 2;
- }
- }
- } else { // odd level
- for (int i = start; i < limit; ++i) {
- byte t = resultTypes[i];
- // Rule I2.
- if (t == R) {
- // no change
- } else { // t == L || t == AN || t == EN
- resultLevels[i] += 1;
- }
- }
- }
- }
-
- //
- // Output
- //
-
- public byte[] getLevels() {
- return getLevels(new int[]{textLength});
- }
-
- /**
- * Return levels array breaking lines at offsets in linebreaks.
- * Rule L1.
- *
- * The returned levels array contains the resolved level for each
- * bidi code passed to the constructor.
- *
- * The linebreaks array must include at least one value.
- * The values must be in strictly increasing order (no duplicates)
- * between 1 and the length of the text, inclusive. The last value
- * must be the length of the text.
- *
- * @param linebreaks the offsets at which to break the paragraph
- * @return the resolved levels of the text
- */
- public byte[] getLevels(int[] linebreaks) {
-
- // Note that since the previous processing has removed all
- // P, S, and WS values from resultTypes, the values referred to
- // in these rules are the initial types, before any processing
- // has been applied (including processing of overrides).
- //
- // This example implementation has reinserted explicit format codes
- // and BN, in order that the levels array correspond to the
- // initial text. Their final placement is not normative.
- // These codes are treated like WS in this implementation,
- // so they don't interrupt sequences of WS.
-
- validateLineBreaks(linebreaks, textLength);
-
- byte[] result = (byte[])resultLevels.clone(); // will be returned to caller
-
- // don't worry about linebreaks since if there is a break within
- // a series of WS values preceeding S, the linebreak itself
- // causes the reset.
- for (int i = 0; i < result.length; ++i) {
- byte t = initialTypes[i];
- if (t == B || t == S) {
- // Rule L1, clauses one and two.
- result[i] = paragraphEmbeddingLevel;
-
- // Rule L1, clause three.
- for (int j = i - 1; j >= 0; --j) {
- if (isWhitespace(initialTypes[j])) { // including format codes
- result[j] = paragraphEmbeddingLevel;
- } else {
- break;
- }
- }
- }
- }
-
- // Rule L1, clause four.
- int start = 0;
- for (int i = 0; i < linebreaks.length; ++i) {
- int limit = linebreaks[i];
- for (int j = limit - 1; j >= start; --j) {
- if (isWhitespace(initialTypes[j])) { // including format codes
- result[j] = paragraphEmbeddingLevel;
- } else {
- break;
- }
- }
-
- start = limit;
- }
-
- return result;
- }
-
- /**
- * Return reordering array breaking lines at offsets in linebreaks.
- *
- * The reordering array maps from a visual index to a logical index.
- * Lines are concatenated from left to right. So for example, the
- * fifth character from the left on the third line is
- *
getReordering(linebreaks)[linebreaks[1] + 4]
- * (linebreaks[1] is the position after the last character of the
- * second line, which is also the index of the first character on the
- * third line, and adding four gets the fifth character from the left).
- *
- * The linebreaks array must include at least one value.
- * The values must be in strictly increasing order (no duplicates)
- * between 1 and the length of the text, inclusive. The last value
- * must be the length of the text.
- *
- * @param linebreaks the offsets at which to break the paragraph.
- */
- public int[] getReordering(int[] linebreaks) {
- validateLineBreaks(linebreaks, textLength);
-
- byte[] levels = getLevels(linebreaks);
-
- return computeMultilineReordering(levels, linebreaks);
- }
-
- /**
- * Return multiline reordering array for a given level array.
- * Reordering does not occur across a line break.
- */
- private static int[] computeMultilineReordering(byte[] levels, int[] linebreaks) {
- int[] result = new int[levels.length];
-
- int start = 0;
- for (int i = 0; i < linebreaks.length; ++i) {
- int limit = linebreaks[i];
-
- byte[] templevels = new byte[limit - start];
- System.arraycopy(levels, start, templevels, 0, templevels.length);
-
- int[] temporder = computeReordering(templevels);
- for (int j = 0; j < temporder.length; ++j) {
- result[start + j] = temporder[j] + start;
- }
-
- start = limit;
- }
-
- return result;
- }
-
- /**
- * Return reordering array for a given level array. This reorders a single line.
- * The reordering is a visual to logical map. For example,
- * the leftmost char is string.charAt(order[0]).
- * Rule L2.
- */
- private static int[] computeReordering(byte[] levels) {
- int lineLength = levels.length;
-
- int[] result = new int[lineLength];
-
- // initialize order
- for (int i = 0; i < lineLength; ++i) {
- result[i] = i;
- }
-
- // locate highest level found on line.
- // Note the rules say text, but no reordering across line bounds is performed,
- // so this is sufficient.
- byte highestLevel = 0;
- byte lowestOddLevel = 63;
- for (int i = 0; i < lineLength; ++i) {
- byte level = levels[i];
- if (level > highestLevel) {
- highestLevel = level;
- }
- if (((level & 1) != 0) && level < lowestOddLevel) {
- lowestOddLevel = level;
- }
- }
-
- for (int level = highestLevel; level >= lowestOddLevel; --level) {
- for (int i = 0; i < lineLength; ++i) {
- if (levels[i] >= level) {
- // find range of text at or above this level
- int start = i;
- int limit = i + 1;
- while (limit < lineLength && levels[limit] >= level) {
- ++limit;
- }
-
- // reverse run
- for (int j = start, k = limit - 1; j < k; ++j, --k) {
- int temp = result[j];
- result[j] = result[k];
- result[k] = temp;
- }
-
- // skip to end of level run
- i = limit;
- }
- }
- }
-
- return result;
- }
-
- /**
- * Return the base level of the paragraph.
- */
- public byte getBaseLevel() {
- return paragraphEmbeddingLevel;
- }
-
- // --- internal utilities -------------------------------------------------
-
- /**
- * Return true if the type is considered a whitespace type for the line break rules.
- */
- private static boolean isWhitespace(byte biditype) {
- switch (biditype) {
- case LRE:
- case RLE:
- case LRO:
- case RLO:
- case PDF:
- case BN:
- case WS:
- return true;
- default:
- return false;
- }
- }
-
- /**
- * Return the strong type (L or R) corresponding to the level.
- */
- private static byte typeForLevel(int level) {
- return ((level & 0x1) == 0) ? L : R;
- }
-
- /**
- * Return the limit of the run starting at index that includes only resultTypes in validSet.
- * This checks the value at index, and will return index if that value is not in validSet.
- */
- private int findRunLimit(int index, int limit, byte[] validSet) {
- --index;
- loop:
- while (++index < limit) {
- byte t = resultTypes[index];
- for (int i = 0; i < validSet.length; ++i) {
- if (t == validSet[i]) {
- continue loop;
- }
- }
- // didn't find a match in validSet
- return index;
- }
- return limit;
- }
-
- /**
- * Return the start of the run including index that includes only resultTypes in validSet.
- * This assumes the value at index is valid, and does not check it.
- */
- private int findRunStart(int index, byte[] validSet) {
- loop:
- while (--index >= 0) {
- byte t = resultTypes[index];
- for (int i = 0; i < validSet.length; ++i) {
- if (t == validSet[i]) {
- continue loop;
- }
- }
- return index + 1;
- }
- return 0;
- }
-
- /**
- * Set resultTypes from start up to (but not including) limit to newType.
- */
- private void setTypes(int start, int limit, byte newType) {
- for (int i = start; i < limit; ++i) {
- resultTypes[i] = newType;
- }
- }
-
- /**
- * Set resultLevels from start up to (but not including) limit to newLevel.
- */
- private void setLevels(int start, int limit, byte newLevel) {
- for (int i = start; i < limit; ++i) {
- resultLevels[i] = newLevel;
- }
- }
-
- // --- input validation ---------------------------------------------------
-
- /**
- * Throw exception if type array is invalid.
- */
- private static void validateTypes(byte[] types) {
- if (types == null) {
- throw new IllegalArgumentException("types is null");
- }
- for (int i = 0; i < types.length; ++i) {
- if (types[i] < TYPE_MIN || types[i] > TYPE_MAX) {
- throw new IllegalArgumentException("illegal type value at " + i + ": " + types[i]);
- }
- }
- for (int i = 0; i < types.length - 1; ++i) {
- if (types[i] == B) {
- throw new IllegalArgumentException("B type before end of paragraph at index: " + i);
- }
- }
- }
-
- /**
- * Throw exception if paragraph embedding level is invalid. Special allowance for -1 so that
- * default processing can still be performed when using this API.
- */
- private static void validateParagraphEmbeddingLevel(byte paragraphEmbeddingLevel) {
- if (paragraphEmbeddingLevel != -1 &&
- paragraphEmbeddingLevel != 0 &&
- paragraphEmbeddingLevel != 1) {
- throw new IllegalArgumentException("illegal paragraph embedding level: " + paragraphEmbeddingLevel);
- }
- }
-
- /**
- * Throw exception if line breaks array is invalid.
- */
- private static void validateLineBreaks(int[] linebreaks, int textLength) {
- int prev = 0;
- for (int i = 0; i < linebreaks.length; ++i) {
- int next = linebreaks[i];
- if (next <= prev) {
- throw new IllegalArgumentException("bad linebreak: " + next + " at index: " + i);
- }
- prev = next;
- }
- if (prev != textLength) {
- throw new IllegalArgumentException("last linebreak must be at " + textLength);
- }
- }
-
- private static final byte rtypes[] = new byte[0x10000];
-
- private static char baseTypes[] = {
- 0, 8, (char)BN, 9, 9, (char)S, 10, 10, (char)B, 11, 11, (char)S, 12, 12, (char)WS, 13, 13, (char)B,
- 14, 27, (char)BN, 28, 30, (char)B, 31, 31, (char)S, 32, 32, (char)WS, 33, 34, (char)ON, 35, 37, (char)ET,
- 38, 42, (char)ON, 43, 43, (char)ET, 44, 44, (char)CS, 45, 45, (char)ET, 46, 46, (char)CS, 47, 47, (char)ES,
- 48, 57, (char)EN, 58, 58, (char)CS, 59, 64, (char)ON, 65, 90, (char)L, 91, 96, (char)ON, 97, 122, (char)L,
- 123, 126, (char)ON, 127, 132, (char)BN, 133, 133, (char)B, 134, 159, (char)BN, 160, 160, (char)CS,
- 161, 161, (char)ON, 162, 165, (char)ET, 166, 169, (char)ON, 170, 170, (char)L, 171, 175, (char)ON,
- 176, 177, (char)ET, 178, 179, (char)EN, 180, 180, (char)ON, 181, 181, (char)L, 182, 184, (char)ON,
- 185, 185, (char)EN, 186, 186, (char)L, 187, 191, (char)ON, 192, 214, (char)L, 215, 215, (char)ON,
- 216, 246, (char)L, 247, 247, (char)ON, 248, 696, (char)L, 697, 698, (char)ON, 699, 705, (char)L,
- 706, 719, (char)ON, 720, 721, (char)L, 722, 735, (char)ON, 736, 740, (char)L, 741, 749, (char)ON,
- 750, 750, (char)L, 751, 767, (char)ON, 768, 855, (char)NSM, 856, 860, (char)L, 861, 879, (char)NSM,
- 880, 883, (char)L, 884, 885, (char)ON, 886, 893, (char)L, 894, 894, (char)ON, 895, 899, (char)L,
- 900, 901, (char)ON, 902, 902, (char)L, 903, 903, (char)ON, 904, 1013, (char)L, 1014, 1014, (char)ON,
- 1015, 1154, (char)L, 1155, 1158, (char)NSM, 1159, 1159, (char)L, 1160, 1161, (char)NSM,
- 1162, 1417, (char)L, 1418, 1418, (char)ON, 1419, 1424, (char)L, 1425, 1441, (char)NSM,
- 1442, 1442, (char)L, 1443, 1465, (char)NSM, 1466, 1466, (char)L, 1467, 1469, (char)NSM,
- 1470, 1470, (char)R, 1471, 1471, (char)NSM, 1472, 1472, (char)R, 1473, 1474, (char)NSM,
- 1475, 1475, (char)R, 1476, 1476, (char)NSM, 1477, 1487, (char)L, 1488, 1514, (char)R,
- 1515, 1519, (char)L, 1520, 1524, (char)R, 1525, 1535, (char)L, 1536, 1539, (char)AL,
- 1540, 1547, (char)L, 1548, 1548, (char)CS, 1549, 1549, (char)AL, 1550, 1551, (char)ON,
- 1552, 1557, (char)NSM, 1558, 1562, (char)L, 1563, 1563, (char)AL, 1564, 1566, (char)L,
- 1567, 1567, (char)AL, 1568, 1568, (char)L, 1569, 1594, (char)AL, 1595, 1599, (char)L,
- 1600, 1610, (char)AL, 1611, 1624, (char)NSM, 1625, 1631, (char)L, 1632, 1641, (char)AN,
- 1642, 1642, (char)ET, 1643, 1644, (char)AN, 1645, 1647, (char)AL, 1648, 1648, (char)NSM,
- 1649, 1749, (char)AL, 1750, 1756, (char)NSM, 1757, 1757, (char)AL, 1758, 1764, (char)NSM,
- 1765, 1766, (char)AL, 1767, 1768, (char)NSM, 1769, 1769, (char)ON, 1770, 1773, (char)NSM,
- 1774, 1775, (char)AL, 1776, 1785, (char)EN, 1786, 1805, (char)AL, 1806, 1806, (char)L,
- 1807, 1807, (char)BN, 1808, 1808, (char)AL, 1809, 1809, (char)NSM, 1810, 1839, (char)AL,
- 1840, 1866, (char)NSM, 1867, 1868, (char)L, 1869, 1871, (char)AL, 1872, 1919, (char)L,
- 1920, 1957, (char)AL, 1958, 1968, (char)NSM, 1969, 1969, (char)AL, 1970, 2304, (char)L,
- 2305, 2306, (char)NSM, 2307, 2363, (char)L, 2364, 2364, (char)NSM, 2365, 2368, (char)L,
- 2369, 2376, (char)NSM, 2377, 2380, (char)L, 2381, 2381, (char)NSM, 2382, 2384, (char)L,
- 2385, 2388, (char)NSM, 2389, 2401, (char)L, 2402, 2403, (char)NSM, 2404, 2432, (char)L,
- 2433, 2433, (char)NSM, 2434, 2491, (char)L, 2492, 2492, (char)NSM, 2493, 2496, (char)L,
- 2497, 2500, (char)NSM, 2501, 2508, (char)L, 2509, 2509, (char)NSM, 2510, 2529, (char)L,
- 2530, 2531, (char)NSM, 2532, 2545, (char)L, 2546, 2547, (char)ET, 2548, 2560, (char)L,
- 2561, 2562, (char)NSM, 2563, 2619, (char)L, 2620, 2620, (char)NSM, 2621, 2624, (char)L,
- 2625, 2626, (char)NSM, 2627, 2630, (char)L, 2631, 2632, (char)NSM, 2633, 2634, (char)L,
- 2635, 2637, (char)NSM, 2638, 2671, (char)L, 2672, 2673, (char)NSM, 2674, 2688, (char)L,
- 2689, 2690, (char)NSM, 2691, 2747, (char)L, 2748, 2748, (char)NSM, 2749, 2752, (char)L,
- 2753, 2757, (char)NSM, 2758, 2758, (char)L, 2759, 2760, (char)NSM, 2761, 2764, (char)L,
- 2765, 2765, (char)NSM, 2766, 2785, (char)L, 2786, 2787, (char)NSM, 2788, 2800, (char)L,
- 2801, 2801, (char)ET, 2802, 2816, (char)L, 2817, 2817, (char)NSM, 2818, 2875, (char)L,
- 2876, 2876, (char)NSM, 2877, 2878, (char)L, 2879, 2879, (char)NSM, 2880, 2880, (char)L,
- 2881, 2883, (char)NSM, 2884, 2892, (char)L, 2893, 2893, (char)NSM, 2894, 2901, (char)L,
- 2902, 2902, (char)NSM, 2903, 2945, (char)L, 2946, 2946, (char)NSM, 2947, 3007, (char)L,
- 3008, 3008, (char)NSM, 3009, 3020, (char)L, 3021, 3021, (char)NSM, 3022, 3058, (char)L,
- 3059, 3064, (char)ON, 3065, 3065, (char)ET, 3066, 3066, (char)ON, 3067, 3133, (char)L,
- 3134, 3136, (char)NSM, 3137, 3141, (char)L, 3142, 3144, (char)NSM, 3145, 3145, (char)L,
- 3146, 3149, (char)NSM, 3150, 3156, (char)L, 3157, 3158, (char)NSM, 3159, 3259, (char)L,
- 3260, 3260, (char)NSM, 3261, 3275, (char)L, 3276, 3277, (char)NSM, 3278, 3392, (char)L,
- 3393, 3395, (char)NSM, 3396, 3404, (char)L, 3405, 3405, (char)NSM, 3406, 3529, (char)L,
- 3530, 3530, (char)NSM, 3531, 3537, (char)L, 3538, 3540, (char)NSM, 3541, 3541, (char)L,
- 3542, 3542, (char)NSM, 3543, 3632, (char)L, 3633, 3633, (char)NSM, 3634, 3635, (char)L,
- 3636, 3642, (char)NSM, 3643, 3646, (char)L, 3647, 3647, (char)ET, 3648, 3654, (char)L,
- 3655, 3662, (char)NSM, 3663, 3760, (char)L, 3761, 3761, (char)NSM, 3762, 3763, (char)L,
- 3764, 3769, (char)NSM, 3770, 3770, (char)L, 3771, 3772, (char)NSM, 3773, 3783, (char)L,
- 3784, 3789, (char)NSM, 3790, 3863, (char)L, 3864, 3865, (char)NSM, 3866, 3892, (char)L,
- 3893, 3893, (char)NSM, 3894, 3894, (char)L, 3895, 3895, (char)NSM, 3896, 3896, (char)L,
- 3897, 3897, (char)NSM, 3898, 3901, (char)ON, 3902, 3952, (char)L, 3953, 3966, (char)NSM,
- 3967, 3967, (char)L, 3968, 3972, (char)NSM, 3973, 3973, (char)L, 3974, 3975, (char)NSM,
- 3976, 3983, (char)L, 3984, 3991, (char)NSM, 3992, 3992, (char)L, 3993, 4028, (char)NSM,
- 4029, 4037, (char)L, 4038, 4038, (char)NSM, 4039, 4140, (char)L, 4141, 4144, (char)NSM,
- 4145, 4145, (char)L, 4146, 4146, (char)NSM, 4147, 4149, (char)L, 4150, 4151, (char)NSM,
- 4152, 4152, (char)L, 4153, 4153, (char)NSM, 4154, 4183, (char)L, 4184, 4185, (char)NSM,
- 4186, 5759, (char)L, 5760, 5760, (char)WS, 5761, 5786, (char)L, 5787, 5788, (char)ON,
- 5789, 5905, (char)L, 5906, 5908, (char)NSM, 5909, 5937, (char)L, 5938, 5940, (char)NSM,
- 5941, 5969, (char)L, 5970, 5971, (char)NSM, 5972, 6001, (char)L, 6002, 6003, (char)NSM,
- 6004, 6070, (char)L, 6071, 6077, (char)NSM, 6078, 6085, (char)L, 6086, 6086, (char)NSM,
- 6087, 6088, (char)L, 6089, 6099, (char)NSM, 6100, 6106, (char)L, 6107, 6107, (char)ET,
- 6108, 6108, (char)L, 6109, 6109, (char)NSM, 6110, 6127, (char)L, 6128, 6137, (char)ON,
- 6138, 6143, (char)L, 6144, 6154, (char)ON, 6155, 6157, (char)NSM, 6158, 6158, (char)WS,
- 6159, 6312, (char)L, 6313, 6313, (char)NSM, 6314, 6431, (char)L, 6432, 6434, (char)NSM,
- 6435, 6438, (char)L, 6439, 6443, (char)NSM, 6444, 6449, (char)L, 6450, 6450, (char)NSM,
- 6451, 6456, (char)L, 6457, 6459, (char)NSM, 6460, 6463, (char)L, 6464, 6464, (char)ON,
- 6465, 6467, (char)L, 6468, 6469, (char)ON, 6470, 6623, (char)L, 6624, 6655, (char)ON,
- 6656, 8124, (char)L, 8125, 8125, (char)ON, 8126, 8126, (char)L, 8127, 8129, (char)ON,
- 8130, 8140, (char)L, 8141, 8143, (char)ON, 8144, 8156, (char)L, 8157, 8159, (char)ON,
- 8160, 8172, (char)L, 8173, 8175, (char)ON, 8176, 8188, (char)L, 8189, 8190, (char)ON,
- 8191, 8191, (char)L, 8192, 8202, (char)WS, 8203, 8205, (char)BN, 8206, 8206, (char)L,
- 8207, 8207, (char)R, 8208, 8231, (char)ON, 8232, 8232, (char)WS, 8233, 8233, (char)B,
- 8234, 8234, (char)LRE, 8235, 8235, (char)RLE, 8236, 8236, (char)PDF, 8237, 8237, (char)LRO,
- 8238, 8238, (char)RLO, 8239, 8239, (char)WS, 8240, 8244, (char)ET, 8245, 8276, (char)ON,
- 8277, 8278, (char)L, 8279, 8279, (char)ON, 8280, 8286, (char)L, 8287, 8287, (char)WS,
- 8288, 8291, (char)BN, 8292, 8297, (char)L, 8298, 8303, (char)BN, 8304, 8304, (char)EN,
- 8305, 8307, (char)L, 8308, 8313, (char)EN, 8314, 8315, (char)ET, 8316, 8318, (char)ON,
- 8319, 8319, (char)L, 8320, 8329, (char)EN, 8330, 8331, (char)ET, 8332, 8334, (char)ON,
- 8335, 8351, (char)L, 8352, 8369, (char)ET, 8370, 8399, (char)L, 8400, 8426, (char)NSM,
- 8427, 8447, (char)L, 8448, 8449, (char)ON, 8450, 8450, (char)L, 8451, 8454, (char)ON,
- 8455, 8455, (char)L, 8456, 8457, (char)ON, 8458, 8467, (char)L, 8468, 8468, (char)ON,
- 8469, 8469, (char)L, 8470, 8472, (char)ON, 8473, 8477, (char)L, 8478, 8483, (char)ON,
- 8484, 8484, (char)L, 8485, 8485, (char)ON, 8486, 8486, (char)L, 8487, 8487, (char)ON,
- 8488, 8488, (char)L, 8489, 8489, (char)ON, 8490, 8493, (char)L, 8494, 8494, (char)ET,
- 8495, 8497, (char)L, 8498, 8498, (char)ON, 8499, 8505, (char)L, 8506, 8507, (char)ON,
- 8508, 8511, (char)L, 8512, 8516, (char)ON, 8517, 8521, (char)L, 8522, 8523, (char)ON,
- 8524, 8530, (char)L, 8531, 8543, (char)ON, 8544, 8591, (char)L, 8592, 8721, (char)ON,
- 8722, 8723, (char)ET, 8724, 9013, (char)ON, 9014, 9082, (char)L, 9083, 9108, (char)ON,
- 9109, 9109, (char)L, 9110, 9168, (char)ON, 9169, 9215, (char)L, 9216, 9254, (char)ON,
- 9255, 9279, (char)L, 9280, 9290, (char)ON, 9291, 9311, (char)L, 9312, 9371, (char)EN,
- 9372, 9449, (char)L, 9450, 9450, (char)EN, 9451, 9751, (char)ON, 9752, 9752, (char)L,
- 9753, 9853, (char)ON, 9854, 9855, (char)L, 9856, 9873, (char)ON, 9874, 9887, (char)L,
- 9888, 9889, (char)ON, 9890, 9984, (char)L, 9985, 9988, (char)ON, 9989, 9989, (char)L,
- 9990, 9993, (char)ON, 9994, 9995, (char)L, 9996, 10023, (char)ON, 10024, 10024, (char)L,
- 10025, 10059, (char)ON, 10060, 10060, (char)L, 10061, 10061, (char)ON, 10062, 10062, (char)L,
- 10063, 10066, (char)ON, 10067, 10069, (char)L, 10070, 10070, (char)ON, 10071, 10071, (char)L,
- 10072, 10078, (char)ON, 10079, 10080, (char)L, 10081, 10132, (char)ON, 10133, 10135, (char)L,
- 10136, 10159, (char)ON, 10160, 10160, (char)L, 10161, 10174, (char)ON, 10175, 10191, (char)L,
- 10192, 10219, (char)ON, 10220, 10223, (char)L, 10224, 11021, (char)ON, 11022, 11903, (char)L,
- 11904, 11929, (char)ON, 11930, 11930, (char)L, 11931, 12019, (char)ON, 12020, 12031, (char)L,
- 12032, 12245, (char)ON, 12246, 12271, (char)L, 12272, 12283, (char)ON, 12284, 12287, (char)L,
- 12288, 12288, (char)WS, 12289, 12292, (char)ON, 12293, 12295, (char)L, 12296, 12320, (char)ON,
- 12321, 12329, (char)L, 12330, 12335, (char)NSM, 12336, 12336, (char)ON, 12337, 12341, (char)L,
- 12342, 12343, (char)ON, 12344, 12348, (char)L, 12349, 12351, (char)ON, 12352, 12440, (char)L,
- 12441, 12442, (char)NSM, 12443, 12444, (char)ON, 12445, 12447, (char)L, 12448, 12448, (char)ON,
- 12449, 12538, (char)L, 12539, 12539, (char)ON, 12540, 12828, (char)L, 12829, 12830, (char)ON,
- 12831, 12879, (char)L, 12880, 12895, (char)ON, 12896, 12923, (char)L, 12924, 12925, (char)ON,
- 12926, 12976, (char)L, 12977, 12991, (char)ON, 12992, 13003, (char)L, 13004, 13007, (char)ON,
- 13008, 13174, (char)L, 13175, 13178, (char)ON, 13179, 13277, (char)L, 13278, 13279, (char)ON,
- 13280, 13310, (char)L, 13311, 13311, (char)ON, 13312, 19903, (char)L, 19904, 19967, (char)ON,
- 19968, 42127, (char)L, 42128, 42182, (char)ON, 42183, 64284, (char)L, 64285, 64285, (char)R,
- 64286, 64286, (char)NSM, 64287, 64296, (char)R, 64297, 64297, (char)ET, 64298, 64310, (char)R,
- 64311, 64311, (char)L, 64312, 64316, (char)R, 64317, 64317, (char)L, 64318, 64318, (char)R,
- 64319, 64319, (char)L, 64320, 64321, (char)R, 64322, 64322, (char)L, 64323, 64324, (char)R,
- 64325, 64325, (char)L, 64326, 64335, (char)R, 64336, 64433, (char)AL, 64434, 64466, (char)L,
- 64467, 64829, (char)AL, 64830, 64831, (char)ON, 64832, 64847, (char)L, 64848, 64911, (char)AL,
- 64912, 64913, (char)L, 64914, 64967, (char)AL, 64968, 65007, (char)L, 65008, 65020, (char)AL,
- 65021, 65021, (char)ON, 65022, 65023, (char)L, 65024, 65039, (char)NSM, 65040, 65055, (char)L,
- 65056, 65059, (char)NSM, 65060, 65071, (char)L, 65072, 65103, (char)ON, 65104, 65104, (char)CS,
- 65105, 65105, (char)ON, 65106, 65106, (char)CS, 65107, 65107, (char)L, 65108, 65108, (char)ON,
- 65109, 65109, (char)CS, 65110, 65118, (char)ON, 65119, 65119, (char)ET, 65120, 65121, (char)ON,
- 65122, 65123, (char)ET, 65124, 65126, (char)ON, 65127, 65127, (char)L, 65128, 65128, (char)ON,
- 65129, 65130, (char)ET, 65131, 65131, (char)ON, 65132, 65135, (char)L, 65136, 65140, (char)AL,
- 65141, 65141, (char)L, 65142, 65276, (char)AL, 65277, 65278, (char)L, 65279, 65279, (char)BN,
- 65280, 65280, (char)L, 65281, 65282, (char)ON, 65283, 65285, (char)ET, 65286, 65290, (char)ON,
- 65291, 65291, (char)ET, 65292, 65292, (char)CS, 65293, 65293, (char)ET, 65294, 65294, (char)CS,
- 65295, 65295, (char)ES, 65296, 65305, (char)EN, 65306, 65306, (char)CS, 65307, 65312, (char)ON,
- 65313, 65338, (char)L, 65339, 65344, (char)ON, 65345, 65370, (char)L, 65371, 65381, (char)ON,
- 65382, 65503, (char)L, 65504, 65505, (char)ET, 65506, 65508, (char)ON, 65509, 65510, (char)ET,
- 65511, 65511, (char)L, 65512, 65518, (char)ON, 65519, 65528, (char)L, 65529, 65531, (char)BN,
- 65532, 65533, (char)ON, 65534, 65535, (char)L};
-
- static {
- for (int k = 0; k < baseTypes.length; ++k) {
- int start = baseTypes[k];
- int end = baseTypes[++k];
- byte b = (byte)baseTypes[++k];
- while (start <= end)
- rtypes[start++] = b;
- }
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/ByteBuffer.java pdftk-2.01/java/com/lowagie/text/pdf/ByteBuffer.java
--- pdftk-1.45/java/com/lowagie/text/pdf/ByteBuffer.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/ByteBuffer.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,603 +0,0 @@
-/*
- * $Id: ByteBuffer.java,v 1.34 2002/06/18 13:59:39 blowagie Exp $
- * $Name: $
- *
- * Copyright 2000, 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import java.io.UnsupportedEncodingException;
-import java.io.OutputStream;
-import java.io.IOException;
-import com.lowagie.text.DocWriter;
-
-/**
- * Acts like a StringBuffer
but works with byte
arrays.
- * Floating point is converted to a format suitable to the PDF.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-
-public class ByteBuffer extends OutputStream {
- /** The count of bytes in the buffer. */
- protected int count;
-
- /** The buffer where the bytes are stored. */
- protected byte buf[];
-
- private static int byteCacheSize = 0;
-
- private static byte[][] byteCache = new byte[byteCacheSize][];
- public static byte ZERO = (byte)'0';
- private static final char[] chars = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
- private static final byte[] bytes = new byte[] {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102};
-
- /** Creates new ByteBuffer with capacity 128 */
- public ByteBuffer() {
- this(128);
- }
-
- /**
- * Creates a byte buffer with a certain capacity.
- * @param size the initial capacity
- */
- public ByteBuffer(int size) {
- if (size < 1)
- size = 128;
- buf = new byte[size];
- }
-
- /**
- * Sets the cache size.
- *
- * This can only be used to increment the size.
- * If the size that is passed through is smaller than the current size, nothing happens.
- *
- * @param size the size of the cache
- */
-
- public static void setCacheSize(int size) {
- if (size > 3276700) size = 3276700;
- if (size <= byteCacheSize) return;
- byte[][] tmpCache = new byte[size][];
- for (int i = 0; i < byteCacheSize; i++) {
- tmpCache[i] = byteCache[i];
- }
- byteCache = tmpCache;
- byteCacheSize = size;
- }
-
- /**
- * You can fill the cache in advance if you want to.
- *
- * @param decimals
- */
-
- public static void fillCache(int decimals) {
- int step = 1;
- switch(decimals) {
- case 0:
- step = 100;
- break;
- case 1:
- step = 10;
- break;
- }
- for (int i = 1; i < byteCacheSize; i += step) {
- if (byteCache[i] != null) continue;
- byteCache[i] = convertToBytes(i);
- }
- }
-
- /**
- * Converts an double (multiplied by 100 and cast to an int) into an array of bytes.
- *
- * @param i the int
- * @return a bytearray
- */
-
- private static byte[] convertToBytes(int i) {
- int size = (int)Math.floor(Math.log(i) / Math.log(10));
- if (i % 100 != 0) {
- size += 2;
- }
- if (i % 10 != 0) {
- size++;
- }
- if (i < 100) {
- size++;
- if (i < 10) {
- size++;
- }
- }
- size--;
- byte[] cache = new byte[size];
- size --;
- if (i < 100) {
- cache[0] = (byte)'0';
- }
- if (i % 10 != 0) {
- cache[size--] = bytes[i % 10];
- }
- if (i % 100 != 0) {
- cache[size--] = bytes[(i / 10) % 10];
- cache[size--] = (byte)'.';
- }
- size = (int)Math.floor(Math.log(i) / Math.log(10)) - 1;
- int add = 0;
- while (add < size) {
- cache[add] = bytes[(i / (int)Math.pow(10, size - add + 1)) % 10];
- add++;
- }
- return cache;
- }
-
- /**
- * Appends an int
. The size of the array will grow by one.
- * @param b the int to be appended
- * @return a reference to this ByteBuffer
object
- */
- public ByteBuffer append_i(int b) {
- int newcount = count + 1;
- if (newcount > buf.length) {
- byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)];
- System.arraycopy(buf, 0, newbuf, 0, count);
- buf = newbuf;
- }
- buf[count] = (byte)b;
- count = newcount;
- return this;
- }
-
- /**
- * Appends the subarray of the byte
array. The buffer will grow by
- * len
bytes.
- * @param b the array to be appended
- * @param off the offset to the start of the array
- * @param len the length of bytes to append
- * @return a reference to this ByteBuffer
object
- */
- public ByteBuffer append(byte b[], int off, int len) {
- if ((off < 0) || (off > b.length) || (len < 0) ||
- ((off + len) > b.length) || ((off + len) < 0) || len == 0)
- return this;
- int newcount = count + len;
- if (newcount > buf.length) {
- byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)];
- System.arraycopy(buf, 0, newbuf, 0, count);
- buf = newbuf;
- }
- System.arraycopy(b, off, buf, count, len);
- count = newcount;
- return this;
- }
-
- /**
- * Appends an array of bytes.
- * @param b the array to be appended
- * @return a reference to this ByteBuffer
object
- */
- public ByteBuffer append(byte b[]) {
- return append(b, 0, b.length);
- }
-
- /**
- * Appends a String
to the buffer. The String
is
- * converted according to the encoding ISO-8859-1.
- * @param str the String
to be appended
- * @return a reference to this ByteBuffer
object
- */
- public ByteBuffer append(String str) {
- if (str != null)
- return append(DocWriter.getISOBytes(str));
- return this;
- }
-
- /**
- * Appends a char
to the buffer. The char
is
- * converted according to the encoding ISO-8859-1.
- * @param c the char
to be appended
- * @return a reference to this ByteBuffer
object
- */
- public ByteBuffer append(char c) {
- return append_i(c);
- }
-
- /**
- * Appends another ByteBuffer
to this buffer.
- * @param buf the ByteBuffer
to be appended
- * @return a reference to this ByteBuffer
object
- */
- public ByteBuffer append(ByteBuffer buf) {
- return append(buf.buf, 0, buf.count);
- }
-
- /**
- * Appends the string representation of an int
.
- * @param i the int
to be appended
- * @return a reference to this ByteBuffer
object
- */
- public ByteBuffer append(int i) {
- return append((double)i);
- }
-
- public ByteBuffer append(byte b) {
- return append_i(b);
- }
-
- public ByteBuffer appendHex(byte b) {
- append(bytes[(b >> 4) & 0x0f]);
- return append(bytes[b & 0x0f]);
- }
-
- /**
- * Appends a string representation of a float
according
- * to the Pdf conventions.
- * @param i the float
to be appended
- * @return a reference to this ByteBuffer
object
- */
- public ByteBuffer append(float i) {
- return append((double)i);
- }
-
- /**
- * Appends a string representation of a double
according
- * to the Pdf conventions.
- * @param d the double
to be appended
- * @return a reference to this ByteBuffer
object
- */
- public ByteBuffer append(double d) {
- append(formatDouble(d, this));
- return this;
- }
-
- /**
- * Outputs a double
into a format suitable for the PDF.
- * @param d a double
- * @return the String
representation of the double
- */
- public static String formatDouble(double d) {
- return formatDouble(d, null);
- }
-
- /**
- * Outputs a double
into a format suitable for the PDF.
- * @param d a double
- * @return the String
representation of the double
if
- * d
is null
. If d
is not null
,
- * then the double is appended directly to the buffer and this methods returns null
.
- */
- public static String formatDouble(double d, ByteBuffer buf) {
- boolean negative = false;
- if (Math.abs(d) < 0.000015) {
- if (buf != null) {
- buf.append((byte)ZERO);
- return null;
- } else {
- return "0";
- }
- }
- if (d < 0) {
- negative = true;
- d = -d;
- }
- if (d < 1.0) {
- d += 0.000005;
- if (d >= 1) {
- if (negative) {
- if (buf != null) {
- buf.append((byte)'-');
- buf.append((byte)'1');
- return null;
- } else {
- return "-1";
- }
- } else {
- if (buf != null) {
- buf.append((byte)'1');
- return null;
- } else {
- return "1";
- }
- }
- }
- if (buf != null) {
- int v = (int) (d * 100000);
-
- if (negative) buf.append((byte)'-');
- buf.append((byte)'0');
- buf.append((byte)'.');
-
- buf.append( (byte)(v / 10000 + ZERO) );
- if (v % 10000 != 0) {
- buf.append( (byte)((v / 1000) % 10 + ZERO) );
- if (v % 1000 != 0) {
- buf.append( (byte)((v / 100) % 10 + ZERO) );
- if (v % 100 != 0) {
- buf.append((byte)((v / 10) % 10 + ZERO) );
- if (v % 10 != 0) {
- buf.append((byte)((v) % 10 + ZERO) );
- }
- }
- }
- }
- return null;
- } else {
- int x = 100000;
- int v = (int) (d * x);
-
- StringBuffer res = new StringBuffer();
- if (negative) res.append('-');
- res.append("0.");
-
- while( v < x/10 ) {
- res.append('0');
- x /= 10;
- }
- res.append(v);
- int cut = res.length() - 1;
- while (res.charAt(cut) == '0') {
- --cut;
- }
- res.setLength(cut + 1);
- return res.toString();
- }
- } else if (d <= 32767) {
- d += 0.005;
- int v = (int) (d * 100);
-
- if (v < byteCacheSize && byteCache[v] != null) {
- if (buf != null) {
- if (negative) buf.append((byte)'-');
- buf.append(byteCache[v]);
- return null;
- } else {
- String tmp = PdfEncodings.convertToString(byteCache[v], null);
- if (negative) tmp = "-" + tmp;
- return tmp;
- }
- }
- if (buf != null) {
- if (v < byteCacheSize) {
- //create the cachebyte[]
- byte[] cache;
- int size = 0;
- if (v >= 1000000) {
- //the original number is >=10000, we need 5 more bytes
- size += 5;
- } else if (v >= 100000) {
- //the original number is >=1000, we need 4 more bytes
- size += 4;
- } else if (v >= 10000) {
- //the original number is >=100, we need 3 more bytes
- size += 3;
- } else if (v >= 1000) {
- //the original number is >=10, we need 2 more bytes
- size += 2;
- } else if (v >= 100) {
- //the original number is >=1, we need 1 more bytes
- size += 1;
- }
-
- //now we must check if we have a decimal number
- if (v % 100 != 0) {
- //yes, do not forget the "."
- size += 2;
- }
- if (v % 10 != 0) {
- size++;
- }
- cache = new byte[size];
- int add = 0;
- if (v >= 1000000) {
- cache[add++] = bytes[(v / 1000000)];
- }
- if (v >= 100000) {
- cache[add++] = bytes[(v / 100000) % 10];
- }
- if (v >= 10000) {
- cache[add++] = bytes[(v / 10000) % 10];
- }
- if (v >= 1000) {
- cache[add++] = bytes[(v / 1000) % 10];
- }
- if (v >= 100) {
- cache[add++] = bytes[(v / 100) % 10];
- }
-
- if (v % 100 != 0) {
- cache[add++] = (byte)'.';
- cache[add++] = bytes[(v / 10) % 10];
- if (v % 10 != 0) {
- cache[add++] = bytes[v % 10];
- }
- }
- byteCache[v] = cache;
- }
-
- if (negative) buf.append((byte)'-');
- if (v >= 1000000) {
- buf.append( bytes[(v / 1000000)] );
- }
- if (v >= 100000) {
- buf.append( bytes[(v / 100000) % 10] );
- }
- if (v >= 10000) {
- buf.append( bytes[(v / 10000) % 10] );
- }
- if (v >= 1000) {
- buf.append( bytes[(v / 1000) % 10] );
- }
- if (v >= 100) {
- buf.append( bytes[(v / 100) % 10] );
- }
-
- if (v % 100 != 0) {
- buf.append((byte)'.');
- buf.append( bytes[(v / 10) % 10] );
- if (v % 10 != 0) {
- buf.append( bytes[v % 10] );
- }
- }
- return null;
- } else {
- StringBuffer res = new StringBuffer();
- if (negative) res.append((char)'-');
- if (v >= 1000000) {
- res.append( chars[(v / 1000000)] );
- }
- if (v >= 100000) {
- res.append( chars[(v / 100000) % 10] );
- }
- if (v >= 10000) {
- res.append( chars[(v / 10000) % 10] );
- }
- if (v >= 1000) {
- res.append( chars[(v / 1000) % 10] );
- }
- if (v >= 100) {
- res.append( chars[(v / 100) % 10] );
- }
-
- if (v % 100 != 0) {
- res.append((char)'.');
- res.append( chars[(v / 10) % 10] );
- if (v % 10 != 0) {
- res.append( chars[v % 10] );
- }
- }
- return res.toString();
- }
- } else {
- StringBuffer res = new StringBuffer();
- if (negative) res.append('-');
- d += 0.5;
- long v = (long) d;
- return res.append(v).toString();
- }
- }
-
- /**
- * Sets the size to zero.
- */
- public void reset() {
- count = 0;
- }
-
- /**
- * Creates a newly allocated byte array. Its size is the current
- * size of this output stream and the valid contents of the buffer
- * have been copied into it.
- *
- * @return the current contents of this output stream, as a byte array.
- */
- public byte[] toByteArray() {
- byte newbuf[] = new byte[count];
- System.arraycopy(buf, 0, newbuf, 0, count);
- return newbuf;
- }
-
- /**
- * Returns the current size of the buffer.
- *
- * @return the value of the count
field, which is the number of valid bytes in this byte buffer.
- */
- public int size() {
- return count;
- }
-
- /**
- * Converts the buffer's contents into a string, translating bytes into
- * characters according to the platform's default character encoding.
- *
- * @return String translated from the buffer's contents.
- */
- public String toString() {
- return new String(buf, 0, count);
- }
-
- /**
- * Converts the buffer's contents into a string, translating bytes into
- * characters according to the specified character encoding.
- *
- * @param enc a character-encoding name.
- * @return String translated from the buffer's contents.
- * @throws UnsupportedEncodingException
- * If the named encoding is not supported.
- */
- public String toString(String enc) throws UnsupportedEncodingException {
- return new String(buf, 0, count, enc);
- }
-
- /**
- * Writes the complete contents of this byte buffer output to
- * the specified output stream argument, as if by calling the output
- * stream's write method using out.write(buf, 0, count)
.
- *
- * @param out the output stream to which to write the data.
- * @exception IOException if an I/O error occurs.
- */
- public void writeTo(OutputStream out) throws IOException {
- out.write(buf, 0, count);
- }
-
- public void write(int b) throws IOException {
- append((byte)b);
- }
-
- public void write(byte[] b, int off, int len) {
- append(b, off, len);
- }
-
- public byte[] getBuffer() {
- return buf;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/CFFFont.java pdftk-2.01/java/com/lowagie/text/pdf/CFFFont.java
--- pdftk-1.45/java/com/lowagie/text/pdf/CFFFont.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/CFFFont.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,1187 +0,0 @@
-/*
- *
- * Copyright 2003 Sivan Toledo
- *
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- */
-
-/*
- * Comments by Sivan Toledo:
- * I created this class in order to add to iText the ability to utilize
- * OpenType fonts with CFF glyphs (these usually have an .otf extension).
- * The CFF font within the CFF table of the OT font might be either a CID
- * or a Type1 font. (CFF fonts may also contain multiple fonts; I do not
- * know if this is allowed in an OT table). The PDF spec, however, only
- * allow a CID font with an Identity-H or Identity-V encoding. Otherwise,
- * you are limited to an 8-bit encoding.
- * Adobe fonts come in both flavors. That is, the OTFs sometimes have
- * a CID CFF inside (for Japanese fonts), and sometimes a Type1 CFF
- * (virtually all the others, Latin/Greek/Cyrillic). So to easily use
- * all the glyphs in the latter, without creating multiple 8-bit encoding,
- * I wrote this class, whose main purpose is to convert a Type1 font inside
- * a CFF container (which might include other fonts) into a CID CFF font
- * that can be directly embeded in the PDF.
- *
- * Limitations of the current version:
- * 1. It does not extract a single CID font from a CFF that contains that
- * particular CID along with other fonts. The Adobe Japanese OTF's that
- * I have only have one font in the CFF table, so these can be
- * embeded in the PDF as is.
- * 2. It does not yet subset fonts.
- * 3. It may or may not work on CFF fonts that are not within OTF's.
- * I didn't try that. In any case, that would probably only be
- * useful for subsetting CID fonts, not for CFF Type1 fonts (I don't
- * think there are any available.
- * I plan to extend the class to support these three features at some
- * future time.
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * @author stoledo
- */
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import com.lowagie.text.ExceptionConverter;
-
-public class CFFFont {
-
- static final String operatorNames[] = {
- "version", "Notice", "FullName", "FamilyName",
- "Weight", "FontBBox", "BlueValues", "OtherBlues",
- "FamilyBlues", "FamilyOtherBlues", "StdHW", "StdVW",
- "UNKNOWN_12", "UniqueID", "XUID", "charset",
- "Encoding", "CharStrings", "Private", "Subrs",
- "defaultWidthX", "nominalWidthX", "UNKNOWN_22", "UNKNOWN_23",
- "UNKNOWN_24", "UNKNOWN_25", "UNKNOWN_26", "UNKNOWN_27",
- "UNKNOWN_28", "UNKNOWN_29", "UNKNOWN_30", "UNKNOWN_31",
- "Copyright", "isFixedPitch", "ItalicAngle", "UnderlinePosition",
- "UnderlineThickness", "PaintType", "CharstringType", "FontMatrix",
- "StrokeWidth", "BlueScale", "BlueShift", "BlueFuzz",
- "StemSnapH", "StemSnapV", "ForceBold", "UNKNOWN_12_15",
- "UNKNOWN_12_16", "LanguageGroup", "ExpansionFactor", "initialRandomSeed",
- "SyntheticBase", "PostScript", "BaseFontName", "BaseFontBlend",
- "UNKNOWN_12_24", "UNKNOWN_12_25", "UNKNOWN_12_26", "UNKNOWN_12_27",
- "UNKNOWN_12_28", "UNKNOWN_12_29", "ROS", "CIDFontVersion",
- "CIDFontRevision", "CIDFontType", "CIDCount", "UIDBase",
- "FDArray", "FDSelect", "FontName"
- };
-
- static final String standardStrings[] = {
- // Automatically generated from Appendix A of the CFF specification; do
- // not edit. Size should be 391.
- ".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar",
- "percent", "ampersand", "quoteright", "parenleft", "parenright",
- "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one",
- "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon",
- "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C",
- "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
- "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash",
- "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c",
- "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
- "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright",
- "asciitilde", "exclamdown", "cent", "sterling", "fraction", "yen",
- "florin", "section", "currency", "quotesingle", "quotedblleft",
- "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash",
- "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet",
- "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
- "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex",
- "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla",
- "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash",
- "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe",
- "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth",
- "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar",
- "degree", "thorn", "threequarters", "twosuperior", "registered", "minus",
- "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex",
- "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute",
- "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis",
- "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve",
- "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave",
- "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis",
- "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex",
- "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave",
- "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde",
- "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute",
- "ydieresis", "zcaron", "exclamsmall", "Hungarumlautsmall",
- "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
- "parenleftsuperior", "parenrightsuperior", "twodotenleader",
- "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle",
- "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle",
- "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior",
- "threequartersemdash", "periodsuperior", "questionsmall", "asuperior",
- "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior",
- "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior",
- "ssuperior", "tsuperior", "ff", "ffi", "ffl", "parenleftinferior",
- "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall",
- "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall",
- "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall",
- "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
- "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary",
- "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle",
- "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall",
- "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash",
- "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall",
- "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths",
- "seveneighths", "onethird", "twothirds", "zerosuperior", "foursuperior",
- "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior",
- "ninesuperior", "zeroinferior", "oneinferior", "twoinferior",
- "threeinferior", "fourinferior", "fiveinferior", "sixinferior",
- "seveninferior", "eightinferior", "nineinferior", "centinferior",
- "dollarinferior", "periodinferior", "commainferior", "Agravesmall",
- "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall",
- "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall",
- "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall",
- "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
- "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall",
- "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall",
- "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall",
- "Ydieresissmall", "001.000", "001.001", "001.002", "001.003", "Black",
- "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold"
- };
-
- //private String[] strings;
- public String getString(char sid) {
- if (sid < standardStrings.length) return standardStrings[sid];
- if (sid >= standardStrings.length+(stringOffsets.length-1)) return null;
- int j = sid - standardStrings.length;
- //java.lang.System.err.println("going for "+j);
- int p = getPosition();
- seek(stringOffsets[j]);
- StringBuffer s = new StringBuffer();
- for (int k=stringOffsets[j]; k count in the index header. 1->offset size in index header
- + 2+1
- //offset array size * offset size
- + (count+1)*indexOffSize
- //???zero <-> one base
- - 1
- // read object offset relative to object array base
- + getOffset(indexOffSize);
- }
- //nextIndexOffset = offsets[count];
- return offsets;
- }
-
- protected String key;
- protected Object[] args = new Object[48];
- protected int arg_count = 0;
-
- protected void getDictItem() {
- for (int i=0; i= 32 && b0 <= 246) {
- byte item = (byte) (b0-139);
- args[arg_count] = new Integer(item);
- arg_count++;
- //System.err.println(item+" ");
- continue;
- }
- if (b0 >= 247 && b0 <= 250) {
- char b1 = getCard8();
- short item = (short) ((b0-247)*256+b1+108);
- args[arg_count] = new Integer(item);
- arg_count++;
- //System.err.println(item+" ");
- continue;
- }
- if (b0 >= 251 && b0 <= 254) {
- char b1 = getCard8();
- short item = (short) (-(b0-251)*256-b1-108);
- args[arg_count] = new Integer(item);
- arg_count++;
- //System.err.println(item+" ");
- continue;
- }
- if (b0 == 30) {
- String item = "";
- boolean done = false;
- char buffer = 0;
- byte avail = 0;
- int nibble = 0;
- while (!done) {
- // get a nibble
- if (avail==0) { buffer = getCard8(); avail=2; }
- if (avail==1) { nibble = (buffer / 16); avail--; }
- if (avail==2) { nibble = (buffer % 16); avail--; }
- switch (nibble) {
- case 0xa: item += "." ; break;
- case 0xb: item += "E" ; break;
- case 0xc: item += "E-"; break;
- case 0xe: item += "-" ; break;
- case 0xf: done=true ; break;
- default:
- if (nibble >= 0 && nibble <= 9)
- item += String.valueOf(nibble);
- else {
- item += "";
- done = true;
- }
- break;
- }
- }
- args[arg_count] = item;
- arg_count++;
- //System.err.println(" real=["+item+"]");
- continue;
- }
- if (b0 <= 21) {
- gotKey=true;
- if (b0 != 12) key = operatorNames[b0];
- else key = operatorNames[32 + getCard8()];
- //for (int i=0; i>> 24) & 0xff);
- i++;
- case 3:
- buffer[myOffset+i] = (byte) ((value >>> 16) & 0xff);
- i++;
- case 2:
- buffer[myOffset+i] = (byte) ((value >>> 8) & 0xff);
- i++;
- case 1:
- buffer[myOffset+i] = (byte) ((value >>> 0) & 0xff);
- i++;
- }
- /*
- int mask = 0xff;
- for (int i=size-1; i>=0; i--) {
- buffer[myOffset+i] = (byte) (value & mask);
- mask <<= 8;
- }
- */
- }
- }
-
- static protected final class IndexBaseItem extends Item {
- public IndexBaseItem() {}
- }
-
- static protected final class IndexMarkerItem extends Item {
- private OffsetItem offItem;
- private IndexBaseItem indexBase;
- public IndexMarkerItem(OffsetItem offItem, IndexBaseItem indexBase) {
- this.offItem = offItem;
- this.indexBase = indexBase;
- }
- public void xref() {
- //System.err.println("index marker item, base="+indexBase.myOffset+" my="+this.myOffset);
- offItem.set(this.myOffset-indexBase.myOffset+1);
- }
- }
- /**
- *
- * @author orly manor
- *
- * TODO To change the template for this generated type comment go to
- * Window - Preferences - Java - Code Generation - Code and Comments
- */
- static protected final class SubrMarkerItem extends Item {
- private OffsetItem offItem;
- private IndexBaseItem indexBase;
- public SubrMarkerItem(OffsetItem offItem, IndexBaseItem indexBase) {
- this.offItem = offItem;
- this.indexBase = indexBase;
- }
- public void xref() {
- //System.err.println("index marker item, base="+indexBase.myOffset+" my="+this.myOffset);
- offItem.set(this.myOffset-indexBase.myOffset);
- }
- }
-
-
- /** an unknown offset in a dictionary for the list.
- * We will fix up the offset later; for now, assume it's large.
- */
- static protected final class DictOffsetItem extends OffsetItem {
- public final int size;
- public DictOffsetItem() {this.size=5; }
-
- public void increment(int[] currentOffset) {
- super.increment(currentOffset);
- currentOffset[0] += size;
- }
- // this is incomplete!
- public void emit(byte[] buffer) {
- if (size==5) {
- buffer[myOffset] = 29;
- buffer[myOffset+1] = (byte) ((value >>> 24) & 0xff);
- buffer[myOffset+2] = (byte) ((value >>> 16) & 0xff);
- buffer[myOffset+3] = (byte) ((value >>> 8) & 0xff);
- buffer[myOffset+4] = (byte) ((value >>> 0) & 0xff);
- }
- }
- }
-
- /** Card24 item.
- */
-
- static protected final class UInt24Item extends Item {
- public int value;
- public UInt24Item(int value) {this.value=value;}
-
- public void increment(int[] currentOffset) {
- super.increment(currentOffset);
- currentOffset[0] += 3;
- }
- // this is incomplete!
- public void emit(byte[] buffer) {
- buffer[myOffset+0] = (byte) ((value >>> 16) & 0xff);
- buffer[myOffset+1] = (byte) ((value >>> 8) & 0xff);
- buffer[myOffset+2] = (byte) ((value >>> 0) & 0xff);
- }
- }
-
- /** Card32 item.
- */
-
- static protected final class UInt32Item extends Item {
- public int value;
- public UInt32Item(int value) {this.value=value;}
-
- public void increment(int[] currentOffset) {
- super.increment(currentOffset);
- currentOffset[0] += 4;
- }
- // this is incomplete!
- public void emit(byte[] buffer) {
- buffer[myOffset+0] = (byte) ((value >>> 24) & 0xff);
- buffer[myOffset+1] = (byte) ((value >>> 16) & 0xff);
- buffer[myOffset+2] = (byte) ((value >>> 8) & 0xff);
- buffer[myOffset+3] = (byte) ((value >>> 0) & 0xff);
- }
- }
-
- /** A SID or Card16 item.
- */
-
- static protected final class UInt16Item extends Item {
- public char value;
- public UInt16Item(char value) {this.value=value;}
-
- public void increment(int[] currentOffset) {
- super.increment(currentOffset);
- currentOffset[0] += 2;
- }
- // this is incomplete!
- public void emit(byte[] buffer) {
- buffer[myOffset+0] = (byte) ((value >>> 8) & 0xff);
- buffer[myOffset+1] = (byte) ((value >>> 0) & 0xff);
- }
- }
-
- /** A Card8 item.
- */
-
- static protected final class UInt8Item extends Item {
- public char value;
- public UInt8Item(char value) {this.value=value;}
-
- public void increment(int[] currentOffset) {
- super.increment(currentOffset);
- currentOffset[0] += 1;
- }
- // this is incomplete!
- public void emit(byte[] buffer) {
- buffer[myOffset+0] = (byte) ((value >>> 0) & 0xff);
- }
- }
-
- static protected final class StringItem extends Item {
- public String s;
- public StringItem(String s) {this.s=s;}
-
- public void increment(int[] currentOffset) {
- super.increment(currentOffset);
- currentOffset[0] += s.length();
- }
- public void emit(byte[] buffer) {
- for (int i=0; i>> 24) & 0xff);
- buffer[myOffset+2] = (byte) ((value >>> 16) & 0xff);
- buffer[myOffset+3] = (byte) ((value >>> 8) & 0xff);
- buffer[myOffset+4] = (byte) ((value >>> 0) & 0xff);
- }
- }
- }
-
- /** An offset-marker item for the list.
- * It is used to mark an offset and to set the offset list item.
- */
-
- static protected final class MarkerItem extends Item {
- OffsetItem p;
- public MarkerItem(OffsetItem pointerToMarker) {p=pointerToMarker;}
- public void xref() {
- p.set(this.myOffset);
- }
- }
-
- /** a utility that creates a range item for an entire index
- *
- * @param indexOffset where the index is
- * @return a range item representing the entire index
- */
-
- protected RangeItem getEntireIndexRange(int indexOffset) {
- seek(indexOffset);
- int count = getCard16();
- if (count==0) {
- return new RangeItem(buf,indexOffset,2);
- } else {
- int indexOffSize = getCard8();
- seek(indexOffset+2+1+count*indexOffSize);
- int size = getOffset(indexOffSize)-1;
- return new RangeItem(buf,indexOffset,
- 2+1+(count+1)*indexOffSize+size);
- }
- }
-
-
- /** get a single CID font. The PDF architecture (1.4)
- * supports 16-bit strings only with CID CFF fonts, not
- * in Type-1 CFF fonts, so we convert the font to CID if
- * it is in the Type-1 format.
- * Two other tasks that we need to do are to select
- * only a single font from the CFF package (this again is
- * a PDF restriction) and to subset the CharStrings glyph
- * description.
- */
-
-
- public byte[] getCID(String fontName)
- //throws java.io.FileNotFoundException
- {
- int j;
- for (j=0; j 127)
- fdFontName = fdFontName.substring(0,127);
- String extraStrings = "Adobe"+"Identity"+fdFontName;
-
- int origStringsLen = stringOffsets[stringOffsets.length-1]
- - stringOffsets[0];
- int stringsBaseOffset = stringOffsets[0]-1;
-
- byte stringsIndexOffSize;
- if (origStringsLen+extraStrings.length() <= 0xff) stringsIndexOffSize = 1;
- else if (origStringsLen+extraStrings.length() <= 0xffff) stringsIndexOffSize = 2;
- else if (origStringsLen+extraStrings.length() <= 0xffffff) stringsIndexOffSize = 3;
- else stringsIndexOffSize = 4;
-
- l.addLast(new UInt16Item((char)((stringOffsets.length-1)+3))); // count
- l.addLast(new UInt8Item((char)stringsIndexOffSize)); // offSize
- for (int i=0; i= 0) {
- //System.err.println("has subrs="+fonts[j].privateSubrs+" ,len="+fonts[j].privateLength);
- l.addLast(getEntireIndexRange(fonts[j].privateSubrs));
- }
- }
-
- // copy the charstring index
-
- l.addLast(new MarkerItem(charstringsRef));
- l.addLast(getEntireIndexRange(fonts[j].charstringsOffset));
-
- // now create the new CFF font
-
- int[] currentOffset = new int[1];
- currentOffset[0] = 0;
-
- Iterator listIter = l.iterator();
- while ( listIter.hasNext() ) {
- Item item = (Item) listIter.next();
- item.increment(currentOffset);
- }
-
- listIter = l.iterator();
- while ( listIter.hasNext() ) {
- Item item = (Item) listIter.next();
- item.xref();
- }
-
- int size = currentOffset[0];
- byte[] b = new byte[size];
-
- listIter = l.iterator();
- while ( listIter.hasNext() ) {
- Item item = (Item) listIter.next();
- item.emit(b);
- }
-
- return b;
- }
-
-
- public boolean isCID(String fontName) {
- int j;
- for (j=0; j");
- }
-
- // string index
-
- //strings = new String[stringOffsets.length-1];
- /*
- System.err.println("std strings = "+standardStrings.length);
- System.err.println("fnt strings = "+(stringOffsets.length-1));
- for (char j=0; j");
- }
- */
-
- // top dict
-
- for (int j=0; j= 0) {
- //System.err.println("PRIVATE::");
- seek(fonts[j].privateOffset);
- while (getPosition() < fonts[j].privateOffset+fonts[j].privateLength) {
- getDictItem();
- if (key=="Subrs")
- //Add the private offset to the lsubrs since the offset is
- // relative to the begining of the PrivateDict
- fonts[j].privateSubrs = ((Integer)args[0]).intValue()+fonts[j].privateOffset;
- }
- }
-
- // fdarray index
- if (fonts[j].fdarrayOffset >= 0) {
- int[] fdarrayOffsets = getIndex(fonts[j].fdarrayOffset);
-
- fonts[j].fdprivateOffsets = new int[fdarrayOffsets.length-1];
- fonts[j].fdprivateLengths = new int[fdarrayOffsets.length-1];
-
- //System.err.println("FD Font::");
-
- for (int k=0; k
- * @author Oren Manor & Ygal Blum
- */
-public class CFFFontSubset extends CFFFont {
-
- /**
- * The Strings in this array represent Type1/Type2 operator names
- */
- static final String SubrsFunctions[] = {
- "RESERVED_0","hstem","RESERVED_2","vstem","vmoveto","rlineto","hlineto","vlineto",
- "rrcurveto","RESERVED_9","callsubr","return","escape","RESERVED_13",
- "endchar","RESERVED_15","RESERVED_16","RESERVED_17","hstemhm","hintmask",
- "cntrmask","rmoveto","hmoveto","vstemhm","rcurveline","rlinecurve","vvcurveto",
- "hhcurveto","shortint","callgsubr","vhcurveto","hvcurveto"
- };
- /**
- * The Strings in this array represent Type1/Type2 escape operator names
- */
- static final String SubrsEscapeFuncs[] = {
- "RESERVED_0","RESERVED_1","RESERVED_2","and","or","not","RESERVED_6",
- "RESERVED_7","RESERVED_8","abs","add","sub","div","RESERVED_13","neg",
- "eq","RESERVED_16","RESERVED_17","drop","RESERVED_19","put","get","ifelse",
- "random","mul","RESERVED_25","sqrt","dup","exch","index","roll","RESERVED_31",
- "RESERVED_32","RESERVED_33","hflex","flex","hflex1","flex1","RESERVED_REST"
- };
-
- /**
- * A HashMap containing the glyphs used in the text after being converted
- * to glyph number by the CMap
- */
- HashMap GlyphsUsed;
- /**
- * The GlyphsUsed keys as an ArrayList
- */
- ArrayList glyphsInList;
- /**
- * A HashMap for keeping the FDArrays being used by the font
- */
- HashMap FDArrayUsed = new HashMap();
- /**
- * A HashMaps array for keeping the subroutines used in each FontDict
- */
- HashMap[] hSubrsUsed;
- /**
- * The SubroutinesUsed HashMaps as ArrayLists
- */
- ArrayList[] lSubrsUsed;
- /**
- * A HashMap for keeping the Global subroutines used in the font
- */
- HashMap hGSubrsUsed = new HashMap();
- /**
- * The Global SubroutinesUsed HashMaps as ArrayLists
- */
- ArrayList lGSubrsUsed = new ArrayList();
- /**
- * A HashMap for keeping the subroutines used in a non-cid font
- */
- HashMap hSubrsUsedNonCID = new HashMap();
- /**
- * The SubroutinesUsed HashMap as ArrayList
- */
- ArrayList lSubrsUsedNonCID = new ArrayList();
- /**
- * An array of the new Indexs for the local Subr. One index for each FontDict
- */
- byte[][] NewLSubrsIndex;
- /**
- * The new subroutines index for a non-cid font
- */
- byte[] NewSubrsIndexNonCID;
- /**
- * The new global subroutines index of the font
- */
- byte[] NewGSubrsIndex;
- /**
- * The new CharString of the font
- */
- byte[] NewCharStringsIndex;
-
- /**
- * The bias for the global subroutines
- */
- int GBias = 0;
-
- /**
- * The linked list for generating the new font stream
- */
- LinkedList OutputList;
-
- /**
- * Number of arguments to the stem operators in a subroutine calculated recursivly
- */
- int NumOfHints=0;
-
-
- /**
- * C'tor for CFFFontSubset
- * @param rf - The font file
- * @param GlyphsUsed - a HashMap that contains the glyph used in the subset
- */
- public CFFFontSubset(RandomAccessFileOrArray rf,HashMap GlyphsUsed){
- // Use CFFFont c'tor in order to parse the font file.
- super(rf);
- this.GlyphsUsed = GlyphsUsed;
- //Put the glyphs into a list
- glyphsInList = new ArrayList(GlyphsUsed.keySet());
-
-
- for (int i=0;i=0)
- {
- // Proces the FDSelect
- readFDSelect(i);
- // Build the FDArrayUsed hashmap
- BuildFDArrayUsed(i);
- }
- if (fonts[i].isCID)
- // Build the FD Array used Hash Map
- ReadFDArray(i);
- // compute the charset length
- fonts[i].CharsetLength = CountCharset(fonts[i].charsetOffset,fonts[i].nglyphs);
- }
- }
-
- /**
- * Calculates the length of the charset according to its format
- * @param Offset The Charset Offset
- * @param NumofGlyphs Number of glyphs in the font
- * @return the length of the Charset
- */
- int CountCharset(int Offset,int NumofGlyphs){
- int format;
- int Length=0;
- seek(Offset);
- // Read the format
- format = getCard8();
- // Calc according to format
- switch (format){
- case 0:
- Length = 1+2*NumofGlyphs;
- break;
- case 1:
- Length = 1+3*CountRange(NumofGlyphs,1);
- break;
- case 2:
- Length = 1+4*CountRange(NumofGlyphs,2);
- break;
- default:
- break;
- }
- return Length;
- }
-
- /**
- * Function calculates the number of ranges in the Charset
- * @param NumofGlyphs The number of glyphs in the font
- * @param Type The format of the Charset
- * @return The number of ranges in the Charset data structure
- */
- int CountRange(int NumofGlyphs,int Type){
- int num=0;
- int i=1,Sid,nLeft;
- while (i= 0)
- GBias = CalcBias(gsubrIndexOffset,j);
-
- // Prepare the new CharStrings Index
- BuildNewCharString(j);
- // Prepare the new Global and Local Subrs Indices
- BuildNewLGSubrs(j);
- // Build the new file
- byte[] Ret = BuildNewFile(j);
- return Ret;
- }
- finally {
- try {
- buf.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- }
-
- /**
- * Function calcs bias according to the CharString type and the count
- * of the subrs
- * @param Offset The offset to the relevent subrs index
- * @param Font the font
- * @return The calculated Bias
- */
- protected int CalcBias(int Offset,int Font)
- {
- seek(Offset);
- int nSubrs = getCard16();
- // If type==1 -> bias=0
- if (fonts[Font].CharstringType == 1)
- return 0;
- // else calc according to the count
- else if (nSubrs < 1240)
- return 107;
- else if (nSubrs < 33900)
- return 1131;
- else
- return 32768;
- }
-
- /**
- *Function uses BuildNewIndex to create the new index of the subset charstrings
- * @param FontIndex the font
- * @throws IOException
- */
- protected void BuildNewCharString(int FontIndex) throws IOException
- {
- NewCharStringsIndex = BuildNewIndex(fonts[FontIndex].charstringsOffsets,GlyphsUsed);
- }
-
- /**
- * Function builds the new local & global subsrs indices. IF CID then All of
- * the FD Array lsubrs will be subsetted.
- * @param Font the font
- * @throws IOException
- */
- protected void BuildNewLGSubrs(int Font)throws IOException
- {
- // If the font is CID then the lsubrs are divided into FontDicts.
- // for each FD array the lsubrs will be subsetted.
- if(fonts[Font].isCID)
- {
- // Init the hasmap-array and the arraylist-array to hold the subrs used
- // in each private dict.
- hSubrsUsed = new HashMap[fonts[Font].fdprivateOffsets.length];
- lSubrsUsed = new ArrayList[fonts[Font].fdprivateOffsets.length];
- // A [][] which will store the byte array for each new FD Array lsubs index
- NewLSubrsIndex = new byte[fonts[Font].fdprivateOffsets.length][];
- // An array to hold the offset for each Lsubr index
- fonts[Font].PrivateSubrsOffset = new int[fonts[Font].fdprivateOffsets.length];
- // A [][] which will store the offset array for each lsubr index
- fonts[Font].PrivateSubrsOffsetsArray = new int[fonts[Font].fdprivateOffsets.length][];
-
- // Put the FDarrayUsed into a list
- ArrayList FDInList = new ArrayList(FDArrayUsed.keySet());
- // For each FD array which is used subset the lsubr
- for (int j=0;j=0)
- {
- //Scans the Charsting data storing the used Local and Global subroutines
- // by the glyphs. Scans the Subrs recursivley.
- BuildSubrUsed(Font,FD,fonts[Font].PrivateSubrsOffset[FD],fonts[Font].PrivateSubrsOffsetsArray[FD],hSubrsUsed[FD],lSubrsUsed[FD]);
- // Builds the New Local Subrs index
- NewLSubrsIndex[FD] = BuildNewIndex(fonts[Font].PrivateSubrsOffsetsArray[FD],hSubrsUsed[FD]);
- }
- }
- }
- // If the font is not CID && the Private Subr exists then subset:
- else if (fonts[Font].privateSubrs>=0)
- {
- // Build the subrs offsets;
- fonts[Font].SubrsOffsets = getIndex(fonts[Font].privateSubrs);
- //Scans the Charsting data storing the used Local and Global subroutines
- // by the glyphs. Scans the Subrs recursivley.
- BuildSubrUsed(Font,-1,fonts[Font].privateSubrs,fonts[Font].SubrsOffsets,hSubrsUsedNonCID,lSubrsUsedNonCID);
- }
- // For all fonts susbset the Global Subroutines
- // Scan the Global Subr Hashmap recursivly on the Gsubrs
- BuildGSubrsUsed(Font);
- if (fonts[Font].privateSubrs>=0)
- // Builds the New Local Subrs index
- NewSubrsIndexNonCID = BuildNewIndex(fonts[Font].SubrsOffsets,hSubrsUsedNonCID);
- //Builds the New Global Subrs index
- NewGSubrsIndex = BuildNewIndex(gsubrOffsets,hGSubrsUsed);
- }
-
- /**
- * The function finds for the FD array processed the local subr offset and its
- * offset array.
- * @param Font the font
- * @param FD The FDARRAY processed
- */
- protected void BuildFDSubrsOffsets(int Font,int FD)
- {
- // Initiate to -1 to indicate lsubr operator present
- fonts[Font].PrivateSubrsOffset[FD] = -1;
- // Goto begining of objects
- seek(fonts[Font].fdprivateOffsets[FD]);
- // While in the same object:
- while (getPosition() < fonts[Font].fdprivateOffsets[FD]+fonts[Font].fdprivateLengths[FD])
- {
- getDictItem();
- // If the dictItem is the "Subrs" then find and store offset,
- if (key=="Subrs")
- fonts[Font].PrivateSubrsOffset[FD] = ((Integer)args[0]).intValue()+fonts[Font].fdprivateOffsets[FD];
- }
- //Read the lsub index if the lsubr was found
- if (fonts[Font].PrivateSubrsOffset[FD] >= 0)
- fonts[Font].PrivateSubrsOffsetsArray[FD] = getIndex(fonts[Font].PrivateSubrsOffset[FD]);
- }
-
- /**
- * Function uses ReadAsubr on the glyph used to build the LSubr & Gsubr HashMap.
- * The HashMap (of the lsub only) is then scaned recursivly for Lsubr & Gsubrs
- * calls.
- * @param Font the font
- * @param FD FD array processed. 0 indicates function was called by non CID font
- * @param SubrOffset the offset to the subr index to calc the bias
- * @param SubrsOffsets the offset array of the subr index
- * @param hSubr HashMap of the subrs used
- * @param lSubr ArrayList of the subrs used
- */
- protected void BuildSubrUsed(int Font,int FD,int SubrOffset,int[] SubrsOffsets,HashMap hSubr,ArrayList lSubr)
- {
-
- // Calc the Bias for the subr index
- int LBias = CalcBias(SubrOffset,Font);
-
- // For each glyph used find its GID, start & end pos
- for (int i=0;i= 0)
- {
- EmptyStack();
- NumOfHints=0;
- // Using FDSELECT find the FD Array the glyph belongs to.
- int GlyphFD = fonts[Font].FDSelect[glyph];
- // If the Glyph is part of the FD being processed
- if (GlyphFD == FD)
- // Find the Subrs called by the glyph and insert to hash:
- ReadASubr(Start,End,GBias,LBias,hSubr,lSubr,SubrsOffsets);
- }
- else
- // If the font is not CID
- //Find the Subrs called by the glyph and insert to hash:
- ReadASubr(Start,End,GBias,LBias,hSubr,lSubr,SubrsOffsets);
- }
- // For all Lsubrs used, check recusrivly for Lsubr & Gsubr used
- for (int i=0;i=0)
- {
- // Read and process the subr
- int Start = SubrsOffsets[Subr];
- int End = SubrsOffsets[Subr+1];
- ReadASubr(Start,End,GBias,LBias,hSubr,lSubr,SubrsOffsets);
- }
- }
- }
-
- /**
- * Function scans the Glsubr used ArrayList to find recursive calls
- * to Gsubrs and adds to Hashmap & ArrayList
- * @param Font the font
- */
- protected void BuildGSubrsUsed(int Font)
- {
- int LBias = 0;
- int SizeOfNonCIDSubrsUsed = 0;
- if (fonts[Font].privateSubrs>=0)
- {
- LBias = CalcBias(fonts[Font].privateSubrs,Font);
- SizeOfNonCIDSubrsUsed = lSubrsUsedNonCID.size();
- }
-
- // For each global subr used
- for (int i=0;i=0)
- {
- // Read the subr and process
- int Start = gsubrOffsets[Subr];
- int End = gsubrOffsets[Subr+1];
-
- if (fonts[Font].isCID)
- ReadASubr(Start,End,GBias,0,hGSubrsUsed,lGSubrsUsed,null);
- else
- {
- ReadASubr(Start,End,GBias,LBias,hSubrsUsedNonCID,lSubrsUsedNonCID,fonts[Font].SubrsOffsets);
- if (SizeOfNonCIDSubrsUsed < lSubrsUsedNonCID.size())
- {
- for (int j=SizeOfNonCIDSubrsUsed;j=0)
- {
- // Read the subr and process
- int LStart = fonts[Font].SubrsOffsets[LSubr];
- int LEnd = fonts[Font].SubrsOffsets[LSubr+1];
- ReadASubr(LStart,LEnd,GBias,LBias,hSubrsUsedNonCID,lSubrsUsedNonCID,fonts[Font].SubrsOffsets);
- }
- }
- SizeOfNonCIDSubrsUsed = lSubrsUsedNonCID.size();
- }
- }
- }
- }
- }
-
- /**
- * The function reads a subrs (glyph info) between begin and end.
- * Adds calls to a Lsubr to the hSubr and lSubrs.
- * Adds calls to a Gsubr to the hGSubr and lGSubrs.
- * @param begin the start point of the subr
- * @param end the end point of the subr
- * @param GBias the bias of the Global Subrs
- * @param LBias the bias of the Local Subrs
- * @param hSubr the HashMap for the lSubrs
- * @param lSubr the ArrayList for the lSubrs
- */
- protected void ReadASubr(int begin,int end,int GBias,int LBias,HashMap hSubr,ArrayList lSubr,int[] LSubrsOffsets)
- {
- // Clear the stack for the subrs
- EmptyStack();
- NumOfHints = 0;
- // Goto begining of the subr
- seek(begin);
- while (getPosition() < end)
- {
- // Read the next command
- ReadCommand();
- int pos = getPosition();
- Object TopElement=null;
- if (arg_count > 0)
- TopElement = args[arg_count-1];
- int NumOfArgs = arg_count;
- // Check the modification needed on the Argument Stack according to key;
- HandelStack();
- // a call to a Lsubr
- if (key=="callsubr")
- {
- // Verify that arguments are passed
- if (NumOfArgs > 0)
- {
- // Calc the index of the Subrs
- int Subr = ((Integer)TopElement).intValue() + LBias;
- // If the subr isn't in the HashMap -> Put in
- if (!hSubr.containsKey(new Integer (Subr)))
- {
- hSubr.put(new Integer(Subr),null);
- lSubr.add(new Integer(Subr));
- }
- CalcHints(LSubrsOffsets[Subr],LSubrsOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
- seek(pos);
- }
- }
- // a call to a Gsubr
- else if (key=="callgsubr")
- {
- // Verify that arguments are passed
- if (NumOfArgs > 0)
- {
- // Calc the index of the Subrs
- int Subr = ((Integer)TopElement).intValue() + GBias;
- // If the subr isn't in the HashMap -> Put in
- if (!hGSubrsUsed.containsKey(new Integer (Subr)))
- {
- hGSubrsUsed.put(new Integer(Subr),null);
- lGSubrsUsed.add(new Integer(Subr));
- }
- CalcHints(gsubrOffsets[Subr],gsubrOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
- seek(pos);
- }
- }
- // A call to "stem"
- else if (key == "hstem" || key == "vstem" || key == "hstemhm" || key == "vstemhm")
- // Increment the NumOfHints by the number couples of of arguments
- NumOfHints += NumOfArgs/2;
- // A call to "mask"
- else if (key == "hintmask" || key == "cntrmask")
- {
- // Compute the size of the mask
- int SizeOfMask = NumOfHints/8;
- if (NumOfHints%8 != 0 || SizeOfMask == 0)
- SizeOfMask++;
- // Continue the pointer in SizeOfMask steps
- for (int i=0;i flush the stack
- */
- protected int StackOpp()
- {
- if (key == "ifelse")
- return -3;
- if (key == "roll" || key == "put")
- return -2;
- if (key == "callsubr" || key == "callgsubr" || key == "add" || key == "sub" ||
- key == "div" || key == "mul" || key == "drop" || key == "and" ||
- key == "or" || key == "eq")
- return -1;
- if (key == "abs" || key == "neg" || key == "sqrt" || key == "exch" ||
- key == "index" || key == "get" || key == "not" || key == "return")
- return 0;
- if (key == "random" || key == "dup")
- return 1;
- return 2;
- }
-
- /**
- * Empty the Type2 Stack
- *
- */
- protected void EmptyStack()
- {
- // Null the arguments
- for (int i=0; i0)
- {
- args[arg_count-1]=null;
- arg_count--;
- }
- }
-
- /**
- * Add an item to the stack
- *
- */
- protected void PushStack()
- {
- arg_count++;
- }
-
- /**
- * The function reads the next command after the file pointer is set
- */
- protected void ReadCommand()
- {
- key = null;
- boolean gotKey = false;
- // Until a key is found
- while (!gotKey) {
- // Read the first Char
- char b0 = getCard8();
- // decode according to the type1/type2 format
- if (b0 == 28) // the two next bytes represent a short int;
- {
- int first = getCard8();
- int second = getCard8();
- args[arg_count] = new Integer(first<<8 | second);
- arg_count++;
- continue;
- }
- if (b0 >= 32 && b0 <= 246) // The byte read is the byte;
- {
- args[arg_count] = new Integer(b0 - 139);
- arg_count++;
- continue;
- }
- if (b0 >= 247 && b0 <= 250) // The byte read and the next byte constetute a short int
- {
- int w = getCard8();
- args[arg_count] = new Integer((b0-247)*256 + w + 108);
- arg_count++;
- continue;
- }
- if (b0 >= 251 && b0 <= 254)// Same as above except negative
- {
- int w = getCard8();
- args[arg_count] = new Integer(-(b0-251)*256 - w - 108);
- arg_count++;
- continue;
- }
- if (b0 == 255)// The next for bytes represent a double.
- {
- int first = getCard8();
- int second = getCard8();
- int third = getCard8();
- int fourth = getCard8();
- args[arg_count] = new Integer(first<<24 | second<<16 | third<<8 | fourth);
- arg_count++;
- continue;
- }
- if (b0<=31 && b0 != 28) // An operator was found.. Set Key.
- {
- gotKey=true;
- // 12 is an escape command therefor the next byte is a part
- // of this command
- if (b0 == 12)
- {
- int b1 = getCard8();
- if (b1>SubrsEscapeFuncs.length-1)
- b1 = SubrsEscapeFuncs.length-1;
- key = SubrsEscapeFuncs[b1];
- }
- else
- key = SubrsFunctions[b0];
- continue;
- }
- }
- }
-
- /**
- * The function reads the subroutine and returns the number of the hint in it.
- * If a call to another subroutine is found the function calls recursively.
- * @param begin the start point of the subr
- * @param end the end point of the subr
- * @param LBias the bias of the Local Subrs
- * @param GBias the bias of the Global Subrs
- * @param LSubrsOffsets The Offsets array of the subroutines
- * @return The number of hints in the subroutine read.
- */
- protected int CalcHints(int begin,int end,int LBias,int GBias,int[] LSubrsOffsets)
- {
- // Goto begining of the subr
- seek(begin);
- while (getPosition() < end)
- {
- // Read the next command
- ReadCommand();
- int pos = getPosition();
- Object TopElement = null;
- if (arg_count>0)
- TopElement = args[arg_count-1];
- int NumOfArgs = arg_count;
- //Check the modification needed on the Argument Stack according to key;
- HandelStack();
- // a call to a Lsubr
- if (key=="callsubr")
- {
- if (NumOfArgs>0)
- {
- int Subr = ((Integer)TopElement).intValue() + LBias;
- CalcHints(LSubrsOffsets[Subr],LSubrsOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
- seek(pos);
- }
- }
- // a call to a Gsubr
- else if (key=="callgsubr")
- {
- if (NumOfArgs>0)
- {
- int Subr = ((Integer)TopElement).intValue() + GBias;
- CalcHints(gsubrOffsets[Subr],gsubrOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
- seek(pos);
- }
- }
- // A call to "stem"
- else if (key == "hstem" || key == "vstem" || key == "hstemhm" || key == "vstemhm")
- // Increment the NumOfHints by the number couples of of arguments
- NumOfHints += NumOfArgs/2;
- // A call to "mask"
- else if (key == "hintmask" || key == "cntrmask")
- {
- // Compute the size of the mask
- int SizeOfMask = NumOfHints/8;
- if (NumOfHints%8 != 0 || SizeOfMask == 0)
- SizeOfMask++;
- // Continue the pointer in SizeOfMask steps
- for (int i=0;i>> 8) & 0xff);
- NewIndex[Place++] = (byte) ((Count >>> 0) & 0xff);
- // Write the offsize field
- NewIndex[Place++] = Offsize;
- // Write the offset array according to the offsize
- for (int i=0;i>> 24) & 0xff);
- case 3:
- NewIndex[Place++] = (byte) ((Num >>> 16) & 0xff);
- case 2:
- NewIndex[Place++] = (byte) ((Num >>> 8) & 0xff);
- case 1:
- NewIndex[Place++] = (byte) ((Num >>> 0) & 0xff);
- }
- }
- // Write the new object array one by one
- for (int i=0;i=0)
- OutputList.addLast(new RangeItem(buf,fonts[Font].fdselectOffset,fonts[Font].FDSelectLength));
- // Else create a new one
- else
- CreateFDSelect(fdselectRef,fonts[Font].nglyphs);
-
- // Copy the Charset
- // Mark the beginning and copy entirly
- OutputList.addLast(new MarkerItem(charsetRef));
- OutputList.addLast(new RangeItem(buf,fonts[Font].charsetOffset,fonts[Font].CharsetLength));
-
- // Copy the FDArray
- // If an FDArray exists
- if (fonts[Font].fdarrayOffset>=0)
- {
- // Mark the beginning
- OutputList.addLast(new MarkerItem(fdarrayRef));
- // Build a new FDArray with its private dicts and their LSubrs
- Reconstruct(Font);
- }
- else
- // Else create a new one
- CreateFDArray(fdarrayRef,privateRef,Font);
-
- }
- // If the font is not CID
- else
- {
- // create FDSelect
- CreateFDSelect(fdselectRef,fonts[Font].nglyphs);
- // recreate a new charset
- CreateCharset(charsetRef,fonts[Font].nglyphs);
- // create a font dict index (fdarray)
- CreateFDArray(fdarrayRef,privateRef,Font);
- }
-
- // if a private dict exists insert its subsetted version
- if (fonts[Font].privateOffset>=0)
- {
- // Mark the beginning of the private dict
- IndexBaseItem PrivateBase = new IndexBaseItem();
- OutputList.addLast(PrivateBase);
- OutputList.addLast(new MarkerItem(privateRef));
-
- OffsetItem Subr = new DictOffsetItem();
- // Build and copy the new private dict
- CreateNonCIDPrivate(Font,Subr);
- // Copy the new LSubrs index
- CreateNonCIDSubrs(Font,PrivateBase,Subr);
- }
-
- // copy the charstring index
- OutputList.addLast(new MarkerItem(charstringsRef));
-
- // Add the subsetted charstring
- OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewCharStringsIndex),0,NewCharStringsIndex.length));
-
- // now create the new CFF font
- int[] currentOffset = new int[1];
- currentOffset[0] = 0;
- // Count and save the offset for each item
- Iterator listIter = OutputList.iterator();
- while ( listIter.hasNext() ) {
- Item item = (Item) listIter.next();
- item.increment(currentOffset);
- }
- // Compute the Xref for each of the offset items
- listIter = OutputList.iterator();
- while ( listIter.hasNext() ) {
- Item item = (Item) listIter.next();
- item.xref();
- }
-
- int size = currentOffset[0];
- byte[] b = new byte[size];
-
- // Emit all the items into the new byte array
- listIter = OutputList.iterator();
- while ( listIter.hasNext() ) {
- Item item = (Item) listIter.next();
- item.emit(b);
- }
- // Return the new stream
- return b;
- }
-
- /**
- * Function Copies the header from the original fileto the output list
- */
- protected void CopyHeader()
- {
- seek(0);
- int major = getCard8();
- int minor = getCard8();
- int hdrSize = getCard8();
- int offSize = getCard8();
- nextIndexOffset = hdrSize;
- OutputList.addLast(new RangeItem(buf,0,hdrSize));
- }
-
- /**
- * Function Build the header of an index
- * @param Count the count field of the index
- * @param Offsize the offsize field of the index
- * @param First the first offset of the index
- */
- protected void BuildIndexHeader(int Count,int Offsize,int First)
- {
- // Add the count field
- OutputList.addLast(new UInt16Item((char)Count)); // count
- // Add the offsize field
- OutputList.addLast(new UInt8Item((char)Offsize)); // offSize
- // Add the first offset according to the offsize
- switch(Offsize){
- case 1:
- OutputList.addLast(new UInt8Item((char)First)); // first offset
- break;
- case 2:
- OutputList.addLast(new UInt16Item((char)First)); // first offset
- break;
- case 3:
- OutputList.addLast(new UInt24Item((char)First)); // first offset
- break;
- case 4:
- OutputList.addLast(new UInt32Item((char)First)); // first offset
- break;
- default:
- break;
- }
- }
-
- /**
- * Function adds the keys into the TopDict
- * @param fdarrayRef OffsetItem for the FDArray
- * @param fdselectRef OffsetItem for the FDSelect
- * @param charsetRef OffsetItem for the CharSet
- * @param charstringsRef OffsetItem for the CharString
- */
- protected void CreateKeys(OffsetItem fdarrayRef,OffsetItem fdselectRef,OffsetItem charsetRef,OffsetItem charstringsRef)
- {
- // create an FDArray key
- OutputList.addLast(fdarrayRef);
- OutputList.addLast(new UInt8Item((char)12));
- OutputList.addLast(new UInt8Item((char)36));
- // create an FDSelect key
- OutputList.addLast(fdselectRef);
- OutputList.addLast(new UInt8Item((char)12));
- OutputList.addLast(new UInt8Item((char)37));
- // create an charset key
- OutputList.addLast(charsetRef);
- OutputList.addLast(new UInt8Item((char)15));
- // create a CharStrings key
- OutputList.addLast(charstringsRef);
- OutputList.addLast(new UInt8Item((char)17));
- }
-
- /**
- * Function takes the original string item and adds the new strings
- * to accomodate the CID rules
- * @param Font the font
- */
- protected void CreateNewStringIndex(int Font)
- {
- String fdFontName = fonts[Font].name+"-OneRange";
- if (fdFontName.length() > 127)
- fdFontName = fdFontName.substring(0,127);
- String extraStrings = "Adobe"+"Identity"+fdFontName;
-
- int origStringsLen = stringOffsets[stringOffsets.length-1]
- - stringOffsets[0];
- int stringsBaseOffset = stringOffsets[0]-1;
-
- byte stringsIndexOffSize;
- if (origStringsLen+extraStrings.length() <= 0xff) stringsIndexOffSize = 1;
- else if (origStringsLen+extraStrings.length() <= 0xffff) stringsIndexOffSize = 2;
- else if (origStringsLen+extraStrings.length() <= 0xffffff) stringsIndexOffSize = 3;
- else stringsIndexOffSize = 4;
-
- OutputList.addLast(new UInt16Item((char)((stringOffsets.length-1)+3))); // count
- OutputList.addLast(new UInt8Item((char)stringsIndexOffSize)); // offSize
- for (int i=0; i= 0)
- {
- OutputList.addLast(new SubrMarkerItem(fdSubrs[i],fdPrivateBase[i]));
- OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewLSubrsIndex[i]),0,NewLSubrsIndex[i].length));
- }
- }
- }
-
- /**
- * Calculates how many byte it took to write the offset for the subrs in a specific
- * private dict.
- * @param Offset The Offset for the private dict
- * @param Size The size of the private dict
- * @return The size of the offset of the subrs in the private dict
- */
- int CalcSubrOffsetSize(int Offset,int Size)
- {
- // Set the size to 0
- int OffsetSize = 0;
- // Go to the beginning of the private dict
- seek(Offset);
- // Go until the end of the private dict
- while (getPosition() < Offset+Size)
- {
- int p1 = getPosition();
- getDictItem();
- int p2 = getPosition();
- // When reached to the subrs offset
- if (key=="Subrs") {
- // The Offsize (minus the subrs key)
- OffsetSize = p2-p1-1;
- }
- // All other keys are ignored
- }
- // return the size
- return OffsetSize;
- }
-
- /**
- * Function computes the size of an index
- * @param indexOffset The offset for the computed index
- * @return The size of the index
- */
- protected int countEntireIndexRange(int indexOffset)
- {
- // Go to the beginning of the index
- seek(indexOffset);
- // Read the count field
- int count = getCard16();
- // If count==0 -> size=2
- if (count==0)
- return 2;
- else
- {
- // Read the offsize field
- int indexOffSize = getCard8();
- // Go to the last element of the offset array
- seek(indexOffset+2+1+count*indexOffSize);
- // The size of the object array is the value of the last element-1
- int size = getOffset(indexOffSize)-1;
- // Return the size of the entire index
- return 2+1+(count+1)*indexOffSize+size;
- }
- }
-
- /**
- * The function creates a private dict for a font that was not CID
- * All the keys are copied as is except for the subrs key
- * @param Font the font
- * @param Subr The OffsetItem for the subrs of the private
- */
- void CreateNonCIDPrivate(int Font,OffsetItem Subr)
- {
- // Go to the beginning of the private dict and read untill the end
- seek(fonts[Font].privateOffset);
- while (getPosition() < fonts[Font].privateOffset+fonts[Font].privateLength)
- {
- int p1 = getPosition();
- getDictItem();
- int p2 = getPosition();
- // If the dictItem is the "Subrs" then,
- // use marker for offset and write operator number
- if (key=="Subrs") {
- OutputList.addLast(Subr);
- OutputList.addLast(new UInt8Item((char)19)); // Subrs
- }
- // Else copy the entire range
- else
- OutputList.addLast(new RangeItem(buf,p1,p2-p1));
- }
- }
-
- /**
- * the function marks the beginning of the subrs index and adds the subsetted subrs
- * index to the output list.
- * @param Font the font
- * @param PrivateBase IndexBaseItem for the private that's referencing to the subrs
- * @param Subrs OffsetItem for the subrs
- * @throws IOException
- */
- void CreateNonCIDSubrs(int Font,IndexBaseItem PrivateBase,OffsetItem Subrs)throws IOException
- {
- // Mark the beginning of the Subrs index
- OutputList.addLast(new SubrMarkerItem(Subrs,PrivateBase));
- // Put the subsetted new subrs index
- OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewSubrsIndexNonCID),0,NewSubrsIndexNonCID.length));
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/CJKFont.java pdftk-2.01/java/com/lowagie/text/pdf/CJKFont.java
--- pdftk-1.45/java/com/lowagie/text/pdf/CJKFont.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/CJKFont.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,632 +0,0 @@
-/*
- * $Id: CJKFont.java,v 1.29 2002/07/09 11:28:22 blowagie Exp $
- * $Name: $
- *
- * Copyright 2000, 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.DocumentException;
-import java.io.*;
-import java.util.HashMap;
-import java.util.Properties;
-import java.util.Hashtable;
-import java.util.StringTokenizer;
-import java.util.Enumeration;
-
-/**
- * Creates a CJK font compatible with the fonts in the Adobe Asian font Pack.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-
-class CJKFont extends BaseFont {
- /** The encoding used in the PDF document for CJK fonts
- */
- static final String CJK_ENCODING = "UnicodeBigUnmarked";
- private static final int FIRST = 0;
- private static final int BRACKET = 1;
- private static final int SERIAL = 2;
- private static final int V1Y = 880;
-
- static Properties cjkFonts = new Properties();
- static Properties cjkEncodings = new Properties();
- static Hashtable allCMaps = new Hashtable();
- static Hashtable allFonts = new Hashtable();
- private static boolean propertiesLoaded = false;
-
- /** The font name */
- private String fontName;
- /** The style modifier */
- private String style = "";
- /** The CMap name associated with this font */
- private String CMap;
-
- private boolean cidDirect = false;
-
- private char[] translationMap;
- private IntHashtable vMetrics;
- private IntHashtable hMetrics;
- private HashMap fontDesc;
- private boolean vertical = false;
-
- private static void loadProperties() {
- if (propertiesLoaded)
- return;
- synchronized (allFonts) {
- if (propertiesLoaded)
- return;
- try {
- InputStream is = getResourceStream(RESOURCE_PATH + "cjkfonts.properties");
- cjkFonts.load(is);
- is.close();
- is = getResourceStream(RESOURCE_PATH + "cjkencodings.properties");
- cjkEncodings.load(is);
- is.close();
- }
- catch (Exception e) {
- cjkFonts = new Properties();
- cjkEncodings = new Properties();
- }
- propertiesLoaded = true;
- }
- }
-
- /** Creates a CJK font.
- * @param fontName the name of the font
- * @param enc the encoding of the font
- * @param emb always false
. CJK font and not embedded
- * @throws DocumentException on error
- * @throws IOException on error
- */
- CJKFont(String fontName, String enc, boolean emb) throws DocumentException, IOException {
- loadProperties();
- fontType = FONT_TYPE_CJK;
- String nameBase = getBaseName(fontName);
- if (!isCJKFont(nameBase, enc))
- throw new DocumentException("Font '" + fontName + "' with '" + enc + "' encoding is not a CJK font.");
- if (nameBase.length() < fontName.length()) {
- style = fontName.substring(nameBase.length());
- fontName = nameBase;
- }
- this.fontName = fontName;
- encoding = CJK_ENCODING;
- vertical = enc.endsWith("V");
- CMap = enc;
- if (enc.startsWith("Identity-")) {
- cidDirect = true;
- String s = cjkFonts.getProperty(fontName);
- s = s.substring(0, s.indexOf('_'));
- char c[] = (char[])allCMaps.get(s);
- if (c == null) {
- c = readCMap(s);
- if (c == null)
- throw new DocumentException("The cmap " + s + " does not exist as a resource.");
- c[CID_NEWLINE] = '\n';
- allCMaps.put(s, c);
- }
- translationMap = c;
- }
- else {
- char c[] = (char[])allCMaps.get(enc);
- if (c == null) {
- String s = cjkEncodings.getProperty(enc);
- if (s == null)
- throw new DocumentException("The resource cjkencodings.properties does not contain the encoding " + enc);
- StringTokenizer tk = new StringTokenizer(s);
- String nt = tk.nextToken();
- c = (char[])allCMaps.get(nt);
- if (c == null) {
- c = readCMap(nt);
- allCMaps.put(nt, c);
- }
- if (tk.hasMoreTokens()) {
- String nt2 = tk.nextToken();
- char m2[] = readCMap(nt2);
- for (int k = 0; k < 0x10000; ++k) {
- if (m2[k] == 0)
- m2[k] = c[k];
- }
- allCMaps.put(enc, m2);
- c = m2;
- }
- }
- translationMap = c;
- }
- fontDesc = (HashMap)allFonts.get(fontName);
- if (fontDesc == null) {
- fontDesc = readFontProperties(fontName);
- allFonts.put(fontName, fontDesc);
- }
- hMetrics = (IntHashtable)fontDesc.get("W");
- vMetrics = (IntHashtable)fontDesc.get("W2");
- }
-
- /** Checks if its a valid CJK font.
- * @param fontName the font name
- * @param enc the encoding
- * @return true
if it is CJK font
- */
- public static boolean isCJKFont(String fontName, String enc) {
- loadProperties();
- String encodings = cjkFonts.getProperty(fontName);
- return (encodings != null && (enc.equals("Identity-H") || enc.equals("Identity-V") || encodings.indexOf("_" + enc + "_") >= 0));
- }
-
- public int getWidth(String text) {
- int total = 0;
- for (int k = 0; k < text.length(); ++k) {
- int c = text.charAt(k);
- if (!cidDirect)
- c = translationMap[c];
- int v;
- if (vertical)
- v = vMetrics.get(c);
- else
- v = hMetrics.get(c);
- if (v > 0)
- total += v;
- else
- total += 1000;
- }
- return total;
- }
-
- int getRawWidth(int c, String name) {
- return 0;
- }
-
- public int getKerning(char char1, char char2) {
- return 0;
- }
-
- private PdfDictionary getFontDescriptor() {
- PdfDictionary dic = new PdfDictionary(PdfName.FONTDESCRIPTOR);
- dic.put(PdfName.ASCENT, new PdfLiteral((String)fontDesc.get("Ascent")));
- dic.put(PdfName.CAPHEIGHT, new PdfLiteral((String)fontDesc.get("CapHeight")));
- dic.put(PdfName.DESCENT, new PdfLiteral((String)fontDesc.get("Descent")));
- dic.put(PdfName.FLAGS, new PdfLiteral((String)fontDesc.get("Flags")));
- dic.put(PdfName.FONTBBOX, new PdfLiteral((String)fontDesc.get("FontBBox")));
- dic.put(PdfName.FONTNAME, new PdfName(fontName + style));
- dic.put(PdfName.ITALICANGLE, new PdfLiteral((String)fontDesc.get("ItalicAngle")));
- dic.put(PdfName.STEMV, new PdfLiteral((String)fontDesc.get("StemV")));
- PdfDictionary pdic = new PdfDictionary();
- pdic.put(PdfName.PANOSE, new PdfString((String)fontDesc.get("Panose"), null));
- dic.put(PdfName.STYLE, pdic);
- return dic;
- }
-
- private PdfDictionary getCIDFont(PdfIndirectReference fontDescriptor, IntHashtable cjkTag) {
- PdfDictionary dic = new PdfDictionary(PdfName.FONT);
- dic.put(PdfName.SUBTYPE, PdfName.CIDFONTTYPE0);
- dic.put(PdfName.BASEFONT, new PdfName(fontName + style));
- dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
- int keys[] = cjkTag.toOrderedKeys();
- String w = convertToHCIDMetrics(keys, hMetrics);
- if (w != null)
- dic.put(PdfName.W, new PdfLiteral(w));
- if (vertical) {
- w = convertToVCIDMetrics(keys, vMetrics, hMetrics);;
- if (w != null)
- dic.put(PdfName.W2, new PdfLiteral(w));
- }
- else
- dic.put(PdfName.DW, new PdfNumber(1000));
- PdfDictionary cdic = new PdfDictionary();
- cdic.put(PdfName.REGISTRY, new PdfString((String)fontDesc.get("Registry"), null));
- cdic.put(PdfName.ORDERING, new PdfString((String)fontDesc.get("Ordering"), null));
- cdic.put(PdfName.SUPPLEMENT, new PdfLiteral((String)fontDesc.get("Supplement")));
- dic.put(PdfName.CIDSYSTEMINFO, cdic);
- return dic;
- }
-
- private PdfDictionary getFontBaseType(PdfIndirectReference CIDFont) {
- PdfDictionary dic = new PdfDictionary(PdfName.FONT);
- dic.put(PdfName.SUBTYPE, PdfName.TYPE0);
- String name = fontName;
- if (style.length() > 0)
- name += "-" + style.substring(1);
- name += "-" + CMap;
- dic.put(PdfName.BASEFONT, new PdfName(name));
- dic.put(PdfName.ENCODING, new PdfName(CMap));
- dic.put(PdfName.DESCENDANTFONTS, new PdfArray(CIDFont));
- return dic;
- }
-
- void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
- IntHashtable cjkTag = (IntHashtable)params[0];
- PdfIndirectReference ind_font = null;
- PdfObject pobj = null;
- PdfIndirectObject obj = null;
- pobj = getFontDescriptor();
- if (pobj != null){
- obj = writer.addToBody(pobj);
- ind_font = obj.getIndirectReference();
- }
- pobj = getCIDFont(ind_font, cjkTag);
- if (pobj != null){
- obj = writer.addToBody(pobj);
- ind_font = obj.getIndirectReference();
- }
- pobj = getFontBaseType(ind_font);
- writer.addToBody(pobj, ref);
- }
-
- private float getDescNumber(String name) {
- return Integer.parseInt((String)fontDesc.get(name));
- }
-
- private float getBBox(int idx) {
- String s = (String)fontDesc.get("FontBBox");
- StringTokenizer tk = new StringTokenizer(s, " []\r\n\t\f");
- String ret = tk.nextToken();
- for (int k = 0; k < idx; ++k)
- ret = tk.nextToken();
- return Integer.parseInt(ret);
- }
-
- /** Gets the font parameter identified by key
. Valid values
- * for key
are ASCENT
, CAPHEIGHT
, DESCENT
- * and ITALICANGLE
.
- * @param key the parameter to be extracted
- * @param fontSize the font size in points
- * @return the parameter in points
- */
- public float getFontDescriptor(int key, float fontSize) {
- switch (key) {
- case AWT_ASCENT:
- case ASCENT:
- return getDescNumber("Ascent") * fontSize / 1000;
- case CAPHEIGHT:
- return getDescNumber("CapHeight") * fontSize / 1000;
- case AWT_DESCENT:
- case DESCENT:
- return getDescNumber("Descent") * fontSize / 1000;
- case ITALICANGLE:
- return getDescNumber("ItalicAngle");
- case BBOXLLX:
- return fontSize * getBBox(0) / 1000;
- case BBOXLLY:
- return fontSize * getBBox(1) / 1000;
- case BBOXURX:
- return fontSize * getBBox(2) / 1000;
- case BBOXURY:
- return fontSize * getBBox(3) / 1000;
- case AWT_LEADING:
- return 0;
- case AWT_MAXADVANCE:
- return fontSize * (getBBox(2) - getBBox(0)) / 1000;
- }
- return 0;
- }
-
- public String getPostscriptFontName() {
- return fontName;
- }
-
- /** Gets the full name of the font. If it is a True Type font
- * each array element will have {Platform ID, Platform Encoding ID,
- * Language ID, font name}. The interpretation of this values can be
- * found in the Open Type specification, chapter 2, in the 'name' table.
- * For the other fonts the array has a single element with {"", "", "",
- * font name}.
- * @return the full name of the font
- */
- public String[][] getFullFontName() {
- return new String[][]{{"", "", "", fontName}};
- }
-
- /** Gets the family name of the font. If it is a True Type font
- * each array element will have {Platform ID, Platform Encoding ID,
- * Language ID, font name}. The interpretation of this values can be
- * found in the Open Type specification, chapter 2, in the 'name' table.
- * For the other fonts the array has a single element with {"", "", "",
- * font name}.
- * @return the family name of the font
- */
- public String[][] getFamilyFontName() {
- return getFullFontName();
- }
-
- static char[] readCMap(String name) {
- try {
- name = name + ".cmap";
- InputStream is = getResourceStream(RESOURCE_PATH + name);
- char c[] = new char[0x10000];
- for (int k = 0; k < 0x10000; ++k)
- c[k] = (char)((is.read() << 8) + is.read());
- return c;
- }
- catch (Exception e) {
- // empty on purpose
- }
- return null;
- }
-
- static IntHashtable createMetric(String s) {
- IntHashtable h = new IntHashtable();
- StringTokenizer tk = new StringTokenizer(s);
- while (tk.hasMoreTokens()) {
- int n1 = Integer.parseInt(tk.nextToken());
- h.put(n1, Integer.parseInt(tk.nextToken()));
- }
- return h;
- }
-
- static String convertToHCIDMetrics(int keys[], IntHashtable h) {
- if (keys.length == 0)
- return null;
- int lastCid = 0;
- int lastValue = 0;
- int start;
- for (start = 0; start < keys.length; ++start) {
- lastCid = keys[start];
- lastValue = h.get(lastCid);
- if (lastValue != 0) {
- ++start;
- break;
- }
- }
- if (lastValue == 0)
- return null;
- StringBuffer buf = new StringBuffer();
- buf.append('[');
- buf.append(lastCid);
- int state = FIRST;
- for (int k = start; k < keys.length; ++k) {
- int cid = keys[k];
- int value = h.get(cid);
- if (value == 0)
- continue;
- switch (state) {
- case FIRST: {
- if (cid == lastCid + 1 && value == lastValue) {
- state = SERIAL;
- }
- else if (cid == lastCid + 1) {
- state = BRACKET;
- buf.append('[').append(lastValue);
- }
- else {
- buf.append('[').append(lastValue).append(']').append(cid);
- }
- break;
- }
- case BRACKET: {
- if (cid == lastCid + 1 && value == lastValue) {
- state = SERIAL;
- buf.append(']').append(lastCid);
- }
- else if (cid == lastCid + 1) {
- buf.append(' ').append(lastValue);
- }
- else {
- state = FIRST;
- buf.append(' ').append(lastValue).append(']').append(cid);
- }
- break;
- }
- case SERIAL: {
- if (cid != lastCid + 1 || value != lastValue) {
- buf.append(' ').append(lastCid).append(' ').append(lastValue).append(' ').append(cid);
- state = FIRST;
- }
- break;
- }
- }
- lastValue = value;
- lastCid = cid;
- }
- switch (state) {
- case FIRST: {
- buf.append('[').append(lastValue).append("]]");
- break;
- }
- case BRACKET: {
- buf.append(' ').append(lastValue).append("]]");
- break;
- }
- case SERIAL: {
- buf.append(' ').append(lastCid).append(' ').append(lastValue).append(']');
- break;
- }
- }
- return buf.toString();
- }
-
- static String convertToVCIDMetrics(int keys[], IntHashtable v, IntHashtable h) {
- if (keys.length == 0)
- return null;
- int lastCid = 0;
- int lastValue = 0;
- int lastHValue = 0;
- int start;
- for (start = 0; start < keys.length; ++start) {
- lastCid = keys[start];
- lastValue = v.get(lastCid);
- if (lastValue != 0) {
- ++start;
- break;
- }
- else
- lastHValue = h.get(lastCid);
- }
- if (lastValue == 0)
- return null;
- if (lastHValue == 0)
- lastHValue = 1000;
- StringBuffer buf = new StringBuffer();
- buf.append('[');
- buf.append(lastCid);
- int state = FIRST;
- for (int k = start; k < keys.length; ++k) {
- int cid = keys[k];
- int value = v.get(cid);
- if (value == 0)
- continue;
- int hValue = h.get(lastCid);
- if (hValue == 0)
- hValue = 1000;
- switch (state) {
- case FIRST: {
- if (cid == lastCid + 1 && value == lastValue && hValue == lastHValue) {
- state = SERIAL;
- }
- else {
- buf.append(' ').append(lastCid).append(' ').append(-lastValue).append(' ').append(lastHValue / 2).append(' ').append(V1Y).append(' ').append(cid);
- }
- break;
- }
- case SERIAL: {
- if (cid != lastCid + 1 || value != lastValue || hValue != lastHValue) {
- buf.append(' ').append(lastCid).append(' ').append(-lastValue).append(' ').append(lastHValue / 2).append(' ').append(V1Y).append(' ').append(cid);
- state = FIRST;
- }
- break;
- }
- }
- lastValue = value;
- lastCid = cid;
- lastHValue = hValue;
- }
- buf.append(' ').append(lastCid).append(' ').append(-lastValue).append(' ').append(lastHValue / 2).append(' ').append(V1Y).append(" ]");
- return buf.toString();
- }
-
- static HashMap readFontProperties(String name) {
- try {
- name += ".properties";
- InputStream is = getResourceStream(RESOURCE_PATH + name);
- Properties p = new Properties();
- p.load(is);
- is.close();
- IntHashtable W = createMetric(p.getProperty("W"));
- p.remove("W");
- IntHashtable W2 = createMetric(p.getProperty("W2"));
- p.remove("W2");
- HashMap map = new HashMap();
- for (Enumeration e = p.keys(); e.hasMoreElements();) {
- Object obj = e.nextElement();
- map.put(obj, p.getProperty((String)obj));
- }
- map.put("W", W);
- map.put("W2", W2);
- return map;
- }
- catch (Exception e) {
- // empty on purpose
- }
- return null;
- }
-
- public char getUnicodeEquivalent(char c) {
- if (cidDirect)
- return translationMap[c];
- return c;
- }
-
- public char getCidCode(char c) {
- if (cidDirect)
- return c;
- return translationMap[c];
- }
-
- /** Checks if the font has any kerning pairs.
- * @return always false
- */
- public boolean hasKernPairs() {
- return false;
- }
-
- /**
- * Checks if a character exists in this font.
- * @param c the character to check
- * @return true
if the character has a glyph,
- * false
otherwise
- */
- public boolean charExists(char c) {
- return translationMap[c] != 0;
- }
-
- /**
- * Sets the character advance.
- * @param c the character
- * @param advance the character advance normalized to 1000 units
- * @return true
if the advance was set,
- * false
otherwise. Will always return false
- */
- public boolean setCharAdvance(char c, int advance) {
- return false;
- }
-
- /**
- * Sets the font name that will appear in the pdf font dictionary.
- * Use with care as it can easily make a font unreadable if not embedded.
- * @param name the new font name
- */
- public void setPostscriptFontName(String name) {
- fontName = name;
- }
-
- public boolean setKerning(char char1, char char2, int kern) {
- return false;
- }
-
- public int[] getCharBBox(char c) {
- return null;
- }
-
- protected int[] getRawCharBBox(int c, String name) {
- return null;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/CMYKColor.java pdftk-2.01/java/com/lowagie/text/pdf/CMYKColor.java
--- pdftk-1.45/java/com/lowagie/text/pdf/CMYKColor.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/CMYKColor.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,124 +0,0 @@
-/*
- * $Id: CMYKColor.java,v 1.43 2005/05/02 11:12:44 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class CMYKColor extends ExtendedColor {
-
- float cyan;
- float magenta;
- float yellow;
- float black;
-
- /**
- * Constructs a CMYK Color beased on 4 colorvalues (values are integers from 0 to 255).
- * @param intCyan
- * @param intMagenta
- * @param intYellow
- * @param intBlack
- */
- public CMYKColor(int intCyan, int intMagenta, int intYellow, int intBlack) {
- this((float)intCyan / 255f, (float)intMagenta / 255f, (float)intYellow / 255f, (float)intBlack / 255f);
- }
-
- /**
- * Construct a CMYK Color.
- * @param floatCyan
- * @param floatMagenta
- * @param floatYellow
- * @param floatBlack
- */
- public CMYKColor(float floatCyan, float floatMagenta, float floatYellow, float floatBlack) {
- super(TYPE_CMYK, 1f - floatCyan - floatBlack, 1f - floatMagenta - floatBlack, 1f - floatYellow - floatBlack);
- cyan = normalize(floatCyan);
- magenta = normalize(floatMagenta);
- yellow = normalize(floatYellow);
- black = normalize(floatBlack);
- }
-
- /**
- * @return the cyan value
- */
- public float getCyan() {
- return cyan;
- }
-
- /**
- * @return the magenta value
- */
- public float getMagenta() {
- return magenta;
- }
-
- /**
- * @return the yellow value
- */
- public float getYellow() {
- return yellow;
- }
-
- /**
- * @return the black value
- */
- public float getBlack() {
- return black;
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/ColorDetails.java pdftk-2.01/java/com/lowagie/text/pdf/ColorDetails.java
--- pdftk-1.45/java/com/lowagie/text/pdf/ColorDetails.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/ColorDetails.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,107 +0,0 @@
-/*
- * $Id: ColorDetails.java,v 1.11 2002/06/20 13:06:47 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-/** Each spotcolor in the document will have an instance of this class
- *
- * @author Phillip Pan (phillip@formstar.com)
- */
-class ColorDetails {
-
- /** The indirect reference to this color
- */
- PdfIndirectReference indirectReference;
- /** The color name that appears in the document body stream
- */
- PdfName colorName;
- /** The color
- */
- PdfSpotColor spotcolor;
-
- /** Each spot color used in a document has an instance of this class.
- * @param colorName the color name
- * @param indirectReference the indirect reference to the font
- * @param scolor the PDfSpotColor
- */
- ColorDetails(PdfName colorName, PdfIndirectReference indirectReference, PdfSpotColor scolor) {
- this.colorName = colorName;
- this.indirectReference = indirectReference;
- this.spotcolor = scolor;
- }
-
- /** Gets the indirect reference to this color.
- * @return the indirect reference to this color
- */
- PdfIndirectReference getIndirectReference() {
- return indirectReference;
- }
-
- /** Gets the color name as it appears in the document body.
- * @return the color name
- */
- PdfName getColorName() {
- return colorName;
- }
-
- /** Gets the SpotColor
object.
- * @return the PdfSpotColor
- */
- PdfObject getSpotColor(PdfWriter writer) throws IOException {
- return spotcolor.getSpotObject(writer);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/ColumnText.java pdftk-2.01/java/com/lowagie/text/pdf/ColumnText.java
--- pdftk-1.45/java/com/lowagie/text/pdf/ColumnText.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/ColumnText.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,1445 +0,0 @@
-/*
- * $Id: ColumnText.java,v 1.58 2005/01/11 14:14:58 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.Stack;
-import java.util.Iterator;
-import com.lowagie.text.Phrase;
-import com.lowagie.text.Chunk;
-import com.lowagie.text.Paragraph;
-// import com.lowagie.text.Graphic; ssteward: dropped in 1.44
-import com.lowagie.text.ListItem;
-import com.lowagie.text.Element;
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.ExceptionConverter;
-// import com.lowagie.text.Image; ssteward: dropped in 1.44
-
-/**
- * Formats text in a columnwise form. The text is bound
- * on the left and on the right by a sequence of lines. This allows the column
- * to have any shape, not only rectangular.
- *
- * Several parameters can be set like the first paragraph line indent and
- * extra space between paragraphs.
- *
- * A call to the method go
will return one of the following
- * situations: the column ended or the text ended.
- *
- * I the column ended, a new column definition can be loaded with the method
- * setColumns
and the method go
can be called again.
- *
- * If the text ended, more text can be loaded with addText
- * and the method go
can be called again.
- * The only limitation is that one or more complete paragraphs must be loaded
- * each time.
- *
- * Full bidirectional reordering is supported. If the run direction is
- * PdfWriter.RUN_DIRECTION_RTL
the meaning of the horizontal
- * alignments and margins is mirrored.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-
-public class ColumnText {
- /** Eliminate the arabic vowels */
- public static final int AR_NOVOWEL = ArabicLigaturizer.ar_novowel;
- /** Compose the tashkeel in the ligatures. */
- public static final int AR_COMPOSEDTASHKEEL = ArabicLigaturizer.ar_composedtashkeel;
- /** Do some extra double ligatures. */
- public static final int AR_LIG = ArabicLigaturizer.ar_lig;
- /**
- * Digit shaping option: Replace European digits (U+0030...U+0039) by Arabic-Indic digits.
- */
- public static final int DIGITS_EN2AN = ArabicLigaturizer.DIGITS_EN2AN;
-
- /**
- * Digit shaping option: Replace Arabic-Indic digits by European digits (U+0030...U+0039).
- */
- public static final int DIGITS_AN2EN = ArabicLigaturizer.DIGITS_AN2EN;
-
- /**
- * Digit shaping option:
- * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
- * if the most recent strongly directional character
- * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
- * The initial state at the start of the text is assumed to be not an Arabic,
- * letter, so European digits at the start of the text will not change.
- * Compare to DIGITS_ALEN2AN_INIT_AL.
- */
- public static final int DIGITS_EN2AN_INIT_LR = ArabicLigaturizer.DIGITS_EN2AN_INIT_LR;
-
- /**
- * Digit shaping option:
- * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
- * if the most recent strongly directional character
- * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
- * The initial state at the start of the text is assumed to be an Arabic,
- * letter, so European digits at the start of the text will change.
- * Compare to DIGITS_ALEN2AN_INT_LR.
- */
- public static final int DIGITS_EN2AN_INIT_AL = ArabicLigaturizer.DIGITS_EN2AN_INIT_AL;
-
- /**
- * Digit type option: Use Arabic-Indic digits (U+0660...U+0669).
- */
- public static final int DIGIT_TYPE_AN = ArabicLigaturizer.DIGIT_TYPE_AN;
-
- /**
- * Digit type option: Use Eastern (Extended) Arabic-Indic digits (U+06f0...U+06f9).
- */
- public static final int DIGIT_TYPE_AN_EXTENDED = ArabicLigaturizer.DIGIT_TYPE_AN_EXTENDED;
-
- protected int runDirection = PdfWriter.RUN_DIRECTION_DEFAULT;
-
- /** the space char ratio */
- public static final float GLOBAL_SPACE_CHAR_RATIO = 0;
-
- /** Signals that there is no more text available. */
- public static final int NO_MORE_TEXT = 1;
-
- /** Signals that there is no more column. */
- public static final int NO_MORE_COLUMN = 2;
-
- /** The column is valid. */
- protected static final int LINE_STATUS_OK = 0;
-
- /** The line is out the column limits. */
- protected static final int LINE_STATUS_OFFLIMITS = 1;
-
- /** The line cannot fit this column position. */
- protected static final int LINE_STATUS_NOLINE = 2;
-
- /** Upper bound of the column. */
- protected float maxY;
-
- /** Lower bound of the column. */
- protected float minY;
-
- protected float leftX;
-
- protected float rightX;
-
- /** The column alignment. Default is left alignment. */
- protected int alignment = Element.ALIGN_LEFT;
-
- /** The left column bound. */
- protected ArrayList leftWall;
-
- /** The right column bound. */
- protected ArrayList rightWall;
-
- /** The chunks that form the text. */
-// protected ArrayList chunks = new ArrayList();
- protected BidiLine bidiLine;
-
- /** The current y line location. Text will be written at this line minus the leading. */
- protected float yLine;
-
- /** The leading for the current line. */
- protected float currentLeading = 16;
-
- /** The fixed text leading. */
- protected float fixedLeading = 16;
-
- /** The text leading that is multiplied by the biggest font size in the line. */
- protected float multipliedLeading = 0;
-
- /** The PdfContent
where the text will be written to. */
- protected PdfContentByte canvas;
-
- /** The line status when trying to fit a line to a column. */
- protected int lineStatus;
-
- /** The first paragraph line indent. */
- protected float indent = 0;
-
- /** The following paragraph lines indent. */
- protected float followingIndent = 0;
-
- /** The right paragraph lines indent. */
- protected float rightIndent = 0;
-
- /** The extra space between paragraphs. */
- protected float extraParagraphSpace = 0;
-
- /** The width of the line when the column is defined as a simple rectangle. */
- protected float rectangularWidth = -1;
-
- protected boolean rectangularMode = false;
- /** Holds value of property spaceCharRatio. */
- private float spaceCharRatio = GLOBAL_SPACE_CHAR_RATIO;
-
- private boolean lastWasNewline = true;
-
- /** Holds value of property linesWritten. */
- private int linesWritten;
-
- private float firstLineY;
- private boolean firstLineYDone = false;
-
- /** Holds value of property arabicOptions. */
- private int arabicOptions = 0;
-
- protected float descender;
-
- protected boolean composite = false;
-
- protected ColumnText compositeColumn;
-
- protected LinkedList compositeElements;
-
- protected int listIdx = 0;
-
- private boolean splittedRow;
-
- protected Phrase waitPhrase;
-
- /** if true, first line height is adjusted so that the max ascender touches the top */
- private boolean useAscender = false;
-
- /**
- * Creates a ColumnText
.
- * @param canvas the place where the text will be written to. Can
- * be a template.
- */
- public ColumnText(PdfContentByte canvas) {
- this.canvas = canvas;
- }
-
- /** Creates an independent duplicated of the instance org
.
- * @param org the original ColumnText
- * @return the duplicated
- */
- public static ColumnText duplicate(ColumnText org) {
- ColumnText ct = new ColumnText(null);
- ct.setACopy(org);
- return ct;
- }
-
- /** Makes this instance an independent copy of org
.
- * @param org the original ColumnText
- * @return itself
- */
- public ColumnText setACopy(ColumnText org) {
- setSimpleVars(org);
- if (org.bidiLine != null)
- bidiLine = new BidiLine(org.bidiLine);
- return this;
- }
-
- protected void setSimpleVars(ColumnText org) {
- maxY = org.maxY;
- minY = org.minY;
- alignment = org.alignment;
- leftWall = null;
- if (org.leftWall != null)
- leftWall = new ArrayList(org.leftWall);
- rightWall = null;
- if (org.rightWall != null)
- rightWall = new ArrayList(org.rightWall);
- yLine = org.yLine;
- currentLeading = org.currentLeading;
- fixedLeading = org.fixedLeading;
- multipliedLeading = org.multipliedLeading;
- canvas = org.canvas;
- lineStatus = org.lineStatus;
- indent = org.indent;
- followingIndent = org.followingIndent;
- rightIndent = org.rightIndent;
- extraParagraphSpace = org.extraParagraphSpace;
- rectangularWidth = org.rectangularWidth;
- rectangularMode = org.rectangularMode;
- spaceCharRatio = org.spaceCharRatio;
- lastWasNewline = org.lastWasNewline;
- linesWritten = org.linesWritten;
- arabicOptions = org.arabicOptions;
- runDirection = org.runDirection;
- descender = org.descender;
- composite = org.composite;
- splittedRow = org.splittedRow;
- if (org.composite) {
- compositeElements = new LinkedList(org.compositeElements);
- /* ssteward: dropped in 1.44
- if (splittedRow) {
- PdfPTable table = (PdfPTable)compositeElements.getFirst();
- compositeElements.set(0, new PdfPTable(table));
- }
- */
- if (org.compositeColumn != null)
- compositeColumn = duplicate(org.compositeColumn);
- }
- listIdx = org.listIdx;
- firstLineY = org.firstLineY;
- leftX = org.leftX;
- rightX = org.rightX;
- firstLineYDone = org.firstLineYDone;
- waitPhrase = org.waitPhrase;
- useAscender = org.useAscender;
- }
-
- private void addWaitingPhrase() {
- if (bidiLine == null && waitPhrase != null) {
- bidiLine = new BidiLine();
- for (Iterator j = waitPhrase.getChunks().iterator(); j.hasNext();) {
- bidiLine.addChunk(new PdfChunk((Chunk)j.next(), null));
- }
- waitPhrase = null;
- }
- }
-
- /**
- * Adds a Phrase
to the current text array.
- * Will not have any effect if addElement() was called before.
- * @param phrase the text
- */
- public void addText(Phrase phrase) {
- if (phrase == null || composite)
- return;
- addWaitingPhrase();
- if (bidiLine == null) {
- waitPhrase = phrase;
- return;
- }
- for (Iterator j = phrase.getChunks().iterator(); j.hasNext();) {
- bidiLine.addChunk(new PdfChunk((Chunk)j.next(), null));
- }
- }
-
- /**
- * Replaces the current text array with this Phrase
.
- * Anything added previously with addElement() is lost.
- * @param phrase the text
- */
- public void setText(Phrase phrase) {
- bidiLine = null;
- composite = false;
- compositeColumn = null;
- compositeElements = null;
- listIdx = 0;
- splittedRow = false;
- waitPhrase = phrase;
- }
-
- /**
- * Adds a Chunk
to the current text array.
- * Will not have any effect if addElement() was called before.
- * @param chunk the text
- */
- public void addText(Chunk chunk) {
- if (chunk == null || composite)
- return;
- addText(new Phrase(chunk));
- }
-
- /**
- * Adds an element. Elements supported are Paragraph
,
- * List
, PdfPTable
, Image
and
- * Graphic
.
- *
- * It removes all the text placed with addText()
.
- * @param element the Element
- */
- public void addElement(Element element) {
- if (element == null)
- return;
- /* ssteward: dropped in 1.44
- if (element instanceof Image) {
- Image img = (Image)element;
- PdfPTable t = new PdfPTable(1);
- float w = img.getWidthPercentage();
- if (w == 0) {
- t.setTotalWidth(img.scaledWidth());
- t.setLockedWidth(true);
- }
- else
- t.setWidthPercentage(w);
- t.setSpacingAfter(img.spacingAfter());
- t.setSpacingBefore(img.spacingBefore());
- switch (img.alignment()) {
- case Image.LEFT:
- t.setHorizontalAlignment(Element.ALIGN_LEFT);
- break;
- case Image.RIGHT:
- t.setHorizontalAlignment(Element.ALIGN_RIGHT);
- break;
- default:
- t.setHorizontalAlignment(Element.ALIGN_CENTER);
- break;
- }
- PdfPCell c = new PdfPCell(img, true);
- c.setPadding(0);
- c.setBorder(img.border());
- c.setBorderColor(img.borderColor());
- c.setBorderWidth(img.borderWidth());
- c.setBackgroundColor(img.backgroundColor());
- c.setGrayFill(img.grayFill());
- t.addCell(c);
- element = t;
- }
- */
- if (element.type() == Element.CHUNK) {
- element = new Paragraph((Chunk)element);
- }
- else if (element.type() == Element.PHRASE) {
- element = new Paragraph((Phrase)element);
- }
- if (element.type() != Element.PARAGRAPH && element.type() != Element.LIST && element.type() != Element.PTABLE && element.type() != Element.GRAPHIC)
- throw new IllegalArgumentException("Element not allowed.");
- if (!composite) {
- composite = true;
- compositeElements = new LinkedList();
- bidiLine = null;
- waitPhrase = null;
- }
- compositeElements.add(element);
- }
-
- /**
- * Converts a sequence of lines representing one of the column bounds into
- * an internal format.
- *
- * Each array element will contain a float[4]
representing
- * the line x = ax + b.
- * @param cLine the column array
- * @return the converted array
- */
- protected ArrayList convertColumn(float cLine[]) {
- if (cLine.length < 4)
- throw new RuntimeException("No valid column line found.");
- ArrayList cc = new ArrayList();
- for (int k = 0; k < cLine.length - 2; k += 2) {
- float x1 = cLine[k];
- float y1 = cLine[k + 1];
- float x2 = cLine[k + 2];
- float y2 = cLine[k + 3];
- if (y1 == y2)
- continue;
- // x = ay + b
- float a = (x1 - x2) / (y1 - y2);
- float b = x1 - a * y1;
- float r[] = new float[4];
- r[0] = Math.min(y1, y2);
- r[1] = Math.max(y1, y2);
- r[2] = a;
- r[3] = b;
- cc.add(r);
- maxY = Math.max(maxY, r[1]);
- minY = Math.min(minY, r[0]);
- }
- if (cc.size() == 0)
- throw new RuntimeException("No valid column line found.");
- return cc;
- }
-
- /**
- * Finds the intersection between the yLine
and the column. It will
- * set the lineStatus
apropriatly.
- * @param wall the column to intersect
- * @return the x coordinate of the intersection
- */
- protected float findLimitsPoint(ArrayList wall) {
- lineStatus = LINE_STATUS_OK;
- if (yLine < minY || yLine > maxY) {
- lineStatus = LINE_STATUS_OFFLIMITS;
- return 0;
- }
- for (int k = 0; k < wall.size(); ++k) {
- float r[] = (float[])wall.get(k);
- if (yLine < r[0] || yLine > r[1])
- continue;
- return r[2] * yLine + r[3];
- }
- lineStatus = LINE_STATUS_NOLINE;
- return 0;
- }
-
- /**
- * Finds the intersection between the yLine
and the two
- * column bounds. It will set the lineStatus
apropriatly.
- * @return a float[2]
with the x coordinates of the intersection
- */
- protected float[] findLimitsOneLine() {
- float x1 = findLimitsPoint(leftWall);
- if (lineStatus == LINE_STATUS_OFFLIMITS || lineStatus == LINE_STATUS_NOLINE)
- return null;
- float x2 = findLimitsPoint(rightWall);
- if (lineStatus == LINE_STATUS_NOLINE)
- return null;
- return new float[]{x1, x2};
- }
-
- /**
- * Finds the intersection between the yLine
,
- * the yLine-leading
and the two
- * column bounds. It will set the lineStatus
apropriatly.
- * @return a float[4]
with the x coordinates of the intersection
- */
- protected float[] findLimitsTwoLines() {
- boolean repeat = false;
- for (;;) {
- if (repeat && currentLeading == 0)
- return null;
- repeat = true;
- float x1[] = findLimitsOneLine();
- if (lineStatus == LINE_STATUS_OFFLIMITS)
- return null;
- yLine -= currentLeading;
- if (lineStatus == LINE_STATUS_NOLINE) {
- continue;
- }
- float x2[] = findLimitsOneLine();
- if (lineStatus == LINE_STATUS_OFFLIMITS)
- return null;
- if (lineStatus == LINE_STATUS_NOLINE) {
- yLine -= currentLeading;
- continue;
- }
- if (x1[0] >= x2[1] || x2[0] >= x1[1])
- continue;
- return new float[]{x1[0], x1[1], x2[0], x2[1]};
- }
- }
-
- /**
- * Sets the columns bounds. Each column bound is described by a
- * float[]
with the line points [x1,y1,x2,y2,...].
- * The array must have at least 4 elements.
- * @param leftLine the left column bound
- * @param rightLine the right column bound
- */
- public void setColumns(float leftLine[], float rightLine[]) {
- maxY = -10e20f;
- minY = 10e20f;
- rightWall = convertColumn(rightLine);
- leftWall = convertColumn(leftLine);
- rectangularWidth = -1;
- rectangularMode = false;
- }
-
- /**
- * Simplified method for rectangular columns.
- * @param phrase a Phrase
- * @param llx the lower left x corner
- * @param lly the lower left y corner
- * @param urx the upper right x corner
- * @param ury the upper right y corner
- * @param leading the leading
- * @param alignment the column alignment
- */
- public void setSimpleColumn(Phrase phrase, float llx, float lly, float urx, float ury, float leading, int alignment) {
- addText(phrase);
- setSimpleColumn(llx, lly, urx, ury, leading, alignment);
- }
-
- /**
- * Simplified method for rectangular columns.
- * @param llx the lower left x corner
- * @param lly the lower left y corner
- * @param urx the upper right x corner
- * @param ury the upper right y corner
- * @param leading the leading
- * @param alignment the column alignment
- */
- public void setSimpleColumn(float llx, float lly, float urx, float ury, float leading, int alignment) {
- setLeading(leading);
- this.alignment = alignment;
- setSimpleColumn(llx, lly, urx, ury);
- }
-
- /**
- * Simplified method for rectangular columns.
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- */
- public void setSimpleColumn(float llx, float lly, float urx, float ury) {
- leftX = Math.min(llx, urx);
- maxY = Math.max(lly, ury);
- minY = Math.min(lly, ury);
- rightX = Math.max(llx, urx);
- yLine = maxY;
- rectangularWidth = rightX - leftX;
- if (rectangularWidth < 0)
- rectangularWidth = 0;
- rectangularMode = true;
- }
- /**
- * Sets the leading to fixed
- * @param leading the leading
- */
- public void setLeading(float leading) {
- fixedLeading = leading;
- multipliedLeading = 0;
- }
-
- /**
- * Sets the leading fixed and variable. The resultant leading will be
- * fixedLeading+multipliedLeading*maxFontSize where maxFontSize is the
- * size of the bigest font in the line.
- * @param fixedLeading the fixed leading
- * @param multipliedLeading the variable leading
- */
- public void setLeading(float fixedLeading, float multipliedLeading) {
- this.fixedLeading = fixedLeading;
- this.multipliedLeading = multipliedLeading;
- }
-
- /**
- * Gets the fixed leading
- * @return the leading
- */
- public float getLeading() {
- return fixedLeading;
- }
-
- /**
- * Gets the variable leading
- * @return the leading
- */
- public float getMultipliedLeading() {
- return multipliedLeading;
- }
-
- /**
- * Sets the yLine. The line will be written to yLine-leading.
- * @param yLine the yLine
- */
- public void setYLine(float yLine) {
- this.yLine = yLine;
- }
-
- /**
- * Gets the yLine.
- * @return the yLine
- */
- public float getYLine() {
- return yLine;
- }
-
- /**
- * Sets the alignment.
- * @param alignment the alignment
- */
- public void setAlignment(int alignment) {
- this.alignment = alignment;
- }
-
- /**
- * Gets the alignment.
- * @return the alignment
- */
- public int getAlignment() {
- return alignment;
- }
-
- /**
- * Sets the first paragraph line indent.
- * @param indent the indent
- */
- public void setIndent(float indent) {
- this.indent = indent;
- lastWasNewline = true;
- }
-
- /**
- * Gets the first paragraph line indent.
- * @return the indent
- */
- public float getIndent() {
- return indent;
- }
-
- /**
- * Sets the following paragraph lines indent.
- * @param indent the indent
- */
- public void setFollowingIndent(float indent) {
- this.followingIndent = indent;
- lastWasNewline = true;
- }
-
- /**
- * Gets the following paragraph lines indent.
- * @return the indent
- */
- public float getFollowingIndent() {
- return followingIndent;
- }
-
- /**
- * Sets the right paragraph lines indent.
- * @param indent the indent
- */
- public void setRightIndent(float indent) {
- this.rightIndent = indent;
- lastWasNewline = true;
- }
-
- /**
- * Gets the right paragraph lines indent.
- * @return the indent
- */
- public float getRightIndent() {
- return rightIndent;
- }
-
- /**
- * Outputs the lines to the document. It is equivalent to go(false)
.
- * @return returns the result of the operation. It can be NO_MORE_TEXT
- * and/or NO_MORE_COLUMN
- * @throws DocumentException on error
- */
- public int go() throws DocumentException {
- return go(false);
- }
-
- /**
- * Outputs the lines to the document. The output can be simulated.
- * @param simulate true
to simulate the writting to the document
- * @return returns the result of the operation. It can be NO_MORE_TEXT
- * and/or NO_MORE_COLUMN
- * @throws DocumentException on error
- */
- public int go(boolean simulate) throws DocumentException {
- if (composite)
- return goComposite(simulate);
- addWaitingPhrase();
- if (bidiLine == null)
- return NO_MORE_TEXT;
- descender = 0;
- linesWritten = 0;
- boolean dirty = false;
- float ratio = spaceCharRatio;
- Object currentValues[] = new Object[2];
- PdfFont currentFont = null;
- Float lastBaseFactor = new Float(0);
- currentValues[1] = lastBaseFactor;
- PdfDocument pdf = null;
- PdfContentByte graphics = null;
- PdfContentByte text = null;
- firstLineY = Float.NaN;
- int localRunDirection = PdfWriter.RUN_DIRECTION_NO_BIDI;
- if (runDirection != PdfWriter.RUN_DIRECTION_DEFAULT)
- localRunDirection = runDirection;
- if (canvas != null) {
- graphics = canvas;
- pdf = canvas.getPdfDocument();
- text = canvas.getDuplicate();
- }
- else if (!simulate)
- throw new NullPointerException("ColumnText.go with simulate==false and text==null.");
- if (!simulate) {
- if (ratio == GLOBAL_SPACE_CHAR_RATIO)
- ratio = text.getPdfWriter().getSpaceCharRatio();
- else if (ratio < 0.001f)
- ratio = 0.001f;
- }
- float firstIndent = 0;
-
- int status = 0;
- if (rectangularMode) {
- for (;;) {
- firstIndent = (lastWasNewline ? indent : followingIndent);
- if (rectangularWidth <= firstIndent + rightIndent) {
- status = NO_MORE_COLUMN;
- if (bidiLine.isEmpty())
- status |= NO_MORE_TEXT;
- break;
- }
- if (bidiLine.isEmpty()) {
- status = NO_MORE_TEXT;
- break;
- }
- PdfLine line = bidiLine.processLine(rectangularWidth - firstIndent - rightIndent, alignment, localRunDirection, arabicOptions);
- if (line == null) {
- status = NO_MORE_TEXT;
- break;
- }
- float maxSize = line.getMaxSizeSimple();
- if (isUseAscender() && Float.isNaN(firstLineY)) {
- currentLeading = line.getAscender();
- }
- else {
- currentLeading = fixedLeading + maxSize * multipliedLeading;
- }
- if (yLine > maxY || yLine - currentLeading < minY ) {
- status = NO_MORE_COLUMN;
- bidiLine.restore();
- break;
- }
- yLine -= currentLeading;
- if (!simulate && !dirty) {
- text.beginText();
- dirty = true;
- }
- if (Float.isNaN(firstLineY)) {
- firstLineY = yLine;
- }
- if (!simulate) {
- currentValues[0] = currentFont;
- text.setTextMatrix(leftX + (line.isRTL() ? rightIndent : firstIndent) + line.indentLeft(), yLine);
- pdf.writeLineToContent(line, text, graphics, currentValues, ratio);
- currentFont = (PdfFont)currentValues[0];
- }
- lastWasNewline = line.isNewlineSplit();
- yLine -= line.isNewlineSplit() ? extraParagraphSpace : 0;
- ++linesWritten;
- descender = line.getDescender();
- }
- }
- else {
- currentLeading = fixedLeading;
- for (;;) {
- firstIndent = (lastWasNewline ? indent : followingIndent);
- float yTemp = yLine;
- float xx[] = findLimitsTwoLines();
- if (xx == null) {
- status = NO_MORE_COLUMN;
- if (bidiLine.isEmpty())
- status |= NO_MORE_TEXT;
- yLine = yTemp;
- break;
- }
- if (bidiLine.isEmpty()) {
- status = NO_MORE_TEXT;
- yLine = yTemp;
- break;
- }
- float x1 = Math.max(xx[0], xx[2]);
- float x2 = Math.min(xx[1], xx[3]);
- if (x2 - x1 <= firstIndent + rightIndent)
- continue;
- if (!simulate && !dirty) {
- text.beginText();
- dirty = true;
- }
- PdfLine line = bidiLine.processLine(x2 - x1 - firstIndent - rightIndent, alignment, localRunDirection, arabicOptions);
- if (line == null) {
- status = NO_MORE_TEXT;
- yLine = yTemp;
- break;
- }
- if (!simulate) {
- currentValues[0] = currentFont;
- text.setTextMatrix(x1 + (line.isRTL() ? rightIndent : firstIndent) + line.indentLeft(), yLine);
- pdf.writeLineToContent(line, text, graphics, currentValues, ratio);
- currentFont = (PdfFont)currentValues[0];
- }
- lastWasNewline = line.isNewlineSplit();
- yLine -= line.isNewlineSplit() ? extraParagraphSpace : 0;
- ++linesWritten;
- descender = line.getDescender();
- }
- }
- if (dirty) {
- text.endText();
- canvas.add(text);
- }
- return status;
- }
-
- /**
- * Sets the extra space between paragraphs.
- * @return the extra space between paragraphs
- */
- public float getExtraParagraphSpace() {
- return extraParagraphSpace;
- }
-
- /**
- * Sets the extra space between paragraphs.
- * @param extraParagraphSpace the extra space between paragraphs
- */
- public void setExtraParagraphSpace(float extraParagraphSpace) {
- this.extraParagraphSpace = extraParagraphSpace;
- }
-
- /**
- * Clears the chunk array. A call to go()
will always return
- * NO_MORE_TEXT.
- */
- public void clearChunks() {
- if (bidiLine != null)
- bidiLine.clearChunks();
- }
-
- /** Gets the space/character extra spacing ratio for
- * fully justified text.
- * @return the space/character extra spacing ratio
- */
- public float getSpaceCharRatio() {
- return spaceCharRatio;
- }
-
- /** Sets the ratio between the extra word spacing and the extra character spacing
- * when the text is fully justified.
- * Extra word spacing will grow spaceCharRatio
times more than extra character spacing.
- * If the ratio is PdfWriter.NO_SPACE_CHAR_RATIO
then the extra character spacing
- * will be zero.
- * @param spaceCharRatio the ratio between the extra word spacing and the extra character spacing
- */
- public void setSpaceCharRatio(float spaceCharRatio) {
- this.spaceCharRatio = spaceCharRatio;
- }
-
- /** Sets the run direction.
- * @param runDirection the run direction
- */
- public void setRunDirection(int runDirection) {
- if (runDirection < PdfWriter.RUN_DIRECTION_DEFAULT || runDirection > PdfWriter.RUN_DIRECTION_RTL)
- throw new RuntimeException("Invalid run direction: " + runDirection);
- this.runDirection = runDirection;
- }
-
- /** Gets the run direction.
- * @return the run direction
- */
- public int getRunDirection() {
- return runDirection;
- }
-
- /** Gets the number of lines written.
- * @return the number of lines written
- */
- public int getLinesWritten() {
- return this.linesWritten;
- }
-
- /** Gets the arabic shaping options.
- * @return the arabic shaping options
- */
- public int getArabicOptions() {
- return this.arabicOptions;
- }
-
- /** Sets the arabic shaping options. The option can be AR_NOVOWEL,
- * AR_COMPOSEDTASHKEEL and AR_LIG.
- * @param arabicOptions the arabic shaping options
- */
- public void setArabicOptions(int arabicOptions) {
- this.arabicOptions = arabicOptions;
- }
-
- /** Gets the biggest descender value of the last line written.
- * @return the biggest descender value of the last line written
- */
- public float getDescender() {
- return descender;
- }
-
- /** Gets the width that the line will occupy after writing.
- * Only the width of the first line is returned.
- * @param phrase the Phrase
containing the line
- * @param runDirection the run direction
- * @param arabicOptions the options for the arabic shaping
- * @return the width of the line
- */
- public static float getWidth(Phrase phrase, int runDirection, int arabicOptions) {
- ColumnText ct = new ColumnText(null);
- ct.addText(phrase);
- ct.addWaitingPhrase();
- PdfLine line = ct.bidiLine.processLine(20000, Element.ALIGN_LEFT, runDirection, arabicOptions);
- if (line == null)
- return 0;
- else
- return 20000 - line.widthLeft();
- }
-
- /** Gets the width that the line will occupy after writing.
- * Only the width of the first line is returned.
- * @param phrase the Phrase
containing the line
- * @return the width of the line
- */
- public static float getWidth(Phrase phrase) {
- return getWidth(phrase, PdfWriter.RUN_DIRECTION_NO_BIDI, 0);
- }
-
- /** Shows a line of text. Only the first line is written.
- * @param canvas where the text is to be written to
- * @param alignment the alignment. It is not influenced by the run direction
- * @param phrase the Phrase
with the text
- * @param x the x reference position
- * @param y the y reference position
- * @param rotation the rotation to be applied in degrees counterclockwise
- * @param runDirection the run direction
- * @param arabicOptions the options for the arabic shaping
- */
- public static void showTextAligned(PdfContentByte canvas, int alignment, Phrase phrase, float x, float y, float rotation, int runDirection, int arabicOptions) {
- if (alignment != Element.ALIGN_LEFT && alignment != Element.ALIGN_CENTER
- && alignment != Element.ALIGN_RIGHT)
- alignment = Element.ALIGN_LEFT;
- canvas.saveState();
- ColumnText ct = new ColumnText(canvas);
- if (rotation == 0) {
- if (alignment == Element.ALIGN_LEFT)
- ct.setSimpleColumn(phrase, x, y - 1, 20000 + x, y + 2, 2, alignment);
- else if (alignment == Element.ALIGN_RIGHT)
- ct.setSimpleColumn(phrase, x-20000, y-1, x, y+2, 2, alignment);
- else
- ct.setSimpleColumn(phrase, x-20000, y-1, x+20000, y+2, 2, alignment);
- }
- else {
- double alpha = rotation * Math.PI / 180.0;
- float cos = (float)Math.cos(alpha);
- float sin = (float)Math.sin(alpha);
- canvas.concatCTM(cos, sin, -sin, cos, x, y);
- if (alignment == Element.ALIGN_LEFT)
- ct.setSimpleColumn(phrase, 0, -1, 20000, 2, 2, alignment);
- else if (alignment == Element.ALIGN_RIGHT)
- ct.setSimpleColumn(phrase, -20000, -1, 0, 2, 2, alignment);
- else
- ct.setSimpleColumn(phrase, -20000, -1, 20000, 2, 2, alignment);
- }
- if (runDirection == PdfWriter.RUN_DIRECTION_RTL) {
- if (alignment == Element.ALIGN_LEFT)
- alignment = Element.ALIGN_RIGHT;
- else if (alignment == Element.ALIGN_RIGHT)
- alignment = Element.ALIGN_LEFT;
- }
- ct.setAlignment(alignment);
- ct.setArabicOptions(arabicOptions);
- ct.setRunDirection(runDirection);
- try {
- ct.go();
- }
- catch (DocumentException e) {
- throw new ExceptionConverter(e);
- }
- canvas.restoreState();
- }
-
- /** Shows a line of text. Only the first line is written.
- * @param canvas where the text is to be written to
- * @param alignment the alignment
- * @param phrase the Phrase
with the text
- * @param x the x reference position
- * @param y the y reference position
- * @param rotation the rotation to be applied in degrees counterclockwise
- */
- public static void showTextAligned(PdfContentByte canvas, int alignment, Phrase phrase, float x, float y, float rotation) {
- showTextAligned(canvas, alignment, phrase, x, y, rotation, PdfWriter.RUN_DIRECTION_NO_BIDI, 0);
- }
-
- protected int goComposite(boolean simulate) throws DocumentException {
- if (!rectangularMode)
- throw new DocumentException("Irregular columns are not supported in composite mode.");
- linesWritten = 0;
- descender = 0;
- boolean firstPass = true;
- main_loop:
- while (true) {
- if (compositeElements.isEmpty())
- return NO_MORE_TEXT;
- Element element = (Element)compositeElements.getFirst();
- if (element.type() == Element.PARAGRAPH) {
- Paragraph para = (Paragraph)element;
- int status = 0;
- for (int keep = 0; keep < 2; ++keep) {
- float lastY = yLine;
- boolean createHere = false;
- if (compositeColumn == null) {
- compositeColumn = new ColumnText(canvas);
- compositeColumn.setUseAscender(firstPass ? useAscender : false);
- compositeColumn.setAlignment(para.alignment());
- compositeColumn.setIndent(para.indentationLeft() + para.getFirstLineIndent());
- compositeColumn.setExtraParagraphSpace(para.getExtraParagraphSpace());
- compositeColumn.setFollowingIndent(para.indentationLeft());
- compositeColumn.setRightIndent(para.indentationRight());
- compositeColumn.setLeading(para.leading(), para.getMultipliedLeading());
- compositeColumn.setRunDirection(runDirection);
- compositeColumn.setArabicOptions(arabicOptions);
- compositeColumn.setSpaceCharRatio(spaceCharRatio);
- compositeColumn.addText(para);
- if (!firstPass) {
- yLine -= para.spacingBefore();
- }
- createHere = true;
- }
- compositeColumn.leftX = leftX;
- compositeColumn.rightX = rightX;
- compositeColumn.yLine = yLine;
- compositeColumn.rectangularWidth = rectangularWidth;
- compositeColumn.rectangularMode = rectangularMode;
- compositeColumn.minY = minY;
- compositeColumn.maxY = maxY;
- boolean keepCandidate = (para.getKeepTogether() && createHere && !firstPass);
- status = compositeColumn.go(simulate || (keepCandidate && keep == 0));
- if ((status & NO_MORE_TEXT) == 0 && keepCandidate) {
- compositeColumn = null;
- yLine = lastY;
- return NO_MORE_COLUMN;
- }
- if (simulate || !keepCandidate)
- break;
- if (keep == 0) {
- compositeColumn = null;
- yLine = lastY;
- }
- }
- firstPass = false;
- yLine = compositeColumn.yLine;
- linesWritten += compositeColumn.linesWritten;
- descender = compositeColumn.descender;
- if ((status & NO_MORE_TEXT) != 0) {
- compositeColumn = null;
- compositeElements.removeFirst();
- yLine -= para.spacingAfter();
- }
- if ((status & NO_MORE_COLUMN) != 0) {
- return NO_MORE_COLUMN;
- }
- }
- else if (element.type() == Element.LIST) {
- com.lowagie.text.List list = (com.lowagie.text.List)element;
- ArrayList items = list.getItems();
- ListItem item = null;
- float listIndentation = list.indentationLeft();
- int count = 0;
- Stack stack = new Stack();
- for (int k = 0; k < items.size(); ++k) {
- Object obj = items.get(k);
- if (obj instanceof ListItem) {
- if (count == listIdx) {
- item = (ListItem)obj;
- break;
- }
- else ++count;
- }
- else if (obj instanceof com.lowagie.text.List) {
- stack.push(new Object[]{list, new Integer(k), new Float(listIndentation)});
- list = (com.lowagie.text.List)obj;
- items = list.getItems();
- listIndentation += list.indentationLeft();
- k = -1;
- continue;
- }
- if (k == items.size() - 1) {
- if (!stack.isEmpty()) {
- Object objs[] = (Object[])stack.pop();
- list = (com.lowagie.text.List)objs[0];
- items = list.getItems();
- k = ((Integer)objs[1]).intValue();
- listIndentation = ((Float)objs[2]).floatValue();
- }
- }
- }
- int status = 0;
- for (int keep = 0; keep < 2; ++keep) {
- float lastY = yLine;
- boolean createHere = false;
- if (compositeColumn == null) {
- if (item == null) {
- listIdx = 0;
- compositeElements.removeFirst();
- continue main_loop;
- }
- compositeColumn = new ColumnText(canvas);
- compositeColumn.setUseAscender(firstPass ? useAscender : false);
- compositeColumn.setAlignment(item.alignment());
- compositeColumn.setIndent(item.indentationLeft() + listIndentation + item.getFirstLineIndent());
- compositeColumn.setExtraParagraphSpace(item.getExtraParagraphSpace());
- compositeColumn.setFollowingIndent(compositeColumn.getIndent());
- compositeColumn.setRightIndent(item.indentationRight() + list.indentationRight());
- compositeColumn.setLeading(item.leading(), item.getMultipliedLeading());
- compositeColumn.setRunDirection(runDirection);
- compositeColumn.setArabicOptions(arabicOptions);
- compositeColumn.setSpaceCharRatio(spaceCharRatio);
- compositeColumn.addText(item);
- if (!firstPass) {
- yLine -= item.spacingBefore();
- }
- createHere = true;
- }
- compositeColumn.leftX = leftX;
- compositeColumn.rightX = rightX;
- compositeColumn.yLine = yLine;
- compositeColumn.rectangularWidth = rectangularWidth;
- compositeColumn.rectangularMode = rectangularMode;
- compositeColumn.minY = minY;
- compositeColumn.maxY = maxY;
- boolean keepCandidate = (item.getKeepTogether() && createHere && !firstPass);
- status = compositeColumn.go(simulate || (keepCandidate && keep == 0));
- if ((status & NO_MORE_TEXT) == 0 && keepCandidate) {
- compositeColumn = null;
- yLine = lastY;
- return NO_MORE_COLUMN;
- }
- if (simulate || !keepCandidate)
- break;
- if (keep == 0) {
- compositeColumn = null;
- yLine = lastY;
- }
- }
- firstPass = false;
- yLine = compositeColumn.yLine;
- linesWritten += compositeColumn.linesWritten;
- descender = compositeColumn.descender;
- if (!Float.isNaN(compositeColumn.firstLineY) && !compositeColumn.firstLineYDone) {
- if (!simulate)
- showTextAligned(canvas, Element.ALIGN_LEFT, new Phrase(item.listSymbol()), compositeColumn.leftX + listIndentation, compositeColumn.firstLineY, 0);
- compositeColumn.firstLineYDone = true;
- }
- if ((status & NO_MORE_TEXT) != 0) {
- compositeColumn = null;
- ++listIdx;
- yLine -= item.spacingAfter();
- }
- if ((status & NO_MORE_COLUMN) != 0) {
- return NO_MORE_COLUMN;
- }
- }
- /* ssteward: dropped in 1.44
- else if (element.type() == Element.PTABLE) {
- if (yLine < minY || yLine > maxY)
- return NO_MORE_COLUMN;
- PdfPTable table = (PdfPTable)element;
- if (table.size() <= table.getHeaderRows()) {
- compositeElements.removeFirst();
- continue;
- }
- float yTemp = yLine;
- float yLineWrite = yLine;
- if (!firstPass && listIdx == 0) {
- yTemp -= table.spacingBefore();
- yLineWrite = yTemp;
- }
- currentLeading = 0;
- if (yTemp < minY || yTemp > maxY)
- return NO_MORE_COLUMN;
- float x1 = leftX;
- float tableWidth;
- if (table.isLockedWidth())
- tableWidth = table.getTotalWidth();
- else {
- tableWidth = rectangularWidth * table.getWidthPercentage() / 100f;
- table.setTotalWidth(tableWidth);
- }
- int k;
- boolean skipHeader = (!firstPass && table.isSkipFirstHeader() && listIdx <= table.getHeaderRows());
- if (!skipHeader) {
- yTemp -= table.getHeaderHeight();
- if (yTemp < minY || yTemp > maxY) {
- if (firstPass) {
- compositeElements.removeFirst();
- continue;
- }
- return NO_MORE_COLUMN;
- }
- }
- if (listIdx < table.getHeaderRows())
- listIdx = table.getHeaderRows();
- for (k = listIdx; k < table.size(); ++k) {
- float rowHeight = table.getRowHeight(k);
- if (yTemp - rowHeight < minY)
- break;
- yTemp -= rowHeight;
- }
- if (k < table.size()) {
- if (table.isSplitRows() && (!table.isSplitLate() || (k == listIdx && firstPass))) {
- if (!splittedRow) {
- splittedRow = true;
- table = new PdfPTable(table);
- compositeElements.set(0, table);
- ArrayList rows = table.getRows();
- for (int i = table.getHeaderRows(); i < listIdx; ++i)
- rows.set(i, null);
- }
- float h = yTemp - minY;
- PdfPRow newRow = table.getRow(k).splitRow(h);
- if (newRow == null) {
- if (k == listIdx)
- return NO_MORE_COLUMN;
- }
- else {
- yTemp = minY;
- table.getRows().add(++k, newRow);
- }
- }
- else if (!table.isSplitRows() && k == listIdx && firstPass) {
- compositeElements.removeFirst();
- splittedRow = false;
- continue;
- }
- else if (k == listIdx && !firstPass && (!table.isSplitRows() || table.isSplitLate())) {
- return NO_MORE_COLUMN;
- }
- }
- firstPass = false;
- if (!simulate) {
- switch (table.getHorizontalAlignment()) {
- case Element.ALIGN_LEFT:
- break;
- case Element.ALIGN_RIGHT:
- x1 += rectangularWidth - tableWidth;
- break;
- default:
- x1 += (rectangularWidth - tableWidth) / 2f;
- }
- PdfPTable nt = PdfPTable.shallowCopy(table);
- ArrayList rows = table.getRows();
- ArrayList sub = nt.getRows();
- if (!skipHeader) {
- for (int j = 0; j < table.getHeaderRows(); ++j)
- sub.add(rows.get(j));
- }
- else
- nt.setHeaderRows(0);
- for (int j = listIdx; j < k; ++j)
- sub.add(rows.get(j));
- float rowHeight = 0;
- if (table.isExtendLastRow()) {
- PdfPRow last = (PdfPRow)sub.get(sub.size() - 1);
- rowHeight = last.getMaxHeights();
- last.setMaxHeights(yTemp - minY + rowHeight);
- yTemp = minY;
- }
- nt.writeSelectedRows(0, -1, x1, yLineWrite, canvas);
- if (table.isExtendLastRow()) {
- PdfPRow last = (PdfPRow)sub.get(sub.size() - 1);
- last.setMaxHeights(rowHeight);
- }
- }
- else if (table.isExtendLastRow() && minY > PdfPRow.BOTTOM_LIMIT)
- yTemp = minY;
- yLine = yTemp;
- if (k >= table.size()) {
- yLine -= table.spacingAfter();
- compositeElements.removeFirst();
- splittedRow = false;
- listIdx = 0;
- }
- else {
- if (splittedRow) {
- ArrayList rows = table.getRows();
- for (int i = listIdx; i < k; ++i)
- rows.set(i, null);
- }
- listIdx = k;
- return NO_MORE_COLUMN;
- }
- }
- */
- /* ssteward: dropped in 1.44
- else if (element.type() == Element.GRAPHIC) {
- if (!simulate) {
- Graphic gr = (Graphic)element;
- ByteBuffer bf = gr.getInternalBuffer();
- ByteBuffer store = null;
- if (bf.size() > 0) {
- store = new ByteBuffer();
- store.append(bf);
- bf.reset();
- }
- gr.processAttributes(leftX, minY, rightX, maxY, yLine);
- canvas.add(gr);
- bf.reset();
- if (store != null) {
- bf.append(store);
- }
- }
- compositeElements.removeFirst();
- }
- */
- else
- compositeElements.removeFirst();
- }
- }
-
- /**
- * Gets the canvas.
- * @return a PdfContentByte.
- */
- public PdfContentByte getCanvas() {
- return canvas;
- }
-
- /**
- * Sets the canvas.
- * @param canvas
- */
- public void setCanvas(PdfContentByte canvas) {
- this.canvas = canvas;
- if (compositeColumn != null)
- compositeColumn.setCanvas(canvas);
- }
-
- /**
- * Checks if the element has a height of 0.
- * @return true or false
- */
- public boolean zeroHeightElement() {
- return composite == true && compositeElements.size() > 0 && ((Element)compositeElements.getFirst()).type() == Element.GRAPHIC;
- }
-
- /**
- * Checks if UseAscender is enabled/disabled.
- * @return true is the adjustment of the first line height is based on max ascender.
- */
- public boolean isUseAscender() {
- return useAscender;
- }
-
- /**
- * Enables/Disables adjustment of first line height based on max ascender.
- * @param use enable adjustment if true
- */
- public void setUseAscender(boolean use) {
- useAscender = use;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/DefaultFontMapper.java pdftk-2.01/java/com/lowagie/text/pdf/DefaultFontMapper.java
--- pdftk-1.45/java/com/lowagie/text/pdf/DefaultFontMapper.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/DefaultFontMapper.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,314 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.awt.Font;
-import com.lowagie.text.ExceptionConverter;
-import java.util.HashMap;
-import java.io.File;
-/** Default class to map awt fonts to BaseFont.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-
-public class DefaultFontMapper implements FontMapper {
-
- /** A representation of BaseFont parameters.
- */
- public static class BaseFontParameters {
- /** The font name.
- */
- public String fontName;
- /** The encoding for that font.
- */
- public String encoding;
- /** The embedding for that font.
- */
- public boolean embedded;
- /** Whether the font is cached of not.
- */
- public boolean cached;
- /** The font bytes for ttf and afm.
- */
- public byte ttfAfm[];
- /** The font bytes for pfb.
- */
- public byte pfb[];
-
- /** Constructs default BaseFont parameters.
- * @param fontName the font name or location
- */
- public BaseFontParameters(String fontName) {
- this.fontName = fontName;
- encoding = BaseFont.CP1252;
- embedded = BaseFont.EMBEDDED;
- cached = BaseFont.CACHED;
- }
- }
-
- /** Maps aliases to names.
- */
- private HashMap aliases = new HashMap();
- /** Maps names to BaseFont parameters.
- */
- private HashMap mapper = new HashMap();
- /**
- * Returns a BaseFont which can be used to represent the given AWT Font
- *
- * @param font the font to be converted
- * @return a BaseFont which has similar properties to the provided Font
- */
-
- public BaseFont awtToPdf(Font font) {
- try {
- BaseFontParameters p = getBaseFontParameters(font.getFontName());
- if (p != null)
- return BaseFont.createFont(p.fontName, p.encoding, p.embedded, p.cached, p.ttfAfm, p.pfb);
- String fontKey = null;
- String logicalName = font.getName();
-
- if (logicalName.equalsIgnoreCase("DialogInput") || logicalName.equalsIgnoreCase("Monospaced") || logicalName.equalsIgnoreCase("Courier")) {
-
- if (font.isItalic()) {
- if (font.isBold()) {
- fontKey = BaseFont.COURIER_BOLDOBLIQUE;
-
- } else {
- fontKey = BaseFont.COURIER_OBLIQUE;
- }
-
- } else {
- if (font.isBold()) {
- fontKey = BaseFont.COURIER_BOLD;
-
- } else {
- fontKey = BaseFont.COURIER;
- }
- }
-
- } else if (logicalName.equalsIgnoreCase("Serif") || logicalName.equalsIgnoreCase("TimesRoman")) {
-
- if (font.isItalic()) {
- if (font.isBold()) {
- fontKey = BaseFont.TIMES_BOLDITALIC;
-
- } else {
- fontKey = BaseFont.TIMES_ITALIC;
- }
-
- } else {
- if (font.isBold()) {
- fontKey = BaseFont.TIMES_BOLD;
-
- } else {
- fontKey = BaseFont.TIMES_ROMAN;
- }
- }
-
- } else { // default, this catches Dialog and SansSerif
-
- if (font.isItalic()) {
- if (font.isBold()) {
- fontKey = BaseFont.HELVETICA_BOLDOBLIQUE;
-
- } else {
- fontKey = BaseFont.HELVETICA_OBLIQUE;
- }
-
- } else {
- if (font.isBold()) {
- fontKey = BaseFont.HELVETICA_BOLD;
- } else {
- fontKey = BaseFont.HELVETICA;
- }
- }
- }
- return BaseFont.createFont(fontKey, BaseFont.CP1252, false);
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Returns an AWT Font which can be used to represent the given BaseFont
- *
- * @param font the font to be converted
- * @param size the desired point size of the resulting font
- * @return a Font which has similar properties to the provided BaseFont
- */
-
- public Font pdfToAwt(BaseFont font, int size) {
- String names[][] = font.getFullFontName();
- if (names.length == 1)
- return new Font(names[0][3], 0, size);
- String name10 = null;
- String name3x = null;
- for (int k = 0; k < names.length; ++k) {
- String name[] = names[k];
- if (name[0].equals("1") && name[1].equals("0"))
- name10 = name[3];
- else if (name[2].equals("1033")) {
- name3x = name[3];
- break;
- }
- }
- String finalName = name3x;
- if (finalName == null)
- finalName = name10;
- if (finalName == null)
- finalName = names[0][3];
- return new Font(finalName, 0, size);
- }
-
- /** Maps a name to a BaseFont parameter.
- * @param awtName the name
- * @param parameters the BaseFont parameter
- */
- public void putName(String awtName, BaseFontParameters parameters) {
- mapper.put(awtName, parameters);
- }
-
- /** Maps an alias to a name.
- * @param alias the alias
- * @param awtName the name
- */
- public void putAlias(String alias, String awtName) {
- aliases.put(alias, awtName);
- }
-
- /** Looks for a BaseFont parameter associated with a name.
- * @param name the name
- * @return the BaseFont parameter or null
if not found.
- */
- public BaseFontParameters getBaseFontParameters(String name) {
- String alias = (String)aliases.get(name);
- if (alias == null)
- return (BaseFontParameters)mapper.get(name);
- BaseFontParameters p = (BaseFontParameters)mapper.get(alias);
- if (p == null)
- return (BaseFontParameters)mapper.get(name);
- else
- return p;
- }
-
- /**
- * Inserts the names in this map.
- * @param allNames the returned value of calling {@link BaseFont#getAllFontNames(String, String, byte[])}
- * @param path the full path to the font
- */
- public void insertNames(Object allNames[], String path) {
- String names[][] = (String[][])allNames[2];
- String main = null;
- for (int k = 0; k < names.length; ++k) {
- String name[] = names[k];
- if (name[2].equals("1033")) {
- main = name[3];
- break;
- }
- }
- if (main == null)
- main = names[0][3];
- BaseFontParameters p = new BaseFontParameters(path);
- mapper.put(main, p);
- for (int k = 0; k < names.length; ++k) {
- aliases.put(names[k][3], main);
- }
- aliases.put((String)allNames[0], main);
- }
-
- /** Inserts all the fonts recognized by iText in the
- * directory
into the map. The encoding
- * will be BaseFont.CP1252
but can be
- * changed later.
- * @param dir the directory to scan
- * @return the number of files processed
- */
- public int insertDirectory(String dir) {
- File file = new File(dir);
- if (!file.exists() || !file.isDirectory())
- return 0;
- File files[] = file.listFiles();
- int count = 0;
- for (int k = 0; k < files.length; ++k) {
- file = files[k];
- String name = file.getPath().toLowerCase();
- try {
- if (name.endsWith(".ttf") || name.endsWith(".otf") || name.endsWith(".afm")) {
- Object allNames[] = BaseFont.getAllFontNames(file.getPath(), BaseFont.CP1252, null);
- insertNames(allNames, file.getPath());
- ++count;
- }
- else if (name.endsWith(".ttc")) {
- String ttcs[] = BaseFont.enumerateTTCNames(file.getPath());
- for (int j = 0; j < ttcs.length; ++j) {
- String nt = file.getPath() + "," + j;
- Object allNames[] = BaseFont.getAllFontNames(nt, BaseFont.CP1252, null);
- insertNames(allNames, nt);
- }
- ++count;
- }
- }
- catch (Exception e) {
- }
- }
- return count;
- }
-
- public HashMap getMapper() {
- return mapper;
- }
-
- public HashMap getAliases() {
- return aliases;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/DocumentFont.java pdftk-2.01/java/com/lowagie/text/pdf/DocumentFont.java
--- pdftk-1.45/java/com/lowagie/text/pdf/DocumentFont.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/DocumentFont.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,419 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.ExceptionConverter;
-
-/**
- *
- * @author psoares
- */
-public class DocumentFont extends BaseFont {
-
- String fontName;
- PRIndirectReference refFont;
- PdfDictionary font;
- IntHashtable uni2byte = new IntHashtable();
- float Ascender = 800;
- float CapHeight = 700;
- float Descender = -200;
- float ItalicAngle = 0;
- float llx = -50;
- float lly = -200;
- float urx = 100;
- float ury = 900;
-
- BaseFont cjkMirror;
-
- String cjkNames[] = {"HeiseiMin-W3", "HeiseiKakuGo-W5", "STSong-Light", "MHei-Medium",
- "MSung-Light", "HYGoThic-Medium", "HYSMyeongJo-Medium", "MSungStd-Light", "STSongStd-Light",
- "HYSMyeongJoStd-Medium", "KozMinPro-Regular"};
-
- String cjkEncs[] = {"UniJIS-UCS2-H", "UniJIS-UCS2-H", "UniGB-UCS2-H", "UniCNS-UCS2-H",
- "UniCNS-UCS2-H", "UniKS-UCS2-H", "UniKS-UCS2-H", "UniCNS-UCS2-H", "UniGB-UCS2-H",
- "UniKS-UCS2-H", "UniJIS-UCS2-H"};
-
- static final int stdEnc[] = {
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 32,33,34,35,36,37,38,8217,40,41,42,43,44,45,46,47,
- 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
- 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
- 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
- 8216,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
- 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,161,162,163,8260,165,402,167,164,39,8220,171,8249,8250,64257,64258,
- 0,8211,8224,8225,183,0,182,8226,8218,8222,8221,187,8230,8240,0,191,
- 0,96,180,710,732,175,728,729,168,0,730,184,0,733,731,711,
- 8212,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,198,0,170,0,0,0,0,321,216,338,186,0,0,0,0,
- 0,230,0,0,0,305,0,0,322,248,339,223,0,0,0,0};
-
- /** Creates a new instance of DocumentFont */
- DocumentFont(PRIndirectReference refFont) {
- encoding = "";
- fontSpecific = false;
- this.refFont = refFont;
- fontType = FONT_TYPE_DOCUMENT;
- font = (PdfDictionary)PdfReader.getPdfObject(refFont);
- fontName = PdfName.decodeName(((PdfName)PdfReader.getPdfObject(font.get(PdfName.BASEFONT))).toString());
- PdfName subType = (PdfName)PdfReader.getPdfObject(font.get(PdfName.SUBTYPE));
- if (PdfName.TYPE1.equals(subType) || PdfName.TRUETYPE.equals(subType))
- doType1TT();
- else {
- for (int k = 0; k < cjkNames.length; ++k) {
- if (fontName.startsWith(cjkNames[k])) {
- fontName = cjkNames[k];
- try {
- cjkMirror = BaseFont.createFont(fontName, cjkEncs[k], false);
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- return;
- }
- }
- }
- }
-
- public void doType1TT() {
- PdfObject enc = PdfReader.getPdfObject(font.get(PdfName.ENCODING));
- if (enc == null)
- fillEncoding(null);
- else {
- if (enc.isName())
- fillEncoding((PdfName)enc);
- else {
- PdfDictionary encDic = (PdfDictionary)enc;
- enc = PdfReader.getPdfObject(encDic.get(PdfName.BASEENCODING));
- if (enc == null)
- fillEncoding(null);
- else
- fillEncoding((PdfName)enc);
- PdfArray diffs = (PdfArray)PdfReader.getPdfObject(encDic.get(PdfName.DIFFERENCES));
- if (diffs != null) {
- ArrayList dif = diffs.getArrayList();
- int currentNumber = 0;
- for (int k = 0; k < dif.size(); ++k) {
- PdfObject obj = (PdfObject)dif.get(k);
- if (obj.isNumber())
- currentNumber = ((PdfNumber)obj).intValue();
- else {
- int c[] = GlyphList.nameToUnicode(PdfName.decodeName(((PdfName)obj).toString()));
- if (c != null && c.length > 0)
- uni2byte.put(c[0], currentNumber);
- ++currentNumber;
- }
- }
- }
- }
- }
- PdfArray newWidths = (PdfArray)PdfReader.getPdfObject(font.get(PdfName.WIDTHS));
- PdfNumber first = (PdfNumber)PdfReader.getPdfObject(font.get(PdfName.FIRSTCHAR));
- PdfNumber last = (PdfNumber)PdfReader.getPdfObject(font.get(PdfName.LASTCHAR));
- if (BuiltinFonts14.containsKey(fontName)) {
- BaseFont bf;
- try {
- bf = BaseFont.createFont(fontName, WINANSI, false);
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- int e[] = uni2byte.toOrderedKeys();
- for (int k = 0; k < e.length; ++k) {
- int n = uni2byte.get(e[k]);
- widths[n] = bf.getRawWidth(n, GlyphList.unicodeToName(e[k]));
- }
- Ascender = bf.getFontDescriptor(ASCENT, 1000);
- CapHeight = bf.getFontDescriptor(CAPHEIGHT, 1000);
- Descender = bf.getFontDescriptor(DESCENT, 1000);
- ItalicAngle = bf.getFontDescriptor(ITALICANGLE, 1000);
- llx = bf.getFontDescriptor(BBOXLLX, 1000);
- lly = bf.getFontDescriptor(BBOXLLY, 1000);
- urx = bf.getFontDescriptor(BBOXURX, 1000);
- ury = bf.getFontDescriptor(BBOXURY, 1000);
- }
- if (first != null && last != null && newWidths != null) {
- int f = ((PdfNumber)first).intValue();
- ArrayList ar = ((PdfArray)newWidths).getArrayList();
- for (int k = 0; k < ar.size(); ++k) {
- widths[f + k] = ((PdfNumber)ar.get(k)).intValue();
- }
- }
- fillFontDesc();
- }
-
- void fillFontDesc() {
- PdfDictionary fontDesc = (PdfDictionary)PdfReader.getPdfObject(font.get(PdfName.FONTDESCRIPTOR));
- if (fontDesc == null)
- return;
- PdfNumber v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.ASCENT));
- if (v != null)
- Ascender = v.floatValue();
- v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.CAPHEIGHT));
- if (v != null)
- CapHeight = v.floatValue();
- v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.DESCENT));
- if (v != null)
- Descender = v.floatValue();
- v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.ITALICANGLE));
- if (v != null)
- ItalicAngle = v.floatValue();
- PdfArray bbox = (PdfArray)PdfReader.getPdfObject(fontDesc.get(PdfName.FONTBBOX));
- if (bbox != null) {
- ArrayList ar = bbox.getArrayList();
- llx = ((PdfNumber)ar.get(0)).floatValue();
- lly = ((PdfNumber)ar.get(1)).floatValue();
- urx = ((PdfNumber)ar.get(2)).floatValue();
- ury = ((PdfNumber)ar.get(3)).floatValue();
- if (llx > urx) {
- float t = llx;
- llx = urx;
- urx = t;
- }
- if (lly > ury) {
- float t = lly;
- lly = ury;
- ury = t;
- }
- }
- }
-
- void fillEncoding(PdfName encoding) {
- if (PdfName.MAC_ROMAN_ENCODING.equals(encoding) || PdfName.WIN_ANSI_ENCODING.equals(encoding)) {
- byte b[] = new byte[256];
- for (int k = 0; k < 256; ++k)
- b[k] = (byte)k;
- String enc = WINANSI;
- if (PdfName.MAC_ROMAN_ENCODING.equals(encoding))
- enc = MACROMAN;
- String cv = PdfEncodings.convertToString(b, enc);
- char arr[] = cv.toCharArray();
- for (int k = 0; k < 256; ++k)
- uni2byte.put(arr[k], k);
- }
- else {
- for (int k = 0; k < 256; ++k)
- uni2byte.put(stdEnc[k], k);
- }
- }
-
- /** Gets the family name of the font. If it is a True Type font
- * each array element will have {Platform ID, Platform Encoding ID,
- * Language ID, font name}. The interpretation of this values can be
- * found in the Open Type specification, chapter 2, in the 'name' table.
- * For the other fonts the array has a single element with {"", "", "",
- * font name}.
- * @return the family name of the font
- *
- */
- public String[][] getFamilyFontName() {
- return null;
- }
-
- /** Gets the font parameter identified by key
. Valid values
- * for key
are ASCENT
, CAPHEIGHT
, DESCENT
,
- * ITALICANGLE
, BBOXLLX
, BBOXLLY
, BBOXURX
- * and BBOXURY
.
- * @param key the parameter to be extracted
- * @param fontSize the font size in points
- * @return the parameter in points
- *
- */
- public float getFontDescriptor(int key, float fontSize) {
- if (cjkMirror != null)
- return cjkMirror.getFontDescriptor(key, fontSize);
- switch (key) {
- case AWT_ASCENT:
- case ASCENT:
- return Ascender * fontSize / 1000;
- case CAPHEIGHT:
- return CapHeight * fontSize / 1000;
- case AWT_DESCENT:
- case DESCENT:
- return Descender * fontSize / 1000;
- case ITALICANGLE:
- return ItalicAngle;
- case BBOXLLX:
- return llx * fontSize / 1000;
- case BBOXLLY:
- return lly * fontSize / 1000;
- case BBOXURX:
- return urx * fontSize / 1000;
- case BBOXURY:
- return ury * fontSize / 1000;
- case AWT_LEADING:
- return 0;
- case AWT_MAXADVANCE:
- return (urx - llx) * fontSize / 1000;
- }
- return 0;
- }
-
- /** Gets the full name of the font. If it is a True Type font
- * each array element will have {Platform ID, Platform Encoding ID,
- * Language ID, font name}. The interpretation of this values can be
- * found in the Open Type specification, chapter 2, in the 'name' table.
- * For the other fonts the array has a single element with {"", "", "",
- * font name}.
- * @return the full name of the font
- *
- */
- public String[][] getFullFontName() {
- return null;
- }
-
- /** Gets the kerning between two Unicode chars.
- * @param char1 the first char
- * @param char2 the second char
- * @return the kerning to be applied
- *
- */
- public int getKerning(char char1, char char2) {
- return 0;
- }
-
- /** Gets the postscript font name.
- * @return the postscript font name
- *
- */
- public String getPostscriptFontName() {
- return fontName;
- }
-
- /** Gets the width from the font according to the Unicode char c
- * or the name
. If the name
is null it's a symbolic font.
- * @param c the unicode char
- * @param name the glyph name
- * @return the width of the char
- *
- */
- int getRawWidth(int c, String name) {
- return 0;
- }
-
- /** Checks if the font has any kerning pairs.
- * @return true
if the font has any kerning pairs
- *
- */
- public boolean hasKernPairs() {
- return false;
- }
-
- /** Outputs to the writer the font dictionaries and streams.
- * @param writer the writer for this document
- * @param ref the font indirect reference
- * @param params several parameters that depend on the font type
- * @throws IOException on error
- * @throws DocumentException error in generating the object
- *
- */
- void writeFont(PdfWriter writer, PdfIndirectReference ref, Object[] params) throws DocumentException, IOException {
- }
-
- public int getWidth(String text) {
- if (cjkMirror != null)
- return cjkMirror.getWidth(text);
- else
- return super.getWidth(text);
- }
-
- byte[] convertToBytes(String text) {
- if (cjkMirror != null)
- return PdfEncodings.convertToBytes(text, CJKFont.CJK_ENCODING);
- else {
- char cc[] = text.toCharArray();
- byte b[] = new byte[cc.length];
- for (int k = 0; k < cc.length; ++k)
- b[k] = (byte)uni2byte.get(cc[k]);
- return b;
- }
- }
-
- PdfIndirectReference getIndirectReference() {
- return refFont;
- }
-
- public boolean charExists(char c) {
- if (cjkMirror != null)
- return cjkMirror.charExists(c);
- else
- return super.charExists(c);
- }
-
- /**
- * Sets the font name that will appear in the pdf font dictionary.
- * It does nothing in this case as the font is already in the document.
- * @param name the new font name
- */
- public void setPostscriptFontName(String name) {
- }
-
- public boolean setKerning(char char1, char char2, int kern) {
- return false;
- }
-
- public int[] getCharBBox(char c) {
- return null;
- }
-
- protected int[] getRawCharBBox(int c, String name) {
- return null;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/EnumerateTTC.java pdftk-2.01/java/com/lowagie/text/pdf/EnumerateTTC.java
--- pdftk-1.45/java/com/lowagie/text/pdf/EnumerateTTC.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/EnumerateTTC.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,124 +0,0 @@
-/*
- * $Id: EnumerateTTC.java,v 1.13 2002/06/20 13:04:40 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.*;
-import java.util.HashMap;
-import com.lowagie.text.DocumentException;
-/** Enumerates all the fonts inside a True Type Collection.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-class EnumerateTTC extends TrueTypeFont{
-
- protected String[] names;
-
- EnumerateTTC(String ttcFile) throws DocumentException, IOException {
- fileName = ttcFile;
- rf = new RandomAccessFileOrArray(ttcFile);
- findNames();
- }
-
- EnumerateTTC(byte ttcArray[]) throws DocumentException, IOException {
- fileName = "Byte array TTC";
- rf = new RandomAccessFileOrArray(ttcArray);
- findNames();
- }
-
- void findNames() throws DocumentException, IOException {
- tables = new HashMap();
-
- try {
- String mainTag = readStandardString(4);
- if (!mainTag.equals("ttcf"))
- throw new DocumentException(fileName + " is not a valid TTC file.");
- rf.skipBytes(4);
- int dirCount = rf.readInt();
- names = new String[dirCount];
- int dirPos = rf.getFilePointer();
- for (int dirIdx = 0; dirIdx < dirCount; ++dirIdx) {
- tables.clear();
- rf.seek(dirPos);
- rf.skipBytes(dirIdx * 4);
- directoryOffset = rf.readInt();
- rf.seek(directoryOffset);
- if (rf.readInt() != 0x00010000)
- throw new DocumentException(fileName + " is not a valid TTF file.");
- int num_tables = rf.readUnsignedShort();
- rf.skipBytes(6);
- for (int k = 0; k < num_tables; ++k) {
- String tag = readStandardString(4);
- rf.skipBytes(4);
- int table_location[] = new int[2];
- table_location[0] = rf.readInt();
- table_location[1] = rf.readInt();
- tables.put(tag, table_location);
- }
- names[dirIdx] = getBaseFont();
- }
- }
- finally {
- if (rf != null)
- rf.close();
- }
- }
-
- String[] getNames() {
- return names;
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/ExtendedColor.java pdftk-2.01/java/com/lowagie/text/pdf/ExtendedColor.java
--- pdftk-1.45/java/com/lowagie/text/pdf/ExtendedColor.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/ExtendedColor.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,128 +0,0 @@
-/*
- * $Id: ExtendedColor.java,v 1.43 2005/03/29 14:08:15 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.awt.Color;
-/**
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class ExtendedColor extends Color{
-
- /** a type of extended color. */
- public static final int TYPE_RGB = 0;
- /** a type of extended color. */
- public static final int TYPE_GRAY = 1;
- /** a type of extended color. */
- public static final int TYPE_CMYK = 2;
- /** a type of extended color. */
- public static final int TYPE_SEPARATION = 3;
- /** a type of extended color. */
- public static final int TYPE_PATTERN = 4;
- /** a type of extended color. */
- public static final int TYPE_SHADING = 5;
-
- protected int type;
-
- /**
- * Constructs an extended color of a certain type.
- * @param type
- */
- public ExtendedColor(int type) {
- super(0, 0, 0);
- this.type = type;
- }
-
- /**
- * Constructs an extended color of a certain type and a certain color.
- * @param type
- * @param red
- * @param green
- * @param blue
- */
- public ExtendedColor(int type, float red, float green, float blue) {
- super(normalize(red), normalize(green), normalize(blue));
- this.type = type;
- }
-
- /**
- * Gets the type of this color.
- * @return one of the types (see constants)
- */
- public int getType() {
- return type;
- }
-
- /**
- * Gets the type of a given color.
- * @param color
- * @return one of the types (see constants)
- */
- public static int getType(Color color) {
- if (color instanceof ExtendedColor)
- return ((ExtendedColor)color).getType();
- return TYPE_RGB;
- }
-
- static final float normalize(float value) {
- if (value < 0)
- return 0;
- if (value > 1)
- return 1;
- return value;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/ExtraEncoding.java pdftk-2.01/java/com/lowagie/text/pdf/ExtraEncoding.java
--- pdftk-1.45/java/com/lowagie/text/pdf/ExtraEncoding.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/ExtraEncoding.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright 2003 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * Classes implementing this interface can create custom encodings or
- * replace existing ones. It is used in the context of PdfEncoding
.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public interface ExtraEncoding {
-
- /**
- * Converts an Unicode string to a byte array according to some encoding.
- * @param text the Unicode string
- * @param encoding the requested encoding. It's mainly of use if the same class
- * supports more than one encoding.
- * @return the conversion or null
if no conversion is supported
- */
- public byte[] charToByte(String text, String encoding);
-
- /**
- * Converts a byte array to an Unicode string according to some encoding.
- * @param b the input byte array
- * @param encoding the requested encoding. It's mainly of use if the same class
- * supports more than one encoding.
- * @return the conversion or null
if no conversion is supported
- */
- public String byteToChar(byte b[], String encoding);
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/FdfReader.java pdftk-2.01/java/com/lowagie/text/pdf/FdfReader.java
--- pdftk-1.45/java/com/lowagie/text/pdf/FdfReader.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/FdfReader.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,239 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * Copyright 2003 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.ArrayList;
-import java.net.URL;
-/** Reads an FDF form and makes the fields available
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class FdfReader extends PdfReader {
-
- HashMap fields;
- String fileSpec;
- PdfName encoding;
-
- /** Reads an FDF form.
- * @param filename the file name of the form
- * @throws IOException on error
- */
- public FdfReader(String filename) throws IOException {
- super(filename);
- }
-
- /** Reads an FDF form.
- * @param pdfIn the byte array with the form
- * @throws IOException on error
- */
- public FdfReader(byte pdfIn[]) throws IOException {
- super(pdfIn);
- }
-
- /** Reads an FDF form.
- * @param url the URL of the document
- * @throws IOException on error
- */
- public FdfReader(URL url) throws IOException {
- super(url);
- }
-
- /** Reads an FDF form.
- * @param is the InputStream
containing the document. The stream is read to the
- * end but is not closed
- * @throws IOException on error
- */
- public FdfReader(InputStream is) throws IOException {
- super(is);
- }
-
- protected void readPdf() throws IOException {
- fields = new HashMap();
- try {
- tokens.checkFdfHeader();
- rebuildXref();
- readDocObj();
- }
- finally {
- try {
- tokens.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- readFields();
- }
-
- protected void kidNode(PdfDictionary merged, String name) {
- PdfArray kids = (PdfArray)getPdfObject(merged.get(PdfName.KIDS));
- if (kids == null || kids.getArrayList().size() == 0) {
- if (name.length() > 0)
- name = name.substring(1);
- fields.put(name, merged);
- }
- else {
- merged.remove(PdfName.KIDS);
- ArrayList ar = kids.getArrayList();
- for (int k = 0; k < ar.size(); ++k) {
- PdfDictionary dic = new PdfDictionary();
- dic.merge(merged);
- PdfDictionary newDic = (PdfDictionary)getPdfObject((PdfObject)ar.get(k));
- PdfString t = (PdfString)getPdfObject(newDic.get(PdfName.T));
- String newName = name;
- if (t != null)
- newName += "." + t.toUnicodeString();
- dic.merge(newDic);
- dic.remove(PdfName.T);
- kidNode(dic, newName);
- }
- }
- }
-
- protected void readFields() throws IOException {
- catalog = (PdfDictionary)getPdfObject(trailer.get(PdfName.ROOT));
- PdfDictionary fdf = (PdfDictionary)getPdfObject(catalog.get(PdfName.FDF));
- PdfString fs = (PdfString)getPdfObject(fdf.get(PdfName.F));
- if (fs != null)
- fileSpec = fs.toUnicodeString();
- PdfArray fld = (PdfArray)getPdfObject(fdf.get(PdfName.FIELDS));
- if (fld == null)
- return;
- encoding = (PdfName)getPdfObject(fdf.get(PdfName.ENCODING));
- PdfDictionary merged = new PdfDictionary();
- merged.put(PdfName.KIDS, fld);
- kidNode(merged, "");
- }
-
- /** Gets all the fields. The map is keyed by the fully qualified
- * field name and the value is a merged PdfDictionary
- * with the field content.
- * @return all the fields
- */
- public HashMap getFields() {
- return fields;
- }
-
- /** Gets the field dictionary.
- * @param name the fully qualified field name
- * @return the field dictionary
- */
- public PdfDictionary getField(String name) {
- return (PdfDictionary)fields.get(name);
- }
-
- /** Gets the field value or null
if the field does not
- * exist or has no value defined.
- * @param name the fully qualified field name
- * @return the field value or null
- */
- public String getFieldValue(String name) {
- PdfDictionary field = (PdfDictionary)fields.get(name);
- if (field == null)
- return null;
- PdfObject v = getPdfObject(field.get(PdfName.V));
- if (v == null)
- return null;
- if (v.isName())
- return PdfName.decodeName(((PdfName)v).toString());
- else if (v.isString()) {
- PdfString vs = (PdfString)v;
- if (encoding == null || vs.getEncoding() != null)
- return vs.toUnicodeString();
- byte b[] = vs.getBytes();
- if (b.length >= 2 && b[0] == (byte)254 && b[1] == (byte)255)
- return vs.toUnicodeString();
- try {
- if (encoding.equals(PdfName.SHIFT_JIS))
- return new String(b, "SJIS");
- else if (encoding.equals(PdfName.UHC))
- return new String(b, "MS949");
- else if (encoding.equals(PdfName.GBK))
- return new String(b, "GBK");
- else if (encoding.equals(PdfName.BIGFIVE))
- return new String(b, "Big5");
- }
- catch (Exception e) {
- }
- return vs.toUnicodeString();
- }
- return null;
- }
-
- // ssteward
- // in a PDF, the Rich Text value of a field may be stored in
- // a string or a stream; I wonder if this applied to FDF, too?
- public String getFieldRichValue(String name) {
- PdfDictionary field = (PdfDictionary)fields.get(name);
- if (field == null)
- return null;
- PdfObject rv = getPdfObject(field.get(PdfName.RV));
- if (rv == null)
- return null;
- if (rv.isName())
- return PdfName.decodeName(((PdfName)rv).toString());
- else if (rv.isString())
- return ((PdfString)rv).toUnicodeString();
- else
- return null;
- }
-
- /** Gets the PDF file specification contained in the FDF.
- * @return the PDF file specification contained in the FDF
- */
- public String getFileSpec() {
- return fileSpec;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/FdfWriter.java pdftk-2.01/java/com/lowagie/text/pdf/FdfWriter.java
--- pdftk-1.45/java/com/lowagie/text/pdf/FdfWriter.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/FdfWriter.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,339 +0,0 @@
-/*
- * Copyright 2003 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Iterator;
-import java.util.StringTokenizer;
-
-import com.lowagie.text.DocWriter;
-import com.lowagie.text.DocumentException;
-
-/** Writes an FDF form.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class FdfWriter {
- static byte[] HEADER_FDF = DocWriter.getISOBytes("%FDF-1.2\n%\u00e2\u00e3\u00cf\u00d3"); // ssteward
- HashMap fields = new HashMap();
-
- /** The PDF file associated with the FDF. */
- private String file;
-
- /** Creates a new FdfWriter. */
- public FdfWriter() {
- }
-
- /** Writes the content to a stream.
- * @param os the stream
- * @throws DocumentException on error
- * @throws IOException on error
- */
- public void writeTo(OutputStream os) throws DocumentException, IOException {
- Wrt wrt = new Wrt(os, this);
- wrt.writeTo();
- }
-
- boolean setField(String field, PdfObject value) {
- HashMap map = fields;
- StringTokenizer tk = new StringTokenizer(field, ".");
- if (!tk.hasMoreTokens())
- return false;
- while (true) {
- String s = tk.nextToken();
- Object obj = map.get(s);
- if (tk.hasMoreTokens()) {
- if (obj == null) {
- obj = new HashMap();
- map.put(s, obj);
- map = (HashMap)obj;
- continue;
- }
- else if (obj instanceof HashMap)
- map = (HashMap)obj;
- else
- return false;
- }
- else {
- if (obj == null || !(obj instanceof HashMap)) {
- map.put(s, value);
- return true;
- }
- else
- return false;
- }
- }
- }
-
- void iterateFields(HashMap values, HashMap map, String name) {
- for (Iterator it = map.keySet().iterator(); it.hasNext();) {
- String s = (String)it.next();
- Object obj = map.get(s);
- if (obj instanceof HashMap)
- iterateFields(values, (HashMap)obj, name + "." + s);
- else
- values.put((name + "." + s).substring(1), obj);
- }
- }
-
- /** Removes the field value.
- * @param field the field name
- * @return true
if the field was found and removed,
- * false
otherwise
- */
- public boolean removeField(String field) {
- HashMap map = fields;
- StringTokenizer tk = new StringTokenizer(field, ".");
- if (!tk.hasMoreTokens())
- return false;
- ArrayList hist = new ArrayList();
- while (true) {
- String s = tk.nextToken();
- Object obj = map.get(s);
- if (obj == null)
- return false;
- hist.add(map);
- hist.add(s);
- if (tk.hasMoreTokens()) {
- if (obj instanceof HashMap)
- map = (HashMap)obj;
- else
- return false;
- }
- else {
- if (obj instanceof HashMap)
- return false;
- else
- break;
- }
- }
- for (int k = hist.size() - 2; k >= 0; k -= 2) {
- map = (HashMap)hist.get(k);
- String s = (String)hist.get(k + 1);
- map.remove(s);
- if (map.size() > 0)
- break;
- }
- return true;
- }
-
- /** Gets all the fields. The map is keyed by the fully qualified
- * field name and the values are PdfObject
.
- * @return a map with all the fields
- */
- public HashMap getFields() {
- HashMap values = new HashMap();
- iterateFields(values, fields, "");
- return values;
- }
-
- /** Gets the field value.
- * @param field the field name
- * @return the field value or null
if not found
- */
- public String getField(String field) {
- HashMap map = fields;
- StringTokenizer tk = new StringTokenizer(field, ".");
- if (!tk.hasMoreTokens())
- return null;
- while (true) {
- String s = tk.nextToken();
- Object obj = map.get(s);
- if (obj == null)
- return null;
- if (tk.hasMoreTokens()) {
- if (obj instanceof HashMap)
- map = (HashMap)obj;
- else
- return null;
- }
- else {
- if (obj instanceof HashMap)
- return null;
- else {
- if (((PdfObject)obj).isString())
- return ((PdfString)obj).toUnicodeString();
- else
- return PdfName.decodeName(obj.toString());
- }
- }
- }
- }
-
- /** Sets the field value as a name.
- * @param field the fully qualified field name
- * @param value the value
- * @return true
if the value was inserted,
- * false
if the name is incompatible with
- * an existing field
- */
- public boolean setFieldAsName(String field, String value) {
- return setField(field, new PdfName(value));
- }
-
- /** Sets the field value as a string.
- * @param field the fully qualified field name
- * @param value the value
- * @return true
if the value was inserted,
- * false
if the name is incompatible with
- * an existing field
- */
- public boolean setFieldAsString(String field, String value) {
- return setField(field, new PdfString(value /* ssteward , PdfObject.TEXT_UNICODE */ ));
- }
-
- /** Sets all the fields from this FdfReader
- * @param fdf the FdfReader
- */
- public void setFields(FdfReader fdf) {
- HashMap map = fdf.getFields();
- for (Iterator it = map.keySet().iterator(); it.hasNext();) {
- String key = (String)it.next();
- PdfDictionary dic = (PdfDictionary)map.get(key);
- PdfObject v = dic.get(PdfName.V);
- if (v != null) {
- setField(key, v);
- }
- }
- }
-
- /** Sets all the fields from this PdfReader
- * @param pdf the PdfReader
- */
- public void setFields(PdfReader pdf) {
- setFields(pdf.getAcroFields());
- }
-
- /** Sets all the fields from this AcroFields
- * @param af the AcroFields
- */
- public void setFields(AcroFields af) {
- for (Iterator it = af.getFields().entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry)it.next();
- String fn = (String)entry.getKey();
- AcroFields.Item item = (AcroFields.Item)entry.getValue();
- PdfDictionary dic = (PdfDictionary)item.merged.get(0);
- PdfObject v = PdfReader.getPdfObjectRelease(dic.get(PdfName.V));
- if (v == null)
- continue;
- PdfObject ft = PdfReader.getPdfObjectRelease(dic.get(PdfName.FT));
- if (ft == null || PdfName.SIG.equals(ft))
- continue;
- setField(fn, v);
- }
- }
-
- /** Gets the PDF file name associated with the FDF.
- * @return the PDF file name associated with the FDF
- */
- public String getFile() {
- return this.file;
- }
-
- /** Sets the PDF file name associated with the FDF.
- * @param file the PDF file name associated with the FDF
- *
- */
- public void setFile(String file) {
- this.file = file;
- }
-
- static class Wrt extends PdfWriter {
- private FdfWriter fdf;
-
- Wrt(OutputStream os, FdfWriter fdf) throws DocumentException, IOException {
- super(new PdfDocument(), os);
- this.fdf = fdf;
- this.os.write(HEADER_FDF);
- body = new PdfBody(this);
- }
-
- void writeTo() throws DocumentException, IOException {
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.FIELDS, calculate(fdf.fields));
- if (fdf.file != null)
- dic.put(PdfName.F, new PdfString(fdf.file /* ssteward, PdfObject.TEXT_UNICODE */ ));
- PdfDictionary fd = new PdfDictionary();
- fd.put(PdfName.FDF, dic);
- PdfIndirectReference ref = addToBody(fd).getIndirectReference();
- os.write(getISOBytes("\ntrailer\n")); // ssteward
- PdfDictionary trailer = new PdfDictionary();
- trailer.put(PdfName.ROOT, ref);
- trailer.toPdf(null, os);
- os.write(getISOBytes("\n%%EOF\n"));
- os.close();
- }
-
-
- PdfArray calculate(HashMap map) throws IOException {
- PdfArray ar = new PdfArray();
- for (Iterator it = map.keySet().iterator(); it.hasNext();) {
- String key = (String)it.next();
- Object v = map.get(key);
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.T, new PdfString(key /* ssteward , PdfObject.TEXT_UNICODE */));
- if (v instanceof HashMap) {
- dic.put(PdfName.KIDS, calculate((HashMap)v));
- }
- else {
- dic.put(PdfName.V, (PdfObject)v);
- }
- ar.add(dic);
- }
- return ar;
- }
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/FontDetails.java pdftk-2.01/java/com/lowagie/text/pdf/FontDetails.java
--- pdftk-1.45/java/com/lowagie/text/pdf/FontDetails.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/FontDetails.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,289 +0,0 @@
-/*
- * $Id: FontDetails.java,v 1.44 2005/05/04 14:32:23 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.ExceptionConverter;
-import java.util.HashMap;
-import java.io.UnsupportedEncodingException;
-/** Each font in the document will have an instance of this class
- * where the characters used will be represented.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-class FontDetails {
-
- /** The indirect reference to this font
- */
- PdfIndirectReference indirectReference;
- /** The font name that appears in the document body stream
- */
- PdfName fontName;
- /** The font
- */
- BaseFont baseFont;
- /** The font if its an instance of TrueTypeFontUnicode
- */
- TrueTypeFontUnicode ttu;
-
- CJKFont cjkFont;
- /** The array used with single byte encodings
- */
- byte shortTag[];
- /** The map used with double byte encodings. The key is Integer(glyph) and the
- * value is int[]{glyph, width, Unicode code}
- */
- HashMap longTag;
-
- IntHashtable cjkTag;
- /** The font type
- */
- int fontType;
- /** true
if the font is symbolic
- */
- boolean symbolic;
- /** Indicates if all the glyphs and widths for that particular
- * encoding should be included in the document.
- */
- protected boolean subset = true;
- /** Each font used in a document has an instance of this class.
- * This class stores the characters used in the document and other
- * specifics unique to the current working document.
- * @param fontName the font name
- * @param indirectReference the indirect reference to the font
- * @param baseFont the BaseFont
- */
- FontDetails(PdfName fontName, PdfIndirectReference indirectReference, BaseFont baseFont) {
- this.fontName = fontName;
- this.indirectReference = indirectReference;
- this.baseFont = baseFont;
- fontType = baseFont.getFontType();
- switch (fontType) {
- case BaseFont.FONT_TYPE_T1:
- case BaseFont.FONT_TYPE_TT:
- shortTag = new byte[256];
- break;
- case BaseFont.FONT_TYPE_CJK:
- cjkTag = new IntHashtable();
- cjkFont = (CJKFont)baseFont;
- break;
- case BaseFont.FONT_TYPE_TTUNI:
- longTag = new HashMap();
- ttu = (TrueTypeFontUnicode)baseFont;
- symbolic = baseFont.isFontSpecific();
- break;
- }
- }
-
- /** Gets the indirect reference to this font.
- * @return the indirect reference to this font
- */
- PdfIndirectReference getIndirectReference() {
- return indirectReference;
- }
-
- /** Gets the font name as it appears in the document body.
- * @return the font name
- */
- PdfName getFontName() {
- return fontName;
- }
-
- /** Gets the BaseFont
of this font.
- * @return the BaseFont
of this font
- */
- BaseFont getBaseFont() {
- return baseFont;
- }
-
- /** Converts the text into bytes to be placed in the document.
- * The conversion is done according to the font and the encoding and the characters
- * used are stored.
- * @param text the text to convert
- * @return the conversion
- */
- byte[] convertToBytes(String text) {
- byte b[] = null;
- switch (fontType) {
- case BaseFont.FONT_TYPE_T3:
- return baseFont.convertToBytes(text);
- case BaseFont.FONT_TYPE_T1:
- case BaseFont.FONT_TYPE_TT: {
- b = baseFont.convertToBytes(text);
- int len = b.length;
- for (int k = 0; k < len; ++k)
- shortTag[((int)b[k]) & 0xff] = 1;
- break;
- }
- case BaseFont.FONT_TYPE_CJK: {
- int len = text.length();
- for (int k = 0; k < len; ++k)
- cjkTag.put(cjkFont.getCidCode(text.charAt(k)), 0);
- b = baseFont.convertToBytes(text);
- break;
- }
- case BaseFont.FONT_TYPE_DOCUMENT: {
- b = baseFont.convertToBytes(text);
- break;
- }
- case BaseFont.FONT_TYPE_TTUNI: {
- try {
- int len = text.length();
- int metrics[] = null;
- char glyph[] = new char[len];
- int i = 0;
- if (symbolic) {
- b = PdfEncodings.convertToBytes(text, "symboltt");
- len = b.length;
- for (int k = 0; k < len; ++k) {
- metrics = ttu.getMetricsTT(b[k] & 0xff);
- if (metrics == null)
- continue;
- longTag.put(new Integer(metrics[0]), new int[]{metrics[0], metrics[1], ttu.getUnicodeDifferences(b[k] & 0xff)});
- glyph[i++] = (char)metrics[0];
- }
- }
- else {
- for (int k = 0; k < len; ++k) {
- char c = text.charAt(k);
- metrics = ttu.getMetricsTT(c);
- if (metrics == null)
- continue;
- int m0 = metrics[0];
- Integer gl = new Integer(m0);
- if (!longTag.containsKey(gl))
- longTag.put(gl, new int[]{m0, metrics[1], c});
- glyph[i++] = (char)m0;
- }
- }
- String s = new String(glyph, 0, i);
- b = s.getBytes(CJKFont.CJK_ENCODING);
- }
- catch (UnsupportedEncodingException e) {
- throw new ExceptionConverter(e);
- }
- break;
- }
- }
- return b;
- }
-
- /** Writes the font definition to the document.
- * @param writer the PdfWriter
of this document
- */
- void writeFont(PdfWriter writer) {
- try {
- switch (fontType) {
- case BaseFont.FONT_TYPE_T3:
- baseFont.writeFont(writer, indirectReference, null);
- break;
- case BaseFont.FONT_TYPE_T1:
- case BaseFont.FONT_TYPE_TT: {
- int firstChar;
- int lastChar;
- if (subset) {
- for (firstChar = 0; firstChar < 256; ++firstChar) {
- if (shortTag[firstChar] != 0)
- break;
- }
- for (lastChar = 255; lastChar >= firstChar; --lastChar) {
- if (shortTag[lastChar] != 0)
- break;
- }
- if (firstChar > 255) {
- firstChar = 255;
- lastChar = 255;
- }
- }
- else {
- for (int k = 0; k < shortTag.length; ++k)
- shortTag[k] = 1;
- firstChar = 0;
- lastChar = shortTag.length - 1;
- }
- baseFont.writeFont(writer, indirectReference, new Object[]{new Integer(firstChar), new Integer(lastChar), shortTag});
- break;
- }
- case BaseFont.FONT_TYPE_CJK:
- baseFont.writeFont(writer, indirectReference, new Object[]{cjkTag});
- break;
- case BaseFont.FONT_TYPE_TTUNI:
- baseFont.writeFont(writer, indirectReference, new Object[]{longTag});
- break;
- }
- }
- catch(Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /** Indicates if all the glyphs and widths for that particular
- * encoding should be included in the document.
- * @return false
to include all the glyphs and widths.
- */
- public boolean isSubset() {
- return subset;
- }
-
- /** Indicates if all the glyphs and widths for that particular
- * encoding should be included in the document. Set to false
- * to include all.
- * @param subset new value of property subset
- */
- public void setSubset(boolean subset) {
- this.subset = subset;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/FontMapper.java pdftk-2.01/java/com/lowagie/text/pdf/FontMapper.java
--- pdftk-1.45/java/com/lowagie/text/pdf/FontMapper.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/FontMapper.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright 2002 by Jeremy Bowman .
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.awt.Font;
-
-/**
- * A FontMapper implementation handles mappings between AWT Fonts and PDF
- * fonts. An interface is used instead of a fixed class because there isn't
- * an exact correlation between the font types, so each application is free
- * to define a mapping which is appropriate for it.
- */
-
-public interface FontMapper {
-
- /**
- * Returns a BaseFont which can be used to represent the given AWT Font
- *
- * @param font the font to be converted
- * @return a BaseFont which has similar properties to the provided Font
- */
-
- public BaseFont awtToPdf(Font font);
-
- /**
- * Returns an AWT Font which can be used to represent the given BaseFont
- *
- * @param font the font to be converted
- * @param size the desired point size of the resulting font
- * @return a Font which has similar properties to the provided BaseFont
- */
-
- public Font pdfToAwt(BaseFont font, int size);
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/GlyphList.java pdftk-2.01/java/com/lowagie/text/pdf/GlyphList.java
--- pdftk-1.45/java/com/lowagie/text/pdf/GlyphList.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/GlyphList.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,2206 +0,0 @@
-/*
- * $Id: GlyphList.java,v 1.20 2002/06/18 13:59:40 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.util.HashMap;
-
-public class GlyphList
-{
- private static HashMap unicode2names = new HashMap();
- private static HashMap names2unicode = new HashMap();
-
- private static final int unicode[] =
- {
- 0x0041,
- 0x00C6,
- 0x01FC,
- 0xF7E6,
- 0x00C1,
- 0xF7E1,
- 0x0102,
- 0x00C2,
- 0xF7E2,
- 0xF6C9,
- 0xF7B4,
- 0x00C4,
- 0xF7E4,
- 0x00C0,
- 0xF7E0,
- 0x0391,
- 0x0386,
- 0x0100,
- 0x0104,
- 0x00C5,
- 0x01FA,
- 0xF7E5,
- 0xF761,
- 0x00C3,
- 0xF7E3,
- 0x0042,
- 0x0392,
- 0xF6F4,
- 0xF762,
- 0x0043,
- 0x0106,
- 0xF6CA,
- 0xF6F5,
- 0x010C,
- 0x00C7,
- 0xF7E7,
- 0x0108,
- 0x010A,
- 0xF7B8,
- 0x03A7,
- 0xF6F6,
- 0xF763,
- 0x0044,
- 0x010E,
- 0x0110,
- 0x2206,
- 0x0394,
- 0xF6CB,
- 0xF6CC,
- 0xF6CD,
- 0xF7A8,
- 0xF6F7,
- 0xF764,
- 0x0045,
- 0x00C9,
- 0xF7E9,
- 0x0114,
- 0x011A,
- 0x00CA,
- 0xF7EA,
- 0x00CB,
- 0xF7EB,
- 0x0116,
- 0x00C8,
- 0xF7E8,
- 0x0112,
- 0x014A,
- 0x0118,
- 0x0395,
- 0x0388,
- 0xF765,
- 0x0397,
- 0x0389,
- 0x00D0,
- 0xF7F0,
- 0x20AC,
- 0x0046,
- 0xF766,
- 0x0047,
- 0x0393,
- 0x011E,
- 0x01E6,
- 0x011C,
- 0x0122,
- 0x0120,
- 0xF6CE,
- 0xF760,
- 0xF767,
- 0x0048,
- 0x25CF,
- 0x25AA,
- 0x25AB,
- 0x25A1,
- 0x0126,
- 0x0124,
- 0xF768,
- 0xF6CF,
- 0xF6F8,
- 0x0049,
- 0x0132,
- 0x00CD,
- 0xF7ED,
- 0x012C,
- 0x00CE,
- 0xF7EE,
- 0x00CF,
- 0xF7EF,
- 0x0130,
- 0x2111,
- 0x00CC,
- 0xF7EC,
- 0x012A,
- 0x012E,
- 0x0399,
- 0x03AA,
- 0x038A,
- 0xF769,
- 0x0128,
- 0x004A,
- 0x0134,
- 0xF76A,
- 0x004B,
- 0x039A,
- 0x0136,
- 0xF76B,
- 0x004C,
- 0xF6BF,
- 0x0139,
- 0x039B,
- 0x013D,
- 0x013B,
- 0x013F,
- 0x0141,
- 0xF6F9,
- 0xF76C,
- 0x004D,
- 0xF6D0,
- 0xF7AF,
- 0xF76D,
- 0x039C,
- 0x004E,
- 0x0143,
- 0x0147,
- 0x0145,
- 0xF76E,
- 0x00D1,
- 0xF7F1,
- 0x039D,
- 0x004F,
- 0x0152,
- 0xF6FA,
- 0x00D3,
- 0xF7F3,
- 0x014E,
- 0x00D4,
- 0xF7F4,
- 0x00D6,
- 0xF7F6,
- 0xF6FB,
- 0x00D2,
- 0xF7F2,
- 0x01A0,
- 0x0150,
- 0x014C,
- 0x2126,
- 0x03A9,
- 0x038F,
- 0x039F,
- 0x038C,
- 0x00D8,
- 0x01FE,
- 0xF7F8,
- 0xF76F,
- 0x00D5,
- 0xF7F5,
- 0x0050,
- 0x03A6,
- 0x03A0,
- 0x03A8,
- 0xF770,
- 0x0051,
- 0xF771,
- 0x0052,
- 0x0154,
- 0x0158,
- 0x0156,
- 0x211C,
- 0x03A1,
- 0xF6FC,
- 0xF772,
- 0x0053,
- 0x250C,
- 0x2514,
- 0x2510,
- 0x2518,
- 0x253C,
- 0x252C,
- 0x2534,
- 0x251C,
- 0x2524,
- 0x2500,
- 0x2502,
- 0x2561,
- 0x2562,
- 0x2556,
- 0x2555,
- 0x2563,
- 0x2551,
- 0x2557,
- 0x255D,
- 0x255C,
- 0x255B,
- 0x255E,
- 0x255F,
- 0x255A,
- 0x2554,
- 0x2569,
- 0x2566,
- 0x2560,
- 0x2550,
- 0x256C,
- 0x2567,
- 0x2568,
- 0x2564,
- 0x2565,
- 0x2559,
- 0x2558,
- 0x2552,
- 0x2553,
- 0x256B,
- 0x256A,
- 0x015A,
- 0x0160,
- 0xF6FD,
- 0x015E,
- 0xF6C1,
- 0x015C,
- 0x0218,
- 0x03A3,
- 0xF773,
- 0x0054,
- 0x03A4,
- 0x0166,
- 0x0164,
- 0x0162,
- 0x021A,
- 0x0398,
- 0x00DE,
- 0xF7FE,
- 0xF6FE,
- 0xF774,
- 0x0055,
- 0x00DA,
- 0xF7FA,
- 0x016C,
- 0x00DB,
- 0xF7FB,
- 0x00DC,
- 0xF7FC,
- 0x00D9,
- 0xF7F9,
- 0x01AF,
- 0x0170,
- 0x016A,
- 0x0172,
- 0x03A5,
- 0x03D2,
- 0x03AB,
- 0x038E,
- 0x016E,
- 0xF775,
- 0x0168,
- 0x0056,
- 0xF776,
- 0x0057,
- 0x1E82,
- 0x0174,
- 0x1E84,
- 0x1E80,
- 0xF777,
- 0x0058,
- 0x039E,
- 0xF778,
- 0x0059,
- 0x00DD,
- 0xF7FD,
- 0x0176,
- 0x0178,
- 0xF7FF,
- 0x1EF2,
- 0xF779,
- 0x005A,
- 0x0179,
- 0x017D,
- 0xF6FF,
- 0x017B,
- 0x0396,
- 0xF77A,
- 0x0061,
- 0x00E1,
- 0x0103,
- 0x00E2,
- 0x00B4,
- 0x0301,
- 0x00E4,
- 0x00E6,
- 0x01FD,
- 0x2015,
- 0x0410,
- 0x0411,
- 0x0412,
- 0x0413,
- 0x0414,
- 0x0415,
- 0x0401,
- 0x0416,
- 0x0417,
- 0x0418,
- 0x0419,
- 0x041A,
- 0x041B,
- 0x041C,
- 0x041D,
- 0x041E,
- 0x041F,
- 0x0420,
- 0x0421,
- 0x0422,
- 0x0423,
- 0x0424,
- 0x0425,
- 0x0426,
- 0x0427,
- 0x0428,
- 0x0429,
- 0x042A,
- 0x042B,
- 0x042C,
- 0x042D,
- 0x042E,
- 0x042F,
- 0x0490,
- 0x0402,
- 0x0403,
- 0x0404,
- 0x0405,
- 0x0406,
- 0x0407,
- 0x0408,
- 0x0409,
- 0x040A,
- 0x040B,
- 0x040C,
- 0x040E,
- 0xF6C4,
- 0xF6C5,
- 0x0430,
- 0x0431,
- 0x0432,
- 0x0433,
- 0x0434,
- 0x0435,
- 0x0451,
- 0x0436,
- 0x0437,
- 0x0438,
- 0x0439,
- 0x043A,
- 0x043B,
- 0x043C,
- 0x043D,
- 0x043E,
- 0x043F,
- 0x0440,
- 0x0441,
- 0x0442,
- 0x0443,
- 0x0444,
- 0x0445,
- 0x0446,
- 0x0447,
- 0x0448,
- 0x0449,
- 0x044A,
- 0x044B,
- 0x044C,
- 0x044D,
- 0x044E,
- 0x044F,
- 0x0491,
- 0x0452,
- 0x0453,
- 0x0454,
- 0x0455,
- 0x0456,
- 0x0457,
- 0x0458,
- 0x0459,
- 0x045A,
- 0x045B,
- 0x045C,
- 0x045E,
- 0x040F,
- 0x0462,
- 0x0472,
- 0x0474,
- 0xF6C6,
- 0x045F,
- 0x0463,
- 0x0473,
- 0x0475,
- 0xF6C7,
- 0xF6C8,
- 0x04D9,
- 0x200E,
- 0x200F,
- 0x200D,
- 0x066A,
- 0x060C,
- 0x0660,
- 0x0661,
- 0x0662,
- 0x0663,
- 0x0664,
- 0x0665,
- 0x0666,
- 0x0667,
- 0x0668,
- 0x0669,
- 0x061B,
- 0x061F,
- 0x0621,
- 0x0622,
- 0x0623,
- 0x0624,
- 0x0625,
- 0x0626,
- 0x0627,
- 0x0628,
- 0x0629,
- 0x062A,
- 0x062B,
- 0x062C,
- 0x062D,
- 0x062E,
- 0x062F,
- 0x0630,
- 0x0631,
- 0x0632,
- 0x0633,
- 0x0634,
- 0x0635,
- 0x0636,
- 0x0637,
- 0x0638,
- 0x0639,
- 0x063A,
- 0x0640,
- 0x0641,
- 0x0642,
- 0x0643,
- 0x0644,
- 0x0645,
- 0x0646,
- 0x0648,
- 0x0649,
- 0x064A,
- 0x064B,
- 0x064C,
- 0x064D,
- 0x064E,
- 0x064F,
- 0x0650,
- 0x0651,
- 0x0652,
- 0x0647,
- 0x06A4,
- 0x067E,
- 0x0686,
- 0x0698,
- 0x06AF,
- 0x0679,
- 0x0688,
- 0x0691,
- 0x06BA,
- 0x06D2,
- 0x06D5,
- 0x20AA,
- 0x05BE,
- 0x05C3,
- 0x05D0,
- 0x05D1,
- 0x05D2,
- 0x05D3,
- 0x05D4,
- 0x05D5,
- 0x05D6,
- 0x05D7,
- 0x05D8,
- 0x05D9,
- 0x05DA,
- 0x05DB,
- 0x05DC,
- 0x05DD,
- 0x05DE,
- 0x05DF,
- 0x05E0,
- 0x05E1,
- 0x05E2,
- 0x05E3,
- 0x05E4,
- 0x05E5,
- 0x05E6,
- 0x05E7,
- 0x05E8,
- 0x05E9,
- 0x05EA,
- 0xFB2A,
- 0xFB2B,
- 0xFB4B,
- 0xFB1F,
- 0x05F0,
- 0x05F1,
- 0x05F2,
- 0xFB35,
- 0x05B4,
- 0x05B5,
- 0x05B6,
- 0x05BB,
- 0x05B8,
- 0x05B7,
- 0x05B0,
- 0x05B2,
- 0x05B1,
- 0x05B3,
- 0x05C2,
- 0x05C1,
- 0x05B9,
- 0x05BC,
- 0x05BD,
- 0x05BF,
- 0x05C0,
- 0x02BC,
- 0x2105,
- 0x2113,
- 0x2116,
- 0x202C,
- 0x202D,
- 0x202E,
- 0x200C,
- 0x066D,
- 0x02BD,
- 0x00E0,
- 0x2135,
- 0x03B1,
- 0x03AC,
- 0x0101,
- 0x0026,
- 0xF726,
- 0x2220,
- 0x2329,
- 0x232A,
- 0x0387,
- 0x0105,
- 0x2248,
- 0x00E5,
- 0x01FB,
- 0x2194,
- 0x21D4,
- 0x21D3,
- 0x21D0,
- 0x21D2,
- 0x21D1,
- 0x2193,
- 0xF8E7,
- 0x2190,
- 0x2192,
- 0x2191,
- 0x2195,
- 0x21A8,
- 0xF8E6,
- 0x005E,
- 0x007E,
- 0x002A,
- 0x2217,
- 0xF6E9,
- 0x0040,
- 0x00E3,
- 0x0062,
- 0x005C,
- 0x007C,
- 0x03B2,
- 0x2588,
- 0xF8F4,
- 0x007B,
- 0xF8F3,
- 0xF8F2,
- 0xF8F1,
- 0x007D,
- 0xF8FE,
- 0xF8FD,
- 0xF8FC,
- 0x005B,
- 0xF8F0,
- 0xF8EF,
- 0xF8EE,
- 0x005D,
- 0xF8FB,
- 0xF8FA,
- 0xF8F9,
- 0x02D8,
- 0x00A6,
- 0xF6EA,
- 0x2022,
- 0x0063,
- 0x0107,
- 0x02C7,
- 0x21B5,
- 0x010D,
- 0x00E7,
- 0x0109,
- 0x010B,
- 0x00B8,
- 0x00A2,
- 0xF6DF,
- 0xF7A2,
- 0xF6E0,
- 0x03C7,
- 0x25CB,
- 0x2297,
- 0x2295,
- 0x02C6,
- 0x2663,
- 0x003A,
- 0x20A1,
- 0x002C,
- 0xF6C3,
- 0xF6E1,
- 0xF6E2,
- 0x2245,
- 0x00A9,
- 0xF8E9,
- 0xF6D9,
- 0x00A4,
- 0xF6D1,
- 0xF6D2,
- 0xF6D4,
- 0xF6D5,
- 0x0064,
- 0x2020,
- 0x2021,
- 0xF6D3,
- 0xF6D6,
- 0x010F,
- 0x0111,
- 0x00B0,
- 0x03B4,
- 0x2666,
- 0x00A8,
- 0xF6D7,
- 0xF6D8,
- 0x0385,
- 0x00F7,
- 0x2593,
- 0x2584,
- 0x0024,
- 0xF6E3,
- 0xF724,
- 0xF6E4,
- 0x20AB,
- 0x02D9,
- 0x0323,
- 0x0131,
- 0xF6BE,
- 0x22C5,
- 0xF6EB,
- 0x0065,
- 0x00E9,
- 0x0115,
- 0x011B,
- 0x00EA,
- 0x00EB,
- 0x0117,
- 0x00E8,
- 0x0038,
- 0x2088,
- 0xF738,
- 0x2078,
- 0x2208,
- 0x2026,
- 0x0113,
- 0x2014,
- 0x2205,
- 0x2013,
- 0x014B,
- 0x0119,
- 0x03B5,
- 0x03AD,
- 0x003D,
- 0x2261,
- 0x212E,
- 0xF6EC,
- 0x03B7,
- 0x03AE,
- 0x00F0,
- 0x0021,
- 0x203C,
- 0x00A1,
- 0xF7A1,
- 0xF721,
- 0x2203,
- 0x0066,
- 0x2640,
- 0xFB00,
- 0xFB03,
- 0xFB04,
- 0xFB01,
- 0x2012,
- 0x25A0,
- 0x25AC,
- 0x0035,
- 0x215D,
- 0x2085,
- 0xF735,
- 0x2075,
- 0xFB02,
- 0x0192,
- 0x0034,
- 0x2084,
- 0xF734,
- 0x2074,
- 0x2044,
- 0x2215,
- 0x20A3,
- 0x0067,
- 0x03B3,
- 0x011F,
- 0x01E7,
- 0x011D,
- 0x0123,
- 0x0121,
- 0x00DF,
- 0x2207,
- 0x0060,
- 0x0300,
- 0x003E,
- 0x2265,
- 0x00AB,
- 0x00BB,
- 0x2039,
- 0x203A,
- 0x0068,
- 0x0127,
- 0x0125,
- 0x2665,
- 0x0309,
- 0x2302,
- 0x02DD,
- 0x002D,
- 0x00AD,
- 0xF6E5,
- 0xF6E6,
- 0x0069,
- 0x00ED,
- 0x012D,
- 0x00EE,
- 0x00EF,
- 0x00EC,
- 0x0133,
- 0x012B,
- 0x221E,
- 0x222B,
- 0x2321,
- 0xF8F5,
- 0x2320,
- 0x2229,
- 0x25D8,
- 0x25D9,
- 0x263B,
- 0x012F,
- 0x03B9,
- 0x03CA,
- 0x0390,
- 0x03AF,
- 0xF6ED,
- 0x0129,
- 0x006A,
- 0x0135,
- 0x006B,
- 0x03BA,
- 0x0137,
- 0x0138,
- 0x006C,
- 0x013A,
- 0x03BB,
- 0x013E,
- 0x013C,
- 0x0140,
- 0x003C,
- 0x2264,
- 0x258C,
- 0x20A4,
- 0xF6C0,
- 0x2227,
- 0x00AC,
- 0x2228,
- 0x017F,
- 0x25CA,
- 0x0142,
- 0xF6EE,
- 0x2591,
- 0x006D,
- 0x00AF,
- 0x02C9,
- 0x2642,
- 0x2212,
- 0x2032,
- 0xF6EF,
- 0x00B5,
- 0x03BC,
- 0x00D7,
- 0x266A,
- 0x266B,
- 0x006E,
- 0x0144,
- 0x0149,
- 0x0148,
- 0x0146,
- 0x0039,
- 0x2089,
- 0xF739,
- 0x2079,
- 0x2209,
- 0x2260,
- 0x2284,
- 0x207F,
- 0x00F1,
- 0x03BD,
- 0x0023,
- 0x006F,
- 0x00F3,
- 0x014F,
- 0x00F4,
- 0x00F6,
- 0x0153,
- 0x02DB,
- 0x00F2,
- 0x01A1,
- 0x0151,
- 0x014D,
- 0x03C9,
- 0x03D6,
- 0x03CE,
- 0x03BF,
- 0x03CC,
- 0x0031,
- 0x2024,
- 0x215B,
- 0xF6DC,
- 0x00BD,
- 0x2081,
- 0xF731,
- 0x00BC,
- 0x00B9,
- 0x2153,
- 0x25E6,
- 0x00AA,
- 0x00BA,
- 0x221F,
- 0x00F8,
- 0x01FF,
- 0xF6F0,
- 0x00F5,
- 0x0070,
- 0x00B6,
- 0x0028,
- 0xF8ED,
- 0xF8EC,
- 0x208D,
- 0x207D,
- 0xF8EB,
- 0x0029,
- 0xF8F8,
- 0xF8F7,
- 0x208E,
- 0x207E,
- 0xF8F6,
- 0x2202,
- 0x0025,
- 0x002E,
- 0x00B7,
- 0x2219,
- 0xF6E7,
- 0xF6E8,
- 0x22A5,
- 0x2030,
- 0x20A7,
- 0x03C6,
- 0x03D5,
- 0x03C0,
- 0x002B,
- 0x00B1,
- 0x211E,
- 0x220F,
- 0x2282,
- 0x2283,
- 0x221D,
- 0x03C8,
- 0x0071,
- 0x003F,
- 0x00BF,
- 0xF7BF,
- 0xF73F,
- 0x0022,
- 0x201E,
- 0x201C,
- 0x201D,
- 0x2018,
- 0x201B,
- 0x2019,
- 0x201A,
- 0x0027,
- 0x0072,
- 0x0155,
- 0x221A,
- 0xF8E5,
- 0x0159,
- 0x0157,
- 0x2286,
- 0x2287,
- 0x00AE,
- 0xF8E8,
- 0xF6DA,
- 0x2310,
- 0x03C1,
- 0x02DA,
- 0xF6F1,
- 0x2590,
- 0xF6DD,
- 0x0073,
- 0x015B,
- 0x0161,
- 0x015F,
- 0xF6C2,
- 0x015D,
- 0x0219,
- 0x2033,
- 0x00A7,
- 0x003B,
- 0x0037,
- 0x215E,
- 0x2087,
- 0xF737,
- 0x2077,
- 0x2592,
- 0x03C3,
- 0x03C2,
- 0x223C,
- 0x0036,
- 0x2086,
- 0xF736,
- 0x2076,
- 0x002F,
- 0x263A,
- 0x0020,
- 0x00A0,
- 0x2660,
- 0xF6F2,
- 0x00A3,
- 0x220B,
- 0x2211,
- 0x263C,
- 0x0074,
- 0x03C4,
- 0x0167,
- 0x0165,
- 0x0163,
- 0x021B,
- 0x2234,
- 0x03B8,
- 0x03D1,
- 0x00FE,
- 0x0033,
- 0x215C,
- 0x2083,
- 0xF733,
- 0x00BE,
- 0xF6DE,
- 0x00B3,
- 0x02DC,
- 0x0303,
- 0x0384,
- 0x2122,
- 0xF8EA,
- 0xF6DB,
- 0x25BC,
- 0x25C4,
- 0x25BA,
- 0x25B2,
- 0xF6F3,
- 0x0032,
- 0x2025,
- 0x2082,
- 0xF732,
- 0x00B2,
- 0x2154,
- 0x0075,
- 0x00FA,
- 0x016D,
- 0x00FB,
- 0x00FC,
- 0x00F9,
- 0x01B0,
- 0x0171,
- 0x016B,
- 0x005F,
- 0x2017,
- 0x222A,
- 0x2200,
- 0x0173,
- 0x2580,
- 0x03C5,
- 0x03CB,
- 0x03B0,
- 0x03CD,
- 0x016F,
- 0x0169,
- 0x0076,
- 0x0077,
- 0x1E83,
- 0x0175,
- 0x1E85,
- 0x2118,
- 0x1E81,
- 0x0078,
- 0x03BE,
- 0x0079,
- 0x00FD,
- 0x0177,
- 0x00FF,
- 0x00A5,
- 0x1EF3,
- 0x007A,
- 0x017A,
- 0x017E,
- 0x017C,
- 0x0030,
- 0x2080,
- 0xF730,
- 0x2070,
- 0x03B6
- };
-
- private static final String names[] =
- {
- "A",
- "AE",
- "AEacute",
- "AEsmall",
- "Aacute",
- "Aacutesmall",
- "Abreve",
- "Acircumflex",
- "Acircumflexsmall",
- "Acute",
- "Acutesmall",
- "Adieresis",
- "Adieresissmall",
- "Agrave",
- "Agravesmall",
- "Alpha",
- "Alphatonos",
- "Amacron",
- "Aogonek",
- "Aring",
- "Aringacute",
- "Aringsmall",
- "Asmall",
- "Atilde",
- "Atildesmall",
- "B",
- "Beta",
- "Brevesmall",
- "Bsmall",
- "C",
- "Cacute",
- "Caron",
- "Caronsmall",
- "Ccaron",
- "Ccedilla",
- "Ccedillasmall",
- "Ccircumflex",
- "Cdotaccent",
- "Cedillasmall",
- "Chi",
- "Circumflexsmall",
- "Csmall",
- "D",
- "Dcaron",
- "Dcroat",
- "Delta",
- "Delta",
- "Dieresis",
- "DieresisAcute",
- "DieresisGrave",
- "Dieresissmall",
- "Dotaccentsmall",
- "Dsmall",
- "E",
- "Eacute",
- "Eacutesmall",
- "Ebreve",
- "Ecaron",
- "Ecircumflex",
- "Ecircumflexsmall",
- "Edieresis",
- "Edieresissmall",
- "Edotaccent",
- "Egrave",
- "Egravesmall",
- "Emacron",
- "Eng",
- "Eogonek",
- "Epsilon",
- "Epsilontonos",
- "Esmall",
- "Eta",
- "Etatonos",
- "Eth",
- "Ethsmall",
- "Euro",
- "F",
- "Fsmall",
- "G",
- "Gamma",
- "Gbreve",
- "Gcaron",
- "Gcircumflex",
- "Gcommaaccent",
- "Gdotaccent",
- "Grave",
- "Gravesmall",
- "Gsmall",
- "H",
- "H18533",
- "H18543",
- "H18551",
- "H22073",
- "Hbar",
- "Hcircumflex",
- "Hsmall",
- "Hungarumlaut",
- "Hungarumlautsmall",
- "I",
- "IJ",
- "Iacute",
- "Iacutesmall",
- "Ibreve",
- "Icircumflex",
- "Icircumflexsmall",
- "Idieresis",
- "Idieresissmall",
- "Idotaccent",
- "Ifraktur",
- "Igrave",
- "Igravesmall",
- "Imacron",
- "Iogonek",
- "Iota",
- "Iotadieresis",
- "Iotatonos",
- "Ismall",
- "Itilde",
- "J",
- "Jcircumflex",
- "Jsmall",
- "K",
- "Kappa",
- "Kcommaaccent",
- "Ksmall",
- "L",
- "LL",
- "Lacute",
- "Lambda",
- "Lcaron",
- "Lcommaaccent",
- "Ldot",
- "Lslash",
- "Lslashsmall",
- "Lsmall",
- "M",
- "Macron",
- "Macronsmall",
- "Msmall",
- "Mu",
- "N",
- "Nacute",
- "Ncaron",
- "Ncommaaccent",
- "Nsmall",
- "Ntilde",
- "Ntildesmall",
- "Nu",
- "O",
- "OE",
- "OEsmall",
- "Oacute",
- "Oacutesmall",
- "Obreve",
- "Ocircumflex",
- "Ocircumflexsmall",
- "Odieresis",
- "Odieresissmall",
- "Ogoneksmall",
- "Ograve",
- "Ogravesmall",
- "Ohorn",
- "Ohungarumlaut",
- "Omacron",
- "Omega",
- "Omega",
- "Omegatonos",
- "Omicron",
- "Omicrontonos",
- "Oslash",
- "Oslashacute",
- "Oslashsmall",
- "Osmall",
- "Otilde",
- "Otildesmall",
- "P",
- "Phi",
- "Pi",
- "Psi",
- "Psmall",
- "Q",
- "Qsmall",
- "R",
- "Racute",
- "Rcaron",
- "Rcommaaccent",
- "Rfraktur",
- "Rho",
- "Ringsmall",
- "Rsmall",
- "S",
- "SF010000",
- "SF020000",
- "SF030000",
- "SF040000",
- "SF050000",
- "SF060000",
- "SF070000",
- "SF080000",
- "SF090000",
- "SF100000",
- "SF110000",
- "SF190000",
- "SF200000",
- "SF210000",
- "SF220000",
- "SF230000",
- "SF240000",
- "SF250000",
- "SF260000",
- "SF270000",
- "SF280000",
- "SF360000",
- "SF370000",
- "SF380000",
- "SF390000",
- "SF400000",
- "SF410000",
- "SF420000",
- "SF430000",
- "SF440000",
- "SF450000",
- "SF460000",
- "SF470000",
- "SF480000",
- "SF490000",
- "SF500000",
- "SF510000",
- "SF520000",
- "SF530000",
- "SF540000",
- "Sacute",
- "Scaron",
- "Scaronsmall",
- "Scedilla",
- "Scedilla",
- "Scircumflex",
- "Scommaaccent",
- "Sigma",
- "Ssmall",
- "T",
- "Tau",
- "Tbar",
- "Tcaron",
- "Tcommaaccent",
- "Tcommaaccent",
- "Theta",
- "Thorn",
- "Thornsmall",
- "Tildesmall",
- "Tsmall",
- "U",
- "Uacute",
- "Uacutesmall",
- "Ubreve",
- "Ucircumflex",
- "Ucircumflexsmall",
- "Udieresis",
- "Udieresissmall",
- "Ugrave",
- "Ugravesmall",
- "Uhorn",
- "Uhungarumlaut",
- "Umacron",
- "Uogonek",
- "Upsilon",
- "Upsilon1",
- "Upsilondieresis",
- "Upsilontonos",
- "Uring",
- "Usmall",
- "Utilde",
- "V",
- "Vsmall",
- "W",
- "Wacute",
- "Wcircumflex",
- "Wdieresis",
- "Wgrave",
- "Wsmall",
- "X",
- "Xi",
- "Xsmall",
- "Y",
- "Yacute",
- "Yacutesmall",
- "Ycircumflex",
- "Ydieresis",
- "Ydieresissmall",
- "Ygrave",
- "Ysmall",
- "Z",
- "Zacute",
- "Zcaron",
- "Zcaronsmall",
- "Zdotaccent",
- "Zeta",
- "Zsmall",
- "a",
- "aacute",
- "abreve",
- "acircumflex",
- "acute",
- "acutecomb",
- "adieresis",
- "ae",
- "aeacute",
- "afii00208",
- "afii10017",
- "afii10018",
- "afii10019",
- "afii10020",
- "afii10021",
- "afii10022",
- "afii10023",
- "afii10024",
- "afii10025",
- "afii10026",
- "afii10027",
- "afii10028",
- "afii10029",
- "afii10030",
- "afii10031",
- "afii10032",
- "afii10033",
- "afii10034",
- "afii10035",
- "afii10036",
- "afii10037",
- "afii10038",
- "afii10039",
- "afii10040",
- "afii10041",
- "afii10042",
- "afii10043",
- "afii10044",
- "afii10045",
- "afii10046",
- "afii10047",
- "afii10048",
- "afii10049",
- "afii10050",
- "afii10051",
- "afii10052",
- "afii10053",
- "afii10054",
- "afii10055",
- "afii10056",
- "afii10057",
- "afii10058",
- "afii10059",
- "afii10060",
- "afii10061",
- "afii10062",
- "afii10063",
- "afii10064",
- "afii10065",
- "afii10066",
- "afii10067",
- "afii10068",
- "afii10069",
- "afii10070",
- "afii10071",
- "afii10072",
- "afii10073",
- "afii10074",
- "afii10075",
- "afii10076",
- "afii10077",
- "afii10078",
- "afii10079",
- "afii10080",
- "afii10081",
- "afii10082",
- "afii10083",
- "afii10084",
- "afii10085",
- "afii10086",
- "afii10087",
- "afii10088",
- "afii10089",
- "afii10090",
- "afii10091",
- "afii10092",
- "afii10093",
- "afii10094",
- "afii10095",
- "afii10096",
- "afii10097",
- "afii10098",
- "afii10099",
- "afii10100",
- "afii10101",
- "afii10102",
- "afii10103",
- "afii10104",
- "afii10105",
- "afii10106",
- "afii10107",
- "afii10108",
- "afii10109",
- "afii10110",
- "afii10145",
- "afii10146",
- "afii10147",
- "afii10148",
- "afii10192",
- "afii10193",
- "afii10194",
- "afii10195",
- "afii10196",
- "afii10831",
- "afii10832",
- "afii10846",
- "afii299",
- "afii300",
- "afii301",
- "afii57381",
- "afii57388",
- "afii57392",
- "afii57393",
- "afii57394",
- "afii57395",
- "afii57396",
- "afii57397",
- "afii57398",
- "afii57399",
- "afii57400",
- "afii57401",
- "afii57403",
- "afii57407",
- "afii57409",
- "afii57410",
- "afii57411",
- "afii57412",
- "afii57413",
- "afii57414",
- "afii57415",
- "afii57416",
- "afii57417",
- "afii57418",
- "afii57419",
- "afii57420",
- "afii57421",
- "afii57422",
- "afii57423",
- "afii57424",
- "afii57425",
- "afii57426",
- "afii57427",
- "afii57428",
- "afii57429",
- "afii57430",
- "afii57431",
- "afii57432",
- "afii57433",
- "afii57434",
- "afii57440",
- "afii57441",
- "afii57442",
- "afii57443",
- "afii57444",
- "afii57445",
- "afii57446",
- "afii57448",
- "afii57449",
- "afii57450",
- "afii57451",
- "afii57452",
- "afii57453",
- "afii57454",
- "afii57455",
- "afii57456",
- "afii57457",
- "afii57458",
- "afii57470",
- "afii57505",
- "afii57506",
- "afii57507",
- "afii57508",
- "afii57509",
- "afii57511",
- "afii57512",
- "afii57513",
- "afii57514",
- "afii57519",
- "afii57534",
- "afii57636",
- "afii57645",
- "afii57658",
- "afii57664",
- "afii57665",
- "afii57666",
- "afii57667",
- "afii57668",
- "afii57669",
- "afii57670",
- "afii57671",
- "afii57672",
- "afii57673",
- "afii57674",
- "afii57675",
- "afii57676",
- "afii57677",
- "afii57678",
- "afii57679",
- "afii57680",
- "afii57681",
- "afii57682",
- "afii57683",
- "afii57684",
- "afii57685",
- "afii57686",
- "afii57687",
- "afii57688",
- "afii57689",
- "afii57690",
- "afii57694",
- "afii57695",
- "afii57700",
- "afii57705",
- "afii57716",
- "afii57717",
- "afii57718",
- "afii57723",
- "afii57793",
- "afii57794",
- "afii57795",
- "afii57796",
- "afii57797",
- "afii57798",
- "afii57799",
- "afii57800",
- "afii57801",
- "afii57802",
- "afii57803",
- "afii57804",
- "afii57806",
- "afii57807",
- "afii57839",
- "afii57841",
- "afii57842",
- "afii57929",
- "afii61248",
- "afii61289",
- "afii61352",
- "afii61573",
- "afii61574",
- "afii61575",
- "afii61664",
- "afii63167",
- "afii64937",
- "agrave",
- "aleph",
- "alpha",
- "alphatonos",
- "amacron",
- "ampersand",
- "ampersandsmall",
- "angle",
- "angleleft",
- "angleright",
- "anoteleia",
- "aogonek",
- "approxequal",
- "aring",
- "aringacute",
- "arrowboth",
- "arrowdblboth",
- "arrowdbldown",
- "arrowdblleft",
- "arrowdblright",
- "arrowdblup",
- "arrowdown",
- "arrowhorizex",
- "arrowleft",
- "arrowright",
- "arrowup",
- "arrowupdn",
- "arrowupdnbse",
- "arrowvertex",
- "asciicircum",
- "asciitilde",
- "asterisk",
- "asteriskmath",
- "asuperior",
- "at",
- "atilde",
- "b",
- "backslash",
- "bar",
- "beta",
- "block",
- "braceex",
- "braceleft",
- "braceleftbt",
- "braceleftmid",
- "bracelefttp",
- "braceright",
- "bracerightbt",
- "bracerightmid",
- "bracerighttp",
- "bracketleft",
- "bracketleftbt",
- "bracketleftex",
- "bracketlefttp",
- "bracketright",
- "bracketrightbt",
- "bracketrightex",
- "bracketrighttp",
- "breve",
- "brokenbar",
- "bsuperior",
- "bullet",
- "c",
- "cacute",
- "caron",
- "carriagereturn",
- "ccaron",
- "ccedilla",
- "ccircumflex",
- "cdotaccent",
- "cedilla",
- "cent",
- "centinferior",
- "centoldstyle",
- "centsuperior",
- "chi",
- "circle",
- "circlemultiply",
- "circleplus",
- "circumflex",
- "club",
- "colon",
- "colonmonetary",
- "comma",
- "commaaccent",
- "commainferior",
- "commasuperior",
- "congruent",
- "copyright",
- "copyrightsans",
- "copyrightserif",
- "currency",
- "cyrBreve",
- "cyrFlex",
- "cyrbreve",
- "cyrflex",
- "d",
- "dagger",
- "daggerdbl",
- "dblGrave",
- "dblgrave",
- "dcaron",
- "dcroat",
- "degree",
- "delta",
- "diamond",
- "dieresis",
- "dieresisacute",
- "dieresisgrave",
- "dieresistonos",
- "divide",
- "dkshade",
- "dnblock",
- "dollar",
- "dollarinferior",
- "dollaroldstyle",
- "dollarsuperior",
- "dong",
- "dotaccent",
- "dotbelowcomb",
- "dotlessi",
- "dotlessj",
- "dotmath",
- "dsuperior",
- "e",
- "eacute",
- "ebreve",
- "ecaron",
- "ecircumflex",
- "edieresis",
- "edotaccent",
- "egrave",
- "eight",
- "eightinferior",
- "eightoldstyle",
- "eightsuperior",
- "element",
- "ellipsis",
- "emacron",
- "emdash",
- "emptyset",
- "endash",
- "eng",
- "eogonek",
- "epsilon",
- "epsilontonos",
- "equal",
- "equivalence",
- "estimated",
- "esuperior",
- "eta",
- "etatonos",
- "eth",
- "exclam",
- "exclamdbl",
- "exclamdown",
- "exclamdownsmall",
- "exclamsmall",
- "existential",
- "f",
- "female",
- "ff",
- "ffi",
- "ffl",
- "fi",
- "figuredash",
- "filledbox",
- "filledrect",
- "five",
- "fiveeighths",
- "fiveinferior",
- "fiveoldstyle",
- "fivesuperior",
- "fl",
- "florin",
- "four",
- "fourinferior",
- "fouroldstyle",
- "foursuperior",
- "fraction",
- "fraction",
- "franc",
- "g",
- "gamma",
- "gbreve",
- "gcaron",
- "gcircumflex",
- "gcommaaccent",
- "gdotaccent",
- "germandbls",
- "gradient",
- "grave",
- "gravecomb",
- "greater",
- "greaterequal",
- "guillemotleft",
- "guillemotright",
- "guilsinglleft",
- "guilsinglright",
- "h",
- "hbar",
- "hcircumflex",
- "heart",
- "hookabovecomb",
- "house",
- "hungarumlaut",
- "hyphen",
- "hyphen",
- "hypheninferior",
- "hyphensuperior",
- "i",
- "iacute",
- "ibreve",
- "icircumflex",
- "idieresis",
- "igrave",
- "ij",
- "imacron",
- "infinity",
- "integral",
- "integralbt",
- "integralex",
- "integraltp",
- "intersection",
- "invbullet",
- "invcircle",
- "invsmileface",
- "iogonek",
- "iota",
- "iotadieresis",
- "iotadieresistonos",
- "iotatonos",
- "isuperior",
- "itilde",
- "j",
- "jcircumflex",
- "k",
- "kappa",
- "kcommaaccent",
- "kgreenlandic",
- "l",
- "lacute",
- "lambda",
- "lcaron",
- "lcommaaccent",
- "ldot",
- "less",
- "lessequal",
- "lfblock",
- "lira",
- "ll",
- "logicaland",
- "logicalnot",
- "logicalor",
- "longs",
- "lozenge",
- "lslash",
- "lsuperior",
- "ltshade",
- "m",
- "macron",
- "macron",
- "male",
- "minus",
- "minute",
- "msuperior",
- "mu",
- "mu",
- "multiply",
- "musicalnote",
- "musicalnotedbl",
- "n",
- "nacute",
- "napostrophe",
- "ncaron",
- "ncommaaccent",
- "nine",
- "nineinferior",
- "nineoldstyle",
- "ninesuperior",
- "notelement",
- "notequal",
- "notsubset",
- "nsuperior",
- "ntilde",
- "nu",
- "numbersign",
- "o",
- "oacute",
- "obreve",
- "ocircumflex",
- "odieresis",
- "oe",
- "ogonek",
- "ograve",
- "ohorn",
- "ohungarumlaut",
- "omacron",
- "omega",
- "omega1",
- "omegatonos",
- "omicron",
- "omicrontonos",
- "one",
- "onedotenleader",
- "oneeighth",
- "onefitted",
- "onehalf",
- "oneinferior",
- "oneoldstyle",
- "onequarter",
- "onesuperior",
- "onethird",
- "openbullet",
- "ordfeminine",
- "ordmasculine",
- "orthogonal",
- "oslash",
- "oslashacute",
- "osuperior",
- "otilde",
- "p",
- "paragraph",
- "parenleft",
- "parenleftbt",
- "parenleftex",
- "parenleftinferior",
- "parenleftsuperior",
- "parenlefttp",
- "parenright",
- "parenrightbt",
- "parenrightex",
- "parenrightinferior",
- "parenrightsuperior",
- "parenrighttp",
- "partialdiff",
- "percent",
- "period",
- "periodcentered",
- "periodcentered",
- "periodinferior",
- "periodsuperior",
- "perpendicular",
- "perthousand",
- "peseta",
- "phi",
- "phi1",
- "pi",
- "plus",
- "plusminus",
- "prescription",
- "product",
- "propersubset",
- "propersuperset",
- "proportional",
- "psi",
- "q",
- "question",
- "questiondown",
- "questiondownsmall",
- "questionsmall",
- "quotedbl",
- "quotedblbase",
- "quotedblleft",
- "quotedblright",
- "quoteleft",
- "quotereversed",
- "quoteright",
- "quotesinglbase",
- "quotesingle",
- "r",
- "racute",
- "radical",
- "radicalex",
- "rcaron",
- "rcommaaccent",
- "reflexsubset",
- "reflexsuperset",
- "registered",
- "registersans",
- "registerserif",
- "revlogicalnot",
- "rho",
- "ring",
- "rsuperior",
- "rtblock",
- "rupiah",
- "s",
- "sacute",
- "scaron",
- "scedilla",
- "scedilla",
- "scircumflex",
- "scommaaccent",
- "second",
- "section",
- "semicolon",
- "seven",
- "seveneighths",
- "seveninferior",
- "sevenoldstyle",
- "sevensuperior",
- "shade",
- "sigma",
- "sigma1",
- "similar",
- "six",
- "sixinferior",
- "sixoldstyle",
- "sixsuperior",
- "slash",
- "smileface",
- "space",
- "space",
- "spade",
- "ssuperior",
- "sterling",
- "suchthat",
- "summation",
- "sun",
- "t",
- "tau",
- "tbar",
- "tcaron",
- "tcommaaccent",
- "tcommaaccent",
- "therefore",
- "theta",
- "theta1",
- "thorn",
- "three",
- "threeeighths",
- "threeinferior",
- "threeoldstyle",
- "threequarters",
- "threequartersemdash",
- "threesuperior",
- "tilde",
- "tildecomb",
- "tonos",
- "trademark",
- "trademarksans",
- "trademarkserif",
- "triagdn",
- "triaglf",
- "triagrt",
- "triagup",
- "tsuperior",
- "two",
- "twodotenleader",
- "twoinferior",
- "twooldstyle",
- "twosuperior",
- "twothirds",
- "u",
- "uacute",
- "ubreve",
- "ucircumflex",
- "udieresis",
- "ugrave",
- "uhorn",
- "uhungarumlaut",
- "umacron",
- "underscore",
- "underscoredbl",
- "union",
- "universal",
- "uogonek",
- "upblock",
- "upsilon",
- "upsilondieresis",
- "upsilondieresistonos",
- "upsilontonos",
- "uring",
- "utilde",
- "v",
- "w",
- "wacute",
- "wcircumflex",
- "wdieresis",
- "weierstrass",
- "wgrave",
- "x",
- "xi",
- "y",
- "yacute",
- "ycircumflex",
- "ydieresis",
- "yen",
- "ygrave",
- "z",
- "zacute",
- "zcaron",
- "zdotaccent",
- "zero",
- "zeroinferior",
- "zerooldstyle",
- "zerosuperior",
- "zeta"
- };
-
- static
- {
- for (int k = 0; k < unicode.length; ++k)
- {
- Integer num = new Integer(unicode[k]);
- unicode2names.put(num, names[k]);
- int code[] = (int[])names2unicode.get(names[k]);
- if (code == null)
- {
- names2unicode.put(names[k], new int[]{unicode[k]});
- }
- else
- {
- int code2[] = new int[code.length + 1];
- System.arraycopy(code, 0, code2, 0, code.length);
- code2[code.length] = unicode[k];
- names2unicode.put(names[k], code2);
- }
- }
- }
-
- public static int[] nameToUnicode(String name)
- {
- return (int[])names2unicode.get(name);
- }
-
- public static String unicodeToName(int num)
- {
- return (String)unicode2names.get(new Integer(num));
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/GrayColor.java pdftk-2.01/java/com/lowagie/text/pdf/GrayColor.java
--- pdftk-1.45/java/com/lowagie/text/pdf/GrayColor.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/GrayColor.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,80 +0,0 @@
-/*
- * $Id: GrayColor.java,v 1.10 2002/06/18 13:59:40 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class GrayColor extends ExtendedColor {
-
- float gray;
-
- public GrayColor(int intGray) {
- this((float)intGray / 255f);
- }
-
- public GrayColor(float floatGray) {
- super(TYPE_GRAY, floatGray, floatGray, floatGray);
- gray = normalize(floatGray);
- }
-
- public float getGray() {
- return gray;
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/HyphenationEvent.java pdftk-2.01/java/com/lowagie/text/pdf/HyphenationEvent.java
--- pdftk-1.45/java/com/lowagie/text/pdf/HyphenationEvent.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/HyphenationEvent.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/** Called by Chunk
to hyphenate a word.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public interface HyphenationEvent {
-
- /** Gets the hyphen symbol.
- * @return the hyphen symbol
- */
- public String getHyphenSymbol();
-
- /** Hyphenates a word and returns the first part of it. To get
- * the second part of the hyphenated word call getHyphenatedWordPost()
.
- * @param word the word to hyphenate
- * @param font the font used by this word
- * @param fontSize the font size used by this word
- * @param remainingWidth the width available to fit this word in
- * @return the first part of the hyphenated word including
- * the hyphen symbol, if any
- */
- public String getHyphenatedWordPre(String word, BaseFont font, float fontSize, float remainingWidth);
-
- /** Gets the second part of the hyphenated word. Must be called
- * after getHyphenatedWordPre()
.
- * @return the second part of the hyphenated word
- */
- public String getHyphenatedWordPost();
-}
-
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/ICC_Profile.java pdftk-2.01/java/com/lowagie/text/pdf/ICC_Profile.java
--- pdftk-1.45/java/com/lowagie/text/pdf/ICC_Profile.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/ICC_Profile.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,25 +0,0 @@
-package com.lowagie.text.pdf;
-
-public class ICC_Profile {
-
- protected byte data[];
- protected int numComponents;
-
- protected ICC_Profile() {
- }
-
- public static ICC_Profile getInstance(byte data[], int numComponents) {
- ICC_Profile icc = new ICC_Profile();
- icc.data = data;
- icc.numComponents = numComponents;
- return icc;
- }
-
- public byte[] getData() {
- return data;
- }
-
- public int getNumComponents() {
- return numComponents;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/IntHashtable.java pdftk-2.01/java/com/lowagie/text/pdf/IntHashtable.java
--- pdftk-1.45/java/com/lowagie/text/pdf/IntHashtable.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/IntHashtable.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,338 +0,0 @@
-// IntHashtable - a Hashtable that uses ints as the keys
-//
-// This is 90% based on JavaSoft's java.util.Hashtable.
-//
-// Visit the ACME Labs Java page for up-to-date versions of this and other
-// fine Java utilities: http://www.acme.com/java/
-
-package com.lowagie.text.pdf;
-
-import java.util.Arrays;
-import java.util.NoSuchElementException;
-import java.util.Iterator;
-
-/// A Hashtable that uses ints as the keys.
-//
-// Use just like java.util.Hashtable, except that the keys must be ints.
-// This is much faster than creating a new Integer for each access.
-//
-// Fetch the software.
-// Fetch the entire Acme package.
-//
-// @see java.util.Hashtable
-
-public class IntHashtable implements Cloneable {
- /// The hash table data.
- private IntHashtableEntry table[];
-
- /// The total number of entries in the hash table.
- private int count;
-
- /// Rehashes the table when count exceeds this threshold.
- private int threshold;
-
- /// The load factor for the hashtable.
- private float loadFactor;
-
- /// Constructs a new, empty hashtable with the specified initial
- // capacity and the specified load factor.
- // @param initialCapacity the initial number of buckets
- // @param loadFactor a number between 0.0 and 1.0, it defines
- // the threshold for rehashing the hashtable into
- // a bigger one.
- // @exception IllegalArgumentException If the initial capacity
- // is less than or equal to zero.
- // @exception IllegalArgumentException If the load factor is
- // less than or equal to zero.
- public IntHashtable( int initialCapacity, float loadFactor ) {
- if ( initialCapacity <= 0 || loadFactor <= 0.0 )
- throw new IllegalArgumentException();
- this.loadFactor = loadFactor;
- table = new IntHashtableEntry[initialCapacity];
- threshold = (int) ( initialCapacity * loadFactor );
- }
-
- /// Constructs a new, empty hashtable with the specified initial
- // capacity.
- // @param initialCapacity the initial number of buckets
- public IntHashtable( int initialCapacity ) {
- this( initialCapacity, 0.75f );
- }
-
- /// Constructs a new, empty hashtable. A default capacity and load factor
- // is used. Note that the hashtable will automatically grow when it gets
- // full.
- public IntHashtable() {
- this( 101, 0.75f );
- }
-
- /// Returns the number of elements contained in the hashtable.
- public int size() {
- return count;
- }
-
- /// Returns true if the hashtable contains no elements.
- public boolean isEmpty() {
- return count == 0;
- }
-
- /// Returns true if the specified object is an element of the hashtable.
- // This operation is more expensive than the containsKey() method.
- // @param value the value that we are looking for
- // @exception NullPointerException If the value being searched
- // for is equal to null.
- // @see IntHashtable#containsKey
- public boolean contains( int value ) {
- IntHashtableEntry tab[] = table;
- for ( int i = tab.length ; i-- > 0 ; ) {
- for ( IntHashtableEntry e = tab[i] ; e != null ; e = e.next ) {
- if ( e.value == value )
- return true;
- }
- }
- return false;
- }
-
- /// Returns true if the collection contains an element for the key.
- // @param key the key that we are looking for
- // @see IntHashtable#contains
- public boolean containsKey( int key ) {
- IntHashtableEntry tab[] = table;
- int hash = key;
- int index = ( hash & 0x7FFFFFFF ) % tab.length;
- for ( IntHashtableEntry e = tab[index] ; e != null ; e = e.next ) {
- if ( e.hash == hash && e.key == key )
- return true;
- }
- return false;
- }
-
- /// Gets the object associated with the specified key in the
- // hashtable.
- // @param key the specified key
- // @returns the element for the key or null if the key
- // is not defined in the hash table.
- // @see IntHashtable#put
- public int get( int key ) {
- IntHashtableEntry tab[] = table;
- int hash = key;
- int index = ( hash & 0x7FFFFFFF ) % tab.length;
- for ( IntHashtableEntry e = tab[index] ; e != null ; e = e.next ) {
- if ( e.hash == hash && e.key == key )
- return e.value;
- }
- return 0;
- }
-
- /// Rehashes the content of the table into a bigger table.
- // This method is called automatically when the hashtable's
- // size exceeds the threshold.
- protected void rehash() {
- int oldCapacity = table.length;
- IntHashtableEntry oldTable[] = table;
-
- int newCapacity = oldCapacity * 2 + 1;
- IntHashtableEntry newTable[] = new IntHashtableEntry[newCapacity];
-
- threshold = (int) ( newCapacity * loadFactor );
- table = newTable;
-
- for ( int i = oldCapacity ; i-- > 0 ; ) {
- for ( IntHashtableEntry old = oldTable[i] ; old != null ; ) {
- IntHashtableEntry e = old;
- old = old.next;
-
- int index = ( e.hash & 0x7FFFFFFF ) % newCapacity;
- e.next = newTable[index];
- newTable[index] = e;
- }
- }
- }
-
- /// Puts the specified element into the hashtable, using the specified
- // key. The element may be retrieved by doing a get() with the same key.
- // The key and the element cannot be null.
- // @param key the specified key in the hashtable
- // @param value the specified element
- // @exception NullPointerException If the value of the element
- // is equal to null.
- // @see IntHashtable#get
- // @return the old value of the key, or null if it did not have one.
- public int put( int key, int value ) {
- // Makes sure the key is not already in the hashtable.
- IntHashtableEntry tab[] = table;
- int hash = key;
- int index = ( hash & 0x7FFFFFFF ) % tab.length;
- for ( IntHashtableEntry e = tab[index] ; e != null ; e = e.next ) {
- if ( e.hash == hash && e.key == key ) {
- int old = e.value;
- e.value = value;
- return old;
- }
- }
-
- if ( count >= threshold ) {
- // Rehash the table if the threshold is exceeded.
- rehash();
- return put( key, value );
- }
-
- // Creates the new entry.
- IntHashtableEntry e = new IntHashtableEntry();
- e.hash = hash;
- e.key = key;
- e.value = value;
- e.next = tab[index];
- tab[index] = e;
- ++count;
- return 0;
- }
-
- /// Removes the element corresponding to the key. Does nothing if the
- // key is not present.
- // @param key the key that needs to be removed
- // @return the value of key, or null if the key was not found.
- public int remove( int key ) {
- IntHashtableEntry tab[] = table;
- int hash = key;
- int index = ( hash & 0x7FFFFFFF ) % tab.length;
- for ( IntHashtableEntry e = tab[index], prev = null ; e != null ; prev = e, e = e.next ) {
- if ( e.hash == hash && e.key == key ) {
- if ( prev != null )
- prev.next = e.next;
- else
- tab[index] = e.next;
- --count;
- return e.value;
- }
- }
- return 0;
- }
-
- /// Clears the hash table so that it has no more elements in it.
- public void clear() {
- IntHashtableEntry tab[] = table;
- for ( int index = tab.length; --index >= 0; )
- tab[index] = null;
- count = 0;
- }
-
- public Object clone() {
- try {
- IntHashtable t = (IntHashtable)super.clone();
- t.table = new IntHashtableEntry[table.length];
- for (int i = table.length ; i-- > 0 ; ) {
- t.table[i] = (table[i] != null)
- ? (IntHashtableEntry)table[i].clone() : null;
- }
- return t;
- } catch (CloneNotSupportedException e) {
- // this shouldn't happen, since we are Cloneable
- throw new InternalError();
- }
- }
-
- public int[] toOrderedKeys() {
- int res[] = getKeys();
- Arrays.sort(res);
- return res;
- }
-
- public int[] getKeys() {
- int res[] = new int[count];
- int ptr = 0;
- int index = table.length;
- IntHashtableEntry entry = null;
- while (true) {
- if (entry == null)
- while ((index-- > 0) && ((entry = table[index]) == null));
- if (entry == null)
- break;
- IntHashtableEntry e = entry;
- entry = e.next;
- res[ptr++] = e.key;
- }
- return res;
- }
-
- public int getOneKey() {
- if (count == 0)
- return 0;
- int index = table.length;
- IntHashtableEntry entry = null;
- while ((index-- > 0) && ((entry = table[index]) == null));
- if (entry == null)
- return 0;
- return entry.key;
- }
-
- static class IntHashtableEntry {
- int hash;
- int key;
- int value;
- IntHashtableEntry next;
-
- public int getKey() {
- return key;
- }
-
- public int getValue() {
- return value;
- }
-
- protected Object clone() {
- IntHashtableEntry entry = new IntHashtableEntry();
- entry.hash = hash;
- entry.key = key;
- entry.value = value;
- entry.next = (next != null) ? (IntHashtableEntry)next.clone() : null;
- return entry;
- }
- }
-
- public Iterator getEntryIterator() {
- return new IntHashtableIterator(table);
- }
-
- static class IntHashtableIterator implements Iterator {
- // boolean keys;
- int index;
- IntHashtableEntry table[];
- IntHashtableEntry entry;
-
- IntHashtableIterator(IntHashtableEntry table[] /* , boolean keys */) {
- this.table = table;
- // this.keys = keys;
- this.index = table.length;
- }
-
- public boolean hasNext() {
- if (entry != null) {
- return true;
- }
- while (index-- > 0) {
- if ((entry = table[index]) != null) {
- return true;
- }
- }
- return false;
- }
-
- public Object next() {
- if (entry == null) {
- while ((index-- > 0) && ((entry = table[index]) == null));
- }
- if (entry != null) {
- IntHashtableEntry e = entry;
- entry = e.next;
- return e;
- }
- throw new NoSuchElementException("IntHashtableIterator");
- }
-
- public void remove() {
- throw new UnsupportedOperationException("remove() not supported.");
- }
-
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/Makefile pdftk-2.01/java/com/lowagie/text/pdf/Makefile
--- pdftk-1.45/java/com/lowagie/text/pdf/Makefile 2010-09-15 09:42:28.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-library= pdf.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-all : $(library) $(headers)
-
-$(library) : $(objects)
- $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/OutputStreamCounter.java pdftk-2.01/java/com/lowagie/text/pdf/OutputStreamCounter.java
--- pdftk-1.45/java/com/lowagie/text/pdf/OutputStreamCounter.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/OutputStreamCounter.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,176 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-import java.io.OutputStream;
-import java.io.IOException;
-
-/**
- *
- * @author psoares
- */
-public class OutputStreamCounter extends OutputStream {
-
- protected OutputStream out;
- protected int counter = 0;
-
- /** Creates a new instance of OutputStreamCounter */
- public OutputStreamCounter(OutputStream out) {
- this.out = out;
- }
-
- /** Closes this output stream and releases any system resources
- * associated with this stream. The general contract of close
- * is that it closes the output stream. A closed stream cannot perform
- * output operations and cannot be reopened.
- *
- * The close
method of OutputStream
does nothing.
- *
- * @exception IOException if an I/O error occurs.
- *
- */
- public void close() throws IOException {
- out.close();
- }
-
- /** Flushes this output stream and forces any buffered output bytes
- * to be written out. The general contract of flush
is
- * that calling it is an indication that, if any bytes previously
- * written have been buffered by the implementation of the output
- * stream, such bytes should immediately be written to their
- * intended destination.
- *
- * The flush
method of OutputStream
does nothing.
- *
- * @exception IOException if an I/O error occurs.
- *
- */
- public void flush() throws IOException {
- out.flush();
- }
-
- /** Writes b.length
bytes from the specified byte array
- * to this output stream. The general contract for write(b)
- * is that it should have exactly the same effect as the call
- * write(b, 0, b.length)
.
- *
- * @param b the data.
- * @exception IOException if an I/O error occurs.
- * @see java.io.OutputStream#write(byte[], int, int)
- *
- */
- public void write(byte[] b) throws IOException {
- counter += b.length;
- out.write(b);
- }
-
- /** Writes the specified byte to this output stream. The general
- * contract for write
is that one byte is written
- * to the output stream. The byte to be written is the eight
- * low-order bits of the argument b
. The 24
- * high-order bits of b
are ignored.
- *
- * Subclasses of OutputStream
must provide an
- * implementation for this method.
- *
- * @param b the byte
.
- * @exception IOException if an I/O error occurs. In particular,
- * an IOException
may be thrown if the
- * output stream has been closed.
- *
- */
- public void write(int b) throws IOException {
- ++counter;
- out.write(b);
- }
-
- /** Writes len
bytes from the specified byte array
- * starting at offset off
to this output stream.
- * The general contract for write(b, off, len)
is that
- * some of the bytes in the array b
are written to the
- * output stream in order; element b[off]
is the first
- * byte written and b[off+len-1]
is the last byte written
- * by this operation.
- *
- * The write
method of OutputStream
calls
- * the write method of one argument on each of the bytes to be
- * written out. Subclasses are encouraged to override this method and
- * provide a more efficient implementation.
- *
- * If b
is null
, a
- * NullPointerException
is thrown.
- *
- * If off
is negative, or len
is negative, or
- * off+len
is greater than the length of the array
- * b
, then an IndexOutOfBoundsException is thrown.
- *
- * @param b the data.
- * @param off the start offset in the data.
- * @param len the number of bytes to write.
- * @exception IOException if an I/O error occurs. In particular,
- * an IOException
is thrown if the output
- * stream is closed.
- *
- */
- public void write(byte[] b, int off, int len) throws IOException {
- counter += len;
- out.write(b, off, len);
- }
-
- public int getCounter() {
- return counter;
- }
-
- public void resetCounter() {
- counter = 0;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PRAcroForm.java pdftk-2.01/java/com/lowagie/text/pdf/PRAcroForm.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PRAcroForm.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PRAcroForm.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,216 +0,0 @@
-/*
- * $Id: PRAcroForm.java,v 1.11 2003/05/02 09:01:12 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * This class written by Mark Thompson, Copyright (C) 2002 by Mark Thompson.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.HashMap;
-
-/**
- * This class captures an AcroForm on input. Basically, it extends Dictionary
- * by indexing the fields of an AcroForm
- * @author Mark Thompson
- */
-
-public class PRAcroForm extends PdfDictionary {
-
- /**
- * This class holds the information for a single field
- */
- public static class FieldInformation {
- String name;
- PdfDictionary info;
- PRIndirectReference ref;
-
- FieldInformation(String name, PdfDictionary info, PRIndirectReference ref) {
- this.name = name; this.info = info; this.ref = ref;
- }
- public String getName() { return name; }
- public PdfDictionary getInfo() { return info; }
- public PRIndirectReference getRef() { return ref; }
- };
- ArrayList fields;
- ArrayList stack;
- HashMap fieldByName;
- PdfReader reader;
-
- /**
- * Constructor
- * @param reader reader of the input file
- */
- public PRAcroForm(PdfReader reader) {
- this.reader = reader;
- fields = new ArrayList();
- fieldByName = new HashMap();
- stack = new ArrayList();
- }
- /**
- * Number of fields found
- * @return size
- */
- public int size() {
- return fields.size();
- }
-
- public ArrayList getFields() {
- return fields;
- }
-
- public FieldInformation getField(String name) {
- return (FieldInformation)fieldByName.get(name);
- }
-
- /**
- * Given the title (/T) of a reference, return the associated reference
- * @param name a string containing the path
- * @return a reference to the field, or null
- */
- public PRIndirectReference getRefByName(String name) {
- FieldInformation fi = (FieldInformation)fieldByName.get(name);
- if (fi == null) return null;
- return fi.getRef();
- }
- /**
- * Read, and comprehend the acroform
- * @param root the docment root
- */
- public void readAcroForm(PdfDictionary root) {
- hashMap = root.hashMap;
- pushAttrib(root);
- PdfArray fieldlist = (PdfArray)PdfReader.getPdfObjectRelease(root.get(PdfName.FIELDS));
- iterateFields(fieldlist, null, null);
- }
-
- /**
- * After reading, we index all of the fields. Recursive.
- * @param fieldlist An array of fields
- * @param fieldDict the last field dictionary we encountered (recursively)
- * @param title the pathname of the field, up to this point or null
- */
- protected void iterateFields(PdfArray fieldlist, PRIndirectReference fieldDict, String title) {
- for (Iterator it = fieldlist.getArrayList().iterator(); it.hasNext();) {
- PRIndirectReference ref = (PRIndirectReference)it.next();
- PdfDictionary dict = (PdfDictionary) PdfReader.getPdfObjectRelease(ref);
-
- // if we are not a field dictionary, pass our parent's values
- PRIndirectReference myFieldDict = fieldDict;
- String myTitle = title;
- PdfString tField = (PdfString)dict.get(PdfName.T);
- boolean isFieldDict = tField != null;
-
- if (isFieldDict) {
- myFieldDict = ref;
- if (title == null) myTitle = tField.toString();
- else myTitle = title + '.' + tField.toString();
- }
-
- PdfArray kids = (PdfArray)dict.get(PdfName.KIDS);
- if (kids != null) {
- pushAttrib(dict);
- iterateFields(kids, myFieldDict, myTitle);
- stack.remove(stack.size() - 1); // pop
- }
- else { // leaf node
- if (myFieldDict != null) {
- PdfDictionary mergedDict = (PdfDictionary)stack.get(stack.size() - 1);
- if (isFieldDict)
- mergedDict = mergeAttrib(mergedDict, dict);
-
- mergedDict.put(PdfName.T, new PdfString(myTitle));
- FieldInformation fi = new FieldInformation(myTitle, mergedDict, myFieldDict);
- fields.add(fi);
- fieldByName.put(myTitle, fi);
- }
- }
- }
- }
- /**
- * merge field attributes from two dictionaries
- * @param parent one dictionary
- * @param child the other dictionary
- * @return a merged dictionary
- */
- protected PdfDictionary mergeAttrib(PdfDictionary parent, PdfDictionary child) {
- PdfDictionary targ = new PdfDictionary();
- if (parent != null) targ.putAll(parent);
-
- for (Iterator it = child.getKeys().iterator(); it.hasNext();) {
- PdfName key = (PdfName) it.next();
- if (key.equals(PdfName.DR) || key.equals(PdfName.DA) ||
- key.equals(PdfName.Q) || key.equals(PdfName.FF) ||
- key.equals(PdfName.DV) || key.equals(PdfName.V)
- || key.equals(PdfName.FT)
- || key.equals(PdfName.F)) {
- targ.put(key,child.get(key));
- }
- }
- return targ;
- }
- /**
- * stack a level of dictionary. Merge in a dictionary from this level
- */
- protected void pushAttrib(PdfDictionary dict) {
- PdfDictionary dic = null;
- if (stack.size() != 0) {
- dic = (PdfDictionary)stack.get(stack.size() - 1);
- }
- dic = mergeAttrib(dic, dict);
- stack.add(dic);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PRIndirectReference.java pdftk-2.01/java/com/lowagie/text/pdf/PRIndirectReference.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PRIndirectReference.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PRIndirectReference.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,109 +0,0 @@
-/*
- * $Id: PRIndirectReference.java,v 1.12 2002/07/09 11:28:22 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import java.io.OutputStream;
-import java.io.IOException;
-
-public class PRIndirectReference extends PdfIndirectReference {
-
- protected PdfReader reader;
- // membervariables
-
- // constructors
-
-/**
- * Constructs a PdfIndirectReference
.
- *
- * @param reader a PdfReader
- * @param number the object number.
- * @param generation the generation number.
- */
-
- PRIndirectReference(PdfReader reader, int number, int generation) {
- type = INDIRECT;
- this.number = number;
- this.generation = generation;
- this.reader = reader;
- }
-
-/**
- * Constructs a PdfIndirectReference
.
- *
- * @param reader a PdfReader
- * @param number the object number.
- */
-
- PRIndirectReference(PdfReader reader, int number) {
- this(reader, number, 0);
- }
-
- // methods
-
- public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
- int n = writer.getNewObjectNumber(reader, number, generation);
- os.write(PdfEncodings.convertToBytes(new StringBuffer().append(n).append(" 0 R").toString(), null));
- }
-
- public PdfReader getReader() {
- return reader;
- }
-
- public void setNumber(int number, int generation) {
- this.number = number;
- this.generation = generation;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PRStream.java pdftk-2.01/java/com/lowagie/text/pdf/PRStream.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PRStream.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PRStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,316 +0,0 @@
-/*
- * $Id: PRStream.java,v 1.12 2002/06/20 13:30:25 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.*;
-import com.lowagie.text.ExceptionConverter;
-import java.util.zip.DeflaterOutputStream;
-import com.lowagie.text.Document;
-import java.io.OutputStream;
-import java.io.IOException;
-import java.util.ArrayList; // ssteward
-
-public class PRStream extends PdfStream {
-
- protected PdfReader reader;
- protected int offset;
- protected int length;
-
- //added by ujihara for decryption
- protected int objNum = 0;
- protected int objGen = 0;
-
- public PRStream(PRStream stream, PdfDictionary newDic) {
- reader = stream.reader;
- offset = stream.offset;
- length = stream.length;
- compressed = stream.compressed;
- streamBytes = stream.streamBytes;
- bytes = stream.bytes;
- objNum = stream.objNum;
- objGen = stream.objGen;
- if (newDic != null)
- putAll(newDic);
- else
- hashMap.putAll(stream.hashMap);
- }
-
- public PRStream(PRStream stream, PdfDictionary newDic, PdfReader reader) {
- this(stream, newDic);
- this.reader = reader;
- }
-
- public PRStream(PdfReader reader, int offset) {
- this.reader = reader;
- this.offset = offset;
- }
-
- public PRStream(PdfReader reader, byte conts[]) {
- this.reader = reader;
- this.offset = -1;
- if (Document.compress) {
- try {
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- DeflaterOutputStream zip = new DeflaterOutputStream(stream);
- zip.write(conts);
- zip.close();
- bytes = stream.toByteArray();
- }
- catch (IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- put(PdfName.FILTER, PdfName.FLATEDECODE);
- }
- else
- bytes = conts;
- setLength(bytes.length);
- }
-
- /**Sets the data associated with the stream
- * @param data raw data, decrypted and uncompressed.
- */
- public void setData(byte[] data) {
- remove(PdfName.FILTER);
- this.offset = -1;
- if (Document.compress) {
- try {
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- DeflaterOutputStream zip = new DeflaterOutputStream(stream);
- zip.write(data);
- zip.close();
- bytes = stream.toByteArray();
- }
- catch (IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- put(PdfName.FILTER, PdfName.FLATEDECODE);
- }
- else
- bytes = data;
- setLength(bytes.length);
- }
-
- public void setLength(int length) {
- this.length = length;
- put(PdfName.LENGTH, new PdfNumber(length));
- }
-
- public int getOffset() {
- return offset;
- }
-
- public int getLength() {
- return length;
- }
-
- public PdfReader getReader() {
- return reader;
- }
-
- public byte[] getBytes() {
- return bytes;
- }
-
- public void setObjNum(int objNum, int objGen) {
- this.objNum = objNum;
- this.objGen = objGen;
- }
-
- int getObjNum() {
- return objNum;
- }
-
- int getObjGen() {
- return objGen;
- }
-
- // ssteward: added material to allow decoded, or "filtered," output;
- // perhaps decryption should be moved to PdfReader, a'la PdfReader.getStreamBytes(),
- // and encryption moved to PdfWriter? it just seems unwieldy to have some
- // of this code duplicated in PdfReader.getStreamBytes();
- //
- public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
-
- { // ssteward (right?)
- // the filters to apply to this, if any
- ArrayList filters= new ArrayList(); {
- PdfObject filter= this.reader.getPdfObject(this.get(PdfName.FILTER));
- if (filter != null) {
- if (filter.type() == PdfObject.NAME) {
- filters.add(filter);
- }
- else if (filter.type() == PdfObject.ARRAY) {
- filters = ((PdfArray)filter).getArrayList();
- }
- }
- }
-
- // apply filters to our stream data before streaming?
- boolean filterStream_b=
- ( writer.filterStreams &&
- 0< this.offset && // our stream data must be stored in a file, not in this.bytes
- this.reader.getPdfObject( this.get(PdfName.DECODEPARMS) )== null &&
- !filters.isEmpty() && allKnownFilters( this.reader, filters ) );
-
- if( filterStream_b ) { // apply filters
- RandomAccessFileOrArray file= writer.getReaderFile( this.reader );
- this.bytes= PdfReader.getStreamBytes( this, file ); // decrypts, too
-
- this.remove(PdfName.FILTER);
- this.setLength( this.bytes.length );
- this.offset= -1; // indicate that we have read the stream into this.bytes
- }
-
- // apply compression to our stream data before streaming?
- // our stream data may be in this.bytes or in a file
- boolean compressStream_b=
- ( writer.compressStreams &&
- this.reader.getPdfObject( this.get(PdfName.DECODEPARMS) )== null &&
- filters.isEmpty() );
-
- if( compressStream_b ) { // apply compression
- if( 0< this.offset ) { // our data is in file; pull into this.bytes
- RandomAccessFileOrArray file= writer.getReaderFile( this.reader );
- this.bytes= PdfReader.getStreamBytes( this, file ); // decrypts, too
- }
-
- ByteArrayOutputStream stream= new ByteArrayOutputStream();
- DeflaterOutputStream zip= new DeflaterOutputStream( stream );
- zip.write( this.bytes );
- zip.close();
- this.bytes= stream.toByteArray();
-
- this.put( PdfName.FILTER, PdfName.FLATEDECODE );
- this.setLength( this.bytes.length );
- this.offset= -1; // indicate that we have read the stream into this.bytes
- }
- }
-
- superToPdf(writer, os); // PdfDictionary.toPdf(), outputs FILTER, LENGTH, etc.
- os.write(STARTSTREAM);
- if (length > 0) {
- PdfEncryption crypto = null;
- if (writer != null) { // ssteward
- crypto = writer.getEncryption();
- }
- if (offset < 0) { // our stream data is stored in this.bytes
- if (crypto == null) {
- os.write(bytes);
- }
- else { // encrypt and output
- crypto.prepareKey();
- byte buf[] = new byte[length];
- System.arraycopy(bytes, 0, buf, 0, length);
- crypto.encryptRC4(buf);
- os.write(buf);
- }
- }
- else { // our stream data is stored in a file
- byte buf[] = new byte[Math.min(length, 4092)];
- RandomAccessFileOrArray file = writer.getReaderFile(reader);
- boolean isOpen = file.isOpen();
- try {
- file.seek(offset);
- int size = length;
-
- //added by ujihara for decryption
- PdfEncryption decrypt = reader.getDecrypt();
- if (decrypt != null) {
- decrypt.setHashKey(objNum, objGen);
- decrypt.prepareKey();
- }
-
- if (crypto != null)
- crypto.prepareKey();
- while (size > 0) {
- int r = file.read(buf, 0, Math.min(size, buf.length));
- size -= r;
-
- if (decrypt != null)
- decrypt.encryptRC4(buf, 0, r); //added by ujihara for decryption
-
- if (crypto != null)
- crypto.encryptRC4(buf, 0, r);
- os.write(buf, 0, r);
- }
- }
- finally {
- if (!isOpen)
- try{file.close();}catch(Exception e){}
- }
- }
- }
- os.write(ENDSTREAM);
- }
-
- // ssteward
- // do we know how to apply all of the filters in (ArrayList filters)?
- public static boolean allKnownFilters( PdfReader reader, ArrayList filters ) {
- boolean retVal= true;
- String name;
- for (int j = 0; j < filters.size(); ++j) {
- name = ((PdfName)reader.getPdfObject((PdfObject)filters.get(j))).toString();
- retVal= retVal &&
- ( (name.equals("/FlateDecode") || name.equals("/Fl")) ||
- (name.equals("/ASCIIHexDecode") || name.equals("/AHx")) ||
- (name.equals("/ASCII85Decode") || name.equals("/A85")) ||
- (name.equals("/LZWDecode")) );
- }
- return retVal;
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PRTokeniser.java pdftk-2.01/java/com/lowagie/text/pdf/PRTokeniser.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PRTokeniser.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PRTokeniser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,595 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * $Id: PRTokeniser.java,v 1.15 2002/06/20 13:30:25 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.*;
-/**
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PRTokeniser {
-
- public static final int TK_NUMBER = 1;
- public static final int TK_STRING = 2;
- public static final int TK_NAME = 3;
- public static final int TK_COMMENT = 4;
- public static final int TK_START_ARRAY = 5;
- public static final int TK_END_ARRAY = 6;
- public static final int TK_START_DIC = 7;
- public static final int TK_END_DIC = 8;
- public static final int TK_REF = 9;
- public static final int TK_OTHER = 10;
- public static final boolean delims[] = {
- true, true, false, false, false, false, false, false, false, false,
- true, true, false, true, true, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, true, false, false, false, false, true, false,
- false, true, true, false, false, false, false, false, true, false,
- false, false, false, false, false, false, false, false, false, false,
- false, true, false, true, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, true, false, true, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false, false, false, false,
- false, false, false, false, false, false, false};
-
- static final String EMPTY = "";
-
-
- protected RandomAccessFileOrArray file;
- protected int type;
- protected String stringValue;
- protected int reference;
- protected int generation;
- protected boolean hexString;
-
- // private static final int LINE_SEGMENT_SIZE = 256;
-
- public PRTokeniser(String filename) throws IOException {
- file = new RandomAccessFileOrArray(filename);
- }
-
- public PRTokeniser(byte pdfIn[]) {
- file = new RandomAccessFileOrArray(pdfIn);
- }
-
- public PRTokeniser(RandomAccessFileOrArray file) {
- this.file = file;
- }
-
- public void seek(int pos) throws IOException {
- file.seek(pos);
- }
-
- public int getFilePointer() throws IOException {
- return file.getFilePointer();
- }
-
- public void close() throws IOException {
- file.close();
- }
-
- public int length() throws IOException {
- return file.length();
- }
-
- public int read() throws IOException {
- return file.read();
- }
-
- public RandomAccessFileOrArray getSafeFile() {
- return new RandomAccessFileOrArray(file);
- }
-
- public RandomAccessFileOrArray getFile() {
- return file;
- }
-
- public String readString(int size) throws IOException {
- StringBuffer buf = new StringBuffer();
- int ch;
- while ((size--) > 0) {
- ch = file.read();
- if (ch == -1)
- break;
- buf.append((char)ch);
- }
- return buf.toString();
- }
-
- public static final boolean isWhitespace(int ch) {
- return (ch == 0 || ch == 9 || ch == 10 || ch == 12 || ch == 13 || ch == 32);
- }
-
- public static final boolean isDelimiter(int ch) {
- return (ch == '(' || ch == ')' || ch == '<' || ch == '>' || ch == '[' || ch == ']' || ch == '/' || ch == '%');
- }
-
- public static final boolean isDelimiterWhitespace(int ch) {
- return delims[ch + 1];
- }
-
- public int getTokenType() {
- return type;
- }
-
- public String getStringValue() {
- return stringValue;
- }
-
- public int getReference() {
- return reference;
- }
-
- public int getGeneration() {
- return generation;
- }
-
- public void backOnePosition(int ch) throws IOException {
- if (ch != -1)
- file.pushBack((byte)ch);
- }
-
- public void throwError(String error) throws IOException {
- throw new IOException(error + " at file pointer " + file.getFilePointer());
- }
-
- public char checkPdfHeader() throws IOException {
- file.setStartOffset(0);
- String str = readString(1024);
- int idx = str.indexOf("%PDF-1.");
- if (idx < 0)
- throw new IOException("PDF header signature not found.");
- file.setStartOffset(idx);
- return str.charAt(idx + 7);
- }
-
- public void checkFdfHeader() throws IOException {
- file.setStartOffset(0);
- String str = readString(1024);
- int idx = str.indexOf("%FDF-1.2");
- if (idx < 0)
- throw new IOException("FDF header signature not found.");
- file.setStartOffset(idx);
- }
-
- public int getStartxref() throws IOException {
- int size = Math.min(1024, file.length());
- int pos = file.length() - size;
- file.seek(pos);
- String str = readString(1024);
- int idx = str.lastIndexOf("startxref");
- if (idx < 0)
- throw new IOException("PDF startxref not found.");
- return pos + idx;
- }
-
- public static int getHex(int v) {
- if (v >= '0' && v <= '9')
- return v - '0';
- if (v >= 'A' && v <= 'F')
- return v - 'A' + 10;
- if (v >= 'a' && v <= 'f')
- return v - 'a' + 10;
- return -1;
- }
-
- public void nextValidToken() throws IOException {
- int level = 0;
- String n1 = null;
- String n2 = null;
- int ptr = 0;
- while (nextToken()) {
- if (type == TK_COMMENT)
- continue;
- switch (level) {
- case 0:
- {
- if (type != TK_NUMBER)
- return;
- ptr = file.getFilePointer();
- n1 = stringValue;
- ++level;
- break;
- }
- case 1:
- {
- if (type != TK_NUMBER) {
- file.seek(ptr);
- type = TK_NUMBER;
- stringValue = n1;
- return;
- }
- n2 = stringValue;
- ++level;
- break;
- }
- default:
- {
- if (type != TK_OTHER || !stringValue.equals("R")) {
- file.seek(ptr);
- type = TK_NUMBER;
- stringValue = n1;
- return;
- }
- type = TK_REF;
- reference = Integer.valueOf(n1).intValue();
- generation = Integer.valueOf(n2).intValue();
- return;
- }
- }
- }
- throwError("Unexpected end of file");
- }
-
- public boolean nextToken() throws IOException {
- StringBuffer outBuf = null;
- stringValue = EMPTY;
- int ch = 0;
- do {
- ch = file.read();
- } while (ch != -1 && isWhitespace(ch));
- if (ch == -1)
- return false;
- switch (ch) {
- case '[':
- type = TK_START_ARRAY;
- break;
- case ']':
- type = TK_END_ARRAY;
- break;
- case '/':
- {
- outBuf = new StringBuffer();
- type = TK_NAME;
- while (true) {
- ch = file.read();
- if (delims[ch + 1])
- break;
- if (ch == '#') {
- ch = (getHex(file.read()) << 4) + getHex(file.read());
- }
- outBuf.append((char)ch);
- }
- backOnePosition(ch);
- break;
- }
- case '>':
- ch = file.read();
- if (ch != '>')
- throwError("'>' not expected");
- type = TK_END_DIC;
- break;
- case '<':
- {
- int v1 = file.read();
- if (v1 == '<') {
- type = TK_START_DIC;
- break;
- }
- outBuf = new StringBuffer();
- type = TK_STRING;
- hexString = true;
- int v2 = 0;
- while (true) {
- while (isWhitespace(v1))
- v1 = file.read();
- if (v1 == '>')
- break;
- v1 = getHex(v1);
- if (v1 < 0)
- break;
- v2 = file.read();
- while (isWhitespace(v2))
- v2 = file.read();
- if (v2 == '>') {
- ch = v1 << 4;
- outBuf.append((char)ch);
- break;
- }
- v2 = getHex(v2);
- if (v2 < 0)
- break;
- ch = (v1 << 4) + v2;
- outBuf.append((char)ch);
- v1 = file.read();
- }
- if (v1 < 0 || v2 < 0)
- throwError("Error reading string");
- break;
- }
- case '%':
- type = TK_COMMENT;
- do {
- ch = file.read();
- } while (ch != -1 && ch != '\r' && ch != '\n');
- break;
- case '(':
- {
- outBuf = new StringBuffer();
- type = TK_STRING;
- hexString = false;
- int nesting = 0;
- while (true) {
- ch = file.read();
- if (ch == -1)
- break;
- if (ch == '(') {
- ++nesting;
- }
- else if (ch == ')') {
- --nesting;
- }
- else if (ch == '\\') {
- boolean lineBreak = false;
- ch = file.read();
- switch (ch) {
- case 'n':
- ch = '\n';
- break;
- case 'r':
- ch = '\r';
- break;
- case 't':
- ch = '\t';
- break;
- case 'b':
- ch = '\b';
- break;
- case 'f':
- ch = '\f';
- break;
- case '(':
- case ')':
- case '\\':
- break;
- case '\r':
- lineBreak = true;
- ch = file.read();
- if (ch != '\n')
- backOnePosition(ch);
- break;
- case '\n':
- lineBreak = true;
- break;
- default:
- {
- if (ch < '0' || ch > '7') {
- break;
- }
- int octal = ch - '0';
- ch = file.read();
- if (ch < '0' || ch > '7') {
- backOnePosition(ch);
- ch = octal;
- break;
- }
- octal = (octal << 3) + ch - '0';
- ch = file.read();
- if (ch < '0' || ch > '7') {
- backOnePosition(ch);
- ch = octal;
- break;
- }
- octal = (octal << 3) + ch - '0';
- ch = octal & 0xff;
- break;
- }
- }
- if (lineBreak)
- continue;
- if (ch < 0)
- break;
- }
- else if (ch == '\r') {
- ch = file.read();
- if (ch < 0)
- break;
- if (ch != '\n') {
- backOnePosition(ch);
- ch = '\n';
- }
- }
- if (nesting == -1)
- break;
- outBuf.append((char)ch);
- }
- if (ch == -1)
- throwError("Error reading string");
- break;
- }
- default:
- {
- outBuf = new StringBuffer();
- if (ch == '-' || ch == '+' || ch == '.' || (ch >= '0' && ch <= '9')) {
- type = TK_NUMBER;
- do {
- outBuf.append((char)ch);
- ch = file.read();
- } while (ch != -1 && ((ch >= '0' && ch <= '9') || ch == '.'));
- }
- else {
- type = TK_OTHER;
- do {
- outBuf.append((char)ch);
- ch = file.read();
- } while (!delims[ch + 1]);
- }
- backOnePosition(ch);
- break;
- }
- }
- if (outBuf != null)
- stringValue = outBuf.toString();
- return true;
- }
-
- public int intValue() {
- return Integer.valueOf(stringValue).intValue();
- }
-
- public boolean readLineSegment(byte input[]) throws IOException {
- int c = -1;
- boolean eol = false;
- int ptr = 0;
- int len = input.length;
-
- // ssteward, pdftk-1.10, 040922:
- // skip initial whitespace; added this because PdfReader.rebuildXref()
- // assumes that line provided by readLineSegment does not have init. whitespace;
- if ( ptr < len ) {
- while ( isWhitespace( (c = read()) ) );
- }
- while ( !eol && ptr < len ) {
- switch (c) {
- case -1:
- case '\n':
- eol = true;
- break;
- case '\r':
- eol = true;
- int cur = getFilePointer();
- if ((read()) != '\n') {
- seek(cur);
- }
- break;
- default:
- input[ptr++] = (byte)c;
- break;
- }
-
- // break loop? do it before we read() again
- if( eol || len <= ptr ) {
- break;
- }
- else {
- c = read();
- }
- }
-
- if( len <= ptr ) {
- eol = false;
- while (!eol) {
- switch (c = read()) {
- case -1:
- case '\n':
- eol = true;
- break;
- case '\r':
- eol = true;
- int cur = getFilePointer();
- if ((read()) != '\n') {
- seek(cur);
- }
- break;
- }
- }
- }
-
- if ((c == -1) && (ptr == 0)) {
- return false;
- }
- if (ptr + 2 <= len) {
- input[ptr++] = (byte)' ';
- input[ptr] = (byte)'X';
- }
- return true;
- }
-
- public static int[] checkObjectStart(byte line[]) {
- try {
- PRTokeniser tk = new PRTokeniser(line);
- int num = 0;
- int gen = 0;
- if (!tk.nextToken() || tk.getTokenType() != TK_NUMBER)
- return null;
- num = tk.intValue();
- if (!tk.nextToken() || tk.getTokenType() != TK_NUMBER)
- return null;
- gen = tk.intValue();
- if (!tk.nextToken())
- return null;
- if (!tk.getStringValue().equals("obj"))
- return null;
- return new int[]{num, gen};
- }
- catch (Exception ioe) {
- // empty on purpose
- }
- return null;
- }
-
- public boolean isHexString() {
- return this.hexString;
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PageResources.java pdftk-2.01/java/com/lowagie/text/pdf/PageResources.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PageResources.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PageResources.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,193 +0,0 @@
-/*
- * $Id: PRTokeniser.java,v 1.15 2002/06/20 13:30:25 blowagie Exp $
- *
- * Copyright 2003-2005 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.util.HashMap;
-import java.util.Iterator;
-
-class PageResources {
-
- protected PdfDictionary fontDictionary = new PdfDictionary();
- protected PdfDictionary xObjectDictionary = new PdfDictionary();
- protected PdfDictionary colorDictionary = new PdfDictionary();
- protected PdfDictionary patternDictionary = new PdfDictionary();
- protected PdfDictionary shadingDictionary = new PdfDictionary();
- protected PdfDictionary extGStateDictionary = new PdfDictionary();
- protected PdfDictionary propertyDictionary = new PdfDictionary();
- protected HashMap forbiddenNames;
- protected PdfDictionary originalResources;
- protected int namePtr[] = {0};
- protected HashMap usedNames;
-
- PageResources() {
- }
-
- void setOriginalResources(PdfDictionary resources, int newNamePtr[]) {
- if (newNamePtr != null)
- namePtr = newNamePtr;
- originalResources = resources;
- forbiddenNames = new HashMap();
- usedNames = new HashMap();
- if (resources == null)
- return;
- for (Iterator i = resources.getKeys().iterator(); i.hasNext();) {
- PdfObject sub = PdfReader.getPdfObject(resources.get((PdfName)i.next()));
- if (sub.isDictionary()) {
- PdfDictionary dic = (PdfDictionary)sub;
- for (Iterator j = dic.getKeys().iterator(); j.hasNext();) {
- forbiddenNames.put(j.next(), null);
- }
- }
- }
- }
-
- PdfName translateName(PdfName name) {
- PdfName translated = name;
- if (forbiddenNames != null) {
- translated = (PdfName)usedNames.get(name);
- if (translated == null) {
- while (true) {
- translated = new PdfName("Xi" + (namePtr[0]++));
- if (!forbiddenNames.containsKey(translated))
- break;
- }
- usedNames.put(name, translated);
- }
- }
- return translated;
- }
-
- PdfName addFont(PdfName name, PdfIndirectReference reference) {
- name = translateName(name);
- fontDictionary.put(name, reference);
- return name;
- }
-
- PdfName addXObject(PdfName name, PdfIndirectReference reference) {
- name = translateName(name);
- xObjectDictionary.put(name, reference);
- return name;
- }
-
- PdfName addColor(PdfName name, PdfIndirectReference reference) {
- name = translateName(name);
- colorDictionary.put(name, reference);
- return name;
- }
-
- void addDefaultColor(PdfName name, PdfObject obj) {
- if (obj == null || obj.isNull())
- colorDictionary.remove(name);
- else
- colorDictionary.put(name, obj);
- }
-
- void addDefaultColor(PdfDictionary dic) {
- colorDictionary.merge(dic);
- }
-
- void addDefaultColorDiff(PdfDictionary dic) {
- colorDictionary.mergeDifferent(dic);
- }
-
- PdfName addShading(PdfName name, PdfIndirectReference reference) {
- name = translateName(name);
- shadingDictionary.put(name, reference);
- return name;
- }
-
- PdfName addPattern(PdfName name, PdfIndirectReference reference) {
- name = translateName(name);
- patternDictionary.put(name, reference);
- return name;
- }
-
- PdfName addExtGState(PdfName name, PdfIndirectReference reference) {
- name = translateName(name);
- extGStateDictionary.put(name, reference);
- return name;
- }
-
- PdfName addProperty(PdfName name, PdfIndirectReference reference) {
- name = translateName(name);
- propertyDictionary.put(name, reference);
- return name;
- }
-
- PdfDictionary getResources() {
- PdfResources resources = new PdfResources();
- if (originalResources != null)
- resources.putAll(originalResources);
- resources.put(PdfName.PROCSET, new PdfLiteral("[/PDF /Text /ImageB /ImageC /ImageI]"));
- resources.add(PdfName.FONT, fontDictionary);
- resources.add(PdfName.XOBJECT, xObjectDictionary);
- resources.add(PdfName.COLORSPACE, colorDictionary);
- resources.add(PdfName.PATTERN, patternDictionary);
- resources.add(PdfName.SHADING, shadingDictionary);
- resources.add(PdfName.EXTGSTATE, extGStateDictionary);
- resources.add(PdfName.PROPERTIES, propertyDictionary);
- return resources;
- }
-
- boolean hasResources() {
- return (fontDictionary.size() > 0
- || xObjectDictionary.size() > 0
- || colorDictionary.size() > 0
- || patternDictionary.size() > 0
- || shadingDictionary.size() > 0
- || extGStateDictionary.size() > 0
- || propertyDictionary.size() > 0);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PangoArabicShapping.java pdftk-2.01/java/com/lowagie/text/pdf/PangoArabicShapping.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PangoArabicShapping.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PangoArabicShapping.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,652 +0,0 @@
-/*
- * Copyright 2003 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-/** Shape arabic characters. This code was converted from a C version
- * at www.pango.org.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PangoArabicShapping {
-
- /** Creates a new instance of PangoArabicShapping */
- public PangoArabicShapping() {
- }
-
- static boolean isVowel(char s) {
- return ((s >= 0x064B) && (s <= 0x0655)) || (s == 0x0670);
- }
-
- static char charshape(char s, int which)
- /* which 0=isolated 1=final 2=initial 3=medial */
- {
- int l, r, m;
- if ((s >= 0x0621) && (s <= 0x06D3)) {
- l = 0;
- r = chartable.length - 1;
- while (l <= r) {
- m = (l + r) / 2;
- if (s == chartable[m][0]) {
- return chartable[m][which + 1];
- }
- else if (s < chartable[m][0]) {
- r = m - 1;
- }
- else {
- l = m + 1;
- }
- }
- }
- return s;
- }
-
- static int shapecount(char s) {
- int l, r, m;
- if ((s >= 0x0621) && (s <= 0x06D3) && !isVowel(s)) {
- l = 0;
- r = chartable.length - 1;
- while (l <= r) {
- m = (l + r) / 2;
- if (s == chartable[m][0]) {
- return chartable[m].length - 1;
- }
- else if (s < chartable[m][0]) {
- r = m - 1;
- }
- else {
- l = m + 1;
- }
- }
- }
- else if (s == ZWJ) {
- return 4;
- }
- return 1;
- }
-
- static int ligature(char newchar, charstruct oldchar) {
- /* 0 == no ligature possible; 1 == vowel; 2 == two chars; 3 == Lam+Alef */
- int retval = 0;
-
- if (oldchar.basechar == 0)
- return 0;
- if (isVowel(newchar)) {
- retval = 1;
- if ((oldchar.vowel != 0) && (newchar != SHADDA)) {
- retval = 2; /* we eliminate the old vowel .. */
- }
- switch (newchar) {
- case SHADDA:
- if (oldchar.mark1 == 0) {
- oldchar.mark1 = SHADDA;
- }
- else {
- return 0; /* no ligature possible */
- }
- break;
- case HAMZABELOW:
- switch (oldchar.basechar) {
- case ALEF:
- oldchar.basechar = ALEFHAMZABELOW;
- retval = 2;
- break;
- case LAM_ALEF:
- oldchar.basechar = LAM_ALEFHAMZABELOW;
- retval = 2;
- break;
- default:
- oldchar.mark1 = HAMZABELOW;
- break;
- }
- break;
- case HAMZAABOVE:
- switch (oldchar.basechar) {
- case ALEF:
- oldchar.basechar = ALEFHAMZA;
- retval = 2;
- break;
- case LAM_ALEF:
- oldchar.basechar = LAM_ALEFHAMZA;
- retval = 2;
- break;
- case WAW:
- oldchar.basechar = WAWHAMZA;
- retval = 2;
- break;
- case YEH:
- case ALEFMAKSURA:
- case FARSIYEH:
- oldchar.basechar = YEHHAMZA;
- retval = 2;
- break;
- default: /* whatever sense this may make .. */
- oldchar.mark1 = HAMZAABOVE;
- break;
- }
- break;
- case MADDA:
- switch (oldchar.basechar) {
- case ALEF:
- oldchar.basechar = ALEFMADDA;
- retval = 2;
- break;
- }
- break;
- default:
- oldchar.vowel = newchar;
- break;
- }
- if (retval == 1) {
- oldchar.lignum++;
- }
- return retval;
- }
- if (oldchar.vowel != 0) { /* if we already joined a vowel, we can't join a Hamza */
- return 0;
- }
-
- switch (oldchar.basechar) {
- case LAM:
- switch (newchar) {
- case ALEF:
- oldchar.basechar = LAM_ALEF;
- oldchar.numshapes = 2;
- retval = 3;
- break;
- case ALEFHAMZA:
- oldchar.basechar = LAM_ALEFHAMZA;
- oldchar.numshapes = 2;
- retval = 3;
- break;
- case ALEFHAMZABELOW:
- oldchar.basechar = LAM_ALEFHAMZABELOW;
- oldchar.numshapes = 2;
- retval = 3;
- break;
- case ALEFMADDA:
- oldchar.basechar = LAM_ALEFMADDA;
- oldchar.numshapes = 2;
- retval = 3;
- break;
- }
- break;
- case 0:
- oldchar.basechar = newchar;
- oldchar.numshapes = shapecount(newchar);
- retval = 1;
- break;
- }
- return retval;
- }
-
- static void copycstostring(StringBuffer string, charstruct s, int level) {
- /* s is a shaped charstruct; i is the index into the string */
- if (s.basechar == 0)
- return;
-
- string.append(s.basechar);
- (s.lignum)--;
- if (s.mark1 != 0) {
- if ((level & ar_novowel) == 0) {
- string.append(s.mark1);
- (s.lignum)--;
- }
- else {
- (s.lignum)--;
- }
- }
- if (s.vowel != 0) {
- if ((level & ar_novowel) == 0) {
- string.append(s.vowel);
- (s.lignum)--;
- }
- else { /* vowel elimination */
- (s.lignum)--;
- }
- }
-// while (s.lignum > 0) { /* NULL-insertion for Langbox-font */
-// string[i] = 0;
-// i++;
-// (s.lignum)--;
-// }
-// return i;
- }
-
- // return len
- static void doublelig(StringBuffer string, int level)
- /* Ok. We have presentation ligatures in our font. */
- {
- int len;
- int olen = len = string.length();
- int j = 0, si = 1;
- char lapresult;
-
- while (si < olen) {
- lapresult = 0;
- if ((level & ar_composedtashkeel) != 0) {
- switch (string.charAt(j)) {
- case SHADDA:
- switch (string.charAt(si)) {
- case KASRA:
- lapresult = 0xFC62;
- break;
- case FATHA:
- lapresult = 0xFC60;
- break;
- case DAMMA:
- lapresult = 0xFC61;
- break;
- case 0x064C:
- lapresult = 0xFC5E;
- break;
- case 0x064D:
- lapresult = 0xFC5F;
- break;
- }
- break;
- case KASRA:
- if (string.charAt(si) == SHADDA)
- lapresult = 0xFC62;
- break;
- case FATHA:
- if (string.charAt(si) == SHADDA)
- lapresult = 0xFC60;
- break;
- case DAMMA:
- if (string.charAt(si) == SHADDA)
- lapresult = 0xFC61;
- break;
- }
- }
-
- if ((level & ar_lig) != 0) {
- switch (string.charAt(j)) {
- case 0xFEDF: /* LAM initial */
- switch (string.charAt(si)) {
- case 0xFE9E:
- lapresult = 0xFC3F;
- break; /* JEEM final */
- case 0xFEA0:
- lapresult = 0xFCC9;
- break; /* JEEM medial */
- case 0xFEA2:
- lapresult = 0xFC40;
- break; /* HAH final */
- case 0xFEA4:
- lapresult = 0xFCCA;
- break; /* HAH medial */
- case 0xFEA6:
- lapresult = 0xFC41;
- break; /* KHAH final */
- case 0xFEA8:
- lapresult = 0xFCCB;
- break; /* KHAH medial */
- case 0xFEE2:
- lapresult = 0xFC42;
- break; /* MEEM final */
- case 0xFEE4:
- lapresult = 0xFCCC;
- break; /* MEEM medial */
- }
- break;
- case 0xFE97: /* TEH inital */
- switch (string.charAt(si)) {
- case 0xFEA0:
- lapresult = 0xFCA1;
- break; /* JEEM medial */
- case 0xFEA4:
- lapresult = 0xFCA2;
- break; /* HAH medial */
- case 0xFEA8:
- lapresult = 0xFCA3;
- break; /* KHAH medial */
- }
- break;
- case 0xFE91: /* BEH inital */
- switch (string.charAt(si)) {
- case 0xFEA0:
- lapresult = 0xFC9C;
- break; /* JEEM medial */
- case 0xFEA4:
- lapresult = 0xFC9D;
- break; /* HAH medial */
- case 0xFEA8:
- lapresult = 0xFC9E;
- break; /* KHAH medial */
- }
- break;
- case 0xFEE7: /* NOON inital */
- switch (string.charAt(si)) {
- case 0xFEA0:
- lapresult = 0xFCD2;
- break; /* JEEM initial */
- case 0xFEA4:
- lapresult = 0xFCD3;
- break; /* HAH medial */
- case 0xFEA8:
- lapresult = 0xFCD4;
- break; /* KHAH medial */
- }
- break;
-
- case 0xFEE8: /* NOON medial */
- switch (string.charAt(si)) {
- case 0xFEAE:
- lapresult = 0xFC8A;
- break; /* REH final */
- case 0xFEB0:
- lapresult = 0xFC8B;
- break; /* ZAIN final */
- }
- break;
- case 0xFEE3: /* MEEM initial */
- switch (string.charAt(si)) {
- case 0xFEA0:
- lapresult = 0xFCCE;
- break; /* JEEM medial */
- case 0xFEA4:
- lapresult = 0xFCCF;
- break; /* HAH medial */
- case 0xFEA8:
- lapresult = 0xFCD0;
- break; /* KHAH medial */
- case 0xFEE4:
- lapresult = 0xFCD1;
- break; /* MEEM medial */
- }
- break;
-
- case 0xFED3: /* FEH initial */
- switch (string.charAt(si)) {
- case 0xFEF2:
- lapresult = 0xFC32;
- break; /* YEH final */
- }
- break;
-
- default:
- break;
- } /* end switch string[si] */
- }
- if (lapresult != 0) {
- string.setCharAt(j, lapresult);
- len--;
- si++; /* jump over one character */
- /* we'll have to change this, too. */
- }
- else {
- j++;
- string.setCharAt(j, string.charAt(si));
- si++;
- }
- }
- string.setLength(len);
- }
-
- static boolean connects_to_left(charstruct a) {
- return a.numshapes > 2;
- }
-
- static void shape(char text[], StringBuffer string, int level) {
- /* string is assumed to be empty and big enough.
- * text is the original text.
- * This routine does the basic arabic reshaping.
- * *len the number of non-null characters.
- *
- * Note: We have to unshape each character first!
- */
- int join;
- int which;
- char nextletter;
-
- int p = 0; /* initialize for output */
- charstruct oldchar = new charstruct();
- charstruct curchar = new charstruct();
- while (p < text.length) {
- nextletter = text[p++];
- //nextletter = unshape (nextletter);
-
- join = ligature(nextletter, curchar);
- if (join == 0) { /* shape curchar */
- int nc = shapecount(nextletter);
- //(*len)++;
- if (nc == 1) {
- which = 0; /* final or isolated */
- }
- else {
- which = 2; /* medial or initial */
- }
- if (connects_to_left(oldchar)) {
- which++;
- }
-
- which = which % (curchar.numshapes);
- curchar.basechar = charshape(curchar.basechar, which);
-
- /* get rid of oldchar */
- copycstostring(string, oldchar, level);
- oldchar = curchar; /* new values in oldchar */
-
- /* init new curchar */
- curchar = new charstruct();
- curchar.basechar = nextletter;
- curchar.numshapes = nc;
- curchar.lignum++;
- // (*len) += unligature (&curchar, level);
- }
- else if ((join == 3) && (level & ar_lboxfont) != 0) { /* Lam+Alef extra in langbox-font */
- curchar.lignum++;
- }
- else if (join == 1) {
- }
- // else
- // {
- // (*len) += unligature (&curchar, level);
- // }
- // p = g_utf8_next_char (p);
- }
-
- /* Handle last char */
- if (connects_to_left(oldchar))
- which = 1;
- else
- which = 0;
- which = which % (curchar.numshapes);
- curchar.basechar = charshape(curchar.basechar, which);
-
- /* get rid of oldchar */
- copycstostring(string, oldchar, level);
- copycstostring(string, curchar, level);
- }
-
- static int arabic_shape(char src[], int srcoffset, int srclength, char dest[], int destoffset, int destlength, int level) {
- char str[] = new char[srclength];
- for (int k = srclength + srcoffset - 1; k >= srcoffset; --k)
- str[k - srcoffset] = src[k];
- StringBuffer string = new StringBuffer(srclength);
- shape(str, string, level);
- if ((level & (ar_composedtashkeel | ar_lig)) != 0)
- doublelig(string, level);
-// string.reverse();
- System.arraycopy(string.toString().toCharArray(), 0, dest, destoffset, string.length());
- return string.length();
- }
-
- private static final char ALEF = 0x0627;
- private static final char ALEFHAMZA = 0x0623;
- private static final char ALEFHAMZABELOW = 0x0625;
- private static final char ALEFMADDA = 0x0622;
- private static final char LAM = 0x0644;
- private static final char HAMZA = 0x0621;
- private static final char TATWEEL = 0x0640;
- private static final char ZWJ = 0x200D;
-
- private static final char HAMZAABOVE = 0x0654;
- private static final char HAMZABELOW = 0x0655;
-
- private static final char WAWHAMZA = 0x0624;
- private static final char YEHHAMZA = 0x0626;
- private static final char WAW = 0x0648;
- private static final char ALEFMAKSURA = 0x0649;
- private static final char YEH = 0x064A;
- private static final char FARSIYEH = 0x06CC;
-
- private static final char SHADDA = 0x0651;
- private static final char KASRA = 0x0650;
- private static final char FATHA = 0x064E;
- private static final char DAMMA = 0x064F;
- private static final char MADDA = 0x0653;
-
- private static final char LAM_ALEF = 0xFEFB;
- private static final char LAM_ALEFHAMZA = 0xFEF7;
- private static final char LAM_ALEFHAMZABELOW = 0xFEF9;
- private static final char LAM_ALEFMADDA = 0xFEF5;
-
- private static final char chartable[][] = {
- {0x0621, 0xFE80}, /* HAMZA */
- {0x0622, 0xFE81, 0xFE82}, /* ALEF WITH MADDA ABOVE */
- {0x0623, 0xFE83, 0xFE84}, /* ALEF WITH HAMZA ABOVE */
- {0x0624, 0xFE85, 0xFE86}, /* WAW WITH HAMZA ABOVE */
- {0x0625, 0xFE87, 0xFE88}, /* ALEF WITH HAMZA BELOW */
- {0x0626, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C}, /* YEH WITH HAMZA ABOVE */
- {0x0627, 0xFE8D, 0xFE8E}, /* ALEF */
- {0x0628, 0xFE8F, 0xFE90, 0xFE91, 0xFE92}, /* BEH */
- {0x0629, 0xFE93, 0xFE94}, /* TEH MARBUTA */
- {0x062A, 0xFE95, 0xFE96, 0xFE97, 0xFE98}, /* TEH */
- {0x062B, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C}, /* THEH */
- {0x062C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0}, /* JEEM */
- {0x062D, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4}, /* HAH */
- {0x062E, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8}, /* KHAH */
- {0x062F, 0xFEA9, 0xFEAA}, /* DAL */
- {0x0630, 0xFEAB, 0xFEAC}, /* THAL */
- {0x0631, 0xFEAD, 0xFEAE}, /* REH */
- {0x0632, 0xFEAF, 0xFEB0}, /* ZAIN */
- {0x0633, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4}, /* SEEN */
- {0x0634, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8}, /* SHEEN */
- {0x0635, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC}, /* SAD */
- {0x0636, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0}, /* DAD */
- {0x0637, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4}, /* TAH */
- {0x0638, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8}, /* ZAH */
- {0x0639, 0xFEC9, 0xFECA, 0xFECB, 0xFECC}, /* AIN */
- {0x063A, 0xFECD, 0xFECE, 0xFECF, 0xFED0}, /* GHAIN */
- {0x0640, 0x0640, 0x0640, 0x0640, 0x0640}, /* TATWEEL */
- {0x0641, 0xFED1, 0xFED2, 0xFED3, 0xFED4}, /* FEH */
- {0x0642, 0xFED5, 0xFED6, 0xFED7, 0xFED8}, /* QAF */
- {0x0643, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC}, /* KAF */
- {0x0644, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0}, /* LAM */
- {0x0645, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4}, /* MEEM */
- {0x0646, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8}, /* NOON */
- {0x0647, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC}, /* HEH */
- {0x0648, 0xFEED, 0xFEEE}, /* WAW */
- {0x0649, 0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9}, /* ALEF MAKSURA */
- {0x064A, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4}, /* YEH */
- {0x0671, 0xFB50, 0xFB51}, /* ALEF WASLA */
- {0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69}, /* TTEH */
- {0x067A, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61}, /* TTEHEH */
- {0x067B, 0xFB52, 0xFB53, 0xFB54, 0xFB55}, /* BEEH */
- {0x067E, 0xFB56, 0xFB57, 0xFB58, 0xFB59}, /* PEH */
- {0x067F, 0xFB62, 0xFB63, 0xFB64, 0xFB65}, /* TEHEH */
- {0x0680, 0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D}, /* BEHEH */
- {0x0683, 0xFB76, 0xFB77, 0xFB78, 0xFB79}, /* NYEH */
- {0x0684, 0xFB72, 0xFB73, 0xFB74, 0xFB75}, /* DYEH */
- {0x0686, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D}, /* TCHEH */
- {0x0687, 0xFB7E, 0xFB7F, 0xFB80, 0xFB81}, /* TCHEHEH */
- {0x0688, 0xFB88, 0xFB89}, /* DDAL */
- {0x068C, 0xFB84, 0xFB85}, /* DAHAL */
- {0x068D, 0xFB82, 0xFB83}, /* DDAHAL */
- {0x068E, 0xFB86, 0xFB87}, /* DUL */
- {0x0691, 0xFB8C, 0xFB8D}, /* RREH */
- {0x0698, 0xFB8A, 0xFB8B}, /* JEH */
- {0x06A4, 0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D}, /* VEH */
- {0x06A6, 0xFB6E, 0xFB6F, 0xFB70, 0xFB71}, /* PEHEH */
- {0x06A9, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91}, /* KEHEH */
- {0x06AD, 0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6}, /* NG */
- {0x06AF, 0xFB92, 0xFB93, 0xFB94, 0xFB95}, /* GAF */
- {0x06B1, 0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D}, /* NGOEH */
- {0x06B3, 0xFB96, 0xFB97, 0xFB98, 0xFB99}, /* GUEH */
- {0x06BB, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3}, /* RNOON */
- {0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD}, /* HEH DOACHASHMEE */
- {0x06C0, 0xFBA4, 0xFBA5}, /* HEH WITH YEH ABOVE */
- {0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9}, /* HEH GOAL */
- {0x06C5, 0xFBE0, 0xFBE1}, /* KIRGHIZ OE */
- {0x06C6, 0xFBD9, 0xFBDA}, /* OE */
- {0x06C7, 0xFBD7, 0xFBD8}, /* U */
- {0x06C8, 0xFBDB, 0xFBDC}, /* YU */
- {0x06C9, 0xFBE2, 0xFBE3}, /* KIRGHIZ YU */
- {0x06CB, 0xFBDE, 0xFBDF}, /* VE */
- {0x06CC, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF}, /* FARSI YEH */
- {0x06D0, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7}, /* E */
- {0x06D2, 0xFBAE, 0xFBAF}, /* YEH BARREE */
- {0x06D3, 0xFBB0, 0xFBB1} /* YEH BARREE WITH HAMZA ABOVE */
- };
-
- static final int ar_nothing = 0x0;
- static final int ar_novowel = 0x1;
- static final int ar_standard = 0x2;
- static final int ar_composedtashkeel = 0x4;
- static final int ar_lig = 0x8;
- static final int ar_mulefont = 0x10;
- static final int ar_lboxfont = 0x20;
- static final int ar_unifont = 0x40;
- static final int ar_naqshfont = 0x80;
-
- static class charstruct {
- char basechar;
- char mark1; /* has to be initialized to zero */
- char vowel;
- int lignum; /* is a ligature with lignum aditional characters */
- int numshapes = 1;
- };
-
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PatternColor.java pdftk-2.01/java/com/lowagie/text/pdf/PatternColor.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PatternColor.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PatternColor.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-/** Represents a pattern. Can be used in high-level constructs (Paragraph, Cell, etc.).
- */
-public class PatternColor extends ExtendedColor {
- /**
- * The actual pattern.
- */
- PdfPatternPainter painter;
-
- /** Creates a color representing a pattern.
- * @param painter the actual pattern
- */
- public PatternColor(PdfPatternPainter painter) {
- super(TYPE_PATTERN, .5f, .5f, .5f);
- this.painter = painter;
- }
-
- /** Gets the pattern.
- * @return the pattern
- */
- public PdfPatternPainter getPainter() {
- return this.painter;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfAcroForm.java pdftk-2.01/java/com/lowagie/text/pdf/PdfAcroForm.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfAcroForm.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfAcroForm.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,752 +0,0 @@
-/*
- * $Id: PdfAcroForm.java,v 1.44 2005/03/30 10:10:58 blowagie Exp $
- * $Name: $
- *
- * Copyright 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.util.Iterator;
-import java.util.HashMap;
-
-import com.lowagie.text.Rectangle;
-import com.lowagie.text.ExceptionConverter;
-
-/**
- * Each PDF document can contain maximum 1 AcroForm.
- */
-
-public class PdfAcroForm extends PdfDictionary {
-
- private PdfWriter writer;
-
-
- /** This is a map containing FieldTemplates. */
- private HashMap fieldTemplates = new HashMap();
-
- /** This is an array containing DocumentFields. */
- private PdfArray documentFields = new PdfArray();
-
- /** This is an array containing the calculationorder of the fields. */
- private PdfArray calculationOrder = new PdfArray();
-
- /** Contains the signature flags. */
- private int sigFlags = 0;
-
- /** Creates new PdfAcroForm
- * @param writer*/
- PdfAcroForm(PdfWriter writer) {
- super();
- this.writer = writer;
- }
-
- /**
- * Adds fieldTemplates.
- * @param ft
- */
-
- void addFieldTemplates(HashMap ft) {
- fieldTemplates.putAll(ft);
- }
-
- /**
- * Adds documentFields.
- * @param ref
- */
-
- void addDocumentField(PdfIndirectReference ref) {
- // ssteward; added test to support my code in PdfCopy
- if( !documentFields.contains(ref) )
- documentFields.add(ref);
- }
-
- /**
- * Checks if the Acroform is valid
- * @return true if the Acroform is valid
- */
-
- boolean isValid() {
- if (documentFields.size() == 0) return false;
- put(PdfName.FIELDS, documentFields);
- if (sigFlags != 0)
- put(PdfName.SIGFLAGS, new PdfNumber(sigFlags));
- if (calculationOrder.size() > 0)
- put(PdfName.CO, calculationOrder);
- if (fieldTemplates.size() == 0) return true;
- PdfDictionary dic = new PdfDictionary();
- for (Iterator it = fieldTemplates.keySet().iterator(); it.hasNext();) {
- PdfTemplate template = (PdfTemplate)it.next();
- PdfFormField.mergeResources(dic, (PdfDictionary)template.getResources());
- }
- put(PdfName.DR, dic);
- PdfDictionary fonts = (PdfDictionary)dic.get(PdfName.FONT);
- if (fonts != null) {
- put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
- writer.eliminateFontSubset(fonts);
- }
- return true;
- }
-
- /**
- * Adds an object to the calculationOrder.
- * @param formField
- */
-
- public void addCalculationOrder(PdfFormField formField) {
- calculationOrder.add(formField.getIndirectReference());
- }
-
- /**
- * Sets the signature flags.
- * @param f
- */
-
- public void setSigFlags(int f) {
- sigFlags |= f;
- }
-
- /**
- * Adds a formfield to the AcroForm.
- * @param formField
- */
-
- public void addFormField(PdfFormField formField) {
- writer.addAnnotation(formField);
- }
-
- /**
- * @param name
- * @param caption
- * @param value
- * @param url
- * @param font
- * @param fontSize
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return a PdfFormField
- */
- public PdfFormField addHtmlPostButton(String name, String caption, String value, String url, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
- PdfAction action = PdfAction.createSubmitForm(url, null, PdfAction.SUBMIT_HTML_FORMAT);
- PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
- setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, value);
- drawButton(button, caption, font, fontSize, llx, lly, urx, ury);
- addFormField(button);
- return button;
- }
-
- /**
- * @param name
- * @param caption
- * @param value
- * @param font
- * @param fontSize
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return a PdfFormField
- */
- public PdfFormField addResetButton(String name, String caption, String value, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
- PdfAction action = PdfAction.createResetForm(null, 0);
- PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
- setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, value);
- drawButton(button, caption, font, fontSize, llx, lly, urx, ury);
- addFormField(button);
- return button;
- }
-
- /**
- * @param name
- * @param value
- * @param url
- * @param appearance
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return a PdfFormField
- */
- public PdfFormField addMap(String name, String value, String url, PdfContentByte appearance, float llx, float lly, float urx, float ury) {
- PdfAction action = PdfAction.createSubmitForm(url, null, PdfAction.SUBMIT_HTML_FORMAT | PdfAction.SUBMIT_COORDINATES);
- PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
- setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, null);
- PdfContentByte cb = writer.getDirectContent();
- PdfAppearance pa = cb.createAppearance(urx - llx, ury - lly);
- pa.add(appearance);
- button.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pa);
- addFormField(button);
- return button;
- }
-
- /**
- * @param button
- * @param characteristics
- * @param name
- * @param value
- */
- public void setButtonParams(PdfFormField button, int characteristics, String name, String value) {
- button.setButton(characteristics);
- button.setFlags(PdfAnnotation.FLAGS_PRINT);
- button.setPage();
- button.setFieldName(name);
- if (value != null) button.setValueAsString(value);
- }
-
- /**
- * @param button
- * @param caption
- * @param font
- * @param fontSize
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- */
- public void drawButton(PdfFormField button, String caption, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
- PdfContentByte cb = writer.getDirectContent();
- PdfAppearance pa = cb.createAppearance(urx - llx, ury - lly);
- pa.drawButton(0f, 0f, urx - llx, ury - lly, caption, font, fontSize);
- button.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pa);
- }
-
- /**
- * @param name
- * @param value
- * @return a PdfFormField
- */
- public PdfFormField addHiddenField(String name, String value) {
- PdfFormField hidden = PdfFormField.createEmpty(writer);
- hidden.setFieldName(name);
- hidden.setValueAsName(value);
- addFormField(hidden);
- return hidden;
- }
-
- /**
- * @param name
- * @param text
- * @param font
- * @param fontSize
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return a PdfFormField
- */
- public PdfFormField addSingleLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
- PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.SINGLELINE, PdfFormField.PLAINTEXT, 0);
- setTextFieldParams(field, text, name, llx, lly, urx, ury);
- drawSingleLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
- addFormField(field);
- return field;
- }
-
- /**
- * @param name
- * @param text
- * @param font
- * @param fontSize
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return a PdfFormField
- */
- public PdfFormField addMultiLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
- PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.MULTILINE, PdfFormField.PLAINTEXT, 0);
- setTextFieldParams(field, text, name, llx, lly, urx, ury);
- drawMultiLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
- addFormField(field);
- return field;
- }
-
- /**
- * @param name
- * @param text
- * @param font
- * @param fontSize
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return PdfFormField
- */
- public PdfFormField addSingleLinePasswordField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
- PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.SINGLELINE, PdfFormField.PASSWORD, 0);
- setTextFieldParams(field, text, name, llx, lly, urx, ury);
- drawSingleLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
- addFormField(field);
- return field;
- }
-
- /**
- * @param field
- * @param text
- * @param name
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- */
- public void setTextFieldParams(PdfFormField field, String text, String name, float llx, float lly, float urx, float ury) {
- field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
- field.setValueAsString(text);
- field.setDefaultValueAsString(text);
- field.setFieldName(name);
- field.setFlags(PdfAnnotation.FLAGS_PRINT);
- field.setPage();
- }
-
- /**
- * @param field
- * @param text
- * @param font
- * @param fontSize
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- */
- public void drawSingleLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
- PdfContentByte cb = writer.getDirectContent();
- PdfAppearance tp = cb.createAppearance(urx - llx, ury - lly);
- PdfAppearance tp2 = (PdfAppearance)tp.getDuplicate();
- tp2.setFontAndSize(font, fontSize);
- tp2.resetRGBColorFill();
- field.setDefaultAppearanceString(tp2);
- tp.drawTextField(0f, 0f, urx - llx, ury - lly);
- tp.beginVariableText();
- tp.saveState();
- tp.rectangle(3f, 3f, urx - llx - 6f, ury - lly - 6f);
- tp.clip();
- tp.newPath();
- tp.beginText();
- tp.setFontAndSize(font, fontSize);
- tp.resetRGBColorFill();
- tp.setTextMatrix(4, (ury - lly) / 2 - (fontSize * 0.3f));
- tp.showText(text);
- tp.endText();
- tp.restoreState();
- tp.endVariableText();
- field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
- }
-
- /**
- * @param field
- * @param text
- * @param font
- * @param fontSize
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- */
- public void drawMultiLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
- PdfContentByte cb = writer.getDirectContent();
- PdfAppearance tp = cb.createAppearance(urx - llx, ury - lly);
- PdfAppearance tp2 = (PdfAppearance)tp.getDuplicate();
- tp2.setFontAndSize(font, fontSize);
- tp2.resetRGBColorFill();
- field.setDefaultAppearanceString(tp2);
- tp.drawTextField(0f, 0f, urx - llx, ury - lly);
- tp.beginVariableText();
- tp.saveState();
- tp.rectangle(3f, 3f, urx - llx - 6f, ury - lly - 6f);
- tp.clip();
- tp.newPath();
- tp.beginText();
- tp.setFontAndSize(font, fontSize);
- tp.resetRGBColorFill();
- tp.setTextMatrix(4, 5);
- java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(text, "\n");
- float yPos = ury - lly;
- while (tokenizer.hasMoreTokens()) {
- yPos -= fontSize * 1.2f;
- tp.showTextAligned(PdfContentByte.ALIGN_LEFT, tokenizer.nextToken(), 3, yPos, 0);
- }
- tp.endText();
- tp.restoreState();
- tp.endVariableText();
- field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
- }
-
- /**
- * @param name
- * @param value
- * @param status
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return a PdfFormField
- */
- public PdfFormField addCheckBox(String name, String value, boolean status, float llx, float lly, float urx, float ury) {
- PdfFormField field = PdfFormField.createCheckBox(writer);
- setCheckBoxParams(field, name, value, status, llx, lly, urx, ury);
- drawCheckBoxAppearences(field, value, llx, lly, urx, ury);
- addFormField(field);
- return field;
- }
-
- /**
- * @param field
- * @param name
- * @param value
- * @param status
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- */
- public void setCheckBoxParams(PdfFormField field, String name, String value, boolean status, float llx, float lly, float urx, float ury) {
- field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_TOGGLE);
- field.setFieldName(name);
- if (status) {
- field.setValueAsName(value);
- field.setAppearanceState(value);
- }
- else {
- field.setValueAsName("Off");
- field.setAppearanceState("Off");
- }
- field.setFlags(PdfAnnotation.FLAGS_PRINT);
- field.setPage();
- field.setBorderStyle(new PdfBorderDictionary(1, PdfBorderDictionary.STYLE_SOLID));
- }
-
- /**
- * @param field
- * @param value
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- */
- public void drawCheckBoxAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury) {
- BaseFont font = null;
- try {
- font = BaseFont.createFont(BaseFont.ZAPFDINGBATS, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
- }
- catch(Exception e) {
- throw new ExceptionConverter(e);
- }
- float size = (ury - lly);
- PdfContentByte cb = writer.getDirectContent();
- PdfAppearance tpOn = cb.createAppearance(urx - llx, ury - lly);
- PdfAppearance tp2 = (PdfAppearance)tpOn.getDuplicate();
- tp2.setFontAndSize(font, size);
- tp2.resetRGBColorFill();
- field.setDefaultAppearanceString(tp2);
- tpOn.drawTextField(0f, 0f, urx - llx, ury - lly);
- tpOn.saveState();
- tpOn.resetRGBColorFill();
- tpOn.beginText();
- tpOn.setFontAndSize(font, size);
- tpOn.showTextAligned(PdfContentByte.ALIGN_CENTER, "4", (urx - llx) / 2, (ury - lly) / 2 - (size * 0.3f), 0);
- tpOn.endText();
- tpOn.restoreState();
- field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, value, tpOn);
- PdfAppearance tpOff = cb.createAppearance(urx - llx, ury - lly);
- tpOff.drawTextField(0f, 0f, urx - llx, ury - lly);
- field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpOff);
- }
-
- /**
- * @param name
- * @param defaultValue
- * @param noToggleToOff
- * @return a PdfFormField
- */
- public PdfFormField getRadioGroup(String name, String defaultValue, boolean noToggleToOff) {
- PdfFormField radio = PdfFormField.createRadioButton(writer, noToggleToOff);
- radio.setFieldName(name);
- radio.setValueAsName(defaultValue);
- return radio;
- }
-
- /**
- * @param radiogroup
- */
- public void addRadioGroup(PdfFormField radiogroup) {
- addFormField(radiogroup);
- }
-
- /**
- * @param radiogroup
- * @param value
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return a PdfFormField
- */
- public PdfFormField addRadioButton(PdfFormField radiogroup, String value, float llx, float lly, float urx, float ury) {
- PdfFormField radio = PdfFormField.createEmpty(writer);
- radio.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_TOGGLE);
- String name = ((PdfName)radiogroup.get(PdfName.V)).toString().substring(1);
- if (name.equals(value)) {
- radio.setAppearanceState(value);
- }
- else {
- radio.setAppearanceState("Off");
- }
- drawRadioAppearences(radio, value, llx, lly, urx, ury);
- radiogroup.addKid(radio);
- return radio;
- }
-
- /**
- * @param field
- * @param value
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- */
- public void drawRadioAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury) {
- PdfContentByte cb = writer.getDirectContent();
- PdfAppearance tpOn = cb.createAppearance(urx - llx, ury - lly);
- tpOn.drawRadioField(0f, 0f, urx - llx, ury - lly, true);
- field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, value, tpOn);
- PdfAppearance tpOff = cb.createAppearance(urx - llx, ury - lly);
- tpOff.drawRadioField(0f, 0f, urx - llx, ury - lly, false);
- field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpOff);
- }
-
- /**
- * @param name
- * @param options
- * @param defaultValue
- * @param font
- * @param fontSize
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return a PdfFormField
- */
- public PdfFormField addSelectList(String name, String[] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
- PdfFormField choice = PdfFormField.createList(writer, options, 0);
- setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
- StringBuffer text = new StringBuffer();
- for (int i = 0; i < options.length; i++) {
- text.append(options[i]).append("\n");
- }
- drawMultiLineOfText(choice, text.toString(), font, fontSize, llx, lly, urx, ury);
- addFormField(choice);
- return choice;
- }
-
- /**
- * @param name
- * @param options
- * @param defaultValue
- * @param font
- * @param fontSize
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return a PdfFormField
- */
- public PdfFormField addSelectList(String name, String[][] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
- PdfFormField choice = PdfFormField.createList(writer, options, 0);
- setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
- StringBuffer text = new StringBuffer();
- for (int i = 0; i < options.length; i++) {
- text.append(options[i][1]).append("\n");
- }
- drawMultiLineOfText(choice, text.toString(), font, fontSize, llx, lly, urx, ury);
- addFormField(choice);
- return choice;
- }
-
- /**
- * @param name
- * @param options
- * @param defaultValue
- * @param editable
- * @param font
- * @param fontSize
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return a PdfFormField
- */
- public PdfFormField addComboBox(String name, String[] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
- PdfFormField choice = PdfFormField.createCombo(writer, editable, options, 0);
- setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
- if (defaultValue == null) {
- defaultValue = options[0];
- }
- drawSingleLineOfText(choice, defaultValue, font, fontSize, llx, lly, urx, ury);
- addFormField(choice);
- return choice;
- }
-
- /**
- * @param name
- * @param options
- * @param defaultValue
- * @param editable
- * @param font
- * @param fontSize
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return a PdfFormField
- */
- public PdfFormField addComboBox(String name, String[][] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
- PdfFormField choice = PdfFormField.createCombo(writer, editable, options, 0);
- setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
- String value = null;
- for (int i = 0; i < options.length; i++) {
- if (options[i][0].equals(defaultValue)) {
- value = options[i][1];
- break;
- }
- }
- if (value == null) {
- value = options[0][1];
- }
- drawSingleLineOfText(choice, value, font, fontSize, llx, lly, urx, ury);
- addFormField(choice);
- return choice;
- }
-
- /**
- * @param field
- * @param name
- * @param defaultValue
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- */
- public void setChoiceParams(PdfFormField field, String name, String defaultValue, float llx, float lly, float urx, float ury) {
- field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
- if (defaultValue != null) {
- field.setValueAsString(defaultValue);
- field.setDefaultValueAsString(defaultValue);
- }
- field.setFieldName(name);
- field.setFlags(PdfAnnotation.FLAGS_PRINT);
- field.setPage();
- field.setBorderStyle(new PdfBorderDictionary(2, PdfBorderDictionary.STYLE_SOLID));
- }
-
- /**
- * @param name
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @return a PdfFormField
- */
- public PdfFormField addSignature(String name,
- float llx, float lly, float urx, float ury) {
- PdfFormField signature = PdfFormField.createSignature(writer);
- setSignatureParams(signature, name, llx, lly, urx, ury);
- drawSignatureAppearences(signature, llx, lly, urx, ury);
- addFormField(signature);
- return signature;
- }
-
- /**
- * @param field
- * @param name
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- */
- public void setSignatureParams(PdfFormField field, String name,
- float llx, float lly, float urx, float ury) {
- field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
- field.setFieldName(name);
- field.setFlags(PdfAnnotation.FLAGS_PRINT);
- field.setPage();
- field.setMKBorderColor(java.awt.Color.black);
- field.setMKBackgroundColor(java.awt.Color.white);
- }
-
- /**
- * @param field
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- */
- public void drawSignatureAppearences(PdfFormField field,
- float llx, float lly, float urx, float ury) {
- PdfContentByte cb = writer.getDirectContent();
- PdfAppearance tp = cb.createAppearance(urx - llx, ury - lly);
- tp.setGrayFill(1.0f);
- tp.rectangle(0, 0, urx - llx, ury - lly);
- tp.fill();
- tp.setGrayStroke(0);
- tp.setLineWidth(1);
- tp.rectangle(0.5f, 0.5f, urx - llx - 0.5f, ury - lly - 0.5f);
- tp.closePathStroke();
- tp.saveState();
- tp.rectangle(1, 1, urx - llx - 2, ury - lly - 2);
- tp.clip();
- tp.newPath();
- tp.restoreState();
- field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfAction.java pdftk-2.01/java/com/lowagie/text/pdf/PdfAction.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfAction.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfAction.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,564 +0,0 @@
-/*
- * $Id: PdfAction.java,v 1.64 2005/01/06 09:40:10 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.net.URL;
-import com.lowagie.text.ExceptionConverter;
-import java.io.IOException;
-import java.util.ArrayList;
-
-/**
- * A PdfAction
defines an action that can be triggered from a PDF file.
- *
- * @see PdfDictionary
- */
-
-public class PdfAction extends PdfDictionary {
-
- /** A named action to go to the first page.
- */
- public static final int FIRSTPAGE = 1;
- /** A named action to go to the previous page.
- */
- public static final int PREVPAGE = 2;
- /** A named action to go to the next page.
- */
- public static final int NEXTPAGE = 3;
- /** A named action to go to the last page.
- */
- public static final int LASTPAGE = 4;
-
- /** A named action to open a print dialog.
- */
- public static final int PRINTDIALOG = 5;
-
- /** a possible submitvalue */
- public static final int SUBMIT_EXCLUDE = 1;
- /** a possible submitvalue */
- public static final int SUBMIT_INCLUDE_NO_VALUE_FIELDS = 2;
- /** a possible submitvalue */
- public static final int SUBMIT_HTML_FORMAT = 4;
- /** a possible submitvalue */
- public static final int SUBMIT_HTML_GET = 8;
- /** a possible submitvalue */
- public static final int SUBMIT_COORDINATES = 16;
- /** a possible submitvalue */
- public static final int SUBMIT_XFDF = 32;
- /** a possible submitvalue */
- public static final int SUBMIT_INCLUDE_APPEND_SAVES = 64;
- /** a possible submitvalue */
- public static final int SUBMIT_INCLUDE_ANNOTATIONS = 128;
- /** a possible submitvalue */
- public static final int SUBMIT_PDF = 256;
- /** a possible submitvalue */
- public static final int SUBMIT_CANONICAL_FORMAT = 512;
- /** a possible submitvalue */
- public static final int SUBMIT_EXCL_NON_USER_ANNOTS = 1024;
- /** a possible submitvalue */
- public static final int SUBMIT_EXCL_F_KEY = 2048;
- /** a possible submitvalue */
- public static final int SUBMIT_EMBED_FORM = 8196;
- /** a possible submitvalue */
- public static final int RESET_EXCLUDE = 1;
-
- // constructors
-
- /** Create an empty action.
- */
- public PdfAction() {
- }
-
- /**
- * Constructs a new PdfAction
of Subtype URI.
- *
- * @param url the Url to go to
- */
-
- public PdfAction(URL url) {
- this(url.toExternalForm());
- }
-
- /**
- * Construct a new PdfAction
of Subtype URI that accepts the x and y coordinate of the position that was clicked.
- * @param url
- * @param isMap
- */
- public PdfAction(URL url, boolean isMap) {
- this(url.toExternalForm(), isMap);
- }
-
- /**
- * Constructs a new PdfAction
of Subtype URI.
- *
- * @param url the url to go to
- */
-
- public PdfAction(String url) {
- this(url, false);
- }
-
- /**
- * Construct a new PdfAction
of Subtype URI that accepts the x and y coordinate of the position that was clicked.
- * @param url
- * @param isMap
- */
-
- public PdfAction(String url, boolean isMap) {
- put(PdfName.S, PdfName.URI);
- put(PdfName.URI, new PdfString(url));
- if (isMap)
- put(PdfName.ISMAP, PdfBoolean.PDFTRUE);
- }
-
- /**
- * Constructs a new PdfAction
of Subtype GoTo.
- * @param destination the destination to go to
- */
-
- PdfAction(PdfIndirectReference destination) {
- put(PdfName.S, PdfName.GOTO);
- put(PdfName.D, destination);
- }
-
- /**
- * Constructs a new PdfAction
of Subtype GoToR.
- * @param filename the file name to go to
- * @param name the named destination to go to
- */
-
- public PdfAction(String filename, String name) {
- put(PdfName.S, PdfName.GOTOR);
- put(PdfName.F, new PdfString(filename));
- put(PdfName.D, new PdfString(name));
- }
-
- /**
- * Constructs a new PdfAction
of Subtype GoToR.
- * @param filename the file name to go to
- * @param page the page destination to go to
- */
-
- public PdfAction(String filename, int page) {
- put(PdfName.S, PdfName.GOTOR);
- put(PdfName.F, new PdfString(filename));
- put(PdfName.D, new PdfLiteral("[" + (page - 1) + " /FitH 10000]"));
- }
-
- /** Implements name actions. The action can be FIRSTPAGE, LASTPAGE,
- * NEXTPAGE, PREVPAGE and PRINTDIALOG.
- * @param named the named action
- */
- public PdfAction(int named) {
- put(PdfName.S, PdfName.NAMED);
- switch (named) {
- case FIRSTPAGE:
- put(PdfName.N, PdfName.FIRSTPAGE);
- break;
- case LASTPAGE:
- put(PdfName.N, PdfName.LASTPAGE);
- break;
- case NEXTPAGE:
- put(PdfName.N, PdfName.NEXTPAGE);
- break;
- case PREVPAGE:
- put(PdfName.N, PdfName.PREVPAGE);
- break;
- case PRINTDIALOG:
- put(PdfName.S, PdfName.JAVASCRIPT);
- put(PdfName.JS, new PdfString("this.print(true);\r"));
- break;
- default:
- throw new RuntimeException("Invalid named action.");
- }
- }
-
- /** Launchs an application or a document.
- * @param application the application to be launched or the document to be opened or printed.
- * @param parameters (Windows-specific) A parameter string to be passed to the application.
- * It can be null
.
- * @param operation (Windows-specific) the operation to perform: "open" - Open a document,
- * "print" - Print a document.
- * It can be null
.
- * @param defaultDir (Windows-specific) the default directory in standard DOS syntax.
- * It can be null
.
- */
- public PdfAction(String application, String parameters, String operation, String defaultDir) {
- put(PdfName.S, PdfName.LAUNCH);
- if (parameters == null && operation == null && defaultDir == null)
- put(PdfName.F, new PdfString(application));
- else {
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.F, new PdfString(application));
- if (parameters != null)
- dic.put(PdfName.P, new PdfString(parameters));
- if (operation != null)
- dic.put(PdfName.O, new PdfString(operation));
- if (defaultDir != null)
- dic.put(PdfName.D, new PdfString(defaultDir));
- put(PdfName.WIN, dic);
- }
- }
-
- /** Launchs an application or a document.
- * @param application the application to be launched or the document to be opened or printed.
- * @param parameters (Windows-specific) A parameter string to be passed to the application.
- * It can be null
.
- * @param operation (Windows-specific) the operation to perform: "open" - Open a document,
- * "print" - Print a document.
- * It can be null
.
- * @param defaultDir (Windows-specific) the default directory in standard DOS syntax.
- * It can be null
.
- * @return a Launch action
- */
- public static PdfAction createLaunch(String application, String parameters, String operation, String defaultDir) {
- return new PdfAction(application, parameters, operation, defaultDir);
- }
-
- /**Creates a Rendition action
- * @param file
- * @param fs
- * @param mimeType
- * @param ref
- * @return a Media Clip action
- * @throws IOException
- */
- public static PdfAction rendition(String file, PdfFileSpecification fs, String mimeType, PdfIndirectReference ref) throws IOException {
- PdfAction js = new PdfAction();
- js.put(PdfName.S, PdfName.RENDITION);
- js.put(PdfName.R, new PdfRendition(file, fs, mimeType));
- js.put(new PdfName("OP"), new PdfNumber(0));
- js.put(new PdfName("AN"), ref);
- return js;
- }
-
- /** Creates a JavaScript action. If the JavaScript is smaller than
- * 50 characters it will be placed as a string, otherwise it will
- * be placed as a compressed stream.
- * @param code the JavaScript code
- * @param writer the writer for this action
- * @param unicode select JavaScript unicode. Note that the internal
- * Acrobat JavaScript engine does not support unicode,
- * so this may or may not work for you
- * @return the JavaScript action
- */
- public static PdfAction javaScript(String code, PdfWriter writer, boolean unicode) {
- PdfAction js = new PdfAction();
- js.put(PdfName.S, PdfName.JAVASCRIPT);
- if (unicode && code.length() < 50) {
- js.put(PdfName.JS, new PdfString(code, PdfObject.TEXT_UNICODE));
- }
- else if (!unicode && code.length() < 100) {
- js.put(PdfName.JS, new PdfString(code));
- }
- else {
- try {
- byte b[] = PdfEncodings.convertToBytes(code, unicode ? PdfObject.TEXT_UNICODE : PdfObject.TEXT_PDFDOCENCODING);
- PdfStream stream = new PdfStream(b);
- stream.flateCompress();
- js.put(PdfName.JS, writer.addToBody(stream).getIndirectReference());
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
- return js;
- }
-
- /** Creates a JavaScript action. If the JavaScript is smaller than
- * 50 characters it will be place as a string, otherwise it will
- * be placed as a compressed stream.
- * @param code the JavaScript code
- * @param writer the writer for this action
- * @return the JavaScript action
- */
- public static PdfAction javaScript(String code, PdfWriter writer) {
- return javaScript(code, writer, false);
- }
-
- /**
- * A Hide action hides or shows an object.
- * @param obj object to hide or show
- * @param hide true is hide, false is show
- * @return a Hide Action
- */
- static PdfAction createHide(PdfObject obj, boolean hide) {
- PdfAction action = new PdfAction();
- action.put(PdfName.S, PdfName.HIDE);
- action.put(PdfName.T, obj);
- if (!hide)
- action.put(PdfName.H, PdfBoolean.PDFFALSE);
- return action;
- }
-
- /**
- * A Hide action hides or shows an annotation.
- * @param annot
- * @param hide
- * @return A Hide Action
- */
- public static PdfAction createHide(PdfAnnotation annot, boolean hide) {
- return createHide(annot.getIndirectReference(), hide);
- }
-
- /**
- * A Hide action hides or shows an annotation.
- * @param name
- * @param hide
- * @return A Hide Action
- */
- public static PdfAction createHide(String name, boolean hide) {
- return createHide(new PdfString(name), hide);
- }
-
- static PdfArray buildArray(Object names[]) {
- PdfArray array = new PdfArray();
- for (int k = 0; k < names.length; ++k) {
- Object obj = names[k];
- if (obj instanceof String)
- array.add(new PdfString((String)obj));
- else if (obj instanceof PdfAnnotation)
- array.add(((PdfAnnotation)obj).getIndirectReference());
- else
- throw new RuntimeException("The array must contain String or PdfAnnotation.");
- }
- return array;
- }
-
- /**
- * A Hide action hides or shows objects.
- * @param names
- * @param hide
- * @return A Hide Action
- */
- public static PdfAction createHide(Object names[], boolean hide) {
- return createHide(buildArray(names), hide);
- }
-
- /**
- * Creates a submit form.
- * @param file the URI to submit the form to
- * @param names the objects to submit
- * @param flags submit properties
- * @return A PdfAction
- */
- public static PdfAction createSubmitForm(String file, Object names[], int flags) {
- PdfAction action = new PdfAction();
- action.put(PdfName.S, PdfName.SUBMITFORM);
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.F, new PdfString(file));
- dic.put(PdfName.FS, PdfName.URL);
- action.put(PdfName.F, dic);
- if (names != null)
- action.put(PdfName.FIELDS, buildArray(names));
- action.put(PdfName.FLAGS, new PdfNumber(flags));
- return action;
- }
-
- /**
- * Creates a resetform.
- * @param names the objects to reset
- * @param flags submit properties
- * @return A PdfAction
- */
- public static PdfAction createResetForm(Object names[], int flags) {
- PdfAction action = new PdfAction();
- action.put(PdfName.S, PdfName.RESETFORM);
- if (names != null)
- action.put(PdfName.FIELDS, buildArray(names));
- action.put(PdfName.FLAGS, new PdfNumber(flags));
- return action;
- }
-
- /**
- * Creates an Import field.
- * @param file
- * @return A PdfAction
- */
- public static PdfAction createImportData(String file) {
- PdfAction action = new PdfAction();
- action.put(PdfName.S, PdfName.IMPORTDATA);
- action.put(PdfName.F, new PdfString(file));
- return action;
- }
-
- /** Add a chained action.
- * @param na the next action
- */
- public void next(PdfAction na) {
- PdfObject nextAction = get(PdfName.NEXT);
- if (nextAction == null)
- put(PdfName.NEXT, na);
- else if (nextAction.isDictionary()) {
- PdfArray array = new PdfArray(nextAction);
- array.add(na);
- put(PdfName.NEXT, array);
- }
- else {
- ((PdfArray)nextAction).add(na);
- }
- }
-
- /** Creates a GoTo action to an internal page.
- * @param page the page to go. First page is 1
- * @param dest the destination for the page
- * @param writer the writer for this action
- * @return a GoTo action
- */
- public static PdfAction gotoLocalPage(int page, PdfDestination dest, PdfWriter writer) {
- PdfIndirectReference ref = writer.getPageReference(page);
- dest.addPage(ref);
- PdfAction action = new PdfAction();
- action.put(PdfName.S, PdfName.GOTO);
- action.put(PdfName.D, dest);
- return action;
- }
-
- /**
- * Creates a GoTo action to a named destination.
- * @param dest the named destination
- * @param isName if true sets the destination as a name, if false sets it as a String
- * @return a GoToR action
- */
- public static PdfAction gotoLocalPage(String dest, boolean isName) {
- PdfAction action = new PdfAction();
- action.put(PdfName.S, PdfName.GOTO);
- if (isName)
- action.put(PdfName.D, new PdfName(dest));
- else
- action.put(PdfName.D, new PdfString(dest, null));
- return action;
- }
-
- /**
- * Creates a GoToR action to a named destination.
- * @param filename the file name to go to
- * @param dest the destination name
- * @param isName if true sets the destination as a name, if false sets it as a String
- * @param newWindow open the document in a new window if true
, if false the current document is replaced by the new document.
- * @return a GoToR action
- */
- public static PdfAction gotoRemotePage(String filename, String dest, boolean isName, boolean newWindow) {
- PdfAction action = new PdfAction();
- action.put(PdfName.F, new PdfString(filename));
- action.put(PdfName.S, PdfName.GOTOR);
- if (isName)
- action.put(PdfName.D, new PdfName(dest));
- else
- action.put(PdfName.D, new PdfString(dest, null));
- if (newWindow)
- action.put(PdfName.NEWWINDOW, PdfBoolean.PDFTRUE);
- return action;
- }
-
- /**
- * A set-OCG-state action (PDF 1.5) sets the state of one or more optional content
- * groups.
- * @param state an array consisting of any number of sequences beginning with a PdfName
- * or String
(ON, OFF, or Toggle) followed by one or more optional content group dictionaries
- * PdfLayer
or a PdfIndirectReference
to a PdfLayer
.
- * The array elements are processed from left to right; each name is applied
- * to the subsequent groups until the next name is encountered:
- *
- * ON sets the state of subsequent groups to ON
- * OFF sets the state of subsequent groups to OFF
- * Toggle reverses the state of subsequent groups
- *
- * @param preserveRB if true
, indicates that radio-button state relationships between optional
- * content groups (as specified by the RBGroups entry in the current configuration
- * dictionary) should be preserved when the states in the
- * state
array are applied. That is, if a group is set to ON (either by ON or Toggle) during
- * processing of the state
array, any other groups belong to the same radio-button
- * group are turned OFF. If a group is set to OFF, there is no effect on other groups.
- * If false
, radio-button state relationships, if any, are ignored
- * @return the action
- */
- public static PdfAction setOCGstate(ArrayList state, boolean preserveRB) {
- PdfAction action = new PdfAction();
- action.put(PdfName.S, PdfName.SETOCGSTATE);
- PdfArray a = new PdfArray();
- for (int k = 0; k < state.size(); ++k) {
- Object o = state.get(k);
- if (o == null)
- continue;
- if (o instanceof PdfIndirectReference)
- a.add((PdfIndirectReference)o);
- else if (o instanceof PdfLayer)
- a.add(((PdfLayer)o).getRef());
- else if (o instanceof PdfName)
- a.add((PdfName)o);
- else if (o instanceof String) {
- PdfName name = null;
- String s = (String)o;
- if (s.equalsIgnoreCase("on"))
- name = PdfName.ON;
- else if (s.equalsIgnoreCase("off"))
- name = PdfName.OFF;
- else if (s.equalsIgnoreCase("toggle"))
- name = PdfName.TOGGLE;
- else
- throw new IllegalArgumentException("A string '" + s + " was passed in state. Only 'ON', 'OFF' and 'Toggle' are allowed.");
- a.add(name);
- }
- else
- throw new IllegalArgumentException("Invalid type was passed in state: " + o.getClass().getName());
- }
- action.put(PdfName.STATE, a);
- if (!preserveRB)
- action.put(PdfName.PRESERVERB, PdfBoolean.PDFFALSE);
- return action;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfAnnotation.java pdftk-2.01/java/com/lowagie/text/pdf/PdfAnnotation.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfAnnotation.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfAnnotation.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,747 +0,0 @@
-/*
- * $Id: PdfAnnotation.java,v 1.57 2005/01/06 13:42:25 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.Rectangle;
-import java.util.HashMap;
-import java.awt.Color;
-import java.io.*;
-/**
- * A PdfAnnotation
is a note that is associated with a page.
- *
- * @see PdfDictionary
- */
-
-public class PdfAnnotation extends PdfDictionary {
- /** highlight attributename */
- public static final PdfName HIGHLIGHT_NONE = PdfName.N;
- /** highlight attributename */
- public static final PdfName HIGHLIGHT_INVERT = PdfName.I;
- /** highlight attributename */
- public static final PdfName HIGHLIGHT_OUTLINE = PdfName.O;
- /** highlight attributename */
- public static final PdfName HIGHLIGHT_PUSH = PdfName.P;
- /** highlight attributename */
- public static final PdfName HIGHLIGHT_TOGGLE = PdfName.T;
- /** flagvalue */
- public static final int FLAGS_INVISIBLE = 1;
- /** flagvalue */
- public static final int FLAGS_HIDDEN = 2;
- /** flagvalue */
- public static final int FLAGS_PRINT = 4;
- /** flagvalue */
- public static final int FLAGS_NOZOOM = 8;
- /** flagvalue */
- public static final int FLAGS_NOROTATE = 16;
- /** flagvalue */
- public static final int FLAGS_NOVIEW = 32;
- /** flagvalue */
- public static final int FLAGS_READONLY = 64;
- /** flagvalue */
- public static final int FLAGS_LOCKED = 128;
- /** flagvalue */
- public static final int FLAGS_TOGGLENOVIEW = 256;
- /** appearance attributename */
- public static final PdfName APPEARANCE_NORMAL = PdfName.N;
- /** appearance attributename */
- public static final PdfName APPEARANCE_ROLLOVER = PdfName.R;
- /** appearance attributename */
- public static final PdfName APPEARANCE_DOWN = PdfName.D;
- /** attributevalue */
- public static final PdfName AA_ENTER = PdfName.E;
- /** attributevalue */
- public static final PdfName AA_EXIT = PdfName.X;
- /** attributevalue */
- public static final PdfName AA_DOWN = PdfName.D;
- /** attributevalue */
- public static final PdfName AA_UP = PdfName.U;
- /** attributevalue */
- public static final PdfName AA_FOCUS = PdfName.FO;
- /** attributevalue */
- public static final PdfName AA_BLUR = PdfName.BL;
- /** attributevalue */
- public static final PdfName AA_JS_KEY = PdfName.K;
- /** attributevalue */
- public static final PdfName AA_JS_FORMAT = PdfName.F;
- /** attributevalue */
- public static final PdfName AA_JS_CHANGE = PdfName.V;
- /** attributevalue */
- public static final PdfName AA_JS_OTHER_CHANGE = PdfName.C;
- /** attributevalue */
- public static final int MARKUP_HIGHLIGHT = 0;
- /** attributevalue */
- public static final int MARKUP_UNDERLINE = 1;
- /** attributevalue */
- public static final int MARKUP_STRIKEOUT = 2;
-
- protected PdfWriter writer;
- protected PdfIndirectReference reference;
- protected HashMap templates;
- protected boolean form = false;
- protected boolean annotation = true;
-
- /** Holds value of property used. */
- protected boolean used = false;
-
- /** Holds value of property placeInPage. */
- private int placeInPage = -1;
-
- // constructors
- public PdfAnnotation(PdfWriter writer, Rectangle rect) {
- this.writer = writer;
- if (rect != null)
- put(PdfName.RECT, new PdfRectangle(rect));
- }
-
-/**
- * Constructs a new PdfAnnotation
of subtype text.
- * @param writer
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @param title
- * @param content
- */
-
- PdfAnnotation(PdfWriter writer, float llx, float lly, float urx, float ury, PdfString title, PdfString content) {
- this.writer = writer;
- put(PdfName.SUBTYPE, PdfName.TEXT);
- put(PdfName.T, title);
- put(PdfName.RECT, new PdfRectangle(llx, lly, urx, ury));
- put(PdfName.CONTENTS, content);
- }
-
-/**
- * Constructs a new PdfAnnotation
of subtype link (Action).
- * @param writer
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @param action
- */
-
- public PdfAnnotation(PdfWriter writer, float llx, float lly, float urx, float ury, PdfAction action) {
- this.writer = writer;
- put(PdfName.SUBTYPE, PdfName.LINK);
- put(PdfName.RECT, new PdfRectangle(llx, lly, urx, ury));
- put(PdfName.A, action);
- put(PdfName.BORDER, new PdfBorderArray(0, 0, 0));
- put(PdfName.C, new PdfColor(0x00, 0x00, 0xFF));
- }
-
- /**
- * Creates a screen PdfAnnotation
- * @param writer
- * @param rect
- * @param clipTitle
- * @param fs
- * @param mimeType
- * @param playOnDisplay
- * @return a screen PdfAnnotation
- * @throws IOException
- */
- public static PdfAnnotation createScreen(PdfWriter writer, Rectangle rect, String clipTitle, PdfFileSpecification fs,
- String mimeType, boolean playOnDisplay) throws IOException {
- PdfAnnotation ann = new PdfAnnotation(writer, rect);
- ann.put(PdfName.SUBTYPE, PdfName.SCREEN);
- ann.put (PdfName.F, new PdfNumber(FLAGS_PRINT));
- ann.put(PdfName.TYPE, PdfName.ANNOT);
- ann.setPage();
- PdfIndirectReference ref = ann.getIndirectReference();
- PdfAction action = PdfAction.rendition(clipTitle,fs,mimeType, ref);
- PdfIndirectReference actionRef = writer.addToBody(action).getIndirectReference();
- // for play on display add trigger event
- if (playOnDisplay)
- {
- PdfDictionary aa = new PdfDictionary();
- aa.put(new PdfName("PV"), actionRef);
- ann.put(PdfName.AA, aa);
- }
- ann.put(PdfName.A, actionRef);
- return ann;
- }
-
- PdfIndirectReference getIndirectReference() {
- if (reference == null) {
- reference = writer.getPdfIndirectReference();
- }
- return reference;
- }
-
- /**
- * @param writer
- * @param rect
- * @param title
- * @param contents
- * @param open
- * @param icon
- * @return a PdfAnnotation
- */
- public static PdfAnnotation createText(PdfWriter writer, Rectangle rect, String title, String contents, boolean open, String icon) {
- PdfAnnotation annot = new PdfAnnotation(writer, rect);
- annot.put(PdfName.SUBTYPE, PdfName.TEXT);
- if (title != null)
- annot.put(PdfName.T, new PdfString(title, PdfObject.TEXT_UNICODE));
- if (contents != null)
- annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
- if (open)
- annot.put(PdfName.OPEN, PdfBoolean.PDFTRUE);
- if (icon != null) {
- annot.put(PdfName.NAME, new PdfName(icon));
- }
- return annot;
- }
-
- /**
- * Creates a link.
- * @param writer
- * @param rect
- * @param highlight
- * @return A PdfAnnotation
- */
- protected static PdfAnnotation createLink(PdfWriter writer, Rectangle rect, PdfName highlight) {
- PdfAnnotation annot = new PdfAnnotation(writer, rect);
- annot.put(PdfName.SUBTYPE, PdfName.LINK);
- if (!highlight.equals(HIGHLIGHT_INVERT))
- annot.put(PdfName.H, highlight);
- return annot;
- }
-
- /**
- * Creates an Annotation with an Action.
- * @param writer
- * @param rect
- * @param highlight
- * @param action
- * @return A PdfAnnotation
- */
- public static PdfAnnotation createLink(PdfWriter writer, Rectangle rect, PdfName highlight, PdfAction action) {
- PdfAnnotation annot = createLink(writer, rect, highlight);
- annot.putEx(PdfName.A, action);
- return annot;
- }
-
- /**
- * Creates an Annotation with an local destination.
- * @param writer
- * @param rect
- * @param highlight
- * @param namedDestination
- * @return A PdfAnnotation
- */
- public static PdfAnnotation createLink(PdfWriter writer, Rectangle rect, PdfName highlight, String namedDestination) {
- PdfAnnotation annot = createLink(writer, rect, highlight);
- annot.put(PdfName.DEST, new PdfString(namedDestination));
- return annot;
- }
-
- /**
- * Creates an Annotation with a PdfDestination.
- * @param writer
- * @param rect
- * @param highlight
- * @param page
- * @param dest
- * @return A PdfAnnotation
- */
- public static PdfAnnotation createLink(PdfWriter writer, Rectangle rect, PdfName highlight, int page, PdfDestination dest) {
- PdfAnnotation annot = createLink(writer, rect, highlight);
- PdfIndirectReference ref = writer.getPageReference(page);
- dest.addPage(ref);
- annot.put(PdfName.DEST, dest);
- return annot;
- }
-
- /**
- * Add some free text to the document.
- * @param writer
- * @param rect
- * @param contents
- * @param defaultAppearance
- * @return A PdfAnnotation
- */
- public static PdfAnnotation createFreeText(PdfWriter writer, Rectangle rect, String contents, PdfContentByte defaultAppearance) {
- PdfAnnotation annot = new PdfAnnotation(writer, rect);
- annot.put(PdfName.SUBTYPE, PdfName.FREETEXT);
- annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
- annot.setDefaultAppearanceString(defaultAppearance);
- return annot;
- }
-
- /**
- * Adds a line to the document. Move over the line and a tooltip is shown.
- * @param writer
- * @param rect
- * @param contents
- * @param x1
- * @param y1
- * @param x2
- * @param y2
- * @return A PdfAnnotation
- */
- public static PdfAnnotation createLine(PdfWriter writer, Rectangle rect, String contents, float x1, float y1, float x2, float y2) {
- PdfAnnotation annot = new PdfAnnotation(writer, rect);
- annot.put(PdfName.SUBTYPE, PdfName.LINE);
- annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
- PdfArray array = new PdfArray(new PdfNumber(x1));
- array.add(new PdfNumber(y1));
- array.add(new PdfNumber(x2));
- array.add(new PdfNumber(y2));
- annot.put(PdfName.L, array);
- return annot;
- }
-
- /**
- * Adds a circle or a square that shows a tooltip when you pass over it.
- * @param writer
- * @param rect
- * @param contents The tooltip
- * @param square true if you want a square, false if you want a circle
- * @return A PdfAnnotation
- */
- public static PdfAnnotation createSquareCircle(PdfWriter writer, Rectangle rect, String contents, boolean square) {
- PdfAnnotation annot = new PdfAnnotation(writer, rect);
- if (square)
- annot.put(PdfName.SUBTYPE, PdfName.SQUARE);
- else
- annot.put(PdfName.SUBTYPE, PdfName.CIRCLE);
- annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
- return annot;
- }
-
- public static PdfAnnotation createMarkup(PdfWriter writer, Rectangle rect, String contents, int type, float quadPoints[]) {
- PdfAnnotation annot = new PdfAnnotation(writer, rect);
- PdfName name = PdfName.HIGHLIGHT;
- switch (type) {
- case MARKUP_UNDERLINE:
- name = PdfName.UNDERLINE;
- break;
- case MARKUP_STRIKEOUT:
- name = PdfName.STRIKEOUT;
- break;
- }
- annot.put(PdfName.SUBTYPE, name);
- annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
- PdfArray array = new PdfArray();
- for (int k = 0; k < quadPoints.length; ++k)
- array.add(new PdfNumber(quadPoints[k]));
- annot.put(PdfName.QUADPOINTS, array);
- return annot;
- }
-
- /**
- * Adds a Stamp to your document. Move over the stamp and a tooltip is shown
- * @param writer
- * @param rect
- * @param contents
- * @param name
- * @return A PdfAnnotation
- */
- public static PdfAnnotation createStamp(PdfWriter writer, Rectangle rect, String contents, String name) {
- PdfAnnotation annot = new PdfAnnotation(writer, rect);
- annot.put(PdfName.SUBTYPE, PdfName.STAMP);
- annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
- annot.put(PdfName.NAME, new PdfName(name));
- return annot;
- }
-
- public static PdfAnnotation createInk(PdfWriter writer, Rectangle rect, String contents, float inkList[][]) {
- PdfAnnotation annot = new PdfAnnotation(writer, rect);
- annot.put(PdfName.SUBTYPE, PdfName.INK);
- annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
- PdfArray outer = new PdfArray();
- for (int k = 0; k < inkList.length; ++k) {
- PdfArray inner = new PdfArray();
- float deep[] = inkList[k];
- for (int j = 0; j < deep.length; ++j)
- inner.add(new PdfNumber(deep[j]));
- outer.add(inner);
- }
- annot.put(PdfName.INKLIST, outer);
- return annot;
- }
-
- /** Creates a file attachment annotation.
- * @param writer the PdfWriter
- * @param rect the dimensions in the page of the annotation
- * @param contents the file description
- * @param fileStore an array with the file. If it's null
- * the file will be read from the disk
- * @param file the path to the file. It will only be used if
- * fileStore
is not null
- * @param fileDisplay the actual file name stored in the pdf
- * @throws IOException on error
- * @return the annotation
- */
- public static PdfAnnotation createFileAttachment(PdfWriter writer, Rectangle rect, String contents, byte fileStore[], String file, String fileDisplay) throws IOException {
- return createFileAttachment(writer, rect, contents, PdfFileSpecification.fileEmbedded(writer, file, fileDisplay, fileStore));
- }
-
- /** Creates a file attachment annotation
- * @param writer
- * @param rect
- * @param contents
- * @param fs
- * @return the annotation
- * @throws IOException
- */
- public static PdfAnnotation createFileAttachment(PdfWriter writer, Rectangle rect, String contents, PdfFileSpecification fs) throws IOException {
- PdfAnnotation annot = new PdfAnnotation(writer, rect);
- annot.put(PdfName.SUBTYPE, PdfName.FILEATTACHMENT);
- annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
- annot.put(PdfName.FS, fs.getReference());
- return annot;
- }
-
- /**
- * Adds a popup to your document.
- * @param writer
- * @param rect
- * @param contents
- * @param open
- * @return A PdfAnnotation
- */
- public static PdfAnnotation createPopup(PdfWriter writer, Rectangle rect, String contents, boolean open) {
- PdfAnnotation annot = new PdfAnnotation(writer, rect);
- annot.put(PdfName.SUBTYPE, PdfName.POPUP);
- if (contents != null)
- annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
- if (open)
- annot.put(PdfName.OPEN, PdfBoolean.PDFTRUE);
- return annot;
- }
-
- public void setDefaultAppearanceString(PdfContentByte cb) {
- byte b[] = cb.getInternalBuffer().toByteArray();
- int len = b.length;
- for (int k = 0; k < len; ++k) {
- if (b[k] == '\n')
- b[k] = 32;
- }
- put(PdfName.DA, new PdfString( b, PdfObject.NOTHING )); // ssteward: added encoding
- }
-
- public void setFlags(int flags) {
- if (flags == 0)
- remove(PdfName.F);
- else
- put(PdfName.F, new PdfNumber(flags));
- }
-
- public void setBorder(PdfBorderArray border) {
- putDel(PdfName.BORDER, border);
- }
-
- public void setBorderStyle(PdfBorderDictionary border) {
- putDel(PdfName.BS, border);
- }
-
- /**
- * Sets the annotation's highlighting mode. The values can be
- * HIGHLIGHT_NONE
, HIGHLIGHT_INVERT
,
- * HIGHLIGHT_OUTLINE
and HIGHLIGHT_PUSH
;
- * @param highlight the annotation's highlighting mode
- */
- public void setHighlighting(PdfName highlight) {
- if (highlight.equals(HIGHLIGHT_INVERT))
- remove(PdfName.H);
- else
- put(PdfName.H, highlight);
- }
-
- public void setAppearance(PdfName ap, PdfTemplate template) {
- PdfDictionary dic = (PdfDictionary)get(PdfName.AP);
- if (dic == null)
- dic = new PdfDictionary();
- dic.put(ap, template.getIndirectReference());
- put(PdfName.AP, dic);
- if (!form)
- return;
- if (templates == null)
- templates = new HashMap();
- templates.put(template, null);
- }
-
- public void setAppearance(PdfName ap, String state, PdfTemplate template) {
- PdfDictionary dicAp = (PdfDictionary)get(PdfName.AP);
- if (dicAp == null)
- dicAp = new PdfDictionary();
-
- PdfDictionary dic;
- PdfObject obj = dicAp.get(ap);
- if (obj != null && obj.isDictionary())
- dic = (PdfDictionary)obj;
- else
- dic = new PdfDictionary();
- dic.put(new PdfName(state), template.getIndirectReference());
- dicAp.put(ap, dic);
- put(PdfName.AP, dicAp);
- if (!form)
- return;
- if (templates == null)
- templates = new HashMap();
- templates.put(template, null);
- }
-
- public void setAppearanceState(String state) {
- if (state == null) {
- remove(PdfName.AS);
- return;
- }
- put(PdfName.AS, new PdfName(state));
- }
-
- public void setColor(Color color) {
- putDel(PdfName.C, new PdfColor(color));
- }
-
- public void setTitle(String title) {
- if (title == null) {
- remove(PdfName.T);
- return;
- }
- put(PdfName.T, new PdfString(title, PdfObject.TEXT_UNICODE));
- }
-
- public void setPopup(PdfAnnotation popup) {
- put(PdfName.POPUP, popup.getIndirectReference());
- popup.put(PdfName.PARENT, getIndirectReference());
- }
-
- public void setAction(PdfAction action) {
- putDel(PdfName.A, action);
- }
-
- public void setAdditionalActions(PdfName key, PdfAction action) {
- PdfDictionary dic;
- PdfObject obj = get(PdfName.AA);
- if (obj != null && obj.isDictionary())
- dic = (PdfDictionary)obj;
- else
- dic = new PdfDictionary();
- dic.put(key, action);
- put(PdfName.AA, dic);
- }
-
- /** Getter for property used.
- * @return Value of property used.
- */
- public boolean isUsed() {
- return used;
- }
-
- /** Setter for property used.
- */
- void setUsed() {
- used = true;
- }
-
- HashMap getTemplates() {
- return templates;
- }
-
- /** Getter for property form.
- * @return Value of property form.
- */
- public boolean isForm() {
- return form;
- }
-
- /** Getter for property annotation.
- * @return Value of property annotation.
- */
- public boolean isAnnotation() {
- return annotation;
- }
-
- public void setPage(int page) {
- put(PdfName.P, writer.getPageReference(page));
- }
-
- public void setPage() {
- put(PdfName.P, writer.getCurrentPage());
- }
-
- /** Getter for property placeInPage.
- * @return Value of property placeInPage.
- */
- public int getPlaceInPage() {
- return placeInPage;
- }
-
- /** Places the annotation in a specified page that must be greater
- * or equal to the current one. With PdfStamper
the page
- * can be any. The first page is 1.
- * @param placeInPage New value of property placeInPage.
- */
- public void setPlaceInPage(int placeInPage) {
- this.placeInPage = placeInPage;
- }
-
- public void setRotate(int v) {
- put(PdfName.ROTATE, new PdfNumber(v));
- }
-
- PdfDictionary getMK() {
- PdfDictionary mk = (PdfDictionary)get(PdfName.MK);
- if (mk == null) {
- mk = new PdfDictionary();
- put(PdfName.MK, mk);
- }
- return mk;
- }
-
- public void setMKRotation(int rotation) {
- getMK().put(PdfName.R, new PdfNumber(rotation));
- }
-
- public static PdfArray getMKColor(Color color) {
- PdfArray array = new PdfArray();
- int type = ExtendedColor.getType(color);
- switch (type) {
- case ExtendedColor.TYPE_GRAY: {
- array.add(new PdfNumber(((GrayColor)color).getGray()));
- break;
- }
- case ExtendedColor.TYPE_CMYK: {
- CMYKColor cmyk = (CMYKColor)color;
- array.add(new PdfNumber(cmyk.getCyan()));
- array.add(new PdfNumber(cmyk.getMagenta()));
- array.add(new PdfNumber(cmyk.getYellow()));
- array.add(new PdfNumber(cmyk.getBlack()));
- break;
- }
- case ExtendedColor.TYPE_SEPARATION:
- case ExtendedColor.TYPE_PATTERN:
- case ExtendedColor.TYPE_SHADING:
- throw new RuntimeException("Separations, patterns and shadings are not allowed in MK dictionary.");
- default:
- array.add(new PdfNumber(color.getRed() / 255f));
- array.add(new PdfNumber(color.getGreen() / 255f));
- array.add(new PdfNumber(color.getBlue() / 255f));
- }
- return array;
- }
-
- public void setMKBorderColor(Color color) {
- if (color == null)
- getMK().remove(PdfName.BC);
- else
- getMK().put(PdfName.BC, getMKColor(color));
- }
-
- public void setMKBackgroundColor(Color color) {
- if (color == null)
- getMK().remove(PdfName.BG);
- else
- getMK().put(PdfName.BG, getMKColor(color));
- }
-
- public void setMKNormalCaption(String caption) {
- getMK().put(PdfName.CA, new PdfString(caption, PdfObject.TEXT_UNICODE));
- }
-
- public void setMKRolloverCaption(String caption) {
- getMK().put(PdfName.RC, new PdfString(caption, PdfObject.TEXT_UNICODE));
- }
-
- public void setMKAlternateCaption(String caption) {
- getMK().put(PdfName.AC, new PdfString(caption, PdfObject.TEXT_UNICODE));
- }
-
- public void setMKNormalIcon(PdfTemplate template) {
- getMK().put(PdfName.I, template.getIndirectReference());
- }
-
- public void setMKRolloverIcon(PdfTemplate template) {
- getMK().put(PdfName.RI, template.getIndirectReference());
- }
-
- public void setMKAlternateIcon(PdfTemplate template) {
- getMK().put(PdfName.IX, template.getIndirectReference());
- }
-
- public void setMKIconFit(PdfName scale, PdfName scalingType, float leftoverLeft, float leftoverBottom, boolean fitInBounds) {
- PdfDictionary dic = new PdfDictionary();
- if (!scale.equals(PdfName.A))
- dic.put(PdfName.SW, scale);
- if (!scalingType.equals(PdfName.P))
- dic.put(PdfName.S, scalingType);
- if (leftoverLeft != 0.5f || leftoverBottom != 0.5f) {
- PdfArray array = new PdfArray(new PdfNumber(leftoverLeft));
- array.add(new PdfNumber(leftoverBottom));
- dic.put(PdfName.A, array);
- }
- if (fitInBounds)
- dic.put(PdfName.FB, PdfBoolean.PDFTRUE);
- getMK().put(PdfName.IF, dic);
- }
-
- public void setMKTextPosition(int tp) {
- getMK().put(PdfName.TP, new PdfNumber(tp));
- }
-
- /**
- * Sets the layer this annotation belongs to.
- * @param layer the layer this annotation belongs to
- */
- public void setLayer(PdfOCG layer) {
- put(PdfName.OC, layer.getRef());
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfAppearance.java pdftk-2.01/java/com/lowagie/text/pdf/PdfAppearance.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfAppearance.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfAppearance.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,158 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * Copyright 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import com.lowagie.text.Rectangle;
-import java.util.HashMap;
-
-/**
- * Implements the appearance stream to be used with form fields..
- */
-
-public class PdfAppearance extends PdfTemplate {
-
- public static final HashMap stdFieldFontNames = new HashMap();
- static {
- stdFieldFontNames.put("Courier-BoldOblique", new PdfName("CoBO"));
- stdFieldFontNames.put("Courier-Bold", new PdfName("CoBo"));
- stdFieldFontNames.put("Courier-Oblique", new PdfName("CoOb"));
- stdFieldFontNames.put("Courier", new PdfName("Cour"));
- stdFieldFontNames.put("Helvetica-BoldOblique", new PdfName("HeBO"));
- stdFieldFontNames.put("Helvetica-Bold", new PdfName("HeBo"));
- stdFieldFontNames.put("Helvetica-Oblique", new PdfName("HeOb"));
- stdFieldFontNames.put("Helvetica", new PdfName("Helv"));
- stdFieldFontNames.put("Symbol", new PdfName("Symb"));
- stdFieldFontNames.put("Times-BoldItalic", new PdfName("TiBI"));
- stdFieldFontNames.put("Times-Bold", new PdfName("TiBo"));
- stdFieldFontNames.put("Times-Italic", new PdfName("TiIt"));
- stdFieldFontNames.put("Times-Roman", new PdfName("TiRo"));
- stdFieldFontNames.put("ZapfDingbats", new PdfName("ZaDb"));
- stdFieldFontNames.put("HYSMyeongJo-Medium", new PdfName("HySm"));
- stdFieldFontNames.put("HYGoThic-Medium", new PdfName("HyGo"));
- stdFieldFontNames.put("HeiseiKakuGo-W5", new PdfName("KaGo"));
- stdFieldFontNames.put("HeiseiMin-W3", new PdfName("KaMi"));
- stdFieldFontNames.put("MHei-Medium", new PdfName("MHei"));
- stdFieldFontNames.put("MSung-Light", new PdfName("MSun"));
- stdFieldFontNames.put("STSong-Light", new PdfName("STSo"));
- stdFieldFontNames.put("MSungStd-Light", new PdfName("MSun"));
- stdFieldFontNames.put("STSongStd-Light", new PdfName("STSo"));
- stdFieldFontNames.put("HYSMyeongJoStd-Medium", new PdfName("HySm"));
- stdFieldFontNames.put("KozMinPro-Regular", new PdfName("KaMi"));
- }
-
- /**
- *Creates a PdfAppearance
.
- */
-
- PdfAppearance() {
- super();
- separator = ' ';
- }
-
- PdfAppearance(PdfIndirectReference iref) {
- thisReference = iref;
- }
-
- /**
- * Creates new PdfTemplate
- *
- * @param wr the PdfWriter
- */
-
- PdfAppearance(PdfWriter wr) {
- super(wr);
- separator = ' ';
- }
-
- /**
- * Set the font and the size for the subsequent text writing.
- *
- * @param bf the font
- * @param size the font size in points
- */
- public void setFontAndSize(BaseFont bf, float size) {
- checkWriter();
- state.size = size;
- if (bf.getFontType() == BaseFont.FONT_TYPE_DOCUMENT) {
- state.fontDetails = new FontDetails(null, ((DocumentFont)bf).getIndirectReference(), bf);
- }
- else
- state.fontDetails = writer.addSimple(bf);
- PdfName psn = (PdfName)stdFieldFontNames.get(bf.getPostscriptFontName());
- if (psn == null) {
- psn = new PdfName(bf.getPostscriptFontName());
- bf.setSubset(false);
- }
- PageResources prs = getPageResources();
-// PdfName name = state.fontDetails.getFontName();
- prs.addFont(psn, state.fontDetails.getIndirectReference());
- content.append(psn.getBytes()).append(' ').append(size).append(" Tf").append_i(separator);
- }
-
- public PdfContentByte getDuplicate() {
- PdfAppearance tpl = new PdfAppearance();
- tpl.writer = writer;
- tpl.pdf = pdf;
- tpl.thisReference = thisReference;
- tpl.pageResources = pageResources;
- tpl.bBox = new Rectangle(bBox);
- tpl.group = group;
- tpl.layer = layer;
- if (matrix != null) {
- tpl.matrix = new PdfArray(matrix);
- }
- tpl.separator = separator;
- return tpl;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfArray.java pdftk-2.01/java/com/lowagie/text/pdf/PdfArray.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfArray.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfArray.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,230 +0,0 @@
-/*
- * $Id: PdfArray.java,v 1.37 2003/05/02 09:01:13 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.ListIterator;
-
-/**
- * PdfArray
is the PDF Array object.
- *
- * An array is a sequence of PDF objects. An array may contain a mixture of object types.
- * An array is written as a left square bracket ([), followed by a sequence of objects,
- * followed by a right square bracket (]).
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 4.6 (page 40).
- *
- * @see PdfObject
- */
-
-public class PdfArray extends PdfObject {
-
- // membervariables
-
-/** this is the actual array of PdfObjects */
- protected ArrayList arrayList;
-
- // constructors
-
-/**
- * Constructs an empty PdfArray
-object.
- */
-
- public PdfArray() {
- super(ARRAY);
- arrayList = new ArrayList();
- }
-
-/**
- * Constructs an PdfArray
-object, containing 1 PdfObject
.
- *
- * @param object a PdfObject
that has to be added to the array
- */
-
- public PdfArray(PdfObject object) {
- super(ARRAY);
- arrayList = new ArrayList();
- arrayList.add(object);
- }
-
- public PdfArray(float values[]) {
- super(ARRAY);
- arrayList = new ArrayList();
- add(values);
- }
-
- public PdfArray(int values[]) {
- super(ARRAY);
- arrayList = new ArrayList();
- add(values);
- }
-
-/**
- * Constructs an PdfArray
-object, containing all the PdfObject
s in a given PdfArray
.
- *
- * @param array a PdfArray
that has to be added to the array
- */
-
- public PdfArray(PdfArray array) {
- super(ARRAY);
- arrayList = new ArrayList(array.getArrayList());
- }
-
- // methods overriding some methods in PdfObject
-
-/**
- * Returns the PDF representation of this PdfArray
.
- *
- * @return an array of byte
s
- */
-
- public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
- os.write('[');
-
- Iterator i = arrayList.iterator();
- PdfObject object;
- // int type = 0; // ssteward
- if (i.hasNext()) {
- object = (PdfObject) i.next();
- object.toPdf(writer, os);
- }
- while (i.hasNext()) {
- object = (PdfObject) i.next();
- // ssteward
- //type = object.type();
- //if (type != PdfObject.ARRAY && type != PdfObject.DICTIONARY && type != PdfObject.NAME && type != PdfObject.STRING)
- os.write(' ');
- object.toPdf(writer, os);
- }
- os.write(']');
- }
-
- // methods concerning the ArrayList-membervalue
-
-/**
- * Returns an ArrayList containing PdfObject
s.
- *
- * @return an ArrayList
- */
-
- public ArrayList getArrayList() {
- return arrayList;
- }
-
-/**
- * Returns the number of entries in the array.
- *
- * @return the size of the ArrayList
- */
-
- public int size() {
- return arrayList.size();
- }
-
-/**
- * Adds a PdfObject
to the PdfArray
.
- *
- * @param object PdfObject
to add
- * @return true
- */
-
- public boolean add(PdfObject object) {
- return arrayList.add(object);
- }
-
- public boolean add(float values[]) {
- for (int k = 0; k < values.length; ++k)
- arrayList.add(new PdfNumber(values[k]));
- return true;
- }
-
- public boolean add(int values[]) {
- for (int k = 0; k < values.length; ++k)
- arrayList.add(new PdfNumber(values[k]));
- return true;
- }
-
-/**
- * Adds a PdfObject
to the PdfArray
.
- *
- * The newly added object will be the first element in the ArrayList
.
- *
- * @param object PdfObject
to add
- */
-
- public void addFirst(PdfObject object) {
- arrayList.add(0, object);
- }
-
-/**
- * Checks if the PdfArray
already contains a certain PdfObject
.
- *
- * @param object PdfObject
to check
- * @return true
- */
-
- public boolean contains(PdfObject object) {
- return arrayList.contains(object);
- }
-
- public ListIterator listIterator() {
- return arrayList.listIterator();
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfBarcode.java pdftk-2.01/java/com/lowagie/text/pdf/PdfBarcode.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfBarcode.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfBarcode.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,231 +0,0 @@
-/*
- * $Id: PdfBarcode.java,v 1.16 2002/06/20 13:28:22 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-
-/**
- * A barcode is a Chunk with a certain type of barcode font.
- *
- * With this class you can construct several types of barcode
- * in different sizes, representing any 'product' or 'article' number.
- */
-
-public class PdfBarcode extends com.lowagie.text.Chunk {
-
- /** This is a type of barcode. */
- public static final int CODE39 = 1;
-
- /** This is a type of barcode. */
- public static final int UPCA = 2;
-
- /** This is a type of barcode. */
- public static final int EAN13 = 3;
-
- /** This is a type of barcode. */
- public static final int INTERLEAVED_2_OF_5 = 4;
-
- /** The variable parity table in EAN 13 */
- public static final int[][] variableParity =
- { {0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2},
- {0, 0, 1, 0, 1, 1, 2, 2, 2, 2, 2, 2},
- {0, 0, 1, 1, 0, 1, 2, 2, 2, 2, 2, 2},
- {0, 0, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2},
- {0, 1, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2},
- {0, 1, 1, 0, 0, 1, 2, 2, 2, 2, 2, 2},
- {0, 1, 1, 1, 0, 0, 2, 2, 2, 2, 2, 2},
- {0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 2, 2},
- {0, 1, 0, 1, 1, 0, 2, 2, 2, 2, 2, 2},
- {0, 1, 1, 0, 1, 0, 2, 2, 2, 2, 2, 2} };
-
- /**
- * Creates a new Barcode.
- *
- * @param ttf the ttf file representing the barcode font
- * @param size the size of the barcode
- * @param number the number you want to convert to a barcode in String format
- */
-
- public PdfBarcode(String ttf, int type, int size, String number) throws com.lowagie.text.BadElementException, com.lowagie.text.DocumentException, java.io.IOException {
- super(convertToCode(type, number), new com.lowagie.text.Font(BaseFont.createFont(ttf, "winansi", true), size));
- }
-
- /**
- * Creates a new Barcode.
- *
- * @param ttf the ttf file representing the barcode font
- * @param size the size of the barcode
- * @param number the number you want to convert to a barcode in long format
- */
-
- public PdfBarcode(String ttf, int type, int size, long number) throws com.lowagie.text.BadElementException, com.lowagie.text.DocumentException, java.io.IOException {
- super(convertToCode(type, String.valueOf(number)), new com.lowagie.text.Font(BaseFont.createFont(ttf, "winansi", true), size));
- }
-
- /**
- * Converts a String representing a number to a barcode with a specific barcode font.
- *
- * @param type the type of barcode
- * @param number the number you want to convert to a barcode in long format
- */
-
- private static String convertToCode(int type, String number) throws com.lowagie.text.BadElementException {
- StringBuffer code = new StringBuffer();
- int length = number.length();
- int digit;
- int pos = 0;
- try {
- switch(type) {
- case CODE39:
- code.append('*');
- while (pos < length) {
- code.append(number.substring(pos, ++pos));
- }
- code.append('*');
- break;
- case UPCA:
- if (length > 12) throw new com.lowagie.text.BadElementException("An UPC-A barcode can only encode a 12 digit number (your number was " + number + ").");
- number = addZero(number, 12);
- digit = Integer.parseInt(number.substring(pos, ++pos));
- code.append((char) (digit + 80));
- while (pos < 6) {
- digit = Integer.parseInt(number.substring(pos, ++pos));
- code.append((char) (digit + 48));
- }
- code.append((char) 112);
- while (pos < 11) {
- digit = Integer.parseInt(number.substring(pos, ++pos));
- code.append((char) (digit + 64));
- }
- digit = Integer.parseInt(number.substring(11));
- code.append((char) (digit + 96));
- break;
- case EAN13:
- if (length > 13) throw new com.lowagie.text.BadElementException("An EAN-13 barcode can only encode a 13 digit number (your number was " + number + ").");
- number = addZero(number, 13);
- int firstdigit = Integer.parseInt(number.substring(pos, ++pos));
- code.append((char) (firstdigit + 33));
- digit = Integer.parseInt(number.substring(pos, ++pos));
- code.append((char) (digit + 96));
- while (pos < 7) {
- digit = Integer.parseInt(number.substring(pos, ++pos));
- code.append((char) (digit + 48 + 16 * variableParity[firstdigit][pos - 2]));
- }
- code.append((char) 124);
- while (pos < 12) {
- digit = Integer.parseInt(number.substring(pos, ++pos));
- code.append((char) (digit + 48 + 16 * variableParity[firstdigit][pos - 2]));
- }
- digit = Integer.parseInt(number.substring(12));
- code.append((char) (digit + 112));
- break;
- case INTERLEAVED_2_OF_5:
- if (length % 2 == 1) {
- number = addZero(number, length + 1);
- }
- code.append('(');
- while (number.length() > 2) {
- digit = Integer.parseInt(number.substring(0, 2));
- code.append(convertInterleaved(digit));
- pos += 2;
- number = number.substring(2);
- }
- digit = Integer.parseInt(number);
- code.append(convertInterleaved(digit));
- code.append(')');
- break;
- default:
- throw new com.lowagie.text.BadElementException("This type of barcode is not supported yet: " + type);
- }
- }
- catch(NumberFormatException nfe) {
- throw new com.lowagie.text.BadElementException("NumberFormatException at position " + pos + " in " + number + ": " + nfe.getMessage());
- }
- return code.toString();
- }
-
- /**
- * Converts an int to a convert interleaved character.
- */
-
- private static char convertInterleaved(int digits) throws NumberFormatException {
- int i;
- if (digits < 50) {
- i = 48;
- }
- else if (digits < 100) {
- i = 142;
- }
- else {
- throw new NumberFormatException(String.valueOf(digits));
- }
- return (char)(digits + i);
- }
-
- /**
- * Adds leading zeros.
- */
-
- private static String addZero(String number, int length) {
- StringBuffer buf = new StringBuffer();
- int zeros = length - number.length();
- for (int i = 0; i < zeros; i++) {
- buf.append('0');
- }
- buf.append(number);
- return buf.toString();
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfBoolean.java pdftk-2.01/java/com/lowagie/text/pdf/PdfBoolean.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfBoolean.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfBoolean.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,136 +0,0 @@
-/*
- * $Id: PdfBoolean.java,v 1.22 2002/06/20 13:28:22 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * PdfBoolean
is the boolean object represented by the keywords true or false .
- *
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 4.2 (page 37).
- *
- * @see PdfObject
- * @see BadPdfFormatException
- */
-
-public class PdfBoolean extends PdfObject {
-
- // static membervariables (possible values of a boolean object)
- public static final PdfBoolean PDFTRUE = new PdfBoolean(true);
- public static final PdfBoolean PDFFALSE = new PdfBoolean(false);
-/** A possible value of PdfBoolean
*/
- public static final String TRUE = "true";
-
-/** A possible value of PdfBoolean
*/
- public static final String FALSE = "false";
-
- // membervariables
-
-/** the boolean value of this object */
- private boolean value;
-
- // constructors
-
-/**
- * Constructs a PdfBoolean
-object.
- *
- * @param value the value of the new PdfObject
- */
-
- public PdfBoolean(boolean value) {
- super(BOOLEAN);
- if (value) {
- setContent(TRUE);
- }
- else {
- setContent(FALSE);
- }
- this.value = value;
- }
-
-/**
- * Constructs a PdfBoolean
-object.
- *
- * @param value the value of the new PdfObject
, represented as a String
- *
- * @throws BadPdfFormatException thrown if the value isn't 'true
' or 'false
'
- */
-
- public PdfBoolean(String value) throws BadPdfFormatException {
- super(BOOLEAN, value);
- if (value.equals(TRUE)) {
- this.value = true;
- }
- else if (value.equals(FALSE)) {
- this.value = false;
- }
- else {
- throw new BadPdfFormatException("The value has to be 'true' of 'false', instead of '" + value + "'.");
- }
- }
-
- // methods returning the value of this object
-
-/**
- * Returns the primitive value of the PdfBoolean
-object.
- *
- * @return the actual value of the object.
- */
-
- public boolean booleanValue() {
- return value;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfBorderArray.java pdftk-2.01/java/com/lowagie/text/pdf/PdfBorderArray.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfBorderArray.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfBorderArray.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,88 +0,0 @@
-/*
- * $Id: PdfBorderArray.java,v 1.23 2002/07/09 11:28:22 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * A PdfBorderArray
defines the border of a PdfAnnotation
.
- *
- * @see PdfArray
- */
-
-public class PdfBorderArray extends PdfArray {
-
- // constructors
-
-/**
- * Constructs a new PdfBorderArray
.
- */
-
- public PdfBorderArray(float hRadius, float vRadius, float width) {
- this(hRadius, vRadius, width, null);
- }
-
-/**
- * Constructs a new PdfBorderArray
.
- */
-
- public PdfBorderArray(float hRadius, float vRadius, float width, PdfDashPattern dash) {
- super(new PdfNumber(hRadius));
- add(new PdfNumber(vRadius));
- add(new PdfNumber(width));
- if (dash != null)
- add(dash);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfBorderDictionary.java pdftk-2.01/java/com/lowagie/text/pdf/PdfBorderDictionary.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfBorderDictionary.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfBorderDictionary.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,106 +0,0 @@
-/*
- * $Id: PdfBorderDictionary.java,v 1.22 2002/06/20 13:28:20 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * A PdfBorderDictionary
define the appearance of a Border (Annotations).
- *
- * @see PdfDictionary
- */
-
-public class PdfBorderDictionary extends PdfDictionary {
-
- public static final int STYLE_SOLID = 0;
- public static final int STYLE_DASHED = 1;
- public static final int STYLE_BEVELED = 2;
- public static final int STYLE_INSET = 3;
- public static final int STYLE_UNDERLINE = 4;
- // constructors
-
-/**
- * Constructs a PdfBorderDictionary
.
- */
-
- public PdfBorderDictionary(float borderWidth, int borderStyle, PdfDashPattern dashes) {
- put(PdfName.W, new PdfNumber(borderWidth));
- switch (borderStyle) {
- case STYLE_SOLID:
- put(PdfName.S, PdfName.S);
- break;
- case STYLE_DASHED:
- if (dashes != null)
- put(PdfName.D, dashes);
- put(PdfName.S, PdfName.D);
- break;
- case STYLE_BEVELED:
- put(PdfName.S, PdfName.B);
- break;
- case STYLE_INSET:
- put(PdfName.S, PdfName.I);
- break;
- case STYLE_UNDERLINE:
- put(PdfName.S, PdfName.U);
- break;
- default:
- throw new IllegalArgumentException("Invalid border style.");
- }
- }
-
- public PdfBorderDictionary(float borderWidth, int borderStyle) {
- this(borderWidth, borderStyle, null);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfChunk.java pdftk-2.01/java/com/lowagie/text/pdf/PdfChunk.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfChunk.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfChunk.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,800 +0,0 @@
-/*
- * $Id: PdfChunk.java,v 1.70 2004/12/20 11:39:08 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.awt.Color;
-
-import com.lowagie.text.Chunk;
-import com.lowagie.text.Font;
-//import com.lowagie.text.Image; ssteward: dropped in 1.44
-import com.lowagie.text.SplitCharacter;
-import java.util.HashMap;
-import java.util.Iterator;
-
-/**
- * A PdfChunk
is the PDF translation of a Chunk
.
- *
- * A PdfChunk
is a PdfString
in a certain
- * PdfFont
and Color
.
- *
- * @see PdfString
- * @see PdfFont
- * @see com.lowagie.text.Chunk
- * @see com.lowagie.text.Font
- */
-
-public class PdfChunk implements SplitCharacter{
-
- private static final char singleSpace[] = {' '};
- private static final PdfChunk thisChunk[] = new PdfChunk[1];
- private static final float ITALIC_ANGLE = 0.21256f;
-/** The allowed attributes in variable attributes
. */
- private static final HashMap keysAttributes = new HashMap();
-
-/** The allowed attributes in variable noStroke
. */
- private static final HashMap keysNoStroke = new HashMap();
-
- static {
- keysAttributes.put(Chunk.ACTION, null);
- keysAttributes.put(Chunk.UNDERLINE, null);
- keysAttributes.put(Chunk.REMOTEGOTO, null);
- keysAttributes.put(Chunk.LOCALGOTO, null);
- keysAttributes.put(Chunk.LOCALDESTINATION, null);
- keysAttributes.put(Chunk.GENERICTAG, null);
- keysAttributes.put(Chunk.NEWPAGE, null);
- keysAttributes.put(Chunk.IMAGE, null);
- keysAttributes.put(Chunk.BACKGROUND, null);
- keysAttributes.put(Chunk.PDFANNOTATION, null);
- keysAttributes.put(Chunk.SKEW, null);
- keysAttributes.put(Chunk.HSCALE, null);
- keysNoStroke.put(Chunk.SUBSUPSCRIPT, null);
- keysNoStroke.put(Chunk.SPLITCHARACTER, null);
- keysNoStroke.put(Chunk.HYPHENATION, null);
- keysNoStroke.put(Chunk.TEXTRENDERMODE, null);
- }
-
- // membervariables
-
- /** The value of this object. */
- protected String value = PdfObject.NOTHING;
-
- /** The encoding. */
- protected String encoding = BaseFont.WINANSI;
-
-
-/** The font for this PdfChunk
. */
- protected PdfFont font;
-
- protected BaseFont baseFont;
-
- protected SplitCharacter splitCharacter;
-/**
- * Metric attributes.
- *
- * This attributes require the mesurement of characters widths when rendering
- * such as underline.
- */
- protected HashMap attributes = new HashMap();
-
-/**
- * Non metric attributes.
- *
- * This attributes do not require the mesurement of characters widths when rendering
- * such as Color.
- */
- protected HashMap noStroke = new HashMap();
-
-/** true
if the chunk split was cause by a newline. */
- protected boolean newlineSplit;
-
-/** The image in this PdfChunk
, if it has one */
- // protected Image image; ssteward: dropped in 1.44
-
-/** The offset in the x direction for the image */
- protected float offsetX;
-
-/** The offset in the y direction for the image */
- protected float offsetY;
-
-/** Indicates if the height and offset of the Image has to be taken into account */
- protected boolean changeLeading = false;
-
- // constructors
-
-/**
- * Constructs a PdfChunk
-object.
- *
- * @param string the content of the PdfChunk
-object
- * @param other Chunk with the same style you want for the new Chunk
- */
-
- PdfChunk(String string, PdfChunk other) {
- thisChunk[0] = this;
- value = string;
- this.font = other.font;
- this.attributes = other.attributes;
- this.noStroke = other.noStroke;
- this.baseFont = other.baseFont;
- Object obj[] = (Object[])attributes.get(Chunk.IMAGE);
- if (obj == null) {
- // image = null; ssteward: dropped in 1.44
- }
- else {
- // image = (Image)obj[0]; ssteward: dropped in 1.44
- offsetX = ((Float)obj[1]).floatValue();
- offsetY = ((Float)obj[2]).floatValue();
- changeLeading = ((Boolean)obj[3]).booleanValue();
- }
- encoding = font.getFont().getEncoding();
- splitCharacter = (SplitCharacter)noStroke.get(Chunk.SPLITCHARACTER);
- if (splitCharacter == null)
- splitCharacter = this;
- }
-
-/**
- * Constructs a PdfChunk
-object.
- *
- * @param chunk the original Chunk
-object
- * @param action the PdfAction
if the Chunk
comes from an Anchor
- */
-
- PdfChunk(Chunk chunk, PdfAction action) {
- thisChunk[0] = this;
- value = chunk.content();
-
- Font f = chunk.font();
- float size = f.size();
- if (size == Font.UNDEFINED)
- size = 12;
- baseFont = f.getBaseFont();
- int style = f.style();
- if (style == Font.UNDEFINED) {
- style = Font.NORMAL;
- }
- if (baseFont == null) {
- // translation of the font-family to a PDF font-family
- baseFont = f.getCalculatedBaseFont(false);
- }
- else {
- // bold simulation
- if ((style & Font.BOLD) != 0)
- attributes.put(Chunk.TEXTRENDERMODE, new Object[]{new Integer(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE), new Float(size / 30f), null});
- // italic simulation
- if ((style & Font.ITALIC) != 0)
- attributes.put(Chunk.SKEW, new float[]{0, ITALIC_ANGLE});
- }
- font = new PdfFont(baseFont, size);
- // other style possibilities
- HashMap attr = chunk.getAttributes();
- if (attr != null) {
- for (Iterator i = attr.keySet().iterator(); i.hasNext();) {
- Object name = i.next();
- if (keysAttributes.containsKey(name)) {
- attributes.put(name, attr.get(name));
- }
- else if (keysNoStroke.containsKey(name)) {
- noStroke.put(name, attr.get(name));
- }
- }
- if ("".equals(attr.get(Chunk.GENERICTAG))) {
- attributes.put(Chunk.GENERICTAG, chunk.content());
- }
- }
- if (f.isUnderlined()) {
- Object obj[] = {null, new float[]{0, 1f / 15, 0, -1f / 3, 0}};
- Object unders[][] = Chunk.addToArray((Object[][])attributes.get(Chunk.UNDERLINE), obj);
- attributes.put(Chunk.UNDERLINE, unders);
- }
- if (f.isStrikethru()) {
- Object obj[] = {null, new float[]{0, 1f / 15, 0, 1f / 3, 0}};
- Object unders[][] = Chunk.addToArray((Object[][])attributes.get(Chunk.UNDERLINE), obj);
- attributes.put(Chunk.UNDERLINE, unders);
- }
- if (action != null)
- attributes.put(Chunk.ACTION, action);
- // the color can't be stored in a PdfFont
- noStroke.put(Chunk.COLOR, f.color());
- noStroke.put(Chunk.ENCODING, font.getFont().getEncoding());
- Object obj[] = (Object[])attributes.get(Chunk.IMAGE);
- if (obj == null) {
- // image = null; ssteward: dropped in 1.44
- }
- else {
- attributes.remove(Chunk.HSCALE); // images are scaled in other ways
- // image = (Image)obj[0]; ssteward: dropped in 1.44
- offsetX = ((Float)obj[1]).floatValue();
- offsetY = ((Float)obj[2]).floatValue();
- changeLeading = ((Boolean)obj[3]).booleanValue();
- }
- // font.setImage(image); ssteward: dropped in 1.44
- Float hs = (Float)attributes.get(Chunk.HSCALE);
- if (hs != null)
- font.setHorizontalScaling(hs.floatValue());
- encoding = font.getFont().getEncoding();
- splitCharacter = (SplitCharacter)noStroke.get(Chunk.SPLITCHARACTER);
- if (splitCharacter == null)
- splitCharacter = this;
- }
-
- // methods
-
- /** Gets the Unicode equivalent to a CID.
- * The (inexistent) CID is translated as '\n'.
- * It has only meaning with CJK fonts with Identity encoding.
- * @param c the CID code
- * @return the Unicode equivalent
- */
- public char getUnicodeEquivalent(char c) {
- return baseFont.getUnicodeEquivalent(c);
- }
-
- protected int getWord(String text, int start) {
- int len = text.length();
- while (start < len) {
- if (!Character.isLetter(text.charAt(start)))
- break;
- ++start;
- }
- return start;
- }
-
-/**
- * Splits this PdfChunk
if it's too long for the given width.
- *
- * Returns null if the PdfChunk
wasn't truncated.
- *
- * @param width a given width
- * @return the PdfChunk
that doesn't fit into the width.
- */
-
- PdfChunk split(float width) {
- newlineSplit = false;
- /* ssteward: dropped in 1.44
- if (image != null) {
- if (image.scaledWidth() > width) {
- PdfChunk pc = new PdfChunk(Chunk.OBJECT_REPLACEMENT_CHARACTER, this);
- value = "";
- attributes = new HashMap();
- image = null;
- font = PdfFont.getDefaultFont();
- return pc;
- }
- else
- return null;
- }
- */
- HyphenationEvent hyphenationEvent = (HyphenationEvent)noStroke.get(Chunk.HYPHENATION);
- int currentPosition = 0;
- int splitPosition = -1;
- float currentWidth = 0;
-
- // loop over all the characters of a string
- // or until the totalWidth is reached
- int lastSpace = -1;
- float lastSpaceWidth = 0;
- int length = value.length();
- char valueArray[] = value.toCharArray();
- char character = 0;
- BaseFont ft = font.getFont();
- if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
- while (currentPosition < length) {
- // the width of every character is added to the currentWidth
- char cidChar = valueArray[currentPosition];
- character = ft.getUnicodeEquivalent(cidChar);
- // if a newLine or carriageReturn is encountered
- if (character == '\n') {
- newlineSplit = true;
- String returnValue = value.substring(currentPosition + 1);
- value = value.substring(0, currentPosition);
- if (value.length() < 1) {
- value = "\u0001";
- }
- PdfChunk pc = new PdfChunk(returnValue, this);
- return pc;
- }
- currentWidth += font.width(cidChar);
- if (character == ' ') {
- lastSpace = currentPosition + 1;
- lastSpaceWidth = currentWidth;
- }
- if (currentWidth > width)
- break;
- // if a split-character is encountered, the splitPosition is altered
- if (splitCharacter.isSplitCharacter(0, currentPosition, length, valueArray, thisChunk))
- splitPosition = currentPosition + 1;
- currentPosition++;
- }
- }
- else {
- while (currentPosition < length) {
- // the width of every character is added to the currentWidth
- character = valueArray[currentPosition];
- // if a newLine or carriageReturn is encountered
- if (character == '\r' || character == '\n') {
- newlineSplit = true;
- int inc = 1;
- if (character == '\r' && currentPosition + 1 < length && valueArray[currentPosition + 1] == '\n')
- inc = 2;
- String returnValue = value.substring(currentPosition + inc);
- value = value.substring(0, currentPosition);
- if (value.length() < 1) {
- value = " ";
- }
- PdfChunk pc = new PdfChunk(returnValue, this);
- return pc;
- }
- currentWidth += font.width(character);
- if (character == ' ') {
- lastSpace = currentPosition + 1;
- lastSpaceWidth = currentWidth;
- }
- if (currentWidth > width)
- break;
- // if a split-character is encountered, the splitPosition is altered
- if (splitCharacter.isSplitCharacter(0, currentPosition, length, valueArray, null))
- splitPosition = currentPosition + 1;
- currentPosition++;
- }
- }
-
- // if all the characters fit in the total width, null is returned (there is no overflow)
- if (currentPosition == length) {
- return null;
- }
- // otherwise, the string has to be truncated
- if (splitPosition < 0) {
- String returnValue = value;
- value = "";
- PdfChunk pc = new PdfChunk(returnValue, this);
- return pc;
- }
- if (lastSpace > splitPosition && splitCharacter.isSplitCharacter(0, 0, 1, singleSpace, null))
- splitPosition = lastSpace;
- if (hyphenationEvent != null && lastSpace < currentPosition) {
- int wordIdx = getWord(value, lastSpace);
- if (wordIdx > lastSpace) {
- String pre = hyphenationEvent.getHyphenatedWordPre(value.substring(lastSpace, wordIdx), font.getFont(), font.size(), width - lastSpaceWidth);
- String post = hyphenationEvent.getHyphenatedWordPost();
- if (pre.length() > 0) {
- String returnValue = post + value.substring(wordIdx);
- value = trim(value.substring(0, lastSpace) + pre);
- PdfChunk pc = new PdfChunk(returnValue, this);
- return pc;
- }
- }
- }
- String returnValue = value.substring(splitPosition);
- value = trim(value.substring(0, splitPosition));
- PdfChunk pc = new PdfChunk(returnValue, this);
- return pc;
- }
-
-/**
- * Truncates this PdfChunk
if it's too long for the given width.
- *
- * Returns null if the PdfChunk
wasn't truncated.
- *
- * @param width a given width
- * @return the PdfChunk
that doesn't fit into the width.
- */
-
- PdfChunk truncate(float width) {
- /* ssteward: dropped in 1.44
- if (image != null) {
- if (image.scaledWidth() > width) {
- PdfChunk pc = new PdfChunk("", this);
- value = "";
- attributes.remove(Chunk.IMAGE);
- image = null;
- font = PdfFont.getDefaultFont();
- return pc;
- }
- else
- return null;
- }
- */
-
- int currentPosition = 0;
- float currentWidth = 0;
-
- // it's no use trying to split if there isn't even enough place for a space
- if (width < font.width()) {
- String returnValue = value.substring(1);
- value = value.substring(0, 1);
- PdfChunk pc = new PdfChunk(returnValue, this);
- return pc;
- }
-
- // loop over all the characters of a string
- // or until the totalWidth is reached
- int length = value.length();
- char character;
- while (currentPosition < length) {
- // the width of every character is added to the currentWidth
- character = value.charAt(currentPosition);
- currentWidth += font.width(character);
- if (currentWidth > width)
- break;
- currentPosition++;
- }
-
- // if all the characters fit in the total width, null is returned (there is no overflow)
- if (currentPosition == length) {
- return null;
- }
-
- // otherwise, the string has to be truncated
- //currentPosition -= 2;
- // we have to chop off minimum 1 character from the chunk
- if (currentPosition == 0) {
- currentPosition = 1;
- }
- String returnValue = value.substring(currentPosition);
- value = value.substring(0, currentPosition);
- PdfChunk pc = new PdfChunk(returnValue, this);
- return pc;
- }
-
- // methods to retrieve the membervariables
-
-/**
- * Returns the font of this Chunk
.
- *
- * @return a PdfFont
- */
-
- PdfFont font() {
- return font;
- }
-
-/**
- * Returns the color of this Chunk
.
- *
- * @return a Color
- */
-
- Color color() {
- return (Color)noStroke.get(Chunk.COLOR);
- }
-
-/**
- * Returns the width of this PdfChunk
.
- *
- * @return a width
- */
-
- float width() {
- return font.width(value);
- }
-
-/**
- * Checks if the PdfChunk
split was caused by a newline.
- * @return true
if the PdfChunk
split was caused by a newline.
- */
-
- public boolean isNewlineSplit()
- {
- return newlineSplit;
- }
-
-/**
- * Gets the width of the PdfChunk
taking into account the
- * extra character and word spacing.
- * @param charSpacing the extra character spacing
- * @param wordSpacing the extra word spacing
- * @return the calculated width
- */
-
- public float getWidthCorrected(float charSpacing, float wordSpacing)
- {
- /* ssteward: dropped in 1.44
- if (image != null) {
- return image.scaledWidth() + charSpacing;
- }
- */
- int numberOfSpaces = 0;
- int idx = -1;
- while ((idx = value.indexOf(' ', idx + 1)) >= 0)
- ++numberOfSpaces;
- return width() + (value.length() * charSpacing + numberOfSpaces * wordSpacing);
- }
-
- /**
- * Gets the text displacement relatiev to the baseline.
- * @return a displacement in points
- */
- public float getTextRise() {
- Float f = (Float) getAttribute(Chunk.SUBSUPSCRIPT);
- if (f != null) {
- return f.floatValue();
- }
- return 0.0f;
- }
-
-/**
- * Trims the last space.
- * @return the width of the space trimmed, otherwise 0
- */
-
- public float trimLastSpace()
- {
- BaseFont ft = font.getFont();
- if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
- if (value.length() > 1 && value.endsWith("\u0001")) {
- value = value.substring(0, value.length() - 1);
- return font.width('\u0001');
- }
- }
- else {
- if (value.length() > 1 && value.endsWith(" ")) {
- value = value.substring(0, value.length() - 1);
- return font.width(' ');
- }
- }
- return 0;
- }
-
-/**
- * Gets an attribute. The search is made in attributes
- * and noStroke
.
- * @param name the attribute key
- * @return the attribute value or null if not found
- */
-
- Object getAttribute(String name)
- {
- if (attributes.containsKey(name))
- return attributes.get(name);
- return noStroke.get(name);
- }
-
-/**
- *Checks if the attribute exists.
- * @param name the attribute key
- * @return true
if the attribute exists
- */
-
- boolean isAttribute(String name)
- {
- if (attributes.containsKey(name))
- return true;
- return noStroke.containsKey(name);
- }
-
-/**
- * Checks if this PdfChunk
needs some special metrics handling.
- * @return true
if this PdfChunk
needs some special metrics handling.
- */
-
- boolean isStroked()
- {
- return (attributes.size() > 0);
- }
-
-/**
- * Checks if there is an image in the PdfChunk
.
- * @return true
if an image is present
- */
- /* ssteward: dropped in 1.44
- boolean isImage()
- {
- return image != null;
- }
- */
-
-/**
- * Gets the image in the PdfChunk
.
- * @return the image or null
- */
- /* ssteward: dropped in 1.44
- Image getImage()
- {
- return image;
- }
- */
-
-/**
- * Sets the image offset in the x direction
- * @param offsetX the image offset in the x direction
- */
- /* ssteward: dropped in 1.44
- void setImageOffsetX(float offsetX)
- {
- this.offsetX = offsetX;
- }
- */
-
-/**
- * Gets the image offset in the x direction
- * @return the image offset in the x direction
- */
- /* ssteward: dropped in 1.44
- float getImageOffsetX()
- {
- return offsetX;
- }
- */
-
-/**
- * Sets the image offset in the y direction
- * @param offsetY the image offset in the y direction
- */
- /* ssteward: dropped in 1.44
- void setImageOffsetY(float offsetY)
- {
- this.offsetY = offsetY;
- }
- */
-
-/**
- * Gets the image offset in the y direction
- * @return Gets the image offset in the y direction
- */
-
- float getImageOffsetY()
- {
- return offsetY;
- }
-
-/**
- * sets the value.
- * @param value content of the Chunk
- */
-
- void setValue(String value)
- {
- this.value = value;
- }
-
- /**
- * @see java.lang.Object#toString()
- */
- public String toString() {
- return value;
- }
-
- /**
- * Tells you if this string is in Chinese, Japanese, Korean or Identity-H.
- * @return true if the Chunk has a special encoding
- */
-
- boolean isSpecialEncoding() {
- return encoding.equals(CJKFont.CJK_ENCODING) || encoding.equals(BaseFont.IDENTITY_H);
- }
-
- /**
- * Gets the encoding of this string.
- *
- * @return a String
- */
-
- String getEncoding() {
- return encoding;
- }
-
- int length() {
- return value.length();
- }
-/**
- * Checks if a character can be used to split a PdfString
.
- *
- * for the moment every character less than or equal to SPACE and the character '-' are 'splitCharacters'.
- *
- * @param start start position in the array
- * @param current current position in the array
- * @param end end position in the array
- * @param cc the character array that has to be checked
- * @param ck chunk array
- * @return true
if the character can be used to split a string, false
otherwise
- */
- public boolean isSplitCharacter(int start, int current, int end, char[] cc, PdfChunk[] ck) {
- char c;
- if (ck == null)
- c = cc[current];
- else
- c = ck[Math.min(current, ck.length - 1)].getUnicodeEquivalent(cc[current]);
- if (c <= ' ' || c == '-') {
- return true;
- }
- if (c < 0x2e80)
- return false;
- return ((c >= 0x2e80 && c < 0xd7a0)
- || (c >= 0xf900 && c < 0xfb00)
- || (c >= 0xfe30 && c < 0xfe50)
- || (c >= 0xff61 && c < 0xffa0));
- }
-
- boolean isExtSplitCharacter(int start, int current, int end, char[] cc, PdfChunk[] ck) {
- return splitCharacter.isSplitCharacter(start, current, end, cc, ck);
- }
-
-/**
- * Removes all the ' ' and '-' -characters on the right of a String
.
- *
- * @param string the String that has to be trimmed.
- * @return the trimmed String
- */
- String trim(String string) {
- BaseFont ft = font.getFont();
- if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
- while (string.endsWith("\u0001")) {
- string = string.substring(0, string.length() - 1);
- }
- }
- else {
- while (string.endsWith(" ") || string.endsWith("\t")) {
- string = string.substring(0, string.length() - 1);
- }
- }
- return string;
- }
-
- public boolean changeLeading() {
- return changeLeading;
- }
-
- float getCharWidth(char c) {
- if (noPrint(c))
- return 0;
- return font.width(c);
- }
-
- public static boolean noPrint(char c) {
- return ((c >= 0x200b && c <= 0x200f) || (c >= 0x202a && c <= 0x202e));
- }
-
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfColor.java pdftk-2.01/java/com/lowagie/text/pdf/PdfColor.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfColor.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfColor.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,86 +0,0 @@
-/*
- * $Id: PdfColor.java,v 1.22 2002/06/20 13:28:22 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import java.awt.Color;
-/**
- * A PdfColor
defines a Color (it's a PdfArray
containing 3 values).
- *
- * @see PdfDictionary
- */
-
-class PdfColor extends PdfArray {
-
- // constructors
-
-/**
- * Constructs a new PdfColor
.
- *
- * @param red a value between 0 and 255
- * @param green a value between 0 and 255
- * @param blue a value between 0 and 255
- */
-
- PdfColor(int red, int green, int blue) {
- super(new PdfNumber((double)(red & 0xFF) / 0xFF));
- add(new PdfNumber((double)(green & 0xFF) / 0xFF));
- add(new PdfNumber((double)(blue & 0xFF) / 0xFF));
- }
-
- PdfColor(Color color) {
- this(color.getRed(), color.getGreen(), color.getBlue());
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfContentByte.java pdftk-2.01/java/com/lowagie/text/pdf/PdfContentByte.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfContentByte.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfContentByte.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,2972 +0,0 @@
-/*
- * $Id: PdfContentByte.java,v 1.91 2005/07/19 18:24:27 psoares33 Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.HashMap;
-// import java.util.Iterator;
-import java.awt.geom.AffineTransform;
-// import java.awt.print.PrinterJob;
-
-// import com.lowagie.text.DocumentException;
-import com.lowagie.text.Element;
-// import com.lowagie.text.Image; ssteward: dropped in 1.44
-import com.lowagie.text.Rectangle;
-// import com.lowagie.text.Annotation;
-import com.lowagie.text.ExceptionConverter;
-
-/**
- * PdfContentByte
is an object containing the user positioned
- * text and graphic contents of a page. It knows how to apply the proper
- * font encoding.
- */
-
-public class PdfContentByte {
-
- /**
- * This class keeps the graphic state of the current page
- */
-
- static class GraphicState {
-
- /** This is the font in use */
- FontDetails fontDetails;
-
- /** This is the color in use */
- ColorDetails colorDetails;
-
- /** This is the font size in use */
- float size;
-
- /** The x position of the text line matrix. */
- protected float xTLM = 0;
- /** The y position of the text line matrix. */
- protected float yTLM = 0;
-
- /** The current text leading. */
- protected float leading = 0;
- }
-
- /** The alignement is center */
- public static final int ALIGN_CENTER = Element.ALIGN_CENTER;
-
- /** The alignement is left */
- public static final int ALIGN_LEFT = Element.ALIGN_LEFT;
-
- /** The alignement is right */
- public static final int ALIGN_RIGHT = Element.ALIGN_RIGHT;
-
- /** A possible line cap value */
- public static final int LINE_CAP_BUTT = 0;
- /** A possible line cap value */
- public static final int LINE_CAP_ROUND = 1;
- /** A possible line cap value */
- public static final int LINE_CAP_PROJECTING_SQUARE = 2;
-
- /** A possible line join value */
- public static final int LINE_JOIN_MITER = 0;
- /** A possible line join value */
- public static final int LINE_JOIN_ROUND = 1;
- /** A possible line join value */
- public static final int LINE_JOIN_BEVEL = 2;
-
- /** A possible text rendering value */
- public static final int TEXT_RENDER_MODE_FILL = 0;
- /** A possible text rendering value */
- public static final int TEXT_RENDER_MODE_STROKE = 1;
- /** A possible text rendering value */
- public static final int TEXT_RENDER_MODE_FILL_STROKE = 2;
- /** A possible text rendering value */
- public static final int TEXT_RENDER_MODE_INVISIBLE = 3;
- /** A possible text rendering value */
- public static final int TEXT_RENDER_MODE_FILL_CLIP = 4;
- /** A possible text rendering value */
- public static final int TEXT_RENDER_MODE_STROKE_CLIP = 5;
- /** A possible text rendering value */
- public static final int TEXT_RENDER_MODE_FILL_STROKE_CLIP = 6;
- /** A possible text rendering value */
- public static final int TEXT_RENDER_MODE_CLIP = 7;
-
- // private static final float[] unitRect = {0, 0, 0, 1, 1, 0, 1, 1};
- // membervariables
-
- /** This is the actual content */
- protected ByteBuffer content = new ByteBuffer();
-
- /** This is the writer */
- protected PdfWriter writer;
-
- /** This is the PdfDocument */
- protected PdfDocument pdf;
-
- /** This is the GraphicState in use */
- protected GraphicState state = new GraphicState();
-
- /** The list were we save/restore the state */
- protected ArrayList stateList = new ArrayList();
-
- /** The list were we save/restore the layer depth */
- protected ArrayList layerDepth;
-
- /** The separator between commands.
- */
- protected int separator = '\n';
-
- private static HashMap abrev = new HashMap();
-
- static {
- abrev.put(PdfName.BITSPERCOMPONENT, "/BPC ");
- abrev.put(PdfName.COLORSPACE, "/CS ");
- abrev.put(PdfName.DECODE, "/D ");
- abrev.put(PdfName.DECODEPARMS, "/DP ");
- abrev.put(PdfName.FILTER, "/F ");
- abrev.put(PdfName.HEIGHT, "/H ");
- abrev.put(PdfName.IMAGEMASK, "/IM ");
- abrev.put(PdfName.INTENT, "/Intent ");
- abrev.put(PdfName.INTERPOLATE, "/I ");
- abrev.put(PdfName.WIDTH, "/W ");
- }
-
- // constructors
-
- /**
- * Constructs a new PdfContentByte
-object.
- *
- * @param wr the writer associated to this content
- */
-
- public PdfContentByte(PdfWriter wr) {
- if (wr != null) {
- writer = wr;
- pdf = writer.getPdfDocument();
- }
- }
-
- // methods to get the content of this object
-
- /**
- * Returns the String
representation of this PdfContentByte
-object.
- *
- * @return a String
- */
-
- public String toString() {
- return content.toString();
- }
-
- /**
- * Gets the internal buffer.
- * @return the internal buffer
- */
- public ByteBuffer getInternalBuffer() {
- return content;
- }
-
- /** Returns the PDF representation of this PdfContentByte
-object.
- *
- * @param writer the PdfWriter
- * @return a byte
array with the representation
- */
-
- public byte[] toPdf(PdfWriter writer) {
- return content.toByteArray();
- }
-
- // methods to add graphical content
-
- /**
- * Adds the content of another PdfContent
-object to this object.
- *
- * @param other another PdfByteContent
-object
- */
-
- public void add(PdfContentByte other) {
- if (other.writer != null && writer != other.writer)
- throw new RuntimeException("Inconsistent writers. Are you mixing two documents?");
- content.append(other.content);
- }
-
- /**
- * Gets the x position of the text line matrix.
- *
- * @return the x position of the text line matrix
- */
- public float getXTLM() {
- return state.xTLM;
- }
-
- /**
- * Gets the y position of the text line matrix.
- *
- * @return the y position of the text line matrix
- */
- public float getYTLM() {
- return state.yTLM;
- }
-
- /**
- * Gets the current text leading.
- *
- * @return the current text leading
- */
- public float getLeading() {
- return state.leading;
- }
-
- /**
- * Changes the Flatness .
- *
- * Flatness sets the maximum permitted distance in device pixels between the
- * mathematically correct path and an approximation constructed from straight line segments.
- *
- * @param flatness a value
- */
-
- public void setFlatness(float flatness) {
- if (flatness >= 0 && flatness <= 100) {
- content.append(flatness).append(" i").append_i(separator);
- }
- }
-
- /**
- * Changes the Line cap style .
- *
- * The line cap style specifies the shape to be used at the end of open subpaths
- * when they are stroked.
- * Allowed values are LINE_CAP_BUTT, LINE_CAP_ROUND and LINE_CAP_PROJECTING_SQUARE.
- *
- * @param style a value
- */
-
- public void setLineCap(int style) {
- if (style >= 0 && style <= 2) {
- content.append(style).append(" J").append_i(separator);
- }
- }
-
- /**
- * Changes the value of the line dash pattern .
- *
- * The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
- * It is specified by an array and a phase . The array specifies the length
- * of the alternating dashes and gaps. The phase specifies the distance into the dash
- * pattern to start the dash.
- *
- * @param phase the value of the phase
- */
-
- public void setLineDash(float phase) {
- content.append("[] ").append(phase).append(" d").append_i(separator);
- }
-
- /**
- * Changes the value of the line dash pattern .
- *
- * The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
- * It is specified by an array and a phase . The array specifies the length
- * of the alternating dashes and gaps. The phase specifies the distance into the dash
- * pattern to start the dash.
- *
- * @param phase the value of the phase
- * @param unitsOn the number of units that must be 'on' (equals the number of units that must be 'off').
- */
-
- public void setLineDash(float unitsOn, float phase) {
- content.append("[").append(unitsOn).append("] ").append(phase).append(" d").append_i(separator);
- }
-
- /**
- * Changes the value of the line dash pattern .
- *
- * The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
- * It is specified by an array and a phase . The array specifies the length
- * of the alternating dashes and gaps. The phase specifies the distance into the dash
- * pattern to start the dash.
- *
- * @param phase the value of the phase
- * @param unitsOn the number of units that must be 'on'
- * @param unitsOff the number of units that must be 'off'
- */
-
- public void setLineDash(float unitsOn, float unitsOff, float phase) {
- content.append("[").append(unitsOn).append(' ').append(unitsOff).append("] ").append(phase).append(" d").append_i(separator);
- }
-
- /**
- * Changes the value of the line dash pattern .
- *
- * The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
- * It is specified by an array and a phase . The array specifies the length
- * of the alternating dashes and gaps. The phase specifies the distance into the dash
- * pattern to start the dash.
- *
- * @param array length of the alternating dashes and gaps
- * @param phase the value of the phase
- */
-
- public final void setLineDash(float[] array, float phase) {
- content.append("[");
- for (int i = 0; i < array.length; i++) {
- content.append(array[i]);
- if (i < array.length - 1) content.append(' ');
- }
- content.append("] ").append(phase).append(" d").append_i(separator);
- }
-
- /**
- * Changes the Line join style .
- *
- * The line join style specifies the shape to be used at the corners of paths
- * that are stroked.
- * Allowed values are LINE_JOIN_MITER (Miter joins), LINE_JOIN_ROUND (Round joins) and LINE_JOIN_BEVEL (Bevel joins).
- *
- * @param style a value
- */
-
- public void setLineJoin(int style) {
- if (style >= 0 && style <= 2) {
- content.append(style).append(" j").append_i(separator);
- }
- }
-
- /**
- * Changes the line width .
- *
- * The line width specifies the thickness of the line used to stroke a path and is measured
- * in used space units.
- *
- * @param w a width
- */
-
- public void setLineWidth(float w) {
- content.append(w).append(" w").append_i(separator);
- }
-
- /**
- * Changes the Miter limit .
- *
- * When two line segments meet at a sharp angle and mitered joins have been specified as the
- * line join style, it is possible for the miter to extend far beyond the thickness of the line
- * stroking path. The miter limit imposes a maximum on the ratio of the miter length to the line
- * witdh. When the limit is exceeded, the join is converted from a miter to a bevel.
- *
- * @param miterLimit a miter limit
- */
-
- public void setMiterLimit(float miterLimit) {
- if (miterLimit > 1) {
- content.append(miterLimit).append(" M").append_i(separator);
- }
- }
-
- /**
- * Modify the current clipping path by intersecting it with the current path, using the
- * nonzero winding number rule to determine which regions lie inside the clipping
- * path.
- */
-
- public void clip() {
- content.append("W").append_i(separator);
- }
-
- /**
- * Modify the current clipping path by intersecting it with the current path, using the
- * even-odd rule to determine which regions lie inside the clipping path.
- */
-
- public void eoClip() {
- content.append("W*").append_i(separator);
- }
-
- /**
- * Changes the currentgray tint for filling paths (device dependent colors!).
- *
- * Sets the color space to DeviceGray (or the DefaultGray color space),
- * and sets the gray tint to use for filling paths.
- *
- * @param gray a value between 0 (black) and 1 (white)
- */
-
- public void setGrayFill(float gray) {
- content.append(gray).append(" g").append_i(separator);
- }
-
- /**
- * Changes the current gray tint for filling paths to black.
- */
-
- public void resetGrayFill() {
- content.append("0 g").append_i(separator);
- }
-
- /**
- * Changes the currentgray tint for stroking paths (device dependent colors!).
- *
- * Sets the color space to DeviceGray (or the DefaultGray color space),
- * and sets the gray tint to use for stroking paths.
- *
- * @param gray a value between 0 (black) and 1 (white)
- */
-
- public void setGrayStroke(float gray) {
- content.append(gray).append(" G").append_i(separator);
- }
-
- /**
- * Changes the current gray tint for stroking paths to black.
- */
-
- public void resetGrayStroke() {
- content.append("0 G").append_i(separator);
- }
-
- /**
- * Helper to validate and write the RGB color components
- * @param red the intensity of red. A value between 0 and 1
- * @param green the intensity of green. A value between 0 and 1
- * @param blue the intensity of blue. A value between 0 and 1
- */
- private void HelperRGB(float red, float green, float blue) {
- PdfWriter.checkPDFXConformance(writer, PdfWriter.PDFXKEY_RGB, null);
- if (red < 0)
- red = 0.0f;
- else if (red > 1.0f)
- red = 1.0f;
- if (green < 0)
- green = 0.0f;
- else if (green > 1.0f)
- green = 1.0f;
- if (blue < 0)
- blue = 0.0f;
- else if (blue > 1.0f)
- blue = 1.0f;
- content.append(red).append(' ').append(green).append(' ').append(blue);
- }
-
- /**
- * Changes the current color for filling paths (device dependent colors!).
- *
- * Sets the color space to DeviceRGB (or the DefaultRGB color space),
- * and sets the color to use for filling paths.
- *
- * Following the PDF manual, each operand must be a number between 0 (minimum intensity) and
- * 1 (maximum intensity).
- *
- * @param red the intensity of red. A value between 0 and 1
- * @param green the intensity of green. A value between 0 and 1
- * @param blue the intensity of blue. A value between 0 and 1
- */
-
- public void setRGBColorFillF(float red, float green, float blue) {
- HelperRGB(red, green, blue);
- content.append(" rg").append_i(separator);
- }
-
- /**
- * Changes the current color for filling paths to black.
- */
-
- public void resetRGBColorFill() {
- content.append("0 g").append_i(separator);
- }
-
- /**
- * Changes the current color for stroking paths (device dependent colors!).
- *
- * Sets the color space to DeviceRGB (or the DefaultRGB color space),
- * and sets the color to use for stroking paths.
- *
- * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
- * 1 (maximum intensity).
- *
- * @param red the intensity of red. A value between 0 and 1
- * @param green the intensity of green. A value between 0 and 1
- * @param blue the intensity of blue. A value between 0 and 1
- */
-
- public void setRGBColorStrokeF(float red, float green, float blue) {
- HelperRGB(red, green, blue);
- content.append(" RG").append_i(separator);
- }
-
- /**
- * Changes the current color for stroking paths to black.
- *
- */
-
- public void resetRGBColorStroke() {
- content.append("0 G").append_i(separator);
- }
-
- /**
- * Helper to validate and write the CMYK color components.
- *
- * @param cyan the intensity of cyan. A value between 0 and 1
- * @param magenta the intensity of magenta. A value between 0 and 1
- * @param yellow the intensity of yellow. A value between 0 and 1
- * @param black the intensity of black. A value between 0 and 1
- */
- private void HelperCMYK(float cyan, float magenta, float yellow, float black) {
- if (cyan < 0)
- cyan = 0.0f;
- else if (cyan > 1.0f)
- cyan = 1.0f;
- if (magenta < 0)
- magenta = 0.0f;
- else if (magenta > 1.0f)
- magenta = 1.0f;
- if (yellow < 0)
- yellow = 0.0f;
- else if (yellow > 1.0f)
- yellow = 1.0f;
- if (black < 0)
- black = 0.0f;
- else if (black > 1.0f)
- black = 1.0f;
- content.append(cyan).append(' ').append(magenta).append(' ').append(yellow).append(' ').append(black);
- }
-
- /**
- * Changes the current color for filling paths (device dependent colors!).
- *
- * Sets the color space to DeviceCMYK (or the DefaultCMYK color space),
- * and sets the color to use for filling paths.
- *
- * Following the PDF manual, each operand must be a number between 0 (no ink) and
- * 1 (maximum ink).
- *
- * @param cyan the intensity of cyan. A value between 0 and 1
- * @param magenta the intensity of magenta. A value between 0 and 1
- * @param yellow the intensity of yellow. A value between 0 and 1
- * @param black the intensity of black. A value between 0 and 1
- */
-
- public void setCMYKColorFillF(float cyan, float magenta, float yellow, float black) {
- HelperCMYK(cyan, magenta, yellow, black);
- content.append(" k").append_i(separator);
- }
-
- /**
- * Changes the current color for filling paths to black.
- *
- */
-
- public void resetCMYKColorFill() {
- content.append("0 0 0 1 k").append_i(separator);
- }
-
- /**
- * Changes the current color for stroking paths (device dependent colors!).
- *
- * Sets the color space to DeviceCMYK (or the DefaultCMYK color space),
- * and sets the color to use for stroking paths.
- *
- * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
- * 1 (maximum intensity).
- *
- * @param cyan the intensity of cyan. A value between 0 and 1
- * @param magenta the intensity of magenta. A value between 0 and 1
- * @param yellow the intensity of yellow. A value between 0 and 1
- * @param black the intensity of black. A value between 0 and 1
- */
-
- public void setCMYKColorStrokeF(float cyan, float magenta, float yellow, float black) {
- HelperCMYK(cyan, magenta, yellow, black);
- content.append(" K").append_i(separator);
- }
-
- /**
- * Changes the current color for stroking paths to black.
- *
- */
-
- public void resetCMYKColorStroke() {
- content.append("0 0 0 1 K").append_i(separator);
- }
-
- /**
- * Move the current point (x, y) , omitting any connecting line segment.
- *
- * @param x new x-coordinate
- * @param y new y-coordinate
- */
-
- public void moveTo(float x, float y) {
- content.append(x).append(' ').append(y).append(" m").append_i(separator);
- }
-
- /**
- * Appends a straight line segment from the current point (x, y) . The new current
- * point is (x, y) .
- *
- * @param x new x-coordinate
- * @param y new y-coordinate
- */
-
- public void lineTo(float x, float y) {
- content.append(x).append(' ').append(y).append(" l").append_i(separator);
- }
-
- /**
- * Appends a Bêzier curve to the path, starting from the current point.
- *
- * @param x1 x-coordinate of the first control point
- * @param y1 y-coordinate of the first control point
- * @param x2 x-coordinate of the second control point
- * @param y2 y-coordinate of the second control point
- * @param x3 x-coordinaat of the ending point (= new current point)
- * @param y3 y-coordinaat of the ending point (= new current point)
- */
-
- public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) {
- content.append(x1).append(' ').append(y1).append(' ').append(x2).append(' ').append(y2).append(' ').append(x3).append(' ').append(y3).append(" c").append_i(separator);
- }
-
- /**
- * Appends a Bêzier curve to the path, starting from the current point.
- *
- * @param x2 x-coordinate of the second control point
- * @param y2 y-coordinate of the second control point
- * @param x3 x-coordinaat of the ending point (= new current point)
- * @param y3 y-coordinaat of the ending point (= new current point)
- */
-
- public void curveTo(float x2, float y2, float x3, float y3) {
- content.append(x2).append(' ').append(y2).append(' ').append(x3).append(' ').append(y3).append(" v").append_i(separator);
- }
-
- /**
- * Appends a Bêzier curve to the path, starting from the current point.
- *
- * @param x1 x-coordinate of the first control point
- * @param y1 y-coordinate of the first control point
- * @param x3 x-coordinaat of the ending point (= new current point)
- * @param y3 y-coordinaat of the ending point (= new current point)
- */
-
- public void curveFromTo(float x1, float y1, float x3, float y3) {
- content.append(x1).append(' ').append(y1).append(' ').append(x3).append(' ').append(y3).append(" y").append_i(separator);
- }
-
- /** Draws a circle. The endpoint will (x+r, y).
- *
- * @param x x center of circle
- * @param y y center of circle
- * @param r radius of circle
- */
- public void circle(float x, float y, float r) {
- float b = 0.5523f;
- moveTo(x + r, y);
- curveTo(x + r, y + r * b, x + r * b, y + r, x, y + r);
- curveTo(x - r * b, y + r, x - r, y + r * b, x - r, y);
- curveTo(x - r, y - r * b, x - r * b, y - r, x, y - r);
- curveTo(x + r * b, y - r, x + r, y - r * b, x + r, y);
- }
-
-
-
- /**
- * Adds a rectangle to the current path.
- *
- * @param x x-coordinate of the starting point
- * @param y y-coordinate of the starting point
- * @param w width
- * @param h height
- */
-
- public void rectangle(float x, float y, float w, float h) {
- content.append(x).append(' ').append(y).append(' ').append(w).append(' ').append(h).append(" re").append_i(separator);
- }
-
-
- // Contribution by Barry Richards and Prabhakar Chaganti
- /**
- * Adds a variable width border to the current path.
- * Only use if {@link com.lowagie.text.Rectangle#isUseVariableBorders() Rectangle.isUseVariableBorders}
- * = true.
- * @param rect a Rectangle
- */
- public void variableRectangle(Rectangle rect) {
- float limit = 0f;
- float startX = rect.left();
- float startY = rect.bottom();
-
- // start at the origin
- // draw bottom
- if (rect.getBorderWidthBottom() > limit) {
- moveTo(startX, startY);
- if (rect.getBorderColorBottom() == null)
- resetRGBColorFill();
- else
- setColorFill(rect.getBorderColorBottom());
- // DRAW BOTTOM EDGE.
- lineTo(startX + rect.width(), startY);
- // DRAW RIGHT EDGE.
- lineTo((startX + rect.width()) - rect.getBorderWidthRight(), startY + rect.getBorderWidthBottom());
- //DRAW TOP EDGE.
- lineTo((startX + rect.getBorderWidthLeft()), startY + rect.getBorderWidthBottom());
- lineTo(startX, startY);
- fill();
- }
-
- // Draw left
- if (rect.getBorderWidthLeft() > limit) {
- moveTo(startX, startY);
- if (rect.getBorderColorLeft() == null)
- resetRGBColorFill();
- else
- setColorFill(rect.getBorderColorLeft());
- // DRAW BOTTOM EDGE.
- lineTo(startX, startY + rect.height());
- // DRAW RIGHT EDGE.
- lineTo(startX + rect.getBorderWidthLeft(), (startY + rect.height()) - rect.getBorderWidthTop());
- //DRAW TOP EDGE.
- lineTo(startX + rect.getBorderWidthLeft(), startY + rect.getBorderWidthBottom());
-
- lineTo(startX, startY);
- fill();
- }
-
-
- startX = startX + rect.width();
- startY = startY + rect.height();
-
- // Draw top
- if (rect.getBorderWidthTop() > limit) {
- moveTo(startX, startY);
- if (rect.getBorderColorTop() == null)
- resetRGBColorFill();
- else
- setColorFill(rect.getBorderColorTop());
- // DRAW LONG EDGE.
- lineTo(startX - rect.width(), startY);
- // DRAW LEFT EDGE.
- lineTo(startX - rect.width() + rect.getBorderWidthLeft(), startY - rect.getBorderWidthTop());
- //DRAW SHORT EDGE.
- lineTo(startX - rect.getBorderWidthRight(), startY - rect.getBorderWidthTop());
-
- lineTo(startX, startY);
- fill();
- }
-
- // Draw Right
- if (rect.getBorderWidthRight() > limit) {
- moveTo(startX, startY);
- if (rect.getBorderColorRight() == null)
- resetRGBColorFill();
- else
- setColorFill(rect.getBorderColorRight());
- // DRAW LONG EDGE.
- lineTo(startX, startY - rect.height());
- // DRAW LEFT EDGE.
- lineTo(startX - rect.getBorderWidthRight(), startY - rect.height() + rect.getBorderWidthBottom());
- //DRAW SHORT EDGE.
- lineTo(startX - rect.getBorderWidthRight(), startY - rect.getBorderWidthTop());
-
- lineTo(startX, startY);
- fill();
- }
- resetRGBColorFill();
- }
-
- /**
- * Adds a border (complete or partially) to the current path..
- *
- * @param rectangle a Rectangle
- */
-
- public void rectangle(Rectangle rectangle) {
- // the coordinates of the border are retrieved
- float x1 = rectangle.left();
- float y1 = rectangle.bottom();
- float x2 = rectangle.right();
- float y2 = rectangle.top();
-
- // the backgroundcolor is set
- Color background = rectangle.backgroundColor();
- if (background != null) {
- setColorFill(background);
- rectangle(x1, y1, x2 - x1, y2 - y1);
- fill();
- resetRGBColorFill();
- }
- else if (rectangle.grayFill() > 0.0) {
- setGrayFill(rectangle.grayFill());
- rectangle(x1, y1, x2 - x1, y2 - y1);
- fill();
- resetGrayFill();
- }
-
-
- // if the element hasn't got any borders, nothing is added
- if (! rectangle.hasBorders()) {
- return;
- }
-
- // if any of the individual border colors are set
- // we draw the borders all around using the
- // different colors
- if (rectangle.isUseVariableBorders()) {
- variableRectangle(rectangle);
- }
- else {
- // the width is set to the width of the element
- if (rectangle.borderWidth() != Rectangle.UNDEFINED) {
- setLineWidth(rectangle.borderWidth());
- }
-
- // the color is set to the color of the element
- Color color = rectangle.borderColor();
- if (color != null) {
- setColorStroke(color);
- }
-
- // if the box is a rectangle, it is added as a rectangle
- if (rectangle.hasBorder(Rectangle.BOX)) {
- rectangle(x1, y1, x2 - x1, y2 - y1);
- }
- // if the border isn't a rectangle, the different sides are added apart
- else {
- if (rectangle.hasBorder(Rectangle.RIGHT)) {
- moveTo(x2, y1);
- lineTo(x2, y2);
- }
- if (rectangle.hasBorder(Rectangle.LEFT)) {
- moveTo(x1, y1);
- lineTo(x1, y2);
- }
- if (rectangle.hasBorder(Rectangle.BOTTOM)) {
- moveTo(x1, y1);
- lineTo(x2, y1);
- }
- if (rectangle.hasBorder(Rectangle.TOP)) {
- moveTo(x1, y2);
- lineTo(x2, y2);
- }
- }
-
- stroke();
-
- if (color != null) {
- resetRGBColorStroke();
- }
- }
- }
-
- /**
- * Closes the current subpath by appending a straight line segment from the current point
- * to the starting point of the subpath.
- */
-
- public void closePath() {
- content.append("h").append_i(separator);
- }
-
- /**
- * Ends the path without filling or stroking it.
- */
-
- public void newPath() {
- content.append("n").append_i(separator);
- }
-
- /**
- * Strokes the path.
- */
-
- public void stroke() {
- content.append("S").append_i(separator);
- }
-
- /**
- * Closes the path and strokes it.
- */
-
- public void closePathStroke() {
- content.append("s").append_i(separator);
- }
-
- /**
- * Fills the path, using the non-zero winding number rule to determine the region to fill.
- */
-
- public void fill() {
- content.append("f").append_i(separator);
- }
-
- /**
- * Fills the path, using the even-odd rule to determine the region to fill.
- */
-
- public void eoFill() {
- content.append("f*").append_i(separator);
- }
-
- /**
- * Fills the path using the non-zero winding number rule to determine the region to fill and strokes it.
- */
-
- public void fillStroke() {
- content.append("B").append_i(separator);
- }
-
- /**
- * Closes the path, fills it using the non-zero winding number rule to determine the region to fill and strokes it.
- */
-
- public void closePathFillStroke() {
- content.append("b").append_i(separator);
- }
-
- /**
- * Fills the path, using the even-odd rule to determine the region to fill and strokes it.
- */
-
- public void eoFillStroke() {
- content.append("B*").append_i(separator);
- }
-
- /**
- * Closes the path, fills it using the even-odd rule to determine the region to fill and strokes it.
- */
-
- public void closePathEoFillStroke() {
- content.append("b*").append_i(separator);
- }
-
- /**
- * Adds an Image
to the page. The Image
must have
- * absolute positioning.
- * @param image the Image
object
- * @throws DocumentException if the Image
does not have absolute positioning
- */
- /* ssteward: dropped in 1.44
- public void addImage(Image image) throws DocumentException {
- addImage(image, false);
- }
- */
-
- /**
- * Adds an Image
to the page. The Image
must have
- * absolute positioning. The image can be placed inline.
- * @param image the Image
object
- * @param inlineImage true
to place this image inline, false
otherwise
- * @throws DocumentException if the Image
does not have absolute positioning
- */
- /* ssteward: dropped in 1.44
- public void addImage(Image image, boolean inlineImage) throws DocumentException {
- if (!image.hasAbsolutePosition())
- throw new DocumentException("The image must have absolute positioning.");
- float matrix[] = image.matrix();
- matrix[Image.CX] = image.absoluteX() - matrix[Image.CX];
- matrix[Image.CY] = image.absoluteY() - matrix[Image.CY];
- addImage(image, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5], inlineImage);
- }
- */
-
- /**
- * Adds an Image
to the page. The positioning of the Image
- * is done with the transformation matrix. To position an image
at (x,y)
- * use addImage(image, image_width, 0, 0, image_height, x, y).
- * @param image the Image
object
- * @param a an element of the transformation matrix
- * @param b an element of the transformation matrix
- * @param c an element of the transformation matrix
- * @param d an element of the transformation matrix
- * @param e an element of the transformation matrix
- * @param f an element of the transformation matrix
- * @throws DocumentException on error
- */
- /* ssteward: dropped in 1.44
- public void addImage(Image image, float a, float b, float c, float d, float e, float f) throws DocumentException {
- addImage(image, a, b, c, d, e, f, false);
- }
- */
-
- /**
- * Adds an Image
to the page. The positioning of the Image
- * is done with the transformation matrix. To position an image
at (x,y)
- * use addImage(image, image_width, 0, 0, image_height, x, y). The image can be placed inline.
- * @param image the Image
object
- * @param a an element of the transformation matrix
- * @param b an element of the transformation matrix
- * @param c an element of the transformation matrix
- * @param d an element of the transformation matrix
- * @param e an element of the transformation matrix
- * @param f an element of the transformation matrix
- * @param inlineImage true
to place this image inline, false
otherwise
- * @throws DocumentException on error
- */
- /*
- public void addImage(Image image, float a, float b, float c, float d, float e, float f, boolean inlineImage) throws DocumentException {
- try {
- if (image.getLayer() != null)
- beginLayer(image.getLayer());
- if (image.isImgTemplate()) {
- writer.addDirectImageSimple(image);
- PdfTemplate template = image.templateData();
- float w = template.getWidth();
- float h = template.getHeight();
- addTemplate(template, a / w, b / w, c / h, d / h, e, f);
- }
- else {
- content.append("q ");
- content.append(a).append(' ');
- content.append(b).append(' ');
- content.append(c).append(' ');
- content.append(d).append(' ');
- content.append(e).append(' ');
- content.append(f).append(" cm");
- if (inlineImage) {
- content.append("\nBI\n");
- PdfImage pimage = new PdfImage(image, "", null);
- for (Iterator it = pimage.getKeys().iterator(); it.hasNext();) {
- PdfName key = (PdfName)it.next();
- PdfObject value = pimage.get(key);
- String s = (String)abrev.get(key);
- if (s == null)
- continue;
- content.append(s);
- boolean check = true;
- if (key.equals(PdfName.COLORSPACE) && value.isArray()) {
- ArrayList ar = ((PdfArray)value).getArrayList();
- if (ar.size() == 4
- && PdfName.INDEXED.equals(ar.get(0))
- && ((PdfObject)ar.get(1)).isName()
- && ((PdfObject)ar.get(2)).isNumber()
- && ((PdfObject)ar.get(3)).isString()
- ) {
- check = false;
- }
-
- }
- if (check && key.equals(PdfName.COLORSPACE) && !value.isName()) {
- PdfName cs = writer.getColorspaceName();
- PageResources prs = getPageResources();
- prs.addColor(cs, writer.addToBody(value).getIndirectReference());
- value = cs;
- }
- value.toPdf(null, content);
- content.append('\n');
- }
- content.append("ID\n");
- pimage.writeContent(content);
- content.append("\nEI\nQ").append_i(separator);
- }
- else {
- PdfName name;
- PageResources prs = getPageResources();
- Image maskImage = image.getImageMask();
- if (maskImage != null) {
- name = writer.addDirectImageSimple(maskImage);
- prs.addXObject(name, writer.getImageReference(name));
- }
- name = writer.addDirectImageSimple(image);
- name = prs.addXObject(name, writer.getImageReference(name));
- content.append(' ').append(name.getBytes()).append(" Do Q").append_i(separator);
- }
- }
- if (image.hasBorders()) {
- saveState();
- float w = image.width();
- float h = image.height();
- concatCTM(a / w, b / w, c / h, d / h, e, f);
- rectangle(image);
- restoreState();
- }
- if (image.getLayer() != null)
- endLayer();
- Annotation annot = image.annotation();
- if (annot == null)
- return;
- float[] r = new float[unitRect.length];
- for (int k = 0; k < unitRect.length; k += 2) {
- r[k] = a * unitRect[k] + c * unitRect[k + 1] + e;
- r[k + 1] = b * unitRect[k] + d * unitRect[k + 1] + f;
- }
- float llx = r[0];
- float lly = r[1];
- float urx = llx;
- float ury = lly;
- for (int k = 2; k < r.length; k += 2) {
- llx = Math.min(llx, r[k]);
- lly = Math.min(lly, r[k + 1]);
- urx = Math.max(urx, r[k]);
- ury = Math.max(ury, r[k + 1]);
- }
- annot = new Annotation(annot);
- annot.setDimensions(llx, lly, urx, ury);
- PdfAnnotation an = PdfDocument.convertAnnotation(writer, annot);
- if (an == null)
- return;
- addAnnotation(an);
- }
- catch (Exception ee) {
- throw new DocumentException(ee);
- }
- }
- */
-
- /**
- * Makes this PdfContentByte
empty.
- */
- public void reset() {
- content.reset();
- stateList.clear();
- state = new GraphicState();
- }
-
- /**
- * Starts the writing of text.
- */
- public void beginText() {
- state.xTLM = 0;
- state.yTLM = 0;
- content.append("BT").append_i(separator);
- }
-
- /**
- * Ends the writing of text and makes the current font invalid.
- */
- public void endText() {
- content.append("ET").append_i(separator);
- }
-
- /**
- * Saves the graphic state. saveState
and
- * restoreState
must be balanced.
- */
- public void saveState() {
- content.append("q").append_i(separator);
- stateList.add(state);
- }
-
- /**
- * Restores the graphic state. saveState
and
- * restoreState
must be balanced.
- */
- public void restoreState() {
- content.append("Q").append_i(separator);
- int idx = stateList.size() - 1;
- if (idx < 0)
- throw new RuntimeException("Unbalanced save/restore state operators.");
- state = (GraphicState)stateList.get(idx);
- stateList.remove(idx);
- }
-
- /**
- * Sets the character spacing parameter.
- *
- * @param charSpace a parameter
- */
- public void setCharacterSpacing(float charSpace) {
- content.append(charSpace).append(" Tc").append_i(separator);
- }
-
- /**
- * Sets the word spacing parameter.
- *
- * @param wordSpace a parameter
- */
- public void setWordSpacing(float wordSpace) {
- content.append(wordSpace).append(" Tw").append_i(separator);
- }
-
- /**
- * Sets the horizontal scaling parameter.
- *
- * @param scale a parameter
- */
- public void setHorizontalScaling(float scale) {
- content.append(scale).append(" Tz").append_i(separator);
- }
-
- /**
- * Sets the text leading parameter.
- *
- * The leading parameter is measured in text space units. It specifies the vertical distance
- * between the baselines of adjacent lines of text.
- *
- * @param leading the new leading
- */
- public void setLeading(float leading) {
- state.leading = leading;
- content.append(leading).append(" TL").append_i(separator);
- }
-
- /**
- * Set the font and the size for the subsequent text writing.
- *
- * @param bf the font
- * @param size the font size in points
- */
- public void setFontAndSize(BaseFont bf, float size) {
- checkWriter();
- state.size = size;
- state.fontDetails = writer.addSimple(bf);
- PageResources prs = getPageResources();
- PdfName name = state.fontDetails.getFontName();
- name = prs.addFont(name, state.fontDetails.getIndirectReference());
- content.append(name.getBytes()).append(' ').append(size).append(" Tf").append_i(separator);
- }
-
- /**
- * Sets the text rendering parameter.
- *
- * @param rendering a parameter
- */
- public void setTextRenderingMode(int rendering) {
- content.append(rendering).append(" Tr").append_i(separator);
- }
-
- /**
- * Sets the text rise parameter.
- *
- * This allows to write text in subscript or superscript mode.
- *
- * @param rise a parameter
- */
- public void setTextRise(float rise) {
- content.append(rise).append(" Ts").append_i(separator);
- }
-
- /**
- * A helper to insert into the content stream the text
- * converted to bytes according to the font's encoding.
- *
- * @param text the text to write
- */
- private void showText2(String text) {
- if (state.fontDetails == null)
- throw new NullPointerException("Font and size must be set before writing any text");
- byte b[] = state.fontDetails.convertToBytes(text);
- escapeString(b, content);
- }
-
- /**
- * Shows the text
.
- *
- * @param text the text to write
- */
- public void showText(String text) {
- showText2(text);
- content.append("Tj").append_i(separator);
- }
-
- /**
- * Constructs a kern array for a text in a certain font
- * @param text the text
- * @param font the font
- * @return a PdfTextArray
- */
- public static PdfTextArray getKernArray(String text, BaseFont font) {
- PdfTextArray pa = new PdfTextArray();
- StringBuffer acc = new StringBuffer();
- int len = text.length() - 1;
- char c[] = text.toCharArray();
- if (len >= 0)
- acc.append(c, 0, 1);
- for (int k = 0; k < len; ++k) {
- char c2 = c[k + 1];
- int kern = font.getKerning(c[k], c2);
- if (kern == 0) {
- acc.append(c2);
- }
- else {
- pa.add(acc.toString());
- acc.setLength(0);
- acc.append(c, k + 1, 1);
- pa.add(-kern);
- }
- }
- pa.add(acc.toString());
- return pa;
- }
-
- /**
- * Shows the text
kerned.
- *
- * @param text the text to write
- */
- public void showTextKerned(String text) {
- if (state.fontDetails == null)
- throw new NullPointerException("Font and size must be set before writing any text");
- BaseFont bf = state.fontDetails.getBaseFont();
- if (bf.hasKernPairs())
- showText(getKernArray(text, bf));
- else
- showText(text);
- }
-
- /**
- * Moves to the next line and shows text
.
- *
- * @param text the text to write
- */
- public void newlineShowText(String text) {
- state.yTLM -= state.leading;
- showText2(text);
- content.append("'").append_i(separator);
- }
-
- /**
- * Moves to the next line and shows text string, using the given values of the character and word spacing parameters.
- *
- * @param wordSpacing a parameter
- * @param charSpacing a parameter
- * @param text the text to write
- */
- public void newlineShowText(float wordSpacing, float charSpacing, String text) {
- state.yTLM -= state.leading;
- content.append(wordSpacing).append(' ').append(charSpacing);
- showText2(text);
- content.append("\"").append_i(separator);
- }
-
- /**
- * Changes the text matrix.
- *
- * Remark: this operation also initializes the current point position.
- *
- * @param a operand 1,1 in the matrix
- * @param b operand 1,2 in the matrix
- * @param c operand 2,1 in the matrix
- * @param d operand 2,2 in the matrix
- * @param x operand 3,1 in the matrix
- * @param y operand 3,2 in the matrix
- */
- public void setTextMatrix(float a, float b, float c, float d, float x, float y) {
- state.xTLM = x;
- state.yTLM = y;
- content.append(a).append(' ').append(b).append_i(' ')
- .append(c).append_i(' ').append(d).append_i(' ')
- .append(x).append_i(' ').append(y).append(" Tm").append_i(separator);
- }
-
- /**
- * Changes the text matrix. The first four parameters are {1,0,0,1}.
- *
- * Remark: this operation also initializes the current point position.
- *
- * @param x operand 3,1 in the matrix
- * @param y operand 3,2 in the matrix
- */
- public void setTextMatrix(float x, float y) {
- setTextMatrix(1, 0, 0, 1, x, y);
- }
-
- /**
- * Moves to the start of the next line, offset from the start of the current line.
- *
- * @param x x-coordinate of the new current point
- * @param y y-coordinate of the new current point
- */
- public void moveText(float x, float y) {
- state.xTLM += x;
- state.yTLM += y;
- content.append(x).append(' ').append(y).append(" Td").append_i(separator);
- }
-
- /**
- * Moves to the start of the next line, offset from the start of the current line.
- *
- * As a side effect, this sets the leading parameter in the text state.
- *
- * @param x offset of the new current point
- * @param y y-coordinate of the new current point
- */
- public void moveTextWithLeading(float x, float y) {
- state.xTLM += x;
- state.yTLM += y;
- state.leading = -y;
- content.append(x).append(' ').append(y).append(" TD").append_i(separator);
- }
-
- /**
- * Moves to the start of the next line.
- */
- public void newlineText() {
- state.yTLM -= state.leading;
- content.append("T*").append_i(separator);
- }
-
- /**
- * Gets the size of this content.
- *
- * @return the size of the content
- */
- int size() {
- return content.size();
- }
-
- /**
- * Escapes a byte
array according to the PDF conventions.
- *
- * @param b the byte
array to escape
- * @return an escaped byte
array
- */
- static byte[] escapeString(byte b[]) {
- ByteBuffer content = new ByteBuffer();
- escapeString(b, content);
- return content.toByteArray();
- }
-
- /**
- * Escapes a byte
array according to the PDF conventions.
- *
- * @param b the byte
array to escape
- * @param content the content
- */
- static void escapeString(byte b[], ByteBuffer content) {
- content.append_i('(');
- for (int k = 0; k < b.length; ++k) {
- byte c = b[k];
- switch (c) {
- case '\r':
- content.append("\\r");
- break;
- case '\n':
- content.append("\\n");
- break;
- case '\t':
- content.append("\\t");
- break;
- case '\b':
- content.append("\\b");
- break;
- case '\f':
- content.append("\\f");
- break;
- case '(':
- case ')':
- case '\\':
- content.append_i('\\').append_i(c);
- break;
- default:
- content.append_i(c);
- }
- }
- content.append(")");
- }
-
- /**
- * Adds an outline to the document.
- *
- * @param outline the outline
- * @deprecated not needed anymore. The outlines are extracted
- * from the root outline
- */
- public void addOutline(PdfOutline outline) {
- // for compatibility
- }
- /**
- * Adds a named outline to the document.
- *
- * @param outline the outline
- * @param name the name for the local destination
- */
- public void addOutline(PdfOutline outline, String name) {
- checkWriter();
- pdf.addOutline(outline, name);
- }
- /**
- * Gets the root outline.
- *
- * @return the root outline
- */
- public PdfOutline getRootOutline() {
- checkWriter();
- return pdf.getRootOutline();
- }
-
- /**
- * Shows text right, left or center aligned with rotation.
- * @param alignment the alignment can be ALIGN_CENTER, ALIGN_RIGHT or ALIGN_LEFT
- * @param text the text to show
- * @param x the x pivot position
- * @param y the y pivot position
- * @param rotation the rotation to be applied in degrees counterclockwise
- */
- public void showTextAligned(int alignment, String text, float x, float y, float rotation) {
- if (state.fontDetails == null)
- throw new NullPointerException("Font and size must be set before writing any text");
- BaseFont bf = state.fontDetails.getBaseFont();
- if (rotation == 0) {
- switch (alignment) {
- case ALIGN_CENTER:
- x -= bf.getWidthPoint(text, state.size) / 2;
- break;
- case ALIGN_RIGHT:
- x -= bf.getWidthPoint(text, state.size);
- break;
- }
- setTextMatrix(x, y);
- showText(text);
- }
- else {
- double alpha = rotation * Math.PI / 180.0;
- float cos = (float)Math.cos(alpha);
- float sin = (float)Math.sin(alpha);
- float len;
- switch (alignment) {
- case ALIGN_CENTER:
- len = bf.getWidthPoint(text, state.size) / 2;
- x -= len * cos;
- y -= len * sin;
- break;
- case ALIGN_RIGHT:
- len = bf.getWidthPoint(text, state.size);
- x -= len * cos;
- y -= len * sin;
- break;
- }
- setTextMatrix(cos, sin, -sin, cos, x, y);
- showText(text);
- setTextMatrix(0f, 0f);
- }
- }
-
- /**
- * Shows text kerned right, left or center aligned with rotation.
- * @param alignement the alignment can be ALIGN_CENTER, ALIGN_RIGHT or ALIGN_LEFT
- * @param text the text to show
- * @param x the x pivot position
- * @param y the y pivot position
- * @param rotation the rotation to be applied in degrees counterclockwise
- */
- public void showTextAlignedKerned(int alignement, String text, float x, float y, float rotation) {
- if (state.fontDetails == null)
- throw new NullPointerException("Font and size must be set before writing any text");
- BaseFont bf = state.fontDetails.getBaseFont();
- if (rotation == 0) {
- switch (alignement) {
- case ALIGN_CENTER:
- x -= bf.getWidthPointKerned(text, state.size) / 2;
- break;
- case ALIGN_RIGHT:
- x -= bf.getWidthPointKerned(text, state.size);
- break;
- }
- setTextMatrix(x, y);
- showTextKerned(text);
- }
- else {
- double alpha = rotation * Math.PI / 180.0;
- float cos = (float)Math.cos(alpha);
- float sin = (float)Math.sin(alpha);
- float len;
- switch (alignement) {
- case ALIGN_CENTER:
- len = bf.getWidthPointKerned(text, state.size) / 2;
- x -= len * cos;
- y -= len * sin;
- break;
- case ALIGN_RIGHT:
- len = bf.getWidthPointKerned(text, state.size);
- x -= len * cos;
- y -= len * sin;
- break;
- }
- setTextMatrix(cos, sin, -sin, cos, x, y);
- showTextKerned(text);
- setTextMatrix(0f, 0f);
- }
- }
-
- /**
- * Concatenate a matrix to the current transformation matrix.
- * @param a an element of the transformation matrix
- * @param b an element of the transformation matrix
- * @param c an element of the transformation matrix
- * @param d an element of the transformation matrix
- * @param e an element of the transformation matrix
- * @param f an element of the transformation matrix
- **/
- public void concatCTM(float a, float b, float c, float d, float e, float f) {
- content.append(a).append(' ').append(b).append(' ').append(c).append(' ');
- content.append(d).append(' ').append(e).append(' ').append(f).append(" cm").append_i(separator);
- }
-
- /**
- * Generates an array of bezier curves to draw an arc.
- *
- * (x1, y1) and (x2, y2) are the corners of the enclosing rectangle.
- * Angles, measured in degrees, start with 0 to the right (the positive X
- * axis) and increase counter-clockwise. The arc extends from startAng
- * to startAng+extent. I.e. startAng=0 and extent=180 yields an openside-down
- * semi-circle.
- *
- * The resulting coordinates are of the form float[]{x1,y1,x2,y2,x3,y3, x4,y4}
- * such that the curve goes from (x1, y1) to (x4, y4) with (x2, y2) and
- * (x3, y3) as their respective Bezier control points.
- *
- * Note: this code was taken from ReportLab (www.reportlab.com), an excelent
- * PDF generator for Python.
- *
- * @param x1 a corner of the enclosing rectangle
- * @param y1 a corner of the enclosing rectangle
- * @param x2 a corner of the enclosing rectangle
- * @param y2 a corner of the enclosing rectangle
- * @param startAng starting angle in degrees
- * @param extent angle extent in degrees
- * @return a list of float[] with the bezier curves
- */
- public static ArrayList bezierArc(float x1, float y1, float x2, float y2, float startAng, float extent) {
- float tmp;
- if (x1 > x2) {
- tmp = x1;
- x1 = x2;
- x2 = tmp;
- }
- if (y2 > y1) {
- tmp = y1;
- y1 = y2;
- y2 = tmp;
- }
-
- float fragAngle;
- int Nfrag;
- if (Math.abs(extent) <= 90f) {
- fragAngle = extent;
- Nfrag = 1;
- }
- else {
- Nfrag = (int)(Math.ceil(Math.abs(extent)/90f));
- fragAngle = extent / Nfrag;
- }
- float x_cen = (x1+x2)/2f;
- float y_cen = (y1+y2)/2f;
- float rx = (x2-x1)/2f;
- float ry = (y2-y1)/2f;
- float halfAng = (float)(fragAngle * Math.PI / 360.);
- float kappa = (float)(Math.abs(4. / 3. * (1. - Math.cos(halfAng)) / Math.sin(halfAng)));
- ArrayList pointList = new ArrayList();
- for (int i = 0; i < Nfrag; ++i) {
- float theta0 = (float)((startAng + i*fragAngle) * Math.PI / 180.);
- float theta1 = (float)((startAng + (i+1)*fragAngle) * Math.PI / 180.);
- float cos0 = (float)Math.cos(theta0);
- float cos1 = (float)Math.cos(theta1);
- float sin0 = (float)Math.sin(theta0);
- float sin1 = (float)Math.sin(theta1);
- if (fragAngle > 0f) {
- pointList.add(new float[]{x_cen + rx * cos0,
- y_cen - ry * sin0,
- x_cen + rx * (cos0 - kappa * sin0),
- y_cen - ry * (sin0 + kappa * cos0),
- x_cen + rx * (cos1 + kappa * sin1),
- y_cen - ry * (sin1 - kappa * cos1),
- x_cen + rx * cos1,
- y_cen - ry * sin1});
- }
- else {
- pointList.add(new float[]{x_cen + rx * cos0,
- y_cen - ry * sin0,
- x_cen + rx * (cos0 + kappa * sin0),
- y_cen - ry * (sin0 - kappa * cos0),
- x_cen + rx * (cos1 - kappa * sin1),
- y_cen - ry * (sin1 + kappa * cos1),
- x_cen + rx * cos1,
- y_cen - ry * sin1});
- }
- }
- return pointList;
- }
-
- /**
- * Draws a partial ellipse inscribed within the rectangle x1,y1,x2,y2,
- * starting at startAng degrees and covering extent degrees. Angles
- * start with 0 to the right (+x) and increase counter-clockwise.
- *
- * @param x1 a corner of the enclosing rectangle
- * @param y1 a corner of the enclosing rectangle
- * @param x2 a corner of the enclosing rectangle
- * @param y2 a corner of the enclosing rectangle
- * @param startAng starting angle in degrees
- * @param extent angle extent in degrees
- */
- public void arc(float x1, float y1, float x2, float y2, float startAng, float extent) {
- ArrayList ar = bezierArc(x1, y1, x2, y2, startAng, extent);
- if (ar.size() == 0)
- return;
- float pt[] = (float [])ar.get(0);
- moveTo(pt[0], pt[1]);
- for (int k = 0; k < ar.size(); ++k) {
- pt = (float [])ar.get(k);
- curveTo(pt[2], pt[3], pt[4], pt[5], pt[6], pt[7]);
- }
- }
-
- /**
- * Draws an ellipse inscribed within the rectangle x1,y1,x2,y2.
- *
- * @param x1 a corner of the enclosing rectangle
- * @param y1 a corner of the enclosing rectangle
- * @param x2 a corner of the enclosing rectangle
- * @param y2 a corner of the enclosing rectangle
- */
- public void ellipse(float x1, float y1, float x2, float y2) {
- arc(x1, y1, x2, y2, 0f, 360f);
- }
-
- /**
- * Create a new colored tiling pattern.
- *
- * @param width the width of the pattern
- * @param height the height of the pattern
- * @param xstep the desired horizontal spacing between pattern cells.
- * May be either positive or negative, but not zero.
- * @param ystep the desired vertical spacing between pattern cells.
- * May be either positive or negative, but not zero.
- * @return the PdfPatternPainter
where the pattern will be created
- */
-
- public PdfPatternPainter createPattern(float width, float height, float xstep, float ystep) {
- checkWriter();
- if ( xstep == 0.0f || ystep == 0.0f )
- throw new RuntimeException("XStep or YStep can not be ZERO.");
- PdfPatternPainter painter = new PdfPatternPainter(writer);
- painter.setWidth(width);
- painter.setHeight(height);
- painter.setXStep(xstep);
- painter.setYStep(ystep);
- writer.addSimplePattern(painter);
- return painter;
- }
-
- /**
- * Create a new colored tiling pattern. Variables xstep and ystep are set to the same values
- * of width and height.
- * @param width the width of the pattern
- * @param height the height of the pattern
- * @return the PdfPatternPainter
where the pattern will be created
- */
- public PdfPatternPainter createPattern(float width, float height) {
- return createPattern(width, height, width, height);
- }
-
- /**
- * Create a new uncolored tiling pattern.
- *
- * @param width the width of the pattern
- * @param height the height of the pattern
- * @param xstep the desired horizontal spacing between pattern cells.
- * May be either positive or negative, but not zero.
- * @param ystep the desired vertical spacing between pattern cells.
- * May be either positive or negative, but not zero.
- * @param color the default color. Can be null
- * @return the PdfPatternPainter
where the pattern will be created
- */
- public PdfPatternPainter createPattern(float width, float height, float xstep, float ystep, Color color) {
- checkWriter();
- if ( xstep == 0.0f || ystep == 0.0f )
- throw new RuntimeException("XStep or YStep can not be ZERO.");
- PdfPatternPainter painter = new PdfPatternPainter(writer, color);
- painter.setWidth(width);
- painter.setHeight(height);
- painter.setXStep(xstep);
- painter.setYStep(ystep);
- writer.addSimplePattern(painter);
- return painter;
- }
-
- /**
- * Create a new uncolored tiling pattern.
- * Variables xstep and ystep are set to the same values
- * of width and height.
- * @param width the width of the pattern
- * @param height the height of the pattern
- * @param color the default color. Can be null
- * @return the PdfPatternPainter
where the pattern will be created
- */
- public PdfPatternPainter createPattern(float width, float height, Color color) {
- return createPattern(width, height, width, height, color);
- }
-
- /**
- * Creates a new template.
- *
- * Creates a new template that is nothing more than a form XObject. This template can be included
- * in this PdfContentByte
or in another template. Templates are only written
- * to the output when the document is closed permitting things like showing text in the first page
- * that is only defined in the last page.
- *
- * @param width the bounding box width
- * @param height the bounding box height
- * @return the templated created
- */
- public PdfTemplate createTemplate(float width, float height) {
- return createTemplate(width, height, null);
- }
-
- PdfTemplate createTemplate(float width, float height, PdfName forcedName) {
- checkWriter();
- PdfTemplate template = new PdfTemplate(writer);
- template.setWidth(width);
- template.setHeight(height);
- writer.addDirectTemplateSimple(template, forcedName);
- return template;
- }
-
- /**
- * Creates a new appearance to be used with form fields.
- *
- * @param width the bounding box width
- * @param height the bounding box height
- * @return the appearance created
- */
- public PdfAppearance createAppearance(float width, float height) {
- return createAppearance(width, height, null);
- }
-
- PdfAppearance createAppearance(float width, float height, PdfName forcedName) {
- checkWriter();
- PdfAppearance template = new PdfAppearance(writer);
- template.setWidth(width);
- template.setHeight(height);
- writer.addDirectTemplateSimple(template, forcedName);
- return template;
- }
-
- /**
- * Adds a PostScript XObject to this content.
- *
- * @param psobject the object
- */
- public void addPSXObject(PdfPSXObject psobject) {
- checkWriter();
- PdfName name = writer.addDirectTemplateSimple(psobject, null);
- PageResources prs = getPageResources();
- name = prs.addXObject(name, psobject.getIndirectReference());
- content.append(name.getBytes()).append(" Do").append_i(separator);
- }
-
- /**
- * Adds a template to this content.
- *
- * @param template the template
- * @param a an element of the transformation matrix
- * @param b an element of the transformation matrix
- * @param c an element of the transformation matrix
- * @param d an element of the transformation matrix
- * @param e an element of the transformation matrix
- * @param f an element of the transformation matrix
- */
- public void addTemplate(PdfTemplate template, float a, float b, float c, float d, float e, float f) {
- checkWriter();
- checkNoPattern(template);
- PdfName name = writer.addDirectTemplateSimple(template, null);
- PageResources prs = getPageResources();
- name = prs.addXObject(name, template.getIndirectReference());
- content.append("q ");
- content.append(a).append(' ');
- content.append(b).append(' ');
- content.append(c).append(' ');
- content.append(d).append(' ');
- content.append(e).append(' ');
- content.append(f).append(" cm ");
- content.append(name.getBytes()).append(" Do Q").append_i(separator);
- }
-
- /**
- * Adds a template to this content.
- *
- * @param template the template
- * @param x the x location of this template
- * @param y the y location of this template
- */
- public void addTemplate(PdfTemplate template, float x, float y) {
- addTemplate(template, 1, 0, 0, 1, x, y);
- }
-
- /**
- * Changes the current color for filling paths (device dependent colors!).
- *
- * Sets the color space to DeviceCMYK (or the DefaultCMYK color space),
- * and sets the color to use for filling paths.
- *
- * This method is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 8.5.2.1 (page 331).
- *
- * Following the PDF manual, each operand must be a number between 0 (no ink) and
- * 1 (maximum ink). This method however accepts only integers between 0x00 and 0xFF.
- *
- * @param cyan the intensity of cyan
- * @param magenta the intensity of magenta
- * @param yellow the intensity of yellow
- * @param black the intensity of black
- */
-
- public void setCMYKColorFill(int cyan, int magenta, int yellow, int black) {
- content.append((float)(cyan & 0xFF) / 0xFF);
- content.append(' ');
- content.append((float)(magenta & 0xFF) / 0xFF);
- content.append(' ');
- content.append((float)(yellow & 0xFF) / 0xFF);
- content.append(' ');
- content.append((float)(black & 0xFF) / 0xFF);
- content.append(" k").append_i(separator);
- }
- /**
- * Changes the current color for stroking paths (device dependent colors!).
- *
- * Sets the color space to DeviceCMYK (or the DefaultCMYK color space),
- * and sets the color to use for stroking paths.
- *
- * This method is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 8.5.2.1 (page 331).
- * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
- * 1 (maximum intensity). This method however accepts only integers between 0x00 and 0xFF.
- *
- * @param cyan the intensity of red
- * @param magenta the intensity of green
- * @param yellow the intensity of blue
- * @param black the intensity of black
- */
-
- public void setCMYKColorStroke(int cyan, int magenta, int yellow, int black) {
- content.append((float)(cyan & 0xFF) / 0xFF);
- content.append(' ');
- content.append((float)(magenta & 0xFF) / 0xFF);
- content.append(' ');
- content.append((float)(yellow & 0xFF) / 0xFF);
- content.append(' ');
- content.append((float)(black & 0xFF) / 0xFF);
- content.append(" K").append_i(separator);
- }
-
- /**
- * Changes the current color for filling paths (device dependent colors!).
- *
- * Sets the color space to DeviceRGB (or the DefaultRGB color space),
- * and sets the color to use for filling paths.
- *
- * This method is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 8.5.2.1 (page 331).
- *
- * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
- * 1 (maximum intensity). This method however accepts only integers between 0x00 and 0xFF.
- *
- * @param red the intensity of red
- * @param green the intensity of green
- * @param blue the intensity of blue
- */
-
- public void setRGBColorFill(int red, int green, int blue) {
- HelperRGB((float)(red & 0xFF) / 0xFF, (float)(green & 0xFF) / 0xFF, (float)(blue & 0xFF) / 0xFF);
- content.append(" rg").append_i(separator);
- }
-
- /**
- * Changes the current color for stroking paths (device dependent colors!).
- *
- * Sets the color space to DeviceRGB (or the DefaultRGB color space),
- * and sets the color to use for stroking paths.
- *
- * This method is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 8.5.2.1 (page 331).
- * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
- * 1 (maximum intensity). This method however accepts only integers between 0x00 and 0xFF.
- *
- * @param red the intensity of red
- * @param green the intensity of green
- * @param blue the intensity of blue
- */
-
- public void setRGBColorStroke(int red, int green, int blue) {
- HelperRGB((float)(red & 0xFF) / 0xFF, (float)(green & 0xFF) / 0xFF, (float)(blue & 0xFF) / 0xFF);
- content.append(" RG").append_i(separator);
- }
-
- /** Sets the stroke color. color
can be an
- * ExtendedColor
.
- * @param color the color
- */
- public void setColorStroke(Color color) {
- PdfWriter.checkPDFXConformance(writer, PdfWriter.PDFXKEY_COLOR, color);
- int type = ExtendedColor.getType(color);
- switch (type) {
- case ExtendedColor.TYPE_GRAY: {
- setGrayStroke(((GrayColor)color).getGray());
- break;
- }
- case ExtendedColor.TYPE_CMYK: {
- CMYKColor cmyk = (CMYKColor)color;
- setCMYKColorStrokeF(cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack());
- break;
- }
- case ExtendedColor.TYPE_SEPARATION: {
- SpotColor spot = (SpotColor)color;
- setColorStroke(spot.getPdfSpotColor(), spot.getTint());
- break;
- }
- case ExtendedColor.TYPE_PATTERN: {
- PatternColor pat = (PatternColor) color;
- setPatternStroke(pat.getPainter());
- break;
- }
- case ExtendedColor.TYPE_SHADING: {
- ShadingColor shading = (ShadingColor) color;
- setShadingStroke(shading.getPdfShadingPattern());
- break;
- }
- default:
- setRGBColorStroke(color.getRed(), color.getGreen(), color.getBlue());
- }
- }
-
- /** Sets the fill color. color
can be an
- * ExtendedColor
.
- * @param color the color
- */
- public void setColorFill(Color color) {
- PdfWriter.checkPDFXConformance(writer, PdfWriter.PDFXKEY_COLOR, color);
- int type = ExtendedColor.getType(color);
- switch (type) {
- case ExtendedColor.TYPE_GRAY: {
- setGrayFill(((GrayColor)color).getGray());
- break;
- }
- case ExtendedColor.TYPE_CMYK: {
- CMYKColor cmyk = (CMYKColor)color;
- setCMYKColorFillF(cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack());
- break;
- }
- case ExtendedColor.TYPE_SEPARATION: {
- SpotColor spot = (SpotColor)color;
- setColorFill(spot.getPdfSpotColor(), spot.getTint());
- break;
- }
- case ExtendedColor.TYPE_PATTERN: {
- PatternColor pat = (PatternColor) color;
- setPatternFill(pat.getPainter());
- break;
- }
- case ExtendedColor.TYPE_SHADING: {
- ShadingColor shading = (ShadingColor) color;
- setShadingFill(shading.getPdfShadingPattern());
- break;
- }
- default:
- setRGBColorFill(color.getRed(), color.getGreen(), color.getBlue());
- }
- }
-
- /** Sets the fill color to a spot color.
- * @param sp the spot color
- * @param tint the tint for the spot color. 0 is no color and 1
- * is 100% color
- */
- public void setColorFill(PdfSpotColor sp, float tint) {
- checkWriter();
- state.colorDetails = writer.addSimple(sp);
- PageResources prs = getPageResources();
- PdfName name = state.colorDetails.getColorName();
- name = prs.addColor(name, state.colorDetails.getIndirectReference());
- content.append(name.getBytes()).append(" cs ").append(tint).append(" scn").append_i(separator);
- }
-
- /** Sets the stroke color to a spot color.
- * @param sp the spot color
- * @param tint the tint for the spot color. 0 is no color and 1
- * is 100% color
- */
- public void setColorStroke(PdfSpotColor sp, float tint) {
- checkWriter();
- state.colorDetails = writer.addSimple(sp);
- PageResources prs = getPageResources();
- PdfName name = state.colorDetails.getColorName();
- name = prs.addColor(name, state.colorDetails.getIndirectReference());
- content.append(name.getBytes()).append(" CS ").append(tint).append(" SCN").append_i(separator);
- }
-
- /** Sets the fill color to a pattern. The pattern can be
- * colored or uncolored.
- * @param p the pattern
- */
- public void setPatternFill(PdfPatternPainter p) {
- if (p.isStencil()) {
- setPatternFill(p, p.getDefaultColor());
- return;
- }
- checkWriter();
- PageResources prs = getPageResources();
- PdfName name = writer.addSimplePattern(p);
- name = prs.addPattern(name, p.getIndirectReference());
- content.append(PdfName.PATTERN.getBytes()).append(" cs ").append(name.getBytes()).append(" scn").append_i(separator);
- }
-
- /** Outputs the color values to the content.
- * @param color The color
- * @param tint the tint if it is a spot color, ignored otherwise
- */
- void outputColorNumbers(Color color, float tint) {
- PdfWriter.checkPDFXConformance(writer, PdfWriter.PDFXKEY_COLOR, color);
- int type = ExtendedColor.getType(color);
- switch (type) {
- case ExtendedColor.TYPE_RGB:
- content.append((float)(color.getRed()) / 0xFF);
- content.append(' ');
- content.append((float)(color.getGreen()) / 0xFF);
- content.append(' ');
- content.append((float)(color.getBlue()) / 0xFF);
- break;
- case ExtendedColor.TYPE_GRAY:
- content.append(((GrayColor)color).getGray());
- break;
- case ExtendedColor.TYPE_CMYK: {
- CMYKColor cmyk = (CMYKColor)color;
- content.append(cmyk.getCyan()).append(' ').append(cmyk.getMagenta());
- content.append(' ').append(cmyk.getYellow()).append(' ').append(cmyk.getBlack());
- break;
- }
- case ExtendedColor.TYPE_SEPARATION:
- content.append(tint);
- break;
- default:
- throw new RuntimeException("Invalid color type.");
- }
- }
-
- /** Sets the fill color to an uncolored pattern.
- * @param p the pattern
- * @param color the color of the pattern
- */
- public void setPatternFill(PdfPatternPainter p, Color color) {
- if (ExtendedColor.getType(color) == ExtendedColor.TYPE_SEPARATION)
- setPatternFill(p, color, ((SpotColor)color).getTint());
- else
- setPatternFill(p, color, 0);
- }
-
- /** Sets the fill color to an uncolored pattern.
- * @param p the pattern
- * @param color the color of the pattern
- * @param tint the tint if the color is a spot color, ignored otherwise
- */
- public void setPatternFill(PdfPatternPainter p, Color color, float tint) {
- checkWriter();
- if (!p.isStencil())
- throw new RuntimeException("An uncolored pattern was expected.");
- PageResources prs = getPageResources();
- PdfName name = writer.addSimplePattern(p);
- name = prs.addPattern(name, p.getIndirectReference());
- ColorDetails csDetail = writer.addSimplePatternColorspace(color);
- PdfName cName = prs.addColor(csDetail.getColorName(), csDetail.getIndirectReference());
- content.append(cName.getBytes()).append(" cs").append_i(separator);
- outputColorNumbers(color, tint);
- content.append(' ').append(name.getBytes()).append(" scn").append_i(separator);
- }
-
- /** Sets the stroke color to an uncolored pattern.
- * @param p the pattern
- * @param color the color of the pattern
- */
- public void setPatternStroke(PdfPatternPainter p, Color color) {
- if (ExtendedColor.getType(color) == ExtendedColor.TYPE_SEPARATION)
- setPatternStroke(p, color, ((SpotColor)color).getTint());
- else
- setPatternStroke(p, color, 0);
- }
-
- /** Sets the stroke color to an uncolored pattern.
- * @param p the pattern
- * @param color the color of the pattern
- * @param tint the tint if the color is a spot color, ignored otherwise
- */
- public void setPatternStroke(PdfPatternPainter p, Color color, float tint) {
- checkWriter();
- if (!p.isStencil())
- throw new RuntimeException("An uncolored pattern was expected.");
- PageResources prs = getPageResources();
- PdfName name = writer.addSimplePattern(p);
- name = prs.addPattern(name, p.getIndirectReference());
- ColorDetails csDetail = writer.addSimplePatternColorspace(color);
- PdfName cName = prs.addColor(csDetail.getColorName(), csDetail.getIndirectReference());
- content.append(cName.getBytes()).append(" CS").append_i(separator);
- outputColorNumbers(color, tint);
- content.append(' ').append(name.getBytes()).append(" SCN").append_i(separator);
- }
-
- /** Sets the stroke color to a pattern. The pattern can be
- * colored or uncolored.
- * @param p the pattern
- */
- public void setPatternStroke(PdfPatternPainter p) {
- if (p.isStencil()) {
- setPatternStroke(p, p.getDefaultColor());
- return;
- }
- checkWriter();
- PageResources prs = getPageResources();
- PdfName name = writer.addSimplePattern(p);
- name = prs.addPattern(name, p.getIndirectReference());
- content.append(PdfName.PATTERN.getBytes()).append(" CS ").append(name.getBytes()).append(" SCN").append_i(separator);
- }
-
- /**
- * Paints using a shading object.
- * @param shading the shading object
- */
- public void paintShading(PdfShading shading) {
- writer.addSimpleShading(shading);
- PageResources prs = getPageResources();
- PdfName name = prs.addShading(shading.getShadingName(), shading.getShadingReference());
- content.append(name.getBytes()).append(" sh").append_i(separator);
- ColorDetails details = shading.getColorDetails();
- if (details != null)
- prs.addColor(details.getColorName(), details.getIndirectReference());
- }
-
- /**
- * Paints using a shading pattern.
- * @param shading the shading pattern
- */
- public void paintShading(PdfShadingPattern shading) {
- paintShading(shading.getShading());
- }
-
- /**
- * Sets the shading fill pattern.
- * @param shading the shading pattern
- */
- public void setShadingFill(PdfShadingPattern shading) {
- writer.addSimpleShadingPattern(shading);
- PageResources prs = getPageResources();
- PdfName name = prs.addPattern(shading.getPatternName(), shading.getPatternReference());
- content.append(PdfName.PATTERN.getBytes()).append(" cs ").append(name.getBytes()).append(" scn").append_i(separator);
- ColorDetails details = shading.getColorDetails();
- if (details != null)
- prs.addColor(details.getColorName(), details.getIndirectReference());
- }
-
- /**
- * Sets the shading stroke pattern
- * @param shading the shading pattern
- */
- public void setShadingStroke(PdfShadingPattern shading) {
- writer.addSimpleShadingPattern(shading);
- PageResources prs = getPageResources();
- PdfName name = prs.addPattern(shading.getPatternName(), shading.getPatternReference());
- content.append(PdfName.PATTERN.getBytes()).append(" CS ").append(name.getBytes()).append(" SCN").append_i(separator);
- ColorDetails details = shading.getColorDetails();
- if (details != null)
- prs.addColor(details.getColorName(), details.getIndirectReference());
- }
-
- /** Check if we have a valid PdfWriter.
- *
- */
- protected void checkWriter() {
- if (writer == null)
- throw new NullPointerException("The writer in PdfContentByte is null.");
- }
-
- /**
- * Show an array of text.
- * @param text array of text
- */
- public void showText(PdfTextArray text) {
- if (state.fontDetails == null)
- throw new NullPointerException("Font and size must be set before writing any text");
- content.append("[");
- ArrayList arrayList = text.getArrayList();
- boolean lastWasNumber = false;
- for (int k = 0; k < arrayList.size(); ++k) {
- Object obj = arrayList.get(k);
- if (obj instanceof String) {
- showText2((String)obj);
- lastWasNumber = false;
- }
- else {
- if (lastWasNumber)
- content.append(' ');
- else
- lastWasNumber = true;
- content.append(((Float)obj).floatValue());
- }
- }
- content.append("]TJ").append_i(separator);
- }
-
- /**
- * Gets the PdfWriter
in use by this object.
- * @return the PdfWriter
in use by this object
- */
- public PdfWriter getPdfWriter() {
- return writer;
- }
-
- /**
- * Gets the PdfDocument
in use by this object.
- * @return the PdfDocument
in use by this object
- */
- public PdfDocument getPdfDocument() {
- return pdf;
- }
-
- /**
- * Implements a link to other part of the document. The jump will
- * be made to a local destination with the same name, that must exist.
- * @param name the name for this link
- * @param llx the lower left x corner of the activation area
- * @param lly the lower left y corner of the activation area
- * @param urx the upper right x corner of the activation area
- * @param ury the upper right y corner of the activation area
- */
- public void localGoto(String name, float llx, float lly, float urx, float ury) {
- pdf.localGoto(name, llx, lly, urx, ury);
- }
-
- /**
- * The local destination to where a local goto with the same
- * name will jump.
- * @param name the name of this local destination
- * @param destination the PdfDestination
with the jump coordinates
- * @return true
if the local destination was added,
- * false
if a local destination with the same name
- * already exists
- */
- public boolean localDestination(String name, PdfDestination destination) {
- return pdf.localDestination(name, destination);
- }
-
- /**
- * Gets a duplicate of this PdfContentByte
. All
- * the members are copied by reference but the buffer stays different.
- *
- * @return a copy of this PdfContentByte
- */
- public PdfContentByte getDuplicate() {
- return new PdfContentByte(writer);
- }
-
- /**
- * Implements a link to another document.
- * @param filename the filename for the remote document
- * @param name the name to jump to
- * @param llx the lower left x corner of the activation area
- * @param lly the lower left y corner of the activation area
- * @param urx the upper right x corner of the activation area
- * @param ury the upper right y corner of the activation area
- */
- public void remoteGoto(String filename, String name, float llx, float lly, float urx, float ury) {
- pdf.remoteGoto(filename, name, llx, lly, urx, ury);
- }
-
- /**
- * Implements a link to another document.
- * @param filename the filename for the remote document
- * @param page the page to jump to
- * @param llx the lower left x corner of the activation area
- * @param lly the lower left y corner of the activation area
- * @param urx the upper right x corner of the activation area
- * @param ury the upper right y corner of the activation area
- */
- public void remoteGoto(String filename, int page, float llx, float lly, float urx, float ury) {
- pdf.remoteGoto(filename, page, llx, lly, urx, ury);
- }
- /**
- * Adds a round rectangle to the current path.
- *
- * @param x x-coordinate of the starting point
- * @param y y-coordinate of the starting point
- * @param w width
- * @param h height
- * @param r radius of the arc corner
- */
- public void roundRectangle(float x, float y, float w, float h, float r) {
- if (w < 0) {
- x += w;
- w = -w;
- }
- if (h < 0) {
- y += h;
- h = -h;
- }
- if (r < 0)
- r = -r;
- float b = 0.4477f;
- moveTo(x + r, y);
- lineTo(x + w - r, y);
- curveTo(x + w - r * b, y, x + w, y + r * b, x + w, y + r);
- lineTo(x + w, y + h - r);
- curveTo(x + w, y + h - r * b, x + w - r * b, y + h, x + w - r, y + h);
- lineTo(x + r, y + h);
- curveTo(x + r * b, y + h, x, y + h - r * b, x, y + h - r);
- lineTo(x, y + r);
- curveTo(x, y + r * b, x + r * b, y, x + r, y);
- }
-
- /** Implements an action in an area.
- * @param action the PdfAction
- * @param llx the lower left x corner of the activation area
- * @param lly the lower left y corner of the activation area
- * @param urx the upper right x corner of the activation area
- * @param ury the upper right y corner of the activation area
- */
- public void setAction(PdfAction action, float llx, float lly, float urx, float ury) {
- pdf.setAction(action, llx, lly, urx, ury);
- }
-
- /** Outputs a String
directly to the content.
- * @param s the String
- */
- public void setLiteral(String s) {
- content.append(s);
- }
-
- /** Outputs a char
directly to the content.
- * @param c the char
- */
- public void setLiteral(char c) {
- content.append(c);
- }
-
- /** Outputs a float
directly to the content.
- * @param n the float
- */
- public void setLiteral(float n) {
- content.append(n);
- }
-
- /** Throws an error if it is a pattern.
- * @param t the object to check
- */
- void checkNoPattern(PdfTemplate t) {
- if (t.getType() == PdfTemplate.TYPE_PATTERN)
- throw new RuntimeException("Invalid use of a pattern. A template was expected.");
- }
-
- /**
- * Draws a TextField.
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @param on
- */
- public void drawRadioField(float llx, float lly, float urx, float ury, boolean on) {
- if (llx > urx) { float x = llx; llx = urx; urx = x; }
- if (lly > ury) { float y = lly; lly = ury; ury = y; }
- // silver circle
- setLineWidth(1);
- setLineCap(1);
- setColorStroke(new Color(0xC0, 0xC0, 0xC0));
- arc(llx + 1f, lly + 1f, urx - 1f, ury - 1f, 0f, 360f);
- stroke();
- // gray circle-segment
- setLineWidth(1);
- setLineCap(1);
- setColorStroke(new Color(0xA0, 0xA0, 0xA0));
- arc(llx + 0.5f, lly + 0.5f, urx - 0.5f, ury - 0.5f, 45, 180);
- stroke();
- // black circle-segment
- setLineWidth(1);
- setLineCap(1);
- setColorStroke(new Color(0x00, 0x00, 0x00));
- arc(llx + 1.5f, lly + 1.5f, urx - 1.5f, ury - 1.5f, 45, 180);
- stroke();
- if (on) {
- // gray circle
- setLineWidth(1);
- setLineCap(1);
- setColorFill(new Color(0x00, 0x00, 0x00));
- arc(llx + 4f, lly + 4f, urx - 4f, ury - 4f, 0, 360);
- fill();
- }
- }
-
- /**
- * Draws a TextField.
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- */
- public void drawTextField(float llx, float lly, float urx, float ury) {
- if (llx > urx) { float x = llx; llx = urx; urx = x; }
- if (lly > ury) { float y = lly; lly = ury; ury = y; }
- // silver rectangle not filled
- setColorStroke(new Color(0xC0, 0xC0, 0xC0));
- setLineWidth(1);
- setLineCap(0);
- rectangle(llx, lly, urx - llx, ury - lly);
- stroke();
- // white rectangle filled
- setLineWidth(1);
- setLineCap(0);
- setColorFill(new Color(0xFF, 0xFF, 0xFF));
- rectangle(llx + 0.5f, lly + 0.5f, urx - llx - 1f, ury -lly - 1f);
- fill();
- // silver lines
- setColorStroke(new Color(0xC0, 0xC0, 0xC0));
- setLineWidth(1);
- setLineCap(0);
- moveTo(llx + 1f, lly + 1.5f);
- lineTo(urx - 1.5f, lly + 1.5f);
- lineTo(urx - 1.5f, ury - 1f);
- stroke();
- // gray lines
- setColorStroke(new Color(0xA0, 0xA0, 0xA0));
- setLineWidth(1);
- setLineCap(0);
- moveTo(llx + 1f, lly + 1);
- lineTo(llx + 1f, ury - 1f);
- lineTo(urx - 1f, ury - 1f);
- stroke();
- // black lines
- setColorStroke(new Color(0x00, 0x00, 0x00));
- setLineWidth(1);
- setLineCap(0);
- moveTo(llx + 2f, lly + 2f);
- lineTo(llx + 2f, ury - 2f);
- lineTo(urx - 2f, ury - 2f);
- stroke();
- }
-
- /**
- * Draws a button.
- * @param llx
- * @param lly
- * @param urx
- * @param ury
- * @param text
- * @param bf
- * @param size
- */
- public void drawButton(float llx, float lly, float urx, float ury, String text, BaseFont bf, float size) {
- if (llx > urx) { float x = llx; llx = urx; urx = x; }
- if (lly > ury) { float y = lly; lly = ury; ury = y; }
- // black rectangle not filled
- setColorStroke(new Color(0x00, 0x00, 0x00));
- setLineWidth(1);
- setLineCap(0);
- rectangle(llx, lly, urx - llx, ury - lly);
- stroke();
- // silver rectangle filled
- setLineWidth(1);
- setLineCap(0);
- setColorFill(new Color(0xC0, 0xC0, 0xC0));
- rectangle(llx + 0.5f, lly + 0.5f, urx - llx - 1f, ury -lly - 1f);
- fill();
- // white lines
- setColorStroke(new Color(0xFF, 0xFF, 0xFF));
- setLineWidth(1);
- setLineCap(0);
- moveTo(llx + 1f, lly + 1f);
- lineTo(llx + 1f, ury - 1f);
- lineTo(urx - 1f, ury - 1f);
- stroke();
- // dark grey lines
- setColorStroke(new Color(0xA0, 0xA0, 0xA0));
- setLineWidth(1);
- setLineCap(0);
- moveTo(llx + 1f, lly + 1f);
- lineTo(urx - 1f, lly + 1f);
- lineTo(urx - 1f, ury - 1f);
- stroke();
- // text
- resetRGBColorFill();
- beginText();
- setFontAndSize(bf, size);
- showTextAligned(PdfContentByte.ALIGN_CENTER, text, llx + (urx - llx) / 2, lly + (ury - lly - size) / 2, 0);
- endText();
- }
-
- /** Gets a Graphics2D
to write on. The graphics
- * are translated to PDF commands as shapes. No PDF fonts will appear.
- * @param width the width of the panel
- * @param height the height of the panel
- * @return a Graphics2D
- */
- /* ssteward: dropped in 1.44
- public java.awt.Graphics2D createGraphicsShapes(float width, float height) {
- return new PdfGraphics2D(this, width, height, null, true, false, 0);
- }
- */
-
- /** Gets a Graphics2D
to print on. The graphics
- * are translated to PDF commands as shapes. No PDF fonts will appear.
- * @param width the width of the panel
- * @param height the height of the panel
- * @param printerJob a printer job
- * @return a Graphics2D
- */
- /* ssteward: dropped in 1.44
- public java.awt.Graphics2D createPrinterGraphicsShapes(float width, float height, PrinterJob printerJob) {
- return new PdfPrinterGraphics2D(this, width, height, null, true, false, 0, printerJob);
- }
- */
-
- /** Gets a Graphics2D
to write on. The graphics
- * are translated to PDF commands.
- * @param width the width of the panel
- * @param height the height of the panel
- * @return a Graphics2D
- */
- /* ssteward: dropped in 1.44
- public java.awt.Graphics2D createGraphics(float width, float height) {
- return new PdfGraphics2D(this, width, height, null, false, false, 0);
- }
- */
-
- /** Gets a Graphics2D
to print on. The graphics
- * are translated to PDF commands.
- * @param width the width of the panel
- * @param height the height of the panel
- * @param printerJob
- * @return a Graphics2D
- */
- /* ssteward: dropped in 1.44
- public java.awt.Graphics2D createPrinterGraphics(float width, float height, PrinterJob printerJob) {
- return new PdfPrinterGraphics2D(this, width, height, null, false, false, 0, printerJob);
- }
- */
-
- /** Gets a Graphics2D
to write on. The graphics
- * are translated to PDF commands.
- * @param width the width of the panel
- * @param height the height of the panel
- * @param convertImagesToJPEG
- * @param quality
- * @return a Graphics2D
- */
- /* ssteward: dropped in 1.44
- public java.awt.Graphics2D createGraphics(float width, float height, boolean convertImagesToJPEG, float quality) {
- return new PdfGraphics2D(this, width, height, null, false, convertImagesToJPEG, quality);
- }
- */
-
- /** Gets a Graphics2D
to print on. The graphics
- * are translated to PDF commands.
- * @param width the width of the panel
- * @param height the height of the panel
- * @param convertImagesToJPEG
- * @param quality
- * @param printerJob
- * @return a Graphics2D
- */
- /* ssteward: dropped in 1.44
- public java.awt.Graphics2D createPrinterGraphics(float width, float height, boolean convertImagesToJPEG, float quality, PrinterJob printerJob) {
- return new PdfPrinterGraphics2D(this, width, height, null, false, convertImagesToJPEG, quality, printerJob);
- }
- */
-
- /** Gets a Graphics2D
to print on. The graphics
- * are translated to PDF commands.
- * @param width
- * @param height
- * @param convertImagesToJPEG
- * @param quality
- * @return A Graphics2D object
- */
- /* ssteward: dropped in 1.44
- public java.awt.Graphics2D createGraphicsShapes(float width, float height, boolean convertImagesToJPEG, float quality) {
- return new PdfGraphics2D(this, width, height, null, true, convertImagesToJPEG, quality);
- }
- */
-
- /** Gets a Graphics2D
to print on. The graphics
- * are translated to PDF commands.
- * @param width
- * @param height
- * @param convertImagesToJPEG
- * @param quality
- * @param printerJob
- * @return a Graphics2D object
- */
- /* ssteward: dropped in 1.44
- public java.awt.Graphics2D createPrinterGraphicsShapes(float width, float height, boolean convertImagesToJPEG, float quality, PrinterJob printerJob) {
- return new PdfPrinterGraphics2D(this, width, height, null, true, convertImagesToJPEG, quality, printerJob);
- }
- */
-
- /** Gets a Graphics2D
to write on. The graphics
- * are translated to PDF commands.
- * @param width the width of the panel
- * @param height the height of the panel
- * @param fontMapper the mapping from awt fonts to BaseFont
- * @return a Graphics2D
- */
- /* ssteward: dropped in 1.44
- public java.awt.Graphics2D createGraphics(float width, float height, FontMapper fontMapper) {
- return new PdfGraphics2D(this, width, height, fontMapper, false, false, 0);
- }
- */
-
- /** Gets a Graphics2D
to print on. The graphics
- * are translated to PDF commands.
- * @param width the width of the panel
- * @param height the height of the panel
- * @param fontMapper the mapping from awt fonts to BaseFont
- * @param printerJob a printer job
- * @return a Graphics2D
- */
- /* ssteward: dropped in 1.44
- public java.awt.Graphics2D createPrinterGraphics(float width, float height, FontMapper fontMapper, PrinterJob printerJob) {
- return new PdfPrinterGraphics2D(this, width, height, fontMapper, false, false, 0, printerJob);
- }
- */
-
- /** Gets a Graphics2D
to write on. The graphics
- * are translated to PDF commands.
- * @param width the width of the panel
- * @param height the height of the panel
- * @param fontMapper the mapping from awt fonts to BaseFont
- * @param convertImagesToJPEG converts awt images to jpeg before inserting in pdf
- * @param quality the quality of the jpeg
- * @return a Graphics2D
- */
- /* ssteward: dropped in 1.44
- public java.awt.Graphics2D createGraphics(float width, float height, FontMapper fontMapper, boolean convertImagesToJPEG, float quality) {
- return new PdfGraphics2D(this, width, height, fontMapper, false, convertImagesToJPEG, quality);
- }
- */
-
- /** Gets a Graphics2D
to print on. The graphics
- * are translated to PDF commands.
- * @param width the width of the panel
- * @param height the height of the panel
- * @param fontMapper the mapping from awt fonts to BaseFont
- * @param convertImagesToJPEG converts awt images to jpeg before inserting in pdf
- * @param quality the quality of the jpeg
- * @param printerJob a printer job
- * @return a Graphics2D
- */
- /* ssteward: dropped in 1.44
- public java.awt.Graphics2D createPrinterGraphics(float width, float height, FontMapper fontMapper, boolean convertImagesToJPEG, float quality, PrinterJob printerJob) {
- return new PdfPrinterGraphics2D(this, width, height, fontMapper, false, convertImagesToJPEG, quality, printerJob);
- }
- */
-
- PageResources getPageResources() {
- return pdf.getPageResources();
- }
-
- /** Sets the graphic state
- * @param gstate the graphic state
- */
- public void setGState(PdfGState gstate) {
- PdfObject obj[] = writer.addSimpleExtGState(gstate);
- PageResources prs = getPageResources();
- PdfName name = prs.addExtGState((PdfName)obj[0], (PdfIndirectReference)obj[1]);
- content.append(name.getBytes()).append(" gs").append_i(separator);
- }
-
- /**
- * Begins a graphic block whose visibility is controled by the layer
.
- * Blocks can be nested. Each block must be terminated by an {@link #endLayer()}.
- * Note that nested layers with {@link PdfLayer#addChild(PdfLayer)} only require a single
- * call to this method and a single call to {@link #endLayer()}; all the nesting control
- * is built in.
- * @param layer the layer
- */
- public void beginLayer(PdfOCG layer) {
- if ((layer instanceof PdfLayer) && ((PdfLayer)layer).getTitle() != null)
- throw new IllegalArgumentException("A title is not a layer");
- if (layerDepth == null)
- layerDepth = new ArrayList();
- if (layer instanceof PdfLayerMembership) {
- layerDepth.add(new Integer(1));
- beginLayer2(layer);
- return;
- }
- int n = 0;
- PdfLayer la = (PdfLayer)layer;
- while (la != null) {
- if (la.getTitle() == null) {
- beginLayer2(la);
- ++n;
- }
- la = la.getParent();
- }
- layerDepth.add(new Integer(n));
- }
-
- private void beginLayer2(PdfOCG layer) {
- PdfName name = (PdfName)writer.addSimpleProperty(layer, layer.getRef())[0];
- PageResources prs = getPageResources();
- name = prs.addProperty(name, layer.getRef());
- content.append("/OC ").append(name.getBytes()).append(" BDC").append_i(separator);
- }
-
- /**
- * Ends a layer controled graphic block. It will end the most recent open block.
- */
- public void endLayer() {
- int n = 1;
- if (layerDepth != null && layerDepth.size() > 0) {
- n = ((Integer)layerDepth.get(layerDepth.size() - 1)).intValue();
- layerDepth.remove(layerDepth.size() - 1);
- }
- while (n-- > 0)
- content.append("EMC").append_i(separator);
- }
-
- /** Concatenates a transformation to the current transformation
- * matrix.
- * @param af the transformation
- */
- public void transform(AffineTransform af) {
- double arr[] = new double[6];
- af.getMatrix(arr);
- content.append(arr[0]).append(' ').append(arr[1]).append(' ').append(arr[2]).append(' ');
- content.append(arr[3]).append(' ').append(arr[4]).append(' ').append(arr[5]).append(" cm").append_i(separator);
- }
-
- void addAnnotation(PdfAnnotation annot) {
- writer.addAnnotation(annot);
- }
-
- /**
- * Sets the default colorspace.
- * @param name the name of the colorspace. It can be PdfName.DEFAULTGRAY
, PdfName.DEFAULTRGB
- * or PdfName.DEFAULTCMYK
- * @param obj the colorspace. A null
or PdfNull
removes any colorspace with the same name
- */
- public void setDefaultColorspace(PdfName name, PdfObject obj) {
- PageResources prs = getPageResources();
- prs.addDefaultColor(name, obj);
- }
-
- /**
- * Begins a marked content sequence. This sequence will be tagged with the structure struc
.
- * The same structure can be used several times to connect text that belongs to the same logical segment
- * but is in a different location, like the same paragraph crossing to another page, for example.
- * @param struc the tagging structure
- */
- public void beginMarkedContentSequence(PdfStructureElement struc) {
- PdfObject obj = struc.get(PdfName.K);
- int mark = pdf.getMarkPoint();
- if (obj != null) {
- PdfArray ar = null;
- if (obj.isNumber()) {
- ar = new PdfArray();
- ar.add(obj);
- struc.put(PdfName.K, ar);
- }
- else if (obj.isArray()) {
- ar = (PdfArray)obj;
- if (!((PdfObject)ar.getArrayList().get(0)).isNumber())
- throw new IllegalArgumentException("The structure has kids.");
- }
- else
- throw new IllegalArgumentException("Unknown object at /K " + obj.getClass().toString());
- PdfDictionary dic = new PdfDictionary(PdfName.MCR);
- dic.put(PdfName.PG, writer.getCurrentPage());
- dic.put(PdfName.MCID, new PdfNumber(mark));
- ar.add(dic);
- struc.setPageMark(writer.getPageNumber() - 1, -1);
- }
- else {
- struc.setPageMark(writer.getPageNumber() - 1, mark);
- struc.put(PdfName.PG, writer.getCurrentPage());
- }
- pdf.incMarkPoint();
- content.append(struc.get(PdfName.S).getBytes()).append(" <> BDC").append_i(separator);
- }
-
- /**
- * Ends a marked content sequence
- */
- public void endMarkedContentSequence() {
- content.append("EMC").append_i(separator);
- }
-
- /**
- * Begins a marked content sequence. If property is null
the mark will be of the type
- * BMC
otherwise it will be BDC
.
- * @param tag the tag
- * @param property the property
- * @param inline true
to include the property in the content or false
- * to include the property in the resource dictionary with the possibility of reusing
- */
- public void beginMarkedContentSequence(PdfName tag, PdfDictionary property, boolean inline) {
- if (property == null) {
- content.append(tag.getBytes()).append(" BMC").append_i(separator);
- return;
- }
- content.append(tag.getBytes()).append(' ');
- if (inline)
- try {
- property.toPdf(writer, content);
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- else {
- PdfObject[] objs;
- if (writer.propertyExists(property))
- objs = writer.addSimpleProperty(property, null);
- else
- objs = writer.addSimpleProperty(property, writer.getPdfIndirectReference());
- PdfName name = (PdfName)objs[0];
- PageResources prs = getPageResources();
- name = prs.addProperty(name, (PdfIndirectReference)objs[1]);
- content.append(name.getBytes());
- }
- content.append(" BDC").append_i(separator);
- }
-
- /**
- * This is just a shorthand to beginMarkedContentSequence(tag, null, false)
.
- * @param tag the tag
- */
- public void beginMarkedContentSequence(PdfName tag) {
- beginMarkedContentSequence(tag, null, false);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfContents.java pdftk-2.01/java/com/lowagie/text/pdf/PdfContents.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfContents.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfContents.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,153 +0,0 @@
-/*
- * $Id: PdfContents.java,v 1.26 2002/06/20 13:28:22 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.DocWriter;
-import com.lowagie.text.Document;
-import com.lowagie.text.Rectangle;
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.util.zip.DeflaterOutputStream;
-
-/**
- * PdfContents
is a PdfStream
containing the contents (text + graphics) of a PdfPage
.
- */
-
-class PdfContents extends PdfStream {
-
- static final byte SAVESTATE[] = DocWriter.getISOBytes("q\n");
- static final byte RESTORESTATE[] = DocWriter.getISOBytes("Q\n");
- static final byte ROTATE90[] = DocWriter.getISOBytes("0 1 -1 0 ");
- static final byte ROTATE180[] = DocWriter.getISOBytes("-1 0 0 -1 ");
- static final byte ROTATE270[] = DocWriter.getISOBytes("0 -1 1 0 ");
- static final byte ROTATEFINAL[] = DocWriter.getISOBytes(" cm\n");
- // constructor
-
-/**
- * Constructs a PdfContents
-object, containing text and general graphics.
- *
- * @param under the direct content that is under all others
- * @param content the graphics in a page
- * @param text the text in a page
- * @param secondContent the direct content that is over all others
- * @throws BadPdfFormatException on error
- */
-
- PdfContents(PdfContentByte under, PdfContentByte content, PdfContentByte text, PdfContentByte secondContent, Rectangle page) throws BadPdfFormatException {
- super();
- try {
- OutputStream out = null;
- streamBytes = new ByteArrayOutputStream();
- if (Document.compress)
- {
- compressed = true;
- out = new DeflaterOutputStream(streamBytes);
- }
- else
- out = streamBytes;
- int rotation = page.getRotation();
- switch (rotation) {
- case 90:
- out.write(ROTATE90);
- out.write(DocWriter.getISOBytes(ByteBuffer.formatDouble(page.top())));
- out.write(' ');
- out.write('0');
- out.write(ROTATEFINAL);
- break;
- case 180:
- out.write(ROTATE180);
- out.write(DocWriter.getISOBytes(ByteBuffer.formatDouble(page.right())));
- out.write(' ');
- out.write(DocWriter.getISOBytes(ByteBuffer.formatDouble(page.top())));
- out.write(ROTATEFINAL);
- break;
- case 270:
- out.write(ROTATE270);
- out.write('0');
- out.write(' ');
- out.write(DocWriter.getISOBytes(ByteBuffer.formatDouble(page.right())));
- out.write(ROTATEFINAL);
- break;
- }
- if (under.size() > 0) {
- out.write(SAVESTATE);
- under.getInternalBuffer().writeTo(out);
- out.write(RESTORESTATE);
- }
- if (content.size() > 0) {
- out.write(SAVESTATE);
- content.getInternalBuffer().writeTo(out);
- out.write(RESTORESTATE);
- }
- if (text != null) {
- out.write(SAVESTATE);
- text.getInternalBuffer().writeTo(out);
- out.write(RESTORESTATE);
- }
- if (secondContent.size() > 0) {
- secondContent.getInternalBuffer().writeTo(out);
- }
- out.close();
- }
- catch (Exception e) {
- throw new BadPdfFormatException(e.getMessage());
- }
- put(PdfName.LENGTH, new PdfNumber(streamBytes.size()));
- if (compressed)
- put(PdfName.FILTER, PdfName.FLATEDECODE);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfCopy.java pdftk-2.01/java/com/lowagie/text/pdf/PdfCopy.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfCopy.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfCopy.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,756 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * $Id: PdfCopy.java,v 1.35 2005/05/04 14:32:21 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- * Co-Developer of the code is Sid Steward. Portions created by the Co-Developer
- * are Copyright (C) 2004, 2010 by Sid Steward. All Rights Reserved.
- *
- * This module by Mark Thompson. Copyright (C) 2002 Mark Thompson
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.util.HashMap;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Iterator;
-import java.io.*;
-import com.lowagie.text.ExceptionConverter;
-import com.lowagie.text.Document;
-import com.lowagie.text.DocumentException;
-
-import java.util.HashSet;
-
-/**
- * Make copies of PDF documents. Documents can be edited after reading and
- * before writing them out.
- * @author Mark Thompson
- */
-
-public class PdfCopy extends PdfWriter {
- /**
- * This class holds information about indirect references, since they are
- * renumbered by iText.
- */
- static class IndirectReferences {
- PdfIndirectReference theRef;
- boolean hasCopied;
- IndirectReferences(PdfIndirectReference ref) {
- theRef = ref;
- hasCopied = false;
- }
- void setCopied() { hasCopied = true; }
- boolean getCopied() { return hasCopied; }
- PdfIndirectReference getRef() { return theRef; }
- };
- protected HashMap indirects;
- protected HashMap indirectMap;
- protected int currentObjectNum = 1;
- protected PdfReader reader;
- // ssteward: why does PdfCopy have an acroForm, when PdfDocument already has one
- //protected PdfIndirectReference acroForm;
- protected PdfIndirectReference topPageParent;
- protected ArrayList pageNumbersToRefs = new ArrayList();
- protected List newBookmarks;
-
- // ssteward: pdftk 1.10; to ensure unique form field names, as pages are added
- protected HashSet fullFormFieldNames; // all full field names; track to prevent collision
- protected HashSet topFormFieldNames; // across all readers; track to prevent collision
- protected class TopFormFieldData {
- HashMap newNamesRefs; // map new top parent field names to refs
- HashMap newNamesKids; // map new top parent field names to kids PdfArray
- HashSet allNames; // ~all~ names, new and not-new
- public TopFormFieldData() {
- newNamesRefs= new HashMap();
- newNamesKids= new HashMap();
- allNames= new HashSet();
- }
- };
- protected HashMap topFormFieldReadersData; // I wish this was C++, where I could templates
-
- /**
- * A key to allow us to hash indirect references
- */
- protected static class RefKey {
- int num;
- int gen;
- RefKey(int num, int gen) {
- this.num = num;
- this.gen = gen;
- }
- RefKey(PdfIndirectReference ref) {
- num = ref.getNumber();
- gen = ref.getGeneration();
- }
- RefKey(PRIndirectReference ref) {
- num = ref.getNumber();
- gen = ref.getGeneration();
- }
- public int hashCode() {
- return (gen<<16)+num;
- }
- public boolean equals(Object o) {
- RefKey other = (RefKey)o;
- return this.gen == other.gen && this.num == other.num;
- }
- public String toString() {
- return "" + num + " " + gen;
- }
- }
-
- /**
- * Constructor
- * @param document
- * @param os outputstream
- */
- public PdfCopy(Document document, OutputStream os) throws DocumentException {
- super(new PdfDocument(), os);
- document.addDocListener(pdf);
- pdf.addWriter(this);
- indirectMap = new HashMap();
-
- // ssteward: pdftk 1.10
- fullFormFieldNames = new HashSet();
- topFormFieldNames = new HashSet();
- topFormFieldReadersData = new HashMap();
- }
- public void open() {
- super.open();
- topPageParent = getPdfIndirectReference();
- root.setLinearMode(topPageParent);
- }
-
- /**
- * Grabs a page from the input document
- * @param reader the reader of the document
- * @param pageNumber which page to get
- * @return the page
- */
- public PdfImportedPage getImportedPage(PdfReader reader, int pageNumber) {
- if (currentPdfReaderInstance != null) {
- if (currentPdfReaderInstance.getReader() != reader) {
- try {
- currentPdfReaderInstance.getReader().close();
- currentPdfReaderInstance.getReaderFile().close();
- }
- catch (IOException ioe) {
- // empty on purpose
- }
- currentPdfReaderInstance = reader.getPdfReaderInstance(this);
- }
- }
- else {
- currentPdfReaderInstance = reader.getPdfReaderInstance(this);
- }
- return currentPdfReaderInstance.getImportedPage(pageNumber);
- }
-
-
- /**
- * Translate a PRIndirectReference to a PdfIndirectReference
- * In addition, translates the object numbers, and copies the
- * referenced object to the output file.
- * NB: PRIndirectReferences (and PRIndirectObjects) really need to know what
- * file they came from, because each file has its own namespace. The translation
- * we do from their namespace to ours is *at best* heuristic, and guaranteed to
- * fail under some circumstances.
- */
- protected PdfIndirectReference copyIndirect(PRIndirectReference in) throws IOException, BadPdfFormatException {
- PdfIndirectReference theRef;
- RefKey key = new RefKey(in);
- IndirectReferences iRef = (IndirectReferences)indirects.get(key);
- boolean recurse_b= true; // ssteward
-
- if (iRef != null) {
- theRef = iRef.getRef();
- if (iRef.getCopied()) { // we've already copied this
- return theRef;
- }
- }
- else {
- theRef = body.getPdfIndirectReference();
- iRef = new IndirectReferences(theRef);
- indirects.put(key, iRef);
- }
-
- // ssteward; if this is a ref to a dictionary with a parent,
- // and we haven't copied the parent yet, then don't recurse
- // into this dictionary; wait to recurse via the parent;
- // this was written to fix a problem with references to pages
- // inside pdf destinations; this problem caused pdf bloat;
- // the pdf spec says broken indirect ref.s (ref, but no obj) are okay;
- //
- // update: we /do/ want to recurse up form field parents (see addPage()),
- // just /not/ pages with parents
- //
- // note: copying an indirect reference to a dictionary is
- // more suspect than copying a dictionary
- //
- // simplify this by not recursing into /any/ type==page via indirect ref?
-
- PdfObject in_obj= (PdfObject)reader.getPdfObject( in );
- if( in_obj!= null && in_obj.isDictionary() ) {
- PdfDictionary in_dict= (PdfDictionary)in_obj;
-
- PdfName type= (PdfName)in_dict.get( PdfName.TYPE );
- if( type!= null && type.isName() && type.equals( PdfName.PAGE ) ) {
-
- PdfObject parent_obj=
- (PdfObject)in_dict.get( PdfName.PARENT );
- if( parent_obj!= null && parent_obj.isIndirect() ) {
- PRIndirectReference parent_iref= (PRIndirectReference)parent_obj;
-
- RefKey parent_key= new RefKey( parent_iref );
- IndirectReferences parent_ref= (IndirectReferences)indirects.get( parent_key );
-
- if( parent_ref== null || !parent_ref.getCopied() ) {
- // parent has not been copied yet, so we've jumped here somehow;
- recurse_b= false;
- }
- }
- }
- }
-
- if( recurse_b ) {
- iRef.setCopied();
- PdfObject obj = copyObject((PdfObject)PdfReader.getPdfObjectRelease(in));
- addToBody(obj, theRef);
- }
-
- return theRef;
- }
-
- /**
- * Translate a PRDictionary to a PdfDictionary. Also translate all of the
- * objects contained in it.
- */
- protected PdfDictionary copyDictionary(PdfDictionary in)
- throws IOException, BadPdfFormatException {
- PdfDictionary out = new PdfDictionary();
- PdfName type = (PdfName)in.get(PdfName.TYPE);
-
- for (Iterator it = in.getKeys().iterator(); it.hasNext();) {
- PdfName key = (PdfName)it.next();
- PdfObject value = in.get(key);
- // System.err.println("Copy " + key); // debug
- if (type != null && PdfName.PAGE.equals(type)) {
- if (key.equals(PdfName.PARENT))
- out.put(PdfName.PARENT, topPageParent);
- else if (!key.equals(PdfName.B))
- out.put(key, copyObject(value));
- }
- else
- out.put(key, copyObject(value));
- }
- return out;
- }
-
- /**
- * Translate a PRStream to a PdfStream. The data part copies itself.
- */
- protected PdfStream copyStream(PRStream in) throws IOException, BadPdfFormatException {
- PRStream out = new PRStream(in, null);
-
- for (Iterator it = in.getKeys().iterator(); it.hasNext();) {
- PdfName key = (PdfName) it.next();
- PdfObject value = in.get(key);
- out.put(key, copyObject(value));
- }
-
- return out;
- }
-
-
- /**
- * Translate a PRArray to a PdfArray. Also translate all of the objects contained
- * in it
- */
- protected PdfArray copyArray(PdfArray in) throws IOException, BadPdfFormatException {
- PdfArray out = new PdfArray();
-
- for (Iterator i = in.getArrayList().iterator(); i.hasNext();) {
- PdfObject value = (PdfObject)i.next();
- out.add(copyObject(value));
- }
- return out;
- }
-
- /**
- * Translate a PR-object to a Pdf-object
- */
- protected PdfObject copyObject(PdfObject in) throws IOException,BadPdfFormatException {
- switch (in.type) {
- case PdfObject.DICTIONARY:
- // System.err.println("Dictionary: " + in.toString());
- return copyDictionary((PdfDictionary)in);
- case PdfObject.INDIRECT:
- return copyIndirect((PRIndirectReference)in);
- case PdfObject.ARRAY:
- return copyArray((PdfArray)in);
- case PdfObject.NUMBER:
- case PdfObject.NAME:
- case PdfObject.STRING:
- case PdfObject.m_NULL: // ssteward
- case PdfObject.BOOLEAN:
- return in;
- case PdfObject.STREAM:
- return copyStream((PRStream)in);
- // return in;
- default:
- if (in.type < 0) {
- String lit = ((PdfLiteral)in).toString();
- if (lit.equals("true") || lit.equals("false")) {
- return new PdfBoolean(lit);
- }
- return new PdfLiteral(lit);
- }
- System.err.println("CANNOT COPY type " + in.type);
- return null;
- }
- }
-
- /**
- * convenience method. Given an importedpage, set our "globals"
- */
- protected int setFromIPage(PdfImportedPage iPage) {
- int pageNum = iPage.getPageNumber();
- PdfReaderInstance inst = currentPdfReaderInstance = iPage.getPdfReaderInstance();
- reader = inst.getReader();
- setFromReader(reader);
- return pageNum;
- }
-
- /**
- * convenience method. Given a reader, set our "globals"
- */
- protected void setFromReader(PdfReader reader) {
- this.reader = reader;
- indirects = (HashMap)indirectMap.get(reader);
- if (indirects == null) {
- indirects = new HashMap();
- indirectMap.put(reader,indirects);
- PdfDictionary catalog = reader.getCatalog();
- PRIndirectReference ref = (PRIndirectReference)catalog.get(PdfName.PAGES);
- indirects.put(new RefKey(ref), new IndirectReferences(topPageParent));
- /* ssteward: why PdfCopy.acroForm when PdfDocument.acroForm?
- ref = (PRIndirectReference)catalog.get(PdfName.ACROFORM);
- if (ref != null) {
- if (acroForm == null) acroForm = body.getPdfIndirectReference();
- indirects.put(new RefKey(ref), new IndirectReferences(acroForm));
- }
- */
- }
- }
- /**
- * Add an imported page to our output
- * @param iPage an imported page
- * @throws IOException, BadPdfFormatException
- */
- public void addPage(PdfImportedPage iPage) throws IOException, BadPdfFormatException {
- int pageNum = setFromIPage(iPage); // sets this.reader
-
- PdfDictionary thePage = reader.getPageN(pageNum);
- PRIndirectReference origRef = reader.getPageOrigRef(pageNum);
- reader.releasePage(pageNum);
- RefKey key = new RefKey(origRef);
- PdfIndirectReference pageRef;
- IndirectReferences iRef = (IndirectReferences)indirects.get(key);
- // if we already have an iref for the page (we got here by another link)
- if (iRef != null) {
- pageRef = iRef.getRef();
- }
- else {
- pageRef = body.getPdfIndirectReference();
- iRef = new IndirectReferences(pageRef);
- indirects.put(key, iRef);
- }
- pageReferences.add(pageRef);
- ++currentPageNumber;
- if (! iRef.getCopied()) {
- iRef.setCopied();
-
- // ssteward
- if( !this.topFormFieldReadersData.containsKey( reader ) ) { // add
- this.topFormFieldReadersData.put( reader, new TopFormFieldData() );
- }
- TopFormFieldData readerData= (TopFormFieldData)topFormFieldReadersData.get(reader);
-
- // ssteward
- // if duplicate form field names are encountered
- // make names unique by inserting a new top parent "field";
- // insert this new parent into the PdfReader of the input document,
- // since any PdfWriter material may have been written already; our
- // changes to the PdfReader will be copied, below, into the PdfWriter;
- //
- {
- PdfArray annots= (PdfArray)reader.getPdfObject(thePage.get(PdfName.ANNOTS));
- if( annots!= null && annots.isArray() ) {
- ArrayList annots_arr= annots.getArrayList();
- for( int ii= 0; ii< annots_arr.size(); ++ii ) {
- // an annotation may be direct or indirect; ours must be indirect
- PdfObject annot_obj= (PdfObject)annots_arr.get(ii);
- if( annot_obj!= null && annot_obj.isIndirect() ) {
- PdfIndirectReference annot_ref= (PdfIndirectReference)annot_obj;
- if( annot_ref!= null ) {
- PdfDictionary annot= (PdfDictionary)reader.getPdfObject(annot_ref);
- if( annot!= null && annot.isDictionary() ) {
- PdfName subtype= (PdfName)reader.getPdfObject(annot.get(PdfName.SUBTYPE));
- if( subtype!= null && subtype.isName() && subtype.equals(PdfName.WIDGET) ) {
- // we have a form field
-
- // get its full name
- //
- String full_name= ""; // construct a full name from partial names using '.', e.g.: foo.bar.
- String top_name= "";
- boolean is_unicode_b= false; // if names are unicode, they must all be unicode
- PdfString tt= (PdfString)reader.getPdfObject(annot.get(PdfName.T));
- if( tt!= null && tt.isString() ) {
- top_name= tt.toString();
- is_unicode_b= ( is_unicode_b || PdfString.isUnicode( tt.getBytes() ) );
- }
- //
- // dig upwards, parent-wise; replace annot as we go with the
- // top-most form field dictionary
- PdfIndirectReference parent_ref=
- (PdfIndirectReference)annot.get(PdfName.PARENT);
- while( parent_ref!= null && parent_ref.isIndirect() )
- {
- annot_ref= parent_ref;
- annot= (PdfDictionary)reader.getPdfObject(annot_ref);
- parent_ref= (PdfIndirectReference)annot.get(PdfName.PARENT);
-
- tt= (PdfString)reader.getPdfObject(annot.get(PdfName.T));
- if( tt!= null && tt.isString() ) {
- if( top_name.length()!= 0 ) {
- full_name+= top_name;
- full_name+= ".";
- }
- top_name= tt.toString();
- }
-
- is_unicode_b= ( is_unicode_b || PdfString.isUnicode( tt.getBytes() ) );
- }
-
- // once we have seen a top-level field parent, we wave
- // it through and assume that it harbors no illegal field duplicates;
- // this is good, because sometimes authors want a single field
- // represented by more than one annotation on the page; this logic
- // respects that programming
- //
- //System.err.println( full_name+ top_name+ "." ); // debug
- if( readerData.allNames.contains( top_name ) )
- { // a parent we have seen or created in this reader
- this.fullFormFieldNames.add( full_name+ top_name+ "." ); // tally
- }
- else {
- if( this.fullFormFieldNames.contains( full_name+ top_name+ "." ) ) {
- // insert new, top-most parent
-
- // name for new parent
- int new_parent_name_ii= 1;
- String new_parent_name= Integer.toString( new_parent_name_ii );
- while( this.fullFormFieldNames.contains( full_name+ top_name+ "."+ new_parent_name+ "." ) ||
- this.topFormFieldNames.contains( new_parent_name ) &&
- !readerData.newNamesKids.containsKey( new_parent_name ) )
- {
- new_parent_name= Integer.toString( ++new_parent_name_ii );
- }
-
- PdfIndirectReference new_parent_ref= null;
- PdfArray new_parent_kids= null;
- //
- if( readerData.newNamesKids.containsKey( new_parent_name ) ) {
- // a new parent we already created
- new_parent_ref= (PdfIndirectReference)
- readerData.newNamesRefs.get( new_parent_name );
- new_parent_kids= (PdfArray)
- readerData.newNamesKids.get( new_parent_name );
- }
- else { // create a new parent using this name
- PdfDictionary new_parent= new PdfDictionary();
- PdfString new_parent_name_pdf= new PdfString( new_parent_name );
- if( is_unicode_b ) { // if names are unicode, they must all be unicode
- new_parent_name_pdf= new PdfString( new_parent_name, PdfObject.TEXT_UNICODE );
- }
- new_parent_ref= reader.getPRIndirectReference( new_parent );
- new_parent.put( PdfName.T, new_parent_name_pdf );
-
- new_parent_kids= new PdfArray();
- PdfIndirectReference new_parent_kids_ref=
- reader.getPRIndirectReference( new_parent_kids );
- new_parent.put(PdfName.KIDS, new_parent_kids_ref);
-
- // tally new parent
- readerData.newNamesRefs.put( new_parent_name, new_parent_ref );
- readerData.newNamesKids.put( new_parent_name, new_parent_kids );
- readerData.allNames.add( new_parent_name );
- this.topFormFieldNames.add( new_parent_name );
- }
-
- // wire annot and new parent together
- annot.put( PdfName.PARENT, new_parent_ref );
- new_parent_kids.add( annot_ref ); // the new parent must point at the field, too
-
- // tally full field name
- this.fullFormFieldNames.add( full_name+ top_name+ "."+ new_parent_name+ "." );
- }
- else {
- // tally parent
- readerData.allNames.add( top_name );
- this.topFormFieldNames.add( top_name );
-
- // tally full field name
- this.fullFormFieldNames.add( full_name+ top_name+ "." );
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- // copy the page; this will copy our work, above, into the target document
- PdfDictionary newPage = copyDictionary(thePage);
-
-
- // ssteward: pdftk-1.00;
- // copy page form field ref.s into document AcroForm
- // dig down into source page to find indirect ref., then
- // look up ref. in dest page.; store ref.s in the PdfDocument acroForm,
- // not the PdfCopy acroForm (which isn't really a PdfAcroForm, anyhow);
- //
- // dig down to annot, and then dig up to topmost Parent
- {
- PdfArray annots= (PdfArray)reader.getPdfObject(thePage.get(PdfName.ANNOTS));
- if( annots!= null && annots.isArray() ) {
- ArrayList annots_arr= annots.getArrayList();
- for( int ii= 0; ii< annots_arr.size(); ++ii ) {
- // an annotation may be direct or indirect; ours must be indirect
- PdfObject annot_obj= (PdfObject)annots_arr.get(ii);
- if( annot_obj!= null && annot_obj.isIndirect() ) {
- PdfIndirectReference annot_ref= (PdfIndirectReference)annots_arr.get(ii);
- if( annot_ref!= null ) {
- PdfDictionary annot= (PdfDictionary)reader.getPdfObject(annot_ref);
- if( annot!= null && annot.isDictionary() ) {
- PdfName subtype= (PdfName)reader.getPdfObject(annot.get(PdfName.SUBTYPE));
- if( subtype!= null && subtype.isName() && subtype.equals(PdfName.WIDGET) ) {
- // we have a form field
-
- // dig upwards, parent-wise
- PdfIndirectReference parent_ref=
- (PdfIndirectReference)annot.get(PdfName.PARENT);
- while( parent_ref!= null && parent_ref.isIndirect() ) {
- annot_ref= parent_ref;
- annot= (PdfDictionary)reader.getPdfObject(annot_ref);
- parent_ref= (PdfIndirectReference)annot.get(PdfName.PARENT);
- }
-
- RefKey annot_key= new RefKey(annot_ref);
- IndirectReferences annot_iRef= (IndirectReferences)indirects.get(annot_key);
- PdfAcroForm acroForm= this.getAcroForm();
- acroForm.addDocumentField( annot_iRef.getRef() );
- }
- }
- }
- }
- }
- }
- }
-
- // ssteward: pdftk-1.00;
- // merge the reader AcroForm/DR dictionary with the target
- //
- // pdftk-1.10: I noticed that the PdfAcroForm.isValid() apprears to stomp on this (TODO)
- //
- PdfDictionary catalog= reader.getCatalog();
- if( catalog!= null && catalog.isDictionary() ) {
- PdfDictionary acroForm= (PdfDictionary)reader.getPdfObject(catalog.get(PdfName.ACROFORM));
- if( acroForm!= null && acroForm.isDictionary() ) {
- PdfDictionary dr= (PdfDictionary)reader.getPdfObject(acroForm.get(PdfName.DR));
- if( dr!= null && dr.isDictionary() ) {
- PdfDictionary acroForm_target= this.getAcroForm();
- PdfDictionary dr_target= (PdfDictionary)reader.getPdfObject(acroForm_target.get(PdfName.DR));
- if( dr_target== null ) {
- PdfDictionary dr_copy= copyDictionary( dr );
- acroForm_target.put( PdfName.DR, dr_copy );
- }
- else {
- for( Iterator it= dr.getKeys().iterator(); it.hasNext(); ) {
- PdfName dr_key= (PdfName)it.next();
- PdfObject dr_val= (PdfObject)dr.get(dr_key);
- if( !dr_target.contains( dr_key ) ) { // copy key/value to dr_target
- dr_target.put( dr_key, copyObject( dr_val ) );
- }
- }
- }
- }
- }
- }
-
-
- newPage.put(PdfName.PARENT, topPageParent);
- addToBody(newPage, pageRef);
- }
- root.addPage(pageRef);
- pageNumbersToRefs.add(pageRef);
- }
-
- public PdfIndirectReference getPageReference(int page) {
- if (page < 0 || page > pageNumbersToRefs.size())
- throw new IllegalArgumentException("Invalid page number " + page);
- return (PdfIndirectReference)pageNumbersToRefs.get(page - 1);
- }
-
- /**
- * Copy the acroform for an input document. Note that you can only have one,
- * we make no effort to merge them.
- * @param reader The reader of the input file that is being copied
- * @throws IOException, BadPdfFormatException
- */
- /* ssteward: why PdfCopy.acroForm when PdfDocument.acroForm?
- public void copyAcroForm(PdfReader reader) throws IOException, BadPdfFormatException {
- setFromReader(reader);
-
- PdfDictionary catalog = reader.getCatalog();
- PRIndirectReference hisRef = null;
- PdfObject o = catalog.get(PdfName.ACROFORM);
- if (o != null && o.type() == PdfObject.INDIRECT)
- hisRef = (PRIndirectReference)o;
- RefKey key = new RefKey(hisRef);
- PdfIndirectReference myRef;
- IndirectReferences iRef = (IndirectReferences)indirects.get(key);
- if (iRef != null) {
- acroForm = myRef = iRef.getRef();
- }
- else {
- acroForm = myRef = body.getPdfIndirectReference();
- iRef = new IndirectReferences(myRef);
- indirects.put(key, iRef);
- }
- if (! iRef.getCopied()) {
- iRef.setCopied();
- PdfDictionary theForm = copyDictionary((PdfDictionary)PdfReader.getPdfObject(hisRef));
- PdfIndirectObject myObj = addToBody(theForm, myRef);
- }
- }
- */
-
- /*
- * the getCatalog method is part of PdfWriter.
- * we wrap this so that we can extend it
- */
- protected PdfDictionary getCatalog(PdfIndirectReference rootObj) {
- try {
- PdfDictionary theCat = ((PdfDocument)document).getCatalog(rootObj);
- // ssteward: this just overwrites the ACROFORM entry added by
- // PdfDocument.getCatalog(); dropped, because we use PdfDocument.acroForm, above;
- //if (acroForm != null) theCat.put(PdfName.ACROFORM, acroForm);
- if (newBookmarks == null || newBookmarks.size() == 0)
- return theCat;
- PdfDictionary top = new PdfDictionary();
- PdfIndirectReference topRef = getPdfIndirectReference();
- Object kids[] = SimpleBookmark.iterateOutlines(this, topRef, newBookmarks, false);
- top.put(PdfName.FIRST, (PdfIndirectReference)kids[0]);
- top.put(PdfName.LAST, (PdfIndirectReference)kids[1]);
- top.put(PdfName.COUNT, new PdfNumber(((Integer)kids[2]).intValue()));
- addToBody(top, topRef);
- theCat.put(PdfName.OUTLINES, topRef);
- return theCat;
- }
- catch (IOException e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Sets the bookmarks. The list structure is defined in
- * SimpleBookmark#
.
- * @param outlines the bookmarks or null
to remove any
- */
- public void setOutlines(List outlines) {
- newBookmarks = outlines;
- }
-
- /**
- * Signals that the Document
was closed and that no other
- * Elements
will be added.
- *
- * The pages-tree is built and written to the outputstream.
- * A Catalog is constructed, as well as an Info-object,
- * the referencetable is composed and everything is written
- * to the outputstream embedded in a Trailer.
- */
-
- public synchronized void close() {
- if (open) {
- PdfReaderInstance ri = currentPdfReaderInstance;
- pdf.close();
- super.close();
- if (ri != null) {
- try {
- ri.getReader().close();
- ri.getReaderFile().close();
- }
- catch (IOException ioe) {
- // empty on purpose
- }
- }
- }
- }
- // PdfIndirectReference add(PdfImage pdfImage) throws PdfException { return null; } ssteward: dropped in 1.44
- public PdfIndirectReference add(PdfOutline outline) { return null; }
- public void addAnnotation(PdfAnnotation annot) { }
- PdfIndirectReference add(PdfPage page, PdfContents contents) throws PdfException { return null; }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfCopyFieldsImp.java pdftk-2.01/java/com/lowagie/text/pdf/PdfCopyFieldsImp.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfCopyFieldsImp.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfCopyFieldsImp.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,645 +0,0 @@
-/*
- * $Id: PdfCopyFieldsImp.java,v 1.10 2005/05/17 11:21:46 blowagie Exp $
- * $Name: $
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.ExceptionConverter;
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.Document;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.StringTokenizer;
-
-/**
- *
- * @author psoares
- */
-class PdfCopyFieldsImp extends PdfWriter {
-
- private static final PdfName iTextTag = new PdfName("_iTextTag_");
- private static final Integer zero = new Integer(0);
- ArrayList readers = new ArrayList();
- HashMap readers2intrefs = new HashMap();
- HashMap pages2intrefs = new HashMap();
- HashMap visited = new HashMap();
- ArrayList fields = new ArrayList();
- RandomAccessFileOrArray file;
- HashMap fieldTree = new HashMap();
- ArrayList pageRefs = new ArrayList();
- ArrayList pageDics = new ArrayList();
- PdfDictionary resources = new PdfDictionary();
- PdfDictionary form;
- protected List newBookmarks;
- boolean closing = false;
- Document nd;
- private HashMap tabOrder;
- private ArrayList calculationOrder = new ArrayList();
- private ArrayList calculationOrderRefs;
-
- PdfCopyFieldsImp(OutputStream os) throws DocumentException, IOException {
- this(os, '\0');
- }
-
- PdfCopyFieldsImp(OutputStream os, char pdfVersion) throws DocumentException, IOException {
- super(new PdfDocument(), os);
- pdf.addWriter(this);
- if (pdfVersion != 0)
- super.setPdfVersion(pdfVersion);
- nd = new Document();
- nd.addDocListener(pdf);
- }
-
- void addDocument(PdfReader reader, List pagesToKeep) throws DocumentException {
- if (!readers2intrefs.containsKey(reader) && reader.isTampered())
- throw new DocumentException("The document was reused.");
- reader = new PdfReader(reader);
- reader.selectPages(pagesToKeep);
- if (reader.getNumberOfPages() == 0)
- return;
- reader.setTampered(false);
- addDocument(reader);
- }
-
- void addDocument(PdfReader reader) throws DocumentException {
- openDoc();
- if (readers2intrefs.containsKey(reader)) {
- reader = new PdfReader(reader);
- }
- else {
- if (reader.isTampered())
- throw new DocumentException("The document was reused.");
- reader.consolidateNamedDestinations();
- reader.setTampered(true);
- }
- reader.shuffleSubsetNames();
- readers2intrefs.put(reader, new IntHashtable());
- readers.add(reader);
- int len = reader.getNumberOfPages();
- IntHashtable refs = new IntHashtable();
- for (int p = 1; p <= len; ++p) {
- refs.put(reader.getPageOrigRef(p).getNumber(), 1);
- reader.releasePage(p);
- }
- pages2intrefs.put(reader, refs);
- visited.put(reader, new IntHashtable());
- fields.add(reader.getAcroFields());
- updateCalculationOrder(reader);
- }
-
- private static String getCOName(PdfReader reader, PRIndirectReference ref) {
- String name = "";
- while (ref != null) {
- PdfObject obj = PdfReader.getPdfObject(ref);
- if (obj == null || obj.type() != PdfObject.DICTIONARY)
- break;
- PdfDictionary dic = (PdfDictionary)obj;
- PdfString t = (PdfString)PdfReader.getPdfObject(dic.get(PdfName.T));
- if (t != null) {
- name = t.toUnicodeString()+ "." + name;
- }
- ref = (PRIndirectReference)dic.get(PdfName.PARENT);
- }
- if (name.endsWith("."))
- name = name.substring(0, name.length() - 1);
- return name;
- }
-
- private void updateCalculationOrder(PdfReader reader) {
- PdfDictionary catalog = reader.getCatalog();
- PdfDictionary acro = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.ACROFORM));
- if (acro == null)
- return;
- PdfArray co = (PdfArray)PdfReader.getPdfObject(acro.get(PdfName.CO));
- if (co == null || co.size() == 0)
- return;
- AcroFields af = reader.getAcroFields();
- ArrayList coa = co.getArrayList();
- for (int k = 0; k < coa.size(); ++k) {
- PdfObject obj = (PdfObject)coa.get(k);
- if (obj == null || !obj.isIndirect())
- continue;
- String name = getCOName(reader, (PRIndirectReference)obj);
- if (af.getFieldItem(name) == null)
- continue;
- name = "." + name;
- if (calculationOrder.contains(name))
- continue;
- calculationOrder.add(name);
- }
- }
-
- void propagate(PdfObject obj, PdfIndirectReference refo, boolean restricted) throws IOException {
- if (obj == null)
- return;
-// if (refo != null)
-// addToBody(obj, refo);
- if (obj instanceof PdfIndirectReference)
- return;
- switch (obj.type()) {
- case PdfObject.DICTIONARY:
- case PdfObject.STREAM: {
- PdfDictionary dic = (PdfDictionary)obj;
- for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
- PdfName key = (PdfName)it.next();
- if (restricted && (key.equals(PdfName.PARENT) || key.equals(PdfName.KIDS)))
- continue;
- PdfObject ob = dic.get(key);
- if (ob != null && ob.isIndirect()) {
- PRIndirectReference ind = (PRIndirectReference)ob;
- if (!setVisited(ind) && !isPage(ind)) {
- PdfIndirectReference ref = getNewReference(ind);
- propagate(PdfReader.getPdfObjectRelease(ind), ref, restricted);
- }
- }
- else
- propagate(ob, null, restricted);
- }
- break;
- }
- case PdfObject.ARRAY: {
- ArrayList list = ((PdfArray)obj).getArrayList();
- //PdfArray arr = new PdfArray();
- for (Iterator it = list.iterator(); it.hasNext();) {
- PdfObject ob = (PdfObject)it.next();
- if (ob != null && ob.isIndirect()) {
- PRIndirectReference ind = (PRIndirectReference)ob;
- if (!isVisited(ind) && !isPage(ind)) {
- PdfIndirectReference ref = getNewReference(ind);
- propagate(PdfReader.getPdfObjectRelease(ind), ref, restricted);
- }
- }
- else
- propagate(ob, null, restricted);
- }
- break;
- }
- case PdfObject.INDIRECT: {
- throw new RuntimeException("Reference pointing to reference.");
- }
- }
- }
-
- private void adjustTabOrder(PdfArray annots, PdfIndirectReference ind, PdfNumber nn) {
- int v = nn.intValue();
- ArrayList t = (ArrayList)tabOrder.get(annots);
- if (t == null) {
- t = new ArrayList();
- int size = annots.size() - 1;
- for (int k = 0; k < size; ++k) {
- t.add(zero);
- }
- t.add(new Integer(v));
- tabOrder.put(annots, t);
- annots.add(ind);
- }
- else {
- int size = t.size() - 1;
- for (int k = size; k >= 0; --k) {
- if (((Integer)t.get(k)).intValue() <= v) {
- t.add(k + 1, new Integer(v));
- annots.getArrayList().add(k + 1, ind);
- size = -2;
- break;
- }
- }
- if (size != -2) {
- t.add(0, new Integer(v));
- annots.getArrayList().add(0, ind);
- }
- }
- }
-
- protected PdfArray branchForm(HashMap level, PdfIndirectReference parent, String fname) throws IOException {
- PdfArray arr = new PdfArray();
- for (Iterator it = level.keySet().iterator(); it.hasNext();) {
- String name = (String)it.next();
- Object obj = level.get(name);
- PdfIndirectReference ind = getPdfIndirectReference();
- PdfDictionary dic = new PdfDictionary();
- if (parent != null)
- dic.put(PdfName.PARENT, parent);
- dic.put(PdfName.T, new PdfString(name, PdfObject.TEXT_UNICODE));
- String fname2 = fname + "." + name;
- int coidx = calculationOrder.indexOf(fname2);
- if (coidx >= 0)
- calculationOrderRefs.set(coidx, ind);
- if (obj instanceof HashMap) {
- dic.put(PdfName.KIDS, branchForm((HashMap)obj, ind, fname2));
- arr.add(ind);
- addToBody(dic, ind);
- }
- else {
- ArrayList list = (ArrayList)obj;
- dic.mergeDifferent((PdfDictionary)list.get(0));
- if (list.size() == 3) {
- dic.mergeDifferent((PdfDictionary)list.get(2));
- int page = ((Integer)list.get(1)).intValue();
- PdfDictionary pageDic = (PdfDictionary)pageDics.get(page - 1);
- PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
- if (annots == null) {
- annots = new PdfArray();
- pageDic.put(PdfName.ANNOTS, annots);
- }
- PdfNumber nn = (PdfNumber)dic.get(iTextTag);
- dic.remove(iTextTag);
- adjustTabOrder(annots, ind, nn);
- }
- else {
- PdfArray kids = new PdfArray();
- for (int k = 1; k < list.size(); k += 2) {
- int page = ((Integer)list.get(k)).intValue();
- PdfDictionary pageDic = (PdfDictionary)pageDics.get(page - 1);
- PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
- if (annots == null) {
- annots = new PdfArray();
- pageDic.put(PdfName.ANNOTS, annots);
- }
- PdfDictionary widget = new PdfDictionary();
- widget.merge((PdfDictionary)list.get(k + 1));
- widget.put(PdfName.PARENT, ind);
- PdfNumber nn = (PdfNumber)widget.get(iTextTag);
- widget.remove(iTextTag);
- PdfIndirectReference wref = addToBody(widget).getIndirectReference();
- adjustTabOrder(annots, wref, nn);
- kids.add(wref);
- propagate(widget, null, false);
- }
- dic.put(PdfName.KIDS, kids);
- }
- arr.add(ind);
- addToBody(dic, ind);
- propagate(dic, null, false);
- }
- }
- return arr;
- }
-
- protected void createAcroForms() throws IOException {
- if (fieldTree.size() == 0)
- return;
- form = new PdfDictionary();
- form.put(PdfName.DR, resources);
- propagate(resources, null, false);
- form.put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
- tabOrder = new HashMap();
- calculationOrderRefs = new ArrayList(calculationOrder);
- form.put(PdfName.FIELDS, branchForm(fieldTree, null, ""));
- PdfArray co = new PdfArray();
- for (int k = 0; k < calculationOrderRefs.size(); ++k) {
- Object obj = calculationOrderRefs.get(k);
- if (obj instanceof PdfIndirectReference)
- co.add((PdfIndirectReference)obj);
- }
- if (co.size() > 0)
- form.put(PdfName.CO, co);
- }
-
- public void close() {
- if (closing) {
- super.close();
- return;
- }
- closing = true;
- try {
- closeIt();
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- protected void closeIt() throws DocumentException, IOException {
- for (int k = 0; k < readers.size(); ++k) {
- ((PdfReader)readers.get(k)).removeFields();
- }
- for (int r = 0; r < readers.size(); ++r) {
- PdfReader reader = (PdfReader)readers.get(r);
- for (int page = 1; page <= reader.getNumberOfPages(); ++page) {
- pageRefs.add(getNewReference(reader.getPageOrigRef(page)));
- pageDics.add(reader.getPageN(page));
- }
- }
- mergeFields();
- createAcroForms();
- for (int r = 0; r < readers.size(); ++r) {
- PdfReader reader = (PdfReader)readers.get(r);
- for (int page = 1; page <= reader.getNumberOfPages(); ++page) {
- PdfDictionary dic = reader.getPageN(page);
- PdfIndirectReference pageRef = getNewReference(reader.getPageOrigRef(page));
- PdfIndirectReference parent = root.addPageRef(pageRef);
- dic.put(PdfName.PARENT, parent);
- propagate(dic, pageRef, false);
- }
- }
- for (Iterator it = readers2intrefs.keySet().iterator(); it.hasNext();) {
- PdfReader reader = (PdfReader)it.next();
- try {
- file = reader.getSafeFile();
- file.reOpen();
- IntHashtable t = (IntHashtable)readers2intrefs.get(reader);
- int keys[] = t.toOrderedKeys();
- for (int k = 0; k < keys.length; ++k) {
- PRIndirectReference ref = new PRIndirectReference(reader, keys[k]);
- addToBody(PdfReader.getPdfObjectRelease(ref), t.get(keys[k]));
- }
- }
- finally {
- try {
- file.close();
- reader.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- }
- pdf.close();
- }
-
- void addPageOffsetToField(HashMap fd, int pageOffset) {
- if (pageOffset == 0)
- return;
- for (Iterator it = fd.values().iterator(); it.hasNext();) {
- ArrayList page = ((AcroFields.Item)it.next()).page;
- for (int k = 0; k < page.size(); ++k)
- page.set(k, new Integer(((Integer)page.get(k)).intValue() + pageOffset));
- }
- }
-
- void createWidgets(ArrayList list, AcroFields.Item item) {
- for (int k = 0; k < item.merged.size(); ++k) {
- list.add(item.page.get(k));
- PdfDictionary merged = (PdfDictionary)item.merged.get(k);
- PdfObject dr = merged.get(PdfName.DR);
- if (dr != null)
- PdfFormField.mergeResources(resources, (PdfDictionary)PdfReader.getPdfObject(dr));
- PdfDictionary widget = new PdfDictionary();
- for (Iterator it = merged.getKeys().iterator(); it.hasNext();) {
- PdfName key = (PdfName)it.next();
- if (widgetKeys.containsKey(key))
- widget.put(key, merged.get(key));
- }
- widget.put(iTextTag, new PdfNumber(((Integer)item.tabOrder.get(k)).intValue() + 1));
- list.add(widget);
- }
- }
-
- void mergeField(String name, AcroFields.Item item) {
- HashMap map = fieldTree;
- StringTokenizer tk = new StringTokenizer(name, ".");
- if (!tk.hasMoreTokens())
- return;
- while (true) {
- String s = tk.nextToken();
- Object obj = map.get(s);
- if (tk.hasMoreTokens()) {
- if (obj == null) {
- obj = new HashMap();
- map.put(s, obj);
- map = (HashMap)obj;
- continue;
- }
- else if (obj instanceof HashMap)
- map = (HashMap)obj;
- else
- return;
- }
- else {
- if (obj instanceof HashMap)
- return;
- PdfDictionary merged = (PdfDictionary)item.merged.get(0);
- if (obj == null) {
- PdfDictionary field = new PdfDictionary();
- for (Iterator it = merged.getKeys().iterator(); it.hasNext();) {
- PdfName key = (PdfName)it.next();
- if (fieldKeys.containsKey(key))
- field.put(key, merged.get(key));
- }
- ArrayList list = new ArrayList();
- list.add(field);
- createWidgets(list, item);
- map.put(s, list);
- }
- else {
- ArrayList list = (ArrayList)obj;
- PdfDictionary field = (PdfDictionary)list.get(0);
- PdfName type1 = (PdfName)field.get(PdfName.FT);
- PdfName type2 = (PdfName)merged.get(PdfName.FT);
- if (type1 == null || !type1.equals(type2))
- return;
- int flag1 = 0;
- PdfObject f1 = field.get(PdfName.FF);
- if (f1 != null && f1.isNumber())
- flag1 = ((PdfNumber)f1).intValue();
- int flag2 = 0;
- PdfObject f2 = merged.get(PdfName.FF);
- if (f2 != null && f2.isNumber())
- flag2 = ((PdfNumber)f2).intValue();
- if (type1.equals(PdfName.BTN)) {
- if (((flag1 ^ flag2) & PdfFormField.FF_PUSHBUTTON) != 0)
- return;
- if ((flag1 & PdfFormField.FF_PUSHBUTTON) == 0 && ((flag1 ^ flag2) & PdfFormField.FF_RADIO) != 0)
- return;
- }
- else if (type1.equals(PdfName.CH)) {
- if (((flag1 ^ flag2) & PdfFormField.FF_COMBO) != 0)
- return;
- }
- createWidgets(list, item);
- }
- return;
- }
- }
- }
-
- void mergeWithMaster(HashMap fd) {
- for (Iterator it = fd.keySet().iterator(); it.hasNext();) {
- String name = (String)it.next();
- mergeField(name, (AcroFields.Item)fd.get(name));
- }
- }
-
- void mergeFields() {
- int pageOffset = 0;
- for (int k = 0; k < fields.size(); ++k) {
- HashMap fd = ((AcroFields)fields.get(k)).getFields();
- addPageOffsetToField(fd, pageOffset);
- mergeWithMaster(fd);
- pageOffset += ((PdfReader)readers.get(k)).getNumberOfPages();
- }
- }
-
- public PdfIndirectReference getPageReference(int page) {
- return (PdfIndirectReference)pageRefs.get(page - 1);
- }
-
- protected PdfDictionary getCatalog(PdfIndirectReference rootObj) {
- try {
- PdfDictionary cat = ((PdfDocument)document).getCatalog(rootObj);
- if (form != null) {
- PdfIndirectReference ref = addToBody(form).getIndirectReference();
- cat.put(PdfName.ACROFORM, ref);
- }
- if (newBookmarks == null || newBookmarks.size() == 0)
- return cat;
- PdfDictionary top = new PdfDictionary();
- PdfIndirectReference topRef = getPdfIndirectReference();
- Object kids[] = SimpleBookmark.iterateOutlines(this, topRef, newBookmarks, false);
- top.put(PdfName.FIRST, (PdfIndirectReference)kids[0]);
- top.put(PdfName.LAST, (PdfIndirectReference)kids[1]);
- top.put(PdfName.COUNT, new PdfNumber(((Integer)kids[2]).intValue()));
- addToBody(top, topRef);
- cat.put(PdfName.OUTLINES, topRef);
- return cat;
- }
- catch (IOException e) {
- throw new ExceptionConverter(e);
- }
- }
-
- protected PdfIndirectReference getNewReference(PRIndirectReference ref) {
- return new PdfIndirectReference(0, getNewObjectNumber(ref.getReader(), ref.getNumber(), 0));
- }
-
- protected int getNewObjectNumber(PdfReader reader, int number, int generation) {
- IntHashtable refs = (IntHashtable)readers2intrefs.get(reader);
- int n = refs.get(number);
- if (n == 0) {
- n = getIndirectReferenceNumber();
- refs.put(number, n);
- }
- return n;
- }
-
- protected boolean isVisited(PdfReader reader, int number, int generation) {
- IntHashtable refs = (IntHashtable)readers2intrefs.get(reader);
- return refs.containsKey(number);
- }
-
- protected boolean isVisited(PRIndirectReference ref) {
- IntHashtable refs = (IntHashtable)visited.get(ref.getReader());
- return refs.containsKey(ref.getNumber());
- }
-
- protected boolean setVisited(PRIndirectReference ref) {
- IntHashtable refs = (IntHashtable)visited.get(ref.getReader());
- return (refs.put(ref.getNumber(), 1) != 0);
- }
-
- protected boolean isPage(PRIndirectReference ref) {
- IntHashtable refs = (IntHashtable)pages2intrefs.get(ref.getReader());
- return refs.containsKey(ref.getNumber());
- }
-
- RandomAccessFileOrArray getReaderFile(PdfReader reader) {
- return file;
- }
-
- /**
- * Sets the bookmarks. The list structure is defined in
- * SimpleBookmark#
.
- * @param outlines the bookmarks or null
to remove any
- */
- public void setOutlines(List outlines) {
- newBookmarks = outlines;
- }
-
- public void openDoc() {
- if (!nd.isOpen())
- nd.open();
- }
-
- protected static final HashMap widgetKeys = new HashMap();
- protected static final HashMap fieldKeys = new HashMap();
- static {
- Integer one = new Integer(1);
- widgetKeys.put(PdfName.SUBTYPE, one);
- widgetKeys.put(PdfName.CONTENTS, one);
- widgetKeys.put(PdfName.RECT, one);
- widgetKeys.put(PdfName.NM, one);
- widgetKeys.put(PdfName.M, one);
- widgetKeys.put(PdfName.F, one);
- widgetKeys.put(PdfName.BS, one);
- widgetKeys.put(PdfName.BORDER, one);
- widgetKeys.put(PdfName.AP, one);
- widgetKeys.put(PdfName.AS, one);
- widgetKeys.put(PdfName.C, one);
- widgetKeys.put(PdfName.A, one);
- widgetKeys.put(PdfName.STRUCTPARENT, one);
- widgetKeys.put(PdfName.OC, one);
- widgetKeys.put(PdfName.H, one);
- widgetKeys.put(PdfName.MK, one);
- widgetKeys.put(PdfName.DA, one);
- widgetKeys.put(PdfName.Q, one);
- fieldKeys.put(PdfName.AA, one);
- fieldKeys.put(PdfName.FT, one);
- fieldKeys.put(PdfName.TU, one);
- fieldKeys.put(PdfName.TM, one);
- fieldKeys.put(PdfName.FF, one);
- fieldKeys.put(PdfName.V, one);
- fieldKeys.put(PdfName.DV, one);
- fieldKeys.put(PdfName.DS, one);
- fieldKeys.put(PdfName.RV, one);
- fieldKeys.put(PdfName.OPT, one);
- fieldKeys.put(PdfName.MAXLEN, one);
- fieldKeys.put(PdfName.TI, one);
- fieldKeys.put(PdfName.I, one);
- fieldKeys.put(PdfName.LOCK, one);
- fieldKeys.put(PdfName.SV, one);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfDashPattern.java pdftk-2.01/java/com/lowagie/text/pdf/PdfDashPattern.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfDashPattern.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfDashPattern.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,150 +0,0 @@
-/*
- * $Id: PdfDashPattern.java,v 1.33 2003/05/02 09:01:18 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * A PdfDashPattern
defines a dash pattern as described in
- * the PDF Reference Manual version 1.3 p 325 (section 8.4.3).
- *
- * @see PdfArray
- */
-
-public class PdfDashPattern extends PdfArray {
-
- // membervariables
-
-/** This is the length of a dash. */
- private float dash = -1;
-
-/** This is the length of a gap. */
- private float gap = -1;
-
-/** This is the phase. */
- private float phase = -1;
-
- // constructors
-
-/**
- * Constructs a new PdfDashPattern
.
- */
-
- public PdfDashPattern() {
- super();
- }
-
-/**
- * Constructs a new PdfDashPattern
.
- */
-
- public PdfDashPattern(float dash) {
- super(new PdfNumber(dash));
- this.dash = dash;
- }
-
-/**
- * Constructs a new PdfDashPattern
.
- */
-
- public PdfDashPattern(float dash, float gap) {
- super(new PdfNumber(dash));
- add(new PdfNumber(gap));
- this.dash = dash;
- this.gap = gap;
- }
-
-/**
- * Constructs a new PdfDashPattern
.
- */
-
- public PdfDashPattern(float dash, float gap, float phase) {
- super(new PdfNumber(dash));
- add(new PdfNumber(gap));
- this.dash = dash;
- this.gap = gap;
- this.phase = phase;
- }
-
- public void add(float n) {
- add(new PdfNumber(n));
- }
-
-/**
- * Returns the PDF representation of this PdfArray
.
- *
- * @return an array of byte
s
- */
-
- public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
- os.write('[');
-
- if (dash >= 0) {
- new PdfNumber(dash).toPdf(writer, os);
- if (gap >= 0) {
- os.write(' ');
- new PdfNumber(gap).toPdf(writer, os);
- }
- }
- os.write(']');
- if (phase >=0) {
- os.write(' ');
- new PdfNumber(phase).toPdf(writer, os);
- }
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfDate.java pdftk-2.01/java/com/lowagie/text/pdf/PdfDate.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfDate.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfDate.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,221 +0,0 @@
-/*
- * $Id: PdfDate.java,v 1.63 2005/09/04 16:20:01 psoares33 Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.text.SimpleDateFormat;
-import java.util.GregorianCalendar;
-import java.util.Calendar;
-import java.util.SimpleTimeZone;
-
-/**
- * PdfDate
is the PDF date object.
- *
- * PDF defines a standard date format. The PDF date format closely follows the format
- * defined by the international standard ASN.1 (Abstract Syntax Notation One, defined
- * in CCITT X.208 or ISO/IEC 8824). A date is a PdfString
of the form:
- *
- * (D: YYYYMMDDHHmmSSOHH'mm')
- *
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 7.2 (page 183-184)
- *
- * @see PdfString
- * @see java.util.GregorianCalendar
- */
-
-public class PdfDate extends PdfString {
-
- // ssteward; static builds of pdftk (Windows, gcc 3.3.1) would
- // omit this class because of its reference by reflection;
- // this treatment ensures that ld will include it
- private static Class c1= java.util.Calendar.class; //gnu.java.locale.Calendar.class;
-
- private static final int dateSpace[] = {Calendar.YEAR, 4, 0, Calendar.MONTH, 2, -1, Calendar.DAY_OF_MONTH, 2, 0,
- Calendar.HOUR_OF_DAY, 2, 0, Calendar.MINUTE, 2, 0, Calendar.SECOND, 2, 0};
-
- // constructors
-
-/**
- * Constructs a PdfDate
-object.
- *
- * @param d the date that has to be turned into a PdfDate
-object
- */
-
- public PdfDate(Calendar d) {
- super();
- StringBuffer date = new StringBuffer("D:");
- date.append(setLength(d.get(Calendar.YEAR), 4));
- date.append(setLength(d.get(Calendar.MONTH) + 1, 2));
- date.append(setLength(d.get(Calendar.DATE), 2));
- date.append(setLength(d.get(Calendar.HOUR_OF_DAY), 2));
- date.append(setLength(d.get(Calendar.MINUTE), 2));
- date.append(setLength(d.get(Calendar.SECOND), 2));
- int timezone = (d.get(Calendar.ZONE_OFFSET) + d.get(Calendar.DST_OFFSET)) / (60 * 60 * 1000);
- if (timezone == 0) {
- date.append("Z");
- }
- else if (timezone < 0) {
- date.append("-");
- timezone = -timezone;
- }
- else {
- date.append("+");
- }
- if (timezone != 0) {
- date.append(setLength(timezone, 2)).append("'");
- int zone = Math.abs((d.get(Calendar.ZONE_OFFSET) + d.get(Calendar.DST_OFFSET)) / (60 * 1000)) - (timezone * 60);
- date.append(setLength(zone, 2)).append("'");
- }
- value = date.toString();
- }
-
-/**
- * Constructs a PdfDate
-object, representing the current day and time.
- */
-
- public PdfDate() {
- this(new GregorianCalendar());
- }
-
-/**
- * Adds a number of leading zeros to a given String
in order to get a String
- * of a certain length.
- *
- * @param i a given number
- * @param length the length of the resulting String
- * @return the resulting String
- */
-
- private String setLength(int i, int length) { // 1.3-1.4 problem fixed by Finn Bock
- StringBuffer tmp = new StringBuffer();
- tmp.append(i);
- while (tmp.length() < length) {
- tmp.insert(0, "0");
- }
- tmp.setLength(length);
- return tmp.toString();
- }
-
- /**
- * Gives the W3C format of the PdfDate.
- * @return a formatted date
- */
- public String getW3CDate() {
- return getW3CDate(value);
- }
-
- /**
- * Gives the W3C format of the PdfDate.
- * @param d
- * @return a formatted date
- */
- public static String getW3CDate(String d) {
- SimpleDateFormat w3c = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
- Calendar c = decode(d);
- return w3c.format(c.getTime());
- }
-
- /**
- * Converts a PDF string representing a date into a Calendar.
- * @param s the PDF string representing a date
- * @return a Calendar
representing the date or null
if the string
- * was not a date
- */
- public static Calendar decode(String s) {
- try {
- if (s.startsWith("D:"))
- s = s.substring(2);
- GregorianCalendar calendar;
- int slen = s.length();
- int idx = s.indexOf('Z');
- if (idx >= 0) {
- slen = idx;
- calendar = new GregorianCalendar(new SimpleTimeZone(0, "ZPDF"));
- }
- else {
- int sign = 1;
- idx = s.indexOf('+');
- if (idx < 0) {
- idx = s.indexOf('-');
- if (idx >= 0)
- sign = -1;
- }
- if (idx < 0)
- calendar = new GregorianCalendar();
- else {
- int offset = Integer.parseInt(s.substring(idx + 1, idx + 3)) * 60;
- if (idx + 5 < s.length())
- offset += Integer.parseInt(s.substring(idx + 4, idx + 6));
- calendar = new GregorianCalendar(new SimpleTimeZone(offset * sign * 60000, "ZPDF"));
- slen = idx;
- }
- }
- calendar.clear();
- idx = 0;
- for (int k = 0; k < dateSpace.length; k += 3) {
- if (idx >= slen)
- break;
- calendar.set(dateSpace[k], Integer.parseInt(s.substring(idx, idx + dateSpace[k + 1])) + dateSpace[k + 2]);
- idx += dateSpace[k + 1];
- }
- return calendar;
- }
- catch (Exception e) {
- return null;
- }
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfDestination.java pdftk-2.01/java/com/lowagie/text/pdf/PdfDestination.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfDestination.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfDestination.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,227 +0,0 @@
-/*
- * $Id: PdfDestination.java,v 1.22 2002/06/20 13:28:22 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * A PdfColor
defines a Color (it's a PdfArray
containing 3 values).
- *
- * @see PdfDictionary
- */
-
-public class PdfDestination extends PdfArray {
-
- // public static final member-variables
-
-/** This is a possible destination type */
- public static final int XYZ = 0;
-
-/** This is a possible destination type */
- public static final int FIT = 1;
-
-/** This is a possible destination type */
- public static final int FITH = 2;
-
-/** This is a possible destination type */
- public static final int FITV = 3;
-
-/** This is a possible destination type */
- public static final int FITR = 4;
-
-/** This is a possible destination type */
- public static final int FITB = 5;
-
-/** This is a possible destination type */
- public static final int FITBH = 6;
-
-/** This is a possible destination type */
- public static final int FITBV = 7;
-
- // member variables
-
-/** Is the indirect reference to a page already added? */
- private boolean status = false;
-
- // constructors
-
-/**
- * Constructs a new PdfDestination
.
- *
- * If type equals FITB , the bounding box of a page
- * will fit the window of the Reader. Otherwise the type will be set to
- * FIT so that the entire page will fit to the window.
- *
- * @param type The destination type
- */
-
- public PdfDestination(int type) {
- super();
- if (type == FITB) {
- add(PdfName.FITB);
- }
- else {
- add(PdfName.FIT);
- }
- }
-
-/**
- * Constructs a new PdfDestination
.
- *
- * If type equals FITBH / FITBV ,
- * the width / height of the bounding box of a page will fit the window
- * of the Reader. The parameter will specify the y / x coordinate of the
- * top / left edge of the window. If the type equals FITH
- * or FITV the width / height of the entire page will fit
- * the window and the parameter will specify the y / x coordinate of the
- * top / left edge. In all other cases the type will be set to FITH .
- *
- * @param type the destination type
- * @param parameter a parameter to combined with the destination type
- */
-
- public PdfDestination(int type, float parameter) {
- super(new PdfNumber(parameter));
- switch(type) {
- default:
- addFirst(PdfName.FITH);
- break;
- case FITV:
- addFirst(PdfName.FITV);
- break;
- case FITBH:
- addFirst(PdfName.FITBH);
- break;
- case FITBV:
- addFirst(PdfName.FITBV);
- }
- }
-
-/** Constructs a new PdfDestination
.
- *
- * Display the page, with the coordinates (left, top) positioned
- * at the top-left corner of the window and the contents of the page magnified
- * by the factor zoom. A negative value for any of the parameters left or top, or a
- * zoom value of 0 specifies that the current value of that parameter is to be retained unchanged.
- * @param type must be a PdfDestination.XYZ
- * @param left the left value. Negative to place a null
- * @param top the top value. Negative to place a null
- * @param zoom The zoom factor. A value of 0 keeps the current value
- */
-
- public PdfDestination(int type, float left, float top, float zoom) {
- super(PdfName.XYZ);
- if (left < 0)
- add(PdfNull.PDFNULL);
- else
- add(new PdfNumber(left));
- if (top < 0)
- add(PdfNull.PDFNULL);
- else
- add(new PdfNumber(top));
- add(new PdfNumber(zoom));
- }
-
-/** Constructs a new PdfDestination
.
- *
- * Display the page, with its contents magnified just enough
- * to fit the rectangle specified by the coordinates left, bottom, right, and top
- * entirely within the window both horizontally and vertically. If the required
- * horizontal and vertical magnification factors are different, use the smaller of
- * the two, centering the rectangle within the window in the other dimension.
- *
- * @param type must be PdfDestination.FITR
- * @param left a parameter
- * @param bottom a parameter
- * @param right a parameter
- * @param top a parameter
- * @since iText0.38
- */
-
- public PdfDestination(int type, float left, float bottom, float right, float top) {
- super(PdfName.FITR);
- add(new PdfNumber(left));
- add(new PdfNumber(bottom));
- add(new PdfNumber(right));
- add(new PdfNumber(top));
- }
-
- // methods
-
-/**
- * Checks if an indirect reference to a page has been added.
- *
- * @return true
or false
- */
-
- public boolean hasPage() {
- return status;
- }
-
-/** Adds the indirect reference of the destination page.
- *
- * @param page an indirect reference
- * @return true if the page reference was added
- */
-
- public boolean addPage(PdfIndirectReference page) {
- if (!status) {
- addFirst(page);
- status = true;
- return true;
- }
- return false;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfDictionary.java pdftk-2.01/java/com/lowagie/text/pdf/PdfDictionary.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfDictionary.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfDictionary.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,327 +0,0 @@
-/*
- * $Id: PdfDictionary.java,v 1.27 2002/07/09 11:28:22 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Iterator;
-import java.util.HashMap;
-import java.util.Set;
-
-/**
- * PdfDictionary
is the Pdf dictionary object.
- *
- * A dictionary is an associative table containing pairs of objects. The first element
- * of each pair is called the key and the second element is called the value .
- * Unlike dictionaries in the PostScript language, a key must be a PdfName
.
- * A value can be any kind of PdfObject
, including a dictionary. A dictionary is
- * generally used to collect and tie together the attributes of a complex object, with each
- * key-value pair specifying the name and value of an attribute.
- * A dictionary is represented by two left angle brackets (<<), followed by a sequence of
- * key-value pairs, followed by two right angle brackets (>>).
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 4.7 (page 40-41).
- *
- *
- * @see PdfObject
- * @see PdfName
- * @see BadPdfFormatException
- */
-
-public class PdfDictionary extends PdfObject {
-
- // static membervariables (types of dictionary's)
-
-/** This is a possible type of dictionary */
- public static final PdfName FONT = PdfName.FONT;
-
-/** This is a possible type of dictionary */
- public static final PdfName OUTLINES = PdfName.OUTLINES;
-
-/** This is a possible type of dictionary */
- public static final PdfName PAGE = PdfName.PAGE;
-
-/** This is a possible type of dictionary */
- public static final PdfName PAGES = PdfName.PAGES;
-
-/** This is a possible type of dictionary */
- public static final PdfName CATALOG = PdfName.CATALOG;
-
- // membervariables
-
-/** This is the type of this dictionary */
- private PdfName dictionaryType = null;
-
-/** This is the hashmap that contains all the values and keys of the dictionary */
- protected HashMap hashMap;
-
- // constructors
-
-/**
- * Constructs an empty PdfDictionary
-object.
- */
-
- public PdfDictionary() {
- super(DICTIONARY);
- hashMap = new HashMap();
- }
-
-/**
- * Constructs a PdfDictionary
-object of a certain type.
- *
- * @param type a PdfName
- */
-
- public PdfDictionary(PdfName type) {
- this();
- dictionaryType = type;
- put(PdfName.TYPE, dictionaryType);
- }
-
- // methods overriding some methods in PdfObject
-
-/**
- * Returns the PDF representation of this PdfDictionary
.
- *
- * @return an array of byte
- */
-
- public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
- os.write('\n'); // ssteward
- os.write('<');
- os.write('<');
-
- // loop over all the object-pairs in the HashMap
- PdfName key;
- PdfObject value;
- //int type = 0; // ssteward
- for (Iterator i = hashMap.keySet().iterator(); i.hasNext(); ) {
- os.write('\n');
- key = (PdfName) i.next();
- value = (PdfObject) hashMap.get(key);
- key.toPdf(writer, os);
- // ssteward: I liked the old syntax formatting
- //type = value.type();
- //if (type != PdfObject.ARRAY && type != PdfObject.DICTIONARY && type != PdfObject.NAME && type != PdfObject.STRING)
- os.write(' ');
- value.toPdf(writer, os);
- }
- os.write('\n'); // ssteward
- os.write('>');
- os.write('>');
- }
-
- // methods concerning the HashMap member value
-
-/**
- * Adds a PdfObject
and its key to the PdfDictionary
.
- *
- * @param key key of the entry (a PdfName
)
- * @param value value of the entry (a PdfObject
)
- * @return the previous
PdfObject
corresponding with the key
- */
-
- public void put(PdfName key, PdfObject value) {
- hashMap.put(key, value);
- }
-
-/**
- * Adds a PdfObject
and its key to the PdfDictionary
.
- * If the value is null it does nothing.
- *
- * @param key key of the entry (a PdfName
)
- * @param value value of the entry (a PdfObject
)
- * @return the previous
PdfObject
corresponding with the key
- */
- public void putEx(PdfName key, PdfObject value) {
- if (value == null)
- return;
- hashMap.put(key, value);
- }
-
-/**
- * Adds a PdfObject
and its key to the PdfDictionary
.
- * If the value is null the key is deleted.
- *
- * @param key key of the entry (a PdfName
)
- * @param value value of the entry (a PdfObject
)
- * @return the previous
PdfObject
corresponding with the key
- */
- public void putDel(PdfName key, PdfObject value) {
- if (value == null) {
- hashMap.remove(key);
- return;
- }
- hashMap.put(key, value);
- }
-
-/**
- * Removes a PdfObject
and its key from the PdfDictionary
.
- *
- * @param key key of the entry (a PdfName
)
- * @return the previous
PdfObject
corresponding with the key
- */
-
- public void remove(PdfName key) {
- hashMap.remove(key);
- }
-
-/**
- * Gets a PdfObject
with a certain key from the PdfDictionary
.
- *
- * @param key key of the entry (a PdfName
)
- * @return the previous
PdfObject
corresponding with the key
- */
-
- public PdfObject get(PdfName key) {
- return (PdfObject) hashMap.get(key);
- }
-
- // methods concerning the type of Dictionary
-
-/**
- * Checks if a PdfDictionary
is of a certain type.
- *
- * @param type a type of dictionary
- * @return true
of false
- *
- * @deprecated
- */
-
- public boolean isDictionaryType(PdfName type) {
- return dictionaryType.compareTo(type) == 0;
- }
-
-/**
- * Checks if a Dictionary
is of the type FONT.
- *
- * @return true
if it is, false
if it isn't.
- */
-
- public boolean isFont() {
- return dictionaryType.compareTo(FONT) == 0;
- }
-
-/**
- * Checks if a Dictionary
is of the type PAGE.
- *
- * @return true
if it is, false
if it isn't.
- */
-
- public boolean isPage() {
- return dictionaryType.compareTo(PAGE) == 0;
- }
-
-/**
- * Checks if a Dictionary
is of the type PAGES.
- *
- * @return true
if it is, false
if it isn't.
- */
-
- public boolean isPages() {
- return dictionaryType.compareTo(PAGES) == 0;
- }
-
-/**
- * Checks if a Dictionary
is of the type CATALOG.
- *
- * @return true
if it is, false
if it isn't.
- */
-
- public boolean isCatalog() {
- return dictionaryType.compareTo(CATALOG) == 0;
- }
-
-/**
- * Checks if a Dictionary
is of the type OUTLINES.
- *
- * @return true
if it is, false
if it isn't.
- */
-
- public boolean isOutlineTree() {
- return dictionaryType.compareTo(OUTLINES) == 0;
- }
-
- public void merge(PdfDictionary other) {
- hashMap.putAll(other.hashMap);
- }
-
- public void mergeDifferent(PdfDictionary other) {
- for (Iterator i = other.hashMap.keySet().iterator(); i.hasNext();) {
- Object key = i.next();
- if (!hashMap.containsKey(key)) {
- hashMap.put(key, other.hashMap.get(key));
- }
- }
- }
-
- public Set getKeys() {
- return hashMap.keySet();
- }
-
- public void putAll(PdfDictionary dic) {
- hashMap.putAll(dic.hashMap);
- }
-
- public int size() {
- return hashMap.size();
- }
-
- public boolean contains(PdfName key) {
- return hashMap.containsKey(key);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfDocument.java pdftk-2.01/java/com/lowagie/text/pdf/PdfDocument.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfDocument.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfDocument.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,3002 +0,0 @@
-/*
- * $Name: $
- * $Id: PdfDocument.java,v 1.209 2005/09/02 11:32:59 blowagie Exp $
- *
- * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.awt.Color;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.ListIterator;
-import java.util.TreeMap;
-
-import com.lowagie.text.Anchor;
-import com.lowagie.text.Annotation;
-import com.lowagie.text.BadElementException;
-// import com.lowagie.text.Cell; ssteward: dropped in 1.44
-import com.lowagie.text.Chunk;
-import com.lowagie.text.DocListener;
-import com.lowagie.text.Document;
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.Element;
-import com.lowagie.text.ExceptionConverter;
-// import com.lowagie.text.Graphic; ssteward: dropped in 1.44
-// import com.lowagie.text.HeaderFooter; ssteward: dropped in 1.44
-// import com.lowagie.text.Image; ssteward: dropped in 1.44
-import com.lowagie.text.List;
-import com.lowagie.text.ListItem;
-import com.lowagie.text.Meta;
-import com.lowagie.text.Paragraph;
-import com.lowagie.text.Phrase;
-import com.lowagie.text.Rectangle;
-// import com.lowagie.text.Section; ssteward: dropped in 1.44
-// import com.lowagie.text.SimpleTable; ssteward: dropped in 1.44
-import com.lowagie.text.StringCompare;
-// import com.lowagie.text.Table; ssteward: dropped in 1.44
-// import com.lowagie.text.Watermark; ssteward: dropped in 1.44
-import com.lowagie.text.xml.xmp.XmpWriter;
-
-/**
- * PdfDocument
is the class that is used by PdfWriter
- * to translate a Document
into a PDF with different pages.
- *
- * A PdfDocument
always listens to a Document
- * and adds the Pdf representation of every Element
that is
- * added to the Document
.
- *
- * @see com.lowagie.text.Document
- * @see com.lowagie.text.DocListener
- * @see PdfWriter
- */
-
-class PdfDocument extends Document implements DocListener {
-
- /**
- * PdfInfo
is the PDF InfoDictionary.
- *
- * A document's trailer may contain a reference to an Info dictionary that provides information
- * about the document. This optional dictionary may contain one or more keys, whose values
- * should be strings.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 6.10 (page 120-121)
- */
-
- public static class PdfInfo extends PdfDictionary {
-
- // constructors
-
- /**
- * Construct a PdfInfo
-object.
- */
-
- PdfInfo() {
- super();
- addProducer();
- addCreationDate();
- }
-
- /**
- * Constructs a PdfInfo
-object.
- *
- * @param author name of the author of the document
- * @param title title of the document
- * @param subject subject of the document
- */
-
- PdfInfo(String author, String title, String subject) {
- this();
- addTitle(title);
- addSubject(subject);
- addAuthor(author);
- }
-
- /**
- * Adds the title of the document.
- *
- * @param title the title of the document
- */
-
- void addTitle(String title) {
- put(PdfName.TITLE, new PdfString(title/*ssteward , PdfObject.TEXT_UNICODE*/));
- }
-
- /**
- * Adds the subject to the document.
- *
- * @param subject the subject of the document
- */
-
- void addSubject(String subject) {
- put(PdfName.SUBJECT, new PdfString(subject/*ssteward, PdfObject.TEXT_UNICODE*/));
- }
-
- /**
- * Adds some keywords to the document.
- *
- * @param keywords the keywords of the document
- */
-
- void addKeywords(String keywords) {
- put(PdfName.KEYWORDS, new PdfString(keywords/*ssteward, PdfObject.TEXT_UNICODE*/));
- }
-
- /**
- * Adds the name of the author to the document.
- *
- * @param author the name of the author
- */
-
- void addAuthor(String author) {
- put(PdfName.AUTHOR, new PdfString(author/*ssteward, PdfObject.TEXT_UNICODE*/));
- }
-
- /**
- * Adds the name of the creator to the document.
- *
- * @param creator the name of the creator
- */
-
- void addCreator(String creator) {
- put(PdfName.CREATOR, new PdfString(creator/*, PdfObject.TEXT_UNICODE ssteward*/));
- }
-
- /**
- * Adds the name of the producer to the document.
- */
-
- void addProducer() {
- // This line may only be changed by Bruno Lowagie or Paulo Soares
- put(PdfName.PRODUCER, new PdfString(getVersion()));
- // Do not edit the line above!
- }
-
- /**
- * Adds the date of creation to the document.
- */
-
- void addCreationDate() {
- PdfString date = new PdfDate();
- put(PdfName.CREATIONDATE, date);
- put(PdfName.MODDATE, date);
- }
-
- void addkey(String key, String value) {
- if (key.equals("Producer") || key.equals("CreationDate"))
- return;
- put(new PdfName(key), new PdfString(value/*ssteward, PdfObject.TEXT_UNICODE*/));
- }
- }
-
- /**
- * PdfCatalog
is the PDF Catalog-object.
- *
- * The Catalog is a dictionary that is the root node of the document. It contains a reference
- * to the tree of pages contained in the document, a reference to the tree of objects representing
- * the document's outline, a reference to the document's article threads, and the list of named
- * destinations. In addition, the Catalog indicates whether the document's outline or thumbnail
- * page images should be displayed automatically when the document is viewed and wether some location
- * other than the first page should be shown when the document is opened.
- * In this class however, only the reference to the tree of pages is implemented.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 6.2 (page 67-71)
- */
-
- static class PdfCatalog extends PdfDictionary {
-
- PdfWriter writer;
- // constructors
-
- /**
- * Constructs a PdfCatalog
.
- *
- * @param pages an indirect reference to the root of the document's Pages tree.
- * @param writer the writer the catalog applies to
- */
-
- PdfCatalog(PdfIndirectReference pages, PdfWriter writer) {
- super(CATALOG);
- this.writer = writer;
- put(PdfName.PAGES, pages);
- }
-
- /**
- * Constructs a PdfCatalog
.
- *
- * @param pages an indirect reference to the root of the document's Pages tree.
- * @param outlines an indirect reference to the outline tree.
- * @param writer the writer the catalog applies to
- */
-
- PdfCatalog(PdfIndirectReference pages, PdfIndirectReference outlines, PdfWriter writer) {
- super(CATALOG);
- this.writer = writer;
- put(PdfName.PAGES, pages);
- put(PdfName.PAGEMODE, PdfName.USEOUTLINES);
- put(PdfName.OUTLINES, outlines);
- }
-
- /**
- * Adds the names of the named destinations to the catalog.
- * @param localDestinations the local destinations
- * @param documentJavaScript the javascript used in the document
- * @param writer the writer the catalog applies to
- */
- void addNames(TreeMap localDestinations, ArrayList documentJavaScript, PdfWriter writer) {
- if (localDestinations.size() == 0 && documentJavaScript.size() == 0)
- return;
- try {
- PdfDictionary names = new PdfDictionary();
- if (localDestinations.size() > 0) {
- PdfArray ar = new PdfArray();
- for (Iterator i = localDestinations.keySet().iterator(); i.hasNext();) {
- String name = (String)i.next();
- Object obj[] = (Object[])localDestinations.get(name);
- PdfIndirectReference ref = (PdfIndirectReference)obj[1];
- ar.add(new PdfString(name));
- ar.add(ref);
- }
- PdfDictionary dests = new PdfDictionary();
- dests.put(PdfName.NAMES, ar);
- names.put(PdfName.DESTS, writer.addToBody(dests).getIndirectReference());
- }
- if (documentJavaScript.size() > 0) {
- String s[] = new String[documentJavaScript.size()];
- for (int k = 0; k < s.length; ++k)
- s[k] = Integer.toHexString(k);
- Arrays.sort(s, new StringCompare());
- PdfArray ar = new PdfArray();
- for (int k = 0; k < s.length; ++k) {
- ar.add(new PdfString(s[k]));
- ar.add((PdfIndirectReference)documentJavaScript.get(k));
- }
- PdfDictionary js = new PdfDictionary();
- js.put(PdfName.NAMES, ar);
- names.put(PdfName.JAVASCRIPT, writer.addToBody(js).getIndirectReference());
- }
- put(PdfName.NAMES, writer.addToBody(names).getIndirectReference());
- }
- catch (IOException e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /** Sets the viewer preferences as the sum of several constants.
- * @param preferences the viewer preferences
- * @see PdfWriter#setViewerPreferences
- */
-
- void setViewerPreferences(int preferences) {
- PdfReader.setViewerPreferences(preferences, this);
- }
-
- void setOpenAction(PdfAction action) {
- put(PdfName.OPENACTION, action);
- }
-
-
- /** Sets the document level additional actions.
- * @param actions dictionary of actions
- */
- void setAdditionalActions(PdfDictionary actions) {
- try {
- put(PdfName.AA, writer.addToBody(actions).getIndirectReference());
- } catch (Exception e) {
- new ExceptionConverter(e);
- }
- }
-
-
- void setPageLabels(PdfPageLabels pageLabels) {
- put(PdfName.PAGELABELS, pageLabels.getDictionary());
- }
-
- void setAcroForm(PdfObject fields) {
- put(PdfName.ACROFORM, fields);
- }
- }
-
- // membervariables
- private PdfIndirectReference thumb;
-
- /** The characters to be applied the hanging ponctuation. */
- static final String hangingPunctuation = ".,;:'";
-
- /** The PdfWriter
. */
- private PdfWriter writer;
-
- /** some meta information about the Document. */
- private PdfInfo info = new PdfInfo();
-
- /** Signals that OnOpenDocument should be called. */
- private boolean firstPageEvent = true;
-
- /** Signals that onParagraph is valid. */
- private boolean isParagraph = true;
-
- // Horizontal line
-
- /** The line that is currently being written. */
- private PdfLine line = null;
-
- /** This represents the current indentation of the PDF Elements on the left side. */
- private float indentLeft = 0;
-
- /** This represents the current indentation of the PDF Elements on the right side. */
- private float indentRight = 0;
-
- /** This represents the current indentation of the PDF Elements on the left side. */
- private float listIndentLeft = 0;
-
- /** This represents the current alignment of the PDF Elements. */
- private int alignment = Element.ALIGN_LEFT;
-
- // Vertical lines
-
- /** This is the PdfContentByte object, containing the text. */
- private PdfContentByte text;
-
- /** This is the PdfContentByte object, containing the borders and other Graphics. */
- private PdfContentByte graphics;
-
- /** The lines that are written until now. */
- private ArrayList lines = new ArrayList();
-
- /** This represents the leading of the lines. */
- private float leading = 0;
-
- /** This is the current height of the document. */
- private float currentHeight = 0;
-
- /** This represents the current indentation of the PDF Elements on the top side. */
- private float indentTop = 0;
-
- /** This represents the current indentation of the PDF Elements on the bottom side. */
- private float indentBottom = 0;
-
- /** This checks if the page is empty. */
- private boolean pageEmpty = true;
-
- private int textEmptySize;
- // resources
-
- /** This is the size of the next page. */
- protected Rectangle nextPageSize = null;
-
- /** This is the size of the several boxes of the current Page. */
- protected HashMap thisBoxSize = new HashMap();
-
- /** This is the size of the several boxes that will be used in
- * the next page. */
- protected HashMap boxSize = new HashMap();
-
- /** This are the page resources of the current Page. */
- protected PageResources pageResources;
-
- // images
-
- /** This is the image that could not be shown on a previous page. */
- //private Image imageWait = null; ssteward: dropped in 1.44
-
- /** This is the position where the image ends. */
- private float imageEnd = -1;
-
- /** This is the indentation caused by an image on the left. */
- private float imageIndentLeft = 0;
-
- /** This is the indentation caused by an image on the right. */
- private float imageIndentRight = 0;
-
- // annotations and outlines
-
- /** This is the array containing the references to the annotations. */
- private ArrayList annotations;
-
- /** This is an array containg references to some delayed annotations. */
- private ArrayList delayedAnnotations = new ArrayList();
-
- /** This is the AcroForm object. */
- PdfAcroForm acroForm;
-
- /** This is the root outline of the document. */
- private PdfOutline rootOutline;
-
- /** This is the current PdfOutline
in the hierarchy of outlines. */
- private PdfOutline currentOutline;
-
- /** The current active PdfAction
when processing an Anchor
. */
- private PdfAction currentAction = null;
-
- /**
- * Stores the destinations keyed by name. Value is
- * Object[]{PdfAction,PdfIndirectReference,PdfDestintion}
.
- */
- private TreeMap localDestinations = new TreeMap(new StringCompare());
-
- private ArrayList documentJavaScript = new ArrayList();
-
- /** these are the viewerpreferences of the document */
- private int viewerPreferences = 0;
-
- private String openActionName;
- private PdfAction openActionAction;
- private PdfDictionary additionalActions;
- private PdfPageLabels pageLabels;
-
- //add by Jin-Hsia Yang
- private boolean isNewpage = false;
-
- private float paraIndent = 0;
- //end add by Jin-Hsia Yang
-
- /** margin in x direction starting from the left. Will be valid in the next page */
- protected float nextMarginLeft;
-
- /** margin in x direction starting from the right. Will be valid in the next page */
- protected float nextMarginRight;
-
- /** margin in y direction starting from the top. Will be valid in the next page */
- protected float nextMarginTop;
-
- /** margin in y direction starting from the bottom. Will be valid in the next page */
- protected float nextMarginBottom;
-
-/** The duration of the page */
- protected int duration=-1; // negative values will indicate no duration
-
-/** The page transition */
- protected PdfTransition transition=null;
-
- protected PdfDictionary pageAA = null;
-
- /** Holds value of property strictImageSequence. */
- private boolean strictImageSequence = false;
-
- /** Holds the type of the last element, that has been added to the document. */
- private int lastElementType = -1;
-
- protected int markPoint;
-
- // constructors
-
- /**
- * Constructs a new PDF document.
- * @throws DocumentException on error
- */
-
- public PdfDocument() throws DocumentException {
- super();
- addProducer();
- addCreationDate();
- }
-
- // listener methods
-
- /**
- * Adds a PdfWriter
to the PdfDocument
.
- *
- * @param writer the PdfWriter
that writes everything
- * what is added to this document to an outputstream.
- * @throws DocumentException on error
- */
-
- public void addWriter(PdfWriter writer) throws DocumentException {
- if (this.writer == null) {
- this.writer = writer;
- acroForm = new PdfAcroForm(writer);
- return;
- }
- throw new DocumentException("You can only add a writer to a PdfDocument once.");
- }
-
- /**
- * Sets the pagesize.
- *
- * @param pageSize the new pagesize
- * @return true
if the page size was set
- */
-
- public boolean setPageSize(Rectangle pageSize) {
- if (writer != null && writer.isPaused()) {
- return false;
- }
- nextPageSize = new Rectangle(pageSize);
- return true;
- }
-
- /**
- * Changes the header of this document.
- *
- * @param header the new header
- */
- /* ssteward: dropped in 1.44
- public void setHeader(HeaderFooter header) {
- if (writer != null && writer.isPaused()) {
- return;
- }
- super.setHeader(header);
- }
- */
-
- /**
- * Resets the header of this document.
- */
- /* ssteward: dropped in 1.44
- public void resetHeader() {
- if (writer != null && writer.isPaused()) {
- return;
- }
- super.resetHeader();
- }
- */
- /**
- * Changes the footer of this document.
- *
- * @param footer the new footer
- */
- /* ssteward: dropped in 1.44
- public void setFooter(HeaderFooter footer) {
- if (writer != null && writer.isPaused()) {
- return;
- }
- super.setFooter(footer);
- }
- */
- /**
- * Resets the footer of this document.
- */
- /* ssteward: dropped in 1.44
- public void resetFooter() {
- if (writer != null && writer.isPaused()) {
- return;
- }
- super.resetFooter();
- }
- */
- /**
- * Sets the page number to 0.
- */
-
- public void resetPageCount() {
- if (writer != null && writer.isPaused()) {
- return;
- }
- super.resetPageCount();
- }
-
- /**
- * Sets the page number.
- *
- * @param pageN the new page number
- */
-
- public void setPageCount(int pageN) {
- if (writer != null && writer.isPaused()) {
- return;
- }
- super.setPageCount(pageN);
- }
-
- /**
- * Sets the Watermark
.
- *
- * @param watermark the watermark to add
- * @return true
if the element was added, false
if not.
- */
- /* ssteward: dropped in 1.44
- public boolean add(Watermark watermark) {
- if (writer != null && writer.isPaused()) {
- return false;
- }
- this.watermark = watermark;
- return true;
- }
- */
-
- /**
- * Removes the Watermark
.
- */
- /* ssteward: dropped in 1.44
- public void removeWatermark() {
- if (writer != null && writer.isPaused()) {
- return;
- }
- this.watermark = null;
- }
- */
-
- /**
- * Sets the margins.
- *
- * @param marginLeft the margin on the left
- * @param marginRight the margin on the right
- * @param marginTop the margin on the top
- * @param marginBottom the margin on the bottom
- * @return a boolean
- */
-
- public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom) {
- if (writer != null && writer.isPaused()) {
- return false;
- }
- nextMarginLeft = marginLeft;
- nextMarginRight = marginRight;
- nextMarginTop = marginTop;
- nextMarginBottom = marginBottom;
- return true;
- }
-
- protected PdfArray rotateAnnotations() {
- PdfArray array = new PdfArray();
- int rotation = pageSize.getRotation() % 360;
- int currentPage = writer.getCurrentPageNumber();
- for (int k = 0; k < annotations.size(); ++k) {
- PdfAnnotation dic = (PdfAnnotation)annotations.get(k);
- int page = dic.getPlaceInPage();
- if (page > currentPage) {
- delayedAnnotations.add(dic);
- continue;
- }
- if (dic.isForm()) {
- if (!dic.isUsed()) {
- HashMap templates = dic.getTemplates();
- if (templates != null)
- acroForm.addFieldTemplates(templates);
- }
- PdfFormField field = (PdfFormField)dic;
- if (field.getParent() == null)
- acroForm.addDocumentField(field.getIndirectReference());
- }
- if (dic.isAnnotation()) {
- array.add(dic.getIndirectReference());
- if (!dic.isUsed()) {
- PdfRectangle rect = (PdfRectangle)dic.get(PdfName.RECT);
- if (rect != null) {
- switch (rotation) {
- case 90:
- dic.put(PdfName.RECT, new PdfRectangle(
- pageSize.top() - rect.bottom(),
- rect.left(),
- pageSize.top() - rect.top(),
- rect.right()));
- break;
- case 180:
- dic.put(PdfName.RECT, new PdfRectangle(
- pageSize.right() - rect.left(),
- pageSize.top() - rect.bottom(),
- pageSize.right() - rect.right(),
- pageSize.top() - rect.top()));
- break;
- case 270:
- dic.put(PdfName.RECT, new PdfRectangle(
- rect.bottom(),
- pageSize.right() - rect.left(),
- rect.top(),
- pageSize.right() - rect.right()));
- break;
- }
- }
- }
- }
- if (!dic.isUsed()) {
- dic.setUsed();
- try {
- writer.addToBody(dic, dic.getIndirectReference());
- }
- catch (IOException e) {
- throw new ExceptionConverter(e);
- }
- }
- }
- return array;
- }
-
- /**
- * Makes a new page and sends it to the PdfWriter
.
- *
- * @return a boolean
- * @throws DocumentException on error
- */
-
- public boolean newPage() throws DocumentException {
- lastElementType = -1;
- //add by Jin-Hsia Yang
- isNewpage = true;
- //end add by Jin-Hsia Yang
- if (writer.getDirectContent().size() == 0 && writer.getDirectContentUnder().size() == 0 && (pageEmpty || (writer != null && writer.isPaused()))) {
- return false;
- }
- PdfPageEvent pageEvent = writer.getPageEvent();
- if (pageEvent != null)
- pageEvent.onEndPage(writer, this);
-
- //Added to inform any listeners that we are moving to a new page (added by David Freels)
- super.newPage();
-
- // the following 2 lines were added by Pelikan Stephan
- imageIndentLeft = 0;
- imageIndentRight = 0;
-
- // we flush the arraylist with recently written lines
- flushLines();
- // we assemble the resources of this pages
- pageResources.addDefaultColorDiff(writer.getDefaultColorspace());
- PdfDictionary resources = pageResources.getResources();
- // we make a new page and add it to the document
- if (writer.getPDFXConformance() != PdfWriter.PDFXNONE) {
- if (thisBoxSize.containsKey("art") && thisBoxSize.containsKey("trim"))
- throw new PdfXConformanceException("Only one of ArtBox or TrimBox can exist in the page.");
- if (!thisBoxSize.containsKey("art") && !thisBoxSize.containsKey("trim")) {
- if (thisBoxSize.containsKey("crop"))
- thisBoxSize.put("trim", thisBoxSize.get("crop"));
- else
- thisBoxSize.put("trim", new PdfRectangle(pageSize, pageSize.getRotation()));
- }
- }
- PdfPage page;
- int rotation = pageSize.getRotation();
- page = new PdfPage(new PdfRectangle(pageSize, rotation), thisBoxSize, resources, rotation);
- if (writer.isTagged())
- page.put(PdfName.STRUCTPARENTS, new PdfNumber(writer.getCurrentPageNumber() - 1));
- // we add the transitions
- if (this.transition!=null) {
- page.put(PdfName.TRANS, this.transition.getTransitionDictionary());
- transition = null;
- }
- if (this.duration>0) {
- page.put(PdfName.DUR,new PdfNumber(this.duration));
- duration = 0;
- }
- // we add the page object additional actions
- if (pageAA != null) {
- try {
- page.put(PdfName.AA, writer.addToBody(pageAA).getIndirectReference());
- }
- catch (IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- pageAA = null;
- }
- // we check if the userunit is defined
- if (writer.getUserunit() > 0f) {
- page.put(PdfName.USERUNIT, new PdfNumber(writer.getUserunit()));
- }
- // we add the annotations
- if (annotations.size() > 0) {
- PdfArray array = rotateAnnotations();
- if (array.size() != 0)
- page.put(PdfName.ANNOTS, array);
- }
- // we add the thumbs
- if (thumb != null) {
- page.put(PdfName.THUMB, thumb);
- thumb = null;
- }
- if (!open || close) {
- throw new PdfException("The document isn't open.");
- }
- if (text.size() > textEmptySize)
- text.endText();
- else
- text = null;
- writer.add(page, new PdfContents(writer.getDirectContentUnder(), graphics, text, writer.getDirectContent(), pageSize));
- // we initialize the new page
- initPage();
-
- //add by Jin-Hsia Yang
- isNewpage = false;
- //end add by Jin-Hsia Yang
-
- return true;
- }
-
- // methods to open and close a document
-
- /**
- * Opens the document.
- *
- * You have to open the document before you can begin to add content
- * to the body of the document.
- */
-
- public void open() {
- if (!open) {
- super.open();
- writer.open();
- rootOutline = new PdfOutline(writer);
- currentOutline = rootOutline;
- }
- try {
- initPage();
- }
- catch(DocumentException de) {
- throw new ExceptionConverter(de);
- }
- }
-
- void outlineTree(PdfOutline outline) throws IOException {
- outline.setIndirectReference(writer.getPdfIndirectReference());
- if (outline.parent() != null)
- outline.put(PdfName.PARENT, outline.parent().indirectReference());
- ArrayList kids = outline.getKids();
- int size = kids.size();
- for (int k = 0; k < size; ++k)
- outlineTree((PdfOutline)kids.get(k));
- for (int k = 0; k < size; ++k) {
- if (k > 0)
- ((PdfOutline)kids.get(k)).put(PdfName.PREV, ((PdfOutline)kids.get(k - 1)).indirectReference());
- if (k < size - 1)
- ((PdfOutline)kids.get(k)).put(PdfName.NEXT, ((PdfOutline)kids.get(k + 1)).indirectReference());
- }
- if (size > 0) {
- outline.put(PdfName.FIRST, ((PdfOutline)kids.get(0)).indirectReference());
- outline.put(PdfName.LAST, ((PdfOutline)kids.get(size - 1)).indirectReference());
- }
- for (int k = 0; k < size; ++k) {
- PdfOutline kid = (PdfOutline)kids.get(k);
- writer.addToBody(kid, kid.indirectReference());
- }
- }
-
- void writeOutlines() throws IOException {
- if (rootOutline.getKids().size() == 0)
- return;
- outlineTree(rootOutline);
- writer.addToBody(rootOutline, rootOutline.indirectReference());
- }
-
- void traverseOutlineCount(PdfOutline outline) {
- ArrayList kids = outline.getKids();
- PdfOutline parent = outline.parent();
- if (kids.size() == 0) {
- if (parent != null) {
- parent.setCount(parent.getCount() + 1);
- }
- }
- else {
- for (int k = 0; k < kids.size(); ++k) {
- traverseOutlineCount((PdfOutline)kids.get(k));
- }
- if (parent != null) {
- if (outline.isOpen()) {
- parent.setCount(outline.getCount() + parent.getCount() + 1);
- }
- else {
- parent.setCount(parent.getCount() + 1);
- outline.setCount(-outline.getCount());
- }
- }
- }
- }
-
- void calculateOutlineCount() {
- if (rootOutline.getKids().size() == 0)
- return;
- traverseOutlineCount(rootOutline);
- }
- /**
- * Closes the document.
- *
- * Once all the content has been written in the body, you have to close
- * the body. After that nothing can be written to the body anymore.
- */
-
- public void close() {
- if (close) {
- return;
- }
- try {
- boolean wasImage = false; // (imageWait != null); ssteward: dropped in 1.44
- newPage();
- if ( false || wasImage) newPage(); // imageWait != null ssteward: dropped in 1.44
- if (annotations.size() > 0)
- throw new RuntimeException(annotations.size() + " annotations had invalid placement pages.");
- PdfPageEvent pageEvent = writer.getPageEvent();
- if (pageEvent != null)
- pageEvent.onCloseDocument(writer, this);
- super.close();
-
- writer.addLocalDestinations(localDestinations);
- calculateOutlineCount();
- writeOutlines();
- }
- catch(Exception e) {
- throw new ExceptionConverter(e);
- }
-
- writer.close();
- }
-
- PageResources getPageResources() {
- return pageResources;
- }
-
- /** Adds a PdfPTable
to the document.
- * @param ptable the PdfPTable
to be added to the document.
- * @throws DocumentException on error
- */
- /* ssteward: dropped in 1.44
- void addPTable(PdfPTable ptable) throws DocumentException {
- ColumnText ct = new ColumnText(writer.getDirectContent());
- if (currentHeight > 0) {
- Paragraph p = new Paragraph();
- p.setLeading(0);
- ct.addElement(p);
- }
- ct.addElement(ptable);
- boolean he = ptable.isHeadersInEvent();
- ptable.setHeadersInEvent(true);
- int loop = 0;
- while (true) {
- ct.setSimpleColumn(indentLeft(), indentBottom(), indentRight(), indentTop() - currentHeight);
- int status = ct.go();
- if ((status & ColumnText.NO_MORE_TEXT) != 0) {
- text.moveText(0, ct.getYLine() - indentTop() + currentHeight);
- currentHeight = indentTop() - ct.getYLine();
- break;
- }
- if (indentTop() - currentHeight == ct.getYLine())
- ++loop;
- else
- loop = 0;
- if (loop == 3) {
- add(new Paragraph("ERROR: Infinite table loop"));
- break;
- }
- newPage();
- }
- ptable.setHeadersInEvent(he);
- }
- */
-
- /**
- * Gets a PdfTable object
- * (contributed by dperezcar@fcc.es)
- * @param table a high level table object
- * @param supportRowAdditions
- * @return returns a PdfTable object
- * @see PdfWriter#getPdfTable(Table)
- */
- /* ssteward: dropped in 1.44
- PdfTable getPdfTable(Table table, boolean supportRowAdditions) {
- return new PdfTable(table, indentLeft(), indentRight(), indentTop() - currentHeight, supportRowAdditions);
- }
- */
-
- /**
- * @see PdfWriter#breakTableIfDoesntFit(PdfTable)
- * (contributed by dperezcar@fcc.es)
- * @param table Table to add
- * @return true if the table will be broken
- * @throws DocumentException
- */
- /* ssteward: dropped in 1.44
- boolean breakTableIfDoesntFit(PdfTable table) throws DocumentException {
- table.updateRowAdditions();
- // Do we have any full page available?
- if (!table.hasToFitPageTable() && table.bottom() <= indentBottom) {
- // Then output that page
- add(table, true);
- return true;
- }
- return false;
- }
- */
-
- /**
- * Adds a new table to
- * @param table Table to add. Rendered rows will be deleted after processing.
- * @param onlyFirstPage Render only the first full page
- * @throws DocumentException
- */
- /* ssteward: dropped in 1.44
- private void add(PdfTable table, boolean onlyFirstPage) throws DocumentException {
- // before every table, we flush all lines
- flushLines();
-
- // initialisation of parameters
- float pagetop = indentTop();
- float oldHeight = currentHeight;
- float cellDisplacement;
- PdfCell cell;
- PdfContentByte cellGraphics = new PdfContentByte(writer);
- boolean tableHasToFit =
- table.hasToFitPageTable() ? (table.bottom() < indentBottom() && table.height() < (top() - bottom())) : false;
- if (pageEmpty)
- tableHasToFit = false;
- boolean cellsHaveToFit = table.hasToFitPageCells();
-
- // drawing the table
- ArrayList cells = table.getCells();
- ArrayList headercells = table.getHeaderCells();
- // Check if we have removed header cells in a previous call
- if (headercells.size() > 0 && (cells.size() == 0 || cells.get(0) != headercells.get(0))) {
- ArrayList allCells = new ArrayList(cells.size()+headercells.size());
- allCells.addAll(headercells);
- allCells.addAll(cells);
- cells = allCells;
- }
- while (!cells.isEmpty()) {
- // initialisation of some extra parameters;
- float lostTableBottom = 0;
-
- // loop over the cells
- boolean cellsShown = false;
- int currentGroupNumber = 0;
- boolean headerChecked = false;
- for (ListIterator iterator = cells.listIterator(); iterator.hasNext() && !tableHasToFit;) {
- cell = (PdfCell) iterator.next();
- boolean atLeastOneFits = false;
- if( cellsHaveToFit ) {
- if( !cell.isHeader() ) {
- if (cell.getGroupNumber() != currentGroupNumber) {
- boolean cellsFit = true;
- currentGroupNumber = cell.getGroupNumber();
- cellsHaveToFit = table.hasToFitPageCells();
- int cellCount = 0;
- while (cell.getGroupNumber() == currentGroupNumber && cellsFit && iterator.hasNext()) {
- if (cell.bottom() < indentBottom()) {
- cellsFit = false;
- }
- else {
- atLeastOneFits |= true;
- }
- cell = (PdfCell) iterator.next();
- cellCount++;
- }
- if (!atLeastOneFits) {
- cellsHaveToFit = false;
- }
- if (!cellsFit) {
- break;
- }
- for (int i = cellCount; i >= 0; i--) {
- cell = (PdfCell) iterator.previous();
- }
- }
- }
- else {
- if( !headerChecked ) {
- headerChecked = true;
- boolean cellsFit = true;
- int cellCount = 0;
- float firstTop = cell.top();
- while (cell.isHeader() && cellsFit && iterator.hasNext()) {
- if (firstTop - cell.bottom(0) > indentTop() - currentHeight - indentBottom()) {
- cellsFit = false;
- }
- cell = (PdfCell) iterator.next();
- cellCount++;
- }
- currentGroupNumber = cell.getGroupNumber();
- while (cell.getGroupNumber() == currentGroupNumber && cellsFit && iterator.hasNext()) {
- if (firstTop - cell.bottom(0) > indentTop() - currentHeight - indentBottom() - 10.0) {
- cellsFit = false;
- }
- cell = (PdfCell) iterator.next();
- cellCount++;
- }
- for (int i = cellCount; i >= 0; i--) {
- cell = (PdfCell) iterator.previous();
- }
- if (!cellsFit) {
- while( cell.isHeader() ) {
- iterator.remove();
- cell = (PdfCell) iterator.next();
- }
- break;
- }
- }
- }
- }
- lines = cell.getLines(pagetop, indentBottom());
- // if there are lines to add, add them
- if (lines != null && lines.size() > 0) {
- // we paint the borders of the cells
- cellsShown = true;
- cellGraphics.rectangle(cell.rectangle(pagetop, indentBottom()));
- lostTableBottom = Math.max(cell.bottom(), indentBottom());
-
- // we write the text
- float cellTop = cell.top(pagetop - oldHeight);
- text.moveText(0, cellTop);
- cellDisplacement = flushLines() - cellTop;
- text.moveText(0, cellDisplacement);
- if (oldHeight + cellDisplacement > currentHeight) {
- currentHeight = oldHeight + cellDisplacement;
- }
- }
- ArrayList images = cell.getImages(pagetop, indentBottom());
- for (Iterator i = images.iterator(); i.hasNext();) {
- cellsShown = true;
- Image image = (Image) i.next();
- graphics.addImage(image);
- }
- // if a cell is allready added completely, remove it
- if (cell.mayBeRemoved()) {
- iterator.remove();
- }
- }
- tableHasToFit = false;
- // we paint the graphics of the table after looping through all the cells
- if (cellsShown) {
- Rectangle tablerec = new Rectangle(table);
- tablerec.setBorder(table.border());
- tablerec.setBorderWidth(table.borderWidth());
- tablerec.setBorderColor(table.borderColor());
- tablerec.setBackgroundColor(table.backgroundColor());
- tablerec.setGrayFill(table.grayFill());
- PdfContentByte under = writer.getDirectContentUnder();
- under.rectangle(tablerec.rectangle(top(), indentBottom()));
- under.add(cellGraphics);
- // bugfix by Gerald Fehringer: now again add the border for the table
- // since it might have been covered by cell backgrounds
- tablerec.setGrayFill(0);
- tablerec.setBackgroundColor(null);
- under.rectangle(tablerec.rectangle(top(), indentBottom()));
- // end bugfix
- }
- cellGraphics = new PdfContentByte(null);
- // if the table continues on the next page
- if (!cells.isEmpty()) {
- graphics.setLineWidth(table.borderWidth());
- if (cellsShown && (table.border() & Rectangle.BOTTOM) == Rectangle.BOTTOM) {
- // Draw the bottom line
-
- // the color is set to the color of the element
- Color tColor = table.borderColor();
- if (tColor != null) {
- graphics.setColorStroke(tColor);
- }
- graphics.moveTo(table.left(), Math.max(table.bottom(), indentBottom()));
- graphics.lineTo(table.right(), Math.max(table.bottom(), indentBottom()));
- graphics.stroke();
- if (tColor != null) {
- graphics.resetRGBColorStroke();
- }
- }
-
- // old page
- pageEmpty = false;
- float difference = lostTableBottom;
-
- // new page
- newPage();
- // G.F.: if something added in page event i.e. currentHeight > 0
- float heightCorrection = 0;
- boolean somethingAdded = false;
- if (currentHeight > 0) {
- heightCorrection = 6;
- currentHeight += heightCorrection;
- somethingAdded = true;
- newLine();
- flushLines();
- indentTop = currentHeight - leading;
- currentHeight = 0;
- }
- else {
- flushLines();
- }
-
- // this part repeats the table headers (if any)
- int size = headercells.size();
- if (size > 0) {
- // this is the top of the headersection
- cell = (PdfCell) headercells.get(0);
- float oldTop = cell.top(0);
- // loop over all the cells of the table header
- for (int i = 0; i < size; i++) {
- cell = (PdfCell) headercells.get(i);
- // calculation of the new cellpositions
- cell.setTop(indentTop() - oldTop + cell.top(0));
- cell.setBottom(indentTop() - oldTop + cell.bottom(0));
- pagetop = cell.bottom();
- // we paint the borders of the cell
- cellGraphics.rectangle(cell.rectangle(indentTop(), indentBottom()));
- // we write the text of the cell
- ArrayList images = cell.getImages(indentTop(), indentBottom());
- for (Iterator im = images.iterator(); im.hasNext();) {
- cellsShown = true;
- Image image = (Image) im.next();
- graphics.addImage(image);
- }
- lines = cell.getLines(indentTop(), indentBottom());
- float cellTop = cell.top(indentTop());
- text.moveText(0, cellTop-heightCorrection);
- cellDisplacement = flushLines() - cellTop+heightCorrection;
- text.moveText(0, cellDisplacement);
- }
- currentHeight = indentTop() - pagetop + table.cellspacing();
- text.moveText(0, pagetop - indentTop() - currentHeight);
- }
- else {
- if (somethingAdded) {
- pagetop = indentTop();
- text.moveText(0, -table.cellspacing());
- }
- }
- oldHeight = currentHeight - heightCorrection;
-
- // calculating the new positions of the table and the cells
- size = Math.min(cells.size(), table.columns());
- int i = 0;
- while (i < size) {
- cell = (PdfCell) cells.get(i);
- if (cell.top(-table.cellspacing()) > lostTableBottom) {
- float newBottom = pagetop - difference + cell.bottom();
- float neededHeight = cell.remainingHeight();
- if (newBottom > pagetop - neededHeight) {
- difference += newBottom - (pagetop - neededHeight);
- }
- }
- i++;
- }
- size = cells.size();
- table.setTop(indentTop());
- table.setBottom(pagetop - difference + table.bottom(table.cellspacing()));
- for (i = 0; i < size; i++) {
- cell = (PdfCell) cells.get(i);
- float newBottom = pagetop - difference + cell.bottom();
- float newTop = pagetop - difference + cell.top(-table.cellspacing());
- if (newTop > indentTop() - currentHeight) {
- newTop = indentTop() - currentHeight;
- }
- //float newBottom = newTop - cell.height();
- cell.setTop(newTop );
- cell.setBottom(newBottom );
- }
- if (onlyFirstPage) {
- break;
- }
- }
- }
-
- float tableHeight = table.top() - table.bottom();
- currentHeight = oldHeight + tableHeight;
- text.moveText(0, -tableHeight );
- pageEmpty = false;
- }
- */
-
- /**
- * Signals that an Element
was added to the Document
.
- *
- * @param element the element to add
- * @return true
if the element was added, false
if not.
- * @throws DocumentException when a document isn't open yet, or has been closed
- */
- public boolean add(Element element) throws DocumentException {
- if (writer != null && writer.isPaused()) {
- return false;
- }
- try {
-
- switch(element.type()) {
-
- // Information (headers)
- case Element.HEADER:
- info.addkey(((Meta)element).name(), ((Meta)element).content());
- break;
- case Element.TITLE:
- info.addTitle(((Meta)element).content());
- break;
- case Element.SUBJECT:
- info.addSubject(((Meta)element).content());
- break;
- case Element.KEYWORDS:
- info.addKeywords(((Meta)element).content());
- break;
- case Element.AUTHOR:
- info.addAuthor(((Meta)element).content());
- break;
- case Element.CREATOR:
- info.addCreator(((Meta)element).content());
- break;
- case Element.PRODUCER:
- // you can not change the name of the producer
- info.addProducer();
- break;
- case Element.CREATIONDATE:
- // you can not set the creation date, only reset it
- info.addCreationDate();
- break;
-
- case Element.CHUNK: {
- // if there isn't a current line available, we make one
- if (line == null) {
- carriageReturn();
- }
-
- // we cast the element to a chunk
- PdfChunk chunk = new PdfChunk((Chunk) element, currentAction);
- // we try to add the chunk to the line, until we succeed
- {
- PdfChunk overflow;
- while ((overflow = line.add(chunk)) != null) {
- carriageReturn();
- chunk = overflow;
- }
- }
- pageEmpty = false;
- if (chunk.isAttribute(Chunk.NEWPAGE)) {
- newPage();
- }
- break;
- }
- case Element.ANCHOR: {
- Anchor anchor = (Anchor) element;
- String url = anchor.reference();
- leading = anchor.leading();
- if (url != null) {
- currentAction = new PdfAction(url);
- }
-
- // we process the element
- element.process(this);
- currentAction = null;
- break;
- }
- case Element.ANNOTATION: {
- if (line == null) {
- carriageReturn();
- }
- Annotation annot = (Annotation) element;
- PdfAnnotation an = convertAnnotation(writer, annot);
- annotations.add(an);
- pageEmpty = false;
- break;
- }
- case Element.PHRASE: {
- // we cast the element to a phrase and set the leading of the document
- leading = ((Phrase) element).leading();
- // we process the element
- element.process(this);
- break;
- }
- case Element.PARAGRAPH: {
- // we cast the element to a paragraph
- Paragraph paragraph = (Paragraph) element;
-
- float spacingBefore = paragraph.spacingBefore();
- if (spacingBefore != 0) {
- leading = spacingBefore;
- carriageReturn();
- if (!pageEmpty) {
- /*
- * Don't add spacing before a paragraph if it's the first
- * on the page
- */
- Chunk space = new Chunk(" ");
- space.process(this);
- carriageReturn();
- }
- }
-
- // we adjust the parameters of the document
- alignment = paragraph.alignment();
- leading = paragraph.leading();
-
- carriageReturn();
- // we don't want to make orphans/widows
- if (currentHeight + line.height() + leading > indentTop() - indentBottom()) {
- newPage();
- }
-
- // Begin added: Bonf (Marc Schneider) 2003-07-29
- //carriageReturn();
- // End added: Bonf (Marc Schneider) 2003-07-29
-
- indentLeft += paragraph.indentationLeft();
- indentRight += paragraph.indentationRight();
-
- // Begin removed: Bonf (Marc Schneider) 2003-07-29
- carriageReturn();
- // End removed: Bonf (Marc Schneider) 2003-07-29
-
-
- //add by Jin-Hsia Yang
-
- paraIndent += paragraph.indentationLeft();
- //end add by Jin-Hsia Yang
-
- PdfPageEvent pageEvent = writer.getPageEvent();
- if (pageEvent != null && isParagraph)
- pageEvent.onParagraph(writer, this, indentTop() - currentHeight);
-
- /* ssteward: dropped in 1.44
- // if a paragraph has to be kept together, we wrap it in a table object
- if (paragraph.getKeepTogether()) {
- Table table = new Table(1, 1);
- table.setOffset(0f);
- table.setBorder(Table.NO_BORDER);
- table.setWidth(100f);
- table.setTableFitsPage(true);
- Cell cell = new Cell(paragraph);
- cell.setBorder(Table.NO_BORDER);
- //patch by Matt Benson 11/01/2002 - 14:32:00
- cell.setHorizontalAlignment(paragraph.alignment());
- //end patch by Matt Benson
- table.addCell(cell);
- this.add(table);
- break;
- }
- else
- */
- // we process the paragraph
- element.process(this);
-
- //add by Jin-Hsia Yang and blowagie
- paraIndent -= paragraph.indentationLeft();
- //end add by Jin-Hsia Yang and blowagie
-
- // Begin removed: Bonf (Marc Schneider) 2003-07-29
- // carriageReturn();
- // End removed: Bonf (Marc Schneider) 2003-07-29
-
- float spacingAfter = paragraph.spacingAfter();
- if (spacingAfter != 0) {
- leading = spacingAfter;
- carriageReturn();
- if (currentHeight + line.height() + leading < indentTop() - indentBottom()) {
- /*
- * Only add spacing after a paragraph if the extra
- * spacing fits on the page.
- */
- Chunk space = new Chunk(" ");
- space.process(this);
- carriageReturn();
- }
- leading = paragraph.leading(); // restore original leading
- }
-
- if (pageEvent != null && isParagraph)
- pageEvent.onParagraphEnd(writer, this, indentTop() - currentHeight);
-
- alignment = Element.ALIGN_LEFT;
- indentLeft -= paragraph.indentationLeft();
- indentRight -= paragraph.indentationRight();
-
- // Begin added: Bonf (Marc Schneider) 2003-07-29
- carriageReturn();
- // End added: Bonf (Marc Schneider) 2003-07-29
-
- //add by Jin-Hsia Yang
-
- //end add by Jin-Hsia Yang
-
- break;
- }
- /* ssteward: dropped in 1.44
- case Element.SECTION:
- case Element.CHAPTER: {
- // Chapters and Sections only differ in their constructor
- // so we cast both to a Section
- Section section = (Section) element;
-
- boolean hasTitle = section.title() != null;
-
- // if the section is a chapter, we begin a new page
- if (section.isChapter()) {
- newPage();
- }
- // otherwise, we begin a new line
- else {
- newLine();
- }
-
- if (hasTitle) {
- float fith = indentTop() - currentHeight;
- int rotation = pageSize.getRotation();
- if (rotation == 90 || rotation == 180)
- fith = pageSize.height() - fith;
- PdfDestination destination = new PdfDestination(PdfDestination.FITH, fith);
- while (currentOutline.level() >= section.depth()) {
- currentOutline = currentOutline.parent();
- }
- PdfOutline outline = new PdfOutline(currentOutline, destination, section.getBookmarkTitle(), section.isBookmarkOpen());
- currentOutline = outline;
- }
-
- // some values are set
- carriageReturn();
- indentLeft += section.indentationLeft();
- indentRight += section.indentationRight();
-
- PdfPageEvent pageEvent = writer.getPageEvent();
- if (pageEvent != null)
- if (element.type() == Element.CHAPTER)
- pageEvent.onChapter(writer, this, indentTop() - currentHeight, section.title());
- else
- pageEvent.onSection(writer, this, indentTop() - currentHeight, section.depth(), section.title());
-
- // the title of the section (if any has to be printed)
- if (hasTitle) {
- isParagraph = false;
- add(section.title());
- isParagraph = true;
- }
- indentLeft += section.indentation();
- // we process the section
- element.process(this);
- // some parameters are set back to normal again
- indentLeft -= section.indentationLeft() + section.indentation();
- indentRight -= section.indentationRight();
-
- if (pageEvent != null)
- if (element.type() == Element.CHAPTER)
- pageEvent.onChapterEnd(writer, this, indentTop() - currentHeight);
- else
- pageEvent.onSectionEnd(writer, this, indentTop() - currentHeight);
-
- break;
- }
-*/
- case Element.LIST: {
- // we cast the element to a List
- List list = (List) element;
- // we adjust the document
- listIndentLeft += list.indentationLeft();
- indentRight += list.indentationRight();
- // we process the items in the list
- element.process(this);
- // some parameters are set back to normal again
- listIndentLeft -= list.indentationLeft();
- indentRight -= list.indentationRight();
- break;
- }
- case Element.LISTITEM: {
- // we cast the element to a ListItem
- ListItem listItem = (ListItem) element;
-
- float spacingBefore = listItem.spacingBefore();
- if (spacingBefore != 0) {
- leading = spacingBefore;
- carriageReturn();
- if (!pageEmpty) {
- /*
- * Don't add spacing before a paragraph if it's the first
- * on the page
- */
- Chunk space = new Chunk(" ");
- space.process(this);
- carriageReturn();
- }
- }
-
- // we adjust the document
- alignment = listItem.alignment();
- listIndentLeft += listItem.indentationLeft();
- indentRight += listItem.indentationRight();
- leading = listItem.leading();
- carriageReturn();
- // we prepare the current line to be able to show us the listsymbol
- line.setListItem(listItem);
- // we process the item
- element.process(this);
-
- float spacingAfter = listItem.spacingAfter();
- if (spacingAfter != 0) {
- leading = spacingAfter;
- carriageReturn();
- if (currentHeight + line.height() + leading < indentTop() - indentBottom()) {
- /*
- * Only add spacing after a paragraph if the extra
- * spacing fits on the page.
- */
- Chunk space = new Chunk(" ");
- space.process(this);
- carriageReturn();
- }
- leading = listItem.leading(); // restore original leading
- }
-
- // if the last line is justified, it should be aligned to the left
- // if (line.hasToBeJustified()) {
- // line.resetAlignment();
- // }
- // some parameters are set back to normal again
- carriageReturn();
- listIndentLeft -= listItem.indentationLeft();
- indentRight -= listItem.indentationRight();
- break;
- }
- case Element.RECTANGLE: {
- Rectangle rectangle = (Rectangle) element;
- graphics.rectangle(rectangle);
- pageEmpty = false;
- break;
- }
- /* ssteward: dropped in 1.44
- case Element.PTABLE: {
- PdfPTable ptable = (PdfPTable)element;
- if (ptable.size() <= ptable.getHeaderRows())
- break; //nothing to do
-
- // before every table, we add a new line and flush all lines
- ensureNewLine();
- flushLines();
- addPTable(ptable);
- pageEmpty = false;
- break;
- }
- case Element.MULTI_COLUMN_TEXT: {
- ensureNewLine();
- flushLines();
- MultiColumnText multiText = (MultiColumnText) element;
- float height = multiText.write(writer.getDirectContent(), this, indentTop() - currentHeight);
- currentHeight += height;
- text.moveText(0, -1f* height);
- pageEmpty = false;
- break;
- }
- case Element.TABLE : {
-
- *//*
- * This is a list of people who worked on the Table functionality.
- * To see who did what, please check the CVS repository:
- *
- * Leslie Baski
- * Matt Benson
- * Francesco De Milato
- * David Freels
- * Bruno Lowagie
- * Veerendra Namineni
- * Geert Poels
- * Tom Ring
- * Paulo Soares
- * Gerald Fehringer
- * Steve Appling
- *//*
-
- PdfTable table;
- if (element instanceof PdfTable) {
- // Already pre-rendered
- table = (PdfTable)element;
- table.updateRowAdditions();
- } else if (element instanceof SimpleTable) {
- PdfPTable ptable = ((SimpleTable)element).createPdfPTable();
- if (ptable.size() <= ptable.getHeaderRows())
- break; //nothing to do
-
- // before every table, we add a new line and flush all lines
- ensureNewLine();
- flushLines();
- addPTable(ptable);
- pageEmpty = false;
- break;
- } else if (element instanceof Table) {
-
- try {
- PdfPTable ptable = ((Table)element).createPdfPTable();
- if (ptable.size() <= ptable.getHeaderRows())
- break; //nothing to do
-
- // before every table, we add a new line and flush all lines
- ensureNewLine();
- flushLines();
- addPTable(ptable);
- pageEmpty = false;
- break;
- }
- catch(BadElementException bee) {
- // constructing the PdfTable
- // Before the table, add a blank line using offset or default leading
- float offset = ((Table)element).getOffset();
- if (Float.isNaN(offset))
- offset = leading;
- carriageReturn();
- lines.add(new PdfLine(indentLeft(), indentRight(), alignment, offset));
- currentHeight += offset;
- table = getPdfTable((Table)element, false);
- }
- } else {
- return false;
- }
- add(table, false);
- break;
- }
- case Element.JPEG:
- case Element.IMGRAW:
- case Element.IMGTEMPLATE: {
- //carriageReturn(); suggestion by Marc Campforts
- add((Image) element);
- break;
- }
- case Element.GRAPHIC: {
- Graphic graphic = (Graphic) element;
- graphic.processAttributes(indentLeft(), indentBottom(), indentRight(), indentTop(), indentTop() - currentHeight);
- graphics.add(graphic);
- pageEmpty = false;
- break;
- }
- */
- default:
- return false;
- }
- lastElementType = element.type();
- return true;
- }
- catch(Exception e) {
- throw new DocumentException(e);
- }
- }
-
- // methods to add Content
-
- /**
- * Adds an image to the document.
- * @param image the Image
to add
- * @throws PdfException on error
- * @throws DocumentException on error
- */
- /* ssteward: dropped in 1.44
- private void add(Image image) throws PdfException, DocumentException {
-
- if (image.hasAbsolutePosition()) {
- graphics.addImage(image);
- pageEmpty = false;
- return;
- }
-
- // if there isn't enough room for the image on this page, save it for the next page
- if (currentHeight != 0 && indentTop() - currentHeight - image.scaledHeight() < indentBottom()) {
- if (!strictImageSequence && imageWait == null) {
- imageWait = image;
- return;
- }
- newPage();
- if (currentHeight != 0 && indentTop() - currentHeight - image.scaledHeight() < indentBottom()) {
- imageWait = image;
- return;
- }
- }
- pageEmpty = false;
- // avoid endless loops
- if (image == imageWait)
- imageWait = null;
- boolean textwrap = (image.alignment() & Image.TEXTWRAP) == Image.TEXTWRAP
- && !((image.alignment() & Image.MIDDLE) == Image.MIDDLE);
- boolean underlying = (image.alignment() & Image.UNDERLYING) == Image.UNDERLYING;
- float diff = leading / 2;
- if (textwrap) {
- diff += leading;
- }
- float lowerleft = indentTop() - currentHeight - image.scaledHeight() -diff;
- float mt[] = image.matrix();
- float startPosition = indentLeft() - mt[4];
- if ((image.alignment() & Image.RIGHT) == Image.RIGHT) startPosition = indentRight() - image.scaledWidth() - mt[4];
- if ((image.alignment() & Image.MIDDLE) == Image.MIDDLE) startPosition = indentLeft() + ((indentRight() - indentLeft() - image.scaledWidth()) / 2) - mt[4];
- if (image.hasAbsoluteX()) startPosition = image.absoluteX();
- graphics.addImage(image, mt[0], mt[1], mt[2], mt[3], startPosition, lowerleft - mt[5]);
- if (textwrap) {
- if (imageEnd < 0 || imageEnd < currentHeight + image.scaledHeight() + diff) {
- imageEnd = currentHeight + image.scaledHeight() + diff;
- }
- if ((image.alignment() & Image.RIGHT) == Image.RIGHT) {
- // indentation suggested by Pelikan Stephan
- imageIndentRight += image.scaledWidth() + image.indentationLeft();
- }
- else {
- // indentation suggested by Pelikan Stephan
- imageIndentLeft += image.scaledWidth() + image.indentationRight();
- }
- }
- if (!(textwrap || underlying)) {
- currentHeight += image.scaledHeight() + diff;
- flushLines();
- text.moveText(0, - (image.scaledHeight() + diff));
- newLine();
- }
- }
- */
-
- /**
- * Initializes a page.
- *
- * If the footer/header is set, it is printed.
- * @throws DocumentException on error
- */
-
- private void initPage() throws DocumentException {
-
- // initialisation of some page objects
- markPoint = 0;
- annotations = delayedAnnotations;
- delayedAnnotations = new ArrayList();
- pageResources = new PageResources();
- writer.resetContent();
-
- // the pagenumber is incremented
- pageN++;
-
- // graphics and text are initialized
- float oldleading = leading;
- int oldAlignment = alignment;
-
- if (marginMirroring && (getPageNumber() & 1) == 0) {
- marginRight = nextMarginLeft;
- marginLeft = nextMarginRight;
- }
- else {
- marginLeft = nextMarginLeft;
- marginRight = nextMarginRight;
- }
- marginTop = nextMarginTop;
- marginBottom = nextMarginBottom;
- imageEnd = -1;
- imageIndentRight = 0;
- imageIndentLeft = 0;
- graphics = new PdfContentByte(writer);
- text = new PdfContentByte(writer);
- text.beginText();
- text.moveText(left(), top());
- textEmptySize = text.size();
- text.reset();
- text.beginText();
- leading = 16;
- indentBottom = 0;
- indentTop = 0;
- currentHeight = 0;
-
- // backgroundcolors, etc...
- pageSize = nextPageSize;
- thisBoxSize = new HashMap(boxSize);
- if (pageSize.backgroundColor() != null
- || pageSize.hasBorders()
- || pageSize.borderColor() != null
- || pageSize.grayFill() > 0) {
- add(pageSize);
- }
-
- // if there is a watermark, the watermark is added
- /*
- if (watermark != null) {
- float mt[] = watermark.matrix();
- graphics.addImage(watermark, mt[0], mt[1], mt[2], mt[3], watermark.offsetX() - mt[4], watermark.offsetY() - mt[5]);
- }
- */
-
- // if there is a footer, the footer is added
- /* ssteward: dropped in 1.44
- if (footer != null) {
- // Avoid footer identation
- float tmpIndentLeft = indentLeft;
- float tmpIndentRight = indentRight;
- // Begin added: Bonf (Marc Schneider) 2003-07-29
- float tmpListIndentLeft = listIndentLeft;
- float tmpImageIndentLeft = imageIndentLeft;
- float tmpImageIndentRight = imageIndentRight;
- // End added: Bonf (Marc Schneider) 2003-07-29
-
- indentLeft = indentRight = 0;
- // Begin added: Bonf (Marc Schneider) 2003-07-29
- listIndentLeft = 0;
- imageIndentLeft = 0;
- imageIndentRight = 0;
- // End added: Bonf (Marc Schneider) 2003-07-29
-
- footer.setPageNumber(pageN);
- leading = footer.paragraph().leading();
- add(footer.paragraph());
- // adding the footer limits the height
- indentBottom = currentHeight;
- text.moveText(left(), indentBottom());
- flushLines();
- text.moveText(-left(), -bottom());
- footer.setTop(bottom(currentHeight));
- footer.setBottom(bottom() - (0.75f * leading));
- footer.setLeft(left());
- footer.setRight(right());
- graphics.rectangle(footer);
- indentBottom = currentHeight + leading * 2;
- currentHeight = 0;
-
- indentLeft = tmpIndentLeft;
- indentRight = tmpIndentRight;
- // Begin added: Bonf (Marc Schneider) 2003-07-29
- listIndentLeft = tmpListIndentLeft;
- imageIndentLeft = tmpImageIndentLeft;
- imageIndentRight = tmpImageIndentRight;
- // End added: Bonf (Marc Schneider) 2003-07-29
- }
- */
-
- // we move to the left/top position of the page
- text.moveText(left(), top());
-
- /* ssteward: dropped in 1.44
- // if there is a header, the header = added
- if (header != null) {
- // Avoid header identation
- float tmpIndentLeft = indentLeft;
- float tmpIndentRight = indentRight;
- // Begin added: Bonf (Marc Schneider) 2003-07-29
- float tmpListIndentLeft = listIndentLeft;
- float tmpImageIndentLeft = imageIndentLeft;
- float tmpImageIndentRight = imageIndentRight;
- // End added: Bonf (Marc Schneider) 2003-07-29
-
- indentLeft = indentRight = 0;
- // Added: Bonf
- listIndentLeft = 0;
- imageIndentLeft = 0;
- imageIndentRight = 0;
- // End added: Bonf
-
- header.setPageNumber(pageN);
- leading = header.paragraph().leading();
- text.moveText(0, leading);
- add(header.paragraph());
- newLine();
- indentTop = currentHeight - leading;
- header.setTop(top() + leading);
- header.setBottom(indentTop() + leading * 2 / 3);
- header.setLeft(left());
- header.setRight(right());
- graphics.rectangle(header);
- flushLines();
- currentHeight = 0;
-
- // Restore identation
- indentLeft = tmpIndentLeft;
- indentRight = tmpIndentRight;
- // Begin added: Bonf (Marc Schneider) 2003-07-29
- listIndentLeft = tmpListIndentLeft;
- imageIndentLeft = tmpImageIndentLeft;
- imageIndentRight = tmpImageIndentRight;
- // End added: Bonf (Marc Schneider) 2003-07-29
- }
- */
-
- pageEmpty = true;
-
- // if there is an image waiting to be drawn, draw it
- /* ssteward: dropped in 1.44
- try {
- if (imageWait != null) {
- add(imageWait);
- imageWait = null;
- }
- }
- catch(Exception e) {
- throw new ExceptionConverter(e);
- }
- */
-
- leading = oldleading;
- alignment = oldAlignment;
- carriageReturn();
- PdfPageEvent pageEvent = writer.getPageEvent();
- if (pageEvent != null) {
- if (firstPageEvent) {
- pageEvent.onOpenDocument(writer, this);
- }
- pageEvent.onStartPage(writer, this);
- }
- firstPageEvent = false;
- }
-
- /**
- * If the current line is not empty or null, it is added to the arraylist
- * of lines and a new empty line is added.
- * @throws DocumentException on error
- */
- private void carriageReturn() throws DocumentException {
- // the arraylist with lines may not be null
- if (lines == null) {
- lines = new ArrayList();
- }
- // If the current line is not null
- if (line != null) {
- // we check if the end of the page is reached (bugfix by Francois Gravel)
- if (currentHeight + line.height() + leading < indentTop() - indentBottom()) {
- // if so nonempty lines are added and the heigt is augmented
- if (line.size() > 0) {
- currentHeight += line.height();
- lines.add(line);
- pageEmpty = false;
- }
- }
- // if the end of the line is reached, we start a new page
- else {
- newPage();
- }
- }
- if (imageEnd > -1 && currentHeight > imageEnd) {
- imageEnd = -1;
- imageIndentRight = 0;
- imageIndentLeft = 0;
- }
- // a new current line is constructed
- line = new PdfLine(indentLeft(), indentRight(), alignment, leading);
- }
-
- /**
- * Adds the current line to the list of lines and also adds an empty line.
- * @throws DocumentException on error
- */
- private void newLine() throws DocumentException {
- lastElementType = -1;
- carriageReturn();
- if (lines != null && lines.size() > 0) {
- lines.add(line);
- currentHeight += line.height();
- }
- line = new PdfLine(indentLeft(), indentRight(), alignment, leading);
- }
-
- /**
- * Writes all the lines to the text-object.
- *
- * @return the displacement that was caused
- * @throws DocumentException on error
- */
- private float flushLines() throws DocumentException {
-
- // checks if the ArrayList with the lines is not null
- if (lines == null) {
- return 0;
- }
-
- //add by Jin-Hsia Yang
- boolean newline=false;
- //end add by Jin-Hsia Yang
-
- // checks if a new Line has to be made.
- if (line != null && line.size() > 0) {
- lines.add(line);
- line = new PdfLine(indentLeft(), indentRight(), alignment, leading);
-
- //add by Jin-Hsia Yang
- newline=true;
- //end add by Jin-Hsia Yang
-
- }
-
- // checks if the ArrayList with the lines is empty
- if (lines.size() == 0) {
- return 0;
- }
-
- // initialisation of some parameters
- Object currentValues[] = new Object[2];
- PdfFont currentFont = null;
- float displacement = 0;
- PdfLine l;
- PdfChunk chunk;
- Float lastBaseFactor = new Float(0);
- currentValues[1] = lastBaseFactor;
- // looping over all the lines
- for (Iterator i = lines.iterator(); i.hasNext(); ) {
-
- // this is a line in the loop
- l = (PdfLine) i.next();
-
- if(isNewpage && newline) { // fix Ken@PDI
- newline=false;
- text.moveText(l.indentLeft() - indentLeft() + listIndentLeft + paraIndent,-l.height());
- }
- else {
- text.moveText(l.indentLeft() - indentLeft() + listIndentLeft, -l.height());
- }
-
- // is the line preceeded by a symbol?
- if (l.listSymbol() != null) {
- chunk = l.listSymbol();
- text.moveText(- l.listIndent(), 0);
- if (chunk.font().compareTo(currentFont) != 0) {
- currentFont = chunk.font();
- text.setFontAndSize(currentFont.getFont(), currentFont.size());
- }
- if (chunk.color() != null) {
- Color color = chunk.color();
- text.setColorFill(color);
- text.showText(chunk.toString());
- text.resetRGBColorFill();
- }
- /* ssteward: dropped in 1.44
- else if (chunk.isImage()) {
- Image image = chunk.getImage();
- float matrix[] = image.matrix();
- float xMarker = text.getXTLM();
- float yMarker = text.getYTLM();
- matrix[Image.CX] = xMarker + chunk.getImageOffsetX() - matrix[Image.CX];
- matrix[Image.CY] = yMarker + chunk.getImageOffsetY() - matrix[Image.CY];
- graphics.addImage(image, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
- }
- */
- else {
- text.showText(chunk.toString());
- }
- text.moveText(l.listIndent(), 0);
- }
-
- currentValues[0] = currentFont;
-
- writeLineToContent(l, text, graphics, currentValues, writer.getSpaceCharRatio());
-
- currentFont = (PdfFont)currentValues[0];
-
- displacement += l.height();
- if (indentLeft() - listIndentLeft != l.indentLeft()) {
- text.moveText(indentLeft() - l.indentLeft() - listIndentLeft, 0);
- }
-
- }
- lines = new ArrayList();
- return displacement;
- }
-
- // methods to retrieve information
-
- /**
- * Gets the PdfInfo
-object.
- *
- * @return PdfInfo
- */
-
- PdfInfo getInfo() {
- return info;
- }
-
- /**
- * Gets the PdfCatalog
-object.
- *
- * @param pages an indirect reference to this document pages
- * @return PdfCatalog
- */
-
- PdfCatalog getCatalog(PdfIndirectReference pages) {
- PdfCatalog catalog;
- if (rootOutline.getKids().size() > 0) {
- catalog = new PdfCatalog(pages, rootOutline.indirectReference(), writer);
- }
- else
- catalog = new PdfCatalog(pages, writer);
- if (openActionName != null) {
- PdfAction action = getLocalGotoAction(openActionName);
- catalog.setOpenAction(action);
- }
- else if (openActionAction != null)
- catalog.setOpenAction(openActionAction);
-
- if (additionalActions != null) {
- catalog.setAdditionalActions(additionalActions);
- }
-
- if (pageLabels != null)
- catalog.setPageLabels(pageLabels);
- catalog.addNames(localDestinations, documentJavaScript, writer);
- catalog.setViewerPreferences(viewerPreferences);
- if (acroForm.isValid()) {
- try {
- catalog.setAcroForm(writer.addToBody(acroForm).getIndirectReference());
- }
- catch (IOException e) {
- throw new ExceptionConverter(e);
- }
- }
- return catalog;
- }
-
- // methods concerning the layout
-
- /**
- * Returns the bottomvalue of a Table
if it were added to this document.
- *
- * @param table the table that may or may not be added to this document
- * @return a bottom value
- */
- /* ssteward: dropped in 1.44
- float bottom(Table table) {
- // where will the table begin?
- float h = (currentHeight > 0) ? indentTop() - currentHeight - 2f * leading : indentTop();
- // constructing a PdfTable
- PdfTable tmp = getPdfTable(table, false);
- return tmp.bottom();
- }
- */
-
- /**
- * Checks if a PdfPTable
fits the current page of the PdfDocument
.
- *
- * @param table the table that has to be checked
- * @param margin a certain margin
- * @return true
if the PdfPTable
fits the page, false
otherwise.
- */
- /* ssteward: dropped in 1.44
- boolean fitsPage(PdfPTable table, float margin) {
- if (!table.isLockedWidth()) {
- float totalWidth = (indentRight() - indentLeft()) * table.getWidthPercentage() / 100;
- table.setTotalWidth(totalWidth);
- }
- // ensuring that a new line has been started.
- ensureNewLine();
- return table.getTotalHeight() <= indentTop() - currentHeight - indentBottom() - margin;
- }
- */
-
-
- /**
- * Gets the current vertical page position.
- * @param ensureNewLine Tells whether a new line shall be enforced. This may cause side effects
- * for elements that do not terminate the lines they've started because those lines will get
- * terminated.
- * @return The current vertical page position.
- */
- public float getVerticalPosition(boolean ensureNewLine) {
- // ensuring that a new line has been started.
- if (ensureNewLine) {
- ensureNewLine();
- }
- return top() - currentHeight - indentTop;
- }
-
- /**
- * Ensures that a new line has been started.
- */
- private void ensureNewLine() {
- try {
- if ((lastElementType == Element.PHRASE) ||
- (lastElementType == Element.CHUNK)) {
- newLine();
- flushLines();
- }
- } catch (DocumentException ex) {
- throw new ExceptionConverter(ex);
- }
- }
-
- /**
- * Gets the indentation on the left side.
- *
- * @return a margin
- */
-
- private float indentLeft() {
- return left(indentLeft + listIndentLeft + imageIndentLeft);
- }
-
- /**
- * Gets the indentation on the right side.
- *
- * @return a margin
- */
-
- private float indentRight() {
- return right(indentRight + imageIndentRight);
- }
-
- /**
- * Gets the indentation on the top side.
- *
- * @return a margin
- */
-
- private float indentTop() {
- return top(indentTop);
- }
-
- /**
- * Gets the indentation on the bottom side.
- *
- * @return a margin
- */
-
- float indentBottom() {
- return bottom(indentBottom);
- }
-
- /**
- * Adds a named outline to the document .
- * @param outline the outline to be added
- * @param name the name of this local destination
- */
- void addOutline(PdfOutline outline, String name) {
- localDestination(name, outline.getPdfDestination());
- }
-
- /**
- * Gets the AcroForm object.
- * @return the PdfAcroform object of the PdfDocument
- */
-
- public PdfAcroForm getAcroForm() {
- return acroForm;
- }
-
- /**
- * Gets the root outline. All the outlines must be created with a parent.
- * The first level is created with this outline.
- * @return the root outline
- */
- public PdfOutline getRootOutline() {
- return rootOutline;
- }
-
- /**
- * Writes a text line to the document. It takes care of all the attributes.
- *
- * Before entering the line position must have been established and the
- * text
argument must be in text object scope (beginText()
).
- * @param line the line to be written
- * @param text the PdfContentByte
where the text will be written to
- * @param graphics the PdfContentByte
where the graphics will be written to
- * @param currentValues the current font and extra spacing values
- * @param ratio
- * @throws DocumentException on error
- */
- void writeLineToContent(PdfLine line, PdfContentByte text, PdfContentByte graphics, Object currentValues[], float ratio) throws DocumentException {
- PdfFont currentFont = (PdfFont)(currentValues[0]);
- float lastBaseFactor = ((Float)(currentValues[1])).floatValue();
- PdfChunk chunk;
- int numberOfSpaces;
- int lineLen;
- boolean isJustified;
- float hangingCorrection = 0;
- float hScale = 1;
- float lastHScale = Float.NaN;
- float baseWordSpacing = 0;
- float baseCharacterSpacing = 0;
-
- numberOfSpaces = line.numberOfSpaces();
- lineLen = line.toString().length();
- // does the line need to be justified?
- isJustified = line.hasToBeJustified() && (numberOfSpaces != 0 || lineLen > 1);
- if (isJustified) {
- if (line.isNewlineSplit() && line.widthLeft() >= (lastBaseFactor * (ratio * numberOfSpaces + lineLen - 1))) {
- if (line.isRTL()) {
- text.moveText(line.widthLeft() - lastBaseFactor * (ratio * numberOfSpaces + lineLen - 1), 0);
- }
- baseWordSpacing = ratio * lastBaseFactor;
- baseCharacterSpacing = lastBaseFactor;
- }
- else {
- float width = line.widthLeft();
- PdfChunk last = line.getChunk(line.size() - 1);
- if (last != null) {
- String s = last.toString();
- char c;
- if (s.length() > 0 && hangingPunctuation.indexOf((c = s.charAt(s.length() - 1))) >= 0) {
- float oldWidth = width;
- width += last.font().width(c) * 0.4f;
- hangingCorrection = width - oldWidth;
- }
- }
- float baseFactor = width / (ratio * numberOfSpaces + lineLen - 1);
- baseWordSpacing = ratio * baseFactor;
- baseCharacterSpacing = baseFactor;
- lastBaseFactor = baseFactor;
- }
- }
-
- int lastChunkStroke = line.getLastStrokeChunk();
- int chunkStrokeIdx = 0;
- float xMarker = text.getXTLM();
- float baseXMarker = xMarker;
- float yMarker = text.getYTLM();
- boolean adjustMatrix = false;
-
- // looping over all the chunks in 1 line
- for (Iterator j = line.iterator(); j.hasNext(); ) {
- chunk = (PdfChunk) j.next();
- Color color = chunk.color();
- hScale = 1;
-
- if (chunkStrokeIdx <= lastChunkStroke) {
- float width;
- if (isJustified) {
- width = chunk.getWidthCorrected(baseCharacterSpacing, baseWordSpacing);
- }
- else
- width = chunk.width();
- if (chunk.isStroked()) {
- PdfChunk nextChunk = line.getChunk(chunkStrokeIdx + 1);
- if (chunk.isAttribute(Chunk.BACKGROUND)) {
- float subtract = lastBaseFactor;
- if (nextChunk != null && nextChunk.isAttribute(Chunk.BACKGROUND))
- subtract = 0;
- if (nextChunk == null)
- subtract += hangingCorrection;
- float fontSize = chunk.font().size();
- float ascender = chunk.font().getFont().getFontDescriptor(BaseFont.ASCENT, fontSize);
- float descender = chunk.font().getFont().getFontDescriptor(BaseFont.DESCENT, fontSize);
- Object bgr[] = (Object[])chunk.getAttribute(Chunk.BACKGROUND);
- graphics.setColorFill((Color)bgr[0]);
- float extra[] = (float[])bgr[1];
- graphics.rectangle(xMarker - extra[0],
- yMarker + descender - extra[1] + chunk.getTextRise(),
- width - subtract + extra[0] + extra[2],
- ascender - descender + extra[1] + extra[3]);
- graphics.fill();
- graphics.setGrayFill(0);
- }
- if (chunk.isAttribute(Chunk.UNDERLINE)) {
- float subtract = lastBaseFactor;
- if (nextChunk != null && nextChunk.isAttribute(Chunk.UNDERLINE))
- subtract = 0;
- if (nextChunk == null)
- subtract += hangingCorrection;
- Object unders[][] = (Object[][])chunk.getAttribute(Chunk.UNDERLINE);
- Color scolor = null;
- for (int k = 0; k < unders.length; ++k) {
- Object obj[] = unders[k];
- scolor = (Color)obj[0];
- float ps[] = (float[])obj[1];
- if (scolor == null)
- scolor = color;
- if (scolor != null)
- graphics.setColorStroke(scolor);
- float fsize = chunk.font().size();
- graphics.setLineWidth(ps[0] + fsize * ps[1]);
- float shift = ps[2] + fsize * ps[3];
- int cap2 = (int)ps[4];
- if (cap2 != 0)
- graphics.setLineCap(cap2);
- graphics.moveTo(xMarker, yMarker + shift);
- graphics.lineTo(xMarker + width - subtract, yMarker + shift);
- graphics.stroke();
- if (scolor != null)
- graphics.resetGrayStroke();
- if (cap2 != 0)
- graphics.setLineCap(0);
- }
- graphics.setLineWidth(1);
- }
- if (chunk.isAttribute(Chunk.ACTION)) {
- float subtract = lastBaseFactor;
- if (nextChunk != null && nextChunk.isAttribute(Chunk.ACTION))
- subtract = 0;
- if (nextChunk == null)
- subtract += hangingCorrection;
- text.addAnnotation(new PdfAnnotation(writer, xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size(), (PdfAction)chunk.getAttribute(Chunk.ACTION)));
- }
- if (chunk.isAttribute(Chunk.REMOTEGOTO)) {
- float subtract = lastBaseFactor;
- if (nextChunk != null && nextChunk.isAttribute(Chunk.REMOTEGOTO))
- subtract = 0;
- if (nextChunk == null)
- subtract += hangingCorrection;
- Object obj[] = (Object[])chunk.getAttribute(Chunk.REMOTEGOTO);
- String filename = (String)obj[0];
- if (obj[1] instanceof String)
- remoteGoto(filename, (String)obj[1], xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size());
- else
- remoteGoto(filename, ((Integer)obj[1]).intValue(), xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size());
- }
- if (chunk.isAttribute(Chunk.LOCALGOTO)) {
- float subtract = lastBaseFactor;
- if (nextChunk != null && nextChunk.isAttribute(Chunk.LOCALGOTO))
- subtract = 0;
- if (nextChunk == null)
- subtract += hangingCorrection;
- localGoto((String)chunk.getAttribute(Chunk.LOCALGOTO), xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size());
- }
- if (chunk.isAttribute(Chunk.LOCALDESTINATION)) {
- float subtract = lastBaseFactor;
- if (nextChunk != null && nextChunk.isAttribute(Chunk.LOCALDESTINATION))
- subtract = 0;
- if (nextChunk == null)
- subtract += hangingCorrection;
- localDestination((String)chunk.getAttribute(Chunk.LOCALDESTINATION), new PdfDestination(PdfDestination.XYZ, xMarker, yMarker + chunk.font().size(), 0));
- }
- if (chunk.isAttribute(Chunk.GENERICTAG)) {
- float subtract = lastBaseFactor;
- if (nextChunk != null && nextChunk.isAttribute(Chunk.GENERICTAG))
- subtract = 0;
- if (nextChunk == null)
- subtract += hangingCorrection;
- Rectangle rect = new Rectangle(xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size());
- PdfPageEvent pev = writer.getPageEvent();
- if (pev != null)
- pev.onGenericTag(writer, this, rect, (String)chunk.getAttribute(Chunk.GENERICTAG));
- }
- if (chunk.isAttribute(Chunk.PDFANNOTATION)) {
- float subtract = lastBaseFactor;
- if (nextChunk != null && nextChunk.isAttribute(Chunk.PDFANNOTATION))
- subtract = 0;
- if (nextChunk == null)
- subtract += hangingCorrection;
- float fontSize = chunk.font().size();
- float ascender = chunk.font().getFont().getFontDescriptor(BaseFont.ASCENT, fontSize);
- float descender = chunk.font().getFont().getFontDescriptor(BaseFont.DESCENT, fontSize);
- PdfAnnotation annot = PdfFormField.shallowDuplicate((PdfAnnotation)chunk.getAttribute(Chunk.PDFANNOTATION));
- annot.put(PdfName.RECT, new PdfRectangle(xMarker, yMarker + descender, xMarker + width - subtract, yMarker + ascender));
- text.addAnnotation(annot);
- }
- float params[] = (float[])chunk.getAttribute(Chunk.SKEW);
- Float hs = (Float)chunk.getAttribute(Chunk.HSCALE);
- if (params != null || hs != null) {
- float b = 0, c = 0;
- if (params != null) {
- b = params[0];
- c = params[1];
- }
- if (hs != null)
- hScale = hs.floatValue();
- text.setTextMatrix(hScale, b, c, 1, xMarker, yMarker);
- }
- /* ssteward: dropped in 1.44
- if (chunk.isImage()) {
- Image image = chunk.getImage();
- float matrix[] = image.matrix();
- matrix[Image.CX] = xMarker + chunk.getImageOffsetX() - matrix[Image.CX];
- matrix[Image.CY] = yMarker + chunk.getImageOffsetY() - matrix[Image.CY];
- graphics.addImage(image, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
- text.moveText(xMarker + lastBaseFactor + image.scaledWidth() - text.getXTLM(), 0);
- }
- */
- }
- xMarker += width;
- ++chunkStrokeIdx;
- }
-
- if (chunk.font().compareTo(currentFont) != 0) {
- currentFont = chunk.font();
- text.setFontAndSize(currentFont.getFont(), currentFont.size());
- }
- float rise = 0;
- Object textRender[] = (Object[])chunk.getAttribute(Chunk.TEXTRENDERMODE);
- int tr = 0;
- float strokeWidth = 1;
- Color strokeColor = null;
- Float fr = (Float)chunk.getAttribute(Chunk.SUBSUPSCRIPT);
- if (textRender != null) {
- tr = ((Integer)textRender[0]).intValue() & 3;
- if (tr != PdfContentByte.TEXT_RENDER_MODE_FILL)
- text.setTextRenderingMode(tr);
- if (tr == PdfContentByte.TEXT_RENDER_MODE_STROKE || tr == PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE) {
- strokeWidth = ((Float)textRender[1]).floatValue();
- if (strokeWidth != 1)
- text.setLineWidth(strokeWidth);
- strokeColor = (Color)textRender[2];
- if (strokeColor == null)
- strokeColor = color;
- if (strokeColor != null)
- text.setColorStroke(strokeColor);
- }
- }
- if (fr != null)
- rise = fr.floatValue();
- if (color != null)
- text.setColorFill(color);
- if (rise != 0)
- text.setTextRise(rise);
- /* ssteward: dropped in 1.44
- if (chunk.isImage()) {
- adjustMatrix = true;
- }
- */
- // If it is a CJK chunk or Unicode TTF we will have to simulate the
- // space adjustment.
- else if (isJustified && numberOfSpaces > 0 && chunk.isSpecialEncoding()) {
- if (hScale != lastHScale) {
- lastHScale = hScale;
- text.setWordSpacing(baseWordSpacing / hScale);
- text.setCharacterSpacing(baseCharacterSpacing / hScale);
- }
- String s = chunk.toString();
- int idx = s.indexOf(' ');
- if (idx < 0)
- text.showText(chunk.toString());
- else {
- float spaceCorrection = - baseWordSpacing * 1000f / chunk.font.size() / hScale;
- PdfTextArray textArray = new PdfTextArray(s.substring(0, idx));
- int lastIdx = idx;
- while ((idx = s.indexOf(' ', lastIdx + 1)) >= 0) {
- textArray.add(spaceCorrection);
- textArray.add(s.substring(lastIdx, idx));
- lastIdx = idx;
- }
- textArray.add(spaceCorrection);
- textArray.add(s.substring(lastIdx));
- text.showText(textArray);
- }
- }
- else {
- if (isJustified && hScale != lastHScale) {
- lastHScale = hScale;
- text.setWordSpacing(baseWordSpacing / hScale);
- text.setCharacterSpacing(baseCharacterSpacing / hScale);
- }
- text.showText(chunk.toString());
- }
-
- if (rise != 0)
- text.setTextRise(0);
- if (color != null)
- text.resetRGBColorFill();
- if (tr != PdfContentByte.TEXT_RENDER_MODE_FILL)
- text.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL);
- if (strokeColor != null)
- text.resetRGBColorStroke();
- if (strokeWidth != 1)
- text.setLineWidth(1);
- if (chunk.isAttribute(Chunk.SKEW) || chunk.isAttribute(Chunk.HSCALE)) {
- adjustMatrix = true;
- text.setTextMatrix(xMarker, yMarker);
- }
- }
- if (isJustified) {
- text.setWordSpacing(0);
- text.setCharacterSpacing(0);
- if (line.isNewlineSplit())
- lastBaseFactor = 0;
- }
- if (adjustMatrix)
- text.moveText(baseXMarker - text.getXTLM(), 0);
- currentValues[0] = currentFont;
- currentValues[1] = new Float(lastBaseFactor);
- }
-
- /**
- * Implements a link to other part of the document. The jump will
- * be made to a local destination with the same name, that must exist.
- * @param name the name for this link
- * @param llx the lower left x corner of the activation area
- * @param lly the lower left y corner of the activation area
- * @param urx the upper right x corner of the activation area
- * @param ury the upper right y corner of the activation area
- */
- void localGoto(String name, float llx, float lly, float urx, float ury) {
- PdfAction action = getLocalGotoAction(name);
- annotations.add(new PdfAnnotation(writer, llx, lly, urx, ury, action));
- }
-
- PdfAction getLocalGotoAction(String name) {
- PdfAction action;
- Object obj[] = (Object[])localDestinations.get(name);
- if (obj == null)
- obj = new Object[3];
- if (obj[0] == null) {
- if (obj[1] == null) {
- obj[1] = writer.getPdfIndirectReference();
- }
- action = new PdfAction((PdfIndirectReference)obj[1]);
- obj[0] = action;
- localDestinations.put(name, obj);
- }
- else {
- action = (PdfAction)obj[0];
- }
- return action;
- }
-
- /**
- * The local destination to where a local goto with the same
- * name will jump to.
- * @param name the name of this local destination
- * @param destination the PdfDestination
with the jump coordinates
- * @return true
if the local destination was added,
- * false
if a local destination with the same name
- * already existed
- */
- boolean localDestination(String name, PdfDestination destination) {
- Object obj[] = (Object[])localDestinations.get(name);
- if (obj == null)
- obj = new Object[3];
- if (obj[2] != null)
- return false;
- obj[2] = destination;
- localDestinations.put(name, obj);
- destination.addPage(writer.getCurrentPage());
- return true;
- }
-
- /**
- * Implements a link to another document.
- * @param filename the filename for the remote document
- * @param name the name to jump to
- * @param llx the lower left x corner of the activation area
- * @param lly the lower left y corner of the activation area
- * @param urx the upper right x corner of the activation area
- * @param ury the upper right y corner of the activation area
- */
- void remoteGoto(String filename, String name, float llx, float lly, float urx, float ury) {
- annotations.add(new PdfAnnotation(writer, llx, lly, urx, ury, new PdfAction(filename, name)));
- }
-
- /**
- * Implements a link to another document.
- * @param filename the filename for the remote document
- * @param page the page to jump to
- * @param llx the lower left x corner of the activation area
- * @param lly the lower left y corner of the activation area
- * @param urx the upper right x corner of the activation area
- * @param ury the upper right y corner of the activation area
- */
- void remoteGoto(String filename, int page, float llx, float lly, float urx, float ury) {
- writer.addAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury, new PdfAction(filename, page)));
- }
-
- /** Sets the viewer preferences as the sum of several constants.
- * @param preferences the viewer preferences
- * @see PdfWriter#setViewerPreferences
- */
-
- public void setViewerPreferences(int preferences) {
- viewerPreferences |= preferences;
- }
-
- /** Implements an action in an area.
- * @param action the PdfAction
- * @param llx the lower left x corner of the activation area
- * @param lly the lower left y corner of the activation area
- * @param urx the upper right x corner of the activation area
- * @param ury the upper right y corner of the activation area
- */
- void setAction(PdfAction action, float llx, float lly, float urx, float ury) {
- writer.addAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury, action));
- }
-
- void setOpenAction(String name) {
- openActionName = name;
- openActionAction = null;
- }
-
- void setOpenAction(PdfAction action) {
- openActionAction = action;
- openActionName = null;
- }
-
- void addAdditionalAction(PdfName actionType, PdfAction action) {
- if (additionalActions == null) {
- additionalActions = new PdfDictionary();
- }
- if (action == null)
- additionalActions.remove(actionType);
- else
- additionalActions.put(actionType, action);
- if (additionalActions.size() == 0)
- additionalActions = null;
- }
-
- void setPageLabels(PdfPageLabels pageLabels) {
- this.pageLabels = pageLabels;
- }
-
- void addJavaScript(PdfAction js) {
- if (js.get(PdfName.JS) == null)
- throw new RuntimeException("Only JavaScript actions are allowed.");
- try {
- documentJavaScript.add(writer.addToBody(js).getIndirectReference());
- }
- catch (IOException e) {
- throw new ExceptionConverter(e);
- }
- }
-
- void setCropBoxSize(Rectangle crop) {
- setBoxSize("crop", crop);
- }
-
- void setBoxSize(String boxName, Rectangle size) {
- if (size == null)
- boxSize.remove(boxName);
- else
- boxSize.put(boxName, new PdfRectangle(size));
- }
-
- void addCalculationOrder(PdfFormField formField) {
- acroForm.addCalculationOrder(formField);
- }
-
- void setSigFlags(int f) {
- acroForm.setSigFlags(f);
- }
-
- void addFormFieldRaw(PdfFormField field) {
- annotations.add(field);
- ArrayList kids = field.getKids();
- if (kids != null) {
- for (int k = 0; k < kids.size(); ++k)
- addFormFieldRaw((PdfFormField)kids.get(k));
- }
- }
-
- void addAnnotation(PdfAnnotation annot) {
- pageEmpty = false;
- if (annot.isForm()) {
- PdfFormField field = (PdfFormField)annot;
- if (field.getParent() == null)
- addFormFieldRaw(field);
- }
- else
- annotations.add(annot);
- }
-
- /**
- * Sets the display duration for the page (for presentations)
- * @param seconds the number of seconds to display the page
- */
- void setDuration(int seconds) {
- if (seconds > 0)
- this.duration=seconds;
- else
- this.duration=-1;
- }
-
- /**
- * Sets the transition for the page
- * @param transition the PdfTransition object
- */
- void setTransition(PdfTransition transition) {
- this.transition=transition;
- }
-
- void setPageAction(PdfName actionType, PdfAction action) {
- if (pageAA == null) {
- pageAA = new PdfDictionary();
- }
- pageAA.put(actionType, action);
- }
-
- /** Getter for property strictImageSequence.
- * @return Value of property strictImageSequence.
- *
- */
- boolean isStrictImageSequence() {
- return this.strictImageSequence;
- }
-
- /** Setter for property strictImageSequence.
- * @param strictImageSequence New value of property strictImageSequence.
- *
- */
- void setStrictImageSequence(boolean strictImageSequence) {
- this.strictImageSequence = strictImageSequence;
- }
-
- void setPageEmpty(boolean pageEmpty) {
- this.pageEmpty = pageEmpty;
- }
- /**
- * Method added by Pelikan Stephan
- * @see com.lowagie.text.DocListener#clearTextWrap()
- */
- /* ssteward: dropped in 1.44
- public void clearTextWrap() throws DocumentException {
- super.clearTextWrap();
- float tmpHeight = imageEnd - currentHeight;
- if (line != null) {
- tmpHeight += line.height();
- }
- if ((imageEnd > -1) && (tmpHeight > 0)) {
- carriageReturn();
- currentHeight += tmpHeight;
- }
- }
- */
-
- ArrayList getDocumentJavaScript() {
- return documentJavaScript;
- }
-
- /**
- * @see com.lowagie.text.DocListener#setMarginMirroring(boolean)
- */
- public boolean setMarginMirroring(boolean MarginMirroring) {
- if (writer != null && writer.isPaused()) {
- return false;
- }
- return super.setMarginMirroring(MarginMirroring);
- }
- /* ssteward: dropped in 1.44
- void setThumbnail(Image image) throws PdfException, DocumentException {
- thumb = writer.getImageReference(writer.addDirectImageSimple(image));
- }
- */
- static PdfAnnotation convertAnnotation(PdfWriter writer, Annotation annot) throws IOException {
- switch(annot.annotationType()) {
- case Annotation.URL_NET:
- return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((URL) annot.attributes().get(Annotation.URL)));
- case Annotation.URL_AS_STRING:
- return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.FILE)));
- case Annotation.FILE_DEST:
- return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.FILE), (String) annot.attributes().get(Annotation.DESTINATION)));
- case Annotation.SCREEN:
- boolean sparams[] = (boolean[])annot.attributes().get(Annotation.PARAMETERS);
- String fname = (String) annot.attributes().get(Annotation.FILE);
- String mimetype = (String) annot.attributes().get(Annotation.MIMETYPE);
- PdfFileSpecification fs;
- if (sparams[0])
- fs = PdfFileSpecification.fileEmbedded(writer, fname, fname, null);
- else
- fs = PdfFileSpecification.fileExtern(writer, fname);
- PdfAnnotation ann = PdfAnnotation.createScreen(writer, new Rectangle(annot.llx(), annot.lly(), annot.urx(), annot.ury()),
- fname, fs, mimetype, sparams[1]);
- return ann;
- case Annotation.FILE_PAGE:
- return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.FILE), ((Integer) annot.attributes().get(Annotation.PAGE)).intValue()));
- case Annotation.NAMED_DEST:
- return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction(((Integer) annot.attributes().get(Annotation.NAMED)).intValue()));
- case Annotation.LAUNCH:
- return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.APPLICATION),(String) annot.attributes().get(Annotation.PARAMETERS),(String) annot.attributes().get(Annotation.OPERATION),(String) annot.attributes().get(Annotation.DEFAULTDIR)));
- default:
- PdfDocument doc = writer.getPdfDocument();
- if (doc.line == null)
- return null;
- PdfAnnotation an = new PdfAnnotation(writer, annot.llx(doc.indentRight() - doc.line.widthLeft()), annot.lly(doc.indentTop() - doc.currentHeight), annot.urx(doc.indentRight() - doc.line.widthLeft() + 20), annot.ury(doc.indentTop() - doc.currentHeight - 20), new PdfString(annot.title()), new PdfString(annot.content()));
- return an;
- }
- }
-
- /**
- * @return an XmpMetadata byte array
- */
- public byte[] createXmpMetadata() {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- try {
- XmpWriter xmp = new XmpWriter(baos, getInfo());
- xmp.close();
- }
- catch(IOException ioe) {
- ioe.printStackTrace();
- }
- return baos.toByteArray();
- }
-
- int getMarkPoint() {
- return markPoint;
- }
-
- void incMarkPoint() {
- ++markPoint;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfEncodings.java pdftk-2.01/java/com/lowagie/text/pdf/PdfEncodings.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfEncodings.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfEncodings.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,754 +0,0 @@
-/*
- * Copyright 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import com.lowagie.text.ExceptionConverter;
-import java.io.UnsupportedEncodingException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.BufferedReader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.StringTokenizer;
-/** Supports fast encodings for winansi and PDFDocEncoding.
- * Supports conversions from CJK encodings to CID.
- * Supports custom encodings.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfEncodings {
-
- // ssteward
- //protected static Class c1= gnu.gcj.convert.Input_UnicodeBig.class;
-
- protected static final int CIDNONE = 0;
- protected static final int CIDRANGE = 1;
- protected static final int CIDCHAR = 2;
-
- static final char winansiByteToChar[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- 8364, 65533, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 65533, 381, 65533,
- 65533, 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250, 339, 65533, 382, 376,
- 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
- 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
- 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
- 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
- 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
- 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
-
- static final char pdfEncodingByteToChar[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018,
- 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 65533,
- 0x20ac, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
- 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
- 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
- 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
- 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
- 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
-
- static final IntHashtable winansi = new IntHashtable();
-
- static final IntHashtable pdfEncoding = new IntHashtable();
-
- static final HashMap extraEncodings = new HashMap();
-
- static {
- for (int k = 128; k < 160; ++k) {
- char c = winansiByteToChar[k];
- if (c != 65533)
- winansi.put(c, k);
- }
-
- for (int k = 128; k < 161; ++k) {
- char c = pdfEncodingByteToChar[k];
- if (c != 65533)
- pdfEncoding.put(c, k);
- }
-
- addExtraEncoding("Wingdings", new WingdingsConversion());
- addExtraEncoding("Symbol", new SymbolConversion(true));
- addExtraEncoding("ZapfDingbats", new SymbolConversion(false));
- addExtraEncoding("SymbolTT", new SymbolTTConversion());
- addExtraEncoding("Cp437", new Cp437Conversion());
- }
-
- /** Converts a String
to a
byte
array according
- * to the font's encoding.
- * @return an array of byte
representing the conversion according to the font's encoding
- * @param encoding the encoding fo the return byte array
- * @param text the String
to be converted
- */
- public static final byte[] convertToBytes(String text, String encoding) {
- if (text == null)
- return new byte[0];
- if (encoding == null || encoding.length() == 0) {
- int len = text.length();
- byte b[] = new byte[len];
- for (int k = 0; k < len; ++k) {
- b[k] = (byte)text.charAt(k);
- }
- return b;
- }
- ExtraEncoding extra = null;
- synchronized (extraEncodings) {
- extra = (ExtraEncoding)extraEncodings.get(encoding.toLowerCase());
- }
- if (extra != null) {
- byte b[] = extra.charToByte(text, encoding);
- if (b != null)
- return b;
- }
- IntHashtable hash = null;
- if (encoding.equals(BaseFont.WINANSI))
- hash = winansi;
- else if (encoding.equals(PdfObject.TEXT_PDFDOCENCODING))
- hash = pdfEncoding;
- if (hash != null) {
- char cc[] = text.toCharArray();
- int len = cc.length;
- int ptr = 0;
- byte b[] = new byte[len];
- int c = 0;
- for (int k = 0; k < len; ++k) {
- char char1 = cc[k];
- if (char1 < 128 || (char1 >= 160 && char1 <= 255))
- c = char1;
- else
- c = hash.get(char1);
- if (c != 0)
- b[ptr++] = (byte)c;
- }
- if (ptr == len)
- return b;
- byte b2[] = new byte[ptr];
- System.arraycopy(b, 0, b2, 0, ptr);
- return b2;
- }
- if (encoding.equals(PdfObject.TEXT_UNICODE)) {
- // workaround for jdk 1.2.2 bug
- char cc[] = text.toCharArray();
- int len = cc.length;
- byte b[] = new byte[cc.length * 2 + 2];
- b[0] = -2;
- b[1] = -1;
- int bptr = 2;
- for (int k = 0; k < len; ++k) {
- char c = cc[k];
- b[bptr++] = (byte)(c >> 8);
- b[bptr++] = (byte)(c & 0xff);
- }
- return b;
- }
- try {
- return text.getBytes(encoding);
- }
- catch (UnsupportedEncodingException e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /** Converts a
byte
array to a String
according
- * to the some encoding.
- * @param bytes the bytes to convert
- * @param encoding the encoding of input bytes
- * @return the converted String
- */
- // ssteward: reorganized for 1.45, added TEXT_UNICODE case
- public static final String convertToString( byte bytes[], String encoding ) {
-
- String ret_val= PdfObject.NOTHING;
- char[] ch= null;
-
- if( bytes!= null ) {
-
- if( encoding== null || encoding.length()== 0 ) {
- char cc[]= new char[bytes.length];
- for( int ii = 0; ii < bytes.length; ++ii ) {
- cc[ii]= (char)(bytes[ii] & 0xff);
- }
- ret_val=new String( cc );
- }
- else if( encoding== PdfObject.TEXT_UNICODE ) {
- // ssteward: we aren't really decoding UTF-16, but simply converting 8-bit splits into UTF-16;
- // added this in 1.45 because of trouble with String( byte, encoding ) in older gcj (3.4.5)
-
- int jj= 0;
- if( bytes.length>= 2 && bytes[0]== (byte)254 && bytes[1]== (byte)255 ) {
- jj= 2;
- }
- int cc_len= (int)Math.floor( (bytes.length- jj)/ 2 );
- char cc[]= new char[cc_len];
- for( int ii= 0; ii< cc_len; ++ii, ++jj ) {
- cc[ii]= (char)( (((int)bytes[ jj] & 0xff) << 8) +
- ((int)bytes[++jj] & 0xff) );
- }
- ret_val= new String( cc );
- }
- else if( encoding== PdfObject.TEXT_PDFDOCENCODING && (ch= pdfEncodingByteToChar)!= null ||
- encoding== BaseFont.WINANSI && (ch= winansiByteToChar)!= null )
- {
- char cc[]= new char[bytes.length];
- for( int ii= 0; ii< bytes.length; ++ii ) {
- cc[ii]= ch[ bytes[ii] & 0xff ];
- }
- ret_val= new String( cc );
- }
- else {
- ExtraEncoding extra= null;
- synchronized (extraEncodings) {
- extra = (ExtraEncoding)extraEncodings.get( encoding.toLowerCase() );
- }
-
- if( extra!= null ) {
- String text = extra.byteToChar(bytes, encoding);
- if (text != null)
- ret_val= text;
- }
- else {
- try {
- ret_val= new String( bytes, encoding );
- }
- catch( UnsupportedEncodingException e ) {
- throw new ExceptionConverter( e );
- }
- }
- }
- }
-
- return ret_val;
- }
-
- /** Checks is text
only has PdfDocEncoding characters.
- * @param text the String
to test
- * @return true
if only PdfDocEncoding characters are present
- */
- // text is unicode, right?
- public static boolean isPdfDocEncoding(String text) {
- if (text == null)
- return true;
- int len = text.length();
- for (int k = 0; k < len; ++k) {
- char char1 = text.charAt(k);
- if (char1 < 128 || (char1 >= 160 && char1 <= 255))
- continue;
- if (!pdfEncoding.containsKey(char1))
- return false;
- }
- return true;
- }
-
- static final HashMap cmaps = new HashMap();
- /** Assumes that '\\n' and '\\r\\n' are the newline sequences. It may not work for
- * all CJK encodings. To be used with loadCmap().
- */
- public static final byte CRLF_CID_NEWLINE[][] = new byte[][]{{(byte)'\n'}, {(byte)'\r', (byte)'\n'}};
-
- /** Clears the CJK cmaps from the cache. If name
is the
- * empty string then all the cache is cleared. Calling this method
- * has no consequences other than the need to reload the cmap
- * if needed.
- * @param name the name of the cmap to clear or all the cmaps if the empty string
- */
- public static void clearCmap(String name) {
- synchronized (cmaps) {
- if (name.length() == 0)
- cmaps.clear();
- else
- cmaps.remove(name);
- }
- }
-
- /** Loads a CJK cmap to the cache with the option of associating
- * sequences to the newline.
- * @param name the CJK cmap name
- * @param newline the sequences to be replaced bi a newline in the resulting CID. See CRLF_CID_NEWLINE
- */
- public static void loadCmap(String name, byte newline[][]) {
- try {
- char planes[][] = null;
- synchronized (cmaps) {
- planes = (char[][])cmaps.get(name);
- }
- if (planes == null) {
- planes = readCmap(name, (byte[][])newline);
- synchronized (cmaps) {
- cmaps.put(name, planes);
- }
- }
- }
- catch (IOException e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /** Converts a byte
array encoded as name
- * to a CID string. This is needed to reach some CJK characters
- * that don't exist in 16 bit Unicode.
- * The font to use this result must use the encoding "Identity-H"
- * or "Identity-V".
- * See ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/.
- * @param name the CJK encoding name
- * @param seq the byte
array to be decoded
- * @return the CID string
- */
- public static String convertCmap(String name, byte seq[]) {
- return convertCmap(name, seq, 0, seq.length);
- }
-
- /** Converts a byte
array encoded as name
- * to a CID string. This is needed to reach some CJK characters
- * that don't exist in 16 bit Unicode.
- * The font to use this result must use the encoding "Identity-H"
- * or "Identity-V".
- * See ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/.
- * @param name the CJK encoding name
- * @param start the start offset in the data
- * @param length the number of bytes to convert
- * @param seq the byte
array to be decoded
- * @return the CID string
- */
- public static String convertCmap(String name, byte seq[], int start, int length) {
- try {
- char planes[][] = null;
- synchronized (cmaps) {
- planes = (char[][])cmaps.get(name);
- }
- if (planes == null) {
- planes = readCmap(name, (byte[][])null);
- synchronized (cmaps) {
- cmaps.put(name, planes);
- }
- }
- return decodeSequence(seq, start, length, planes);
- }
- catch (IOException e) {
- throw new ExceptionConverter(e);
- }
- }
-
- static String decodeSequence(byte seq[], int start, int length, char planes[][]) {
- StringBuffer buf = new StringBuffer();
- int end = start + length;
- int currentPlane = 0;
- for (int k = start; k < end; ++k) {
- int one = (int)seq[k] & 0xff;
- char plane[] = planes[currentPlane];
- int cid = plane[one];
- if ((cid & 0x8000) == 0) {
- buf.append((char)cid);
- currentPlane = 0;
- }
- else
- currentPlane = cid & 0x7fff;
- }
- return buf.toString();
- }
-
- static char[][] readCmap(String name, byte newline[][]) throws IOException {
- ArrayList planes = new ArrayList();
- planes.add(new char[256]);
- readCmap(name, planes);
- if (newline != null) {
- for (int k = 0; k < newline.length; ++k)
- encodeSequence(newline[k].length, newline[k], BaseFont.CID_NEWLINE, planes);
- }
- char ret[][] = new char[planes.size()][];
- return (char[][])planes.toArray(ret);
- }
-
- static void readCmap(String name, ArrayList planes) throws IOException {
- String fullName = BaseFont.RESOURCE_PATH + "cmaps/" + name;
- InputStream in = BaseFont.getResourceStream(fullName);
- if (in == null)
- throw new IOException("The Cmap " + name + " was not found.");
- encodeStream(in, planes);
- in.close();
- }
-
- static void encodeStream(InputStream in, ArrayList planes) throws IOException {
- BufferedReader rd = new BufferedReader(new InputStreamReader(in, "iso-8859-1"));
- String line = null;
- int state = CIDNONE;
- byte seqs[] = new byte[7];
- while ((line = rd.readLine()) != null) {
- if (line.length() < 6)
- continue;
- switch (state) {
- case CIDNONE: {
- if (line.indexOf("begincidrange") >= 0)
- state = CIDRANGE;
- else if (line.indexOf("begincidchar") >= 0)
- state = CIDCHAR;
- else if (line.indexOf("usecmap") >= 0) {
- StringTokenizer tk = new StringTokenizer(line);
- String t = tk.nextToken();
- readCmap(t.substring(1), planes);
- }
- break;
- }
- case CIDRANGE: {
- if (line.indexOf("endcidrange") >= 0) {
- state = CIDNONE;
- break;
- }
- StringTokenizer tk = new StringTokenizer(line);
- String t = tk.nextToken();
- int size = t.length() / 2 - 1;
- long start = Long.parseLong(t.substring(1, t.length() - 1), 16);
- t = tk.nextToken();
- long end = Long.parseLong(t.substring(1, t.length() - 1), 16);
- t = tk.nextToken();
- int cid = Integer.parseInt(t);
- for (long k = start; k <= end; ++k) {
- breakLong(k, size, seqs);
- encodeSequence(size, seqs, (char)cid, planes);
- ++cid;
- }
- break;
- }
- case CIDCHAR: {
- if (line.indexOf("endcidchar") >= 0) {
- state = CIDNONE;
- break;
- }
- StringTokenizer tk = new StringTokenizer(line);
- String t = tk.nextToken();
- int size = t.length() / 2 - 1;
- long start = Long.parseLong(t.substring(1, t.length() - 1), 16);
- t = tk.nextToken();
- int cid = Integer.parseInt(t);
- breakLong(start, size, seqs);
- encodeSequence(size, seqs, (char)cid, planes);
- break;
- }
- }
- }
- }
-
- static void breakLong(long n, int size, byte seqs[]) {
- for (int k = 0; k < size; ++k) {
- seqs[k] = (byte)(n >> ((size - 1 - k) * 8));
- }
- }
-
- static void encodeSequence(int size, byte seqs[], char cid, ArrayList planes) {
- --size;
- int nextPlane = 0;
- for (int idx = 0; idx < size; ++idx) {
- char plane[] = (char[])planes.get(nextPlane);
- int one = (int)seqs[idx] & 0xff;
- char c = plane[one];
- if (c != 0 && (c & 0x8000) == 0)
- throw new RuntimeException("Inconsistent mapping.");
- if (c == 0) {
- planes.add(new char[256]);
- c = (char)((planes.size() - 1) | 0x8000);
- plane[one] = c;
- }
- nextPlane = c & 0x7fff;
- }
- char plane[] = (char[])planes.get(nextPlane);
- int one = (int)seqs[size] & 0xff;
- char c = plane[one];
- if ((c & 0x8000) != 0)
- throw new RuntimeException("Inconsistent mapping.");
- plane[one] = cid;
- }
-
- /** Adds an extra encoding.
- * @param name the name of the encoding. The encoding recognition is case insensitive
- * @param enc the conversion class
- */
- public static void addExtraEncoding(String name, ExtraEncoding enc) {
- synchronized (extraEncodings) {
- extraEncodings.put(name.toLowerCase(), enc);
- }
- }
-
- private static class WingdingsConversion implements ExtraEncoding {
-
- public byte[] charToByte(String text, String encoding) {
- char cc[] = text.toCharArray();
- byte b[] = new byte[cc.length];
- int ptr = 0;
- int len = cc.length;
- for (int k = 0; k < len; ++k) {
- char c = cc[k];
- if (c == ' ')
- b[ptr++] = (byte)c;
- else if (c >= '\u2701' && c <= '\u27BE') {
- byte v = table[c - 0x2700];
- if (v != 0)
- b[ptr++] = v;
- }
- }
- if (ptr == len)
- return b;
- byte b2[] = new byte[ptr];
- System.arraycopy(b, 0, b2, 0, ptr);
- return b2;
- }
-
- public String byteToChar(byte[] b, String encoding) {
- return null;
- }
-
- private final static byte table[] = {
- 0, 35, 34, 0, 0, 0, 41, 62, 81, 42,
- 0, 0, 65, 63, 0, 0, 0, 0, 0, -4,
- 0, 0, 0, -5, 0, 0, 0, 0, 0, 0,
- 86, 0, 88, 89, 0, 0, 0, 0, 0, 0,
- 0, 0, -75, 0, 0, 0, 0, 0, -74, 0,
- 0, 0, -83, -81, -84, 0, 0, 0, 0, 0,
- 0, 0, 0, 124, 123, 0, 0, 0, 84, 0,
- 0, 0, 0, 0, 0, 0, 0, -90, 0, 0,
- 0, 113, 114, 0, 0, 0, 117, 0, 0, 0,
- 0, 0, 0, 125, 126, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, -116, -115,
- -114, -113, -112, -111, -110, -109, -108, -107, -127, -126,
- -125, -124, -123, -122, -121, -120, -119, -118, -116, -115,
- -114, -113, -112, -111, -110, -109, -108, -107, -24, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, -24, -40, 0, 0, -60, -58, 0, 0, -16,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, -36,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0
- };
- }
-
- private static class Cp437Conversion implements ExtraEncoding {
- private static IntHashtable c2b = new IntHashtable();
-
- public byte[] charToByte(String text, String encoding) {
- char cc[] = text.toCharArray();
- byte b[] = new byte[cc.length];
- int ptr = 0;
- int len = cc.length;
- for (int k = 0; k < len; ++k) {
- char c = cc[k];
- if (c < ' ')
- continue;
- if (c < 128)
- b[ptr++] = (byte)c;
- else {
- byte v = (byte)c2b.get(c);
- if (v != 0)
- b[ptr++] = v;
- }
- }
- if (ptr == len)
- return b;
- byte b2[] = new byte[ptr];
- System.arraycopy(b, 0, b2, 0, ptr);
- return b2;
- }
-
- public String byteToChar(byte[] b, String encoding) {
- int len = b.length;
- char cc[] = new char[len];
- int ptr = 0;
- for (int k = 0; k < len; ++k) {
- int c = b[k] & 0xff;
- if (c < ' ')
- continue;
- if (c < 128)
- cc[ptr++] = (char)c;
- else {
- char v = table[c - 128];
- cc[ptr++] = v;
- }
- }
- return new String(cc, 0, ptr);
- }
-
- private final static char table[] = {
- '\u00C7', '\u00FC', '\u00E9', '\u00E2', '\u00E4', '\u00E0', '\u00E5', '\u00E7', '\u00EA', '\u00EB', '\u00E8', '\u00EF', '\u00EE', '\u00EC', '\u00C4', '\u00C5',
- '\u00C9', '\u00E6', '\u00C6', '\u00F4', '\u00F6', '\u00F2', '\u00FB', '\u00F9', '\u00FF', '\u00D6', '\u00DC', '\u00A2', '\u00A3', '\u00A5', '\u20A7', '\u0192',
- '\u00E1', '\u00ED', '\u00F3', '\u00FA', '\u00F1', '\u00D1', '\u00AA', '\u00BA', '\u00BF', '\u2310', '\u00AC', '\u00BD', '\u00BC', '\u00A1', '\u00AB', '\u00BB',
- '\u2591', '\u2592', '\u2593', '\u2502', '\u2524', '\u2561', '\u2562', '\u2556', '\u2555', '\u2563', '\u2551', '\u2557', '\u255D', '\u255C', '\u255B', '\u2510',
- '\u2514', '\u2534', '\u252C', '\u251C', '\u2500', '\u253C', '\u255E', '\u255F', '\u255A', '\u2554', '\u2569', '\u2566', '\u2560', '\u2550', '\u256C', '\u2567',
- '\u2568', '\u2564', '\u2565', '\u2559', '\u2558', '\u2552', '\u2553', '\u256B', '\u256A', '\u2518', '\u250C', '\u2588', '\u2584', '\u258C', '\u2590', '\u2580',
- '\u03B1', '\u00DF', '\u0393', '\u03C0', '\u03A3', '\u03C3', '\u00B5', '\u03C4', '\u03A6', '\u0398', '\u03A9', '\u03B4', '\u221E', '\u03C6', '\u03B5', '\u2229',
- '\u2261', '\u00B1', '\u2265', '\u2264', '\u2320', '\u2321', '\u00F7', '\u2248', '\u00B0', '\u2219', '\u00B7', '\u221A', '\u207F', '\u00B2', '\u25A0', '\u00A0'
- };
-
- static {
- for (int k = 0; k < table.length; ++k)
- c2b.put(table[k], k + 128);
- }
- }
-
- private static class SymbolConversion implements ExtraEncoding {
-
- private static final IntHashtable t1 = new IntHashtable();
- private static final IntHashtable t2 = new IntHashtable();
- private IntHashtable translation;
-
- SymbolConversion(boolean symbol) {
- if (symbol)
- translation = t1;
- else
- translation = t2;
- }
-
- public byte[] charToByte(String text, String encoding) {
- char cc[] = text.toCharArray();
- byte b[] = new byte[cc.length];
- int ptr = 0;
- int len = cc.length;
- for (int k = 0; k < len; ++k) {
- char c = cc[k];
- byte v = (byte)translation.get((int)c);
- if (v != 0)
- b[ptr++] = v;
- }
- if (ptr == len)
- return b;
- byte b2[] = new byte[ptr];
- System.arraycopy(b, 0, b2, 0, ptr);
- return b2;
- }
-
- public String byteToChar(byte[] b, String encoding) {
- return null;
- }
-
- private final static char table1[] = {
- ' ','!','\u2200','#','\u2203','%','&','\u220b','(',')','*','+',',','-','.','/',
- '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
- '\u2245','\u0391','\u0392','\u03a7','\u0394','\u0395','\u03a6','\u0393','\u0397','\u0399','\u03d1','\u039a','\u039b','\u039c','\u039d','\u039f',
- '\u03a0','\u0398','\u03a1','\u03a3','\u03a4','\u03a5','\u03c2','\u03a9','\u039e','\u03a8','\u0396','[','\u2234',']','\u22a5','_',
- '\u0305','\u03b1','\u03b2','\u03c7','\u03b4','\u03b5','\u03d5','\u03b3','\u03b7','\u03b9','\u03c6','\u03ba','\u03bb','\u03bc','\u03bd','\u03bf',
- '\u03c0','\u03b8','\u03c1','\u03c3','\u03c4','\u03c5','\u03d6','\u03c9','\u03be','\u03c8','\u03b6','{','|','}','~','\0',
- '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
- '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
- '\u20ac','\u03d2','\u2032','\u2264','\u2044','\u221e','\u0192','\u2663','\u2666','\u2665','\u2660','\u2194','\u2190','\u2191','\u2192','\u2193',
- '\u00b0','\u00b1','\u2033','\u2265','\u00d7','\u221d','\u2202','\u2022','\u00f7','\u2260','\u2261','\u2248','\u2026','\u2502','\u2500','\u21b5',
- '\u2135','\u2111','\u211c','\u2118','\u2297','\u2295','\u2205','\u2229','\u222a','\u2283','\u2287','\u2284','\u2282','\u2286','\u2208','\u2209',
- '\u2220','\u2207','\u00ae','\u00a9','\u2122','\u220f','\u221a','\u2022','\u00ac','\u2227','\u2228','\u21d4','\u21d0','\u21d1','\u21d2','\u21d3',
- '\u25ca','\u2329','\0','\0','\0','\u2211','\u239b','\u239c','\u239d','\u23a1','\u23a2','\u23a3','\u23a7','\u23a8','\u23a9','\u23aa',
- '\0','\u232a','\u222b','\u2320','\u23ae','\u2321','\u239e','\u239f','\u23a0','\u23a4','\u23a5','\u23a6','\u23ab','\u23ac','\u23ad','\0'
- };
-
- private final static char table2[] = {
- '\u0020','\u2701','\u2702','\u2703','\u2704','\u260e','\u2706','\u2707','\u2708','\u2709','\u261b','\u261e','\u270C','\u270D','\u270E','\u270F',
- '\u2710','\u2711','\u2712','\u2713','\u2714','\u2715','\u2716','\u2717','\u2718','\u2719','\u271A','\u271B','\u271C','\u271D','\u271E','\u271F',
- '\u2720','\u2721','\u2722','\u2723','\u2724','\u2725','\u2726','\u2727','\u2605','\u2729','\u272A','\u272B','\u272C','\u272D','\u272E','\u272F',
- '\u2730','\u2731','\u2732','\u2733','\u2734','\u2735','\u2736','\u2737','\u2738','\u2739','\u273A','\u273B','\u273C','\u273D','\u273E','\u273F',
- '\u2740','\u2741','\u2742','\u2743','\u2744','\u2745','\u2746','\u2747','\u2748','\u2749','\u274A','\u274B','\u25cf','\u274D','\u25a0','\u274F',
- '\u2750','\u2751','\u2752','\u25b2','\u25bc','\u25c6','\u2756','\u25d7','\u2758','\u2759','\u275A','\u275B','\u275C','\u275D','\u275E','\u0000',
- '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
- '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
- '\u0000','\u2761','\u2762','\u2763','\u2764','\u2765','\u2766','\u2767','\u2663','\u2666','\u2665','\u2660','\u2460','\u2461','\u2462','\u2463',
- '\u2464','\u2465','\u2466','\u2467','\u2468','\u2469','\u2776','\u2777','\u2778','\u2779','\u277A','\u277B','\u277C','\u277D','\u277E','\u277F',
- '\u2780','\u2781','\u2782','\u2783','\u2784','\u2785','\u2786','\u2787','\u2788','\u2789','\u278A','\u278B','\u278C','\u278D','\u278E','\u278F',
- '\u2790','\u2791','\u2792','\u2793','\u2794','\u2192','\u2194','\u2195','\u2798','\u2799','\u279A','\u279B','\u279C','\u279D','\u279E','\u279F',
- '\u27A0','\u27A1','\u27A2','\u27A3','\u27A4','\u27A5','\u27A6','\u27A7','\u27A8','\u27A9','\u27AA','\u27AB','\u27AC','\u27AD','\u27AE','\u27AF',
- '\u0000','\u27B1','\u27B2','\u27B3','\u27B4','\u27B5','\u27B6','\u27B7','\u27B8','\u27B9','\u27BA','\u27BB','\u27BC','\u27BD','\u27BE','\u0000'
- };
-
- static {
- for (int k = 0; k < table1.length; ++k) {
- int v = (int)table1[k];
- if (v != 0)
- t1.put(v, k + 32);
- }
- for (int k = 0; k < table2.length; ++k) {
- int v = (int)table2[k];
- if (v != 0)
- t2.put(v, k + 32);
- }
- }
- }
-
- private static class SymbolTTConversion implements ExtraEncoding {
-
- public byte[] charToByte(String text, String encoding) {
- char ch[] = text.toCharArray();
- byte b[] = new byte[ch.length];
- int ptr = 0;
- int len = ch.length;
- for (int k = 0; k < len; ++k) {
- char c = ch[k];
- if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
- b[ptr++] = (byte)c;
- }
- if (ptr == len)
- return b;
- byte b2[] = new byte[ptr];
- System.arraycopy(b, 0, b2, 0, ptr);
- return b2;
- }
-
- public String byteToChar(byte[] b, String encoding) {
- return null;
- }
-
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfEncryption.java.c pdftk-2.01/java/com/lowagie/text/pdf/PdfEncryption.java.c
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfEncryption.java.c 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfEncryption.java.c 1970-01-01 00:00:00.000000000 +0000
@@ -1,366 +0,0 @@
-/*
- * $Id: PdfEncryption.java,v 1.53 2005/08/05 23:13:44 psoares33 Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-// ssteward: local libs only needed for gcc 3.4
-#ifdef PDFTK_JAVA_LOCAL
-import java_local.security.MessageDigest;
-#else
-import java.security.MessageDigest;
-#endif
-import com.lowagie.text.ExceptionConverter;
-
-/**
- *
- * @author Paulo Soares (psoares@consiste.pt)
- * @author Kazuya Ujihara
- */
-public class PdfEncryption {
-
- static final byte pad[] = {
- (byte)0x28, (byte)0xBF, (byte)0x4E, (byte)0x5E, (byte)0x4E, (byte)0x75,
- (byte)0x8A, (byte)0x41, (byte)0x64, (byte)0x00, (byte)0x4E, (byte)0x56,
- (byte)0xFF, (byte)0xFA, (byte)0x01, (byte)0x08, (byte)0x2E, (byte)0x2E,
- (byte)0x00, (byte)0xB6, (byte)0xD0, (byte)0x68, (byte)0x3E, (byte)0x80,
- (byte)0x2F, (byte)0x0C, (byte)0xA9, (byte)0xFE, (byte)0x64, (byte)0x53,
- (byte)0x69, (byte)0x7A};
-
- byte state[] = new byte[256];
- int x;
- int y;
- /** The encryption key for a particular object/generation */
- byte key[];
- /** The encryption key length for a particular object/generation */
- int keySize;
- /** The global encryption key */
- byte mkey[];
- /** Work area to prepare the object/generation bytes */
- byte extra[] = new byte[5];
- /** The message digest algorithm MD5 */
- MessageDigest md5;
- /** The encryption key for the owner */
- byte ownerKey[] = new byte[32];
- /** The encryption key for the user */
- byte userKey[] = new byte[32];
- int permissions;
- byte documentID[];
- static long seq = System.currentTimeMillis();
-
- public PdfEncryption() {
- try {
- md5 = MessageDigest.getInstance("MD5");
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- public PdfEncryption(PdfEncryption enc) {
- this();
- mkey = (byte[])enc.mkey.clone();
- ownerKey = (byte[])enc.ownerKey.clone();
- userKey = (byte[])enc.userKey.clone();
- permissions = enc.permissions;
- if (enc.documentID != null)
- documentID = (byte[])enc.documentID.clone();
- }
-
- /**
- */
- private byte[] padPassword(byte userPassword[]) {
- byte userPad[] = new byte[32];
- if (userPassword == null) {
- System.arraycopy(pad, 0, userPad, 0, 32);
- }
- else {
- System.arraycopy(userPassword, 0, userPad, 0, Math.min(userPassword.length, 32));
- if (userPassword.length < 32)
- System.arraycopy(pad, 0, userPad, userPassword.length, 32 - userPassword.length);
- }
-
- return userPad;
- }
-
- /**
- */
- private byte[] computeOwnerKey(byte userPad[], byte ownerPad[], boolean strength128Bits) {
- byte ownerKey[] = new byte[32];
-
- byte digest[] = md5.digest(ownerPad);
- if (strength128Bits) {
- byte mkey[] = new byte[16];
- for (int k = 0; k < 50; ++k)
- digest = md5.digest(digest);
- System.arraycopy(userPad, 0, ownerKey, 0, 32);
- for (int i = 0; i < 20; ++i) {
- for (int j = 0; j < mkey.length ; ++j)
- mkey[j] = (byte)(digest[j] ^ i);
- prepareRC4Key(mkey);
- encryptRC4(ownerKey);
- }
- }
- else {
- prepareRC4Key(digest, 0, 5);
- encryptRC4(userPad, ownerKey);
- }
-
- return ownerKey;
- }
-
- /**
- *
- * ownerKey, documentID must be setuped
- */
- private void setupGlobalEncryptionKey(byte[] documentID, byte userPad[], byte ownerKey[], int permissions, boolean strength128Bits) {
- this.documentID = documentID;
- this.ownerKey = ownerKey;
- this.permissions = permissions;
- mkey = new byte[strength128Bits ? 16 : 5];
-
- //fixed by ujihara in order to follow PDF refrence
- md5.reset();
- md5.update(userPad);
- md5.update(ownerKey);
-
- byte ext[] = new byte[4];
- ext[0] = (byte)permissions;
- ext[1] = (byte)(permissions >> 8);
- ext[2] = (byte)(permissions >> 16);
- ext[3] = (byte)(permissions >> 24);
- md5.update(ext, 0, 4);
- if (documentID != null) md5.update(documentID);
-
- byte digest[] = md5.digest();
-
- if (mkey.length == 16) {
- for (int k = 0; k < 50; ++k)
- digest = md5.digest(digest);
- }
-
- System.arraycopy(digest, 0, mkey, 0, mkey.length);
- }
-
- /**
- *
- * mkey must be setuped
- */
- private void setupUserKey() {
- if (mkey.length == 16) {
- md5.update(pad);
- byte digest[] = md5.digest(documentID);
- System.arraycopy(digest, 0, userKey, 0, 16);
- for (int k = 16; k < 32; ++k)
- userKey[k] = 0;
- for (int i = 0; i < 20; ++i) {
- for (int j = 0; j < mkey.length; ++j)
- digest[j] = (byte)(mkey[j] ^ i);
- prepareRC4Key(digest, 0, mkey.length);
- encryptRC4(userKey, 0, 16);
- }
- }
- else {
- prepareRC4Key(mkey);
- encryptRC4(pad, userKey);
- }
- }
-
- public void setupAllKeys(byte userPassword[], byte ownerPassword[], int permissions, boolean strength128Bits) {
- // ssteward: this 'random' owner PW is generally unexpected behavior
- // and could lead to unpleasant surprises; as noted, below,
- // if no owner password is given, use the user password in its place;
- //if (ownerPassword == null || ownerPassword.length == 0)
- // ownerPassword = md5.digest(createDocumentId());
- if( ownerPassword== null || ownerPassword.length== 0 ) {
- ownerPassword= new byte[userPassword.length];
- System.arraycopy( userPassword, 0, ownerPassword, 0, userPassword.length );
- }
- // PDF 1.3 ref. (40 bit enc.) says to set unused, upper bits to 1
- permissions |= strength128Bits ? 0xfffff0c0 : 0xffffffc0;
- permissions &= 0xfffffffc;
- //PDF refrence 3.5.2 Standard Security Handler, Algorithum 3.3-1
- //If there is no owner password, use the user password instead.
- byte userPad[] = padPassword(userPassword);
- byte ownerPad[] = padPassword(ownerPassword);
-
- this.ownerKey = computeOwnerKey(userPad, ownerPad, strength128Bits);
- documentID = createDocumentId();
- setupByUserPad(this.documentID, userPad, this.ownerKey, permissions, strength128Bits);
- }
-
- public static byte[] createDocumentId() {
- MessageDigest md5;
- try {
- md5 = MessageDigest.getInstance("MD5");
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- long time = System.currentTimeMillis();
- long mem = Runtime.getRuntime().freeMemory();
- String s = time + "+" + mem + "+" + (seq++);
- return md5.digest(s.getBytes());
- }
-
- /**
- */
- public void setupByUserPassword(byte[] documentID, byte userPassword[], byte ownerKey[], int permissions, boolean strength128Bits) {
- setupByUserPad(documentID, padPassword(userPassword), ownerKey, permissions, strength128Bits);
- }
-
- /**
- */
- private void setupByUserPad(byte[] documentID, byte userPad[], byte ownerKey[], int permissions, boolean strength128Bits) {
- setupGlobalEncryptionKey(documentID, userPad, ownerKey, permissions, strength128Bits);
- setupUserKey();
- }
-
- /**
- */
- public void setupByOwnerPassword(byte[] documentID, byte ownerPassword[], byte userKey[], byte ownerKey[], int permissions, boolean strength128Bits) {
- setupByOwnerPad(documentID, padPassword(ownerPassword), userKey, ownerKey, permissions, strength128Bits);
- }
-
- private void setupByOwnerPad(byte[] documentID, byte ownerPad[], byte userKey[], byte ownerKey[], int permissions, boolean strength128Bits) {
- byte userPad[] = computeOwnerKey(ownerKey, ownerPad, strength128Bits); //userPad will be set in this.ownerKey
- setupGlobalEncryptionKey(documentID, userPad, ownerKey, permissions, strength128Bits); //step 3
- setupUserKey();
- }
-
- public void prepareKey() {
- prepareRC4Key(key, 0, keySize);
- }
-
- public void setHashKey(int number, int generation) {
- md5.reset(); //added by ujihara
- extra[0] = (byte)number;
- extra[1] = (byte)(number >> 8);
- extra[2] = (byte)(number >> 16);
- extra[3] = (byte)generation;
- extra[4] = (byte)(generation >> 8);
- md5.update(mkey);
- key = md5.digest(extra);
- keySize = mkey.length + 5;
- if (keySize > 16)
- keySize = 16;
- }
-
- public static PdfObject createInfoId(byte id[]) {
- ByteBuffer buf = new ByteBuffer(90);
- buf.append('[').append('<');
- for (int k = 0; k < 16; ++k)
- buf.appendHex(id[k]);
- buf.append('>').append('<');
- id = createDocumentId();
- for (int k = 0; k < 16; ++k)
- buf.appendHex(id[k]);
- buf.append('>').append(']');
- return new PdfLiteral(buf.toByteArray());
- }
-
- public PdfDictionary getEncryptionDictionary() {
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.FILTER, PdfName.STANDARD);
- dic.put(PdfName.O, new PdfLiteral(PdfContentByte.escapeString(ownerKey)));
- dic.put(PdfName.U, new PdfLiteral(PdfContentByte.escapeString(userKey)));
- dic.put(PdfName.P, new PdfNumber(permissions));
- if (mkey.length > 5) {
- dic.put(PdfName.V, new PdfNumber(2));
- dic.put(PdfName.R, new PdfNumber(3));
- dic.put(PdfName.LENGTH, new PdfNumber(128));
- }
- else {
- dic.put(PdfName.V, new PdfNumber(1));
- dic.put(PdfName.R, new PdfNumber(2));
- }
- return dic;
- }
-
- public void prepareRC4Key(byte key[]) {
- prepareRC4Key(key, 0, key.length);
- }
-
- public void prepareRC4Key(byte key[], int off, int len) {
- int index1 = 0;
- int index2 = 0;
- for (int k = 0; k < 256; ++k)
- state[k] = (byte)k;
- x = 0;
- y = 0;
- byte tmp;
- for (int k = 0; k < 256; ++k) {
- index2 = (key[index1 + off] + state[k] + index2) & 255;
- tmp = state[k];
- state[k] = state[index2];
- state[index2] = tmp;
- index1 = (index1 + 1) % len;
- }
- }
-
- public void encryptRC4(byte dataIn[], int off, int len, byte dataOut[]) {
- int length = len + off;
- byte tmp;
- for (int k = off; k < length; ++k) {
- x = (x + 1) & 255;
- y = (state[x] + y) & 255;
- tmp = state[x];
- state[x] = state[y];
- state[y] = tmp;
- dataOut[k] = (byte)(dataIn[k] ^ state[(state[x] + state[y]) & 255]);
- }
- }
-
- public void encryptRC4(byte data[], int off, int len) {
- encryptRC4(data, off, len, data);
- }
-
- public void encryptRC4(byte dataIn[], byte dataOut[]) {
- encryptRC4(dataIn, 0, dataIn.length, dataOut);
- }
-
- public void encryptRC4(byte data[]) {
- encryptRC4(data, 0, data.length, data);
- }
-
- public PdfObject getFileID() {
- return createInfoId(documentID);
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfEncryptionStream.java pdftk-2.01/java/com/lowagie/text/pdf/PdfEncryptionStream.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfEncryptionStream.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfEncryptionStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,91 +0,0 @@
-/*
- * $Id: PdfEncryptionStream.java,v 1.3 2005/02/17 09:20:54 blowagie Exp $
- * $Name: $
- *
- * Copyright 2004 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.FilterOutputStream;
-import java.io.OutputStream;
-import java.io.IOException;
-
-public class PdfEncryptionStream extends FilterOutputStream {
-
- protected PdfEncryption enc;
- private byte buf[] = new byte[1];
-
- public PdfEncryptionStream(OutputStream out, PdfEncryption enc) {
- super(out);
- this.enc = enc;
- }
-
- public void write(byte[] b, int off, int len) throws IOException {
- if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
- throw new IndexOutOfBoundsException();
- enc.encryptRC4(b, off, len);
- out.write(b, off, len);
- }
-
- public void close() throws IOException {
- }
-
- public void write(int b) throws IOException {
- buf[0] = (byte)b;
- write(buf);
- }
-
- public void flush() throws IOException {
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfEncryptor.java pdftk-2.01/java/com/lowagie/text/pdf/PdfEncryptor.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfEncryptor.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfEncryptor.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,182 +0,0 @@
-/*
-/*
- * Copyright 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.OutputStream;
-import java.io.IOException;
-import com.lowagie.text.DocumentException;
-import java.util.HashMap;
-
-/** This class takes any PDF and returns exactly the same but
- * encrypted. All the content, links, outlines, etc, are kept.
- * It is also possible to change the info dictionary.
- */
-public class PdfEncryptor {
-
- private PdfEncryptor(){
- }
-
- /** Entry point to encrypt a PDF document. The encryption parameters are the same as in
- * PdfWriter
. The userPassword and the
- * ownerPassword can be null or have zero length. In this case the ownerPassword
- * is replaced by a random string. The open permissions for the document can be
- * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
- * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
- * The permissions can be combined by ORing them.
- * @param reader the read PDF
- * @param os the output destination
- * @param userPassword the user password. Can be null or empty
- * @param ownerPassword the owner password. Can be null or empty
- * @param permissions the user permissions
- * @param strength128Bits true
for 128 bit key length, false
for 40 bit key length
- * @throws DocumentException on error
- * @throws IOException on error */
- public static void encrypt(PdfReader reader, OutputStream os, byte userPassword[], byte ownerPassword[], int permissions, boolean strength128Bits) throws DocumentException, IOException {
- PdfStamper stamper = new PdfStamper(reader, os);
- stamper.setEncryption(userPassword, ownerPassword, permissions, strength128Bits);
- stamper.close();
- }
-
- /** Entry point to encrypt a PDF document. The encryption parameters are the same as in
- * PdfWriter
. The userPassword and the
- * ownerPassword can be null or have zero length. In this case the ownerPassword
- * is replaced by a random string. The open permissions for the document can be
- * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
- * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
- * The permissions can be combined by ORing them.
- * @param reader the read PDF
- * @param os the output destination
- * @param userPassword the user password. Can be null or empty
- * @param ownerPassword the owner password. Can be null or empty
- * @param permissions the user permissions
- * @param strength128Bits true
for 128 bit key length, false
for 40 bit key length
- * @param newInfo an optional String
map to add or change
- * the info dictionary. Entries with null
- * values delete the key in the original info dictionary
- * @throws DocumentException on error
- * @throws IOException on error
- */
- public static void encrypt(PdfReader reader, OutputStream os, byte userPassword[], byte ownerPassword[], int permissions, boolean strength128Bits, HashMap newInfo) throws DocumentException, IOException {
- PdfStamper stamper = new PdfStamper(reader, os);
- stamper.setEncryption(userPassword, ownerPassword, permissions, strength128Bits);
- stamper.setMoreInfo(newInfo);
- stamper.close();
- }
-
- /** Entry point to encrypt a PDF document. The encryption parameters are the same as in
- * PdfWriter
. The userPassword and the
- * ownerPassword can be null or have zero length. In this case the ownerPassword
- * is replaced by a random string. The open permissions for the document can be
- * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
- * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
- * The permissions can be combined by ORing them.
- * @param reader the read PDF
- * @param os the output destination
- * @param strength true
for 128 bit key length, false
for 40 bit key length
- * @param userPassword the user password. Can be null or empty
- * @param ownerPassword the owner password. Can be null or empty
- * @param permissions the user permissions
- * @throws DocumentException on error
- * @throws IOException on error */
- public static void encrypt(PdfReader reader, OutputStream os, boolean strength, String userPassword, String ownerPassword, int permissions) throws DocumentException, IOException {
- PdfStamper stamper = new PdfStamper(reader, os);
- stamper.setEncryption(strength, userPassword, ownerPassword, permissions);
- stamper.close();
- }
-
- /** Entry point to encrypt a PDF document. The encryption parameters are the same as in
- * PdfWriter
. The userPassword and the
- * ownerPassword can be null or have zero length. In this case the ownerPassword
- * is replaced by a random string. The open permissions for the document can be
- * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
- * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
- * The permissions can be combined by ORing them.
- * @param reader the read PDF
- * @param os the output destination
- * @param strength true
for 128 bit key length, false
for 40 bit key length
- * @param userPassword the user password. Can be null or empty
- * @param ownerPassword the owner password. Can be null or empty
- * @param permissions the user permissions
- * @param newInfo an optional String
map to add or change
- * the info dictionary. Entries with null
- * values delete the key in the original info dictionary
- * @throws DocumentException on error
- * @throws IOException on error
- */
- public static void encrypt(PdfReader reader, OutputStream os, boolean strength, String userPassword, String ownerPassword, int permissions, HashMap newInfo) throws DocumentException, IOException {
- PdfStamper stamper = new PdfStamper(reader, os);
- stamper.setEncryption(strength, userPassword, ownerPassword, permissions);
- stamper.setMoreInfo(newInfo);
- stamper.close();
- }
-
- /**
- * Give you a verbose analysis of the permissions.
- * @param permissions the permissions value of a PDF file
- * @return a String that explains the meaning of the permissions value
- */
- public static String getPermissionsVerbose(int permissions) {
- StringBuffer buf = new StringBuffer("Allowed:");
- if ((PdfWriter.AllowPrinting & permissions) == PdfWriter.AllowPrinting) buf.append(" Printing");
- if ((PdfWriter.AllowModifyContents & permissions) == PdfWriter.AllowModifyContents) buf.append(" Modify contents");
- if ((PdfWriter.AllowCopy & permissions) == PdfWriter.AllowCopy) buf.append(" Copy");
- if ((PdfWriter.AllowModifyAnnotations & permissions) == PdfWriter.AllowModifyAnnotations) buf.append(" Modify annotations");
- if ((PdfWriter.AllowFillIn & permissions) == PdfWriter.AllowFillIn) buf.append(" Fill in");
- if ((PdfWriter.AllowScreenReaders & permissions) == PdfWriter.AllowScreenReaders) buf.append(" Screen readers");
- if ((PdfWriter.AllowAssembly & permissions) == PdfWriter.AllowAssembly) buf.append(" Assembly");
- if ((PdfWriter.AllowDegradedPrinting & permissions) == PdfWriter.AllowDegradedPrinting) buf.append(" Degraded printing");
- return buf.toString();
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfException.java pdftk-2.01/java/com/lowagie/text/pdf/PdfException.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfException.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,92 +0,0 @@
-/*
- * $Id: PdfException.java,v 1.22 2002/06/20 13:30:25 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.DocumentException;
-
-/**
- * Signals that an unspecified problem while constructing a PDF document.
- *
- * @see BadPdfFormatException
- */
-
-public class PdfException extends DocumentException {
-
- // constructors
-
- public PdfException(Exception ex) {
- super(ex);
- }
-
- /**
- * Constructs a PdfException
whithout a message.
- */
-
- PdfException() {
- super();
- }
-
-/**
- * Constructs a PdfException
with a message.
- *
- * @param message a message describing the exception
- */
-
- PdfException(String message) {
- super(message);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfFileSpecification.java pdftk-2.01/java/com/lowagie/text/pdf/PdfFileSpecification.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfFileSpecification.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfFileSpecification.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,214 +0,0 @@
-/*
- * Copyright 2003 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.*;
-import java.net.URL;
-/** Specifies a file or an URL. The file can be extern or embedded.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfFileSpecification extends PdfDictionary {
- protected PdfWriter writer;
- protected PdfIndirectReference ref;
-
- /** Creates a new instance of PdfFileSpecification. The static methods are preferred. */
- public PdfFileSpecification() {
-
- // ssteward: for Acrobat 5 compatibility, set Type to "F" instead
- // of the (more correct) "Filesec"; this quirk is documented
- // in Implementation Note 38 on page 955 of the PDF Ref. ver. 1.5;
- // Acrobat 6 (and later) accept either "Filespec" or "F"
- //super(PdfName.FILESPEC);
- super(PdfName.F);
- }
-
- /**
- * Creates a file specification of type URL.
- * @param writer the PdfWriter
- * @param url the URL
- * @return the file specification
- */
- public static PdfFileSpecification url(PdfWriter writer, String url) {
- PdfFileSpecification fs = new PdfFileSpecification();
- fs.writer = writer;
- fs.put(PdfName.FS, PdfName.URL);
- fs.put(PdfName.F, new PdfString(url));
- return fs;
- }
-
- /**
- * Creates a file specification with the file embedded. The file may
- * come from the file system or from a byte array. The data is flate compressed.
- * @param writer the PdfWriter
- * @param filePath the file path
- * @param fileDisplay the file information that is presented to the user
- * @param fileStore the byte array with the file. If it is not null
- * it takes precedence over filePath
- * @throws IOException on error
- * @return the file specification
- */
- public static PdfFileSpecification fileEmbedded(PdfWriter writer, String filePath, String fileDisplay, byte fileStore[]) throws IOException {
- return fileEmbedded(writer, filePath, fileDisplay, fileStore, true);
- }
-
-
- /**
- * Creates a file specification with the file embedded. The file may
- * come from the file system or from a byte array.
- * @param writer the PdfWriter
- * @param filePath the file path
- * @param fileDisplay the file information that is presented to the user
- * @param fileStore the byte array with the file. If it is not null
- * it takes precedence over filePath
- * @param compress sets the compression on the data. Multimedia content will benefit little
- * from compression
- * @throws IOException on error
- * @return the file specification
- */
- public static PdfFileSpecification fileEmbedded(PdfWriter writer, String filePath, String fileDisplay, byte fileStore[], boolean compress) throws IOException {
- PdfFileSpecification fs = new PdfFileSpecification();
- fs.writer = writer;
-
- PdfString fileDisplayPdf= new PdfString( fileDisplay, PdfObject.TEXT_PDFDOCENCODING );
- PdfString fileDisplayPdfUnicode= new PdfString( fileDisplay, PdfObject.TEXT_UNICODE );
- fs.put(PdfName.F, fileDisplayPdf);
- fs.put(PdfName.UF, fileDisplayPdfUnicode); // introduced in PDF 1.7
-
- PdfStream stream;
- InputStream in = null;
- PdfIndirectReference ref;
- PdfIndirectReference refFileLength;
- try {
- refFileLength = writer.getPdfIndirectReference();
- if (fileStore == null) {
- File file = new File(filePath);
- if (file.canRead()) {
- in = new FileInputStream(filePath);
- }
- else {
- if (filePath.startsWith("file:/") || filePath.startsWith("http://") || filePath.startsWith("https://") || filePath.startsWith("jar:")) {
- in = new URL(filePath).openStream();
- }
- else {
- in = BaseFont.getResourceStream(filePath);
- if (in == null)
- throw new IOException(filePath + " not found as file or resource.");
- }
- }
- stream = new PdfStream(in, writer);
- }
- else
- stream = new PdfStream(fileStore);
- stream.put(PdfName.TYPE, PdfName.EMBEDDEDFILE);
- if (compress)
- stream.flateCompress();
- stream.put(PdfName.PARAMS, refFileLength);
- ref = writer.addToBody(stream).getIndirectReference();
- if (fileStore == null) {
- stream.writeLength();
- }
- PdfDictionary params = new PdfDictionary();
- params.put(PdfName.SIZE, new PdfNumber(stream.getRawLength()));
- writer.addToBody(params, refFileLength);
- }
- finally {
- if (in != null)
- try{in.close();}catch(Exception e){}
- }
- PdfDictionary f = new PdfDictionary();
- f.put(PdfName.F, ref);
- fs.put(PdfName.EF, f);
- return fs;
- }
-
- /**
- * Creates a file specification for an external file.
- * @param writer the PdfWriter
- * @param filePath the file path
- * @return the file specification
- */
- public static PdfFileSpecification fileExtern(PdfWriter writer, String filePath) {
- PdfFileSpecification fs = new PdfFileSpecification();
- fs.writer = writer;
- fs.put(PdfName.F, new PdfString(filePath));
- return fs;
- }
-
- /**
- * Gets the indirect reference to this file specification.
- * Multiple invocations will retrieve the same value.
- * @throws IOException on error
- * @return the indirect reference
- */
- public PdfIndirectReference getReference() throws IOException {
- if (ref != null)
- return ref;
- ref = writer.addToBody(this).getIndirectReference();
- return ref;
- }
-
- /**
- * Sets the file name (the key /F) string as an hex representation
- * to support multi byte file names. The name must heve th slash and
- * backslash escaped according to the file specification rules
- * @param fileName the file name as a byte array
- */
- /* ssteward: appears that fileName should hold the multi-byte data -- it isn't converted,
- but is packed literally into the PDF;
- public void setMultiByteFileName(byte fileName[]) {
- put(PdfName.F, new PdfString(fileName).setHexWriting(true));
- }
- */
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfFont.java pdftk-2.01/java/com/lowagie/text/pdf/PdfFont.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfFont.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfFont.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,206 +0,0 @@
-/*
- * $Id: PdfFont.java,v 1.30 2002/07/09 11:28:23 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-// import com.lowagie.text.Image; ssteward: dropped in 1.44
-import com.lowagie.text.ExceptionConverter;
-
-/**
- * PdfFont
is the Pdf Font object.
- *
- * Limitation: in this class only base 14 Type 1 fonts (courier, courier bold, courier oblique,
- * courier boldoblique, helvetica, helvetica bold, helvetica oblique, helvetica boldoblique,
- * symbol, times roman, times bold, times italic, times bolditalic, zapfdingbats) and their
- * standard encoding (standard, MacRoman, (MacExpert,) WinAnsi) are supported.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 7.7 (page 198-203).
- *
- * @see PdfName
- * @see PdfDictionary
- * @see BadPdfFormatException
- */
-
-class PdfFont implements Comparable {
-
-
- /** the font metrics. */
- private BaseFont font;
-
- /** the size. */
- private float size;
-
- /** an image. */
- // protected Image image; ssteward: dropped in 1.44
-
- protected float hScale = 1;
-
- // constructors
-
- PdfFont(BaseFont bf, float size) {
- this.size = size;
- font = bf;
- }
-
- // methods
-
- /**
- * Compares this PdfFont
with another
- *
- * @param object the other PdfFont
- * @return a value
- */
-
- public int compareTo(Object object) {
- /* ssteward: dropped in 1.44
- if (image != null)
- return 0;
- */
- if (object == null) {
- return -1;
- }
- PdfFont pdfFont;
- try {
- pdfFont = (PdfFont) object;
- if (font != pdfFont.font) {
- return 1;
- }
- if (this.size() != pdfFont.size()) {
- return 2;
- }
- return 0;
- }
- catch(ClassCastException cce) {
- return -2;
- }
- }
-
- /**
- * Returns the size of this font.
- *
- * @return a size
- */
-
- float size() {
- return size;
- /* ssteward: dropped in 1.44
- if (image == null)
- return size;
- else {
- return image.scaledHeight();
- }
- */
- }
-
- /**
- * Returns the approximative width of 1 character of this font.
- *
- * @return a width in Text Space
- */
-
- float width() {
- return width(' ');
- }
-
- /**
- * Returns the width of a certain character of this font.
- *
- * @param character a certain character
- * @return a width in Text Space
- */
-
- float width(char character) {
- return font.getWidthPoint(character, size) * hScale;
- /* ssteward: dropped in 1.44
- if (image == null)
- return font.getWidthPoint(character, size) * hScale;
- else
- return image.scaledWidth();
- */
- }
-
- float width(String s) {
- return font.getWidthPoint(s, size) * hScale;
- /* ssteward: dropped in 1.44
- if (image == null)
- return font.getWidthPoint(s, size) * hScale;
- else
- return image.scaledWidth();
- */
- }
-
- BaseFont getFont() {
- return font;
- }
- /* ssteward: dropped in 1.44
- void setImage(Image image) {
- this.image = image;
- }
- */
-
- static PdfFont getDefaultFont() {
- try {
- BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, false);
- return new PdfFont(bf, 12);
- }
- catch (Exception ee) {
- throw new ExceptionConverter(ee);
- }
- }
- void setHorizontalScaling(float hScale) {
- this.hScale = hScale;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfFormField.java pdftk-2.01/java/com/lowagie/text/pdf/PdfFormField.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfFormField.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfFormField.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,353 +0,0 @@
-/*
- * Copyright 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import com.lowagie.text.Rectangle;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/** Implements form fields.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfFormField extends PdfAnnotation {
-
- public static final int FF_READ_ONLY = 1;
- public static final int FF_REQUIRED = 2;
- public static final int FF_NO_EXPORT = 4;
- public static final int FF_NO_TOGGLE_TO_OFF = 16384;
- public static final int FF_RADIO = 32768;
- public static final int FF_PUSHBUTTON = 65536;
- public static final int FF_MULTILINE = 4096;
- public static final int FF_PASSWORD = 8192;
- public static final int FF_COMBO = 131072;
- public static final int FF_EDIT = 262144;
- public static final int FF_FILESELECT = 1048576;
- public static final int FF_MULTISELECT = 2097152;
- public static final int FF_DONOTSPELLCHECK = 4194304;
- public static final int FF_DONOTSCROLL = 8388608;
- public static final int FF_COMB = 16777216;
- public static final int FF_RADIOSINUNISON = 1 << 25;
- public static final int Q_LEFT = 0;
- public static final int Q_CENTER = 1;
- public static final int Q_RIGHT = 2;
- public static final int MK_NO_ICON = 0;
- public static final int MK_NO_CAPTION = 1;
- public static final int MK_CAPTION_BELOW = 2;
- public static final int MK_CAPTION_ABOVE = 3;
- public static final int MK_CAPTION_RIGHT = 4;
- public static final int MK_CAPTION_LEFT = 5;
- public static final int MK_CAPTION_OVERLAID = 6;
- public static final PdfName IF_SCALE_ALWAYS = PdfName.A;
- public static final PdfName IF_SCALE_BIGGER = PdfName.B;
- public static final PdfName IF_SCALE_SMALLER = PdfName.S;
- public static final PdfName IF_SCALE_NEVER = PdfName.N;
- public static final PdfName IF_SCALE_ANAMORPHIC = PdfName.A;
- public static final PdfName IF_SCALE_PROPORTIONAL = PdfName.P;
- public static final boolean MULTILINE = true;
- public static final boolean SINGLELINE = false;
- public static final boolean PLAINTEXT = false;
- public static final boolean PASSWORD = true;
- static PdfName mergeTarget[] = {PdfName.FONT, PdfName.XOBJECT, PdfName.COLORSPACE, PdfName.PATTERN};
-
- /** Holds value of property parent. */
- protected PdfFormField parent;
-
- protected ArrayList kids;
-
-/**
- * Constructs a new PdfAnnotation
of subtype link (Action).
- */
-
- public PdfFormField(PdfWriter writer, float llx, float lly, float urx, float ury, PdfAction action) {
- super(writer, llx, lly, urx, ury, action);
- put(PdfName.TYPE, PdfName.ANNOT);
- put(PdfName.SUBTYPE, PdfName.WIDGET);
- annotation = true;
- }
-
- /** Creates new PdfFormField */
- protected PdfFormField(PdfWriter writer) {
- super(writer, null);
- form = true;
- annotation = false;
- }
-
- public void setWidget(Rectangle rect, PdfName highlight) {
- put(PdfName.TYPE, PdfName.ANNOT);
- put(PdfName.SUBTYPE, PdfName.WIDGET);
- put(PdfName.RECT, new PdfRectangle(rect));
- annotation = true;
- if (highlight != null && !highlight.equals(HIGHLIGHT_INVERT))
- put(PdfName.H, highlight);
- }
-
- public static PdfFormField createEmpty(PdfWriter writer) {
- PdfFormField field = new PdfFormField(writer);
- return field;
- }
-
- public void setButton(int flags) {
- put(PdfName.FT, PdfName.BTN);
- if (flags != 0)
- put(PdfName.FF, new PdfNumber(flags));
- }
-
- protected static PdfFormField createButton(PdfWriter writer, int flags) {
- PdfFormField field = new PdfFormField(writer);
- field.setButton(flags);
- return field;
- }
-
- public static PdfFormField createPushButton(PdfWriter writer) {
- return createButton(writer, FF_PUSHBUTTON);
- }
-
- public static PdfFormField createCheckBox(PdfWriter writer) {
- return createButton(writer, 0);
- }
-
- public static PdfFormField createRadioButton(PdfWriter writer, boolean noToggleToOff) {
- return createButton(writer, FF_RADIO + (noToggleToOff ? FF_NO_TOGGLE_TO_OFF : 0));
- }
-
- public static PdfFormField createTextField(PdfWriter writer, boolean multiline, boolean password, int maxLen) {
- PdfFormField field = new PdfFormField(writer);
- field.put(PdfName.FT, PdfName.TX);
- int flags = (multiline ? FF_MULTILINE : 0);
- flags += (password ? FF_PASSWORD : 0);
- field.put(PdfName.FF, new PdfNumber(flags));
- if (maxLen > 0)
- field.put(PdfName.MAXLEN, new PdfNumber(maxLen));
- return field;
- }
-
- protected static PdfFormField createChoice(PdfWriter writer, int flags, PdfArray options, int topIndex) {
- PdfFormField field = new PdfFormField(writer);
- field.put(PdfName.FT, PdfName.CH);
- field.put(PdfName.FF, new PdfNumber(flags));
- field.put(PdfName.OPT, options);
- if (topIndex > 0)
- field.put(PdfName.TI, new PdfNumber(topIndex));
- return field;
- }
-
- public static PdfFormField createList(PdfWriter writer, String options[], int topIndex) {
- return createChoice(writer, 0, processOptions(options), topIndex);
- }
-
- public static PdfFormField createList(PdfWriter writer, String options[][], int topIndex) {
- return createChoice(writer, 0, processOptions(options), topIndex);
- }
-
- public static PdfFormField createCombo(PdfWriter writer, boolean edit, String options[], int topIndex) {
- return createChoice(writer, FF_COMBO + (edit ? FF_EDIT : 0), processOptions(options), topIndex);
- }
-
- public static PdfFormField createCombo(PdfWriter writer, boolean edit, String options[][], int topIndex) {
- return createChoice(writer, FF_COMBO + (edit ? FF_EDIT : 0), processOptions(options), topIndex);
- }
-
- protected static PdfArray processOptions(String options[]) {
- PdfArray array = new PdfArray();
- for (int k = 0; k < options.length; ++k) {
- array.add(new PdfString(options[k], PdfObject.TEXT_UNICODE));
- }
- return array;
- }
-
- protected static PdfArray processOptions(String options[][]) {
- PdfArray array = new PdfArray();
- for (int k = 0; k < options.length; ++k) {
- String subOption[] = options[k];
- PdfArray ar2 = new PdfArray(new PdfString(subOption[0], PdfObject.TEXT_UNICODE));
- ar2.add(new PdfString(subOption[1], PdfObject.TEXT_UNICODE));
- array.add(ar2);
- }
- return array;
- }
-
- public static PdfFormField createSignature(PdfWriter writer) {
- PdfFormField field = new PdfFormField(writer);
- field.put(PdfName.FT, PdfName.SIG);
- return field;
- }
-
- /** Getter for property parent.
- * @return Value of property parent.
- */
- public PdfFormField getParent() {
- return parent;
- }
-
- public void addKid(PdfFormField field) {
- field.parent = this;
- if (kids == null)
- kids = new ArrayList();
- kids.add(field);
- }
-
- ArrayList getKids() {
- return kids;
- }
-
- public int setFieldFlags(int flags) {
- PdfNumber obj = (PdfNumber)get(PdfName.FF);
- int old;
- if (obj == null)
- old = 0;
- else
- old = obj.intValue();
- int v = old | flags;
- put(PdfName.FF, new PdfNumber(v));
- return old;
- }
-
- public void setValueAsString(String s) {
- put(PdfName.V, new PdfString(s, PdfObject.TEXT_UNICODE));
- }
-
- public void setValueAsName(String s) {
- put(PdfName.V, new PdfName(s));
- }
-
- public void setValue(PdfSignature sig) {
- put(PdfName.V, sig);
- }
-
- public void setDefaultValueAsString(String s) {
- put(PdfName.DV, new PdfString(s, PdfObject.TEXT_UNICODE));
- }
-
- public void setDefaultValueAsName(String s) {
- put(PdfName.DV, new PdfName(s));
- }
-
- public void setFieldName(String s) {
- if (s != null)
- put(PdfName.T, new PdfString(s, PdfObject.TEXT_UNICODE));
- }
-
- public void setUserName(String s) {
- put(PdfName.TU, new PdfString(s, PdfObject.TEXT_UNICODE));
- }
-
- public void setMappingName(String s) {
- put(PdfName.TM, new PdfString(s, PdfObject.TEXT_UNICODE));
- }
-
- public void setQuadding(int v) {
- put(PdfName.Q, new PdfNumber(v));
- }
-
- static void mergeResources(PdfDictionary result, PdfDictionary source, PdfStamperImp writer) {
- PdfDictionary dic = null;
- PdfDictionary res = null;
- PdfName target = null;
- for (int k = 0; k < mergeTarget.length; ++k) {
- target = mergeTarget[k];
- PdfDictionary pdfDict = (PdfDictionary)PdfReader.getPdfObject(source.get(target));
- if ((dic = pdfDict) != null) {
- if ((res = (PdfDictionary)PdfReader.getPdfObject(result.get(target), result)) == null) {
- res = new PdfDictionary();
- }
- res.mergeDifferent(dic);
- result.put(target, res);
- if (writer != null)
- writer.markUsed(res);
- }
- }
- }
-
- static void mergeResources(PdfDictionary result, PdfDictionary source) {
- mergeResources(result, source, null);
- }
-
- void setUsed() {
- used = true;
- if (parent != null)
- put(PdfName.PARENT, parent.getIndirectReference());
- if (kids != null) {
- PdfArray array = new PdfArray();
- for (int k = 0; k < kids.size(); ++k)
- array.add(((PdfFormField)kids.get(k)).getIndirectReference());
- put(PdfName.KIDS, array);
- }
- if (templates == null)
- return;
- PdfDictionary dic = new PdfDictionary();
- for (Iterator it = templates.keySet().iterator(); it.hasNext();) {
- PdfTemplate template = (PdfTemplate)it.next();
- mergeResources(dic, (PdfDictionary)template.getResources());
- }
- put(PdfName.DR, dic);
- }
-
- public static PdfAnnotation shallowDuplicate(PdfAnnotation annot) {
- PdfAnnotation dup;
- if (annot.isForm()) {
- dup = new PdfFormField(annot.writer);
- PdfFormField dupField = (PdfFormField)dup;
- PdfFormField srcField = (PdfFormField)annot;
- dupField.parent = srcField.parent;
- dupField.kids = srcField.kids;
- }
- else
- dup = new PdfAnnotation(annot.writer, null);
- dup.merge(annot);
- dup.form = annot.form;
- dup.annotation = annot.annotation;
- dup.templates = annot.templates;
- return dup;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfFormXObject.java pdftk-2.01/java/com/lowagie/text/pdf/PdfFormXObject.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfFormXObject.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfFormXObject.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,109 +0,0 @@
-/*
- * $Id: PdfFormXObject.java,v 1.58 2005/07/16 16:49:22 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * PdfFormObject
is a type of XObject containing a template-object.
- */
-
-public class PdfFormXObject extends PdfStream {
-
- // public static final variables
-
-/** This is a PdfNumber representing 0. */
- public static final PdfNumber ZERO = new PdfNumber(0);
-
-/** This is a PdfNumber representing 1. */
- public static final PdfNumber ONE = new PdfNumber(1);
-
-/** This is the 1 - matrix. */
- public static final PdfLiteral MATRIX = new PdfLiteral("[1 0 0 1 0 0]");
-
- // membervariables
-
-
- // constructor
-
-/**
- * Constructs a PdfFormXObject
-object.
- *
- * @param template the template
- */
-
- PdfFormXObject(PdfTemplate template) // throws BadPdfFormatException
- {
- super();
- put(PdfName.TYPE, PdfName.XOBJECT);
- put(PdfName.SUBTYPE, PdfName.FORM);
- put(PdfName.RESOURCES, template.getResources());
- put(PdfName.BBOX, new PdfRectangle(template.getBoundingBox()));
- put(PdfName.FORMTYPE, ONE);
- if (template.getLayer() != null)
- put(PdfName.OC, template.getLayer().getRef());
- if (template.getGroup() != null)
- put(PdfName.GROUP, template.getGroup());
- PdfArray matrix = template.getMatrix();
- if (matrix == null)
- put(PdfName.MATRIX, MATRIX);
- else
- put(PdfName.MATRIX, matrix);
- bytes = template.toPdf(null);
- put(PdfName.LENGTH, new PdfNumber(bytes.length));
- flateCompress();
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfFunction.java pdftk-2.01/java/com/lowagie/text/pdf/PdfFunction.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfFunction.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfFunction.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.ExceptionConverter;
-import java.io.IOException;
-/** Implements PDF functions.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfFunction {
-
- protected PdfWriter writer;
-
- protected PdfIndirectReference reference;
-
- protected PdfDictionary dictionary;
-
- /** Creates new PdfFunction */
- protected PdfFunction(PdfWriter writer) {
- this.writer = writer;
- }
-
- PdfIndirectReference getReference() {
- try {
- if (reference == null) {
- reference = writer.addToBody(dictionary).getIndirectReference();
- }
- }
- catch (IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- return reference;
- }
-
- public static PdfFunction type0(PdfWriter writer, float domain[], float range[], int size[],
- int bitsPerSample, int order, float encode[], float decode[], byte stream[]) {
- PdfFunction func = new PdfFunction(writer);
- func.dictionary = new PdfStream(stream);
- ((PdfStream)func.dictionary).flateCompress();
- func.dictionary.put(PdfName.FUNCTIONTYPE, new PdfNumber(0));
- func.dictionary.put(PdfName.m_DOMAIN, new PdfArray(domain)); // ssteward
- func.dictionary.put(PdfName.RANGE, new PdfArray(range));
- func.dictionary.put(PdfName.SIZE, new PdfArray(size));
- func.dictionary.put(PdfName.BITSPERSAMPLE, new PdfNumber(bitsPerSample));
- if (order != 1)
- func.dictionary.put(PdfName.ORDER, new PdfNumber(order));
- if (encode != null)
- func.dictionary.put(PdfName.ENCODE, new PdfArray(encode));
- if (decode != null)
- func.dictionary.put(PdfName.DECODE, new PdfArray(decode));
- return func;
- }
-
- public static PdfFunction type2(PdfWriter writer, float domain[], float range[], float c0[], float c1[], float n) {
- PdfFunction func = new PdfFunction(writer);
- func.dictionary = new PdfDictionary();
- func.dictionary.put(PdfName.FUNCTIONTYPE, new PdfNumber(2));
- func.dictionary.put(PdfName.m_DOMAIN, new PdfArray(domain)); // ssteward
- if (range != null)
- func.dictionary.put(PdfName.RANGE, new PdfArray(range));
- if (c0 != null)
- func.dictionary.put(PdfName.C0, new PdfArray(c0));
- if (c1 != null)
- func.dictionary.put(PdfName.C1, new PdfArray(c1));
- func.dictionary.put(PdfName.N, new PdfNumber(n));
- return func;
- }
-
- public static PdfFunction type3(PdfWriter writer, float domain[], float range[], PdfFunction functions[], float bounds[], float encode[]) {
- PdfFunction func = new PdfFunction(writer);
- func.dictionary = new PdfDictionary();
- func.dictionary.put(PdfName.FUNCTIONTYPE, new PdfNumber(3));
- func.dictionary.put(PdfName.m_DOMAIN, new PdfArray(domain)); // ssteward
- if (range != null)
- func.dictionary.put(PdfName.RANGE, new PdfArray(range));
- PdfArray array = new PdfArray();
- for (int k = 0; k < functions.length; ++k)
- array.add(functions[k].getReference());
- func.dictionary.put(PdfName.FUNCTIONS, array);
- func.dictionary.put(PdfName.BOUNDS, new PdfArray(bounds));
- func.dictionary.put(PdfName.ENCODE, new PdfArray(encode));
- return func;
- }
-
- public static PdfFunction type4(PdfWriter writer, float domain[], float range[], String postscript) {
- byte b[] = new byte[postscript.length()];
- for (int k = 0; k < b.length; ++k)
- b[k] = (byte)postscript.charAt(k);
- PdfFunction func = new PdfFunction(writer);
- func.dictionary = new PdfStream(b);
- ((PdfStream)func.dictionary).flateCompress();
- func.dictionary.put(PdfName.FUNCTIONTYPE, new PdfNumber(4));
- func.dictionary.put(PdfName.m_DOMAIN, new PdfArray(domain)); // ssteward
- func.dictionary.put(PdfName.RANGE, new PdfArray(range));
- return func;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfGState.java pdftk-2.01/java/com/lowagie/text/pdf/PdfGState.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfGState.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfGState.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,150 +0,0 @@
-/*
- * Copyright 2003 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-/** The graphic state dictionary.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfGState extends PdfDictionary {
- /** A possible blend mode */
- public static final PdfName BM_NORMAL = new PdfName("Normal");
- /** A possible blend mode */
- public static final PdfName BM_COMPATIBLE = new PdfName("Compatible");
- /** A possible blend mode */
- public static final PdfName BM_MULTIPLY = new PdfName("Multiply");
- /** A possible blend mode */
- public static final PdfName BM_SCREEN = new PdfName("Screen");
- /** A possible blend mode */
- public static final PdfName BM_OVERLAY = new PdfName("Overlay");
- /** A possible blend mode */
- public static final PdfName BM_DARKEN = new PdfName("Darken");
- /** A possible blend mode */
- public static final PdfName BM_LIGHTEN = new PdfName("Lighten");
- /** A possible blend mode */
- public static final PdfName BM_COLORDODGE = new PdfName("ColorDodge");
- /** A possible blend mode */
- public static final PdfName BM_COLORBURN = new PdfName("ColorBurn");
- /** A possible blend mode */
- public static final PdfName BM_HARDLIGHT = new PdfName("HardLight");
- /** A possible blend mode */
- public static final PdfName BM_SOFTLIGHT = new PdfName("SoftLight");
- /** A possible blend mode */
- public static final PdfName BM_DIFFERENCE = new PdfName("Difference");
- /** A possible blend mode */
- public static final PdfName BM_EXCLUSION = new PdfName("Exclusion");
-
- /**
- * Sets the flag whether to apply overprint for stroking.
- * @param ov
- */
- public void setOverPrintStroking(boolean ov) {
- put(PdfName.OP, ov ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
- }
-
- /**
- * Sets the flag whether to apply overprint for non stroking painting operations.
- * @param ov
- */
- public void setOverPrintNonStroking(boolean ov) {
- put(PdfName.op, ov ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
- }
-
- /**
- * Sets the current stroking alpha constant, specifying the constant shape or
- * constant opacity value to be used for stroking operations in the transparent
- * imaging model.
- * @param n
- */
- public void setStrokeOpacity(float n) {
- put(PdfName.CA, new PdfNumber(n));
- }
-
- /**
- * Sets the current stroking alpha constant, specifying the constant shape or
- * constant opacity value to be used for nonstroking operations in the transparent
- * imaging model.
- * @param n
- */
- public void setFillOpacity(float n) {
- put(PdfName.ca, new PdfNumber(n));
- }
-
- /**
- * The alpha source flag specifying whether the current soft mask
- * and alpha constant are to be interpreted as shape values (true)
- * or opacity values (false).
- * @param v
- */
- public void setAlphaIsShape(boolean v) {
- put(PdfName.AIS, v ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
- }
-
- /**
- * Determines the behaviour of overlapping glyphs within a text object
- * in the transparent imaging model.
- * @param v
- */
- public void setTextKnockout(boolean v) {
- put(PdfName.TK, v ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
- }
-
- /**
- * The current blend mode to be used in the transparent imaging model.
- * @param bm
- */
- public void setBlendMode(PdfName bm) {
- put(PdfName.BM, bm);
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfImportedPage.java pdftk-2.01/java/com/lowagie/text/pdf/PdfImportedPage.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfImportedPage.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfImportedPage.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,156 +0,0 @@
-/*
- * $Id: PdfImportedPage.java,v 1.14 2002/06/20 13:30:25 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-// import com.lowagie.text.Image; ssteward: dropped in 1.44
-import java.io.IOException;
-
-/** Represents an imported page.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfImportedPage extends com.lowagie.text.pdf.PdfTemplate {
-
- PdfReaderInstance readerInstance;
- int pageNumber;
-
- PdfImportedPage(PdfReaderInstance readerInstance, PdfWriter writer, int pageNumber) {
- this.readerInstance = readerInstance;
- this.pageNumber = pageNumber;
- thisReference = writer.getPdfIndirectReference();
- bBox = readerInstance.getReader().getPageSize(pageNumber);
- type = TYPE_IMPORTED;
- }
-
- /** Reads the content from this PdfImportedPage
-object from a reader.
- *
- * @return self
- *
- */
- public PdfImportedPage getFromReader() {
- return this;
- }
-
- public int getPageNumber() {
- return pageNumber;
- }
-
-
- /** Always throws an error. This operation is not allowed.
- * @param image dummy
- * @param a dummy
- * @param b dummy
- * @param c dummy
- * @param d dummy
- * @param e dummy
- * @param f dummy
- * @throws DocumentException dummy */
- /* ssteward: dropped in 1.44
- public void addImage(Image image, float a, float b, float c, float d, float e, float f) throws DocumentException {
- throwError();
- }
- */
-
- /** Always throws an error. This operation is not allowed.
- * @param template dummy
- * @param a dummy
- * @param b dummy
- * @param c dummy
- * @param d dummy
- * @param e dummy
- * @param f dummy */
- public void addTemplate(PdfTemplate template, float a, float b, float c, float d, float e, float f) {
- throwError();
- }
-
- /** Always throws an error. This operation is not allowed.
- * @return dummy */
- public PdfContentByte getDuplicate() {
- throwError();
- return null;
- }
-
- PdfStream getFormXObject() throws IOException {
- return readerInstance.getFormXObject(pageNumber);
- }
-
- public void setColorFill(PdfSpotColor sp, float tint) {
- throwError();
- }
-
- public void setColorStroke(PdfSpotColor sp, float tint) {
- throwError();
- }
-
- PdfObject getResources() {
- return readerInstance.getResources(pageNumber);
- }
-
- /** Always throws an error. This operation is not allowed.
- * @param bf dummy
- * @param size dummy */
- public void setFontAndSize(BaseFont bf, float size) {
- throwError();
- }
-
- void throwError() {
- throw new RuntimeException("Content can not be added to a PdfImportedPage.");
- }
-
- PdfReaderInstance getPdfReaderInstance() {
- return readerInstance;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfIndirectObject.java pdftk-2.01/java/com/lowagie/text/pdf/PdfIndirectObject.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfIndirectObject.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfIndirectObject.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,178 +0,0 @@
-/*
- * $Id: PdfIndirectObject.java,v 1.35 2003/05/02 09:01:25 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import com.lowagie.text.DocWriter;
-
-/**
- * PdfIndirectObject
is the Pdf indirect object.
- *
- * An indirect object is an object that has been labeled so that it can be referenced by
- * other objects. Any type of PdfObject
may be labeled as an indirect object.
- * An indirect object consists of an object identifier, a direct object, and the endobj
- * keyword. The object identifier consists of an integer object number , an integer
- * generation number , and the obj keyword.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 4.10 (page 53).
- *
- * @see PdfObject
- * @see PdfIndirectReference
- */
-
-public class PdfIndirectObject {
-
- // membervariables
-
-/** The object number */
- protected int number;
-
-/** the generation number */
- protected int generation = 0;
-
- static final byte STARTOBJ[] = DocWriter.getISOBytes(" obj "); // ssteward
- static final byte ENDOBJ[] = DocWriter.getISOBytes("\nendobj "); // ssteward
- static final int SIZEOBJ = STARTOBJ.length + ENDOBJ.length;
- PdfObject object;
- PdfWriter writer;
-
- // constructors
-
-/**
- * Constructs a PdfIndirectObject
.
- *
- * @param number the object number
- * @param object the direct object
- */
-
- PdfIndirectObject(int number, PdfObject object, PdfWriter writer) {
- this(number, 0, object, writer);
- }
-
- PdfIndirectObject(PdfIndirectReference ref, PdfObject object, PdfWriter writer) {
- this(ref.getNumber(),ref.getGeneration(),object,writer);
- }
-/**
- * Constructs a PdfIndirectObject
.
- *
- * @param number the object number
- * @param generation the generation number
- * @param object the direct object
- */
-
- PdfIndirectObject(int number, int generation, PdfObject object, PdfWriter writer) {
- this.writer = writer;
- this.number = number;
- this.generation = generation;
- this.object = object;
- PdfEncryption crypto = null;
- if (writer != null)
- crypto = writer.getEncryption();
- if (crypto != null) {
- crypto.setHashKey(number, generation);
- }
- }
-
- // methods
-
-/**
- * Return the length of this PdfIndirectObject
.
- *
- * @return the length of the PDF-representation of this indirect object.
- */
-
-// public int length() {
-// if (isStream)
-// return bytes.size() + SIZEOBJ + stream.getStreamLength(writer);
-// else
-// return bytes.size();
-// }
-
-
-/**
- * Returns a PdfIndirectReference
to this PdfIndirectObject
.
- *
- * @return a PdfIndirectReference
- */
-
- public PdfIndirectReference getIndirectReference() {
- return new PdfIndirectReference(object.type(), number, generation);
- }
-
-/**
- * Writes eficiently to a stream
- *
- * @param os the stream to write to
- * @throws IOException on write error
- */
- void writeTo(OutputStream os) throws IOException
- {
- // ssteward: don't os.write() anything here, before the number, or you'll throw off the xref position
- os.write(DocWriter.getISOBytes(String.valueOf(number)));
- os.write(' ');
- os.write(DocWriter.getISOBytes(String.valueOf(generation)));
- os.write(STARTOBJ);
- // ssteward
- //int type = object.type();
- //if (type != PdfObject.ARRAY && type != PdfObject.DICTIONARY && type != PdfObject.NAME && type != PdfObject.STRING)
- // os.write(' ');
- object.toPdf(writer, os);
- os.write(ENDOBJ);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfIndirectReference.java pdftk-2.01/java/com/lowagie/text/pdf/PdfIndirectReference.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfIndirectReference.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfIndirectReference.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,135 +0,0 @@
-/*
- * $Id: PdfIndirectReference.java,v 1.22 2002/06/20 13:30:25 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * PdfIndirectReference
contains a reference to a PdfIndirectObject
.
- *
- * Any object used as an element of an array or as a value in a dictionary may be specified
- * by either a direct object of an indirect reference. An indirect reference is a reference
- * to an indirect object, and consists of the indirect object's object number, generation number
- * and the R keyword.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 4.11 (page 54).
- *
- * @see PdfObject
- * @see PdfIndirectObject
- */
-
-public class PdfIndirectReference extends PdfObject {
-
- // membervariables
-
-/** the object number */
- protected int number;
-
-/** the generation number */
- protected int generation = 0;
-
- // constructors
-
- protected PdfIndirectReference() {
- super(0);
- }
-
-/**
- * Constructs a PdfIndirectReference
.
- *
- * @param type the type of the PdfObject
that is referenced to
- * @param number the object number.
- * @param generation the generation number.
- */
-
- PdfIndirectReference(int type, int number, int generation) {
- super(0, new StringBuffer().append(number).append(" ").append(generation).append(" R").toString());
- this.number = number;
- this.generation = generation;
- }
-
-/**
- * Constructs a PdfIndirectReference
.
- *
- * @param type the type of the PdfObject
that is referenced to
- * @param number the object number.
- */
-
- PdfIndirectReference(int type, int number) {
- this(type, number, 0);
- }
-
- // methods
-
-/**
- * Returns the number of the object.
- *
- * @return a number.
- */
-
- public int getNumber() {
- return number;
- }
-
-/**
- * Returns the generation of the object.
- *
- * @return a number.
- */
-
- public int getGeneration() {
- return generation;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfLayer.java pdftk-2.01/java/com/lowagie/text/pdf/PdfLayer.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfLayer.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfLayer.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,308 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.util.ArrayList;
-/**
- * An optional content group is a dictionary representing a collection of graphics
- * that can be made visible or invisible dynamically by users of viewer applications.
- * In iText they are referenced as layers.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfLayer extends PdfDictionary implements PdfOCG {
- protected PdfIndirectReference ref;
- protected ArrayList children;
- protected PdfLayer parent;
- protected String title;
-
- /**
- * Holds value of property on.
- */
- private boolean on = true;
-
- /**
- * Holds value of property onPanel.
- */
- private boolean onPanel = true;
-
- PdfLayer(String title) {
- this.title = title;
- }
-
- /**
- * Creates a title layer. A title layer is not really a layer but a collection of layers
- * under the same title heading.
- * @param title the title text
- * @param writer the PdfWriter
- * @return the title layer
- */
- public static PdfLayer createTitle(String title, PdfWriter writer) {
- if (title == null)
- throw new NullPointerException("Title cannot be null.");
- PdfLayer layer = new PdfLayer(title);
- writer.registerLayer(layer);
- return layer;
- }
- /**
- * Creates a new layer.
- * @param name the name of the layer
- * @param writer the writer
- */
- public PdfLayer(String name, PdfWriter writer) {
- super(PdfName.OCG);
- setName(name);
- ref = writer.getPdfIndirectReference();
- writer.registerLayer(this);
- }
-
- String getTitle() {
- return title;
- }
-
- /**
- * Adds a child layer. Nested layers can only have one parent.
- * @param child the child layer
- */
- public void addChild(PdfLayer child) {
- if (child.parent != null)
- throw new IllegalArgumentException("The layer '" + ((PdfString)child.get(PdfName.NAME)).toUnicodeString() + "' already has a parent.");
- child.parent = this;
- if (children == null)
- children = new ArrayList();
- children.add(child);
- }
-
-
- /**
- * Gets the parent layer.
- * @return the parent layer or null
if the layer has no parent
- */
- public PdfLayer getParent() {
- return parent;
- }
-
- /**
- * Gets the children layers.
- * @return the children layers or null
if the layer has no children
- */
- public ArrayList getChildren() {
- return children;
- }
-
- /**
- * Gets the PdfIndirectReference
that represents this layer.
- * @return the PdfIndirectReference
that represents this layer
- */
- public PdfIndirectReference getRef() {
- return ref;
- }
-
- /**
- * Sets the name of this layer.
- * @param name the name of this layer
- */
- public void setName(String name) {
- put(PdfName.NAME, new PdfString(name, PdfObject.TEXT_UNICODE));
- }
-
- /**
- * Gets the dictionary representing the layer. It just returns this
.
- * @return the dictionary representing the layer
- */
- public PdfObject getPdfObject() {
- return this;
- }
-
- /**
- * Gets the initial visibility of the layer.
- * @return the initial visibility of the layer
- */
- public boolean isOn() {
- return this.on;
- }
-
- /**
- * Sets the initial visibility of the layer.
- * @param on the initial visibility of the layer
- */
- public void setOn(boolean on) {
- this.on = on;
- }
-
- private PdfDictionary getUsage() {
- PdfDictionary usage = (PdfDictionary)get(PdfName.USAGE);
- if (usage == null) {
- usage = new PdfDictionary();
- put(PdfName.USAGE, usage);
- }
- return usage;
- }
-
- /**
- * Used by the creating application to store application-specific
- * data associated with this optional content group.
- * @param creator a text string specifying the application that created the group
- * @param subtype a string defining the type of content controlled by the group. Suggested
- * values include but are not limited to Artwork , for graphic-design or publishing
- * applications, and Technical , for technical designs such as building plans or
- * schematics
- */
- public void setCreatorInfo(String creator, String subtype) {
- PdfDictionary usage = getUsage();
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.CREATOR, new PdfString(creator, PdfObject.TEXT_UNICODE));
- dic.put(PdfName.SUBTYPE, new PdfName(subtype));
- usage.put(PdfName.CREATORINFO, dic);
- }
-
- /**
- * Specifies the language of the content controlled by this
- * optional content group
- * @param lang a language string which specifies a language and possibly a locale
- * (for example, es-MX represents Mexican Spanish)
- * @param preferred used by viewer applications when there is a partial match but no exact
- * match between the system language and the language strings in all usage dictionaries
- */
- public void setLanguage(String lang, boolean preferred) {
- PdfDictionary usage = getUsage();
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.LANG, new PdfString(lang, PdfObject.TEXT_UNICODE));
- if (preferred)
- dic.put(PdfName.PREFERRED, PdfName.ON);
- usage.put(PdfName.LANGUAGE, dic);
- }
-
- /**
- * Specifies the recommended state for content in this
- * group when the document (or part of it) is saved by a viewer application to a format
- * that does not support optional content (for example, an earlier version of
- * PDF or a raster image format).
- * @param export the export state
- */
- public void setExport(boolean export) {
- PdfDictionary usage = getUsage();
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.EXPORTSTATE, export ? PdfName.ON : PdfName.OFF);
- usage.put(PdfName.EXPORT, dic);
- }
-
- /**
- * Specifies a range of magnifications at which the content
- * in this optional content group is best viewed.
- * @param min the minimum recommended magnification factors at which the group
- * should be ON. A negative value will set the default to 0
- * @param max the maximum recommended magnification factor at which the group
- * should be ON. A negative value will set the largest possible magnification supported by the
- * viewer application
- */
- public void setZoom(float min, float max) {
- if (min <= 0 && max < 0)
- return;
- PdfDictionary usage = getUsage();
- PdfDictionary dic = new PdfDictionary();
- if (min > 0)
- dic.put(PdfName.MIN, new PdfNumber(min));
- if (max >= 0)
- dic.put(PdfName.MAX, new PdfNumber(max));
- usage.put(PdfName.ZOOM, dic);
- }
-
- /**
- * Specifies that the content in this group is intended for
- * use in printing
- * @param subtype a name specifying the kind of content controlled by the group;
- * for example, Trapping , PrintersMarks and Watermark
- * @param printstate indicates that the group should be
- * set to that state when the document is printed from a viewer application
- */
- public void setPrint(String subtype, boolean printstate) {
- PdfDictionary usage = getUsage();
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.SUBTYPE, new PdfName(subtype));
- dic.put(PdfName.PRINTSTATE, printstate ? PdfName.ON : PdfName.OFF);
- usage.put(PdfName.PRINT, dic);
- }
-
- /**
- * Indicates that the group should be set to that state when the
- * document is opened in a viewer application.
- * @param view the view state
- */
- public void setView(boolean view) {
- PdfDictionary usage = getUsage();
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.VIEWSTATE, view ? PdfName.ON : PdfName.OFF);
- usage.put(PdfName.VIEW, dic);
- }
-
- /**
- * Gets the layer visibility in Acrobat's layer panel
- * @return the layer visibility in Acrobat's layer panel
- */
- public boolean isOnPanel() {
- return this.onPanel;
- }
-
- /**
- * Sets the visibility of the layer in Acrobat's layer panel. If false
- * the layer cannot be directly manipulated by the user. Note that any children layers will
- * also be absent from the panel.
- * @param onPanel the visibility of the layer in Acrobat's layer panel
- */
- public void setOnPanel(boolean onPanel) {
- this.onPanel = onPanel;
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfLayerMembership.java pdftk-2.01/java/com/lowagie/text/pdf/PdfLayerMembership.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfLayerMembership.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfLayerMembership.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,145 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.util.HashSet;
-import java.util.Collection;
-
-/**
- * Content typically belongs to a single optional content group,
- * and is visible when the group is ON and invisible when it is OFF . To express more
- * complex visibility policies, content should not declare itself to belong to an optional
- * content group directly, but rather to an optional content membership dictionary
- * represented by this class.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfLayerMembership extends PdfDictionary implements PdfOCG {
-
- /**
- * Visible only if all of the entries are ON .
- */
- public static PdfName ALLON = new PdfName("AllOn");
- /**
- * Visible if any of the entries are ON .
- */
- public static PdfName ANYON = new PdfName("AnyOn");
- /**
- * Visible if any of the entries are OFF .
- */
- public static PdfName ANYOFF = new PdfName("AnyOff");
- /**
- * Visible only if all of the entries are OFF .
- */
- public static PdfName ALLOFF = new PdfName("AllOff");
-
- PdfIndirectReference ref;
- PdfArray members = new PdfArray();
- HashSet layers = new HashSet();
-
- /**
- * Creates a new, empty, membership layer.
- * @param writer the writer
- */
- public PdfLayerMembership(PdfWriter writer) {
- super(PdfName.OCMD);
- put(PdfName.OCGS, members);
- ref = writer.getPdfIndirectReference();
- }
-
- /**
- * Gets the PdfIndirectReference
that represents this membership layer.
- * @return the PdfIndirectReference
that represents this layer
- */
- public PdfIndirectReference getRef() {
- return ref;
- }
-
- /**
- * Adds a new member to the layer.
- * @param layer the new member to the layer
- */
- public void addMember(PdfLayer layer) {
- if (!layers.contains(layer)) {
- members.add(layer.getRef());
- layers.add(layer);
- }
- }
-
- /**
- * Gets the member layers.
- * @return the member layers
- */
- public Collection getLayers() {
- return layers;
- }
-
- /**
- * Sets the visibility policy for content belonging to this
- * membership dictionary. Possible values are ALLON, ANYON, ANYOFF and ALLOFF.
- * The default value is ANYON.
- * @param type the visibility policy
- */
- public void setVisibilityPolicy(PdfName type) {
- put(PdfName.P, type);
- }
-
- /**
- * Gets the dictionary representing the membership layer. It just returns this
.
- * @return the dictionary representing the layer
- */
- public PdfObject getPdfObject() {
- return this;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfLine.java pdftk-2.01/java/com/lowagie/text/pdf/PdfLine.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfLine.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfLine.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,494 +0,0 @@
-/*
- * $Id: PdfLine.java,v 1.65 2005/04/08 07:33:22 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-
-import com.lowagie.text.Element;
-import com.lowagie.text.ListItem;
-
-/**
- * PdfLine
defines an array with PdfChunk
-objects
- * that fit into 1 line.
- */
-
-public class PdfLine {
-
- // membervariables
-
- /** The arraylist containing the chunks. */
- protected ArrayList line;
-
- /** The left indentation of the line. */
- protected float left;
-
- /** The width of the line. */
- protected float width;
-
- /** The alignment of the line. */
- protected int alignment;
-
- /** The heigth of the line. */
- protected float height;
-
- /** The listsymbol (if necessary). */
- protected PdfChunk listSymbol = null;
-
- /** The listsymbol (if necessary). */
- protected float symbolIndent;
-
- /** true
if the chunk splitting was caused by a newline. */
- protected boolean newlineSplit = false;
-
- /** The original width. */
- protected float originalWidth;
-
- protected boolean isRTL = false;
-
- // constructors
-
- /**
- * Constructs a new PdfLine
-object.
- *
- * @param left the limit of the line at the left
- * @param right the limit of the line at the right
- * @param alignment the alignment of the line
- * @param height the height of the line
- */
-
- PdfLine(float left, float right, int alignment, float height) {
- this.left = left;
- this.width = right - left;
- this.originalWidth = this.width;
- this.alignment = alignment;
- this.height = height;
- this.line = new ArrayList();
- }
-
- PdfLine(float left, float remainingWidth, int alignment, boolean newlineSplit, ArrayList line, boolean isRTL) {
- this.left = left;
- this.width = remainingWidth;
- this.alignment = alignment;
- this.line = line;
- this.newlineSplit = newlineSplit;
- this.isRTL = isRTL;
- }
-
- // methods
-
- /**
- * Adds a PdfChunk
to the PdfLine
.
- *
- * @param chunk the PdfChunk
to add
- * @return null
if the chunk could be added completely; if not
- * a PdfChunk
containing the part of the chunk that could
- * not be added is returned
- */
-
- PdfChunk add(PdfChunk chunk) {
- // nothing happens if the chunk is null.
- if (chunk == null || chunk.toString().equals("")) {
- return null;
- }
-
- // we split the chunk to be added
- PdfChunk overflow = chunk.split(width);
- newlineSplit = (chunk.isNewlineSplit() || overflow == null);
- // if (chunk.isNewlineSplit() && alignment == Element.ALIGN_JUSTIFIED)
- // alignment = Element.ALIGN_LEFT;
-
-
- // if the length of the chunk > 0 we add it to the line
- if (chunk.length() > 0) {
- if (overflow != null)
- chunk.trimLastSpace();
- width -= chunk.width();
- line.add(chunk);
- }
-
- // if the length == 0 and there were no other chunks added to the line yet,
- // we risk to end up in an endless loop trying endlessly to add the same chunk
- else if (line.size() < 1) {
- chunk = overflow;
- overflow = chunk.truncate(width);
- width -= chunk.width();
- if (chunk.length() > 0) {
- line.add(chunk);
- return overflow;
- }
- // if the chunck couldn't even be truncated, we add everything, so be it
- else {
- if (overflow != null)
- line.add(overflow);
- return null;
- }
- }
- else {
- width += ((PdfChunk)(line.get(line.size() - 1))).trimLastSpace();
- }
- return overflow;
- }
-
- // methods to retrieve information
-
- /**
- * Returns the number of chunks in the line.
- *
- * @return a value
- */
-
- public int size() {
- return line.size();
- }
-
- /**
- * Returns an iterator of PdfChunk
s.
- *
- * @return an Iterator
- */
-
- public Iterator iterator() {
- return line.iterator();
- }
-
- /**
- * Returns the height of the line.
- *
- * @return a value
- */
-
- float height() {
- return height;
- }
-
- /**
- * Returns the left indentation of the line taking the alignment of the line into account.
- *
- * @return a value
- */
-
- float indentLeft() {
- if (isRTL) {
- switch (alignment) {
- case Element.ALIGN_LEFT:
- return left + width;
- case Element.ALIGN_CENTER:
- return left + (width / 2f);
- default:
- return left;
- }
- }
- else {
- switch (alignment) {
- case Element.ALIGN_RIGHT:
- return left + width;
- case Element.ALIGN_CENTER:
- return left + (width / 2f);
- default:
- return left;
- }
- }
- }
-
- /**
- * Checks if this line has to be justified.
- *
- * @return true
if the alignment equals ALIGN_JUSTIFIED and there is some width left.
- */
-
- public boolean hasToBeJustified() {
- return ((alignment == Element.ALIGN_JUSTIFIED || alignment == Element.ALIGN_JUSTIFIED_ALL) && width != 0);
- }
-
- /**
- * Resets the alignment of this line.
- *
- * The alignment of the last line of for instance a Paragraph
- * that has to be justified, has to be reset to ALIGN_LEFT .
- */
-
- public void resetAlignment() {
- if (alignment == Element.ALIGN_JUSTIFIED) {
- alignment = Element.ALIGN_LEFT;
- }
- }
-
- /**
- * Returns the width that is left, after a maximum of characters is added to the line.
- *
- * @return a value
- */
-
- float widthLeft() {
- return width;
- }
-
- /**
- * Returns the number of space-characters in this line.
- *
- * @return a value
- */
-
- int numberOfSpaces() {
- String string = toString();
- int length = string.length();
- int numberOfSpaces = 0;
- for (int i = 0; i < length; i++) {
- if (string.charAt(i) == ' ') {
- numberOfSpaces++;
- }
- }
- return numberOfSpaces;
- }
-
- /**
- * Sets the listsymbol of this line.
- *
- * This is only necessary for the first line of a ListItem
.
- *
- * @param listItem the list symbol
- */
-
- public void setListItem(ListItem listItem) {
- this.listSymbol = new PdfChunk(listItem.listSymbol(), null);
- this.symbolIndent = listItem.indentationLeft();
- }
-
- /**
- * Returns the listsymbol of this line.
- *
- * @return a PdfChunk
if the line has a listsymbol; null
otherwise
- */
-
- public PdfChunk listSymbol() {
- return listSymbol;
- }
-
- /**
- * Return the indentation needed to show the listsymbol.
- *
- * @return a value
- */
-
- public float listIndent() {
- return symbolIndent;
- }
-
- /**
- * Get the string representation of what is in this line.
- *
- * @return a String
- */
-
- public String toString() {
- StringBuffer tmp = new StringBuffer();
- for (Iterator i = line.iterator(); i.hasNext(); ) {
- tmp.append(((PdfChunk) i.next()).toString());
- }
- return tmp.toString();
- }
-
- /**
- * Checks if a newline caused the line split.
- * @return true
if a newline caused the line split
- */
- public boolean isNewlineSplit() {
- return newlineSplit && (alignment != Element.ALIGN_JUSTIFIED_ALL);
- }
-
- /**
- * Gets the index of the last PdfChunk
with metric attributes
- * @return the last PdfChunk
with metric attributes
- */
- public int getLastStrokeChunk() {
- int lastIdx = line.size() - 1;
- for (; lastIdx >= 0; --lastIdx) {
- PdfChunk chunk = (PdfChunk)line.get(lastIdx);
- if (chunk.isStroked())
- break;
- }
- return lastIdx;
- }
-
- /**
- * Gets a PdfChunk
by index.
- * @param idx the index
- * @return the PdfChunk
or null if beyond the array
- */
- public PdfChunk getChunk(int idx) {
- if (idx < 0 || idx >= line.size())
- return null;
- return (PdfChunk)line.get(idx);
- }
-
- /**
- * Gets the original width of the line.
- * @return the original width of the line
- */
- public float getOriginalWidth() {
- return originalWidth;
- }
-
- /**
- * Gets the maximum size of all the fonts used in this line
- * including images (if there are images in the line and if
- * the leading has to be changed).
- * @return maximum size of all the fonts used in this line
- */
- float getMaxSize() {
- float maxSize = 0;
- for (int k = 0; k < line.size(); ++k) {
- PdfChunk chunk = (PdfChunk)line.get(k);
- if ( /*!chunk.isImage() ssteward: dropped in 1.44 */ true || !chunk.changeLeading()) {
- maxSize = Math.max(chunk.font().size(), maxSize);
- }
- /* ssteward: dropped in 1.44
- else {
- maxSize = Math.max(chunk.getImage().scaledHeight() + chunk.getImageOffsetY() , maxSize);
- }
- */
- }
- return maxSize;
- }
-
- /**
- * Gets the maximum size of all the fonts used in this line
- * including images.
- * @return maximum size of all the fonts used in this line
- */
- float getMaxSizeSimple() {
- float maxSize = 0;
- for (int k = 0; k < line.size(); ++k) {
- PdfChunk chunk = (PdfChunk)line.get(k);
- if ( /*!chunk.isImage() ssteward: dropped in 1.44 */ true ) {
- maxSize = Math.max(chunk.font().size(), maxSize);
- }
- /* ssteward: dropped in 1.44
- else {
- maxSize = Math.max(chunk.getImage().scaledHeight() + chunk.getImageOffsetY() , maxSize);
- }
- */
- }
- return maxSize;
- }
-
- boolean isRTL() {
- return isRTL;
- }
-
- /**
- * Gets a width corrected with a charSpacing and wordSpacing.
- * @param charSpacing
- * @param wordSpacing
- * @return a corrected width
- */
- public float getWidthCorrected(float charSpacing, float wordSpacing) {
- float total = 0;
- for (int k = 0; k < line.size(); ++k) {
- PdfChunk ck = (PdfChunk)line.get(k);
- total += ck.getWidthCorrected(charSpacing, wordSpacing);
- }
- return total;
- }
-
-/**
- * Gets the maximum size of the ascender for all the fonts used
- * in this line.
- * @return maximum size of all the ascenders used in this line
- */
- public float getAscender() {
- float ascender = 0;
- for (int k = 0; k < line.size(); ++k) {
- PdfChunk ck = (PdfChunk)line.get(k);
- /* ssteward: dropped in 1.44
- if (ck.isImage())
- ascender = Math.max(ascender, ck.getImage().scaledHeight() + ck.getImageOffsetY());
- else {
- */
- PdfFont font = ck.font();
- ascender = Math.max(ascender, font.getFont().getFontDescriptor(BaseFont.ASCENT, font.size()));
- /*
- }
- */
- }
- return ascender;
- }
-
-/**
- * Gets the biggest descender for all the fonts used
- * in this line. Note that this is a negative number.
- * @return maximum size of all the ascenders used in this line
- */
- public float getDescender() {
- float descender = 0;
- for (int k = 0; k < line.size(); ++k) {
- PdfChunk ck = (PdfChunk)line.get(k);
- /* ssteward: dropped in 1.44
- if (ck.isImage())
- descender = Math.min(descender, ck.getImageOffsetY());
- else {
- */
- PdfFont font = ck.font();
- descender = Math.min(descender, font.getFont().getFontDescriptor(BaseFont.DESCENT, font.size()));
- /*
- }
- */
- }
- return descender;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfLister.java pdftk-2.01/java/com/lowagie/text/pdf/PdfLister.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfLister.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfLister.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,193 +0,0 @@
-/*
- * $Id: PdfLister.java,v 1.33 2005/02/01 14:30:50 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * This class by Mark Thompson. Copyright (C) 2002 Mark Thompson
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
- package com.lowagie.text.pdf;
-
-import java.io.*;
-import java.util.Iterator;
-/**
- * List a PDF file in human-readable form (for debugging reasons mostly)
- * @author Mark Thompson
- */
-
-public class PdfLister {
-
- /** the printStream you want to write the output to. */
- PrintStream out;
-
- /**
- * Create a new lister object.
- * @param out
- */
- public PdfLister(PrintStream out) {
- this.out = out;
- }
-
- /**
- * Visualizes a PDF object.
- * @param object a com.lowagie.text.pdf object
- */
- public void listAnyObject(PdfObject object)
- {
- switch (object.type()) {
- case PdfObject.ARRAY:
- listArray((PdfArray)object);
- break;
- case PdfObject.DICTIONARY:
- listDict((PdfDictionary) object);
- break;
- case PdfObject.STRING:
- out.println("(" + object.toString() + ")");
- break;
- default:
- out.println(object.toString());
- break;
- }
- }
- /**
- * Visualizes a PdfDictionary object.
- * @param dictionary a com.lowagie.text.pdf.PdfDictionary object
- */
- public void listDict(PdfDictionary dictionary)
- {
- out.println("<<");
- PdfName key;
- PdfObject value;
- for (Iterator i = dictionary.getKeys().iterator(); i.hasNext(); ) {
- key = (PdfName) i.next();
- value = (PdfObject) dictionary.get(key);
- out.print(key.toString());
- out.print(' ');
- listAnyObject(value);
- }
- out.println(">>");
- }
-
- /**
- * Visualizes a PdfArray object.
- * @param array a com.lowagie.text.pdf.PdfArray object
- */
- public void listArray(PdfArray array)
- {
- out.println('[');
- for (Iterator i = array.getArrayList().iterator(); i.hasNext(); ) {
- PdfObject item = (PdfObject)i.next();
- listAnyObject(item);
- }
- out.println(']');
- }
- /**
- * Visualizes a Stream.
- * @param stream
- * @param reader
- */
- public void listStream(PRStream stream, PdfReaderInstance reader)
- {
- try {
- listDict(stream);
- out.println("startstream");
- byte[] b = PdfReader.getStreamBytes(stream);
-// byte buf[] = new byte[Math.min(stream.getLength(), 4096)];
-// int r = 0;
-// stream.openStream(reader);
-// for (;;) {
-// r = stream.readStream(buf, 0, buf.length);
-// if (r == 0) break;
-// out.write(buf, 0, r);
-// }
-// stream.closeStream();
- int len = b.length - 1;
- for (int k = 0; k < len; ++k) {
- if (b[k] == '\r' && b[k + 1] != '\n')
- b[k] = (byte)'\n';
- }
- out.println(new String(b));
- out.println("endstream");
- } catch (IOException e) {
- System.err.println("I/O exception: " + e);
-// } catch (java.util.zip.DataFormatException e) {
-// System.err.println("Data Format Exception: " + e);
- }
- }
- /**
- * Visualizes an imported page
- * @param iPage
- */
- public void listPage(PdfImportedPage iPage)
- {
- int pageNum = iPage.getPageNumber();
- PdfReaderInstance readerInst = iPage.getPdfReaderInstance();
- PdfReader reader = readerInst.getReader();
-
- PdfDictionary page = reader.getPageN(pageNum);
- listDict(page);
- PdfObject obj = PdfReader.getPdfObject(page.get(PdfName.CONTENTS));
- switch (obj.type) {
- case PdfObject.STREAM:
- listStream((PRStream)obj, readerInst);
- break;
- case PdfObject.ARRAY:
- for (Iterator i = ((PdfArray)obj).getArrayList().iterator(); i.hasNext();) {
- PdfObject o = PdfReader.getPdfObject((PdfObject)i.next());
- listStream((PRStream)o, readerInst);
- out.println("-----------");
- }
- break;
- }
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfLiteral.java pdftk-2.01/java/com/lowagie/text/pdf/PdfLiteral.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfLiteral.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfLiteral.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,117 +0,0 @@
-/*
- * $Id: PdfLiteral.java,v 1.21 2002/06/20 13:30:25 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * a Literal
- */
-
-public class PdfLiteral extends PdfObject {
-
- /**
- * Holds value of property position.
- */
- private int position;
-
- public PdfLiteral(String text) {
- super(0, text);
- }
-
- public PdfLiteral(byte b[]) {
- super(0, b);
- }
-
- public PdfLiteral(int size) {
- super(0, (byte[])null);
- bytes = new byte[size];
- java.util.Arrays.fill(bytes, (byte)32);
- }
-
- public PdfLiteral(int type, String text) {
- super(type, text);
- }
-
- public PdfLiteral(int type, byte b[]) {
- super(type, b);
- }
-
- public void toPdf(PdfWriter writer, java.io.OutputStream os) throws java.io.IOException {
- if (os instanceof OutputStreamCounter)
- position = ((OutputStreamCounter)os).getCounter();
- super.toPdf(writer, os);
- }
-
- /**
- * Getter for property position.
- * @return Value of property position.
- */
- public int getPosition() {
- return this.position;
- }
-
- /**
- * Getter for property posLength.
- * @return Value of property posLength.
- */
- public int getPosLength() {
- if (bytes != null)
- return bytes.length;
- else
- return 0;
- }
-
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfMediaClipData.java pdftk-2.01/java/com/lowagie/text/pdf/PdfMediaClipData.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfMediaClipData.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfMediaClipData.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright 2003 Galo Gimenez
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-
-public class PdfMediaClipData extends PdfDictionary {
-
- PdfMediaClipData(String file, PdfFileSpecification fs, String mimeType) throws IOException {
- put(PdfName.TYPE,new PdfName("MediaClip"));
- put(PdfName.S, new PdfName("MCD"));
- put(PdfName.N, new PdfString("Media clip for "+file));
- put(new PdfName("CT"), new PdfString(mimeType));
- PdfDictionary dic = new PdfDictionary();
- dic.put(new PdfName("TF"), new PdfString("TEMPACCESS"));
- put(new PdfName("P"), dic);
- put(PdfName.D, fs.getReference());
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfName.java pdftk-2.01/java/com/lowagie/text/pdf/PdfName.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfName.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfName.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,1139 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * $Id: PdfName.java,v 1.74 2005/07/15 13:04:21 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * PdfName
is an object that can be used as a name in a PDF-file.
- *
- * A name, like a string, is a sequence of characters. It must begin with a slash
- * followed by a sequence of ASCII characters in the range 32 through 136 except
- * %, (, ), [, ], <, >, {, }, / and #. Any character except 0x00 may be included
- * in a name by writing its twocharacter hex code, preceded by #. The maximum number
- * of characters in a name is 127.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 4.5 (page 39-40).
- *
- *
- * @see PdfObject
- * @see PdfDictionary
- * @see BadPdfFormatException
- */
-
-public class PdfName extends PdfObject implements Comparable{
-
- // static membervariables (a variety of standard names used in PDF)
-
- /** A name */
- public static final PdfName A = new PdfName("A");
- /** A name */
- public static final PdfName AA = new PdfName("AA");
- /** A name */
- public static final PdfName ABSOLUTECALORIMETRIC = new PdfName("AbsoluteColorimetric");
- /** A name */
- public static final PdfName AC = new PdfName("AC");
- /** A name */
- public static final PdfName ACROFORM = new PdfName("AcroForm");
- /** A name */
- public static final PdfName ACTION = new PdfName("Action");
- /** A name */
- public static final PdfName ADBE_PKCS7_DETACHED = new PdfName("adbe.pkcs7.detached");
- /** A name */
- public static final PdfName ADBE_PKCS7_SHA1 = new PdfName("adbe.pkcs7.sha1");
- /** A name */
- public static final PdfName ADBE_X509_RSA_SHA1 = new PdfName("adbe.x509.rsa_sha1");
- /** A name */
- public static final PdfName ADOBE_PPKLITE = new PdfName("Adobe.PPKLite");
- /** A name */
- public static final PdfName ADOBE_PPKMS = new PdfName("Adobe.PPKMS");
- /** A name */
- public static final PdfName AIS = new PdfName("AIS");
- /** A name */
- public static final PdfName ALLPAGES = new PdfName("AllPages");
- /** A name */
- public static final PdfName ALTERNATE = new PdfName("Alternate");
- /** A name */
- public static final PdfName ANNOT = new PdfName("Annot");
- /** A name */
- public static final PdfName ANTIALIAS = new PdfName("AntiAlias");
- /** A name */
- public static final PdfName ANNOTS = new PdfName("Annots");
- /** A name */
- public static final PdfName AP = new PdfName("AP");
- /** A name */
- public static final PdfName ARTBOX = new PdfName("ArtBox");
- /** A name */
- public static final PdfName ASCENT = new PdfName("Ascent");
- /** A name */
- public static final PdfName AS = new PdfName("AS");
- /** A name */
- public static final PdfName ASCII85DECODE = new PdfName("ASCII85Decode");
- /** A name */
- public static final PdfName ASCIIHEXDECODE = new PdfName("ASCIIHexDecode");
- /** A name */
- public static final PdfName AUTHOR = new PdfName("Author");
- /** A name */
- public static final PdfName B = new PdfName("B");
- /** A name */
- public static final PdfName BASEENCODING = new PdfName("BaseEncoding");
- /** A name */
- public static final PdfName BASEFONT = new PdfName("BaseFont");
- /** A name */
- public static final PdfName BBOX = new PdfName("BBox");
- /** A name */
- public static final PdfName BC = new PdfName("BC");
- /** A name */
- public static final PdfName BG = new PdfName("BG");
- /** A name */
- public static final PdfName BIGFIVE = new PdfName("BigFive");
- /** A name */
- public static final PdfName BITSPERCOMPONENT = new PdfName("BitsPerComponent");
- /** A name */
- public static final PdfName BITSPERSAMPLE = new PdfName("BitsPerSample");
- /** A name */
- public static final PdfName BL = new PdfName("Bl");
- /** A name */
- public static final PdfName BLACKIS1 = new PdfName("BlackIs1");
- /** A name */
- public static final PdfName BLACKPOINT = new PdfName("BlackPoint");
- /** A name */
- public static final PdfName BLEEDBOX = new PdfName("BleedBox");
- /** A name */
- public static final PdfName BLINDS = new PdfName("Blinds");
- /** A name */
- public static final PdfName BM = new PdfName("BM");
- /** A name */
- public static final PdfName BORDER = new PdfName("Border");
- /** A name */
- public static final PdfName BOUNDS = new PdfName("Bounds");
- /** A name */
- public static final PdfName BOX = new PdfName("Box");
- /** A name */
- public static final PdfName BS = new PdfName("BS");
- /** A name */
- public static final PdfName BTN = new PdfName("Btn");
- /** A name */
- public static final PdfName BYTERANGE = new PdfName("ByteRange");
- /** A name */
- public static final PdfName C = new PdfName("C");
- /** A name */
- public static final PdfName C0 = new PdfName("C0");
- /** A name */
- public static final PdfName C1 = new PdfName("C1");
- /** A name */
- public static final PdfName CA = new PdfName("CA");
- /** A name */
- public static final PdfName ca = new PdfName("ca");
- /** A name */
- public static final PdfName CALGRAY = new PdfName("CalGray");
- /** A name */
- public static final PdfName CALRGB = new PdfName("CalRGB");
- /** A name */
- public static final PdfName CAPHEIGHT = new PdfName("CapHeight");
- /** A name */
- public static final PdfName CATALOG = new PdfName("Catalog");
- /** A name */
- public static final PdfName CATEGORY = new PdfName("Category");
- /** A name */
- public static final PdfName CCITTFAXDECODE = new PdfName("CCITTFaxDecode");
- /** A name */
- public static final PdfName CENTERWINDOW = new PdfName("CenterWindow");
- /** A name */
- public static final PdfName CERT = new PdfName("Cert");
- /** A name */
- public static final PdfName CH = new PdfName("Ch");
- /** A name */
- public static final PdfName CHARPROCS = new PdfName("CharProcs");
- /** A name */
- public static final PdfName CIDFONTTYPE0 = new PdfName("CIDFontType0");
- /** A name */
- public static final PdfName CIDFONTTYPE2 = new PdfName("CIDFontType2");
- /** A name */
- public static final PdfName CIDSYSTEMINFO = new PdfName("CIDSystemInfo");
- /** A name */
- public static final PdfName CIDTOGIDMAP = new PdfName("CIDToGIDMap");
- /** A name */
- public static final PdfName CIRCLE = new PdfName("Circle");
- /** A name */
- public static final PdfName CO = new PdfName("CO");
- /** A name */
- public static final PdfName COLORS = new PdfName("Colors");
- /** A name */
- public static final PdfName COLORSPACE = new PdfName("ColorSpace");
- /** A name */
- public static final PdfName COLUMNS = new PdfName("Columns");
- /** A name */
- public static final PdfName CONTACTINFO = new PdfName("ContactInfo");
- /** A name */
- public static final PdfName CONTENT = new PdfName("Content");
- /** A name */
- public static final PdfName CONTENTS = new PdfName("Contents");
- /** A name */
- public static final PdfName COORDS = new PdfName("Coords");
- /** A name */
- public static final PdfName COUNT = new PdfName("Count");
- /** A name of a base 14 type 1 font */
- public static final PdfName COURIER = new PdfName("Courier");
- /** A name of a base 14 type 1 font */
- public static final PdfName COURIER_BOLD = new PdfName("Courier-Bold");
- /** A name of a base 14 type 1 font */
- public static final PdfName COURIER_OBLIQUE = new PdfName("Courier-Oblique");
- /** A name of a base 14 type 1 font */
- public static final PdfName COURIER_BOLDOBLIQUE = new PdfName("Courier-BoldOblique");
- /** A name */
- public static final PdfName CREATIONDATE = new PdfName("CreationDate");
- /** A name */
- public static final PdfName CREATOR = new PdfName("Creator");
- /** A name */
- public static final PdfName CREATORINFO = new PdfName("CreatorInfo");
- /** A name */
- public static final PdfName CROPBOX = new PdfName("CropBox");
- /** A name */
- public static final PdfName CS = new PdfName("CS");
- /** A name */
- public static final PdfName D = new PdfName("D");
- /** A name */
- public static final PdfName DA = new PdfName("DA");
- /** A name */
- public static final PdfName DC = new PdfName("DC");
- /** A name */
- public static final PdfName DCTDECODE = new PdfName("DCTDecode");
- /** A name */
- public static final PdfName DECODE = new PdfName("Decode");
- /** A name */
- public static final PdfName DECODEPARMS = new PdfName("DecodeParms");
- /** A name */
- public static final PdfName DEFAULTCMYK = new PdfName("DefaultCMYK");
- /** A name */
- public static final PdfName DEFAULTGRAY = new PdfName("DefaultGray");
- /** A name */
- public static final PdfName DEFAULTRGB = new PdfName("DefaultRGB");
- /** A name */
- public static final PdfName DESCENDANTFONTS = new PdfName("DescendantFonts");
- /** A name */
- public static final PdfName DESCENT = new PdfName("Descent");
- /** A name */
- public static final PdfName DEST = new PdfName("Dest");
- /** A name */
- public static final PdfName DESTOUTPUTPROFILE = new PdfName("DestOutputProfile");
- /** A name */
- public static final PdfName DESTS = new PdfName("Dests");
- /** A name */
- public static final PdfName DEVICEGRAY = new PdfName("DeviceGray");
- /** A name */
- public static final PdfName DEVICERGB = new PdfName("DeviceRGB");
- /** A name */
- public static final PdfName DEVICECMYK = new PdfName("DeviceCMYK");
- /** A name */
- public static final PdfName DI = new PdfName("Di");
- /** A name */
- public static final PdfName DIFFERENCES = new PdfName("Differences");
- /** A name */
- public static final PdfName DISSOLVE = new PdfName("Dissolve");
- /** A name */
- public static final PdfName DIRECTION = new PdfName("Direction");
- /** A name */
- public static final PdfName DISPLAYDOCTITLE = new PdfName("DisplayDocTitle");
- /** A name */
- public static final PdfName DM = new PdfName("Dm");
- /** A name */
- //public static final PdfName DOMAIN = new PdfName("Domain");
- // changed this member name to prevent confusion on gcj (ssteward)
- public static final PdfName m_DOMAIN = new PdfName("Domain");
- /** A name */
- public static final PdfName DP = new PdfName("DP");
- /** A name */
- public static final PdfName DR = new PdfName("DR");
- /** A name */
- public static final PdfName DS = new PdfName("DS");
- /** A name */
- public static final PdfName DUR = new PdfName("Dur");
- /** A name */
- public static final PdfName DV = new PdfName("DV");
- /** A name */
- public static final PdfName DW = new PdfName("DW");
- /** A name */
- public static final PdfName E = new PdfName("E");
- /** A name */
- public static final PdfName EARLYCHANGE = new PdfName("EarlyChange");
- /** A name */
- public static final PdfName EF = new PdfName("EF");
- /** A name */
- public static final PdfName EMBEDDEDFILE = new PdfName("EmbeddedFile");
- /* sec. 3.10.3 of PDF Ref. 1.5 cites the name "EmbeddedFiles" (ssteward) */
- public static final PdfName EMBEDDEDFILES = new PdfName("EmbeddedFiles");
- /** A name */
- public static final PdfName ENCODE = new PdfName("Encode");
- /** A name */
- public static final PdfName ENCODEDBYTEALIGN = new PdfName("EncodedByteAlign");
- /** A name */
- public static final PdfName ENCODING = new PdfName("Encoding");
- /** A name */
- public static final PdfName ENCRYPT = new PdfName("Encrypt");
- /** A name */
- public static final PdfName ENDOFBLOCK = new PdfName("EndOfBlock");
- /** A name */
- public static final PdfName ENDOFLINE = new PdfName("EndOfLine");
- /** A name */
- public static final PdfName EXTEND = new PdfName("Extend");
- /** A name */
- public static final PdfName EXTGSTATE = new PdfName("ExtGState");
- /** A name */
- public static final PdfName EXPORT = new PdfName("Export");
- /** A name */
- public static final PdfName EXPORTSTATE = new PdfName("ExportState");
- /** A name */
- public static final PdfName EVENT = new PdfName("Event");
- /** A name */
- public static final PdfName F = new PdfName("F");
- /** A name */
- public static final PdfName FB = new PdfName("FB");
- /** A name */
- public static final PdfName FDECODEPARMS = new PdfName("FDecodeParms");
- /** A name */
- public static final PdfName FDF = new PdfName("FDF");
- /** A name */
- public static final PdfName FF = new PdfName("Ff");
- /** A name */
- public static final PdfName FFILTER = new PdfName("FFilter");
- /** A name */
- public static final PdfName FIELDS = new PdfName("Fields");
- /** A name */
- public static final PdfName FILEATTACHMENT = new PdfName("FileAttachment");
- /** A name */
- public static final PdfName FILESPEC = new PdfName("Filespec");
- /** A name */
- public static final PdfName FILTER = new PdfName("Filter");
- /** A name */
- public static final PdfName FIRST = new PdfName("First");
- /** A name */
- public static final PdfName FIRSTCHAR = new PdfName("FirstChar");
- /** A name */
- public static final PdfName FIRSTPAGE = new PdfName("FirstPage");
- /** A name */
- public static final PdfName FIT = new PdfName("Fit");
- /** A name */
- public static final PdfName FITH = new PdfName("FitH");
- /** A name */
- public static final PdfName FITV = new PdfName("FitV");
- /** A name */
- public static final PdfName FITR = new PdfName("FitR");
- /** A name */
- public static final PdfName FITB = new PdfName("FitB");
- /** A name */
- public static final PdfName FITBH = new PdfName("FitBH");
- /** A name */
- public static final PdfName FITBV = new PdfName("FitBV");
- /** A name */
- public static final PdfName FITWINDOW = new PdfName("FitWindow");
- /** A name */
- public static final PdfName FLAGS = new PdfName("Flags");
- /** A name */
- public static final PdfName FLATEDECODE = new PdfName("FlateDecode");
- /** A name */
- public static final PdfName FO = new PdfName("Fo");
- /** A name */
- public static final PdfName FONT = new PdfName("Font");
- /** A name */
- public static final PdfName FONTBBOX = new PdfName("FontBBox");
- /** A name */
- public static final PdfName FONTDESCRIPTOR = new PdfName("FontDescriptor");
- /** A name */
- public static final PdfName FONTFILE = new PdfName("FontFile");
- /** A name */
- public static final PdfName FONTFILE2 = new PdfName("FontFile2");
- /** A name */
- public static final PdfName FONTFILE3 = new PdfName("FontFile3");
- /** A name */
- public static final PdfName FONTMATRIX = new PdfName("FontMatrix");
- /** A name */
- public static final PdfName FONTNAME = new PdfName("FontName");
- /** A name */
- public static final PdfName FORM = new PdfName("Form");
- /** A name */
- public static final PdfName FORMTYPE = new PdfName("FormType");
- /** A name */
- public static final PdfName FREETEXT = new PdfName("FreeText");
- /** A name */
- public static final PdfName FRM = new PdfName("FRM");
- /** A name */
- public static final PdfName FS = new PdfName("FS");
- /** A name */
- public static final PdfName FT = new PdfName("FT");
- /** A name */
- public static final PdfName FULLSCREEN = new PdfName("FullScreen");
- /** A name */
- public static final PdfName FUNCTION = new PdfName("Function");
- /** A name */
- public static final PdfName FUNCTIONS = new PdfName("Functions");
- /** A name */
- public static final PdfName FUNCTIONTYPE = new PdfName("FunctionType");
- /** A name of an attribute. */
- public static final PdfName GAMMA = new PdfName("Gamma");
- /** A name of an attribute. */
- public static final PdfName GBK = new PdfName("GBK");
- /** A name of an attribute. */
- public static final PdfName GLITTER = new PdfName("Glitter");
- /** A name of an attribute. */
- public static final PdfName GOTO = new PdfName("GoTo");
- /** A name of an attribute. */
- public static final PdfName GOTOR = new PdfName("GoToR");
- /** A name of an attribute. */
- public static final PdfName GROUP = new PdfName("Group");
- /** A name of an attribute. */
- public static final PdfName GTS_PDFX = new PdfName("GTS_PDFX");
- /** A name of an attribute. */
- public static final PdfName GTS_PDFXVERSION = new PdfName("GTS_PDFXVersion");
- /** A name of an attribute. */
- public static final PdfName H = new PdfName("H");
- /** A name of an attribute. */
- public static final PdfName HEIGHT = new PdfName("Height");
- /** A name of a base 14 type 1 font */
- public static final PdfName HELVETICA = new PdfName("Helvetica");
- /** A name of a base 14 type 1 font */
- public static final PdfName HELVETICA_BOLD = new PdfName("Helvetica-Bold");
- /** This is a static PdfName PdfName of a base 14 type 1 font */
- public static final PdfName HELVETICA_OBLIQUE = new PdfName("Helvetica-Oblique");
- /** This is a static PdfName PdfName of a base 14 type 1 font */
- public static final PdfName HELVETICA_BOLDOBLIQUE = new PdfName("Helvetica-BoldOblique");
- /** A name */
- public static final PdfName HID = new PdfName("Hid");
- /** A name */
- public static final PdfName HIDE = new PdfName("Hide");
- /** A name */
- public static final PdfName HIDEMENUBAR = new PdfName("HideMenubar");
- /** A name */
- public static final PdfName HIDETOOLBAR = new PdfName("HideToolbar");
- /** A name */
- public static final PdfName HIDEWINDOWUI = new PdfName("HideWindowUI");
- /** A name */
- public static final PdfName HIGHLIGHT = new PdfName("Highlight");
- /** A name */
- public static final PdfName I = new PdfName("I");
- /** A name */
- public static final PdfName ICCBASED = new PdfName("ICCBased");
- /** A name */
- public static final PdfName ID = new PdfName("ID");
- /** A name */
- public static final PdfName IDENTITY = new PdfName("Identity");
- /** A name */
- public static final PdfName IF = new PdfName("IF");
- /** A name */
- public static final PdfName IMAGE = new PdfName("Image");
- /** A name */
- public static final PdfName IMAGEB = new PdfName("ImageB");
- /** A name */
- public static final PdfName IMAGEC = new PdfName("ImageC");
- /** A name */
- public static final PdfName IMAGEI = new PdfName("ImageI");
- /** A name */
- public static final PdfName IMAGEMASK = new PdfName("ImageMask");
- /** A name */
- public static final PdfName INDEX = new PdfName("Index");
- /** A name */
- public static final PdfName INDEXED = new PdfName("Indexed");
- /** A name */
- public static final PdfName INFO = new PdfName("Info");
- /** A name */
- public static final PdfName INK = new PdfName("Ink");
- /** A name */
- public static final PdfName INKLIST = new PdfName("InkList");
- /** A name */
- public static final PdfName IMPORTDATA = new PdfName("ImportData");
- /** A name */
- public static final PdfName INTENT = new PdfName("Intent");
- /** A name */
- public static final PdfName INTERPOLATE = new PdfName("Interpolate");
- /** A name */
- public static final PdfName ISMAP = new PdfName("IsMap");
- /** A name */
- public static final PdfName IRT = new PdfName("IRT");
- /** A name */
- public static final PdfName ITALICANGLE = new PdfName("ItalicAngle");
- /** A name */
- public static final PdfName IX = new PdfName("IX");
- /** A name */
- public static final PdfName JAVASCRIPT = new PdfName("JavaScript");
- /** A name */
- public static final PdfName JS = new PdfName("JS");
- /** A name */
- public static final PdfName K = new PdfName("K");
- /** A name */
- public static final PdfName KEYWORDS = new PdfName("Keywords");
- /** A name */
- public static final PdfName KIDS = new PdfName("Kids");
- /** A name */
- public static final PdfName L = new PdfName("L");
- /** A name */
- public static final PdfName L2R = new PdfName("L2R");
- /** A name */
- public static final PdfName LANG = new PdfName("Lang");
- /** A name */
- public static final PdfName LANGUAGE = new PdfName("Language");
- /** A name */
- public static final PdfName LAST = new PdfName("Last");
- /** A name */
- public static final PdfName LASTCHAR = new PdfName("LastChar");
- /** A name */
- public static final PdfName LASTPAGE = new PdfName("LastPage");
- /** A name */
- public static final PdfName LAUNCH = new PdfName("Launch");
- /** A name */
- public static final PdfName LENGTH = new PdfName("Length");
- /** A name */
- public static final PdfName LENGTH1 = new PdfName("Length1");
- /** A name */
- public static final PdfName LIMITS = new PdfName("Limits");
- /** A name */
- public static final PdfName LINE = new PdfName("Line");
- /** A name */
- public static final PdfName LINK = new PdfName("Link");
- /** A name */
- public static final PdfName LISTMODE = new PdfName("ListMode");
- /** A name */
- public static final PdfName LOCATION = new PdfName("Location");
- /** A name */
- public static final PdfName LOCK = new PdfName("Lock");
- /** A name */
- public static final PdfName LZWDECODE = new PdfName("LZWDecode");
- /** A name */
- public static final PdfName M = new PdfName("M");
- /** A name */
- public static final PdfName MATRIX = new PdfName("Matrix");
- /** A name of an encoding */
- public static final PdfName MAC_EXPERT_ENCODING = new PdfName("MacExpertEncoding");
- /** A name of an encoding */
- public static final PdfName MAC_ROMAN_ENCODING = new PdfName("MacRomanEncoding");
- /** A name */
- public static final PdfName MARKED = new PdfName("Marked");
- /** A name */
- public static final PdfName MARKINFO = new PdfName("MarkInfo");
- /** A name */
- public static final PdfName MASK = new PdfName("Mask");
- /** A name */
- public static final PdfName MAX = new PdfName("max");
- /** A name */
- public static final PdfName MAXLEN = new PdfName("MaxLen");
- /** A name */
- public static final PdfName MEDIABOX = new PdfName("MediaBox");
- /** A name */
- public static final PdfName MCID = new PdfName("MCID");
- /** A name */
- public static final PdfName MCR = new PdfName("MCR");
- /** A name */
- public static final PdfName METADATA = new PdfName("Metadata");
- /** A name */
- public static final PdfName MIN = new PdfName("min");
- /** A name */
- public static final PdfName MK = new PdfName("MK");
- /** A name */
- public static final PdfName MMTYPE1 = new PdfName("MMType1");
- /** A name */
- public static final PdfName MODDATE = new PdfName("ModDate");
- /** A name */
- public static final PdfName N = new PdfName("N");
- /** A name */
- public static final PdfName N0 = new PdfName("n0");
- /** A name */
- public static final PdfName N1 = new PdfName("n1");
- /** A name */
- public static final PdfName N2 = new PdfName("n2");
- /** A name */
- public static final PdfName N3 = new PdfName("n3");
- /** A name */
- public static final PdfName N4 = new PdfName("n4");
- /** A name */
- public static final PdfName NAME = new PdfName("Name");
- /** A name */
- public static final PdfName NAMED = new PdfName("Named");
- /** A name */
- public static final PdfName NAMES = new PdfName("Names");
- /** A name */
- public static final PdfName NEEDAPPEARANCES = new PdfName("NeedAppearances");
- /** A name */
- public static final PdfName NEWWINDOW = new PdfName("NewWindow");
- /** A name */
- public static final PdfName NEXT = new PdfName("Next");
- /** A name */
- public static final PdfName NEXTPAGE = new PdfName("NextPage");
- /** A name */
- public static final PdfName NM = new PdfName("NM");
- /** A name */
- public static final PdfName NONE = new PdfName("None");
- /** A name */
- public static final PdfName NONFULLSCREENPAGEMODE = new PdfName("NonFullScreenPageMode");
- /** A name */
- public static final PdfName NUMS = new PdfName("Nums");
- /** A name */
- public static final PdfName O = new PdfName("O");
- /** A name */
- public static final PdfName OBJSTM = new PdfName("ObjStm");
- /** A name */
- public static final PdfName OC = new PdfName("OC");
- /** A name */
- public static final PdfName OCG = new PdfName("OCG");
- /** A name */
- public static final PdfName OCGS = new PdfName("OCGs");
- /** A name */
- public static final PdfName OCMD = new PdfName("OCMD");
- /** A name */
- public static final PdfName OCPROPERTIES = new PdfName("OCProperties");
- /** A name */
- public static final PdfName Off = new PdfName("Off");
- /** A name */
- public static final PdfName OFF = new PdfName("OFF");
- /** A name */
- public static final PdfName ON = new PdfName("ON");
- /** A name */
- public static final PdfName ONECOLUMN = new PdfName("OneColumn");
- /** A name */
- public static final PdfName OPEN = new PdfName("Open");
- /** A name */
- public static final PdfName OPENACTION = new PdfName("OpenAction");
- /** A name */
- public static final PdfName OP = new PdfName("OP");
- /** A name */
- public static final PdfName op = new PdfName("op");
- /** A name */
- public static final PdfName OPM = new PdfName("OPM");
- /** A name */
- public static final PdfName OPT = new PdfName("Opt");
- /** A name */
- public static final PdfName ORDER = new PdfName("Order");
- /** A name */
- public static final PdfName ORDERING = new PdfName("Ordering");
- /** A name */
- public static final PdfName OUTLINES = new PdfName("Outlines");
- /** A name */
- public static final PdfName OUTPUTCONDITION = new PdfName("OutputCondition");
- /** A name */
- public static final PdfName OUTPUTCONDITIONIDENTIFIER = new PdfName("OutputConditionIdentifier");
- /** A name */
- public static final PdfName OUTPUTINTENT = new PdfName("OutputIntent");
- /** A name */
- public static final PdfName OUTPUTINTENTS = new PdfName("OutputIntents");
- /** A name */
- public static final PdfName P = new PdfName("P");
- /** A name */
- public static final PdfName PAGE = new PdfName("Page");
- /** A name */
- public static final PdfName PAGELABELS = new PdfName("PageLabels");
- /** A name */
- public static final PdfName PAGELAYOUT = new PdfName("PageLayout");
- /** A name */
- public static final PdfName PAGEMODE = new PdfName("PageMode");
- /** A name */
- public static final PdfName PAGES = new PdfName("Pages");
- /** A name */
- public static final PdfName PAINTTYPE = new PdfName("PaintType");
- /** A name */
- public static final PdfName PANOSE = new PdfName("Panose");
- /** A name */
- public static final PdfName PARAMS = new PdfName("Params");
- /** A name */
- public static final PdfName PARENT = new PdfName("Parent");
- /** A name */
- public static final PdfName PARENTTREE = new PdfName("ParentTree");
- /** A name */
- public static final PdfName PATTERN = new PdfName("Pattern");
- /** A name */
- public static final PdfName PATTERNTYPE = new PdfName("PatternType");
- /** A name */
- public static final PdfName PDF = new PdfName("PDF");
- /** A name */
- public static final PdfName PERCEPTUAL = new PdfName("Perceptual");
- /** A name */
- public static final PdfName PG = new PdfName("Pg");
- /** A name */
- public static final PdfName POPUP = new PdfName("Popup");
- /** A name */
- public static final PdfName PREDICTOR = new PdfName("Predictor");
- /** A name */
- public static final PdfName PREFERRED = new PdfName("Preferred");
- /** A name */
- public static final PdfName PRESERVERB = new PdfName("PreserveRB");
- /** A name */
- public static final PdfName PREV = new PdfName("Prev");
- /** A name */
- public static final PdfName PREVPAGE = new PdfName("PrevPage");
- /** A name */
- public static final PdfName PRINT = new PdfName("Print");
- /** A name */
- public static final PdfName PRINTSCALING = new PdfName("PrintScaling");
- /** A name */
- public static final PdfName PRINTSTATE = new PdfName("PrintState");
- /** A name */
- public static final PdfName PROCSET = new PdfName("ProcSet");
- /** A name */
- public static final PdfName PRODUCER = new PdfName("Producer");
- /** A name */
- public static final PdfName PROPERTIES = new PdfName("Properties");
- /** A name */
- public static final PdfName PS = new PdfName("PS");
- /** A name */
- public static final PdfName Q = new PdfName("Q");
- /** A name */
- public static final PdfName QUADPOINTS = new PdfName("QuadPoints");
- /** A name */
- public static final PdfName R = new PdfName("R");
- /** A name */
- public static final PdfName R2L = new PdfName("R2L");
- /** A name */
- public static final PdfName RANGE = new PdfName("Range");
- /** A name */
- public static final PdfName RC = new PdfName("RC");
- /** A name */
- public static final PdfName RBGROUPS = new PdfName("RBGroups");
- /** A name */
- public static final PdfName REASON = new PdfName("Reason");
- /** A name */
- public static final PdfName RECT = new PdfName("Rect");
- /** A name */
- public static final PdfName REGISTRY = new PdfName("Registry");
- /** A name */
- public static final PdfName REGISTRYNAME = new PdfName("RegistryName");
- /** A name */
- public static final PdfName RELATIVECALORIMETRIC = new PdfName("RelativeColorimetric");
- /** A name */
- public static final PdfName RENDITION = new PdfName("Rendition");
- /** A name */
- public static final PdfName RESETFORM = new PdfName("ResetForm");
- /** A name */
- public static final PdfName RESOURCES = new PdfName("Resources");
- /** A name */
- public static final PdfName RI = new PdfName("RI");
- /** A name */
- public static final PdfName ROLEMAP = new PdfName("RoleMap");
- /** A name */
- public static final PdfName ROOT = new PdfName("Root");
- /** A name */
- public static final PdfName ROTATE = new PdfName("Rotate");
- /** A name */
- public static final PdfName ROWS = new PdfName("Rows");
- /** A name */
- public static final PdfName RUNLENGTHDECODE = new PdfName("RunLengthDecode");
- /** A name */
- public static final PdfName RV = new PdfName("RV");
- /** A name */
- public static final PdfName S = new PdfName("S");
- /** A name */
- public static final PdfName SATURATION = new PdfName("Saturation");
- /** A name */
- public static final PdfName SCREEN = new PdfName("Screen");
- /** A name */
- public static final PdfName SEPARATION = new PdfName("Separation");
- /** A name */
- public static final PdfName SETOCGSTATE = new PdfName("SetOCGState");
- /** A name */
- public static final PdfName SHADING = new PdfName("Shading");
- /** A name */
- public static final PdfName SHADINGTYPE = new PdfName("ShadingType");
- /** A name */
- public static final PdfName SHIFT_JIS = new PdfName("Shift-JIS");
- /** A name */
- public static final PdfName SIG = new PdfName("Sig");
- /** A name */
- public static final PdfName SIGFLAGS = new PdfName("SigFlags");
- /** A name */
- public static final PdfName SINGLEPAGE = new PdfName("SinglePage");
- /** A name */
- public static final PdfName SIZE = new PdfName("Size");
- /** A name */
- public static final PdfName SMASK = new PdfName("SMask");
- /** A name */
- public static final PdfName SPLIT = new PdfName("Split");
- /** A name */
- public static final PdfName SQUARE = new PdfName("Square");
- /** A name */
- public static final PdfName ST = new PdfName("St");
- /** A name */
- public static final PdfName STAMP = new PdfName("Stamp");
- /** A name */
- public static final PdfName STANDARD = new PdfName("Standard");
- /** A name */
- public static final PdfName STATE = new PdfName("State");
- /** A name */
- public static final PdfName STRIKEOUT = new PdfName("StrikeOut");
- /** A name */
- public static final PdfName STRUCTPARENT = new PdfName("StructParent");
- /** A name */
- public static final PdfName STRUCTPARENTS = new PdfName("StructParents");
- /** A name */
- public static final PdfName STRUCTTREEROOT = new PdfName("StructTreeRoot");
- /** A name */
- public static final PdfName STYLE = new PdfName("Style");
- /** A name */
- public static final PdfName STEMV = new PdfName("StemV");
- /** A name */
- public static final PdfName SUBFILTER = new PdfName("SubFilter");
- /** A name */
- public static final PdfName SUBJECT = new PdfName("Subject");
- /** A name */
- public static final PdfName SUBMITFORM = new PdfName("SubmitForm");
- /** A name */
- public static final PdfName SUBTYPE = new PdfName("Subtype");
- /** A name */
- public static final PdfName SUPPLEMENT = new PdfName("Supplement");
- /** A name */
- public static final PdfName SV = new PdfName("SV");
- /** A name */
- public static final PdfName SW = new PdfName("SW");
- /** A name of a base 14 type 1 font */
- public static final PdfName SYMBOL = new PdfName("Symbol");
- /** A name */
- public static final PdfName T = new PdfName("T");
- /** A name */
- public static final PdfName TEXT = new PdfName("Text");
- /** A name */
- public static final PdfName THUMB = new PdfName("Thumb");
- /** A name */
- public static final PdfName THREADS = new PdfName("Threads");
- /** A name */
- public static final PdfName TI = new PdfName("TI");
- /** A name */
- public static final PdfName TILINGTYPE = new PdfName("TilingType");
- /** A name of a base 14 type 1 font */
- public static final PdfName TIMES_ROMAN = new PdfName("Times-Roman");
- /** A name of a base 14 type 1 font */
- public static final PdfName TIMES_BOLD = new PdfName("Times-Bold");
- /** A name of a base 14 type 1 font */
- public static final PdfName TIMES_ITALIC = new PdfName("Times-Italic");
- /** A name of a base 14 type 1 font */
- public static final PdfName TIMES_BOLDITALIC = new PdfName("Times-BoldItalic");
- /** A name */
- public static final PdfName TITLE = new PdfName("Title");
- /** A name */
- public static final PdfName TK = new PdfName("TK");
- /** A name */
- public static final PdfName TM = new PdfName("TM");
- /** A name */
- public static final PdfName TOGGLE = new PdfName("Toggle");
- /** A name */
- public static final PdfName TOUNICODE = new PdfName("ToUnicode");
- /** A name */
- public static final PdfName TP = new PdfName("TP");
- /** A name */
- public static final PdfName TRANS = new PdfName("Trans");
- /** A name */
- public static final PdfName TRANSPARENCY = new PdfName("Transparency");
- /** A name */
- public static final PdfName TRAPPED = new PdfName("Trapped");
- /** A name */
- public static final PdfName TRIMBOX = new PdfName("TrimBox");
- /** A name */
- public static final PdfName TRUETYPE = new PdfName("TrueType");
- /** A name */
- public static final PdfName TU = new PdfName("TU");
- /** A name */
- public static final PdfName TWOCOLUMNLEFT = new PdfName("TwoColumnLeft");
- /** A name */
- public static final PdfName TWOCOLUMNRIGHT = new PdfName("TwoColumnRight");
- /** A name */
- public static final PdfName TX = new PdfName("Tx");
- /** A name */
- public static final PdfName TYPE = new PdfName("Type");
- /** A name */
- public static final PdfName TYPE0 = new PdfName("Type0");
- /** A name */
- public static final PdfName TYPE1 = new PdfName("Type1");
- /** A name of an attribute. */
- public static final PdfName TYPE3 = new PdfName("Type3");
- /** A name of an attribute. */
- public static final PdfName U = new PdfName("U");
- /** A name */
- public static final PdfName UF = new PdfName("UF");
- /** A name of an attribute. */
- public static final PdfName UHC = new PdfName("UHC");
- /** A name of an attribute. */
- public static final PdfName UNDERLINE = new PdfName("Underline");
- /** A name */
- public static final PdfName URI = new PdfName("URI");
- /** A name */
- public static final PdfName URL = new PdfName("URL");
- /** A name */
- public static final PdfName USAGE = new PdfName("Usage");
- /** A name */
- public static final PdfName USENONE = new PdfName("UseNone");
- /** A name */
- public static final PdfName USEOC = new PdfName("UseOC");
- /** A name */
- public static final PdfName USEOUTLINES = new PdfName("UseOutlines");
- /** A name */
- public static final PdfName USER = new PdfName("User");
- /** A name */
- public static final PdfName USERUNIT = new PdfName("UserUnit");
- /** A name */
- public static final PdfName USETHUMBS = new PdfName("UseThumbs");
- /** A name */
- public static final PdfName V = new PdfName("V");
- /** A name */
- public static final PdfName VERISIGN_PPKVS = new PdfName("VeriSign.PPKVS");
- /** A name */
- public static final PdfName VIEW = new PdfName("View");
- /** A name */
- public static final PdfName VIEWERPREFERENCES = new PdfName("ViewerPreferences");
- /** A name */
- public static final PdfName VIEWSTATE = new PdfName("ViewState");
- /** A name */
- public static final PdfName VISIBLEPAGES = new PdfName("VisiblePages");
- /** A name of an attribute. */
- public static final PdfName W = new PdfName("W");
- /** A name of an attribute. */
- public static final PdfName W2 = new PdfName("W2");
- /** A name of an attribute. */
- public static final PdfName WC = new PdfName("WC");
- /** A name of an attribute. */
- public static final PdfName WIDGET = new PdfName("Widget");
- /** A name of an attribute. */
- public static final PdfName WIDTH = new PdfName("Width");
- /** A name */
- public static final PdfName WIDTHS = new PdfName("Widths");
- /** A name of an encoding */
- public static final PdfName WIN = new PdfName("Win");
- /** A name of an encoding */
- public static final PdfName WIN_ANSI_ENCODING = new PdfName("WinAnsiEncoding");
- /** A name of an encoding */
- public static final PdfName WIPE = new PdfName("Wipe");
- /** A name */
- public static final PdfName WHITEPOINT = new PdfName("WhitePoint");
- /** A name */
- public static final PdfName WP = new PdfName("WP");
- /** A name of an encoding */
- public static final PdfName WS = new PdfName("WS");
- /** A name */
- public static final PdfName X = new PdfName("X");
- /** A name */
- public static final PdfName XFA = new PdfName("XFA");
- /** A name */
- public static final PdfName XML = new PdfName("XML");
- /** A name */
- public static final PdfName XOBJECT = new PdfName("XObject");
- /** A name */
- public static final PdfName XSTEP = new PdfName("XStep");
- /** A name */
- public static final PdfName XREF = new PdfName("XRef");
- /** A name */
- public static final PdfName XREFSTM = new PdfName("XRefStm");
- /** A name */
- public static final PdfName XYZ = new PdfName("XYZ");
- /** A name */
- public static final PdfName YSTEP = new PdfName("YStep");
- /** A name of a base 14 type 1 font */
- public static final PdfName ZAPFDINGBATS = new PdfName("ZapfDingbats");
- /** A name */
- public static final PdfName ZOOM = new PdfName("Zoom");
-
- private int hash = 0;
-
- // constructors
-
- /**
- * Constructs a PdfName
-object.
- *
- * @param name the new Name.
- */
-
- public PdfName(String name) {
- super(PdfObject.NAME);
- // The minimum number of characters in a name is 0, the maximum is 127 (the '/' not included)
- int length = name.length();
- /* ssteward: just pass this problem along, since we didn't create it
- if (length > 127) {
- throw new IllegalArgumentException("The name '" + name + "' is too long (" + length + " characters).");
- }
- */
- // The name has to be checked for illegal characters
- // every special character has to be substituted
- ByteBuffer pdfName = new ByteBuffer(length + 20);
- pdfName.append('/');
- char character;
- char chars[] = name.toCharArray();
- // loop over all the characters
- for (int index = 0; index < length; index++) {
- character = (char)(chars[index] & 0xff);
- // special characters are escaped (reference manual p.39)
- switch (character) {
- case ' ':
- case '%':
- case '(':
- case ')':
- case '<':
- case '>':
- case '[':
- case ']':
- case '{':
- case '}':
- case '/':
- case '#':
- pdfName.append('#');
- pdfName.append(Integer.toString(character, 16));
- break;
- default:
- if (character > 126 || character < 32) {
- pdfName.append('#');
- if (character < 16)
- pdfName.append('0');
- pdfName.append(Integer.toString(character, 16));
- }
- else
- pdfName.append(character);
- break;
- }
- }
- bytes = pdfName.toByteArray();
- }
-
- /**
- * Constructs a PdfName.
- * @param bytes
- */
- public PdfName(byte bytes[]) {
- super(PdfObject.NAME, bytes);
- }
- // methods
-
- /**
- * Compares this object with the specified object for order. Returns a
- * negative integer, zero, or a positive integer as this object is less
- * than, equal to, or greater than the specified object.
- *
- *
- * @param object the Object to be compared.
- * @return a negative integer, zero, or a positive integer as this object
- * is less than, equal to, or greater than the specified object.
- *
- * @throws ClassCastException if the specified object's type prevents it
- * from being compared to this Object.
- */
- public int compareTo(Object object) {
- PdfName name = (PdfName) object;
-
- byte myBytes[] = bytes;
- byte objBytes[] = name.bytes;
- int len = Math.min(myBytes.length, objBytes.length);
- for(int i=0; i objBytes[i])
- return 1;
-
- if(myBytes[i] < objBytes[i])
- return -1;
- }
- if (myBytes.length < objBytes.length)
- return -1;
- if (myBytes.length > objBytes.length)
- return 1;
- return 0;
- }
-
- /**
- * Indicates whether some other object is "equal to" this one.
- *
- * @param obj the reference object with which to compare.
- * @return true
if this object is the same as the obj
- * argument; false
otherwise.
- */
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj instanceof PdfName)
- return compareTo(obj) == 0;
- return false;
- }
-
- /**
- * Returns a hash code value for the object. This method is
- * supported for the benefit of hashtables such as those provided by
- * java.util.Hashtable
.
- *
- * @return a hash code value for this object.
- */
- public int hashCode() {
- int h = hash;
- if (h == 0) {
- int ptr = 0;
- int len = bytes.length;
-
- for (int i = 0; i < len; i++)
- h = 31*h + (bytes[ptr++] & 0xff);
- hash = h;
- }
- return h;
- }
-
- /** Decodes an escaped name in the form "/AB#20CD" into "AB CD".
- * @param name the name to decode
- * @return the decoded name
- */
- public static String decodeName(String name) {
- StringBuffer buf = new StringBuffer();
- try {
- int len = name.length();
- for (int k = 1; k < len; ++k) {
- char c = name.charAt(k);
- if (c == '#') {
- c = (char)((PRTokeniser.getHex(name.charAt(k + 1)) << 4) + PRTokeniser.getHex(name.charAt(k + 2)));
- k += 2;
- }
- buf.append(c);
- }
- }
- catch (IndexOutOfBoundsException e) {
- // empty on purpose
- }
- return buf.toString();
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfNameTree.java pdftk-2.01/java/com/lowagie/text/pdf/PdfNameTree.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfNameTree.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfNameTree.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,181 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.util.HashMap;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.io.IOException;
-import com.lowagie.text.StringCompare;
-
-/**
- * Creates a name tree.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfNameTree {
-
- private static final int leafSize = 64;
- private static final StringCompare stringCompare = new StringCompare();
-
- /**
- * Creates a name tree.
- * @param items the item of the name tree. The key is a String
- * and the value is a PdfIndirectReference
. Note that although the
- * keys are strings only the lower byte is used and no check is made for chars
- * with the same lower byte and different upper byte. This will generate a wrong
- * tree name.
- * @param writer the writer
- * @throws IOException on error
- * @return the dictionary with the name tree. This dictionary is the one
- * generally pointed to by the key /Dests
- */
- public static PdfDictionary writeTree(HashMap items, PdfWriter writer) throws IOException {
- if (items.size() == 0)
- return null;
- String names[] = new String[items.size()];
- names = (String[])items.keySet().toArray(names);
- Arrays.sort(names, stringCompare);
- if (names.length <= leafSize) {
- PdfDictionary dic = new PdfDictionary();
- PdfArray ar = new PdfArray();
- for (int k = 0; k < names.length; ++k) {
- // ar.add(new PdfString(names[k], null));
- // ssteward, pdftk 1.0: Acrobat 5 expects unicode encoded text strings in
- // its EmbeddedFiles name tree, so I added the TEXT_UNICODE option here and throughout;
- // looks like an Acro5 bug to me;
- ar.add(new PdfString(names[k], PdfObject.TEXT_UNICODE )); // ssteward
- ar.add((PdfIndirectReference)items.get(names[k]));
- }
- dic.put(PdfName.NAMES, ar);
- return dic;
- }
- int skip = leafSize;
- PdfIndirectReference kids[] = new PdfIndirectReference[(names.length + leafSize - 1) / leafSize];
- for (int k = 0; k < kids.length; ++k) {
- int offset = k * leafSize;
- int end = Math.min(offset + leafSize, names.length);
- PdfDictionary dic = new PdfDictionary();
- PdfArray arr = new PdfArray();
- //arr.add(new PdfString(names[offset], null));
- arr.add(new PdfString(names[offset], PdfObject.TEXT_UNICODE)); // ssteward
- //arr.add(new PdfString(names[end - 1], null));
- arr.add(new PdfString(names[end - 1], PdfObject.TEXT_UNICODE)); // ssteward
- dic.put(PdfName.LIMITS, arr);
- arr = new PdfArray();
- for (; offset < end; ++offset) {
- //arr.add(new PdfString(names[offset], null));
- arr.add(new PdfString(names[offset], PdfObject.TEXT_UNICODE)); // ssteward
- arr.add((PdfIndirectReference)items.get(names[offset]));
- }
- dic.put(PdfName.NAMES, arr);
- kids[k] = writer.addToBody(dic).getIndirectReference();
- }
- int top = kids.length;
- while (true) {
- if (top <= leafSize) {
- PdfArray arr = new PdfArray();
- for (int k = 0; k < top; ++k)
- arr.add(kids[k]);
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.KIDS, arr);
- return dic;
- }
- skip *= leafSize;
- int tt = (names.length + skip - 1 )/ skip;
- for (int k = 0; k < tt; ++k) {
- int offset = k * leafSize;
- int end = Math.min(offset + leafSize, top);
- PdfDictionary dic = new PdfDictionary();
- PdfArray arr = new PdfArray();
- //arr.add(new PdfString(names[k * skip], null));
- arr.add(new PdfString(names[k * skip], PdfObject.TEXT_UNICODE)); // ssteward
- //arr.add(new PdfString(names[Math.min((k + 1) * skip, names.length) - 1], null));
- arr.add(new PdfString(names[Math.min((k + 1) * skip, names.length) - 1], PdfObject.TEXT_UNICODE)); // ssteward
- dic.put(PdfName.LIMITS, arr);
- arr = new PdfArray();
- for (; offset < end; ++offset) {
- arr.add(kids[offset]);
- }
- dic.put(PdfName.KIDS, arr);
- kids[k] = writer.addToBody(dic).getIndirectReference();
- }
- top = tt;
- }
- }
-
- private static void iterateItems(PdfDictionary dic, HashMap items) {
- PdfArray nn = (PdfArray)PdfReader.getPdfObjectRelease(dic.get(PdfName.NAMES));
- if (nn != null) {
- ArrayList arr = nn.getArrayList();
- for (int k = 0; k < arr.size(); ++k) {
- PdfString s = (PdfString)PdfReader.getPdfObjectRelease((PdfObject)arr.get(k++));
- //items.put(s.toString(), arr.get(k));
- items.put(s.toUnicodeString(), arr.get(k)); // ssteward; to match above changes
- }
- }
- else if ((nn = (PdfArray)PdfReader.getPdfObjectRelease(dic.get(PdfName.KIDS))) != null) {
- ArrayList arr = nn.getArrayList();
- for (int k = 0; k < arr.size(); ++k) {
- PdfDictionary kid = (PdfDictionary)PdfReader.getPdfObjectRelease((PdfObject)arr.get(k));
- iterateItems(kid, items);
- }
- }
- }
-
- public static HashMap readTree(PdfDictionary dic) {
- HashMap items = new HashMap();
- if (dic != null)
- iterateItems(dic, items);
- return items;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfNull.java pdftk-2.01/java/com/lowagie/text/pdf/PdfNull.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfNull.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfNull.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,89 +0,0 @@
-/*
- * $Id: PdfNull.java,v 1.22 2002/06/20 13:30:25 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * PdfNull
is the Null object represented by the keyword null .
- *
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 4.9 (page 53).
- *
- * @see PdfObject
- */
-
-public class PdfNull extends PdfObject {
-
- // static membervariables
-
-/** This is an instance of the PdfNull
-object. */
- public static final PdfNull PDFNULL = new PdfNull();
-
-/** This is the content of a PdfNull
-object. */
- private static final String CONTENT = "null";
-
- // constructors
-
-/**
- * Constructs a PdfNull
-object.
- *
- * You never need to do this yourself, you can always use the static final object PDFNULL .
- */
-
- public PdfNull() {
- super(m_NULL, CONTENT); // ssteward
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfNumber.java pdftk-2.01/java/com/lowagie/text/pdf/PdfNumber.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfNumber.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfNumber.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,165 +0,0 @@
-/*
- * $Id: PdfNumber.java,v 1.24 2002/07/09 11:28:23 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * PdfNumber
provides two types of numbers, integer and real.
- *
- * Integers may be specified by signed or unsigned constants. Reals may only be
- * in decimal format.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 4.3 (page 37).
- *
- * @see PdfObject
- * @see BadPdfFormatException
- */
-
-public class PdfNumber extends PdfObject {
-
-/** actual value of this PdfNumber
, represented as a double
*/
- private double value;
-
- // constructors
-
-/**
- * Constructs a PdfNumber
-object.
- *
- * @param content value of the new PdfNumber
-object
- */
-
- public PdfNumber(String content) {
- super(NUMBER);
- try {
- value = Double.valueOf(content.trim()).doubleValue();
- setContent(content);
- }
- catch (NumberFormatException nfe){
- throw new RuntimeException(content + " is not a valid number - " + nfe.toString());
- }
- }
-
-/**
- * Constructs a new INTEGER PdfNumber
-object.
- *
- * @param value value of the new PdfNumber
-object
- */
-
- public PdfNumber(int value) {
- super(NUMBER);
- this.value = value;
- setContent(String.valueOf(value));
- }
-
-/**
- * Constructs a new REAL PdfNumber
-object.
- *
- * @param value value of the new PdfNumber
-object
- */
-
- public PdfNumber(double value) {
- super(NUMBER);
- this.value = value;
- setContent(ByteBuffer.formatDouble(value));
- }
-
-/**
- * Constructs a new REAL PdfNumber
-object.
- *
- * @param value value of the new PdfNumber
-object
- */
-
- public PdfNumber(float value) {
- this((double)value);
- }
-
- // methods returning the value of this object
-
-/**
- * Returns the primitive int
value of this object.
- *
- * @return a value
- */
-
- public int intValue() {
- return (int) value;
- }
-
-/**
- * Returns the primitive double
value of this object.
- *
- * @return a value
- */
-
- public double doubleValue() {
- return value;
- }
-
- public float floatValue() {
- return (float)value;
- }
-
- // other methods
-
-/**
- * Increments the value of the PdfNumber
-object with 1.
- */
-
- public void increment() {
- value += 1.0;
- setContent(ByteBuffer.formatDouble(value));
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfNumberTree.java pdftk-2.01/java/com/lowagie/text/pdf/PdfNumberTree.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfNumberTree.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfNumberTree.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,165 +0,0 @@
-/*
- * Copyright 2005 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.util.HashMap;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.io.IOException;
-
-/**
- * Creates a number tree.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfNumberTree {
-
- private static final int leafSize = 64;
-
- /**
- * Creates a number tree.
- * @param items the item of the number tree. The key is an Integer
- * and the value is a PdfIndirectReference
.
- * @param writer the writer
- * @throws IOException on error
- * @return the dictionary with the number tree.
- */
- public static PdfDictionary writeTree(HashMap items, PdfWriter writer) throws IOException {
- if (items.size() == 0)
- return null;
- Integer numbers[] = new Integer[items.size()];
- numbers = (Integer[])items.keySet().toArray(numbers);
- Arrays.sort(numbers);
- if (numbers.length <= leafSize) {
- PdfDictionary dic = new PdfDictionary();
- PdfArray ar = new PdfArray();
- for (int k = 0; k < numbers.length; ++k) {
- ar.add(new PdfNumber(numbers[k].intValue()));
- ar.add((PdfIndirectReference)items.get(numbers[k]));
- }
- dic.put(PdfName.NUMS, ar);
- return dic;
- }
- int skip = leafSize;
- PdfIndirectReference kids[] = new PdfIndirectReference[(numbers.length + leafSize - 1) / leafSize];
- for (int k = 0; k < kids.length; ++k) {
- int offset = k * leafSize;
- int end = Math.min(offset + leafSize, numbers.length);
- PdfDictionary dic = new PdfDictionary();
- PdfArray arr = new PdfArray();
- arr.add(new PdfNumber(numbers[offset].intValue()));
- arr.add(new PdfNumber(numbers[end - 1].intValue()));
- dic.put(PdfName.LIMITS, arr);
- arr = new PdfArray();
- for (; offset < end; ++offset) {
- arr.add(new PdfNumber(numbers[offset].intValue()));
- arr.add((PdfIndirectReference)items.get(numbers[offset]));
- }
- dic.put(PdfName.NUMS, arr);
- kids[k] = writer.addToBody(dic).getIndirectReference();
- }
- int top = kids.length;
- while (true) {
- if (top <= leafSize) {
- PdfArray arr = new PdfArray();
- for (int k = 0; k < top; ++k)
- arr.add(kids[k]);
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.KIDS, arr);
- return dic;
- }
- skip *= leafSize;
- int tt = (numbers.length + skip - 1 )/ skip;
- for (int k = 0; k < tt; ++k) {
- int offset = k * leafSize;
- int end = Math.min(offset + leafSize, top);
- PdfDictionary dic = new PdfDictionary();
- PdfArray arr = new PdfArray();
- arr.add(new PdfNumber(numbers[k * skip].intValue()));
- arr.add(new PdfNumber(numbers[Math.min((k + 1) * skip, numbers.length) - 1].intValue()));
- dic.put(PdfName.LIMITS, arr);
- arr = new PdfArray();
- for (; offset < end; ++offset) {
- arr.add(kids[offset]);
- }
- dic.put(PdfName.KIDS, arr);
- kids[k] = writer.addToBody(dic).getIndirectReference();
- }
- top = tt;
- }
- }
-
- private static void iterateItems(PdfDictionary dic, HashMap items) {
- PdfArray nn = (PdfArray)PdfReader.getPdfObjectRelease(dic.get(PdfName.NUMS));
- if (nn != null) {
- ArrayList arr = nn.getArrayList();
- for (int k = 0; k < arr.size(); ++k) {
- PdfNumber s = (PdfNumber)PdfReader.getPdfObjectRelease((PdfObject)arr.get(k++));
- items.put(new Integer(s.intValue()), arr.get(k));
- }
- }
- else if ((nn = (PdfArray)PdfReader.getPdfObjectRelease(dic.get(PdfName.KIDS))) != null) {
- ArrayList arr = nn.getArrayList();
- for (int k = 0; k < arr.size(); ++k) {
- PdfDictionary kid = (PdfDictionary)PdfReader.getPdfObjectRelease((PdfObject)arr.get(k));
- iterateItems(kid, items);
- }
- }
- }
-
- public static HashMap readTree(PdfDictionary dic) {
- HashMap items = new HashMap();
- if (dic != null)
- iterateItems(dic, items);
- return items;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfOCG.java pdftk-2.01/java/com/lowagie/text/pdf/PdfOCG.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfOCG.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfOCG.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-/**
- * The interface common to all layer types.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public interface PdfOCG {
-
- /**
- * Gets the PdfIndirectReference
that represents this layer.
- * @return the PdfIndirectReference
that represents this layer
- */
- public PdfIndirectReference getRef();
-
- /**
- * Gets the object representing the layer.
- * @return the object representing the layer
- */
- public PdfObject getPdfObject();
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfOCProperties.java pdftk-2.01/java/com/lowagie/text/pdf/PdfOCProperties.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfOCProperties.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfOCProperties.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-/**
- * This class represents the /OCProperties entry in the document catalog
- * and holds the optional content properties dictionary, which contains
- * a list of all the optional content groups in the document, as well as information
- * about the default and alternate configurations for optional content.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfOCProperties extends PdfDictionary {
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfObject.java pdftk-2.01/java/com/lowagie/text/pdf/PdfObject.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfObject.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfObject.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,381 +0,0 @@
-/*
- * $Id: PdfObject.java,v 1.26 2002/07/09 11:28:23 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import java.io.OutputStream;
-import java.io.IOException;
-
-/**
- * PdfObject
is the abstract superclass of all PDF objects.
- *
- * PDF supports seven basic types of objects: Booleans, numbers, strings, names,
- * arrays, dictionaries and streams. In addition, PDF provides a null object.
- * Objects may be labeled so that they can be referred to by other objects.
- * All these basic PDF objects are described in the 'Portable Document Format
- * Reference Manual version 1.3' Chapter 4 (pages 37-54).
- *
- * @see PdfNull
- * @see PdfBoolean
- * @see PdfNumber
- * @see PdfString
- * @see PdfName
- * @see PdfArray
- * @see PdfDictionary
- * @see PdfStream
- * @see PdfIndirectReference
- */
-
-public abstract class PdfObject {
-
- // static membervariables (all the possible types of a PdfObject)
-
-/** a possible type of PdfObject
*/
- public static final int BOOLEAN = 1;
-
-/** a possible type of PdfObject
*/
- public static final int NUMBER = 2;
-
-/** a possible type of PdfObject
*/
- public static final int STRING = 3;
-
-/** a possible type of PdfObject
*/
- public static final int NAME = 4;
-
-/** a possible type of PdfObject
*/
- public static final int ARRAY = 5;
-
-/** a possible type of PdfObject
*/
- public static final int DICTIONARY = 6;
-
-/** a possible type of PdfObject
*/
- public static final int STREAM = 7;
-
-/** a possible type of PdfObject
*/
- // ssteward
- //public static final int NULL = 8;
- // renamed this member to m_NULL to prevent confusion w/ gcj
- public static final int m_NULL = 8;
-
- /** a possible type of PdfObject
*/
- public static final int INDIRECT = 10;
-
-/** This is an empty string used for the PdfNull
-object and for an empty PdfString
-object. */
- public static final String NOTHING = "";
-
-/** This is the default encoding to be used for converting Strings into bytes and vice versa.
- * The default encoding is PdfDocEncoding.
- */
- public static final String TEXT_PDFDOCENCODING = "PDF";
-
-/** This is the encoding to be used to output text in Unicode. */
- //public static final String TEXT_UNICODE = "UnicodeBig";
- public static final String TEXT_UNICODE = "UTF-16"; // ssteward; uses byte order mark
-
- // membervariables
-
-/** the content of this PdfObject
*/
- protected byte[] bytes;
-
-/** the type of this PdfObject
*/
- protected int type;
-
- /**
- * Holds value of property indRef.
- */
- protected PRIndirectReference indRef;
-
- // constructors
-
-/**
- * Constructs a PdfObject
of a certain type without any content .
- *
- * @param type type of the new PdfObject
- */
-
- protected PdfObject(int type) {
- this.type = type;
- this.bytes = null;
- }
-
-/**
- * Constructs a PdfObject
of a certain type with a certain content .
- *
- * @param type type of the new PdfObject
- * @param content content of the new PdfObject
as a String
.
- */
-
- protected PdfObject(int type, String content) {
- this.type = type;
- bytes = PdfEncodings.convertToBytes(content, null);
- }
-
-/**
- * Constructs a PdfObject
of a certain type with a certain content .
- *
- * @param type type of the new PdfObject
- * @param bytes content of the new PdfObject
as an array of byte
.
- */
-
- protected PdfObject(int type, byte[] bytes) {
- this.bytes = bytes;
- this.type = type;
- }
-
- // methods dealing with the content of this object
-
-/**
- * Writes the PDF representation of this PdfObject
as an array of byte
s to the writer.
- * @param writer for backwards compatibility
- * @param os the outputstream to write the bytes to.
- * @throws IOException
- */
-
- public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
- if (bytes != null)
- os.write(bytes);
- }
-
- /**
- * Gets the presentation of this object in a byte array
- * @return a byte array
- */
- public byte[] getBytes() {
- return bytes;
- }
-
- /**
- * Can this object be in an object stream?
- * @return true if this object can be in an object stream.
- */
- public boolean canBeInObjStm() {
- return (type >= 1 && type <= 6) || type == 8;
- }
-
-/**
- * Returns the length of the PDF representation of the PdfObject
.
- *
- * In some cases, namely for PdfString
and PdfStream
,
- * this method differs from the method length
because length
- * returns the length of the actual content of the PdfObject
.
- *
- * Remark: the actual content of an object is in most cases identical to its representation.
- * The following statement is always true: length() >= pdfLength().
- *
- * @return a length
- */
-
-// public int pdfLength() {
-// return toPdf(null).length;
-// }
-
-/**
- * Returns the String
-representation of this PdfObject
.
- *
- * @return a String
- */
-
- public String toString() {
- if (bytes == null)
- return super.toString();
- else
- return PdfEncodings.convertToString(bytes, null);
- }
-
-/**
- * Returns the length of the actual content of the PdfObject
.
- *
- * In some cases, namely for PdfString
and PdfStream
,
- * this method differs from the method pdfLength
because pdfLength
- * returns the length of the PDF representation of the object, not of the actual content
- * as does the method length
.
- *
- * Remark: the actual content of an object is in some cases identical to its representation.
- * The following statement is always true: length() >= pdfLength().
- *
- * @return a length
- */
-
- public int length() {
- return toString().length();
- }
-
-/**
- * Changes the content of this PdfObject
.
- *
- * @param content the new content of this PdfObject
- */
-
- protected void setContent(String content) {
- bytes = PdfEncodings.convertToBytes(content, null);
- }
-
- // methods dealing with the type of this object
-
-/**
- * Returns the type of this PdfObject
.
- *
- * @return a type
- */
-
- public int type() {
- return type;
- }
-
-/**
- * Checks if this PdfObject
is of the type PdfNull
.
- *
- * @return true
or false
- */
-
- public boolean isNull() {
- return (this.type == m_NULL); // sstewar
- }
-
-/**
- * Checks if this PdfObject
is of the type PdfBoolean
.
- *
- * @return true
or false
- */
-
- public boolean isBoolean() {
- return (this.type == BOOLEAN);
- }
-
-/**
- * Checks if this PdfObject
is of the type PdfNumber
.
- *
- * @return true
or false
- */
-
- public boolean isNumber() {
- return (this.type == NUMBER);
- }
-
-/**
- * Checks if this PdfObject
is of the type PdfString
.
- *
- * @return true
or false
- */
-
- public boolean isString() {
- return (this.type == STRING);
- }
-
-/**
- * Checks if this PdfObject
is of the type PdfName
.
- *
- * @return true
or false
- */
-
- public boolean isName() {
- return (this.type == NAME);
- }
-
-/**
- * Checks if this PdfObject
is of the type PdfArray
.
- *
- * @return true
or false
- */
-
- public boolean isArray() {
- return (this.type == ARRAY);
- }
-
-/**
- * Checks if this PdfObject
is of the type PdfDictionary
.
- *
- * @return true
or false
- */
-
- public boolean isDictionary() {
- return (this.type == DICTIONARY);
- }
-
-/**
- * Checks if this PdfObject
is of the type PdfStream
.
- *
- * @return true
or false
- */
-
- public boolean isStream() {
- return (this.type == STREAM);
- }
-
- /**
- * Checks if this is an indirect object.
- * @return true if this is an indirect object
- */
- public boolean isIndirect() {
- return (this.type == INDIRECT);
- }
-
- /**
- * Getter for property indRef.
- * @return Value of property indRef.
- */
- public PRIndirectReference getIndRef() {
- return this.indRef;
- }
-
- /**
- * Setter for property indRef.
- * @param indRef New value of property indRef.
- */
- public void setIndRef(PRIndirectReference indRef) {
- this.indRef = indRef;
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfOutline.java pdftk-2.01/java/com/lowagie/text/pdf/PdfOutline.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfOutline.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfOutline.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,548 +0,0 @@
-/*
- * $Id: PdfOutline.java,v 1.51 2005/01/05 10:05:20 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.util.Iterator;
-
-import com.lowagie.text.Chunk;
-import com.lowagie.text.Paragraph;
-import java.util.ArrayList;
-import java.awt.Color;
-import com.lowagie.text.Font;
-import java.io.OutputStream;
-import java.io.IOException;
-
-/**
- * PdfOutline
is an object that represents a PDF outline entry.
- *
- * An outline allows a user to access views of a document by name.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 6.7 (page 104-106)
- *
- * @see PdfDictionary
- */
-
-public class PdfOutline extends PdfDictionary {
-
- // membervariables
-
- /** the PdfIndirectReference
of this object */
- private PdfIndirectReference reference;
-
- /** value of the Count -key */
- private int count = 0;
-
- /** value of the Parent -key */
- private PdfOutline parent;
-
- /** value of the Destination -key */
- private PdfDestination destination;
-
- /** The PdfAction
for this outline.
- */
- private PdfAction action;
-
- protected ArrayList kids = new ArrayList();
-
- protected PdfWriter writer;
-
- /** Holds value of property tag. */
- private String tag;
-
- /** Holds value of property open. */
- private boolean open;
-
- /** Holds value of property color. */
- private Color color;
-
- /** Holds value of property style. */
- private int style = 0;
-
- // constructors
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for the outlines object
.
- *
- * @param writer The PdfWriter you are adding the outline to
- */
-
- PdfOutline(PdfWriter writer) {
- super(OUTLINES);
- open = true;
- parent = null;
- this.writer = writer;
- }
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for an outline entry
. The open mode is
- * true
.
- *
- * @param parent the parent of this outline item
- * @param action the PdfAction
for this outline item
- * @param title the title of this outline item
- */
-
- public PdfOutline(PdfOutline parent, PdfAction action, String title) {
- this(parent, action, title, true);
- }
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for an outline entry
.
- *
- * @param parent the parent of this outline item
- * @param action the PdfAction
for this outline item
- * @param title the title of this outline item
- * @param open true
if the children are visible
- */
- public PdfOutline(PdfOutline parent, PdfAction action, String title, boolean open) {
- super();
- this.action = action;
- initOutline(parent, title, open);
- }
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for an outline entry
. The open mode is
- * true
.
- *
- * @param parent the parent of this outline item
- * @param destination the destination for this outline item
- * @param title the title of this outline item
- */
-
- public PdfOutline(PdfOutline parent, PdfDestination destination, String title) {
- this(parent, destination, title, true);
- }
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for an outline entry
.
- *
- * @param parent the parent of this outline item
- * @param destination the destination for this outline item
- * @param title the title of this outline item
- * @param open true
if the children are visible
- */
- public PdfOutline(PdfOutline parent, PdfDestination destination, String title, boolean open) {
- super();
- this.destination = destination;
- initOutline(parent, title, open);
- }
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for an outline entry
. The open mode is
- * true
.
- *
- * @param parent the parent of this outline item
- * @param action the PdfAction
for this outline item
- * @param title the title of this outline item
- */
- public PdfOutline(PdfOutline parent, PdfAction action, PdfString title) {
- this(parent, action, title, true);
- }
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for an outline entry
.
- *
- * @param parent the parent of this outline item
- * @param action the PdfAction
for this outline item
- * @param title the title of this outline item
- * @param open true
if the children are visible
- */
- public PdfOutline(PdfOutline parent, PdfAction action, PdfString title, boolean open) {
- this(parent, action, title.toString(), true);
- }
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for an outline entry
. The open mode is
- * true
.
- *
- * @param parent the parent of this outline item
- * @param destination the destination for this outline item
- * @param title the title of this outline item
- */
-
- public PdfOutline(PdfOutline parent, PdfDestination destination, PdfString title) {
- this(parent, destination, title, true);
- }
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for an outline entry
.
- *
- * @param parent the parent of this outline item
- * @param destination the destination for this outline item
- * @param title the title of this outline item
- * @param open true
if the children are visible
- */
- public PdfOutline(PdfOutline parent, PdfDestination destination, PdfString title, boolean open) {
- this(parent, destination, title.toString(), true);
- }
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for an outline entry
. The open mode is
- * true
.
- *
- * @param parent the parent of this outline item
- * @param action the PdfAction
for this outline item
- * @param title the title of this outline item
- */
-
- public PdfOutline(PdfOutline parent, PdfAction action, Paragraph title) {
- this(parent, action, title, true);
- }
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for an outline entry
.
- *
- * @param parent the parent of this outline item
- * @param action the PdfAction
for this outline item
- * @param title the title of this outline item
- * @param open true
if the children are visible
- */
- public PdfOutline(PdfOutline parent, PdfAction action, Paragraph title, boolean open) {
- super();
- StringBuffer buf = new StringBuffer();
- for (Iterator i = title.getChunks().iterator(); i.hasNext(); ) {
- Chunk chunk = (Chunk) i.next();
- buf.append(chunk.content());
- }
- this.action = action;
- initOutline(parent, buf.toString(), open);
- }
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for an outline entry
. The open mode is
- * true
.
- *
- * @param parent the parent of this outline item
- * @param destination the destination for this outline item
- * @param title the title of this outline item
- */
-
- public PdfOutline(PdfOutline parent, PdfDestination destination, Paragraph title) {
- this(parent, destination, title, true);
- }
-
- /**
- * Constructs a PdfOutline
.
- *
- * This is the constructor for an outline entry
.
- *
- * @param parent the parent of this outline item
- * @param destination the destination for this outline item
- * @param title the title of this outline item
- * @param open true
if the children are visible
- */
- public PdfOutline(PdfOutline parent, PdfDestination destination, Paragraph title, boolean open) {
- super();
- StringBuffer buf = new StringBuffer();
- for (Iterator i = title.getChunks().iterator(); i.hasNext(); ) {
- Chunk chunk = (Chunk) i.next();
- buf.append(chunk.content());
- }
- this.destination = destination;
- initOutline(parent, buf.toString(), open);
- }
-
-
- // methods
-
- /** Helper for the constructors.
- * @param parent the parent outline
- * @param title the title for this outline
- * @param open true
if the children are visible
- */
- void initOutline(PdfOutline parent, String title, boolean open) {
- this.open = open;
- this.parent = parent;
- writer = parent.writer;
- put(PdfName.TITLE, new PdfString(title, PdfObject.TEXT_UNICODE));
- parent.addKid(this);
- if (destination != null && !destination.hasPage()) // bugfix Finn Bock
- setDestinationPage(writer.getCurrentPage());
- }
-
- /**
- * Sets the indirect reference of this PdfOutline
.
- *
- * @param reference the PdfIndirectReference
to this outline.
- */
-
- public void setIndirectReference(PdfIndirectReference reference) {
- this.reference = reference;
- }
-
- /**
- * Gets the indirect reference of this PdfOutline
.
- *
- * @return the PdfIndirectReference
to this outline.
- */
-
- public PdfIndirectReference indirectReference() {
- return reference;
- }
-
- /**
- * Gets the parent of this PdfOutline
.
- *
- * @return the PdfOutline
that is the parent of this outline.
- */
-
- public PdfOutline parent() {
- return parent;
- }
-
- /**
- * Set the page of the PdfDestination
-object.
- *
- * @param pageReference indirect reference to the page
- * @return true
if this page was set as the PdfDestination
-page.
- */
-
- public boolean setDestinationPage(PdfIndirectReference pageReference) {
- if (destination == null) {
- return false;
- }
- return destination.addPage(pageReference);
- }
-
- /**
- * Gets the destination for this outline.
- * @return the destination
- */
- public PdfDestination getPdfDestination() {
- return destination;
- }
-
- int getCount() {
- return count;
- }
-
- void setCount(int count) {
- this.count = count;
- }
-
- /**
- * returns the level of this outline.
- *
- * @return a level
- */
-
- public int level() {
- if (parent == null) {
- return 0;
- }
- return (parent.level() + 1);
- }
-
- /**
- * Returns the PDF representation of this PdfOutline
.
- *
- * @param writer the encryption information
- * @param os
- * @throws IOException
- */
-
- public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
- if (color != null && !color.equals(Color.black)) {
- put(PdfName.C, new PdfArray(new float[]{color.getRed()/255f,color.getGreen()/255f,color.getBlue()/255f}));
- }
- int flag = 0;
- if ((style & Font.BOLD) != 0)
- flag |= 2;
- if ((style & Font.ITALIC) != 0)
- flag |= 1;
- if (flag != 0)
- put(PdfName.F, new PdfNumber(flag));
- if (parent != null) {
- put(PdfName.PARENT, parent.indirectReference());
- }
- if (destination != null && destination.hasPage()) {
- put(PdfName.DEST, destination);
- }
- if (action != null)
- put(PdfName.A, action);
- if (count != 0) {
- put(PdfName.COUNT, new PdfNumber(count));
- }
- super.toPdf(writer, os);
- }
-
- /**
- * Adds a kid to the outline
- * @param outline
- */
- public void addKid(PdfOutline outline) {
- kids.add(outline);
- }
-
- /**
- * Returns the kids of this outline
- * @return an ArrayList with PdfOutlines
- */
- public ArrayList getKids() {
- return kids;
- }
-
- /**
- * Sets the kids of this outline
- * @param kids
- */
- public void setKids(ArrayList kids) {
- this.kids = kids;
- }
-
- /** Getter for property tag.
- * @return Value of property tag.
- */
- public String getTag() {
- return tag;
- }
-
- /** Setter for property tag.
- * @param tag New value of property tag.
- */
- public void setTag(String tag) {
- this.tag = tag;
- }
-
- /**
- * Gets the title of this outline
- * @return the title as a String
- */
- public String getTitle() {
- PdfString title = (PdfString)get(PdfName.TITLE);
- return title.toString();
- }
-
- /**
- * Sets the title of this outline
- * @param title
- */
- public void setTitle(String title) {
- put(PdfName.TITLE, new PdfString(title, PdfObject.TEXT_UNICODE));
- }
-
- /** Getter for property open.
- * @return Value of property open.
- */
- public boolean isOpen() {
- return open;
- }
-
- /** Setter for property open.
- * @param open New value of property open.
- */
- public void setOpen(boolean open) {
- this.open = open;
- }
-
- /** Getter for property color.
- * @return Value of property color.
- *
- */
- public Color getColor() {
- return this.color;
- }
-
- /** Setter for property color.
- * @param color New value of property color.
- *
- */
- public void setColor(Color color) {
- this.color = color;
- }
-
- /** Getter for property style.
- * @return Value of property style.
- *
- */
- public int getStyle() {
- return this.style;
- }
-
- /** Setter for property style.
- * @param style New value of property style.
- *
- */
- public void setStyle(int style) {
- this.style = style;
- }
-
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfPKCS7.java pdftk-2.01/java/com/lowagie/text/pdf/PdfPKCS7.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfPKCS7.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfPKCS7.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,1282 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.FileInputStream;
-import java.math.BigInteger;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
-import java.security.Signature;
-import java.security.MessageDigest;
-import java.security.SignatureException;
-import java.security.cert.CRL;
-import java.security.cert.CRLException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509CRL;
-import java.security.cert.X509Certificate;
-import java.security.KeyStore;
-import java.io.File;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import com.lowagie.text.ExceptionConverter;
-
-import org.bouncycastle.asn1.ASN1InputStream;
-import org.bouncycastle.asn1.DERObject;
-import org.bouncycastle.asn1.ASN1Sequence;
-import org.bouncycastle.asn1.ASN1Set;
-import org.bouncycastle.asn1.DERObjectIdentifier;
-import org.bouncycastle.asn1.DEROctetString;
-import org.bouncycastle.asn1.DERTaggedObject;
-import org.bouncycastle.asn1.DERInteger;
-import org.bouncycastle.asn1.ASN1TaggedObject;
-import org.bouncycastle.asn1.DERConstructedSet;
-import org.bouncycastle.asn1.DERSequence;
-import org.bouncycastle.asn1.DERNull;
-import org.bouncycastle.asn1.ASN1EncodableVector;
-import org.bouncycastle.asn1.DERSet;
-import org.bouncycastle.asn1.DERString;
-import org.bouncycastle.asn1.DERUTCTime;
-import org.bouncycastle.asn1.ASN1OutputStream;
-
-/**
- * This class does all the processing related to signing and verifying a PKCS#7
- * signature.
- *
- * It's based in code found at org.bouncycastle.
- */
-public class PdfPKCS7 {
-
- private byte sigAttr[];
- private byte digestAttr[];
- private int version, signerversion;
- private Set digestalgos;
- private Collection certs, crls;
- private X509Certificate signCert;
- private byte[] digest;
- private MessageDigest messageDigest;
- private String digestAlgorithm, digestEncryptionAlgorithm;
- private Signature sig;
- private transient PrivateKey privKey;
- private byte RSAdata[];
- private boolean verified;
- private boolean verifyResult;
- private byte externalDigest[];
- private byte externalRSAdata[];
-
- private static final String ID_PKCS7_DATA = "1.2.840.113549.1.7.1";
- private static final String ID_PKCS7_SIGNED_DATA = "1.2.840.113549.1.7.2";
- private static final String ID_MD5 = "1.2.840.113549.2.5";
- private static final String ID_MD2 = "1.2.840.113549.2.2";
- private static final String ID_SHA1 = "1.3.14.3.2.26";
- private static final String ID_RSA = "1.2.840.113549.1.1.1";
- private static final String ID_DSA = "1.2.840.10040.4.1";
- private static final String ID_CONTENT_TYPE = "1.2.840.113549.1.9.3";
- private static final String ID_MESSAGE_DIGEST = "1.2.840.113549.1.9.4";
- private static final String ID_SIGNING_TIME = "1.2.840.113549.1.9.5";
- private static final String ID_MD2RSA = "1.2.840.113549.1.1.2";
- private static final String ID_MD5RSA = "1.2.840.113549.1.1.4";
- private static final String ID_SHA1RSA = "1.2.840.113549.1.1.5";
- /**
- * Holds value of property reason.
- */
- private String reason;
-
- /**
- * Holds value of property location.
- */
- private String location;
-
- /**
- * Holds value of property signDate.
- */
- private Calendar signDate;
-
- /**
- * Holds value of property signName.
- */
- private String signName;
-
- /**
- * Verifies a signature using the sub-filter adbe.x509.rsa_sha1.
- * @param contentsKey the /Contents key
- * @param certsKey the /Cert key
- * @param provider the provider or null
for the default provider
- * @throws SecurityException on error
- * @throws CRLException on error
- * @throws InvalidKeyException on error
- * @throws CertificateException on error
- * @throws NoSuchProviderException on error
- * @throws NoSuchAlgorithmException on error
- * @throws IOException on error
- */
- public PdfPKCS7(byte[] contentsKey, byte[] certsKey, String provider) throws SecurityException, CRLException, InvalidKeyException, CertificateException, NoSuchProviderException, NoSuchAlgorithmException, IOException {
- CertificateFactory cf;
- if (provider == null)
- cf = CertificateFactory.getInstance("X.509");
- else
- cf = CertificateFactory.getInstance("X.509", provider);
- if (provider == null)
- certs = cf.generateCertificates(new ByteArrayInputStream(certsKey));
- signCert = (X509Certificate)certs.iterator().next();
- crls = new ArrayList();
- ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(contentsKey));
- digest = ((DEROctetString)in.readObject()).getOctets();
- if (provider == null)
- sig = Signature.getInstance("SHA1withRSA");
- else
- sig = Signature.getInstance("SHA1withRSA", provider);
- sig.initVerify(signCert.getPublicKey());
- }
-
- /**
- * Verifies a signature using the sub-filter adbe.pkcs7.detached or
- * adbe.pkcs7.sha1.
- * @param contentsKey the /Contents key
- * @param provider the provider or null
for the default provider
- * @throws SecurityException on error
- * @throws CRLException on error
- * @throws InvalidKeyException on error
- * @throws CertificateException on error
- * @throws NoSuchProviderException on error
- * @throws NoSuchAlgorithmException on error
- */
- public PdfPKCS7(byte[] contentsKey, String provider) throws SecurityException, CRLException, InvalidKeyException, CertificateException, NoSuchProviderException, NoSuchAlgorithmException {
- ASN1InputStream din = new ASN1InputStream(new ByteArrayInputStream(contentsKey));
-
- //
- // Basic checks to make sure it's a PKCS#7 SignedData Object
- //
- DERObject pkcs;
-
- try {
- pkcs = din.readObject();
- }
- catch (IOException e) {
- throw new SecurityException("can't decode PKCS7SignedData object");
- }
- if (!(pkcs instanceof ASN1Sequence)) {
- throw new SecurityException("Not a valid PKCS#7 object - not a sequence");
- }
- ASN1Sequence signedData = (ASN1Sequence)pkcs;
- DERObjectIdentifier objId = (DERObjectIdentifier)signedData.getObjectAt(0);
- if (!objId.getId().equals(ID_PKCS7_SIGNED_DATA))
- throw new SecurityException("Not a valid PKCS#7 object - not signed data");
- ASN1Sequence content = (ASN1Sequence)((DERTaggedObject)signedData.getObjectAt(1)).getObject();
- // the positions that we care are:
- // 0 - version
- // 1 - digestAlgorithms
- // 2 - possible ID_PKCS7_DATA
- // (the certificates and crls are taken out by other means)
- // last - signerInfos
-
- // the version
- version = ((DERInteger)content.getObjectAt(0)).getValue().intValue();
-
- // the digestAlgorithms
- digestalgos = new HashSet();
- Enumeration e = ((ASN1Set)content.getObjectAt(1)).getObjects();
- while (e.hasMoreElements())
- {
- ASN1Sequence s = (ASN1Sequence)e.nextElement();
- DERObjectIdentifier o = (DERObjectIdentifier)s.getObjectAt(0);
- digestalgos.add(o.getId());
- }
-
- // the certificates and crls
- CertificateFactory cf;
- if (provider == null)
- cf = CertificateFactory.getInstance("X.509");
- else
- cf = CertificateFactory.getInstance("X.509", provider);
- certs = cf.generateCertificates(new ByteArrayInputStream(contentsKey));
- crls = cf.generateCRLs(new ByteArrayInputStream(contentsKey));
-
- // the possible ID_PKCS7_DATA
- ASN1Sequence rsaData = (ASN1Sequence)content.getObjectAt(2);
- if (rsaData.size() > 1) {
- DEROctetString rsaDataContent = (DEROctetString)((DERTaggedObject)rsaData.getObjectAt(1)).getObject();
- RSAdata = rsaDataContent.getOctets();
- }
-
- // the signerInfos
- int next = 3;
- while (content.getObjectAt(next) instanceof DERTaggedObject)
- ++next;
- ASN1Set signerInfos = (ASN1Set)content.getObjectAt(next);
- if (signerInfos.size() != 1)
- throw new SecurityException("This PKCS#7 object has multiple SignerInfos - only one is supported at this time");
- ASN1Sequence signerInfo = (ASN1Sequence)signerInfos.getObjectAt(0);
- // the positions that we care are
- // 0 - version
- // 1 - the signing certificate serial number
- // 2 - the digest algorithm
- // 3 or 4 - digestEncryptionAlgorithm
- // 4 or 5 - encryptedDigest
- signerversion = ((DERInteger)signerInfo.getObjectAt(0)).getValue().intValue();
- // Get the signing certificate
- ASN1Sequence issuerAndSerialNumber = (ASN1Sequence)signerInfo.getObjectAt(1);
- BigInteger serialNumber = ((DERInteger)issuerAndSerialNumber.getObjectAt(1)).getValue();
- for (Iterator i = certs.iterator(); i.hasNext();) {
- X509Certificate cert = (X509Certificate)i.next();
- if (serialNumber.equals(cert.getSerialNumber())) {
- signCert = cert;
- break;
- }
- }
- if (signCert == null) {
- throw new SecurityException("Can't find signing certificate with serial " + serialNumber.toString(16));
- }
- digestAlgorithm = ((DERObjectIdentifier)((ASN1Sequence)signerInfo.getObjectAt(2)).getObjectAt(0)).getId();
- next = 3;
- if (signerInfo.getObjectAt(next) instanceof ASN1TaggedObject) {
- ASN1TaggedObject tagsig = (ASN1TaggedObject)signerInfo.getObjectAt(next);
- ASN1Sequence sseq = (ASN1Sequence)tagsig.getObject();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream dout = new ASN1OutputStream(bOut);
- try {
- ASN1EncodableVector attribute = new ASN1EncodableVector();
- for (int k = 0; k < sseq.size(); ++k) {
- attribute.add(sseq.getObjectAt(k));
- }
- dout.writeObject(new DERSet(attribute));
- dout.close();
- }
- catch (IOException ioe){}
- sigAttr = bOut.toByteArray();
-
- for (int k = 0; k < sseq.size(); ++k) {
- ASN1Sequence seq2 = (ASN1Sequence)sseq.getObjectAt(k);
- if (((DERObjectIdentifier)seq2.getObjectAt(0)).getId().equals(ID_MESSAGE_DIGEST)) {
- ASN1Set set = (ASN1Set)seq2.getObjectAt(1);
- digestAttr = ((DEROctetString)set.getObjectAt(0)).getOctets();
- break;
- }
- }
- if (digestAttr == null)
- throw new SecurityException("Authenticated attribute is missing the digest.");
- ++next;
- }
- digestEncryptionAlgorithm = ((DERObjectIdentifier)((ASN1Sequence)signerInfo.getObjectAt(next++)).getObjectAt(0)).getId();
- digest = ((DEROctetString)signerInfo.getObjectAt(next)).getOctets();
- if (RSAdata != null || digestAttr != null) {
- if (provider == null || provider.startsWith("SunPKCS11"))
- messageDigest = MessageDigest.getInstance(getHashAlgorithm());
- else
- messageDigest = MessageDigest.getInstance(getHashAlgorithm(), provider);
- }
- if (provider == null)
- sig = Signature.getInstance(getDigestAlgorithm());
- else
- sig = Signature.getInstance(getDigestAlgorithm(), provider);
- sig.initVerify(signCert.getPublicKey());
- }
-
- /**
- * Generates a signature.
- * @param privKey the private key
- * @param certChain the certificate chain
- * @param crlList the certificate revocation list
- * @param hashAlgorithm the hash algorithm
- * @param provider the provider or null
for the default provider
- * @param hasRSAdata true
if the sub-filter is adbe.pkcs7.sha1
- * @throws SecurityException on error
- * @throws InvalidKeyException on error
- * @throws NoSuchProviderException on error
- * @throws NoSuchAlgorithmException on error
- */
- public PdfPKCS7(PrivateKey privKey, Certificate[] certChain, CRL[] crlList,
- String hashAlgorithm, String provider, boolean hasRSAdata)
- throws SecurityException, InvalidKeyException, NoSuchProviderException,
- NoSuchAlgorithmException
- {
- this.privKey = privKey;
-
- if (hashAlgorithm.equals("MD5")) {
- digestAlgorithm = ID_MD5;
- }
- else if (hashAlgorithm.equals("MD2")) {
- digestAlgorithm = ID_MD2;
- }
- else if (hashAlgorithm.equals("SHA")) {
- digestAlgorithm = ID_SHA1;
- }
- else if (hashAlgorithm.equals("SHA1")) {
- digestAlgorithm = ID_SHA1;
- }
- else {
- throw new NoSuchAlgorithmException("Unknown Hash Algorithm "+hashAlgorithm);
- }
-
- version = signerversion = 1;
- certs = new ArrayList();
- crls = new ArrayList();
- digestalgos = new HashSet();
- digestalgos.add(digestAlgorithm);
-
- //
- // Copy in the certificates and crls used to sign the private key.
- //
- signCert = (X509Certificate)certChain[0];
- for (int i = 0;i < certChain.length;i++) {
- certs.add(certChain[i]);
- }
-
- if (crlList != null) {
- for (int i = 0;i < crlList.length;i++) {
- crls.add(crlList[i]);
- }
- }
-
- if (privKey != null) {
- //
- // Now we have private key, find out what the digestEncryptionAlgorithm is.
- //
- digestEncryptionAlgorithm = privKey.getAlgorithm();
- if (digestEncryptionAlgorithm.equals("RSA")) {
- digestEncryptionAlgorithm = ID_RSA;
- }
- else if (digestEncryptionAlgorithm.equals("DSA")) {
- digestEncryptionAlgorithm = ID_DSA;
- }
- else {
- throw new NoSuchAlgorithmException("Unknown Key Algorithm "+digestEncryptionAlgorithm);
- }
- }
- if (hasRSAdata) {
- RSAdata = new byte[0];
- if (provider == null || provider.startsWith("SunPKCS11"))
- messageDigest = MessageDigest.getInstance(getHashAlgorithm());
- else
- messageDigest = MessageDigest.getInstance(getHashAlgorithm(), provider);
- }
-
- if (privKey != null) {
- if (provider == null)
- sig = Signature.getInstance(getDigestAlgorithm());
- else
- sig = Signature.getInstance(getDigestAlgorithm(), provider);
-
- sig.initSign(privKey);
- }
- }
-
- /**
- * Update the digest with the specified bytes. This method is used both for signing and verifying
- * @param buf the data buffer
- * @param off the offset in the data buffer
- * @param len the data length
- * @throws SignatureException on error
- */
- public void update(byte[] buf, int off, int len) throws SignatureException {
- if (RSAdata != null || digestAttr != null)
- messageDigest.update(buf, off, len);
- else
- sig.update(buf, off, len);
- }
-
- /**
- * Verify the digest.
- * @throws SignatureException on error
- * @return true
if the signature checks out, false
otherwise
- */
- public boolean verify() throws SignatureException {
- if (verified)
- return verifyResult;
- if (sigAttr != null) {
- sig.update(sigAttr);
- if (RSAdata != null) {
- byte msd[] = messageDigest.digest();
- messageDigest.update(msd);
- }
- verifyResult = (Arrays.equals(messageDigest.digest(), digestAttr) && sig.verify(digest));
- }
- else {
- if (RSAdata != null)
- sig.update(messageDigest.digest());
- verifyResult = sig.verify(digest);
- }
- verified = true;
- return verifyResult;
- }
-
- /**
- * Get the X.509 certificates associated with this PKCS#7 object
- * @return the X.509 certificates associated with this PKCS#7 object
- */
- public Certificate[] getCertificates() {
- return (X509Certificate[])certs.toArray(new X509Certificate[0]);
- }
-
- /**
- * Get the X.509 certificate revocation lists associated with this PKCS#7 object
- * @return the X.509 certificate revocation lists associated with this PKCS#7 object
- */
- public Collection getCRLs() {
- return crls;
- }
-
- /**
- * Get the X.509 certificate actually used to sign the digest.
- * @return the X.509 certificate actually used to sign the digest
- */
- public X509Certificate getSigningCertificate() {
- return signCert;
- }
-
- /**
- * Get the version of the PKCS#7 object. Always 1
- * @return the version of the PKCS#7 object. Always 1
- */
- public int getVersion() {
- return version;
- }
-
- /**
- * Get the version of the PKCS#7 "SignerInfo" object. Always 1
- * @return the version of the PKCS#7 "SignerInfo" object. Always 1
- */
- public int getSigningInfoVersion() {
- return signerversion;
- }
-
- /**
- * Get the algorithm used to calculate the message digest
- * @return the algorithm used to calculate the message digest
- */
- public String getDigestAlgorithm() {
- String dea = digestEncryptionAlgorithm;
-
- if (digestEncryptionAlgorithm.equals(ID_RSA)) {
- dea = "RSA";
- }
- else if (digestEncryptionAlgorithm.equals(ID_DSA)) {
- dea = "DSA";
- }
-
- return getHashAlgorithm() + "with" + dea;
- }
-
- /**
- * Returns the algorithm.
- * @return the digest algorithm
- */
- public String getHashAlgorithm() {
- String da = digestAlgorithm;
-
- if (digestAlgorithm.equals(ID_MD5) || digestAlgorithm.equals(ID_MD5RSA)) {
- da = "MD5";
- }
- else if (digestAlgorithm.equals(ID_MD2) || digestAlgorithm.equals(ID_MD2RSA)) {
- da = "MD2";
- }
- else if (digestAlgorithm.equals(ID_SHA1) || digestAlgorithm.equals(ID_SHA1RSA)) {
- da = "SHA1";
- }
- return da;
- }
-
- /**
- * Loads the default root certificates at <java.home>/lib/security/cacerts
- * with the default provider.
- * @return a KeyStore
- */
- public static KeyStore loadCacertsKeyStore() {
- return loadCacertsKeyStore(null);
- }
-
- /**
- * Loads the default root certificates at <java.home>/lib/security/cacerts.
- * @param provider the provider or null
for the default provider
- * @return a KeyStore
- */
- public static KeyStore loadCacertsKeyStore(String provider) {
- File file = new File(System.getProperty("java.home"), "lib");
- file = new File(file, "security");
- file = new File(file, "cacerts");
- FileInputStream fin = null;
- try {
- fin = new FileInputStream(file);
- KeyStore k;
- if (provider == null)
- k = KeyStore.getInstance("JKS");
- else
- k = KeyStore.getInstance("JKS", provider);
- k.load(fin, null);
- return k;
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- finally {
- try{fin.close();}catch(Exception ex){}
- }
- }
-
- /**
- * Verifies a single certificate.
- * @param cert the certificate to verify
- * @param crls the certificate revocation list or null
- * @param calendar the date or null
for the current date
- * @return a String
with the error description or null
- * if no error
- */
- public static String verifyCertificate(X509Certificate cert, Collection crls, Calendar calendar) {
- if (calendar == null)
- calendar = new GregorianCalendar();
- if (cert.hasUnsupportedCriticalExtension())
- return "Has unsupported critical extension";
- try {
- cert.checkValidity(calendar.getTime());
- }
- catch (Exception e) {
- return e.getMessage();
- }
- if (crls != null) {
- for (Iterator it = crls.iterator(); it.hasNext();) {
- if (((CRL)it.next()).isRevoked(cert))
- return "Certificate revoked";
- }
- }
- return null;
- }
-
- /**
- * Verifies a certificate chain against a KeyStore.
- * @param certs the certificate chain
- * @param keystore the KeyStore
- * @param crls the certificate revocation list or null
- * @param calendar the date or null
for the current date
- * @return null
if the certificate chain could be validade or a
- * Object[]{cert,error}
where cert
is the
- * failed certificate and error
is the error message
- */
- public static Object[] verifyCertificates(Certificate certs[], KeyStore keystore, Collection crls, Calendar calendar) {
- if (calendar == null)
- calendar = new GregorianCalendar();
- for (int k = 0; k < certs.length; ++k) {
- X509Certificate cert = (X509Certificate)certs[k];
- String err = verifyCertificate(cert, crls, calendar);
- if (err != null)
- return new Object[]{cert, err};
- try {
- for (Enumeration aliases = keystore.aliases(); aliases.hasMoreElements();) {
- try {
- String alias = (String)aliases.nextElement();
- if (!keystore.isCertificateEntry(alias))
- continue;
- X509Certificate certStoreX509 = (X509Certificate)keystore.getCertificate(alias);
- if (verifyCertificate(certStoreX509, crls, calendar) != null)
- continue;
- try {
- cert.verify(certStoreX509.getPublicKey());
- return null;
- }
- catch (Exception e) {
- continue;
- }
- }
- catch (Exception ex) {
- }
- }
- }
- catch (Exception e) {
- }
- int j;
- for (j = 0; j < certs.length; ++j) {
- if (j == k)
- continue;
- X509Certificate certNext = (X509Certificate)certs[j];
- try {
- cert.verify(certNext.getPublicKey());
- break;
- }
- catch (Exception e) {
- }
- }
- if (j == certs.length)
- return new Object[]{cert, "Cannot be verified against the KeyStore or the certificate chain"};
- }
- return new Object[]{null, "Invalid state. Possible circular certificate chain"};
- }
-
- /**
- * Get the "issuer" from the TBSCertificate bytes that are passed in
- * @param enc a TBSCertificate in a byte array
- * @return a DERObject
- */
- private static DERObject getIssuer(byte[] enc) {
- try {
- ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(enc));
- ASN1Sequence seq = (ASN1Sequence)in.readObject();
- return (DERObject)seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 3 : 2);
- }
- catch (IOException e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Get the "subject" from the TBSCertificate bytes that are passed in
- * @param enc A TBSCertificate in a byte array
- * @return a DERObject
- */
- private static DERObject getSubject(byte[] enc) {
- try {
- ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(enc));
- ASN1Sequence seq = (ASN1Sequence)in.readObject();
- return (DERObject)seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 5 : 4);
- }
- catch (IOException e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Get the issuer fields from an X509 Certificate
- * @param cert an X509Certificate
- * @return an X509Name
- */
- public static X509Name getIssuerFields(X509Certificate cert) {
- try {
- return new X509Name((ASN1Sequence)getIssuer(cert.getTBSCertificate()));
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Get the subject fields from an X509 Certificate
- * @param cert an X509Certificate
- * @return an X509Name
- */
- public static X509Name getSubjectFields(X509Certificate cert) {
- try {
- return new X509Name((ASN1Sequence)getSubject(cert.getTBSCertificate()));
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Gets the bytes for the PKCS#1 object.
- * @return a byte array
- */
- public byte[] getEncodedPKCS1() {
- try {
- if (externalDigest != null)
- digest = externalDigest;
- else
- digest = sig.sign();
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- ASN1OutputStream dout = new ASN1OutputStream(bOut);
- dout.writeObject(new DEROctetString(digest));
- dout.close();
-
- return bOut.toByteArray();
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Sets the digest/signature to an external calculated value.
- * @param digest the digest. This is the actual signature
- * @param RSAdata the extra data that goes into the data tag in PKCS#7
- * @param digestEncryptionAlgorithm the encryption algorithm. It may must be null
if the digest
- * is also null
. If the digest
is not null
- * then it may be "RSA" or "DSA"
- */
- public void setExternalDigest(byte digest[], byte RSAdata[], String digestEncryptionAlgorithm) {
- externalDigest = digest;
- externalRSAdata = RSAdata;
- if (digestEncryptionAlgorithm != null) {
- if (digestEncryptionAlgorithm.equals("RSA")) {
- this.digestEncryptionAlgorithm = ID_RSA;
- }
- else if (digestEncryptionAlgorithm.equals("DSA")) {
- this.digestEncryptionAlgorithm = ID_DSA;
- }
- else
- throw new ExceptionConverter(new NoSuchAlgorithmException("Unknown Key Algorithm "+digestEncryptionAlgorithm));
- }
- }
-
- /**
- * Gets the bytes for the PKCS7SignedData object.
- * @return the bytes for the PKCS7SignedData object
- */
- public byte[] getEncodedPKCS7() {
- return getEncodedPKCS7(null, null);
- }
-
- /**
- * Gets the bytes for the PKCS7SignedData object. Optionally the authenticatedAttributes
- * in the signerInfo can also be set. If either of the parameters is null
, none will be used.
- * @param secondDigest the digest in the authenticatedAttributes
- * @param signingTime the signing time in the authenticatedAttributes
- * @return the bytes for the PKCS7SignedData object
- */
- public byte[] getEncodedPKCS7(byte secondDigest[], Calendar signingTime) {
- try {
- if (externalDigest != null) {
- digest = externalDigest;
- if (RSAdata != null)
- RSAdata = externalRSAdata;
- }
- else if (externalRSAdata != null && RSAdata != null) {
- RSAdata = externalRSAdata;
- sig.update(RSAdata);
- digest = sig.sign();
- }
- else {
- if (RSAdata != null) {
- RSAdata = messageDigest.digest();
- sig.update(RSAdata);
- }
- digest = sig.sign();
- }
-
- // Create the set of Hash algorithms
- DERConstructedSet digestAlgorithms = new DERConstructedSet();
- for(Iterator it = digestalgos.iterator(); it.hasNext();) {
- ASN1EncodableVector algos = new ASN1EncodableVector();
- algos.add(new DERObjectIdentifier((String)it.next()));
- algos.add(new DERNull());
- digestAlgorithms.addObject(new DERSequence(algos));
- }
-
- // Create the contentInfo.
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(new DERObjectIdentifier(ID_PKCS7_DATA));
- if (RSAdata != null)
- v.add(new DERTaggedObject(0, new DEROctetString(RSAdata)));
- DERSequence contentinfo = new DERSequence(v);
-
- // Get all the certificates
- //
- v = new ASN1EncodableVector();
- for (Iterator i = certs.iterator(); i.hasNext();) {
- ASN1InputStream tempstream = new ASN1InputStream(new ByteArrayInputStream(((X509Certificate)i.next()).getEncoded()));
- v.add(tempstream.readObject());
- }
-
- DERSet dercertificates = new DERSet(v);
-
- // Create signerinfo structure.
- //
- ASN1EncodableVector signerinfo = new ASN1EncodableVector();
-
- // Add the signerInfo version
- //
- signerinfo.add(new DERInteger(signerversion));
-
- v = new ASN1EncodableVector();
- v.add(getIssuer(signCert.getTBSCertificate()));
- v.add(new DERInteger(signCert.getSerialNumber()));
- signerinfo.add(new DERSequence(v));
-
- // Add the digestAlgorithm
- v = new ASN1EncodableVector();
- v.add(new DERObjectIdentifier(digestAlgorithm));
- v.add(new DERNull());
- signerinfo.add(new DERSequence(v));
-
- // add the authenticated attribute if present
- if (secondDigest != null && signingTime != null) {
- ASN1EncodableVector attribute = new ASN1EncodableVector();
- v = new ASN1EncodableVector();
- v.add(new DERObjectIdentifier(ID_CONTENT_TYPE));
- v.add(new DERSet(new DERObjectIdentifier(ID_PKCS7_DATA)));
- attribute.add(new DERSequence(v));
- v = new ASN1EncodableVector();
- v.add(new DERObjectIdentifier(ID_SIGNING_TIME));
- v.add(new DERSet(new DERUTCTime(signingTime.getTime())));
- attribute.add(new DERSequence(v));
- v = new ASN1EncodableVector();
- v.add(new DERObjectIdentifier(ID_MESSAGE_DIGEST));
- v.add(new DERSet(new DEROctetString(secondDigest)));
- attribute.add(new DERSequence(v));
- signerinfo.add(new DERTaggedObject(false, 0, new DERSet(attribute)));
- }
- // Add the digestEncryptionAlgorithm
- v = new ASN1EncodableVector();
- v.add(new DERObjectIdentifier(digestEncryptionAlgorithm));
- v.add(new DERNull());
- signerinfo.add(new DERSequence(v));
-
- // Add the digest
- signerinfo.add(new DEROctetString(digest));
-
-
- // Finally build the body out of all the components above
- ASN1EncodableVector body = new ASN1EncodableVector();
- body.add(new DERInteger(version));
- body.add(digestAlgorithms);
- body.add(contentinfo);
- body.add(new DERTaggedObject(false, 0, dercertificates));
-
- if (crls.size() > 0) {
- v = new ASN1EncodableVector();
- for (Iterator i = crls.iterator();i.hasNext();) {
- ASN1InputStream t = new ASN1InputStream(new ByteArrayInputStream((((X509CRL)i.next()).getEncoded())));
- v.add(t.readObject());
- }
- DERSet dercrls = new DERSet(v);
- body.add(new DERTaggedObject(false, 1, dercrls));
- }
-
- // Only allow one signerInfo
- body.add(new DERSet(new DERSequence(signerinfo)));
-
- // Now we have the body, wrap it in it's PKCS7Signed shell
- // and return it
- //
- ASN1EncodableVector whole = new ASN1EncodableVector();
- whole.add(new DERObjectIdentifier(ID_PKCS7_SIGNED_DATA));
- whole.add(new DERTaggedObject(0, new DERSequence(body)));
-
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- ASN1OutputStream dout = new ASN1OutputStream(bOut);
- dout.writeObject(new DERSequence(whole));
- dout.close();
-
- return bOut.toByteArray();
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
-
- /**
- * When using authenticatedAttributes the authentication process is different.
- * The document digest is generated and put inside the attribute. The signing is done over the DER encoded
- * authenticatedAttributes. This method provides that encoding and the parameters must be
- * exactly the same as in {@link #getEncodedPKCS7(byte[],Calendar)}.
- *
- * A simple example:
- *
- *
- * Calendar cal = Calendar.getInstance();
- * PdfPKCS7 pk7 = new PdfPKCS7(key, chain, null, "SHA1", null, false);
- * MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
- * byte buf[] = new byte[8192];
- * int n;
- * InputStream inp = sap.getRangeStream();
- * while ((n = inp.read(buf)) > 0) {
- * messageDigest.update(buf, 0, n);
- * }
- * byte hash[] = messageDigest.digest();
- * byte sh[] = pk7.getAuthenticatedAttributeBytes(hash, cal);
- * pk7.update(sh, 0, sh.length);
- * byte sg[] = pk7.getEncodedPKCS7(hash, cal);
- *
- * @param secondDigest the content digest
- * @param signingTime the signing time
- * @return the byte array representation of the authenticatedAttributes ready to be signed
- */
- public byte[] getAuthenticatedAttributeBytes(byte secondDigest[], Calendar signingTime) {
- try {
- ASN1EncodableVector attribute = new ASN1EncodableVector();
- ASN1EncodableVector v = new ASN1EncodableVector();
- v.add(new DERObjectIdentifier(ID_CONTENT_TYPE));
- v.add(new DERSet(new DERObjectIdentifier(ID_PKCS7_DATA)));
- attribute.add(new DERSequence(v));
- v = new ASN1EncodableVector();
- v.add(new DERObjectIdentifier(ID_SIGNING_TIME));
- v.add(new DERSet(new DERUTCTime(signingTime.getTime())));
- attribute.add(new DERSequence(v));
- v = new ASN1EncodableVector();
- v.add(new DERObjectIdentifier(ID_MESSAGE_DIGEST));
- v.add(new DERSet(new DEROctetString(secondDigest)));
- attribute.add(new DERSequence(v));
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- ASN1OutputStream dout = new ASN1OutputStream(bOut);
- dout.writeObject(new DERSet(attribute));
- dout.close();
-
- return bOut.toByteArray();
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
- /**
- * Getter for property reason.
- * @return Value of property reason.
- */
- public String getReason() {
- return this.reason;
- }
-
- /**
- * Setter for property reason.
- * @param reason New value of property reason.
- */
- public void setReason(String reason) {
- this.reason = reason;
- }
-
- /**
- * Getter for property location.
- * @return Value of property location.
- */
- public String getLocation() {
- return this.location;
- }
-
- /**
- * Setter for property location.
- * @param location New value of property location.
- */
- public void setLocation(String location) {
- this.location = location;
- }
-
- /**
- * Getter for property signDate.
- * @return Value of property signDate.
- */
- public Calendar getSignDate() {
- return this.signDate;
- }
-
- /**
- * Setter for property signDate.
- * @param signDate New value of property signDate.
- */
- public void setSignDate(Calendar signDate) {
- this.signDate = signDate;
- }
-
- /**
- * Getter for property sigName.
- * @return Value of property sigName.
- */
- public String getSignName() {
- return this.signName;
- }
-
- /**
- * Setter for property sigName.
- * @param signName New value of property sigName.
- */
- public void setSignName(String signName) {
- this.signName = signName;
- }
-
- /**
- * a class that holds an X509 name
- */
- public static class X509Name {
- /**
- * country code - StringType(SIZE(2))
- */
- public static final DERObjectIdentifier C = new DERObjectIdentifier("2.5.4.6");
-
- /**
- * organization - StringType(SIZE(1..64))
- */
- public static final DERObjectIdentifier O = new DERObjectIdentifier("2.5.4.10");
-
- /**
- * organizational unit name - StringType(SIZE(1..64))
- */
- public static final DERObjectIdentifier OU = new DERObjectIdentifier("2.5.4.11");
-
- /**
- * Title
- */
- public static final DERObjectIdentifier T = new DERObjectIdentifier("2.5.4.12");
-
- /**
- * common name - StringType(SIZE(1..64))
- */
- public static final DERObjectIdentifier CN = new DERObjectIdentifier("2.5.4.3");
-
- /**
- * device serial number name - StringType(SIZE(1..64))
- */
- public static final DERObjectIdentifier SN = new DERObjectIdentifier("2.5.4.5");
-
- /**
- * locality name - StringType(SIZE(1..64))
- */
- public static final DERObjectIdentifier L = new DERObjectIdentifier("2.5.4.7");
-
- /**
- * state, or province name - StringType(SIZE(1..64))
- */
- public static final DERObjectIdentifier ST = new DERObjectIdentifier("2.5.4.8");
-
- /** Naming attribute of type X520name */
- public static final DERObjectIdentifier SURNAME = new DERObjectIdentifier("2.5.4.4");
- /** Naming attribute of type X520name */
- public static final DERObjectIdentifier GIVENNAME = new DERObjectIdentifier("2.5.4.42");
- /** Naming attribute of type X520name */
- public static final DERObjectIdentifier INITIALS = new DERObjectIdentifier("2.5.4.43");
- /** Naming attribute of type X520name */
- public static final DERObjectIdentifier GENERATION = new DERObjectIdentifier("2.5.4.44");
- /** Naming attribute of type X520name */
- public static final DERObjectIdentifier UNIQUE_IDENTIFIER = new DERObjectIdentifier("2.5.4.45");
-
- /**
- * Email address (RSA PKCS#9 extension) - IA5String.
- * Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
- */
- public static final DERObjectIdentifier EmailAddress = new DERObjectIdentifier("1.2.840.113549.1.9.1");
-
- /**
- * email address in Verisign certificates
- */
- public static final DERObjectIdentifier E = EmailAddress;
-
- /** object identifier */
- public static final DERObjectIdentifier DC = new DERObjectIdentifier("0.9.2342.19200300.100.1.25");
-
- /** LDAP User id. */
- public static final DERObjectIdentifier UID = new DERObjectIdentifier("0.9.2342.19200300.100.1.1");
-
- /** A HashMap with default symbols */
- public static HashMap DefaultSymbols = new HashMap();
-
- static {
- DefaultSymbols.put(C, "C");
- DefaultSymbols.put(O, "O");
- DefaultSymbols.put(T, "T");
- DefaultSymbols.put(OU, "OU");
- DefaultSymbols.put(CN, "CN");
- DefaultSymbols.put(L, "L");
- DefaultSymbols.put(ST, "ST");
- DefaultSymbols.put(SN, "SN");
- DefaultSymbols.put(EmailAddress, "E");
- DefaultSymbols.put(DC, "DC");
- DefaultSymbols.put(UID, "UID");
- DefaultSymbols.put(SURNAME, "SURNAME");
- DefaultSymbols.put(GIVENNAME, "GIVENNAME");
- DefaultSymbols.put(INITIALS, "INITIALS");
- DefaultSymbols.put(GENERATION, "GENERATION");
- }
- /** A HashMap with values */
- public HashMap values = new HashMap();
-
- /**
- * Constructs an X509 name
- * @param seq an ASN1 Sequence
- */
- public X509Name(ASN1Sequence seq) {
- Enumeration e = seq.getObjects();
-
- while (e.hasMoreElements()) {
- ASN1Set set = (ASN1Set)e.nextElement();
-
- for (int i = 0; i < set.size(); i++) {
- ASN1Sequence s = (ASN1Sequence)set.getObjectAt(i);
- String id = (String)DefaultSymbols.get(s.getObjectAt(0));
- if (id == null)
- continue;
- ArrayList vs = (ArrayList)values.get(id);
- if (vs == null) {
- vs = new ArrayList();
- values.put(id, vs);
- }
- vs.add(((DERString)s.getObjectAt(1)).getString());
- }
- }
- }
- /**
- * Constructs an X509 name
- * @param dirName a directory name
- */
- public X509Name(String dirName) {
- X509NameTokenizer nTok = new X509NameTokenizer(dirName);
-
- while (nTok.hasMoreTokens()) {
- String token = nTok.nextToken();
- int index = token.indexOf('=');
-
- if (index == -1) {
- throw new IllegalArgumentException("badly formated directory string");
- }
-
- String id = token.substring(0, index).toUpperCase();
- String value = token.substring(index + 1);
- ArrayList vs = (ArrayList)values.get(id);
- if (vs == null) {
- vs = new ArrayList();
- values.put(id, vs);
- }
- vs.add(value);
- }
-
- }
-
- public String getField(String name) {
- ArrayList vs = (ArrayList)values.get(name);
- return vs == null ? null : (String)vs.get(0);
- }
-
- /**
- * gets a field array from the values Hashmap
- * @param name
- * @return an ArrayList
- */
- public ArrayList getFieldArray(String name) {
- ArrayList vs = (ArrayList)values.get(name);
- return vs == null ? null : vs;
- }
-
- /**
- * getter for values
- * @return a HashMap with the fields of the X509 name
- */
- public HashMap getFields() {
- return values;
- }
-
- /**
- * @see java.lang.Object#toString()
- */
- public String toString() {
- return values.toString();
- }
- }
-
- /**
- * class for breaking up an X500 Name into it's component tokens, ala
- * java.util.StringTokenizer. We need this class as some of the
- * lightweight Java environment don't support classes like
- * StringTokenizer.
- */
- public static class X509NameTokenizer {
- private String oid;
- private int index;
- private StringBuffer buf = new StringBuffer();
-
- public X509NameTokenizer(
- String oid) {
- this.oid = oid;
- this.index = -1;
- }
-
- public boolean hasMoreTokens() {
- return (index != oid.length());
- }
-
- public String nextToken() {
- if (index == oid.length()) {
- return null;
- }
-
- int end = index + 1;
- boolean quoted = false;
- boolean escaped = false;
-
- buf.setLength(0);
-
- while (end != oid.length()) {
- char c = oid.charAt(end);
-
- if (c == '"') {
- if (!escaped) {
- quoted = !quoted;
- }
- else {
- buf.append(c);
- }
- escaped = false;
- }
- else {
- if (escaped || quoted) {
- buf.append(c);
- escaped = false;
- }
- else if (c == '\\') {
- escaped = true;
- }
- else if (c == ',') {
- break;
- }
- else {
- buf.append(c);
- }
- }
- end++;
- }
-
- index = end;
- return buf.toString().trim();
- }
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfPSXObject.java pdftk-2.01/java/com/lowagie/text/pdf/PdfPSXObject.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfPSXObject.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfPSXObject.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,105 +0,0 @@
-/*
- * Copyright 2005 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-
-/**
- * Implements the PostScript XObject.
- */
-public class PdfPSXObject extends PdfTemplate {
-
- /** Creates a new instance of PdfPSXObject */
- protected PdfPSXObject() {
- super();
- }
-
- /**
- * Constructs a PSXObject
- * @param wr
- */
- public PdfPSXObject(PdfWriter wr) {
- super(wr);
- }
-
- /**
- * Gets the stream representing this object.
- *
- * @return the stream representing this object
- * @throws IOException
- */
-
- PdfStream getFormXObject() throws IOException {
- PdfStream s = new PdfStream(content.toByteArray());
- s.put(PdfName.TYPE, PdfName.XOBJECT);
- s.put(PdfName.SUBTYPE, PdfName.PS);
- s.flateCompress();
- return s;
- }
-
- /**
- * Gets a duplicate of this PdfPSXObject
. All
- * the members are copied by reference but the buffer stays different.
- * @return a copy of this PdfPSXObject
- */
-
- public PdfContentByte getDuplicate() {
- PdfPSXObject tpl = new PdfPSXObject();
- tpl.writer = writer;
- tpl.pdf = pdf;
- tpl.thisReference = thisReference;
- tpl.pageResources = pageResources;
- tpl.separator = separator;
- return tpl;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfPage.java pdftk-2.01/java/com/lowagie/text/pdf/PdfPage.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfPage.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfPage.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,204 +0,0 @@
-/*
- * $Id: PdfPage.java,v 1.47 2004/11/29 14:07:03 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import java.util.HashMap;
-/**
- * PdfPage
is the PDF Page-object.
- *
- * A Page object is a dictionary whose keys describe a single page containing text,
- * graphics, and images. A Page onjects is a leaf of the Pages tree.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 6.4 (page 73-81)
- *
- * @see PdfPageElement
- * @see PdfPages
- */
-
-public class PdfPage extends PdfDictionary {
-
- private static final String boxStrings[] = {"crop", "trim", "art", "bleed"};
- private static final PdfName boxNames[] = {PdfName.CROPBOX, PdfName.TRIMBOX, PdfName.ARTBOX, PdfName.BLEEDBOX};
- // membervariables
-
-/** value of the Rotate key for a page in PORTRAIT */
- public static final PdfNumber PORTRAIT = new PdfNumber(0);
-
-/** value of the Rotate key for a page in LANDSCAPE */
- public static final PdfNumber LANDSCAPE = new PdfNumber(90);
-
-/** value of the Rotate key for a page in INVERTEDPORTRAIT */
- public static final PdfNumber INVERTEDPORTRAIT = new PdfNumber(180);
-
-/** value of the Rotate key for a page in SEASCAPE */
- public static final PdfNumber SEASCAPE = new PdfNumber(270);
-
-/** value of the MediaBox key */
- PdfRectangle mediaBox;
-
- // constructors
-
-/**
- * Constructs a PdfPage
.
- *
- * @param mediaBox a value for the MediaBox key
- * @param resources an indirect reference to a PdfResources
-object
- * @param rotate a value for the Rotate key
- */
-
-// PdfPage(PdfRectangle mediaBox, Rectangle cropBox, PdfIndirectReference resources, PdfNumber rotate) {
-// super(PAGE);
-// this.mediaBox = mediaBox;
-// put(PdfName.MEDIABOX, mediaBox);
-// put(PdfName.RESOURCES, resources);
-// if (rotate != null) {
-// put(PdfName.ROTATE, rotate);
-// }
-// if (cropBox != null)
-// put(PdfName.CROPBOX, new PdfRectangle(cropBox));
-// }
-
-/**
- * Constructs a PdfPage
.
- *
- * @param mediaBox a value for the MediaBox key
- * @param resources an indirect reference to a PdfResources
-object
- * @param rotate a value for the Rotate key
- */
-
- PdfPage(PdfRectangle mediaBox, HashMap boxSize, PdfDictionary resources, int rotate) {
- super(PAGE);
- this.mediaBox = mediaBox;
- put(PdfName.MEDIABOX, mediaBox);
- put(PdfName.RESOURCES, resources);
- if (rotate != 0) {
- put(PdfName.ROTATE, new PdfNumber(rotate));
- }
- for (int k = 0; k < boxStrings.length; ++k) {
- PdfObject rect = (PdfObject)boxSize.get(boxStrings[k]);
- if (rect != null)
- put(boxNames[k], rect);
- }
- }
-
-/**
- * Constructs a PdfPage
.
- *
- * @param mediaBox a value for the MediaBox key
- * @param resources an indirect reference to a PdfResources
-object
- */
-
-// PdfPage(PdfRectangle mediaBox, Rectangle cropBox, PdfIndirectReference resources) {
-// this(mediaBox, cropBox, resources, null);
-// }
-
-/**
- * Constructs a PdfPage
.
- *
- * @param mediaBox a value for the MediaBox key
- * @param resources an indirect reference to a PdfResources
-object
- */
-
- PdfPage(PdfRectangle mediaBox, HashMap boxSize, PdfDictionary resources) {
- this(mediaBox, boxSize, resources, 0);
- }
-
-/**
- * Checks if this page element is a tree of pages.
- *
- * This method allways returns false
.
- *
- * @return false
because this is a single page
- */
-
- public boolean isParent() {
- return false;
- }
-
- // methods
-
-/**
- * Adds an indirect reference pointing to a PdfContents
-object.
- *
- * @param contents an indirect reference to a PdfContents
-object
- */
-
- void add(PdfIndirectReference contents) {
- put(PdfName.CONTENTS, contents);
- }
-
-/**
- * Rotates the mediabox, but not the text in it.
- *
- * @return a PdfRectangle
- */
-
- PdfRectangle rotateMediaBox() {
- this.mediaBox = mediaBox.rotate();
- put(PdfName.MEDIABOX, this.mediaBox);
- return this.mediaBox;
- }
-
-/**
- * Returns the MediaBox of this Page.
- *
- * @return a PdfRectangle
- */
-
- PdfRectangle getMediaBox() {
- return mediaBox;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfPageElement.java pdftk-2.01/java/com/lowagie/text/pdf/PdfPageElement.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfPageElement.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfPageElement.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,84 +0,0 @@
-/*
- * $Id: PdfPageElement.java,v 1.24 2002/07/09 11:28:23 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * The PdfPageElement
interface has to be implemented by PdfPage
and PdfPages
.
- *
- * @see PdfPage
- * @see PdfPages
- */
-
-interface PdfPageElement {
-
-/**
- * Set the value for the Parent key in the Page or Pages Dictionary.
- *
- * @param reference an indirect reference to a PdfPages
-object
- */
-
- public void setParent(PdfIndirectReference reference);
-
-/**
- * Checks if this page element is a tree of pages.
- *
- * @return true
if it's a tree of pages;
- * false
if it's a single page
- */
-
- public boolean isParent();
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfPageEvent.java pdftk-2.01/java/com/lowagie/text/pdf/PdfPageEvent.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfPageEvent.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfPageEvent.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,196 +0,0 @@
-/*
- * $Id: PdfPageEvent.java,v 1.23 2002/07/09 11:28:24 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import com.lowagie.text.Document;
-import com.lowagie.text.Rectangle;
-import com.lowagie.text.Paragraph;
-
-/**
- * Allows a class to catch several document events.
- *
- * Note: do not use Document.add() inside a page event.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-
-public interface PdfPageEvent {
-
-/**
- * Called when the document is opened.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- */
- public void onOpenDocument(PdfWriter writer, Document document);
-
-/**
- * Called when a page is initialized.
- *
- * Note that if even if a page is not written this method is still
- * called. It is preferable to use onEndPage
to avoid
- * infinite loops.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- */
- public void onStartPage(PdfWriter writer, Document document);
-
-/**
- * Called when a page is finished, just before being written to the document.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- */
- public void onEndPage(PdfWriter writer, Document document);
-
-/**
- * Called when the document is closed.
- *
- * Note that this method is called with the page number equal
- * to the last page plus one.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- */
- public void onCloseDocument(PdfWriter writer, Document document);
-
-/**
- * Called when a Paragraph is written.
- *
- * paragraphPosition
will hold the height at which the
- * paragraph will be written to. This is useful to insert bookmarks with
- * more control.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param paragraphPosition the position the paragraph will be written to
- */
- public void onParagraph(PdfWriter writer, Document document, float paragraphPosition);
-
-/**
- * Called when a Paragraph is written.
- *
- * paragraphPosition
will hold the height of the end of the paragraph.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param paragraphPosition the position of the end of the paragraph
- */
- public void onParagraphEnd(PdfWriter writer,Document document,float paragraphPosition);
-
-/**
- * Called when a Chapter is written.
- *
- * position
will hold the height at which the
- * chapter will be written to.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param paragraphPosition the position the chapter will be written to
- * @param title the title of the Chapter
- */
- public void onChapter(PdfWriter writer,Document document,float paragraphPosition, Paragraph title);
-
-/**
- * Called when the end of a Chapter is reached.
- *
- * position
will hold the height of the end of the chapter.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param paragraphPosition the position the chapter will be written to
- */
- public void onChapterEnd(PdfWriter writer,Document document,float paragraphPosition);
-
-/**
- * Called when a Section is written.
- *
- * position
will hold the height at which the
- * section will be written to.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param paragraphPosition the position the section will be written to
- * @param depth the number depth of the section
- * @param title the title of the section
- */
- public void onSection(PdfWriter writer,Document document,float paragraphPosition, int depth, Paragraph title);
-
-/**
- * Called when the end of a Section is reached.
- *
- * position
will hold the height of the section end.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param paragraphPosition the position the section will be written to
- */
- public void onSectionEnd(PdfWriter writer,Document document,float paragraphPosition);
-
-/**
- * Called when a Chunk
with a generic tag is written.
- *
- * It is usefull to pinpoint the Chunk
location to generate
- * bookmarks, for example.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param rect the Rectangle
containing the Chunk
- * @param text the text of the tag
- */
- public void onGenericTag(PdfWriter writer, Document document, Rectangle rect, String text);
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfPageEventHelper.java pdftk-2.01/java/com/lowagie/text/pdf/PdfPageEventHelper.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfPageEventHelper.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfPageEventHelper.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,208 +0,0 @@
-/*
- * $Id: PdfPageEventHelper.java,v 1.23 2002/07/09 11:28:24 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import com.lowagie.text.Document;
-import com.lowagie.text.Rectangle;
-import com.lowagie.text.Paragraph;
-
-/**
- * Helps the use of PdfPageEvent
by implementing all the interface methods.
- * A class can extend PdfPageEventHelper
and only implement the
- * needed methods.
- *
- * Note: do not use Document.add() inside a page event.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-
-public class PdfPageEventHelper implements PdfPageEvent {
-
-/**
- * Called when the document is opened.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- */
- public void onOpenDocument(PdfWriter writer,Document document) {
- }
-
-/**
- * Called when a page is initialized.
- *
- * Note that if even if a page is not written this method is still
- * called. It is preferable to use onEndPage
to avoid
- * infinite loops.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- */
- public void onStartPage(PdfWriter writer,Document document) {
- }
-
-/**
- * Called when a page is finished, just before being written to the document.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- */
- public void onEndPage(PdfWriter writer,Document document) {
- }
-
-/**
- * Called when the document is closed.
- *
- * Note that this method is called with the page number equal
- * to the last page plus one.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- */
- public void onCloseDocument(PdfWriter writer,Document document) {
- }
-
-/**
- * Called when a Paragraph is written.
- *
- * paragraphPosition
will hold the height at which the
- * paragraph will be written to. This is useful to insert bookmarks with
- * more control.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param paragraphPosition the position the paragraph will be written to
- */
- public void onParagraph(PdfWriter writer,Document document,float paragraphPosition) {
- }
-
-/**
- * Called when a Paragraph is written.
- *
- * paragraphPosition
will hold the height of the end of the paragraph.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param paragraphPosition the position of the end of the paragraph
- */
- public void onParagraphEnd(PdfWriter writer,Document document,float paragraphPosition) {
- }
-
-/**
- * Called when a Chapter is written.
- *
- * position
will hold the height at which the
- * chapter will be written to.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param paragraphPosition the position the chapter will be written to
- * @param title the title of the Chapter
- */
- public void onChapter(PdfWriter writer,Document document,float paragraphPosition,Paragraph title) {
- }
-
-/**
- * Called when the end of a Chapter is reached.
- *
- * position
will hold the height of the end of the chapter.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param position the position of the end of the chapter.
- */
- public void onChapterEnd(PdfWriter writer,Document document,float position) {
- }
-
-/**
- * Called when a Section is written.
- *
- * position
will hold the height at which the
- * section will be written to.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param paragraphPosition the position the section will be written to
- * @param depth the number depth of the Section
- * @param title the title of the section
- */
- public void onSection(PdfWriter writer,Document document,float paragraphPosition,int depth,Paragraph title) {
- }
-
-/**
- * Called when the end of a Section is reached.
- *
- * position
will hold the height of the section end.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param position the position of the end of the section
- */
- public void onSectionEnd(PdfWriter writer,Document document,float position) {
- }
-
-/**
- * Called when a Chunk
with a generic tag is written.
- *
- * It is usefull to pinpoint the Chunk
location to generate
- * bookmarks, for example.
- *
- * @param writer the PdfWriter
for this document
- * @param document the document
- * @param rect the Rectangle
containing the Chunk
- * @param text the text of the tag
- */
- public void onGenericTag(PdfWriter writer,Document document,Rectangle rect,String text) {
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfPageLabels.java pdftk-2.01/java/com/lowagie/text/pdf/PdfPageLabels.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfPageLabels.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfPageLabels.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,197 +0,0 @@
-/*
- * $Id: PdfPageLabels.java,v 1.14 2002/07/09 11:28:24 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.util.Comparator;
-import java.util.TreeMap;
-import java.util.Iterator;
-
-/** Page labels are used to identify each
- * page visually on the screen or in print.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfPageLabels implements Comparator {
-
- /** Logical pages will have the form 1,2,3,...
- */
- public static int DECIMAL_ARABIC_NUMERALS = 0;
- /** Logical pages will have the form I,II,III,IV,...
- */
- public static int UPPERCASE_ROMAN_NUMERALS = 1;
- /** Logical pages will have the form i,ii,iii,iv,...
- */
- public static int LOWERCASE_ROMAN_NUMERALS = 2;
- /** Logical pages will have the form of uppercase letters
- * (A to Z for the first 26 pages, AA to ZZ for the next 26, and so on)
- */
- public static int UPPERCASE_LETTERS = 3;
- /** Logical pages will have the form of uppercase letters
- * (a to z for the first 26 pages, aa to zz for the next 26, and so on)
- */
- public static int LOWERCASE_LETTERS = 4;
- /** No logical page numbers are generated but fixed text may
- * still exist
- */
- public static int EMPTY = 5;
- /** Dictionary values to set the logical page styles
- */
- static PdfName numberingStyle[] = new PdfName[]{PdfName.D, PdfName.R,
- new PdfName("r"), PdfName.A, new PdfName("a")};
- /** The sequence of logical pages. Will contain at least a value for page 1
- */
- TreeMap map;
-
- /** Creates a new PdfPageLabel with a default logical page 1
- */
- public PdfPageLabels() {
- map = new TreeMap(this);
- addPageLabel(1, DECIMAL_ARABIC_NUMERALS, null, 1);
- }
-
- /** Compares two Integer
.
- * @param obj the first Integer
- * @param obj1 the second Integer
- * @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second
- */
- public int compare(Object obj, Object obj1) {
- int v1 = ((Integer)obj).intValue();
- int v2 = ((Integer)obj1).intValue();
- if (v1 < v2)
- return -1;
- if (v1 == v2)
- return 0;
- return 1;
- }
-
- /** Not used
- * @param obj not used
- * @return always true
- */
- public boolean equals(Object obj) {
- return true;
- }
-
- /** Adds or replaces a page label.
- * @param page the real page to start the numbering. First page is 1
- * @param numberStyle the numbering style such as LOWERCASE_ROMAN_NUMERALS
- * @param text the text to prefix the number. Can be null
or empty
- * @param firstPage the first logical page number
- */
- public void addPageLabel(int page, int numberStyle, String text, int firstPage) {
- if (page < 1 || firstPage < 1)
- throw new IllegalArgumentException("In a page label the page numbers must be greater or equal to 1.");
- PdfName pdfName = null;
- if (numberStyle >= 0 && numberStyle < numberingStyle.length)
- pdfName = numberingStyle[numberStyle];
- Integer iPage = new Integer(page);
- Object obj = new Object[]{iPage, pdfName, text, new Integer(firstPage)};
- map.put(iPage, obj);
- }
-
- /** Adds or replaces a page label. The first logical page has the default
- * of 1.
- * @param page the real page to start the numbering. First page is 1
- * @param numberStyle the numbering style such as LOWERCASE_ROMAN_NUMERALS
- * @param text the text to prefix the number. Can be null
or empty
- */
- public void addPageLabel(int page, int numberStyle, String text) {
- addPageLabel(page, numberStyle, text, 1);
- }
-
- /** Adds or replaces a page label. There is no text prefix and the first
- * logical page has the default of 1.
- * @param page the real page to start the numbering. First page is 1
- * @param numberStyle the numbering style such as LOWERCASE_ROMAN_NUMERALS
- */
- public void addPageLabel(int page, int numberStyle) {
- addPageLabel(page, numberStyle, null, 1);
- }
-
- /** Removes a page label. The first page label can not be removed, only changed.
- * @param page the real page to remove
- */
- public void removePageLabel(int page) {
- if (page <= 1)
- return;
- map.remove(new Integer(page));
- }
-
- /** Gets the page label dictionary to insert into the document.
- * @return the page label dictionary
- */
- PdfDictionary getDictionary() {
- PdfDictionary dic = new PdfDictionary();
- PdfArray array = new PdfArray();
- for (Iterator it = map.values().iterator(); it.hasNext();) {
- Object obj[] = (Object[])it.next();
- PdfDictionary subDic = new PdfDictionary();
- PdfName pName = (PdfName)obj[1];
- if (pName != null)
- subDic.put(PdfName.S, pName);
- String text = (String)obj[2];
- if (text != null)
- subDic.put(PdfName.P, new PdfString(text, PdfObject.TEXT_UNICODE));
- int st = ((Integer)obj[3]).intValue();
- if (st != 1)
- subDic.put(PdfName.ST, new PdfNumber(st));
- array.add(new PdfNumber(((Integer)obj[0]).intValue() - 1));
- array.add(subDic);
- }
- dic.put(PdfName.NUMS, array);
- return dic;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfPages.java pdftk-2.01/java/com/lowagie/text/pdf/PdfPages.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfPages.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfPages.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,212 +0,0 @@
-/*
- * $Id: PdfPages.java,v 1.33 2003/05/02 09:01:26 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.ExceptionConverter;
-
-/**
- * PdfPages
is the PDF Pages-object.
- *
- * The Pages of a document are accessible through a tree of nodes known as the Pages tree.
- * This tree defines the ordering of the pages in the document.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 6.3 (page 71-73)
- *
- * @see PdfPageElement
- * @see PdfPage
- */
-
-public class PdfPages {
-
- private ArrayList pages = new ArrayList();
- private ArrayList parents = new ArrayList();
- private int leafSize = 10;
- private PdfWriter writer;
- private PdfIndirectReference topParent;
-
- // constructors
-
-/**
- * Constructs a PdfPages
-object.
- */
-
- PdfPages(PdfWriter writer) {
- this.writer = writer;
- }
-
- void addPage(PdfDictionary page) {
- try {
- if ((pages.size() % leafSize) == 0)
- parents.add(writer.getPdfIndirectReference());
- PdfIndirectReference parent = (PdfIndirectReference)parents.get(parents.size() - 1);
- page.put(PdfName.PARENT, parent);
- PdfIndirectReference current = writer.getCurrentPage();
- writer.addToBody(page, current);
- pages.add(current);
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- PdfIndirectReference addPageRef(PdfIndirectReference pageRef) {
- try {
- if ((pages.size() % leafSize) == 0)
- parents.add(writer.getPdfIndirectReference());
- pages.add(pageRef);
- return (PdfIndirectReference)parents.get(parents.size() - 1);
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- // returns the top parent to include in the catalog
- PdfIndirectReference writePageTree() throws IOException {
- if (pages.size() == 0)
- throw new IOException("The document has no pages.");
- int leaf = 1;
- ArrayList tParents = parents;
- ArrayList tPages = pages;
- ArrayList nextParents = new ArrayList();
- while (true) {
- leaf *= leafSize;
- int stdCount = leafSize;
- int rightCount = tPages.size() % leafSize;
- if (rightCount == 0)
- rightCount = leafSize;
- for (int p = 0; p < tParents.size(); ++p) {
- int count;
- int thisLeaf = leaf;
- if (p == tParents.size() - 1) {
- count = rightCount;
- thisLeaf = pages.size() % leaf;
- if (thisLeaf == 0)
- thisLeaf = leaf;
- }
- else
- count = stdCount;
- PdfDictionary top = new PdfDictionary(PdfName.PAGES);
- top.put(PdfName.COUNT, new PdfNumber(thisLeaf));
- PdfArray kids = new PdfArray();
- ArrayList internal = kids.getArrayList();
- internal.addAll(tPages.subList(p * stdCount, p * stdCount + count));
- top.put(PdfName.KIDS, kids);
- if (tParents.size() > 1) {
- if ((p % leafSize) == 0)
- nextParents.add(writer.getPdfIndirectReference());
- top.put(PdfName.PARENT, (PdfIndirectReference)nextParents.get(p / leafSize));
- }
- writer.addToBody(top, (PdfIndirectReference)tParents.get(p));
- }
- if (tParents.size() == 1) {
- topParent = (PdfIndirectReference)tParents.get(0);
- return topParent;
- }
- tPages = tParents;
- tParents = nextParents;
- nextParents = new ArrayList();
- }
- }
-
- PdfIndirectReference getTopParent() {
- return topParent;
- }
-
- void setLinearMode(PdfIndirectReference topParent) {
- if (parents.size() > 1)
- throw new RuntimeException("Linear page mode can only be called with a single parent.");
- if (topParent != null) {
- this.topParent = topParent;
- parents.clear();
- parents.add(topParent);
- }
- leafSize = 10000000;
- }
-
- void addPage(PdfIndirectReference page) {
- pages.add(page);
- }
-
- int reorderPages(int order[]) throws DocumentException {
- if (order == null)
- return pages.size();
- if (parents.size() > 1)
- throw new DocumentException("Page reordering requires a single parent in the page tree. Call PdfWriter.setLinearMode() after open.");
- if (order.length != pages.size())
- throw new DocumentException("Page reordering requires an array with the same size as the number of pages.");
- int max = pages.size();
- boolean temp[] = new boolean[max];
- for (int k = 0; k < max; ++k) {
- int p = order[k];
- if (p < 1 || p > max)
- throw new DocumentException("Page reordering requires pages between 1 and " + max + ". Found " + p + ".");
- if (temp[p - 1])
- throw new DocumentException("Page reordering requires no page repetition. Page " + p + " is repeated.");
- temp[p - 1] = true;
- }
- Object copy[] = pages.toArray();
- for (int k = 0; k < max; ++k) {
- pages.set(k, copy[order[k] - 1]);
- }
- return max;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfPattern.java pdftk-2.01/java/com/lowagie/text/pdf/PdfPattern.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfPattern.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfPattern.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,89 +0,0 @@
-/*
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.ExceptionConverter;
-
-/**
- * A PdfPattern
defines a ColorSpace
- *
- * @see PdfStream
- */
-
-public class PdfPattern extends PdfStream {
-
- PdfPattern(PdfPatternPainter painter) {
- super();
- PdfNumber one = new PdfNumber(1);
- PdfArray matrix = painter.getMatrix();
- if ( matrix != null ) {
- put(PdfName.MATRIX, matrix);
- }
- put(PdfName.TYPE, PdfName.PATTERN);
- put(PdfName.BBOX, new PdfRectangle(painter.getBoundingBox()));
- put(PdfName.RESOURCES, painter.getResources());
- put(PdfName.TILINGTYPE, one);
- put(PdfName.PATTERNTYPE, one);
- if (painter.isStencil())
- put(PdfName.PAINTTYPE, new PdfNumber(2));
- else
- put(PdfName.PAINTTYPE, one);
- put(PdfName.XSTEP, new PdfNumber(painter.getXStep()));
- put(PdfName.YSTEP, new PdfNumber(painter.getYStep()));
- bytes = painter.toPdf(null);
- put(PdfName.LENGTH, new PdfNumber(bytes.length));
- try {
- flateCompress();
- } catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfPatternPainter.java pdftk-2.01/java/com/lowagie/text/pdf/PdfPatternPainter.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfPatternPainter.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfPatternPainter.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,399 +0,0 @@
-/*
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-// import com.lowagie.text.DocumentException;
-// import com.lowagie.text.Image; ssteward: dropped in 1.44
-import com.lowagie.text.Rectangle;
-import java.awt.Color;
-
-/**
- * Implements the pattern.
- */
-
-public class PdfPatternPainter extends PdfTemplate {
-
- protected float xstep, ystep;
- protected boolean stencil = false;
- protected Color defaultColor;
-
- /**
- *Creates a PdfPattern
.
- */
-
- private PdfPatternPainter() {
- super(null);
- type = TYPE_PATTERN;
- }
-
- /**
- * Creates new PdfPattern
- *
- * @param wr the PdfWriter
- */
-
- PdfPatternPainter(PdfWriter wr) {
- super(wr);
- type = TYPE_PATTERN;
- }
-
- PdfPatternPainter(PdfWriter wr, Color defaultColor) {
- this(wr);
- stencil = true;
- if (defaultColor == null)
- this.defaultColor = Color.gray;
- else
- this.defaultColor = defaultColor;
- }
-
- /**
- * Sets the horizontal interval of this pattern.
- *
- * @param xstep the xstep in horizontal painting
- */
-
- public void setXStep(float xstep) {
- this.xstep = xstep;
- }
-
- /**
- * Sets the vertical interval of this pattern.
- *
- * @param ystep in vertical painting
- */
-
- public void setYStep(float ystep) {
- this.ystep = ystep;
- }
-
- /**
- * Returns the horizontal interval when repeating the pattern.
- * @return a value
- */
- public float getXStep() {
- return this.xstep;
- }
-
- /**
- * Returns the vertical interval when repeating the pattern.
- * @return a value
- */
- public float getYStep() {
- return this.ystep;
- }
-
- /**
- * Tells you if this pattern is colored/uncolored (stencil = uncolored, you need to set a default color).
- * @return true if the pattern is an uncolored tiling pattern (stencil).
- */
- public boolean isStencil() {
- return stencil;
- }
-
- /**
- * Sets the transformation matrix for the pattern.
- * @param a
- * @param b
- * @param c
- * @param d
- * @param e
- * @param f
- */
- public void setPatternMatrix(float a, float b, float c, float d, float e, float f) {
- setMatrix(a, b, c, d, e, f);
- }
- /**
- * Gets the stream representing this pattern
- *
- * @return the stream representing this pattern
- */
-
- PdfPattern getPattern() {
- return new PdfPattern(this);
- }
-
- /**
- * Gets a duplicate of this PdfPatternPainter
. All
- * the members are copied by reference but the buffer stays different.
- * @return a copy of this PdfPatternPainter
- */
-
- public PdfContentByte getDuplicate() {
- PdfPatternPainter tpl = new PdfPatternPainter();
- tpl.writer = writer;
- tpl.pdf = pdf;
- tpl.thisReference = thisReference;
- tpl.pageResources = pageResources;
- tpl.bBox = new Rectangle(bBox);
- tpl.xstep = xstep;
- tpl.ystep = ystep;
- tpl.matrix = matrix;
- tpl.stencil = stencil;
- tpl.defaultColor = defaultColor;
- return tpl;
- }
-
- /**
- * Returns the default color of the pattern.
- * @return a Color
- */
- public Color getDefaultColor() {
- return defaultColor;
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setGrayFill(float)
- */
- public void setGrayFill(float gray) {
- checkNoColor();
- super.setGrayFill(gray);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#resetGrayFill()
- */
- public void resetGrayFill() {
- checkNoColor();
- super.resetGrayFill();
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setGrayStroke(float)
- */
- public void setGrayStroke(float gray) {
- checkNoColor();
- super.setGrayStroke(gray);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#resetGrayStroke()
- */
- public void resetGrayStroke() {
- checkNoColor();
- super.resetGrayStroke();
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setRGBColorFillF(float, float, float)
- */
- public void setRGBColorFillF(float red, float green, float blue) {
- checkNoColor();
- super.setRGBColorFillF(red, green, blue);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#resetRGBColorFill()
- */
- public void resetRGBColorFill() {
- checkNoColor();
- super.resetRGBColorFill();
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setRGBColorStrokeF(float, float, float)
- */
- public void setRGBColorStrokeF(float red, float green, float blue) {
- checkNoColor();
- super.setRGBColorStrokeF(red, green, blue);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#resetRGBColorStroke()
- */
- public void resetRGBColorStroke() {
- checkNoColor();
- super.resetRGBColorStroke();
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setCMYKColorFillF(float, float, float, float)
- */
- public void setCMYKColorFillF(float cyan, float magenta, float yellow, float black) {
- checkNoColor();
- super.setCMYKColorFillF(cyan, magenta, yellow, black);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#resetCMYKColorFill()
- */
- public void resetCMYKColorFill() {
- checkNoColor();
- super.resetCMYKColorFill();
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setCMYKColorStrokeF(float, float, float, float)
- */
- public void setCMYKColorStrokeF(float cyan, float magenta, float yellow, float black) {
- checkNoColor();
- super.setCMYKColorStrokeF(cyan, magenta, yellow, black);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#resetCMYKColorStroke()
- */
- public void resetCMYKColorStroke() {
- checkNoColor();
- super.resetCMYKColorStroke();
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#addImage(com.lowagie.text.Image, float, float, float, float, float, float)
- */
- /* ssteward: dropped in 1.44
- public void addImage(Image image, float a, float b, float c, float d, float e, float f) throws DocumentException {
- if (stencil && !image.isMask())
- checkNoColor();
- super.addImage(image, a, b, c, d, e, f);
- }
- */
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setCMYKColorFill(int, int, int, int)
- */
- public void setCMYKColorFill(int cyan, int magenta, int yellow, int black) {
- checkNoColor();
- super.setCMYKColorFill(cyan, magenta, yellow, black);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setCMYKColorStroke(int, int, int, int)
- */
- public void setCMYKColorStroke(int cyan, int magenta, int yellow, int black) {
- checkNoColor();
- super.setCMYKColorStroke(cyan, magenta, yellow, black);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setRGBColorFill(int, int, int)
- */
- public void setRGBColorFill(int red, int green, int blue) {
- checkNoColor();
- super.setRGBColorFill(red, green, blue);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setRGBColorStroke(int, int, int)
- */
- public void setRGBColorStroke(int red, int green, int blue) {
- checkNoColor();
- super.setRGBColorStroke(red, green, blue);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setColorStroke(java.awt.Color)
- */
- public void setColorStroke(Color color) {
- checkNoColor();
- super.setColorStroke(color);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setColorFill(java.awt.Color)
- */
- public void setColorFill(Color color) {
- checkNoColor();
- super.setColorFill(color);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setColorFill(com.lowagie.text.pdf.PdfSpotColor, float)
- */
- public void setColorFill(PdfSpotColor sp, float tint) {
- checkNoColor();
- super.setColorFill(sp, tint);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setColorStroke(com.lowagie.text.pdf.PdfSpotColor, float)
- */
- public void setColorStroke(PdfSpotColor sp, float tint) {
- checkNoColor();
- super.setColorStroke(sp, tint);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setPatternFill(com.lowagie.text.pdf.PdfPatternPainter)
- */
- public void setPatternFill(PdfPatternPainter p) {
- checkNoColor();
- super.setPatternFill(p);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setPatternFill(com.lowagie.text.pdf.PdfPatternPainter, java.awt.Color, float)
- */
- public void setPatternFill(PdfPatternPainter p, Color color, float tint) {
- checkNoColor();
- super.setPatternFill(p, color, tint);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setPatternStroke(com.lowagie.text.pdf.PdfPatternPainter, java.awt.Color, float)
- */
- public void setPatternStroke(PdfPatternPainter p, Color color, float tint) {
- checkNoColor();
- super.setPatternStroke(p, color, tint);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfContentByte#setPatternStroke(com.lowagie.text.pdf.PdfPatternPainter)
- */
- public void setPatternStroke(PdfPatternPainter p) {
- checkNoColor();
- super.setPatternStroke(p);
- }
-
- void checkNoColor() {
- if (stencil)
- throw new RuntimeException("Colors are not allowed in uncolored tile patterns.");
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfReader.java pdftk-2.01/java/com/lowagie/text/pdf/PdfReader.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfReader.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfReader.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,3223 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * $Id: PdfReader.java,v 1.64 2005/10/13 09:36:06 psoares33 Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.Iterator;
-import java.util.zip.InflaterInputStream;
-import java.util.Arrays;
-import java.util.Collections;
-
-import com.lowagie.text.Rectangle;
-import com.lowagie.text.PageSize;
-import com.lowagie.text.StringCompare;
-import com.lowagie.text.ExceptionConverter;
-
-/** Reads a PDF document.
- * @author Paulo Soares (psoares@consiste.pt)
- * @author Kazuya Ujihara
- */
-public class PdfReader {
-
- static final PdfName pageInhCandidates[] = {
- PdfName.MEDIABOX, PdfName.ROTATE, PdfName.RESOURCES, PdfName.CROPBOX
- };
-
- static final PdfName vpnames[] = {PdfName.HIDETOOLBAR, PdfName.HIDEMENUBAR,
- PdfName.HIDEWINDOWUI, PdfName.FITWINDOW, PdfName.CENTERWINDOW, PdfName.DISPLAYDOCTITLE};
- static final int vpints[] = {PdfWriter.HideToolbar, PdfWriter.HideMenubar,
- PdfWriter.HideWindowUI, PdfWriter.FitWindow, PdfWriter.CenterWindow, PdfWriter.DisplayDocTitle};
-
- static final byte endstream[] = PdfEncodings.convertToBytes("endstream", null);
- static final byte endobj[] = PdfEncodings.convertToBytes("endobj", null);
- protected PRTokeniser tokens;
- // Each xref pair is a position
- // type 0 -> -1, 0
- // type 1 -> offset, 0
- // type 2 -> index, obj num
- protected int xref[];
- protected HashMap objStmMark;
- protected IntHashtable objStmToOffset;
- protected boolean newXrefType;
- private ArrayList xrefObj;
- PdfDictionary rootPages;
- protected PdfDictionary trailer;
- //protected ArrayList pages;
- protected PdfDictionary catalog;
- protected PageRefs pageRefs;
- protected PRAcroForm acroForm = null;
- protected boolean acroFormParsed = false;
- protected ArrayList pageInh;
- protected boolean encrypted = false;
- protected boolean rebuilt = false;
- protected int freeXref;
- protected boolean tampered = false;
- protected int lastXref;
- protected int eofPos;
- protected char pdfVersion;
- protected PdfEncryption decrypt;
- protected byte password[] = null; //added by ujihara for decryption
- protected boolean passwordIsOwner= false; // added by ssteward
- protected ArrayList strings = new ArrayList();
- protected boolean sharedStreams = true;
- protected boolean consolidateNamedDestinations = false;
- protected int rValue;
- protected int pValue;
- private int objNum;
- private int objGen;
- private boolean visited[];
- private IntHashtable newHits;
- private int fileLength;
- private boolean hybridXref;
- private int lastXrefPartial = -1;
- private boolean partial;
-
- /**
- * Holds value of property appendable.
- */
- private boolean appendable;
-
- protected PdfReader() {
- }
-
- /** Reads and parses a PDF document.
- * @param filename the file name of the document
- * @throws IOException on error
- */
- public PdfReader(String filename) throws IOException {
- this(filename, null);
- }
-
- /** Reads and parses a PDF document.
- * @param filename the file name of the document
- * @param ownerPassword the password to read the document
- * @throws IOException on error
- */
- public PdfReader(String filename, byte ownerPassword[]) throws IOException {
- password = ownerPassword;
- tokens = new PRTokeniser(filename);
- readPdf();
- }
-
- /** Reads and parses a PDF document.
- * @param pdfIn the byte array with the document
- * @throws IOException on error
- */
- public PdfReader(byte pdfIn[]) throws IOException {
- this(pdfIn, null);
- }
-
- /** Reads and parses a PDF document.
- * @param pdfIn the byte array with the document
- * @param ownerPassword the password to read the document
- * @throws IOException on error
- */
- public PdfReader(byte pdfIn[], byte ownerPassword[]) throws IOException {
- password = ownerPassword;
- tokens = new PRTokeniser(pdfIn);
- readPdf();
- }
-
- /** Reads and parses a PDF document.
- * @param url the URL of the document
- * @throws IOException on error
- */
- public PdfReader(URL url) throws IOException {
- this(url, null);
- }
-
- /** Reads and parses a PDF document.
- * @param url the URL of the document
- * @param ownerPassword the password to read the document
- * @throws IOException on error
- */
- public PdfReader(URL url, byte ownerPassword[]) throws IOException {
- password = ownerPassword;
- tokens = new PRTokeniser(new RandomAccessFileOrArray(url));
- readPdf();
- }
-
- /**
- * Reads and parses a PDF document.
- * @param is the InputStream
containing the document. The stream is read to the
- * end but is not closed
- * @param ownerPassword the password to read the document
- * @throws IOException on error
- */
- public PdfReader(InputStream is, byte ownerPassword[]) throws IOException {
- password = ownerPassword;
- tokens = new PRTokeniser(new RandomAccessFileOrArray(is));
- readPdf();
- }
-
- /**
- * Reads and parses a PDF document.
- * @param is the InputStream
containing the document. The stream is read to the
- * end but is not closed
- * @throws IOException on error
- */
- public PdfReader(InputStream is) throws IOException {
- this(is, null);
- }
-
- /**
- * Reads and parses a pdf document. Contrary to the other constructors only the xref is read
- * into memory. The reader is said to be working in "partial" mode as only parts of the pdf
- * are read as needed. The pdf is left open but may be closed at any time with
- * PdfReader.close()
, reopen is automatic.
- * @param raf the document location
- * @param ownerPassword the password or null
for no password
- * @throws IOException on error
- */
- public PdfReader(RandomAccessFileOrArray raf, byte ownerPassword[]) throws IOException {
- password = ownerPassword;
- partial = true;
- tokens = new PRTokeniser(raf);
- readPdfPartial();
- }
-
- /** Creates an independent duplicate.
- * @param reader the PdfReader
to duplicate
- */
- public PdfReader(PdfReader reader) {
- this.appendable = reader.appendable;
- this.consolidateNamedDestinations = reader.consolidateNamedDestinations;
- this.encrypted = reader.encrypted;
- this.rebuilt = reader.rebuilt;
- this.sharedStreams = reader.sharedStreams;
- this.tampered = reader.tampered;
- this.password = reader.password;
- this.pdfVersion = reader.pdfVersion;
- this.eofPos = reader.eofPos;
- this.freeXref = reader.freeXref;
- this.lastXref = reader.lastXref;
- this.tokens = new PRTokeniser(reader.tokens.getSafeFile());
- if (reader.decrypt != null)
- this.decrypt = new PdfEncryption(reader.decrypt);
- this.pValue = reader.pValue;
- this.rValue = reader.rValue;
- this.xrefObj = new ArrayList(reader.xrefObj);
- for (int k = 0; k < reader.xrefObj.size(); ++k) {
- this.xrefObj.set(k, duplicatePdfObject((PdfObject)reader.xrefObj.get(k), this));
- }
- this.pageRefs = new PageRefs(reader.pageRefs, this);
- this.trailer = (PdfDictionary)duplicatePdfObject(reader.trailer, this);
- this.catalog = (PdfDictionary)getPdfObject(trailer.get(PdfName.ROOT));
- this.rootPages = (PdfDictionary)getPdfObject(catalog.get(PdfName.PAGES));
- this.fileLength = reader.fileLength;
- this.partial = reader.partial;
- this.hybridXref = reader.hybridXref;
- this.objStmToOffset = reader.objStmToOffset;
- this.xref = reader.xref;
- }
-
- /** Gets a new file instance of the original PDF
- * document.
- * @return a new file instance of the original PDF document
- */
- public RandomAccessFileOrArray getSafeFile() {
- return tokens.getSafeFile();
- }
-
- protected PdfReaderInstance getPdfReaderInstance(PdfWriter writer) {
- return new PdfReaderInstance(this, writer);
- }
-
- /** Gets the number of pages in the document.
- * @return the number of pages in the document
- */
- public int getNumberOfPages() {
- return pageRefs.size();
- }
-
- /** Returns the document's catalog. This dictionary is not a copy,
- * any changes will be reflected in the catalog.
- * @return the document's catalog
- */
- public PdfDictionary getCatalog() {
- return catalog;
- }
-
- /** Returns the document's acroform, if it has one.
- * @return the document's acroform
- */
- public PRAcroForm getAcroForm() {
- if (!acroFormParsed) {
- acroFormParsed = true;
- PdfObject form = catalog.get(PdfName.ACROFORM);
- if (form != null) {
- try {
- acroForm = new PRAcroForm(this);
- acroForm.readAcroForm((PdfDictionary)getPdfObject(form));
- }
- catch (Exception e) {
- acroForm = null;
- }
- }
- }
- return acroForm;
- }
- /**
- * Gets the page rotation. This value can be 0, 90, 180 or 270.
- * @param index the page number. The first page is 1
- * @return the page rotation
- */
- public int getPageRotation(int index) {
- return getPageRotation(pageRefs.getPageNRelease(index));
- }
-
- int getPageRotation(PdfDictionary page) {
- PdfNumber rotate = (PdfNumber)getPdfObject(page.get(PdfName.ROTATE));
- if (rotate == null)
- return 0;
- else {
- int n = rotate.intValue();
- n %= 360;
- return n < 0 ? n + 360 : n;
- }
- }
- /** Gets the page size, taking rotation into account. This
- * is a Rectangle
with the value of the /MediaBox and the /Rotate key.
- * @param index the page number. The first page is 1
- * @return a Rectangle
- */
- public Rectangle getPageSizeWithRotation(int index) {
- return getPageSizeWithRotation(pageRefs.getPageNRelease(index));
- }
-
- /**
- * Gets the rotated page from a page dictionary.
- * @param page the page dictionary
- * @return the rotated page
- */
- public Rectangle getPageSizeWithRotation(PdfDictionary page) {
- Rectangle rect = getPageSize(page);
- int rotation = getPageRotation(page);
- while (rotation > 0) {
- rect = rect.rotate();
- rotation -= 90;
- }
- return rect;
- }
-
- /** Gets the page size without taking rotation into account. This
- * is the value of the /MediaBox key.
- * @param index the page number. The first page is 1
- * @return the page size
- */
- public Rectangle getPageSize(int index) {
- return getPageSize(pageRefs.getPageNRelease(index));
- }
-
- /**
- * Gets the page from a page dictionary
- * @param page the page dictionary
- * @return the page
- */
- public Rectangle getPageSize(PdfDictionary page) {
- PdfArray mediaBox = (PdfArray)getPdfObject(page.get(PdfName.MEDIABOX));
- return getNormalizedRectangle(mediaBox);
- }
-
- /** Gets the crop box without taking rotation into account. This
- * is the value of the /CropBox key. The crop box is the part
- * of the document to be displayed or printed. It usually is the same
- * as the media box but may be smaller. If the page doesn't have a crop
- * box the page size will be returned.
- * @param index the page number. The first page is 1
- * @return the crop box
- */
- public Rectangle getCropBox(int index) {
- PdfDictionary page = pageRefs.getPageNRelease(index);
- PdfArray cropBox = (PdfArray)getPdfObjectRelease(page.get(PdfName.CROPBOX));
- if (cropBox == null)
- return getPageSize(page);
- return getNormalizedRectangle(cropBox);
- }
-
- /** Gets the box size. Allowed names are: "crop", "trim", "art", "bleed" and "media".
- * @param index the page number. The first page is 1
- * @param boxName the box name
- * @return the box rectangle or null
- */
- public Rectangle getBoxSize(int index, String boxName) {
- PdfDictionary page = pageRefs.getPageNRelease(index);
- PdfArray box = null;
- if (boxName.equals("trim"))
- box = (PdfArray)getPdfObjectRelease(page.get(PdfName.TRIMBOX));
- else if (boxName.equals("art"))
- box = (PdfArray)getPdfObjectRelease(page.get(PdfName.ARTBOX));
- else if (boxName.equals("bleed"))
- box = (PdfArray)getPdfObjectRelease(page.get(PdfName.BLEEDBOX));
- else if (boxName.equals("crop"))
- box = (PdfArray)getPdfObjectRelease(page.get(PdfName.CROPBOX));
- else if (boxName.equals("media"))
- box = (PdfArray)getPdfObjectRelease(page.get(PdfName.MEDIABOX));
- if (box == null)
- return null;
- return getNormalizedRectangle(box);
- }
-
- /** Returns the content of the document information dictionary as a HashMap
- * of String
.
- * @return content of the document information dictionary
- */
- public HashMap getInfo() {
- HashMap map = new HashMap();
- PdfDictionary info = (PdfDictionary)getPdfObject(trailer.get(PdfName.INFO));
- if (info == null)
- return map;
- for (Iterator it = info.getKeys().iterator(); it.hasNext();) {
- PdfName key = (PdfName)it.next();
- PdfObject obj = getPdfObject(info.get(key));
- if (obj == null)
- continue;
- String value = obj.toString();
- switch (obj.type()) {
- case PdfObject.STRING: {
- value = ((PdfString)obj).toUnicodeString();
- break;
- }
- case PdfObject.NAME: {
- value = PdfName.decodeName(value);
- break;
- }
- }
- map.put(PdfName.decodeName(key.toString()), value);
- }
- return map;
- }
-
- /** Normalizes a Rectangle
so that llx and lly are smaller than urx and ury.
- * @param box the original rectangle
- * @return a normalized Rectangle
- */
- public static Rectangle getNormalizedRectangle(PdfArray box) {
- ArrayList rect = box.getArrayList();
- float llx = ((PdfNumber)rect.get(0)).floatValue();
- float lly = ((PdfNumber)rect.get(1)).floatValue();
- float urx = ((PdfNumber)rect.get(2)).floatValue();
- float ury = ((PdfNumber)rect.get(3)).floatValue();
- return new Rectangle(Math.min(llx, urx), Math.min(lly, ury),
- Math.max(llx, urx), Math.max(lly, ury));
- }
-
- protected void readPdf() throws IOException {
- try {
- fileLength = tokens.getFile().length();
- pdfVersion = tokens.checkPdfHeader();
- try {
- readXref();
- }
- catch (Exception e) {
- try {
- rebuilt = true;
- rebuildXref();
- lastXref = -1;
- }
- catch (Exception ne) {
- throw new IOException("Rebuild failed: " + ne.getMessage() + "; Original message: " + e.getMessage());
- }
- }
- try {
- readDocObj();
- }
- catch (IOException ne) {
- if (rebuilt)
- throw ne;
- rebuilt = true;
- encrypted = false;
- rebuildXref();
- lastXref = -1;
- readDocObj();
- }
-
- strings.clear();
- readPages();
- eliminateSharedStreams();
- removeUnusedObjects();
- }
- finally {
- try {
- tokens.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- }
-
- protected void readPdfPartial() throws IOException {
- try {
- fileLength = tokens.getFile().length();
- pdfVersion = tokens.checkPdfHeader();
- try {
- readXref();
- }
- catch (Exception e) {
- try {
- rebuilt = true;
- rebuildXref();
- lastXref = -1;
- }
- catch (Exception ne) {
- throw new IOException("Rebuild failed: " + ne.getMessage() + "; Original message: " + e.getMessage());
- }
- }
- readDocObjPartial();
- readPages();
- }
- catch (IOException e) {
- try{tokens.close();}catch(Exception ee){}
- throw e;
- }
- }
-
- private boolean equalsArray(byte ar1[], byte ar2[], int size) {
- for (int k = 0; k < size; ++k) {
- if (ar1[k] != ar2[k])
- return false;
- }
- return true;
- }
-
- /**
- * @throws IOException
- */
- private void readDecryptedDocObj() throws IOException {
- if (encrypted)
- return;
- PdfObject encDic = trailer.get(PdfName.ENCRYPT);
- if (encDic == null || encDic.toString().equals("null"))
- return;
- encrypted = true;
- PdfDictionary enc = (PdfDictionary)getPdfObject(encDic);
-
- String s;
- PdfObject o;
-
- // ssteward: updated to suit modified PdfString
- PdfArray documentIDs = (PdfArray)getPdfObject(trailer.get(PdfName.ID));
- byte documentID[] = null;
- if (documentIDs != null) {
- o = (PdfObject)documentIDs.getArrayList().get(0);
- documentID= o.getBytes(); // ssteward
- }
- byte uValue[]= enc.get(PdfName.U).getBytes(); // ssteward
- byte oValue[]= enc.get(PdfName.O).getBytes(); // ssteward
-
- o = enc.get(PdfName.R);
- if (!o.isNumber()) throw new IOException("Illegal R value.");
- rValue = ((PdfNumber)o).intValue();
- if (rValue != 2 && rValue != 3) throw new IOException("Unknown encryption type (" + rValue + ")");
-
- o = enc.get(PdfName.P);
- if (!o.isNumber()) throw new IOException("Illegal P value.");
- pValue = ((PdfNumber)o).intValue();
-
- decrypt = new PdfEncryption();
-
- // switched by ssteward
- //check by owner password, first, to ensure greatest authorization
- decrypt.setupByOwnerPassword(documentID, password, uValue, oValue, pValue, (rValue == 3));
- if (equalsArray(uValue, decrypt.userKey, ((rValue == 3) ? 16 : 32))) {
- passwordIsOwner= true;
- }
- else {
- //check by user password
- decrypt.setupByUserPassword(documentID, password, oValue, pValue, (rValue == 3));
- if (!equalsArray(uValue, decrypt.userKey, ((rValue == 3) ? 16 : 32))) {
- throw new IOException("Bad password");
- }
- }
- for (int k = 0; k < strings.size(); ++k) {
- PdfString str = (PdfString)strings.get(k);
- str.decrypt(this);
- }
- if (encDic.isIndirect())
- xrefObj.set(((PRIndirectReference)encDic).getNumber(), null);
- }
-
- /**
- * @param obj
- * @return a PdfObject
- */
- public static PdfObject getPdfObjectRelease(PdfObject obj) {
- PdfObject obj2 = getPdfObject(obj);
- releaseLastXrefPartial(obj);
- return obj2;
- }
-
-
- /**
- * Reads a PdfObject
resolving an indirect reference
- * if needed.
- * @param obj the PdfObject
to read
- * @return the resolved PdfObject
- */
- public static PdfObject getPdfObject(PdfObject obj) {
- if (obj == null)
- return null;
- if (!obj.isIndirect())
- return obj;
- try {
- PRIndirectReference ref = (PRIndirectReference)obj;
- int idx = ref.getNumber();
- boolean appendable = ref.getReader().appendable;
- obj = ref.getReader().getPdfObject(idx);
- if (obj == null) {
- if (appendable) {
- obj = new PdfNull();
- obj.setIndRef(ref);
- return obj;
- }
- else
- return PdfNull.PDFNULL;
- }
- else {
- if (appendable) {
- switch (obj.type()) {
- case PdfObject.m_NULL:
- obj = new PdfNull();
- break;
- case PdfObject.BOOLEAN:
- obj = new PdfBoolean(((PdfBoolean)obj).booleanValue());
- break;
- case PdfObject.NAME:
- obj = new PdfName(obj.getBytes());
- break;
- }
- obj.setIndRef(ref);
- }
- return obj;
- }
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Reads a PdfObject
resolving an indirect reference
- * if needed. If the reader was opened in partial mode the object will be released
- * to save memory.
- * @param obj the PdfObject
to read
- * @param parent
- * @return a PdfObject
- */
- public static PdfObject getPdfObjectRelease(PdfObject obj, PdfObject parent) {
- PdfObject obj2 = getPdfObject(obj, parent);
- releaseLastXrefPartial(obj);
- return obj2;
- }
-
- /**
- * @param obj
- * @param parent
- * @return a PdfObject
- */
- public static PdfObject getPdfObject(PdfObject obj, PdfObject parent) {
- if (obj == null)
- return null;
- if (!obj.isIndirect()) {
- PRIndirectReference ref = null;
- if (parent != null && (ref = parent.getIndRef()) != null && ref.getReader().isAppendable()) {
- switch (obj.type()) {
- case PdfObject.m_NULL: // ssteward
- obj = new PdfNull();
- break;
- case PdfObject.BOOLEAN:
- obj = new PdfBoolean(((PdfBoolean)obj).booleanValue());
- break;
- case PdfObject.NAME:
- obj = new PdfName(obj.getBytes());
- break;
- }
- obj.setIndRef(ref);
- }
- return obj;
- }
- return getPdfObject(obj);
- }
-
- /**
- * @param idx
- * @return a PdfObject
- */
- public PdfObject getPdfObjectRelease(int idx) {
- PdfObject obj = getPdfObject(idx);
- releaseLastXrefPartial();
- return obj;
- }
-
- /**
- * @param idx
- * @return aPdfObject
- */
- public PdfObject getPdfObject(int idx) {
- try {
- lastXrefPartial = -1;
- if (idx < 0 || idx >= xrefObj.size())
- return null;
- PdfObject obj = (PdfObject)xrefObj.get(idx);
- if (!partial || obj != null)
- return obj;
- if (idx * 2 >= xref.length)
- return null;
- obj = readSingleObject(idx);
- lastXrefPartial = -1;
- if (obj != null)
- lastXrefPartial = idx;
- return obj;
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- *
- */
- public void resetLastXrefPartial() {
- lastXrefPartial = -1;
- }
-
- /**
- *
- */
- public void releaseLastXrefPartial() {
- if (partial && lastXrefPartial != -1) {
- xrefObj.set(lastXrefPartial, null);
- lastXrefPartial = -1;
- }
- }
-
- /**
- * @param obj
- */
- public static void releaseLastXrefPartial(PdfObject obj) {
- if (obj == null)
- return;
- if (!obj.isIndirect())
- return;
- PRIndirectReference ref = (PRIndirectReference)obj;
- PdfReader reader = ref.getReader();
- if (reader.partial && reader.lastXrefPartial != -1 && reader.lastXrefPartial == ref.getNumber()) {
- reader.xrefObj.set(reader.lastXrefPartial, null);
- }
- reader.lastXrefPartial = -1;
- }
-
- private void setXrefPartialObject(int idx, PdfObject obj) {
- if (!partial || idx < 0)
- return;
- xrefObj.set(idx, obj);
- }
-
- /**
- * @param obj
- * @return an indirect reference
- */
- public PRIndirectReference addPdfObject(PdfObject obj) {
- xrefObj.add(obj);
- return new PRIndirectReference(this, xrefObj.size() - 1);
- }
-
- protected void readPages() throws IOException {
- pageInh = new ArrayList();
- catalog = (PdfDictionary)getPdfObject(trailer.get(PdfName.ROOT));
- rootPages = (PdfDictionary)getPdfObject(catalog.get(PdfName.PAGES));
- pageRefs = new PageRefs(this);
- }
-
- protected PRIndirectReference getSinglePage(int n) throws IOException {
- /*
- PdfDictionary acc = new PdfDictionary();
- PdfDictionary top = rootPages;
- int base = 0;
- while (true) {
- break;
- }
- */
- return null;
- }
-
- protected void PRSimpleRecursive(PdfObject obj) throws IOException {
- switch (obj.type()) {
- case PdfObject.DICTIONARY:
- case PdfObject.STREAM:
- PdfDictionary dic = (PdfDictionary)obj;
- for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
- PdfName key = (PdfName)it.next();
- PRSimpleRecursive(dic.get(key));
- }
- break;
- case PdfObject.ARRAY:
- ArrayList list = ((PdfArray)obj).getArrayList();
- for (int k = 0; k < list.size(); ++k) {
- PRSimpleRecursive((PdfObject)list.get(k));
- }
- break;
- case PdfObject.INDIRECT:
- PRIndirectReference ref = (PRIndirectReference)obj;
- int num = ref.getNumber();
- if (!visited[num]) {
- visited[num] = true;
- newHits.put(num, 1);
- }
- break;
- }
- }
-
- protected void readDocObjPartial() throws IOException {
- xrefObj = new ArrayList(xref.length / 2);
- xrefObj.addAll(Collections.nCopies(xref.length / 2, null));
- readDecryptedDocObj();
- if (objStmToOffset != null) {
- int keys[] = objStmToOffset.getKeys();
- for (int k = 0; k < keys.length; ++k) {
- int n = keys[k];
- objStmToOffset.put(n, xref[n * 2]);
- xref[n * 2] = -1;
- }
- }
- }
-
- protected PdfObject readSingleObject(int k) throws IOException {
- strings.clear();
- int k2 = k * 2;
- int pos = xref[k2];
- if (pos < 0)
- return null;
- if (xref[k2 + 1] > 0)
- pos = objStmToOffset.get(xref[k2 + 1]);
- tokens.seek(pos);
- tokens.nextValidToken();
- if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
- tokens.throwError("Invalid object number.");
- objNum = tokens.intValue();
- tokens.nextValidToken();
- if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
- tokens.throwError("Invalid generation number.");
- objGen = tokens.intValue();
- tokens.nextValidToken();
- if (!tokens.getStringValue().equals("obj"))
- tokens.throwError("Token 'obj' expected.");
- PdfObject obj;
- try {
- obj = readPRObject();
- for (int j = 0; j < strings.size(); ++j) {
- PdfString str = (PdfString)strings.get(j);
- str.decrypt(this);
- }
- if (obj.isStream()) {
- checkPRStreamLength((PRStream)obj);
- }
- }
- catch (Exception e) {
- obj = null;
- }
- if (xref[k2 + 1] > 0) {
- obj = readOneObjStm((PRStream)obj, xref[k2]);
- }
- xrefObj.set(k, obj);
- return obj;
- }
-
- protected PdfObject readOneObjStm(PRStream stream, int idx) throws IOException {
- int first = ((PdfNumber)getPdfObject(stream.get(PdfName.FIRST))).intValue();
- // int n = ((PdfNumber)getPdfObject(stream.get(PdfName.N))).intValue();
- byte b[] = getStreamBytes(stream, tokens.getFile());
- PRTokeniser saveTokens = tokens;
- tokens = new PRTokeniser(b);
- try {
- int address = 0;
- // int objNumber = 0;
- boolean ok = true;
- ++idx;
- for (int k = 0; k < idx; ++k) {
- ok = tokens.nextToken();
- if (!ok)
- break;
- if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) {
- ok = false;
- break;
- }
- // objNumber = tokens.intValue();
- ok = tokens.nextToken();
- if (!ok)
- break;
- if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) {
- ok = false;
- break;
- }
- address = tokens.intValue() + first;
- }
- if (!ok)
- throw new IOException("Error reading ObjStm");
- tokens.seek(address);
- return readPRObject();
- }
- finally {
- tokens = saveTokens;
- }
- }
-
- /**
- * @return the percentage of the cross reference table that has been read
- */
- public double dumpPerc() {
- int total = 0;
- for (int k = 0; k < xrefObj.size(); ++k) {
- if (xrefObj.get(k) != null)
- ++total;
- }
- return (total * 100.0 / xrefObj.size());
- }
-
- protected void readDocObj() throws IOException {
- ArrayList streams = new ArrayList();
- xrefObj = new ArrayList(xref.length / 2);
- xrefObj.addAll(Collections.nCopies(xref.length / 2, null));
- for (int k = 2; k < xref.length; k += 2) {
- int pos = xref[k];
- if (pos <= 0 || xref[k + 1] > 0)
- continue;
- tokens.seek(pos);
- tokens.nextValidToken();
- if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
- tokens.throwError("Invalid object number.");
- objNum = tokens.intValue();
- tokens.nextValidToken();
- if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
- tokens.throwError("Invalid generation number.");
- objGen = tokens.intValue();
- tokens.nextValidToken();
- if (!tokens.getStringValue().equals("obj"))
- tokens.throwError("Token 'obj' expected.");
- PdfObject obj;
- try {
- obj = readPRObject();
- if (obj.isStream()) {
- streams.add(obj);
- }
- }
- catch (Exception e) {
- obj = null;
- }
- xrefObj.set(k / 2, obj);
- }
- // int fileLength = tokens.length();
- // byte tline[] = new byte[16];
- for (int k = 0; k < streams.size(); ++k) {
- checkPRStreamLength((PRStream)streams.get(k));
- }
- readDecryptedDocObj();
- if (objStmMark != null) {
- for (Iterator i = objStmMark.entrySet().iterator(); i.hasNext();) {
- Map.Entry entry = (Map.Entry)i.next();
- int n = ((Integer)entry.getKey()).intValue();
- IntHashtable h = (IntHashtable)entry.getValue();
- readObjStm((PRStream)xrefObj.get(n), h);
- xrefObj.set(n, null);
- }
- objStmMark = null;
- }
- xref = null;
- }
-
- private void checkPRStreamLength(PRStream stream) throws IOException {
- int fileLength = tokens.length();
- int start = stream.getOffset();
-
- // debug -- is this working okay?
- //System.out.println( " stream start: "+ start );
- //System.out.flush();
-
- boolean calc = false;
- int streamLength = 0;
- PdfObject obj = getPdfObjectRelease(stream.get(PdfName.LENGTH));
- if (obj != null && obj.type() == PdfObject.NUMBER) {
- streamLength = ((PdfNumber)obj).intValue();
- if (streamLength + start > fileLength - 20)
- calc = true;
- else {
- tokens.seek(start + streamLength);
- String line = tokens.readString(20);
- if (!line.startsWith("\nendstream") &&
- !line.startsWith("\r\nendstream") &&
- !line.startsWith("\rendstream") &&
- !line.startsWith("endstream"))
- calc = true;
- }
- }
- else
- calc = true;
-
- if (calc) {
- byte tline[] = new byte[16];
- tokens.seek(start);
- while (true) {
- int pos = tokens.getFilePointer();
- if (!tokens.readLineSegment(tline))
- break;
- if (equalsn(tline, endstream)) {
- streamLength = pos - start;
- break;
- }
- if (equalsn(tline, endobj)) {
- tokens.seek(pos - 16);
- String s = tokens.readString(16);
- int index = s.indexOf("endstream");
- if (index >= 0)
- pos = pos - 16 + index;
- streamLength = pos - start;
- break;
- }
- }
- }
- stream.setLength(streamLength);
- }
-
- protected void readObjStm(PRStream stream, IntHashtable map) throws IOException {
- int first = ((PdfNumber)getPdfObject(stream.get(PdfName.FIRST))).intValue();
- int n = ((PdfNumber)getPdfObject(stream.get(PdfName.N))).intValue();
- byte b[] = getStreamBytes(stream, tokens.getFile());
- PRTokeniser saveTokens = tokens;
- tokens = new PRTokeniser(b);
- try {
- int address[] = new int[n];
- int objNumber[] = new int[n];
- boolean ok = true;
- for (int k = 0; k < n; ++k) {
- ok = tokens.nextToken();
- if (!ok)
- break;
- if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) {
- ok = false;
- break;
- }
- objNumber[k] = tokens.intValue();
- ok = tokens.nextToken();
- if (!ok)
- break;
- if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) {
- ok = false;
- break;
- }
- address[k] = tokens.intValue() + first;
- }
- if (!ok)
- throw new IOException("Error reading ObjStm");
- for (int k = 0; k < n; ++k) {
- if (map.containsKey(k)) {
- tokens.seek(address[k]);
- PdfObject obj = readPRObject();
- xrefObj.set(objNumber[k], obj);
- }
- }
- }
- finally {
- tokens = saveTokens;
- }
- }
-
- static PdfObject killIndirect(PdfObject obj) {
- if (obj == null || obj.isNull())
- return null;
- PdfObject ret = getPdfObjectRelease(obj);
- if (obj.isIndirect()) {
- PRIndirectReference ref = (PRIndirectReference)obj;
- PdfReader reader = ref.getReader();
- int n = ref.getNumber();
- reader.xrefObj.set(n, null);
- if (reader.partial)
- reader.xref[n * 2] = -1;
- }
- return ret;
- }
-
- private void ensureXrefSize(int size) {
- if (size == 0)
- return;
- if (xref == null)
- xref = new int[size];
- else {
- if (xref.length < size) {
- int xref2[] = new int[size];
- System.arraycopy(xref, 0, xref2, 0, xref.length);
- xref = xref2;
- }
- }
- }
-
- protected void readXref() throws IOException {
- hybridXref = false;
- newXrefType = false;
- tokens.seek(tokens.getStartxref());
- tokens.nextToken();
- if (!tokens.getStringValue().equals("startxref"))
- throw new IOException("startxref not found.");
- tokens.nextToken();
- if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
- throw new IOException("startxref is not followed by a number.");
- int startxref = tokens.intValue();
- lastXref = startxref;
- eofPos = tokens.getFilePointer();
- try {
- if (readXRefStream(startxref)) {
- newXrefType = true;
- return;
- }
- }
- catch (Exception e) {}
- xref = null;
- tokens.seek(startxref);
- trailer = readXrefSection();
- PdfDictionary trailer2 = trailer;
- while (true) {
- PdfNumber prev = (PdfNumber)trailer2.get(PdfName.PREV);
- if (prev == null)
- break;
- tokens.seek(prev.intValue());
- trailer2 = readXrefSection();
- }
- }
-
- protected PdfDictionary readXrefSection() throws IOException {
- tokens.nextValidToken();
- if (!tokens.getStringValue().equals("xref"))
- tokens.throwError("xref subsection not found");
- int start = 0;
- int end = 0;
- int pos = 0;
- int gen = 0;
- while (true) {
- tokens.nextValidToken();
- if (tokens.getStringValue().equals("trailer"))
- break;
- if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
- tokens.throwError("Object number of the first object in this xref subsection not found");
- start = tokens.intValue();
- tokens.nextValidToken();
- if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
- tokens.throwError("Number of entries in this xref subsection not found");
- end = tokens.intValue() + start;
- if (start == 1) { // fix incorrect start number
- int back = tokens.getFilePointer();
- tokens.nextValidToken();
- pos = tokens.intValue();
- tokens.nextValidToken();
- gen = tokens.intValue();
- if (pos == 0 && gen == 65535) {
- --start;
- --end;
- }
- tokens.seek(back);
- }
- ensureXrefSize(end * 2);
- for (int k = start; k < end; ++k) {
- tokens.nextValidToken();
- pos = tokens.intValue();
- tokens.nextValidToken();
- gen = tokens.intValue();
- tokens.nextValidToken();
- int p = k * 2;
- if (tokens.getStringValue().equals("n")) {
- if (xref[p] == 0 && xref[p + 1] == 0) {
-// if (pos == 0)
-// tokens.throwError("File position 0 cross-reference entry in this xref subsection");
- xref[p] = pos;
- }
- }
- else if (tokens.getStringValue().equals("f")) {
- if (xref[p] == 0 && xref[p + 1] == 0)
- xref[p] = -1;
- }
- else
- tokens.throwError("Invalid cross-reference entry in this xref subsection");
- }
- }
- PdfDictionary trailer = (PdfDictionary)readPRObject();
- PdfNumber xrefSize = (PdfNumber)trailer.get(PdfName.SIZE);
- ensureXrefSize(xrefSize.intValue() * 2);
- PdfObject xrs = trailer.get(PdfName.XREFSTM);
- if (xrs != null && xrs.isNumber()) {
- int loc = ((PdfNumber)xrs).intValue();
- try {
- readXRefStream(loc);
- newXrefType = true;
- hybridXref = true;
- }
- catch (IOException e) {
- xref = null;
- throw e;
- }
- }
- return trailer;
- }
-
- protected boolean readXRefStream(int ptr) throws IOException {
- tokens.seek(ptr);
- int thisStream = 0;
- if (!tokens.nextToken())
- return false;
- if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
- return false;
- thisStream = tokens.intValue();
- if (!tokens.nextToken() || tokens.getTokenType() != PRTokeniser.TK_NUMBER)
- return false;
- if (!tokens.nextToken() || !tokens.getStringValue().equals("obj"))
- return false;
- PdfObject object = readPRObject();
- PRStream stm = null;
- if (object.isStream()) {
- stm = (PRStream)object;
- if (!PdfName.XREF.equals(stm.get(PdfName.TYPE)))
- return false;
- }
- if (trailer == null) {
- trailer = new PdfDictionary();
- trailer.putAll(stm);
- }
- stm.setLength(((PdfNumber)stm.get(PdfName.LENGTH)).intValue());
- int size = ((PdfNumber)stm.get(PdfName.SIZE)).intValue();
- PdfArray index;
- PdfObject obj = stm.get(PdfName.INDEX);
- if (obj == null) {
- index = new PdfArray();
- index.add(new int[]{0, size});
- }
- else
- index = (PdfArray)obj;
- PdfArray w = (PdfArray)stm.get(PdfName.W);
- int prev = -1;
- obj = stm.get(PdfName.PREV);
- if (obj != null)
- prev = ((PdfNumber)obj).intValue();
- // Each xref pair is a position
- // type 0 -> -1, 0
- // type 1 -> offset, 0
- // type 2 -> index, obj num
- ensureXrefSize(size * 2);
- if (objStmMark == null && !partial)
- objStmMark = new HashMap();
- if (objStmToOffset == null && partial)
- objStmToOffset = new IntHashtable();
- byte b[] = getStreamBytes(stm, tokens.getFile());
- int bptr = 0;
- ArrayList wa = w.getArrayList();
- int wc[] = new int[3];
- for (int k = 0; k < 3; ++k)
- wc[k] = ((PdfNumber)wa.get(k)).intValue();
- ArrayList sections = index.getArrayList();
- for (int idx = 0; idx < sections.size(); idx += 2) {
- int start = ((PdfNumber)sections.get(idx)).intValue();
- int length = ((PdfNumber)sections.get(idx + 1)).intValue();
- ensureXrefSize((start + length) * 2);
- while (length-- > 0) {
- // int total = 0;
- int type = 1;
- if (wc[0] > 0) {
- type = 0;
- for (int k = 0; k < wc[0]; ++k)
- type = (type << 8) + (b[bptr++] & 0xff);
- }
- int field2 = 0;
- for (int k = 0; k < wc[1]; ++k)
- field2 = (field2 << 8) + (b[bptr++] & 0xff);
- int field3 = 0;
- for (int k = 0; k < wc[2]; ++k)
- field3 = (field3 << 8) + (b[bptr++] & 0xff);
- int base = start * 2;
- if (xref[base] == 0 && xref[base + 1] == 0) {
- switch (type) {
- case 0:
- xref[base] = -1;
- break;
- case 1:
- xref[base] = field2;
- break;
- case 2:
- xref[base] = field3;
- xref[base + 1] = field2;
- if (partial) {
- objStmToOffset.put(field2, 0);
- }
- else {
- Integer on = new Integer(field2);
- IntHashtable seq = (IntHashtable)objStmMark.get(on);
- if (seq == null) {
- seq = new IntHashtable();
- seq.put(field3, 1);
- objStmMark.put(on, seq);
- }
- else
- seq.put(field3, 1);
- }
- break;
- }
- }
- ++start;
- }
- }
- thisStream *= 2;
- if (thisStream < xref.length)
- xref[thisStream] = -1;
-
- if (prev == -1)
- return true;
- return readXRefStream(prev);
- }
-
- protected void rebuildXref() throws IOException {
- hybridXref = false;
- newXrefType = false;
- tokens.seek(0);
- int xr[][] = new int[1024][];
- int top = 0;
- trailer = null;
- byte line[] = new byte[64];
- for (;;) {
- int pos = tokens.getFilePointer();
- if (!tokens.readLineSegment(line))
- break;
- if (line[0] == 't') {
- if (!PdfEncodings.convertToString(line, null).startsWith("trailer"))
- continue;
- tokens.seek(pos);
- tokens.nextToken();
- pos = tokens.getFilePointer();
- try {
- PdfDictionary dic = (PdfDictionary)readPRObject();
- if (dic.get(PdfName.ROOT) != null)
- trailer = dic;
- else
- tokens.seek(pos);
- }
- catch (Exception e) {
- tokens.seek(pos);
- }
- }
- else if (line[0] >= '0' && line[0] <= '9') {
- int obj[] = PRTokeniser.checkObjectStart(line);
- if (obj == null)
- continue;
- int num = obj[0];
- int gen = obj[1];
- if (num >= xr.length) {
- int newLength = num * 2;
- int xr2[][] = new int[newLength][];
- System.arraycopy(xr, 0, xr2, 0, top);
- xr = xr2;
- }
- if (num >= top)
- top = num + 1;
- if (xr[num] == null || gen >= xr[num][1]) {
- obj[0] = pos;
- xr[num] = obj;
- }
- }
- }
- if (trailer == null)
- throw new IOException("trailer not found.");
- xref = new int[top * 2];
- for (int k = 0; k < top; ++k) {
- int obj[] = xr[k];
- if (obj != null)
- xref[k * 2] = obj[0];
- }
- }
-
- protected PdfDictionary readDictionary() throws IOException {
- PdfDictionary dic = new PdfDictionary();
- while (true) {
- tokens.nextValidToken();
- if (tokens.getTokenType() == PRTokeniser.TK_END_DIC)
- break;
- if (tokens.getTokenType() != PRTokeniser.TK_NAME)
- tokens.throwError("Dictionary key is not a name.");
- PdfName name = new PdfName(tokens.getStringValue());
- PdfObject obj = readPRObject();
- int type = obj.type();
- if (-type == PRTokeniser.TK_END_DIC)
- tokens.throwError("Unexpected '>>'");
- if (-type == PRTokeniser.TK_END_ARRAY)
- tokens.throwError("Unexpected ']'");
- dic.put(name, obj);
- }
- return dic;
- }
-
- protected PdfArray readArray() throws IOException {
- PdfArray array = new PdfArray();
- while (true) {
- PdfObject obj = readPRObject();
- int type = obj.type();
- if (-type == PRTokeniser.TK_END_ARRAY)
- break;
- if (-type == PRTokeniser.TK_END_DIC)
- tokens.throwError("Unexpected '>>'");
- array.add(obj);
- }
- return array;
- }
-
- protected PdfObject readPRObject() throws IOException {
- tokens.nextValidToken();
- int type = tokens.getTokenType();
- switch (type) {
- case PRTokeniser.TK_START_DIC: {
- PdfDictionary dic = readDictionary();
- int pos = tokens.getFilePointer();
- // be careful in the trailer. May not be a "next" token.
- if (tokens.nextToken() && tokens.getStringValue().equals("stream")) {
- // ssteward - 6/21/10
- // stream should be followed by a LF or a CRLF, but not just a CR, per the PDF spec.
- // however, I have encountered a generated PDF (Microsoft Reporting Services 10.0.0.0)
- // that added a space after "stream" but before the CR; so gobble up unexpected chars
- // until we find a LF
- // ssteward - 10/30/12
- // I have been given a PDF with a stream with a CR but no LF -- I should have foreseen this case;
- int ch = tokens.read();
- /* original code
- if (ch != '\n')
- ch = tokens.read();
- if (ch != '\n')
- tokens.backOnePosition(ch);
- */
- // ssteward -- 6/21/10 fix
- //while (ch != '\n')
- // ch = tokens.read();
- // ssteward -- 10/31/12 fix
- // eat whitespace until we hit a LF, which is supposed to mark the beginning of the stream;
- // this logic should work even if there is no w/s padding around the stream data
- while( PRTokeniser.isWhitespace( ch ) ) {
- if( ch== '\n' )
- break;
- ch= tokens.read();
- }
- // PRStream(), below, seems to assume that our position is one before the data; testing for
- // whitespace catches case where there is a CR no LF used to delim stream data
- if( !PRTokeniser.isWhitespace( ch ) )
- tokens.backOnePosition( ch );
-
- PRStream stream = new PRStream(this, tokens.getFilePointer());
- stream.putAll(dic);
- stream.setObjNum(objNum, objGen);
- return stream;
- }
- else {
- tokens.seek(pos);
- return dic;
- }
- }
- case PRTokeniser.TK_START_ARRAY:
- return readArray();
- case PRTokeniser.TK_NUMBER:
- return new PdfNumber(tokens.getStringValue());
- case PRTokeniser.TK_STRING:
- // ssteward: change from String to byte array input to PdfString()
- //PdfString str = new PdfString(tokens.getStringValue(), null).setHexWriting(tokens.isHexString());
- PdfString str = new PdfString( PdfEncodings.convertToBytes( tokens.getStringValue(), null) ).setHexWriting(tokens.isHexString());
- str.setObjNum(objNum, objGen);
- if (strings != null)
- strings.add(str);
- return str;
- case PRTokeniser.TK_NAME:
- return new PdfName(tokens.getStringValue());
- case PRTokeniser.TK_REF:
- int num = tokens.getReference();
- PRIndirectReference ref = new PRIndirectReference(this, num, tokens.getGeneration());
- if (visited != null && !visited[num]) {
- visited[num] = true;
- newHits.put(num, 1);
- }
- return ref;
- default:
- return new PdfLiteral(-type, tokens.getStringValue());
- }
- }
-
- /** Decodes a stream that has the FlateDecode filter.
- * @param in the input data
- * @return the decoded data
- */
- public static byte[] FlateDecode(byte in[]) {
- byte b[] = FlateDecode(in, true);
- if (b == null)
- return FlateDecode(in, false);
- return b;
- }
-
- /**
- * @param in
- * @param dicPar
- * @return a byte array
- */
- public static byte[] decodePredictor(byte in[], PdfObject dicPar) {
- if (dicPar == null || !dicPar.isDictionary())
- return in;
- PdfDictionary dic = (PdfDictionary)dicPar;
- PdfObject obj = getPdfObject(dic.get(PdfName.PREDICTOR));
- if (obj == null || !obj.isNumber())
- return in;
- int predictor = ((PdfNumber)obj).intValue();
- if (predictor < 10)
- return in;
- int width = 1;
- obj = getPdfObject(dic.get(PdfName.COLUMNS));
- if (obj != null && obj.isNumber())
- width = ((PdfNumber)obj).intValue();
- int colors = 1;
- obj = getPdfObject(dic.get(PdfName.COLORS));
- if (obj != null && obj.isNumber())
- colors = ((PdfNumber)obj).intValue();
- int bpc = 8;
- obj = getPdfObject(dic.get(PdfName.BITSPERCOMPONENT));
- if (obj != null && obj.isNumber())
- bpc = ((PdfNumber)obj).intValue();
- DataInputStream dataStream = new DataInputStream(new ByteArrayInputStream(in));
- ByteArrayOutputStream fout = new ByteArrayOutputStream(in.length);
- int bytesPerPixel = colors * bpc / 8;
- int bytesPerRow = (colors*width*bpc + 7)/8;
- byte[] curr = new byte[bytesPerRow];
- byte[] prior = new byte[bytesPerRow];
-
- // Decode the (sub)image row-by-row
- while (true) {
- // Read the filter type byte and a row of data
- int filter = 0;
- try {
- filter = dataStream.read();
- if (filter < 0) {
- return fout.toByteArray();
- }
- dataStream.readFully(curr, 0, bytesPerRow);
- } catch (Exception e) {
- return fout.toByteArray();
- }
-
- switch (filter) {
- case 0: //PNG_FILTER_NONE
- break;
- case 1: //PNG_FILTER_SUB
- for (int i = bytesPerPixel; i < bytesPerRow; i++) {
- curr[i] += curr[i - bytesPerPixel];
- }
- break;
- case 2: //PNG_FILTER_UP
- for (int i = 0; i < bytesPerRow; i++) {
- curr[i] += prior[i];
- }
- break;
- case 3: //PNG_FILTER_AVERAGE
- for (int i = 0; i < bytesPerPixel; i++) {
- curr[i] += prior[i] / 2;
- }
- for (int i = bytesPerPixel; i < bytesPerRow; i++) {
- curr[i] += ((curr[i - bytesPerPixel] & 0xff) + (prior[i] & 0xff))/2;
- }
- break;
- case 4: //PNG_FILTER_PAETH
- for (int i = 0; i < bytesPerPixel; i++) {
- curr[i] += prior[i];
- }
-
- for (int i = bytesPerPixel; i < bytesPerRow; i++) {
- int a = curr[i - bytesPerPixel] & 0xff;
- int b = prior[i] & 0xff;
- int c = prior[i - bytesPerPixel] & 0xff;
-
- int p = a + b - c;
- int pa = Math.abs(p - a);
- int pb = Math.abs(p - b);
- int pc = Math.abs(p - c);
-
- int ret;
-
- if ((pa <= pb) && (pa <= pc)) {
- ret = a;
- } else if (pb <= pc) {
- ret = b;
- } else {
- ret = c;
- }
- curr[i] += (byte)(ret);
- }
- break;
- default:
- // Error -- uknown filter type
- throw new RuntimeException("PNG filter unknown.");
- }
- try {
- fout.write(curr);
- }
- catch (IOException ioe) {
- // Never happens
- }
-
- // Swap curr and prior
- byte[] tmp = prior;
- prior = curr;
- curr = tmp;
- }
- }
-
- /** A helper to FlateDecode.
- * @param in the input data
- * @param strict true
to read a correct stream. false
- * to try to read a corrupted stream
- * @return the decoded data
- */
- public static byte[] FlateDecode(byte in[], boolean strict) {
- ByteArrayInputStream stream = new ByteArrayInputStream(in);
- InflaterInputStream zip = new InflaterInputStream(stream);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte b[] = new byte[strict ? 4092 : 1];
- try {
- int n;
- while ((n = zip.read(b)) >= 0) {
- out.write(b, 0, n);
- }
- zip.close();
- out.close();
- return out.toByteArray();
- }
- catch (Exception e) {
- if (strict)
- return null;
- return out.toByteArray();
- }
- }
-
- /** Decodes a stream that has the ASCIIHexDecode filter.
- * @param in the input data
- * @return the decoded data
- */
- public static byte[] ASCIIHexDecode(byte in[]) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- boolean first = true;
- int n1 = 0;
- for (int k = 0; k < in.length; ++k) {
- int ch = in[k] & 0xff;
- if (ch == '>')
- break;
- if (PRTokeniser.isWhitespace(ch))
- continue;
- int n = PRTokeniser.getHex(ch);
- if (n == -1)
- throw new RuntimeException("Illegal character in ASCIIHexDecode.");
- if (first)
- n1 = n;
- else
- out.write((byte)((n1 << 4) + n));
- first = !first;
- }
- if (!first)
- out.write((byte)(n1 << 4));
- return out.toByteArray();
- }
-
- /** Decodes a stream that has the ASCII85Decode filter.
- * @param in the input data
- * @return the decoded data
- */
- public static byte[] ASCII85Decode(byte in[]) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- int state = 0;
- int chn[] = new int[5];
- for (int k = 0; k < in.length; ++k) {
- int ch = in[k] & 0xff;
- if (ch == '~')
- break;
- if (PRTokeniser.isWhitespace(ch))
- continue;
- if (ch == 'z' && state == 0) {
- out.write(0);
- out.write(0);
- out.write(0);
- out.write(0);
- continue;
- }
- if (ch < '!' || ch > 'u')
- throw new RuntimeException("Illegal character in ASCII85Decode.");
- chn[state] = ch - '!';
- ++state;
- if (state == 5) {
- state = 0;
- int r = 0;
- for (int j = 0; j < 5; ++j)
- r = r * 85 + chn[j];
- out.write((byte)(r >> 24));
- out.write((byte)(r >> 16));
- out.write((byte)(r >> 8));
- out.write((byte)r);
- }
- }
- int r = 0;
- if (state == 1)
- throw new RuntimeException("Illegal length in ASCII85Decode.");
- if (state == 2) {
- r = chn[0] * 85 * 85 * 85 * 85 + chn[1] * 85 * 85 * 85;
- out.write((byte)(r >> 24));
- }
- else if (state == 3) {
- r = chn[0] * 85 * 85 * 85 * 85 + chn[1] * 85 * 85 * 85 + chn[2] * 85 * 85;
- out.write((byte)(r >> 24));
- out.write((byte)(r >> 16));
- }
- else if (state == 4) {
- r = chn[0] * 85 * 85 * 85 * 85 + chn[1] * 85 * 85 * 85 + chn[2] * 85 * 85 + chn[3] * 85 ;
- out.write((byte)(r >> 24));
- out.write((byte)(r >> 16));
- out.write((byte)(r >> 8));
- }
- return out.toByteArray();
- }
-
- /** Decodes a stream that has the LZWDecode filter.
- * @param in the input data
- * @return the decoded data
- */
- public static byte[] LZWDecode(byte in[]) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- // ssteward: pdftk 1.44
- /* uses old Sun code
- LZWDecoder lzw = new LZWDecoder();
- lzw.decode(in, out);
- */
- // new Apache Batik code
- TIFFLZWDecoder tlzw= new TIFFLZWDecoder();
- tlzw.decode( in, out );
-
- return out.toByteArray();
- }
-
- /** Checks if the document had errors and was rebuilt.
- * @return true if rebuilt.
- *
- */
- public boolean isRebuilt() {
- return this.rebuilt;
- }
-
- /** Gets the dictionary that represents a page.
- * @param pageNum the page number. 1 is the first
- * @return the page dictionary
- */
- public PdfDictionary getPageN(int pageNum) {
- PdfDictionary dic = pageRefs.getPageN(pageNum);
- if (dic == null)
- return null;
- if (appendable)
- dic.setIndRef(pageRefs.getPageOrigRef(pageNum));
- return dic;
- }
-
- /**
- * @param pageNum
- * @return a Dictionary object
- */
- public PdfDictionary getPageNRelease(int pageNum) {
- PdfDictionary dic = getPageN(pageNum);
- pageRefs.releasePage(pageNum);
- return dic;
- }
-
- /**
- * @param pageNum
- */
- public void releasePage(int pageNum) {
- pageRefs.releasePage(pageNum);
- }
-
- /**
- *
- */
- public void resetReleasePage() {
- pageRefs.resetReleasePage();
- }
-
- /** Gets the page reference to this page.
- * @param pageNum the page number. 1 is the first
- * @return the page reference
- */
- public PRIndirectReference getPageOrigRef(int pageNum) {
- return pageRefs.getPageOrigRef(pageNum);
- }
-
- /** Gets the contents of the page.
- * @param pageNum the page number. 1 is the first
- * @param file the location of the PDF document
- * @throws IOException on error
- * @return the content
- */
- public byte[] getPageContent(int pageNum, RandomAccessFileOrArray file) throws IOException{
- PdfDictionary page = getPageNRelease(pageNum);
- if (page == null)
- return null;
- PdfObject contents = getPdfObjectRelease(page.get(PdfName.CONTENTS));
- if (contents == null)
- return new byte[0];
- ByteArrayOutputStream bout = null;
- if (contents.isStream()) {
- return getStreamBytes((PRStream)contents, file);
- }
- else if (contents.isArray()) {
- PdfArray array = (PdfArray)contents;
- ArrayList list = array.getArrayList();
- bout = new ByteArrayOutputStream();
- for (int k = 0; k < list.size(); ++k) {
- PdfObject item = getPdfObjectRelease((PdfObject)list.get(k));
- if (item == null || !item.isStream())
- continue;
- byte[] b = getStreamBytes((PRStream)item, file);
- bout.write(b);
- if (k != list.size() - 1)
- bout.write('\n');
- }
- return bout.toByteArray();
- }
- else
- return new byte[0];
- }
-
- /** Gets the contents of the page.
- * @param pageNum the page number. 1 is the first
- * @throws IOException on error
- * @return the content
- */
- public byte[] getPageContent(int pageNum) throws IOException{
- RandomAccessFileOrArray rf = getSafeFile();
- try {
- rf.reOpen();
- return getPageContent(pageNum, rf);
- }
- finally {
- try{rf.close();}catch(Exception e){}
- }
- }
-
- protected void killXref(PdfObject obj) {
- if (obj == null)
- return;
- if ((obj instanceof PdfIndirectReference) && !obj.isIndirect())
- return;
- switch (obj.type()) {
- case PdfObject.INDIRECT: {
- int xr = ((PRIndirectReference)obj).getNumber();
- obj = (PdfObject)xrefObj.get(xr);
- xrefObj.set(xr, null);
- freeXref = xr;
- killXref(obj);
- break;
- }
- case PdfObject.ARRAY: {
- ArrayList t = ((PdfArray)obj).getArrayList();
- for (int i = 0; i < t.size(); ++i)
- killXref((PdfObject)t.get(i));
- break;
- }
- case PdfObject.STREAM:
- case PdfObject.DICTIONARY: {
- PdfDictionary dic = (PdfDictionary)obj;
- for (Iterator i = dic.getKeys().iterator(); i.hasNext();){
- killXref(dic.get((PdfName)i.next()));
- }
- break;
- }
- }
- }
-
- // ssteward, pdftk 1.10; pulled this out of setPageContent for use elsewhere
- public int getFreeXref() {
- /* changed in itext-paulo 153
- // look for an opening;
- for (int k = xrefObj.length - 1; k > 0; --k) {
- if (xrefObj[k] == null) {
- return k; // <--- return
- }
- }
-
- // no luck; extend xrefObj instead
- int xrefObj_length= xrefObj.length;
- PdfObject temp[] = new PdfObject[xrefObj_length + 10];
- System.arraycopy(xrefObj, 0, temp, 0, xrefObj_length);
- xrefObj = temp;
- return xrefObj_length;
- */
-
- xrefObj.add(null);
- return xrefObj.size() - 1;
- }
-
- // ssteward
- public PRIndirectReference getPRIndirectReference( PdfObject obj ) {
- //int xref= getFreeXref();
- //this.xrefObj[ xref ]= obj;
- xrefObj.add(obj);
- return new PRIndirectReference(this, xrefObj.size() - 1);
- }
-
- /** Sets the contents of the page.
- * @param content the new page content
- * @param pageNum the page number. 1 is the first
- * @throws IOException on error
- */
- public void setPageContent(int pageNum, byte content[]) throws IOException{
- PdfDictionary page = getPageN(pageNum);
- if (page == null)
- return;
- PdfObject contents = page.get(PdfName.CONTENTS);
- freeXref = -1;
- killXref(contents);
- if (freeXref == -1) {
- freeXref = getFreeXref();
- /* ssteward
- xrefObj.add(null);
- freeXref = xrefObj.size() - 1;
- */
- }
- page.put(PdfName.CONTENTS, new PRIndirectReference(this, freeXref));
- xrefObj.set(freeXref, new PRStream(this, content));
- }
-
- /** Get the content from a stream.
- * @param stream the stream
- * @param file the location where the stream is
- * @throws IOException on error
- * @return the stream content
- */
- public static byte[] getStreamBytes(PRStream stream, RandomAccessFileOrArray file) throws IOException {
- PdfReader reader = stream.getReader();
- PdfObject filter = getPdfObjectRelease(stream.get(PdfName.FILTER));
- byte b[];
- if (stream.getOffset() < 0)
- b = stream.getBytes();
- else {
- b = new byte[stream.getLength()];
- file.seek(stream.getOffset());
- file.readFully(b);
- PdfEncryption decrypt = reader.getDecrypt();
- if (decrypt != null) {
- decrypt.setHashKey(stream.getObjNum(), stream.getObjGen());
- decrypt.prepareKey();
- decrypt.encryptRC4(b);
- }
- }
- ArrayList filters = new ArrayList();
- if (filter != null) {
- if (filter.isName())
- filters.add(filter);
- else if (filter.isArray())
- filters = ((PdfArray)filter).getArrayList();
- }
- ArrayList dp = new ArrayList();
- PdfObject dpo = getPdfObjectRelease(stream.get(PdfName.DECODEPARMS));
- if (dpo == null || (!dpo.isDictionary() && !dpo.isArray()))
- dpo = getPdfObjectRelease(stream.get(PdfName.DP));
- if (dpo != null) {
- if (dpo.isDictionary())
- dp.add(dpo);
- else if (dpo.isArray())
- dp = ((PdfArray)dpo).getArrayList();
- }
- String name;
- for (int j = 0; j < filters.size(); ++j) {
- name = ((PdfName)PdfReader.getPdfObjectRelease((PdfObject)filters.get(j))).toString();
- if (name.equals("/FlateDecode") || name.equals("/Fl")) {
- b = PdfReader.FlateDecode(b);
- PdfObject dicParam = null;
- if (j < dp.size()) {
- dicParam = (PdfObject)dp.get(j);
- b = decodePredictor(b, dicParam);
- }
- }
- else if (name.equals("/ASCIIHexDecode") || name.equals("/AHx"))
- b = PdfReader.ASCIIHexDecode(b);
- else if (name.equals("/ASCII85Decode") || name.equals("/A85"))
- b = PdfReader.ASCII85Decode(b);
- else if (name.equals("/LZWDecode")) {
- b = PdfReader.LZWDecode(b);
- PdfObject dicParam = null;
- if (j < dp.size()) {
- dicParam = (PdfObject)dp.get(j);
- b = decodePredictor(b, dicParam);
- }
- }
- else
- throw new IOException("The filter " + name + " is not supported.");
- }
- return b;
- }
-
- /** Get the content from a stream.
- * @param stream the stream
- * @throws IOException on error
- * @return the stream content
- */
- public static byte[] getStreamBytes(PRStream stream) throws IOException {
- RandomAccessFileOrArray rf = stream.getReader().getSafeFile();
- try {
- rf.reOpen();
- return PdfReader.getStreamBytes(stream, rf);
- }
- finally {
- try{rf.close();}catch(Exception e){}
- }
- }
-
- /** Eliminates shared streams if they exist. */
- public void eliminateSharedStreams() {
- if (!sharedStreams)
- return;
- sharedStreams = false;
- if (pageRefs.size() == 1)
- return;
- ArrayList newRefs = new ArrayList();
- ArrayList newStreams = new ArrayList();
- IntHashtable visited = new IntHashtable();
- for (int k = 1; k <= pageRefs.size(); ++k) {
- PdfDictionary page = pageRefs.getPageN(k);
- if (page == null)
- continue;
- PdfObject contents = getPdfObject(page.get(PdfName.CONTENTS));
- if (contents == null)
- continue;
- if (contents.isStream()) {
- PRIndirectReference ref = (PRIndirectReference)page.get(PdfName.CONTENTS);
- if (visited.containsKey(ref.getNumber())) {
- // need to duplicate
- newRefs.add(ref);
- newStreams.add(new PRStream((PRStream)contents, null));
- }
- else
- visited.put(ref.getNumber(), 1);
- }
- else if (contents.isArray()) {
- PdfArray array = (PdfArray)contents;
- ArrayList list = array.getArrayList();
- for (int j = 0; j < list.size(); ++j) {
- PRIndirectReference ref = (PRIndirectReference)list.get(j);
- if (visited.containsKey(ref.getNumber())) {
- // need to duplicate
- newRefs.add(ref);
- newStreams.add(new PRStream((PRStream)getPdfObject(ref), null));
- }
- else
- visited.put(ref.getNumber(), 1);
- }
- }
- }
- if (newStreams.size() == 0)
- return;
- for (int k = 0; k < newStreams.size(); ++k) {
- xrefObj.add(newStreams.get(k));
- PRIndirectReference ref = (PRIndirectReference)newRefs.get(k);
- ref.setNumber(xrefObj.size() - 1, 0);
- }
- }
-
- /** Checks if the document was changed.
- * @return true
if the document was changed,
- * false
otherwise
- */
- public boolean isTampered() {
- return tampered;
- }
-
- /**
- * Sets the tampered state. A tampered PdfReader cannot be reused in PdfStamper.
- * @param tampered the tampered state
- */
- public void setTampered(boolean tampered) {
- this.tampered = tampered;
- }
-
- /** Gets the XML metadata.
- * @throws IOException on error
- * @return the XML metadata
- */
- public byte[] getMetadata() throws IOException {
- PdfObject obj = getPdfObject(catalog.get(PdfName.METADATA));
- if (!(obj instanceof PRStream))
- return null;
- RandomAccessFileOrArray rf = getSafeFile();
- byte b[] = null;
- try {
- rf.reOpen();
- b = getStreamBytes((PRStream)obj, rf);
- }
- finally {
- try {
- rf.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- return b;
- }
-
- /**
- * Gets the byte address of the last xref table.
- * @return the byte address of the last xref table
- */
- public int getLastXref() {
- return lastXref;
- }
-
- /**
- * Gets the number of xref objects.
- * @return the number of xref objects
- */
- public int getXrefSize() {
- return xrefObj.size();
- }
-
- /**
- * Gets the byte address of the %%EOF marker.
- * @return the byte address of the %%EOF marker
- */
- public int getEofPos() {
- return eofPos;
- }
-
- /**
- * Gets the PDF version. Only the last version char is returned. For example
- * version 1.4 is returned as '4'.
- * @return the PDF version
- */
- public char getPdfVersion() {
- return pdfVersion;
- }
-
- /**
- * Returns true
if the PDF is encrypted.
- * @return true
if the PDF is encrypted
- */
- public boolean isEncrypted() {
- return encrypted;
- }
-
- /**
- * Gets the encryption permissions. It can be used directly in
- * PdfWriter.setEncryption()
.
- * @return the encryption permissions
- */
- public int getPermissions() {
- return pValue;
- }
-
- /**
- * Returns true
if the PDF has a 128 bit key encryption.
- * @return true
if the PDF has a 128 bit key encryption
- */
- public boolean is128Key() {
- return rValue == 3;
- }
-
- /**
- * Gets the trailer dictionary
- * @return the trailer dictionary
- */
- public PdfDictionary getTrailer() {
- return trailer;
- }
-
- PdfEncryption getDecrypt() {
- return decrypt;
- }
-
- static boolean equalsn(byte a1[], byte a2[]) {
- int length = a2.length;
- for (int k = 0; k < length; ++k) {
- if (a1[k] != a2[k])
- return false;
- }
- return true;
- }
-
- static boolean existsName(PdfDictionary dic, PdfName key, PdfName value) {
- PdfObject type = getPdfObjectRelease(dic.get(key));
- if (type == null || !type.isName())
- return false;
- PdfName name = (PdfName)type;
- return name.equals(value);
- }
-
- static String getFontName(PdfDictionary dic) {
- PdfObject type = getPdfObjectRelease(dic.get(PdfName.BASEFONT));
- if (type == null || !type.isName())
- return null;
- return PdfName.decodeName(type.toString());
- }
-
- static String getSubsetPrefix(PdfDictionary dic) {
- String s = getFontName(dic);
- if (s == null)
- return null;
- if (s.length() < 8 || s.charAt(6) != '+')
- return null;
- for (int k = 0; k < 6; ++k) {
- char c = s.charAt(k);
- if (c < 'A' || c > 'Z')
- return null;
- }
- return s;
- }
-
- /** Finds all the font subsets and changes the prefixes to some
- * random values.
- * @return the number of font subsets altered
- */
- public int shuffleSubsetNames() {
- int total = 0;
- for (int k = 1; k < xrefObj.size(); ++k) {
- PdfObject obj = getPdfObjectRelease(k);
- if (obj == null || !obj.isDictionary())
- continue;
- PdfDictionary dic = (PdfDictionary)obj;
- if (!existsName(dic, PdfName.TYPE, PdfName.FONT))
- continue;
- if (existsName(dic, PdfName.SUBTYPE, PdfName.TYPE1)
- || existsName(dic, PdfName.SUBTYPE, PdfName.MMTYPE1)
- || existsName(dic, PdfName.SUBTYPE, PdfName.TRUETYPE)) {
- String s = getSubsetPrefix(dic);
- if (s == null)
- continue;
- String ns = BaseFont.createSubsetPrefix() + s.substring(7);
- PdfName newName = new PdfName(ns);
- dic.put(PdfName.BASEFONT, newName);
- setXrefPartialObject(k, dic);
- ++total;
- PdfDictionary fd = (PdfDictionary)getPdfObject(dic.get(PdfName.FONTDESCRIPTOR));
- if (fd == null)
- continue;
- fd.put(PdfName.FONTNAME, newName);
- }
- else if (existsName(dic, PdfName.SUBTYPE, PdfName.TYPE0)) {
- String s = getSubsetPrefix(dic);
- PdfArray arr = (PdfArray)getPdfObject(dic.get(PdfName.DESCENDANTFONTS));
- if (arr == null)
- continue;
- ArrayList list = arr.getArrayList();
- if (list.size() == 0)
- continue;
- PdfDictionary desc = (PdfDictionary)getPdfObject((PdfObject)list.get(0));
- String sde = getSubsetPrefix(desc);
- if (sde == null)
- continue;
- String ns = BaseFont.createSubsetPrefix();
- if (s != null)
- dic.put(PdfName.BASEFONT, new PdfName(ns + s.substring(7)));
- setXrefPartialObject(k, dic);
- PdfName newName = new PdfName(ns + sde.substring(7));
- desc.put(PdfName.BASEFONT, newName);
- ++total;
- PdfDictionary fd = (PdfDictionary)getPdfObject(desc.get(PdfName.FONTDESCRIPTOR));
- if (fd == null)
- continue;
- fd.put(PdfName.FONTNAME, newName);
- }
- }
- return total;
- }
-
- /** Finds all the fonts not subset but embedded and marks them as subset.
- * @return the number of fonts altered
- */
- public int createFakeFontSubsets() {
- int total = 0;
- for (int k = 1; k < xrefObj.size(); ++k) {
- PdfObject obj = getPdfObjectRelease(k);
- if (obj == null || !obj.isDictionary())
- continue;
- PdfDictionary dic = (PdfDictionary)obj;
- if (!existsName(dic, PdfName.TYPE, PdfName.FONT))
- continue;
- if (existsName(dic, PdfName.SUBTYPE, PdfName.TYPE1)
- || existsName(dic, PdfName.SUBTYPE, PdfName.MMTYPE1)
- || existsName(dic, PdfName.SUBTYPE, PdfName.TRUETYPE)) {
- String s = getSubsetPrefix(dic);
- if (s != null)
- continue;
- s = getFontName(dic);
- if (s == null)
- continue;
- String ns = BaseFont.createSubsetPrefix() + s;
- PdfDictionary fd = (PdfDictionary)getPdfObjectRelease(dic.get(PdfName.FONTDESCRIPTOR));
- if (fd == null)
- continue;
- if (fd.get(PdfName.FONTFILE) == null && fd.get(PdfName.FONTFILE2) == null
- && fd.get(PdfName.FONTFILE3) == null)
- continue;
- fd = (PdfDictionary)getPdfObject(dic.get(PdfName.FONTDESCRIPTOR));
- PdfName newName = new PdfName(ns);
- dic.put(PdfName.BASEFONT, newName);
- fd.put(PdfName.FONTNAME, newName);
- setXrefPartialObject(k, dic);
- ++total;
- }
- }
- return total;
- }
-
- private static PdfArray getNameArray(PdfObject obj) {
- if (obj == null)
- return null;
- obj = getPdfObjectRelease(obj);
- if (obj.isArray())
- return (PdfArray)obj;
- else if (obj.isDictionary()) {
- PdfObject arr2 = getPdfObjectRelease(((PdfDictionary)obj).get(PdfName.D));
- if (arr2 != null && arr2.isArray())
- return (PdfArray)arr2;
- }
- return null;
- }
-
- /**
- * Gets all the named destinations as an HashMap
. The key is the name
- * and the value is the destinations array.
- * @return gets all the named destinations
- */
- public HashMap getNamedDestination() {
- HashMap names = getNamedDestinationFromNames();
- names.putAll(getNamedDestinationFromStrings());
- return names;
- }
-
- /**
- * Gets the named destinations from the /Dests key in the catalog as an HashMap
. The key is the name
- * and the value is the destinations array.
- * @return gets the named destinations
- */
- public HashMap getNamedDestinationFromNames() {
- HashMap names = new HashMap();
- if (catalog.get(PdfName.DESTS) != null) {
- PdfDictionary dic = (PdfDictionary)getPdfObjectRelease(catalog.get(PdfName.DESTS));
- Set keys = dic.getKeys();
- for (Iterator it = keys.iterator(); it.hasNext();) {
- PdfName key = (PdfName)it.next();
- String name = PdfName.decodeName(key.toString());
- PdfArray arr = getNameArray(dic.get(key));
- if (arr != null)
- names.put(name, arr);
- }
- }
- return names;
- }
-
- /**
- * Gets the named destinations from the /Names key in the catalog as an HashMap
. The key is the name
- * and the value is the destinations array.
- * @return gets the named destinations
- */
- public HashMap getNamedDestinationFromStrings() {
- if (catalog.get(PdfName.NAMES) != null) {
- PdfDictionary dic = (PdfDictionary)getPdfObjectRelease(catalog.get(PdfName.NAMES));
- dic = (PdfDictionary)getPdfObjectRelease(dic.get(PdfName.DESTS));
- if (dic != null) {
- HashMap names = PdfNameTree.readTree(dic);
- for (Iterator it = names.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry)it.next();
- PdfArray arr = getNameArray((PdfObject)entry.getValue());
- if (arr != null)
- entry.setValue(arr);
- else
- it.remove();
- }
- return names;
- }
- }
- return new HashMap();
- }
-
- private boolean replaceNamedDestination(PdfObject obj, HashMap names) {
- obj = getPdfObject(obj);
- int objIdx = lastXrefPartial;
- releaseLastXrefPartial();
- if (obj != null && obj.isDictionary()) {
- PdfObject ob2 = getPdfObjectRelease(((PdfDictionary)obj).get(PdfName.DEST));
- String name = null;
- if (ob2 != null) {
- if (ob2.isName())
- name = PdfName.decodeName(ob2.toString());
- else if (ob2.isString())
- name = ob2.toString();
- PdfArray dest = (PdfArray)names.get(name);
- if (dest != null) {
- ((PdfDictionary)obj).put(PdfName.DEST, dest);
- setXrefPartialObject(objIdx, obj);
- return true;
- }
- }
- else if ((ob2 = getPdfObject(((PdfDictionary)obj).get(PdfName.A))) != null) {
- int obj2Idx = lastXrefPartial;
- releaseLastXrefPartial();
- PdfDictionary dic = (PdfDictionary)ob2;
- PdfName type = (PdfName)getPdfObjectRelease(dic.get(PdfName.S));
- if (PdfName.GOTO.equals(type)) {
- PdfObject ob3 = getPdfObjectRelease(dic.get(PdfName.D));
- if (ob3.isName())
- name = PdfName.decodeName(ob3.toString());
- else if (ob3.isString())
- name = ob3.toString();
- PdfArray dest = (PdfArray)names.get(name);
- if (dest != null) {
- dic.put(PdfName.D, dest);
- setXrefPartialObject(obj2Idx, ob2);
- setXrefPartialObject(objIdx, obj);
- return true;
- }
- }
- }
- }
- return false;
- }
-
- /**
- * Removes all the fields from the document.
- */
- public void removeFields() {
- pageRefs.resetReleasePage();
- for (int k = 1; k <= pageRefs.size(); ++k) {
- PdfDictionary page = pageRefs.getPageN(k);
- PdfArray annots = (PdfArray)getPdfObject(page.get(PdfName.ANNOTS));
- if (annots == null) {
- pageRefs.releasePage(k);
- continue;
- }
- ArrayList arr = annots.getArrayList();
- // int startSize = arr.size();
- for (int j = 0; j < arr.size(); ++j) {
- PdfDictionary annot = (PdfDictionary)getPdfObjectRelease((PdfObject)arr.get(j));
- if (PdfName.WIDGET.equals(annot.get(PdfName.SUBTYPE)))
- arr.remove(j--);
- }
- if (arr.isEmpty())
- page.remove(PdfName.ANNOTS);
- else
- pageRefs.releasePage(k);
- }
- catalog.remove(PdfName.ACROFORM);
- pageRefs.resetReleasePage();
- }
-
- /**
- * Removes all the annotations and fields from the document.
- */
- public void removeAnnotations() {
- pageRefs.resetReleasePage();
- for (int k = 1; k <= pageRefs.size(); ++k) {
- PdfDictionary page = pageRefs.getPageN(k);
- if (page.get(PdfName.ANNOTS) == null)
- pageRefs.releasePage(k);
- else
- page.remove(PdfName.ANNOTS);
- }
- catalog.remove(PdfName.ACROFORM);
- pageRefs.resetReleasePage();
- }
-
- private void iterateBookmarks(PdfObject outlineRef, HashMap names) {
- while (outlineRef != null) {
- replaceNamedDestination(outlineRef, names);
- PdfDictionary outline = (PdfDictionary)getPdfObjectRelease(outlineRef);
- PdfObject first = outline.get(PdfName.FIRST);
- if (first != null) {
- iterateBookmarks(first, names);
- }
- outlineRef = outline.get(PdfName.NEXT);
- }
- }
-
- /** Replaces all the local named links with the actual destinations. */
- public void consolidateNamedDestinations() {
- if (consolidateNamedDestinations)
- return;
- consolidateNamedDestinations = true;
- HashMap names = getNamedDestination();
- if (names.size() == 0)
- return;
- for (int k = 1; k <= pageRefs.size(); ++k) {
- PdfDictionary page = pageRefs.getPageN(k);
- PdfObject annotsRef;
- PdfArray annots = (PdfArray)getPdfObject(annotsRef = page.get(PdfName.ANNOTS));
- int annotIdx = lastXrefPartial;
- releaseLastXrefPartial();
- if (annots == null) {
- pageRefs.releasePage(k);
- continue;
- }
- ArrayList list = annots.getArrayList();
- boolean commitAnnots = false;
- for (int an = 0; an < list.size(); ++an) {
- PdfObject objRef = (PdfObject)list.get(an);
- if (replaceNamedDestination(objRef, names) && !objRef.isIndirect())
- commitAnnots = true;
- }
- if (commitAnnots)
- setXrefPartialObject(annotIdx, annots);
- if (!commitAnnots || annotsRef.isIndirect())
- pageRefs.releasePage(k);
- }
- PdfDictionary outlines = (PdfDictionary)getPdfObjectRelease(catalog.get(PdfName.OUTLINES));
- if (outlines == null)
- return;
- iterateBookmarks(outlines.get(PdfName.FIRST), names);
- }
-
- protected static PdfDictionary duplicatePdfDictionary(PdfDictionary original, PdfDictionary copy, PdfReader newReader) {
- if (copy == null)
- copy = new PdfDictionary();
- for (Iterator it = original.getKeys().iterator(); it.hasNext();) {
- PdfName key = (PdfName)it.next();
- copy.put(key, duplicatePdfObject(original.get(key), newReader));
- }
- return copy;
- }
-
- protected static PdfObject duplicatePdfObject(PdfObject original, PdfReader newReader) {
- if (original == null)
- return null;
- switch (original.type()) {
- case PdfObject.DICTIONARY: {
- return duplicatePdfDictionary((PdfDictionary)original, null, newReader);
- }
- case PdfObject.STREAM: {
- PRStream org = (PRStream)original;
- PRStream stream = new PRStream(org, null, newReader);
- duplicatePdfDictionary(org, stream, newReader);
- return stream;
- }
- case PdfObject.ARRAY: {
- ArrayList list = ((PdfArray)original).getArrayList();
- PdfArray arr = new PdfArray();
- for (Iterator it = list.iterator(); it.hasNext();) {
- arr.add(duplicatePdfObject((PdfObject)it.next(), newReader));
- }
- return arr;
- }
- case PdfObject.INDIRECT: {
- PRIndirectReference org = (PRIndirectReference)original;
- return new PRIndirectReference(newReader, org.getNumber(), org.getGeneration());
- }
- default:
- return original;
- }
- }
-
- /**
- * Closes the reader
- */
- public void close() {
- if (!partial)
- return;
- try {
- tokens.close();
- }
- catch (IOException e) {
- throw new ExceptionConverter(e);
- }
- }
-
- protected void removeUnusedNode(PdfObject obj, boolean hits[]) {
- if (obj == null)
- return;
- switch (obj.type()) {
- case PdfObject.DICTIONARY:
- case PdfObject.STREAM: {
- PdfDictionary dic = (PdfDictionary)obj;
- for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
- PdfName key = (PdfName)it.next();
- PdfObject v = dic.get(key);
- if (v.isIndirect()) {
- int num = ((PRIndirectReference)v).getNumber();
- if (num >= xrefObj.size() || (!partial && xrefObj.get(num) == null)) {
- dic.put(key, PdfNull.PDFNULL);
- continue;
- }
- }
- removeUnusedNode(v, hits);
- }
- break;
- }
- case PdfObject.ARRAY: {
- ArrayList list = ((PdfArray)obj).getArrayList();
- for (int k = 0; k < list.size(); ++k) {
- PdfObject v = (PdfObject)list.get(k);
- if (v.isIndirect()) {
- int num = ((PRIndirectReference)v).getNumber();
- if (num >= xrefObj.size() || (!partial && xrefObj.get(num) == null)) {
- list.set(k, PdfNull.PDFNULL);
- continue;
- }
- }
- removeUnusedNode(v, hits);
- }
- break;
- }
- case PdfObject.INDIRECT: {
- PRIndirectReference ref = (PRIndirectReference)obj;
- int num = ref.getNumber();
- if (!hits[num]) {
- hits[num] = true;
- removeUnusedNode(getPdfObjectRelease(ref), hits);
- }
- }
- }
- }
-
- /** Removes all the unreachable objects.
- * @return the number of indirect objects removed
- */
- public int removeUnusedObjects() {
- boolean hits[] = new boolean[xrefObj.size()];
- removeUnusedNode(trailer, hits);
- int total = 0;
- if (partial) {
- for (int k = 1; k < hits.length; ++k) {
- if (!hits[k]) {
- xref[k * 2] = -1;
- xref[k * 2 + 1] = 0;
- xrefObj.set(k, null);
- ++total;
- }
- }
- }
- else {
- for (int k = 1; k < hits.length; ++k) {
- if (!hits[k]) {
- xrefObj.set(k, null);
- ++total;
- }
- }
- }
- return total;
- }
-
- /** Gets a read-only version of AcroFields
.
- * @return a read-only version of AcroFields
- */
- public AcroFields getAcroFields() {
- return new AcroFields(this, null);
- }
-
- /**
- * Gets the global document JavaScript.
- * @param file the document file
- * @throws IOException on error
- * @return the global document JavaScript
- */
- public String getJavaScript(RandomAccessFileOrArray file) throws IOException {
- PdfDictionary names = (PdfDictionary)getPdfObjectRelease(catalog.get(PdfName.NAMES));
- if (names == null)
- return null;
- PdfDictionary js = (PdfDictionary)getPdfObjectRelease(names.get(PdfName.JAVASCRIPT));
- if (js == null)
- return null;
- HashMap jscript = PdfNameTree.readTree(js);
- String sortedNames[] = new String[jscript.size()];
- sortedNames = (String[])jscript.keySet().toArray(sortedNames);
- Arrays.sort(sortedNames, new StringCompare());
- StringBuffer buf = new StringBuffer();
- for (int k = 0; k < sortedNames.length; ++k) {
- PdfDictionary j = (PdfDictionary)getPdfObjectRelease((PdfIndirectReference)jscript.get(sortedNames[k]));
- if (j == null)
- continue;
- PdfObject obj = getPdfObjectRelease(j.get(PdfName.JS));
- if (obj.isString())
- buf.append(((PdfString)obj).toUnicodeString()).append('\n');
- else if (obj.isStream()) {
- byte bytes[] = getStreamBytes((PRStream)obj, file);
- if (bytes.length >= 2 && bytes[0] == (byte)254 && bytes[1] == (byte)255)
- buf.append(PdfEncodings.convertToString(bytes, PdfObject.TEXT_UNICODE));
- else
- buf.append(PdfEncodings.convertToString(bytes, PdfObject.TEXT_PDFDOCENCODING));
- buf.append('\n');
- }
- }
- return buf.toString();
- }
-
- /**
- * Gets the global document JavaScript.
- * @throws IOException on error
- * @return the global document JavaScript
- */
- public String getJavaScript() throws IOException {
- RandomAccessFileOrArray rf = getSafeFile();
- try {
- rf.reOpen();
- return getJavaScript(rf);
- }
- finally {
- try{rf.close();}catch(Exception e){}
- }
- }
-
- /**
- * Selects the pages to keep in the document. The pages are described as
- * ranges. The page ordering can be changed but
- * no page repetitions are allowed. Note that it may be very slow in partial mode.
- * @param ranges the comma separated ranges as described in {@link SequenceList}
- */
- public void selectPages(String ranges) {
- selectPages(SequenceList.expand(ranges, getNumberOfPages()));
- }
-
- /**
- * Selects the pages to keep in the document. The pages are described as a
- * List
of Integer
. The page ordering can be changed but
- * no page repetitions are allowed. Note that it may be very slow in partial mode.
- * @param pagesToKeep the pages to keep in the document
- */
- public void selectPages(List pagesToKeep) {
- pageRefs.selectPages(pagesToKeep);
- removeUnusedObjects();
- }
-
- /**
- * @param preferences
- * @param catalog
- */
- public static void setViewerPreferences(int preferences, PdfDictionary catalog) {
- catalog.remove(PdfName.PAGELAYOUT);
- catalog.remove(PdfName.PAGEMODE);
- catalog.remove(PdfName.VIEWERPREFERENCES);
- if ((preferences & PdfWriter.PageLayoutSinglePage) != 0)
- catalog.put(PdfName.PAGELAYOUT, PdfName.SINGLEPAGE);
- else if ((preferences & PdfWriter.PageLayoutOneColumn) != 0)
- catalog.put(PdfName.PAGELAYOUT, PdfName.ONECOLUMN);
- else if ((preferences & PdfWriter.PageLayoutTwoColumnLeft) != 0)
- catalog.put(PdfName.PAGELAYOUT, PdfName.TWOCOLUMNLEFT);
- else if ((preferences & PdfWriter.PageLayoutTwoColumnRight) != 0)
- catalog.put(PdfName.PAGELAYOUT, PdfName.TWOCOLUMNRIGHT);
- if ((preferences & PdfWriter.PageModeUseNone) != 0)
- catalog.put(PdfName.PAGEMODE, PdfName.USENONE);
- else if ((preferences & PdfWriter.PageModeUseOutlines) != 0)
- catalog.put(PdfName.PAGEMODE, PdfName.USEOUTLINES);
- else if ((preferences & PdfWriter.PageModeUseThumbs) != 0)
- catalog.put(PdfName.PAGEMODE, PdfName.USETHUMBS);
- else if ((preferences & PdfWriter.PageModeFullScreen) != 0)
- catalog.put(PdfName.PAGEMODE, PdfName.FULLSCREEN);
- else if ((preferences & PdfWriter.PageModeUseOC) != 0)
- catalog.put(PdfName.PAGEMODE, PdfName.USEOC);
- if ((preferences & PdfWriter.ViewerPreferencesMask) == 0)
- return;
- PdfDictionary vp = new PdfDictionary();
- if ((preferences & PdfWriter.HideToolbar) != 0)
- vp.put(PdfName.HIDETOOLBAR, PdfBoolean.PDFTRUE);
- if ((preferences & PdfWriter.HideMenubar) != 0)
- vp.put(PdfName.HIDEMENUBAR, PdfBoolean.PDFTRUE);
- if ((preferences & PdfWriter.HideWindowUI) != 0)
- vp.put(PdfName.HIDEWINDOWUI, PdfBoolean.PDFTRUE);
- if ((preferences & PdfWriter.FitWindow) != 0)
- vp.put(PdfName.FITWINDOW, PdfBoolean.PDFTRUE);
- if ((preferences & PdfWriter.CenterWindow) != 0)
- vp.put(PdfName.CENTERWINDOW, PdfBoolean.PDFTRUE);
- if ((preferences & PdfWriter.DisplayDocTitle) != 0)
- vp.put(PdfName.DISPLAYDOCTITLE, PdfBoolean.PDFTRUE);
- if ((preferences & PdfWriter.NonFullScreenPageModeUseNone) != 0)
- vp.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USENONE);
- else if ((preferences & PdfWriter.NonFullScreenPageModeUseOutlines) != 0)
- vp.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USEOUTLINES);
- else if ((preferences & PdfWriter.NonFullScreenPageModeUseThumbs) != 0)
- vp.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USETHUMBS);
- else if ((preferences & PdfWriter.NonFullScreenPageModeUseOC) != 0)
- vp.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USEOC);
- if ((preferences & PdfWriter.DirectionL2R) != 0)
- vp.put(PdfName.DIRECTION, PdfName.L2R);
- else if ((preferences & PdfWriter.DirectionR2L) != 0)
- vp.put(PdfName.DIRECTION, PdfName.R2L);
- if ((preferences & PdfWriter.PrintScalingNone) != 0)
- vp.put(PdfName.PRINTSCALING, PdfName.NONE);
- catalog.put(PdfName.VIEWERPREFERENCES, vp);
- }
-
- /**
- * @param preferences
- */
- public void setViewerPreferences(int preferences) {
- setViewerPreferences(preferences, catalog);
- }
-
- /**
- * @return an int that contains the Viewer Preferences.
- */
- public int getViewerPreferences() {
- int prefs = 0;
- PdfName name = null;
- PdfObject obj = getPdfObjectRelease(catalog.get(PdfName.PAGELAYOUT));
- if (obj != null && obj.isName()) {
- name = (PdfName)obj;
- if (name.equals(PdfName.SINGLEPAGE))
- prefs |= PdfWriter.PageLayoutSinglePage;
- else if (name.equals(PdfName.ONECOLUMN))
- prefs |= PdfWriter.PageLayoutOneColumn;
- else if (name.equals(PdfName.TWOCOLUMNLEFT))
- prefs |= PdfWriter.PageLayoutTwoColumnLeft;
- else if (name.equals(PdfName.TWOCOLUMNRIGHT))
- prefs |= PdfWriter.PageLayoutTwoColumnRight;
- }
- obj = getPdfObjectRelease(catalog.get(PdfName.PAGEMODE));
- if (obj != null && obj.isName()) {
- name = (PdfName)obj;
- if (name.equals(PdfName.USENONE))
- prefs |= PdfWriter.PageModeUseNone;
- else if (name.equals(PdfName.USEOUTLINES))
- prefs |= PdfWriter.PageModeUseOutlines;
- else if (name.equals(PdfName.USETHUMBS))
- prefs |= PdfWriter.PageModeUseThumbs;
- else if (name.equals(PdfName.USEOC))
- prefs |= PdfWriter.PageModeUseOC;
- }
- obj = getPdfObjectRelease(catalog.get(PdfName.VIEWERPREFERENCES));
- if (obj == null || !obj.isDictionary())
- return prefs;
- PdfDictionary vp = (PdfDictionary)obj;
- for (int k = 0; k < vpnames.length; ++k) {
- obj = getPdfObject(vp.get(vpnames[k]));
- if (obj != null && "true".equals(obj.toString()))
- prefs |= vpints[k];
- }
- obj = getPdfObjectRelease(vp.get(PdfName.PRINTSCALING));
- if (PdfName.NONE.equals(obj))
- prefs |= PdfWriter.PrintScalingNone;
- obj = getPdfObjectRelease(vp.get(PdfName.NONFULLSCREENPAGEMODE));
- if (obj != null && obj.isName()) {
- name = (PdfName)obj;
- if (name.equals(PdfName.USENONE))
- prefs |= PdfWriter.NonFullScreenPageModeUseNone;
- else if (name.equals(PdfName.USEOUTLINES))
- prefs |= PdfWriter.NonFullScreenPageModeUseOutlines;
- else if (name.equals(PdfName.USETHUMBS))
- prefs |= PdfWriter.NonFullScreenPageModeUseThumbs;
- else if (name.equals(PdfName.USEOC))
- prefs |= PdfWriter.NonFullScreenPageModeUseOC;
- }
- obj = getPdfObjectRelease(vp.get(PdfName.DIRECTION));
- if (obj != null && obj.isName()) {
- name = (PdfName)obj;
- if (name.equals(PdfName.L2R))
- prefs |= PdfWriter.DirectionL2R;
- else if (name.equals(PdfName.R2L))
- prefs |= PdfWriter.DirectionR2L;
- }
- return prefs;
- }
-
- /**
- * Getter for property appendable.
- * @return Value of property appendable.
- */
- public boolean isAppendable() {
- return this.appendable;
- }
-
- /**
- * Setter for property appendable.
- * @param appendable New value of property appendable.
- */
- public void setAppendable(boolean appendable) {
- this.appendable = appendable;
- if (appendable)
- getPdfObject(trailer.get(PdfName.ROOT));
- }
-
- /**
- * Getter for property newXrefType.
- * @return Value of property newXrefType.
- */
- public boolean isNewXrefType() {
- return newXrefType;
- }
-
- /**
- * Getter for property fileLength.
- * @return Value of property fileLength.
- */
- public int getFileLength() {
- return fileLength;
- }
-
- /**
- * Getter for property hybridXref.
- * @return Value of property hybridXref.
- */
- public boolean isHybridXref() {
- return hybridXref;
- }
-
- static class PageRefs {
- private PdfReader reader;
- private IntHashtable refsp;
- private ArrayList refsn;
- private ArrayList pageInh;
- private int lastPageRead = -1;
- private int sizep;
-
- private PageRefs(PdfReader reader) throws IOException {
- this.reader = reader;
- if (reader.partial) {
- refsp = new IntHashtable();
- PdfNumber npages = (PdfNumber)PdfReader.getPdfObjectRelease(reader.rootPages.get(PdfName.COUNT));
- sizep = npages.intValue();
- }
- else {
- readPages();
- }
- }
-
- PageRefs(PageRefs other, PdfReader reader) {
- this.reader = reader;
- this.sizep = other.sizep;
- if (other.refsn != null) {
- refsn = new ArrayList(other.refsn);
- for (int k = 0; k < refsn.size(); ++k) {
- refsn.set(k, duplicatePdfObject((PdfObject)refsn.get(k), reader));
- }
- }
- else
- this.refsp = (IntHashtable)other.refsp.clone();
- }
-
- int size() {
- if (refsn != null)
- return refsn.size();
- else
- return sizep;
- }
-
- void readPages() throws IOException {
- if (refsn != null)
- return;
- refsp = null;
- refsn = new ArrayList();
- pageInh = new ArrayList();
- iteratePages((PRIndirectReference)reader.catalog.get(PdfName.PAGES));
- pageInh = null;
- reader.rootPages.put(PdfName.COUNT, new PdfNumber(refsn.size()));
- }
-
- void reReadPages() throws IOException {
- refsn = null;
- readPages();
- }
-
- /** Gets the dictionary that represents a page.
- * @param pageNum the page number. 1 is the first
- * @return the page dictionary
- */
- public PdfDictionary getPageN(int pageNum) {
- PRIndirectReference ref = getPageOrigRef(pageNum);
- return (PdfDictionary)PdfReader.getPdfObject(ref);
- }
-
- /**
- * @param pageNum
- * @return a dictionary object
- */
- public PdfDictionary getPageNRelease(int pageNum) {
- PdfDictionary page = getPageN(pageNum);
- releasePage(pageNum);
- return page;
- }
-
- /**
- * @param pageNum
- * @return an indirect reference
- */
- public PRIndirectReference getPageOrigRefRelease(int pageNum) {
- PRIndirectReference ref = getPageOrigRef(pageNum);
- releasePage(pageNum);
- return ref;
- }
-
- /** Gets the page reference to this page.
- * @param pageNum the page number. 1 is the first
- * @return the page reference
- */
- public PRIndirectReference getPageOrigRef(int pageNum) {
- try {
- --pageNum;
- if (pageNum < 0 || pageNum >= size())
- return null;
- if (refsn != null)
- return (PRIndirectReference)refsn.get(pageNum);
- else {
- int n = refsp.get(pageNum);
- if (n == 0) {
- PRIndirectReference ref = getSinglePage(pageNum);
- if (reader.lastXrefPartial == -1)
- lastPageRead = -1;
- else
- lastPageRead = pageNum;
- reader.lastXrefPartial = -1;
- refsp.put(pageNum, ref.getNumber());
- return ref;
- }
- else {
- if (lastPageRead != pageNum)
- lastPageRead = -1;
- return new PRIndirectReference(reader, n);
- }
- }
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * @param pageNum
- */
- public void releasePage(int pageNum) {
- if (refsp == null)
- return;
- --pageNum;
- if (pageNum < 0 || pageNum >= size())
- return;
- if (pageNum != lastPageRead)
- return;
- lastPageRead = -1;
- reader.lastXrefPartial = refsp.get(pageNum);
- reader.releaseLastXrefPartial();
- refsp.remove(pageNum);
- }
-
- /**
- *
- */
- public void resetReleasePage() {
- if (refsp == null)
- return;
- lastPageRead = -1;
- }
-
- void insertPage(int pageNum, PRIndirectReference ref) {
- --pageNum;
- if (refsn != null) {
- if (pageNum >= refsn.size())
- refsn.add(ref);
- else
- refsn.add(pageNum, ref);
- }
- else {
- ++sizep;
- lastPageRead = -1;
- if (pageNum >= size()) {
- refsp.put(size(), ref.getNumber());
- }
- else {
- IntHashtable refs2 = new IntHashtable((refsp.size() + 1) * 2);
- for (Iterator it = refsp.getEntryIterator(); it.hasNext();) {
- IntHashtable.IntHashtableEntry entry = (IntHashtable.IntHashtableEntry)it.next();
- int p = entry.getKey();
- refs2.put(p >= pageNum ? p + 1 : p, entry.getValue());
- }
- refs2.put(pageNum, ref.getNumber());
- refsp = refs2;
- }
- }
- }
-
- private void pushPageAttributes(PdfDictionary nodePages) {
- PdfDictionary dic = new PdfDictionary();
- if (pageInh.size() != 0) {
- dic.putAll((PdfDictionary)pageInh.get(pageInh.size() - 1));
- }
- for (int k = 0; k < pageInhCandidates.length; ++k) {
- PdfObject obj = nodePages.get(pageInhCandidates[k]);
- if (obj != null)
- dic.put(pageInhCandidates[k], obj);
- }
- pageInh.add(dic);
- }
-
- private void popPageAttributes() {
- pageInh.remove(pageInh.size() - 1);
- }
-
- private void iteratePages(PRIndirectReference rpage) throws IOException {
- PdfDictionary page = (PdfDictionary)getPdfObject(rpage);
- PdfArray kidsPR = (PdfArray)getPdfObject(page.get(PdfName.KIDS));
- if (kidsPR == null) {
- page.put(PdfName.TYPE, PdfName.PAGE);
- PdfDictionary dic = (PdfDictionary)pageInh.get(pageInh.size() - 1);
- PdfName key;
- for (Iterator i = dic.getKeys().iterator(); i.hasNext();) {
- key = (PdfName)i.next();
- if (page.get(key) == null)
- page.put(key, dic.get(key));
- }
- if (page.get(PdfName.MEDIABOX) == null) {
- PdfArray arr = new PdfArray(new float[]{0,0,PageSize.LETTER.right(),PageSize.LETTER.top()});
- page.put(PdfName.MEDIABOX, arr);
- }
- refsn.add(rpage);
- }
- else {
- page.put(PdfName.TYPE, PdfName.PAGES);
- pushPageAttributes(page);
- ArrayList kids = kidsPR.getArrayList();
- for (int k = 0; k < kids.size(); ++k){
- iteratePages((PRIndirectReference)kids.get(k));
- }
- popPageAttributes();
- }
- }
-
- protected PRIndirectReference getSinglePage(int n) throws IOException {
- PdfDictionary acc = new PdfDictionary();
- PdfDictionary top = reader.rootPages;
- int base = 0;
- while (true) {
- for (int k = 0; k < pageInhCandidates.length; ++k) {
- PdfObject obj = top.get(pageInhCandidates[k]);
- if (obj != null)
- acc.put(pageInhCandidates[k], obj);
- }
- PdfArray kids = (PdfArray)PdfReader.getPdfObjectRelease(top.get(PdfName.KIDS));
- for (Iterator it = kids.listIterator(); it.hasNext();) {
- PRIndirectReference ref = (PRIndirectReference)it.next();
- PdfDictionary dic = (PdfDictionary)getPdfObject(ref);
- int last = reader.lastXrefPartial;
- PdfObject count = getPdfObjectRelease(dic.get(PdfName.COUNT));
- reader.lastXrefPartial = last;
- int acn = 1;
- if (count != null && count.type() == PdfObject.NUMBER)
- acn = ((PdfNumber)count).intValue();
- if (n < base + acn) {
- if (count == null) {
- dic.mergeDifferent(acc);
- return ref;
- }
- reader.releaseLastXrefPartial();
- top = dic;
- break;
- }
- reader.releaseLastXrefPartial();
- base += acn;
- }
- }
- }
-
- private void selectPages(List pagesToKeep) {
- IntHashtable pg = new IntHashtable();
- ArrayList finalPages = new ArrayList();
- int psize = size();
- for (Iterator it = pagesToKeep.iterator(); it.hasNext();) {
- Integer pi = (Integer)it.next();
- int p = pi.intValue();
- if (p >= 1 && p <= psize && pg.put(p, 1) == 0)
- finalPages.add(pi);
- }
- if (reader.partial) {
- for (int k = 1; k <= psize; ++k) {
- getPageOrigRef(k);
- resetReleasePage();
- }
- }
- PRIndirectReference parent = (PRIndirectReference)reader.catalog.get(PdfName.PAGES);
- PdfDictionary topPages = (PdfDictionary)PdfReader.getPdfObject(parent);
- ArrayList newPageRefs = new ArrayList(finalPages.size());
- PdfArray kids = new PdfArray();
- for (int k = 0; k < finalPages.size(); ++k) {
- int p = ((Integer)finalPages.get(k)).intValue();
- PRIndirectReference pref = getPageOrigRef(p);
- resetReleasePage();
- kids.add(pref);
- newPageRefs.add(pref);
- getPageN(p).put(PdfName.PARENT, parent);
- }
- AcroFields af = reader.getAcroFields();
- boolean removeFields = (af.getFields().size() > 0);
- for (int k = 1; k <= psize; ++k) {
- if (!pg.containsKey(k)) {
- if (removeFields)
- af.removeFieldsFromPage(k);
- PRIndirectReference pref = getPageOrigRef(k);
- int nref = pref.getNumber();
- reader.xrefObj.set(nref, null);
- if (reader.partial) {
- reader.xref[nref * 2] = -1;
- reader.xref[nref * 2 + 1] = 0;
- }
- }
- }
- topPages.put(PdfName.COUNT, new PdfNumber(finalPages.size()));
- topPages.put(PdfName.KIDS, kids);
- refsp = null;
- refsn = newPageRefs;
- }
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfReaderInstance.java pdftk-2.01/java/com/lowagie/text/pdf/PdfReaderInstance.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfReaderInstance.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfReaderInstance.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,188 +0,0 @@
-/*
- * $Id: PdfReaderInstance.java,v 1.27 2003/05/02 09:01:27 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.io.*;
-/**
- * Instance of PdfReader in each output document.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-class PdfReaderInstance {
- static final PdfLiteral IDENTITYMATRIX = new PdfLiteral("[1 0 0 1 0 0]");
- static final PdfNumber ONE = new PdfNumber(1);
- int myXref[];
- PdfReader reader;
- RandomAccessFileOrArray file;
- HashMap importedPages = new HashMap();
- PdfWriter writer;
- HashMap visited = new HashMap();
- ArrayList nextRound = new ArrayList();
-
- PdfReaderInstance(PdfReader reader, PdfWriter writer) {
- this.reader = reader;
- this.writer = writer;
- file = reader.getSafeFile();
- myXref = new int[reader.getXrefSize()];
- }
-
- PdfReader getReader() {
- return reader;
- }
-
- PdfImportedPage getImportedPage(int pageNumber) {
- if (pageNumber < 1 || pageNumber > reader.getNumberOfPages())
- throw new IllegalArgumentException("Invalid page number");
- Integer i = new Integer(pageNumber);
- PdfImportedPage pageT = (PdfImportedPage)importedPages.get(i);
- if (pageT == null) {
- pageT = new PdfImportedPage(this, writer, pageNumber);
- importedPages.put(i, pageT);
- }
- return pageT;
- }
-
- int getNewObjectNumber(int number, int generation) {
- if (myXref[number] == 0) {
- myXref[number] = writer.getIndirectReferenceNumber();
- nextRound.add(new Integer(number));
- }
- return myXref[number];
- }
-
- RandomAccessFileOrArray getReaderFile() {
- return file;
- }
-
- PdfObject getResources(int pageNumber) {
- PdfObject obj = PdfReader.getPdfObjectRelease(reader.getPageNRelease(pageNumber).get(PdfName.RESOURCES));
- return obj;
- }
-
-
- PdfStream getFormXObject(int pageNumber) throws IOException {
- PdfDictionary page = reader.getPageNRelease(pageNumber);
- PdfObject contents = PdfReader.getPdfObjectRelease(page.get(PdfName.CONTENTS));
- PdfDictionary dic = new PdfDictionary();
- byte bout[] = null;
- if (contents != null) {
- if (contents.isStream())
- dic.putAll((PRStream)contents);
- else
- bout = reader.getPageContent(pageNumber, file);
- }
- else
- bout = new byte[0];
- dic.put(PdfName.RESOURCES, PdfReader.getPdfObjectRelease(page.get(PdfName.RESOURCES)));
- dic.put(PdfName.TYPE, PdfName.XOBJECT);
- dic.put(PdfName.SUBTYPE, PdfName.FORM);
- PdfImportedPage impPage = (PdfImportedPage)importedPages.get(new Integer(pageNumber));
- dic.put(PdfName.BBOX, new PdfRectangle(impPage.getBoundingBox()));
- PdfArray matrix = impPage.getMatrix();
- if (matrix == null)
- dic.put(PdfName.MATRIX, IDENTITYMATRIX);
- else
- dic.put(PdfName.MATRIX, matrix);
- dic.put(PdfName.FORMTYPE, ONE);
- PRStream stream;
- if (bout == null) {
- stream = new PRStream((PRStream)contents, dic);
- }
- else {
- stream = new PRStream(reader, bout);
- stream.putAll(dic);
- }
- return stream;
- }
-
- void writeAllVisited() throws IOException {
- while (nextRound.size() > 0) {
- ArrayList vec = nextRound;
- nextRound = new ArrayList();
- for (int k = 0; k < vec.size(); ++k) {
- Integer i = (Integer)vec.get(k);
- if (!visited.containsKey(i)) {
- visited.put(i, null);
- int n = i.intValue();
- writer.addToBody(reader.getPdfObjectRelease(n), myXref[n]);
- }
- }
- }
- }
-
- void writeAllPages() throws IOException {
- try {
- file.reOpen();
- for (Iterator it = importedPages.values().iterator(); it.hasNext();) {
- PdfImportedPage ip = (PdfImportedPage)it.next();
- writer.addToBody(ip.getFormXObject(), ip.getIndirectReference());
- }
- writeAllVisited();
- }
- finally {
- try {
- reader.close();
- file.close();
- }
- catch (Exception e) {
- //Empty on purpose
- }
- }
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfRectangle.java pdftk-2.01/java/com/lowagie/text/pdf/PdfRectangle.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfRectangle.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfRectangle.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,283 +0,0 @@
-/*
- * $Id: PdfRectangle.java,v 1.26 2002/07/09 11:28:24 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.Rectangle;
-
-/**
- * PdfRectangle
is the PDF Rectangle object.
- *
- * Rectangles are used to describe locations on the page and bounding boxes for several
- * objects in PDF, such as fonts. A rectangle is represented as an array
of
- * four numbers, specifying the lower lef x , lower left y , upper right x ,
- * and upper right y coordinates of the rectangle, in that order.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 7.1 (page 183).
- *
- * @see com.lowagie.text.Rectangle
- * @see PdfArray
- */
-
-public class PdfRectangle extends PdfArray {
-
- // membervariables
-
-/** lower left x */
- private float llx = 0;
-
-/** lower left y */
- private float lly = 0;
-
-/** upper right x */
- private float urx = 0;
-
-/** upper right y */
- private float ury = 0;
-
- // constructors
-
-/**
- * Constructs a PdfRectangle
-object.
- *
- * @param llx lower left x
- * @param lly lower left y
- * @param urx upper right x
- * @param ury upper right y
- *
- * @since rugPdf0.10
- */
-
- public PdfRectangle(float llx, float lly, float urx, float ury, int rotation) {
- super();
- if (rotation == 90 || rotation == 270) {
- this.llx = lly;
- this.lly = llx;
- this.urx = ury;
- this.ury = urx;
- }
- else {
- this.llx = llx;
- this.lly = lly;
- this.urx = urx;
- this.ury = ury;
- }
- super.add(new PdfNumber(this.llx));
- super.add(new PdfNumber(this.lly));
- super.add(new PdfNumber(this.urx));
- super.add(new PdfNumber(this.ury));
- }
-
- public PdfRectangle(float llx, float lly, float urx, float ury) {
- this(llx, lly, urx, ury, 0);
- }
-
-/**
- * Constructs a PdfRectangle
-object starting from the origin (0, 0).
- *
- * @param urx upper right x
- * @param ury upper right y
- */
-
- public PdfRectangle(float urx, float ury, int rotation) {
- this(0, 0, urx, ury, rotation);
- }
-
- public PdfRectangle(float urx, float ury) {
- this(0, 0, urx, ury, 0);
- }
-
-/**
- * Constructs a PdfRectangle
-object with a Rectangle
-object.
- *
- * @param rectangle a Rectangle
- */
-
- public PdfRectangle(Rectangle rectangle, int rotation) {
- this(rectangle.left(), rectangle.bottom(), rectangle.right(), rectangle.top(), rotation);
- }
-
- public PdfRectangle(Rectangle rectangle) {
- this(rectangle.left(), rectangle.bottom(), rectangle.right(), rectangle.top(), 0);
- }
-
- // methods
-
-/**
- * Overrides the add
-method in PdfArray
in order to prevent the adding of extra object to the array.
- *
- * @param object PdfObject
to add (will not be added here)
- * @return false
- */
-
- public boolean add(PdfObject object) {
- return false;
- }
-
-/**
- * Returns the lower left x-coordinate.
- *
- * @return the lower left x-coordinaat
- */
-
- public float left() {
- return llx;
- }
-
-/**
- * Returns the upper right x-coordinate.
- *
- * @return the upper right x-coordinate
- */
-
- public float right() {
- return urx;
- }
-
-/**
- * Returns the upper right y-coordinate.
- *
- * @return the upper right y-coordinate
- */
-
- public float top() {
- return ury;
- }
-
-/**
- * Returns the lower left y-coordinate.
- *
- * @return the lower left y-coordinate
- */
-
- public float bottom() {
- return lly;
- }
-
-/**
- * Returns the lower left x-coordinate, considering a given margin.
- *
- * @param margin a margin
- * @return the lower left x-coordinate
- */
-
- public float left(int margin) {
- return llx + margin;
- }
-
-/**
- * Returns the upper right x-coordinate, considering a given margin.
- *
- * @param margin a margin
- * @return the upper right x-coordinate
- */
-
- public float right(int margin) {
- return urx - margin;
- }
-
-/**
- * Returns the upper right y-coordinate, considering a given margin.
- *
- * @param margin a margin
- * @return the upper right y-coordinate
- */
-
- public float top(int margin) {
- return ury - margin;
- }
-
-/**
- * Returns the lower left y-coordinate, considering a given margin.
- *
- * @param margin a margin
- * @return the lower left y-coordinate
- */
-
- public float bottom(int margin) {
- return lly + margin;
- }
-
-/**
- * Returns the width of the rectangle.
- *
- * @return a width
- */
-
- public float width() {
- return urx - llx;
- }
-
-/**
- * Returns the height of the rectangle.
- *
- * @return a height
- */
-
- public float height() {
- return ury - lly;
- }
-
-/**
- * Swaps the values of urx and ury and of lly and llx in order to rotate the rectangle.
- *
- * @return a PdfRectangle
- */
-
- public PdfRectangle rotate() {
- return new PdfRectangle(lly, llx, ury, urx, 0);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfRendition.java pdftk-2.01/java/com/lowagie/text/pdf/PdfRendition.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfRendition.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfRendition.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright 2003 Galo Gimenez
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-
-/**
- * A Rendition dictionary (pdf spec 1.5)
- */
-public class PdfRendition extends PdfDictionary {
- PdfRendition(String file, PdfFileSpecification fs, String mimeType) throws IOException{
- put(PdfName.S, new PdfName("MR"));
- put(PdfName.N, new PdfString("Rendition for "+file));
- put(PdfName.C, new PdfMediaClipData(file, fs, mimeType));
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfResources.java pdftk-2.01/java/com/lowagie/text/pdf/PdfResources.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfResources.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfResources.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,97 +0,0 @@
-/*
- * $Id: PdfResources.java,v 1.22 2002/06/20 13:30:25 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- * PdfResources
is the PDF Resources-object.
- *
- * The marking operations for drawing a page are stored in a stream that is the value of the
- * Contents key in the Page object's dictionary. Each marking context includes a list
- * of the named resources it uses. This resource list is stored as a dictionary that is the
- * value of the context's Resources key, and it serves two functions: it enumerates
- * the named resources in the contents stream, and it established the mapping from the names
- * to the objects used by the marking operations.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 7.5 (page 195-197).
- *
- * @see PdfPage
- */
-
-class PdfResources extends PdfDictionary {
-
- // constructor
-
-/**
- * Constructs a PDF ResourcesDictionary.
- */
-
- PdfResources() {
- super();
- }
-
- // methods
-
- void add(PdfName key, PdfDictionary resource) {
- if (resource.size() == 0)
- return;
- PdfDictionary dic = (PdfDictionary)PdfReader.getPdfObject(get(key));
- if (dic == null)
- put(key, resource);
- else
- dic.putAll(resource);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfShading.java pdftk-2.01/java/com/lowagie/text/pdf/PdfShading.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfShading.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfShading.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,268 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * Copyright 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.awt.Color;
-import java.io.IOException;
-/** Implements the shading dictionary (or stream).
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfShading {
-
- protected PdfDictionary shading;
-
- protected PdfWriter writer;
-
- protected int shadingType;
-
- protected ColorDetails colorDetails;
-
- protected PdfName shadingName;
-
- protected PdfIndirectReference shadingReference;
-
- private Color cspace;
-
- /** Holds value of property bBox. */
- protected float[] bBox;
-
- /** Holds value of property antiAlias. */
- protected boolean antiAlias = false;
-
- /** Creates new PdfShading */
- protected PdfShading(PdfWriter writer) {
- this.writer = writer;
- }
-
- protected void setColorSpace(Color color) {
- cspace = color;
- int type = ExtendedColor.getType(color);
- PdfObject colorSpace = null;
- switch (type) {
- case ExtendedColor.TYPE_GRAY: {
- colorSpace = PdfName.DEVICEGRAY;
- break;
- }
- case ExtendedColor.TYPE_CMYK: {
- colorSpace = PdfName.DEVICECMYK;
- break;
- }
- case ExtendedColor.TYPE_SEPARATION: {
- SpotColor spot = (SpotColor)color;
- colorDetails = writer.addSimple(spot.getPdfSpotColor());
- colorSpace = colorDetails.getIndirectReference();
- break;
- }
- case ExtendedColor.TYPE_PATTERN:
- case ExtendedColor.TYPE_SHADING: {
- throwColorSpaceError();
- }
- default:
- colorSpace = PdfName.DEVICERGB;
- break;
- }
- shading.put(PdfName.COLORSPACE, colorSpace);
- }
-
- Color getColorSpace() {
- return cspace;
- }
-
- public static void throwColorSpaceError() {
- throw new IllegalArgumentException("A tiling or shading pattern cannot be used as a color space in a shading pattern");
- }
-
- public static void checkCompatibleColors(Color c1, Color c2) {
- int type1 = ExtendedColor.getType(c1);
- int type2 = ExtendedColor.getType(c2);
- if (type1 != type2)
- throw new IllegalArgumentException("Both colors must be of the same type.");
- if (type1 == ExtendedColor.TYPE_SEPARATION && ((SpotColor)c1).getPdfSpotColor() != ((SpotColor)c2).getPdfSpotColor())
- throw new IllegalArgumentException("The spot color must be the same, only the tint can vary.");
- if (type1 == ExtendedColor.TYPE_PATTERN || type1 == ExtendedColor.TYPE_SHADING)
- throwColorSpaceError();
- }
-
- public static float[] getColorArray(Color color) {
- int type = ExtendedColor.getType(color);
- switch (type) {
- case ExtendedColor.TYPE_GRAY: {
- return new float[]{((GrayColor)color).getGray()};
- }
- case ExtendedColor.TYPE_CMYK: {
- CMYKColor cmyk = (CMYKColor)color;
- return new float[]{cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack()};
- }
- case ExtendedColor.TYPE_SEPARATION: {
- return new float[]{((SpotColor)color).getTint()};
- }
- case ExtendedColor.TYPE_RGB: {
- return new float[]{color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f};
- }
- }
- throwColorSpaceError();
- return null;
- }
-
- public static PdfShading type1(PdfWriter writer, Color colorSpace, float domain[], float tMatrix[], PdfFunction function) {
- PdfShading sp = new PdfShading(writer);
- sp.shading = new PdfDictionary();
- sp.shadingType = 1;
- sp.shading.put(PdfName.SHADINGTYPE, new PdfNumber(sp.shadingType));
- sp.setColorSpace(colorSpace);
- if (domain != null)
- sp.shading.put(PdfName.m_DOMAIN, new PdfArray(domain)); // ssteward
- if (tMatrix != null)
- sp.shading.put(PdfName.MATRIX, new PdfArray(tMatrix));
- sp.shading.put(PdfName.FUNCTION, function.getReference());
- return sp;
- }
-
- public static PdfShading type2(PdfWriter writer, Color colorSpace, float coords[], float domain[], PdfFunction function, boolean extend[]) {
- PdfShading sp = new PdfShading(writer);
- sp.shading = new PdfDictionary();
- sp.shadingType = 2;
- sp.shading.put(PdfName.SHADINGTYPE, new PdfNumber(sp.shadingType));
- sp.setColorSpace(colorSpace);
- sp.shading.put(PdfName.COORDS, new PdfArray(coords));
- if (domain != null)
- sp.shading.put(PdfName.m_DOMAIN, new PdfArray(domain)); // ssteward
- sp.shading.put(PdfName.FUNCTION, function.getReference());
- if (extend != null && (extend[0] || extend[1])) {
- PdfArray array = new PdfArray(extend[0] ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
- array.add(extend[1] ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
- sp.shading.put(PdfName.EXTEND, array);
- }
- return sp;
- }
-
- public static PdfShading type3(PdfWriter writer, Color colorSpace, float coords[], float domain[], PdfFunction function, boolean extend[]) {
- PdfShading sp = type2(writer, colorSpace, coords, domain, function, extend);
- sp.shadingType = 3;
- sp.shading.put(PdfName.SHADINGTYPE, new PdfNumber(sp.shadingType));
- return sp;
- }
-
- public static PdfShading simpleAxial(PdfWriter writer, float x0, float y0, float x1, float y1, Color startColor, Color endColor, boolean extendStart, boolean extendEnd) {
- checkCompatibleColors(startColor, endColor);
- PdfFunction function = PdfFunction.type2(writer, new float[]{0, 1}, null, getColorArray(startColor),
- getColorArray(endColor), 1);
- return type2(writer, startColor, new float[]{x0, y0, x1, y1}, null, function, new boolean[]{extendStart, extendEnd});
- }
-
- public static PdfShading simpleAxial(PdfWriter writer, float x0, float y0, float x1, float y1, Color startColor, Color endColor) {
- return simpleAxial(writer, x0, y0, x1, y1, startColor, endColor, true, true);
- }
-
- public static PdfShading simpleRadial(PdfWriter writer, float x0, float y0, float r0, float x1, float y1, float r1, Color startColor, Color endColor, boolean extendStart, boolean extendEnd) {
- checkCompatibleColors(startColor, endColor);
- PdfFunction function = PdfFunction.type2(writer, new float[]{0, 1}, null, getColorArray(startColor),
- getColorArray(endColor), 1);
- return type3(writer, startColor, new float[]{x0, y0, r0, x1, y1, r1}, null, function, new boolean[]{extendStart, extendEnd});
- }
-
- public static PdfShading simpleRadial(PdfWriter writer, float x0, float y0, float r0, float x1, float y1, float r1, Color startColor, Color endColor) {
- return simpleRadial(writer, x0, y0, r0, x1, y1, r1, startColor, endColor, true, true);
- }
-
- PdfName getShadingName() {
- return shadingName;
- }
-
- PdfIndirectReference getShadingReference() {
- if (shadingReference == null)
- shadingReference = writer.getPdfIndirectReference();
- return shadingReference;
- }
-
- void setName(int number) {
- shadingName = new PdfName("Sh" + number);
- }
-
- void addToBody() throws IOException {
- if (bBox != null)
- shading.put(PdfName.BBOX, new PdfArray(bBox));
- if (antiAlias)
- shading.put(PdfName.ANTIALIAS, PdfBoolean.PDFTRUE);
- writer.addToBody(shading, getShadingReference());
- }
-
- PdfWriter getWriter() {
- return writer;
- }
-
- ColorDetails getColorDetails() {
- return colorDetails;
- }
-
- public float[] getBBox() {
- return bBox;
- }
-
- public void setBBox(float[] bBox) {
- if (bBox.length != 4)
- throw new IllegalArgumentException("BBox must be a 4 element array.");
- this.bBox = bBox;
- }
-
- public boolean isAntiAlias() {
- return antiAlias;
- }
-
- public void setAntiAlias(boolean antiAlias) {
- this.antiAlias = antiAlias;
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfShadingPattern.java pdftk-2.01/java/com/lowagie/text/pdf/PdfShadingPattern.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfShadingPattern.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfShadingPattern.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-/** Implements the shading pattern dictionary.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfShadingPattern extends PdfDictionary {
-
- protected PdfShading shading;
-
- protected PdfWriter writer;
-
- protected float matrix[] = {1, 0, 0, 1, 0, 0};
-
- protected PdfName patternName;
-
- protected PdfIndirectReference patternReference;
-
- /** Creates new PdfShadingPattern */
- public PdfShadingPattern(PdfShading shading) {
- writer = shading.getWriter();
- put(PdfName.PATTERNTYPE, new PdfNumber(2));
- this.shading = shading;
- }
-
- PdfName getPatternName() {
- return patternName;
- }
-
- PdfName getShadingName() {
- return shading.getShadingName();
- }
-
- PdfIndirectReference getPatternReference() {
- if (patternReference == null)
- patternReference = writer.getPdfIndirectReference();
- return patternReference;
- }
-
- PdfIndirectReference getShadingReference() {
- return shading.getShadingReference();
- }
-
- void setName(int number) {
- patternName = new PdfName("P" + number);
- }
-
- void addToBody() throws IOException {
- put(PdfName.SHADING, getShadingReference());
- put(PdfName.MATRIX, new PdfArray(matrix));
- writer.addToBody(this, getPatternReference());
- }
-
- public void setMatrix(float matrix[]) {
- if (matrix.length != 6)
- throw new RuntimeException("The matrix size must be 6.");
- this.matrix = matrix;
- }
-
- public float[] getMatrix() {
- return matrix;
- }
-
- PdfShading getShading() {
- return shading;
- }
-
- ColorDetails getColorDetails() {
- return shading.getColorDetails();
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfSigGenericPKCS.java pdftk-2.01/java/com/lowagie/text/pdf/PdfSigGenericPKCS.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfSigGenericPKCS.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfSigGenericPKCS.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,236 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.security.cert.Certificate;
-import java.security.cert.CRL;
-import java.security.PrivateKey;
-import com.lowagie.text.ExceptionConverter;
-import java.io.ByteArrayOutputStream;
-
-/**
- * A signature dictionary representation for the standard filters.
- */
-public abstract class PdfSigGenericPKCS extends PdfSignature {
- /**
- * The hash algorith, for example "SHA1"
- */
- protected String hashAlgorithm;
- /**
- * The crypto provider
- */
- protected String provider = null;
- /**
- * The class instance that calculates the PKCS#1 and PKCS#7
- */
- protected PdfPKCS7 pkcs;
- /**
- * The subject name in the signing certificate (the element "CN")
- */
- protected String name;
-
- private byte externalDigest[];
- private byte externalRSAdata[];
- private String digestEncryptionAlgorithm;
-
- /**
- * Creates a generic standard filter.
- * @param filter the filter name
- * @param subFilter the sub-filter name
- */
- public PdfSigGenericPKCS(PdfName filter, PdfName subFilter) {
- super(filter, subFilter);
- }
-
- /**
- * Sets the crypto information to sign.
- * @param privKey the private key
- * @param certChain the certificate chain
- * @param crlList the certificate revocation list. It can be null
- */
- public void setSignInfo(PrivateKey privKey, Certificate[] certChain, CRL[] crlList) {
- try {
- pkcs = new PdfPKCS7(privKey, certChain, crlList, hashAlgorithm, provider, PdfName.ADBE_PKCS7_SHA1.equals(get(PdfName.SUBFILTER)));
- pkcs.setExternalDigest(externalDigest, externalRSAdata, digestEncryptionAlgorithm);
- if (PdfName.ADBE_X509_RSA_SHA1.equals(get(PdfName.SUBFILTER))) {
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- for (int k = 0; k < certChain.length; ++k) {
- bout.write(certChain[k].getEncoded());
- }
- bout.close();
- setCert(bout.toByteArray());
- setContents(pkcs.getEncodedPKCS1());
- }
- else
- setContents(pkcs.getEncodedPKCS7());
- name = PdfPKCS7.getSubjectFields(pkcs.getSigningCertificate()).getField("CN");
- if (name != null)
- put(PdfName.NAME, new PdfString(name, PdfObject.TEXT_UNICODE));
- pkcs = new PdfPKCS7(privKey, certChain, crlList, hashAlgorithm, provider, PdfName.ADBE_PKCS7_SHA1.equals(get(PdfName.SUBFILTER)));
- pkcs.setExternalDigest(externalDigest, externalRSAdata, digestEncryptionAlgorithm);
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Sets the digest/signature to an external calculated value.
- * @param digest the digest. This is the actual signature
- * @param RSAdata the extra data that goes into the data tag in PKCS#7
- * @param digestEncryptionAlgorithm the encryption algorithm. It may must be null
if the digest
- * is also null
. If the digest
is not null
- * then it may be "RSA" or "DSA"
- */
- public void setExternalDigest(byte digest[], byte RSAdata[], String digestEncryptionAlgorithm) {
- externalDigest = digest;
- externalRSAdata = RSAdata;
- this.digestEncryptionAlgorithm = digestEncryptionAlgorithm;
- }
-
- /**
- * Gets the subject name in the signing certificate (the element "CN")
- * @return the subject name in the signing certificate (the element "CN")
- */
- public String getName() {
- return name;
- }
-
- /**
- * Gets the class instance that does the actual signing.
- * @return the class instance that does the actual signing
- */
- public PdfPKCS7 getSigner() {
- return pkcs;
- }
-
- /**
- * Gets the signature content. This can be a PKCS#1 or a PKCS#7. It corresponds to
- * the /Contents key.
- * @return the signature content
- */
- public byte[] getSignerContents() {
- if (PdfName.ADBE_X509_RSA_SHA1.equals(get(PdfName.SUBFILTER)))
- return pkcs.getEncodedPKCS1();
- else
- return pkcs.getEncodedPKCS7();
- }
-
- /**
- * Creates a standard filter of the type VeriSign.
- */
- public static class VeriSign extends PdfSigGenericPKCS {
- /**
- * The constructor for the default provider.
- */
- public VeriSign() {
- super(PdfName.VERISIGN_PPKVS, PdfName.ADBE_PKCS7_DETACHED);
- hashAlgorithm = "MD5";
- put(PdfName.R, new PdfNumber(65537));
- }
-
- /**
- * The constructor for an explicit provider.
- * @param provider the crypto provider
- */
- public VeriSign(String provider) {
- this();
- this.provider = provider;
- }
- }
-
- /**
- * Creates a standard filter of the type self signed.
- */
- public static class PPKLite extends PdfSigGenericPKCS {
- /**
- * The constructor for the default provider.
- */
- public PPKLite() {
- super(PdfName.ADOBE_PPKLITE, PdfName.ADBE_X509_RSA_SHA1);
- hashAlgorithm = "SHA1";
- put(PdfName.R, new PdfNumber(65541));
- }
-
- /**
- * The constructor for an explicit provider.
- * @param provider the crypto provider
- */
- public PPKLite(String provider) {
- this();
- this.provider = provider;
- }
- }
-
- /**
- * Creates a standard filter of the type Windows Certificate.
- */
- public static class PPKMS extends PdfSigGenericPKCS {
- /**
- * The constructor for the default provider.
- */
- public PPKMS() {
- super(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_SHA1);
- hashAlgorithm = "SHA1";
- }
-
- /**
- * The constructor for an explicit provider.
- * @param provider the crypto provider
- */
- public PPKMS(String provider) {
- this();
- this.provider = provider;
- }
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfSignature.java pdftk-2.01/java/com/lowagie/text/pdf/PdfSignature.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfSignature.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfSignature.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/** Implements the signature dictionary.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfSignature extends PdfDictionary {
-
- /** Creates new PdfSignature */
- public PdfSignature(PdfName filter, PdfName subFilter) {
- super(PdfName.SIG);
- put(PdfName.FILTER, filter);
- put(PdfName.SUBFILTER, subFilter);
- }
-
- public void setByteRange(int range[]) {
- PdfArray array = new PdfArray();
- for (int k = 0; k < range.length; ++k)
- array.add(new PdfNumber(range[k]));
- put(PdfName.BYTERANGE, array);
- }
-
- public void setContents(byte contents[]) {
- put(PdfName.CONTENTS, new PdfString(contents, PdfObject.NOTHING).setHexWriting(true)); // ssteward: added encoding
- }
-
- public void setCert(byte cert[]) {
- put(PdfName.CERT, new PdfString(cert, PdfObject.NOTHING)); // ssteward: added encoding
- }
-
- public void setName(String name) {
- put(PdfName.NAME, new PdfString(name, PdfObject.TEXT_UNICODE));
- }
-
- public void setDate(PdfDate date) {
- put(PdfName.M, date);
- }
-
- public void setLocation(String name) {
- put(PdfName.LOCATION, new PdfString(name, PdfObject.TEXT_UNICODE));
- }
-
- public void setReason(String name) {
- put(PdfName.REASON, new PdfString(name, PdfObject.TEXT_UNICODE));
- }
-
- public void setContact(String name) {
- put(PdfName.CONTACTINFO, new PdfString(name, PdfObject.TEXT_UNICODE));
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfSignatureAppearance.java pdftk-2.01/java/com/lowagie/text/pdf/PdfSignatureAppearance.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfSignatureAppearance.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfSignatureAppearance.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,1303 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.Rectangle;
-import com.lowagie.text.ExceptionConverter;
-import com.lowagie.text.Phrase;
-import com.lowagie.text.Font;
-import com.lowagie.text.Element;
-// import com.lowagie.text.Image; ssteward: dropped in 1.44
-import com.lowagie.text.DocumentException;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Iterator;
-import java.text.SimpleDateFormat;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-import java.security.cert.CRL;
-import java.security.PrivateKey;
-import java.io.OutputStream;
-import java.io.IOException;
-import java.io.EOFException;
-import java.io.RandomAccessFile;
-import java.io.File;
-import java.io.InputStream;
-
-/**
- * This class takes care of the cryptographic options and appearances that form a signature.
- */
-public class PdfSignatureAppearance {
-
- /**
- * The self signed filter.
- */
- public static final PdfName SELF_SIGNED = PdfName.ADOBE_PPKLITE;
- /**
- * The VeriSign filter.
- */
- public static final PdfName VERISIGN_SIGNED = PdfName.VERISIGN_PPKVS;
- /**
- * The Windows Certificate Security.
- */
- public static final PdfName WINCER_SIGNED = PdfName.ADOBE_PPKMS;
-
- private static final float topSection = 0.3f;
- private static final float margin = 2;
- private Rectangle rect;
- private Rectangle pageRect;
- private PdfTemplate app[] = new PdfTemplate[5];
- private PdfTemplate frm;
- private PdfStamperImp writer;
- private String layer2Text;
- private String reason;
- private String location;
- private Calendar signDate;
- private String provider;
- private int page = 1;
- private String fieldName;
- private PrivateKey privKey;
- private Certificate[] certChain;
- private CRL[] crlList;
- private PdfName filter;
- private boolean newField;
- private ByteBuffer sigout;
- private OutputStream originalout;
- private File tempFile;
- private PdfDictionary cryptoDictionary;
- private PdfStamper stamper;
- private boolean preClosed = false;
- private PdfSigGenericPKCS sigStandard;
- private int range[];
- private RandomAccessFile raf;
- private int rangePosition = 0;
- private byte bout[];
- private int boutLen;
- private byte externalDigest[];
- private byte externalRSAdata[];
- private String digestEncryptionAlgorithm;
- private HashMap exclusionLocations;
-
- PdfSignatureAppearance(PdfStamperImp writer) {
- this.writer = writer;
- signDate = new GregorianCalendar();
- fieldName = getNewSigName();
- }
-
- /**
- * Sets the signature text identifying the signer.
- * @param text the signature text identifying the signer. If null
or not set
- * a standard description will be used
- */
- public void setLayer2Text(String text) {
- layer2Text = text;
- }
-
- /**
- * Gets the signature text identifying the signer if set by setLayer2Text().
- * @return the signature text identifying the signer
- */
- public String getLayer2Text() {
- return layer2Text;
- }
-
- /**
- * Sets the text identifying the signature status.
- * @param text the text identifying the signature status. If null
or not set
- * the description "Signature Not Verified" will be used
- */
- public void setLayer4Text(String text) {
- layer4Text = text;
- }
-
- /**
- * Gets the text identifying the signature status if set by setLayer4Text().
- * @return the text identifying the signature status
- */
- public String getLayer4Text() {
- return layer4Text;
- }
-
- /**
- * Gets the rectangle representing the signature dimensions.
- * @return the rectangle representing the signature dimensions. It may be null
- * or have zero width or height for invisible signatures
- */
- public Rectangle getRect() {
- return rect;
- }
-
- /**
- * Gets the visibility status of the signature.
- * @return the visibility status of the signature
- */
- public boolean isInvisible() {
- return (rect == null || rect.width() == 0 || rect.height() == 0);
- }
-
- /**
- * Sets the cryptographic parameters.
- * @param privKey the private key
- * @param certChain the certificate chain
- * @param crlList the certificate revocation list. It may be null
- * @param filter the crytographic filter type. It can be SELF_SIGNED, VERISIGN_SIGNED or WINCER_SIGNED
- */
- public void setCrypto(PrivateKey privKey, Certificate[] certChain, CRL[] crlList, PdfName filter) {
- this.privKey = privKey;
- this.certChain = certChain;
- this.crlList = crlList;
- this.filter = filter;
- }
-
- /**
- * Sets the signature to be visible. It creates a new visible signature field.
- * @param pageRect the position and dimension of the field in the page
- * @param page the page to place the field. The fist page is 1
- * @param fieldName the field name or null
to generate automatically a new field name
- */
- public void setVisibleSignature(Rectangle pageRect, int page, String fieldName) {
- if (fieldName != null) {
- AcroFields af = writer.getAcroFields();
- AcroFields.Item item = af.getFieldItem(fieldName);
- if (item != null)
- throw new IllegalArgumentException("The field " + fieldName + " already exists.");
- this.fieldName = fieldName;
- }
- if (page < 1 || page > writer.reader.getNumberOfPages())
- throw new IllegalArgumentException("Invalid page number: " + page);
- this.pageRect = new Rectangle(pageRect);
- this.pageRect.normalize();
- rect = new Rectangle(this.pageRect.width(), this.pageRect.height());
- this.page = page;
- newField = true;
- }
-
- /**
- * Sets the signature to be visible. An empty signature field with the same name must already exist.
- * @param fieldName the existing empty signature field name
- */
- public void setVisibleSignature(String fieldName) {
- AcroFields af = writer.getAcroFields();
- AcroFields.Item item = af.getFieldItem(fieldName);
- if (item == null)
- throw new IllegalArgumentException("The field " + fieldName + " does not exist.");
- PdfDictionary merged = (PdfDictionary)item.merged.get(0);
- if (!PdfName.SIG.equals(PdfReader.getPdfObject(merged.get(PdfName.FT))))
- throw new IllegalArgumentException("The field " + fieldName + " is not a signature field.");
- this.fieldName = fieldName;
- PdfArray r = (PdfArray)PdfReader.getPdfObject(merged.get(PdfName.RECT));
- ArrayList ar = r.getArrayList();
- float llx = ((PdfNumber)PdfReader.getPdfObject((PdfObject)ar.get(0))).floatValue();
- float lly = ((PdfNumber)PdfReader.getPdfObject((PdfObject)ar.get(1))).floatValue();
- float urx = ((PdfNumber)PdfReader.getPdfObject((PdfObject)ar.get(2))).floatValue();
- float ury = ((PdfNumber)PdfReader.getPdfObject((PdfObject)ar.get(3))).floatValue();
- pageRect = new Rectangle(llx, lly, urx, ury);
- pageRect.normalize();
- page = ((Integer)item.page.get(0)).intValue();
- int rotation = writer.reader.getPageRotation(page);
- Rectangle pageSize = writer.reader.getPageSizeWithRotation(page);
- switch (rotation) {
- case 90:
- pageRect = new Rectangle(
- pageRect.bottom(),
- pageSize.top() - pageRect.left(),
- pageRect.top(),
- pageSize.top() - pageRect.right());
- break;
- case 180:
- pageRect = new Rectangle(
- pageSize.right() - pageRect.left(),
- pageSize.top() - pageRect.bottom(),
- pageSize.right() - pageRect.right(),
- pageSize.top() - pageRect.top());
- break;
- case 270:
- pageRect = new Rectangle(
- pageSize.right() - pageRect.bottom(),
- pageRect.left(),
- pageSize.right() - pageRect.top(),
- pageRect.right());
- break;
- }
- if (rotation != 0)
- pageRect.normalize();
- rect = new Rectangle(this.pageRect.width(), this.pageRect.height());
- }
-
- /**
- * Gets a template layer to create a signature appearance. The layers can go from 0 to 4.
- *
- * Consult PPKAppearances.pdf
- * for further details.
- * @param layer the layer
- * @return a template
- */
- public PdfTemplate getLayer(int layer) {
- if (layer < 0 || layer >= app.length)
- return null;
- PdfTemplate t = app[layer];
- if (t == null) {
- t = app[layer] = new PdfTemplate(writer);
- t.setBoundingBox(rect);
- writer.addDirectTemplateSimple(t, new PdfName("n" + layer));
- }
- return t;
- }
-
- /**
- * Gets the template that aggregates all appearance layers. This corresponds to the /FRM resource.
- *
- * Consult PPKAppearances.pdf
- * for further details.
- * @return the template that aggregates all appearance layers
- */
- public PdfTemplate getTopLayer() {
- if (frm == null) {
- frm = new PdfTemplate(writer);
- frm.setBoundingBox(rect);
- writer.addDirectTemplateSimple(frm, new PdfName("FRM"));
- }
- return frm;
- }
-
- /**
- * Gets the main appearance layer.
- *
- * Consult PPKAppearances.pdf
- * for further details.
- * @return the main appearance layer
- * @throws DocumentException on error
- * @throws IOException on error
- */
- public PdfTemplate getAppearance() throws DocumentException, IOException {
- if (app[0] == null) {
- PdfTemplate t = app[0] = new PdfTemplate(writer);
- t.setBoundingBox(new Rectangle(100, 100));
- writer.addDirectTemplateSimple(t, new PdfName("n0"));
- t.setLiteral("% DSBlank\n");
- }
- if (app[1] == null && !acro6Layers) {
- PdfTemplate t = app[1] = new PdfTemplate(writer);
- t.setBoundingBox(new Rectangle(100, 100));
- writer.addDirectTemplateSimple(t, new PdfName("n1"));
- t.setLiteral(questionMark);
- }
- if (app[2] == null) {
- String text;
- if (layer2Text == null) {
- StringBuffer buf = new StringBuffer();
- buf.append("Digitally signed by ").append(PdfPKCS7.getSubjectFields((X509Certificate)certChain[0]).getField("CN")).append("\n");
- SimpleDateFormat sd = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
- buf.append("Date: ").append(sd.format(signDate.getTime()));
- if (reason != null)
- buf.append("\n").append("Reason: ").append(reason);
- if (location != null)
- buf.append("\n").append("Location: ").append(location);
- text = buf.toString();
- }
- else
- text = layer2Text;
- PdfTemplate t = app[2] = new PdfTemplate(writer);
- t.setBoundingBox(rect);
- writer.addDirectTemplateSimple(t, new PdfName("n2"));
- /* ssteward: dropped in 1.44
- if (image != null) {
- if (imageScale == 0) {
- t.addImage(image, rect.width(), 0, 0, rect.height(), 0, 0);
- }
- else {
- float usableScale = imageScale;
- if (imageScale < 0)
- usableScale = Math.min(rect.width() / image.width(), rect.height() / image.height());
- float w = image.width() * usableScale;
- float h = image.height() * usableScale;
- float x = (rect.width() - w) / 2;
- float y = (rect.height() - h) / 2;
- t.addImage(image, w, 0, 0, h, x, y);
- }
- }
- */
- Font font;
- if (layer2Font == null)
- font = new Font();
- else
- font = new Font(layer2Font);
- float size = font.size();
- if (size <= 0) {
- Rectangle sr = new Rectangle(rect.width() - 2 * margin, rect.height() * (1 - topSection) - 2 * margin);
- size = fitText(font, text, sr, 12, runDirection);
- }
- ColumnText ct = new ColumnText(t);
- ct.setRunDirection(runDirection);
- ct.setSimpleColumn(new Phrase(text, font), margin, 0, rect.width() - margin, rect.height() * (1 - topSection) - margin, size, Element.ALIGN_LEFT);
- ct.go();
- }
- if (app[3] == null && !acro6Layers) {
- PdfTemplate t = app[3] = new PdfTemplate(writer);
- t.setBoundingBox(new Rectangle(100, 100));
- writer.addDirectTemplateSimple(t, new PdfName("n3"));
- t.setLiteral("% DSBlank\n");
- }
- if (app[4] == null && !acro6Layers) {
- PdfTemplate t = app[4] = new PdfTemplate(writer);
- t.setBoundingBox(new Rectangle(0, rect.height() * (1 - topSection), rect.right(), rect.top()));
- writer.addDirectTemplateSimple(t, new PdfName("n4"));
- Font font;
- if (layer2Font == null)
- font = new Font();
- else
- font = new Font(layer2Font);
- float size = font.size();
- String text = "Signature Not Verified";
- if (layer4Text != null)
- text = layer4Text;
- Rectangle sr = new Rectangle(rect.width() - 2 * margin, rect.height() * topSection - 2 * margin);
- size = fitText(font, text, sr, 15, runDirection);
- ColumnText ct = new ColumnText(t);
- ct.setRunDirection(runDirection);
- ct.setSimpleColumn(new Phrase(text, font), margin, 0, rect.width() - margin, rect.height() - margin, size, Element.ALIGN_LEFT);
- ct.go();
- }
- int rotation = writer.reader.getPageRotation(page);
- Rectangle rotated = new Rectangle(rect);
- int n = rotation;
- while (n > 0) {
- rotated = rotated.rotate();
- n -= 90;
- }
- if (frm == null) {
- frm = new PdfTemplate(writer);
- frm.setBoundingBox(rotated);
- writer.addDirectTemplateSimple(frm, new PdfName("FRM"));
- float scale = Math.min(rect.width(), rect.height()) * 0.9f;
- float x = (rect.width() - scale) / 2;
- float y = (rect.height() - scale) / 2;
- scale /= 100;
- if (rotation == 90)
- frm.concatCTM(0, 1, -1, 0, rect.height(), 0);
- else if (rotation == 180)
- frm.concatCTM(-1, 0, 0, -1, rect.width(), rect.height());
- else if (rotation == 270)
- frm.concatCTM(0, -1, 1, 0, 0, rect.width());
- frm.addTemplate(app[0], 0, 0);
- if (!acro6Layers)
- frm.addTemplate(app[1], scale, 0, 0, scale, x, y);
- frm.addTemplate(app[2], 0, 0);
- if (!acro6Layers) {
- frm.addTemplate(app[3], scale, 0, 0, scale, x, y);
- frm.addTemplate(app[4], 0, 0);
- }
- }
- PdfTemplate napp = new PdfTemplate(writer);
- napp.setBoundingBox(rotated);
- writer.addDirectTemplateSimple(napp, null);
- napp.addTemplate(frm, 0, 0);
- return napp;
- }
-
- /**
- * Fits the text to some rectangle adjusting the font size as needed.
- * @param font the font to use
- * @param text the text
- * @param rect the rectangle where the text must fit
- * @param maxFontSize the maximum font size
- * @param runDirection the run direction
- * @return the calculated font size that makes the text fit
- */
- public static float fitText(Font font, String text, Rectangle rect, float maxFontSize, int runDirection) {
- try {
- ColumnText ct = null;
- int status = 0;
- if (maxFontSize <= 0) {
- int cr = 0;
- int lf = 0;
- char t[] = text.toCharArray();
- for (int k = 0; k < t.length; ++k) {
- if (t[k] == '\n')
- ++lf;
- else if (t[k] == '\r')
- ++cr;
- }
- int minLines = Math.max(cr, lf) + 1;
- maxFontSize = Math.abs(rect.height()) / minLines - 0.001f;
- }
- font.setSize(maxFontSize);
- Phrase ph = new Phrase(text, font);
- ct = new ColumnText(null);
- ct.setSimpleColumn(ph, rect.left(), rect.bottom(), rect.right(), rect.top(), maxFontSize, Element.ALIGN_LEFT);
- ct.setRunDirection(runDirection);
- status = ct.go(true);
- if ((status & ColumnText.NO_MORE_TEXT) != 0)
- return maxFontSize;
- float precision = 0.1f;
- float min = 0;
- float max = maxFontSize;
- float size = maxFontSize;
- for (int k = 0; k < 50; ++k) { //just in case it doesn't converge
- size = (min + max) / 2;
- ct = new ColumnText(null);
- font.setSize(size);
- ct.setSimpleColumn(new Phrase(text, font), rect.left(), rect.bottom(), rect.right(), rect.top(), size, Element.ALIGN_LEFT);
- ct.setRunDirection(runDirection);
- status = ct.go(true);
- if ((status & ColumnText.NO_MORE_TEXT) != 0) {
- if (max - min < size * precision)
- return size;
- min = size;
- }
- else
- max = size;
- }
- return size;
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Sets the digest/signature to an external calculated value.
- * @param digest the digest. This is the actual signature
- * @param RSAdata the extra data that goes into the data tag in PKCS#7
- * @param digestEncryptionAlgorithm the encryption algorithm. It may must be null
if the digest
- * is also null
. If the digest
is not null
- * then it may be "RSA" or "DSA"
- */
- public void setExternalDigest(byte digest[], byte RSAdata[], String digestEncryptionAlgorithm) {
- externalDigest = digest;
- externalRSAdata = RSAdata;
- this.digestEncryptionAlgorithm = digestEncryptionAlgorithm;
- }
-
- /**
- * Gets the signing reason.
- * @return the signing reason
- */
- public String getReason() {
- return this.reason;
- }
-
- /**
- * Sets the signing reason.
- * @param reason the signing reason
- */
- public void setReason(String reason) {
- this.reason = reason;
- }
-
- /**
- * Gets the signing location.
- * @return the signing location
- */
- public String getLocation() {
- return this.location;
- }
-
- /**
- * Sets the signing location.
- * @param location the signing location
- */
- public void setLocation(String location) {
- this.location = location;
- }
-
- /**
- * Returns the Cryptographic Service Provider that will sign the document.
- * @return provider the name of the provider, for example "SUN",
- * or null
to use the default provider.
- */
- public String getProvider() {
- return this.provider;
- }
-
- /**
- * Sets the Cryptographic Service Provider that will sign the document.
- *
- * @param provider the name of the provider, for example "SUN", or
- * null
to use the default provider.
- */
- public void setProvider(String provider) {
- this.provider = provider;
- }
-
- /**
- * Gets the private key.
- * @return the private key
- */
- public java.security.PrivateKey getPrivKey() {
- return privKey;
- }
-
- /**
- * Gets the certificate chain.
- * @return the certificate chain
- */
- public java.security.cert.Certificate[] getCertChain() {
- return this.certChain;
- }
-
- /**
- * Gets the certificate revocation list.
- * @return the certificate revocation list
- */
- public java.security.cert.CRL[] getCrlList() {
- return this.crlList;
- }
-
- /**
- * Gets the filter used to sign the document.
- * @return the filter used to sign the document
- */
- public com.lowagie.text.pdf.PdfName getFilter() {
- return filter;
- }
-
- /**
- * Checks if a new field was created.
- * @return true
if a new field was created, false
if signing
- * an existing field or if the signature is invisible
- */
- public boolean isNewField() {
- return this.newField;
- }
-
- /**
- * Gets the page number of the field.
- * @return the page number of the field
- */
- public int getPage() {
- return page;
- }
-
- /**
- * Gets the field name.
- * @return the field name
- */
- public java.lang.String getFieldName() {
- return fieldName;
- }
-
- /**
- * Gets the rectangle that represent the position and dimension of the signature in the page.
- * @return the rectangle that represent the position and dimension of the signature in the page
- */
- public com.lowagie.text.Rectangle getPageRect() {
- return pageRect;
- }
-
- /**
- * Gets the signature date.
- * @return the signature date
- */
- public java.util.Calendar getSignDate() {
- return signDate;
- }
-
- /**
- * Sets the signature date.
- * @param signDate the signature date
- */
- public void setSignDate(java.util.Calendar signDate) {
- this.signDate = signDate;
- }
-
- com.lowagie.text.pdf.ByteBuffer getSigout() {
- return sigout;
- }
-
- void setSigout(com.lowagie.text.pdf.ByteBuffer sigout) {
- this.sigout = sigout;
- }
-
- java.io.OutputStream getOriginalout() {
- return originalout;
- }
-
- void setOriginalout(java.io.OutputStream originalout) {
- this.originalout = originalout;
- }
-
- /**
- * Gets the temporary file.
- * @return the temporary file or null
is the document is created in memory
- */
- public java.io.File getTempFile() {
- return tempFile;
- }
-
- void setTempFile(java.io.File tempFile) {
- this.tempFile = tempFile;
- }
-
- /**
- * Gets a new signature fied name that doesn't clash with any existing name.
- * @return a new signature fied name
- */
- public String getNewSigName() {
- AcroFields af = writer.getAcroFields();
- String name = "Signature";
- int step = 0;
- boolean found = false;
- while (!found) {
- ++step;
- String n1 = name + step;
- if (af.getFieldItem(n1) != null)
- continue;
- n1 += ".";
- found = true;
- for (Iterator it = af.getFields().keySet().iterator(); it.hasNext();) {
- String fn = (String)it.next();
- if (fn.startsWith(n1)) {
- found = false;
- break;
- }
- }
- }
- name += step;
- return name;
- }
-
- /**
- * This is the first method to be called when using external signatures. The general sequence is:
- * preClose(), getDocumentBytes() and close().
- *
- * If calling preClose() dont't call PdfStamper.close().
- *
- * No external signatures are allowed if this methos is called.
- * @throws IOException on error
- * @throws DocumentException on error
- */
- public void preClose() throws IOException, DocumentException {
- preClose(null);
- }
- /**
- * This is the first method to be called when using external signatures. The general sequence is:
- * preClose(), getDocumentBytes() and close().
- *
- * If calling preClose() dont't call PdfStamper.close().
- *
- * If using an external signature exclusionSizes
must contain at least
- * the PdfName.CONTENTS
key with the size that it will take in the
- * document. Note that due to the hex string coding this size should be
- * byte_size*2+2.
- * @param exclusionSizes a HashMap
with names and sizes to be excluded in the signature
- * calculation. The key is a PdfName
and the value an
- * Integer
. At least the PdfName.CONTENTS
must be present
- * @throws IOException on error
- * @throws DocumentException on error
- */
- public void preClose(HashMap exclusionSizes) throws IOException, DocumentException {
- if (preClosed)
- throw new DocumentException("Document already pre closed.");
- preClosed = true;
- AcroFields af = writer.getAcroFields();
- String name = getFieldName();
- boolean fieldExists = !(isInvisible() || isNewField());
- int flags = 132;
- if (fieldExists) {
- flags = 0;
- ArrayList merged = af.getFieldItem(name).merged;
- PdfObject obj = PdfReader.getPdfObjectRelease(((PdfDictionary)merged.get(0)).get(PdfName.F));
- if (obj != null && obj.isNumber())
- flags = ((PdfNumber)obj).intValue();
- af.removeField(name);
- }
- writer.setSigFlags(3);
- PdfFormField sigField = PdfFormField.createSignature(writer);
- sigField.setFieldName(name);
- PdfIndirectReference refSig = writer.getPdfIndirectReference();
- sigField.put(PdfName.V, refSig);
- sigField.setFlags(flags);
-
- int pagen = getPage();
- // PdfReader reader = writer.reader;
- if (!isInvisible()) {
- sigField.setWidget(getPageRect(), null);
- sigField.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, getAppearance());
- }
- else
- sigField.setWidget(new Rectangle(0, 0), null);
- sigField.setPage(pagen);
- writer.addAnnotation(sigField, pagen);
-
- exclusionLocations = new HashMap();
- if (cryptoDictionary == null) {
- if (PdfName.ADOBE_PPKLITE.equals(getFilter()))
- sigStandard = new PdfSigGenericPKCS.PPKLite(getProvider());
- else if (PdfName.ADOBE_PPKMS.equals(getFilter()))
- sigStandard = new PdfSigGenericPKCS.PPKMS(getProvider());
- else if (PdfName.VERISIGN_PPKVS.equals(getFilter()))
- sigStandard = new PdfSigGenericPKCS.VeriSign(getProvider());
- else
- throw new IllegalArgumentException("Unknown filter: " + getFilter());
- sigStandard.setExternalDigest(externalDigest, externalRSAdata, digestEncryptionAlgorithm);
- if (getReason() != null)
- sigStandard.setReason(getReason());
- if (getLocation() != null)
- sigStandard.setLocation(getLocation());
- if (getContact() != null)
- sigStandard.setContact(getContact());
- sigStandard.put(PdfName.M, new PdfDate(getSignDate()));
- sigStandard.setSignInfo(getPrivKey(), getCertChain(), getCrlList());
- PdfString contents = (PdfString)sigStandard.get(PdfName.CONTENTS);
- PdfLiteral lit = new PdfLiteral((contents.toString().length() + (PdfName.ADOBE_PPKLITE.equals(getFilter())?0:64)) * 2 + 2);
- exclusionLocations.put(PdfName.CONTENTS, lit);
- sigStandard.put(PdfName.CONTENTS, lit);
- lit = new PdfLiteral(80);
- exclusionLocations.put(PdfName.BYTERANGE, lit);
- sigStandard.put(PdfName.BYTERANGE, lit);
- if (signatureEvent != null)
- signatureEvent.getSignatureDictionary(sigStandard);
- writer.addToBody(sigStandard, refSig, false);
- }
- else {
- PdfLiteral lit = new PdfLiteral(80);
- exclusionLocations.put(PdfName.BYTERANGE, lit);
- cryptoDictionary.put(PdfName.BYTERANGE, lit);
- for (Iterator it = exclusionSizes.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry)it.next();
- PdfName key = (PdfName)entry.getKey();
- Integer v = (Integer)entry.getValue();
- lit = new PdfLiteral(v.intValue());
- exclusionLocations.put(key, lit);
- cryptoDictionary.put(key, lit);
- }
- if (signatureEvent != null)
- signatureEvent.getSignatureDictionary(cryptoDictionary);
- writer.addToBody(cryptoDictionary, refSig, false);
- }
- writer.close(stamper.getMoreInfo());
-
- range = new int[exclusionLocations.size() * 2];
- int byteRangePosition = ((PdfLiteral)exclusionLocations.get(PdfName.BYTERANGE)).getPosition();
- exclusionLocations.remove(PdfName.BYTERANGE);
- int idx = 1;
- for (Iterator it = exclusionLocations.values().iterator(); it.hasNext();) {
- PdfLiteral lit = (PdfLiteral)it.next();
- int n = lit.getPosition();
- range[idx++] = n;
- range[idx++] = lit.getPosLength() + n;
- }
- Arrays.sort(range, 1, range.length - 1);
- for (int k = 3; k < range.length - 2; k += 2)
- range[k] -= range[k - 1];
-
- if (tempFile == null) {
- bout = sigout.getBuffer();
- boutLen = sigout.size();
- range[range.length - 1] = boutLen - range[range.length - 2];
- ByteBuffer bf = new ByteBuffer();
- bf.append('[');
- for (int k = 0; k < range.length; ++k)
- bf.append(range[k]).append(' ');
- bf.append(']');
- System.arraycopy(bf.getBuffer(), 0, bout, byteRangePosition, bf.size());
- }
- else {
- try {
- raf = new RandomAccessFile(tempFile, "rw");
- int boutLen = (int)raf.length();
- range[range.length - 1] = boutLen - range[range.length - 2];
- ByteBuffer bf = new ByteBuffer();
- bf.append('[');
- for (int k = 0; k < range.length; ++k)
- bf.append(range[k]).append(' ');
- bf.append(']');
- raf.seek(byteRangePosition);
- raf.write(bf.getBuffer(), 0, bf.size());
- }
- catch (IOException e) {
- try{raf.close();}catch(Exception ee){}
- try{tempFile.delete();}catch(Exception ee){}
- throw e;
- }
- }
- }
-
- /**
- * This is the last method to be called when using external signatures. The general sequence is:
- * preClose(), getDocumentBytes() and close().
- *
- * update
is a PdfDictionary
that must have exactly the
- * same keys as the ones provided in {@link #preClose(HashMap)}.
- * @param update a PdfDictionary
with the key/value that will fill the holes defined
- * in {@link #preClose(HashMap)}
- * @throws DocumentException on error
- * @throws IOException on error
- */
- public void close(PdfDictionary update) throws IOException, DocumentException {
- try {
- if (!preClosed)
- throw new DocumentException("preClose() must be called first.");
- ByteBuffer bf = new ByteBuffer();
- for (Iterator it = update.getKeys().iterator(); it.hasNext();) {
- PdfName key = (PdfName)it.next();
- PdfObject obj = update.get(key);
- PdfLiteral lit = (PdfLiteral)exclusionLocations.get(key);
- if (lit == null)
- throw new IllegalArgumentException("The key " + key.toString() + " didn't reserve space in preClose().");
- bf.reset();
- obj.toPdf(null, bf);
- if (bf.size() > lit.getPosLength())
- throw new IllegalArgumentException("The key " + key.toString() + " is too big. Is " + bf.size() + ", reserved " + lit.getPosLength());
- if (tempFile == null)
- System.arraycopy(bf.getBuffer(), 0, bout, lit.getPosition(), bf.size());
- else {
- raf.seek(lit.getPosition());
- raf.write(bf.getBuffer(), 0, bf.size());
- }
- }
- if (update.size() != exclusionLocations.size())
- throw new IllegalArgumentException("The update dictionary has less keys than required.");
- if (tempFile == null) {
- originalout.write(bout, 0, boutLen);
- }
- else {
- if (originalout != null) {
- raf.seek(0);
- int length = (int)raf.length();
- byte buf[] = new byte[8192];
- while (length > 0) {
- int r = raf.read(buf, 0, Math.min(buf.length, length));
- if (r < 0)
- throw new EOFException("Unexpected EOF");
- originalout.write(buf, 0, r);
- length -= r;
- }
- }
- }
- }
- finally {
- if (tempFile != null) {
- try{raf.close();}catch(Exception ee){}
- if (originalout != null)
- try{tempFile.delete();}catch(Exception ee){}
- }
- if (originalout != null)
- try{originalout.close();}catch(Exception e){}
- }
- }
-
- private static int indexArray(byte bout[], int position, String search) {
- byte ss[] = PdfEncodings.convertToBytes(search, null);
- while (true) {
- int k;
- for (k = 0; k < ss.length; ++k) {
- if (ss[k] != bout[position + k])
- break;
- }
- if (k == ss.length)
- return position;
- ++position;
- }
- }
-
- private static int indexFile(RandomAccessFile raf, int position, String search) throws IOException {
- byte ss[] = PdfEncodings.convertToBytes(search, null);
- while (true) {
- raf.seek(position);
- int k;
- for (k = 0; k < ss.length; ++k) {
- int b = raf.read();
- if (b < 0)
- throw new EOFException("Unexpected EOF");
- if (ss[k] != (byte)b)
- break;
- }
- if (k == ss.length)
- return position;
- ++position;
- }
- }
-
- /**
- * Gets the document bytes that are hashable when using external signatures. The general sequence is:
- * preClose(), getRangeStream() and close().
- *
- * @return the document bytes that are hashable
- */
- public InputStream getRangeStream() {
- return new PdfSignatureAppearance.RangeStream(raf, bout, range);
- }
-
- /**
- * Gets the user made signature dictionary. This is the dictionary at the /V key.
- * @return the user made signature dictionary
- */
- public com.lowagie.text.pdf.PdfDictionary getCryptoDictionary() {
- return cryptoDictionary;
- }
-
- /**
- * Sets a user made signature dictionary. This is the dictionary at the /V key.
- * @param cryptoDictionary a user made signature dictionary
- */
- public void setCryptoDictionary(com.lowagie.text.pdf.PdfDictionary cryptoDictionary) {
- this.cryptoDictionary = cryptoDictionary;
- }
-
- /**
- * Gets the PdfStamper
associated with this instance.
- * @return the PdfStamper
associated with this instance
- */
- public com.lowagie.text.pdf.PdfStamper getStamper() {
- return stamper;
- }
-
- void setStamper(com.lowagie.text.pdf.PdfStamper stamper) {
- this.stamper = stamper;
- }
-
- /**
- * Checks if the document is in the process of closing.
- * @return true
if the document is in the process of closing,
- * false
otherwise
- */
- public boolean isPreClosed() {
- return preClosed;
- }
-
- /**
- * Gets the instance of the standard signature dictionary. This instance
- * is only available after pre close.
- *
- * The main use is to insert external signatures.
- * @return the instance of the standard signature dictionary
- */
- public com.lowagie.text.pdf.PdfSigGenericPKCS getSigStandard() {
- return sigStandard;
- }
-
- /**
- * Gets the signing contact.
- * @return the signing contact
- */
- public String getContact() {
- return this.contact;
- }
-
- /**
- * Sets the signing contact.
- * @param contact the signing contact
- */
- public void setContact(String contact) {
- this.contact = contact;
- }
-
- /**
- * Gets the n2 and n4 layer font.
- * @return the n2 and n4 layer font
- */
- public Font getLayer2Font() {
- return this.layer2Font;
- }
-
- /**
- * Sets the n2 and n4 layer font. If the font size is zero, auto-fit will be used.
- * @param layer2Font the n2 and n4 font
- */
- public void setLayer2Font(Font layer2Font) {
- this.layer2Font = layer2Font;
- }
-
- /**
- * Gets the Acrobat 6.0 layer mode.
- * @return the Acrobat 6.0 layer mode
- */
- public boolean isAcro6Layers() {
- return this.acro6Layers;
- }
-
- /**
- * Acrobat 6.0 and higher recomends that only layer n2 and n4 be present. This method sets that mode.
- * @param acro6Layers if true
only the layers n2 and n4 will be present
- */
- public void setAcro6Layers(boolean acro6Layers) {
- this.acro6Layers = acro6Layers;
- }
-
- /** Sets the run direction in the n2 and n4 layer.
- * @param runDirection the run direction
- */
- public void setRunDirection(int runDirection) {
- if (runDirection < PdfWriter.RUN_DIRECTION_DEFAULT || runDirection > PdfWriter.RUN_DIRECTION_RTL)
- throw new RuntimeException("Invalid run direction: " + runDirection);
- this.runDirection = runDirection;
- }
-
- /** Gets the run direction.
- * @return the run direction
- */
- public int getRunDirection() {
- return runDirection;
- }
-
- /**
- * Getter for property signatureEvent.
- * @return Value of property signatureEvent.
- */
- public SignatureEvent getSignatureEvent() {
- return this.signatureEvent;
- }
-
- /**
- * Sets the signature event to allow modification of the signature dictionary.
- * @param signatureEvent the signature event
- */
- public void setSignatureEvent(SignatureEvent signatureEvent) {
- this.signatureEvent = signatureEvent;
- }
-
- /**
- * Gets the background image for the layer 2.
- * @return the background image for the layer 2
- */
- /* ssteward: dropped in 1.44
- public Image getImage() {
- return this.image;
- }
- */
-
- /**
- * Sets the background image for the layer 2.
- * @param image the background image for the layer 2
- */
- /* ssteward: dropped in 1.44
- public void setImage(Image image) {
- this.image = image;
- }
- */
-
- /**
- * Gets the scaling to be applied to the background image.
- * @return the scaling to be applied to the background image
- */
- public float getImageScale() {
- return this.imageScale;
- }
-
- /**
- * Sets the scaling to be applied to the background image. If it's zero the image
- * will fully fill the rectangle. If it's less than zero the image will fill the rectangle but
- * will keep the proportions. If it's greater than zero that scaling will be applied.
- * In any of the cases the image will always be centered. It's zero by default.
- * @param imageScale the scaling to be applied to the background image
- */
- public void setImageScale(float imageScale) {
- this.imageScale = imageScale;
- }
-
- /**
- * Commands to draw a yellow question mark in a stream content
- */
- public static final String questionMark =
- "% DSUnknown\n" +
- "q\n" +
- "1 G\n" +
- "1 g\n" +
- "0.1 0 0 0.1 9 0 cm\n" +
- "0 J 0 j 4 M []0 d\n" +
- "1 i \n" +
- "0 g\n" +
- "313 292 m\n" +
- "313 404 325 453 432 529 c\n" +
- "478 561 504 597 504 645 c\n" +
- "504 736 440 760 391 760 c\n" +
- "286 760 271 681 265 626 c\n" +
- "265 625 l\n" +
- "100 625 l\n" +
- "100 828 253 898 381 898 c\n" +
- "451 898 679 878 679 650 c\n" +
- "679 555 628 499 538 435 c\n" +
- "488 399 467 376 467 292 c\n" +
- "313 292 l\n" +
- "h\n" +
- "308 214 170 -164 re\n" +
- "f\n" +
- "0.44 G\n" +
- "1.2 w\n" +
- "1 1 0.4 rg\n" +
- "287 318 m\n" +
- "287 430 299 479 406 555 c\n" +
- "451 587 478 623 478 671 c\n" +
- "478 762 414 786 365 786 c\n" +
- "260 786 245 707 239 652 c\n" +
- "239 651 l\n" +
- "74 651 l\n" +
- "74 854 227 924 355 924 c\n" +
- "425 924 653 904 653 676 c\n" +
- "653 581 602 525 512 461 c\n" +
- "462 425 441 402 441 318 c\n" +
- "287 318 l\n" +
- "h\n" +
- "282 240 170 -164 re\n" +
- "B\n" +
- "Q\n";
-
- /**
- * Holds value of property contact.
- */
- private String contact;
-
- /**
- * Holds value of property layer2Font.
- */
- private Font layer2Font;
-
- /**
- * Holds value of property layer4Text.
- */
- private String layer4Text;
-
- /**
- * Holds value of property acro6Layers.
- */
- private boolean acro6Layers;
-
- /**
- * Holds value of property runDirection.
- */
- private int runDirection = PdfWriter.RUN_DIRECTION_NO_BIDI;
-
- /**
- * Holds value of property signatureEvent.
- */
- private SignatureEvent signatureEvent;
-
- /**
- * Holds value of property image.
- */
- // private Image image; ssteward: dropped in 1.44
-
- /**
- * Holds value of property imageScale.
- */
- private float imageScale;
-
- /**
- *
- */
- private static class RangeStream extends InputStream {
- private byte b[] = new byte[1];
- private RandomAccessFile raf;
- private byte bout[];
- private int range[];
- private int rangePosition = 0;
-
- private RangeStream(RandomAccessFile raf, byte bout[], int range[]) {
- this.raf = raf;
- this.bout = bout;
- this.range = range;
- }
-
- /**
- * @see java.io.InputStream#read()
- */
- public int read() throws IOException {
- int n = read(b);
- if (n != 1)
- return -1;
- return b[0] & 0xff;
- }
-
- /**
- * @see java.io.InputStream#read(byte[], int, int)
- */
- public int read(byte[] b, int off, int len) throws IOException {
- if (b == null) {
- throw new NullPointerException();
- } else if ((off < 0) || (off > b.length) || (len < 0) ||
- ((off + len) > b.length) || ((off + len) < 0)) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return 0;
- }
- if (rangePosition >= range[range.length - 2] + range[range.length - 1]) {
- return -1;
- }
- for (int k = 0; k < range.length; k += 2) {
- int start = range[k];
- int end = start + range[k + 1];
- if (rangePosition < start)
- rangePosition = start;
- if (rangePosition >= start && rangePosition < end) {
- int lenf = Math.min(len, end - rangePosition);
- if (raf == null)
- System.arraycopy(bout, rangePosition, b, off, lenf);
- else {
- raf.seek(rangePosition);
- raf.readFully(b, off, lenf);
- }
- rangePosition += lenf;
- return lenf;
- }
- }
- return -1;
- }
- }
-
- /**
- * An interface to retrieve the signature dictionary for modification.
- */
- public interface SignatureEvent {
- /**
- * Allows modification of the signature dictionary.
- * @param sig the signature dictionary
- */
- public void getSignatureDictionary(PdfDictionary sig);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfSpotColor.java pdftk-2.01/java/com/lowagie/text/pdf/PdfSpotColor.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfSpotColor.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfSpotColor.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,148 +0,0 @@
-/*
- * $Id: PdfSpotColor.java,v 1.45 2005/03/24 12:38:19 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.awt.Color;
-import java.io.IOException;
-/**
- * A PdfSpotColor
defines a ColorSpace
- *
- * @see PdfDictionary
- */
-
-public class PdfSpotColor{
-
-/* The tint value */
- protected float tint;
-
-/** The color name */
- public PdfName name;
-
-/** The alternative color space */
- public Color altcs;
- // constructors
-
- /**
- * Constructs a new PdfSpotColor
.
- *
- * @param name a String value
- * @param tint a tint value between 0 and 1
- * @param altcs a altnative colorspace value
- */
-
- public PdfSpotColor(String name, float tint, Color altcs) {
- this.name = new PdfName(name);
- this.tint = tint;
- this.altcs = altcs;
- }
-
- /**
- * Gets the tint of the SpotColor.
- * @return a float
- */
- public float getTint() {
- return tint;
- }
-
- /**
- * Gets the alternative ColorSpace.
- * @return a Colot
- */
- public Color getAlternativeCS() {
- return altcs;
- }
-
- protected PdfObject getSpotObject(PdfWriter writer) throws IOException {
- PdfArray array = new PdfArray(PdfName.SEPARATION);
- array.add(name);
- PdfFunction func = null;
- if (altcs instanceof ExtendedColor) {
- int type = ((ExtendedColor)altcs).type;
-
- // ssteward
- // having trouble with unreachable bytecode in switch default (per gcj 4.4)
- // so try a clumsier workaround
- boolean handled_b= false;
- switch (type) {
- case ExtendedColor.TYPE_GRAY:
- array.add(PdfName.DEVICEGRAY);
- func = PdfFunction.type2(writer, new float[]{0, 1}, null, new float[]{0}, new float[]{((GrayColor)altcs).getGray()}, 1);
- handled_b= true;
- break;
- case ExtendedColor.TYPE_CMYK:
- array.add(PdfName.DEVICECMYK);
- CMYKColor cmyk = (CMYKColor)altcs;
- func = PdfFunction.type2(writer, new float[]{0, 1}, null, new float[]{0, 0, 0, 0},
- new float[]{cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack()}, 1);
- handled_b= true;
- break;
-// default:
-// throw new RuntimeException("Only RGB, Gray and CMYK are supported as alternative color spaces.");
- }
- if( !handled_b ) {
- throw new RuntimeException("Only RGB, Gray and CMYK are supported as alternative color spaces.");
- }
- }
- else {
- array.add(PdfName.DEVICERGB);
- func = PdfFunction.type2(writer, new float[]{0, 1}, null, new float[]{1, 1, 1},
- new float[]{(float)altcs.getRed() / 255, (float)altcs.getGreen() / 255, (float)altcs.getBlue() / 255}, 1);
- }
- array.add(func.getReference());
- return array;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfStamper.java pdftk-2.01/java/com/lowagie/text/pdf/PdfStamper.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfStamper.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfStamper.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,654 +0,0 @@
-/*
- * Copyright 2003, 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.security.SignatureException;
-import java.io.OutputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.EOFException;
-import java.io.RandomAccessFile;
-import java.io.File;
-import java.io.InputStream;
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.ExceptionConverter;
-import com.lowagie.text.DocWriter;
-import com.lowagie.text.Rectangle;
-// import com.lowagie.text.Image; ssteward: dropped in 1.44
-import java.util.HashMap;
-import java.util.List;
-import java.util.Iterator;
-
-/** Applies extra content to the pages of a PDF document.
- * This extra content can be all the objects allowed in PdfContentByte
- * including pages from other Pdfs. The original PDF will keep
- * all the interactive elements including bookmarks, links and form fields.
- *
- * It is also possible to change the field values and to
- * flatten them. New fields can be added but not flattened.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfStamper {
- /**
- * The writer
- */
- protected PdfStamperImp stamper;
- private HashMap moreInfo;
- private boolean hasSignature;
- private PdfSignatureAppearance sigApp;
-
- /** Starts the process of adding extra content to an existing PDF
- * document.
- * @param reader the original document. It cannot be reused
- * @param os the output stream
- * @throws DocumentException on error
- * @throws IOException on error
- */
- public PdfStamper(PdfReader reader, OutputStream os) throws DocumentException, IOException {
- stamper = new PdfStamperImp(reader, os, '\0', false);
- }
-
- /**
- * Starts the process of adding extra content to an existing PDF
- * document.
- * @param reader the original document. It cannot be reused
- * @param os the output stream
- * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
- * document
- * @throws DocumentException on error
- * @throws IOException on error
- */
- public PdfStamper(PdfReader reader, OutputStream os, char pdfVersion) throws DocumentException, IOException {
- stamper = new PdfStamperImp(reader, os, pdfVersion, false);
- }
-
- /**
- * Starts the process of adding extra content to an existing PDF
- * document, possibly as a new revision.
- * @param reader the original document. It cannot be reused
- * @param os the output stream
- * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
- * document
- * @param append if true
appends the document changes as a new revision. This is
- * only useful for multiple signatures as nothing is gained in speed or memory
- * @throws DocumentException on error
- * @throws IOException on error
- */
- public PdfStamper(PdfReader reader, OutputStream os, char pdfVersion, boolean append) throws DocumentException, IOException {
- stamper = new PdfStamperImp(reader, os, pdfVersion, append);
- }
-
- /** Gets the optional String
map to add or change values in
- * the info dictionary.
- * @return the map or null
- *
- */
- public HashMap getMoreInfo() {
- return this.moreInfo;
- }
-
- /** An optional String
map to add or change values in
- * the info dictionary. Entries with null
- * values delete the key in the original info dictionary
- * @param moreInfo additional entries to the info dictionary
- *
- */
- public void setMoreInfo(HashMap moreInfo) {
- this.moreInfo = moreInfo;
- }
-
- /**
- * Inserts a blank page. All the pages above and including pageNumber
will
- * be shifted up. If pageNumber
is bigger than the total number of pages
- * the new page will be the last one.
- * @param pageNumber the page number position where the new page will be inserted
- * @param mediabox the size of the new page
- */
- public void insertPage(int pageNumber, Rectangle mediabox) {
- stamper.insertPage(pageNumber, mediabox);
- }
-
- /**
- * Gets the signing instance. The appearances and other parameters can the be set.
- * @return the signing instance
- */
- public PdfSignatureAppearance getSignatureAppearance() {
- return sigApp;
- }
-
- private String getNewSigName() {
- AcroFields af = getAcroFields();
- String name = "Signature";
- int step = 0;
- boolean found = false;
- while (!found) {
- ++step;
- String n1 = name + step;
- if (af.getFieldItem(n1) != null)
- continue;
- n1 += ".";
- found = true;
- for (Iterator it = af.getFields().keySet().iterator(); it.hasNext();) {
- String fn = (String)it.next();
- if (fn.startsWith(n1)) {
- found = false;
- break;
- }
- }
- }
- name += step;
- return name;
- }
- /**
- * Closes the document. No more content can be written after the
- * document is closed.
- *
- * If closing a signed document with an external signature the closing must be done
- * in the PdfSignatureAppearance
instance.
- * @throws DocumentException on error
- * @throws IOException on error
- */
- public void close() throws DocumentException, IOException {
- if (!hasSignature) {
- stamper.close(moreInfo);
- return;
- }
- sigApp.preClose();
- PdfSigGenericPKCS sig = sigApp.getSigStandard();
- PdfLiteral lit = (PdfLiteral)sig.get(PdfName.CONTENTS);
- int totalBuf = (lit.getPosLength() - 2) / 2;
- byte buf[] = new byte[8192];
- int n;
- InputStream inp = sigApp.getRangeStream();
- try {
- while ((n = inp.read(buf)) > 0) {
- sig.getSigner().update(buf, 0, n);
- }
- }
- catch (SignatureException se) {
- throw new ExceptionConverter(se);
- }
- buf = new byte[totalBuf];
- byte[] bsig = sig.getSignerContents();
- System.arraycopy(bsig, 0, buf, 0, bsig.length);
- PdfString str = new PdfString(buf);
- str.setHexWriting(true);
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.CONTENTS, str);
- sigApp.close(dic);
- stamper.reader.close();
- }
-
- private static int indexArray(byte bout[], int position, String search) {
- byte ss[] = PdfEncodings.convertToBytes(search, null);
- while (true) {
- int k;
- for (k = 0; k < ss.length; ++k) {
- if (ss[k] != bout[position + k])
- break;
- }
- if (k == ss.length)
- return position;
- ++position;
- }
- }
-
- private static int indexFile(RandomAccessFile raf, int position, String search) throws IOException {
- byte ss[] = PdfEncodings.convertToBytes(search, null);
- while (true) {
- raf.seek(position);
- int k;
- for (k = 0; k < ss.length; ++k) {
- int b = raf.read();
- if (b < 0)
- throw new EOFException("Unexpected EOF");
- if (ss[k] != (byte)b)
- break;
- }
- if (k == ss.length)
- return position;
- ++position;
- }
- }
-
- /** Gets a PdfContentByte
to write under the page of
- * the original document.
- * @param pageNum the page number where the extra content is written
- * @return a PdfContentByte
to write under the page of
- * the original document
- */
- public PdfContentByte getUnderContent(int pageNum) {
- return stamper.getUnderContent(pageNum);
- }
-
- /** Gets a PdfContentByte
to write over the page of
- * the original document.
- * @param pageNum the page number where the extra content is written
- * @return a PdfContentByte
to write over the page of
- * the original document
- */
- public PdfContentByte getOverContent(int pageNum) {
- return stamper.getOverContent(pageNum);
- }
-
- /** Checks if the content is automatically adjusted to compensate
- * the original page rotation.
- * @return the auto-rotation status
- */
- public boolean isRotateContents() {
- return stamper.isRotateContents();
- }
-
- /** Flags the content to be automatically adjusted to compensate
- * the original page rotation. The default is true
.
- * @param rotateContents true
to set auto-rotation, false
- * otherwise
- */
- public void setRotateContents(boolean rotateContents) {
- stamper.setRotateContents(rotateContents);
- }
-
- /** Sets the encryption options for this document. The userPassword and the
- * ownerPassword can be null or have zero length. In this case the ownerPassword
- * is replaced by a random string. The open permissions for the document can be
- * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
- * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
- * The permissions can be combined by ORing them.
- * @param userPassword the user password. Can be null or empty
- * @param ownerPassword the owner password. Can be null or empty
- * @param permissions the user permissions
- * @param strength128Bits true
for 128 bit key length, false
for 40 bit key length
- * @throws DocumentException if anything was already written to the output
- */
- public void setEncryption(byte userPassword[], byte ownerPassword[], int permissions, boolean strength128Bits) throws DocumentException {
- if (stamper.isAppend())
- throw new DocumentException("Append mode does not support changing the encryption status.");
- if (stamper.isContentWritten())
- throw new DocumentException("Content was already written to the output.");
- stamper.setEncryption(userPassword, ownerPassword, permissions, strength128Bits);
- }
-
- /**
- * Sets the encryption options for this document. The userPassword and the
- * ownerPassword can be null or have zero length. In this case the ownerPassword
- * is replaced by a random string. The open permissions for the document can be
- * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
- * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
- * The permissions can be combined by ORing them.
- * @param strength true
for 128 bit key length, false
for 40 bit key length
- * @param userPassword the user password. Can be null or empty
- * @param ownerPassword the owner password. Can be null or empty
- * @param permissions the user permissions
- * @throws DocumentException if anything was already written to the output
- */
- public void setEncryption(boolean strength, String userPassword, String ownerPassword, int permissions) throws DocumentException {
- setEncryption(DocWriter.getISOBytes(userPassword), DocWriter.getISOBytes(ownerPassword), permissions, strength);
- }
-
- /** Gets a page from other PDF document. Note that calling this method more than
- * once with the same parameters will retrieve the same object.
- * @param reader the PDF document where the page is
- * @param pageNumber the page number. The first page is 1
- * @return the template representing the imported page
- */
- public PdfImportedPage getImportedPage(PdfReader reader, int pageNumber) {
- return stamper.getImportedPage(reader, pageNumber);
- }
-
- /** Gets the underlying PdfWriter.
- * @return the underlying PdfWriter
- */
- public PdfWriter getWriter() {
- return stamper;
- }
-
- /** Gets the underlying PdfReader.
- * @return the underlying PdfReader
- */
- public PdfReader getReader() {
- return stamper.reader;
- }
-
- /** Gets the AcroFields
object that allows to get and set field values
- * and to merge FDF forms.
- * @return the AcroFields
object
- */
- public AcroFields getAcroFields() {
- return stamper.getAcroFields();
- }
-
- /** Determines if the fields are flattened on close. The fields added with
- * {@link #addAnnotation(PdfAnnotation,int)} will never be flattened.
- * @param flat true
to flatten the fields, false
- * to keep the fields
- */
- public void setFormFlattening(boolean flat) {
- stamper.setFormFlattening(flat);
- }
-
- /** Determines if the FreeText annotations are flattened on close.
- * @param flat true
to flatten the FreeText annotations, false
- * (the default) to keep the FreeText annotations as active content.
- */
- public void setFreeTextFlattening(boolean flat) {
- stamper.setFreeTextFlattening(flat);
- }
-
- /**
- * Adds an annotation of form field in a specific page. This page number
- * can be overridden with {@link PdfAnnotation#setPlaceInPage(int)}.
- * @param annot the annotation
- * @param page the page
- */
- public void addAnnotation(PdfAnnotation annot, int page) {
- stamper.addAnnotation(annot, page);
- }
-
- /**
- * Adds the comments present in an FDF file.
- * @param fdf the FDF file
- * @throws IOException on error
- */
- public void addComments(FdfReader fdf) throws IOException {
- stamper.addComments(fdf);
- }
-
- /**
- * Sets the bookmarks. The list structure is defined in
- * {@link SimpleBookmark}.
- * @param outlines the bookmarks or null
to remove any
- * @throws IOException on error
- */
- public void setOutlines(List outlines) throws IOException {
- stamper.setOutlines(outlines);
- }
-
- /**
- * Sets the thumbnail image for a page.
- * @param image the image
- * @param page the page
- * @throws PdfException on error
- * @throws DocumentException on error
- */
- /*
- public void setThumbnail(Image image, int page) throws PdfException, DocumentException {
- stamper.setThumbnail(image, page);
- }
- */
-
- /**
- * Adds name
to the list of fields that will be flattened on close,
- * all the other fields will remain. If this method is never called or is called
- * with invalid field names, all the fields will be flattened.
- *
- * Calling setFormFlattening(true)
is needed to have any kind of
- * flattening.
- * @param name the field name
- * @return true
if the field exists, false
otherwise
- */
- public boolean partialFormFlattening(String name) {
- return stamper.partialFormFlattening(name);
- }
-
- /** Adds a JavaScript action at the document level. When the document
- * opens all this JavaScript runs.
- * @param js the JavaScript code
- */
- public void addJavaScript(String js) {
- stamper.addJavaScript(js, !PdfEncodings.isPdfDocEncoding(js));
- }
-
- /**
- * Sets the viewer preferences.
- * @param preferences the viewer preferences
- * @see PdfWriter#setViewerPreferences(int)
- */
- public void setViewerPreferences(int preferences) {
- stamper.setViewerPreferences(preferences);
- }
-
- /**
- * Sets the XMP metadata.
- * @param xmp
- * @see PdfWriter#setXmpMetadata(byte[])
- */
- public void setXmpMetadata(byte[] xmp) {
- stamper.setXmpMetadata(xmp);
- }
-
- /**
- * Gets the 1.5 compression status.
- * @return true
if the 1.5 compression is on
- */
- public boolean isFullCompression() {
- return stamper.isFullCompression();
- }
-
- /**
- * Sets the document's compression to the new 1.5 mode with object streams and xref
- * streams. It can be set at any time but once set it can't be unset.
- */
- public void setFullCompression() {
- if (stamper.isAppend())
- return;
- stamper.setFullCompression();
- }
-
- /**
- * Sets the open and close page additional action.
- * @param actionType the action type. It can be PdfWriter.PAGE_OPEN
- * or PdfWriter.PAGE_CLOSE
- * @param action the action to perform
- * @param page the page where the action will be applied. The first page is 1
- * @throws PdfException if the action type is invalid
- */
- public void setPageAction(PdfName actionType, PdfAction action, int page) throws PdfException {
- stamper.setPageAction(actionType, action, page);
- }
-
- /**
- * Sets the display duration for the page (for presentations)
- * @param seconds the number of seconds to display the page. A negative value removes the entry
- * @param page the page where the duration will be applied. The first page is 1
- */
- public void setDuration(int seconds, int page) {
- stamper.setDuration(seconds, page);
- }
-
- /**
- * Sets the transition for the page
- * @param transition the transition object. A null
removes the transition
- * @param page the page where the transition will be applied. The first page is 1
- */
- public void setTransition(PdfTransition transition, int page) {
- stamper.setTransition(transition, page);
- }
-
- /**
- * Applies a digital signature to a document, possibly as a new revision, making
- * possible multiple signatures. The returned PdfStamper
- * can be used normally as the signature is only applied when closing.
- *
- * A possible use for adding a signature without invalidating an existing one is:
- *
- *
- * KeyStore ks = KeyStore.getInstance("pkcs12");
- * ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
- * String alias = (String)ks.aliases().nextElement();
- * PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
- * Certificate[] chain = ks.getCertificateChain(alias);
- * PdfReader reader = new PdfReader("original.pdf");
- * FileOutputStream fout = new FileOutputStream("signed.pdf");
- * PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0', new
- * File("/temp"), true);
- * PdfSignatureAppearance sap = stp.getSignatureAppearance();
- * sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
- * sap.setReason("I'm the author");
- * sap.setLocation("Lisbon");
- * // comment next line to have an invisible signature
- * sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
- * stp.close();
- *
- * @param reader the original document
- * @param os the output stream or null
to keep the document in the temporary file
- * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
- * document
- * @param tempFile location of the temporary file. If it's a directory a temporary file will be created there.
- * If it's a file it will be used directly. The file will be deleted on exit unless os
is null.
- * In that case the document can be retrieved directly from the temporary file. If it's null
- * no temporary file will be created and memory will be used
- * @param append if true
the signature and all the other content will be added as a
- * new revision thus not invalidating existing signatures
- * @return a PdfStamper
- * @throws DocumentException on error
- * @throws IOException on error
- */
- public static PdfStamper createSignature(PdfReader reader, OutputStream os, char pdfVersion, File tempFile, boolean append) throws DocumentException, IOException {
- PdfStamper stp;
- if (tempFile == null) {
- ByteBuffer bout = new ByteBuffer();
- stp = new PdfStamper(reader, bout, pdfVersion, append);
- stp.sigApp = new PdfSignatureAppearance(stp.stamper);
- stp.sigApp.setSigout(bout);
- }
- else {
- if (tempFile.isDirectory())
- tempFile = File.createTempFile("pdf", null, tempFile);
- FileOutputStream fout = new FileOutputStream(tempFile);
- stp = new PdfStamper(reader, fout, pdfVersion, append);
- stp.sigApp = new PdfSignatureAppearance(stp.stamper);
- stp.sigApp.setTempFile(tempFile);
- }
- stp.sigApp.setOriginalout(os);
- stp.sigApp.setStamper(stp);
- stp.hasSignature = true;
- return stp;
- }
-
- /**
- * Applies a digital signature to a document. The returned PdfStamper
- * can be used normally as the signature is only applied when closing.
- *
- * Note that the pdf is created in memory.
- *
- * A possible use is:
- *
- *
- * KeyStore ks = KeyStore.getInstance("pkcs12");
- * ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
- * String alias = (String)ks.aliases().nextElement();
- * PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
- * Certificate[] chain = ks.getCertificateChain(alias);
- * PdfReader reader = new PdfReader("original.pdf");
- * FileOutputStream fout = new FileOutputStream("signed.pdf");
- * PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
- * PdfSignatureAppearance sap = stp.getSignatureAppearance();
- * sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
- * sap.setReason("I'm the author");
- * sap.setLocation("Lisbon");
- * // comment next line to have an invisible signature
- * sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
- * stp.close();
- *
- * @param reader the original document
- * @param os the output stream
- * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
- * document
- * @throws DocumentException on error
- * @throws IOException on error
- * @return a PdfStamper
- */
- public static PdfStamper createSignature(PdfReader reader, OutputStream os, char pdfVersion) throws DocumentException, IOException {
- return createSignature(reader, os, pdfVersion, null, false);
- }
-
- /**
- * Applies a digital signature to a document. The returned PdfStamper
- * can be used normally as the signature is only applied when closing.
- *
- * A possible use is:
- *
- *
- * KeyStore ks = KeyStore.getInstance("pkcs12");
- * ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
- * String alias = (String)ks.aliases().nextElement();
- * PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
- * Certificate[] chain = ks.getCertificateChain(alias);
- * PdfReader reader = new PdfReader("original.pdf");
- * FileOutputStream fout = new FileOutputStream("signed.pdf");
- * PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0', new File("/temp"));
- * PdfSignatureAppearance sap = stp.getSignatureAppearance();
- * sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
- * sap.setReason("I'm the author");
- * sap.setLocation("Lisbon");
- * // comment next line to have an invisible signature
- * sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
- * stp.close();
- *
- * @param reader the original document
- * @param os the output stream or null
to keep the document in the temporary file
- * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
- * document
- * @param tempFile location of the temporary file. If it's a directory a temporary file will be created there.
- * If it's a file it will be used directly. The file will be deleted on exit unless os
is null.
- * In that case the document can be retrieved directly from the temporary file. If it's null
- * no temporary file will be created and memory will be used
- * @return a PdfStamper
- * @throws DocumentException on error
- * @throws IOException on error
- */
- public static PdfStamper createSignature(PdfReader reader, OutputStream os, char pdfVersion, File tempFile) throws DocumentException, IOException
- {
- return createSignature(reader, os, pdfVersion, tempFile, false);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfStamperImp.java pdftk-2.01/java/com/lowagie/text/pdf/PdfStamperImp.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfStamperImp.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfStamperImp.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,1387 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * Copyright 2003 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.Rectangle;
-// import com.lowagie.text.Image; ssteward: dropped in 1.44
-import com.lowagie.text.ExceptionConverter;
-
-class PdfStamperImp extends PdfWriter {
- HashMap readers2intrefs = new HashMap();
- HashMap readers2file = new HashMap();
- RandomAccessFileOrArray file;
- PdfReader reader;
- IntHashtable myXref = new IntHashtable();
- /** Integer(page number) -> PageStamp */
- HashMap pagesToContent = new HashMap();
- boolean closed = false;
- /** Holds value of property rotateContents. */
- private boolean rotateContents = true;
- protected AcroFields acroFields;
- protected boolean flat = false;
- protected boolean flatFreeText = false;
- protected int namePtr[] = {0};
- protected boolean namedAsNames;
- protected List newBookmarks;
- protected HashSet partialFlattening = new HashSet();
- protected boolean useVp = false;
- protected int vp = 0;
- protected HashMap fieldTemplates = new HashMap();
- protected boolean fieldsAdded = false;
- protected int sigFlags = 0;
- protected boolean append;
- protected IntHashtable marked;
- protected int initialXrefSize;
- protected PdfAction openAction;
-
- /** Creates new PdfStamperImp.
- * @param reader the read PDF
- * @param os the output destination
- * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
- * document
- * @param append
- * @throws DocumentException on error
- * @throws IOException
- */
- PdfStamperImp(PdfReader reader, OutputStream os, char pdfVersion, boolean append) throws DocumentException, IOException {
- super(new PdfDocument(), os);
- if (reader.isTampered())
- throw new DocumentException("The original document was reused. Read it again from file.");
- reader.setTampered(true);
- this.reader = reader;
- file = reader.getSafeFile();
- this.append = append;
- if (append) {
- if (reader.isRebuilt())
- throw new DocumentException("Append mode requires a document without errors even if recovery was possible.");
- if (reader.isEncrypted())
- crypto = new PdfEncryption(reader.getDecrypt());
- HEADER = getISOBytes("\n");
- file.reOpen();
- byte buf[] = new byte[8192];
- int n;
- while ((n = file.read(buf)) > 0)
- this.os.write(buf, 0, n);
- file.close();
- prevxref = reader.getLastXref();
- reader.setAppendable(true);
- }
- else {
- if (pdfVersion == 0)
- super.setPdfVersion(reader.getPdfVersion());
- else
- super.setPdfVersion(pdfVersion);
- }
- super.open();
- pdf.addWriter(this);
- if (append) {
- body.setRefnum(reader.getXrefSize());
- marked = new IntHashtable();
- if (reader.isNewXrefType())
- fullCompression = true;
- if (reader.isHybridXref())
- fullCompression = false;
- }
- initialXrefSize = reader.getXrefSize();
- }
-
- void close(HashMap moreInfo) throws DocumentException, IOException {
- if (closed)
- return;
- if (useVp) {
- reader.setViewerPreferences(vp);
- markUsed(reader.getTrailer().get(PdfName.ROOT));
- }
- if (flat)
- flatFields();
- if (flatFreeText)
- flatFreeTextFields();
- addFieldResources();
- if (sigFlags != 0) {
- PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM), reader.getCatalog());
- if (acroForm != null) {
- acroForm.put(PdfName.SIGFLAGS, new PdfNumber(sigFlags));
- markUsed(acroForm);
- }
- }
- closed = true;
- addSharedObjectsToBody();
- setOutlines();
- setJavaScript();
- if (openAction != null) {
- reader.getCatalog().put(PdfName.OPENACTION, openAction);
- }
- // if there is XMP data to add: add it
- if (xmpMetadata != null) {
- PdfDictionary catalog = reader.getCatalog();
- PdfStream xmp = new PdfStream(xmpMetadata);
- xmp.put(PdfName.TYPE, PdfName.METADATA);
- xmp.put(PdfName.SUBTYPE, PdfName.XML);
- catalog.put(PdfName.METADATA, body.add(xmp).getIndirectReference());
- markUsed(catalog);
- }
- PRIndirectReference iInfo = null;
- try {
- file.reOpen();
- alterContents();
- iInfo = (PRIndirectReference)reader.trailer.get(PdfName.INFO);
- int skip = -1;
- if (iInfo != null)
- skip = iInfo.getNumber();
- int rootN = ((PRIndirectReference)reader.trailer.get(PdfName.ROOT)).getNumber();
- if (append) {
- int keys[] = marked.getKeys();
- for (int k = 0; k < keys.length; ++k) {
- int j = keys[k];
- PdfObject obj = reader.getPdfObjectRelease(j);
- if (obj != null && skip != j && j < initialXrefSize) {
- addToBody(obj, j, j != rootN);
- }
- }
- for (int k = initialXrefSize; k < reader.getXrefSize(); ++k) {
- PdfObject obj = reader.getPdfObject(k);
- if (obj != null) {
- addToBody(obj, getNewObjectNumber(reader, k, 0));
- }
- }
- }
- else {
- for (int k = 1; k < reader.getXrefSize(); ++k) {
- PdfObject obj = reader.getPdfObjectRelease(k);
- if (obj != null && skip != k) {
- addToBody(obj, getNewObjectNumber(reader, k, 0), k != rootN);
- }
- }
- }
- }
- finally {
- try {
- file.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- PdfIndirectReference encryption = null;
- PdfObject fileID = null;
- if (crypto != null) {
- if (append) {
- PdfIndirectReference cryref = (PdfIndirectReference)reader.trailer.get(PdfName.ENCRYPT);
- encryption = new PdfIndirectReference(0, cryref.getNumber(), cryref.getGeneration());
- }
- else {
- PdfIndirectObject encryptionObject = addToBody(crypto.getEncryptionDictionary(), false);
- encryption = encryptionObject.getIndirectReference();
- }
- fileID = crypto.getFileID();
- }
- else { // ssteward: carry ID over from reader
- fileID = reader.trailer.get(PdfName.ID);
- }
- PRIndirectReference iRoot = (PRIndirectReference)reader.trailer.get(PdfName.ROOT);
- PdfIndirectReference root = new PdfIndirectReference(0, getNewObjectNumber(reader, iRoot.getNumber(), 0));
- PdfIndirectReference info = null;
- PdfDictionary oldInfo = (PdfDictionary)PdfReader.getPdfObject(iInfo);
- PdfDictionary newInfo = new PdfDictionary();
- if (oldInfo != null) {
- for (Iterator i = oldInfo.getKeys().iterator(); i.hasNext();) {
- PdfName key = (PdfName)i.next();
- PdfObject value = PdfReader.getPdfObject(oldInfo.get(key));
- newInfo.put(key, value);
- }
- }
- if (moreInfo != null) {
- for (Iterator i = moreInfo.keySet().iterator(); i.hasNext();) {
- String key = (String)i.next();
- PdfName keyName = new PdfName(key);
- String value = (String)moreInfo.get(key);
- if (value == null)
- newInfo.remove(keyName);
- else
- newInfo.put(keyName, new PdfString(value, PdfObject.TEXT_UNICODE));
- }
- }
- if (append) {
- if (iInfo == null)
- info = addToBody(newInfo, false).getIndirectReference();
- else
- info = addToBody(newInfo, iInfo.getNumber(), false).getIndirectReference();
- }
- else {
- if (!newInfo.getKeys().isEmpty())
- info = addToBody(newInfo, false).getIndirectReference();
- }
- // write the cross-reference table of the body
- body.writeCrossReferenceTable(os, root, info, encryption, fileID, prevxref);
- if (fullCompression) {
- os.write(getISOBytes("startxref\n"));
- os.write(getISOBytes(String.valueOf(body.offset())));
- os.write(getISOBytes("\n%%EOF\n"));
- }
- else {
- PdfTrailer trailer = new PdfTrailer(body.size(),
- body.offset(),
- root,
- info,
- encryption,
- fileID, prevxref);
- trailer.toPdf(this, os);
- }
- os.flush();
- if (isCloseStream())
- os.close();
- reader.close();
- }
-
- // added by ssteward to match PdfWriter::close()
- public void close() { try {close(null);}catch(Exception e){throw new ExceptionConverter(e);} }
-
- void applyRotation(PdfDictionary pageN, ByteBuffer out) {
- if (!rotateContents)
- return;
- Rectangle page = reader.getPageSizeWithRotation(pageN);
- int rotation = page.getRotation();
- switch (rotation) {
- case 90:
- out.append(PdfContents.ROTATE90);
- out.append(page.top());
- out.append(' ').append('0').append(PdfContents.ROTATEFINAL);
- break;
- case 180:
- out.append(PdfContents.ROTATE180);
- out.append(page.right());
- out.append(' ');
- out.append(page.top());
- out.append(PdfContents.ROTATEFINAL);
- break;
- case 270:
- out.append(PdfContents.ROTATE270);
- out.append('0').append(' ');
- out.append(page.right());
- out.append(PdfContents.ROTATEFINAL);
- break;
- }
- }
-
- void alterContents() throws IOException {
- for (Iterator i = pagesToContent.values().iterator(); i.hasNext();) {
- PageStamp ps = (PageStamp)i.next();
- PdfDictionary pageN = ps.pageN;
- markUsed(pageN);
- PdfArray ar = null;
- PdfObject content = PdfReader.getPdfObject(pageN.get(PdfName.CONTENTS), pageN);
- if (content == null) {
- ar = new PdfArray();
- pageN.put(PdfName.CONTENTS, ar);
- }
- else if (content.isArray()) {
- ar = (PdfArray)content;
- markUsed(ar);
- }
- else if (content.isStream()) {
- ar = new PdfArray();
- ar.add(pageN.get(PdfName.CONTENTS));
- pageN.put(PdfName.CONTENTS, ar);
- }
- else {
- ar = new PdfArray();
- pageN.put(PdfName.CONTENTS, ar);
- }
- ByteBuffer out = new ByteBuffer();
- if (ps.under != null) {
- out.append(PdfContents.SAVESTATE);
- applyRotation(pageN, out);
- out.append(ps.under.getInternalBuffer());
- out.append(PdfContents.RESTORESTATE);
- }
- if (ps.over != null)
- out.append(PdfContents.SAVESTATE);
- PdfStream stream = new PdfStream(out.toByteArray());
- try{stream.flateCompress();}catch(Exception e){throw new ExceptionConverter(e);}
- ar.addFirst(addToBody(stream).getIndirectReference());
- out.reset();
- if (ps.over != null) {
- out.append(' ');
- out.append(PdfContents.RESTORESTATE);
- out.append(PdfContents.SAVESTATE);
- applyRotation(pageN, out);
- out.append(ps.over.getInternalBuffer());
- out.append(PdfContents.RESTORESTATE);
- stream = new PdfStream(out.toByteArray());
- try{stream.flateCompress();}catch(Exception e){throw new ExceptionConverter(e);}
- ar.add(addToBody(stream).getIndirectReference());
- }
- alterResources(ps);
- }
- }
-
- void alterResources(PageStamp ps) {
- ps.pageN.put(PdfName.RESOURCES, ps.pageResources.getResources());
- }
-
- protected int getNewObjectNumber(PdfReader reader, int number, int generation) {
- IntHashtable ref = (IntHashtable)readers2intrefs.get(reader);
- if (ref != null) {
- int n = ref.get(number);
- if (n == 0) {
- n = getIndirectReferenceNumber();
- ref.put(number, n);
- }
- return n;
- }
- if (currentPdfReaderInstance == null) {
- if (append && number < initialXrefSize)
- return number;
- int n = myXref.get(number);
- if (n == 0) {
- n = getIndirectReferenceNumber();
- myXref.put(number, n);
- }
- return n;
- }
- else
- return currentPdfReaderInstance.getNewObjectNumber(number, generation);
- }
-
- RandomAccessFileOrArray getReaderFile(PdfReader reader) {
- if (readers2intrefs.containsKey(reader)) {
- RandomAccessFileOrArray raf = (RandomAccessFileOrArray)readers2file.get(reader);
- if (raf != null)
- return raf;
- return reader.getSafeFile();
- }
- if (currentPdfReaderInstance == null)
- return file;
- else
- return currentPdfReaderInstance.getReaderFile();
- }
-
- /**
- * @param reader
- * @param openFile
- * @throws IOException
- */
- public void registerReader(PdfReader reader, boolean openFile) throws IOException {
- if (readers2intrefs.containsKey(reader))
- return;
- readers2intrefs.put(reader, new IntHashtable());
- if (openFile) {
- RandomAccessFileOrArray raf = reader.getSafeFile();
- readers2file.put(reader, raf);
- raf.reOpen();
- }
- }
-
- /**
- * @param reader
- */
- public void unRegisterReader(PdfReader reader) {
- if (!readers2intrefs.containsKey(reader))
- return;
- readers2intrefs.remove(reader);
- RandomAccessFileOrArray raf = (RandomAccessFileOrArray)readers2file.get(reader);
- if (raf == null)
- return;
- readers2file.remove(reader);
- try{raf.close();}catch(Exception e){}
- }
-
- static void findAllObjects(PdfReader reader, PdfObject obj, IntHashtable hits) {
- if (obj == null)
- return;
- switch (obj.type()) {
- case PdfObject.INDIRECT:
- PRIndirectReference iref = (PRIndirectReference)obj;
- if (reader != iref.getReader())
- return;
- if (hits.containsKey(iref.getNumber()))
- return;
- hits.put(iref.getNumber(), 1);
- findAllObjects(reader, PdfReader.getPdfObject(obj), hits);
- return;
- case PdfObject.ARRAY:
- ArrayList lst = ((PdfArray)obj).getArrayList();
- for (int k = 0; k < lst.size(); ++k) {
- findAllObjects(reader, (PdfObject)lst.get(k), hits);
- }
- return;
- case PdfObject.DICTIONARY:
- case PdfObject.STREAM:
- PdfDictionary dic = (PdfDictionary)obj;
- for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
- PdfName name = (PdfName)it.next();
- findAllObjects(reader, dic.get(name), hits);
- }
- return;
- }
- }
-
- /**
- * @param fdf
- * @throws IOException
- */
- public void addComments(FdfReader fdf) throws IOException{
- if (readers2intrefs.containsKey(fdf))
- return;
- PdfDictionary catalog = fdf.getCatalog();
- catalog = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.FDF));
- if (catalog == null)
- return;
- PdfArray annots = (PdfArray)PdfReader.getPdfObject(catalog.get(PdfName.ANNOTS));
- if (annots == null || annots.size() == 0)
- return;
- registerReader(fdf, false);
- IntHashtable hits = new IntHashtable();
- HashMap irt = new HashMap();
- ArrayList an = new ArrayList();
- ArrayList ar = annots.getArrayList();
- for (int k = 0; k < ar.size(); ++k) {
- PdfObject obj = (PdfObject)ar.get(k);
- PdfDictionary annot = (PdfDictionary)PdfReader.getPdfObject(obj);
- PdfNumber page = (PdfNumber)PdfReader.getPdfObject(annot.get(PdfName.PAGE));
- if (page == null || page.intValue() >= reader.getNumberOfPages())
- continue;
- findAllObjects(fdf, obj, hits);
- an.add(obj);
- if (obj.type() == PdfObject.INDIRECT) {
- PdfObject nm = PdfReader.getPdfObject(annot.get(PdfName.NM));
- if (nm != null && nm.type() == PdfObject.STRING)
- irt.put(nm.toString(), obj);
- }
- }
- int arhits[] = hits.getKeys();
- for (int k = 0; k < arhits.length; ++k) {
- int n = arhits[k];
- PdfObject obj = fdf.getPdfObject(n);
- if (obj.type() == PdfObject.DICTIONARY) {
- PdfObject str = PdfReader.getPdfObject(((PdfDictionary)obj).get(PdfName.IRT));
- if (str != null && str.type() == PdfObject.STRING) {
- PdfObject i = (PdfObject)irt.get(str.toString());
- if (i != null) {
- PdfDictionary dic2 = new PdfDictionary();
- dic2.merge((PdfDictionary)obj);
- dic2.put(PdfName.IRT, i);
- obj = dic2;
- }
- }
- }
- addToBody(obj, getNewObjectNumber(fdf, n, 0));
- }
- for (int k = 0; k < an.size(); ++k) {
- PdfObject obj = (PdfObject)an.get(k);
- PdfDictionary annot = (PdfDictionary)PdfReader.getPdfObject(obj);
- PdfNumber page = (PdfNumber)PdfReader.getPdfObject(annot.get(PdfName.PAGE));
- PdfDictionary dic = reader.getPageN(page.intValue() + 1);
- PdfArray annotsp = (PdfArray)PdfReader.getPdfObject(dic.get(PdfName.ANNOTS), dic);
- if (annotsp == null) {
- annotsp = new PdfArray();
- dic.put(PdfName.ANNOTS, annotsp);
- markUsed(dic);
- }
- markUsed(annotsp);
- annotsp.add(obj);
- }
- }
-
- PageStamp getPageStamp(int pageNum) {
- PdfDictionary pageN = reader.getPageN(pageNum);
- PageStamp ps = (PageStamp)pagesToContent.get(pageN);
- if (ps == null) {
- ps = new PageStamp(this, reader, pageN);
- pagesToContent.put(pageN, ps);
- }
- return ps;
- }
-
- PdfContentByte getUnderContent(int pageNum) {
- if (pageNum < 1 || pageNum > reader.getNumberOfPages())
- return null;
- PageStamp ps = getPageStamp(pageNum);
- if (ps.under == null)
- ps.under = new StampContent(this, ps);
- return ps.under;
- }
-
- PdfContentByte getOverContent(int pageNum) {
- if (pageNum < 1 || pageNum > reader.getNumberOfPages())
- return null;
- PageStamp ps = getPageStamp(pageNum);
- if (ps.over == null)
- ps.over = new StampContent(this, ps);
- return ps.over;
- }
-
- void correctAcroFieldPages(int page) {
- if (acroFields == null)
- return;
- if (page > reader.getNumberOfPages())
- return;
- HashMap fields = acroFields.getFields();
- for (Iterator it = fields.values().iterator(); it.hasNext();) {
- AcroFields.Item item = (AcroFields.Item)it.next();
- ArrayList pages = item.page;
- for (int k = 0; k < pages.size(); ++k) {
- int p = ((Integer)pages.get(k)).intValue();
- if (p >= page)
- pages.set(k, new Integer(p + 1));
- }
- }
- }
-
- void insertPage(int pageNumber, Rectangle mediabox) {
- Rectangle media = new Rectangle(mediabox);
- int rotation = media.getRotation() % 360;
- PdfDictionary page = new PdfDictionary(PdfName.PAGE);
- PdfDictionary resources = new PdfDictionary();
- PdfArray procset = new PdfArray();
- procset.add(PdfName.PDF);
- procset.add(PdfName.TEXT);
- procset.add(PdfName.IMAGEB);
- procset.add(PdfName.IMAGEC);
- procset.add(PdfName.IMAGEI);
- resources.put(PdfName.PROCSET, procset);
- page.put(PdfName.RESOURCES, resources);
- page.put(PdfName.ROTATE, new PdfNumber(rotation));
- page.put(PdfName.MEDIABOX, new PdfRectangle(media, rotation));
- PRIndirectReference pref = reader.addPdfObject(page);
- PdfDictionary parent;
- PRIndirectReference parentRef;
- if (pageNumber > reader.getNumberOfPages()) {
- PdfDictionary lastPage = reader.getPageNRelease(reader.getNumberOfPages());
- parentRef = (PRIndirectReference)lastPage.get(PdfName.PARENT);
- parentRef = new PRIndirectReference(reader, parentRef.getNumber());
- parent = (PdfDictionary)PdfReader.getPdfObject(parentRef);
- PdfArray kids = (PdfArray)PdfReader.getPdfObject(parent.get(PdfName.KIDS), parent);
- kids.add(pref);
- markUsed(kids);
- reader.pageRefs.insertPage(pageNumber, pref);
- }
- else {
- if (pageNumber < 1)
- pageNumber = 1;
- PdfDictionary firstPage = reader.getPageN(pageNumber);
- PRIndirectReference firstPageRef = (PRIndirectReference)reader.getPageOrigRef(pageNumber);
- reader.releasePage(pageNumber);
- parentRef = (PRIndirectReference)firstPage.get(PdfName.PARENT);
- parentRef = new PRIndirectReference(reader, parentRef.getNumber());
- parent = (PdfDictionary)PdfReader.getPdfObject(parentRef);
- PdfArray kids = (PdfArray)PdfReader.getPdfObject(parent.get(PdfName.KIDS), parent);
- ArrayList ar = kids.getArrayList();
- int len = ar.size();
- int num = firstPageRef.getNumber();
- for (int k = 0; k < len; ++k) {
- PRIndirectReference cur = (PRIndirectReference)ar.get(k);
- if (num == cur.getNumber()) {
- ar.add(k, pref);
- break;
- }
- }
- if (len == ar.size())
- throw new RuntimeException("Internal inconsistence.");
- markUsed(kids);
- reader.pageRefs.insertPage(pageNumber, pref);
- correctAcroFieldPages(pageNumber);
- }
- page.put(PdfName.PARENT, parentRef);
- while (parent != null) {
- markUsed(parent);
- PdfNumber count = (PdfNumber)PdfReader.getPdfObjectRelease(parent.get(PdfName.COUNT));
- parent.put(PdfName.COUNT, new PdfNumber(count.intValue() + 1));
- parent = (PdfDictionary)PdfReader.getPdfObject(parent.get(PdfName.PARENT));
- }
- }
-
- /** Getter for property rotateContents.
- * @return Value of property rotateContents.
- *
- */
- boolean isRotateContents() {
- return this.rotateContents;
- }
-
- /** Setter for property rotateContents.
- * @param rotateContents New value of property rotateContents.
- *
- */
- void setRotateContents(boolean rotateContents) {
- this.rotateContents = rotateContents;
- }
-
- boolean isContentWritten() {
- return body.size() > 1;
- }
-
- AcroFields getAcroFields() {
- if (acroFields == null) {
- acroFields = new AcroFields(reader, this);
- }
- return acroFields;
- }
-
- void setFormFlattening(boolean flat) {
- this.flat = flat;
- }
-
- void setFreeTextFlattening(boolean flat) {
- this.flatFreeText = flat;
- }
-
- boolean partialFormFlattening(String name) {
- getAcroFields();
- if (!acroFields.getFields().containsKey(name))
- return false;
- partialFlattening.add(name);
- return true;
- }
-
- void flatFields() {
- if (append)
- throw new IllegalArgumentException("Field flattening is not supported in append mode.");
- getAcroFields();
- HashMap fields = acroFields.getFields();
- if (fieldsAdded && partialFlattening.isEmpty()) {
- for (Iterator i = fields.keySet().iterator(); i.hasNext();) {
- partialFlattening.add(i.next());
- }
- }
- PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM));
- ArrayList acroFds = null;
- if (acroForm != null) {
- PdfArray array = (PdfArray)PdfReader.getPdfObject(acroForm.get(PdfName.FIELDS), acroForm);
- if (array != null)
- acroFds = array.getArrayList();
- }
- for (Iterator i = fields.keySet().iterator(); i.hasNext();) {
- String name = (String)i.next();
- if (!partialFlattening.isEmpty() && !partialFlattening.contains(name))
- continue;
- AcroFields.Item item = (AcroFields.Item)fields.get(name);
- for (int k = 0; k < item.merged.size(); ++k) {
- PdfDictionary merged = (PdfDictionary)item.merged.get(k);
- PdfNumber ff = (PdfNumber)PdfReader.getPdfObject(merged.get(PdfName.F));
- int flags = 0;
- if (ff != null)
- flags = ff.intValue();
- int page = ((Integer)item.page.get(k)).intValue();
- PdfDictionary appDic = (PdfDictionary)PdfReader.getPdfObject(merged.get(PdfName.AP));
- if (appDic != null && (flags & PdfFormField.FLAGS_PRINT) != 0 && (flags & PdfFormField.FLAGS_HIDDEN) == 0) {
- PdfObject obj = appDic.get(PdfName.N);
- PdfAppearance app = null;
- PdfObject objReal = PdfReader.getPdfObject(obj);
- if (obj instanceof PdfIndirectReference && !obj.isIndirect())
- app = new PdfAppearance((PdfIndirectReference)obj);
- else if (objReal instanceof PdfStream) {
- ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
- app = new PdfAppearance((PdfIndirectReference)obj);
- }
- else {
- if (objReal.isDictionary()) {
- PdfName as = (PdfName)PdfReader.getPdfObject(merged.get(PdfName.AS));
- if (as != null) {
- PdfIndirectReference iref = (PdfIndirectReference)((PdfDictionary)objReal).get(as);
- if (iref != null) {
- app = new PdfAppearance(iref);
- if (iref.isIndirect()) {
- objReal = PdfReader.getPdfObject(iref);
- ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
- }
- }
- }
- }
- }
- if (app != null) {
- Rectangle box = PdfReader.getNormalizedRectangle((PdfArray)PdfReader.getPdfObject(merged.get(PdfName.RECT)));
- PdfContentByte cb = getOverContent(page);
- cb.setLiteral("Q ");
- cb.addTemplate(app, box.left(), box.bottom());
- cb.setLiteral("q ");
- }
- }
- if (partialFlattening.isEmpty())
- continue;
- PdfDictionary pageDic = reader.getPageN(page);
- PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
- if (annots == null)
- continue;
- ArrayList ar = annots.getArrayList();
- for (int idx = 0; idx < ar.size(); ++idx) {
- PdfObject ran = (PdfObject)ar.get(idx);
- if (!ran.isIndirect())
- continue;
- PdfObject ran2 = (PdfObject)item.widget_refs.get(k);
- if (!ran2.isIndirect())
- continue;
- if (((PRIndirectReference)ran).getNumber() == ((PRIndirectReference)ran2).getNumber()) {
- ar.remove(idx--);
- PRIndirectReference wdref = (PRIndirectReference)ran2;
- while (true) {
- PdfDictionary wd = (PdfDictionary)PdfReader.getPdfObject(wdref);
- PRIndirectReference parentRef = (PRIndirectReference)wd.get(PdfName.PARENT);
- PdfReader.killIndirect(wdref);
- if (parentRef == null) { // reached AcroForm
- for (int fr = 0; fr < acroFds.size(); ++fr) {
- PdfObject h = (PdfObject)acroFds.get(fr);
- if (h.isIndirect() && ((PRIndirectReference)h).getNumber() == wdref.getNumber()) {
- acroFds.remove(fr);
- --fr;
- }
- }
- break;
- }
- PdfDictionary parent = (PdfDictionary)PdfReader.getPdfObject(parentRef);
- PdfArray kids = (PdfArray)PdfReader.getPdfObject(parent.get(PdfName.KIDS));
- ArrayList kar = kids.getArrayList();
- for (int fr = 0; fr < kar.size(); ++fr) {
- PdfObject h = (PdfObject)kar.get(fr);
- if (h.isIndirect() && ((PRIndirectReference)h).getNumber() == wdref.getNumber()) {
- kar.remove(fr);
- --fr;
- }
- }
- if (!kar.isEmpty())
- break;
- wdref = parentRef;
- }
- }
- }
- if (ar.size() == 0) {
- PdfReader.killIndirect(pageDic.get(PdfName.ANNOTS));
- pageDic.remove(PdfName.ANNOTS);
- }
- }
- }
- if (!fieldsAdded && partialFlattening.isEmpty()) {
- for (int page = 1; page <= reader.getNumberOfPages(); ++page) {
- PdfDictionary pageDic = reader.getPageN(page);
- PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
- if (annots == null)
- continue;
- ArrayList ar = annots.getArrayList();
- for (int idx = 0; idx < ar.size(); ++idx) {
- PdfObject annoto = PdfReader.getPdfObject((PdfObject)ar.get(idx));
- if ((annoto instanceof PdfIndirectReference) && !annoto.isIndirect())
- continue;
- PdfDictionary annot = (PdfDictionary)annoto;
- if (PdfName.WIDGET.equals(annot.get(PdfName.SUBTYPE))) {
- ar.remove(idx);
- --idx;
- }
- }
- if (ar.size() == 0) {
- PdfReader.killIndirect(pageDic.get(PdfName.ANNOTS));
- pageDic.remove(PdfName.ANNOTS);
- }
- }
- eliminateAcroformObjects();
- }
- }
-
- void eliminateAcroformObjects() {
- PdfObject acro = reader.getCatalog().get(PdfName.ACROFORM);
- if (acro == null)
- return;
- PdfDictionary acrodic = (PdfDictionary)PdfReader.getPdfObject(acro);
- PdfObject iFields = acrodic.get(PdfName.FIELDS);
- if (iFields != null) {
- PdfDictionary kids = new PdfDictionary();
- kids.put(PdfName.KIDS, iFields);
- sweepKids(kids);
- PdfReader.killIndirect(iFields);
- acrodic.put(PdfName.FIELDS, new PdfArray());
- }
-// PdfReader.killIndirect(acro);
-// reader.getCatalog().remove(PdfName.ACROFORM);
- }
-
- void sweepKids(PdfObject obj) {
- PdfObject oo = PdfReader.killIndirect(obj);
- if (oo == null || !oo.isDictionary())
- return;
- PdfDictionary dic = (PdfDictionary)oo;
- PdfArray kids = (PdfArray)PdfReader.killIndirect(dic.get(PdfName.KIDS));
- if (kids == null)
- return;
- ArrayList ar = kids.getArrayList();
- for (int k = 0; k < ar.size(); ++k) {
- sweepKids((PdfObject)ar.get(k));
- }
- }
-
- private void flatFreeTextFields()
- {
- if (append)
- throw new IllegalArgumentException("FreeText flattening is not supported in append mode.");
-
- for (int page = 1; page <= reader.getNumberOfPages(); ++page)
- {
- PdfDictionary pageDic = reader.getPageN(page);
- PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
- if (annots == null)
- continue;
- ArrayList ar = annots.getArrayList();
- for (int idx = 0; idx < ar.size(); ++idx)
- {
- PdfObject annoto = PdfReader.getPdfObject((PdfObject)ar.get(idx));
- if ((annoto instanceof PdfIndirectReference) && !annoto.isIndirect())
- continue;
-
- PdfDictionary annDic = (PdfDictionary)annoto;
- if (!((PdfName)annDic.get(PdfName.SUBTYPE)).equals(PdfName.FREETEXT))
- continue;
- PdfNumber ff = (PdfNumber)PdfReader.getPdfObject(annDic.get(PdfName.F));
- int flags = (ff != null) ? ff.intValue() : 0;
-
- if ( (flags & PdfFormField.FLAGS_PRINT) != 0 && (flags & PdfFormField.FLAGS_HIDDEN) == 0)
- {
- PdfObject obj1 = (PdfObject) annDic.get(PdfName.AP);
- if (obj1 == null)
- continue;
- PdfDictionary appDic = (obj1 instanceof PdfIndirectReference) ?
- (PdfDictionary) PdfReader.getPdfObject((PdfIndirectReference) obj1) : (PdfDictionary) obj1;
- PdfObject obj = appDic.get(PdfName.N);
- PdfAppearance app = null;
- PdfObject objReal = PdfReader.getPdfObject(obj);
-
- if (obj instanceof PdfIndirectReference && !obj.isIndirect())
- app = new PdfAppearance((PdfIndirectReference)obj);
- else if (objReal instanceof PdfStream)
- {
- ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
- app = new PdfAppearance((PdfIndirectReference)obj);
- }
- else
- {
- if (objReal.isDictionary())
- {
- PdfName as_p = (PdfName)PdfReader.getPdfObject(appDic.get(PdfName.AS));
- if (as_p != null)
- {
- PdfIndirectReference iref = (PdfIndirectReference)((PdfDictionary)objReal).get(as_p);
- if (iref != null)
- {
- app = new PdfAppearance(iref);
- if (iref.isIndirect())
- {
- objReal = PdfReader.getPdfObject(iref);
- ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
- }
- }
- }
- }
- }
- if (app != null)
- {
- Rectangle box = PdfReader.getNormalizedRectangle((PdfArray)PdfReader.getPdfObject(annDic.get(PdfName.RECT)));
- PdfContentByte cb = getOverContent(page);
- cb.setLiteral("Q ");
- cb.addTemplate(app, box.left(), box.bottom());
- cb.setLiteral("q ");
- }
- }
- if (partialFlattening.size() == 0)
- continue;
- }
- for (int idx = 0; idx < ar.size(); ++idx)
- {
- PdfObject annoto = PdfReader.getPdfObject((PdfObject)ar.get(idx));
- if ((annoto instanceof PdfIndirectReference) && annoto.isIndirect())
- {
- PdfDictionary annot = (PdfDictionary)annoto;
- if (PdfName.FREETEXT.equals(annot.get(PdfName.SUBTYPE)))
- {
- ar.remove(idx);
- --idx;
- }
- }
- }
- if (ar.size() == 0)
- {
- PdfReader.killIndirect(pageDic.get(PdfName.ANNOTS));
- pageDic.remove(PdfName.ANNOTS);
- }
- }
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfWriter#getPageReference(int)
- */
- public PdfIndirectReference getPageReference(int page) {
- PdfIndirectReference ref = reader.getPageOrigRef(page);
- if (ref == null)
- throw new IllegalArgumentException("Invalid page number " + page);
- return ref;
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfWriter#addAnnotation(com.lowagie.text.pdf.PdfAnnotation)
- */
- public void addAnnotation(PdfAnnotation annot) {
- throw new RuntimeException("Unsupported in this context. Use PdfStamper.addAnnotation()");
- }
-
- void addDocumentField(PdfIndirectReference ref) {
- PdfDictionary catalog = reader.getCatalog();
- PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.ACROFORM), catalog);
- if (acroForm == null) {
- acroForm = new PdfDictionary();
- catalog.put(PdfName.ACROFORM, acroForm);
- markUsed(catalog);
- }
- PdfArray fields = (PdfArray)PdfReader.getPdfObject(acroForm.get(PdfName.FIELDS), acroForm);
- if (fields == null) {
- fields = new PdfArray();
- acroForm.put(PdfName.FIELDS, fields);
- markUsed(acroForm);
- }
- fields.add(ref);
- markUsed(fields);
- }
-
- void addFieldResources() {
- if (fieldTemplates.size() == 0)
- return;
- PdfDictionary catalog = reader.getCatalog();
- PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.ACROFORM), catalog);
- if (acroForm == null) {
- acroForm = new PdfDictionary();
- catalog.put(PdfName.ACROFORM, acroForm);
- markUsed(catalog);
- }
- PdfDictionary dr = (PdfDictionary)PdfReader.getPdfObject(acroForm.get(PdfName.DR), acroForm);
- if (dr == null) {
- dr = new PdfDictionary();
- acroForm.put(PdfName.DR, dr);
- markUsed(acroForm);
- }
- markUsed(dr);
- for (Iterator it = fieldTemplates.keySet().iterator(); it.hasNext();) {
- PdfTemplate template = (PdfTemplate)it.next();
- PdfFormField.mergeResources(dr, (PdfDictionary)template.getResources(), this);
- }
- PdfDictionary fonts = (PdfDictionary)PdfReader.getPdfObject(dr.get(PdfName.FONT));
- if (fonts != null && acroForm.get(PdfName.DA) == null) {
- acroForm.put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
- markUsed(acroForm);
- }
- }
-
- void expandFields(PdfFormField field, ArrayList allAnnots) {
- allAnnots.add(field);
- ArrayList kids = field.getKids();
- if (kids != null) {
- for (int k = 0; k < kids.size(); ++k)
- expandFields((PdfFormField)kids.get(k), allAnnots);
- }
- }
-
- void addAnnotation(PdfAnnotation annot, PdfDictionary pageN) {
- try {
- ArrayList allAnnots = new ArrayList();
- if (annot.isForm()) {
- fieldsAdded = true;
- getAcroFields();
- PdfFormField field = (PdfFormField)annot;
- if (field.getParent() != null)
- return;
- expandFields(field, allAnnots);
- }
- else
- allAnnots.add(annot);
- for (int k = 0; k < allAnnots.size(); ++k) {
- annot = (PdfAnnotation)allAnnots.get(k);
- if (annot.getPlaceInPage() > 0)
- pageN = reader.getPageN(annot.getPlaceInPage());
- if (annot.isForm()) {
- if (!annot.isUsed()) {
- HashMap templates = annot.getTemplates();
- if (templates != null)
- fieldTemplates.putAll(templates);
- }
- PdfFormField field = (PdfFormField)annot;
- if (field.getParent() == null)
- addDocumentField(field.getIndirectReference());
- }
- if (annot.isAnnotation()) {
- PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageN.get(PdfName.ANNOTS), pageN);
- if (annots == null) {
- annots = new PdfArray();
- pageN.put(PdfName.ANNOTS, annots);
- markUsed(pageN);
- }
- annots.add(annot.getIndirectReference());
- markUsed(annots);
- if (!annot.isUsed()) {
- PdfRectangle rect = (PdfRectangle)annot.get(PdfName.RECT);
- if (rect != null && (rect.left() != 0 || rect.right() != 0 || rect.top() != 0 || rect.bottom() != 0)) {
- int rotation = reader.getPageRotation(pageN);
- Rectangle pageSize = reader.getPageSizeWithRotation(pageN);
- switch (rotation) {
- case 90:
- annot.put(PdfName.RECT, new PdfRectangle(
- pageSize.top() - rect.bottom(),
- rect.left(),
- pageSize.top() - rect.top(),
- rect.right()));
- break;
- case 180:
- annot.put(PdfName.RECT, new PdfRectangle(
- pageSize.right() - rect.left(),
- pageSize.top() - rect.bottom(),
- pageSize.right() - rect.right(),
- pageSize.top() - rect.top()));
- break;
- case 270:
- annot.put(PdfName.RECT, new PdfRectangle(
- rect.bottom(),
- pageSize.right() - rect.left(),
- rect.top(),
- pageSize.right() - rect.right()));
- break;
- }
- }
- }
- }
- if (!annot.isUsed()) {
- annot.setUsed();
- addToBody(annot, annot.getIndirectReference());
- }
- }
- }
- catch (IOException e) {
- throw new ExceptionConverter(e);
- }
- }
-
- void addAnnotation(PdfAnnotation annot, int page) {
- addAnnotation(annot, reader.getPageN(page));
- }
-
- private void outlineTravel(PRIndirectReference outline) {
- while (outline != null) {
- PdfDictionary outlineR = (PdfDictionary)PdfReader.getPdfObjectRelease(outline);
- PRIndirectReference first = (PRIndirectReference)outlineR.get(PdfName.FIRST);
- if (first != null) {
- outlineTravel(first);
- }
- PdfReader.killIndirect(outlineR.get(PdfName.DEST));
- PdfReader.killIndirect(outlineR.get(PdfName.A));
- PdfReader.killIndirect(outline);
- outline = (PRIndirectReference)outlineR.get(PdfName.NEXT);
- }
- }
-
- void deleteOutlines() {
- PdfDictionary catalog = reader.getCatalog();
- PRIndirectReference outlines = (PRIndirectReference)catalog.get(PdfName.OUTLINES);
- if (outlines == null)
- return;
- outlineTravel(outlines);
- PdfReader.killIndirect(outlines);
- catalog.remove(PdfName.OUTLINES);
- markUsed(catalog);
- }
-
- void setJavaScript() throws IOException {
- ArrayList djs = pdf.getDocumentJavaScript();
- if (djs.size() == 0)
- return;
- PdfDictionary catalog = reader.getCatalog();
- PdfDictionary names = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.NAMES), catalog);
- if (names == null) {
- names = new PdfDictionary();
- catalog.put(PdfName.NAMES, names);
- markUsed(catalog);
- }
- markUsed(names);
- String s = String.valueOf(djs.size() - 1);
- int n = s.length();
- String pad = "000000000000000";
- HashMap maptree = new HashMap();
- for (int k = 0; k < djs.size(); ++k) {
- s = String.valueOf(k);
- s = pad.substring(0, n - s.length()) + s;
- maptree.put(s, djs.get(k));
- }
- PdfDictionary tree = PdfNameTree.writeTree(maptree, this);
- names.put(PdfName.JAVASCRIPT, addToBody(tree).getIndirectReference());
- }
-
- void setOutlines() throws IOException {
- if (newBookmarks == null)
- return;
- deleteOutlines();
- if (newBookmarks.size() == 0)
- return;
- namedAsNames = (reader.getCatalog().get(PdfName.DESTS) != null);
- PdfDictionary top = new PdfDictionary();
- PdfIndirectReference topRef = getPdfIndirectReference();
- Object kids[] = SimpleBookmark.iterateOutlines(this, topRef, newBookmarks, namedAsNames);
- top.put(PdfName.FIRST, (PdfIndirectReference)kids[0]);
- top.put(PdfName.LAST, (PdfIndirectReference)kids[1]);
- top.put(PdfName.COUNT, new PdfNumber(((Integer)kids[2]).intValue()));
- addToBody(top, topRef);
- reader.getCatalog().put(PdfName.OUTLINES, topRef);
- markUsed(reader.getCatalog());
- }
-
- void setOutlines(List outlines) {
- newBookmarks = outlines;
- }
-
- /**
- * Sets the viewer preferences.
- * @param preferences the viewer preferences
- * @see PdfWriter#setViewerPreferences(int)
- */
- public void setViewerPreferences(int preferences) {
- useVp = true;
- vp |= preferences;
- }
-
- /**
- * Set the signature flags.
- * @param f the flags. This flags are ORed with current ones
- */
- public void setSigFlags(int f) {
- sigFlags |= f;
- }
-
- /** Always throws an UnsupportedOperationException
.
- * @param actionType ignore
- * @param action ignore
- * @throws PdfException ignore
- * @see PdfStamper#setPageAction(PdfName, PdfAction, int)
- */
- public void setPageAction(PdfName actionType, PdfAction action) throws PdfException {
- throw new UnsupportedOperationException("Use setPageAction(PdfName actionType, PdfAction action, int page)");
- }
-
- /**
- * Sets the open and close page additional action.
- * @param actionType the action type. It can be PdfWriter.PAGE_OPEN
- * or PdfWriter.PAGE_CLOSE
- * @param action the action to perform
- * @param page the page where the action will be applied. The first page is 1
- * @throws PdfException if the action type is invalid
- */
- void setPageAction(PdfName actionType, PdfAction action, int page) throws PdfException {
- if (!actionType.equals(PAGE_OPEN) && !actionType.equals(PAGE_CLOSE))
- throw new PdfException("Invalid page additional action type: " + actionType.toString());
- PdfDictionary pg = reader.getPageN(page);
- PdfDictionary aa = (PdfDictionary)PdfReader.getPdfObject(pg.get(PdfName.AA), pg);
- if (aa == null) {
- aa = new PdfDictionary();
- pg.put(PdfName.AA, aa);
- markUsed(pg);
- }
- aa.put(actionType, action);
- markUsed(aa);
- }
-
- /**
- * Always throws an UnsupportedOperationException
.
- * @param seconds ignore
- */
- public void setDuration(int seconds) {
- throw new UnsupportedOperationException("Use setPageAction(PdfName actionType, PdfAction action, int page)");
- }
-
- /**
- * Always throws an UnsupportedOperationException
.
- * @param transition ignore
- */
- public void setTransition(PdfTransition transition) {
- throw new UnsupportedOperationException("Use setPageAction(PdfName actionType, PdfAction action, int page)");
- }
-
- /**
- * Sets the display duration for the page (for presentations)
- * @param seconds the number of seconds to display the page. A negative value removes the entry
- * @param page the page where the duration will be applied. The first page is 1
- */
- void setDuration(int seconds, int page) {
- PdfDictionary pg = reader.getPageN(page);
- if (seconds < 0)
- pg.remove(PdfName.DUR);
- else
- pg.put(PdfName.DUR, new PdfNumber(seconds));
- markUsed(pg);
- }
-
- /**
- * Sets the transition for the page
- * @param transition the transition object. A null
removes the transition
- * @param page the page where the transition will be applied. The first page is 1
- */
- void setTransition(PdfTransition transition, int page) {
- PdfDictionary pg = reader.getPageN(page);
- if (transition == null)
- pg.remove(PdfName.TRANS);
- else
- pg.put(PdfName.TRANS, transition.getTransitionDictionary());
- markUsed(pg);
- }
-
- protected void markUsed(PdfObject obj) {
- if (append && obj != null) {
- PRIndirectReference ref = null;
- if (obj.type() == PdfObject.INDIRECT)
- ref = (PRIndirectReference)obj;
- else
- ref = obj.getIndRef();
- if (ref != null)
- marked.put(ref.getNumber(), 1);
- }
- }
-
- protected void markUsed(int num) {
- if (append)
- marked.put(num, 1);
- }
-
- /**
- * Getter for property append.
- * @return Value of property append.
- */
- boolean isAppend() {
- return append;
- }
-
- /** Additional-actions defining the actions to be taken in
- * response to various trigger events affecting the document
- * as a whole. The actions types allowed are: DOCUMENT_CLOSE
,
- * WILL_SAVE
, DID_SAVE
, WILL_PRINT
- * and DID_PRINT
.
- *
- * @param actionType the action type
- * @param action the action to execute in response to the trigger
- * @throws PdfException on invalid action type
- */
- public void setAdditionalAction(PdfName actionType, PdfAction action) throws PdfException {
- if (!(actionType.equals(DOCUMENT_CLOSE) ||
- actionType.equals(WILL_SAVE) ||
- actionType.equals(DID_SAVE) ||
- actionType.equals(WILL_PRINT) ||
- actionType.equals(DID_PRINT))) {
- throw new PdfException("Invalid additional action type: " + actionType.toString());
- }
- PdfDictionary aa = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.AA));
- if (aa == null) {
- if (action == null)
- return;
- aa = new PdfDictionary();
- reader.getCatalog().put(PdfName.AA, aa);
- }
- markUsed(aa);
- if (action == null)
- aa.remove(actionType);
- else
- aa.put(actionType, action);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfWriter#setOpenAction(com.lowagie.text.pdf.PdfAction)
- */
- public void setOpenAction(PdfAction action) {
- openAction = action;
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfWriter#setOpenAction(java.lang.String)
- */
- public void setOpenAction(String name) {
- throw new UnsupportedOperationException("Open actions by name are not supported.");
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfWriter#setThumbnail(com.lowagie.text.Image)
- */
- /* ssteward: dropped in 1.44
- public void setThumbnail(com.lowagie.text.Image image) {
- throw new UnsupportedOperationException("Use PdfStamper.setThumbnail().");
- }
-
- void setThumbnail(Image image, int page) throws PdfException, DocumentException {
- PdfIndirectReference thumb = getImageReference(addDirectImageSimple(image));
- reader.resetReleasePage();
- PdfDictionary dic = reader.getPageN(page);
- dic.put(PdfName.THUMB, thumb);
- reader.resetReleasePage();
- }
- */
-
- static class PageStamp {
-
- PdfDictionary pageN;
- StampContent under;
- StampContent over;
- PageResources pageResources;
-
- PageStamp(PdfStamperImp stamper, PdfReader reader, PdfDictionary pageN) {
- this.pageN = pageN;
- pageResources = new PageResources();
- PdfDictionary resources = (PdfDictionary)PdfReader.getPdfObject(pageN.get(PdfName.RESOURCES));
- pageResources.setOriginalResources(resources, stamper.namePtr);
- }
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfStream.java pdftk-2.01/java/com/lowagie/text/pdf/PdfStream.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfStream.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,320 +0,0 @@
-/*
- * $Id: PdfStream.java,v 1.53 2004/12/14 15:15:59 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.util.zip.DeflaterOutputStream;
-import java.util.zip.Deflater;
-import com.lowagie.text.Document;
-import com.lowagie.text.DocWriter;
-import com.lowagie.text.ExceptionConverter;
-
-/**
- * PdfStream
is the Pdf stream object.
- *
- * A stream, like a string, is a sequence of characters. However, an application can
- * read a small portion of a stream at a time, while a string must be read in its entirety.
- * For this reason, objects with potentially large amounts of data, such as images and
- * page descriptions, are represented as streams.
- * A stream consists of a dictionary that describes a sequence of characters, followed by
- * the keyword stream , followed by zero or more lines of characters, followed by
- * the keyword endstream .
- * All streams must be PdfIndirectObject
s. The stream dictionary must be a direct
- * object. The keyword stream that follows the stream dictionary should be followed by
- * a carriage return and linefeed or just a linefeed.
- * Remark: In this version only the FLATEDECODE-filter is supported.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 4.8 (page 41-53).
- *
- * @see PdfObject
- * @see PdfDictionary
- */
-
-public class PdfStream extends PdfDictionary {
-
- // membervariables
-
-/** is the stream compressed? */
- protected boolean compressed = false;
-
- protected ByteArrayOutputStream streamBytes = null;
- protected InputStream inputStream;
- protected PdfIndirectReference ref;
- protected int inputStreamLength = -1;
- protected PdfWriter writer;
- protected int rawLength;
-
- static final byte STARTSTREAM[] = DocWriter.getISOBytes("\nstream\n"); // ssteward
- static final byte ENDSTREAM[] = DocWriter.getISOBytes("\nendstream "); // ssteward
- static final int SIZESTREAM = STARTSTREAM.length + ENDSTREAM.length;
-
- // constructors
-
-/**
- * Constructs a PdfStream
-object.
- *
- * @param bytes content of the new PdfObject
as an array of byte
.
- */
-
- public PdfStream(byte[] bytes) {
- super();
- type = STREAM;
- this.bytes = bytes;
- rawLength = bytes.length;
- put(PdfName.LENGTH, new PdfNumber(bytes.length));
- }
-
- /**
- * Creates an efficient stream. No temporary array is ever created. The InputStream
- * is totally consumed but is not closed. The general usage is:
- *
- *
- * InputStream in = ...;
- * PdfStream stream = new PdfStream(in, writer);
- * stream.flateCompress();
- * writer.addToBody(stream);
- * stream.writeLength();
- * in.close();
- *
- * @param inputStream the data to write to this stream
- * @param writer the PdfWriter
for this stream
- */
- public PdfStream(InputStream inputStream, PdfWriter writer) {
- super();
- type = STREAM;
- this.inputStream = inputStream;
- this.writer = writer;
- ref = writer.getPdfIndirectReference();
- put(PdfName.LENGTH, ref);
- }
-
-/**
- * Constructs a PdfStream
-object.
- */
-
- protected PdfStream() {
- super();
- type = STREAM;
- }
-
- /**
- * Writes the stream length to the PdfWriter
.
- *
- * This method must be called and can only be called if the contructor {@link #PdfStream(InputStream,PdfWriter)}
- * is used to create the stream.
- * @throws IOException on error
- * @see #PdfStream(InputStream,PdfWriter)
- */
- public void writeLength() throws IOException {
- if (inputStream == null)
- throw new UnsupportedOperationException("writeLength() can only be called in a contructed PdfStream(InputStream,PdfWriter).");
- if (inputStreamLength == -1)
- throw new IOException("writeLength() can only be called after output of the stream body.");
- writer.addToBody(new PdfNumber(inputStreamLength), ref, false);
- }
-
- /**
- * Gets the raw length of the stream.
- * @return the raw length of the stream
- */
- public int getRawLength() {
- return rawLength;
- }
-
- /**
- * Compresses the stream.
- */
-
- public void flateCompress() {
- if (!Document.compress)
- return;
- // check if the flateCompress-method has already been
- if (compressed) {
- return;
- }
- if (inputStream != null) {
- compressed = true;
- return;
- }
- // check if a filter already exists
- PdfObject filter = get(PdfName.FILTER);
- if (filter != null) {
- if (filter.isName() && ((PdfName) filter).compareTo(PdfName.FLATEDECODE) == 0) {
- return;
- }
- else if (filter.isArray() && ((PdfArray) filter).contains(PdfName.FLATEDECODE)) {
- return;
- }
- else {
- throw new RuntimeException("Stream could not be compressed: filter is not a name or array.");
- }
- }
- try {
- // compress
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
- DeflaterOutputStream zip = new DeflaterOutputStream(stream);
- if (streamBytes != null)
- streamBytes.writeTo(zip);
- else
- zip.write(bytes);
- zip.close();
- // update the object
- streamBytes = stream;
- bytes = null;
- put(PdfName.LENGTH, new PdfNumber(streamBytes.size()));
- if (filter == null) {
- put(PdfName.FILTER, PdfName.FLATEDECODE);
- }
- else {
- PdfArray filters = new PdfArray(filter);
- filters.add(PdfName.FLATEDECODE);
- put(PdfName.FILTER, filters);
- }
- compressed = true;
- }
- catch(IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- }
-
-// public int getStreamLength(PdfWriter writer) {
-// if (dicBytes == null)
-// toPdf(writer);
-// if (streamBytes != null)
-// return streamBytes.size() + dicBytes.length + SIZESTREAM;
-// else
-// return bytes.length + dicBytes.length + SIZESTREAM;
-// }
-
- protected void superToPdf(PdfWriter writer, OutputStream os) throws IOException {
- super.toPdf(writer, os);
- }
-
- /**
- * @see com.lowagie.text.pdf.PdfDictionary#toPdf(com.lowagie.text.pdf.PdfWriter, java.io.OutputStream)
- */
- public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
- if (inputStream != null && compressed)
- put(PdfName.FILTER, PdfName.FLATEDECODE);
- superToPdf(writer, os);
- os.write(STARTSTREAM);
- PdfEncryption crypto = null;
- if (writer != null)
- crypto = writer.getEncryption();
- if (crypto != null)
- crypto.prepareKey();
- if (inputStream != null) {
- rawLength = 0;
- DeflaterOutputStream def = null;
- // PdfEncryptionStream encs = null;
- OutputStreamCounter osc = new OutputStreamCounter(os);
- OutputStream fout = osc;
- if (crypto != null)
- fout = new PdfEncryptionStream(fout, crypto);
- if (compressed)
- fout = def = new DeflaterOutputStream(fout, new Deflater(Deflater.BEST_COMPRESSION), 0x8000);
-
- byte buf[] = new byte[0x10000];
- while (true) {
- int n = inputStream.read(buf);
- if (n <= 0)
- break;
- fout.write(buf, 0, n);
- rawLength += n;
- }
- if (def != null)
- def.finish();
- inputStreamLength = osc.getCounter();
- }
- else {
- if (crypto == null) {
- if (streamBytes != null)
- streamBytes.writeTo(os);
- else
- os.write(bytes);
- }
- else {
- byte b[];
- if (streamBytes != null) {
- b = streamBytes.toByteArray();
- crypto.encryptRC4(b);
- }
- else {
- b = new byte[bytes.length];
- crypto.encryptRC4(bytes, b);
- }
- os.write(b);
- }
- }
- os.write(ENDSTREAM);
- }
-
- /**
- * Writes the data content to an OutputStream
.
- * @param os the destination to write to
- * @throws IOException on error
- */
- public void writeContent(OutputStream os) throws IOException {
- if (streamBytes != null)
- streamBytes.writeTo(os);
- else if (bytes != null)
- os.write(bytes);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfString.java pdftk-2.01/java/com/lowagie/text/pdf/PdfString.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfString.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfString.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,356 +0,0 @@
-/*
- * $Id: PdfString.java,v 1.26 2002/07/09 11:28:24 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- * Co-Developer of the code is Sid Steward. Portions created by the Co-Developer
- * are Copyright (C) 2010 by Sid Steward. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import java.io.OutputStream;
-import java.io.IOException;
-
-/**
- * A PdfString
-class is the PDF-equivalent of a JAVA-String
-object.
- *
- * A string is a sequence of characters delimited by parenthesis. If a string is too long
- * to be conveniently placed on a single line, it may be split across multiple lines by using
- * the backslash character (\) at the end of a line to indicate that the string continues
- * on the following line. Within a string, the backslash character is used as an escape to
- * specify unbalanced parenthesis, non-printing ASCII characters, and the backslash character
- * itself. Use of the \ddd escape sequence is the preferred way to represent characters
- * outside the printable ASCII character set.
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 4.4 (page 37-39).
- *
- * @see PdfObject
- * @see BadPdfFormatException
- */
-
-public class PdfString extends PdfObject {
-
- // ssteward: rewrite for pdftk 1.45
- // membervariables
-
- /** The value of this object. */
- protected String value= null; // NOTHING;
- //protected String originalValue = null; // TODO: this might be broken in pdftk 1.45
- protected byte[] originalBytes= null;
-
- /** The encoding. */
- // ssteward
- // the encoding indicates how to encode the data in the PDF file;
- // encodings:
- // null => not set
- // NOTHING => literal bytes; used with hex output
- // TEXT_UNICODE => UTF-16
- // TEXT_PDFDOCENCODING => PdfDoc encoding
- //
- protected String encoding= null;
-
- protected int objNum = 0;
- protected int objGen = 0;
- protected boolean hexWriting = false;
-
- // constructors
-
- /**
- * Constructs an empty PdfString
-object.
- */
-
- public PdfString() {
- super( STRING );
- }
-
- /**
- * Constructs a PdfString
-object.
- *
- * @param value the content of the string
- */
-
- // ssteward: rewrite for pdftk 1.45
- public PdfString( String value ) {
- super( STRING );
- this.value= value;
- this.bytes= getBytes();
- }
-
- /**
- * Constructs a PdfString
-object.
- *
- * @param value the content of the string
- * @param encoding an encoding
- */
-
- // ssteward: rewrite for pdftk 1.45
- public PdfString( String value, String encoding ) {
- super( STRING );
- this.encoding= encoding;
- this.value= value;
- this.bytes= getBytes();
- }
-
- /**
- * Constructs a PdfString
-object.
- *
- * @param bytes an array of byte
- */
-
- // construct from bytes, not value;
- // ssteward: rewrite for pdftk 1.45
- public PdfString( byte[] bytes, String encoding ) {
- super( STRING );
- this.encoding= encoding;
- this.bytes= bytes;
- this.value= getValue();
- }
-
- // ssteward: rewrite for pdftk 1.45
- public PdfString( byte[] bytes ) {
- super( STRING );
- this.bytes= bytes;
- this.value= getValue();
- }
-
-
-
- // methods overriding some methods in PdfObject
-
- /**
- * Returns the PDF representation of this PdfString
.
- *
- * @return an array of byte
s
- */
-
- public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
- byte b[] = getBytes();
- PdfEncryption crypto = null;
- if (writer != null)
- crypto = writer.getEncryption();
- if (crypto != null) {
- b = (byte[])bytes.clone();
- crypto.prepareKey();
- crypto.encryptRC4(b);
- }
- if (hexWriting) {
- ByteBuffer buf = new ByteBuffer();
- buf.append('<');
- int len = b.length;
- for (int k = 0; k < len; ++k)
- buf.appendHex(b[k]);
- buf.append('>');
- os.write(buf.toByteArray());
- }
- else
- os.write(PdfContentByte.escapeString(b));
- }
-
- /**
- * Returns the String
value of the PdfString
-object.
- *
- * @return a String
- */
- public String toString() {
- return value;
- }
-
- // other methods
-
- /**
- * Gets the encoding of this string.
- *
- * @return a String
- */
-
- public String getEncoding() {
- return encoding;
- }
-
- // ssteward: rewrite for pdftk 1.45
- public String toUnicodeString() {
- // value should be unicode
- /*
- //getBytes();
- if( bytes== null ) {
- System.err.println( "bytes==null" );
- if( encoding== NOTHING || encoding== null ) {
- System.err.println( "encoding=="+ encoding );
- if( PdfEncodings.isPdfDocEncoding(value) ) {
- encoding= TEXT_PDFDOCENCODING;
- System.err.println( "encoding==TEXT_PDFDOCENCODING "+ encoding );
- }
- else {
- encoding= TEXT_UNICODE;
- System.err.println( "encoding==TEXT_UNICODE "+ encoding );
- }
- }
- bytes= PdfEncodings.convertToBytes( value, encoding );
- }
- */
- //value= PdfEncodings.convertToString(bytes, PdfObject.TEXT_PDFDOCENCODING);
-
- //System.err.println( value );
- //System.err.println( encoding );
- return value;
-
- /*
- // if encoding is set, then the value is unicode, right? seems like flimsy logic;
- // let's see... encoding can only be set by the (String, encoding) constructor, so I guess
- // this works; it can also be set in getBytes(), which tries to detect a suitable
- // encoding;
- if( encoding== null || encoding== NOTHING ) {
- getBytes();
- if (bytes.length >= 2 && bytes[0] == (byte)254 && bytes[1] == (byte)255) {
-
- // ssteward
- // pdftk-0.94: trim off these signature bytes (problem reading bookmarks);
- // pdftk-1.00: still an issue; problem reading EmbeddedFiles name tree keys,
- // see PdfNameTree::iterateItems(); resulted in an extra null char at end of string
- byte b_copy[]= new byte[bytes.length- 2];
- System.arraycopy( bytes, 2, b_copy, 0, b_copy.length );
-
- //return PdfEncodings.convertToString(bytes, PdfObject.TEXT_UNICODE);
- value= PdfEncodings.convertToString(b_copy, PdfObject.TEXT_UNICODE);
- }
- else
- value= PdfEncodings.convertToString(bytes, PdfObject.TEXT_PDFDOCENCODING);
- }
- return value;
- */
- }
-
- void setObjNum(int objNum, int objGen) {
- this.objNum = objNum;
- this.objGen = objGen;
- }
-
- // ssteward: rewrite for pdftk 1.45
- void decrypt(PdfReader reader) {
- PdfEncryption decrypt = reader.getDecrypt();
- if (decrypt != null) {
- //originalValue = value;
- decrypt.setHashKey(objNum, objGen);
- decrypt.prepareKey();
- //bytes = PdfEncodings.convertToBytes(value, null);
- originalBytes= bytes;
- decrypt.encryptRC4(bytes);
- //value = PdfEncodings.convertToString(bytes, null);
- value= getValue();
- }
- }
-
- // sets bytes and encoding based on value, if necessary
- // ssteward: rewrite for pdftk 1.45
- public byte[] getBytes() {
- if( bytes== null && value!= null ) {
- if( encoding== null ) {
- if( PdfEncodings.isPdfDocEncoding(value) ) {
- encoding= TEXT_PDFDOCENCODING;
- }
- else {
- encoding= TEXT_UNICODE;
- }
- }
- bytes= PdfEncodings.convertToBytes( value, encoding );
- }
- return bytes;
- }
-
- // ssteward: added for pdftk 1.45
- private String getValue() {
- if( value== null && bytes!= null ) {
- if( encoding== null ) {
- //if( bytes.length>= 2 && bytes[0]== (byte)254 && bytes[1]== (byte)255 ) {
- if( isUnicode( bytes ) ) {
- encoding= TEXT_UNICODE;
- }
- else {
- encoding= TEXT_PDFDOCENCODING;
- }
- }
- value= PdfEncodings.convertToString( bytes, encoding );
- }
- return this.value;
- }
-
- // ssteward: rewrite for pdftk 1.45
- public byte[] getOriginalBytes() {
- if( originalBytes!= null ) {
- return originalBytes;
- }
- //return getBytes();
- //return PdfEncodings.convertToBytes(originalValue, null);
- return bytes;
- }
-
- public PdfString setHexWriting(boolean hexWriting) {
- this.hexWriting = hexWriting;
- return this;
- }
-
- public boolean isHexWriting() {
- return hexWriting;
- }
-
- /*
- public boolean isUnicode() {
- //getBytes();
- return( bytes.length >= 2 && bytes[0] == (byte)254 && bytes[1] == (byte)255 );
- }
- */
-
- // ssteward: rewrite for pdftk 1.45
- public static boolean isUnicode( byte[] bb ) {
- return( bb.length >= 2 && bb[0] == (byte)254 && bb[1] == (byte)255 );
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfStructureElement.java pdftk-2.01/java/com/lowagie/text/pdf/PdfStructureElement.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfStructureElement.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfStructureElement.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,137 +0,0 @@
-/*
- * $Id: PRTokeniser.java,v 1.15 2002/06/20 13:30:25 blowagie Exp $
- *
- * Copyright 2005 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-//import java.util.ArrayList;
-/**
- * This is a node in a document logical structure. It may contain a mark point or it may contain
- * other nodes.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfStructureElement extends PdfDictionary {
-
- /**
- * Holds value of property kids.
- */
- private PdfStructureElement parent;
- private PdfStructureTreeRoot top;
-
- /**
- * Holds value of property reference.
- */
- private PdfIndirectReference reference;
-
- /**
- * Creates a new instance of PdfStructureElement.
- * @param parent the parent of this node
- * @param structureType the type of structure. It may be a standard type or a user type mapped by the role map
- */
- public PdfStructureElement(PdfStructureElement parent, PdfName structureType) {
- top = parent.top;
- init(parent, structureType);
- this.parent = parent;
- put(PdfName.P, parent.reference);
- }
-
- /**
- * Creates a new instance of PdfStructureElement.
- * @param parent the parent of this node
- * @param structureType the type of structure. It may be a standard type or a user type mapped by the role map
- */
- public PdfStructureElement(PdfStructureTreeRoot parent, PdfName structureType) {
- top = parent;
- init(parent, structureType);
- put(PdfName.P, parent.getReference());
- }
-
- private void init(PdfDictionary parent, PdfName structureType) {
- PdfObject kido = parent.get(PdfName.K);
- PdfArray kids = null;
- if (kido != null && !kido.isArray())
- throw new IllegalArgumentException("The parent has already another function.");
- if (kido == null) {
- kids = new PdfArray();
- parent.put(PdfName.K, kids);
- }
- else
- kids = (PdfArray)kido;
- kids.add(this);
- put(PdfName.S, structureType);
- reference = top.getWriter().getPdfIndirectReference();
- }
-
- /**
- * Gets the parent of this node.
- * @return the parent of this node
- */
- public PdfDictionary getParent() {
- return parent;
- }
-
- void setPageMark(int page, int mark) {
- if (mark >= 0)
- put(PdfName.K, new PdfNumber(mark));
- top.setPageMark(page, reference);
- }
-
- /**
- * Gets the reference this object will be written to.
- * @return the reference this object will be written to
- */
- public PdfIndirectReference getReference() {
- return this.reference;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfStructureTreeRoot.java pdftk-2.01/java/com/lowagie/text/pdf/PdfStructureTreeRoot.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfStructureTreeRoot.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfStructureTreeRoot.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,152 +0,0 @@
-/*
- * $Id: PRTokeniser.java,v 1.15 2002/06/20 13:30:25 blowagie Exp $
- *
- * Copyright 2005 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.io.IOException;
-
-/**
- * The structure tree root corresponds to the highest hierarchy level in a tagged PDF.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfStructureTreeRoot extends PdfDictionary {
-
- private HashMap parentTree = new HashMap();
- private PdfIndirectReference reference;
-
- /**
- * Holds value of property writer.
- */
- private PdfWriter writer;
-
- /** Creates a new instance of PdfStructureTreeRoot */
- PdfStructureTreeRoot(PdfWriter writer) {
- super(PdfName.STRUCTTREEROOT);
- this.writer = writer;
- reference = writer.getPdfIndirectReference();
- }
-
- /**
- * Maps the user tags to the standard tags. The mapping will allow a standard application to make some sense of the tagged
- * document whatever the user tags may be.
- * @param used the user tag
- * @param standard the standard tag
- */
- public void mapRole(PdfName used, PdfName standard) {
- PdfDictionary rm = (PdfDictionary)get(PdfName.ROLEMAP);
- if (rm == null) {
- rm = new PdfDictionary();
- put(PdfName.ROLEMAP, rm);
- }
- rm.put(used, standard);
- }
-
- /**
- * Gets the writer.
- * @return the writer
- */
- public PdfWriter getWriter() {
- return this.writer;
- }
-
- /**
- * Gets the reference this object will be written to.
- * @return the reference this object will be written to
- */
- public PdfIndirectReference getReference() {
- return this.reference;
- }
-
- void setPageMark(int page, PdfIndirectReference struc) {
- Integer i = new Integer(page);
- PdfArray ar = (PdfArray)parentTree.get(i);
- if (ar == null) {
- ar = new PdfArray();
- parentTree.put(i, ar);
- }
- ar.add(struc);
- }
-
- private void nodeProcess(PdfDictionary struc, PdfIndirectReference reference) throws IOException {
- PdfObject obj = struc.get(PdfName.K);
- if (obj != null && obj.isArray() && !((PdfObject)((PdfArray)obj).getArrayList().get(0)).isNumber()) {
- PdfArray ar = (PdfArray)obj;
- ArrayList a = ar.getArrayList();
- for (int k = 0; k < a.size(); ++k) {
- PdfStructureElement e = (PdfStructureElement)a.get(k);
- a.set(k, e.getReference());
- nodeProcess(e, e.getReference());
- }
- }
- if (reference != null)
- writer.addToBody(struc, reference);
- }
-
- void buildTree() throws IOException {
- HashMap numTree = new HashMap();
- for (Iterator it = parentTree.keySet().iterator(); it.hasNext();) {
- Integer i = (Integer)it.next();
- PdfArray ar = (PdfArray)parentTree.get(i);
- numTree.put(i, writer.addToBody(ar).getIndirectReference());
- }
- PdfDictionary dicTree = PdfNumberTree.writeTree(numTree, writer);
- if (dicTree != null)
- put(PdfName.PARENTTREE, writer.addToBody(dicTree).getIndirectReference());
-
- nodeProcess(this, reference);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfTemplate.java pdftk-2.01/java/com/lowagie/text/pdf/PdfTemplate.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfTemplate.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfTemplate.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,273 +0,0 @@
-/*
- * $Id: PdfTemplate.java,v 1.36 2003/05/02 09:01:28 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-import java.io.IOException;
-
-import com.lowagie.text.Rectangle;
-
-/**
- * Implements the form XObject.
- */
-
-public class PdfTemplate extends PdfContentByte {
- public static final int TYPE_TEMPLATE = 1;
- public static final int TYPE_IMPORTED = 2;
- public static final int TYPE_PATTERN = 3;
- protected int type;
- /** The indirect reference to this template */
- protected PdfIndirectReference thisReference;
-
- /** The resources used by this template */
- protected PageResources pageResources;
-
-
- /** The bounding box of this template */
- protected Rectangle bBox = new Rectangle(0, 0);
-
- protected PdfArray matrix;
-
- protected PdfTransparencyGroup group;
-
- protected PdfOCG layer;
-
- /**
- *Creates a PdfTemplate
.
- */
-
- protected PdfTemplate() {
- super(null);
- type = TYPE_TEMPLATE;
- }
-
- /**
- * Creates new PdfTemplate
- *
- * @param wr the PdfWriter
- */
-
- PdfTemplate(PdfWriter wr) {
- super(wr);
- type = TYPE_TEMPLATE;
- pageResources = new PageResources();
- pageResources.addDefaultColor(wr.getDefaultColorspace());
- thisReference = writer.getPdfIndirectReference();
- }
-
- /**
- * Sets the bounding width of this template.
- *
- * @param width the bounding width
- */
-
- public void setWidth(float width) {
- bBox.setLeft(0);
- bBox.setRight(width);
- }
-
- /**
- * Sets the bounding heigth of this template.
- *
- * @param height the bounding height
- */
-
- public void setHeight(float height) {
- bBox.setBottom(0);
- bBox.setTop(height);
- }
-
- /**
- * Gets the bounding width of this template.
- *
- * @return width the bounding width
- */
- public float getWidth() {
- return bBox.width();
- }
-
- /**
- * Gets the bounding heigth of this template.
- *
- * @return heigth the bounding height
- */
-
- public float getHeight() {
- return bBox.height();
- }
-
- public Rectangle getBoundingBox() {
- return bBox;
- }
-
- public void setBoundingBox(Rectangle bBox) {
- this.bBox = bBox;
- }
-
- /**
- * Sets the layer this template belongs to.
- * @param layer the layer this template belongs to
- */
- public void setLayer(PdfOCG layer) {
- this.layer = layer;
- }
-
- /**
- * Gets the layer this template belongs to.
- * @return the layer this template belongs to or null
for no layer defined
- */
- public PdfOCG getLayer() {
- return layer;
- }
-
- public void setMatrix(float a, float b, float c, float d, float e, float f) {
- matrix = new PdfArray();
- matrix.add(new PdfNumber(a));
- matrix.add(new PdfNumber(b));
- matrix.add(new PdfNumber(c));
- matrix.add(new PdfNumber(d));
- matrix.add(new PdfNumber(e));
- matrix.add(new PdfNumber(f));
- }
-
- PdfArray getMatrix() {
- return matrix;
- }
-
- /**
- * Gets the indirect reference to this template.
- *
- * @return the indirect reference to this template
- */
-
- PdfIndirectReference getIndirectReference() {
- return thisReference;
- }
-
- public void beginVariableText() {
- content.append("/Tx BMC ");
- }
-
- public void endVariableText() {
- content.append("EMC ");
- }
-
- /**
- * Constructs the resources used by this template.
- *
- * @return the resources used by this template
- */
-
- PdfObject getResources() {
- return getPageResources().getResources();
- }
-
- /**
- * Gets the stream representing this template.
- *
- * @return the stream representing this template
- */
-
- PdfStream getFormXObject() throws IOException {
- return new PdfFormXObject(this);
- }
-
- /**
- * Gets a duplicate of this PdfTemplate
. All
- * the members are copied by reference but the buffer stays different.
- * @return a copy of this PdfTemplate
- */
-
- public PdfContentByte getDuplicate() {
- PdfTemplate tpl = new PdfTemplate();
- tpl.writer = writer;
- tpl.pdf = pdf;
- tpl.thisReference = thisReference;
- tpl.pageResources = pageResources;
- tpl.bBox = new Rectangle(bBox);
- tpl.group = group;
- tpl.layer = layer;
- if (matrix != null) {
- tpl.matrix = new PdfArray(matrix);
- }
- tpl.separator = separator;
- return tpl;
- }
-
- public int getType() {
- return type;
- }
-
- PageResources getPageResources() {
- return pageResources;
- }
-
- /** Getter for property group.
- * @return Value of property group.
- *
- */
- public PdfTransparencyGroup getGroup() {
- return this.group;
- }
-
- /** Setter for property group.
- * @param group New value of property group.
- *
- */
- public void setGroup(PdfTransparencyGroup group) {
- this.group = group;
- }
-
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfTextArray.java pdftk-2.01/java/com/lowagie/text/pdf/PdfTextArray.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfTextArray.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfTextArray.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,105 +0,0 @@
-/*
- * $Id: PdfTextArray.java,v 1.24 2002/07/09 11:28:24 blowagie Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.util.ArrayList;
-
-/**
- * PdfTextArray
defines an array with displacements and PdfString
-objects.
- *
- * A TextArray
is used with the operator TJ in PdfText
.
- * The first object in this array has to be a PdfString
;
- * see reference manual version 1.3 section 8.7.5, pages 346-347.
- */
-
-public class PdfTextArray{
- ArrayList arrayList = new ArrayList();
- // constructors
-
-
- public PdfTextArray(String str) {
- arrayList.add(str);
- }
-
- public PdfTextArray() {
- }
-
-/**
- * Adds a PdfNumber
to the PdfArray
.
- *
- * @param number displacement of the string
- */
-
- public void add(PdfNumber number)
- {
- arrayList.add(new Float(number.doubleValue()));
- }
-
- public void add(float number)
- {
- arrayList.add(new Float(number));
- }
-
- public void add(String str)
- {
- arrayList.add(str);
- }
-
- ArrayList getArrayList() {
- return arrayList;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfTransition.java pdftk-2.01/java/com/lowagie/text/pdf/PdfTransition.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfTransition.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfTransition.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,259 +0,0 @@
-/*
- * Copyright 2002 by Josselin PUJO.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-public class PdfTransition {
- /**
- * Out Vertical Split
- */
- public static final int SPLITVOUT = 1;
- /**
- * Out Horizontal Split
- */
- public static final int SPLITHOUT = 2;
- /**
- * In Vertical Split
- */
- public static final int SPLITVIN = 3;
- /**
- * IN Horizontal Split
- */
- public static final int SPLITHIN = 4;
- /**
- * Vertical Blinds
- */
- public static final int BLINDV = 5;
- /**
- * Vertical Blinds
- */
- public static final int BLINDH = 6;
- /**
- * Inward Box
- */
- public static final int INBOX = 7;
- /**
- * Outward Box
- */
- public static final int OUTBOX = 8;
- /**
- * Left-Right Wipe
- */
- public static final int LRWIPE = 9;
- /**
- * Right-Left Wipe
- */
- public static final int RLWIPE = 10;
- /**
- * Bottom-Top Wipe
- */
- public static final int BTWIPE = 11;
- /**
- * Top-Bottom Wipe
- */
- public static final int TBWIPE = 12;
- /**
- * Dissolve
- */
- public static final int DISSOLVE = 13;
- /**
- * Left-Right Glitter
- */
- public static final int LRGLITTER = 14;
- /**
- * Top-Bottom Glitter
- */
- public static final int TBGLITTER = 15;
- /**
- * Diagonal Glitter
- */
- public static final int DGLITTER = 16;
-
- /**
- * duration of the transition effect
- */
- protected int duration;
- /**
- * type of the transition effect
- */
- protected int type;
-
- /**
- * Constructs a Transition
.
- *
- */
- public PdfTransition() {
- this(BLINDH);
- }
-
- /**
- * Constructs a Transition
.
- *
- *@param type type of the transition effect
- */
- public PdfTransition(int type) {
- this(type,1);
- }
-
- /**
- * Constructs a Transition
.
- *
- *@param type type of the transition effect
- *@param duration duration of the transition effect
- */
- public PdfTransition(int type, int duration) {
- this.duration = duration;
- this.type = type;
- }
-
-
- public int getDuration() {
- return duration;
- }
-
-
- public int getType() {
- return type;
- }
-
- public PdfDictionary getTransitionDictionary() {
- PdfDictionary trans = new PdfDictionary(PdfName.TRANS);
- switch (type) {
- case SPLITVOUT:
- trans.put(PdfName.S,PdfName.SPLIT);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DM,PdfName.V);
- trans.put(PdfName.M,PdfName.O);
- break;
- case SPLITHOUT:
- trans.put(PdfName.S,PdfName.SPLIT);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DM,PdfName.H);
- trans.put(PdfName.M,PdfName.O);
- break;
- case SPLITVIN:
- trans.put(PdfName.S,PdfName.SPLIT);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DM,PdfName.V);
- trans.put(PdfName.M,PdfName.I);
- break;
- case SPLITHIN:
- trans.put(PdfName.S,PdfName.SPLIT);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DM,PdfName.H);
- trans.put(PdfName.M,PdfName.I);
- break;
- case BLINDV:
- trans.put(PdfName.S,PdfName.BLINDS);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DM,PdfName.V);
- break;
- case BLINDH:
- trans.put(PdfName.S,PdfName.BLINDS);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DM,PdfName.H);
- break;
- case INBOX:
- trans.put(PdfName.S,PdfName.BOX);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.M,PdfName.I);
- break;
- case OUTBOX:
- trans.put(PdfName.S,PdfName.BOX);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.M,PdfName.O);
- break;
- case LRWIPE:
- trans.put(PdfName.S,PdfName.WIPE);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DI,new PdfNumber(0));
- break;
- case RLWIPE:
- trans.put(PdfName.S,PdfName.WIPE);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DI,new PdfNumber(180));
- break;
- case BTWIPE:
- trans.put(PdfName.S,PdfName.WIPE);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DI,new PdfNumber(90));
- break;
- case TBWIPE:
- trans.put(PdfName.S,PdfName.WIPE);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DI,new PdfNumber(270));
- break;
- case DISSOLVE:
- trans.put(PdfName.S,PdfName.DISSOLVE);
- trans.put(PdfName.D,new PdfNumber(duration));
- break;
- case LRGLITTER:
- trans.put(PdfName.S,PdfName.GLITTER);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DI,new PdfNumber(0));
- break;
- case TBGLITTER:
- trans.put(PdfName.S,PdfName.GLITTER);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DI,new PdfNumber(270));
- break;
- case DGLITTER:
- trans.put(PdfName.S,PdfName.GLITTER);
- trans.put(PdfName.D,new PdfNumber(duration));
- trans.put(PdfName.DI,new PdfNumber(315));
- break;
- }
- return trans;
- }
-}
-
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfTransparencyGroup.java pdftk-2.01/java/com/lowagie/text/pdf/PdfTransparencyGroup.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfTransparencyGroup.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfTransparencyGroup.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright 2003 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-/** The transparency group dictionary.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class PdfTransparencyGroup extends PdfDictionary {
-
- /**
- * Constructs a transparencyGroup.
- */
- public PdfTransparencyGroup() {
- super();
- put(PdfName.S, PdfName.TRANSPARENCY);
- }
-
- /**
- * Determining the initial backdrop against which its stack is composited.
- * @param isolated
- */
- public void setIsolated(boolean isolated) {
- if (isolated)
- put(PdfName.I, PdfBoolean.PDFTRUE);
- else
- remove(PdfName.I);
- }
-
- /**
- * Determining whether the objects within the stack are composited with one another or only with the group's backdrop.
- * @param knockout
- */
- public void setKnockout(boolean knockout) {
- if (knockout)
- put(PdfName.K, PdfBoolean.PDFTRUE);
- else
- remove(PdfName.K);
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfWriter.java pdftk-2.01/java/com/lowagie/text/pdf/PdfWriter.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfWriter.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfWriter.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,2714 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- * $Id: PdfWriter.java,v 1.104 2005/09/10 10:52:41 psoares33 Exp $
- * $Name: $
- *
- * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.awt.Color;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.HashSet;
-
-import com.lowagie.text.DocListener;
-import com.lowagie.text.DocWriter;
-import com.lowagie.text.Document;
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.ExceptionConverter;
-// import com.lowagie.text.Image; // ssteward: dropped in 1.44
-// import com.lowagie.text.ImgWMF; // ssteward: dropped in 1.44
-import com.lowagie.text.Rectangle;
-// import com.lowagie.text.Table; ssteward: dropped in 1.44
-// import com.lowagie.text.ImgPostscript; ssteward: dropped in 1.44
-
-/**
- * A DocWriter
class for PDF.
- *
- * When this PdfWriter
is added
- * to a certain PdfDocument
, the PDF representation of every Element
- * added to this Document will be written to the outputstream.
- */
-
-public class PdfWriter extends DocWriter {
-
- // inner classes
-
- /**
- * This class generates the structure of a PDF document.
- *
- * This class covers the third section of Chapter 5 in the 'Portable Document Format
- * Reference Manual version 1.3' (page 55-60). It contains the body of a PDF document
- * (section 5.14) and it can also generate a Cross-reference Table (section 5.15).
- *
- * @see PdfWriter
- * @see PdfObject
- * @see PdfIndirectObject
- */
-
- public static class PdfBody {
-
- // inner classes
-
- /**
- * PdfCrossReference
is an entry in the PDF Cross-Reference table.
- */
-
- static class PdfCrossReference implements Comparable {
-
- // membervariables
- private int type;
-
- /** Byte offset in the PDF file. */
- private int offset;
-
- private int refnum;
- /** generation of the object. */
- private int generation;
-
- // constructors
- /**
- * Constructs a cross-reference element for a PdfIndirectObject.
- * @param refnum
- * @param offset byte offset of the object
- * @param generation generationnumber of the object
- */
-
- PdfCrossReference(int refnum, int offset, int generation) {
- type = 0;
- this.offset = offset;
- this.refnum = refnum;
- this.generation = generation;
- }
-
- /**
- * Constructs a cross-reference element for a PdfIndirectObject.
- * @param refnum
- * @param offset byte offset of the object
- */
-
- PdfCrossReference(int refnum, int offset) {
- type = 1;
- this.offset = offset;
- this.refnum = refnum;
- this.generation = 0;
- }
-
- PdfCrossReference(int type, int refnum, int offset, int generation) {
- this.type = type;
- this.offset = offset;
- this.refnum = refnum;
- this.generation = generation;
- }
-
- int getRefnum() {
- return refnum;
- }
-
- /**
- * Returns the PDF representation of this PdfObject
.
- * @param os
- * @throws IOException
- */
-
- public void toPdf(OutputStream os) throws IOException {
- // This code makes it more difficult to port the lib to JDK1.1.x:
- // StringBuffer off = new StringBuffer("0000000000").append(offset);
- // off.delete(0, off.length() - 10);
- // StringBuffer gen = new StringBuffer("00000").append(generation);
- // gen.delete(0, gen.length() - 5);
- // so it was changed into this:
- String s = "0000000000" + offset;
- StringBuffer off = new StringBuffer(s.substring(s.length() - 10));
- s = "00000" + generation;
- String gen = s.substring(s.length() - 5);
- if (generation == 65535) {
- os.write(getISOBytes(off.append(' ').append(gen).append(" f \n").toString()));
- }
- else
- os.write(getISOBytes(off.append(' ').append(gen).append(" n \n").toString()));
- }
-
- /**
- * Writes PDF syntax to the OutputStream
- * @param midSize
- * @param os
- * @throws IOException
- */
- public void toPdf(int midSize, OutputStream os) throws IOException {
- os.write((byte)type);
- while (--midSize >= 0)
- os.write((byte)((offset >>> (8 * midSize)) & 0xff));
- os.write((byte)((generation >>> 8) & 0xff));
- os.write((byte)(generation & 0xff));
- }
-
- /**
- * @see java.lang.Comparable#compareTo(java.lang.Object)
- */
- public int compareTo(Object o) {
- PdfCrossReference other = (PdfCrossReference)o;
- return (refnum < other.refnum ? -1 : (refnum==other.refnum ? 0 : 1));
- }
-
- /**
- * @see java.lang.Object#equals(java.lang.Object)
- */
- public boolean equals(Object obj) {
- if (obj instanceof PdfCrossReference) {
- PdfCrossReference other = (PdfCrossReference)obj;
- return (refnum == other.refnum);
- }
- else
- return false;
- }
-
- }
-
- // membervariables
-
- /** array containing the cross-reference table of the normal objects. */
- private TreeSet xrefs;
- private int refnum;
- /** the current byteposition in the body. */
- private int position;
- private PdfWriter writer;
- // constructors
-
- /**
- * Constructs a new PdfBody
.
- * @param writer
- */
- PdfBody(PdfWriter writer) {
- xrefs = new TreeSet();
- xrefs.add(new PdfCrossReference(0, 0, 65535));
- position = writer.getOs().getCounter();
- refnum = 1;
- this.writer = writer;
- }
-
- void setRefnum(int refnum) {
- this.refnum = refnum;
- }
-
- // methods
-
- private static final int OBJSINSTREAM = 200;
-
- private ByteBuffer index;
- private ByteBuffer streamObjects;
- private int currentObjNum;
- private int numObj = 0;
-
- private PdfWriter.PdfBody.PdfCrossReference addToObjStm(PdfObject obj, int nObj) throws IOException {
- if (numObj >= OBJSINSTREAM)
- flushObjStm();
- if (index == null) {
- index = new ByteBuffer();
- streamObjects = new ByteBuffer();
- currentObjNum = getIndirectReferenceNumber();
- numObj = 0;
- }
- int p = streamObjects.size();
- int idx = numObj++;
- PdfEncryption enc = writer.crypto;
- writer.crypto = null;
- obj.toPdf(writer, streamObjects);
- writer.crypto = enc;
- streamObjects.append(' ');
- index.append(nObj).append(' ').append(p).append(' ');
- return new PdfWriter.PdfBody.PdfCrossReference(2, nObj, currentObjNum, idx);
- }
-
- private void flushObjStm() throws IOException {
- if (numObj == 0)
- return;
- int first = index.size();
- index.append(streamObjects);
- PdfStream stream = new PdfStream(index.toByteArray());
- stream.flateCompress();
- stream.put(PdfName.TYPE, PdfName.OBJSTM);
- stream.put(PdfName.N, new PdfNumber(numObj));
- stream.put(PdfName.FIRST, new PdfNumber(first));
- add(stream, currentObjNum);
- index = null;
- streamObjects = null;
- numObj = 0;
- }
-
- /**
- * Adds a PdfObject
to the body.
- *
- * This methods creates a PdfIndirectObject
with a
- * certain number, containing the given PdfObject
.
- * It also adds a PdfCrossReference
for this object
- * to an ArrayList
that will be used to build the
- * Cross-reference Table.
- *
- * @param object a PdfObject
- * @return a PdfIndirectObject
- * @throws IOException
- */
-
- PdfIndirectObject add(PdfObject object) throws IOException {
- return add(object, getIndirectReferenceNumber());
- }
-
- PdfIndirectObject add(PdfObject object, boolean inObjStm) throws IOException {
- return add(object, getIndirectReferenceNumber(), inObjStm);
- }
-
- /**
- * Gets a PdfIndirectReference for an object that will be created in the future.
- * @return a PdfIndirectReference
- */
-
- PdfIndirectReference getPdfIndirectReference() {
- return new PdfIndirectReference(0, getIndirectReferenceNumber());
- }
-
- int getIndirectReferenceNumber() {
- int n = refnum++;
- xrefs.add(new PdfCrossReference(n, 0, 65536));
- return n;
- }
-
- /**
- * Adds a PdfObject
to the body given an already existing
- * PdfIndirectReference.
- *
- * This methods creates a PdfIndirectObject
with the number given by
- * ref
, containing the given PdfObject
.
- * It also adds a PdfCrossReference
for this object
- * to an ArrayList
that will be used to build the
- * Cross-reference Table.
- *
- * @param object a PdfObject
- * @param ref a PdfIndirectReference
- * @return a PdfIndirectObject
- * @throws IOException
- */
-
- PdfIndirectObject add(PdfObject object, PdfIndirectReference ref) throws IOException {
- return add(object, ref.getNumber());
- }
-
- PdfIndirectObject add(PdfObject object, PdfIndirectReference ref, boolean inObjStm) throws IOException {
- return add(object, ref.getNumber(), inObjStm);
- }
-
- PdfIndirectObject add(PdfObject object, int refNumber) throws IOException {
- return add(object, refNumber, true); // to false
- }
-
- PdfIndirectObject add(PdfObject object, int refNumber, boolean inObjStm) throws IOException {
- if (inObjStm && object.canBeInObjStm() && writer.isFullCompression()) {
- PdfCrossReference pxref = addToObjStm(object, refNumber);
- PdfIndirectObject indirect = new PdfIndirectObject(refNumber, object, writer);
- if (!xrefs.add(pxref)) {
- xrefs.remove(pxref);
- xrefs.add(pxref);
- }
- return indirect;
- }
- else {
- PdfIndirectObject indirect = new PdfIndirectObject(refNumber, object, writer);
- writer.getOs().write('\n'); // ssteward: for pretty pdf
- PdfCrossReference pxref = new PdfCrossReference(refNumber, position+ 1); // ssteward: +1 for newline
- if (!xrefs.add(pxref)) {
- xrefs.remove(pxref);
- xrefs.add(pxref);
- }
- indirect.writeTo(writer.getOs());
- position = writer.getOs().getCounter();
- return indirect;
- }
- }
-
- /**
- * Adds a PdfResources
object to the body.
- *
- * @param object the PdfResources
- * @return a PdfIndirectObject
- */
-
-// PdfIndirectObject add(PdfResources object) {
-// return add(object);
-// }
-
- /**
- * Adds a PdfPages
object to the body.
- *
- * @param object the root of the document
- * @return a PdfIndirectObject
- */
-
-// PdfIndirectObject add(PdfPages object) throws IOException {
-// PdfIndirectObject indirect = new PdfIndirectObject(PdfWriter.ROOT, object, writer);
-// rootOffset = position;
-// indirect.writeTo(writer.getOs());
-// position = writer.getOs().getCounter();
-// return indirect;
-// }
-
- /**
- * Returns the offset of the Cross-Reference table.
- *
- * @return an offset
- */
-
- int offset() {
- return position;
- }
-
- /**
- * Returns the total number of objects contained in the CrossReferenceTable of this Body
.
- *
- * @return a number of objects
- */
-
- int size() {
- return Math.max(((PdfCrossReference)xrefs.last()).getRefnum() + 1, refnum);
- }
-
- /**
- * Returns the CrossReferenceTable of the Body
.
- * @param os
- * @param root
- * @param info
- * @param encryption
- * @param fileID
- * @param prevxref
- * @throws IOException
- */
-
- void writeCrossReferenceTable(OutputStream os, PdfIndirectReference root, PdfIndirectReference info, PdfIndirectReference encryption, PdfObject fileID, int prevxref) throws IOException {
- int refNumber = 0;
- if (writer.isFullCompression()) {
- flushObjStm();
- refNumber = getIndirectReferenceNumber();
- xrefs.add(new PdfCrossReference(refNumber, position));
- }
- PdfCrossReference entry = (PdfCrossReference)xrefs.first();
- int first = entry.getRefnum();
- int len = 0;
- ArrayList sections = new ArrayList();
- for (Iterator i = xrefs.iterator(); i.hasNext(); ) {
- entry = (PdfCrossReference)i.next();
- if (first + len == entry.getRefnum())
- ++len;
- else {
- sections.add(new Integer(first));
- sections.add(new Integer(len));
- first = entry.getRefnum();
- len = 1;
- }
- }
- sections.add(new Integer(first));
- sections.add(new Integer(len));
- if (writer.isFullCompression()) {
- int mid = 4;
- int mask = 0xff000000;
- for (; mid > 1; --mid) {
- if ((mask & position) != 0)
- break;
- mask >>>= 8;
- }
- ByteBuffer buf = new ByteBuffer();
-
- for (Iterator i = xrefs.iterator(); i.hasNext(); ) {
- entry = (PdfCrossReference) i.next();
- entry.toPdf(mid, buf);
- }
- PdfStream xr = new PdfStream(buf.toByteArray());
- buf = null;
- xr.flateCompress();
- xr.put(PdfName.SIZE, new PdfNumber(size()));
- xr.put(PdfName.ROOT, root);
- if (info != null) {
- xr.put(PdfName.INFO, info);
- }
- if (encryption != null)
- xr.put(PdfName.ENCRYPT, encryption);
- if (fileID != null)
- xr.put(PdfName.ID, fileID);
- xr.put(PdfName.W, new PdfArray(new int[]{1, mid, 2}));
- xr.put(PdfName.TYPE, PdfName.XREF);
- PdfArray idx = new PdfArray();
- for (int k = 0; k < sections.size(); ++k)
- idx.add(new PdfNumber(((Integer)sections.get(k)).intValue()));
- xr.put(PdfName.INDEX, idx);
- if (prevxref > 0)
- xr.put(PdfName.PREV, new PdfNumber(prevxref));
- PdfEncryption enc = writer.crypto;
- writer.crypto = null;
- PdfIndirectObject indirect = new PdfIndirectObject(refNumber, xr, writer);
- indirect.writeTo(writer.getOs());
- writer.crypto = enc;
- }
- else {
- os.write(getISOBytes("xref\n"));
- Iterator i = xrefs.iterator();
- for (int k = 0; k < sections.size(); k += 2) {
- first = ((Integer)sections.get(k)).intValue();
- len = ((Integer)sections.get(k + 1)).intValue();
- os.write(getISOBytes(String.valueOf(first)));
- os.write(getISOBytes(" "));
- os.write(getISOBytes(String.valueOf(len)));
- os.write('\n');
- while (len-- > 0) {
- entry = (PdfCrossReference) i.next();
- entry.toPdf(os);
- }
- }
- }
- }
- }
-
- /**
- * PdfTrailer
is the PDF Trailer object.
- *
- * This object is described in the 'Portable Document Format Reference Manual version 1.3'
- * section 5.16 (page 59-60).
- */
-
- static class PdfTrailer extends PdfDictionary {
-
- // membervariables
-
- int offset;
-
- // constructors
-
- /**
- * Constructs a PDF-Trailer.
- *
- * @param size the number of entries in the PdfCrossReferenceTable
- * @param offset offset of the PdfCrossReferenceTable
- * @param root an indirect reference to the root of the PDF document
- * @param info an indirect reference to the info object of the PDF document
- * @param encryption
- * @param fileID
- * @param prevxref
- */
-
- PdfTrailer(int size, int offset, PdfIndirectReference root, PdfIndirectReference info, PdfIndirectReference encryption, PdfObject fileID, int prevxref) {
- this.offset = offset;
- put(PdfName.SIZE, new PdfNumber(size));
- put(PdfName.ROOT, root);
- if (info != null) {
- put(PdfName.INFO, info);
- }
- if (encryption != null)
- put(PdfName.ENCRYPT, encryption);
- if (fileID != null)
- put(PdfName.ID, fileID);
- if (prevxref > 0)
- put(PdfName.PREV, new PdfNumber(prevxref));
- }
-
- /**
- * Returns the PDF representation of this PdfObject
.
- * @param writer
- * @param os
- * @throws IOException
- */
- public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
- os.write(getISOBytes("trailer\n")); // ssteward: 1.44 - preserve newline after trailer
- super.toPdf(null, os);
- os.write(getISOBytes("\nstartxref\n"));
- os.write(getISOBytes(String.valueOf(offset)));
- os.write(getISOBytes("\n%%EOF\n"));
- }
- }
- // static membervariables
-
- /** A viewer preference */
- public static final int PageLayoutSinglePage = 1;
- /** A viewer preference */
- public static final int PageLayoutOneColumn = 2;
- /** A viewer preference */
- public static final int PageLayoutTwoColumnLeft = 4;
- /** A viewer preference */
- public static final int PageLayoutTwoColumnRight = 8;
-
- /** A viewer preference */
- public static final int PageModeUseNone = 16;
- /** A viewer preference */
- public static final int PageModeUseOutlines = 32;
- /** A viewer preference */
- public static final int PageModeUseThumbs = 64;
- /** A viewer preference */
- public static final int PageModeFullScreen = 128;
- /** A viewer preference */
- public static final int PageModeUseOC = 1 << 20;
-
- /** A viewer preference */
- public static final int HideToolbar = 256;
- /** A viewer preference */
- public static final int HideMenubar = 512;
- /** A viewer preference */
- public static final int HideWindowUI = 1024;
- /** A viewer preference */
- public static final int FitWindow = 2048;
- /** A viewer preference */
- public static final int CenterWindow = 4096;
-
- /** A viewer preference */
- public static final int NonFullScreenPageModeUseNone = 8192;
- /** A viewer preference */
- public static final int NonFullScreenPageModeUseOutlines = 16384;
- /** A viewer preference */
- public static final int NonFullScreenPageModeUseThumbs = 32768;
- /** A viewer preference */
- public static final int NonFullScreenPageModeUseOC = 1 << 19;
-
- /** A viewer preference */
- public static final int DirectionL2R = 1 << 16;
- /** A viewer preference */
- public static final int DirectionR2L = 1 << 17;
- /** A viewer preference */
- public static final int DisplayDocTitle = 1 << 18;
- /** A viewer preference */
- public static final int PrintScalingNone = 1 << 21;
- /** The mask to decide if a ViewerPreferences dictionary is needed */
- static final int ViewerPreferencesMask = 0xffff00;
- /** The operation permitted when the document is opened with the user password */
- public static final int AllowPrinting = 4 + 2048;
- /** The operation permitted when the document is opened with the user password */
- public static final int AllowModifyContents = 8;
- /** The operation permitted when the document is opened with the user password */
- public static final int AllowCopy = 16;
- /** The operation permitted when the document is opened with the user password */
- public static final int AllowModifyAnnotations = 32;
- /** The operation permitted when the document is opened with the user password */
- public static final int AllowFillIn = 256;
- /** The operation permitted when the document is opened with the user password */
- public static final int AllowScreenReaders = 512;
- /** The operation permitted when the document is opened with the user password */
- public static final int AllowAssembly = 1024;
- /** The operation permitted when the document is opened with the user password */
- public static final int AllowDegradedPrinting = 4;
- /** Type of encryption */
- public static final boolean STRENGTH40BITS = false;
- /** Type of encryption */
- public static final boolean STRENGTH128BITS = true;
- /** action value */
- public static final PdfName DOCUMENT_CLOSE = PdfName.WC;
- /** action value */
- public static final PdfName WILL_SAVE = PdfName.WS;
- /** action value */
- public static final PdfName DID_SAVE = PdfName.DS;
- /** action value */
- public static final PdfName WILL_PRINT = PdfName.WP;
- /** action value */
- public static final PdfName DID_PRINT = PdfName.DP;
- /** action value */
- public static final PdfName PAGE_OPEN = PdfName.O;
- /** action value */
- public static final PdfName PAGE_CLOSE = PdfName.C;
-
- /** signature value */
- public static final int SIGNATURE_EXISTS = 1;
- /** signature value */
- public static final int SIGNATURE_APPEND_ONLY = 2;
-
- /** possible PDF version */
- public static final char VERSION_1_2 = '2';
- /** possible PDF version */
- public static final char VERSION_1_3 = '3';
- /** possible PDF version */
- public static final char VERSION_1_4 = '4';
- /** possible PDF version */
- public static final char VERSION_1_5 = '5';
- /** possible PDF version */
- public static final char VERSION_1_6 = '6';
-
- private static final int VPOINT = 7;
- /** this is the header of a PDF document */
- protected byte[] HEADER = getISOBytes("%PDF-1.4\n%\u00e2\u00e3\u00cf\u00d3"); // ssteward: dropped trailing \n
-
- protected int prevxref = 0;
-
- protected PdfPages root = new PdfPages(this);
-
- /** Dictionary, containing all the images of the PDF document */
- protected PdfDictionary imageDictionary = new PdfDictionary();
-
- /** This is the list with all the images in the document. */
- // private HashMap images = new HashMap();
-
- /** The form XObjects in this document. The key is the xref and the value
- is Object[]{PdfName, template}.*/
- protected HashMap formXObjects = new HashMap();
-
- /** The name counter for the form XObjects name. */
- protected int formXObjectsCounter = 1;
-
- /** The font number counter for the fonts in the document. */
- protected int fontNumber = 1;
-
- /** The color number counter for the colors in the document. */
- protected int colorNumber = 1;
-
- /** The patten number counter for the colors in the document. */
- protected int patternNumber = 1;
-
- /** The direct content in this document. */
- protected PdfContentByte directContent;
-
- /** The direct content under in this document. */
- protected PdfContentByte directContentUnder;
-
- /** The fonts of this document */
- protected HashMap documentFonts = new HashMap();
-
- /** The colors of this document */
- protected HashMap documentColors = new HashMap();
-
- /** The patterns of this document */
- protected HashMap documentPatterns = new HashMap();
-
- protected HashMap documentShadings = new HashMap();
-
- protected HashMap documentShadingPatterns = new HashMap();
-
- protected ColorDetails patternColorspaceRGB;
- protected ColorDetails patternColorspaceGRAY;
- protected ColorDetails patternColorspaceCMYK;
- protected HashMap documentSpotPatterns = new HashMap();
-
- protected HashMap documentExtGState = new HashMap();
-
- protected HashMap documentProperties = new HashMap();
- protected HashSet documentOCG = new HashSet();
- protected ArrayList documentOCGorder = new ArrayList();
- protected PdfOCProperties OCProperties;
- protected PdfArray OCGRadioGroup = new PdfArray();
-
- protected PdfDictionary defaultColorspace = new PdfDictionary();
- protected float userunit = 0f;
-
- /** PDF/X value */
- public static final int PDFXNONE = 0;
- /** PDF/X value */
- public static final int PDFX1A2001 = 1;
- /** PDF/X value */
- public static final int PDFX32002 = 2;
-
- private int pdfxConformance = PDFXNONE;
-
- static final int PDFXKEY_COLOR = 1;
- static final int PDFXKEY_CMYK = 2;
- static final int PDFXKEY_RGB = 3;
- static final int PDFXKEY_FONT = 4;
- static final int PDFXKEY_IMAGE = 5;
- static final int PDFXKEY_GSTATE = 6;
- static final int PDFXKEY_LAYER = 7;
-
- // membervariables
-
- /** body of the PDF document */
- protected PdfBody body;
-
- /** the pdfdocument object. */
- protected PdfDocument pdf;
-
- /** The PdfPageEvent
for this document. */
- private PdfPageEvent pageEvent;
-
- protected PdfEncryption crypto;
-
- protected HashMap importedPages = new HashMap();
-
- protected PdfReaderInstance currentPdfReaderInstance;
-
- /** The PdfIndirectReference to the pages. */
- protected ArrayList pageReferences = new ArrayList();
-
- protected int currentPageNumber = 1;
-
- protected PdfDictionary group;
-
- /** The default space-char ratio. */
- public static final float SPACE_CHAR_RATIO_DEFAULT = 2.5f;
- /** Disable the inter-character spacing. */
- public static final float NO_SPACE_CHAR_RATIO = 10000000f;
-
- /** Use the default run direction. */
- public static final int RUN_DIRECTION_DEFAULT = 0;
- /** Do not use bidirectional reordering. */
- public static final int RUN_DIRECTION_NO_BIDI = 1;
- /** Use bidirectional reordering with left-to-right
- * preferential run direction.
- */
- public static final int RUN_DIRECTION_LTR = 2;
- /** Use bidirectional reordering with right-to-left
- * preferential run direction.
- */
- public static final int RUN_DIRECTION_RTL = 3;
- protected int runDirection = RUN_DIRECTION_NO_BIDI;
- /**
- * The ratio between the extra word spacing and the extra character spacing.
- * Extra word spacing will grow ratio
times more than extra character spacing.
- */
- private float spaceCharRatio = SPACE_CHAR_RATIO_DEFAULT;
-
- /** Holds value of property extraCatalog. */
- private PdfDictionary extraCatalog;
-
- // ssteward: for PRStream.toPdf()
- public boolean filterStreams = false; // apply decode filters to some streams upon output
- public boolean compressStreams = false; // add compression to some stream upon output
-
- /** XMP Metadata for the document. */
- protected byte[] xmpMetadata = null;
- /**
- * Holds value of property fullCompression.
- */
- protected boolean fullCompression = false;
-
- protected boolean tagged = false;
-
- protected PdfObject fileID = null; // ssteward: allow setting of fileID
-
- protected PdfStructureTreeRoot structureTreeRoot;
-
- // constructor
-
- protected PdfWriter() {
- }
-
- /**
- * Constructs a PdfWriter
.
- *
- * Remark: a PdfWriter can only be constructed by calling the method
- * getInstance(Document document, OutputStream os)
.
- *
- * @param document The PdfDocument
that has to be written
- * @param os The OutputStream
the writer has to write to.
- */
-
- protected PdfWriter(PdfDocument document, OutputStream os) {
- super(document, os);
- pdf = document;
- directContent = new PdfContentByte(this);
- directContentUnder = new PdfContentByte(this);
- }
-
- // get an instance of the PdfWriter
-
- /**
- * Gets an instance of the PdfWriter
.
- *
- * @param document The Document
that has to be written
- * @param os The OutputStream
the writer has to write to.
- * @return a new PdfWriter
- *
- * @throws DocumentException on error
- */
-
- public static PdfWriter getInstance(Document document, OutputStream os)
- throws DocumentException {
- PdfDocument pdf = new PdfDocument();
- document.addDocListener(pdf);
- PdfWriter writer = new PdfWriter(pdf, os);
- pdf.addWriter(writer);
- return writer;
- }
-
- /** Gets an instance of the PdfWriter
.
- *
- * @return a new PdfWriter
- * @param document The Document
that has to be written
- * @param os The OutputStream
the writer has to write to.
- * @param listener A DocListener
to pass to the PdfDocument.
- * @throws DocumentException on error
- */
-
- public static PdfWriter getInstance(Document document, OutputStream os, DocListener listener)
- throws DocumentException {
- PdfDocument pdf = new PdfDocument();
- pdf.addDocListener(listener);
- document.addDocListener(pdf);
- PdfWriter writer = new PdfWriter(pdf, os);
- pdf.addWriter(writer);
- return writer;
- }
-
- // methods to write objects to the outputstream
-
- /**
- * Adds some PdfContents
to this Writer.
- *
- * The document has to be open before you can begin to add content
- * to the body of the document.
- *
- * @return a PdfIndirectReference
- * @param page the PdfPage
to add
- * @param contents the PdfContents
of the page
- * @throws PdfException on error
- */
-
- PdfIndirectReference add(PdfPage page, PdfContents contents) throws PdfException {
- if (!open) {
- throw new PdfException("The document isn't open.");
- }
- PdfIndirectObject object;
- try {
- object = addToBody(contents);
- }
- catch(IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- page.add(object.getIndirectReference());
- if (group != null) {
- page.put(PdfName.GROUP, group);
- group = null;
- }
- root.addPage(page);
- currentPageNumber++;
- return null;
- }
-
- /** Adds an image to the document but not to the page resources. It is used with
- * templates and Document.add(Image)
.
- * @param image the Image
to add
- * @return the name of the image added
- * @throws PdfException on error
- * @throws DocumentException on error
- */
- /* ssteward: dropped in 1.44
- PdfName addDirectImageSimple(Image image) throws PdfException, DocumentException {
- PdfName name;
- // if the images is already added, just retrieve the name
- if (images.containsKey(image.getMySerialId())) {
- name = (PdfName) images.get(image.getMySerialId());
- }
- // if it's a new image, add it to the document
- else {
- if (image.isImgTemplate()) {
- name = new PdfName("img" + images.size());
- if (image.templateData() == null) {
- if(image instanceof ImgWMF){
- try {
- ImgWMF wmf = (ImgWMF)image;
- wmf.readWMF(getDirectContent().createTemplate(0, 0));
- }
- catch (Exception e) {
- throw new DocumentException(e);
- }
- }else{
- try {
- ((ImgPostscript)image).readPostscript(getDirectContent().createTemplate(0, 0));
- }
- catch (Exception e) {
- throw new DocumentException(e);
- }
-
- }
- }
- }
- else {
- Image maskImage = image.getImageMask();
- PdfIndirectReference maskRef = null;
- if (maskImage != null) {
- PdfName mname = (PdfName)images.get(maskImage.getMySerialId());
- maskRef = getImageReference(mname);
- }
- PdfImage i = new PdfImage(image, "img" + images.size(), maskRef);
- if (image.hasICCProfile()) {
- PdfICCBased icc = new PdfICCBased(image.getICCProfile());
- PdfIndirectReference iccRef = add(icc);
- PdfArray iccArray = new PdfArray();
- iccArray.add(PdfName.ICCBASED);
- iccArray.add(iccRef);
- PdfObject colorspace = i.get(PdfName.COLORSPACE);
- if (colorspace != null && colorspace.isArray()) {
- ArrayList ar = ((PdfArray)colorspace).getArrayList();
- if (ar.size() > 1 && PdfName.INDEXED.equals(ar.get(0)))
- ar.set(1, iccArray);
- else
- i.put(PdfName.COLORSPACE, iccArray);
- }
- else
- i.put(PdfName.COLORSPACE, iccArray);
- }
- add(i);
- name = i.name();
- }
- images.put(image.getMySerialId(), name);
- }
- return name;
- }
- */
-
- /**
- * Writes a PdfImage
to the outputstream.
- *
- * @param pdfImage the image to be added
- * @return a PdfIndirectReference
to the encapsulated image
- * @throws PdfException when a document isn't open yet, or has been closed
- */
- /* ssteward: dropped in 1.44
- PdfIndirectReference add(PdfImage pdfImage) throws PdfException {
- if (! imageDictionary.contains(pdfImage.name())) {
- checkPDFXConformance(this, PDFXKEY_IMAGE, pdfImage);
- PdfIndirectObject object;
- try {
- object = addToBody(pdfImage);
- }
- catch(IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- imageDictionary.put(pdfImage.name(), object.getIndirectReference());
- return object.getIndirectReference();
- }
- return (PdfIndirectReference) imageDictionary.get(pdfImage.name());
- }
- */
- /* ssteward: gcc 3.4.0 doesn't have ICC_Profile
- protected PdfIndirectReference add(PdfICCBased icc) throws PdfException {
- PdfIndirectObject object;
- try {
- object = addToBody(icc);
- }
- catch(IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- return object.getIndirectReference();
- }
- */
-
- /**
- * return the PdfIndirectReference
to the image with a given name.
- *
- * @param name the name of the image
- * @return a PdfIndirectReference
- */
-
- PdfIndirectReference getImageReference(PdfName name) {
- return (PdfIndirectReference) imageDictionary.get(name);
- }
-
- // methods to open and close the writer
-
- /**
- * Signals that the Document
has been opened and that
- * Elements
can be added.
- *
- * When this method is called, the PDF-document header is
- * written to the outputstream.
- */
-
- public void open() {
- super.open();
- try {
- os.write(HEADER);
- body = new PdfBody(this);
- if (pdfxConformance == PDFX32002) {
- PdfDictionary sec = new PdfDictionary();
- sec.put(PdfName.GAMMA, new PdfArray(new float[]{2.2f,2.2f,2.2f}));
- sec.put(PdfName.MATRIX, new PdfArray(new float[]{0.4124f,0.2126f,0.0193f,0.3576f,0.7152f,0.1192f,0.1805f,0.0722f,0.9505f}));
- sec.put(PdfName.WHITEPOINT, new PdfArray(new float[]{0.9505f,1f,1.089f}));
- PdfArray arr = new PdfArray(PdfName.CALRGB);
- arr.add(sec);
- setDefaultColorspace(PdfName.DEFAULTRGB, addToBody(arr).getIndirectReference());
- }
- }
- catch(IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- }
-
- private static void getOCGOrder(PdfArray order, PdfLayer layer) {
- if (!layer.isOnPanel())
- return;
- if (layer.getTitle() == null)
- order.add(layer.getRef());
- ArrayList children = layer.getChildren();
- if (children == null)
- return;
- PdfArray kids = new PdfArray();
- if (layer.getTitle() != null)
- kids.add(new PdfString(layer.getTitle(), PdfObject.TEXT_UNICODE));
- for (int k = 0; k < children.size(); ++k) {
- getOCGOrder(kids, (PdfLayer)children.get(k));
- }
- if (kids.size() > 0)
- order.add(kids);
- }
-
- private void addASEvent(PdfName event, PdfName category) {
- PdfArray arr = new PdfArray();
- for (Iterator it = documentOCG.iterator(); it.hasNext();) {
- PdfLayer layer = (PdfLayer)it.next();
- PdfDictionary usage = (PdfDictionary)layer.get(PdfName.USAGE);
- if (usage != null && usage.get(category) != null)
- arr.add(layer.getRef());
- }
- if (arr.size() == 0)
- return;
- PdfDictionary d = (PdfDictionary)OCProperties.get(PdfName.D);
- PdfArray arras = (PdfArray)d.get(PdfName.AS);
- if (arras == null) {
- arras = new PdfArray();
- d.put(PdfName.AS, arras);
- }
- PdfDictionary as = new PdfDictionary();
- as.put(PdfName.EVENT, event);
- as.put(PdfName.CATEGORY, new PdfArray(category));
- as.put(PdfName.OCGS, arr);
- arras.add(as);
- }
-
- private void fillOCProperties(boolean erase) {
- if (OCProperties == null)
- OCProperties = new PdfOCProperties();
- if (erase) {
- OCProperties.remove(PdfName.OCGS);
- OCProperties.remove(PdfName.D);
- }
- if (OCProperties.get(PdfName.OCGS) == null) {
- PdfArray gr = new PdfArray();
- for (Iterator it = documentOCG.iterator(); it.hasNext();) {
- PdfLayer layer = (PdfLayer)it.next();
- gr.add(layer.getRef());
- }
- OCProperties.put(PdfName.OCGS, gr);
- }
- if (OCProperties.get(PdfName.D) != null)
- return;
- ArrayList docOrder = new ArrayList(documentOCGorder);
- for (Iterator it = docOrder.iterator(); it.hasNext();) {
- PdfLayer layer = (PdfLayer)it.next();
- if (layer.getParent() != null)
- it.remove();
- }
- PdfArray order = new PdfArray();
- for (Iterator it = docOrder.iterator(); it.hasNext();) {
- PdfLayer layer = (PdfLayer)it.next();
- getOCGOrder(order, layer);
- }
- PdfDictionary d = new PdfDictionary();
- OCProperties.put(PdfName.D, d);
- d.put(PdfName.ORDER, order);
- PdfArray gr = new PdfArray();
- for (Iterator it = documentOCG.iterator(); it.hasNext();) {
- PdfLayer layer = (PdfLayer)it.next();
- if (!layer.isOn())
- gr.add(layer.getRef());
- }
- if (gr.size() > 0)
- d.put(PdfName.OFF, gr);
- if (OCGRadioGroup.size() > 0)
- d.put(PdfName.RBGROUPS, OCGRadioGroup);
- addASEvent(PdfName.VIEW, PdfName.ZOOM);
- addASEvent(PdfName.VIEW, PdfName.VIEW);
- addASEvent(PdfName.PRINT, PdfName.PRINT);
- addASEvent(PdfName.EXPORT, PdfName.EXPORT);
- d.put(PdfName.LISTMODE, PdfName.VISIBLEPAGES);
- }
-
- protected PdfDictionary getCatalog(PdfIndirectReference rootObj)
- {
- PdfDictionary catalog = ((PdfDocument)document).getCatalog(rootObj);
- if (tagged) {
- try {
- getStructureTreeRoot().buildTree();
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- catalog.put(PdfName.STRUCTTREEROOT, structureTreeRoot.getReference());
- PdfDictionary mi = new PdfDictionary();
- mi.put(PdfName.MARKED, PdfBoolean.PDFTRUE);
- catalog.put(PdfName.MARKINFO, mi);
- }
- if (documentOCG.size() == 0)
- return catalog;
- fillOCProperties(false);
- catalog.put(PdfName.OCPROPERTIES, OCProperties);
- return catalog;
- }
-
- protected void addSharedObjectsToBody() throws IOException {
- // add the fonts
- for (Iterator it = documentFonts.values().iterator(); it.hasNext();) {
- FontDetails details = (FontDetails)it.next();
- details.writeFont(this);
- }
- // add the form XObjects
- for (Iterator it = formXObjects.values().iterator(); it.hasNext();) {
- Object objs[] = (Object[])it.next();
- PdfTemplate template = (PdfTemplate)objs[1];
- if (template != null && template.getIndirectReference() instanceof PRIndirectReference)
- continue;
- if (template != null && template.getType() == PdfTemplate.TYPE_TEMPLATE) {
- addToBody(template.getFormXObject(), template.getIndirectReference());
- }
- }
- // add all the dependencies in the imported pages
- for (Iterator it = importedPages.values().iterator(); it.hasNext();) {
- currentPdfReaderInstance = (PdfReaderInstance)it.next();
- currentPdfReaderInstance.writeAllPages();
- }
- currentPdfReaderInstance = null;
- // add the color
- for (Iterator it = documentColors.values().iterator(); it.hasNext();) {
- ColorDetails color = (ColorDetails)it.next();
- addToBody(color.getSpotColor(this), color.getIndirectReference());
- }
- // add the pattern
- for (Iterator it = documentPatterns.keySet().iterator(); it.hasNext();) {
- PdfPatternPainter pat = (PdfPatternPainter)it.next();
- addToBody(pat.getPattern(), pat.getIndirectReference());
- }
- // add the shading patterns
- for (Iterator it = documentShadingPatterns.keySet().iterator(); it.hasNext();) {
- PdfShadingPattern shadingPattern = (PdfShadingPattern)it.next();
- shadingPattern.addToBody();
- }
- // add the shadings
- for (Iterator it = documentShadings.keySet().iterator(); it.hasNext();) {
- PdfShading shading = (PdfShading)it.next();
- shading.addToBody();
- }
- // add the extgstate
- for (Iterator it = documentExtGState.keySet().iterator(); it.hasNext();) {
- PdfDictionary gstate = (PdfDictionary)it.next();
- PdfObject obj[] = (PdfObject[])documentExtGState.get(gstate);
- addToBody(gstate, (PdfIndirectReference)obj[1]);
- }
- // add the properties
- for (Iterator it = documentProperties.keySet().iterator(); it.hasNext();) {
- Object prop = it.next();
- PdfObject[] obj = (PdfObject[])documentProperties.get(prop);
- if (prop instanceof PdfLayerMembership){
- PdfLayerMembership layer = (PdfLayerMembership)prop;
- addToBody(layer.getPdfObject(), layer.getRef());
- }
- else if ((prop instanceof PdfDictionary) && !(prop instanceof PdfLayer)){
- addToBody((PdfDictionary)prop, (PdfIndirectReference)obj[1]);
- }
- }
- for (Iterator it = documentOCG.iterator(); it.hasNext();) {
- PdfOCG layer = (PdfOCG)it.next();
- addToBody(layer.getPdfObject(), layer.getRef());
- }
- }
-
- /**
- * Signals that the Document
was closed and that no other
- * Elements
will be added.
- *
- * The pages-tree is built and written to the outputstream.
- * A Catalog is constructed, as well as an Info-object,
- * the referencetable is composed and everything is written
- * to the outputstream embedded in a Trailer.
- */
-
- public synchronized void close() {
- if (open) {
- if ((currentPageNumber - 1) != pageReferences.size())
- throw new RuntimeException("The page " + pageReferences.size() +
- " was requested but the document has only " + (currentPageNumber - 1) + " pages.");
- pdf.close();
- try {
- addSharedObjectsToBody();
- // add the root to the body
- PdfIndirectReference rootRef = root.writePageTree();
- // make the catalog-object and add it to the body
- PdfDictionary catalog = getCatalog(rootRef);
- // if there is XMP data to add: add it
- if (xmpMetadata != null) {
- PdfStream xmp = new PdfStream(xmpMetadata);
- xmp.put(PdfName.TYPE, PdfName.METADATA);
- xmp.put(PdfName.SUBTYPE, PdfName.XML);
- catalog.put(PdfName.METADATA, body.add(xmp).getIndirectReference());
- }
- // make pdfx conformant
- PdfDictionary info = getInfo();
- if (pdfxConformance != PDFXNONE) {
- if (info.get(PdfName.GTS_PDFXVERSION) == null) {
- if (pdfxConformance == PDFX1A2001) {
- info.put(PdfName.GTS_PDFXVERSION, new PdfString("PDF/X-1:2001"));
- info.put(new PdfName("GTS_PDFXConformance"), new PdfString("PDF/X-1a:2001"));
- }
- else if (pdfxConformance == PDFX32002)
- info.put(PdfName.GTS_PDFXVERSION, new PdfString("PDF/X-3:2002"));
- }
- if (info.get(PdfName.TITLE) == null) {
- info.put(PdfName.TITLE, new PdfString("Pdf document"));
- }
- if (info.get(PdfName.CREATOR) == null) {
- info.put(PdfName.CREATOR, new PdfString("Unknown"));
- }
- if (info.get(PdfName.TRAPPED) == null) {
- info.put(PdfName.TRAPPED, new PdfName("False"));
- }
- getExtraCatalog();
- if (extraCatalog.get(PdfName.OUTPUTINTENTS) == null) {
- PdfDictionary out = new PdfDictionary(PdfName.OUTPUTINTENT);
- out.put(PdfName.OUTPUTCONDITION, new PdfString("SWOP CGATS TR 001-1995"));
- out.put(PdfName.OUTPUTCONDITIONIDENTIFIER, new PdfString("CGATS TR 001"));
- out.put(PdfName.REGISTRYNAME, new PdfString("http://www.color.org"));
- out.put(PdfName.INFO, new PdfString(""));
- out.put(PdfName.S, PdfName.GTS_PDFX);
- extraCatalog.put(PdfName.OUTPUTINTENTS, new PdfArray(out));
- }
- }
- if (extraCatalog != null) {
- catalog.mergeDifferent(extraCatalog);
- }
- PdfIndirectObject indirectCatalog = addToBody(catalog, false);
- // add the info-object to the body
- PdfIndirectObject infoObj = addToBody(info, false);
- PdfIndirectReference encryption = null;
- //PdfObject fileID = null; // ssteward: moved this out into PdfWriter
- body.flushObjStm();
- if (crypto != null) {
- PdfIndirectObject encryptionObject = addToBody(crypto.getEncryptionDictionary(), false);
- encryption = encryptionObject.getIndirectReference();
- fileID = crypto.getFileID();
- }
- else if (fileID == null) // ssteward
- fileID = PdfEncryption.createInfoId(PdfEncryption.createDocumentId());
-
- // write the cross-reference table of the body
- body.writeCrossReferenceTable(os, indirectCatalog.getIndirectReference(),
- infoObj.getIndirectReference(), encryption, fileID, prevxref);
-
- // make the trailer
- if (fullCompression) {
- os.write(getISOBytes("startxref\n"));
- os.write(getISOBytes(String.valueOf(body.offset())));
- os.write(getISOBytes("\n%%EOF\n"));
- }
- else {
- PdfTrailer trailer = new PdfTrailer(body.size(),
- body.offset(),
- indirectCatalog.getIndirectReference(),
- infoObj.getIndirectReference(),
- encryption,
- fileID, prevxref);
- trailer.toPdf(this, os);
- }
- super.close();
- }
- catch(IOException ioe) {
- throw new ExceptionConverter(ioe);
- }
- }
- }
-
- // methods
-
- /**
- * Sometimes it is necessary to know where the just added Table
ends.
- *
- * For instance to avoid to add another table in a page that is ending up, because
- * the new table will be probably splitted just after the header (it is an
- * unpleasant effect, isn't it?).
- *
- * Added on September 8th, 2001
- * by Francesco De Milato
- * francesco.demilato@tiscalinet.it
- * @param table the Table
- * @return the bottom height of the just added table
- */
- /* ssteward: dropped in 1.44
- public float getTableBottom(Table table) {
- return pdf.bottom(table) - pdf.indentBottom();
- }
- */
-
- /**
- * Gets a pre-rendered table.
- * (Contributed by dperezcar@fcc.es)
- * @param table Contains the table definition. Its contents are deleted, after being pre-rendered.
- * @return a PdfTable
- */
- /* ssteward: dropped in 1.44
- public PdfTable getPdfTable(Table table) {
- return pdf.getPdfTable(table, true);
- }
- */
-
- /**
- * Row additions to the original {@link Table} used to build the {@link PdfTable} are processed and pre-rendered,
- * and then the contents are deleted.
- * If the pre-rendered table doesn't fit, then it is fully rendered and its data discarded.
- * There shouldn't be any column change in the underlying {@link Table} object.
- * (Contributed by dperezcar@fcc.es)
- *
- * @param table The pre-rendered table obtained from {@link #getPdfTable(Table)}
- * @return true if the table is rendered and emptied.
- * @throws DocumentException
- * @see #getPdfTable(Table)
- */
- /* ssteward: dropped in 1.44
- public boolean breakTableIfDoesntFit(PdfTable table) throws DocumentException {
- return pdf.breakTableIfDoesntFit(table);
- }
- */
- /**
- * Checks if a Table
fits the current page of the PdfDocument
.
- *
- * @param table the table that has to be checked
- * @param margin a certain margin
- * @return true
if the Table
fits the page, false
otherwise.
- */
- /* ssteward: dropped in 1.44
- public boolean fitsPage(Table table, float margin) {
- return pdf.bottom(table) > pdf.indentBottom() + margin;
- }
- */
-
- /**
- * Checks if a Table
fits the current page of the PdfDocument
.
- *
- * @param table the table that has to be checked
- * @return true
if the Table
fits the page, false
otherwise.
- */
- /* ssteward: dropped in 1.44
- public boolean fitsPage(Table table) {
- return fitsPage(table, 0);
- }
- */
-
- /**
- * Checks if a PdfPTable
fits the current page of the PdfDocument
.
- *
- * @param table the table that has to be checked
- * @param margin a certain margin
- * @return true
if the PdfPTable
fits the page, false
otherwise.
- */
- /* ssteward: dropped in 1.44
- public boolean fitsPage(PdfPTable table, float margin) {
- return pdf.fitsPage(table, margin);
- }
- */
-
- /**
- * Checks if a PdfPTable
fits the current page of the PdfDocument
.
- *
- * @param table the table that has to be checked
- * @return true
if the PdfPTable
fits the page, false
otherwise.
- */
- /* ssteward: dropped in 1.44
- public boolean fitsPage(PdfPTable table) {
- return pdf.fitsPage(table, 0);
- }
- */
-
- /**
- * Gets the current vertical page position.
- * @param ensureNewLine Tells whether a new line shall be enforced. This may cause side effects
- * for elements that do not terminate the lines they've started because those lines will get
- * terminated.
- * @return The current vertical page position.
- */
- public float getVerticalPosition(boolean ensureNewLine) {
- return pdf.getVerticalPosition(ensureNewLine);
- }
-
- /**
- * Checks if writing is paused.
- *
- * @return true
if writing temporarely has to be paused, false
otherwise.
- */
-
- boolean isPaused() {
- // ssteward: changed from "pause" to "m_pause" to
- // bring in line with DocWriter
- return m_pause;
- }
-
- /**
- * Gets the direct content for this document. There is only one direct content,
- * multiple calls to this method will allways retrieve the same.
- * @return the direct content
- */
-
- public PdfContentByte getDirectContent() {
- if (!open)
- throw new RuntimeException("The document is not open.");
- return directContent;
- }
-
- /**
- * Gets the direct content under for this document. There is only one direct content,
- * multiple calls to this method will allways retrieve the same.
- * @return the direct content
- */
-
- public PdfContentByte getDirectContentUnder() {
- if (!open)
- throw new RuntimeException("The document is not open.");
- return directContentUnder;
- }
-
- /**
- * Resets all the direct contents to empty. This happens when a new page is started.
- */
-
- void resetContent() {
- directContent.reset();
- directContentUnder.reset();
- }
-
- /** Gets the AcroForm object.
- * @return the PdfAcroForm
- */
-
- public PdfAcroForm getAcroForm() {
- return pdf.getAcroForm();
- }
-
- /** Gets the root outline.
- * @return the root outline
- */
-
- public PdfOutline getRootOutline() {
- return directContent.getRootOutline();
- }
-
- /**
- * Returns the outputStreamCounter.
- * @return the outputStreamCounter
- */
- public OutputStreamCounter getOs() {
- return os;
- }
-
- /**
- * Adds a BaseFont
to the document but not to the page resources.
- * It is used for templates.
- * @param bf the BaseFont
to add
- * @return an Object[]
where position 0 is a PdfName
- * and position 1 is an PdfIndirectReference
- */
-
- FontDetails addSimple(BaseFont bf) {
- if (bf.getFontType() == BaseFont.FONT_TYPE_DOCUMENT) {
- return new FontDetails(new PdfName("F" + (fontNumber++)), ((DocumentFont)bf).getIndirectReference(), bf);
- }
- FontDetails ret = (FontDetails)documentFonts.get(bf);
- if (ret == null) {
- checkPDFXConformance(this, PDFXKEY_FONT, bf);
- ret = new FontDetails(new PdfName("F" + (fontNumber++)), body.getPdfIndirectReference(), bf);
- documentFonts.put(bf, ret);
- }
- return ret;
- }
-
- void eliminateFontSubset(PdfDictionary fonts) {
- for (Iterator it = documentFonts.values().iterator(); it.hasNext();) {
- FontDetails ft = (FontDetails)it.next();
- if (fonts.get(ft.getFontName()) != null)
- ft.setSubset(false);
- }
- }
-
- PdfName getColorspaceName() {
- return new PdfName("CS" + (colorNumber++));
- }
-
- /**
- * Adds a SpotColor
to the document but not to the page resources.
- * @param spc the SpotColor
to add
- * @return an Object[]
where position 0 is a PdfName
- * and position 1 is an PdfIndirectReference
- */
-
- ColorDetails addSimple(PdfSpotColor spc) {
- ColorDetails ret = (ColorDetails)documentColors.get(spc);
- if (ret == null) {
- ret = new ColorDetails(getColorspaceName(), body.getPdfIndirectReference(), spc);
- documentColors.put(spc, ret);
- }
- return ret;
- }
-
- ColorDetails addSimplePatternColorspace(Color color) {
- int type = ExtendedColor.getType(color);
- if (type == ExtendedColor.TYPE_PATTERN || type == ExtendedColor.TYPE_SHADING)
- throw new RuntimeException("An uncolored tile pattern can not have another pattern or shading as color.");
- try {
- switch (type) {
- case ExtendedColor.TYPE_RGB:
- if (patternColorspaceRGB == null) {
- patternColorspaceRGB = new ColorDetails(getColorspaceName(), body.getPdfIndirectReference(), null);
- PdfArray array = new PdfArray(PdfName.PATTERN);
- array.add(PdfName.DEVICERGB);
- addToBody(array, patternColorspaceRGB.getIndirectReference());
- }
- return patternColorspaceRGB;
- case ExtendedColor.TYPE_CMYK:
- if (patternColorspaceCMYK == null) {
- patternColorspaceCMYK = new ColorDetails(getColorspaceName(), body.getPdfIndirectReference(), null);
- PdfArray array = new PdfArray(PdfName.PATTERN);
- array.add(PdfName.DEVICECMYK);
- addToBody(array, patternColorspaceCMYK.getIndirectReference());
- }
- return patternColorspaceCMYK;
- case ExtendedColor.TYPE_GRAY:
- if (patternColorspaceGRAY == null) {
- patternColorspaceGRAY = new ColorDetails(getColorspaceName(), body.getPdfIndirectReference(), null);
- PdfArray array = new PdfArray(PdfName.PATTERN);
- array.add(PdfName.DEVICEGRAY);
- addToBody(array, patternColorspaceGRAY.getIndirectReference());
- }
- return patternColorspaceGRAY;
- case ExtendedColor.TYPE_SEPARATION: {
- ColorDetails details = addSimple(((SpotColor)color).getPdfSpotColor());
- ColorDetails patternDetails = (ColorDetails)documentSpotPatterns.get(details);
- if (patternDetails == null) {
- patternDetails = new ColorDetails(getColorspaceName(), body.getPdfIndirectReference(), null);
- PdfArray array = new PdfArray(PdfName.PATTERN);
- array.add(details.getIndirectReference());
- addToBody(array, patternDetails.getIndirectReference());
- documentSpotPatterns.put(details, patternDetails);
- }
- return patternDetails;
- }
- default:
- throw new RuntimeException("Invalid color type in PdfWriter.addSimplePatternColorspace().");
- }
- }
- catch (Exception e) {
- throw new RuntimeException(e.getMessage());
- }
- }
-
- void addSimpleShadingPattern(PdfShadingPattern shading) {
- if (!documentShadingPatterns.containsKey(shading)) {
- shading.setName(patternNumber);
- ++patternNumber;
- documentShadingPatterns.put(shading, null);
- addSimpleShading(shading.getShading());
- }
- }
-
- void addSimpleShading(PdfShading shading) {
- if (!documentShadings.containsKey(shading)) {
- documentShadings.put(shading, null);
- shading.setName(documentShadings.size());
- }
- }
-
- PdfObject[] addSimpleExtGState(PdfDictionary gstate) {
- if (!documentExtGState.containsKey(gstate)) {
- checkPDFXConformance(this, PDFXKEY_GSTATE, gstate);
- documentExtGState.put(gstate, new PdfObject[]{new PdfName("GS" + (documentExtGState.size() + 1)), getPdfIndirectReference()});
- }
- return (PdfObject[])documentExtGState.get(gstate);
- }
-
- void registerLayer(PdfOCG layer) {
- checkPDFXConformance(this, PDFXKEY_LAYER, null);
- if (layer instanceof PdfLayer) {
- PdfLayer la = (PdfLayer)layer;
- if (la.getTitle() == null) {
- if (!documentOCG.contains(layer)) {
- documentOCG.add(layer);
- documentOCGorder.add(layer);
- }
- }
- else {
- documentOCGorder.add(layer);
- }
- }
- else
- throw new IllegalArgumentException("Only PdfLayer is accepted.");
- }
-
- PdfObject[] addSimpleProperty(Object prop, PdfIndirectReference refi) {
- if (!documentProperties.containsKey(prop)) {
- if (prop instanceof PdfOCG)
- checkPDFXConformance(this, PDFXKEY_LAYER, null);
- documentProperties.put(prop, new PdfObject[]{new PdfName("Pr" + (documentProperties.size() + 1)), refi});
- }
- return (PdfObject[])documentProperties.get(prop);
- }
-
- boolean propertyExists(Object prop) {
- return documentProperties.containsKey(prop);
- }
- /**
- * Gets the PdfDocument
associated with this writer.
- * @return the PdfDocument
- */
-
- PdfDocument getPdfDocument() {
- return pdf;
- }
-
- /**
- * Gets a PdfIndirectReference
for an object that
- * will be created in the future.
- * @return the PdfIndirectReference
- */
-
- public PdfIndirectReference getPdfIndirectReference() {
- return body.getPdfIndirectReference();
- }
-
- int getIndirectReferenceNumber() {
- return body.getIndirectReferenceNumber();
- }
-
- PdfName addSimplePattern(PdfPatternPainter painter) {
- PdfName name = (PdfName)documentPatterns.get(painter);
- try {
- if ( name == null ) {
- name = new PdfName("P" + patternNumber);
- ++patternNumber;
- documentPatterns.put(painter, name);
- }
- } catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- return name;
- }
-
- /**
- * Adds a template to the document but not to the page resources.
- * @param template the template to add
- * @param forcedName the template name, rather than a generated one. Can be null
- * @return the PdfName
for this template
- */
-
- PdfName addDirectTemplateSimple(PdfTemplate template, PdfName forcedName) {
- PdfIndirectReference ref = template.getIndirectReference();
- Object obj[] = (Object[])formXObjects.get(ref);
- PdfName name = null;
- try {
- if (obj == null) {
- if (forcedName == null) {
- name = new PdfName("Xf" + formXObjectsCounter);
- ++formXObjectsCounter;
- }
- else
- name = forcedName;
- if (template.getType() == PdfTemplate.TYPE_IMPORTED)
- template = null;
- formXObjects.put(ref, new Object[]{name, template});
- }
- else
- name = (PdfName)obj[0];
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- return name;
- }
-
- /**
- * Sets the PdfPageEvent
for this document.
- * @param pageEvent the PdfPageEvent
for this document
- */
-
- public void setPageEvent(PdfPageEvent pageEvent) {
- this.pageEvent = pageEvent;
- }
-
- /**
- * Gets the PdfPageEvent
for this document or null
- * if none is set.
- * @return the PdfPageEvent
for this document or null
- * if none is set
- */
-
- public PdfPageEvent getPageEvent() {
- return pageEvent;
- }
-
- /**
- * Adds the local destinations to the body of the document.
- * @param dest the HashMap
containing the destinations
- * @throws IOException on error
- */
-
- void addLocalDestinations(TreeMap dest) throws IOException {
- for (Iterator i = dest.keySet().iterator(); i.hasNext();) {
- String name = (String)i.next();
- Object obj[] = (Object[])dest.get(name);
- PdfDestination destination = (PdfDestination)obj[2];
- if (destination == null)
- throw new RuntimeException("The name '" + name + "' has no local destination.");
- if (obj[1] == null)
- obj[1] = getPdfIndirectReference();
- addToBody(destination, (PdfIndirectReference)obj[1]);
- }
- }
-
- /**
- * Gets the current pagenumber of this document.
- *
- * @return a page number
- */
-
- public int getPageNumber() {
- return pdf.getPageNumber();
- }
-
- /**
- * Sets the viewer preferences by ORing some constants.
- *
- *
- * The page layout to be used when the document is opened (choose one).
- *
- * PageLayoutSinglePage - Display one page at a time. (default)
- * PageLayoutOneColumn - Display the pages in one column.
- * PageLayoutTwoColumnLeft - Display the pages in two columns, with
- * oddnumbered pages on the left.
- * PageLayoutTwoColumnRight - Display the pages in two columns, with
- * oddnumbered pages on the right.
- *
- * The page mode how the document should be displayed
- * when opened (choose one).
- *
- * PageModeUseNone - Neither document outline nor thumbnail images visible. (default)
- * PageModeUseOutlines - Document outline visible.
- * PageModeUseThumbs - Thumbnail images visible.
- * PageModeFullScreen - Full-screen mode, with no menu bar, window
- * controls, or any other window visible.
- * PageModeUseOC - Optional content group panel visible
- *
- * HideToolbar - A flag specifying whether to hide the viewer application's tool
- * bars when the document is active.
- * HideMenubar - A flag specifying whether to hide the viewer application's
- * menu bar when the document is active.
- * HideWindowUI - A flag specifying whether to hide user interface elements in
- * the document's window (such as scroll bars and navigation controls),
- * leaving only the document's contents displayed.
- * FitWindow - A flag specifying whether to resize the document's window to
- * fit the size of the first displayed page.
- * CenterWindow - A flag specifying whether to position the document's window
- * in the center of the screen.
- * DisplayDocTitle - A flag specifying whether to display the document's title
- * in the top bar.
- * The predominant reading order for text. This entry has no direct effect on the
- * document's contents or page numbering, but can be used to determine the relative
- * positioning of pages when displayed side by side or printed n-up (choose one).
- *
- * DirectionL2R - Left to right
- * DirectionR2L - Right to left (including vertical writing systems such as
- * Chinese, Japanese, and Korean)
- *
- * The document's page mode, specifying how to display the
- * document on exiting full-screen mode. It is meaningful only
- * if the page mode is PageModeFullScreen (choose one).
- *
- * NonFullScreenPageModeUseNone - Neither document outline nor thumbnail images
- * visible
- * NonFullScreenPageModeUseOutlines - Document outline visible
- * NonFullScreenPageModeUseThumbs - Thumbnail images visible
- * NonFullScreenPageModeUseOC - Optional content group panel visible
- *
- * PrintScalingNone - Indicates that the print dialog should reflect no page scaling.
- *
- * @param preferences the viewer preferences
- */
-
- public void setViewerPreferences(int preferences) {
- pdf.setViewerPreferences(preferences);
- }
-
- /** Sets the encryption options for this document. The userPassword and the
- * ownerPassword can be null or have zero length. In this case the ownerPassword
- * is replaced by a random string. The open permissions for the document can be
- * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
- * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
- * The permissions can be combined by ORing them.
- * @param userPassword the user password. Can be null or empty
- * @param ownerPassword the owner password. Can be null or empty
- * @param permissions the user permissions
- * @param strength128Bits true
for 128 bit key length, false
for 40 bit key length
- * @throws DocumentException if the document is already open
- */
- public void setEncryption(byte userPassword[], byte ownerPassword[], int permissions, boolean strength128Bits) throws DocumentException {
- if (pdf.isOpen())
- throw new DocumentException("Encryption can only be added before opening the document.");
- crypto = new PdfEncryption();
- crypto.setupAllKeys(userPassword, ownerPassword, permissions, strength128Bits);
- }
-
- /**
- * Sets the encryption options for this document. The userPassword and the
- * ownerPassword can be null or have zero length. In this case the ownerPassword
- * is replaced by a random string. The open permissions for the document can be
- * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
- * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
- * The permissions can be combined by ORing them.
- * @param strength true
for 128 bit key length, false
for 40 bit key length
- * @param userPassword the user password. Can be null or empty
- * @param ownerPassword the owner password. Can be null or empty
- * @param permissions the user permissions
- * @throws DocumentException if the document is already open
- */
- public void setEncryption(boolean strength, String userPassword, String ownerPassword, int permissions) throws DocumentException {
- setEncryption(getISOBytes(userPassword), getISOBytes(ownerPassword), permissions, strength);
- }
-
- /**
- * Adds an object to the PDF body.
- * @param object
- * @return a PdfIndirectObject
- * @throws IOException
- */
- public PdfIndirectObject addToBody(PdfObject object) throws IOException {
- PdfIndirectObject iobj = body.add(object);
- return iobj;
- }
-
- /**
- * Adds an object to the PDF body.
- * @param object
- * @param inObjStm
- * @return a PdfIndirectObject
- * @throws IOException
- */
- public PdfIndirectObject addToBody(PdfObject object, boolean inObjStm) throws IOException {
- PdfIndirectObject iobj = body.add(object, inObjStm);
- return iobj;
- }
-
- /**
- * Adds an object to the PDF body.
- * @param object
- * @param ref
- * @return a PdfIndirectObject
- * @throws IOException
- */
- public PdfIndirectObject addToBody(PdfObject object, PdfIndirectReference ref) throws IOException {
- PdfIndirectObject iobj = body.add(object, ref);
- return iobj;
- }
-
- /**
- * Adds an object to the PDF body.
- * @param object
- * @param ref
- * @param inObjStm
- * @return a PdfIndirectObject
- * @throws IOException
- */
- public PdfIndirectObject addToBody(PdfObject object, PdfIndirectReference ref, boolean inObjStm) throws IOException {
- PdfIndirectObject iobj = body.add(object, ref, inObjStm);
- return iobj;
- }
-
- /**
- * Adds an object to the PDF body.
- * @param object
- * @param refNumber
- * @return a PdfIndirectObject
- * @throws IOException
- */
- public PdfIndirectObject addToBody(PdfObject object, int refNumber) throws IOException {
- PdfIndirectObject iobj = body.add(object, refNumber);
- return iobj;
- }
-
- /**
- * Adds an object to the PDF body.
- * @param object
- * @param refNumber
- * @param inObjStm
- * @return a PdfIndirectObject
- * @throws IOException
- */
- public PdfIndirectObject addToBody(PdfObject object, int refNumber, boolean inObjStm) throws IOException {
- PdfIndirectObject iobj = body.add(object, refNumber, inObjStm);
- return iobj;
- }
-
- /** When the document opens it will jump to the destination with
- * this name.
- * @param name the name of the destination to jump to
- */
- public void setOpenAction(String name) {
- pdf.setOpenAction(name);
- }
-
- /** Additional-actions defining the actions to be taken in
- * response to various trigger events affecting the document
- * as a whole. The actions types allowed are: DOCUMENT_CLOSE
,
- * WILL_SAVE
, DID_SAVE
, WILL_PRINT
- * and DID_PRINT
.
- *
- * @param actionType the action type
- * @param action the action to execute in response to the trigger
- * @throws PdfException on invalid action type
- */
- public void setAdditionalAction(PdfName actionType, PdfAction action) throws PdfException {
- if (!(actionType.equals(DOCUMENT_CLOSE) ||
- actionType.equals(WILL_SAVE) ||
- actionType.equals(DID_SAVE) ||
- actionType.equals(WILL_PRINT) ||
- actionType.equals(DID_PRINT))) {
- throw new PdfException("Invalid additional action type: " + actionType.toString());
- }
- pdf.addAdditionalAction(actionType, action);
- }
-
- /** When the document opens this action
will be
- * invoked.
- * @param action the action to be invoked
- */
- public void setOpenAction(PdfAction action) {
- pdf.setOpenAction(action);
- }
-
- /** Sets the page labels
- * @param pageLabels the page labels
- */
- public void setPageLabels(PdfPageLabels pageLabels) {
- pdf.setPageLabels(pageLabels);
- }
-
- PdfEncryption getEncryption() {
- return crypto;
- }
-
- RandomAccessFileOrArray getReaderFile(PdfReader reader) {
- return currentPdfReaderInstance.getReaderFile();
- }
-
- protected int getNewObjectNumber(PdfReader reader, int number, int generation) {
- return currentPdfReaderInstance.getNewObjectNumber(number, generation);
- }
-
- /** Gets a page from other PDF document. The page can be used as
- * any other PdfTemplate. Note that calling this method more than
- * once with the same parameters will retrieve the same object.
- * @param reader the PDF document where the page is
- * @param pageNumber the page number. The first page is 1
- * @return the template representing the imported page
- */
- public PdfImportedPage getImportedPage(PdfReader reader, int pageNumber) {
- PdfReaderInstance inst = (PdfReaderInstance)importedPages.get(reader);
- if (inst == null) {
- inst = reader.getPdfReaderInstance(this);
- importedPages.put(reader, inst);
- }
- return inst.getImportedPage(pageNumber);
- }
-
- /** Adds a JavaScript action at the document level. When the document
- * opens all this JavaScript runs.
- * @param js The JavaScrip action
- */
- public void addJavaScript(PdfAction js) {
- pdf.addJavaScript(js);
- }
-
- /** Adds a JavaScript action at the document level. When the document
- * opens all this JavaScript runs.
- * @param code the JavaScript code
- * @param unicode select JavaScript unicode. Note that the internal
- * Acrobat JavaScript engine does not support unicode,
- * so this may or may not work for you
- */
- public void addJavaScript(String code, boolean unicode) {
- addJavaScript(PdfAction.javaScript(code, this, unicode));
- }
-
- /** Adds a JavaScript action at the document level. When the document
- * opens all this JavaScript runs.
- * @param code the JavaScript code
- */
- public void addJavaScript(String code) {
- addJavaScript(code, false);
- }
-
- /** Sets the crop box. The crop box should not be rotated even if the
- * page is rotated. This change only takes effect in the next
- * page.
- * @param crop the crop box
- */
- public void setCropBoxSize(Rectangle crop) {
- pdf.setCropBoxSize(crop);
- }
-
- /** Gets a reference to a page existing or not. If the page does not exist
- * yet the reference will be created in advance. If on closing the document, a
- * page number greater than the total number of pages was requested, an
- * exception is thrown.
- * @param page the page number. The first page is 1
- * @return the reference to the page
- */
- public PdfIndirectReference getPageReference(int page) {
- --page;
- if (page < 0)
- throw new IndexOutOfBoundsException("The page numbers start at 1.");
- PdfIndirectReference ref;
- if (page < pageReferences.size()) {
- ref = (PdfIndirectReference)pageReferences.get(page);
- if (ref == null) {
- ref = body.getPdfIndirectReference();
- pageReferences.set(page, ref);
- }
- }
- else {
- int empty = page - pageReferences.size();
- for (int k = 0; k < empty; ++k)
- pageReferences.add(null);
- ref = body.getPdfIndirectReference();
- pageReferences.add(ref);
- }
- return ref;
- }
-
- PdfIndirectReference getCurrentPage() {
- return getPageReference(currentPageNumber);
- }
-
- int getCurrentPageNumber() {
- return currentPageNumber;
- }
-
- /** Adds the PdfAnnotation
to the calculation order
- * array.
- * @param annot the PdfAnnotation
to be added
- */
- public void addCalculationOrder(PdfFormField annot) {
- pdf.addCalculationOrder(annot);
- }
-
- /** Set the signature flags.
- * @param f the flags. This flags are ORed with current ones
- */
- public void setSigFlags(int f) {
- pdf.setSigFlags(f);
- }
-
- /** Adds a PdfAnnotation
or a PdfFormField
- * to the document. Only the top parent of a PdfFormField
- * needs to be added.
- * @param annot the PdfAnnotation
or the PdfFormField
to add
- */
- public void addAnnotation(PdfAnnotation annot) {
- pdf.addAnnotation(annot);
- }
-
- void addAnnotation(PdfAnnotation annot, int page) {
- addAnnotation(annot);
- }
-
- /** Sets the PDF version. Must be used right before the document
- * is opened. Valid options are VERSION_1_2, VERSION_1_3,
- * VERSION_1_4, VERSION_1_5 and VERSION_1_6. VERSION_1_4 is the default.
- * @param version the version number
- */
- public void setPdfVersion(char version) {
- if (HEADER.length > VPOINT)
- HEADER[VPOINT] = (byte)version;
- }
-
- /** Reorder the pages in the document. A null
argument value
- * only returns the number of pages to process. It is
- * advisable to issue a Document.newPage()
- * before using this method.
- * @return the total number of pages
- * @param order an array with the new page sequence. It must have the
- * same size as the number of pages.
- * @throws DocumentException if all the pages are not present in the array
- */
- public int reorderPages(int order[]) throws DocumentException {
- return root.reorderPages(order);
- }
-
- /** Gets the space/character extra spacing ratio for
- * fully justified text.
- * @return the space/character extra spacing ratio
- */
- public float getSpaceCharRatio() {
- return spaceCharRatio;
- }
-
- /** Sets the ratio between the extra word spacing and the extra character spacing
- * when the text is fully justified.
- * Extra word spacing will grow spaceCharRatio
times more than extra character spacing.
- * If the ratio is PdfWriter.NO_SPACE_CHAR_RATIO
then the extra character spacing
- * will be zero.
- * @param spaceCharRatio the ratio between the extra word spacing and the extra character spacing
- */
- public void setSpaceCharRatio(float spaceCharRatio) {
- if (spaceCharRatio < 0.001f)
- this.spaceCharRatio = 0.001f;
- else
- this.spaceCharRatio = spaceCharRatio;
- }
-
- /** Sets the run direction. This is only used as a placeholder
- * as it does not affect anything.
- * @param runDirection the run direction
- */
- public void setRunDirection(int runDirection) {
- if (runDirection < RUN_DIRECTION_NO_BIDI || runDirection > RUN_DIRECTION_RTL)
- throw new RuntimeException("Invalid run direction: " + runDirection);
- this.runDirection = runDirection;
- }
-
- /** Gets the run direction.
- * @return the run direction
- */
- public int getRunDirection() {
- return runDirection;
- }
-
- /**
- * Sets the display duration for the page (for presentations)
- * @param seconds the number of seconds to display the page
- */
- public void setDuration(int seconds) {
- pdf.setDuration(seconds);
- }
-
- /**
- * Sets the transition for the page
- * @param transition the Transition object
- */
- public void setTransition(PdfTransition transition) {
- pdf.setTransition(transition);
- }
-
- /** Writes the reader to the document and frees the memory used by it.
- * The main use is when concatenating multiple documents to keep the
- * memory usage restricted to the current appending document.
- * @param reader the PdfReader
to free
- * @throws IOException on error
- */
- public void freeReader(PdfReader reader) throws IOException {
- currentPdfReaderInstance = (PdfReaderInstance)importedPages.get(reader);
- if (currentPdfReaderInstance == null)
- return;
- currentPdfReaderInstance.writeAllPages();
- currentPdfReaderInstance = null;
- importedPages.remove(reader);
- }
-
- /** Sets the open and close page additional action.
- * @param actionType the action type. It can be PdfWriter.PAGE_OPEN
- * or PdfWriter.PAGE_CLOSE
- * @param action the action to perform
- * @throws PdfException if the action type is invalid
- */
- public void setPageAction(PdfName actionType, PdfAction action) throws PdfException {
- if (!actionType.equals(PAGE_OPEN) && !actionType.equals(PAGE_CLOSE))
- throw new PdfException("Invalid page additional action type: " + actionType.toString());
- pdf.setPageAction(actionType, action);
- }
-
- /** Gets the current document size. This size only includes
- * the data already writen to the output stream, it does not
- * include templates or fonts. It is usefull if used with
- * freeReader()
when concatenating many documents
- * and an idea of the current size is needed.
- * @return the approximate size without fonts or templates
- */
- public int getCurrentDocumentSize() {
- return body.offset() + body.size() * 20 + 0x48;
- }
-
- /** Getter for property strictImageSequence.
- * @return value of property strictImageSequence
- *
- */
- public boolean isStrictImageSequence() {
- return pdf.isStrictImageSequence();
- }
-
- /** Sets the image sequence to follow the text in strict order.
- * @param strictImageSequence new value of property strictImageSequence
- *
- */
- public void setStrictImageSequence(boolean strictImageSequence) {
- pdf.setStrictImageSequence(strictImageSequence);
- }
-
- /**
- * If you use setPageEmpty(false), invoking newPage() after a blank page will add a newPage.
- * @param pageEmpty the state
- */
- public void setPageEmpty(boolean pageEmpty) {
- pdf.setPageEmpty(pageEmpty);
- }
-
- /** Gets the info dictionary for changing.
- * @return the info dictionary
- */
- public PdfDictionary getInfo() {
- return ((PdfDocument)document).getInfo();
- }
-
- /**
- * Sets extra keys to the catalog.
- * @return the catalog to change
- */
- public PdfDictionary getExtraCatalog() {
- if (extraCatalog == null)
- extraCatalog = new PdfDictionary();
- return this.extraCatalog;
- }
-
- /**
- * Sets the document in a suitable way to do page reordering.
- */
- public void setLinearPageMode() {
- root.setLinearMode(null);
- }
-
- /** Getter for property group.
- * @return Value of property group.
- *
- */
- public PdfDictionary getGroup() {
- return this.group;
- }
-
- /** Setter for property group.
- * @param group New value of property group.
- *
- */
- public void setGroup(PdfDictionary group) {
- this.group = group;
- }
-
- /**
- * Sets the PDFX conformance level. Allowed values are PDFX1A2001 and PDFX32002. It
- * must be called before opening the document.
- * @param pdfxConformance the conformance level
- */
- public void setPDFXConformance(int pdfxConformance) {
- if (this.pdfxConformance == pdfxConformance)
- return;
- if (pdf.isOpen())
- throw new PdfXConformanceException("PDFX conformance can only be set before opening the document.");
- if (crypto != null)
- throw new PdfXConformanceException("A PDFX conforming document cannot be encrypted.");
- if (pdfxConformance != PDFXNONE)
- setPdfVersion(VERSION_1_3);
- this.pdfxConformance = pdfxConformance;
- }
-
- /**
- * Gets the PDFX conformance level.
- * @return the PDFX conformance level
- */
- public int getPDFXConformance() {
- return pdfxConformance;
- }
-
- static void checkPDFXConformance(PdfWriter writer, int key, Object obj1) {
- if (writer == null || writer.pdfxConformance == PDFXNONE)
- return;
- int conf = writer.pdfxConformance;
- switch (key) {
- case PDFXKEY_COLOR:
- switch (conf) {
- case PDFX1A2001:
- if (obj1 instanceof ExtendedColor) {
- ExtendedColor ec = (ExtendedColor)obj1;
- switch (ec.getType()) {
- case ExtendedColor.TYPE_CMYK:
- case ExtendedColor.TYPE_GRAY:
- return;
- case ExtendedColor.TYPE_RGB:
- throw new PdfXConformanceException("Colorspace RGB is not allowed.");
- case ExtendedColor.TYPE_SEPARATION:
- SpotColor sc = (SpotColor)ec;
- checkPDFXConformance(writer, PDFXKEY_COLOR, sc.getPdfSpotColor().getAlternativeCS());
- break;
- case ExtendedColor.TYPE_SHADING:
- ShadingColor xc = (ShadingColor)ec;
- checkPDFXConformance(writer, PDFXKEY_COLOR, xc.getPdfShadingPattern().getShading().getColorSpace());
- break;
- case ExtendedColor.TYPE_PATTERN:
- PatternColor pc = (PatternColor)ec;
- checkPDFXConformance(writer, PDFXKEY_COLOR, pc.getPainter().getDefaultColor());
- break;
- }
- }
- else if (obj1 instanceof Color)
- throw new PdfXConformanceException("Colorspace RGB is not allowed.");
- break;
- }
- break;
- case PDFXKEY_CMYK:
- break;
- case PDFXKEY_RGB:
- if (conf == PDFX1A2001)
- throw new PdfXConformanceException("Colorspace RGB is not allowed.");
- break;
- case PDFXKEY_FONT:
- if (!((BaseFont)obj1).isEmbedded())
- throw new PdfXConformanceException("All the fonts must be embedded.");
- break;
- case PDFXKEY_IMAGE:
- break;
- /*
- PdfImage image = (PdfImage)obj1;
- if (image.get(PdfName.SMASK) != null)
- throw new PdfXConformanceException("The /SMask key is not allowed in images.");
- switch (conf) {
- case PDFX1A2001:
- PdfObject cs = image.get(PdfName.COLORSPACE);
- if (cs == null)
- return;
- if (cs.isName()) {
- if (PdfName.DEVICERGB.equals(cs))
- throw new PdfXConformanceException("Colorspace RGB is not allowed.");
- }
- else if (cs.isArray()) {
- if (PdfName.CALRGB.equals((PdfObject)((PdfArray)cs).getArrayList().get(0)))
- throw new PdfXConformanceException("Colorspace CalRGB is not allowed.");
- }
- break;
- }
- */
- case PDFXKEY_GSTATE:
- PdfDictionary gs = (PdfDictionary)obj1;
- PdfObject obj = gs.get(PdfName.BM);
- if (obj != null && !PdfGState.BM_NORMAL.equals(obj) && !PdfGState.BM_COMPATIBLE.equals(obj))
- throw new PdfXConformanceException("Blend mode " + obj.toString() + " not allowed.");
- obj = gs.get(PdfName.CA);
- double v = 0.0;
- if (obj != null && (v = ((PdfNumber)obj).doubleValue()) != 1.0)
- throw new PdfXConformanceException("Transparency is not allowed: /CA = " + v);
- obj = gs.get(PdfName.ca);
- v = 0.0;
- if (obj != null && (v = ((PdfNumber)obj).doubleValue()) != 1.0)
- throw new PdfXConformanceException("Transparency is not allowed: /ca = " + v);
- break;
- case PDFXKEY_LAYER:
- throw new PdfXConformanceException("Layers are not allowed.");
- }
- }
-
- /**
- * Sets the values of the output intent dictionary. Null values are allowed to
- * suppress any key.
- * @param outputConditionIdentifier a value
- * @param outputCondition a value
- * @param registryName a value
- * @param info a value
- * @param destOutputProfile a value
- * @throws IOException on error
- */
- public void setOutputIntents(String outputConditionIdentifier, String outputCondition, String registryName, String info, byte destOutputProfile[]) throws IOException {
- getExtraCatalog();
- PdfDictionary out = new PdfDictionary(PdfName.OUTPUTINTENT);
- if (outputCondition != null)
- out.put(PdfName.OUTPUTCONDITION, new PdfString(outputCondition, PdfObject.TEXT_UNICODE));
- if (outputConditionIdentifier != null)
- out.put(PdfName.OUTPUTCONDITIONIDENTIFIER, new PdfString(outputConditionIdentifier, PdfObject.TEXT_UNICODE));
- if (registryName != null)
- out.put(PdfName.REGISTRYNAME, new PdfString(registryName, PdfObject.TEXT_UNICODE));
- if (info != null)
- out.put(PdfName.INFO, new PdfString(registryName, PdfObject.TEXT_UNICODE));
- if (destOutputProfile != null) {
- PdfStream stream = new PdfStream(destOutputProfile);
- stream.flateCompress();
- out.put(PdfName.DESTOUTPUTPROFILE, addToBody(stream).getIndirectReference());
- }
- out.put(PdfName.S, PdfName.GTS_PDFX);
- extraCatalog.put(PdfName.OUTPUTINTENTS, new PdfArray(out));
- }
-
- private static String getNameString(PdfDictionary dic, PdfName key) {
- PdfObject obj = PdfReader.getPdfObject(dic.get(key));
- if (obj == null || !obj.isString())
- return null;
- return ((PdfString)obj).toUnicodeString();
- }
-
- /**
- * Copies the output intent dictionary from other document to this one.
- * @param reader the other document
- * @param checkExistence true
to just check for the existence of a valid output intent
- * dictionary, false
to insert the dictionary if it exists
- * @throws IOException on error
- * @return true
if the output intent dictionary exists, false
- * otherwise
- */
- public boolean setOutputIntents(PdfReader reader, boolean checkExistence) throws IOException {
- PdfDictionary catalog = reader.getCatalog();
- PdfArray outs = (PdfArray)PdfReader.getPdfObject(catalog.get(PdfName.OUTPUTINTENTS));
- if (outs == null)
- return false;
- ArrayList arr = outs.getArrayList();
- if (arr.size() == 0)
- return false;
- PdfDictionary out = (PdfDictionary)PdfReader.getPdfObject((PdfObject)arr.get(0));
- PdfObject obj = PdfReader.getPdfObject(out.get(PdfName.S));
- if (obj == null || !PdfName.GTS_PDFX.equals(obj))
- return false;
- if (checkExistence)
- return true;
- PRStream stream = (PRStream)PdfReader.getPdfObject(out.get(PdfName.DESTOUTPUTPROFILE));
- byte destProfile[] = null;
- if (stream != null) {
- destProfile = PdfReader.getStreamBytes(stream);
- }
- setOutputIntents(getNameString(out, PdfName.OUTPUTCONDITIONIDENTIFIER), getNameString(out, PdfName.OUTPUTCONDITION),
- getNameString(out, PdfName.REGISTRYNAME), getNameString(out, PdfName.INFO), destProfile);
- return true;
- }
-
- /**
- * Sets the page box sizes. Allowed names are: "crop", "trim", "art" and "bleed".
- * @param boxName the box size
- * @param size the size
- */
- public void setBoxSize(String boxName, Rectangle size) {
- pdf.setBoxSize(boxName, size);
- }
-
- /**
- * Gets the default colorspaces.
- * @return the default colorspaces
- */
- public PdfDictionary getDefaultColorspace() {
- return defaultColorspace;
- }
-
- /**
- * Sets the default colorspace that will be applied to all the document.
- * The colorspace is only applied if another colorspace with the same name
- * is not present in the content.
- *
- * The colorspace is applied immediately when creating templates and at the page
- * end for the main document content.
- * @param key the name of the colorspace. It can be PdfName.DEFAULTGRAY
, PdfName.DEFAULTRGB
- * or PdfName.DEFAULTCMYK
- * @param cs the colorspace. A null
or PdfNull
removes any colorspace with the same name
- */
- public void setDefaultColorspace(PdfName key, PdfObject cs) {
- if (cs == null || cs.isNull())
- defaultColorspace.remove(key);
- defaultColorspace.put(key, cs);
- }
-
- /**
- * Gets the 1.5 compression status.
- * @return true
if the 1.5 compression is on
- */
- public boolean isFullCompression() {
- return this.fullCompression;
- }
-
- /**
- * Sets the document's compression to the new 1.5 mode with object streams and xref
- * streams. It can be set at any time but once set it can't be unset.
- *
- * If set before opening the document it will also set the pdf version to 1.5.
- */
- public void setFullCompression() {
- this.fullCompression = true;
- setPdfVersion(VERSION_1_5);
- }
-
- /**
- * Gets the Optional Content Properties Dictionary . Each call fills the dictionary with the current layer
- * state. It's advisable to only call this method right before close and do any modifications
- * at that time.
- * @return the Optional Content Properties Dictionary
- */
- public PdfOCProperties getOCProperties() {
- fillOCProperties(true);
- return OCProperties;
- }
-
- /**
- * Sets a collection of optional content groups whose states are intended to follow
- * a "radio button" paradigm. That is, the state of at most one optional
- * content group in the array should be ON at a time: if one group is turned
- * ON, all others must be turned OFF.
- * @param group the radio group
- */
- public void addOCGRadioGroup(ArrayList group) {
- PdfArray ar = new PdfArray();
- for (int k = 0; k < group.size(); ++k) {
- PdfLayer layer = (PdfLayer)group.get(k);
- if (layer.getTitle() == null)
- ar.add(layer.getRef());
- }
- if (ar.size() == 0)
- return;
- OCGRadioGroup.add(ar);
- }
-
- /**
- * Sets the the thumbnail image for the current page.
- * @param image the image
- * @throws PdfException on error
- * @throws DocumentException or error
- */
- /* ssteward: dropped in 1.44
- public void setThumbnail(Image image) throws PdfException, DocumentException {
- pdf.setThumbnail(image);
- }
- */
-
- /**
- * A UserUnit is a value that defines the default user space unit.
- * The minimum UserUnit is 1 (1 unit = 1/72 inch).
- * The maximum UserUnit is 75,000.
- * Remark that this userunit only works starting with PDF1.6!
- * @return Returns the userunit.
- */
- public float getUserunit() {
- return userunit;
- }
- /**
- * A UserUnit is a value that defines the default user space unit.
- * The minimum UserUnit is 1 (1 unit = 1/72 inch).
- * The maximum UserUnit is 75,000.
- * Remark that this userunit only works starting with PDF1.6!
- * @param userunit The userunit to set.
- * @throws DocumentException
- */
- public void setUserunit(float userunit) throws DocumentException {
- if (userunit < 1f || userunit > 75000f) throw new DocumentException("UserUnit should be a value between 1 and 75000.");
- this.userunit = userunit;
- setPdfVersion(VERSION_1_6);
- }
-
- /**
- * Sets XMP Metadata.
- * @param xmpMetadata The xmpMetadata to set.
- */
- public void setXmpMetadata(byte[] xmpMetadata) {
- this.xmpMetadata = xmpMetadata;
- }
-
- /**
- * Creates XMP Metadata based on the metadata in the PdfDocument.
- */
- public void createXmpMetadata() {
- setXmpMetadata(pdf.createXmpMetadata());
- }
-
- /**
- * Releases the memory used by a template by writing it to the output. The template
- * can still be added to any content but changes to the template itself won't have
- * any effect.
- * @param tp the template to release
- * @throws IOException on error
- */
- public void releaseTemplate(PdfTemplate tp) throws IOException {
- PdfIndirectReference ref = tp.getIndirectReference();
- Object[] objs = (Object[])formXObjects.get(ref);
- if (objs == null || objs[1] == null)
- return;
- PdfTemplate template = (PdfTemplate)objs[1];
- if (template.getIndirectReference() instanceof PRIndirectReference)
- return;
- if (template.getType() == PdfTemplate.TYPE_TEMPLATE) {
- addToBody(template.getFormXObject(), template.getIndirectReference());
- objs[1] = null;
- }
- }
-
- /**
- * Mark this document for tagging. It must be called before open.
- */
- public void setTagged() {
- if (open)
- throw new IllegalArgumentException("Tagging must be set before opening the document.");
- tagged = true;
- }
-
- /**
- * Check if the document is marked for tagging.
- * @return true
if the document is marked for tagging
- */
- public boolean isTagged() {
- return tagged;
- }
-
- /**
- * Set the PDF ID; ssteward
- */
- public void setFileID( PdfObject fileID ) {
- this.fileID = fileID;
- }
-
- /**
- * Get the pre-set PDF ID; ssteward
- */
- public PdfObject getFileID() {
- return( this.fileID );
- }
-
- /**
- * Gets the structure tree root. If the document is not marked for tagging it will return null
.
- * @return the structure tree root
- */
- public PdfStructureTreeRoot getStructureTreeRoot() {
- if (tagged && structureTreeRoot == null)
- structureTreeRoot = new PdfStructureTreeRoot(this);
- return structureTreeRoot;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/PdfXConformanceException.java pdftk-2.01/java/com/lowagie/text/pdf/PdfXConformanceException.java
--- pdftk-1.45/java/com/lowagie/text/pdf/PdfXConformanceException.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/PdfXConformanceException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,76 +0,0 @@
-/*
- * $Id: PdfXConformanceException.java,v 1.2 2005/02/17 09:20:54 blowagie Exp $
- * $Name: $
- *
- * Copyright 2004 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- *
- * @author psoares
- */
-public class PdfXConformanceException extends RuntimeException {
-
- /** Creates a new instance of PdfXConformanceException. */
- public PdfXConformanceException() {
- }
-
- /**
- * Creates a new instance of PdfXConformanceException.
- * @param s
- */
- public PdfXConformanceException(String s) {
- super(s);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/Pfm2afm.java pdftk-2.01/java/com/lowagie/text/pdf/Pfm2afm.java
--- pdftk-1.45/java/com/lowagie/text/pdf/Pfm2afm.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/Pfm2afm.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,779 +0,0 @@
-/*
- * Copyright 2005 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-/********************************************************************
- * *
- * Title: pfm2afm - Convert Windows .pfm files to .afm files *
- * *
- * Author: Ken Borgendale 10/9/91 Version 1.0 *
- * *
- * Function: *
- * Convert a Windows .pfm (Printer Font Metrics) file to a *
- * .afm (Adobe Font Metrics) file. The purpose of this is *
- * to allow fonts put out for Windows to be used with OS/2. *
- * *
- * Syntax: *
- * pfm2afm infile [outfile] -a *
- * *
- * Copyright: *
- * pfm2afm - Copyright (C) IBM Corp., 1991 *
- * *
- * This code is released for public use as long as the *
- * copyright remains intact. This code is provided asis *
- * without any warrenties, express or implied. *
- * *
- * Notes: *
- * 1. Much of the information in the original .afm file is *
- * lost when the .pfm file is created, and thus cannot be *
- * reconstructed by this utility. This is especially true *
- * of data for characters not in the Windows character set. *
- * *
- * 2. This module is coded to be compiled by the MSC 6.0. *
- * For other compilers, be careful of the packing of the *
- * PFM structure. *
- * *
- ********************************************************************/
-
-/********************************************************************
- * *
- * Modifications by Rod Smith, 5/22/96 *
- * *
- * These changes look for the strings "italic", "bold", "black", *
- * and "light" in the font's name and set the weight accordingly *
- * and adds an ItalicAngle line with a value of "0" or "-12.00". *
- * This allows OS/2 programs such as DeScribe to handle the bold *
- * and italic attributes appropriately, which was not the case *
- * when I used the original version on fonts from the KeyFonts *
- * Pro 2002 font CD. *
- * *
- * I've also increased the size of the buffer used to load the *
- * .PFM file; the old size was inadequate for most of the fonts *
- * from the SoftKey collection. *
- * *
- * Compiled with Watcom C 10.6 *
- * *
- ********************************************************************/
-
-/********************************************************************
- * *
- * Further modifications, 4/21/98, by Rod Smith *
- * *
- * Minor changes to get the program to compile with gcc under *
- * Linux (Red Hat 5.0, to be precise). I had to add an itoa *
- * function from the net (the function was buggy, so I had to fix *
- * it, too!). I also made the program more friendly towards *
- * files with mixed-case filenames. *
- * *
- ********************************************************************/
-package com.lowagie.text.pdf;
-
-import java.io.*;
-
-/**
- * Converts a PFM file into an AFM file.
- */
-public class Pfm2afm {
- private RandomAccessFileOrArray in;
- private PrintWriter out;
-
- /** Creates a new instance of Pfm2afm */
- private Pfm2afm(RandomAccessFileOrArray in, OutputStream out) throws IOException {
- this.in = in;
- this.out = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1"));
- }
-
- /**
- * Converts a PFM file into an AFM file.
- * @param in the PFM file
- * @param out the AFM file
- * @throws IOException on error
- */
- public static void convert(RandomAccessFileOrArray in, OutputStream out) throws IOException {
- Pfm2afm p = new Pfm2afm(in, out);
- p.openpfm();
- p.putheader();
- p.putchartab();
- p.putkerntab();
- p.puttrailer();
- p.out.flush();
- }
-
- public static void main(String[] args) {
- try {
- RandomAccessFileOrArray in = new RandomAccessFileOrArray(args[0]);
- OutputStream out = new FileOutputStream(args[1]);
- convert(in, out);
- in.close();
- out.close();
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private String readString(int n) throws IOException {
- byte b[] = new byte[n];
- in.readFully(b);
- int k;
- for (k = 0; k < b.length; ++k) {
- if (b[k] == 0)
- break;
- }
- return new String(b, 0, k, "ISO-8859-1");
- }
-
- private String readString() throws IOException {
- StringBuffer buf = new StringBuffer();
- while (true) {
- int c = in.read();
- if (c <= 0)
- break;
- buf.append((char)c);
- }
- return buf.toString();
- }
-
- private void outval(int n) {
- out.print(' ');
- out.print(n);
- }
-
- /*
- * Output a character entry
- */
- private void outchar(int code, int width, String name) {
- out.print("C ");
- outval(code);
- out.print(" ; WX ");
- outval(width);
- if (name != null) {
- out.print(" ; N ");
- out.print(name);
- }
- out.print(" ;\n");
- }
-
- private void openpfm() throws IOException {
- in.seek(0);
- vers = in.readShortLE();
- h_len = in.readIntLE();
- copyright = readString(60);
- type = in.readShortLE();
- points = in.readShortLE();
- verres = in.readShortLE();
- horres = in.readShortLE();
- ascent = in.readShortLE();
- intleading = in.readShortLE();
- extleading = in.readShortLE();
- italic = (byte)in.read();
- uline = (byte)in.read();
- overs = (byte)in.read();
- weight = in.readShortLE();
- charset = (byte)in.read();
- pixwidth = in.readShortLE();
- pixheight = in.readShortLE();
- kind = (byte)in.read();
- avgwidth = in.readShortLE();
- maxwidth = in.readShortLE();
- firstchar = in.read();
- lastchar = in.read();
- defchar = (byte)in.read();
- brkchar = (byte)in.read();
- widthby = in.readShortLE();
- device = in.readIntLE();
- face = in.readIntLE();
- bits = in.readIntLE();
- bitoff = in.readIntLE();
- extlen = in.readShortLE();
- psext = in.readIntLE();
- chartab = in.readIntLE();
- res1 = in.readIntLE();
- kernpairs = in.readIntLE();
- res2 = in.readIntLE();
- fontname = in.readIntLE();
- if (h_len != in.length() || extlen != 30 || fontname < 75 || fontname > 512)
- throw new IOException("Not a valid PFM file.");
- in.seek(psext + 14);
- capheight = in.readShortLE();
- xheight = in.readShortLE();
- ascender = in.readShortLE();
- descender = in.readShortLE();
- }
-
- private void putheader() throws IOException {
- out.print("StartFontMetrics 2.0\n");
- if (copyright.length() > 0)
- out.print("Comment " + copyright + '\n');
- out.print("FontName ");
- in.seek(fontname);
- String fname = readString();
- out.print(fname);
- out.print("\nEncodingScheme ");
- if (charset != 0)
- out.print("FontSpecific\n");
- else
- out.print("AdobeStandardEncoding\n");
- /*
- * The .pfm is missing full name, so construct from font name by
- * changing the hyphen to a space. This actually works in a lot
- * of cases.
- */
- out.print("FullName " + fname.replace('-', ' '));
- if (face != 0) {
- in.seek(face);
- out.print("\nFamilyName " + readString());
- }
-
- out.print("\nWeight ");
- if (weight > 475 || fname.toLowerCase().indexOf("bold") >= 0)
- out.print("Bold");
- else if ((weight < 325 && weight != 0) || fname.toLowerCase().indexOf("light") >= 0)
- out.print("Light");
- else if (fname.toLowerCase().indexOf("black") >= 0)
- out.print("Black");
- else
- out.print("Medium");
-
- out.print("\nItalicAngle ");
- if (italic != 0 || fname.toLowerCase().indexOf("italic") >= 0)
- out.print("-12.00");
- /* this is a typical value; something else may work better for a
- specific font */
- else
- out.print("0");
-
- /*
- * The mono flag in the pfm actually indicates whether there is a
- * table of font widths, not if they are all the same.
- */
- out.print("\nIsFixedPitch ");
- if ((kind & 1) == 0 || /* Flag for mono */
- avgwidth == maxwidth ) { /* Avg width = max width */
- out.print("true");
- isMono = true;
- }
- else {
- out.print("false");
- isMono = false;
- }
-
- /*
- * The font bounding box is lost, but try to reconstruct it.
- * Much of this is just guess work. The bounding box is required in
- * the .afm, but is not used by the PM font installer.
- */
- out.print("\nFontBBox");
- if (isMono)
- outval(-20); /* Just guess at left bounds */
- else
- outval(-100);
- outval(-(descender+5)); /* Descender is given as positive value */
- outval(maxwidth+10);
- outval(ascent+5);
-
- /*
- * Give other metrics that were kept
- */
- out.print("\nCapHeight");
- outval(capheight);
- out.print("\nXHeight");
- outval(xheight);
- out.print("\nDescender");
- outval(descender);
- out.print("\nAscender");
- outval(ascender);
- out.print('\n');
- }
-
- private void putchartab() throws IOException {
- int count = lastchar - firstchar + 1;
- int ctabs[] = new int[count];
- in.seek(chartab);
- for (int k = 0; k < count; ++k)
- ctabs[k] = in.readUnsignedShortLE();
- int back[] = new int[256];
- if (charset == 0) {
- for (int i = firstchar; i <= lastchar; ++i) {
- if (Win2PSStd[i] != 0)
- back[Win2PSStd[i]] = i;
- }
- }
- /* Put out the header */
- out.print("StartCharMetrics");
- outval(count);
- out.print('\n');
-
- /* Put out all encoded chars */
- if (charset != 0) {
- /*
- * If the charset is not the Windows standard, just put out
- * unnamed entries.
- */
- for (int i = firstchar; i <= lastchar; i++) {
- if (ctabs[i - firstchar] != 0) {
- outchar(i, ctabs[i - firstchar], null);
- }
- }
- }
- else {
- for (int i = 0; i < 256; i++) {
- int j = back[i];
- if (j != 0) {
- outchar(i, ctabs[j - firstchar], WinChars[j]);
- ctabs[j - firstchar] = 0;
- }
- }
- /* Put out all non-encoded chars */
- for (int i = firstchar; i <= lastchar; i++) {
- if (ctabs[i - firstchar] != 0) {
- outchar(-1, ctabs[i - firstchar], WinChars[i]);
- }
- }
- }
- /* Put out the trailer */
- out.print("EndCharMetrics\n");
-
- }
-
- private void putkerntab() throws IOException {
- if (kernpairs == 0)
- return;
- in.seek(kernpairs);
- int count = in.readUnsignedShortLE();
- int nzero = 0;
- int kerns[] = new int[count * 3];
- for (int k = 0; k < kerns.length;) {
- kerns[k++] = in.read();
- kerns[k++] = in.read();
- if ((kerns[k++] = in.readShortLE()) != 0)
- ++nzero;
- }
- if (nzero == 0)
- return;
- out.print("StartKernData\nStartKernPairs");
- outval(nzero);
- out.print('\n');
- for (int k = 0; k < kerns.length; k += 3) {
- if (kerns[k + 2] != 0) {
- out.print("KPX ");
- out.print(WinChars[kerns[k]]);
- out.print(' ');
- out.print(WinChars[kerns[k + 1]]);
- outval(kerns[k + 2]);
- out.print('\n');
- }
- }
- /* Put out trailer */
- out.print("EndKernPairs\nEndKernData\n");
- }
-
-
- private void puttrailer() {
- out.print("EndFontMetrics\n");
- }
-
- private short vers;
- private int h_len; /* Total length of .pfm file */
- private String copyright; /* Copyright string [60]*/
- private short type;
- private short points;
- private short verres;
- private short horres;
- private short ascent;
- private short intleading;
- private short extleading;
- private byte italic;
- private byte uline;
- private byte overs;
- private short weight;
- private byte charset; /* 0=windows, otherwise nomap */
- private short pixwidth; /* Width for mono fonts */
- private short pixheight;
- private byte kind; /* Lower bit off in mono */
- private short avgwidth; /* Mono if avg=max width */
- private short maxwidth; /* Use to compute bounding box */
- private int firstchar; /* First char in table */
- private int lastchar; /* Last char in table */
- private byte defchar;
- private byte brkchar;
- private short widthby;
- private int device;
- private int face; /* Face name */
- private int bits;
- private int bitoff;
- private short extlen;
- private int psext; /* PostScript extension */
- private int chartab; /* Character width tables */
- private int res1;
- private int kernpairs; /* Kerning pairs */
- private int res2;
- private int fontname; /* Font name */
-
-/*
- * Some metrics from the PostScript extension
- */
- private short capheight; /* Cap height */
- private short xheight; /* X height */
- private short ascender; /* Ascender */
- private short descender; /* Descender (positive) */
-
-
- private boolean isMono;
-/*
- * Translate table from 1004 to psstd. 1004 is an extension of the
- * Windows translate table used in PM.
- */
- private int Win2PSStd[] = {
- 0, 0, 0, 0, 197, 198, 199, 0, 202, 0, 205, 206, 207, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 32, 33, 34, 35, 36, 37, 38, 169, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 193, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
- 0, 0, 184, 0, 185, 188, 178, 179, 94, 189, 0, 172, 234, 0, 0, 0,
- 0, 96, 0, 170, 186, 0, 177, 208, 126, 0, 0, 173, 250, 0, 0, 0,
- 0, 161, 162, 163, 168, 165, 0, 167, 200, 0, 227, 171, 0, 0, 0, 0,
- 0, 0, 0, 0, 194, 0, 182, 180, 203, 0, 235, 187, 0, 0, 0, 191,
- 0, 0, 0, 0, 0, 0, 225, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 251,
- 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 0, 0, 0, 0, 0
- };
-
-/*
- * Character class. This is a minor attempt to overcome the problem that
- * in the pfm file, all unused characters are given the width of space.
- */
- private int WinClass[] = {
- 0, 0, 0, 0, 2, 2, 2, 0, 2, 0, 2, 2, 2, 0, 0, 0, /* 00 */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, /* 70 */
- 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, /* 80 */
- 0, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, /* 90 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a0 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b0 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* c0 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* d0 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e0 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* f0 */
- };
-
-/*
- * Windows chararacter names. Give a name to the usused locations
- * for when the all flag is specified.
- */
- private String WinChars[] = {
- "W00", /* 00 */
- "W01", /* 01 */
- "W02", /* 02 */
- "W03", /* 03 */
- "macron", /* 04 */
- "breve", /* 05 */
- "dotaccent", /* 06 */
- "W07", /* 07 */
- "ring", /* 08 */
- "W09", /* 09 */
- "W0a", /* 0a */
- "W0b", /* 0b */
- "W0c", /* 0c */
- "W0d", /* 0d */
- "W0e", /* 0e */
- "W0f", /* 0f */
- "hungarumlaut", /* 10 */
- "ogonek", /* 11 */
- "caron", /* 12 */
- "W13", /* 13 */
- "W14", /* 14 */
- "W15", /* 15 */
- "W16", /* 16 */
- "W17", /* 17 */
- "W18", /* 18 */
- "W19", /* 19 */
- "W1a", /* 1a */
- "W1b", /* 1b */
- "W1c", /* 1c */
- "W1d", /* 1d */
- "W1e", /* 1e */
- "W1f", /* 1f */
- "space", /* 20 */
- "exclam", /* 21 */
- "quotedbl", /* 22 */
- "numbersign", /* 23 */
- "dollar", /* 24 */
- "percent", /* 25 */
- "ampersand", /* 26 */
- "quotesingle", /* 27 */
- "parenleft", /* 28 */
- "parenright", /* 29 */
- "asterisk", /* 2A */
- "plus", /* 2B */
- "comma", /* 2C */
- "hyphen", /* 2D */
- "period", /* 2E */
- "slash", /* 2F */
- "zero", /* 30 */
- "one", /* 31 */
- "two", /* 32 */
- "three", /* 33 */
- "four", /* 34 */
- "five", /* 35 */
- "six", /* 36 */
- "seven", /* 37 */
- "eight", /* 38 */
- "nine", /* 39 */
- "colon", /* 3A */
- "semicolon", /* 3B */
- "less", /* 3C */
- "equal", /* 3D */
- "greater", /* 3E */
- "question", /* 3F */
- "at", /* 40 */
- "A", /* 41 */
- "B", /* 42 */
- "C", /* 43 */
- "D", /* 44 */
- "E", /* 45 */
- "F", /* 46 */
- "G", /* 47 */
- "H", /* 48 */
- "I", /* 49 */
- "J", /* 4A */
- "K", /* 4B */
- "L", /* 4C */
- "M", /* 4D */
- "N", /* 4E */
- "O", /* 4F */
- "P", /* 50 */
- "Q", /* 51 */
- "R", /* 52 */
- "S", /* 53 */
- "T", /* 54 */
- "U", /* 55 */
- "V", /* 56 */
- "W", /* 57 */
- "X", /* 58 */
- "Y", /* 59 */
- "Z", /* 5A */
- "bracketleft", /* 5B */
- "backslash", /* 5C */
- "bracketright", /* 5D */
- "asciicircum", /* 5E */
- "underscore", /* 5F */
- "grave", /* 60 */
- "a", /* 61 */
- "b", /* 62 */
- "c", /* 63 */
- "d", /* 64 */
- "e", /* 65 */
- "f", /* 66 */
- "g", /* 67 */
- "h", /* 68 */
- "i", /* 69 */
- "j", /* 6A */
- "k", /* 6B */
- "l", /* 6C */
- "m", /* 6D */
- "n", /* 6E */
- "o", /* 6F */
- "p", /* 70 */
- "q", /* 71 */
- "r", /* 72 */
- "s", /* 73 */
- "t", /* 74 */
- "u", /* 75 */
- "v", /* 76 */
- "w", /* 77 */
- "x", /* 78 */
- "y", /* 79 */
- "z", /* 7A */
- "braceleft", /* 7B */
- "bar", /* 7C */
- "braceright", /* 7D */
- "asciitilde", /* 7E */
- "W7f", /* 7F */
- "W80", /* 80 */
- "W81", /* 81 */
- "quotesinglbase", /* 82 */
- "W83", /* 83 */
- "quotedblbase", /* 84 */
- "ellipsis", /* 85 */
- "dagger", /* 86 */
- "daggerdbl", /* 87 */
- "asciicircum", /* 88 */
- "perthousand", /* 89 */
- "Scaron", /* 8A */
- "guilsinglleft", /* 8B */
- "OE", /* 8C */
- "W8d", /* 8D */
- "W8e", /* 8E */
- "W8f", /* 8F */
- "W90", /* 90 */
- "quoteleft", /* 91 */
- "quoteright", /* 92 */
- "quotedblleft", /* 93 */
- "quotedblright", /* 94 */
- "bullet1", /* 95 */
- "endash", /* 96 */
- "emdash", /* 97 */
- "asciitilde", /* 98 */
- "trademark", /* 99 */
- "scaron", /* 9A */
- "guilsinglright", /* 9B */
- "oe", /* 9C */
- "W9d", /* 9D */
- "W9e", /* 9E */
- "Ydieresis", /* 9F */
- "reqspace", /* A0 */
- "exclamdown", /* A1 */
- "cent", /* A2 */
- "sterling", /* A3 */
- "currency", /* A4 */
- "yen", /* A5 */
- "brokenbar", /* A6 */
- "section", /* A7 */
- "dieresis", /* A8 */
- "copyright", /* A9 */
- "ordfeminine", /* AA */
- "guillemotleft", /* AB */
- "logicalnot", /* AC */
- "syllable", /* AD */
- "registered", /* AE */
- "overbar", /* AF */
- "degree", /* B0 */
- "plusminus", /* B1 */
- "twosuperior", /* B2 */
- "threesuperior", /* B3 */
- "acute", /* B4 */
- "mu", /* B5 */
- "paragraph", /* B6 */
- "periodcentered", /* B7 */
- "cedilla", /* B8 */
- "onesuperior", /* B9 */
- "ordmasculine", /* BA */
- "guillemotright", /* BB */
- "onequarter", /* BC */
- "onehalf", /* BD */
- "threequarters", /* BE */
- "questiondown", /* BF */
- "Agrave", /* C0 */
- "Aacute", /* C1 */
- "Acircumflex", /* C2 */
- "Atilde", /* C3 */
- "Adieresis", /* C4 */
- "Aring", /* C5 */
- "AE", /* C6 */
- "Ccedilla", /* C7 */
- "Egrave", /* C8 */
- "Eacute", /* C9 */
- "Ecircumflex", /* CA */
- "Edieresis", /* CB */
- "Igrave", /* CC */
- "Iacute", /* CD */
- "Icircumflex", /* CE */
- "Idieresis", /* CF */
- "Eth", /* D0 */
- "Ntilde", /* D1 */
- "Ograve", /* D2 */
- "Oacute", /* D3 */
- "Ocircumflex", /* D4 */
- "Otilde", /* D5 */
- "Odieresis", /* D6 */
- "multiply", /* D7 */
- "Oslash", /* D8 */
- "Ugrave", /* D9 */
- "Uacute", /* DA */
- "Ucircumflex", /* DB */
- "Udieresis", /* DC */
- "Yacute", /* DD */
- "Thorn", /* DE */
- "germandbls", /* DF */
- "agrave", /* E0 */
- "aacute", /* E1 */
- "acircumflex", /* E2 */
- "atilde", /* E3 */
- "adieresis", /* E4 */
- "aring", /* E5 */
- "ae", /* E6 */
- "ccedilla", /* E7 */
- "egrave", /* E8 */
- "eacute", /* E9 */
- "ecircumflex", /* EA */
- "edieresis", /* EB */
- "igrave", /* EC */
- "iacute", /* ED */
- "icircumflex", /* EE */
- "idieresis", /* EF */
- "eth", /* F0 */
- "ntilde", /* F1 */
- "ograve", /* F2 */
- "oacute", /* F3 */
- "ocircumflex", /* F4 */
- "otilde", /* F5 */
- "odieresis", /* F6 */
- "divide", /* F7 */
- "oslash", /* F8 */
- "ugrave", /* F9 */
- "uacute", /* FA */
- "ucircumflex", /* FB */
- "udieresis", /* FC */
- "yacute", /* FD */
- "thorn", /* FE */
- "ydieresis" /* FF */
- };
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/RandomAccessFileOrArray.java pdftk-2.01/java/com/lowagie/text/pdf/RandomAccessFileOrArray.java
--- pdftk-1.45/java/com/lowagie/text/pdf/RandomAccessFileOrArray.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/RandomAccessFileOrArray.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,622 +0,0 @@
-/*
- * $Id: RandomAccessFileOrArray.java,v 1.48 2005/09/11 08:38:18 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.DataInputStream;
-import java.io.DataInput;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.EOFException;
-import java.io.RandomAccessFile;
-import java.io.File;
-import java.io.InputStream;
-import java.io.ByteArrayOutputStream;
-import java.net.URL;
-/** An implementation of a RandomAccessFile for input only
- * that accepts a file or a byte array as data source.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class RandomAccessFileOrArray implements DataInput {
-
- RandomAccessFile rf;
- String filename;
- byte arrayIn[];
- int arrayInPtr;
- byte back;
- boolean isBack = false;
-
- /** Holds value of property startOffset. */
- private int startOffset = 0;
-
- public RandomAccessFileOrArray(String filename) throws IOException {
- this(filename, false);
- }
-
- public RandomAccessFileOrArray(String filename, boolean forceRead) throws IOException {
- File file = new File(filename);
- if (!file.canRead()) {
- if (filename.startsWith("file:/") || filename.startsWith("http://") || filename.startsWith("https://") || filename.startsWith("jar:")) {
- InputStream is = new URL(filename).openStream();
- try {
- this.arrayIn = InputStreamToArray(is);
- return;
- }
- finally {
- try {is.close();}catch(IOException ioe){}
- }
- }
- else {
- InputStream is;
- if( filename.equals("-") ) {
- // ssteward, pdftk 1.10; patch provided by Bart Orbons to permit stdin input via pdftk
- is = System.in;
- }
- else {
- is = BaseFont.getResourceStream(filename);
- }
- if (is == null)
- throw new IOException(filename + " not found as file or resource.");
- try {
- this.arrayIn = InputStreamToArray(is);
- return;
- }
- finally {
- try {is.close();}catch(IOException ioe){}
- }
- }
- }
- else if (forceRead) {
- InputStream s = null;
- try {
- s = new FileInputStream(file);
- this.arrayIn = InputStreamToArray(s);
- }
- finally {
- try {s.close();}catch(Exception e){}
- }
- return;
- }
- this.filename = filename;
- rf = new RandomAccessFile(filename, "r");
- }
-
- public RandomAccessFileOrArray(URL url) throws IOException {
- InputStream is = url.openStream();
- try {
- this.arrayIn = InputStreamToArray(is);
- }
- finally {
- try {is.close();}catch(IOException ioe){}
- }
- }
-
- public RandomAccessFileOrArray(InputStream is) throws IOException {
- this.arrayIn = InputStreamToArray(is);
- }
-
- public static byte[] InputStreamToArray(InputStream is) throws IOException {
- byte b[] = new byte[8192];
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- while (true) {
- int read = is.read(b);
- if (read < 1)
- break;
- out.write(b, 0, read);
- }
- return out.toByteArray();
- }
-
- public RandomAccessFileOrArray(byte arrayIn[]) {
- this.arrayIn = arrayIn;
- }
-
- public RandomAccessFileOrArray(RandomAccessFileOrArray file) {
- filename = file.filename;
- arrayIn = file.arrayIn;
- startOffset = file.startOffset;
- }
-
- public void pushBack(byte b) {
- back = b;
- isBack = true;
- }
-
- public int read() throws IOException {
- if(isBack) {
- isBack = false;
- return back & 0xff;
- }
- if (arrayIn == null)
- return rf.read();
- else {
- if (arrayInPtr >= arrayIn.length)
- return -1;
- return arrayIn[arrayInPtr++] & 0xff;
- }
- }
-
- public int read(byte[] b, int off, int len) throws IOException {
- if (len == 0)
- return 0;
- int n = 0;
- if (isBack) {
- isBack = false;
- if (len == 1) {
- b[off] = back;
- return 1;
- }
- else {
- n = 1;
- b[off++] = back;
- --len;
- }
- }
- if (arrayIn == null) {
- return rf.read(b, off, len) + n;
- }
- else {
- if (arrayInPtr >= arrayIn.length)
- return -1;
- if (arrayInPtr + len > arrayIn.length)
- len = arrayIn.length - arrayInPtr;
- System.arraycopy(arrayIn, arrayInPtr, b, off, len);
- arrayInPtr += len;
- return len + n;
- }
- }
-
- public int read(byte b[]) throws IOException {
- return read(b, 0, b.length);
- }
-
- public void readFully(byte b[]) throws IOException {
- readFully(b, 0, b.length);
- }
-
- public void readFully(byte b[], int off, int len) throws IOException {
- int n = 0;
- do {
- int count = read(b, off + n, len - n);
- if (count < 0)
- throw new EOFException();
- n += count;
- } while (n < len);
- }
-
- public long skip(long n) throws IOException {
- return skipBytes((int)n);
- }
-
- public int skipBytes(int n) throws IOException {
- if (n <= 0) {
- return 0;
- }
- int adj = 0;
- if (isBack) {
- isBack = false;
- if (n == 1) {
- return 1;
- }
- else {
- --n;
- adj = 1;
- }
- }
- int pos;
- int len;
- int newpos;
-
- pos = getFilePointer();
- len = length();
- newpos = pos + n;
- if (newpos > len) {
- newpos = len;
- }
- seek(newpos);
-
- /* return the actual number of bytes skipped */
- return newpos - pos + adj;
- }
-
- public void reOpen() throws IOException {
- if (filename != null && rf == null)
- rf = new RandomAccessFile(filename, "r");
- seek(0);
- }
-
- protected void insureOpen() throws IOException {
- if (filename != null && rf == null) {
- reOpen();
- }
- }
-
- public boolean isOpen() {
- return (filename == null || rf != null);
- }
-
- public void close() throws IOException {
- isBack = false;
- if (rf != null) {
- rf.close();
- rf = null;
- }
- }
-
- public int length() throws IOException {
- if (arrayIn == null) {
- insureOpen();
- return (int)rf.length() - startOffset;
- }
- else
- return arrayIn.length - startOffset;
- }
-
- public void seek(int pos) throws IOException {
- pos += startOffset;
- isBack = false;
- if (arrayIn == null) {
- insureOpen();
- rf.seek(pos);
- }
- else
- arrayInPtr = pos;
- }
-
- public void seek(long pos) throws IOException {
- seek((int)pos);
- }
-
- public int getFilePointer() throws IOException {
- insureOpen();
- int n = isBack ? 1 : 0;
- if (arrayIn == null) {
- return (int)rf.getFilePointer() - n - startOffset;
- }
- else
- return arrayInPtr - n - startOffset;
- }
-
- public boolean readBoolean() throws IOException {
- int ch = this.read();
- if (ch < 0)
- throw new EOFException();
- return (ch != 0);
- }
-
- public byte readByte() throws IOException {
- int ch = this.read();
- if (ch < 0)
- throw new EOFException();
- return (byte)(ch);
- }
-
- public int readUnsignedByte() throws IOException {
- int ch = this.read();
- if (ch < 0)
- throw new EOFException();
- return ch;
- }
-
- public short readShort() throws IOException {
- int ch1 = this.read();
- int ch2 = this.read();
- if ((ch1 | ch2) < 0)
- throw new EOFException();
- return (short)((ch1 << 8) + ch2);
- }
-
- /**
- * Reads a signed 16-bit number from this stream in little-endian order.
- * The method reads two
- * bytes from this stream, starting at the current stream pointer.
- * If the two bytes read, in order, are
- * b1
and b2
, where each of the two values is
- * between 0
and 255
, inclusive, then the
- * result is equal to:
- *
- * (short)((b2 << 8) | b1)
- *
- *
- * This method blocks until the two bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next two bytes of this stream, interpreted as a signed
- * 16-bit number.
- * @exception EOFException if this stream reaches the end before reading
- * two bytes.
- * @exception IOException if an I/O error occurs.
- */
- public final short readShortLE() throws IOException {
- int ch1 = this.read();
- int ch2 = this.read();
- if ((ch1 | ch2) < 0)
- throw new EOFException();
- return (short)((ch2 << 8) + (ch1 << 0));
- }
-
- public int readUnsignedShort() throws IOException {
- int ch1 = this.read();
- int ch2 = this.read();
- if ((ch1 | ch2) < 0)
- throw new EOFException();
- return (ch1 << 8) + ch2;
- }
-
- /**
- * Reads an unsigned 16-bit number from this stream in little-endian order.
- * This method reads
- * two bytes from the stream, starting at the current stream pointer.
- * If the bytes read, in order, are
- * b1
and b2
, where
- * 0 <= b1, b2 <= 255
,
- * then the result is equal to:
- *
- * (b2 << 8) | b1
- *
- *
- * This method blocks until the two bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next two bytes of this stream, interpreted as an
- * unsigned 16-bit integer.
- * @exception EOFException if this stream reaches the end before reading
- * two bytes.
- * @exception IOException if an I/O error occurs.
- */
- public final int readUnsignedShortLE() throws IOException {
- int ch1 = this.read();
- int ch2 = this.read();
- if ((ch1 | ch2) < 0)
- throw new EOFException();
- return (ch2 << 8) + (ch1 << 0);
- }
-
- public char readChar() throws IOException {
- int ch1 = this.read();
- int ch2 = this.read();
- if ((ch1 | ch2) < 0)
- throw new EOFException();
- return (char)((ch1 << 8) + ch2);
- }
-
- /**
- * Reads a Unicode character from this stream in little-endian order.
- * This method reads two
- * bytes from the stream, starting at the current stream pointer.
- * If the bytes read, in order, are
- * b1
and b2
, where
- * 0 <= b1, b2 <= 255
,
- * then the result is equal to:
- *
- * (char)((b2 << 8) | b1)
- *
- *
- * This method blocks until the two bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next two bytes of this stream as a Unicode character.
- * @exception EOFException if this stream reaches the end before reading
- * two bytes.
- * @exception IOException if an I/O error occurs.
- */
- public final char readCharLE() throws IOException {
- int ch1 = this.read();
- int ch2 = this.read();
- if ((ch1 | ch2) < 0)
- throw new EOFException();
- return (char)((ch2 << 8) + (ch1 << 0));
- }
-
- public int readInt() throws IOException {
- int ch1 = this.read();
- int ch2 = this.read();
- int ch3 = this.read();
- int ch4 = this.read();
- if ((ch1 | ch2 | ch3 | ch4) < 0)
- throw new EOFException();
- return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4);
- }
-
- /**
- * Reads a signed 32-bit integer from this stream in little-endian order.
- * This method reads 4
- * bytes from the stream, starting at the current stream pointer.
- * If the bytes read, in order, are b1
,
- * b2
, b3
, and b4
, where
- * 0 <= b1, b2, b3, b4 <= 255
,
- * then the result is equal to:
- *
- * (b4 << 24) | (b3 << 16) + (b2 << 8) + b1
- *
- *
- * This method blocks until the four bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next four bytes of this stream, interpreted as an
- * int
.
- * @exception EOFException if this stream reaches the end before reading
- * four bytes.
- * @exception IOException if an I/O error occurs.
- */
- public final int readIntLE() throws IOException {
- int ch1 = this.read();
- int ch2 = this.read();
- int ch3 = this.read();
- int ch4 = this.read();
- if ((ch1 | ch2 | ch3 | ch4) < 0)
- throw new EOFException();
- return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
- }
-
- /**
- * Reads an unsigned 32-bit integer from this stream. This method reads 4
- * bytes from the stream, starting at the current stream pointer.
- * If the bytes read, in order, are b1
,
- * b2
, b3
, and b4
, where
- * 0 <= b1, b2, b3, b4 <= 255
,
- * then the result is equal to:
- *
- * (b1 << 24) | (b2 << 16) + (b3 << 8) + b4
- *
- *
- * This method blocks until the four bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @return the next four bytes of this stream, interpreted as a
- * long
.
- * @exception EOFException if this stream reaches the end before reading
- * four bytes.
- * @exception IOException if an I/O error occurs.
- */
- public final long readUnsignedInt() throws IOException {
- long ch1 = this.read();
- long ch2 = this.read();
- long ch3 = this.read();
- long ch4 = this.read();
- if ((ch1 | ch2 | ch3 | ch4) < 0)
- throw new EOFException();
- return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
- }
-
- public final long readUnsignedIntLE() throws IOException {
- long ch1 = this.read();
- long ch2 = this.read();
- long ch3 = this.read();
- long ch4 = this.read();
- if ((ch1 | ch2 | ch3 | ch4) < 0)
- throw new EOFException();
- return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
- }
-
- public long readLong() throws IOException {
- return ((long)(readInt()) << 32) + (readInt() & 0xFFFFFFFFL);
- }
-
- public final long readLongLE() throws IOException {
- int i1 = readIntLE();
- int i2 = readIntLE();
- return ((long)i2 << 32) + (i1 & 0xFFFFFFFFL);
- }
-
- public float readFloat() throws IOException {
- return Float.intBitsToFloat(readInt());
- }
-
- public final float readFloatLE() throws IOException {
- return Float.intBitsToFloat(readIntLE());
- }
-
- public double readDouble() throws IOException {
- return Double.longBitsToDouble(readLong());
- }
-
- public final double readDoubleLE() throws IOException {
- return Double.longBitsToDouble(readLongLE());
- }
-
- public String readLine() throws IOException {
- StringBuffer input = new StringBuffer();
- int c = -1;
- boolean eol = false;
-
- while (!eol) {
- switch (c = read()) {
- case -1:
- case '\n':
- eol = true;
- break;
- case '\r':
- eol = true;
- int cur = getFilePointer();
- if ((read()) != '\n') {
- seek(cur);
- }
- break;
- default:
- input.append((char)c);
- break;
- }
- }
-
- if ((c == -1) && (input.length() == 0)) {
- return null;
- }
- return input.toString();
- }
-
- public String readUTF() throws IOException {
- return DataInputStream.readUTF(this);
- }
-
- /** Getter for property startOffset.
- * @return Value of property startOffset.
- *
- */
- public int getStartOffset() {
- return this.startOffset;
- }
-
- /** Setter for property startOffset.
- * @param startOffset New value of property startOffset.
- *
- */
- public void setStartOffset(int startOffset) {
- this.startOffset = startOffset;
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/SequenceList.java pdftk-2.01/java/com/lowagie/text/pdf/SequenceList.java
--- pdftk-1.45/java/com/lowagie/text/pdf/SequenceList.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/SequenceList.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,323 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.util.List;
-import java.util.LinkedList;
-import java.util.ListIterator;
-
-/**
- * This class expands a string into a list of numbers. The main use is to select a
- * range of pages.
- *
- * The general systax is:
- * [!][o][odd][e][even]start-end
- *
- * You can have multiple ranges separated by commas ','. The '!' modifier removes the
- * range from what is already selected. The range changes are incremental, that is,
- * numbers are added or deleted as the range appears. The start or the end, but not both, can be ommited.
- */
-public class SequenceList {
- protected static final int COMMA = 1;
- protected static final int MINUS = 2;
- protected static final int NOT = 3;
- protected static final int TEXT = 4;
- protected static final int NUMBER = 5;
- protected static final int END = 6;
- protected static final char EOT = '\uffff';
-
- private static final int FIRST = 0;
- private static final int DIGIT = 1;
- private static final int OTHER = 2;
- private static final int DIGIT2 = 3;
- private static final String NOT_OTHER = "-,!0123456789";
-
- protected char text[];
- protected int ptr;
- protected int number;
- protected String other;
-
- protected int low;
- protected int high;
- protected boolean odd;
- protected boolean even;
- protected boolean inverse;
-
- protected SequenceList(String range) {
- ptr = 0;
- text = range.toCharArray();
- }
-
- protected char nextChar() {
- while (true) {
- if (ptr >= text.length)
- return EOT;
- char c = text[ptr++];
- if (c > ' ')
- return c;
- }
- }
-
- protected void putBack() {
- --ptr;
- if (ptr < 0)
- ptr = 0;
- }
-
- protected int getType() {
- StringBuffer buf = new StringBuffer();
- int state = FIRST;
- while (true) {
- char c = nextChar();
- if (c == EOT) {
- if (state == DIGIT) {
- number = Integer.parseInt(other = buf.toString());
- return NUMBER;
- }
- else if (state == OTHER) {
- other = buf.toString().toLowerCase();
- return TEXT;
- }
- return END;
- }
- switch (state) {
- case FIRST:
- switch (c) {
- case '!':
- return NOT;
- case '-':
- return MINUS;
- case ',':
- return COMMA;
- }
- buf.append(c);
- if (c >= '0' && c <= '9')
- state = DIGIT;
- else
- state = OTHER;
- break;
- case DIGIT:
- if (c >= '0' && c <= '9')
- buf.append(c);
- else {
- putBack();
- number = Integer.parseInt(other = buf.toString());
- return NUMBER;
- }
- break;
- case OTHER:
- if (NOT_OTHER.indexOf(c) < 0)
- buf.append(c);
- else {
- putBack();
- other = buf.toString().toLowerCase();
- return TEXT;
- }
- break;
- }
- }
- }
-
- private void otherProc() {
- if (other.equals("odd") || other.equals("o")) {
- odd = true;
- even = false;
- }
- else if (other.equals("even") || other.equals("e")) {
- odd = false;
- even = true;
- }
- }
-
- protected boolean getAttributes() {
- low = -1;
- high = -1;
- odd = even = inverse = false;
- int state = OTHER;
- while (true) {
- int type = getType();
- if (type == END || type == COMMA) {
- if (state == DIGIT)
- high = low;
- return (type == END);
- }
- switch (state) {
- case OTHER:
- switch (type) {
- case NOT:
- inverse = true;
- break;
- case MINUS:
- state = DIGIT2;
- break;
- default:
- if (type == NUMBER) {
- low = number;
- state = DIGIT;
- }
- else
- otherProc();
- break;
- }
- break;
- case DIGIT:
- switch (type) {
- case NOT:
- inverse = true;
- state = OTHER;
- high = low;
- break;
- case MINUS:
- state = DIGIT2;
- break;
- default:
- high = low;
- state = OTHER;
- otherProc();
- break;
- }
- break;
- case DIGIT2:
- switch (type) {
- case NOT:
- inverse = true;
- state = OTHER;
- break;
- case MINUS:
- break;
- case NUMBER:
- high = number;
- state = OTHER;
- break;
- default:
- state = OTHER;
- otherProc();
- break;
- }
- break;
- }
- }
- }
-
- /**
- * Generates a list of numbers from a string.
- * @param ranges the comma separated ranges
- * @param maxNumber the maximum number in the range
- * @return a list with the numbers as Integer
- */
- public static List expand(String ranges, int maxNumber) {
- SequenceList parse = new SequenceList(ranges);
- LinkedList list = new LinkedList();
- boolean sair = false;
- while (!sair) {
- sair = parse.getAttributes();
- if (parse.low == -1 && parse.high == -1 && !parse.even && !parse.odd)
- continue;
- if (parse.low < 1)
- parse.low = 1;
- if (parse.high < 1 || parse.high > maxNumber)
- parse.high = maxNumber;
- if (parse.low > maxNumber)
- parse.low = maxNumber;
-
- //System.out.println("low="+parse.low+",high="+parse.high+",odd="+parse.odd+",even="+parse.even+",inverse="+parse.inverse);
- int inc = 1;
- if (parse.inverse) {
- if (parse.low > parse.high) {
- int t = parse.low;
- parse.low = parse.high;
- parse.high = t;
- }
- for (ListIterator it = list.listIterator(); it.hasNext();) {
- int n = ((Integer)it.next()).intValue();
- if (parse.even && (n & 1) == 1)
- continue;
- if (parse.odd && (n & 1) == 0)
- continue;
- if (n >= parse.low && n <= parse.high)
- it.remove();
- }
- }
- else {
- if (parse.low > parse.high) {
- inc = -1;
- if (parse.odd || parse.even) {
- --inc;
- if (parse.even)
- parse.low &= ~1;
- else
- parse.low -= ((parse.low & 1) == 1 ? 0 : 1);
- }
- for (int k = parse.low; k >= parse.high; k += inc)
- list.add(new Integer(k));
- }
- else {
- if (parse.odd || parse.even) {
- ++inc;
- if (parse.odd)
- parse.low |= 1;
- else
- parse.low += ((parse.low & 1) == 1 ? 1 : 0);
- }
- for (int k = parse.low; k <= parse.high; k += inc) {
- list.add(new Integer(k));
- }
- }
- }
-// for (int k = 0; k < list.size(); ++k)
-// System.out.print(((Integer)list.get(k)).intValue() + ",");
-// System.out.println();
- }
- return list;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/ShadingColor.java pdftk-2.01/java/com/lowagie/text/pdf/ShadingColor.java
--- pdftk-1.45/java/com/lowagie/text/pdf/ShadingColor.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/ShadingColor.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/** Implements a shading pattern as a Color
.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class ShadingColor extends ExtendedColor {
-
- PdfShadingPattern shadingPattern;
-
- /**
- * Creates a shading color.
- * @param shadingPattern
- */
- public ShadingColor(PdfShadingPattern shadingPattern) {
- super(TYPE_SHADING, .5f, .5f, .5f);
- this.shadingPattern = shadingPattern;
- }
-
- /**
- * Gets the shading pattern.
- * @return a shading pattern.
- */
- public PdfShadingPattern getPdfShadingPattern() {
- return shadingPattern;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/SimpleBookmark.java pdftk-2.01/java/com/lowagie/text/pdf/SimpleBookmark.java
--- pdftk-1.45/java/com/lowagie/text/pdf/SimpleBookmark.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/SimpleBookmark.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,751 +0,0 @@
-/*
- * Copyright 2003 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.util.List;
-import java.util.Iterator;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.StringTokenizer;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.Writer;
-import java.io.Reader;
-import java.io.BufferedWriter;
-import java.io.OutputStreamWriter;
-import java.util.Stack;
-/**
- * Bookmark processing in a simple way. It has some limitations, mainly the only
- * action types supported are GoTo, GoToR, URI and Launch.
- *
- * The list structure is composed by a number of HashMap, keyed by strings, one HashMap
- * for each bookmark.
- * The element values are all strings with the exception of the key "Kids" that has
- * another list for the child bookmarks.
- *
- * All the bookmarks have a "Title" with the
- * bookmark title and optionally a "Style" that can be "bold", "italic" or a
- * combination of both. They can also have a "Color" key with a value of three
- * floats separated by spaces. The key "Open" can have the values "true" or "false" and
- * signals the open status of the children. It's "true" by default.
- *
- * The actions and the parameters can be:
- *
- * "Action" = "GoTo" - "Page" | "Named"
- *
- * "Page" = "3 XYZ 70 400 null" - page number followed by a destination (/XYZ is also accepted)
- * "Named" = "named_destination"
- *
- * "Action" = "GoToR" - "Page" | "Named" | "NamedN", "File", ["NewWindow"]
- *
- * "Page" = "3 XYZ 70 400 null" - page number followed by a destination (/XYZ is also accepted)
- * "Named" = "named_destination_as_a_string"
- * "NamedN" = "named_destination_as_a_name"
- * "File" - "the_file_to_open"
- * "NewWindow" - "true" or "false"
- *
- * "Action" = "URI" - "URI"
- *
- * "URI" = "http://sf.net" - URI to jump to
- *
- * "Action" = "Launch" - "File"
- *
- * "File" - "the_file_to_open_or_execute"
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class SimpleBookmark implements SimpleXMLDocHandler {
-
- private ArrayList topList;
- private Stack attr = new Stack();
-
- /** Creates a new instance of SimpleBookmark */
- private SimpleBookmark() {
- }
-
- private static List bookmarkDepth(PdfReader reader, PdfDictionary outline, IntHashtable pages) {
- ArrayList list = new ArrayList();
- while (outline != null) {
- HashMap map = new HashMap();
- PdfString title = (PdfString)PdfReader.getPdfObjectRelease(outline.get(PdfName.TITLE));
- map.put("Title", title.toUnicodeString());
- PdfArray color = (PdfArray)PdfReader.getPdfObjectRelease(outline.get(PdfName.C));
- if (color != null && color.getArrayList().size() == 3) {
- ByteBuffer out = new ByteBuffer();
- ArrayList arr = color.getArrayList();
- out.append(((PdfNumber)arr.get(0)).floatValue()).append(' ');
- out.append(((PdfNumber)arr.get(1)).floatValue()).append(' ');
- out.append(((PdfNumber)arr.get(2)).floatValue());
- map.put("Color", PdfEncodings.convertToString(out.toByteArray(), null));
- }
- PdfNumber style = (PdfNumber)PdfReader.getPdfObjectRelease(outline.get(PdfName.F));
- if (style != null) {
- int f = style.intValue();
- String s = "";
- if ((f & 1) != 0)
- s += "italic ";
- if ((f & 2) != 0)
- s += "bold ";
- s = s.trim();
- if (s.length() != 0)
- map.put("Style", s);
- }
- PdfNumber count = (PdfNumber)PdfReader.getPdfObjectRelease(outline.get(PdfName.COUNT));
- if (count != null && count.intValue() < 0)
- map.put("Open", "false");
- try {
- PdfObject dest = PdfReader.getPdfObjectRelease(outline.get(PdfName.DEST));
- if (dest != null) {
- mapGotoBookmark(map, dest, pages); //changed by ujihara 2004-06-13
- }
- else {
- PdfDictionary action = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.A));
- if (action != null) {
- if (PdfName.GOTO.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
- dest = PdfReader.getPdfObjectRelease(action.get(PdfName.D));
- if (dest != null) {
- mapGotoBookmark(map, dest, pages);
- }
- }
- else if (PdfName.URI.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
- map.put("Action", "URI");
- map.put("URI", ((PdfString)PdfReader.getPdfObjectRelease(action.get(PdfName.URI))).toUnicodeString());
- }
- else if (PdfName.GOTOR.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
- dest = PdfReader.getPdfObjectRelease(action.get(PdfName.D));
- if (dest != null) {
- if (dest.isString())
- map.put("Named", dest.toString());
- else if (dest.isName())
- map.put("NamedN", PdfName.decodeName(dest.toString()));
- else if (dest.isArray()) {
- ArrayList arr = ((PdfArray)dest).getArrayList();
- StringBuffer s = new StringBuffer();
- s.append(arr.get(0).toString());
- s.append(' ').append(arr.get(1).toString());
- for (int k = 2; k < arr.size(); ++k)
- s.append(' ').append(arr.get(k).toString());
- map.put("Page", s.toString());
- }
- }
- map.put("Action", "GoToR");
- PdfObject file = PdfReader.getPdfObjectRelease(action.get(PdfName.F));
- if (file != null) {
- if (file.isString())
- map.put("File", ((PdfString)file).toUnicodeString());
- else if (file.isDictionary()) {
- file = PdfReader.getPdfObject(((PdfDictionary)file).get(PdfName.F));
- if (file.isString())
- map.put("File", ((PdfString)file).toUnicodeString());
- }
- }
- PdfObject newWindow = PdfReader.getPdfObjectRelease(action.get(PdfName.NEWWINDOW));
- if (newWindow != null)
- map.put("NewWindow", newWindow.toString());
- }
- else if (PdfName.LAUNCH.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
- map.put("Action", "Launch");
- PdfObject file = PdfReader.getPdfObjectRelease(action.get(PdfName.F));
- if (file == null)
- file = PdfReader.getPdfObjectRelease(action.get(PdfName.WIN));
- if (file != null) {
- if (file.isString())
- map.put("File", ((PdfString)file).toUnicodeString());
- else if (file.isDictionary()) {
- file = PdfReader.getPdfObjectRelease(((PdfDictionary)file).get(PdfName.F));
- if (file.isString())
- map.put("File", ((PdfString)file).toUnicodeString());
- }
- }
- }
- }
- }
- }
- catch (Exception e) {
- //empty on purpose
- }
- PdfDictionary first = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.FIRST));
- if (first != null) {
- map.put("Kids", bookmarkDepth(reader, first, pages));
- }
- list.add(map);
- outline = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.NEXT));
- }
- return list;
- }
-
- private static void mapGotoBookmark(HashMap map, PdfObject dest, IntHashtable pages)
- {
- if (dest.isString())
- map.put("Named", dest.toString());
- else if (dest.isName())
- map.put("Named", PdfName.decodeName(dest.toString()));
- else if (dest.isArray())
- map.put("Page", makeBookmarkParam((PdfArray)dest, pages)); //changed by ujihara 2004-06-13
- map.put("Action", "GoTo");
- }
-
- private static String makeBookmarkParam(PdfArray dest, IntHashtable pages)
- {
- ArrayList arr = ((PdfArray)dest).getArrayList();
- StringBuffer s = new StringBuffer();
- s.append(pages.get(getNumber((PdfIndirectReference)arr.get(0)))); //changed by ujihara 2004-06-13
- s.append(' ').append(arr.get(1).toString().substring(1));
- for (int k = 2; k < arr.size(); ++k)
- s.append(' ').append(arr.get(k).toString());
- return s.toString();
- }
-
- /**
- * Gets number of indirect. If type of directed indirect is PAGES, it refers PAGE object through KIDS.
- * (Contributed by Kazuya Ujihara)
- * @param indirect
- * 2004-06-13
- */
- private static int getNumber(PdfIndirectReference indirect)
- {
- PdfDictionary pdfObj = (PdfDictionary)PdfReader.getPdfObjectRelease(indirect);
- if (pdfObj.contains(PdfName.TYPE) && pdfObj.get(PdfName.TYPE).equals(PdfName.PAGES) && pdfObj.contains(PdfName.KIDS))
- {
- PdfArray kids = (PdfArray)pdfObj.get(PdfName.KIDS);
- indirect = (PdfIndirectReference)kids.arrayList.get(0);
- }
- return indirect.getNumber();
- }
-
- /**
- * Gets a List
with the bookmarks. It returns null
if
- * the document doesn't have any bookmarks.
- * @param reader the document
- * @return a List
with the bookmarks or null
if the
- * document doesn't have any
- */
- public static List getBookmark(PdfReader reader) {
- PdfDictionary catalog = reader.getCatalog();
- PdfObject obj = PdfReader.getPdfObjectRelease(catalog.get(PdfName.OUTLINES));
- if (obj == null || !obj.isDictionary())
- return null;
- PdfDictionary outlines = (PdfDictionary)obj;
- IntHashtable pages = new IntHashtable();
- int numPages = reader.getNumberOfPages();
- for (int k = 1; k <= numPages; ++k) {
- pages.put(reader.getPageOrigRef(k).getNumber(), k);
- reader.releasePage(k);
- }
- return bookmarkDepth(reader, (PdfDictionary)PdfReader.getPdfObjectRelease(outlines.get(PdfName.FIRST)), pages);
- }
-
- /**
- * Removes the bookmark entries for a number of page ranges. The page ranges
- * consists of a number of pairs with the start/end page range. The page numbers
- * are inclusive.
- * @param list the bookmarks
- * @param pageRange the page ranges, always in pairs.
- */
- public static void eliminatePages(List list, int pageRange[]) {
- if (list == null)
- return;
- for (Iterator it = list.listIterator(); it.hasNext();) {
- HashMap map = (HashMap)it.next();
- boolean hit = false;
- if ("GoTo".equals(map.get("Action"))) {
- String page = (String)map.get("Page");
- if (page != null) {
- page = page.trim();
- int idx = page.indexOf(' ');
- int pageNum;
- if (idx < 0)
- pageNum = Integer.parseInt(page);
- else
- pageNum = Integer.parseInt(page.substring(0, idx));
- int len = pageRange.length & 0xfffffffe;
- for (int k = 0; k < len; k += 2) {
- if (pageNum >= pageRange[k] && pageNum <= pageRange[k + 1]) {
- hit = true;
- break;
- }
- }
- }
- }
- List kids = (List)map.get("Kids");
- if (kids != null) {
- eliminatePages(kids, pageRange);
- if (kids.size() == 0) {
- map.remove("Kids");
- kids = null;
- }
- }
- if (hit) {
- if (kids == null)
- it.remove();
- else {
- map.remove("Action");
- map.remove("Page");
- map.remove("Named");
- }
- }
- }
- }
-
- /**
- * For the pages in range add the pageShift
to the page number.
- * The page ranges
- * consists of a number of pairs with the start/end page range. The page numbers
- * are inclusive.
- * @param list the bookmarks
- * @param pageShift the number to add to the pages in range
- * @param pageRange the page ranges, always in pairs. It can be null
- * to include all the pages
- */
- public static void shiftPageNumbers(List list, int pageShift, int pageRange[]) {
- if (list == null)
- return;
- for (Iterator it = list.listIterator(); it.hasNext();) {
- HashMap map = (HashMap)it.next();
- if ("GoTo".equals(map.get("Action"))) {
- String page = (String)map.get("Page");
- if (page != null) {
- page = page.trim();
- int idx = page.indexOf(' ');
- int pageNum;
- if (idx < 0)
- pageNum = Integer.parseInt(page);
- else
- pageNum = Integer.parseInt(page.substring(0, idx));
- boolean hit = false;
- if (pageRange == null)
- hit = true;
- else {
- int len = pageRange.length & 0xfffffffe;
- for (int k = 0; k < len; k += 2) {
- if (pageNum >= pageRange[k] && pageNum <= pageRange[k + 1]) {
- hit = true;
- break;
- }
- }
- }
- if (hit) {
- if (idx < 0)
- page = (pageNum + pageShift) + "";
- else
- page = (pageNum + pageShift) + page.substring(idx);
- }
- map.put("Page", page);
- }
- }
- List kids = (List)map.get("Kids");
- if (kids != null)
- shiftPageNumbers(kids, pageShift, pageRange);
- }
- }
-
- static void createOutlineAction(PdfDictionary outline, HashMap map, PdfWriter writer, boolean namedAsNames) throws IOException {
- try {
- String action = (String)map.get("Action");
- if ("GoTo".equals(action)) {
- String p;
- if ((p = (String)map.get("Named")) != null) {
- if (namedAsNames)
- outline.put(PdfName.DEST, new PdfName(p));
- else
- outline.put(PdfName.DEST, new PdfString(p, null));
- }
- else if ((p = (String)map.get("Page")) != null) {
- PdfArray ar = new PdfArray();
- StringTokenizer tk = new StringTokenizer(p);
- int n = Integer.parseInt(tk.nextToken());
- ar.add(writer.getPageReference(n));
- if (!tk.hasMoreTokens()) {
- ar.add(PdfName.XYZ);
- ar.add(new float[]{0, 10000, 0});
- }
- else {
- String fn = tk.nextToken();
- if (fn.startsWith("/"))
- fn = fn.substring(1);
- ar.add(new PdfName(fn));
- for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) {
- fn = tk.nextToken();
- if (fn.equals("null"))
- ar.add(PdfNull.PDFNULL);
- else
- ar.add(new PdfNumber(fn));
- }
- }
- outline.put(PdfName.DEST, ar);
- }
- }
- else if ("GoToR".equals(action)) {
- String p;
- PdfDictionary dic = new PdfDictionary();
- if ((p = (String)map.get("Named")) != null)
- dic.put(PdfName.D, new PdfString(p, null));
- else if ((p = (String)map.get("NamedN")) != null)
- dic.put(PdfName.D, new PdfName(p));
- else if ((p = (String)map.get("Page")) != null){
- PdfArray ar = new PdfArray();
- StringTokenizer tk = new StringTokenizer(p);
- ar.add(new PdfNumber(tk.nextToken()));
- if (!tk.hasMoreTokens()) {
- ar.add(PdfName.XYZ);
- ar.add(new float[]{0, 10000, 0});
- }
- else {
- String fn = tk.nextToken();
- if (fn.startsWith("/"))
- fn = fn.substring(1);
- ar.add(new PdfName(fn));
- for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) {
- fn = tk.nextToken();
- if (fn.equals("null"))
- ar.add(PdfNull.PDFNULL);
- else
- ar.add(new PdfNumber(fn));
- }
- }
- dic.put(PdfName.D, ar);
- }
- String file = (String)map.get("File");
- if (dic.size() > 0 && file != null) {
- dic.put(PdfName.S, PdfName.GOTOR);
- dic.put(PdfName.F, new PdfString(file));
- String nw = (String)map.get("NewWindow");
- if (nw != null) {
- if (nw.equals("true"))
- dic.put(PdfName.NEWWINDOW, PdfBoolean.PDFTRUE);
- else if (nw.equals("false"))
- dic.put(PdfName.NEWWINDOW, PdfBoolean.PDFFALSE);
- }
- outline.put(PdfName.A, dic);
- }
- }
- else if ("URI".equals(action)) {
- String uri = (String)map.get("URI");
- if (uri != null) {
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.S, PdfName.URI);
- dic.put(PdfName.URI, new PdfString(uri));
- outline.put(PdfName.A, dic);
- }
- }
- else if ("Launch".equals(action)) {
- String file = (String)map.get("File");
- if (file != null) {
- PdfDictionary dic = new PdfDictionary();
- dic.put(PdfName.S, PdfName.LAUNCH);
- dic.put(PdfName.F, new PdfString(file));
- outline.put(PdfName.A, dic);
- }
- }
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
-
- public static Object[] iterateOutlines(PdfWriter writer, PdfIndirectReference parent, List kids, boolean namedAsNames) throws IOException {
- PdfIndirectReference refs[] = new PdfIndirectReference[kids.size()];
- for (int k = 0; k < refs.length; ++k)
- refs[k] = writer.getPdfIndirectReference();
- int ptr = 0;
- int count = 0;
- for (Iterator it = kids.listIterator(); it.hasNext(); ++ptr) {
- HashMap map = (HashMap)it.next();
- Object lower[] = null;
- List subKid = (List)map.get("Kids");
- if (subKid != null && subKid.size() > 0)
- lower = iterateOutlines(writer, refs[ptr], subKid, namedAsNames);
- PdfDictionary outline = new PdfDictionary();
- ++count;
- if (lower != null) {
- outline.put(PdfName.FIRST, (PdfIndirectReference)lower[0]);
- outline.put(PdfName.LAST, (PdfIndirectReference)lower[1]);
- int n = ((Integer)lower[2]).intValue();
- if ("false".equals(map.get("Open"))) {
- outline.put(PdfName.COUNT, new PdfNumber(-n));
- }
- else {
- outline.put(PdfName.COUNT, new PdfNumber(n));
- count += n;
- }
- }
- outline.put(PdfName.PARENT, parent);
- if (ptr > 0)
- outline.put(PdfName.PREV, refs[ptr - 1]);
- if (ptr < refs.length - 1)
- outline.put(PdfName.NEXT, refs[ptr + 1]);
- outline.put(PdfName.TITLE, new PdfString((String)map.get("Title"), PdfObject.TEXT_UNICODE));
- String color = (String)map.get("Color");
- if (color != null) {
- try {
- PdfArray arr = new PdfArray();
- StringTokenizer tk = new StringTokenizer(color);
- for (int k = 0; k < 3; ++k) {
- float f = Float.valueOf(tk.nextToken()).intValue();
- if (f < 0) f = 0;
- if (f > 1) f = 1;
- arr.add(new PdfNumber(f));
- }
- outline.put(PdfName.C, arr);
- } catch(Exception e){} //in case it's malformed
- }
- String style = (String)map.get("Style");
- if (style != null) {
- style = style.toLowerCase();
- int bits = 0;
- if (style.indexOf("italic") >= 0)
- bits |= 1;
- if (style.indexOf("bold") >= 0)
- bits |= 2;
- if (bits != 0)
- outline.put(PdfName.F, new PdfNumber(bits));
- }
- createOutlineAction(outline, map, writer, namedAsNames);
- writer.addToBody(outline, refs[ptr]);
- }
- return new Object[]{refs[0], refs[refs.length - 1], new Integer(count)};
- }
-
- /**
- * Exports the bookmarks to XML. Only of use if the generation is to be include in
- * some other XML document.
- * @param list the bookmarks
- * @param out the export destination. The writer is not closed
- * @param indent the indentation level. Pretty printing significant only
- * @param onlyASCII codes above 127 will always be escaped with &#nn; if true
,
- * whatever the encoding
- * @throws IOException on error
- */
- public static void exportToXMLNode(List list, Writer out, int indent, boolean onlyASCII) throws IOException {
- String dep = "";
- for (int k = 0; k < indent; ++k)
- dep += " ";
- for (Iterator it = list.iterator(); it.hasNext();) {
- HashMap map = (HashMap)it.next();
- String title = null;
- out.write(dep);
- out.write("");
- if (title == null)
- title = "";
- out.write(SimpleXMLParser.escapeXML(title, onlyASCII));
- if (kids != null) {
- out.write("\n");
- exportToXMLNode(kids, out, indent + 1, onlyASCII);
- out.write(dep);
- }
- out.write(" \n");
- }
- }
-
- /**
- * Exports the bookmarks to XML. The DTD for this XML is:
- *
- *
- * <?xml version='1.0' encoding='UTF-8'?>
- * <!ELEMENT Title (#PCDATA|Title)*>
- * <!ATTLIST Title
- * Action CDATA #IMPLIED
- * Open CDATA #IMPLIED
- * Page CDATA #IMPLIED
- * URI CDATA #IMPLIED
- * File CDATA #IMPLIED
- * Named CDATA #IMPLIED
- * NamedN CDATA #IMPLIED
- * NewWindow CDATA #IMPLIED
- * Style CDATA #IMPLIED
- * Color CDATA #IMPLIED
- * >
- * <!ELEMENT Bookmark (Title)*>
- *
- * @param list the bookmarks
- * @param out the export destination. The stream is not closed
- * @param encoding the encoding according to IANA conventions
- * @param onlyASCII codes above 127 will always be escaped with &#nn; if true
,
- * whatever the encoding
- * @throws IOException on error
- */
- public static void exportToXML(List list, OutputStream out, String encoding, boolean onlyASCII) throws IOException {
- String jenc = SimpleXMLParser.getJavaEncoding(encoding);
- Writer wrt = new BufferedWriter(new OutputStreamWriter(out, jenc));
- exportToXML(list, wrt, encoding, onlyASCII);
- }
-
- /**
- * Exports the bookmarks to XML.
- * @param list the bookmarks
- * @param wrt the export destination. The writer is not closed
- * @param encoding the encoding according to IANA conventions
- * @param onlyASCII codes above 127 will always be escaped with &#nn; if true
,
- * whatever the encoding
- * @throws IOException on error
- */
- public static void exportToXML(List list, Writer wrt, String encoding, boolean onlyASCII) throws IOException {
- wrt.write("\n\n");
- exportToXMLNode(list, wrt, 1, onlyASCII);
- wrt.write(" \n");
- wrt.flush();
- }
-
- /**
- * Import the bookmarks from XML.
- * @param in the XML source. The stream is not closed
- * @throws IOException on error
- * @return the bookmarks
- */
- public static List importFromXML(InputStream in) throws IOException {
- SimpleBookmark book = new SimpleBookmark();
- SimpleXMLParser.parse(book, in);
- return book.topList;
- }
-
- /**
- * Import the bookmarks from XML.
- * @param in the XML source. The reader is not closed
- * @throws IOException on error
- * @return the bookmarks
- */
- public static List importFromXML(Reader in) throws IOException {
- SimpleBookmark book = new SimpleBookmark();
- SimpleXMLParser.parse(book, in);
- return book.topList;
- }
-
- public void endDocument() {
- }
-
- public void endElement(String tag) {
- if (tag.equals("Bookmark")) {
- if (attr.isEmpty())
- return;
- else
- throw new RuntimeException("Bookmark end tag out of place.");
- }
- if (!tag.equals("Title"))
- throw new RuntimeException("Invalid end tag - " + tag);
- HashMap attributes = (HashMap)attr.pop();
- String title = (String)attributes.get("Title");
- attributes.put("Title", title.trim());
- String named = (String)attributes.get("Named");
- if (named != null)
- attributes.put("Named", SimpleNamedDestination.unEscapeBinaryString(named));
- named = (String)attributes.get("NamedN");
- if (named != null)
- attributes.put("NamedN", SimpleNamedDestination.unEscapeBinaryString(named));
- if (attr.isEmpty())
- topList.add(attributes);
- else {
- HashMap parent = (HashMap)attr.peek();
- List kids = (List)parent.get("Kids");
- if (kids == null) {
- kids = new ArrayList();
- parent.put("Kids", kids);
- }
- kids.add(attributes);
- }
- }
-
- public void startDocument() {
- }
-
- public void startElement(String tag, HashMap h) {
- if (topList == null) {
- if (tag.equals("Bookmark")) {
- topList = new ArrayList();
- return;
- }
- else
- throw new RuntimeException("Root element is not Bookmark.");
- }
- if (!tag.equals("Title"))
- throw new RuntimeException("Tag " + tag + " not allowed.");
- HashMap attributes = new HashMap(h);
- attributes.put("Title", "");
- attributes.remove("Kids");
- attr.push(attributes);
- }
-
- public void text(String str) {
- if (attr.isEmpty())
- return;
- HashMap attributes = (HashMap)attr.peek();
- String title = (String)attributes.get("Title");
- title += str;
- attributes.put("Title", title);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/SimpleNamedDestination.java pdftk-2.01/java/com/lowagie/text/pdf/SimpleNamedDestination.java
--- pdftk-1.45/java/com/lowagie/text/pdf/SimpleNamedDestination.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/SimpleNamedDestination.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,341 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Iterator;
-import java.util.ArrayList;
-import java.util.StringTokenizer;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.io.BufferedWriter;
-import java.io.InputStream;
-import java.io.Reader;
-
-/**
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class SimpleNamedDestination implements SimpleXMLDocHandler {
-
- private HashMap xmlNames;
- private HashMap xmlLast;
-
- private SimpleNamedDestination() {
- }
-
- public static HashMap getNamedDestination(PdfReader reader, boolean fromNames) {
- IntHashtable pages = new IntHashtable();
- int numPages = reader.getNumberOfPages();
- for (int k = 1; k <= numPages; ++k)
- pages.put(reader.getPageOrigRef(k).getNumber(), k);
- HashMap names = fromNames ? reader.getNamedDestinationFromNames() : reader.getNamedDestinationFromStrings();
- for (Iterator it = names.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry)it.next();
- ArrayList arr = ((PdfArray)entry.getValue()).getArrayList();
- StringBuffer s = new StringBuffer();
- try {
- s.append(pages.get(((PdfIndirectReference)arr.get(0)).getNumber()));
- s.append(' ').append(arr.get(1).toString().substring(1));
- for (int k = 2; k < arr.size(); ++k)
- s.append(' ').append(arr.get(k).toString());
- entry.setValue(s.toString());
- }
- catch (Exception e) {
- it.remove();
- }
- }
- return names;
- }
-
- /**
- * Exports the bookmarks to XML. The DTD for this XML is:
- *
- *
- * <?xml version='1.0' encoding='UTF-8'?>
- * <!ELEMENT Name (#PCDATA)>
- * <!ATTLIST Name
- * Page CDATA #IMPLIED
- * >
- * <!ELEMENT Destination (Name)*>
- *
- * @param names the names
- * @param out the export destination. The stream is not closed
- * @param encoding the encoding according to IANA conventions
- * @param onlyASCII codes above 127 will always be escaped with &#nn; if true
,
- * whatever the encoding
- * @throws IOException on error
- */
- public static void exportToXML(HashMap names, OutputStream out, String encoding, boolean onlyASCII) throws IOException {
- String jenc = SimpleXMLParser.getJavaEncoding(encoding);
- Writer wrt = new BufferedWriter(new OutputStreamWriter(out, jenc));
- exportToXML(names, wrt, encoding, onlyASCII);
- }
-
- /**
- * Exports the bookmarks to XML.
- * @param names the names
- * @param wrt the export destination. The writer is not closed
- * @param encoding the encoding according to IANA conventions
- * @param onlyASCII codes above 127 will always be escaped with &#nn; if true
,
- * whatever the encoding
- * @throws IOException on error
- */
- public static void exportToXML(HashMap names, Writer wrt, String encoding, boolean onlyASCII) throws IOException {
- wrt.write("\n\n");
- for (Iterator it = names.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry)it.next();
- String key = (String)entry.getKey();
- String value = (String)entry.getValue();
- wrt.write(" ");
- wrt.write(SimpleXMLParser.escapeXML(escapeBinaryString(key), onlyASCII));
- wrt.write(" \n");
- }
- wrt.write(" \n");
- wrt.flush();
- }
-
- /**
- * Import the names from XML.
- * @param in the XML source. The stream is not closed
- * @throws IOException on error
- * @return the names
- */
- public static HashMap importFromXML(InputStream in) throws IOException {
- SimpleNamedDestination names = new SimpleNamedDestination();
- SimpleXMLParser.parse(names, in);
- return names.xmlNames;
- }
-
- /**
- * Import the names from XML.
- * @param in the XML source. The reader is not closed
- * @throws IOException on error
- * @return the names
- */
- public static HashMap importFromXML(Reader in) throws IOException {
- SimpleNamedDestination names = new SimpleNamedDestination();
- SimpleXMLParser.parse(names, in);
- return names.xmlNames;
- }
-
- static PdfArray createDestinationArray(String value, PdfWriter writer) throws IOException {
- PdfArray ar = new PdfArray();
- StringTokenizer tk = new StringTokenizer(value);
- int n = Integer.parseInt(tk.nextToken());
- ar.add(writer.getPageReference(n));
- if (!tk.hasMoreTokens()) {
- ar.add(PdfName.XYZ);
- ar.add(new float[]{0, 10000, 0});
- }
- else {
- String fn = tk.nextToken();
- if (fn.startsWith("/"))
- fn = fn.substring(1);
- ar.add(new PdfName(fn));
- for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) {
- fn = tk.nextToken();
- if (fn.equals("null"))
- ar.add(PdfNull.PDFNULL);
- else
- ar.add(new PdfNumber(fn));
- }
- }
- return ar;
- }
-
- public static PdfDictionary outputNamedDestinationAsNames(HashMap names, PdfWriter writer) throws IOException {
- PdfDictionary dic = new PdfDictionary();
- for (Iterator it = names.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry)it.next();
- try {
- String key = (String)entry.getKey();
- String value = (String)entry.getValue();
- PdfArray ar = createDestinationArray(value, writer);
- PdfName kn = new PdfName(key);
- dic.put(kn, ar);
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- return dic;
- }
-
- public static PdfDictionary outputNamedDestinationAsStrings(HashMap names, PdfWriter writer) throws IOException {
- HashMap n2 = new HashMap(names);
- for (Iterator it = n2.entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry)it.next();
- try {
- String value = (String)entry.getValue();
- PdfArray ar = createDestinationArray(value, writer);
- entry.setValue(writer.addToBody(ar).getIndirectReference());
- }
- catch (Exception e) {
- it.remove();
- }
- }
- return PdfNameTree.writeTree(n2, writer);
- }
-
- public static String escapeBinaryString(String s) {
- StringBuffer buf = new StringBuffer();
- char cc[] = s.toCharArray();
- int len = cc.length;
- for (int k = 0; k < len; ++k) {
- char c = cc[k];
- if (c < ' ') {
- buf.append('\\');
- String octal = "00" + Integer.toOctalString((int)c);
- buf.append(octal.substring(octal.length() - 3));
- }
- else if (c == '\\')
- buf.append("\\\\");
- else
- buf.append(c);
- }
- return buf.toString();
- }
-
- public static String unEscapeBinaryString(String s) {
- StringBuffer buf = new StringBuffer();
- char cc[] = s.toCharArray();
- int len = cc.length;
- for (int k = 0; k < len; ++k) {
- char c = cc[k];
- if (c == '\\') {
- if (++k >= len) {
- buf.append('\\');
- break;
- }
- c = cc[k];
- if (c >= '0' && c <= '7') {
- int n = c - '0';
- ++k;
- for (int j = 0; j < 2 && k < len; ++j) {
- c = cc[k];
- if (c >= '0' && c <= '7') {
- ++k;
- n = n * 8 + c - '0';
- }
- else {
- break;
- }
- }
- --k;
- buf.append((char)n);
- }
- else
- buf.append(c);
- }
- else
- buf.append(c);
- }
- return buf.toString();
- }
-
- public void endDocument() {
- }
-
- public void endElement(String tag) {
- if (tag.equals("Destination")) {
- if (xmlLast == null && xmlNames != null)
- return;
- else
- throw new RuntimeException("Destination end tag out of place.");
- }
- if (!tag.equals("Name"))
- throw new RuntimeException("Invalid end tag - " + tag);
- if (xmlLast == null || xmlNames == null)
- throw new RuntimeException("Name end tag out of place.");
- if (!xmlLast.containsKey("Page"))
- throw new RuntimeException("Page attribute missing.");
- xmlNames.put(unEscapeBinaryString((String)xmlLast.get("Name")), xmlLast.get("Page"));
- xmlLast = null;
- }
-
- public void startDocument() {
- }
-
- public void startElement(String tag, HashMap h) {
- if (xmlNames == null) {
- if (tag.equals("Destination")) {
- xmlNames = new HashMap();
- return;
- }
- else
- throw new RuntimeException("Root element is not Destination.");
- }
- if (!tag.equals("Name"))
- throw new RuntimeException("Tag " + tag + " not allowed.");
- if (xmlLast != null)
- throw new RuntimeException("Nested tags are not allowed.");
- xmlLast = new HashMap(h);
- xmlLast.put("Name", "");
- }
-
- public void text(String str) {
- if (xmlLast == null)
- return;
- String name = (String)xmlLast.get("Name");
- name += str;
- xmlLast.put("Name", name);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/SimpleXMLDocHandler.java pdftk-2.01/java/com/lowagie/text/pdf/SimpleXMLDocHandler.java
--- pdftk-1.45/java/com/lowagie/text/pdf/SimpleXMLDocHandler.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/SimpleXMLDocHandler.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright 2003 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.util.HashMap;
-
-/**
- * The handler for the events fired by SimpleXMLParser
.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public interface SimpleXMLDocHandler {
- /**
- * Called when a start tag is found.
- * @param tag the tag name
- * @param h the tag's attributes
- */
- public void startElement(String tag, HashMap h);
- /**
- * Called when an end tag is found.
- * @param tag the tag name
- */
- public void endElement(String tag);
- /**
- * Called when the document starts to be parsed.
- */
- public void startDocument();
- /**
- * Called after the document is parsed.
- */
- public void endDocument();
- /**
- * Called when a text element is found.
- * @param str the text element, probably a fragment.
- */
- public void text(String str);
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/SimpleXMLDocHandlerComment.java pdftk-2.01/java/com/lowagie/text/pdf/SimpleXMLDocHandlerComment.java
--- pdftk-1.45/java/com/lowagie/text/pdf/SimpleXMLDocHandlerComment.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/SimpleXMLDocHandlerComment.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright 2003 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-/**
- * The handler for the events fired by SimpleXMLParser
.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public interface SimpleXMLDocHandlerComment {
- /**
- * Called when a comment is found.
- * @param text the comment text
- */
- public void comment(String text);
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/SimpleXMLParser.java pdftk-2.01/java/com/lowagie/text/pdf/SimpleXMLParser.java
--- pdftk-1.45/java/com/lowagie/text/pdf/SimpleXMLParser.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/SimpleXMLParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,1190 +0,0 @@
-/*
- * Copyright 2003 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.io.*;
-import java.util.Stack;
-import java.util.HashMap;
-
-/**
- * A simple XML and HTML parser. This parser is, like the SAX parser,
- * an event based parser, but with much less functionality.
- *
- * The parser can:
- *
- *
- * It recognizes the encoding used
- * It recognizes all the elements' start tags and end tags
- * It lists attributes, where attribute values can be enclosed in single or double quotes
- * It recognizes the <[CDATA[ ... ]]>
construct
- * It recognizes the standard entities: &, <, >, ", and ', as well as numeric entities
- * It maps lines ending in \r\n
and \r
to \n
on input, in accordance with the XML Specification, Section 2.11
- *
- *
- * The code is based on
- * http://www.javaworld.com/javaworld/javatips/javatip128/ with some extra
- * code from XERCES to recognize the encoding.
- */
-public class SimpleXMLParser {
-
- // ssteward
- // Input_UTF8 was being omitted from Windows static builds
- private static Class c1= gnu.gcj.convert.Input_UTF8.class;
- private static Class c2= gnu.gcj.convert.Input_8859_1.class;
- private static Class c3= gnu.gcj.convert.Input_ASCII.class;
-
- private static final HashMap fIANA2JavaMap = new HashMap();
- private static final HashMap entityMap = new HashMap();
-
- private static int popMode(Stack st) {
- if(!st.empty())
- return ((Integer)st.pop()).intValue();
- else
- return PRE;
- }
-
- private final static int
- TEXT = 1,
- ENTITY = 2,
- OPEN_TAG = 3,
- CLOSE_TAG = 4,
- START_TAG = 5,
- ATTRIBUTE_LVALUE = 6,
- ATTRIBUTE_EQUAL = 9,
- ATTRIBUTE_RVALUE = 10,
- QUOTE = 7,
- IN_TAG = 8,
- SINGLE_TAG = 12,
- COMMENT = 13,
- DONE = 11,
- DOCTYPE = 14,
- PRE = 15,
- CDATA = 16;
-
- private SimpleXMLParser() {
- }
-
- /**
- * Parses the XML document firing the events to the handler.
- * @param doc the document handler
- * @param in the document. The encoding is deduced from the stream. The stream is not closed
- * @throws IOException on error
- */
- public static void parse(SimpleXMLDocHandler doc, InputStream in) throws IOException {
- byte b4[] = new byte[4];
- int count = in.read(b4);
- if (count != 4)
- throw new IOException("Insufficient length.");
- String encoding = getEncodingName(b4);
- String decl = null;
- if (encoding.equals("UTF-8")) {
- StringBuffer sb = new StringBuffer();
- int c;
- while ((c = in.read()) != -1) {
- if (c == '>')
- break;
- sb.append((char)c);
- }
- decl = sb.toString();
- }
- else if (encoding.equals("CP037")) {
- ByteArrayOutputStream bi = new ByteArrayOutputStream();
- int c;
- while ((c = in.read()) != -1) {
- if (c == 0x6e) // that's '>' in ebcdic
- break;
- bi.write(c);
- }
- decl = new String(bi.toByteArray(), "CP037");
- }
- if (decl != null) {
- decl = getDeclaredEncoding(decl);
- if (decl != null)
- encoding = decl;
- }
- parse(doc, new InputStreamReader(in, getJavaEncoding(encoding)));
- }
-
- private static String getDeclaredEncoding(String decl) {
- if (decl == null)
- return null;
- int idx = decl.indexOf("encoding");
- if (idx < 0)
- return null;
- int idx1 = decl.indexOf('"', idx);
- int idx2 = decl.indexOf('\'', idx);
- if (idx1 == idx2)
- return null;
- if ((idx1 < 0 && idx2 > 0) || (idx2 > 0 && idx2 < idx1)) {
- int idx3 = decl.indexOf('\'', idx2 + 1);
- if (idx3 < 0)
- return null;
- return decl.substring(idx2 + 1, idx3);
- }
- if ((idx2 < 0 && idx1 > 0) || (idx1 > 0 && idx1 < idx2)) {
- int idx3 = decl.indexOf('"', idx1 + 1);
- if (idx3 < 0)
- return null;
- return decl.substring(idx1 + 1, idx3);
- }
- return null;
- }
-
- /**
- * Gets the java encoding from the IANA encoding. If the encoding cannot be found
- * it returns the input.
- * @param iana the IANA encoding
- * @return the java encoding
- */
- public static String getJavaEncoding(String iana) {
- String IANA = iana.toUpperCase();
- String jdec = (String)fIANA2JavaMap.get(IANA);
- if (jdec == null)
- jdec = iana;
- return jdec;
- }
-
- public static void parse(SimpleXMLDocHandler doc,Reader r) throws IOException {
- parse(doc, null, r, false);
- }
-
- /**
- * Parses the XML document firing the events to the handler.
- * @param doc the document handler
- * @param r the document. The encoding is already resolved. The reader is not closed
- * @throws IOException on error
- */
- public static void parse(SimpleXMLDocHandler doc, SimpleXMLDocHandlerComment comment, Reader r, boolean html) throws IOException {
- BufferedReader reader;
- if (r instanceof BufferedReader)
- reader = (BufferedReader)r;
- else
- reader = new BufferedReader(r);
- Stack st = new Stack();
- int depth = 0;
- int mode = PRE;
- int c = 0;
- int quotec = '"';
- depth = 0;
- StringBuffer sb = new StringBuffer();
- StringBuffer etag = new StringBuffer();
- String tagName = null;
- String lvalue = null;
- String rvalue = null;
- HashMap attrs = null;
- st = new Stack();
- doc.startDocument();
- int line=1, col=0;
- boolean eol = false;
- if (html)
- mode = TEXT;
- int pushBack = -1;
- while(true) {
- if (pushBack != -1) {
- c = pushBack;
- pushBack = -1;
- }
- else
- c = reader.read();
- if (c == -1)
- break;
-
- // We need to map \r, \r\n, and \n to \n
- // See XML spec section 2.11
- if(c == '\n' && eol) {
- eol = false;
- continue;
- } else if(eol) {
- eol = false;
- } else if(c == '\n') {
- line++;
- col=0;
- } else if(c == '\r') {
- eol = true;
- c = '\n';
- line++;
- col=0;
- } else {
- col++;
- }
-
- if(mode == DONE) {
- doc.endDocument();
- return;
-
- // We are between tags collecting text.
- } else if(mode == TEXT) {
- if(c == '<') {
- st.push(new Integer(mode));
- mode = START_TAG;
- if(sb.length() > 0) {
- doc.text(sb.toString());
- sb.setLength(0);
- }
- } else if(c == '&') {
- st.push(new Integer(mode));
- mode = ENTITY;
- etag.setLength(0);
- } else
- sb.append((char)c);
-
- // we are processing a closing tag: e.g.
- } else if(mode == CLOSE_TAG) {
- if(c == '>') {
- mode = popMode(st);
- tagName = sb.toString();
- if (html)
- tagName = tagName.toLowerCase();
- sb.setLength(0);
- depth--;
- if(!html && depth==0)
- mode = DONE;
- doc.endElement(tagName);
- } else {
- if (!Character.isWhitespace((char)c))
- sb.append((char)c);
- }
-
- // we are processing CDATA
- } else if(mode == CDATA) {
- if(c == '>'
- && sb.toString().endsWith("]]")) {
- sb.setLength(sb.length()-2);
- doc.text(sb.toString());
- sb.setLength(0);
- mode = popMode(st);
- } else
- sb.append((char)c);
-
- // we are processing a comment. We are inside
- // the looking for the -->.
- } else if(mode == COMMENT) {
- if(c == '>'
- && sb.toString().endsWith("--")) {
- if (comment != null) {
- sb.setLength(sb.length() - 2);
- comment.comment(sb.toString());
- }
- sb.setLength(0);
- mode = popMode(st);
- } else
- sb.append((char)c);
-
- // We are outside the root tag element
- } else if(mode == PRE) {
- if(c == '<') {
- mode = TEXT;
- st.push(new Integer(mode));
- mode = START_TAG;
- }
-
- // We are inside one of these ... ?>
- // or one of these
- } else if(mode == DOCTYPE) {
- if(c == '>') {
- mode = popMode(st);
- if(mode == TEXT) mode = PRE;
- }
-
- // we have just seen a < and
- // are wondering what we are looking at
- // , , , etc.
- } else if(mode == START_TAG) {
- mode = popMode(st);
- if(c == '/') {
- st.push(new Integer(mode));
- mode = CLOSE_TAG;
- } else if (c == '?') {
- mode = DOCTYPE;
- } else {
- st.push(new Integer(mode));
- mode = OPEN_TAG;
- tagName = null;
- attrs = new HashMap();
- sb.append((char)c);
- }
-
- // we are processing an entity, e.g. <, », etc.
- } else if(mode == ENTITY) {
- if(c == ';') {
- mode = popMode(st);
- String cent = etag.toString();
- etag.setLength(0);
- if(cent.startsWith("#x")) {
- try {
- char ci = (char)Integer.parseInt(cent.substring(2),16);
- sb.append(ci);
- }
- catch (Exception es) {
- sb.append('&').append(cent).append(';');
- }
- }
- else if(cent.startsWith("#")) {
- try {
- char ci = (char)Integer.parseInt(cent.substring(1));
- sb.append(ci);
- }
- catch (Exception es) {
- sb.append('&').append(cent).append(';');
- }
- }
- else {
- char ce = decodeEntity(cent);
- if (ce == '\0')
- sb.append('&').append(cent).append(';');
- else
- sb.append(ce);
- }
- } else if ((c != '#' && (c < '0' || c > '9') && (c < 'a' || c > 'z')
- && (c < 'A' || c > 'Z')) || etag.length() >= 7) {
- mode = popMode(st);
- pushBack = c;
- sb.append('&').append(etag.toString());
- etag.setLength(0);
- }
- else {
- etag.append((char)c);
- }
-
- // we have just seen something like this:
- // .
- } else if(mode == SINGLE_TAG) {
- if(tagName == null)
- tagName = sb.toString();
- if (html)
- tagName = tagName.toLowerCase();
- if(c != '>')
- exc("Expected > for tag: <"+tagName+"/>",line,col);
- doc.startElement(tagName,attrs);
- doc.endElement(tagName);
- if(!html && depth==0) {
- doc.endDocument();
- return;
- }
- sb.setLength(0);
- attrs = new HashMap();
- tagName = null;
- mode = popMode(st);
-
- // we are processing something
- // like this . It could
- // still be a or something.
- } else if(mode == OPEN_TAG) {
- if(c == '>') {
- if(tagName == null)
- tagName = sb.toString();
- if (html)
- tagName = tagName.toLowerCase();
- sb.setLength(0);
- depth++;
- doc.startElement(tagName,attrs);
- tagName = null;
- attrs = new HashMap();
- mode = popMode(st);
- } else if(c == '/') {
- mode = SINGLE_TAG;
- } else if(c == '-' && sb.toString().equals("!-")) {
- mode = COMMENT;
- sb.setLength(0);
- } else if(c == '[' && sb.toString().equals("![CDATA")) {
- mode = CDATA;
- sb.setLength(0);
- } else if(c == 'E' && sb.toString().equals("!DOCTYP")) {
- sb.setLength(0);
- mode = DOCTYPE;
- } else if(Character.isWhitespace((char)c)) {
- tagName = sb.toString();
- if (html)
- tagName = tagName.toLowerCase();
- sb.setLength(0);
- mode = IN_TAG;
- } else {
- sb.append((char)c);
- }
-
- // We are processing the quoted right-hand side
- // of an element's attribute.
- } else if(mode == QUOTE) {
- if (html && quotec == ' ' && c == '>') {
- rvalue = sb.toString();
- sb.setLength(0);
- attrs.put(lvalue,rvalue);
- mode = popMode(st);
- doc.startElement(tagName,attrs);
- depth++;
- tagName = null;
- attrs = new HashMap();
- }
- else if (html && quotec == ' ' && Character.isWhitespace((char)c)) {
- rvalue = sb.toString();
- sb.setLength(0);
- attrs.put(lvalue,rvalue);
- mode = IN_TAG;
- }
- else if (html && quotec == ' ') {
- sb.append((char)c);
- }
- else if(c == quotec) {
- rvalue = sb.toString();
- sb.setLength(0);
- attrs.put(lvalue,rvalue);
- mode = IN_TAG;
- // See section the XML spec, section 3.3.3
- // on normalization processing.
- } else if(" \r\n\u0009".indexOf(c)>=0) {
- sb.append(' ');
- } else if(c == '&') {
- st.push(new Integer(mode));
- mode = ENTITY;
- etag.setLength(0);
- } else {
- sb.append((char)c);
- }
-
- } else if(mode == ATTRIBUTE_RVALUE) {
- if(c == '"' || c == '\'') {
- quotec = c;
- mode = QUOTE;
- } else if(Character.isWhitespace((char)c)) {
- ;
- } else if (html && c == '>') {
- attrs.put(lvalue,sb.toString());
- sb.setLength(0);
- mode = popMode(st);
- doc.startElement(tagName,attrs);
- depth++;
- tagName = null;
- attrs = new HashMap();
- } else if (html) {
- sb.append((char)c);
- quotec = ' ';
- mode = QUOTE;
- } else {
- exc("Error in attribute processing",line,col);
- }
-
- } else if(mode == ATTRIBUTE_LVALUE) {
- if(Character.isWhitespace((char)c)) {
- lvalue = sb.toString();
- if (html)
- lvalue = lvalue.toLowerCase();
- sb.setLength(0);
- mode = ATTRIBUTE_EQUAL;
- } else if(c == '=') {
- lvalue = sb.toString();
- if (html)
- lvalue = lvalue.toLowerCase();
- sb.setLength(0);
- mode = ATTRIBUTE_RVALUE;
- } else if (html && c == '>') {
- sb.setLength(0);
- mode = popMode(st);
- doc.startElement(tagName,attrs);
- depth++;
- tagName = null;
- attrs = new HashMap();
- } else {
- sb.append((char)c);
- }
-
- } else if(mode == ATTRIBUTE_EQUAL) {
- if(c == '=') {
- mode = ATTRIBUTE_RVALUE;
- } else if(Character.isWhitespace((char)c)) {
- ;
- } else if (html && c == '>') {
- sb.setLength(0);
- mode = popMode(st);
- doc.startElement(tagName,attrs);
- depth++;
- tagName = null;
- attrs = new HashMap();
- } else if (html && c == '/') {
- sb.setLength(0);
- mode = SINGLE_TAG;
- } else if (html) {
- sb.setLength(0);
- sb.append((char)c);
- mode = ATTRIBUTE_LVALUE;
- } else {
- exc("Error in attribute processing.",line,col);
- }
-
- } else if(mode == IN_TAG) {
- if(c == '>') {
- mode = popMode(st);
- doc.startElement(tagName,attrs);
- depth++;
- tagName = null;
- attrs = new HashMap();
- } else if(c == '/') {
- mode = SINGLE_TAG;
- } else if(Character.isWhitespace((char)c)) {
- ;
- } else {
- mode = ATTRIBUTE_LVALUE;
- sb.append((char)c);
- }
- }
- }
- if(html || mode == DONE) {
- if (html && mode == TEXT)
- doc.text(sb.toString());
- doc.endDocument();
- }
- else
- exc("missing end tag",line,col);
- }
- private static void exc(String s,int line,int col) throws IOException {
- throw new IOException(s+" near line "+line+", column "+col);
- }
-
- /**
- * Escapes a string with the appropriated XML codes.
- * @param s the string to be escaped
- * @param onlyASCII codes above 127 will always be escaped with &#nn; if true
- * @return the escaped string
- */
- public static String escapeXML(String s, boolean onlyASCII) {
- char cc[] = s.toCharArray();
- int len = cc.length;
- StringBuffer sb = new StringBuffer();
- for (int k = 0; k < len; ++k) {
- int c = cc[k];
- switch (c) {
- case '<':
- sb.append("<");
- break;
- case '>':
- sb.append(">");
- break;
- case '&':
- sb.append("&");
- break;
- case '"':
- sb.append(""");
- break;
- case '\'':
- sb.append("'");
- break;
- default:
- if (onlyASCII && c > 127)
- sb.append("").append(c).append(";");
- else
- sb.append((char)c);
- }
- }
- return sb.toString();
- }
-
- public static char decodeEntity(String s) {
- Character c = (Character)entityMap.get(s);
- if (c == null)
- return '\0';
- else
- return c.charValue();
- }
-
- private static String getEncodingName(byte[] b4) {
-
- // UTF-16, with BOM
- int b0 = b4[0] & 0xFF;
- int b1 = b4[1] & 0xFF;
- if (b0 == 0xFE && b1 == 0xFF) {
- // UTF-16, big-endian
- return "UTF-16BE";
- }
- if (b0 == 0xFF && b1 == 0xFE) {
- // UTF-16, little-endian
- return "UTF-16LE";
- }
-
- // UTF-8 with a BOM
- int b2 = b4[2] & 0xFF;
- if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
- return "UTF-8";
- }
-
- // other encodings
- int b3 = b4[3] & 0xFF;
- if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
- // UCS-4, big endian (1234)
- return "ISO-10646-UCS-4";
- }
- if (b0 == 0x3C && b1 == 0x00 && b2 == 0x00 && b3 == 0x00) {
- // UCS-4, little endian (4321)
- return "ISO-10646-UCS-4";
- }
- if (b0 == 0x00 && b1 == 0x00 && b2 == 0x3C && b3 == 0x00) {
- // UCS-4, unusual octet order (2143)
- // REVISIT: What should this be?
- return "ISO-10646-UCS-4";
- }
- if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x00) {
- // UCS-4, unusual octect order (3412)
- // REVISIT: What should this be?
- return "ISO-10646-UCS-4";
- }
- if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
- // UTF-16, big-endian, no BOM
- // (or could turn out to be UCS-2...
- // REVISIT: What should this be?
- return "UTF-16BE";
- }
- if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
- // UTF-16, little-endian, no BOM
- // (or could turn out to be UCS-2...
- return "UTF-16LE";
- }
- if (b0 == 0x4C && b1 == 0x6F && b2 == 0xA7 && b3 == 0x94) {
- // EBCDIC
- // a la xerces1, return CP037 instead of EBCDIC here
- return "CP037";
- }
-
- // default encoding
- return "UTF-8";
- }
-
- static {
- // add IANA to Java encoding mappings.
- fIANA2JavaMap.put("BIG5", "Big5");
- fIANA2JavaMap.put("CSBIG5", "Big5");
- fIANA2JavaMap.put("CP037", "CP037");
- fIANA2JavaMap.put("IBM037", "CP037");
- fIANA2JavaMap.put("CSIBM037", "CP037");
- fIANA2JavaMap.put("EBCDIC-CP-US", "CP037");
- fIANA2JavaMap.put("EBCDIC-CP-CA", "CP037");
- fIANA2JavaMap.put("EBCDIC-CP-NL", "CP037");
- fIANA2JavaMap.put("EBCDIC-CP-WT", "CP037");
- fIANA2JavaMap.put("IBM277", "CP277");
- fIANA2JavaMap.put("CP277", "CP277");
- fIANA2JavaMap.put("CSIBM277", "CP277");
- fIANA2JavaMap.put("EBCDIC-CP-DK", "CP277");
- fIANA2JavaMap.put("EBCDIC-CP-NO", "CP277");
- fIANA2JavaMap.put("IBM278", "CP278");
- fIANA2JavaMap.put("CP278", "CP278");
- fIANA2JavaMap.put("CSIBM278", "CP278");
- fIANA2JavaMap.put("EBCDIC-CP-FI", "CP278");
- fIANA2JavaMap.put("EBCDIC-CP-SE", "CP278");
- fIANA2JavaMap.put("IBM280", "CP280");
- fIANA2JavaMap.put("CP280", "CP280");
- fIANA2JavaMap.put("CSIBM280", "CP280");
- fIANA2JavaMap.put("EBCDIC-CP-IT", "CP280");
- fIANA2JavaMap.put("IBM284", "CP284");
- fIANA2JavaMap.put("CP284", "CP284");
- fIANA2JavaMap.put("CSIBM284", "CP284");
- fIANA2JavaMap.put("EBCDIC-CP-ES", "CP284");
- fIANA2JavaMap.put("EBCDIC-CP-GB", "CP285");
- fIANA2JavaMap.put("IBM285", "CP285");
- fIANA2JavaMap.put("CP285", "CP285");
- fIANA2JavaMap.put("CSIBM285", "CP285");
- fIANA2JavaMap.put("EBCDIC-CP-FR", "CP297");
- fIANA2JavaMap.put("IBM297", "CP297");
- fIANA2JavaMap.put("CP297", "CP297");
- fIANA2JavaMap.put("CSIBM297", "CP297");
- fIANA2JavaMap.put("EBCDIC-CP-AR1", "CP420");
- fIANA2JavaMap.put("IBM420", "CP420");
- fIANA2JavaMap.put("CP420", "CP420");
- fIANA2JavaMap.put("CSIBM420", "CP420");
- fIANA2JavaMap.put("EBCDIC-CP-HE", "CP424");
- fIANA2JavaMap.put("IBM424", "CP424");
- fIANA2JavaMap.put("CP424", "CP424");
- fIANA2JavaMap.put("CSIBM424", "CP424");
- fIANA2JavaMap.put("EBCDIC-CP-CH", "CP500");
- fIANA2JavaMap.put("IBM500", "CP500");
- fIANA2JavaMap.put("CP500", "CP500");
- fIANA2JavaMap.put("CSIBM500", "CP500");
- fIANA2JavaMap.put("EBCDIC-CP-CH", "CP500");
- fIANA2JavaMap.put("EBCDIC-CP-BE", "CP500");
- fIANA2JavaMap.put("IBM868", "CP868");
- fIANA2JavaMap.put("CP868", "CP868");
- fIANA2JavaMap.put("CSIBM868", "CP868");
- fIANA2JavaMap.put("CP-AR", "CP868");
- fIANA2JavaMap.put("IBM869", "CP869");
- fIANA2JavaMap.put("CP869", "CP869");
- fIANA2JavaMap.put("CSIBM869", "CP869");
- fIANA2JavaMap.put("CP-GR", "CP869");
- fIANA2JavaMap.put("IBM870", "CP870");
- fIANA2JavaMap.put("CP870", "CP870");
- fIANA2JavaMap.put("CSIBM870", "CP870");
- fIANA2JavaMap.put("EBCDIC-CP-ROECE", "CP870");
- fIANA2JavaMap.put("EBCDIC-CP-YU", "CP870");
- fIANA2JavaMap.put("IBM871", "CP871");
- fIANA2JavaMap.put("CP871", "CP871");
- fIANA2JavaMap.put("CSIBM871", "CP871");
- fIANA2JavaMap.put("EBCDIC-CP-IS", "CP871");
- fIANA2JavaMap.put("IBM918", "CP918");
- fIANA2JavaMap.put("CP918", "CP918");
- fIANA2JavaMap.put("CSIBM918", "CP918");
- fIANA2JavaMap.put("EBCDIC-CP-AR2", "CP918");
- fIANA2JavaMap.put("EUC-JP", "EUCJIS");
- fIANA2JavaMap.put("CSEUCPkdFmtJapanese", "EUCJIS");
- fIANA2JavaMap.put("EUC-KR", "KSC5601");
- fIANA2JavaMap.put("GB2312", "GB2312");
- fIANA2JavaMap.put("CSGB2312", "GB2312");
- fIANA2JavaMap.put("ISO-2022-JP", "JIS");
- fIANA2JavaMap.put("CSISO2022JP", "JIS");
- fIANA2JavaMap.put("ISO-2022-KR", "ISO2022KR");
- fIANA2JavaMap.put("CSISO2022KR", "ISO2022KR");
- fIANA2JavaMap.put("ISO-2022-CN", "ISO2022CN");
-
- fIANA2JavaMap.put("X0201", "JIS0201");
- fIANA2JavaMap.put("CSISO13JISC6220JP", "JIS0201");
- fIANA2JavaMap.put("X0208", "JIS0208");
- fIANA2JavaMap.put("ISO-IR-87", "JIS0208");
- fIANA2JavaMap.put("X0208dbiJIS_X0208-1983", "JIS0208");
- fIANA2JavaMap.put("CSISO87JISX0208", "JIS0208");
- fIANA2JavaMap.put("X0212", "JIS0212");
- fIANA2JavaMap.put("ISO-IR-159", "JIS0212");
- fIANA2JavaMap.put("CSISO159JISX02121990", "JIS0212");
- fIANA2JavaMap.put("SHIFT_JIS", "SJIS");
- fIANA2JavaMap.put("CSSHIFT_JIS", "SJIS");
- fIANA2JavaMap.put("MS_Kanji", "SJIS");
-
- // Add support for Cp1252 and its friends
- fIANA2JavaMap.put("WINDOWS-1250", "Cp1250");
- fIANA2JavaMap.put("WINDOWS-1251", "Cp1251");
- fIANA2JavaMap.put("WINDOWS-1252", "Cp1252");
- fIANA2JavaMap.put("WINDOWS-1253", "Cp1253");
- fIANA2JavaMap.put("WINDOWS-1254", "Cp1254");
- fIANA2JavaMap.put("WINDOWS-1255", "Cp1255");
- fIANA2JavaMap.put("WINDOWS-1256", "Cp1256");
- fIANA2JavaMap.put("WINDOWS-1257", "Cp1257");
- fIANA2JavaMap.put("WINDOWS-1258", "Cp1258");
- fIANA2JavaMap.put("TIS-620", "TIS620");
-
- fIANA2JavaMap.put("ISO-8859-1", "ISO8859_1");
- fIANA2JavaMap.put("ISO-IR-100", "ISO8859_1");
- fIANA2JavaMap.put("ISO_8859-1", "ISO8859_1");
- fIANA2JavaMap.put("LATIN1", "ISO8859_1");
- fIANA2JavaMap.put("CSISOLATIN1", "ISO8859_1");
- fIANA2JavaMap.put("L1", "ISO8859_1");
- fIANA2JavaMap.put("IBM819", "ISO8859_1");
- fIANA2JavaMap.put("CP819", "ISO8859_1");
-
- fIANA2JavaMap.put("ISO-8859-2", "ISO8859_2");
- fIANA2JavaMap.put("ISO-IR-101", "ISO8859_2");
- fIANA2JavaMap.put("ISO_8859-2", "ISO8859_2");
- fIANA2JavaMap.put("LATIN2", "ISO8859_2");
- fIANA2JavaMap.put("CSISOLATIN2", "ISO8859_2");
- fIANA2JavaMap.put("L2", "ISO8859_2");
-
- fIANA2JavaMap.put("ISO-8859-3", "ISO8859_3");
- fIANA2JavaMap.put("ISO-IR-109", "ISO8859_3");
- fIANA2JavaMap.put("ISO_8859-3", "ISO8859_3");
- fIANA2JavaMap.put("LATIN3", "ISO8859_3");
- fIANA2JavaMap.put("CSISOLATIN3", "ISO8859_3");
- fIANA2JavaMap.put("L3", "ISO8859_3");
-
- fIANA2JavaMap.put("ISO-8859-4", "ISO8859_4");
- fIANA2JavaMap.put("ISO-IR-110", "ISO8859_4");
- fIANA2JavaMap.put("ISO_8859-4", "ISO8859_4");
- fIANA2JavaMap.put("LATIN4", "ISO8859_4");
- fIANA2JavaMap.put("CSISOLATIN4", "ISO8859_4");
- fIANA2JavaMap.put("L4", "ISO8859_4");
-
- fIANA2JavaMap.put("ISO-8859-5", "ISO8859_5");
- fIANA2JavaMap.put("ISO-IR-144", "ISO8859_5");
- fIANA2JavaMap.put("ISO_8859-5", "ISO8859_5");
- fIANA2JavaMap.put("CYRILLIC", "ISO8859_5");
- fIANA2JavaMap.put("CSISOLATINCYRILLIC", "ISO8859_5");
-
- fIANA2JavaMap.put("ISO-8859-6", "ISO8859_6");
- fIANA2JavaMap.put("ISO-IR-127", "ISO8859_6");
- fIANA2JavaMap.put("ISO_8859-6", "ISO8859_6");
- fIANA2JavaMap.put("ECMA-114", "ISO8859_6");
- fIANA2JavaMap.put("ASMO-708", "ISO8859_6");
- fIANA2JavaMap.put("ARABIC", "ISO8859_6");
- fIANA2JavaMap.put("CSISOLATINARABIC", "ISO8859_6");
-
- fIANA2JavaMap.put("ISO-8859-7", "ISO8859_7");
- fIANA2JavaMap.put("ISO-IR-126", "ISO8859_7");
- fIANA2JavaMap.put("ISO_8859-7", "ISO8859_7");
- fIANA2JavaMap.put("ELOT_928", "ISO8859_7");
- fIANA2JavaMap.put("ECMA-118", "ISO8859_7");
- fIANA2JavaMap.put("GREEK", "ISO8859_7");
- fIANA2JavaMap.put("CSISOLATINGREEK", "ISO8859_7");
- fIANA2JavaMap.put("GREEK8", "ISO8859_7");
-
- fIANA2JavaMap.put("ISO-8859-8", "ISO8859_8");
- fIANA2JavaMap.put("ISO-8859-8-I", "ISO8859_8"); // added since this encoding only differs w.r.t. presentation
- fIANA2JavaMap.put("ISO-IR-138", "ISO8859_8");
- fIANA2JavaMap.put("ISO_8859-8", "ISO8859_8");
- fIANA2JavaMap.put("HEBREW", "ISO8859_8");
- fIANA2JavaMap.put("CSISOLATINHEBREW", "ISO8859_8");
-
- fIANA2JavaMap.put("ISO-8859-9", "ISO8859_9");
- fIANA2JavaMap.put("ISO-IR-148", "ISO8859_9");
- fIANA2JavaMap.put("ISO_8859-9", "ISO8859_9");
- fIANA2JavaMap.put("LATIN5", "ISO8859_9");
- fIANA2JavaMap.put("CSISOLATIN5", "ISO8859_9");
- fIANA2JavaMap.put("L5", "ISO8859_9");
-
- fIANA2JavaMap.put("KOI8-R", "KOI8_R");
- fIANA2JavaMap.put("CSKOI8-R", "KOI8_R");
- fIANA2JavaMap.put("US-ASCII", "ASCII");
- fIANA2JavaMap.put("ISO-IR-6", "ASCII");
- fIANA2JavaMap.put("ANSI_X3.4-1986", "ASCII");
- fIANA2JavaMap.put("ISO_646.IRV:1991", "ASCII");
- fIANA2JavaMap.put("ASCII", "ASCII");
- fIANA2JavaMap.put("CSASCII", "ASCII");
- fIANA2JavaMap.put("ISO646-US", "ASCII");
- fIANA2JavaMap.put("US", "ASCII");
- fIANA2JavaMap.put("IBM367", "ASCII");
- fIANA2JavaMap.put("CP367", "ASCII");
- fIANA2JavaMap.put("UTF-8", "UTF8");
- fIANA2JavaMap.put("UTF-16", "Unicode");
- fIANA2JavaMap.put("UTF-16BE", "UnicodeBig");
- fIANA2JavaMap.put("UTF-16LE", "UnicodeLittle");
-
- entityMap.put("nbsp", new Character('\u00a0')); // no-break space = non-breaking space, U+00A0 ISOnum
- entityMap.put("iexcl", new Character('\u00a1')); // inverted exclamation mark, U+00A1 ISOnum
- entityMap.put("cent", new Character('\u00a2')); // cent sign, U+00A2 ISOnum
- entityMap.put("pound", new Character('\u00a3')); // pound sign, U+00A3 ISOnum
- entityMap.put("curren", new Character('\u00a4')); // currency sign, U+00A4 ISOnum
- entityMap.put("yen", new Character('\u00a5')); // yen sign = yuan sign, U+00A5 ISOnum
- entityMap.put("brvbar", new Character('\u00a6')); // broken bar = broken vertical bar, U+00A6 ISOnum
- entityMap.put("sect", new Character('\u00a7')); // section sign, U+00A7 ISOnum
- entityMap.put("uml", new Character('\u00a8')); // diaeresis = spacing diaeresis, U+00A8 ISOdia
- entityMap.put("copy", new Character('\u00a9')); // copyright sign, U+00A9 ISOnum
- entityMap.put("ordf", new Character('\u00aa')); // feminine ordinal indicator, U+00AA ISOnum
- entityMap.put("laquo", new Character('\u00ab')); // left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum
- entityMap.put("not", new Character('\u00ac')); // not sign, U+00AC ISOnum
- entityMap.put("shy", new Character('\u00ad')); // soft hyphen = discretionary hyphen, U+00AD ISOnum
- entityMap.put("reg", new Character('\u00ae')); // registered sign = registered trade mark sign, U+00AE ISOnum
- entityMap.put("macr", new Character('\u00af')); // macron = spacing macron = overline = APL overbar, U+00AF ISOdia
- entityMap.put("deg", new Character('\u00b0')); // degree sign, U+00B0 ISOnum
- entityMap.put("plusmn", new Character('\u00b1')); // plus-minus sign = plus-or-minus sign, U+00B1 ISOnum
- entityMap.put("sup2", new Character('\u00b2')); // superscript two = superscript digit two = squared, U+00B2 ISOnum
- entityMap.put("sup3", new Character('\u00b3')); // superscript three = superscript digit three = cubed, U+00B3 ISOnum
- entityMap.put("acute", new Character('\u00b4')); // acute accent = spacing acute, U+00B4 ISOdia
- entityMap.put("micro", new Character('\u00b5')); // micro sign, U+00B5 ISOnum
- entityMap.put("para", new Character('\u00b6')); // pilcrow sign = paragraph sign, U+00B6 ISOnum
- entityMap.put("middot", new Character('\u00b7')); // middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum
- entityMap.put("cedil", new Character('\u00b8')); // cedilla = spacing cedilla, U+00B8 ISOdia
- entityMap.put("sup1", new Character('\u00b9')); // superscript one = superscript digit one, U+00B9 ISOnum
- entityMap.put("ordm", new Character('\u00ba')); // masculine ordinal indicator, U+00BA ISOnum
- entityMap.put("raquo", new Character('\u00bb')); // right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum
- entityMap.put("frac14", new Character('\u00bc')); // vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum
- entityMap.put("frac12", new Character('\u00bd')); // vulgar fraction one half = fraction one half, U+00BD ISOnum
- entityMap.put("frac34", new Character('\u00be')); // vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum
- entityMap.put("iquest", new Character('\u00bf')); // inverted question mark = turned question mark, U+00BF ISOnum
- entityMap.put("Agrave", new Character('\u00c0')); // latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1
- entityMap.put("Aacute", new Character('\u00c1')); // latin capital letter A with acute, U+00C1 ISOlat1
- entityMap.put("Acirc", new Character('\u00c2')); // latin capital letter A with circumflex, U+00C2 ISOlat1
- entityMap.put("Atilde", new Character('\u00c3')); // latin capital letter A with tilde, U+00C3 ISOlat1
- entityMap.put("Auml", new Character('\u00c4')); // latin capital letter A with diaeresis, U+00C4 ISOlat1
- entityMap.put("Aring", new Character('\u00c5')); // latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1
- entityMap.put("AElig", new Character('\u00c6')); // latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1
- entityMap.put("Ccedil", new Character('\u00c7')); // latin capital letter C with cedilla, U+00C7 ISOlat1
- entityMap.put("Egrave", new Character('\u00c8')); // latin capital letter E with grave, U+00C8 ISOlat1
- entityMap.put("Eacute", new Character('\u00c9')); // latin capital letter E with acute, U+00C9 ISOlat1
- entityMap.put("Ecirc", new Character('\u00ca')); // latin capital letter E with circumflex, U+00CA ISOlat1
- entityMap.put("Euml", new Character('\u00cb')); // latin capital letter E with diaeresis, U+00CB ISOlat1
- entityMap.put("Igrave", new Character('\u00cc')); // latin capital letter I with grave, U+00CC ISOlat1
- entityMap.put("Iacute", new Character('\u00cd')); // latin capital letter I with acute, U+00CD ISOlat1
- entityMap.put("Icirc", new Character('\u00ce')); // latin capital letter I with circumflex, U+00CE ISOlat1
- entityMap.put("Iuml", new Character('\u00cf')); // latin capital letter I with diaeresis, U+00CF ISOlat1
- entityMap.put("ETH", new Character('\u00d0')); // latin capital letter ETH, U+00D0 ISOlat1
- entityMap.put("Ntilde", new Character('\u00d1')); // latin capital letter N with tilde, U+00D1 ISOlat1
- entityMap.put("Ograve", new Character('\u00d2')); // latin capital letter O with grave, U+00D2 ISOlat1
- entityMap.put("Oacute", new Character('\u00d3')); // latin capital letter O with acute, U+00D3 ISOlat1
- entityMap.put("Ocirc", new Character('\u00d4')); // latin capital letter O with circumflex, U+00D4 ISOlat1
- entityMap.put("Otilde", new Character('\u00d5')); // latin capital letter O with tilde, U+00D5 ISOlat1
- entityMap.put("Ouml", new Character('\u00d6')); // latin capital letter O with diaeresis, U+00D6 ISOlat1
- entityMap.put("times", new Character('\u00d7')); // multiplication sign, U+00D7 ISOnum
- entityMap.put("Oslash", new Character('\u00d8')); // latin capital letter O with stroke = latin capital letter O slash, U+00D8 ISOlat1
- entityMap.put("Ugrave", new Character('\u00d9')); // latin capital letter U with grave, U+00D9 ISOlat1
- entityMap.put("Uacute", new Character('\u00da')); // latin capital letter U with acute, U+00DA ISOlat1
- entityMap.put("Ucirc", new Character('\u00db')); // latin capital letter U with circumflex, U+00DB ISOlat1
- entityMap.put("Uuml", new Character('\u00dc')); // latin capital letter U with diaeresis, U+00DC ISOlat1
- entityMap.put("Yacute", new Character('\u00dd')); // latin capital letter Y with acute, U+00DD ISOlat1
- entityMap.put("THORN", new Character('\u00de')); // latin capital letter THORN, U+00DE ISOlat1
- entityMap.put("szlig", new Character('\u00df')); // latin small letter sharp s = ess-zed, U+00DF ISOlat1
- entityMap.put("agrave", new Character('\u00e0')); // latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1
- entityMap.put("aacute", new Character('\u00e1')); // latin small letter a with acute, U+00E1 ISOlat1
- entityMap.put("acirc", new Character('\u00e2')); // latin small letter a with circumflex, U+00E2 ISOlat1
- entityMap.put("atilde", new Character('\u00e3')); // latin small letter a with tilde, U+00E3 ISOlat1
- entityMap.put("auml", new Character('\u00e4')); // latin small letter a with diaeresis, U+00E4 ISOlat1
- entityMap.put("aring", new Character('\u00e5')); // latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1
- entityMap.put("aelig", new Character('\u00e6')); // latin small letter ae = latin small ligature ae, U+00E6 ISOlat1
- entityMap.put("ccedil", new Character('\u00e7')); // latin small letter c with cedilla, U+00E7 ISOlat1
- entityMap.put("egrave", new Character('\u00e8')); // latin small letter e with grave, U+00E8 ISOlat1
- entityMap.put("eacute", new Character('\u00e9')); // latin small letter e with acute, U+00E9 ISOlat1
- entityMap.put("ecirc", new Character('\u00ea')); // latin small letter e with circumflex, U+00EA ISOlat1
- entityMap.put("euml", new Character('\u00eb')); // latin small letter e with diaeresis, U+00EB ISOlat1
- entityMap.put("igrave", new Character('\u00ec')); // latin small letter i with grave, U+00EC ISOlat1
- entityMap.put("iacute", new Character('\u00ed')); // latin small letter i with acute, U+00ED ISOlat1
- entityMap.put("icirc", new Character('\u00ee')); // latin small letter i with circumflex, U+00EE ISOlat1
- entityMap.put("iuml", new Character('\u00ef')); // latin small letter i with diaeresis, U+00EF ISOlat1
- entityMap.put("eth", new Character('\u00f0')); // latin small letter eth, U+00F0 ISOlat1
- entityMap.put("ntilde", new Character('\u00f1')); // latin small letter n with tilde, U+00F1 ISOlat1
- entityMap.put("ograve", new Character('\u00f2')); // latin small letter o with grave, U+00F2 ISOlat1
- entityMap.put("oacute", new Character('\u00f3')); // latin small letter o with acute, U+00F3 ISOlat1
- entityMap.put("ocirc", new Character('\u00f4')); // latin small letter o with circumflex, U+00F4 ISOlat1
- entityMap.put("otilde", new Character('\u00f5')); // latin small letter o with tilde, U+00F5 ISOlat1
- entityMap.put("ouml", new Character('\u00f6')); // latin small letter o with diaeresis, U+00F6 ISOlat1
- entityMap.put("divide", new Character('\u00f7')); // division sign, U+00F7 ISOnum
- entityMap.put("oslash", new Character('\u00f8')); // latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1
- entityMap.put("ugrave", new Character('\u00f9')); // latin small letter u with grave, U+00F9 ISOlat1
- entityMap.put("uacute", new Character('\u00fa')); // latin small letter u with acute, U+00FA ISOlat1
- entityMap.put("ucirc", new Character('\u00fb')); // latin small letter u with circumflex, U+00FB ISOlat1
- entityMap.put("uuml", new Character('\u00fc')); // latin small letter u with diaeresis, U+00FC ISOlat1
- entityMap.put("yacute", new Character('\u00fd')); // latin small letter y with acute, U+00FD ISOlat1
- entityMap.put("thorn", new Character('\u00fe')); // latin small letter thorn, U+00FE ISOlat1
- entityMap.put("yuml", new Character('\u00ff')); // latin small letter y with diaeresis, U+00FF ISOlat1
- // Latin Extended-B
- entityMap.put("fnof", new Character('\u0192')); // latin small f with hook = function = florin, U+0192 ISOtech
- // Greek
- entityMap.put("Alpha", new Character('\u0391')); // greek capital letter alpha, U+0391
- entityMap.put("Beta", new Character('\u0392')); // greek capital letter beta, U+0392
- entityMap.put("Gamma", new Character('\u0393')); // greek capital letter gamma, U+0393 ISOgrk3
- entityMap.put("Delta", new Character('\u0394')); // greek capital letter delta, U+0394 ISOgrk3
- entityMap.put("Epsilon", new Character('\u0395')); // greek capital letter epsilon, U+0395
- entityMap.put("Zeta", new Character('\u0396')); // greek capital letter zeta, U+0396
- entityMap.put("Eta", new Character('\u0397')); // greek capital letter eta, U+0397
- entityMap.put("Theta", new Character('\u0398')); // greek capital letter theta, U+0398 ISOgrk3
- entityMap.put("Iota", new Character('\u0399')); // greek capital letter iota, U+0399
- entityMap.put("Kappa", new Character('\u039a')); // greek capital letter kappa, U+039A
- entityMap.put("Lambda", new Character('\u039b')); // greek capital letter lambda, U+039B ISOgrk3
- entityMap.put("Mu", new Character('\u039c')); // greek capital letter mu, U+039C
- entityMap.put("Nu", new Character('\u039d')); // greek capital letter nu, U+039D
- entityMap.put("Xi", new Character('\u039e')); // greek capital letter xi, U+039E ISOgrk3
- entityMap.put("Omicron", new Character('\u039f')); // greek capital letter omicron, U+039F
- entityMap.put("Pi", new Character('\u03a0')); // greek capital letter pi, U+03A0 ISOgrk3
- entityMap.put("Rho", new Character('\u03a1')); // greek capital letter rho, U+03A1
- // there is no Sigmaf, and no U+03A2 character either
- entityMap.put("Sigma", new Character('\u03a3')); // greek capital letter sigma, U+03A3 ISOgrk3
- entityMap.put("Tau", new Character('\u03a4')); // greek capital letter tau, U+03A4
- entityMap.put("Upsilon", new Character('\u03a5')); // greek capital letter upsilon, U+03A5 ISOgrk3
- entityMap.put("Phi", new Character('\u03a6')); // greek capital letter phi, U+03A6 ISOgrk3
- entityMap.put("Chi", new Character('\u03a7')); // greek capital letter chi, U+03A7
- entityMap.put("Psi", new Character('\u03a8')); // greek capital letter psi, U+03A8 ISOgrk3
- entityMap.put("Omega", new Character('\u03a9')); // greek capital letter omega, U+03A9 ISOgrk3
- entityMap.put("alpha", new Character('\u03b1')); // greek small letter alpha, U+03B1 ISOgrk3
- entityMap.put("beta", new Character('\u03b2')); // greek small letter beta, U+03B2 ISOgrk3
- entityMap.put("gamma", new Character('\u03b3')); // greek small letter gamma, U+03B3 ISOgrk3
- entityMap.put("delta", new Character('\u03b4')); // greek small letter delta, U+03B4 ISOgrk3
- entityMap.put("epsilon", new Character('\u03b5')); // greek small letter epsilon, U+03B5 ISOgrk3
- entityMap.put("zeta", new Character('\u03b6')); // greek small letter zeta, U+03B6 ISOgrk3
- entityMap.put("eta", new Character('\u03b7')); // greek small letter eta, U+03B7 ISOgrk3
- entityMap.put("theta", new Character('\u03b8')); // greek small letter theta, U+03B8 ISOgrk3
- entityMap.put("iota", new Character('\u03b9')); // greek small letter iota, U+03B9 ISOgrk3
- entityMap.put("kappa", new Character('\u03ba')); // greek small letter kappa, U+03BA ISOgrk3
- entityMap.put("lambda", new Character('\u03bb')); // greek small letter lambda, U+03BB ISOgrk3
- entityMap.put("mu", new Character('\u03bc')); // greek small letter mu, U+03BC ISOgrk3
- entityMap.put("nu", new Character('\u03bd')); // greek small letter nu, U+03BD ISOgrk3
- entityMap.put("xi", new Character('\u03be')); // greek small letter xi, U+03BE ISOgrk3
- entityMap.put("omicron", new Character('\u03bf')); // greek small letter omicron, U+03BF NEW
- entityMap.put("pi", new Character('\u03c0')); // greek small letter pi, U+03C0 ISOgrk3
- entityMap.put("rho", new Character('\u03c1')); // greek small letter rho, U+03C1 ISOgrk3
- entityMap.put("sigmaf", new Character('\u03c2')); // greek small letter final sigma, U+03C2 ISOgrk3
- entityMap.put("sigma", new Character('\u03c3')); // greek small letter sigma, U+03C3 ISOgrk3
- entityMap.put("tau", new Character('\u03c4')); // greek small letter tau, U+03C4 ISOgrk3
- entityMap.put("upsilon", new Character('\u03c5')); // greek small letter upsilon, U+03C5 ISOgrk3
- entityMap.put("phi", new Character('\u03c6')); // greek small letter phi, U+03C6 ISOgrk3
- entityMap.put("chi", new Character('\u03c7')); // greek small letter chi, U+03C7 ISOgrk3
- entityMap.put("psi", new Character('\u03c8')); // greek small letter psi, U+03C8 ISOgrk3
- entityMap.put("omega", new Character('\u03c9')); // greek small letter omega, U+03C9 ISOgrk3
- entityMap.put("thetasym", new Character('\u03d1')); // greek small letter theta symbol, U+03D1 NEW
- entityMap.put("upsih", new Character('\u03d2')); // greek upsilon with hook symbol, U+03D2 NEW
- entityMap.put("piv", new Character('\u03d6')); // greek pi symbol, U+03D6 ISOgrk3
- // General Punctuation
- entityMap.put("bull", new Character('\u2022')); // bullet = black small circle, U+2022 ISOpub
- // bullet is NOT the same as bullet operator, U+2219
- entityMap.put("hellip", new Character('\u2026')); // horizontal ellipsis = three dot leader, U+2026 ISOpub
- entityMap.put("prime", new Character('\u2032')); // prime = minutes = feet, U+2032 ISOtech
- entityMap.put("Prime", new Character('\u2033')); // double prime = seconds = inches, U+2033 ISOtech
- entityMap.put("oline", new Character('\u203e')); // overline = spacing overscore, U+203E NEW
- entityMap.put("frasl", new Character('\u2044')); // fraction slash, U+2044 NEW
- // Letterlike Symbols
- entityMap.put("weierp", new Character('\u2118')); // script capital P = power set = Weierstrass p, U+2118 ISOamso
- entityMap.put("image", new Character('\u2111')); // blackletter capital I = imaginary part, U+2111 ISOamso
- entityMap.put("real", new Character('\u211c')); // blackletter capital R = real part symbol, U+211C ISOamso
- entityMap.put("trade", new Character('\u2122')); // trade mark sign, U+2122 ISOnum
- entityMap.put("alefsym", new Character('\u2135')); // alef symbol = first transfinite cardinal, U+2135 NEW
- // alef symbol is NOT the same as hebrew letter alef,
- // U+05D0 although the same glyph could be used to depict both characters
- // Arrows
- entityMap.put("larr", new Character('\u2190')); // leftwards arrow, U+2190 ISOnum
- entityMap.put("uarr", new Character('\u2191')); // upwards arrow, U+2191 ISOnum
- entityMap.put("rarr", new Character('\u2192')); // rightwards arrow, U+2192 ISOnum
- entityMap.put("darr", new Character('\u2193')); // downwards arrow, U+2193 ISOnum
- entityMap.put("harr", new Character('\u2194')); // left right arrow, U+2194 ISOamsa
- entityMap.put("crarr", new Character('\u21b5')); // downwards arrow with corner leftwards = carriage return, U+21B5 NEW
- entityMap.put("lArr", new Character('\u21d0')); // leftwards double arrow, U+21D0 ISOtech
- // ISO 10646 does not say that lArr is the same as the 'is implied by' arrow
- // but also does not have any other character for that function. So ? lArr can
- // be used for 'is implied by' as ISOtech suggests
- entityMap.put("uArr", new Character('\u21d1')); // upwards double arrow, U+21D1 ISOamsa
- entityMap.put("rArr", new Character('\u21d2')); // rightwards double arrow, U+21D2 ISOtech
- // ISO 10646 does not say this is the 'implies' character but does not have
- // another character with this function so ?
- // rArr can be used for 'implies' as ISOtech suggests
- entityMap.put("dArr", new Character('\u21d3')); // downwards double arrow, U+21D3 ISOamsa
- entityMap.put("hArr", new Character('\u21d4')); // left right double arrow, U+21D4 ISOamsa
- // Mathematical Operators
- entityMap.put("forall", new Character('\u2200')); // for all, U+2200 ISOtech
- entityMap.put("part", new Character('\u2202')); // partial differential, U+2202 ISOtech
- entityMap.put("exist", new Character('\u2203')); // there exists, U+2203 ISOtech
- entityMap.put("empty", new Character('\u2205')); // empty set = null set = diameter, U+2205 ISOamso
- entityMap.put("nabla", new Character('\u2207')); // nabla = backward difference, U+2207 ISOtech
- entityMap.put("isin", new Character('\u2208')); // element of, U+2208 ISOtech
- entityMap.put("notin", new Character('\u2209')); // not an element of, U+2209 ISOtech
- entityMap.put("ni", new Character('\u220b')); // contains as member, U+220B ISOtech
- // should there be a more memorable name than 'ni'?
- entityMap.put("prod", new Character('\u220f')); // n-ary product = product sign, U+220F ISOamsb
- // prod is NOT the same character as U+03A0 'greek capital letter pi' though
- // the same glyph might be used for both
- entityMap.put("sum", new Character('\u2211')); // n-ary sumation, U+2211 ISOamsb
- // sum is NOT the same character as U+03A3 'greek capital letter sigma'
- // though the same glyph might be used for both
- entityMap.put("minus", new Character('\u2212')); // minus sign, U+2212 ISOtech
- entityMap.put("lowast", new Character('\u2217')); // asterisk operator, U+2217 ISOtech
- entityMap.put("radic", new Character('\u221a')); // square root = radical sign, U+221A ISOtech
- entityMap.put("prop", new Character('\u221d')); // proportional to, U+221D ISOtech
- entityMap.put("infin", new Character('\u221e')); // infinity, U+221E ISOtech
- entityMap.put("ang", new Character('\u2220')); // angle, U+2220 ISOamso
- entityMap.put("and", new Character('\u2227')); // logical and = wedge, U+2227 ISOtech
- entityMap.put("or", new Character('\u2228')); // logical or = vee, U+2228 ISOtech
- entityMap.put("cap", new Character('\u2229')); // intersection = cap, U+2229 ISOtech
- entityMap.put("cup", new Character('\u222a')); // union = cup, U+222A ISOtech
- entityMap.put("int", new Character('\u222b')); // integral, U+222B ISOtech
- entityMap.put("there4", new Character('\u2234')); // therefore, U+2234 ISOtech
- entityMap.put("sim", new Character('\u223c')); // tilde operator = varies with = similar to, U+223C ISOtech
- // tilde operator is NOT the same character as the tilde, U+007E,
- // although the same glyph might be used to represent both
- entityMap.put("cong", new Character('\u2245')); // approximately equal to, U+2245 ISOtech
- entityMap.put("asymp", new Character('\u2248')); // almost equal to = asymptotic to, U+2248 ISOamsr
- entityMap.put("ne", new Character('\u2260')); // not equal to, U+2260 ISOtech
- entityMap.put("equiv", new Character('\u2261')); // identical to, U+2261 ISOtech
- entityMap.put("le", new Character('\u2264')); // less-than or equal to, U+2264 ISOtech
- entityMap.put("ge", new Character('\u2265')); // greater-than or equal to, U+2265 ISOtech
- entityMap.put("sub", new Character('\u2282')); // subset of, U+2282 ISOtech
- entityMap.put("sup", new Character('\u2283')); // superset of, U+2283 ISOtech
- // note that nsup, 'not a superset of, U+2283' is not covered by the Symbol
- // font encoding and is not included. Should it be, for symmetry?
- // It is in ISOamsn
- entityMap.put("nsub", new Character('\u2284')); // not a subset of, U+2284 ISOamsn
- entityMap.put("sube", new Character('\u2286')); // subset of or equal to, U+2286 ISOtech
- entityMap.put("supe", new Character('\u2287')); // superset of or equal to, U+2287 ISOtech
- entityMap.put("oplus", new Character('\u2295')); // circled plus = direct sum, U+2295 ISOamsb
- entityMap.put("otimes", new Character('\u2297')); // circled times = vector product, U+2297 ISOamsb
- entityMap.put("perp", new Character('\u22a5')); // up tack = orthogonal to = perpendicular, U+22A5 ISOtech
- entityMap.put("sdot", new Character('\u22c5')); // dot operator, U+22C5 ISOamsb
- // dot operator is NOT the same character as U+00B7 middle dot
- // Miscellaneous Technical
- entityMap.put("lceil", new Character('\u2308')); // left ceiling = apl upstile, U+2308 ISOamsc
- entityMap.put("rceil", new Character('\u2309')); // right ceiling, U+2309 ISOamsc
- entityMap.put("lfloor", new Character('\u230a')); // left floor = apl downstile, U+230A ISOamsc
- entityMap.put("rfloor", new Character('\u230b')); // right floor, U+230B ISOamsc
- entityMap.put("lang", new Character('\u2329')); // left-pointing angle bracket = bra, U+2329 ISOtech
- // lang is NOT the same character as U+003C 'less than'
- // or U+2039 'single left-pointing angle quotation mark'
- entityMap.put("rang", new Character('\u232a')); // right-pointing angle bracket = ket, U+232A ISOtech
- // rang is NOT the same character as U+003E 'greater than'
- // or U+203A 'single right-pointing angle quotation mark'
- // Geometric Shapes
- entityMap.put("loz", new Character('\u25ca')); // lozenge, U+25CA ISOpub
- // Miscellaneous Symbols
- entityMap.put("spades", new Character('\u2660')); // black spade suit, U+2660 ISOpub
- // black here seems to mean filled as opposed to hollow
- entityMap.put("clubs", new Character('\u2663')); // black club suit = shamrock, U+2663 ISOpub
- entityMap.put("hearts", new Character('\u2665')); // black heart suit = valentine, U+2665 ISOpub
- entityMap.put("diams", new Character('\u2666')); // black diamond suit, U+2666 ISOpub
- // C0 Controls and Basic Latin
- entityMap.put("quot", new Character('\u0022')); // quotation mark = APL quote, U+0022 ISOnum
- entityMap.put("amp", new Character('\u0026')); // ampersand, U+0026 ISOnum
- entityMap.put("apos", new Character('\''));
- entityMap.put("lt", new Character('\u003c')); // less-than sign, U+003C ISOnum
- entityMap.put("gt", new Character('\u003e')); // greater-than sign, U+003E ISOnum
- // Latin Extended-A
- entityMap.put("OElig", new Character('\u0152')); // latin capital ligature OE, U+0152 ISOlat2
- entityMap.put("oelig", new Character('\u0153')); // latin small ligature oe, U+0153 ISOlat2
- // ligature is a misnomer, this is a separate character in some languages
- entityMap.put("Scaron", new Character('\u0160')); // latin capital letter S with caron, U+0160 ISOlat2
- entityMap.put("scaron", new Character('\u0161')); // latin small letter s with caron, U+0161 ISOlat2
- entityMap.put("Yuml", new Character('\u0178')); // latin capital letter Y with diaeresis, U+0178 ISOlat2
- // Spacing Modifier Letters
- entityMap.put("circ", new Character('\u02c6')); // modifier letter circumflex accent, U+02C6 ISOpub
- entityMap.put("tilde", new Character('\u02dc')); // small tilde, U+02DC ISOdia
- // General Punctuation
- entityMap.put("ensp", new Character('\u2002')); // en space, U+2002 ISOpub
- entityMap.put("emsp", new Character('\u2003')); // em space, U+2003 ISOpub
- entityMap.put("thinsp", new Character('\u2009')); // thin space, U+2009 ISOpub
- entityMap.put("zwnj", new Character('\u200c')); // zero width non-joiner, U+200C NEW RFC 2070
- entityMap.put("zwj", new Character('\u200d')); // zero width joiner, U+200D NEW RFC 2070
- entityMap.put("lrm", new Character('\u200e')); // left-to-right mark, U+200E NEW RFC 2070
- entityMap.put("rlm", new Character('\u200f')); // right-to-left mark, U+200F NEW RFC 2070
- entityMap.put("ndash", new Character('\u2013')); // en dash, U+2013 ISOpub
- entityMap.put("mdash", new Character('\u2014')); // em dash, U+2014 ISOpub
- entityMap.put("lsquo", new Character('\u2018')); // left single quotation mark, U+2018 ISOnum
- entityMap.put("rsquo", new Character('\u2019')); // right single quotation mark, U+2019 ISOnum
- entityMap.put("sbquo", new Character('\u201a')); // single low-9 quotation mark, U+201A NEW
- entityMap.put("ldquo", new Character('\u201c')); // left double quotation mark, U+201C ISOnum
- entityMap.put("rdquo", new Character('\u201d')); // right double quotation mark, U+201D ISOnum
- entityMap.put("bdquo", new Character('\u201e')); // double low-9 quotation mark, U+201E NEW
- entityMap.put("dagger", new Character('\u2020')); // dagger, U+2020 ISOpub
- entityMap.put("Dagger", new Character('\u2021')); // double dagger, U+2021 ISOpub
- entityMap.put("permil", new Character('\u2030')); // per mille sign, U+2030 ISOtech
- entityMap.put("lsaquo", new Character('\u2039')); // single left-pointing angle quotation mark, U+2039 ISO proposed
- // lsaquo is proposed but not yet ISO standardized
- entityMap.put("rsaquo", new Character('\u203a')); // single right-pointing angle quotation mark, U+203A ISO proposed
- // rsaquo is proposed but not yet ISO standardized
- entityMap.put("euro", new Character('\u20ac')); // euro sign, U+20AC NEW
-
-
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/SpotColor.java pdftk-2.01/java/com/lowagie/text/pdf/SpotColor.java
--- pdftk-1.45/java/com/lowagie/text/pdf/SpotColor.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/SpotColor.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,89 +0,0 @@
-/*
- * $Id: SpotColor.java,v 1.13 2002/07/09 11:28:24 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-/**
- *
- * @author psoares
- */
-public class SpotColor extends ExtendedColor {
-
- PdfSpotColor spot;
- float tint;
-
- public SpotColor(PdfSpotColor spot, float tint) {
- super(TYPE_SEPARATION,
- ((float)spot.getAlternativeCS().getRed() / 255f - 1f) * tint + 1,
- ((float)spot.getAlternativeCS().getGreen() / 255f - 1f) * tint + 1,
- ((float)spot.getAlternativeCS().getBlue() / 255f - 1f) * tint + 1);
- this.spot = spot;
- this.tint = tint;
- }
-
- public SpotColor(PdfSpotColor spot) {
- this(spot, spot.getTint());
- }
-
- public PdfSpotColor getPdfSpotColor() {
- return spot;
- }
-
- public float getTint() {
- return tint;
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/StampContent.java pdftk-2.01/java/com/lowagie/text/pdf/StampContent.java
--- pdftk-1.45/java/com/lowagie/text/pdf/StampContent.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/StampContent.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright 2003 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-public class StampContent extends PdfContentByte {
- PdfStamperImp.PageStamp ps;
- PageResources pageResources;
-
- /** Creates a new instance of StampContent */
- StampContent(PdfStamperImp stamper, PdfStamperImp.PageStamp ps) {
- super(stamper);
- this.ps = ps;
- pageResources = ps.pageResources;
- }
-
- public void setAction(PdfAction action, float llx, float lly, float urx, float ury) {
- ((PdfStamperImp)writer).addAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury, action), ps.pageN);
- }
-
- /**
- * Gets a duplicate of this PdfContentByte
. All
- * the members are copied by reference but the buffer stays different.
- *
- * @return a copy of this PdfContentByte
- */
- public PdfContentByte getDuplicate() {
- return new StampContent((PdfStamperImp)writer, ps);
- }
-
- PageResources getPageResources() {
- return pageResources;
- }
-
- void addAnnotation(PdfAnnotation annot) {
- ((PdfStamperImp)writer).addAnnotation(annot, ps.pageN);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/TIFFLZWDecoder.java pdftk-2.01/java/com/lowagie/text/pdf/TIFFLZWDecoder.java
--- pdftk-1.45/java/com/lowagie/text/pdf/TIFFLZWDecoder.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/TIFFLZWDecoder.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,261 +0,0 @@
-/*
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-*/
-
-// ssteward
-//package org.apache.batik.ext.awt.image.codec.tiff;
-package com.lowagie.text.pdf;
-
-// ssteward
-import java.io.OutputStream;
-import java.io.IOException;
-
-/**
- * A class for performing LZW decoding.
- *
- * @version $Id: TIFFLZWDecoder.java 498740 2007-01-22 18:35:57Z dvholten $
- */
-public class TIFFLZWDecoder {
-
- byte[][] stringTable;
- byte[] data = null;
- // ssteward
- // byte[] uncompData;
- OutputStream uncompData;
- int tableIndex, bitsToGet = 9;
- int bytePointer, bitPointer;
- int dstIndex;
- // int w, h;
- // int predictor, samplesPerPixel;
- int nextData = 0;
- int nextBits = 0;
-
- int[] andTable = {
- 511,
- 1023,
- 2047,
- 4095
- };
-
- // ssteward: dropped w, predictor, samplesPerPixel because we won't use them
- public TIFFLZWDecoder( /* int w, int predictor, int samplesPerPixel */ ) {
- // this.w = w;
- // this.predictor = predictor;
- // this.samplesPerPixel = samplesPerPixel;
- }
-
- /**
- * Method to decode LZW compressed data.
- *
- * @param data The compressed data.
- * @param uncompData Array to return the uncompressed data in.
- * @param h The number of rows the compressed data contains.
- */
- // ssteward: replaced byte[] with OutputStream for uncompData and return value
- // dropped input h
- public OutputStream decode(byte[] data, OutputStream uncompData /*, int h */ ) {
-
- if(data[0] == (byte)0x00 && data[1] == (byte)0x01) {
- throw new UnsupportedOperationException("TIFFLZWDecoder0");
- }
-
- initializeStringTable();
-
- this.data = data;
- // this.h = h;
- this.uncompData = uncompData;
-
- // Initialize pointers
- bytePointer = 0;
- bitPointer = 0;
- dstIndex = 0;
-
-
- nextData = 0;
- nextBits = 0;
-
- int code, oldCode = 0;
- byte[] string;
-
- while ( ((code = getNextCode()) != 257) /* && dstIndex != uncompData.length */ ) {
-
- if (code == 256) {
-
- initializeStringTable();
- code = getNextCode();
-
- if (code == 257) {
- break;
- }
-
- writeString(stringTable[code]);
- oldCode = code;
-
- } else {
-
- if (code < tableIndex) {
-
- string = stringTable[code];
-
- writeString(string);
- addStringToTable(stringTable[oldCode], string[0]);
- oldCode = code;
-
- } else {
-
- string = stringTable[oldCode];
- string = composeString(string, string[0]);
- writeString(string);
- addStringToTable(string);
- oldCode = code;
- }
-
- }
-
- }
-
- /* ssteward
- // Horizontal Differencing Predictor
- if (predictor == 2) {
-
- int count;
- for (int j = 0; j < h; j++) {
-
- count = samplesPerPixel * (j * w + 1);
-
- for (int i = samplesPerPixel; i < w * samplesPerPixel; i++) {
-
- uncompData[count] += uncompData[count - samplesPerPixel];
- count++;
- }
- }
- }
- */
-
- return uncompData;
- }
-
-
- /**
- * Initialize the string table.
- */
- public void initializeStringTable() {
-
- stringTable = new byte[4096][];
-
- for (int i=0; i<256; i++) {
- stringTable[i] = new byte[1];
- stringTable[i][0] = (byte)i;
- }
-
- tableIndex = 258;
- bitsToGet = 9;
- }
-
- /**
- * Write out the string just uncompressed.
- */
- public void writeString(byte[] string) {
- /* ssteward
- for (int i=0; inewString to the end of oldString
.
- */
- public byte[] composeString(byte[] oldString, byte newString) {
- int length = oldString.length;
- byte[] string = new byte[length + 1];
- System.arraycopy(oldString, 0, string, 0, length);
- string[length] = newString;
-
- return string;
- }
-
- // Returns the next 9, 10, 11 or 12 bits
- public int getNextCode() {
- // Attempt to get the next code. The exception is caught to make
- // this robust to cases wherein the EndOfInformation code has been
- // omitted from a strip. Examples of such cases have been observed
- // in practice.
- try {
- nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
- nextBits += 8;
-
- if (nextBits < bitsToGet) {
- nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
- nextBits += 8;
- }
-
- int code =
- (nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet-9];
- nextBits -= bitsToGet;
-
- return code;
- } catch(ArrayIndexOutOfBoundsException e) {
- // Strip not terminated as expected: return EndOfInformation code.
- return 257;
- }
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/TextField.java pdftk-2.01/java/com/lowagie/text/pdf/TextField.java
--- pdftk-1.45/java/com/lowagie/text/pdf/TextField.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/TextField.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,584 +0,0 @@
-/*
- * Copyright 2003-2005 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.awt.Color;
-import com.lowagie.text.Element;
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.Rectangle;
-import java.io.IOException;
-import java.util.ArrayList;
-
-/** Supports text, combo and list fields generating the correct appearances.
- * All the option in the Acrobat GUI are supported in an easy to use API.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class TextField extends BaseField {
-
- /** Holds value of property defaultText. */
- private String defaultText;
-
- /** Holds value of property choices. */
- private String[] choices;
-
- /** Holds value of property choiceExports. */
- private String[] choiceExports;
-
- /** Holds value of property choiceSelection. */
- private int choiceSelection;
-
- private int topFirst;
-
- private float extraMarginLeft;
- private float extraMarginTop;
-
- /** Creates a new TextField
.
- * @param writer the document PdfWriter
- * @param box the field location and dimensions
- * @param fieldName the field name. If null
only the widget keys
- * will be included in the field allowing it to be used as a kid field.
- */
- public TextField(PdfWriter writer, Rectangle box, String fieldName) {
- super(writer, box, fieldName);
- }
-
- /**
- * Gets the appearance for this TextField.
- * @return the appearance object for this TextField
- * @throws IOException
- * @throws DocumentException
- */
- public PdfAppearance getAppearance() throws IOException, DocumentException {
- PdfAppearance app = getBorderAppearance();
- app.beginVariableText();
- if (text == null || text.length() == 0) {
- app.endVariableText();
- return app;
- }
- BaseFont ufont = getRealFont();
- boolean borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET;
- float h = box.height() - borderWidth * 2;
- float bw2 = borderWidth;
- if (borderExtra) {
- h -= borderWidth * 2;
- bw2 *= 2;
- }
- h -= extraMarginTop;
- float offsetX = (borderExtra ? 2 * borderWidth : borderWidth);
- offsetX = Math.max(offsetX, 1);
- float offX = Math.min(bw2, offsetX);
- app.saveState();
- app.rectangle(offX, offX, box.width() - 2 * offX, box.height() - 2 * offX);
- app.clip();
- app.newPath();
- if (textColor == null)
- app.setGrayFill(0);
- else
- app.setColorFill(textColor);
- app.beginText();
- String ptext = text; //fixed by Kazuya Ujihara (ujihara.jp)
- if ((options & PASSWORD) != 0) {
- char[] pchar = new char[text.length()];
- for (int i = 0; i < text.length(); i++)
- pchar[i] = '*';
- ptext = new String(pchar);
- }
- if ((options & MULTILINE) != 0) {
- float usize = fontSize;
- float width = box.width() - 3 * offsetX - extraMarginLeft;
- ArrayList breaks = getHardBreaks(ptext);
- ArrayList lines = breaks;
- float factor = ufont.getFontDescriptor(BaseFont.BBOXURY, 1) - ufont.getFontDescriptor(BaseFont.BBOXLLY, 1);
- if (usize == 0) {
- usize = h / breaks.size() / factor;
- if (usize > 4) {
- if (usize > 12)
- usize = 12;
- float step = Math.max((usize - 4) / 10, 0.2f);
- for (; usize > 4; usize -= step) {
- lines = breakLines(breaks, ufont, usize, width);
- if (lines.size() * usize * factor <= h)
- break;
- }
- }
- if (usize <= 4) {
- usize = 4;
- lines = breakLines(breaks, ufont, usize, width);
- }
- }
- else
- lines = breakLines(breaks, ufont, usize, width);
- app.setFontAndSize(ufont, usize);
- app.setLeading(usize * factor);
- float offsetY = offsetX + h - ufont.getFontDescriptor(BaseFont.BBOXURY, usize);
- String nt = (String)lines.get(0);
- if (alignment == Element.ALIGN_RIGHT) {
- float wd = ufont.getWidthPoint(nt, usize);
- app.moveText(extraMarginLeft + box.width() - 2 * offsetX - wd, offsetY);
- }
- else if (alignment == Element.ALIGN_CENTER) {
- nt = nt.trim();
- float wd = ufont.getWidthPoint(nt, usize);
- app.moveText(extraMarginLeft + box.width() / 2 - wd / 2, offsetY);
- }
- else
- app.moveText(extraMarginLeft + 2 * offsetX, offsetY);
- app.showText(nt);
- int maxline = (int)(h / usize / factor) + 1;
- maxline = Math.min(maxline, lines.size());
- for (int k = 1; k < maxline; ++k) {
- nt = (String)lines.get(k);
- if (alignment == Element.ALIGN_RIGHT) {
- float wd = ufont.getWidthPoint(nt, usize);
- app.moveText(extraMarginLeft + box.width() - 2 * offsetX - wd - app.getXTLM(), 0);
- }
- else if (alignment == Element.ALIGN_CENTER) {
- nt = nt.trim();
- float wd = ufont.getWidthPoint(nt, usize);
- app.moveText(extraMarginLeft + box.width() / 2 - wd / 2 - app.getXTLM(), 0);
- }
- app.newlineShowText(nt);
- }
- }
- else {
- float usize = fontSize;
- if (usize == 0) {
- float maxCalculatedSize = h / (ufont.getFontDescriptor(BaseFont.BBOXURX, 1) - ufont.getFontDescriptor(BaseFont.BBOXLLY, 1));
- float wd = ufont.getWidthPoint(ptext, 1);
- if (wd == 0)
- usize = maxCalculatedSize;
- else
- usize = (box.width() - extraMarginLeft - 2 * offsetX) / wd;
- if (usize > maxCalculatedSize)
- usize = maxCalculatedSize;
- if (usize < 4)
- usize = 4;
- }
- app.setFontAndSize(ufont, usize);
- float offsetY = offX + ((box.height() - 2*offX) - ufont.getFontDescriptor(BaseFont.ASCENT, usize)) / 2;
- if (offsetY < offX)
- offsetY = offX;
- if (offsetY - offX < -ufont.getFontDescriptor(BaseFont.DESCENT, usize)) {
- float ny = -ufont.getFontDescriptor(BaseFont.DESCENT, usize) + offX;
- float dy = box.height() - offX - ufont.getFontDescriptor(BaseFont.ASCENT, usize);
- offsetY = Math.min(ny, Math.max(offsetY, dy));
- }
- if ((options & COMB) != 0 && maxCharacterLength > 0) {
- int textLen = Math.min(maxCharacterLength, ptext.length());
- int position = 0;
- if (alignment == Element.ALIGN_RIGHT) {
- position = maxCharacterLength - textLen;
- }
- else if (alignment == Element.ALIGN_CENTER) {
- position = (maxCharacterLength - textLen) / 2;
- }
- float step = (box.width() - extraMarginLeft) / maxCharacterLength;
- float start = step / 2 + position * step;
- for (int k = 0; k < textLen; ++k) {
- String c = ptext.substring(k, k + 1);
- float wd = ufont.getWidthPoint(c, usize);
- app.setTextMatrix(extraMarginLeft + start - wd / 2, offsetY - extraMarginTop);
- app.showText(c);
- start += step;
- }
- }
- else {
- if (alignment == Element.ALIGN_RIGHT) {
- float wd = ufont.getWidthPoint(ptext, usize);
- app.moveText(extraMarginLeft + box.width() - 2 * offsetX - wd, offsetY - extraMarginTop);
- }
- else if (alignment == Element.ALIGN_CENTER) {
- float wd = ufont.getWidthPoint(ptext, usize);
- app.moveText(extraMarginLeft + box.width() / 2 - wd / 2, offsetY - extraMarginTop);
- }
- else
- app.moveText(extraMarginLeft + 2 * offsetX, offsetY - extraMarginTop);
- app.showText(ptext);
- }
- }
- app.endText();
- app.restoreState();
- app.endVariableText();
- return app;
- }
-
- PdfAppearance getListAppearance() throws IOException, DocumentException {
- PdfAppearance app = getBorderAppearance();
- app.beginVariableText();
- if (choices == null || choices.length == 0) {
- app.endVariableText();
- return app;
- }
- int topChoice = choiceSelection;
- if (topChoice >= choices.length) {
- topChoice = choices.length - 1;
- }
- if (topChoice < 0)
- topChoice = 0;
- BaseFont ufont = getRealFont();
- float usize = fontSize;
- if (usize == 0)
- usize = 12;
- boolean borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET;
- float h = box.height() - borderWidth * 2;
- if (borderExtra)
- h -= borderWidth * 2;
- float offsetX = (borderExtra ? 2 * borderWidth : borderWidth);
- float leading = ufont.getFontDescriptor(BaseFont.BBOXURY, usize) - ufont.getFontDescriptor(BaseFont.BBOXLLY, usize);
- int maxFit = (int)(h / leading) + 1;
- int first = 0;
- int last = 0;
- last = topChoice + maxFit / 2 + 1;
- first = last - maxFit;
- if (first < 0) {
- last += first;
- first = 0;
- }
-// first = topChoice;
- last = first + maxFit;
- if (last > choices.length)
- last = choices.length;
- topFirst = first;
- app.saveState();
- app.rectangle(offsetX, offsetX, box.width() - 2 * offsetX, box.height() - 2 * offsetX);
- app.clip();
- app.newPath();
- Color mColor;
- if (textColor == null)
- mColor = new GrayColor(0);
- else
- mColor = textColor;
- app.setColorFill(new Color(10, 36, 106));
- app.rectangle(offsetX, offsetX + h - (topChoice - first + 1) * leading, box.width() - 2 * offsetX, leading);
- app.fill();
- app.beginText();
- app.setFontAndSize(ufont, usize);
- app.setLeading(leading);
- app.moveText(offsetX * 2, offsetX + h - ufont.getFontDescriptor(BaseFont.BBOXURY, usize) + leading);
- app.setColorFill(mColor);
- for (int idx = first; idx < last; ++idx) {
- if (idx == topChoice) {
- app.setGrayFill(1);
- app.newlineShowText(choices[idx]);
- app.setColorFill(mColor);
- }
- else
- app.newlineShowText(choices[idx]);
- }
- app.endText();
- app.restoreState();
- app.endVariableText();
- return app;
- }
-
- /** Gets a new text field.
- * @throws IOException on error
- * @throws DocumentException on error
- * @return a new text field
- */
- public PdfFormField getTextField() throws IOException, DocumentException {
- if (maxCharacterLength <= 0)
- options &= ~COMB;
- if ((options & COMB) != 0)
- options &= ~MULTILINE;
- PdfFormField field = PdfFormField.createTextField(writer, false, false, maxCharacterLength);
- field.setWidget(box, PdfAnnotation.HIGHLIGHT_INVERT);
- switch (alignment) {
- case Element.ALIGN_CENTER:
- field.setQuadding(PdfFormField.Q_CENTER);
- break;
- case Element.ALIGN_RIGHT:
- field.setQuadding(PdfFormField.Q_RIGHT);
- break;
- }
- if (rotation != 0)
- field.setMKRotation(rotation);
- if (fieldName != null) {
- field.setFieldName(fieldName);
- field.setValueAsString(text);
- if (defaultText != null)
- field.setDefaultValueAsString(defaultText);
- if ((options & READ_ONLY) != 0)
- field.setFieldFlags(PdfFormField.FF_READ_ONLY);
- if ((options & REQUIRED) != 0)
- field.setFieldFlags(PdfFormField.FF_REQUIRED);
- if ((options & MULTILINE) != 0)
- field.setFieldFlags(PdfFormField.FF_MULTILINE);
- if ((options & DO_NOT_SCROLL) != 0)
- field.setFieldFlags(PdfFormField.FF_DONOTSCROLL);
- if ((options & PASSWORD) != 0)
- field.setFieldFlags(PdfFormField.FF_PASSWORD);
- if ((options & FILE_SELECTION) != 0)
- field.setFieldFlags(PdfFormField.FF_FILESELECT);
- if ((options & DO_NOT_SPELL_CHECK) != 0)
- field.setFieldFlags(PdfFormField.FF_DONOTSPELLCHECK);
- if ((options & COMB) != 0)
- field.setFieldFlags(PdfFormField.FF_COMB);
- }
- field.setBorderStyle(new PdfBorderDictionary(borderWidth, borderStyle, new PdfDashPattern(3)));
- PdfAppearance tp = getAppearance();
- field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
- PdfAppearance da = (PdfAppearance)tp.getDuplicate();
- da.setFontAndSize(getRealFont(), fontSize);
- if (textColor == null)
- da.setGrayFill(0);
- else
- da.setColorFill(textColor);
- field.setDefaultAppearanceString(da);
- if (borderColor != null)
- field.setMKBorderColor(borderColor);
- if (backgroundColor != null)
- field.setMKBackgroundColor(backgroundColor);
- switch (visibility) {
- case HIDDEN:
- field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_HIDDEN);
- break;
- case VISIBLE_BUT_DOES_NOT_PRINT:
- break;
- case HIDDEN_BUT_PRINTABLE:
- field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_NOVIEW);
- break;
- default:
- field.setFlags(PdfAnnotation.FLAGS_PRINT);
- break;
- }
- return field;
- }
-
- /** Gets a new combo field.
- * @throws IOException on error
- * @throws DocumentException on error
- * @return a new combo field
- */
- public PdfFormField getComboField() throws IOException, DocumentException {
- return getChoiceField(false);
- }
-
- /** Gets a new list field.
- * @throws IOException on error
- * @throws DocumentException on error
- * @return a new list field
- */
- public PdfFormField getListField() throws IOException, DocumentException {
- return getChoiceField(true);
- }
-
- protected PdfFormField getChoiceField(boolean isList) throws IOException, DocumentException {
- options &= (~MULTILINE) & (~COMB);
- String uchoices[] = choices;
- if (uchoices == null)
- uchoices = new String[0];
- int topChoice = choiceSelection;
- if (topChoice >= uchoices.length)
- topChoice = uchoices.length - 1;
- if (text == null) text = ""; //fixed by Kazuya Ujihara (ujihara.jp)
- if (topChoice >= 0)
- text = uchoices[topChoice];
- if (topChoice < 0)
- topChoice = 0;
- PdfFormField field = null;
- String mix[][] = null;
- if (choiceExports == null) {
- if (isList)
- field = PdfFormField.createList(writer, uchoices, topChoice);
- else
- field = PdfFormField.createCombo(writer, (options & EDIT) != 0, uchoices, topChoice);
- }
- else {
- mix = new String[uchoices.length][2];
- for (int k = 0; k < mix.length; ++k)
- mix[k][0] = mix[k][1] = uchoices[k];
- int top = Math.min(uchoices.length, choiceExports.length);
- for (int k = 0; k < top; ++k) {
- if (choiceExports[k] != null)
- mix[k][0] = choiceExports[k];
- }
- if (isList)
- field = PdfFormField.createList(writer, mix, topChoice);
- else
- field = PdfFormField.createCombo(writer, (options & EDIT) != 0, mix, topChoice);
- }
- field.setWidget(box, PdfAnnotation.HIGHLIGHT_INVERT);
- if (rotation != 0)
- field.setMKRotation(rotation);
- if (fieldName != null) {
- field.setFieldName(fieldName);
- if (uchoices.length > 0) {
- if (mix != null) {
- field.setValueAsString(mix[topChoice][0]);
- field.setDefaultValueAsString(mix[topChoice][0]);
- }
- else {
- field.setValueAsString(text);
- field.setDefaultValueAsString(text);
- }
- }
- if ((options & READ_ONLY) != 0)
- field.setFieldFlags(PdfFormField.FF_READ_ONLY);
- if ((options & REQUIRED) != 0)
- field.setFieldFlags(PdfFormField.FF_REQUIRED);
- if ((options & DO_NOT_SPELL_CHECK) != 0)
- field.setFieldFlags(PdfFormField.FF_DONOTSPELLCHECK);
- }
- field.setBorderStyle(new PdfBorderDictionary(borderWidth, borderStyle, new PdfDashPattern(3)));
- PdfAppearance tp;
- if (isList) {
- tp = getListAppearance();
- if (topFirst > 0)
- field.put(PdfName.TI, new PdfNumber(topFirst));
- }
- else
- tp = getAppearance();
- field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
- PdfAppearance da = (PdfAppearance)tp.getDuplicate();
- da.setFontAndSize(getRealFont(), fontSize);
- if (textColor == null)
- da.setGrayFill(0);
- else
- da.setColorFill(textColor);
- field.setDefaultAppearanceString(da);
- if (borderColor != null)
- field.setMKBorderColor(borderColor);
- if (backgroundColor != null)
- field.setMKBackgroundColor(backgroundColor);
- switch (visibility) {
- case HIDDEN:
- field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_HIDDEN);
- break;
- case VISIBLE_BUT_DOES_NOT_PRINT:
- break;
- case HIDDEN_BUT_PRINTABLE:
- field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_NOVIEW);
- break;
- default:
- field.setFlags(PdfAnnotation.FLAGS_PRINT);
- break;
- }
- return field;
- }
-
- /** Gets the default text.
- * @return the default text
- */
- public String getDefaultText() {
- return this.defaultText;
- }
-
- /** Sets the default text. It is only meaningful for text fields.
- * @param defaultText the default text
- */
- public void setDefaultText(String defaultText) {
- this.defaultText = defaultText;
- }
-
- /** Gets the choices to be presented to the user in list/combo
- * fields.
- * @return the choices to be presented to the user
- */
- public String[] getChoices() {
- return this.choices;
- }
-
- /** Sets the choices to be presented to the user in list/combo
- * fields.
- * @param choices the choices to be presented to the user
- */
- public void setChoices(String[] choices) {
- this.choices = choices;
- }
-
- /** Gets the export values in list/combo fields.
- * @return the export values in list/combo fields
- */
- public String[] getChoiceExports() {
- return this.choiceExports;
- }
-
- /** Sets the export values in list/combo fields. If this array
- * is null
then the choice values will also be used
- * as the export values.
- * @param choiceExports the export values in list/combo fields
- */
- public void setChoiceExports(String[] choiceExports) {
- this.choiceExports = choiceExports;
- }
-
- /** Gets the zero based index of the selected item.
- * @return the zero based index of the selected item
- */
- public int getChoiceSelection() {
- return this.choiceSelection;
- }
-
- /** Sets the zero based index of the selected item.
- * @param choiceSelection the zero based index of the selected item
- */
- public void setChoiceSelection(int choiceSelection) {
- this.choiceSelection = choiceSelection;
- }
-
- int getTopFirst() {
- return topFirst;
- }
-
- /**
- * Sets extra margins in text fields to better mimic the Acrobat layout.
- * @param extraMarginLeft the extra marging left
- * @param extraMarginTop the extra margin top
- */
- public void setExtraMargin(float extraMarginLeft, float extraMarginTop) {
- this.extraMarginLeft = extraMarginLeft;
- this.extraMarginTop = extraMarginTop;
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/TrueTypeFont.java pdftk-2.01/java/com/lowagie/text/pdf/TrueTypeFont.java
--- pdftk-1.45/java/com/lowagie/text/pdf/TrueTypeFont.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/TrueTypeFont.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,1306 +0,0 @@
-/*
- * $Id: TrueTypeFont.java,v 1.55 2004/12/14 15:15:59 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.*;
-import java.util.HashMap;
-import java.util.ArrayList;
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.ExceptionConverter;
-/** Reads a Truetype font
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-class TrueTypeFont extends BaseFont {
-
- /** The code pages possible for a True Type font.
- */
- static final String codePages[] = {
- "1252 Latin 1",
- "1250 Latin 2: Eastern Europe",
- "1251 Cyrillic",
- "1253 Greek",
- "1254 Turkish",
- "1255 Hebrew",
- "1256 Arabic",
- "1257 Windows Baltic",
- "1258 Vietnamese",
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- "874 Thai",
- "932 JIS/Japan",
- "936 Chinese: Simplified chars--PRC and Singapore",
- "949 Korean Wansung",
- "950 Chinese: Traditional chars--Taiwan and Hong Kong",
- "1361 Korean Johab",
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- "Macintosh Character Set (US Roman)",
- "OEM Character Set",
- "Symbol Character Set",
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- null,
- "869 IBM Greek",
- "866 MS-DOS Russian",
- "865 MS-DOS Nordic",
- "864 Arabic",
- "863 MS-DOS Canadian French",
- "862 Hebrew",
- "861 MS-DOS Icelandic",
- "860 MS-DOS Portuguese",
- "857 IBM Turkish",
- "855 IBM Cyrillic; primarily Russian",
- "852 Latin 2",
- "775 MS-DOS Baltic",
- "737 Greek; former 437 G",
- "708 Arabic; ASMO 708",
- "850 WE/Latin 1",
- "437 US"};
-
- protected boolean justNames = false;
- /** Contains the location of the several tables. The key is the name of
- * the table and the value is an int[2]
where position 0
- * is the offset from the start of the file and position 1 is the length
- * of the table.
- */
- protected HashMap tables;
- /** The file in use.
- */
- protected RandomAccessFileOrArray rf;
- /** The file name.
- */
- protected String fileName;
-
- protected boolean cff = false;
-
- protected int cffOffset;
-
- protected int cffLength;
-
- /** The offset from the start of the file to the table directory.
- * It is 0 for TTF and may vary for TTC depending on the chosen font.
- */
- protected int directoryOffset;
- /** The index for the TTC font. It is an empty String
for a
- * TTF file.
- */
- protected String ttcIndex;
- /** The style modifier */
- protected String style = "";
- /** The content of table 'head'.
- */
- protected FontHeader head = new FontHeader();
- /** The content of table 'hhea'.
- */
- protected HorizontalHeader hhea = new HorizontalHeader();
- /** The content of table 'OS/2'.
- */
- protected WindowsMetrics os_2 = new WindowsMetrics();
- /** The width of the glyphs. This is essentially the content of table
- * 'hmtx' normalized to 1000 units.
- */
- protected int GlyphWidths[];
-
- protected int bboxes[][];
- /** The map containing the code information for the table 'cmap', encoding 1.0.
- * The key is the code and the value is an int[2]
where position 0
- * is the glyph number and position 1 is the glyph width normalized to 1000
- * units.
- */
- protected HashMap cmap10;
- /** The map containing the code information for the table 'cmap', encoding 3.1
- * in Unicode.
- *
- * The key is the code and the value is an int
[2] where position 0
- * is the glyph number and position 1 is the glyph width normalized to 1000
- * units.
- */
- protected HashMap cmap31;
- /** The map containing the kerning information. It represents the content of
- * table 'kern'. The key is an Integer
where the top 16 bits
- * are the glyph number for the first character and the lower 16 bits are the
- * glyph number for the second character. The value is the amount of kerning in
- * normalized 1000 units as an Integer
. This value is usually negative.
- */
- protected IntHashtable kerning = new IntHashtable();
- /**
- * The font name.
- * This name is usually extracted from the table 'name' with
- * the 'Name ID' 6.
- */
- protected String fontName;
-
- /** The full name of the font
- */
- protected String fullName[][];
-
- /** The family name of the font
- */
- protected String familyName[][];
- /** The italic angle. It is usually extracted from the 'post' table or in it's
- * absence with the code:
- *
- *
- * -Math.atan2(hhea.caretSlopeRun, hhea.caretSlopeRise) * 180 / Math.PI
- *
- */
- protected double italicAngle;
- /** true
if all the glyphs have the same width.
- */
- protected boolean isFixedPitch = false;
-
- /** The components of table 'head'.
- */
- protected static class FontHeader {
- /** A variable. */
- int flags;
- /** A variable. */
- int unitsPerEm;
- /** A variable. */
- short xMin;
- /** A variable. */
- short yMin;
- /** A variable. */
- short xMax;
- /** A variable. */
- short yMax;
- /** A variable. */
- int macStyle;
- }
-
- /** The components of table 'hhea'.
- */
- protected static class HorizontalHeader {
- /** A variable. */
- short Ascender;
- /** A variable. */
- short Descender;
- /** A variable. */
- short LineGap;
- /** A variable. */
- int advanceWidthMax;
- /** A variable. */
- short minLeftSideBearing;
- /** A variable. */
- short minRightSideBearing;
- /** A variable. */
- short xMaxExtent;
- /** A variable. */
- short caretSlopeRise;
- /** A variable. */
- short caretSlopeRun;
- /** A variable. */
- int numberOfHMetrics;
- }
-
- /** The components of table 'OS/2'.
- */
- protected static class WindowsMetrics {
- /** A variable. */
- short xAvgCharWidth;
- /** A variable. */
- int usWeightClass;
- /** A variable. */
- int usWidthClass;
- /** A variable. */
- short fsType;
- /** A variable. */
- short ySubscriptXSize;
- /** A variable. */
- short ySubscriptYSize;
- /** A variable. */
- short ySubscriptXOffset;
- /** A variable. */
- short ySubscriptYOffset;
- /** A variable. */
- short ySuperscriptXSize;
- /** A variable. */
- short ySuperscriptYSize;
- /** A variable. */
- short ySuperscriptXOffset;
- /** A variable. */
- short ySuperscriptYOffset;
- /** A variable. */
- short yStrikeoutSize;
- /** A variable. */
- short yStrikeoutPosition;
- /** A variable. */
- short sFamilyClass;
- /** A variable. */
- byte panose[] = new byte[10];
- /** A variable. */
- byte achVendID[] = new byte[4];
- /** A variable. */
- int fsSelection;
- /** A variable. */
- int usFirstCharIndex;
- /** A variable. */
- int usLastCharIndex;
- /** A variable. */
- short sTypoAscender;
- /** A variable. */
- short sTypoDescender;
- /** A variable. */
- short sTypoLineGap;
- /** A variable. */
- int usWinAscent;
- /** A variable. */
- int usWinDescent;
- /** A variable. */
- int ulCodePageRange1;
- /** A variable. */
- int ulCodePageRange2;
- /** A variable. */
- int sCapHeight;
- }
-
- /** This constructor is present to allow extending the class.
- */
- protected TrueTypeFont() {
- }
-
- TrueTypeFont(String ttFile, String enc, boolean emb, byte ttfAfm[]) throws DocumentException, IOException {
- this(ttFile, enc, emb, ttfAfm, false);
- }
-
- /** Creates a new TrueType font.
- * @param ttFile the location of the font on file. The file must end in '.ttf' or
- * '.ttc' but can have modifiers after the name
- * @param enc the encoding to be applied to this font
- * @param emb true if the font is to be embedded in the PDF
- * @param ttfAfm the font as a byte
array
- * @throws DocumentException the font is invalid
- * @throws IOException the font file could not be read
- */
- TrueTypeFont(String ttFile, String enc, boolean emb, byte ttfAfm[], boolean justNames) throws DocumentException, IOException {
- this.justNames = justNames;
- String nameBase = getBaseName(ttFile);
- String ttcName = getTTCName(nameBase);
- if (nameBase.length() < ttFile.length()) {
- style = ttFile.substring(nameBase.length());
- }
- encoding = enc;
- embedded = emb;
- fileName = ttcName;
- fontType = FONT_TYPE_TT;
- ttcIndex = "";
- if (ttcName.length() < nameBase.length())
- ttcIndex = nameBase.substring(ttcName.length() + 1);
- if (fileName.toLowerCase().endsWith(".ttf") || fileName.toLowerCase().endsWith(".otf") || fileName.toLowerCase().endsWith(".ttc")) {
- process(ttfAfm);
- if (!justNames && embedded && os_2.fsType == 2)
- throw new DocumentException(fileName + style + " cannot be embedded due to licensing restrictions.");
- }
- else
- throw new DocumentException(fileName + style + " is not a TTF, OTF or TTC font file.");
- PdfEncodings.convertToBytes(" ", enc); // check if the encoding exists
- createEncoding();
- }
-
- /** Gets the name from a composed TTC file name.
- * If I have for input "myfont.ttc,2" the return will
- * be "myfont.ttc".
- * @param name the full name
- * @return the simple file name
- */
- protected static String getTTCName(String name) {
- int idx = name.toLowerCase().indexOf(".ttc,");
- if (idx < 0)
- return name;
- else
- return name.substring(0, idx + 4);
- }
-
-
- /**
- * Reads the tables 'head', 'hhea', 'OS/2' and 'post' filling several variables.
- * @throws DocumentException the font is invalid
- * @throws IOException the font file could not be read
- */
- void fillTables() throws DocumentException, IOException {
- int table_location[];
- table_location = (int[])tables.get("head");
- if (table_location == null)
- throw new DocumentException("Table 'head' does not exist in " + fileName + style);
- rf.seek(table_location[0] + 16);
- head.flags = rf.readUnsignedShort();
- head.unitsPerEm = rf.readUnsignedShort();
- rf.skipBytes(16);
- head.xMin = rf.readShort();
- head.yMin = rf.readShort();
- head.xMax = rf.readShort();
- head.yMax = rf.readShort();
- head.macStyle = rf.readUnsignedShort();
-
- table_location = (int[])tables.get("hhea");
- if (table_location == null)
- throw new DocumentException("Table 'hhea' does not exist " + fileName + style);
- rf.seek(table_location[0] + 4);
- hhea.Ascender = rf.readShort();
- hhea.Descender = rf.readShort();
- hhea.LineGap = rf.readShort();
- hhea.advanceWidthMax = rf.readUnsignedShort();
- hhea.minLeftSideBearing = rf.readShort();
- hhea.minRightSideBearing = rf.readShort();
- hhea.xMaxExtent = rf.readShort();
- hhea.caretSlopeRise = rf.readShort();
- hhea.caretSlopeRun = rf.readShort();
- rf.skipBytes(12);
- hhea.numberOfHMetrics = rf.readUnsignedShort();
-
- table_location = (int[])tables.get("OS/2");
- if (table_location == null)
- throw new DocumentException("Table 'OS/2' does not exist in " + fileName + style);
- rf.seek(table_location[0]);
- int version = rf.readUnsignedShort();
- os_2.xAvgCharWidth = rf.readShort();
- os_2.usWeightClass = rf.readUnsignedShort();
- os_2.usWidthClass = rf.readUnsignedShort();
- os_2.fsType = rf.readShort();
- os_2.ySubscriptXSize = rf.readShort();
- os_2.ySubscriptYSize = rf.readShort();
- os_2.ySubscriptXOffset = rf.readShort();
- os_2.ySubscriptYOffset = rf.readShort();
- os_2.ySuperscriptXSize = rf.readShort();
- os_2.ySuperscriptYSize = rf.readShort();
- os_2.ySuperscriptXOffset = rf.readShort();
- os_2.ySuperscriptYOffset = rf.readShort();
- os_2.yStrikeoutSize = rf.readShort();
- os_2.yStrikeoutPosition = rf.readShort();
- os_2.sFamilyClass = rf.readShort();
- rf.readFully(os_2.panose);
- rf.skipBytes(16);
- rf.readFully(os_2.achVendID);
- os_2.fsSelection = rf.readUnsignedShort();
- os_2.usFirstCharIndex = rf.readUnsignedShort();
- os_2.usLastCharIndex = rf.readUnsignedShort();
- os_2.sTypoAscender = rf.readShort();
- os_2.sTypoDescender = rf.readShort();
- if (os_2.sTypoDescender > 0)
- os_2.sTypoDescender = (short)(-os_2.sTypoDescender);
- os_2.sTypoLineGap = rf.readShort();
- os_2.usWinAscent = rf.readUnsignedShort();
- os_2.usWinDescent = rf.readUnsignedShort();
- os_2.ulCodePageRange1 = 0;
- os_2.ulCodePageRange2 = 0;
- if (version > 0) {
- os_2.ulCodePageRange1 = rf.readInt();
- os_2.ulCodePageRange2 = rf.readInt();
- }
- if (version > 1) {
- rf.skipBytes(2);
- os_2.sCapHeight = rf.readShort();
- }
- else
- os_2.sCapHeight = (int)(0.7 * head.unitsPerEm);
-
- table_location = (int[])tables.get("post");
- if (table_location == null) {
- italicAngle = -Math.atan2(hhea.caretSlopeRun, hhea.caretSlopeRise) * 180 / Math.PI;
- return;
- }
- rf.seek(table_location[0] + 4);
- short mantissa = rf.readShort();
- int fraction = rf.readUnsignedShort();
- italicAngle = (double)mantissa + (double)fraction / 16384.0;
- rf.skipBytes(4);
- isFixedPitch = rf.readInt() != 0;
- }
-
- /**
- * Gets the Postscript font name.
- * @throws DocumentException the font is invalid
- * @throws IOException the font file could not be read
- * @return the Postscript font name
- */
- String getBaseFont() throws DocumentException, IOException {
- int table_location[];
- table_location = (int[])tables.get("name");
- if (table_location == null)
- throw new DocumentException("Table 'name' does not exist in " + fileName + style);
- rf.seek(table_location[0] + 2);
- int numRecords = rf.readUnsignedShort();
- int startOfStorage = rf.readUnsignedShort();
- for (int k = 0; k < numRecords; ++k) {
- int platformID = rf.readUnsignedShort();
- int platformEncodingID = rf.readUnsignedShort();
- int languageID = rf.readUnsignedShort();
- int nameID = rf.readUnsignedShort();
- int length = rf.readUnsignedShort();
- int offset = rf.readUnsignedShort();
- if (nameID == 6) {
- rf.seek(table_location[0] + startOfStorage + offset);
- if (platformID == 0 || platformID == 3)
- return readUnicodeString(length);
- else
- return readStandardString(length);
- }
- }
- File file = new File(fileName);
- return file.getName().replace(' ', '-');
- }
-
- /** Extracts the names of the font in all the languages available.
- * @param id the name id to retrieve
- * @throws DocumentException on error
- * @throws IOException on error
- */
- String[][] getNames(int id) throws DocumentException, IOException {
- int table_location[];
- table_location = (int[])tables.get("name");
- if (table_location == null)
- throw new DocumentException("Table 'name' does not exist in " + fileName + style);
- rf.seek(table_location[0] + 2);
- int numRecords = rf.readUnsignedShort();
- int startOfStorage = rf.readUnsignedShort();
- ArrayList names = new ArrayList();
- for (int k = 0; k < numRecords; ++k) {
- int platformID = rf.readUnsignedShort();
- int platformEncodingID = rf.readUnsignedShort();
- int languageID = rf.readUnsignedShort();
- int nameID = rf.readUnsignedShort();
- int length = rf.readUnsignedShort();
- int offset = rf.readUnsignedShort();
- if (nameID == id) {
- int pos = rf.getFilePointer();
- rf.seek(table_location[0] + startOfStorage + offset);
- String name;
- if (platformID == 0 || platformID == 3 || (platformID == 2 && platformEncodingID == 1)){
- name = readUnicodeString(length);
- }
- else {
- name = readStandardString(length);
- }
- names.add(new String[]{String.valueOf(platformID),
- String.valueOf(platformEncodingID), String.valueOf(languageID), name});
- rf.seek(pos);
- }
- }
- String thisName[][] = new String[names.size()][];
- for (int k = 0; k < names.size(); ++k)
- thisName[k] = (String[])names.get(k);
- return thisName;
- }
-
- void checkCff() throws DocumentException, IOException {
- int table_location[];
- table_location = (int[])tables.get("CFF ");
- if (table_location != null) {
- cff = true;
- cffOffset = table_location[0];
- cffLength = table_location[1];
- }
- }
-
- /** Reads the font data.
- * @param ttfAfm the font as a byte
array, possibly null
- * @throws DocumentException the font is invalid
- * @throws IOException the font file could not be read
- */
- void process(byte ttfAfm[]) throws DocumentException, IOException {
- tables = new HashMap();
-
- try {
- if (ttfAfm == null)
- rf = new RandomAccessFileOrArray(fileName);
- else
- rf = new RandomAccessFileOrArray(ttfAfm);
- if (ttcIndex.length() > 0) {
- int dirIdx = Integer.parseInt(ttcIndex);
- if (dirIdx < 0)
- throw new DocumentException("The font index for " + fileName + " must be positive.");
- String mainTag = readStandardString(4);
- if (!mainTag.equals("ttcf"))
- throw new DocumentException(fileName + " is not a valid TTC file.");
- rf.skipBytes(4);
- int dirCount = rf.readInt();
- if (dirIdx >= dirCount)
- throw new DocumentException("The font index for " + fileName + " must be between 0 and " + (dirCount - 1) + ". It was " + dirIdx + ".");
- rf.skipBytes(dirIdx * 4);
- directoryOffset = rf.readInt();
- }
- rf.seek(directoryOffset);
- int ttId = rf.readInt();
- if (ttId != 0x00010000 && ttId != 0x4F54544F)
- throw new DocumentException(fileName + " is not a valid TTF or OTF file.");
- int num_tables = rf.readUnsignedShort();
- rf.skipBytes(6);
- for (int k = 0; k < num_tables; ++k) {
- String tag = readStandardString(4);
- rf.skipBytes(4);
- int table_location[] = new int[2];
- table_location[0] = rf.readInt();
- table_location[1] = rf.readInt();
- tables.put(tag, table_location);
- }
- checkCff();
- fontName = getBaseFont();
- fullName = getNames(4); //full name
- familyName = getNames(1); //family name
- if (!justNames) {
- fillTables();
- readGlyphWidths();
- readCMaps();
- readKerning();
- readBbox();
- GlyphWidths = null;
- }
- }
- finally {
- if (rf != null) {
- rf.close();
- if (!embedded)
- rf = null;
- }
- }
- }
-
- /** Reads a String
from the font file as bytes using the Cp1252
- * encoding.
- * @param length the length of bytes to read
- * @return the String
read
- * @throws IOException the font file could not be read
- */
- protected String readStandardString(int length) throws IOException {
- byte buf[] = new byte[length];
- rf.readFully(buf);
- try {
- return new String(buf, WINANSI);
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /** Reads a Unicode String
from the font file. Each character is
- * represented by two bytes.
- * @param length the length of bytes to read. The String
will have length
/2
- * characters
- * @return the String
read
- * @throws IOException the font file could not be read
- */
- protected String readUnicodeString(int length) throws IOException {
- StringBuffer buf = new StringBuffer();
- length /= 2;
- for (int k = 0; k < length; ++k) {
- buf.append(rf.readChar());
- }
- return buf.toString();
- }
-
- /** Reads the glyphs widths. The widths are extracted from the table 'hmtx'.
- * The glyphs are normalized to 1000 units.
- * @throws DocumentException the font is invalid
- * @throws IOException the font file could not be read
- */
- protected void readGlyphWidths() throws DocumentException, IOException {
- int table_location[];
- table_location = (int[])tables.get("hmtx");
- if (table_location == null)
- throw new DocumentException("Table 'hmtx' does not exist in " + fileName + style);
- rf.seek(table_location[0]);
- GlyphWidths = new int[hhea.numberOfHMetrics];
- for (int k = 0; k < hhea.numberOfHMetrics; ++k) {
- GlyphWidths[k] = (rf.readUnsignedShort() * 1000) / head.unitsPerEm;
- rf.readUnsignedShort();
- }
- }
-
- /** Gets a glyph width.
- * @param glyph the glyph to get the width of
- * @return the width of the glyph in normalized 1000 units
- */
- protected int getGlyphWidth(int glyph) {
- if (glyph >= GlyphWidths.length)
- glyph = GlyphWidths.length - 1;
- return GlyphWidths[glyph];
- }
-
- private void readBbox() throws DocumentException, IOException {
- int tableLocation[];
- tableLocation = (int[])tables.get("head");
- if (tableLocation == null)
- throw new DocumentException("Table 'head' does not exist in " + fileName + style);
- rf.seek(tableLocation[0] + TrueTypeFontSubSet.HEAD_LOCA_FORMAT_OFFSET);
- boolean locaShortTable = (rf.readUnsignedShort() == 0);
- tableLocation = (int[])tables.get("loca");
- if (tableLocation == null)
- return;
- rf.seek(tableLocation[0]);
- int locaTable[];
- if (locaShortTable) {
- int entries = tableLocation[1] / 2;
- locaTable = new int[entries];
- for (int k = 0; k < entries; ++k)
- locaTable[k] = rf.readUnsignedShort() * 2;
- }
- else {
- int entries = tableLocation[1] / 4;
- locaTable = new int[entries];
- for (int k = 0; k < entries; ++k)
- locaTable[k] = rf.readInt();
- }
- tableLocation = (int[])tables.get("glyf");
- if (tableLocation == null)
- throw new DocumentException("Table 'glyf' does not exist in " + fileName + style);
- int tableGlyphOffset = tableLocation[0];
- bboxes = new int[locaTable.length - 1][];
- for (int glyph = 0; glyph < locaTable.length - 1; ++glyph) {
- int start = locaTable[glyph];
- if (start != locaTable[glyph + 1]) {
- rf.seek(tableGlyphOffset + start + 2);
- bboxes[glyph] = new int[]{
- (rf.readShort() * 1000) / head.unitsPerEm,
- (rf.readShort() * 1000) / head.unitsPerEm,
- (rf.readShort() * 1000) / head.unitsPerEm,
- (rf.readShort() * 1000) / head.unitsPerEm};
- }
- }
- }
-
- /** Reads the several maps from the table 'cmap'. The maps of interest are 1.0 for symbolic
- * fonts and 3.1 for all others. A symbolic font is defined as having the map 3.0.
- * @throws DocumentException the font is invalid
- * @throws IOException the font file could not be read
- */
- void readCMaps() throws DocumentException, IOException {
- int table_location[];
- table_location = (int[])tables.get("cmap");
- if (table_location == null)
- throw new DocumentException("Table 'cmap' does not exist in " + fileName + style);
- rf.seek(table_location[0]);
- rf.skipBytes(2);
- int num_tables = rf.readUnsignedShort();
- fontSpecific = false;
- int map10 = 0;
- int map31 = 0;
- int map30 = 0;
- for (int k = 0; k < num_tables; ++k) {
- int platId = rf.readUnsignedShort();
- int platSpecId = rf.readUnsignedShort();
- int offset = rf.readInt();
- if (platId == 3 && platSpecId == 0) {
- fontSpecific = true;
- map30 = offset;
- }
- else if (platId == 3 && platSpecId == 1) {
- map31 = offset;
- }
- if (platId == 1 && platSpecId == 0) {
- map10 = offset;
- }
- }
- if (map10 > 0) {
- rf.seek(table_location[0] + map10);
- int format = rf.readUnsignedShort();
- switch (format) {
- case 0:
- cmap10 = readFormat0();
- break;
- case 4:
- cmap10 = readFormat4();
- break;
- case 6:
- cmap10 = readFormat6();
- break;
- }
- }
- if (map31 > 0) {
- rf.seek(table_location[0] + map31);
- int format = rf.readUnsignedShort();
- if (format == 4) {
- cmap31 = readFormat4();
- }
- }
- if (map30 > 0) {
- rf.seek(table_location[0] + map30);
- int format = rf.readUnsignedShort();
- if (format == 4) {
- cmap10 = readFormat4();
- }
- }
- }
-
- /** The information in the maps of the table 'cmap' is coded in several formats.
- * Format 0 is the Apple standard character to glyph index mapping table.
- * @return a HashMap
representing this map
- * @throws IOException the font file could not be read
- */
- HashMap readFormat0() throws IOException {
- HashMap h = new HashMap();
- rf.skipBytes(4);
- for (int k = 0; k < 256; ++k) {
- int r[] = new int[2];
- r[0] = rf.readUnsignedByte();
- r[1] = getGlyphWidth(r[0]);
- h.put(new Integer(k), r);
- }
- return h;
- }
-
- /** The information in the maps of the table 'cmap' is coded in several formats.
- * Format 4 is the Microsoft standard character to glyph index mapping table.
- * @return a HashMap
representing this map
- * @throws IOException the font file could not be read
- */
- HashMap readFormat4() throws IOException {
- HashMap h = new HashMap();
- int table_lenght = rf.readUnsignedShort();
- rf.skipBytes(2);
- int segCount = rf.readUnsignedShort() / 2;
- rf.skipBytes(6);
- int endCount[] = new int[segCount];
- for (int k = 0; k < segCount; ++k) {
- endCount[k] = rf.readUnsignedShort();
- }
- rf.skipBytes(2);
- int startCount[] = new int[segCount];
- for (int k = 0; k < segCount; ++k) {
- startCount[k] = rf.readUnsignedShort();
- }
- int idDelta[] = new int[segCount];
- for (int k = 0; k < segCount; ++k) {
- idDelta[k] = rf.readUnsignedShort();
- }
- int idRO[] = new int[segCount];
- for (int k = 0; k < segCount; ++k) {
- idRO[k] = rf.readUnsignedShort();
- }
- int glyphId[] = new int[table_lenght / 2 - 8 - segCount * 4];
- for (int k = 0; k < glyphId.length; ++k) {
- glyphId[k] = rf.readUnsignedShort();
- }
- for (int k = 0; k < segCount; ++k) {
- int glyph;
- for (int j = startCount[k]; j <= endCount[k] && j != 0xFFFF; ++j) {
- if (idRO[k] == 0) {
- glyph = (j + idDelta[k]) & 0xFFFF;
- }
- else {
- int idx = k + idRO[k] / 2 - segCount + j - startCount[k];
- if (idx >= glyphId.length)
- continue;
- glyph = (glyphId[idx] + idDelta[k]) & 0xFFFF;
- }
- int r[] = new int[2];
- r[0] = glyph;
- r[1] = getGlyphWidth(r[0]);
- h.put(new Integer(fontSpecific ? ((j & 0xff00) == 0xf000 ? j & 0xff : j) : j), r);
- }
- }
- return h;
- }
-
- /** The information in the maps of the table 'cmap' is coded in several formats.
- * Format 6 is a trimmed table mapping. It is similar to format 0 but can have
- * less than 256 entries.
- * @return a HashMap
representing this map
- * @throws IOException the font file could not be read
- */
- HashMap readFormat6() throws IOException {
- HashMap h = new HashMap();
- rf.skipBytes(4);
- int start_code = rf.readUnsignedShort();
- int code_count = rf.readUnsignedShort();
- for (int k = 0; k < code_count; ++k) {
- int r[] = new int[2];
- r[0] = rf.readUnsignedShort();
- r[1] = getGlyphWidth(r[0]);
- h.put(new Integer(k + start_code), r);
- }
- return h;
- }
-
- /** Reads the kerning information from the 'kern' table.
- * @throws IOException the font file could not be read
- */
- void readKerning() throws IOException {
- int table_location[];
- table_location = (int[])tables.get("kern");
- if (table_location == null)
- return;
- rf.seek(table_location[0] + 2);
- int nTables = rf.readUnsignedShort();
- int checkpoint = table_location[0] + 4;
- int length = 0;
- for (int k = 0; k < nTables; ++k) {
- checkpoint += length;
- rf.seek(checkpoint);
- rf.skipBytes(2);
- length = rf.readUnsignedShort();
- int coverage = rf.readUnsignedShort();
- if ((coverage & 0xfff7) == 0x0001) {
- int nPairs = rf.readUnsignedShort();
- rf.skipBytes(6);
- for (int j = 0; j < nPairs; ++j) {
- int pair = rf.readInt();
- int value = ((int)rf.readShort() * 1000) / head.unitsPerEm;
- kerning.put(pair, value);
- }
- }
- }
- }
-
- /** Gets the kerning between two Unicode chars.
- * @param char1 the first char
- * @param char2 the second char
- * @return the kerning to be applied
- */
- public int getKerning(char char1, char char2) {
- int metrics[] = getMetricsTT(char1);
- if (metrics == null)
- return 0;
- int c1 = metrics[0];
- metrics = getMetricsTT(char2);
- if (metrics == null)
- return 0;
- int c2 = metrics[0];
- return kerning.get((c1 << 16) + c2);
- }
-
- /** Gets the width from the font according to the unicode char c
.
- * If the name
is null it's a symbolic font.
- * @param c the unicode char
- * @param name the glyph name
- * @return the width of the char
- */
- int getRawWidth(int c, String name) {
- HashMap map = null;
- if (name == null || cmap31 == null)
- map = cmap10;
- else
- map = cmap31;
- if (map == null)
- return 0;
- int metric[] = (int[])map.get(new Integer(c));
- if (metric == null)
- return 0;
- return metric[1];
- }
-
- /** Generates the font descriptor for this font.
- * @return the PdfDictionary containing the font descriptor or null
- * @param subsetPrefix the subset prefix
- * @param fontStream the indirect reference to a PdfStream containing the font or null
- * @throws DocumentException if there is an error
- */
- protected PdfDictionary getFontDescriptor(PdfIndirectReference fontStream, String subsetPrefix) throws DocumentException {
- PdfDictionary dic = new PdfDictionary(PdfName.FONTDESCRIPTOR);
- dic.put(PdfName.ASCENT, new PdfNumber((int)os_2.sTypoAscender * 1000 / head.unitsPerEm));
- dic.put(PdfName.CAPHEIGHT, new PdfNumber((int)os_2.sCapHeight * 1000 / head.unitsPerEm));
- dic.put(PdfName.DESCENT, new PdfNumber((int)os_2.sTypoDescender * 1000 / head.unitsPerEm));
- dic.put(PdfName.FONTBBOX, new PdfRectangle(
- (int)head.xMin * 1000 / head.unitsPerEm,
- (int)head.yMin * 1000 / head.unitsPerEm,
- (int)head.xMax * 1000 / head.unitsPerEm,
- (int)head.yMax * 1000 / head.unitsPerEm));
- if (cff) {
- if (encoding.startsWith("Identity-"))
- dic.put(PdfName.FONTNAME, new PdfName(subsetPrefix + fontName+"-"+encoding));
- else
- dic.put(PdfName.FONTNAME, new PdfName(subsetPrefix + fontName + style));
- }
- else
- dic.put(PdfName.FONTNAME, new PdfName(subsetPrefix + fontName + style));
- dic.put(PdfName.ITALICANGLE, new PdfNumber(italicAngle));
- dic.put(PdfName.STEMV, new PdfNumber(80));
- if (fontStream != null) {
- if (cff)
- dic.put(PdfName.FONTFILE3, fontStream);
- else
- dic.put(PdfName.FONTFILE2, fontStream);
- }
- int flags = 0;
- if (isFixedPitch)
- flags |= 1;
- flags |= fontSpecific ? 4 : 32;
- if ((head.macStyle & 2) != 0)
- flags |= 64;
- if ((head.macStyle & 1) != 0)
- flags |= 262144;
- dic.put(PdfName.FLAGS, new PdfNumber(flags));
-
- return dic;
- }
-
- /** Generates the font dictionary for this font.
- * @return the PdfDictionary containing the font dictionary
- * @param subsetPrefix the subset prefx
- * @param firstChar the first valid character
- * @param lastChar the last valid character
- * @param shortTag a 256 bytes long byte
array where each unused byte is represented by 0
- * @param fontDescriptor the indirect reference to a PdfDictionary containing the font descriptor or null
- * @throws DocumentException if there is an error
- */
- protected PdfDictionary getFontBaseType(PdfIndirectReference fontDescriptor, String subsetPrefix, int firstChar, int lastChar, byte shortTag[]) throws DocumentException {
- PdfDictionary dic = new PdfDictionary(PdfName.FONT);
- if (cff) {
- dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
- dic.put(PdfName.BASEFONT, new PdfName(fontName + style));
- }
- else {
- dic.put(PdfName.SUBTYPE, PdfName.TRUETYPE);
- dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName + style));
- }
- dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName + style));
- if (!fontSpecific) {
- for (int k = firstChar; k <= lastChar; ++k) {
- if (!differences[k].equals(notdef)) {
- firstChar = k;
- break;
- }
- }
- if (encoding.equals("Cp1252") || encoding.equals("MacRoman"))
- dic.put(PdfName.ENCODING, encoding.equals("Cp1252") ? PdfName.WIN_ANSI_ENCODING : PdfName.MAC_ROMAN_ENCODING);
- else {
- PdfDictionary enc = new PdfDictionary(PdfName.ENCODING);
- PdfArray dif = new PdfArray();
- boolean gap = true;
- for (int k = firstChar; k <= lastChar; ++k) {
- if (shortTag[k] != 0) {
- if (gap) {
- dif.add(new PdfNumber(k));
- gap = false;
- }
- dif.add(new PdfName(differences[k]));
- }
- else
- gap = true;
- }
- enc.put(PdfName.DIFFERENCES, dif);
- dic.put(PdfName.ENCODING, enc);
- }
- }
- dic.put(PdfName.FIRSTCHAR, new PdfNumber(firstChar));
- dic.put(PdfName.LASTCHAR, new PdfNumber(lastChar));
- PdfArray wd = new PdfArray();
- for (int k = firstChar; k <= lastChar; ++k) {
- if (shortTag[k] == 0)
- wd.add(new PdfNumber(0));
- else
- wd.add(new PdfNumber(widths[k]));
- }
- dic.put(PdfName.WIDTHS, wd);
- if (fontDescriptor != null)
- dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
- return dic;
- }
-
- private byte[] getFullFont() throws IOException {
- RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf);
- rf2.reOpen();
- byte b[] = new byte[rf2.length()];
- rf2.readFully(b);
- rf2.close();
- return b;
- }
-
- /** Outputs to the writer the font dictionaries and streams.
- * @param writer the writer for this document
- * @param ref the font indirect reference
- * @param params several parameters that depend on the font type
- * @throws IOException on error
- * @throws DocumentException error in generating the object
- */
- void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
- int firstChar = ((Integer)params[0]).intValue();
- int lastChar = ((Integer)params[1]).intValue();
- byte shortTag[] = (byte[])params[2];
- if (!subset) {
- firstChar = 0;
- lastChar = shortTag.length - 1;
- for (int k = 0; k < shortTag.length; ++k)
- shortTag[k] = 1;
- }
- PdfIndirectReference ind_font = null;
- PdfObject pobj = null;
- PdfIndirectObject obj = null;
- String subsetPrefix = "";
- if (embedded) {
- if (cff) {
- RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf);
- byte b[] = new byte[cffLength];
- try {
- rf2.reOpen();
- rf2.seek(cffOffset);
- rf2.readFully(b);
- }
- finally {
- try {
- rf2.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- pobj = new StreamFont(b, "Type1C");
- obj = writer.addToBody(pobj);
- ind_font = obj.getIndirectReference();
- }
- else {
- if (subset)
- subsetPrefix = createSubsetPrefix();
- HashMap glyphs = new HashMap();
- for (int k = firstChar; k <= lastChar; ++k) {
- if (shortTag[k] != 0) {
- int metrics[];
- if (fontSpecific)
- metrics = getMetricsTT(k);
- else
- metrics = getMetricsTT(unicodeDifferences[k]);
- if (metrics != null)
- glyphs.put(new Integer(metrics[0]), null);
- }
- }
- TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, new RandomAccessFileOrArray(rf), glyphs, directoryOffset, true);
- byte b[] = sb.process();
- int lengths[] = new int[]{b.length};
- pobj = new StreamFont(b, lengths);
- obj = writer.addToBody(pobj);
- ind_font = obj.getIndirectReference();
- }
- }
- pobj = getFontDescriptor(ind_font, subsetPrefix);
- if (pobj != null){
- obj = writer.addToBody(pobj);
- ind_font = obj.getIndirectReference();
- }
- pobj = getFontBaseType(ind_font, subsetPrefix, firstChar, lastChar, shortTag);
- writer.addToBody(pobj, ref);
- }
-
- /** Gets the font parameter identified by key
. Valid values
- * for key
are ASCENT
, CAPHEIGHT
, DESCENT
- * and ITALICANGLE
.
- * @param key the parameter to be extracted
- * @param fontSize the font size in points
- * @return the parameter in points
- */
- public float getFontDescriptor(int key, float fontSize) {
- switch (key) {
- case ASCENT:
- return (float)os_2.sTypoAscender * fontSize / (float)head.unitsPerEm;
- case CAPHEIGHT:
- return (float)os_2.sCapHeight * fontSize / (float)head.unitsPerEm;
- case DESCENT:
- return (float)os_2.sTypoDescender * fontSize / (float)head.unitsPerEm;
- case ITALICANGLE:
- return (float)italicAngle;
- case BBOXLLX:
- return fontSize * (int)head.xMin / head.unitsPerEm;
- case BBOXLLY:
- return fontSize * (int)head.yMin / head.unitsPerEm;
- case BBOXURX:
- return fontSize * (int)head.xMax / head.unitsPerEm;
- case BBOXURY:
- return fontSize * (int)head.yMax / head.unitsPerEm;
- case AWT_ASCENT:
- return fontSize * (int)hhea.Ascender / head.unitsPerEm;
- case AWT_DESCENT:
- return fontSize * (int)hhea.Descender / head.unitsPerEm;
- case AWT_LEADING:
- return fontSize * (int)hhea.LineGap / head.unitsPerEm;
- case AWT_MAXADVANCE:
- return fontSize * (int)hhea.advanceWidthMax / head.unitsPerEm;
- }
- return 0;
- }
-
- /** Gets the glyph index and metrics for a character.
- * @param c the character
- * @return an int
array with {glyph index, width}
- */
- public int[] getMetricsTT(int c) {
- if (!fontSpecific && cmap31 != null)
- return (int[])cmap31.get(new Integer(c));
- if (fontSpecific && cmap10 != null)
- return (int[])cmap10.get(new Integer(c));
- if (cmap31 != null)
- return (int[])cmap31.get(new Integer(c));
- if (cmap10 != null)
- return (int[])cmap10.get(new Integer(c));
- return null;
- }
-
- /** Gets the postscript font name.
- * @return the postscript font name
- */
- public String getPostscriptFontName() {
- return fontName;
- }
-
- /** Gets the code pages supported by the font.
- * @return the code pages supported by the font
- */
- public String[] getCodePagesSupported() {
- long cp = (((long)os_2.ulCodePageRange2) << 32) + ((long)os_2.ulCodePageRange1 & 0xffffffffL);
- int count = 0;
- long bit = 1;
- for (int k = 0; k < 64; ++k) {
- if ((cp & bit) != 0 && codePages[k] != null)
- ++count;
- bit <<= 1;
- }
- String ret[] = new String[count];
- count = 0;
- bit = 1;
- for (int k = 0; k < 64; ++k) {
- if ((cp & bit) != 0 && codePages[k] != null)
- ret[count++] = codePages[k];
- bit <<= 1;
- }
- return ret;
- }
-
- /** Gets the full name of the font. If it is a True Type font
- * each array element will have {Platform ID, Platform Encoding ID,
- * Language ID, font name}. The interpretation of this values can be
- * found in the Open Type specification, chapter 2, in the 'name' table.
- * For the other fonts the array has a single element with {"", "", "",
- * font name}.
- * @return the full name of the font
- */
- public String[][] getFullFontName() {
- return fullName;
- }
-
- /** Gets the family name of the font. If it is a True Type font
- * each array element will have {Platform ID, Platform Encoding ID,
- * Language ID, font name}. The interpretation of this values can be
- * found in the Open Type specification, chapter 2, in the 'name' table.
- * For the other fonts the array has a single element with {"", "", "",
- * font name}.
- * @return the family name of the font
- */
- public String[][] getFamilyFontName() {
- return familyName;
- }
-
- /** Checks if the font has any kerning pairs.
- * @return true
if the font has any kerning pairs
- */
- public boolean hasKernPairs() {
- return kerning.size() > 0;
- }
-
- /**
- * Sets the font name that will appear in the pdf font dictionary.
- * Use with care as it can easily make a font unreadable if not embedded.
- * @param name the new font name
- */
- public void setPostscriptFontName(String name) {
- fontName = name;
- }
-
- /**
- * Sets the kerning between two Unicode chars.
- * @param char1 the first char
- * @param char2 the second char
- * @param kern the kerning to apply in normalized 1000 units
- * @return true
if the kerning was applied, false
otherwise
- */
- public boolean setKerning(char char1, char char2, int kern) {
- int metrics[] = getMetricsTT(char1);
- if (metrics == null)
- return false;
- int c1 = metrics[0];
- metrics = getMetricsTT(char2);
- if (metrics == null)
- return false;
- int c2 = metrics[0];
- kerning.put((c1 << 16) + c2, kern);
- return true;
- }
-
- protected int[] getRawCharBBox(int c, String name) {
- HashMap map = null;
- if (name == null || cmap31 == null)
- map = cmap10;
- else
- map = cmap31;
- if (map == null)
- return null;
- int metric[] = (int[])map.get(new Integer(c));
- if (metric == null || bboxes == null)
- return null;
- return bboxes[metric[0]];
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/TrueTypeFontSubSet.java pdftk-2.01/java/com/lowagie/text/pdf/TrueTypeFontSubSet.java
--- pdftk-1.45/java/com/lowagie/text/pdf/TrueTypeFontSubSet.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/TrueTypeFontSubSet.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,426 +0,0 @@
-/*
- * $Id: TrueTypeFontSubSet.java,v 1.15 2002/07/09 11:28:24 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.*;
-import java.util.HashMap;
-import java.util.ArrayList;
-import java.util.Arrays;
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.ExceptionConverter;
-
-/** Subsets a True Type font by removing the unneeded glyphs from
- * the font.
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-class TrueTypeFontSubSet {
- static final String tableNamesSimple[] = {"cvt ", "fpgm", "glyf", "head",
- "hhea", "hmtx", "loca", "maxp", "prep"};
- static final String tableNamesCmap[] = {"cmap", "cvt ", "fpgm", "glyf", "head",
- "hhea", "hmtx", "loca", "maxp", "prep"};
- static final int entrySelectors[] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4};
- static final int TABLE_CHECKSUM = 0;
- static final int TABLE_OFFSET = 1;
- static final int TABLE_LENGTH = 2;
- static final int HEAD_LOCA_FORMAT_OFFSET = 51;
-
- static final int ARG_1_AND_2_ARE_WORDS = 1;
- static final int WE_HAVE_A_SCALE = 8;
- static final int MORE_COMPONENTS = 32;
- static final int WE_HAVE_AN_X_AND_Y_SCALE = 64;
- static final int WE_HAVE_A_TWO_BY_TWO = 128;
-
-
- /** Contains the location of the several tables. The key is the name of
- * the table and the value is an int[3]
where position 0
- * is the checksum, position 1 is the offset from the start of the file
- * and position 2 is the length of the table.
- */
- protected HashMap tableDirectory;
- /** The file in use.
- */
- protected RandomAccessFileOrArray rf;
- /** The file name.
- */
- protected String fileName;
- protected boolean includeCmap;
- protected boolean locaShortTable;
- protected int locaTable[];
- protected HashMap glyphsUsed;
- protected ArrayList glyphsInList;
- protected int tableGlyphOffset;
- protected int newLocaTable[];
- protected byte newLocaTableOut[];
- protected byte newGlyfTable[];
- protected int glyfTableRealSize;
- protected int locaTableRealSize;
- protected byte outFont[];
- protected int fontPtr;
- protected int directoryOffset;
-
- /** Creates a new TrueTypeFontSubSet
- * @param directoryOffset The offset from the start of the file to the table directory
- * @param fileName the file name of the font
- * @param glyphsUsed the glyphs used
- * @param includeCmap true
if the table cmap is to be included in the generated font
- */
- TrueTypeFontSubSet(String fileName, RandomAccessFileOrArray rf, HashMap glyphsUsed, int directoryOffset, boolean includeCmap) {
- this.fileName = fileName;
- this.rf = rf;
- this.glyphsUsed = glyphsUsed;
- this.includeCmap = includeCmap;
- this.directoryOffset = directoryOffset;
- glyphsInList = new ArrayList(glyphsUsed.keySet());
- }
-
- /** Does the actual work of subsetting the font.
- * @throws IOException on error
- * @throws DocumentException on error
- * @return the subset font
- */
- byte[] process() throws IOException, DocumentException {
- try {
- rf.reOpen();
- createTableDirectory();
- readLoca();
- flatGlyphs();
- createNewGlyphTables();
- locaTobytes();
- assembleFont();
- return outFont;
- }
- finally {
- try {
- rf.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- }
-
- protected void assembleFont() throws IOException, DocumentException {
- int tableLocation[];
- int fullFontSize = 0;
- String tableNames[];
- if (includeCmap)
- tableNames = tableNamesCmap;
- else
- tableNames = tableNamesSimple;
- int tablesUsed = 2;
- int len = 0;
- for (int k = 0; k < tableNames.length; ++k) {
- String name = tableNames[k];
- if (name.equals("glyf") || name.equals("loca"))
- continue;
- tableLocation = (int[])tableDirectory.get(name);
- if (tableLocation == null)
- continue;
- ++tablesUsed;
- fullFontSize += (tableLocation[TABLE_LENGTH] + 3) & (~3);
- }
- fullFontSize += newLocaTableOut.length;
- fullFontSize += newGlyfTable.length;
- int ref = 16 * tablesUsed + 12;
- fullFontSize += ref;
- outFont = new byte[fullFontSize];
- fontPtr = 0;
- writeFontInt(0x00010000);
- writeFontShort(tablesUsed);
- int selector = entrySelectors[tablesUsed];
- writeFontShort((1 << selector) * 16);
- writeFontShort(selector);
- writeFontShort((tablesUsed - (1 << selector)) * 16);
- for (int k = 0; k < tableNames.length; ++k) {
- String name = tableNames[k];
- tableLocation = (int[])tableDirectory.get(name);
- if (tableLocation == null)
- continue;
- writeFontString(name);
- if (name.equals("glyf")) {
- writeFontInt(calculateChecksum(newGlyfTable));
- len = glyfTableRealSize;
- }
- else if (name.equals("loca")) {
- writeFontInt(calculateChecksum(newLocaTableOut));
- len = locaTableRealSize;
- }
- else {
- writeFontInt(tableLocation[TABLE_CHECKSUM]);
- len = tableLocation[TABLE_LENGTH];
- }
- writeFontInt(ref);
- writeFontInt(len);
- ref += (len + 3) & (~3);
- }
- for (int k = 0; k < tableNames.length; ++k) {
- String name = tableNames[k];
- tableLocation = (int[])tableDirectory.get(name);
- if (tableLocation == null)
- continue;
- if (name.equals("glyf")) {
- System.arraycopy(newGlyfTable, 0, outFont, fontPtr, newGlyfTable.length);
- fontPtr += newGlyfTable.length;
- newGlyfTable = null;
- }
- else if (name.equals("loca")) {
- System.arraycopy(newLocaTableOut, 0, outFont, fontPtr, newLocaTableOut.length);
- fontPtr += newLocaTableOut.length;
- newLocaTableOut = null;
- }
- else {
- rf.seek(tableLocation[TABLE_OFFSET]);
- rf.readFully(outFont, fontPtr, tableLocation[TABLE_LENGTH]);
- fontPtr += (tableLocation[TABLE_LENGTH] + 3) & (~3);
- }
- }
- }
-
- protected void createTableDirectory() throws IOException, DocumentException {
- tableDirectory = new HashMap();
- rf.seek(directoryOffset);
- int id = rf.readInt();
- if (id != 0x00010000)
- throw new DocumentException(fileName + " is not a true type file.");
- int num_tables = rf.readUnsignedShort();
- rf.skipBytes(6);
- for (int k = 0; k < num_tables; ++k) {
- String tag = readStandardString(4);
- int tableLocation[] = new int[3];
- tableLocation[TABLE_CHECKSUM] = rf.readInt();
- tableLocation[TABLE_OFFSET] = rf.readInt();
- tableLocation[TABLE_LENGTH] = rf.readInt();
- tableDirectory.put(tag, tableLocation);
- }
- }
-
- protected void readLoca() throws IOException, DocumentException {
- int tableLocation[];
- tableLocation = (int[])tableDirectory.get("head");
- if (tableLocation == null)
- throw new DocumentException("Table 'head' does not exist in " + fileName);
- rf.seek(tableLocation[TABLE_OFFSET] + HEAD_LOCA_FORMAT_OFFSET);
- locaShortTable = (rf.readUnsignedShort() == 0);
- tableLocation = (int[])tableDirectory.get("loca");
- if (tableLocation == null)
- throw new DocumentException("Table 'loca' does not exist in " + fileName);
- rf.seek(tableLocation[TABLE_OFFSET]);
- if (locaShortTable) {
- int entries = tableLocation[TABLE_LENGTH] / 2;
- locaTable = new int[entries];
- for (int k = 0; k < entries; ++k)
- locaTable[k] = rf.readUnsignedShort() * 2;
- }
- else {
- int entries = tableLocation[TABLE_LENGTH] / 4;
- locaTable = new int[entries];
- for (int k = 0; k < entries; ++k)
- locaTable[k] = rf.readInt();
- }
- }
-
- protected void createNewGlyphTables() throws IOException {
- newLocaTable = new int[locaTable.length];
- int activeGlyphs[] = new int[glyphsInList.size()];
- for (int k = 0; k < activeGlyphs.length; ++k)
- activeGlyphs[k] = ((Integer)glyphsInList.get(k)).intValue();
- Arrays.sort(activeGlyphs);
- int glyfSize = 0;
- for (int k = 0; k < activeGlyphs.length; ++k) {
- int glyph = activeGlyphs[k];
- glyfSize += locaTable[glyph + 1] - locaTable[glyph];
- }
- glyfTableRealSize = glyfSize;
- glyfSize = (glyfSize + 3) & (~3);
- newGlyfTable = new byte[glyfSize];
- int glyfPtr = 0;
- int listGlyf = 0;
- for (int k = 0; k < newLocaTable.length; ++k) {
- newLocaTable[k] = glyfPtr;
- if (listGlyf < activeGlyphs.length && activeGlyphs[listGlyf] == k) {
- ++listGlyf;
- newLocaTable[k] = glyfPtr;
- int start = locaTable[k];
- int len = locaTable[k + 1] - start;
- if (len > 0) {
- rf.seek(tableGlyphOffset + start);
- rf.readFully(newGlyfTable, glyfPtr, len);
- glyfPtr += len;
- }
- }
- }
- }
-
- protected void locaTobytes() {
- if (locaShortTable)
- locaTableRealSize = newLocaTable.length * 2;
- else
- locaTableRealSize = newLocaTable.length * 4;
- newLocaTableOut = new byte[(locaTableRealSize + 3) & (~3)];
- outFont = newLocaTableOut;
- fontPtr = 0;
- for (int k = 0; k < newLocaTable.length; ++k) {
- if (locaShortTable)
- writeFontShort(newLocaTable[k] / 2);
- else
- writeFontInt(newLocaTable[k]);
- }
-
- }
-
- protected void flatGlyphs() throws IOException, DocumentException {
- int tableLocation[];
- tableLocation = (int[])tableDirectory.get("glyf");
- if (tableLocation == null)
- throw new DocumentException("Table 'glyf' does not exist in " + fileName);
- Integer glyph0 = new Integer(0);
- if (!glyphsUsed.containsKey(glyph0)) {
- glyphsUsed.put(glyph0, null);
- glyphsInList.add(glyph0);
- }
- tableGlyphOffset = tableLocation[TABLE_OFFSET];
- for (int k = 0; k < glyphsInList.size(); ++k) {
- int glyph = ((Integer)glyphsInList.get(k)).intValue();
- checkGlyphComposite(glyph);
- }
- }
-
- protected void checkGlyphComposite(int glyph) throws IOException {
- int start = locaTable[glyph];
- if (start == locaTable[glyph + 1]) // no contour
- return;
- rf.seek(tableGlyphOffset + start);
- int numContours = rf.readShort();
- if (numContours >= 0)
- return;
- rf.skipBytes(8);
- for(;;) {
- int flags = rf.readUnsignedShort();
- Integer cGlyph = new Integer(rf.readUnsignedShort());
- if (!glyphsUsed.containsKey(cGlyph)) {
- glyphsUsed.put(cGlyph, null);
- glyphsInList.add(cGlyph);
- }
- if ((flags & MORE_COMPONENTS) == 0)
- return;
- int skip;
- if ((flags & ARG_1_AND_2_ARE_WORDS) != 0)
- skip = 4;
- else
- skip = 2;
- if ((flags & WE_HAVE_A_SCALE) != 0)
- skip += 2;
- else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0)
- skip += 4;
- if ((flags & WE_HAVE_A_TWO_BY_TWO) != 0)
- skip += 8;
- rf.skipBytes(skip);
- }
- }
-
- /** Reads a String
from the font file as bytes using the Cp1252
- * encoding.
- * @param length the length of bytes to read
- * @return the String
read
- * @throws IOException the font file could not be read
- */
- protected String readStandardString(int length) throws IOException {
- byte buf[] = new byte[length];
- rf.readFully(buf);
- try {
- return new String(buf, BaseFont.WINANSI);
- }
- catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- protected void writeFontShort(int n) {
- outFont[fontPtr++] = (byte)(n >> 8);
- outFont[fontPtr++] = (byte)(n);
- }
-
- protected void writeFontInt(int n) {
- outFont[fontPtr++] = (byte)(n >> 24);
- outFont[fontPtr++] = (byte)(n >> 16);
- outFont[fontPtr++] = (byte)(n >> 8);
- outFont[fontPtr++] = (byte)(n);
- }
-
- protected void writeFontString(String s) {
- byte b[] = PdfEncodings.convertToBytes(s, BaseFont.WINANSI);
- System.arraycopy(b, 0, outFont, fontPtr, b.length);
- fontPtr += b.length;
- }
-
- protected int calculateChecksum(byte b[]) {
- int len = b.length / 4;
- int v0 = 0;
- int v1 = 0;
- int v2 = 0;
- int v3 = 0;
- int ptr = 0;
- for (int k = 0; k < len; ++k) {
- v3 += (int)b[ptr++] & 0xff;
- v2 += (int)b[ptr++] & 0xff;
- v1 += (int)b[ptr++] & 0xff;
- v0 += (int)b[ptr++] & 0xff;
- }
- return v0 + (v1 << 8) + (v2 << 16) + (v3 << 24);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/TrueTypeFontUnicode.java pdftk-2.01/java/com/lowagie/text/pdf/TrueTypeFontUnicode.java
--- pdftk-1.45/java/com/lowagie/text/pdf/TrueTypeFontUnicode.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/TrueTypeFontUnicode.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,485 +0,0 @@
-/*
- * $Id: TrueTypeFontUnicode.java,v 1.3 2003/11/17 12:53:06 stoledo Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashMap;
-
-import com.lowagie.text.DocumentException;
-/** Represents a True Type font with Unicode encoding. All the character
- * in the font can be used directly by using the encoding Identity-H or
- * Identity-V. This is the only way to represent some character sets such
- * as Thai.
- * @author Paulo Soares (psoares@consiste.pt)
- */
-class TrueTypeFontUnicode extends TrueTypeFont implements Comparator{
-
- /** true
if the encoding is vertical.
- */
- boolean vertical = false;
-
- /** Creates a new TrueType font addressed by Unicode characters. The font
- * will always be embedded.
- * @param ttFile the location of the font on file. The file must end in '.ttf'.
- * The modifiers after the name are ignored.
- * @param enc the encoding to be applied to this font
- * @param emb true if the font is to be embedded in the PDF
- * @param ttfAfm the font as a byte
array
- * @throws DocumentException the font is invalid
- * @throws IOException the font file could not be read
- */
- TrueTypeFontUnicode(String ttFile, String enc, boolean emb, byte ttfAfm[]) throws DocumentException, IOException {
- String nameBase = getBaseName(ttFile);
- String ttcName = getTTCName(nameBase);
- if (nameBase.length() < ttFile.length()) {
- style = ttFile.substring(nameBase.length());
- }
- encoding = enc;
- embedded = emb;
- fileName = ttcName;
- ttcIndex = "";
- if (ttcName.length() < nameBase.length())
- ttcIndex = nameBase.substring(ttcName.length() + 1);
- fontType = FONT_TYPE_TTUNI;
- if ((fileName.toLowerCase().endsWith(".ttf") || fileName.toLowerCase().endsWith(".otf") || fileName.toLowerCase().endsWith(".ttc")) && ((enc.equals(IDENTITY_H) || enc.equals(IDENTITY_V)) && emb)) {
- process(ttfAfm);
- if (os_2.fsType == 2)
- throw new DocumentException(fileName + style + " cannot be embedded due to licensing restrictions.");
- // Sivan
- if ((cmap31 == null && !fontSpecific) || (cmap10 == null && fontSpecific))
- directTextToByte=true;
- //throw new DocumentException(fileName + " " + style + " does not contain an usable cmap.");
- if (fontSpecific) {
- fontSpecific = false;
- String tempEncoding = encoding;
- encoding = "";
- createEncoding();
- encoding = tempEncoding;
- fontSpecific = true;
- }
- }
- else
- throw new DocumentException(fileName + " " + style + " is not a TTF font file.");
- vertical = enc.endsWith("V");
- }
-
-/**
- * Gets the width of a String
in normalized 1000 units.
- * @param text the String
to get the witdth of
- * @return the width in normalized 1000 units
- */
- public int getWidth(String text)
- {
- if (vertical)
- return text.length() * 1000;
- int total = 0;
- if (fontSpecific) {
- char cc[] = text.toCharArray();
- int len = cc.length;
- for (int k = 0; k < len; ++k) {
- char c = cc[k];
- if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
- total += getRawWidth(c & 0xff, null);
- }
- }
- else {
- int len = text.length();
- for (int k = 0; k < len; ++k)
- total += getRawWidth(text.charAt(k), encoding);
- }
- return total;
- }
-
- /** Creates a ToUnicode CMap to allow copy and paste from Acrobat.
- * @param metrics metrics[0] contains the glyph index and metrics[2]
- * contains the Unicode code
- * @throws DocumentException on error
- * @return the stream representing this CMap or null
- */
- private PdfStream getToUnicode(Object metrics[]) throws DocumentException {
- if (metrics.length == 0)
- return null;
- StringBuffer buf = new StringBuffer(
- "/CIDInit /ProcSet findresource begin\n" +
- "12 dict begin\n" +
- "begincmap\n" +
- "/CIDSystemInfo\n" +
- "<< /Registry (Adobe)\n" +
- "/Ordering (UCS)\n" +
- "/Supplement 0\n" +
- ">> def\n" +
- "/CMapName /Adobe-Identity-UCS def\n" +
- "/CMapType 2 def\n" +
- "1 begincodespacerange\n" +
- toHex(((int[])metrics[0])[0]) + toHex(((int[])metrics[metrics.length - 1])[0]) + "\n" +
- "endcodespacerange\n");
- int size = 0;
- for (int k = 0; k < metrics.length; ++k) {
- if (size == 0) {
- if (k != 0) {
- buf.append("endbfrange\n");
- }
- size = Math.min(100, metrics.length - k);
- buf.append(size).append(" beginbfrange\n");
- }
- --size;
- int metric[] = (int[])metrics[k];
- String fromTo = toHex(metric[0]);
- buf.append(fromTo).append(fromTo).append(toHex(metric[2])).append("\n");
- }
- buf.append(
- "endbfrange\n" +
- "endcmap\n" +
- "CMapName currentdict /CMap defineresource pop\n" +
- "end end\n");
- String s = buf.toString();
- PdfStream stream = new PdfStream(PdfEncodings.convertToBytes(s, null));
- stream.flateCompress();
- return stream;
- }
-
- /** Gets an hex string in the format "<HHHH>".
- * @param n the number
- * @return the hex string
- */
- static String toHex(int n) {
- String s = Integer.toHexString(n);
- return "<0000".substring(0, 5 - s.length()) + s + ">";
- }
-
- /** Generates the CIDFontTyte2 dictionary.
- * @param fontDescriptor the indirect reference to the font descriptor
- * @param subsetPrefix the subset prefix
- * @param metrics the horizontal width metrics
- * @return a stream
- */
- private PdfDictionary getCIDFontType2(PdfIndirectReference fontDescriptor, String subsetPrefix, Object metrics[]) {
- PdfDictionary dic = new PdfDictionary(PdfName.FONT);
- // sivan; cff
- if (cff) {
- dic.put(PdfName.SUBTYPE, PdfName.CIDFONTTYPE0);
- dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix+fontName+"-"+encoding));
- }
- else {
- dic.put(PdfName.SUBTYPE, PdfName.CIDFONTTYPE2);
- dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName));
- }
- dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
- if (!cff)
- dic.put(PdfName.CIDTOGIDMAP,PdfName.IDENTITY);
- PdfDictionary cdic = new PdfDictionary();
- cdic.put(PdfName.REGISTRY, new PdfString("Adobe"));
- cdic.put(PdfName.ORDERING, new PdfString("Identity"));
- cdic.put(PdfName.SUPPLEMENT, new PdfNumber(0));
- dic.put(PdfName.CIDSYSTEMINFO, cdic);
- if (!vertical) {
- dic.put(PdfName.DW, new PdfNumber(1000));
- StringBuffer buf = new StringBuffer("[");
- int lastNumber = -10;
- boolean firstTime = true;
- for (int k = 0; k < metrics.length; ++k) {
- int metric[] = (int[])metrics[k];
- if (metric[1] == 1000)
- continue;
- int m = metric[0];
- if (m == lastNumber + 1) {
- buf.append(" ").append(metric[1]);
- }
- else {
- if (!firstTime) {
- buf.append("]");
- }
- firstTime = false;
- buf.append(m).append("[").append(metric[1]);
- }
- lastNumber = m;
- }
- if (buf.length() > 1) {
- buf.append("]]");
- dic.put(PdfName.W, new PdfLiteral(buf.toString()));
- }
- }
- return dic;
- }
-
- /** Generates the font dictionary.
- * @param descendant the descendant dictionary
- * @param subsetPrefix the subset prefix
- * @param toUnicode the ToUnicode stream
- * @return the stream
- */
- private PdfDictionary getFontBaseType(PdfIndirectReference descendant, String subsetPrefix, PdfIndirectReference toUnicode) {
- PdfDictionary dic = new PdfDictionary(PdfName.FONT);
-
- dic.put(PdfName.SUBTYPE, PdfName.TYPE0);
- // The PDF Reference manual advises to add -encoding to CID font names
- if (cff)
- dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix+fontName+"-"+encoding));
- //dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix+fontName));
- else
- dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName));
- //dic.put(PdfName.BASEFONT, new PdfName(fontName));
- dic.put(PdfName.ENCODING, new PdfName(encoding));
- dic.put(PdfName.DESCENDANTFONTS, new PdfArray(descendant));
- if (toUnicode != null)
- dic.put(PdfName.TOUNICODE, toUnicode);
- return dic;
- }
-
- /** The method used to sort the metrics array.
- * @param o1 the first element
- * @param o2 the second element
- * @return the comparisation
- */
- public int compare(Object o1, Object o2) {
- int m1 = ((int[])o1)[0];
- int m2 = ((int[])o2)[0];
- if (m1 < m2)
- return -1;
- if (m1 == m2)
- return 0;
- return 1;
- }
-
- /** Outputs to the writer the font dictionaries and streams.
- * @param writer the writer for this document
- * @param ref the font indirect reference
- * @param params several parameters that depend on the font type
- * @throws IOException on error
- * @throws DocumentException error in generating the object
- */
- void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
- HashMap longTag = (HashMap)params[0];
- Object metrics[] = longTag.values().toArray();
- Arrays.sort(metrics, this);
- PdfIndirectReference ind_font = null;
- PdfObject pobj = null;
- PdfIndirectObject obj = null;
- // sivan: cff
- if (cff) {
- RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf);
- byte b[] = new byte[cffLength];
- try {
- rf2.reOpen();
- rf2.seek(cffOffset);
- rf2.readFully(b);
- } finally {
- try {
- rf2.close();
- } catch (Exception e) {
- // empty on purpose
- }
- }
- /*
- CFFFont cffFont = new CFFFont(new RandomAccessFileOrArray(b));
- // test if we can find the font by name and if it's a type1 CFF
- if (cffFont.exists(fontName) && !cffFont.isCID(fontName)) {
- byte[] cid = cffFont.getCID( (cffFont.getNames())[0] );
- if (cid != null) b=cid;
- }
-
- */
-
- CFFFontSubset cff = new CFFFontSubset(new RandomAccessFileOrArray(b),longTag);
- b = cff.Process( (cff.getNames())[0] );
-
- // if the font is already CID, or not found by name, or
- // getCID returned null, we just use the data in the CFF
- // table and hope for the best.
-
-
- // for debugging, force a reparsing
- /*
- java.lang.System.err.println("");
- java.lang.System.err.println("");
- java.lang.System.err.println("");
- CFFFont dummy = new CFFFont(java.nio.ByteBuffer.wrap(b));
- java.lang.System.err.println("");
- java.lang.System.err.println("");
- java.lang.System.err.println("");
- */
- pobj = new StreamFont(b, "CIDFontType0C");
- obj = writer.addToBody(pobj);
- ind_font = obj.getIndirectReference();
- } else {
- byte[] b;
- if (subset || directoryOffset != 0) {
- TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, new RandomAccessFileOrArray(rf), longTag, directoryOffset, false);
- b = sb.process();
- }
- else {
- RandomAccessFileOrArray r = new RandomAccessFileOrArray(rf);
- b = new byte[r.length()];
- r.readFully(b);
- }
- int lengths[] = new int[]{b.length};
- pobj = new StreamFont(b, lengths);
- obj = writer.addToBody(pobj);
- ind_font = obj.getIndirectReference();
- }
- String subsetPrefix = createSubsetPrefix();
- //if (cff) subsetPrefix = "";
- PdfDictionary dic = getFontDescriptor(ind_font, subsetPrefix);
- obj = writer.addToBody(dic);
- ind_font = obj.getIndirectReference();
-
- pobj = getCIDFontType2(ind_font, subsetPrefix, metrics);
- obj = writer.addToBody(pobj);
- ind_font = obj.getIndirectReference();
-
- pobj = getToUnicode(metrics);
- PdfIndirectReference toUnicodeRef = null;
-
- if (pobj != null) {
- obj = writer.addToBody(pobj);
- toUnicodeRef = obj.getIndirectReference();
- }
-
- pobj = getFontBaseType(ind_font, subsetPrefix, toUnicodeRef);
- writer.addToBody(pobj, ref);
- }
-
- /** A forbidden operation. Will throw a null pointer exception.
- * @param text the text
- * @return always null
- */
- byte[] convertToBytes(String text)
- {
- return null;
- }
-
- /**
- * Checks if a character exists in this font.
- * @param c the character to check
- * @return true
if the character has a glyph,
- * false
otherwise
- */
- public boolean charExists(char c) {
- HashMap map = null;
- if (fontSpecific)
- map = cmap10;
- else
- map = cmap31;
- if (map == null)
- return false;
- if (fontSpecific) {
- if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
- return map.get(new Integer(c & 0xff)) != null;
- else
- return false;
- }
- else
- return map.get(new Integer(c)) != null;
- }
-
- /**
- * Sets the character advance.
- * @param c the character
- * @param advance the character advance normalized to 1000 units
- * @return true
if the advance was set,
- * false
otherwise
- */
- public boolean setCharAdvance(char c, int advance) {
- HashMap map = null;
- if (fontSpecific)
- map = cmap10;
- else
- map = cmap31;
- if (map == null)
- return false;
- int m[] = null;
- if (fontSpecific) {
- if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
- m = (int[])map.get(new Integer(c & 0xff));
- else
- return false;
- }
- else
- m = (int[])map.get(new Integer(c));
- if (m == null)
- return false;
- else
- m[1] = advance;
- return true;
- }
-
- public int[] getCharBBox(char c) {
- if (bboxes == null)
- return null;
- HashMap map = null;
- if (fontSpecific)
- map = cmap10;
- else
- map = cmap31;
- if (map == null)
- return null;
- int m[] = null;
- if (fontSpecific) {
- if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
- m = (int[])map.get(new Integer(c & 0xff));
- else
- return null;
- }
- else
- m = (int[])map.get(new Integer(c));
- if (m == null)
- return null;
- return bboxes[m[0]];
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/Type1Font.java pdftk-2.01/java/com/lowagie/text/pdf/Type1Font.java
--- pdftk-1.45/java/com/lowagie/text/pdf/Type1Font.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/Type1Font.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,812 +0,0 @@
-/*
- * $Id: Type1Font.java,v 1.64 2005/07/16 16:49:25 blowagie Exp $
- * $Name: $
- *
- * Copyright 2001, 2002 Paulo Soares
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import com.lowagie.text.DocumentException;
-import java.util.HashMap;
-import java.util.StringTokenizer;
-import com.lowagie.text.pdf.fonts.FontsResourceAnchor;
-import java.io.*;
-
-/** Reads a Type1 font
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-class Type1Font extends BaseFont
-{
- private static FontsResourceAnchor resourceAnchor;
-
- /** The PFB file if the input was made with a byte
array.
- */
- protected byte pfb[];
-/** The Postscript font name.
- */
- private String FontName;
-/** The full name of the font.
- */
- private String FullName;
-/** The family name of the font.
- */
- private String FamilyName;
-/** The weight of the font: normal, bold, etc.
- */
- private String Weight = "";
-/** The italic angle of the font, usually 0.0 or negative.
- */
- private float ItalicAngle = 0.0f;
-/** true
if all the characters have the same
- * width.
- */
- private boolean IsFixedPitch = false;
-/** The character set of the font.
- */
- private String CharacterSet;
-/** The llx of the FontBox.
- */
- private int llx = -50;
-/** The lly of the FontBox.
- */
- private int lly = -200;
-/** The lurx of the FontBox.
- */
- private int urx = 1000;
-/** The ury of the FontBox.
- */
- private int ury = 900;
-/** The underline position.
- */
- private int UnderlinePosition = -100;
-/** The underline thickness.
- */
- private int UnderlineThickness = 50;
-/** The font's encoding name. This encoding is 'StandardEncoding' or
- * 'AdobeStandardEncoding' for a font that can be totally encoded
- * according to the characters names. For all other names the
- * font is treated as symbolic.
- */
- private String EncodingScheme = "FontSpecific";
-/** A variable.
- */
- private int CapHeight = 700;
-/** A variable.
- */
- private int XHeight = 480;
-/** A variable.
- */
- private int Ascender = 800;
-/** A variable.
- */
- private int Descender = -200;
-/** A variable.
- */
- private int StdHW;
-/** A variable.
- */
- private int StdVW = 80;
-
-/** Represents the section CharMetrics in the AFM file. Each
- * value of this array contains a Object[4]
with an
- * Integer, Integer, String and int[]. This is the code, width, name and char bbox.
- * The key is the name of the char and also an Integer with the char number.
- */
- private HashMap CharMetrics = new HashMap();
-/** Represents the section KernPairs in the AFM file. The key is
- * the name of the first character and the value is a Object[]
- * with 2 elements for each kern pair. Position 0 is the name of
- * the second character and position 1 is the kerning distance. This is
- * repeated for all the pairs.
- */
- private HashMap KernPairs = new HashMap();
-/** The file in use.
- */
- private String fileName;
-/** true
if this font is one of the 14 built in fonts.
- */
- private boolean builtinFont = false;
-/** Types of records in a PFB file. ASCII is 1 and BINARY is 2.
- * They have to appear in the PFB file in this sequence.
- */
- private static final int pfbTypes[] = {1, 2, 1};
-
- /** Creates a new Type1 font.
- * @param ttfAfm the AFM file if the input is made with a byte
array
- * @param pfb the PFB file if the input is made with a byte
array
- * @param afmFile the name of one of the 14 built-in fonts or the location of an AFM file. The file must end in '.afm'
- * @param enc the encoding to be applied to this font
- * @param emb true if the font is to be embedded in the PDF
- * @throws DocumentException the AFM file is invalid
- * @throws IOException the AFM file could not be read
- */
- Type1Font(String afmFile, String enc, boolean emb, byte ttfAfm[], byte pfb[]) throws DocumentException, IOException
- {
- if (emb && ttfAfm != null && pfb == null)
- throw new DocumentException("Two byte arrays are needed if the Type1 font is embedded.");
- if (emb && ttfAfm != null)
- this.pfb = pfb;
- encoding = enc;
- embedded = emb;
- fileName = afmFile;
- fontType = FONT_TYPE_T1;
- RandomAccessFileOrArray rf = null;
- InputStream is = null;
- if (BuiltinFonts14.containsKey(afmFile)) {
- embedded = false;
- builtinFont = true;
- byte buf[] = new byte[1024];
- try {
- if (resourceAnchor == null)
- resourceAnchor = new FontsResourceAnchor();
- is = getResourceStream(RESOURCE_PATH + afmFile + ".afm", resourceAnchor.getClass().getClassLoader());
- if (is == null) {
- String msg = afmFile + " not found as resource. (The *.afm files must exist as resources in the package com.lowagie.text.pdf.fonts)";
- System.err.println(msg);
- throw new DocumentException(msg);
- }
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- while (true) {
- int size = is.read(buf);
- if (size < 0)
- break;
- out.write(buf, 0, size);
- }
- buf = out.toByteArray();
- }
- finally {
- if (is != null) {
- try {
- is.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- }
- try {
- rf = new RandomAccessFileOrArray(buf);
- process(rf);
- }
- finally {
- if (rf != null) {
- try {
- rf.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- }
- }
- else if (afmFile.toLowerCase().endsWith(".afm")) {
- try {
- if (ttfAfm == null)
- rf = new RandomAccessFileOrArray(afmFile);
- else
- rf = new RandomAccessFileOrArray(ttfAfm);
- process(rf);
- }
- finally {
- if (rf != null) {
- try {
- rf.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- }
- }
- else if (afmFile.toLowerCase().endsWith(".pfm")) {
- try {
- ByteArrayOutputStream ba = new ByteArrayOutputStream();
- if (ttfAfm == null)
- rf = new RandomAccessFileOrArray(afmFile);
- else
- rf = new RandomAccessFileOrArray(ttfAfm);
- Pfm2afm.convert(rf, ba);
- rf.close();
- rf = new RandomAccessFileOrArray(ba.toByteArray());
- process(rf);
- }
- finally {
- if (rf != null) {
- try {
- rf.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- }
- }
- else
- throw new DocumentException(afmFile + " is not an AFM or PFM font file.");
- try {
- EncodingScheme = EncodingScheme.trim();
- if (EncodingScheme.equals("AdobeStandardEncoding") || EncodingScheme.equals("StandardEncoding")) {
- fontSpecific = false;
- }
- PdfEncodings.convertToBytes(" ", enc); // check if the encoding exists
- createEncoding();
- }
- catch (RuntimeException re) {
- throw re;
- }
- catch (Exception e) {
- throw new DocumentException(e);
- }
- }
-
-/** Gets the width from the font according to the name
or,
- * if the name
is null, meaning it is a symbolic font,
- * the char c
.
- * @param c the char if the font is symbolic
- * @param name the glyph name
- * @return the width of the char
- */
- int getRawWidth(int c, String name) {
- Object metrics[];
- if (name == null) { // font specific
- metrics = (Object[])CharMetrics.get(new Integer(c));
- }
- else {
- if (name.equals(".notdef"))
- return 0;
- metrics = (Object[])CharMetrics.get(name);
- }
- if (metrics != null)
- return ((Integer)(metrics[1])).intValue();
- return 0;
- }
-
-/** Gets the kerning between two Unicode characters. The characters
- * are converted to names and this names are used to find the kerning
- * pairs in the HashMap
KernPairs
.
- * @param char1 the first char
- * @param char2 the second char
- * @return the kerning to be applied
- */
- public int getKerning(char char1, char char2)
- {
- String first = GlyphList.unicodeToName(char1);
- if (first == null)
- return 0;
- String second = GlyphList.unicodeToName(char2);
- if (second == null)
- return 0;
- Object obj[] = (Object[])KernPairs.get(first);
- if (obj == null)
- return 0;
- for (int k = 0; k < obj.length; k += 2) {
- if (second.equals(obj[k]))
- return ((Integer)obj[k + 1]).intValue();
- }
- return 0;
- }
-
-
- /** Reads the font metrics
- * @param rf the AFM file
- * @throws DocumentException the AFM file is invalid
- * @throws IOException the AFM file could not be read
- */
- public void process(RandomAccessFileOrArray rf) throws DocumentException, IOException
- {
- String line;
- boolean isMetrics = false;
- while ((line = rf.readLine()) != null)
- {
- StringTokenizer tok = new StringTokenizer(line);
- if (!tok.hasMoreTokens())
- continue;
- String ident = tok.nextToken();
- if (ident.equals("FontName"))
- FontName = tok.nextToken("\u00ff").substring(1);
- else if (ident.equals("FullName"))
- FullName = tok.nextToken("\u00ff").substring(1);
- else if (ident.equals("FamilyName"))
- FamilyName = tok.nextToken("\u00ff").substring(1);
- else if (ident.equals("Weight"))
- Weight = tok.nextToken("\u00ff").substring(1);
- else if (ident.equals("ItalicAngle"))
- ItalicAngle = Float.valueOf(tok.nextToken()).floatValue();
- else if (ident.equals("IsFixedPitch"))
- IsFixedPitch = tok.nextToken().equals("true");
- else if (ident.equals("CharacterSet"))
- CharacterSet = tok.nextToken("\u00ff").substring(1);
- else if (ident.equals("FontBBox"))
- {
- llx = (int)Float.valueOf(tok.nextToken()).floatValue();
- lly = (int)Float.valueOf(tok.nextToken()).floatValue();
- urx = (int)Float.valueOf(tok.nextToken()).floatValue();
- ury = (int)Float.valueOf(tok.nextToken()).floatValue();
- }
- else if (ident.equals("UnderlinePosition"))
- UnderlinePosition = (int)Float.valueOf(tok.nextToken()).floatValue();
- else if (ident.equals("UnderlineThickness"))
- UnderlineThickness = (int)Float.valueOf(tok.nextToken()).floatValue();
- else if (ident.equals("EncodingScheme"))
- EncodingScheme = tok.nextToken("\u00ff").substring(1);
- else if (ident.equals("CapHeight"))
- CapHeight = (int)Float.valueOf(tok.nextToken()).floatValue();
- else if (ident.equals("XHeight"))
- XHeight = (int)Float.valueOf(tok.nextToken()).floatValue();
- else if (ident.equals("Ascender"))
- Ascender = (int)Float.valueOf(tok.nextToken()).floatValue();
- else if (ident.equals("Descender"))
- Descender = (int)Float.valueOf(tok.nextToken()).floatValue();
- else if (ident.equals("StdHW"))
- StdHW = (int)Float.valueOf(tok.nextToken()).floatValue();
- else if (ident.equals("StdVW"))
- StdVW = (int)Float.valueOf(tok.nextToken()).floatValue();
- else if (ident.equals("StartCharMetrics"))
- {
- isMetrics = true;
- break;
- }
- }
- if (!isMetrics)
- throw new DocumentException("Missing StartCharMetrics in " + fileName);
- while ((line = rf.readLine()) != null)
- {
- StringTokenizer tok = new StringTokenizer(line);
- if (!tok.hasMoreTokens())
- continue;
- String ident = tok.nextToken();
- if (ident.equals("EndCharMetrics"))
- {
- isMetrics = false;
- break;
- }
- Integer C = new Integer(-1);
- Integer WX = new Integer(250);
- String N = "";
- int B[] = null;
-
- tok = new StringTokenizer(line, ";");
- while (tok.hasMoreTokens())
- {
- StringTokenizer tokc = new StringTokenizer(tok.nextToken());
- if (!tokc.hasMoreTokens())
- continue;
- ident = tokc.nextToken();
- if (ident.equals("C"))
- C = Integer.valueOf(tokc.nextToken());
- else if (ident.equals("WX"))
- WX = new Integer(Float.valueOf(tokc.nextToken()).intValue());
- else if (ident.equals("N"))
- N = tokc.nextToken();
- else if (ident.equals("B")) {
- B = new int[]{Integer.parseInt(tokc.nextToken()),
- Integer.parseInt(tokc.nextToken()),
- Integer.parseInt(tokc.nextToken()),
- Integer.parseInt(tokc.nextToken())};
- }
- }
- Object metrics[] = new Object[]{C, WX, N, B};
- if (C.intValue() >= 0)
- CharMetrics.put(C, metrics);
- CharMetrics.put(N, metrics);
- }
- if (isMetrics)
- throw new DocumentException("Missing EndCharMetrics in " + fileName);
- while ((line = rf.readLine()) != null)
- {
- StringTokenizer tok = new StringTokenizer(line);
- if (!tok.hasMoreTokens())
- continue;
- String ident = tok.nextToken();
- if (ident.equals("EndFontMetrics"))
- return;
- if (ident.equals("StartKernPairs"))
- {
- isMetrics = true;
- break;
- }
- }
- if (!isMetrics)
- throw new DocumentException("Missing EndFontMetrics in " + fileName);
- while ((line = rf.readLine()) != null)
- {
- StringTokenizer tok = new StringTokenizer(line);
- if (!tok.hasMoreTokens())
- continue;
- String ident = tok.nextToken();
- if (ident.equals("KPX"))
- {
- String first = tok.nextToken();
- String second = tok.nextToken();
- Integer width = new Integer(Float.valueOf(tok.nextToken()).intValue());
- Object relates[] = (Object[])KernPairs.get(first);
- if (relates == null)
- KernPairs.put(first, new Object[]{second, width});
- else
- {
- int n = relates.length;
- Object relates2[] = new Object[n + 2];
- System.arraycopy(relates, 0, relates2, 0, n);
- relates2[n] = second;
- relates2[n + 1] = width;
- KernPairs.put(first, relates2);
- }
- }
- else if (ident.equals("EndKernPairs"))
- {
- isMetrics = false;
- break;
- }
- }
- if (isMetrics)
- throw new DocumentException("Missing EndKernPairs in " + fileName);
- rf.close();
- }
-
-/** If the embedded flag is false
or if the font is
- * one of the 14 built in types, it returns null
,
- * otherwise the font is read and output in a PdfStream object.
- * @return the PdfStream containing the font or null
- * @throws DocumentException if there is an error reading the font
- */
- private PdfStream getFontStream() throws DocumentException
- {
- if (builtinFont || !embedded)
- return null;
- RandomAccessFileOrArray rf = null;
- try {
- String filePfb = fileName.substring(0, fileName.length() - 3) + "pfb";
- if (pfb == null)
- rf = new RandomAccessFileOrArray(filePfb);
- else
- rf = new RandomAccessFileOrArray(pfb);
- int fileLength = rf.length();
- byte st[] = new byte[fileLength - 18];
- int lengths[] = new int[3];
- int bytePtr = 0;
- for (int k = 0; k < 3; ++k) {
- if (rf.read() != 0x80)
- throw new DocumentException("Start marker missing in " + filePfb);
- if (rf.read() != pfbTypes[k])
- throw new DocumentException("Incorrect segment type in " + filePfb);
- int size = rf.read();
- size += rf.read() << 8;
- size += rf.read() << 16;
- size += rf.read() << 24;
- lengths[k] = size;
- while (size != 0) {
- int got = rf.read(st, bytePtr, size);
- if (got < 0)
- throw new DocumentException("Premature end in " + filePfb);
- bytePtr += got;
- size -= got;
- }
- }
- return new StreamFont(st, lengths);
- }
- catch (Exception e) {
- throw new DocumentException(e);
- }
- finally {
- if (rf != null) {
- try {
- rf.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- }
- }
-
-/** Generates the font descriptor for this font or null
if it is
- * one of the 14 built in fonts.
- * @param fontStream the indirect reference to a PdfStream containing the font or null
- * @return the PdfDictionary containing the font descriptor or null
- */
- private PdfDictionary getFontDescriptor(PdfIndirectReference fontStream)
- {
- if (builtinFont)
- return null;
- PdfDictionary dic = new PdfDictionary(PdfName.FONTDESCRIPTOR);
- dic.put(PdfName.ASCENT, new PdfNumber(Ascender));
- dic.put(PdfName.CAPHEIGHT, new PdfNumber(CapHeight));
- dic.put(PdfName.DESCENT, new PdfNumber(Descender));
- dic.put(PdfName.FONTBBOX, new PdfRectangle(llx, lly, urx, ury));
- dic.put(PdfName.FONTNAME, new PdfName(FontName));
- dic.put(PdfName.ITALICANGLE, new PdfNumber(ItalicAngle));
- dic.put(PdfName.STEMV, new PdfNumber(StdVW));
- if (fontStream != null)
- dic.put(PdfName.FONTFILE, fontStream);
- int flags = 0;
- if (IsFixedPitch)
- flags |= 1;
- flags |= fontSpecific ? 4 : 32;
- if (ItalicAngle < 0)
- flags |= 64;
- if (FontName.indexOf("Caps") >= 0 || FontName.endsWith("SC"))
- flags |= 131072;
- if (Weight.equals("Bold"))
- flags |= 262144;
- dic.put(PdfName.FLAGS, new PdfNumber(flags));
-
- return dic;
- }
-
- /** Generates the font dictionary for this font.
- * @return the PdfDictionary containing the font dictionary
- * @param firstChar the first valid character
- * @param lastChar the last valid character
- * @param shortTag a 256 bytes long byte
array where each unused byte is represented by 0
- * @param fontDescriptor the indirect reference to a PdfDictionary containing the font descriptor or null
- */
- private PdfDictionary getFontBaseType(PdfIndirectReference fontDescriptor, int firstChar, int lastChar, byte shortTag[])
- {
- PdfDictionary dic = new PdfDictionary(PdfName.FONT);
- dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
- dic.put(PdfName.BASEFONT, new PdfName(FontName));
- boolean stdEncoding = encoding.equals("Cp1252") || encoding.equals("MacRoman");
- if (!fontSpecific) {
- for (int k = firstChar; k <= lastChar; ++k) {
- if (!differences[k].equals(notdef)) {
- firstChar = k;
- break;
- }
- }
- if (stdEncoding)
- dic.put(PdfName.ENCODING, encoding.equals("Cp1252") ? PdfName.WIN_ANSI_ENCODING : PdfName.MAC_ROMAN_ENCODING);
- else {
- PdfDictionary enc = new PdfDictionary(PdfName.ENCODING);
- PdfArray dif = new PdfArray();
- boolean gap = true;
- for (int k = firstChar; k <= lastChar; ++k) {
- if (shortTag[k] != 0) {
- if (gap) {
- dif.add(new PdfNumber(k));
- gap = false;
- }
- dif.add(new PdfName(differences[k]));
- }
- else
- gap = true;
- }
- enc.put(PdfName.DIFFERENCES, dif);
- dic.put(PdfName.ENCODING, enc);
- }
- }
- if (forceWidthsOutput || !(builtinFont && (fontSpecific || stdEncoding))) {
- dic.put(PdfName.FIRSTCHAR, new PdfNumber(firstChar));
- dic.put(PdfName.LASTCHAR, new PdfNumber(lastChar));
- PdfArray wd = new PdfArray();
- for (int k = firstChar; k <= lastChar; ++k) {
- if (shortTag[k] == 0)
- wd.add(new PdfNumber(0));
- else
- wd.add(new PdfNumber(widths[k]));
- }
- dic.put(PdfName.WIDTHS, wd);
- }
- if (!builtinFont && fontDescriptor != null)
- dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
- return dic;
- }
-
- /** Outputs to the writer the font dictionaries and streams.
- * @param writer the writer for this document
- * @param ref the font indirect reference
- * @param params several parameters that depend on the font type
- * @throws IOException on error
- * @throws DocumentException error in generating the object
- */
- void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
- int firstChar = ((Integer)params[0]).intValue();
- int lastChar = ((Integer)params[1]).intValue();
- byte shortTag[] = (byte[])params[2];
- if (!subset) {
- firstChar = 0;
- lastChar = shortTag.length - 1;
- for (int k = 0; k < shortTag.length; ++k)
- shortTag[k] = 1;
- }
- PdfIndirectReference ind_font = null;
- PdfObject pobj = null;
- PdfIndirectObject obj = null;
- pobj = getFontStream();
- if (pobj != null){
- obj = writer.addToBody(pobj);
- ind_font = obj.getIndirectReference();
- }
- pobj = getFontDescriptor(ind_font);
- if (pobj != null){
- obj = writer.addToBody(pobj);
- ind_font = obj.getIndirectReference();
- }
- pobj = getFontBaseType(ind_font, firstChar, lastChar, shortTag);
- writer.addToBody(pobj, ref);
- }
-
- /** Gets the font parameter identified by key
. Valid values
- * for key
are ASCENT
, CAPHEIGHT
, DESCENT
,
- * ITALICANGLE
, BBOXLLX
, BBOXLLY
, BBOXURX
- * and BBOXURY
.
- * @param key the parameter to be extracted
- * @param fontSize the font size in points
- * @return the parameter in points
- */
- public float getFontDescriptor(int key, float fontSize) {
- switch (key) {
- case AWT_ASCENT:
- case ASCENT:
- return Ascender * fontSize / 1000;
- case CAPHEIGHT:
- return CapHeight * fontSize / 1000;
- case AWT_DESCENT:
- case DESCENT:
- return Descender * fontSize / 1000;
- case ITALICANGLE:
- return ItalicAngle;
- case BBOXLLX:
- return llx * fontSize / 1000;
- case BBOXLLY:
- return lly * fontSize / 1000;
- case BBOXURX:
- return urx * fontSize / 1000;
- case BBOXURY:
- return ury * fontSize / 1000;
- case AWT_LEADING:
- return 0;
- case AWT_MAXADVANCE:
- return (urx - llx) * fontSize / 1000;
- }
- return 0;
- }
-
- /** Gets the postscript font name.
- * @return the postscript font name
- */
- public String getPostscriptFontName() {
- return FontName;
- }
-
- /** Gets the full name of the font. If it is a True Type font
- * each array element will have {Platform ID, Platform Encoding ID,
- * Language ID, font name}. The interpretation of this values can be
- * found in the Open Type specification, chapter 2, in the 'name' table.
- * For the other fonts the array has a single element with {"", "", "",
- * font name}.
- * @return the full name of the font
- */
- public String[][] getFullFontName() {
- return new String[][]{{"", "", "", FullName}};
- }
-
- /** Gets the family name of the font. If it is a True Type font
- * each array element will have {Platform ID, Platform Encoding ID,
- * Language ID, font name}. The interpretation of this values can be
- * found in the Open Type specification, chapter 2, in the 'name' table.
- * For the other fonts the array has a single element with {"", "", "",
- * font name}.
- * @return the family name of the font
- */
- public String[][] getFamilyFontName() {
- return new String[][]{{"", "", "", FamilyName}};
- }
-
- /** Checks if the font has any kerning pairs.
- * @return true
if the font has any kerning pairs
- */
- public boolean hasKernPairs() {
- return KernPairs.size() > 0;
- }
-
- /**
- * Sets the font name that will appear in the pdf font dictionary.
- * Use with care as it can easily make a font unreadable if not embedded.
- * @param name the new font name
- */
- public void setPostscriptFontName(String name) {
- FontName = name;
- }
-
- /**
- * Sets the kerning between two Unicode chars.
- * @param char1 the first char
- * @param char2 the second char
- * @param kern the kerning to apply in normalized 1000 units
- * @return true
if the kerning was applied, false
otherwise
- */
- public boolean setKerning(char char1, char char2, int kern) {
- String first = GlyphList.unicodeToName(char1);
- if (first == null)
- return false;
- String second = GlyphList.unicodeToName(char2);
- if (second == null)
- return false;
- Object obj[] = (Object[])KernPairs.get(first);
- if (obj == null) {
- obj = new Object[]{second, new Integer(kern)};
- KernPairs.put(first, obj);
- return true;
- }
- for (int k = 0; k < obj.length; k += 2) {
- if (second.equals(obj[k])) {
- obj[k + 1] = new Integer(kern);
- return true;
- }
- }
- int size = obj.length;
- Object obj2[] = new Object[size + 2];
- System.arraycopy(obj, 0, obj2, 0, size);
- obj2[size] = second;
- obj2[size + 1] = new Integer(kern);
- KernPairs.put(first, obj2);
- return true;
- }
-
- protected int[] getRawCharBBox(int c, String name) {
- Object metrics[];
- if (name == null) { // font specific
- metrics = (Object[])CharMetrics.get(new Integer(c));
- }
- else {
- if (name.equals(".notdef"))
- return null;
- metrics = (Object[])CharMetrics.get(name);
- }
- if (metrics != null)
- return ((int[])(metrics[3]));
- return null;
- }
-
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/VerticalText.java pdftk-2.01/java/com/lowagie/text/pdf/VerticalText.java
--- pdftk-1.45/java/com/lowagie/text/pdf/VerticalText.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/VerticalText.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,355 +0,0 @@
-/*
- *
- * Copyright 2002 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-import java.util.ArrayList;
-import java.util.Iterator;
-import com.lowagie.text.Phrase;
-import com.lowagie.text.Chunk;
-import com.lowagie.text.Element;
-import com.lowagie.text.DocumentException;
-import java.awt.Color;
-
-/** Writes text vertically. Note that the naming is done according
- * to horizontal text although it referrs to vertical text.
- * A line with the alignment Element.LEFT_ALIGN will actually
- * be top aligned.
- */
-public class VerticalText {
-
-/** Signals that there are no more text available. */
- public static final int NO_MORE_TEXT = 1;
-
-/** Signals that there is no more column. */
- public static final int NO_MORE_COLUMN = 2;
-
-/** The chunks that form the text. */
- protected ArrayList chunks = new ArrayList();
-
- /** The PdfContent
where the text will be written to. */
- protected PdfContentByte text;
-
- /** The column alignment. Default is left alignment. */
- protected int alignment = Element.ALIGN_LEFT;
-
- /** Marks the chunks to be eliminated when the line is written. */
- protected int currentChunkMarker = -1;
-
- /** The chunk created by the splitting. */
- protected PdfChunk currentStandbyChunk;
-
- /** The chunk created by the splitting. */
- protected String splittedChunkText;
-
- /** The leading
- */
- protected float leading;
-
- /** The X coordinate.
- */
- protected float startX;
-
- /** The Y coordinate.
- */
- protected float startY;
-
- /** The maximum number of vertical lines.
- */
- protected int maxLines;
-
- /** The height of the text.
- */
- protected float height;
-
- /** Creates new VerticalText
- * @param text the place where the text will be written to. Can
- * be a template.
- */
- public VerticalText(PdfContentByte text) {
- this.text = text;
- }
-
- /**
- * Adds a Phrase
to the current text array.
- * @param phrase the text
- */
- public void addText(Phrase phrase) {
- for (Iterator j = phrase.getChunks().iterator(); j.hasNext();) {
- chunks.add(new PdfChunk((Chunk)j.next(), null));
- }
- }
-
- /**
- * Adds a Chunk
to the current text array.
- * @param chunk the text
- */
- public void addText(Chunk chunk) {
- chunks.add(new PdfChunk(chunk, null));
- }
-
- /** Sets the layout.
- * @param startX the top right X line position
- * @param startY the top right Y line position
- * @param height the height of the lines
- * @param maxLines the maximum number of lines
- * @param leading the separation between the lines
- */
- public void setVerticalLayout(float startX, float startY, float height, int maxLines, float leading) {
- this.startX = startX;
- this.startY = startY;
- this.height = height;
- this.maxLines = maxLines;
- setLeading(leading);
- }
-
- /** Sets the separation between the vertical lines.
- * @param leading the vertical line separation
- */
- public void setLeading(float leading) {
- this.leading = leading;
- }
-
- /** Gets the separation between the vertical lines.
- * @return the vertical line separation
- */
- public float getLeading() {
- return leading;
- }
-
- /**
- * Creates a line from the chunk array.
- * @param width the width of the line
- * @return the line or null if no more chunks
- */
- protected PdfLine createLine(float width) {
- if (chunks.size() == 0)
- return null;
- splittedChunkText = null;
- currentStandbyChunk = null;
- PdfLine line = new PdfLine(0, width, alignment, 0);
- String total;
- for (currentChunkMarker = 0; currentChunkMarker < chunks.size(); ++currentChunkMarker) {
- PdfChunk original = (PdfChunk)(chunks.get(currentChunkMarker));
- total = original.toString();
- currentStandbyChunk = line.add(original);
- if (currentStandbyChunk != null) {
- splittedChunkText = original.toString();
- original.setValue(total);
- return line;
- }
- }
- return line;
- }
-
- /**
- * Normalizes the list of chunks when the line is accepted.
- */
- protected void shortenChunkArray() {
- if (currentChunkMarker < 0)
- return;
- if (currentChunkMarker >= chunks.size()) {
- chunks.clear();
- return;
- }
- PdfChunk split = (PdfChunk)(chunks.get(currentChunkMarker));
- split.setValue(splittedChunkText);
- chunks.set(currentChunkMarker, currentStandbyChunk);
- for (int j = currentChunkMarker - 1; j >= 0; --j)
- chunks.remove(j);
- }
-
- /**
- * Outputs the lines to the document. It is equivalent to go(false)
.
- * @return returns the result of the operation. It can be NO_MORE_TEXT
- * and/or NO_MORE_COLUMN
- * @throws DocumentException on error
- */
- public int go() throws DocumentException {
- return go(false);
- }
-
- /**
- * Outputs the lines to the document. The output can be simulated.
- * @param simulate true
to simulate the writting to the document
- * @return returns the result of the operation. It can be NO_MORE_TEXT
- * and/or NO_MORE_COLUMN
- * @throws DocumentException on error
- */
- public int go(boolean simulate) throws DocumentException {
- boolean dirty = false;
- PdfContentByte graphics = null;
- if (text != null) {
- graphics = text.getDuplicate();
- }
- else if (simulate == false)
- throw new NullPointerException("VerticalText.go with simulate==false and text==null.");
- int status = 0;
- for (;;) {
- if (maxLines <= 0) {
- status = NO_MORE_COLUMN;
- if (chunks.size() == 0)
- status |= NO_MORE_TEXT;
- break;
- }
- if (chunks.size() == 0) {
- status = NO_MORE_TEXT;
- break;
- }
- PdfLine line = createLine(height);
- if (!simulate && !dirty) {
- text.beginText();
- dirty = true;
- }
- shortenChunkArray();
- if (!simulate) {
- text.setTextMatrix(startX, startY - line.indentLeft());
- writeLine(line, text, graphics);
- }
- --maxLines;
- startX -= leading;
- }
- if (dirty) {
- text.endText();
- text.add(graphics);
- }
- return status;
- }
-
- void writeLine(PdfLine line, PdfContentByte text, PdfContentByte graphics) throws DocumentException {
- PdfFont currentFont = null;
- PdfChunk chunk;
- for (Iterator j = line.iterator(); j.hasNext(); ) {
- chunk = (PdfChunk) j.next();
-
- if (chunk.font().compareTo(currentFont) != 0) {
- currentFont = chunk.font();
- text.setFontAndSize(currentFont.getFont(), currentFont.size());
- }
- Color color = chunk.color();
- if (color != null)
- text.setColorFill(color);
- text.showText(chunk.toString());
- if (color != null)
- text.resetRGBColorFill();
- }
- }
-
- /** Sets the new text origin.
- * @param startX the X coordinate
- * @param startY the Y coordinate
- */
- public void setOrigin(float startX, float startY) {
- this.startX = startX;
- this.startY = startY;
- }
-
- /** Gets the X coordinate where the next line will be writen. This value will change
- * after each call to go()
.
- * @return the X coordinate
- */
- public float getOriginX() {
- return startX;
- }
-
- /** Gets the Y coordinate where the next line will be writen.
- * @return the Y coordinate
- */
- public float getOriginY() {
- return startY;
- }
-
- /** Gets the maximum number of available lines. This value will change
- * after each call to go()
.
- * @return Value of property maxLines.
- */
- public int getMaxLines() {
- return maxLines;
- }
-
- /** Sets the maximum number of lines.
- * @param maxLines the maximum number of lines
- */
- public void setMaxLines(int maxLines) {
- this.maxLines = maxLines;
- }
-
- /** Gets the height of the line
- * @return the height
- */
- public float getHeight() {
- return height;
- }
-
- /** Sets the height of the line
- * @param height the new height
- */
- public void setHeight(float height) {
- this.height = height;
- }
-
- /**
- * Sets the alignment.
- * @param alignment the alignment
- */
- public void setAlignment(int alignment) {
- this.alignment = alignment;
- }
-
- /**
- * Gets the alignment.
- * @return the alignment
- */
- public int getAlignment() {
- return alignment;
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/XfdfReader.java pdftk-2.01/java/com/lowagie/text/pdf/XfdfReader.java
--- pdftk-1.45/java/com/lowagie/text/pdf/XfdfReader.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/XfdfReader.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,247 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
-/*
- *
- * Copyright 2004 by Leonard Rosenthol.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.pdf;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream; // ssteward
-import java.io.FileInputStream;
-import java.util.HashMap;
-import java.util.Stack;
-
-/**
- * Reads a XFDF.
- * @author Leonard Rosenthol (leonardr@pdfsages.com)
- */
-public class XfdfReader implements SimpleXMLDocHandler {
- // stuff used during parsing to handle state
- private boolean foundRoot = false;
- private Stack fieldNames = new Stack();
- private Stack fieldValues = new Stack();
-
- // storage for the field list and their values
- HashMap fields;
-
- // storage for the field list and their rich text; ssteward
- HashMap fieldsRichText;
-
- // storage for the path to referenced PDF, if any
- String fileSpec;
-
- /** Reads an XFDF form.
- * @param filename the file name of the form
- * @throws IOException on error
- */
- public XfdfReader(String filename) throws IOException {
- InputStream fin = null; // ssteward: was FileInputStream
- try {
- // ssteward: added for stdin handling (also see RandomAccessFileOrArray.java)
- if( filename.equals("-") ) {
- fin = System.in;
- }
- else {
- fin = new FileInputStream(filename);
- }
- SimpleXMLParser.parse(this, fin);
- }
- finally {
- try{fin.close();}catch(Exception e){}
- }
- }
-
- /** Reads an XFDF form.
- * @param xfdfIn the byte array with the form
- * @throws IOException on error
- */
- public XfdfReader(byte xfdfIn[]) throws IOException {
- SimpleXMLParser.parse( this, new ByteArrayInputStream(xfdfIn));
- }
-
- /** Gets all the fields. The map is keyed by the fully qualified
- * field name and the value is a merged PdfDictionary
- * with the field content.
- * @return all the fields
- */
- public HashMap getFields() {
- return fields;
- }
-
- /** Gets the field value.
- * @param name the fully qualified field name
- * @return the field's value
- */
- public String getField(String name) {
- return (String)fields.get(name);
- }
-
- /** Gets the field value or null
if the field does not
- * exist or has no value defined.
- * @param name the fully qualified field name
- * @return the field value or null
- */
- public String getFieldValue(String name) {
- String field = (String)fields.get(name);
- if (field == null)
- return null;
- else
- return field;
- }
-
- // ssteward
- // for parity with FdfReader addition
- public String getFieldRichValue(String name) {
- String field = (String)fieldsRichText.get(name);
- if (field == null)
- return null;
- else
- return field;
- }
-
- /** Gets the PDF file specification contained in the FDF.
- * @return the PDF file specification contained in the FDF
- */
- public String getFileSpec() {
- return fileSpec;
- }
-
- /**
- * Called when a start tag is found.
- * @param tag the tag name
- * @param h the tag's attributes
- */
- public void startElement(String tag, HashMap h)
- {
- if ( !foundRoot ) {
- if (!tag.equals("xfdf"))
- throw new RuntimeException("Root element is not Bookmark.");
- else
- foundRoot = true;
- }
-
- if ( tag.equals("xfdf") ){
-
- } else if ( tag.equals("f") ) {
- fileSpec = (String)h.get( "href" );
- } else if ( tag.equals("fields") ) {
- fields = new HashMap(); // init it!
- fieldsRichText = new HashMap();
- } else if ( tag.equals("field") ) {
- String fName = (String) h.get( "name" );
- fieldNames.push( fName );
- } else if ( tag.equals("value") ||
- tag.equals("value-richtext") ) // ssteward
- {
- fieldValues.push( (String)"" );
- }
- }
-
- /**
- * Called when an end tag is found.
- * @param tag the tag name
- */
- public void endElement(String tag) {
- if ( tag.equals("value") ||
- tag.equals("value-richtext") ) // ssteward
- {
- String fName = "";
- for (int k = 0; k < fieldNames.size(); ++k) {
- fName += "." + (String)fieldNames.elementAt(k);
- }
- if (fName.startsWith("."))
- fName = fName.substring(1);
- String fVal = (String) fieldValues.pop();
-
- if (tag.equals("value")) { // ssteward
- fields.put( fName, fVal );
- }
- else { // rich text value
- fieldsRichText.put( fName, fVal );
- }
- }
- else if (tag.equals("field") ) {
- if (!fieldNames.isEmpty())
- fieldNames.pop();
- }
- }
-
- /**
- * Called when the document starts to be parsed.
- */
- public void startDocument()
- {
- fileSpec = new String(""); // and this too...
- }
- /**
- * Called after the document is parsed.
- */
- public void endDocument()
- {
-
- }
- /**
- * Called when a text element is found.
- * @param str the text element, probably a fragment.
- */
- public void text(String str)
- {
- if (fieldNames.isEmpty() || fieldValues.isEmpty())
- return;
-
- String val = (String)fieldValues.pop();
- val += str;
- fieldValues.push(val);
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/codec/Makefile pdftk-2.01/java/com/lowagie/text/pdf/codec/Makefile
--- pdftk-1.45/java/com/lowagie/text/pdf/codec/Makefile 2010-09-15 09:42:40.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/codec/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-library= codec.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-all : $(library) $(headers)
-
-$(library) : $(objects)
- $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/codec/postscript/Makefile pdftk-2.01/java/com/lowagie/text/pdf/codec/postscript/Makefile
--- pdftk-1.45/java/com/lowagie/text/pdf/codec/postscript/Makefile 2010-09-15 09:42:48.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/codec/postscript/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-library= postscript.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-all : $(library) $(headers)
-
-$(library) : $(objects)
- $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/codec/postscript/paparser.jj pdftk-2.01/java/com/lowagie/text/pdf/codec/postscript/paparser.jj
--- pdftk-1.45/java/com/lowagie/text/pdf/codec/postscript/paparser.jj 2005-02-28 17:31:28.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/codec/postscript/paparser.jj 1970-01-01 00:00:00.000000000 +0000
@@ -1,289 +0,0 @@
-options {
- LOOKAHEAD=1;
- JAVA_UNICODE_ESCAPE = true;
- STATIC = false;
-}
-
-PARSER_BEGIN(PAParser)
-
-package com.lowagie.text.pdf.codec.postscript;
-
-import java.lang.*;
-import java.lang.reflect.*;
-import java.util.*;
-import java.awt.*;
-import java.awt.geom.*;
-import java.awt.color.*;
-import java.awt.font.*;
-
-import java.io.*;
-import java.net.URL;
-
-public class PAParser extends Object {
-
-}
-
-PARSER_END(PAParser)
-
-
-/* WHITE SPACE */
-
-SKIP :
-{
- < WHITESPACE: " " | "\t" | "\n" | "\r" | "\f" >
-|
- < "%" ( ~["\n"] )* "\n" >
- |
- < "%" ( ~["\r"] )* "\r" >
-}
-
-/* LITERALS */
-
-TOKEN :
-{
- < INTEGER_LITERAL:
- ("-")? ( (["l","L"])?
- | (["l","L"])?
- )
- >
-|
- < #DECIMAL_LITERAL: ["0"-"9"] (["0"-"9"])* >
-|
- < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
-|
- < FLOATING_POINT_LITERAL:
- ((["0"-"9"])+ "." (["0"-"9"])* ()? (["f","F","d","D"])?)
- | ("." (["0"-"9"])+ ()? (["f","F","d","D"])?)
- | ((["0"-"9"])+ (["f","F","d","D"])?)
- | ((["0"-"9"])+ ()? ["f","F","d","D"])
- | ("-" (["0"-"9"])+ "." (["0"-"9"])* ()? (["f","F","d","D"])?)
- | ("-" "." (["0"-"9"])+ ()? (["f","F","d","D"])?)
- | ("-" (["0"-"9"])+ (["f","F","d","D"])?)
- | ("-" (["0"-"9"])+ ()? ["f","F","d","D"])
- >
-|
- < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
-|
- < STRING_LITERAL:
- "("
- ( (~[")","\\","\n","\r"])
- | ("\\"
- ( ["n","t","b","r","f","\\","'",")", "\n"]
- | ["0"-"7"] ( ["0"-"7"] )?
- | ["0"-"3"] ["0"-"7"] ["0"-"7"]
- )
- )
- )*
- ")"
- >
-}
-
-/* IDENTIFIERS */
-
-TOKEN :
-{
- < IDENTIFIER: (||"-"|".")* >
-|
- < KEY_IDENTIFIER: "/" >
-|
- < IMMEDIATE_IDENTIFIER: "//" >
-|
- < #LETTER:
- [
- "\u0024",
- "\u0041"-"\u005a",
- "\u005f",
- "\u0061"-"\u007a",
- "\u00c0"-"\u00d6",
- "\u00d8"-"\u00f6",
- "\u00f8"-"\u00ff",
- "\u0100"-"\u1fff",
- "\u3040"-"\u318f",
- "\u3300"-"\u337f",
- "\u3400"-"\u3d2d",
- "\u4e00"-"\u9fff",
- "\uf900"-"\ufaff"
- ]
- >
-|
- < #DIGIT:
- [
- "\u0030"-"\u0039",
- "\u0660"-"\u0669",
- "\u06f0"-"\u06f9",
- "\u0966"-"\u096f",
- "\u09e6"-"\u09ef",
- "\u0a66"-"\u0a6f",
- "\u0ae6"-"\u0aef",
- "\u0b66"-"\u0b6f",
- "\u0be7"-"\u0bef",
- "\u0c66"-"\u0c6f",
- "\u0ce6"-"\u0cef",
- "\u0d66"-"\u0d6f",
- "\u0e50"-"\u0e59",
- "\u0ed0"-"\u0ed9",
- "\u1040"-"\u1049"
- ]
- >
-}
-
-/* SEPARATORS */
-
-TOKEN :
-{
-
- < LBRACE: "{" >
-| < RBRACE: "}" >
-| < LBRACKET: "[" >
-| < RBRACKET: "]" >
-
-}
-
-JAVACODE
-void error_skipto(int kind){
-ParseException e=generateParseException();
-Token t;
-String dump="";
-do{
-if(getToken(1).kind==kind)break;
-t=getNextToken();
-dump+=t.image;
-}while(t.kind!=kind);
-System.out.println("Ignoriere >"+dump+"<");
-}
-
-
-void parse(PAContext context) :
-{
- Token x = null;
-}
-{
- try{
- (
- (
- ( (
- x =
- {
- try {
- context.engine.process(new Integer(x.image));
- } catch(NumberFormatException e) {
- throw new ParseException(e.toString());
- } catch(PainterException e) {
- throw new ParseException(e.toString());
- }
- }
- )
- |
- (
- x =
- {
- try {
- context.engine.process(new Double(x.image));
- } catch(NumberFormatException e) {
- throw new ParseException(e.toString());
- } catch(PainterException e) {
- throw new ParseException(e.toString());
- }
- }
- )
- |
- (
- x =
- {
- try {
- context.engine.process(x.image.substring(1, x.image.length() -1));
- } catch(PainterException e) {
- throw new ParseException(e.toString());
- }
- }
- )
- |
- (
- x =
- {
- try {
- context.engine.process(new PAToken(x.image, PAToken.IDENTIFIER));
- } catch(PainterException e) {
- throw new ParseException(e.toString());
- }
- }
- )
- |
- (
- x =
- {
- try {
- context.engine.process(new PAToken(x.image.substring(1, x.image.length()), PAToken.KEY));
- } catch(PainterException e) {
- throw new ParseException(e.toString());
- }
- }
- )
- |
- (
- x =
- {
- try {
- context.engine.process(new PAToken(x.image.substring(2, x.image.length()), PAToken.IMMEDIATE));
- } catch(PainterException e) {
- throw new ParseException(e.toString());
- }
- }
- ) )
- |
- (
-
- {
- try {
- context.engine.process(new PAToken(null, PAToken.START_PROCEDURE));
- } catch(PainterException e) {
- throw new ParseException(e.toString());
- }
- }
- )
- |
- (
-
- {
- try {
- context.engine.process(new PAToken(null, PAToken.END_PROCEDURE));
- } catch(PainterException e) {
- throw new ParseException(e.toString());
- }
- }
- )
- |
- (
-
- {
- try {
- context.engine.process(new PAToken(null, PAToken.START_ARRAY));
- } catch(PainterException e) {
- throw new ParseException(e.toString());
- }
- }
- )
- |
- (
-
- {
- try {
- context.engine.process(new PAToken(null, PAToken.END_ARRAY));
- } catch(PainterException e) {
- throw new ParseException(e.toString());
- }
- }
- )
- )//{System.out.println(">>>"+token.image+"");System.out.flush();}
- )*
-
- }catch(ParseException e){
- //System.out.println("Fehlerhaftes Element in Spalte "+e.currentToken.beginColumn+" in Eingabedatei in Zeile="+e.currentToken.next.beginLine+" in Zeichen Nr. "+e.currentToken.next.beginColumn+". >"+e.currentToken.next.image+"< wurde hier nicht erwartet.");
- //System.err.println("Fehler:"+e);
- e.printStackTrace();
- error_skipto(WHITESPACE);
- }
-}
-
-
-
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Courier-Bold.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Courier-Bold.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Courier-Bold.afm 2004-05-26 16:06:20.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Courier-Bold.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,342 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Mon Jun 23 16:28:00 1997
-Comment UniqueID 43048
-Comment VMusage 41139 52164
-FontName Courier-Bold
-FullName Courier Bold
-FamilyName Courier
-Weight Bold
-ItalicAngle 0
-IsFixedPitch true
-CharacterSet ExtendedRoman
-FontBBox -113 -250 749 801
-UnderlinePosition -100
-UnderlineThickness 50
-Version 003.000
-Notice Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
-EncodingScheme AdobeStandardEncoding
-CapHeight 562
-XHeight 439
-Ascender 629
-Descender -157
-StdHW 84
-StdVW 106
-StartCharMetrics 315
-C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 600 ; N exclam ; B 202 -15 398 572 ;
-C 34 ; WX 600 ; N quotedbl ; B 135 277 465 562 ;
-C 35 ; WX 600 ; N numbersign ; B 56 -45 544 651 ;
-C 36 ; WX 600 ; N dollar ; B 82 -126 519 666 ;
-C 37 ; WX 600 ; N percent ; B 5 -15 595 616 ;
-C 38 ; WX 600 ; N ampersand ; B 36 -15 546 543 ;
-C 39 ; WX 600 ; N quoteright ; B 171 277 423 562 ;
-C 40 ; WX 600 ; N parenleft ; B 219 -102 461 616 ;
-C 41 ; WX 600 ; N parenright ; B 139 -102 381 616 ;
-C 42 ; WX 600 ; N asterisk ; B 91 219 509 601 ;
-C 43 ; WX 600 ; N plus ; B 71 39 529 478 ;
-C 44 ; WX 600 ; N comma ; B 123 -111 393 174 ;
-C 45 ; WX 600 ; N hyphen ; B 100 203 500 313 ;
-C 46 ; WX 600 ; N period ; B 192 -15 408 171 ;
-C 47 ; WX 600 ; N slash ; B 98 -77 502 626 ;
-C 48 ; WX 600 ; N zero ; B 87 -15 513 616 ;
-C 49 ; WX 600 ; N one ; B 81 0 539 616 ;
-C 50 ; WX 600 ; N two ; B 61 0 499 616 ;
-C 51 ; WX 600 ; N three ; B 63 -15 501 616 ;
-C 52 ; WX 600 ; N four ; B 53 0 507 616 ;
-C 53 ; WX 600 ; N five ; B 70 -15 521 601 ;
-C 54 ; WX 600 ; N six ; B 90 -15 521 616 ;
-C 55 ; WX 600 ; N seven ; B 55 0 494 601 ;
-C 56 ; WX 600 ; N eight ; B 83 -15 517 616 ;
-C 57 ; WX 600 ; N nine ; B 79 -15 510 616 ;
-C 58 ; WX 600 ; N colon ; B 191 -15 407 425 ;
-C 59 ; WX 600 ; N semicolon ; B 123 -111 408 425 ;
-C 60 ; WX 600 ; N less ; B 66 15 523 501 ;
-C 61 ; WX 600 ; N equal ; B 71 118 529 398 ;
-C 62 ; WX 600 ; N greater ; B 77 15 534 501 ;
-C 63 ; WX 600 ; N question ; B 98 -14 501 580 ;
-C 64 ; WX 600 ; N at ; B 16 -15 584 616 ;
-C 65 ; WX 600 ; N A ; B -9 0 609 562 ;
-C 66 ; WX 600 ; N B ; B 30 0 573 562 ;
-C 67 ; WX 600 ; N C ; B 22 -18 560 580 ;
-C 68 ; WX 600 ; N D ; B 30 0 594 562 ;
-C 69 ; WX 600 ; N E ; B 25 0 560 562 ;
-C 70 ; WX 600 ; N F ; B 39 0 570 562 ;
-C 71 ; WX 600 ; N G ; B 22 -18 594 580 ;
-C 72 ; WX 600 ; N H ; B 20 0 580 562 ;
-C 73 ; WX 600 ; N I ; B 77 0 523 562 ;
-C 74 ; WX 600 ; N J ; B 37 -18 601 562 ;
-C 75 ; WX 600 ; N K ; B 21 0 599 562 ;
-C 76 ; WX 600 ; N L ; B 39 0 578 562 ;
-C 77 ; WX 600 ; N M ; B -2 0 602 562 ;
-C 78 ; WX 600 ; N N ; B 8 -12 610 562 ;
-C 79 ; WX 600 ; N O ; B 22 -18 578 580 ;
-C 80 ; WX 600 ; N P ; B 48 0 559 562 ;
-C 81 ; WX 600 ; N Q ; B 32 -138 578 580 ;
-C 82 ; WX 600 ; N R ; B 24 0 599 562 ;
-C 83 ; WX 600 ; N S ; B 47 -22 553 582 ;
-C 84 ; WX 600 ; N T ; B 21 0 579 562 ;
-C 85 ; WX 600 ; N U ; B 4 -18 596 562 ;
-C 86 ; WX 600 ; N V ; B -13 0 613 562 ;
-C 87 ; WX 600 ; N W ; B -18 0 618 562 ;
-C 88 ; WX 600 ; N X ; B 12 0 588 562 ;
-C 89 ; WX 600 ; N Y ; B 12 0 589 562 ;
-C 90 ; WX 600 ; N Z ; B 62 0 539 562 ;
-C 91 ; WX 600 ; N bracketleft ; B 245 -102 475 616 ;
-C 92 ; WX 600 ; N backslash ; B 99 -77 503 626 ;
-C 93 ; WX 600 ; N bracketright ; B 125 -102 355 616 ;
-C 94 ; WX 600 ; N asciicircum ; B 108 250 492 616 ;
-C 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ;
-C 96 ; WX 600 ; N quoteleft ; B 178 277 428 562 ;
-C 97 ; WX 600 ; N a ; B 35 -15 570 454 ;
-C 98 ; WX 600 ; N b ; B 0 -15 584 626 ;
-C 99 ; WX 600 ; N c ; B 40 -15 545 459 ;
-C 100 ; WX 600 ; N d ; B 20 -15 591 626 ;
-C 101 ; WX 600 ; N e ; B 40 -15 563 454 ;
-C 102 ; WX 600 ; N f ; B 83 0 547 626 ; L i fi ; L l fl ;
-C 103 ; WX 600 ; N g ; B 30 -146 580 454 ;
-C 104 ; WX 600 ; N h ; B 5 0 592 626 ;
-C 105 ; WX 600 ; N i ; B 77 0 523 658 ;
-C 106 ; WX 600 ; N j ; B 63 -146 440 658 ;
-C 107 ; WX 600 ; N k ; B 20 0 585 626 ;
-C 108 ; WX 600 ; N l ; B 77 0 523 626 ;
-C 109 ; WX 600 ; N m ; B -22 0 626 454 ;
-C 110 ; WX 600 ; N n ; B 18 0 592 454 ;
-C 111 ; WX 600 ; N o ; B 30 -15 570 454 ;
-C 112 ; WX 600 ; N p ; B -1 -142 570 454 ;
-C 113 ; WX 600 ; N q ; B 20 -142 591 454 ;
-C 114 ; WX 600 ; N r ; B 47 0 580 454 ;
-C 115 ; WX 600 ; N s ; B 68 -17 535 459 ;
-C 116 ; WX 600 ; N t ; B 47 -15 532 562 ;
-C 117 ; WX 600 ; N u ; B -1 -15 569 439 ;
-C 118 ; WX 600 ; N v ; B -1 0 601 439 ;
-C 119 ; WX 600 ; N w ; B -18 0 618 439 ;
-C 120 ; WX 600 ; N x ; B 6 0 594 439 ;
-C 121 ; WX 600 ; N y ; B -4 -142 601 439 ;
-C 122 ; WX 600 ; N z ; B 81 0 520 439 ;
-C 123 ; WX 600 ; N braceleft ; B 160 -102 464 616 ;
-C 124 ; WX 600 ; N bar ; B 255 -250 345 750 ;
-C 125 ; WX 600 ; N braceright ; B 136 -102 440 616 ;
-C 126 ; WX 600 ; N asciitilde ; B 71 153 530 356 ;
-C 161 ; WX 600 ; N exclamdown ; B 202 -146 398 449 ;
-C 162 ; WX 600 ; N cent ; B 66 -49 518 614 ;
-C 163 ; WX 600 ; N sterling ; B 72 -28 558 611 ;
-C 164 ; WX 600 ; N fraction ; B 25 -60 576 661 ;
-C 165 ; WX 600 ; N yen ; B 10 0 590 562 ;
-C 166 ; WX 600 ; N florin ; B -30 -131 572 616 ;
-C 167 ; WX 600 ; N section ; B 83 -70 517 580 ;
-C 168 ; WX 600 ; N currency ; B 54 49 546 517 ;
-C 169 ; WX 600 ; N quotesingle ; B 227 277 373 562 ;
-C 170 ; WX 600 ; N quotedblleft ; B 71 277 535 562 ;
-C 171 ; WX 600 ; N guillemotleft ; B 8 70 553 446 ;
-C 172 ; WX 600 ; N guilsinglleft ; B 141 70 459 446 ;
-C 173 ; WX 600 ; N guilsinglright ; B 141 70 459 446 ;
-C 174 ; WX 600 ; N fi ; B 12 0 593 626 ;
-C 175 ; WX 600 ; N fl ; B 12 0 593 626 ;
-C 177 ; WX 600 ; N endash ; B 65 203 535 313 ;
-C 178 ; WX 600 ; N dagger ; B 106 -70 494 580 ;
-C 179 ; WX 600 ; N daggerdbl ; B 106 -70 494 580 ;
-C 180 ; WX 600 ; N periodcentered ; B 196 165 404 351 ;
-C 182 ; WX 600 ; N paragraph ; B 6 -70 576 580 ;
-C 183 ; WX 600 ; N bullet ; B 140 132 460 430 ;
-C 184 ; WX 600 ; N quotesinglbase ; B 175 -142 427 143 ;
-C 185 ; WX 600 ; N quotedblbase ; B 65 -142 529 143 ;
-C 186 ; WX 600 ; N quotedblright ; B 61 277 525 562 ;
-C 187 ; WX 600 ; N guillemotright ; B 47 70 592 446 ;
-C 188 ; WX 600 ; N ellipsis ; B 26 -15 574 116 ;
-C 189 ; WX 600 ; N perthousand ; B -113 -15 713 616 ;
-C 191 ; WX 600 ; N questiondown ; B 99 -146 502 449 ;
-C 193 ; WX 600 ; N grave ; B 132 508 395 661 ;
-C 194 ; WX 600 ; N acute ; B 205 508 468 661 ;
-C 195 ; WX 600 ; N circumflex ; B 103 483 497 657 ;
-C 196 ; WX 600 ; N tilde ; B 89 493 512 636 ;
-C 197 ; WX 600 ; N macron ; B 88 505 512 585 ;
-C 198 ; WX 600 ; N breve ; B 83 468 517 631 ;
-C 199 ; WX 600 ; N dotaccent ; B 230 498 370 638 ;
-C 200 ; WX 600 ; N dieresis ; B 128 498 472 638 ;
-C 202 ; WX 600 ; N ring ; B 198 481 402 678 ;
-C 203 ; WX 600 ; N cedilla ; B 205 -206 387 0 ;
-C 205 ; WX 600 ; N hungarumlaut ; B 68 488 588 661 ;
-C 206 ; WX 600 ; N ogonek ; B 169 -199 400 0 ;
-C 207 ; WX 600 ; N caron ; B 103 493 497 667 ;
-C 208 ; WX 600 ; N emdash ; B -10 203 610 313 ;
-C 225 ; WX 600 ; N AE ; B -29 0 602 562 ;
-C 227 ; WX 600 ; N ordfeminine ; B 147 196 453 580 ;
-C 232 ; WX 600 ; N Lslash ; B 39 0 578 562 ;
-C 233 ; WX 600 ; N Oslash ; B 22 -22 578 584 ;
-C 234 ; WX 600 ; N OE ; B -25 0 595 562 ;
-C 235 ; WX 600 ; N ordmasculine ; B 147 196 453 580 ;
-C 241 ; WX 600 ; N ae ; B -4 -15 601 454 ;
-C 245 ; WX 600 ; N dotlessi ; B 77 0 523 439 ;
-C 248 ; WX 600 ; N lslash ; B 77 0 523 626 ;
-C 249 ; WX 600 ; N oslash ; B 30 -24 570 463 ;
-C 250 ; WX 600 ; N oe ; B -18 -15 611 454 ;
-C 251 ; WX 600 ; N germandbls ; B 22 -15 596 626 ;
-C -1 ; WX 600 ; N Idieresis ; B 77 0 523 761 ;
-C -1 ; WX 600 ; N eacute ; B 40 -15 563 661 ;
-C -1 ; WX 600 ; N abreve ; B 35 -15 570 661 ;
-C -1 ; WX 600 ; N uhungarumlaut ; B -1 -15 628 661 ;
-C -1 ; WX 600 ; N ecaron ; B 40 -15 563 667 ;
-C -1 ; WX 600 ; N Ydieresis ; B 12 0 589 761 ;
-C -1 ; WX 600 ; N divide ; B 71 16 529 500 ;
-C -1 ; WX 600 ; N Yacute ; B 12 0 589 784 ;
-C -1 ; WX 600 ; N Acircumflex ; B -9 0 609 780 ;
-C -1 ; WX 600 ; N aacute ; B 35 -15 570 661 ;
-C -1 ; WX 600 ; N Ucircumflex ; B 4 -18 596 780 ;
-C -1 ; WX 600 ; N yacute ; B -4 -142 601 661 ;
-C -1 ; WX 600 ; N scommaaccent ; B 68 -250 535 459 ;
-C -1 ; WX 600 ; N ecircumflex ; B 40 -15 563 657 ;
-C -1 ; WX 600 ; N Uring ; B 4 -18 596 801 ;
-C -1 ; WX 600 ; N Udieresis ; B 4 -18 596 761 ;
-C -1 ; WX 600 ; N aogonek ; B 35 -199 586 454 ;
-C -1 ; WX 600 ; N Uacute ; B 4 -18 596 784 ;
-C -1 ; WX 600 ; N uogonek ; B -1 -199 585 439 ;
-C -1 ; WX 600 ; N Edieresis ; B 25 0 560 761 ;
-C -1 ; WX 600 ; N Dcroat ; B 30 0 594 562 ;
-C -1 ; WX 600 ; N commaaccent ; B 205 -250 397 -57 ;
-C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ;
-C -1 ; WX 600 ; N Emacron ; B 25 0 560 708 ;
-C -1 ; WX 600 ; N ccaron ; B 40 -15 545 667 ;
-C -1 ; WX 600 ; N aring ; B 35 -15 570 678 ;
-C -1 ; WX 600 ; N Ncommaaccent ; B 8 -250 610 562 ;
-C -1 ; WX 600 ; N lacute ; B 77 0 523 801 ;
-C -1 ; WX 600 ; N agrave ; B 35 -15 570 661 ;
-C -1 ; WX 600 ; N Tcommaaccent ; B 21 -250 579 562 ;
-C -1 ; WX 600 ; N Cacute ; B 22 -18 560 784 ;
-C -1 ; WX 600 ; N atilde ; B 35 -15 570 636 ;
-C -1 ; WX 600 ; N Edotaccent ; B 25 0 560 761 ;
-C -1 ; WX 600 ; N scaron ; B 68 -17 535 667 ;
-C -1 ; WX 600 ; N scedilla ; B 68 -206 535 459 ;
-C -1 ; WX 600 ; N iacute ; B 77 0 523 661 ;
-C -1 ; WX 600 ; N lozenge ; B 66 0 534 740 ;
-C -1 ; WX 600 ; N Rcaron ; B 24 0 599 790 ;
-C -1 ; WX 600 ; N Gcommaaccent ; B 22 -250 594 580 ;
-C -1 ; WX 600 ; N ucircumflex ; B -1 -15 569 657 ;
-C -1 ; WX 600 ; N acircumflex ; B 35 -15 570 657 ;
-C -1 ; WX 600 ; N Amacron ; B -9 0 609 708 ;
-C -1 ; WX 600 ; N rcaron ; B 47 0 580 667 ;
-C -1 ; WX 600 ; N ccedilla ; B 40 -206 545 459 ;
-C -1 ; WX 600 ; N Zdotaccent ; B 62 0 539 761 ;
-C -1 ; WX 600 ; N Thorn ; B 48 0 557 562 ;
-C -1 ; WX 600 ; N Omacron ; B 22 -18 578 708 ;
-C -1 ; WX 600 ; N Racute ; B 24 0 599 784 ;
-C -1 ; WX 600 ; N Sacute ; B 47 -22 553 784 ;
-C -1 ; WX 600 ; N dcaron ; B 20 -15 727 626 ;
-C -1 ; WX 600 ; N Umacron ; B 4 -18 596 708 ;
-C -1 ; WX 600 ; N uring ; B -1 -15 569 678 ;
-C -1 ; WX 600 ; N threesuperior ; B 138 222 433 616 ;
-C -1 ; WX 600 ; N Ograve ; B 22 -18 578 784 ;
-C -1 ; WX 600 ; N Agrave ; B -9 0 609 784 ;
-C -1 ; WX 600 ; N Abreve ; B -9 0 609 784 ;
-C -1 ; WX 600 ; N multiply ; B 81 39 520 478 ;
-C -1 ; WX 600 ; N uacute ; B -1 -15 569 661 ;
-C -1 ; WX 600 ; N Tcaron ; B 21 0 579 790 ;
-C -1 ; WX 600 ; N partialdiff ; B 63 -38 537 728 ;
-C -1 ; WX 600 ; N ydieresis ; B -4 -142 601 638 ;
-C -1 ; WX 600 ; N Nacute ; B 8 -12 610 784 ;
-C -1 ; WX 600 ; N icircumflex ; B 73 0 523 657 ;
-C -1 ; WX 600 ; N Ecircumflex ; B 25 0 560 780 ;
-C -1 ; WX 600 ; N adieresis ; B 35 -15 570 638 ;
-C -1 ; WX 600 ; N edieresis ; B 40 -15 563 638 ;
-C -1 ; WX 600 ; N cacute ; B 40 -15 545 661 ;
-C -1 ; WX 600 ; N nacute ; B 18 0 592 661 ;
-C -1 ; WX 600 ; N umacron ; B -1 -15 569 585 ;
-C -1 ; WX 600 ; N Ncaron ; B 8 -12 610 790 ;
-C -1 ; WX 600 ; N Iacute ; B 77 0 523 784 ;
-C -1 ; WX 600 ; N plusminus ; B 71 24 529 515 ;
-C -1 ; WX 600 ; N brokenbar ; B 255 -175 345 675 ;
-C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ;
-C -1 ; WX 600 ; N Gbreve ; B 22 -18 594 784 ;
-C -1 ; WX 600 ; N Idotaccent ; B 77 0 523 761 ;
-C -1 ; WX 600 ; N summation ; B 15 -10 586 706 ;
-C -1 ; WX 600 ; N Egrave ; B 25 0 560 784 ;
-C -1 ; WX 600 ; N racute ; B 47 0 580 661 ;
-C -1 ; WX 600 ; N omacron ; B 30 -15 570 585 ;
-C -1 ; WX 600 ; N Zacute ; B 62 0 539 784 ;
-C -1 ; WX 600 ; N Zcaron ; B 62 0 539 790 ;
-C -1 ; WX 600 ; N greaterequal ; B 26 0 523 696 ;
-C -1 ; WX 600 ; N Eth ; B 30 0 594 562 ;
-C -1 ; WX 600 ; N Ccedilla ; B 22 -206 560 580 ;
-C -1 ; WX 600 ; N lcommaaccent ; B 77 -250 523 626 ;
-C -1 ; WX 600 ; N tcaron ; B 47 -15 532 703 ;
-C -1 ; WX 600 ; N eogonek ; B 40 -199 563 454 ;
-C -1 ; WX 600 ; N Uogonek ; B 4 -199 596 562 ;
-C -1 ; WX 600 ; N Aacute ; B -9 0 609 784 ;
-C -1 ; WX 600 ; N Adieresis ; B -9 0 609 761 ;
-C -1 ; WX 600 ; N egrave ; B 40 -15 563 661 ;
-C -1 ; WX 600 ; N zacute ; B 81 0 520 661 ;
-C -1 ; WX 600 ; N iogonek ; B 77 -199 523 658 ;
-C -1 ; WX 600 ; N Oacute ; B 22 -18 578 784 ;
-C -1 ; WX 600 ; N oacute ; B 30 -15 570 661 ;
-C -1 ; WX 600 ; N amacron ; B 35 -15 570 585 ;
-C -1 ; WX 600 ; N sacute ; B 68 -17 535 661 ;
-C -1 ; WX 600 ; N idieresis ; B 77 0 523 618 ;
-C -1 ; WX 600 ; N Ocircumflex ; B 22 -18 578 780 ;
-C -1 ; WX 600 ; N Ugrave ; B 4 -18 596 784 ;
-C -1 ; WX 600 ; N Delta ; B 6 0 594 688 ;
-C -1 ; WX 600 ; N thorn ; B -14 -142 570 626 ;
-C -1 ; WX 600 ; N twosuperior ; B 143 230 436 616 ;
-C -1 ; WX 600 ; N Odieresis ; B 22 -18 578 761 ;
-C -1 ; WX 600 ; N mu ; B -1 -142 569 439 ;
-C -1 ; WX 600 ; N igrave ; B 77 0 523 661 ;
-C -1 ; WX 600 ; N ohungarumlaut ; B 30 -15 668 661 ;
-C -1 ; WX 600 ; N Eogonek ; B 25 -199 576 562 ;
-C -1 ; WX 600 ; N dcroat ; B 20 -15 591 626 ;
-C -1 ; WX 600 ; N threequarters ; B -47 -60 648 661 ;
-C -1 ; WX 600 ; N Scedilla ; B 47 -206 553 582 ;
-C -1 ; WX 600 ; N lcaron ; B 77 0 597 626 ;
-C -1 ; WX 600 ; N Kcommaaccent ; B 21 -250 599 562 ;
-C -1 ; WX 600 ; N Lacute ; B 39 0 578 784 ;
-C -1 ; WX 600 ; N trademark ; B -9 230 749 562 ;
-C -1 ; WX 600 ; N edotaccent ; B 40 -15 563 638 ;
-C -1 ; WX 600 ; N Igrave ; B 77 0 523 784 ;
-C -1 ; WX 600 ; N Imacron ; B 77 0 523 708 ;
-C -1 ; WX 600 ; N Lcaron ; B 39 0 637 562 ;
-C -1 ; WX 600 ; N onehalf ; B -47 -60 648 661 ;
-C -1 ; WX 600 ; N lessequal ; B 26 0 523 696 ;
-C -1 ; WX 600 ; N ocircumflex ; B 30 -15 570 657 ;
-C -1 ; WX 600 ; N ntilde ; B 18 0 592 636 ;
-C -1 ; WX 600 ; N Uhungarumlaut ; B 4 -18 638 784 ;
-C -1 ; WX 600 ; N Eacute ; B 25 0 560 784 ;
-C -1 ; WX 600 ; N emacron ; B 40 -15 563 585 ;
-C -1 ; WX 600 ; N gbreve ; B 30 -146 580 661 ;
-C -1 ; WX 600 ; N onequarter ; B -56 -60 656 661 ;
-C -1 ; WX 600 ; N Scaron ; B 47 -22 553 790 ;
-C -1 ; WX 600 ; N Scommaaccent ; B 47 -250 553 582 ;
-C -1 ; WX 600 ; N Ohungarumlaut ; B 22 -18 628 784 ;
-C -1 ; WX 600 ; N degree ; B 86 243 474 616 ;
-C -1 ; WX 600 ; N ograve ; B 30 -15 570 661 ;
-C -1 ; WX 600 ; N Ccaron ; B 22 -18 560 790 ;
-C -1 ; WX 600 ; N ugrave ; B -1 -15 569 661 ;
-C -1 ; WX 600 ; N radical ; B -19 -104 473 778 ;
-C -1 ; WX 600 ; N Dcaron ; B 30 0 594 790 ;
-C -1 ; WX 600 ; N rcommaaccent ; B 47 -250 580 454 ;
-C -1 ; WX 600 ; N Ntilde ; B 8 -12 610 759 ;
-C -1 ; WX 600 ; N otilde ; B 30 -15 570 636 ;
-C -1 ; WX 600 ; N Rcommaaccent ; B 24 -250 599 562 ;
-C -1 ; WX 600 ; N Lcommaaccent ; B 39 -250 578 562 ;
-C -1 ; WX 600 ; N Atilde ; B -9 0 609 759 ;
-C -1 ; WX 600 ; N Aogonek ; B -9 -199 625 562 ;
-C -1 ; WX 600 ; N Aring ; B -9 0 609 801 ;
-C -1 ; WX 600 ; N Otilde ; B 22 -18 578 759 ;
-C -1 ; WX 600 ; N zdotaccent ; B 81 0 520 638 ;
-C -1 ; WX 600 ; N Ecaron ; B 25 0 560 790 ;
-C -1 ; WX 600 ; N Iogonek ; B 77 -199 523 562 ;
-C -1 ; WX 600 ; N kcommaaccent ; B 20 -250 585 626 ;
-C -1 ; WX 600 ; N minus ; B 71 203 529 313 ;
-C -1 ; WX 600 ; N Icircumflex ; B 77 0 523 780 ;
-C -1 ; WX 600 ; N ncaron ; B 18 0 592 667 ;
-C -1 ; WX 600 ; N tcommaaccent ; B 47 -250 532 562 ;
-C -1 ; WX 600 ; N logicalnot ; B 71 103 529 413 ;
-C -1 ; WX 600 ; N odieresis ; B 30 -15 570 638 ;
-C -1 ; WX 600 ; N udieresis ; B -1 -15 569 638 ;
-C -1 ; WX 600 ; N notequal ; B 12 -47 537 563 ;
-C -1 ; WX 600 ; N gcommaaccent ; B 30 -146 580 714 ;
-C -1 ; WX 600 ; N eth ; B 58 -27 543 626 ;
-C -1 ; WX 600 ; N zcaron ; B 81 0 520 667 ;
-C -1 ; WX 600 ; N ncommaaccent ; B 18 -250 592 454 ;
-C -1 ; WX 600 ; N onesuperior ; B 153 230 447 616 ;
-C -1 ; WX 600 ; N imacron ; B 77 0 523 585 ;
-C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
-EndCharMetrics
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Courier-BoldOblique.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Courier-BoldOblique.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Courier-BoldOblique.afm 2004-05-26 16:06:20.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Courier-BoldOblique.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,342 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Mon Jun 23 16:28:46 1997
-Comment UniqueID 43049
-Comment VMusage 17529 79244
-FontName Courier-BoldOblique
-FullName Courier Bold Oblique
-FamilyName Courier
-Weight Bold
-ItalicAngle -12
-IsFixedPitch true
-CharacterSet ExtendedRoman
-FontBBox -57 -250 869 801
-UnderlinePosition -100
-UnderlineThickness 50
-Version 003.000
-Notice Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
-EncodingScheme AdobeStandardEncoding
-CapHeight 562
-XHeight 439
-Ascender 629
-Descender -157
-StdHW 84
-StdVW 106
-StartCharMetrics 315
-C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 600 ; N exclam ; B 215 -15 495 572 ;
-C 34 ; WX 600 ; N quotedbl ; B 211 277 585 562 ;
-C 35 ; WX 600 ; N numbersign ; B 88 -45 641 651 ;
-C 36 ; WX 600 ; N dollar ; B 87 -126 630 666 ;
-C 37 ; WX 600 ; N percent ; B 101 -15 625 616 ;
-C 38 ; WX 600 ; N ampersand ; B 61 -15 595 543 ;
-C 39 ; WX 600 ; N quoteright ; B 229 277 543 562 ;
-C 40 ; WX 600 ; N parenleft ; B 265 -102 592 616 ;
-C 41 ; WX 600 ; N parenright ; B 117 -102 444 616 ;
-C 42 ; WX 600 ; N asterisk ; B 179 219 598 601 ;
-C 43 ; WX 600 ; N plus ; B 114 39 596 478 ;
-C 44 ; WX 600 ; N comma ; B 99 -111 430 174 ;
-C 45 ; WX 600 ; N hyphen ; B 143 203 567 313 ;
-C 46 ; WX 600 ; N period ; B 206 -15 427 171 ;
-C 47 ; WX 600 ; N slash ; B 90 -77 626 626 ;
-C 48 ; WX 600 ; N zero ; B 135 -15 593 616 ;
-C 49 ; WX 600 ; N one ; B 93 0 562 616 ;
-C 50 ; WX 600 ; N two ; B 61 0 594 616 ;
-C 51 ; WX 600 ; N three ; B 71 -15 571 616 ;
-C 52 ; WX 600 ; N four ; B 81 0 559 616 ;
-C 53 ; WX 600 ; N five ; B 77 -15 621 601 ;
-C 54 ; WX 600 ; N six ; B 135 -15 652 616 ;
-C 55 ; WX 600 ; N seven ; B 147 0 622 601 ;
-C 56 ; WX 600 ; N eight ; B 115 -15 604 616 ;
-C 57 ; WX 600 ; N nine ; B 75 -15 592 616 ;
-C 58 ; WX 600 ; N colon ; B 205 -15 480 425 ;
-C 59 ; WX 600 ; N semicolon ; B 99 -111 481 425 ;
-C 60 ; WX 600 ; N less ; B 120 15 613 501 ;
-C 61 ; WX 600 ; N equal ; B 96 118 614 398 ;
-C 62 ; WX 600 ; N greater ; B 97 15 589 501 ;
-C 63 ; WX 600 ; N question ; B 183 -14 592 580 ;
-C 64 ; WX 600 ; N at ; B 65 -15 642 616 ;
-C 65 ; WX 600 ; N A ; B -9 0 632 562 ;
-C 66 ; WX 600 ; N B ; B 30 0 630 562 ;
-C 67 ; WX 600 ; N C ; B 74 -18 675 580 ;
-C 68 ; WX 600 ; N D ; B 30 0 664 562 ;
-C 69 ; WX 600 ; N E ; B 25 0 670 562 ;
-C 70 ; WX 600 ; N F ; B 39 0 684 562 ;
-C 71 ; WX 600 ; N G ; B 74 -18 675 580 ;
-C 72 ; WX 600 ; N H ; B 20 0 700 562 ;
-C 73 ; WX 600 ; N I ; B 77 0 643 562 ;
-C 74 ; WX 600 ; N J ; B 58 -18 721 562 ;
-C 75 ; WX 600 ; N K ; B 21 0 692 562 ;
-C 76 ; WX 600 ; N L ; B 39 0 636 562 ;
-C 77 ; WX 600 ; N M ; B -2 0 722 562 ;
-C 78 ; WX 600 ; N N ; B 8 -12 730 562 ;
-C 79 ; WX 600 ; N O ; B 74 -18 645 580 ;
-C 80 ; WX 600 ; N P ; B 48 0 643 562 ;
-C 81 ; WX 600 ; N Q ; B 83 -138 636 580 ;
-C 82 ; WX 600 ; N R ; B 24 0 617 562 ;
-C 83 ; WX 600 ; N S ; B 54 -22 673 582 ;
-C 84 ; WX 600 ; N T ; B 86 0 679 562 ;
-C 85 ; WX 600 ; N U ; B 101 -18 716 562 ;
-C 86 ; WX 600 ; N V ; B 84 0 733 562 ;
-C 87 ; WX 600 ; N W ; B 79 0 738 562 ;
-C 88 ; WX 600 ; N X ; B 12 0 690 562 ;
-C 89 ; WX 600 ; N Y ; B 109 0 709 562 ;
-C 90 ; WX 600 ; N Z ; B 62 0 637 562 ;
-C 91 ; WX 600 ; N bracketleft ; B 223 -102 606 616 ;
-C 92 ; WX 600 ; N backslash ; B 222 -77 496 626 ;
-C 93 ; WX 600 ; N bracketright ; B 103 -102 486 616 ;
-C 94 ; WX 600 ; N asciicircum ; B 171 250 556 616 ;
-C 95 ; WX 600 ; N underscore ; B -27 -125 585 -75 ;
-C 96 ; WX 600 ; N quoteleft ; B 297 277 487 562 ;
-C 97 ; WX 600 ; N a ; B 61 -15 593 454 ;
-C 98 ; WX 600 ; N b ; B 13 -15 636 626 ;
-C 99 ; WX 600 ; N c ; B 81 -15 631 459 ;
-C 100 ; WX 600 ; N d ; B 60 -15 645 626 ;
-C 101 ; WX 600 ; N e ; B 81 -15 605 454 ;
-C 102 ; WX 600 ; N f ; B 83 0 677 626 ; L i fi ; L l fl ;
-C 103 ; WX 600 ; N g ; B 40 -146 674 454 ;
-C 104 ; WX 600 ; N h ; B 18 0 615 626 ;
-C 105 ; WX 600 ; N i ; B 77 0 546 658 ;
-C 106 ; WX 600 ; N j ; B 36 -146 580 658 ;
-C 107 ; WX 600 ; N k ; B 33 0 643 626 ;
-C 108 ; WX 600 ; N l ; B 77 0 546 626 ;
-C 109 ; WX 600 ; N m ; B -22 0 649 454 ;
-C 110 ; WX 600 ; N n ; B 18 0 615 454 ;
-C 111 ; WX 600 ; N o ; B 71 -15 622 454 ;
-C 112 ; WX 600 ; N p ; B -32 -142 622 454 ;
-C 113 ; WX 600 ; N q ; B 60 -142 685 454 ;
-C 114 ; WX 600 ; N r ; B 47 0 655 454 ;
-C 115 ; WX 600 ; N s ; B 66 -17 608 459 ;
-C 116 ; WX 600 ; N t ; B 118 -15 567 562 ;
-C 117 ; WX 600 ; N u ; B 70 -15 592 439 ;
-C 118 ; WX 600 ; N v ; B 70 0 695 439 ;
-C 119 ; WX 600 ; N w ; B 53 0 712 439 ;
-C 120 ; WX 600 ; N x ; B 6 0 671 439 ;
-C 121 ; WX 600 ; N y ; B -21 -142 695 439 ;
-C 122 ; WX 600 ; N z ; B 81 0 614 439 ;
-C 123 ; WX 600 ; N braceleft ; B 203 -102 595 616 ;
-C 124 ; WX 600 ; N bar ; B 201 -250 505 750 ;
-C 125 ; WX 600 ; N braceright ; B 114 -102 506 616 ;
-C 126 ; WX 600 ; N asciitilde ; B 120 153 590 356 ;
-C 161 ; WX 600 ; N exclamdown ; B 196 -146 477 449 ;
-C 162 ; WX 600 ; N cent ; B 121 -49 605 614 ;
-C 163 ; WX 600 ; N sterling ; B 106 -28 650 611 ;
-C 164 ; WX 600 ; N fraction ; B 22 -60 708 661 ;
-C 165 ; WX 600 ; N yen ; B 98 0 710 562 ;
-C 166 ; WX 600 ; N florin ; B -57 -131 702 616 ;
-C 167 ; WX 600 ; N section ; B 74 -70 620 580 ;
-C 168 ; WX 600 ; N currency ; B 77 49 644 517 ;
-C 169 ; WX 600 ; N quotesingle ; B 303 277 493 562 ;
-C 170 ; WX 600 ; N quotedblleft ; B 190 277 594 562 ;
-C 171 ; WX 600 ; N guillemotleft ; B 62 70 639 446 ;
-C 172 ; WX 600 ; N guilsinglleft ; B 195 70 545 446 ;
-C 173 ; WX 600 ; N guilsinglright ; B 165 70 514 446 ;
-C 174 ; WX 600 ; N fi ; B 12 0 644 626 ;
-C 175 ; WX 600 ; N fl ; B 12 0 644 626 ;
-C 177 ; WX 600 ; N endash ; B 108 203 602 313 ;
-C 178 ; WX 600 ; N dagger ; B 175 -70 586 580 ;
-C 179 ; WX 600 ; N daggerdbl ; B 121 -70 587 580 ;
-C 180 ; WX 600 ; N periodcentered ; B 248 165 461 351 ;
-C 182 ; WX 600 ; N paragraph ; B 61 -70 700 580 ;
-C 183 ; WX 600 ; N bullet ; B 196 132 523 430 ;
-C 184 ; WX 600 ; N quotesinglbase ; B 144 -142 458 143 ;
-C 185 ; WX 600 ; N quotedblbase ; B 34 -142 560 143 ;
-C 186 ; WX 600 ; N quotedblright ; B 119 277 645 562 ;
-C 187 ; WX 600 ; N guillemotright ; B 71 70 647 446 ;
-C 188 ; WX 600 ; N ellipsis ; B 35 -15 587 116 ;
-C 189 ; WX 600 ; N perthousand ; B -45 -15 743 616 ;
-C 191 ; WX 600 ; N questiondown ; B 100 -146 509 449 ;
-C 193 ; WX 600 ; N grave ; B 272 508 503 661 ;
-C 194 ; WX 600 ; N acute ; B 312 508 609 661 ;
-C 195 ; WX 600 ; N circumflex ; B 212 483 607 657 ;
-C 196 ; WX 600 ; N tilde ; B 199 493 643 636 ;
-C 197 ; WX 600 ; N macron ; B 195 505 637 585 ;
-C 198 ; WX 600 ; N breve ; B 217 468 652 631 ;
-C 199 ; WX 600 ; N dotaccent ; B 348 498 493 638 ;
-C 200 ; WX 600 ; N dieresis ; B 246 498 595 638 ;
-C 202 ; WX 600 ; N ring ; B 319 481 528 678 ;
-C 203 ; WX 600 ; N cedilla ; B 168 -206 368 0 ;
-C 205 ; WX 600 ; N hungarumlaut ; B 171 488 729 661 ;
-C 206 ; WX 600 ; N ogonek ; B 143 -199 367 0 ;
-C 207 ; WX 600 ; N caron ; B 238 493 633 667 ;
-C 208 ; WX 600 ; N emdash ; B 33 203 677 313 ;
-C 225 ; WX 600 ; N AE ; B -29 0 708 562 ;
-C 227 ; WX 600 ; N ordfeminine ; B 188 196 526 580 ;
-C 232 ; WX 600 ; N Lslash ; B 39 0 636 562 ;
-C 233 ; WX 600 ; N Oslash ; B 48 -22 673 584 ;
-C 234 ; WX 600 ; N OE ; B 26 0 701 562 ;
-C 235 ; WX 600 ; N ordmasculine ; B 188 196 543 580 ;
-C 241 ; WX 600 ; N ae ; B 21 -15 652 454 ;
-C 245 ; WX 600 ; N dotlessi ; B 77 0 546 439 ;
-C 248 ; WX 600 ; N lslash ; B 77 0 587 626 ;
-C 249 ; WX 600 ; N oslash ; B 54 -24 638 463 ;
-C 250 ; WX 600 ; N oe ; B 18 -15 662 454 ;
-C 251 ; WX 600 ; N germandbls ; B 22 -15 629 626 ;
-C -1 ; WX 600 ; N Idieresis ; B 77 0 643 761 ;
-C -1 ; WX 600 ; N eacute ; B 81 -15 609 661 ;
-C -1 ; WX 600 ; N abreve ; B 61 -15 658 661 ;
-C -1 ; WX 600 ; N uhungarumlaut ; B 70 -15 769 661 ;
-C -1 ; WX 600 ; N ecaron ; B 81 -15 633 667 ;
-C -1 ; WX 600 ; N Ydieresis ; B 109 0 709 761 ;
-C -1 ; WX 600 ; N divide ; B 114 16 596 500 ;
-C -1 ; WX 600 ; N Yacute ; B 109 0 709 784 ;
-C -1 ; WX 600 ; N Acircumflex ; B -9 0 632 780 ;
-C -1 ; WX 600 ; N aacute ; B 61 -15 609 661 ;
-C -1 ; WX 600 ; N Ucircumflex ; B 101 -18 716 780 ;
-C -1 ; WX 600 ; N yacute ; B -21 -142 695 661 ;
-C -1 ; WX 600 ; N scommaaccent ; B 66 -250 608 459 ;
-C -1 ; WX 600 ; N ecircumflex ; B 81 -15 607 657 ;
-C -1 ; WX 600 ; N Uring ; B 101 -18 716 801 ;
-C -1 ; WX 600 ; N Udieresis ; B 101 -18 716 761 ;
-C -1 ; WX 600 ; N aogonek ; B 61 -199 593 454 ;
-C -1 ; WX 600 ; N Uacute ; B 101 -18 716 784 ;
-C -1 ; WX 600 ; N uogonek ; B 70 -199 592 439 ;
-C -1 ; WX 600 ; N Edieresis ; B 25 0 670 761 ;
-C -1 ; WX 600 ; N Dcroat ; B 30 0 664 562 ;
-C -1 ; WX 600 ; N commaaccent ; B 151 -250 385 -57 ;
-C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ;
-C -1 ; WX 600 ; N Emacron ; B 25 0 670 708 ;
-C -1 ; WX 600 ; N ccaron ; B 81 -15 633 667 ;
-C -1 ; WX 600 ; N aring ; B 61 -15 593 678 ;
-C -1 ; WX 600 ; N Ncommaaccent ; B 8 -250 730 562 ;
-C -1 ; WX 600 ; N lacute ; B 77 0 639 801 ;
-C -1 ; WX 600 ; N agrave ; B 61 -15 593 661 ;
-C -1 ; WX 600 ; N Tcommaaccent ; B 86 -250 679 562 ;
-C -1 ; WX 600 ; N Cacute ; B 74 -18 675 784 ;
-C -1 ; WX 600 ; N atilde ; B 61 -15 643 636 ;
-C -1 ; WX 600 ; N Edotaccent ; B 25 0 670 761 ;
-C -1 ; WX 600 ; N scaron ; B 66 -17 633 667 ;
-C -1 ; WX 600 ; N scedilla ; B 66 -206 608 459 ;
-C -1 ; WX 600 ; N iacute ; B 77 0 609 661 ;
-C -1 ; WX 600 ; N lozenge ; B 145 0 614 740 ;
-C -1 ; WX 600 ; N Rcaron ; B 24 0 659 790 ;
-C -1 ; WX 600 ; N Gcommaaccent ; B 74 -250 675 580 ;
-C -1 ; WX 600 ; N ucircumflex ; B 70 -15 597 657 ;
-C -1 ; WX 600 ; N acircumflex ; B 61 -15 607 657 ;
-C -1 ; WX 600 ; N Amacron ; B -9 0 633 708 ;
-C -1 ; WX 600 ; N rcaron ; B 47 0 655 667 ;
-C -1 ; WX 600 ; N ccedilla ; B 81 -206 631 459 ;
-C -1 ; WX 600 ; N Zdotaccent ; B 62 0 637 761 ;
-C -1 ; WX 600 ; N Thorn ; B 48 0 620 562 ;
-C -1 ; WX 600 ; N Omacron ; B 74 -18 663 708 ;
-C -1 ; WX 600 ; N Racute ; B 24 0 665 784 ;
-C -1 ; WX 600 ; N Sacute ; B 54 -22 673 784 ;
-C -1 ; WX 600 ; N dcaron ; B 60 -15 861 626 ;
-C -1 ; WX 600 ; N Umacron ; B 101 -18 716 708 ;
-C -1 ; WX 600 ; N uring ; B 70 -15 592 678 ;
-C -1 ; WX 600 ; N threesuperior ; B 193 222 526 616 ;
-C -1 ; WX 600 ; N Ograve ; B 74 -18 645 784 ;
-C -1 ; WX 600 ; N Agrave ; B -9 0 632 784 ;
-C -1 ; WX 600 ; N Abreve ; B -9 0 684 784 ;
-C -1 ; WX 600 ; N multiply ; B 104 39 606 478 ;
-C -1 ; WX 600 ; N uacute ; B 70 -15 599 661 ;
-C -1 ; WX 600 ; N Tcaron ; B 86 0 679 790 ;
-C -1 ; WX 600 ; N partialdiff ; B 91 -38 627 728 ;
-C -1 ; WX 600 ; N ydieresis ; B -21 -142 695 638 ;
-C -1 ; WX 600 ; N Nacute ; B 8 -12 730 784 ;
-C -1 ; WX 600 ; N icircumflex ; B 77 0 577 657 ;
-C -1 ; WX 600 ; N Ecircumflex ; B 25 0 670 780 ;
-C -1 ; WX 600 ; N adieresis ; B 61 -15 595 638 ;
-C -1 ; WX 600 ; N edieresis ; B 81 -15 605 638 ;
-C -1 ; WX 600 ; N cacute ; B 81 -15 649 661 ;
-C -1 ; WX 600 ; N nacute ; B 18 0 639 661 ;
-C -1 ; WX 600 ; N umacron ; B 70 -15 637 585 ;
-C -1 ; WX 600 ; N Ncaron ; B 8 -12 730 790 ;
-C -1 ; WX 600 ; N Iacute ; B 77 0 643 784 ;
-C -1 ; WX 600 ; N plusminus ; B 76 24 614 515 ;
-C -1 ; WX 600 ; N brokenbar ; B 217 -175 489 675 ;
-C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ;
-C -1 ; WX 600 ; N Gbreve ; B 74 -18 684 784 ;
-C -1 ; WX 600 ; N Idotaccent ; B 77 0 643 761 ;
-C -1 ; WX 600 ; N summation ; B 15 -10 672 706 ;
-C -1 ; WX 600 ; N Egrave ; B 25 0 670 784 ;
-C -1 ; WX 600 ; N racute ; B 47 0 655 661 ;
-C -1 ; WX 600 ; N omacron ; B 71 -15 637 585 ;
-C -1 ; WX 600 ; N Zacute ; B 62 0 665 784 ;
-C -1 ; WX 600 ; N Zcaron ; B 62 0 659 790 ;
-C -1 ; WX 600 ; N greaterequal ; B 26 0 627 696 ;
-C -1 ; WX 600 ; N Eth ; B 30 0 664 562 ;
-C -1 ; WX 600 ; N Ccedilla ; B 74 -206 675 580 ;
-C -1 ; WX 600 ; N lcommaaccent ; B 77 -250 546 626 ;
-C -1 ; WX 600 ; N tcaron ; B 118 -15 627 703 ;
-C -1 ; WX 600 ; N eogonek ; B 81 -199 605 454 ;
-C -1 ; WX 600 ; N Uogonek ; B 101 -199 716 562 ;
-C -1 ; WX 600 ; N Aacute ; B -9 0 655 784 ;
-C -1 ; WX 600 ; N Adieresis ; B -9 0 632 761 ;
-C -1 ; WX 600 ; N egrave ; B 81 -15 605 661 ;
-C -1 ; WX 600 ; N zacute ; B 81 0 614 661 ;
-C -1 ; WX 600 ; N iogonek ; B 77 -199 546 658 ;
-C -1 ; WX 600 ; N Oacute ; B 74 -18 645 784 ;
-C -1 ; WX 600 ; N oacute ; B 71 -15 649 661 ;
-C -1 ; WX 600 ; N amacron ; B 61 -15 637 585 ;
-C -1 ; WX 600 ; N sacute ; B 66 -17 609 661 ;
-C -1 ; WX 600 ; N idieresis ; B 77 0 561 618 ;
-C -1 ; WX 600 ; N Ocircumflex ; B 74 -18 645 780 ;
-C -1 ; WX 600 ; N Ugrave ; B 101 -18 716 784 ;
-C -1 ; WX 600 ; N Delta ; B 6 0 594 688 ;
-C -1 ; WX 600 ; N thorn ; B -32 -142 622 626 ;
-C -1 ; WX 600 ; N twosuperior ; B 191 230 542 616 ;
-C -1 ; WX 600 ; N Odieresis ; B 74 -18 645 761 ;
-C -1 ; WX 600 ; N mu ; B 49 -142 592 439 ;
-C -1 ; WX 600 ; N igrave ; B 77 0 546 661 ;
-C -1 ; WX 600 ; N ohungarumlaut ; B 71 -15 809 661 ;
-C -1 ; WX 600 ; N Eogonek ; B 25 -199 670 562 ;
-C -1 ; WX 600 ; N dcroat ; B 60 -15 712 626 ;
-C -1 ; WX 600 ; N threequarters ; B 8 -60 699 661 ;
-C -1 ; WX 600 ; N Scedilla ; B 54 -206 673 582 ;
-C -1 ; WX 600 ; N lcaron ; B 77 0 731 626 ;
-C -1 ; WX 600 ; N Kcommaaccent ; B 21 -250 692 562 ;
-C -1 ; WX 600 ; N Lacute ; B 39 0 636 784 ;
-C -1 ; WX 600 ; N trademark ; B 86 230 869 562 ;
-C -1 ; WX 600 ; N edotaccent ; B 81 -15 605 638 ;
-C -1 ; WX 600 ; N Igrave ; B 77 0 643 784 ;
-C -1 ; WX 600 ; N Imacron ; B 77 0 663 708 ;
-C -1 ; WX 600 ; N Lcaron ; B 39 0 757 562 ;
-C -1 ; WX 600 ; N onehalf ; B 22 -60 716 661 ;
-C -1 ; WX 600 ; N lessequal ; B 26 0 671 696 ;
-C -1 ; WX 600 ; N ocircumflex ; B 71 -15 622 657 ;
-C -1 ; WX 600 ; N ntilde ; B 18 0 643 636 ;
-C -1 ; WX 600 ; N Uhungarumlaut ; B 101 -18 805 784 ;
-C -1 ; WX 600 ; N Eacute ; B 25 0 670 784 ;
-C -1 ; WX 600 ; N emacron ; B 81 -15 637 585 ;
-C -1 ; WX 600 ; N gbreve ; B 40 -146 674 661 ;
-C -1 ; WX 600 ; N onequarter ; B 13 -60 707 661 ;
-C -1 ; WX 600 ; N Scaron ; B 54 -22 689 790 ;
-C -1 ; WX 600 ; N Scommaaccent ; B 54 -250 673 582 ;
-C -1 ; WX 600 ; N Ohungarumlaut ; B 74 -18 795 784 ;
-C -1 ; WX 600 ; N degree ; B 173 243 570 616 ;
-C -1 ; WX 600 ; N ograve ; B 71 -15 622 661 ;
-C -1 ; WX 600 ; N Ccaron ; B 74 -18 689 790 ;
-C -1 ; WX 600 ; N ugrave ; B 70 -15 592 661 ;
-C -1 ; WX 600 ; N radical ; B 67 -104 635 778 ;
-C -1 ; WX 600 ; N Dcaron ; B 30 0 664 790 ;
-C -1 ; WX 600 ; N rcommaaccent ; B 47 -250 655 454 ;
-C -1 ; WX 600 ; N Ntilde ; B 8 -12 730 759 ;
-C -1 ; WX 600 ; N otilde ; B 71 -15 643 636 ;
-C -1 ; WX 600 ; N Rcommaaccent ; B 24 -250 617 562 ;
-C -1 ; WX 600 ; N Lcommaaccent ; B 39 -250 636 562 ;
-C -1 ; WX 600 ; N Atilde ; B -9 0 669 759 ;
-C -1 ; WX 600 ; N Aogonek ; B -9 -199 632 562 ;
-C -1 ; WX 600 ; N Aring ; B -9 0 632 801 ;
-C -1 ; WX 600 ; N Otilde ; B 74 -18 669 759 ;
-C -1 ; WX 600 ; N zdotaccent ; B 81 0 614 638 ;
-C -1 ; WX 600 ; N Ecaron ; B 25 0 670 790 ;
-C -1 ; WX 600 ; N Iogonek ; B 77 -199 643 562 ;
-C -1 ; WX 600 ; N kcommaaccent ; B 33 -250 643 626 ;
-C -1 ; WX 600 ; N minus ; B 114 203 596 313 ;
-C -1 ; WX 600 ; N Icircumflex ; B 77 0 643 780 ;
-C -1 ; WX 600 ; N ncaron ; B 18 0 633 667 ;
-C -1 ; WX 600 ; N tcommaaccent ; B 118 -250 567 562 ;
-C -1 ; WX 600 ; N logicalnot ; B 135 103 617 413 ;
-C -1 ; WX 600 ; N odieresis ; B 71 -15 622 638 ;
-C -1 ; WX 600 ; N udieresis ; B 70 -15 595 638 ;
-C -1 ; WX 600 ; N notequal ; B 30 -47 626 563 ;
-C -1 ; WX 600 ; N gcommaaccent ; B 40 -146 674 714 ;
-C -1 ; WX 600 ; N eth ; B 93 -27 661 626 ;
-C -1 ; WX 600 ; N zcaron ; B 81 0 643 667 ;
-C -1 ; WX 600 ; N ncommaaccent ; B 18 -250 615 454 ;
-C -1 ; WX 600 ; N onesuperior ; B 212 230 514 616 ;
-C -1 ; WX 600 ; N imacron ; B 77 0 575 585 ;
-C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
-EndCharMetrics
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Courier-Oblique.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Courier-Oblique.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Courier-Oblique.afm 2004-05-26 16:06:20.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Courier-Oblique.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,342 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Thu May 1 17:37:52 1997
-Comment UniqueID 43051
-Comment VMusage 16248 75829
-FontName Courier-Oblique
-FullName Courier Oblique
-FamilyName Courier
-Weight Medium
-ItalicAngle -12
-IsFixedPitch true
-CharacterSet ExtendedRoman
-FontBBox -27 -250 849 805
-UnderlinePosition -100
-UnderlineThickness 50
-Version 003.000
-Notice Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
-EncodingScheme AdobeStandardEncoding
-CapHeight 562
-XHeight 426
-Ascender 629
-Descender -157
-StdHW 51
-StdVW 51
-StartCharMetrics 315
-C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 600 ; N exclam ; B 243 -15 464 572 ;
-C 34 ; WX 600 ; N quotedbl ; B 273 328 532 562 ;
-C 35 ; WX 600 ; N numbersign ; B 133 -32 596 639 ;
-C 36 ; WX 600 ; N dollar ; B 108 -126 596 662 ;
-C 37 ; WX 600 ; N percent ; B 134 -15 599 622 ;
-C 38 ; WX 600 ; N ampersand ; B 87 -15 580 543 ;
-C 39 ; WX 600 ; N quoteright ; B 283 328 495 562 ;
-C 40 ; WX 600 ; N parenleft ; B 313 -108 572 622 ;
-C 41 ; WX 600 ; N parenright ; B 137 -108 396 622 ;
-C 42 ; WX 600 ; N asterisk ; B 212 257 580 607 ;
-C 43 ; WX 600 ; N plus ; B 129 44 580 470 ;
-C 44 ; WX 600 ; N comma ; B 157 -112 370 122 ;
-C 45 ; WX 600 ; N hyphen ; B 152 231 558 285 ;
-C 46 ; WX 600 ; N period ; B 238 -15 382 109 ;
-C 47 ; WX 600 ; N slash ; B 112 -80 604 629 ;
-C 48 ; WX 600 ; N zero ; B 154 -15 575 622 ;
-C 49 ; WX 600 ; N one ; B 98 0 515 622 ;
-C 50 ; WX 600 ; N two ; B 70 0 568 622 ;
-C 51 ; WX 600 ; N three ; B 82 -15 538 622 ;
-C 52 ; WX 600 ; N four ; B 108 0 541 622 ;
-C 53 ; WX 600 ; N five ; B 99 -15 589 607 ;
-C 54 ; WX 600 ; N six ; B 155 -15 629 622 ;
-C 55 ; WX 600 ; N seven ; B 182 0 612 607 ;
-C 56 ; WX 600 ; N eight ; B 132 -15 588 622 ;
-C 57 ; WX 600 ; N nine ; B 93 -15 574 622 ;
-C 58 ; WX 600 ; N colon ; B 238 -15 441 385 ;
-C 59 ; WX 600 ; N semicolon ; B 157 -112 441 385 ;
-C 60 ; WX 600 ; N less ; B 96 42 610 472 ;
-C 61 ; WX 600 ; N equal ; B 109 138 600 376 ;
-C 62 ; WX 600 ; N greater ; B 85 42 599 472 ;
-C 63 ; WX 600 ; N question ; B 222 -15 583 572 ;
-C 64 ; WX 600 ; N at ; B 127 -15 582 622 ;
-C 65 ; WX 600 ; N A ; B 3 0 607 562 ;
-C 66 ; WX 600 ; N B ; B 43 0 616 562 ;
-C 67 ; WX 600 ; N C ; B 93 -18 655 580 ;
-C 68 ; WX 600 ; N D ; B 43 0 645 562 ;
-C 69 ; WX 600 ; N E ; B 53 0 660 562 ;
-C 70 ; WX 600 ; N F ; B 53 0 660 562 ;
-C 71 ; WX 600 ; N G ; B 83 -18 645 580 ;
-C 72 ; WX 600 ; N H ; B 32 0 687 562 ;
-C 73 ; WX 600 ; N I ; B 96 0 623 562 ;
-C 74 ; WX 600 ; N J ; B 52 -18 685 562 ;
-C 75 ; WX 600 ; N K ; B 38 0 671 562 ;
-C 76 ; WX 600 ; N L ; B 47 0 607 562 ;
-C 77 ; WX 600 ; N M ; B 4 0 715 562 ;
-C 78 ; WX 600 ; N N ; B 7 -13 712 562 ;
-C 79 ; WX 600 ; N O ; B 94 -18 625 580 ;
-C 80 ; WX 600 ; N P ; B 79 0 644 562 ;
-C 81 ; WX 600 ; N Q ; B 95 -138 625 580 ;
-C 82 ; WX 600 ; N R ; B 38 0 598 562 ;
-C 83 ; WX 600 ; N S ; B 76 -20 650 580 ;
-C 84 ; WX 600 ; N T ; B 108 0 665 562 ;
-C 85 ; WX 600 ; N U ; B 125 -18 702 562 ;
-C 86 ; WX 600 ; N V ; B 105 -13 723 562 ;
-C 87 ; WX 600 ; N W ; B 106 -13 722 562 ;
-C 88 ; WX 600 ; N X ; B 23 0 675 562 ;
-C 89 ; WX 600 ; N Y ; B 133 0 695 562 ;
-C 90 ; WX 600 ; N Z ; B 86 0 610 562 ;
-C 91 ; WX 600 ; N bracketleft ; B 246 -108 574 622 ;
-C 92 ; WX 600 ; N backslash ; B 249 -80 468 629 ;
-C 93 ; WX 600 ; N bracketright ; B 135 -108 463 622 ;
-C 94 ; WX 600 ; N asciicircum ; B 175 354 587 622 ;
-C 95 ; WX 600 ; N underscore ; B -27 -125 584 -75 ;
-C 96 ; WX 600 ; N quoteleft ; B 343 328 457 562 ;
-C 97 ; WX 600 ; N a ; B 76 -15 569 441 ;
-C 98 ; WX 600 ; N b ; B 29 -15 625 629 ;
-C 99 ; WX 600 ; N c ; B 106 -15 608 441 ;
-C 100 ; WX 600 ; N d ; B 85 -15 640 629 ;
-C 101 ; WX 600 ; N e ; B 106 -15 598 441 ;
-C 102 ; WX 600 ; N f ; B 114 0 662 629 ; L i fi ; L l fl ;
-C 103 ; WX 600 ; N g ; B 61 -157 657 441 ;
-C 104 ; WX 600 ; N h ; B 33 0 592 629 ;
-C 105 ; WX 600 ; N i ; B 95 0 515 657 ;
-C 106 ; WX 600 ; N j ; B 52 -157 550 657 ;
-C 107 ; WX 600 ; N k ; B 58 0 633 629 ;
-C 108 ; WX 600 ; N l ; B 95 0 515 629 ;
-C 109 ; WX 600 ; N m ; B -5 0 615 441 ;
-C 110 ; WX 600 ; N n ; B 26 0 585 441 ;
-C 111 ; WX 600 ; N o ; B 102 -15 588 441 ;
-C 112 ; WX 600 ; N p ; B -24 -157 605 441 ;
-C 113 ; WX 600 ; N q ; B 85 -157 682 441 ;
-C 114 ; WX 600 ; N r ; B 60 0 636 441 ;
-C 115 ; WX 600 ; N s ; B 78 -15 584 441 ;
-C 116 ; WX 600 ; N t ; B 167 -15 561 561 ;
-C 117 ; WX 600 ; N u ; B 101 -15 572 426 ;
-C 118 ; WX 600 ; N v ; B 90 -10 681 426 ;
-C 119 ; WX 600 ; N w ; B 76 -10 695 426 ;
-C 120 ; WX 600 ; N x ; B 20 0 655 426 ;
-C 121 ; WX 600 ; N y ; B -4 -157 683 426 ;
-C 122 ; WX 600 ; N z ; B 99 0 593 426 ;
-C 123 ; WX 600 ; N braceleft ; B 233 -108 569 622 ;
-C 124 ; WX 600 ; N bar ; B 222 -250 485 750 ;
-C 125 ; WX 600 ; N braceright ; B 140 -108 477 622 ;
-C 126 ; WX 600 ; N asciitilde ; B 116 197 600 320 ;
-C 161 ; WX 600 ; N exclamdown ; B 225 -157 445 430 ;
-C 162 ; WX 600 ; N cent ; B 151 -49 588 614 ;
-C 163 ; WX 600 ; N sterling ; B 124 -21 621 611 ;
-C 164 ; WX 600 ; N fraction ; B 84 -57 646 665 ;
-C 165 ; WX 600 ; N yen ; B 120 0 693 562 ;
-C 166 ; WX 600 ; N florin ; B -26 -143 671 622 ;
-C 167 ; WX 600 ; N section ; B 104 -78 590 580 ;
-C 168 ; WX 600 ; N currency ; B 94 58 628 506 ;
-C 169 ; WX 600 ; N quotesingle ; B 345 328 460 562 ;
-C 170 ; WX 600 ; N quotedblleft ; B 262 328 541 562 ;
-C 171 ; WX 600 ; N guillemotleft ; B 92 70 652 446 ;
-C 172 ; WX 600 ; N guilsinglleft ; B 204 70 540 446 ;
-C 173 ; WX 600 ; N guilsinglright ; B 170 70 506 446 ;
-C 174 ; WX 600 ; N fi ; B 3 0 619 629 ;
-C 175 ; WX 600 ; N fl ; B 3 0 619 629 ;
-C 177 ; WX 600 ; N endash ; B 124 231 586 285 ;
-C 178 ; WX 600 ; N dagger ; B 217 -78 546 580 ;
-C 179 ; WX 600 ; N daggerdbl ; B 163 -78 546 580 ;
-C 180 ; WX 600 ; N periodcentered ; B 275 189 434 327 ;
-C 182 ; WX 600 ; N paragraph ; B 100 -78 630 562 ;
-C 183 ; WX 600 ; N bullet ; B 224 130 485 383 ;
-C 184 ; WX 600 ; N quotesinglbase ; B 185 -134 397 100 ;
-C 185 ; WX 600 ; N quotedblbase ; B 115 -134 478 100 ;
-C 186 ; WX 600 ; N quotedblright ; B 213 328 576 562 ;
-C 187 ; WX 600 ; N guillemotright ; B 58 70 618 446 ;
-C 188 ; WX 600 ; N ellipsis ; B 46 -15 575 111 ;
-C 189 ; WX 600 ; N perthousand ; B 59 -15 627 622 ;
-C 191 ; WX 600 ; N questiondown ; B 105 -157 466 430 ;
-C 193 ; WX 600 ; N grave ; B 294 497 484 672 ;
-C 194 ; WX 600 ; N acute ; B 348 497 612 672 ;
-C 195 ; WX 600 ; N circumflex ; B 229 477 581 654 ;
-C 196 ; WX 600 ; N tilde ; B 212 489 629 606 ;
-C 197 ; WX 600 ; N macron ; B 232 525 600 565 ;
-C 198 ; WX 600 ; N breve ; B 279 501 576 609 ;
-C 199 ; WX 600 ; N dotaccent ; B 373 537 478 640 ;
-C 200 ; WX 600 ; N dieresis ; B 272 537 579 640 ;
-C 202 ; WX 600 ; N ring ; B 332 463 500 627 ;
-C 203 ; WX 600 ; N cedilla ; B 197 -151 344 10 ;
-C 205 ; WX 600 ; N hungarumlaut ; B 239 497 683 672 ;
-C 206 ; WX 600 ; N ogonek ; B 189 -172 377 4 ;
-C 207 ; WX 600 ; N caron ; B 262 492 614 669 ;
-C 208 ; WX 600 ; N emdash ; B 49 231 661 285 ;
-C 225 ; WX 600 ; N AE ; B 3 0 655 562 ;
-C 227 ; WX 600 ; N ordfeminine ; B 209 249 512 580 ;
-C 232 ; WX 600 ; N Lslash ; B 47 0 607 562 ;
-C 233 ; WX 600 ; N Oslash ; B 94 -80 625 629 ;
-C 234 ; WX 600 ; N OE ; B 59 0 672 562 ;
-C 235 ; WX 600 ; N ordmasculine ; B 210 249 535 580 ;
-C 241 ; WX 600 ; N ae ; B 41 -15 626 441 ;
-C 245 ; WX 600 ; N dotlessi ; B 95 0 515 426 ;
-C 248 ; WX 600 ; N lslash ; B 95 0 587 629 ;
-C 249 ; WX 600 ; N oslash ; B 102 -80 588 506 ;
-C 250 ; WX 600 ; N oe ; B 54 -15 615 441 ;
-C 251 ; WX 600 ; N germandbls ; B 48 -15 617 629 ;
-C -1 ; WX 600 ; N Idieresis ; B 96 0 623 753 ;
-C -1 ; WX 600 ; N eacute ; B 106 -15 612 672 ;
-C -1 ; WX 600 ; N abreve ; B 76 -15 576 609 ;
-C -1 ; WX 600 ; N uhungarumlaut ; B 101 -15 723 672 ;
-C -1 ; WX 600 ; N ecaron ; B 106 -15 614 669 ;
-C -1 ; WX 600 ; N Ydieresis ; B 133 0 695 753 ;
-C -1 ; WX 600 ; N divide ; B 136 48 573 467 ;
-C -1 ; WX 600 ; N Yacute ; B 133 0 695 805 ;
-C -1 ; WX 600 ; N Acircumflex ; B 3 0 607 787 ;
-C -1 ; WX 600 ; N aacute ; B 76 -15 612 672 ;
-C -1 ; WX 600 ; N Ucircumflex ; B 125 -18 702 787 ;
-C -1 ; WX 600 ; N yacute ; B -4 -157 683 672 ;
-C -1 ; WX 600 ; N scommaaccent ; B 78 -250 584 441 ;
-C -1 ; WX 600 ; N ecircumflex ; B 106 -15 598 654 ;
-C -1 ; WX 600 ; N Uring ; B 125 -18 702 760 ;
-C -1 ; WX 600 ; N Udieresis ; B 125 -18 702 753 ;
-C -1 ; WX 600 ; N aogonek ; B 76 -172 569 441 ;
-C -1 ; WX 600 ; N Uacute ; B 125 -18 702 805 ;
-C -1 ; WX 600 ; N uogonek ; B 101 -172 572 426 ;
-C -1 ; WX 600 ; N Edieresis ; B 53 0 660 753 ;
-C -1 ; WX 600 ; N Dcroat ; B 43 0 645 562 ;
-C -1 ; WX 600 ; N commaaccent ; B 145 -250 323 -58 ;
-C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ;
-C -1 ; WX 600 ; N Emacron ; B 53 0 660 698 ;
-C -1 ; WX 600 ; N ccaron ; B 106 -15 614 669 ;
-C -1 ; WX 600 ; N aring ; B 76 -15 569 627 ;
-C -1 ; WX 600 ; N Ncommaaccent ; B 7 -250 712 562 ;
-C -1 ; WX 600 ; N lacute ; B 95 0 640 805 ;
-C -1 ; WX 600 ; N agrave ; B 76 -15 569 672 ;
-C -1 ; WX 600 ; N Tcommaaccent ; B 108 -250 665 562 ;
-C -1 ; WX 600 ; N Cacute ; B 93 -18 655 805 ;
-C -1 ; WX 600 ; N atilde ; B 76 -15 629 606 ;
-C -1 ; WX 600 ; N Edotaccent ; B 53 0 660 753 ;
-C -1 ; WX 600 ; N scaron ; B 78 -15 614 669 ;
-C -1 ; WX 600 ; N scedilla ; B 78 -151 584 441 ;
-C -1 ; WX 600 ; N iacute ; B 95 0 612 672 ;
-C -1 ; WX 600 ; N lozenge ; B 94 0 519 706 ;
-C -1 ; WX 600 ; N Rcaron ; B 38 0 642 802 ;
-C -1 ; WX 600 ; N Gcommaaccent ; B 83 -250 645 580 ;
-C -1 ; WX 600 ; N ucircumflex ; B 101 -15 572 654 ;
-C -1 ; WX 600 ; N acircumflex ; B 76 -15 581 654 ;
-C -1 ; WX 600 ; N Amacron ; B 3 0 607 698 ;
-C -1 ; WX 600 ; N rcaron ; B 60 0 636 669 ;
-C -1 ; WX 600 ; N ccedilla ; B 106 -151 614 441 ;
-C -1 ; WX 600 ; N Zdotaccent ; B 86 0 610 753 ;
-C -1 ; WX 600 ; N Thorn ; B 79 0 606 562 ;
-C -1 ; WX 600 ; N Omacron ; B 94 -18 628 698 ;
-C -1 ; WX 600 ; N Racute ; B 38 0 670 805 ;
-C -1 ; WX 600 ; N Sacute ; B 76 -20 650 805 ;
-C -1 ; WX 600 ; N dcaron ; B 85 -15 849 629 ;
-C -1 ; WX 600 ; N Umacron ; B 125 -18 702 698 ;
-C -1 ; WX 600 ; N uring ; B 101 -15 572 627 ;
-C -1 ; WX 600 ; N threesuperior ; B 213 240 501 622 ;
-C -1 ; WX 600 ; N Ograve ; B 94 -18 625 805 ;
-C -1 ; WX 600 ; N Agrave ; B 3 0 607 805 ;
-C -1 ; WX 600 ; N Abreve ; B 3 0 607 732 ;
-C -1 ; WX 600 ; N multiply ; B 103 43 607 470 ;
-C -1 ; WX 600 ; N uacute ; B 101 -15 602 672 ;
-C -1 ; WX 600 ; N Tcaron ; B 108 0 665 802 ;
-C -1 ; WX 600 ; N partialdiff ; B 45 -38 546 710 ;
-C -1 ; WX 600 ; N ydieresis ; B -4 -157 683 620 ;
-C -1 ; WX 600 ; N Nacute ; B 7 -13 712 805 ;
-C -1 ; WX 600 ; N icircumflex ; B 95 0 551 654 ;
-C -1 ; WX 600 ; N Ecircumflex ; B 53 0 660 787 ;
-C -1 ; WX 600 ; N adieresis ; B 76 -15 575 620 ;
-C -1 ; WX 600 ; N edieresis ; B 106 -15 598 620 ;
-C -1 ; WX 600 ; N cacute ; B 106 -15 612 672 ;
-C -1 ; WX 600 ; N nacute ; B 26 0 602 672 ;
-C -1 ; WX 600 ; N umacron ; B 101 -15 600 565 ;
-C -1 ; WX 600 ; N Ncaron ; B 7 -13 712 802 ;
-C -1 ; WX 600 ; N Iacute ; B 96 0 640 805 ;
-C -1 ; WX 600 ; N plusminus ; B 96 44 594 558 ;
-C -1 ; WX 600 ; N brokenbar ; B 238 -175 469 675 ;
-C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ;
-C -1 ; WX 600 ; N Gbreve ; B 83 -18 645 732 ;
-C -1 ; WX 600 ; N Idotaccent ; B 96 0 623 753 ;
-C -1 ; WX 600 ; N summation ; B 15 -10 670 706 ;
-C -1 ; WX 600 ; N Egrave ; B 53 0 660 805 ;
-C -1 ; WX 600 ; N racute ; B 60 0 636 672 ;
-C -1 ; WX 600 ; N omacron ; B 102 -15 600 565 ;
-C -1 ; WX 600 ; N Zacute ; B 86 0 670 805 ;
-C -1 ; WX 600 ; N Zcaron ; B 86 0 642 802 ;
-C -1 ; WX 600 ; N greaterequal ; B 98 0 594 710 ;
-C -1 ; WX 600 ; N Eth ; B 43 0 645 562 ;
-C -1 ; WX 600 ; N Ccedilla ; B 93 -151 658 580 ;
-C -1 ; WX 600 ; N lcommaaccent ; B 95 -250 515 629 ;
-C -1 ; WX 600 ; N tcaron ; B 167 -15 587 717 ;
-C -1 ; WX 600 ; N eogonek ; B 106 -172 598 441 ;
-C -1 ; WX 600 ; N Uogonek ; B 124 -172 702 562 ;
-C -1 ; WX 600 ; N Aacute ; B 3 0 660 805 ;
-C -1 ; WX 600 ; N Adieresis ; B 3 0 607 753 ;
-C -1 ; WX 600 ; N egrave ; B 106 -15 598 672 ;
-C -1 ; WX 600 ; N zacute ; B 99 0 612 672 ;
-C -1 ; WX 600 ; N iogonek ; B 95 -172 515 657 ;
-C -1 ; WX 600 ; N Oacute ; B 94 -18 640 805 ;
-C -1 ; WX 600 ; N oacute ; B 102 -15 612 672 ;
-C -1 ; WX 600 ; N amacron ; B 76 -15 600 565 ;
-C -1 ; WX 600 ; N sacute ; B 78 -15 612 672 ;
-C -1 ; WX 600 ; N idieresis ; B 95 0 545 620 ;
-C -1 ; WX 600 ; N Ocircumflex ; B 94 -18 625 787 ;
-C -1 ; WX 600 ; N Ugrave ; B 125 -18 702 805 ;
-C -1 ; WX 600 ; N Delta ; B 6 0 598 688 ;
-C -1 ; WX 600 ; N thorn ; B -24 -157 605 629 ;
-C -1 ; WX 600 ; N twosuperior ; B 230 249 535 622 ;
-C -1 ; WX 600 ; N Odieresis ; B 94 -18 625 753 ;
-C -1 ; WX 600 ; N mu ; B 72 -157 572 426 ;
-C -1 ; WX 600 ; N igrave ; B 95 0 515 672 ;
-C -1 ; WX 600 ; N ohungarumlaut ; B 102 -15 723 672 ;
-C -1 ; WX 600 ; N Eogonek ; B 53 -172 660 562 ;
-C -1 ; WX 600 ; N dcroat ; B 85 -15 704 629 ;
-C -1 ; WX 600 ; N threequarters ; B 73 -56 659 666 ;
-C -1 ; WX 600 ; N Scedilla ; B 76 -151 650 580 ;
-C -1 ; WX 600 ; N lcaron ; B 95 0 667 629 ;
-C -1 ; WX 600 ; N Kcommaaccent ; B 38 -250 671 562 ;
-C -1 ; WX 600 ; N Lacute ; B 47 0 607 805 ;
-C -1 ; WX 600 ; N trademark ; B 75 263 742 562 ;
-C -1 ; WX 600 ; N edotaccent ; B 106 -15 598 620 ;
-C -1 ; WX 600 ; N Igrave ; B 96 0 623 805 ;
-C -1 ; WX 600 ; N Imacron ; B 96 0 628 698 ;
-C -1 ; WX 600 ; N Lcaron ; B 47 0 632 562 ;
-C -1 ; WX 600 ; N onehalf ; B 65 -57 669 665 ;
-C -1 ; WX 600 ; N lessequal ; B 98 0 645 710 ;
-C -1 ; WX 600 ; N ocircumflex ; B 102 -15 588 654 ;
-C -1 ; WX 600 ; N ntilde ; B 26 0 629 606 ;
-C -1 ; WX 600 ; N Uhungarumlaut ; B 125 -18 761 805 ;
-C -1 ; WX 600 ; N Eacute ; B 53 0 670 805 ;
-C -1 ; WX 600 ; N emacron ; B 106 -15 600 565 ;
-C -1 ; WX 600 ; N gbreve ; B 61 -157 657 609 ;
-C -1 ; WX 600 ; N onequarter ; B 65 -57 674 665 ;
-C -1 ; WX 600 ; N Scaron ; B 76 -20 672 802 ;
-C -1 ; WX 600 ; N Scommaaccent ; B 76 -250 650 580 ;
-C -1 ; WX 600 ; N Ohungarumlaut ; B 94 -18 751 805 ;
-C -1 ; WX 600 ; N degree ; B 214 269 576 622 ;
-C -1 ; WX 600 ; N ograve ; B 102 -15 588 672 ;
-C -1 ; WX 600 ; N Ccaron ; B 93 -18 672 802 ;
-C -1 ; WX 600 ; N ugrave ; B 101 -15 572 672 ;
-C -1 ; WX 600 ; N radical ; B 85 -15 765 792 ;
-C -1 ; WX 600 ; N Dcaron ; B 43 0 645 802 ;
-C -1 ; WX 600 ; N rcommaaccent ; B 60 -250 636 441 ;
-C -1 ; WX 600 ; N Ntilde ; B 7 -13 712 729 ;
-C -1 ; WX 600 ; N otilde ; B 102 -15 629 606 ;
-C -1 ; WX 600 ; N Rcommaaccent ; B 38 -250 598 562 ;
-C -1 ; WX 600 ; N Lcommaaccent ; B 47 -250 607 562 ;
-C -1 ; WX 600 ; N Atilde ; B 3 0 655 729 ;
-C -1 ; WX 600 ; N Aogonek ; B 3 -172 607 562 ;
-C -1 ; WX 600 ; N Aring ; B 3 0 607 750 ;
-C -1 ; WX 600 ; N Otilde ; B 94 -18 655 729 ;
-C -1 ; WX 600 ; N zdotaccent ; B 99 0 593 620 ;
-C -1 ; WX 600 ; N Ecaron ; B 53 0 660 802 ;
-C -1 ; WX 600 ; N Iogonek ; B 96 -172 623 562 ;
-C -1 ; WX 600 ; N kcommaaccent ; B 58 -250 633 629 ;
-C -1 ; WX 600 ; N minus ; B 129 232 580 283 ;
-C -1 ; WX 600 ; N Icircumflex ; B 96 0 623 787 ;
-C -1 ; WX 600 ; N ncaron ; B 26 0 614 669 ;
-C -1 ; WX 600 ; N tcommaaccent ; B 165 -250 561 561 ;
-C -1 ; WX 600 ; N logicalnot ; B 155 108 591 369 ;
-C -1 ; WX 600 ; N odieresis ; B 102 -15 588 620 ;
-C -1 ; WX 600 ; N udieresis ; B 101 -15 575 620 ;
-C -1 ; WX 600 ; N notequal ; B 43 -16 621 529 ;
-C -1 ; WX 600 ; N gcommaaccent ; B 61 -157 657 708 ;
-C -1 ; WX 600 ; N eth ; B 102 -15 639 629 ;
-C -1 ; WX 600 ; N zcaron ; B 99 0 624 669 ;
-C -1 ; WX 600 ; N ncommaaccent ; B 26 -250 585 441 ;
-C -1 ; WX 600 ; N onesuperior ; B 231 249 491 622 ;
-C -1 ; WX 600 ; N imacron ; B 95 0 543 565 ;
-C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
-EndCharMetrics
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Courier.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Courier.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Courier.afm 2004-05-26 16:06:20.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Courier.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,342 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Thu May 1 17:27:09 1997
-Comment UniqueID 43050
-Comment VMusage 39754 50779
-FontName Courier
-FullName Courier
-FamilyName Courier
-Weight Medium
-ItalicAngle 0
-IsFixedPitch true
-CharacterSet ExtendedRoman
-FontBBox -23 -250 715 805
-UnderlinePosition -100
-UnderlineThickness 50
-Version 003.000
-Notice Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
-EncodingScheme AdobeStandardEncoding
-CapHeight 562
-XHeight 426
-Ascender 629
-Descender -157
-StdHW 51
-StdVW 51
-StartCharMetrics 315
-C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 600 ; N exclam ; B 236 -15 364 572 ;
-C 34 ; WX 600 ; N quotedbl ; B 187 328 413 562 ;
-C 35 ; WX 600 ; N numbersign ; B 93 -32 507 639 ;
-C 36 ; WX 600 ; N dollar ; B 105 -126 496 662 ;
-C 37 ; WX 600 ; N percent ; B 81 -15 518 622 ;
-C 38 ; WX 600 ; N ampersand ; B 63 -15 538 543 ;
-C 39 ; WX 600 ; N quoteright ; B 213 328 376 562 ;
-C 40 ; WX 600 ; N parenleft ; B 269 -108 440 622 ;
-C 41 ; WX 600 ; N parenright ; B 160 -108 331 622 ;
-C 42 ; WX 600 ; N asterisk ; B 116 257 484 607 ;
-C 43 ; WX 600 ; N plus ; B 80 44 520 470 ;
-C 44 ; WX 600 ; N comma ; B 181 -112 344 122 ;
-C 45 ; WX 600 ; N hyphen ; B 103 231 497 285 ;
-C 46 ; WX 600 ; N period ; B 229 -15 371 109 ;
-C 47 ; WX 600 ; N slash ; B 125 -80 475 629 ;
-C 48 ; WX 600 ; N zero ; B 106 -15 494 622 ;
-C 49 ; WX 600 ; N one ; B 96 0 505 622 ;
-C 50 ; WX 600 ; N two ; B 70 0 471 622 ;
-C 51 ; WX 600 ; N three ; B 75 -15 466 622 ;
-C 52 ; WX 600 ; N four ; B 78 0 500 622 ;
-C 53 ; WX 600 ; N five ; B 92 -15 497 607 ;
-C 54 ; WX 600 ; N six ; B 111 -15 497 622 ;
-C 55 ; WX 600 ; N seven ; B 82 0 483 607 ;
-C 56 ; WX 600 ; N eight ; B 102 -15 498 622 ;
-C 57 ; WX 600 ; N nine ; B 96 -15 489 622 ;
-C 58 ; WX 600 ; N colon ; B 229 -15 371 385 ;
-C 59 ; WX 600 ; N semicolon ; B 181 -112 371 385 ;
-C 60 ; WX 600 ; N less ; B 41 42 519 472 ;
-C 61 ; WX 600 ; N equal ; B 80 138 520 376 ;
-C 62 ; WX 600 ; N greater ; B 66 42 544 472 ;
-C 63 ; WX 600 ; N question ; B 129 -15 492 572 ;
-C 64 ; WX 600 ; N at ; B 77 -15 533 622 ;
-C 65 ; WX 600 ; N A ; B 3 0 597 562 ;
-C 66 ; WX 600 ; N B ; B 43 0 559 562 ;
-C 67 ; WX 600 ; N C ; B 41 -18 540 580 ;
-C 68 ; WX 600 ; N D ; B 43 0 574 562 ;
-C 69 ; WX 600 ; N E ; B 53 0 550 562 ;
-C 70 ; WX 600 ; N F ; B 53 0 545 562 ;
-C 71 ; WX 600 ; N G ; B 31 -18 575 580 ;
-C 72 ; WX 600 ; N H ; B 32 0 568 562 ;
-C 73 ; WX 600 ; N I ; B 96 0 504 562 ;
-C 74 ; WX 600 ; N J ; B 34 -18 566 562 ;
-C 75 ; WX 600 ; N K ; B 38 0 582 562 ;
-C 76 ; WX 600 ; N L ; B 47 0 554 562 ;
-C 77 ; WX 600 ; N M ; B 4 0 596 562 ;
-C 78 ; WX 600 ; N N ; B 7 -13 593 562 ;
-C 79 ; WX 600 ; N O ; B 43 -18 557 580 ;
-C 80 ; WX 600 ; N P ; B 79 0 558 562 ;
-C 81 ; WX 600 ; N Q ; B 43 -138 557 580 ;
-C 82 ; WX 600 ; N R ; B 38 0 588 562 ;
-C 83 ; WX 600 ; N S ; B 72 -20 529 580 ;
-C 84 ; WX 600 ; N T ; B 38 0 563 562 ;
-C 85 ; WX 600 ; N U ; B 17 -18 583 562 ;
-C 86 ; WX 600 ; N V ; B -4 -13 604 562 ;
-C 87 ; WX 600 ; N W ; B -3 -13 603 562 ;
-C 88 ; WX 600 ; N X ; B 23 0 577 562 ;
-C 89 ; WX 600 ; N Y ; B 24 0 576 562 ;
-C 90 ; WX 600 ; N Z ; B 86 0 514 562 ;
-C 91 ; WX 600 ; N bracketleft ; B 269 -108 442 622 ;
-C 92 ; WX 600 ; N backslash ; B 118 -80 482 629 ;
-C 93 ; WX 600 ; N bracketright ; B 158 -108 331 622 ;
-C 94 ; WX 600 ; N asciicircum ; B 94 354 506 622 ;
-C 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ;
-C 96 ; WX 600 ; N quoteleft ; B 224 328 387 562 ;
-C 97 ; WX 600 ; N a ; B 53 -15 559 441 ;
-C 98 ; WX 600 ; N b ; B 14 -15 575 629 ;
-C 99 ; WX 600 ; N c ; B 66 -15 529 441 ;
-C 100 ; WX 600 ; N d ; B 45 -15 591 629 ;
-C 101 ; WX 600 ; N e ; B 66 -15 548 441 ;
-C 102 ; WX 600 ; N f ; B 114 0 531 629 ; L i fi ; L l fl ;
-C 103 ; WX 600 ; N g ; B 45 -157 566 441 ;
-C 104 ; WX 600 ; N h ; B 18 0 582 629 ;
-C 105 ; WX 600 ; N i ; B 95 0 505 657 ;
-C 106 ; WX 600 ; N j ; B 82 -157 410 657 ;
-C 107 ; WX 600 ; N k ; B 43 0 580 629 ;
-C 108 ; WX 600 ; N l ; B 95 0 505 629 ;
-C 109 ; WX 600 ; N m ; B -5 0 605 441 ;
-C 110 ; WX 600 ; N n ; B 26 0 575 441 ;
-C 111 ; WX 600 ; N o ; B 62 -15 538 441 ;
-C 112 ; WX 600 ; N p ; B 9 -157 555 441 ;
-C 113 ; WX 600 ; N q ; B 45 -157 591 441 ;
-C 114 ; WX 600 ; N r ; B 60 0 559 441 ;
-C 115 ; WX 600 ; N s ; B 80 -15 513 441 ;
-C 116 ; WX 600 ; N t ; B 87 -15 530 561 ;
-C 117 ; WX 600 ; N u ; B 21 -15 562 426 ;
-C 118 ; WX 600 ; N v ; B 10 -10 590 426 ;
-C 119 ; WX 600 ; N w ; B -4 -10 604 426 ;
-C 120 ; WX 600 ; N x ; B 20 0 580 426 ;
-C 121 ; WX 600 ; N y ; B 7 -157 592 426 ;
-C 122 ; WX 600 ; N z ; B 99 0 502 426 ;
-C 123 ; WX 600 ; N braceleft ; B 182 -108 437 622 ;
-C 124 ; WX 600 ; N bar ; B 275 -250 326 750 ;
-C 125 ; WX 600 ; N braceright ; B 163 -108 418 622 ;
-C 126 ; WX 600 ; N asciitilde ; B 63 197 540 320 ;
-C 161 ; WX 600 ; N exclamdown ; B 236 -157 364 430 ;
-C 162 ; WX 600 ; N cent ; B 96 -49 500 614 ;
-C 163 ; WX 600 ; N sterling ; B 84 -21 521 611 ;
-C 164 ; WX 600 ; N fraction ; B 92 -57 509 665 ;
-C 165 ; WX 600 ; N yen ; B 26 0 574 562 ;
-C 166 ; WX 600 ; N florin ; B 4 -143 539 622 ;
-C 167 ; WX 600 ; N section ; B 113 -78 488 580 ;
-C 168 ; WX 600 ; N currency ; B 73 58 527 506 ;
-C 169 ; WX 600 ; N quotesingle ; B 259 328 341 562 ;
-C 170 ; WX 600 ; N quotedblleft ; B 143 328 471 562 ;
-C 171 ; WX 600 ; N guillemotleft ; B 37 70 563 446 ;
-C 172 ; WX 600 ; N guilsinglleft ; B 149 70 451 446 ;
-C 173 ; WX 600 ; N guilsinglright ; B 149 70 451 446 ;
-C 174 ; WX 600 ; N fi ; B 3 0 597 629 ;
-C 175 ; WX 600 ; N fl ; B 3 0 597 629 ;
-C 177 ; WX 600 ; N endash ; B 75 231 525 285 ;
-C 178 ; WX 600 ; N dagger ; B 141 -78 459 580 ;
-C 179 ; WX 600 ; N daggerdbl ; B 141 -78 459 580 ;
-C 180 ; WX 600 ; N periodcentered ; B 222 189 378 327 ;
-C 182 ; WX 600 ; N paragraph ; B 50 -78 511 562 ;
-C 183 ; WX 600 ; N bullet ; B 172 130 428 383 ;
-C 184 ; WX 600 ; N quotesinglbase ; B 213 -134 376 100 ;
-C 185 ; WX 600 ; N quotedblbase ; B 143 -134 457 100 ;
-C 186 ; WX 600 ; N quotedblright ; B 143 328 457 562 ;
-C 187 ; WX 600 ; N guillemotright ; B 37 70 563 446 ;
-C 188 ; WX 600 ; N ellipsis ; B 37 -15 563 111 ;
-C 189 ; WX 600 ; N perthousand ; B 3 -15 600 622 ;
-C 191 ; WX 600 ; N questiondown ; B 108 -157 471 430 ;
-C 193 ; WX 600 ; N grave ; B 151 497 378 672 ;
-C 194 ; WX 600 ; N acute ; B 242 497 469 672 ;
-C 195 ; WX 600 ; N circumflex ; B 124 477 476 654 ;
-C 196 ; WX 600 ; N tilde ; B 105 489 503 606 ;
-C 197 ; WX 600 ; N macron ; B 120 525 480 565 ;
-C 198 ; WX 600 ; N breve ; B 153 501 447 609 ;
-C 199 ; WX 600 ; N dotaccent ; B 249 537 352 640 ;
-C 200 ; WX 600 ; N dieresis ; B 148 537 453 640 ;
-C 202 ; WX 600 ; N ring ; B 218 463 382 627 ;
-C 203 ; WX 600 ; N cedilla ; B 224 -151 362 10 ;
-C 205 ; WX 600 ; N hungarumlaut ; B 133 497 540 672 ;
-C 206 ; WX 600 ; N ogonek ; B 211 -172 407 4 ;
-C 207 ; WX 600 ; N caron ; B 124 492 476 669 ;
-C 208 ; WX 600 ; N emdash ; B 0 231 600 285 ;
-C 225 ; WX 600 ; N AE ; B 3 0 550 562 ;
-C 227 ; WX 600 ; N ordfeminine ; B 156 249 442 580 ;
-C 232 ; WX 600 ; N Lslash ; B 47 0 554 562 ;
-C 233 ; WX 600 ; N Oslash ; B 43 -80 557 629 ;
-C 234 ; WX 600 ; N OE ; B 7 0 567 562 ;
-C 235 ; WX 600 ; N ordmasculine ; B 157 249 443 580 ;
-C 241 ; WX 600 ; N ae ; B 19 -15 570 441 ;
-C 245 ; WX 600 ; N dotlessi ; B 95 0 505 426 ;
-C 248 ; WX 600 ; N lslash ; B 95 0 505 629 ;
-C 249 ; WX 600 ; N oslash ; B 62 -80 538 506 ;
-C 250 ; WX 600 ; N oe ; B 19 -15 559 441 ;
-C 251 ; WX 600 ; N germandbls ; B 48 -15 588 629 ;
-C -1 ; WX 600 ; N Idieresis ; B 96 0 504 753 ;
-C -1 ; WX 600 ; N eacute ; B 66 -15 548 672 ;
-C -1 ; WX 600 ; N abreve ; B 53 -15 559 609 ;
-C -1 ; WX 600 ; N uhungarumlaut ; B 21 -15 580 672 ;
-C -1 ; WX 600 ; N ecaron ; B 66 -15 548 669 ;
-C -1 ; WX 600 ; N Ydieresis ; B 24 0 576 753 ;
-C -1 ; WX 600 ; N divide ; B 87 48 513 467 ;
-C -1 ; WX 600 ; N Yacute ; B 24 0 576 805 ;
-C -1 ; WX 600 ; N Acircumflex ; B 3 0 597 787 ;
-C -1 ; WX 600 ; N aacute ; B 53 -15 559 672 ;
-C -1 ; WX 600 ; N Ucircumflex ; B 17 -18 583 787 ;
-C -1 ; WX 600 ; N yacute ; B 7 -157 592 672 ;
-C -1 ; WX 600 ; N scommaaccent ; B 80 -250 513 441 ;
-C -1 ; WX 600 ; N ecircumflex ; B 66 -15 548 654 ;
-C -1 ; WX 600 ; N Uring ; B 17 -18 583 760 ;
-C -1 ; WX 600 ; N Udieresis ; B 17 -18 583 753 ;
-C -1 ; WX 600 ; N aogonek ; B 53 -172 587 441 ;
-C -1 ; WX 600 ; N Uacute ; B 17 -18 583 805 ;
-C -1 ; WX 600 ; N uogonek ; B 21 -172 590 426 ;
-C -1 ; WX 600 ; N Edieresis ; B 53 0 550 753 ;
-C -1 ; WX 600 ; N Dcroat ; B 30 0 574 562 ;
-C -1 ; WX 600 ; N commaaccent ; B 198 -250 335 -58 ;
-C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ;
-C -1 ; WX 600 ; N Emacron ; B 53 0 550 698 ;
-C -1 ; WX 600 ; N ccaron ; B 66 -15 529 669 ;
-C -1 ; WX 600 ; N aring ; B 53 -15 559 627 ;
-C -1 ; WX 600 ; N Ncommaaccent ; B 7 -250 593 562 ;
-C -1 ; WX 600 ; N lacute ; B 95 0 505 805 ;
-C -1 ; WX 600 ; N agrave ; B 53 -15 559 672 ;
-C -1 ; WX 600 ; N Tcommaaccent ; B 38 -250 563 562 ;
-C -1 ; WX 600 ; N Cacute ; B 41 -18 540 805 ;
-C -1 ; WX 600 ; N atilde ; B 53 -15 559 606 ;
-C -1 ; WX 600 ; N Edotaccent ; B 53 0 550 753 ;
-C -1 ; WX 600 ; N scaron ; B 80 -15 513 669 ;
-C -1 ; WX 600 ; N scedilla ; B 80 -151 513 441 ;
-C -1 ; WX 600 ; N iacute ; B 95 0 505 672 ;
-C -1 ; WX 600 ; N lozenge ; B 18 0 443 706 ;
-C -1 ; WX 600 ; N Rcaron ; B 38 0 588 802 ;
-C -1 ; WX 600 ; N Gcommaaccent ; B 31 -250 575 580 ;
-C -1 ; WX 600 ; N ucircumflex ; B 21 -15 562 654 ;
-C -1 ; WX 600 ; N acircumflex ; B 53 -15 559 654 ;
-C -1 ; WX 600 ; N Amacron ; B 3 0 597 698 ;
-C -1 ; WX 600 ; N rcaron ; B 60 0 559 669 ;
-C -1 ; WX 600 ; N ccedilla ; B 66 -151 529 441 ;
-C -1 ; WX 600 ; N Zdotaccent ; B 86 0 514 753 ;
-C -1 ; WX 600 ; N Thorn ; B 79 0 538 562 ;
-C -1 ; WX 600 ; N Omacron ; B 43 -18 557 698 ;
-C -1 ; WX 600 ; N Racute ; B 38 0 588 805 ;
-C -1 ; WX 600 ; N Sacute ; B 72 -20 529 805 ;
-C -1 ; WX 600 ; N dcaron ; B 45 -15 715 629 ;
-C -1 ; WX 600 ; N Umacron ; B 17 -18 583 698 ;
-C -1 ; WX 600 ; N uring ; B 21 -15 562 627 ;
-C -1 ; WX 600 ; N threesuperior ; B 155 240 406 622 ;
-C -1 ; WX 600 ; N Ograve ; B 43 -18 557 805 ;
-C -1 ; WX 600 ; N Agrave ; B 3 0 597 805 ;
-C -1 ; WX 600 ; N Abreve ; B 3 0 597 732 ;
-C -1 ; WX 600 ; N multiply ; B 87 43 515 470 ;
-C -1 ; WX 600 ; N uacute ; B 21 -15 562 672 ;
-C -1 ; WX 600 ; N Tcaron ; B 38 0 563 802 ;
-C -1 ; WX 600 ; N partialdiff ; B 17 -38 459 710 ;
-C -1 ; WX 600 ; N ydieresis ; B 7 -157 592 620 ;
-C -1 ; WX 600 ; N Nacute ; B 7 -13 593 805 ;
-C -1 ; WX 600 ; N icircumflex ; B 94 0 505 654 ;
-C -1 ; WX 600 ; N Ecircumflex ; B 53 0 550 787 ;
-C -1 ; WX 600 ; N adieresis ; B 53 -15 559 620 ;
-C -1 ; WX 600 ; N edieresis ; B 66 -15 548 620 ;
-C -1 ; WX 600 ; N cacute ; B 66 -15 529 672 ;
-C -1 ; WX 600 ; N nacute ; B 26 0 575 672 ;
-C -1 ; WX 600 ; N umacron ; B 21 -15 562 565 ;
-C -1 ; WX 600 ; N Ncaron ; B 7 -13 593 802 ;
-C -1 ; WX 600 ; N Iacute ; B 96 0 504 805 ;
-C -1 ; WX 600 ; N plusminus ; B 87 44 513 558 ;
-C -1 ; WX 600 ; N brokenbar ; B 275 -175 326 675 ;
-C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ;
-C -1 ; WX 600 ; N Gbreve ; B 31 -18 575 732 ;
-C -1 ; WX 600 ; N Idotaccent ; B 96 0 504 753 ;
-C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ;
-C -1 ; WX 600 ; N Egrave ; B 53 0 550 805 ;
-C -1 ; WX 600 ; N racute ; B 60 0 559 672 ;
-C -1 ; WX 600 ; N omacron ; B 62 -15 538 565 ;
-C -1 ; WX 600 ; N Zacute ; B 86 0 514 805 ;
-C -1 ; WX 600 ; N Zcaron ; B 86 0 514 802 ;
-C -1 ; WX 600 ; N greaterequal ; B 98 0 502 710 ;
-C -1 ; WX 600 ; N Eth ; B 30 0 574 562 ;
-C -1 ; WX 600 ; N Ccedilla ; B 41 -151 540 580 ;
-C -1 ; WX 600 ; N lcommaaccent ; B 95 -250 505 629 ;
-C -1 ; WX 600 ; N tcaron ; B 87 -15 530 717 ;
-C -1 ; WX 600 ; N eogonek ; B 66 -172 548 441 ;
-C -1 ; WX 600 ; N Uogonek ; B 17 -172 583 562 ;
-C -1 ; WX 600 ; N Aacute ; B 3 0 597 805 ;
-C -1 ; WX 600 ; N Adieresis ; B 3 0 597 753 ;
-C -1 ; WX 600 ; N egrave ; B 66 -15 548 672 ;
-C -1 ; WX 600 ; N zacute ; B 99 0 502 672 ;
-C -1 ; WX 600 ; N iogonek ; B 95 -172 505 657 ;
-C -1 ; WX 600 ; N Oacute ; B 43 -18 557 805 ;
-C -1 ; WX 600 ; N oacute ; B 62 -15 538 672 ;
-C -1 ; WX 600 ; N amacron ; B 53 -15 559 565 ;
-C -1 ; WX 600 ; N sacute ; B 80 -15 513 672 ;
-C -1 ; WX 600 ; N idieresis ; B 95 0 505 620 ;
-C -1 ; WX 600 ; N Ocircumflex ; B 43 -18 557 787 ;
-C -1 ; WX 600 ; N Ugrave ; B 17 -18 583 805 ;
-C -1 ; WX 600 ; N Delta ; B 6 0 598 688 ;
-C -1 ; WX 600 ; N thorn ; B -6 -157 555 629 ;
-C -1 ; WX 600 ; N twosuperior ; B 177 249 424 622 ;
-C -1 ; WX 600 ; N Odieresis ; B 43 -18 557 753 ;
-C -1 ; WX 600 ; N mu ; B 21 -157 562 426 ;
-C -1 ; WX 600 ; N igrave ; B 95 0 505 672 ;
-C -1 ; WX 600 ; N ohungarumlaut ; B 62 -15 580 672 ;
-C -1 ; WX 600 ; N Eogonek ; B 53 -172 561 562 ;
-C -1 ; WX 600 ; N dcroat ; B 45 -15 591 629 ;
-C -1 ; WX 600 ; N threequarters ; B 8 -56 593 666 ;
-C -1 ; WX 600 ; N Scedilla ; B 72 -151 529 580 ;
-C -1 ; WX 600 ; N lcaron ; B 95 0 533 629 ;
-C -1 ; WX 600 ; N Kcommaaccent ; B 38 -250 582 562 ;
-C -1 ; WX 600 ; N Lacute ; B 47 0 554 805 ;
-C -1 ; WX 600 ; N trademark ; B -23 263 623 562 ;
-C -1 ; WX 600 ; N edotaccent ; B 66 -15 548 620 ;
-C -1 ; WX 600 ; N Igrave ; B 96 0 504 805 ;
-C -1 ; WX 600 ; N Imacron ; B 96 0 504 698 ;
-C -1 ; WX 600 ; N Lcaron ; B 47 0 554 562 ;
-C -1 ; WX 600 ; N onehalf ; B 0 -57 611 665 ;
-C -1 ; WX 600 ; N lessequal ; B 98 0 502 710 ;
-C -1 ; WX 600 ; N ocircumflex ; B 62 -15 538 654 ;
-C -1 ; WX 600 ; N ntilde ; B 26 0 575 606 ;
-C -1 ; WX 600 ; N Uhungarumlaut ; B 17 -18 590 805 ;
-C -1 ; WX 600 ; N Eacute ; B 53 0 550 805 ;
-C -1 ; WX 600 ; N emacron ; B 66 -15 548 565 ;
-C -1 ; WX 600 ; N gbreve ; B 45 -157 566 609 ;
-C -1 ; WX 600 ; N onequarter ; B 0 -57 600 665 ;
-C -1 ; WX 600 ; N Scaron ; B 72 -20 529 802 ;
-C -1 ; WX 600 ; N Scommaaccent ; B 72 -250 529 580 ;
-C -1 ; WX 600 ; N Ohungarumlaut ; B 43 -18 580 805 ;
-C -1 ; WX 600 ; N degree ; B 123 269 477 622 ;
-C -1 ; WX 600 ; N ograve ; B 62 -15 538 672 ;
-C -1 ; WX 600 ; N Ccaron ; B 41 -18 540 802 ;
-C -1 ; WX 600 ; N ugrave ; B 21 -15 562 672 ;
-C -1 ; WX 600 ; N radical ; B 3 -15 597 792 ;
-C -1 ; WX 600 ; N Dcaron ; B 43 0 574 802 ;
-C -1 ; WX 600 ; N rcommaaccent ; B 60 -250 559 441 ;
-C -1 ; WX 600 ; N Ntilde ; B 7 -13 593 729 ;
-C -1 ; WX 600 ; N otilde ; B 62 -15 538 606 ;
-C -1 ; WX 600 ; N Rcommaaccent ; B 38 -250 588 562 ;
-C -1 ; WX 600 ; N Lcommaaccent ; B 47 -250 554 562 ;
-C -1 ; WX 600 ; N Atilde ; B 3 0 597 729 ;
-C -1 ; WX 600 ; N Aogonek ; B 3 -172 608 562 ;
-C -1 ; WX 600 ; N Aring ; B 3 0 597 750 ;
-C -1 ; WX 600 ; N Otilde ; B 43 -18 557 729 ;
-C -1 ; WX 600 ; N zdotaccent ; B 99 0 502 620 ;
-C -1 ; WX 600 ; N Ecaron ; B 53 0 550 802 ;
-C -1 ; WX 600 ; N Iogonek ; B 96 -172 504 562 ;
-C -1 ; WX 600 ; N kcommaaccent ; B 43 -250 580 629 ;
-C -1 ; WX 600 ; N minus ; B 80 232 520 283 ;
-C -1 ; WX 600 ; N Icircumflex ; B 96 0 504 787 ;
-C -1 ; WX 600 ; N ncaron ; B 26 0 575 669 ;
-C -1 ; WX 600 ; N tcommaaccent ; B 87 -250 530 561 ;
-C -1 ; WX 600 ; N logicalnot ; B 87 108 513 369 ;
-C -1 ; WX 600 ; N odieresis ; B 62 -15 538 620 ;
-C -1 ; WX 600 ; N udieresis ; B 21 -15 562 620 ;
-C -1 ; WX 600 ; N notequal ; B 15 -16 540 529 ;
-C -1 ; WX 600 ; N gcommaaccent ; B 45 -157 566 708 ;
-C -1 ; WX 600 ; N eth ; B 62 -15 538 629 ;
-C -1 ; WX 600 ; N zcaron ; B 99 0 502 669 ;
-C -1 ; WX 600 ; N ncommaaccent ; B 26 -250 575 441 ;
-C -1 ; WX 600 ; N onesuperior ; B 172 249 428 622 ;
-C -1 ; WX 600 ; N imacron ; B 95 0 505 565 ;
-C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
-EndCharMetrics
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/FontsResourceAnchor.java pdftk-2.01/java/com/lowagie/text/pdf/fonts/FontsResourceAnchor.java
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/FontsResourceAnchor.java 2012-12-06 14:06:24.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/FontsResourceAnchor.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright 2004 by Paulo Soares.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf.fonts;
-
-/**
- * A class to facilitate the loading of resources
- *
- * @author Paulo Soares (psoares@consiste.pt)
- */
-public class FontsResourceAnchor {
-
- /**
- * Creates a FontsResourceAnchor
- */
- public FontsResourceAnchor() {
- }
-
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Helvetica-Bold.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Helvetica-Bold.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Helvetica-Bold.afm 2004-05-26 16:06:20.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Helvetica-Bold.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,2827 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Thu May 1 12:43:52 1997
-Comment UniqueID 43052
-Comment VMusage 37169 48194
-FontName Helvetica-Bold
-FullName Helvetica Bold
-FamilyName Helvetica
-Weight Bold
-ItalicAngle 0
-IsFixedPitch false
-CharacterSet ExtendedRoman
-FontBBox -170 -228 1003 962
-UnderlinePosition -100
-UnderlineThickness 50
-Version 002.000
-Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
-EncodingScheme AdobeStandardEncoding
-CapHeight 718
-XHeight 532
-Ascender 718
-Descender -207
-StdHW 118
-StdVW 140
-StartCharMetrics 315
-C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 333 ; N exclam ; B 90 0 244 718 ;
-C 34 ; WX 474 ; N quotedbl ; B 98 447 376 718 ;
-C 35 ; WX 556 ; N numbersign ; B 18 0 538 698 ;
-C 36 ; WX 556 ; N dollar ; B 30 -115 523 775 ;
-C 37 ; WX 889 ; N percent ; B 28 -19 861 710 ;
-C 38 ; WX 722 ; N ampersand ; B 54 -19 701 718 ;
-C 39 ; WX 278 ; N quoteright ; B 69 445 209 718 ;
-C 40 ; WX 333 ; N parenleft ; B 35 -208 314 734 ;
-C 41 ; WX 333 ; N parenright ; B 19 -208 298 734 ;
-C 42 ; WX 389 ; N asterisk ; B 27 387 362 718 ;
-C 43 ; WX 584 ; N plus ; B 40 0 544 506 ;
-C 44 ; WX 278 ; N comma ; B 64 -168 214 146 ;
-C 45 ; WX 333 ; N hyphen ; B 27 215 306 345 ;
-C 46 ; WX 278 ; N period ; B 64 0 214 146 ;
-C 47 ; WX 278 ; N slash ; B -33 -19 311 737 ;
-C 48 ; WX 556 ; N zero ; B 32 -19 524 710 ;
-C 49 ; WX 556 ; N one ; B 69 0 378 710 ;
-C 50 ; WX 556 ; N two ; B 26 0 511 710 ;
-C 51 ; WX 556 ; N three ; B 27 -19 516 710 ;
-C 52 ; WX 556 ; N four ; B 27 0 526 710 ;
-C 53 ; WX 556 ; N five ; B 27 -19 516 698 ;
-C 54 ; WX 556 ; N six ; B 31 -19 520 710 ;
-C 55 ; WX 556 ; N seven ; B 25 0 528 698 ;
-C 56 ; WX 556 ; N eight ; B 32 -19 524 710 ;
-C 57 ; WX 556 ; N nine ; B 30 -19 522 710 ;
-C 58 ; WX 333 ; N colon ; B 92 0 242 512 ;
-C 59 ; WX 333 ; N semicolon ; B 92 -168 242 512 ;
-C 60 ; WX 584 ; N less ; B 38 -8 546 514 ;
-C 61 ; WX 584 ; N equal ; B 40 87 544 419 ;
-C 62 ; WX 584 ; N greater ; B 38 -8 546 514 ;
-C 63 ; WX 611 ; N question ; B 60 0 556 727 ;
-C 64 ; WX 975 ; N at ; B 118 -19 856 737 ;
-C 65 ; WX 722 ; N A ; B 20 0 702 718 ;
-C 66 ; WX 722 ; N B ; B 76 0 669 718 ;
-C 67 ; WX 722 ; N C ; B 44 -19 684 737 ;
-C 68 ; WX 722 ; N D ; B 76 0 685 718 ;
-C 69 ; WX 667 ; N E ; B 76 0 621 718 ;
-C 70 ; WX 611 ; N F ; B 76 0 587 718 ;
-C 71 ; WX 778 ; N G ; B 44 -19 713 737 ;
-C 72 ; WX 722 ; N H ; B 71 0 651 718 ;
-C 73 ; WX 278 ; N I ; B 64 0 214 718 ;
-C 74 ; WX 556 ; N J ; B 22 -18 484 718 ;
-C 75 ; WX 722 ; N K ; B 87 0 722 718 ;
-C 76 ; WX 611 ; N L ; B 76 0 583 718 ;
-C 77 ; WX 833 ; N M ; B 69 0 765 718 ;
-C 78 ; WX 722 ; N N ; B 69 0 654 718 ;
-C 79 ; WX 778 ; N O ; B 44 -19 734 737 ;
-C 80 ; WX 667 ; N P ; B 76 0 627 718 ;
-C 81 ; WX 778 ; N Q ; B 44 -52 737 737 ;
-C 82 ; WX 722 ; N R ; B 76 0 677 718 ;
-C 83 ; WX 667 ; N S ; B 39 -19 629 737 ;
-C 84 ; WX 611 ; N T ; B 14 0 598 718 ;
-C 85 ; WX 722 ; N U ; B 72 -19 651 718 ;
-C 86 ; WX 667 ; N V ; B 19 0 648 718 ;
-C 87 ; WX 944 ; N W ; B 16 0 929 718 ;
-C 88 ; WX 667 ; N X ; B 14 0 653 718 ;
-C 89 ; WX 667 ; N Y ; B 15 0 653 718 ;
-C 90 ; WX 611 ; N Z ; B 25 0 586 718 ;
-C 91 ; WX 333 ; N bracketleft ; B 63 -196 309 722 ;
-C 92 ; WX 278 ; N backslash ; B -33 -19 311 737 ;
-C 93 ; WX 333 ; N bracketright ; B 24 -196 270 722 ;
-C 94 ; WX 584 ; N asciicircum ; B 62 323 522 698 ;
-C 95 ; WX 556 ; N underscore ; B 0 -125 556 -75 ;
-C 96 ; WX 278 ; N quoteleft ; B 69 454 209 727 ;
-C 97 ; WX 556 ; N a ; B 29 -14 527 546 ;
-C 98 ; WX 611 ; N b ; B 61 -14 578 718 ;
-C 99 ; WX 556 ; N c ; B 34 -14 524 546 ;
-C 100 ; WX 611 ; N d ; B 34 -14 551 718 ;
-C 101 ; WX 556 ; N e ; B 23 -14 528 546 ;
-C 102 ; WX 333 ; N f ; B 10 0 318 727 ; L i fi ; L l fl ;
-C 103 ; WX 611 ; N g ; B 40 -217 553 546 ;
-C 104 ; WX 611 ; N h ; B 65 0 546 718 ;
-C 105 ; WX 278 ; N i ; B 69 0 209 725 ;
-C 106 ; WX 278 ; N j ; B 3 -214 209 725 ;
-C 107 ; WX 556 ; N k ; B 69 0 562 718 ;
-C 108 ; WX 278 ; N l ; B 69 0 209 718 ;
-C 109 ; WX 889 ; N m ; B 64 0 826 546 ;
-C 110 ; WX 611 ; N n ; B 65 0 546 546 ;
-C 111 ; WX 611 ; N o ; B 34 -14 578 546 ;
-C 112 ; WX 611 ; N p ; B 62 -207 578 546 ;
-C 113 ; WX 611 ; N q ; B 34 -207 552 546 ;
-C 114 ; WX 389 ; N r ; B 64 0 373 546 ;
-C 115 ; WX 556 ; N s ; B 30 -14 519 546 ;
-C 116 ; WX 333 ; N t ; B 10 -6 309 676 ;
-C 117 ; WX 611 ; N u ; B 66 -14 545 532 ;
-C 118 ; WX 556 ; N v ; B 13 0 543 532 ;
-C 119 ; WX 778 ; N w ; B 10 0 769 532 ;
-C 120 ; WX 556 ; N x ; B 15 0 541 532 ;
-C 121 ; WX 556 ; N y ; B 10 -214 539 532 ;
-C 122 ; WX 500 ; N z ; B 20 0 480 532 ;
-C 123 ; WX 389 ; N braceleft ; B 48 -196 365 722 ;
-C 124 ; WX 280 ; N bar ; B 84 -225 196 775 ;
-C 125 ; WX 389 ; N braceright ; B 24 -196 341 722 ;
-C 126 ; WX 584 ; N asciitilde ; B 61 163 523 343 ;
-C 161 ; WX 333 ; N exclamdown ; B 90 -186 244 532 ;
-C 162 ; WX 556 ; N cent ; B 34 -118 524 628 ;
-C 163 ; WX 556 ; N sterling ; B 28 -16 541 718 ;
-C 164 ; WX 167 ; N fraction ; B -170 -19 336 710 ;
-C 165 ; WX 556 ; N yen ; B -9 0 565 698 ;
-C 166 ; WX 556 ; N florin ; B -10 -210 516 737 ;
-C 167 ; WX 556 ; N section ; B 34 -184 522 727 ;
-C 168 ; WX 556 ; N currency ; B -3 76 559 636 ;
-C 169 ; WX 238 ; N quotesingle ; B 70 447 168 718 ;
-C 170 ; WX 500 ; N quotedblleft ; B 64 454 436 727 ;
-C 171 ; WX 556 ; N guillemotleft ; B 88 76 468 484 ;
-C 172 ; WX 333 ; N guilsinglleft ; B 83 76 250 484 ;
-C 173 ; WX 333 ; N guilsinglright ; B 83 76 250 484 ;
-C 174 ; WX 611 ; N fi ; B 10 0 542 727 ;
-C 175 ; WX 611 ; N fl ; B 10 0 542 727 ;
-C 177 ; WX 556 ; N endash ; B 0 227 556 333 ;
-C 178 ; WX 556 ; N dagger ; B 36 -171 520 718 ;
-C 179 ; WX 556 ; N daggerdbl ; B 36 -171 520 718 ;
-C 180 ; WX 278 ; N periodcentered ; B 58 172 220 334 ;
-C 182 ; WX 556 ; N paragraph ; B -8 -191 539 700 ;
-C 183 ; WX 350 ; N bullet ; B 10 194 340 524 ;
-C 184 ; WX 278 ; N quotesinglbase ; B 69 -146 209 127 ;
-C 185 ; WX 500 ; N quotedblbase ; B 64 -146 436 127 ;
-C 186 ; WX 500 ; N quotedblright ; B 64 445 436 718 ;
-C 187 ; WX 556 ; N guillemotright ; B 88 76 468 484 ;
-C 188 ; WX 1000 ; N ellipsis ; B 92 0 908 146 ;
-C 189 ; WX 1000 ; N perthousand ; B -3 -19 1003 710 ;
-C 191 ; WX 611 ; N questiondown ; B 55 -195 551 532 ;
-C 193 ; WX 333 ; N grave ; B -23 604 225 750 ;
-C 194 ; WX 333 ; N acute ; B 108 604 356 750 ;
-C 195 ; WX 333 ; N circumflex ; B -10 604 343 750 ;
-C 196 ; WX 333 ; N tilde ; B -17 610 350 737 ;
-C 197 ; WX 333 ; N macron ; B -6 604 339 678 ;
-C 198 ; WX 333 ; N breve ; B -2 604 335 750 ;
-C 199 ; WX 333 ; N dotaccent ; B 104 614 230 729 ;
-C 200 ; WX 333 ; N dieresis ; B 6 614 327 729 ;
-C 202 ; WX 333 ; N ring ; B 59 568 275 776 ;
-C 203 ; WX 333 ; N cedilla ; B 6 -228 245 0 ;
-C 205 ; WX 333 ; N hungarumlaut ; B 9 604 486 750 ;
-C 206 ; WX 333 ; N ogonek ; B 71 -228 304 0 ;
-C 207 ; WX 333 ; N caron ; B -10 604 343 750 ;
-C 208 ; WX 1000 ; N emdash ; B 0 227 1000 333 ;
-C 225 ; WX 1000 ; N AE ; B 5 0 954 718 ;
-C 227 ; WX 370 ; N ordfeminine ; B 22 401 347 737 ;
-C 232 ; WX 611 ; N Lslash ; B -20 0 583 718 ;
-C 233 ; WX 778 ; N Oslash ; B 33 -27 744 745 ;
-C 234 ; WX 1000 ; N OE ; B 37 -19 961 737 ;
-C 235 ; WX 365 ; N ordmasculine ; B 6 401 360 737 ;
-C 241 ; WX 889 ; N ae ; B 29 -14 858 546 ;
-C 245 ; WX 278 ; N dotlessi ; B 69 0 209 532 ;
-C 248 ; WX 278 ; N lslash ; B -18 0 296 718 ;
-C 249 ; WX 611 ; N oslash ; B 22 -29 589 560 ;
-C 250 ; WX 944 ; N oe ; B 34 -14 912 546 ;
-C 251 ; WX 611 ; N germandbls ; B 69 -14 579 731 ;
-C -1 ; WX 278 ; N Idieresis ; B -21 0 300 915 ;
-C -1 ; WX 556 ; N eacute ; B 23 -14 528 750 ;
-C -1 ; WX 556 ; N abreve ; B 29 -14 527 750 ;
-C -1 ; WX 611 ; N uhungarumlaut ; B 66 -14 625 750 ;
-C -1 ; WX 556 ; N ecaron ; B 23 -14 528 750 ;
-C -1 ; WX 667 ; N Ydieresis ; B 15 0 653 915 ;
-C -1 ; WX 584 ; N divide ; B 40 -42 544 548 ;
-C -1 ; WX 667 ; N Yacute ; B 15 0 653 936 ;
-C -1 ; WX 722 ; N Acircumflex ; B 20 0 702 936 ;
-C -1 ; WX 556 ; N aacute ; B 29 -14 527 750 ;
-C -1 ; WX 722 ; N Ucircumflex ; B 72 -19 651 936 ;
-C -1 ; WX 556 ; N yacute ; B 10 -214 539 750 ;
-C -1 ; WX 556 ; N scommaaccent ; B 30 -228 519 546 ;
-C -1 ; WX 556 ; N ecircumflex ; B 23 -14 528 750 ;
-C -1 ; WX 722 ; N Uring ; B 72 -19 651 962 ;
-C -1 ; WX 722 ; N Udieresis ; B 72 -19 651 915 ;
-C -1 ; WX 556 ; N aogonek ; B 29 -224 545 546 ;
-C -1 ; WX 722 ; N Uacute ; B 72 -19 651 936 ;
-C -1 ; WX 611 ; N uogonek ; B 66 -228 545 532 ;
-C -1 ; WX 667 ; N Edieresis ; B 76 0 621 915 ;
-C -1 ; WX 722 ; N Dcroat ; B -5 0 685 718 ;
-C -1 ; WX 250 ; N commaaccent ; B 64 -228 199 -50 ;
-C -1 ; WX 737 ; N copyright ; B -11 -19 749 737 ;
-C -1 ; WX 667 ; N Emacron ; B 76 0 621 864 ;
-C -1 ; WX 556 ; N ccaron ; B 34 -14 524 750 ;
-C -1 ; WX 556 ; N aring ; B 29 -14 527 776 ;
-C -1 ; WX 722 ; N Ncommaaccent ; B 69 -228 654 718 ;
-C -1 ; WX 278 ; N lacute ; B 69 0 329 936 ;
-C -1 ; WX 556 ; N agrave ; B 29 -14 527 750 ;
-C -1 ; WX 611 ; N Tcommaaccent ; B 14 -228 598 718 ;
-C -1 ; WX 722 ; N Cacute ; B 44 -19 684 936 ;
-C -1 ; WX 556 ; N atilde ; B 29 -14 527 737 ;
-C -1 ; WX 667 ; N Edotaccent ; B 76 0 621 915 ;
-C -1 ; WX 556 ; N scaron ; B 30 -14 519 750 ;
-C -1 ; WX 556 ; N scedilla ; B 30 -228 519 546 ;
-C -1 ; WX 278 ; N iacute ; B 69 0 329 750 ;
-C -1 ; WX 494 ; N lozenge ; B 10 0 484 745 ;
-C -1 ; WX 722 ; N Rcaron ; B 76 0 677 936 ;
-C -1 ; WX 778 ; N Gcommaaccent ; B 44 -228 713 737 ;
-C -1 ; WX 611 ; N ucircumflex ; B 66 -14 545 750 ;
-C -1 ; WX 556 ; N acircumflex ; B 29 -14 527 750 ;
-C -1 ; WX 722 ; N Amacron ; B 20 0 702 864 ;
-C -1 ; WX 389 ; N rcaron ; B 18 0 373 750 ;
-C -1 ; WX 556 ; N ccedilla ; B 34 -228 524 546 ;
-C -1 ; WX 611 ; N Zdotaccent ; B 25 0 586 915 ;
-C -1 ; WX 667 ; N Thorn ; B 76 0 627 718 ;
-C -1 ; WX 778 ; N Omacron ; B 44 -19 734 864 ;
-C -1 ; WX 722 ; N Racute ; B 76 0 677 936 ;
-C -1 ; WX 667 ; N Sacute ; B 39 -19 629 936 ;
-C -1 ; WX 743 ; N dcaron ; B 34 -14 750 718 ;
-C -1 ; WX 722 ; N Umacron ; B 72 -19 651 864 ;
-C -1 ; WX 611 ; N uring ; B 66 -14 545 776 ;
-C -1 ; WX 333 ; N threesuperior ; B 8 271 326 710 ;
-C -1 ; WX 778 ; N Ograve ; B 44 -19 734 936 ;
-C -1 ; WX 722 ; N Agrave ; B 20 0 702 936 ;
-C -1 ; WX 722 ; N Abreve ; B 20 0 702 936 ;
-C -1 ; WX 584 ; N multiply ; B 40 1 545 505 ;
-C -1 ; WX 611 ; N uacute ; B 66 -14 545 750 ;
-C -1 ; WX 611 ; N Tcaron ; B 14 0 598 936 ;
-C -1 ; WX 494 ; N partialdiff ; B 11 -21 494 750 ;
-C -1 ; WX 556 ; N ydieresis ; B 10 -214 539 729 ;
-C -1 ; WX 722 ; N Nacute ; B 69 0 654 936 ;
-C -1 ; WX 278 ; N icircumflex ; B -37 0 316 750 ;
-C -1 ; WX 667 ; N Ecircumflex ; B 76 0 621 936 ;
-C -1 ; WX 556 ; N adieresis ; B 29 -14 527 729 ;
-C -1 ; WX 556 ; N edieresis ; B 23 -14 528 729 ;
-C -1 ; WX 556 ; N cacute ; B 34 -14 524 750 ;
-C -1 ; WX 611 ; N nacute ; B 65 0 546 750 ;
-C -1 ; WX 611 ; N umacron ; B 66 -14 545 678 ;
-C -1 ; WX 722 ; N Ncaron ; B 69 0 654 936 ;
-C -1 ; WX 278 ; N Iacute ; B 64 0 329 936 ;
-C -1 ; WX 584 ; N plusminus ; B 40 0 544 506 ;
-C -1 ; WX 280 ; N brokenbar ; B 84 -150 196 700 ;
-C -1 ; WX 737 ; N registered ; B -11 -19 748 737 ;
-C -1 ; WX 778 ; N Gbreve ; B 44 -19 713 936 ;
-C -1 ; WX 278 ; N Idotaccent ; B 64 0 214 915 ;
-C -1 ; WX 600 ; N summation ; B 14 -10 585 706 ;
-C -1 ; WX 667 ; N Egrave ; B 76 0 621 936 ;
-C -1 ; WX 389 ; N racute ; B 64 0 384 750 ;
-C -1 ; WX 611 ; N omacron ; B 34 -14 578 678 ;
-C -1 ; WX 611 ; N Zacute ; B 25 0 586 936 ;
-C -1 ; WX 611 ; N Zcaron ; B 25 0 586 936 ;
-C -1 ; WX 549 ; N greaterequal ; B 26 0 523 704 ;
-C -1 ; WX 722 ; N Eth ; B -5 0 685 718 ;
-C -1 ; WX 722 ; N Ccedilla ; B 44 -228 684 737 ;
-C -1 ; WX 278 ; N lcommaaccent ; B 69 -228 213 718 ;
-C -1 ; WX 389 ; N tcaron ; B 10 -6 421 878 ;
-C -1 ; WX 556 ; N eogonek ; B 23 -228 528 546 ;
-C -1 ; WX 722 ; N Uogonek ; B 72 -228 651 718 ;
-C -1 ; WX 722 ; N Aacute ; B 20 0 702 936 ;
-C -1 ; WX 722 ; N Adieresis ; B 20 0 702 915 ;
-C -1 ; WX 556 ; N egrave ; B 23 -14 528 750 ;
-C -1 ; WX 500 ; N zacute ; B 20 0 480 750 ;
-C -1 ; WX 278 ; N iogonek ; B 16 -224 249 725 ;
-C -1 ; WX 778 ; N Oacute ; B 44 -19 734 936 ;
-C -1 ; WX 611 ; N oacute ; B 34 -14 578 750 ;
-C -1 ; WX 556 ; N amacron ; B 29 -14 527 678 ;
-C -1 ; WX 556 ; N sacute ; B 30 -14 519 750 ;
-C -1 ; WX 278 ; N idieresis ; B -21 0 300 729 ;
-C -1 ; WX 778 ; N Ocircumflex ; B 44 -19 734 936 ;
-C -1 ; WX 722 ; N Ugrave ; B 72 -19 651 936 ;
-C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
-C -1 ; WX 611 ; N thorn ; B 62 -208 578 718 ;
-C -1 ; WX 333 ; N twosuperior ; B 9 283 324 710 ;
-C -1 ; WX 778 ; N Odieresis ; B 44 -19 734 915 ;
-C -1 ; WX 611 ; N mu ; B 66 -207 545 532 ;
-C -1 ; WX 278 ; N igrave ; B -50 0 209 750 ;
-C -1 ; WX 611 ; N ohungarumlaut ; B 34 -14 625 750 ;
-C -1 ; WX 667 ; N Eogonek ; B 76 -224 639 718 ;
-C -1 ; WX 611 ; N dcroat ; B 34 -14 650 718 ;
-C -1 ; WX 834 ; N threequarters ; B 16 -19 799 710 ;
-C -1 ; WX 667 ; N Scedilla ; B 39 -228 629 737 ;
-C -1 ; WX 400 ; N lcaron ; B 69 0 408 718 ;
-C -1 ; WX 722 ; N Kcommaaccent ; B 87 -228 722 718 ;
-C -1 ; WX 611 ; N Lacute ; B 76 0 583 936 ;
-C -1 ; WX 1000 ; N trademark ; B 44 306 956 718 ;
-C -1 ; WX 556 ; N edotaccent ; B 23 -14 528 729 ;
-C -1 ; WX 278 ; N Igrave ; B -50 0 214 936 ;
-C -1 ; WX 278 ; N Imacron ; B -33 0 312 864 ;
-C -1 ; WX 611 ; N Lcaron ; B 76 0 583 718 ;
-C -1 ; WX 834 ; N onehalf ; B 26 -19 794 710 ;
-C -1 ; WX 549 ; N lessequal ; B 29 0 526 704 ;
-C -1 ; WX 611 ; N ocircumflex ; B 34 -14 578 750 ;
-C -1 ; WX 611 ; N ntilde ; B 65 0 546 737 ;
-C -1 ; WX 722 ; N Uhungarumlaut ; B 72 -19 681 936 ;
-C -1 ; WX 667 ; N Eacute ; B 76 0 621 936 ;
-C -1 ; WX 556 ; N emacron ; B 23 -14 528 678 ;
-C -1 ; WX 611 ; N gbreve ; B 40 -217 553 750 ;
-C -1 ; WX 834 ; N onequarter ; B 26 -19 766 710 ;
-C -1 ; WX 667 ; N Scaron ; B 39 -19 629 936 ;
-C -1 ; WX 667 ; N Scommaaccent ; B 39 -228 629 737 ;
-C -1 ; WX 778 ; N Ohungarumlaut ; B 44 -19 734 936 ;
-C -1 ; WX 400 ; N degree ; B 57 426 343 712 ;
-C -1 ; WX 611 ; N ograve ; B 34 -14 578 750 ;
-C -1 ; WX 722 ; N Ccaron ; B 44 -19 684 936 ;
-C -1 ; WX 611 ; N ugrave ; B 66 -14 545 750 ;
-C -1 ; WX 549 ; N radical ; B 10 -46 512 850 ;
-C -1 ; WX 722 ; N Dcaron ; B 76 0 685 936 ;
-C -1 ; WX 389 ; N rcommaaccent ; B 64 -228 373 546 ;
-C -1 ; WX 722 ; N Ntilde ; B 69 0 654 923 ;
-C -1 ; WX 611 ; N otilde ; B 34 -14 578 737 ;
-C -1 ; WX 722 ; N Rcommaaccent ; B 76 -228 677 718 ;
-C -1 ; WX 611 ; N Lcommaaccent ; B 76 -228 583 718 ;
-C -1 ; WX 722 ; N Atilde ; B 20 0 702 923 ;
-C -1 ; WX 722 ; N Aogonek ; B 20 -224 742 718 ;
-C -1 ; WX 722 ; N Aring ; B 20 0 702 962 ;
-C -1 ; WX 778 ; N Otilde ; B 44 -19 734 923 ;
-C -1 ; WX 500 ; N zdotaccent ; B 20 0 480 729 ;
-C -1 ; WX 667 ; N Ecaron ; B 76 0 621 936 ;
-C -1 ; WX 278 ; N Iogonek ; B -11 -228 222 718 ;
-C -1 ; WX 556 ; N kcommaaccent ; B 69 -228 562 718 ;
-C -1 ; WX 584 ; N minus ; B 40 197 544 309 ;
-C -1 ; WX 278 ; N Icircumflex ; B -37 0 316 936 ;
-C -1 ; WX 611 ; N ncaron ; B 65 0 546 750 ;
-C -1 ; WX 333 ; N tcommaaccent ; B 10 -228 309 676 ;
-C -1 ; WX 584 ; N logicalnot ; B 40 108 544 419 ;
-C -1 ; WX 611 ; N odieresis ; B 34 -14 578 729 ;
-C -1 ; WX 611 ; N udieresis ; B 66 -14 545 729 ;
-C -1 ; WX 549 ; N notequal ; B 15 -49 540 570 ;
-C -1 ; WX 611 ; N gcommaaccent ; B 40 -217 553 850 ;
-C -1 ; WX 611 ; N eth ; B 34 -14 578 737 ;
-C -1 ; WX 500 ; N zcaron ; B 20 0 480 750 ;
-C -1 ; WX 611 ; N ncommaaccent ; B 65 -228 546 546 ;
-C -1 ; WX 333 ; N onesuperior ; B 26 283 237 710 ;
-C -1 ; WX 278 ; N imacron ; B -8 0 285 678 ;
-C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ;
-EndCharMetrics
-StartKernData
-StartKernPairs 2481
-KPX A C -40
-KPX A Cacute -40
-KPX A Ccaron -40
-KPX A Ccedilla -40
-KPX A G -50
-KPX A Gbreve -50
-KPX A Gcommaaccent -50
-KPX A O -40
-KPX A Oacute -40
-KPX A Ocircumflex -40
-KPX A Odieresis -40
-KPX A Ograve -40
-KPX A Ohungarumlaut -40
-KPX A Omacron -40
-KPX A Oslash -40
-KPX A Otilde -40
-KPX A Q -40
-KPX A T -90
-KPX A Tcaron -90
-KPX A Tcommaaccent -90
-KPX A U -50
-KPX A Uacute -50
-KPX A Ucircumflex -50
-KPX A Udieresis -50
-KPX A Ugrave -50
-KPX A Uhungarumlaut -50
-KPX A Umacron -50
-KPX A Uogonek -50
-KPX A Uring -50
-KPX A V -80
-KPX A W -60
-KPX A Y -110
-KPX A Yacute -110
-KPX A Ydieresis -110
-KPX A u -30
-KPX A uacute -30
-KPX A ucircumflex -30
-KPX A udieresis -30
-KPX A ugrave -30
-KPX A uhungarumlaut -30
-KPX A umacron -30
-KPX A uogonek -30
-KPX A uring -30
-KPX A v -40
-KPX A w -30
-KPX A y -30
-KPX A yacute -30
-KPX A ydieresis -30
-KPX Aacute C -40
-KPX Aacute Cacute -40
-KPX Aacute Ccaron -40
-KPX Aacute Ccedilla -40
-KPX Aacute G -50
-KPX Aacute Gbreve -50
-KPX Aacute Gcommaaccent -50
-KPX Aacute O -40
-KPX Aacute Oacute -40
-KPX Aacute Ocircumflex -40
-KPX Aacute Odieresis -40
-KPX Aacute Ograve -40
-KPX Aacute Ohungarumlaut -40
-KPX Aacute Omacron -40
-KPX Aacute Oslash -40
-KPX Aacute Otilde -40
-KPX Aacute Q -40
-KPX Aacute T -90
-KPX Aacute Tcaron -90
-KPX Aacute Tcommaaccent -90
-KPX Aacute U -50
-KPX Aacute Uacute -50
-KPX Aacute Ucircumflex -50
-KPX Aacute Udieresis -50
-KPX Aacute Ugrave -50
-KPX Aacute Uhungarumlaut -50
-KPX Aacute Umacron -50
-KPX Aacute Uogonek -50
-KPX Aacute Uring -50
-KPX Aacute V -80
-KPX Aacute W -60
-KPX Aacute Y -110
-KPX Aacute Yacute -110
-KPX Aacute Ydieresis -110
-KPX Aacute u -30
-KPX Aacute uacute -30
-KPX Aacute ucircumflex -30
-KPX Aacute udieresis -30
-KPX Aacute ugrave -30
-KPX Aacute uhungarumlaut -30
-KPX Aacute umacron -30
-KPX Aacute uogonek -30
-KPX Aacute uring -30
-KPX Aacute v -40
-KPX Aacute w -30
-KPX Aacute y -30
-KPX Aacute yacute -30
-KPX Aacute ydieresis -30
-KPX Abreve C -40
-KPX Abreve Cacute -40
-KPX Abreve Ccaron -40
-KPX Abreve Ccedilla -40
-KPX Abreve G -50
-KPX Abreve Gbreve -50
-KPX Abreve Gcommaaccent -50
-KPX Abreve O -40
-KPX Abreve Oacute -40
-KPX Abreve Ocircumflex -40
-KPX Abreve Odieresis -40
-KPX Abreve Ograve -40
-KPX Abreve Ohungarumlaut -40
-KPX Abreve Omacron -40
-KPX Abreve Oslash -40
-KPX Abreve Otilde -40
-KPX Abreve Q -40
-KPX Abreve T -90
-KPX Abreve Tcaron -90
-KPX Abreve Tcommaaccent -90
-KPX Abreve U -50
-KPX Abreve Uacute -50
-KPX Abreve Ucircumflex -50
-KPX Abreve Udieresis -50
-KPX Abreve Ugrave -50
-KPX Abreve Uhungarumlaut -50
-KPX Abreve Umacron -50
-KPX Abreve Uogonek -50
-KPX Abreve Uring -50
-KPX Abreve V -80
-KPX Abreve W -60
-KPX Abreve Y -110
-KPX Abreve Yacute -110
-KPX Abreve Ydieresis -110
-KPX Abreve u -30
-KPX Abreve uacute -30
-KPX Abreve ucircumflex -30
-KPX Abreve udieresis -30
-KPX Abreve ugrave -30
-KPX Abreve uhungarumlaut -30
-KPX Abreve umacron -30
-KPX Abreve uogonek -30
-KPX Abreve uring -30
-KPX Abreve v -40
-KPX Abreve w -30
-KPX Abreve y -30
-KPX Abreve yacute -30
-KPX Abreve ydieresis -30
-KPX Acircumflex C -40
-KPX Acircumflex Cacute -40
-KPX Acircumflex Ccaron -40
-KPX Acircumflex Ccedilla -40
-KPX Acircumflex G -50
-KPX Acircumflex Gbreve -50
-KPX Acircumflex Gcommaaccent -50
-KPX Acircumflex O -40
-KPX Acircumflex Oacute -40
-KPX Acircumflex Ocircumflex -40
-KPX Acircumflex Odieresis -40
-KPX Acircumflex Ograve -40
-KPX Acircumflex Ohungarumlaut -40
-KPX Acircumflex Omacron -40
-KPX Acircumflex Oslash -40
-KPX Acircumflex Otilde -40
-KPX Acircumflex Q -40
-KPX Acircumflex T -90
-KPX Acircumflex Tcaron -90
-KPX Acircumflex Tcommaaccent -90
-KPX Acircumflex U -50
-KPX Acircumflex Uacute -50
-KPX Acircumflex Ucircumflex -50
-KPX Acircumflex Udieresis -50
-KPX Acircumflex Ugrave -50
-KPX Acircumflex Uhungarumlaut -50
-KPX Acircumflex Umacron -50
-KPX Acircumflex Uogonek -50
-KPX Acircumflex Uring -50
-KPX Acircumflex V -80
-KPX Acircumflex W -60
-KPX Acircumflex Y -110
-KPX Acircumflex Yacute -110
-KPX Acircumflex Ydieresis -110
-KPX Acircumflex u -30
-KPX Acircumflex uacute -30
-KPX Acircumflex ucircumflex -30
-KPX Acircumflex udieresis -30
-KPX Acircumflex ugrave -30
-KPX Acircumflex uhungarumlaut -30
-KPX Acircumflex umacron -30
-KPX Acircumflex uogonek -30
-KPX Acircumflex uring -30
-KPX Acircumflex v -40
-KPX Acircumflex w -30
-KPX Acircumflex y -30
-KPX Acircumflex yacute -30
-KPX Acircumflex ydieresis -30
-KPX Adieresis C -40
-KPX Adieresis Cacute -40
-KPX Adieresis Ccaron -40
-KPX Adieresis Ccedilla -40
-KPX Adieresis G -50
-KPX Adieresis Gbreve -50
-KPX Adieresis Gcommaaccent -50
-KPX Adieresis O -40
-KPX Adieresis Oacute -40
-KPX Adieresis Ocircumflex -40
-KPX Adieresis Odieresis -40
-KPX Adieresis Ograve -40
-KPX Adieresis Ohungarumlaut -40
-KPX Adieresis Omacron -40
-KPX Adieresis Oslash -40
-KPX Adieresis Otilde -40
-KPX Adieresis Q -40
-KPX Adieresis T -90
-KPX Adieresis Tcaron -90
-KPX Adieresis Tcommaaccent -90
-KPX Adieresis U -50
-KPX Adieresis Uacute -50
-KPX Adieresis Ucircumflex -50
-KPX Adieresis Udieresis -50
-KPX Adieresis Ugrave -50
-KPX Adieresis Uhungarumlaut -50
-KPX Adieresis Umacron -50
-KPX Adieresis Uogonek -50
-KPX Adieresis Uring -50
-KPX Adieresis V -80
-KPX Adieresis W -60
-KPX Adieresis Y -110
-KPX Adieresis Yacute -110
-KPX Adieresis Ydieresis -110
-KPX Adieresis u -30
-KPX Adieresis uacute -30
-KPX Adieresis ucircumflex -30
-KPX Adieresis udieresis -30
-KPX Adieresis ugrave -30
-KPX Adieresis uhungarumlaut -30
-KPX Adieresis umacron -30
-KPX Adieresis uogonek -30
-KPX Adieresis uring -30
-KPX Adieresis v -40
-KPX Adieresis w -30
-KPX Adieresis y -30
-KPX Adieresis yacute -30
-KPX Adieresis ydieresis -30
-KPX Agrave C -40
-KPX Agrave Cacute -40
-KPX Agrave Ccaron -40
-KPX Agrave Ccedilla -40
-KPX Agrave G -50
-KPX Agrave Gbreve -50
-KPX Agrave Gcommaaccent -50
-KPX Agrave O -40
-KPX Agrave Oacute -40
-KPX Agrave Ocircumflex -40
-KPX Agrave Odieresis -40
-KPX Agrave Ograve -40
-KPX Agrave Ohungarumlaut -40
-KPX Agrave Omacron -40
-KPX Agrave Oslash -40
-KPX Agrave Otilde -40
-KPX Agrave Q -40
-KPX Agrave T -90
-KPX Agrave Tcaron -90
-KPX Agrave Tcommaaccent -90
-KPX Agrave U -50
-KPX Agrave Uacute -50
-KPX Agrave Ucircumflex -50
-KPX Agrave Udieresis -50
-KPX Agrave Ugrave -50
-KPX Agrave Uhungarumlaut -50
-KPX Agrave Umacron -50
-KPX Agrave Uogonek -50
-KPX Agrave Uring -50
-KPX Agrave V -80
-KPX Agrave W -60
-KPX Agrave Y -110
-KPX Agrave Yacute -110
-KPX Agrave Ydieresis -110
-KPX Agrave u -30
-KPX Agrave uacute -30
-KPX Agrave ucircumflex -30
-KPX Agrave udieresis -30
-KPX Agrave ugrave -30
-KPX Agrave uhungarumlaut -30
-KPX Agrave umacron -30
-KPX Agrave uogonek -30
-KPX Agrave uring -30
-KPX Agrave v -40
-KPX Agrave w -30
-KPX Agrave y -30
-KPX Agrave yacute -30
-KPX Agrave ydieresis -30
-KPX Amacron C -40
-KPX Amacron Cacute -40
-KPX Amacron Ccaron -40
-KPX Amacron Ccedilla -40
-KPX Amacron G -50
-KPX Amacron Gbreve -50
-KPX Amacron Gcommaaccent -50
-KPX Amacron O -40
-KPX Amacron Oacute -40
-KPX Amacron Ocircumflex -40
-KPX Amacron Odieresis -40
-KPX Amacron Ograve -40
-KPX Amacron Ohungarumlaut -40
-KPX Amacron Omacron -40
-KPX Amacron Oslash -40
-KPX Amacron Otilde -40
-KPX Amacron Q -40
-KPX Amacron T -90
-KPX Amacron Tcaron -90
-KPX Amacron Tcommaaccent -90
-KPX Amacron U -50
-KPX Amacron Uacute -50
-KPX Amacron Ucircumflex -50
-KPX Amacron Udieresis -50
-KPX Amacron Ugrave -50
-KPX Amacron Uhungarumlaut -50
-KPX Amacron Umacron -50
-KPX Amacron Uogonek -50
-KPX Amacron Uring -50
-KPX Amacron V -80
-KPX Amacron W -60
-KPX Amacron Y -110
-KPX Amacron Yacute -110
-KPX Amacron Ydieresis -110
-KPX Amacron u -30
-KPX Amacron uacute -30
-KPX Amacron ucircumflex -30
-KPX Amacron udieresis -30
-KPX Amacron ugrave -30
-KPX Amacron uhungarumlaut -30
-KPX Amacron umacron -30
-KPX Amacron uogonek -30
-KPX Amacron uring -30
-KPX Amacron v -40
-KPX Amacron w -30
-KPX Amacron y -30
-KPX Amacron yacute -30
-KPX Amacron ydieresis -30
-KPX Aogonek C -40
-KPX Aogonek Cacute -40
-KPX Aogonek Ccaron -40
-KPX Aogonek Ccedilla -40
-KPX Aogonek G -50
-KPX Aogonek Gbreve -50
-KPX Aogonek Gcommaaccent -50
-KPX Aogonek O -40
-KPX Aogonek Oacute -40
-KPX Aogonek Ocircumflex -40
-KPX Aogonek Odieresis -40
-KPX Aogonek Ograve -40
-KPX Aogonek Ohungarumlaut -40
-KPX Aogonek Omacron -40
-KPX Aogonek Oslash -40
-KPX Aogonek Otilde -40
-KPX Aogonek Q -40
-KPX Aogonek T -90
-KPX Aogonek Tcaron -90
-KPX Aogonek Tcommaaccent -90
-KPX Aogonek U -50
-KPX Aogonek Uacute -50
-KPX Aogonek Ucircumflex -50
-KPX Aogonek Udieresis -50
-KPX Aogonek Ugrave -50
-KPX Aogonek Uhungarumlaut -50
-KPX Aogonek Umacron -50
-KPX Aogonek Uogonek -50
-KPX Aogonek Uring -50
-KPX Aogonek V -80
-KPX Aogonek W -60
-KPX Aogonek Y -110
-KPX Aogonek Yacute -110
-KPX Aogonek Ydieresis -110
-KPX Aogonek u -30
-KPX Aogonek uacute -30
-KPX Aogonek ucircumflex -30
-KPX Aogonek udieresis -30
-KPX Aogonek ugrave -30
-KPX Aogonek uhungarumlaut -30
-KPX Aogonek umacron -30
-KPX Aogonek uogonek -30
-KPX Aogonek uring -30
-KPX Aogonek v -40
-KPX Aogonek w -30
-KPX Aogonek y -30
-KPX Aogonek yacute -30
-KPX Aogonek ydieresis -30
-KPX Aring C -40
-KPX Aring Cacute -40
-KPX Aring Ccaron -40
-KPX Aring Ccedilla -40
-KPX Aring G -50
-KPX Aring Gbreve -50
-KPX Aring Gcommaaccent -50
-KPX Aring O -40
-KPX Aring Oacute -40
-KPX Aring Ocircumflex -40
-KPX Aring Odieresis -40
-KPX Aring Ograve -40
-KPX Aring Ohungarumlaut -40
-KPX Aring Omacron -40
-KPX Aring Oslash -40
-KPX Aring Otilde -40
-KPX Aring Q -40
-KPX Aring T -90
-KPX Aring Tcaron -90
-KPX Aring Tcommaaccent -90
-KPX Aring U -50
-KPX Aring Uacute -50
-KPX Aring Ucircumflex -50
-KPX Aring Udieresis -50
-KPX Aring Ugrave -50
-KPX Aring Uhungarumlaut -50
-KPX Aring Umacron -50
-KPX Aring Uogonek -50
-KPX Aring Uring -50
-KPX Aring V -80
-KPX Aring W -60
-KPX Aring Y -110
-KPX Aring Yacute -110
-KPX Aring Ydieresis -110
-KPX Aring u -30
-KPX Aring uacute -30
-KPX Aring ucircumflex -30
-KPX Aring udieresis -30
-KPX Aring ugrave -30
-KPX Aring uhungarumlaut -30
-KPX Aring umacron -30
-KPX Aring uogonek -30
-KPX Aring uring -30
-KPX Aring v -40
-KPX Aring w -30
-KPX Aring y -30
-KPX Aring yacute -30
-KPX Aring ydieresis -30
-KPX Atilde C -40
-KPX Atilde Cacute -40
-KPX Atilde Ccaron -40
-KPX Atilde Ccedilla -40
-KPX Atilde G -50
-KPX Atilde Gbreve -50
-KPX Atilde Gcommaaccent -50
-KPX Atilde O -40
-KPX Atilde Oacute -40
-KPX Atilde Ocircumflex -40
-KPX Atilde Odieresis -40
-KPX Atilde Ograve -40
-KPX Atilde Ohungarumlaut -40
-KPX Atilde Omacron -40
-KPX Atilde Oslash -40
-KPX Atilde Otilde -40
-KPX Atilde Q -40
-KPX Atilde T -90
-KPX Atilde Tcaron -90
-KPX Atilde Tcommaaccent -90
-KPX Atilde U -50
-KPX Atilde Uacute -50
-KPX Atilde Ucircumflex -50
-KPX Atilde Udieresis -50
-KPX Atilde Ugrave -50
-KPX Atilde Uhungarumlaut -50
-KPX Atilde Umacron -50
-KPX Atilde Uogonek -50
-KPX Atilde Uring -50
-KPX Atilde V -80
-KPX Atilde W -60
-KPX Atilde Y -110
-KPX Atilde Yacute -110
-KPX Atilde Ydieresis -110
-KPX Atilde u -30
-KPX Atilde uacute -30
-KPX Atilde ucircumflex -30
-KPX Atilde udieresis -30
-KPX Atilde ugrave -30
-KPX Atilde uhungarumlaut -30
-KPX Atilde umacron -30
-KPX Atilde uogonek -30
-KPX Atilde uring -30
-KPX Atilde v -40
-KPX Atilde w -30
-KPX Atilde y -30
-KPX Atilde yacute -30
-KPX Atilde ydieresis -30
-KPX B A -30
-KPX B Aacute -30
-KPX B Abreve -30
-KPX B Acircumflex -30
-KPX B Adieresis -30
-KPX B Agrave -30
-KPX B Amacron -30
-KPX B Aogonek -30
-KPX B Aring -30
-KPX B Atilde -30
-KPX B U -10
-KPX B Uacute -10
-KPX B Ucircumflex -10
-KPX B Udieresis -10
-KPX B Ugrave -10
-KPX B Uhungarumlaut -10
-KPX B Umacron -10
-KPX B Uogonek -10
-KPX B Uring -10
-KPX D A -40
-KPX D Aacute -40
-KPX D Abreve -40
-KPX D Acircumflex -40
-KPX D Adieresis -40
-KPX D Agrave -40
-KPX D Amacron -40
-KPX D Aogonek -40
-KPX D Aring -40
-KPX D Atilde -40
-KPX D V -40
-KPX D W -40
-KPX D Y -70
-KPX D Yacute -70
-KPX D Ydieresis -70
-KPX D comma -30
-KPX D period -30
-KPX Dcaron A -40
-KPX Dcaron Aacute -40
-KPX Dcaron Abreve -40
-KPX Dcaron Acircumflex -40
-KPX Dcaron Adieresis -40
-KPX Dcaron Agrave -40
-KPX Dcaron Amacron -40
-KPX Dcaron Aogonek -40
-KPX Dcaron Aring -40
-KPX Dcaron Atilde -40
-KPX Dcaron V -40
-KPX Dcaron W -40
-KPX Dcaron Y -70
-KPX Dcaron Yacute -70
-KPX Dcaron Ydieresis -70
-KPX Dcaron comma -30
-KPX Dcaron period -30
-KPX Dcroat A -40
-KPX Dcroat Aacute -40
-KPX Dcroat Abreve -40
-KPX Dcroat Acircumflex -40
-KPX Dcroat Adieresis -40
-KPX Dcroat Agrave -40
-KPX Dcroat Amacron -40
-KPX Dcroat Aogonek -40
-KPX Dcroat Aring -40
-KPX Dcroat Atilde -40
-KPX Dcroat V -40
-KPX Dcroat W -40
-KPX Dcroat Y -70
-KPX Dcroat Yacute -70
-KPX Dcroat Ydieresis -70
-KPX Dcroat comma -30
-KPX Dcroat period -30
-KPX F A -80
-KPX F Aacute -80
-KPX F Abreve -80
-KPX F Acircumflex -80
-KPX F Adieresis -80
-KPX F Agrave -80
-KPX F Amacron -80
-KPX F Aogonek -80
-KPX F Aring -80
-KPX F Atilde -80
-KPX F a -20
-KPX F aacute -20
-KPX F abreve -20
-KPX F acircumflex -20
-KPX F adieresis -20
-KPX F agrave -20
-KPX F amacron -20
-KPX F aogonek -20
-KPX F aring -20
-KPX F atilde -20
-KPX F comma -100
-KPX F period -100
-KPX J A -20
-KPX J Aacute -20
-KPX J Abreve -20
-KPX J Acircumflex -20
-KPX J Adieresis -20
-KPX J Agrave -20
-KPX J Amacron -20
-KPX J Aogonek -20
-KPX J Aring -20
-KPX J Atilde -20
-KPX J comma -20
-KPX J period -20
-KPX J u -20
-KPX J uacute -20
-KPX J ucircumflex -20
-KPX J udieresis -20
-KPX J ugrave -20
-KPX J uhungarumlaut -20
-KPX J umacron -20
-KPX J uogonek -20
-KPX J uring -20
-KPX K O -30
-KPX K Oacute -30
-KPX K Ocircumflex -30
-KPX K Odieresis -30
-KPX K Ograve -30
-KPX K Ohungarumlaut -30
-KPX K Omacron -30
-KPX K Oslash -30
-KPX K Otilde -30
-KPX K e -15
-KPX K eacute -15
-KPX K ecaron -15
-KPX K ecircumflex -15
-KPX K edieresis -15
-KPX K edotaccent -15
-KPX K egrave -15
-KPX K emacron -15
-KPX K eogonek -15
-KPX K o -35
-KPX K oacute -35
-KPX K ocircumflex -35
-KPX K odieresis -35
-KPX K ograve -35
-KPX K ohungarumlaut -35
-KPX K omacron -35
-KPX K oslash -35
-KPX K otilde -35
-KPX K u -30
-KPX K uacute -30
-KPX K ucircumflex -30
-KPX K udieresis -30
-KPX K ugrave -30
-KPX K uhungarumlaut -30
-KPX K umacron -30
-KPX K uogonek -30
-KPX K uring -30
-KPX K y -40
-KPX K yacute -40
-KPX K ydieresis -40
-KPX Kcommaaccent O -30
-KPX Kcommaaccent Oacute -30
-KPX Kcommaaccent Ocircumflex -30
-KPX Kcommaaccent Odieresis -30
-KPX Kcommaaccent Ograve -30
-KPX Kcommaaccent Ohungarumlaut -30
-KPX Kcommaaccent Omacron -30
-KPX Kcommaaccent Oslash -30
-KPX Kcommaaccent Otilde -30
-KPX Kcommaaccent e -15
-KPX Kcommaaccent eacute -15
-KPX Kcommaaccent ecaron -15
-KPX Kcommaaccent ecircumflex -15
-KPX Kcommaaccent edieresis -15
-KPX Kcommaaccent edotaccent -15
-KPX Kcommaaccent egrave -15
-KPX Kcommaaccent emacron -15
-KPX Kcommaaccent eogonek -15
-KPX Kcommaaccent o -35
-KPX Kcommaaccent oacute -35
-KPX Kcommaaccent ocircumflex -35
-KPX Kcommaaccent odieresis -35
-KPX Kcommaaccent ograve -35
-KPX Kcommaaccent ohungarumlaut -35
-KPX Kcommaaccent omacron -35
-KPX Kcommaaccent oslash -35
-KPX Kcommaaccent otilde -35
-KPX Kcommaaccent u -30
-KPX Kcommaaccent uacute -30
-KPX Kcommaaccent ucircumflex -30
-KPX Kcommaaccent udieresis -30
-KPX Kcommaaccent ugrave -30
-KPX Kcommaaccent uhungarumlaut -30
-KPX Kcommaaccent umacron -30
-KPX Kcommaaccent uogonek -30
-KPX Kcommaaccent uring -30
-KPX Kcommaaccent y -40
-KPX Kcommaaccent yacute -40
-KPX Kcommaaccent ydieresis -40
-KPX L T -90
-KPX L Tcaron -90
-KPX L Tcommaaccent -90
-KPX L V -110
-KPX L W -80
-KPX L Y -120
-KPX L Yacute -120
-KPX L Ydieresis -120
-KPX L quotedblright -140
-KPX L quoteright -140
-KPX L y -30
-KPX L yacute -30
-KPX L ydieresis -30
-KPX Lacute T -90
-KPX Lacute Tcaron -90
-KPX Lacute Tcommaaccent -90
-KPX Lacute V -110
-KPX Lacute W -80
-KPX Lacute Y -120
-KPX Lacute Yacute -120
-KPX Lacute Ydieresis -120
-KPX Lacute quotedblright -140
-KPX Lacute quoteright -140
-KPX Lacute y -30
-KPX Lacute yacute -30
-KPX Lacute ydieresis -30
-KPX Lcommaaccent T -90
-KPX Lcommaaccent Tcaron -90
-KPX Lcommaaccent Tcommaaccent -90
-KPX Lcommaaccent V -110
-KPX Lcommaaccent W -80
-KPX Lcommaaccent Y -120
-KPX Lcommaaccent Yacute -120
-KPX Lcommaaccent Ydieresis -120
-KPX Lcommaaccent quotedblright -140
-KPX Lcommaaccent quoteright -140
-KPX Lcommaaccent y -30
-KPX Lcommaaccent yacute -30
-KPX Lcommaaccent ydieresis -30
-KPX Lslash T -90
-KPX Lslash Tcaron -90
-KPX Lslash Tcommaaccent -90
-KPX Lslash V -110
-KPX Lslash W -80
-KPX Lslash Y -120
-KPX Lslash Yacute -120
-KPX Lslash Ydieresis -120
-KPX Lslash quotedblright -140
-KPX Lslash quoteright -140
-KPX Lslash y -30
-KPX Lslash yacute -30
-KPX Lslash ydieresis -30
-KPX O A -50
-KPX O Aacute -50
-KPX O Abreve -50
-KPX O Acircumflex -50
-KPX O Adieresis -50
-KPX O Agrave -50
-KPX O Amacron -50
-KPX O Aogonek -50
-KPX O Aring -50
-KPX O Atilde -50
-KPX O T -40
-KPX O Tcaron -40
-KPX O Tcommaaccent -40
-KPX O V -50
-KPX O W -50
-KPX O X -50
-KPX O Y -70
-KPX O Yacute -70
-KPX O Ydieresis -70
-KPX O comma -40
-KPX O period -40
-KPX Oacute A -50
-KPX Oacute Aacute -50
-KPX Oacute Abreve -50
-KPX Oacute Acircumflex -50
-KPX Oacute Adieresis -50
-KPX Oacute Agrave -50
-KPX Oacute Amacron -50
-KPX Oacute Aogonek -50
-KPX Oacute Aring -50
-KPX Oacute Atilde -50
-KPX Oacute T -40
-KPX Oacute Tcaron -40
-KPX Oacute Tcommaaccent -40
-KPX Oacute V -50
-KPX Oacute W -50
-KPX Oacute X -50
-KPX Oacute Y -70
-KPX Oacute Yacute -70
-KPX Oacute Ydieresis -70
-KPX Oacute comma -40
-KPX Oacute period -40
-KPX Ocircumflex A -50
-KPX Ocircumflex Aacute -50
-KPX Ocircumflex Abreve -50
-KPX Ocircumflex Acircumflex -50
-KPX Ocircumflex Adieresis -50
-KPX Ocircumflex Agrave -50
-KPX Ocircumflex Amacron -50
-KPX Ocircumflex Aogonek -50
-KPX Ocircumflex Aring -50
-KPX Ocircumflex Atilde -50
-KPX Ocircumflex T -40
-KPX Ocircumflex Tcaron -40
-KPX Ocircumflex Tcommaaccent -40
-KPX Ocircumflex V -50
-KPX Ocircumflex W -50
-KPX Ocircumflex X -50
-KPX Ocircumflex Y -70
-KPX Ocircumflex Yacute -70
-KPX Ocircumflex Ydieresis -70
-KPX Ocircumflex comma -40
-KPX Ocircumflex period -40
-KPX Odieresis A -50
-KPX Odieresis Aacute -50
-KPX Odieresis Abreve -50
-KPX Odieresis Acircumflex -50
-KPX Odieresis Adieresis -50
-KPX Odieresis Agrave -50
-KPX Odieresis Amacron -50
-KPX Odieresis Aogonek -50
-KPX Odieresis Aring -50
-KPX Odieresis Atilde -50
-KPX Odieresis T -40
-KPX Odieresis Tcaron -40
-KPX Odieresis Tcommaaccent -40
-KPX Odieresis V -50
-KPX Odieresis W -50
-KPX Odieresis X -50
-KPX Odieresis Y -70
-KPX Odieresis Yacute -70
-KPX Odieresis Ydieresis -70
-KPX Odieresis comma -40
-KPX Odieresis period -40
-KPX Ograve A -50
-KPX Ograve Aacute -50
-KPX Ograve Abreve -50
-KPX Ograve Acircumflex -50
-KPX Ograve Adieresis -50
-KPX Ograve Agrave -50
-KPX Ograve Amacron -50
-KPX Ograve Aogonek -50
-KPX Ograve Aring -50
-KPX Ograve Atilde -50
-KPX Ograve T -40
-KPX Ograve Tcaron -40
-KPX Ograve Tcommaaccent -40
-KPX Ograve V -50
-KPX Ograve W -50
-KPX Ograve X -50
-KPX Ograve Y -70
-KPX Ograve Yacute -70
-KPX Ograve Ydieresis -70
-KPX Ograve comma -40
-KPX Ograve period -40
-KPX Ohungarumlaut A -50
-KPX Ohungarumlaut Aacute -50
-KPX Ohungarumlaut Abreve -50
-KPX Ohungarumlaut Acircumflex -50
-KPX Ohungarumlaut Adieresis -50
-KPX Ohungarumlaut Agrave -50
-KPX Ohungarumlaut Amacron -50
-KPX Ohungarumlaut Aogonek -50
-KPX Ohungarumlaut Aring -50
-KPX Ohungarumlaut Atilde -50
-KPX Ohungarumlaut T -40
-KPX Ohungarumlaut Tcaron -40
-KPX Ohungarumlaut Tcommaaccent -40
-KPX Ohungarumlaut V -50
-KPX Ohungarumlaut W -50
-KPX Ohungarumlaut X -50
-KPX Ohungarumlaut Y -70
-KPX Ohungarumlaut Yacute -70
-KPX Ohungarumlaut Ydieresis -70
-KPX Ohungarumlaut comma -40
-KPX Ohungarumlaut period -40
-KPX Omacron A -50
-KPX Omacron Aacute -50
-KPX Omacron Abreve -50
-KPX Omacron Acircumflex -50
-KPX Omacron Adieresis -50
-KPX Omacron Agrave -50
-KPX Omacron Amacron -50
-KPX Omacron Aogonek -50
-KPX Omacron Aring -50
-KPX Omacron Atilde -50
-KPX Omacron T -40
-KPX Omacron Tcaron -40
-KPX Omacron Tcommaaccent -40
-KPX Omacron V -50
-KPX Omacron W -50
-KPX Omacron X -50
-KPX Omacron Y -70
-KPX Omacron Yacute -70
-KPX Omacron Ydieresis -70
-KPX Omacron comma -40
-KPX Omacron period -40
-KPX Oslash A -50
-KPX Oslash Aacute -50
-KPX Oslash Abreve -50
-KPX Oslash Acircumflex -50
-KPX Oslash Adieresis -50
-KPX Oslash Agrave -50
-KPX Oslash Amacron -50
-KPX Oslash Aogonek -50
-KPX Oslash Aring -50
-KPX Oslash Atilde -50
-KPX Oslash T -40
-KPX Oslash Tcaron -40
-KPX Oslash Tcommaaccent -40
-KPX Oslash V -50
-KPX Oslash W -50
-KPX Oslash X -50
-KPX Oslash Y -70
-KPX Oslash Yacute -70
-KPX Oslash Ydieresis -70
-KPX Oslash comma -40
-KPX Oslash period -40
-KPX Otilde A -50
-KPX Otilde Aacute -50
-KPX Otilde Abreve -50
-KPX Otilde Acircumflex -50
-KPX Otilde Adieresis -50
-KPX Otilde Agrave -50
-KPX Otilde Amacron -50
-KPX Otilde Aogonek -50
-KPX Otilde Aring -50
-KPX Otilde Atilde -50
-KPX Otilde T -40
-KPX Otilde Tcaron -40
-KPX Otilde Tcommaaccent -40
-KPX Otilde V -50
-KPX Otilde W -50
-KPX Otilde X -50
-KPX Otilde Y -70
-KPX Otilde Yacute -70
-KPX Otilde Ydieresis -70
-KPX Otilde comma -40
-KPX Otilde period -40
-KPX P A -100
-KPX P Aacute -100
-KPX P Abreve -100
-KPX P Acircumflex -100
-KPX P Adieresis -100
-KPX P Agrave -100
-KPX P Amacron -100
-KPX P Aogonek -100
-KPX P Aring -100
-KPX P Atilde -100
-KPX P a -30
-KPX P aacute -30
-KPX P abreve -30
-KPX P acircumflex -30
-KPX P adieresis -30
-KPX P agrave -30
-KPX P amacron -30
-KPX P aogonek -30
-KPX P aring -30
-KPX P atilde -30
-KPX P comma -120
-KPX P e -30
-KPX P eacute -30
-KPX P ecaron -30
-KPX P ecircumflex -30
-KPX P edieresis -30
-KPX P edotaccent -30
-KPX P egrave -30
-KPX P emacron -30
-KPX P eogonek -30
-KPX P o -40
-KPX P oacute -40
-KPX P ocircumflex -40
-KPX P odieresis -40
-KPX P ograve -40
-KPX P ohungarumlaut -40
-KPX P omacron -40
-KPX P oslash -40
-KPX P otilde -40
-KPX P period -120
-KPX Q U -10
-KPX Q Uacute -10
-KPX Q Ucircumflex -10
-KPX Q Udieresis -10
-KPX Q Ugrave -10
-KPX Q Uhungarumlaut -10
-KPX Q Umacron -10
-KPX Q Uogonek -10
-KPX Q Uring -10
-KPX Q comma 20
-KPX Q period 20
-KPX R O -20
-KPX R Oacute -20
-KPX R Ocircumflex -20
-KPX R Odieresis -20
-KPX R Ograve -20
-KPX R Ohungarumlaut -20
-KPX R Omacron -20
-KPX R Oslash -20
-KPX R Otilde -20
-KPX R T -20
-KPX R Tcaron -20
-KPX R Tcommaaccent -20
-KPX R U -20
-KPX R Uacute -20
-KPX R Ucircumflex -20
-KPX R Udieresis -20
-KPX R Ugrave -20
-KPX R Uhungarumlaut -20
-KPX R Umacron -20
-KPX R Uogonek -20
-KPX R Uring -20
-KPX R V -50
-KPX R W -40
-KPX R Y -50
-KPX R Yacute -50
-KPX R Ydieresis -50
-KPX Racute O -20
-KPX Racute Oacute -20
-KPX Racute Ocircumflex -20
-KPX Racute Odieresis -20
-KPX Racute Ograve -20
-KPX Racute Ohungarumlaut -20
-KPX Racute Omacron -20
-KPX Racute Oslash -20
-KPX Racute Otilde -20
-KPX Racute T -20
-KPX Racute Tcaron -20
-KPX Racute Tcommaaccent -20
-KPX Racute U -20
-KPX Racute Uacute -20
-KPX Racute Ucircumflex -20
-KPX Racute Udieresis -20
-KPX Racute Ugrave -20
-KPX Racute Uhungarumlaut -20
-KPX Racute Umacron -20
-KPX Racute Uogonek -20
-KPX Racute Uring -20
-KPX Racute V -50
-KPX Racute W -40
-KPX Racute Y -50
-KPX Racute Yacute -50
-KPX Racute Ydieresis -50
-KPX Rcaron O -20
-KPX Rcaron Oacute -20
-KPX Rcaron Ocircumflex -20
-KPX Rcaron Odieresis -20
-KPX Rcaron Ograve -20
-KPX Rcaron Ohungarumlaut -20
-KPX Rcaron Omacron -20
-KPX Rcaron Oslash -20
-KPX Rcaron Otilde -20
-KPX Rcaron T -20
-KPX Rcaron Tcaron -20
-KPX Rcaron Tcommaaccent -20
-KPX Rcaron U -20
-KPX Rcaron Uacute -20
-KPX Rcaron Ucircumflex -20
-KPX Rcaron Udieresis -20
-KPX Rcaron Ugrave -20
-KPX Rcaron Uhungarumlaut -20
-KPX Rcaron Umacron -20
-KPX Rcaron Uogonek -20
-KPX Rcaron Uring -20
-KPX Rcaron V -50
-KPX Rcaron W -40
-KPX Rcaron Y -50
-KPX Rcaron Yacute -50
-KPX Rcaron Ydieresis -50
-KPX Rcommaaccent O -20
-KPX Rcommaaccent Oacute -20
-KPX Rcommaaccent Ocircumflex -20
-KPX Rcommaaccent Odieresis -20
-KPX Rcommaaccent Ograve -20
-KPX Rcommaaccent Ohungarumlaut -20
-KPX Rcommaaccent Omacron -20
-KPX Rcommaaccent Oslash -20
-KPX Rcommaaccent Otilde -20
-KPX Rcommaaccent T -20
-KPX Rcommaaccent Tcaron -20
-KPX Rcommaaccent Tcommaaccent -20
-KPX Rcommaaccent U -20
-KPX Rcommaaccent Uacute -20
-KPX Rcommaaccent Ucircumflex -20
-KPX Rcommaaccent Udieresis -20
-KPX Rcommaaccent Ugrave -20
-KPX Rcommaaccent Uhungarumlaut -20
-KPX Rcommaaccent Umacron -20
-KPX Rcommaaccent Uogonek -20
-KPX Rcommaaccent Uring -20
-KPX Rcommaaccent V -50
-KPX Rcommaaccent W -40
-KPX Rcommaaccent Y -50
-KPX Rcommaaccent Yacute -50
-KPX Rcommaaccent Ydieresis -50
-KPX T A -90
-KPX T Aacute -90
-KPX T Abreve -90
-KPX T Acircumflex -90
-KPX T Adieresis -90
-KPX T Agrave -90
-KPX T Amacron -90
-KPX T Aogonek -90
-KPX T Aring -90
-KPX T Atilde -90
-KPX T O -40
-KPX T Oacute -40
-KPX T Ocircumflex -40
-KPX T Odieresis -40
-KPX T Ograve -40
-KPX T Ohungarumlaut -40
-KPX T Omacron -40
-KPX T Oslash -40
-KPX T Otilde -40
-KPX T a -80
-KPX T aacute -80
-KPX T abreve -80
-KPX T acircumflex -80
-KPX T adieresis -80
-KPX T agrave -80
-KPX T amacron -80
-KPX T aogonek -80
-KPX T aring -80
-KPX T atilde -80
-KPX T colon -40
-KPX T comma -80
-KPX T e -60
-KPX T eacute -60
-KPX T ecaron -60
-KPX T ecircumflex -60
-KPX T edieresis -60
-KPX T edotaccent -60
-KPX T egrave -60
-KPX T emacron -60
-KPX T eogonek -60
-KPX T hyphen -120
-KPX T o -80
-KPX T oacute -80
-KPX T ocircumflex -80
-KPX T odieresis -80
-KPX T ograve -80
-KPX T ohungarumlaut -80
-KPX T omacron -80
-KPX T oslash -80
-KPX T otilde -80
-KPX T period -80
-KPX T r -80
-KPX T racute -80
-KPX T rcommaaccent -80
-KPX T semicolon -40
-KPX T u -90
-KPX T uacute -90
-KPX T ucircumflex -90
-KPX T udieresis -90
-KPX T ugrave -90
-KPX T uhungarumlaut -90
-KPX T umacron -90
-KPX T uogonek -90
-KPX T uring -90
-KPX T w -60
-KPX T y -60
-KPX T yacute -60
-KPX T ydieresis -60
-KPX Tcaron A -90
-KPX Tcaron Aacute -90
-KPX Tcaron Abreve -90
-KPX Tcaron Acircumflex -90
-KPX Tcaron Adieresis -90
-KPX Tcaron Agrave -90
-KPX Tcaron Amacron -90
-KPX Tcaron Aogonek -90
-KPX Tcaron Aring -90
-KPX Tcaron Atilde -90
-KPX Tcaron O -40
-KPX Tcaron Oacute -40
-KPX Tcaron Ocircumflex -40
-KPX Tcaron Odieresis -40
-KPX Tcaron Ograve -40
-KPX Tcaron Ohungarumlaut -40
-KPX Tcaron Omacron -40
-KPX Tcaron Oslash -40
-KPX Tcaron Otilde -40
-KPX Tcaron a -80
-KPX Tcaron aacute -80
-KPX Tcaron abreve -80
-KPX Tcaron acircumflex -80
-KPX Tcaron adieresis -80
-KPX Tcaron agrave -80
-KPX Tcaron amacron -80
-KPX Tcaron aogonek -80
-KPX Tcaron aring -80
-KPX Tcaron atilde -80
-KPX Tcaron colon -40
-KPX Tcaron comma -80
-KPX Tcaron e -60
-KPX Tcaron eacute -60
-KPX Tcaron ecaron -60
-KPX Tcaron ecircumflex -60
-KPX Tcaron edieresis -60
-KPX Tcaron edotaccent -60
-KPX Tcaron egrave -60
-KPX Tcaron emacron -60
-KPX Tcaron eogonek -60
-KPX Tcaron hyphen -120
-KPX Tcaron o -80
-KPX Tcaron oacute -80
-KPX Tcaron ocircumflex -80
-KPX Tcaron odieresis -80
-KPX Tcaron ograve -80
-KPX Tcaron ohungarumlaut -80
-KPX Tcaron omacron -80
-KPX Tcaron oslash -80
-KPX Tcaron otilde -80
-KPX Tcaron period -80
-KPX Tcaron r -80
-KPX Tcaron racute -80
-KPX Tcaron rcommaaccent -80
-KPX Tcaron semicolon -40
-KPX Tcaron u -90
-KPX Tcaron uacute -90
-KPX Tcaron ucircumflex -90
-KPX Tcaron udieresis -90
-KPX Tcaron ugrave -90
-KPX Tcaron uhungarumlaut -90
-KPX Tcaron umacron -90
-KPX Tcaron uogonek -90
-KPX Tcaron uring -90
-KPX Tcaron w -60
-KPX Tcaron y -60
-KPX Tcaron yacute -60
-KPX Tcaron ydieresis -60
-KPX Tcommaaccent A -90
-KPX Tcommaaccent Aacute -90
-KPX Tcommaaccent Abreve -90
-KPX Tcommaaccent Acircumflex -90
-KPX Tcommaaccent Adieresis -90
-KPX Tcommaaccent Agrave -90
-KPX Tcommaaccent Amacron -90
-KPX Tcommaaccent Aogonek -90
-KPX Tcommaaccent Aring -90
-KPX Tcommaaccent Atilde -90
-KPX Tcommaaccent O -40
-KPX Tcommaaccent Oacute -40
-KPX Tcommaaccent Ocircumflex -40
-KPX Tcommaaccent Odieresis -40
-KPX Tcommaaccent Ograve -40
-KPX Tcommaaccent Ohungarumlaut -40
-KPX Tcommaaccent Omacron -40
-KPX Tcommaaccent Oslash -40
-KPX Tcommaaccent Otilde -40
-KPX Tcommaaccent a -80
-KPX Tcommaaccent aacute -80
-KPX Tcommaaccent abreve -80
-KPX Tcommaaccent acircumflex -80
-KPX Tcommaaccent adieresis -80
-KPX Tcommaaccent agrave -80
-KPX Tcommaaccent amacron -80
-KPX Tcommaaccent aogonek -80
-KPX Tcommaaccent aring -80
-KPX Tcommaaccent atilde -80
-KPX Tcommaaccent colon -40
-KPX Tcommaaccent comma -80
-KPX Tcommaaccent e -60
-KPX Tcommaaccent eacute -60
-KPX Tcommaaccent ecaron -60
-KPX Tcommaaccent ecircumflex -60
-KPX Tcommaaccent edieresis -60
-KPX Tcommaaccent edotaccent -60
-KPX Tcommaaccent egrave -60
-KPX Tcommaaccent emacron -60
-KPX Tcommaaccent eogonek -60
-KPX Tcommaaccent hyphen -120
-KPX Tcommaaccent o -80
-KPX Tcommaaccent oacute -80
-KPX Tcommaaccent ocircumflex -80
-KPX Tcommaaccent odieresis -80
-KPX Tcommaaccent ograve -80
-KPX Tcommaaccent ohungarumlaut -80
-KPX Tcommaaccent omacron -80
-KPX Tcommaaccent oslash -80
-KPX Tcommaaccent otilde -80
-KPX Tcommaaccent period -80
-KPX Tcommaaccent r -80
-KPX Tcommaaccent racute -80
-KPX Tcommaaccent rcommaaccent -80
-KPX Tcommaaccent semicolon -40
-KPX Tcommaaccent u -90
-KPX Tcommaaccent uacute -90
-KPX Tcommaaccent ucircumflex -90
-KPX Tcommaaccent udieresis -90
-KPX Tcommaaccent ugrave -90
-KPX Tcommaaccent uhungarumlaut -90
-KPX Tcommaaccent umacron -90
-KPX Tcommaaccent uogonek -90
-KPX Tcommaaccent uring -90
-KPX Tcommaaccent w -60
-KPX Tcommaaccent y -60
-KPX Tcommaaccent yacute -60
-KPX Tcommaaccent ydieresis -60
-KPX U A -50
-KPX U Aacute -50
-KPX U Abreve -50
-KPX U Acircumflex -50
-KPX U Adieresis -50
-KPX U Agrave -50
-KPX U Amacron -50
-KPX U Aogonek -50
-KPX U Aring -50
-KPX U Atilde -50
-KPX U comma -30
-KPX U period -30
-KPX Uacute A -50
-KPX Uacute Aacute -50
-KPX Uacute Abreve -50
-KPX Uacute Acircumflex -50
-KPX Uacute Adieresis -50
-KPX Uacute Agrave -50
-KPX Uacute Amacron -50
-KPX Uacute Aogonek -50
-KPX Uacute Aring -50
-KPX Uacute Atilde -50
-KPX Uacute comma -30
-KPX Uacute period -30
-KPX Ucircumflex A -50
-KPX Ucircumflex Aacute -50
-KPX Ucircumflex Abreve -50
-KPX Ucircumflex Acircumflex -50
-KPX Ucircumflex Adieresis -50
-KPX Ucircumflex Agrave -50
-KPX Ucircumflex Amacron -50
-KPX Ucircumflex Aogonek -50
-KPX Ucircumflex Aring -50
-KPX Ucircumflex Atilde -50
-KPX Ucircumflex comma -30
-KPX Ucircumflex period -30
-KPX Udieresis A -50
-KPX Udieresis Aacute -50
-KPX Udieresis Abreve -50
-KPX Udieresis Acircumflex -50
-KPX Udieresis Adieresis -50
-KPX Udieresis Agrave -50
-KPX Udieresis Amacron -50
-KPX Udieresis Aogonek -50
-KPX Udieresis Aring -50
-KPX Udieresis Atilde -50
-KPX Udieresis comma -30
-KPX Udieresis period -30
-KPX Ugrave A -50
-KPX Ugrave Aacute -50
-KPX Ugrave Abreve -50
-KPX Ugrave Acircumflex -50
-KPX Ugrave Adieresis -50
-KPX Ugrave Agrave -50
-KPX Ugrave Amacron -50
-KPX Ugrave Aogonek -50
-KPX Ugrave Aring -50
-KPX Ugrave Atilde -50
-KPX Ugrave comma -30
-KPX Ugrave period -30
-KPX Uhungarumlaut A -50
-KPX Uhungarumlaut Aacute -50
-KPX Uhungarumlaut Abreve -50
-KPX Uhungarumlaut Acircumflex -50
-KPX Uhungarumlaut Adieresis -50
-KPX Uhungarumlaut Agrave -50
-KPX Uhungarumlaut Amacron -50
-KPX Uhungarumlaut Aogonek -50
-KPX Uhungarumlaut Aring -50
-KPX Uhungarumlaut Atilde -50
-KPX Uhungarumlaut comma -30
-KPX Uhungarumlaut period -30
-KPX Umacron A -50
-KPX Umacron Aacute -50
-KPX Umacron Abreve -50
-KPX Umacron Acircumflex -50
-KPX Umacron Adieresis -50
-KPX Umacron Agrave -50
-KPX Umacron Amacron -50
-KPX Umacron Aogonek -50
-KPX Umacron Aring -50
-KPX Umacron Atilde -50
-KPX Umacron comma -30
-KPX Umacron period -30
-KPX Uogonek A -50
-KPX Uogonek Aacute -50
-KPX Uogonek Abreve -50
-KPX Uogonek Acircumflex -50
-KPX Uogonek Adieresis -50
-KPX Uogonek Agrave -50
-KPX Uogonek Amacron -50
-KPX Uogonek Aogonek -50
-KPX Uogonek Aring -50
-KPX Uogonek Atilde -50
-KPX Uogonek comma -30
-KPX Uogonek period -30
-KPX Uring A -50
-KPX Uring Aacute -50
-KPX Uring Abreve -50
-KPX Uring Acircumflex -50
-KPX Uring Adieresis -50
-KPX Uring Agrave -50
-KPX Uring Amacron -50
-KPX Uring Aogonek -50
-KPX Uring Aring -50
-KPX Uring Atilde -50
-KPX Uring comma -30
-KPX Uring period -30
-KPX V A -80
-KPX V Aacute -80
-KPX V Abreve -80
-KPX V Acircumflex -80
-KPX V Adieresis -80
-KPX V Agrave -80
-KPX V Amacron -80
-KPX V Aogonek -80
-KPX V Aring -80
-KPX V Atilde -80
-KPX V G -50
-KPX V Gbreve -50
-KPX V Gcommaaccent -50
-KPX V O -50
-KPX V Oacute -50
-KPX V Ocircumflex -50
-KPX V Odieresis -50
-KPX V Ograve -50
-KPX V Ohungarumlaut -50
-KPX V Omacron -50
-KPX V Oslash -50
-KPX V Otilde -50
-KPX V a -60
-KPX V aacute -60
-KPX V abreve -60
-KPX V acircumflex -60
-KPX V adieresis -60
-KPX V agrave -60
-KPX V amacron -60
-KPX V aogonek -60
-KPX V aring -60
-KPX V atilde -60
-KPX V colon -40
-KPX V comma -120
-KPX V e -50
-KPX V eacute -50
-KPX V ecaron -50
-KPX V ecircumflex -50
-KPX V edieresis -50
-KPX V edotaccent -50
-KPX V egrave -50
-KPX V emacron -50
-KPX V eogonek -50
-KPX V hyphen -80
-KPX V o -90
-KPX V oacute -90
-KPX V ocircumflex -90
-KPX V odieresis -90
-KPX V ograve -90
-KPX V ohungarumlaut -90
-KPX V omacron -90
-KPX V oslash -90
-KPX V otilde -90
-KPX V period -120
-KPX V semicolon -40
-KPX V u -60
-KPX V uacute -60
-KPX V ucircumflex -60
-KPX V udieresis -60
-KPX V ugrave -60
-KPX V uhungarumlaut -60
-KPX V umacron -60
-KPX V uogonek -60
-KPX V uring -60
-KPX W A -60
-KPX W Aacute -60
-KPX W Abreve -60
-KPX W Acircumflex -60
-KPX W Adieresis -60
-KPX W Agrave -60
-KPX W Amacron -60
-KPX W Aogonek -60
-KPX W Aring -60
-KPX W Atilde -60
-KPX W O -20
-KPX W Oacute -20
-KPX W Ocircumflex -20
-KPX W Odieresis -20
-KPX W Ograve -20
-KPX W Ohungarumlaut -20
-KPX W Omacron -20
-KPX W Oslash -20
-KPX W Otilde -20
-KPX W a -40
-KPX W aacute -40
-KPX W abreve -40
-KPX W acircumflex -40
-KPX W adieresis -40
-KPX W agrave -40
-KPX W amacron -40
-KPX W aogonek -40
-KPX W aring -40
-KPX W atilde -40
-KPX W colon -10
-KPX W comma -80
-KPX W e -35
-KPX W eacute -35
-KPX W ecaron -35
-KPX W ecircumflex -35
-KPX W edieresis -35
-KPX W edotaccent -35
-KPX W egrave -35
-KPX W emacron -35
-KPX W eogonek -35
-KPX W hyphen -40
-KPX W o -60
-KPX W oacute -60
-KPX W ocircumflex -60
-KPX W odieresis -60
-KPX W ograve -60
-KPX W ohungarumlaut -60
-KPX W omacron -60
-KPX W oslash -60
-KPX W otilde -60
-KPX W period -80
-KPX W semicolon -10
-KPX W u -45
-KPX W uacute -45
-KPX W ucircumflex -45
-KPX W udieresis -45
-KPX W ugrave -45
-KPX W uhungarumlaut -45
-KPX W umacron -45
-KPX W uogonek -45
-KPX W uring -45
-KPX W y -20
-KPX W yacute -20
-KPX W ydieresis -20
-KPX Y A -110
-KPX Y Aacute -110
-KPX Y Abreve -110
-KPX Y Acircumflex -110
-KPX Y Adieresis -110
-KPX Y Agrave -110
-KPX Y Amacron -110
-KPX Y Aogonek -110
-KPX Y Aring -110
-KPX Y Atilde -110
-KPX Y O -70
-KPX Y Oacute -70
-KPX Y Ocircumflex -70
-KPX Y Odieresis -70
-KPX Y Ograve -70
-KPX Y Ohungarumlaut -70
-KPX Y Omacron -70
-KPX Y Oslash -70
-KPX Y Otilde -70
-KPX Y a -90
-KPX Y aacute -90
-KPX Y abreve -90
-KPX Y acircumflex -90
-KPX Y adieresis -90
-KPX Y agrave -90
-KPX Y amacron -90
-KPX Y aogonek -90
-KPX Y aring -90
-KPX Y atilde -90
-KPX Y colon -50
-KPX Y comma -100
-KPX Y e -80
-KPX Y eacute -80
-KPX Y ecaron -80
-KPX Y ecircumflex -80
-KPX Y edieresis -80
-KPX Y edotaccent -80
-KPX Y egrave -80
-KPX Y emacron -80
-KPX Y eogonek -80
-KPX Y o -100
-KPX Y oacute -100
-KPX Y ocircumflex -100
-KPX Y odieresis -100
-KPX Y ograve -100
-KPX Y ohungarumlaut -100
-KPX Y omacron -100
-KPX Y oslash -100
-KPX Y otilde -100
-KPX Y period -100
-KPX Y semicolon -50
-KPX Y u -100
-KPX Y uacute -100
-KPX Y ucircumflex -100
-KPX Y udieresis -100
-KPX Y ugrave -100
-KPX Y uhungarumlaut -100
-KPX Y umacron -100
-KPX Y uogonek -100
-KPX Y uring -100
-KPX Yacute A -110
-KPX Yacute Aacute -110
-KPX Yacute Abreve -110
-KPX Yacute Acircumflex -110
-KPX Yacute Adieresis -110
-KPX Yacute Agrave -110
-KPX Yacute Amacron -110
-KPX Yacute Aogonek -110
-KPX Yacute Aring -110
-KPX Yacute Atilde -110
-KPX Yacute O -70
-KPX Yacute Oacute -70
-KPX Yacute Ocircumflex -70
-KPX Yacute Odieresis -70
-KPX Yacute Ograve -70
-KPX Yacute Ohungarumlaut -70
-KPX Yacute Omacron -70
-KPX Yacute Oslash -70
-KPX Yacute Otilde -70
-KPX Yacute a -90
-KPX Yacute aacute -90
-KPX Yacute abreve -90
-KPX Yacute acircumflex -90
-KPX Yacute adieresis -90
-KPX Yacute agrave -90
-KPX Yacute amacron -90
-KPX Yacute aogonek -90
-KPX Yacute aring -90
-KPX Yacute atilde -90
-KPX Yacute colon -50
-KPX Yacute comma -100
-KPX Yacute e -80
-KPX Yacute eacute -80
-KPX Yacute ecaron -80
-KPX Yacute ecircumflex -80
-KPX Yacute edieresis -80
-KPX Yacute edotaccent -80
-KPX Yacute egrave -80
-KPX Yacute emacron -80
-KPX Yacute eogonek -80
-KPX Yacute o -100
-KPX Yacute oacute -100
-KPX Yacute ocircumflex -100
-KPX Yacute odieresis -100
-KPX Yacute ograve -100
-KPX Yacute ohungarumlaut -100
-KPX Yacute omacron -100
-KPX Yacute oslash -100
-KPX Yacute otilde -100
-KPX Yacute period -100
-KPX Yacute semicolon -50
-KPX Yacute u -100
-KPX Yacute uacute -100
-KPX Yacute ucircumflex -100
-KPX Yacute udieresis -100
-KPX Yacute ugrave -100
-KPX Yacute uhungarumlaut -100
-KPX Yacute umacron -100
-KPX Yacute uogonek -100
-KPX Yacute uring -100
-KPX Ydieresis A -110
-KPX Ydieresis Aacute -110
-KPX Ydieresis Abreve -110
-KPX Ydieresis Acircumflex -110
-KPX Ydieresis Adieresis -110
-KPX Ydieresis Agrave -110
-KPX Ydieresis Amacron -110
-KPX Ydieresis Aogonek -110
-KPX Ydieresis Aring -110
-KPX Ydieresis Atilde -110
-KPX Ydieresis O -70
-KPX Ydieresis Oacute -70
-KPX Ydieresis Ocircumflex -70
-KPX Ydieresis Odieresis -70
-KPX Ydieresis Ograve -70
-KPX Ydieresis Ohungarumlaut -70
-KPX Ydieresis Omacron -70
-KPX Ydieresis Oslash -70
-KPX Ydieresis Otilde -70
-KPX Ydieresis a -90
-KPX Ydieresis aacute -90
-KPX Ydieresis abreve -90
-KPX Ydieresis acircumflex -90
-KPX Ydieresis adieresis -90
-KPX Ydieresis agrave -90
-KPX Ydieresis amacron -90
-KPX Ydieresis aogonek -90
-KPX Ydieresis aring -90
-KPX Ydieresis atilde -90
-KPX Ydieresis colon -50
-KPX Ydieresis comma -100
-KPX Ydieresis e -80
-KPX Ydieresis eacute -80
-KPX Ydieresis ecaron -80
-KPX Ydieresis ecircumflex -80
-KPX Ydieresis edieresis -80
-KPX Ydieresis edotaccent -80
-KPX Ydieresis egrave -80
-KPX Ydieresis emacron -80
-KPX Ydieresis eogonek -80
-KPX Ydieresis o -100
-KPX Ydieresis oacute -100
-KPX Ydieresis ocircumflex -100
-KPX Ydieresis odieresis -100
-KPX Ydieresis ograve -100
-KPX Ydieresis ohungarumlaut -100
-KPX Ydieresis omacron -100
-KPX Ydieresis oslash -100
-KPX Ydieresis otilde -100
-KPX Ydieresis period -100
-KPX Ydieresis semicolon -50
-KPX Ydieresis u -100
-KPX Ydieresis uacute -100
-KPX Ydieresis ucircumflex -100
-KPX Ydieresis udieresis -100
-KPX Ydieresis ugrave -100
-KPX Ydieresis uhungarumlaut -100
-KPX Ydieresis umacron -100
-KPX Ydieresis uogonek -100
-KPX Ydieresis uring -100
-KPX a g -10
-KPX a gbreve -10
-KPX a gcommaaccent -10
-KPX a v -15
-KPX a w -15
-KPX a y -20
-KPX a yacute -20
-KPX a ydieresis -20
-KPX aacute g -10
-KPX aacute gbreve -10
-KPX aacute gcommaaccent -10
-KPX aacute v -15
-KPX aacute w -15
-KPX aacute y -20
-KPX aacute yacute -20
-KPX aacute ydieresis -20
-KPX abreve g -10
-KPX abreve gbreve -10
-KPX abreve gcommaaccent -10
-KPX abreve v -15
-KPX abreve w -15
-KPX abreve y -20
-KPX abreve yacute -20
-KPX abreve ydieresis -20
-KPX acircumflex g -10
-KPX acircumflex gbreve -10
-KPX acircumflex gcommaaccent -10
-KPX acircumflex v -15
-KPX acircumflex w -15
-KPX acircumflex y -20
-KPX acircumflex yacute -20
-KPX acircumflex ydieresis -20
-KPX adieresis g -10
-KPX adieresis gbreve -10
-KPX adieresis gcommaaccent -10
-KPX adieresis v -15
-KPX adieresis w -15
-KPX adieresis y -20
-KPX adieresis yacute -20
-KPX adieresis ydieresis -20
-KPX agrave g -10
-KPX agrave gbreve -10
-KPX agrave gcommaaccent -10
-KPX agrave v -15
-KPX agrave w -15
-KPX agrave y -20
-KPX agrave yacute -20
-KPX agrave ydieresis -20
-KPX amacron g -10
-KPX amacron gbreve -10
-KPX amacron gcommaaccent -10
-KPX amacron v -15
-KPX amacron w -15
-KPX amacron y -20
-KPX amacron yacute -20
-KPX amacron ydieresis -20
-KPX aogonek g -10
-KPX aogonek gbreve -10
-KPX aogonek gcommaaccent -10
-KPX aogonek v -15
-KPX aogonek w -15
-KPX aogonek y -20
-KPX aogonek yacute -20
-KPX aogonek ydieresis -20
-KPX aring g -10
-KPX aring gbreve -10
-KPX aring gcommaaccent -10
-KPX aring v -15
-KPX aring w -15
-KPX aring y -20
-KPX aring yacute -20
-KPX aring ydieresis -20
-KPX atilde g -10
-KPX atilde gbreve -10
-KPX atilde gcommaaccent -10
-KPX atilde v -15
-KPX atilde w -15
-KPX atilde y -20
-KPX atilde yacute -20
-KPX atilde ydieresis -20
-KPX b l -10
-KPX b lacute -10
-KPX b lcommaaccent -10
-KPX b lslash -10
-KPX b u -20
-KPX b uacute -20
-KPX b ucircumflex -20
-KPX b udieresis -20
-KPX b ugrave -20
-KPX b uhungarumlaut -20
-KPX b umacron -20
-KPX b uogonek -20
-KPX b uring -20
-KPX b v -20
-KPX b y -20
-KPX b yacute -20
-KPX b ydieresis -20
-KPX c h -10
-KPX c k -20
-KPX c kcommaaccent -20
-KPX c l -20
-KPX c lacute -20
-KPX c lcommaaccent -20
-KPX c lslash -20
-KPX c y -10
-KPX c yacute -10
-KPX c ydieresis -10
-KPX cacute h -10
-KPX cacute k -20
-KPX cacute kcommaaccent -20
-KPX cacute l -20
-KPX cacute lacute -20
-KPX cacute lcommaaccent -20
-KPX cacute lslash -20
-KPX cacute y -10
-KPX cacute yacute -10
-KPX cacute ydieresis -10
-KPX ccaron h -10
-KPX ccaron k -20
-KPX ccaron kcommaaccent -20
-KPX ccaron l -20
-KPX ccaron lacute -20
-KPX ccaron lcommaaccent -20
-KPX ccaron lslash -20
-KPX ccaron y -10
-KPX ccaron yacute -10
-KPX ccaron ydieresis -10
-KPX ccedilla h -10
-KPX ccedilla k -20
-KPX ccedilla kcommaaccent -20
-KPX ccedilla l -20
-KPX ccedilla lacute -20
-KPX ccedilla lcommaaccent -20
-KPX ccedilla lslash -20
-KPX ccedilla y -10
-KPX ccedilla yacute -10
-KPX ccedilla ydieresis -10
-KPX colon space -40
-KPX comma quotedblright -120
-KPX comma quoteright -120
-KPX comma space -40
-KPX d d -10
-KPX d dcroat -10
-KPX d v -15
-KPX d w -15
-KPX d y -15
-KPX d yacute -15
-KPX d ydieresis -15
-KPX dcroat d -10
-KPX dcroat dcroat -10
-KPX dcroat v -15
-KPX dcroat w -15
-KPX dcroat y -15
-KPX dcroat yacute -15
-KPX dcroat ydieresis -15
-KPX e comma 10
-KPX e period 20
-KPX e v -15
-KPX e w -15
-KPX e x -15
-KPX e y -15
-KPX e yacute -15
-KPX e ydieresis -15
-KPX eacute comma 10
-KPX eacute period 20
-KPX eacute v -15
-KPX eacute w -15
-KPX eacute x -15
-KPX eacute y -15
-KPX eacute yacute -15
-KPX eacute ydieresis -15
-KPX ecaron comma 10
-KPX ecaron period 20
-KPX ecaron v -15
-KPX ecaron w -15
-KPX ecaron x -15
-KPX ecaron y -15
-KPX ecaron yacute -15
-KPX ecaron ydieresis -15
-KPX ecircumflex comma 10
-KPX ecircumflex period 20
-KPX ecircumflex v -15
-KPX ecircumflex w -15
-KPX ecircumflex x -15
-KPX ecircumflex y -15
-KPX ecircumflex yacute -15
-KPX ecircumflex ydieresis -15
-KPX edieresis comma 10
-KPX edieresis period 20
-KPX edieresis v -15
-KPX edieresis w -15
-KPX edieresis x -15
-KPX edieresis y -15
-KPX edieresis yacute -15
-KPX edieresis ydieresis -15
-KPX edotaccent comma 10
-KPX edotaccent period 20
-KPX edotaccent v -15
-KPX edotaccent w -15
-KPX edotaccent x -15
-KPX edotaccent y -15
-KPX edotaccent yacute -15
-KPX edotaccent ydieresis -15
-KPX egrave comma 10
-KPX egrave period 20
-KPX egrave v -15
-KPX egrave w -15
-KPX egrave x -15
-KPX egrave y -15
-KPX egrave yacute -15
-KPX egrave ydieresis -15
-KPX emacron comma 10
-KPX emacron period 20
-KPX emacron v -15
-KPX emacron w -15
-KPX emacron x -15
-KPX emacron y -15
-KPX emacron yacute -15
-KPX emacron ydieresis -15
-KPX eogonek comma 10
-KPX eogonek period 20
-KPX eogonek v -15
-KPX eogonek w -15
-KPX eogonek x -15
-KPX eogonek y -15
-KPX eogonek yacute -15
-KPX eogonek ydieresis -15
-KPX f comma -10
-KPX f e -10
-KPX f eacute -10
-KPX f ecaron -10
-KPX f ecircumflex -10
-KPX f edieresis -10
-KPX f edotaccent -10
-KPX f egrave -10
-KPX f emacron -10
-KPX f eogonek -10
-KPX f o -20
-KPX f oacute -20
-KPX f ocircumflex -20
-KPX f odieresis -20
-KPX f ograve -20
-KPX f ohungarumlaut -20
-KPX f omacron -20
-KPX f oslash -20
-KPX f otilde -20
-KPX f period -10
-KPX f quotedblright 30
-KPX f quoteright 30
-KPX g e 10
-KPX g eacute 10
-KPX g ecaron 10
-KPX g ecircumflex 10
-KPX g edieresis 10
-KPX g edotaccent 10
-KPX g egrave 10
-KPX g emacron 10
-KPX g eogonek 10
-KPX g g -10
-KPX g gbreve -10
-KPX g gcommaaccent -10
-KPX gbreve e 10
-KPX gbreve eacute 10
-KPX gbreve ecaron 10
-KPX gbreve ecircumflex 10
-KPX gbreve edieresis 10
-KPX gbreve edotaccent 10
-KPX gbreve egrave 10
-KPX gbreve emacron 10
-KPX gbreve eogonek 10
-KPX gbreve g -10
-KPX gbreve gbreve -10
-KPX gbreve gcommaaccent -10
-KPX gcommaaccent e 10
-KPX gcommaaccent eacute 10
-KPX gcommaaccent ecaron 10
-KPX gcommaaccent ecircumflex 10
-KPX gcommaaccent edieresis 10
-KPX gcommaaccent edotaccent 10
-KPX gcommaaccent egrave 10
-KPX gcommaaccent emacron 10
-KPX gcommaaccent eogonek 10
-KPX gcommaaccent g -10
-KPX gcommaaccent gbreve -10
-KPX gcommaaccent gcommaaccent -10
-KPX h y -20
-KPX h yacute -20
-KPX h ydieresis -20
-KPX k o -15
-KPX k oacute -15
-KPX k ocircumflex -15
-KPX k odieresis -15
-KPX k ograve -15
-KPX k ohungarumlaut -15
-KPX k omacron -15
-KPX k oslash -15
-KPX k otilde -15
-KPX kcommaaccent o -15
-KPX kcommaaccent oacute -15
-KPX kcommaaccent ocircumflex -15
-KPX kcommaaccent odieresis -15
-KPX kcommaaccent ograve -15
-KPX kcommaaccent ohungarumlaut -15
-KPX kcommaaccent omacron -15
-KPX kcommaaccent oslash -15
-KPX kcommaaccent otilde -15
-KPX l w -15
-KPX l y -15
-KPX l yacute -15
-KPX l ydieresis -15
-KPX lacute w -15
-KPX lacute y -15
-KPX lacute yacute -15
-KPX lacute ydieresis -15
-KPX lcommaaccent w -15
-KPX lcommaaccent y -15
-KPX lcommaaccent yacute -15
-KPX lcommaaccent ydieresis -15
-KPX lslash w -15
-KPX lslash y -15
-KPX lslash yacute -15
-KPX lslash ydieresis -15
-KPX m u -20
-KPX m uacute -20
-KPX m ucircumflex -20
-KPX m udieresis -20
-KPX m ugrave -20
-KPX m uhungarumlaut -20
-KPX m umacron -20
-KPX m uogonek -20
-KPX m uring -20
-KPX m y -30
-KPX m yacute -30
-KPX m ydieresis -30
-KPX n u -10
-KPX n uacute -10
-KPX n ucircumflex -10
-KPX n udieresis -10
-KPX n ugrave -10
-KPX n uhungarumlaut -10
-KPX n umacron -10
-KPX n uogonek -10
-KPX n uring -10
-KPX n v -40
-KPX n y -20
-KPX n yacute -20
-KPX n ydieresis -20
-KPX nacute u -10
-KPX nacute uacute -10
-KPX nacute ucircumflex -10
-KPX nacute udieresis -10
-KPX nacute ugrave -10
-KPX nacute uhungarumlaut -10
-KPX nacute umacron -10
-KPX nacute uogonek -10
-KPX nacute uring -10
-KPX nacute v -40
-KPX nacute y -20
-KPX nacute yacute -20
-KPX nacute ydieresis -20
-KPX ncaron u -10
-KPX ncaron uacute -10
-KPX ncaron ucircumflex -10
-KPX ncaron udieresis -10
-KPX ncaron ugrave -10
-KPX ncaron uhungarumlaut -10
-KPX ncaron umacron -10
-KPX ncaron uogonek -10
-KPX ncaron uring -10
-KPX ncaron v -40
-KPX ncaron y -20
-KPX ncaron yacute -20
-KPX ncaron ydieresis -20
-KPX ncommaaccent u -10
-KPX ncommaaccent uacute -10
-KPX ncommaaccent ucircumflex -10
-KPX ncommaaccent udieresis -10
-KPX ncommaaccent ugrave -10
-KPX ncommaaccent uhungarumlaut -10
-KPX ncommaaccent umacron -10
-KPX ncommaaccent uogonek -10
-KPX ncommaaccent uring -10
-KPX ncommaaccent v -40
-KPX ncommaaccent y -20
-KPX ncommaaccent yacute -20
-KPX ncommaaccent ydieresis -20
-KPX ntilde u -10
-KPX ntilde uacute -10
-KPX ntilde ucircumflex -10
-KPX ntilde udieresis -10
-KPX ntilde ugrave -10
-KPX ntilde uhungarumlaut -10
-KPX ntilde umacron -10
-KPX ntilde uogonek -10
-KPX ntilde uring -10
-KPX ntilde v -40
-KPX ntilde y -20
-KPX ntilde yacute -20
-KPX ntilde ydieresis -20
-KPX o v -20
-KPX o w -15
-KPX o x -30
-KPX o y -20
-KPX o yacute -20
-KPX o ydieresis -20
-KPX oacute v -20
-KPX oacute w -15
-KPX oacute x -30
-KPX oacute y -20
-KPX oacute yacute -20
-KPX oacute ydieresis -20
-KPX ocircumflex v -20
-KPX ocircumflex w -15
-KPX ocircumflex x -30
-KPX ocircumflex y -20
-KPX ocircumflex yacute -20
-KPX ocircumflex ydieresis -20
-KPX odieresis v -20
-KPX odieresis w -15
-KPX odieresis x -30
-KPX odieresis y -20
-KPX odieresis yacute -20
-KPX odieresis ydieresis -20
-KPX ograve v -20
-KPX ograve w -15
-KPX ograve x -30
-KPX ograve y -20
-KPX ograve yacute -20
-KPX ograve ydieresis -20
-KPX ohungarumlaut v -20
-KPX ohungarumlaut w -15
-KPX ohungarumlaut x -30
-KPX ohungarumlaut y -20
-KPX ohungarumlaut yacute -20
-KPX ohungarumlaut ydieresis -20
-KPX omacron v -20
-KPX omacron w -15
-KPX omacron x -30
-KPX omacron y -20
-KPX omacron yacute -20
-KPX omacron ydieresis -20
-KPX oslash v -20
-KPX oslash w -15
-KPX oslash x -30
-KPX oslash y -20
-KPX oslash yacute -20
-KPX oslash ydieresis -20
-KPX otilde v -20
-KPX otilde w -15
-KPX otilde x -30
-KPX otilde y -20
-KPX otilde yacute -20
-KPX otilde ydieresis -20
-KPX p y -15
-KPX p yacute -15
-KPX p ydieresis -15
-KPX period quotedblright -120
-KPX period quoteright -120
-KPX period space -40
-KPX quotedblright space -80
-KPX quoteleft quoteleft -46
-KPX quoteright d -80
-KPX quoteright dcroat -80
-KPX quoteright l -20
-KPX quoteright lacute -20
-KPX quoteright lcommaaccent -20
-KPX quoteright lslash -20
-KPX quoteright quoteright -46
-KPX quoteright r -40
-KPX quoteright racute -40
-KPX quoteright rcaron -40
-KPX quoteright rcommaaccent -40
-KPX quoteright s -60
-KPX quoteright sacute -60
-KPX quoteright scaron -60
-KPX quoteright scedilla -60
-KPX quoteright scommaaccent -60
-KPX quoteright space -80
-KPX quoteright v -20
-KPX r c -20
-KPX r cacute -20
-KPX r ccaron -20
-KPX r ccedilla -20
-KPX r comma -60
-KPX r d -20
-KPX r dcroat -20
-KPX r g -15
-KPX r gbreve -15
-KPX r gcommaaccent -15
-KPX r hyphen -20
-KPX r o -20
-KPX r oacute -20
-KPX r ocircumflex -20
-KPX r odieresis -20
-KPX r ograve -20
-KPX r ohungarumlaut -20
-KPX r omacron -20
-KPX r oslash -20
-KPX r otilde -20
-KPX r period -60
-KPX r q -20
-KPX r s -15
-KPX r sacute -15
-KPX r scaron -15
-KPX r scedilla -15
-KPX r scommaaccent -15
-KPX r t 20
-KPX r tcommaaccent 20
-KPX r v 10
-KPX r y 10
-KPX r yacute 10
-KPX r ydieresis 10
-KPX racute c -20
-KPX racute cacute -20
-KPX racute ccaron -20
-KPX racute ccedilla -20
-KPX racute comma -60
-KPX racute d -20
-KPX racute dcroat -20
-KPX racute g -15
-KPX racute gbreve -15
-KPX racute gcommaaccent -15
-KPX racute hyphen -20
-KPX racute o -20
-KPX racute oacute -20
-KPX racute ocircumflex -20
-KPX racute odieresis -20
-KPX racute ograve -20
-KPX racute ohungarumlaut -20
-KPX racute omacron -20
-KPX racute oslash -20
-KPX racute otilde -20
-KPX racute period -60
-KPX racute q -20
-KPX racute s -15
-KPX racute sacute -15
-KPX racute scaron -15
-KPX racute scedilla -15
-KPX racute scommaaccent -15
-KPX racute t 20
-KPX racute tcommaaccent 20
-KPX racute v 10
-KPX racute y 10
-KPX racute yacute 10
-KPX racute ydieresis 10
-KPX rcaron c -20
-KPX rcaron cacute -20
-KPX rcaron ccaron -20
-KPX rcaron ccedilla -20
-KPX rcaron comma -60
-KPX rcaron d -20
-KPX rcaron dcroat -20
-KPX rcaron g -15
-KPX rcaron gbreve -15
-KPX rcaron gcommaaccent -15
-KPX rcaron hyphen -20
-KPX rcaron o -20
-KPX rcaron oacute -20
-KPX rcaron ocircumflex -20
-KPX rcaron odieresis -20
-KPX rcaron ograve -20
-KPX rcaron ohungarumlaut -20
-KPX rcaron omacron -20
-KPX rcaron oslash -20
-KPX rcaron otilde -20
-KPX rcaron period -60
-KPX rcaron q -20
-KPX rcaron s -15
-KPX rcaron sacute -15
-KPX rcaron scaron -15
-KPX rcaron scedilla -15
-KPX rcaron scommaaccent -15
-KPX rcaron t 20
-KPX rcaron tcommaaccent 20
-KPX rcaron v 10
-KPX rcaron y 10
-KPX rcaron yacute 10
-KPX rcaron ydieresis 10
-KPX rcommaaccent c -20
-KPX rcommaaccent cacute -20
-KPX rcommaaccent ccaron -20
-KPX rcommaaccent ccedilla -20
-KPX rcommaaccent comma -60
-KPX rcommaaccent d -20
-KPX rcommaaccent dcroat -20
-KPX rcommaaccent g -15
-KPX rcommaaccent gbreve -15
-KPX rcommaaccent gcommaaccent -15
-KPX rcommaaccent hyphen -20
-KPX rcommaaccent o -20
-KPX rcommaaccent oacute -20
-KPX rcommaaccent ocircumflex -20
-KPX rcommaaccent odieresis -20
-KPX rcommaaccent ograve -20
-KPX rcommaaccent ohungarumlaut -20
-KPX rcommaaccent omacron -20
-KPX rcommaaccent oslash -20
-KPX rcommaaccent otilde -20
-KPX rcommaaccent period -60
-KPX rcommaaccent q -20
-KPX rcommaaccent s -15
-KPX rcommaaccent sacute -15
-KPX rcommaaccent scaron -15
-KPX rcommaaccent scedilla -15
-KPX rcommaaccent scommaaccent -15
-KPX rcommaaccent t 20
-KPX rcommaaccent tcommaaccent 20
-KPX rcommaaccent v 10
-KPX rcommaaccent y 10
-KPX rcommaaccent yacute 10
-KPX rcommaaccent ydieresis 10
-KPX s w -15
-KPX sacute w -15
-KPX scaron w -15
-KPX scedilla w -15
-KPX scommaaccent w -15
-KPX semicolon space -40
-KPX space T -100
-KPX space Tcaron -100
-KPX space Tcommaaccent -100
-KPX space V -80
-KPX space W -80
-KPX space Y -120
-KPX space Yacute -120
-KPX space Ydieresis -120
-KPX space quotedblleft -80
-KPX space quoteleft -60
-KPX v a -20
-KPX v aacute -20
-KPX v abreve -20
-KPX v acircumflex -20
-KPX v adieresis -20
-KPX v agrave -20
-KPX v amacron -20
-KPX v aogonek -20
-KPX v aring -20
-KPX v atilde -20
-KPX v comma -80
-KPX v o -30
-KPX v oacute -30
-KPX v ocircumflex -30
-KPX v odieresis -30
-KPX v ograve -30
-KPX v ohungarumlaut -30
-KPX v omacron -30
-KPX v oslash -30
-KPX v otilde -30
-KPX v period -80
-KPX w comma -40
-KPX w o -20
-KPX w oacute -20
-KPX w ocircumflex -20
-KPX w odieresis -20
-KPX w ograve -20
-KPX w ohungarumlaut -20
-KPX w omacron -20
-KPX w oslash -20
-KPX w otilde -20
-KPX w period -40
-KPX x e -10
-KPX x eacute -10
-KPX x ecaron -10
-KPX x ecircumflex -10
-KPX x edieresis -10
-KPX x edotaccent -10
-KPX x egrave -10
-KPX x emacron -10
-KPX x eogonek -10
-KPX y a -30
-KPX y aacute -30
-KPX y abreve -30
-KPX y acircumflex -30
-KPX y adieresis -30
-KPX y agrave -30
-KPX y amacron -30
-KPX y aogonek -30
-KPX y aring -30
-KPX y atilde -30
-KPX y comma -80
-KPX y e -10
-KPX y eacute -10
-KPX y ecaron -10
-KPX y ecircumflex -10
-KPX y edieresis -10
-KPX y edotaccent -10
-KPX y egrave -10
-KPX y emacron -10
-KPX y eogonek -10
-KPX y o -25
-KPX y oacute -25
-KPX y ocircumflex -25
-KPX y odieresis -25
-KPX y ograve -25
-KPX y ohungarumlaut -25
-KPX y omacron -25
-KPX y oslash -25
-KPX y otilde -25
-KPX y period -80
-KPX yacute a -30
-KPX yacute aacute -30
-KPX yacute abreve -30
-KPX yacute acircumflex -30
-KPX yacute adieresis -30
-KPX yacute agrave -30
-KPX yacute amacron -30
-KPX yacute aogonek -30
-KPX yacute aring -30
-KPX yacute atilde -30
-KPX yacute comma -80
-KPX yacute e -10
-KPX yacute eacute -10
-KPX yacute ecaron -10
-KPX yacute ecircumflex -10
-KPX yacute edieresis -10
-KPX yacute edotaccent -10
-KPX yacute egrave -10
-KPX yacute emacron -10
-KPX yacute eogonek -10
-KPX yacute o -25
-KPX yacute oacute -25
-KPX yacute ocircumflex -25
-KPX yacute odieresis -25
-KPX yacute ograve -25
-KPX yacute ohungarumlaut -25
-KPX yacute omacron -25
-KPX yacute oslash -25
-KPX yacute otilde -25
-KPX yacute period -80
-KPX ydieresis a -30
-KPX ydieresis aacute -30
-KPX ydieresis abreve -30
-KPX ydieresis acircumflex -30
-KPX ydieresis adieresis -30
-KPX ydieresis agrave -30
-KPX ydieresis amacron -30
-KPX ydieresis aogonek -30
-KPX ydieresis aring -30
-KPX ydieresis atilde -30
-KPX ydieresis comma -80
-KPX ydieresis e -10
-KPX ydieresis eacute -10
-KPX ydieresis ecaron -10
-KPX ydieresis ecircumflex -10
-KPX ydieresis edieresis -10
-KPX ydieresis edotaccent -10
-KPX ydieresis egrave -10
-KPX ydieresis emacron -10
-KPX ydieresis eogonek -10
-KPX ydieresis o -25
-KPX ydieresis oacute -25
-KPX ydieresis ocircumflex -25
-KPX ydieresis odieresis -25
-KPX ydieresis ograve -25
-KPX ydieresis ohungarumlaut -25
-KPX ydieresis omacron -25
-KPX ydieresis oslash -25
-KPX ydieresis otilde -25
-KPX ydieresis period -80
-KPX z e 10
-KPX z eacute 10
-KPX z ecaron 10
-KPX z ecircumflex 10
-KPX z edieresis 10
-KPX z edotaccent 10
-KPX z egrave 10
-KPX z emacron 10
-KPX z eogonek 10
-KPX zacute e 10
-KPX zacute eacute 10
-KPX zacute ecaron 10
-KPX zacute ecircumflex 10
-KPX zacute edieresis 10
-KPX zacute edotaccent 10
-KPX zacute egrave 10
-KPX zacute emacron 10
-KPX zacute eogonek 10
-KPX zcaron e 10
-KPX zcaron eacute 10
-KPX zcaron ecaron 10
-KPX zcaron ecircumflex 10
-KPX zcaron edieresis 10
-KPX zcaron edotaccent 10
-KPX zcaron egrave 10
-KPX zcaron emacron 10
-KPX zcaron eogonek 10
-KPX zdotaccent e 10
-KPX zdotaccent eacute 10
-KPX zdotaccent ecaron 10
-KPX zdotaccent ecircumflex 10
-KPX zdotaccent edieresis 10
-KPX zdotaccent edotaccent 10
-KPX zdotaccent egrave 10
-KPX zdotaccent emacron 10
-KPX zdotaccent eogonek 10
-EndKernPairs
-EndKernData
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Helvetica-BoldOblique.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Helvetica-BoldOblique.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Helvetica-BoldOblique.afm 2004-05-26 16:06:20.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Helvetica-BoldOblique.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,2827 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Thu May 1 12:45:12 1997
-Comment UniqueID 43053
-Comment VMusage 14482 68586
-FontName Helvetica-BoldOblique
-FullName Helvetica Bold Oblique
-FamilyName Helvetica
-Weight Bold
-ItalicAngle -12
-IsFixedPitch false
-CharacterSet ExtendedRoman
-FontBBox -174 -228 1114 962
-UnderlinePosition -100
-UnderlineThickness 50
-Version 002.000
-Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
-EncodingScheme AdobeStandardEncoding
-CapHeight 718
-XHeight 532
-Ascender 718
-Descender -207
-StdHW 118
-StdVW 140
-StartCharMetrics 315
-C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 333 ; N exclam ; B 94 0 397 718 ;
-C 34 ; WX 474 ; N quotedbl ; B 193 447 529 718 ;
-C 35 ; WX 556 ; N numbersign ; B 60 0 644 698 ;
-C 36 ; WX 556 ; N dollar ; B 67 -115 622 775 ;
-C 37 ; WX 889 ; N percent ; B 136 -19 901 710 ;
-C 38 ; WX 722 ; N ampersand ; B 89 -19 732 718 ;
-C 39 ; WX 278 ; N quoteright ; B 167 445 362 718 ;
-C 40 ; WX 333 ; N parenleft ; B 76 -208 470 734 ;
-C 41 ; WX 333 ; N parenright ; B -25 -208 369 734 ;
-C 42 ; WX 389 ; N asterisk ; B 146 387 481 718 ;
-C 43 ; WX 584 ; N plus ; B 82 0 610 506 ;
-C 44 ; WX 278 ; N comma ; B 28 -168 245 146 ;
-C 45 ; WX 333 ; N hyphen ; B 73 215 379 345 ;
-C 46 ; WX 278 ; N period ; B 64 0 245 146 ;
-C 47 ; WX 278 ; N slash ; B -37 -19 468 737 ;
-C 48 ; WX 556 ; N zero ; B 86 -19 617 710 ;
-C 49 ; WX 556 ; N one ; B 173 0 529 710 ;
-C 50 ; WX 556 ; N two ; B 26 0 619 710 ;
-C 51 ; WX 556 ; N three ; B 65 -19 608 710 ;
-C 52 ; WX 556 ; N four ; B 60 0 598 710 ;
-C 53 ; WX 556 ; N five ; B 64 -19 636 698 ;
-C 54 ; WX 556 ; N six ; B 85 -19 619 710 ;
-C 55 ; WX 556 ; N seven ; B 125 0 676 698 ;
-C 56 ; WX 556 ; N eight ; B 69 -19 616 710 ;
-C 57 ; WX 556 ; N nine ; B 78 -19 615 710 ;
-C 58 ; WX 333 ; N colon ; B 92 0 351 512 ;
-C 59 ; WX 333 ; N semicolon ; B 56 -168 351 512 ;
-C 60 ; WX 584 ; N less ; B 82 -8 655 514 ;
-C 61 ; WX 584 ; N equal ; B 58 87 633 419 ;
-C 62 ; WX 584 ; N greater ; B 36 -8 609 514 ;
-C 63 ; WX 611 ; N question ; B 165 0 671 727 ;
-C 64 ; WX 975 ; N at ; B 186 -19 954 737 ;
-C 65 ; WX 722 ; N A ; B 20 0 702 718 ;
-C 66 ; WX 722 ; N B ; B 76 0 764 718 ;
-C 67 ; WX 722 ; N C ; B 107 -19 789 737 ;
-C 68 ; WX 722 ; N D ; B 76 0 777 718 ;
-C 69 ; WX 667 ; N E ; B 76 0 757 718 ;
-C 70 ; WX 611 ; N F ; B 76 0 740 718 ;
-C 71 ; WX 778 ; N G ; B 108 -19 817 737 ;
-C 72 ; WX 722 ; N H ; B 71 0 804 718 ;
-C 73 ; WX 278 ; N I ; B 64 0 367 718 ;
-C 74 ; WX 556 ; N J ; B 60 -18 637 718 ;
-C 75 ; WX 722 ; N K ; B 87 0 858 718 ;
-C 76 ; WX 611 ; N L ; B 76 0 611 718 ;
-C 77 ; WX 833 ; N M ; B 69 0 918 718 ;
-C 78 ; WX 722 ; N N ; B 69 0 807 718 ;
-C 79 ; WX 778 ; N O ; B 107 -19 823 737 ;
-C 80 ; WX 667 ; N P ; B 76 0 738 718 ;
-C 81 ; WX 778 ; N Q ; B 107 -52 823 737 ;
-C 82 ; WX 722 ; N R ; B 76 0 778 718 ;
-C 83 ; WX 667 ; N S ; B 81 -19 718 737 ;
-C 84 ; WX 611 ; N T ; B 140 0 751 718 ;
-C 85 ; WX 722 ; N U ; B 116 -19 804 718 ;
-C 86 ; WX 667 ; N V ; B 172 0 801 718 ;
-C 87 ; WX 944 ; N W ; B 169 0 1082 718 ;
-C 88 ; WX 667 ; N X ; B 14 0 791 718 ;
-C 89 ; WX 667 ; N Y ; B 168 0 806 718 ;
-C 90 ; WX 611 ; N Z ; B 25 0 737 718 ;
-C 91 ; WX 333 ; N bracketleft ; B 21 -196 462 722 ;
-C 92 ; WX 278 ; N backslash ; B 124 -19 307 737 ;
-C 93 ; WX 333 ; N bracketright ; B -18 -196 423 722 ;
-C 94 ; WX 584 ; N asciicircum ; B 131 323 591 698 ;
-C 95 ; WX 556 ; N underscore ; B -27 -125 540 -75 ;
-C 96 ; WX 278 ; N quoteleft ; B 165 454 361 727 ;
-C 97 ; WX 556 ; N a ; B 55 -14 583 546 ;
-C 98 ; WX 611 ; N b ; B 61 -14 645 718 ;
-C 99 ; WX 556 ; N c ; B 79 -14 599 546 ;
-C 100 ; WX 611 ; N d ; B 82 -14 704 718 ;
-C 101 ; WX 556 ; N e ; B 70 -14 593 546 ;
-C 102 ; WX 333 ; N f ; B 87 0 469 727 ; L i fi ; L l fl ;
-C 103 ; WX 611 ; N g ; B 38 -217 666 546 ;
-C 104 ; WX 611 ; N h ; B 65 0 629 718 ;
-C 105 ; WX 278 ; N i ; B 69 0 363 725 ;
-C 106 ; WX 278 ; N j ; B -42 -214 363 725 ;
-C 107 ; WX 556 ; N k ; B 69 0 670 718 ;
-C 108 ; WX 278 ; N l ; B 69 0 362 718 ;
-C 109 ; WX 889 ; N m ; B 64 0 909 546 ;
-C 110 ; WX 611 ; N n ; B 65 0 629 546 ;
-C 111 ; WX 611 ; N o ; B 82 -14 643 546 ;
-C 112 ; WX 611 ; N p ; B 18 -207 645 546 ;
-C 113 ; WX 611 ; N q ; B 80 -207 665 546 ;
-C 114 ; WX 389 ; N r ; B 64 0 489 546 ;
-C 115 ; WX 556 ; N s ; B 63 -14 584 546 ;
-C 116 ; WX 333 ; N t ; B 100 -6 422 676 ;
-C 117 ; WX 611 ; N u ; B 98 -14 658 532 ;
-C 118 ; WX 556 ; N v ; B 126 0 656 532 ;
-C 119 ; WX 778 ; N w ; B 123 0 882 532 ;
-C 120 ; WX 556 ; N x ; B 15 0 648 532 ;
-C 121 ; WX 556 ; N y ; B 42 -214 652 532 ;
-C 122 ; WX 500 ; N z ; B 20 0 583 532 ;
-C 123 ; WX 389 ; N braceleft ; B 94 -196 518 722 ;
-C 124 ; WX 280 ; N bar ; B 36 -225 361 775 ;
-C 125 ; WX 389 ; N braceright ; B -18 -196 407 722 ;
-C 126 ; WX 584 ; N asciitilde ; B 115 163 577 343 ;
-C 161 ; WX 333 ; N exclamdown ; B 50 -186 353 532 ;
-C 162 ; WX 556 ; N cent ; B 79 -118 599 628 ;
-C 163 ; WX 556 ; N sterling ; B 50 -16 635 718 ;
-C 164 ; WX 167 ; N fraction ; B -174 -19 487 710 ;
-C 165 ; WX 556 ; N yen ; B 60 0 713 698 ;
-C 166 ; WX 556 ; N florin ; B -50 -210 669 737 ;
-C 167 ; WX 556 ; N section ; B 61 -184 598 727 ;
-C 168 ; WX 556 ; N currency ; B 27 76 680 636 ;
-C 169 ; WX 238 ; N quotesingle ; B 165 447 321 718 ;
-C 170 ; WX 500 ; N quotedblleft ; B 160 454 588 727 ;
-C 171 ; WX 556 ; N guillemotleft ; B 135 76 571 484 ;
-C 172 ; WX 333 ; N guilsinglleft ; B 130 76 353 484 ;
-C 173 ; WX 333 ; N guilsinglright ; B 99 76 322 484 ;
-C 174 ; WX 611 ; N fi ; B 87 0 696 727 ;
-C 175 ; WX 611 ; N fl ; B 87 0 695 727 ;
-C 177 ; WX 556 ; N endash ; B 48 227 627 333 ;
-C 178 ; WX 556 ; N dagger ; B 118 -171 626 718 ;
-C 179 ; WX 556 ; N daggerdbl ; B 46 -171 628 718 ;
-C 180 ; WX 278 ; N periodcentered ; B 110 172 276 334 ;
-C 182 ; WX 556 ; N paragraph ; B 98 -191 688 700 ;
-C 183 ; WX 350 ; N bullet ; B 83 194 420 524 ;
-C 184 ; WX 278 ; N quotesinglbase ; B 41 -146 236 127 ;
-C 185 ; WX 500 ; N quotedblbase ; B 36 -146 463 127 ;
-C 186 ; WX 500 ; N quotedblright ; B 162 445 589 718 ;
-C 187 ; WX 556 ; N guillemotright ; B 104 76 540 484 ;
-C 188 ; WX 1000 ; N ellipsis ; B 92 0 939 146 ;
-C 189 ; WX 1000 ; N perthousand ; B 76 -19 1038 710 ;
-C 191 ; WX 611 ; N questiondown ; B 53 -195 559 532 ;
-C 193 ; WX 333 ; N grave ; B 136 604 353 750 ;
-C 194 ; WX 333 ; N acute ; B 236 604 515 750 ;
-C 195 ; WX 333 ; N circumflex ; B 118 604 471 750 ;
-C 196 ; WX 333 ; N tilde ; B 113 610 507 737 ;
-C 197 ; WX 333 ; N macron ; B 122 604 483 678 ;
-C 198 ; WX 333 ; N breve ; B 156 604 494 750 ;
-C 199 ; WX 333 ; N dotaccent ; B 235 614 385 729 ;
-C 200 ; WX 333 ; N dieresis ; B 137 614 482 729 ;
-C 202 ; WX 333 ; N ring ; B 200 568 420 776 ;
-C 203 ; WX 333 ; N cedilla ; B -37 -228 220 0 ;
-C 205 ; WX 333 ; N hungarumlaut ; B 137 604 645 750 ;
-C 206 ; WX 333 ; N ogonek ; B 41 -228 264 0 ;
-C 207 ; WX 333 ; N caron ; B 149 604 502 750 ;
-C 208 ; WX 1000 ; N emdash ; B 48 227 1071 333 ;
-C 225 ; WX 1000 ; N AE ; B 5 0 1100 718 ;
-C 227 ; WX 370 ; N ordfeminine ; B 125 401 465 737 ;
-C 232 ; WX 611 ; N Lslash ; B 34 0 611 718 ;
-C 233 ; WX 778 ; N Oslash ; B 35 -27 894 745 ;
-C 234 ; WX 1000 ; N OE ; B 99 -19 1114 737 ;
-C 235 ; WX 365 ; N ordmasculine ; B 123 401 485 737 ;
-C 241 ; WX 889 ; N ae ; B 56 -14 923 546 ;
-C 245 ; WX 278 ; N dotlessi ; B 69 0 322 532 ;
-C 248 ; WX 278 ; N lslash ; B 40 0 407 718 ;
-C 249 ; WX 611 ; N oslash ; B 22 -29 701 560 ;
-C 250 ; WX 944 ; N oe ; B 82 -14 977 546 ;
-C 251 ; WX 611 ; N germandbls ; B 69 -14 657 731 ;
-C -1 ; WX 278 ; N Idieresis ; B 64 0 494 915 ;
-C -1 ; WX 556 ; N eacute ; B 70 -14 627 750 ;
-C -1 ; WX 556 ; N abreve ; B 55 -14 606 750 ;
-C -1 ; WX 611 ; N uhungarumlaut ; B 98 -14 784 750 ;
-C -1 ; WX 556 ; N ecaron ; B 70 -14 614 750 ;
-C -1 ; WX 667 ; N Ydieresis ; B 168 0 806 915 ;
-C -1 ; WX 584 ; N divide ; B 82 -42 610 548 ;
-C -1 ; WX 667 ; N Yacute ; B 168 0 806 936 ;
-C -1 ; WX 722 ; N Acircumflex ; B 20 0 706 936 ;
-C -1 ; WX 556 ; N aacute ; B 55 -14 627 750 ;
-C -1 ; WX 722 ; N Ucircumflex ; B 116 -19 804 936 ;
-C -1 ; WX 556 ; N yacute ; B 42 -214 652 750 ;
-C -1 ; WX 556 ; N scommaaccent ; B 63 -228 584 546 ;
-C -1 ; WX 556 ; N ecircumflex ; B 70 -14 593 750 ;
-C -1 ; WX 722 ; N Uring ; B 116 -19 804 962 ;
-C -1 ; WX 722 ; N Udieresis ; B 116 -19 804 915 ;
-C -1 ; WX 556 ; N aogonek ; B 55 -224 583 546 ;
-C -1 ; WX 722 ; N Uacute ; B 116 -19 804 936 ;
-C -1 ; WX 611 ; N uogonek ; B 98 -228 658 532 ;
-C -1 ; WX 667 ; N Edieresis ; B 76 0 757 915 ;
-C -1 ; WX 722 ; N Dcroat ; B 62 0 777 718 ;
-C -1 ; WX 250 ; N commaaccent ; B 16 -228 188 -50 ;
-C -1 ; WX 737 ; N copyright ; B 56 -19 835 737 ;
-C -1 ; WX 667 ; N Emacron ; B 76 0 757 864 ;
-C -1 ; WX 556 ; N ccaron ; B 79 -14 614 750 ;
-C -1 ; WX 556 ; N aring ; B 55 -14 583 776 ;
-C -1 ; WX 722 ; N Ncommaaccent ; B 69 -228 807 718 ;
-C -1 ; WX 278 ; N lacute ; B 69 0 528 936 ;
-C -1 ; WX 556 ; N agrave ; B 55 -14 583 750 ;
-C -1 ; WX 611 ; N Tcommaaccent ; B 140 -228 751 718 ;
-C -1 ; WX 722 ; N Cacute ; B 107 -19 789 936 ;
-C -1 ; WX 556 ; N atilde ; B 55 -14 619 737 ;
-C -1 ; WX 667 ; N Edotaccent ; B 76 0 757 915 ;
-C -1 ; WX 556 ; N scaron ; B 63 -14 614 750 ;
-C -1 ; WX 556 ; N scedilla ; B 63 -228 584 546 ;
-C -1 ; WX 278 ; N iacute ; B 69 0 488 750 ;
-C -1 ; WX 494 ; N lozenge ; B 90 0 564 745 ;
-C -1 ; WX 722 ; N Rcaron ; B 76 0 778 936 ;
-C -1 ; WX 778 ; N Gcommaaccent ; B 108 -228 817 737 ;
-C -1 ; WX 611 ; N ucircumflex ; B 98 -14 658 750 ;
-C -1 ; WX 556 ; N acircumflex ; B 55 -14 583 750 ;
-C -1 ; WX 722 ; N Amacron ; B 20 0 718 864 ;
-C -1 ; WX 389 ; N rcaron ; B 64 0 530 750 ;
-C -1 ; WX 556 ; N ccedilla ; B 79 -228 599 546 ;
-C -1 ; WX 611 ; N Zdotaccent ; B 25 0 737 915 ;
-C -1 ; WX 667 ; N Thorn ; B 76 0 716 718 ;
-C -1 ; WX 778 ; N Omacron ; B 107 -19 823 864 ;
-C -1 ; WX 722 ; N Racute ; B 76 0 778 936 ;
-C -1 ; WX 667 ; N Sacute ; B 81 -19 722 936 ;
-C -1 ; WX 743 ; N dcaron ; B 82 -14 903 718 ;
-C -1 ; WX 722 ; N Umacron ; B 116 -19 804 864 ;
-C -1 ; WX 611 ; N uring ; B 98 -14 658 776 ;
-C -1 ; WX 333 ; N threesuperior ; B 91 271 441 710 ;
-C -1 ; WX 778 ; N Ograve ; B 107 -19 823 936 ;
-C -1 ; WX 722 ; N Agrave ; B 20 0 702 936 ;
-C -1 ; WX 722 ; N Abreve ; B 20 0 729 936 ;
-C -1 ; WX 584 ; N multiply ; B 57 1 635 505 ;
-C -1 ; WX 611 ; N uacute ; B 98 -14 658 750 ;
-C -1 ; WX 611 ; N Tcaron ; B 140 0 751 936 ;
-C -1 ; WX 494 ; N partialdiff ; B 43 -21 585 750 ;
-C -1 ; WX 556 ; N ydieresis ; B 42 -214 652 729 ;
-C -1 ; WX 722 ; N Nacute ; B 69 0 807 936 ;
-C -1 ; WX 278 ; N icircumflex ; B 69 0 444 750 ;
-C -1 ; WX 667 ; N Ecircumflex ; B 76 0 757 936 ;
-C -1 ; WX 556 ; N adieresis ; B 55 -14 594 729 ;
-C -1 ; WX 556 ; N edieresis ; B 70 -14 594 729 ;
-C -1 ; WX 556 ; N cacute ; B 79 -14 627 750 ;
-C -1 ; WX 611 ; N nacute ; B 65 0 654 750 ;
-C -1 ; WX 611 ; N umacron ; B 98 -14 658 678 ;
-C -1 ; WX 722 ; N Ncaron ; B 69 0 807 936 ;
-C -1 ; WX 278 ; N Iacute ; B 64 0 528 936 ;
-C -1 ; WX 584 ; N plusminus ; B 40 0 625 506 ;
-C -1 ; WX 280 ; N brokenbar ; B 52 -150 345 700 ;
-C -1 ; WX 737 ; N registered ; B 55 -19 834 737 ;
-C -1 ; WX 778 ; N Gbreve ; B 108 -19 817 936 ;
-C -1 ; WX 278 ; N Idotaccent ; B 64 0 397 915 ;
-C -1 ; WX 600 ; N summation ; B 14 -10 670 706 ;
-C -1 ; WX 667 ; N Egrave ; B 76 0 757 936 ;
-C -1 ; WX 389 ; N racute ; B 64 0 543 750 ;
-C -1 ; WX 611 ; N omacron ; B 82 -14 643 678 ;
-C -1 ; WX 611 ; N Zacute ; B 25 0 737 936 ;
-C -1 ; WX 611 ; N Zcaron ; B 25 0 737 936 ;
-C -1 ; WX 549 ; N greaterequal ; B 26 0 629 704 ;
-C -1 ; WX 722 ; N Eth ; B 62 0 777 718 ;
-C -1 ; WX 722 ; N Ccedilla ; B 107 -228 789 737 ;
-C -1 ; WX 278 ; N lcommaaccent ; B 30 -228 362 718 ;
-C -1 ; WX 389 ; N tcaron ; B 100 -6 608 878 ;
-C -1 ; WX 556 ; N eogonek ; B 70 -228 593 546 ;
-C -1 ; WX 722 ; N Uogonek ; B 116 -228 804 718 ;
-C -1 ; WX 722 ; N Aacute ; B 20 0 750 936 ;
-C -1 ; WX 722 ; N Adieresis ; B 20 0 716 915 ;
-C -1 ; WX 556 ; N egrave ; B 70 -14 593 750 ;
-C -1 ; WX 500 ; N zacute ; B 20 0 599 750 ;
-C -1 ; WX 278 ; N iogonek ; B -14 -224 363 725 ;
-C -1 ; WX 778 ; N Oacute ; B 107 -19 823 936 ;
-C -1 ; WX 611 ; N oacute ; B 82 -14 654 750 ;
-C -1 ; WX 556 ; N amacron ; B 55 -14 595 678 ;
-C -1 ; WX 556 ; N sacute ; B 63 -14 627 750 ;
-C -1 ; WX 278 ; N idieresis ; B 69 0 455 729 ;
-C -1 ; WX 778 ; N Ocircumflex ; B 107 -19 823 936 ;
-C -1 ; WX 722 ; N Ugrave ; B 116 -19 804 936 ;
-C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
-C -1 ; WX 611 ; N thorn ; B 18 -208 645 718 ;
-C -1 ; WX 333 ; N twosuperior ; B 69 283 449 710 ;
-C -1 ; WX 778 ; N Odieresis ; B 107 -19 823 915 ;
-C -1 ; WX 611 ; N mu ; B 22 -207 658 532 ;
-C -1 ; WX 278 ; N igrave ; B 69 0 326 750 ;
-C -1 ; WX 611 ; N ohungarumlaut ; B 82 -14 784 750 ;
-C -1 ; WX 667 ; N Eogonek ; B 76 -224 757 718 ;
-C -1 ; WX 611 ; N dcroat ; B 82 -14 789 718 ;
-C -1 ; WX 834 ; N threequarters ; B 99 -19 839 710 ;
-C -1 ; WX 667 ; N Scedilla ; B 81 -228 718 737 ;
-C -1 ; WX 400 ; N lcaron ; B 69 0 561 718 ;
-C -1 ; WX 722 ; N Kcommaaccent ; B 87 -228 858 718 ;
-C -1 ; WX 611 ; N Lacute ; B 76 0 611 936 ;
-C -1 ; WX 1000 ; N trademark ; B 179 306 1109 718 ;
-C -1 ; WX 556 ; N edotaccent ; B 70 -14 593 729 ;
-C -1 ; WX 278 ; N Igrave ; B 64 0 367 936 ;
-C -1 ; WX 278 ; N Imacron ; B 64 0 496 864 ;
-C -1 ; WX 611 ; N Lcaron ; B 76 0 643 718 ;
-C -1 ; WX 834 ; N onehalf ; B 132 -19 858 710 ;
-C -1 ; WX 549 ; N lessequal ; B 29 0 676 704 ;
-C -1 ; WX 611 ; N ocircumflex ; B 82 -14 643 750 ;
-C -1 ; WX 611 ; N ntilde ; B 65 0 646 737 ;
-C -1 ; WX 722 ; N Uhungarumlaut ; B 116 -19 880 936 ;
-C -1 ; WX 667 ; N Eacute ; B 76 0 757 936 ;
-C -1 ; WX 556 ; N emacron ; B 70 -14 595 678 ;
-C -1 ; WX 611 ; N gbreve ; B 38 -217 666 750 ;
-C -1 ; WX 834 ; N onequarter ; B 132 -19 806 710 ;
-C -1 ; WX 667 ; N Scaron ; B 81 -19 718 936 ;
-C -1 ; WX 667 ; N Scommaaccent ; B 81 -228 718 737 ;
-C -1 ; WX 778 ; N Ohungarumlaut ; B 107 -19 908 936 ;
-C -1 ; WX 400 ; N degree ; B 175 426 467 712 ;
-C -1 ; WX 611 ; N ograve ; B 82 -14 643 750 ;
-C -1 ; WX 722 ; N Ccaron ; B 107 -19 789 936 ;
-C -1 ; WX 611 ; N ugrave ; B 98 -14 658 750 ;
-C -1 ; WX 549 ; N radical ; B 112 -46 689 850 ;
-C -1 ; WX 722 ; N Dcaron ; B 76 0 777 936 ;
-C -1 ; WX 389 ; N rcommaaccent ; B 26 -228 489 546 ;
-C -1 ; WX 722 ; N Ntilde ; B 69 0 807 923 ;
-C -1 ; WX 611 ; N otilde ; B 82 -14 646 737 ;
-C -1 ; WX 722 ; N Rcommaaccent ; B 76 -228 778 718 ;
-C -1 ; WX 611 ; N Lcommaaccent ; B 76 -228 611 718 ;
-C -1 ; WX 722 ; N Atilde ; B 20 0 741 923 ;
-C -1 ; WX 722 ; N Aogonek ; B 20 -224 702 718 ;
-C -1 ; WX 722 ; N Aring ; B 20 0 702 962 ;
-C -1 ; WX 778 ; N Otilde ; B 107 -19 823 923 ;
-C -1 ; WX 500 ; N zdotaccent ; B 20 0 583 729 ;
-C -1 ; WX 667 ; N Ecaron ; B 76 0 757 936 ;
-C -1 ; WX 278 ; N Iogonek ; B -41 -228 367 718 ;
-C -1 ; WX 556 ; N kcommaaccent ; B 69 -228 670 718 ;
-C -1 ; WX 584 ; N minus ; B 82 197 610 309 ;
-C -1 ; WX 278 ; N Icircumflex ; B 64 0 484 936 ;
-C -1 ; WX 611 ; N ncaron ; B 65 0 641 750 ;
-C -1 ; WX 333 ; N tcommaaccent ; B 58 -228 422 676 ;
-C -1 ; WX 584 ; N logicalnot ; B 105 108 633 419 ;
-C -1 ; WX 611 ; N odieresis ; B 82 -14 643 729 ;
-C -1 ; WX 611 ; N udieresis ; B 98 -14 658 729 ;
-C -1 ; WX 549 ; N notequal ; B 32 -49 630 570 ;
-C -1 ; WX 611 ; N gcommaaccent ; B 38 -217 666 850 ;
-C -1 ; WX 611 ; N eth ; B 82 -14 670 737 ;
-C -1 ; WX 500 ; N zcaron ; B 20 0 586 750 ;
-C -1 ; WX 611 ; N ncommaaccent ; B 65 -228 629 546 ;
-C -1 ; WX 333 ; N onesuperior ; B 148 283 388 710 ;
-C -1 ; WX 278 ; N imacron ; B 69 0 429 678 ;
-C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ;
-EndCharMetrics
-StartKernData
-StartKernPairs 2481
-KPX A C -40
-KPX A Cacute -40
-KPX A Ccaron -40
-KPX A Ccedilla -40
-KPX A G -50
-KPX A Gbreve -50
-KPX A Gcommaaccent -50
-KPX A O -40
-KPX A Oacute -40
-KPX A Ocircumflex -40
-KPX A Odieresis -40
-KPX A Ograve -40
-KPX A Ohungarumlaut -40
-KPX A Omacron -40
-KPX A Oslash -40
-KPX A Otilde -40
-KPX A Q -40
-KPX A T -90
-KPX A Tcaron -90
-KPX A Tcommaaccent -90
-KPX A U -50
-KPX A Uacute -50
-KPX A Ucircumflex -50
-KPX A Udieresis -50
-KPX A Ugrave -50
-KPX A Uhungarumlaut -50
-KPX A Umacron -50
-KPX A Uogonek -50
-KPX A Uring -50
-KPX A V -80
-KPX A W -60
-KPX A Y -110
-KPX A Yacute -110
-KPX A Ydieresis -110
-KPX A u -30
-KPX A uacute -30
-KPX A ucircumflex -30
-KPX A udieresis -30
-KPX A ugrave -30
-KPX A uhungarumlaut -30
-KPX A umacron -30
-KPX A uogonek -30
-KPX A uring -30
-KPX A v -40
-KPX A w -30
-KPX A y -30
-KPX A yacute -30
-KPX A ydieresis -30
-KPX Aacute C -40
-KPX Aacute Cacute -40
-KPX Aacute Ccaron -40
-KPX Aacute Ccedilla -40
-KPX Aacute G -50
-KPX Aacute Gbreve -50
-KPX Aacute Gcommaaccent -50
-KPX Aacute O -40
-KPX Aacute Oacute -40
-KPX Aacute Ocircumflex -40
-KPX Aacute Odieresis -40
-KPX Aacute Ograve -40
-KPX Aacute Ohungarumlaut -40
-KPX Aacute Omacron -40
-KPX Aacute Oslash -40
-KPX Aacute Otilde -40
-KPX Aacute Q -40
-KPX Aacute T -90
-KPX Aacute Tcaron -90
-KPX Aacute Tcommaaccent -90
-KPX Aacute U -50
-KPX Aacute Uacute -50
-KPX Aacute Ucircumflex -50
-KPX Aacute Udieresis -50
-KPX Aacute Ugrave -50
-KPX Aacute Uhungarumlaut -50
-KPX Aacute Umacron -50
-KPX Aacute Uogonek -50
-KPX Aacute Uring -50
-KPX Aacute V -80
-KPX Aacute W -60
-KPX Aacute Y -110
-KPX Aacute Yacute -110
-KPX Aacute Ydieresis -110
-KPX Aacute u -30
-KPX Aacute uacute -30
-KPX Aacute ucircumflex -30
-KPX Aacute udieresis -30
-KPX Aacute ugrave -30
-KPX Aacute uhungarumlaut -30
-KPX Aacute umacron -30
-KPX Aacute uogonek -30
-KPX Aacute uring -30
-KPX Aacute v -40
-KPX Aacute w -30
-KPX Aacute y -30
-KPX Aacute yacute -30
-KPX Aacute ydieresis -30
-KPX Abreve C -40
-KPX Abreve Cacute -40
-KPX Abreve Ccaron -40
-KPX Abreve Ccedilla -40
-KPX Abreve G -50
-KPX Abreve Gbreve -50
-KPX Abreve Gcommaaccent -50
-KPX Abreve O -40
-KPX Abreve Oacute -40
-KPX Abreve Ocircumflex -40
-KPX Abreve Odieresis -40
-KPX Abreve Ograve -40
-KPX Abreve Ohungarumlaut -40
-KPX Abreve Omacron -40
-KPX Abreve Oslash -40
-KPX Abreve Otilde -40
-KPX Abreve Q -40
-KPX Abreve T -90
-KPX Abreve Tcaron -90
-KPX Abreve Tcommaaccent -90
-KPX Abreve U -50
-KPX Abreve Uacute -50
-KPX Abreve Ucircumflex -50
-KPX Abreve Udieresis -50
-KPX Abreve Ugrave -50
-KPX Abreve Uhungarumlaut -50
-KPX Abreve Umacron -50
-KPX Abreve Uogonek -50
-KPX Abreve Uring -50
-KPX Abreve V -80
-KPX Abreve W -60
-KPX Abreve Y -110
-KPX Abreve Yacute -110
-KPX Abreve Ydieresis -110
-KPX Abreve u -30
-KPX Abreve uacute -30
-KPX Abreve ucircumflex -30
-KPX Abreve udieresis -30
-KPX Abreve ugrave -30
-KPX Abreve uhungarumlaut -30
-KPX Abreve umacron -30
-KPX Abreve uogonek -30
-KPX Abreve uring -30
-KPX Abreve v -40
-KPX Abreve w -30
-KPX Abreve y -30
-KPX Abreve yacute -30
-KPX Abreve ydieresis -30
-KPX Acircumflex C -40
-KPX Acircumflex Cacute -40
-KPX Acircumflex Ccaron -40
-KPX Acircumflex Ccedilla -40
-KPX Acircumflex G -50
-KPX Acircumflex Gbreve -50
-KPX Acircumflex Gcommaaccent -50
-KPX Acircumflex O -40
-KPX Acircumflex Oacute -40
-KPX Acircumflex Ocircumflex -40
-KPX Acircumflex Odieresis -40
-KPX Acircumflex Ograve -40
-KPX Acircumflex Ohungarumlaut -40
-KPX Acircumflex Omacron -40
-KPX Acircumflex Oslash -40
-KPX Acircumflex Otilde -40
-KPX Acircumflex Q -40
-KPX Acircumflex T -90
-KPX Acircumflex Tcaron -90
-KPX Acircumflex Tcommaaccent -90
-KPX Acircumflex U -50
-KPX Acircumflex Uacute -50
-KPX Acircumflex Ucircumflex -50
-KPX Acircumflex Udieresis -50
-KPX Acircumflex Ugrave -50
-KPX Acircumflex Uhungarumlaut -50
-KPX Acircumflex Umacron -50
-KPX Acircumflex Uogonek -50
-KPX Acircumflex Uring -50
-KPX Acircumflex V -80
-KPX Acircumflex W -60
-KPX Acircumflex Y -110
-KPX Acircumflex Yacute -110
-KPX Acircumflex Ydieresis -110
-KPX Acircumflex u -30
-KPX Acircumflex uacute -30
-KPX Acircumflex ucircumflex -30
-KPX Acircumflex udieresis -30
-KPX Acircumflex ugrave -30
-KPX Acircumflex uhungarumlaut -30
-KPX Acircumflex umacron -30
-KPX Acircumflex uogonek -30
-KPX Acircumflex uring -30
-KPX Acircumflex v -40
-KPX Acircumflex w -30
-KPX Acircumflex y -30
-KPX Acircumflex yacute -30
-KPX Acircumflex ydieresis -30
-KPX Adieresis C -40
-KPX Adieresis Cacute -40
-KPX Adieresis Ccaron -40
-KPX Adieresis Ccedilla -40
-KPX Adieresis G -50
-KPX Adieresis Gbreve -50
-KPX Adieresis Gcommaaccent -50
-KPX Adieresis O -40
-KPX Adieresis Oacute -40
-KPX Adieresis Ocircumflex -40
-KPX Adieresis Odieresis -40
-KPX Adieresis Ograve -40
-KPX Adieresis Ohungarumlaut -40
-KPX Adieresis Omacron -40
-KPX Adieresis Oslash -40
-KPX Adieresis Otilde -40
-KPX Adieresis Q -40
-KPX Adieresis T -90
-KPX Adieresis Tcaron -90
-KPX Adieresis Tcommaaccent -90
-KPX Adieresis U -50
-KPX Adieresis Uacute -50
-KPX Adieresis Ucircumflex -50
-KPX Adieresis Udieresis -50
-KPX Adieresis Ugrave -50
-KPX Adieresis Uhungarumlaut -50
-KPX Adieresis Umacron -50
-KPX Adieresis Uogonek -50
-KPX Adieresis Uring -50
-KPX Adieresis V -80
-KPX Adieresis W -60
-KPX Adieresis Y -110
-KPX Adieresis Yacute -110
-KPX Adieresis Ydieresis -110
-KPX Adieresis u -30
-KPX Adieresis uacute -30
-KPX Adieresis ucircumflex -30
-KPX Adieresis udieresis -30
-KPX Adieresis ugrave -30
-KPX Adieresis uhungarumlaut -30
-KPX Adieresis umacron -30
-KPX Adieresis uogonek -30
-KPX Adieresis uring -30
-KPX Adieresis v -40
-KPX Adieresis w -30
-KPX Adieresis y -30
-KPX Adieresis yacute -30
-KPX Adieresis ydieresis -30
-KPX Agrave C -40
-KPX Agrave Cacute -40
-KPX Agrave Ccaron -40
-KPX Agrave Ccedilla -40
-KPX Agrave G -50
-KPX Agrave Gbreve -50
-KPX Agrave Gcommaaccent -50
-KPX Agrave O -40
-KPX Agrave Oacute -40
-KPX Agrave Ocircumflex -40
-KPX Agrave Odieresis -40
-KPX Agrave Ograve -40
-KPX Agrave Ohungarumlaut -40
-KPX Agrave Omacron -40
-KPX Agrave Oslash -40
-KPX Agrave Otilde -40
-KPX Agrave Q -40
-KPX Agrave T -90
-KPX Agrave Tcaron -90
-KPX Agrave Tcommaaccent -90
-KPX Agrave U -50
-KPX Agrave Uacute -50
-KPX Agrave Ucircumflex -50
-KPX Agrave Udieresis -50
-KPX Agrave Ugrave -50
-KPX Agrave Uhungarumlaut -50
-KPX Agrave Umacron -50
-KPX Agrave Uogonek -50
-KPX Agrave Uring -50
-KPX Agrave V -80
-KPX Agrave W -60
-KPX Agrave Y -110
-KPX Agrave Yacute -110
-KPX Agrave Ydieresis -110
-KPX Agrave u -30
-KPX Agrave uacute -30
-KPX Agrave ucircumflex -30
-KPX Agrave udieresis -30
-KPX Agrave ugrave -30
-KPX Agrave uhungarumlaut -30
-KPX Agrave umacron -30
-KPX Agrave uogonek -30
-KPX Agrave uring -30
-KPX Agrave v -40
-KPX Agrave w -30
-KPX Agrave y -30
-KPX Agrave yacute -30
-KPX Agrave ydieresis -30
-KPX Amacron C -40
-KPX Amacron Cacute -40
-KPX Amacron Ccaron -40
-KPX Amacron Ccedilla -40
-KPX Amacron G -50
-KPX Amacron Gbreve -50
-KPX Amacron Gcommaaccent -50
-KPX Amacron O -40
-KPX Amacron Oacute -40
-KPX Amacron Ocircumflex -40
-KPX Amacron Odieresis -40
-KPX Amacron Ograve -40
-KPX Amacron Ohungarumlaut -40
-KPX Amacron Omacron -40
-KPX Amacron Oslash -40
-KPX Amacron Otilde -40
-KPX Amacron Q -40
-KPX Amacron T -90
-KPX Amacron Tcaron -90
-KPX Amacron Tcommaaccent -90
-KPX Amacron U -50
-KPX Amacron Uacute -50
-KPX Amacron Ucircumflex -50
-KPX Amacron Udieresis -50
-KPX Amacron Ugrave -50
-KPX Amacron Uhungarumlaut -50
-KPX Amacron Umacron -50
-KPX Amacron Uogonek -50
-KPX Amacron Uring -50
-KPX Amacron V -80
-KPX Amacron W -60
-KPX Amacron Y -110
-KPX Amacron Yacute -110
-KPX Amacron Ydieresis -110
-KPX Amacron u -30
-KPX Amacron uacute -30
-KPX Amacron ucircumflex -30
-KPX Amacron udieresis -30
-KPX Amacron ugrave -30
-KPX Amacron uhungarumlaut -30
-KPX Amacron umacron -30
-KPX Amacron uogonek -30
-KPX Amacron uring -30
-KPX Amacron v -40
-KPX Amacron w -30
-KPX Amacron y -30
-KPX Amacron yacute -30
-KPX Amacron ydieresis -30
-KPX Aogonek C -40
-KPX Aogonek Cacute -40
-KPX Aogonek Ccaron -40
-KPX Aogonek Ccedilla -40
-KPX Aogonek G -50
-KPX Aogonek Gbreve -50
-KPX Aogonek Gcommaaccent -50
-KPX Aogonek O -40
-KPX Aogonek Oacute -40
-KPX Aogonek Ocircumflex -40
-KPX Aogonek Odieresis -40
-KPX Aogonek Ograve -40
-KPX Aogonek Ohungarumlaut -40
-KPX Aogonek Omacron -40
-KPX Aogonek Oslash -40
-KPX Aogonek Otilde -40
-KPX Aogonek Q -40
-KPX Aogonek T -90
-KPX Aogonek Tcaron -90
-KPX Aogonek Tcommaaccent -90
-KPX Aogonek U -50
-KPX Aogonek Uacute -50
-KPX Aogonek Ucircumflex -50
-KPX Aogonek Udieresis -50
-KPX Aogonek Ugrave -50
-KPX Aogonek Uhungarumlaut -50
-KPX Aogonek Umacron -50
-KPX Aogonek Uogonek -50
-KPX Aogonek Uring -50
-KPX Aogonek V -80
-KPX Aogonek W -60
-KPX Aogonek Y -110
-KPX Aogonek Yacute -110
-KPX Aogonek Ydieresis -110
-KPX Aogonek u -30
-KPX Aogonek uacute -30
-KPX Aogonek ucircumflex -30
-KPX Aogonek udieresis -30
-KPX Aogonek ugrave -30
-KPX Aogonek uhungarumlaut -30
-KPX Aogonek umacron -30
-KPX Aogonek uogonek -30
-KPX Aogonek uring -30
-KPX Aogonek v -40
-KPX Aogonek w -30
-KPX Aogonek y -30
-KPX Aogonek yacute -30
-KPX Aogonek ydieresis -30
-KPX Aring C -40
-KPX Aring Cacute -40
-KPX Aring Ccaron -40
-KPX Aring Ccedilla -40
-KPX Aring G -50
-KPX Aring Gbreve -50
-KPX Aring Gcommaaccent -50
-KPX Aring O -40
-KPX Aring Oacute -40
-KPX Aring Ocircumflex -40
-KPX Aring Odieresis -40
-KPX Aring Ograve -40
-KPX Aring Ohungarumlaut -40
-KPX Aring Omacron -40
-KPX Aring Oslash -40
-KPX Aring Otilde -40
-KPX Aring Q -40
-KPX Aring T -90
-KPX Aring Tcaron -90
-KPX Aring Tcommaaccent -90
-KPX Aring U -50
-KPX Aring Uacute -50
-KPX Aring Ucircumflex -50
-KPX Aring Udieresis -50
-KPX Aring Ugrave -50
-KPX Aring Uhungarumlaut -50
-KPX Aring Umacron -50
-KPX Aring Uogonek -50
-KPX Aring Uring -50
-KPX Aring V -80
-KPX Aring W -60
-KPX Aring Y -110
-KPX Aring Yacute -110
-KPX Aring Ydieresis -110
-KPX Aring u -30
-KPX Aring uacute -30
-KPX Aring ucircumflex -30
-KPX Aring udieresis -30
-KPX Aring ugrave -30
-KPX Aring uhungarumlaut -30
-KPX Aring umacron -30
-KPX Aring uogonek -30
-KPX Aring uring -30
-KPX Aring v -40
-KPX Aring w -30
-KPX Aring y -30
-KPX Aring yacute -30
-KPX Aring ydieresis -30
-KPX Atilde C -40
-KPX Atilde Cacute -40
-KPX Atilde Ccaron -40
-KPX Atilde Ccedilla -40
-KPX Atilde G -50
-KPX Atilde Gbreve -50
-KPX Atilde Gcommaaccent -50
-KPX Atilde O -40
-KPX Atilde Oacute -40
-KPX Atilde Ocircumflex -40
-KPX Atilde Odieresis -40
-KPX Atilde Ograve -40
-KPX Atilde Ohungarumlaut -40
-KPX Atilde Omacron -40
-KPX Atilde Oslash -40
-KPX Atilde Otilde -40
-KPX Atilde Q -40
-KPX Atilde T -90
-KPX Atilde Tcaron -90
-KPX Atilde Tcommaaccent -90
-KPX Atilde U -50
-KPX Atilde Uacute -50
-KPX Atilde Ucircumflex -50
-KPX Atilde Udieresis -50
-KPX Atilde Ugrave -50
-KPX Atilde Uhungarumlaut -50
-KPX Atilde Umacron -50
-KPX Atilde Uogonek -50
-KPX Atilde Uring -50
-KPX Atilde V -80
-KPX Atilde W -60
-KPX Atilde Y -110
-KPX Atilde Yacute -110
-KPX Atilde Ydieresis -110
-KPX Atilde u -30
-KPX Atilde uacute -30
-KPX Atilde ucircumflex -30
-KPX Atilde udieresis -30
-KPX Atilde ugrave -30
-KPX Atilde uhungarumlaut -30
-KPX Atilde umacron -30
-KPX Atilde uogonek -30
-KPX Atilde uring -30
-KPX Atilde v -40
-KPX Atilde w -30
-KPX Atilde y -30
-KPX Atilde yacute -30
-KPX Atilde ydieresis -30
-KPX B A -30
-KPX B Aacute -30
-KPX B Abreve -30
-KPX B Acircumflex -30
-KPX B Adieresis -30
-KPX B Agrave -30
-KPX B Amacron -30
-KPX B Aogonek -30
-KPX B Aring -30
-KPX B Atilde -30
-KPX B U -10
-KPX B Uacute -10
-KPX B Ucircumflex -10
-KPX B Udieresis -10
-KPX B Ugrave -10
-KPX B Uhungarumlaut -10
-KPX B Umacron -10
-KPX B Uogonek -10
-KPX B Uring -10
-KPX D A -40
-KPX D Aacute -40
-KPX D Abreve -40
-KPX D Acircumflex -40
-KPX D Adieresis -40
-KPX D Agrave -40
-KPX D Amacron -40
-KPX D Aogonek -40
-KPX D Aring -40
-KPX D Atilde -40
-KPX D V -40
-KPX D W -40
-KPX D Y -70
-KPX D Yacute -70
-KPX D Ydieresis -70
-KPX D comma -30
-KPX D period -30
-KPX Dcaron A -40
-KPX Dcaron Aacute -40
-KPX Dcaron Abreve -40
-KPX Dcaron Acircumflex -40
-KPX Dcaron Adieresis -40
-KPX Dcaron Agrave -40
-KPX Dcaron Amacron -40
-KPX Dcaron Aogonek -40
-KPX Dcaron Aring -40
-KPX Dcaron Atilde -40
-KPX Dcaron V -40
-KPX Dcaron W -40
-KPX Dcaron Y -70
-KPX Dcaron Yacute -70
-KPX Dcaron Ydieresis -70
-KPX Dcaron comma -30
-KPX Dcaron period -30
-KPX Dcroat A -40
-KPX Dcroat Aacute -40
-KPX Dcroat Abreve -40
-KPX Dcroat Acircumflex -40
-KPX Dcroat Adieresis -40
-KPX Dcroat Agrave -40
-KPX Dcroat Amacron -40
-KPX Dcroat Aogonek -40
-KPX Dcroat Aring -40
-KPX Dcroat Atilde -40
-KPX Dcroat V -40
-KPX Dcroat W -40
-KPX Dcroat Y -70
-KPX Dcroat Yacute -70
-KPX Dcroat Ydieresis -70
-KPX Dcroat comma -30
-KPX Dcroat period -30
-KPX F A -80
-KPX F Aacute -80
-KPX F Abreve -80
-KPX F Acircumflex -80
-KPX F Adieresis -80
-KPX F Agrave -80
-KPX F Amacron -80
-KPX F Aogonek -80
-KPX F Aring -80
-KPX F Atilde -80
-KPX F a -20
-KPX F aacute -20
-KPX F abreve -20
-KPX F acircumflex -20
-KPX F adieresis -20
-KPX F agrave -20
-KPX F amacron -20
-KPX F aogonek -20
-KPX F aring -20
-KPX F atilde -20
-KPX F comma -100
-KPX F period -100
-KPX J A -20
-KPX J Aacute -20
-KPX J Abreve -20
-KPX J Acircumflex -20
-KPX J Adieresis -20
-KPX J Agrave -20
-KPX J Amacron -20
-KPX J Aogonek -20
-KPX J Aring -20
-KPX J Atilde -20
-KPX J comma -20
-KPX J period -20
-KPX J u -20
-KPX J uacute -20
-KPX J ucircumflex -20
-KPX J udieresis -20
-KPX J ugrave -20
-KPX J uhungarumlaut -20
-KPX J umacron -20
-KPX J uogonek -20
-KPX J uring -20
-KPX K O -30
-KPX K Oacute -30
-KPX K Ocircumflex -30
-KPX K Odieresis -30
-KPX K Ograve -30
-KPX K Ohungarumlaut -30
-KPX K Omacron -30
-KPX K Oslash -30
-KPX K Otilde -30
-KPX K e -15
-KPX K eacute -15
-KPX K ecaron -15
-KPX K ecircumflex -15
-KPX K edieresis -15
-KPX K edotaccent -15
-KPX K egrave -15
-KPX K emacron -15
-KPX K eogonek -15
-KPX K o -35
-KPX K oacute -35
-KPX K ocircumflex -35
-KPX K odieresis -35
-KPX K ograve -35
-KPX K ohungarumlaut -35
-KPX K omacron -35
-KPX K oslash -35
-KPX K otilde -35
-KPX K u -30
-KPX K uacute -30
-KPX K ucircumflex -30
-KPX K udieresis -30
-KPX K ugrave -30
-KPX K uhungarumlaut -30
-KPX K umacron -30
-KPX K uogonek -30
-KPX K uring -30
-KPX K y -40
-KPX K yacute -40
-KPX K ydieresis -40
-KPX Kcommaaccent O -30
-KPX Kcommaaccent Oacute -30
-KPX Kcommaaccent Ocircumflex -30
-KPX Kcommaaccent Odieresis -30
-KPX Kcommaaccent Ograve -30
-KPX Kcommaaccent Ohungarumlaut -30
-KPX Kcommaaccent Omacron -30
-KPX Kcommaaccent Oslash -30
-KPX Kcommaaccent Otilde -30
-KPX Kcommaaccent e -15
-KPX Kcommaaccent eacute -15
-KPX Kcommaaccent ecaron -15
-KPX Kcommaaccent ecircumflex -15
-KPX Kcommaaccent edieresis -15
-KPX Kcommaaccent edotaccent -15
-KPX Kcommaaccent egrave -15
-KPX Kcommaaccent emacron -15
-KPX Kcommaaccent eogonek -15
-KPX Kcommaaccent o -35
-KPX Kcommaaccent oacute -35
-KPX Kcommaaccent ocircumflex -35
-KPX Kcommaaccent odieresis -35
-KPX Kcommaaccent ograve -35
-KPX Kcommaaccent ohungarumlaut -35
-KPX Kcommaaccent omacron -35
-KPX Kcommaaccent oslash -35
-KPX Kcommaaccent otilde -35
-KPX Kcommaaccent u -30
-KPX Kcommaaccent uacute -30
-KPX Kcommaaccent ucircumflex -30
-KPX Kcommaaccent udieresis -30
-KPX Kcommaaccent ugrave -30
-KPX Kcommaaccent uhungarumlaut -30
-KPX Kcommaaccent umacron -30
-KPX Kcommaaccent uogonek -30
-KPX Kcommaaccent uring -30
-KPX Kcommaaccent y -40
-KPX Kcommaaccent yacute -40
-KPX Kcommaaccent ydieresis -40
-KPX L T -90
-KPX L Tcaron -90
-KPX L Tcommaaccent -90
-KPX L V -110
-KPX L W -80
-KPX L Y -120
-KPX L Yacute -120
-KPX L Ydieresis -120
-KPX L quotedblright -140
-KPX L quoteright -140
-KPX L y -30
-KPX L yacute -30
-KPX L ydieresis -30
-KPX Lacute T -90
-KPX Lacute Tcaron -90
-KPX Lacute Tcommaaccent -90
-KPX Lacute V -110
-KPX Lacute W -80
-KPX Lacute Y -120
-KPX Lacute Yacute -120
-KPX Lacute Ydieresis -120
-KPX Lacute quotedblright -140
-KPX Lacute quoteright -140
-KPX Lacute y -30
-KPX Lacute yacute -30
-KPX Lacute ydieresis -30
-KPX Lcommaaccent T -90
-KPX Lcommaaccent Tcaron -90
-KPX Lcommaaccent Tcommaaccent -90
-KPX Lcommaaccent V -110
-KPX Lcommaaccent W -80
-KPX Lcommaaccent Y -120
-KPX Lcommaaccent Yacute -120
-KPX Lcommaaccent Ydieresis -120
-KPX Lcommaaccent quotedblright -140
-KPX Lcommaaccent quoteright -140
-KPX Lcommaaccent y -30
-KPX Lcommaaccent yacute -30
-KPX Lcommaaccent ydieresis -30
-KPX Lslash T -90
-KPX Lslash Tcaron -90
-KPX Lslash Tcommaaccent -90
-KPX Lslash V -110
-KPX Lslash W -80
-KPX Lslash Y -120
-KPX Lslash Yacute -120
-KPX Lslash Ydieresis -120
-KPX Lslash quotedblright -140
-KPX Lslash quoteright -140
-KPX Lslash y -30
-KPX Lslash yacute -30
-KPX Lslash ydieresis -30
-KPX O A -50
-KPX O Aacute -50
-KPX O Abreve -50
-KPX O Acircumflex -50
-KPX O Adieresis -50
-KPX O Agrave -50
-KPX O Amacron -50
-KPX O Aogonek -50
-KPX O Aring -50
-KPX O Atilde -50
-KPX O T -40
-KPX O Tcaron -40
-KPX O Tcommaaccent -40
-KPX O V -50
-KPX O W -50
-KPX O X -50
-KPX O Y -70
-KPX O Yacute -70
-KPX O Ydieresis -70
-KPX O comma -40
-KPX O period -40
-KPX Oacute A -50
-KPX Oacute Aacute -50
-KPX Oacute Abreve -50
-KPX Oacute Acircumflex -50
-KPX Oacute Adieresis -50
-KPX Oacute Agrave -50
-KPX Oacute Amacron -50
-KPX Oacute Aogonek -50
-KPX Oacute Aring -50
-KPX Oacute Atilde -50
-KPX Oacute T -40
-KPX Oacute Tcaron -40
-KPX Oacute Tcommaaccent -40
-KPX Oacute V -50
-KPX Oacute W -50
-KPX Oacute X -50
-KPX Oacute Y -70
-KPX Oacute Yacute -70
-KPX Oacute Ydieresis -70
-KPX Oacute comma -40
-KPX Oacute period -40
-KPX Ocircumflex A -50
-KPX Ocircumflex Aacute -50
-KPX Ocircumflex Abreve -50
-KPX Ocircumflex Acircumflex -50
-KPX Ocircumflex Adieresis -50
-KPX Ocircumflex Agrave -50
-KPX Ocircumflex Amacron -50
-KPX Ocircumflex Aogonek -50
-KPX Ocircumflex Aring -50
-KPX Ocircumflex Atilde -50
-KPX Ocircumflex T -40
-KPX Ocircumflex Tcaron -40
-KPX Ocircumflex Tcommaaccent -40
-KPX Ocircumflex V -50
-KPX Ocircumflex W -50
-KPX Ocircumflex X -50
-KPX Ocircumflex Y -70
-KPX Ocircumflex Yacute -70
-KPX Ocircumflex Ydieresis -70
-KPX Ocircumflex comma -40
-KPX Ocircumflex period -40
-KPX Odieresis A -50
-KPX Odieresis Aacute -50
-KPX Odieresis Abreve -50
-KPX Odieresis Acircumflex -50
-KPX Odieresis Adieresis -50
-KPX Odieresis Agrave -50
-KPX Odieresis Amacron -50
-KPX Odieresis Aogonek -50
-KPX Odieresis Aring -50
-KPX Odieresis Atilde -50
-KPX Odieresis T -40
-KPX Odieresis Tcaron -40
-KPX Odieresis Tcommaaccent -40
-KPX Odieresis V -50
-KPX Odieresis W -50
-KPX Odieresis X -50
-KPX Odieresis Y -70
-KPX Odieresis Yacute -70
-KPX Odieresis Ydieresis -70
-KPX Odieresis comma -40
-KPX Odieresis period -40
-KPX Ograve A -50
-KPX Ograve Aacute -50
-KPX Ograve Abreve -50
-KPX Ograve Acircumflex -50
-KPX Ograve Adieresis -50
-KPX Ograve Agrave -50
-KPX Ograve Amacron -50
-KPX Ograve Aogonek -50
-KPX Ograve Aring -50
-KPX Ograve Atilde -50
-KPX Ograve T -40
-KPX Ograve Tcaron -40
-KPX Ograve Tcommaaccent -40
-KPX Ograve V -50
-KPX Ograve W -50
-KPX Ograve X -50
-KPX Ograve Y -70
-KPX Ograve Yacute -70
-KPX Ograve Ydieresis -70
-KPX Ograve comma -40
-KPX Ograve period -40
-KPX Ohungarumlaut A -50
-KPX Ohungarumlaut Aacute -50
-KPX Ohungarumlaut Abreve -50
-KPX Ohungarumlaut Acircumflex -50
-KPX Ohungarumlaut Adieresis -50
-KPX Ohungarumlaut Agrave -50
-KPX Ohungarumlaut Amacron -50
-KPX Ohungarumlaut Aogonek -50
-KPX Ohungarumlaut Aring -50
-KPX Ohungarumlaut Atilde -50
-KPX Ohungarumlaut T -40
-KPX Ohungarumlaut Tcaron -40
-KPX Ohungarumlaut Tcommaaccent -40
-KPX Ohungarumlaut V -50
-KPX Ohungarumlaut W -50
-KPX Ohungarumlaut X -50
-KPX Ohungarumlaut Y -70
-KPX Ohungarumlaut Yacute -70
-KPX Ohungarumlaut Ydieresis -70
-KPX Ohungarumlaut comma -40
-KPX Ohungarumlaut period -40
-KPX Omacron A -50
-KPX Omacron Aacute -50
-KPX Omacron Abreve -50
-KPX Omacron Acircumflex -50
-KPX Omacron Adieresis -50
-KPX Omacron Agrave -50
-KPX Omacron Amacron -50
-KPX Omacron Aogonek -50
-KPX Omacron Aring -50
-KPX Omacron Atilde -50
-KPX Omacron T -40
-KPX Omacron Tcaron -40
-KPX Omacron Tcommaaccent -40
-KPX Omacron V -50
-KPX Omacron W -50
-KPX Omacron X -50
-KPX Omacron Y -70
-KPX Omacron Yacute -70
-KPX Omacron Ydieresis -70
-KPX Omacron comma -40
-KPX Omacron period -40
-KPX Oslash A -50
-KPX Oslash Aacute -50
-KPX Oslash Abreve -50
-KPX Oslash Acircumflex -50
-KPX Oslash Adieresis -50
-KPX Oslash Agrave -50
-KPX Oslash Amacron -50
-KPX Oslash Aogonek -50
-KPX Oslash Aring -50
-KPX Oslash Atilde -50
-KPX Oslash T -40
-KPX Oslash Tcaron -40
-KPX Oslash Tcommaaccent -40
-KPX Oslash V -50
-KPX Oslash W -50
-KPX Oslash X -50
-KPX Oslash Y -70
-KPX Oslash Yacute -70
-KPX Oslash Ydieresis -70
-KPX Oslash comma -40
-KPX Oslash period -40
-KPX Otilde A -50
-KPX Otilde Aacute -50
-KPX Otilde Abreve -50
-KPX Otilde Acircumflex -50
-KPX Otilde Adieresis -50
-KPX Otilde Agrave -50
-KPX Otilde Amacron -50
-KPX Otilde Aogonek -50
-KPX Otilde Aring -50
-KPX Otilde Atilde -50
-KPX Otilde T -40
-KPX Otilde Tcaron -40
-KPX Otilde Tcommaaccent -40
-KPX Otilde V -50
-KPX Otilde W -50
-KPX Otilde X -50
-KPX Otilde Y -70
-KPX Otilde Yacute -70
-KPX Otilde Ydieresis -70
-KPX Otilde comma -40
-KPX Otilde period -40
-KPX P A -100
-KPX P Aacute -100
-KPX P Abreve -100
-KPX P Acircumflex -100
-KPX P Adieresis -100
-KPX P Agrave -100
-KPX P Amacron -100
-KPX P Aogonek -100
-KPX P Aring -100
-KPX P Atilde -100
-KPX P a -30
-KPX P aacute -30
-KPX P abreve -30
-KPX P acircumflex -30
-KPX P adieresis -30
-KPX P agrave -30
-KPX P amacron -30
-KPX P aogonek -30
-KPX P aring -30
-KPX P atilde -30
-KPX P comma -120
-KPX P e -30
-KPX P eacute -30
-KPX P ecaron -30
-KPX P ecircumflex -30
-KPX P edieresis -30
-KPX P edotaccent -30
-KPX P egrave -30
-KPX P emacron -30
-KPX P eogonek -30
-KPX P o -40
-KPX P oacute -40
-KPX P ocircumflex -40
-KPX P odieresis -40
-KPX P ograve -40
-KPX P ohungarumlaut -40
-KPX P omacron -40
-KPX P oslash -40
-KPX P otilde -40
-KPX P period -120
-KPX Q U -10
-KPX Q Uacute -10
-KPX Q Ucircumflex -10
-KPX Q Udieresis -10
-KPX Q Ugrave -10
-KPX Q Uhungarumlaut -10
-KPX Q Umacron -10
-KPX Q Uogonek -10
-KPX Q Uring -10
-KPX Q comma 20
-KPX Q period 20
-KPX R O -20
-KPX R Oacute -20
-KPX R Ocircumflex -20
-KPX R Odieresis -20
-KPX R Ograve -20
-KPX R Ohungarumlaut -20
-KPX R Omacron -20
-KPX R Oslash -20
-KPX R Otilde -20
-KPX R T -20
-KPX R Tcaron -20
-KPX R Tcommaaccent -20
-KPX R U -20
-KPX R Uacute -20
-KPX R Ucircumflex -20
-KPX R Udieresis -20
-KPX R Ugrave -20
-KPX R Uhungarumlaut -20
-KPX R Umacron -20
-KPX R Uogonek -20
-KPX R Uring -20
-KPX R V -50
-KPX R W -40
-KPX R Y -50
-KPX R Yacute -50
-KPX R Ydieresis -50
-KPX Racute O -20
-KPX Racute Oacute -20
-KPX Racute Ocircumflex -20
-KPX Racute Odieresis -20
-KPX Racute Ograve -20
-KPX Racute Ohungarumlaut -20
-KPX Racute Omacron -20
-KPX Racute Oslash -20
-KPX Racute Otilde -20
-KPX Racute T -20
-KPX Racute Tcaron -20
-KPX Racute Tcommaaccent -20
-KPX Racute U -20
-KPX Racute Uacute -20
-KPX Racute Ucircumflex -20
-KPX Racute Udieresis -20
-KPX Racute Ugrave -20
-KPX Racute Uhungarumlaut -20
-KPX Racute Umacron -20
-KPX Racute Uogonek -20
-KPX Racute Uring -20
-KPX Racute V -50
-KPX Racute W -40
-KPX Racute Y -50
-KPX Racute Yacute -50
-KPX Racute Ydieresis -50
-KPX Rcaron O -20
-KPX Rcaron Oacute -20
-KPX Rcaron Ocircumflex -20
-KPX Rcaron Odieresis -20
-KPX Rcaron Ograve -20
-KPX Rcaron Ohungarumlaut -20
-KPX Rcaron Omacron -20
-KPX Rcaron Oslash -20
-KPX Rcaron Otilde -20
-KPX Rcaron T -20
-KPX Rcaron Tcaron -20
-KPX Rcaron Tcommaaccent -20
-KPX Rcaron U -20
-KPX Rcaron Uacute -20
-KPX Rcaron Ucircumflex -20
-KPX Rcaron Udieresis -20
-KPX Rcaron Ugrave -20
-KPX Rcaron Uhungarumlaut -20
-KPX Rcaron Umacron -20
-KPX Rcaron Uogonek -20
-KPX Rcaron Uring -20
-KPX Rcaron V -50
-KPX Rcaron W -40
-KPX Rcaron Y -50
-KPX Rcaron Yacute -50
-KPX Rcaron Ydieresis -50
-KPX Rcommaaccent O -20
-KPX Rcommaaccent Oacute -20
-KPX Rcommaaccent Ocircumflex -20
-KPX Rcommaaccent Odieresis -20
-KPX Rcommaaccent Ograve -20
-KPX Rcommaaccent Ohungarumlaut -20
-KPX Rcommaaccent Omacron -20
-KPX Rcommaaccent Oslash -20
-KPX Rcommaaccent Otilde -20
-KPX Rcommaaccent T -20
-KPX Rcommaaccent Tcaron -20
-KPX Rcommaaccent Tcommaaccent -20
-KPX Rcommaaccent U -20
-KPX Rcommaaccent Uacute -20
-KPX Rcommaaccent Ucircumflex -20
-KPX Rcommaaccent Udieresis -20
-KPX Rcommaaccent Ugrave -20
-KPX Rcommaaccent Uhungarumlaut -20
-KPX Rcommaaccent Umacron -20
-KPX Rcommaaccent Uogonek -20
-KPX Rcommaaccent Uring -20
-KPX Rcommaaccent V -50
-KPX Rcommaaccent W -40
-KPX Rcommaaccent Y -50
-KPX Rcommaaccent Yacute -50
-KPX Rcommaaccent Ydieresis -50
-KPX T A -90
-KPX T Aacute -90
-KPX T Abreve -90
-KPX T Acircumflex -90
-KPX T Adieresis -90
-KPX T Agrave -90
-KPX T Amacron -90
-KPX T Aogonek -90
-KPX T Aring -90
-KPX T Atilde -90
-KPX T O -40
-KPX T Oacute -40
-KPX T Ocircumflex -40
-KPX T Odieresis -40
-KPX T Ograve -40
-KPX T Ohungarumlaut -40
-KPX T Omacron -40
-KPX T Oslash -40
-KPX T Otilde -40
-KPX T a -80
-KPX T aacute -80
-KPX T abreve -80
-KPX T acircumflex -80
-KPX T adieresis -80
-KPX T agrave -80
-KPX T amacron -80
-KPX T aogonek -80
-KPX T aring -80
-KPX T atilde -80
-KPX T colon -40
-KPX T comma -80
-KPX T e -60
-KPX T eacute -60
-KPX T ecaron -60
-KPX T ecircumflex -60
-KPX T edieresis -60
-KPX T edotaccent -60
-KPX T egrave -60
-KPX T emacron -60
-KPX T eogonek -60
-KPX T hyphen -120
-KPX T o -80
-KPX T oacute -80
-KPX T ocircumflex -80
-KPX T odieresis -80
-KPX T ograve -80
-KPX T ohungarumlaut -80
-KPX T omacron -80
-KPX T oslash -80
-KPX T otilde -80
-KPX T period -80
-KPX T r -80
-KPX T racute -80
-KPX T rcommaaccent -80
-KPX T semicolon -40
-KPX T u -90
-KPX T uacute -90
-KPX T ucircumflex -90
-KPX T udieresis -90
-KPX T ugrave -90
-KPX T uhungarumlaut -90
-KPX T umacron -90
-KPX T uogonek -90
-KPX T uring -90
-KPX T w -60
-KPX T y -60
-KPX T yacute -60
-KPX T ydieresis -60
-KPX Tcaron A -90
-KPX Tcaron Aacute -90
-KPX Tcaron Abreve -90
-KPX Tcaron Acircumflex -90
-KPX Tcaron Adieresis -90
-KPX Tcaron Agrave -90
-KPX Tcaron Amacron -90
-KPX Tcaron Aogonek -90
-KPX Tcaron Aring -90
-KPX Tcaron Atilde -90
-KPX Tcaron O -40
-KPX Tcaron Oacute -40
-KPX Tcaron Ocircumflex -40
-KPX Tcaron Odieresis -40
-KPX Tcaron Ograve -40
-KPX Tcaron Ohungarumlaut -40
-KPX Tcaron Omacron -40
-KPX Tcaron Oslash -40
-KPX Tcaron Otilde -40
-KPX Tcaron a -80
-KPX Tcaron aacute -80
-KPX Tcaron abreve -80
-KPX Tcaron acircumflex -80
-KPX Tcaron adieresis -80
-KPX Tcaron agrave -80
-KPX Tcaron amacron -80
-KPX Tcaron aogonek -80
-KPX Tcaron aring -80
-KPX Tcaron atilde -80
-KPX Tcaron colon -40
-KPX Tcaron comma -80
-KPX Tcaron e -60
-KPX Tcaron eacute -60
-KPX Tcaron ecaron -60
-KPX Tcaron ecircumflex -60
-KPX Tcaron edieresis -60
-KPX Tcaron edotaccent -60
-KPX Tcaron egrave -60
-KPX Tcaron emacron -60
-KPX Tcaron eogonek -60
-KPX Tcaron hyphen -120
-KPX Tcaron o -80
-KPX Tcaron oacute -80
-KPX Tcaron ocircumflex -80
-KPX Tcaron odieresis -80
-KPX Tcaron ograve -80
-KPX Tcaron ohungarumlaut -80
-KPX Tcaron omacron -80
-KPX Tcaron oslash -80
-KPX Tcaron otilde -80
-KPX Tcaron period -80
-KPX Tcaron r -80
-KPX Tcaron racute -80
-KPX Tcaron rcommaaccent -80
-KPX Tcaron semicolon -40
-KPX Tcaron u -90
-KPX Tcaron uacute -90
-KPX Tcaron ucircumflex -90
-KPX Tcaron udieresis -90
-KPX Tcaron ugrave -90
-KPX Tcaron uhungarumlaut -90
-KPX Tcaron umacron -90
-KPX Tcaron uogonek -90
-KPX Tcaron uring -90
-KPX Tcaron w -60
-KPX Tcaron y -60
-KPX Tcaron yacute -60
-KPX Tcaron ydieresis -60
-KPX Tcommaaccent A -90
-KPX Tcommaaccent Aacute -90
-KPX Tcommaaccent Abreve -90
-KPX Tcommaaccent Acircumflex -90
-KPX Tcommaaccent Adieresis -90
-KPX Tcommaaccent Agrave -90
-KPX Tcommaaccent Amacron -90
-KPX Tcommaaccent Aogonek -90
-KPX Tcommaaccent Aring -90
-KPX Tcommaaccent Atilde -90
-KPX Tcommaaccent O -40
-KPX Tcommaaccent Oacute -40
-KPX Tcommaaccent Ocircumflex -40
-KPX Tcommaaccent Odieresis -40
-KPX Tcommaaccent Ograve -40
-KPX Tcommaaccent Ohungarumlaut -40
-KPX Tcommaaccent Omacron -40
-KPX Tcommaaccent Oslash -40
-KPX Tcommaaccent Otilde -40
-KPX Tcommaaccent a -80
-KPX Tcommaaccent aacute -80
-KPX Tcommaaccent abreve -80
-KPX Tcommaaccent acircumflex -80
-KPX Tcommaaccent adieresis -80
-KPX Tcommaaccent agrave -80
-KPX Tcommaaccent amacron -80
-KPX Tcommaaccent aogonek -80
-KPX Tcommaaccent aring -80
-KPX Tcommaaccent atilde -80
-KPX Tcommaaccent colon -40
-KPX Tcommaaccent comma -80
-KPX Tcommaaccent e -60
-KPX Tcommaaccent eacute -60
-KPX Tcommaaccent ecaron -60
-KPX Tcommaaccent ecircumflex -60
-KPX Tcommaaccent edieresis -60
-KPX Tcommaaccent edotaccent -60
-KPX Tcommaaccent egrave -60
-KPX Tcommaaccent emacron -60
-KPX Tcommaaccent eogonek -60
-KPX Tcommaaccent hyphen -120
-KPX Tcommaaccent o -80
-KPX Tcommaaccent oacute -80
-KPX Tcommaaccent ocircumflex -80
-KPX Tcommaaccent odieresis -80
-KPX Tcommaaccent ograve -80
-KPX Tcommaaccent ohungarumlaut -80
-KPX Tcommaaccent omacron -80
-KPX Tcommaaccent oslash -80
-KPX Tcommaaccent otilde -80
-KPX Tcommaaccent period -80
-KPX Tcommaaccent r -80
-KPX Tcommaaccent racute -80
-KPX Tcommaaccent rcommaaccent -80
-KPX Tcommaaccent semicolon -40
-KPX Tcommaaccent u -90
-KPX Tcommaaccent uacute -90
-KPX Tcommaaccent ucircumflex -90
-KPX Tcommaaccent udieresis -90
-KPX Tcommaaccent ugrave -90
-KPX Tcommaaccent uhungarumlaut -90
-KPX Tcommaaccent umacron -90
-KPX Tcommaaccent uogonek -90
-KPX Tcommaaccent uring -90
-KPX Tcommaaccent w -60
-KPX Tcommaaccent y -60
-KPX Tcommaaccent yacute -60
-KPX Tcommaaccent ydieresis -60
-KPX U A -50
-KPX U Aacute -50
-KPX U Abreve -50
-KPX U Acircumflex -50
-KPX U Adieresis -50
-KPX U Agrave -50
-KPX U Amacron -50
-KPX U Aogonek -50
-KPX U Aring -50
-KPX U Atilde -50
-KPX U comma -30
-KPX U period -30
-KPX Uacute A -50
-KPX Uacute Aacute -50
-KPX Uacute Abreve -50
-KPX Uacute Acircumflex -50
-KPX Uacute Adieresis -50
-KPX Uacute Agrave -50
-KPX Uacute Amacron -50
-KPX Uacute Aogonek -50
-KPX Uacute Aring -50
-KPX Uacute Atilde -50
-KPX Uacute comma -30
-KPX Uacute period -30
-KPX Ucircumflex A -50
-KPX Ucircumflex Aacute -50
-KPX Ucircumflex Abreve -50
-KPX Ucircumflex Acircumflex -50
-KPX Ucircumflex Adieresis -50
-KPX Ucircumflex Agrave -50
-KPX Ucircumflex Amacron -50
-KPX Ucircumflex Aogonek -50
-KPX Ucircumflex Aring -50
-KPX Ucircumflex Atilde -50
-KPX Ucircumflex comma -30
-KPX Ucircumflex period -30
-KPX Udieresis A -50
-KPX Udieresis Aacute -50
-KPX Udieresis Abreve -50
-KPX Udieresis Acircumflex -50
-KPX Udieresis Adieresis -50
-KPX Udieresis Agrave -50
-KPX Udieresis Amacron -50
-KPX Udieresis Aogonek -50
-KPX Udieresis Aring -50
-KPX Udieresis Atilde -50
-KPX Udieresis comma -30
-KPX Udieresis period -30
-KPX Ugrave A -50
-KPX Ugrave Aacute -50
-KPX Ugrave Abreve -50
-KPX Ugrave Acircumflex -50
-KPX Ugrave Adieresis -50
-KPX Ugrave Agrave -50
-KPX Ugrave Amacron -50
-KPX Ugrave Aogonek -50
-KPX Ugrave Aring -50
-KPX Ugrave Atilde -50
-KPX Ugrave comma -30
-KPX Ugrave period -30
-KPX Uhungarumlaut A -50
-KPX Uhungarumlaut Aacute -50
-KPX Uhungarumlaut Abreve -50
-KPX Uhungarumlaut Acircumflex -50
-KPX Uhungarumlaut Adieresis -50
-KPX Uhungarumlaut Agrave -50
-KPX Uhungarumlaut Amacron -50
-KPX Uhungarumlaut Aogonek -50
-KPX Uhungarumlaut Aring -50
-KPX Uhungarumlaut Atilde -50
-KPX Uhungarumlaut comma -30
-KPX Uhungarumlaut period -30
-KPX Umacron A -50
-KPX Umacron Aacute -50
-KPX Umacron Abreve -50
-KPX Umacron Acircumflex -50
-KPX Umacron Adieresis -50
-KPX Umacron Agrave -50
-KPX Umacron Amacron -50
-KPX Umacron Aogonek -50
-KPX Umacron Aring -50
-KPX Umacron Atilde -50
-KPX Umacron comma -30
-KPX Umacron period -30
-KPX Uogonek A -50
-KPX Uogonek Aacute -50
-KPX Uogonek Abreve -50
-KPX Uogonek Acircumflex -50
-KPX Uogonek Adieresis -50
-KPX Uogonek Agrave -50
-KPX Uogonek Amacron -50
-KPX Uogonek Aogonek -50
-KPX Uogonek Aring -50
-KPX Uogonek Atilde -50
-KPX Uogonek comma -30
-KPX Uogonek period -30
-KPX Uring A -50
-KPX Uring Aacute -50
-KPX Uring Abreve -50
-KPX Uring Acircumflex -50
-KPX Uring Adieresis -50
-KPX Uring Agrave -50
-KPX Uring Amacron -50
-KPX Uring Aogonek -50
-KPX Uring Aring -50
-KPX Uring Atilde -50
-KPX Uring comma -30
-KPX Uring period -30
-KPX V A -80
-KPX V Aacute -80
-KPX V Abreve -80
-KPX V Acircumflex -80
-KPX V Adieresis -80
-KPX V Agrave -80
-KPX V Amacron -80
-KPX V Aogonek -80
-KPX V Aring -80
-KPX V Atilde -80
-KPX V G -50
-KPX V Gbreve -50
-KPX V Gcommaaccent -50
-KPX V O -50
-KPX V Oacute -50
-KPX V Ocircumflex -50
-KPX V Odieresis -50
-KPX V Ograve -50
-KPX V Ohungarumlaut -50
-KPX V Omacron -50
-KPX V Oslash -50
-KPX V Otilde -50
-KPX V a -60
-KPX V aacute -60
-KPX V abreve -60
-KPX V acircumflex -60
-KPX V adieresis -60
-KPX V agrave -60
-KPX V amacron -60
-KPX V aogonek -60
-KPX V aring -60
-KPX V atilde -60
-KPX V colon -40
-KPX V comma -120
-KPX V e -50
-KPX V eacute -50
-KPX V ecaron -50
-KPX V ecircumflex -50
-KPX V edieresis -50
-KPX V edotaccent -50
-KPX V egrave -50
-KPX V emacron -50
-KPX V eogonek -50
-KPX V hyphen -80
-KPX V o -90
-KPX V oacute -90
-KPX V ocircumflex -90
-KPX V odieresis -90
-KPX V ograve -90
-KPX V ohungarumlaut -90
-KPX V omacron -90
-KPX V oslash -90
-KPX V otilde -90
-KPX V period -120
-KPX V semicolon -40
-KPX V u -60
-KPX V uacute -60
-KPX V ucircumflex -60
-KPX V udieresis -60
-KPX V ugrave -60
-KPX V uhungarumlaut -60
-KPX V umacron -60
-KPX V uogonek -60
-KPX V uring -60
-KPX W A -60
-KPX W Aacute -60
-KPX W Abreve -60
-KPX W Acircumflex -60
-KPX W Adieresis -60
-KPX W Agrave -60
-KPX W Amacron -60
-KPX W Aogonek -60
-KPX W Aring -60
-KPX W Atilde -60
-KPX W O -20
-KPX W Oacute -20
-KPX W Ocircumflex -20
-KPX W Odieresis -20
-KPX W Ograve -20
-KPX W Ohungarumlaut -20
-KPX W Omacron -20
-KPX W Oslash -20
-KPX W Otilde -20
-KPX W a -40
-KPX W aacute -40
-KPX W abreve -40
-KPX W acircumflex -40
-KPX W adieresis -40
-KPX W agrave -40
-KPX W amacron -40
-KPX W aogonek -40
-KPX W aring -40
-KPX W atilde -40
-KPX W colon -10
-KPX W comma -80
-KPX W e -35
-KPX W eacute -35
-KPX W ecaron -35
-KPX W ecircumflex -35
-KPX W edieresis -35
-KPX W edotaccent -35
-KPX W egrave -35
-KPX W emacron -35
-KPX W eogonek -35
-KPX W hyphen -40
-KPX W o -60
-KPX W oacute -60
-KPX W ocircumflex -60
-KPX W odieresis -60
-KPX W ograve -60
-KPX W ohungarumlaut -60
-KPX W omacron -60
-KPX W oslash -60
-KPX W otilde -60
-KPX W period -80
-KPX W semicolon -10
-KPX W u -45
-KPX W uacute -45
-KPX W ucircumflex -45
-KPX W udieresis -45
-KPX W ugrave -45
-KPX W uhungarumlaut -45
-KPX W umacron -45
-KPX W uogonek -45
-KPX W uring -45
-KPX W y -20
-KPX W yacute -20
-KPX W ydieresis -20
-KPX Y A -110
-KPX Y Aacute -110
-KPX Y Abreve -110
-KPX Y Acircumflex -110
-KPX Y Adieresis -110
-KPX Y Agrave -110
-KPX Y Amacron -110
-KPX Y Aogonek -110
-KPX Y Aring -110
-KPX Y Atilde -110
-KPX Y O -70
-KPX Y Oacute -70
-KPX Y Ocircumflex -70
-KPX Y Odieresis -70
-KPX Y Ograve -70
-KPX Y Ohungarumlaut -70
-KPX Y Omacron -70
-KPX Y Oslash -70
-KPX Y Otilde -70
-KPX Y a -90
-KPX Y aacute -90
-KPX Y abreve -90
-KPX Y acircumflex -90
-KPX Y adieresis -90
-KPX Y agrave -90
-KPX Y amacron -90
-KPX Y aogonek -90
-KPX Y aring -90
-KPX Y atilde -90
-KPX Y colon -50
-KPX Y comma -100
-KPX Y e -80
-KPX Y eacute -80
-KPX Y ecaron -80
-KPX Y ecircumflex -80
-KPX Y edieresis -80
-KPX Y edotaccent -80
-KPX Y egrave -80
-KPX Y emacron -80
-KPX Y eogonek -80
-KPX Y o -100
-KPX Y oacute -100
-KPX Y ocircumflex -100
-KPX Y odieresis -100
-KPX Y ograve -100
-KPX Y ohungarumlaut -100
-KPX Y omacron -100
-KPX Y oslash -100
-KPX Y otilde -100
-KPX Y period -100
-KPX Y semicolon -50
-KPX Y u -100
-KPX Y uacute -100
-KPX Y ucircumflex -100
-KPX Y udieresis -100
-KPX Y ugrave -100
-KPX Y uhungarumlaut -100
-KPX Y umacron -100
-KPX Y uogonek -100
-KPX Y uring -100
-KPX Yacute A -110
-KPX Yacute Aacute -110
-KPX Yacute Abreve -110
-KPX Yacute Acircumflex -110
-KPX Yacute Adieresis -110
-KPX Yacute Agrave -110
-KPX Yacute Amacron -110
-KPX Yacute Aogonek -110
-KPX Yacute Aring -110
-KPX Yacute Atilde -110
-KPX Yacute O -70
-KPX Yacute Oacute -70
-KPX Yacute Ocircumflex -70
-KPX Yacute Odieresis -70
-KPX Yacute Ograve -70
-KPX Yacute Ohungarumlaut -70
-KPX Yacute Omacron -70
-KPX Yacute Oslash -70
-KPX Yacute Otilde -70
-KPX Yacute a -90
-KPX Yacute aacute -90
-KPX Yacute abreve -90
-KPX Yacute acircumflex -90
-KPX Yacute adieresis -90
-KPX Yacute agrave -90
-KPX Yacute amacron -90
-KPX Yacute aogonek -90
-KPX Yacute aring -90
-KPX Yacute atilde -90
-KPX Yacute colon -50
-KPX Yacute comma -100
-KPX Yacute e -80
-KPX Yacute eacute -80
-KPX Yacute ecaron -80
-KPX Yacute ecircumflex -80
-KPX Yacute edieresis -80
-KPX Yacute edotaccent -80
-KPX Yacute egrave -80
-KPX Yacute emacron -80
-KPX Yacute eogonek -80
-KPX Yacute o -100
-KPX Yacute oacute -100
-KPX Yacute ocircumflex -100
-KPX Yacute odieresis -100
-KPX Yacute ograve -100
-KPX Yacute ohungarumlaut -100
-KPX Yacute omacron -100
-KPX Yacute oslash -100
-KPX Yacute otilde -100
-KPX Yacute period -100
-KPX Yacute semicolon -50
-KPX Yacute u -100
-KPX Yacute uacute -100
-KPX Yacute ucircumflex -100
-KPX Yacute udieresis -100
-KPX Yacute ugrave -100
-KPX Yacute uhungarumlaut -100
-KPX Yacute umacron -100
-KPX Yacute uogonek -100
-KPX Yacute uring -100
-KPX Ydieresis A -110
-KPX Ydieresis Aacute -110
-KPX Ydieresis Abreve -110
-KPX Ydieresis Acircumflex -110
-KPX Ydieresis Adieresis -110
-KPX Ydieresis Agrave -110
-KPX Ydieresis Amacron -110
-KPX Ydieresis Aogonek -110
-KPX Ydieresis Aring -110
-KPX Ydieresis Atilde -110
-KPX Ydieresis O -70
-KPX Ydieresis Oacute -70
-KPX Ydieresis Ocircumflex -70
-KPX Ydieresis Odieresis -70
-KPX Ydieresis Ograve -70
-KPX Ydieresis Ohungarumlaut -70
-KPX Ydieresis Omacron -70
-KPX Ydieresis Oslash -70
-KPX Ydieresis Otilde -70
-KPX Ydieresis a -90
-KPX Ydieresis aacute -90
-KPX Ydieresis abreve -90
-KPX Ydieresis acircumflex -90
-KPX Ydieresis adieresis -90
-KPX Ydieresis agrave -90
-KPX Ydieresis amacron -90
-KPX Ydieresis aogonek -90
-KPX Ydieresis aring -90
-KPX Ydieresis atilde -90
-KPX Ydieresis colon -50
-KPX Ydieresis comma -100
-KPX Ydieresis e -80
-KPX Ydieresis eacute -80
-KPX Ydieresis ecaron -80
-KPX Ydieresis ecircumflex -80
-KPX Ydieresis edieresis -80
-KPX Ydieresis edotaccent -80
-KPX Ydieresis egrave -80
-KPX Ydieresis emacron -80
-KPX Ydieresis eogonek -80
-KPX Ydieresis o -100
-KPX Ydieresis oacute -100
-KPX Ydieresis ocircumflex -100
-KPX Ydieresis odieresis -100
-KPX Ydieresis ograve -100
-KPX Ydieresis ohungarumlaut -100
-KPX Ydieresis omacron -100
-KPX Ydieresis oslash -100
-KPX Ydieresis otilde -100
-KPX Ydieresis period -100
-KPX Ydieresis semicolon -50
-KPX Ydieresis u -100
-KPX Ydieresis uacute -100
-KPX Ydieresis ucircumflex -100
-KPX Ydieresis udieresis -100
-KPX Ydieresis ugrave -100
-KPX Ydieresis uhungarumlaut -100
-KPX Ydieresis umacron -100
-KPX Ydieresis uogonek -100
-KPX Ydieresis uring -100
-KPX a g -10
-KPX a gbreve -10
-KPX a gcommaaccent -10
-KPX a v -15
-KPX a w -15
-KPX a y -20
-KPX a yacute -20
-KPX a ydieresis -20
-KPX aacute g -10
-KPX aacute gbreve -10
-KPX aacute gcommaaccent -10
-KPX aacute v -15
-KPX aacute w -15
-KPX aacute y -20
-KPX aacute yacute -20
-KPX aacute ydieresis -20
-KPX abreve g -10
-KPX abreve gbreve -10
-KPX abreve gcommaaccent -10
-KPX abreve v -15
-KPX abreve w -15
-KPX abreve y -20
-KPX abreve yacute -20
-KPX abreve ydieresis -20
-KPX acircumflex g -10
-KPX acircumflex gbreve -10
-KPX acircumflex gcommaaccent -10
-KPX acircumflex v -15
-KPX acircumflex w -15
-KPX acircumflex y -20
-KPX acircumflex yacute -20
-KPX acircumflex ydieresis -20
-KPX adieresis g -10
-KPX adieresis gbreve -10
-KPX adieresis gcommaaccent -10
-KPX adieresis v -15
-KPX adieresis w -15
-KPX adieresis y -20
-KPX adieresis yacute -20
-KPX adieresis ydieresis -20
-KPX agrave g -10
-KPX agrave gbreve -10
-KPX agrave gcommaaccent -10
-KPX agrave v -15
-KPX agrave w -15
-KPX agrave y -20
-KPX agrave yacute -20
-KPX agrave ydieresis -20
-KPX amacron g -10
-KPX amacron gbreve -10
-KPX amacron gcommaaccent -10
-KPX amacron v -15
-KPX amacron w -15
-KPX amacron y -20
-KPX amacron yacute -20
-KPX amacron ydieresis -20
-KPX aogonek g -10
-KPX aogonek gbreve -10
-KPX aogonek gcommaaccent -10
-KPX aogonek v -15
-KPX aogonek w -15
-KPX aogonek y -20
-KPX aogonek yacute -20
-KPX aogonek ydieresis -20
-KPX aring g -10
-KPX aring gbreve -10
-KPX aring gcommaaccent -10
-KPX aring v -15
-KPX aring w -15
-KPX aring y -20
-KPX aring yacute -20
-KPX aring ydieresis -20
-KPX atilde g -10
-KPX atilde gbreve -10
-KPX atilde gcommaaccent -10
-KPX atilde v -15
-KPX atilde w -15
-KPX atilde y -20
-KPX atilde yacute -20
-KPX atilde ydieresis -20
-KPX b l -10
-KPX b lacute -10
-KPX b lcommaaccent -10
-KPX b lslash -10
-KPX b u -20
-KPX b uacute -20
-KPX b ucircumflex -20
-KPX b udieresis -20
-KPX b ugrave -20
-KPX b uhungarumlaut -20
-KPX b umacron -20
-KPX b uogonek -20
-KPX b uring -20
-KPX b v -20
-KPX b y -20
-KPX b yacute -20
-KPX b ydieresis -20
-KPX c h -10
-KPX c k -20
-KPX c kcommaaccent -20
-KPX c l -20
-KPX c lacute -20
-KPX c lcommaaccent -20
-KPX c lslash -20
-KPX c y -10
-KPX c yacute -10
-KPX c ydieresis -10
-KPX cacute h -10
-KPX cacute k -20
-KPX cacute kcommaaccent -20
-KPX cacute l -20
-KPX cacute lacute -20
-KPX cacute lcommaaccent -20
-KPX cacute lslash -20
-KPX cacute y -10
-KPX cacute yacute -10
-KPX cacute ydieresis -10
-KPX ccaron h -10
-KPX ccaron k -20
-KPX ccaron kcommaaccent -20
-KPX ccaron l -20
-KPX ccaron lacute -20
-KPX ccaron lcommaaccent -20
-KPX ccaron lslash -20
-KPX ccaron y -10
-KPX ccaron yacute -10
-KPX ccaron ydieresis -10
-KPX ccedilla h -10
-KPX ccedilla k -20
-KPX ccedilla kcommaaccent -20
-KPX ccedilla l -20
-KPX ccedilla lacute -20
-KPX ccedilla lcommaaccent -20
-KPX ccedilla lslash -20
-KPX ccedilla y -10
-KPX ccedilla yacute -10
-KPX ccedilla ydieresis -10
-KPX colon space -40
-KPX comma quotedblright -120
-KPX comma quoteright -120
-KPX comma space -40
-KPX d d -10
-KPX d dcroat -10
-KPX d v -15
-KPX d w -15
-KPX d y -15
-KPX d yacute -15
-KPX d ydieresis -15
-KPX dcroat d -10
-KPX dcroat dcroat -10
-KPX dcroat v -15
-KPX dcroat w -15
-KPX dcroat y -15
-KPX dcroat yacute -15
-KPX dcroat ydieresis -15
-KPX e comma 10
-KPX e period 20
-KPX e v -15
-KPX e w -15
-KPX e x -15
-KPX e y -15
-KPX e yacute -15
-KPX e ydieresis -15
-KPX eacute comma 10
-KPX eacute period 20
-KPX eacute v -15
-KPX eacute w -15
-KPX eacute x -15
-KPX eacute y -15
-KPX eacute yacute -15
-KPX eacute ydieresis -15
-KPX ecaron comma 10
-KPX ecaron period 20
-KPX ecaron v -15
-KPX ecaron w -15
-KPX ecaron x -15
-KPX ecaron y -15
-KPX ecaron yacute -15
-KPX ecaron ydieresis -15
-KPX ecircumflex comma 10
-KPX ecircumflex period 20
-KPX ecircumflex v -15
-KPX ecircumflex w -15
-KPX ecircumflex x -15
-KPX ecircumflex y -15
-KPX ecircumflex yacute -15
-KPX ecircumflex ydieresis -15
-KPX edieresis comma 10
-KPX edieresis period 20
-KPX edieresis v -15
-KPX edieresis w -15
-KPX edieresis x -15
-KPX edieresis y -15
-KPX edieresis yacute -15
-KPX edieresis ydieresis -15
-KPX edotaccent comma 10
-KPX edotaccent period 20
-KPX edotaccent v -15
-KPX edotaccent w -15
-KPX edotaccent x -15
-KPX edotaccent y -15
-KPX edotaccent yacute -15
-KPX edotaccent ydieresis -15
-KPX egrave comma 10
-KPX egrave period 20
-KPX egrave v -15
-KPX egrave w -15
-KPX egrave x -15
-KPX egrave y -15
-KPX egrave yacute -15
-KPX egrave ydieresis -15
-KPX emacron comma 10
-KPX emacron period 20
-KPX emacron v -15
-KPX emacron w -15
-KPX emacron x -15
-KPX emacron y -15
-KPX emacron yacute -15
-KPX emacron ydieresis -15
-KPX eogonek comma 10
-KPX eogonek period 20
-KPX eogonek v -15
-KPX eogonek w -15
-KPX eogonek x -15
-KPX eogonek y -15
-KPX eogonek yacute -15
-KPX eogonek ydieresis -15
-KPX f comma -10
-KPX f e -10
-KPX f eacute -10
-KPX f ecaron -10
-KPX f ecircumflex -10
-KPX f edieresis -10
-KPX f edotaccent -10
-KPX f egrave -10
-KPX f emacron -10
-KPX f eogonek -10
-KPX f o -20
-KPX f oacute -20
-KPX f ocircumflex -20
-KPX f odieresis -20
-KPX f ograve -20
-KPX f ohungarumlaut -20
-KPX f omacron -20
-KPX f oslash -20
-KPX f otilde -20
-KPX f period -10
-KPX f quotedblright 30
-KPX f quoteright 30
-KPX g e 10
-KPX g eacute 10
-KPX g ecaron 10
-KPX g ecircumflex 10
-KPX g edieresis 10
-KPX g edotaccent 10
-KPX g egrave 10
-KPX g emacron 10
-KPX g eogonek 10
-KPX g g -10
-KPX g gbreve -10
-KPX g gcommaaccent -10
-KPX gbreve e 10
-KPX gbreve eacute 10
-KPX gbreve ecaron 10
-KPX gbreve ecircumflex 10
-KPX gbreve edieresis 10
-KPX gbreve edotaccent 10
-KPX gbreve egrave 10
-KPX gbreve emacron 10
-KPX gbreve eogonek 10
-KPX gbreve g -10
-KPX gbreve gbreve -10
-KPX gbreve gcommaaccent -10
-KPX gcommaaccent e 10
-KPX gcommaaccent eacute 10
-KPX gcommaaccent ecaron 10
-KPX gcommaaccent ecircumflex 10
-KPX gcommaaccent edieresis 10
-KPX gcommaaccent edotaccent 10
-KPX gcommaaccent egrave 10
-KPX gcommaaccent emacron 10
-KPX gcommaaccent eogonek 10
-KPX gcommaaccent g -10
-KPX gcommaaccent gbreve -10
-KPX gcommaaccent gcommaaccent -10
-KPX h y -20
-KPX h yacute -20
-KPX h ydieresis -20
-KPX k o -15
-KPX k oacute -15
-KPX k ocircumflex -15
-KPX k odieresis -15
-KPX k ograve -15
-KPX k ohungarumlaut -15
-KPX k omacron -15
-KPX k oslash -15
-KPX k otilde -15
-KPX kcommaaccent o -15
-KPX kcommaaccent oacute -15
-KPX kcommaaccent ocircumflex -15
-KPX kcommaaccent odieresis -15
-KPX kcommaaccent ograve -15
-KPX kcommaaccent ohungarumlaut -15
-KPX kcommaaccent omacron -15
-KPX kcommaaccent oslash -15
-KPX kcommaaccent otilde -15
-KPX l w -15
-KPX l y -15
-KPX l yacute -15
-KPX l ydieresis -15
-KPX lacute w -15
-KPX lacute y -15
-KPX lacute yacute -15
-KPX lacute ydieresis -15
-KPX lcommaaccent w -15
-KPX lcommaaccent y -15
-KPX lcommaaccent yacute -15
-KPX lcommaaccent ydieresis -15
-KPX lslash w -15
-KPX lslash y -15
-KPX lslash yacute -15
-KPX lslash ydieresis -15
-KPX m u -20
-KPX m uacute -20
-KPX m ucircumflex -20
-KPX m udieresis -20
-KPX m ugrave -20
-KPX m uhungarumlaut -20
-KPX m umacron -20
-KPX m uogonek -20
-KPX m uring -20
-KPX m y -30
-KPX m yacute -30
-KPX m ydieresis -30
-KPX n u -10
-KPX n uacute -10
-KPX n ucircumflex -10
-KPX n udieresis -10
-KPX n ugrave -10
-KPX n uhungarumlaut -10
-KPX n umacron -10
-KPX n uogonek -10
-KPX n uring -10
-KPX n v -40
-KPX n y -20
-KPX n yacute -20
-KPX n ydieresis -20
-KPX nacute u -10
-KPX nacute uacute -10
-KPX nacute ucircumflex -10
-KPX nacute udieresis -10
-KPX nacute ugrave -10
-KPX nacute uhungarumlaut -10
-KPX nacute umacron -10
-KPX nacute uogonek -10
-KPX nacute uring -10
-KPX nacute v -40
-KPX nacute y -20
-KPX nacute yacute -20
-KPX nacute ydieresis -20
-KPX ncaron u -10
-KPX ncaron uacute -10
-KPX ncaron ucircumflex -10
-KPX ncaron udieresis -10
-KPX ncaron ugrave -10
-KPX ncaron uhungarumlaut -10
-KPX ncaron umacron -10
-KPX ncaron uogonek -10
-KPX ncaron uring -10
-KPX ncaron v -40
-KPX ncaron y -20
-KPX ncaron yacute -20
-KPX ncaron ydieresis -20
-KPX ncommaaccent u -10
-KPX ncommaaccent uacute -10
-KPX ncommaaccent ucircumflex -10
-KPX ncommaaccent udieresis -10
-KPX ncommaaccent ugrave -10
-KPX ncommaaccent uhungarumlaut -10
-KPX ncommaaccent umacron -10
-KPX ncommaaccent uogonek -10
-KPX ncommaaccent uring -10
-KPX ncommaaccent v -40
-KPX ncommaaccent y -20
-KPX ncommaaccent yacute -20
-KPX ncommaaccent ydieresis -20
-KPX ntilde u -10
-KPX ntilde uacute -10
-KPX ntilde ucircumflex -10
-KPX ntilde udieresis -10
-KPX ntilde ugrave -10
-KPX ntilde uhungarumlaut -10
-KPX ntilde umacron -10
-KPX ntilde uogonek -10
-KPX ntilde uring -10
-KPX ntilde v -40
-KPX ntilde y -20
-KPX ntilde yacute -20
-KPX ntilde ydieresis -20
-KPX o v -20
-KPX o w -15
-KPX o x -30
-KPX o y -20
-KPX o yacute -20
-KPX o ydieresis -20
-KPX oacute v -20
-KPX oacute w -15
-KPX oacute x -30
-KPX oacute y -20
-KPX oacute yacute -20
-KPX oacute ydieresis -20
-KPX ocircumflex v -20
-KPX ocircumflex w -15
-KPX ocircumflex x -30
-KPX ocircumflex y -20
-KPX ocircumflex yacute -20
-KPX ocircumflex ydieresis -20
-KPX odieresis v -20
-KPX odieresis w -15
-KPX odieresis x -30
-KPX odieresis y -20
-KPX odieresis yacute -20
-KPX odieresis ydieresis -20
-KPX ograve v -20
-KPX ograve w -15
-KPX ograve x -30
-KPX ograve y -20
-KPX ograve yacute -20
-KPX ograve ydieresis -20
-KPX ohungarumlaut v -20
-KPX ohungarumlaut w -15
-KPX ohungarumlaut x -30
-KPX ohungarumlaut y -20
-KPX ohungarumlaut yacute -20
-KPX ohungarumlaut ydieresis -20
-KPX omacron v -20
-KPX omacron w -15
-KPX omacron x -30
-KPX omacron y -20
-KPX omacron yacute -20
-KPX omacron ydieresis -20
-KPX oslash v -20
-KPX oslash w -15
-KPX oslash x -30
-KPX oslash y -20
-KPX oslash yacute -20
-KPX oslash ydieresis -20
-KPX otilde v -20
-KPX otilde w -15
-KPX otilde x -30
-KPX otilde y -20
-KPX otilde yacute -20
-KPX otilde ydieresis -20
-KPX p y -15
-KPX p yacute -15
-KPX p ydieresis -15
-KPX period quotedblright -120
-KPX period quoteright -120
-KPX period space -40
-KPX quotedblright space -80
-KPX quoteleft quoteleft -46
-KPX quoteright d -80
-KPX quoteright dcroat -80
-KPX quoteright l -20
-KPX quoteright lacute -20
-KPX quoteright lcommaaccent -20
-KPX quoteright lslash -20
-KPX quoteright quoteright -46
-KPX quoteright r -40
-KPX quoteright racute -40
-KPX quoteright rcaron -40
-KPX quoteright rcommaaccent -40
-KPX quoteright s -60
-KPX quoteright sacute -60
-KPX quoteright scaron -60
-KPX quoteright scedilla -60
-KPX quoteright scommaaccent -60
-KPX quoteright space -80
-KPX quoteright v -20
-KPX r c -20
-KPX r cacute -20
-KPX r ccaron -20
-KPX r ccedilla -20
-KPX r comma -60
-KPX r d -20
-KPX r dcroat -20
-KPX r g -15
-KPX r gbreve -15
-KPX r gcommaaccent -15
-KPX r hyphen -20
-KPX r o -20
-KPX r oacute -20
-KPX r ocircumflex -20
-KPX r odieresis -20
-KPX r ograve -20
-KPX r ohungarumlaut -20
-KPX r omacron -20
-KPX r oslash -20
-KPX r otilde -20
-KPX r period -60
-KPX r q -20
-KPX r s -15
-KPX r sacute -15
-KPX r scaron -15
-KPX r scedilla -15
-KPX r scommaaccent -15
-KPX r t 20
-KPX r tcommaaccent 20
-KPX r v 10
-KPX r y 10
-KPX r yacute 10
-KPX r ydieresis 10
-KPX racute c -20
-KPX racute cacute -20
-KPX racute ccaron -20
-KPX racute ccedilla -20
-KPX racute comma -60
-KPX racute d -20
-KPX racute dcroat -20
-KPX racute g -15
-KPX racute gbreve -15
-KPX racute gcommaaccent -15
-KPX racute hyphen -20
-KPX racute o -20
-KPX racute oacute -20
-KPX racute ocircumflex -20
-KPX racute odieresis -20
-KPX racute ograve -20
-KPX racute ohungarumlaut -20
-KPX racute omacron -20
-KPX racute oslash -20
-KPX racute otilde -20
-KPX racute period -60
-KPX racute q -20
-KPX racute s -15
-KPX racute sacute -15
-KPX racute scaron -15
-KPX racute scedilla -15
-KPX racute scommaaccent -15
-KPX racute t 20
-KPX racute tcommaaccent 20
-KPX racute v 10
-KPX racute y 10
-KPX racute yacute 10
-KPX racute ydieresis 10
-KPX rcaron c -20
-KPX rcaron cacute -20
-KPX rcaron ccaron -20
-KPX rcaron ccedilla -20
-KPX rcaron comma -60
-KPX rcaron d -20
-KPX rcaron dcroat -20
-KPX rcaron g -15
-KPX rcaron gbreve -15
-KPX rcaron gcommaaccent -15
-KPX rcaron hyphen -20
-KPX rcaron o -20
-KPX rcaron oacute -20
-KPX rcaron ocircumflex -20
-KPX rcaron odieresis -20
-KPX rcaron ograve -20
-KPX rcaron ohungarumlaut -20
-KPX rcaron omacron -20
-KPX rcaron oslash -20
-KPX rcaron otilde -20
-KPX rcaron period -60
-KPX rcaron q -20
-KPX rcaron s -15
-KPX rcaron sacute -15
-KPX rcaron scaron -15
-KPX rcaron scedilla -15
-KPX rcaron scommaaccent -15
-KPX rcaron t 20
-KPX rcaron tcommaaccent 20
-KPX rcaron v 10
-KPX rcaron y 10
-KPX rcaron yacute 10
-KPX rcaron ydieresis 10
-KPX rcommaaccent c -20
-KPX rcommaaccent cacute -20
-KPX rcommaaccent ccaron -20
-KPX rcommaaccent ccedilla -20
-KPX rcommaaccent comma -60
-KPX rcommaaccent d -20
-KPX rcommaaccent dcroat -20
-KPX rcommaaccent g -15
-KPX rcommaaccent gbreve -15
-KPX rcommaaccent gcommaaccent -15
-KPX rcommaaccent hyphen -20
-KPX rcommaaccent o -20
-KPX rcommaaccent oacute -20
-KPX rcommaaccent ocircumflex -20
-KPX rcommaaccent odieresis -20
-KPX rcommaaccent ograve -20
-KPX rcommaaccent ohungarumlaut -20
-KPX rcommaaccent omacron -20
-KPX rcommaaccent oslash -20
-KPX rcommaaccent otilde -20
-KPX rcommaaccent period -60
-KPX rcommaaccent q -20
-KPX rcommaaccent s -15
-KPX rcommaaccent sacute -15
-KPX rcommaaccent scaron -15
-KPX rcommaaccent scedilla -15
-KPX rcommaaccent scommaaccent -15
-KPX rcommaaccent t 20
-KPX rcommaaccent tcommaaccent 20
-KPX rcommaaccent v 10
-KPX rcommaaccent y 10
-KPX rcommaaccent yacute 10
-KPX rcommaaccent ydieresis 10
-KPX s w -15
-KPX sacute w -15
-KPX scaron w -15
-KPX scedilla w -15
-KPX scommaaccent w -15
-KPX semicolon space -40
-KPX space T -100
-KPX space Tcaron -100
-KPX space Tcommaaccent -100
-KPX space V -80
-KPX space W -80
-KPX space Y -120
-KPX space Yacute -120
-KPX space Ydieresis -120
-KPX space quotedblleft -80
-KPX space quoteleft -60
-KPX v a -20
-KPX v aacute -20
-KPX v abreve -20
-KPX v acircumflex -20
-KPX v adieresis -20
-KPX v agrave -20
-KPX v amacron -20
-KPX v aogonek -20
-KPX v aring -20
-KPX v atilde -20
-KPX v comma -80
-KPX v o -30
-KPX v oacute -30
-KPX v ocircumflex -30
-KPX v odieresis -30
-KPX v ograve -30
-KPX v ohungarumlaut -30
-KPX v omacron -30
-KPX v oslash -30
-KPX v otilde -30
-KPX v period -80
-KPX w comma -40
-KPX w o -20
-KPX w oacute -20
-KPX w ocircumflex -20
-KPX w odieresis -20
-KPX w ograve -20
-KPX w ohungarumlaut -20
-KPX w omacron -20
-KPX w oslash -20
-KPX w otilde -20
-KPX w period -40
-KPX x e -10
-KPX x eacute -10
-KPX x ecaron -10
-KPX x ecircumflex -10
-KPX x edieresis -10
-KPX x edotaccent -10
-KPX x egrave -10
-KPX x emacron -10
-KPX x eogonek -10
-KPX y a -30
-KPX y aacute -30
-KPX y abreve -30
-KPX y acircumflex -30
-KPX y adieresis -30
-KPX y agrave -30
-KPX y amacron -30
-KPX y aogonek -30
-KPX y aring -30
-KPX y atilde -30
-KPX y comma -80
-KPX y e -10
-KPX y eacute -10
-KPX y ecaron -10
-KPX y ecircumflex -10
-KPX y edieresis -10
-KPX y edotaccent -10
-KPX y egrave -10
-KPX y emacron -10
-KPX y eogonek -10
-KPX y o -25
-KPX y oacute -25
-KPX y ocircumflex -25
-KPX y odieresis -25
-KPX y ograve -25
-KPX y ohungarumlaut -25
-KPX y omacron -25
-KPX y oslash -25
-KPX y otilde -25
-KPX y period -80
-KPX yacute a -30
-KPX yacute aacute -30
-KPX yacute abreve -30
-KPX yacute acircumflex -30
-KPX yacute adieresis -30
-KPX yacute agrave -30
-KPX yacute amacron -30
-KPX yacute aogonek -30
-KPX yacute aring -30
-KPX yacute atilde -30
-KPX yacute comma -80
-KPX yacute e -10
-KPX yacute eacute -10
-KPX yacute ecaron -10
-KPX yacute ecircumflex -10
-KPX yacute edieresis -10
-KPX yacute edotaccent -10
-KPX yacute egrave -10
-KPX yacute emacron -10
-KPX yacute eogonek -10
-KPX yacute o -25
-KPX yacute oacute -25
-KPX yacute ocircumflex -25
-KPX yacute odieresis -25
-KPX yacute ograve -25
-KPX yacute ohungarumlaut -25
-KPX yacute omacron -25
-KPX yacute oslash -25
-KPX yacute otilde -25
-KPX yacute period -80
-KPX ydieresis a -30
-KPX ydieresis aacute -30
-KPX ydieresis abreve -30
-KPX ydieresis acircumflex -30
-KPX ydieresis adieresis -30
-KPX ydieresis agrave -30
-KPX ydieresis amacron -30
-KPX ydieresis aogonek -30
-KPX ydieresis aring -30
-KPX ydieresis atilde -30
-KPX ydieresis comma -80
-KPX ydieresis e -10
-KPX ydieresis eacute -10
-KPX ydieresis ecaron -10
-KPX ydieresis ecircumflex -10
-KPX ydieresis edieresis -10
-KPX ydieresis edotaccent -10
-KPX ydieresis egrave -10
-KPX ydieresis emacron -10
-KPX ydieresis eogonek -10
-KPX ydieresis o -25
-KPX ydieresis oacute -25
-KPX ydieresis ocircumflex -25
-KPX ydieresis odieresis -25
-KPX ydieresis ograve -25
-KPX ydieresis ohungarumlaut -25
-KPX ydieresis omacron -25
-KPX ydieresis oslash -25
-KPX ydieresis otilde -25
-KPX ydieresis period -80
-KPX z e 10
-KPX z eacute 10
-KPX z ecaron 10
-KPX z ecircumflex 10
-KPX z edieresis 10
-KPX z edotaccent 10
-KPX z egrave 10
-KPX z emacron 10
-KPX z eogonek 10
-KPX zacute e 10
-KPX zacute eacute 10
-KPX zacute ecaron 10
-KPX zacute ecircumflex 10
-KPX zacute edieresis 10
-KPX zacute edotaccent 10
-KPX zacute egrave 10
-KPX zacute emacron 10
-KPX zacute eogonek 10
-KPX zcaron e 10
-KPX zcaron eacute 10
-KPX zcaron ecaron 10
-KPX zcaron ecircumflex 10
-KPX zcaron edieresis 10
-KPX zcaron edotaccent 10
-KPX zcaron egrave 10
-KPX zcaron emacron 10
-KPX zcaron eogonek 10
-KPX zdotaccent e 10
-KPX zdotaccent eacute 10
-KPX zdotaccent ecaron 10
-KPX zdotaccent ecircumflex 10
-KPX zdotaccent edieresis 10
-KPX zdotaccent edotaccent 10
-KPX zdotaccent egrave 10
-KPX zdotaccent emacron 10
-KPX zdotaccent eogonek 10
-EndKernPairs
-EndKernData
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Helvetica-Oblique.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Helvetica-Oblique.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Helvetica-Oblique.afm 2004-05-26 16:06:20.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Helvetica-Oblique.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,3051 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Thu May 1 12:44:31 1997
-Comment UniqueID 43055
-Comment VMusage 14960 69346
-FontName Helvetica-Oblique
-FullName Helvetica Oblique
-FamilyName Helvetica
-Weight Medium
-ItalicAngle -12
-IsFixedPitch false
-CharacterSet ExtendedRoman
-FontBBox -170 -225 1116 931
-UnderlinePosition -100
-UnderlineThickness 50
-Version 002.000
-Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
-EncodingScheme AdobeStandardEncoding
-CapHeight 718
-XHeight 523
-Ascender 718
-Descender -207
-StdHW 76
-StdVW 88
-StartCharMetrics 315
-C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 278 ; N exclam ; B 90 0 340 718 ;
-C 34 ; WX 355 ; N quotedbl ; B 168 463 438 718 ;
-C 35 ; WX 556 ; N numbersign ; B 73 0 631 688 ;
-C 36 ; WX 556 ; N dollar ; B 69 -115 617 775 ;
-C 37 ; WX 889 ; N percent ; B 147 -19 889 703 ;
-C 38 ; WX 667 ; N ampersand ; B 77 -15 647 718 ;
-C 39 ; WX 222 ; N quoteright ; B 151 463 310 718 ;
-C 40 ; WX 333 ; N parenleft ; B 108 -207 454 733 ;
-C 41 ; WX 333 ; N parenright ; B -9 -207 337 733 ;
-C 42 ; WX 389 ; N asterisk ; B 165 431 475 718 ;
-C 43 ; WX 584 ; N plus ; B 85 0 606 505 ;
-C 44 ; WX 278 ; N comma ; B 56 -147 214 106 ;
-C 45 ; WX 333 ; N hyphen ; B 93 232 357 322 ;
-C 46 ; WX 278 ; N period ; B 87 0 214 106 ;
-C 47 ; WX 278 ; N slash ; B -21 -19 452 737 ;
-C 48 ; WX 556 ; N zero ; B 93 -19 608 703 ;
-C 49 ; WX 556 ; N one ; B 207 0 508 703 ;
-C 50 ; WX 556 ; N two ; B 26 0 617 703 ;
-C 51 ; WX 556 ; N three ; B 75 -19 610 703 ;
-C 52 ; WX 556 ; N four ; B 61 0 576 703 ;
-C 53 ; WX 556 ; N five ; B 68 -19 621 688 ;
-C 54 ; WX 556 ; N six ; B 91 -19 615 703 ;
-C 55 ; WX 556 ; N seven ; B 137 0 669 688 ;
-C 56 ; WX 556 ; N eight ; B 74 -19 607 703 ;
-C 57 ; WX 556 ; N nine ; B 82 -19 609 703 ;
-C 58 ; WX 278 ; N colon ; B 87 0 301 516 ;
-C 59 ; WX 278 ; N semicolon ; B 56 -147 301 516 ;
-C 60 ; WX 584 ; N less ; B 94 11 641 495 ;
-C 61 ; WX 584 ; N equal ; B 63 115 628 390 ;
-C 62 ; WX 584 ; N greater ; B 50 11 597 495 ;
-C 63 ; WX 556 ; N question ; B 161 0 610 727 ;
-C 64 ; WX 1015 ; N at ; B 215 -19 965 737 ;
-C 65 ; WX 667 ; N A ; B 14 0 654 718 ;
-C 66 ; WX 667 ; N B ; B 74 0 712 718 ;
-C 67 ; WX 722 ; N C ; B 108 -19 782 737 ;
-C 68 ; WX 722 ; N D ; B 81 0 764 718 ;
-C 69 ; WX 667 ; N E ; B 86 0 762 718 ;
-C 70 ; WX 611 ; N F ; B 86 0 736 718 ;
-C 71 ; WX 778 ; N G ; B 111 -19 799 737 ;
-C 72 ; WX 722 ; N H ; B 77 0 799 718 ;
-C 73 ; WX 278 ; N I ; B 91 0 341 718 ;
-C 74 ; WX 500 ; N J ; B 47 -19 581 718 ;
-C 75 ; WX 667 ; N K ; B 76 0 808 718 ;
-C 76 ; WX 556 ; N L ; B 76 0 555 718 ;
-C 77 ; WX 833 ; N M ; B 73 0 914 718 ;
-C 78 ; WX 722 ; N N ; B 76 0 799 718 ;
-C 79 ; WX 778 ; N O ; B 105 -19 826 737 ;
-C 80 ; WX 667 ; N P ; B 86 0 737 718 ;
-C 81 ; WX 778 ; N Q ; B 105 -56 826 737 ;
-C 82 ; WX 722 ; N R ; B 88 0 773 718 ;
-C 83 ; WX 667 ; N S ; B 90 -19 713 737 ;
-C 84 ; WX 611 ; N T ; B 148 0 750 718 ;
-C 85 ; WX 722 ; N U ; B 123 -19 797 718 ;
-C 86 ; WX 667 ; N V ; B 173 0 800 718 ;
-C 87 ; WX 944 ; N W ; B 169 0 1081 718 ;
-C 88 ; WX 667 ; N X ; B 19 0 790 718 ;
-C 89 ; WX 667 ; N Y ; B 167 0 806 718 ;
-C 90 ; WX 611 ; N Z ; B 23 0 741 718 ;
-C 91 ; WX 278 ; N bracketleft ; B 21 -196 403 722 ;
-C 92 ; WX 278 ; N backslash ; B 140 -19 291 737 ;
-C 93 ; WX 278 ; N bracketright ; B -14 -196 368 722 ;
-C 94 ; WX 469 ; N asciicircum ; B 42 264 539 688 ;
-C 95 ; WX 556 ; N underscore ; B -27 -125 540 -75 ;
-C 96 ; WX 222 ; N quoteleft ; B 165 470 323 725 ;
-C 97 ; WX 556 ; N a ; B 61 -15 559 538 ;
-C 98 ; WX 556 ; N b ; B 58 -15 584 718 ;
-C 99 ; WX 500 ; N c ; B 74 -15 553 538 ;
-C 100 ; WX 556 ; N d ; B 84 -15 652 718 ;
-C 101 ; WX 556 ; N e ; B 84 -15 578 538 ;
-C 102 ; WX 278 ; N f ; B 86 0 416 728 ; L i fi ; L l fl ;
-C 103 ; WX 556 ; N g ; B 42 -220 610 538 ;
-C 104 ; WX 556 ; N h ; B 65 0 573 718 ;
-C 105 ; WX 222 ; N i ; B 67 0 308 718 ;
-C 106 ; WX 222 ; N j ; B -60 -210 308 718 ;
-C 107 ; WX 500 ; N k ; B 67 0 600 718 ;
-C 108 ; WX 222 ; N l ; B 67 0 308 718 ;
-C 109 ; WX 833 ; N m ; B 65 0 852 538 ;
-C 110 ; WX 556 ; N n ; B 65 0 573 538 ;
-C 111 ; WX 556 ; N o ; B 83 -14 585 538 ;
-C 112 ; WX 556 ; N p ; B 14 -207 584 538 ;
-C 113 ; WX 556 ; N q ; B 84 -207 605 538 ;
-C 114 ; WX 333 ; N r ; B 77 0 446 538 ;
-C 115 ; WX 500 ; N s ; B 63 -15 529 538 ;
-C 116 ; WX 278 ; N t ; B 102 -7 368 669 ;
-C 117 ; WX 556 ; N u ; B 94 -15 600 523 ;
-C 118 ; WX 500 ; N v ; B 119 0 603 523 ;
-C 119 ; WX 722 ; N w ; B 125 0 820 523 ;
-C 120 ; WX 500 ; N x ; B 11 0 594 523 ;
-C 121 ; WX 500 ; N y ; B 15 -214 600 523 ;
-C 122 ; WX 500 ; N z ; B 31 0 571 523 ;
-C 123 ; WX 334 ; N braceleft ; B 92 -196 445 722 ;
-C 124 ; WX 260 ; N bar ; B 46 -225 332 775 ;
-C 125 ; WX 334 ; N braceright ; B 0 -196 354 722 ;
-C 126 ; WX 584 ; N asciitilde ; B 111 180 580 326 ;
-C 161 ; WX 333 ; N exclamdown ; B 77 -195 326 523 ;
-C 162 ; WX 556 ; N cent ; B 95 -115 584 623 ;
-C 163 ; WX 556 ; N sterling ; B 49 -16 634 718 ;
-C 164 ; WX 167 ; N fraction ; B -170 -19 482 703 ;
-C 165 ; WX 556 ; N yen ; B 81 0 699 688 ;
-C 166 ; WX 556 ; N florin ; B -52 -207 654 737 ;
-C 167 ; WX 556 ; N section ; B 76 -191 584 737 ;
-C 168 ; WX 556 ; N currency ; B 60 99 646 603 ;
-C 169 ; WX 191 ; N quotesingle ; B 157 463 285 718 ;
-C 170 ; WX 333 ; N quotedblleft ; B 138 470 461 725 ;
-C 171 ; WX 556 ; N guillemotleft ; B 146 108 554 446 ;
-C 172 ; WX 333 ; N guilsinglleft ; B 137 108 340 446 ;
-C 173 ; WX 333 ; N guilsinglright ; B 111 108 314 446 ;
-C 174 ; WX 500 ; N fi ; B 86 0 587 728 ;
-C 175 ; WX 500 ; N fl ; B 86 0 585 728 ;
-C 177 ; WX 556 ; N endash ; B 51 240 623 313 ;
-C 178 ; WX 556 ; N dagger ; B 135 -159 622 718 ;
-C 179 ; WX 556 ; N daggerdbl ; B 52 -159 623 718 ;
-C 180 ; WX 278 ; N periodcentered ; B 129 190 257 315 ;
-C 182 ; WX 537 ; N paragraph ; B 126 -173 650 718 ;
-C 183 ; WX 350 ; N bullet ; B 91 202 413 517 ;
-C 184 ; WX 222 ; N quotesinglbase ; B 21 -149 180 106 ;
-C 185 ; WX 333 ; N quotedblbase ; B -6 -149 318 106 ;
-C 186 ; WX 333 ; N quotedblright ; B 124 463 448 718 ;
-C 187 ; WX 556 ; N guillemotright ; B 120 108 528 446 ;
-C 188 ; WX 1000 ; N ellipsis ; B 115 0 908 106 ;
-C 189 ; WX 1000 ; N perthousand ; B 88 -19 1029 703 ;
-C 191 ; WX 611 ; N questiondown ; B 85 -201 534 525 ;
-C 193 ; WX 333 ; N grave ; B 170 593 337 734 ;
-C 194 ; WX 333 ; N acute ; B 248 593 475 734 ;
-C 195 ; WX 333 ; N circumflex ; B 147 593 438 734 ;
-C 196 ; WX 333 ; N tilde ; B 125 606 490 722 ;
-C 197 ; WX 333 ; N macron ; B 143 627 468 684 ;
-C 198 ; WX 333 ; N breve ; B 167 595 476 731 ;
-C 199 ; WX 333 ; N dotaccent ; B 249 604 362 706 ;
-C 200 ; WX 333 ; N dieresis ; B 168 604 443 706 ;
-C 202 ; WX 333 ; N ring ; B 214 572 402 756 ;
-C 203 ; WX 333 ; N cedilla ; B 2 -225 232 0 ;
-C 205 ; WX 333 ; N hungarumlaut ; B 157 593 565 734 ;
-C 206 ; WX 333 ; N ogonek ; B 43 -225 249 0 ;
-C 207 ; WX 333 ; N caron ; B 177 593 468 734 ;
-C 208 ; WX 1000 ; N emdash ; B 51 240 1067 313 ;
-C 225 ; WX 1000 ; N AE ; B 8 0 1097 718 ;
-C 227 ; WX 370 ; N ordfeminine ; B 127 405 449 737 ;
-C 232 ; WX 556 ; N Lslash ; B 41 0 555 718 ;
-C 233 ; WX 778 ; N Oslash ; B 43 -19 890 737 ;
-C 234 ; WX 1000 ; N OE ; B 98 -19 1116 737 ;
-C 235 ; WX 365 ; N ordmasculine ; B 141 405 468 737 ;
-C 241 ; WX 889 ; N ae ; B 61 -15 909 538 ;
-C 245 ; WX 278 ; N dotlessi ; B 95 0 294 523 ;
-C 248 ; WX 222 ; N lslash ; B 41 0 347 718 ;
-C 249 ; WX 611 ; N oslash ; B 29 -22 647 545 ;
-C 250 ; WX 944 ; N oe ; B 83 -15 964 538 ;
-C 251 ; WX 611 ; N germandbls ; B 67 -15 658 728 ;
-C -1 ; WX 278 ; N Idieresis ; B 91 0 458 901 ;
-C -1 ; WX 556 ; N eacute ; B 84 -15 587 734 ;
-C -1 ; WX 556 ; N abreve ; B 61 -15 578 731 ;
-C -1 ; WX 556 ; N uhungarumlaut ; B 94 -15 677 734 ;
-C -1 ; WX 556 ; N ecaron ; B 84 -15 580 734 ;
-C -1 ; WX 667 ; N Ydieresis ; B 167 0 806 901 ;
-C -1 ; WX 584 ; N divide ; B 85 -19 606 524 ;
-C -1 ; WX 667 ; N Yacute ; B 167 0 806 929 ;
-C -1 ; WX 667 ; N Acircumflex ; B 14 0 654 929 ;
-C -1 ; WX 556 ; N aacute ; B 61 -15 587 734 ;
-C -1 ; WX 722 ; N Ucircumflex ; B 123 -19 797 929 ;
-C -1 ; WX 500 ; N yacute ; B 15 -214 600 734 ;
-C -1 ; WX 500 ; N scommaaccent ; B 63 -225 529 538 ;
-C -1 ; WX 556 ; N ecircumflex ; B 84 -15 578 734 ;
-C -1 ; WX 722 ; N Uring ; B 123 -19 797 931 ;
-C -1 ; WX 722 ; N Udieresis ; B 123 -19 797 901 ;
-C -1 ; WX 556 ; N aogonek ; B 61 -220 559 538 ;
-C -1 ; WX 722 ; N Uacute ; B 123 -19 797 929 ;
-C -1 ; WX 556 ; N uogonek ; B 94 -225 600 523 ;
-C -1 ; WX 667 ; N Edieresis ; B 86 0 762 901 ;
-C -1 ; WX 722 ; N Dcroat ; B 69 0 764 718 ;
-C -1 ; WX 250 ; N commaaccent ; B 39 -225 172 -40 ;
-C -1 ; WX 737 ; N copyright ; B 54 -19 837 737 ;
-C -1 ; WX 667 ; N Emacron ; B 86 0 762 879 ;
-C -1 ; WX 500 ; N ccaron ; B 74 -15 553 734 ;
-C -1 ; WX 556 ; N aring ; B 61 -15 559 756 ;
-C -1 ; WX 722 ; N Ncommaaccent ; B 76 -225 799 718 ;
-C -1 ; WX 222 ; N lacute ; B 67 0 461 929 ;
-C -1 ; WX 556 ; N agrave ; B 61 -15 559 734 ;
-C -1 ; WX 611 ; N Tcommaaccent ; B 148 -225 750 718 ;
-C -1 ; WX 722 ; N Cacute ; B 108 -19 782 929 ;
-C -1 ; WX 556 ; N atilde ; B 61 -15 592 722 ;
-C -1 ; WX 667 ; N Edotaccent ; B 86 0 762 901 ;
-C -1 ; WX 500 ; N scaron ; B 63 -15 552 734 ;
-C -1 ; WX 500 ; N scedilla ; B 63 -225 529 538 ;
-C -1 ; WX 278 ; N iacute ; B 95 0 448 734 ;
-C -1 ; WX 471 ; N lozenge ; B 88 0 540 728 ;
-C -1 ; WX 722 ; N Rcaron ; B 88 0 773 929 ;
-C -1 ; WX 778 ; N Gcommaaccent ; B 111 -225 799 737 ;
-C -1 ; WX 556 ; N ucircumflex ; B 94 -15 600 734 ;
-C -1 ; WX 556 ; N acircumflex ; B 61 -15 559 734 ;
-C -1 ; WX 667 ; N Amacron ; B 14 0 677 879 ;
-C -1 ; WX 333 ; N rcaron ; B 77 0 508 734 ;
-C -1 ; WX 500 ; N ccedilla ; B 74 -225 553 538 ;
-C -1 ; WX 611 ; N Zdotaccent ; B 23 0 741 901 ;
-C -1 ; WX 667 ; N Thorn ; B 86 0 712 718 ;
-C -1 ; WX 778 ; N Omacron ; B 105 -19 826 879 ;
-C -1 ; WX 722 ; N Racute ; B 88 0 773 929 ;
-C -1 ; WX 667 ; N Sacute ; B 90 -19 713 929 ;
-C -1 ; WX 643 ; N dcaron ; B 84 -15 808 718 ;
-C -1 ; WX 722 ; N Umacron ; B 123 -19 797 879 ;
-C -1 ; WX 556 ; N uring ; B 94 -15 600 756 ;
-C -1 ; WX 333 ; N threesuperior ; B 90 270 436 703 ;
-C -1 ; WX 778 ; N Ograve ; B 105 -19 826 929 ;
-C -1 ; WX 667 ; N Agrave ; B 14 0 654 929 ;
-C -1 ; WX 667 ; N Abreve ; B 14 0 685 926 ;
-C -1 ; WX 584 ; N multiply ; B 50 0 642 506 ;
-C -1 ; WX 556 ; N uacute ; B 94 -15 600 734 ;
-C -1 ; WX 611 ; N Tcaron ; B 148 0 750 929 ;
-C -1 ; WX 476 ; N partialdiff ; B 41 -38 550 714 ;
-C -1 ; WX 500 ; N ydieresis ; B 15 -214 600 706 ;
-C -1 ; WX 722 ; N Nacute ; B 76 0 799 929 ;
-C -1 ; WX 278 ; N icircumflex ; B 95 0 411 734 ;
-C -1 ; WX 667 ; N Ecircumflex ; B 86 0 762 929 ;
-C -1 ; WX 556 ; N adieresis ; B 61 -15 559 706 ;
-C -1 ; WX 556 ; N edieresis ; B 84 -15 578 706 ;
-C -1 ; WX 500 ; N cacute ; B 74 -15 559 734 ;
-C -1 ; WX 556 ; N nacute ; B 65 0 587 734 ;
-C -1 ; WX 556 ; N umacron ; B 94 -15 600 684 ;
-C -1 ; WX 722 ; N Ncaron ; B 76 0 799 929 ;
-C -1 ; WX 278 ; N Iacute ; B 91 0 489 929 ;
-C -1 ; WX 584 ; N plusminus ; B 39 0 618 506 ;
-C -1 ; WX 260 ; N brokenbar ; B 62 -150 316 700 ;
-C -1 ; WX 737 ; N registered ; B 54 -19 837 737 ;
-C -1 ; WX 778 ; N Gbreve ; B 111 -19 799 926 ;
-C -1 ; WX 278 ; N Idotaccent ; B 91 0 377 901 ;
-C -1 ; WX 600 ; N summation ; B 15 -10 671 706 ;
-C -1 ; WX 667 ; N Egrave ; B 86 0 762 929 ;
-C -1 ; WX 333 ; N racute ; B 77 0 475 734 ;
-C -1 ; WX 556 ; N omacron ; B 83 -14 585 684 ;
-C -1 ; WX 611 ; N Zacute ; B 23 0 741 929 ;
-C -1 ; WX 611 ; N Zcaron ; B 23 0 741 929 ;
-C -1 ; WX 549 ; N greaterequal ; B 26 0 620 674 ;
-C -1 ; WX 722 ; N Eth ; B 69 0 764 718 ;
-C -1 ; WX 722 ; N Ccedilla ; B 108 -225 782 737 ;
-C -1 ; WX 222 ; N lcommaaccent ; B 25 -225 308 718 ;
-C -1 ; WX 317 ; N tcaron ; B 102 -7 501 808 ;
-C -1 ; WX 556 ; N eogonek ; B 84 -225 578 538 ;
-C -1 ; WX 722 ; N Uogonek ; B 123 -225 797 718 ;
-C -1 ; WX 667 ; N Aacute ; B 14 0 683 929 ;
-C -1 ; WX 667 ; N Adieresis ; B 14 0 654 901 ;
-C -1 ; WX 556 ; N egrave ; B 84 -15 578 734 ;
-C -1 ; WX 500 ; N zacute ; B 31 0 571 734 ;
-C -1 ; WX 222 ; N iogonek ; B -61 -225 308 718 ;
-C -1 ; WX 778 ; N Oacute ; B 105 -19 826 929 ;
-C -1 ; WX 556 ; N oacute ; B 83 -14 587 734 ;
-C -1 ; WX 556 ; N amacron ; B 61 -15 580 684 ;
-C -1 ; WX 500 ; N sacute ; B 63 -15 559 734 ;
-C -1 ; WX 278 ; N idieresis ; B 95 0 416 706 ;
-C -1 ; WX 778 ; N Ocircumflex ; B 105 -19 826 929 ;
-C -1 ; WX 722 ; N Ugrave ; B 123 -19 797 929 ;
-C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
-C -1 ; WX 556 ; N thorn ; B 14 -207 584 718 ;
-C -1 ; WX 333 ; N twosuperior ; B 64 281 449 703 ;
-C -1 ; WX 778 ; N Odieresis ; B 105 -19 826 901 ;
-C -1 ; WX 556 ; N mu ; B 24 -207 600 523 ;
-C -1 ; WX 278 ; N igrave ; B 95 0 310 734 ;
-C -1 ; WX 556 ; N ohungarumlaut ; B 83 -14 677 734 ;
-C -1 ; WX 667 ; N Eogonek ; B 86 -220 762 718 ;
-C -1 ; WX 556 ; N dcroat ; B 84 -15 689 718 ;
-C -1 ; WX 834 ; N threequarters ; B 130 -19 861 703 ;
-C -1 ; WX 667 ; N Scedilla ; B 90 -225 713 737 ;
-C -1 ; WX 299 ; N lcaron ; B 67 0 464 718 ;
-C -1 ; WX 667 ; N Kcommaaccent ; B 76 -225 808 718 ;
-C -1 ; WX 556 ; N Lacute ; B 76 0 555 929 ;
-C -1 ; WX 1000 ; N trademark ; B 186 306 1056 718 ;
-C -1 ; WX 556 ; N edotaccent ; B 84 -15 578 706 ;
-C -1 ; WX 278 ; N Igrave ; B 91 0 351 929 ;
-C -1 ; WX 278 ; N Imacron ; B 91 0 483 879 ;
-C -1 ; WX 556 ; N Lcaron ; B 76 0 570 718 ;
-C -1 ; WX 834 ; N onehalf ; B 114 -19 839 703 ;
-C -1 ; WX 549 ; N lessequal ; B 26 0 666 674 ;
-C -1 ; WX 556 ; N ocircumflex ; B 83 -14 585 734 ;
-C -1 ; WX 556 ; N ntilde ; B 65 0 592 722 ;
-C -1 ; WX 722 ; N Uhungarumlaut ; B 123 -19 801 929 ;
-C -1 ; WX 667 ; N Eacute ; B 86 0 762 929 ;
-C -1 ; WX 556 ; N emacron ; B 84 -15 580 684 ;
-C -1 ; WX 556 ; N gbreve ; B 42 -220 610 731 ;
-C -1 ; WX 834 ; N onequarter ; B 150 -19 802 703 ;
-C -1 ; WX 667 ; N Scaron ; B 90 -19 713 929 ;
-C -1 ; WX 667 ; N Scommaaccent ; B 90 -225 713 737 ;
-C -1 ; WX 778 ; N Ohungarumlaut ; B 105 -19 829 929 ;
-C -1 ; WX 400 ; N degree ; B 169 411 468 703 ;
-C -1 ; WX 556 ; N ograve ; B 83 -14 585 734 ;
-C -1 ; WX 722 ; N Ccaron ; B 108 -19 782 929 ;
-C -1 ; WX 556 ; N ugrave ; B 94 -15 600 734 ;
-C -1 ; WX 453 ; N radical ; B 79 -80 617 762 ;
-C -1 ; WX 722 ; N Dcaron ; B 81 0 764 929 ;
-C -1 ; WX 333 ; N rcommaaccent ; B 30 -225 446 538 ;
-C -1 ; WX 722 ; N Ntilde ; B 76 0 799 917 ;
-C -1 ; WX 556 ; N otilde ; B 83 -14 602 722 ;
-C -1 ; WX 722 ; N Rcommaaccent ; B 88 -225 773 718 ;
-C -1 ; WX 556 ; N Lcommaaccent ; B 76 -225 555 718 ;
-C -1 ; WX 667 ; N Atilde ; B 14 0 699 917 ;
-C -1 ; WX 667 ; N Aogonek ; B 14 -225 654 718 ;
-C -1 ; WX 667 ; N Aring ; B 14 0 654 931 ;
-C -1 ; WX 778 ; N Otilde ; B 105 -19 826 917 ;
-C -1 ; WX 500 ; N zdotaccent ; B 31 0 571 706 ;
-C -1 ; WX 667 ; N Ecaron ; B 86 0 762 929 ;
-C -1 ; WX 278 ; N Iogonek ; B -33 -225 341 718 ;
-C -1 ; WX 500 ; N kcommaaccent ; B 67 -225 600 718 ;
-C -1 ; WX 584 ; N minus ; B 85 216 606 289 ;
-C -1 ; WX 278 ; N Icircumflex ; B 91 0 452 929 ;
-C -1 ; WX 556 ; N ncaron ; B 65 0 580 734 ;
-C -1 ; WX 278 ; N tcommaaccent ; B 63 -225 368 669 ;
-C -1 ; WX 584 ; N logicalnot ; B 106 108 628 390 ;
-C -1 ; WX 556 ; N odieresis ; B 83 -14 585 706 ;
-C -1 ; WX 556 ; N udieresis ; B 94 -15 600 706 ;
-C -1 ; WX 549 ; N notequal ; B 34 -35 623 551 ;
-C -1 ; WX 556 ; N gcommaaccent ; B 42 -220 610 822 ;
-C -1 ; WX 556 ; N eth ; B 81 -15 617 737 ;
-C -1 ; WX 500 ; N zcaron ; B 31 0 571 734 ;
-C -1 ; WX 556 ; N ncommaaccent ; B 65 -225 573 538 ;
-C -1 ; WX 333 ; N onesuperior ; B 166 281 371 703 ;
-C -1 ; WX 278 ; N imacron ; B 95 0 417 684 ;
-C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ;
-EndCharMetrics
-StartKernData
-StartKernPairs 2705
-KPX A C -30
-KPX A Cacute -30
-KPX A Ccaron -30
-KPX A Ccedilla -30
-KPX A G -30
-KPX A Gbreve -30
-KPX A Gcommaaccent -30
-KPX A O -30
-KPX A Oacute -30
-KPX A Ocircumflex -30
-KPX A Odieresis -30
-KPX A Ograve -30
-KPX A Ohungarumlaut -30
-KPX A Omacron -30
-KPX A Oslash -30
-KPX A Otilde -30
-KPX A Q -30
-KPX A T -120
-KPX A Tcaron -120
-KPX A Tcommaaccent -120
-KPX A U -50
-KPX A Uacute -50
-KPX A Ucircumflex -50
-KPX A Udieresis -50
-KPX A Ugrave -50
-KPX A Uhungarumlaut -50
-KPX A Umacron -50
-KPX A Uogonek -50
-KPX A Uring -50
-KPX A V -70
-KPX A W -50
-KPX A Y -100
-KPX A Yacute -100
-KPX A Ydieresis -100
-KPX A u -30
-KPX A uacute -30
-KPX A ucircumflex -30
-KPX A udieresis -30
-KPX A ugrave -30
-KPX A uhungarumlaut -30
-KPX A umacron -30
-KPX A uogonek -30
-KPX A uring -30
-KPX A v -40
-KPX A w -40
-KPX A y -40
-KPX A yacute -40
-KPX A ydieresis -40
-KPX Aacute C -30
-KPX Aacute Cacute -30
-KPX Aacute Ccaron -30
-KPX Aacute Ccedilla -30
-KPX Aacute G -30
-KPX Aacute Gbreve -30
-KPX Aacute Gcommaaccent -30
-KPX Aacute O -30
-KPX Aacute Oacute -30
-KPX Aacute Ocircumflex -30
-KPX Aacute Odieresis -30
-KPX Aacute Ograve -30
-KPX Aacute Ohungarumlaut -30
-KPX Aacute Omacron -30
-KPX Aacute Oslash -30
-KPX Aacute Otilde -30
-KPX Aacute Q -30
-KPX Aacute T -120
-KPX Aacute Tcaron -120
-KPX Aacute Tcommaaccent -120
-KPX Aacute U -50
-KPX Aacute Uacute -50
-KPX Aacute Ucircumflex -50
-KPX Aacute Udieresis -50
-KPX Aacute Ugrave -50
-KPX Aacute Uhungarumlaut -50
-KPX Aacute Umacron -50
-KPX Aacute Uogonek -50
-KPX Aacute Uring -50
-KPX Aacute V -70
-KPX Aacute W -50
-KPX Aacute Y -100
-KPX Aacute Yacute -100
-KPX Aacute Ydieresis -100
-KPX Aacute u -30
-KPX Aacute uacute -30
-KPX Aacute ucircumflex -30
-KPX Aacute udieresis -30
-KPX Aacute ugrave -30
-KPX Aacute uhungarumlaut -30
-KPX Aacute umacron -30
-KPX Aacute uogonek -30
-KPX Aacute uring -30
-KPX Aacute v -40
-KPX Aacute w -40
-KPX Aacute y -40
-KPX Aacute yacute -40
-KPX Aacute ydieresis -40
-KPX Abreve C -30
-KPX Abreve Cacute -30
-KPX Abreve Ccaron -30
-KPX Abreve Ccedilla -30
-KPX Abreve G -30
-KPX Abreve Gbreve -30
-KPX Abreve Gcommaaccent -30
-KPX Abreve O -30
-KPX Abreve Oacute -30
-KPX Abreve Ocircumflex -30
-KPX Abreve Odieresis -30
-KPX Abreve Ograve -30
-KPX Abreve Ohungarumlaut -30
-KPX Abreve Omacron -30
-KPX Abreve Oslash -30
-KPX Abreve Otilde -30
-KPX Abreve Q -30
-KPX Abreve T -120
-KPX Abreve Tcaron -120
-KPX Abreve Tcommaaccent -120
-KPX Abreve U -50
-KPX Abreve Uacute -50
-KPX Abreve Ucircumflex -50
-KPX Abreve Udieresis -50
-KPX Abreve Ugrave -50
-KPX Abreve Uhungarumlaut -50
-KPX Abreve Umacron -50
-KPX Abreve Uogonek -50
-KPX Abreve Uring -50
-KPX Abreve V -70
-KPX Abreve W -50
-KPX Abreve Y -100
-KPX Abreve Yacute -100
-KPX Abreve Ydieresis -100
-KPX Abreve u -30
-KPX Abreve uacute -30
-KPX Abreve ucircumflex -30
-KPX Abreve udieresis -30
-KPX Abreve ugrave -30
-KPX Abreve uhungarumlaut -30
-KPX Abreve umacron -30
-KPX Abreve uogonek -30
-KPX Abreve uring -30
-KPX Abreve v -40
-KPX Abreve w -40
-KPX Abreve y -40
-KPX Abreve yacute -40
-KPX Abreve ydieresis -40
-KPX Acircumflex C -30
-KPX Acircumflex Cacute -30
-KPX Acircumflex Ccaron -30
-KPX Acircumflex Ccedilla -30
-KPX Acircumflex G -30
-KPX Acircumflex Gbreve -30
-KPX Acircumflex Gcommaaccent -30
-KPX Acircumflex O -30
-KPX Acircumflex Oacute -30
-KPX Acircumflex Ocircumflex -30
-KPX Acircumflex Odieresis -30
-KPX Acircumflex Ograve -30
-KPX Acircumflex Ohungarumlaut -30
-KPX Acircumflex Omacron -30
-KPX Acircumflex Oslash -30
-KPX Acircumflex Otilde -30
-KPX Acircumflex Q -30
-KPX Acircumflex T -120
-KPX Acircumflex Tcaron -120
-KPX Acircumflex Tcommaaccent -120
-KPX Acircumflex U -50
-KPX Acircumflex Uacute -50
-KPX Acircumflex Ucircumflex -50
-KPX Acircumflex Udieresis -50
-KPX Acircumflex Ugrave -50
-KPX Acircumflex Uhungarumlaut -50
-KPX Acircumflex Umacron -50
-KPX Acircumflex Uogonek -50
-KPX Acircumflex Uring -50
-KPX Acircumflex V -70
-KPX Acircumflex W -50
-KPX Acircumflex Y -100
-KPX Acircumflex Yacute -100
-KPX Acircumflex Ydieresis -100
-KPX Acircumflex u -30
-KPX Acircumflex uacute -30
-KPX Acircumflex ucircumflex -30
-KPX Acircumflex udieresis -30
-KPX Acircumflex ugrave -30
-KPX Acircumflex uhungarumlaut -30
-KPX Acircumflex umacron -30
-KPX Acircumflex uogonek -30
-KPX Acircumflex uring -30
-KPX Acircumflex v -40
-KPX Acircumflex w -40
-KPX Acircumflex y -40
-KPX Acircumflex yacute -40
-KPX Acircumflex ydieresis -40
-KPX Adieresis C -30
-KPX Adieresis Cacute -30
-KPX Adieresis Ccaron -30
-KPX Adieresis Ccedilla -30
-KPX Adieresis G -30
-KPX Adieresis Gbreve -30
-KPX Adieresis Gcommaaccent -30
-KPX Adieresis O -30
-KPX Adieresis Oacute -30
-KPX Adieresis Ocircumflex -30
-KPX Adieresis Odieresis -30
-KPX Adieresis Ograve -30
-KPX Adieresis Ohungarumlaut -30
-KPX Adieresis Omacron -30
-KPX Adieresis Oslash -30
-KPX Adieresis Otilde -30
-KPX Adieresis Q -30
-KPX Adieresis T -120
-KPX Adieresis Tcaron -120
-KPX Adieresis Tcommaaccent -120
-KPX Adieresis U -50
-KPX Adieresis Uacute -50
-KPX Adieresis Ucircumflex -50
-KPX Adieresis Udieresis -50
-KPX Adieresis Ugrave -50
-KPX Adieresis Uhungarumlaut -50
-KPX Adieresis Umacron -50
-KPX Adieresis Uogonek -50
-KPX Adieresis Uring -50
-KPX Adieresis V -70
-KPX Adieresis W -50
-KPX Adieresis Y -100
-KPX Adieresis Yacute -100
-KPX Adieresis Ydieresis -100
-KPX Adieresis u -30
-KPX Adieresis uacute -30
-KPX Adieresis ucircumflex -30
-KPX Adieresis udieresis -30
-KPX Adieresis ugrave -30
-KPX Adieresis uhungarumlaut -30
-KPX Adieresis umacron -30
-KPX Adieresis uogonek -30
-KPX Adieresis uring -30
-KPX Adieresis v -40
-KPX Adieresis w -40
-KPX Adieresis y -40
-KPX Adieresis yacute -40
-KPX Adieresis ydieresis -40
-KPX Agrave C -30
-KPX Agrave Cacute -30
-KPX Agrave Ccaron -30
-KPX Agrave Ccedilla -30
-KPX Agrave G -30
-KPX Agrave Gbreve -30
-KPX Agrave Gcommaaccent -30
-KPX Agrave O -30
-KPX Agrave Oacute -30
-KPX Agrave Ocircumflex -30
-KPX Agrave Odieresis -30
-KPX Agrave Ograve -30
-KPX Agrave Ohungarumlaut -30
-KPX Agrave Omacron -30
-KPX Agrave Oslash -30
-KPX Agrave Otilde -30
-KPX Agrave Q -30
-KPX Agrave T -120
-KPX Agrave Tcaron -120
-KPX Agrave Tcommaaccent -120
-KPX Agrave U -50
-KPX Agrave Uacute -50
-KPX Agrave Ucircumflex -50
-KPX Agrave Udieresis -50
-KPX Agrave Ugrave -50
-KPX Agrave Uhungarumlaut -50
-KPX Agrave Umacron -50
-KPX Agrave Uogonek -50
-KPX Agrave Uring -50
-KPX Agrave V -70
-KPX Agrave W -50
-KPX Agrave Y -100
-KPX Agrave Yacute -100
-KPX Agrave Ydieresis -100
-KPX Agrave u -30
-KPX Agrave uacute -30
-KPX Agrave ucircumflex -30
-KPX Agrave udieresis -30
-KPX Agrave ugrave -30
-KPX Agrave uhungarumlaut -30
-KPX Agrave umacron -30
-KPX Agrave uogonek -30
-KPX Agrave uring -30
-KPX Agrave v -40
-KPX Agrave w -40
-KPX Agrave y -40
-KPX Agrave yacute -40
-KPX Agrave ydieresis -40
-KPX Amacron C -30
-KPX Amacron Cacute -30
-KPX Amacron Ccaron -30
-KPX Amacron Ccedilla -30
-KPX Amacron G -30
-KPX Amacron Gbreve -30
-KPX Amacron Gcommaaccent -30
-KPX Amacron O -30
-KPX Amacron Oacute -30
-KPX Amacron Ocircumflex -30
-KPX Amacron Odieresis -30
-KPX Amacron Ograve -30
-KPX Amacron Ohungarumlaut -30
-KPX Amacron Omacron -30
-KPX Amacron Oslash -30
-KPX Amacron Otilde -30
-KPX Amacron Q -30
-KPX Amacron T -120
-KPX Amacron Tcaron -120
-KPX Amacron Tcommaaccent -120
-KPX Amacron U -50
-KPX Amacron Uacute -50
-KPX Amacron Ucircumflex -50
-KPX Amacron Udieresis -50
-KPX Amacron Ugrave -50
-KPX Amacron Uhungarumlaut -50
-KPX Amacron Umacron -50
-KPX Amacron Uogonek -50
-KPX Amacron Uring -50
-KPX Amacron V -70
-KPX Amacron W -50
-KPX Amacron Y -100
-KPX Amacron Yacute -100
-KPX Amacron Ydieresis -100
-KPX Amacron u -30
-KPX Amacron uacute -30
-KPX Amacron ucircumflex -30
-KPX Amacron udieresis -30
-KPX Amacron ugrave -30
-KPX Amacron uhungarumlaut -30
-KPX Amacron umacron -30
-KPX Amacron uogonek -30
-KPX Amacron uring -30
-KPX Amacron v -40
-KPX Amacron w -40
-KPX Amacron y -40
-KPX Amacron yacute -40
-KPX Amacron ydieresis -40
-KPX Aogonek C -30
-KPX Aogonek Cacute -30
-KPX Aogonek Ccaron -30
-KPX Aogonek Ccedilla -30
-KPX Aogonek G -30
-KPX Aogonek Gbreve -30
-KPX Aogonek Gcommaaccent -30
-KPX Aogonek O -30
-KPX Aogonek Oacute -30
-KPX Aogonek Ocircumflex -30
-KPX Aogonek Odieresis -30
-KPX Aogonek Ograve -30
-KPX Aogonek Ohungarumlaut -30
-KPX Aogonek Omacron -30
-KPX Aogonek Oslash -30
-KPX Aogonek Otilde -30
-KPX Aogonek Q -30
-KPX Aogonek T -120
-KPX Aogonek Tcaron -120
-KPX Aogonek Tcommaaccent -120
-KPX Aogonek U -50
-KPX Aogonek Uacute -50
-KPX Aogonek Ucircumflex -50
-KPX Aogonek Udieresis -50
-KPX Aogonek Ugrave -50
-KPX Aogonek Uhungarumlaut -50
-KPX Aogonek Umacron -50
-KPX Aogonek Uogonek -50
-KPX Aogonek Uring -50
-KPX Aogonek V -70
-KPX Aogonek W -50
-KPX Aogonek Y -100
-KPX Aogonek Yacute -100
-KPX Aogonek Ydieresis -100
-KPX Aogonek u -30
-KPX Aogonek uacute -30
-KPX Aogonek ucircumflex -30
-KPX Aogonek udieresis -30
-KPX Aogonek ugrave -30
-KPX Aogonek uhungarumlaut -30
-KPX Aogonek umacron -30
-KPX Aogonek uogonek -30
-KPX Aogonek uring -30
-KPX Aogonek v -40
-KPX Aogonek w -40
-KPX Aogonek y -40
-KPX Aogonek yacute -40
-KPX Aogonek ydieresis -40
-KPX Aring C -30
-KPX Aring Cacute -30
-KPX Aring Ccaron -30
-KPX Aring Ccedilla -30
-KPX Aring G -30
-KPX Aring Gbreve -30
-KPX Aring Gcommaaccent -30
-KPX Aring O -30
-KPX Aring Oacute -30
-KPX Aring Ocircumflex -30
-KPX Aring Odieresis -30
-KPX Aring Ograve -30
-KPX Aring Ohungarumlaut -30
-KPX Aring Omacron -30
-KPX Aring Oslash -30
-KPX Aring Otilde -30
-KPX Aring Q -30
-KPX Aring T -120
-KPX Aring Tcaron -120
-KPX Aring Tcommaaccent -120
-KPX Aring U -50
-KPX Aring Uacute -50
-KPX Aring Ucircumflex -50
-KPX Aring Udieresis -50
-KPX Aring Ugrave -50
-KPX Aring Uhungarumlaut -50
-KPX Aring Umacron -50
-KPX Aring Uogonek -50
-KPX Aring Uring -50
-KPX Aring V -70
-KPX Aring W -50
-KPX Aring Y -100
-KPX Aring Yacute -100
-KPX Aring Ydieresis -100
-KPX Aring u -30
-KPX Aring uacute -30
-KPX Aring ucircumflex -30
-KPX Aring udieresis -30
-KPX Aring ugrave -30
-KPX Aring uhungarumlaut -30
-KPX Aring umacron -30
-KPX Aring uogonek -30
-KPX Aring uring -30
-KPX Aring v -40
-KPX Aring w -40
-KPX Aring y -40
-KPX Aring yacute -40
-KPX Aring ydieresis -40
-KPX Atilde C -30
-KPX Atilde Cacute -30
-KPX Atilde Ccaron -30
-KPX Atilde Ccedilla -30
-KPX Atilde G -30
-KPX Atilde Gbreve -30
-KPX Atilde Gcommaaccent -30
-KPX Atilde O -30
-KPX Atilde Oacute -30
-KPX Atilde Ocircumflex -30
-KPX Atilde Odieresis -30
-KPX Atilde Ograve -30
-KPX Atilde Ohungarumlaut -30
-KPX Atilde Omacron -30
-KPX Atilde Oslash -30
-KPX Atilde Otilde -30
-KPX Atilde Q -30
-KPX Atilde T -120
-KPX Atilde Tcaron -120
-KPX Atilde Tcommaaccent -120
-KPX Atilde U -50
-KPX Atilde Uacute -50
-KPX Atilde Ucircumflex -50
-KPX Atilde Udieresis -50
-KPX Atilde Ugrave -50
-KPX Atilde Uhungarumlaut -50
-KPX Atilde Umacron -50
-KPX Atilde Uogonek -50
-KPX Atilde Uring -50
-KPX Atilde V -70
-KPX Atilde W -50
-KPX Atilde Y -100
-KPX Atilde Yacute -100
-KPX Atilde Ydieresis -100
-KPX Atilde u -30
-KPX Atilde uacute -30
-KPX Atilde ucircumflex -30
-KPX Atilde udieresis -30
-KPX Atilde ugrave -30
-KPX Atilde uhungarumlaut -30
-KPX Atilde umacron -30
-KPX Atilde uogonek -30
-KPX Atilde uring -30
-KPX Atilde v -40
-KPX Atilde w -40
-KPX Atilde y -40
-KPX Atilde yacute -40
-KPX Atilde ydieresis -40
-KPX B U -10
-KPX B Uacute -10
-KPX B Ucircumflex -10
-KPX B Udieresis -10
-KPX B Ugrave -10
-KPX B Uhungarumlaut -10
-KPX B Umacron -10
-KPX B Uogonek -10
-KPX B Uring -10
-KPX B comma -20
-KPX B period -20
-KPX C comma -30
-KPX C period -30
-KPX Cacute comma -30
-KPX Cacute period -30
-KPX Ccaron comma -30
-KPX Ccaron period -30
-KPX Ccedilla comma -30
-KPX Ccedilla period -30
-KPX D A -40
-KPX D Aacute -40
-KPX D Abreve -40
-KPX D Acircumflex -40
-KPX D Adieresis -40
-KPX D Agrave -40
-KPX D Amacron -40
-KPX D Aogonek -40
-KPX D Aring -40
-KPX D Atilde -40
-KPX D V -70
-KPX D W -40
-KPX D Y -90
-KPX D Yacute -90
-KPX D Ydieresis -90
-KPX D comma -70
-KPX D period -70
-KPX Dcaron A -40
-KPX Dcaron Aacute -40
-KPX Dcaron Abreve -40
-KPX Dcaron Acircumflex -40
-KPX Dcaron Adieresis -40
-KPX Dcaron Agrave -40
-KPX Dcaron Amacron -40
-KPX Dcaron Aogonek -40
-KPX Dcaron Aring -40
-KPX Dcaron Atilde -40
-KPX Dcaron V -70
-KPX Dcaron W -40
-KPX Dcaron Y -90
-KPX Dcaron Yacute -90
-KPX Dcaron Ydieresis -90
-KPX Dcaron comma -70
-KPX Dcaron period -70
-KPX Dcroat A -40
-KPX Dcroat Aacute -40
-KPX Dcroat Abreve -40
-KPX Dcroat Acircumflex -40
-KPX Dcroat Adieresis -40
-KPX Dcroat Agrave -40
-KPX Dcroat Amacron -40
-KPX Dcroat Aogonek -40
-KPX Dcroat Aring -40
-KPX Dcroat Atilde -40
-KPX Dcroat V -70
-KPX Dcroat W -40
-KPX Dcroat Y -90
-KPX Dcroat Yacute -90
-KPX Dcroat Ydieresis -90
-KPX Dcroat comma -70
-KPX Dcroat period -70
-KPX F A -80
-KPX F Aacute -80
-KPX F Abreve -80
-KPX F Acircumflex -80
-KPX F Adieresis -80
-KPX F Agrave -80
-KPX F Amacron -80
-KPX F Aogonek -80
-KPX F Aring -80
-KPX F Atilde -80
-KPX F a -50
-KPX F aacute -50
-KPX F abreve -50
-KPX F acircumflex -50
-KPX F adieresis -50
-KPX F agrave -50
-KPX F amacron -50
-KPX F aogonek -50
-KPX F aring -50
-KPX F atilde -50
-KPX F comma -150
-KPX F e -30
-KPX F eacute -30
-KPX F ecaron -30
-KPX F ecircumflex -30
-KPX F edieresis -30
-KPX F edotaccent -30
-KPX F egrave -30
-KPX F emacron -30
-KPX F eogonek -30
-KPX F o -30
-KPX F oacute -30
-KPX F ocircumflex -30
-KPX F odieresis -30
-KPX F ograve -30
-KPX F ohungarumlaut -30
-KPX F omacron -30
-KPX F oslash -30
-KPX F otilde -30
-KPX F period -150
-KPX F r -45
-KPX F racute -45
-KPX F rcaron -45
-KPX F rcommaaccent -45
-KPX J A -20
-KPX J Aacute -20
-KPX J Abreve -20
-KPX J Acircumflex -20
-KPX J Adieresis -20
-KPX J Agrave -20
-KPX J Amacron -20
-KPX J Aogonek -20
-KPX J Aring -20
-KPX J Atilde -20
-KPX J a -20
-KPX J aacute -20
-KPX J abreve -20
-KPX J acircumflex -20
-KPX J adieresis -20
-KPX J agrave -20
-KPX J amacron -20
-KPX J aogonek -20
-KPX J aring -20
-KPX J atilde -20
-KPX J comma -30
-KPX J period -30
-KPX J u -20
-KPX J uacute -20
-KPX J ucircumflex -20
-KPX J udieresis -20
-KPX J ugrave -20
-KPX J uhungarumlaut -20
-KPX J umacron -20
-KPX J uogonek -20
-KPX J uring -20
-KPX K O -50
-KPX K Oacute -50
-KPX K Ocircumflex -50
-KPX K Odieresis -50
-KPX K Ograve -50
-KPX K Ohungarumlaut -50
-KPX K Omacron -50
-KPX K Oslash -50
-KPX K Otilde -50
-KPX K e -40
-KPX K eacute -40
-KPX K ecaron -40
-KPX K ecircumflex -40
-KPX K edieresis -40
-KPX K edotaccent -40
-KPX K egrave -40
-KPX K emacron -40
-KPX K eogonek -40
-KPX K o -40
-KPX K oacute -40
-KPX K ocircumflex -40
-KPX K odieresis -40
-KPX K ograve -40
-KPX K ohungarumlaut -40
-KPX K omacron -40
-KPX K oslash -40
-KPX K otilde -40
-KPX K u -30
-KPX K uacute -30
-KPX K ucircumflex -30
-KPX K udieresis -30
-KPX K ugrave -30
-KPX K uhungarumlaut -30
-KPX K umacron -30
-KPX K uogonek -30
-KPX K uring -30
-KPX K y -50
-KPX K yacute -50
-KPX K ydieresis -50
-KPX Kcommaaccent O -50
-KPX Kcommaaccent Oacute -50
-KPX Kcommaaccent Ocircumflex -50
-KPX Kcommaaccent Odieresis -50
-KPX Kcommaaccent Ograve -50
-KPX Kcommaaccent Ohungarumlaut -50
-KPX Kcommaaccent Omacron -50
-KPX Kcommaaccent Oslash -50
-KPX Kcommaaccent Otilde -50
-KPX Kcommaaccent e -40
-KPX Kcommaaccent eacute -40
-KPX Kcommaaccent ecaron -40
-KPX Kcommaaccent ecircumflex -40
-KPX Kcommaaccent edieresis -40
-KPX Kcommaaccent edotaccent -40
-KPX Kcommaaccent egrave -40
-KPX Kcommaaccent emacron -40
-KPX Kcommaaccent eogonek -40
-KPX Kcommaaccent o -40
-KPX Kcommaaccent oacute -40
-KPX Kcommaaccent ocircumflex -40
-KPX Kcommaaccent odieresis -40
-KPX Kcommaaccent ograve -40
-KPX Kcommaaccent ohungarumlaut -40
-KPX Kcommaaccent omacron -40
-KPX Kcommaaccent oslash -40
-KPX Kcommaaccent otilde -40
-KPX Kcommaaccent u -30
-KPX Kcommaaccent uacute -30
-KPX Kcommaaccent ucircumflex -30
-KPX Kcommaaccent udieresis -30
-KPX Kcommaaccent ugrave -30
-KPX Kcommaaccent uhungarumlaut -30
-KPX Kcommaaccent umacron -30
-KPX Kcommaaccent uogonek -30
-KPX Kcommaaccent uring -30
-KPX Kcommaaccent y -50
-KPX Kcommaaccent yacute -50
-KPX Kcommaaccent ydieresis -50
-KPX L T -110
-KPX L Tcaron -110
-KPX L Tcommaaccent -110
-KPX L V -110
-KPX L W -70
-KPX L Y -140
-KPX L Yacute -140
-KPX L Ydieresis -140
-KPX L quotedblright -140
-KPX L quoteright -160
-KPX L y -30
-KPX L yacute -30
-KPX L ydieresis -30
-KPX Lacute T -110
-KPX Lacute Tcaron -110
-KPX Lacute Tcommaaccent -110
-KPX Lacute V -110
-KPX Lacute W -70
-KPX Lacute Y -140
-KPX Lacute Yacute -140
-KPX Lacute Ydieresis -140
-KPX Lacute quotedblright -140
-KPX Lacute quoteright -160
-KPX Lacute y -30
-KPX Lacute yacute -30
-KPX Lacute ydieresis -30
-KPX Lcaron T -110
-KPX Lcaron Tcaron -110
-KPX Lcaron Tcommaaccent -110
-KPX Lcaron V -110
-KPX Lcaron W -70
-KPX Lcaron Y -140
-KPX Lcaron Yacute -140
-KPX Lcaron Ydieresis -140
-KPX Lcaron quotedblright -140
-KPX Lcaron quoteright -160
-KPX Lcaron y -30
-KPX Lcaron yacute -30
-KPX Lcaron ydieresis -30
-KPX Lcommaaccent T -110
-KPX Lcommaaccent Tcaron -110
-KPX Lcommaaccent Tcommaaccent -110
-KPX Lcommaaccent V -110
-KPX Lcommaaccent W -70
-KPX Lcommaaccent Y -140
-KPX Lcommaaccent Yacute -140
-KPX Lcommaaccent Ydieresis -140
-KPX Lcommaaccent quotedblright -140
-KPX Lcommaaccent quoteright -160
-KPX Lcommaaccent y -30
-KPX Lcommaaccent yacute -30
-KPX Lcommaaccent ydieresis -30
-KPX Lslash T -110
-KPX Lslash Tcaron -110
-KPX Lslash Tcommaaccent -110
-KPX Lslash V -110
-KPX Lslash W -70
-KPX Lslash Y -140
-KPX Lslash Yacute -140
-KPX Lslash Ydieresis -140
-KPX Lslash quotedblright -140
-KPX Lslash quoteright -160
-KPX Lslash y -30
-KPX Lslash yacute -30
-KPX Lslash ydieresis -30
-KPX O A -20
-KPX O Aacute -20
-KPX O Abreve -20
-KPX O Acircumflex -20
-KPX O Adieresis -20
-KPX O Agrave -20
-KPX O Amacron -20
-KPX O Aogonek -20
-KPX O Aring -20
-KPX O Atilde -20
-KPX O T -40
-KPX O Tcaron -40
-KPX O Tcommaaccent -40
-KPX O V -50
-KPX O W -30
-KPX O X -60
-KPX O Y -70
-KPX O Yacute -70
-KPX O Ydieresis -70
-KPX O comma -40
-KPX O period -40
-KPX Oacute A -20
-KPX Oacute Aacute -20
-KPX Oacute Abreve -20
-KPX Oacute Acircumflex -20
-KPX Oacute Adieresis -20
-KPX Oacute Agrave -20
-KPX Oacute Amacron -20
-KPX Oacute Aogonek -20
-KPX Oacute Aring -20
-KPX Oacute Atilde -20
-KPX Oacute T -40
-KPX Oacute Tcaron -40
-KPX Oacute Tcommaaccent -40
-KPX Oacute V -50
-KPX Oacute W -30
-KPX Oacute X -60
-KPX Oacute Y -70
-KPX Oacute Yacute -70
-KPX Oacute Ydieresis -70
-KPX Oacute comma -40
-KPX Oacute period -40
-KPX Ocircumflex A -20
-KPX Ocircumflex Aacute -20
-KPX Ocircumflex Abreve -20
-KPX Ocircumflex Acircumflex -20
-KPX Ocircumflex Adieresis -20
-KPX Ocircumflex Agrave -20
-KPX Ocircumflex Amacron -20
-KPX Ocircumflex Aogonek -20
-KPX Ocircumflex Aring -20
-KPX Ocircumflex Atilde -20
-KPX Ocircumflex T -40
-KPX Ocircumflex Tcaron -40
-KPX Ocircumflex Tcommaaccent -40
-KPX Ocircumflex V -50
-KPX Ocircumflex W -30
-KPX Ocircumflex X -60
-KPX Ocircumflex Y -70
-KPX Ocircumflex Yacute -70
-KPX Ocircumflex Ydieresis -70
-KPX Ocircumflex comma -40
-KPX Ocircumflex period -40
-KPX Odieresis A -20
-KPX Odieresis Aacute -20
-KPX Odieresis Abreve -20
-KPX Odieresis Acircumflex -20
-KPX Odieresis Adieresis -20
-KPX Odieresis Agrave -20
-KPX Odieresis Amacron -20
-KPX Odieresis Aogonek -20
-KPX Odieresis Aring -20
-KPX Odieresis Atilde -20
-KPX Odieresis T -40
-KPX Odieresis Tcaron -40
-KPX Odieresis Tcommaaccent -40
-KPX Odieresis V -50
-KPX Odieresis W -30
-KPX Odieresis X -60
-KPX Odieresis Y -70
-KPX Odieresis Yacute -70
-KPX Odieresis Ydieresis -70
-KPX Odieresis comma -40
-KPX Odieresis period -40
-KPX Ograve A -20
-KPX Ograve Aacute -20
-KPX Ograve Abreve -20
-KPX Ograve Acircumflex -20
-KPX Ograve Adieresis -20
-KPX Ograve Agrave -20
-KPX Ograve Amacron -20
-KPX Ograve Aogonek -20
-KPX Ograve Aring -20
-KPX Ograve Atilde -20
-KPX Ograve T -40
-KPX Ograve Tcaron -40
-KPX Ograve Tcommaaccent -40
-KPX Ograve V -50
-KPX Ograve W -30
-KPX Ograve X -60
-KPX Ograve Y -70
-KPX Ograve Yacute -70
-KPX Ograve Ydieresis -70
-KPX Ograve comma -40
-KPX Ograve period -40
-KPX Ohungarumlaut A -20
-KPX Ohungarumlaut Aacute -20
-KPX Ohungarumlaut Abreve -20
-KPX Ohungarumlaut Acircumflex -20
-KPX Ohungarumlaut Adieresis -20
-KPX Ohungarumlaut Agrave -20
-KPX Ohungarumlaut Amacron -20
-KPX Ohungarumlaut Aogonek -20
-KPX Ohungarumlaut Aring -20
-KPX Ohungarumlaut Atilde -20
-KPX Ohungarumlaut T -40
-KPX Ohungarumlaut Tcaron -40
-KPX Ohungarumlaut Tcommaaccent -40
-KPX Ohungarumlaut V -50
-KPX Ohungarumlaut W -30
-KPX Ohungarumlaut X -60
-KPX Ohungarumlaut Y -70
-KPX Ohungarumlaut Yacute -70
-KPX Ohungarumlaut Ydieresis -70
-KPX Ohungarumlaut comma -40
-KPX Ohungarumlaut period -40
-KPX Omacron A -20
-KPX Omacron Aacute -20
-KPX Omacron Abreve -20
-KPX Omacron Acircumflex -20
-KPX Omacron Adieresis -20
-KPX Omacron Agrave -20
-KPX Omacron Amacron -20
-KPX Omacron Aogonek -20
-KPX Omacron Aring -20
-KPX Omacron Atilde -20
-KPX Omacron T -40
-KPX Omacron Tcaron -40
-KPX Omacron Tcommaaccent -40
-KPX Omacron V -50
-KPX Omacron W -30
-KPX Omacron X -60
-KPX Omacron Y -70
-KPX Omacron Yacute -70
-KPX Omacron Ydieresis -70
-KPX Omacron comma -40
-KPX Omacron period -40
-KPX Oslash A -20
-KPX Oslash Aacute -20
-KPX Oslash Abreve -20
-KPX Oslash Acircumflex -20
-KPX Oslash Adieresis -20
-KPX Oslash Agrave -20
-KPX Oslash Amacron -20
-KPX Oslash Aogonek -20
-KPX Oslash Aring -20
-KPX Oslash Atilde -20
-KPX Oslash T -40
-KPX Oslash Tcaron -40
-KPX Oslash Tcommaaccent -40
-KPX Oslash V -50
-KPX Oslash W -30
-KPX Oslash X -60
-KPX Oslash Y -70
-KPX Oslash Yacute -70
-KPX Oslash Ydieresis -70
-KPX Oslash comma -40
-KPX Oslash period -40
-KPX Otilde A -20
-KPX Otilde Aacute -20
-KPX Otilde Abreve -20
-KPX Otilde Acircumflex -20
-KPX Otilde Adieresis -20
-KPX Otilde Agrave -20
-KPX Otilde Amacron -20
-KPX Otilde Aogonek -20
-KPX Otilde Aring -20
-KPX Otilde Atilde -20
-KPX Otilde T -40
-KPX Otilde Tcaron -40
-KPX Otilde Tcommaaccent -40
-KPX Otilde V -50
-KPX Otilde W -30
-KPX Otilde X -60
-KPX Otilde Y -70
-KPX Otilde Yacute -70
-KPX Otilde Ydieresis -70
-KPX Otilde comma -40
-KPX Otilde period -40
-KPX P A -120
-KPX P Aacute -120
-KPX P Abreve -120
-KPX P Acircumflex -120
-KPX P Adieresis -120
-KPX P Agrave -120
-KPX P Amacron -120
-KPX P Aogonek -120
-KPX P Aring -120
-KPX P Atilde -120
-KPX P a -40
-KPX P aacute -40
-KPX P abreve -40
-KPX P acircumflex -40
-KPX P adieresis -40
-KPX P agrave -40
-KPX P amacron -40
-KPX P aogonek -40
-KPX P aring -40
-KPX P atilde -40
-KPX P comma -180
-KPX P e -50
-KPX P eacute -50
-KPX P ecaron -50
-KPX P ecircumflex -50
-KPX P edieresis -50
-KPX P edotaccent -50
-KPX P egrave -50
-KPX P emacron -50
-KPX P eogonek -50
-KPX P o -50
-KPX P oacute -50
-KPX P ocircumflex -50
-KPX P odieresis -50
-KPX P ograve -50
-KPX P ohungarumlaut -50
-KPX P omacron -50
-KPX P oslash -50
-KPX P otilde -50
-KPX P period -180
-KPX Q U -10
-KPX Q Uacute -10
-KPX Q Ucircumflex -10
-KPX Q Udieresis -10
-KPX Q Ugrave -10
-KPX Q Uhungarumlaut -10
-KPX Q Umacron -10
-KPX Q Uogonek -10
-KPX Q Uring -10
-KPX R O -20
-KPX R Oacute -20
-KPX R Ocircumflex -20
-KPX R Odieresis -20
-KPX R Ograve -20
-KPX R Ohungarumlaut -20
-KPX R Omacron -20
-KPX R Oslash -20
-KPX R Otilde -20
-KPX R T -30
-KPX R Tcaron -30
-KPX R Tcommaaccent -30
-KPX R U -40
-KPX R Uacute -40
-KPX R Ucircumflex -40
-KPX R Udieresis -40
-KPX R Ugrave -40
-KPX R Uhungarumlaut -40
-KPX R Umacron -40
-KPX R Uogonek -40
-KPX R Uring -40
-KPX R V -50
-KPX R W -30
-KPX R Y -50
-KPX R Yacute -50
-KPX R Ydieresis -50
-KPX Racute O -20
-KPX Racute Oacute -20
-KPX Racute Ocircumflex -20
-KPX Racute Odieresis -20
-KPX Racute Ograve -20
-KPX Racute Ohungarumlaut -20
-KPX Racute Omacron -20
-KPX Racute Oslash -20
-KPX Racute Otilde -20
-KPX Racute T -30
-KPX Racute Tcaron -30
-KPX Racute Tcommaaccent -30
-KPX Racute U -40
-KPX Racute Uacute -40
-KPX Racute Ucircumflex -40
-KPX Racute Udieresis -40
-KPX Racute Ugrave -40
-KPX Racute Uhungarumlaut -40
-KPX Racute Umacron -40
-KPX Racute Uogonek -40
-KPX Racute Uring -40
-KPX Racute V -50
-KPX Racute W -30
-KPX Racute Y -50
-KPX Racute Yacute -50
-KPX Racute Ydieresis -50
-KPX Rcaron O -20
-KPX Rcaron Oacute -20
-KPX Rcaron Ocircumflex -20
-KPX Rcaron Odieresis -20
-KPX Rcaron Ograve -20
-KPX Rcaron Ohungarumlaut -20
-KPX Rcaron Omacron -20
-KPX Rcaron Oslash -20
-KPX Rcaron Otilde -20
-KPX Rcaron T -30
-KPX Rcaron Tcaron -30
-KPX Rcaron Tcommaaccent -30
-KPX Rcaron U -40
-KPX Rcaron Uacute -40
-KPX Rcaron Ucircumflex -40
-KPX Rcaron Udieresis -40
-KPX Rcaron Ugrave -40
-KPX Rcaron Uhungarumlaut -40
-KPX Rcaron Umacron -40
-KPX Rcaron Uogonek -40
-KPX Rcaron Uring -40
-KPX Rcaron V -50
-KPX Rcaron W -30
-KPX Rcaron Y -50
-KPX Rcaron Yacute -50
-KPX Rcaron Ydieresis -50
-KPX Rcommaaccent O -20
-KPX Rcommaaccent Oacute -20
-KPX Rcommaaccent Ocircumflex -20
-KPX Rcommaaccent Odieresis -20
-KPX Rcommaaccent Ograve -20
-KPX Rcommaaccent Ohungarumlaut -20
-KPX Rcommaaccent Omacron -20
-KPX Rcommaaccent Oslash -20
-KPX Rcommaaccent Otilde -20
-KPX Rcommaaccent T -30
-KPX Rcommaaccent Tcaron -30
-KPX Rcommaaccent Tcommaaccent -30
-KPX Rcommaaccent U -40
-KPX Rcommaaccent Uacute -40
-KPX Rcommaaccent Ucircumflex -40
-KPX Rcommaaccent Udieresis -40
-KPX Rcommaaccent Ugrave -40
-KPX Rcommaaccent Uhungarumlaut -40
-KPX Rcommaaccent Umacron -40
-KPX Rcommaaccent Uogonek -40
-KPX Rcommaaccent Uring -40
-KPX Rcommaaccent V -50
-KPX Rcommaaccent W -30
-KPX Rcommaaccent Y -50
-KPX Rcommaaccent Yacute -50
-KPX Rcommaaccent Ydieresis -50
-KPX S comma -20
-KPX S period -20
-KPX Sacute comma -20
-KPX Sacute period -20
-KPX Scaron comma -20
-KPX Scaron period -20
-KPX Scedilla comma -20
-KPX Scedilla period -20
-KPX Scommaaccent comma -20
-KPX Scommaaccent period -20
-KPX T A -120
-KPX T Aacute -120
-KPX T Abreve -120
-KPX T Acircumflex -120
-KPX T Adieresis -120
-KPX T Agrave -120
-KPX T Amacron -120
-KPX T Aogonek -120
-KPX T Aring -120
-KPX T Atilde -120
-KPX T O -40
-KPX T Oacute -40
-KPX T Ocircumflex -40
-KPX T Odieresis -40
-KPX T Ograve -40
-KPX T Ohungarumlaut -40
-KPX T Omacron -40
-KPX T Oslash -40
-KPX T Otilde -40
-KPX T a -120
-KPX T aacute -120
-KPX T abreve -60
-KPX T acircumflex -120
-KPX T adieresis -120
-KPX T agrave -120
-KPX T amacron -60
-KPX T aogonek -120
-KPX T aring -120
-KPX T atilde -60
-KPX T colon -20
-KPX T comma -120
-KPX T e -120
-KPX T eacute -120
-KPX T ecaron -120
-KPX T ecircumflex -120
-KPX T edieresis -120
-KPX T edotaccent -120
-KPX T egrave -60
-KPX T emacron -60
-KPX T eogonek -120
-KPX T hyphen -140
-KPX T o -120
-KPX T oacute -120
-KPX T ocircumflex -120
-KPX T odieresis -120
-KPX T ograve -120
-KPX T ohungarumlaut -120
-KPX T omacron -60
-KPX T oslash -120
-KPX T otilde -60
-KPX T period -120
-KPX T r -120
-KPX T racute -120
-KPX T rcaron -120
-KPX T rcommaaccent -120
-KPX T semicolon -20
-KPX T u -120
-KPX T uacute -120
-KPX T ucircumflex -120
-KPX T udieresis -120
-KPX T ugrave -120
-KPX T uhungarumlaut -120
-KPX T umacron -60
-KPX T uogonek -120
-KPX T uring -120
-KPX T w -120
-KPX T y -120
-KPX T yacute -120
-KPX T ydieresis -60
-KPX Tcaron A -120
-KPX Tcaron Aacute -120
-KPX Tcaron Abreve -120
-KPX Tcaron Acircumflex -120
-KPX Tcaron Adieresis -120
-KPX Tcaron Agrave -120
-KPX Tcaron Amacron -120
-KPX Tcaron Aogonek -120
-KPX Tcaron Aring -120
-KPX Tcaron Atilde -120
-KPX Tcaron O -40
-KPX Tcaron Oacute -40
-KPX Tcaron Ocircumflex -40
-KPX Tcaron Odieresis -40
-KPX Tcaron Ograve -40
-KPX Tcaron Ohungarumlaut -40
-KPX Tcaron Omacron -40
-KPX Tcaron Oslash -40
-KPX Tcaron Otilde -40
-KPX Tcaron a -120
-KPX Tcaron aacute -120
-KPX Tcaron abreve -60
-KPX Tcaron acircumflex -120
-KPX Tcaron adieresis -120
-KPX Tcaron agrave -120
-KPX Tcaron amacron -60
-KPX Tcaron aogonek -120
-KPX Tcaron aring -120
-KPX Tcaron atilde -60
-KPX Tcaron colon -20
-KPX Tcaron comma -120
-KPX Tcaron e -120
-KPX Tcaron eacute -120
-KPX Tcaron ecaron -120
-KPX Tcaron ecircumflex -120
-KPX Tcaron edieresis -120
-KPX Tcaron edotaccent -120
-KPX Tcaron egrave -60
-KPX Tcaron emacron -60
-KPX Tcaron eogonek -120
-KPX Tcaron hyphen -140
-KPX Tcaron o -120
-KPX Tcaron oacute -120
-KPX Tcaron ocircumflex -120
-KPX Tcaron odieresis -120
-KPX Tcaron ograve -120
-KPX Tcaron ohungarumlaut -120
-KPX Tcaron omacron -60
-KPX Tcaron oslash -120
-KPX Tcaron otilde -60
-KPX Tcaron period -120
-KPX Tcaron r -120
-KPX Tcaron racute -120
-KPX Tcaron rcaron -120
-KPX Tcaron rcommaaccent -120
-KPX Tcaron semicolon -20
-KPX Tcaron u -120
-KPX Tcaron uacute -120
-KPX Tcaron ucircumflex -120
-KPX Tcaron udieresis -120
-KPX Tcaron ugrave -120
-KPX Tcaron uhungarumlaut -120
-KPX Tcaron umacron -60
-KPX Tcaron uogonek -120
-KPX Tcaron uring -120
-KPX Tcaron w -120
-KPX Tcaron y -120
-KPX Tcaron yacute -120
-KPX Tcaron ydieresis -60
-KPX Tcommaaccent A -120
-KPX Tcommaaccent Aacute -120
-KPX Tcommaaccent Abreve -120
-KPX Tcommaaccent Acircumflex -120
-KPX Tcommaaccent Adieresis -120
-KPX Tcommaaccent Agrave -120
-KPX Tcommaaccent Amacron -120
-KPX Tcommaaccent Aogonek -120
-KPX Tcommaaccent Aring -120
-KPX Tcommaaccent Atilde -120
-KPX Tcommaaccent O -40
-KPX Tcommaaccent Oacute -40
-KPX Tcommaaccent Ocircumflex -40
-KPX Tcommaaccent Odieresis -40
-KPX Tcommaaccent Ograve -40
-KPX Tcommaaccent Ohungarumlaut -40
-KPX Tcommaaccent Omacron -40
-KPX Tcommaaccent Oslash -40
-KPX Tcommaaccent Otilde -40
-KPX Tcommaaccent a -120
-KPX Tcommaaccent aacute -120
-KPX Tcommaaccent abreve -60
-KPX Tcommaaccent acircumflex -120
-KPX Tcommaaccent adieresis -120
-KPX Tcommaaccent agrave -120
-KPX Tcommaaccent amacron -60
-KPX Tcommaaccent aogonek -120
-KPX Tcommaaccent aring -120
-KPX Tcommaaccent atilde -60
-KPX Tcommaaccent colon -20
-KPX Tcommaaccent comma -120
-KPX Tcommaaccent e -120
-KPX Tcommaaccent eacute -120
-KPX Tcommaaccent ecaron -120
-KPX Tcommaaccent ecircumflex -120
-KPX Tcommaaccent edieresis -120
-KPX Tcommaaccent edotaccent -120
-KPX Tcommaaccent egrave -60
-KPX Tcommaaccent emacron -60
-KPX Tcommaaccent eogonek -120
-KPX Tcommaaccent hyphen -140
-KPX Tcommaaccent o -120
-KPX Tcommaaccent oacute -120
-KPX Tcommaaccent ocircumflex -120
-KPX Tcommaaccent odieresis -120
-KPX Tcommaaccent ograve -120
-KPX Tcommaaccent ohungarumlaut -120
-KPX Tcommaaccent omacron -60
-KPX Tcommaaccent oslash -120
-KPX Tcommaaccent otilde -60
-KPX Tcommaaccent period -120
-KPX Tcommaaccent r -120
-KPX Tcommaaccent racute -120
-KPX Tcommaaccent rcaron -120
-KPX Tcommaaccent rcommaaccent -120
-KPX Tcommaaccent semicolon -20
-KPX Tcommaaccent u -120
-KPX Tcommaaccent uacute -120
-KPX Tcommaaccent ucircumflex -120
-KPX Tcommaaccent udieresis -120
-KPX Tcommaaccent ugrave -120
-KPX Tcommaaccent uhungarumlaut -120
-KPX Tcommaaccent umacron -60
-KPX Tcommaaccent uogonek -120
-KPX Tcommaaccent uring -120
-KPX Tcommaaccent w -120
-KPX Tcommaaccent y -120
-KPX Tcommaaccent yacute -120
-KPX Tcommaaccent ydieresis -60
-KPX U A -40
-KPX U Aacute -40
-KPX U Abreve -40
-KPX U Acircumflex -40
-KPX U Adieresis -40
-KPX U Agrave -40
-KPX U Amacron -40
-KPX U Aogonek -40
-KPX U Aring -40
-KPX U Atilde -40
-KPX U comma -40
-KPX U period -40
-KPX Uacute A -40
-KPX Uacute Aacute -40
-KPX Uacute Abreve -40
-KPX Uacute Acircumflex -40
-KPX Uacute Adieresis -40
-KPX Uacute Agrave -40
-KPX Uacute Amacron -40
-KPX Uacute Aogonek -40
-KPX Uacute Aring -40
-KPX Uacute Atilde -40
-KPX Uacute comma -40
-KPX Uacute period -40
-KPX Ucircumflex A -40
-KPX Ucircumflex Aacute -40
-KPX Ucircumflex Abreve -40
-KPX Ucircumflex Acircumflex -40
-KPX Ucircumflex Adieresis -40
-KPX Ucircumflex Agrave -40
-KPX Ucircumflex Amacron -40
-KPX Ucircumflex Aogonek -40
-KPX Ucircumflex Aring -40
-KPX Ucircumflex Atilde -40
-KPX Ucircumflex comma -40
-KPX Ucircumflex period -40
-KPX Udieresis A -40
-KPX Udieresis Aacute -40
-KPX Udieresis Abreve -40
-KPX Udieresis Acircumflex -40
-KPX Udieresis Adieresis -40
-KPX Udieresis Agrave -40
-KPX Udieresis Amacron -40
-KPX Udieresis Aogonek -40
-KPX Udieresis Aring -40
-KPX Udieresis Atilde -40
-KPX Udieresis comma -40
-KPX Udieresis period -40
-KPX Ugrave A -40
-KPX Ugrave Aacute -40
-KPX Ugrave Abreve -40
-KPX Ugrave Acircumflex -40
-KPX Ugrave Adieresis -40
-KPX Ugrave Agrave -40
-KPX Ugrave Amacron -40
-KPX Ugrave Aogonek -40
-KPX Ugrave Aring -40
-KPX Ugrave Atilde -40
-KPX Ugrave comma -40
-KPX Ugrave period -40
-KPX Uhungarumlaut A -40
-KPX Uhungarumlaut Aacute -40
-KPX Uhungarumlaut Abreve -40
-KPX Uhungarumlaut Acircumflex -40
-KPX Uhungarumlaut Adieresis -40
-KPX Uhungarumlaut Agrave -40
-KPX Uhungarumlaut Amacron -40
-KPX Uhungarumlaut Aogonek -40
-KPX Uhungarumlaut Aring -40
-KPX Uhungarumlaut Atilde -40
-KPX Uhungarumlaut comma -40
-KPX Uhungarumlaut period -40
-KPX Umacron A -40
-KPX Umacron Aacute -40
-KPX Umacron Abreve -40
-KPX Umacron Acircumflex -40
-KPX Umacron Adieresis -40
-KPX Umacron Agrave -40
-KPX Umacron Amacron -40
-KPX Umacron Aogonek -40
-KPX Umacron Aring -40
-KPX Umacron Atilde -40
-KPX Umacron comma -40
-KPX Umacron period -40
-KPX Uogonek A -40
-KPX Uogonek Aacute -40
-KPX Uogonek Abreve -40
-KPX Uogonek Acircumflex -40
-KPX Uogonek Adieresis -40
-KPX Uogonek Agrave -40
-KPX Uogonek Amacron -40
-KPX Uogonek Aogonek -40
-KPX Uogonek Aring -40
-KPX Uogonek Atilde -40
-KPX Uogonek comma -40
-KPX Uogonek period -40
-KPX Uring A -40
-KPX Uring Aacute -40
-KPX Uring Abreve -40
-KPX Uring Acircumflex -40
-KPX Uring Adieresis -40
-KPX Uring Agrave -40
-KPX Uring Amacron -40
-KPX Uring Aogonek -40
-KPX Uring Aring -40
-KPX Uring Atilde -40
-KPX Uring comma -40
-KPX Uring period -40
-KPX V A -80
-KPX V Aacute -80
-KPX V Abreve -80
-KPX V Acircumflex -80
-KPX V Adieresis -80
-KPX V Agrave -80
-KPX V Amacron -80
-KPX V Aogonek -80
-KPX V Aring -80
-KPX V Atilde -80
-KPX V G -40
-KPX V Gbreve -40
-KPX V Gcommaaccent -40
-KPX V O -40
-KPX V Oacute -40
-KPX V Ocircumflex -40
-KPX V Odieresis -40
-KPX V Ograve -40
-KPX V Ohungarumlaut -40
-KPX V Omacron -40
-KPX V Oslash -40
-KPX V Otilde -40
-KPX V a -70
-KPX V aacute -70
-KPX V abreve -70
-KPX V acircumflex -70
-KPX V adieresis -70
-KPX V agrave -70
-KPX V amacron -70
-KPX V aogonek -70
-KPX V aring -70
-KPX V atilde -70
-KPX V colon -40
-KPX V comma -125
-KPX V e -80
-KPX V eacute -80
-KPX V ecaron -80
-KPX V ecircumflex -80
-KPX V edieresis -80
-KPX V edotaccent -80
-KPX V egrave -80
-KPX V emacron -80
-KPX V eogonek -80
-KPX V hyphen -80
-KPX V o -80
-KPX V oacute -80
-KPX V ocircumflex -80
-KPX V odieresis -80
-KPX V ograve -80
-KPX V ohungarumlaut -80
-KPX V omacron -80
-KPX V oslash -80
-KPX V otilde -80
-KPX V period -125
-KPX V semicolon -40
-KPX V u -70
-KPX V uacute -70
-KPX V ucircumflex -70
-KPX V udieresis -70
-KPX V ugrave -70
-KPX V uhungarumlaut -70
-KPX V umacron -70
-KPX V uogonek -70
-KPX V uring -70
-KPX W A -50
-KPX W Aacute -50
-KPX W Abreve -50
-KPX W Acircumflex -50
-KPX W Adieresis -50
-KPX W Agrave -50
-KPX W Amacron -50
-KPX W Aogonek -50
-KPX W Aring -50
-KPX W Atilde -50
-KPX W O -20
-KPX W Oacute -20
-KPX W Ocircumflex -20
-KPX W Odieresis -20
-KPX W Ograve -20
-KPX W Ohungarumlaut -20
-KPX W Omacron -20
-KPX W Oslash -20
-KPX W Otilde -20
-KPX W a -40
-KPX W aacute -40
-KPX W abreve -40
-KPX W acircumflex -40
-KPX W adieresis -40
-KPX W agrave -40
-KPX W amacron -40
-KPX W aogonek -40
-KPX W aring -40
-KPX W atilde -40
-KPX W comma -80
-KPX W e -30
-KPX W eacute -30
-KPX W ecaron -30
-KPX W ecircumflex -30
-KPX W edieresis -30
-KPX W edotaccent -30
-KPX W egrave -30
-KPX W emacron -30
-KPX W eogonek -30
-KPX W hyphen -40
-KPX W o -30
-KPX W oacute -30
-KPX W ocircumflex -30
-KPX W odieresis -30
-KPX W ograve -30
-KPX W ohungarumlaut -30
-KPX W omacron -30
-KPX W oslash -30
-KPX W otilde -30
-KPX W period -80
-KPX W u -30
-KPX W uacute -30
-KPX W ucircumflex -30
-KPX W udieresis -30
-KPX W ugrave -30
-KPX W uhungarumlaut -30
-KPX W umacron -30
-KPX W uogonek -30
-KPX W uring -30
-KPX W y -20
-KPX W yacute -20
-KPX W ydieresis -20
-KPX Y A -110
-KPX Y Aacute -110
-KPX Y Abreve -110
-KPX Y Acircumflex -110
-KPX Y Adieresis -110
-KPX Y Agrave -110
-KPX Y Amacron -110
-KPX Y Aogonek -110
-KPX Y Aring -110
-KPX Y Atilde -110
-KPX Y O -85
-KPX Y Oacute -85
-KPX Y Ocircumflex -85
-KPX Y Odieresis -85
-KPX Y Ograve -85
-KPX Y Ohungarumlaut -85
-KPX Y Omacron -85
-KPX Y Oslash -85
-KPX Y Otilde -85
-KPX Y a -140
-KPX Y aacute -140
-KPX Y abreve -70
-KPX Y acircumflex -140
-KPX Y adieresis -140
-KPX Y agrave -140
-KPX Y amacron -70
-KPX Y aogonek -140
-KPX Y aring -140
-KPX Y atilde -140
-KPX Y colon -60
-KPX Y comma -140
-KPX Y e -140
-KPX Y eacute -140
-KPX Y ecaron -140
-KPX Y ecircumflex -140
-KPX Y edieresis -140
-KPX Y edotaccent -140
-KPX Y egrave -140
-KPX Y emacron -70
-KPX Y eogonek -140
-KPX Y hyphen -140
-KPX Y i -20
-KPX Y iacute -20
-KPX Y iogonek -20
-KPX Y o -140
-KPX Y oacute -140
-KPX Y ocircumflex -140
-KPX Y odieresis -140
-KPX Y ograve -140
-KPX Y ohungarumlaut -140
-KPX Y omacron -140
-KPX Y oslash -140
-KPX Y otilde -140
-KPX Y period -140
-KPX Y semicolon -60
-KPX Y u -110
-KPX Y uacute -110
-KPX Y ucircumflex -110
-KPX Y udieresis -110
-KPX Y ugrave -110
-KPX Y uhungarumlaut -110
-KPX Y umacron -110
-KPX Y uogonek -110
-KPX Y uring -110
-KPX Yacute A -110
-KPX Yacute Aacute -110
-KPX Yacute Abreve -110
-KPX Yacute Acircumflex -110
-KPX Yacute Adieresis -110
-KPX Yacute Agrave -110
-KPX Yacute Amacron -110
-KPX Yacute Aogonek -110
-KPX Yacute Aring -110
-KPX Yacute Atilde -110
-KPX Yacute O -85
-KPX Yacute Oacute -85
-KPX Yacute Ocircumflex -85
-KPX Yacute Odieresis -85
-KPX Yacute Ograve -85
-KPX Yacute Ohungarumlaut -85
-KPX Yacute Omacron -85
-KPX Yacute Oslash -85
-KPX Yacute Otilde -85
-KPX Yacute a -140
-KPX Yacute aacute -140
-KPX Yacute abreve -70
-KPX Yacute acircumflex -140
-KPX Yacute adieresis -140
-KPX Yacute agrave -140
-KPX Yacute amacron -70
-KPX Yacute aogonek -140
-KPX Yacute aring -140
-KPX Yacute atilde -70
-KPX Yacute colon -60
-KPX Yacute comma -140
-KPX Yacute e -140
-KPX Yacute eacute -140
-KPX Yacute ecaron -140
-KPX Yacute ecircumflex -140
-KPX Yacute edieresis -140
-KPX Yacute edotaccent -140
-KPX Yacute egrave -140
-KPX Yacute emacron -70
-KPX Yacute eogonek -140
-KPX Yacute hyphen -140
-KPX Yacute i -20
-KPX Yacute iacute -20
-KPX Yacute iogonek -20
-KPX Yacute o -140
-KPX Yacute oacute -140
-KPX Yacute ocircumflex -140
-KPX Yacute odieresis -140
-KPX Yacute ograve -140
-KPX Yacute ohungarumlaut -140
-KPX Yacute omacron -70
-KPX Yacute oslash -140
-KPX Yacute otilde -140
-KPX Yacute period -140
-KPX Yacute semicolon -60
-KPX Yacute u -110
-KPX Yacute uacute -110
-KPX Yacute ucircumflex -110
-KPX Yacute udieresis -110
-KPX Yacute ugrave -110
-KPX Yacute uhungarumlaut -110
-KPX Yacute umacron -110
-KPX Yacute uogonek -110
-KPX Yacute uring -110
-KPX Ydieresis A -110
-KPX Ydieresis Aacute -110
-KPX Ydieresis Abreve -110
-KPX Ydieresis Acircumflex -110
-KPX Ydieresis Adieresis -110
-KPX Ydieresis Agrave -110
-KPX Ydieresis Amacron -110
-KPX Ydieresis Aogonek -110
-KPX Ydieresis Aring -110
-KPX Ydieresis Atilde -110
-KPX Ydieresis O -85
-KPX Ydieresis Oacute -85
-KPX Ydieresis Ocircumflex -85
-KPX Ydieresis Odieresis -85
-KPX Ydieresis Ograve -85
-KPX Ydieresis Ohungarumlaut -85
-KPX Ydieresis Omacron -85
-KPX Ydieresis Oslash -85
-KPX Ydieresis Otilde -85
-KPX Ydieresis a -140
-KPX Ydieresis aacute -140
-KPX Ydieresis abreve -70
-KPX Ydieresis acircumflex -140
-KPX Ydieresis adieresis -140
-KPX Ydieresis agrave -140
-KPX Ydieresis amacron -70
-KPX Ydieresis aogonek -140
-KPX Ydieresis aring -140
-KPX Ydieresis atilde -70
-KPX Ydieresis colon -60
-KPX Ydieresis comma -140
-KPX Ydieresis e -140
-KPX Ydieresis eacute -140
-KPX Ydieresis ecaron -140
-KPX Ydieresis ecircumflex -140
-KPX Ydieresis edieresis -140
-KPX Ydieresis edotaccent -140
-KPX Ydieresis egrave -140
-KPX Ydieresis emacron -70
-KPX Ydieresis eogonek -140
-KPX Ydieresis hyphen -140
-KPX Ydieresis i -20
-KPX Ydieresis iacute -20
-KPX Ydieresis iogonek -20
-KPX Ydieresis o -140
-KPX Ydieresis oacute -140
-KPX Ydieresis ocircumflex -140
-KPX Ydieresis odieresis -140
-KPX Ydieresis ograve -140
-KPX Ydieresis ohungarumlaut -140
-KPX Ydieresis omacron -140
-KPX Ydieresis oslash -140
-KPX Ydieresis otilde -140
-KPX Ydieresis period -140
-KPX Ydieresis semicolon -60
-KPX Ydieresis u -110
-KPX Ydieresis uacute -110
-KPX Ydieresis ucircumflex -110
-KPX Ydieresis udieresis -110
-KPX Ydieresis ugrave -110
-KPX Ydieresis uhungarumlaut -110
-KPX Ydieresis umacron -110
-KPX Ydieresis uogonek -110
-KPX Ydieresis uring -110
-KPX a v -20
-KPX a w -20
-KPX a y -30
-KPX a yacute -30
-KPX a ydieresis -30
-KPX aacute v -20
-KPX aacute w -20
-KPX aacute y -30
-KPX aacute yacute -30
-KPX aacute ydieresis -30
-KPX abreve v -20
-KPX abreve w -20
-KPX abreve y -30
-KPX abreve yacute -30
-KPX abreve ydieresis -30
-KPX acircumflex v -20
-KPX acircumflex w -20
-KPX acircumflex y -30
-KPX acircumflex yacute -30
-KPX acircumflex ydieresis -30
-KPX adieresis v -20
-KPX adieresis w -20
-KPX adieresis y -30
-KPX adieresis yacute -30
-KPX adieresis ydieresis -30
-KPX agrave v -20
-KPX agrave w -20
-KPX agrave y -30
-KPX agrave yacute -30
-KPX agrave ydieresis -30
-KPX amacron v -20
-KPX amacron w -20
-KPX amacron y -30
-KPX amacron yacute -30
-KPX amacron ydieresis -30
-KPX aogonek v -20
-KPX aogonek w -20
-KPX aogonek y -30
-KPX aogonek yacute -30
-KPX aogonek ydieresis -30
-KPX aring v -20
-KPX aring w -20
-KPX aring y -30
-KPX aring yacute -30
-KPX aring ydieresis -30
-KPX atilde v -20
-KPX atilde w -20
-KPX atilde y -30
-KPX atilde yacute -30
-KPX atilde ydieresis -30
-KPX b b -10
-KPX b comma -40
-KPX b l -20
-KPX b lacute -20
-KPX b lcommaaccent -20
-KPX b lslash -20
-KPX b period -40
-KPX b u -20
-KPX b uacute -20
-KPX b ucircumflex -20
-KPX b udieresis -20
-KPX b ugrave -20
-KPX b uhungarumlaut -20
-KPX b umacron -20
-KPX b uogonek -20
-KPX b uring -20
-KPX b v -20
-KPX b y -20
-KPX b yacute -20
-KPX b ydieresis -20
-KPX c comma -15
-KPX c k -20
-KPX c kcommaaccent -20
-KPX cacute comma -15
-KPX cacute k -20
-KPX cacute kcommaaccent -20
-KPX ccaron comma -15
-KPX ccaron k -20
-KPX ccaron kcommaaccent -20
-KPX ccedilla comma -15
-KPX ccedilla k -20
-KPX ccedilla kcommaaccent -20
-KPX colon space -50
-KPX comma quotedblright -100
-KPX comma quoteright -100
-KPX e comma -15
-KPX e period -15
-KPX e v -30
-KPX e w -20
-KPX e x -30
-KPX e y -20
-KPX e yacute -20
-KPX e ydieresis -20
-KPX eacute comma -15
-KPX eacute period -15
-KPX eacute v -30
-KPX eacute w -20
-KPX eacute x -30
-KPX eacute y -20
-KPX eacute yacute -20
-KPX eacute ydieresis -20
-KPX ecaron comma -15
-KPX ecaron period -15
-KPX ecaron v -30
-KPX ecaron w -20
-KPX ecaron x -30
-KPX ecaron y -20
-KPX ecaron yacute -20
-KPX ecaron ydieresis -20
-KPX ecircumflex comma -15
-KPX ecircumflex period -15
-KPX ecircumflex v -30
-KPX ecircumflex w -20
-KPX ecircumflex x -30
-KPX ecircumflex y -20
-KPX ecircumflex yacute -20
-KPX ecircumflex ydieresis -20
-KPX edieresis comma -15
-KPX edieresis period -15
-KPX edieresis v -30
-KPX edieresis w -20
-KPX edieresis x -30
-KPX edieresis y -20
-KPX edieresis yacute -20
-KPX edieresis ydieresis -20
-KPX edotaccent comma -15
-KPX edotaccent period -15
-KPX edotaccent v -30
-KPX edotaccent w -20
-KPX edotaccent x -30
-KPX edotaccent y -20
-KPX edotaccent yacute -20
-KPX edotaccent ydieresis -20
-KPX egrave comma -15
-KPX egrave period -15
-KPX egrave v -30
-KPX egrave w -20
-KPX egrave x -30
-KPX egrave y -20
-KPX egrave yacute -20
-KPX egrave ydieresis -20
-KPX emacron comma -15
-KPX emacron period -15
-KPX emacron v -30
-KPX emacron w -20
-KPX emacron x -30
-KPX emacron y -20
-KPX emacron yacute -20
-KPX emacron ydieresis -20
-KPX eogonek comma -15
-KPX eogonek period -15
-KPX eogonek v -30
-KPX eogonek w -20
-KPX eogonek x -30
-KPX eogonek y -20
-KPX eogonek yacute -20
-KPX eogonek ydieresis -20
-KPX f a -30
-KPX f aacute -30
-KPX f abreve -30
-KPX f acircumflex -30
-KPX f adieresis -30
-KPX f agrave -30
-KPX f amacron -30
-KPX f aogonek -30
-KPX f aring -30
-KPX f atilde -30
-KPX f comma -30
-KPX f dotlessi -28
-KPX f e -30
-KPX f eacute -30
-KPX f ecaron -30
-KPX f ecircumflex -30
-KPX f edieresis -30
-KPX f edotaccent -30
-KPX f egrave -30
-KPX f emacron -30
-KPX f eogonek -30
-KPX f o -30
-KPX f oacute -30
-KPX f ocircumflex -30
-KPX f odieresis -30
-KPX f ograve -30
-KPX f ohungarumlaut -30
-KPX f omacron -30
-KPX f oslash -30
-KPX f otilde -30
-KPX f period -30
-KPX f quotedblright 60
-KPX f quoteright 50
-KPX g r -10
-KPX g racute -10
-KPX g rcaron -10
-KPX g rcommaaccent -10
-KPX gbreve r -10
-KPX gbreve racute -10
-KPX gbreve rcaron -10
-KPX gbreve rcommaaccent -10
-KPX gcommaaccent r -10
-KPX gcommaaccent racute -10
-KPX gcommaaccent rcaron -10
-KPX gcommaaccent rcommaaccent -10
-KPX h y -30
-KPX h yacute -30
-KPX h ydieresis -30
-KPX k e -20
-KPX k eacute -20
-KPX k ecaron -20
-KPX k ecircumflex -20
-KPX k edieresis -20
-KPX k edotaccent -20
-KPX k egrave -20
-KPX k emacron -20
-KPX k eogonek -20
-KPX k o -20
-KPX k oacute -20
-KPX k ocircumflex -20
-KPX k odieresis -20
-KPX k ograve -20
-KPX k ohungarumlaut -20
-KPX k omacron -20
-KPX k oslash -20
-KPX k otilde -20
-KPX kcommaaccent e -20
-KPX kcommaaccent eacute -20
-KPX kcommaaccent ecaron -20
-KPX kcommaaccent ecircumflex -20
-KPX kcommaaccent edieresis -20
-KPX kcommaaccent edotaccent -20
-KPX kcommaaccent egrave -20
-KPX kcommaaccent emacron -20
-KPX kcommaaccent eogonek -20
-KPX kcommaaccent o -20
-KPX kcommaaccent oacute -20
-KPX kcommaaccent ocircumflex -20
-KPX kcommaaccent odieresis -20
-KPX kcommaaccent ograve -20
-KPX kcommaaccent ohungarumlaut -20
-KPX kcommaaccent omacron -20
-KPX kcommaaccent oslash -20
-KPX kcommaaccent otilde -20
-KPX m u -10
-KPX m uacute -10
-KPX m ucircumflex -10
-KPX m udieresis -10
-KPX m ugrave -10
-KPX m uhungarumlaut -10
-KPX m umacron -10
-KPX m uogonek -10
-KPX m uring -10
-KPX m y -15
-KPX m yacute -15
-KPX m ydieresis -15
-KPX n u -10
-KPX n uacute -10
-KPX n ucircumflex -10
-KPX n udieresis -10
-KPX n ugrave -10
-KPX n uhungarumlaut -10
-KPX n umacron -10
-KPX n uogonek -10
-KPX n uring -10
-KPX n v -20
-KPX n y -15
-KPX n yacute -15
-KPX n ydieresis -15
-KPX nacute u -10
-KPX nacute uacute -10
-KPX nacute ucircumflex -10
-KPX nacute udieresis -10
-KPX nacute ugrave -10
-KPX nacute uhungarumlaut -10
-KPX nacute umacron -10
-KPX nacute uogonek -10
-KPX nacute uring -10
-KPX nacute v -20
-KPX nacute y -15
-KPX nacute yacute -15
-KPX nacute ydieresis -15
-KPX ncaron u -10
-KPX ncaron uacute -10
-KPX ncaron ucircumflex -10
-KPX ncaron udieresis -10
-KPX ncaron ugrave -10
-KPX ncaron uhungarumlaut -10
-KPX ncaron umacron -10
-KPX ncaron uogonek -10
-KPX ncaron uring -10
-KPX ncaron v -20
-KPX ncaron y -15
-KPX ncaron yacute -15
-KPX ncaron ydieresis -15
-KPX ncommaaccent u -10
-KPX ncommaaccent uacute -10
-KPX ncommaaccent ucircumflex -10
-KPX ncommaaccent udieresis -10
-KPX ncommaaccent ugrave -10
-KPX ncommaaccent uhungarumlaut -10
-KPX ncommaaccent umacron -10
-KPX ncommaaccent uogonek -10
-KPX ncommaaccent uring -10
-KPX ncommaaccent v -20
-KPX ncommaaccent y -15
-KPX ncommaaccent yacute -15
-KPX ncommaaccent ydieresis -15
-KPX ntilde u -10
-KPX ntilde uacute -10
-KPX ntilde ucircumflex -10
-KPX ntilde udieresis -10
-KPX ntilde ugrave -10
-KPX ntilde uhungarumlaut -10
-KPX ntilde umacron -10
-KPX ntilde uogonek -10
-KPX ntilde uring -10
-KPX ntilde v -20
-KPX ntilde y -15
-KPX ntilde yacute -15
-KPX ntilde ydieresis -15
-KPX o comma -40
-KPX o period -40
-KPX o v -15
-KPX o w -15
-KPX o x -30
-KPX o y -30
-KPX o yacute -30
-KPX o ydieresis -30
-KPX oacute comma -40
-KPX oacute period -40
-KPX oacute v -15
-KPX oacute w -15
-KPX oacute x -30
-KPX oacute y -30
-KPX oacute yacute -30
-KPX oacute ydieresis -30
-KPX ocircumflex comma -40
-KPX ocircumflex period -40
-KPX ocircumflex v -15
-KPX ocircumflex w -15
-KPX ocircumflex x -30
-KPX ocircumflex y -30
-KPX ocircumflex yacute -30
-KPX ocircumflex ydieresis -30
-KPX odieresis comma -40
-KPX odieresis period -40
-KPX odieresis v -15
-KPX odieresis w -15
-KPX odieresis x -30
-KPX odieresis y -30
-KPX odieresis yacute -30
-KPX odieresis ydieresis -30
-KPX ograve comma -40
-KPX ograve period -40
-KPX ograve v -15
-KPX ograve w -15
-KPX ograve x -30
-KPX ograve y -30
-KPX ograve yacute -30
-KPX ograve ydieresis -30
-KPX ohungarumlaut comma -40
-KPX ohungarumlaut period -40
-KPX ohungarumlaut v -15
-KPX ohungarumlaut w -15
-KPX ohungarumlaut x -30
-KPX ohungarumlaut y -30
-KPX ohungarumlaut yacute -30
-KPX ohungarumlaut ydieresis -30
-KPX omacron comma -40
-KPX omacron period -40
-KPX omacron v -15
-KPX omacron w -15
-KPX omacron x -30
-KPX omacron y -30
-KPX omacron yacute -30
-KPX omacron ydieresis -30
-KPX oslash a -55
-KPX oslash aacute -55
-KPX oslash abreve -55
-KPX oslash acircumflex -55
-KPX oslash adieresis -55
-KPX oslash agrave -55
-KPX oslash amacron -55
-KPX oslash aogonek -55
-KPX oslash aring -55
-KPX oslash atilde -55
-KPX oslash b -55
-KPX oslash c -55
-KPX oslash cacute -55
-KPX oslash ccaron -55
-KPX oslash ccedilla -55
-KPX oslash comma -95
-KPX oslash d -55
-KPX oslash dcroat -55
-KPX oslash e -55
-KPX oslash eacute -55
-KPX oslash ecaron -55
-KPX oslash ecircumflex -55
-KPX oslash edieresis -55
-KPX oslash edotaccent -55
-KPX oslash egrave -55
-KPX oslash emacron -55
-KPX oslash eogonek -55
-KPX oslash f -55
-KPX oslash g -55
-KPX oslash gbreve -55
-KPX oslash gcommaaccent -55
-KPX oslash h -55
-KPX oslash i -55
-KPX oslash iacute -55
-KPX oslash icircumflex -55
-KPX oslash idieresis -55
-KPX oslash igrave -55
-KPX oslash imacron -55
-KPX oslash iogonek -55
-KPX oslash j -55
-KPX oslash k -55
-KPX oslash kcommaaccent -55
-KPX oslash l -55
-KPX oslash lacute -55
-KPX oslash lcommaaccent -55
-KPX oslash lslash -55
-KPX oslash m -55
-KPX oslash n -55
-KPX oslash nacute -55
-KPX oslash ncaron -55
-KPX oslash ncommaaccent -55
-KPX oslash ntilde -55
-KPX oslash o -55
-KPX oslash oacute -55
-KPX oslash ocircumflex -55
-KPX oslash odieresis -55
-KPX oslash ograve -55
-KPX oslash ohungarumlaut -55
-KPX oslash omacron -55
-KPX oslash oslash -55
-KPX oslash otilde -55
-KPX oslash p -55
-KPX oslash period -95
-KPX oslash q -55
-KPX oslash r -55
-KPX oslash racute -55
-KPX oslash rcaron -55
-KPX oslash rcommaaccent -55
-KPX oslash s -55
-KPX oslash sacute -55
-KPX oslash scaron -55
-KPX oslash scedilla -55
-KPX oslash scommaaccent -55
-KPX oslash t -55
-KPX oslash tcommaaccent -55
-KPX oslash u -55
-KPX oslash uacute -55
-KPX oslash ucircumflex -55
-KPX oslash udieresis -55
-KPX oslash ugrave -55
-KPX oslash uhungarumlaut -55
-KPX oslash umacron -55
-KPX oslash uogonek -55
-KPX oslash uring -55
-KPX oslash v -70
-KPX oslash w -70
-KPX oslash x -85
-KPX oslash y -70
-KPX oslash yacute -70
-KPX oslash ydieresis -70
-KPX oslash z -55
-KPX oslash zacute -55
-KPX oslash zcaron -55
-KPX oslash zdotaccent -55
-KPX otilde comma -40
-KPX otilde period -40
-KPX otilde v -15
-KPX otilde w -15
-KPX otilde x -30
-KPX otilde y -30
-KPX otilde yacute -30
-KPX otilde ydieresis -30
-KPX p comma -35
-KPX p period -35
-KPX p y -30
-KPX p yacute -30
-KPX p ydieresis -30
-KPX period quotedblright -100
-KPX period quoteright -100
-KPX period space -60
-KPX quotedblright space -40
-KPX quoteleft quoteleft -57
-KPX quoteright d -50
-KPX quoteright dcroat -50
-KPX quoteright quoteright -57
-KPX quoteright r -50
-KPX quoteright racute -50
-KPX quoteright rcaron -50
-KPX quoteright rcommaaccent -50
-KPX quoteright s -50
-KPX quoteright sacute -50
-KPX quoteright scaron -50
-KPX quoteright scedilla -50
-KPX quoteright scommaaccent -50
-KPX quoteright space -70
-KPX r a -10
-KPX r aacute -10
-KPX r abreve -10
-KPX r acircumflex -10
-KPX r adieresis -10
-KPX r agrave -10
-KPX r amacron -10
-KPX r aogonek -10
-KPX r aring -10
-KPX r atilde -10
-KPX r colon 30
-KPX r comma -50
-KPX r i 15
-KPX r iacute 15
-KPX r icircumflex 15
-KPX r idieresis 15
-KPX r igrave 15
-KPX r imacron 15
-KPX r iogonek 15
-KPX r k 15
-KPX r kcommaaccent 15
-KPX r l 15
-KPX r lacute 15
-KPX r lcommaaccent 15
-KPX r lslash 15
-KPX r m 25
-KPX r n 25
-KPX r nacute 25
-KPX r ncaron 25
-KPX r ncommaaccent 25
-KPX r ntilde 25
-KPX r p 30
-KPX r period -50
-KPX r semicolon 30
-KPX r t 40
-KPX r tcommaaccent 40
-KPX r u 15
-KPX r uacute 15
-KPX r ucircumflex 15
-KPX r udieresis 15
-KPX r ugrave 15
-KPX r uhungarumlaut 15
-KPX r umacron 15
-KPX r uogonek 15
-KPX r uring 15
-KPX r v 30
-KPX r y 30
-KPX r yacute 30
-KPX r ydieresis 30
-KPX racute a -10
-KPX racute aacute -10
-KPX racute abreve -10
-KPX racute acircumflex -10
-KPX racute adieresis -10
-KPX racute agrave -10
-KPX racute amacron -10
-KPX racute aogonek -10
-KPX racute aring -10
-KPX racute atilde -10
-KPX racute colon 30
-KPX racute comma -50
-KPX racute i 15
-KPX racute iacute 15
-KPX racute icircumflex 15
-KPX racute idieresis 15
-KPX racute igrave 15
-KPX racute imacron 15
-KPX racute iogonek 15
-KPX racute k 15
-KPX racute kcommaaccent 15
-KPX racute l 15
-KPX racute lacute 15
-KPX racute lcommaaccent 15
-KPX racute lslash 15
-KPX racute m 25
-KPX racute n 25
-KPX racute nacute 25
-KPX racute ncaron 25
-KPX racute ncommaaccent 25
-KPX racute ntilde 25
-KPX racute p 30
-KPX racute period -50
-KPX racute semicolon 30
-KPX racute t 40
-KPX racute tcommaaccent 40
-KPX racute u 15
-KPX racute uacute 15
-KPX racute ucircumflex 15
-KPX racute udieresis 15
-KPX racute ugrave 15
-KPX racute uhungarumlaut 15
-KPX racute umacron 15
-KPX racute uogonek 15
-KPX racute uring 15
-KPX racute v 30
-KPX racute y 30
-KPX racute yacute 30
-KPX racute ydieresis 30
-KPX rcaron a -10
-KPX rcaron aacute -10
-KPX rcaron abreve -10
-KPX rcaron acircumflex -10
-KPX rcaron adieresis -10
-KPX rcaron agrave -10
-KPX rcaron amacron -10
-KPX rcaron aogonek -10
-KPX rcaron aring -10
-KPX rcaron atilde -10
-KPX rcaron colon 30
-KPX rcaron comma -50
-KPX rcaron i 15
-KPX rcaron iacute 15
-KPX rcaron icircumflex 15
-KPX rcaron idieresis 15
-KPX rcaron igrave 15
-KPX rcaron imacron 15
-KPX rcaron iogonek 15
-KPX rcaron k 15
-KPX rcaron kcommaaccent 15
-KPX rcaron l 15
-KPX rcaron lacute 15
-KPX rcaron lcommaaccent 15
-KPX rcaron lslash 15
-KPX rcaron m 25
-KPX rcaron n 25
-KPX rcaron nacute 25
-KPX rcaron ncaron 25
-KPX rcaron ncommaaccent 25
-KPX rcaron ntilde 25
-KPX rcaron p 30
-KPX rcaron period -50
-KPX rcaron semicolon 30
-KPX rcaron t 40
-KPX rcaron tcommaaccent 40
-KPX rcaron u 15
-KPX rcaron uacute 15
-KPX rcaron ucircumflex 15
-KPX rcaron udieresis 15
-KPX rcaron ugrave 15
-KPX rcaron uhungarumlaut 15
-KPX rcaron umacron 15
-KPX rcaron uogonek 15
-KPX rcaron uring 15
-KPX rcaron v 30
-KPX rcaron y 30
-KPX rcaron yacute 30
-KPX rcaron ydieresis 30
-KPX rcommaaccent a -10
-KPX rcommaaccent aacute -10
-KPX rcommaaccent abreve -10
-KPX rcommaaccent acircumflex -10
-KPX rcommaaccent adieresis -10
-KPX rcommaaccent agrave -10
-KPX rcommaaccent amacron -10
-KPX rcommaaccent aogonek -10
-KPX rcommaaccent aring -10
-KPX rcommaaccent atilde -10
-KPX rcommaaccent colon 30
-KPX rcommaaccent comma -50
-KPX rcommaaccent i 15
-KPX rcommaaccent iacute 15
-KPX rcommaaccent icircumflex 15
-KPX rcommaaccent idieresis 15
-KPX rcommaaccent igrave 15
-KPX rcommaaccent imacron 15
-KPX rcommaaccent iogonek 15
-KPX rcommaaccent k 15
-KPX rcommaaccent kcommaaccent 15
-KPX rcommaaccent l 15
-KPX rcommaaccent lacute 15
-KPX rcommaaccent lcommaaccent 15
-KPX rcommaaccent lslash 15
-KPX rcommaaccent m 25
-KPX rcommaaccent n 25
-KPX rcommaaccent nacute 25
-KPX rcommaaccent ncaron 25
-KPX rcommaaccent ncommaaccent 25
-KPX rcommaaccent ntilde 25
-KPX rcommaaccent p 30
-KPX rcommaaccent period -50
-KPX rcommaaccent semicolon 30
-KPX rcommaaccent t 40
-KPX rcommaaccent tcommaaccent 40
-KPX rcommaaccent u 15
-KPX rcommaaccent uacute 15
-KPX rcommaaccent ucircumflex 15
-KPX rcommaaccent udieresis 15
-KPX rcommaaccent ugrave 15
-KPX rcommaaccent uhungarumlaut 15
-KPX rcommaaccent umacron 15
-KPX rcommaaccent uogonek 15
-KPX rcommaaccent uring 15
-KPX rcommaaccent v 30
-KPX rcommaaccent y 30
-KPX rcommaaccent yacute 30
-KPX rcommaaccent ydieresis 30
-KPX s comma -15
-KPX s period -15
-KPX s w -30
-KPX sacute comma -15
-KPX sacute period -15
-KPX sacute w -30
-KPX scaron comma -15
-KPX scaron period -15
-KPX scaron w -30
-KPX scedilla comma -15
-KPX scedilla period -15
-KPX scedilla w -30
-KPX scommaaccent comma -15
-KPX scommaaccent period -15
-KPX scommaaccent w -30
-KPX semicolon space -50
-KPX space T -50
-KPX space Tcaron -50
-KPX space Tcommaaccent -50
-KPX space V -50
-KPX space W -40
-KPX space Y -90
-KPX space Yacute -90
-KPX space Ydieresis -90
-KPX space quotedblleft -30
-KPX space quoteleft -60
-KPX v a -25
-KPX v aacute -25
-KPX v abreve -25
-KPX v acircumflex -25
-KPX v adieresis -25
-KPX v agrave -25
-KPX v amacron -25
-KPX v aogonek -25
-KPX v aring -25
-KPX v atilde -25
-KPX v comma -80
-KPX v e -25
-KPX v eacute -25
-KPX v ecaron -25
-KPX v ecircumflex -25
-KPX v edieresis -25
-KPX v edotaccent -25
-KPX v egrave -25
-KPX v emacron -25
-KPX v eogonek -25
-KPX v o -25
-KPX v oacute -25
-KPX v ocircumflex -25
-KPX v odieresis -25
-KPX v ograve -25
-KPX v ohungarumlaut -25
-KPX v omacron -25
-KPX v oslash -25
-KPX v otilde -25
-KPX v period -80
-KPX w a -15
-KPX w aacute -15
-KPX w abreve -15
-KPX w acircumflex -15
-KPX w adieresis -15
-KPX w agrave -15
-KPX w amacron -15
-KPX w aogonek -15
-KPX w aring -15
-KPX w atilde -15
-KPX w comma -60
-KPX w e -10
-KPX w eacute -10
-KPX w ecaron -10
-KPX w ecircumflex -10
-KPX w edieresis -10
-KPX w edotaccent -10
-KPX w egrave -10
-KPX w emacron -10
-KPX w eogonek -10
-KPX w o -10
-KPX w oacute -10
-KPX w ocircumflex -10
-KPX w odieresis -10
-KPX w ograve -10
-KPX w ohungarumlaut -10
-KPX w omacron -10
-KPX w oslash -10
-KPX w otilde -10
-KPX w period -60
-KPX x e -30
-KPX x eacute -30
-KPX x ecaron -30
-KPX x ecircumflex -30
-KPX x edieresis -30
-KPX x edotaccent -30
-KPX x egrave -30
-KPX x emacron -30
-KPX x eogonek -30
-KPX y a -20
-KPX y aacute -20
-KPX y abreve -20
-KPX y acircumflex -20
-KPX y adieresis -20
-KPX y agrave -20
-KPX y amacron -20
-KPX y aogonek -20
-KPX y aring -20
-KPX y atilde -20
-KPX y comma -100
-KPX y e -20
-KPX y eacute -20
-KPX y ecaron -20
-KPX y ecircumflex -20
-KPX y edieresis -20
-KPX y edotaccent -20
-KPX y egrave -20
-KPX y emacron -20
-KPX y eogonek -20
-KPX y o -20
-KPX y oacute -20
-KPX y ocircumflex -20
-KPX y odieresis -20
-KPX y ograve -20
-KPX y ohungarumlaut -20
-KPX y omacron -20
-KPX y oslash -20
-KPX y otilde -20
-KPX y period -100
-KPX yacute a -20
-KPX yacute aacute -20
-KPX yacute abreve -20
-KPX yacute acircumflex -20
-KPX yacute adieresis -20
-KPX yacute agrave -20
-KPX yacute amacron -20
-KPX yacute aogonek -20
-KPX yacute aring -20
-KPX yacute atilde -20
-KPX yacute comma -100
-KPX yacute e -20
-KPX yacute eacute -20
-KPX yacute ecaron -20
-KPX yacute ecircumflex -20
-KPX yacute edieresis -20
-KPX yacute edotaccent -20
-KPX yacute egrave -20
-KPX yacute emacron -20
-KPX yacute eogonek -20
-KPX yacute o -20
-KPX yacute oacute -20
-KPX yacute ocircumflex -20
-KPX yacute odieresis -20
-KPX yacute ograve -20
-KPX yacute ohungarumlaut -20
-KPX yacute omacron -20
-KPX yacute oslash -20
-KPX yacute otilde -20
-KPX yacute period -100
-KPX ydieresis a -20
-KPX ydieresis aacute -20
-KPX ydieresis abreve -20
-KPX ydieresis acircumflex -20
-KPX ydieresis adieresis -20
-KPX ydieresis agrave -20
-KPX ydieresis amacron -20
-KPX ydieresis aogonek -20
-KPX ydieresis aring -20
-KPX ydieresis atilde -20
-KPX ydieresis comma -100
-KPX ydieresis e -20
-KPX ydieresis eacute -20
-KPX ydieresis ecaron -20
-KPX ydieresis ecircumflex -20
-KPX ydieresis edieresis -20
-KPX ydieresis edotaccent -20
-KPX ydieresis egrave -20
-KPX ydieresis emacron -20
-KPX ydieresis eogonek -20
-KPX ydieresis o -20
-KPX ydieresis oacute -20
-KPX ydieresis ocircumflex -20
-KPX ydieresis odieresis -20
-KPX ydieresis ograve -20
-KPX ydieresis ohungarumlaut -20
-KPX ydieresis omacron -20
-KPX ydieresis oslash -20
-KPX ydieresis otilde -20
-KPX ydieresis period -100
-KPX z e -15
-KPX z eacute -15
-KPX z ecaron -15
-KPX z ecircumflex -15
-KPX z edieresis -15
-KPX z edotaccent -15
-KPX z egrave -15
-KPX z emacron -15
-KPX z eogonek -15
-KPX z o -15
-KPX z oacute -15
-KPX z ocircumflex -15
-KPX z odieresis -15
-KPX z ograve -15
-KPX z ohungarumlaut -15
-KPX z omacron -15
-KPX z oslash -15
-KPX z otilde -15
-KPX zacute e -15
-KPX zacute eacute -15
-KPX zacute ecaron -15
-KPX zacute ecircumflex -15
-KPX zacute edieresis -15
-KPX zacute edotaccent -15
-KPX zacute egrave -15
-KPX zacute emacron -15
-KPX zacute eogonek -15
-KPX zacute o -15
-KPX zacute oacute -15
-KPX zacute ocircumflex -15
-KPX zacute odieresis -15
-KPX zacute ograve -15
-KPX zacute ohungarumlaut -15
-KPX zacute omacron -15
-KPX zacute oslash -15
-KPX zacute otilde -15
-KPX zcaron e -15
-KPX zcaron eacute -15
-KPX zcaron ecaron -15
-KPX zcaron ecircumflex -15
-KPX zcaron edieresis -15
-KPX zcaron edotaccent -15
-KPX zcaron egrave -15
-KPX zcaron emacron -15
-KPX zcaron eogonek -15
-KPX zcaron o -15
-KPX zcaron oacute -15
-KPX zcaron ocircumflex -15
-KPX zcaron odieresis -15
-KPX zcaron ograve -15
-KPX zcaron ohungarumlaut -15
-KPX zcaron omacron -15
-KPX zcaron oslash -15
-KPX zcaron otilde -15
-KPX zdotaccent e -15
-KPX zdotaccent eacute -15
-KPX zdotaccent ecaron -15
-KPX zdotaccent ecircumflex -15
-KPX zdotaccent edieresis -15
-KPX zdotaccent edotaccent -15
-KPX zdotaccent egrave -15
-KPX zdotaccent emacron -15
-KPX zdotaccent eogonek -15
-KPX zdotaccent o -15
-KPX zdotaccent oacute -15
-KPX zdotaccent ocircumflex -15
-KPX zdotaccent odieresis -15
-KPX zdotaccent ograve -15
-KPX zdotaccent ohungarumlaut -15
-KPX zdotaccent omacron -15
-KPX zdotaccent oslash -15
-KPX zdotaccent otilde -15
-EndKernPairs
-EndKernData
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Helvetica.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Helvetica.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Helvetica.afm 2004-05-26 16:06:20.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Helvetica.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,3051 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Thu May 1 12:38:23 1997
-Comment UniqueID 43054
-Comment VMusage 37069 48094
-FontName Helvetica
-FullName Helvetica
-FamilyName Helvetica
-Weight Medium
-ItalicAngle 0
-IsFixedPitch false
-CharacterSet ExtendedRoman
-FontBBox -166 -225 1000 931
-UnderlinePosition -100
-UnderlineThickness 50
-Version 002.000
-Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
-EncodingScheme AdobeStandardEncoding
-CapHeight 718
-XHeight 523
-Ascender 718
-Descender -207
-StdHW 76
-StdVW 88
-StartCharMetrics 315
-C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 278 ; N exclam ; B 90 0 187 718 ;
-C 34 ; WX 355 ; N quotedbl ; B 70 463 285 718 ;
-C 35 ; WX 556 ; N numbersign ; B 28 0 529 688 ;
-C 36 ; WX 556 ; N dollar ; B 32 -115 520 775 ;
-C 37 ; WX 889 ; N percent ; B 39 -19 850 703 ;
-C 38 ; WX 667 ; N ampersand ; B 44 -15 645 718 ;
-C 39 ; WX 222 ; N quoteright ; B 53 463 157 718 ;
-C 40 ; WX 333 ; N parenleft ; B 68 -207 299 733 ;
-C 41 ; WX 333 ; N parenright ; B 34 -207 265 733 ;
-C 42 ; WX 389 ; N asterisk ; B 39 431 349 718 ;
-C 43 ; WX 584 ; N plus ; B 39 0 545 505 ;
-C 44 ; WX 278 ; N comma ; B 87 -147 191 106 ;
-C 45 ; WX 333 ; N hyphen ; B 44 232 289 322 ;
-C 46 ; WX 278 ; N period ; B 87 0 191 106 ;
-C 47 ; WX 278 ; N slash ; B -17 -19 295 737 ;
-C 48 ; WX 556 ; N zero ; B 37 -19 519 703 ;
-C 49 ; WX 556 ; N one ; B 101 0 359 703 ;
-C 50 ; WX 556 ; N two ; B 26 0 507 703 ;
-C 51 ; WX 556 ; N three ; B 34 -19 522 703 ;
-C 52 ; WX 556 ; N four ; B 25 0 523 703 ;
-C 53 ; WX 556 ; N five ; B 32 -19 514 688 ;
-C 54 ; WX 556 ; N six ; B 38 -19 518 703 ;
-C 55 ; WX 556 ; N seven ; B 37 0 523 688 ;
-C 56 ; WX 556 ; N eight ; B 38 -19 517 703 ;
-C 57 ; WX 556 ; N nine ; B 42 -19 514 703 ;
-C 58 ; WX 278 ; N colon ; B 87 0 191 516 ;
-C 59 ; WX 278 ; N semicolon ; B 87 -147 191 516 ;
-C 60 ; WX 584 ; N less ; B 48 11 536 495 ;
-C 61 ; WX 584 ; N equal ; B 39 115 545 390 ;
-C 62 ; WX 584 ; N greater ; B 48 11 536 495 ;
-C 63 ; WX 556 ; N question ; B 56 0 492 727 ;
-C 64 ; WX 1015 ; N at ; B 147 -19 868 737 ;
-C 65 ; WX 667 ; N A ; B 14 0 654 718 ;
-C 66 ; WX 667 ; N B ; B 74 0 627 718 ;
-C 67 ; WX 722 ; N C ; B 44 -19 681 737 ;
-C 68 ; WX 722 ; N D ; B 81 0 674 718 ;
-C 69 ; WX 667 ; N E ; B 86 0 616 718 ;
-C 70 ; WX 611 ; N F ; B 86 0 583 718 ;
-C 71 ; WX 778 ; N G ; B 48 -19 704 737 ;
-C 72 ; WX 722 ; N H ; B 77 0 646 718 ;
-C 73 ; WX 278 ; N I ; B 91 0 188 718 ;
-C 74 ; WX 500 ; N J ; B 17 -19 428 718 ;
-C 75 ; WX 667 ; N K ; B 76 0 663 718 ;
-C 76 ; WX 556 ; N L ; B 76 0 537 718 ;
-C 77 ; WX 833 ; N M ; B 73 0 761 718 ;
-C 78 ; WX 722 ; N N ; B 76 0 646 718 ;
-C 79 ; WX 778 ; N O ; B 39 -19 739 737 ;
-C 80 ; WX 667 ; N P ; B 86 0 622 718 ;
-C 81 ; WX 778 ; N Q ; B 39 -56 739 737 ;
-C 82 ; WX 722 ; N R ; B 88 0 684 718 ;
-C 83 ; WX 667 ; N S ; B 49 -19 620 737 ;
-C 84 ; WX 611 ; N T ; B 14 0 597 718 ;
-C 85 ; WX 722 ; N U ; B 79 -19 644 718 ;
-C 86 ; WX 667 ; N V ; B 20 0 647 718 ;
-C 87 ; WX 944 ; N W ; B 16 0 928 718 ;
-C 88 ; WX 667 ; N X ; B 19 0 648 718 ;
-C 89 ; WX 667 ; N Y ; B 14 0 653 718 ;
-C 90 ; WX 611 ; N Z ; B 23 0 588 718 ;
-C 91 ; WX 278 ; N bracketleft ; B 63 -196 250 722 ;
-C 92 ; WX 278 ; N backslash ; B -17 -19 295 737 ;
-C 93 ; WX 278 ; N bracketright ; B 28 -196 215 722 ;
-C 94 ; WX 469 ; N asciicircum ; B -14 264 483 688 ;
-C 95 ; WX 556 ; N underscore ; B 0 -125 556 -75 ;
-C 96 ; WX 222 ; N quoteleft ; B 65 470 169 725 ;
-C 97 ; WX 556 ; N a ; B 36 -15 530 538 ;
-C 98 ; WX 556 ; N b ; B 58 -15 517 718 ;
-C 99 ; WX 500 ; N c ; B 30 -15 477 538 ;
-C 100 ; WX 556 ; N d ; B 35 -15 499 718 ;
-C 101 ; WX 556 ; N e ; B 40 -15 516 538 ;
-C 102 ; WX 278 ; N f ; B 14 0 262 728 ; L i fi ; L l fl ;
-C 103 ; WX 556 ; N g ; B 40 -220 499 538 ;
-C 104 ; WX 556 ; N h ; B 65 0 491 718 ;
-C 105 ; WX 222 ; N i ; B 67 0 155 718 ;
-C 106 ; WX 222 ; N j ; B -16 -210 155 718 ;
-C 107 ; WX 500 ; N k ; B 67 0 501 718 ;
-C 108 ; WX 222 ; N l ; B 67 0 155 718 ;
-C 109 ; WX 833 ; N m ; B 65 0 769 538 ;
-C 110 ; WX 556 ; N n ; B 65 0 491 538 ;
-C 111 ; WX 556 ; N o ; B 35 -14 521 538 ;
-C 112 ; WX 556 ; N p ; B 58 -207 517 538 ;
-C 113 ; WX 556 ; N q ; B 35 -207 494 538 ;
-C 114 ; WX 333 ; N r ; B 77 0 332 538 ;
-C 115 ; WX 500 ; N s ; B 32 -15 464 538 ;
-C 116 ; WX 278 ; N t ; B 14 -7 257 669 ;
-C 117 ; WX 556 ; N u ; B 68 -15 489 523 ;
-C 118 ; WX 500 ; N v ; B 8 0 492 523 ;
-C 119 ; WX 722 ; N w ; B 14 0 709 523 ;
-C 120 ; WX 500 ; N x ; B 11 0 490 523 ;
-C 121 ; WX 500 ; N y ; B 11 -214 489 523 ;
-C 122 ; WX 500 ; N z ; B 31 0 469 523 ;
-C 123 ; WX 334 ; N braceleft ; B 42 -196 292 722 ;
-C 124 ; WX 260 ; N bar ; B 94 -225 167 775 ;
-C 125 ; WX 334 ; N braceright ; B 42 -196 292 722 ;
-C 126 ; WX 584 ; N asciitilde ; B 61 180 523 326 ;
-C 161 ; WX 333 ; N exclamdown ; B 118 -195 215 523 ;
-C 162 ; WX 556 ; N cent ; B 51 -115 513 623 ;
-C 163 ; WX 556 ; N sterling ; B 33 -16 539 718 ;
-C 164 ; WX 167 ; N fraction ; B -166 -19 333 703 ;
-C 165 ; WX 556 ; N yen ; B 3 0 553 688 ;
-C 166 ; WX 556 ; N florin ; B -11 -207 501 737 ;
-C 167 ; WX 556 ; N section ; B 43 -191 512 737 ;
-C 168 ; WX 556 ; N currency ; B 28 99 528 603 ;
-C 169 ; WX 191 ; N quotesingle ; B 59 463 132 718 ;
-C 170 ; WX 333 ; N quotedblleft ; B 38 470 307 725 ;
-C 171 ; WX 556 ; N guillemotleft ; B 97 108 459 446 ;
-C 172 ; WX 333 ; N guilsinglleft ; B 88 108 245 446 ;
-C 173 ; WX 333 ; N guilsinglright ; B 88 108 245 446 ;
-C 174 ; WX 500 ; N fi ; B 14 0 434 728 ;
-C 175 ; WX 500 ; N fl ; B 14 0 432 728 ;
-C 177 ; WX 556 ; N endash ; B 0 240 556 313 ;
-C 178 ; WX 556 ; N dagger ; B 43 -159 514 718 ;
-C 179 ; WX 556 ; N daggerdbl ; B 43 -159 514 718 ;
-C 180 ; WX 278 ; N periodcentered ; B 77 190 202 315 ;
-C 182 ; WX 537 ; N paragraph ; B 18 -173 497 718 ;
-C 183 ; WX 350 ; N bullet ; B 18 202 333 517 ;
-C 184 ; WX 222 ; N quotesinglbase ; B 53 -149 157 106 ;
-C 185 ; WX 333 ; N quotedblbase ; B 26 -149 295 106 ;
-C 186 ; WX 333 ; N quotedblright ; B 26 463 295 718 ;
-C 187 ; WX 556 ; N guillemotright ; B 97 108 459 446 ;
-C 188 ; WX 1000 ; N ellipsis ; B 115 0 885 106 ;
-C 189 ; WX 1000 ; N perthousand ; B 7 -19 994 703 ;
-C 191 ; WX 611 ; N questiondown ; B 91 -201 527 525 ;
-C 193 ; WX 333 ; N grave ; B 14 593 211 734 ;
-C 194 ; WX 333 ; N acute ; B 122 593 319 734 ;
-C 195 ; WX 333 ; N circumflex ; B 21 593 312 734 ;
-C 196 ; WX 333 ; N tilde ; B -4 606 337 722 ;
-C 197 ; WX 333 ; N macron ; B 10 627 323 684 ;
-C 198 ; WX 333 ; N breve ; B 13 595 321 731 ;
-C 199 ; WX 333 ; N dotaccent ; B 121 604 212 706 ;
-C 200 ; WX 333 ; N dieresis ; B 40 604 293 706 ;
-C 202 ; WX 333 ; N ring ; B 75 572 259 756 ;
-C 203 ; WX 333 ; N cedilla ; B 45 -225 259 0 ;
-C 205 ; WX 333 ; N hungarumlaut ; B 31 593 409 734 ;
-C 206 ; WX 333 ; N ogonek ; B 73 -225 287 0 ;
-C 207 ; WX 333 ; N caron ; B 21 593 312 734 ;
-C 208 ; WX 1000 ; N emdash ; B 0 240 1000 313 ;
-C 225 ; WX 1000 ; N AE ; B 8 0 951 718 ;
-C 227 ; WX 370 ; N ordfeminine ; B 24 405 346 737 ;
-C 232 ; WX 556 ; N Lslash ; B -20 0 537 718 ;
-C 233 ; WX 778 ; N Oslash ; B 39 -19 740 737 ;
-C 234 ; WX 1000 ; N OE ; B 36 -19 965 737 ;
-C 235 ; WX 365 ; N ordmasculine ; B 25 405 341 737 ;
-C 241 ; WX 889 ; N ae ; B 36 -15 847 538 ;
-C 245 ; WX 278 ; N dotlessi ; B 95 0 183 523 ;
-C 248 ; WX 222 ; N lslash ; B -20 0 242 718 ;
-C 249 ; WX 611 ; N oslash ; B 28 -22 537 545 ;
-C 250 ; WX 944 ; N oe ; B 35 -15 902 538 ;
-C 251 ; WX 611 ; N germandbls ; B 67 -15 571 728 ;
-C -1 ; WX 278 ; N Idieresis ; B 13 0 266 901 ;
-C -1 ; WX 556 ; N eacute ; B 40 -15 516 734 ;
-C -1 ; WX 556 ; N abreve ; B 36 -15 530 731 ;
-C -1 ; WX 556 ; N uhungarumlaut ; B 68 -15 521 734 ;
-C -1 ; WX 556 ; N ecaron ; B 40 -15 516 734 ;
-C -1 ; WX 667 ; N Ydieresis ; B 14 0 653 901 ;
-C -1 ; WX 584 ; N divide ; B 39 -19 545 524 ;
-C -1 ; WX 667 ; N Yacute ; B 14 0 653 929 ;
-C -1 ; WX 667 ; N Acircumflex ; B 14 0 654 929 ;
-C -1 ; WX 556 ; N aacute ; B 36 -15 530 734 ;
-C -1 ; WX 722 ; N Ucircumflex ; B 79 -19 644 929 ;
-C -1 ; WX 500 ; N yacute ; B 11 -214 489 734 ;
-C -1 ; WX 500 ; N scommaaccent ; B 32 -225 464 538 ;
-C -1 ; WX 556 ; N ecircumflex ; B 40 -15 516 734 ;
-C -1 ; WX 722 ; N Uring ; B 79 -19 644 931 ;
-C -1 ; WX 722 ; N Udieresis ; B 79 -19 644 901 ;
-C -1 ; WX 556 ; N aogonek ; B 36 -220 547 538 ;
-C -1 ; WX 722 ; N Uacute ; B 79 -19 644 929 ;
-C -1 ; WX 556 ; N uogonek ; B 68 -225 519 523 ;
-C -1 ; WX 667 ; N Edieresis ; B 86 0 616 901 ;
-C -1 ; WX 722 ; N Dcroat ; B 0 0 674 718 ;
-C -1 ; WX 250 ; N commaaccent ; B 87 -225 181 -40 ;
-C -1 ; WX 737 ; N copyright ; B -14 -19 752 737 ;
-C -1 ; WX 667 ; N Emacron ; B 86 0 616 879 ;
-C -1 ; WX 500 ; N ccaron ; B 30 -15 477 734 ;
-C -1 ; WX 556 ; N aring ; B 36 -15 530 756 ;
-C -1 ; WX 722 ; N Ncommaaccent ; B 76 -225 646 718 ;
-C -1 ; WX 222 ; N lacute ; B 67 0 264 929 ;
-C -1 ; WX 556 ; N agrave ; B 36 -15 530 734 ;
-C -1 ; WX 611 ; N Tcommaaccent ; B 14 -225 597 718 ;
-C -1 ; WX 722 ; N Cacute ; B 44 -19 681 929 ;
-C -1 ; WX 556 ; N atilde ; B 36 -15 530 722 ;
-C -1 ; WX 667 ; N Edotaccent ; B 86 0 616 901 ;
-C -1 ; WX 500 ; N scaron ; B 32 -15 464 734 ;
-C -1 ; WX 500 ; N scedilla ; B 32 -225 464 538 ;
-C -1 ; WX 278 ; N iacute ; B 95 0 292 734 ;
-C -1 ; WX 471 ; N lozenge ; B 10 0 462 728 ;
-C -1 ; WX 722 ; N Rcaron ; B 88 0 684 929 ;
-C -1 ; WX 778 ; N Gcommaaccent ; B 48 -225 704 737 ;
-C -1 ; WX 556 ; N ucircumflex ; B 68 -15 489 734 ;
-C -1 ; WX 556 ; N acircumflex ; B 36 -15 530 734 ;
-C -1 ; WX 667 ; N Amacron ; B 14 0 654 879 ;
-C -1 ; WX 333 ; N rcaron ; B 61 0 352 734 ;
-C -1 ; WX 500 ; N ccedilla ; B 30 -225 477 538 ;
-C -1 ; WX 611 ; N Zdotaccent ; B 23 0 588 901 ;
-C -1 ; WX 667 ; N Thorn ; B 86 0 622 718 ;
-C -1 ; WX 778 ; N Omacron ; B 39 -19 739 879 ;
-C -1 ; WX 722 ; N Racute ; B 88 0 684 929 ;
-C -1 ; WX 667 ; N Sacute ; B 49 -19 620 929 ;
-C -1 ; WX 643 ; N dcaron ; B 35 -15 655 718 ;
-C -1 ; WX 722 ; N Umacron ; B 79 -19 644 879 ;
-C -1 ; WX 556 ; N uring ; B 68 -15 489 756 ;
-C -1 ; WX 333 ; N threesuperior ; B 5 270 325 703 ;
-C -1 ; WX 778 ; N Ograve ; B 39 -19 739 929 ;
-C -1 ; WX 667 ; N Agrave ; B 14 0 654 929 ;
-C -1 ; WX 667 ; N Abreve ; B 14 0 654 926 ;
-C -1 ; WX 584 ; N multiply ; B 39 0 545 506 ;
-C -1 ; WX 556 ; N uacute ; B 68 -15 489 734 ;
-C -1 ; WX 611 ; N Tcaron ; B 14 0 597 929 ;
-C -1 ; WX 476 ; N partialdiff ; B 13 -38 463 714 ;
-C -1 ; WX 500 ; N ydieresis ; B 11 -214 489 706 ;
-C -1 ; WX 722 ; N Nacute ; B 76 0 646 929 ;
-C -1 ; WX 278 ; N icircumflex ; B -6 0 285 734 ;
-C -1 ; WX 667 ; N Ecircumflex ; B 86 0 616 929 ;
-C -1 ; WX 556 ; N adieresis ; B 36 -15 530 706 ;
-C -1 ; WX 556 ; N edieresis ; B 40 -15 516 706 ;
-C -1 ; WX 500 ; N cacute ; B 30 -15 477 734 ;
-C -1 ; WX 556 ; N nacute ; B 65 0 491 734 ;
-C -1 ; WX 556 ; N umacron ; B 68 -15 489 684 ;
-C -1 ; WX 722 ; N Ncaron ; B 76 0 646 929 ;
-C -1 ; WX 278 ; N Iacute ; B 91 0 292 929 ;
-C -1 ; WX 584 ; N plusminus ; B 39 0 545 506 ;
-C -1 ; WX 260 ; N brokenbar ; B 94 -150 167 700 ;
-C -1 ; WX 737 ; N registered ; B -14 -19 752 737 ;
-C -1 ; WX 778 ; N Gbreve ; B 48 -19 704 926 ;
-C -1 ; WX 278 ; N Idotaccent ; B 91 0 188 901 ;
-C -1 ; WX 600 ; N summation ; B 15 -10 586 706 ;
-C -1 ; WX 667 ; N Egrave ; B 86 0 616 929 ;
-C -1 ; WX 333 ; N racute ; B 77 0 332 734 ;
-C -1 ; WX 556 ; N omacron ; B 35 -14 521 684 ;
-C -1 ; WX 611 ; N Zacute ; B 23 0 588 929 ;
-C -1 ; WX 611 ; N Zcaron ; B 23 0 588 929 ;
-C -1 ; WX 549 ; N greaterequal ; B 26 0 523 674 ;
-C -1 ; WX 722 ; N Eth ; B 0 0 674 718 ;
-C -1 ; WX 722 ; N Ccedilla ; B 44 -225 681 737 ;
-C -1 ; WX 222 ; N lcommaaccent ; B 67 -225 167 718 ;
-C -1 ; WX 317 ; N tcaron ; B 14 -7 329 808 ;
-C -1 ; WX 556 ; N eogonek ; B 40 -225 516 538 ;
-C -1 ; WX 722 ; N Uogonek ; B 79 -225 644 718 ;
-C -1 ; WX 667 ; N Aacute ; B 14 0 654 929 ;
-C -1 ; WX 667 ; N Adieresis ; B 14 0 654 901 ;
-C -1 ; WX 556 ; N egrave ; B 40 -15 516 734 ;
-C -1 ; WX 500 ; N zacute ; B 31 0 469 734 ;
-C -1 ; WX 222 ; N iogonek ; B -31 -225 183 718 ;
-C -1 ; WX 778 ; N Oacute ; B 39 -19 739 929 ;
-C -1 ; WX 556 ; N oacute ; B 35 -14 521 734 ;
-C -1 ; WX 556 ; N amacron ; B 36 -15 530 684 ;
-C -1 ; WX 500 ; N sacute ; B 32 -15 464 734 ;
-C -1 ; WX 278 ; N idieresis ; B 13 0 266 706 ;
-C -1 ; WX 778 ; N Ocircumflex ; B 39 -19 739 929 ;
-C -1 ; WX 722 ; N Ugrave ; B 79 -19 644 929 ;
-C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
-C -1 ; WX 556 ; N thorn ; B 58 -207 517 718 ;
-C -1 ; WX 333 ; N twosuperior ; B 4 281 323 703 ;
-C -1 ; WX 778 ; N Odieresis ; B 39 -19 739 901 ;
-C -1 ; WX 556 ; N mu ; B 68 -207 489 523 ;
-C -1 ; WX 278 ; N igrave ; B -13 0 184 734 ;
-C -1 ; WX 556 ; N ohungarumlaut ; B 35 -14 521 734 ;
-C -1 ; WX 667 ; N Eogonek ; B 86 -220 633 718 ;
-C -1 ; WX 556 ; N dcroat ; B 35 -15 550 718 ;
-C -1 ; WX 834 ; N threequarters ; B 45 -19 810 703 ;
-C -1 ; WX 667 ; N Scedilla ; B 49 -225 620 737 ;
-C -1 ; WX 299 ; N lcaron ; B 67 0 311 718 ;
-C -1 ; WX 667 ; N Kcommaaccent ; B 76 -225 663 718 ;
-C -1 ; WX 556 ; N Lacute ; B 76 0 537 929 ;
-C -1 ; WX 1000 ; N trademark ; B 46 306 903 718 ;
-C -1 ; WX 556 ; N edotaccent ; B 40 -15 516 706 ;
-C -1 ; WX 278 ; N Igrave ; B -13 0 188 929 ;
-C -1 ; WX 278 ; N Imacron ; B -17 0 296 879 ;
-C -1 ; WX 556 ; N Lcaron ; B 76 0 537 718 ;
-C -1 ; WX 834 ; N onehalf ; B 43 -19 773 703 ;
-C -1 ; WX 549 ; N lessequal ; B 26 0 523 674 ;
-C -1 ; WX 556 ; N ocircumflex ; B 35 -14 521 734 ;
-C -1 ; WX 556 ; N ntilde ; B 65 0 491 722 ;
-C -1 ; WX 722 ; N Uhungarumlaut ; B 79 -19 644 929 ;
-C -1 ; WX 667 ; N Eacute ; B 86 0 616 929 ;
-C -1 ; WX 556 ; N emacron ; B 40 -15 516 684 ;
-C -1 ; WX 556 ; N gbreve ; B 40 -220 499 731 ;
-C -1 ; WX 834 ; N onequarter ; B 73 -19 756 703 ;
-C -1 ; WX 667 ; N Scaron ; B 49 -19 620 929 ;
-C -1 ; WX 667 ; N Scommaaccent ; B 49 -225 620 737 ;
-C -1 ; WX 778 ; N Ohungarumlaut ; B 39 -19 739 929 ;
-C -1 ; WX 400 ; N degree ; B 54 411 346 703 ;
-C -1 ; WX 556 ; N ograve ; B 35 -14 521 734 ;
-C -1 ; WX 722 ; N Ccaron ; B 44 -19 681 929 ;
-C -1 ; WX 556 ; N ugrave ; B 68 -15 489 734 ;
-C -1 ; WX 453 ; N radical ; B -4 -80 458 762 ;
-C -1 ; WX 722 ; N Dcaron ; B 81 0 674 929 ;
-C -1 ; WX 333 ; N rcommaaccent ; B 77 -225 332 538 ;
-C -1 ; WX 722 ; N Ntilde ; B 76 0 646 917 ;
-C -1 ; WX 556 ; N otilde ; B 35 -14 521 722 ;
-C -1 ; WX 722 ; N Rcommaaccent ; B 88 -225 684 718 ;
-C -1 ; WX 556 ; N Lcommaaccent ; B 76 -225 537 718 ;
-C -1 ; WX 667 ; N Atilde ; B 14 0 654 917 ;
-C -1 ; WX 667 ; N Aogonek ; B 14 -225 654 718 ;
-C -1 ; WX 667 ; N Aring ; B 14 0 654 931 ;
-C -1 ; WX 778 ; N Otilde ; B 39 -19 739 917 ;
-C -1 ; WX 500 ; N zdotaccent ; B 31 0 469 706 ;
-C -1 ; WX 667 ; N Ecaron ; B 86 0 616 929 ;
-C -1 ; WX 278 ; N Iogonek ; B -3 -225 211 718 ;
-C -1 ; WX 500 ; N kcommaaccent ; B 67 -225 501 718 ;
-C -1 ; WX 584 ; N minus ; B 39 216 545 289 ;
-C -1 ; WX 278 ; N Icircumflex ; B -6 0 285 929 ;
-C -1 ; WX 556 ; N ncaron ; B 65 0 491 734 ;
-C -1 ; WX 278 ; N tcommaaccent ; B 14 -225 257 669 ;
-C -1 ; WX 584 ; N logicalnot ; B 39 108 545 390 ;
-C -1 ; WX 556 ; N odieresis ; B 35 -14 521 706 ;
-C -1 ; WX 556 ; N udieresis ; B 68 -15 489 706 ;
-C -1 ; WX 549 ; N notequal ; B 12 -35 537 551 ;
-C -1 ; WX 556 ; N gcommaaccent ; B 40 -220 499 822 ;
-C -1 ; WX 556 ; N eth ; B 35 -15 522 737 ;
-C -1 ; WX 500 ; N zcaron ; B 31 0 469 734 ;
-C -1 ; WX 556 ; N ncommaaccent ; B 65 -225 491 538 ;
-C -1 ; WX 333 ; N onesuperior ; B 43 281 222 703 ;
-C -1 ; WX 278 ; N imacron ; B 5 0 272 684 ;
-C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ;
-EndCharMetrics
-StartKernData
-StartKernPairs 2705
-KPX A C -30
-KPX A Cacute -30
-KPX A Ccaron -30
-KPX A Ccedilla -30
-KPX A G -30
-KPX A Gbreve -30
-KPX A Gcommaaccent -30
-KPX A O -30
-KPX A Oacute -30
-KPX A Ocircumflex -30
-KPX A Odieresis -30
-KPX A Ograve -30
-KPX A Ohungarumlaut -30
-KPX A Omacron -30
-KPX A Oslash -30
-KPX A Otilde -30
-KPX A Q -30
-KPX A T -120
-KPX A Tcaron -120
-KPX A Tcommaaccent -120
-KPX A U -50
-KPX A Uacute -50
-KPX A Ucircumflex -50
-KPX A Udieresis -50
-KPX A Ugrave -50
-KPX A Uhungarumlaut -50
-KPX A Umacron -50
-KPX A Uogonek -50
-KPX A Uring -50
-KPX A V -70
-KPX A W -50
-KPX A Y -100
-KPX A Yacute -100
-KPX A Ydieresis -100
-KPX A u -30
-KPX A uacute -30
-KPX A ucircumflex -30
-KPX A udieresis -30
-KPX A ugrave -30
-KPX A uhungarumlaut -30
-KPX A umacron -30
-KPX A uogonek -30
-KPX A uring -30
-KPX A v -40
-KPX A w -40
-KPX A y -40
-KPX A yacute -40
-KPX A ydieresis -40
-KPX Aacute C -30
-KPX Aacute Cacute -30
-KPX Aacute Ccaron -30
-KPX Aacute Ccedilla -30
-KPX Aacute G -30
-KPX Aacute Gbreve -30
-KPX Aacute Gcommaaccent -30
-KPX Aacute O -30
-KPX Aacute Oacute -30
-KPX Aacute Ocircumflex -30
-KPX Aacute Odieresis -30
-KPX Aacute Ograve -30
-KPX Aacute Ohungarumlaut -30
-KPX Aacute Omacron -30
-KPX Aacute Oslash -30
-KPX Aacute Otilde -30
-KPX Aacute Q -30
-KPX Aacute T -120
-KPX Aacute Tcaron -120
-KPX Aacute Tcommaaccent -120
-KPX Aacute U -50
-KPX Aacute Uacute -50
-KPX Aacute Ucircumflex -50
-KPX Aacute Udieresis -50
-KPX Aacute Ugrave -50
-KPX Aacute Uhungarumlaut -50
-KPX Aacute Umacron -50
-KPX Aacute Uogonek -50
-KPX Aacute Uring -50
-KPX Aacute V -70
-KPX Aacute W -50
-KPX Aacute Y -100
-KPX Aacute Yacute -100
-KPX Aacute Ydieresis -100
-KPX Aacute u -30
-KPX Aacute uacute -30
-KPX Aacute ucircumflex -30
-KPX Aacute udieresis -30
-KPX Aacute ugrave -30
-KPX Aacute uhungarumlaut -30
-KPX Aacute umacron -30
-KPX Aacute uogonek -30
-KPX Aacute uring -30
-KPX Aacute v -40
-KPX Aacute w -40
-KPX Aacute y -40
-KPX Aacute yacute -40
-KPX Aacute ydieresis -40
-KPX Abreve C -30
-KPX Abreve Cacute -30
-KPX Abreve Ccaron -30
-KPX Abreve Ccedilla -30
-KPX Abreve G -30
-KPX Abreve Gbreve -30
-KPX Abreve Gcommaaccent -30
-KPX Abreve O -30
-KPX Abreve Oacute -30
-KPX Abreve Ocircumflex -30
-KPX Abreve Odieresis -30
-KPX Abreve Ograve -30
-KPX Abreve Ohungarumlaut -30
-KPX Abreve Omacron -30
-KPX Abreve Oslash -30
-KPX Abreve Otilde -30
-KPX Abreve Q -30
-KPX Abreve T -120
-KPX Abreve Tcaron -120
-KPX Abreve Tcommaaccent -120
-KPX Abreve U -50
-KPX Abreve Uacute -50
-KPX Abreve Ucircumflex -50
-KPX Abreve Udieresis -50
-KPX Abreve Ugrave -50
-KPX Abreve Uhungarumlaut -50
-KPX Abreve Umacron -50
-KPX Abreve Uogonek -50
-KPX Abreve Uring -50
-KPX Abreve V -70
-KPX Abreve W -50
-KPX Abreve Y -100
-KPX Abreve Yacute -100
-KPX Abreve Ydieresis -100
-KPX Abreve u -30
-KPX Abreve uacute -30
-KPX Abreve ucircumflex -30
-KPX Abreve udieresis -30
-KPX Abreve ugrave -30
-KPX Abreve uhungarumlaut -30
-KPX Abreve umacron -30
-KPX Abreve uogonek -30
-KPX Abreve uring -30
-KPX Abreve v -40
-KPX Abreve w -40
-KPX Abreve y -40
-KPX Abreve yacute -40
-KPX Abreve ydieresis -40
-KPX Acircumflex C -30
-KPX Acircumflex Cacute -30
-KPX Acircumflex Ccaron -30
-KPX Acircumflex Ccedilla -30
-KPX Acircumflex G -30
-KPX Acircumflex Gbreve -30
-KPX Acircumflex Gcommaaccent -30
-KPX Acircumflex O -30
-KPX Acircumflex Oacute -30
-KPX Acircumflex Ocircumflex -30
-KPX Acircumflex Odieresis -30
-KPX Acircumflex Ograve -30
-KPX Acircumflex Ohungarumlaut -30
-KPX Acircumflex Omacron -30
-KPX Acircumflex Oslash -30
-KPX Acircumflex Otilde -30
-KPX Acircumflex Q -30
-KPX Acircumflex T -120
-KPX Acircumflex Tcaron -120
-KPX Acircumflex Tcommaaccent -120
-KPX Acircumflex U -50
-KPX Acircumflex Uacute -50
-KPX Acircumflex Ucircumflex -50
-KPX Acircumflex Udieresis -50
-KPX Acircumflex Ugrave -50
-KPX Acircumflex Uhungarumlaut -50
-KPX Acircumflex Umacron -50
-KPX Acircumflex Uogonek -50
-KPX Acircumflex Uring -50
-KPX Acircumflex V -70
-KPX Acircumflex W -50
-KPX Acircumflex Y -100
-KPX Acircumflex Yacute -100
-KPX Acircumflex Ydieresis -100
-KPX Acircumflex u -30
-KPX Acircumflex uacute -30
-KPX Acircumflex ucircumflex -30
-KPX Acircumflex udieresis -30
-KPX Acircumflex ugrave -30
-KPX Acircumflex uhungarumlaut -30
-KPX Acircumflex umacron -30
-KPX Acircumflex uogonek -30
-KPX Acircumflex uring -30
-KPX Acircumflex v -40
-KPX Acircumflex w -40
-KPX Acircumflex y -40
-KPX Acircumflex yacute -40
-KPX Acircumflex ydieresis -40
-KPX Adieresis C -30
-KPX Adieresis Cacute -30
-KPX Adieresis Ccaron -30
-KPX Adieresis Ccedilla -30
-KPX Adieresis G -30
-KPX Adieresis Gbreve -30
-KPX Adieresis Gcommaaccent -30
-KPX Adieresis O -30
-KPX Adieresis Oacute -30
-KPX Adieresis Ocircumflex -30
-KPX Adieresis Odieresis -30
-KPX Adieresis Ograve -30
-KPX Adieresis Ohungarumlaut -30
-KPX Adieresis Omacron -30
-KPX Adieresis Oslash -30
-KPX Adieresis Otilde -30
-KPX Adieresis Q -30
-KPX Adieresis T -120
-KPX Adieresis Tcaron -120
-KPX Adieresis Tcommaaccent -120
-KPX Adieresis U -50
-KPX Adieresis Uacute -50
-KPX Adieresis Ucircumflex -50
-KPX Adieresis Udieresis -50
-KPX Adieresis Ugrave -50
-KPX Adieresis Uhungarumlaut -50
-KPX Adieresis Umacron -50
-KPX Adieresis Uogonek -50
-KPX Adieresis Uring -50
-KPX Adieresis V -70
-KPX Adieresis W -50
-KPX Adieresis Y -100
-KPX Adieresis Yacute -100
-KPX Adieresis Ydieresis -100
-KPX Adieresis u -30
-KPX Adieresis uacute -30
-KPX Adieresis ucircumflex -30
-KPX Adieresis udieresis -30
-KPX Adieresis ugrave -30
-KPX Adieresis uhungarumlaut -30
-KPX Adieresis umacron -30
-KPX Adieresis uogonek -30
-KPX Adieresis uring -30
-KPX Adieresis v -40
-KPX Adieresis w -40
-KPX Adieresis y -40
-KPX Adieresis yacute -40
-KPX Adieresis ydieresis -40
-KPX Agrave C -30
-KPX Agrave Cacute -30
-KPX Agrave Ccaron -30
-KPX Agrave Ccedilla -30
-KPX Agrave G -30
-KPX Agrave Gbreve -30
-KPX Agrave Gcommaaccent -30
-KPX Agrave O -30
-KPX Agrave Oacute -30
-KPX Agrave Ocircumflex -30
-KPX Agrave Odieresis -30
-KPX Agrave Ograve -30
-KPX Agrave Ohungarumlaut -30
-KPX Agrave Omacron -30
-KPX Agrave Oslash -30
-KPX Agrave Otilde -30
-KPX Agrave Q -30
-KPX Agrave T -120
-KPX Agrave Tcaron -120
-KPX Agrave Tcommaaccent -120
-KPX Agrave U -50
-KPX Agrave Uacute -50
-KPX Agrave Ucircumflex -50
-KPX Agrave Udieresis -50
-KPX Agrave Ugrave -50
-KPX Agrave Uhungarumlaut -50
-KPX Agrave Umacron -50
-KPX Agrave Uogonek -50
-KPX Agrave Uring -50
-KPX Agrave V -70
-KPX Agrave W -50
-KPX Agrave Y -100
-KPX Agrave Yacute -100
-KPX Agrave Ydieresis -100
-KPX Agrave u -30
-KPX Agrave uacute -30
-KPX Agrave ucircumflex -30
-KPX Agrave udieresis -30
-KPX Agrave ugrave -30
-KPX Agrave uhungarumlaut -30
-KPX Agrave umacron -30
-KPX Agrave uogonek -30
-KPX Agrave uring -30
-KPX Agrave v -40
-KPX Agrave w -40
-KPX Agrave y -40
-KPX Agrave yacute -40
-KPX Agrave ydieresis -40
-KPX Amacron C -30
-KPX Amacron Cacute -30
-KPX Amacron Ccaron -30
-KPX Amacron Ccedilla -30
-KPX Amacron G -30
-KPX Amacron Gbreve -30
-KPX Amacron Gcommaaccent -30
-KPX Amacron O -30
-KPX Amacron Oacute -30
-KPX Amacron Ocircumflex -30
-KPX Amacron Odieresis -30
-KPX Amacron Ograve -30
-KPX Amacron Ohungarumlaut -30
-KPX Amacron Omacron -30
-KPX Amacron Oslash -30
-KPX Amacron Otilde -30
-KPX Amacron Q -30
-KPX Amacron T -120
-KPX Amacron Tcaron -120
-KPX Amacron Tcommaaccent -120
-KPX Amacron U -50
-KPX Amacron Uacute -50
-KPX Amacron Ucircumflex -50
-KPX Amacron Udieresis -50
-KPX Amacron Ugrave -50
-KPX Amacron Uhungarumlaut -50
-KPX Amacron Umacron -50
-KPX Amacron Uogonek -50
-KPX Amacron Uring -50
-KPX Amacron V -70
-KPX Amacron W -50
-KPX Amacron Y -100
-KPX Amacron Yacute -100
-KPX Amacron Ydieresis -100
-KPX Amacron u -30
-KPX Amacron uacute -30
-KPX Amacron ucircumflex -30
-KPX Amacron udieresis -30
-KPX Amacron ugrave -30
-KPX Amacron uhungarumlaut -30
-KPX Amacron umacron -30
-KPX Amacron uogonek -30
-KPX Amacron uring -30
-KPX Amacron v -40
-KPX Amacron w -40
-KPX Amacron y -40
-KPX Amacron yacute -40
-KPX Amacron ydieresis -40
-KPX Aogonek C -30
-KPX Aogonek Cacute -30
-KPX Aogonek Ccaron -30
-KPX Aogonek Ccedilla -30
-KPX Aogonek G -30
-KPX Aogonek Gbreve -30
-KPX Aogonek Gcommaaccent -30
-KPX Aogonek O -30
-KPX Aogonek Oacute -30
-KPX Aogonek Ocircumflex -30
-KPX Aogonek Odieresis -30
-KPX Aogonek Ograve -30
-KPX Aogonek Ohungarumlaut -30
-KPX Aogonek Omacron -30
-KPX Aogonek Oslash -30
-KPX Aogonek Otilde -30
-KPX Aogonek Q -30
-KPX Aogonek T -120
-KPX Aogonek Tcaron -120
-KPX Aogonek Tcommaaccent -120
-KPX Aogonek U -50
-KPX Aogonek Uacute -50
-KPX Aogonek Ucircumflex -50
-KPX Aogonek Udieresis -50
-KPX Aogonek Ugrave -50
-KPX Aogonek Uhungarumlaut -50
-KPX Aogonek Umacron -50
-KPX Aogonek Uogonek -50
-KPX Aogonek Uring -50
-KPX Aogonek V -70
-KPX Aogonek W -50
-KPX Aogonek Y -100
-KPX Aogonek Yacute -100
-KPX Aogonek Ydieresis -100
-KPX Aogonek u -30
-KPX Aogonek uacute -30
-KPX Aogonek ucircumflex -30
-KPX Aogonek udieresis -30
-KPX Aogonek ugrave -30
-KPX Aogonek uhungarumlaut -30
-KPX Aogonek umacron -30
-KPX Aogonek uogonek -30
-KPX Aogonek uring -30
-KPX Aogonek v -40
-KPX Aogonek w -40
-KPX Aogonek y -40
-KPX Aogonek yacute -40
-KPX Aogonek ydieresis -40
-KPX Aring C -30
-KPX Aring Cacute -30
-KPX Aring Ccaron -30
-KPX Aring Ccedilla -30
-KPX Aring G -30
-KPX Aring Gbreve -30
-KPX Aring Gcommaaccent -30
-KPX Aring O -30
-KPX Aring Oacute -30
-KPX Aring Ocircumflex -30
-KPX Aring Odieresis -30
-KPX Aring Ograve -30
-KPX Aring Ohungarumlaut -30
-KPX Aring Omacron -30
-KPX Aring Oslash -30
-KPX Aring Otilde -30
-KPX Aring Q -30
-KPX Aring T -120
-KPX Aring Tcaron -120
-KPX Aring Tcommaaccent -120
-KPX Aring U -50
-KPX Aring Uacute -50
-KPX Aring Ucircumflex -50
-KPX Aring Udieresis -50
-KPX Aring Ugrave -50
-KPX Aring Uhungarumlaut -50
-KPX Aring Umacron -50
-KPX Aring Uogonek -50
-KPX Aring Uring -50
-KPX Aring V -70
-KPX Aring W -50
-KPX Aring Y -100
-KPX Aring Yacute -100
-KPX Aring Ydieresis -100
-KPX Aring u -30
-KPX Aring uacute -30
-KPX Aring ucircumflex -30
-KPX Aring udieresis -30
-KPX Aring ugrave -30
-KPX Aring uhungarumlaut -30
-KPX Aring umacron -30
-KPX Aring uogonek -30
-KPX Aring uring -30
-KPX Aring v -40
-KPX Aring w -40
-KPX Aring y -40
-KPX Aring yacute -40
-KPX Aring ydieresis -40
-KPX Atilde C -30
-KPX Atilde Cacute -30
-KPX Atilde Ccaron -30
-KPX Atilde Ccedilla -30
-KPX Atilde G -30
-KPX Atilde Gbreve -30
-KPX Atilde Gcommaaccent -30
-KPX Atilde O -30
-KPX Atilde Oacute -30
-KPX Atilde Ocircumflex -30
-KPX Atilde Odieresis -30
-KPX Atilde Ograve -30
-KPX Atilde Ohungarumlaut -30
-KPX Atilde Omacron -30
-KPX Atilde Oslash -30
-KPX Atilde Otilde -30
-KPX Atilde Q -30
-KPX Atilde T -120
-KPX Atilde Tcaron -120
-KPX Atilde Tcommaaccent -120
-KPX Atilde U -50
-KPX Atilde Uacute -50
-KPX Atilde Ucircumflex -50
-KPX Atilde Udieresis -50
-KPX Atilde Ugrave -50
-KPX Atilde Uhungarumlaut -50
-KPX Atilde Umacron -50
-KPX Atilde Uogonek -50
-KPX Atilde Uring -50
-KPX Atilde V -70
-KPX Atilde W -50
-KPX Atilde Y -100
-KPX Atilde Yacute -100
-KPX Atilde Ydieresis -100
-KPX Atilde u -30
-KPX Atilde uacute -30
-KPX Atilde ucircumflex -30
-KPX Atilde udieresis -30
-KPX Atilde ugrave -30
-KPX Atilde uhungarumlaut -30
-KPX Atilde umacron -30
-KPX Atilde uogonek -30
-KPX Atilde uring -30
-KPX Atilde v -40
-KPX Atilde w -40
-KPX Atilde y -40
-KPX Atilde yacute -40
-KPX Atilde ydieresis -40
-KPX B U -10
-KPX B Uacute -10
-KPX B Ucircumflex -10
-KPX B Udieresis -10
-KPX B Ugrave -10
-KPX B Uhungarumlaut -10
-KPX B Umacron -10
-KPX B Uogonek -10
-KPX B Uring -10
-KPX B comma -20
-KPX B period -20
-KPX C comma -30
-KPX C period -30
-KPX Cacute comma -30
-KPX Cacute period -30
-KPX Ccaron comma -30
-KPX Ccaron period -30
-KPX Ccedilla comma -30
-KPX Ccedilla period -30
-KPX D A -40
-KPX D Aacute -40
-KPX D Abreve -40
-KPX D Acircumflex -40
-KPX D Adieresis -40
-KPX D Agrave -40
-KPX D Amacron -40
-KPX D Aogonek -40
-KPX D Aring -40
-KPX D Atilde -40
-KPX D V -70
-KPX D W -40
-KPX D Y -90
-KPX D Yacute -90
-KPX D Ydieresis -90
-KPX D comma -70
-KPX D period -70
-KPX Dcaron A -40
-KPX Dcaron Aacute -40
-KPX Dcaron Abreve -40
-KPX Dcaron Acircumflex -40
-KPX Dcaron Adieresis -40
-KPX Dcaron Agrave -40
-KPX Dcaron Amacron -40
-KPX Dcaron Aogonek -40
-KPX Dcaron Aring -40
-KPX Dcaron Atilde -40
-KPX Dcaron V -70
-KPX Dcaron W -40
-KPX Dcaron Y -90
-KPX Dcaron Yacute -90
-KPX Dcaron Ydieresis -90
-KPX Dcaron comma -70
-KPX Dcaron period -70
-KPX Dcroat A -40
-KPX Dcroat Aacute -40
-KPX Dcroat Abreve -40
-KPX Dcroat Acircumflex -40
-KPX Dcroat Adieresis -40
-KPX Dcroat Agrave -40
-KPX Dcroat Amacron -40
-KPX Dcroat Aogonek -40
-KPX Dcroat Aring -40
-KPX Dcroat Atilde -40
-KPX Dcroat V -70
-KPX Dcroat W -40
-KPX Dcroat Y -90
-KPX Dcroat Yacute -90
-KPX Dcroat Ydieresis -90
-KPX Dcroat comma -70
-KPX Dcroat period -70
-KPX F A -80
-KPX F Aacute -80
-KPX F Abreve -80
-KPX F Acircumflex -80
-KPX F Adieresis -80
-KPX F Agrave -80
-KPX F Amacron -80
-KPX F Aogonek -80
-KPX F Aring -80
-KPX F Atilde -80
-KPX F a -50
-KPX F aacute -50
-KPX F abreve -50
-KPX F acircumflex -50
-KPX F adieresis -50
-KPX F agrave -50
-KPX F amacron -50
-KPX F aogonek -50
-KPX F aring -50
-KPX F atilde -50
-KPX F comma -150
-KPX F e -30
-KPX F eacute -30
-KPX F ecaron -30
-KPX F ecircumflex -30
-KPX F edieresis -30
-KPX F edotaccent -30
-KPX F egrave -30
-KPX F emacron -30
-KPX F eogonek -30
-KPX F o -30
-KPX F oacute -30
-KPX F ocircumflex -30
-KPX F odieresis -30
-KPX F ograve -30
-KPX F ohungarumlaut -30
-KPX F omacron -30
-KPX F oslash -30
-KPX F otilde -30
-KPX F period -150
-KPX F r -45
-KPX F racute -45
-KPX F rcaron -45
-KPX F rcommaaccent -45
-KPX J A -20
-KPX J Aacute -20
-KPX J Abreve -20
-KPX J Acircumflex -20
-KPX J Adieresis -20
-KPX J Agrave -20
-KPX J Amacron -20
-KPX J Aogonek -20
-KPX J Aring -20
-KPX J Atilde -20
-KPX J a -20
-KPX J aacute -20
-KPX J abreve -20
-KPX J acircumflex -20
-KPX J adieresis -20
-KPX J agrave -20
-KPX J amacron -20
-KPX J aogonek -20
-KPX J aring -20
-KPX J atilde -20
-KPX J comma -30
-KPX J period -30
-KPX J u -20
-KPX J uacute -20
-KPX J ucircumflex -20
-KPX J udieresis -20
-KPX J ugrave -20
-KPX J uhungarumlaut -20
-KPX J umacron -20
-KPX J uogonek -20
-KPX J uring -20
-KPX K O -50
-KPX K Oacute -50
-KPX K Ocircumflex -50
-KPX K Odieresis -50
-KPX K Ograve -50
-KPX K Ohungarumlaut -50
-KPX K Omacron -50
-KPX K Oslash -50
-KPX K Otilde -50
-KPX K e -40
-KPX K eacute -40
-KPX K ecaron -40
-KPX K ecircumflex -40
-KPX K edieresis -40
-KPX K edotaccent -40
-KPX K egrave -40
-KPX K emacron -40
-KPX K eogonek -40
-KPX K o -40
-KPX K oacute -40
-KPX K ocircumflex -40
-KPX K odieresis -40
-KPX K ograve -40
-KPX K ohungarumlaut -40
-KPX K omacron -40
-KPX K oslash -40
-KPX K otilde -40
-KPX K u -30
-KPX K uacute -30
-KPX K ucircumflex -30
-KPX K udieresis -30
-KPX K ugrave -30
-KPX K uhungarumlaut -30
-KPX K umacron -30
-KPX K uogonek -30
-KPX K uring -30
-KPX K y -50
-KPX K yacute -50
-KPX K ydieresis -50
-KPX Kcommaaccent O -50
-KPX Kcommaaccent Oacute -50
-KPX Kcommaaccent Ocircumflex -50
-KPX Kcommaaccent Odieresis -50
-KPX Kcommaaccent Ograve -50
-KPX Kcommaaccent Ohungarumlaut -50
-KPX Kcommaaccent Omacron -50
-KPX Kcommaaccent Oslash -50
-KPX Kcommaaccent Otilde -50
-KPX Kcommaaccent e -40
-KPX Kcommaaccent eacute -40
-KPX Kcommaaccent ecaron -40
-KPX Kcommaaccent ecircumflex -40
-KPX Kcommaaccent edieresis -40
-KPX Kcommaaccent edotaccent -40
-KPX Kcommaaccent egrave -40
-KPX Kcommaaccent emacron -40
-KPX Kcommaaccent eogonek -40
-KPX Kcommaaccent o -40
-KPX Kcommaaccent oacute -40
-KPX Kcommaaccent ocircumflex -40
-KPX Kcommaaccent odieresis -40
-KPX Kcommaaccent ograve -40
-KPX Kcommaaccent ohungarumlaut -40
-KPX Kcommaaccent omacron -40
-KPX Kcommaaccent oslash -40
-KPX Kcommaaccent otilde -40
-KPX Kcommaaccent u -30
-KPX Kcommaaccent uacute -30
-KPX Kcommaaccent ucircumflex -30
-KPX Kcommaaccent udieresis -30
-KPX Kcommaaccent ugrave -30
-KPX Kcommaaccent uhungarumlaut -30
-KPX Kcommaaccent umacron -30
-KPX Kcommaaccent uogonek -30
-KPX Kcommaaccent uring -30
-KPX Kcommaaccent y -50
-KPX Kcommaaccent yacute -50
-KPX Kcommaaccent ydieresis -50
-KPX L T -110
-KPX L Tcaron -110
-KPX L Tcommaaccent -110
-KPX L V -110
-KPX L W -70
-KPX L Y -140
-KPX L Yacute -140
-KPX L Ydieresis -140
-KPX L quotedblright -140
-KPX L quoteright -160
-KPX L y -30
-KPX L yacute -30
-KPX L ydieresis -30
-KPX Lacute T -110
-KPX Lacute Tcaron -110
-KPX Lacute Tcommaaccent -110
-KPX Lacute V -110
-KPX Lacute W -70
-KPX Lacute Y -140
-KPX Lacute Yacute -140
-KPX Lacute Ydieresis -140
-KPX Lacute quotedblright -140
-KPX Lacute quoteright -160
-KPX Lacute y -30
-KPX Lacute yacute -30
-KPX Lacute ydieresis -30
-KPX Lcaron T -110
-KPX Lcaron Tcaron -110
-KPX Lcaron Tcommaaccent -110
-KPX Lcaron V -110
-KPX Lcaron W -70
-KPX Lcaron Y -140
-KPX Lcaron Yacute -140
-KPX Lcaron Ydieresis -140
-KPX Lcaron quotedblright -140
-KPX Lcaron quoteright -160
-KPX Lcaron y -30
-KPX Lcaron yacute -30
-KPX Lcaron ydieresis -30
-KPX Lcommaaccent T -110
-KPX Lcommaaccent Tcaron -110
-KPX Lcommaaccent Tcommaaccent -110
-KPX Lcommaaccent V -110
-KPX Lcommaaccent W -70
-KPX Lcommaaccent Y -140
-KPX Lcommaaccent Yacute -140
-KPX Lcommaaccent Ydieresis -140
-KPX Lcommaaccent quotedblright -140
-KPX Lcommaaccent quoteright -160
-KPX Lcommaaccent y -30
-KPX Lcommaaccent yacute -30
-KPX Lcommaaccent ydieresis -30
-KPX Lslash T -110
-KPX Lslash Tcaron -110
-KPX Lslash Tcommaaccent -110
-KPX Lslash V -110
-KPX Lslash W -70
-KPX Lslash Y -140
-KPX Lslash Yacute -140
-KPX Lslash Ydieresis -140
-KPX Lslash quotedblright -140
-KPX Lslash quoteright -160
-KPX Lslash y -30
-KPX Lslash yacute -30
-KPX Lslash ydieresis -30
-KPX O A -20
-KPX O Aacute -20
-KPX O Abreve -20
-KPX O Acircumflex -20
-KPX O Adieresis -20
-KPX O Agrave -20
-KPX O Amacron -20
-KPX O Aogonek -20
-KPX O Aring -20
-KPX O Atilde -20
-KPX O T -40
-KPX O Tcaron -40
-KPX O Tcommaaccent -40
-KPX O V -50
-KPX O W -30
-KPX O X -60
-KPX O Y -70
-KPX O Yacute -70
-KPX O Ydieresis -70
-KPX O comma -40
-KPX O period -40
-KPX Oacute A -20
-KPX Oacute Aacute -20
-KPX Oacute Abreve -20
-KPX Oacute Acircumflex -20
-KPX Oacute Adieresis -20
-KPX Oacute Agrave -20
-KPX Oacute Amacron -20
-KPX Oacute Aogonek -20
-KPX Oacute Aring -20
-KPX Oacute Atilde -20
-KPX Oacute T -40
-KPX Oacute Tcaron -40
-KPX Oacute Tcommaaccent -40
-KPX Oacute V -50
-KPX Oacute W -30
-KPX Oacute X -60
-KPX Oacute Y -70
-KPX Oacute Yacute -70
-KPX Oacute Ydieresis -70
-KPX Oacute comma -40
-KPX Oacute period -40
-KPX Ocircumflex A -20
-KPX Ocircumflex Aacute -20
-KPX Ocircumflex Abreve -20
-KPX Ocircumflex Acircumflex -20
-KPX Ocircumflex Adieresis -20
-KPX Ocircumflex Agrave -20
-KPX Ocircumflex Amacron -20
-KPX Ocircumflex Aogonek -20
-KPX Ocircumflex Aring -20
-KPX Ocircumflex Atilde -20
-KPX Ocircumflex T -40
-KPX Ocircumflex Tcaron -40
-KPX Ocircumflex Tcommaaccent -40
-KPX Ocircumflex V -50
-KPX Ocircumflex W -30
-KPX Ocircumflex X -60
-KPX Ocircumflex Y -70
-KPX Ocircumflex Yacute -70
-KPX Ocircumflex Ydieresis -70
-KPX Ocircumflex comma -40
-KPX Ocircumflex period -40
-KPX Odieresis A -20
-KPX Odieresis Aacute -20
-KPX Odieresis Abreve -20
-KPX Odieresis Acircumflex -20
-KPX Odieresis Adieresis -20
-KPX Odieresis Agrave -20
-KPX Odieresis Amacron -20
-KPX Odieresis Aogonek -20
-KPX Odieresis Aring -20
-KPX Odieresis Atilde -20
-KPX Odieresis T -40
-KPX Odieresis Tcaron -40
-KPX Odieresis Tcommaaccent -40
-KPX Odieresis V -50
-KPX Odieresis W -30
-KPX Odieresis X -60
-KPX Odieresis Y -70
-KPX Odieresis Yacute -70
-KPX Odieresis Ydieresis -70
-KPX Odieresis comma -40
-KPX Odieresis period -40
-KPX Ograve A -20
-KPX Ograve Aacute -20
-KPX Ograve Abreve -20
-KPX Ograve Acircumflex -20
-KPX Ograve Adieresis -20
-KPX Ograve Agrave -20
-KPX Ograve Amacron -20
-KPX Ograve Aogonek -20
-KPX Ograve Aring -20
-KPX Ograve Atilde -20
-KPX Ograve T -40
-KPX Ograve Tcaron -40
-KPX Ograve Tcommaaccent -40
-KPX Ograve V -50
-KPX Ograve W -30
-KPX Ograve X -60
-KPX Ograve Y -70
-KPX Ograve Yacute -70
-KPX Ograve Ydieresis -70
-KPX Ograve comma -40
-KPX Ograve period -40
-KPX Ohungarumlaut A -20
-KPX Ohungarumlaut Aacute -20
-KPX Ohungarumlaut Abreve -20
-KPX Ohungarumlaut Acircumflex -20
-KPX Ohungarumlaut Adieresis -20
-KPX Ohungarumlaut Agrave -20
-KPX Ohungarumlaut Amacron -20
-KPX Ohungarumlaut Aogonek -20
-KPX Ohungarumlaut Aring -20
-KPX Ohungarumlaut Atilde -20
-KPX Ohungarumlaut T -40
-KPX Ohungarumlaut Tcaron -40
-KPX Ohungarumlaut Tcommaaccent -40
-KPX Ohungarumlaut V -50
-KPX Ohungarumlaut W -30
-KPX Ohungarumlaut X -60
-KPX Ohungarumlaut Y -70
-KPX Ohungarumlaut Yacute -70
-KPX Ohungarumlaut Ydieresis -70
-KPX Ohungarumlaut comma -40
-KPX Ohungarumlaut period -40
-KPX Omacron A -20
-KPX Omacron Aacute -20
-KPX Omacron Abreve -20
-KPX Omacron Acircumflex -20
-KPX Omacron Adieresis -20
-KPX Omacron Agrave -20
-KPX Omacron Amacron -20
-KPX Omacron Aogonek -20
-KPX Omacron Aring -20
-KPX Omacron Atilde -20
-KPX Omacron T -40
-KPX Omacron Tcaron -40
-KPX Omacron Tcommaaccent -40
-KPX Omacron V -50
-KPX Omacron W -30
-KPX Omacron X -60
-KPX Omacron Y -70
-KPX Omacron Yacute -70
-KPX Omacron Ydieresis -70
-KPX Omacron comma -40
-KPX Omacron period -40
-KPX Oslash A -20
-KPX Oslash Aacute -20
-KPX Oslash Abreve -20
-KPX Oslash Acircumflex -20
-KPX Oslash Adieresis -20
-KPX Oslash Agrave -20
-KPX Oslash Amacron -20
-KPX Oslash Aogonek -20
-KPX Oslash Aring -20
-KPX Oslash Atilde -20
-KPX Oslash T -40
-KPX Oslash Tcaron -40
-KPX Oslash Tcommaaccent -40
-KPX Oslash V -50
-KPX Oslash W -30
-KPX Oslash X -60
-KPX Oslash Y -70
-KPX Oslash Yacute -70
-KPX Oslash Ydieresis -70
-KPX Oslash comma -40
-KPX Oslash period -40
-KPX Otilde A -20
-KPX Otilde Aacute -20
-KPX Otilde Abreve -20
-KPX Otilde Acircumflex -20
-KPX Otilde Adieresis -20
-KPX Otilde Agrave -20
-KPX Otilde Amacron -20
-KPX Otilde Aogonek -20
-KPX Otilde Aring -20
-KPX Otilde Atilde -20
-KPX Otilde T -40
-KPX Otilde Tcaron -40
-KPX Otilde Tcommaaccent -40
-KPX Otilde V -50
-KPX Otilde W -30
-KPX Otilde X -60
-KPX Otilde Y -70
-KPX Otilde Yacute -70
-KPX Otilde Ydieresis -70
-KPX Otilde comma -40
-KPX Otilde period -40
-KPX P A -120
-KPX P Aacute -120
-KPX P Abreve -120
-KPX P Acircumflex -120
-KPX P Adieresis -120
-KPX P Agrave -120
-KPX P Amacron -120
-KPX P Aogonek -120
-KPX P Aring -120
-KPX P Atilde -120
-KPX P a -40
-KPX P aacute -40
-KPX P abreve -40
-KPX P acircumflex -40
-KPX P adieresis -40
-KPX P agrave -40
-KPX P amacron -40
-KPX P aogonek -40
-KPX P aring -40
-KPX P atilde -40
-KPX P comma -180
-KPX P e -50
-KPX P eacute -50
-KPX P ecaron -50
-KPX P ecircumflex -50
-KPX P edieresis -50
-KPX P edotaccent -50
-KPX P egrave -50
-KPX P emacron -50
-KPX P eogonek -50
-KPX P o -50
-KPX P oacute -50
-KPX P ocircumflex -50
-KPX P odieresis -50
-KPX P ograve -50
-KPX P ohungarumlaut -50
-KPX P omacron -50
-KPX P oslash -50
-KPX P otilde -50
-KPX P period -180
-KPX Q U -10
-KPX Q Uacute -10
-KPX Q Ucircumflex -10
-KPX Q Udieresis -10
-KPX Q Ugrave -10
-KPX Q Uhungarumlaut -10
-KPX Q Umacron -10
-KPX Q Uogonek -10
-KPX Q Uring -10
-KPX R O -20
-KPX R Oacute -20
-KPX R Ocircumflex -20
-KPX R Odieresis -20
-KPX R Ograve -20
-KPX R Ohungarumlaut -20
-KPX R Omacron -20
-KPX R Oslash -20
-KPX R Otilde -20
-KPX R T -30
-KPX R Tcaron -30
-KPX R Tcommaaccent -30
-KPX R U -40
-KPX R Uacute -40
-KPX R Ucircumflex -40
-KPX R Udieresis -40
-KPX R Ugrave -40
-KPX R Uhungarumlaut -40
-KPX R Umacron -40
-KPX R Uogonek -40
-KPX R Uring -40
-KPX R V -50
-KPX R W -30
-KPX R Y -50
-KPX R Yacute -50
-KPX R Ydieresis -50
-KPX Racute O -20
-KPX Racute Oacute -20
-KPX Racute Ocircumflex -20
-KPX Racute Odieresis -20
-KPX Racute Ograve -20
-KPX Racute Ohungarumlaut -20
-KPX Racute Omacron -20
-KPX Racute Oslash -20
-KPX Racute Otilde -20
-KPX Racute T -30
-KPX Racute Tcaron -30
-KPX Racute Tcommaaccent -30
-KPX Racute U -40
-KPX Racute Uacute -40
-KPX Racute Ucircumflex -40
-KPX Racute Udieresis -40
-KPX Racute Ugrave -40
-KPX Racute Uhungarumlaut -40
-KPX Racute Umacron -40
-KPX Racute Uogonek -40
-KPX Racute Uring -40
-KPX Racute V -50
-KPX Racute W -30
-KPX Racute Y -50
-KPX Racute Yacute -50
-KPX Racute Ydieresis -50
-KPX Rcaron O -20
-KPX Rcaron Oacute -20
-KPX Rcaron Ocircumflex -20
-KPX Rcaron Odieresis -20
-KPX Rcaron Ograve -20
-KPX Rcaron Ohungarumlaut -20
-KPX Rcaron Omacron -20
-KPX Rcaron Oslash -20
-KPX Rcaron Otilde -20
-KPX Rcaron T -30
-KPX Rcaron Tcaron -30
-KPX Rcaron Tcommaaccent -30
-KPX Rcaron U -40
-KPX Rcaron Uacute -40
-KPX Rcaron Ucircumflex -40
-KPX Rcaron Udieresis -40
-KPX Rcaron Ugrave -40
-KPX Rcaron Uhungarumlaut -40
-KPX Rcaron Umacron -40
-KPX Rcaron Uogonek -40
-KPX Rcaron Uring -40
-KPX Rcaron V -50
-KPX Rcaron W -30
-KPX Rcaron Y -50
-KPX Rcaron Yacute -50
-KPX Rcaron Ydieresis -50
-KPX Rcommaaccent O -20
-KPX Rcommaaccent Oacute -20
-KPX Rcommaaccent Ocircumflex -20
-KPX Rcommaaccent Odieresis -20
-KPX Rcommaaccent Ograve -20
-KPX Rcommaaccent Ohungarumlaut -20
-KPX Rcommaaccent Omacron -20
-KPX Rcommaaccent Oslash -20
-KPX Rcommaaccent Otilde -20
-KPX Rcommaaccent T -30
-KPX Rcommaaccent Tcaron -30
-KPX Rcommaaccent Tcommaaccent -30
-KPX Rcommaaccent U -40
-KPX Rcommaaccent Uacute -40
-KPX Rcommaaccent Ucircumflex -40
-KPX Rcommaaccent Udieresis -40
-KPX Rcommaaccent Ugrave -40
-KPX Rcommaaccent Uhungarumlaut -40
-KPX Rcommaaccent Umacron -40
-KPX Rcommaaccent Uogonek -40
-KPX Rcommaaccent Uring -40
-KPX Rcommaaccent V -50
-KPX Rcommaaccent W -30
-KPX Rcommaaccent Y -50
-KPX Rcommaaccent Yacute -50
-KPX Rcommaaccent Ydieresis -50
-KPX S comma -20
-KPX S period -20
-KPX Sacute comma -20
-KPX Sacute period -20
-KPX Scaron comma -20
-KPX Scaron period -20
-KPX Scedilla comma -20
-KPX Scedilla period -20
-KPX Scommaaccent comma -20
-KPX Scommaaccent period -20
-KPX T A -120
-KPX T Aacute -120
-KPX T Abreve -120
-KPX T Acircumflex -120
-KPX T Adieresis -120
-KPX T Agrave -120
-KPX T Amacron -120
-KPX T Aogonek -120
-KPX T Aring -120
-KPX T Atilde -120
-KPX T O -40
-KPX T Oacute -40
-KPX T Ocircumflex -40
-KPX T Odieresis -40
-KPX T Ograve -40
-KPX T Ohungarumlaut -40
-KPX T Omacron -40
-KPX T Oslash -40
-KPX T Otilde -40
-KPX T a -120
-KPX T aacute -120
-KPX T abreve -60
-KPX T acircumflex -120
-KPX T adieresis -120
-KPX T agrave -120
-KPX T amacron -60
-KPX T aogonek -120
-KPX T aring -120
-KPX T atilde -60
-KPX T colon -20
-KPX T comma -120
-KPX T e -120
-KPX T eacute -120
-KPX T ecaron -120
-KPX T ecircumflex -120
-KPX T edieresis -120
-KPX T edotaccent -120
-KPX T egrave -60
-KPX T emacron -60
-KPX T eogonek -120
-KPX T hyphen -140
-KPX T o -120
-KPX T oacute -120
-KPX T ocircumflex -120
-KPX T odieresis -120
-KPX T ograve -120
-KPX T ohungarumlaut -120
-KPX T omacron -60
-KPX T oslash -120
-KPX T otilde -60
-KPX T period -120
-KPX T r -120
-KPX T racute -120
-KPX T rcaron -120
-KPX T rcommaaccent -120
-KPX T semicolon -20
-KPX T u -120
-KPX T uacute -120
-KPX T ucircumflex -120
-KPX T udieresis -120
-KPX T ugrave -120
-KPX T uhungarumlaut -120
-KPX T umacron -60
-KPX T uogonek -120
-KPX T uring -120
-KPX T w -120
-KPX T y -120
-KPX T yacute -120
-KPX T ydieresis -60
-KPX Tcaron A -120
-KPX Tcaron Aacute -120
-KPX Tcaron Abreve -120
-KPX Tcaron Acircumflex -120
-KPX Tcaron Adieresis -120
-KPX Tcaron Agrave -120
-KPX Tcaron Amacron -120
-KPX Tcaron Aogonek -120
-KPX Tcaron Aring -120
-KPX Tcaron Atilde -120
-KPX Tcaron O -40
-KPX Tcaron Oacute -40
-KPX Tcaron Ocircumflex -40
-KPX Tcaron Odieresis -40
-KPX Tcaron Ograve -40
-KPX Tcaron Ohungarumlaut -40
-KPX Tcaron Omacron -40
-KPX Tcaron Oslash -40
-KPX Tcaron Otilde -40
-KPX Tcaron a -120
-KPX Tcaron aacute -120
-KPX Tcaron abreve -60
-KPX Tcaron acircumflex -120
-KPX Tcaron adieresis -120
-KPX Tcaron agrave -120
-KPX Tcaron amacron -60
-KPX Tcaron aogonek -120
-KPX Tcaron aring -120
-KPX Tcaron atilde -60
-KPX Tcaron colon -20
-KPX Tcaron comma -120
-KPX Tcaron e -120
-KPX Tcaron eacute -120
-KPX Tcaron ecaron -120
-KPX Tcaron ecircumflex -120
-KPX Tcaron edieresis -120
-KPX Tcaron edotaccent -120
-KPX Tcaron egrave -60
-KPX Tcaron emacron -60
-KPX Tcaron eogonek -120
-KPX Tcaron hyphen -140
-KPX Tcaron o -120
-KPX Tcaron oacute -120
-KPX Tcaron ocircumflex -120
-KPX Tcaron odieresis -120
-KPX Tcaron ograve -120
-KPX Tcaron ohungarumlaut -120
-KPX Tcaron omacron -60
-KPX Tcaron oslash -120
-KPX Tcaron otilde -60
-KPX Tcaron period -120
-KPX Tcaron r -120
-KPX Tcaron racute -120
-KPX Tcaron rcaron -120
-KPX Tcaron rcommaaccent -120
-KPX Tcaron semicolon -20
-KPX Tcaron u -120
-KPX Tcaron uacute -120
-KPX Tcaron ucircumflex -120
-KPX Tcaron udieresis -120
-KPX Tcaron ugrave -120
-KPX Tcaron uhungarumlaut -120
-KPX Tcaron umacron -60
-KPX Tcaron uogonek -120
-KPX Tcaron uring -120
-KPX Tcaron w -120
-KPX Tcaron y -120
-KPX Tcaron yacute -120
-KPX Tcaron ydieresis -60
-KPX Tcommaaccent A -120
-KPX Tcommaaccent Aacute -120
-KPX Tcommaaccent Abreve -120
-KPX Tcommaaccent Acircumflex -120
-KPX Tcommaaccent Adieresis -120
-KPX Tcommaaccent Agrave -120
-KPX Tcommaaccent Amacron -120
-KPX Tcommaaccent Aogonek -120
-KPX Tcommaaccent Aring -120
-KPX Tcommaaccent Atilde -120
-KPX Tcommaaccent O -40
-KPX Tcommaaccent Oacute -40
-KPX Tcommaaccent Ocircumflex -40
-KPX Tcommaaccent Odieresis -40
-KPX Tcommaaccent Ograve -40
-KPX Tcommaaccent Ohungarumlaut -40
-KPX Tcommaaccent Omacron -40
-KPX Tcommaaccent Oslash -40
-KPX Tcommaaccent Otilde -40
-KPX Tcommaaccent a -120
-KPX Tcommaaccent aacute -120
-KPX Tcommaaccent abreve -60
-KPX Tcommaaccent acircumflex -120
-KPX Tcommaaccent adieresis -120
-KPX Tcommaaccent agrave -120
-KPX Tcommaaccent amacron -60
-KPX Tcommaaccent aogonek -120
-KPX Tcommaaccent aring -120
-KPX Tcommaaccent atilde -60
-KPX Tcommaaccent colon -20
-KPX Tcommaaccent comma -120
-KPX Tcommaaccent e -120
-KPX Tcommaaccent eacute -120
-KPX Tcommaaccent ecaron -120
-KPX Tcommaaccent ecircumflex -120
-KPX Tcommaaccent edieresis -120
-KPX Tcommaaccent edotaccent -120
-KPX Tcommaaccent egrave -60
-KPX Tcommaaccent emacron -60
-KPX Tcommaaccent eogonek -120
-KPX Tcommaaccent hyphen -140
-KPX Tcommaaccent o -120
-KPX Tcommaaccent oacute -120
-KPX Tcommaaccent ocircumflex -120
-KPX Tcommaaccent odieresis -120
-KPX Tcommaaccent ograve -120
-KPX Tcommaaccent ohungarumlaut -120
-KPX Tcommaaccent omacron -60
-KPX Tcommaaccent oslash -120
-KPX Tcommaaccent otilde -60
-KPX Tcommaaccent period -120
-KPX Tcommaaccent r -120
-KPX Tcommaaccent racute -120
-KPX Tcommaaccent rcaron -120
-KPX Tcommaaccent rcommaaccent -120
-KPX Tcommaaccent semicolon -20
-KPX Tcommaaccent u -120
-KPX Tcommaaccent uacute -120
-KPX Tcommaaccent ucircumflex -120
-KPX Tcommaaccent udieresis -120
-KPX Tcommaaccent ugrave -120
-KPX Tcommaaccent uhungarumlaut -120
-KPX Tcommaaccent umacron -60
-KPX Tcommaaccent uogonek -120
-KPX Tcommaaccent uring -120
-KPX Tcommaaccent w -120
-KPX Tcommaaccent y -120
-KPX Tcommaaccent yacute -120
-KPX Tcommaaccent ydieresis -60
-KPX U A -40
-KPX U Aacute -40
-KPX U Abreve -40
-KPX U Acircumflex -40
-KPX U Adieresis -40
-KPX U Agrave -40
-KPX U Amacron -40
-KPX U Aogonek -40
-KPX U Aring -40
-KPX U Atilde -40
-KPX U comma -40
-KPX U period -40
-KPX Uacute A -40
-KPX Uacute Aacute -40
-KPX Uacute Abreve -40
-KPX Uacute Acircumflex -40
-KPX Uacute Adieresis -40
-KPX Uacute Agrave -40
-KPX Uacute Amacron -40
-KPX Uacute Aogonek -40
-KPX Uacute Aring -40
-KPX Uacute Atilde -40
-KPX Uacute comma -40
-KPX Uacute period -40
-KPX Ucircumflex A -40
-KPX Ucircumflex Aacute -40
-KPX Ucircumflex Abreve -40
-KPX Ucircumflex Acircumflex -40
-KPX Ucircumflex Adieresis -40
-KPX Ucircumflex Agrave -40
-KPX Ucircumflex Amacron -40
-KPX Ucircumflex Aogonek -40
-KPX Ucircumflex Aring -40
-KPX Ucircumflex Atilde -40
-KPX Ucircumflex comma -40
-KPX Ucircumflex period -40
-KPX Udieresis A -40
-KPX Udieresis Aacute -40
-KPX Udieresis Abreve -40
-KPX Udieresis Acircumflex -40
-KPX Udieresis Adieresis -40
-KPX Udieresis Agrave -40
-KPX Udieresis Amacron -40
-KPX Udieresis Aogonek -40
-KPX Udieresis Aring -40
-KPX Udieresis Atilde -40
-KPX Udieresis comma -40
-KPX Udieresis period -40
-KPX Ugrave A -40
-KPX Ugrave Aacute -40
-KPX Ugrave Abreve -40
-KPX Ugrave Acircumflex -40
-KPX Ugrave Adieresis -40
-KPX Ugrave Agrave -40
-KPX Ugrave Amacron -40
-KPX Ugrave Aogonek -40
-KPX Ugrave Aring -40
-KPX Ugrave Atilde -40
-KPX Ugrave comma -40
-KPX Ugrave period -40
-KPX Uhungarumlaut A -40
-KPX Uhungarumlaut Aacute -40
-KPX Uhungarumlaut Abreve -40
-KPX Uhungarumlaut Acircumflex -40
-KPX Uhungarumlaut Adieresis -40
-KPX Uhungarumlaut Agrave -40
-KPX Uhungarumlaut Amacron -40
-KPX Uhungarumlaut Aogonek -40
-KPX Uhungarumlaut Aring -40
-KPX Uhungarumlaut Atilde -40
-KPX Uhungarumlaut comma -40
-KPX Uhungarumlaut period -40
-KPX Umacron A -40
-KPX Umacron Aacute -40
-KPX Umacron Abreve -40
-KPX Umacron Acircumflex -40
-KPX Umacron Adieresis -40
-KPX Umacron Agrave -40
-KPX Umacron Amacron -40
-KPX Umacron Aogonek -40
-KPX Umacron Aring -40
-KPX Umacron Atilde -40
-KPX Umacron comma -40
-KPX Umacron period -40
-KPX Uogonek A -40
-KPX Uogonek Aacute -40
-KPX Uogonek Abreve -40
-KPX Uogonek Acircumflex -40
-KPX Uogonek Adieresis -40
-KPX Uogonek Agrave -40
-KPX Uogonek Amacron -40
-KPX Uogonek Aogonek -40
-KPX Uogonek Aring -40
-KPX Uogonek Atilde -40
-KPX Uogonek comma -40
-KPX Uogonek period -40
-KPX Uring A -40
-KPX Uring Aacute -40
-KPX Uring Abreve -40
-KPX Uring Acircumflex -40
-KPX Uring Adieresis -40
-KPX Uring Agrave -40
-KPX Uring Amacron -40
-KPX Uring Aogonek -40
-KPX Uring Aring -40
-KPX Uring Atilde -40
-KPX Uring comma -40
-KPX Uring period -40
-KPX V A -80
-KPX V Aacute -80
-KPX V Abreve -80
-KPX V Acircumflex -80
-KPX V Adieresis -80
-KPX V Agrave -80
-KPX V Amacron -80
-KPX V Aogonek -80
-KPX V Aring -80
-KPX V Atilde -80
-KPX V G -40
-KPX V Gbreve -40
-KPX V Gcommaaccent -40
-KPX V O -40
-KPX V Oacute -40
-KPX V Ocircumflex -40
-KPX V Odieresis -40
-KPX V Ograve -40
-KPX V Ohungarumlaut -40
-KPX V Omacron -40
-KPX V Oslash -40
-KPX V Otilde -40
-KPX V a -70
-KPX V aacute -70
-KPX V abreve -70
-KPX V acircumflex -70
-KPX V adieresis -70
-KPX V agrave -70
-KPX V amacron -70
-KPX V aogonek -70
-KPX V aring -70
-KPX V atilde -70
-KPX V colon -40
-KPX V comma -125
-KPX V e -80
-KPX V eacute -80
-KPX V ecaron -80
-KPX V ecircumflex -80
-KPX V edieresis -80
-KPX V edotaccent -80
-KPX V egrave -80
-KPX V emacron -80
-KPX V eogonek -80
-KPX V hyphen -80
-KPX V o -80
-KPX V oacute -80
-KPX V ocircumflex -80
-KPX V odieresis -80
-KPX V ograve -80
-KPX V ohungarumlaut -80
-KPX V omacron -80
-KPX V oslash -80
-KPX V otilde -80
-KPX V period -125
-KPX V semicolon -40
-KPX V u -70
-KPX V uacute -70
-KPX V ucircumflex -70
-KPX V udieresis -70
-KPX V ugrave -70
-KPX V uhungarumlaut -70
-KPX V umacron -70
-KPX V uogonek -70
-KPX V uring -70
-KPX W A -50
-KPX W Aacute -50
-KPX W Abreve -50
-KPX W Acircumflex -50
-KPX W Adieresis -50
-KPX W Agrave -50
-KPX W Amacron -50
-KPX W Aogonek -50
-KPX W Aring -50
-KPX W Atilde -50
-KPX W O -20
-KPX W Oacute -20
-KPX W Ocircumflex -20
-KPX W Odieresis -20
-KPX W Ograve -20
-KPX W Ohungarumlaut -20
-KPX W Omacron -20
-KPX W Oslash -20
-KPX W Otilde -20
-KPX W a -40
-KPX W aacute -40
-KPX W abreve -40
-KPX W acircumflex -40
-KPX W adieresis -40
-KPX W agrave -40
-KPX W amacron -40
-KPX W aogonek -40
-KPX W aring -40
-KPX W atilde -40
-KPX W comma -80
-KPX W e -30
-KPX W eacute -30
-KPX W ecaron -30
-KPX W ecircumflex -30
-KPX W edieresis -30
-KPX W edotaccent -30
-KPX W egrave -30
-KPX W emacron -30
-KPX W eogonek -30
-KPX W hyphen -40
-KPX W o -30
-KPX W oacute -30
-KPX W ocircumflex -30
-KPX W odieresis -30
-KPX W ograve -30
-KPX W ohungarumlaut -30
-KPX W omacron -30
-KPX W oslash -30
-KPX W otilde -30
-KPX W period -80
-KPX W u -30
-KPX W uacute -30
-KPX W ucircumflex -30
-KPX W udieresis -30
-KPX W ugrave -30
-KPX W uhungarumlaut -30
-KPX W umacron -30
-KPX W uogonek -30
-KPX W uring -30
-KPX W y -20
-KPX W yacute -20
-KPX W ydieresis -20
-KPX Y A -110
-KPX Y Aacute -110
-KPX Y Abreve -110
-KPX Y Acircumflex -110
-KPX Y Adieresis -110
-KPX Y Agrave -110
-KPX Y Amacron -110
-KPX Y Aogonek -110
-KPX Y Aring -110
-KPX Y Atilde -110
-KPX Y O -85
-KPX Y Oacute -85
-KPX Y Ocircumflex -85
-KPX Y Odieresis -85
-KPX Y Ograve -85
-KPX Y Ohungarumlaut -85
-KPX Y Omacron -85
-KPX Y Oslash -85
-KPX Y Otilde -85
-KPX Y a -140
-KPX Y aacute -140
-KPX Y abreve -70
-KPX Y acircumflex -140
-KPX Y adieresis -140
-KPX Y agrave -140
-KPX Y amacron -70
-KPX Y aogonek -140
-KPX Y aring -140
-KPX Y atilde -140
-KPX Y colon -60
-KPX Y comma -140
-KPX Y e -140
-KPX Y eacute -140
-KPX Y ecaron -140
-KPX Y ecircumflex -140
-KPX Y edieresis -140
-KPX Y edotaccent -140
-KPX Y egrave -140
-KPX Y emacron -70
-KPX Y eogonek -140
-KPX Y hyphen -140
-KPX Y i -20
-KPX Y iacute -20
-KPX Y iogonek -20
-KPX Y o -140
-KPX Y oacute -140
-KPX Y ocircumflex -140
-KPX Y odieresis -140
-KPX Y ograve -140
-KPX Y ohungarumlaut -140
-KPX Y omacron -140
-KPX Y oslash -140
-KPX Y otilde -140
-KPX Y period -140
-KPX Y semicolon -60
-KPX Y u -110
-KPX Y uacute -110
-KPX Y ucircumflex -110
-KPX Y udieresis -110
-KPX Y ugrave -110
-KPX Y uhungarumlaut -110
-KPX Y umacron -110
-KPX Y uogonek -110
-KPX Y uring -110
-KPX Yacute A -110
-KPX Yacute Aacute -110
-KPX Yacute Abreve -110
-KPX Yacute Acircumflex -110
-KPX Yacute Adieresis -110
-KPX Yacute Agrave -110
-KPX Yacute Amacron -110
-KPX Yacute Aogonek -110
-KPX Yacute Aring -110
-KPX Yacute Atilde -110
-KPX Yacute O -85
-KPX Yacute Oacute -85
-KPX Yacute Ocircumflex -85
-KPX Yacute Odieresis -85
-KPX Yacute Ograve -85
-KPX Yacute Ohungarumlaut -85
-KPX Yacute Omacron -85
-KPX Yacute Oslash -85
-KPX Yacute Otilde -85
-KPX Yacute a -140
-KPX Yacute aacute -140
-KPX Yacute abreve -70
-KPX Yacute acircumflex -140
-KPX Yacute adieresis -140
-KPX Yacute agrave -140
-KPX Yacute amacron -70
-KPX Yacute aogonek -140
-KPX Yacute aring -140
-KPX Yacute atilde -70
-KPX Yacute colon -60
-KPX Yacute comma -140
-KPX Yacute e -140
-KPX Yacute eacute -140
-KPX Yacute ecaron -140
-KPX Yacute ecircumflex -140
-KPX Yacute edieresis -140
-KPX Yacute edotaccent -140
-KPX Yacute egrave -140
-KPX Yacute emacron -70
-KPX Yacute eogonek -140
-KPX Yacute hyphen -140
-KPX Yacute i -20
-KPX Yacute iacute -20
-KPX Yacute iogonek -20
-KPX Yacute o -140
-KPX Yacute oacute -140
-KPX Yacute ocircumflex -140
-KPX Yacute odieresis -140
-KPX Yacute ograve -140
-KPX Yacute ohungarumlaut -140
-KPX Yacute omacron -70
-KPX Yacute oslash -140
-KPX Yacute otilde -140
-KPX Yacute period -140
-KPX Yacute semicolon -60
-KPX Yacute u -110
-KPX Yacute uacute -110
-KPX Yacute ucircumflex -110
-KPX Yacute udieresis -110
-KPX Yacute ugrave -110
-KPX Yacute uhungarumlaut -110
-KPX Yacute umacron -110
-KPX Yacute uogonek -110
-KPX Yacute uring -110
-KPX Ydieresis A -110
-KPX Ydieresis Aacute -110
-KPX Ydieresis Abreve -110
-KPX Ydieresis Acircumflex -110
-KPX Ydieresis Adieresis -110
-KPX Ydieresis Agrave -110
-KPX Ydieresis Amacron -110
-KPX Ydieresis Aogonek -110
-KPX Ydieresis Aring -110
-KPX Ydieresis Atilde -110
-KPX Ydieresis O -85
-KPX Ydieresis Oacute -85
-KPX Ydieresis Ocircumflex -85
-KPX Ydieresis Odieresis -85
-KPX Ydieresis Ograve -85
-KPX Ydieresis Ohungarumlaut -85
-KPX Ydieresis Omacron -85
-KPX Ydieresis Oslash -85
-KPX Ydieresis Otilde -85
-KPX Ydieresis a -140
-KPX Ydieresis aacute -140
-KPX Ydieresis abreve -70
-KPX Ydieresis acircumflex -140
-KPX Ydieresis adieresis -140
-KPX Ydieresis agrave -140
-KPX Ydieresis amacron -70
-KPX Ydieresis aogonek -140
-KPX Ydieresis aring -140
-KPX Ydieresis atilde -70
-KPX Ydieresis colon -60
-KPX Ydieresis comma -140
-KPX Ydieresis e -140
-KPX Ydieresis eacute -140
-KPX Ydieresis ecaron -140
-KPX Ydieresis ecircumflex -140
-KPX Ydieresis edieresis -140
-KPX Ydieresis edotaccent -140
-KPX Ydieresis egrave -140
-KPX Ydieresis emacron -70
-KPX Ydieresis eogonek -140
-KPX Ydieresis hyphen -140
-KPX Ydieresis i -20
-KPX Ydieresis iacute -20
-KPX Ydieresis iogonek -20
-KPX Ydieresis o -140
-KPX Ydieresis oacute -140
-KPX Ydieresis ocircumflex -140
-KPX Ydieresis odieresis -140
-KPX Ydieresis ograve -140
-KPX Ydieresis ohungarumlaut -140
-KPX Ydieresis omacron -140
-KPX Ydieresis oslash -140
-KPX Ydieresis otilde -140
-KPX Ydieresis period -140
-KPX Ydieresis semicolon -60
-KPX Ydieresis u -110
-KPX Ydieresis uacute -110
-KPX Ydieresis ucircumflex -110
-KPX Ydieresis udieresis -110
-KPX Ydieresis ugrave -110
-KPX Ydieresis uhungarumlaut -110
-KPX Ydieresis umacron -110
-KPX Ydieresis uogonek -110
-KPX Ydieresis uring -110
-KPX a v -20
-KPX a w -20
-KPX a y -30
-KPX a yacute -30
-KPX a ydieresis -30
-KPX aacute v -20
-KPX aacute w -20
-KPX aacute y -30
-KPX aacute yacute -30
-KPX aacute ydieresis -30
-KPX abreve v -20
-KPX abreve w -20
-KPX abreve y -30
-KPX abreve yacute -30
-KPX abreve ydieresis -30
-KPX acircumflex v -20
-KPX acircumflex w -20
-KPX acircumflex y -30
-KPX acircumflex yacute -30
-KPX acircumflex ydieresis -30
-KPX adieresis v -20
-KPX adieresis w -20
-KPX adieresis y -30
-KPX adieresis yacute -30
-KPX adieresis ydieresis -30
-KPX agrave v -20
-KPX agrave w -20
-KPX agrave y -30
-KPX agrave yacute -30
-KPX agrave ydieresis -30
-KPX amacron v -20
-KPX amacron w -20
-KPX amacron y -30
-KPX amacron yacute -30
-KPX amacron ydieresis -30
-KPX aogonek v -20
-KPX aogonek w -20
-KPX aogonek y -30
-KPX aogonek yacute -30
-KPX aogonek ydieresis -30
-KPX aring v -20
-KPX aring w -20
-KPX aring y -30
-KPX aring yacute -30
-KPX aring ydieresis -30
-KPX atilde v -20
-KPX atilde w -20
-KPX atilde y -30
-KPX atilde yacute -30
-KPX atilde ydieresis -30
-KPX b b -10
-KPX b comma -40
-KPX b l -20
-KPX b lacute -20
-KPX b lcommaaccent -20
-KPX b lslash -20
-KPX b period -40
-KPX b u -20
-KPX b uacute -20
-KPX b ucircumflex -20
-KPX b udieresis -20
-KPX b ugrave -20
-KPX b uhungarumlaut -20
-KPX b umacron -20
-KPX b uogonek -20
-KPX b uring -20
-KPX b v -20
-KPX b y -20
-KPX b yacute -20
-KPX b ydieresis -20
-KPX c comma -15
-KPX c k -20
-KPX c kcommaaccent -20
-KPX cacute comma -15
-KPX cacute k -20
-KPX cacute kcommaaccent -20
-KPX ccaron comma -15
-KPX ccaron k -20
-KPX ccaron kcommaaccent -20
-KPX ccedilla comma -15
-KPX ccedilla k -20
-KPX ccedilla kcommaaccent -20
-KPX colon space -50
-KPX comma quotedblright -100
-KPX comma quoteright -100
-KPX e comma -15
-KPX e period -15
-KPX e v -30
-KPX e w -20
-KPX e x -30
-KPX e y -20
-KPX e yacute -20
-KPX e ydieresis -20
-KPX eacute comma -15
-KPX eacute period -15
-KPX eacute v -30
-KPX eacute w -20
-KPX eacute x -30
-KPX eacute y -20
-KPX eacute yacute -20
-KPX eacute ydieresis -20
-KPX ecaron comma -15
-KPX ecaron period -15
-KPX ecaron v -30
-KPX ecaron w -20
-KPX ecaron x -30
-KPX ecaron y -20
-KPX ecaron yacute -20
-KPX ecaron ydieresis -20
-KPX ecircumflex comma -15
-KPX ecircumflex period -15
-KPX ecircumflex v -30
-KPX ecircumflex w -20
-KPX ecircumflex x -30
-KPX ecircumflex y -20
-KPX ecircumflex yacute -20
-KPX ecircumflex ydieresis -20
-KPX edieresis comma -15
-KPX edieresis period -15
-KPX edieresis v -30
-KPX edieresis w -20
-KPX edieresis x -30
-KPX edieresis y -20
-KPX edieresis yacute -20
-KPX edieresis ydieresis -20
-KPX edotaccent comma -15
-KPX edotaccent period -15
-KPX edotaccent v -30
-KPX edotaccent w -20
-KPX edotaccent x -30
-KPX edotaccent y -20
-KPX edotaccent yacute -20
-KPX edotaccent ydieresis -20
-KPX egrave comma -15
-KPX egrave period -15
-KPX egrave v -30
-KPX egrave w -20
-KPX egrave x -30
-KPX egrave y -20
-KPX egrave yacute -20
-KPX egrave ydieresis -20
-KPX emacron comma -15
-KPX emacron period -15
-KPX emacron v -30
-KPX emacron w -20
-KPX emacron x -30
-KPX emacron y -20
-KPX emacron yacute -20
-KPX emacron ydieresis -20
-KPX eogonek comma -15
-KPX eogonek period -15
-KPX eogonek v -30
-KPX eogonek w -20
-KPX eogonek x -30
-KPX eogonek y -20
-KPX eogonek yacute -20
-KPX eogonek ydieresis -20
-KPX f a -30
-KPX f aacute -30
-KPX f abreve -30
-KPX f acircumflex -30
-KPX f adieresis -30
-KPX f agrave -30
-KPX f amacron -30
-KPX f aogonek -30
-KPX f aring -30
-KPX f atilde -30
-KPX f comma -30
-KPX f dotlessi -28
-KPX f e -30
-KPX f eacute -30
-KPX f ecaron -30
-KPX f ecircumflex -30
-KPX f edieresis -30
-KPX f edotaccent -30
-KPX f egrave -30
-KPX f emacron -30
-KPX f eogonek -30
-KPX f o -30
-KPX f oacute -30
-KPX f ocircumflex -30
-KPX f odieresis -30
-KPX f ograve -30
-KPX f ohungarumlaut -30
-KPX f omacron -30
-KPX f oslash -30
-KPX f otilde -30
-KPX f period -30
-KPX f quotedblright 60
-KPX f quoteright 50
-KPX g r -10
-KPX g racute -10
-KPX g rcaron -10
-KPX g rcommaaccent -10
-KPX gbreve r -10
-KPX gbreve racute -10
-KPX gbreve rcaron -10
-KPX gbreve rcommaaccent -10
-KPX gcommaaccent r -10
-KPX gcommaaccent racute -10
-KPX gcommaaccent rcaron -10
-KPX gcommaaccent rcommaaccent -10
-KPX h y -30
-KPX h yacute -30
-KPX h ydieresis -30
-KPX k e -20
-KPX k eacute -20
-KPX k ecaron -20
-KPX k ecircumflex -20
-KPX k edieresis -20
-KPX k edotaccent -20
-KPX k egrave -20
-KPX k emacron -20
-KPX k eogonek -20
-KPX k o -20
-KPX k oacute -20
-KPX k ocircumflex -20
-KPX k odieresis -20
-KPX k ograve -20
-KPX k ohungarumlaut -20
-KPX k omacron -20
-KPX k oslash -20
-KPX k otilde -20
-KPX kcommaaccent e -20
-KPX kcommaaccent eacute -20
-KPX kcommaaccent ecaron -20
-KPX kcommaaccent ecircumflex -20
-KPX kcommaaccent edieresis -20
-KPX kcommaaccent edotaccent -20
-KPX kcommaaccent egrave -20
-KPX kcommaaccent emacron -20
-KPX kcommaaccent eogonek -20
-KPX kcommaaccent o -20
-KPX kcommaaccent oacute -20
-KPX kcommaaccent ocircumflex -20
-KPX kcommaaccent odieresis -20
-KPX kcommaaccent ograve -20
-KPX kcommaaccent ohungarumlaut -20
-KPX kcommaaccent omacron -20
-KPX kcommaaccent oslash -20
-KPX kcommaaccent otilde -20
-KPX m u -10
-KPX m uacute -10
-KPX m ucircumflex -10
-KPX m udieresis -10
-KPX m ugrave -10
-KPX m uhungarumlaut -10
-KPX m umacron -10
-KPX m uogonek -10
-KPX m uring -10
-KPX m y -15
-KPX m yacute -15
-KPX m ydieresis -15
-KPX n u -10
-KPX n uacute -10
-KPX n ucircumflex -10
-KPX n udieresis -10
-KPX n ugrave -10
-KPX n uhungarumlaut -10
-KPX n umacron -10
-KPX n uogonek -10
-KPX n uring -10
-KPX n v -20
-KPX n y -15
-KPX n yacute -15
-KPX n ydieresis -15
-KPX nacute u -10
-KPX nacute uacute -10
-KPX nacute ucircumflex -10
-KPX nacute udieresis -10
-KPX nacute ugrave -10
-KPX nacute uhungarumlaut -10
-KPX nacute umacron -10
-KPX nacute uogonek -10
-KPX nacute uring -10
-KPX nacute v -20
-KPX nacute y -15
-KPX nacute yacute -15
-KPX nacute ydieresis -15
-KPX ncaron u -10
-KPX ncaron uacute -10
-KPX ncaron ucircumflex -10
-KPX ncaron udieresis -10
-KPX ncaron ugrave -10
-KPX ncaron uhungarumlaut -10
-KPX ncaron umacron -10
-KPX ncaron uogonek -10
-KPX ncaron uring -10
-KPX ncaron v -20
-KPX ncaron y -15
-KPX ncaron yacute -15
-KPX ncaron ydieresis -15
-KPX ncommaaccent u -10
-KPX ncommaaccent uacute -10
-KPX ncommaaccent ucircumflex -10
-KPX ncommaaccent udieresis -10
-KPX ncommaaccent ugrave -10
-KPX ncommaaccent uhungarumlaut -10
-KPX ncommaaccent umacron -10
-KPX ncommaaccent uogonek -10
-KPX ncommaaccent uring -10
-KPX ncommaaccent v -20
-KPX ncommaaccent y -15
-KPX ncommaaccent yacute -15
-KPX ncommaaccent ydieresis -15
-KPX ntilde u -10
-KPX ntilde uacute -10
-KPX ntilde ucircumflex -10
-KPX ntilde udieresis -10
-KPX ntilde ugrave -10
-KPX ntilde uhungarumlaut -10
-KPX ntilde umacron -10
-KPX ntilde uogonek -10
-KPX ntilde uring -10
-KPX ntilde v -20
-KPX ntilde y -15
-KPX ntilde yacute -15
-KPX ntilde ydieresis -15
-KPX o comma -40
-KPX o period -40
-KPX o v -15
-KPX o w -15
-KPX o x -30
-KPX o y -30
-KPX o yacute -30
-KPX o ydieresis -30
-KPX oacute comma -40
-KPX oacute period -40
-KPX oacute v -15
-KPX oacute w -15
-KPX oacute x -30
-KPX oacute y -30
-KPX oacute yacute -30
-KPX oacute ydieresis -30
-KPX ocircumflex comma -40
-KPX ocircumflex period -40
-KPX ocircumflex v -15
-KPX ocircumflex w -15
-KPX ocircumflex x -30
-KPX ocircumflex y -30
-KPX ocircumflex yacute -30
-KPX ocircumflex ydieresis -30
-KPX odieresis comma -40
-KPX odieresis period -40
-KPX odieresis v -15
-KPX odieresis w -15
-KPX odieresis x -30
-KPX odieresis y -30
-KPX odieresis yacute -30
-KPX odieresis ydieresis -30
-KPX ograve comma -40
-KPX ograve period -40
-KPX ograve v -15
-KPX ograve w -15
-KPX ograve x -30
-KPX ograve y -30
-KPX ograve yacute -30
-KPX ograve ydieresis -30
-KPX ohungarumlaut comma -40
-KPX ohungarumlaut period -40
-KPX ohungarumlaut v -15
-KPX ohungarumlaut w -15
-KPX ohungarumlaut x -30
-KPX ohungarumlaut y -30
-KPX ohungarumlaut yacute -30
-KPX ohungarumlaut ydieresis -30
-KPX omacron comma -40
-KPX omacron period -40
-KPX omacron v -15
-KPX omacron w -15
-KPX omacron x -30
-KPX omacron y -30
-KPX omacron yacute -30
-KPX omacron ydieresis -30
-KPX oslash a -55
-KPX oslash aacute -55
-KPX oslash abreve -55
-KPX oslash acircumflex -55
-KPX oslash adieresis -55
-KPX oslash agrave -55
-KPX oslash amacron -55
-KPX oslash aogonek -55
-KPX oslash aring -55
-KPX oslash atilde -55
-KPX oslash b -55
-KPX oslash c -55
-KPX oslash cacute -55
-KPX oslash ccaron -55
-KPX oslash ccedilla -55
-KPX oslash comma -95
-KPX oslash d -55
-KPX oslash dcroat -55
-KPX oslash e -55
-KPX oslash eacute -55
-KPX oslash ecaron -55
-KPX oslash ecircumflex -55
-KPX oslash edieresis -55
-KPX oslash edotaccent -55
-KPX oslash egrave -55
-KPX oslash emacron -55
-KPX oslash eogonek -55
-KPX oslash f -55
-KPX oslash g -55
-KPX oslash gbreve -55
-KPX oslash gcommaaccent -55
-KPX oslash h -55
-KPX oslash i -55
-KPX oslash iacute -55
-KPX oslash icircumflex -55
-KPX oslash idieresis -55
-KPX oslash igrave -55
-KPX oslash imacron -55
-KPX oslash iogonek -55
-KPX oslash j -55
-KPX oslash k -55
-KPX oslash kcommaaccent -55
-KPX oslash l -55
-KPX oslash lacute -55
-KPX oslash lcommaaccent -55
-KPX oslash lslash -55
-KPX oslash m -55
-KPX oslash n -55
-KPX oslash nacute -55
-KPX oslash ncaron -55
-KPX oslash ncommaaccent -55
-KPX oslash ntilde -55
-KPX oslash o -55
-KPX oslash oacute -55
-KPX oslash ocircumflex -55
-KPX oslash odieresis -55
-KPX oslash ograve -55
-KPX oslash ohungarumlaut -55
-KPX oslash omacron -55
-KPX oslash oslash -55
-KPX oslash otilde -55
-KPX oslash p -55
-KPX oslash period -95
-KPX oslash q -55
-KPX oslash r -55
-KPX oslash racute -55
-KPX oslash rcaron -55
-KPX oslash rcommaaccent -55
-KPX oslash s -55
-KPX oslash sacute -55
-KPX oslash scaron -55
-KPX oslash scedilla -55
-KPX oslash scommaaccent -55
-KPX oslash t -55
-KPX oslash tcommaaccent -55
-KPX oslash u -55
-KPX oslash uacute -55
-KPX oslash ucircumflex -55
-KPX oslash udieresis -55
-KPX oslash ugrave -55
-KPX oslash uhungarumlaut -55
-KPX oslash umacron -55
-KPX oslash uogonek -55
-KPX oslash uring -55
-KPX oslash v -70
-KPX oslash w -70
-KPX oslash x -85
-KPX oslash y -70
-KPX oslash yacute -70
-KPX oslash ydieresis -70
-KPX oslash z -55
-KPX oslash zacute -55
-KPX oslash zcaron -55
-KPX oslash zdotaccent -55
-KPX otilde comma -40
-KPX otilde period -40
-KPX otilde v -15
-KPX otilde w -15
-KPX otilde x -30
-KPX otilde y -30
-KPX otilde yacute -30
-KPX otilde ydieresis -30
-KPX p comma -35
-KPX p period -35
-KPX p y -30
-KPX p yacute -30
-KPX p ydieresis -30
-KPX period quotedblright -100
-KPX period quoteright -100
-KPX period space -60
-KPX quotedblright space -40
-KPX quoteleft quoteleft -57
-KPX quoteright d -50
-KPX quoteright dcroat -50
-KPX quoteright quoteright -57
-KPX quoteright r -50
-KPX quoteright racute -50
-KPX quoteright rcaron -50
-KPX quoteright rcommaaccent -50
-KPX quoteright s -50
-KPX quoteright sacute -50
-KPX quoteright scaron -50
-KPX quoteright scedilla -50
-KPX quoteright scommaaccent -50
-KPX quoteright space -70
-KPX r a -10
-KPX r aacute -10
-KPX r abreve -10
-KPX r acircumflex -10
-KPX r adieresis -10
-KPX r agrave -10
-KPX r amacron -10
-KPX r aogonek -10
-KPX r aring -10
-KPX r atilde -10
-KPX r colon 30
-KPX r comma -50
-KPX r i 15
-KPX r iacute 15
-KPX r icircumflex 15
-KPX r idieresis 15
-KPX r igrave 15
-KPX r imacron 15
-KPX r iogonek 15
-KPX r k 15
-KPX r kcommaaccent 15
-KPX r l 15
-KPX r lacute 15
-KPX r lcommaaccent 15
-KPX r lslash 15
-KPX r m 25
-KPX r n 25
-KPX r nacute 25
-KPX r ncaron 25
-KPX r ncommaaccent 25
-KPX r ntilde 25
-KPX r p 30
-KPX r period -50
-KPX r semicolon 30
-KPX r t 40
-KPX r tcommaaccent 40
-KPX r u 15
-KPX r uacute 15
-KPX r ucircumflex 15
-KPX r udieresis 15
-KPX r ugrave 15
-KPX r uhungarumlaut 15
-KPX r umacron 15
-KPX r uogonek 15
-KPX r uring 15
-KPX r v 30
-KPX r y 30
-KPX r yacute 30
-KPX r ydieresis 30
-KPX racute a -10
-KPX racute aacute -10
-KPX racute abreve -10
-KPX racute acircumflex -10
-KPX racute adieresis -10
-KPX racute agrave -10
-KPX racute amacron -10
-KPX racute aogonek -10
-KPX racute aring -10
-KPX racute atilde -10
-KPX racute colon 30
-KPX racute comma -50
-KPX racute i 15
-KPX racute iacute 15
-KPX racute icircumflex 15
-KPX racute idieresis 15
-KPX racute igrave 15
-KPX racute imacron 15
-KPX racute iogonek 15
-KPX racute k 15
-KPX racute kcommaaccent 15
-KPX racute l 15
-KPX racute lacute 15
-KPX racute lcommaaccent 15
-KPX racute lslash 15
-KPX racute m 25
-KPX racute n 25
-KPX racute nacute 25
-KPX racute ncaron 25
-KPX racute ncommaaccent 25
-KPX racute ntilde 25
-KPX racute p 30
-KPX racute period -50
-KPX racute semicolon 30
-KPX racute t 40
-KPX racute tcommaaccent 40
-KPX racute u 15
-KPX racute uacute 15
-KPX racute ucircumflex 15
-KPX racute udieresis 15
-KPX racute ugrave 15
-KPX racute uhungarumlaut 15
-KPX racute umacron 15
-KPX racute uogonek 15
-KPX racute uring 15
-KPX racute v 30
-KPX racute y 30
-KPX racute yacute 30
-KPX racute ydieresis 30
-KPX rcaron a -10
-KPX rcaron aacute -10
-KPX rcaron abreve -10
-KPX rcaron acircumflex -10
-KPX rcaron adieresis -10
-KPX rcaron agrave -10
-KPX rcaron amacron -10
-KPX rcaron aogonek -10
-KPX rcaron aring -10
-KPX rcaron atilde -10
-KPX rcaron colon 30
-KPX rcaron comma -50
-KPX rcaron i 15
-KPX rcaron iacute 15
-KPX rcaron icircumflex 15
-KPX rcaron idieresis 15
-KPX rcaron igrave 15
-KPX rcaron imacron 15
-KPX rcaron iogonek 15
-KPX rcaron k 15
-KPX rcaron kcommaaccent 15
-KPX rcaron l 15
-KPX rcaron lacute 15
-KPX rcaron lcommaaccent 15
-KPX rcaron lslash 15
-KPX rcaron m 25
-KPX rcaron n 25
-KPX rcaron nacute 25
-KPX rcaron ncaron 25
-KPX rcaron ncommaaccent 25
-KPX rcaron ntilde 25
-KPX rcaron p 30
-KPX rcaron period -50
-KPX rcaron semicolon 30
-KPX rcaron t 40
-KPX rcaron tcommaaccent 40
-KPX rcaron u 15
-KPX rcaron uacute 15
-KPX rcaron ucircumflex 15
-KPX rcaron udieresis 15
-KPX rcaron ugrave 15
-KPX rcaron uhungarumlaut 15
-KPX rcaron umacron 15
-KPX rcaron uogonek 15
-KPX rcaron uring 15
-KPX rcaron v 30
-KPX rcaron y 30
-KPX rcaron yacute 30
-KPX rcaron ydieresis 30
-KPX rcommaaccent a -10
-KPX rcommaaccent aacute -10
-KPX rcommaaccent abreve -10
-KPX rcommaaccent acircumflex -10
-KPX rcommaaccent adieresis -10
-KPX rcommaaccent agrave -10
-KPX rcommaaccent amacron -10
-KPX rcommaaccent aogonek -10
-KPX rcommaaccent aring -10
-KPX rcommaaccent atilde -10
-KPX rcommaaccent colon 30
-KPX rcommaaccent comma -50
-KPX rcommaaccent i 15
-KPX rcommaaccent iacute 15
-KPX rcommaaccent icircumflex 15
-KPX rcommaaccent idieresis 15
-KPX rcommaaccent igrave 15
-KPX rcommaaccent imacron 15
-KPX rcommaaccent iogonek 15
-KPX rcommaaccent k 15
-KPX rcommaaccent kcommaaccent 15
-KPX rcommaaccent l 15
-KPX rcommaaccent lacute 15
-KPX rcommaaccent lcommaaccent 15
-KPX rcommaaccent lslash 15
-KPX rcommaaccent m 25
-KPX rcommaaccent n 25
-KPX rcommaaccent nacute 25
-KPX rcommaaccent ncaron 25
-KPX rcommaaccent ncommaaccent 25
-KPX rcommaaccent ntilde 25
-KPX rcommaaccent p 30
-KPX rcommaaccent period -50
-KPX rcommaaccent semicolon 30
-KPX rcommaaccent t 40
-KPX rcommaaccent tcommaaccent 40
-KPX rcommaaccent u 15
-KPX rcommaaccent uacute 15
-KPX rcommaaccent ucircumflex 15
-KPX rcommaaccent udieresis 15
-KPX rcommaaccent ugrave 15
-KPX rcommaaccent uhungarumlaut 15
-KPX rcommaaccent umacron 15
-KPX rcommaaccent uogonek 15
-KPX rcommaaccent uring 15
-KPX rcommaaccent v 30
-KPX rcommaaccent y 30
-KPX rcommaaccent yacute 30
-KPX rcommaaccent ydieresis 30
-KPX s comma -15
-KPX s period -15
-KPX s w -30
-KPX sacute comma -15
-KPX sacute period -15
-KPX sacute w -30
-KPX scaron comma -15
-KPX scaron period -15
-KPX scaron w -30
-KPX scedilla comma -15
-KPX scedilla period -15
-KPX scedilla w -30
-KPX scommaaccent comma -15
-KPX scommaaccent period -15
-KPX scommaaccent w -30
-KPX semicolon space -50
-KPX space T -50
-KPX space Tcaron -50
-KPX space Tcommaaccent -50
-KPX space V -50
-KPX space W -40
-KPX space Y -90
-KPX space Yacute -90
-KPX space Ydieresis -90
-KPX space quotedblleft -30
-KPX space quoteleft -60
-KPX v a -25
-KPX v aacute -25
-KPX v abreve -25
-KPX v acircumflex -25
-KPX v adieresis -25
-KPX v agrave -25
-KPX v amacron -25
-KPX v aogonek -25
-KPX v aring -25
-KPX v atilde -25
-KPX v comma -80
-KPX v e -25
-KPX v eacute -25
-KPX v ecaron -25
-KPX v ecircumflex -25
-KPX v edieresis -25
-KPX v edotaccent -25
-KPX v egrave -25
-KPX v emacron -25
-KPX v eogonek -25
-KPX v o -25
-KPX v oacute -25
-KPX v ocircumflex -25
-KPX v odieresis -25
-KPX v ograve -25
-KPX v ohungarumlaut -25
-KPX v omacron -25
-KPX v oslash -25
-KPX v otilde -25
-KPX v period -80
-KPX w a -15
-KPX w aacute -15
-KPX w abreve -15
-KPX w acircumflex -15
-KPX w adieresis -15
-KPX w agrave -15
-KPX w amacron -15
-KPX w aogonek -15
-KPX w aring -15
-KPX w atilde -15
-KPX w comma -60
-KPX w e -10
-KPX w eacute -10
-KPX w ecaron -10
-KPX w ecircumflex -10
-KPX w edieresis -10
-KPX w edotaccent -10
-KPX w egrave -10
-KPX w emacron -10
-KPX w eogonek -10
-KPX w o -10
-KPX w oacute -10
-KPX w ocircumflex -10
-KPX w odieresis -10
-KPX w ograve -10
-KPX w ohungarumlaut -10
-KPX w omacron -10
-KPX w oslash -10
-KPX w otilde -10
-KPX w period -60
-KPX x e -30
-KPX x eacute -30
-KPX x ecaron -30
-KPX x ecircumflex -30
-KPX x edieresis -30
-KPX x edotaccent -30
-KPX x egrave -30
-KPX x emacron -30
-KPX x eogonek -30
-KPX y a -20
-KPX y aacute -20
-KPX y abreve -20
-KPX y acircumflex -20
-KPX y adieresis -20
-KPX y agrave -20
-KPX y amacron -20
-KPX y aogonek -20
-KPX y aring -20
-KPX y atilde -20
-KPX y comma -100
-KPX y e -20
-KPX y eacute -20
-KPX y ecaron -20
-KPX y ecircumflex -20
-KPX y edieresis -20
-KPX y edotaccent -20
-KPX y egrave -20
-KPX y emacron -20
-KPX y eogonek -20
-KPX y o -20
-KPX y oacute -20
-KPX y ocircumflex -20
-KPX y odieresis -20
-KPX y ograve -20
-KPX y ohungarumlaut -20
-KPX y omacron -20
-KPX y oslash -20
-KPX y otilde -20
-KPX y period -100
-KPX yacute a -20
-KPX yacute aacute -20
-KPX yacute abreve -20
-KPX yacute acircumflex -20
-KPX yacute adieresis -20
-KPX yacute agrave -20
-KPX yacute amacron -20
-KPX yacute aogonek -20
-KPX yacute aring -20
-KPX yacute atilde -20
-KPX yacute comma -100
-KPX yacute e -20
-KPX yacute eacute -20
-KPX yacute ecaron -20
-KPX yacute ecircumflex -20
-KPX yacute edieresis -20
-KPX yacute edotaccent -20
-KPX yacute egrave -20
-KPX yacute emacron -20
-KPX yacute eogonek -20
-KPX yacute o -20
-KPX yacute oacute -20
-KPX yacute ocircumflex -20
-KPX yacute odieresis -20
-KPX yacute ograve -20
-KPX yacute ohungarumlaut -20
-KPX yacute omacron -20
-KPX yacute oslash -20
-KPX yacute otilde -20
-KPX yacute period -100
-KPX ydieresis a -20
-KPX ydieresis aacute -20
-KPX ydieresis abreve -20
-KPX ydieresis acircumflex -20
-KPX ydieresis adieresis -20
-KPX ydieresis agrave -20
-KPX ydieresis amacron -20
-KPX ydieresis aogonek -20
-KPX ydieresis aring -20
-KPX ydieresis atilde -20
-KPX ydieresis comma -100
-KPX ydieresis e -20
-KPX ydieresis eacute -20
-KPX ydieresis ecaron -20
-KPX ydieresis ecircumflex -20
-KPX ydieresis edieresis -20
-KPX ydieresis edotaccent -20
-KPX ydieresis egrave -20
-KPX ydieresis emacron -20
-KPX ydieresis eogonek -20
-KPX ydieresis o -20
-KPX ydieresis oacute -20
-KPX ydieresis ocircumflex -20
-KPX ydieresis odieresis -20
-KPX ydieresis ograve -20
-KPX ydieresis ohungarumlaut -20
-KPX ydieresis omacron -20
-KPX ydieresis oslash -20
-KPX ydieresis otilde -20
-KPX ydieresis period -100
-KPX z e -15
-KPX z eacute -15
-KPX z ecaron -15
-KPX z ecircumflex -15
-KPX z edieresis -15
-KPX z edotaccent -15
-KPX z egrave -15
-KPX z emacron -15
-KPX z eogonek -15
-KPX z o -15
-KPX z oacute -15
-KPX z ocircumflex -15
-KPX z odieresis -15
-KPX z ograve -15
-KPX z ohungarumlaut -15
-KPX z omacron -15
-KPX z oslash -15
-KPX z otilde -15
-KPX zacute e -15
-KPX zacute eacute -15
-KPX zacute ecaron -15
-KPX zacute ecircumflex -15
-KPX zacute edieresis -15
-KPX zacute edotaccent -15
-KPX zacute egrave -15
-KPX zacute emacron -15
-KPX zacute eogonek -15
-KPX zacute o -15
-KPX zacute oacute -15
-KPX zacute ocircumflex -15
-KPX zacute odieresis -15
-KPX zacute ograve -15
-KPX zacute ohungarumlaut -15
-KPX zacute omacron -15
-KPX zacute oslash -15
-KPX zacute otilde -15
-KPX zcaron e -15
-KPX zcaron eacute -15
-KPX zcaron ecaron -15
-KPX zcaron ecircumflex -15
-KPX zcaron edieresis -15
-KPX zcaron edotaccent -15
-KPX zcaron egrave -15
-KPX zcaron emacron -15
-KPX zcaron eogonek -15
-KPX zcaron o -15
-KPX zcaron oacute -15
-KPX zcaron ocircumflex -15
-KPX zcaron odieresis -15
-KPX zcaron ograve -15
-KPX zcaron ohungarumlaut -15
-KPX zcaron omacron -15
-KPX zcaron oslash -15
-KPX zcaron otilde -15
-KPX zdotaccent e -15
-KPX zdotaccent eacute -15
-KPX zdotaccent ecaron -15
-KPX zdotaccent ecircumflex -15
-KPX zdotaccent edieresis -15
-KPX zdotaccent edotaccent -15
-KPX zdotaccent egrave -15
-KPX zdotaccent emacron -15
-KPX zdotaccent eogonek -15
-KPX zdotaccent o -15
-KPX zdotaccent oacute -15
-KPX zdotaccent ocircumflex -15
-KPX zdotaccent odieresis -15
-KPX zdotaccent ograve -15
-KPX zdotaccent ohungarumlaut -15
-KPX zdotaccent omacron -15
-KPX zdotaccent oslash -15
-KPX zdotaccent otilde -15
-EndKernPairs
-EndKernData
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/License-Adobe.txt pdftk-2.01/java/com/lowagie/text/pdf/fonts/License-Adobe.txt
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/License-Adobe.txt 2005-11-01 13:49:20.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/License-Adobe.txt 1970-01-01 00:00:00.000000000 +0000
@@ -1,65 +0,0 @@
-This file and the 14 PostScript(R) AFM files it accompanies may be
-used, copied, and distributed for any purpose and without charge, with
-or without modification, provided that all copyright notices are
-retained; that the AFM files are not distributed without this file;
-that all modifications to this file or any of the AFM files are
-prominently noted in the modified file(s); and that this paragraph is
-not modified. Adobe Systems has no responsibility or obligation to
-support the use of the AFM files.
-
-
-Courier-Bold.afm:
-Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated.
-All Rights Reserved.
-
-Courier-BoldOblique.afm:
-Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated.
-All Rights Reserved.
-
-Courier-Oblique.afm:
-Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated.
-
-All Rights Reserved.
-Courier.afm:
-Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated.
-All Rights Reserved.
-
-Helvetica-Bold.afm:
-Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.
-All Rights Reserved.
-
-Helvetica-BoldOblique.afm:
-Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.
-All Rights Reserved.
-
-Helvetica-Oblique.afm:
-Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.
-All Rights Reserved.
-
-Helvetica.afm:
-Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.
-All Rights Reserved.
-
-Symbol.afm:
-Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.
-All rights reserved.
-
-Times-Bold.afm:
-Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.
-All Rights Reserved.
-
-Times-BoldItalic.afm:
-Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.
-All Rights Reserved.
-
-Times-Italic.afm:
-Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.
-All Rights Reserved.
-
-Times-Roman.afm:
-Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.
-All Rights Reserved.
-
-ZapfDingbats.afm:
-Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated.
-All Rights Reserved.
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Makefile pdftk-2.01/java/com/lowagie/text/pdf/fonts/Makefile
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Makefile 2010-09-15 09:43:08.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,52 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-library= fonts.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-# font metric files, included as resources
-afms= $(wildcard *.afm)
-afm_objects= $(patsubst %.afm, %.o, $(afms))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# the --resource argument gives the name by which this resource is
-# referenced; I took this prefix from RESOURCE_PATH in BaseFont.java
-%.o : %.afm
- $(GCJ) -c --resource com/lowagie/text/pdf/fonts/$< $< -o $@
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-# we don't include afm_objects in the final fonts.a, since
-# they must be referenced directly at link-time (for some reason)
-
-all : $(library) $(headers) $(afm_objects)
-
-$(library) : $(objects)
- $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Symbol.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Symbol.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Symbol.afm 2004-05-26 16:06:20.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Symbol.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,213 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All rights reserved.
-Comment Creation Date: Thu May 1 15:12:25 1997
-Comment UniqueID 43064
-Comment VMusage 30820 39997
-FontName Symbol
-FullName Symbol
-FamilyName Symbol
-Weight Medium
-ItalicAngle 0
-IsFixedPitch false
-CharacterSet Special
-FontBBox -180 -293 1090 1010
-UnderlinePosition -100
-UnderlineThickness 50
-Version 001.008
-Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All rights reserved.
-EncodingScheme FontSpecific
-StdHW 92
-StdVW 85
-StartCharMetrics 190
-C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 333 ; N exclam ; B 128 -17 240 672 ;
-C 34 ; WX 713 ; N universal ; B 31 0 681 705 ;
-C 35 ; WX 500 ; N numbersign ; B 20 -16 481 673 ;
-C 36 ; WX 549 ; N existential ; B 25 0 478 707 ;
-C 37 ; WX 833 ; N percent ; B 63 -36 771 655 ;
-C 38 ; WX 778 ; N ampersand ; B 41 -18 750 661 ;
-C 39 ; WX 439 ; N suchthat ; B 48 -17 414 500 ;
-C 40 ; WX 333 ; N parenleft ; B 53 -191 300 673 ;
-C 41 ; WX 333 ; N parenright ; B 30 -191 277 673 ;
-C 42 ; WX 500 ; N asteriskmath ; B 65 134 427 551 ;
-C 43 ; WX 549 ; N plus ; B 10 0 539 533 ;
-C 44 ; WX 250 ; N comma ; B 56 -152 194 104 ;
-C 45 ; WX 549 ; N minus ; B 11 233 535 288 ;
-C 46 ; WX 250 ; N period ; B 69 -17 181 95 ;
-C 47 ; WX 278 ; N slash ; B 0 -18 254 646 ;
-C 48 ; WX 500 ; N zero ; B 24 -14 476 685 ;
-C 49 ; WX 500 ; N one ; B 117 0 390 673 ;
-C 50 ; WX 500 ; N two ; B 25 0 475 685 ;
-C 51 ; WX 500 ; N three ; B 43 -14 435 685 ;
-C 52 ; WX 500 ; N four ; B 15 0 469 685 ;
-C 53 ; WX 500 ; N five ; B 32 -14 445 690 ;
-C 54 ; WX 500 ; N six ; B 34 -14 468 685 ;
-C 55 ; WX 500 ; N seven ; B 24 -16 448 673 ;
-C 56 ; WX 500 ; N eight ; B 56 -14 445 685 ;
-C 57 ; WX 500 ; N nine ; B 30 -18 459 685 ;
-C 58 ; WX 278 ; N colon ; B 81 -17 193 460 ;
-C 59 ; WX 278 ; N semicolon ; B 83 -152 221 460 ;
-C 60 ; WX 549 ; N less ; B 26 0 523 522 ;
-C 61 ; WX 549 ; N equal ; B 11 141 537 390 ;
-C 62 ; WX 549 ; N greater ; B 26 0 523 522 ;
-C 63 ; WX 444 ; N question ; B 70 -17 412 686 ;
-C 64 ; WX 549 ; N congruent ; B 11 0 537 475 ;
-C 65 ; WX 722 ; N Alpha ; B 4 0 684 673 ;
-C 66 ; WX 667 ; N Beta ; B 29 0 592 673 ;
-C 67 ; WX 722 ; N Chi ; B -9 0 704 673 ;
-C 68 ; WX 612 ; N Delta ; B 6 0 608 688 ;
-C 69 ; WX 611 ; N Epsilon ; B 32 0 617 673 ;
-C 70 ; WX 763 ; N Phi ; B 26 0 741 673 ;
-C 71 ; WX 603 ; N Gamma ; B 24 0 609 673 ;
-C 72 ; WX 722 ; N Eta ; B 39 0 729 673 ;
-C 73 ; WX 333 ; N Iota ; B 32 0 316 673 ;
-C 74 ; WX 631 ; N theta1 ; B 18 -18 623 689 ;
-C 75 ; WX 722 ; N Kappa ; B 35 0 722 673 ;
-C 76 ; WX 686 ; N Lambda ; B 6 0 680 688 ;
-C 77 ; WX 889 ; N Mu ; B 28 0 887 673 ;
-C 78 ; WX 722 ; N Nu ; B 29 -8 720 673 ;
-C 79 ; WX 722 ; N Omicron ; B 41 -17 715 685 ;
-C 80 ; WX 768 ; N Pi ; B 25 0 745 673 ;
-C 81 ; WX 741 ; N Theta ; B 41 -17 715 685 ;
-C 82 ; WX 556 ; N Rho ; B 28 0 563 673 ;
-C 83 ; WX 592 ; N Sigma ; B 5 0 589 673 ;
-C 84 ; WX 611 ; N Tau ; B 33 0 607 673 ;
-C 85 ; WX 690 ; N Upsilon ; B -8 0 694 673 ;
-C 86 ; WX 439 ; N sigma1 ; B 40 -233 436 500 ;
-C 87 ; WX 768 ; N Omega ; B 34 0 736 688 ;
-C 88 ; WX 645 ; N Xi ; B 40 0 599 673 ;
-C 89 ; WX 795 ; N Psi ; B 15 0 781 684 ;
-C 90 ; WX 611 ; N Zeta ; B 44 0 636 673 ;
-C 91 ; WX 333 ; N bracketleft ; B 86 -155 299 674 ;
-C 92 ; WX 863 ; N therefore ; B 163 0 701 487 ;
-C 93 ; WX 333 ; N bracketright ; B 33 -155 246 674 ;
-C 94 ; WX 658 ; N perpendicular ; B 15 0 652 674 ;
-C 95 ; WX 500 ; N underscore ; B -2 -125 502 -75 ;
-C 96 ; WX 500 ; N radicalex ; B 480 881 1090 917 ;
-C 97 ; WX 631 ; N alpha ; B 41 -18 622 500 ;
-C 98 ; WX 549 ; N beta ; B 61 -223 515 741 ;
-C 99 ; WX 549 ; N chi ; B 12 -231 522 499 ;
-C 100 ; WX 494 ; N delta ; B 40 -19 481 740 ;
-C 101 ; WX 439 ; N epsilon ; B 22 -19 427 502 ;
-C 102 ; WX 521 ; N phi ; B 28 -224 492 673 ;
-C 103 ; WX 411 ; N gamma ; B 5 -225 484 499 ;
-C 104 ; WX 603 ; N eta ; B 0 -202 527 514 ;
-C 105 ; WX 329 ; N iota ; B 0 -17 301 503 ;
-C 106 ; WX 603 ; N phi1 ; B 36 -224 587 499 ;
-C 107 ; WX 549 ; N kappa ; B 33 0 558 501 ;
-C 108 ; WX 549 ; N lambda ; B 24 -17 548 739 ;
-C 109 ; WX 576 ; N mu ; B 33 -223 567 500 ;
-C 110 ; WX 521 ; N nu ; B -9 -16 475 507 ;
-C 111 ; WX 549 ; N omicron ; B 35 -19 501 499 ;
-C 112 ; WX 549 ; N pi ; B 10 -19 530 487 ;
-C 113 ; WX 521 ; N theta ; B 43 -17 485 690 ;
-C 114 ; WX 549 ; N rho ; B 50 -230 490 499 ;
-C 115 ; WX 603 ; N sigma ; B 30 -21 588 500 ;
-C 116 ; WX 439 ; N tau ; B 10 -19 418 500 ;
-C 117 ; WX 576 ; N upsilon ; B 7 -18 535 507 ;
-C 118 ; WX 713 ; N omega1 ; B 12 -18 671 583 ;
-C 119 ; WX 686 ; N omega ; B 42 -17 684 500 ;
-C 120 ; WX 493 ; N xi ; B 27 -224 469 766 ;
-C 121 ; WX 686 ; N psi ; B 12 -228 701 500 ;
-C 122 ; WX 494 ; N zeta ; B 60 -225 467 756 ;
-C 123 ; WX 480 ; N braceleft ; B 58 -183 397 673 ;
-C 124 ; WX 200 ; N bar ; B 65 -293 135 707 ;
-C 125 ; WX 480 ; N braceright ; B 79 -183 418 673 ;
-C 126 ; WX 549 ; N similar ; B 17 203 529 307 ;
-C 160 ; WX 750 ; N Euro ; B 20 -12 714 685 ;
-C 161 ; WX 620 ; N Upsilon1 ; B -2 0 610 685 ;
-C 162 ; WX 247 ; N minute ; B 27 459 228 735 ;
-C 163 ; WX 549 ; N lessequal ; B 29 0 526 639 ;
-C 164 ; WX 167 ; N fraction ; B -180 -12 340 677 ;
-C 165 ; WX 713 ; N infinity ; B 26 124 688 404 ;
-C 166 ; WX 500 ; N florin ; B 2 -193 494 686 ;
-C 167 ; WX 753 ; N club ; B 86 -26 660 533 ;
-C 168 ; WX 753 ; N diamond ; B 142 -36 600 550 ;
-C 169 ; WX 753 ; N heart ; B 117 -33 631 532 ;
-C 170 ; WX 753 ; N spade ; B 113 -36 629 548 ;
-C 171 ; WX 1042 ; N arrowboth ; B 24 -15 1024 511 ;
-C 172 ; WX 987 ; N arrowleft ; B 32 -15 942 511 ;
-C 173 ; WX 603 ; N arrowup ; B 45 0 571 910 ;
-C 174 ; WX 987 ; N arrowright ; B 49 -15 959 511 ;
-C 175 ; WX 603 ; N arrowdown ; B 45 -22 571 888 ;
-C 176 ; WX 400 ; N degree ; B 50 385 350 685 ;
-C 177 ; WX 549 ; N plusminus ; B 10 0 539 645 ;
-C 178 ; WX 411 ; N second ; B 20 459 413 737 ;
-C 179 ; WX 549 ; N greaterequal ; B 29 0 526 639 ;
-C 180 ; WX 549 ; N multiply ; B 17 8 533 524 ;
-C 181 ; WX 713 ; N proportional ; B 27 123 639 404 ;
-C 182 ; WX 494 ; N partialdiff ; B 26 -20 462 746 ;
-C 183 ; WX 460 ; N bullet ; B 50 113 410 473 ;
-C 184 ; WX 549 ; N divide ; B 10 71 536 456 ;
-C 185 ; WX 549 ; N notequal ; B 15 -25 540 549 ;
-C 186 ; WX 549 ; N equivalence ; B 14 82 538 443 ;
-C 187 ; WX 549 ; N approxequal ; B 14 135 527 394 ;
-C 188 ; WX 1000 ; N ellipsis ; B 111 -17 889 95 ;
-C 189 ; WX 603 ; N arrowvertex ; B 280 -120 336 1010 ;
-C 190 ; WX 1000 ; N arrowhorizex ; B -60 220 1050 276 ;
-C 191 ; WX 658 ; N carriagereturn ; B 15 -16 602 629 ;
-C 192 ; WX 823 ; N aleph ; B 175 -18 661 658 ;
-C 193 ; WX 686 ; N Ifraktur ; B 10 -53 578 740 ;
-C 194 ; WX 795 ; N Rfraktur ; B 26 -15 759 734 ;
-C 195 ; WX 987 ; N weierstrass ; B 159 -211 870 573 ;
-C 196 ; WX 768 ; N circlemultiply ; B 43 -17 733 673 ;
-C 197 ; WX 768 ; N circleplus ; B 43 -15 733 675 ;
-C 198 ; WX 823 ; N emptyset ; B 39 -24 781 719 ;
-C 199 ; WX 768 ; N intersection ; B 40 0 732 509 ;
-C 200 ; WX 768 ; N union ; B 40 -17 732 492 ;
-C 201 ; WX 713 ; N propersuperset ; B 20 0 673 470 ;
-C 202 ; WX 713 ; N reflexsuperset ; B 20 -125 673 470 ;
-C 203 ; WX 713 ; N notsubset ; B 36 -70 690 540 ;
-C 204 ; WX 713 ; N propersubset ; B 37 0 690 470 ;
-C 205 ; WX 713 ; N reflexsubset ; B 37 -125 690 470 ;
-C 206 ; WX 713 ; N element ; B 45 0 505 468 ;
-C 207 ; WX 713 ; N notelement ; B 45 -58 505 555 ;
-C 208 ; WX 768 ; N angle ; B 26 0 738 673 ;
-C 209 ; WX 713 ; N gradient ; B 36 -19 681 718 ;
-C 210 ; WX 790 ; N registerserif ; B 50 -17 740 673 ;
-C 211 ; WX 790 ; N copyrightserif ; B 51 -15 741 675 ;
-C 212 ; WX 890 ; N trademarkserif ; B 18 293 855 673 ;
-C 213 ; WX 823 ; N product ; B 25 -101 803 751 ;
-C 214 ; WX 549 ; N radical ; B 10 -38 515 917 ;
-C 215 ; WX 250 ; N dotmath ; B 69 210 169 310 ;
-C 216 ; WX 713 ; N logicalnot ; B 15 0 680 288 ;
-C 217 ; WX 603 ; N logicaland ; B 23 0 583 454 ;
-C 218 ; WX 603 ; N logicalor ; B 30 0 578 477 ;
-C 219 ; WX 1042 ; N arrowdblboth ; B 27 -20 1023 510 ;
-C 220 ; WX 987 ; N arrowdblleft ; B 30 -15 939 513 ;
-C 221 ; WX 603 ; N arrowdblup ; B 39 2 567 911 ;
-C 222 ; WX 987 ; N arrowdblright ; B 45 -20 954 508 ;
-C 223 ; WX 603 ; N arrowdbldown ; B 44 -19 572 890 ;
-C 224 ; WX 494 ; N lozenge ; B 18 0 466 745 ;
-C 225 ; WX 329 ; N angleleft ; B 25 -198 306 746 ;
-C 226 ; WX 790 ; N registersans ; B 50 -20 740 670 ;
-C 227 ; WX 790 ; N copyrightsans ; B 49 -15 739 675 ;
-C 228 ; WX 786 ; N trademarksans ; B 5 293 725 673 ;
-C 229 ; WX 713 ; N summation ; B 14 -108 695 752 ;
-C 230 ; WX 384 ; N parenlefttp ; B 24 -293 436 926 ;
-C 231 ; WX 384 ; N parenleftex ; B 24 -85 108 925 ;
-C 232 ; WX 384 ; N parenleftbt ; B 24 -293 436 926 ;
-C 233 ; WX 384 ; N bracketlefttp ; B 0 -80 349 926 ;
-C 234 ; WX 384 ; N bracketleftex ; B 0 -79 77 925 ;
-C 235 ; WX 384 ; N bracketleftbt ; B 0 -80 349 926 ;
-C 236 ; WX 494 ; N bracelefttp ; B 209 -85 445 925 ;
-C 237 ; WX 494 ; N braceleftmid ; B 20 -85 284 935 ;
-C 238 ; WX 494 ; N braceleftbt ; B 209 -75 445 935 ;
-C 239 ; WX 494 ; N braceex ; B 209 -85 284 935 ;
-C 241 ; WX 329 ; N angleright ; B 21 -198 302 746 ;
-C 242 ; WX 274 ; N integral ; B 2 -107 291 916 ;
-C 243 ; WX 686 ; N integraltp ; B 308 -88 675 920 ;
-C 244 ; WX 686 ; N integralex ; B 308 -88 378 975 ;
-C 245 ; WX 686 ; N integralbt ; B 11 -87 378 921 ;
-C 246 ; WX 384 ; N parenrighttp ; B 54 -293 466 926 ;
-C 247 ; WX 384 ; N parenrightex ; B 382 -85 466 925 ;
-C 248 ; WX 384 ; N parenrightbt ; B 54 -293 466 926 ;
-C 249 ; WX 384 ; N bracketrighttp ; B 22 -80 371 926 ;
-C 250 ; WX 384 ; N bracketrightex ; B 294 -79 371 925 ;
-C 251 ; WX 384 ; N bracketrightbt ; B 22 -80 371 926 ;
-C 252 ; WX 494 ; N bracerighttp ; B 48 -85 284 925 ;
-C 253 ; WX 494 ; N bracerightmid ; B 209 -85 473 935 ;
-C 254 ; WX 494 ; N bracerightbt ; B 48 -75 284 935 ;
-C -1 ; WX 790 ; N apple ; B 56 -3 733 808 ;
-EndCharMetrics
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Times-Bold.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Times-Bold.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Times-Bold.afm 2004-05-26 16:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Times-Bold.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,2588 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Thu May 1 12:52:56 1997
-Comment UniqueID 43065
-Comment VMusage 41636 52661
-FontName Times-Bold
-FullName Times Bold
-FamilyName Times
-Weight Bold
-ItalicAngle 0
-IsFixedPitch false
-CharacterSet ExtendedRoman
-FontBBox -168 -218 1000 935
-UnderlinePosition -100
-UnderlineThickness 50
-Version 002.000
-Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries.
-EncodingScheme AdobeStandardEncoding
-CapHeight 676
-XHeight 461
-Ascender 683
-Descender -217
-StdHW 44
-StdVW 139
-StartCharMetrics 315
-C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 333 ; N exclam ; B 81 -13 251 691 ;
-C 34 ; WX 555 ; N quotedbl ; B 83 404 472 691 ;
-C 35 ; WX 500 ; N numbersign ; B 4 0 496 700 ;
-C 36 ; WX 500 ; N dollar ; B 29 -99 472 750 ;
-C 37 ; WX 1000 ; N percent ; B 124 -14 877 692 ;
-C 38 ; WX 833 ; N ampersand ; B 62 -16 787 691 ;
-C 39 ; WX 333 ; N quoteright ; B 79 356 263 691 ;
-C 40 ; WX 333 ; N parenleft ; B 46 -168 306 694 ;
-C 41 ; WX 333 ; N parenright ; B 27 -168 287 694 ;
-C 42 ; WX 500 ; N asterisk ; B 56 255 447 691 ;
-C 43 ; WX 570 ; N plus ; B 33 0 537 506 ;
-C 44 ; WX 250 ; N comma ; B 39 -180 223 155 ;
-C 45 ; WX 333 ; N hyphen ; B 44 171 287 287 ;
-C 46 ; WX 250 ; N period ; B 41 -13 210 156 ;
-C 47 ; WX 278 ; N slash ; B -24 -19 302 691 ;
-C 48 ; WX 500 ; N zero ; B 24 -13 476 688 ;
-C 49 ; WX 500 ; N one ; B 65 0 442 688 ;
-C 50 ; WX 500 ; N two ; B 17 0 478 688 ;
-C 51 ; WX 500 ; N three ; B 16 -14 468 688 ;
-C 52 ; WX 500 ; N four ; B 19 0 475 688 ;
-C 53 ; WX 500 ; N five ; B 22 -8 470 676 ;
-C 54 ; WX 500 ; N six ; B 28 -13 475 688 ;
-C 55 ; WX 500 ; N seven ; B 17 0 477 676 ;
-C 56 ; WX 500 ; N eight ; B 28 -13 472 688 ;
-C 57 ; WX 500 ; N nine ; B 26 -13 473 688 ;
-C 58 ; WX 333 ; N colon ; B 82 -13 251 472 ;
-C 59 ; WX 333 ; N semicolon ; B 82 -180 266 472 ;
-C 60 ; WX 570 ; N less ; B 31 -8 539 514 ;
-C 61 ; WX 570 ; N equal ; B 33 107 537 399 ;
-C 62 ; WX 570 ; N greater ; B 31 -8 539 514 ;
-C 63 ; WX 500 ; N question ; B 57 -13 445 689 ;
-C 64 ; WX 930 ; N at ; B 108 -19 822 691 ;
-C 65 ; WX 722 ; N A ; B 9 0 689 690 ;
-C 66 ; WX 667 ; N B ; B 16 0 619 676 ;
-C 67 ; WX 722 ; N C ; B 49 -19 687 691 ;
-C 68 ; WX 722 ; N D ; B 14 0 690 676 ;
-C 69 ; WX 667 ; N E ; B 16 0 641 676 ;
-C 70 ; WX 611 ; N F ; B 16 0 583 676 ;
-C 71 ; WX 778 ; N G ; B 37 -19 755 691 ;
-C 72 ; WX 778 ; N H ; B 21 0 759 676 ;
-C 73 ; WX 389 ; N I ; B 20 0 370 676 ;
-C 74 ; WX 500 ; N J ; B 3 -96 479 676 ;
-C 75 ; WX 778 ; N K ; B 30 0 769 676 ;
-C 76 ; WX 667 ; N L ; B 19 0 638 676 ;
-C 77 ; WX 944 ; N M ; B 14 0 921 676 ;
-C 78 ; WX 722 ; N N ; B 16 -18 701 676 ;
-C 79 ; WX 778 ; N O ; B 35 -19 743 691 ;
-C 80 ; WX 611 ; N P ; B 16 0 600 676 ;
-C 81 ; WX 778 ; N Q ; B 35 -176 743 691 ;
-C 82 ; WX 722 ; N R ; B 26 0 715 676 ;
-C 83 ; WX 556 ; N S ; B 35 -19 513 692 ;
-C 84 ; WX 667 ; N T ; B 31 0 636 676 ;
-C 85 ; WX 722 ; N U ; B 16 -19 701 676 ;
-C 86 ; WX 722 ; N V ; B 16 -18 701 676 ;
-C 87 ; WX 1000 ; N W ; B 19 -15 981 676 ;
-C 88 ; WX 722 ; N X ; B 16 0 699 676 ;
-C 89 ; WX 722 ; N Y ; B 15 0 699 676 ;
-C 90 ; WX 667 ; N Z ; B 28 0 634 676 ;
-C 91 ; WX 333 ; N bracketleft ; B 67 -149 301 678 ;
-C 92 ; WX 278 ; N backslash ; B -25 -19 303 691 ;
-C 93 ; WX 333 ; N bracketright ; B 32 -149 266 678 ;
-C 94 ; WX 581 ; N asciicircum ; B 73 311 509 676 ;
-C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
-C 96 ; WX 333 ; N quoteleft ; B 70 356 254 691 ;
-C 97 ; WX 500 ; N a ; B 25 -14 488 473 ;
-C 98 ; WX 556 ; N b ; B 17 -14 521 676 ;
-C 99 ; WX 444 ; N c ; B 25 -14 430 473 ;
-C 100 ; WX 556 ; N d ; B 25 -14 534 676 ;
-C 101 ; WX 444 ; N e ; B 25 -14 426 473 ;
-C 102 ; WX 333 ; N f ; B 14 0 389 691 ; L i fi ; L l fl ;
-C 103 ; WX 500 ; N g ; B 28 -206 483 473 ;
-C 104 ; WX 556 ; N h ; B 16 0 534 676 ;
-C 105 ; WX 278 ; N i ; B 16 0 255 691 ;
-C 106 ; WX 333 ; N j ; B -57 -203 263 691 ;
-C 107 ; WX 556 ; N k ; B 22 0 543 676 ;
-C 108 ; WX 278 ; N l ; B 16 0 255 676 ;
-C 109 ; WX 833 ; N m ; B 16 0 814 473 ;
-C 110 ; WX 556 ; N n ; B 21 0 539 473 ;
-C 111 ; WX 500 ; N o ; B 25 -14 476 473 ;
-C 112 ; WX 556 ; N p ; B 19 -205 524 473 ;
-C 113 ; WX 556 ; N q ; B 34 -205 536 473 ;
-C 114 ; WX 444 ; N r ; B 29 0 434 473 ;
-C 115 ; WX 389 ; N s ; B 25 -14 361 473 ;
-C 116 ; WX 333 ; N t ; B 20 -12 332 630 ;
-C 117 ; WX 556 ; N u ; B 16 -14 537 461 ;
-C 118 ; WX 500 ; N v ; B 21 -14 485 461 ;
-C 119 ; WX 722 ; N w ; B 23 -14 707 461 ;
-C 120 ; WX 500 ; N x ; B 12 0 484 461 ;
-C 121 ; WX 500 ; N y ; B 16 -205 480 461 ;
-C 122 ; WX 444 ; N z ; B 21 0 420 461 ;
-C 123 ; WX 394 ; N braceleft ; B 22 -175 340 698 ;
-C 124 ; WX 220 ; N bar ; B 66 -218 154 782 ;
-C 125 ; WX 394 ; N braceright ; B 54 -175 372 698 ;
-C 126 ; WX 520 ; N asciitilde ; B 29 173 491 333 ;
-C 161 ; WX 333 ; N exclamdown ; B 82 -203 252 501 ;
-C 162 ; WX 500 ; N cent ; B 53 -140 458 588 ;
-C 163 ; WX 500 ; N sterling ; B 21 -14 477 684 ;
-C 164 ; WX 167 ; N fraction ; B -168 -12 329 688 ;
-C 165 ; WX 500 ; N yen ; B -64 0 547 676 ;
-C 166 ; WX 500 ; N florin ; B 0 -155 498 706 ;
-C 167 ; WX 500 ; N section ; B 57 -132 443 691 ;
-C 168 ; WX 500 ; N currency ; B -26 61 526 613 ;
-C 169 ; WX 278 ; N quotesingle ; B 75 404 204 691 ;
-C 170 ; WX 500 ; N quotedblleft ; B 32 356 486 691 ;
-C 171 ; WX 500 ; N guillemotleft ; B 23 36 473 415 ;
-C 172 ; WX 333 ; N guilsinglleft ; B 51 36 305 415 ;
-C 173 ; WX 333 ; N guilsinglright ; B 28 36 282 415 ;
-C 174 ; WX 556 ; N fi ; B 14 0 536 691 ;
-C 175 ; WX 556 ; N fl ; B 14 0 536 691 ;
-C 177 ; WX 500 ; N endash ; B 0 181 500 271 ;
-C 178 ; WX 500 ; N dagger ; B 47 -134 453 691 ;
-C 179 ; WX 500 ; N daggerdbl ; B 45 -132 456 691 ;
-C 180 ; WX 250 ; N periodcentered ; B 41 248 210 417 ;
-C 182 ; WX 540 ; N paragraph ; B 0 -186 519 676 ;
-C 183 ; WX 350 ; N bullet ; B 35 198 315 478 ;
-C 184 ; WX 333 ; N quotesinglbase ; B 79 -180 263 155 ;
-C 185 ; WX 500 ; N quotedblbase ; B 14 -180 468 155 ;
-C 186 ; WX 500 ; N quotedblright ; B 14 356 468 691 ;
-C 187 ; WX 500 ; N guillemotright ; B 27 36 477 415 ;
-C 188 ; WX 1000 ; N ellipsis ; B 82 -13 917 156 ;
-C 189 ; WX 1000 ; N perthousand ; B 7 -29 995 706 ;
-C 191 ; WX 500 ; N questiondown ; B 55 -201 443 501 ;
-C 193 ; WX 333 ; N grave ; B 8 528 246 713 ;
-C 194 ; WX 333 ; N acute ; B 86 528 324 713 ;
-C 195 ; WX 333 ; N circumflex ; B -2 528 335 704 ;
-C 196 ; WX 333 ; N tilde ; B -16 547 349 674 ;
-C 197 ; WX 333 ; N macron ; B 1 565 331 637 ;
-C 198 ; WX 333 ; N breve ; B 15 528 318 691 ;
-C 199 ; WX 333 ; N dotaccent ; B 103 536 258 691 ;
-C 200 ; WX 333 ; N dieresis ; B -2 537 335 667 ;
-C 202 ; WX 333 ; N ring ; B 60 527 273 740 ;
-C 203 ; WX 333 ; N cedilla ; B 68 -218 294 0 ;
-C 205 ; WX 333 ; N hungarumlaut ; B -13 528 425 713 ;
-C 206 ; WX 333 ; N ogonek ; B 90 -193 319 24 ;
-C 207 ; WX 333 ; N caron ; B -2 528 335 704 ;
-C 208 ; WX 1000 ; N emdash ; B 0 181 1000 271 ;
-C 225 ; WX 1000 ; N AE ; B 4 0 951 676 ;
-C 227 ; WX 300 ; N ordfeminine ; B -1 397 301 688 ;
-C 232 ; WX 667 ; N Lslash ; B 19 0 638 676 ;
-C 233 ; WX 778 ; N Oslash ; B 35 -74 743 737 ;
-C 234 ; WX 1000 ; N OE ; B 22 -5 981 684 ;
-C 235 ; WX 330 ; N ordmasculine ; B 18 397 312 688 ;
-C 241 ; WX 722 ; N ae ; B 33 -14 693 473 ;
-C 245 ; WX 278 ; N dotlessi ; B 16 0 255 461 ;
-C 248 ; WX 278 ; N lslash ; B -22 0 303 676 ;
-C 249 ; WX 500 ; N oslash ; B 25 -92 476 549 ;
-C 250 ; WX 722 ; N oe ; B 22 -14 696 473 ;
-C 251 ; WX 556 ; N germandbls ; B 19 -12 517 691 ;
-C -1 ; WX 389 ; N Idieresis ; B 20 0 370 877 ;
-C -1 ; WX 444 ; N eacute ; B 25 -14 426 713 ;
-C -1 ; WX 500 ; N abreve ; B 25 -14 488 691 ;
-C -1 ; WX 556 ; N uhungarumlaut ; B 16 -14 557 713 ;
-C -1 ; WX 444 ; N ecaron ; B 25 -14 426 704 ;
-C -1 ; WX 722 ; N Ydieresis ; B 15 0 699 877 ;
-C -1 ; WX 570 ; N divide ; B 33 -31 537 537 ;
-C -1 ; WX 722 ; N Yacute ; B 15 0 699 923 ;
-C -1 ; WX 722 ; N Acircumflex ; B 9 0 689 914 ;
-C -1 ; WX 500 ; N aacute ; B 25 -14 488 713 ;
-C -1 ; WX 722 ; N Ucircumflex ; B 16 -19 701 914 ;
-C -1 ; WX 500 ; N yacute ; B 16 -205 480 713 ;
-C -1 ; WX 389 ; N scommaaccent ; B 25 -218 361 473 ;
-C -1 ; WX 444 ; N ecircumflex ; B 25 -14 426 704 ;
-C -1 ; WX 722 ; N Uring ; B 16 -19 701 935 ;
-C -1 ; WX 722 ; N Udieresis ; B 16 -19 701 877 ;
-C -1 ; WX 500 ; N aogonek ; B 25 -193 504 473 ;
-C -1 ; WX 722 ; N Uacute ; B 16 -19 701 923 ;
-C -1 ; WX 556 ; N uogonek ; B 16 -193 539 461 ;
-C -1 ; WX 667 ; N Edieresis ; B 16 0 641 877 ;
-C -1 ; WX 722 ; N Dcroat ; B 6 0 690 676 ;
-C -1 ; WX 250 ; N commaaccent ; B 47 -218 203 -50 ;
-C -1 ; WX 747 ; N copyright ; B 26 -19 721 691 ;
-C -1 ; WX 667 ; N Emacron ; B 16 0 641 847 ;
-C -1 ; WX 444 ; N ccaron ; B 25 -14 430 704 ;
-C -1 ; WX 500 ; N aring ; B 25 -14 488 740 ;
-C -1 ; WX 722 ; N Ncommaaccent ; B 16 -188 701 676 ;
-C -1 ; WX 278 ; N lacute ; B 16 0 297 923 ;
-C -1 ; WX 500 ; N agrave ; B 25 -14 488 713 ;
-C -1 ; WX 667 ; N Tcommaaccent ; B 31 -218 636 676 ;
-C -1 ; WX 722 ; N Cacute ; B 49 -19 687 923 ;
-C -1 ; WX 500 ; N atilde ; B 25 -14 488 674 ;
-C -1 ; WX 667 ; N Edotaccent ; B 16 0 641 901 ;
-C -1 ; WX 389 ; N scaron ; B 25 -14 363 704 ;
-C -1 ; WX 389 ; N scedilla ; B 25 -218 361 473 ;
-C -1 ; WX 278 ; N iacute ; B 16 0 289 713 ;
-C -1 ; WX 494 ; N lozenge ; B 10 0 484 745 ;
-C -1 ; WX 722 ; N Rcaron ; B 26 0 715 914 ;
-C -1 ; WX 778 ; N Gcommaaccent ; B 37 -218 755 691 ;
-C -1 ; WX 556 ; N ucircumflex ; B 16 -14 537 704 ;
-C -1 ; WX 500 ; N acircumflex ; B 25 -14 488 704 ;
-C -1 ; WX 722 ; N Amacron ; B 9 0 689 847 ;
-C -1 ; WX 444 ; N rcaron ; B 29 0 434 704 ;
-C -1 ; WX 444 ; N ccedilla ; B 25 -218 430 473 ;
-C -1 ; WX 667 ; N Zdotaccent ; B 28 0 634 901 ;
-C -1 ; WX 611 ; N Thorn ; B 16 0 600 676 ;
-C -1 ; WX 778 ; N Omacron ; B 35 -19 743 847 ;
-C -1 ; WX 722 ; N Racute ; B 26 0 715 923 ;
-C -1 ; WX 556 ; N Sacute ; B 35 -19 513 923 ;
-C -1 ; WX 672 ; N dcaron ; B 25 -14 681 682 ;
-C -1 ; WX 722 ; N Umacron ; B 16 -19 701 847 ;
-C -1 ; WX 556 ; N uring ; B 16 -14 537 740 ;
-C -1 ; WX 300 ; N threesuperior ; B 3 268 297 688 ;
-C -1 ; WX 778 ; N Ograve ; B 35 -19 743 923 ;
-C -1 ; WX 722 ; N Agrave ; B 9 0 689 923 ;
-C -1 ; WX 722 ; N Abreve ; B 9 0 689 901 ;
-C -1 ; WX 570 ; N multiply ; B 48 16 522 490 ;
-C -1 ; WX 556 ; N uacute ; B 16 -14 537 713 ;
-C -1 ; WX 667 ; N Tcaron ; B 31 0 636 914 ;
-C -1 ; WX 494 ; N partialdiff ; B 11 -21 494 750 ;
-C -1 ; WX 500 ; N ydieresis ; B 16 -205 480 667 ;
-C -1 ; WX 722 ; N Nacute ; B 16 -18 701 923 ;
-C -1 ; WX 278 ; N icircumflex ; B -37 0 300 704 ;
-C -1 ; WX 667 ; N Ecircumflex ; B 16 0 641 914 ;
-C -1 ; WX 500 ; N adieresis ; B 25 -14 488 667 ;
-C -1 ; WX 444 ; N edieresis ; B 25 -14 426 667 ;
-C -1 ; WX 444 ; N cacute ; B 25 -14 430 713 ;
-C -1 ; WX 556 ; N nacute ; B 21 0 539 713 ;
-C -1 ; WX 556 ; N umacron ; B 16 -14 537 637 ;
-C -1 ; WX 722 ; N Ncaron ; B 16 -18 701 914 ;
-C -1 ; WX 389 ; N Iacute ; B 20 0 370 923 ;
-C -1 ; WX 570 ; N plusminus ; B 33 0 537 506 ;
-C -1 ; WX 220 ; N brokenbar ; B 66 -143 154 707 ;
-C -1 ; WX 747 ; N registered ; B 26 -19 721 691 ;
-C -1 ; WX 778 ; N Gbreve ; B 37 -19 755 901 ;
-C -1 ; WX 389 ; N Idotaccent ; B 20 0 370 901 ;
-C -1 ; WX 600 ; N summation ; B 14 -10 585 706 ;
-C -1 ; WX 667 ; N Egrave ; B 16 0 641 923 ;
-C -1 ; WX 444 ; N racute ; B 29 0 434 713 ;
-C -1 ; WX 500 ; N omacron ; B 25 -14 476 637 ;
-C -1 ; WX 667 ; N Zacute ; B 28 0 634 923 ;
-C -1 ; WX 667 ; N Zcaron ; B 28 0 634 914 ;
-C -1 ; WX 549 ; N greaterequal ; B 26 0 523 704 ;
-C -1 ; WX 722 ; N Eth ; B 6 0 690 676 ;
-C -1 ; WX 722 ; N Ccedilla ; B 49 -218 687 691 ;
-C -1 ; WX 278 ; N lcommaaccent ; B 16 -218 255 676 ;
-C -1 ; WX 416 ; N tcaron ; B 20 -12 425 815 ;
-C -1 ; WX 444 ; N eogonek ; B 25 -193 426 473 ;
-C -1 ; WX 722 ; N Uogonek ; B 16 -193 701 676 ;
-C -1 ; WX 722 ; N Aacute ; B 9 0 689 923 ;
-C -1 ; WX 722 ; N Adieresis ; B 9 0 689 877 ;
-C -1 ; WX 444 ; N egrave ; B 25 -14 426 713 ;
-C -1 ; WX 444 ; N zacute ; B 21 0 420 713 ;
-C -1 ; WX 278 ; N iogonek ; B 16 -193 274 691 ;
-C -1 ; WX 778 ; N Oacute ; B 35 -19 743 923 ;
-C -1 ; WX 500 ; N oacute ; B 25 -14 476 713 ;
-C -1 ; WX 500 ; N amacron ; B 25 -14 488 637 ;
-C -1 ; WX 389 ; N sacute ; B 25 -14 361 713 ;
-C -1 ; WX 278 ; N idieresis ; B -37 0 300 667 ;
-C -1 ; WX 778 ; N Ocircumflex ; B 35 -19 743 914 ;
-C -1 ; WX 722 ; N Ugrave ; B 16 -19 701 923 ;
-C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
-C -1 ; WX 556 ; N thorn ; B 19 -205 524 676 ;
-C -1 ; WX 300 ; N twosuperior ; B 0 275 300 688 ;
-C -1 ; WX 778 ; N Odieresis ; B 35 -19 743 877 ;
-C -1 ; WX 556 ; N mu ; B 33 -206 536 461 ;
-C -1 ; WX 278 ; N igrave ; B -27 0 255 713 ;
-C -1 ; WX 500 ; N ohungarumlaut ; B 25 -14 529 713 ;
-C -1 ; WX 667 ; N Eogonek ; B 16 -193 644 676 ;
-C -1 ; WX 556 ; N dcroat ; B 25 -14 534 676 ;
-C -1 ; WX 750 ; N threequarters ; B 23 -12 733 688 ;
-C -1 ; WX 556 ; N Scedilla ; B 35 -218 513 692 ;
-C -1 ; WX 394 ; N lcaron ; B 16 0 412 682 ;
-C -1 ; WX 778 ; N Kcommaaccent ; B 30 -218 769 676 ;
-C -1 ; WX 667 ; N Lacute ; B 19 0 638 923 ;
-C -1 ; WX 1000 ; N trademark ; B 24 271 977 676 ;
-C -1 ; WX 444 ; N edotaccent ; B 25 -14 426 691 ;
-C -1 ; WX 389 ; N Igrave ; B 20 0 370 923 ;
-C -1 ; WX 389 ; N Imacron ; B 20 0 370 847 ;
-C -1 ; WX 667 ; N Lcaron ; B 19 0 652 682 ;
-C -1 ; WX 750 ; N onehalf ; B -7 -12 775 688 ;
-C -1 ; WX 549 ; N lessequal ; B 29 0 526 704 ;
-C -1 ; WX 500 ; N ocircumflex ; B 25 -14 476 704 ;
-C -1 ; WX 556 ; N ntilde ; B 21 0 539 674 ;
-C -1 ; WX 722 ; N Uhungarumlaut ; B 16 -19 701 923 ;
-C -1 ; WX 667 ; N Eacute ; B 16 0 641 923 ;
-C -1 ; WX 444 ; N emacron ; B 25 -14 426 637 ;
-C -1 ; WX 500 ; N gbreve ; B 28 -206 483 691 ;
-C -1 ; WX 750 ; N onequarter ; B 28 -12 743 688 ;
-C -1 ; WX 556 ; N Scaron ; B 35 -19 513 914 ;
-C -1 ; WX 556 ; N Scommaaccent ; B 35 -218 513 692 ;
-C -1 ; WX 778 ; N Ohungarumlaut ; B 35 -19 743 923 ;
-C -1 ; WX 400 ; N degree ; B 57 402 343 688 ;
-C -1 ; WX 500 ; N ograve ; B 25 -14 476 713 ;
-C -1 ; WX 722 ; N Ccaron ; B 49 -19 687 914 ;
-C -1 ; WX 556 ; N ugrave ; B 16 -14 537 713 ;
-C -1 ; WX 549 ; N radical ; B 10 -46 512 850 ;
-C -1 ; WX 722 ; N Dcaron ; B 14 0 690 914 ;
-C -1 ; WX 444 ; N rcommaaccent ; B 29 -218 434 473 ;
-C -1 ; WX 722 ; N Ntilde ; B 16 -18 701 884 ;
-C -1 ; WX 500 ; N otilde ; B 25 -14 476 674 ;
-C -1 ; WX 722 ; N Rcommaaccent ; B 26 -218 715 676 ;
-C -1 ; WX 667 ; N Lcommaaccent ; B 19 -218 638 676 ;
-C -1 ; WX 722 ; N Atilde ; B 9 0 689 884 ;
-C -1 ; WX 722 ; N Aogonek ; B 9 -193 699 690 ;
-C -1 ; WX 722 ; N Aring ; B 9 0 689 935 ;
-C -1 ; WX 778 ; N Otilde ; B 35 -19 743 884 ;
-C -1 ; WX 444 ; N zdotaccent ; B 21 0 420 691 ;
-C -1 ; WX 667 ; N Ecaron ; B 16 0 641 914 ;
-C -1 ; WX 389 ; N Iogonek ; B 20 -193 370 676 ;
-C -1 ; WX 556 ; N kcommaaccent ; B 22 -218 543 676 ;
-C -1 ; WX 570 ; N minus ; B 33 209 537 297 ;
-C -1 ; WX 389 ; N Icircumflex ; B 20 0 370 914 ;
-C -1 ; WX 556 ; N ncaron ; B 21 0 539 704 ;
-C -1 ; WX 333 ; N tcommaaccent ; B 20 -218 332 630 ;
-C -1 ; WX 570 ; N logicalnot ; B 33 108 537 399 ;
-C -1 ; WX 500 ; N odieresis ; B 25 -14 476 667 ;
-C -1 ; WX 556 ; N udieresis ; B 16 -14 537 667 ;
-C -1 ; WX 549 ; N notequal ; B 15 -49 540 570 ;
-C -1 ; WX 500 ; N gcommaaccent ; B 28 -206 483 829 ;
-C -1 ; WX 500 ; N eth ; B 25 -14 476 691 ;
-C -1 ; WX 444 ; N zcaron ; B 21 0 420 704 ;
-C -1 ; WX 556 ; N ncommaaccent ; B 21 -218 539 473 ;
-C -1 ; WX 300 ; N onesuperior ; B 28 275 273 688 ;
-C -1 ; WX 278 ; N imacron ; B -8 0 272 637 ;
-C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ;
-EndCharMetrics
-StartKernData
-StartKernPairs 2242
-KPX A C -55
-KPX A Cacute -55
-KPX A Ccaron -55
-KPX A Ccedilla -55
-KPX A G -55
-KPX A Gbreve -55
-KPX A Gcommaaccent -55
-KPX A O -45
-KPX A Oacute -45
-KPX A Ocircumflex -45
-KPX A Odieresis -45
-KPX A Ograve -45
-KPX A Ohungarumlaut -45
-KPX A Omacron -45
-KPX A Oslash -45
-KPX A Otilde -45
-KPX A Q -45
-KPX A T -95
-KPX A Tcaron -95
-KPX A Tcommaaccent -95
-KPX A U -50
-KPX A Uacute -50
-KPX A Ucircumflex -50
-KPX A Udieresis -50
-KPX A Ugrave -50
-KPX A Uhungarumlaut -50
-KPX A Umacron -50
-KPX A Uogonek -50
-KPX A Uring -50
-KPX A V -145
-KPX A W -130
-KPX A Y -100
-KPX A Yacute -100
-KPX A Ydieresis -100
-KPX A p -25
-KPX A quoteright -74
-KPX A u -50
-KPX A uacute -50
-KPX A ucircumflex -50
-KPX A udieresis -50
-KPX A ugrave -50
-KPX A uhungarumlaut -50
-KPX A umacron -50
-KPX A uogonek -50
-KPX A uring -50
-KPX A v -100
-KPX A w -90
-KPX A y -74
-KPX A yacute -74
-KPX A ydieresis -74
-KPX Aacute C -55
-KPX Aacute Cacute -55
-KPX Aacute Ccaron -55
-KPX Aacute Ccedilla -55
-KPX Aacute G -55
-KPX Aacute Gbreve -55
-KPX Aacute Gcommaaccent -55
-KPX Aacute O -45
-KPX Aacute Oacute -45
-KPX Aacute Ocircumflex -45
-KPX Aacute Odieresis -45
-KPX Aacute Ograve -45
-KPX Aacute Ohungarumlaut -45
-KPX Aacute Omacron -45
-KPX Aacute Oslash -45
-KPX Aacute Otilde -45
-KPX Aacute Q -45
-KPX Aacute T -95
-KPX Aacute Tcaron -95
-KPX Aacute Tcommaaccent -95
-KPX Aacute U -50
-KPX Aacute Uacute -50
-KPX Aacute Ucircumflex -50
-KPX Aacute Udieresis -50
-KPX Aacute Ugrave -50
-KPX Aacute Uhungarumlaut -50
-KPX Aacute Umacron -50
-KPX Aacute Uogonek -50
-KPX Aacute Uring -50
-KPX Aacute V -145
-KPX Aacute W -130
-KPX Aacute Y -100
-KPX Aacute Yacute -100
-KPX Aacute Ydieresis -100
-KPX Aacute p -25
-KPX Aacute quoteright -74
-KPX Aacute u -50
-KPX Aacute uacute -50
-KPX Aacute ucircumflex -50
-KPX Aacute udieresis -50
-KPX Aacute ugrave -50
-KPX Aacute uhungarumlaut -50
-KPX Aacute umacron -50
-KPX Aacute uogonek -50
-KPX Aacute uring -50
-KPX Aacute v -100
-KPX Aacute w -90
-KPX Aacute y -74
-KPX Aacute yacute -74
-KPX Aacute ydieresis -74
-KPX Abreve C -55
-KPX Abreve Cacute -55
-KPX Abreve Ccaron -55
-KPX Abreve Ccedilla -55
-KPX Abreve G -55
-KPX Abreve Gbreve -55
-KPX Abreve Gcommaaccent -55
-KPX Abreve O -45
-KPX Abreve Oacute -45
-KPX Abreve Ocircumflex -45
-KPX Abreve Odieresis -45
-KPX Abreve Ograve -45
-KPX Abreve Ohungarumlaut -45
-KPX Abreve Omacron -45
-KPX Abreve Oslash -45
-KPX Abreve Otilde -45
-KPX Abreve Q -45
-KPX Abreve T -95
-KPX Abreve Tcaron -95
-KPX Abreve Tcommaaccent -95
-KPX Abreve U -50
-KPX Abreve Uacute -50
-KPX Abreve Ucircumflex -50
-KPX Abreve Udieresis -50
-KPX Abreve Ugrave -50
-KPX Abreve Uhungarumlaut -50
-KPX Abreve Umacron -50
-KPX Abreve Uogonek -50
-KPX Abreve Uring -50
-KPX Abreve V -145
-KPX Abreve W -130
-KPX Abreve Y -100
-KPX Abreve Yacute -100
-KPX Abreve Ydieresis -100
-KPX Abreve p -25
-KPX Abreve quoteright -74
-KPX Abreve u -50
-KPX Abreve uacute -50
-KPX Abreve ucircumflex -50
-KPX Abreve udieresis -50
-KPX Abreve ugrave -50
-KPX Abreve uhungarumlaut -50
-KPX Abreve umacron -50
-KPX Abreve uogonek -50
-KPX Abreve uring -50
-KPX Abreve v -100
-KPX Abreve w -90
-KPX Abreve y -74
-KPX Abreve yacute -74
-KPX Abreve ydieresis -74
-KPX Acircumflex C -55
-KPX Acircumflex Cacute -55
-KPX Acircumflex Ccaron -55
-KPX Acircumflex Ccedilla -55
-KPX Acircumflex G -55
-KPX Acircumflex Gbreve -55
-KPX Acircumflex Gcommaaccent -55
-KPX Acircumflex O -45
-KPX Acircumflex Oacute -45
-KPX Acircumflex Ocircumflex -45
-KPX Acircumflex Odieresis -45
-KPX Acircumflex Ograve -45
-KPX Acircumflex Ohungarumlaut -45
-KPX Acircumflex Omacron -45
-KPX Acircumflex Oslash -45
-KPX Acircumflex Otilde -45
-KPX Acircumflex Q -45
-KPX Acircumflex T -95
-KPX Acircumflex Tcaron -95
-KPX Acircumflex Tcommaaccent -95
-KPX Acircumflex U -50
-KPX Acircumflex Uacute -50
-KPX Acircumflex Ucircumflex -50
-KPX Acircumflex Udieresis -50
-KPX Acircumflex Ugrave -50
-KPX Acircumflex Uhungarumlaut -50
-KPX Acircumflex Umacron -50
-KPX Acircumflex Uogonek -50
-KPX Acircumflex Uring -50
-KPX Acircumflex V -145
-KPX Acircumflex W -130
-KPX Acircumflex Y -100
-KPX Acircumflex Yacute -100
-KPX Acircumflex Ydieresis -100
-KPX Acircumflex p -25
-KPX Acircumflex quoteright -74
-KPX Acircumflex u -50
-KPX Acircumflex uacute -50
-KPX Acircumflex ucircumflex -50
-KPX Acircumflex udieresis -50
-KPX Acircumflex ugrave -50
-KPX Acircumflex uhungarumlaut -50
-KPX Acircumflex umacron -50
-KPX Acircumflex uogonek -50
-KPX Acircumflex uring -50
-KPX Acircumflex v -100
-KPX Acircumflex w -90
-KPX Acircumflex y -74
-KPX Acircumflex yacute -74
-KPX Acircumflex ydieresis -74
-KPX Adieresis C -55
-KPX Adieresis Cacute -55
-KPX Adieresis Ccaron -55
-KPX Adieresis Ccedilla -55
-KPX Adieresis G -55
-KPX Adieresis Gbreve -55
-KPX Adieresis Gcommaaccent -55
-KPX Adieresis O -45
-KPX Adieresis Oacute -45
-KPX Adieresis Ocircumflex -45
-KPX Adieresis Odieresis -45
-KPX Adieresis Ograve -45
-KPX Adieresis Ohungarumlaut -45
-KPX Adieresis Omacron -45
-KPX Adieresis Oslash -45
-KPX Adieresis Otilde -45
-KPX Adieresis Q -45
-KPX Adieresis T -95
-KPX Adieresis Tcaron -95
-KPX Adieresis Tcommaaccent -95
-KPX Adieresis U -50
-KPX Adieresis Uacute -50
-KPX Adieresis Ucircumflex -50
-KPX Adieresis Udieresis -50
-KPX Adieresis Ugrave -50
-KPX Adieresis Uhungarumlaut -50
-KPX Adieresis Umacron -50
-KPX Adieresis Uogonek -50
-KPX Adieresis Uring -50
-KPX Adieresis V -145
-KPX Adieresis W -130
-KPX Adieresis Y -100
-KPX Adieresis Yacute -100
-KPX Adieresis Ydieresis -100
-KPX Adieresis p -25
-KPX Adieresis quoteright -74
-KPX Adieresis u -50
-KPX Adieresis uacute -50
-KPX Adieresis ucircumflex -50
-KPX Adieresis udieresis -50
-KPX Adieresis ugrave -50
-KPX Adieresis uhungarumlaut -50
-KPX Adieresis umacron -50
-KPX Adieresis uogonek -50
-KPX Adieresis uring -50
-KPX Adieresis v -100
-KPX Adieresis w -90
-KPX Adieresis y -74
-KPX Adieresis yacute -74
-KPX Adieresis ydieresis -74
-KPX Agrave C -55
-KPX Agrave Cacute -55
-KPX Agrave Ccaron -55
-KPX Agrave Ccedilla -55
-KPX Agrave G -55
-KPX Agrave Gbreve -55
-KPX Agrave Gcommaaccent -55
-KPX Agrave O -45
-KPX Agrave Oacute -45
-KPX Agrave Ocircumflex -45
-KPX Agrave Odieresis -45
-KPX Agrave Ograve -45
-KPX Agrave Ohungarumlaut -45
-KPX Agrave Omacron -45
-KPX Agrave Oslash -45
-KPX Agrave Otilde -45
-KPX Agrave Q -45
-KPX Agrave T -95
-KPX Agrave Tcaron -95
-KPX Agrave Tcommaaccent -95
-KPX Agrave U -50
-KPX Agrave Uacute -50
-KPX Agrave Ucircumflex -50
-KPX Agrave Udieresis -50
-KPX Agrave Ugrave -50
-KPX Agrave Uhungarumlaut -50
-KPX Agrave Umacron -50
-KPX Agrave Uogonek -50
-KPX Agrave Uring -50
-KPX Agrave V -145
-KPX Agrave W -130
-KPX Agrave Y -100
-KPX Agrave Yacute -100
-KPX Agrave Ydieresis -100
-KPX Agrave p -25
-KPX Agrave quoteright -74
-KPX Agrave u -50
-KPX Agrave uacute -50
-KPX Agrave ucircumflex -50
-KPX Agrave udieresis -50
-KPX Agrave ugrave -50
-KPX Agrave uhungarumlaut -50
-KPX Agrave umacron -50
-KPX Agrave uogonek -50
-KPX Agrave uring -50
-KPX Agrave v -100
-KPX Agrave w -90
-KPX Agrave y -74
-KPX Agrave yacute -74
-KPX Agrave ydieresis -74
-KPX Amacron C -55
-KPX Amacron Cacute -55
-KPX Amacron Ccaron -55
-KPX Amacron Ccedilla -55
-KPX Amacron G -55
-KPX Amacron Gbreve -55
-KPX Amacron Gcommaaccent -55
-KPX Amacron O -45
-KPX Amacron Oacute -45
-KPX Amacron Ocircumflex -45
-KPX Amacron Odieresis -45
-KPX Amacron Ograve -45
-KPX Amacron Ohungarumlaut -45
-KPX Amacron Omacron -45
-KPX Amacron Oslash -45
-KPX Amacron Otilde -45
-KPX Amacron Q -45
-KPX Amacron T -95
-KPX Amacron Tcaron -95
-KPX Amacron Tcommaaccent -95
-KPX Amacron U -50
-KPX Amacron Uacute -50
-KPX Amacron Ucircumflex -50
-KPX Amacron Udieresis -50
-KPX Amacron Ugrave -50
-KPX Amacron Uhungarumlaut -50
-KPX Amacron Umacron -50
-KPX Amacron Uogonek -50
-KPX Amacron Uring -50
-KPX Amacron V -145
-KPX Amacron W -130
-KPX Amacron Y -100
-KPX Amacron Yacute -100
-KPX Amacron Ydieresis -100
-KPX Amacron p -25
-KPX Amacron quoteright -74
-KPX Amacron u -50
-KPX Amacron uacute -50
-KPX Amacron ucircumflex -50
-KPX Amacron udieresis -50
-KPX Amacron ugrave -50
-KPX Amacron uhungarumlaut -50
-KPX Amacron umacron -50
-KPX Amacron uogonek -50
-KPX Amacron uring -50
-KPX Amacron v -100
-KPX Amacron w -90
-KPX Amacron y -74
-KPX Amacron yacute -74
-KPX Amacron ydieresis -74
-KPX Aogonek C -55
-KPX Aogonek Cacute -55
-KPX Aogonek Ccaron -55
-KPX Aogonek Ccedilla -55
-KPX Aogonek G -55
-KPX Aogonek Gbreve -55
-KPX Aogonek Gcommaaccent -55
-KPX Aogonek O -45
-KPX Aogonek Oacute -45
-KPX Aogonek Ocircumflex -45
-KPX Aogonek Odieresis -45
-KPX Aogonek Ograve -45
-KPX Aogonek Ohungarumlaut -45
-KPX Aogonek Omacron -45
-KPX Aogonek Oslash -45
-KPX Aogonek Otilde -45
-KPX Aogonek Q -45
-KPX Aogonek T -95
-KPX Aogonek Tcaron -95
-KPX Aogonek Tcommaaccent -95
-KPX Aogonek U -50
-KPX Aogonek Uacute -50
-KPX Aogonek Ucircumflex -50
-KPX Aogonek Udieresis -50
-KPX Aogonek Ugrave -50
-KPX Aogonek Uhungarumlaut -50
-KPX Aogonek Umacron -50
-KPX Aogonek Uogonek -50
-KPX Aogonek Uring -50
-KPX Aogonek V -145
-KPX Aogonek W -130
-KPX Aogonek Y -100
-KPX Aogonek Yacute -100
-KPX Aogonek Ydieresis -100
-KPX Aogonek p -25
-KPX Aogonek quoteright -74
-KPX Aogonek u -50
-KPX Aogonek uacute -50
-KPX Aogonek ucircumflex -50
-KPX Aogonek udieresis -50
-KPX Aogonek ugrave -50
-KPX Aogonek uhungarumlaut -50
-KPX Aogonek umacron -50
-KPX Aogonek uogonek -50
-KPX Aogonek uring -50
-KPX Aogonek v -100
-KPX Aogonek w -90
-KPX Aogonek y -34
-KPX Aogonek yacute -34
-KPX Aogonek ydieresis -34
-KPX Aring C -55
-KPX Aring Cacute -55
-KPX Aring Ccaron -55
-KPX Aring Ccedilla -55
-KPX Aring G -55
-KPX Aring Gbreve -55
-KPX Aring Gcommaaccent -55
-KPX Aring O -45
-KPX Aring Oacute -45
-KPX Aring Ocircumflex -45
-KPX Aring Odieresis -45
-KPX Aring Ograve -45
-KPX Aring Ohungarumlaut -45
-KPX Aring Omacron -45
-KPX Aring Oslash -45
-KPX Aring Otilde -45
-KPX Aring Q -45
-KPX Aring T -95
-KPX Aring Tcaron -95
-KPX Aring Tcommaaccent -95
-KPX Aring U -50
-KPX Aring Uacute -50
-KPX Aring Ucircumflex -50
-KPX Aring Udieresis -50
-KPX Aring Ugrave -50
-KPX Aring Uhungarumlaut -50
-KPX Aring Umacron -50
-KPX Aring Uogonek -50
-KPX Aring Uring -50
-KPX Aring V -145
-KPX Aring W -130
-KPX Aring Y -100
-KPX Aring Yacute -100
-KPX Aring Ydieresis -100
-KPX Aring p -25
-KPX Aring quoteright -74
-KPX Aring u -50
-KPX Aring uacute -50
-KPX Aring ucircumflex -50
-KPX Aring udieresis -50
-KPX Aring ugrave -50
-KPX Aring uhungarumlaut -50
-KPX Aring umacron -50
-KPX Aring uogonek -50
-KPX Aring uring -50
-KPX Aring v -100
-KPX Aring w -90
-KPX Aring y -74
-KPX Aring yacute -74
-KPX Aring ydieresis -74
-KPX Atilde C -55
-KPX Atilde Cacute -55
-KPX Atilde Ccaron -55
-KPX Atilde Ccedilla -55
-KPX Atilde G -55
-KPX Atilde Gbreve -55
-KPX Atilde Gcommaaccent -55
-KPX Atilde O -45
-KPX Atilde Oacute -45
-KPX Atilde Ocircumflex -45
-KPX Atilde Odieresis -45
-KPX Atilde Ograve -45
-KPX Atilde Ohungarumlaut -45
-KPX Atilde Omacron -45
-KPX Atilde Oslash -45
-KPX Atilde Otilde -45
-KPX Atilde Q -45
-KPX Atilde T -95
-KPX Atilde Tcaron -95
-KPX Atilde Tcommaaccent -95
-KPX Atilde U -50
-KPX Atilde Uacute -50
-KPX Atilde Ucircumflex -50
-KPX Atilde Udieresis -50
-KPX Atilde Ugrave -50
-KPX Atilde Uhungarumlaut -50
-KPX Atilde Umacron -50
-KPX Atilde Uogonek -50
-KPX Atilde Uring -50
-KPX Atilde V -145
-KPX Atilde W -130
-KPX Atilde Y -100
-KPX Atilde Yacute -100
-KPX Atilde Ydieresis -100
-KPX Atilde p -25
-KPX Atilde quoteright -74
-KPX Atilde u -50
-KPX Atilde uacute -50
-KPX Atilde ucircumflex -50
-KPX Atilde udieresis -50
-KPX Atilde ugrave -50
-KPX Atilde uhungarumlaut -50
-KPX Atilde umacron -50
-KPX Atilde uogonek -50
-KPX Atilde uring -50
-KPX Atilde v -100
-KPX Atilde w -90
-KPX Atilde y -74
-KPX Atilde yacute -74
-KPX Atilde ydieresis -74
-KPX B A -30
-KPX B Aacute -30
-KPX B Abreve -30
-KPX B Acircumflex -30
-KPX B Adieresis -30
-KPX B Agrave -30
-KPX B Amacron -30
-KPX B Aogonek -30
-KPX B Aring -30
-KPX B Atilde -30
-KPX B U -10
-KPX B Uacute -10
-KPX B Ucircumflex -10
-KPX B Udieresis -10
-KPX B Ugrave -10
-KPX B Uhungarumlaut -10
-KPX B Umacron -10
-KPX B Uogonek -10
-KPX B Uring -10
-KPX D A -35
-KPX D Aacute -35
-KPX D Abreve -35
-KPX D Acircumflex -35
-KPX D Adieresis -35
-KPX D Agrave -35
-KPX D Amacron -35
-KPX D Aogonek -35
-KPX D Aring -35
-KPX D Atilde -35
-KPX D V -40
-KPX D W -40
-KPX D Y -40
-KPX D Yacute -40
-KPX D Ydieresis -40
-KPX D period -20
-KPX Dcaron A -35
-KPX Dcaron Aacute -35
-KPX Dcaron Abreve -35
-KPX Dcaron Acircumflex -35
-KPX Dcaron Adieresis -35
-KPX Dcaron Agrave -35
-KPX Dcaron Amacron -35
-KPX Dcaron Aogonek -35
-KPX Dcaron Aring -35
-KPX Dcaron Atilde -35
-KPX Dcaron V -40
-KPX Dcaron W -40
-KPX Dcaron Y -40
-KPX Dcaron Yacute -40
-KPX Dcaron Ydieresis -40
-KPX Dcaron period -20
-KPX Dcroat A -35
-KPX Dcroat Aacute -35
-KPX Dcroat Abreve -35
-KPX Dcroat Acircumflex -35
-KPX Dcroat Adieresis -35
-KPX Dcroat Agrave -35
-KPX Dcroat Amacron -35
-KPX Dcroat Aogonek -35
-KPX Dcroat Aring -35
-KPX Dcroat Atilde -35
-KPX Dcroat V -40
-KPX Dcroat W -40
-KPX Dcroat Y -40
-KPX Dcroat Yacute -40
-KPX Dcroat Ydieresis -40
-KPX Dcroat period -20
-KPX F A -90
-KPX F Aacute -90
-KPX F Abreve -90
-KPX F Acircumflex -90
-KPX F Adieresis -90
-KPX F Agrave -90
-KPX F Amacron -90
-KPX F Aogonek -90
-KPX F Aring -90
-KPX F Atilde -90
-KPX F a -25
-KPX F aacute -25
-KPX F abreve -25
-KPX F acircumflex -25
-KPX F adieresis -25
-KPX F agrave -25
-KPX F amacron -25
-KPX F aogonek -25
-KPX F aring -25
-KPX F atilde -25
-KPX F comma -92
-KPX F e -25
-KPX F eacute -25
-KPX F ecaron -25
-KPX F ecircumflex -25
-KPX F edieresis -25
-KPX F edotaccent -25
-KPX F egrave -25
-KPX F emacron -25
-KPX F eogonek -25
-KPX F o -25
-KPX F oacute -25
-KPX F ocircumflex -25
-KPX F odieresis -25
-KPX F ograve -25
-KPX F ohungarumlaut -25
-KPX F omacron -25
-KPX F oslash -25
-KPX F otilde -25
-KPX F period -110
-KPX J A -30
-KPX J Aacute -30
-KPX J Abreve -30
-KPX J Acircumflex -30
-KPX J Adieresis -30
-KPX J Agrave -30
-KPX J Amacron -30
-KPX J Aogonek -30
-KPX J Aring -30
-KPX J Atilde -30
-KPX J a -15
-KPX J aacute -15
-KPX J abreve -15
-KPX J acircumflex -15
-KPX J adieresis -15
-KPX J agrave -15
-KPX J amacron -15
-KPX J aogonek -15
-KPX J aring -15
-KPX J atilde -15
-KPX J e -15
-KPX J eacute -15
-KPX J ecaron -15
-KPX J ecircumflex -15
-KPX J edieresis -15
-KPX J edotaccent -15
-KPX J egrave -15
-KPX J emacron -15
-KPX J eogonek -15
-KPX J o -15
-KPX J oacute -15
-KPX J ocircumflex -15
-KPX J odieresis -15
-KPX J ograve -15
-KPX J ohungarumlaut -15
-KPX J omacron -15
-KPX J oslash -15
-KPX J otilde -15
-KPX J period -20
-KPX J u -15
-KPX J uacute -15
-KPX J ucircumflex -15
-KPX J udieresis -15
-KPX J ugrave -15
-KPX J uhungarumlaut -15
-KPX J umacron -15
-KPX J uogonek -15
-KPX J uring -15
-KPX K O -30
-KPX K Oacute -30
-KPX K Ocircumflex -30
-KPX K Odieresis -30
-KPX K Ograve -30
-KPX K Ohungarumlaut -30
-KPX K Omacron -30
-KPX K Oslash -30
-KPX K Otilde -30
-KPX K e -25
-KPX K eacute -25
-KPX K ecaron -25
-KPX K ecircumflex -25
-KPX K edieresis -25
-KPX K edotaccent -25
-KPX K egrave -25
-KPX K emacron -25
-KPX K eogonek -25
-KPX K o -25
-KPX K oacute -25
-KPX K ocircumflex -25
-KPX K odieresis -25
-KPX K ograve -25
-KPX K ohungarumlaut -25
-KPX K omacron -25
-KPX K oslash -25
-KPX K otilde -25
-KPX K u -15
-KPX K uacute -15
-KPX K ucircumflex -15
-KPX K udieresis -15
-KPX K ugrave -15
-KPX K uhungarumlaut -15
-KPX K umacron -15
-KPX K uogonek -15
-KPX K uring -15
-KPX K y -45
-KPX K yacute -45
-KPX K ydieresis -45
-KPX Kcommaaccent O -30
-KPX Kcommaaccent Oacute -30
-KPX Kcommaaccent Ocircumflex -30
-KPX Kcommaaccent Odieresis -30
-KPX Kcommaaccent Ograve -30
-KPX Kcommaaccent Ohungarumlaut -30
-KPX Kcommaaccent Omacron -30
-KPX Kcommaaccent Oslash -30
-KPX Kcommaaccent Otilde -30
-KPX Kcommaaccent e -25
-KPX Kcommaaccent eacute -25
-KPX Kcommaaccent ecaron -25
-KPX Kcommaaccent ecircumflex -25
-KPX Kcommaaccent edieresis -25
-KPX Kcommaaccent edotaccent -25
-KPX Kcommaaccent egrave -25
-KPX Kcommaaccent emacron -25
-KPX Kcommaaccent eogonek -25
-KPX Kcommaaccent o -25
-KPX Kcommaaccent oacute -25
-KPX Kcommaaccent ocircumflex -25
-KPX Kcommaaccent odieresis -25
-KPX Kcommaaccent ograve -25
-KPX Kcommaaccent ohungarumlaut -25
-KPX Kcommaaccent omacron -25
-KPX Kcommaaccent oslash -25
-KPX Kcommaaccent otilde -25
-KPX Kcommaaccent u -15
-KPX Kcommaaccent uacute -15
-KPX Kcommaaccent ucircumflex -15
-KPX Kcommaaccent udieresis -15
-KPX Kcommaaccent ugrave -15
-KPX Kcommaaccent uhungarumlaut -15
-KPX Kcommaaccent umacron -15
-KPX Kcommaaccent uogonek -15
-KPX Kcommaaccent uring -15
-KPX Kcommaaccent y -45
-KPX Kcommaaccent yacute -45
-KPX Kcommaaccent ydieresis -45
-KPX L T -92
-KPX L Tcaron -92
-KPX L Tcommaaccent -92
-KPX L V -92
-KPX L W -92
-KPX L Y -92
-KPX L Yacute -92
-KPX L Ydieresis -92
-KPX L quotedblright -20
-KPX L quoteright -110
-KPX L y -55
-KPX L yacute -55
-KPX L ydieresis -55
-KPX Lacute T -92
-KPX Lacute Tcaron -92
-KPX Lacute Tcommaaccent -92
-KPX Lacute V -92
-KPX Lacute W -92
-KPX Lacute Y -92
-KPX Lacute Yacute -92
-KPX Lacute Ydieresis -92
-KPX Lacute quotedblright -20
-KPX Lacute quoteright -110
-KPX Lacute y -55
-KPX Lacute yacute -55
-KPX Lacute ydieresis -55
-KPX Lcommaaccent T -92
-KPX Lcommaaccent Tcaron -92
-KPX Lcommaaccent Tcommaaccent -92
-KPX Lcommaaccent V -92
-KPX Lcommaaccent W -92
-KPX Lcommaaccent Y -92
-KPX Lcommaaccent Yacute -92
-KPX Lcommaaccent Ydieresis -92
-KPX Lcommaaccent quotedblright -20
-KPX Lcommaaccent quoteright -110
-KPX Lcommaaccent y -55
-KPX Lcommaaccent yacute -55
-KPX Lcommaaccent ydieresis -55
-KPX Lslash T -92
-KPX Lslash Tcaron -92
-KPX Lslash Tcommaaccent -92
-KPX Lslash V -92
-KPX Lslash W -92
-KPX Lslash Y -92
-KPX Lslash Yacute -92
-KPX Lslash Ydieresis -92
-KPX Lslash quotedblright -20
-KPX Lslash quoteright -110
-KPX Lslash y -55
-KPX Lslash yacute -55
-KPX Lslash ydieresis -55
-KPX N A -20
-KPX N Aacute -20
-KPX N Abreve -20
-KPX N Acircumflex -20
-KPX N Adieresis -20
-KPX N Agrave -20
-KPX N Amacron -20
-KPX N Aogonek -20
-KPX N Aring -20
-KPX N Atilde -20
-KPX Nacute A -20
-KPX Nacute Aacute -20
-KPX Nacute Abreve -20
-KPX Nacute Acircumflex -20
-KPX Nacute Adieresis -20
-KPX Nacute Agrave -20
-KPX Nacute Amacron -20
-KPX Nacute Aogonek -20
-KPX Nacute Aring -20
-KPX Nacute Atilde -20
-KPX Ncaron A -20
-KPX Ncaron Aacute -20
-KPX Ncaron Abreve -20
-KPX Ncaron Acircumflex -20
-KPX Ncaron Adieresis -20
-KPX Ncaron Agrave -20
-KPX Ncaron Amacron -20
-KPX Ncaron Aogonek -20
-KPX Ncaron Aring -20
-KPX Ncaron Atilde -20
-KPX Ncommaaccent A -20
-KPX Ncommaaccent Aacute -20
-KPX Ncommaaccent Abreve -20
-KPX Ncommaaccent Acircumflex -20
-KPX Ncommaaccent Adieresis -20
-KPX Ncommaaccent Agrave -20
-KPX Ncommaaccent Amacron -20
-KPX Ncommaaccent Aogonek -20
-KPX Ncommaaccent Aring -20
-KPX Ncommaaccent Atilde -20
-KPX Ntilde A -20
-KPX Ntilde Aacute -20
-KPX Ntilde Abreve -20
-KPX Ntilde Acircumflex -20
-KPX Ntilde Adieresis -20
-KPX Ntilde Agrave -20
-KPX Ntilde Amacron -20
-KPX Ntilde Aogonek -20
-KPX Ntilde Aring -20
-KPX Ntilde Atilde -20
-KPX O A -40
-KPX O Aacute -40
-KPX O Abreve -40
-KPX O Acircumflex -40
-KPX O Adieresis -40
-KPX O Agrave -40
-KPX O Amacron -40
-KPX O Aogonek -40
-KPX O Aring -40
-KPX O Atilde -40
-KPX O T -40
-KPX O Tcaron -40
-KPX O Tcommaaccent -40
-KPX O V -50
-KPX O W -50
-KPX O X -40
-KPX O Y -50
-KPX O Yacute -50
-KPX O Ydieresis -50
-KPX Oacute A -40
-KPX Oacute Aacute -40
-KPX Oacute Abreve -40
-KPX Oacute Acircumflex -40
-KPX Oacute Adieresis -40
-KPX Oacute Agrave -40
-KPX Oacute Amacron -40
-KPX Oacute Aogonek -40
-KPX Oacute Aring -40
-KPX Oacute Atilde -40
-KPX Oacute T -40
-KPX Oacute Tcaron -40
-KPX Oacute Tcommaaccent -40
-KPX Oacute V -50
-KPX Oacute W -50
-KPX Oacute X -40
-KPX Oacute Y -50
-KPX Oacute Yacute -50
-KPX Oacute Ydieresis -50
-KPX Ocircumflex A -40
-KPX Ocircumflex Aacute -40
-KPX Ocircumflex Abreve -40
-KPX Ocircumflex Acircumflex -40
-KPX Ocircumflex Adieresis -40
-KPX Ocircumflex Agrave -40
-KPX Ocircumflex Amacron -40
-KPX Ocircumflex Aogonek -40
-KPX Ocircumflex Aring -40
-KPX Ocircumflex Atilde -40
-KPX Ocircumflex T -40
-KPX Ocircumflex Tcaron -40
-KPX Ocircumflex Tcommaaccent -40
-KPX Ocircumflex V -50
-KPX Ocircumflex W -50
-KPX Ocircumflex X -40
-KPX Ocircumflex Y -50
-KPX Ocircumflex Yacute -50
-KPX Ocircumflex Ydieresis -50
-KPX Odieresis A -40
-KPX Odieresis Aacute -40
-KPX Odieresis Abreve -40
-KPX Odieresis Acircumflex -40
-KPX Odieresis Adieresis -40
-KPX Odieresis Agrave -40
-KPX Odieresis Amacron -40
-KPX Odieresis Aogonek -40
-KPX Odieresis Aring -40
-KPX Odieresis Atilde -40
-KPX Odieresis T -40
-KPX Odieresis Tcaron -40
-KPX Odieresis Tcommaaccent -40
-KPX Odieresis V -50
-KPX Odieresis W -50
-KPX Odieresis X -40
-KPX Odieresis Y -50
-KPX Odieresis Yacute -50
-KPX Odieresis Ydieresis -50
-KPX Ograve A -40
-KPX Ograve Aacute -40
-KPX Ograve Abreve -40
-KPX Ograve Acircumflex -40
-KPX Ograve Adieresis -40
-KPX Ograve Agrave -40
-KPX Ograve Amacron -40
-KPX Ograve Aogonek -40
-KPX Ograve Aring -40
-KPX Ograve Atilde -40
-KPX Ograve T -40
-KPX Ograve Tcaron -40
-KPX Ograve Tcommaaccent -40
-KPX Ograve V -50
-KPX Ograve W -50
-KPX Ograve X -40
-KPX Ograve Y -50
-KPX Ograve Yacute -50
-KPX Ograve Ydieresis -50
-KPX Ohungarumlaut A -40
-KPX Ohungarumlaut Aacute -40
-KPX Ohungarumlaut Abreve -40
-KPX Ohungarumlaut Acircumflex -40
-KPX Ohungarumlaut Adieresis -40
-KPX Ohungarumlaut Agrave -40
-KPX Ohungarumlaut Amacron -40
-KPX Ohungarumlaut Aogonek -40
-KPX Ohungarumlaut Aring -40
-KPX Ohungarumlaut Atilde -40
-KPX Ohungarumlaut T -40
-KPX Ohungarumlaut Tcaron -40
-KPX Ohungarumlaut Tcommaaccent -40
-KPX Ohungarumlaut V -50
-KPX Ohungarumlaut W -50
-KPX Ohungarumlaut X -40
-KPX Ohungarumlaut Y -50
-KPX Ohungarumlaut Yacute -50
-KPX Ohungarumlaut Ydieresis -50
-KPX Omacron A -40
-KPX Omacron Aacute -40
-KPX Omacron Abreve -40
-KPX Omacron Acircumflex -40
-KPX Omacron Adieresis -40
-KPX Omacron Agrave -40
-KPX Omacron Amacron -40
-KPX Omacron Aogonek -40
-KPX Omacron Aring -40
-KPX Omacron Atilde -40
-KPX Omacron T -40
-KPX Omacron Tcaron -40
-KPX Omacron Tcommaaccent -40
-KPX Omacron V -50
-KPX Omacron W -50
-KPX Omacron X -40
-KPX Omacron Y -50
-KPX Omacron Yacute -50
-KPX Omacron Ydieresis -50
-KPX Oslash A -40
-KPX Oslash Aacute -40
-KPX Oslash Abreve -40
-KPX Oslash Acircumflex -40
-KPX Oslash Adieresis -40
-KPX Oslash Agrave -40
-KPX Oslash Amacron -40
-KPX Oslash Aogonek -40
-KPX Oslash Aring -40
-KPX Oslash Atilde -40
-KPX Oslash T -40
-KPX Oslash Tcaron -40
-KPX Oslash Tcommaaccent -40
-KPX Oslash V -50
-KPX Oslash W -50
-KPX Oslash X -40
-KPX Oslash Y -50
-KPX Oslash Yacute -50
-KPX Oslash Ydieresis -50
-KPX Otilde A -40
-KPX Otilde Aacute -40
-KPX Otilde Abreve -40
-KPX Otilde Acircumflex -40
-KPX Otilde Adieresis -40
-KPX Otilde Agrave -40
-KPX Otilde Amacron -40
-KPX Otilde Aogonek -40
-KPX Otilde Aring -40
-KPX Otilde Atilde -40
-KPX Otilde T -40
-KPX Otilde Tcaron -40
-KPX Otilde Tcommaaccent -40
-KPX Otilde V -50
-KPX Otilde W -50
-KPX Otilde X -40
-KPX Otilde Y -50
-KPX Otilde Yacute -50
-KPX Otilde Ydieresis -50
-KPX P A -74
-KPX P Aacute -74
-KPX P Abreve -74
-KPX P Acircumflex -74
-KPX P Adieresis -74
-KPX P Agrave -74
-KPX P Amacron -74
-KPX P Aogonek -74
-KPX P Aring -74
-KPX P Atilde -74
-KPX P a -10
-KPX P aacute -10
-KPX P abreve -10
-KPX P acircumflex -10
-KPX P adieresis -10
-KPX P agrave -10
-KPX P amacron -10
-KPX P aogonek -10
-KPX P aring -10
-KPX P atilde -10
-KPX P comma -92
-KPX P e -20
-KPX P eacute -20
-KPX P ecaron -20
-KPX P ecircumflex -20
-KPX P edieresis -20
-KPX P edotaccent -20
-KPX P egrave -20
-KPX P emacron -20
-KPX P eogonek -20
-KPX P o -20
-KPX P oacute -20
-KPX P ocircumflex -20
-KPX P odieresis -20
-KPX P ograve -20
-KPX P ohungarumlaut -20
-KPX P omacron -20
-KPX P oslash -20
-KPX P otilde -20
-KPX P period -110
-KPX Q U -10
-KPX Q Uacute -10
-KPX Q Ucircumflex -10
-KPX Q Udieresis -10
-KPX Q Ugrave -10
-KPX Q Uhungarumlaut -10
-KPX Q Umacron -10
-KPX Q Uogonek -10
-KPX Q Uring -10
-KPX Q period -20
-KPX R O -30
-KPX R Oacute -30
-KPX R Ocircumflex -30
-KPX R Odieresis -30
-KPX R Ograve -30
-KPX R Ohungarumlaut -30
-KPX R Omacron -30
-KPX R Oslash -30
-KPX R Otilde -30
-KPX R T -40
-KPX R Tcaron -40
-KPX R Tcommaaccent -40
-KPX R U -30
-KPX R Uacute -30
-KPX R Ucircumflex -30
-KPX R Udieresis -30
-KPX R Ugrave -30
-KPX R Uhungarumlaut -30
-KPX R Umacron -30
-KPX R Uogonek -30
-KPX R Uring -30
-KPX R V -55
-KPX R W -35
-KPX R Y -35
-KPX R Yacute -35
-KPX R Ydieresis -35
-KPX Racute O -30
-KPX Racute Oacute -30
-KPX Racute Ocircumflex -30
-KPX Racute Odieresis -30
-KPX Racute Ograve -30
-KPX Racute Ohungarumlaut -30
-KPX Racute Omacron -30
-KPX Racute Oslash -30
-KPX Racute Otilde -30
-KPX Racute T -40
-KPX Racute Tcaron -40
-KPX Racute Tcommaaccent -40
-KPX Racute U -30
-KPX Racute Uacute -30
-KPX Racute Ucircumflex -30
-KPX Racute Udieresis -30
-KPX Racute Ugrave -30
-KPX Racute Uhungarumlaut -30
-KPX Racute Umacron -30
-KPX Racute Uogonek -30
-KPX Racute Uring -30
-KPX Racute V -55
-KPX Racute W -35
-KPX Racute Y -35
-KPX Racute Yacute -35
-KPX Racute Ydieresis -35
-KPX Rcaron O -30
-KPX Rcaron Oacute -30
-KPX Rcaron Ocircumflex -30
-KPX Rcaron Odieresis -30
-KPX Rcaron Ograve -30
-KPX Rcaron Ohungarumlaut -30
-KPX Rcaron Omacron -30
-KPX Rcaron Oslash -30
-KPX Rcaron Otilde -30
-KPX Rcaron T -40
-KPX Rcaron Tcaron -40
-KPX Rcaron Tcommaaccent -40
-KPX Rcaron U -30
-KPX Rcaron Uacute -30
-KPX Rcaron Ucircumflex -30
-KPX Rcaron Udieresis -30
-KPX Rcaron Ugrave -30
-KPX Rcaron Uhungarumlaut -30
-KPX Rcaron Umacron -30
-KPX Rcaron Uogonek -30
-KPX Rcaron Uring -30
-KPX Rcaron V -55
-KPX Rcaron W -35
-KPX Rcaron Y -35
-KPX Rcaron Yacute -35
-KPX Rcaron Ydieresis -35
-KPX Rcommaaccent O -30
-KPX Rcommaaccent Oacute -30
-KPX Rcommaaccent Ocircumflex -30
-KPX Rcommaaccent Odieresis -30
-KPX Rcommaaccent Ograve -30
-KPX Rcommaaccent Ohungarumlaut -30
-KPX Rcommaaccent Omacron -30
-KPX Rcommaaccent Oslash -30
-KPX Rcommaaccent Otilde -30
-KPX Rcommaaccent T -40
-KPX Rcommaaccent Tcaron -40
-KPX Rcommaaccent Tcommaaccent -40
-KPX Rcommaaccent U -30
-KPX Rcommaaccent Uacute -30
-KPX Rcommaaccent Ucircumflex -30
-KPX Rcommaaccent Udieresis -30
-KPX Rcommaaccent Ugrave -30
-KPX Rcommaaccent Uhungarumlaut -30
-KPX Rcommaaccent Umacron -30
-KPX Rcommaaccent Uogonek -30
-KPX Rcommaaccent Uring -30
-KPX Rcommaaccent V -55
-KPX Rcommaaccent W -35
-KPX Rcommaaccent Y -35
-KPX Rcommaaccent Yacute -35
-KPX Rcommaaccent Ydieresis -35
-KPX T A -90
-KPX T Aacute -90
-KPX T Abreve -90
-KPX T Acircumflex -90
-KPX T Adieresis -90
-KPX T Agrave -90
-KPX T Amacron -90
-KPX T Aogonek -90
-KPX T Aring -90
-KPX T Atilde -90
-KPX T O -18
-KPX T Oacute -18
-KPX T Ocircumflex -18
-KPX T Odieresis -18
-KPX T Ograve -18
-KPX T Ohungarumlaut -18
-KPX T Omacron -18
-KPX T Oslash -18
-KPX T Otilde -18
-KPX T a -92
-KPX T aacute -92
-KPX T abreve -52
-KPX T acircumflex -52
-KPX T adieresis -52
-KPX T agrave -52
-KPX T amacron -52
-KPX T aogonek -92
-KPX T aring -92
-KPX T atilde -52
-KPX T colon -74
-KPX T comma -74
-KPX T e -92
-KPX T eacute -92
-KPX T ecaron -92
-KPX T ecircumflex -92
-KPX T edieresis -52
-KPX T edotaccent -92
-KPX T egrave -52
-KPX T emacron -52
-KPX T eogonek -92
-KPX T hyphen -92
-KPX T i -18
-KPX T iacute -18
-KPX T iogonek -18
-KPX T o -92
-KPX T oacute -92
-KPX T ocircumflex -92
-KPX T odieresis -92
-KPX T ograve -92
-KPX T ohungarumlaut -92
-KPX T omacron -92
-KPX T oslash -92
-KPX T otilde -92
-KPX T period -90
-KPX T r -74
-KPX T racute -74
-KPX T rcaron -74
-KPX T rcommaaccent -74
-KPX T semicolon -74
-KPX T u -92
-KPX T uacute -92
-KPX T ucircumflex -92
-KPX T udieresis -92
-KPX T ugrave -92
-KPX T uhungarumlaut -92
-KPX T umacron -92
-KPX T uogonek -92
-KPX T uring -92
-KPX T w -74
-KPX T y -34
-KPX T yacute -34
-KPX T ydieresis -34
-KPX Tcaron A -90
-KPX Tcaron Aacute -90
-KPX Tcaron Abreve -90
-KPX Tcaron Acircumflex -90
-KPX Tcaron Adieresis -90
-KPX Tcaron Agrave -90
-KPX Tcaron Amacron -90
-KPX Tcaron Aogonek -90
-KPX Tcaron Aring -90
-KPX Tcaron Atilde -90
-KPX Tcaron O -18
-KPX Tcaron Oacute -18
-KPX Tcaron Ocircumflex -18
-KPX Tcaron Odieresis -18
-KPX Tcaron Ograve -18
-KPX Tcaron Ohungarumlaut -18
-KPX Tcaron Omacron -18
-KPX Tcaron Oslash -18
-KPX Tcaron Otilde -18
-KPX Tcaron a -92
-KPX Tcaron aacute -92
-KPX Tcaron abreve -52
-KPX Tcaron acircumflex -52
-KPX Tcaron adieresis -52
-KPX Tcaron agrave -52
-KPX Tcaron amacron -52
-KPX Tcaron aogonek -92
-KPX Tcaron aring -92
-KPX Tcaron atilde -52
-KPX Tcaron colon -74
-KPX Tcaron comma -74
-KPX Tcaron e -92
-KPX Tcaron eacute -92
-KPX Tcaron ecaron -92
-KPX Tcaron ecircumflex -92
-KPX Tcaron edieresis -52
-KPX Tcaron edotaccent -92
-KPX Tcaron egrave -52
-KPX Tcaron emacron -52
-KPX Tcaron eogonek -92
-KPX Tcaron hyphen -92
-KPX Tcaron i -18
-KPX Tcaron iacute -18
-KPX Tcaron iogonek -18
-KPX Tcaron o -92
-KPX Tcaron oacute -92
-KPX Tcaron ocircumflex -92
-KPX Tcaron odieresis -92
-KPX Tcaron ograve -92
-KPX Tcaron ohungarumlaut -92
-KPX Tcaron omacron -92
-KPX Tcaron oslash -92
-KPX Tcaron otilde -92
-KPX Tcaron period -90
-KPX Tcaron r -74
-KPX Tcaron racute -74
-KPX Tcaron rcaron -74
-KPX Tcaron rcommaaccent -74
-KPX Tcaron semicolon -74
-KPX Tcaron u -92
-KPX Tcaron uacute -92
-KPX Tcaron ucircumflex -92
-KPX Tcaron udieresis -92
-KPX Tcaron ugrave -92
-KPX Tcaron uhungarumlaut -92
-KPX Tcaron umacron -92
-KPX Tcaron uogonek -92
-KPX Tcaron uring -92
-KPX Tcaron w -74
-KPX Tcaron y -34
-KPX Tcaron yacute -34
-KPX Tcaron ydieresis -34
-KPX Tcommaaccent A -90
-KPX Tcommaaccent Aacute -90
-KPX Tcommaaccent Abreve -90
-KPX Tcommaaccent Acircumflex -90
-KPX Tcommaaccent Adieresis -90
-KPX Tcommaaccent Agrave -90
-KPX Tcommaaccent Amacron -90
-KPX Tcommaaccent Aogonek -90
-KPX Tcommaaccent Aring -90
-KPX Tcommaaccent Atilde -90
-KPX Tcommaaccent O -18
-KPX Tcommaaccent Oacute -18
-KPX Tcommaaccent Ocircumflex -18
-KPX Tcommaaccent Odieresis -18
-KPX Tcommaaccent Ograve -18
-KPX Tcommaaccent Ohungarumlaut -18
-KPX Tcommaaccent Omacron -18
-KPX Tcommaaccent Oslash -18
-KPX Tcommaaccent Otilde -18
-KPX Tcommaaccent a -92
-KPX Tcommaaccent aacute -92
-KPX Tcommaaccent abreve -52
-KPX Tcommaaccent acircumflex -52
-KPX Tcommaaccent adieresis -52
-KPX Tcommaaccent agrave -52
-KPX Tcommaaccent amacron -52
-KPX Tcommaaccent aogonek -92
-KPX Tcommaaccent aring -92
-KPX Tcommaaccent atilde -52
-KPX Tcommaaccent colon -74
-KPX Tcommaaccent comma -74
-KPX Tcommaaccent e -92
-KPX Tcommaaccent eacute -92
-KPX Tcommaaccent ecaron -92
-KPX Tcommaaccent ecircumflex -92
-KPX Tcommaaccent edieresis -52
-KPX Tcommaaccent edotaccent -92
-KPX Tcommaaccent egrave -52
-KPX Tcommaaccent emacron -52
-KPX Tcommaaccent eogonek -92
-KPX Tcommaaccent hyphen -92
-KPX Tcommaaccent i -18
-KPX Tcommaaccent iacute -18
-KPX Tcommaaccent iogonek -18
-KPX Tcommaaccent o -92
-KPX Tcommaaccent oacute -92
-KPX Tcommaaccent ocircumflex -92
-KPX Tcommaaccent odieresis -92
-KPX Tcommaaccent ograve -92
-KPX Tcommaaccent ohungarumlaut -92
-KPX Tcommaaccent omacron -92
-KPX Tcommaaccent oslash -92
-KPX Tcommaaccent otilde -92
-KPX Tcommaaccent period -90
-KPX Tcommaaccent r -74
-KPX Tcommaaccent racute -74
-KPX Tcommaaccent rcaron -74
-KPX Tcommaaccent rcommaaccent -74
-KPX Tcommaaccent semicolon -74
-KPX Tcommaaccent u -92
-KPX Tcommaaccent uacute -92
-KPX Tcommaaccent ucircumflex -92
-KPX Tcommaaccent udieresis -92
-KPX Tcommaaccent ugrave -92
-KPX Tcommaaccent uhungarumlaut -92
-KPX Tcommaaccent umacron -92
-KPX Tcommaaccent uogonek -92
-KPX Tcommaaccent uring -92
-KPX Tcommaaccent w -74
-KPX Tcommaaccent y -34
-KPX Tcommaaccent yacute -34
-KPX Tcommaaccent ydieresis -34
-KPX U A -60
-KPX U Aacute -60
-KPX U Abreve -60
-KPX U Acircumflex -60
-KPX U Adieresis -60
-KPX U Agrave -60
-KPX U Amacron -60
-KPX U Aogonek -60
-KPX U Aring -60
-KPX U Atilde -60
-KPX U comma -50
-KPX U period -50
-KPX Uacute A -60
-KPX Uacute Aacute -60
-KPX Uacute Abreve -60
-KPX Uacute Acircumflex -60
-KPX Uacute Adieresis -60
-KPX Uacute Agrave -60
-KPX Uacute Amacron -60
-KPX Uacute Aogonek -60
-KPX Uacute Aring -60
-KPX Uacute Atilde -60
-KPX Uacute comma -50
-KPX Uacute period -50
-KPX Ucircumflex A -60
-KPX Ucircumflex Aacute -60
-KPX Ucircumflex Abreve -60
-KPX Ucircumflex Acircumflex -60
-KPX Ucircumflex Adieresis -60
-KPX Ucircumflex Agrave -60
-KPX Ucircumflex Amacron -60
-KPX Ucircumflex Aogonek -60
-KPX Ucircumflex Aring -60
-KPX Ucircumflex Atilde -60
-KPX Ucircumflex comma -50
-KPX Ucircumflex period -50
-KPX Udieresis A -60
-KPX Udieresis Aacute -60
-KPX Udieresis Abreve -60
-KPX Udieresis Acircumflex -60
-KPX Udieresis Adieresis -60
-KPX Udieresis Agrave -60
-KPX Udieresis Amacron -60
-KPX Udieresis Aogonek -60
-KPX Udieresis Aring -60
-KPX Udieresis Atilde -60
-KPX Udieresis comma -50
-KPX Udieresis period -50
-KPX Ugrave A -60
-KPX Ugrave Aacute -60
-KPX Ugrave Abreve -60
-KPX Ugrave Acircumflex -60
-KPX Ugrave Adieresis -60
-KPX Ugrave Agrave -60
-KPX Ugrave Amacron -60
-KPX Ugrave Aogonek -60
-KPX Ugrave Aring -60
-KPX Ugrave Atilde -60
-KPX Ugrave comma -50
-KPX Ugrave period -50
-KPX Uhungarumlaut A -60
-KPX Uhungarumlaut Aacute -60
-KPX Uhungarumlaut Abreve -60
-KPX Uhungarumlaut Acircumflex -60
-KPX Uhungarumlaut Adieresis -60
-KPX Uhungarumlaut Agrave -60
-KPX Uhungarumlaut Amacron -60
-KPX Uhungarumlaut Aogonek -60
-KPX Uhungarumlaut Aring -60
-KPX Uhungarumlaut Atilde -60
-KPX Uhungarumlaut comma -50
-KPX Uhungarumlaut period -50
-KPX Umacron A -60
-KPX Umacron Aacute -60
-KPX Umacron Abreve -60
-KPX Umacron Acircumflex -60
-KPX Umacron Adieresis -60
-KPX Umacron Agrave -60
-KPX Umacron Amacron -60
-KPX Umacron Aogonek -60
-KPX Umacron Aring -60
-KPX Umacron Atilde -60
-KPX Umacron comma -50
-KPX Umacron period -50
-KPX Uogonek A -60
-KPX Uogonek Aacute -60
-KPX Uogonek Abreve -60
-KPX Uogonek Acircumflex -60
-KPX Uogonek Adieresis -60
-KPX Uogonek Agrave -60
-KPX Uogonek Amacron -60
-KPX Uogonek Aogonek -60
-KPX Uogonek Aring -60
-KPX Uogonek Atilde -60
-KPX Uogonek comma -50
-KPX Uogonek period -50
-KPX Uring A -60
-KPX Uring Aacute -60
-KPX Uring Abreve -60
-KPX Uring Acircumflex -60
-KPX Uring Adieresis -60
-KPX Uring Agrave -60
-KPX Uring Amacron -60
-KPX Uring Aogonek -60
-KPX Uring Aring -60
-KPX Uring Atilde -60
-KPX Uring comma -50
-KPX Uring period -50
-KPX V A -135
-KPX V Aacute -135
-KPX V Abreve -135
-KPX V Acircumflex -135
-KPX V Adieresis -135
-KPX V Agrave -135
-KPX V Amacron -135
-KPX V Aogonek -135
-KPX V Aring -135
-KPX V Atilde -135
-KPX V G -30
-KPX V Gbreve -30
-KPX V Gcommaaccent -30
-KPX V O -45
-KPX V Oacute -45
-KPX V Ocircumflex -45
-KPX V Odieresis -45
-KPX V Ograve -45
-KPX V Ohungarumlaut -45
-KPX V Omacron -45
-KPX V Oslash -45
-KPX V Otilde -45
-KPX V a -92
-KPX V aacute -92
-KPX V abreve -92
-KPX V acircumflex -92
-KPX V adieresis -92
-KPX V agrave -92
-KPX V amacron -92
-KPX V aogonek -92
-KPX V aring -92
-KPX V atilde -92
-KPX V colon -92
-KPX V comma -129
-KPX V e -100
-KPX V eacute -100
-KPX V ecaron -100
-KPX V ecircumflex -100
-KPX V edieresis -100
-KPX V edotaccent -100
-KPX V egrave -100
-KPX V emacron -100
-KPX V eogonek -100
-KPX V hyphen -74
-KPX V i -37
-KPX V iacute -37
-KPX V icircumflex -37
-KPX V idieresis -37
-KPX V igrave -37
-KPX V imacron -37
-KPX V iogonek -37
-KPX V o -100
-KPX V oacute -100
-KPX V ocircumflex -100
-KPX V odieresis -100
-KPX V ograve -100
-KPX V ohungarumlaut -100
-KPX V omacron -100
-KPX V oslash -100
-KPX V otilde -100
-KPX V period -145
-KPX V semicolon -92
-KPX V u -92
-KPX V uacute -92
-KPX V ucircumflex -92
-KPX V udieresis -92
-KPX V ugrave -92
-KPX V uhungarumlaut -92
-KPX V umacron -92
-KPX V uogonek -92
-KPX V uring -92
-KPX W A -120
-KPX W Aacute -120
-KPX W Abreve -120
-KPX W Acircumflex -120
-KPX W Adieresis -120
-KPX W Agrave -120
-KPX W Amacron -120
-KPX W Aogonek -120
-KPX W Aring -120
-KPX W Atilde -120
-KPX W O -10
-KPX W Oacute -10
-KPX W Ocircumflex -10
-KPX W Odieresis -10
-KPX W Ograve -10
-KPX W Ohungarumlaut -10
-KPX W Omacron -10
-KPX W Oslash -10
-KPX W Otilde -10
-KPX W a -65
-KPX W aacute -65
-KPX W abreve -65
-KPX W acircumflex -65
-KPX W adieresis -65
-KPX W agrave -65
-KPX W amacron -65
-KPX W aogonek -65
-KPX W aring -65
-KPX W atilde -65
-KPX W colon -55
-KPX W comma -92
-KPX W e -65
-KPX W eacute -65
-KPX W ecaron -65
-KPX W ecircumflex -65
-KPX W edieresis -65
-KPX W edotaccent -65
-KPX W egrave -65
-KPX W emacron -65
-KPX W eogonek -65
-KPX W hyphen -37
-KPX W i -18
-KPX W iacute -18
-KPX W iogonek -18
-KPX W o -75
-KPX W oacute -75
-KPX W ocircumflex -75
-KPX W odieresis -75
-KPX W ograve -75
-KPX W ohungarumlaut -75
-KPX W omacron -75
-KPX W oslash -75
-KPX W otilde -75
-KPX W period -92
-KPX W semicolon -55
-KPX W u -50
-KPX W uacute -50
-KPX W ucircumflex -50
-KPX W udieresis -50
-KPX W ugrave -50
-KPX W uhungarumlaut -50
-KPX W umacron -50
-KPX W uogonek -50
-KPX W uring -50
-KPX W y -60
-KPX W yacute -60
-KPX W ydieresis -60
-KPX Y A -110
-KPX Y Aacute -110
-KPX Y Abreve -110
-KPX Y Acircumflex -110
-KPX Y Adieresis -110
-KPX Y Agrave -110
-KPX Y Amacron -110
-KPX Y Aogonek -110
-KPX Y Aring -110
-KPX Y Atilde -110
-KPX Y O -35
-KPX Y Oacute -35
-KPX Y Ocircumflex -35
-KPX Y Odieresis -35
-KPX Y Ograve -35
-KPX Y Ohungarumlaut -35
-KPX Y Omacron -35
-KPX Y Oslash -35
-KPX Y Otilde -35
-KPX Y a -85
-KPX Y aacute -85
-KPX Y abreve -85
-KPX Y acircumflex -85
-KPX Y adieresis -85
-KPX Y agrave -85
-KPX Y amacron -85
-KPX Y aogonek -85
-KPX Y aring -85
-KPX Y atilde -85
-KPX Y colon -92
-KPX Y comma -92
-KPX Y e -111
-KPX Y eacute -111
-KPX Y ecaron -111
-KPX Y ecircumflex -111
-KPX Y edieresis -71
-KPX Y edotaccent -111
-KPX Y egrave -71
-KPX Y emacron -71
-KPX Y eogonek -111
-KPX Y hyphen -92
-KPX Y i -37
-KPX Y iacute -37
-KPX Y iogonek -37
-KPX Y o -111
-KPX Y oacute -111
-KPX Y ocircumflex -111
-KPX Y odieresis -111
-KPX Y ograve -111
-KPX Y ohungarumlaut -111
-KPX Y omacron -111
-KPX Y oslash -111
-KPX Y otilde -111
-KPX Y period -92
-KPX Y semicolon -92
-KPX Y u -92
-KPX Y uacute -92
-KPX Y ucircumflex -92
-KPX Y udieresis -92
-KPX Y ugrave -92
-KPX Y uhungarumlaut -92
-KPX Y umacron -92
-KPX Y uogonek -92
-KPX Y uring -92
-KPX Yacute A -110
-KPX Yacute Aacute -110
-KPX Yacute Abreve -110
-KPX Yacute Acircumflex -110
-KPX Yacute Adieresis -110
-KPX Yacute Agrave -110
-KPX Yacute Amacron -110
-KPX Yacute Aogonek -110
-KPX Yacute Aring -110
-KPX Yacute Atilde -110
-KPX Yacute O -35
-KPX Yacute Oacute -35
-KPX Yacute Ocircumflex -35
-KPX Yacute Odieresis -35
-KPX Yacute Ograve -35
-KPX Yacute Ohungarumlaut -35
-KPX Yacute Omacron -35
-KPX Yacute Oslash -35
-KPX Yacute Otilde -35
-KPX Yacute a -85
-KPX Yacute aacute -85
-KPX Yacute abreve -85
-KPX Yacute acircumflex -85
-KPX Yacute adieresis -85
-KPX Yacute agrave -85
-KPX Yacute amacron -85
-KPX Yacute aogonek -85
-KPX Yacute aring -85
-KPX Yacute atilde -85
-KPX Yacute colon -92
-KPX Yacute comma -92
-KPX Yacute e -111
-KPX Yacute eacute -111
-KPX Yacute ecaron -111
-KPX Yacute ecircumflex -111
-KPX Yacute edieresis -71
-KPX Yacute edotaccent -111
-KPX Yacute egrave -71
-KPX Yacute emacron -71
-KPX Yacute eogonek -111
-KPX Yacute hyphen -92
-KPX Yacute i -37
-KPX Yacute iacute -37
-KPX Yacute iogonek -37
-KPX Yacute o -111
-KPX Yacute oacute -111
-KPX Yacute ocircumflex -111
-KPX Yacute odieresis -111
-KPX Yacute ograve -111
-KPX Yacute ohungarumlaut -111
-KPX Yacute omacron -111
-KPX Yacute oslash -111
-KPX Yacute otilde -111
-KPX Yacute period -92
-KPX Yacute semicolon -92
-KPX Yacute u -92
-KPX Yacute uacute -92
-KPX Yacute ucircumflex -92
-KPX Yacute udieresis -92
-KPX Yacute ugrave -92
-KPX Yacute uhungarumlaut -92
-KPX Yacute umacron -92
-KPX Yacute uogonek -92
-KPX Yacute uring -92
-KPX Ydieresis A -110
-KPX Ydieresis Aacute -110
-KPX Ydieresis Abreve -110
-KPX Ydieresis Acircumflex -110
-KPX Ydieresis Adieresis -110
-KPX Ydieresis Agrave -110
-KPX Ydieresis Amacron -110
-KPX Ydieresis Aogonek -110
-KPX Ydieresis Aring -110
-KPX Ydieresis Atilde -110
-KPX Ydieresis O -35
-KPX Ydieresis Oacute -35
-KPX Ydieresis Ocircumflex -35
-KPX Ydieresis Odieresis -35
-KPX Ydieresis Ograve -35
-KPX Ydieresis Ohungarumlaut -35
-KPX Ydieresis Omacron -35
-KPX Ydieresis Oslash -35
-KPX Ydieresis Otilde -35
-KPX Ydieresis a -85
-KPX Ydieresis aacute -85
-KPX Ydieresis abreve -85
-KPX Ydieresis acircumflex -85
-KPX Ydieresis adieresis -85
-KPX Ydieresis agrave -85
-KPX Ydieresis amacron -85
-KPX Ydieresis aogonek -85
-KPX Ydieresis aring -85
-KPX Ydieresis atilde -85
-KPX Ydieresis colon -92
-KPX Ydieresis comma -92
-KPX Ydieresis e -111
-KPX Ydieresis eacute -111
-KPX Ydieresis ecaron -111
-KPX Ydieresis ecircumflex -111
-KPX Ydieresis edieresis -71
-KPX Ydieresis edotaccent -111
-KPX Ydieresis egrave -71
-KPX Ydieresis emacron -71
-KPX Ydieresis eogonek -111
-KPX Ydieresis hyphen -92
-KPX Ydieresis i -37
-KPX Ydieresis iacute -37
-KPX Ydieresis iogonek -37
-KPX Ydieresis o -111
-KPX Ydieresis oacute -111
-KPX Ydieresis ocircumflex -111
-KPX Ydieresis odieresis -111
-KPX Ydieresis ograve -111
-KPX Ydieresis ohungarumlaut -111
-KPX Ydieresis omacron -111
-KPX Ydieresis oslash -111
-KPX Ydieresis otilde -111
-KPX Ydieresis period -92
-KPX Ydieresis semicolon -92
-KPX Ydieresis u -92
-KPX Ydieresis uacute -92
-KPX Ydieresis ucircumflex -92
-KPX Ydieresis udieresis -92
-KPX Ydieresis ugrave -92
-KPX Ydieresis uhungarumlaut -92
-KPX Ydieresis umacron -92
-KPX Ydieresis uogonek -92
-KPX Ydieresis uring -92
-KPX a v -25
-KPX aacute v -25
-KPX abreve v -25
-KPX acircumflex v -25
-KPX adieresis v -25
-KPX agrave v -25
-KPX amacron v -25
-KPX aogonek v -25
-KPX aring v -25
-KPX atilde v -25
-KPX b b -10
-KPX b period -40
-KPX b u -20
-KPX b uacute -20
-KPX b ucircumflex -20
-KPX b udieresis -20
-KPX b ugrave -20
-KPX b uhungarumlaut -20
-KPX b umacron -20
-KPX b uogonek -20
-KPX b uring -20
-KPX b v -15
-KPX comma quotedblright -45
-KPX comma quoteright -55
-KPX d w -15
-KPX dcroat w -15
-KPX e v -15
-KPX eacute v -15
-KPX ecaron v -15
-KPX ecircumflex v -15
-KPX edieresis v -15
-KPX edotaccent v -15
-KPX egrave v -15
-KPX emacron v -15
-KPX eogonek v -15
-KPX f comma -15
-KPX f dotlessi -35
-KPX f i -25
-KPX f o -25
-KPX f oacute -25
-KPX f ocircumflex -25
-KPX f odieresis -25
-KPX f ograve -25
-KPX f ohungarumlaut -25
-KPX f omacron -25
-KPX f oslash -25
-KPX f otilde -25
-KPX f period -15
-KPX f quotedblright 50
-KPX f quoteright 55
-KPX g period -15
-KPX gbreve period -15
-KPX gcommaaccent period -15
-KPX h y -15
-KPX h yacute -15
-KPX h ydieresis -15
-KPX i v -10
-KPX iacute v -10
-KPX icircumflex v -10
-KPX idieresis v -10
-KPX igrave v -10
-KPX imacron v -10
-KPX iogonek v -10
-KPX k e -10
-KPX k eacute -10
-KPX k ecaron -10
-KPX k ecircumflex -10
-KPX k edieresis -10
-KPX k edotaccent -10
-KPX k egrave -10
-KPX k emacron -10
-KPX k eogonek -10
-KPX k o -15
-KPX k oacute -15
-KPX k ocircumflex -15
-KPX k odieresis -15
-KPX k ograve -15
-KPX k ohungarumlaut -15
-KPX k omacron -15
-KPX k oslash -15
-KPX k otilde -15
-KPX k y -15
-KPX k yacute -15
-KPX k ydieresis -15
-KPX kcommaaccent e -10
-KPX kcommaaccent eacute -10
-KPX kcommaaccent ecaron -10
-KPX kcommaaccent ecircumflex -10
-KPX kcommaaccent edieresis -10
-KPX kcommaaccent edotaccent -10
-KPX kcommaaccent egrave -10
-KPX kcommaaccent emacron -10
-KPX kcommaaccent eogonek -10
-KPX kcommaaccent o -15
-KPX kcommaaccent oacute -15
-KPX kcommaaccent ocircumflex -15
-KPX kcommaaccent odieresis -15
-KPX kcommaaccent ograve -15
-KPX kcommaaccent ohungarumlaut -15
-KPX kcommaaccent omacron -15
-KPX kcommaaccent oslash -15
-KPX kcommaaccent otilde -15
-KPX kcommaaccent y -15
-KPX kcommaaccent yacute -15
-KPX kcommaaccent ydieresis -15
-KPX n v -40
-KPX nacute v -40
-KPX ncaron v -40
-KPX ncommaaccent v -40
-KPX ntilde v -40
-KPX o v -10
-KPX o w -10
-KPX oacute v -10
-KPX oacute w -10
-KPX ocircumflex v -10
-KPX ocircumflex w -10
-KPX odieresis v -10
-KPX odieresis w -10
-KPX ograve v -10
-KPX ograve w -10
-KPX ohungarumlaut v -10
-KPX ohungarumlaut w -10
-KPX omacron v -10
-KPX omacron w -10
-KPX oslash v -10
-KPX oslash w -10
-KPX otilde v -10
-KPX otilde w -10
-KPX period quotedblright -55
-KPX period quoteright -55
-KPX quotedblleft A -10
-KPX quotedblleft Aacute -10
-KPX quotedblleft Abreve -10
-KPX quotedblleft Acircumflex -10
-KPX quotedblleft Adieresis -10
-KPX quotedblleft Agrave -10
-KPX quotedblleft Amacron -10
-KPX quotedblleft Aogonek -10
-KPX quotedblleft Aring -10
-KPX quotedblleft Atilde -10
-KPX quoteleft A -10
-KPX quoteleft Aacute -10
-KPX quoteleft Abreve -10
-KPX quoteleft Acircumflex -10
-KPX quoteleft Adieresis -10
-KPX quoteleft Agrave -10
-KPX quoteleft Amacron -10
-KPX quoteleft Aogonek -10
-KPX quoteleft Aring -10
-KPX quoteleft Atilde -10
-KPX quoteleft quoteleft -63
-KPX quoteright d -20
-KPX quoteright dcroat -20
-KPX quoteright quoteright -63
-KPX quoteright r -20
-KPX quoteright racute -20
-KPX quoteright rcaron -20
-KPX quoteright rcommaaccent -20
-KPX quoteright s -37
-KPX quoteright sacute -37
-KPX quoteright scaron -37
-KPX quoteright scedilla -37
-KPX quoteright scommaaccent -37
-KPX quoteright space -74
-KPX quoteright v -20
-KPX r c -18
-KPX r cacute -18
-KPX r ccaron -18
-KPX r ccedilla -18
-KPX r comma -92
-KPX r e -18
-KPX r eacute -18
-KPX r ecaron -18
-KPX r ecircumflex -18
-KPX r edieresis -18
-KPX r edotaccent -18
-KPX r egrave -18
-KPX r emacron -18
-KPX r eogonek -18
-KPX r g -10
-KPX r gbreve -10
-KPX r gcommaaccent -10
-KPX r hyphen -37
-KPX r n -15
-KPX r nacute -15
-KPX r ncaron -15
-KPX r ncommaaccent -15
-KPX r ntilde -15
-KPX r o -18
-KPX r oacute -18
-KPX r ocircumflex -18
-KPX r odieresis -18
-KPX r ograve -18
-KPX r ohungarumlaut -18
-KPX r omacron -18
-KPX r oslash -18
-KPX r otilde -18
-KPX r p -10
-KPX r period -100
-KPX r q -18
-KPX r v -10
-KPX racute c -18
-KPX racute cacute -18
-KPX racute ccaron -18
-KPX racute ccedilla -18
-KPX racute comma -92
-KPX racute e -18
-KPX racute eacute -18
-KPX racute ecaron -18
-KPX racute ecircumflex -18
-KPX racute edieresis -18
-KPX racute edotaccent -18
-KPX racute egrave -18
-KPX racute emacron -18
-KPX racute eogonek -18
-KPX racute g -10
-KPX racute gbreve -10
-KPX racute gcommaaccent -10
-KPX racute hyphen -37
-KPX racute n -15
-KPX racute nacute -15
-KPX racute ncaron -15
-KPX racute ncommaaccent -15
-KPX racute ntilde -15
-KPX racute o -18
-KPX racute oacute -18
-KPX racute ocircumflex -18
-KPX racute odieresis -18
-KPX racute ograve -18
-KPX racute ohungarumlaut -18
-KPX racute omacron -18
-KPX racute oslash -18
-KPX racute otilde -18
-KPX racute p -10
-KPX racute period -100
-KPX racute q -18
-KPX racute v -10
-KPX rcaron c -18
-KPX rcaron cacute -18
-KPX rcaron ccaron -18
-KPX rcaron ccedilla -18
-KPX rcaron comma -92
-KPX rcaron e -18
-KPX rcaron eacute -18
-KPX rcaron ecaron -18
-KPX rcaron ecircumflex -18
-KPX rcaron edieresis -18
-KPX rcaron edotaccent -18
-KPX rcaron egrave -18
-KPX rcaron emacron -18
-KPX rcaron eogonek -18
-KPX rcaron g -10
-KPX rcaron gbreve -10
-KPX rcaron gcommaaccent -10
-KPX rcaron hyphen -37
-KPX rcaron n -15
-KPX rcaron nacute -15
-KPX rcaron ncaron -15
-KPX rcaron ncommaaccent -15
-KPX rcaron ntilde -15
-KPX rcaron o -18
-KPX rcaron oacute -18
-KPX rcaron ocircumflex -18
-KPX rcaron odieresis -18
-KPX rcaron ograve -18
-KPX rcaron ohungarumlaut -18
-KPX rcaron omacron -18
-KPX rcaron oslash -18
-KPX rcaron otilde -18
-KPX rcaron p -10
-KPX rcaron period -100
-KPX rcaron q -18
-KPX rcaron v -10
-KPX rcommaaccent c -18
-KPX rcommaaccent cacute -18
-KPX rcommaaccent ccaron -18
-KPX rcommaaccent ccedilla -18
-KPX rcommaaccent comma -92
-KPX rcommaaccent e -18
-KPX rcommaaccent eacute -18
-KPX rcommaaccent ecaron -18
-KPX rcommaaccent ecircumflex -18
-KPX rcommaaccent edieresis -18
-KPX rcommaaccent edotaccent -18
-KPX rcommaaccent egrave -18
-KPX rcommaaccent emacron -18
-KPX rcommaaccent eogonek -18
-KPX rcommaaccent g -10
-KPX rcommaaccent gbreve -10
-KPX rcommaaccent gcommaaccent -10
-KPX rcommaaccent hyphen -37
-KPX rcommaaccent n -15
-KPX rcommaaccent nacute -15
-KPX rcommaaccent ncaron -15
-KPX rcommaaccent ncommaaccent -15
-KPX rcommaaccent ntilde -15
-KPX rcommaaccent o -18
-KPX rcommaaccent oacute -18
-KPX rcommaaccent ocircumflex -18
-KPX rcommaaccent odieresis -18
-KPX rcommaaccent ograve -18
-KPX rcommaaccent ohungarumlaut -18
-KPX rcommaaccent omacron -18
-KPX rcommaaccent oslash -18
-KPX rcommaaccent otilde -18
-KPX rcommaaccent p -10
-KPX rcommaaccent period -100
-KPX rcommaaccent q -18
-KPX rcommaaccent v -10
-KPX space A -55
-KPX space Aacute -55
-KPX space Abreve -55
-KPX space Acircumflex -55
-KPX space Adieresis -55
-KPX space Agrave -55
-KPX space Amacron -55
-KPX space Aogonek -55
-KPX space Aring -55
-KPX space Atilde -55
-KPX space T -30
-KPX space Tcaron -30
-KPX space Tcommaaccent -30
-KPX space V -45
-KPX space W -30
-KPX space Y -55
-KPX space Yacute -55
-KPX space Ydieresis -55
-KPX v a -10
-KPX v aacute -10
-KPX v abreve -10
-KPX v acircumflex -10
-KPX v adieresis -10
-KPX v agrave -10
-KPX v amacron -10
-KPX v aogonek -10
-KPX v aring -10
-KPX v atilde -10
-KPX v comma -55
-KPX v e -10
-KPX v eacute -10
-KPX v ecaron -10
-KPX v ecircumflex -10
-KPX v edieresis -10
-KPX v edotaccent -10
-KPX v egrave -10
-KPX v emacron -10
-KPX v eogonek -10
-KPX v o -10
-KPX v oacute -10
-KPX v ocircumflex -10
-KPX v odieresis -10
-KPX v ograve -10
-KPX v ohungarumlaut -10
-KPX v omacron -10
-KPX v oslash -10
-KPX v otilde -10
-KPX v period -70
-KPX w comma -55
-KPX w o -10
-KPX w oacute -10
-KPX w ocircumflex -10
-KPX w odieresis -10
-KPX w ograve -10
-KPX w ohungarumlaut -10
-KPX w omacron -10
-KPX w oslash -10
-KPX w otilde -10
-KPX w period -70
-KPX y comma -55
-KPX y e -10
-KPX y eacute -10
-KPX y ecaron -10
-KPX y ecircumflex -10
-KPX y edieresis -10
-KPX y edotaccent -10
-KPX y egrave -10
-KPX y emacron -10
-KPX y eogonek -10
-KPX y o -25
-KPX y oacute -25
-KPX y ocircumflex -25
-KPX y odieresis -25
-KPX y ograve -25
-KPX y ohungarumlaut -25
-KPX y omacron -25
-KPX y oslash -25
-KPX y otilde -25
-KPX y period -70
-KPX yacute comma -55
-KPX yacute e -10
-KPX yacute eacute -10
-KPX yacute ecaron -10
-KPX yacute ecircumflex -10
-KPX yacute edieresis -10
-KPX yacute edotaccent -10
-KPX yacute egrave -10
-KPX yacute emacron -10
-KPX yacute eogonek -10
-KPX yacute o -25
-KPX yacute oacute -25
-KPX yacute ocircumflex -25
-KPX yacute odieresis -25
-KPX yacute ograve -25
-KPX yacute ohungarumlaut -25
-KPX yacute omacron -25
-KPX yacute oslash -25
-KPX yacute otilde -25
-KPX yacute period -70
-KPX ydieresis comma -55
-KPX ydieresis e -10
-KPX ydieresis eacute -10
-KPX ydieresis ecaron -10
-KPX ydieresis ecircumflex -10
-KPX ydieresis edieresis -10
-KPX ydieresis edotaccent -10
-KPX ydieresis egrave -10
-KPX ydieresis emacron -10
-KPX ydieresis eogonek -10
-KPX ydieresis o -25
-KPX ydieresis oacute -25
-KPX ydieresis ocircumflex -25
-KPX ydieresis odieresis -25
-KPX ydieresis ograve -25
-KPX ydieresis ohungarumlaut -25
-KPX ydieresis omacron -25
-KPX ydieresis oslash -25
-KPX ydieresis otilde -25
-KPX ydieresis period -70
-EndKernPairs
-EndKernData
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Times-BoldItalic.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Times-BoldItalic.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Times-BoldItalic.afm 2004-05-26 16:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Times-BoldItalic.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,2384 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Thu May 1 13:04:06 1997
-Comment UniqueID 43066
-Comment VMusage 45874 56899
-FontName Times-BoldItalic
-FullName Times Bold Italic
-FamilyName Times
-Weight Bold
-ItalicAngle -15
-IsFixedPitch false
-CharacterSet ExtendedRoman
-FontBBox -200 -218 996 921
-UnderlinePosition -100
-UnderlineThickness 50
-Version 002.000
-Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries.
-EncodingScheme AdobeStandardEncoding
-CapHeight 669
-XHeight 462
-Ascender 683
-Descender -217
-StdHW 42
-StdVW 121
-StartCharMetrics 315
-C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 389 ; N exclam ; B 67 -13 370 684 ;
-C 34 ; WX 555 ; N quotedbl ; B 136 398 536 685 ;
-C 35 ; WX 500 ; N numbersign ; B -33 0 533 700 ;
-C 36 ; WX 500 ; N dollar ; B -20 -100 497 733 ;
-C 37 ; WX 833 ; N percent ; B 39 -10 793 692 ;
-C 38 ; WX 778 ; N ampersand ; B 5 -19 699 682 ;
-C 39 ; WX 333 ; N quoteright ; B 98 369 302 685 ;
-C 40 ; WX 333 ; N parenleft ; B 28 -179 344 685 ;
-C 41 ; WX 333 ; N parenright ; B -44 -179 271 685 ;
-C 42 ; WX 500 ; N asterisk ; B 65 249 456 685 ;
-C 43 ; WX 570 ; N plus ; B 33 0 537 506 ;
-C 44 ; WX 250 ; N comma ; B -60 -182 144 134 ;
-C 45 ; WX 333 ; N hyphen ; B 2 166 271 282 ;
-C 46 ; WX 250 ; N period ; B -9 -13 139 135 ;
-C 47 ; WX 278 ; N slash ; B -64 -18 342 685 ;
-C 48 ; WX 500 ; N zero ; B 17 -14 477 683 ;
-C 49 ; WX 500 ; N one ; B 5 0 419 683 ;
-C 50 ; WX 500 ; N two ; B -27 0 446 683 ;
-C 51 ; WX 500 ; N three ; B -15 -13 450 683 ;
-C 52 ; WX 500 ; N four ; B -15 0 503 683 ;
-C 53 ; WX 500 ; N five ; B -11 -13 487 669 ;
-C 54 ; WX 500 ; N six ; B 23 -15 509 679 ;
-C 55 ; WX 500 ; N seven ; B 52 0 525 669 ;
-C 56 ; WX 500 ; N eight ; B 3 -13 476 683 ;
-C 57 ; WX 500 ; N nine ; B -12 -10 475 683 ;
-C 58 ; WX 333 ; N colon ; B 23 -13 264 459 ;
-C 59 ; WX 333 ; N semicolon ; B -25 -183 264 459 ;
-C 60 ; WX 570 ; N less ; B 31 -8 539 514 ;
-C 61 ; WX 570 ; N equal ; B 33 107 537 399 ;
-C 62 ; WX 570 ; N greater ; B 31 -8 539 514 ;
-C 63 ; WX 500 ; N question ; B 79 -13 470 684 ;
-C 64 ; WX 832 ; N at ; B 63 -18 770 685 ;
-C 65 ; WX 667 ; N A ; B -67 0 593 683 ;
-C 66 ; WX 667 ; N B ; B -24 0 624 669 ;
-C 67 ; WX 667 ; N C ; B 32 -18 677 685 ;
-C 68 ; WX 722 ; N D ; B -46 0 685 669 ;
-C 69 ; WX 667 ; N E ; B -27 0 653 669 ;
-C 70 ; WX 667 ; N F ; B -13 0 660 669 ;
-C 71 ; WX 722 ; N G ; B 21 -18 706 685 ;
-C 72 ; WX 778 ; N H ; B -24 0 799 669 ;
-C 73 ; WX 389 ; N I ; B -32 0 406 669 ;
-C 74 ; WX 500 ; N J ; B -46 -99 524 669 ;
-C 75 ; WX 667 ; N K ; B -21 0 702 669 ;
-C 76 ; WX 611 ; N L ; B -22 0 590 669 ;
-C 77 ; WX 889 ; N M ; B -29 -12 917 669 ;
-C 78 ; WX 722 ; N N ; B -27 -15 748 669 ;
-C 79 ; WX 722 ; N O ; B 27 -18 691 685 ;
-C 80 ; WX 611 ; N P ; B -27 0 613 669 ;
-C 81 ; WX 722 ; N Q ; B 27 -208 691 685 ;
-C 82 ; WX 667 ; N R ; B -29 0 623 669 ;
-C 83 ; WX 556 ; N S ; B 2 -18 526 685 ;
-C 84 ; WX 611 ; N T ; B 50 0 650 669 ;
-C 85 ; WX 722 ; N U ; B 67 -18 744 669 ;
-C 86 ; WX 667 ; N V ; B 65 -18 715 669 ;
-C 87 ; WX 889 ; N W ; B 65 -18 940 669 ;
-C 88 ; WX 667 ; N X ; B -24 0 694 669 ;
-C 89 ; WX 611 ; N Y ; B 73 0 659 669 ;
-C 90 ; WX 611 ; N Z ; B -11 0 590 669 ;
-C 91 ; WX 333 ; N bracketleft ; B -37 -159 362 674 ;
-C 92 ; WX 278 ; N backslash ; B -1 -18 279 685 ;
-C 93 ; WX 333 ; N bracketright ; B -56 -157 343 674 ;
-C 94 ; WX 570 ; N asciicircum ; B 67 304 503 669 ;
-C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
-C 96 ; WX 333 ; N quoteleft ; B 128 369 332 685 ;
-C 97 ; WX 500 ; N a ; B -21 -14 455 462 ;
-C 98 ; WX 500 ; N b ; B -14 -13 444 699 ;
-C 99 ; WX 444 ; N c ; B -5 -13 392 462 ;
-C 100 ; WX 500 ; N d ; B -21 -13 517 699 ;
-C 101 ; WX 444 ; N e ; B 5 -13 398 462 ;
-C 102 ; WX 333 ; N f ; B -169 -205 446 698 ; L i fi ; L l fl ;
-C 103 ; WX 500 ; N g ; B -52 -203 478 462 ;
-C 104 ; WX 556 ; N h ; B -13 -9 498 699 ;
-C 105 ; WX 278 ; N i ; B 2 -9 263 684 ;
-C 106 ; WX 278 ; N j ; B -189 -207 279 684 ;
-C 107 ; WX 500 ; N k ; B -23 -8 483 699 ;
-C 108 ; WX 278 ; N l ; B 2 -9 290 699 ;
-C 109 ; WX 778 ; N m ; B -14 -9 722 462 ;
-C 110 ; WX 556 ; N n ; B -6 -9 493 462 ;
-C 111 ; WX 500 ; N o ; B -3 -13 441 462 ;
-C 112 ; WX 500 ; N p ; B -120 -205 446 462 ;
-C 113 ; WX 500 ; N q ; B 1 -205 471 462 ;
-C 114 ; WX 389 ; N r ; B -21 0 389 462 ;
-C 115 ; WX 389 ; N s ; B -19 -13 333 462 ;
-C 116 ; WX 278 ; N t ; B -11 -9 281 594 ;
-C 117 ; WX 556 ; N u ; B 15 -9 492 462 ;
-C 118 ; WX 444 ; N v ; B 16 -13 401 462 ;
-C 119 ; WX 667 ; N w ; B 16 -13 614 462 ;
-C 120 ; WX 500 ; N x ; B -46 -13 469 462 ;
-C 121 ; WX 444 ; N y ; B -94 -205 392 462 ;
-C 122 ; WX 389 ; N z ; B -43 -78 368 449 ;
-C 123 ; WX 348 ; N braceleft ; B 5 -187 436 686 ;
-C 124 ; WX 220 ; N bar ; B 66 -218 154 782 ;
-C 125 ; WX 348 ; N braceright ; B -129 -187 302 686 ;
-C 126 ; WX 570 ; N asciitilde ; B 54 173 516 333 ;
-C 161 ; WX 389 ; N exclamdown ; B 19 -205 322 492 ;
-C 162 ; WX 500 ; N cent ; B 42 -143 439 576 ;
-C 163 ; WX 500 ; N sterling ; B -32 -12 510 683 ;
-C 164 ; WX 167 ; N fraction ; B -169 -14 324 683 ;
-C 165 ; WX 500 ; N yen ; B 33 0 628 669 ;
-C 166 ; WX 500 ; N florin ; B -87 -156 537 707 ;
-C 167 ; WX 500 ; N section ; B 36 -143 459 685 ;
-C 168 ; WX 500 ; N currency ; B -26 34 526 586 ;
-C 169 ; WX 278 ; N quotesingle ; B 128 398 268 685 ;
-C 170 ; WX 500 ; N quotedblleft ; B 53 369 513 685 ;
-C 171 ; WX 500 ; N guillemotleft ; B 12 32 468 415 ;
-C 172 ; WX 333 ; N guilsinglleft ; B 32 32 303 415 ;
-C 173 ; WX 333 ; N guilsinglright ; B 10 32 281 415 ;
-C 174 ; WX 556 ; N fi ; B -188 -205 514 703 ;
-C 175 ; WX 556 ; N fl ; B -186 -205 553 704 ;
-C 177 ; WX 500 ; N endash ; B -40 178 477 269 ;
-C 178 ; WX 500 ; N dagger ; B 91 -145 494 685 ;
-C 179 ; WX 500 ; N daggerdbl ; B 10 -139 493 685 ;
-C 180 ; WX 250 ; N periodcentered ; B 51 257 199 405 ;
-C 182 ; WX 500 ; N paragraph ; B -57 -193 562 669 ;
-C 183 ; WX 350 ; N bullet ; B 0 175 350 525 ;
-C 184 ; WX 333 ; N quotesinglbase ; B -5 -182 199 134 ;
-C 185 ; WX 500 ; N quotedblbase ; B -57 -182 403 134 ;
-C 186 ; WX 500 ; N quotedblright ; B 53 369 513 685 ;
-C 187 ; WX 500 ; N guillemotright ; B 12 32 468 415 ;
-C 188 ; WX 1000 ; N ellipsis ; B 40 -13 852 135 ;
-C 189 ; WX 1000 ; N perthousand ; B 7 -29 996 706 ;
-C 191 ; WX 500 ; N questiondown ; B 30 -205 421 492 ;
-C 193 ; WX 333 ; N grave ; B 85 516 297 697 ;
-C 194 ; WX 333 ; N acute ; B 139 516 379 697 ;
-C 195 ; WX 333 ; N circumflex ; B 40 516 367 690 ;
-C 196 ; WX 333 ; N tilde ; B 48 536 407 655 ;
-C 197 ; WX 333 ; N macron ; B 51 553 393 623 ;
-C 198 ; WX 333 ; N breve ; B 71 516 387 678 ;
-C 199 ; WX 333 ; N dotaccent ; B 163 550 298 684 ;
-C 200 ; WX 333 ; N dieresis ; B 55 550 402 684 ;
-C 202 ; WX 333 ; N ring ; B 127 516 340 729 ;
-C 203 ; WX 333 ; N cedilla ; B -80 -218 156 5 ;
-C 205 ; WX 333 ; N hungarumlaut ; B 69 516 498 697 ;
-C 206 ; WX 333 ; N ogonek ; B 15 -183 244 34 ;
-C 207 ; WX 333 ; N caron ; B 79 516 411 690 ;
-C 208 ; WX 1000 ; N emdash ; B -40 178 977 269 ;
-C 225 ; WX 944 ; N AE ; B -64 0 918 669 ;
-C 227 ; WX 266 ; N ordfeminine ; B 16 399 330 685 ;
-C 232 ; WX 611 ; N Lslash ; B -22 0 590 669 ;
-C 233 ; WX 722 ; N Oslash ; B 27 -125 691 764 ;
-C 234 ; WX 944 ; N OE ; B 23 -8 946 677 ;
-C 235 ; WX 300 ; N ordmasculine ; B 56 400 347 685 ;
-C 241 ; WX 722 ; N ae ; B -5 -13 673 462 ;
-C 245 ; WX 278 ; N dotlessi ; B 2 -9 238 462 ;
-C 248 ; WX 278 ; N lslash ; B -7 -9 307 699 ;
-C 249 ; WX 500 ; N oslash ; B -3 -119 441 560 ;
-C 250 ; WX 722 ; N oe ; B 6 -13 674 462 ;
-C 251 ; WX 500 ; N germandbls ; B -200 -200 473 705 ;
-C -1 ; WX 389 ; N Idieresis ; B -32 0 450 862 ;
-C -1 ; WX 444 ; N eacute ; B 5 -13 435 697 ;
-C -1 ; WX 500 ; N abreve ; B -21 -14 471 678 ;
-C -1 ; WX 556 ; N uhungarumlaut ; B 15 -9 610 697 ;
-C -1 ; WX 444 ; N ecaron ; B 5 -13 467 690 ;
-C -1 ; WX 611 ; N Ydieresis ; B 73 0 659 862 ;
-C -1 ; WX 570 ; N divide ; B 33 -29 537 535 ;
-C -1 ; WX 611 ; N Yacute ; B 73 0 659 904 ;
-C -1 ; WX 667 ; N Acircumflex ; B -67 0 593 897 ;
-C -1 ; WX 500 ; N aacute ; B -21 -14 463 697 ;
-C -1 ; WX 722 ; N Ucircumflex ; B 67 -18 744 897 ;
-C -1 ; WX 444 ; N yacute ; B -94 -205 435 697 ;
-C -1 ; WX 389 ; N scommaaccent ; B -19 -218 333 462 ;
-C -1 ; WX 444 ; N ecircumflex ; B 5 -13 423 690 ;
-C -1 ; WX 722 ; N Uring ; B 67 -18 744 921 ;
-C -1 ; WX 722 ; N Udieresis ; B 67 -18 744 862 ;
-C -1 ; WX 500 ; N aogonek ; B -21 -183 455 462 ;
-C -1 ; WX 722 ; N Uacute ; B 67 -18 744 904 ;
-C -1 ; WX 556 ; N uogonek ; B 15 -183 492 462 ;
-C -1 ; WX 667 ; N Edieresis ; B -27 0 653 862 ;
-C -1 ; WX 722 ; N Dcroat ; B -31 0 700 669 ;
-C -1 ; WX 250 ; N commaaccent ; B -36 -218 131 -50 ;
-C -1 ; WX 747 ; N copyright ; B 30 -18 718 685 ;
-C -1 ; WX 667 ; N Emacron ; B -27 0 653 830 ;
-C -1 ; WX 444 ; N ccaron ; B -5 -13 467 690 ;
-C -1 ; WX 500 ; N aring ; B -21 -14 455 729 ;
-C -1 ; WX 722 ; N Ncommaaccent ; B -27 -218 748 669 ;
-C -1 ; WX 278 ; N lacute ; B 2 -9 392 904 ;
-C -1 ; WX 500 ; N agrave ; B -21 -14 455 697 ;
-C -1 ; WX 611 ; N Tcommaaccent ; B 50 -218 650 669 ;
-C -1 ; WX 667 ; N Cacute ; B 32 -18 677 904 ;
-C -1 ; WX 500 ; N atilde ; B -21 -14 491 655 ;
-C -1 ; WX 667 ; N Edotaccent ; B -27 0 653 862 ;
-C -1 ; WX 389 ; N scaron ; B -19 -13 424 690 ;
-C -1 ; WX 389 ; N scedilla ; B -19 -218 333 462 ;
-C -1 ; WX 278 ; N iacute ; B 2 -9 352 697 ;
-C -1 ; WX 494 ; N lozenge ; B 10 0 484 745 ;
-C -1 ; WX 667 ; N Rcaron ; B -29 0 623 897 ;
-C -1 ; WX 722 ; N Gcommaaccent ; B 21 -218 706 685 ;
-C -1 ; WX 556 ; N ucircumflex ; B 15 -9 492 690 ;
-C -1 ; WX 500 ; N acircumflex ; B -21 -14 455 690 ;
-C -1 ; WX 667 ; N Amacron ; B -67 0 593 830 ;
-C -1 ; WX 389 ; N rcaron ; B -21 0 424 690 ;
-C -1 ; WX 444 ; N ccedilla ; B -5 -218 392 462 ;
-C -1 ; WX 611 ; N Zdotaccent ; B -11 0 590 862 ;
-C -1 ; WX 611 ; N Thorn ; B -27 0 573 669 ;
-C -1 ; WX 722 ; N Omacron ; B 27 -18 691 830 ;
-C -1 ; WX 667 ; N Racute ; B -29 0 623 904 ;
-C -1 ; WX 556 ; N Sacute ; B 2 -18 531 904 ;
-C -1 ; WX 608 ; N dcaron ; B -21 -13 675 708 ;
-C -1 ; WX 722 ; N Umacron ; B 67 -18 744 830 ;
-C -1 ; WX 556 ; N uring ; B 15 -9 492 729 ;
-C -1 ; WX 300 ; N threesuperior ; B 17 265 321 683 ;
-C -1 ; WX 722 ; N Ograve ; B 27 -18 691 904 ;
-C -1 ; WX 667 ; N Agrave ; B -67 0 593 904 ;
-C -1 ; WX 667 ; N Abreve ; B -67 0 593 885 ;
-C -1 ; WX 570 ; N multiply ; B 48 16 522 490 ;
-C -1 ; WX 556 ; N uacute ; B 15 -9 492 697 ;
-C -1 ; WX 611 ; N Tcaron ; B 50 0 650 897 ;
-C -1 ; WX 494 ; N partialdiff ; B 11 -21 494 750 ;
-C -1 ; WX 444 ; N ydieresis ; B -94 -205 443 655 ;
-C -1 ; WX 722 ; N Nacute ; B -27 -15 748 904 ;
-C -1 ; WX 278 ; N icircumflex ; B -3 -9 324 690 ;
-C -1 ; WX 667 ; N Ecircumflex ; B -27 0 653 897 ;
-C -1 ; WX 500 ; N adieresis ; B -21 -14 476 655 ;
-C -1 ; WX 444 ; N edieresis ; B 5 -13 448 655 ;
-C -1 ; WX 444 ; N cacute ; B -5 -13 435 697 ;
-C -1 ; WX 556 ; N nacute ; B -6 -9 493 697 ;
-C -1 ; WX 556 ; N umacron ; B 15 -9 492 623 ;
-C -1 ; WX 722 ; N Ncaron ; B -27 -15 748 897 ;
-C -1 ; WX 389 ; N Iacute ; B -32 0 432 904 ;
-C -1 ; WX 570 ; N plusminus ; B 33 0 537 506 ;
-C -1 ; WX 220 ; N brokenbar ; B 66 -143 154 707 ;
-C -1 ; WX 747 ; N registered ; B 30 -18 718 685 ;
-C -1 ; WX 722 ; N Gbreve ; B 21 -18 706 885 ;
-C -1 ; WX 389 ; N Idotaccent ; B -32 0 406 862 ;
-C -1 ; WX 600 ; N summation ; B 14 -10 585 706 ;
-C -1 ; WX 667 ; N Egrave ; B -27 0 653 904 ;
-C -1 ; WX 389 ; N racute ; B -21 0 407 697 ;
-C -1 ; WX 500 ; N omacron ; B -3 -13 462 623 ;
-C -1 ; WX 611 ; N Zacute ; B -11 0 590 904 ;
-C -1 ; WX 611 ; N Zcaron ; B -11 0 590 897 ;
-C -1 ; WX 549 ; N greaterequal ; B 26 0 523 704 ;
-C -1 ; WX 722 ; N Eth ; B -31 0 700 669 ;
-C -1 ; WX 667 ; N Ccedilla ; B 32 -218 677 685 ;
-C -1 ; WX 278 ; N lcommaaccent ; B -42 -218 290 699 ;
-C -1 ; WX 366 ; N tcaron ; B -11 -9 434 754 ;
-C -1 ; WX 444 ; N eogonek ; B 5 -183 398 462 ;
-C -1 ; WX 722 ; N Uogonek ; B 67 -183 744 669 ;
-C -1 ; WX 667 ; N Aacute ; B -67 0 593 904 ;
-C -1 ; WX 667 ; N Adieresis ; B -67 0 593 862 ;
-C -1 ; WX 444 ; N egrave ; B 5 -13 398 697 ;
-C -1 ; WX 389 ; N zacute ; B -43 -78 407 697 ;
-C -1 ; WX 278 ; N iogonek ; B -20 -183 263 684 ;
-C -1 ; WX 722 ; N Oacute ; B 27 -18 691 904 ;
-C -1 ; WX 500 ; N oacute ; B -3 -13 463 697 ;
-C -1 ; WX 500 ; N amacron ; B -21 -14 467 623 ;
-C -1 ; WX 389 ; N sacute ; B -19 -13 407 697 ;
-C -1 ; WX 278 ; N idieresis ; B 2 -9 364 655 ;
-C -1 ; WX 722 ; N Ocircumflex ; B 27 -18 691 897 ;
-C -1 ; WX 722 ; N Ugrave ; B 67 -18 744 904 ;
-C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
-C -1 ; WX 500 ; N thorn ; B -120 -205 446 699 ;
-C -1 ; WX 300 ; N twosuperior ; B 2 274 313 683 ;
-C -1 ; WX 722 ; N Odieresis ; B 27 -18 691 862 ;
-C -1 ; WX 576 ; N mu ; B -60 -207 516 449 ;
-C -1 ; WX 278 ; N igrave ; B 2 -9 259 697 ;
-C -1 ; WX 500 ; N ohungarumlaut ; B -3 -13 582 697 ;
-C -1 ; WX 667 ; N Eogonek ; B -27 -183 653 669 ;
-C -1 ; WX 500 ; N dcroat ; B -21 -13 552 699 ;
-C -1 ; WX 750 ; N threequarters ; B 7 -14 726 683 ;
-C -1 ; WX 556 ; N Scedilla ; B 2 -218 526 685 ;
-C -1 ; WX 382 ; N lcaron ; B 2 -9 448 708 ;
-C -1 ; WX 667 ; N Kcommaaccent ; B -21 -218 702 669 ;
-C -1 ; WX 611 ; N Lacute ; B -22 0 590 904 ;
-C -1 ; WX 1000 ; N trademark ; B 32 263 968 669 ;
-C -1 ; WX 444 ; N edotaccent ; B 5 -13 398 655 ;
-C -1 ; WX 389 ; N Igrave ; B -32 0 406 904 ;
-C -1 ; WX 389 ; N Imacron ; B -32 0 461 830 ;
-C -1 ; WX 611 ; N Lcaron ; B -22 0 671 718 ;
-C -1 ; WX 750 ; N onehalf ; B -9 -14 723 683 ;
-C -1 ; WX 549 ; N lessequal ; B 29 0 526 704 ;
-C -1 ; WX 500 ; N ocircumflex ; B -3 -13 451 690 ;
-C -1 ; WX 556 ; N ntilde ; B -6 -9 504 655 ;
-C -1 ; WX 722 ; N Uhungarumlaut ; B 67 -18 744 904 ;
-C -1 ; WX 667 ; N Eacute ; B -27 0 653 904 ;
-C -1 ; WX 444 ; N emacron ; B 5 -13 439 623 ;
-C -1 ; WX 500 ; N gbreve ; B -52 -203 478 678 ;
-C -1 ; WX 750 ; N onequarter ; B 7 -14 721 683 ;
-C -1 ; WX 556 ; N Scaron ; B 2 -18 553 897 ;
-C -1 ; WX 556 ; N Scommaaccent ; B 2 -218 526 685 ;
-C -1 ; WX 722 ; N Ohungarumlaut ; B 27 -18 723 904 ;
-C -1 ; WX 400 ; N degree ; B 83 397 369 683 ;
-C -1 ; WX 500 ; N ograve ; B -3 -13 441 697 ;
-C -1 ; WX 667 ; N Ccaron ; B 32 -18 677 897 ;
-C -1 ; WX 556 ; N ugrave ; B 15 -9 492 697 ;
-C -1 ; WX 549 ; N radical ; B 10 -46 512 850 ;
-C -1 ; WX 722 ; N Dcaron ; B -46 0 685 897 ;
-C -1 ; WX 389 ; N rcommaaccent ; B -67 -218 389 462 ;
-C -1 ; WX 722 ; N Ntilde ; B -27 -15 748 862 ;
-C -1 ; WX 500 ; N otilde ; B -3 -13 491 655 ;
-C -1 ; WX 667 ; N Rcommaaccent ; B -29 -218 623 669 ;
-C -1 ; WX 611 ; N Lcommaaccent ; B -22 -218 590 669 ;
-C -1 ; WX 667 ; N Atilde ; B -67 0 593 862 ;
-C -1 ; WX 667 ; N Aogonek ; B -67 -183 604 683 ;
-C -1 ; WX 667 ; N Aring ; B -67 0 593 921 ;
-C -1 ; WX 722 ; N Otilde ; B 27 -18 691 862 ;
-C -1 ; WX 389 ; N zdotaccent ; B -43 -78 368 655 ;
-C -1 ; WX 667 ; N Ecaron ; B -27 0 653 897 ;
-C -1 ; WX 389 ; N Iogonek ; B -32 -183 406 669 ;
-C -1 ; WX 500 ; N kcommaaccent ; B -23 -218 483 699 ;
-C -1 ; WX 606 ; N minus ; B 51 209 555 297 ;
-C -1 ; WX 389 ; N Icircumflex ; B -32 0 450 897 ;
-C -1 ; WX 556 ; N ncaron ; B -6 -9 523 690 ;
-C -1 ; WX 278 ; N tcommaaccent ; B -62 -218 281 594 ;
-C -1 ; WX 606 ; N logicalnot ; B 51 108 555 399 ;
-C -1 ; WX 500 ; N odieresis ; B -3 -13 471 655 ;
-C -1 ; WX 556 ; N udieresis ; B 15 -9 499 655 ;
-C -1 ; WX 549 ; N notequal ; B 15 -49 540 570 ;
-C -1 ; WX 500 ; N gcommaaccent ; B -52 -203 478 767 ;
-C -1 ; WX 500 ; N eth ; B -3 -13 454 699 ;
-C -1 ; WX 389 ; N zcaron ; B -43 -78 424 690 ;
-C -1 ; WX 556 ; N ncommaaccent ; B -6 -218 493 462 ;
-C -1 ; WX 300 ; N onesuperior ; B 30 274 301 683 ;
-C -1 ; WX 278 ; N imacron ; B 2 -9 294 623 ;
-C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ;
-EndCharMetrics
-StartKernData
-StartKernPairs 2038
-KPX A C -65
-KPX A Cacute -65
-KPX A Ccaron -65
-KPX A Ccedilla -65
-KPX A G -60
-KPX A Gbreve -60
-KPX A Gcommaaccent -60
-KPX A O -50
-KPX A Oacute -50
-KPX A Ocircumflex -50
-KPX A Odieresis -50
-KPX A Ograve -50
-KPX A Ohungarumlaut -50
-KPX A Omacron -50
-KPX A Oslash -50
-KPX A Otilde -50
-KPX A Q -55
-KPX A T -55
-KPX A Tcaron -55
-KPX A Tcommaaccent -55
-KPX A U -50
-KPX A Uacute -50
-KPX A Ucircumflex -50
-KPX A Udieresis -50
-KPX A Ugrave -50
-KPX A Uhungarumlaut -50
-KPX A Umacron -50
-KPX A Uogonek -50
-KPX A Uring -50
-KPX A V -95
-KPX A W -100
-KPX A Y -70
-KPX A Yacute -70
-KPX A Ydieresis -70
-KPX A quoteright -74
-KPX A u -30
-KPX A uacute -30
-KPX A ucircumflex -30
-KPX A udieresis -30
-KPX A ugrave -30
-KPX A uhungarumlaut -30
-KPX A umacron -30
-KPX A uogonek -30
-KPX A uring -30
-KPX A v -74
-KPX A w -74
-KPX A y -74
-KPX A yacute -74
-KPX A ydieresis -74
-KPX Aacute C -65
-KPX Aacute Cacute -65
-KPX Aacute Ccaron -65
-KPX Aacute Ccedilla -65
-KPX Aacute G -60
-KPX Aacute Gbreve -60
-KPX Aacute Gcommaaccent -60
-KPX Aacute O -50
-KPX Aacute Oacute -50
-KPX Aacute Ocircumflex -50
-KPX Aacute Odieresis -50
-KPX Aacute Ograve -50
-KPX Aacute Ohungarumlaut -50
-KPX Aacute Omacron -50
-KPX Aacute Oslash -50
-KPX Aacute Otilde -50
-KPX Aacute Q -55
-KPX Aacute T -55
-KPX Aacute Tcaron -55
-KPX Aacute Tcommaaccent -55
-KPX Aacute U -50
-KPX Aacute Uacute -50
-KPX Aacute Ucircumflex -50
-KPX Aacute Udieresis -50
-KPX Aacute Ugrave -50
-KPX Aacute Uhungarumlaut -50
-KPX Aacute Umacron -50
-KPX Aacute Uogonek -50
-KPX Aacute Uring -50
-KPX Aacute V -95
-KPX Aacute W -100
-KPX Aacute Y -70
-KPX Aacute Yacute -70
-KPX Aacute Ydieresis -70
-KPX Aacute quoteright -74
-KPX Aacute u -30
-KPX Aacute uacute -30
-KPX Aacute ucircumflex -30
-KPX Aacute udieresis -30
-KPX Aacute ugrave -30
-KPX Aacute uhungarumlaut -30
-KPX Aacute umacron -30
-KPX Aacute uogonek -30
-KPX Aacute uring -30
-KPX Aacute v -74
-KPX Aacute w -74
-KPX Aacute y -74
-KPX Aacute yacute -74
-KPX Aacute ydieresis -74
-KPX Abreve C -65
-KPX Abreve Cacute -65
-KPX Abreve Ccaron -65
-KPX Abreve Ccedilla -65
-KPX Abreve G -60
-KPX Abreve Gbreve -60
-KPX Abreve Gcommaaccent -60
-KPX Abreve O -50
-KPX Abreve Oacute -50
-KPX Abreve Ocircumflex -50
-KPX Abreve Odieresis -50
-KPX Abreve Ograve -50
-KPX Abreve Ohungarumlaut -50
-KPX Abreve Omacron -50
-KPX Abreve Oslash -50
-KPX Abreve Otilde -50
-KPX Abreve Q -55
-KPX Abreve T -55
-KPX Abreve Tcaron -55
-KPX Abreve Tcommaaccent -55
-KPX Abreve U -50
-KPX Abreve Uacute -50
-KPX Abreve Ucircumflex -50
-KPX Abreve Udieresis -50
-KPX Abreve Ugrave -50
-KPX Abreve Uhungarumlaut -50
-KPX Abreve Umacron -50
-KPX Abreve Uogonek -50
-KPX Abreve Uring -50
-KPX Abreve V -95
-KPX Abreve W -100
-KPX Abreve Y -70
-KPX Abreve Yacute -70
-KPX Abreve Ydieresis -70
-KPX Abreve quoteright -74
-KPX Abreve u -30
-KPX Abreve uacute -30
-KPX Abreve ucircumflex -30
-KPX Abreve udieresis -30
-KPX Abreve ugrave -30
-KPX Abreve uhungarumlaut -30
-KPX Abreve umacron -30
-KPX Abreve uogonek -30
-KPX Abreve uring -30
-KPX Abreve v -74
-KPX Abreve w -74
-KPX Abreve y -74
-KPX Abreve yacute -74
-KPX Abreve ydieresis -74
-KPX Acircumflex C -65
-KPX Acircumflex Cacute -65
-KPX Acircumflex Ccaron -65
-KPX Acircumflex Ccedilla -65
-KPX Acircumflex G -60
-KPX Acircumflex Gbreve -60
-KPX Acircumflex Gcommaaccent -60
-KPX Acircumflex O -50
-KPX Acircumflex Oacute -50
-KPX Acircumflex Ocircumflex -50
-KPX Acircumflex Odieresis -50
-KPX Acircumflex Ograve -50
-KPX Acircumflex Ohungarumlaut -50
-KPX Acircumflex Omacron -50
-KPX Acircumflex Oslash -50
-KPX Acircumflex Otilde -50
-KPX Acircumflex Q -55
-KPX Acircumflex T -55
-KPX Acircumflex Tcaron -55
-KPX Acircumflex Tcommaaccent -55
-KPX Acircumflex U -50
-KPX Acircumflex Uacute -50
-KPX Acircumflex Ucircumflex -50
-KPX Acircumflex Udieresis -50
-KPX Acircumflex Ugrave -50
-KPX Acircumflex Uhungarumlaut -50
-KPX Acircumflex Umacron -50
-KPX Acircumflex Uogonek -50
-KPX Acircumflex Uring -50
-KPX Acircumflex V -95
-KPX Acircumflex W -100
-KPX Acircumflex Y -70
-KPX Acircumflex Yacute -70
-KPX Acircumflex Ydieresis -70
-KPX Acircumflex quoteright -74
-KPX Acircumflex u -30
-KPX Acircumflex uacute -30
-KPX Acircumflex ucircumflex -30
-KPX Acircumflex udieresis -30
-KPX Acircumflex ugrave -30
-KPX Acircumflex uhungarumlaut -30
-KPX Acircumflex umacron -30
-KPX Acircumflex uogonek -30
-KPX Acircumflex uring -30
-KPX Acircumflex v -74
-KPX Acircumflex w -74
-KPX Acircumflex y -74
-KPX Acircumflex yacute -74
-KPX Acircumflex ydieresis -74
-KPX Adieresis C -65
-KPX Adieresis Cacute -65
-KPX Adieresis Ccaron -65
-KPX Adieresis Ccedilla -65
-KPX Adieresis G -60
-KPX Adieresis Gbreve -60
-KPX Adieresis Gcommaaccent -60
-KPX Adieresis O -50
-KPX Adieresis Oacute -50
-KPX Adieresis Ocircumflex -50
-KPX Adieresis Odieresis -50
-KPX Adieresis Ograve -50
-KPX Adieresis Ohungarumlaut -50
-KPX Adieresis Omacron -50
-KPX Adieresis Oslash -50
-KPX Adieresis Otilde -50
-KPX Adieresis Q -55
-KPX Adieresis T -55
-KPX Adieresis Tcaron -55
-KPX Adieresis Tcommaaccent -55
-KPX Adieresis U -50
-KPX Adieresis Uacute -50
-KPX Adieresis Ucircumflex -50
-KPX Adieresis Udieresis -50
-KPX Adieresis Ugrave -50
-KPX Adieresis Uhungarumlaut -50
-KPX Adieresis Umacron -50
-KPX Adieresis Uogonek -50
-KPX Adieresis Uring -50
-KPX Adieresis V -95
-KPX Adieresis W -100
-KPX Adieresis Y -70
-KPX Adieresis Yacute -70
-KPX Adieresis Ydieresis -70
-KPX Adieresis quoteright -74
-KPX Adieresis u -30
-KPX Adieresis uacute -30
-KPX Adieresis ucircumflex -30
-KPX Adieresis udieresis -30
-KPX Adieresis ugrave -30
-KPX Adieresis uhungarumlaut -30
-KPX Adieresis umacron -30
-KPX Adieresis uogonek -30
-KPX Adieresis uring -30
-KPX Adieresis v -74
-KPX Adieresis w -74
-KPX Adieresis y -74
-KPX Adieresis yacute -74
-KPX Adieresis ydieresis -74
-KPX Agrave C -65
-KPX Agrave Cacute -65
-KPX Agrave Ccaron -65
-KPX Agrave Ccedilla -65
-KPX Agrave G -60
-KPX Agrave Gbreve -60
-KPX Agrave Gcommaaccent -60
-KPX Agrave O -50
-KPX Agrave Oacute -50
-KPX Agrave Ocircumflex -50
-KPX Agrave Odieresis -50
-KPX Agrave Ograve -50
-KPX Agrave Ohungarumlaut -50
-KPX Agrave Omacron -50
-KPX Agrave Oslash -50
-KPX Agrave Otilde -50
-KPX Agrave Q -55
-KPX Agrave T -55
-KPX Agrave Tcaron -55
-KPX Agrave Tcommaaccent -55
-KPX Agrave U -50
-KPX Agrave Uacute -50
-KPX Agrave Ucircumflex -50
-KPX Agrave Udieresis -50
-KPX Agrave Ugrave -50
-KPX Agrave Uhungarumlaut -50
-KPX Agrave Umacron -50
-KPX Agrave Uogonek -50
-KPX Agrave Uring -50
-KPX Agrave V -95
-KPX Agrave W -100
-KPX Agrave Y -70
-KPX Agrave Yacute -70
-KPX Agrave Ydieresis -70
-KPX Agrave quoteright -74
-KPX Agrave u -30
-KPX Agrave uacute -30
-KPX Agrave ucircumflex -30
-KPX Agrave udieresis -30
-KPX Agrave ugrave -30
-KPX Agrave uhungarumlaut -30
-KPX Agrave umacron -30
-KPX Agrave uogonek -30
-KPX Agrave uring -30
-KPX Agrave v -74
-KPX Agrave w -74
-KPX Agrave y -74
-KPX Agrave yacute -74
-KPX Agrave ydieresis -74
-KPX Amacron C -65
-KPX Amacron Cacute -65
-KPX Amacron Ccaron -65
-KPX Amacron Ccedilla -65
-KPX Amacron G -60
-KPX Amacron Gbreve -60
-KPX Amacron Gcommaaccent -60
-KPX Amacron O -50
-KPX Amacron Oacute -50
-KPX Amacron Ocircumflex -50
-KPX Amacron Odieresis -50
-KPX Amacron Ograve -50
-KPX Amacron Ohungarumlaut -50
-KPX Amacron Omacron -50
-KPX Amacron Oslash -50
-KPX Amacron Otilde -50
-KPX Amacron Q -55
-KPX Amacron T -55
-KPX Amacron Tcaron -55
-KPX Amacron Tcommaaccent -55
-KPX Amacron U -50
-KPX Amacron Uacute -50
-KPX Amacron Ucircumflex -50
-KPX Amacron Udieresis -50
-KPX Amacron Ugrave -50
-KPX Amacron Uhungarumlaut -50
-KPX Amacron Umacron -50
-KPX Amacron Uogonek -50
-KPX Amacron Uring -50
-KPX Amacron V -95
-KPX Amacron W -100
-KPX Amacron Y -70
-KPX Amacron Yacute -70
-KPX Amacron Ydieresis -70
-KPX Amacron quoteright -74
-KPX Amacron u -30
-KPX Amacron uacute -30
-KPX Amacron ucircumflex -30
-KPX Amacron udieresis -30
-KPX Amacron ugrave -30
-KPX Amacron uhungarumlaut -30
-KPX Amacron umacron -30
-KPX Amacron uogonek -30
-KPX Amacron uring -30
-KPX Amacron v -74
-KPX Amacron w -74
-KPX Amacron y -74
-KPX Amacron yacute -74
-KPX Amacron ydieresis -74
-KPX Aogonek C -65
-KPX Aogonek Cacute -65
-KPX Aogonek Ccaron -65
-KPX Aogonek Ccedilla -65
-KPX Aogonek G -60
-KPX Aogonek Gbreve -60
-KPX Aogonek Gcommaaccent -60
-KPX Aogonek O -50
-KPX Aogonek Oacute -50
-KPX Aogonek Ocircumflex -50
-KPX Aogonek Odieresis -50
-KPX Aogonek Ograve -50
-KPX Aogonek Ohungarumlaut -50
-KPX Aogonek Omacron -50
-KPX Aogonek Oslash -50
-KPX Aogonek Otilde -50
-KPX Aogonek Q -55
-KPX Aogonek T -55
-KPX Aogonek Tcaron -55
-KPX Aogonek Tcommaaccent -55
-KPX Aogonek U -50
-KPX Aogonek Uacute -50
-KPX Aogonek Ucircumflex -50
-KPX Aogonek Udieresis -50
-KPX Aogonek Ugrave -50
-KPX Aogonek Uhungarumlaut -50
-KPX Aogonek Umacron -50
-KPX Aogonek Uogonek -50
-KPX Aogonek Uring -50
-KPX Aogonek V -95
-KPX Aogonek W -100
-KPX Aogonek Y -70
-KPX Aogonek Yacute -70
-KPX Aogonek Ydieresis -70
-KPX Aogonek quoteright -74
-KPX Aogonek u -30
-KPX Aogonek uacute -30
-KPX Aogonek ucircumflex -30
-KPX Aogonek udieresis -30
-KPX Aogonek ugrave -30
-KPX Aogonek uhungarumlaut -30
-KPX Aogonek umacron -30
-KPX Aogonek uogonek -30
-KPX Aogonek uring -30
-KPX Aogonek v -74
-KPX Aogonek w -74
-KPX Aogonek y -34
-KPX Aogonek yacute -34
-KPX Aogonek ydieresis -34
-KPX Aring C -65
-KPX Aring Cacute -65
-KPX Aring Ccaron -65
-KPX Aring Ccedilla -65
-KPX Aring G -60
-KPX Aring Gbreve -60
-KPX Aring Gcommaaccent -60
-KPX Aring O -50
-KPX Aring Oacute -50
-KPX Aring Ocircumflex -50
-KPX Aring Odieresis -50
-KPX Aring Ograve -50
-KPX Aring Ohungarumlaut -50
-KPX Aring Omacron -50
-KPX Aring Oslash -50
-KPX Aring Otilde -50
-KPX Aring Q -55
-KPX Aring T -55
-KPX Aring Tcaron -55
-KPX Aring Tcommaaccent -55
-KPX Aring U -50
-KPX Aring Uacute -50
-KPX Aring Ucircumflex -50
-KPX Aring Udieresis -50
-KPX Aring Ugrave -50
-KPX Aring Uhungarumlaut -50
-KPX Aring Umacron -50
-KPX Aring Uogonek -50
-KPX Aring Uring -50
-KPX Aring V -95
-KPX Aring W -100
-KPX Aring Y -70
-KPX Aring Yacute -70
-KPX Aring Ydieresis -70
-KPX Aring quoteright -74
-KPX Aring u -30
-KPX Aring uacute -30
-KPX Aring ucircumflex -30
-KPX Aring udieresis -30
-KPX Aring ugrave -30
-KPX Aring uhungarumlaut -30
-KPX Aring umacron -30
-KPX Aring uogonek -30
-KPX Aring uring -30
-KPX Aring v -74
-KPX Aring w -74
-KPX Aring y -74
-KPX Aring yacute -74
-KPX Aring ydieresis -74
-KPX Atilde C -65
-KPX Atilde Cacute -65
-KPX Atilde Ccaron -65
-KPX Atilde Ccedilla -65
-KPX Atilde G -60
-KPX Atilde Gbreve -60
-KPX Atilde Gcommaaccent -60
-KPX Atilde O -50
-KPX Atilde Oacute -50
-KPX Atilde Ocircumflex -50
-KPX Atilde Odieresis -50
-KPX Atilde Ograve -50
-KPX Atilde Ohungarumlaut -50
-KPX Atilde Omacron -50
-KPX Atilde Oslash -50
-KPX Atilde Otilde -50
-KPX Atilde Q -55
-KPX Atilde T -55
-KPX Atilde Tcaron -55
-KPX Atilde Tcommaaccent -55
-KPX Atilde U -50
-KPX Atilde Uacute -50
-KPX Atilde Ucircumflex -50
-KPX Atilde Udieresis -50
-KPX Atilde Ugrave -50
-KPX Atilde Uhungarumlaut -50
-KPX Atilde Umacron -50
-KPX Atilde Uogonek -50
-KPX Atilde Uring -50
-KPX Atilde V -95
-KPX Atilde W -100
-KPX Atilde Y -70
-KPX Atilde Yacute -70
-KPX Atilde Ydieresis -70
-KPX Atilde quoteright -74
-KPX Atilde u -30
-KPX Atilde uacute -30
-KPX Atilde ucircumflex -30
-KPX Atilde udieresis -30
-KPX Atilde ugrave -30
-KPX Atilde uhungarumlaut -30
-KPX Atilde umacron -30
-KPX Atilde uogonek -30
-KPX Atilde uring -30
-KPX Atilde v -74
-KPX Atilde w -74
-KPX Atilde y -74
-KPX Atilde yacute -74
-KPX Atilde ydieresis -74
-KPX B A -25
-KPX B Aacute -25
-KPX B Abreve -25
-KPX B Acircumflex -25
-KPX B Adieresis -25
-KPX B Agrave -25
-KPX B Amacron -25
-KPX B Aogonek -25
-KPX B Aring -25
-KPX B Atilde -25
-KPX B U -10
-KPX B Uacute -10
-KPX B Ucircumflex -10
-KPX B Udieresis -10
-KPX B Ugrave -10
-KPX B Uhungarumlaut -10
-KPX B Umacron -10
-KPX B Uogonek -10
-KPX B Uring -10
-KPX D A -25
-KPX D Aacute -25
-KPX D Abreve -25
-KPX D Acircumflex -25
-KPX D Adieresis -25
-KPX D Agrave -25
-KPX D Amacron -25
-KPX D Aogonek -25
-KPX D Aring -25
-KPX D Atilde -25
-KPX D V -50
-KPX D W -40
-KPX D Y -50
-KPX D Yacute -50
-KPX D Ydieresis -50
-KPX Dcaron A -25
-KPX Dcaron Aacute -25
-KPX Dcaron Abreve -25
-KPX Dcaron Acircumflex -25
-KPX Dcaron Adieresis -25
-KPX Dcaron Agrave -25
-KPX Dcaron Amacron -25
-KPX Dcaron Aogonek -25
-KPX Dcaron Aring -25
-KPX Dcaron Atilde -25
-KPX Dcaron V -50
-KPX Dcaron W -40
-KPX Dcaron Y -50
-KPX Dcaron Yacute -50
-KPX Dcaron Ydieresis -50
-KPX Dcroat A -25
-KPX Dcroat Aacute -25
-KPX Dcroat Abreve -25
-KPX Dcroat Acircumflex -25
-KPX Dcroat Adieresis -25
-KPX Dcroat Agrave -25
-KPX Dcroat Amacron -25
-KPX Dcroat Aogonek -25
-KPX Dcroat Aring -25
-KPX Dcroat Atilde -25
-KPX Dcroat V -50
-KPX Dcroat W -40
-KPX Dcroat Y -50
-KPX Dcroat Yacute -50
-KPX Dcroat Ydieresis -50
-KPX F A -100
-KPX F Aacute -100
-KPX F Abreve -100
-KPX F Acircumflex -100
-KPX F Adieresis -100
-KPX F Agrave -100
-KPX F Amacron -100
-KPX F Aogonek -100
-KPX F Aring -100
-KPX F Atilde -100
-KPX F a -95
-KPX F aacute -95
-KPX F abreve -95
-KPX F acircumflex -95
-KPX F adieresis -95
-KPX F agrave -95
-KPX F amacron -95
-KPX F aogonek -95
-KPX F aring -95
-KPX F atilde -95
-KPX F comma -129
-KPX F e -100
-KPX F eacute -100
-KPX F ecaron -100
-KPX F ecircumflex -100
-KPX F edieresis -100
-KPX F edotaccent -100
-KPX F egrave -100
-KPX F emacron -100
-KPX F eogonek -100
-KPX F i -40
-KPX F iacute -40
-KPX F icircumflex -40
-KPX F idieresis -40
-KPX F igrave -40
-KPX F imacron -40
-KPX F iogonek -40
-KPX F o -70
-KPX F oacute -70
-KPX F ocircumflex -70
-KPX F odieresis -70
-KPX F ograve -70
-KPX F ohungarumlaut -70
-KPX F omacron -70
-KPX F oslash -70
-KPX F otilde -70
-KPX F period -129
-KPX F r -50
-KPX F racute -50
-KPX F rcaron -50
-KPX F rcommaaccent -50
-KPX J A -25
-KPX J Aacute -25
-KPX J Abreve -25
-KPX J Acircumflex -25
-KPX J Adieresis -25
-KPX J Agrave -25
-KPX J Amacron -25
-KPX J Aogonek -25
-KPX J Aring -25
-KPX J Atilde -25
-KPX J a -40
-KPX J aacute -40
-KPX J abreve -40
-KPX J acircumflex -40
-KPX J adieresis -40
-KPX J agrave -40
-KPX J amacron -40
-KPX J aogonek -40
-KPX J aring -40
-KPX J atilde -40
-KPX J comma -10
-KPX J e -40
-KPX J eacute -40
-KPX J ecaron -40
-KPX J ecircumflex -40
-KPX J edieresis -40
-KPX J edotaccent -40
-KPX J egrave -40
-KPX J emacron -40
-KPX J eogonek -40
-KPX J o -40
-KPX J oacute -40
-KPX J ocircumflex -40
-KPX J odieresis -40
-KPX J ograve -40
-KPX J ohungarumlaut -40
-KPX J omacron -40
-KPX J oslash -40
-KPX J otilde -40
-KPX J period -10
-KPX J u -40
-KPX J uacute -40
-KPX J ucircumflex -40
-KPX J udieresis -40
-KPX J ugrave -40
-KPX J uhungarumlaut -40
-KPX J umacron -40
-KPX J uogonek -40
-KPX J uring -40
-KPX K O -30
-KPX K Oacute -30
-KPX K Ocircumflex -30
-KPX K Odieresis -30
-KPX K Ograve -30
-KPX K Ohungarumlaut -30
-KPX K Omacron -30
-KPX K Oslash -30
-KPX K Otilde -30
-KPX K e -25
-KPX K eacute -25
-KPX K ecaron -25
-KPX K ecircumflex -25
-KPX K edieresis -25
-KPX K edotaccent -25
-KPX K egrave -25
-KPX K emacron -25
-KPX K eogonek -25
-KPX K o -25
-KPX K oacute -25
-KPX K ocircumflex -25
-KPX K odieresis -25
-KPX K ograve -25
-KPX K ohungarumlaut -25
-KPX K omacron -25
-KPX K oslash -25
-KPX K otilde -25
-KPX K u -20
-KPX K uacute -20
-KPX K ucircumflex -20
-KPX K udieresis -20
-KPX K ugrave -20
-KPX K uhungarumlaut -20
-KPX K umacron -20
-KPX K uogonek -20
-KPX K uring -20
-KPX K y -20
-KPX K yacute -20
-KPX K ydieresis -20
-KPX Kcommaaccent O -30
-KPX Kcommaaccent Oacute -30
-KPX Kcommaaccent Ocircumflex -30
-KPX Kcommaaccent Odieresis -30
-KPX Kcommaaccent Ograve -30
-KPX Kcommaaccent Ohungarumlaut -30
-KPX Kcommaaccent Omacron -30
-KPX Kcommaaccent Oslash -30
-KPX Kcommaaccent Otilde -30
-KPX Kcommaaccent e -25
-KPX Kcommaaccent eacute -25
-KPX Kcommaaccent ecaron -25
-KPX Kcommaaccent ecircumflex -25
-KPX Kcommaaccent edieresis -25
-KPX Kcommaaccent edotaccent -25
-KPX Kcommaaccent egrave -25
-KPX Kcommaaccent emacron -25
-KPX Kcommaaccent eogonek -25
-KPX Kcommaaccent o -25
-KPX Kcommaaccent oacute -25
-KPX Kcommaaccent ocircumflex -25
-KPX Kcommaaccent odieresis -25
-KPX Kcommaaccent ograve -25
-KPX Kcommaaccent ohungarumlaut -25
-KPX Kcommaaccent omacron -25
-KPX Kcommaaccent oslash -25
-KPX Kcommaaccent otilde -25
-KPX Kcommaaccent u -20
-KPX Kcommaaccent uacute -20
-KPX Kcommaaccent ucircumflex -20
-KPX Kcommaaccent udieresis -20
-KPX Kcommaaccent ugrave -20
-KPX Kcommaaccent uhungarumlaut -20
-KPX Kcommaaccent umacron -20
-KPX Kcommaaccent uogonek -20
-KPX Kcommaaccent uring -20
-KPX Kcommaaccent y -20
-KPX Kcommaaccent yacute -20
-KPX Kcommaaccent ydieresis -20
-KPX L T -18
-KPX L Tcaron -18
-KPX L Tcommaaccent -18
-KPX L V -37
-KPX L W -37
-KPX L Y -37
-KPX L Yacute -37
-KPX L Ydieresis -37
-KPX L quoteright -55
-KPX L y -37
-KPX L yacute -37
-KPX L ydieresis -37
-KPX Lacute T -18
-KPX Lacute Tcaron -18
-KPX Lacute Tcommaaccent -18
-KPX Lacute V -37
-KPX Lacute W -37
-KPX Lacute Y -37
-KPX Lacute Yacute -37
-KPX Lacute Ydieresis -37
-KPX Lacute quoteright -55
-KPX Lacute y -37
-KPX Lacute yacute -37
-KPX Lacute ydieresis -37
-KPX Lcommaaccent T -18
-KPX Lcommaaccent Tcaron -18
-KPX Lcommaaccent Tcommaaccent -18
-KPX Lcommaaccent V -37
-KPX Lcommaaccent W -37
-KPX Lcommaaccent Y -37
-KPX Lcommaaccent Yacute -37
-KPX Lcommaaccent Ydieresis -37
-KPX Lcommaaccent quoteright -55
-KPX Lcommaaccent y -37
-KPX Lcommaaccent yacute -37
-KPX Lcommaaccent ydieresis -37
-KPX Lslash T -18
-KPX Lslash Tcaron -18
-KPX Lslash Tcommaaccent -18
-KPX Lslash V -37
-KPX Lslash W -37
-KPX Lslash Y -37
-KPX Lslash Yacute -37
-KPX Lslash Ydieresis -37
-KPX Lslash quoteright -55
-KPX Lslash y -37
-KPX Lslash yacute -37
-KPX Lslash ydieresis -37
-KPX N A -30
-KPX N Aacute -30
-KPX N Abreve -30
-KPX N Acircumflex -30
-KPX N Adieresis -30
-KPX N Agrave -30
-KPX N Amacron -30
-KPX N Aogonek -30
-KPX N Aring -30
-KPX N Atilde -30
-KPX Nacute A -30
-KPX Nacute Aacute -30
-KPX Nacute Abreve -30
-KPX Nacute Acircumflex -30
-KPX Nacute Adieresis -30
-KPX Nacute Agrave -30
-KPX Nacute Amacron -30
-KPX Nacute Aogonek -30
-KPX Nacute Aring -30
-KPX Nacute Atilde -30
-KPX Ncaron A -30
-KPX Ncaron Aacute -30
-KPX Ncaron Abreve -30
-KPX Ncaron Acircumflex -30
-KPX Ncaron Adieresis -30
-KPX Ncaron Agrave -30
-KPX Ncaron Amacron -30
-KPX Ncaron Aogonek -30
-KPX Ncaron Aring -30
-KPX Ncaron Atilde -30
-KPX Ncommaaccent A -30
-KPX Ncommaaccent Aacute -30
-KPX Ncommaaccent Abreve -30
-KPX Ncommaaccent Acircumflex -30
-KPX Ncommaaccent Adieresis -30
-KPX Ncommaaccent Agrave -30
-KPX Ncommaaccent Amacron -30
-KPX Ncommaaccent Aogonek -30
-KPX Ncommaaccent Aring -30
-KPX Ncommaaccent Atilde -30
-KPX Ntilde A -30
-KPX Ntilde Aacute -30
-KPX Ntilde Abreve -30
-KPX Ntilde Acircumflex -30
-KPX Ntilde Adieresis -30
-KPX Ntilde Agrave -30
-KPX Ntilde Amacron -30
-KPX Ntilde Aogonek -30
-KPX Ntilde Aring -30
-KPX Ntilde Atilde -30
-KPX O A -40
-KPX O Aacute -40
-KPX O Abreve -40
-KPX O Acircumflex -40
-KPX O Adieresis -40
-KPX O Agrave -40
-KPX O Amacron -40
-KPX O Aogonek -40
-KPX O Aring -40
-KPX O Atilde -40
-KPX O T -40
-KPX O Tcaron -40
-KPX O Tcommaaccent -40
-KPX O V -50
-KPX O W -50
-KPX O X -40
-KPX O Y -50
-KPX O Yacute -50
-KPX O Ydieresis -50
-KPX Oacute A -40
-KPX Oacute Aacute -40
-KPX Oacute Abreve -40
-KPX Oacute Acircumflex -40
-KPX Oacute Adieresis -40
-KPX Oacute Agrave -40
-KPX Oacute Amacron -40
-KPX Oacute Aogonek -40
-KPX Oacute Aring -40
-KPX Oacute Atilde -40
-KPX Oacute T -40
-KPX Oacute Tcaron -40
-KPX Oacute Tcommaaccent -40
-KPX Oacute V -50
-KPX Oacute W -50
-KPX Oacute X -40
-KPX Oacute Y -50
-KPX Oacute Yacute -50
-KPX Oacute Ydieresis -50
-KPX Ocircumflex A -40
-KPX Ocircumflex Aacute -40
-KPX Ocircumflex Abreve -40
-KPX Ocircumflex Acircumflex -40
-KPX Ocircumflex Adieresis -40
-KPX Ocircumflex Agrave -40
-KPX Ocircumflex Amacron -40
-KPX Ocircumflex Aogonek -40
-KPX Ocircumflex Aring -40
-KPX Ocircumflex Atilde -40
-KPX Ocircumflex T -40
-KPX Ocircumflex Tcaron -40
-KPX Ocircumflex Tcommaaccent -40
-KPX Ocircumflex V -50
-KPX Ocircumflex W -50
-KPX Ocircumflex X -40
-KPX Ocircumflex Y -50
-KPX Ocircumflex Yacute -50
-KPX Ocircumflex Ydieresis -50
-KPX Odieresis A -40
-KPX Odieresis Aacute -40
-KPX Odieresis Abreve -40
-KPX Odieresis Acircumflex -40
-KPX Odieresis Adieresis -40
-KPX Odieresis Agrave -40
-KPX Odieresis Amacron -40
-KPX Odieresis Aogonek -40
-KPX Odieresis Aring -40
-KPX Odieresis Atilde -40
-KPX Odieresis T -40
-KPX Odieresis Tcaron -40
-KPX Odieresis Tcommaaccent -40
-KPX Odieresis V -50
-KPX Odieresis W -50
-KPX Odieresis X -40
-KPX Odieresis Y -50
-KPX Odieresis Yacute -50
-KPX Odieresis Ydieresis -50
-KPX Ograve A -40
-KPX Ograve Aacute -40
-KPX Ograve Abreve -40
-KPX Ograve Acircumflex -40
-KPX Ograve Adieresis -40
-KPX Ograve Agrave -40
-KPX Ograve Amacron -40
-KPX Ograve Aogonek -40
-KPX Ograve Aring -40
-KPX Ograve Atilde -40
-KPX Ograve T -40
-KPX Ograve Tcaron -40
-KPX Ograve Tcommaaccent -40
-KPX Ograve V -50
-KPX Ograve W -50
-KPX Ograve X -40
-KPX Ograve Y -50
-KPX Ograve Yacute -50
-KPX Ograve Ydieresis -50
-KPX Ohungarumlaut A -40
-KPX Ohungarumlaut Aacute -40
-KPX Ohungarumlaut Abreve -40
-KPX Ohungarumlaut Acircumflex -40
-KPX Ohungarumlaut Adieresis -40
-KPX Ohungarumlaut Agrave -40
-KPX Ohungarumlaut Amacron -40
-KPX Ohungarumlaut Aogonek -40
-KPX Ohungarumlaut Aring -40
-KPX Ohungarumlaut Atilde -40
-KPX Ohungarumlaut T -40
-KPX Ohungarumlaut Tcaron -40
-KPX Ohungarumlaut Tcommaaccent -40
-KPX Ohungarumlaut V -50
-KPX Ohungarumlaut W -50
-KPX Ohungarumlaut X -40
-KPX Ohungarumlaut Y -50
-KPX Ohungarumlaut Yacute -50
-KPX Ohungarumlaut Ydieresis -50
-KPX Omacron A -40
-KPX Omacron Aacute -40
-KPX Omacron Abreve -40
-KPX Omacron Acircumflex -40
-KPX Omacron Adieresis -40
-KPX Omacron Agrave -40
-KPX Omacron Amacron -40
-KPX Omacron Aogonek -40
-KPX Omacron Aring -40
-KPX Omacron Atilde -40
-KPX Omacron T -40
-KPX Omacron Tcaron -40
-KPX Omacron Tcommaaccent -40
-KPX Omacron V -50
-KPX Omacron W -50
-KPX Omacron X -40
-KPX Omacron Y -50
-KPX Omacron Yacute -50
-KPX Omacron Ydieresis -50
-KPX Oslash A -40
-KPX Oslash Aacute -40
-KPX Oslash Abreve -40
-KPX Oslash Acircumflex -40
-KPX Oslash Adieresis -40
-KPX Oslash Agrave -40
-KPX Oslash Amacron -40
-KPX Oslash Aogonek -40
-KPX Oslash Aring -40
-KPX Oslash Atilde -40
-KPX Oslash T -40
-KPX Oslash Tcaron -40
-KPX Oslash Tcommaaccent -40
-KPX Oslash V -50
-KPX Oslash W -50
-KPX Oslash X -40
-KPX Oslash Y -50
-KPX Oslash Yacute -50
-KPX Oslash Ydieresis -50
-KPX Otilde A -40
-KPX Otilde Aacute -40
-KPX Otilde Abreve -40
-KPX Otilde Acircumflex -40
-KPX Otilde Adieresis -40
-KPX Otilde Agrave -40
-KPX Otilde Amacron -40
-KPX Otilde Aogonek -40
-KPX Otilde Aring -40
-KPX Otilde Atilde -40
-KPX Otilde T -40
-KPX Otilde Tcaron -40
-KPX Otilde Tcommaaccent -40
-KPX Otilde V -50
-KPX Otilde W -50
-KPX Otilde X -40
-KPX Otilde Y -50
-KPX Otilde Yacute -50
-KPX Otilde Ydieresis -50
-KPX P A -85
-KPX P Aacute -85
-KPX P Abreve -85
-KPX P Acircumflex -85
-KPX P Adieresis -85
-KPX P Agrave -85
-KPX P Amacron -85
-KPX P Aogonek -85
-KPX P Aring -85
-KPX P Atilde -85
-KPX P a -40
-KPX P aacute -40
-KPX P abreve -40
-KPX P acircumflex -40
-KPX P adieresis -40
-KPX P agrave -40
-KPX P amacron -40
-KPX P aogonek -40
-KPX P aring -40
-KPX P atilde -40
-KPX P comma -129
-KPX P e -50
-KPX P eacute -50
-KPX P ecaron -50
-KPX P ecircumflex -50
-KPX P edieresis -50
-KPX P edotaccent -50
-KPX P egrave -50
-KPX P emacron -50
-KPX P eogonek -50
-KPX P o -55
-KPX P oacute -55
-KPX P ocircumflex -55
-KPX P odieresis -55
-KPX P ograve -55
-KPX P ohungarumlaut -55
-KPX P omacron -55
-KPX P oslash -55
-KPX P otilde -55
-KPX P period -129
-KPX Q U -10
-KPX Q Uacute -10
-KPX Q Ucircumflex -10
-KPX Q Udieresis -10
-KPX Q Ugrave -10
-KPX Q Uhungarumlaut -10
-KPX Q Umacron -10
-KPX Q Uogonek -10
-KPX Q Uring -10
-KPX R O -40
-KPX R Oacute -40
-KPX R Ocircumflex -40
-KPX R Odieresis -40
-KPX R Ograve -40
-KPX R Ohungarumlaut -40
-KPX R Omacron -40
-KPX R Oslash -40
-KPX R Otilde -40
-KPX R T -30
-KPX R Tcaron -30
-KPX R Tcommaaccent -30
-KPX R U -40
-KPX R Uacute -40
-KPX R Ucircumflex -40
-KPX R Udieresis -40
-KPX R Ugrave -40
-KPX R Uhungarumlaut -40
-KPX R Umacron -40
-KPX R Uogonek -40
-KPX R Uring -40
-KPX R V -18
-KPX R W -18
-KPX R Y -18
-KPX R Yacute -18
-KPX R Ydieresis -18
-KPX Racute O -40
-KPX Racute Oacute -40
-KPX Racute Ocircumflex -40
-KPX Racute Odieresis -40
-KPX Racute Ograve -40
-KPX Racute Ohungarumlaut -40
-KPX Racute Omacron -40
-KPX Racute Oslash -40
-KPX Racute Otilde -40
-KPX Racute T -30
-KPX Racute Tcaron -30
-KPX Racute Tcommaaccent -30
-KPX Racute U -40
-KPX Racute Uacute -40
-KPX Racute Ucircumflex -40
-KPX Racute Udieresis -40
-KPX Racute Ugrave -40
-KPX Racute Uhungarumlaut -40
-KPX Racute Umacron -40
-KPX Racute Uogonek -40
-KPX Racute Uring -40
-KPX Racute V -18
-KPX Racute W -18
-KPX Racute Y -18
-KPX Racute Yacute -18
-KPX Racute Ydieresis -18
-KPX Rcaron O -40
-KPX Rcaron Oacute -40
-KPX Rcaron Ocircumflex -40
-KPX Rcaron Odieresis -40
-KPX Rcaron Ograve -40
-KPX Rcaron Ohungarumlaut -40
-KPX Rcaron Omacron -40
-KPX Rcaron Oslash -40
-KPX Rcaron Otilde -40
-KPX Rcaron T -30
-KPX Rcaron Tcaron -30
-KPX Rcaron Tcommaaccent -30
-KPX Rcaron U -40
-KPX Rcaron Uacute -40
-KPX Rcaron Ucircumflex -40
-KPX Rcaron Udieresis -40
-KPX Rcaron Ugrave -40
-KPX Rcaron Uhungarumlaut -40
-KPX Rcaron Umacron -40
-KPX Rcaron Uogonek -40
-KPX Rcaron Uring -40
-KPX Rcaron V -18
-KPX Rcaron W -18
-KPX Rcaron Y -18
-KPX Rcaron Yacute -18
-KPX Rcaron Ydieresis -18
-KPX Rcommaaccent O -40
-KPX Rcommaaccent Oacute -40
-KPX Rcommaaccent Ocircumflex -40
-KPX Rcommaaccent Odieresis -40
-KPX Rcommaaccent Ograve -40
-KPX Rcommaaccent Ohungarumlaut -40
-KPX Rcommaaccent Omacron -40
-KPX Rcommaaccent Oslash -40
-KPX Rcommaaccent Otilde -40
-KPX Rcommaaccent T -30
-KPX Rcommaaccent Tcaron -30
-KPX Rcommaaccent Tcommaaccent -30
-KPX Rcommaaccent U -40
-KPX Rcommaaccent Uacute -40
-KPX Rcommaaccent Ucircumflex -40
-KPX Rcommaaccent Udieresis -40
-KPX Rcommaaccent Ugrave -40
-KPX Rcommaaccent Uhungarumlaut -40
-KPX Rcommaaccent Umacron -40
-KPX Rcommaaccent Uogonek -40
-KPX Rcommaaccent Uring -40
-KPX Rcommaaccent V -18
-KPX Rcommaaccent W -18
-KPX Rcommaaccent Y -18
-KPX Rcommaaccent Yacute -18
-KPX Rcommaaccent Ydieresis -18
-KPX T A -55
-KPX T Aacute -55
-KPX T Abreve -55
-KPX T Acircumflex -55
-KPX T Adieresis -55
-KPX T Agrave -55
-KPX T Amacron -55
-KPX T Aogonek -55
-KPX T Aring -55
-KPX T Atilde -55
-KPX T O -18
-KPX T Oacute -18
-KPX T Ocircumflex -18
-KPX T Odieresis -18
-KPX T Ograve -18
-KPX T Ohungarumlaut -18
-KPX T Omacron -18
-KPX T Oslash -18
-KPX T Otilde -18
-KPX T a -92
-KPX T aacute -92
-KPX T abreve -92
-KPX T acircumflex -92
-KPX T adieresis -92
-KPX T agrave -92
-KPX T amacron -92
-KPX T aogonek -92
-KPX T aring -92
-KPX T atilde -92
-KPX T colon -74
-KPX T comma -92
-KPX T e -92
-KPX T eacute -92
-KPX T ecaron -92
-KPX T ecircumflex -92
-KPX T edieresis -52
-KPX T edotaccent -92
-KPX T egrave -52
-KPX T emacron -52
-KPX T eogonek -92
-KPX T hyphen -92
-KPX T i -37
-KPX T iacute -37
-KPX T iogonek -37
-KPX T o -95
-KPX T oacute -95
-KPX T ocircumflex -95
-KPX T odieresis -95
-KPX T ograve -95
-KPX T ohungarumlaut -95
-KPX T omacron -95
-KPX T oslash -95
-KPX T otilde -95
-KPX T period -92
-KPX T r -37
-KPX T racute -37
-KPX T rcaron -37
-KPX T rcommaaccent -37
-KPX T semicolon -74
-KPX T u -37
-KPX T uacute -37
-KPX T ucircumflex -37
-KPX T udieresis -37
-KPX T ugrave -37
-KPX T uhungarumlaut -37
-KPX T umacron -37
-KPX T uogonek -37
-KPX T uring -37
-KPX T w -37
-KPX T y -37
-KPX T yacute -37
-KPX T ydieresis -37
-KPX Tcaron A -55
-KPX Tcaron Aacute -55
-KPX Tcaron Abreve -55
-KPX Tcaron Acircumflex -55
-KPX Tcaron Adieresis -55
-KPX Tcaron Agrave -55
-KPX Tcaron Amacron -55
-KPX Tcaron Aogonek -55
-KPX Tcaron Aring -55
-KPX Tcaron Atilde -55
-KPX Tcaron O -18
-KPX Tcaron Oacute -18
-KPX Tcaron Ocircumflex -18
-KPX Tcaron Odieresis -18
-KPX Tcaron Ograve -18
-KPX Tcaron Ohungarumlaut -18
-KPX Tcaron Omacron -18
-KPX Tcaron Oslash -18
-KPX Tcaron Otilde -18
-KPX Tcaron a -92
-KPX Tcaron aacute -92
-KPX Tcaron abreve -92
-KPX Tcaron acircumflex -92
-KPX Tcaron adieresis -92
-KPX Tcaron agrave -92
-KPX Tcaron amacron -92
-KPX Tcaron aogonek -92
-KPX Tcaron aring -92
-KPX Tcaron atilde -92
-KPX Tcaron colon -74
-KPX Tcaron comma -92
-KPX Tcaron e -92
-KPX Tcaron eacute -92
-KPX Tcaron ecaron -92
-KPX Tcaron ecircumflex -92
-KPX Tcaron edieresis -52
-KPX Tcaron edotaccent -92
-KPX Tcaron egrave -52
-KPX Tcaron emacron -52
-KPX Tcaron eogonek -92
-KPX Tcaron hyphen -92
-KPX Tcaron i -37
-KPX Tcaron iacute -37
-KPX Tcaron iogonek -37
-KPX Tcaron o -95
-KPX Tcaron oacute -95
-KPX Tcaron ocircumflex -95
-KPX Tcaron odieresis -95
-KPX Tcaron ograve -95
-KPX Tcaron ohungarumlaut -95
-KPX Tcaron omacron -95
-KPX Tcaron oslash -95
-KPX Tcaron otilde -95
-KPX Tcaron period -92
-KPX Tcaron r -37
-KPX Tcaron racute -37
-KPX Tcaron rcaron -37
-KPX Tcaron rcommaaccent -37
-KPX Tcaron semicolon -74
-KPX Tcaron u -37
-KPX Tcaron uacute -37
-KPX Tcaron ucircumflex -37
-KPX Tcaron udieresis -37
-KPX Tcaron ugrave -37
-KPX Tcaron uhungarumlaut -37
-KPX Tcaron umacron -37
-KPX Tcaron uogonek -37
-KPX Tcaron uring -37
-KPX Tcaron w -37
-KPX Tcaron y -37
-KPX Tcaron yacute -37
-KPX Tcaron ydieresis -37
-KPX Tcommaaccent A -55
-KPX Tcommaaccent Aacute -55
-KPX Tcommaaccent Abreve -55
-KPX Tcommaaccent Acircumflex -55
-KPX Tcommaaccent Adieresis -55
-KPX Tcommaaccent Agrave -55
-KPX Tcommaaccent Amacron -55
-KPX Tcommaaccent Aogonek -55
-KPX Tcommaaccent Aring -55
-KPX Tcommaaccent Atilde -55
-KPX Tcommaaccent O -18
-KPX Tcommaaccent Oacute -18
-KPX Tcommaaccent Ocircumflex -18
-KPX Tcommaaccent Odieresis -18
-KPX Tcommaaccent Ograve -18
-KPX Tcommaaccent Ohungarumlaut -18
-KPX Tcommaaccent Omacron -18
-KPX Tcommaaccent Oslash -18
-KPX Tcommaaccent Otilde -18
-KPX Tcommaaccent a -92
-KPX Tcommaaccent aacute -92
-KPX Tcommaaccent abreve -92
-KPX Tcommaaccent acircumflex -92
-KPX Tcommaaccent adieresis -92
-KPX Tcommaaccent agrave -92
-KPX Tcommaaccent amacron -92
-KPX Tcommaaccent aogonek -92
-KPX Tcommaaccent aring -92
-KPX Tcommaaccent atilde -92
-KPX Tcommaaccent colon -74
-KPX Tcommaaccent comma -92
-KPX Tcommaaccent e -92
-KPX Tcommaaccent eacute -92
-KPX Tcommaaccent ecaron -92
-KPX Tcommaaccent ecircumflex -92
-KPX Tcommaaccent edieresis -52
-KPX Tcommaaccent edotaccent -92
-KPX Tcommaaccent egrave -52
-KPX Tcommaaccent emacron -52
-KPX Tcommaaccent eogonek -92
-KPX Tcommaaccent hyphen -92
-KPX Tcommaaccent i -37
-KPX Tcommaaccent iacute -37
-KPX Tcommaaccent iogonek -37
-KPX Tcommaaccent o -95
-KPX Tcommaaccent oacute -95
-KPX Tcommaaccent ocircumflex -95
-KPX Tcommaaccent odieresis -95
-KPX Tcommaaccent ograve -95
-KPX Tcommaaccent ohungarumlaut -95
-KPX Tcommaaccent omacron -95
-KPX Tcommaaccent oslash -95
-KPX Tcommaaccent otilde -95
-KPX Tcommaaccent period -92
-KPX Tcommaaccent r -37
-KPX Tcommaaccent racute -37
-KPX Tcommaaccent rcaron -37
-KPX Tcommaaccent rcommaaccent -37
-KPX Tcommaaccent semicolon -74
-KPX Tcommaaccent u -37
-KPX Tcommaaccent uacute -37
-KPX Tcommaaccent ucircumflex -37
-KPX Tcommaaccent udieresis -37
-KPX Tcommaaccent ugrave -37
-KPX Tcommaaccent uhungarumlaut -37
-KPX Tcommaaccent umacron -37
-KPX Tcommaaccent uogonek -37
-KPX Tcommaaccent uring -37
-KPX Tcommaaccent w -37
-KPX Tcommaaccent y -37
-KPX Tcommaaccent yacute -37
-KPX Tcommaaccent ydieresis -37
-KPX U A -45
-KPX U Aacute -45
-KPX U Abreve -45
-KPX U Acircumflex -45
-KPX U Adieresis -45
-KPX U Agrave -45
-KPX U Amacron -45
-KPX U Aogonek -45
-KPX U Aring -45
-KPX U Atilde -45
-KPX Uacute A -45
-KPX Uacute Aacute -45
-KPX Uacute Abreve -45
-KPX Uacute Acircumflex -45
-KPX Uacute Adieresis -45
-KPX Uacute Agrave -45
-KPX Uacute Amacron -45
-KPX Uacute Aogonek -45
-KPX Uacute Aring -45
-KPX Uacute Atilde -45
-KPX Ucircumflex A -45
-KPX Ucircumflex Aacute -45
-KPX Ucircumflex Abreve -45
-KPX Ucircumflex Acircumflex -45
-KPX Ucircumflex Adieresis -45
-KPX Ucircumflex Agrave -45
-KPX Ucircumflex Amacron -45
-KPX Ucircumflex Aogonek -45
-KPX Ucircumflex Aring -45
-KPX Ucircumflex Atilde -45
-KPX Udieresis A -45
-KPX Udieresis Aacute -45
-KPX Udieresis Abreve -45
-KPX Udieresis Acircumflex -45
-KPX Udieresis Adieresis -45
-KPX Udieresis Agrave -45
-KPX Udieresis Amacron -45
-KPX Udieresis Aogonek -45
-KPX Udieresis Aring -45
-KPX Udieresis Atilde -45
-KPX Ugrave A -45
-KPX Ugrave Aacute -45
-KPX Ugrave Abreve -45
-KPX Ugrave Acircumflex -45
-KPX Ugrave Adieresis -45
-KPX Ugrave Agrave -45
-KPX Ugrave Amacron -45
-KPX Ugrave Aogonek -45
-KPX Ugrave Aring -45
-KPX Ugrave Atilde -45
-KPX Uhungarumlaut A -45
-KPX Uhungarumlaut Aacute -45
-KPX Uhungarumlaut Abreve -45
-KPX Uhungarumlaut Acircumflex -45
-KPX Uhungarumlaut Adieresis -45
-KPX Uhungarumlaut Agrave -45
-KPX Uhungarumlaut Amacron -45
-KPX Uhungarumlaut Aogonek -45
-KPX Uhungarumlaut Aring -45
-KPX Uhungarumlaut Atilde -45
-KPX Umacron A -45
-KPX Umacron Aacute -45
-KPX Umacron Abreve -45
-KPX Umacron Acircumflex -45
-KPX Umacron Adieresis -45
-KPX Umacron Agrave -45
-KPX Umacron Amacron -45
-KPX Umacron Aogonek -45
-KPX Umacron Aring -45
-KPX Umacron Atilde -45
-KPX Uogonek A -45
-KPX Uogonek Aacute -45
-KPX Uogonek Abreve -45
-KPX Uogonek Acircumflex -45
-KPX Uogonek Adieresis -45
-KPX Uogonek Agrave -45
-KPX Uogonek Amacron -45
-KPX Uogonek Aogonek -45
-KPX Uogonek Aring -45
-KPX Uogonek Atilde -45
-KPX Uring A -45
-KPX Uring Aacute -45
-KPX Uring Abreve -45
-KPX Uring Acircumflex -45
-KPX Uring Adieresis -45
-KPX Uring Agrave -45
-KPX Uring Amacron -45
-KPX Uring Aogonek -45
-KPX Uring Aring -45
-KPX Uring Atilde -45
-KPX V A -85
-KPX V Aacute -85
-KPX V Abreve -85
-KPX V Acircumflex -85
-KPX V Adieresis -85
-KPX V Agrave -85
-KPX V Amacron -85
-KPX V Aogonek -85
-KPX V Aring -85
-KPX V Atilde -85
-KPX V G -10
-KPX V Gbreve -10
-KPX V Gcommaaccent -10
-KPX V O -30
-KPX V Oacute -30
-KPX V Ocircumflex -30
-KPX V Odieresis -30
-KPX V Ograve -30
-KPX V Ohungarumlaut -30
-KPX V Omacron -30
-KPX V Oslash -30
-KPX V Otilde -30
-KPX V a -111
-KPX V aacute -111
-KPX V abreve -111
-KPX V acircumflex -111
-KPX V adieresis -111
-KPX V agrave -111
-KPX V amacron -111
-KPX V aogonek -111
-KPX V aring -111
-KPX V atilde -111
-KPX V colon -74
-KPX V comma -129
-KPX V e -111
-KPX V eacute -111
-KPX V ecaron -111
-KPX V ecircumflex -111
-KPX V edieresis -71
-KPX V edotaccent -111
-KPX V egrave -71
-KPX V emacron -71
-KPX V eogonek -111
-KPX V hyphen -70
-KPX V i -55
-KPX V iacute -55
-KPX V iogonek -55
-KPX V o -111
-KPX V oacute -111
-KPX V ocircumflex -111
-KPX V odieresis -111
-KPX V ograve -111
-KPX V ohungarumlaut -111
-KPX V omacron -111
-KPX V oslash -111
-KPX V otilde -111
-KPX V period -129
-KPX V semicolon -74
-KPX V u -55
-KPX V uacute -55
-KPX V ucircumflex -55
-KPX V udieresis -55
-KPX V ugrave -55
-KPX V uhungarumlaut -55
-KPX V umacron -55
-KPX V uogonek -55
-KPX V uring -55
-KPX W A -74
-KPX W Aacute -74
-KPX W Abreve -74
-KPX W Acircumflex -74
-KPX W Adieresis -74
-KPX W Agrave -74
-KPX W Amacron -74
-KPX W Aogonek -74
-KPX W Aring -74
-KPX W Atilde -74
-KPX W O -15
-KPX W Oacute -15
-KPX W Ocircumflex -15
-KPX W Odieresis -15
-KPX W Ograve -15
-KPX W Ohungarumlaut -15
-KPX W Omacron -15
-KPX W Oslash -15
-KPX W Otilde -15
-KPX W a -85
-KPX W aacute -85
-KPX W abreve -85
-KPX W acircumflex -85
-KPX W adieresis -85
-KPX W agrave -85
-KPX W amacron -85
-KPX W aogonek -85
-KPX W aring -85
-KPX W atilde -85
-KPX W colon -55
-KPX W comma -74
-KPX W e -90
-KPX W eacute -90
-KPX W ecaron -90
-KPX W ecircumflex -90
-KPX W edieresis -50
-KPX W edotaccent -90
-KPX W egrave -50
-KPX W emacron -50
-KPX W eogonek -90
-KPX W hyphen -50
-KPX W i -37
-KPX W iacute -37
-KPX W iogonek -37
-KPX W o -80
-KPX W oacute -80
-KPX W ocircumflex -80
-KPX W odieresis -80
-KPX W ograve -80
-KPX W ohungarumlaut -80
-KPX W omacron -80
-KPX W oslash -80
-KPX W otilde -80
-KPX W period -74
-KPX W semicolon -55
-KPX W u -55
-KPX W uacute -55
-KPX W ucircumflex -55
-KPX W udieresis -55
-KPX W ugrave -55
-KPX W uhungarumlaut -55
-KPX W umacron -55
-KPX W uogonek -55
-KPX W uring -55
-KPX W y -55
-KPX W yacute -55
-KPX W ydieresis -55
-KPX Y A -74
-KPX Y Aacute -74
-KPX Y Abreve -74
-KPX Y Acircumflex -74
-KPX Y Adieresis -74
-KPX Y Agrave -74
-KPX Y Amacron -74
-KPX Y Aogonek -74
-KPX Y Aring -74
-KPX Y Atilde -74
-KPX Y O -25
-KPX Y Oacute -25
-KPX Y Ocircumflex -25
-KPX Y Odieresis -25
-KPX Y Ograve -25
-KPX Y Ohungarumlaut -25
-KPX Y Omacron -25
-KPX Y Oslash -25
-KPX Y Otilde -25
-KPX Y a -92
-KPX Y aacute -92
-KPX Y abreve -92
-KPX Y acircumflex -92
-KPX Y adieresis -92
-KPX Y agrave -92
-KPX Y amacron -92
-KPX Y aogonek -92
-KPX Y aring -92
-KPX Y atilde -92
-KPX Y colon -92
-KPX Y comma -92
-KPX Y e -111
-KPX Y eacute -111
-KPX Y ecaron -111
-KPX Y ecircumflex -71
-KPX Y edieresis -71
-KPX Y edotaccent -111
-KPX Y egrave -71
-KPX Y emacron -71
-KPX Y eogonek -111
-KPX Y hyphen -92
-KPX Y i -55
-KPX Y iacute -55
-KPX Y iogonek -55
-KPX Y o -111
-KPX Y oacute -111
-KPX Y ocircumflex -111
-KPX Y odieresis -111
-KPX Y ograve -111
-KPX Y ohungarumlaut -111
-KPX Y omacron -111
-KPX Y oslash -111
-KPX Y otilde -111
-KPX Y period -74
-KPX Y semicolon -92
-KPX Y u -92
-KPX Y uacute -92
-KPX Y ucircumflex -92
-KPX Y udieresis -92
-KPX Y ugrave -92
-KPX Y uhungarumlaut -92
-KPX Y umacron -92
-KPX Y uogonek -92
-KPX Y uring -92
-KPX Yacute A -74
-KPX Yacute Aacute -74
-KPX Yacute Abreve -74
-KPX Yacute Acircumflex -74
-KPX Yacute Adieresis -74
-KPX Yacute Agrave -74
-KPX Yacute Amacron -74
-KPX Yacute Aogonek -74
-KPX Yacute Aring -74
-KPX Yacute Atilde -74
-KPX Yacute O -25
-KPX Yacute Oacute -25
-KPX Yacute Ocircumflex -25
-KPX Yacute Odieresis -25
-KPX Yacute Ograve -25
-KPX Yacute Ohungarumlaut -25
-KPX Yacute Omacron -25
-KPX Yacute Oslash -25
-KPX Yacute Otilde -25
-KPX Yacute a -92
-KPX Yacute aacute -92
-KPX Yacute abreve -92
-KPX Yacute acircumflex -92
-KPX Yacute adieresis -92
-KPX Yacute agrave -92
-KPX Yacute amacron -92
-KPX Yacute aogonek -92
-KPX Yacute aring -92
-KPX Yacute atilde -92
-KPX Yacute colon -92
-KPX Yacute comma -92
-KPX Yacute e -111
-KPX Yacute eacute -111
-KPX Yacute ecaron -111
-KPX Yacute ecircumflex -71
-KPX Yacute edieresis -71
-KPX Yacute edotaccent -111
-KPX Yacute egrave -71
-KPX Yacute emacron -71
-KPX Yacute eogonek -111
-KPX Yacute hyphen -92
-KPX Yacute i -55
-KPX Yacute iacute -55
-KPX Yacute iogonek -55
-KPX Yacute o -111
-KPX Yacute oacute -111
-KPX Yacute ocircumflex -111
-KPX Yacute odieresis -111
-KPX Yacute ograve -111
-KPX Yacute ohungarumlaut -111
-KPX Yacute omacron -111
-KPX Yacute oslash -111
-KPX Yacute otilde -111
-KPX Yacute period -74
-KPX Yacute semicolon -92
-KPX Yacute u -92
-KPX Yacute uacute -92
-KPX Yacute ucircumflex -92
-KPX Yacute udieresis -92
-KPX Yacute ugrave -92
-KPX Yacute uhungarumlaut -92
-KPX Yacute umacron -92
-KPX Yacute uogonek -92
-KPX Yacute uring -92
-KPX Ydieresis A -74
-KPX Ydieresis Aacute -74
-KPX Ydieresis Abreve -74
-KPX Ydieresis Acircumflex -74
-KPX Ydieresis Adieresis -74
-KPX Ydieresis Agrave -74
-KPX Ydieresis Amacron -74
-KPX Ydieresis Aogonek -74
-KPX Ydieresis Aring -74
-KPX Ydieresis Atilde -74
-KPX Ydieresis O -25
-KPX Ydieresis Oacute -25
-KPX Ydieresis Ocircumflex -25
-KPX Ydieresis Odieresis -25
-KPX Ydieresis Ograve -25
-KPX Ydieresis Ohungarumlaut -25
-KPX Ydieresis Omacron -25
-KPX Ydieresis Oslash -25
-KPX Ydieresis Otilde -25
-KPX Ydieresis a -92
-KPX Ydieresis aacute -92
-KPX Ydieresis abreve -92
-KPX Ydieresis acircumflex -92
-KPX Ydieresis adieresis -92
-KPX Ydieresis agrave -92
-KPX Ydieresis amacron -92
-KPX Ydieresis aogonek -92
-KPX Ydieresis aring -92
-KPX Ydieresis atilde -92
-KPX Ydieresis colon -92
-KPX Ydieresis comma -92
-KPX Ydieresis e -111
-KPX Ydieresis eacute -111
-KPX Ydieresis ecaron -111
-KPX Ydieresis ecircumflex -71
-KPX Ydieresis edieresis -71
-KPX Ydieresis edotaccent -111
-KPX Ydieresis egrave -71
-KPX Ydieresis emacron -71
-KPX Ydieresis eogonek -111
-KPX Ydieresis hyphen -92
-KPX Ydieresis i -55
-KPX Ydieresis iacute -55
-KPX Ydieresis iogonek -55
-KPX Ydieresis o -111
-KPX Ydieresis oacute -111
-KPX Ydieresis ocircumflex -111
-KPX Ydieresis odieresis -111
-KPX Ydieresis ograve -111
-KPX Ydieresis ohungarumlaut -111
-KPX Ydieresis omacron -111
-KPX Ydieresis oslash -111
-KPX Ydieresis otilde -111
-KPX Ydieresis period -74
-KPX Ydieresis semicolon -92
-KPX Ydieresis u -92
-KPX Ydieresis uacute -92
-KPX Ydieresis ucircumflex -92
-KPX Ydieresis udieresis -92
-KPX Ydieresis ugrave -92
-KPX Ydieresis uhungarumlaut -92
-KPX Ydieresis umacron -92
-KPX Ydieresis uogonek -92
-KPX Ydieresis uring -92
-KPX b b -10
-KPX b period -40
-KPX b u -20
-KPX b uacute -20
-KPX b ucircumflex -20
-KPX b udieresis -20
-KPX b ugrave -20
-KPX b uhungarumlaut -20
-KPX b umacron -20
-KPX b uogonek -20
-KPX b uring -20
-KPX c h -10
-KPX c k -10
-KPX c kcommaaccent -10
-KPX cacute h -10
-KPX cacute k -10
-KPX cacute kcommaaccent -10
-KPX ccaron h -10
-KPX ccaron k -10
-KPX ccaron kcommaaccent -10
-KPX ccedilla h -10
-KPX ccedilla k -10
-KPX ccedilla kcommaaccent -10
-KPX comma quotedblright -95
-KPX comma quoteright -95
-KPX e b -10
-KPX eacute b -10
-KPX ecaron b -10
-KPX ecircumflex b -10
-KPX edieresis b -10
-KPX edotaccent b -10
-KPX egrave b -10
-KPX emacron b -10
-KPX eogonek b -10
-KPX f comma -10
-KPX f dotlessi -30
-KPX f e -10
-KPX f eacute -10
-KPX f edotaccent -10
-KPX f eogonek -10
-KPX f f -18
-KPX f o -10
-KPX f oacute -10
-KPX f ocircumflex -10
-KPX f ograve -10
-KPX f ohungarumlaut -10
-KPX f oslash -10
-KPX f otilde -10
-KPX f period -10
-KPX f quoteright 55
-KPX k e -30
-KPX k eacute -30
-KPX k ecaron -30
-KPX k ecircumflex -30
-KPX k edieresis -30
-KPX k edotaccent -30
-KPX k egrave -30
-KPX k emacron -30
-KPX k eogonek -30
-KPX k o -10
-KPX k oacute -10
-KPX k ocircumflex -10
-KPX k odieresis -10
-KPX k ograve -10
-KPX k ohungarumlaut -10
-KPX k omacron -10
-KPX k oslash -10
-KPX k otilde -10
-KPX kcommaaccent e -30
-KPX kcommaaccent eacute -30
-KPX kcommaaccent ecaron -30
-KPX kcommaaccent ecircumflex -30
-KPX kcommaaccent edieresis -30
-KPX kcommaaccent edotaccent -30
-KPX kcommaaccent egrave -30
-KPX kcommaaccent emacron -30
-KPX kcommaaccent eogonek -30
-KPX kcommaaccent o -10
-KPX kcommaaccent oacute -10
-KPX kcommaaccent ocircumflex -10
-KPX kcommaaccent odieresis -10
-KPX kcommaaccent ograve -10
-KPX kcommaaccent ohungarumlaut -10
-KPX kcommaaccent omacron -10
-KPX kcommaaccent oslash -10
-KPX kcommaaccent otilde -10
-KPX n v -40
-KPX nacute v -40
-KPX ncaron v -40
-KPX ncommaaccent v -40
-KPX ntilde v -40
-KPX o v -15
-KPX o w -25
-KPX o x -10
-KPX o y -10
-KPX o yacute -10
-KPX o ydieresis -10
-KPX oacute v -15
-KPX oacute w -25
-KPX oacute x -10
-KPX oacute y -10
-KPX oacute yacute -10
-KPX oacute ydieresis -10
-KPX ocircumflex v -15
-KPX ocircumflex w -25
-KPX ocircumflex x -10
-KPX ocircumflex y -10
-KPX ocircumflex yacute -10
-KPX ocircumflex ydieresis -10
-KPX odieresis v -15
-KPX odieresis w -25
-KPX odieresis x -10
-KPX odieresis y -10
-KPX odieresis yacute -10
-KPX odieresis ydieresis -10
-KPX ograve v -15
-KPX ograve w -25
-KPX ograve x -10
-KPX ograve y -10
-KPX ograve yacute -10
-KPX ograve ydieresis -10
-KPX ohungarumlaut v -15
-KPX ohungarumlaut w -25
-KPX ohungarumlaut x -10
-KPX ohungarumlaut y -10
-KPX ohungarumlaut yacute -10
-KPX ohungarumlaut ydieresis -10
-KPX omacron v -15
-KPX omacron w -25
-KPX omacron x -10
-KPX omacron y -10
-KPX omacron yacute -10
-KPX omacron ydieresis -10
-KPX oslash v -15
-KPX oslash w -25
-KPX oslash x -10
-KPX oslash y -10
-KPX oslash yacute -10
-KPX oslash ydieresis -10
-KPX otilde v -15
-KPX otilde w -25
-KPX otilde x -10
-KPX otilde y -10
-KPX otilde yacute -10
-KPX otilde ydieresis -10
-KPX period quotedblright -95
-KPX period quoteright -95
-KPX quoteleft quoteleft -74
-KPX quoteright d -15
-KPX quoteright dcroat -15
-KPX quoteright quoteright -74
-KPX quoteright r -15
-KPX quoteright racute -15
-KPX quoteright rcaron -15
-KPX quoteright rcommaaccent -15
-KPX quoteright s -74
-KPX quoteright sacute -74
-KPX quoteright scaron -74
-KPX quoteright scedilla -74
-KPX quoteright scommaaccent -74
-KPX quoteright space -74
-KPX quoteright t -37
-KPX quoteright tcommaaccent -37
-KPX quoteright v -15
-KPX r comma -65
-KPX r period -65
-KPX racute comma -65
-KPX racute period -65
-KPX rcaron comma -65
-KPX rcaron period -65
-KPX rcommaaccent comma -65
-KPX rcommaaccent period -65
-KPX space A -37
-KPX space Aacute -37
-KPX space Abreve -37
-KPX space Acircumflex -37
-KPX space Adieresis -37
-KPX space Agrave -37
-KPX space Amacron -37
-KPX space Aogonek -37
-KPX space Aring -37
-KPX space Atilde -37
-KPX space V -70
-KPX space W -70
-KPX space Y -70
-KPX space Yacute -70
-KPX space Ydieresis -70
-KPX v comma -37
-KPX v e -15
-KPX v eacute -15
-KPX v ecaron -15
-KPX v ecircumflex -15
-KPX v edieresis -15
-KPX v edotaccent -15
-KPX v egrave -15
-KPX v emacron -15
-KPX v eogonek -15
-KPX v o -15
-KPX v oacute -15
-KPX v ocircumflex -15
-KPX v odieresis -15
-KPX v ograve -15
-KPX v ohungarumlaut -15
-KPX v omacron -15
-KPX v oslash -15
-KPX v otilde -15
-KPX v period -37
-KPX w a -10
-KPX w aacute -10
-KPX w abreve -10
-KPX w acircumflex -10
-KPX w adieresis -10
-KPX w agrave -10
-KPX w amacron -10
-KPX w aogonek -10
-KPX w aring -10
-KPX w atilde -10
-KPX w comma -37
-KPX w e -10
-KPX w eacute -10
-KPX w ecaron -10
-KPX w ecircumflex -10
-KPX w edieresis -10
-KPX w edotaccent -10
-KPX w egrave -10
-KPX w emacron -10
-KPX w eogonek -10
-KPX w o -15
-KPX w oacute -15
-KPX w ocircumflex -15
-KPX w odieresis -15
-KPX w ograve -15
-KPX w ohungarumlaut -15
-KPX w omacron -15
-KPX w oslash -15
-KPX w otilde -15
-KPX w period -37
-KPX x e -10
-KPX x eacute -10
-KPX x ecaron -10
-KPX x ecircumflex -10
-KPX x edieresis -10
-KPX x edotaccent -10
-KPX x egrave -10
-KPX x emacron -10
-KPX x eogonek -10
-KPX y comma -37
-KPX y period -37
-KPX yacute comma -37
-KPX yacute period -37
-KPX ydieresis comma -37
-KPX ydieresis period -37
-EndKernPairs
-EndKernData
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Times-Italic.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Times-Italic.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Times-Italic.afm 2004-05-26 16:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Times-Italic.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,2667 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Thu May 1 12:56:55 1997
-Comment UniqueID 43067
-Comment VMusage 47727 58752
-FontName Times-Italic
-FullName Times Italic
-FamilyName Times
-Weight Medium
-ItalicAngle -15.5
-IsFixedPitch false
-CharacterSet ExtendedRoman
-FontBBox -169 -217 1010 883
-UnderlinePosition -100
-UnderlineThickness 50
-Version 002.000
-Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries.
-EncodingScheme AdobeStandardEncoding
-CapHeight 653
-XHeight 441
-Ascender 683
-Descender -217
-StdHW 32
-StdVW 76
-StartCharMetrics 315
-C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 333 ; N exclam ; B 39 -11 302 667 ;
-C 34 ; WX 420 ; N quotedbl ; B 144 421 432 666 ;
-C 35 ; WX 500 ; N numbersign ; B 2 0 540 676 ;
-C 36 ; WX 500 ; N dollar ; B 31 -89 497 731 ;
-C 37 ; WX 833 ; N percent ; B 79 -13 790 676 ;
-C 38 ; WX 778 ; N ampersand ; B 76 -18 723 666 ;
-C 39 ; WX 333 ; N quoteright ; B 151 436 290 666 ;
-C 40 ; WX 333 ; N parenleft ; B 42 -181 315 669 ;
-C 41 ; WX 333 ; N parenright ; B 16 -180 289 669 ;
-C 42 ; WX 500 ; N asterisk ; B 128 255 492 666 ;
-C 43 ; WX 675 ; N plus ; B 86 0 590 506 ;
-C 44 ; WX 250 ; N comma ; B -4 -129 135 101 ;
-C 45 ; WX 333 ; N hyphen ; B 49 192 282 255 ;
-C 46 ; WX 250 ; N period ; B 27 -11 138 100 ;
-C 47 ; WX 278 ; N slash ; B -65 -18 386 666 ;
-C 48 ; WX 500 ; N zero ; B 32 -7 497 676 ;
-C 49 ; WX 500 ; N one ; B 49 0 409 676 ;
-C 50 ; WX 500 ; N two ; B 12 0 452 676 ;
-C 51 ; WX 500 ; N three ; B 15 -7 465 676 ;
-C 52 ; WX 500 ; N four ; B 1 0 479 676 ;
-C 53 ; WX 500 ; N five ; B 15 -7 491 666 ;
-C 54 ; WX 500 ; N six ; B 30 -7 521 686 ;
-C 55 ; WX 500 ; N seven ; B 75 -8 537 666 ;
-C 56 ; WX 500 ; N eight ; B 30 -7 493 676 ;
-C 57 ; WX 500 ; N nine ; B 23 -17 492 676 ;
-C 58 ; WX 333 ; N colon ; B 50 -11 261 441 ;
-C 59 ; WX 333 ; N semicolon ; B 27 -129 261 441 ;
-C 60 ; WX 675 ; N less ; B 84 -8 592 514 ;
-C 61 ; WX 675 ; N equal ; B 86 120 590 386 ;
-C 62 ; WX 675 ; N greater ; B 84 -8 592 514 ;
-C 63 ; WX 500 ; N question ; B 132 -12 472 664 ;
-C 64 ; WX 920 ; N at ; B 118 -18 806 666 ;
-C 65 ; WX 611 ; N A ; B -51 0 564 668 ;
-C 66 ; WX 611 ; N B ; B -8 0 588 653 ;
-C 67 ; WX 667 ; N C ; B 66 -18 689 666 ;
-C 68 ; WX 722 ; N D ; B -8 0 700 653 ;
-C 69 ; WX 611 ; N E ; B -1 0 634 653 ;
-C 70 ; WX 611 ; N F ; B 8 0 645 653 ;
-C 71 ; WX 722 ; N G ; B 52 -18 722 666 ;
-C 72 ; WX 722 ; N H ; B -8 0 767 653 ;
-C 73 ; WX 333 ; N I ; B -8 0 384 653 ;
-C 74 ; WX 444 ; N J ; B -6 -18 491 653 ;
-C 75 ; WX 667 ; N K ; B 7 0 722 653 ;
-C 76 ; WX 556 ; N L ; B -8 0 559 653 ;
-C 77 ; WX 833 ; N M ; B -18 0 873 653 ;
-C 78 ; WX 667 ; N N ; B -20 -15 727 653 ;
-C 79 ; WX 722 ; N O ; B 60 -18 699 666 ;
-C 80 ; WX 611 ; N P ; B 0 0 605 653 ;
-C 81 ; WX 722 ; N Q ; B 59 -182 699 666 ;
-C 82 ; WX 611 ; N R ; B -13 0 588 653 ;
-C 83 ; WX 500 ; N S ; B 17 -18 508 667 ;
-C 84 ; WX 556 ; N T ; B 59 0 633 653 ;
-C 85 ; WX 722 ; N U ; B 102 -18 765 653 ;
-C 86 ; WX 611 ; N V ; B 76 -18 688 653 ;
-C 87 ; WX 833 ; N W ; B 71 -18 906 653 ;
-C 88 ; WX 611 ; N X ; B -29 0 655 653 ;
-C 89 ; WX 556 ; N Y ; B 78 0 633 653 ;
-C 90 ; WX 556 ; N Z ; B -6 0 606 653 ;
-C 91 ; WX 389 ; N bracketleft ; B 21 -153 391 663 ;
-C 92 ; WX 278 ; N backslash ; B -41 -18 319 666 ;
-C 93 ; WX 389 ; N bracketright ; B 12 -153 382 663 ;
-C 94 ; WX 422 ; N asciicircum ; B 0 301 422 666 ;
-C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
-C 96 ; WX 333 ; N quoteleft ; B 171 436 310 666 ;
-C 97 ; WX 500 ; N a ; B 17 -11 476 441 ;
-C 98 ; WX 500 ; N b ; B 23 -11 473 683 ;
-C 99 ; WX 444 ; N c ; B 30 -11 425 441 ;
-C 100 ; WX 500 ; N d ; B 15 -13 527 683 ;
-C 101 ; WX 444 ; N e ; B 31 -11 412 441 ;
-C 102 ; WX 278 ; N f ; B -147 -207 424 678 ; L i fi ; L l fl ;
-C 103 ; WX 500 ; N g ; B 8 -206 472 441 ;
-C 104 ; WX 500 ; N h ; B 19 -9 478 683 ;
-C 105 ; WX 278 ; N i ; B 49 -11 264 654 ;
-C 106 ; WX 278 ; N j ; B -124 -207 276 654 ;
-C 107 ; WX 444 ; N k ; B 14 -11 461 683 ;
-C 108 ; WX 278 ; N l ; B 41 -11 279 683 ;
-C 109 ; WX 722 ; N m ; B 12 -9 704 441 ;
-C 110 ; WX 500 ; N n ; B 14 -9 474 441 ;
-C 111 ; WX 500 ; N o ; B 27 -11 468 441 ;
-C 112 ; WX 500 ; N p ; B -75 -205 469 441 ;
-C 113 ; WX 500 ; N q ; B 25 -209 483 441 ;
-C 114 ; WX 389 ; N r ; B 45 0 412 441 ;
-C 115 ; WX 389 ; N s ; B 16 -13 366 442 ;
-C 116 ; WX 278 ; N t ; B 37 -11 296 546 ;
-C 117 ; WX 500 ; N u ; B 42 -11 475 441 ;
-C 118 ; WX 444 ; N v ; B 21 -18 426 441 ;
-C 119 ; WX 667 ; N w ; B 16 -18 648 441 ;
-C 120 ; WX 444 ; N x ; B -27 -11 447 441 ;
-C 121 ; WX 444 ; N y ; B -24 -206 426 441 ;
-C 122 ; WX 389 ; N z ; B -2 -81 380 428 ;
-C 123 ; WX 400 ; N braceleft ; B 51 -177 407 687 ;
-C 124 ; WX 275 ; N bar ; B 105 -217 171 783 ;
-C 125 ; WX 400 ; N braceright ; B -7 -177 349 687 ;
-C 126 ; WX 541 ; N asciitilde ; B 40 183 502 323 ;
-C 161 ; WX 389 ; N exclamdown ; B 59 -205 322 473 ;
-C 162 ; WX 500 ; N cent ; B 77 -143 472 560 ;
-C 163 ; WX 500 ; N sterling ; B 10 -6 517 670 ;
-C 164 ; WX 167 ; N fraction ; B -169 -10 337 676 ;
-C 165 ; WX 500 ; N yen ; B 27 0 603 653 ;
-C 166 ; WX 500 ; N florin ; B 25 -182 507 682 ;
-C 167 ; WX 500 ; N section ; B 53 -162 461 666 ;
-C 168 ; WX 500 ; N currency ; B -22 53 522 597 ;
-C 169 ; WX 214 ; N quotesingle ; B 132 421 241 666 ;
-C 170 ; WX 556 ; N quotedblleft ; B 166 436 514 666 ;
-C 171 ; WX 500 ; N guillemotleft ; B 53 37 445 403 ;
-C 172 ; WX 333 ; N guilsinglleft ; B 51 37 281 403 ;
-C 173 ; WX 333 ; N guilsinglright ; B 52 37 282 403 ;
-C 174 ; WX 500 ; N fi ; B -141 -207 481 681 ;
-C 175 ; WX 500 ; N fl ; B -141 -204 518 682 ;
-C 177 ; WX 500 ; N endash ; B -6 197 505 243 ;
-C 178 ; WX 500 ; N dagger ; B 101 -159 488 666 ;
-C 179 ; WX 500 ; N daggerdbl ; B 22 -143 491 666 ;
-C 180 ; WX 250 ; N periodcentered ; B 70 199 181 310 ;
-C 182 ; WX 523 ; N paragraph ; B 55 -123 616 653 ;
-C 183 ; WX 350 ; N bullet ; B 40 191 310 461 ;
-C 184 ; WX 333 ; N quotesinglbase ; B 44 -129 183 101 ;
-C 185 ; WX 556 ; N quotedblbase ; B 57 -129 405 101 ;
-C 186 ; WX 556 ; N quotedblright ; B 151 436 499 666 ;
-C 187 ; WX 500 ; N guillemotright ; B 55 37 447 403 ;
-C 188 ; WX 889 ; N ellipsis ; B 57 -11 762 100 ;
-C 189 ; WX 1000 ; N perthousand ; B 25 -19 1010 706 ;
-C 191 ; WX 500 ; N questiondown ; B 28 -205 368 471 ;
-C 193 ; WX 333 ; N grave ; B 121 492 311 664 ;
-C 194 ; WX 333 ; N acute ; B 180 494 403 664 ;
-C 195 ; WX 333 ; N circumflex ; B 91 492 385 661 ;
-C 196 ; WX 333 ; N tilde ; B 100 517 427 624 ;
-C 197 ; WX 333 ; N macron ; B 99 532 411 583 ;
-C 198 ; WX 333 ; N breve ; B 117 492 418 650 ;
-C 199 ; WX 333 ; N dotaccent ; B 207 548 305 646 ;
-C 200 ; WX 333 ; N dieresis ; B 107 548 405 646 ;
-C 202 ; WX 333 ; N ring ; B 155 492 355 691 ;
-C 203 ; WX 333 ; N cedilla ; B -30 -217 182 0 ;
-C 205 ; WX 333 ; N hungarumlaut ; B 93 494 486 664 ;
-C 206 ; WX 333 ; N ogonek ; B 20 -169 203 40 ;
-C 207 ; WX 333 ; N caron ; B 121 492 426 661 ;
-C 208 ; WX 889 ; N emdash ; B -6 197 894 243 ;
-C 225 ; WX 889 ; N AE ; B -27 0 911 653 ;
-C 227 ; WX 276 ; N ordfeminine ; B 42 406 352 676 ;
-C 232 ; WX 556 ; N Lslash ; B -8 0 559 653 ;
-C 233 ; WX 722 ; N Oslash ; B 60 -105 699 722 ;
-C 234 ; WX 944 ; N OE ; B 49 -8 964 666 ;
-C 235 ; WX 310 ; N ordmasculine ; B 67 406 362 676 ;
-C 241 ; WX 667 ; N ae ; B 23 -11 640 441 ;
-C 245 ; WX 278 ; N dotlessi ; B 49 -11 235 441 ;
-C 248 ; WX 278 ; N lslash ; B 41 -11 312 683 ;
-C 249 ; WX 500 ; N oslash ; B 28 -135 469 554 ;
-C 250 ; WX 667 ; N oe ; B 20 -12 646 441 ;
-C 251 ; WX 500 ; N germandbls ; B -168 -207 493 679 ;
-C -1 ; WX 333 ; N Idieresis ; B -8 0 435 818 ;
-C -1 ; WX 444 ; N eacute ; B 31 -11 459 664 ;
-C -1 ; WX 500 ; N abreve ; B 17 -11 502 650 ;
-C -1 ; WX 500 ; N uhungarumlaut ; B 42 -11 580 664 ;
-C -1 ; WX 444 ; N ecaron ; B 31 -11 482 661 ;
-C -1 ; WX 556 ; N Ydieresis ; B 78 0 633 818 ;
-C -1 ; WX 675 ; N divide ; B 86 -11 590 517 ;
-C -1 ; WX 556 ; N Yacute ; B 78 0 633 876 ;
-C -1 ; WX 611 ; N Acircumflex ; B -51 0 564 873 ;
-C -1 ; WX 500 ; N aacute ; B 17 -11 487 664 ;
-C -1 ; WX 722 ; N Ucircumflex ; B 102 -18 765 873 ;
-C -1 ; WX 444 ; N yacute ; B -24 -206 459 664 ;
-C -1 ; WX 389 ; N scommaaccent ; B 16 -217 366 442 ;
-C -1 ; WX 444 ; N ecircumflex ; B 31 -11 441 661 ;
-C -1 ; WX 722 ; N Uring ; B 102 -18 765 883 ;
-C -1 ; WX 722 ; N Udieresis ; B 102 -18 765 818 ;
-C -1 ; WX 500 ; N aogonek ; B 17 -169 476 441 ;
-C -1 ; WX 722 ; N Uacute ; B 102 -18 765 876 ;
-C -1 ; WX 500 ; N uogonek ; B 42 -169 477 441 ;
-C -1 ; WX 611 ; N Edieresis ; B -1 0 634 818 ;
-C -1 ; WX 722 ; N Dcroat ; B -8 0 700 653 ;
-C -1 ; WX 250 ; N commaaccent ; B 8 -217 133 -50 ;
-C -1 ; WX 760 ; N copyright ; B 41 -18 719 666 ;
-C -1 ; WX 611 ; N Emacron ; B -1 0 634 795 ;
-C -1 ; WX 444 ; N ccaron ; B 30 -11 482 661 ;
-C -1 ; WX 500 ; N aring ; B 17 -11 476 691 ;
-C -1 ; WX 667 ; N Ncommaaccent ; B -20 -187 727 653 ;
-C -1 ; WX 278 ; N lacute ; B 41 -11 395 876 ;
-C -1 ; WX 500 ; N agrave ; B 17 -11 476 664 ;
-C -1 ; WX 556 ; N Tcommaaccent ; B 59 -217 633 653 ;
-C -1 ; WX 667 ; N Cacute ; B 66 -18 690 876 ;
-C -1 ; WX 500 ; N atilde ; B 17 -11 511 624 ;
-C -1 ; WX 611 ; N Edotaccent ; B -1 0 634 818 ;
-C -1 ; WX 389 ; N scaron ; B 16 -13 454 661 ;
-C -1 ; WX 389 ; N scedilla ; B 16 -217 366 442 ;
-C -1 ; WX 278 ; N iacute ; B 49 -11 355 664 ;
-C -1 ; WX 471 ; N lozenge ; B 13 0 459 724 ;
-C -1 ; WX 611 ; N Rcaron ; B -13 0 588 873 ;
-C -1 ; WX 722 ; N Gcommaaccent ; B 52 -217 722 666 ;
-C -1 ; WX 500 ; N ucircumflex ; B 42 -11 475 661 ;
-C -1 ; WX 500 ; N acircumflex ; B 17 -11 476 661 ;
-C -1 ; WX 611 ; N Amacron ; B -51 0 564 795 ;
-C -1 ; WX 389 ; N rcaron ; B 45 0 434 661 ;
-C -1 ; WX 444 ; N ccedilla ; B 30 -217 425 441 ;
-C -1 ; WX 556 ; N Zdotaccent ; B -6 0 606 818 ;
-C -1 ; WX 611 ; N Thorn ; B 0 0 569 653 ;
-C -1 ; WX 722 ; N Omacron ; B 60 -18 699 795 ;
-C -1 ; WX 611 ; N Racute ; B -13 0 588 876 ;
-C -1 ; WX 500 ; N Sacute ; B 17 -18 508 876 ;
-C -1 ; WX 544 ; N dcaron ; B 15 -13 658 683 ;
-C -1 ; WX 722 ; N Umacron ; B 102 -18 765 795 ;
-C -1 ; WX 500 ; N uring ; B 42 -11 475 691 ;
-C -1 ; WX 300 ; N threesuperior ; B 43 268 339 676 ;
-C -1 ; WX 722 ; N Ograve ; B 60 -18 699 876 ;
-C -1 ; WX 611 ; N Agrave ; B -51 0 564 876 ;
-C -1 ; WX 611 ; N Abreve ; B -51 0 564 862 ;
-C -1 ; WX 675 ; N multiply ; B 93 8 582 497 ;
-C -1 ; WX 500 ; N uacute ; B 42 -11 477 664 ;
-C -1 ; WX 556 ; N Tcaron ; B 59 0 633 873 ;
-C -1 ; WX 476 ; N partialdiff ; B 17 -38 459 710 ;
-C -1 ; WX 444 ; N ydieresis ; B -24 -206 441 606 ;
-C -1 ; WX 667 ; N Nacute ; B -20 -15 727 876 ;
-C -1 ; WX 278 ; N icircumflex ; B 33 -11 327 661 ;
-C -1 ; WX 611 ; N Ecircumflex ; B -1 0 634 873 ;
-C -1 ; WX 500 ; N adieresis ; B 17 -11 489 606 ;
-C -1 ; WX 444 ; N edieresis ; B 31 -11 451 606 ;
-C -1 ; WX 444 ; N cacute ; B 30 -11 459 664 ;
-C -1 ; WX 500 ; N nacute ; B 14 -9 477 664 ;
-C -1 ; WX 500 ; N umacron ; B 42 -11 485 583 ;
-C -1 ; WX 667 ; N Ncaron ; B -20 -15 727 873 ;
-C -1 ; WX 333 ; N Iacute ; B -8 0 433 876 ;
-C -1 ; WX 675 ; N plusminus ; B 86 0 590 506 ;
-C -1 ; WX 275 ; N brokenbar ; B 105 -142 171 708 ;
-C -1 ; WX 760 ; N registered ; B 41 -18 719 666 ;
-C -1 ; WX 722 ; N Gbreve ; B 52 -18 722 862 ;
-C -1 ; WX 333 ; N Idotaccent ; B -8 0 384 818 ;
-C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ;
-C -1 ; WX 611 ; N Egrave ; B -1 0 634 876 ;
-C -1 ; WX 389 ; N racute ; B 45 0 431 664 ;
-C -1 ; WX 500 ; N omacron ; B 27 -11 495 583 ;
-C -1 ; WX 556 ; N Zacute ; B -6 0 606 876 ;
-C -1 ; WX 556 ; N Zcaron ; B -6 0 606 873 ;
-C -1 ; WX 549 ; N greaterequal ; B 26 0 523 658 ;
-C -1 ; WX 722 ; N Eth ; B -8 0 700 653 ;
-C -1 ; WX 667 ; N Ccedilla ; B 66 -217 689 666 ;
-C -1 ; WX 278 ; N lcommaaccent ; B 22 -217 279 683 ;
-C -1 ; WX 300 ; N tcaron ; B 37 -11 407 681 ;
-C -1 ; WX 444 ; N eogonek ; B 31 -169 412 441 ;
-C -1 ; WX 722 ; N Uogonek ; B 102 -184 765 653 ;
-C -1 ; WX 611 ; N Aacute ; B -51 0 564 876 ;
-C -1 ; WX 611 ; N Adieresis ; B -51 0 564 818 ;
-C -1 ; WX 444 ; N egrave ; B 31 -11 412 664 ;
-C -1 ; WX 389 ; N zacute ; B -2 -81 431 664 ;
-C -1 ; WX 278 ; N iogonek ; B 49 -169 264 654 ;
-C -1 ; WX 722 ; N Oacute ; B 60 -18 699 876 ;
-C -1 ; WX 500 ; N oacute ; B 27 -11 487 664 ;
-C -1 ; WX 500 ; N amacron ; B 17 -11 495 583 ;
-C -1 ; WX 389 ; N sacute ; B 16 -13 431 664 ;
-C -1 ; WX 278 ; N idieresis ; B 49 -11 352 606 ;
-C -1 ; WX 722 ; N Ocircumflex ; B 60 -18 699 873 ;
-C -1 ; WX 722 ; N Ugrave ; B 102 -18 765 876 ;
-C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
-C -1 ; WX 500 ; N thorn ; B -75 -205 469 683 ;
-C -1 ; WX 300 ; N twosuperior ; B 33 271 324 676 ;
-C -1 ; WX 722 ; N Odieresis ; B 60 -18 699 818 ;
-C -1 ; WX 500 ; N mu ; B -30 -209 497 428 ;
-C -1 ; WX 278 ; N igrave ; B 49 -11 284 664 ;
-C -1 ; WX 500 ; N ohungarumlaut ; B 27 -11 590 664 ;
-C -1 ; WX 611 ; N Eogonek ; B -1 -169 634 653 ;
-C -1 ; WX 500 ; N dcroat ; B 15 -13 572 683 ;
-C -1 ; WX 750 ; N threequarters ; B 23 -10 736 676 ;
-C -1 ; WX 500 ; N Scedilla ; B 17 -217 508 667 ;
-C -1 ; WX 300 ; N lcaron ; B 41 -11 407 683 ;
-C -1 ; WX 667 ; N Kcommaaccent ; B 7 -217 722 653 ;
-C -1 ; WX 556 ; N Lacute ; B -8 0 559 876 ;
-C -1 ; WX 980 ; N trademark ; B 30 247 957 653 ;
-C -1 ; WX 444 ; N edotaccent ; B 31 -11 412 606 ;
-C -1 ; WX 333 ; N Igrave ; B -8 0 384 876 ;
-C -1 ; WX 333 ; N Imacron ; B -8 0 441 795 ;
-C -1 ; WX 611 ; N Lcaron ; B -8 0 586 653 ;
-C -1 ; WX 750 ; N onehalf ; B 34 -10 749 676 ;
-C -1 ; WX 549 ; N lessequal ; B 26 0 523 658 ;
-C -1 ; WX 500 ; N ocircumflex ; B 27 -11 468 661 ;
-C -1 ; WX 500 ; N ntilde ; B 14 -9 476 624 ;
-C -1 ; WX 722 ; N Uhungarumlaut ; B 102 -18 765 876 ;
-C -1 ; WX 611 ; N Eacute ; B -1 0 634 876 ;
-C -1 ; WX 444 ; N emacron ; B 31 -11 457 583 ;
-C -1 ; WX 500 ; N gbreve ; B 8 -206 487 650 ;
-C -1 ; WX 750 ; N onequarter ; B 33 -10 736 676 ;
-C -1 ; WX 500 ; N Scaron ; B 17 -18 520 873 ;
-C -1 ; WX 500 ; N Scommaaccent ; B 17 -217 508 667 ;
-C -1 ; WX 722 ; N Ohungarumlaut ; B 60 -18 699 876 ;
-C -1 ; WX 400 ; N degree ; B 101 390 387 676 ;
-C -1 ; WX 500 ; N ograve ; B 27 -11 468 664 ;
-C -1 ; WX 667 ; N Ccaron ; B 66 -18 689 873 ;
-C -1 ; WX 500 ; N ugrave ; B 42 -11 475 664 ;
-C -1 ; WX 453 ; N radical ; B 2 -60 452 768 ;
-C -1 ; WX 722 ; N Dcaron ; B -8 0 700 873 ;
-C -1 ; WX 389 ; N rcommaaccent ; B -3 -217 412 441 ;
-C -1 ; WX 667 ; N Ntilde ; B -20 -15 727 836 ;
-C -1 ; WX 500 ; N otilde ; B 27 -11 496 624 ;
-C -1 ; WX 611 ; N Rcommaaccent ; B -13 -187 588 653 ;
-C -1 ; WX 556 ; N Lcommaaccent ; B -8 -217 559 653 ;
-C -1 ; WX 611 ; N Atilde ; B -51 0 566 836 ;
-C -1 ; WX 611 ; N Aogonek ; B -51 -169 566 668 ;
-C -1 ; WX 611 ; N Aring ; B -51 0 564 883 ;
-C -1 ; WX 722 ; N Otilde ; B 60 -18 699 836 ;
-C -1 ; WX 389 ; N zdotaccent ; B -2 -81 380 606 ;
-C -1 ; WX 611 ; N Ecaron ; B -1 0 634 873 ;
-C -1 ; WX 333 ; N Iogonek ; B -8 -169 384 653 ;
-C -1 ; WX 444 ; N kcommaaccent ; B 14 -187 461 683 ;
-C -1 ; WX 675 ; N minus ; B 86 220 590 286 ;
-C -1 ; WX 333 ; N Icircumflex ; B -8 0 425 873 ;
-C -1 ; WX 500 ; N ncaron ; B 14 -9 510 661 ;
-C -1 ; WX 278 ; N tcommaaccent ; B 2 -217 296 546 ;
-C -1 ; WX 675 ; N logicalnot ; B 86 108 590 386 ;
-C -1 ; WX 500 ; N odieresis ; B 27 -11 489 606 ;
-C -1 ; WX 500 ; N udieresis ; B 42 -11 479 606 ;
-C -1 ; WX 549 ; N notequal ; B 12 -29 537 541 ;
-C -1 ; WX 500 ; N gcommaaccent ; B 8 -206 472 706 ;
-C -1 ; WX 500 ; N eth ; B 27 -11 482 683 ;
-C -1 ; WX 389 ; N zcaron ; B -2 -81 434 661 ;
-C -1 ; WX 500 ; N ncommaaccent ; B 14 -187 474 441 ;
-C -1 ; WX 300 ; N onesuperior ; B 43 271 284 676 ;
-C -1 ; WX 278 ; N imacron ; B 46 -11 311 583 ;
-C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ;
-EndCharMetrics
-StartKernData
-StartKernPairs 2321
-KPX A C -30
-KPX A Cacute -30
-KPX A Ccaron -30
-KPX A Ccedilla -30
-KPX A G -35
-KPX A Gbreve -35
-KPX A Gcommaaccent -35
-KPX A O -40
-KPX A Oacute -40
-KPX A Ocircumflex -40
-KPX A Odieresis -40
-KPX A Ograve -40
-KPX A Ohungarumlaut -40
-KPX A Omacron -40
-KPX A Oslash -40
-KPX A Otilde -40
-KPX A Q -40
-KPX A T -37
-KPX A Tcaron -37
-KPX A Tcommaaccent -37
-KPX A U -50
-KPX A Uacute -50
-KPX A Ucircumflex -50
-KPX A Udieresis -50
-KPX A Ugrave -50
-KPX A Uhungarumlaut -50
-KPX A Umacron -50
-KPX A Uogonek -50
-KPX A Uring -50
-KPX A V -105
-KPX A W -95
-KPX A Y -55
-KPX A Yacute -55
-KPX A Ydieresis -55
-KPX A quoteright -37
-KPX A u -20
-KPX A uacute -20
-KPX A ucircumflex -20
-KPX A udieresis -20
-KPX A ugrave -20
-KPX A uhungarumlaut -20
-KPX A umacron -20
-KPX A uogonek -20
-KPX A uring -20
-KPX A v -55
-KPX A w -55
-KPX A y -55
-KPX A yacute -55
-KPX A ydieresis -55
-KPX Aacute C -30
-KPX Aacute Cacute -30
-KPX Aacute Ccaron -30
-KPX Aacute Ccedilla -30
-KPX Aacute G -35
-KPX Aacute Gbreve -35
-KPX Aacute Gcommaaccent -35
-KPX Aacute O -40
-KPX Aacute Oacute -40
-KPX Aacute Ocircumflex -40
-KPX Aacute Odieresis -40
-KPX Aacute Ograve -40
-KPX Aacute Ohungarumlaut -40
-KPX Aacute Omacron -40
-KPX Aacute Oslash -40
-KPX Aacute Otilde -40
-KPX Aacute Q -40
-KPX Aacute T -37
-KPX Aacute Tcaron -37
-KPX Aacute Tcommaaccent -37
-KPX Aacute U -50
-KPX Aacute Uacute -50
-KPX Aacute Ucircumflex -50
-KPX Aacute Udieresis -50
-KPX Aacute Ugrave -50
-KPX Aacute Uhungarumlaut -50
-KPX Aacute Umacron -50
-KPX Aacute Uogonek -50
-KPX Aacute Uring -50
-KPX Aacute V -105
-KPX Aacute W -95
-KPX Aacute Y -55
-KPX Aacute Yacute -55
-KPX Aacute Ydieresis -55
-KPX Aacute quoteright -37
-KPX Aacute u -20
-KPX Aacute uacute -20
-KPX Aacute ucircumflex -20
-KPX Aacute udieresis -20
-KPX Aacute ugrave -20
-KPX Aacute uhungarumlaut -20
-KPX Aacute umacron -20
-KPX Aacute uogonek -20
-KPX Aacute uring -20
-KPX Aacute v -55
-KPX Aacute w -55
-KPX Aacute y -55
-KPX Aacute yacute -55
-KPX Aacute ydieresis -55
-KPX Abreve C -30
-KPX Abreve Cacute -30
-KPX Abreve Ccaron -30
-KPX Abreve Ccedilla -30
-KPX Abreve G -35
-KPX Abreve Gbreve -35
-KPX Abreve Gcommaaccent -35
-KPX Abreve O -40
-KPX Abreve Oacute -40
-KPX Abreve Ocircumflex -40
-KPX Abreve Odieresis -40
-KPX Abreve Ograve -40
-KPX Abreve Ohungarumlaut -40
-KPX Abreve Omacron -40
-KPX Abreve Oslash -40
-KPX Abreve Otilde -40
-KPX Abreve Q -40
-KPX Abreve T -37
-KPX Abreve Tcaron -37
-KPX Abreve Tcommaaccent -37
-KPX Abreve U -50
-KPX Abreve Uacute -50
-KPX Abreve Ucircumflex -50
-KPX Abreve Udieresis -50
-KPX Abreve Ugrave -50
-KPX Abreve Uhungarumlaut -50
-KPX Abreve Umacron -50
-KPX Abreve Uogonek -50
-KPX Abreve Uring -50
-KPX Abreve V -105
-KPX Abreve W -95
-KPX Abreve Y -55
-KPX Abreve Yacute -55
-KPX Abreve Ydieresis -55
-KPX Abreve quoteright -37
-KPX Abreve u -20
-KPX Abreve uacute -20
-KPX Abreve ucircumflex -20
-KPX Abreve udieresis -20
-KPX Abreve ugrave -20
-KPX Abreve uhungarumlaut -20
-KPX Abreve umacron -20
-KPX Abreve uogonek -20
-KPX Abreve uring -20
-KPX Abreve v -55
-KPX Abreve w -55
-KPX Abreve y -55
-KPX Abreve yacute -55
-KPX Abreve ydieresis -55
-KPX Acircumflex C -30
-KPX Acircumflex Cacute -30
-KPX Acircumflex Ccaron -30
-KPX Acircumflex Ccedilla -30
-KPX Acircumflex G -35
-KPX Acircumflex Gbreve -35
-KPX Acircumflex Gcommaaccent -35
-KPX Acircumflex O -40
-KPX Acircumflex Oacute -40
-KPX Acircumflex Ocircumflex -40
-KPX Acircumflex Odieresis -40
-KPX Acircumflex Ograve -40
-KPX Acircumflex Ohungarumlaut -40
-KPX Acircumflex Omacron -40
-KPX Acircumflex Oslash -40
-KPX Acircumflex Otilde -40
-KPX Acircumflex Q -40
-KPX Acircumflex T -37
-KPX Acircumflex Tcaron -37
-KPX Acircumflex Tcommaaccent -37
-KPX Acircumflex U -50
-KPX Acircumflex Uacute -50
-KPX Acircumflex Ucircumflex -50
-KPX Acircumflex Udieresis -50
-KPX Acircumflex Ugrave -50
-KPX Acircumflex Uhungarumlaut -50
-KPX Acircumflex Umacron -50
-KPX Acircumflex Uogonek -50
-KPX Acircumflex Uring -50
-KPX Acircumflex V -105
-KPX Acircumflex W -95
-KPX Acircumflex Y -55
-KPX Acircumflex Yacute -55
-KPX Acircumflex Ydieresis -55
-KPX Acircumflex quoteright -37
-KPX Acircumflex u -20
-KPX Acircumflex uacute -20
-KPX Acircumflex ucircumflex -20
-KPX Acircumflex udieresis -20
-KPX Acircumflex ugrave -20
-KPX Acircumflex uhungarumlaut -20
-KPX Acircumflex umacron -20
-KPX Acircumflex uogonek -20
-KPX Acircumflex uring -20
-KPX Acircumflex v -55
-KPX Acircumflex w -55
-KPX Acircumflex y -55
-KPX Acircumflex yacute -55
-KPX Acircumflex ydieresis -55
-KPX Adieresis C -30
-KPX Adieresis Cacute -30
-KPX Adieresis Ccaron -30
-KPX Adieresis Ccedilla -30
-KPX Adieresis G -35
-KPX Adieresis Gbreve -35
-KPX Adieresis Gcommaaccent -35
-KPX Adieresis O -40
-KPX Adieresis Oacute -40
-KPX Adieresis Ocircumflex -40
-KPX Adieresis Odieresis -40
-KPX Adieresis Ograve -40
-KPX Adieresis Ohungarumlaut -40
-KPX Adieresis Omacron -40
-KPX Adieresis Oslash -40
-KPX Adieresis Otilde -40
-KPX Adieresis Q -40
-KPX Adieresis T -37
-KPX Adieresis Tcaron -37
-KPX Adieresis Tcommaaccent -37
-KPX Adieresis U -50
-KPX Adieresis Uacute -50
-KPX Adieresis Ucircumflex -50
-KPX Adieresis Udieresis -50
-KPX Adieresis Ugrave -50
-KPX Adieresis Uhungarumlaut -50
-KPX Adieresis Umacron -50
-KPX Adieresis Uogonek -50
-KPX Adieresis Uring -50
-KPX Adieresis V -105
-KPX Adieresis W -95
-KPX Adieresis Y -55
-KPX Adieresis Yacute -55
-KPX Adieresis Ydieresis -55
-KPX Adieresis quoteright -37
-KPX Adieresis u -20
-KPX Adieresis uacute -20
-KPX Adieresis ucircumflex -20
-KPX Adieresis udieresis -20
-KPX Adieresis ugrave -20
-KPX Adieresis uhungarumlaut -20
-KPX Adieresis umacron -20
-KPX Adieresis uogonek -20
-KPX Adieresis uring -20
-KPX Adieresis v -55
-KPX Adieresis w -55
-KPX Adieresis y -55
-KPX Adieresis yacute -55
-KPX Adieresis ydieresis -55
-KPX Agrave C -30
-KPX Agrave Cacute -30
-KPX Agrave Ccaron -30
-KPX Agrave Ccedilla -30
-KPX Agrave G -35
-KPX Agrave Gbreve -35
-KPX Agrave Gcommaaccent -35
-KPX Agrave O -40
-KPX Agrave Oacute -40
-KPX Agrave Ocircumflex -40
-KPX Agrave Odieresis -40
-KPX Agrave Ograve -40
-KPX Agrave Ohungarumlaut -40
-KPX Agrave Omacron -40
-KPX Agrave Oslash -40
-KPX Agrave Otilde -40
-KPX Agrave Q -40
-KPX Agrave T -37
-KPX Agrave Tcaron -37
-KPX Agrave Tcommaaccent -37
-KPX Agrave U -50
-KPX Agrave Uacute -50
-KPX Agrave Ucircumflex -50
-KPX Agrave Udieresis -50
-KPX Agrave Ugrave -50
-KPX Agrave Uhungarumlaut -50
-KPX Agrave Umacron -50
-KPX Agrave Uogonek -50
-KPX Agrave Uring -50
-KPX Agrave V -105
-KPX Agrave W -95
-KPX Agrave Y -55
-KPX Agrave Yacute -55
-KPX Agrave Ydieresis -55
-KPX Agrave quoteright -37
-KPX Agrave u -20
-KPX Agrave uacute -20
-KPX Agrave ucircumflex -20
-KPX Agrave udieresis -20
-KPX Agrave ugrave -20
-KPX Agrave uhungarumlaut -20
-KPX Agrave umacron -20
-KPX Agrave uogonek -20
-KPX Agrave uring -20
-KPX Agrave v -55
-KPX Agrave w -55
-KPX Agrave y -55
-KPX Agrave yacute -55
-KPX Agrave ydieresis -55
-KPX Amacron C -30
-KPX Amacron Cacute -30
-KPX Amacron Ccaron -30
-KPX Amacron Ccedilla -30
-KPX Amacron G -35
-KPX Amacron Gbreve -35
-KPX Amacron Gcommaaccent -35
-KPX Amacron O -40
-KPX Amacron Oacute -40
-KPX Amacron Ocircumflex -40
-KPX Amacron Odieresis -40
-KPX Amacron Ograve -40
-KPX Amacron Ohungarumlaut -40
-KPX Amacron Omacron -40
-KPX Amacron Oslash -40
-KPX Amacron Otilde -40
-KPX Amacron Q -40
-KPX Amacron T -37
-KPX Amacron Tcaron -37
-KPX Amacron Tcommaaccent -37
-KPX Amacron U -50
-KPX Amacron Uacute -50
-KPX Amacron Ucircumflex -50
-KPX Amacron Udieresis -50
-KPX Amacron Ugrave -50
-KPX Amacron Uhungarumlaut -50
-KPX Amacron Umacron -50
-KPX Amacron Uogonek -50
-KPX Amacron Uring -50
-KPX Amacron V -105
-KPX Amacron W -95
-KPX Amacron Y -55
-KPX Amacron Yacute -55
-KPX Amacron Ydieresis -55
-KPX Amacron quoteright -37
-KPX Amacron u -20
-KPX Amacron uacute -20
-KPX Amacron ucircumflex -20
-KPX Amacron udieresis -20
-KPX Amacron ugrave -20
-KPX Amacron uhungarumlaut -20
-KPX Amacron umacron -20
-KPX Amacron uogonek -20
-KPX Amacron uring -20
-KPX Amacron v -55
-KPX Amacron w -55
-KPX Amacron y -55
-KPX Amacron yacute -55
-KPX Amacron ydieresis -55
-KPX Aogonek C -30
-KPX Aogonek Cacute -30
-KPX Aogonek Ccaron -30
-KPX Aogonek Ccedilla -30
-KPX Aogonek G -35
-KPX Aogonek Gbreve -35
-KPX Aogonek Gcommaaccent -35
-KPX Aogonek O -40
-KPX Aogonek Oacute -40
-KPX Aogonek Ocircumflex -40
-KPX Aogonek Odieresis -40
-KPX Aogonek Ograve -40
-KPX Aogonek Ohungarumlaut -40
-KPX Aogonek Omacron -40
-KPX Aogonek Oslash -40
-KPX Aogonek Otilde -40
-KPX Aogonek Q -40
-KPX Aogonek T -37
-KPX Aogonek Tcaron -37
-KPX Aogonek Tcommaaccent -37
-KPX Aogonek U -50
-KPX Aogonek Uacute -50
-KPX Aogonek Ucircumflex -50
-KPX Aogonek Udieresis -50
-KPX Aogonek Ugrave -50
-KPX Aogonek Uhungarumlaut -50
-KPX Aogonek Umacron -50
-KPX Aogonek Uogonek -50
-KPX Aogonek Uring -50
-KPX Aogonek V -105
-KPX Aogonek W -95
-KPX Aogonek Y -55
-KPX Aogonek Yacute -55
-KPX Aogonek Ydieresis -55
-KPX Aogonek quoteright -37
-KPX Aogonek u -20
-KPX Aogonek uacute -20
-KPX Aogonek ucircumflex -20
-KPX Aogonek udieresis -20
-KPX Aogonek ugrave -20
-KPX Aogonek uhungarumlaut -20
-KPX Aogonek umacron -20
-KPX Aogonek uogonek -20
-KPX Aogonek uring -20
-KPX Aogonek v -55
-KPX Aogonek w -55
-KPX Aogonek y -55
-KPX Aogonek yacute -55
-KPX Aogonek ydieresis -55
-KPX Aring C -30
-KPX Aring Cacute -30
-KPX Aring Ccaron -30
-KPX Aring Ccedilla -30
-KPX Aring G -35
-KPX Aring Gbreve -35
-KPX Aring Gcommaaccent -35
-KPX Aring O -40
-KPX Aring Oacute -40
-KPX Aring Ocircumflex -40
-KPX Aring Odieresis -40
-KPX Aring Ograve -40
-KPX Aring Ohungarumlaut -40
-KPX Aring Omacron -40
-KPX Aring Oslash -40
-KPX Aring Otilde -40
-KPX Aring Q -40
-KPX Aring T -37
-KPX Aring Tcaron -37
-KPX Aring Tcommaaccent -37
-KPX Aring U -50
-KPX Aring Uacute -50
-KPX Aring Ucircumflex -50
-KPX Aring Udieresis -50
-KPX Aring Ugrave -50
-KPX Aring Uhungarumlaut -50
-KPX Aring Umacron -50
-KPX Aring Uogonek -50
-KPX Aring Uring -50
-KPX Aring V -105
-KPX Aring W -95
-KPX Aring Y -55
-KPX Aring Yacute -55
-KPX Aring Ydieresis -55
-KPX Aring quoteright -37
-KPX Aring u -20
-KPX Aring uacute -20
-KPX Aring ucircumflex -20
-KPX Aring udieresis -20
-KPX Aring ugrave -20
-KPX Aring uhungarumlaut -20
-KPX Aring umacron -20
-KPX Aring uogonek -20
-KPX Aring uring -20
-KPX Aring v -55
-KPX Aring w -55
-KPX Aring y -55
-KPX Aring yacute -55
-KPX Aring ydieresis -55
-KPX Atilde C -30
-KPX Atilde Cacute -30
-KPX Atilde Ccaron -30
-KPX Atilde Ccedilla -30
-KPX Atilde G -35
-KPX Atilde Gbreve -35
-KPX Atilde Gcommaaccent -35
-KPX Atilde O -40
-KPX Atilde Oacute -40
-KPX Atilde Ocircumflex -40
-KPX Atilde Odieresis -40
-KPX Atilde Ograve -40
-KPX Atilde Ohungarumlaut -40
-KPX Atilde Omacron -40
-KPX Atilde Oslash -40
-KPX Atilde Otilde -40
-KPX Atilde Q -40
-KPX Atilde T -37
-KPX Atilde Tcaron -37
-KPX Atilde Tcommaaccent -37
-KPX Atilde U -50
-KPX Atilde Uacute -50
-KPX Atilde Ucircumflex -50
-KPX Atilde Udieresis -50
-KPX Atilde Ugrave -50
-KPX Atilde Uhungarumlaut -50
-KPX Atilde Umacron -50
-KPX Atilde Uogonek -50
-KPX Atilde Uring -50
-KPX Atilde V -105
-KPX Atilde W -95
-KPX Atilde Y -55
-KPX Atilde Yacute -55
-KPX Atilde Ydieresis -55
-KPX Atilde quoteright -37
-KPX Atilde u -20
-KPX Atilde uacute -20
-KPX Atilde ucircumflex -20
-KPX Atilde udieresis -20
-KPX Atilde ugrave -20
-KPX Atilde uhungarumlaut -20
-KPX Atilde umacron -20
-KPX Atilde uogonek -20
-KPX Atilde uring -20
-KPX Atilde v -55
-KPX Atilde w -55
-KPX Atilde y -55
-KPX Atilde yacute -55
-KPX Atilde ydieresis -55
-KPX B A -25
-KPX B Aacute -25
-KPX B Abreve -25
-KPX B Acircumflex -25
-KPX B Adieresis -25
-KPX B Agrave -25
-KPX B Amacron -25
-KPX B Aogonek -25
-KPX B Aring -25
-KPX B Atilde -25
-KPX B U -10
-KPX B Uacute -10
-KPX B Ucircumflex -10
-KPX B Udieresis -10
-KPX B Ugrave -10
-KPX B Uhungarumlaut -10
-KPX B Umacron -10
-KPX B Uogonek -10
-KPX B Uring -10
-KPX D A -35
-KPX D Aacute -35
-KPX D Abreve -35
-KPX D Acircumflex -35
-KPX D Adieresis -35
-KPX D Agrave -35
-KPX D Amacron -35
-KPX D Aogonek -35
-KPX D Aring -35
-KPX D Atilde -35
-KPX D V -40
-KPX D W -40
-KPX D Y -40
-KPX D Yacute -40
-KPX D Ydieresis -40
-KPX Dcaron A -35
-KPX Dcaron Aacute -35
-KPX Dcaron Abreve -35
-KPX Dcaron Acircumflex -35
-KPX Dcaron Adieresis -35
-KPX Dcaron Agrave -35
-KPX Dcaron Amacron -35
-KPX Dcaron Aogonek -35
-KPX Dcaron Aring -35
-KPX Dcaron Atilde -35
-KPX Dcaron V -40
-KPX Dcaron W -40
-KPX Dcaron Y -40
-KPX Dcaron Yacute -40
-KPX Dcaron Ydieresis -40
-KPX Dcroat A -35
-KPX Dcroat Aacute -35
-KPX Dcroat Abreve -35
-KPX Dcroat Acircumflex -35
-KPX Dcroat Adieresis -35
-KPX Dcroat Agrave -35
-KPX Dcroat Amacron -35
-KPX Dcroat Aogonek -35
-KPX Dcroat Aring -35
-KPX Dcroat Atilde -35
-KPX Dcroat V -40
-KPX Dcroat W -40
-KPX Dcroat Y -40
-KPX Dcroat Yacute -40
-KPX Dcroat Ydieresis -40
-KPX F A -115
-KPX F Aacute -115
-KPX F Abreve -115
-KPX F Acircumflex -115
-KPX F Adieresis -115
-KPX F Agrave -115
-KPX F Amacron -115
-KPX F Aogonek -115
-KPX F Aring -115
-KPX F Atilde -115
-KPX F a -75
-KPX F aacute -75
-KPX F abreve -75
-KPX F acircumflex -75
-KPX F adieresis -75
-KPX F agrave -75
-KPX F amacron -75
-KPX F aogonek -75
-KPX F aring -75
-KPX F atilde -75
-KPX F comma -135
-KPX F e -75
-KPX F eacute -75
-KPX F ecaron -75
-KPX F ecircumflex -75
-KPX F edieresis -75
-KPX F edotaccent -75
-KPX F egrave -75
-KPX F emacron -75
-KPX F eogonek -75
-KPX F i -45
-KPX F iacute -45
-KPX F icircumflex -45
-KPX F idieresis -45
-KPX F igrave -45
-KPX F imacron -45
-KPX F iogonek -45
-KPX F o -105
-KPX F oacute -105
-KPX F ocircumflex -105
-KPX F odieresis -105
-KPX F ograve -105
-KPX F ohungarumlaut -105
-KPX F omacron -105
-KPX F oslash -105
-KPX F otilde -105
-KPX F period -135
-KPX F r -55
-KPX F racute -55
-KPX F rcaron -55
-KPX F rcommaaccent -55
-KPX J A -40
-KPX J Aacute -40
-KPX J Abreve -40
-KPX J Acircumflex -40
-KPX J Adieresis -40
-KPX J Agrave -40
-KPX J Amacron -40
-KPX J Aogonek -40
-KPX J Aring -40
-KPX J Atilde -40
-KPX J a -35
-KPX J aacute -35
-KPX J abreve -35
-KPX J acircumflex -35
-KPX J adieresis -35
-KPX J agrave -35
-KPX J amacron -35
-KPX J aogonek -35
-KPX J aring -35
-KPX J atilde -35
-KPX J comma -25
-KPX J e -25
-KPX J eacute -25
-KPX J ecaron -25
-KPX J ecircumflex -25
-KPX J edieresis -25
-KPX J edotaccent -25
-KPX J egrave -25
-KPX J emacron -25
-KPX J eogonek -25
-KPX J o -25
-KPX J oacute -25
-KPX J ocircumflex -25
-KPX J odieresis -25
-KPX J ograve -25
-KPX J ohungarumlaut -25
-KPX J omacron -25
-KPX J oslash -25
-KPX J otilde -25
-KPX J period -25
-KPX J u -35
-KPX J uacute -35
-KPX J ucircumflex -35
-KPX J udieresis -35
-KPX J ugrave -35
-KPX J uhungarumlaut -35
-KPX J umacron -35
-KPX J uogonek -35
-KPX J uring -35
-KPX K O -50
-KPX K Oacute -50
-KPX K Ocircumflex -50
-KPX K Odieresis -50
-KPX K Ograve -50
-KPX K Ohungarumlaut -50
-KPX K Omacron -50
-KPX K Oslash -50
-KPX K Otilde -50
-KPX K e -35
-KPX K eacute -35
-KPX K ecaron -35
-KPX K ecircumflex -35
-KPX K edieresis -35
-KPX K edotaccent -35
-KPX K egrave -35
-KPX K emacron -35
-KPX K eogonek -35
-KPX K o -40
-KPX K oacute -40
-KPX K ocircumflex -40
-KPX K odieresis -40
-KPX K ograve -40
-KPX K ohungarumlaut -40
-KPX K omacron -40
-KPX K oslash -40
-KPX K otilde -40
-KPX K u -40
-KPX K uacute -40
-KPX K ucircumflex -40
-KPX K udieresis -40
-KPX K ugrave -40
-KPX K uhungarumlaut -40
-KPX K umacron -40
-KPX K uogonek -40
-KPX K uring -40
-KPX K y -40
-KPX K yacute -40
-KPX K ydieresis -40
-KPX Kcommaaccent O -50
-KPX Kcommaaccent Oacute -50
-KPX Kcommaaccent Ocircumflex -50
-KPX Kcommaaccent Odieresis -50
-KPX Kcommaaccent Ograve -50
-KPX Kcommaaccent Ohungarumlaut -50
-KPX Kcommaaccent Omacron -50
-KPX Kcommaaccent Oslash -50
-KPX Kcommaaccent Otilde -50
-KPX Kcommaaccent e -35
-KPX Kcommaaccent eacute -35
-KPX Kcommaaccent ecaron -35
-KPX Kcommaaccent ecircumflex -35
-KPX Kcommaaccent edieresis -35
-KPX Kcommaaccent edotaccent -35
-KPX Kcommaaccent egrave -35
-KPX Kcommaaccent emacron -35
-KPX Kcommaaccent eogonek -35
-KPX Kcommaaccent o -40
-KPX Kcommaaccent oacute -40
-KPX Kcommaaccent ocircumflex -40
-KPX Kcommaaccent odieresis -40
-KPX Kcommaaccent ograve -40
-KPX Kcommaaccent ohungarumlaut -40
-KPX Kcommaaccent omacron -40
-KPX Kcommaaccent oslash -40
-KPX Kcommaaccent otilde -40
-KPX Kcommaaccent u -40
-KPX Kcommaaccent uacute -40
-KPX Kcommaaccent ucircumflex -40
-KPX Kcommaaccent udieresis -40
-KPX Kcommaaccent ugrave -40
-KPX Kcommaaccent uhungarumlaut -40
-KPX Kcommaaccent umacron -40
-KPX Kcommaaccent uogonek -40
-KPX Kcommaaccent uring -40
-KPX Kcommaaccent y -40
-KPX Kcommaaccent yacute -40
-KPX Kcommaaccent ydieresis -40
-KPX L T -20
-KPX L Tcaron -20
-KPX L Tcommaaccent -20
-KPX L V -55
-KPX L W -55
-KPX L Y -20
-KPX L Yacute -20
-KPX L Ydieresis -20
-KPX L quoteright -37
-KPX L y -30
-KPX L yacute -30
-KPX L ydieresis -30
-KPX Lacute T -20
-KPX Lacute Tcaron -20
-KPX Lacute Tcommaaccent -20
-KPX Lacute V -55
-KPX Lacute W -55
-KPX Lacute Y -20
-KPX Lacute Yacute -20
-KPX Lacute Ydieresis -20
-KPX Lacute quoteright -37
-KPX Lacute y -30
-KPX Lacute yacute -30
-KPX Lacute ydieresis -30
-KPX Lcommaaccent T -20
-KPX Lcommaaccent Tcaron -20
-KPX Lcommaaccent Tcommaaccent -20
-KPX Lcommaaccent V -55
-KPX Lcommaaccent W -55
-KPX Lcommaaccent Y -20
-KPX Lcommaaccent Yacute -20
-KPX Lcommaaccent Ydieresis -20
-KPX Lcommaaccent quoteright -37
-KPX Lcommaaccent y -30
-KPX Lcommaaccent yacute -30
-KPX Lcommaaccent ydieresis -30
-KPX Lslash T -20
-KPX Lslash Tcaron -20
-KPX Lslash Tcommaaccent -20
-KPX Lslash V -55
-KPX Lslash W -55
-KPX Lslash Y -20
-KPX Lslash Yacute -20
-KPX Lslash Ydieresis -20
-KPX Lslash quoteright -37
-KPX Lslash y -30
-KPX Lslash yacute -30
-KPX Lslash ydieresis -30
-KPX N A -27
-KPX N Aacute -27
-KPX N Abreve -27
-KPX N Acircumflex -27
-KPX N Adieresis -27
-KPX N Agrave -27
-KPX N Amacron -27
-KPX N Aogonek -27
-KPX N Aring -27
-KPX N Atilde -27
-KPX Nacute A -27
-KPX Nacute Aacute -27
-KPX Nacute Abreve -27
-KPX Nacute Acircumflex -27
-KPX Nacute Adieresis -27
-KPX Nacute Agrave -27
-KPX Nacute Amacron -27
-KPX Nacute Aogonek -27
-KPX Nacute Aring -27
-KPX Nacute Atilde -27
-KPX Ncaron A -27
-KPX Ncaron Aacute -27
-KPX Ncaron Abreve -27
-KPX Ncaron Acircumflex -27
-KPX Ncaron Adieresis -27
-KPX Ncaron Agrave -27
-KPX Ncaron Amacron -27
-KPX Ncaron Aogonek -27
-KPX Ncaron Aring -27
-KPX Ncaron Atilde -27
-KPX Ncommaaccent A -27
-KPX Ncommaaccent Aacute -27
-KPX Ncommaaccent Abreve -27
-KPX Ncommaaccent Acircumflex -27
-KPX Ncommaaccent Adieresis -27
-KPX Ncommaaccent Agrave -27
-KPX Ncommaaccent Amacron -27
-KPX Ncommaaccent Aogonek -27
-KPX Ncommaaccent Aring -27
-KPX Ncommaaccent Atilde -27
-KPX Ntilde A -27
-KPX Ntilde Aacute -27
-KPX Ntilde Abreve -27
-KPX Ntilde Acircumflex -27
-KPX Ntilde Adieresis -27
-KPX Ntilde Agrave -27
-KPX Ntilde Amacron -27
-KPX Ntilde Aogonek -27
-KPX Ntilde Aring -27
-KPX Ntilde Atilde -27
-KPX O A -55
-KPX O Aacute -55
-KPX O Abreve -55
-KPX O Acircumflex -55
-KPX O Adieresis -55
-KPX O Agrave -55
-KPX O Amacron -55
-KPX O Aogonek -55
-KPX O Aring -55
-KPX O Atilde -55
-KPX O T -40
-KPX O Tcaron -40
-KPX O Tcommaaccent -40
-KPX O V -50
-KPX O W -50
-KPX O X -40
-KPX O Y -50
-KPX O Yacute -50
-KPX O Ydieresis -50
-KPX Oacute A -55
-KPX Oacute Aacute -55
-KPX Oacute Abreve -55
-KPX Oacute Acircumflex -55
-KPX Oacute Adieresis -55
-KPX Oacute Agrave -55
-KPX Oacute Amacron -55
-KPX Oacute Aogonek -55
-KPX Oacute Aring -55
-KPX Oacute Atilde -55
-KPX Oacute T -40
-KPX Oacute Tcaron -40
-KPX Oacute Tcommaaccent -40
-KPX Oacute V -50
-KPX Oacute W -50
-KPX Oacute X -40
-KPX Oacute Y -50
-KPX Oacute Yacute -50
-KPX Oacute Ydieresis -50
-KPX Ocircumflex A -55
-KPX Ocircumflex Aacute -55
-KPX Ocircumflex Abreve -55
-KPX Ocircumflex Acircumflex -55
-KPX Ocircumflex Adieresis -55
-KPX Ocircumflex Agrave -55
-KPX Ocircumflex Amacron -55
-KPX Ocircumflex Aogonek -55
-KPX Ocircumflex Aring -55
-KPX Ocircumflex Atilde -55
-KPX Ocircumflex T -40
-KPX Ocircumflex Tcaron -40
-KPX Ocircumflex Tcommaaccent -40
-KPX Ocircumflex V -50
-KPX Ocircumflex W -50
-KPX Ocircumflex X -40
-KPX Ocircumflex Y -50
-KPX Ocircumflex Yacute -50
-KPX Ocircumflex Ydieresis -50
-KPX Odieresis A -55
-KPX Odieresis Aacute -55
-KPX Odieresis Abreve -55
-KPX Odieresis Acircumflex -55
-KPX Odieresis Adieresis -55
-KPX Odieresis Agrave -55
-KPX Odieresis Amacron -55
-KPX Odieresis Aogonek -55
-KPX Odieresis Aring -55
-KPX Odieresis Atilde -55
-KPX Odieresis T -40
-KPX Odieresis Tcaron -40
-KPX Odieresis Tcommaaccent -40
-KPX Odieresis V -50
-KPX Odieresis W -50
-KPX Odieresis X -40
-KPX Odieresis Y -50
-KPX Odieresis Yacute -50
-KPX Odieresis Ydieresis -50
-KPX Ograve A -55
-KPX Ograve Aacute -55
-KPX Ograve Abreve -55
-KPX Ograve Acircumflex -55
-KPX Ograve Adieresis -55
-KPX Ograve Agrave -55
-KPX Ograve Amacron -55
-KPX Ograve Aogonek -55
-KPX Ograve Aring -55
-KPX Ograve Atilde -55
-KPX Ograve T -40
-KPX Ograve Tcaron -40
-KPX Ograve Tcommaaccent -40
-KPX Ograve V -50
-KPX Ograve W -50
-KPX Ograve X -40
-KPX Ograve Y -50
-KPX Ograve Yacute -50
-KPX Ograve Ydieresis -50
-KPX Ohungarumlaut A -55
-KPX Ohungarumlaut Aacute -55
-KPX Ohungarumlaut Abreve -55
-KPX Ohungarumlaut Acircumflex -55
-KPX Ohungarumlaut Adieresis -55
-KPX Ohungarumlaut Agrave -55
-KPX Ohungarumlaut Amacron -55
-KPX Ohungarumlaut Aogonek -55
-KPX Ohungarumlaut Aring -55
-KPX Ohungarumlaut Atilde -55
-KPX Ohungarumlaut T -40
-KPX Ohungarumlaut Tcaron -40
-KPX Ohungarumlaut Tcommaaccent -40
-KPX Ohungarumlaut V -50
-KPX Ohungarumlaut W -50
-KPX Ohungarumlaut X -40
-KPX Ohungarumlaut Y -50
-KPX Ohungarumlaut Yacute -50
-KPX Ohungarumlaut Ydieresis -50
-KPX Omacron A -55
-KPX Omacron Aacute -55
-KPX Omacron Abreve -55
-KPX Omacron Acircumflex -55
-KPX Omacron Adieresis -55
-KPX Omacron Agrave -55
-KPX Omacron Amacron -55
-KPX Omacron Aogonek -55
-KPX Omacron Aring -55
-KPX Omacron Atilde -55
-KPX Omacron T -40
-KPX Omacron Tcaron -40
-KPX Omacron Tcommaaccent -40
-KPX Omacron V -50
-KPX Omacron W -50
-KPX Omacron X -40
-KPX Omacron Y -50
-KPX Omacron Yacute -50
-KPX Omacron Ydieresis -50
-KPX Oslash A -55
-KPX Oslash Aacute -55
-KPX Oslash Abreve -55
-KPX Oslash Acircumflex -55
-KPX Oslash Adieresis -55
-KPX Oslash Agrave -55
-KPX Oslash Amacron -55
-KPX Oslash Aogonek -55
-KPX Oslash Aring -55
-KPX Oslash Atilde -55
-KPX Oslash T -40
-KPX Oslash Tcaron -40
-KPX Oslash Tcommaaccent -40
-KPX Oslash V -50
-KPX Oslash W -50
-KPX Oslash X -40
-KPX Oslash Y -50
-KPX Oslash Yacute -50
-KPX Oslash Ydieresis -50
-KPX Otilde A -55
-KPX Otilde Aacute -55
-KPX Otilde Abreve -55
-KPX Otilde Acircumflex -55
-KPX Otilde Adieresis -55
-KPX Otilde Agrave -55
-KPX Otilde Amacron -55
-KPX Otilde Aogonek -55
-KPX Otilde Aring -55
-KPX Otilde Atilde -55
-KPX Otilde T -40
-KPX Otilde Tcaron -40
-KPX Otilde Tcommaaccent -40
-KPX Otilde V -50
-KPX Otilde W -50
-KPX Otilde X -40
-KPX Otilde Y -50
-KPX Otilde Yacute -50
-KPX Otilde Ydieresis -50
-KPX P A -90
-KPX P Aacute -90
-KPX P Abreve -90
-KPX P Acircumflex -90
-KPX P Adieresis -90
-KPX P Agrave -90
-KPX P Amacron -90
-KPX P Aogonek -90
-KPX P Aring -90
-KPX P Atilde -90
-KPX P a -80
-KPX P aacute -80
-KPX P abreve -80
-KPX P acircumflex -80
-KPX P adieresis -80
-KPX P agrave -80
-KPX P amacron -80
-KPX P aogonek -80
-KPX P aring -80
-KPX P atilde -80
-KPX P comma -135
-KPX P e -80
-KPX P eacute -80
-KPX P ecaron -80
-KPX P ecircumflex -80
-KPX P edieresis -80
-KPX P edotaccent -80
-KPX P egrave -80
-KPX P emacron -80
-KPX P eogonek -80
-KPX P o -80
-KPX P oacute -80
-KPX P ocircumflex -80
-KPX P odieresis -80
-KPX P ograve -80
-KPX P ohungarumlaut -80
-KPX P omacron -80
-KPX P oslash -80
-KPX P otilde -80
-KPX P period -135
-KPX Q U -10
-KPX Q Uacute -10
-KPX Q Ucircumflex -10
-KPX Q Udieresis -10
-KPX Q Ugrave -10
-KPX Q Uhungarumlaut -10
-KPX Q Umacron -10
-KPX Q Uogonek -10
-KPX Q Uring -10
-KPX R O -40
-KPX R Oacute -40
-KPX R Ocircumflex -40
-KPX R Odieresis -40
-KPX R Ograve -40
-KPX R Ohungarumlaut -40
-KPX R Omacron -40
-KPX R Oslash -40
-KPX R Otilde -40
-KPX R U -40
-KPX R Uacute -40
-KPX R Ucircumflex -40
-KPX R Udieresis -40
-KPX R Ugrave -40
-KPX R Uhungarumlaut -40
-KPX R Umacron -40
-KPX R Uogonek -40
-KPX R Uring -40
-KPX R V -18
-KPX R W -18
-KPX R Y -18
-KPX R Yacute -18
-KPX R Ydieresis -18
-KPX Racute O -40
-KPX Racute Oacute -40
-KPX Racute Ocircumflex -40
-KPX Racute Odieresis -40
-KPX Racute Ograve -40
-KPX Racute Ohungarumlaut -40
-KPX Racute Omacron -40
-KPX Racute Oslash -40
-KPX Racute Otilde -40
-KPX Racute U -40
-KPX Racute Uacute -40
-KPX Racute Ucircumflex -40
-KPX Racute Udieresis -40
-KPX Racute Ugrave -40
-KPX Racute Uhungarumlaut -40
-KPX Racute Umacron -40
-KPX Racute Uogonek -40
-KPX Racute Uring -40
-KPX Racute V -18
-KPX Racute W -18
-KPX Racute Y -18
-KPX Racute Yacute -18
-KPX Racute Ydieresis -18
-KPX Rcaron O -40
-KPX Rcaron Oacute -40
-KPX Rcaron Ocircumflex -40
-KPX Rcaron Odieresis -40
-KPX Rcaron Ograve -40
-KPX Rcaron Ohungarumlaut -40
-KPX Rcaron Omacron -40
-KPX Rcaron Oslash -40
-KPX Rcaron Otilde -40
-KPX Rcaron U -40
-KPX Rcaron Uacute -40
-KPX Rcaron Ucircumflex -40
-KPX Rcaron Udieresis -40
-KPX Rcaron Ugrave -40
-KPX Rcaron Uhungarumlaut -40
-KPX Rcaron Umacron -40
-KPX Rcaron Uogonek -40
-KPX Rcaron Uring -40
-KPX Rcaron V -18
-KPX Rcaron W -18
-KPX Rcaron Y -18
-KPX Rcaron Yacute -18
-KPX Rcaron Ydieresis -18
-KPX Rcommaaccent O -40
-KPX Rcommaaccent Oacute -40
-KPX Rcommaaccent Ocircumflex -40
-KPX Rcommaaccent Odieresis -40
-KPX Rcommaaccent Ograve -40
-KPX Rcommaaccent Ohungarumlaut -40
-KPX Rcommaaccent Omacron -40
-KPX Rcommaaccent Oslash -40
-KPX Rcommaaccent Otilde -40
-KPX Rcommaaccent U -40
-KPX Rcommaaccent Uacute -40
-KPX Rcommaaccent Ucircumflex -40
-KPX Rcommaaccent Udieresis -40
-KPX Rcommaaccent Ugrave -40
-KPX Rcommaaccent Uhungarumlaut -40
-KPX Rcommaaccent Umacron -40
-KPX Rcommaaccent Uogonek -40
-KPX Rcommaaccent Uring -40
-KPX Rcommaaccent V -18
-KPX Rcommaaccent W -18
-KPX Rcommaaccent Y -18
-KPX Rcommaaccent Yacute -18
-KPX Rcommaaccent Ydieresis -18
-KPX T A -50
-KPX T Aacute -50
-KPX T Abreve -50
-KPX T Acircumflex -50
-KPX T Adieresis -50
-KPX T Agrave -50
-KPX T Amacron -50
-KPX T Aogonek -50
-KPX T Aring -50
-KPX T Atilde -50
-KPX T O -18
-KPX T Oacute -18
-KPX T Ocircumflex -18
-KPX T Odieresis -18
-KPX T Ograve -18
-KPX T Ohungarumlaut -18
-KPX T Omacron -18
-KPX T Oslash -18
-KPX T Otilde -18
-KPX T a -92
-KPX T aacute -92
-KPX T abreve -92
-KPX T acircumflex -92
-KPX T adieresis -92
-KPX T agrave -92
-KPX T amacron -92
-KPX T aogonek -92
-KPX T aring -92
-KPX T atilde -92
-KPX T colon -55
-KPX T comma -74
-KPX T e -92
-KPX T eacute -92
-KPX T ecaron -92
-KPX T ecircumflex -52
-KPX T edieresis -52
-KPX T edotaccent -92
-KPX T egrave -52
-KPX T emacron -52
-KPX T eogonek -92
-KPX T hyphen -74
-KPX T i -55
-KPX T iacute -55
-KPX T iogonek -55
-KPX T o -92
-KPX T oacute -92
-KPX T ocircumflex -92
-KPX T odieresis -92
-KPX T ograve -92
-KPX T ohungarumlaut -92
-KPX T omacron -92
-KPX T oslash -92
-KPX T otilde -92
-KPX T period -74
-KPX T r -55
-KPX T racute -55
-KPX T rcaron -55
-KPX T rcommaaccent -55
-KPX T semicolon -65
-KPX T u -55
-KPX T uacute -55
-KPX T ucircumflex -55
-KPX T udieresis -55
-KPX T ugrave -55
-KPX T uhungarumlaut -55
-KPX T umacron -55
-KPX T uogonek -55
-KPX T uring -55
-KPX T w -74
-KPX T y -74
-KPX T yacute -74
-KPX T ydieresis -34
-KPX Tcaron A -50
-KPX Tcaron Aacute -50
-KPX Tcaron Abreve -50
-KPX Tcaron Acircumflex -50
-KPX Tcaron Adieresis -50
-KPX Tcaron Agrave -50
-KPX Tcaron Amacron -50
-KPX Tcaron Aogonek -50
-KPX Tcaron Aring -50
-KPX Tcaron Atilde -50
-KPX Tcaron O -18
-KPX Tcaron Oacute -18
-KPX Tcaron Ocircumflex -18
-KPX Tcaron Odieresis -18
-KPX Tcaron Ograve -18
-KPX Tcaron Ohungarumlaut -18
-KPX Tcaron Omacron -18
-KPX Tcaron Oslash -18
-KPX Tcaron Otilde -18
-KPX Tcaron a -92
-KPX Tcaron aacute -92
-KPX Tcaron abreve -92
-KPX Tcaron acircumflex -92
-KPX Tcaron adieresis -92
-KPX Tcaron agrave -92
-KPX Tcaron amacron -92
-KPX Tcaron aogonek -92
-KPX Tcaron aring -92
-KPX Tcaron atilde -92
-KPX Tcaron colon -55
-KPX Tcaron comma -74
-KPX Tcaron e -92
-KPX Tcaron eacute -92
-KPX Tcaron ecaron -92
-KPX Tcaron ecircumflex -52
-KPX Tcaron edieresis -52
-KPX Tcaron edotaccent -92
-KPX Tcaron egrave -52
-KPX Tcaron emacron -52
-KPX Tcaron eogonek -92
-KPX Tcaron hyphen -74
-KPX Tcaron i -55
-KPX Tcaron iacute -55
-KPX Tcaron iogonek -55
-KPX Tcaron o -92
-KPX Tcaron oacute -92
-KPX Tcaron ocircumflex -92
-KPX Tcaron odieresis -92
-KPX Tcaron ograve -92
-KPX Tcaron ohungarumlaut -92
-KPX Tcaron omacron -92
-KPX Tcaron oslash -92
-KPX Tcaron otilde -92
-KPX Tcaron period -74
-KPX Tcaron r -55
-KPX Tcaron racute -55
-KPX Tcaron rcaron -55
-KPX Tcaron rcommaaccent -55
-KPX Tcaron semicolon -65
-KPX Tcaron u -55
-KPX Tcaron uacute -55
-KPX Tcaron ucircumflex -55
-KPX Tcaron udieresis -55
-KPX Tcaron ugrave -55
-KPX Tcaron uhungarumlaut -55
-KPX Tcaron umacron -55
-KPX Tcaron uogonek -55
-KPX Tcaron uring -55
-KPX Tcaron w -74
-KPX Tcaron y -74
-KPX Tcaron yacute -74
-KPX Tcaron ydieresis -34
-KPX Tcommaaccent A -50
-KPX Tcommaaccent Aacute -50
-KPX Tcommaaccent Abreve -50
-KPX Tcommaaccent Acircumflex -50
-KPX Tcommaaccent Adieresis -50
-KPX Tcommaaccent Agrave -50
-KPX Tcommaaccent Amacron -50
-KPX Tcommaaccent Aogonek -50
-KPX Tcommaaccent Aring -50
-KPX Tcommaaccent Atilde -50
-KPX Tcommaaccent O -18
-KPX Tcommaaccent Oacute -18
-KPX Tcommaaccent Ocircumflex -18
-KPX Tcommaaccent Odieresis -18
-KPX Tcommaaccent Ograve -18
-KPX Tcommaaccent Ohungarumlaut -18
-KPX Tcommaaccent Omacron -18
-KPX Tcommaaccent Oslash -18
-KPX Tcommaaccent Otilde -18
-KPX Tcommaaccent a -92
-KPX Tcommaaccent aacute -92
-KPX Tcommaaccent abreve -92
-KPX Tcommaaccent acircumflex -92
-KPX Tcommaaccent adieresis -92
-KPX Tcommaaccent agrave -92
-KPX Tcommaaccent amacron -92
-KPX Tcommaaccent aogonek -92
-KPX Tcommaaccent aring -92
-KPX Tcommaaccent atilde -92
-KPX Tcommaaccent colon -55
-KPX Tcommaaccent comma -74
-KPX Tcommaaccent e -92
-KPX Tcommaaccent eacute -92
-KPX Tcommaaccent ecaron -92
-KPX Tcommaaccent ecircumflex -52
-KPX Tcommaaccent edieresis -52
-KPX Tcommaaccent edotaccent -92
-KPX Tcommaaccent egrave -52
-KPX Tcommaaccent emacron -52
-KPX Tcommaaccent eogonek -92
-KPX Tcommaaccent hyphen -74
-KPX Tcommaaccent i -55
-KPX Tcommaaccent iacute -55
-KPX Tcommaaccent iogonek -55
-KPX Tcommaaccent o -92
-KPX Tcommaaccent oacute -92
-KPX Tcommaaccent ocircumflex -92
-KPX Tcommaaccent odieresis -92
-KPX Tcommaaccent ograve -92
-KPX Tcommaaccent ohungarumlaut -92
-KPX Tcommaaccent omacron -92
-KPX Tcommaaccent oslash -92
-KPX Tcommaaccent otilde -92
-KPX Tcommaaccent period -74
-KPX Tcommaaccent r -55
-KPX Tcommaaccent racute -55
-KPX Tcommaaccent rcaron -55
-KPX Tcommaaccent rcommaaccent -55
-KPX Tcommaaccent semicolon -65
-KPX Tcommaaccent u -55
-KPX Tcommaaccent uacute -55
-KPX Tcommaaccent ucircumflex -55
-KPX Tcommaaccent udieresis -55
-KPX Tcommaaccent ugrave -55
-KPX Tcommaaccent uhungarumlaut -55
-KPX Tcommaaccent umacron -55
-KPX Tcommaaccent uogonek -55
-KPX Tcommaaccent uring -55
-KPX Tcommaaccent w -74
-KPX Tcommaaccent y -74
-KPX Tcommaaccent yacute -74
-KPX Tcommaaccent ydieresis -34
-KPX U A -40
-KPX U Aacute -40
-KPX U Abreve -40
-KPX U Acircumflex -40
-KPX U Adieresis -40
-KPX U Agrave -40
-KPX U Amacron -40
-KPX U Aogonek -40
-KPX U Aring -40
-KPX U Atilde -40
-KPX U comma -25
-KPX U period -25
-KPX Uacute A -40
-KPX Uacute Aacute -40
-KPX Uacute Abreve -40
-KPX Uacute Acircumflex -40
-KPX Uacute Adieresis -40
-KPX Uacute Agrave -40
-KPX Uacute Amacron -40
-KPX Uacute Aogonek -40
-KPX Uacute Aring -40
-KPX Uacute Atilde -40
-KPX Uacute comma -25
-KPX Uacute period -25
-KPX Ucircumflex A -40
-KPX Ucircumflex Aacute -40
-KPX Ucircumflex Abreve -40
-KPX Ucircumflex Acircumflex -40
-KPX Ucircumflex Adieresis -40
-KPX Ucircumflex Agrave -40
-KPX Ucircumflex Amacron -40
-KPX Ucircumflex Aogonek -40
-KPX Ucircumflex Aring -40
-KPX Ucircumflex Atilde -40
-KPX Ucircumflex comma -25
-KPX Ucircumflex period -25
-KPX Udieresis A -40
-KPX Udieresis Aacute -40
-KPX Udieresis Abreve -40
-KPX Udieresis Acircumflex -40
-KPX Udieresis Adieresis -40
-KPX Udieresis Agrave -40
-KPX Udieresis Amacron -40
-KPX Udieresis Aogonek -40
-KPX Udieresis Aring -40
-KPX Udieresis Atilde -40
-KPX Udieresis comma -25
-KPX Udieresis period -25
-KPX Ugrave A -40
-KPX Ugrave Aacute -40
-KPX Ugrave Abreve -40
-KPX Ugrave Acircumflex -40
-KPX Ugrave Adieresis -40
-KPX Ugrave Agrave -40
-KPX Ugrave Amacron -40
-KPX Ugrave Aogonek -40
-KPX Ugrave Aring -40
-KPX Ugrave Atilde -40
-KPX Ugrave comma -25
-KPX Ugrave period -25
-KPX Uhungarumlaut A -40
-KPX Uhungarumlaut Aacute -40
-KPX Uhungarumlaut Abreve -40
-KPX Uhungarumlaut Acircumflex -40
-KPX Uhungarumlaut Adieresis -40
-KPX Uhungarumlaut Agrave -40
-KPX Uhungarumlaut Amacron -40
-KPX Uhungarumlaut Aogonek -40
-KPX Uhungarumlaut Aring -40
-KPX Uhungarumlaut Atilde -40
-KPX Uhungarumlaut comma -25
-KPX Uhungarumlaut period -25
-KPX Umacron A -40
-KPX Umacron Aacute -40
-KPX Umacron Abreve -40
-KPX Umacron Acircumflex -40
-KPX Umacron Adieresis -40
-KPX Umacron Agrave -40
-KPX Umacron Amacron -40
-KPX Umacron Aogonek -40
-KPX Umacron Aring -40
-KPX Umacron Atilde -40
-KPX Umacron comma -25
-KPX Umacron period -25
-KPX Uogonek A -40
-KPX Uogonek Aacute -40
-KPX Uogonek Abreve -40
-KPX Uogonek Acircumflex -40
-KPX Uogonek Adieresis -40
-KPX Uogonek Agrave -40
-KPX Uogonek Amacron -40
-KPX Uogonek Aogonek -40
-KPX Uogonek Aring -40
-KPX Uogonek Atilde -40
-KPX Uogonek comma -25
-KPX Uogonek period -25
-KPX Uring A -40
-KPX Uring Aacute -40
-KPX Uring Abreve -40
-KPX Uring Acircumflex -40
-KPX Uring Adieresis -40
-KPX Uring Agrave -40
-KPX Uring Amacron -40
-KPX Uring Aogonek -40
-KPX Uring Aring -40
-KPX Uring Atilde -40
-KPX Uring comma -25
-KPX Uring period -25
-KPX V A -60
-KPX V Aacute -60
-KPX V Abreve -60
-KPX V Acircumflex -60
-KPX V Adieresis -60
-KPX V Agrave -60
-KPX V Amacron -60
-KPX V Aogonek -60
-KPX V Aring -60
-KPX V Atilde -60
-KPX V O -30
-KPX V Oacute -30
-KPX V Ocircumflex -30
-KPX V Odieresis -30
-KPX V Ograve -30
-KPX V Ohungarumlaut -30
-KPX V Omacron -30
-KPX V Oslash -30
-KPX V Otilde -30
-KPX V a -111
-KPX V aacute -111
-KPX V abreve -111
-KPX V acircumflex -111
-KPX V adieresis -111
-KPX V agrave -111
-KPX V amacron -111
-KPX V aogonek -111
-KPX V aring -111
-KPX V atilde -111
-KPX V colon -65
-KPX V comma -129
-KPX V e -111
-KPX V eacute -111
-KPX V ecaron -111
-KPX V ecircumflex -111
-KPX V edieresis -71
-KPX V edotaccent -111
-KPX V egrave -71
-KPX V emacron -71
-KPX V eogonek -111
-KPX V hyphen -55
-KPX V i -74
-KPX V iacute -74
-KPX V icircumflex -34
-KPX V idieresis -34
-KPX V igrave -34
-KPX V imacron -34
-KPX V iogonek -74
-KPX V o -111
-KPX V oacute -111
-KPX V ocircumflex -111
-KPX V odieresis -111
-KPX V ograve -111
-KPX V ohungarumlaut -111
-KPX V omacron -111
-KPX V oslash -111
-KPX V otilde -111
-KPX V period -129
-KPX V semicolon -74
-KPX V u -74
-KPX V uacute -74
-KPX V ucircumflex -74
-KPX V udieresis -74
-KPX V ugrave -74
-KPX V uhungarumlaut -74
-KPX V umacron -74
-KPX V uogonek -74
-KPX V uring -74
-KPX W A -60
-KPX W Aacute -60
-KPX W Abreve -60
-KPX W Acircumflex -60
-KPX W Adieresis -60
-KPX W Agrave -60
-KPX W Amacron -60
-KPX W Aogonek -60
-KPX W Aring -60
-KPX W Atilde -60
-KPX W O -25
-KPX W Oacute -25
-KPX W Ocircumflex -25
-KPX W Odieresis -25
-KPX W Ograve -25
-KPX W Ohungarumlaut -25
-KPX W Omacron -25
-KPX W Oslash -25
-KPX W Otilde -25
-KPX W a -92
-KPX W aacute -92
-KPX W abreve -92
-KPX W acircumflex -92
-KPX W adieresis -92
-KPX W agrave -92
-KPX W amacron -92
-KPX W aogonek -92
-KPX W aring -92
-KPX W atilde -92
-KPX W colon -65
-KPX W comma -92
-KPX W e -92
-KPX W eacute -92
-KPX W ecaron -92
-KPX W ecircumflex -92
-KPX W edieresis -52
-KPX W edotaccent -92
-KPX W egrave -52
-KPX W emacron -52
-KPX W eogonek -92
-KPX W hyphen -37
-KPX W i -55
-KPX W iacute -55
-KPX W iogonek -55
-KPX W o -92
-KPX W oacute -92
-KPX W ocircumflex -92
-KPX W odieresis -92
-KPX W ograve -92
-KPX W ohungarumlaut -92
-KPX W omacron -92
-KPX W oslash -92
-KPX W otilde -92
-KPX W period -92
-KPX W semicolon -65
-KPX W u -55
-KPX W uacute -55
-KPX W ucircumflex -55
-KPX W udieresis -55
-KPX W ugrave -55
-KPX W uhungarumlaut -55
-KPX W umacron -55
-KPX W uogonek -55
-KPX W uring -55
-KPX W y -70
-KPX W yacute -70
-KPX W ydieresis -70
-KPX Y A -50
-KPX Y Aacute -50
-KPX Y Abreve -50
-KPX Y Acircumflex -50
-KPX Y Adieresis -50
-KPX Y Agrave -50
-KPX Y Amacron -50
-KPX Y Aogonek -50
-KPX Y Aring -50
-KPX Y Atilde -50
-KPX Y O -15
-KPX Y Oacute -15
-KPX Y Ocircumflex -15
-KPX Y Odieresis -15
-KPX Y Ograve -15
-KPX Y Ohungarumlaut -15
-KPX Y Omacron -15
-KPX Y Oslash -15
-KPX Y Otilde -15
-KPX Y a -92
-KPX Y aacute -92
-KPX Y abreve -92
-KPX Y acircumflex -92
-KPX Y adieresis -92
-KPX Y agrave -92
-KPX Y amacron -92
-KPX Y aogonek -92
-KPX Y aring -92
-KPX Y atilde -92
-KPX Y colon -65
-KPX Y comma -92
-KPX Y e -92
-KPX Y eacute -92
-KPX Y ecaron -92
-KPX Y ecircumflex -92
-KPX Y edieresis -52
-KPX Y edotaccent -92
-KPX Y egrave -52
-KPX Y emacron -52
-KPX Y eogonek -92
-KPX Y hyphen -74
-KPX Y i -74
-KPX Y iacute -74
-KPX Y icircumflex -34
-KPX Y idieresis -34
-KPX Y igrave -34
-KPX Y imacron -34
-KPX Y iogonek -74
-KPX Y o -92
-KPX Y oacute -92
-KPX Y ocircumflex -92
-KPX Y odieresis -92
-KPX Y ograve -92
-KPX Y ohungarumlaut -92
-KPX Y omacron -92
-KPX Y oslash -92
-KPX Y otilde -92
-KPX Y period -92
-KPX Y semicolon -65
-KPX Y u -92
-KPX Y uacute -92
-KPX Y ucircumflex -92
-KPX Y udieresis -92
-KPX Y ugrave -92
-KPX Y uhungarumlaut -92
-KPX Y umacron -92
-KPX Y uogonek -92
-KPX Y uring -92
-KPX Yacute A -50
-KPX Yacute Aacute -50
-KPX Yacute Abreve -50
-KPX Yacute Acircumflex -50
-KPX Yacute Adieresis -50
-KPX Yacute Agrave -50
-KPX Yacute Amacron -50
-KPX Yacute Aogonek -50
-KPX Yacute Aring -50
-KPX Yacute Atilde -50
-KPX Yacute O -15
-KPX Yacute Oacute -15
-KPX Yacute Ocircumflex -15
-KPX Yacute Odieresis -15
-KPX Yacute Ograve -15
-KPX Yacute Ohungarumlaut -15
-KPX Yacute Omacron -15
-KPX Yacute Oslash -15
-KPX Yacute Otilde -15
-KPX Yacute a -92
-KPX Yacute aacute -92
-KPX Yacute abreve -92
-KPX Yacute acircumflex -92
-KPX Yacute adieresis -92
-KPX Yacute agrave -92
-KPX Yacute amacron -92
-KPX Yacute aogonek -92
-KPX Yacute aring -92
-KPX Yacute atilde -92
-KPX Yacute colon -65
-KPX Yacute comma -92
-KPX Yacute e -92
-KPX Yacute eacute -92
-KPX Yacute ecaron -92
-KPX Yacute ecircumflex -92
-KPX Yacute edieresis -52
-KPX Yacute edotaccent -92
-KPX Yacute egrave -52
-KPX Yacute emacron -52
-KPX Yacute eogonek -92
-KPX Yacute hyphen -74
-KPX Yacute i -74
-KPX Yacute iacute -74
-KPX Yacute icircumflex -34
-KPX Yacute idieresis -34
-KPX Yacute igrave -34
-KPX Yacute imacron -34
-KPX Yacute iogonek -74
-KPX Yacute o -92
-KPX Yacute oacute -92
-KPX Yacute ocircumflex -92
-KPX Yacute odieresis -92
-KPX Yacute ograve -92
-KPX Yacute ohungarumlaut -92
-KPX Yacute omacron -92
-KPX Yacute oslash -92
-KPX Yacute otilde -92
-KPX Yacute period -92
-KPX Yacute semicolon -65
-KPX Yacute u -92
-KPX Yacute uacute -92
-KPX Yacute ucircumflex -92
-KPX Yacute udieresis -92
-KPX Yacute ugrave -92
-KPX Yacute uhungarumlaut -92
-KPX Yacute umacron -92
-KPX Yacute uogonek -92
-KPX Yacute uring -92
-KPX Ydieresis A -50
-KPX Ydieresis Aacute -50
-KPX Ydieresis Abreve -50
-KPX Ydieresis Acircumflex -50
-KPX Ydieresis Adieresis -50
-KPX Ydieresis Agrave -50
-KPX Ydieresis Amacron -50
-KPX Ydieresis Aogonek -50
-KPX Ydieresis Aring -50
-KPX Ydieresis Atilde -50
-KPX Ydieresis O -15
-KPX Ydieresis Oacute -15
-KPX Ydieresis Ocircumflex -15
-KPX Ydieresis Odieresis -15
-KPX Ydieresis Ograve -15
-KPX Ydieresis Ohungarumlaut -15
-KPX Ydieresis Omacron -15
-KPX Ydieresis Oslash -15
-KPX Ydieresis Otilde -15
-KPX Ydieresis a -92
-KPX Ydieresis aacute -92
-KPX Ydieresis abreve -92
-KPX Ydieresis acircumflex -92
-KPX Ydieresis adieresis -92
-KPX Ydieresis agrave -92
-KPX Ydieresis amacron -92
-KPX Ydieresis aogonek -92
-KPX Ydieresis aring -92
-KPX Ydieresis atilde -92
-KPX Ydieresis colon -65
-KPX Ydieresis comma -92
-KPX Ydieresis e -92
-KPX Ydieresis eacute -92
-KPX Ydieresis ecaron -92
-KPX Ydieresis ecircumflex -92
-KPX Ydieresis edieresis -52
-KPX Ydieresis edotaccent -92
-KPX Ydieresis egrave -52
-KPX Ydieresis emacron -52
-KPX Ydieresis eogonek -92
-KPX Ydieresis hyphen -74
-KPX Ydieresis i -74
-KPX Ydieresis iacute -74
-KPX Ydieresis icircumflex -34
-KPX Ydieresis idieresis -34
-KPX Ydieresis igrave -34
-KPX Ydieresis imacron -34
-KPX Ydieresis iogonek -74
-KPX Ydieresis o -92
-KPX Ydieresis oacute -92
-KPX Ydieresis ocircumflex -92
-KPX Ydieresis odieresis -92
-KPX Ydieresis ograve -92
-KPX Ydieresis ohungarumlaut -92
-KPX Ydieresis omacron -92
-KPX Ydieresis oslash -92
-KPX Ydieresis otilde -92
-KPX Ydieresis period -92
-KPX Ydieresis semicolon -65
-KPX Ydieresis u -92
-KPX Ydieresis uacute -92
-KPX Ydieresis ucircumflex -92
-KPX Ydieresis udieresis -92
-KPX Ydieresis ugrave -92
-KPX Ydieresis uhungarumlaut -92
-KPX Ydieresis umacron -92
-KPX Ydieresis uogonek -92
-KPX Ydieresis uring -92
-KPX a g -10
-KPX a gbreve -10
-KPX a gcommaaccent -10
-KPX aacute g -10
-KPX aacute gbreve -10
-KPX aacute gcommaaccent -10
-KPX abreve g -10
-KPX abreve gbreve -10
-KPX abreve gcommaaccent -10
-KPX acircumflex g -10
-KPX acircumflex gbreve -10
-KPX acircumflex gcommaaccent -10
-KPX adieresis g -10
-KPX adieresis gbreve -10
-KPX adieresis gcommaaccent -10
-KPX agrave g -10
-KPX agrave gbreve -10
-KPX agrave gcommaaccent -10
-KPX amacron g -10
-KPX amacron gbreve -10
-KPX amacron gcommaaccent -10
-KPX aogonek g -10
-KPX aogonek gbreve -10
-KPX aogonek gcommaaccent -10
-KPX aring g -10
-KPX aring gbreve -10
-KPX aring gcommaaccent -10
-KPX atilde g -10
-KPX atilde gbreve -10
-KPX atilde gcommaaccent -10
-KPX b period -40
-KPX b u -20
-KPX b uacute -20
-KPX b ucircumflex -20
-KPX b udieresis -20
-KPX b ugrave -20
-KPX b uhungarumlaut -20
-KPX b umacron -20
-KPX b uogonek -20
-KPX b uring -20
-KPX c h -15
-KPX c k -20
-KPX c kcommaaccent -20
-KPX cacute h -15
-KPX cacute k -20
-KPX cacute kcommaaccent -20
-KPX ccaron h -15
-KPX ccaron k -20
-KPX ccaron kcommaaccent -20
-KPX ccedilla h -15
-KPX ccedilla k -20
-KPX ccedilla kcommaaccent -20
-KPX comma quotedblright -140
-KPX comma quoteright -140
-KPX e comma -10
-KPX e g -40
-KPX e gbreve -40
-KPX e gcommaaccent -40
-KPX e period -15
-KPX e v -15
-KPX e w -15
-KPX e x -20
-KPX e y -30
-KPX e yacute -30
-KPX e ydieresis -30
-KPX eacute comma -10
-KPX eacute g -40
-KPX eacute gbreve -40
-KPX eacute gcommaaccent -40
-KPX eacute period -15
-KPX eacute v -15
-KPX eacute w -15
-KPX eacute x -20
-KPX eacute y -30
-KPX eacute yacute -30
-KPX eacute ydieresis -30
-KPX ecaron comma -10
-KPX ecaron g -40
-KPX ecaron gbreve -40
-KPX ecaron gcommaaccent -40
-KPX ecaron period -15
-KPX ecaron v -15
-KPX ecaron w -15
-KPX ecaron x -20
-KPX ecaron y -30
-KPX ecaron yacute -30
-KPX ecaron ydieresis -30
-KPX ecircumflex comma -10
-KPX ecircumflex g -40
-KPX ecircumflex gbreve -40
-KPX ecircumflex gcommaaccent -40
-KPX ecircumflex period -15
-KPX ecircumflex v -15
-KPX ecircumflex w -15
-KPX ecircumflex x -20
-KPX ecircumflex y -30
-KPX ecircumflex yacute -30
-KPX ecircumflex ydieresis -30
-KPX edieresis comma -10
-KPX edieresis g -40
-KPX edieresis gbreve -40
-KPX edieresis gcommaaccent -40
-KPX edieresis period -15
-KPX edieresis v -15
-KPX edieresis w -15
-KPX edieresis x -20
-KPX edieresis y -30
-KPX edieresis yacute -30
-KPX edieresis ydieresis -30
-KPX edotaccent comma -10
-KPX edotaccent g -40
-KPX edotaccent gbreve -40
-KPX edotaccent gcommaaccent -40
-KPX edotaccent period -15
-KPX edotaccent v -15
-KPX edotaccent w -15
-KPX edotaccent x -20
-KPX edotaccent y -30
-KPX edotaccent yacute -30
-KPX edotaccent ydieresis -30
-KPX egrave comma -10
-KPX egrave g -40
-KPX egrave gbreve -40
-KPX egrave gcommaaccent -40
-KPX egrave period -15
-KPX egrave v -15
-KPX egrave w -15
-KPX egrave x -20
-KPX egrave y -30
-KPX egrave yacute -30
-KPX egrave ydieresis -30
-KPX emacron comma -10
-KPX emacron g -40
-KPX emacron gbreve -40
-KPX emacron gcommaaccent -40
-KPX emacron period -15
-KPX emacron v -15
-KPX emacron w -15
-KPX emacron x -20
-KPX emacron y -30
-KPX emacron yacute -30
-KPX emacron ydieresis -30
-KPX eogonek comma -10
-KPX eogonek g -40
-KPX eogonek gbreve -40
-KPX eogonek gcommaaccent -40
-KPX eogonek period -15
-KPX eogonek v -15
-KPX eogonek w -15
-KPX eogonek x -20
-KPX eogonek y -30
-KPX eogonek yacute -30
-KPX eogonek ydieresis -30
-KPX f comma -10
-KPX f dotlessi -60
-KPX f f -18
-KPX f i -20
-KPX f iogonek -20
-KPX f period -15
-KPX f quoteright 92
-KPX g comma -10
-KPX g e -10
-KPX g eacute -10
-KPX g ecaron -10
-KPX g ecircumflex -10
-KPX g edieresis -10
-KPX g edotaccent -10
-KPX g egrave -10
-KPX g emacron -10
-KPX g eogonek -10
-KPX g g -10
-KPX g gbreve -10
-KPX g gcommaaccent -10
-KPX g period -15
-KPX gbreve comma -10
-KPX gbreve e -10
-KPX gbreve eacute -10
-KPX gbreve ecaron -10
-KPX gbreve ecircumflex -10
-KPX gbreve edieresis -10
-KPX gbreve edotaccent -10
-KPX gbreve egrave -10
-KPX gbreve emacron -10
-KPX gbreve eogonek -10
-KPX gbreve g -10
-KPX gbreve gbreve -10
-KPX gbreve gcommaaccent -10
-KPX gbreve period -15
-KPX gcommaaccent comma -10
-KPX gcommaaccent e -10
-KPX gcommaaccent eacute -10
-KPX gcommaaccent ecaron -10
-KPX gcommaaccent ecircumflex -10
-KPX gcommaaccent edieresis -10
-KPX gcommaaccent edotaccent -10
-KPX gcommaaccent egrave -10
-KPX gcommaaccent emacron -10
-KPX gcommaaccent eogonek -10
-KPX gcommaaccent g -10
-KPX gcommaaccent gbreve -10
-KPX gcommaaccent gcommaaccent -10
-KPX gcommaaccent period -15
-KPX k e -10
-KPX k eacute -10
-KPX k ecaron -10
-KPX k ecircumflex -10
-KPX k edieresis -10
-KPX k edotaccent -10
-KPX k egrave -10
-KPX k emacron -10
-KPX k eogonek -10
-KPX k o -10
-KPX k oacute -10
-KPX k ocircumflex -10
-KPX k odieresis -10
-KPX k ograve -10
-KPX k ohungarumlaut -10
-KPX k omacron -10
-KPX k oslash -10
-KPX k otilde -10
-KPX k y -10
-KPX k yacute -10
-KPX k ydieresis -10
-KPX kcommaaccent e -10
-KPX kcommaaccent eacute -10
-KPX kcommaaccent ecaron -10
-KPX kcommaaccent ecircumflex -10
-KPX kcommaaccent edieresis -10
-KPX kcommaaccent edotaccent -10
-KPX kcommaaccent egrave -10
-KPX kcommaaccent emacron -10
-KPX kcommaaccent eogonek -10
-KPX kcommaaccent o -10
-KPX kcommaaccent oacute -10
-KPX kcommaaccent ocircumflex -10
-KPX kcommaaccent odieresis -10
-KPX kcommaaccent ograve -10
-KPX kcommaaccent ohungarumlaut -10
-KPX kcommaaccent omacron -10
-KPX kcommaaccent oslash -10
-KPX kcommaaccent otilde -10
-KPX kcommaaccent y -10
-KPX kcommaaccent yacute -10
-KPX kcommaaccent ydieresis -10
-KPX n v -40
-KPX nacute v -40
-KPX ncaron v -40
-KPX ncommaaccent v -40
-KPX ntilde v -40
-KPX o g -10
-KPX o gbreve -10
-KPX o gcommaaccent -10
-KPX o v -10
-KPX oacute g -10
-KPX oacute gbreve -10
-KPX oacute gcommaaccent -10
-KPX oacute v -10
-KPX ocircumflex g -10
-KPX ocircumflex gbreve -10
-KPX ocircumflex gcommaaccent -10
-KPX ocircumflex v -10
-KPX odieresis g -10
-KPX odieresis gbreve -10
-KPX odieresis gcommaaccent -10
-KPX odieresis v -10
-KPX ograve g -10
-KPX ograve gbreve -10
-KPX ograve gcommaaccent -10
-KPX ograve v -10
-KPX ohungarumlaut g -10
-KPX ohungarumlaut gbreve -10
-KPX ohungarumlaut gcommaaccent -10
-KPX ohungarumlaut v -10
-KPX omacron g -10
-KPX omacron gbreve -10
-KPX omacron gcommaaccent -10
-KPX omacron v -10
-KPX oslash g -10
-KPX oslash gbreve -10
-KPX oslash gcommaaccent -10
-KPX oslash v -10
-KPX otilde g -10
-KPX otilde gbreve -10
-KPX otilde gcommaaccent -10
-KPX otilde v -10
-KPX period quotedblright -140
-KPX period quoteright -140
-KPX quoteleft quoteleft -111
-KPX quoteright d -25
-KPX quoteright dcroat -25
-KPX quoteright quoteright -111
-KPX quoteright r -25
-KPX quoteright racute -25
-KPX quoteright rcaron -25
-KPX quoteright rcommaaccent -25
-KPX quoteright s -40
-KPX quoteright sacute -40
-KPX quoteright scaron -40
-KPX quoteright scedilla -40
-KPX quoteright scommaaccent -40
-KPX quoteright space -111
-KPX quoteright t -30
-KPX quoteright tcommaaccent -30
-KPX quoteright v -10
-KPX r a -15
-KPX r aacute -15
-KPX r abreve -15
-KPX r acircumflex -15
-KPX r adieresis -15
-KPX r agrave -15
-KPX r amacron -15
-KPX r aogonek -15
-KPX r aring -15
-KPX r atilde -15
-KPX r c -37
-KPX r cacute -37
-KPX r ccaron -37
-KPX r ccedilla -37
-KPX r comma -111
-KPX r d -37
-KPX r dcroat -37
-KPX r e -37
-KPX r eacute -37
-KPX r ecaron -37
-KPX r ecircumflex -37
-KPX r edieresis -37
-KPX r edotaccent -37
-KPX r egrave -37
-KPX r emacron -37
-KPX r eogonek -37
-KPX r g -37
-KPX r gbreve -37
-KPX r gcommaaccent -37
-KPX r hyphen -20
-KPX r o -45
-KPX r oacute -45
-KPX r ocircumflex -45
-KPX r odieresis -45
-KPX r ograve -45
-KPX r ohungarumlaut -45
-KPX r omacron -45
-KPX r oslash -45
-KPX r otilde -45
-KPX r period -111
-KPX r q -37
-KPX r s -10
-KPX r sacute -10
-KPX r scaron -10
-KPX r scedilla -10
-KPX r scommaaccent -10
-KPX racute a -15
-KPX racute aacute -15
-KPX racute abreve -15
-KPX racute acircumflex -15
-KPX racute adieresis -15
-KPX racute agrave -15
-KPX racute amacron -15
-KPX racute aogonek -15
-KPX racute aring -15
-KPX racute atilde -15
-KPX racute c -37
-KPX racute cacute -37
-KPX racute ccaron -37
-KPX racute ccedilla -37
-KPX racute comma -111
-KPX racute d -37
-KPX racute dcroat -37
-KPX racute e -37
-KPX racute eacute -37
-KPX racute ecaron -37
-KPX racute ecircumflex -37
-KPX racute edieresis -37
-KPX racute edotaccent -37
-KPX racute egrave -37
-KPX racute emacron -37
-KPX racute eogonek -37
-KPX racute g -37
-KPX racute gbreve -37
-KPX racute gcommaaccent -37
-KPX racute hyphen -20
-KPX racute o -45
-KPX racute oacute -45
-KPX racute ocircumflex -45
-KPX racute odieresis -45
-KPX racute ograve -45
-KPX racute ohungarumlaut -45
-KPX racute omacron -45
-KPX racute oslash -45
-KPX racute otilde -45
-KPX racute period -111
-KPX racute q -37
-KPX racute s -10
-KPX racute sacute -10
-KPX racute scaron -10
-KPX racute scedilla -10
-KPX racute scommaaccent -10
-KPX rcaron a -15
-KPX rcaron aacute -15
-KPX rcaron abreve -15
-KPX rcaron acircumflex -15
-KPX rcaron adieresis -15
-KPX rcaron agrave -15
-KPX rcaron amacron -15
-KPX rcaron aogonek -15
-KPX rcaron aring -15
-KPX rcaron atilde -15
-KPX rcaron c -37
-KPX rcaron cacute -37
-KPX rcaron ccaron -37
-KPX rcaron ccedilla -37
-KPX rcaron comma -111
-KPX rcaron d -37
-KPX rcaron dcroat -37
-KPX rcaron e -37
-KPX rcaron eacute -37
-KPX rcaron ecaron -37
-KPX rcaron ecircumflex -37
-KPX rcaron edieresis -37
-KPX rcaron edotaccent -37
-KPX rcaron egrave -37
-KPX rcaron emacron -37
-KPX rcaron eogonek -37
-KPX rcaron g -37
-KPX rcaron gbreve -37
-KPX rcaron gcommaaccent -37
-KPX rcaron hyphen -20
-KPX rcaron o -45
-KPX rcaron oacute -45
-KPX rcaron ocircumflex -45
-KPX rcaron odieresis -45
-KPX rcaron ograve -45
-KPX rcaron ohungarumlaut -45
-KPX rcaron omacron -45
-KPX rcaron oslash -45
-KPX rcaron otilde -45
-KPX rcaron period -111
-KPX rcaron q -37
-KPX rcaron s -10
-KPX rcaron sacute -10
-KPX rcaron scaron -10
-KPX rcaron scedilla -10
-KPX rcaron scommaaccent -10
-KPX rcommaaccent a -15
-KPX rcommaaccent aacute -15
-KPX rcommaaccent abreve -15
-KPX rcommaaccent acircumflex -15
-KPX rcommaaccent adieresis -15
-KPX rcommaaccent agrave -15
-KPX rcommaaccent amacron -15
-KPX rcommaaccent aogonek -15
-KPX rcommaaccent aring -15
-KPX rcommaaccent atilde -15
-KPX rcommaaccent c -37
-KPX rcommaaccent cacute -37
-KPX rcommaaccent ccaron -37
-KPX rcommaaccent ccedilla -37
-KPX rcommaaccent comma -111
-KPX rcommaaccent d -37
-KPX rcommaaccent dcroat -37
-KPX rcommaaccent e -37
-KPX rcommaaccent eacute -37
-KPX rcommaaccent ecaron -37
-KPX rcommaaccent ecircumflex -37
-KPX rcommaaccent edieresis -37
-KPX rcommaaccent edotaccent -37
-KPX rcommaaccent egrave -37
-KPX rcommaaccent emacron -37
-KPX rcommaaccent eogonek -37
-KPX rcommaaccent g -37
-KPX rcommaaccent gbreve -37
-KPX rcommaaccent gcommaaccent -37
-KPX rcommaaccent hyphen -20
-KPX rcommaaccent o -45
-KPX rcommaaccent oacute -45
-KPX rcommaaccent ocircumflex -45
-KPX rcommaaccent odieresis -45
-KPX rcommaaccent ograve -45
-KPX rcommaaccent ohungarumlaut -45
-KPX rcommaaccent omacron -45
-KPX rcommaaccent oslash -45
-KPX rcommaaccent otilde -45
-KPX rcommaaccent period -111
-KPX rcommaaccent q -37
-KPX rcommaaccent s -10
-KPX rcommaaccent sacute -10
-KPX rcommaaccent scaron -10
-KPX rcommaaccent scedilla -10
-KPX rcommaaccent scommaaccent -10
-KPX space A -18
-KPX space Aacute -18
-KPX space Abreve -18
-KPX space Acircumflex -18
-KPX space Adieresis -18
-KPX space Agrave -18
-KPX space Amacron -18
-KPX space Aogonek -18
-KPX space Aring -18
-KPX space Atilde -18
-KPX space T -18
-KPX space Tcaron -18
-KPX space Tcommaaccent -18
-KPX space V -35
-KPX space W -40
-KPX space Y -75
-KPX space Yacute -75
-KPX space Ydieresis -75
-KPX v comma -74
-KPX v period -74
-KPX w comma -74
-KPX w period -74
-KPX y comma -55
-KPX y period -55
-KPX yacute comma -55
-KPX yacute period -55
-KPX ydieresis comma -55
-KPX ydieresis period -55
-EndKernPairs
-EndKernData
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/Times-Roman.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/Times-Roman.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/Times-Roman.afm 2004-05-26 16:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/Times-Roman.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,2419 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Thu May 1 12:49:17 1997
-Comment UniqueID 43068
-Comment VMusage 43909 54934
-FontName Times-Roman
-FullName Times Roman
-FamilyName Times
-Weight Roman
-ItalicAngle 0
-IsFixedPitch false
-CharacterSet ExtendedRoman
-FontBBox -168 -218 1000 898
-UnderlinePosition -100
-UnderlineThickness 50
-Version 002.000
-Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries.
-EncodingScheme AdobeStandardEncoding
-CapHeight 662
-XHeight 450
-Ascender 683
-Descender -217
-StdHW 28
-StdVW 84
-StartCharMetrics 315
-C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 333 ; N exclam ; B 130 -9 238 676 ;
-C 34 ; WX 408 ; N quotedbl ; B 77 431 331 676 ;
-C 35 ; WX 500 ; N numbersign ; B 5 0 496 662 ;
-C 36 ; WX 500 ; N dollar ; B 44 -87 457 727 ;
-C 37 ; WX 833 ; N percent ; B 61 -13 772 676 ;
-C 38 ; WX 778 ; N ampersand ; B 42 -13 750 676 ;
-C 39 ; WX 333 ; N quoteright ; B 79 433 218 676 ;
-C 40 ; WX 333 ; N parenleft ; B 48 -177 304 676 ;
-C 41 ; WX 333 ; N parenright ; B 29 -177 285 676 ;
-C 42 ; WX 500 ; N asterisk ; B 69 265 432 676 ;
-C 43 ; WX 564 ; N plus ; B 30 0 534 506 ;
-C 44 ; WX 250 ; N comma ; B 56 -141 195 102 ;
-C 45 ; WX 333 ; N hyphen ; B 39 194 285 257 ;
-C 46 ; WX 250 ; N period ; B 70 -11 181 100 ;
-C 47 ; WX 278 ; N slash ; B -9 -14 287 676 ;
-C 48 ; WX 500 ; N zero ; B 24 -14 476 676 ;
-C 49 ; WX 500 ; N one ; B 111 0 394 676 ;
-C 50 ; WX 500 ; N two ; B 30 0 475 676 ;
-C 51 ; WX 500 ; N three ; B 43 -14 431 676 ;
-C 52 ; WX 500 ; N four ; B 12 0 472 676 ;
-C 53 ; WX 500 ; N five ; B 32 -14 438 688 ;
-C 54 ; WX 500 ; N six ; B 34 -14 468 684 ;
-C 55 ; WX 500 ; N seven ; B 20 -8 449 662 ;
-C 56 ; WX 500 ; N eight ; B 56 -14 445 676 ;
-C 57 ; WX 500 ; N nine ; B 30 -22 459 676 ;
-C 58 ; WX 278 ; N colon ; B 81 -11 192 459 ;
-C 59 ; WX 278 ; N semicolon ; B 80 -141 219 459 ;
-C 60 ; WX 564 ; N less ; B 28 -8 536 514 ;
-C 61 ; WX 564 ; N equal ; B 30 120 534 386 ;
-C 62 ; WX 564 ; N greater ; B 28 -8 536 514 ;
-C 63 ; WX 444 ; N question ; B 68 -8 414 676 ;
-C 64 ; WX 921 ; N at ; B 116 -14 809 676 ;
-C 65 ; WX 722 ; N A ; B 15 0 706 674 ;
-C 66 ; WX 667 ; N B ; B 17 0 593 662 ;
-C 67 ; WX 667 ; N C ; B 28 -14 633 676 ;
-C 68 ; WX 722 ; N D ; B 16 0 685 662 ;
-C 69 ; WX 611 ; N E ; B 12 0 597 662 ;
-C 70 ; WX 556 ; N F ; B 12 0 546 662 ;
-C 71 ; WX 722 ; N G ; B 32 -14 709 676 ;
-C 72 ; WX 722 ; N H ; B 19 0 702 662 ;
-C 73 ; WX 333 ; N I ; B 18 0 315 662 ;
-C 74 ; WX 389 ; N J ; B 10 -14 370 662 ;
-C 75 ; WX 722 ; N K ; B 34 0 723 662 ;
-C 76 ; WX 611 ; N L ; B 12 0 598 662 ;
-C 77 ; WX 889 ; N M ; B 12 0 863 662 ;
-C 78 ; WX 722 ; N N ; B 12 -11 707 662 ;
-C 79 ; WX 722 ; N O ; B 34 -14 688 676 ;
-C 80 ; WX 556 ; N P ; B 16 0 542 662 ;
-C 81 ; WX 722 ; N Q ; B 34 -178 701 676 ;
-C 82 ; WX 667 ; N R ; B 17 0 659 662 ;
-C 83 ; WX 556 ; N S ; B 42 -14 491 676 ;
-C 84 ; WX 611 ; N T ; B 17 0 593 662 ;
-C 85 ; WX 722 ; N U ; B 14 -14 705 662 ;
-C 86 ; WX 722 ; N V ; B 16 -11 697 662 ;
-C 87 ; WX 944 ; N W ; B 5 -11 932 662 ;
-C 88 ; WX 722 ; N X ; B 10 0 704 662 ;
-C 89 ; WX 722 ; N Y ; B 22 0 703 662 ;
-C 90 ; WX 611 ; N Z ; B 9 0 597 662 ;
-C 91 ; WX 333 ; N bracketleft ; B 88 -156 299 662 ;
-C 92 ; WX 278 ; N backslash ; B -9 -14 287 676 ;
-C 93 ; WX 333 ; N bracketright ; B 34 -156 245 662 ;
-C 94 ; WX 469 ; N asciicircum ; B 24 297 446 662 ;
-C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
-C 96 ; WX 333 ; N quoteleft ; B 115 433 254 676 ;
-C 97 ; WX 444 ; N a ; B 37 -10 442 460 ;
-C 98 ; WX 500 ; N b ; B 3 -10 468 683 ;
-C 99 ; WX 444 ; N c ; B 25 -10 412 460 ;
-C 100 ; WX 500 ; N d ; B 27 -10 491 683 ;
-C 101 ; WX 444 ; N e ; B 25 -10 424 460 ;
-C 102 ; WX 333 ; N f ; B 20 0 383 683 ; L i fi ; L l fl ;
-C 103 ; WX 500 ; N g ; B 28 -218 470 460 ;
-C 104 ; WX 500 ; N h ; B 9 0 487 683 ;
-C 105 ; WX 278 ; N i ; B 16 0 253 683 ;
-C 106 ; WX 278 ; N j ; B -70 -218 194 683 ;
-C 107 ; WX 500 ; N k ; B 7 0 505 683 ;
-C 108 ; WX 278 ; N l ; B 19 0 257 683 ;
-C 109 ; WX 778 ; N m ; B 16 0 775 460 ;
-C 110 ; WX 500 ; N n ; B 16 0 485 460 ;
-C 111 ; WX 500 ; N o ; B 29 -10 470 460 ;
-C 112 ; WX 500 ; N p ; B 5 -217 470 460 ;
-C 113 ; WX 500 ; N q ; B 24 -217 488 460 ;
-C 114 ; WX 333 ; N r ; B 5 0 335 460 ;
-C 115 ; WX 389 ; N s ; B 51 -10 348 460 ;
-C 116 ; WX 278 ; N t ; B 13 -10 279 579 ;
-C 117 ; WX 500 ; N u ; B 9 -10 479 450 ;
-C 118 ; WX 500 ; N v ; B 19 -14 477 450 ;
-C 119 ; WX 722 ; N w ; B 21 -14 694 450 ;
-C 120 ; WX 500 ; N x ; B 17 0 479 450 ;
-C 121 ; WX 500 ; N y ; B 14 -218 475 450 ;
-C 122 ; WX 444 ; N z ; B 27 0 418 450 ;
-C 123 ; WX 480 ; N braceleft ; B 100 -181 350 680 ;
-C 124 ; WX 200 ; N bar ; B 67 -218 133 782 ;
-C 125 ; WX 480 ; N braceright ; B 130 -181 380 680 ;
-C 126 ; WX 541 ; N asciitilde ; B 40 183 502 323 ;
-C 161 ; WX 333 ; N exclamdown ; B 97 -218 205 467 ;
-C 162 ; WX 500 ; N cent ; B 53 -138 448 579 ;
-C 163 ; WX 500 ; N sterling ; B 12 -8 490 676 ;
-C 164 ; WX 167 ; N fraction ; B -168 -14 331 676 ;
-C 165 ; WX 500 ; N yen ; B -53 0 512 662 ;
-C 166 ; WX 500 ; N florin ; B 7 -189 490 676 ;
-C 167 ; WX 500 ; N section ; B 70 -148 426 676 ;
-C 168 ; WX 500 ; N currency ; B -22 58 522 602 ;
-C 169 ; WX 180 ; N quotesingle ; B 48 431 133 676 ;
-C 170 ; WX 444 ; N quotedblleft ; B 43 433 414 676 ;
-C 171 ; WX 500 ; N guillemotleft ; B 42 33 456 416 ;
-C 172 ; WX 333 ; N guilsinglleft ; B 63 33 285 416 ;
-C 173 ; WX 333 ; N guilsinglright ; B 48 33 270 416 ;
-C 174 ; WX 556 ; N fi ; B 31 0 521 683 ;
-C 175 ; WX 556 ; N fl ; B 32 0 521 683 ;
-C 177 ; WX 500 ; N endash ; B 0 201 500 250 ;
-C 178 ; WX 500 ; N dagger ; B 59 -149 442 676 ;
-C 179 ; WX 500 ; N daggerdbl ; B 58 -153 442 676 ;
-C 180 ; WX 250 ; N periodcentered ; B 70 199 181 310 ;
-C 182 ; WX 453 ; N paragraph ; B -22 -154 450 662 ;
-C 183 ; WX 350 ; N bullet ; B 40 196 310 466 ;
-C 184 ; WX 333 ; N quotesinglbase ; B 79 -141 218 102 ;
-C 185 ; WX 444 ; N quotedblbase ; B 45 -141 416 102 ;
-C 186 ; WX 444 ; N quotedblright ; B 30 433 401 676 ;
-C 187 ; WX 500 ; N guillemotright ; B 44 33 458 416 ;
-C 188 ; WX 1000 ; N ellipsis ; B 111 -11 888 100 ;
-C 189 ; WX 1000 ; N perthousand ; B 7 -19 994 706 ;
-C 191 ; WX 444 ; N questiondown ; B 30 -218 376 466 ;
-C 193 ; WX 333 ; N grave ; B 19 507 242 678 ;
-C 194 ; WX 333 ; N acute ; B 93 507 317 678 ;
-C 195 ; WX 333 ; N circumflex ; B 11 507 322 674 ;
-C 196 ; WX 333 ; N tilde ; B 1 532 331 638 ;
-C 197 ; WX 333 ; N macron ; B 11 547 322 601 ;
-C 198 ; WX 333 ; N breve ; B 26 507 307 664 ;
-C 199 ; WX 333 ; N dotaccent ; B 118 581 216 681 ;
-C 200 ; WX 333 ; N dieresis ; B 18 581 315 681 ;
-C 202 ; WX 333 ; N ring ; B 67 512 266 711 ;
-C 203 ; WX 333 ; N cedilla ; B 52 -215 261 0 ;
-C 205 ; WX 333 ; N hungarumlaut ; B -3 507 377 678 ;
-C 206 ; WX 333 ; N ogonek ; B 62 -165 243 0 ;
-C 207 ; WX 333 ; N caron ; B 11 507 322 674 ;
-C 208 ; WX 1000 ; N emdash ; B 0 201 1000 250 ;
-C 225 ; WX 889 ; N AE ; B 0 0 863 662 ;
-C 227 ; WX 276 ; N ordfeminine ; B 4 394 270 676 ;
-C 232 ; WX 611 ; N Lslash ; B 12 0 598 662 ;
-C 233 ; WX 722 ; N Oslash ; B 34 -80 688 734 ;
-C 234 ; WX 889 ; N OE ; B 30 -6 885 668 ;
-C 235 ; WX 310 ; N ordmasculine ; B 6 394 304 676 ;
-C 241 ; WX 667 ; N ae ; B 38 -10 632 460 ;
-C 245 ; WX 278 ; N dotlessi ; B 16 0 253 460 ;
-C 248 ; WX 278 ; N lslash ; B 19 0 259 683 ;
-C 249 ; WX 500 ; N oslash ; B 29 -112 470 551 ;
-C 250 ; WX 722 ; N oe ; B 30 -10 690 460 ;
-C 251 ; WX 500 ; N germandbls ; B 12 -9 468 683 ;
-C -1 ; WX 333 ; N Idieresis ; B 18 0 315 835 ;
-C -1 ; WX 444 ; N eacute ; B 25 -10 424 678 ;
-C -1 ; WX 444 ; N abreve ; B 37 -10 442 664 ;
-C -1 ; WX 500 ; N uhungarumlaut ; B 9 -10 501 678 ;
-C -1 ; WX 444 ; N ecaron ; B 25 -10 424 674 ;
-C -1 ; WX 722 ; N Ydieresis ; B 22 0 703 835 ;
-C -1 ; WX 564 ; N divide ; B 30 -10 534 516 ;
-C -1 ; WX 722 ; N Yacute ; B 22 0 703 890 ;
-C -1 ; WX 722 ; N Acircumflex ; B 15 0 706 886 ;
-C -1 ; WX 444 ; N aacute ; B 37 -10 442 678 ;
-C -1 ; WX 722 ; N Ucircumflex ; B 14 -14 705 886 ;
-C -1 ; WX 500 ; N yacute ; B 14 -218 475 678 ;
-C -1 ; WX 389 ; N scommaaccent ; B 51 -218 348 460 ;
-C -1 ; WX 444 ; N ecircumflex ; B 25 -10 424 674 ;
-C -1 ; WX 722 ; N Uring ; B 14 -14 705 898 ;
-C -1 ; WX 722 ; N Udieresis ; B 14 -14 705 835 ;
-C -1 ; WX 444 ; N aogonek ; B 37 -165 469 460 ;
-C -1 ; WX 722 ; N Uacute ; B 14 -14 705 890 ;
-C -1 ; WX 500 ; N uogonek ; B 9 -155 487 450 ;
-C -1 ; WX 611 ; N Edieresis ; B 12 0 597 835 ;
-C -1 ; WX 722 ; N Dcroat ; B 16 0 685 662 ;
-C -1 ; WX 250 ; N commaaccent ; B 59 -218 184 -50 ;
-C -1 ; WX 760 ; N copyright ; B 38 -14 722 676 ;
-C -1 ; WX 611 ; N Emacron ; B 12 0 597 813 ;
-C -1 ; WX 444 ; N ccaron ; B 25 -10 412 674 ;
-C -1 ; WX 444 ; N aring ; B 37 -10 442 711 ;
-C -1 ; WX 722 ; N Ncommaaccent ; B 12 -198 707 662 ;
-C -1 ; WX 278 ; N lacute ; B 19 0 290 890 ;
-C -1 ; WX 444 ; N agrave ; B 37 -10 442 678 ;
-C -1 ; WX 611 ; N Tcommaaccent ; B 17 -218 593 662 ;
-C -1 ; WX 667 ; N Cacute ; B 28 -14 633 890 ;
-C -1 ; WX 444 ; N atilde ; B 37 -10 442 638 ;
-C -1 ; WX 611 ; N Edotaccent ; B 12 0 597 835 ;
-C -1 ; WX 389 ; N scaron ; B 39 -10 350 674 ;
-C -1 ; WX 389 ; N scedilla ; B 51 -215 348 460 ;
-C -1 ; WX 278 ; N iacute ; B 16 0 290 678 ;
-C -1 ; WX 471 ; N lozenge ; B 13 0 459 724 ;
-C -1 ; WX 667 ; N Rcaron ; B 17 0 659 886 ;
-C -1 ; WX 722 ; N Gcommaaccent ; B 32 -218 709 676 ;
-C -1 ; WX 500 ; N ucircumflex ; B 9 -10 479 674 ;
-C -1 ; WX 444 ; N acircumflex ; B 37 -10 442 674 ;
-C -1 ; WX 722 ; N Amacron ; B 15 0 706 813 ;
-C -1 ; WX 333 ; N rcaron ; B 5 0 335 674 ;
-C -1 ; WX 444 ; N ccedilla ; B 25 -215 412 460 ;
-C -1 ; WX 611 ; N Zdotaccent ; B 9 0 597 835 ;
-C -1 ; WX 556 ; N Thorn ; B 16 0 542 662 ;
-C -1 ; WX 722 ; N Omacron ; B 34 -14 688 813 ;
-C -1 ; WX 667 ; N Racute ; B 17 0 659 890 ;
-C -1 ; WX 556 ; N Sacute ; B 42 -14 491 890 ;
-C -1 ; WX 588 ; N dcaron ; B 27 -10 589 695 ;
-C -1 ; WX 722 ; N Umacron ; B 14 -14 705 813 ;
-C -1 ; WX 500 ; N uring ; B 9 -10 479 711 ;
-C -1 ; WX 300 ; N threesuperior ; B 15 262 291 676 ;
-C -1 ; WX 722 ; N Ograve ; B 34 -14 688 890 ;
-C -1 ; WX 722 ; N Agrave ; B 15 0 706 890 ;
-C -1 ; WX 722 ; N Abreve ; B 15 0 706 876 ;
-C -1 ; WX 564 ; N multiply ; B 38 8 527 497 ;
-C -1 ; WX 500 ; N uacute ; B 9 -10 479 678 ;
-C -1 ; WX 611 ; N Tcaron ; B 17 0 593 886 ;
-C -1 ; WX 476 ; N partialdiff ; B 17 -38 459 710 ;
-C -1 ; WX 500 ; N ydieresis ; B 14 -218 475 623 ;
-C -1 ; WX 722 ; N Nacute ; B 12 -11 707 890 ;
-C -1 ; WX 278 ; N icircumflex ; B -16 0 295 674 ;
-C -1 ; WX 611 ; N Ecircumflex ; B 12 0 597 886 ;
-C -1 ; WX 444 ; N adieresis ; B 37 -10 442 623 ;
-C -1 ; WX 444 ; N edieresis ; B 25 -10 424 623 ;
-C -1 ; WX 444 ; N cacute ; B 25 -10 413 678 ;
-C -1 ; WX 500 ; N nacute ; B 16 0 485 678 ;
-C -1 ; WX 500 ; N umacron ; B 9 -10 479 601 ;
-C -1 ; WX 722 ; N Ncaron ; B 12 -11 707 886 ;
-C -1 ; WX 333 ; N Iacute ; B 18 0 317 890 ;
-C -1 ; WX 564 ; N plusminus ; B 30 0 534 506 ;
-C -1 ; WX 200 ; N brokenbar ; B 67 -143 133 707 ;
-C -1 ; WX 760 ; N registered ; B 38 -14 722 676 ;
-C -1 ; WX 722 ; N Gbreve ; B 32 -14 709 876 ;
-C -1 ; WX 333 ; N Idotaccent ; B 18 0 315 835 ;
-C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ;
-C -1 ; WX 611 ; N Egrave ; B 12 0 597 890 ;
-C -1 ; WX 333 ; N racute ; B 5 0 335 678 ;
-C -1 ; WX 500 ; N omacron ; B 29 -10 470 601 ;
-C -1 ; WX 611 ; N Zacute ; B 9 0 597 890 ;
-C -1 ; WX 611 ; N Zcaron ; B 9 0 597 886 ;
-C -1 ; WX 549 ; N greaterequal ; B 26 0 523 666 ;
-C -1 ; WX 722 ; N Eth ; B 16 0 685 662 ;
-C -1 ; WX 667 ; N Ccedilla ; B 28 -215 633 676 ;
-C -1 ; WX 278 ; N lcommaaccent ; B 19 -218 257 683 ;
-C -1 ; WX 326 ; N tcaron ; B 13 -10 318 722 ;
-C -1 ; WX 444 ; N eogonek ; B 25 -165 424 460 ;
-C -1 ; WX 722 ; N Uogonek ; B 14 -165 705 662 ;
-C -1 ; WX 722 ; N Aacute ; B 15 0 706 890 ;
-C -1 ; WX 722 ; N Adieresis ; B 15 0 706 835 ;
-C -1 ; WX 444 ; N egrave ; B 25 -10 424 678 ;
-C -1 ; WX 444 ; N zacute ; B 27 0 418 678 ;
-C -1 ; WX 278 ; N iogonek ; B 16 -165 265 683 ;
-C -1 ; WX 722 ; N Oacute ; B 34 -14 688 890 ;
-C -1 ; WX 500 ; N oacute ; B 29 -10 470 678 ;
-C -1 ; WX 444 ; N amacron ; B 37 -10 442 601 ;
-C -1 ; WX 389 ; N sacute ; B 51 -10 348 678 ;
-C -1 ; WX 278 ; N idieresis ; B -9 0 288 623 ;
-C -1 ; WX 722 ; N Ocircumflex ; B 34 -14 688 886 ;
-C -1 ; WX 722 ; N Ugrave ; B 14 -14 705 890 ;
-C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
-C -1 ; WX 500 ; N thorn ; B 5 -217 470 683 ;
-C -1 ; WX 300 ; N twosuperior ; B 1 270 296 676 ;
-C -1 ; WX 722 ; N Odieresis ; B 34 -14 688 835 ;
-C -1 ; WX 500 ; N mu ; B 36 -218 512 450 ;
-C -1 ; WX 278 ; N igrave ; B -8 0 253 678 ;
-C -1 ; WX 500 ; N ohungarumlaut ; B 29 -10 491 678 ;
-C -1 ; WX 611 ; N Eogonek ; B 12 -165 597 662 ;
-C -1 ; WX 500 ; N dcroat ; B 27 -10 500 683 ;
-C -1 ; WX 750 ; N threequarters ; B 15 -14 718 676 ;
-C -1 ; WX 556 ; N Scedilla ; B 42 -215 491 676 ;
-C -1 ; WX 344 ; N lcaron ; B 19 0 347 695 ;
-C -1 ; WX 722 ; N Kcommaaccent ; B 34 -198 723 662 ;
-C -1 ; WX 611 ; N Lacute ; B 12 0 598 890 ;
-C -1 ; WX 980 ; N trademark ; B 30 256 957 662 ;
-C -1 ; WX 444 ; N edotaccent ; B 25 -10 424 623 ;
-C -1 ; WX 333 ; N Igrave ; B 18 0 315 890 ;
-C -1 ; WX 333 ; N Imacron ; B 11 0 322 813 ;
-C -1 ; WX 611 ; N Lcaron ; B 12 0 598 676 ;
-C -1 ; WX 750 ; N onehalf ; B 31 -14 746 676 ;
-C -1 ; WX 549 ; N lessequal ; B 26 0 523 666 ;
-C -1 ; WX 500 ; N ocircumflex ; B 29 -10 470 674 ;
-C -1 ; WX 500 ; N ntilde ; B 16 0 485 638 ;
-C -1 ; WX 722 ; N Uhungarumlaut ; B 14 -14 705 890 ;
-C -1 ; WX 611 ; N Eacute ; B 12 0 597 890 ;
-C -1 ; WX 444 ; N emacron ; B 25 -10 424 601 ;
-C -1 ; WX 500 ; N gbreve ; B 28 -218 470 664 ;
-C -1 ; WX 750 ; N onequarter ; B 37 -14 718 676 ;
-C -1 ; WX 556 ; N Scaron ; B 42 -14 491 886 ;
-C -1 ; WX 556 ; N Scommaaccent ; B 42 -218 491 676 ;
-C -1 ; WX 722 ; N Ohungarumlaut ; B 34 -14 688 890 ;
-C -1 ; WX 400 ; N degree ; B 57 390 343 676 ;
-C -1 ; WX 500 ; N ograve ; B 29 -10 470 678 ;
-C -1 ; WX 667 ; N Ccaron ; B 28 -14 633 886 ;
-C -1 ; WX 500 ; N ugrave ; B 9 -10 479 678 ;
-C -1 ; WX 453 ; N radical ; B 2 -60 452 768 ;
-C -1 ; WX 722 ; N Dcaron ; B 16 0 685 886 ;
-C -1 ; WX 333 ; N rcommaaccent ; B 5 -218 335 460 ;
-C -1 ; WX 722 ; N Ntilde ; B 12 -11 707 850 ;
-C -1 ; WX 500 ; N otilde ; B 29 -10 470 638 ;
-C -1 ; WX 667 ; N Rcommaaccent ; B 17 -198 659 662 ;
-C -1 ; WX 611 ; N Lcommaaccent ; B 12 -218 598 662 ;
-C -1 ; WX 722 ; N Atilde ; B 15 0 706 850 ;
-C -1 ; WX 722 ; N Aogonek ; B 15 -165 738 674 ;
-C -1 ; WX 722 ; N Aring ; B 15 0 706 898 ;
-C -1 ; WX 722 ; N Otilde ; B 34 -14 688 850 ;
-C -1 ; WX 444 ; N zdotaccent ; B 27 0 418 623 ;
-C -1 ; WX 611 ; N Ecaron ; B 12 0 597 886 ;
-C -1 ; WX 333 ; N Iogonek ; B 18 -165 315 662 ;
-C -1 ; WX 500 ; N kcommaaccent ; B 7 -218 505 683 ;
-C -1 ; WX 564 ; N minus ; B 30 220 534 286 ;
-C -1 ; WX 333 ; N Icircumflex ; B 11 0 322 886 ;
-C -1 ; WX 500 ; N ncaron ; B 16 0 485 674 ;
-C -1 ; WX 278 ; N tcommaaccent ; B 13 -218 279 579 ;
-C -1 ; WX 564 ; N logicalnot ; B 30 108 534 386 ;
-C -1 ; WX 500 ; N odieresis ; B 29 -10 470 623 ;
-C -1 ; WX 500 ; N udieresis ; B 9 -10 479 623 ;
-C -1 ; WX 549 ; N notequal ; B 12 -31 537 547 ;
-C -1 ; WX 500 ; N gcommaaccent ; B 28 -218 470 749 ;
-C -1 ; WX 500 ; N eth ; B 29 -10 471 686 ;
-C -1 ; WX 444 ; N zcaron ; B 27 0 418 674 ;
-C -1 ; WX 500 ; N ncommaaccent ; B 16 -218 485 460 ;
-C -1 ; WX 300 ; N onesuperior ; B 57 270 248 676 ;
-C -1 ; WX 278 ; N imacron ; B 6 0 271 601 ;
-C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ;
-EndCharMetrics
-StartKernData
-StartKernPairs 2073
-KPX A C -40
-KPX A Cacute -40
-KPX A Ccaron -40
-KPX A Ccedilla -40
-KPX A G -40
-KPX A Gbreve -40
-KPX A Gcommaaccent -40
-KPX A O -55
-KPX A Oacute -55
-KPX A Ocircumflex -55
-KPX A Odieresis -55
-KPX A Ograve -55
-KPX A Ohungarumlaut -55
-KPX A Omacron -55
-KPX A Oslash -55
-KPX A Otilde -55
-KPX A Q -55
-KPX A T -111
-KPX A Tcaron -111
-KPX A Tcommaaccent -111
-KPX A U -55
-KPX A Uacute -55
-KPX A Ucircumflex -55
-KPX A Udieresis -55
-KPX A Ugrave -55
-KPX A Uhungarumlaut -55
-KPX A Umacron -55
-KPX A Uogonek -55
-KPX A Uring -55
-KPX A V -135
-KPX A W -90
-KPX A Y -105
-KPX A Yacute -105
-KPX A Ydieresis -105
-KPX A quoteright -111
-KPX A v -74
-KPX A w -92
-KPX A y -92
-KPX A yacute -92
-KPX A ydieresis -92
-KPX Aacute C -40
-KPX Aacute Cacute -40
-KPX Aacute Ccaron -40
-KPX Aacute Ccedilla -40
-KPX Aacute G -40
-KPX Aacute Gbreve -40
-KPX Aacute Gcommaaccent -40
-KPX Aacute O -55
-KPX Aacute Oacute -55
-KPX Aacute Ocircumflex -55
-KPX Aacute Odieresis -55
-KPX Aacute Ograve -55
-KPX Aacute Ohungarumlaut -55
-KPX Aacute Omacron -55
-KPX Aacute Oslash -55
-KPX Aacute Otilde -55
-KPX Aacute Q -55
-KPX Aacute T -111
-KPX Aacute Tcaron -111
-KPX Aacute Tcommaaccent -111
-KPX Aacute U -55
-KPX Aacute Uacute -55
-KPX Aacute Ucircumflex -55
-KPX Aacute Udieresis -55
-KPX Aacute Ugrave -55
-KPX Aacute Uhungarumlaut -55
-KPX Aacute Umacron -55
-KPX Aacute Uogonek -55
-KPX Aacute Uring -55
-KPX Aacute V -135
-KPX Aacute W -90
-KPX Aacute Y -105
-KPX Aacute Yacute -105
-KPX Aacute Ydieresis -105
-KPX Aacute quoteright -111
-KPX Aacute v -74
-KPX Aacute w -92
-KPX Aacute y -92
-KPX Aacute yacute -92
-KPX Aacute ydieresis -92
-KPX Abreve C -40
-KPX Abreve Cacute -40
-KPX Abreve Ccaron -40
-KPX Abreve Ccedilla -40
-KPX Abreve G -40
-KPX Abreve Gbreve -40
-KPX Abreve Gcommaaccent -40
-KPX Abreve O -55
-KPX Abreve Oacute -55
-KPX Abreve Ocircumflex -55
-KPX Abreve Odieresis -55
-KPX Abreve Ograve -55
-KPX Abreve Ohungarumlaut -55
-KPX Abreve Omacron -55
-KPX Abreve Oslash -55
-KPX Abreve Otilde -55
-KPX Abreve Q -55
-KPX Abreve T -111
-KPX Abreve Tcaron -111
-KPX Abreve Tcommaaccent -111
-KPX Abreve U -55
-KPX Abreve Uacute -55
-KPX Abreve Ucircumflex -55
-KPX Abreve Udieresis -55
-KPX Abreve Ugrave -55
-KPX Abreve Uhungarumlaut -55
-KPX Abreve Umacron -55
-KPX Abreve Uogonek -55
-KPX Abreve Uring -55
-KPX Abreve V -135
-KPX Abreve W -90
-KPX Abreve Y -105
-KPX Abreve Yacute -105
-KPX Abreve Ydieresis -105
-KPX Abreve quoteright -111
-KPX Abreve v -74
-KPX Abreve w -92
-KPX Abreve y -92
-KPX Abreve yacute -92
-KPX Abreve ydieresis -92
-KPX Acircumflex C -40
-KPX Acircumflex Cacute -40
-KPX Acircumflex Ccaron -40
-KPX Acircumflex Ccedilla -40
-KPX Acircumflex G -40
-KPX Acircumflex Gbreve -40
-KPX Acircumflex Gcommaaccent -40
-KPX Acircumflex O -55
-KPX Acircumflex Oacute -55
-KPX Acircumflex Ocircumflex -55
-KPX Acircumflex Odieresis -55
-KPX Acircumflex Ograve -55
-KPX Acircumflex Ohungarumlaut -55
-KPX Acircumflex Omacron -55
-KPX Acircumflex Oslash -55
-KPX Acircumflex Otilde -55
-KPX Acircumflex Q -55
-KPX Acircumflex T -111
-KPX Acircumflex Tcaron -111
-KPX Acircumflex Tcommaaccent -111
-KPX Acircumflex U -55
-KPX Acircumflex Uacute -55
-KPX Acircumflex Ucircumflex -55
-KPX Acircumflex Udieresis -55
-KPX Acircumflex Ugrave -55
-KPX Acircumflex Uhungarumlaut -55
-KPX Acircumflex Umacron -55
-KPX Acircumflex Uogonek -55
-KPX Acircumflex Uring -55
-KPX Acircumflex V -135
-KPX Acircumflex W -90
-KPX Acircumflex Y -105
-KPX Acircumflex Yacute -105
-KPX Acircumflex Ydieresis -105
-KPX Acircumflex quoteright -111
-KPX Acircumflex v -74
-KPX Acircumflex w -92
-KPX Acircumflex y -92
-KPX Acircumflex yacute -92
-KPX Acircumflex ydieresis -92
-KPX Adieresis C -40
-KPX Adieresis Cacute -40
-KPX Adieresis Ccaron -40
-KPX Adieresis Ccedilla -40
-KPX Adieresis G -40
-KPX Adieresis Gbreve -40
-KPX Adieresis Gcommaaccent -40
-KPX Adieresis O -55
-KPX Adieresis Oacute -55
-KPX Adieresis Ocircumflex -55
-KPX Adieresis Odieresis -55
-KPX Adieresis Ograve -55
-KPX Adieresis Ohungarumlaut -55
-KPX Adieresis Omacron -55
-KPX Adieresis Oslash -55
-KPX Adieresis Otilde -55
-KPX Adieresis Q -55
-KPX Adieresis T -111
-KPX Adieresis Tcaron -111
-KPX Adieresis Tcommaaccent -111
-KPX Adieresis U -55
-KPX Adieresis Uacute -55
-KPX Adieresis Ucircumflex -55
-KPX Adieresis Udieresis -55
-KPX Adieresis Ugrave -55
-KPX Adieresis Uhungarumlaut -55
-KPX Adieresis Umacron -55
-KPX Adieresis Uogonek -55
-KPX Adieresis Uring -55
-KPX Adieresis V -135
-KPX Adieresis W -90
-KPX Adieresis Y -105
-KPX Adieresis Yacute -105
-KPX Adieresis Ydieresis -105
-KPX Adieresis quoteright -111
-KPX Adieresis v -74
-KPX Adieresis w -92
-KPX Adieresis y -92
-KPX Adieresis yacute -92
-KPX Adieresis ydieresis -92
-KPX Agrave C -40
-KPX Agrave Cacute -40
-KPX Agrave Ccaron -40
-KPX Agrave Ccedilla -40
-KPX Agrave G -40
-KPX Agrave Gbreve -40
-KPX Agrave Gcommaaccent -40
-KPX Agrave O -55
-KPX Agrave Oacute -55
-KPX Agrave Ocircumflex -55
-KPX Agrave Odieresis -55
-KPX Agrave Ograve -55
-KPX Agrave Ohungarumlaut -55
-KPX Agrave Omacron -55
-KPX Agrave Oslash -55
-KPX Agrave Otilde -55
-KPX Agrave Q -55
-KPX Agrave T -111
-KPX Agrave Tcaron -111
-KPX Agrave Tcommaaccent -111
-KPX Agrave U -55
-KPX Agrave Uacute -55
-KPX Agrave Ucircumflex -55
-KPX Agrave Udieresis -55
-KPX Agrave Ugrave -55
-KPX Agrave Uhungarumlaut -55
-KPX Agrave Umacron -55
-KPX Agrave Uogonek -55
-KPX Agrave Uring -55
-KPX Agrave V -135
-KPX Agrave W -90
-KPX Agrave Y -105
-KPX Agrave Yacute -105
-KPX Agrave Ydieresis -105
-KPX Agrave quoteright -111
-KPX Agrave v -74
-KPX Agrave w -92
-KPX Agrave y -92
-KPX Agrave yacute -92
-KPX Agrave ydieresis -92
-KPX Amacron C -40
-KPX Amacron Cacute -40
-KPX Amacron Ccaron -40
-KPX Amacron Ccedilla -40
-KPX Amacron G -40
-KPX Amacron Gbreve -40
-KPX Amacron Gcommaaccent -40
-KPX Amacron O -55
-KPX Amacron Oacute -55
-KPX Amacron Ocircumflex -55
-KPX Amacron Odieresis -55
-KPX Amacron Ograve -55
-KPX Amacron Ohungarumlaut -55
-KPX Amacron Omacron -55
-KPX Amacron Oslash -55
-KPX Amacron Otilde -55
-KPX Amacron Q -55
-KPX Amacron T -111
-KPX Amacron Tcaron -111
-KPX Amacron Tcommaaccent -111
-KPX Amacron U -55
-KPX Amacron Uacute -55
-KPX Amacron Ucircumflex -55
-KPX Amacron Udieresis -55
-KPX Amacron Ugrave -55
-KPX Amacron Uhungarumlaut -55
-KPX Amacron Umacron -55
-KPX Amacron Uogonek -55
-KPX Amacron Uring -55
-KPX Amacron V -135
-KPX Amacron W -90
-KPX Amacron Y -105
-KPX Amacron Yacute -105
-KPX Amacron Ydieresis -105
-KPX Amacron quoteright -111
-KPX Amacron v -74
-KPX Amacron w -92
-KPX Amacron y -92
-KPX Amacron yacute -92
-KPX Amacron ydieresis -92
-KPX Aogonek C -40
-KPX Aogonek Cacute -40
-KPX Aogonek Ccaron -40
-KPX Aogonek Ccedilla -40
-KPX Aogonek G -40
-KPX Aogonek Gbreve -40
-KPX Aogonek Gcommaaccent -40
-KPX Aogonek O -55
-KPX Aogonek Oacute -55
-KPX Aogonek Ocircumflex -55
-KPX Aogonek Odieresis -55
-KPX Aogonek Ograve -55
-KPX Aogonek Ohungarumlaut -55
-KPX Aogonek Omacron -55
-KPX Aogonek Oslash -55
-KPX Aogonek Otilde -55
-KPX Aogonek Q -55
-KPX Aogonek T -111
-KPX Aogonek Tcaron -111
-KPX Aogonek Tcommaaccent -111
-KPX Aogonek U -55
-KPX Aogonek Uacute -55
-KPX Aogonek Ucircumflex -55
-KPX Aogonek Udieresis -55
-KPX Aogonek Ugrave -55
-KPX Aogonek Uhungarumlaut -55
-KPX Aogonek Umacron -55
-KPX Aogonek Uogonek -55
-KPX Aogonek Uring -55
-KPX Aogonek V -135
-KPX Aogonek W -90
-KPX Aogonek Y -105
-KPX Aogonek Yacute -105
-KPX Aogonek Ydieresis -105
-KPX Aogonek quoteright -111
-KPX Aogonek v -74
-KPX Aogonek w -52
-KPX Aogonek y -52
-KPX Aogonek yacute -52
-KPX Aogonek ydieresis -52
-KPX Aring C -40
-KPX Aring Cacute -40
-KPX Aring Ccaron -40
-KPX Aring Ccedilla -40
-KPX Aring G -40
-KPX Aring Gbreve -40
-KPX Aring Gcommaaccent -40
-KPX Aring O -55
-KPX Aring Oacute -55
-KPX Aring Ocircumflex -55
-KPX Aring Odieresis -55
-KPX Aring Ograve -55
-KPX Aring Ohungarumlaut -55
-KPX Aring Omacron -55
-KPX Aring Oslash -55
-KPX Aring Otilde -55
-KPX Aring Q -55
-KPX Aring T -111
-KPX Aring Tcaron -111
-KPX Aring Tcommaaccent -111
-KPX Aring U -55
-KPX Aring Uacute -55
-KPX Aring Ucircumflex -55
-KPX Aring Udieresis -55
-KPX Aring Ugrave -55
-KPX Aring Uhungarumlaut -55
-KPX Aring Umacron -55
-KPX Aring Uogonek -55
-KPX Aring Uring -55
-KPX Aring V -135
-KPX Aring W -90
-KPX Aring Y -105
-KPX Aring Yacute -105
-KPX Aring Ydieresis -105
-KPX Aring quoteright -111
-KPX Aring v -74
-KPX Aring w -92
-KPX Aring y -92
-KPX Aring yacute -92
-KPX Aring ydieresis -92
-KPX Atilde C -40
-KPX Atilde Cacute -40
-KPX Atilde Ccaron -40
-KPX Atilde Ccedilla -40
-KPX Atilde G -40
-KPX Atilde Gbreve -40
-KPX Atilde Gcommaaccent -40
-KPX Atilde O -55
-KPX Atilde Oacute -55
-KPX Atilde Ocircumflex -55
-KPX Atilde Odieresis -55
-KPX Atilde Ograve -55
-KPX Atilde Ohungarumlaut -55
-KPX Atilde Omacron -55
-KPX Atilde Oslash -55
-KPX Atilde Otilde -55
-KPX Atilde Q -55
-KPX Atilde T -111
-KPX Atilde Tcaron -111
-KPX Atilde Tcommaaccent -111
-KPX Atilde U -55
-KPX Atilde Uacute -55
-KPX Atilde Ucircumflex -55
-KPX Atilde Udieresis -55
-KPX Atilde Ugrave -55
-KPX Atilde Uhungarumlaut -55
-KPX Atilde Umacron -55
-KPX Atilde Uogonek -55
-KPX Atilde Uring -55
-KPX Atilde V -135
-KPX Atilde W -90
-KPX Atilde Y -105
-KPX Atilde Yacute -105
-KPX Atilde Ydieresis -105
-KPX Atilde quoteright -111
-KPX Atilde v -74
-KPX Atilde w -92
-KPX Atilde y -92
-KPX Atilde yacute -92
-KPX Atilde ydieresis -92
-KPX B A -35
-KPX B Aacute -35
-KPX B Abreve -35
-KPX B Acircumflex -35
-KPX B Adieresis -35
-KPX B Agrave -35
-KPX B Amacron -35
-KPX B Aogonek -35
-KPX B Aring -35
-KPX B Atilde -35
-KPX B U -10
-KPX B Uacute -10
-KPX B Ucircumflex -10
-KPX B Udieresis -10
-KPX B Ugrave -10
-KPX B Uhungarumlaut -10
-KPX B Umacron -10
-KPX B Uogonek -10
-KPX B Uring -10
-KPX D A -40
-KPX D Aacute -40
-KPX D Abreve -40
-KPX D Acircumflex -40
-KPX D Adieresis -40
-KPX D Agrave -40
-KPX D Amacron -40
-KPX D Aogonek -40
-KPX D Aring -40
-KPX D Atilde -40
-KPX D V -40
-KPX D W -30
-KPX D Y -55
-KPX D Yacute -55
-KPX D Ydieresis -55
-KPX Dcaron A -40
-KPX Dcaron Aacute -40
-KPX Dcaron Abreve -40
-KPX Dcaron Acircumflex -40
-KPX Dcaron Adieresis -40
-KPX Dcaron Agrave -40
-KPX Dcaron Amacron -40
-KPX Dcaron Aogonek -40
-KPX Dcaron Aring -40
-KPX Dcaron Atilde -40
-KPX Dcaron V -40
-KPX Dcaron W -30
-KPX Dcaron Y -55
-KPX Dcaron Yacute -55
-KPX Dcaron Ydieresis -55
-KPX Dcroat A -40
-KPX Dcroat Aacute -40
-KPX Dcroat Abreve -40
-KPX Dcroat Acircumflex -40
-KPX Dcroat Adieresis -40
-KPX Dcroat Agrave -40
-KPX Dcroat Amacron -40
-KPX Dcroat Aogonek -40
-KPX Dcroat Aring -40
-KPX Dcroat Atilde -40
-KPX Dcroat V -40
-KPX Dcroat W -30
-KPX Dcroat Y -55
-KPX Dcroat Yacute -55
-KPX Dcroat Ydieresis -55
-KPX F A -74
-KPX F Aacute -74
-KPX F Abreve -74
-KPX F Acircumflex -74
-KPX F Adieresis -74
-KPX F Agrave -74
-KPX F Amacron -74
-KPX F Aogonek -74
-KPX F Aring -74
-KPX F Atilde -74
-KPX F a -15
-KPX F aacute -15
-KPX F abreve -15
-KPX F acircumflex -15
-KPX F adieresis -15
-KPX F agrave -15
-KPX F amacron -15
-KPX F aogonek -15
-KPX F aring -15
-KPX F atilde -15
-KPX F comma -80
-KPX F o -15
-KPX F oacute -15
-KPX F ocircumflex -15
-KPX F odieresis -15
-KPX F ograve -15
-KPX F ohungarumlaut -15
-KPX F omacron -15
-KPX F oslash -15
-KPX F otilde -15
-KPX F period -80
-KPX J A -60
-KPX J Aacute -60
-KPX J Abreve -60
-KPX J Acircumflex -60
-KPX J Adieresis -60
-KPX J Agrave -60
-KPX J Amacron -60
-KPX J Aogonek -60
-KPX J Aring -60
-KPX J Atilde -60
-KPX K O -30
-KPX K Oacute -30
-KPX K Ocircumflex -30
-KPX K Odieresis -30
-KPX K Ograve -30
-KPX K Ohungarumlaut -30
-KPX K Omacron -30
-KPX K Oslash -30
-KPX K Otilde -30
-KPX K e -25
-KPX K eacute -25
-KPX K ecaron -25
-KPX K ecircumflex -25
-KPX K edieresis -25
-KPX K edotaccent -25
-KPX K egrave -25
-KPX K emacron -25
-KPX K eogonek -25
-KPX K o -35
-KPX K oacute -35
-KPX K ocircumflex -35
-KPX K odieresis -35
-KPX K ograve -35
-KPX K ohungarumlaut -35
-KPX K omacron -35
-KPX K oslash -35
-KPX K otilde -35
-KPX K u -15
-KPX K uacute -15
-KPX K ucircumflex -15
-KPX K udieresis -15
-KPX K ugrave -15
-KPX K uhungarumlaut -15
-KPX K umacron -15
-KPX K uogonek -15
-KPX K uring -15
-KPX K y -25
-KPX K yacute -25
-KPX K ydieresis -25
-KPX Kcommaaccent O -30
-KPX Kcommaaccent Oacute -30
-KPX Kcommaaccent Ocircumflex -30
-KPX Kcommaaccent Odieresis -30
-KPX Kcommaaccent Ograve -30
-KPX Kcommaaccent Ohungarumlaut -30
-KPX Kcommaaccent Omacron -30
-KPX Kcommaaccent Oslash -30
-KPX Kcommaaccent Otilde -30
-KPX Kcommaaccent e -25
-KPX Kcommaaccent eacute -25
-KPX Kcommaaccent ecaron -25
-KPX Kcommaaccent ecircumflex -25
-KPX Kcommaaccent edieresis -25
-KPX Kcommaaccent edotaccent -25
-KPX Kcommaaccent egrave -25
-KPX Kcommaaccent emacron -25
-KPX Kcommaaccent eogonek -25
-KPX Kcommaaccent o -35
-KPX Kcommaaccent oacute -35
-KPX Kcommaaccent ocircumflex -35
-KPX Kcommaaccent odieresis -35
-KPX Kcommaaccent ograve -35
-KPX Kcommaaccent ohungarumlaut -35
-KPX Kcommaaccent omacron -35
-KPX Kcommaaccent oslash -35
-KPX Kcommaaccent otilde -35
-KPX Kcommaaccent u -15
-KPX Kcommaaccent uacute -15
-KPX Kcommaaccent ucircumflex -15
-KPX Kcommaaccent udieresis -15
-KPX Kcommaaccent ugrave -15
-KPX Kcommaaccent uhungarumlaut -15
-KPX Kcommaaccent umacron -15
-KPX Kcommaaccent uogonek -15
-KPX Kcommaaccent uring -15
-KPX Kcommaaccent y -25
-KPX Kcommaaccent yacute -25
-KPX Kcommaaccent ydieresis -25
-KPX L T -92
-KPX L Tcaron -92
-KPX L Tcommaaccent -92
-KPX L V -100
-KPX L W -74
-KPX L Y -100
-KPX L Yacute -100
-KPX L Ydieresis -100
-KPX L quoteright -92
-KPX L y -55
-KPX L yacute -55
-KPX L ydieresis -55
-KPX Lacute T -92
-KPX Lacute Tcaron -92
-KPX Lacute Tcommaaccent -92
-KPX Lacute V -100
-KPX Lacute W -74
-KPX Lacute Y -100
-KPX Lacute Yacute -100
-KPX Lacute Ydieresis -100
-KPX Lacute quoteright -92
-KPX Lacute y -55
-KPX Lacute yacute -55
-KPX Lacute ydieresis -55
-KPX Lcaron quoteright -92
-KPX Lcaron y -55
-KPX Lcaron yacute -55
-KPX Lcaron ydieresis -55
-KPX Lcommaaccent T -92
-KPX Lcommaaccent Tcaron -92
-KPX Lcommaaccent Tcommaaccent -92
-KPX Lcommaaccent V -100
-KPX Lcommaaccent W -74
-KPX Lcommaaccent Y -100
-KPX Lcommaaccent Yacute -100
-KPX Lcommaaccent Ydieresis -100
-KPX Lcommaaccent quoteright -92
-KPX Lcommaaccent y -55
-KPX Lcommaaccent yacute -55
-KPX Lcommaaccent ydieresis -55
-KPX Lslash T -92
-KPX Lslash Tcaron -92
-KPX Lslash Tcommaaccent -92
-KPX Lslash V -100
-KPX Lslash W -74
-KPX Lslash Y -100
-KPX Lslash Yacute -100
-KPX Lslash Ydieresis -100
-KPX Lslash quoteright -92
-KPX Lslash y -55
-KPX Lslash yacute -55
-KPX Lslash ydieresis -55
-KPX N A -35
-KPX N Aacute -35
-KPX N Abreve -35
-KPX N Acircumflex -35
-KPX N Adieresis -35
-KPX N Agrave -35
-KPX N Amacron -35
-KPX N Aogonek -35
-KPX N Aring -35
-KPX N Atilde -35
-KPX Nacute A -35
-KPX Nacute Aacute -35
-KPX Nacute Abreve -35
-KPX Nacute Acircumflex -35
-KPX Nacute Adieresis -35
-KPX Nacute Agrave -35
-KPX Nacute Amacron -35
-KPX Nacute Aogonek -35
-KPX Nacute Aring -35
-KPX Nacute Atilde -35
-KPX Ncaron A -35
-KPX Ncaron Aacute -35
-KPX Ncaron Abreve -35
-KPX Ncaron Acircumflex -35
-KPX Ncaron Adieresis -35
-KPX Ncaron Agrave -35
-KPX Ncaron Amacron -35
-KPX Ncaron Aogonek -35
-KPX Ncaron Aring -35
-KPX Ncaron Atilde -35
-KPX Ncommaaccent A -35
-KPX Ncommaaccent Aacute -35
-KPX Ncommaaccent Abreve -35
-KPX Ncommaaccent Acircumflex -35
-KPX Ncommaaccent Adieresis -35
-KPX Ncommaaccent Agrave -35
-KPX Ncommaaccent Amacron -35
-KPX Ncommaaccent Aogonek -35
-KPX Ncommaaccent Aring -35
-KPX Ncommaaccent Atilde -35
-KPX Ntilde A -35
-KPX Ntilde Aacute -35
-KPX Ntilde Abreve -35
-KPX Ntilde Acircumflex -35
-KPX Ntilde Adieresis -35
-KPX Ntilde Agrave -35
-KPX Ntilde Amacron -35
-KPX Ntilde Aogonek -35
-KPX Ntilde Aring -35
-KPX Ntilde Atilde -35
-KPX O A -35
-KPX O Aacute -35
-KPX O Abreve -35
-KPX O Acircumflex -35
-KPX O Adieresis -35
-KPX O Agrave -35
-KPX O Amacron -35
-KPX O Aogonek -35
-KPX O Aring -35
-KPX O Atilde -35
-KPX O T -40
-KPX O Tcaron -40
-KPX O Tcommaaccent -40
-KPX O V -50
-KPX O W -35
-KPX O X -40
-KPX O Y -50
-KPX O Yacute -50
-KPX O Ydieresis -50
-KPX Oacute A -35
-KPX Oacute Aacute -35
-KPX Oacute Abreve -35
-KPX Oacute Acircumflex -35
-KPX Oacute Adieresis -35
-KPX Oacute Agrave -35
-KPX Oacute Amacron -35
-KPX Oacute Aogonek -35
-KPX Oacute Aring -35
-KPX Oacute Atilde -35
-KPX Oacute T -40
-KPX Oacute Tcaron -40
-KPX Oacute Tcommaaccent -40
-KPX Oacute V -50
-KPX Oacute W -35
-KPX Oacute X -40
-KPX Oacute Y -50
-KPX Oacute Yacute -50
-KPX Oacute Ydieresis -50
-KPX Ocircumflex A -35
-KPX Ocircumflex Aacute -35
-KPX Ocircumflex Abreve -35
-KPX Ocircumflex Acircumflex -35
-KPX Ocircumflex Adieresis -35
-KPX Ocircumflex Agrave -35
-KPX Ocircumflex Amacron -35
-KPX Ocircumflex Aogonek -35
-KPX Ocircumflex Aring -35
-KPX Ocircumflex Atilde -35
-KPX Ocircumflex T -40
-KPX Ocircumflex Tcaron -40
-KPX Ocircumflex Tcommaaccent -40
-KPX Ocircumflex V -50
-KPX Ocircumflex W -35
-KPX Ocircumflex X -40
-KPX Ocircumflex Y -50
-KPX Ocircumflex Yacute -50
-KPX Ocircumflex Ydieresis -50
-KPX Odieresis A -35
-KPX Odieresis Aacute -35
-KPX Odieresis Abreve -35
-KPX Odieresis Acircumflex -35
-KPX Odieresis Adieresis -35
-KPX Odieresis Agrave -35
-KPX Odieresis Amacron -35
-KPX Odieresis Aogonek -35
-KPX Odieresis Aring -35
-KPX Odieresis Atilde -35
-KPX Odieresis T -40
-KPX Odieresis Tcaron -40
-KPX Odieresis Tcommaaccent -40
-KPX Odieresis V -50
-KPX Odieresis W -35
-KPX Odieresis X -40
-KPX Odieresis Y -50
-KPX Odieresis Yacute -50
-KPX Odieresis Ydieresis -50
-KPX Ograve A -35
-KPX Ograve Aacute -35
-KPX Ograve Abreve -35
-KPX Ograve Acircumflex -35
-KPX Ograve Adieresis -35
-KPX Ograve Agrave -35
-KPX Ograve Amacron -35
-KPX Ograve Aogonek -35
-KPX Ograve Aring -35
-KPX Ograve Atilde -35
-KPX Ograve T -40
-KPX Ograve Tcaron -40
-KPX Ograve Tcommaaccent -40
-KPX Ograve V -50
-KPX Ograve W -35
-KPX Ograve X -40
-KPX Ograve Y -50
-KPX Ograve Yacute -50
-KPX Ograve Ydieresis -50
-KPX Ohungarumlaut A -35
-KPX Ohungarumlaut Aacute -35
-KPX Ohungarumlaut Abreve -35
-KPX Ohungarumlaut Acircumflex -35
-KPX Ohungarumlaut Adieresis -35
-KPX Ohungarumlaut Agrave -35
-KPX Ohungarumlaut Amacron -35
-KPX Ohungarumlaut Aogonek -35
-KPX Ohungarumlaut Aring -35
-KPX Ohungarumlaut Atilde -35
-KPX Ohungarumlaut T -40
-KPX Ohungarumlaut Tcaron -40
-KPX Ohungarumlaut Tcommaaccent -40
-KPX Ohungarumlaut V -50
-KPX Ohungarumlaut W -35
-KPX Ohungarumlaut X -40
-KPX Ohungarumlaut Y -50
-KPX Ohungarumlaut Yacute -50
-KPX Ohungarumlaut Ydieresis -50
-KPX Omacron A -35
-KPX Omacron Aacute -35
-KPX Omacron Abreve -35
-KPX Omacron Acircumflex -35
-KPX Omacron Adieresis -35
-KPX Omacron Agrave -35
-KPX Omacron Amacron -35
-KPX Omacron Aogonek -35
-KPX Omacron Aring -35
-KPX Omacron Atilde -35
-KPX Omacron T -40
-KPX Omacron Tcaron -40
-KPX Omacron Tcommaaccent -40
-KPX Omacron V -50
-KPX Omacron W -35
-KPX Omacron X -40
-KPX Omacron Y -50
-KPX Omacron Yacute -50
-KPX Omacron Ydieresis -50
-KPX Oslash A -35
-KPX Oslash Aacute -35
-KPX Oslash Abreve -35
-KPX Oslash Acircumflex -35
-KPX Oslash Adieresis -35
-KPX Oslash Agrave -35
-KPX Oslash Amacron -35
-KPX Oslash Aogonek -35
-KPX Oslash Aring -35
-KPX Oslash Atilde -35
-KPX Oslash T -40
-KPX Oslash Tcaron -40
-KPX Oslash Tcommaaccent -40
-KPX Oslash V -50
-KPX Oslash W -35
-KPX Oslash X -40
-KPX Oslash Y -50
-KPX Oslash Yacute -50
-KPX Oslash Ydieresis -50
-KPX Otilde A -35
-KPX Otilde Aacute -35
-KPX Otilde Abreve -35
-KPX Otilde Acircumflex -35
-KPX Otilde Adieresis -35
-KPX Otilde Agrave -35
-KPX Otilde Amacron -35
-KPX Otilde Aogonek -35
-KPX Otilde Aring -35
-KPX Otilde Atilde -35
-KPX Otilde T -40
-KPX Otilde Tcaron -40
-KPX Otilde Tcommaaccent -40
-KPX Otilde V -50
-KPX Otilde W -35
-KPX Otilde X -40
-KPX Otilde Y -50
-KPX Otilde Yacute -50
-KPX Otilde Ydieresis -50
-KPX P A -92
-KPX P Aacute -92
-KPX P Abreve -92
-KPX P Acircumflex -92
-KPX P Adieresis -92
-KPX P Agrave -92
-KPX P Amacron -92
-KPX P Aogonek -92
-KPX P Aring -92
-KPX P Atilde -92
-KPX P a -15
-KPX P aacute -15
-KPX P abreve -15
-KPX P acircumflex -15
-KPX P adieresis -15
-KPX P agrave -15
-KPX P amacron -15
-KPX P aogonek -15
-KPX P aring -15
-KPX P atilde -15
-KPX P comma -111
-KPX P period -111
-KPX Q U -10
-KPX Q Uacute -10
-KPX Q Ucircumflex -10
-KPX Q Udieresis -10
-KPX Q Ugrave -10
-KPX Q Uhungarumlaut -10
-KPX Q Umacron -10
-KPX Q Uogonek -10
-KPX Q Uring -10
-KPX R O -40
-KPX R Oacute -40
-KPX R Ocircumflex -40
-KPX R Odieresis -40
-KPX R Ograve -40
-KPX R Ohungarumlaut -40
-KPX R Omacron -40
-KPX R Oslash -40
-KPX R Otilde -40
-KPX R T -60
-KPX R Tcaron -60
-KPX R Tcommaaccent -60
-KPX R U -40
-KPX R Uacute -40
-KPX R Ucircumflex -40
-KPX R Udieresis -40
-KPX R Ugrave -40
-KPX R Uhungarumlaut -40
-KPX R Umacron -40
-KPX R Uogonek -40
-KPX R Uring -40
-KPX R V -80
-KPX R W -55
-KPX R Y -65
-KPX R Yacute -65
-KPX R Ydieresis -65
-KPX Racute O -40
-KPX Racute Oacute -40
-KPX Racute Ocircumflex -40
-KPX Racute Odieresis -40
-KPX Racute Ograve -40
-KPX Racute Ohungarumlaut -40
-KPX Racute Omacron -40
-KPX Racute Oslash -40
-KPX Racute Otilde -40
-KPX Racute T -60
-KPX Racute Tcaron -60
-KPX Racute Tcommaaccent -60
-KPX Racute U -40
-KPX Racute Uacute -40
-KPX Racute Ucircumflex -40
-KPX Racute Udieresis -40
-KPX Racute Ugrave -40
-KPX Racute Uhungarumlaut -40
-KPX Racute Umacron -40
-KPX Racute Uogonek -40
-KPX Racute Uring -40
-KPX Racute V -80
-KPX Racute W -55
-KPX Racute Y -65
-KPX Racute Yacute -65
-KPX Racute Ydieresis -65
-KPX Rcaron O -40
-KPX Rcaron Oacute -40
-KPX Rcaron Ocircumflex -40
-KPX Rcaron Odieresis -40
-KPX Rcaron Ograve -40
-KPX Rcaron Ohungarumlaut -40
-KPX Rcaron Omacron -40
-KPX Rcaron Oslash -40
-KPX Rcaron Otilde -40
-KPX Rcaron T -60
-KPX Rcaron Tcaron -60
-KPX Rcaron Tcommaaccent -60
-KPX Rcaron U -40
-KPX Rcaron Uacute -40
-KPX Rcaron Ucircumflex -40
-KPX Rcaron Udieresis -40
-KPX Rcaron Ugrave -40
-KPX Rcaron Uhungarumlaut -40
-KPX Rcaron Umacron -40
-KPX Rcaron Uogonek -40
-KPX Rcaron Uring -40
-KPX Rcaron V -80
-KPX Rcaron W -55
-KPX Rcaron Y -65
-KPX Rcaron Yacute -65
-KPX Rcaron Ydieresis -65
-KPX Rcommaaccent O -40
-KPX Rcommaaccent Oacute -40
-KPX Rcommaaccent Ocircumflex -40
-KPX Rcommaaccent Odieresis -40
-KPX Rcommaaccent Ograve -40
-KPX Rcommaaccent Ohungarumlaut -40
-KPX Rcommaaccent Omacron -40
-KPX Rcommaaccent Oslash -40
-KPX Rcommaaccent Otilde -40
-KPX Rcommaaccent T -60
-KPX Rcommaaccent Tcaron -60
-KPX Rcommaaccent Tcommaaccent -60
-KPX Rcommaaccent U -40
-KPX Rcommaaccent Uacute -40
-KPX Rcommaaccent Ucircumflex -40
-KPX Rcommaaccent Udieresis -40
-KPX Rcommaaccent Ugrave -40
-KPX Rcommaaccent Uhungarumlaut -40
-KPX Rcommaaccent Umacron -40
-KPX Rcommaaccent Uogonek -40
-KPX Rcommaaccent Uring -40
-KPX Rcommaaccent V -80
-KPX Rcommaaccent W -55
-KPX Rcommaaccent Y -65
-KPX Rcommaaccent Yacute -65
-KPX Rcommaaccent Ydieresis -65
-KPX T A -93
-KPX T Aacute -93
-KPX T Abreve -93
-KPX T Acircumflex -93
-KPX T Adieresis -93
-KPX T Agrave -93
-KPX T Amacron -93
-KPX T Aogonek -93
-KPX T Aring -93
-KPX T Atilde -93
-KPX T O -18
-KPX T Oacute -18
-KPX T Ocircumflex -18
-KPX T Odieresis -18
-KPX T Ograve -18
-KPX T Ohungarumlaut -18
-KPX T Omacron -18
-KPX T Oslash -18
-KPX T Otilde -18
-KPX T a -80
-KPX T aacute -80
-KPX T abreve -80
-KPX T acircumflex -80
-KPX T adieresis -40
-KPX T agrave -40
-KPX T amacron -40
-KPX T aogonek -80
-KPX T aring -80
-KPX T atilde -40
-KPX T colon -50
-KPX T comma -74
-KPX T e -70
-KPX T eacute -70
-KPX T ecaron -70
-KPX T ecircumflex -70
-KPX T edieresis -30
-KPX T edotaccent -70
-KPX T egrave -70
-KPX T emacron -30
-KPX T eogonek -70
-KPX T hyphen -92
-KPX T i -35
-KPX T iacute -35
-KPX T iogonek -35
-KPX T o -80
-KPX T oacute -80
-KPX T ocircumflex -80
-KPX T odieresis -80
-KPX T ograve -80
-KPX T ohungarumlaut -80
-KPX T omacron -80
-KPX T oslash -80
-KPX T otilde -80
-KPX T period -74
-KPX T r -35
-KPX T racute -35
-KPX T rcaron -35
-KPX T rcommaaccent -35
-KPX T semicolon -55
-KPX T u -45
-KPX T uacute -45
-KPX T ucircumflex -45
-KPX T udieresis -45
-KPX T ugrave -45
-KPX T uhungarumlaut -45
-KPX T umacron -45
-KPX T uogonek -45
-KPX T uring -45
-KPX T w -80
-KPX T y -80
-KPX T yacute -80
-KPX T ydieresis -80
-KPX Tcaron A -93
-KPX Tcaron Aacute -93
-KPX Tcaron Abreve -93
-KPX Tcaron Acircumflex -93
-KPX Tcaron Adieresis -93
-KPX Tcaron Agrave -93
-KPX Tcaron Amacron -93
-KPX Tcaron Aogonek -93
-KPX Tcaron Aring -93
-KPX Tcaron Atilde -93
-KPX Tcaron O -18
-KPX Tcaron Oacute -18
-KPX Tcaron Ocircumflex -18
-KPX Tcaron Odieresis -18
-KPX Tcaron Ograve -18
-KPX Tcaron Ohungarumlaut -18
-KPX Tcaron Omacron -18
-KPX Tcaron Oslash -18
-KPX Tcaron Otilde -18
-KPX Tcaron a -80
-KPX Tcaron aacute -80
-KPX Tcaron abreve -80
-KPX Tcaron acircumflex -80
-KPX Tcaron adieresis -40
-KPX Tcaron agrave -40
-KPX Tcaron amacron -40
-KPX Tcaron aogonek -80
-KPX Tcaron aring -80
-KPX Tcaron atilde -40
-KPX Tcaron colon -50
-KPX Tcaron comma -74
-KPX Tcaron e -70
-KPX Tcaron eacute -70
-KPX Tcaron ecaron -70
-KPX Tcaron ecircumflex -30
-KPX Tcaron edieresis -30
-KPX Tcaron edotaccent -70
-KPX Tcaron egrave -70
-KPX Tcaron emacron -30
-KPX Tcaron eogonek -70
-KPX Tcaron hyphen -92
-KPX Tcaron i -35
-KPX Tcaron iacute -35
-KPX Tcaron iogonek -35
-KPX Tcaron o -80
-KPX Tcaron oacute -80
-KPX Tcaron ocircumflex -80
-KPX Tcaron odieresis -80
-KPX Tcaron ograve -80
-KPX Tcaron ohungarumlaut -80
-KPX Tcaron omacron -80
-KPX Tcaron oslash -80
-KPX Tcaron otilde -80
-KPX Tcaron period -74
-KPX Tcaron r -35
-KPX Tcaron racute -35
-KPX Tcaron rcaron -35
-KPX Tcaron rcommaaccent -35
-KPX Tcaron semicolon -55
-KPX Tcaron u -45
-KPX Tcaron uacute -45
-KPX Tcaron ucircumflex -45
-KPX Tcaron udieresis -45
-KPX Tcaron ugrave -45
-KPX Tcaron uhungarumlaut -45
-KPX Tcaron umacron -45
-KPX Tcaron uogonek -45
-KPX Tcaron uring -45
-KPX Tcaron w -80
-KPX Tcaron y -80
-KPX Tcaron yacute -80
-KPX Tcaron ydieresis -80
-KPX Tcommaaccent A -93
-KPX Tcommaaccent Aacute -93
-KPX Tcommaaccent Abreve -93
-KPX Tcommaaccent Acircumflex -93
-KPX Tcommaaccent Adieresis -93
-KPX Tcommaaccent Agrave -93
-KPX Tcommaaccent Amacron -93
-KPX Tcommaaccent Aogonek -93
-KPX Tcommaaccent Aring -93
-KPX Tcommaaccent Atilde -93
-KPX Tcommaaccent O -18
-KPX Tcommaaccent Oacute -18
-KPX Tcommaaccent Ocircumflex -18
-KPX Tcommaaccent Odieresis -18
-KPX Tcommaaccent Ograve -18
-KPX Tcommaaccent Ohungarumlaut -18
-KPX Tcommaaccent Omacron -18
-KPX Tcommaaccent Oslash -18
-KPX Tcommaaccent Otilde -18
-KPX Tcommaaccent a -80
-KPX Tcommaaccent aacute -80
-KPX Tcommaaccent abreve -80
-KPX Tcommaaccent acircumflex -80
-KPX Tcommaaccent adieresis -40
-KPX Tcommaaccent agrave -40
-KPX Tcommaaccent amacron -40
-KPX Tcommaaccent aogonek -80
-KPX Tcommaaccent aring -80
-KPX Tcommaaccent atilde -40
-KPX Tcommaaccent colon -50
-KPX Tcommaaccent comma -74
-KPX Tcommaaccent e -70
-KPX Tcommaaccent eacute -70
-KPX Tcommaaccent ecaron -70
-KPX Tcommaaccent ecircumflex -30
-KPX Tcommaaccent edieresis -30
-KPX Tcommaaccent edotaccent -70
-KPX Tcommaaccent egrave -30
-KPX Tcommaaccent emacron -70
-KPX Tcommaaccent eogonek -70
-KPX Tcommaaccent hyphen -92
-KPX Tcommaaccent i -35
-KPX Tcommaaccent iacute -35
-KPX Tcommaaccent iogonek -35
-KPX Tcommaaccent o -80
-KPX Tcommaaccent oacute -80
-KPX Tcommaaccent ocircumflex -80
-KPX Tcommaaccent odieresis -80
-KPX Tcommaaccent ograve -80
-KPX Tcommaaccent ohungarumlaut -80
-KPX Tcommaaccent omacron -80
-KPX Tcommaaccent oslash -80
-KPX Tcommaaccent otilde -80
-KPX Tcommaaccent period -74
-KPX Tcommaaccent r -35
-KPX Tcommaaccent racute -35
-KPX Tcommaaccent rcaron -35
-KPX Tcommaaccent rcommaaccent -35
-KPX Tcommaaccent semicolon -55
-KPX Tcommaaccent u -45
-KPX Tcommaaccent uacute -45
-KPX Tcommaaccent ucircumflex -45
-KPX Tcommaaccent udieresis -45
-KPX Tcommaaccent ugrave -45
-KPX Tcommaaccent uhungarumlaut -45
-KPX Tcommaaccent umacron -45
-KPX Tcommaaccent uogonek -45
-KPX Tcommaaccent uring -45
-KPX Tcommaaccent w -80
-KPX Tcommaaccent y -80
-KPX Tcommaaccent yacute -80
-KPX Tcommaaccent ydieresis -80
-KPX U A -40
-KPX U Aacute -40
-KPX U Abreve -40
-KPX U Acircumflex -40
-KPX U Adieresis -40
-KPX U Agrave -40
-KPX U Amacron -40
-KPX U Aogonek -40
-KPX U Aring -40
-KPX U Atilde -40
-KPX Uacute A -40
-KPX Uacute Aacute -40
-KPX Uacute Abreve -40
-KPX Uacute Acircumflex -40
-KPX Uacute Adieresis -40
-KPX Uacute Agrave -40
-KPX Uacute Amacron -40
-KPX Uacute Aogonek -40
-KPX Uacute Aring -40
-KPX Uacute Atilde -40
-KPX Ucircumflex A -40
-KPX Ucircumflex Aacute -40
-KPX Ucircumflex Abreve -40
-KPX Ucircumflex Acircumflex -40
-KPX Ucircumflex Adieresis -40
-KPX Ucircumflex Agrave -40
-KPX Ucircumflex Amacron -40
-KPX Ucircumflex Aogonek -40
-KPX Ucircumflex Aring -40
-KPX Ucircumflex Atilde -40
-KPX Udieresis A -40
-KPX Udieresis Aacute -40
-KPX Udieresis Abreve -40
-KPX Udieresis Acircumflex -40
-KPX Udieresis Adieresis -40
-KPX Udieresis Agrave -40
-KPX Udieresis Amacron -40
-KPX Udieresis Aogonek -40
-KPX Udieresis Aring -40
-KPX Udieresis Atilde -40
-KPX Ugrave A -40
-KPX Ugrave Aacute -40
-KPX Ugrave Abreve -40
-KPX Ugrave Acircumflex -40
-KPX Ugrave Adieresis -40
-KPX Ugrave Agrave -40
-KPX Ugrave Amacron -40
-KPX Ugrave Aogonek -40
-KPX Ugrave Aring -40
-KPX Ugrave Atilde -40
-KPX Uhungarumlaut A -40
-KPX Uhungarumlaut Aacute -40
-KPX Uhungarumlaut Abreve -40
-KPX Uhungarumlaut Acircumflex -40
-KPX Uhungarumlaut Adieresis -40
-KPX Uhungarumlaut Agrave -40
-KPX Uhungarumlaut Amacron -40
-KPX Uhungarumlaut Aogonek -40
-KPX Uhungarumlaut Aring -40
-KPX Uhungarumlaut Atilde -40
-KPX Umacron A -40
-KPX Umacron Aacute -40
-KPX Umacron Abreve -40
-KPX Umacron Acircumflex -40
-KPX Umacron Adieresis -40
-KPX Umacron Agrave -40
-KPX Umacron Amacron -40
-KPX Umacron Aogonek -40
-KPX Umacron Aring -40
-KPX Umacron Atilde -40
-KPX Uogonek A -40
-KPX Uogonek Aacute -40
-KPX Uogonek Abreve -40
-KPX Uogonek Acircumflex -40
-KPX Uogonek Adieresis -40
-KPX Uogonek Agrave -40
-KPX Uogonek Amacron -40
-KPX Uogonek Aogonek -40
-KPX Uogonek Aring -40
-KPX Uogonek Atilde -40
-KPX Uring A -40
-KPX Uring Aacute -40
-KPX Uring Abreve -40
-KPX Uring Acircumflex -40
-KPX Uring Adieresis -40
-KPX Uring Agrave -40
-KPX Uring Amacron -40
-KPX Uring Aogonek -40
-KPX Uring Aring -40
-KPX Uring Atilde -40
-KPX V A -135
-KPX V Aacute -135
-KPX V Abreve -135
-KPX V Acircumflex -135
-KPX V Adieresis -135
-KPX V Agrave -135
-KPX V Amacron -135
-KPX V Aogonek -135
-KPX V Aring -135
-KPX V Atilde -135
-KPX V G -15
-KPX V Gbreve -15
-KPX V Gcommaaccent -15
-KPX V O -40
-KPX V Oacute -40
-KPX V Ocircumflex -40
-KPX V Odieresis -40
-KPX V Ograve -40
-KPX V Ohungarumlaut -40
-KPX V Omacron -40
-KPX V Oslash -40
-KPX V Otilde -40
-KPX V a -111
-KPX V aacute -111
-KPX V abreve -111
-KPX V acircumflex -71
-KPX V adieresis -71
-KPX V agrave -71
-KPX V amacron -71
-KPX V aogonek -111
-KPX V aring -111
-KPX V atilde -71
-KPX V colon -74
-KPX V comma -129
-KPX V e -111
-KPX V eacute -111
-KPX V ecaron -71
-KPX V ecircumflex -71
-KPX V edieresis -71
-KPX V edotaccent -111
-KPX V egrave -71
-KPX V emacron -71
-KPX V eogonek -111
-KPX V hyphen -100
-KPX V i -60
-KPX V iacute -60
-KPX V icircumflex -20
-KPX V idieresis -20
-KPX V igrave -20
-KPX V imacron -20
-KPX V iogonek -60
-KPX V o -129
-KPX V oacute -129
-KPX V ocircumflex -129
-KPX V odieresis -89
-KPX V ograve -89
-KPX V ohungarumlaut -129
-KPX V omacron -89
-KPX V oslash -129
-KPX V otilde -89
-KPX V period -129
-KPX V semicolon -74
-KPX V u -75
-KPX V uacute -75
-KPX V ucircumflex -75
-KPX V udieresis -75
-KPX V ugrave -75
-KPX V uhungarumlaut -75
-KPX V umacron -75
-KPX V uogonek -75
-KPX V uring -75
-KPX W A -120
-KPX W Aacute -120
-KPX W Abreve -120
-KPX W Acircumflex -120
-KPX W Adieresis -120
-KPX W Agrave -120
-KPX W Amacron -120
-KPX W Aogonek -120
-KPX W Aring -120
-KPX W Atilde -120
-KPX W O -10
-KPX W Oacute -10
-KPX W Ocircumflex -10
-KPX W Odieresis -10
-KPX W Ograve -10
-KPX W Ohungarumlaut -10
-KPX W Omacron -10
-KPX W Oslash -10
-KPX W Otilde -10
-KPX W a -80
-KPX W aacute -80
-KPX W abreve -80
-KPX W acircumflex -80
-KPX W adieresis -80
-KPX W agrave -80
-KPX W amacron -80
-KPX W aogonek -80
-KPX W aring -80
-KPX W atilde -80
-KPX W colon -37
-KPX W comma -92
-KPX W e -80
-KPX W eacute -80
-KPX W ecaron -80
-KPX W ecircumflex -80
-KPX W edieresis -40
-KPX W edotaccent -80
-KPX W egrave -40
-KPX W emacron -40
-KPX W eogonek -80
-KPX W hyphen -65
-KPX W i -40
-KPX W iacute -40
-KPX W iogonek -40
-KPX W o -80
-KPX W oacute -80
-KPX W ocircumflex -80
-KPX W odieresis -80
-KPX W ograve -80
-KPX W ohungarumlaut -80
-KPX W omacron -80
-KPX W oslash -80
-KPX W otilde -80
-KPX W period -92
-KPX W semicolon -37
-KPX W u -50
-KPX W uacute -50
-KPX W ucircumflex -50
-KPX W udieresis -50
-KPX W ugrave -50
-KPX W uhungarumlaut -50
-KPX W umacron -50
-KPX W uogonek -50
-KPX W uring -50
-KPX W y -73
-KPX W yacute -73
-KPX W ydieresis -73
-KPX Y A -120
-KPX Y Aacute -120
-KPX Y Abreve -120
-KPX Y Acircumflex -120
-KPX Y Adieresis -120
-KPX Y Agrave -120
-KPX Y Amacron -120
-KPX Y Aogonek -120
-KPX Y Aring -120
-KPX Y Atilde -120
-KPX Y O -30
-KPX Y Oacute -30
-KPX Y Ocircumflex -30
-KPX Y Odieresis -30
-KPX Y Ograve -30
-KPX Y Ohungarumlaut -30
-KPX Y Omacron -30
-KPX Y Oslash -30
-KPX Y Otilde -30
-KPX Y a -100
-KPX Y aacute -100
-KPX Y abreve -100
-KPX Y acircumflex -100
-KPX Y adieresis -60
-KPX Y agrave -60
-KPX Y amacron -60
-KPX Y aogonek -100
-KPX Y aring -100
-KPX Y atilde -60
-KPX Y colon -92
-KPX Y comma -129
-KPX Y e -100
-KPX Y eacute -100
-KPX Y ecaron -100
-KPX Y ecircumflex -100
-KPX Y edieresis -60
-KPX Y edotaccent -100
-KPX Y egrave -60
-KPX Y emacron -60
-KPX Y eogonek -100
-KPX Y hyphen -111
-KPX Y i -55
-KPX Y iacute -55
-KPX Y iogonek -55
-KPX Y o -110
-KPX Y oacute -110
-KPX Y ocircumflex -110
-KPX Y odieresis -70
-KPX Y ograve -70
-KPX Y ohungarumlaut -110
-KPX Y omacron -70
-KPX Y oslash -110
-KPX Y otilde -70
-KPX Y period -129
-KPX Y semicolon -92
-KPX Y u -111
-KPX Y uacute -111
-KPX Y ucircumflex -111
-KPX Y udieresis -71
-KPX Y ugrave -71
-KPX Y uhungarumlaut -111
-KPX Y umacron -71
-KPX Y uogonek -111
-KPX Y uring -111
-KPX Yacute A -120
-KPX Yacute Aacute -120
-KPX Yacute Abreve -120
-KPX Yacute Acircumflex -120
-KPX Yacute Adieresis -120
-KPX Yacute Agrave -120
-KPX Yacute Amacron -120
-KPX Yacute Aogonek -120
-KPX Yacute Aring -120
-KPX Yacute Atilde -120
-KPX Yacute O -30
-KPX Yacute Oacute -30
-KPX Yacute Ocircumflex -30
-KPX Yacute Odieresis -30
-KPX Yacute Ograve -30
-KPX Yacute Ohungarumlaut -30
-KPX Yacute Omacron -30
-KPX Yacute Oslash -30
-KPX Yacute Otilde -30
-KPX Yacute a -100
-KPX Yacute aacute -100
-KPX Yacute abreve -100
-KPX Yacute acircumflex -100
-KPX Yacute adieresis -60
-KPX Yacute agrave -60
-KPX Yacute amacron -60
-KPX Yacute aogonek -100
-KPX Yacute aring -100
-KPX Yacute atilde -60
-KPX Yacute colon -92
-KPX Yacute comma -129
-KPX Yacute e -100
-KPX Yacute eacute -100
-KPX Yacute ecaron -100
-KPX Yacute ecircumflex -100
-KPX Yacute edieresis -60
-KPX Yacute edotaccent -100
-KPX Yacute egrave -60
-KPX Yacute emacron -60
-KPX Yacute eogonek -100
-KPX Yacute hyphen -111
-KPX Yacute i -55
-KPX Yacute iacute -55
-KPX Yacute iogonek -55
-KPX Yacute o -110
-KPX Yacute oacute -110
-KPX Yacute ocircumflex -110
-KPX Yacute odieresis -70
-KPX Yacute ograve -70
-KPX Yacute ohungarumlaut -110
-KPX Yacute omacron -70
-KPX Yacute oslash -110
-KPX Yacute otilde -70
-KPX Yacute period -129
-KPX Yacute semicolon -92
-KPX Yacute u -111
-KPX Yacute uacute -111
-KPX Yacute ucircumflex -111
-KPX Yacute udieresis -71
-KPX Yacute ugrave -71
-KPX Yacute uhungarumlaut -111
-KPX Yacute umacron -71
-KPX Yacute uogonek -111
-KPX Yacute uring -111
-KPX Ydieresis A -120
-KPX Ydieresis Aacute -120
-KPX Ydieresis Abreve -120
-KPX Ydieresis Acircumflex -120
-KPX Ydieresis Adieresis -120
-KPX Ydieresis Agrave -120
-KPX Ydieresis Amacron -120
-KPX Ydieresis Aogonek -120
-KPX Ydieresis Aring -120
-KPX Ydieresis Atilde -120
-KPX Ydieresis O -30
-KPX Ydieresis Oacute -30
-KPX Ydieresis Ocircumflex -30
-KPX Ydieresis Odieresis -30
-KPX Ydieresis Ograve -30
-KPX Ydieresis Ohungarumlaut -30
-KPX Ydieresis Omacron -30
-KPX Ydieresis Oslash -30
-KPX Ydieresis Otilde -30
-KPX Ydieresis a -100
-KPX Ydieresis aacute -100
-KPX Ydieresis abreve -100
-KPX Ydieresis acircumflex -100
-KPX Ydieresis adieresis -60
-KPX Ydieresis agrave -60
-KPX Ydieresis amacron -60
-KPX Ydieresis aogonek -100
-KPX Ydieresis aring -100
-KPX Ydieresis atilde -100
-KPX Ydieresis colon -92
-KPX Ydieresis comma -129
-KPX Ydieresis e -100
-KPX Ydieresis eacute -100
-KPX Ydieresis ecaron -100
-KPX Ydieresis ecircumflex -100
-KPX Ydieresis edieresis -60
-KPX Ydieresis edotaccent -100
-KPX Ydieresis egrave -60
-KPX Ydieresis emacron -60
-KPX Ydieresis eogonek -100
-KPX Ydieresis hyphen -111
-KPX Ydieresis i -55
-KPX Ydieresis iacute -55
-KPX Ydieresis iogonek -55
-KPX Ydieresis o -110
-KPX Ydieresis oacute -110
-KPX Ydieresis ocircumflex -110
-KPX Ydieresis odieresis -70
-KPX Ydieresis ograve -70
-KPX Ydieresis ohungarumlaut -110
-KPX Ydieresis omacron -70
-KPX Ydieresis oslash -110
-KPX Ydieresis otilde -70
-KPX Ydieresis period -129
-KPX Ydieresis semicolon -92
-KPX Ydieresis u -111
-KPX Ydieresis uacute -111
-KPX Ydieresis ucircumflex -111
-KPX Ydieresis udieresis -71
-KPX Ydieresis ugrave -71
-KPX Ydieresis uhungarumlaut -111
-KPX Ydieresis umacron -71
-KPX Ydieresis uogonek -111
-KPX Ydieresis uring -111
-KPX a v -20
-KPX a w -15
-KPX aacute v -20
-KPX aacute w -15
-KPX abreve v -20
-KPX abreve w -15
-KPX acircumflex v -20
-KPX acircumflex w -15
-KPX adieresis v -20
-KPX adieresis w -15
-KPX agrave v -20
-KPX agrave w -15
-KPX amacron v -20
-KPX amacron w -15
-KPX aogonek v -20
-KPX aogonek w -15
-KPX aring v -20
-KPX aring w -15
-KPX atilde v -20
-KPX atilde w -15
-KPX b period -40
-KPX b u -20
-KPX b uacute -20
-KPX b ucircumflex -20
-KPX b udieresis -20
-KPX b ugrave -20
-KPX b uhungarumlaut -20
-KPX b umacron -20
-KPX b uogonek -20
-KPX b uring -20
-KPX b v -15
-KPX c y -15
-KPX c yacute -15
-KPX c ydieresis -15
-KPX cacute y -15
-KPX cacute yacute -15
-KPX cacute ydieresis -15
-KPX ccaron y -15
-KPX ccaron yacute -15
-KPX ccaron ydieresis -15
-KPX ccedilla y -15
-KPX ccedilla yacute -15
-KPX ccedilla ydieresis -15
-KPX comma quotedblright -70
-KPX comma quoteright -70
-KPX e g -15
-KPX e gbreve -15
-KPX e gcommaaccent -15
-KPX e v -25
-KPX e w -25
-KPX e x -15
-KPX e y -15
-KPX e yacute -15
-KPX e ydieresis -15
-KPX eacute g -15
-KPX eacute gbreve -15
-KPX eacute gcommaaccent -15
-KPX eacute v -25
-KPX eacute w -25
-KPX eacute x -15
-KPX eacute y -15
-KPX eacute yacute -15
-KPX eacute ydieresis -15
-KPX ecaron g -15
-KPX ecaron gbreve -15
-KPX ecaron gcommaaccent -15
-KPX ecaron v -25
-KPX ecaron w -25
-KPX ecaron x -15
-KPX ecaron y -15
-KPX ecaron yacute -15
-KPX ecaron ydieresis -15
-KPX ecircumflex g -15
-KPX ecircumflex gbreve -15
-KPX ecircumflex gcommaaccent -15
-KPX ecircumflex v -25
-KPX ecircumflex w -25
-KPX ecircumflex x -15
-KPX ecircumflex y -15
-KPX ecircumflex yacute -15
-KPX ecircumflex ydieresis -15
-KPX edieresis g -15
-KPX edieresis gbreve -15
-KPX edieresis gcommaaccent -15
-KPX edieresis v -25
-KPX edieresis w -25
-KPX edieresis x -15
-KPX edieresis y -15
-KPX edieresis yacute -15
-KPX edieresis ydieresis -15
-KPX edotaccent g -15
-KPX edotaccent gbreve -15
-KPX edotaccent gcommaaccent -15
-KPX edotaccent v -25
-KPX edotaccent w -25
-KPX edotaccent x -15
-KPX edotaccent y -15
-KPX edotaccent yacute -15
-KPX edotaccent ydieresis -15
-KPX egrave g -15
-KPX egrave gbreve -15
-KPX egrave gcommaaccent -15
-KPX egrave v -25
-KPX egrave w -25
-KPX egrave x -15
-KPX egrave y -15
-KPX egrave yacute -15
-KPX egrave ydieresis -15
-KPX emacron g -15
-KPX emacron gbreve -15
-KPX emacron gcommaaccent -15
-KPX emacron v -25
-KPX emacron w -25
-KPX emacron x -15
-KPX emacron y -15
-KPX emacron yacute -15
-KPX emacron ydieresis -15
-KPX eogonek g -15
-KPX eogonek gbreve -15
-KPX eogonek gcommaaccent -15
-KPX eogonek v -25
-KPX eogonek w -25
-KPX eogonek x -15
-KPX eogonek y -15
-KPX eogonek yacute -15
-KPX eogonek ydieresis -15
-KPX f a -10
-KPX f aacute -10
-KPX f abreve -10
-KPX f acircumflex -10
-KPX f adieresis -10
-KPX f agrave -10
-KPX f amacron -10
-KPX f aogonek -10
-KPX f aring -10
-KPX f atilde -10
-KPX f dotlessi -50
-KPX f f -25
-KPX f i -20
-KPX f iacute -20
-KPX f quoteright 55
-KPX g a -5
-KPX g aacute -5
-KPX g abreve -5
-KPX g acircumflex -5
-KPX g adieresis -5
-KPX g agrave -5
-KPX g amacron -5
-KPX g aogonek -5
-KPX g aring -5
-KPX g atilde -5
-KPX gbreve a -5
-KPX gbreve aacute -5
-KPX gbreve abreve -5
-KPX gbreve acircumflex -5
-KPX gbreve adieresis -5
-KPX gbreve agrave -5
-KPX gbreve amacron -5
-KPX gbreve aogonek -5
-KPX gbreve aring -5
-KPX gbreve atilde -5
-KPX gcommaaccent a -5
-KPX gcommaaccent aacute -5
-KPX gcommaaccent abreve -5
-KPX gcommaaccent acircumflex -5
-KPX gcommaaccent adieresis -5
-KPX gcommaaccent agrave -5
-KPX gcommaaccent amacron -5
-KPX gcommaaccent aogonek -5
-KPX gcommaaccent aring -5
-KPX gcommaaccent atilde -5
-KPX h y -5
-KPX h yacute -5
-KPX h ydieresis -5
-KPX i v -25
-KPX iacute v -25
-KPX icircumflex v -25
-KPX idieresis v -25
-KPX igrave v -25
-KPX imacron v -25
-KPX iogonek v -25
-KPX k e -10
-KPX k eacute -10
-KPX k ecaron -10
-KPX k ecircumflex -10
-KPX k edieresis -10
-KPX k edotaccent -10
-KPX k egrave -10
-KPX k emacron -10
-KPX k eogonek -10
-KPX k o -10
-KPX k oacute -10
-KPX k ocircumflex -10
-KPX k odieresis -10
-KPX k ograve -10
-KPX k ohungarumlaut -10
-KPX k omacron -10
-KPX k oslash -10
-KPX k otilde -10
-KPX k y -15
-KPX k yacute -15
-KPX k ydieresis -15
-KPX kcommaaccent e -10
-KPX kcommaaccent eacute -10
-KPX kcommaaccent ecaron -10
-KPX kcommaaccent ecircumflex -10
-KPX kcommaaccent edieresis -10
-KPX kcommaaccent edotaccent -10
-KPX kcommaaccent egrave -10
-KPX kcommaaccent emacron -10
-KPX kcommaaccent eogonek -10
-KPX kcommaaccent o -10
-KPX kcommaaccent oacute -10
-KPX kcommaaccent ocircumflex -10
-KPX kcommaaccent odieresis -10
-KPX kcommaaccent ograve -10
-KPX kcommaaccent ohungarumlaut -10
-KPX kcommaaccent omacron -10
-KPX kcommaaccent oslash -10
-KPX kcommaaccent otilde -10
-KPX kcommaaccent y -15
-KPX kcommaaccent yacute -15
-KPX kcommaaccent ydieresis -15
-KPX l w -10
-KPX lacute w -10
-KPX lcommaaccent w -10
-KPX lslash w -10
-KPX n v -40
-KPX n y -15
-KPX n yacute -15
-KPX n ydieresis -15
-KPX nacute v -40
-KPX nacute y -15
-KPX nacute yacute -15
-KPX nacute ydieresis -15
-KPX ncaron v -40
-KPX ncaron y -15
-KPX ncaron yacute -15
-KPX ncaron ydieresis -15
-KPX ncommaaccent v -40
-KPX ncommaaccent y -15
-KPX ncommaaccent yacute -15
-KPX ncommaaccent ydieresis -15
-KPX ntilde v -40
-KPX ntilde y -15
-KPX ntilde yacute -15
-KPX ntilde ydieresis -15
-KPX o v -15
-KPX o w -25
-KPX o y -10
-KPX o yacute -10
-KPX o ydieresis -10
-KPX oacute v -15
-KPX oacute w -25
-KPX oacute y -10
-KPX oacute yacute -10
-KPX oacute ydieresis -10
-KPX ocircumflex v -15
-KPX ocircumflex w -25
-KPX ocircumflex y -10
-KPX ocircumflex yacute -10
-KPX ocircumflex ydieresis -10
-KPX odieresis v -15
-KPX odieresis w -25
-KPX odieresis y -10
-KPX odieresis yacute -10
-KPX odieresis ydieresis -10
-KPX ograve v -15
-KPX ograve w -25
-KPX ograve y -10
-KPX ograve yacute -10
-KPX ograve ydieresis -10
-KPX ohungarumlaut v -15
-KPX ohungarumlaut w -25
-KPX ohungarumlaut y -10
-KPX ohungarumlaut yacute -10
-KPX ohungarumlaut ydieresis -10
-KPX omacron v -15
-KPX omacron w -25
-KPX omacron y -10
-KPX omacron yacute -10
-KPX omacron ydieresis -10
-KPX oslash v -15
-KPX oslash w -25
-KPX oslash y -10
-KPX oslash yacute -10
-KPX oslash ydieresis -10
-KPX otilde v -15
-KPX otilde w -25
-KPX otilde y -10
-KPX otilde yacute -10
-KPX otilde ydieresis -10
-KPX p y -10
-KPX p yacute -10
-KPX p ydieresis -10
-KPX period quotedblright -70
-KPX period quoteright -70
-KPX quotedblleft A -80
-KPX quotedblleft Aacute -80
-KPX quotedblleft Abreve -80
-KPX quotedblleft Acircumflex -80
-KPX quotedblleft Adieresis -80
-KPX quotedblleft Agrave -80
-KPX quotedblleft Amacron -80
-KPX quotedblleft Aogonek -80
-KPX quotedblleft Aring -80
-KPX quotedblleft Atilde -80
-KPX quoteleft A -80
-KPX quoteleft Aacute -80
-KPX quoteleft Abreve -80
-KPX quoteleft Acircumflex -80
-KPX quoteleft Adieresis -80
-KPX quoteleft Agrave -80
-KPX quoteleft Amacron -80
-KPX quoteleft Aogonek -80
-KPX quoteleft Aring -80
-KPX quoteleft Atilde -80
-KPX quoteleft quoteleft -74
-KPX quoteright d -50
-KPX quoteright dcroat -50
-KPX quoteright l -10
-KPX quoteright lacute -10
-KPX quoteright lcommaaccent -10
-KPX quoteright lslash -10
-KPX quoteright quoteright -74
-KPX quoteright r -50
-KPX quoteright racute -50
-KPX quoteright rcaron -50
-KPX quoteright rcommaaccent -50
-KPX quoteright s -55
-KPX quoteright sacute -55
-KPX quoteright scaron -55
-KPX quoteright scedilla -55
-KPX quoteright scommaaccent -55
-KPX quoteright space -74
-KPX quoteright t -18
-KPX quoteright tcommaaccent -18
-KPX quoteright v -50
-KPX r comma -40
-KPX r g -18
-KPX r gbreve -18
-KPX r gcommaaccent -18
-KPX r hyphen -20
-KPX r period -55
-KPX racute comma -40
-KPX racute g -18
-KPX racute gbreve -18
-KPX racute gcommaaccent -18
-KPX racute hyphen -20
-KPX racute period -55
-KPX rcaron comma -40
-KPX rcaron g -18
-KPX rcaron gbreve -18
-KPX rcaron gcommaaccent -18
-KPX rcaron hyphen -20
-KPX rcaron period -55
-KPX rcommaaccent comma -40
-KPX rcommaaccent g -18
-KPX rcommaaccent gbreve -18
-KPX rcommaaccent gcommaaccent -18
-KPX rcommaaccent hyphen -20
-KPX rcommaaccent period -55
-KPX space A -55
-KPX space Aacute -55
-KPX space Abreve -55
-KPX space Acircumflex -55
-KPX space Adieresis -55
-KPX space Agrave -55
-KPX space Amacron -55
-KPX space Aogonek -55
-KPX space Aring -55
-KPX space Atilde -55
-KPX space T -18
-KPX space Tcaron -18
-KPX space Tcommaaccent -18
-KPX space V -50
-KPX space W -30
-KPX space Y -90
-KPX space Yacute -90
-KPX space Ydieresis -90
-KPX v a -25
-KPX v aacute -25
-KPX v abreve -25
-KPX v acircumflex -25
-KPX v adieresis -25
-KPX v agrave -25
-KPX v amacron -25
-KPX v aogonek -25
-KPX v aring -25
-KPX v atilde -25
-KPX v comma -65
-KPX v e -15
-KPX v eacute -15
-KPX v ecaron -15
-KPX v ecircumflex -15
-KPX v edieresis -15
-KPX v edotaccent -15
-KPX v egrave -15
-KPX v emacron -15
-KPX v eogonek -15
-KPX v o -20
-KPX v oacute -20
-KPX v ocircumflex -20
-KPX v odieresis -20
-KPX v ograve -20
-KPX v ohungarumlaut -20
-KPX v omacron -20
-KPX v oslash -20
-KPX v otilde -20
-KPX v period -65
-KPX w a -10
-KPX w aacute -10
-KPX w abreve -10
-KPX w acircumflex -10
-KPX w adieresis -10
-KPX w agrave -10
-KPX w amacron -10
-KPX w aogonek -10
-KPX w aring -10
-KPX w atilde -10
-KPX w comma -65
-KPX w o -10
-KPX w oacute -10
-KPX w ocircumflex -10
-KPX w odieresis -10
-KPX w ograve -10
-KPX w ohungarumlaut -10
-KPX w omacron -10
-KPX w oslash -10
-KPX w otilde -10
-KPX w period -65
-KPX x e -15
-KPX x eacute -15
-KPX x ecaron -15
-KPX x ecircumflex -15
-KPX x edieresis -15
-KPX x edotaccent -15
-KPX x egrave -15
-KPX x emacron -15
-KPX x eogonek -15
-KPX y comma -65
-KPX y period -65
-KPX yacute comma -65
-KPX yacute period -65
-KPX ydieresis comma -65
-KPX ydieresis period -65
-EndKernPairs
-EndKernData
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/pdf/fonts/ZapfDingbats.afm pdftk-2.01/java/com/lowagie/text/pdf/fonts/ZapfDingbats.afm
--- pdftk-1.45/java/com/lowagie/text/pdf/fonts/ZapfDingbats.afm 2004-05-26 16:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/pdf/fonts/ZapfDingbats.afm 1970-01-01 00:00:00.000000000 +0000
@@ -1,225 +0,0 @@
-StartFontMetrics 4.1
-Comment Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated. All Rights Reserved.
-Comment Creation Date: Thu May 1 15:14:13 1997
-Comment UniqueID 43082
-Comment VMusage 45775 55535
-FontName ZapfDingbats
-FullName ITC Zapf Dingbats
-FamilyName ZapfDingbats
-Weight Medium
-ItalicAngle 0
-IsFixedPitch false
-CharacterSet Special
-FontBBox -1 -143 981 820
-UnderlinePosition -100
-UnderlineThickness 50
-Version 002.000
-Notice Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated. All Rights Reserved.ITC Zapf Dingbats is a registered trademark of International Typeface Corporation.
-EncodingScheme FontSpecific
-StdHW 28
-StdVW 90
-StartCharMetrics 202
-C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
-C 33 ; WX 974 ; N a1 ; B 35 72 939 621 ;
-C 34 ; WX 961 ; N a2 ; B 35 81 927 611 ;
-C 35 ; WX 974 ; N a202 ; B 35 72 939 621 ;
-C 36 ; WX 980 ; N a3 ; B 35 0 945 692 ;
-C 37 ; WX 719 ; N a4 ; B 34 139 685 566 ;
-C 38 ; WX 789 ; N a5 ; B 35 -14 755 705 ;
-C 39 ; WX 790 ; N a119 ; B 35 -14 755 705 ;
-C 40 ; WX 791 ; N a118 ; B 35 -13 761 705 ;
-C 41 ; WX 690 ; N a117 ; B 34 138 655 553 ;
-C 42 ; WX 960 ; N a11 ; B 35 123 925 568 ;
-C 43 ; WX 939 ; N a12 ; B 35 134 904 559 ;
-C 44 ; WX 549 ; N a13 ; B 29 -11 516 705 ;
-C 45 ; WX 855 ; N a14 ; B 34 59 820 632 ;
-C 46 ; WX 911 ; N a15 ; B 35 50 876 642 ;
-C 47 ; WX 933 ; N a16 ; B 35 139 899 550 ;
-C 48 ; WX 911 ; N a105 ; B 35 50 876 642 ;
-C 49 ; WX 945 ; N a17 ; B 35 139 909 553 ;
-C 50 ; WX 974 ; N a18 ; B 35 104 938 587 ;
-C 51 ; WX 755 ; N a19 ; B 34 -13 721 705 ;
-C 52 ; WX 846 ; N a20 ; B 36 -14 811 705 ;
-C 53 ; WX 762 ; N a21 ; B 35 0 727 692 ;
-C 54 ; WX 761 ; N a22 ; B 35 0 727 692 ;
-C 55 ; WX 571 ; N a23 ; B -1 -68 571 661 ;
-C 56 ; WX 677 ; N a24 ; B 36 -13 642 705 ;
-C 57 ; WX 763 ; N a25 ; B 35 0 728 692 ;
-C 58 ; WX 760 ; N a26 ; B 35 0 726 692 ;
-C 59 ; WX 759 ; N a27 ; B 35 0 725 692 ;
-C 60 ; WX 754 ; N a28 ; B 35 0 720 692 ;
-C 61 ; WX 494 ; N a6 ; B 35 0 460 692 ;
-C 62 ; WX 552 ; N a7 ; B 35 0 517 692 ;
-C 63 ; WX 537 ; N a8 ; B 35 0 503 692 ;
-C 64 ; WX 577 ; N a9 ; B 35 96 542 596 ;
-C 65 ; WX 692 ; N a10 ; B 35 -14 657 705 ;
-C 66 ; WX 786 ; N a29 ; B 35 -14 751 705 ;
-C 67 ; WX 788 ; N a30 ; B 35 -14 752 705 ;
-C 68 ; WX 788 ; N a31 ; B 35 -14 753 705 ;
-C 69 ; WX 790 ; N a32 ; B 35 -14 756 705 ;
-C 70 ; WX 793 ; N a33 ; B 35 -13 759 705 ;
-C 71 ; WX 794 ; N a34 ; B 35 -13 759 705 ;
-C 72 ; WX 816 ; N a35 ; B 35 -14 782 705 ;
-C 73 ; WX 823 ; N a36 ; B 35 -14 787 705 ;
-C 74 ; WX 789 ; N a37 ; B 35 -14 754 705 ;
-C 75 ; WX 841 ; N a38 ; B 35 -14 807 705 ;
-C 76 ; WX 823 ; N a39 ; B 35 -14 789 705 ;
-C 77 ; WX 833 ; N a40 ; B 35 -14 798 705 ;
-C 78 ; WX 816 ; N a41 ; B 35 -13 782 705 ;
-C 79 ; WX 831 ; N a42 ; B 35 -14 796 705 ;
-C 80 ; WX 923 ; N a43 ; B 35 -14 888 705 ;
-C 81 ; WX 744 ; N a44 ; B 35 0 710 692 ;
-C 82 ; WX 723 ; N a45 ; B 35 0 688 692 ;
-C 83 ; WX 749 ; N a46 ; B 35 0 714 692 ;
-C 84 ; WX 790 ; N a47 ; B 34 -14 756 705 ;
-C 85 ; WX 792 ; N a48 ; B 35 -14 758 705 ;
-C 86 ; WX 695 ; N a49 ; B 35 -14 661 706 ;
-C 87 ; WX 776 ; N a50 ; B 35 -6 741 699 ;
-C 88 ; WX 768 ; N a51 ; B 35 -7 734 699 ;
-C 89 ; WX 792 ; N a52 ; B 35 -14 757 705 ;
-C 90 ; WX 759 ; N a53 ; B 35 0 725 692 ;
-C 91 ; WX 707 ; N a54 ; B 35 -13 672 704 ;
-C 92 ; WX 708 ; N a55 ; B 35 -14 672 705 ;
-C 93 ; WX 682 ; N a56 ; B 35 -14 647 705 ;
-C 94 ; WX 701 ; N a57 ; B 35 -14 666 705 ;
-C 95 ; WX 826 ; N a58 ; B 35 -14 791 705 ;
-C 96 ; WX 815 ; N a59 ; B 35 -14 780 705 ;
-C 97 ; WX 789 ; N a60 ; B 35 -14 754 705 ;
-C 98 ; WX 789 ; N a61 ; B 35 -14 754 705 ;
-C 99 ; WX 707 ; N a62 ; B 34 -14 673 705 ;
-C 100 ; WX 687 ; N a63 ; B 36 0 651 692 ;
-C 101 ; WX 696 ; N a64 ; B 35 0 661 691 ;
-C 102 ; WX 689 ; N a65 ; B 35 0 655 692 ;
-C 103 ; WX 786 ; N a66 ; B 34 -14 751 705 ;
-C 104 ; WX 787 ; N a67 ; B 35 -14 752 705 ;
-C 105 ; WX 713 ; N a68 ; B 35 -14 678 705 ;
-C 106 ; WX 791 ; N a69 ; B 35 -14 756 705 ;
-C 107 ; WX 785 ; N a70 ; B 36 -14 751 705 ;
-C 108 ; WX 791 ; N a71 ; B 35 -14 757 705 ;
-C 109 ; WX 873 ; N a72 ; B 35 -14 838 705 ;
-C 110 ; WX 761 ; N a73 ; B 35 0 726 692 ;
-C 111 ; WX 762 ; N a74 ; B 35 0 727 692 ;
-C 112 ; WX 762 ; N a203 ; B 35 0 727 692 ;
-C 113 ; WX 759 ; N a75 ; B 35 0 725 692 ;
-C 114 ; WX 759 ; N a204 ; B 35 0 725 692 ;
-C 115 ; WX 892 ; N a76 ; B 35 0 858 705 ;
-C 116 ; WX 892 ; N a77 ; B 35 -14 858 692 ;
-C 117 ; WX 788 ; N a78 ; B 35 -14 754 705 ;
-C 118 ; WX 784 ; N a79 ; B 35 -14 749 705 ;
-C 119 ; WX 438 ; N a81 ; B 35 -14 403 705 ;
-C 120 ; WX 138 ; N a82 ; B 35 0 104 692 ;
-C 121 ; WX 277 ; N a83 ; B 35 0 242 692 ;
-C 122 ; WX 415 ; N a84 ; B 35 0 380 692 ;
-C 123 ; WX 392 ; N a97 ; B 35 263 357 705 ;
-C 124 ; WX 392 ; N a98 ; B 34 263 357 705 ;
-C 125 ; WX 668 ; N a99 ; B 35 263 633 705 ;
-C 126 ; WX 668 ; N a100 ; B 36 263 634 705 ;
-C 128 ; WX 390 ; N a89 ; B 35 -14 356 705 ;
-C 129 ; WX 390 ; N a90 ; B 35 -14 355 705 ;
-C 130 ; WX 317 ; N a93 ; B 35 0 283 692 ;
-C 131 ; WX 317 ; N a94 ; B 35 0 283 692 ;
-C 132 ; WX 276 ; N a91 ; B 35 0 242 692 ;
-C 133 ; WX 276 ; N a92 ; B 35 0 242 692 ;
-C 134 ; WX 509 ; N a205 ; B 35 0 475 692 ;
-C 135 ; WX 509 ; N a85 ; B 35 0 475 692 ;
-C 136 ; WX 410 ; N a206 ; B 35 0 375 692 ;
-C 137 ; WX 410 ; N a86 ; B 35 0 375 692 ;
-C 138 ; WX 234 ; N a87 ; B 35 -14 199 705 ;
-C 139 ; WX 234 ; N a88 ; B 35 -14 199 705 ;
-C 140 ; WX 334 ; N a95 ; B 35 0 299 692 ;
-C 141 ; WX 334 ; N a96 ; B 35 0 299 692 ;
-C 161 ; WX 732 ; N a101 ; B 35 -143 697 806 ;
-C 162 ; WX 544 ; N a102 ; B 56 -14 488 706 ;
-C 163 ; WX 544 ; N a103 ; B 34 -14 508 705 ;
-C 164 ; WX 910 ; N a104 ; B 35 40 875 651 ;
-C 165 ; WX 667 ; N a106 ; B 35 -14 633 705 ;
-C 166 ; WX 760 ; N a107 ; B 35 -14 726 705 ;
-C 167 ; WX 760 ; N a108 ; B 0 121 758 569 ;
-C 168 ; WX 776 ; N a112 ; B 35 0 741 705 ;
-C 169 ; WX 595 ; N a111 ; B 34 -14 560 705 ;
-C 170 ; WX 694 ; N a110 ; B 35 -14 659 705 ;
-C 171 ; WX 626 ; N a109 ; B 34 0 591 705 ;
-C 172 ; WX 788 ; N a120 ; B 35 -14 754 705 ;
-C 173 ; WX 788 ; N a121 ; B 35 -14 754 705 ;
-C 174 ; WX 788 ; N a122 ; B 35 -14 754 705 ;
-C 175 ; WX 788 ; N a123 ; B 35 -14 754 705 ;
-C 176 ; WX 788 ; N a124 ; B 35 -14 754 705 ;
-C 177 ; WX 788 ; N a125 ; B 35 -14 754 705 ;
-C 178 ; WX 788 ; N a126 ; B 35 -14 754 705 ;
-C 179 ; WX 788 ; N a127 ; B 35 -14 754 705 ;
-C 180 ; WX 788 ; N a128 ; B 35 -14 754 705 ;
-C 181 ; WX 788 ; N a129 ; B 35 -14 754 705 ;
-C 182 ; WX 788 ; N a130 ; B 35 -14 754 705 ;
-C 183 ; WX 788 ; N a131 ; B 35 -14 754 705 ;
-C 184 ; WX 788 ; N a132 ; B 35 -14 754 705 ;
-C 185 ; WX 788 ; N a133 ; B 35 -14 754 705 ;
-C 186 ; WX 788 ; N a134 ; B 35 -14 754 705 ;
-C 187 ; WX 788 ; N a135 ; B 35 -14 754 705 ;
-C 188 ; WX 788 ; N a136 ; B 35 -14 754 705 ;
-C 189 ; WX 788 ; N a137 ; B 35 -14 754 705 ;
-C 190 ; WX 788 ; N a138 ; B 35 -14 754 705 ;
-C 191 ; WX 788 ; N a139 ; B 35 -14 754 705 ;
-C 192 ; WX 788 ; N a140 ; B 35 -14 754 705 ;
-C 193 ; WX 788 ; N a141 ; B 35 -14 754 705 ;
-C 194 ; WX 788 ; N a142 ; B 35 -14 754 705 ;
-C 195 ; WX 788 ; N a143 ; B 35 -14 754 705 ;
-C 196 ; WX 788 ; N a144 ; B 35 -14 754 705 ;
-C 197 ; WX 788 ; N a145 ; B 35 -14 754 705 ;
-C 198 ; WX 788 ; N a146 ; B 35 -14 754 705 ;
-C 199 ; WX 788 ; N a147 ; B 35 -14 754 705 ;
-C 200 ; WX 788 ; N a148 ; B 35 -14 754 705 ;
-C 201 ; WX 788 ; N a149 ; B 35 -14 754 705 ;
-C 202 ; WX 788 ; N a150 ; B 35 -14 754 705 ;
-C 203 ; WX 788 ; N a151 ; B 35 -14 754 705 ;
-C 204 ; WX 788 ; N a152 ; B 35 -14 754 705 ;
-C 205 ; WX 788 ; N a153 ; B 35 -14 754 705 ;
-C 206 ; WX 788 ; N a154 ; B 35 -14 754 705 ;
-C 207 ; WX 788 ; N a155 ; B 35 -14 754 705 ;
-C 208 ; WX 788 ; N a156 ; B 35 -14 754 705 ;
-C 209 ; WX 788 ; N a157 ; B 35 -14 754 705 ;
-C 210 ; WX 788 ; N a158 ; B 35 -14 754 705 ;
-C 211 ; WX 788 ; N a159 ; B 35 -14 754 705 ;
-C 212 ; WX 894 ; N a160 ; B 35 58 860 634 ;
-C 213 ; WX 838 ; N a161 ; B 35 152 803 540 ;
-C 214 ; WX 1016 ; N a163 ; B 34 152 981 540 ;
-C 215 ; WX 458 ; N a164 ; B 35 -127 422 820 ;
-C 216 ; WX 748 ; N a196 ; B 35 94 698 597 ;
-C 217 ; WX 924 ; N a165 ; B 35 140 890 552 ;
-C 218 ; WX 748 ; N a192 ; B 35 94 698 597 ;
-C 219 ; WX 918 ; N a166 ; B 35 166 884 526 ;
-C 220 ; WX 927 ; N a167 ; B 35 32 892 660 ;
-C 221 ; WX 928 ; N a168 ; B 35 129 891 562 ;
-C 222 ; WX 928 ; N a169 ; B 35 128 893 563 ;
-C 223 ; WX 834 ; N a170 ; B 35 155 799 537 ;
-C 224 ; WX 873 ; N a171 ; B 35 93 838 599 ;
-C 225 ; WX 828 ; N a172 ; B 35 104 791 588 ;
-C 226 ; WX 924 ; N a173 ; B 35 98 889 594 ;
-C 227 ; WX 924 ; N a162 ; B 35 98 889 594 ;
-C 228 ; WX 917 ; N a174 ; B 35 0 882 692 ;
-C 229 ; WX 930 ; N a175 ; B 35 84 896 608 ;
-C 230 ; WX 931 ; N a176 ; B 35 84 896 608 ;
-C 231 ; WX 463 ; N a177 ; B 35 -99 429 791 ;
-C 232 ; WX 883 ; N a178 ; B 35 71 848 623 ;
-C 233 ; WX 836 ; N a179 ; B 35 44 802 648 ;
-C 234 ; WX 836 ; N a193 ; B 35 44 802 648 ;
-C 235 ; WX 867 ; N a180 ; B 35 101 832 591 ;
-C 236 ; WX 867 ; N a199 ; B 35 101 832 591 ;
-C 237 ; WX 696 ; N a181 ; B 35 44 661 648 ;
-C 238 ; WX 696 ; N a200 ; B 35 44 661 648 ;
-C 239 ; WX 874 ; N a182 ; B 35 77 840 619 ;
-C 241 ; WX 874 ; N a201 ; B 35 73 840 615 ;
-C 242 ; WX 760 ; N a183 ; B 35 0 725 692 ;
-C 243 ; WX 946 ; N a184 ; B 35 160 911 533 ;
-C 244 ; WX 771 ; N a197 ; B 34 37 736 655 ;
-C 245 ; WX 865 ; N a185 ; B 35 207 830 481 ;
-C 246 ; WX 771 ; N a194 ; B 34 37 736 655 ;
-C 247 ; WX 888 ; N a198 ; B 34 -19 853 712 ;
-C 248 ; WX 967 ; N a186 ; B 35 124 932 568 ;
-C 249 ; WX 888 ; N a195 ; B 34 -19 853 712 ;
-C 250 ; WX 831 ; N a187 ; B 35 113 796 579 ;
-C 251 ; WX 873 ; N a188 ; B 36 118 838 578 ;
-C 252 ; WX 927 ; N a189 ; B 35 150 891 542 ;
-C 253 ; WX 970 ; N a190 ; B 35 76 931 616 ;
-C 254 ; WX 918 ; N a191 ; B 34 99 884 593 ;
-EndCharMetrics
-EndFontMetrics
diff -Nru pdftk-1.45/java/com/lowagie/text/xml/xmp/DublinCoreSchema.java pdftk-2.01/java/com/lowagie/text/xml/xmp/DublinCoreSchema.java
--- pdftk-1.45/java/com/lowagie/text/xml/xmp/DublinCoreSchema.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/xml/xmp/DublinCoreSchema.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,193 +0,0 @@
-/*
- * $Id: DublinCoreSchema.java,v 1.5 2005/09/08 07:50:15 blowagie Exp $
- * $Name: $
- *
- * Copyright 2005 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.xml.xmp;
-
-import java.io.IOException;
-
-/**
- * An implementation of an XmpSchema.
- */
-public class DublinCoreSchema extends XmpSchema {
-
- /** default namespace identifier*/
- public static final String DEFAULT_XPATH_ID = "dc";
- /** default namespace uri*/
- public static final String DEFAULT_XPATH_URI = "http://purl.org/dc/elements/1.1/";
-
- /** External Contributors to the resource (other than the authors). */
- public static final String CONTRIBUTOR = "dc:contributor";
- /** The extent or scope of the resource. */
- public static final String COVERAGE = "dc:coverage";
- /** The authors of the resource (listed in order of precedence, if significant). */
- public static final String CREATOR = "dc:creator";
- /** Date(s) that something interesting happened to the resource. */
- public static final String DATE = "dc:date";
- /** A textual description of the content of the resource. Multiple values may be present for different languages. */
- public static final String DESCRIPTION = "dc:description";
- /** The file format used when saving the resource. Tools and applications should set this property to the save format of the data. It may include appropriate qualifiers. */
- public static final String FORMAT = "dc:format";
- /** Unique identifier of the resource. */
- public static final String IDENTIFIER = "dc:identifier";
- /** An unordered array specifying the languages used in the resource. */
- public static final String LANGUAGE = "dc:language";
- /** Publishers. */
- public static final String PUBLISHER = "dc:publisher";
- /** Relationships to other documents. */
- public static final String RELATION = "dc:relation";
- /** Informal rights statement, selected by language. */
- public static final String RIGHTS = "dc:rights";
- /** Unique identifier of the work from which this resource was derived. */
- public static final String SOURCE = "dc:source";
- /** An unordered array of descriptive phrases or keywords that specify the topic of the content of the resource. */
- public static final String SUBJECT = "dc:subject";
- /** The title of the document, or the name given to the resource. Typically, it will be a name by which the resource is formally known. */
- public static final String TITLE = "dc:title";
- /** A document type; for example, novel, poem, or working paper. */
- public static final String TYPE = "dc:type";
-
-
- /**
- * @throws IOException
- */
- public DublinCoreSchema() throws IOException {
- super("xmlns:" + DEFAULT_XPATH_ID + "=\"" + DEFAULT_XPATH_URI + "\"");
- setProperty(FORMAT, "application/pdf");
- }
-
- /**
- * Adds a title.
- * @param title
- */
- public void addTitle(String title) {
- setProperty(TITLE, title);
- }
-
- /**
- * Adds a description.
- * @param desc
- */
- public void addDescription(String desc) {
- setProperty(DESCRIPTION, desc);
- }
-
- /**
- * Adds a subject.
- * @param subject
- */
- public void addSubject(String subject) {
- XmpArray array = new XmpArray(XmpArray.UNORDERED);
- array.add(subject);
- setProperty(SUBJECT, array);
- }
-
-
- /**
- * Adds a subject.
- * @param subject array of subjects
- */
- public void addSubject(String[] subject) {
- XmpArray array = new XmpArray(XmpArray.UNORDERED);
- for (int i = 0; i < subject.length; i++) {
- array.add(subject[i]);
- }
- setProperty(SUBJECT, array);
- }
-
- /**
- * Adds a single author.
- * @param author
- */
- public void addAuthor(String author) {
- XmpArray array = new XmpArray(XmpArray.ORDERED);
- array.add(author);
- setProperty(CREATOR, array);
- }
-
- /**
- * Adds an array of authors.
- * @param author
- */
- public void addAuthor(String[] author) {
- XmpArray array = new XmpArray(XmpArray.ORDERED);
- for (int i = 0; i < author.length; i++) {
- array.add(author[i]);
- }
- setProperty(CREATOR, array);
- }
-
- /**
- * Adds a single publisher.
- * @param publisher
- */
- public void addPublisher(String publisher) {
- XmpArray array = new XmpArray(XmpArray.ORDERED);
- array.add(publisher);
- setProperty(PUBLISHER, array);
- }
-
- /**
- * Adds an array of publishers.
- * @param publisher
- */
- public void addPublisher(String[] publisher) {
- XmpArray array = new XmpArray(XmpArray.ORDERED);
- for (int i = 0; i < publisher.length; i++) {
- array.add(publisher[i]);
- }
- setProperty(PUBLISHER, array);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/xml/xmp/Makefile pdftk-2.01/java/com/lowagie/text/xml/xmp/Makefile
--- pdftk-1.45/java/com/lowagie/text/xml/xmp/Makefile 2010-09-15 09:43:42.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/xml/xmp/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-library= xmp.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-all : $(library) $(headers)
-
-$(library) : $(objects)
- $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/com/lowagie/text/xml/xmp/PdfSchema.java pdftk-2.01/java/com/lowagie/text/xml/xmp/PdfSchema.java
--- pdftk-1.45/java/com/lowagie/text/xml/xmp/PdfSchema.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/xml/xmp/PdfSchema.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,111 +0,0 @@
-/*
- * $Id: PdfSchema.java,v 1.4 2005/09/08 07:50:15 blowagie Exp $
- * $Name: $
- *
- * Copyright 2005 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.xml.xmp;
-
-import com.lowagie.text.Document;
-import java.io.IOException;
-
-/**
- * An implementation of an XmpSchema.
- */
-public class PdfSchema extends XmpSchema {
-
- /** default namespace identifier*/
- public static final String DEFAULT_XPATH_ID = "pdf";
- /** default namespace uri*/
- public static final String DEFAULT_XPATH_URI = "http://ns.adobe.com/pdf/1.3/";
-
- /** Keywords. */
- public static final String KEYWORDS = "pdf:Keywords";
- /** The PDF file version (for example: 1.0, 1.3, and so on). */
- public static final String VERSION = "pdf:PDFVersion";
- /** The Producer. */
- public static final String PRODUCER = "pdf:Producer";
-
-
- /**
- * @throws IOException
- */
- public PdfSchema() throws IOException {
- super("xmlns:" + DEFAULT_XPATH_ID + "=\"" + DEFAULT_XPATH_URI + "\"");
- addProducer(Document.getVersion());
- }
-
- /**
- * Adds keywords.
- * @param keywords
- */
- public void addKeywords(String keywords) {
- setProperty(KEYWORDS, keywords);
- }
-
- /**
- * Adds the producer.
- * @param producer
- */
- public void addProducer(String producer) {
- setProperty(PRODUCER, producer);
- }
-
- /**
- * Adds the version.
- * @param version
- */
- public void addVersion(String version) {
- setProperty(VERSION, version);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/xml/xmp/XmpArray.java pdftk-2.01/java/com/lowagie/text/xml/xmp/XmpArray.java
--- pdftk-1.45/java/com/lowagie/text/xml/xmp/XmpArray.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/xml/xmp/XmpArray.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,105 +0,0 @@
-/*
- * $Id: XmpArray.java,v 1.2 2005/09/03 12:50:41 blowagie Exp $
- * $Name: $
- *
- * Copyright 2005 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.xml.xmp;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * StringBuffer to construct an XMP array.
- */
-public class XmpArray extends ArrayList {
-
- /** An array that is unordered. */
- public static final String UNORDERED = "rdf:Bag";
- /** An array that is ordered. */
- public static final String ORDERED = "rdf:Seq";
- /** An array with alternatives. */
- public static final String ALTERNATIVE = "rdf:Alt";
-
- /** the type of array. */
- protected String type;
-
- /**
- * Creates an XmpArray.
- * @param type the type of array: UNORDERED, ORDERED or ALTERNATIVE.
- */
- public XmpArray(String type) {
- this.type = type;
- }
-
- /**
- * Returns the String representation of the XmpArray.
- * @return a String representation
- */
- public String toString() {
- StringBuffer buf = new StringBuffer("<");
- buf.append(type);
- buf.append(">");
- String s;
- for (Iterator i = iterator(); i.hasNext(); ) {
- s = (String) i.next();
- buf.append("");
- buf.append(XmpSchema.escape(s));
- buf.append(" ");
- }
- buf.append("");
- buf.append(type);
- buf.append(">");
- return buf.toString();
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/com/lowagie/text/xml/xmp/XmpBasicSchema.java pdftk-2.01/java/com/lowagie/text/xml/xmp/XmpBasicSchema.java
--- pdftk-1.45/java/com/lowagie/text/xml/xmp/XmpBasicSchema.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/xml/xmp/XmpBasicSchema.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,147 +0,0 @@
-/*
- * $Id: XmpBasicSchema.java,v 1.4 2005/09/08 07:50:15 blowagie Exp $
- * $Name: $
- *
- * Copyright 2005 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.xml.xmp;
-
-import java.io.IOException;
-
-/**
- * An implementation of an XmpSchema.
- */
-public class XmpBasicSchema extends XmpSchema {
-
- /** default namespace identifier*/
- public static final String DEFAULT_XPATH_ID = "xmp";
- /** default namespace uri*/
- public static final String DEFAULT_XPATH_URI = "http://ns.adobe.com/xap/1.0/";
-
- /** An unordered array specifying properties that were edited outside the authoring application. Each item should contain a single namespace and XPath separated by one ASCII space (U+0020). */
- public static final String ADVISORY = "xmp:Advisory";
- /** The base URL for relative URLs in the document content. If this document contains Internet links, and those links are relative, they are relative to this base URL. This property provides a standard way for embedded relative URLs to be interpreted by tools. Web authoring tools should set the value based on their notion of where URLs will be interpreted. */
- public static final String BASEURL = "xmp:BaseURL";
- /** The date and time the resource was originally created. */
- public static final String CREATEDATE = "xmp:CreateDate";
- /** The name of the first known tool used to create the resource. If history is present in the metadata, this value should be equivalent to that of xmpMM:History's softwareAgent property. */
- public static final String CREATORTOOL = "xmp:CreatorTool";
- /** An unordered array of text strings that unambiguously identify the resource within a given context. */
- public static final String IDENTIFIER = "xmp:Identifier";
- /** The date and time that any metadata for this resource was last changed. */
- public static final String METADATADATE = "xmp:MetadataDate";
- /** The date and time the resource was last modified. */
- public static final String MODIFYDATE = "xmp:ModifyDate";
- /** A short informal name for the resource. */
- public static final String NICKNAME = "xmp:Nickname";
- /** An alternative array of thumbnail images for a file, which can differ in characteristics such as size or image encoding. */
- public static final String THUMBNAILS = "xmp:Thumbnails";
-
-
- /**
- * @throws IOException
- */
- public XmpBasicSchema() throws IOException {
- super("xmlns:" + DEFAULT_XPATH_ID + "=\"" + DEFAULT_XPATH_URI + "\"");
- }
-
- /**
- * Adds the creatortool.
- * @param creator
- */
- public void addCreatorTool(String creator) {
- setProperty(CREATORTOOL, creator);
- }
-
- /**
- * Adds the creation date.
- * @param date
- */
- public void addCreateDate(String date) {
- setProperty(CREATEDATE, date);
- }
-
- /**
- * Adds the modification date.
- * @param date
- */
- public void addModDate(String date) {
- setProperty(MODIFYDATE, date);
- }
-
- /**
- * Adds the meta data date.
- * @param date
- */
- public void addMetaDataDate(String date) {
- setProperty(METADATADATE, date);
- }
-
- /** Adds the identifier.
- * @param id
- */
- public void addIdentifiers(String[] id) {
- XmpArray array = new XmpArray(XmpArray.UNORDERED);
- for (int i = 0; i < id.length; i++) {
- array.add(id[i]);
- }
- setProperty(IDENTIFIER, array);
- }
-
- /** Adds the nickname.
- * @param name
- */
- public void addNickname(String name) {
- setProperty(NICKNAME, name);
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/xml/xmp/XmpMMSchema.java pdftk-2.01/java/com/lowagie/text/xml/xmp/XmpMMSchema.java
--- pdftk-1.45/java/com/lowagie/text/xml/xmp/XmpMMSchema.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/xml/xmp/XmpMMSchema.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,103 +0,0 @@
-/*
- * $Id: XmpMMSchema.java,v 1.3 2005/09/08 07:50:15 blowagie Exp $
- * $Name: $
- *
- * Copyright 2005 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.xml.xmp;
-
-import java.io.IOException;
-
-/**
- * An implementation of an XmpSchema.
- */
-public class XmpMMSchema extends XmpSchema {
-
- /** default namespace identifier*/
- public static final String DEFAULT_XPATH_ID = "xmpMM";
- /** default namespace uri*/
- public static final String DEFAULT_XPATH_URI = "http://ns.adobe.com/xap/1.0/mm/";
-
-
- /** A reference to the original document from which this one is derived. It is a minimal reference; missing components can be assumed to be unchanged. For example, a new version might only need to specify the instance ID and version number of the previous version, or a rendition might only need to specify the instance ID and rendition class of the original. */
- public static final String DERIVEDFROM = "xmpMM:DerivedFrom";
- /** The common identifier for all versions and renditions of a document. */
- public static final String DOCUMENTID = "xmpMM:DocumentID";
- /** An ordered array of high-level user actions that resulted in this resource. It is intended to give human readers a general indication of the steps taken to make the changes from the previous version to this one. The list should be at an abstract level; it is not intended to be an exhaustive keystroke or other detailed history. */
- public static final String HISTORY = "xmpMM:History";
- /** A reference to the document as it was prior to becoming managed. It is set when a managed document is introduced to an asset management system that does not currently own it. It may or may not include references to different management systems. */
- public static final String MANAGEDFROM = "xmpMM:ManagedFrom";
- /** The name of the asset management system that manages this resource. */
- public static final String MANAGER = "xmpMM:Manager";
- /** A URI identifying the managed resource to the asset management system; the presence of this property is the formal indication that this resource is managed. The form and content of this URI is private to the asset management system. */
- public static final String MANAGETO = "xmpMM:ManageTo";
- /** A URI that can be used to access information about the managed resource through a web browser. It might require a custom browser plugin. */
- public static final String MANAGEUI = "xmpMM:ManageUI";
- /** Specifies a particular variant of the asset management system. The format of this property is private to the specific asset management system. */
- public static final String MANAGERVARIANT = "xmpMM:ManagerVariant";
- /** The rendition class name for this resource.*/
- public static final String RENDITIONCLASS = "xmpMM:RenditionClass";
- /** Can be used to provide additional rendition parameters that are too complex or verbose to encode in xmpMM: RenditionClass. */
- public static final String RENDITIONPARAMS = "xmpMM:RenditionParams";
- /** The document version identifier for this resource. */
- public static final String VERSIONID = "xmpMM:VersionID";
- /** The version history associated with this resource.*/
- public static final String VERSIONS = "xmpMM:Versions";
-
- /**
- * @throws IOException
- */
- public XmpMMSchema() throws IOException {
- super("xmlns:" + DEFAULT_XPATH_ID + "=\"" + DEFAULT_XPATH_URI + "\"");
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/xml/xmp/XmpSchema.java pdftk-2.01/java/com/lowagie/text/xml/xmp/XmpSchema.java
--- pdftk-1.45/java/com/lowagie/text/xml/xmp/XmpSchema.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/xml/xmp/XmpSchema.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,164 +0,0 @@
-/*
- * $Id: XmpSchema.java,v 1.5 2005/09/08 10:27:29 blowagie Exp $
- * $Name: $
- *
- * Copyright 2005 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.xml.xmp;
-
-import java.util.Enumeration;
-import java.util.Properties;
-
-/**
- * Abstract superclass of the XmpSchemas supported by iText.
- */
-public abstract class XmpSchema extends Properties {
-
- /** the namesspace */
- protected String xmlns;
-
- /** Constructs an XMP schema.
- * @param xmlns
- */
- public XmpSchema(String xmlns) {
- super();
- this.xmlns = xmlns;
- }
- /**
- * The String representation of the contents.
- * @return a String representation.
- */
- public String toString() {
- StringBuffer buf = new StringBuffer();
- for (Enumeration e = this.propertyNames(); e.hasMoreElements(); ) {
- process(buf, e.nextElement());
- }
- return buf.toString();
- }
- /**
- * Processes a property
- * @param buf
- * @param p
- */
- protected void process(StringBuffer buf, Object p) {
- buf.append("<");
- buf.append(p);
- buf.append(">");
- buf.append(this.get(p));
- buf.append("");
- buf.append(p);
- buf.append(">");
- }
- /**
- * @return Returns the xmlns.
- */
- public String getXmlns() {
- return xmlns;
- }
-
- /**
- * @param key
- * @param value
- * @return the previous property (null if there wasn't one)
- */
- public synchronized Object addProperty(String key, String value) {
- return this.setProperty(key, value);
- }
-
- /**
- * @see java.util.Properties#setProperty(java.lang.String, java.lang.String)
- */
- public synchronized Object setProperty(String key, String value) {
- return super.setProperty(key, escape(value));
- }
-
- /**
- * @see java.util.Properties#setProperty(java.lang.String, java.lang.String)
- *
- * @param key
- * @param value
- * @return the previous property (null if there wasn't one)
- */
- public synchronized Object setProperty(String key, XmpArray value) {
- return super.setProperty(key, value.toString());
- }
- /**
- * @param content
- * @return an escaped string
- */
- public static String escape(String content) {
- StringBuffer buf = new StringBuffer();
- for (int i = 0; i < content.length(); i++) {
- switch(content.charAt(i)) {
- case '<':
- buf.append("<");
- break;
- case '>':
- buf.append(">");
- break;
- case '\'':
- buf.append("'");
- break;
- case '\"':
- buf.append(""");
- break;
- case '&':
- buf.append("&");
- break;
- default:
- buf.append(content.charAt(i));
- }
- }
- return buf.toString();
- }
-}
diff -Nru pdftk-1.45/java/com/lowagie/text/xml/xmp/XmpWriter.java pdftk-2.01/java/com/lowagie/text/xml/xmp/XmpWriter.java
--- pdftk-1.45/java/com/lowagie/text/xml/xmp/XmpWriter.java 2012-12-06 14:06:22.000000000 +0000
+++ pdftk-2.01/java/com/lowagie/text/xml/xmp/XmpWriter.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,282 +0,0 @@
-/*
- * $Id: XmpWriter.java,v 1.7 2005/09/08 07:50:15 blowagie Exp $
- * $Name: $
- *
- * Copyright 2005 by Bruno Lowagie.
- *
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
- *
- * Contributor(s): all the names of the contributors are added in the source code
- * where applicable.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-
-package com.lowagie.text.xml.xmp;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.util.HashMap;
-import java.util.Iterator;
-
-import com.lowagie.text.pdf.PdfDate;
-import com.lowagie.text.pdf.PdfDictionary;
-import com.lowagie.text.pdf.PdfName;
-import com.lowagie.text.pdf.PdfObject;
-import com.lowagie.text.pdf.PdfString;
-
-/**
- * With this class you can create an Xmp Stream that can be used for adding
- * Metadata to a PDF Dictionary. Remark that this class doesn't cover the
- * complete XMP specification.
- */
-public class XmpWriter {
-
- /** A possible charset for the XMP. */
- public static final String UTF8 = "UTF-8";
- /** A possible charset for the XMP. */
- public static final String UTF16 = "UTF-16";
- /** A possible charset for the XMP. */
- public static final String UTF16BE = "UTF-16BE";
- /** A possible charset for the XMP. */
- public static final String UTF16LE = "UTF-16LE";
-
- /** String used to fill the extra space. */
- public static final String EXTRASPACE = " \n";
-
- /** You can add some extra space in the XMP packet; 1 unit in this variable represents 100 spaces and a newline. */
- protected int extraSpace;
-
- /** The writer to which you can write bytes for the XMP stream. */
- protected OutputStreamWriter writer;
-
- /** The about string that goes into the rdf:Description tags. */
- protected String about;
-
- /** The end attribute. */
- protected char end = 'w';
-
- /**
- * Creates an XmpWriter.
- * @param os
- * @param utfEncoding
- * @param extraSpace
- * @throws IOException
- */
- public XmpWriter(OutputStream os, String utfEncoding, int extraSpace) throws IOException {
- this.extraSpace = extraSpace;
- writer = new OutputStreamWriter(os, utfEncoding);
- writer.write("\n");
- writer.write("\n");
- writer.write("\n");
- about = "";
- }
-
- /**
- * Creates an XmpWriter.
- * @param os
- * @throws IOException
- */
- public XmpWriter(OutputStream os) throws IOException {
- this(os, UTF8, 20);
- }
-
- /** Sets the XMP to read-only */
- public void setReadOnly() {
- end = 'r';
- }
-
- /**
- * @param about The about to set.
- */
- public void setAbout(String about) {
- this.about = about;
- }
-
- /**
- * Adds an rdf:Description.
- * @param xmlns
- * @param content
- * @throws IOException
- */
- public void addRdfDescription(String xmlns, String content) throws IOException {
- writer.write("");
- writer.write(content);
- writer.write(" \n");
- }
-
- /**
- * Adds an rdf:Description.
- * @param s
- * @throws IOException
- */
- public void addRdfDescription(XmpSchema s) throws IOException {
- writer.write("");
- writer.write(s.toString());
- writer.write(" \n");
- }
-
- /**
- * Flushes and closes the XmpWriter.
- * @throws IOException
- */
- public void close() throws IOException {
- writer.write(" ");
- writer.write(" \n");
- for (int i = 0; i < extraSpace; i++) {
- writer.write(EXTRASPACE);
- }
- writer.write("");
- writer.flush();
- writer.close();
- }
-
- /**
- * @param os
- * @param info
- * @throws IOException
- */
- public XmpWriter(OutputStream os, PdfDictionary info) throws IOException {
- this(os);
- if (info != null) {
- DublinCoreSchema dc = new DublinCoreSchema();
- PdfSchema p = new PdfSchema();
- XmpBasicSchema basic = new XmpBasicSchema();
- PdfName key;
- PdfObject obj;
- for (Iterator it = info.getKeys().iterator(); it.hasNext();) {
- key = (PdfName)it.next();
- obj = info.get(key);
- if (obj == null)
- continue;
- if (PdfName.TITLE.equals(key)) {
- dc.addTitle(((PdfString)obj).toUnicodeString());
- }
- if (PdfName.AUTHOR.equals(key)) {
- dc.addAuthor(((PdfString)obj).toUnicodeString());
- }
- if (PdfName.SUBJECT.equals(key)) {
- dc.addSubject(((PdfString)obj).toUnicodeString());
- }
- if (PdfName.KEYWORDS.equals(key)) {
- p.addKeywords(((PdfString)obj).toUnicodeString());
- }
- if (PdfName.CREATOR.equals(key)) {
- basic.addCreatorTool(((PdfString)obj).toUnicodeString());
- }
- if (PdfName.PRODUCER.equals(key)) {
- p.addProducer(((PdfString)obj).toUnicodeString());
- }
- if (PdfName.CREATIONDATE.equals(key)) {
- basic.addCreateDate(((PdfDate)obj).getW3CDate());
- }
- if (PdfName.MODDATE.equals(key)) {
- basic.addModDate(((PdfDate)obj).getW3CDate());
- }
- }
- if (dc.size() > 0) addRdfDescription(dc);
- if (p.size() > 0) addRdfDescription(p);
- if (basic.size() > 0) addRdfDescription(basic);
- }
- }
-
- /**
- * @param os
- * @param info
- * @throws IOException
- */
- public XmpWriter(OutputStream os, HashMap info) throws IOException {
- this(os);
- if (info != null) {
- DublinCoreSchema dc = new DublinCoreSchema();
- PdfSchema p = new PdfSchema();
- XmpBasicSchema basic = new XmpBasicSchema();
- String key;
- String value;
- for (Iterator it = info.keySet().iterator(); it.hasNext();) {
- key = (String)it.next();
- value = (String)info.get(key);
- if (value == null)
- continue;
- if ("Title".equals(key)) {
- dc.addTitle(value);
- }
- if ("Author".equals(key)) {
- dc.addAuthor(value);
- }
- if ("Subject".equals(key)) {
- dc.addSubject(value);
- }
- if ("Keywords".equals(key)) {
- p.addKeywords(value);
- }
- if ("Creator".equals(key)) {
- basic.addCreatorTool(value);
- }
- if ("Producer".equals(key)) {
- p.addProducer(value);
- }
- if ("CreationDate".equals(key)) {
- basic.addCreateDate(PdfDate.getW3CDate(value));
- }
- if ("ModDate".equals(key)) {
- basic.addModDate(PdfDate.getW3CDate(value));
- }
- }
- if (dc.size() > 0) addRdfDescription(dc);
- if (p.size() > 0) addRdfDescription(p);
- if (basic.size() > 0) addRdfDescription(basic);
- }
- }
-}
\ No newline at end of file
diff -Nru pdftk-1.45/java/gnu_local/java/security/Engine.java pdftk-2.01/java/gnu_local/java/security/Engine.java
--- pdftk-1.45/java/gnu_local/java/security/Engine.java 2004-05-26 16:08:10.000000000 +0000
+++ pdftk-2.01/java/gnu_local/java/security/Engine.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,237 +0,0 @@
-/* Engine -- generic getInstance method.
- Copyright (C) 2003 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package gnu_local.java.security;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
-import java_local.security.NoSuchAlgorithmException;
-import java_local.security.Provider;
-
-/**
- * Generic implementation of the getInstance methods in the various
- * engine classes in java.security.
- *
- * These classes ({@link java.security.Signature} for example) can be
- * thought of as the "chrome, upholstery, and steering wheel", and the SPI
- * (service provider interface, e.g. {@link java.security.SignatureSpi})
- * classes can be thought of as the "engine" -- providing the actual
- * functionality of whatever cryptographic algorithm the instance
- * represents.
- *
- * @see Provider
- * @author Casey Marshall
- */
-public final class Engine
-{
-
- // Constants.
- // ------------------------------------------------------------------------
-
- /** Prefix for aliases. */
- private static final String ALG_ALIAS = "Alg.Alias.";
-
- /** Maximum number of aliases to try. */
- private static final int MAX_ALIASES = 5;
-
- /** Argument list for no-argument constructors. */
- private static final Object[] NO_ARGS = new Object[0];
-
- // Constructor.
- // ------------------------------------------------------------------------
-
- /** This class cannot be instantiated. */
- private Engine() { }
-
- // Class method.
- // ------------------------------------------------------------------------
-
- /**
- * Get the implementation for algorithm for service
- * service from provider . The service is e.g.
- * "Signature", and the algorithm "DSA".
- *
- * @param service The service name.
- * @param algorithm The name of the algorithm to get.
- * @param provider The provider to get the implementation from.
- * @return The engine class for the specified algorithm; the object
- * returned is typically a subclass of the SPI class for that
- * service, but callers should check that this is so.
- * @throws NoSuchAlgorithmException If the implementation cannot be
- * found or cannot be instantiated.
- * @throws InvocationTargetException If the SPI class's constructor
- * throws an exception.
- * @throws IllegalArgumentException If any of the three arguments are null.
- */
- public static Object getInstance(String service, String algorithm,
- Provider provider)
- throws InvocationTargetException, NoSuchAlgorithmException
- {
- return getInstance(service, algorithm, provider, NO_ARGS);
- }
-
- /**
- * Get the implementation for algorithm for service
- * service from provider , passing initArgs to the
- * SPI class's constructor (which cannot be null; pass a zero-length
- * array if the SPI takes no arguments). The service is e.g.
- * "Signature", and the algorithm "DSA".
- *
- * @param service The service name.
- * @param algorithm The name of the algorithm to get.
- * @param provider The provider to get the implementation from.
- * @param initArgs The arguments to pass to the SPI class's
- * constructor (cannot be null).
- * @return The engine class for the specified algorithm; the object
- * returned is typically a subclass of the SPI class for that
- * service, but callers should check that this is so.
- * @throws NoSuchAlgorithmException If the implementation cannot be
- * found or cannot be instantiated.
- * @throws InvocationTargetException If the SPI class's constructor
- * throws an exception.
- * @throws IllegalArgumentException If any of the four arguments are null.
- */
- public static Object getInstance(String service, String algorithm,
- Provider provider, Object[] initArgs)
- throws InvocationTargetException, NoSuchAlgorithmException
- {
- if (service == null || algorithm == null
- || provider == null || initArgs == null)
- throw new IllegalArgumentException();
-
- // If there is no property "service.algorithm"
- if (provider.getProperty(service + "." + algorithm) == null)
- {
- // Iterate through aliases, until we find the class name or resolve
- // too many aliases.
- String alias = null;
- int count = 0;
- while ((alias = provider.getProperty(
- ALG_ALIAS + service + "." + algorithm)) != null)
- {
- if (algorithm.equals(alias)) // Refers to itself!
- break;
- algorithm = alias;
- if (count++ > MAX_ALIASES)
- throw new NoSuchAlgorithmException("too many aliases");
- }
- if (provider.getProperty(service + "." + algorithm) == null)
- throw new NoSuchAlgorithmException(algorithm);
- }
-
- // Find and instantiate the implementation.
- Class clazz = null;
- ClassLoader loader = provider.getClass().getClassLoader();
- Constructor constructor = null;
- String error = algorithm;
-
- try
- {
- if (loader != null)
- clazz = loader.loadClass(provider.getProperty(service+"."+algorithm));
- else
- clazz = Class.forName(provider.getProperty(service+"."+algorithm));
- constructor = getCompatibleConstructor(clazz, initArgs);
- return constructor.newInstance(initArgs);
- }
- catch (ClassNotFoundException cnfe)
- {
- error = "class not found: " + algorithm;
- }
- catch (IllegalAccessException iae)
- {
- error = "illegal access: " + iae.getMessage();
- }
- catch (InstantiationException ie)
- {
- error = "instantiation exception: " + ie.getMessage();
- }
- catch (ExceptionInInitializerError eiie)
- {
- error = "exception in initializer: " + eiie.getMessage();
- }
- catch (SecurityException se)
- {
- error = "security exception: " + se.getMessage();
- }
- catch (NoSuchMethodException nsme)
- {
- error = "no appropriate constructor found";
- }
-
- throw new NoSuchAlgorithmException(error);
- }
-
- // Own methods.
- // ------------------------------------------------------------------------
-
- /**
- * Find a constructor in the given class that can take the specified
- * argument list, allowing any of which to be null.
- *
- * @param clazz The class from which to get the constructor.
- * @param initArgs The argument list to be passed to the constructor.
- * @return The constructor.
- * @throws NoSuchMethodException If no constructor of the given class
- * can take the specified argument array.
- */
- private static Constructor getCompatibleConstructor(Class clazz,
- Object[] initArgs)
- throws NoSuchMethodException
- {
- Constructor[] c = clazz.getConstructors();
- outer:for (int i = 0; i < c.length; i++)
- {
- Class[] argTypes = c[i].getParameterTypes();
- if (argTypes.length != initArgs.length)
- continue;
- for (int j = 0; j < argTypes.length; j++)
- {
- if (initArgs[j] != null &&
- !argTypes[j].isAssignableFrom(initArgs[j].getClass()))
- continue outer;
- }
- // If we reach this point, we know this constructor (c[i]) has
- // the same number of parameters as the target parameter list,
- // and all our parameters are either (1) null, or (2) assignable
- // to the target parameter type.
- return c[i];
- }
- throw new NoSuchMethodException();
- }
-}
diff -Nru pdftk-1.45/java/gnu_local/java/security/Makefile pdftk-2.01/java/gnu_local/java/security/Makefile
--- pdftk-1.45/java/gnu_local/java/security/Makefile 2010-09-15 09:41:14.000000000 +0000
+++ pdftk-2.01/java/gnu_local/java/security/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-library= security.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-all : $(library) $(headers)
-
-$(library) : $(objects)
- $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/gnu_local/java/security/provider/Gnu.java pdftk-2.01/java/gnu_local/java/security/provider/Gnu.java
--- pdftk-1.45/java/gnu_local/java/security/provider/Gnu.java 2004-05-26 16:08:10.000000000 +0000
+++ pdftk-2.01/java/gnu_local/java/security/provider/Gnu.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,117 +0,0 @@
-/* Gnu.java --- Gnu provider main class
- Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu_local.java.security.provider;
-import java_local.security.Provider;
-
-public final class Gnu extends Provider
-{
- public Gnu()
- {
- super("GNU", 1.0, "GNU provider v1.0 implementing SHA-1, MD5, DSA, X.509 Certificates");
-
- // Note that all implementation class names are referenced by using
- // Class.getName(). That way when we staticly link the Gnu provider
- // we automatically get all the implementation classes.
-
- /* SID: we simply want the MD5 algorithm (for pdftk)
-
- // Signature
- put("Signature.SHA1withDSA",
- gnu_local.java.security.provider.DSASignature.class.getName());
-
- put("Alg.Alias.Signature.DSS", "SHA1withDSA");
- put("Alg.Alias.Signature.DSA", "SHA1withDSA");
- put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA");
- put("Alg.Alias.Signature.DSAwithSHA", "SHA1withDSA");
- put("Alg.Alias.Signature.DSAwithSHA1", "SHA1withDSA");
- put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA");
- put("Alg.Alias.Signature.SHA-1/DSA", "SHA1withDSA");
- put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA");
- put("Alg.Alias.Signature.OID.1.2.840.10040.4.3", "SHA1withDSA");
- put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA");
- put("Alg.Alias.Signature.1.3.14.3.2.13", "SHA1withDSA");
- put("Alg.Alias.Signature.1.3.14.3.2.27", "SHA1withDSA");
-
- // Key Pair Generator
- put("KeyPairGenerator.DSA",
- gnu_local.java.security.provider.DSAKeyPairGenerator.class.getName());
-
- put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1", "DSA");
- put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA");
- put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA");
-
- // Key Factory
- put("KeyFactory.DSA",
- gnu_local.java.security.provider.DSAKeyFactory.class.getName());
-
- put("Alg.Alias.KeyFactory.OID.1.2.840.10040.4.1", "DSA");
- put("Alg.Alias.KeyFactory.1.2.840.10040.4.1", "DSA");
- put("Alg.Alias.KeyFactory.1.3.14.3.2.12", "DSA");
-
- // Message Digests
- put("MessageDigest.SHA", gnu_local.java.security.provider.SHA.class.getName());
- */
-
- put("MessageDigest.MD5", gnu_local.java.security.provider.MD5.class.getName());
-
- /*
- // Format "Alias", "Actual Name"
- put("Alg.Alias.MessageDigest.SHA1", "SHA");
- put("Alg.Alias.MessageDigest.SHA-1", "SHA");
-
- // Algorithm Parameters
- put("AlgorithmParameters.DSA",
- gnu_local.java.security.provider.DSAParameters.class.getName());
-
- // Algorithm Parameter Generator
- put("AlgorithmParameterGenerator.DSA",
- gnu_local.java.security.provider.DSAParameterGenerator.class.getName());
-
- // SecureRandom
- put("SecureRandom.SHA1PRNG",
- gnu_local.java.security.provider.SHA1PRNG.class.getName());
-
- // CertificateFactory
- put("CertificateFactory.X.509",
- gnu_local.java.security.provider.X509CertificateFactory.class.getName());
-
- put("Alg.Alias.CertificateFactory.X509", "X.509");
- */
- }
-}
diff -Nru pdftk-1.45/java/gnu_local/java/security/provider/MD5.java pdftk-2.01/java/gnu_local/java/security/provider/MD5.java
--- pdftk-1.45/java/gnu_local/java/security/provider/MD5.java 2004-05-26 16:08:10.000000000 +0000
+++ pdftk-2.01/java/gnu_local/java/security/provider/MD5.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,338 +0,0 @@
-/* MD5.java -- Class implementing the MD5 algorithm as specified in RFC1321.
- Copyright (C) 1999, 2002 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu_local.java.security.provider;
-import java_local.security.MessageDigest;
-
-/**
- This class implements the MD5 algorithm as described in RFC1321.
-
- @see java.security.MessageDigest
-*/
-public class MD5 extends MessageDigest implements Cloneable
-{
- private final int W[] = new int[16];
- private long bytecount;
- private int A;
- private int B;
- private int C;
- private int D;
-
- public MD5()
- {
- super("MD5");
- engineReset ();
- }
-
- public Object clone()
- {
- return new MD5 (this);
- }
-
- private MD5 (MD5 copy)
- {
- this ();
- bytecount = copy.bytecount;
- A = copy.A;
- B = copy.B;
- C = copy.C;
- D = copy.D;
- System.arraycopy (copy.W, 0, W, 0, 16);
- }
-
- public int engineGetDigestLength()
- {
- return 16;
- }
-
- // Intialize the A,B,C,D needed for the hash
- public void engineReset()
- {
- bytecount = 0;
- A = 0x67452301;
- B = 0xefcdab89;
- C = 0x98badcfe;
- D = 0x10325476;
- for(int i = 0; i < 16; i++)
- W[i] = 0;
- }
-
- public void engineUpdate (byte b)
- {
- int i = (int)bytecount % 64;
- int shift = (3 - i % 4) * 8;
- int idx = i / 4;
-
- // if you could index ints, this would be: W[idx][shift/8] = b
- W[idx] = (W[idx] & ~(0xff << shift)) | ((b & 0xff) << shift);
-
- // if we've filled up a block, then process it
- if ((++ bytecount) % 64 == 0)
- munch ();
- }
-
- public void engineUpdate (byte bytes[], int off, int len)
- {
- if (len < 0)
- throw new ArrayIndexOutOfBoundsException ();
-
- int end = off + len;
- while (off < end)
- engineUpdate (bytes[off++]);
- }
-
- public byte[] engineDigest()
- {
- long bitcount = bytecount * 8;
- engineUpdate ((byte)0x80); // 10000000 in binary; the start of the padding
-
- // add the rest of the padding to fill this block out, but leave 8
- // bytes to put in the original bytecount
- while ((int)bytecount % 64 != 56)
- engineUpdate ((byte)0);
-
- // add the length of the original, unpadded block to the end of
- // the padding
- W[14] = SWAP((int)(0xffffffff & bitcount));
- W[15] = SWAP((int)(0xffffffff & (bitcount >>> 32)));
- bytecount += 8;
-
- // digest the fully padded block
- munch ();
-
- A = SWAP(A);
- B = SWAP(B);
- C = SWAP(C);
- D = SWAP(D);
- byte[] result = new byte[] {(byte)(A >>> 24), (byte)(A >>> 16),
- (byte)(A >>> 8), (byte)A,
- (byte)(B >>> 24), (byte)(B >>> 16),
- (byte)(B >>> 8), (byte)B,
- (byte)(C >>> 24), (byte)(C >>> 16),
- (byte)(C >>> 8), (byte)C,
- (byte)(D >>> 24), (byte)(D >>> 16),
- (byte)(D >>> 8), (byte)D};
-
- engineReset ();
- return result;
- }
-
- private int F( int X, int Y, int Z)
- {
- return ((X & Y) | (~X & Z));
- }
-
- private int G( int X, int Y, int Z)
- {
- return ((X & Z) | (Y & ~Z));
- }
-
- private int H( int X, int Y, int Z)
- {
- return (X ^ Y ^ Z);
- }
-
- private int I( int X, int Y, int Z)
- {
- return (Y ^ (X | ~Z));
- }
-
- private int rotateLeft( int i, int count)
- {
- //Taken from FIPS 180-1
- return ( (i << count) | (i >>> (32 - count)) ) ;
- }
-
- /* Round 1. */
- private int FF( int a, int b, int c, int d, int k, int s, int i)
- {
- /* Let [abcd k s i] denote the operation */
- a += F(b,c,d) + k + i;
- return b + rotateLeft(a, s);
- }
- /* Round 2. */
- private int GG( int a, int b, int c, int d, int k, int s, int i)
- {
- /* Let [abcd k s i] denote the operation */
- a += G(b,c,d) + k + i;
- return b + rotateLeft(a, s);
- }
- /* Round 3. */
- private int HH( int a, int b, int c, int d, int k, int s, int i)
- {
- /* Let [abcd k s t] denote the operation */
- a += H(b,c,d) + k + i;
- return b + rotateLeft(a, s);
- }
-
- /* Round 4. */
- private int II( int a, int b, int c, int d, int k, int s, int i)
- {
- /* Let [abcd k s t] denote the operation */
- a += I(b,c,d) + k + i;
- return b + rotateLeft(a, s);
- }
-
- private int SWAP(int n)
- {
- //Copied from md5.c in FSF Gnu Privacy Guard 0.9.2
- return (( (0xff & n) << 24) | ((n & 0xff00) << 8) | ((n >>> 8) & 0xff00) | (n >>> 24));
- }
-
- private void munch()
- {
- int AA,BB,CC,DD, j;
- int X[] = new int[16];
-
- /* Copy block i into X. */
- for(j = 0; j < 16; j++)
- X[j] = SWAP(W[j]);
-
- /* Save A as AA, B as BB, C as CC, and D as DD. */
- AA = A;
- BB = B;
- CC = C;
- DD = D;
-
- /* The hex constants are from md5.c
- in FSF Gnu Privacy Guard 0.9.2 */
- /* Round 1. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
- /* Do the following 16 operations. */
- A = FF(A,B,C,D, X[0], 7, 0xd76aa478);
- D = FF(D,A,B,C, X[1], 12, 0xe8c7b756);
- C = FF(C,D,A,B, X[2], 17, 0x242070db);
- B = FF(B,C,D,A, X[3], 22, 0xc1bdceee);
-
- A = FF(A,B,C,D, X[4], 7, 0xf57c0faf);
- D = FF(D,A,B,C, X[5], 12, 0x4787c62a);
- C = FF(C,D,A,B, X[6], 17, 0xa8304613);
- B = FF(B,C,D,A, X[7], 22, 0xfd469501);
-
- A = FF(A,B,C,D, X[8], 7, 0x698098d8);
- D = FF(D,A,B,C, X[9], 12, 0x8b44f7af);
- C = FF(C,D,A,B, X[10], 17, 0xffff5bb1);
- B = FF(B,C,D,A, X[11], 22, 0x895cd7be);
-
- A = FF(A,B,C,D, X[12], 7, 0x6b901122);
- D = FF(D,A,B,C, X[13], 12, 0xfd987193);
- C = FF(C,D,A,B, X[14], 17, 0xa679438e);
- B = FF(B,C,D,A, X[15], 22, 0x49b40821);
-
- /* Round 2. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
- /* Do the following 16 operations. */
- A = GG(A,B,C,D, X[1], 5, 0xf61e2562);
- D = GG(D,A,B,C, X[6], 9, 0xc040b340);
- C = GG(C,D,A,B, X[11], 14, 0x265e5a51);
- B = GG(B,C,D,A, X[0], 20, 0xe9b6c7aa);
-
- A = GG(A,B,C,D, X[5], 5, 0xd62f105d);
- D = GG(D,A,B,C, X[10], 9, 0x02441453);
- C = GG(C,D,A,B, X[15], 14, 0xd8a1e681);
- B = GG(B,C,D,A, X[4], 20, 0xe7d3fbc8);
-
- A = GG(A,B,C,D, X[9], 5, 0x21e1cde6);
- D = GG(D,A,B,C, X[14], 9, 0xc33707d6);
- C = GG(C,D,A,B, X[3], 14, 0xf4d50d87);
- B = GG(B,C,D,A, X[8], 20, 0x455a14ed);
-
- A = GG(A,B,C,D, X[13], 5, 0xa9e3e905);
- D = GG(D,A,B,C, X[2], 9, 0xfcefa3f8);
- C = GG(C,D,A,B, X[7], 14, 0x676f02d9);
- B = GG(B,C,D,A, X[12], 20, 0x8d2a4c8a);
-
- /* Round 3. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
- /* Do the following 16 operations. */
- A = HH(A,B,C,D, X[5], 4, 0xfffa3942);
- D = HH(D,A,B,C, X[8], 11, 0x8771f681);
- C = HH(C,D,A,B, X[11], 16, 0x6d9d6122);
- B = HH(B,C,D,A, X[14], 23, 0xfde5380c);
-
- A = HH(A,B,C,D, X[1], 4, 0xa4beea44);
- D = HH(D,A,B,C, X[4], 11, 0x4bdecfa9);
- C = HH(C,D,A,B, X[7], 16, 0xf6bb4b60);
- B = HH(B,C,D,A, X[10], 23, 0xbebfbc70);
-
- A = HH(A,B,C,D, X[13], 4, 0x289b7ec6);
- D = HH(D,A,B,C, X[0], 11, 0xeaa127fa);
- C = HH(C,D,A,B, X[3], 16, 0xd4ef3085);
- B = HH(B,C,D,A, X[6], 23, 0x04881d05);
-
- A = HH(A,B,C,D, X[9], 4, 0xd9d4d039);
- D = HH(D,A,B,C, X[12], 11, 0xe6db99e5);
- C = HH(C,D,A,B, X[15], 16, 0x1fa27cf8);
- B = HH(B,C,D,A, X[2], 23, 0xc4ac5665);
-
- /* Round 4. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
- /* Do the following 16 operations. */
- A = II(A,B,C,D, X[0], 6, 0xf4292244);
- D = II(D,A,B,C, X[7], 10, 0x432aff97);
- C = II(C,D,A,B, X[14], 15, 0xab9423a7);
- B = II(B,C,D,A, X[5], 21, 0xfc93a039);
-
- A = II(A,B,C,D, X[12], 6, 0x655b59c3);
- D = II(D,A,B,C, X[3], 10, 0x8f0ccc92);
- C = II(C,D,A,B, X[10], 15, 0xffeff47d);
- B = II(B,C,D,A, X[1], 21, 0x85845dd1);
-
- A = II(A,B,C,D, X[8], 6, 0x6fa87e4f);
- D = II(D,A,B,C, X[15], 10, 0xfe2ce6e0);
- C = II(C,D,A,B, X[6], 15, 0xa3014314);
- B = II(B,C,D,A, X[13], 21, 0x4e0811a1);
-
- A = II(A,B,C,D, X[4], 6, 0xf7537e82);
- D = II(D,A,B,C, X[11], 10, 0xbd3af235);
- C = II(C,D,A,B, X[2], 15, 0x2ad7d2bb);
- B = II(B,C,D,A, X[9], 21, 0xeb86d391);
-
- /* Then perform the following additions. (That is increment each
- of the four registers by the value it had before this block
- was started.) */
- A = A + AA;
- B = B + BB;
- C = C + CC;
- D = D + DD;
- }
-}
diff -Nru pdftk-1.45/java/gnu_local/java/security/provider/Makefile pdftk-2.01/java/gnu_local/java/security/provider/Makefile
--- pdftk-1.45/java/gnu_local/java/security/provider/Makefile 2010-09-15 09:41:22.000000000 +0000
+++ pdftk-2.01/java/gnu_local/java/security/provider/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-library= provider.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-all : $(library) $(headers)
-
-$(library) : $(objects)
- $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/java/security/Security.java pdftk-2.01/java/java/security/Security.java
--- pdftk-1.45/java/java/security/Security.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/java/security/Security.java 2013-06-05 11:20:54.000000000 +0000
@@ -0,0 +1,735 @@
+/* Security.java --- Java base security class implementation
+ Copyright (C) 1999, 2001, 2002, 2003, Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.security;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.security.Provider;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+
+/**
+ * This class centralizes all security properties and common security methods.
+ * One of its primary uses is to manage providers.
+ *
+ * @author Mark Benvenuto
+ */
+public final class Security extends Object
+{
+ private static final String ALG_ALIAS = "Alg.Alias.";
+
+ private static Vector providers = new Vector();
+ private static Properties secprops = new Properties();
+
+ static
+ {
+ /* ssteward
+ String base = System.getProperty ("gnu.classpath.home.url");
+ String vendor = System.getProperty ("gnu.classpath.vm.shortname");
+
+ // Try VM specific security file
+ boolean loaded = loadProviders (base, vendor);
+
+ // Append classpath standard provider if possible
+ if (!loadProviders (base, "classpath")
+ && !loaded
+ && providers.size() == 0)
+ {
+ // No providers found and both security files failed to load properly.
+ System.err.println
+ ("WARNING: could not properly read security provider files:");
+ System.err.println
+ (" " + base + "/security/" + vendor + ".security");
+ System.err.println
+ (" " + base + "/security/" + "classpath" + ".security");
+ System.err.println
+ (" Falling back to standard GNU security provider");
+ providers.addElement (new gnu.java.security.provider.Gnu());
+ }
+ */
+
+ // ssteward: copied from above
+ providers.addElement (new gnu.java.security.provider.Gnu());
+ }
+
+ // This class can't be instantiated.
+ private Security()
+ {
+ }
+
+ /**
+ * Tries to load the vender specific security providers from the given
+ * base URL. Returns true if the resource could be read and completely
+ * parsed successfully, false otherwise.
+ */
+ private static boolean loadProviders(String baseUrl, String vendor)
+ {
+ if (baseUrl == null || vendor == null)
+ return false;
+
+ boolean result = true;
+ String secfilestr = baseUrl + "/security/" + vendor + ".security";
+ try
+ {
+ InputStream fin = new URL(secfilestr).openStream();
+ secprops.load(fin);
+
+ int i = 1;
+ String name;
+ while ((name = secprops.getProperty("security.provider." + i)) != null)
+ {
+ Exception exception = null;
+ try
+ {
+ providers.addElement(Class.forName(name).newInstance());
+ }
+ catch (ClassNotFoundException x)
+ {
+ exception = x;
+ }
+ catch (InstantiationException x)
+ {
+ exception = x;
+ }
+ catch (IllegalAccessException x)
+ {
+ exception = x;
+ }
+
+ if (exception != null)
+ {
+ System.err.println ("WARNING: Error loading security provider "
+ + name + ": " + exception);
+ result = false;
+ }
+ i++;
+ }
+ }
+ catch (IOException ignored)
+ {
+ result = false;
+ }
+
+ return false;
+ }
+
+ /**
+ * Gets a specified property for an algorithm. The algorithm name should be a
+ * standard name. See Appendix A in the Java Cryptography Architecture API
+ * Specification & Reference for information about standard algorithm
+ * names. One possible use is by specialized algorithm parsers, which may map
+ * classes to algorithms which they understand (much like {@link Key} parsers
+ * do).
+ *
+ * @param algName the algorithm name.
+ * @param propName the name of the property to get.
+ * @return the value of the specified property.
+ * @deprecated This method used to return the value of a proprietary property
+ * in the master file of the "SUN" Cryptographic Service Provider in order to
+ * determine how to parse algorithm-specific parameters. Use the new
+ * provider-based and algorithm-independent {@link AlgorithmParameters} and
+ * {@link KeyFactory} engine classes (introduced in the Java 2 platform)
+ * instead.
+ */
+ public static String getAlgorithmProperty(String algName, String propName)
+ {
+ if (algName == null || propName == null)
+ return null;
+
+ String property = String.valueOf(propName) + "." + String.valueOf(algName);
+ Provider p;
+ for (Iterator i = providers.iterator(); i.hasNext(); )
+ {
+ p = (Provider) i.next();
+ for (Iterator j = p.keySet().iterator(); j.hasNext(); )
+ {
+ String key = (String) j.next();
+ if (key.equalsIgnoreCase(property))
+ return p.getProperty(key);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adds a new provider, at a specified position. The position is the
+ * preference order in which providers are searched for requested algorithms.
+ * Note that it is not guaranteed that this preference will be respected. The
+ * position is 1-based, that is, 1
is most preferred, followed by
+ * 2
, and so on.
+ *
+ * If the given provider is installed at the requested position, the
+ * provider that used to be at that position, and all providers with a
+ * position greater than position, are shifted up one position (towards the
+ * end of the list of installed providers).
+ *
+ * A provider cannot be added if it is already installed.
+ *
+ * First, if there is a security manager, its checkSecurityAccess()
+ *
method is called with the string "insertProvider."+provider.
+ * getName()
to see if it's ok to add a new provider. If the default
+ * implementation of checkSecurityAccess()
is used (i.e., that
+ * method is not overriden), then this will result in a call to the security
+ * manager's checkPermission()
method with a
+ * SecurityPermission("insertProvider."+provider.getName())
+ * permission.
+ *
+ * @param provider the provider to be added.
+ * @param position the preference position that the caller would like for
+ * this provider.
+ * @return the actual preference position in which the provider was added, or
+ * -1
if the provider was not added because it is already
+ * installed.
+ * @throws SecurityException if a security manager exists and its
+ * {@link SecurityManager#checkSecurityAccess(String)} method denies access
+ * to add a new provider.
+ * @see #getProvider(String)
+ * @see #removeProvider(String)
+ * @see SecurityPermission
+ */
+ public static int insertProviderAt(Provider provider, int position)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("insertProvider." + provider.getName());
+
+ position--;
+ int max = providers.size ();
+ for (int i = 0; i < max; i++)
+ {
+ if (((Provider) providers.elementAt(i)).getName() == provider.getName())
+ return -1;
+ }
+
+ if (position < 0)
+ position = 0;
+ if (position > max)
+ position = max;
+
+ providers.insertElementAt(provider, position);
+
+ return position + 1;
+ }
+
+ /**
+ * Adds a provider to the next position available.
+ *
+ * First, if there is a security manager, its checkSecurityAccess()
+ *
method is called with the string "insertProvider."+provider.
+ * getName()
to see if it's ok to add a new provider. If the default
+ * implementation of checkSecurityAccess()
is used (i.e., that
+ * method is not overriden), then this will result in a call to the security
+ * manager's checkPermission()
method with a
+ * SecurityPermission("insertProvider."+provider.getName())
+ * permission.
+ *
+ * @param provider the provider to be added.
+ * @return the preference position in which the provider was added, or
+ * -1
if the provider was not added because it is already
+ * installed.
+ * @throws SecurityException if a security manager exists and its
+ * {@link SecurityManager#checkSecurityAccess(String)} method denies access
+ * to add a new provider.
+ * @see #getProvider(String)
+ * @see #removeProvider(String)
+ * @see SecurityPermission
+ */
+ public static int addProvider(Provider provider)
+ {
+ return insertProviderAt (provider, providers.size () + 1);
+ }
+
+ /**
+ * Removes the provider with the specified name.
+ *
+ * When the specified provider is removed, all providers located at a
+ * position greater than where the specified provider was are shifted down
+ * one position (towards the head of the list of installed providers).
+ *
+ * This method returns silently if the provider is not installed.
+ *
+ * First, if there is a security manager, its checkSecurityAccess()
+ *
method is called with the string "removeProvider."+name
+ * to see if it's ok to remove the provider. If the default implementation of
+ * checkSecurityAccess()
is used (i.e., that method is not
+ * overriden), then this will result in a call to the security manager's
+ * checkPermission()
method with a SecurityPermission(
+ * "removeProvider."+name)
permission.
+ *
+ * @param name the name of the provider to remove.
+ * @throws SecurityException if a security manager exists and its
+ * {@link SecurityManager#checkSecurityAccess(String)} method denies access
+ * to remove the provider.
+ * @see #getProvider(String)
+ * @see #addProvider(Provider)
+ */
+ public static void removeProvider(String name)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("removeProvider." + name);
+
+ int max = providers.size ();
+ for (int i = 0; i < max; i++)
+ {
+ if (((Provider) providers.elementAt(i)).getName() == name)
+ {
+ providers.remove(i);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Returns an array containing all the installed providers. The order of the
+ * providers in the array is their preference order.
+ *
+ * @return an array of all the installed providers.
+ */
+ public static Provider[] getProviders()
+ {
+ Provider array[] = new Provider[providers.size ()];
+ providers.copyInto (array);
+ return array;
+ }
+
+ /**
+ * Returns the provider installed with the specified name, if any. Returns
+ * null
if no provider with the specified name is installed.
+ *
+ * @param name the name of the provider to get.
+ * @return the provider of the specified name.
+ * @see #removeProvider(String)
+ * @see #addProvider(Provider)
+ */
+ public static Provider getProvider(String name)
+ {
+ Provider p;
+ int max = providers.size ();
+ for (int i = 0; i < max; i++)
+ {
+ p = (Provider) providers.elementAt(i);
+ if (p.getName() == name)
+ return p;
+ }
+ return null;
+ }
+
+ /**
+ * Gets a security property value.
+ *
+ * First, if there is a security manager, its checkPermission()
+ * method is called with a SecurityPermission("getProperty."+key)
+ * permission to see if it's ok to retrieve the specified security property
+ * value.
+ *
+ * @param key the key of the property being retrieved.
+ * @return the value of the security property corresponding to key.
+ * @throws SecurityException if a security manager exists and its
+ * {@link SecurityManager#checkPermission(Permission)} method denies access
+ * to retrieve the specified security property value.
+ * @see #setProperty(String, String)
+ * @see SecurityPermission
+ */
+ public static String getProperty(String key)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("getProperty." + key);
+
+ return secprops.getProperty(key);
+ }
+
+ /**
+ * Sets a security property value.
+ *
+ * First, if there is a security manager, its checkPermission()
+ * method is called with a SecurityPermission("setProperty."+key)
+ * permission to see if it's ok to set the specified security property value.
+ *
+ *
+ * @param key the name of the property to be set.
+ * @param datnum the value of the property to be set.
+ * @throws SecurityException if a security manager exists and its
+ * {@link SecurityManager#checkPermission(Permission)} method denies access
+ * to set the specified security property value.
+ * @see #getProperty(String)
+ * @see SecurityPermission
+ */
+ public static void setProperty(String key, String datnum)
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkSecurityAccess("setProperty." + key);
+
+ secprops.put(key, datnum);
+ }
+
+ /**
+ * Returns a Set of Strings containing the names of all available algorithms
+ * or types for the specified Java cryptographic service (e.g., Signature,
+ * MessageDigest, Cipher, Mac, KeyStore). Returns an empty Set if there is no
+ * provider that supports the specified service. For a complete list of Java
+ * cryptographic services, please see the Java Cryptography Architecture API
+ * Specification & Reference. Note: the returned set is immutable.
+ *
+ * @param serviceName the name of the Java cryptographic service (e.g.,
+ * Signature, MessageDigest, Cipher, Mac, KeyStore). Note: this parameter is
+ * case-insensitive.
+ * @return a Set of Strings containing the names of all available algorithms
+ * or types for the specified Java cryptographic service or an empty set if
+ * no provider supports the specified service.
+ * @since 1.4
+ */
+ public static Set getAlgorithms(String serviceName)
+ {
+ HashSet result = new HashSet();
+ if (serviceName == null || serviceName.length() == 0)
+ return result;
+
+ serviceName = serviceName.trim();
+ if (serviceName.length() == 0)
+ return result;
+
+ serviceName = serviceName.toUpperCase()+".";
+ Provider[] providers = getProviders();
+ int ndx;
+ for (int i = 0; i < providers.length; i++)
+ for (Enumeration e = providers[i].propertyNames(); e.hasMoreElements(); )
+ {
+ String service = ((String) e.nextElement()).trim();
+ if (service.toUpperCase().startsWith(serviceName))
+ {
+ service = service.substring(serviceName.length()).trim();
+ ndx = service.indexOf(' '); // get rid of attributes
+ if (ndx != -1)
+ service = service.substring(0, ndx);
+ result.add(service);
+ }
+ }
+ return Collections.unmodifiableSet(result);
+ }
+
+ /**
+ * Returns an array containing all installed providers that satisfy the
+ * specified selection criterion, or null
if no such providers
+ * have been installed. The returned providers are ordered according to their
+ * preference order.
+ *
+ * A cryptographic service is always associated with a particular
+ * algorithm or type. For example, a digital signature service is always
+ * associated with a particular algorithm (e.g., DSA ), and a
+ * CertificateFactory service is always associated with a particular
+ * certificate type (e.g., X.509 ).
+ *
+ * The selection criterion must be specified in one of the following two
+ * formats:
+ *
+ *
+ * <crypto_service>.<algorithm_or_type>
+ * The cryptographic service name must not contain any dots.
+ * A provider satisfies the specified selection criterion iff the
+ * provider implements the specified algorithm or type for the specified
+ * cryptographic service.
+ * For example, "CertificateFactory.X.509" would be satisfied by any
+ * provider that supplied a CertificateFactory implementation for X.509
+ * certificates.
+ *
+ * <crypto_service>.<algorithm_or_type> <attribute_name>:<attribute_value>
+ * The cryptographic service name must not contain any dots. There must
+ * be one or more space charaters between the the <algorithm_or_type>
+ * and the <attribute_name>.
+ * A provider satisfies this selection criterion iff the provider
+ * implements the specified algorithm or type for the specified
+ * cryptographic service and its implementation meets the constraint
+ * expressed by the specified attribute name/value pair.
+ * For example, "Signature.SHA1withDSA KeySize:1024" would be satisfied
+ * by any provider that implemented the SHA1withDSA signature algorithm
+ * with a keysize of 1024 (or larger).
+ *
+ *
+ * See Appendix A in the Java Cryptogaphy Architecture API Specification
+ * & Reference for information about standard cryptographic service names,
+ * standard algorithm names and standard attribute names.
+ *
+ * @param filter the criterion for selecting providers. The filter is case-
+ * insensitive.
+ * @return all the installed providers that satisfy the selection criterion,
+ * or null if no such providers have been installed.
+ * @throws InvalidParameterException if the filter is not in the required
+ * format.
+ * @see #getProviders(Map)
+ */
+ public static Provider[] getProviders(String filter)
+ {
+ if (providers == null || providers.isEmpty())
+ return null;
+
+ if (filter == null || filter.length() == 0)
+ return getProviders();
+
+ HashMap map = new HashMap(1);
+ int i = filter.indexOf(':');
+ if (i == -1) // .
+ map.put(filter, "");
+ else // . :
+ map.put(filter.substring(0, i), filter.substring(i+1));
+
+ return getProviders(map);
+ }
+
+ /**
+ * Returns an array containing all installed providers that satisfy the
+ * specified selection criteria, or null
if no such providers
+ * have been installed. The returned providers are ordered according to their
+ * preference order.
+ *
+ * The selection criteria are represented by a map. Each map entry
+ * represents a selection criterion. A provider is selected iff it satisfies
+ * all selection criteria. The key for any entry in such a map must be in one
+ * of the following two formats:
+ *
+ *
+ * <crypto_service>.<algorithm_or_type>
+ * The cryptographic service name must not contain any dots.
+ * The value associated with the key must be an empty string.
+ * A provider satisfies this selection criterion iff the provider
+ * implements the specified algorithm or type for the specified
+ * cryptographic service.
+ *
+ * <crypto_service>.<algorithm_or_type> <attribute_name>
+ * The cryptographic service name must not contain any dots. There must
+ * be one or more space charaters between the <algorithm_or_type> and
+ * the <attribute_name>.
+ * The value associated with the key must be a non-empty string. A
+ * provider satisfies this selection criterion iff the provider implements
+ * the specified algorithm or type for the specified cryptographic service
+ * and its implementation meets the constraint expressed by the specified
+ * attribute name/value pair.
+ *
+ *
+ * See Appendix A in the Java Cryptogaphy Architecture API Specification
+ * & Reference for information about standard cryptographic service names,
+ * standard algorithm names and standard attribute names.
+ *
+ * @param filter the criteria for selecting providers. The filter is case-
+ * insensitive.
+ * @return all the installed providers that satisfy the selection criteria,
+ * or null
if no such providers have been installed.
+ * @throws InvalidParameterException if the filter is not in the required
+ * format.
+ * @see #getProviders(String)
+ */
+ public static Provider[] getProviders(Map filter)
+ {
+ if (providers == null || providers.isEmpty())
+ return null;
+
+ if (filter == null)
+ return getProviders();
+
+ Set querries = filter.keySet();
+ if (querries == null || querries.isEmpty())
+ return getProviders();
+
+ LinkedHashSet result = new LinkedHashSet(providers); // assume all
+ int dot, ws;
+ String querry, service, algorithm, attribute, value;
+ LinkedHashSet serviceProviders = new LinkedHashSet(); // preserve insertion order
+ for (Iterator i = querries.iterator(); i.hasNext(); )
+ {
+ querry = (String) i.next();
+ if (querry == null) // all providers
+ continue;
+
+ querry = querry.trim();
+ if (querry.length() == 0) // all providers
+ continue;
+
+ dot = querry.indexOf('.');
+ if (dot == -1) // syntax error
+ throw new InvalidParameterException(
+ "missing dot in '" + String.valueOf(querry)+"'");
+
+ value = (String) filter.get(querry);
+ // deconstruct querry into [service, algorithm, attribute]
+ if (value == null || value.trim().length() == 0) // .
+ {
+ value = null;
+ attribute = null;
+ service = querry.substring(0, dot).trim();
+ algorithm = querry.substring(dot+1).trim();
+ }
+ else // .
+ {
+ ws = querry.indexOf(' ');
+ if (ws == -1)
+ throw new InvalidParameterException(
+ "value (" + String.valueOf(value) +
+ ") is not empty, but querry (" + String.valueOf(querry) +
+ ") is missing at least one space character");
+ value = value.trim();
+ attribute = querry.substring(ws+1).trim();
+ // was the dot in the attribute?
+ if (attribute.indexOf('.') != -1)
+ throw new InvalidParameterException(
+ "attribute_name (" + String.valueOf(attribute) +
+ ") in querry (" + String.valueOf(querry) + ") contains a dot");
+
+ querry = querry.substring(0, ws).trim();
+ service = querry.substring(0, dot).trim();
+ algorithm = querry.substring(dot+1).trim();
+ }
+
+ // service and algorithm must not be empty
+ if (service.length() == 0)
+ throw new InvalidParameterException(
+ " in querry (" + String.valueOf(querry) +
+ ") is empty");
+
+ if (algorithm.length() == 0)
+ throw new InvalidParameterException(
+ " in querry (" + String.valueOf(querry) +
+ ") is empty");
+
+ selectProviders(service, algorithm, attribute, value, result, serviceProviders);
+ result.retainAll(serviceProviders); // eval next retaining found providers
+ if (result.isEmpty()) // no point continuing
+ break;
+ }
+
+ if (result.isEmpty())
+ return null;
+
+ return (Provider[]) result.toArray(new Provider[0]);
+ }
+
+ private static void selectProviders(String svc, String algo, String attr,
+ String val, LinkedHashSet providerSet,
+ LinkedHashSet result)
+ {
+ result.clear(); // ensure we start with an empty result set
+ for (Iterator i = providerSet.iterator(); i.hasNext(); )
+ {
+ Provider p = (Provider) i.next();
+ if (provides(p, svc, algo, attr, val))
+ result.add(p);
+ }
+ }
+
+ private static boolean provides(Provider p, String svc, String algo,
+ String attr, String val)
+ {
+ Iterator it;
+ String serviceDotAlgorithm = null;
+ String key = null;
+ String realVal;
+ boolean found = false;
+ // if . is in the set then so is .
+ // but it may be stored under an alias . resolve
+ outer: for (int r = 0; r < 3; r++) // guard against circularity
+ {
+ serviceDotAlgorithm = (svc+"."+String.valueOf(algo)).trim();
+ inner: for (it = p.keySet().iterator(); it.hasNext(); )
+ {
+ key = (String) it.next();
+ if (key.equalsIgnoreCase(serviceDotAlgorithm)) // eureka
+ {
+ found = true;
+ break outer;
+ }
+ // it may be there but as an alias
+ if (key.equalsIgnoreCase(ALG_ALIAS + serviceDotAlgorithm))
+ {
+ algo = p.getProperty(key);
+ continue outer;
+ }
+ // else continue inner
+ }
+ }
+
+ if (!found)
+ return false;
+
+ // found a candidate for the querry. do we have an attr to match?
+ if (val == null) // . querry
+ return true;
+
+ // . ; find the key entry that match
+ String realAttr;
+ int limit = serviceDotAlgorithm.length() + 1;
+ for (it = p.keySet().iterator(); it.hasNext(); )
+ {
+ key = (String) it.next();
+ if (key.length() <= limit)
+ continue;
+
+ if (key.substring(0, limit).equalsIgnoreCase(serviceDotAlgorithm+" "))
+ {
+ realAttr = key.substring(limit).trim();
+ if (! realAttr.equalsIgnoreCase(attr))
+ continue;
+
+ // eveything matches so far. do the value
+ realVal = p.getProperty(key);
+ if (realVal == null)
+ return false;
+
+ realVal = realVal.trim();
+ // is it a string value?
+ if (val.equalsIgnoreCase(realVal))
+ return true;
+
+ // assume value is a number. cehck for greater-than-or-equal
+ return (new Integer(val).intValue() >= new Integer(realVal).intValue());
+ }
+ }
+
+ return false;
+ }
+}
diff -Nru pdftk-1.45/java/java_local/security/DigestException.java pdftk-2.01/java/java_local/security/DigestException.java
--- pdftk-1.45/java/java_local/security/DigestException.java 2006-09-05 17:46:40.000000000 +0000
+++ pdftk-2.01/java/java_local/security/DigestException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,70 +0,0 @@
-/* DigestException.java -- A generic message digest exception
- Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java_local.security;
-
-/**
- * This exception indicates that a generic message digest exception has
- * occurred.
- *
- * @author Aaron M. Renn (arenn@urbanophile.com)
- * @status updated to 1.4
- */
-public class DigestException extends GeneralSecurityException
-{
- /**
- * Compatible with JDK 1.1+.
- */
- private static final long serialVersionUID = 5821450303093652515L;
-
- /**
- * Create a new instance with no descriptive message.
- */
- public DigestException()
- {
- }
-
- /**
- * Create a new instance with a descriptive error message.
- *
- * @param msg the descriptive message
- */
- public DigestException(String msg)
- {
- super(msg);
- }
-}
diff -Nru pdftk-1.45/java/java_local/security/DummyMessageDigest.java pdftk-2.01/java/java_local/security/DummyMessageDigest.java
--- pdftk-1.45/java/java_local/security/DummyMessageDigest.java 2006-09-05 17:22:52.000000000 +0000
+++ pdftk-2.01/java/java_local/security/DummyMessageDigest.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,90 +0,0 @@
-/* DummyMessageDigest.java - Wrapper for MessageDigestSpi
- Copyright (C) 1999, 2002 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java_local.security;
-
-final class DummyMessageDigest extends MessageDigest
-{
- private MessageDigestSpi mdSpi = null;
-
- public DummyMessageDigest(MessageDigestSpi mdSpi, String algorithm)
- {
- super(algorithm);
- this.mdSpi = mdSpi;
- }
-
- public Object clone() throws CloneNotSupportedException
- {
- MessageDigest result = new DummyMessageDigest
- ((MessageDigestSpi) mdSpi.clone(), this.getAlgorithm());
- result.provider = this.getProvider();
- return result;
- }
-
- // java.security.MessageDigestSpi abstract methods implementation ---------
-
- public byte[] engineDigest()
- {
- return mdSpi.engineDigest();
- }
-
- public int engineDigest(byte[] buf, int offset, int len)
- throws DigestException
- {
- return mdSpi.engineDigest(buf, offset, len);
- }
-
- public int engineGetDigestLength()
- {
- return mdSpi.engineGetDigestLength();
- }
-
- public void engineReset()
- {
- mdSpi.engineReset();
- }
-
- public void engineUpdate(byte input)
- {
- mdSpi.engineUpdate(input);
- }
-
- public void engineUpdate(byte[] input, int offset, int len)
- {
- mdSpi.engineUpdate(input, offset, len);
- }
-}
diff -Nru pdftk-1.45/java/java_local/security/GeneralSecurityException.java pdftk-2.01/java/java_local/security/GeneralSecurityException.java
--- pdftk-1.45/java/java_local/security/GeneralSecurityException.java 2006-09-05 17:23:06.000000000 +0000
+++ pdftk-2.01/java/java_local/security/GeneralSecurityException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,75 +0,0 @@
-/* GeneralSecurityException.java -- Common superclass of security exceptions
- Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java_local.security;
-
-/**
- * This class is the common superclass of all security exceptions. All
- * exceptions in java.security extend this class with the exception (no
- * pun intended) of AccessControlException
and
- * CertificateException
(which extend
- * SecurityException
), ProviderException
- * (RuntimeException
), and InvalidParamterException
- * (IllegalArgumentException
).
- *
- * @author Aaron M. Renn (arenn@urbanophile.com)
- * @status updated to 1.4
- */
-public class GeneralSecurityException extends Exception
-{
- /**
- * Compatible with JDK 1.1+.
- */
- private static final long serialVersionUID = 894798122053539237L;
-
- /**
- * Create a new instance with no descriptive error message.
- */
- public GeneralSecurityException()
- {
- }
-
- /**
- * Create a new instance with a descriptive error message.
- *
- * @param msg the descriptive error message
- */
- public GeneralSecurityException(String msg)
- {
- super(msg);
- }
-}
diff -Nru pdftk-1.45/java/java_local/security/InvalidParameterException.java pdftk-2.01/java/java_local/security/InvalidParameterException.java
--- pdftk-1.45/java/java_local/security/InvalidParameterException.java 2006-09-05 17:23:16.000000000 +0000
+++ pdftk-2.01/java/java_local/security/InvalidParameterException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,70 +0,0 @@
-/* InvalidParameterException.java -- an invalid parameter in the JCA/JCE engine
- Copyright (C) 2000, 2002 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java_local.security;
-
-/**
- * Thrown when an invalid parameter is passed to a method of the JCA/JCE
- * engine classes.
- *
- * @author Warren Levy (warrenl@cygnus.com)
- * @status updated to 1.4
- */
-public class InvalidParameterException extends IllegalArgumentException
-{
- /**
- * Compatible with JDK 1.1+.
- */
- private static final long serialVersionUID = -857968536935667808L;
-
- /**
- * Construct an exception with no message.
- */
- public InvalidParameterException()
- {
- }
-
- /**
- * Construct an exception with a message.
- *
- * @param msg the message
- */
- public InvalidParameterException(String msg)
- {
- super(msg);
- }
-}
diff -Nru pdftk-1.45/java/java_local/security/Makefile pdftk-2.01/java/java_local/security/Makefile
--- pdftk-1.45/java/java_local/security/Makefile 2010-09-15 09:40:52.000000000 +0000
+++ pdftk-2.01/java/java_local/security/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-library= security.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-all : $(library) $(headers)
-
-$(library) : $(objects)
- $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/java_local/security/MessageDigest.java pdftk-2.01/java/java_local/security/MessageDigest.java
--- pdftk-1.45/java/java_local/security/MessageDigest.java 2006-09-05 17:47:24.000000000 +0000
+++ pdftk-2.01/java/java_local/security/MessageDigest.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,414 +0,0 @@
-/* MessageDigest.java --- The message digest interface.
- Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java_local.security;
-
-import gnu_local.java.security.Engine;
-//import java_local.security.Provider;
-
-/**
- * This MessageDigest
class provides applications the
- * functionality of a message digest algorithm, such as MD5 or SHA .
- * Message digests are secure one-way hash functions that take arbitrary-sized
- * data and output a fixed-length hash value.
- *
- * A MessageDigest
object starts out initialized. The data is
- * processed through it using the update()
methods. At any point
- * reset()
can be called to reset the digest. Once all the data to
- * be updated has been updated, one of the digest()
methods should
- * be called to complete the hash computation.
- *
- * The digest()
method can be called once for a given
- * number of updates. After digest()
has been called, the
- * MessageDigest
object is reset to its initialized state.
- *
- *
- * Implementations are free to implement the {@link Cloneable} interface.
- * Client applications can test cloneability by attempting cloning and catching
- * the {@link CloneNotSupportedException}:
- *
- *
- * MessageDigest md = MessageDigest.getInstance("SHA");
- * try
- * {
- * md.update(toChapter1);
- * MessageDigest tc1 = md.clone();
- * byte[] toChapter1Digest = tc1.digest();
- * md.update(toChapter2);
- * // ...
- * }
- * catch (CloneNotSupportedException x)
- * {
- * throw new DigestException("couldn't make digest of partial content");
- * }
- *
- *
- * Note that if a given implementation is not cloneable, it is still possible
- * to compute intermediate digests by instantiating several instances, if the
- * number of digests is known in advance.
- *
- * Note that this class is abstract and extends from {@link MessageDigestSpi}
- * for historical reasons. Application developers should only take notice of the
- * methods defined in this MessageDigest
class; all the methods in
- * the superclass are intended for cryptographic service providers who wish to
- * supply their own implementations of message digest algorithms.
- *
- * @see MessageDigestSpi
- * @see Provider
- * @since JDK 1.1
- */
-public abstract class MessageDigest extends MessageDigestSpi
-{
- /** The service name for message digests. */
- private static final String MESSAGE_DIGEST = "MessageDigest";
-
- private String algorithm;
- Provider provider;
- private byte[] lastDigest;
-
- /**
- * Creates a message digest with the specified algorithm name.
- *
- * @param algorithm the standard name of the digest algorithm.
- * See Appendix A in the Java Cryptography Architecture API
- * Specification & Reference for information about standard
- * algorithm names.
- */
- protected MessageDigest(String algorithm)
- {
- this.algorithm = algorithm;
- provider = null;
- }
-
- /**
- * Generates a MessageDigest
object that implements the specified
- * digest algorithm. If the default provider package provides an
- * implementation of the requested digest algorithm, an instance of
- * MessageDigest
containing that implementation is returned. If
- * the algorithm is not available in the default package, other packages are
- * searched.
- *
- * @param algorithm the name of the algorithm requested. See Appendix A in the
- * Java Cryptography Architecture API Specification & Reference for
- * information about standard algorithm names.
- * @return a Message Digest object implementing the specified algorithm.
- * @throws NoSuchAlgorithmException if the algorithm is not available in the
- * caller's environment.
- */
- public static MessageDigest getInstance(String algorithm)
- throws NoSuchAlgorithmException
- {
- Provider[] p = Security.getProviders();
- for (int i = 0; i < p.length; i++)
- {
- try
- {
- return getInstance(algorithm, p[i]);
- }
- catch (NoSuchAlgorithmException ignored)
- {
- // Ignore.
- }
- }
-
- throw new NoSuchAlgorithmException(algorithm);
- }
-
- /**
- * Generates a MessageDigest
object implementing the specified
- * algorithm, as supplied from the specified provider, if such an algorithm is
- * available from the provider.
- *
- * @param algorithm the name of the algorithm requested. See Appendix A in the
- * Java Cryptography Architecture API Specification & Reference for
- * information about standard algorithm names.
- * @param provider the name of the provider.
- * @return a Message Digest object implementing the specified algorithm.
- * @throws NoSuchAlgorithmException if the algorithm is not available in the
- * package supplied by the requested provider.
- * @throws NoSuchProviderException if the provider is not available in the
- * environment.
- * @throws IllegalArgumentException if the provider name is null or empty.
- * @see Provider
- */
- public static MessageDigest getInstance(String algorithm, String provider)
- throws NoSuchAlgorithmException, NoSuchProviderException
- {
- if (provider == null || provider.length() == 0)
- throw new IllegalArgumentException("Illegal provider");
-
- Provider p = Security.getProvider(provider);
- if (p == null)
- throw new NoSuchProviderException(provider);
-
- return getInstance(algorithm, p);
- }
-
- /**
- * Generates a MessageDigest
object implementing the specified
- * algorithm, as supplied from the specified provider, if such an algorithm
- * is available from the provider. Note: the provider doesn't have to be
- * registered.
- *
- * @param algorithm the name of the algorithm requested. See Appendix A in
- * the Java Cryptography Architecture API Specification & Reference for
- * information about standard algorithm names.
- * @param provider the provider.
- * @return a Message Digest object implementing the specified algorithm.
- * @throws NoSuchAlgorithmException if the algorithm
is not
- * available in the package supplied by the requested provider
.
- * @throws IllegalArgumentException if the provider
is
- * null
.
- * @since 1.4
- * @see Provider
- */
- public static MessageDigest getInstance(String algorithm, Provider provider)
- throws NoSuchAlgorithmException
- {
- if (provider == null)
- throw new IllegalArgumentException("Illegal provider");
-
- MessageDigest result = null;
- Object o = null;
- try
- {
- o = Engine.getInstance(MESSAGE_DIGEST, algorithm, provider);
- }
- catch (java.lang.reflect.InvocationTargetException ite)
- {
- throw new NoSuchAlgorithmException(algorithm);
- }
-
- if (o instanceof MessageDigestSpi)
- {
- result = new DummyMessageDigest((MessageDigestSpi) o, algorithm);
- }
- else if (o instanceof MessageDigest)
- {
- result = (MessageDigest) o;
- result.algorithm = algorithm;
- }
- else
- {
- throw new NoSuchAlgorithmException(algorithm);
- }
- result.provider = provider;
- return result;
- }
-
- /**
- * Returns the provider of this message digest object.
- *
- * @return the provider of this message digest object.
- */
- public final Provider getProvider()
- {
- return provider;
- }
-
- /**
- * Updates the digest using the specified byte.
- *
- * @param input the byte with which to update the digest.
- */
- public void update(byte input)
- {
- engineUpdate(input);
- }
-
- /**
- * Updates the digest using the specified array of bytes, starting at the
- * specified offset.
- *
- * @param input the array of bytes.
- * @param offset the offset to start from in the array of bytes.
- * @param len the number of bytes to use, starting at offset.
- */
- public void update(byte[] input, int offset, int len)
- {
- engineUpdate(input, offset, len);
- }
-
- /**
- * Updates the digest using the specified array of bytes.
- *
- * @param input the array of bytes.
- */
- public void update(byte[] input)
- {
- engineUpdate(input, 0, input.length);
- }
-
- /**
- * Completes the hash computation by performing final operations such as
- * padding. The digest is reset after this call is made.
- *
- * @return the array of bytes for the resulting hash value.
- */
- public byte[] digest()
- {
- return lastDigest = engineDigest();
- }
-
- /**
- * Completes the hash computation by performing final operations such as
- * padding. The digest is reset after this call is made.
- *
- * @param buf An output buffer for the computed digest.
- * @param offset The offset into the output buffer to begin storing the digest.
- * @param len The number of bytes within buf allotted for the digest.
- * @return The number of bytes placed into buf.
- * @throws DigestException if an error occurs.
- */
- public int digest(byte[] buf, int offset, int len) throws DigestException
- {
- return engineDigest(buf, offset, len);
- }
-
- /**
- * Performs a final update on the digest using the specified array of bytes,
- * then completes the digest computation. That is, this method first calls
- * update(input)
, passing the input array to the update()
- *
method, then calls digest()
.
- *
- * @param input the input to be updated before the digest is completed.
- * @return the array of bytes for the resulting hash value.
- */
- public byte[] digest(byte[] input)
- {
- update(input);
- return digest();
- }
-
- /**
- * Returns a string representation of this message digest object.
- *
- * @return a string representation of the object.
- */
- public String toString()
- {
- return (getClass()).getName() + " Message Digest <" + digestToString() + ">";
- }
-
- /**
- * Compares two digests for equality. Does a simple byte compare.
- *
- * @param digesta one of the digests to compare.
- * @param digestb the other digest to compare.
- * @return true
if the digests are equal, false
- * otherwise.
- */
- public static boolean isEqual(byte[] digesta, byte[] digestb)
- {
- if (digesta.length != digestb.length)
- return false;
-
- for (int i = digesta.length - 1; i >= 0; --i)
- if (digesta[i] != digestb[i])
- return false;
-
- return true;
- }
-
- /** Resets the digest for further use. */
- public void reset()
- {
- engineReset();
- }
-
- /**
- * Returns a string that identifies the algorithm, independent of
- * implementation details. The name should be a standard Java Security name
- * (such as "SHA"
, "MD5"
, and so on). See Appendix
- * A in the Java Cryptography Architecture API Specification & Reference
- * for information about standard algorithm names.
- *
- * @return the name of the algorithm.
- */
- public final String getAlgorithm()
- {
- return algorithm;
- }
-
- /**
- * Returns the length of the digest in bytes, or 0
if this
- * operation is not supported by the provider and the implementation is not
- * cloneable.
- *
- * @return the digest length in bytes, or 0
if this operation is
- * not supported by the provider and the implementation is not cloneable.
- * @since 1.2
- */
- public final int getDigestLength()
- {
- return engineGetDigestLength();
- }
-
- /**
- * Returns a clone if the implementation is cloneable.
- *
- * @return a clone if the implementation is cloneable.
- * @throws CloneNotSupportedException if this is called on an implementation
- * that does not support {@link Cloneable}.
- */
- public Object clone() throws CloneNotSupportedException
- {
- return super.clone();
- }
-
- private String digestToString()
- {
- byte[] digest = lastDigest;
-
- if (digest == null)
- return "incomplete";
-
- StringBuffer buf = new StringBuffer();
- int len = digest.length;
- for (int i = 0; i < len; ++i)
- {
- byte b = digest[i];
- byte high = (byte) ((b & 0xff) >>> 4);
- byte low = (byte) (b & 0xf);
-
- buf.append(high > 9 ? ('a' - 10) + high : '0' + high);
- buf.append(low > 9 ? ('a' - 10) + low : '0' + low);
- }
-
- return buf.toString();
- }
-}
diff -Nru pdftk-1.45/java/java_local/security/MessageDigestSpi.java pdftk-2.01/java/java_local/security/MessageDigestSpi.java
--- pdftk-1.45/java/java_local/security/MessageDigestSpi.java 2006-09-05 17:25:00.000000000 +0000
+++ pdftk-2.01/java/java_local/security/MessageDigestSpi.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,155 +0,0 @@
-/* MessageDigestSpi.java --- The message digest service provider interface.
- Copyright (C) 1999, 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java_local.security;
-
-/**
- This is the Service Provider Interface (SPI) for MessageDigest
- class in java.security. It provides the back end functionality
- for the MessageDigest class so that it can compute message
- hashes. The default hashes are SHA-1 and MD5. A message hash
- takes data of arbitrary length and produces a unique number
- representing it.
-
- Cryptography service providers who want to implement their
- own message digest hashes need only to subclass this class.
-
- The implementation of a Cloneable interface is left to up to
- the programmer of a subclass.
-
- @version 0.0
-
- @author Mark Benvenuto (ivymccough@worldnet.att.net)
- */
-public abstract class MessageDigestSpi
-{
- /**
- Default constructor of the MessageDigestSpi class
- */
- public MessageDigestSpi()
- {
- }
-
- /**
- Returns the length of the digest. It may be overridden by the
- provider to return the length of the digest. Default is to
- return 0. It is concrete for backwards compatibility with JDK1.1
- message digest classes.
-
- @return Length of Digest in Bytes
-
- @since 1.2
- */
- protected int engineGetDigestLength()
- {
- return 0;
- }
-
- /**
- Updates the digest with the specified byte.
-
- @param input the byte to update digest with
- */
- protected abstract void engineUpdate(byte input);
-
-
- /**
- Updates the digest with the specified bytes starting with the
- offset and proceeding for the specified length.
-
- @param input the byte array to update digest with
- @param offset the offset of the byte to start with
- @param len the number of the bytes to update with
- */
- protected abstract void engineUpdate(byte[]input, int offset, int len);
-
- /**
- Computes the final digest of the stored bytes and returns
- them. It performs any necessary padding. The message digest
- should reset sensitive data after performing the digest.
-
- @return An array of bytes containing the digest
- */
- protected abstract byte[] engineDigest();
-
- /**
- Computes the final digest of the stored bytes and returns
- them. It performs any necessary padding. The message digest
- should reset sensitive data after performing the digest. This
- method is left concrete for backwards compatibility with JDK1.1
- message digest classes.
-
- @param buf An array of bytes to store the digest
- @param offset An offset to start storing the digest at
- @param len The length of the buffer
- @return Returns the length of the buffer
-
- @since 1.2
- */
- protected int engineDigest(byte[]buf, int offset, int len)
- throws DigestException
- {
- if (engineGetDigestLength() > len)
- throw new DigestException("Buffer is too small.");
-
- byte[] tmp = engineDigest();
- if (tmp.length > len)
- throw new DigestException("Buffer is too small");
-
- System.arraycopy(tmp, 0, buf, offset, tmp.length);
- return tmp.length;
- }
-
- /**
- Resets the digest engine. Reinitializes internal variables
- and clears sensitive data.
- */
- protected abstract void engineReset();
-
- /**
- Returns a clone of this class.
-
- If cloning is not supported, then by default the class throws a
- CloneNotSupportedException. The MessageDigestSpi provider
- implementation has to overload this class in order to be
- cloneable.
- */
- public Object clone() throws CloneNotSupportedException
- {
- return super.clone();
- }
-}
diff -Nru pdftk-1.45/java/java_local/security/NoSuchAlgorithmException.java pdftk-2.01/java/java_local/security/NoSuchAlgorithmException.java
--- pdftk-1.45/java/java_local/security/NoSuchAlgorithmException.java 2006-09-05 17:25:12.000000000 +0000
+++ pdftk-2.01/java/java_local/security/NoSuchAlgorithmException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,70 +0,0 @@
-/* NoSuchAlgorithmException.java -- an algorithm was not available
- Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java_local.security;
-
-/**
- * This exception is thrown when the requested security algorithm is
- * not available
- *
- * @author Aaron M. Renn (arenn@urbanophile.com)
- * @status updated to 1.4
- */
-public class NoSuchAlgorithmException extends GeneralSecurityException
-{
- /**
- * Compatible with JDK 1.1+.
- */
- private static final long serialVersionUID = -7443947487218346562L;
-
- /**
- * Create a new instance with no descriptive error message.
- */
- public NoSuchAlgorithmException()
- {
- }
-
- /**
- * Create a new instance with a descriptive error message.
- *
- * @param msg the descriptive error message
- */
- public NoSuchAlgorithmException(String msg)
- {
- super(msg);
- }
-}
diff -Nru pdftk-1.45/java/java_local/security/NoSuchProviderException.java pdftk-2.01/java/java_local/security/NoSuchProviderException.java
--- pdftk-1.45/java/java_local/security/NoSuchProviderException.java 2006-09-05 17:25:22.000000000 +0000
+++ pdftk-2.01/java/java_local/security/NoSuchProviderException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,70 +0,0 @@
-/* NoSuchProviderException.java -- thrown when a provider is not found
- Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java_local.security;
-
-/**
- * This exception is thrown when the requested security provider is
- * not available.
- *
- * @author Aaron M. Renn (arenn@urbanophile.com)
- * @status updated to 1.4
- */
-public class NoSuchProviderException extends GeneralSecurityException
-{
- /**
- * Compatible with JDK 1.1+.
- */
- private static final long serialVersionUID = 8488111756688534474L;
-
- /**
- * Create a new instance with no descriptive error message.
- */
- public NoSuchProviderException()
- {
- }
-
- /**
- * Create a new instance with a descriptive error message.
- *
- * @param msg the descriptive error message
- */
- public NoSuchProviderException(String msg)
- {
- super(msg);
- }
-}
diff -Nru pdftk-1.45/java/java_local/security/Provider.java pdftk-2.01/java/java_local/security/Provider.java
--- pdftk-1.45/java/java_local/security/Provider.java 2006-09-05 17:25:30.000000000 +0000
+++ pdftk-2.01/java/java_local/security/Provider.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,202 +0,0 @@
-/* Provider.java -- Security provider information
- Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java_local.security;
-
-import java.io.Serializable;
-import java.util.Properties;
-
-/**
- * This class represents a Java security architecture service provider.
- * The services provided by a such a provider can range from security
- * algorithms to key generation.
- *
- * Providers are installed by name and version number. There is one
- * standard provider supplied with the class library. This is the
- * "GNU" provider, which can also be accessed by the alias "SUN" for
- * compatibility with the JDK.
- *
- * @version 0.0
- *
- * @author Aaron M. Renn (arenn@urbanophile.com)
- */
-public abstract class Provider extends Properties implements Serializable
-{
- private static final long serialVersionUID = -4298000515446427739L;
-
- /**
- * This is a textual description of the provider
- */
- private String info;
-
- /**
- * This is the name of the provider
- */
- private String name;
-
- /**
- * This is the version number of the provider
- */
- private double version;
-
- /**
- * This method initializes a new instance of Provider
to have
- * the specified name, version, and description information.
- *
- * @param name The name to assign to this Provider
.
- * @param version The version number for this Provider
.
- * @param info A textual description of this provider.
- */
- protected Provider(String name, double version, String info)
- {
- this.name = name;
- this.version = version;
- this.info = info;
- }
-
- /**
- * This method returns the name assigned to this Provider
.
- *
- * @return The Provider
's name.
- */
- public String getName()
- {
- return (name);
- }
-
- /**
- * This method retunrs the version number of this Provider
.
- *
- * @return The Provider
's version number.
- */
- public double getVersion()
- {
- return (version);
- }
-
- /**
- * This method returns a textual description of the Provider
.
- *
- * @return A description of the Provider
.
- */
- public String getInfo()
- {
- return (info);
- }
-
- /**
- * Sets the key property to have the specified value.
- *
- * NOT IMPLEMENTED YET [
- * First, if there is a security manager, its checkSecurityAccess
- * method is called with the string "putProviderProperty."+name, where name is
- * the provider name, to see if it's ok to set this provider's property
- * values.
- * If the default implementation of checkSecurityAccess
is used
- * (that is, that method is not overriden), then this results in a call to the
- * security manager's checkPermission
method with a
- * SecurityPermission("putProviderProperty."+name)
- * permission. ]
- *
- * @param key The property key.
- * @param value The property value.
- *
- * @return The previous value of the specified property (key
),
- * or null
if it did not have one.
- * @throws SecurityException If a security manager exists and its
- * {@link java.lang.SecurityManager.checkSecurityAccess(java.lang.String)}
- * method denies access to set property values.
- * @since Classpath 0.4+cvs, JDK 1.2
- * @see java.lang.Object.equals(Object)
- * @see java.util.Hashtable.get(Object)
- */
- public Object put(Object key, Object value)
- {
- return super.put(toCanonicalKey(key), value);
- }
-
- // overrides same in java.util.Hashtable
- public Object get(Object key)
- {
- return super.get(toCanonicalKey(key));
- }
-
- /**
- * This method removes the specified key entry (and its associated value)
- * from the property mapping list.
- *
- * @param key The key to remove
- *
- * @return The previous value for this key, or null
if no
- * previous value.
- */
- public Object remove(Object key)
- {
- return super.remove(toCanonicalKey(key));
- }
-
- /**
- * This method clears the entire property list such that it no longer
- * contains the properties used to look up the services provided by
- * the Provider
.
- */
- public void clear()
- {
- super.clear();
- }
-
- /**
- * This method returns a String
representation of this
- * object. This will include the Provider
name and
- * version number.
- *
- * @return A String
representation of this object.
- */
- public String toString()
- {
- return (getClass().getName() + ": name=" + getName() + " version=" +
- version);
- }
-
- private Object toCanonicalKey(Object key)
- {
- if (key.getClass().isAssignableFrom(String.class)) // is it ours?
- return ((String) key).toUpperCase(); // use default locale
- else
- return key;
- }
-}
diff -Nru pdftk-1.45/java/java_local/security/Security.java pdftk-2.01/java/java_local/security/Security.java
--- pdftk-1.45/java/java_local/security/Security.java 2006-09-05 17:21:58.000000000 +0000
+++ pdftk-2.01/java/java_local/security/Security.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,745 +0,0 @@
-/* Security.java --- Java base security class implementation
- Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java_local.security;
-
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.io.IOException;
-import java.net.URL;
-import java_local.security.Provider;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.Vector;
-
-/**
- * This class centralizes all security properties and common security methods.
- * One of its primary uses is to manage providers.
- *
- * @author Mark Benvenuto (ivymccough@worldnet.att.net)
- */
-public final class Security
-{
- private static final String ALG_ALIAS = "Alg.Alias.";
-
- private static Vector providers = new Vector();
- private static Properties secprops = new Properties();
-
- static
- {
- /* SID: do not load system providers, since we've packaged our own
-
- String base = System.getProperty ("gnu.classpath.home.url");
- String vendor = System.getProperty ("gnu.classpath.vm.shortname");
-
- // Try VM specific security file
- boolean loaded = loadProviders (base, vendor);
-
- // Append classpath standard provider if possible
- if (!loadProviders (base, "classpath")
- && !loaded
- && providers.size() == 0)
- {
- if (Configuration.DEBUG)
- {
- // No providers found and both security files failed to
- // load properly. Give a warning in case of DEBUG is
- // enabled. Could be done with java.util.logging later.
- //
- System.err.println
- ("WARNING: could not properly read security provider files:");
- System.err.println
- (" " + base + "/security/" + vendor
- + ".security");
- System.err.println
- (" " + base + "/security/" + "classpath"
- + ".security");
- System.err.println
- (" Falling back to standard GNU security provider");
- }
- providers.addElement (new gnu_local.java.security.provider.Gnu());
- }
- */
-
- // SID: add our provider
- providers.addElement (new gnu_local.java.security.provider.Gnu());
-
- }
- // This class can't be instantiated.
- private Security()
- {
- }
-
- /**
- * Tries to load the vender specific security providers from the given
- * base URL. Returns true if the resource could be read and completely
- * parsed successfully, false otherwise.
- */
- private static boolean loadProviders(String baseUrl, String vendor)
- {
- if (baseUrl == null || vendor == null)
- return false;
-
- boolean result = true;
- String secfilestr = baseUrl + "/security/" + vendor + ".security";
- try
- {
- InputStream fin = new URL(secfilestr).openStream();
- secprops.load(fin);
-
- int i = 1;
- String name;
- while ((name = secprops.getProperty("security.provider." + i)) != null)
- {
- Exception exception = null;
- try
- {
- ClassLoader sys = ClassLoader.getSystemClassLoader();
- providers.addElement(Class.forName(name, true, sys).newInstance());
- }
- catch (ClassNotFoundException x)
- {
- exception = x;
- }
- catch (InstantiationException x)
- {
- exception = x;
- }
- catch (IllegalAccessException x)
- {
- exception = x;
- }
-
- if (exception != null)
- {
- System.err.println ("WARNING: Error loading security provider "
- + name + ": " + exception);
- result = false;
- }
- i++;
- }
- }
- catch (IOException ignored)
- {
- result = false;
- }
-
- return result;
- }
-
- /**
- * Gets a specified property for an algorithm. The algorithm name should be a
- * standard name. See Appendix A in the Java Cryptography Architecture API
- * Specification & Reference for information about standard algorithm
- * names. One possible use is by specialized algorithm parsers, which may map
- * classes to algorithms which they understand (much like {@link Key} parsers
- * do).
- *
- * @param algName the algorithm name.
- * @param propName the name of the property to get.
- * @return the value of the specified property.
- * @deprecated This method used to return the value of a proprietary property
- * in the master file of the "SUN" Cryptographic Service Provider in order to
- * determine how to parse algorithm-specific parameters. Use the new
- * provider-based and algorithm-independent {@link AlgorithmParameters} and
- * {@link KeyFactory} engine classes (introduced in the Java 2 platform)
- * instead.
- */
- public static String getAlgorithmProperty(String algName, String propName)
- {
- if (algName == null || propName == null)
- return null;
-
- String property = String.valueOf(propName) + "." + String.valueOf(algName);
- Provider p;
- for (Iterator i = providers.iterator(); i.hasNext(); )
- {
- p = (Provider) i.next();
- for (Iterator j = p.keySet().iterator(); j.hasNext(); )
- {
- String key = (String) j.next();
- if (key.equalsIgnoreCase(property))
- return p.getProperty(key);
- }
- }
- return null;
- }
-
- /**
- *
Adds a new provider, at a specified position. The position is the
- * preference order in which providers are searched for requested algorithms.
- * Note that it is not guaranteed that this preference will be respected. The
- * position is 1-based, that is, 1
is most preferred, followed by
- * 2
, and so on.
- *
- * If the given provider is installed at the requested position, the
- * provider that used to be at that position, and all providers with a
- * position greater than position, are shifted up one position (towards the
- * end of the list of installed providers).
- *
- * A provider cannot be added if it is already installed.
- *
- * First, if there is a security manager, its checkSecurityAccess()
- *
method is called with the string "insertProvider."+provider.
- * getName()
to see if it's ok to add a new provider. If the default
- * implementation of checkSecurityAccess()
is used (i.e., that
- * method is not overriden), then this will result in a call to the security
- * manager's checkPermission()
method with a
- * SecurityPermission("insertProvider."+provider.getName())
- * permission.
- *
- * @param provider the provider to be added.
- * @param position the preference position that the caller would like for
- * this provider.
- * @return the actual preference position in which the provider was added, or
- * -1
if the provider was not added because it is already
- * installed.
- * @throws SecurityException if a security manager exists and its
- * {@link SecurityManager#checkSecurityAccess(String)} method denies access
- * to add a new provider.
- * @see #getProvider(String)
- * @see #removeProvider(String)
- * @see SecurityPermission
- */
- public static int insertProviderAt(Provider provider, int position)
- {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkSecurityAccess("insertProvider." + provider.getName());
-
- position--;
- int max = providers.size ();
- for (int i = 0; i < max; i++)
- {
- if (((Provider) providers.elementAt(i)).getName().equals(provider.getName()))
- return -1;
- }
-
- if (position < 0)
- position = 0;
- if (position > max)
- position = max;
-
- providers.insertElementAt(provider, position);
-
- return position + 1;
- }
-
- /**
- * Adds a provider to the next position available.
- *
- * First, if there is a security manager, its checkSecurityAccess()
- *
method is called with the string "insertProvider."+provider.
- * getName()
to see if it's ok to add a new provider. If the default
- * implementation of checkSecurityAccess()
is used (i.e., that
- * method is not overriden), then this will result in a call to the security
- * manager's checkPermission()
method with a
- * SecurityPermission("insertProvider."+provider.getName())
- * permission.
- *
- * @param provider the provider to be added.
- * @return the preference position in which the provider was added, or
- * -1
if the provider was not added because it is already
- * installed.
- * @throws SecurityException if a security manager exists and its
- * {@link SecurityManager#checkSecurityAccess(String)} method denies access
- * to add a new provider.
- * @see #getProvider(String)
- * @see #removeProvider(String)
- * @see SecurityPermission
- */
- public static int addProvider(Provider provider)
- {
- return insertProviderAt (provider, providers.size () + 1);
- }
-
- /**
- * Removes the provider with the specified name.
- *
- * When the specified provider is removed, all providers located at a
- * position greater than where the specified provider was are shifted down
- * one position (towards the head of the list of installed providers).
- *
- * This method returns silently if the provider is not installed.
- *
- * First, if there is a security manager, its checkSecurityAccess()
- *
method is called with the string "removeProvider."+name
- * to see if it's ok to remove the provider. If the default implementation of
- * checkSecurityAccess()
is used (i.e., that method is not
- * overriden), then this will result in a call to the security manager's
- * checkPermission()
method with a SecurityPermission(
- * "removeProvider."+name)
permission.
- *
- * @param name the name of the provider to remove.
- * @throws SecurityException if a security manager exists and its
- * {@link SecurityManager#checkSecurityAccess(String)} method denies access
- * to remove the provider.
- * @see #getProvider(String)
- * @see #addProvider(Provider)
- */
- public static void removeProvider(String name)
- {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkSecurityAccess("removeProvider." + name);
-
- int max = providers.size ();
- for (int i = 0; i < max; i++)
- {
- if (((Provider) providers.elementAt(i)).getName().equals(name))
- {
- providers.remove(i);
- break;
- }
- }
- }
-
- /**
- * Returns an array containing all the installed providers. The order of the
- * providers in the array is their preference order.
- *
- * @return an array of all the installed providers.
- */
- public static Provider[] getProviders()
- {
- Provider[] array = new Provider[providers.size ()];
- providers.copyInto (array);
- return array;
- }
-
- /**
- * Returns the provider installed with the specified name, if any. Returns
- * null
if no provider with the specified name is installed.
- *
- * @param name the name of the provider to get.
- * @return the provider of the specified name.
- * @see #removeProvider(String)
- * @see #addProvider(Provider)
- */
- public static Provider getProvider(String name)
- {
- Provider p;
- int max = providers.size ();
- for (int i = 0; i < max; i++)
- {
- p = (Provider) providers.elementAt(i);
- if (p.getName().equals(name))
- return p;
- }
- return null;
- }
-
- /**
- * Gets a security property value.
- *
- * First, if there is a security manager, its checkPermission()
- * method is called with a SecurityPermission("getProperty."+key)
- * permission to see if it's ok to retrieve the specified security property
- * value.
- *
- * @param key the key of the property being retrieved.
- * @return the value of the security property corresponding to key.
- * @throws SecurityException if a security manager exists and its
- * {@link SecurityManager#checkPermission(Permission)} method denies access
- * to retrieve the specified security property value.
- * @see #setProperty(String, String)
- * @see SecurityPermission
- */
- public static String getProperty(String key)
- {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkSecurityAccess("getProperty." + key);
-
- return secprops.getProperty(key);
- }
-
- /**
- * Sets a security property value.
- *
- * First, if there is a security manager, its checkPermission()
- * method is called with a SecurityPermission("setProperty."+key)
- * permission to see if it's ok to set the specified security property value.
- *
- *
- * @param key the name of the property to be set.
- * @param datnum the value of the property to be set.
- * @throws SecurityException if a security manager exists and its
- * {@link SecurityManager#checkPermission(Permission)} method denies access
- * to set the specified security property value.
- * @see #getProperty(String)
- * @see SecurityPermission
- */
- public static void setProperty(String key, String datnum)
- {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkSecurityAccess("setProperty." + key);
-
- secprops.put(key, datnum);
- }
-
- /**
- * Returns a Set of Strings containing the names of all available algorithms
- * or types for the specified Java cryptographic service (e.g., Signature,
- * MessageDigest, Cipher, Mac, KeyStore). Returns an empty Set if there is no
- * provider that supports the specified service. For a complete list of Java
- * cryptographic services, please see the Java Cryptography Architecture API
- * Specification & Reference. Note: the returned set is immutable.
- *
- * @param serviceName the name of the Java cryptographic service (e.g.,
- * Signature, MessageDigest, Cipher, Mac, KeyStore). Note: this parameter is
- * case-insensitive.
- * @return a Set of Strings containing the names of all available algorithms
- * or types for the specified Java cryptographic service or an empty set if
- * no provider supports the specified service.
- * @since 1.4
- */
- public static Set getAlgorithms(String serviceName)
- {
- HashSet result = new HashSet();
- if (serviceName == null || serviceName.length() == 0)
- return result;
-
- serviceName = serviceName.trim();
- if (serviceName.length() == 0)
- return result;
-
- serviceName = serviceName.toUpperCase()+".";
- Provider[] providers = getProviders();
- int ndx;
- for (int i = 0; i < providers.length; i++)
- for (Enumeration e = providers[i].propertyNames(); e.hasMoreElements(); )
- {
- String service = ((String) e.nextElement()).trim();
- if (service.toUpperCase().startsWith(serviceName))
- {
- service = service.substring(serviceName.length()).trim();
- ndx = service.indexOf(' '); // get rid of attributes
- if (ndx != -1)
- service = service.substring(0, ndx);
- result.add(service);
- }
- }
- return Collections.unmodifiableSet(result);
- }
-
- /**
- * Returns an array containing all installed providers that satisfy the
- * specified selection criterion, or null
if no such providers
- * have been installed. The returned providers are ordered according to their
- * preference order.
- *
- * A cryptographic service is always associated with a particular
- * algorithm or type. For example, a digital signature service is always
- * associated with a particular algorithm (e.g., DSA ), and a
- * CertificateFactory service is always associated with a particular
- * certificate type (e.g., X.509 ).
- *
- * The selection criterion must be specified in one of the following two
- * formats:
- *
- *
- * <crypto_service>.<algorithm_or_type>
- * The cryptographic service name must not contain any dots.
- * A provider satisfies the specified selection criterion iff the
- * provider implements the specified algorithm or type for the specified
- * cryptographic service.
- * For example, "CertificateFactory.X.509" would be satisfied by any
- * provider that supplied a CertificateFactory implementation for X.509
- * certificates.
- *
- * <crypto_service>.<algorithm_or_type> <attribute_name>:<attribute_value>
- * The cryptographic service name must not contain any dots. There must
- * be one or more space charaters between the the <algorithm_or_type>
- * and the <attribute_name>.
- * A provider satisfies this selection criterion iff the provider
- * implements the specified algorithm or type for the specified
- * cryptographic service and its implementation meets the constraint
- * expressed by the specified attribute name/value pair.
- * For example, "Signature.SHA1withDSA KeySize:1024" would be satisfied
- * by any provider that implemented the SHA1withDSA signature algorithm
- * with a keysize of 1024 (or larger).
- *
- *
- * See Appendix A in the Java Cryptogaphy Architecture API Specification
- * & Reference for information about standard cryptographic service names,
- * standard algorithm names and standard attribute names.
- *
- * @param filter the criterion for selecting providers. The filter is case-
- * insensitive.
- * @return all the installed providers that satisfy the selection criterion,
- * or null if no such providers have been installed.
- * @throws InvalidParameterException if the filter is not in the required
- * format.
- * @see #getProviders(Map)
- */
- public static Provider[] getProviders(String filter)
- {
- if (providers == null || providers.isEmpty())
- return null;
-
- if (filter == null || filter.length() == 0)
- return getProviders();
-
- HashMap map = new HashMap(1);
- int i = filter.indexOf(':');
- if (i == -1) // .
- map.put(filter, "");
- else // . :
- map.put(filter.substring(0, i), filter.substring(i+1));
-
- return getProviders(map);
- }
-
- /**
- * Returns an array containing all installed providers that satisfy the
- * specified selection criteria, or null
if no such providers
- * have been installed. The returned providers are ordered according to their
- * preference order.
- *
- * The selection criteria are represented by a map. Each map entry
- * represents a selection criterion. A provider is selected iff it satisfies
- * all selection criteria. The key for any entry in such a map must be in one
- * of the following two formats:
- *
- *
- * <crypto_service>.<algorithm_or_type>
- * The cryptographic service name must not contain any dots.
- * The value associated with the key must be an empty string.
- * A provider satisfies this selection criterion iff the provider
- * implements the specified algorithm or type for the specified
- * cryptographic service.
- *
- * <crypto_service>.<algorithm_or_type> <attribute_name>
- * The cryptographic service name must not contain any dots. There must
- * be one or more space charaters between the <algorithm_or_type> and
- * the <attribute_name>.
- * The value associated with the key must be a non-empty string. A
- * provider satisfies this selection criterion iff the provider implements
- * the specified algorithm or type for the specified cryptographic service
- * and its implementation meets the constraint expressed by the specified
- * attribute name/value pair.
- *
- *
- * See Appendix A in the Java Cryptogaphy Architecture API Specification
- * & Reference for information about standard cryptographic service names,
- * standard algorithm names and standard attribute names.
- *
- * @param filter the criteria for selecting providers. The filter is case-
- * insensitive.
- * @return all the installed providers that satisfy the selection criteria,
- * or null
if no such providers have been installed.
- * @throws InvalidParameterException if the filter is not in the required
- * format.
- * @see #getProviders(String)
- */
- public static Provider[] getProviders(Map filter)
- {
- if (providers == null || providers.isEmpty())
- return null;
-
- if (filter == null)
- return getProviders();
-
- Set querries = filter.keySet();
- if (querries == null || querries.isEmpty())
- return getProviders();
-
- LinkedHashSet result = new LinkedHashSet(providers); // assume all
- int dot, ws;
- String querry, service, algorithm, attribute, value;
- LinkedHashSet serviceProviders = new LinkedHashSet(); // preserve insertion order
- for (Iterator i = querries.iterator(); i.hasNext(); )
- {
- querry = (String) i.next();
- if (querry == null) // all providers
- continue;
-
- querry = querry.trim();
- if (querry.length() == 0) // all providers
- continue;
-
- dot = querry.indexOf('.');
- if (dot == -1) // syntax error
- throw new InvalidParameterException(
- "missing dot in '" + String.valueOf(querry)+"'");
-
- value = (String) filter.get(querry);
- // deconstruct querry into [service, algorithm, attribute]
- if (value == null || value.trim().length() == 0) // .
- {
- value = null;
- attribute = null;
- service = querry.substring(0, dot).trim();
- algorithm = querry.substring(dot+1).trim();
- }
- else // .
- {
- ws = querry.indexOf(' ');
- if (ws == -1)
- throw new InvalidParameterException(
- "value (" + String.valueOf(value) +
- ") is not empty, but querry (" + String.valueOf(querry) +
- ") is missing at least one space character");
- value = value.trim();
- attribute = querry.substring(ws+1).trim();
- // was the dot in the attribute?
- if (attribute.indexOf('.') != -1)
- throw new InvalidParameterException(
- "attribute_name (" + String.valueOf(attribute) +
- ") in querry (" + String.valueOf(querry) + ") contains a dot");
-
- querry = querry.substring(0, ws).trim();
- service = querry.substring(0, dot).trim();
- algorithm = querry.substring(dot+1).trim();
- }
-
- // service and algorithm must not be empty
- if (service.length() == 0)
- throw new InvalidParameterException(
- " in querry (" + String.valueOf(querry) +
- ") is empty");
-
- if (algorithm.length() == 0)
- throw new InvalidParameterException(
- " in querry (" + String.valueOf(querry) +
- ") is empty");
-
- selectProviders(service, algorithm, attribute, value, result, serviceProviders);
- result.retainAll(serviceProviders); // eval next retaining found providers
- if (result.isEmpty()) // no point continuing
- break;
- }
-
- if (result.isEmpty())
- return null;
-
- return (Provider[]) result.toArray(new Provider[result.size()]);
- }
-
- private static void selectProviders(String svc, String algo, String attr,
- String val, LinkedHashSet providerSet,
- LinkedHashSet result)
- {
- result.clear(); // ensure we start with an empty result set
- for (Iterator i = providerSet.iterator(); i.hasNext(); )
- {
- Provider p = (Provider) i.next();
- if (provides(p, svc, algo, attr, val))
- result.add(p);
- }
- }
-
- private static boolean provides(Provider p, String svc, String algo,
- String attr, String val)
- {
- Iterator it;
- String serviceDotAlgorithm = null;
- String key = null;
- String realVal;
- boolean found = false;
- // if . is in the set then so is .
- // but it may be stored under an alias . resolve
- outer: for (int r = 0; r < 3; r++) // guard against circularity
- {
- serviceDotAlgorithm = (svc+"."+String.valueOf(algo)).trim();
- for (it = p.keySet().iterator(); it.hasNext(); )
- {
- key = (String) it.next();
- if (key.equalsIgnoreCase(serviceDotAlgorithm)) // eureka
- {
- found = true;
- break outer;
- }
- // it may be there but as an alias
- if (key.equalsIgnoreCase(ALG_ALIAS + serviceDotAlgorithm))
- {
- algo = p.getProperty(key);
- continue outer;
- }
- // else continue inner
- }
- }
-
- if (!found)
- return false;
-
- // found a candidate for the querry. do we have an attr to match?
- if (val == null) // . querry
- return true;
-
- // . ; find the key entry that match
- String realAttr;
- int limit = serviceDotAlgorithm.length() + 1;
- for (it = p.keySet().iterator(); it.hasNext(); )
- {
- key = (String) it.next();
- if (key.length() <= limit)
- continue;
-
- if (key.substring(0, limit).equalsIgnoreCase(serviceDotAlgorithm+" "))
- {
- realAttr = key.substring(limit).trim();
- if (! realAttr.equalsIgnoreCase(attr))
- continue;
-
- // eveything matches so far. do the value
- realVal = p.getProperty(key);
- if (realVal == null)
- return false;
-
- realVal = realVal.trim();
- // is it a string value?
- if (val.equalsIgnoreCase(realVal))
- return true;
-
- // assume value is a number. cehck for greater-than-or-equal
- return (new Integer(val).intValue() >= new Integer(realVal).intValue());
- }
- }
-
- return false;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,10 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public interface ASN1ApplicationSpecificParser
- extends DEREncodable
-{
- DEREncodable readObject()
- throws IOException;
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1Choice.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1Choice.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1Choice.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1Choice.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,14 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * Marker interface for CHOICE objects - if you implement this in a role your
- * own object any attempt to tag the object implicitly will convert the tag to
- * an explicit one as the encoding rules require.
- *
- * If you use this interface your class should also implement the getInstance
- * pattern which takes a tag object and the tagging mode used.
- */
-public interface ASN1Choice
-{
- // marker interface
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1Encodable.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1Encodable.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1Encodable.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1Encodable.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,102 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-/**
- * Base class for objects which can be written directly to ASN.1 output streams.
- */
-public abstract class ASN1Encodable
- implements DEREncodable
-{
- public static final String DER = "DER";
- public static final String BER = "BER";
-
- /**
- * Return the default BER or DER encoding for this object.
- *
- * @return BER/DER byte encoded object.
- * @throws IOException on encoding error.
- */
- public byte[] getEncoded()
- throws IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- aOut.writeObject(this);
-
- return bOut.toByteArray();
- }
-
- /**
- * Return either the default for "BER" or a DER encoding if "DER" is specified.
- *
- * @param encoding name of encoding to use.
- * @return byte encoded object.
- * @throws IOException on encoding error.
- */
- public byte[] getEncoded(
- String encoding)
- throws IOException
- {
- if (encoding.equals(DER))
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DEROutputStream dOut = new DEROutputStream(bOut);
-
- dOut.writeObject(this);
-
- return bOut.toByteArray();
- }
-
- return this.getEncoded();
- }
-
- /**
- * Return the DER encoding of the object, null if the DER encoding can not be made.
- *
- * @return a DER byte array, null otherwise.
- */
- public byte[] getDEREncoded()
- {
- try
- {
- return this.getEncoded(DER);
- }
- catch (IOException e)
- {
- return null;
- }
- }
-
- public int hashCode()
- {
- return this.toASN1Object().hashCode();
- }
-
- public boolean equals(
- Object o)
- {
- if (this == o)
- {
- return true;
- }
-
- if (!(o instanceof DEREncodable))
- {
- return false;
- }
-
- DEREncodable other = (DEREncodable)o;
-
- return this.toASN1Object().equals(other.getDERObject());
- }
-
- public DERObject getDERObject()
- {
- return this.toASN1Object();
- }
-
- public abstract DERObject toASN1Object();
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1EncodableVector.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1EncodableVector.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1EncodableVector.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1EncodableVector.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,14 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * the parent class for this will eventually disappear. Use this one!
- */
-public class ASN1EncodableVector
- extends DEREncodableVector
-{
- // migrating from DEREncodeableVector
- public ASN1EncodableVector()
- {
-
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1InputStream.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1InputStream.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1InputStream.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1InputStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,386 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.EOFException;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.util.io.Streams;
-
-/**
- * a general purpose ASN.1 decoder - note: this class differs from the
- * others in that it returns null after it has read the last object in
- * the stream. If an ASN.1 NULL is encountered a DER/BER Null object is
- * returned.
- */
-public class ASN1InputStream
- extends FilterInputStream
- implements DERTags
-{
- private final int limit;
- private final boolean lazyEvaluate;
-
- public ASN1InputStream(
- InputStream is)
- {
- this(is, Integer.MAX_VALUE);
- }
-
- /**
- * Create an ASN1InputStream based on the input byte array. The length of DER objects in
- * the stream is automatically limited to the length of the input array.
- *
- * @param input array containing ASN.1 encoded data.
- */
- public ASN1InputStream(
- byte[] input)
- {
- this(new ByteArrayInputStream(input), input.length);
- }
-
- /**
- * Create an ASN1InputStream based on the input byte array. The length of DER objects in
- * the stream is automatically limited to the length of the input array.
- *
- * @param input array containing ASN.1 encoded data.
- * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
- */
- public ASN1InputStream(
- byte[] input,
- boolean lazyEvaluate)
- {
- this(new ByteArrayInputStream(input), input.length, lazyEvaluate);
- }
-
- /**
- * Create an ASN1InputStream where no DER object will be longer than limit.
- *
- * @param input stream containing ASN.1 encoded data.
- * @param limit maximum size of a DER encoded object.
- */
- public ASN1InputStream(
- InputStream input,
- int limit)
- {
- this(input, limit, false);
- }
-
- /**
- * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
- * objects such as sequences will be parsed lazily.
- *
- * @param input stream containing ASN.1 encoded data.
- * @param limit maximum size of a DER encoded object.
- * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
- */
- public ASN1InputStream(
- InputStream input,
- int limit,
- boolean lazyEvaluate)
- {
- super(input);
- this.limit = limit;
- this.lazyEvaluate = lazyEvaluate;
- }
-
- protected int readLength()
- throws IOException
- {
- return readLength(this, limit);
- }
-
- protected void readFully(
- byte[] bytes)
- throws IOException
- {
- if (Streams.readFully(this, bytes) != bytes.length)
- {
- throw new EOFException("EOF encountered in middle of object");
- }
- }
-
- /**
- * build an object given its tag and the number of bytes to construct it from.
- */
- protected DERObject buildObject(
- int tag,
- int tagNo,
- int length)
- throws IOException
- {
- boolean isConstructed = (tag & CONSTRUCTED) != 0;
-
- DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this, length);
-
- if ((tag & APPLICATION) != 0)
- {
- return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
- }
-
- if ((tag & TAGGED) != 0)
- {
- return new BERTaggedObjectParser(tag, tagNo, defIn).getDERObject();
- }
-
- if (isConstructed)
- {
- // TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagNo)
- {
- case OCTET_STRING:
- //
- // yes, people actually do this...
- //
- return new BERConstructedOctetString(buildDEREncodableVector(defIn).v);
- case SEQUENCE:
- if (lazyEvaluate)
- {
- return new LazyDERSequence(defIn.toByteArray());
- }
- else
- {
- return DERFactory.createSequence(buildDEREncodableVector(defIn));
- }
- case SET:
- return DERFactory.createSet(buildDEREncodableVector(defIn), false);
- case EXTERNAL:
- return new DERExternal(buildDEREncodableVector(defIn));
- default:
- return new DERUnknownTag(true, tagNo, defIn.toByteArray());
- }
- }
-
- return createPrimitiveDERObject(tagNo, defIn.toByteArray());
- }
-
- ASN1EncodableVector buildEncodableVector()
- throws IOException
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
- DERObject o;
-
- while ((o = readObject()) != null)
- {
- v.add(o);
- }
-
- return v;
- }
-
- ASN1EncodableVector buildDEREncodableVector(
- DefiniteLengthInputStream dIn) throws IOException
- {
- return new ASN1InputStream(dIn).buildEncodableVector();
- }
-
- public DERObject readObject()
- throws IOException
- {
- int tag = read();
- if (tag <= 0)
- {
- if (tag == 0)
- {
- throw new IOException("unexpected end-of-contents marker");
- }
-
- return null;
- }
-
- //
- // calculate tag number
- //
- int tagNo = readTagNumber(this, tag);
-
- boolean isConstructed = (tag & CONSTRUCTED) != 0;
-
- //
- // calculate length
- //
- int length = readLength();
-
- if (length < 0) // indefinite length method
- {
- if (!isConstructed)
- {
- throw new IOException("indefinite length primitive encoding encountered");
- }
-
- IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this);
-
- if ((tag & APPLICATION) != 0)
- {
- ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
-
- return new BERApplicationSpecificParser(tagNo, sp).getDERObject();
- }
- if ((tag & TAGGED) != 0)
- {
- return new BERTaggedObjectParser(tag, tagNo, indIn).getDERObject();
- }
-
- ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
-
- // TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagNo)
- {
- case OCTET_STRING:
- return new BEROctetStringParser(sp).getDERObject();
- case SEQUENCE:
- return new BERSequenceParser(sp).getDERObject();
- case SET:
- return new BERSetParser(sp).getDERObject();
- case EXTERNAL:
- return new DERExternalParser(sp).getDERObject();
- default:
- throw new IOException("unknown BER object encountered");
- }
- }
- else
- {
- return buildObject(tag, tagNo, length);
- }
- }
-
- static int readTagNumber(InputStream s, int tag)
- throws IOException
- {
- int tagNo = tag & 0x1f;
-
- //
- // with tagged object tag number is bottom 5 bits, or stored at the start of the content
- //
- if (tagNo == 0x1f)
- {
- tagNo = 0;
-
- int b = s.read();
-
- // X.690-0207 8.1.2.4.2
- // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
- if ((b & 0x7f) == 0) // Note: -1 will pass
- {
- throw new IOException("corrupted stream - invalid high tag number found");
- }
-
- while ((b >= 0) && ((b & 0x80) != 0))
- {
- tagNo |= (b & 0x7f);
- tagNo <<= 7;
- b = s.read();
- }
-
- if (b < 0)
- {
- throw new EOFException("EOF found inside tag value.");
- }
-
- tagNo |= (b & 0x7f);
- }
-
- return tagNo;
- }
-
- static int readLength(InputStream s, int limit)
- throws IOException
- {
- int length = s.read();
- if (length < 0)
- {
- throw new EOFException("EOF found when length expected");
- }
-
- if (length == 0x80)
- {
- return -1; // indefinite-length encoding
- }
-
- if (length > 127)
- {
- int size = length & 0x7f;
-
- if (size > 4)
- {
- throw new IOException("DER length more than 4 bytes: " + size);
- }
-
- length = 0;
- for (int i = 0; i < size; i++)
- {
- int next = s.read();
-
- if (next < 0)
- {
- throw new EOFException("EOF found reading length");
- }
-
- length = (length << 8) + next;
- }
-
- if (length < 0)
- {
- throw new IOException("corrupted stream - negative length found");
- }
-
- if (length >= limit) // after all we must have read at least 1 byte
- {
- throw new IOException("corrupted stream - out of bounds length found");
- }
- }
-
- return length;
- }
-
- static DERObject createPrimitiveDERObject(
- int tagNo,
- byte[] bytes)
- {
- switch (tagNo)
- {
- case BIT_STRING:
- {
- int padBits = bytes[0];
- byte[] data = new byte[bytes.length - 1];
- System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
- return new DERBitString(data, padBits);
- }
- case BMP_STRING:
- return new DERBMPString(bytes);
- case BOOLEAN:
- return new DERBoolean(bytes);
- case ENUMERATED:
- return new DEREnumerated(bytes);
- case GENERALIZED_TIME:
- return new DERGeneralizedTime(bytes);
- case GENERAL_STRING:
- return new DERGeneralString(bytes);
- case IA5_STRING:
- return new DERIA5String(bytes);
- case INTEGER:
- return new DERInteger(bytes);
- case NULL:
- return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?)
- case NUMERIC_STRING:
- return new DERNumericString(bytes);
- case OBJECT_IDENTIFIER:
- return new DERObjectIdentifier(bytes);
- case OCTET_STRING:
- return new DEROctetString(bytes);
- case PRINTABLE_STRING:
- return new DERPrintableString(bytes);
- case T61_STRING:
- return new DERT61String(bytes);
- case UNIVERSAL_STRING:
- return new DERUniversalString(bytes);
- case UTC_TIME:
- return new DERUTCTime(bytes);
- case UTF8_STRING:
- return new DERUTF8String(bytes);
- case VISIBLE_STRING:
- return new DERVisibleString(bytes);
- default:
- return new DERUnknownTag(false, tagNo, bytes);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1Null.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1Null.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1Null.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1Null.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * A NULL object.
- */
-public abstract class ASN1Null
- extends ASN1Object
-{
- public ASN1Null()
- {
- }
-
- public int hashCode()
- {
- return -1;
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof ASN1Null))
- {
- return false;
- }
-
- return true;
- }
-
- abstract void encode(DEROutputStream out)
- throws IOException;
-
- public String toString()
- {
- return "NULL";
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1Object.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1Object.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1Object.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1Object.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public abstract class ASN1Object
- extends DERObject
-{
- /**
- * Create a base ASN.1 object from a byte stream.
- *
- * @param data the byte stream to parse.
- * @return the base ASN.1 object represented by the byte stream.
- * @exception IOException if there is a problem parsing the data.
- */
- public static ASN1Object fromByteArray(byte[] data)
- throws IOException
- {
- ASN1InputStream aIn = new ASN1InputStream(data);
-
- return (ASN1Object)aIn.readObject();
- }
-
- public final boolean equals(Object o)
- {
- if (this == o)
- {
- return true;
- }
-
- return (o instanceof DEREncodable) && asn1Equals(((DEREncodable)o).getDERObject());
- }
-
- public abstract int hashCode();
-
- abstract void encode(DEROutputStream out) throws IOException;
-
- abstract boolean asn1Equals(DERObject o);
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1ObjectParser.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1ObjectParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1ObjectParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1ObjectParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,19 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.InputStream;
-
-/**
- * @deprecated will be removed
- */
-public class ASN1ObjectParser
-{
- ASN1StreamParser _aIn;
-
- protected ASN1ObjectParser(
- int baseTag,
- int tagNumber,
- InputStream contentStream)
- {
- _aIn = new ASN1StreamParser(contentStream);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1OctetString.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1OctetString.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1OctetString.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1OctetString.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,135 +0,0 @@
-package org.bouncycastle.asn1;
-
-import org.bouncycastle.util.encoders.Hex;
-import org.bouncycastle.util.Arrays;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Enumeration;
-import java.util.Vector;
-
-public abstract class ASN1OctetString
- extends ASN1Object
- implements ASN1OctetStringParser
-{
- byte[] string;
-
- /**
- * return an Octet String from a tagged object.
- *
- * @param obj the tagged object holding the object we want.
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1OctetString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- /**
- * return an Octet String from the given object.
- *
- * @param obj the object we want converted.
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1OctetString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1OctetString)
- {
- return (ASN1OctetString)obj;
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- if (obj instanceof ASN1Sequence)
- {
- Vector v = new Vector();
- Enumeration e = ((ASN1Sequence)obj).getObjects();
-
- while (e.hasMoreElements())
- {
- v.addElement(e.nextElement());
- }
-
- return new BERConstructedOctetString(v);
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * @param string the octets making up the octet string.
- */
- public ASN1OctetString(
- byte[] string)
- {
- if (string == null)
- {
- throw new NullPointerException("string cannot be null");
- }
- this.string = string;
- }
-
- public ASN1OctetString(
- DEREncodable obj)
- {
- try
- {
- this.string = obj.getDERObject().getEncoded(ASN1Encodable.DER);
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("Error processing object : " + e.toString());
- }
- }
-
- public InputStream getOctetStream()
- {
- return new ByteArrayInputStream(string);
- }
-
- public ASN1OctetStringParser parser()
- {
- return this;
- }
-
- public byte[] getOctets()
- {
- return string;
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(this.getOctets());
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof ASN1OctetString))
- {
- return false;
- }
-
- ASN1OctetString other = (ASN1OctetString)o;
-
- return Arrays.areEqual(string, other.string);
- }
-
- abstract void encode(DEROutputStream out)
- throws IOException;
-
- public String toString()
- {
- return "#"+new String(Hex.encode(string));
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1OctetStringParser.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1OctetStringParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1OctetStringParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1OctetStringParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,9 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.InputStream;
-
-public interface ASN1OctetStringParser
- extends DEREncodable
-{
- public InputStream getOctetStream();
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1OutputStream.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1OutputStream.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1OutputStream.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1OutputStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,36 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class ASN1OutputStream
- extends DEROutputStream
-{
- public ASN1OutputStream(
- OutputStream os)
- {
- super(os);
- }
-
- public void writeObject(
- Object obj)
- throws IOException
- {
- if (obj == null)
- {
- writeNull();
- }
- else if (obj instanceof DERObject)
- {
- ((DERObject)obj).encode(this);
- }
- else if (obj instanceof DEREncodable)
- {
- ((DEREncodable)obj).getDERObject().encode(this);
- }
- else
- {
- throw new IOException("object not ASN1Encodable");
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1ParsingException.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1ParsingException.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1ParsingException.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1ParsingException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,23 +0,0 @@
-package org.bouncycastle.asn1;
-
-public class ASN1ParsingException
- extends IllegalStateException
-{
- private Throwable cause;
-
- ASN1ParsingException(String message)
- {
- super(message);
- }
-
- ASN1ParsingException(String message, Throwable cause)
- {
- super(message);
- this.cause = cause;
- }
-
- public Throwable getCause()
- {
- return cause;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1Sequence.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1Sequence.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1Sequence.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1Sequence.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,217 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-public abstract class ASN1Sequence
- extends ASN1Object
-{
- private Vector seq = new Vector();
-
- /**
- * return an ASN1Sequence from the given object.
- *
- * @param obj the object we want converted.
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1Sequence getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1Sequence)
- {
- return (ASN1Sequence)obj;
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * Return an ASN1 sequence from a tagged object. There is a special
- * case here, if an object appears to have been explicitly tagged on
- * reading but we were expecting it to be implicitly tagged in the
- * normal course of events it indicates that we lost the surrounding
- * sequence - so we need to add it back (this will happen if the tagged
- * object is a sequence that contains other sequences). If you are
- * dealing with implicitly tagged sequences you really should
- * be using this method.
- *
- * @param obj the tagged object.
- * @param explicit true if the object is meant to be explicitly tagged,
- * false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1Sequence getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- if (explicit)
- {
- if (!obj.isExplicit())
- {
- throw new IllegalArgumentException("object implicit - explicit expected.");
- }
-
- return (ASN1Sequence)obj.getObject();
- }
- else
- {
- //
- // constructed object which appears to be explicitly tagged
- // when it should be implicit means we have to add the
- // surrounding sequence.
- //
- if (obj.isExplicit())
- {
- if (obj instanceof BERTaggedObject)
- {
- return new BERSequence(obj.getObject());
- }
- else
- {
- return new DERSequence(obj.getObject());
- }
- }
- else
- {
- if (obj.getObject() instanceof ASN1Sequence)
- {
- return (ASN1Sequence)obj.getObject();
- }
- }
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- public Enumeration getObjects()
- {
- return seq.elements();
- }
-
- public ASN1SequenceParser parser()
- {
- final ASN1Sequence outer = this;
-
- return new ASN1SequenceParser()
- {
- private final int max = size();
-
- private int index;
-
- public DEREncodable readObject() throws IOException
- {
- if (index == max)
- {
- return null;
- }
-
- DEREncodable obj = getObjectAt(index++);
- if (obj instanceof ASN1Sequence)
- {
- return ((ASN1Sequence)obj).parser();
- }
- if (obj instanceof ASN1Set)
- {
- return ((ASN1Set)obj).parser();
- }
-
- return obj;
- }
-
- public DERObject getDERObject()
- {
- return outer;
- }
- };
- }
-
- /**
- * return the object at the sequence position indicated by index.
- *
- * @param index the sequence number (starting at zero) of the object
- * @return the object at the sequence position indicated by index.
- */
- public DEREncodable getObjectAt(
- int index)
- {
- return (DEREncodable)seq.elementAt(index);
- }
-
- /**
- * return the number of objects in this sequence.
- *
- * @return the number of objects in this sequence.
- */
- public int size()
- {
- return seq.size();
- }
-
- public int hashCode()
- {
- Enumeration e = this.getObjects();
- int hashCode = size();
-
- while (e.hasMoreElements())
- {
- Object o = e.nextElement();
- hashCode *= 17;
- if (o != null)
- {
- hashCode ^= o.hashCode();
- }
- }
-
- return hashCode;
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof ASN1Sequence))
- {
- return false;
- }
-
- ASN1Sequence other = (ASN1Sequence)o;
-
- if (this.size() != other.size())
- {
- return false;
- }
-
- Enumeration s1 = this.getObjects();
- Enumeration s2 = other.getObjects();
-
- while (s1.hasMoreElements())
- {
- DERObject o1 = ((DEREncodable)s1.nextElement()).getDERObject();
- DERObject o2 = ((DEREncodable)s2.nextElement()).getDERObject();
-
- if (o1 == o2 || (o1 != null && o1.equals(o2)))
- {
- continue;
- }
-
- return false;
- }
-
- return true;
- }
-
- protected void addObject(
- DEREncodable obj)
- {
- seq.addElement(obj);
- }
-
- abstract void encode(DEROutputStream out)
- throws IOException;
-
- public String toString()
- {
- return seq.toString();
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1SequenceParser.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1SequenceParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1SequenceParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1SequenceParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,10 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public interface ASN1SequenceParser
- extends DEREncodable
-{
- DEREncodable readObject()
- throws IOException;
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1Set.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1Set.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1Set.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1Set.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,343 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-abstract public class ASN1Set
- extends ASN1Object
-{
- protected Vector set = new Vector();
-
- /**
- * return an ASN1Set from the given object.
- *
- * @param obj the object we want converted.
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static ASN1Set getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1Set)
- {
- return (ASN1Set)obj;
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * Return an ASN1 set from a tagged object. There is a special
- * case here, if an object appears to have been explicitly tagged on
- * reading but we were expecting it to be implicitly tagged in the
- * normal course of events it indicates that we lost the surrounding
- * set - so we need to add it back (this will happen if the tagged
- * object is a sequence that contains other sequences). If you are
- * dealing with implicitly tagged sets you really should
- * be using this method.
- *
- * @param obj the tagged object.
- * @param explicit true if the object is meant to be explicitly tagged
- * false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static ASN1Set getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- if (explicit)
- {
- if (!obj.isExplicit())
- {
- throw new IllegalArgumentException("object implicit - explicit expected.");
- }
-
- return (ASN1Set)obj.getObject();
- }
- else
- {
- //
- // constructed object which appears to be explicitly tagged
- // and it's really implicit means we have to add the
- // surrounding sequence.
- //
- if (obj.isExplicit())
- {
- ASN1Set set = new DERSet(obj.getObject());
-
- return set;
- }
- else
- {
- if (obj.getObject() instanceof ASN1Set)
- {
- return (ASN1Set)obj.getObject();
- }
-
- //
- // in this case the parser returns a sequence, convert it
- // into a set.
- //
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- if (obj.getObject() instanceof ASN1Sequence)
- {
- ASN1Sequence s = (ASN1Sequence)obj.getObject();
- Enumeration e = s.getObjects();
-
- while (e.hasMoreElements())
- {
- v.add((DEREncodable)e.nextElement());
- }
-
- return new DERSet(v, false);
- }
- }
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- public ASN1Set()
- {
- }
-
- public Enumeration getObjects()
- {
- return set.elements();
- }
-
- /**
- * return the object at the set position indicated by index.
- *
- * @param index the set number (starting at zero) of the object
- * @return the object at the set position indicated by index.
- */
- public DEREncodable getObjectAt(
- int index)
- {
- return (DEREncodable)set.elementAt(index);
- }
-
- /**
- * return the number of objects in this set.
- *
- * @return the number of objects in this set.
- */
- public int size()
- {
- return set.size();
- }
-
- public ASN1SetParser parser()
- {
- final ASN1Set outer = this;
-
- return new ASN1SetParser()
- {
- private final int max = size();
-
- private int index;
-
- public DEREncodable readObject() throws IOException
- {
- if (index == max)
- {
- return null;
- }
-
- DEREncodable obj = getObjectAt(index++);
- if (obj instanceof ASN1Sequence)
- {
- return ((ASN1Sequence)obj).parser();
- }
- if (obj instanceof ASN1Set)
- {
- return ((ASN1Set)obj).parser();
- }
-
- return obj;
- }
-
- public DERObject getDERObject()
- {
- return outer;
- }
- };
- }
-
- public int hashCode()
- {
- Enumeration e = this.getObjects();
- int hashCode = size();
-
- while (e.hasMoreElements())
- {
- Object o = e.nextElement();
- hashCode *= 17;
- if (o != null)
- {
- hashCode ^= o.hashCode();
- }
- }
-
- return hashCode;
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof ASN1Set))
- {
- return false;
- }
-
- ASN1Set other = (ASN1Set)o;
-
- if (this.size() != other.size())
- {
- return false;
- }
-
- Enumeration s1 = this.getObjects();
- Enumeration s2 = other.getObjects();
-
- while (s1.hasMoreElements())
- {
- DERObject o1 = ((DEREncodable)s1.nextElement()).getDERObject();
- DERObject o2 = ((DEREncodable)s2.nextElement()).getDERObject();
-
- if (o1 == o2 || (o1 != null && o1.equals(o2)))
- {
- continue;
- }
-
- return false;
- }
-
- return true;
- }
-
- /**
- * return true if a <= b (arrays are assumed padded with zeros).
- */
- private boolean lessThanOrEqual(
- byte[] a,
- byte[] b)
- {
- if (a.length <= b.length)
- {
- for (int i = 0; i != a.length; i++)
- {
- int l = a[i] & 0xff;
- int r = b[i] & 0xff;
-
- if (r > l)
- {
- return true;
- }
- else if (l > r)
- {
- return false;
- }
- }
-
- return true;
- }
- else
- {
- for (int i = 0; i != b.length; i++)
- {
- int l = a[i] & 0xff;
- int r = b[i] & 0xff;
-
- if (r > l)
- {
- return true;
- }
- else if (l > r)
- {
- return false;
- }
- }
-
- return false;
- }
- }
-
- private byte[] getEncoded(
- DEREncodable obj)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- try
- {
- aOut.writeObject(obj);
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("cannot encode object added to SET");
- }
-
- return bOut.toByteArray();
- }
-
- protected void sort()
- {
- if (set.size() > 1)
- {
- boolean swapped = true;
- int lastSwap = set.size() - 1;
-
- while (swapped)
- {
- int index = 0;
- int swapIndex = 0;
- byte[] a = getEncoded((DEREncodable)set.elementAt(0));
-
- swapped = false;
-
- while (index != lastSwap)
- {
- byte[] b = getEncoded((DEREncodable)set.elementAt(index + 1));
-
- if (lessThanOrEqual(a, b))
- {
- a = b;
- }
- else
- {
- Object o = set.elementAt(index);
-
- set.setElementAt(set.elementAt(index + 1), index);
- set.setElementAt(o, index + 1);
-
- swapped = true;
- swapIndex = index;
- }
-
- index++;
- }
-
- lastSwap = swapIndex;
- }
- }
- }
-
- protected void addObject(
- DEREncodable obj)
- {
- set.addElement(obj);
- }
-
- abstract void encode(DEROutputStream out)
- throws IOException;
-
- public String toString()
- {
- return set.toString();
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1SetParser.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1SetParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1SetParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1SetParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,10 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public interface ASN1SetParser
- extends DEREncodable
-{
- public DEREncodable readObject()
- throws IOException;
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1StreamParser.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1StreamParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1StreamParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1StreamParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,174 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-public class ASN1StreamParser
-{
- private final InputStream _in;
- private final int _limit;
-
- private static int findLimit(InputStream in)
- {
- if (in instanceof DefiniteLengthInputStream)
- {
- return ((DefiniteLengthInputStream)in).getRemaining();
- }
-
- return Integer.MAX_VALUE;
- }
-
- public ASN1StreamParser(
- InputStream in)
- {
- this(in, findLimit(in));
- }
-
- public ASN1StreamParser(
- InputStream in,
- int limit)
- {
- this._in = in;
- this._limit = limit;
- }
-
- public ASN1StreamParser(
- byte[] encoding)
- {
- this(new ByteArrayInputStream(encoding), encoding.length);
- }
-
- public DEREncodable readObject()
- throws IOException
- {
- int tag = _in.read();
- if (tag == -1)
- {
- return null;
- }
-
- //
- // turn of looking for "00" while we resolve the tag
- //
- set00Check(false);
-
- //
- // calculate tag number
- //
- int tagNo = ASN1InputStream.readTagNumber(_in, tag);
-
- boolean isConstructed = (tag & DERTags.CONSTRUCTED) != 0;
-
- //
- // calculate length
- //
- int length = ASN1InputStream.readLength(_in, _limit);
-
- if (length < 0) // indefinite length method
- {
- if (!isConstructed)
- {
- throw new IOException("indefinite length primitive encoding encountered");
- }
-
- IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in);
-
- if ((tag & DERTags.APPLICATION) != 0)
- {
- ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
-
- return new BERApplicationSpecificParser(tagNo, sp);
- }
-
- if ((tag & DERTags.TAGGED) != 0)
- {
- return new BERTaggedObjectParser(tag, tagNo, indIn);
- }
-
- ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
-
- // TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagNo)
- {
- case DERTags.OCTET_STRING:
- return new BEROctetStringParser(sp);
- case DERTags.SEQUENCE:
- return new BERSequenceParser(sp);
- case DERTags.SET:
- return new BERSetParser(sp);
- case DERTags.EXTERNAL:{
- return new DERExternalParser(sp);
- }
- default:
- throw new IOException("unknown BER object encountered: 0x" + Integer.toHexString(tagNo));
- }
- }
- else
- {
- DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
-
- if ((tag & DERTags.APPLICATION) != 0)
- {
- return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
- }
-
- if ((tag & DERTags.TAGGED) != 0)
- {
- return new BERTaggedObjectParser(tag, tagNo, defIn);
- }
-
- if (isConstructed)
- {
- // TODO There are other tags that may be constructed (e.g. BIT_STRING)
- switch (tagNo)
- {
- case DERTags.OCTET_STRING:
- //
- // yes, people actually do this...
- //
- return new BEROctetStringParser(new ASN1StreamParser(defIn));
- case DERTags.SEQUENCE:
- return new DERSequenceParser(new ASN1StreamParser(defIn));
- case DERTags.SET:
- return new DERSetParser(new ASN1StreamParser(defIn));
- case DERTags.EXTERNAL:
- return new DERExternalParser(new ASN1StreamParser(defIn));
- default:
- // TODO Add DERUnknownTagParser class?
- return new DERUnknownTag(true, tagNo, defIn.toByteArray());
- }
- }
-
- // Some primitive encodings can be handled by parsers too...
- switch (tagNo)
- {
- case DERTags.OCTET_STRING:
- return new DEROctetStringParser(defIn);
- }
-
- return ASN1InputStream.createPrimitiveDERObject(tagNo, defIn.toByteArray());
- }
- }
-
- private void set00Check(boolean enabled)
- {
- if (_in instanceof IndefiniteLengthInputStream)
- {
- ((IndefiniteLengthInputStream)_in).setEofOn00(enabled);
- }
- }
-
- ASN1EncodableVector readVector() throws IOException
- {
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- DEREncodable obj;
- while ((obj = readObject()) != null)
- {
- v.add(obj.getDERObject());
- }
-
- return v;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1TaggedObject.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1TaggedObject.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1TaggedObject.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1TaggedObject.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,210 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
- * a [n] where n is some number - these are assumed to follow the construction
- * rules (as with sequences).
- */
-public abstract class ASN1TaggedObject
- extends ASN1Object
- implements ASN1TaggedObjectParser
-{
- int tagNo;
- boolean empty = false;
- boolean explicit = true;
- DEREncodable obj = null;
-
- static public ASN1TaggedObject getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- if (explicit)
- {
- return (ASN1TaggedObject)obj.getObject();
- }
-
- throw new IllegalArgumentException("implicitly tagged tagged object");
- }
-
- static public ASN1TaggedObject getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof ASN1TaggedObject)
- {
- return (ASN1TaggedObject)obj;
- }
-
- throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * Create a tagged object in the explicit style.
- *
- * @param tagNo the tag number for this object.
- * @param obj the tagged object.
- */
- public ASN1TaggedObject(
- int tagNo,
- DEREncodable obj)
- {
- this.explicit = true;
- this.tagNo = tagNo;
- this.obj = obj;
- }
-
- /**
- * Create a tagged object with the style given by the value of explicit.
- *
- * If the object implements ASN1Choice the tag style will always be changed
- * to explicit in accordance with the ASN.1 encoding rules.
- *
- * @param explicit true if the object is explicitly tagged.
- * @param tagNo the tag number for this object.
- * @param obj the tagged object.
- */
- public ASN1TaggedObject(
- boolean explicit,
- int tagNo,
- DEREncodable obj)
- {
- if (obj instanceof ASN1Choice)
- {
- this.explicit = true;
- }
- else
- {
- this.explicit = explicit;
- }
-
- this.tagNo = tagNo;
- this.obj = obj;
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof ASN1TaggedObject))
- {
- return false;
- }
-
- ASN1TaggedObject other = (ASN1TaggedObject)o;
-
- if (tagNo != other.tagNo || empty != other.empty || explicit != other.explicit)
- {
- return false;
- }
-
- if(obj == null)
- {
- if (other.obj != null)
- {
- return false;
- }
- }
- else
- {
- if (!(obj.getDERObject().equals(other.obj.getDERObject())))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public int hashCode()
- {
- int code = tagNo;
-
- // TODO: actually this is wrong - the problem is that a re-encoded
- // object may end up with a different hashCode due to implicit
- // tagging. As implicit tagging is ambiguous if a sequence is involved
- // it seems the only correct method for both equals and hashCode is to
- // compare the encodings...
- if (obj != null)
- {
- code ^= obj.hashCode();
- }
-
- return code;
- }
-
- public int getTagNo()
- {
- return tagNo;
- }
-
- /**
- * return whether or not the object may be explicitly tagged.
- *
- * Note: if the object has been read from an input stream, the only
- * time you can be sure if isExplicit is returning the true state of
- * affairs is if it returns false. An implicitly tagged object may appear
- * to be explicitly tagged, so you need to understand the context under
- * which the reading was done as well, see getObject below.
- */
- public boolean isExplicit()
- {
- return explicit;
- }
-
- public boolean isEmpty()
- {
- return empty;
- }
-
- /**
- * return whatever was following the tag.
- *
- * Note: tagged objects are generally context dependent if you're
- * trying to extract a tagged object you should be going via the
- * appropriate getInstance method.
- */
- public DERObject getObject()
- {
- if (obj != null)
- {
- return obj.getDERObject();
- }
-
- return null;
- }
-
- /**
- * Return the object held in this tagged object as a parser assuming it has
- * the type of the passed in tag. If the object doesn't have a parser
- * associated with it, the base object is returned.
- */
- public DEREncodable getObjectParser(
- int tag,
- boolean isExplicit)
- {
- switch (tag)
- {
- case DERTags.SET:
- return ASN1Set.getInstance(this, isExplicit).parser();
- case DERTags.SEQUENCE:
- return ASN1Sequence.getInstance(this, isExplicit).parser();
- case DERTags.OCTET_STRING:
- return ASN1OctetString.getInstance(this, isExplicit).parser();
- }
-
- if (isExplicit)
- {
- return getObject();
- }
-
- throw new RuntimeException("implicit tagging not implemented for tag: " + tag);
- }
-
- abstract void encode(DEROutputStream out)
- throws IOException;
-
- public String toString()
- {
- return "[" + tagNo + "]" + obj;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java pdftk-2.01/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ASN1TaggedObjectParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,12 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public interface ASN1TaggedObjectParser
- extends DEREncodable
-{
- public int getTagNo();
-
- public DEREncodable getObjectParser(int tag, boolean isExplicit)
- throws IOException;
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERApplicationSpecific.java pdftk-2.01/java/org/bouncycastle/asn1/BERApplicationSpecific.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERApplicationSpecific.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERApplicationSpecific.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,10 +0,0 @@
-package org.bouncycastle.asn1;
-
-public class BERApplicationSpecific
- extends DERApplicationSpecific
-{
- public BERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
- {
- super(tagNo, vec);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java pdftk-2.01/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERApplicationSpecificParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,34 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class BERApplicationSpecificParser
- implements ASN1ApplicationSpecificParser
-{
- private final int tag;
- private final ASN1StreamParser parser;
-
- BERApplicationSpecificParser(int tag, ASN1StreamParser parser)
- {
- this.tag = tag;
- this.parser = parser;
- }
-
- public DEREncodable readObject()
- throws IOException
- {
- return parser.readObject();
- }
-
- public DERObject getDERObject()
- {
- try
- {
- return new BERApplicationSpecific(tag, parser.readVector());
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException(e.getMessage(), e);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERConstructedOctetString.java pdftk-2.01/java/org/bouncycastle/asn1/BERConstructedOctetString.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERConstructedOctetString.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERConstructedOctetString.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,144 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Vector;
-
-public class BERConstructedOctetString
- extends DEROctetString
-{
- private static final int MAX_LENGTH = 1000;
-
- /**
- * convert a vector of octet strings into a single byte string
- */
- static private byte[] toBytes(
- Vector octs)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- for (int i = 0; i != octs.size(); i++)
- {
- try
- {
- DEROctetString o = (DEROctetString)octs.elementAt(i);
-
- bOut.write(o.getOctets());
- }
- catch (ClassCastException e)
- {
- throw new IllegalArgumentException(octs.elementAt(i).getClass().getName() + " found in input should only contain DEROctetString");
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("exception converting octets " + e.toString());
- }
- }
-
- return bOut.toByteArray();
- }
-
- private Vector octs;
-
- /**
- * @param string the octets making up the octet string.
- */
- public BERConstructedOctetString(
- byte[] string)
- {
- super(string);
- }
-
- public BERConstructedOctetString(
- Vector octs)
- {
- super(toBytes(octs));
-
- this.octs = octs;
- }
-
- public BERConstructedOctetString(
- DERObject obj)
- {
- super(obj);
- }
-
- public BERConstructedOctetString(
- DEREncodable obj)
- {
- super(obj.getDERObject());
- }
-
- public byte[] getOctets()
- {
- return string;
- }
-
- /**
- * return the DER octets that make up this string.
- */
- public Enumeration getObjects()
- {
- if (octs == null)
- {
- return generateOcts().elements();
- }
-
- return octs.elements();
- }
-
- private Vector generateOcts()
- {
- Vector vec = new Vector();
- for (int i = 0; i < string.length; i += MAX_LENGTH)
- {
- int end;
-
- if (i + MAX_LENGTH > string.length)
- {
- end = string.length;
- }
- else
- {
- end = i + MAX_LENGTH;
- }
-
- byte[] nStr = new byte[end - i];
-
- System.arraycopy(string, i, nStr, 0, nStr.length);
-
- vec.addElement(new DEROctetString(nStr));
- }
-
- return vec;
- }
-
- public void encode(
- DEROutputStream out)
- throws IOException
- {
- if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
- {
- out.write(CONSTRUCTED | OCTET_STRING);
-
- out.write(0x80);
-
- //
- // write out the octet array
- //
- Enumeration e = getObjects();
- while (e.hasMoreElements())
- {
- out.writeObject(e.nextElement());
- }
-
- out.write(0x00);
- out.write(0x00);
- }
- else
- {
- super.encode(out);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERConstructedSequence.java pdftk-2.01/java/org/bouncycastle/asn1/BERConstructedSequence.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERConstructedSequence.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERConstructedSequence.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,37 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * @deprecated use BERSequence
- */
-public class BERConstructedSequence
- extends DERConstructedSequence
-{
- /*
- */
- void encode(
- DEROutputStream out)
- throws IOException
- {
- if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
- {
- out.write(SEQUENCE | CONSTRUCTED);
- out.write(0x80);
-
- Enumeration e = getObjects();
- while (e.hasMoreElements())
- {
- out.writeObject(e.nextElement());
- }
-
- out.write(0x00);
- out.write(0x00);
- }
- else
- {
- super.encode(out);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERFactory.java pdftk-2.01/java/org/bouncycastle/asn1/BERFactory.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERFactory.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERFactory.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,22 +0,0 @@
-package org.bouncycastle.asn1;
-
-class BERFactory
-{
- static final BERSequence EMPTY_SEQUENCE = new BERSequence();
- static final BERSet EMPTY_SET = new BERSet();
-
- static BERSequence createSequence(ASN1EncodableVector v)
- {
- return v.size() < 1 ? EMPTY_SEQUENCE : new BERSequence(v);
- }
-
- static BERSet createSet(ASN1EncodableVector v)
- {
- return v.size() < 1 ? EMPTY_SET : new BERSet(v);
- }
-
- static BERSet createSet(ASN1EncodableVector v, boolean needsSorting)
- {
- return v.size() < 1 ? EMPTY_SET : new BERSet(v, needsSorting);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERInputStream.java pdftk-2.01/java/org/bouncycastle/asn1/BERInputStream.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERInputStream.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERInputStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,209 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Vector;
-
-/**
- * @deprecated use ASN1InputStream
- */
-public class BERInputStream
- extends DERInputStream
-{
- private static final DERObject END_OF_STREAM = new DERObject()
- {
- void encode(
- DEROutputStream out)
- throws IOException
- {
- throw new IOException("Eeek!");
- }
- public int hashCode()
- {
- return 0;
- }
- public boolean equals(
- Object o)
- {
- return o == this;
- }
- };
- public BERInputStream(
- InputStream is)
- {
- super(is);
- }
-
- /**
- * read a string of bytes representing an indefinite length object.
- */
- private byte[] readIndefiniteLengthFully()
- throws IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- int b, b1;
-
- b1 = read();
-
- while ((b = read()) >= 0)
- {
- if (b1 == 0 && b == 0)
- {
- break;
- }
-
- bOut.write(b1);
- b1 = b;
- }
-
- return bOut.toByteArray();
- }
-
- private BERConstructedOctetString buildConstructedOctetString()
- throws IOException
- {
- Vector octs = new Vector();
-
- for (;;)
- {
- DERObject o = readObject();
-
- if (o == END_OF_STREAM)
- {
- break;
- }
-
- octs.addElement(o);
- }
-
- return new BERConstructedOctetString(octs);
- }
-
- public DERObject readObject()
- throws IOException
- {
- int tag = read();
- if (tag == -1)
- {
- throw new EOFException();
- }
-
- int length = readLength();
-
- if (length < 0) // indefinite length method
- {
- switch (tag)
- {
- case NULL:
- return null;
- case SEQUENCE | CONSTRUCTED:
- BERConstructedSequence seq = new BERConstructedSequence();
-
- for (;;)
- {
- DERObject obj = readObject();
-
- if (obj == END_OF_STREAM)
- {
- break;
- }
-
- seq.addObject(obj);
- }
- return seq;
- case OCTET_STRING | CONSTRUCTED:
- return buildConstructedOctetString();
- case SET | CONSTRUCTED:
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- for (;;)
- {
- DERObject obj = readObject();
-
- if (obj == END_OF_STREAM)
- {
- break;
- }
-
- v.add(obj);
- }
- return new BERSet(v);
- default:
- //
- // with tagged object tag number is bottom 5 bits
- //
- if ((tag & TAGGED) != 0)
- {
- if ((tag & 0x1f) == 0x1f)
- {
- throw new IOException("unsupported high tag encountered");
- }
-
- //
- // simple type - implicit... return an octet string
- //
- if ((tag & CONSTRUCTED) == 0)
- {
- byte[] bytes = readIndefiniteLengthFully();
-
- return new BERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
- }
-
- //
- // either constructed or explicitly tagged
- //
- DERObject dObj = readObject();
-
- if (dObj == END_OF_STREAM) // empty tag!
- {
- return new DERTaggedObject(tag & 0x1f);
- }
-
- DERObject next = readObject();
-
- //
- // explicitly tagged (probably!) - if it isn't we'd have to
- // tell from the context
- //
- if (next == END_OF_STREAM)
- {
- return new BERTaggedObject(tag & 0x1f, dObj);
- }
-
- //
- // another implicit object, we'll create a sequence...
- //
- seq = new BERConstructedSequence();
-
- seq.addObject(dObj);
-
- do
- {
- seq.addObject(next);
- next = readObject();
- }
- while (next != END_OF_STREAM);
-
- return new BERTaggedObject(false, tag & 0x1f, seq);
- }
-
- throw new IOException("unknown BER object encountered");
- }
- }
- else
- {
- if (tag == 0 && length == 0) // end of contents marker.
- {
- return END_OF_STREAM;
- }
-
- byte[] bytes = new byte[length];
-
- readFully(bytes);
-
- return buildObject(tag, bytes);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERNull.java pdftk-2.01/java/org/bouncycastle/asn1/BERNull.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERNull.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERNull.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,30 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * A BER NULL object.
- */
-public class BERNull
- extends DERNull
-{
- public static final BERNull INSTANCE = new BERNull();
-
- public BERNull()
- {
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
- {
- out.write(NULL);
- }
- else
- {
- super.encode(out);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BEROctetStringParser.java pdftk-2.01/java/org/bouncycastle/asn1/BEROctetStringParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BEROctetStringParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BEROctetStringParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,44 +0,0 @@
-package org.bouncycastle.asn1;
-
-import org.bouncycastle.util.io.Streams;
-
-import java.io.InputStream;
-import java.io.IOException;
-
-public class BEROctetStringParser
- implements ASN1OctetStringParser
-{
- private ASN1StreamParser _parser;
-
- BEROctetStringParser(
- ASN1StreamParser parser)
- {
- _parser = parser;
- }
-
- /**
- * @deprecated will be removed
- */
- protected BEROctetStringParser(
- ASN1ObjectParser parser)
- {
- _parser = parser._aIn;
- }
-
- public InputStream getOctetStream()
- {
- return new ConstructedOctetStream(_parser);
- }
-
- public DERObject getDERObject()
- {
- try
- {
- return new BERConstructedOctetString(Streams.readAll(getOctetStream()));
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BEROutputStream.java pdftk-2.01/java/org/bouncycastle/asn1/BEROutputStream.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BEROutputStream.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BEROutputStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,36 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class BEROutputStream
- extends DEROutputStream
-{
- public BEROutputStream(
- OutputStream os)
- {
- super(os);
- }
-
- public void writeObject(
- Object obj)
- throws IOException
- {
- if (obj == null)
- {
- writeNull();
- }
- else if (obj instanceof DERObject)
- {
- ((DERObject)obj).encode(this);
- }
- else if (obj instanceof DEREncodable)
- {
- ((DEREncodable)obj).getDERObject().encode(this);
- }
- else
- {
- throw new IOException("object not BEREncodable");
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERSequence.java pdftk-2.01/java/org/bouncycastle/asn1/BERSequence.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERSequence.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERSequence.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,59 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-public class BERSequence
- extends DERSequence
-{
- /**
- * create an empty sequence
- */
- public BERSequence()
- {
- }
-
- /**
- * create a sequence containing one object
- */
- public BERSequence(
- DEREncodable obj)
- {
- super(obj);
- }
-
- /**
- * create a sequence containing a vector of objects.
- */
- public BERSequence(
- DEREncodableVector v)
- {
- super(v);
- }
-
- /*
- */
- void encode(
- DEROutputStream out)
- throws IOException
- {
- if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
- {
- out.write(SEQUENCE | CONSTRUCTED);
- out.write(0x80);
-
- Enumeration e = getObjects();
- while (e.hasMoreElements())
- {
- out.writeObject(e.nextElement());
- }
-
- out.write(0x00);
- out.write(0x00);
- }
- else
- {
- super.encode(out);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERSequenceParser.java pdftk-2.01/java/org/bouncycastle/asn1/BERSequenceParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERSequenceParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERSequenceParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,32 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class BERSequenceParser
- implements ASN1SequenceParser
-{
- private ASN1StreamParser _parser;
-
- BERSequenceParser(ASN1StreamParser parser)
- {
- this._parser = parser;
- }
-
- public DEREncodable readObject()
- throws IOException
- {
- return _parser.readObject();
- }
-
- public DERObject getDERObject()
- {
- try
- {
- return new BERSequence(_parser.readVector());
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e.getMessage());
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERSet.java pdftk-2.01/java/org/bouncycastle/asn1/BERSet.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERSet.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERSet.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,69 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-public class BERSet
- extends DERSet
-{
- /**
- * create an empty sequence
- */
- public BERSet()
- {
- }
-
- /**
- * create a set containing one object
- */
- public BERSet(
- DEREncodable obj)
- {
- super(obj);
- }
-
- /**
- * @param v - a vector of objects making up the set.
- */
- public BERSet(
- DEREncodableVector v)
- {
- super(v, false);
- }
-
- /**
- * @param v - a vector of objects making up the set.
- */
- BERSet(
- DEREncodableVector v,
- boolean needsSorting)
- {
- super(v, needsSorting);
- }
-
- /*
- */
- void encode(
- DEROutputStream out)
- throws IOException
- {
- if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
- {
- out.write(SET | CONSTRUCTED);
- out.write(0x80);
-
- Enumeration e = getObjects();
- while (e.hasMoreElements())
- {
- out.writeObject(e.nextElement());
- }
-
- out.write(0x00);
- out.write(0x00);
- }
- else
- {
- super.encode(out);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERSetParser.java pdftk-2.01/java/org/bouncycastle/asn1/BERSetParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERSetParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERSetParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,32 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class BERSetParser
- implements ASN1SetParser
-{
- private ASN1StreamParser _parser;
-
- BERSetParser(ASN1StreamParser parser)
- {
- this._parser = parser;
- }
-
- public DEREncodable readObject()
- throws IOException
- {
- return _parser.readObject();
- }
-
- public DERObject getDERObject()
- {
- try
- {
- return new BERSet(_parser.readVector(), false);
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException(e.getMessage(), e);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERTaggedObject.java pdftk-2.01/java/org/bouncycastle/asn1/BERTaggedObject.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERTaggedObject.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERTaggedObject.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,107 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * BER TaggedObject - in ASN.1 notation this is any object preceded by
- * a [n] where n is some number - these are assumed to follow the construction
- * rules (as with sequences).
- */
-public class BERTaggedObject
- extends DERTaggedObject
-{
- /**
- * @param tagNo the tag number for this object.
- * @param obj the tagged object.
- */
- public BERTaggedObject(
- int tagNo,
- DEREncodable obj)
- {
- super(tagNo, obj);
- }
-
- /**
- * @param explicit true if an explicitly tagged object.
- * @param tagNo the tag number for this object.
- * @param obj the tagged object.
- */
- public BERTaggedObject(
- boolean explicit,
- int tagNo,
- DEREncodable obj)
- {
- super(explicit, tagNo, obj);
- }
-
- /**
- * create an implicitly tagged object that contains a zero
- * length sequence.
- */
- public BERTaggedObject(
- int tagNo)
- {
- super(false, tagNo, new BERSequence());
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- if (out instanceof ASN1OutputStream || out instanceof BEROutputStream)
- {
- out.writeTag(CONSTRUCTED | TAGGED, tagNo);
- out.write(0x80);
-
- if (!empty)
- {
- if (!explicit)
- {
- Enumeration e;
- if (obj instanceof ASN1OctetString)
- {
- if (obj instanceof BERConstructedOctetString)
- {
- e = ((BERConstructedOctetString)obj).getObjects();
- }
- else
- {
- ASN1OctetString octs = (ASN1OctetString)obj;
- BERConstructedOctetString berO = new BERConstructedOctetString(octs.getOctets());
- e = berO.getObjects();
- }
- }
- else if (obj instanceof ASN1Sequence)
- {
- e = ((ASN1Sequence)obj).getObjects();
- }
- else if (obj instanceof ASN1Set)
- {
- e = ((ASN1Set)obj).getObjects();
- }
- else
- {
- throw new RuntimeException("not implemented: " + obj.getClass().getName());
- }
-
- while (e.hasMoreElements())
- {
- out.writeObject(e.nextElement());
- }
- }
- else
- {
- out.writeObject(obj);
- }
- }
-
- out.write(0x00);
- out.write(0x00);
- }
- else
- {
- super.encode(out);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/BERTaggedObjectParser.java pdftk-2.01/java/org/bouncycastle/asn1/BERTaggedObjectParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/BERTaggedObjectParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/BERTaggedObjectParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,123 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public class BERTaggedObjectParser
- implements ASN1TaggedObjectParser
-{
- private int _baseTag;
- private int _tagNumber;
- private InputStream _contentStream;
-
- private boolean _indefiniteLength;
-
- protected BERTaggedObjectParser(
- int baseTag,
- int tagNumber,
- InputStream contentStream)
- {
- _baseTag = baseTag;
- _tagNumber = tagNumber;
- _contentStream = contentStream;
- _indefiniteLength = contentStream instanceof IndefiniteLengthInputStream;
- }
-
- public boolean isConstructed()
- {
- return (_baseTag & DERTags.CONSTRUCTED) != 0;
- }
-
- public int getTagNo()
- {
- return _tagNumber;
- }
-
- public DEREncodable getObjectParser(
- int tag,
- boolean isExplicit)
- throws IOException
- {
- if (isExplicit)
- {
- return new ASN1StreamParser(_contentStream).readObject();
- }
-
- switch (tag)
- {
- case DERTags.SET:
- if (_indefiniteLength)
- {
- return new BERSetParser(new ASN1StreamParser(_contentStream));
- }
- else
- {
- return new DERSetParser(new ASN1StreamParser(_contentStream));
- }
- case DERTags.SEQUENCE:
- if (_indefiniteLength)
- {
- return new BERSequenceParser(new ASN1StreamParser(_contentStream));
- }
- else
- {
- return new DERSequenceParser(new ASN1StreamParser(_contentStream));
- }
- case DERTags.OCTET_STRING:
- // TODO Is the handling of definite length constructed encodings correct?
- if (_indefiniteLength || this.isConstructed())
- {
- return new BEROctetStringParser(new ASN1StreamParser(_contentStream));
- }
- else
- {
- return new DEROctetStringParser((DefiniteLengthInputStream)_contentStream);
- }
- }
-
- throw new RuntimeException("implicit tagging not implemented");
- }
-
- private ASN1EncodableVector rLoadVector(InputStream in)
- {
- try
- {
- return new ASN1StreamParser(in).readVector();
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException(e.getMessage(), e);
- }
- }
-
- public DERObject getDERObject()
- {
- if (_indefiniteLength)
- {
- ASN1EncodableVector v = rLoadVector(_contentStream);
-
- return v.size() == 1
- ? new BERTaggedObject(true, _tagNumber, v.get(0))
- : new BERTaggedObject(false, _tagNumber, BERFactory.createSequence(v));
- }
-
- if (this.isConstructed())
- {
- ASN1EncodableVector v = rLoadVector(_contentStream);
-
- return v.size() == 1
- ? new DERTaggedObject(true, _tagNumber, v.get(0))
- : new DERTaggedObject(false, _tagNumber, DERFactory.createSequence(v));
- }
-
- try
- {
- DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_contentStream;
- return new DERTaggedObject(false, _tagNumber, new DEROctetString(defIn.toByteArray()));
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e.getMessage());
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/ConstructedOctetStream.java pdftk-2.01/java/org/bouncycastle/asn1/ConstructedOctetStream.java
--- pdftk-1.45/java/org/bouncycastle/asn1/ConstructedOctetStream.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/ConstructedOctetStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,111 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.InputStream;
-import java.io.IOException;
-
-class ConstructedOctetStream
- extends InputStream
-{
- private final ASN1StreamParser _parser;
-
- private boolean _first = true;
- private InputStream _currentStream;
-
- ConstructedOctetStream(
- ASN1StreamParser parser)
- {
- _parser = parser;
- }
-
- public int read(byte[] b, int off, int len) throws IOException
- {
- if (_currentStream == null)
- {
- if (!_first)
- {
- return -1;
- }
-
- ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
-
- if (s == null)
- {
- return -1;
- }
-
- _first = false;
- _currentStream = s.getOctetStream();
- }
-
- int totalRead = 0;
-
- for (;;)
- {
- int numRead = _currentStream.read(b, off + totalRead, len - totalRead);
-
- if (numRead >= 0)
- {
- totalRead += numRead;
-
- if (totalRead == len)
- {
- return totalRead;
- }
- }
- else
- {
- ASN1OctetStringParser aos = (ASN1OctetStringParser)_parser.readObject();
-
- if (aos == null)
- {
- _currentStream = null;
- return totalRead < 1 ? -1 : totalRead;
- }
-
- _currentStream = aos.getOctetStream();
- }
- }
- }
-
- public int read()
- throws IOException
- {
- if (_currentStream == null)
- {
- if (!_first)
- {
- return -1;
- }
-
- ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
-
- if (s == null)
- {
- return -1;
- }
-
- _first = false;
- _currentStream = s.getOctetStream();
- }
-
- for (;;)
- {
- int b = _currentStream.read();
-
- if (b >= 0)
- {
- return b;
- }
-
- ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
-
- if (s == null)
- {
- _currentStream = null;
- return -1;
- }
-
- _currentStream = s.getOctetStream();
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERApplicationSpecific.java pdftk-2.01/java/org/bouncycastle/asn1/DERApplicationSpecific.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERApplicationSpecific.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERApplicationSpecific.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,225 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * Base class for an application specific object
- */
-public class DERApplicationSpecific
- extends ASN1Object
-{
- private final boolean isConstructed;
- private final int tag;
- private final byte[] octets;
-
- DERApplicationSpecific(
- boolean isConstructed,
- int tag,
- byte[] octets)
- {
- this.isConstructed = isConstructed;
- this.tag = tag;
- this.octets = octets;
- }
-
- public DERApplicationSpecific(
- int tag,
- byte[] octets)
- {
- this(false, tag, octets);
- }
-
- public DERApplicationSpecific(
- int tag,
- DEREncodable object)
- throws IOException
- {
- this(true, tag, object);
- }
-
- public DERApplicationSpecific(
- boolean explicit,
- int tag,
- DEREncodable object)
- throws IOException
- {
- byte[] data = object.getDERObject().getDEREncoded();
-
- this.isConstructed = explicit;
- this.tag = tag;
-
- if (explicit)
- {
- this.octets = data;
- }
- else
- {
- int lenBytes = getLengthOfLength(data);
- byte[] tmp = new byte[data.length - lenBytes];
- System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
- this.octets = tmp;
- }
- }
-
- public DERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
- {
- this.tag = tagNo;
- this.isConstructed = true;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- for (int i = 0; i != vec.size(); i++)
- {
- try
- {
- bOut.write(((ASN1Encodable)vec.get(i)).getEncoded());
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException("malformed object: " + e, e);
- }
- }
- this.octets = bOut.toByteArray();
- }
-
- private int getLengthOfLength(byte[] data)
- {
- int count = 2; // TODO: assumes only a 1 byte tag number
-
- while((data[count - 1] & 0x80) != 0)
- {
- count++;
- }
-
- return count;
- }
-
- public boolean isConstructed()
- {
- return isConstructed;
- }
-
- public byte[] getContents()
- {
- return octets;
- }
-
- public int getApplicationTag()
- {
- return tag;
- }
-
- /**
- * Return the enclosed object assuming explicit tagging.
- *
- * @return the resulting object
- * @throws IOException if reconstruction fails.
- */
- public DERObject getObject()
- throws IOException
- {
- return new ASN1InputStream(getContents()).readObject();
- }
-
- /**
- * Return the enclosed object assuming implicit tagging.
- *
- * @param derTagNo the type tag that should be applied to the object's contents.
- * @return the resulting object
- * @throws IOException if reconstruction fails.
- */
- public DERObject getObject(int derTagNo)
- throws IOException
- {
- if (derTagNo >= 0x1f)
- {
- throw new IOException("unsupported tag number");
- }
-
- byte[] orig = this.getEncoded();
- byte[] tmp = replaceTagNumber(derTagNo, orig);
-
- if ((orig[0] & DERTags.CONSTRUCTED) != 0)
- {
- tmp[0] |= DERTags.CONSTRUCTED;
- }
-
- return new ASN1InputStream(tmp).readObject();
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.asn1.DERObject#encode(org.bouncycastle.asn1.DEROutputStream)
- */
- void encode(DEROutputStream out) throws IOException
- {
- int classBits = DERTags.APPLICATION;
- if (isConstructed)
- {
- classBits |= DERTags.CONSTRUCTED;
- }
-
- out.writeEncoded(classBits, tag, octets);
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERApplicationSpecific))
- {
- return false;
- }
-
- DERApplicationSpecific other = (DERApplicationSpecific)o;
-
- return isConstructed == other.isConstructed
- && tag == other.tag
- && Arrays.areEqual(octets, other.octets);
- }
-
- public int hashCode()
- {
- return (isConstructed ? 1 : 0) ^ tag ^ Arrays.hashCode(octets);
- }
-
- private byte[] replaceTagNumber(int newTag, byte[] input)
- throws IOException
- {
- int tagNo = input[0] & 0x1f;
- int index = 1;
- //
- // with tagged object tag number is bottom 5 bits, or stored at the start of the content
- //
- if (tagNo == 0x1f)
- {
- tagNo = 0;
-
- int b = input[index++] & 0xff;
-
- // X.690-0207 8.1.2.4.2
- // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
- if ((b & 0x7f) == 0) // Note: -1 will pass
- {
- throw new ASN1ParsingException("corrupted stream - invalid high tag number found");
- }
-
- while ((b >= 0) && ((b & 0x80) != 0))
- {
- tagNo |= (b & 0x7f);
- tagNo <<= 7;
- b = input[index++] & 0xff;
- }
-
- tagNo |= (b & 0x7f);
- }
-
- byte[] tmp = new byte[input.length - index + 1];
-
- System.arraycopy(input, index, tmp, 1, tmp.length - 1);
-
- tmp[0] = (byte)newTag;
-
- return tmp;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERBMPString.java pdftk-2.01/java/org/bouncycastle/asn1/DERBMPString.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERBMPString.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERBMPString.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,126 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER BMPString object.
- */
-public class DERBMPString
- extends ASN1Object
- implements DERString
-{
- String string;
-
- /**
- * return a BMP String from the given object.
- *
- * @param obj the object we want converted.
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERBMPString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERBMPString)
- {
- return (DERBMPString)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERBMPString(((ASN1OctetString)obj).getOctets());
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a BMP String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERBMPString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
-
- /**
- * basic constructor - byte encoded string.
- */
- public DERBMPString(
- byte[] string)
- {
- char[] cs = new char[string.length / 2];
-
- for (int i = 0; i != cs.length; i++)
- {
- cs[i] = (char)((string[2 * i] << 8) | (string[2 * i + 1] & 0xff));
- }
-
- this.string = new String(cs);
- }
-
- /**
- * basic constructor
- */
- public DERBMPString(
- String string)
- {
- this.string = string;
- }
-
- public String getString()
- {
- return string;
- }
-
- public String toString()
- {
- return string;
- }
-
- public int hashCode()
- {
- return this.getString().hashCode();
- }
-
- protected boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERBMPString))
- {
- return false;
- }
-
- DERBMPString s = (DERBMPString)o;
-
- return this.getString().equals(s.getString());
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- char[] c = string.toCharArray();
- byte[] b = new byte[c.length * 2];
-
- for (int i = 0; i != c.length; i++)
- {
- b[2 * i] = (byte)(c[i] >> 8);
- b[2 * i + 1] = (byte)c[i];
- }
-
- out.writeEncoded(BMP_STRING, b);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERBitString.java pdftk-2.01/java/org/bouncycastle/asn1/DERBitString.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERBitString.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERBitString.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,266 +0,0 @@
-package org.bouncycastle.asn1;
-
-import org.bouncycastle.util.Arrays;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-public class DERBitString
- extends ASN1Object
- implements DERString
-{
- private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-
- protected byte[] data;
- protected int padBits;
-
- /**
- * return the correct number of pad bits for a bit string defined in
- * a 32 bit constant
- */
- static protected int getPadBits(
- int bitString)
- {
- int val = 0;
- for (int i = 3; i >= 0; i--)
- {
- //
- // this may look a little odd, but if it isn't done like this pre jdk1.2
- // JVM's break!
- //
- if (i != 0)
- {
- if ((bitString >> (i * 8)) != 0)
- {
- val = (bitString >> (i * 8)) & 0xFF;
- break;
- }
- }
- else
- {
- if (bitString != 0)
- {
- val = bitString & 0xFF;
- break;
- }
- }
- }
-
- if (val == 0)
- {
- return 7;
- }
-
-
- int bits = 1;
-
- while (((val <<= 1) & 0xFF) != 0)
- {
- bits++;
- }
-
- return 8 - bits;
- }
-
- /**
- * return the correct number of bytes for a bit string defined in
- * a 32 bit constant
- */
- static protected byte[] getBytes(int bitString)
- {
- int bytes = 4;
- for (int i = 3; i >= 1; i--)
- {
- if ((bitString & (0xFF << (i * 8))) != 0)
- {
- break;
- }
- bytes--;
- }
-
- byte[] result = new byte[bytes];
- for (int i = 0; i < bytes; i++)
- {
- result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
- }
-
- return result;
- }
-
- /**
- * return a Bit String from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERBitString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERBitString)
- {
- return (DERBitString)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- byte[] bytes = ((ASN1OctetString)obj).getOctets();
- int padBits = bytes[0];
- byte[] data = new byte[bytes.length - 1];
-
- System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
-
- return new DERBitString(data, padBits);
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a Bit String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERBitString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- protected DERBitString(
- byte data,
- int padBits)
- {
- this.data = new byte[1];
- this.data[0] = data;
- this.padBits = padBits;
- }
-
- /**
- * @param data the octets making up the bit string.
- * @param padBits the number of extra bits at the end of the string.
- */
- public DERBitString(
- byte[] data,
- int padBits)
- {
- this.data = data;
- this.padBits = padBits;
- }
-
- public DERBitString(
- byte[] data)
- {
- this(data, 0);
- }
-
- public DERBitString(
- DEREncodable obj)
- {
- try
- {
- this.data = obj.getDERObject().getEncoded(ASN1Encodable.DER);
- this.padBits = 0;
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("Error processing object : " + e.toString());
- }
- }
-
- public byte[] getBytes()
- {
- return data;
- }
-
- public int getPadBits()
- {
- return padBits;
- }
-
-
- /**
- * @return the value of the bit string as an int (truncating if necessary)
- */
- public int intValue()
- {
- int value = 0;
-
- for (int i = 0; i != data.length && i != 4; i++)
- {
- value |= (data[i] & 0xff) << (8 * i);
- }
-
- return value;
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- byte[] bytes = new byte[getBytes().length + 1];
-
- bytes[0] = (byte)getPadBits();
- System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1);
-
- out.writeEncoded(BIT_STRING, bytes);
- }
-
- public int hashCode()
- {
- return padBits ^ Arrays.hashCode(data);
- }
-
- protected boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERBitString))
- {
- return false;
- }
-
- DERBitString other = (DERBitString)o;
-
- return this.padBits == other.padBits
- && Arrays.areEqual(this.data, other.data);
- }
-
- public String getString()
- {
- StringBuffer buf = new StringBuffer("#");
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- try
- {
- aOut.writeObject(this);
- }
- catch (IOException e)
- {
- throw new RuntimeException("internal error encoding BitString");
- }
-
- byte[] string = bOut.toByteArray();
-
- for (int i = 0; i != string.length; i++)
- {
- buf.append(table[(string[i] >>> 4) & 0xf]);
- buf.append(table[string[i] & 0xf]);
- }
-
- return buf.toString();
- }
-
- public String toString()
- {
- return getString();
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERBoolean.java pdftk-2.01/java/org/bouncycastle/asn1/DERBoolean.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERBoolean.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERBoolean.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,113 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DERBoolean
- extends ASN1Object
-{
- byte value;
-
- public static final DERBoolean FALSE = new DERBoolean(false);
- public static final DERBoolean TRUE = new DERBoolean(true);
-
- /**
- * return a boolean from the passed in object.
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERBoolean getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERBoolean)
- {
- return (DERBoolean)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERBoolean(((ASN1OctetString)obj).getOctets());
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a DERBoolean from the passed in boolean.
- */
- public static DERBoolean getInstance(
- boolean value)
- {
- return (value ? TRUE : FALSE);
- }
-
- /**
- * return a Boolean from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERBoolean getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- public DERBoolean(
- byte[] value)
- {
- this.value = value[0];
- }
-
- public DERBoolean(
- boolean value)
- {
- this.value = (value) ? (byte)0xff : (byte)0;
- }
-
- public boolean isTrue()
- {
- return (value != 0);
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- byte[] bytes = new byte[1];
-
- bytes[0] = value;
-
- out.writeEncoded(BOOLEAN, bytes);
- }
-
- protected boolean asn1Equals(
- DERObject o)
- {
- if ((o == null) || !(o instanceof DERBoolean))
- {
- return false;
- }
-
- return (value == ((DERBoolean)o).value);
- }
-
- public int hashCode()
- {
- return value;
- }
-
-
- public String toString()
- {
- return (value != 0) ? "TRUE" : "FALSE";
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERConstructedSequence.java pdftk-2.01/java/org/bouncycastle/asn1/DERConstructedSequence.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERConstructedSequence.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERConstructedSequence.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,53 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * @deprecated use DERSequence.
- */
-public class DERConstructedSequence
- extends ASN1Sequence
-{
- public void addObject(
- DEREncodable obj)
- {
- super.addObject(obj);
- }
-
- public int getSize()
- {
- return size();
- }
-
- /*
- * A note on the implementation:
- *
- * As DER requires the constructed, definite-length model to
- * be used for structured types, this varies slightly from the
- * ASN.1 descriptions given. Rather than just outputing SEQUENCE,
- * we also have to specify CONSTRUCTED, and the objects length.
- */
- void encode(
- DEROutputStream out)
- throws IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DEROutputStream dOut = new DEROutputStream(bOut);
- Enumeration e = this.getObjects();
-
- while (e.hasMoreElements())
- {
- Object obj = e.nextElement();
-
- dOut.writeObject(obj);
- }
-
- dOut.close();
-
- byte[] bytes = bOut.toByteArray();
-
- out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERConstructedSet.java pdftk-2.01/java/org/bouncycastle/asn1/DERConstructedSet.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERConstructedSet.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERConstructedSet.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,79 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- *
- * @deprecated use DERSet
- */
-public class DERConstructedSet
- extends ASN1Set
-{
- public DERConstructedSet()
- {
- }
-
- /**
- * @param obj - a single object that makes up the set.
- */
- public DERConstructedSet(
- DEREncodable obj)
- {
- this.addObject(obj);
- }
-
- /**
- * @param v - a vector of objects making up the set.
- */
- public DERConstructedSet(
- DEREncodableVector v)
- {
- for (int i = 0; i != v.size(); i++)
- {
- this.addObject(v.get(i));
- }
- }
-
- public void addObject(
- DEREncodable obj)
- {
- super.addObject(obj);
- }
-
- public int getSize()
- {
- return size();
- }
-
- /*
- * A note on the implementation:
- *
- * As DER requires the constructed, definite-length model to
- * be used for structured types, this varies slightly from the
- * ASN.1 descriptions given. Rather than just outputing SET,
- * we also have to specify CONSTRUCTED, and the objects length.
- */
- void encode(
- DEROutputStream out)
- throws IOException
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DEROutputStream dOut = new DEROutputStream(bOut);
- Enumeration e = this.getObjects();
-
- while (e.hasMoreElements())
- {
- Object obj = e.nextElement();
-
- dOut.writeObject(obj);
- }
-
- dOut.close();
-
- byte[] bytes = bOut.toByteArray();
-
- out.writeEncoded(SET | CONSTRUCTED, bytes);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DEREncodable.java pdftk-2.01/java/org/bouncycastle/asn1/DEREncodable.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DEREncodable.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DEREncodable.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,6 +0,0 @@
-package org.bouncycastle.asn1;
-
-public interface DEREncodable
-{
- public DERObject getDERObject();
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DEREncodableVector.java pdftk-2.01/java/org/bouncycastle/asn1/DEREncodableVector.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DEREncodableVector.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DEREncodableVector.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,38 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.util.Vector;
-
-/**
- * a general class for building up a vector of DER encodable objects -
- * this will eventually be superceded by ASN1EncodableVector so you should
- * use that class in preference.
- */
-public class DEREncodableVector
-{
- Vector v = new Vector();
-
- /**
- * @deprecated use ASN1EncodableVector instead.
- */
- public DEREncodableVector()
- {
-
- }
-
- public void add(
- DEREncodable obj)
- {
- v.addElement(obj);
- }
-
- public DEREncodable get(
- int i)
- {
- return (DEREncodable)v.elementAt(i);
- }
-
- public int size()
- {
- return v.size();
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DEREnumerated.java pdftk-2.01/java/org/bouncycastle/asn1/DEREnumerated.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DEREnumerated.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DEREnumerated.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,102 +0,0 @@
-package org.bouncycastle.asn1;
-
-import org.bouncycastle.util.Arrays;
-
-import java.io.IOException;
-import java.math.BigInteger;
-
-public class DEREnumerated
- extends ASN1Object
-{
- byte[] bytes;
-
- /**
- * return an integer from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DEREnumerated getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DEREnumerated)
- {
- return (DEREnumerated)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DEREnumerated(((ASN1OctetString)obj).getOctets());
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an Enumerated from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DEREnumerated getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- public DEREnumerated(
- int value)
- {
- bytes = BigInteger.valueOf(value).toByteArray();
- }
-
- public DEREnumerated(
- BigInteger value)
- {
- bytes = value.toByteArray();
- }
-
- public DEREnumerated(
- byte[] bytes)
- {
- this.bytes = bytes;
- }
-
- public BigInteger getValue()
- {
- return new BigInteger(bytes);
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(ENUMERATED, bytes);
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DEREnumerated))
- {
- return false;
- }
-
- DEREnumerated other = (DEREnumerated)o;
-
- return Arrays.areEqual(this.bytes, other.bytes);
- }
-
- public int hashCode()
- {
- return Arrays.hashCode(bytes);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERExternal.java pdftk-2.01/java/org/bouncycastle/asn1/DERExternal.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERExternal.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERExternal.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,267 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-/**
- * Class representing the DER-type External
- */
-public class DERExternal
- extends ASN1Object
-{
- private DERObjectIdentifier directReference;
- private DERInteger indirectReference;
- private ASN1Object dataValueDescriptor;
- private int encoding;
- private DERObject externalContent;
-
- public DERExternal(ASN1EncodableVector vector)
- {
- int offset = 0;
- DERObject enc = vector.get(offset).getDERObject();
- if (enc instanceof DERObjectIdentifier)
- {
- directReference = (DERObjectIdentifier)enc;
- offset++;
- enc = vector.get(offset).getDERObject();
- }
- if (enc instanceof DERInteger)
- {
- indirectReference = (DERInteger) enc;
- offset++;
- enc = vector.get(offset).getDERObject();
- }
- if (!(enc instanceof DERTaggedObject))
- {
- dataValueDescriptor = (ASN1Object) enc;
- offset++;
- enc = vector.get(offset).getDERObject();
- }
- if (!(enc instanceof DERTaggedObject))
- {
- throw new IllegalArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External");
- }
- DERTaggedObject obj = (DERTaggedObject)enc;
- setEncoding(obj.getTagNo());
- externalContent = obj.getObject();
- }
-
- /**
- * Creates a new instance of DERExternal
- * See X.690 for more informations about the meaning of these parameters
- * @param directReference The direct reference or null
if not set.
- * @param indirectReference The indirect reference or null
if not set.
- * @param dataValueDescriptor The data value descriptor or null
if not set.
- * @param externalData The external data in its encoded form.
- */
- public DERExternal(DERObjectIdentifier directReference, DERInteger indirectReference, ASN1Object dataValueDescriptor, DERTaggedObject externalData)
- {
- this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.getDERObject());
- }
-
- /**
- * Creates a new instance of DERExternal.
- * See X.690 for more informations about the meaning of these parameters
- * @param directReference The direct reference or null
if not set.
- * @param indirectReference The indirect reference or null
if not set.
- * @param dataValueDescriptor The data value descriptor or null
if not set.
- * @param encoding The encoding to be used for the external data
- * @param externalData The external data
- */
- public DERExternal(DERObjectIdentifier directReference, DERInteger indirectReference, ASN1Object dataValueDescriptor, int encoding, DERObject externalData)
- {
- setDirectReference(directReference);
- setIndirectReference(indirectReference);
- setDataValueDescriptor(dataValueDescriptor);
- setEncoding(encoding);
- setExternalContent(externalData.getDERObject());
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#hashCode()
- */
- public int hashCode()
- {
- int ret = 0;
- if (directReference != null)
- {
- ret = directReference.hashCode();
- }
- if (indirectReference != null)
- {
- ret ^= indirectReference.hashCode();
- }
- if (dataValueDescriptor != null)
- {
- ret ^= dataValueDescriptor.hashCode();
- }
- ret ^= externalContent.hashCode();
- return ret;
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.asn1.DERObject#encode(org.bouncycastle.asn1.DEROutputStream)
- */
- void encode(DEROutputStream out)
- throws IOException
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- if (directReference != null)
- {
- baos.write(directReference.getDEREncoded());
- }
- if (indirectReference != null)
- {
- baos.write(indirectReference.getDEREncoded());
- }
- if (dataValueDescriptor != null)
- {
- baos.write(dataValueDescriptor.getDEREncoded());
- }
- DERTaggedObject obj = new DERTaggedObject(encoding, externalContent);
- baos.write(obj.getDEREncoded());
- out.writeEncoded(DERTags.CONSTRUCTED, DERTags.EXTERNAL, baos.toByteArray());
- }
-
- /* (non-Javadoc)
- * @see org.bouncycastle.asn1.ASN1Object#asn1Equals(org.bouncycastle.asn1.DERObject)
- */
- boolean asn1Equals(DERObject o)
- {
- if (!(o instanceof DERExternal))
- {
- return false;
- }
- if (this == o)
- {
- return true;
- }
- DERExternal other = (DERExternal)o;
- if (directReference != null)
- {
- if (other.directReference == null || !other.directReference.equals(directReference))
- {
- return false;
- }
- }
- if (indirectReference != null)
- {
- if (other.indirectReference == null || !other.indirectReference.equals(indirectReference))
- {
- return false;
- }
- }
- if (dataValueDescriptor != null)
- {
- if (other.dataValueDescriptor == null || !other.dataValueDescriptor.equals(dataValueDescriptor))
- {
- return false;
- }
- }
- return externalContent.equals(other.externalContent);
- }
-
- /**
- * Returns the data value descriptor
- * @return The descriptor
- */
- public ASN1Object getDataValueDescriptor()
- {
- return dataValueDescriptor;
- }
-
- /**
- * Returns the direct reference of the external element
- * @return The reference
- */
- public DERObjectIdentifier getDirectReference()
- {
- return directReference;
- }
-
- /**
- * Returns the encoding of the content. Valid values are
- *
- * 0
single-ASN1-type
- * 1
OCTET STRING
- * 2
BIT STRING
- *
- * @return The encoding
- */
- public int getEncoding()
- {
- return encoding;
- }
-
- /**
- * Returns the content of this element
- * @return The content
- */
- public DERObject getExternalContent()
- {
- return externalContent;
- }
-
- /**
- * Returns the indirect reference of this element
- * @return The reference
- */
- public DERInteger getIndirectReference()
- {
- return indirectReference;
- }
-
- /**
- * Sets the data value descriptor
- * @param dataValueDescriptor The descriptor
- */
- private void setDataValueDescriptor(ASN1Object dataValueDescriptor)
- {
- this.dataValueDescriptor = dataValueDescriptor;
- }
-
- /**
- * Sets the direct reference of the external element
- * @param directReferemce The reference
- */
- private void setDirectReference(DERObjectIdentifier directReferemce)
- {
- this.directReference = directReferemce;
- }
-
- /**
- * Sets the encoding of the content. Valid values are
- *
- * 0
single-ASN1-type
- * 1
OCTET STRING
- * 2
BIT STRING
- *
- * @param encoding The encoding
- */
- private void setEncoding(int encoding)
- {
- if (encoding < 0 || encoding > 2)
- {
- throw new IllegalArgumentException("invalid encoding value: " + encoding);
- }
- this.encoding = encoding;
- }
-
- /**
- * Sets the content of this element
- * @param externalContent The content
- */
- private void setExternalContent(DERObject externalContent)
- {
- this.externalContent = externalContent;
- }
-
- /**
- * Sets the indirect reference of this element
- * @param indirectReference The reference
- */
- private void setIndirectReference(DERInteger indirectReference)
- {
- this.indirectReference = indirectReference;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERExternalParser.java pdftk-2.01/java/org/bouncycastle/asn1/DERExternalParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERExternalParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERExternalParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,39 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DERExternalParser
- implements DEREncodable
-{
- private ASN1StreamParser _parser;
-
- /**
- *
- */
- public DERExternalParser(ASN1StreamParser parser)
- {
- this._parser = parser;
- }
-
- public DEREncodable readObject()
- throws IOException
- {
- return _parser.readObject();
- }
-
- public DERObject getDERObject()
- {
- try
- {
- return new DERExternal(_parser.readVector());
- }
- catch (IOException ioe)
- {
- throw new ASN1ParsingException("unable to get DER object", ioe);
- }
- catch (IllegalArgumentException ioe)
- {
- throw new ASN1ParsingException("unable to get DER object", ioe);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERFactory.java pdftk-2.01/java/org/bouncycastle/asn1/DERFactory.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERFactory.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERFactory.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,22 +0,0 @@
-package org.bouncycastle.asn1;
-
-class DERFactory
-{
- static final DERSequence EMPTY_SEQUENCE = new DERSequence();
- static final DERSet EMPTY_SET = new DERSet();
-
- static DERSequence createSequence(ASN1EncodableVector v)
- {
- return v.size() < 1 ? EMPTY_SEQUENCE : new DERSequence(v);
- }
-
- static DERSet createSet(ASN1EncodableVector v)
- {
- return v.size() < 1 ? EMPTY_SET : new DERSet(v);
- }
-
- static DERSet createSet(ASN1EncodableVector v, boolean needsSorting)
- {
- return v.size() < 1 ? EMPTY_SET : new DERSet(v, needsSorting);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERGeneralString.java pdftk-2.01/java/org/bouncycastle/asn1/DERGeneralString.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERGeneralString.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERGeneralString.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,92 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DERGeneralString
- extends ASN1Object implements DERString
-{
- private String string;
-
- public static DERGeneralString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERGeneralString)
- {
- return (DERGeneralString) obj;
- }
- if (obj instanceof ASN1OctetString)
- {
- return new DERGeneralString(((ASN1OctetString) obj).getOctets());
- }
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject) obj).getObject());
- }
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- public static DERGeneralString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- public DERGeneralString(byte[] string)
- {
- char[] cs = new char[string.length];
- for (int i = 0; i != cs.length; i++)
- {
- cs[i] = (char)(string[i] & 0xff);
- }
- this.string = new String(cs);
- }
-
- public DERGeneralString(String string)
- {
- this.string = string;
- }
-
- public String getString()
- {
- return string;
- }
-
- public String toString()
- {
- return string;
- }
-
- public byte[] getOctets()
- {
- char[] cs = string.toCharArray();
- byte[] bs = new byte[cs.length];
- for (int i = 0; i != cs.length; i++)
- {
- bs[i] = (byte) cs[i];
- }
- return bs;
- }
-
- void encode(DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(GENERAL_STRING, this.getOctets());
- }
-
- public int hashCode()
- {
- return this.getString().hashCode();
- }
-
- boolean asn1Equals(DERObject o)
- {
- if (!(o instanceof DERGeneralString))
- {
- return false;
- }
- DERGeneralString s = (DERGeneralString) o;
- return this.getString().equals(s.getString());
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERGeneralizedTime.java pdftk-2.01/java/org/bouncycastle/asn1/DERGeneralizedTime.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERGeneralizedTime.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERGeneralizedTime.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,314 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.SimpleTimeZone;
-import java.util.TimeZone;
-
-/**
- * Generalized time object.
- */
-public class DERGeneralizedTime
- extends ASN1Object
-{
- String time;
-
- /**
- * return a generalized time from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERGeneralizedTime getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERGeneralizedTime)
- {
- return (DERGeneralizedTime)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERGeneralizedTime(((ASN1OctetString)obj).getOctets());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a Generalized Time object from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERGeneralizedTime getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- /**
- * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
- * for local time, or Z+-HHMM on the end, for difference between local
- * time and UTC time. The fractional second amount f must consist of at
- * least one number with trailing zeroes removed.
- *
- * @param time the time string.
- * @exception IllegalArgumentException if String is an illegal format.
- */
- public DERGeneralizedTime(
- String time)
- {
- this.time = time;
- try
- {
- this.getDate();
- }
- catch (ParseException e)
- {
- throw new IllegalArgumentException("invalid date string: " + e.getMessage());
- }
- }
-
- /**
- * base constructer from a java.util.date object
- */
- public DERGeneralizedTime(
- Date time)
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
-
- dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
- this.time = dateF.format(time);
- }
-
- DERGeneralizedTime(
- byte[] bytes)
- {
- //
- // explicitly convert to characters
- //
- char[] dateC = new char[bytes.length];
-
- for (int i = 0; i != dateC.length; i++)
- {
- dateC[i] = (char)(bytes[i] & 0xff);
- }
-
- this.time = new String(dateC);
- }
-
- /**
- * Return the time.
- * @return The time string as it appeared in the encoded object.
- */
- public String getTimeString()
- {
- return time;
- }
-
- /**
- * return the time - always in the form of
- * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
- *
- * Normally in a certificate we would expect "Z" rather than "GMT",
- * however adding the "GMT" means we can just use:
- *
- * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
- *
- * To read in the time and get a date which is compatible with our local
- * time zone.
- */
- public String getTime()
- {
- //
- // standardise the format.
- //
- if (time.charAt(time.length() - 1) == 'Z')
- {
- return time.substring(0, time.length() - 1) + "GMT+00:00";
- }
- else
- {
- int signPos = time.length() - 5;
- char sign = time.charAt(signPos);
- if (sign == '-' || sign == '+')
- {
- return time.substring(0, signPos)
- + "GMT"
- + time.substring(signPos, signPos + 3)
- + ":"
- + time.substring(signPos + 3);
- }
- else
- {
- signPos = time.length() - 3;
- sign = time.charAt(signPos);
- if (sign == '-' || sign == '+')
- {
- return time.substring(0, signPos)
- + "GMT"
- + time.substring(signPos)
- + ":00";
- }
- }
- }
- return time + calculateGMTOffset();
- }
-
- private String calculateGMTOffset()
- {
- String sign = "+";
- TimeZone timeZone = TimeZone.getDefault();
- int offset = timeZone.getRawOffset();
- if (offset < 0)
- {
- sign = "-";
- offset = -offset;
- }
- int hours = offset / (60 * 60 * 1000);
- int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
-
- try
- {
- if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
- {
- hours += sign.equals("+") ? 1 : -1;
- }
- }
- catch (ParseException e)
- {
- // we'll do our best and ignore daylight savings
- }
-
- return "GMT" + sign + convert(hours) + ":" + convert(minutes);
- }
-
- private String convert(int time)
- {
- if (time < 10)
- {
- return "0" + time;
- }
-
- return Integer.toString(time);
- }
-
- public Date getDate()
- throws ParseException
- {
- SimpleDateFormat dateF;
- String d = time;
-
- if (time.endsWith("Z"))
- {
- if (hasFractionalSeconds())
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
- }
- else
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
- }
-
- dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
- }
- else if (time.indexOf('-') > 0 || time.indexOf('+') > 0)
- {
- d = this.getTime();
- if (hasFractionalSeconds())
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz");
- }
- else
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
- }
-
- dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
- }
- else
- {
- if (hasFractionalSeconds())
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
- }
- else
- {
- dateF = new SimpleDateFormat("yyyyMMddHHmmss");
- }
-
- dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
- }
-
- if (hasFractionalSeconds())
- {
- // java misinterprets extra digits as being milliseconds...
- String frac = d.substring(14);
- int index;
- for (index = 1; index < frac.length(); index++)
- {
- char ch = frac.charAt(index);
- if (!('0' <= ch && ch <= '9'))
- {
- break;
- }
- }
- if (index - 1 > 3)
- {
- frac = frac.substring(0, 4) + frac.substring(index);
- d = d.substring(0, 14) + frac;
- }
- }
-
- return dateF.parse(d);
- }
-
- private boolean hasFractionalSeconds()
- {
- return time.indexOf('.') == 14;
- }
-
- private byte[] getOctets()
- {
- char[] cs = time.toCharArray();
- byte[] bs = new byte[cs.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- bs[i] = (byte)cs[i];
- }
-
- return bs;
- }
-
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(GENERALIZED_TIME, this.getOctets());
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERGeneralizedTime))
- {
- return false;
- }
-
- return time.equals(((DERGeneralizedTime)o).time);
- }
-
- public int hashCode()
- {
- return time.hashCode();
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERIA5String.java pdftk-2.01/java/org/bouncycastle/asn1/DERIA5String.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERIA5String.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERIA5String.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,174 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER IA5String object - this is an ascii string.
- */
-public class DERIA5String
- extends ASN1Object
- implements DERString
-{
- String string;
-
- /**
- * return a IA5 string from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERIA5String getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERIA5String)
- {
- return (DERIA5String)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERIA5String(((ASN1OctetString)obj).getOctets());
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an IA5 String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERIA5String getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- /**
- * basic constructor - with bytes.
- */
- public DERIA5String(
- byte[] string)
- {
- char[] cs = new char[string.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- cs[i] = (char)(string[i] & 0xff);
- }
-
- this.string = new String(cs);
- }
-
- /**
- * basic constructor - without validation.
- */
- public DERIA5String(
- String string)
- {
- this(string, false);
- }
-
- /**
- * Constructor with optional validation.
- *
- * @param string the base string to wrap.
- * @param validate whether or not to check the string.
- * @throws IllegalArgumentException if validate is true and the string
- * contains characters that should not be in an IA5String.
- */
- public DERIA5String(
- String string,
- boolean validate)
- {
- if (string == null)
- {
- throw new NullPointerException("string cannot be null");
- }
- if (validate && !isIA5String(string))
- {
- throw new IllegalArgumentException("string contains illegal characters");
- }
-
- this.string = string;
- }
-
- public String getString()
- {
- return string;
- }
-
- public String toString()
- {
- return string;
- }
-
- public byte[] getOctets()
- {
- char[] cs = string.toCharArray();
- byte[] bs = new byte[cs.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- bs[i] = (byte)cs[i];
- }
-
- return bs;
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(IA5_STRING, this.getOctets());
- }
-
- public int hashCode()
- {
- return this.getString().hashCode();
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERIA5String))
- {
- return false;
- }
-
- DERIA5String s = (DERIA5String)o;
-
- return this.getString().equals(s.getString());
- }
-
- /**
- * return true if the passed in String can be represented without
- * loss as an IA5String, false otherwise.
- *
- * @return true if in printable set, false otherwise.
- */
- public static boolean isIA5String(
- String str)
- {
- for (int i = str.length() - 1; i >= 0; i--)
- {
- char ch = str.charAt(i);
-
- if (ch > 0x007f)
- {
- return false;
- }
- }
-
- return true;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERInputStream.java pdftk-2.01/java/org/bouncycastle/asn1/DERInputStream.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERInputStream.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERInputStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,272 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayInputStream;
-import java.io.EOFException;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Don't use this class. It will eventually disappear, use ASN1InputStream.
- *
- * This class is scheduled for removal.
- * @deprecated use ASN1InputStream
- */
-public class DERInputStream
- extends FilterInputStream implements DERTags
-{
- /**
- * @deprecated use ASN1InputStream
- */
- public DERInputStream(
- InputStream is)
- {
- super(is);
- }
-
- protected int readLength()
- throws IOException
- {
- int length = read();
- if (length < 0)
- {
- throw new IOException("EOF found when length expected");
- }
-
- if (length == 0x80)
- {
- return -1; // indefinite-length encoding
- }
-
- if (length > 127)
- {
- int size = length & 0x7f;
-
- if (size > 4)
- {
- throw new IOException("DER length more than 4 bytes");
- }
-
- length = 0;
- for (int i = 0; i < size; i++)
- {
- int next = read();
-
- if (next < 0)
- {
- throw new IOException("EOF found reading length");
- }
-
- length = (length << 8) + next;
- }
-
- if (length < 0)
- {
- throw new IOException("corrupted stream - negative length found");
- }
- }
-
- return length;
- }
-
- protected void readFully(
- byte[] bytes)
- throws IOException
- {
- int left = bytes.length;
-
- if (left == 0)
- {
- return;
- }
-
- while (left > 0)
- {
- int l = read(bytes, bytes.length - left, left);
-
- if (l < 0)
- {
- throw new EOFException("unexpected end of stream");
- }
-
- left -= l;
- }
- }
-
- /**
- * build an object given its tag and a byte stream to construct it
- * from.
- */
- protected DERObject buildObject(
- int tag,
- byte[] bytes)
- throws IOException
- {
- switch (tag)
- {
- case NULL:
- return null;
- case SEQUENCE | CONSTRUCTED:
- ByteArrayInputStream bIn = new ByteArrayInputStream(bytes);
- BERInputStream dIn = new BERInputStream(bIn);
- DERConstructedSequence seq = new DERConstructedSequence();
-
- try
- {
- for (;;)
- {
- DERObject obj = dIn.readObject();
-
- seq.addObject(obj);
- }
- }
- catch (EOFException ex)
- {
- return seq;
- }
- case SET | CONSTRUCTED:
- bIn = new ByteArrayInputStream(bytes);
- dIn = new BERInputStream(bIn);
-
- ASN1EncodableVector v = new ASN1EncodableVector();
-
- try
- {
- for (;;)
- {
- DERObject obj = dIn.readObject();
-
- v.add(obj);
- }
- }
- catch (EOFException ex)
- {
- return new DERConstructedSet(v);
- }
- case BOOLEAN:
- return new DERBoolean(bytes);
- case INTEGER:
- return new DERInteger(bytes);
- case ENUMERATED:
- return new DEREnumerated(bytes);
- case OBJECT_IDENTIFIER:
- return new DERObjectIdentifier(bytes);
- case BIT_STRING:
- int padBits = bytes[0];
- byte[] data = new byte[bytes.length - 1];
-
- System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
-
- return new DERBitString(data, padBits);
- case UTF8_STRING:
- return new DERUTF8String(bytes);
- case PRINTABLE_STRING:
- return new DERPrintableString(bytes);
- case IA5_STRING:
- return new DERIA5String(bytes);
- case T61_STRING:
- return new DERT61String(bytes);
- case VISIBLE_STRING:
- return new DERVisibleString(bytes);
- case UNIVERSAL_STRING:
- return new DERUniversalString(bytes);
- case GENERAL_STRING:
- return new DERGeneralString(bytes);
- case BMP_STRING:
- return new DERBMPString(bytes);
- case OCTET_STRING:
- return new DEROctetString(bytes);
- case UTC_TIME:
- return new DERUTCTime(bytes);
- case GENERALIZED_TIME:
- return new DERGeneralizedTime(bytes);
- default:
- //
- // with tagged object tag number is bottom 5 bits
- //
- if ((tag & TAGGED) != 0)
- {
- if ((tag & 0x1f) == 0x1f)
- {
- throw new IOException("unsupported high tag encountered");
- }
-
- if (bytes.length == 0) // empty tag!
- {
- if ((tag & CONSTRUCTED) == 0)
- {
- return new DERTaggedObject(false, tag & 0x1f, new DERNull());
- }
- else
- {
- return new DERTaggedObject(false, tag & 0x1f, new DERConstructedSequence());
- }
- }
-
- //
- // simple type - implicit... return an octet string
- //
- if ((tag & CONSTRUCTED) == 0)
- {
- return new DERTaggedObject(false, tag & 0x1f, new DEROctetString(bytes));
- }
-
- bIn = new ByteArrayInputStream(bytes);
- dIn = new BERInputStream(bIn);
-
- DEREncodable dObj = dIn.readObject();
-
- //
- // explicitly tagged (probably!) - if it isn't we'd have to
- // tell from the context
- //
- if (dIn.available() == 0)
- {
- return new DERTaggedObject(tag & 0x1f, dObj);
- }
-
- //
- // another implicit object, we'll create a sequence...
- //
- seq = new DERConstructedSequence();
-
- seq.addObject(dObj);
-
- try
- {
- for (;;)
- {
- dObj = dIn.readObject();
-
- seq.addObject(dObj);
- }
- }
- catch (EOFException ex)
- {
- // ignore --
- }
-
- return new DERTaggedObject(false, tag & 0x1f, seq);
- }
-
- return new DERUnknownTag(tag, bytes);
- }
- }
-
- public DERObject readObject()
- throws IOException
- {
- int tag = read();
- if (tag == -1)
- {
- throw new EOFException();
- }
-
- int length = readLength();
- byte[] bytes = new byte[length];
-
- readFully(bytes);
-
- return buildObject(tag, bytes);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERInteger.java pdftk-2.01/java/org/bouncycastle/asn1/DERInteger.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERInteger.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERInteger.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,123 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.math.BigInteger;
-
-import org.bouncycastle.util.Arrays;
-
-public class DERInteger
- extends ASN1Object
-{
- byte[] bytes;
-
- /**
- * return an integer from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERInteger getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERInteger)
- {
- return (DERInteger)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERInteger(((ASN1OctetString)obj).getOctets());
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an Integer from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERInteger getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- public DERInteger(
- int value)
- {
- bytes = BigInteger.valueOf(value).toByteArray();
- }
-
- public DERInteger(
- BigInteger value)
- {
- bytes = value.toByteArray();
- }
-
- public DERInteger(
- byte[] bytes)
- {
- this.bytes = bytes;
- }
-
- public BigInteger getValue()
- {
- return new BigInteger(bytes);
- }
-
- /**
- * in some cases positive values get crammed into a space,
- * that's not quite big enough...
- */
- public BigInteger getPositiveValue()
- {
- return new BigInteger(1, bytes);
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(INTEGER, bytes);
- }
-
- public int hashCode()
- {
- int value = 0;
-
- for (int i = 0; i != bytes.length; i++)
- {
- value ^= (bytes[i] & 0xff) << (i % 4);
- }
-
- return value;
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERInteger))
- {
- return false;
- }
-
- DERInteger other = (DERInteger)o;
-
- return Arrays.areEqual(bytes, other.bytes);
- }
-
- public String toString()
- {
- return getValue().toString();
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERNull.java pdftk-2.01/java/org/bouncycastle/asn1/DERNull.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERNull.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERNull.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,25 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * A NULL object.
- */
-public class DERNull
- extends ASN1Null
-{
- public static final DERNull INSTANCE = new DERNull();
-
- byte[] zeroBytes = new byte[0];
-
- public DERNull()
- {
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(NULL, zeroBytes);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERNumericString.java pdftk-2.01/java/org/bouncycastle/asn1/DERNumericString.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERNumericString.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERNumericString.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,177 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
- */
-public class DERNumericString
- extends ASN1Object
- implements DERString
-{
- String string;
-
- /**
- * return a Numeric string from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERNumericString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERNumericString)
- {
- return (DERNumericString)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERNumericString(((ASN1OctetString)obj).getOctets());
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an Numeric String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERNumericString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- /**
- * basic constructor - with bytes.
- */
- public DERNumericString(
- byte[] string)
- {
- char[] cs = new char[string.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- cs[i] = (char)(string[i] & 0xff);
- }
-
- this.string = new String(cs);
- }
-
- /**
- * basic constructor - without validation..
- */
- public DERNumericString(
- String string)
- {
- this(string, false);
- }
-
- /**
- * Constructor with optional validation.
- *
- * @param string the base string to wrap.
- * @param validate whether or not to check the string.
- * @throws IllegalArgumentException if validate is true and the string
- * contains characters that should not be in a NumericString.
- */
- public DERNumericString(
- String string,
- boolean validate)
- {
- if (validate && !isNumericString(string))
- {
- throw new IllegalArgumentException("string contains illegal characters");
- }
-
- this.string = string;
- }
-
- public String getString()
- {
- return string;
- }
-
- public String toString()
- {
- return string;
- }
-
- public byte[] getOctets()
- {
- char[] cs = string.toCharArray();
- byte[] bs = new byte[cs.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- bs[i] = (byte)cs[i];
- }
-
- return bs;
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(NUMERIC_STRING, this.getOctets());
- }
-
- public int hashCode()
- {
- return this.getString().hashCode();
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERNumericString))
- {
- return false;
- }
-
- DERNumericString s = (DERNumericString)o;
-
- return this.getString().equals(s.getString());
- }
-
- /**
- * Return true if the string can be represented as a NumericString ('0'..'9', ' ')
- *
- * @param str string to validate.
- * @return true if numeric, fale otherwise.
- */
- public static boolean isNumericString(
- String str)
- {
- for (int i = str.length() - 1; i >= 0; i--)
- {
- char ch = str.charAt(i);
-
- if (ch > 0x007f)
- {
- return false;
- }
-
- if (('0' <= ch && ch <= '9') || ch == ' ')
- {
- continue;
- }
-
- return false;
- }
-
- return true;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERObject.java pdftk-2.01/java/org/bouncycastle/asn1/DERObject.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERObject.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERObject.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,20 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public abstract class DERObject
- extends ASN1Encodable
- implements DERTags
-{
- public DERObject toASN1Object()
- {
- return this;
- }
-
- public abstract int hashCode();
-
- public abstract boolean equals(Object o);
-
- abstract void encode(DEROutputStream out)
- throws IOException;
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERObjectIdentifier.java pdftk-2.01/java/org/bouncycastle/asn1/DERObjectIdentifier.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERObjectIdentifier.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERObjectIdentifier.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,293 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.math.BigInteger;
-
-public class DERObjectIdentifier
- extends ASN1Object
-{
- String identifier;
-
- /**
- * return an OID from the passed in object
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERObjectIdentifier getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERObjectIdentifier)
- {
- return (DERObjectIdentifier)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERObjectIdentifier(((ASN1OctetString)obj).getOctets());
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an Object Identifier from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERObjectIdentifier getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
-
- DERObjectIdentifier(
- byte[] bytes)
- {
- StringBuffer objId = new StringBuffer();
- long value = 0;
- BigInteger bigValue = null;
- boolean first = true;
-
- for (int i = 0; i != bytes.length; i++)
- {
- int b = bytes[i] & 0xff;
-
- if (value < 0x80000000000000L)
- {
- value = value * 128 + (b & 0x7f);
- if ((b & 0x80) == 0) // end of number reached
- {
- if (first)
- {
- switch ((int)value / 40)
- {
- case 0:
- objId.append('0');
- break;
- case 1:
- objId.append('1');
- value -= 40;
- break;
- default:
- objId.append('2');
- value -= 80;
- }
- first = false;
- }
-
- objId.append('.');
- objId.append(value);
- value = 0;
- }
- }
- else
- {
- if (bigValue == null)
- {
- bigValue = BigInteger.valueOf(value);
- }
- bigValue = bigValue.shiftLeft(7);
- bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
- if ((b & 0x80) == 0)
- {
- objId.append('.');
- objId.append(bigValue);
- bigValue = null;
- value = 0;
- }
- }
- }
-
- this.identifier = objId.toString();
- }
-
- public DERObjectIdentifier(
- String identifier)
- {
- if (!isValidIdentifier(identifier))
- {
- throw new IllegalArgumentException("string " + identifier + " not an OID");
- }
-
- this.identifier = identifier;
- }
-
- public String getId()
- {
- return identifier;
- }
-
- private void writeField(
- OutputStream out,
- long fieldValue)
- throws IOException
- {
- if (fieldValue >= (1L << 7))
- {
- if (fieldValue >= (1L << 14))
- {
- if (fieldValue >= (1L << 21))
- {
- if (fieldValue >= (1L << 28))
- {
- if (fieldValue >= (1L << 35))
- {
- if (fieldValue >= (1L << 42))
- {
- if (fieldValue >= (1L << 49))
- {
- if (fieldValue >= (1L << 56))
- {
- out.write((int)(fieldValue >> 56) | 0x80);
- }
- out.write((int)(fieldValue >> 49) | 0x80);
- }
- out.write((int)(fieldValue >> 42) | 0x80);
- }
- out.write((int)(fieldValue >> 35) | 0x80);
- }
- out.write((int)(fieldValue >> 28) | 0x80);
- }
- out.write((int)(fieldValue >> 21) | 0x80);
- }
- out.write((int)(fieldValue >> 14) | 0x80);
- }
- out.write((int)(fieldValue >> 7) | 0x80);
- }
- out.write((int)fieldValue & 0x7f);
- }
-
- private void writeField(
- OutputStream out,
- BigInteger fieldValue)
- throws IOException
- {
- int byteCount = (fieldValue.bitLength()+6)/7;
- if (byteCount == 0)
- {
- out.write(0);
- }
- else
- {
- BigInteger tmpValue = fieldValue;
- byte[] tmp = new byte[byteCount];
- for (int i = byteCount-1; i >= 0; i--)
- {
- tmp[i] = (byte) ((tmpValue.intValue() & 0x7f) | 0x80);
- tmpValue = tmpValue.shiftRight(7);
- }
- tmp[byteCount-1] &= 0x7f;
- out.write(tmp);
- }
-
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- OIDTokenizer tok = new OIDTokenizer(identifier);
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DEROutputStream dOut = new DEROutputStream(bOut);
-
- writeField(bOut,
- Integer.parseInt(tok.nextToken()) * 40
- + Integer.parseInt(tok.nextToken()));
-
- while (tok.hasMoreTokens())
- {
- String token = tok.nextToken();
- if (token.length() < 18)
- {
- writeField(bOut, Long.parseLong(token));
- }
- else
- {
- writeField(bOut, new BigInteger(token));
- }
- }
-
- dOut.close();
-
- byte[] bytes = bOut.toByteArray();
-
- out.writeEncoded(OBJECT_IDENTIFIER, bytes);
- }
-
- public int hashCode()
- {
- return identifier.hashCode();
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERObjectIdentifier))
- {
- return false;
- }
-
- return identifier.equals(((DERObjectIdentifier)o).identifier);
- }
-
- public String toString()
- {
- return getId();
- }
-
- private static boolean isValidIdentifier(
- String identifier)
- {
- if (identifier.length() < 3
- || identifier.charAt(1) != '.')
- {
- return false;
- }
-
- char first = identifier.charAt(0);
- if (first < '0' || first > '2')
- {
- return false;
- }
-
- boolean periodAllowed = false;
- for (int i = identifier.length() - 1; i >= 2; i--)
- {
- char ch = identifier.charAt(i);
-
- if ('0' <= ch && ch <= '9')
- {
- periodAllowed = true;
- continue;
- }
-
- if (ch == '.')
- {
- if (!periodAllowed)
- {
- return false;
- }
-
- periodAllowed = false;
- continue;
- }
-
- return false;
- }
-
- return periodAllowed;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DEROctetString.java pdftk-2.01/java/org/bouncycastle/asn1/DEROctetString.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DEROctetString.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DEROctetString.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,37 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DEROctetString
- extends ASN1OctetString
-{
- /**
- * @param string the octets making up the octet string.
- */
- public DEROctetString(
- byte[] string)
- {
- super(string);
- }
-
- public DEROctetString(
- DEREncodable obj)
- {
- super(obj);
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(OCTET_STRING, string);
- }
-
- static void encode(
- DEROutputStream derOut,
- byte[] bytes)
- throws IOException
- {
- derOut.writeEncoded(DERTags.OCTET_STRING, bytes);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DEROctetStringParser.java pdftk-2.01/java/org/bouncycastle/asn1/DEROctetStringParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DEROctetStringParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DEROctetStringParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,33 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.InputStream;
-import java.io.IOException;
-
-public class DEROctetStringParser
- implements ASN1OctetStringParser
-{
- private DefiniteLengthInputStream stream;
-
- DEROctetStringParser(
- DefiniteLengthInputStream stream)
- {
- this.stream = stream;
- }
-
- public InputStream getOctetStream()
- {
- return stream;
- }
-
- public DERObject getDERObject()
- {
- try
- {
- return new DEROctetString(stream.toByteArray());
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DEROutputStream.java pdftk-2.01/java/org/bouncycastle/asn1/DEROutputStream.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DEROutputStream.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DEROutputStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,134 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class DEROutputStream
- extends FilterOutputStream implements DERTags
-{
- public DEROutputStream(
- OutputStream os)
- {
- super(os);
- }
-
- private void writeLength(
- int length)
- throws IOException
- {
- if (length > 127)
- {
- int size = 1;
- int val = length;
-
- while ((val >>>= 8) != 0)
- {
- size++;
- }
-
- write((byte)(size | 0x80));
-
- for (int i = (size - 1) * 8; i >= 0; i -= 8)
- {
- write((byte)(length >> i));
- }
- }
- else
- {
- write((byte)length);
- }
- }
-
- void writeEncoded(
- int tag,
- byte[] bytes)
- throws IOException
- {
- write(tag);
- writeLength(bytes.length);
- write(bytes);
- }
-
- void writeTag(int flags, int tagNo)
- throws IOException
- {
- if (tagNo < 31)
- {
- write(flags | tagNo);
- }
- else
- {
- write(flags | 0x1f);
- if (tagNo < 128)
- {
- write(tagNo);
- }
- else
- {
- byte[] stack = new byte[5];
- int pos = stack.length;
-
- stack[--pos] = (byte)(tagNo & 0x7F);
-
- do
- {
- tagNo >>= 7;
- stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
- }
- while (tagNo > 127);
-
- write(stack, pos, stack.length - pos);
- }
- }
- }
-
- void writeEncoded(int flags, int tagNo, byte[] bytes)
- throws IOException
- {
- writeTag(flags, tagNo);
- writeLength(bytes.length);
- write(bytes);
- }
-
- protected void writeNull()
- throws IOException
- {
- write(NULL);
- write(0x00);
- }
-
- public void write(byte[] buf)
- throws IOException
- {
- out.write(buf, 0, buf.length);
- }
-
- public void write(byte[] buf, int offSet, int len)
- throws IOException
- {
- out.write(buf, offSet, len);
- }
-
- public void writeObject(
- Object obj)
- throws IOException
- {
- if (obj == null)
- {
- writeNull();
- }
- else if (obj instanceof DERObject)
- {
- ((DERObject)obj).encode(this);
- }
- else if (obj instanceof DEREncodable)
- {
- ((DEREncodable)obj).getDERObject().encode(this);
- }
- else
- {
- throw new IOException("object not DEREncodable");
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERPrintableString.java pdftk-2.01/java/org/bouncycastle/asn1/DERPrintableString.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERPrintableString.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERPrintableString.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,204 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER PrintableString object.
- */
-public class DERPrintableString
- extends ASN1Object
- implements DERString
-{
- String string;
-
- /**
- * return a printable string from the passed in object.
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERPrintableString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERPrintableString)
- {
- return (DERPrintableString)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERPrintableString(((ASN1OctetString)obj).getOctets());
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a Printable String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERPrintableString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- /**
- * basic constructor - byte encoded string.
- */
- public DERPrintableString(
- byte[] string)
- {
- char[] cs = new char[string.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- cs[i] = (char)(string[i] & 0xff);
- }
-
- this.string = new String(cs);
- }
-
- /**
- * basic constructor - this does not validate the string
- */
- public DERPrintableString(
- String string)
- {
- this(string, false);
- }
-
- /**
- * Constructor with optional validation.
- *
- * @param string the base string to wrap.
- * @param validate whether or not to check the string.
- * @throws IllegalArgumentException if validate is true and the string
- * contains characters that should not be in a PrintableString.
- */
- public DERPrintableString(
- String string,
- boolean validate)
- {
- if (validate && !isPrintableString(string))
- {
- throw new IllegalArgumentException("string contains illegal characters");
- }
-
- this.string = string;
- }
-
- public String getString()
- {
- return string;
- }
-
- public byte[] getOctets()
- {
- char[] cs = string.toCharArray();
- byte[] bs = new byte[cs.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- bs[i] = (byte)cs[i];
- }
-
- return bs;
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(PRINTABLE_STRING, this.getOctets());
- }
-
- public int hashCode()
- {
- return this.getString().hashCode();
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERPrintableString))
- {
- return false;
- }
-
- DERPrintableString s = (DERPrintableString)o;
-
- return this.getString().equals(s.getString());
- }
-
- public String toString()
- {
- return string;
- }
-
- /**
- * return true if the passed in String can be represented without
- * loss as a PrintableString, false otherwise.
- *
- * @return true if in printable set, false otherwise.
- */
- public static boolean isPrintableString(
- String str)
- {
- for (int i = str.length() - 1; i >= 0; i--)
- {
- char ch = str.charAt(i);
-
- if (ch > 0x007f)
- {
- return false;
- }
-
- if ('a' <= ch && ch <= 'z')
- {
- continue;
- }
-
- if ('A' <= ch && ch <= 'Z')
- {
- continue;
- }
-
- if ('0' <= ch && ch <= '9')
- {
- continue;
- }
-
- switch (ch)
- {
- case ' ':
- case '\'':
- case '(':
- case ')':
- case '+':
- case '-':
- case '.':
- case ':':
- case '=':
- case '?':
- case '/':
- case ',':
- continue;
- }
-
- return false;
- }
-
- return true;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERSequence.java pdftk-2.01/java/org/bouncycastle/asn1/DERSequence.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERSequence.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERSequence.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,80 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-
-public class DERSequence
- extends ASN1Sequence
-{
- /**
- * create an empty sequence
- */
- public DERSequence()
- {
- }
-
- /**
- * create a sequence containing one object
- */
- public DERSequence(
- DEREncodable obj)
- {
- this.addObject(obj);
- }
-
- /**
- * create a sequence containing a vector of objects.
- */
- public DERSequence(
- DEREncodableVector v)
- {
- for (int i = 0; i != v.size(); i++)
- {
- this.addObject(v.get(i));
- }
- }
-
- /**
- * create a sequence containing an array of objects.
- */
- public DERSequence(
- ASN1Encodable[] a)
- {
- for (int i = 0; i != a.length; i++)
- {
- this.addObject(a[i]);
- }
- }
-
- /*
- * A note on the implementation:
- *
- * As DER requires the constructed, definite-length model to
- * be used for structured types, this varies slightly from the
- * ASN.1 descriptions given. Rather than just outputing SEQUENCE,
- * we also have to specify CONSTRUCTED, and the objects length.
- */
- void encode(
- DEROutputStream out)
- throws IOException
- {
- // TODO Intermediate buffer could be avoided if we could calculate expected length
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DEROutputStream dOut = new DEROutputStream(bOut);
- Enumeration e = this.getObjects();
-
- while (e.hasMoreElements())
- {
- Object obj = e.nextElement();
-
- dOut.writeObject(obj);
- }
-
- dOut.close();
-
- byte[] bytes = bOut.toByteArray();
-
- out.writeEncoded(SEQUENCE | CONSTRUCTED, bytes);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERSequenceParser.java pdftk-2.01/java/org/bouncycastle/asn1/DERSequenceParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERSequenceParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERSequenceParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,32 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DERSequenceParser
- implements ASN1SequenceParser
-{
- private ASN1StreamParser _parser;
-
- DERSequenceParser(ASN1StreamParser parser)
- {
- this._parser = parser;
- }
-
- public DEREncodable readObject()
- throws IOException
- {
- return _parser.readObject();
- }
-
- public DERObject getDERObject()
- {
- try
- {
- return new DERSequence(_parser.readVector());
- }
- catch (IOException e)
- {
- throw new IllegalStateException(e.getMessage());
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERSet.java pdftk-2.01/java/org/bouncycastle/asn1/DERSet.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERSet.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERSet.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,100 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-
-/**
- * A DER encoded set object
- */
-public class DERSet
- extends ASN1Set
-{
- /**
- * create an empty set
- */
- public DERSet()
- {
- }
-
- /**
- * @param obj - a single object that makes up the set.
- */
- public DERSet(
- DEREncodable obj)
- {
- this.addObject(obj);
- }
-
- /**
- * @param v - a vector of objects making up the set.
- */
- public DERSet(
- DEREncodableVector v)
- {
- this(v, true);
- }
-
- /**
- * create a set from an array of objects.
- */
- public DERSet(
- ASN1Encodable[] a)
- {
- for (int i = 0; i != a.length; i++)
- {
- this.addObject(a[i]);
- }
-
- this.sort();
- }
-
- /**
- * @param v - a vector of objects making up the set.
- */
- DERSet(
- DEREncodableVector v,
- boolean needsSorting)
- {
- for (int i = 0; i != v.size(); i++)
- {
- this.addObject(v.get(i));
- }
-
- if (needsSorting)
- {
- this.sort();
- }
- }
-
- /*
- * A note on the implementation:
- *
- * As DER requires the constructed, definite-length model to
- * be used for structured types, this varies slightly from the
- * ASN.1 descriptions given. Rather than just outputing SET,
- * we also have to specify CONSTRUCTED, and the objects length.
- */
- void encode(
- DEROutputStream out)
- throws IOException
- {
- // TODO Intermediate buffer could be avoided if we could calculate expected length
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- DEROutputStream dOut = new DEROutputStream(bOut);
- Enumeration e = this.getObjects();
-
- while (e.hasMoreElements())
- {
- Object obj = e.nextElement();
-
- dOut.writeObject(obj);
- }
-
- dOut.close();
-
- byte[] bytes = bOut.toByteArray();
-
- out.writeEncoded(SET | CONSTRUCTED, bytes);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERSetParser.java pdftk-2.01/java/org/bouncycastle/asn1/DERSetParser.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERSetParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERSetParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,32 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-public class DERSetParser
- implements ASN1SetParser
-{
- private ASN1StreamParser _parser;
-
- DERSetParser(ASN1StreamParser parser)
- {
- this._parser = parser;
- }
-
- public DEREncodable readObject()
- throws IOException
- {
- return _parser.readObject();
- }
-
- public DERObject getDERObject()
- {
- try
- {
- return new DERSet(_parser.readVector(), false);
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException(e.getMessage(), e);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERString.java pdftk-2.01/java/org/bouncycastle/asn1/DERString.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERString.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERString.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,9 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * basic interface for DER string objects.
- */
-public interface DERString
-{
- public String getString();
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERT61String.java pdftk-2.01/java/org/bouncycastle/asn1/DERT61String.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERT61String.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERT61String.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,126 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER T61String (also the teletex string)
- */
-public class DERT61String
- extends ASN1Object
- implements DERString
-{
- String string;
-
- /**
- * return a T61 string from the passed in object.
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERT61String getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERT61String)
- {
- return (DERT61String)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERT61String(((ASN1OctetString)obj).getOctets());
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an T61 String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERT61String getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- /**
- * basic constructor - with bytes.
- */
- public DERT61String(
- byte[] string)
- {
- char[] cs = new char[string.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- cs[i] = (char)(string[i] & 0xff);
- }
-
- this.string = new String(cs);
- }
-
- /**
- * basic constructor - with string.
- */
- public DERT61String(
- String string)
- {
- this.string = string;
- }
-
- public String getString()
- {
- return string;
- }
-
- public String toString()
- {
- return string;
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(T61_STRING, this.getOctets());
- }
-
- public byte[] getOctets()
- {
- char[] cs = string.toCharArray();
- byte[] bs = new byte[cs.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- bs[i] = (byte)cs[i];
- }
-
- return bs;
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERT61String))
- {
- return false;
- }
-
- return this.getString().equals(((DERT61String)o).getString());
- }
-
- public int hashCode()
- {
- return this.getString().hashCode();
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERTaggedObject.java pdftk-2.01/java/org/bouncycastle/asn1/DERTaggedObject.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERTaggedObject.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERTaggedObject.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,85 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER TaggedObject - in ASN.1 notation this is any object preceded by
- * a [n] where n is some number - these are assumed to follow the construction
- * rules (as with sequences).
- */
-public class DERTaggedObject
- extends ASN1TaggedObject
-{
- private static final byte[] ZERO_BYTES = new byte[0];
-
- /**
- * @param tagNo the tag number for this object.
- * @param obj the tagged object.
- */
- public DERTaggedObject(
- int tagNo,
- DEREncodable obj)
- {
- super(tagNo, obj);
- }
-
- /**
- * @param explicit true if an explicitly tagged object.
- * @param tagNo the tag number for this object.
- * @param obj the tagged object.
- */
- public DERTaggedObject(
- boolean explicit,
- int tagNo,
- DEREncodable obj)
- {
- super(explicit, tagNo, obj);
- }
-
- /**
- * create an implicitly tagged object that contains a zero
- * length sequence.
- */
- public DERTaggedObject(
- int tagNo)
- {
- super(false, tagNo, new DERSequence());
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- if (!empty)
- {
- byte[] bytes = obj.getDERObject().getEncoded(DER);
-
- if (explicit)
- {
- out.writeEncoded(CONSTRUCTED | TAGGED, tagNo, bytes);
- }
- else
- {
- //
- // need to mark constructed types...
- //
- int flags;
- if ((bytes[0] & CONSTRUCTED) != 0)
- {
- flags = CONSTRUCTED | TAGGED;
- }
- else
- {
- flags = TAGGED;
- }
-
- out.writeTag(flags, tagNo);
- out.write(bytes, 1, bytes.length - 1);
- }
- }
- else
- {
- out.writeEncoded(CONSTRUCTED | TAGGED, tagNo, ZERO_BYTES);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERTags.java pdftk-2.01/java/org/bouncycastle/asn1/DERTags.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERTags.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERTags.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,36 +0,0 @@
-package org.bouncycastle.asn1;
-
-public interface DERTags
-{
- public static final int BOOLEAN = 0x01;
- public static final int INTEGER = 0x02;
- public static final int BIT_STRING = 0x03;
- public static final int OCTET_STRING = 0x04;
- public static final int NULL = 0x05;
- public static final int OBJECT_IDENTIFIER = 0x06;
- public static final int EXTERNAL = 0x08;
- public static final int ENUMERATED = 0x0a;
- public static final int SEQUENCE = 0x10;
- public static final int SEQUENCE_OF = 0x10; // for completeness
- public static final int SET = 0x11;
- public static final int SET_OF = 0x11; // for completeness
-
-
- public static final int NUMERIC_STRING = 0x12;
- public static final int PRINTABLE_STRING = 0x13;
- public static final int T61_STRING = 0x14;
- public static final int VIDEOTEX_STRING = 0x15;
- public static final int IA5_STRING = 0x16;
- public static final int UTC_TIME = 0x17;
- public static final int GENERALIZED_TIME = 0x18;
- public static final int GRAPHIC_STRING = 0x19;
- public static final int VISIBLE_STRING = 0x1a;
- public static final int GENERAL_STRING = 0x1b;
- public static final int UNIVERSAL_STRING = 0x1c;
- public static final int BMP_STRING = 0x1e;
- public static final int UTF8_STRING = 0x0c;
-
- public static final int CONSTRUCTED = 0x20;
- public static final int APPLICATION = 0x40;
- public static final int TAGGED = 0x80;
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERUTCTime.java pdftk-2.01/java/org/bouncycastle/asn1/DERUTCTime.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERUTCTime.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERUTCTime.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,254 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.SimpleTimeZone;
-
-/**
- * UTC time object.
- */
-public class DERUTCTime
- extends ASN1Object
-{
- String time;
-
- /**
- * return an UTC Time from the passed in object.
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERUTCTime getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERUTCTime)
- {
- return (DERUTCTime)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERUTCTime(((ASN1OctetString)obj).getOctets());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return an UTC Time from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERUTCTime getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- /**
- * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
- * never encoded. When you're creating one of these objects from scratch, that's
- * what you want to use, otherwise we'll try to deal with whatever gets read from
- * the input stream... (this is why the input format is different from the getTime()
- * method output).
- *
- *
- * @param time the time string.
- */
- public DERUTCTime(
- String time)
- {
- this.time = time;
- try
- {
- this.getDate();
- }
- catch (ParseException e)
- {
- throw new IllegalArgumentException("invalid date string: " + e.getMessage());
- }
- }
-
- /**
- * base constructer from a java.util.date object
- */
- public DERUTCTime(
- Date time)
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
-
- dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
-
- this.time = dateF.format(time);
- }
-
- DERUTCTime(
- byte[] bytes)
- {
- //
- // explicitly convert to characters
- //
- char[] dateC = new char[bytes.length];
-
- for (int i = 0; i != dateC.length; i++)
- {
- dateC[i] = (char)(bytes[i] & 0xff);
- }
-
- this.time = new String(dateC);
- }
-
- /**
- * return the time as a date based on whatever a 2 digit year will return. For
- * standardised processing use getAdjustedDate().
- *
- * @return the resulting date
- * @exception ParseException if the date string cannot be parsed.
- */
- public Date getDate()
- throws ParseException
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz");
-
- return dateF.parse(getTime());
- }
-
- /**
- * return the time as an adjusted date
- * in the range of 1950 - 2049.
- *
- * @return a date in the range of 1950 to 2049.
- * @exception ParseException if the date string cannot be parsed.
- */
- public Date getAdjustedDate()
- throws ParseException
- {
- SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
-
- dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
-
- return dateF.parse(getAdjustedTime());
- }
-
- /**
- * return the time - always in the form of
- * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
- *
- * Normally in a certificate we would expect "Z" rather than "GMT",
- * however adding the "GMT" means we can just use:
- *
- * dateF = new SimpleDateFormat("yyMMddHHmmssz");
- *
- * To read in the time and get a date which is compatible with our local
- * time zone.
- *
- * Note: In some cases, due to the local date processing, this
- * may lead to unexpected results. If you want to stick the normal
- * convention of 1950 to 2049 use the getAdjustedTime() method.
- */
- public String getTime()
- {
- //
- // standardise the format.
- //
- if (time.indexOf('-') < 0 && time.indexOf('+') < 0)
- {
- if (time.length() == 11)
- {
- return time.substring(0, 10) + "00GMT+00:00";
- }
- else
- {
- return time.substring(0, 12) + "GMT+00:00";
- }
- }
- else
- {
- int index = time.indexOf('-');
- if (index < 0)
- {
- index = time.indexOf('+');
- }
- String d = time;
-
- if (index == time.length() - 3)
- {
- d += "00";
- }
-
- if (index == 10)
- {
- return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
- }
- else
- {
- return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
- }
- }
- }
-
- /**
- * return a time string as an adjusted date with a 4 digit year. This goes
- * in the range of 1950 - 2049.
- */
- public String getAdjustedTime()
- {
- String d = this.getTime();
-
- if (d.charAt(0) < '5')
- {
- return "20" + d;
- }
- else
- {
- return "19" + d;
- }
- }
-
- private byte[] getOctets()
- {
- char[] cs = time.toCharArray();
- byte[] bs = new byte[cs.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- bs[i] = (byte)cs[i];
- }
-
- return bs;
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(UTC_TIME, this.getOctets());
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERUTCTime))
- {
- return false;
- }
-
- return time.equals(((DERUTCTime)o).time);
- }
-
- public int hashCode()
- {
- return time.hashCode();
- }
-
- public String toString()
- {
- return time;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERUTF8String.java pdftk-2.01/java/org/bouncycastle/asn1/DERUTF8String.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERUTF8String.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERUTF8String.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,109 +0,0 @@
-package org.bouncycastle.asn1;
-
-import org.bouncycastle.util.Strings;
-
-import java.io.IOException;
-
-/**
- * DER UTF8String object.
- */
-public class DERUTF8String
- extends ASN1Object
- implements DERString
-{
- String string;
-
- /**
- * return an UTF8 string from the passed in object.
- *
- * @exception IllegalArgumentException
- * if the object cannot be converted.
- */
- public static DERUTF8String getInstance(Object obj)
- {
- if (obj == null || obj instanceof DERUTF8String)
- {
- return (DERUTF8String)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERUTF8String(((ASN1OctetString)obj).getOctets());
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: "
- + obj.getClass().getName());
- }
-
- /**
- * return an UTF8 String from a tagged object.
- *
- * @param obj
- * the tagged object holding the object we want
- * @param explicit
- * true if the object is meant to be explicitly tagged false
- * otherwise.
- * @exception IllegalArgumentException
- * if the tagged object cannot be converted.
- */
- public static DERUTF8String getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- /**
- * basic constructor - byte encoded string.
- */
- DERUTF8String(byte[] string)
- {
- this.string = Strings.fromUTF8ByteArray(string);
- }
-
- /**
- * basic constructor
- */
- public DERUTF8String(String string)
- {
- this.string = string;
- }
-
- public String getString()
- {
- return string;
- }
-
- public String toString()
- {
- return string;
- }
-
- public int hashCode()
- {
- return this.getString().hashCode();
- }
-
- boolean asn1Equals(DERObject o)
- {
- if (!(o instanceof DERUTF8String))
- {
- return false;
- }
-
- DERUTF8String s = (DERUTF8String)o;
-
- return this.getString().equals(s.getString());
- }
-
- void encode(DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(UTF8_STRING, Strings.toUTF8ByteArray(string));
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERUniversalString.java pdftk-2.01/java/org/bouncycastle/asn1/DERUniversalString.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERUniversalString.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERUniversalString.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,120 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-/**
- * DER UniversalString object.
- */
-public class DERUniversalString
- extends ASN1Object
- implements DERString
-{
- private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
- private byte[] string;
-
- /**
- * return a Universal String from the passed in object.
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERUniversalString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERUniversalString)
- {
- return (DERUniversalString)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERUniversalString(((ASN1OctetString)obj).getOctets());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a Universal String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERUniversalString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- /**
- * basic constructor - byte encoded string.
- */
- public DERUniversalString(
- byte[] string)
- {
- this.string = string;
- }
-
- public String getString()
- {
- StringBuffer buf = new StringBuffer("#");
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- ASN1OutputStream aOut = new ASN1OutputStream(bOut);
-
- try
- {
- aOut.writeObject(this);
- }
- catch (IOException e)
- {
- throw new RuntimeException("internal error encoding BitString");
- }
-
- byte[] string = bOut.toByteArray();
-
- for (int i = 0; i != string.length; i++)
- {
- buf.append(table[(string[i] >>> 4) & 0xf]);
- buf.append(table[string[i] & 0xf]);
- }
-
- return buf.toString();
- }
-
- public String toString()
- {
- return getString();
- }
-
- public byte[] getOctets()
- {
- return string;
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(UNIVERSAL_STRING, this.getOctets());
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERUniversalString))
- {
- return false;
- }
-
- return this.getString().equals(((DERUniversalString)o).getString());
- }
-
- public int hashCode()
- {
- return this.getString().hashCode();
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERUnknownTag.java pdftk-2.01/java/org/bouncycastle/asn1/DERUnknownTag.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERUnknownTag.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERUnknownTag.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,79 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-import org.bouncycastle.util.Arrays;
-
-/**
- * We insert one of these when we find a tag we don't recognise.
- */
-public class DERUnknownTag
- extends DERObject
-{
- private boolean isConstructed;
- private int tag;
- private byte[] data;
-
- /**
- * @param tag the tag value.
- * @param data the contents octets.
- */
- public DERUnknownTag(
- int tag,
- byte[] data)
- {
- this(false, tag, data);
- }
-
- public DERUnknownTag(
- boolean isConstructed,
- int tag,
- byte[] data)
- {
- this.isConstructed = isConstructed;
- this.tag = tag;
- this.data = data;
- }
-
- public boolean isConstructed()
- {
- return isConstructed;
- }
-
- public int getTag()
- {
- return tag;
- }
-
- public byte[] getData()
- {
- return data;
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(isConstructed ? DERTags.CONSTRUCTED : 0, tag, data);
- }
-
- public boolean equals(
- Object o)
- {
- if (!(o instanceof DERUnknownTag))
- {
- return false;
- }
-
- DERUnknownTag other = (DERUnknownTag)o;
-
- return isConstructed == other.isConstructed
- && tag == other.tag
- && Arrays.areEqual(data, other.data);
- }
-
- public int hashCode()
- {
- return (isConstructed ? ~0 : 0) ^ tag ^ Arrays.hashCode(data);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DERVisibleString.java pdftk-2.01/java/org/bouncycastle/asn1/DERVisibleString.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DERVisibleString.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DERVisibleString.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,126 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-
-/**
- * DER VisibleString object.
- */
-public class DERVisibleString
- extends ASN1Object
- implements DERString
-{
- String string;
-
- /**
- * return a Visible String from the passed in object.
- *
- * @exception IllegalArgumentException if the object cannot be converted.
- */
- public static DERVisibleString getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof DERVisibleString)
- {
- return (DERVisibleString)obj;
- }
-
- if (obj instanceof ASN1OctetString)
- {
- return new DERVisibleString(((ASN1OctetString)obj).getOctets());
- }
-
- if (obj instanceof ASN1TaggedObject)
- {
- return getInstance(((ASN1TaggedObject)obj).getObject());
- }
-
- throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
- }
-
- /**
- * return a Visible String from a tagged object.
- *
- * @param obj the tagged object holding the object we want
- * @param explicit true if the object is meant to be explicitly
- * tagged false otherwise.
- * @exception IllegalArgumentException if the tagged object cannot
- * be converted.
- */
- public static DERVisibleString getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject());
- }
-
- /**
- * basic constructor - byte encoded string.
- */
- public DERVisibleString(
- byte[] string)
- {
- char[] cs = new char[string.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- cs[i] = (char)(string[i] & 0xff);
- }
-
- this.string = new String(cs);
- }
-
- /**
- * basic constructor
- */
- public DERVisibleString(
- String string)
- {
- this.string = string;
- }
-
- public String getString()
- {
- return string;
- }
-
- public String toString()
- {
- return string;
- }
-
- public byte[] getOctets()
- {
- char[] cs = string.toCharArray();
- byte[] bs = new byte[cs.length];
-
- for (int i = 0; i != cs.length; i++)
- {
- bs[i] = (byte)cs[i];
- }
-
- return bs;
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(VISIBLE_STRING, this.getOctets());
- }
-
- boolean asn1Equals(
- DERObject o)
- {
- if (!(o instanceof DERVisibleString))
- {
- return false;
- }
-
- return this.getString().equals(((DERVisibleString)o).getString());
- }
-
- public int hashCode()
- {
- return this.getString().hashCode();
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java pdftk-2.01/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java
--- pdftk-1.45/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/DefiniteLengthInputStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,105 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bouncycastle.util.io.Streams;
-
-class DefiniteLengthInputStream
- extends LimitedInputStream
-{
- private static final byte[] EMPTY_BYTES = new byte[0];
-
- private final int _originalLength;
- private int _remaining;
-
- DefiniteLengthInputStream(
- InputStream in,
- int length)
- {
- super(in);
-
- if (length < 0)
- {
- throw new IllegalArgumentException("negative lengths not allowed");
- }
-
- this._originalLength = length;
- this._remaining = length;
-
- if (length == 0)
- {
- setParentEofDetect(true);
- }
- }
-
- int getRemaining()
- {
- return _remaining;
- }
-
- public int read()
- throws IOException
- {
- if (_remaining == 0)
- {
- return -1;
- }
-
- int b = _in.read();
-
- if (b < 0)
- {
- throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
- }
-
- if (--_remaining == 0)
- {
- setParentEofDetect(true);
- }
-
- return b;
- }
-
- public int read(byte[] buf, int off, int len)
- throws IOException
- {
- if (_remaining == 0)
- {
- return -1;
- }
-
- int toRead = Math.min(len, _remaining);
- int numRead = _in.read(buf, off, toRead);
-
- if (numRead < 0)
- {
- throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
- }
-
- if ((_remaining -= numRead) == 0)
- {
- setParentEofDetect(true);
- }
-
- return numRead;
- }
-
- byte[] toByteArray()
- throws IOException
- {
- if (_remaining == 0)
- {
- return EMPTY_BYTES;
- }
-
- byte[] bytes = new byte[_remaining];
- if ((_remaining -= Streams.readFully(_in, bytes)) != 0)
- {
- throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
- }
- setParentEofDetect(true);
- return bytes;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/IndefiniteLengthInputStream.java pdftk-2.01/java/org/bouncycastle/asn1/IndefiniteLengthInputStream.java
--- pdftk-1.45/java/org/bouncycastle/asn1/IndefiniteLengthInputStream.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/IndefiniteLengthInputStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,110 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-
-class IndefiniteLengthInputStream
- extends LimitedInputStream
-{
- private int _b1;
- private int _b2;
- private boolean _eofReached = false;
- private boolean _eofOn00 = true;
-
- IndefiniteLengthInputStream(
- InputStream in)
- throws IOException
- {
- super(in);
-
- _b1 = in.read();
- _b2 = in.read();
-
- if (_b2 < 0)
- {
- // Corrupted stream
- throw new EOFException();
- }
-
- checkForEof();
- }
-
- void setEofOn00(
- boolean eofOn00)
- {
- _eofOn00 = eofOn00;
- checkForEof();
- }
-
- private boolean checkForEof()
- {
- if (!_eofReached && _eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
- {
- _eofReached = true;
- setParentEofDetect(true);
- }
- return _eofReached;
- }
-
- public int read(byte[] b, int off, int len)
- throws IOException
- {
- // Only use this optimisation if we aren't checking for 00
- if (_eofOn00 || len < 3)
- {
- return super.read(b, off, len);
- }
-
- if (_eofReached)
- {
- return -1;
- }
-
- int numRead = _in.read(b, off + 2, len - 2);
-
- if (numRead < 0)
- {
- // Corrupted stream
- throw new EOFException();
- }
-
- b[off] = (byte)_b1;
- b[off + 1] = (byte)_b2;
-
- _b1 = _in.read();
- _b2 = _in.read();
-
- if (_b2 < 0)
- {
- // Corrupted stream
- throw new EOFException();
- }
-
- return numRead + 2;
- }
-
- public int read()
- throws IOException
- {
- if (checkForEof())
- {
- return -1;
- }
-
- int b = _in.read();
-
- if (b < 0)
- {
- // Corrupted stream
- throw new EOFException();
- }
-
- int v = _b1;
-
- _b1 = _b2;
- _b2 = b;
-
- return v;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/LazyDERConstructionEnumeration.java pdftk-2.01/java/org/bouncycastle/asn1/LazyDERConstructionEnumeration.java
--- pdftk-1.45/java/org/bouncycastle/asn1/LazyDERConstructionEnumeration.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/LazyDERConstructionEnumeration.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,43 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.util.Enumeration;
-import java.io.IOException;
-
-class LazyDERConstructionEnumeration
- implements Enumeration
-{
- private ASN1InputStream aIn;
- private Object nextObj;
-
- public LazyDERConstructionEnumeration(byte[] encoded)
- {
- aIn = new ASN1InputStream(encoded, true);
- nextObj = readObject();
- }
-
- public boolean hasMoreElements()
- {
- return nextObj != null;
- }
-
- public Object nextElement()
- {
- Object o = nextObj;
-
- nextObj = readObject();
-
- return o;
- }
-
- private Object readObject()
- {
- try
- {
- return aIn.readObject();
- }
- catch (IOException e)
- {
- throw new ASN1ParsingException("malformed DER construction: " + e, e);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/LazyDERSequence.java pdftk-2.01/java/org/bouncycastle/asn1/LazyDERSequence.java
--- pdftk-1.45/java/org/bouncycastle/asn1/LazyDERSequence.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/LazyDERSequence.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,75 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.IOException;
-import java.util.Enumeration;
-
-public class LazyDERSequence
- extends DERSequence
-{
- private byte[] encoded;
- private boolean parsed = false;
- private int size = -1;
-
- LazyDERSequence(
- byte[] encoded)
- throws IOException
- {
- this.encoded = encoded;
- }
-
- private void parse()
- {
- Enumeration en = new LazyDERConstructionEnumeration(encoded);
-
- while (en.hasMoreElements())
- {
- addObject((DEREncodable)en.nextElement());
- }
-
- parsed = true;
- }
-
- public DEREncodable getObjectAt(int index)
- {
- if (!parsed)
- {
- parse();
- }
-
- return super.getObjectAt(index);
- }
-
- public Enumeration getObjects()
- {
- if (parsed)
- {
- return super.getObjects();
- }
-
- return new LazyDERConstructionEnumeration(encoded);
- }
-
- public int size()
- {
- if (size < 0)
- {
- Enumeration en = new LazyDERConstructionEnumeration(encoded);
-
- size = 0;
- while (en.hasMoreElements())
- {
- en.nextElement();
- size++;
- }
- }
-
- return size;
- }
-
- void encode(
- DEROutputStream out)
- throws IOException
- {
- out.writeEncoded(SEQUENCE | CONSTRUCTED, encoded);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/LimitedInputStream.java pdftk-2.01/java/org/bouncycastle/asn1/LimitedInputStream.java
--- pdftk-1.45/java/org/bouncycastle/asn1/LimitedInputStream.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/LimitedInputStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,23 +0,0 @@
-package org.bouncycastle.asn1;
-
-import java.io.InputStream;
-
-abstract class LimitedInputStream
- extends InputStream
-{
- protected final InputStream _in;
-
- LimitedInputStream(
- InputStream in)
- {
- this._in = in;
- }
-
- protected void setParentEofDetect(boolean on)
- {
- if (_in instanceof IndefiniteLengthInputStream)
- {
- ((IndefiniteLengthInputStream)_in).setEofOn00(on);
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/Makefile pdftk-2.01/java/org/bouncycastle/asn1/Makefile
--- pdftk-1.45/java/org/bouncycastle/asn1/Makefile 2010-10-12 13:29:48.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-#library= asn1.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-#all : $(library) $(headers)
-
-#$(library) : $(objects)
-# $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/org/bouncycastle/asn1/OIDTokenizer.java pdftk-2.01/java/org/bouncycastle/asn1/OIDTokenizer.java
--- pdftk-1.45/java/org/bouncycastle/asn1/OIDTokenizer.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/asn1/OIDTokenizer.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,48 +0,0 @@
-package org.bouncycastle.asn1;
-
-/**
- * class for breaking up an OID into it's component tokens, ala
- * java.util.StringTokenizer. We need this class as some of the
- * lightweight Java environment don't support classes like
- * StringTokenizer.
- */
-public class OIDTokenizer
-{
- private String oid;
- private int index;
-
- public OIDTokenizer(
- String oid)
- {
- this.oid = oid;
- this.index = 0;
- }
-
- public boolean hasMoreTokens()
- {
- return (index != -1);
- }
-
- public String nextToken()
- {
- if (index == -1)
- {
- return null;
- }
-
- String token;
- int end = oid.indexOf('.', index);
-
- if (end == -1)
- {
- token = oid.substring(index);
- index = -1;
- return token;
- }
-
- token = oid.substring(index, end);
-
- index = end + 1;
- return token;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/Arrays.java pdftk-2.01/java/org/bouncycastle/util/Arrays.java
--- pdftk-1.45/java/org/bouncycastle/util/Arrays.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/Arrays.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,214 +0,0 @@
-package org.bouncycastle.util;
-
-/**
- * General array utilities.
- */
-public final class Arrays
-{
- private Arrays()
- {
- // static class, hide constructor
- }
-
- public static boolean areEqual(
- boolean[] a,
- boolean[] b)
- {
- if (a == b)
- {
- return true;
- }
-
- if (a == null || b == null)
- {
- return false;
- }
-
- if (a.length != b.length)
- {
- return false;
- }
-
- for (int i = 0; i != a.length; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- public static boolean areEqual(
- byte[] a,
- byte[] b)
- {
- if (a == b)
- {
- return true;
- }
-
- if (a == null || b == null)
- {
- return false;
- }
-
- if (a.length != b.length)
- {
- return false;
- }
-
- for (int i = 0; i != a.length; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * A constant time equals comparison - does not terminate early if
- * test will fail.
- *
- * @param a first array
- * @param b second array
- * @return true if arrays equal, false otherwise.
- */
- public static boolean constantTimeAreEqual(
- byte[] a,
- byte[] b)
- {
- if (a == b)
- {
- return true;
- }
-
- if (a == null || b == null)
- {
- return false;
- }
-
- if (a.length != b.length)
- {
- return false;
- }
-
- int nonEqual = 0;
-
- for (int i = 0; i != a.length; i++)
- {
- nonEqual |= (a[i] ^ b[i]);
- }
-
- return nonEqual == 0;
- }
-
- public static boolean areEqual(
- int[] a,
- int[] b)
- {
- if (a == b)
- {
- return true;
- }
-
- if (a == null || b == null)
- {
- return false;
- }
-
- if (a.length != b.length)
- {
- return false;
- }
-
- for (int i = 0; i != a.length; i++)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
- public static void fill(
- byte[] array,
- byte value)
- {
- for (int i = 0; i < array.length; i++)
- {
- array[i] = value;
- }
- }
-
- public static void fill(
- long[] array,
- long value)
- {
- for (int i = 0; i < array.length; i++)
- {
- array[i] = value;
- }
- }
-
- public static void fill(
- short[] array,
- short value)
- {
- for (int i = 0; i < array.length; i++)
- {
- array[i] = value;
- }
- }
-
- public static int hashCode(byte[] data)
- {
- if (data == null)
- {
- return 0;
- }
-
- int i = data.length;
- int hc = i + 1;
-
- while (--i >= 0)
- {
- hc *= 257;
- hc ^= data[i];
- }
-
- return hc;
- }
-
- public static byte[] clone(byte[] data)
- {
- if (data == null)
- {
- return null;
- }
- byte[] copy = new byte[data.length];
-
- System.arraycopy(data, 0, copy, 0, data.length);
-
- return copy;
- }
-
- public static int[] clone(int[] data)
- {
- if (data == null)
- {
- return null;
- }
- int[] copy = new int[data.length];
-
- System.arraycopy(data, 0, copy, 0, data.length);
-
- return copy;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/BigIntegers.java pdftk-2.01/java/org/bouncycastle/util/BigIntegers.java
--- pdftk-1.45/java/org/bouncycastle/util/BigIntegers.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/BigIntegers.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,78 +0,0 @@
-package org.bouncycastle.util;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-/**
- * BigInteger utilities.
- */
-public final class BigIntegers
-{
- private static final int MAX_ITERATIONS = 1000;
- private static final BigInteger ZERO = BigInteger.valueOf(0);
-
- /**
- * Return the passed in value as an unsigned byte array.
- *
- * @param value value to be converted.
- * @return a byte array without a leading zero byte if present in the signed encoding.
- */
- public static byte[] asUnsignedByteArray(
- BigInteger value)
- {
- byte[] bytes = value.toByteArray();
-
- if (bytes[0] == 0)
- {
- byte[] tmp = new byte[bytes.length - 1];
-
- System.arraycopy(bytes, 1, tmp, 0, tmp.length);
-
- return tmp;
- }
-
- return bytes;
- }
-
- /**
- * Return a random BigInteger not less than 'min' and not greater than 'max'
- *
- * @param min the least value that may be generated
- * @param max the greatest value that may be generated
- * @param random the source of randomness
- * @return a random BigInteger value in the range [min,max]
- */
- public static BigInteger createRandomInRange(
- BigInteger min,
- BigInteger max,
- SecureRandom random)
- {
- int cmp = min.compareTo(max);
- if (cmp >= 0)
- {
- if (cmp > 0)
- {
- throw new IllegalArgumentException("'min' may not be greater than 'max'");
- }
-
- return min;
- }
-
- if (min.bitLength() > max.bitLength() / 2)
- {
- return createRandomInRange(ZERO, max.subtract(min), random).add(min);
- }
-
- for (int i = 0; i < MAX_ITERATIONS; ++i)
- {
- BigInteger x = new BigInteger(max.bitLength(), random);
- if (x.compareTo(min) >= 0 && x.compareTo(max) <= 0)
- {
- return x;
- }
- }
-
- // fall back to a faster (restricted) method
- return new BigInteger(max.subtract(min).bitLength() - 1, random).add(min);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/CollectionStore.java pdftk-2.01/java/org/bouncycastle/util/CollectionStore.java
--- pdftk-1.45/java/org/bouncycastle/util/CollectionStore.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/CollectionStore.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,57 +0,0 @@
-package org.bouncycastle.util;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * A simple collection backed store.
- */
-public class CollectionStore
- implements Store
-{
- private Collection _local;
-
- /**
- * Basic constructor.
- *
- * @param collection - initial contents for the store, this is copied.
- */
- public CollectionStore(
- Collection collection)
- {
- _local = new ArrayList(collection);
- }
-
- /**
- * Return the matches in the collection for the passed in selector.
- *
- * @param selector the selector to match against.
- * @return a possibly empty collection of matching objects.
- */
- public Collection getMatches(Selector selector)
- {
- if (selector == null)
- {
- return new ArrayList(_local);
- }
- else
- {
- List col = new ArrayList();
- Iterator iter = _local.iterator();
-
- while (iter.hasNext())
- {
- Object obj = iter.next();
-
- if (selector.match(obj))
- {
- col.add(obj);
- }
- }
-
- return col;
- }
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/IPAddress.java pdftk-2.01/java/org/bouncycastle/util/IPAddress.java
--- pdftk-1.45/java/org/bouncycastle/util/IPAddress.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/IPAddress.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,188 +0,0 @@
-package org.bouncycastle.util;
-
-public class IPAddress
-{
- /**
- * Validate the given IPv4 or IPv6 address.
- *
- * @param address the IP address as a String.
- *
- * @return true if a valid address, false otherwise
- */
- public static boolean isValid(
- String address)
- {
- return isValidIPv4(address) || isValidIPv6(address);
- }
-
- /**
- * Validate the given IPv4 or IPv6 address and netmask.
- *
- * @param address the IP address as a String.
- *
- * @return true if a valid address with netmask, false otherwise
- */
- public static boolean isValidWithNetMask(
- String address)
- {
- return isValidIPv4WithNetmask(address) || isValidIPv6WithNetmask(address);
- }
-
- /**
- * Validate the given IPv4 address.
- *
- * @param address the IP address as a String.
- *
- * @return true if a valid IPv4 address, false otherwise
- */
- public static boolean isValidIPv4(
- String address)
- {
- if (address.length() == 0)
- {
- return false;
- }
-
- int octet;
- int octets = 0;
-
- String temp = address+".";
-
- int pos;
- int start = 0;
- while (start < temp.length()
- && (pos = temp.indexOf('.', start)) > start)
- {
- if (octets == 4)
- {
- return false;
- }
- try
- {
- octet = Integer.parseInt(temp.substring(start, pos));
- }
- catch (NumberFormatException ex)
- {
- return false;
- }
- if (octet < 0 || octet > 255)
- {
- return false;
- }
- start = pos + 1;
- octets++;
- }
-
- return octets == 4;
- }
-
- public static boolean isValidIPv4WithNetmask(
- String address)
- {
- int index = address.indexOf("/");
- String mask = address.substring(index + 1);
-
- return (index > 0) && isValidIPv4(address.substring(0, index))
- && (isValidIPv4(mask) || isMaskValue(mask, 32));
- }
-
- public static boolean isValidIPv6WithNetmask(
- String address)
- {
- int index = address.indexOf("/");
- String mask = address.substring(index + 1);
-
- return (index > 0) && (isValidIPv6(address.substring(0, index))
- && (isValidIPv6(mask) || isMaskValue(mask, 128)));
- }
-
- private static boolean isMaskValue(String component, int size)
- {
- try
- {
- int value = Integer.parseInt(component);
-
- return value >= 0 && value <= size;
- }
- catch (NumberFormatException e)
- {
- return false;
- }
- }
-
- /**
- * Validate the given IPv6 address.
- *
- * @param address the IP address as a String.
- *
- * @return true if a valid IPv4 address, false otherwise
- */
- public static boolean isValidIPv6(
- String address)
- {
- if (address.length() == 0)
- {
- return false;
- }
-
- int octet;
- int octets = 0;
-
- String temp = address + ":";
- boolean doubleColonFound = false;
- int pos;
- int start = 0;
- while (start < temp.length()
- && (pos = temp.indexOf(':', start)) >= start)
- {
- if (octets == 8)
- {
- return false;
- }
-
- if (start != pos)
- {
- String value = temp.substring(start, pos);
-
- if (pos == (temp.length() - 1) && value.indexOf('.') > 0)
- {
- if (!isValidIPv4(value))
- {
- return false;
- }
-
- octets++; // add an extra one as address covers 2 words.
- }
- else
- {
- try
- {
- octet = Integer.parseInt(temp.substring(start, pos), 16);
- }
- catch (NumberFormatException ex)
- {
- return false;
- }
- if (octet < 0 || octet > 0xffff)
- {
- return false;
- }
- }
- }
- else
- {
- if (pos != 1 && pos != temp.length() - 1 && doubleColonFound)
- {
- return false;
- }
- doubleColonFound = true;
- }
- start = pos + 1;
- octets++;
- }
-
- return octets == 8 || doubleColonFound;
- }
-}
-
-
diff -Nru pdftk-1.45/java/org/bouncycastle/util/Makefile pdftk-2.01/java/org/bouncycastle/util/Makefile
--- pdftk-1.45/java/org/bouncycastle/util/Makefile 2010-10-12 13:29:48.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-#library= asn1.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-#all : $(library) $(headers)
-
-#$(library) : $(objects)
-# $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/org/bouncycastle/util/Selector.java pdftk-2.01/java/org/bouncycastle/util/Selector.java
--- pdftk-1.45/java/org/bouncycastle/util/Selector.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/Selector.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,9 +0,0 @@
-package org.bouncycastle.util;
-
-public interface Selector
- extends Cloneable
-{
- boolean match(Object obj);
-
- Object clone();
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/Store.java pdftk-2.01/java/org/bouncycastle/util/Store.java
--- pdftk-1.45/java/org/bouncycastle/util/Store.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/Store.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,9 +0,0 @@
-package org.bouncycastle.util;
-
-import java.util.Collection;
-
-public interface Store
-{
- Collection getMatches(Selector selector)
- throws StoreException;
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/StoreException.java pdftk-2.01/java/org/bouncycastle/util/StoreException.java
--- pdftk-1.45/java/org/bouncycastle/util/StoreException.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/StoreException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,18 +0,0 @@
-package org.bouncycastle.util;
-
-public class StoreException
- extends RuntimeException
-{
- private Throwable _e;
-
- public StoreException(String s, Throwable e)
- {
- super(s);
- _e = e;
- }
-
- public Throwable getCause()
- {
- return _e;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/StreamParser.java pdftk-2.01/java/org/bouncycastle/util/StreamParser.java
--- pdftk-1.45/java/org/bouncycastle/util/StreamParser.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/StreamParser.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,10 +0,0 @@
-package org.bouncycastle.util;
-
-import java.util.Collection;
-
-public interface StreamParser
-{
- Object read() throws StreamParsingException;
-
- Collection readAll() throws StreamParsingException;
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/StreamParsingException.java pdftk-2.01/java/org/bouncycastle/util/StreamParsingException.java
--- pdftk-1.45/java/org/bouncycastle/util/StreamParsingException.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/StreamParsingException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,18 +0,0 @@
-package org.bouncycastle.util;
-
-public class StreamParsingException
- extends Exception
-{
- Throwable _e;
-
- public StreamParsingException(String message, Throwable e)
- {
- super(message);
- _e = e;
- }
-
- public Throwable getCause()
- {
- return _e;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/Strings.java pdftk-2.01/java/org/bouncycastle/util/Strings.java
--- pdftk-1.45/java/org/bouncycastle/util/Strings.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/Strings.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,246 +0,0 @@
-package org.bouncycastle.util;
-
-import java.io.ByteArrayOutputStream;
-import java.util.Vector;
-
-public final class Strings
-{
- public static String fromUTF8ByteArray(byte[] bytes)
- {
- int i = 0;
- int length = 0;
-
- while (i < bytes.length)
- {
- length++;
- if ((bytes[i] & 0xf0) == 0xf0)
- {
- // surrogate pair
- length++;
- i += 4;
- }
- else if ((bytes[i] & 0xe0) == 0xe0)
- {
- i += 3;
- }
- else if ((bytes[i] & 0xc0) == 0xc0)
- {
- i += 2;
- }
- else
- {
- i += 1;
- }
- }
-
- char[] cs = new char[length];
-
- i = 0;
- length = 0;
-
- while (i < bytes.length)
- {
- char ch;
-
- if ((bytes[i] & 0xf0) == 0xf0)
- {
- int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i+1] & 0x3F) << 12) | ((bytes[i+2] & 0x3F) << 6) | (bytes[i+3] & 0x3F);
- int U = codePoint - 0x10000;
- char W1 = (char)(0xD800 | (U >> 10));
- char W2 = (char)(0xDC00 | (U & 0x3FF));
- cs[length++] = W1;
- ch = W2;
- i += 4;
- }
- else if ((bytes[i] & 0xe0) == 0xe0)
- {
- ch = (char)(((bytes[i] & 0x0f) << 12)
- | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f));
- i += 3;
- }
- else if ((bytes[i] & 0xd0) == 0xd0)
- {
- ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
- i += 2;
- }
- else if ((bytes[i] & 0xc0) == 0xc0)
- {
- ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
- i += 2;
- }
- else
- {
- ch = (char)(bytes[i] & 0xff);
- i += 1;
- }
-
- cs[length++] = ch;
- }
-
- return new String(cs);
- }
-
- public static byte[] toUTF8ByteArray(String string)
- {
- return toUTF8ByteArray(string.toCharArray());
- }
-
- public static byte[] toUTF8ByteArray(char[] string)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
- char[] c = string;
- int i = 0;
-
- while (i < c.length)
- {
- char ch = c[i];
-
- if (ch < 0x0080)
- {
- bOut.write(ch);
- }
- else if (ch < 0x0800)
- {
- bOut.write(0xc0 | (ch >> 6));
- bOut.write(0x80 | (ch & 0x3f));
- }
- // surrogate pair
- else if (ch >= 0xD800 && ch <= 0xDFFF)
- {
- // in error - can only happen, if the Java String class has a
- // bug.
- if (i + 1 >= c.length)
- {
- throw new IllegalStateException("invalid UTF-16 codepoint");
- }
- char W1 = ch;
- ch = c[++i];
- char W2 = ch;
- // in error - can only happen, if the Java String class has a
- // bug.
- if (W1 > 0xDBFF)
- {
- throw new IllegalStateException("invalid UTF-16 codepoint");
- }
- int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000;
- bOut.write(0xf0 | (codePoint >> 18));
- bOut.write(0x80 | ((codePoint >> 12) & 0x3F));
- bOut.write(0x80 | ((codePoint >> 6) & 0x3F));
- bOut.write(0x80 | (codePoint & 0x3F));
- }
- else
- {
- bOut.write(0xe0 | (ch >> 12));
- bOut.write(0x80 | ((ch >> 6) & 0x3F));
- bOut.write(0x80 | (ch & 0x3F));
- }
-
- i++;
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * A locale independent version of toUpperCase.
- *
- * @param string input to be converted
- * @return a US Ascii uppercase version
- */
- public static String toUpperCase(String string)
- {
- boolean changed = false;
- char[] chars = string.toCharArray();
-
- for (int i = 0; i != chars.length; i++)
- {
- char ch = chars[i];
- if ('a' <= ch && 'z' >= ch)
- {
- changed = true;
- chars[i] = (char)(ch - 'a' + 'A');
- }
- }
-
- if (changed)
- {
- return new String(chars);
- }
-
- return string;
- }
-
- /**
- * A locale independent version of toLowerCase.
- *
- * @param string input to be converted
- * @return a US ASCII lowercase version
- */
- public static String toLowerCase(String string)
- {
- boolean changed = false;
- char[] chars = string.toCharArray();
-
- for (int i = 0; i != chars.length; i++)
- {
- char ch = chars[i];
- if ('A' <= ch && 'Z' >= ch)
- {
- changed = true;
- chars[i] = (char)(ch - 'A' + 'a');
- }
- }
-
- if (changed)
- {
- return new String(chars);
- }
-
- return string;
- }
-
- public static byte[] toByteArray(String string)
- {
- byte[] bytes = new byte[string.length()];
-
- for (int i = 0; i != bytes.length; i++)
- {
- char ch = string.charAt(i);
-
- bytes[i] = (byte)ch;
- }
-
- return bytes;
- }
-
- public static String[] split(String input, char delimiter)
- {
- Vector v = new Vector();
- boolean moreTokens = true;
- String subString;
-
- while (moreTokens)
- {
- int tokenLocation = input.indexOf(delimiter);
- if (tokenLocation > 0)
- {
- subString = input.substring(0, tokenLocation);
- v.addElement(subString);
- input = input.substring(tokenLocation + 1);
- }
- else
- {
- moreTokens = false;
- v.addElement(input);
- }
- }
-
- String[] res = new String[v.size()];
-
- for (int i = 0; i != res.length; i++)
- {
- res[i] = (String)v.elementAt(i);
- }
- return res;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/Base64.java pdftk-2.01/java/org/bouncycastle/util/encoders/Base64.java
--- pdftk-1.45/java/org/bouncycastle/util/encoders/Base64.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/Base64.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,121 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class Base64
-{
- private static final Encoder encoder = new Base64Encoder();
-
- /**
- * encode the input data producing a base 64 encoded byte array.
- *
- * @return a byte array containing the base 64 encoded data.
- */
- public static byte[] encode(
- byte[] data)
- {
- int len = (data.length + 2) / 3 * 4;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
-
- try
- {
- encoder.encode(data, 0, data.length, bOut);
- }
- catch (IOException e)
- {
- throw new RuntimeException("exception encoding base64 string: " + e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * Encode the byte data to base 64 writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, 0, data.length, out);
- }
-
- /**
- * Encode the byte data to base 64 writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, off, length, out);
- }
-
- /**
- * decode the base 64 encoded input data. It is assumed the input data is valid.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- byte[] data)
- {
- int len = data.length / 4 * 3;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
-
- try
- {
- encoder.decode(data, 0, data.length, bOut);
- }
- catch (IOException e)
- {
- throw new RuntimeException("exception decoding base64 string: " + e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the base 64 encoded String data - whitespace will be ignored.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- String data)
- {
- int len = data.length() / 4 * 3;
- ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
-
- try
- {
- encoder.decode(data, bOut);
- }
- catch (IOException e)
- {
- throw new RuntimeException("exception decoding base64 string: " + e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the base 64 encoded String data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public static int decode(
- String data,
- OutputStream out)
- throws IOException
- {
- return encoder.decode(data, out);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/Base64Encoder.java pdftk-2.01/java/org/bouncycastle/util/encoders/Base64Encoder.java
--- pdftk-1.45/java/org/bouncycastle/util/encoders/Base64Encoder.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/Base64Encoder.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,298 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class Base64Encoder
- implements Encoder
-{
- protected final byte[] encodingTable =
- {
- (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
- (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
- (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
- (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
- (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
- (byte)'v',
- (byte)'w', (byte)'x', (byte)'y', (byte)'z',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
- (byte)'7', (byte)'8', (byte)'9',
- (byte)'+', (byte)'/'
- };
-
- protected byte padding = (byte)'=';
-
- /*
- * set up the decoding table.
- */
- protected final byte[] decodingTable = new byte[128];
-
- protected void initialiseDecodingTable()
- {
- for (int i = 0; i < encodingTable.length; i++)
- {
- decodingTable[encodingTable[i]] = (byte)i;
- }
- }
-
- public Base64Encoder()
- {
- initialiseDecodingTable();
- }
-
- /**
- * encode the input data producing a base 64 output stream.
- *
- * @return the number of bytes produced.
- */
- public int encode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- int modulus = length % 3;
- int dataLength = (length - modulus);
- int a1, a2, a3;
-
- for (int i = off; i < off + dataLength; i += 3)
- {
- a1 = data[i] & 0xff;
- a2 = data[i + 1] & 0xff;
- a3 = data[i + 2] & 0xff;
-
- out.write(encodingTable[(a1 >>> 2) & 0x3f]);
- out.write(encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]);
- out.write(encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]);
- out.write(encodingTable[a3 & 0x3f]);
- }
-
- /*
- * process the tail end.
- */
- int b1, b2, b3;
- int d1, d2;
-
- switch (modulus)
- {
- case 0: /* nothing left to do */
- break;
- case 1:
- d1 = data[off + dataLength] & 0xff;
- b1 = (d1 >>> 2) & 0x3f;
- b2 = (d1 << 4) & 0x3f;
-
- out.write(encodingTable[b1]);
- out.write(encodingTable[b2]);
- out.write(padding);
- out.write(padding);
- break;
- case 2:
- d1 = data[off + dataLength] & 0xff;
- d2 = data[off + dataLength + 1] & 0xff;
-
- b1 = (d1 >>> 2) & 0x3f;
- b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
- b3 = (d2 << 2) & 0x3f;
-
- out.write(encodingTable[b1]);
- out.write(encodingTable[b2]);
- out.write(encodingTable[b3]);
- out.write(padding);
- break;
- }
-
- return (dataLength / 3) * 4 + ((modulus == 0) ? 0 : 4);
- }
-
- private boolean ignore(
- char c)
- {
- return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
- }
-
- /**
- * decode the base 64 encoded byte data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public int decode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- byte b1, b2, b3, b4;
- int outLen = 0;
-
- int end = off + length;
-
- while (end > off)
- {
- if (!ignore((char)data[end - 1]))
- {
- break;
- }
-
- end--;
- }
-
- int i = off;
- int finish = end - 4;
-
- i = nextI(data, i, finish);
-
- while (i < finish)
- {
- b1 = decodingTable[data[i++]];
-
- i = nextI(data, i, finish);
-
- b2 = decodingTable[data[i++]];
-
- i = nextI(data, i, finish);
-
- b3 = decodingTable[data[i++]];
-
- i = nextI(data, i, finish);
-
- b4 = decodingTable[data[i++]];
-
- out.write((b1 << 2) | (b2 >> 4));
- out.write((b2 << 4) | (b3 >> 2));
- out.write((b3 << 6) | b4);
-
- outLen += 3;
-
- i = nextI(data, i, finish);
- }
-
- outLen += decodeLastBlock(out, (char)data[end - 4], (char)data[end - 3], (char)data[end - 2], (char)data[end - 1]);
-
- return outLen;
- }
-
- private int nextI(byte[] data, int i, int finish)
- {
- while ((i < finish) && ignore((char)data[i]))
- {
- i++;
- }
- return i;
- }
-
- /**
- * decode the base 64 encoded String data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public int decode(
- String data,
- OutputStream out)
- throws IOException
- {
- byte b1, b2, b3, b4;
- int length = 0;
-
- int end = data.length();
-
- while (end > 0)
- {
- if (!ignore(data.charAt(end - 1)))
- {
- break;
- }
-
- end--;
- }
-
- int i = 0;
- int finish = end - 4;
-
- i = nextI(data, i, finish);
-
- while (i < finish)
- {
- b1 = decodingTable[data.charAt(i++)];
-
- i = nextI(data, i, finish);
-
- b2 = decodingTable[data.charAt(i++)];
-
- i = nextI(data, i, finish);
-
- b3 = decodingTable[data.charAt(i++)];
-
- i = nextI(data, i, finish);
-
- b4 = decodingTable[data.charAt(i++)];
-
- out.write((b1 << 2) | (b2 >> 4));
- out.write((b2 << 4) | (b3 >> 2));
- out.write((b3 << 6) | b4);
-
- length += 3;
-
- i = nextI(data, i, finish);
- }
-
- length += decodeLastBlock(out, data.charAt(end - 4), data.charAt(end - 3), data.charAt(end - 2), data.charAt(end - 1));
-
- return length;
- }
-
- private int decodeLastBlock(OutputStream out, char c1, char c2, char c3, char c4)
- throws IOException
- {
- byte b1, b2, b3, b4;
-
- if (c3 == padding)
- {
- b1 = decodingTable[c1];
- b2 = decodingTable[c2];
-
- out.write((b1 << 2) | (b2 >> 4));
-
- return 1;
- }
- else if (c4 == padding)
- {
- b1 = decodingTable[c1];
- b2 = decodingTable[c2];
- b3 = decodingTable[c3];
-
- out.write((b1 << 2) | (b2 >> 4));
- out.write((b2 << 4) | (b3 >> 2));
-
- return 2;
- }
- else
- {
- b1 = decodingTable[c1];
- b2 = decodingTable[c2];
- b3 = decodingTable[c3];
- b4 = decodingTable[c4];
-
- out.write((b1 << 2) | (b2 >> 4));
- out.write((b2 << 4) | (b3 >> 2));
- out.write((b3 << 6) | b4);
-
- return 3;
- }
- }
-
- private int nextI(String data, int i, int finish)
- {
- while ((i < finish) && ignore(data.charAt(i)))
- {
- i++;
- }
- return i;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/BufferedDecoder.java pdftk-2.01/java/org/bouncycastle/util/encoders/BufferedDecoder.java
--- pdftk-1.45/java/org/bouncycastle/util/encoders/BufferedDecoder.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/BufferedDecoder.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,96 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-
-/**
- * a buffering class to allow translation from one format to another to
- * be done in discrete chunks.
- */
-public class BufferedDecoder
-{
- protected byte[] buf;
- protected int bufOff;
-
- protected Translator translator;
-
- /**
- * @param translator the translator to use.
- * @param bufSize amount of input to buffer for each chunk.
- */
- public BufferedDecoder(
- Translator translator,
- int bufSize)
- {
- this.translator = translator;
-
- if ((bufSize % translator.getEncodedBlockSize()) != 0)
- {
- throw new IllegalArgumentException("buffer size not multiple of input block size");
- }
-
- buf = new byte[bufSize];
- bufOff = 0;
- }
-
- public int processByte(
- byte in,
- byte[] out,
- int outOff)
- {
- int resultLen = 0;
-
- buf[bufOff++] = in;
-
- if (bufOff == buf.length)
- {
- resultLen = translator.decode(buf, 0, buf.length, out, outOff);
- bufOff = 0;
- }
-
- return resultLen;
- }
-
- public int processBytes(
- byte[] in,
- int inOff,
- int len,
- byte[] out,
- int outOff)
- {
- if (len < 0)
- {
- throw new IllegalArgumentException("Can't have a negative input length!");
- }
-
- int resultLen = 0;
- int gapLen = buf.length - bufOff;
-
- if (len > gapLen)
- {
- System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
- resultLen += translator.decode(buf, 0, buf.length, out, outOff);
-
- bufOff = 0;
-
- len -= gapLen;
- inOff += gapLen;
- outOff += resultLen;
-
- int chunkSize = len - (len % buf.length);
-
- resultLen += translator.decode(in, inOff, chunkSize, out, outOff);
-
- len -= chunkSize;
- inOff += chunkSize;
- }
-
- if (len != 0)
- {
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
- }
-
- return resultLen;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/BufferedEncoder.java pdftk-2.01/java/org/bouncycastle/util/encoders/BufferedEncoder.java
--- pdftk-1.45/java/org/bouncycastle/util/encoders/BufferedEncoder.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/BufferedEncoder.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,96 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-
-/**
- * a buffering class to allow translation from one format to another to
- * be done in discrete chunks.
- */
-public class BufferedEncoder
-{
- protected byte[] buf;
- protected int bufOff;
-
- protected Translator translator;
-
- /**
- * @param translator the translator to use.
- * @param bufSize amount of input to buffer for each chunk.
- */
- public BufferedEncoder(
- Translator translator,
- int bufSize)
- {
- this.translator = translator;
-
- if ((bufSize % translator.getEncodedBlockSize()) != 0)
- {
- throw new IllegalArgumentException("buffer size not multiple of input block size");
- }
-
- buf = new byte[bufSize];
- bufOff = 0;
- }
-
- public int processByte(
- byte in,
- byte[] out,
- int outOff)
- {
- int resultLen = 0;
-
- buf[bufOff++] = in;
-
- if (bufOff == buf.length)
- {
- resultLen = translator.encode(buf, 0, buf.length, out, outOff);
- bufOff = 0;
- }
-
- return resultLen;
- }
-
- public int processBytes(
- byte[] in,
- int inOff,
- int len,
- byte[] out,
- int outOff)
- {
- if (len < 0)
- {
- throw new IllegalArgumentException("Can't have a negative input length!");
- }
-
- int resultLen = 0;
- int gapLen = buf.length - bufOff;
-
- if (len > gapLen)
- {
- System.arraycopy(in, inOff, buf, bufOff, gapLen);
-
- resultLen += translator.encode(buf, 0, buf.length, out, outOff);
-
- bufOff = 0;
-
- len -= gapLen;
- inOff += gapLen;
- outOff += resultLen;
-
- int chunkSize = len - (len % buf.length);
-
- resultLen += translator.encode(in, inOff, chunkSize, out, outOff);
-
- len -= chunkSize;
- inOff += chunkSize;
- }
-
- if (len != 0)
- {
- System.arraycopy(in, inOff, buf, bufOff, len);
-
- bufOff += len;
- }
-
- return resultLen;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/Encoder.java pdftk-2.01/java/org/bouncycastle/util/encoders/Encoder.java
--- pdftk-1.45/java/org/bouncycastle/util/encoders/Encoder.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/Encoder.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,17 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Encode and decode byte arrays (typically from binary to 7-bit ASCII
- * encodings).
- */
-public interface Encoder
-{
- int encode(byte[] data, int off, int length, OutputStream out) throws IOException;
-
- int decode(byte[] data, int off, int length, OutputStream out) throws IOException;
-
- int decode(String data, OutputStream out) throws IOException;
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/Hex.java pdftk-2.01/java/org/bouncycastle/util/encoders/Hex.java
--- pdftk-1.45/java/org/bouncycastle/util/encoders/Hex.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/Hex.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,131 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class Hex
-{
- private static final Encoder encoder = new HexEncoder();
-
- /**
- * encode the input data producing a Hex encoded byte array.
- *
- * @return a byte array containing the Hex encoded data.
- */
- public static byte[] encode(
- byte[] data)
- {
- return encode(data, 0, data.length);
- }
-
- /**
- * encode the input data producing a Hex encoded byte array.
- *
- * @return a byte array containing the Hex encoded data.
- */
- public static byte[] encode(
- byte[] data,
- int off,
- int length)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.encode(data, off, length, bOut);
- }
- catch (IOException e)
- {
- throw new RuntimeException("exception encoding Hex string: " + e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * Hex encode the byte data writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, 0, data.length, out);
- }
-
- /**
- * Hex encode the byte data writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, off, length, out);
- }
-
- /**
- * decode the Hex encoded input data. It is assumed the input data is valid.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- byte[] data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.decode(data, 0, data.length, bOut);
- }
- catch (IOException e)
- {
- throw new RuntimeException("exception decoding Hex string: " + e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the Hex encoded String data - whitespace will be ignored.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- String data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.decode(data, bOut);
- }
- catch (IOException e)
- {
- throw new RuntimeException("exception decoding Hex string: " + e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the Hex encoded String data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public static int decode(
- String data,
- OutputStream out)
- throws IOException
- {
- return encoder.decode(data, out);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/HexEncoder.java pdftk-2.01/java/org/bouncycastle/util/encoders/HexEncoder.java
--- pdftk-1.45/java/org/bouncycastle/util/encoders/HexEncoder.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/HexEncoder.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,172 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class HexEncoder
- implements Encoder
-{
- protected final byte[] encodingTable =
- {
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
- (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
- };
-
- /*
- * set up the decoding table.
- */
- protected final byte[] decodingTable = new byte[128];
-
- protected void initialiseDecodingTable()
- {
- for (int i = 0; i < encodingTable.length; i++)
- {
- decodingTable[encodingTable[i]] = (byte)i;
- }
-
- decodingTable['A'] = decodingTable['a'];
- decodingTable['B'] = decodingTable['b'];
- decodingTable['C'] = decodingTable['c'];
- decodingTable['D'] = decodingTable['d'];
- decodingTable['E'] = decodingTable['e'];
- decodingTable['F'] = decodingTable['f'];
- }
-
- public HexEncoder()
- {
- initialiseDecodingTable();
- }
-
- /**
- * encode the input data producing a Hex output stream.
- *
- * @return the number of bytes produced.
- */
- public int encode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- for (int i = off; i < (off + length); i++)
- {
- int v = data[i] & 0xff;
-
- out.write(encodingTable[(v >>> 4)]);
- out.write(encodingTable[v & 0xf]);
- }
-
- return length * 2;
- }
-
- private boolean ignore(
- char c)
- {
- return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
- }
-
- /**
- * decode the Hex encoded byte data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public int decode(
- byte[] data,
- int off,
- int length,
- OutputStream out)
- throws IOException
- {
- byte b1, b2;
- int outLen = 0;
-
- int end = off + length;
-
- while (end > off)
- {
- if (!ignore((char)data[end - 1]))
- {
- break;
- }
-
- end--;
- }
-
- int i = off;
- while (i < end)
- {
- while (i < end && ignore((char)data[i]))
- {
- i++;
- }
-
- b1 = decodingTable[data[i++]];
-
- while (i < end && ignore((char)data[i]))
- {
- i++;
- }
-
- b2 = decodingTable[data[i++]];
-
- out.write((b1 << 4) | b2);
-
- outLen++;
- }
-
- return outLen;
- }
-
- /**
- * decode the Hex encoded String data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public int decode(
- String data,
- OutputStream out)
- throws IOException
- {
- byte b1, b2;
- int length = 0;
-
- int end = data.length();
-
- while (end > 0)
- {
- if (!ignore(data.charAt(end - 1)))
- {
- break;
- }
-
- end--;
- }
-
- int i = 0;
- while (i < end)
- {
- while (i < end && ignore(data.charAt(i)))
- {
- i++;
- }
-
- b1 = decodingTable[data.charAt(i++)];
-
- while (i < end && ignore(data.charAt(i)))
- {
- i++;
- }
-
- b2 = decodingTable[data.charAt(i++)];
-
- out.write((b1 << 4) | b2);
-
- length++;
- }
-
- return length;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/HexTranslator.java pdftk-2.01/java/org/bouncycastle/util/encoders/HexTranslator.java
--- pdftk-1.45/java/org/bouncycastle/util/encoders/HexTranslator.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/HexTranslator.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,87 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-/**
- * Converters for going from hex to binary and back. Note: this class assumes ASCII processing.
- */
-public class HexTranslator
- implements Translator
-{
- private static final byte[] hexTable =
- {
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
- (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
- };
-
- /**
- * size of the output block on encoding produced by getDecodedBlockSize()
- * bytes.
- */
- public int getEncodedBlockSize()
- {
- return 2;
- }
-
- public int encode(
- byte[] in,
- int inOff,
- int length,
- byte[] out,
- int outOff)
- {
- for (int i = 0, j = 0; i < length; i++, j += 2)
- {
- out[outOff + j] = hexTable[(in[inOff] >> 4) & 0x0f];
- out[outOff + j + 1] = hexTable[in[inOff] & 0x0f];
-
- inOff++;
- }
-
- return length * 2;
- }
-
- /**
- * size of the output block on decoding produced by getEncodedBlockSize()
- * bytes.
- */
- public int getDecodedBlockSize()
- {
- return 1;
- }
-
- public int decode(
- byte[] in,
- int inOff,
- int length,
- byte[] out,
- int outOff)
- {
- int halfLength = length / 2;
- byte left, right;
- for (int i = 0; i < halfLength; i++)
- {
- left = in[inOff + i * 2];
- right = in[inOff + i * 2 + 1];
-
- if (left < (byte)'a')
- {
- out[outOff] = (byte)((left - '0') << 4);
- }
- else
- {
- out[outOff] = (byte)((left - 'a' + 10) << 4);
- }
- if (right < (byte)'a')
- {
- out[outOff] += (byte)(right - '0');
- }
- else
- {
- out[outOff] += (byte)(right - 'a' + 10);
- }
-
- outOff++;
- }
-
- return halfLength;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/Makefile pdftk-2.01/java/org/bouncycastle/util/encoders/Makefile
--- pdftk-1.45/java/org/bouncycastle/util/encoders/Makefile 2010-10-12 13:29:48.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-#library= asn1.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-#all : $(library) $(headers)
-
-#$(library) : $(objects)
-# $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/Translator.java pdftk-2.01/java/org/bouncycastle/util/encoders/Translator.java
--- pdftk-1.45/java/org/bouncycastle/util/encoders/Translator.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/Translator.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,23 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-/**
- * general interface for an translator.
- */
-public interface Translator
-{
- /**
- * size of the output block on encoding produced by getDecodedBlockSize()
- * bytes.
- */
- public int getEncodedBlockSize();
-
- public int encode(byte[] in, int inOff, int length, byte[] out, int outOff);
-
- /**
- * size of the output block on decoding produced by getEncodedBlockSize()
- * bytes.
- */
- public int getDecodedBlockSize();
-
- public int decode(byte[] in, int inOff, int length, byte[] out, int outOff);
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/UrlBase64.java pdftk-2.01/java/org/bouncycastle/util/encoders/UrlBase64.java
--- pdftk-1.45/java/org/bouncycastle/util/encoders/UrlBase64.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/UrlBase64.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,129 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Convert binary data to and from UrlBase64 encoding. This is identical to
- * Base64 encoding, except that the padding character is "." and the other
- * non-alphanumeric characters are "-" and "_" instead of "+" and "/".
- *
- * The purpose of UrlBase64 encoding is to provide a compact encoding of binary
- * data that is safe for use as an URL parameter. Base64 encoding does not
- * produce encoded values that are safe for use in URLs, since "/" can be
- * interpreted as a path delimiter; "+" is the encoded form of a space; and
- * "=" is used to separate a name from the corresponding value in an URL
- * parameter.
- */
-public class UrlBase64
-{
- private static final Encoder encoder = new UrlBase64Encoder();
-
- /**
- * Encode the input data producing a URL safe base 64 encoded byte array.
- *
- * @return a byte array containing the URL safe base 64 encoded data.
- */
- public static byte[] encode(
- byte[] data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.encode(data, 0, data.length, bOut);
- }
- catch (IOException e)
- {
- throw new RuntimeException("exception encoding URL safe base64 string: " + e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * Encode the byte data writing it to the given output stream.
- *
- * @return the number of bytes produced.
- */
- public static int encode(
- byte[] data,
- OutputStream out)
- throws IOException
- {
- return encoder.encode(data, 0, data.length, out);
- }
-
- /**
- * Decode the URL safe base 64 encoded input data - white space will be ignored.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- byte[] data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.decode(data, 0, data.length, bOut);
- }
- catch (IOException e)
- {
- throw new RuntimeException("exception decoding URL safe base64 string: " + e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * decode the URL safe base 64 encoded byte data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public static int decode(
- byte[] data,
- OutputStream out)
- throws IOException
- {
- return encoder.decode(data, 0, data.length, out);
- }
-
- /**
- * decode the URL safe base 64 encoded String data - whitespace will be ignored.
- *
- * @return a byte array representing the decoded data.
- */
- public static byte[] decode(
- String data)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- try
- {
- encoder.decode(data, bOut);
- }
- catch (IOException e)
- {
- throw new RuntimeException("exception decoding URL safe base64 string: " + e);
- }
-
- return bOut.toByteArray();
- }
-
- /**
- * Decode the URL safe base 64 encoded String data writing it to the given output stream,
- * whitespace characters will be ignored.
- *
- * @return the number of bytes produced.
- */
- public static int decode(
- String data,
- OutputStream out)
- throws IOException
- {
- return encoder.decode(data, out);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/UrlBase64Encoder.java pdftk-2.01/java/org/bouncycastle/util/encoders/UrlBase64Encoder.java
--- pdftk-1.45/java/org/bouncycastle/util/encoders/UrlBase64Encoder.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/UrlBase64Encoder.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,25 +0,0 @@
-package org.bouncycastle.util.encoders;
-
-/**
- * Convert binary data to and from UrlBase64 encoding. This is identical to
- * Base64 encoding, except that the padding character is "." and the other
- * non-alphanumeric characters are "-" and "_" instead of "+" and "/".
- *
- * The purpose of UrlBase64 encoding is to provide a compact encoding of binary
- * data that is safe for use as an URL parameter. Base64 encoding does not
- * produce encoded values that are safe for use in URLs, since "/" can be
- * interpreted as a path delimiter; "+" is the encoded form of a space; and
- * "=" is used to separate a name from the corresponding value in an URL
- * parameter.
- */
-public class UrlBase64Encoder extends Base64Encoder
-{
- public UrlBase64Encoder()
- {
- encodingTable[encodingTable.length - 2] = (byte) '-';
- encodingTable[encodingTable.length - 1] = (byte) '_';
- padding = (byte) '.';
- // we must re-create the decoding table with the new encoded values.
- initialiseDecodingTable();
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/encoders/package.html pdftk-2.01/java/org/bouncycastle/util/encoders/package.html
--- pdftk-1.45/java/org/bouncycastle/util/encoders/package.html 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/encoders/package.html 1970-01-01 00:00:00.000000000 +0000
@@ -1,5 +0,0 @@
-
-
-Classes for producing and reading Base64 and Hex strings.
-
-
diff -Nru pdftk-1.45/java/org/bouncycastle/util/io/Makefile pdftk-2.01/java/org/bouncycastle/util/io/Makefile
--- pdftk-1.45/java/org/bouncycastle/util/io/Makefile 2010-10-12 13:29:48.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/io/Makefile 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# Copyright 2003, 2004, 2010 Sid Steward
-# This is part of pdftk; visit: www.pdftk.com
-#
-
-##
-# variables
-
-#library= asn1.a
-
-sources= $(wildcard *.java)
-objects= $(patsubst %.java, %.o, $(sources))
-headers= $(patsubst %.java, %.h, $(sources))
-classes= $(patsubst %.java, %.class, $(sources))
-
-##
-# implicit rules for creating A from B
-
-%.o : %.java
- $(GCJ) $(GCJFLAGS) -c $< -o $@
-
-%.class : %.java
- $(GCJ) $(GCJFLAGS) -C $<
-
-# gcjh doesn't want the ".class" extension, so use
-# the "$*" automatic variable, here
-#
-%.h : %.class
- $(GCJH) --classpath="." $*;
- $(RM) $<
-
-##
-# targets
-
-#all : $(library) $(headers)
-
-#$(library) : $(objects)
-# $(AR) $(ARFLAGS) $(library) $(objects);
-
-clean :
- $(RM) $(RMFLAGS) *.o *.h *.class *.a
diff -Nru pdftk-1.45/java/org/bouncycastle/util/io/StreamOverflowException.java pdftk-2.01/java/org/bouncycastle/util/io/StreamOverflowException.java
--- pdftk-1.45/java/org/bouncycastle/util/io/StreamOverflowException.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/io/StreamOverflowException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,12 +0,0 @@
-package org.bouncycastle.util.io;
-
-import java.io.IOException;
-
-public class StreamOverflowException
- extends IOException
-{
- public StreamOverflowException(String msg)
- {
- super(msg);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/io/Streams.java pdftk-2.01/java/org/bouncycastle/util/io/Streams.java
--- pdftk-1.45/java/org/bouncycastle/util/io/Streams.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/io/Streams.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,87 +0,0 @@
-package org.bouncycastle.util.io;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public final class Streams
-{
- private static int BUFFER_SIZE = 512;
-
- public static void drain(InputStream inStr)
- throws IOException
- {
- byte[] bs = new byte[BUFFER_SIZE];
- while (inStr.read(bs, 0, bs.length) >= 0)
- {
- }
- }
-
- public static byte[] readAll(InputStream inStr)
- throws IOException
- {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- pipeAll(inStr, buf);
- return buf.toByteArray();
- }
-
- public static byte[] readAllLimited(InputStream inStr, int limit)
- throws IOException
- {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- pipeAllLimited(inStr, limit, buf);
- return buf.toByteArray();
- }
-
- public static int readFully(InputStream inStr, byte[] buf)
- throws IOException
- {
- return readFully(inStr, buf, 0, buf.length);
- }
-
- public static int readFully(InputStream inStr, byte[] buf, int off, int len)
- throws IOException
- {
- int totalRead = 0;
- while (totalRead < len)
- {
- int numRead = inStr.read(buf, off + totalRead, len - totalRead);
- if (numRead < 0)
- {
- break;
- }
- totalRead += numRead;
- }
- return totalRead;
- }
-
- public static void pipeAll(InputStream inStr, OutputStream outStr)
- throws IOException
- {
- byte[] bs = new byte[BUFFER_SIZE];
- int numRead;
- while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
- {
- outStr.write(bs, 0, numRead);
- }
- }
-
- public static long pipeAllLimited(InputStream inStr, long limit, OutputStream outStr)
- throws IOException
- {
- long total = 0;
- byte[] bs = new byte[BUFFER_SIZE];
- int numRead;
- while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
- {
- total += numRead;
- if (total > limit)
- {
- throw new StreamOverflowException("Data Overflow");
- }
- outStr.write(bs, 0, numRead);
- }
- return total;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/test/FixedSecureRandom.java pdftk-2.01/java/org/bouncycastle/util/test/FixedSecureRandom.java
--- pdftk-1.45/java/org/bouncycastle/util/test/FixedSecureRandom.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/test/FixedSecureRandom.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,135 +0,0 @@
-package org.bouncycastle.util.test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.security.SecureRandom;
-
-public class FixedSecureRandom
- extends SecureRandom
-{
- private byte[] _data;
-
- private int _index;
- private int _intPad;
-
- public FixedSecureRandom(byte[] value)
- {
- this(false, new byte[][] { value });
- }
-
- public FixedSecureRandom(
- byte[][] values)
- {
- this(false, values);
- }
-
- /**
- * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
- * implementation.
- */
- public FixedSecureRandom(
- boolean intPad,
- byte[] value)
- {
- this(intPad, new byte[][] { value });
- }
-
- /**
- * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
- * implementation.
- */
- public FixedSecureRandom(
- boolean intPad,
- byte[][] values)
- {
- ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-
- for (int i = 0; i != values.length; i++)
- {
- try
- {
- bOut.write(values[i]);
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException("can't save value array.");
- }
- }
-
- _data = bOut.toByteArray();
-
- if (intPad)
- {
- _intPad = _data.length % 4;
- }
- }
-
- public void nextBytes(byte[] bytes)
- {
- System.arraycopy(_data, _index, bytes, 0, bytes.length);
-
- _index += bytes.length;
- }
-
- //
- // classpath's implementation of SecureRandom doesn't currently go back to nextBytes
- // when next is called. We can't override next as it's a final method.
- //
- public int nextInt()
- {
- int val = 0;
-
- val |= nextValue() << 24;
- val |= nextValue() << 16;
-
- if (_intPad == 2)
- {
- _intPad--;
- }
- else
- {
- val |= nextValue() << 8;
- }
-
- if (_intPad == 1)
- {
- _intPad--;
- }
- else
- {
- val |= nextValue();
- }
-
- return val;
- }
-
- //
- // classpath's implementation of SecureRandom doesn't currently go back to nextBytes
- // when next is called. We can't override next as it's a final method.
- //
- public long nextLong()
- {
- long val = 0;
-
- val |= (long)nextValue() << 56;
- val |= (long)nextValue() << 48;
- val |= (long)nextValue() << 40;
- val |= (long)nextValue() << 32;
- val |= (long)nextValue() << 24;
- val |= (long)nextValue() << 16;
- val |= (long)nextValue() << 8;
- val |= (long)nextValue();
-
- return val;
- }
-
- public boolean isExhausted()
- {
- return _index == _data.length;
- }
-
- private int nextValue()
- {
- return _data[_index++] & 0xff;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/test/NumberParsing.java pdftk-2.01/java/org/bouncycastle/util/test/NumberParsing.java
--- pdftk-1.45/java/org/bouncycastle/util/test/NumberParsing.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/test/NumberParsing.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,34 +0,0 @@
-package org.bouncycastle.util.test;
-
-/**
- * Parsing
- */
-public final class NumberParsing
-{
- private NumberParsing()
- {
- // Hide constructor
- }
-
- public static long decodeLongFromHex(String longAsString)
- {
- if ((longAsString.charAt(1) == 'x')
- || (longAsString.charAt(1) == 'X'))
- {
- return Long.parseLong(longAsString.substring(2), 16);
- }
-
- return Long.parseLong(longAsString, 16);
- }
-
- public static int decodeIntFromHex(String intAsString)
- {
- if ((intAsString.charAt(1) == 'x')
- || (intAsString.charAt(1) == 'X'))
- {
- return Integer.parseInt(intAsString.substring(2), 16);
- }
-
- return Integer.parseInt(intAsString, 16);
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/test/SimpleTest.java pdftk-2.01/java/org/bouncycastle/util/test/SimpleTest.java
--- pdftk-1.45/java/org/bouncycastle/util/test/SimpleTest.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/test/SimpleTest.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,84 +0,0 @@
-package org.bouncycastle.util.test;
-
-import java.io.PrintStream;
-
-import org.bouncycastle.util.Arrays;
-
-public abstract class SimpleTest
- implements Test
-{
- public abstract String getName();
-
- private TestResult success()
- {
- return SimpleTestResult.successful(this, "Okay");
- }
-
- protected void fail(
- String message)
- {
- throw new TestFailedException(SimpleTestResult.failed(this, message));
- }
-
- protected void fail(
- String message,
- Throwable throwable)
- {
- throw new TestFailedException(SimpleTestResult.failed(this, message, throwable));
- }
-
- protected void fail(
- String message,
- Object expected,
- Object found)
- {
- throw new TestFailedException(SimpleTestResult.failed(this, message, expected, found));
- }
-
- protected boolean areEqual(
- byte[] a,
- byte[] b)
- {
- return Arrays.areEqual(a, b);
- }
-
- public TestResult perform()
- {
- try
- {
- performTest();
-
- return success();
- }
- catch (TestFailedException e)
- {
- return e.getResult();
- }
- catch (Exception e)
- {
- return SimpleTestResult.failed(this, "Exception: " + e, e);
- }
- }
-
- protected static void runTest(
- Test test)
- {
- runTest(test, System.out);
- }
-
- protected static void runTest(
- Test test,
- PrintStream out)
- {
- TestResult result = test.perform();
-
- out.println(result.toString());
- if (result.getException() != null)
- {
- result.getException().printStackTrace(out);
- }
- }
-
- public abstract void performTest()
- throws Exception;
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/test/SimpleTestResult.java pdftk-2.01/java/org/bouncycastle/util/test/SimpleTestResult.java
--- pdftk-1.45/java/org/bouncycastle/util/test/SimpleTestResult.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/test/SimpleTestResult.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,80 +0,0 @@
-package org.bouncycastle.util.test;
-
-public class SimpleTestResult implements TestResult
-{
- private static final String SEPARATOR = System.getProperty("line.separator");
-
- private boolean success;
- private String message;
- private Throwable exception;
-
- public SimpleTestResult(boolean success, String message)
- {
- this.success = success;
- this.message = message;
- }
-
- public SimpleTestResult(boolean success, String message, Throwable exception)
- {
- this.success = success;
- this.message = message;
- this.exception = exception;
- }
-
- public static TestResult successful(
- Test test,
- String message)
- {
- return new SimpleTestResult(true, test.getName() + ": " + message);
- }
-
- public static TestResult failed(
- Test test,
- String message)
- {
- return new SimpleTestResult(false, test.getName() + ": " + message);
- }
-
- public static TestResult failed(
- Test test,
- String message,
- Throwable t)
- {
- return new SimpleTestResult(false, test.getName() + ": " + message, t);
- }
-
- public static TestResult failed(
- Test test,
- String message,
- Object expected,
- Object found)
- {
- return failed(test, message + SEPARATOR + "Expected: " + expected + SEPARATOR + "Found : " + found);
- }
-
- public static String failedMessage(String algorithm, String testName, String expected,
- String actual)
- {
- StringBuffer sb = new StringBuffer(algorithm);
- sb.append(" failing ").append(testName);
- sb.append(SEPARATOR).append(" expected: ").append(expected);
- sb.append(SEPARATOR).append(" got : ").append(actual);
-
- return sb.toString();
- }
-
- public boolean isSuccessful()
- {
- return success;
- }
-
- public String toString()
- {
- return message;
- }
-
- public Throwable getException()
- {
- return exception;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/test/Test.java pdftk-2.01/java/org/bouncycastle/util/test/Test.java
--- pdftk-1.45/java/org/bouncycastle/util/test/Test.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/test/Test.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,8 +0,0 @@
-package org.bouncycastle.util.test;
-
-public interface Test
-{
- String getName();
-
- TestResult perform();
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/test/TestFailedException.java pdftk-2.01/java/org/bouncycastle/util/test/TestFailedException.java
--- pdftk-1.45/java/org/bouncycastle/util/test/TestFailedException.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/test/TestFailedException.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,18 +0,0 @@
-package org.bouncycastle.util.test;
-
-public class TestFailedException
- extends RuntimeException
-{
- private TestResult _result;
-
- public TestFailedException(
- TestResult result)
- {
- _result = result;
- }
-
- public TestResult getResult()
- {
- return _result;
- }
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/test/TestResult.java pdftk-2.01/java/org/bouncycastle/util/test/TestResult.java
--- pdftk-1.45/java/org/bouncycastle/util/test/TestResult.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/test/TestResult.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,10 +0,0 @@
-package org.bouncycastle.util.test;
-
-public interface TestResult
-{
- public boolean isSuccessful();
-
- public Throwable getException();
-
- public String toString();
-}
diff -Nru pdftk-1.45/java/org/bouncycastle/util/test/UncloseableOutputStream.java pdftk-2.01/java/org/bouncycastle/util/test/UncloseableOutputStream.java
--- pdftk-1.45/java/org/bouncycastle/util/test/UncloseableOutputStream.java 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/test/UncloseableOutputStream.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,23 +0,0 @@
-package org.bouncycastle.util.test;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-public class UncloseableOutputStream extends FilterOutputStream
-{
- public UncloseableOutputStream(OutputStream s)
- {
- super(s);
- }
-
- public void close()
- {
- throw new RuntimeException("close() called on UncloseableOutputStream");
- }
-
- public void write(byte[] b, int off, int len) throws IOException
- {
- out.write(b, off, len);
- }
- }
diff -Nru pdftk-1.45/java/org/bouncycastle/util/test/package.html pdftk-2.01/java/org/bouncycastle/util/test/package.html
--- pdftk-1.45/java/org/bouncycastle/util/test/package.html 2010-01-11 14:16:44.000000000 +0000
+++ pdftk-2.01/java/org/bouncycastle/util/test/package.html 1970-01-01 00:00:00.000000000 +0000
@@ -1,5 +0,0 @@
-
-
-Light weight test API. If you can use Junit!
-
-
diff -Nru pdftk-1.45/java/pdftk/com/itext_lgpl_header.txt pdftk-2.01/java/pdftk/com/itext_lgpl_header.txt
--- pdftk-1.45/java/pdftk/com/itext_lgpl_header.txt 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/itext_lgpl_header.txt 2010-09-22 15:06:26.000000000 +0000
@@ -0,0 +1,16 @@
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
diff -Nru pdftk-1.45/java/pdftk/com/itext_replace_mpl_text_with_lgpl.sh pdftk-2.01/java/pdftk/com/itext_replace_mpl_text_with_lgpl.sh
--- pdftk-1.45/java/pdftk/com/itext_replace_mpl_text_with_lgpl.sh 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/itext_replace_mpl_text_with_lgpl.sh 2013-05-22 08:30:20.000000000 +0000
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# The original iText (itext-paulo-155) library files included these sections:
+
+#* The contents of this file are subject to the Mozilla Public License Version 1.1
+#* (the "License"); you may not use this file except in compliance with the License.
+#* You may obtain a copy of the License at http://www.mozilla.org/MPL/
+#*
+#* Software distributed under the License is distributed on an "AS IS" basis,
+#* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+#* for the specific language governing rights and limitations under the License.
+
+#* Alternatively, the contents of this file may be used under the terms of the
+#* LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
+#* provisions of LGPL are applicable instead of those above. If you wish to
+#* allow use of your version of this file only under the terms of the LGPL
+#* License and not to allow others to use your version of this file under
+#* the MPL, indicate your decision by deleting the provisions above and
+#* replace them with the notice and other provisions required by the LGPL.
+#* If you do not delete the provisions above, a recipient may use your version
+#* of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
+#*
+#* This library is free software; you can redistribute it and/or modify it
+#* under the terms of the MPL as stated above or under the terms of the GNU
+#* Library General Public License as published by the Free Software Foundation;
+#* either version 2 of the License, or any later version.
+#*
+#* This library is distributed in the hope that it will be useful, but WITHOUT
+#* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+#* FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
+#* details.
+
+# The pdftk code is distributed with a GPL, and it links with the iText library.
+# What is more, I have read many places that the GPL is incompatible with the
+# MPL. So I have replaced the above MPL/LGPL boilerplate with LGPL boilerplate
+# in all iText java files as described in this original MPL/LGPL boilerplate.
+#
+# This is the script I used for that purpose. You can find the LGPL boilerplate
+# I used in itext_lgpl_header.txt. This was copied from:
+# http://www.gnu.org/licenses/lgpl-2.0.html#SEC4
+#
+# If you have any questions, please contact me, Sid Steward, at:
+# sid.steward (at) pdflabs (dot) com
+#
+
+for file in `find . -name "*.java"`
+do
+echo $file
+sed -n -e '/ * The contents of this file are subject to the Mozilla Public License Version 1.1/,/limitations under the License.$/!p' $file | \
+sed -n -e '/ * Alternatively, the contents of this file may be used under the terms of the/,/ * details.$/!p' | \
+sed '/ * where applicable./r itext_lgpl_header.txt' > $file.foo
+mv $file.foo $file
+done
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Anchor.java pdftk-2.01/java/pdftk/com/lowagie/text/Anchor.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Anchor.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Anchor.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,355 @@
+/*
+ * $Id: Anchor.java,v 1.84 2005/05/03 13:03:49 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Properties;
+
+import pdftk.com.lowagie.text.markup.MarkupTags;
+import pdftk.com.lowagie.text.markup.MarkupParser;
+
+/**
+ * An Anchor
can be a reference or a destination of a reference.
+ *
+ * An Anchor
is a special kind of Phrase
.
+ * It is constructed in the same way.
+ *
+ * Example:
+ *
+ * Anchor anchor = new Anchor("this is a link");
+ * anchor.setName("LINK");
+ * anchor.setReference("http://www.lowagie.com");
+ *
+ *
+ * @see Element
+ * @see Phrase
+ */
+
+public class Anchor extends Phrase implements TextElementArray, MarkupAttributes {
+
+ // membervariables
+
+/** This is the anchor tag. */
+ public static final String ANCHOR = "anchor";
+
+/** This is the name of the Anchor
. */
+ protected String name = null;
+
+/** This is the reference of the Anchor
. */
+ protected String reference = null;
+
+ // constructors
+
+/**
+ * Constructs an Anchor
without specifying a leading.
+ */
+
+ public Anchor() {
+ super(16);
+ }
+
+/**
+ * Constructs an Anchor
with a certain leading.
+ *
+ * @param leading the leading
+ */
+
+ public Anchor(float leading) {
+ super(leading);
+ }
+
+/**
+ * Constructs an Anchor
with a certain Chunk
.
+ *
+ * @param chunk a Chunk
+ */
+
+ public Anchor(Chunk chunk) {
+ super(chunk);
+ }
+
+/**
+ * Constructs an Anchor
with a certain String
.
+ *
+ * @param string a String
+ */
+
+ public Anchor(String string) {
+ super(string);
+ }
+
+/**
+ * Constructs an Anchor
with a certain String
+ * and a certain Font
.
+ *
+ * @param string a String
+ * @param font a Font
+ */
+
+ public Anchor(String string, Font font) {
+ super(string, font);
+ }
+
+/**
+ * Constructs an Anchor
with a certain Chunk
+ * and a certain leading.
+ *
+ * @param leading the leading
+ * @param chunk a Chunk
+ */
+
+ public Anchor(float leading, Chunk chunk) {
+ super(leading, chunk);
+ }
+
+/**
+ * Constructs an Anchor
with a certain leading
+ * and a certain String
.
+ *
+ * @param leading the leading
+ * @param string a String
+ */
+
+ public Anchor(float leading, String string) {
+ super(leading, string);
+ }
+
+/**
+ * Constructs an Anchor
with a certain leading,
+ * a certain String
and a certain Font
.
+ *
+ * @param leading the leading
+ * @param string a String
+ * @param font a Font
+ */
+
+ public Anchor(float leading, String string, Font font) {
+ super(leading, string, font);
+ }
+
+/**
+ * Returns an Anchor
that has been constructed taking in account
+ * the value of some attributes .
+ *
+ * @param attributes Some attributes
+ */
+
+ public Anchor(Properties attributes) {
+ this("", FontFactory.getFont(attributes));
+ String value;
+ if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
+ Chunk chunk = new Chunk(value);
+ if ((value = (String)attributes.remove(ElementTags.GENERICTAG)) != null) {
+ chunk.setGenericTag(value);
+ }
+ add(chunk);
+ }
+ if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
+ setLeading(Float.valueOf(value + "f").floatValue());
+ }
+ else if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_LINEHEIGHT)) != null) {
+ setLeading(MarkupParser.parseLength(value));
+ }
+ if ((value = (String)attributes.remove(ElementTags.NAME)) != null) {
+ setName(value);
+ }
+ if ((value = (String)attributes.remove(ElementTags.REFERENCE)) != null) {
+ setReference(value);
+ }
+ if (attributes.size() > 0) setMarkupAttributes(attributes);
+ }
+
+ // implementation of the Element-methods
+
+/**
+ * Processes the element by adding it (or the different parts) to an
+ * ElementListener
.
+ *
+ * @param listener an ElementListener
+ * @return true
if the element was processed successfully
+ */
+
+ public boolean process(ElementListener listener) {
+ try {
+ Chunk chunk;
+ Iterator i = getChunks().iterator();
+ boolean localDestination = (reference != null && reference.startsWith("#"));
+ boolean notGotoOK = true;
+ while (i.hasNext()) {
+ chunk = (Chunk) i.next();
+ if (name != null && notGotoOK && !chunk.isEmpty()) {
+ chunk.setLocalDestination(name);
+ notGotoOK = false;
+ }
+ if (localDestination) {
+ chunk.setLocalGoto(reference.substring(1));
+ }
+ listener.add(chunk);
+ }
+ return true;
+ }
+ catch(DocumentException de) {
+ return false;
+ }
+ }
+
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return an ArrayList
+ */
+
+ public ArrayList getChunks() {
+ ArrayList tmp = new ArrayList();
+ Chunk chunk;
+ Iterator i = iterator();
+ boolean localDestination = (reference != null && reference.startsWith("#"));
+ boolean notGotoOK = true;
+ while (i.hasNext()) {
+ chunk = (Chunk) i.next();
+ if (name != null && notGotoOK && !chunk.isEmpty()) {
+ chunk.setLocalDestination(name);
+ notGotoOK = false;
+ }
+ if (localDestination) {
+ chunk.setLocalGoto(reference.substring(1));
+ }
+ else if (reference != null)
+ chunk.setAnchor(reference);
+ tmp.add(chunk);
+ }
+ return tmp;
+ }
+
+/**
+ * Gets the type of the text element.
+ *
+ * @return a type
+ */
+
+ public int type() {
+ return Element.ANCHOR;
+ }
+
+ // methods
+
+/**
+ * Gets an iterator of Element
s.
+ *
+ * @return an Iterator
+ */
+
+ // suggestion by by Curt Thompson
+ public Iterator getElements() {
+ return this.iterator();
+ }
+
+/**
+ * Sets the name of this Anchor
.
+ *
+ * @param name a new name
+ */
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+/**
+ * Sets the reference of this Anchor
.
+ *
+ * @param reference a new reference
+ */
+
+ public void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ // methods to retrieve information
+
+/**
+ * Returns the name of this Anchor
.
+ *
+ * @return a name
+ */
+
+ public String name() {
+ return name;
+ }
+
+/**
+ * Gets the reference of this Anchor
.
+ *
+ * @return a reference
+ */
+
+ public String reference() {
+ return reference;
+ }
+
+/**
+ * Gets the reference of this Anchor
.
+ *
+ * @return an URL
+ */
+
+ public URL url() {
+ try {
+ return new URL(reference);
+ }
+ catch(MalformedURLException mue) {
+ return null;
+ }
+ }
+
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param tag the given tag
+ * @return true if the tag corresponds
+ */
+
+ public static boolean isTag(String tag) {
+ return ElementTags.ANCHOR.equals(tag);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Annotation.java pdftk-2.01/java/pdftk/com/lowagie/text/Annotation.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Annotation.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Annotation.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,727 @@
+/*
+ * $Id: Annotation.java,v 1.70 2005/04/13 09:17:09 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * An Annotation
is a little note that can be added to a page on
+ * a document.
+ *
+ * @see Element
+ * @see Anchor
+ */
+
+public class Annotation implements Element, MarkupAttributes {
+
+ // membervariables
+
+ /** This is a possible annotation type. */
+ public static final int TEXT = 0;
+
+ /** This is a possible annotation type. */
+ public static final int URL_NET = 1;
+
+ /** This is a possible annotation type. */
+ public static final int URL_AS_STRING = 2;
+
+ /** This is a possible annotation type. */
+ public static final int FILE_DEST = 3;
+
+ /** This is a possible annotation type. */
+ public static final int FILE_PAGE = 4;
+
+ /** This is a possible annotation type. */
+ public static final int NAMED_DEST = 5;
+
+ /** This is a possible annotation type. */
+ public static final int LAUNCH = 6;
+
+ /** This is a possible annotation type. */
+ public static final int SCREEN = 7;
+
+ /** This is a possible attribute. */
+ public static String TITLE = "title";
+
+ /** This is a possible attribute. */
+ public static String CONTENT = "content";
+
+ /** This is a possible attribute. */
+ public static String URL = "url";
+
+ /** This is a possible attribute. */
+ public static String FILE = "file";
+
+ /** This is a possible attribute. */
+ public static String DESTINATION = "destination";
+
+ /** This is a possible attribute. */
+ public static String PAGE = "page";
+
+ /** This is a possible attribute. */
+ public static String NAMED = "named";
+
+ /** This is a possible attribute. */
+ public static String APPLICATION = "application";
+
+ /** This is a possible attribute. */
+ public static String PARAMETERS = "parameters";
+
+ /** This is a possible attribute. */
+ public static String OPERATION = "operation";
+
+ /** This is a possible attribute. */
+ public static String DEFAULTDIR = "defaultdir";
+
+ /** This is a possible attribute. */
+ public static String LLX = "llx";
+
+ /** This is a possible attribute. */
+ public static String LLY = "lly";
+
+ /** This is a possible attribute. */
+ public static String URX = "urx";
+
+ /** This is a possible attribute. */
+ public static String URY = "ury";
+
+ /** This is a possible attribute. */
+ public static String MIMETYPE = "mime";
+
+ /** This is the type of annotation. */
+ protected int annotationtype;
+
+ /** This is the title of the Annotation
. */
+ protected HashMap annotationAttributes = new HashMap();
+
+ /** Contains extra markupAttributes */
+ protected Properties markupAttributes = null;
+
+ /** This is the lower left x-value */
+ protected float llx = Float.NaN;
+
+ /** This is the lower left y-value */
+ protected float lly = Float.NaN;
+
+ /** This is the upper right x-value */
+ protected float urx = Float.NaN;
+
+ /** This is the upper right y-value */
+ protected float ury = Float.NaN;
+
+ // constructors
+
+ /**
+ * Constructs an Annotation
with a certain title and some
+ * text.
+ *
+ * @param llx
+ * lower left x coordinate
+ * @param lly
+ * lower left y coordinate
+ * @param urx
+ * upper right x coordinate
+ * @param ury
+ * upper right y coordinate
+ */
+
+ private Annotation(float llx, float lly, float urx, float ury) {
+ this.llx = llx;
+ this.lly = lly;
+ this.urx = urx;
+ this.ury = ury;
+ }
+
+ public Annotation(Annotation an) {
+ annotationtype = an.annotationtype;
+ annotationAttributes = an.annotationAttributes;
+ markupAttributes = an.markupAttributes;
+ llx = an.llx;
+ lly = an.lly;
+ urx = an.urx;
+ ury = an.ury;
+ }
+
+ /**
+ * Constructs an Annotation
with a certain title and some
+ * text.
+ *
+ * @param title
+ * the title of the annotation
+ * @param text
+ * the content of the annotation
+ */
+
+ public Annotation(String title, String text) {
+ annotationtype = TEXT;
+ annotationAttributes.put(TITLE, title);
+ annotationAttributes.put(CONTENT, text);
+ }
+
+ /**
+ * Constructs an Annotation
with a certain title and some
+ * text.
+ *
+ * @param title
+ * the title of the annotation
+ * @param text
+ * the content of the annotation
+ * @param llx
+ * the lower left x-value
+ * @param lly
+ * the lower left y-value
+ * @param urx
+ * the upper right x-value
+ * @param ury
+ * the upper right y-value
+ */
+
+ public Annotation(String title, String text, float llx, float lly,
+ float urx, float ury) {
+ this(llx, lly, urx, ury);
+ annotationtype = TEXT;
+ annotationAttributes.put(TITLE, title);
+ annotationAttributes.put(CONTENT, text);
+ }
+
+ /**
+ * Constructs an Annotation
.
+ *
+ * @param llx
+ * the lower left x-value
+ * @param lly
+ * the lower left y-value
+ * @param urx
+ * the upper right x-value
+ * @param ury
+ * the upper right y-value
+ * @param url
+ * the external reference
+ */
+
+ public Annotation(float llx, float lly, float urx, float ury, URL url) {
+ this(llx, lly, urx, ury);
+ annotationtype = URL_NET;
+ annotationAttributes.put(URL, url);
+ }
+
+ /**
+ * Constructs an Annotation
.
+ *
+ * @param llx
+ * the lower left x-value
+ * @param lly
+ * the lower left y-value
+ * @param urx
+ * the upper right x-value
+ * @param ury
+ * the upper right y-value
+ * @param url
+ * the external reference
+ */
+
+ public Annotation(float llx, float lly, float urx, float ury, String url) {
+ this(llx, lly, urx, ury);
+ annotationtype = URL_AS_STRING;
+ annotationAttributes.put(FILE, url);
+ }
+
+ /**
+ * Constructs an Annotation
.
+ *
+ * @param llx
+ * the lower left x-value
+ * @param lly
+ * the lower left y-value
+ * @param urx
+ * the upper right x-value
+ * @param ury
+ * the upper right y-value
+ * @param file
+ * an external PDF file
+ * @param dest
+ * the destination in this file
+ */
+
+ public Annotation(float llx, float lly, float urx, float ury, String file,
+ String dest) {
+ this(llx, lly, urx, ury);
+ annotationtype = FILE_DEST;
+ annotationAttributes.put(FILE, file);
+ annotationAttributes.put(DESTINATION, dest);
+ }
+
+ /**
+ * Creates a Screen anotation to embed media clips
+ *
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @param moviePath
+ * path to the media clip file
+ * @param mimeType
+ * mime type of the media
+ * @param showOnDisplay
+ * if true play on display of the page
+ */
+ public Annotation(float llx, float lly, float urx, float ury,
+ String moviePath, String mimeType, boolean showOnDisplay) {
+ this(llx, lly, urx, ury);
+ annotationtype = SCREEN;
+ annotationAttributes.put(FILE, moviePath);
+ annotationAttributes.put(MIMETYPE, mimeType);
+ annotationAttributes.put(PARAMETERS, new boolean[] {
+ false /* embedded */, showOnDisplay });
+ }
+
+ /**
+ * Constructs an Annotation
.
+ *
+ * @param llx
+ * the lower left x-value
+ * @param lly
+ * the lower left y-value
+ * @param urx
+ * the upper right x-value
+ * @param ury
+ * the upper right y-value
+ * @param file
+ * an external PDF file
+ * @param page
+ * a page number in this file
+ */
+
+ public Annotation(float llx, float lly, float urx, float ury, String file,
+ int page) {
+ this(llx, lly, urx, ury);
+ annotationtype = FILE_PAGE;
+ annotationAttributes.put(FILE, file);
+ annotationAttributes.put(PAGE, new Integer(page));
+ }
+
+ /**
+ * Constructs an Annotation
.
+ *
+ * @param llx
+ * the lower left x-value
+ * @param lly
+ * the lower left y-value
+ * @param urx
+ * the upper right x-value
+ * @param ury
+ * the upper right y-value
+ * @param named
+ * a named destination in this file
+ */
+
+ public Annotation(float llx, float lly, float urx, float ury, int named) {
+ this(llx, lly, urx, ury);
+ annotationtype = NAMED_DEST;
+ annotationAttributes.put(NAMED, new Integer(named));
+ }
+
+ /**
+ * Constructs an Annotation
.
+ *
+ * @param llx
+ * the lower left x-value
+ * @param lly
+ * the lower left y-value
+ * @param urx
+ * the upper right x-value
+ * @param ury
+ * the upper right y-value
+ * @param application
+ * an external application
+ * @param parameters
+ * parameters to pass to this application
+ * @param operation
+ * the operation to pass to this application
+ * @param defaultdir
+ * the default directory to run this application in
+ */
+
+ public Annotation(float llx, float lly, float urx, float ury,
+ String application, String parameters, String operation,
+ String defaultdir) {
+ this(llx, lly, urx, ury);
+ annotationtype = LAUNCH;
+ annotationAttributes.put(APPLICATION, application);
+ annotationAttributes.put(PARAMETERS, parameters);
+ annotationAttributes.put(OPERATION, operation);
+ annotationAttributes.put(DEFAULTDIR, defaultdir);
+ }
+
+ /**
+ * Returns an Annotation
that has been constructed taking in
+ * account the value of some attributes .
+ *
+ * @param attributes
+ * Some attributes
+ */
+
+ public Annotation(Properties attributes) {
+ String value = (String) attributes.remove(ElementTags.LLX);
+ if (value != null) {
+ llx = Float.valueOf(value + "f").floatValue();
+ }
+ value = (String) attributes.remove(ElementTags.LLY);
+ if (value != null) {
+ lly = Float.valueOf(value + "f").floatValue();
+ }
+ value = (String) attributes.remove(ElementTags.URX);
+ if (value != null) {
+ urx = Float.valueOf(value + "f").floatValue();
+ }
+ value = (String) attributes.remove(ElementTags.URY);
+ if (value != null) {
+ ury = Float.valueOf(value + "f").floatValue();
+ }
+ String title = (String) attributes.remove(ElementTags.TITLE);
+ String text = (String) attributes.remove(ElementTags.CONTENT);
+ if (title != null || text != null) {
+ annotationtype = TEXT;
+ } else if ((value = (String) attributes.remove(ElementTags.URL)) != null) {
+ annotationtype = URL_AS_STRING;
+ annotationAttributes.put(FILE, value);
+ } else if ((value = (String) attributes.remove(ElementTags.NAMED)) != null) {
+ annotationtype = NAMED_DEST;
+ annotationAttributes.put(NAMED, Integer.valueOf(value));
+ } else {
+ String file = (String) attributes.remove(ElementTags.FILE);
+ String destination = (String) attributes
+ .remove(ElementTags.DESTINATION);
+ String page = (String) attributes.remove(ElementTags.PAGE);
+ if (file != null) {
+ annotationAttributes.put(FILE, file);
+ if (destination != null) {
+ annotationtype = FILE_DEST;
+ annotationAttributes.put(DESTINATION, destination);
+ } else if (page != null) {
+ annotationtype = FILE_PAGE;
+ annotationAttributes.put(FILE, file);
+ annotationAttributes.put(PAGE, Integer.valueOf(page));
+ }
+ } else if ((value = (String) attributes.remove(ElementTags.NAMED)) != null) {
+ annotationtype = LAUNCH;
+ annotationAttributes.put(APPLICATION, value);
+ annotationAttributes.put(PARAMETERS, attributes
+ .remove(ElementTags.PARAMETERS));
+ annotationAttributes.put(OPERATION, attributes
+ .remove(ElementTags.OPERATION));
+ annotationAttributes.put(DEFAULTDIR, attributes
+ .remove(ElementTags.DEFAULTDIR));
+ }
+ }
+ if (annotationtype == TEXT) {
+ if (title == null)
+ title = "";
+ if (text == null)
+ text = "";
+ annotationAttributes.put(TITLE, title);
+ annotationAttributes.put(CONTENT, text);
+ }
+ if (attributes.size() > 0)
+ setMarkupAttributes(attributes);
+ }
+
+ // implementation of the Element-methods
+
+ /**
+ * Gets the type of the text element.
+ *
+ * @return a type
+ */
+
+ public int type() {
+ return Element.ANNOTATION;
+ }
+
+ // methods
+
+ /**
+ * Processes the element by adding it (or the different parts) to an
+ * ElementListener
.
+ *
+ * @param listener
+ * an ElementListener
+ * @return true
if the element was processed successfully
+ */
+
+ public boolean process(ElementListener listener) {
+ try {
+ return listener.add(this);
+ } catch (DocumentException de) {
+ return false;
+ }
+ }
+
+ /**
+ * Gets all the chunks in this element.
+ *
+ * @return an ArrayList
+ */
+
+ public ArrayList getChunks() {
+ return new ArrayList();
+ }
+
+ // methods
+
+ /**
+ * Sets the dimensions of this annotation.
+ *
+ * @param llx
+ * the lower left x-value
+ * @param lly
+ * the lower left y-value
+ * @param urx
+ * the upper right x-value
+ * @param ury
+ * the upper right y-value
+ */
+
+ public void setDimensions(float llx, float lly, float urx, float ury) {
+ this.llx = llx;
+ this.lly = lly;
+ this.urx = urx;
+ this.ury = ury;
+ }
+
+ // methods to retrieve information
+
+ /**
+ * Returns the lower left x-value.
+ *
+ * @return a value
+ */
+
+ public float llx() {
+ return llx;
+ }
+
+ /**
+ * Returns the lower left y-value.
+ *
+ * @return a value
+ */
+
+ public float lly() {
+ return lly;
+ }
+
+ /**
+ * Returns the uppper right x-value.
+ *
+ * @return a value
+ */
+
+ public float urx() {
+ return urx;
+ }
+
+ /**
+ * Returns the uppper right y-value.
+ *
+ * @return a value
+ */
+
+ public float ury() {
+ return ury;
+ }
+
+ /**
+ * Returns the lower left x-value.
+ *
+ * @param def
+ * the default value
+ * @return a value
+ */
+
+ public float llx(float def) {
+ if (Float.isNaN(llx))
+ return def;
+ return llx;
+ }
+
+ /**
+ * Returns the lower left y-value.
+ *
+ * @param def
+ * the default value
+ * @return a value
+ */
+
+ public float lly(float def) {
+ if (Float.isNaN(lly))
+ return def;
+ return lly;
+ }
+
+ /**
+ * Returns the upper right x-value.
+ *
+ * @param def
+ * the default value
+ * @return a value
+ */
+
+ public float urx(float def) {
+ if (Float.isNaN(urx))
+ return def;
+ return urx;
+ }
+
+ /**
+ * Returns the upper right y-value.
+ *
+ * @param def
+ * the default value
+ * @return a value
+ */
+
+ public float ury(float def) {
+ if (Float.isNaN(ury))
+ return def;
+ return ury;
+ }
+
+ /**
+ * Returns the type of this Annotation
.
+ *
+ * @return a type
+ */
+
+ public int annotationType() {
+ return annotationtype;
+ }
+
+ /**
+ * Returns the title of this Annotation
.
+ *
+ * @return a name
+ */
+
+ public String title() {
+ String s = (String) annotationAttributes.get(TITLE);
+ if (s == null)
+ s = "";
+ return s;
+ }
+
+ /**
+ * Gets the content of this Annotation
.
+ *
+ * @return a reference
+ */
+
+ public String content() {
+ String s = (String) annotationAttributes.get(CONTENT);
+ if (s == null)
+ s = "";
+ return s;
+ }
+
+ /**
+ * Gets the content of this Annotation
.
+ *
+ * @return a reference
+ */
+
+ public HashMap attributes() {
+ return annotationAttributes;
+ }
+
+ /**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param tag
+ * the given tag
+ * @return true if the tag corresponds
+ */
+
+ public static boolean isTag(String tag) {
+ return ElementTags.ANNOTATION.equals(tag);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String,
+ * java.lang.String)
+ */
+ public void setMarkupAttribute(String name, String value) {
+ if (markupAttributes == null) markupAttributes = new Properties();
+ markupAttributes.put(name, value);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+ */
+ public void setMarkupAttributes(Properties markupAttributes) {
+ this.markupAttributes = markupAttributes;
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+ */
+ public String getMarkupAttribute(String name) {
+ return (markupAttributes == null) ? null : String
+ .valueOf(markupAttributes.get(name));
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+ */
+ public Set getMarkupAttributeNames() {
+ return Chunk.getKeySet(markupAttributes);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+ */
+ public Properties getMarkupAttributes() {
+ return markupAttributes;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/BadElementException.java pdftk-2.01/java/pdftk/com/lowagie/text/BadElementException.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/BadElementException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/BadElementException.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,79 @@
+/*
+ * $Id: BadElementException.java,v 1.50 2004/12/14 11:33:49 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+/**
+ * Signals an attempt to create an Element
that hasn't got the right form.
+ *
+ * @see DocumentException
+ * @see Cell
+ * @see Table
+ */
+
+public class BadElementException extends DocumentException {
+
+ // constructors
+ /**
+ * Constructs a BadElementException
+ * @param ex an Exception object that has to be turned into a BadElementException
+ */
+ public BadElementException(Exception ex) {
+ super(ex);
+ }
+
+/**
+ * Constructs a BadElementException
whithout a message.
+ */
+
+ BadElementException() {
+ super();
+ }
+
+/**
+ * Constructs a BadElementException
with a message.
+ *
+ * @param message a message describing the exception
+ */
+
+ public BadElementException(String message) {
+ super(message);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Chunk.java pdftk-2.01/java/pdftk/com/lowagie/text/Chunk.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Chunk.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Chunk.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,908 @@
+/*
+ * $Id: Chunk.java,v 1.112 2005/10/05 07:23:47 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Set;
+import java.net.URL;
+
+import pdftk.com.lowagie.text.pdf.PdfAction;
+import pdftk.com.lowagie.text.pdf.PdfAnnotation;
+import pdftk.com.lowagie.text.pdf.HyphenationEvent;
+import pdftk.com.lowagie.text.pdf.PdfContentByte;
+import pdftk.com.lowagie.text.markup.MarkupTags;
+import pdftk.com.lowagie.text.markup.MarkupParser;
+
+/**
+ * This is the smallest significant part of text that can be added to a
+ * document.
+ *
+ * Most elements can be divided in one or more Chunk
s. A chunk
+ * is a String
with a certain Font
. all other
+ * layoutparameters should be defined in the object to which this chunk of text
+ * is added.
+ *
+ * Example:
+ *
+ *
+ *
+ * Chunk chunk = new Chunk("Hello world",
+ * FontFactory.getFont(FontFactory.COURIER, 20, Font.ITALIC, new Color(255, 0,
+ * 0))); document.add(chunk);
+ *
+ *
+ *
+ *
+ */
+
+public class Chunk implements Element, MarkupAttributes {
+
+ // public static membervariables
+
+ /**
+ * The character stand in for an image.
+ */
+ public static final String OBJECT_REPLACEMENT_CHARACTER = "\ufffc";
+
+ /** This is a Chunk containing a newline. */
+ public static final Chunk NEWLINE = new Chunk("\n");
+
+ /** This is a Chunk containing a newpage. */
+ public static final Chunk NEXTPAGE = new Chunk("");
+ static {
+ NEXTPAGE.setNewPage();
+ }
+
+ /** Key for sub/superscript. */
+ public static final String SUBSUPSCRIPT = "SUBSUPSCRIPT";
+
+ /** Key for underline. */
+ public static final String UNDERLINE = "UNDERLINE";
+
+ /** Key for color. */
+ public static final String COLOR = "COLOR";
+
+ /** Key for encoding. */
+ public static final String ENCODING = "ENCODING";
+
+ /** Key for remote goto. */
+ public static final String REMOTEGOTO = "REMOTEGOTO";
+
+ /** Key for local goto. */
+ public static final String LOCALGOTO = "LOCALGOTO";
+
+ /** Key for local destination. */
+ public static final String LOCALDESTINATION = "LOCALDESTINATION";
+
+ /** Key for image. */
+ public static final String IMAGE = "IMAGE";
+
+ /** Key for generic tag. */
+ public static final String GENERICTAG = "GENERICTAG";
+
+ /** Key for newpage. */
+ public static final String NEWPAGE = "NEWPAGE";
+
+ /** Key for split character. */
+ public static final String SPLITCHARACTER = "SPLITCHARACTER";
+
+ /** Key for Action. */
+ public static final String ACTION = "ACTION";
+
+ /** Key for background. */
+ public static final String BACKGROUND = "BACKGROUND";
+
+ /** Key for annotation. */
+ public static final String PDFANNOTATION = "PDFANNOTATION";
+
+ /** Key for hyphenation. */
+ public static final String HYPHENATION = "HYPHENATION";
+
+ /** Key for text rendering mode. */
+ public static final String TEXTRENDERMODE = "TEXTRENDERMODE";
+
+ /** Key for text skewing. */
+ public static final String SKEW = "SKEW";
+
+ /** Key for text horizontal scaling. */
+ public static final String HSCALE = "HSCALE";
+
+ // member variables
+
+ /** This is the content of this chunk of text. */
+ protected StringBuffer content = null;
+
+ /** This is the Font
of this chunk of text. */
+ protected Font font = null;
+
+ /** Contains some of the attributes for this Chunk. */
+ protected HashMap attributes = null;
+
+ /** Contains extra markupAttributes */
+ protected Properties markupAttributes = null;
+
+ // constructors
+
+ /**
+ * Empty constructor.
+ */
+ protected Chunk() {
+ }
+
+ /**
+ * Constructs a chunk of text with a certain content and a certain
+ * Font
.
+ *
+ * @param content
+ * the content
+ * @param font
+ * the font
+ */
+
+ public Chunk(String content, Font font) {
+ this.content = new StringBuffer(content);
+ this.font = font;
+ }
+
+ /**
+ * Constructs a chunk of text with a certain content, without specifying a
+ * Font
.
+ *
+ * @param content
+ * the content
+ */
+ public Chunk(String content) {
+ this(content, new Font());
+ }
+
+ /**
+ * Constructs a chunk of text with a char and a certain Font
.
+ *
+ * @param c
+ * the content
+ * @param font
+ * the font
+ */
+ public Chunk(char c, Font font) {
+ this.content = new StringBuffer();
+ this.content.append(c);
+ this.font = font;
+ }
+
+ /**
+ * Constructs a chunk of text with a char, without specifying a Font
+ *
.
+ *
+ * @param c
+ * the content
+ */
+ public Chunk(char c) {
+ this(c, new Font());
+ }
+
+ /**
+ * Constructs a chunk containing an Image
.
+ *
+ * @param image
+ * the image
+ * @param offsetX
+ * the image offset in the x direction
+ * @param offsetY
+ * the image offset in the y direction
+ */
+ /* ssteward: dropped in 1.44
+ public Chunk(Image image, float offsetX, float offsetY) {
+ this(OBJECT_REPLACEMENT_CHARACTER, new Font());
+ Image copyImage = Image.getInstance(image);
+ copyImage.setAbsolutePosition(Float.NaN, Float.NaN);
+ setAttribute(IMAGE, new Object[] { copyImage, new Float(offsetX),
+ new Float(offsetY), new Boolean(false) });
+ }
+ */
+
+ /**
+ * Constructs a chunk containing an Image
.
+ *
+ * @param image
+ * the image
+ * @param offsetX
+ * the image offset in the x direction
+ * @param offsetY
+ * the image offset in the y direction
+ * @param changeLeading
+ * true if the leading has to be adapted to the image
+ */
+ /* ssteward: dropped in 1.44
+ public Chunk(Image image, float offsetX, float offsetY,
+ boolean changeLeading) {
+ this(OBJECT_REPLACEMENT_CHARACTER, new Font());
+ setAttribute(IMAGE, new Object[] { image, new Float(offsetX),
+ new Float(offsetY), new Boolean(changeLeading) });
+ }
+ */
+ /**
+ * Returns a Chunk
that has been constructed taking in
+ * account the value of some attributes .
+ *
+ * @param attributes
+ * Some attributes
+ */
+
+ public Chunk(Properties attributes) {
+ this("", FontFactory.getFont(attributes));
+ String value;
+ if ((value = (String) attributes.remove(ElementTags.ITEXT)) != null) {
+ append(value);
+ }
+ if ((value = (String) attributes.remove(ElementTags.LOCALGOTO)) != null) {
+ setLocalGoto(value);
+ }
+ if ((value = (String) attributes.remove(ElementTags.REMOTEGOTO)) != null) {
+ String destination = (String) attributes
+ .remove(ElementTags.DESTINATION);
+ String page = (String) attributes.remove(ElementTags.PAGE);
+ if (page != null) {
+ setRemoteGoto(value, Integer.valueOf(page).intValue());
+ } else if (destination != null) {
+ setRemoteGoto(value, destination);
+ }
+ }
+ if ((value = (String) attributes.remove(ElementTags.LOCALDESTINATION)) != null) {
+ setLocalDestination(value);
+ }
+ if ((value = (String) attributes.remove(ElementTags.SUBSUPSCRIPT)) != null) {
+ setTextRise(Float.valueOf(value + "f").floatValue());
+ }
+ if ((value = (String) attributes
+ .remove(MarkupTags.CSS_KEY_VERTICALALIGN)) != null
+ && value.endsWith("%")) {
+ float p = Float.valueOf(
+ value.substring(0, value.length() - 1) + "f").floatValue() / 100f;
+ setTextRise(p * font.size());
+ }
+ if ((value = (String) attributes.remove(ElementTags.GENERICTAG)) != null) {
+ setGenericTag(value);
+ }
+ if ((value = (String) attributes.remove(ElementTags.BACKGROUNDCOLOR)) != null) {
+ setBackground(MarkupParser.decodeColor(value));
+ }
+ if (attributes.size() > 0)
+ setMarkupAttributes(attributes);
+ }
+
+ // implementation of the Element-methods
+
+ /**
+ * Processes the element by adding it (or the different parts) to an
+ * ElementListener
.
+ *
+ * @param listener
+ * an ElementListener
+ * @return true
if the element was processed successfully
+ */
+
+ public boolean process(ElementListener listener) {
+ try {
+ return listener.add(this);
+ } catch (DocumentException de) {
+ return false;
+ }
+ }
+
+ /**
+ * Gets the type of the text element.
+ *
+ * @return a type
+ */
+
+ public int type() {
+ return Element.CHUNK;
+ }
+
+ /**
+ * Gets all the chunks in this element.
+ *
+ * @return an ArrayList
+ */
+
+ public ArrayList getChunks() {
+ ArrayList tmp = new ArrayList();
+ tmp.add(this);
+ return tmp;
+ }
+
+ // methods
+
+ /**
+ * appends some text to this Chunk
.
+ *
+ * @param string
+ * String
+ * @return a StringBuffer
+ */
+
+ public StringBuffer append(String string) {
+ return content.append(string);
+ }
+
+ // methods to retrieve information
+
+ /**
+ * Gets the font of this Chunk
.
+ *
+ * @return a Font
+ */
+
+ public Font font() {
+ return font;
+ }
+
+ /**
+ * Sets the font of this Chunk
.
+ *
+ * @param font
+ * a Font
+ */
+
+ public void setFont(Font font) {
+ this.font = font;
+ }
+
+ /**
+ * Returns the content of this Chunk
.
+ *
+ * @return a String
+ */
+
+ public String content() {
+ return content.toString();
+ }
+
+ /**
+ * Returns the content of this Chunk
.
+ *
+ * @return a String
+ */
+
+ public String toString() {
+ return content.toString();
+ }
+
+ /**
+ * Checks is this Chunk
is empty.
+ *
+ * @return false
if the Chunk contains other characters than
+ * space.
+ */
+
+ public boolean isEmpty() {
+ return (content.toString().trim().length() == 0)
+ && (content.toString().indexOf("\n") == -1)
+ && (attributes == null);
+ }
+
+ /**
+ * Gets the width of the Chunk in points.
+ *
+ * @return a width in points
+ */
+ public float getWidthPoint() {
+ /* ssteward: dropped in 1.44
+ if (getImage() != null) {
+ return getImage().scaledWidth();
+ }
+ */
+ return font.getCalculatedBaseFont(true).getWidthPoint(content(),
+ font.getCalculatedSize())
+ * getHorizontalScaling();
+ }
+
+ /**
+ * Sets the text displacement relative to the baseline. Positive values rise
+ * the text, negative values lower the text.
+ *
+ * It can be used to implement sub/superscript.
+ *
+ * @param rise
+ * the displacement in points
+ * @return this Chunk
+ */
+
+ public Chunk setTextRise(float rise) {
+ return setAttribute(SUBSUPSCRIPT, new Float(rise));
+ }
+
+ /**
+ * Gets the text displacement relatiev to the baseline.
+ *
+ * @return a displacement in points
+ */
+ public float getTextRise() {
+ if (attributes.containsKey(SUBSUPSCRIPT)) {
+ Float f = (Float) attributes.get(SUBSUPSCRIPT);
+ return f.floatValue();
+ }
+ return 0.0f;
+ }
+
+ /**
+ * Sets the text rendering mode. It can outline text, simulate bold and make
+ * text invisible.
+ *
+ * @param mode
+ * the text rendering mode. It can be
+ * PdfContentByte.TEXT_RENDER_MODE_FILL
,
+ * PdfContentByte.TEXT_RENDER_MODE_STROKE
,
+ * PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE
and
+ * PdfContentByte.TEXT_RENDER_MODE_INVISIBLE
.
+ * @param strokeWidth
+ * the stroke line width for the modes
+ * PdfContentByte.TEXT_RENDER_MODE_STROKE
and
+ * PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE
.
+ * @param strokeColor
+ * the stroke color or null
to follow the text
+ * color
+ * @return this Chunk
+ */
+ public Chunk setTextRenderMode(int mode, float strokeWidth,
+ Color strokeColor) {
+ return setAttribute(TEXTRENDERMODE, new Object[] { new Integer(mode),
+ new Float(strokeWidth), strokeColor });
+ }
+
+ /**
+ * Skews the text to simulate italic and other effects. Try alpha=0
+ *
and beta=12
.
+ *
+ * @param alpha
+ * the first angle in degrees
+ * @param beta
+ * the second angle in degrees
+ * @return this Chunk
+ */
+ public Chunk setSkew(float alpha, float beta) {
+ alpha = (float) Math.tan(alpha * Math.PI / 180);
+ beta = (float) Math.tan(beta * Math.PI / 180);
+ return setAttribute(SKEW, new float[] { alpha, beta });
+ }
+
+ /**
+ * Sets the text horizontal scaling. A value of 1 is normal and a value of
+ * 0.5f shrinks the text to half it's width.
+ *
+ * @param scale
+ * the horizontal scaling factor
+ * @return this Chunk
+ */
+ public Chunk setHorizontalScaling(float scale) {
+ return setAttribute(HSCALE, new Float(scale));
+ }
+
+ /**
+ * Gets the horizontal scaling.
+ *
+ * @return a percentage in float
+ */
+ public float getHorizontalScaling() {
+ if (attributes == null)
+ return 1f;
+ Float f = (Float) attributes.get(HSCALE);
+ if (f == null)
+ return 1f;
+ return f.floatValue();
+ }
+
+ /**
+ * Sets an action for this Chunk
.
+ *
+ * @param action
+ * the action
+ * @return this Chunk
+ */
+
+ public Chunk setAction(PdfAction action) {
+ return setAttribute(ACTION, action);
+ }
+
+ /**
+ * Sets an anchor for this Chunk
.
+ *
+ * @param url
+ * the URL
to link to
+ * @return this Chunk
+ */
+
+ public Chunk setAnchor(URL url) {
+ return setAttribute(ACTION, new PdfAction(url.toExternalForm()));
+ }
+
+ /**
+ * Sets an anchor for this Chunk
.
+ *
+ * @param url
+ * the url to link to
+ * @return this Chunk
+ */
+
+ public Chunk setAnchor(String url) {
+ return setAttribute(ACTION, new PdfAction(url));
+ }
+
+ /**
+ * Sets a local goto for this Chunk
.
+ *
+ * There must be a local destination matching the name.
+ *
+ * @param name
+ * the name of the destination to go to
+ * @return this Chunk
+ */
+
+ public Chunk setLocalGoto(String name) {
+ return setAttribute(LOCALGOTO, name);
+ }
+
+ /**
+ * Sets the color of the background Chunk
.
+ *
+ * @param color
+ * the color of the background
+ * @return this Chunk
+ */
+ public Chunk setBackground(Color color) {
+ return setBackground(color, 0, 0, 0, 0);
+ }
+
+ /**
+ * Sets the color and the size of the background Chunk
.
+ *
+ * @param color
+ * the color of the background
+ * @param extraLeft
+ * increase the size of the rectangle in the left
+ * @param extraBottom
+ * increase the size of the rectangle in the bottom
+ * @param extraRight
+ * increase the size of the rectangle in the right
+ * @param extraTop
+ * increase the size of the rectangle in the top
+ * @return this Chunk
+ */
+ public Chunk setBackground(Color color, float extraLeft, float extraBottom,
+ float extraRight, float extraTop) {
+ return setAttribute(BACKGROUND, new Object[] { color,
+ new float[] { extraLeft, extraBottom, extraRight, extraTop } });
+ }
+
+ /**
+ * Sets an horizontal line that can be an underline or a strikethrough.
+ * Actually, the line can be anywhere vertically and has always the
+ * Chunk
width. Multiple call to this method will produce multiple
+ * lines.
+ *
+ * @param thickness
+ * the absolute thickness of the line
+ * @param yPosition
+ * the absolute y position relative to the baseline
+ * @return this Chunk
+ */
+ public Chunk setUnderline(float thickness, float yPosition) {
+ return setUnderline(null, thickness, 0f, yPosition, 0f,
+ PdfContentByte.LINE_CAP_BUTT);
+ }
+
+ /**
+ * Sets an horizontal line that can be an underline or a strikethrough.
+ * Actually, the line can be anywhere vertically and has always the
+ * Chunk
width. Multiple call to this method will produce multiple
+ * lines.
+ *
+ * @param color
+ * the color of the line or null
to follow the
+ * text color
+ * @param thickness
+ * the absolute thickness of the line
+ * @param thicknessMul
+ * the thickness multiplication factor with the font size
+ * @param yPosition
+ * the absolute y position relative to the baseline
+ * @param yPositionMul
+ * the position multiplication factor with the font size
+ * @param cap
+ * the end line cap. Allowed values are
+ * PdfContentByte.LINE_CAP_BUTT, PdfContentByte.LINE_CAP_ROUND
+ * and PdfContentByte.LINE_CAP_PROJECTING_SQUARE
+ * @return this Chunk
+ */
+ public Chunk setUnderline(Color color, float thickness, float thicknessMul,
+ float yPosition, float yPositionMul, int cap) {
+ if (attributes == null)
+ attributes = new HashMap();
+ Object obj[] = {
+ color,
+ new float[] { thickness, thicknessMul, yPosition, yPositionMul, cap } };
+ Object unders[][] = addToArray((Object[][]) attributes.get(UNDERLINE),
+ obj);
+ return setAttribute(UNDERLINE, unders);
+ }
+
+ /**
+ * Utility method to extend an array.
+ *
+ * @param original
+ * the original array or null
+ * @param item
+ * the item to be added to the array
+ * @return a new array with the item appended
+ */
+ public static Object[][] addToArray(Object original[][], Object item[]) {
+ if (original == null) {
+ original = new Object[1][];
+ original[0] = item;
+ return original;
+ } else {
+ Object original2[][] = new Object[original.length + 1][];
+ System.arraycopy(original, 0, original2, 0, original.length);
+ original2[original.length] = item;
+ return original2;
+ }
+ }
+
+ /**
+ * Sets a generic annotation to this Chunk
.
+ *
+ * @param annotation
+ * the annotation
+ * @return this Chunk
+ */
+ public Chunk setAnnotation(PdfAnnotation annotation) {
+ return setAttribute(PDFANNOTATION, annotation);
+ }
+
+ /**
+ * sets the hyphenation engine to this Chunk
.
+ *
+ * @param hyphenation
+ * the hyphenation engine
+ * @return this Chunk
+ */
+ public Chunk setHyphenation(HyphenationEvent hyphenation) {
+ return setAttribute(HYPHENATION, hyphenation);
+ }
+
+ /**
+ * Sets a goto for a remote destination for this Chunk
.
+ *
+ * @param filename
+ * the file name of the destination document
+ * @param name
+ * the name of the destination to go to
+ * @return this Chunk
+ */
+
+ public Chunk setRemoteGoto(String filename, String name) {
+ return setAttribute(REMOTEGOTO, new Object[] { filename, name });
+ }
+
+ /**
+ * Sets a goto for a remote destination for this Chunk
.
+ *
+ * @param filename
+ * the file name of the destination document
+ * @param page
+ * the page of the destination to go to. First page is 1
+ * @return this Chunk
+ */
+
+ public Chunk setRemoteGoto(String filename, int page) {
+ return setAttribute(REMOTEGOTO, new Object[] { filename,
+ new Integer(page) });
+ }
+
+ /**
+ * Sets a local destination for this Chunk
.
+ *
+ * @param name
+ * the name for this destination
+ * @return this Chunk
+ */
+ public Chunk setLocalDestination(String name) {
+ return setAttribute(LOCALDESTINATION, name);
+ }
+
+ /**
+ * Sets the generic tag Chunk
.
+ *
+ * The text for this tag can be retrieved with PdfPageEvent
.
+ *
+ * @param text
+ * the text for the tag
+ * @return this Chunk
+ */
+
+ public Chunk setGenericTag(String text) {
+ return setAttribute(GENERICTAG, text);
+ }
+
+ /**
+ * Sets the split characters.
+ *
+ * @param splitCharacter
+ * the SplitCharacter
interface
+ * @return this Chunk
+ */
+ public Chunk setSplitCharacter(SplitCharacter splitCharacter) {
+ return setAttribute(SPLITCHARACTER, splitCharacter);
+ }
+
+ /**
+ * Sets a new page tag..
+ *
+ * @return this Chunk
+ */
+
+ public Chunk setNewPage() {
+ return setAttribute(NEWPAGE, null);
+ }
+
+ /**
+ * Sets an arbitrary attribute.
+ *
+ * @param name
+ * the key for the attribute
+ * @param obj
+ * the value of the attribute
+ * @return this Chunk
+ */
+
+ private Chunk setAttribute(String name, Object obj) {
+ if (attributes == null)
+ attributes = new HashMap();
+ attributes.put(name, obj);
+ return this;
+ }
+
+ /**
+ * Gets the attributes for this Chunk
.
+ *
+ * It may be null.
+ *
+ * @return the attributes for this Chunk
+ */
+
+ public HashMap getAttributes() {
+ return attributes;
+ }
+
+ /**
+ * Checks the attributes of this Chunk
.
+ *
+ * @return false if there aren't any.
+ */
+
+ public boolean hasAttributes() {
+ return attributes != null;
+ }
+
+ /**
+ * Returns the image.
+ *
+ * @return the image
+ */
+ /* ssteward: dropped in 1.44
+ public Image getImage() {
+ if (attributes == null)
+ return null;
+ Object obj[] = (Object[]) attributes.get(Chunk.IMAGE);
+ if (obj == null)
+ return null;
+ else {
+ return (Image) obj[0];
+ }
+ }
+ */
+ /**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param tag
+ * the given tag
+ * @return true if the tag corresponds
+ */
+
+ public static boolean isTag(String tag) {
+ return ElementTags.CHUNK.equals(tag);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String,
+ * java.lang.String)
+ */
+ public void setMarkupAttribute(String name, String value) {
+ if (markupAttributes == null)
+ markupAttributes = new Properties();
+ markupAttributes.put(name, value);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+ */
+ public void setMarkupAttributes(Properties markupAttributes) {
+ this.markupAttributes = markupAttributes;
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+ */
+ public String getMarkupAttribute(String name) {
+ return (markupAttributes == null) ? null : String
+ .valueOf(markupAttributes.get(name));
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+ */
+ public Set getMarkupAttributeNames() {
+ return getKeySet(markupAttributes);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+ */
+ public Properties getMarkupAttributes() {
+ return markupAttributes;
+ }
+
+ /**
+ * Gets the keys of a Hashtable
+ *
+ * @param table
+ * a Hashtable
+ * @return the keyset of a Hashtable (or an empty set if table is null)
+ */
+ public static Set getKeySet(Hashtable table) {
+ return (table == null) ? Collections.EMPTY_SET : table.keySet();
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/DocListener.java pdftk-2.01/java/pdftk/com/lowagie/text/DocListener.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/DocListener.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/DocListener.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,172 @@
+/*
+ * $Id: DocListener.java,v 1.52 2004/12/14 11:52:47 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright (c) 1999, 2000, 2001, 2002 Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+/**
+ * A class that implements DocListener
will perform some
+ * actions when some actions are performed on a Document
.
+ *
+ * @see ElementListener
+ * @see Document
+ * @see DocWriter
+ */
+
+public interface DocListener extends ElementListener {
+
+ // methods
+
+/**
+ * Signals that the Document
has been opened and that
+ * Elements
can be added.
+ */
+
+ public void open();
+
+/**
+ * Sets the pagesize.
+ *
+ * @param pageSize the new pagesize
+ * @return a boolean
+ */
+
+ public boolean setPageSize(Rectangle pageSize);
+
+/**
+ * Signals that a Watermark
was added to the Document
.
+ *
+ * @param watermark the Watermark object
+ * @return true
if the element was added, false
if not.
+ */
+
+ // public boolean add(Watermark watermark); ssteward: dropped in 1.44
+
+/**
+ * Signals that a Watermark
was removed from the Document
.
+ */
+
+ // public void removeWatermark(); ssteward: dropped in 1.44
+
+/**
+ * Sets the margins.
+ *
+ * @param marginLeft the margin on the left
+ * @param marginRight the margin on the right
+ * @param marginTop the margin on the top
+ * @param marginBottom the margin on the bottom
+ * @return a boolean
+ */
+
+ public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom);
+
+ /**
+ * Parameter that allows you to do margin mirroring (odd/even pages)
+ * @param marginMirroring
+ * @return true if succesfull
+ */
+ public boolean setMarginMirroring(boolean marginMirroring);
+
+/**
+ * Signals that an new page has to be started.
+ *
+ * @return true
if the page was added, false
if not.
+ * @throws DocumentException when a document isn't open yet, or has been closed
+ */
+
+ public boolean newPage() throws DocumentException;
+
+/**
+ * Changes the header of this document.
+ *
+ * @param header the new header
+ */
+
+ // public void setHeader(HeaderFooter header); ssteward: dropped in 1.44
+
+/**
+ * Resets the header of this document.
+ */
+
+ // public void resetHeader(); ssteward: dropped in 1.44
+
+/**
+ * Changes the footer of this document.
+ *
+ * @param footer the new footer
+ */
+
+ // public void setFooter(HeaderFooter footer); ssteward: dropped in 1.44
+
+/**
+ * Resets the footer of this document.
+ */
+
+ // public void resetFooter(); ssteward: dropped in 1.44
+
+/**
+ * Sets the page number to 0.
+ */
+
+ public void resetPageCount();
+
+/**
+ * Sets the page number.
+ *
+ * @param pageN the new page number
+ */
+
+ public void setPageCount(int pageN);
+
+/**
+ * Clears text wrapping around images (if applicable).
+ * Method suggested by Pelikan Stephan
+ * @throws DocumentException
+ */
+ public void clearTextWrap() throws DocumentException;
+
+/**
+ * Signals that the Document
was closed and that no other
+ * Elements
will be added.
+ *
+ * The outputstream of every writer implementing DocListener
will be closed.
+ */
+
+ public void close();
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/DocWriter.java pdftk-2.01/java/pdftk/com/lowagie/text/DocWriter.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/DocWriter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/DocWriter.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,505 @@
+/*
+ * $Id: DocWriter.java,v 1.70 2004/12/14 11:52:47 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.io.BufferedOutputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import pdftk.com.lowagie.text.pdf.OutputStreamCounter;
+
+/**
+ * An abstract Writer
class for documents.
+ *
+ * DocWriter
is the abstract class of several writers such
+ * as PdfWriter
and HtmlWriter
.
+ * A DocWriter
can be added as a DocListener
+ * to a certain Document
by getting an instance (see method
+ * getInstance()
in the specific writer-classes).
+ * Every Element
added to the original Document
+ * will be written to the OutputStream
of the listening
+ * DocWriter
.
+ *
+ * @see Document
+ * @see DocListener
+ */
+
+public abstract class DocWriter implements DocListener {
+
+/** This is some byte that is often used. */
+ public static final byte NEWLINE = (byte)'\n';
+
+/** This is some byte that is often used. */
+ public static final byte TAB = (byte)'\t';
+
+/** This is some byte that is often used. */
+ public static final byte LT = (byte)'<';
+
+/** This is some byte that is often used. */
+ public static final byte SPACE = (byte)' ';
+
+/** This is some byte that is often used. */
+ public static final byte EQUALS = (byte)'=';
+
+/** This is some byte that is often used. */
+ public static final byte QUOTE = (byte)'\"';
+
+/** This is some byte that is often used. */
+ public static final byte GT = (byte)'>';
+
+/** This is some byte that is often used. */
+ public static final byte FORWARD = (byte)'/';
+
+ // membervariables
+
+/** The pageSize. */
+ protected Rectangle pageSize;
+
+/** This is the document that has to be written. */
+ protected Document document;
+
+/** The outputstream of this writer. */
+ protected OutputStreamCounter os;
+
+/** Is the writer open for writing? */
+ protected boolean open = false;
+
+/** Do we have to pause all writing actions? */
+ // ssteward: changed from "pause" to "m_pause" to
+ // remove gcj complaints over ambiguity with pause()
+ protected boolean m_pause = false;
+
+/** Closes the stream on document close */
+ protected boolean closeStream = true;
+
+ // constructor
+
+ protected DocWriter() {
+ }
+
+/**
+ * Constructs a DocWriter
.
+ *
+ * @param document The Document
that has to be written
+ * @param os The OutputStream
the writer has to write to.
+ */
+
+ protected DocWriter(Document document, OutputStream os) {
+ this.document = document;
+ this.os = new OutputStreamCounter(new BufferedOutputStream(os));
+ }
+
+ // implementation of the DocListener methods
+
+/**
+ * Signals that an Element
was added to the Document
.
+ *
+ * This method should be overriden in the specific DocWriter classes
+ * derived from this abstract class.
+ *
+ * @param element A high level object to add
+ * @return false
+ * @throws DocumentException when a document isn't open yet, or has been closed
+ */
+
+ public boolean add(Element element) throws DocumentException {
+ return false;
+ }
+
+/**
+ * Signals that the Document
was opened.
+ */
+
+ public void open() {
+ open = true;
+ }
+
+/**
+ * Sets the pagesize.
+ *
+ * @param pageSize the new pagesize
+ * @return a boolean
+ */
+
+ public boolean setPageSize(Rectangle pageSize) {
+ this.pageSize = pageSize;
+ return true;
+ }
+
+/**
+ * Sets the Watermark
.
+ *
+ * This method should be overriden in the specific DocWriter classes
+ * derived from this abstract class if they actually support the use of
+ * a Watermark
.
+ *
+ * @param watermark A watermark object
+ * @return false
(because watermarks aren't supported by default).
+ */
+/* ssteward: dropped in 1.44
+ public boolean add(Watermark watermark) {
+ return false;
+ }
+*/
+/**
+ * Removes the Watermark
(if there is one).
+ */
+/* ssteward: dropped in 1.44
+ public void removeWatermark() {
+ }
+*/
+/**
+ * Sets the margins.
+ *
+ * This does nothing. Has to be overridden if needed.
+ *
+ * @param marginLeft the margin on the left
+ * @param marginRight the margin on the right
+ * @param marginTop the margin on the top
+ * @param marginBottom the margin on the bottom
+ * @return false
+ */
+
+ public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom) {
+ return false;
+ }
+
+/**
+ * Signals that an new page has to be started.
+ *
+ * This does nothing. Has to be overridden if needed.
+ *
+ * @return true
if the page was added, false
if not.
+ * @throws DocumentException when a document isn't open yet, or has been closed
+ */
+
+ public boolean newPage() throws DocumentException {
+ if (!open) {
+ return false;
+ }
+ return true;
+ }
+
+/**
+ * Changes the header of this document.
+ *
+ * This method should be overriden in the specific DocWriter classes
+ * derived from this abstract class if they actually support the use of
+ * headers.
+ *
+ * @param header the new header
+ */
+/* ssteward: dropped in 1.44
+ public void setHeader(HeaderFooter header) {
+ }
+*/
+
+/**
+ * Resets the header of this document.
+ *
+ * This method should be overriden in the specific DocWriter classes
+ * derived from this abstract class if they actually support the use of
+ * headers.
+ */
+
+ public void resetHeader() {
+ }
+
+/**
+ * Changes the footer of this document.
+ *
+ * This method should be overriden in the specific DocWriter classes
+ * derived from this abstract class if they actually support the use of
+ * footers.
+ *
+ * @param footer the new footer
+ */
+/* ssteward: dropped in 1.44
+ public void setFooter(HeaderFooter footer) {
+ }
+*/
+
+/**
+ * Resets the footer of this document.
+ *
+ * This method should be overriden in the specific DocWriter classes
+ * derived from this abstract class if they actually support the use of
+ * footers.
+ */
+
+ public void resetFooter() {
+ }
+
+/**
+ * Sets the page number to 0.
+ *
+ * This method should be overriden in the specific DocWriter classes
+ * derived from this abstract class if they actually support the use of
+ * pagenumbers.
+ */
+
+ public void resetPageCount() {
+ }
+
+/**
+ * Sets the page number.
+ *
+ * This method should be overriden in the specific DocWriter classes
+ * derived from this abstract class if they actually support the use of
+ * pagenumbers.
+ *
+ * @param pageN the new page number
+ */
+
+ public void setPageCount(int pageN) {
+ }
+
+/**
+ * Signals that the Document
was closed and that no other
+ * Elements
will be added.
+ */
+
+ public void close() {
+ open = false;
+ try {
+ os.flush();
+ if (closeStream)
+ os.close();
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ }
+
+ // methods
+
+/** Converts a String
into a Byte
array
+ * according to the ISO-8859-1 codepage.
+ * @param text the text to be converted
+ * @return the conversion result
+ */
+
+ public static final byte[] getISOBytes(String text)
+ {
+ if (text == null)
+ return null;
+ int len = text.length();
+ byte b[] = new byte[len];
+ for (int k = 0; k < len; ++k)
+ b[k] = (byte)text.charAt(k);
+ return b;
+ }
+
+/**
+ * Let the writer know that all writing has to be paused.
+ */
+
+ public void pause() {
+ // ssteward
+ m_pause = true;
+ }
+
+/**
+ * Let the writer know that writing may be resumed.
+ */
+
+ public void resume() {
+ // ssteward
+ m_pause = false;
+ }
+
+/**
+ * Flushes the BufferedOutputStream
.
+ */
+
+ public void flush() {
+ try {
+ os.flush();
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ }
+
+/**
+ * Writes a String
to the OutputStream
.
+ *
+ * @param string the String
to write
+ * @throws IOException
+ */
+
+ protected void write(String string) throws IOException {
+ os.write(getISOBytes(string));
+ }
+
+/**
+ * Writes a number of tabs.
+ *
+ * @param indent the number of tabs to add
+ * @throws IOException
+ */
+
+ protected void addTabs(int indent) throws IOException {
+ os.write(NEWLINE);
+ for (int i = 0; i < indent; i++) {
+ os.write(TAB);
+ }
+ }
+
+/**
+ * Writes a key-value pair to the outputstream.
+ *
+ * @param key the name of an attribute
+ * @param value the value of an attribute
+ * @throws IOException
+ */
+
+ protected void write(String key, String value)
+ throws IOException {
+ os.write(SPACE);
+ write(key);
+ os.write(EQUALS);
+ os.write(QUOTE);
+ write(value);
+ os.write(QUOTE);
+ }
+
+/**
+ * Writes a starttag to the outputstream.
+ *
+ * @param tag the name of the tag
+ * @throws IOException
+ */
+
+ protected void writeStart(String tag)
+ throws IOException {
+ os.write(LT);
+ write(tag);
+ }
+
+/**
+ * Writes an endtag to the outputstream.
+ *
+ * @param tag the name of the tag
+ * @throws IOException
+ */
+
+ protected void writeEnd(String tag)
+ throws IOException {
+ os.write(LT);
+ os.write(FORWARD);
+ write(tag);
+ os.write(GT);
+ }
+
+/**
+ * Writes an endtag to the outputstream.
+ * @throws IOException
+ */
+
+ protected void writeEnd()
+ throws IOException {
+ os.write(SPACE);
+ os.write(FORWARD);
+ os.write(GT);
+ }
+
+/**
+ * Writes the markup attributes of the specified MarkupAttributes
+ * object to the OutputStream
.
+ * @param mAtt the MarkupAttributes
to write.
+ * @return true, if writing the markup attributes succeeded
+ * @throws IOException
+ */
+ protected boolean writeMarkupAttributes(MarkupAttributes mAtt)
+ throws IOException
+ {
+ Iterator attributeIterator = mAtt.getMarkupAttributeNames().iterator();
+ boolean result = attributeIterator.hasNext();
+ while (attributeIterator.hasNext()) {
+ String name = String.valueOf(attributeIterator.next());
+ write(name, mAtt.getMarkupAttribute(name));
+ }
+ return result;
+ }
+
+/**
+ * Returns true
if the specified Element
implements
+ * MarkupAttributes
and has one or more attributes to write.
+ * @param element the Element
to check.
+ * @return boolean
.
+ */
+ protected static boolean hasMarkupAttributes(Element element) {
+ return (element instanceof MarkupAttributes &&
+ !(((MarkupAttributes)element).getMarkupAttributeNames().isEmpty()));
+ }
+
+ /** Checks if the stream is to be closed on document close
+ * @return true if the stream is closed on documnt close
+ *
+ */
+ public boolean isCloseStream() {
+ return closeStream;
+ }
+
+ /** Sets the close state of the stream after document close
+ * @param closeStream true if the stream is closed on document close
+ *
+ */
+ public void setCloseStream(boolean closeStream) {
+ this.closeStream = closeStream;
+ }
+
+
+ /**
+ * @see pdftk.com.lowagie.text.DocListener#clearTextWrap()
+ */
+ public void clearTextWrap() throws DocumentException {
+ // do nothing
+ }
+ /**
+ * @see pdftk.com.lowagie.text.DocListener#setMarginMirroring(boolean)
+ */
+ public boolean setMarginMirroring(boolean MarginMirroring) {
+ return false;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Document.java pdftk-2.01/java/pdftk/com/lowagie/text/Document.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Document.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Document.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,912 @@
+/*
+ * $Id: Document.java,v 1.100 2005/07/17 14:45:30 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import java.util.Date;
+
+/**
+ * A generic Document class.
+ *
+ * All kinds of Text-elements can be added to a HTMLDocument
.
+ * The Document
signals all the listeners when an element has
+ * been added.
+ *
+ * Remark:
+ *
+ * Once a document is created you can add some meta information.
+ * You can also set the headers/footers.
+ * You have to open the document before you can write content.
+ * You can only write content (no more meta-formation!) once a document is
+ * opened.
+ * When you change the header/footer on a certain page, this will be
+ * effective starting on the next page.
+ * Ater closing the document, every listener (as well as its
+ * OutputStream
) is closed too.
+ *
+ * Example:
+ *
+ * // creation of the document with a certain size and certain margins
+ * Document document = new Document(PageSize.A4, 50, 50, 50, 50);
+ * try { // creation of the different writers HtmlWriter.getInstance(
+ * document , System.out); PdfWriter.getInstance(
+ * document , new FileOutputStream("text.pdf"));
+ * // we add some meta information to the document
+ * document.addAuthor("Bruno Lowagie");
+ * document.addSubject("This is the result of a Test.");
+ * // we define a header and a footer HeaderFooter header = new
+ * HeaderFooter(new Phrase("This is a header."), false); HeaderFooter footer =
+ * new HeaderFooter(new Phrase("This is page "), new Phrase("."));
+ * footer.setAlignment(Element.ALIGN_CENTER);
+ * document.setHeader(header);
+ * document.setFooter(footer); // we open the document for
+ * writing document.open(); document.add(new
+ * Paragraph("Hello world")); } catch(DocumentException de) {
+ * System.err.println(de.getMessage()); } document.close();
+ *
+ *
+ *
+ *
+ */
+
+public class Document implements DocListener {
+
+ // membervariables
+
+ /** This constant may only be changed by Paulo Soares and/or Bruno Lowagie. */
+ private static final String ITEXT_VERSION = "itext-paulo-155 (itextpdf.sf.net-lowagie.com)";
+
+ /**
+ * Allows the pdf documents to be produced without compression for debugging
+ * purposes.
+ */
+ public static boolean compress = true;
+
+ /** The DocListener. */
+ private ArrayList listeners = new ArrayList();
+
+ /** Is the document open or not? */
+ protected boolean open;
+
+ /** Has the document already been closed? */
+ protected boolean close;
+
+ // membervariables concerning the layout
+
+ /** The size of the page. */
+ protected Rectangle pageSize;
+
+ /** The watermark on the pages. */
+ // protected Watermark watermark = null; ssteward: dropped in 1.44
+
+ /** margin in x direction starting from the left */
+ protected float marginLeft = 0;
+
+ /** margin in x direction starting from the right */
+ protected float marginRight = 0;
+
+ /** margin in y direction starting from the top */
+ protected float marginTop = 0;
+
+ /** margin in y direction starting from the bottom */
+ protected float marginBottom = 0;
+
+ protected boolean marginMirroring = false;
+
+ /** Content of JavaScript onLoad function */
+ protected String javaScript_onLoad = null;
+
+ /** Content of JavaScript onUnLoad function */
+ protected String javaScript_onUnLoad = null;
+
+ /** Style class in HTML body tag */
+ protected String htmlStyleClass = null;
+
+ // headers, footers
+
+ /** Current pagenumber */
+ protected int pageN = 0;
+
+ /** This is the textual part of a Page; it can contain a header */
+ // protected HeaderFooter header = null; ssteward: dropped in 1.44
+
+ /** This is the textual part of the footer */
+ // protected HeaderFooter footer = null; ssteward: dropped in 1.44
+
+ // constructor
+
+ /**
+ * Constructs a new Document
-object.
+ */
+
+ public Document() {
+ this(PageSize.A4);
+ }
+
+ /**
+ * Constructs a new Document
-object.
+ *
+ * @param pageSize
+ * the pageSize
+ */
+
+ public Document(Rectangle pageSize) {
+ this(pageSize, 36, 36, 36, 36);
+ }
+
+ /**
+ * Constructs a new Document
-object.
+ *
+ * @param pageSize
+ * the pageSize
+ * @param marginLeft
+ * the margin on the left
+ * @param marginRight
+ * the margin on the right
+ * @param marginTop
+ * the margin on the top
+ * @param marginBottom
+ * the margin on the bottom
+ */
+
+ public Document(Rectangle pageSize, float marginLeft, float marginRight,
+ float marginTop, float marginBottom) {
+ this.pageSize = pageSize;
+ this.marginLeft = marginLeft;
+ this.marginRight = marginRight;
+ this.marginTop = marginTop;
+ this.marginBottom = marginBottom;
+ }
+
+ // listener methods
+
+ /**
+ * Adds a DocListener
to the Document
.
+ *
+ * @param listener
+ * the new DocListener.
+ */
+
+ public void addDocListener(DocListener listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * Removes a DocListener
from the Document
.
+ *
+ * @param listener
+ * the DocListener that has to be removed.
+ */
+
+ public void removeDocListener(DocListener listener) {
+ listeners.remove(listener);
+ }
+
+ // methods implementing the DocListener interface
+
+ /**
+ * Adds an Element
to the Document
.
+ *
+ * @param element
+ * the Element
to add
+ * @return true
if the element was added, false
+ *
if not
+ * @throws DocumentException
+ * when a document isn't open yet, or has been closed
+ */
+
+ public boolean add(Element element) throws DocumentException {
+ if (close) {
+ throw new DocumentException(
+ "The document has been closed. You can't add any Elements.");
+ }
+ int type = element.type();
+ if (open) {
+ if (!(type == Element.CHUNK || type == Element.PHRASE
+ || type == Element.PARAGRAPH || type == Element.TABLE
+ || type == Element.PTABLE
+ || type == Element.MULTI_COLUMN_TEXT
+ || type == Element.ANCHOR || type == Element.ANNOTATION
+ || type == Element.CHAPTER || type == Element.SECTION
+ || type == Element.LIST || type == Element.LISTITEM
+ || type == Element.RECTANGLE || type == Element.JPEG
+ || type == Element.IMGRAW || type == Element.IMGTEMPLATE || type == Element.GRAPHIC)) {
+ throw new DocumentException(
+ "The document is open; you can only add Elements with content.");
+ }
+ } else {
+ if (!(type == Element.HEADER || type == Element.TITLE
+ || type == Element.SUBJECT || type == Element.KEYWORDS
+ || type == Element.AUTHOR || type == Element.PRODUCER
+ || type == Element.CREATOR || type == Element.CREATIONDATE)) {
+ throw new DocumentException(
+ "The document is not open yet; you can only add Meta information.");
+ }
+ }
+ boolean success = false;
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ success |= listener.add(element);
+ }
+ return success;
+ }
+
+ /**
+ * Opens the document.
+ *
+ * Once the document is opened, you can't write any Header- or
+ * Meta-information anymore. You have to open the document before you can
+ * begin to add content to the body of the document.
+ */
+
+ public void open() {
+ if (!close) {
+ open = true;
+ }
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.setPageSize(pageSize);
+ listener.setMargins(marginLeft, marginRight, marginTop,
+ marginBottom);
+ listener.open();
+ }
+ }
+
+ /**
+ * Sets the pagesize.
+ *
+ * @param pageSize
+ * the new pagesize
+ * @return a boolean
+ */
+
+ public boolean setPageSize(Rectangle pageSize) {
+ this.pageSize = pageSize;
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.setPageSize(pageSize);
+ }
+ return true;
+ }
+
+ /**
+ * Sets the Watermark
.
+ *
+ * @param watermark
+ * the watermark to add
+ * @return true
if the element was added, false
+ *
if not.
+ */
+ /* ssteward: dropped in 1.44
+ public boolean add(Watermark watermark) {
+ this.watermark = watermark;
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.add(watermark);
+ }
+ return true;
+ }
+ */
+
+ /**
+ * Removes the Watermark
.
+ */
+ /* ssteward: dropped in 1.44
+ public void removeWatermark() {
+ this.watermark = null;
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.removeWatermark();
+ }
+ }
+ */
+
+ /**
+ * Sets the margins.
+ *
+ * @param marginLeft
+ * the margin on the left
+ * @param marginRight
+ * the margin on the right
+ * @param marginTop
+ * the margin on the top
+ * @param marginBottom
+ * the margin on the bottom
+ * @return a boolean
+ */
+
+ public boolean setMargins(float marginLeft, float marginRight,
+ float marginTop, float marginBottom) {
+ this.marginLeft = marginLeft;
+ this.marginRight = marginRight;
+ this.marginTop = marginTop;
+ this.marginBottom = marginBottom;
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.setMargins(marginLeft, marginRight, marginTop,
+ marginBottom);
+ }
+ return true;
+ }
+
+ /**
+ * Signals that an new page has to be started.
+ *
+ * @return true
if the page was added, false
+ * if not.
+ * @throws DocumentException
+ * when a document isn't open yet, or has been closed
+ */
+
+ public boolean newPage() throws DocumentException {
+ if (!open || close) {
+ return false;
+ }
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.newPage();
+ }
+ return true;
+ }
+
+ /**
+ * Changes the header of this document.
+ *
+ * @param header
+ * the new header
+ */
+ /* ssteward: dropped in 1.44
+ public void setHeader(HeaderFooter header) {
+ this.header = header;
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.setHeader(header);
+ }
+ }
+ */
+
+ /**
+ * Resets the header of this document.
+ */
+ /* ssteward: dropped in 1.44
+ public void resetHeader() {
+ this.header = null;
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.resetHeader();
+ }
+ }
+ */
+
+ /**
+ * Changes the footer of this document.
+ *
+ * @param footer
+ * the new footer
+ */
+ /* ssteward: dropped in 1.44
+ public void setFooter(HeaderFooter footer) {
+ this.footer = footer;
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.setFooter(footer);
+ }
+ }
+ */
+
+ /**
+ * Resets the footer of this document.
+ */
+ /* ssteward: dropped in 1.44
+ public void resetFooter() {
+ this.footer = null;
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.resetFooter();
+ }
+ }
+ */
+
+ /**
+ * Sets the page number to 0.
+ */
+
+ public void resetPageCount() {
+ pageN = 0;
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.resetPageCount();
+ }
+ }
+
+ /**
+ * Sets the page number.
+ *
+ * @param pageN
+ * the new page number
+ */
+
+ public void setPageCount(int pageN) {
+ this.pageN = pageN;
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.setPageCount(pageN);
+ }
+ }
+
+ /**
+ * Returns the current page number.
+ *
+ * @return the current page number
+ */
+
+ public int getPageNumber() {
+ return this.pageN;
+ }
+
+ /**
+ * Closes the document.
+ *
+ * Once all the content has been written in the body, you have to close the
+ * body. After that nothing can be written to the body anymore.
+ */
+
+ public void close() {
+ if (!close) {
+ open = false;
+ close = true;
+ }
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.close();
+ }
+ }
+
+ // methods concerning the header or some meta information
+
+ /**
+ * Adds a user defined header to the document.
+ *
+ * @param name
+ * the name of the header
+ * @param content
+ * the content of the header
+ * @return true
if successful, false
otherwise
+ */
+
+ public boolean addHeader(String name, String content) {
+ try {
+ return add(new Header(name, content));
+ } catch (DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+ /**
+ * Adds the title to a Document.
+ *
+ * @param title
+ * the title
+ * @return true
if successful, false
otherwise
+ */
+
+ public boolean addTitle(String title) {
+ try {
+ return add(new Meta(Element.TITLE, title));
+ } catch (DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+ /**
+ * Adds the subject to a Document.
+ *
+ * @param subject
+ * the subject
+ * @return true
if successful, false
otherwise
+ */
+
+ public boolean addSubject(String subject) {
+ try {
+ return add(new Meta(Element.SUBJECT, subject));
+ } catch (DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+ /**
+ * Adds the keywords to a Document.
+ *
+ * @param keywords
+ * adds the keywords to the document
+ * @return true
if successful, false
otherwise
+ */
+
+ public boolean addKeywords(String keywords) {
+ try {
+ return add(new Meta(Element.KEYWORDS, keywords));
+ } catch (DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+ /**
+ * Adds the author to a Document.
+ *
+ * @param author
+ * the name of the author
+ * @return true
if successful, false
otherwise
+ */
+
+ public boolean addAuthor(String author) {
+ try {
+ return add(new Meta(Element.AUTHOR, author));
+ } catch (DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+ /**
+ * Adds the creator to a Document.
+ *
+ * @param creator
+ * the name of the creator
+ * @return true
if successful, false
otherwise
+ */
+
+ public boolean addCreator(String creator) {
+ try {
+ return add(new Meta(Element.CREATOR, creator));
+ } catch (DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+ /**
+ * Adds the producer to a Document.
+ *
+ * @return true
if successful, false
otherwise
+ */
+
+ public boolean addProducer() {
+ try {
+ return add(new Meta(Element.PRODUCER, "iText by lowagie.com"));
+ } catch (DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+ /**
+ * Adds the current date and time to a Document.
+ *
+ * @return true
if successful, false
otherwise
+ */
+
+ public boolean addCreationDate() {
+ try {
+ /* bugfix by 'taqua' (Thomas) */
+ final SimpleDateFormat sdf = new SimpleDateFormat(
+ "EEE MMM dd HH:mm:ss zzz yyyy");
+ return add(new Meta(Element.CREATIONDATE, sdf.format(new Date())));
+ } catch (DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+ // methods to get the layout of the document.
+
+ /**
+ * Returns the left margin.
+ *
+ * @return the left margin
+ */
+
+ public float leftMargin() {
+ return marginLeft;
+ }
+
+ /**
+ * Return the right margin.
+ *
+ * @return the right margin
+ */
+
+ public float rightMargin() {
+ return marginRight;
+ }
+
+ /**
+ * Returns the top margin.
+ *
+ * @return the top margin
+ */
+
+ public float topMargin() {
+ return marginTop;
+ }
+
+ /**
+ * Returns the bottom margin.
+ *
+ * @return the bottom margin
+ */
+
+ public float bottomMargin() {
+ return marginBottom;
+ }
+
+ /**
+ * Returns the lower left x-coordinate.
+ *
+ * @return the lower left x-coordinate
+ */
+
+ public float left() {
+ return pageSize.left(marginLeft);
+ }
+
+ /**
+ * Returns the upper right x-coordinate.
+ *
+ * @return the upper right x-coordinate
+ */
+
+ public float right() {
+ return pageSize.right(marginRight);
+ }
+
+ /**
+ * Returns the upper right y-coordinate.
+ *
+ * @return the upper right y-coordinate
+ */
+
+ public float top() {
+ return pageSize.top(marginTop);
+ }
+
+ /**
+ * Returns the lower left y-coordinate.
+ *
+ * @return the lower left y-coordinate
+ */
+
+ public float bottom() {
+ return pageSize.bottom(marginBottom);
+ }
+
+ /**
+ * Returns the lower left x-coordinate considering a given margin.
+ *
+ * @param margin
+ * a margin
+ * @return the lower left x-coordinate
+ */
+
+ public float left(float margin) {
+ return pageSize.left(marginLeft + margin);
+ }
+
+ /**
+ * Returns the upper right x-coordinate, considering a given margin.
+ *
+ * @param margin
+ * a margin
+ * @return the upper right x-coordinate
+ */
+
+ public float right(float margin) {
+ return pageSize.right(marginRight + margin);
+ }
+
+ /**
+ * Returns the upper right y-coordinate, considering a given margin.
+ *
+ * @param margin
+ * a margin
+ * @return the upper right y-coordinate
+ */
+
+ public float top(float margin) {
+ return pageSize.top(marginTop + margin);
+ }
+
+ /**
+ * Returns the lower left y-coordinate, considering a given margin.
+ *
+ * @param margin
+ * a margin
+ * @return the lower left y-coordinate
+ */
+
+ public float bottom(float margin) {
+ return pageSize.bottom(marginBottom + margin);
+ }
+
+ /**
+ * Gets the pagesize.
+ *
+ * @return the page size
+ */
+
+ public Rectangle getPageSize() {
+ return this.pageSize;
+ }
+
+ /**
+ * Checks if the document is open.
+ *
+ * @return true
if the document is open
+ */
+ public boolean isOpen() {
+ return open;
+ }
+
+ /**
+ * Gets the iText version.
+ * This method may only be changed by Paulo Soares and/or Bruno Lowagie.
+ * @return iText version
+ */
+ public static final String getVersion() {
+ return ITEXT_VERSION;
+ }
+
+ /**
+ * Adds a JavaScript onLoad function to the HTML body tag
+ *
+ * @param code
+ * the JavaScript code to be executed on load of the HTML page
+ */
+
+ public void setJavaScript_onLoad(String code) {
+ this.javaScript_onLoad = code;
+ }
+
+ /**
+ * Gets the JavaScript onLoad command.
+ *
+ * @return the JavaScript onLoad command
+ */
+
+ public String getJavaScript_onLoad() {
+ return this.javaScript_onLoad;
+ }
+
+ /**
+ * Adds a JavaScript onUnLoad function to the HTML body tag
+ *
+ * @param code
+ * the JavaScript code to be executed on unload of the HTML page
+ */
+
+ public void setJavaScript_onUnLoad(String code) {
+ this.javaScript_onUnLoad = code;
+ }
+
+ /**
+ * Gets the JavaScript onUnLoad command.
+ *
+ * @return the JavaScript onUnLoad command
+ */
+
+ public String getJavaScript_onUnLoad() {
+ return this.javaScript_onUnLoad;
+ }
+
+ /**
+ * Adds a style class to the HTML body tag
+ *
+ * @param htmlStyleClass
+ * the style class for the HTML body tag
+ */
+
+ public void setHtmlStyleClass(String htmlStyleClass) {
+ this.htmlStyleClass = htmlStyleClass;
+ }
+
+ /**
+ * Gets the style class of the HTML body tag
+ *
+ * @return the style class of the HTML body tag
+ */
+
+ public String getHtmlStyleClass() {
+ return this.htmlStyleClass;
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.DocListener#clearTextWrap()
+ */
+ public void clearTextWrap() throws DocumentException {
+ if (open && !close) {
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.clearTextWrap();
+ }
+ }
+ }
+
+ /**
+ * Set the margin mirroring. It will mirror margins for odd/even pages.
+ *
+ * Note: it will not work with {@link Table}.
+ *
+ * @param marginMirroring
+ * true
to mirror the margins
+ * @return always true
+ */
+ public boolean setMarginMirroring(boolean marginMirroring) {
+ this.marginMirroring = marginMirroring;
+ DocListener listener;
+ for (Iterator iterator = listeners.iterator(); iterator.hasNext();) {
+ listener = (DocListener) iterator.next();
+ listener.setMarginMirroring(marginMirroring);
+ }
+ return true;
+ }
+
+ /**
+ * Gets the margin mirroring flag.
+ *
+ * @return the margin mirroring flag
+ */
+ public boolean isMarginMirroring() {
+ return marginMirroring;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/DocumentException.java pdftk-2.01/java/pdftk/com/lowagie/text/DocumentException.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/DocumentException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/DocumentException.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,176 @@
+/*
+ * $Id: DocumentException.java,v 1.50 2004/12/14 11:52:46 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ *
+ */
+
+package pdftk.com.lowagie.text;
+
+/**
+ * Signals that an error has occurred in a Document
.
+ *
+ * @see BadElementException
+ * @see Document
+ * @see DocWriter
+ * @see DocListener
+ */
+
+public class DocumentException extends Exception {
+ private Exception ex;
+
+ /**
+ * Creates a Document exception.
+ * @param ex an exception that has to be turned into a DocumentException
+ */
+ public DocumentException(Exception ex) {
+ this.ex = ex;
+ }
+
+ // constructors
+
+/**
+ * Constructs a DocumentException
whithout a message.
+ */
+
+ public DocumentException() {
+ super();
+ }
+
+/**
+ * Constructs a DocumentException
with a message.
+ *
+ * @param message a message describing the exception
+ */
+
+ public DocumentException(String message) {
+ super(message);
+ }
+
+ /**
+ * We print the message of the checked exception
+ * @return the error message
+ */
+ public String getMessage() {
+ if (ex == null)
+ return super.getMessage();
+ else
+ return ex.getMessage();
+ }
+
+ /**
+ * and make sure we also produce a localized version
+ * @return a localized message
+ */
+ public String getLocalizedMessage() {
+ if (ex == null)
+ return super.getLocalizedMessage();
+ else
+ return ex.getLocalizedMessage();
+ }
+
+ /**
+ * The toString() is changed to be prefixed with ExceptionConverter
+ * @return the String version of the exception
+ */
+ public String toString() {
+ if (ex == null)
+ return super.toString();
+ else
+ return split(getClass().getName()) + ": " + ex;
+ }
+
+ /** we have to override this as well */
+ public void printStackTrace() {
+ printStackTrace(System.err);
+ }
+
+ /**
+ * here we prefix, with s.print(), not s.println(), the stack
+ * trace with "ExceptionConverter:"
+ * @param s a printstream object
+ */
+ public void printStackTrace(java.io.PrintStream s) {
+ if (ex == null)
+ super.printStackTrace(s);
+ else {
+ synchronized (s) {
+ s.print(split(getClass().getName()) + ": ");
+ ex.printStackTrace(s);
+ }
+ }
+ }
+
+ /**
+ * Again, we prefix the stack trace with "ExceptionConverter:"
+ * @param s A PrintWriter object
+ */
+ public void printStackTrace(java.io.PrintWriter s) {
+ if (ex == null)
+ super.printStackTrace(s);
+ else {
+ synchronized (s) {
+ s.print(split(getClass().getName()) + ": ");
+ ex.printStackTrace(s);
+ }
+ }
+ }
+
+ /**
+ * Removes everything in a String that comes before a '.'
+ * @param s the original string
+ * @return the part that comes after the dot
+ */
+ private static String split(String s) {
+ int i = s.lastIndexOf('.');
+ if (i < 0)
+ return s;
+ else
+ return s.substring(i + 1);
+ }
+
+ /** requests to fill in the stack trace we will have to ignore.
+ * We can't throw an exception here, because this method
+ * is called by the constructor of Throwable */
+// public Throwable fillInStackTrace() {
+// if (ex == null)
+// return super.fillInStackTrace();
+// else
+// return this;
+// }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Element.java pdftk-2.01/java/pdftk/com/lowagie/text/Element.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Element.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Element.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,315 @@
+/*
+ * $Id: Element.java,v 1.66 2005/05/04 14:41:15 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.util.ArrayList;
+
+/**
+ * Interface for a text element.
+ *
+ * Remark: I looked at the interface javax.swing.text.Element, but I decided to
+ * write my own text-classes for two reasons:
+ *
+ * The javax.swing.text-classes may be very generic, I think they are
+ * overkill: they are to heavy for what they have to do.
+ * A lot of people using iText (formerly known as rugPdf), still use
+ * JDK1.1.x. I try to keep the Java2 requirements limited to the Collection
+ * classes (I think they're really great). However, if I use the
+ * javax.swing.text classes, it will become very difficult to downgrade rugPdf.
+ *
+ *
+ * @see Anchor
+ * @see Cell
+ * @see Chapter
+ * @see Chunk
+ * @see Graphic
+ * @see Header
+ * @see Image
+ * @see Jpeg
+ * @see List
+ * @see ListItem
+ * @see Meta
+ * @see Paragraph
+ * @see Phrase
+ * @see Rectangle
+ * @see Row
+ * @see Section
+ * @see Table
+ */
+
+public interface Element {
+
+ // static membervariables (meta information)
+
+ /** This is a possible type of Element
. */
+ public static final int HEADER = 0;
+
+ /** This is a possible type of Element
. */
+ public static final int TITLE = 1;
+
+ /** This is a possible type of Element
. */
+ public static final int SUBJECT = 2;
+
+ /** This is a possible type of Element
. */
+ public static final int KEYWORDS = 3;
+
+ /** This is a possible type of Element . */
+ public static final int AUTHOR = 4;
+
+ /** This is a possible type of Element . */
+ public static final int PRODUCER = 5;
+
+ /** This is a possible type of Element . */
+ public static final int CREATIONDATE = 6;
+
+ /** This is a possible type of Element . */
+ public static final int CREATOR = 7;
+
+ // static membervariables (content)
+
+ /** This is a possible type of Element
. */
+ public static final int CHUNK = 10;
+
+ /** This is a possible type of Element
. */
+ public static final int PHRASE = 11;
+
+ /** This is a possible type of Element
. */
+ public static final int PARAGRAPH = 12;
+
+ /** This is a possible type of Element
*/
+ public static final int SECTION = 13;
+
+ /** This is a possible type of Element
*/
+ public static final int LIST = 14;
+
+ /** This is a possible type of Element
*/
+ public static final int LISTITEM = 15;
+
+ /** This is a possible type of Element
*/
+ public static final int CHAPTER = 16;
+
+ /** This is a possible type of Element
*/
+ public static final int ANCHOR = 17;
+
+ // static membervariables (tables)
+
+ /** This is a possible type of Element
. */
+ public static final int CELL = 20;
+
+ /** This is a possible type of Element
. */
+ public static final int ROW = 21;
+
+ /** This is a possible type of Element
. */
+ public static final int TABLE = 22;
+
+ /** This is a possible type of Element
. */
+ public static final int PTABLE = 23;
+
+ // static membervariables (annotations)
+
+ /** This is a possible type of Element
. */
+ public static final int ANNOTATION = 29;
+
+ // static membervariables (geometric figures)
+
+ /** This is a possible type of Element
. */
+ public static final int RECTANGLE = 30;
+
+ /** This is a possible type of Element
. */
+ public static final int JPEG = 32;
+
+ /** This is a possible type of Element
. */
+ public static final int IMGRAW = 34;
+
+ /** This is a possible type of Element
. */
+ public static final int IMGTEMPLATE = 35;
+
+ /** This is a possible type of Element
. */
+ public static final int GRAPHIC = 39;
+
+ /** This is a possible type of Element
. */
+ public static final int MULTI_COLUMN_TEXT = 40;
+
+ // static membervariables (alignment)
+
+ /**
+ * A possible value for paragraph alignment. This specifies that the text is
+ * aligned to the left indent and extra whitespace should be placed on the
+ * right.
+ */
+ public static final int ALIGN_UNDEFINED = -1;
+
+ /**
+ * A possible value for paragraph alignment. This specifies that the text is
+ * aligned to the left indent and extra whitespace should be placed on the
+ * right.
+ */
+ public static final int ALIGN_LEFT = 0;
+
+ /**
+ * A possible value for paragraph alignment. This specifies that the text is
+ * aligned to the center and extra whitespace should be placed equally on
+ * the left and right.
+ */
+ public static final int ALIGN_CENTER = 1;
+
+ /**
+ * A possible value for paragraph alignment. This specifies that the text is
+ * aligned to the right indent and extra whitespace should be placed on the
+ * left.
+ */
+ public static final int ALIGN_RIGHT = 2;
+
+ /**
+ * A possible value for paragraph alignment. This specifies that extra
+ * whitespace should be spread out through the rows of the paragraph with
+ * the text lined up with the left and right indent except on the last line
+ * which should be aligned to the left.
+ */
+ public static final int ALIGN_JUSTIFIED = 3;
+
+ /**
+ * A possible value for vertical alignment.
+ */
+
+ public static final int ALIGN_TOP = 4;
+
+ /**
+ * A possible value for vertical alignment.
+ */
+
+ public static final int ALIGN_MIDDLE = 5;
+
+ /**
+ * A possible value for vertical alignment.
+ */
+
+ public static final int ALIGN_BOTTOM = 6;
+
+ /**
+ * A possible value for vertical alignment.
+ */
+ public static final int ALIGN_BASELINE = 7;
+
+ /**
+ * Does the same as ALIGN_JUSTIFIED but the last line is also spread out.
+ */
+ public static final int ALIGN_JUSTIFIED_ALL = 8;
+
+ // static member variables for CCITT compression
+
+ /**
+ * Pure two-dimensional encoding (Group 4)
+ */
+ public static final int CCITTG4 = 0x100;
+
+ /**
+ * Pure one-dimensional encoding (Group 3, 1-D)
+ */
+ public static final int CCITTG3_1D = 0x101;
+
+ /**
+ * Mixed one- and two-dimensional encoding (Group 3, 2-D)
+ */
+ public static final int CCITTG3_2D = 0x102;
+
+ /**
+ * A flag indicating whether 1-bits are to be interpreted as black pixels
+ * and 0-bits as white pixels,
+ */
+ public static final int CCITT_BLACKIS1 = 1;
+
+ /**
+ * A flag indicating whether the filter expects extra 0-bits before each
+ * encoded line so that the line begins on a byte boundary.
+ */
+ public static final int CCITT_ENCODEDBYTEALIGN = 2;
+
+ /**
+ * A flag indicating whether end-of-line bit patterns are required to be
+ * present in the encoding.
+ */
+ public static final int CCITT_ENDOFLINE = 4;
+
+ /**
+ * A flag indicating whether the filter expects the encoded data to be
+ * terminated by an end-of-block pattern, overriding the Rows parameter. The
+ * use of this flag will set the key /EndOfBlock to false.
+ */
+ public static final int CCITT_ENDOFBLOCK = 8;
+
+ // methods
+
+ /**
+ * Processes the element by adding it (or the different parts) to an
+ * ElementListener
.
+ *
+ * @param listener
+ * an ElementListener
+ * @return true
if the element was processed successfully
+ */
+
+ public boolean process(ElementListener listener);
+
+ /**
+ * Gets the type of the text element.
+ *
+ * @return a type
+ */
+
+ public int type();
+
+ /**
+ * Gets all the chunks in this element.
+ *
+ * @return an ArrayList
+ */
+
+ public ArrayList getChunks();
+
+ /**
+ * Gets the content of the text element.
+ *
+ * @return a type
+ */
+
+ public String toString();
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/ElementListener.java pdftk-2.01/java/pdftk/com/lowagie/text/ElementListener.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/ElementListener.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/ElementListener.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,65 @@
+/*
+ * $Id: ElementListener.java,v 1.48 2004/12/14 11:52:46 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.util.EventListener;
+
+/**
+ * A class that implements ElementListener
will perform some
+ * actions when an Element
is added.
+ *
+ * @see DocListener
+ */
+
+public interface ElementListener extends EventListener {
+
+ // methods
+
+/**
+ * Signals that an Element
was added to the Document
.
+ *
+ * @param element a high level object
+ * @return true
if the element was added, false
if not.
+ * @throws DocumentException when a document isn't open yet, or has been closed
+ */
+
+ public boolean add(Element element) throws DocumentException;
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/ElementTags.java pdftk-2.01/java/pdftk/com/lowagie/text/ElementTags.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/ElementTags.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/ElementTags.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,451 @@
+/*
+ * $Id: ElementTags.java,v 1.84 2005/04/06 07:01:18 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright (c) 2001, 2002 Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+/**
+ * A class that contains all the possible tagnames and their attributes.
+ */
+
+public class ElementTags {
+
+/** the root tag. */
+ public static final String ITEXT = "itext";
+
+/** attribute of the root and annotation tag (also a special tag within a chapter or section) */
+ public static final String TITLE = "title";
+
+/** attribute of the root tag */
+ public static final String SUBJECT = "subject";
+
+/** attribute of the root tag */
+ public static final String KEYWORDS = "keywords";
+
+/** attribute of the root tag */
+ public static final String AUTHOR = "author";
+
+/** attribute of the root tag */
+ public static final String CREATIONDATE = "creationdate";
+
+/** attribute of the root tag */
+ public static final String PRODUCER = "producer";
+
+ // Chapters and Sections
+
+/** the chapter tag */
+ public static final String CHAPTER = "chapter";
+
+/** the section tag */
+ public static final String SECTION = "section";
+
+/** attribute of section/chapter tag */
+ public static final String NUMBERDEPTH = "numberdepth";
+
+/** attribute of section/chapter tag */
+ public static final String DEPTH = "depth";
+
+/** attribute of section/chapter tag */
+ public static final String NUMBER = "number";
+
+/** attribute of section/chapter tag */
+ public static final String INDENT = "indent";
+
+/** attribute of chapter/section/paragraph/table/cell tag */
+ public static final String LEFT = "left";
+
+/** attribute of chapter/section/paragraph/table/cell tag */
+ public static final String RIGHT = "right";
+
+ // Phrases, Anchors, Lists and Paragraphs
+
+/** the phrase tag */
+ public static final String PHRASE = "phrase";
+
+/** the anchor tag */
+ public static final String ANCHOR = "anchor";
+
+/** the list tag */
+ public static final String LIST = "list";
+
+/** the listitem tag */
+ public static final String LISTITEM = "listitem";
+
+/** the paragraph tag */
+ public static final String PARAGRAPH = "paragraph";
+
+/** attribute of phrase/paragraph/cell tag */
+ public static final String LEADING = "leading";
+
+/** attribute of paragraph/image/table tag */
+ public static final String ALIGN = "align";
+
+/** attribute of paragraph */
+ public static final String KEEPTOGETHER = "keeptogether";
+
+/** attribute of anchor tag */
+ public static final String NAME = "name";
+
+/** attribute of anchor tag */
+ public static final String REFERENCE = "reference";
+
+/** attribute of list tag */
+ public static final String LISTSYMBOL = "listsymbol";
+
+/** attribute of list tag */
+ public static final String NUMBERED = "numbered";
+
+/** attribute of the list tag */
+ public static final String LETTERED = "lettered";
+
+/** attribute of list tag */
+ public static final String FIRST = "first";
+
+/** attribute of list tag */
+ public static final String SYMBOLINDENT = "symbolindent";
+
+/** attribute of list tag */
+ public static final String INDENTATIONLEFT = "indentationleft";
+
+/** attribute of list tag */
+ public static final String INDENTATIONRIGHT = "indentationright";
+
+ // Chunks
+
+/** the chunk tag */
+ public static final String IGNORE = "ignore";
+
+/** the chunk tag */
+ public static final String ENTITY = "entity";
+
+/** the chunk tag */
+ public static final String ID = "id";
+
+/** the chunk tag */
+ public static final String CHUNK = "chunk";
+
+/** attribute of the chunk tag */
+ public static final String ENCODING = "encoding";
+
+/** attribute of the chunk tag */
+ public static final String EMBEDDED = "embedded";
+
+/** attribute of the chunk/table/cell tag */
+ public static final String COLOR = "color";
+
+/** attribute of the chunk/table/cell tag */
+ public static final String RED = "red";
+
+/** attribute of the chunk/table/cell tag */
+ public static final String GREEN = "green";
+
+/** attribute of the chunk/table/cell tag */
+ public static final String BLUE = "blue";
+
+/** attribute of the chunk tag */
+ public static final String SUBSUPSCRIPT = Chunk.SUBSUPSCRIPT.toLowerCase();
+
+/** attribute of the chunk tag */
+ public static final String LOCALGOTO = Chunk.LOCALGOTO.toLowerCase();
+
+/** attribute of the chunk tag */
+ public static final String REMOTEGOTO = Chunk.REMOTEGOTO.toLowerCase();
+
+/** attribute of the chunk tag */
+ public static final String LOCALDESTINATION = Chunk.LOCALDESTINATION.toLowerCase();
+
+/** attribute of the chunk tag */
+ public static final String GENERICTAG = Chunk.GENERICTAG.toLowerCase();
+
+ // tables/cells
+
+/** the table tag */
+ public static final String TABLE = "table";
+
+/** the cell tag */
+ public static final String ROW = "row";
+
+/** the cell tag */
+ public static final String CELL = "cell";
+
+/** attribute of the table tag */
+ public static final String COLUMNS = "columns";
+
+/** attribute of the table tag */
+ public static final String LASTHEADERROW = "lastHeaderRow";
+
+/** attribute of the table tag */
+ public static final String CELLPADDING = "cellpadding";
+
+/** attribute of the table tag */
+ public static final String CELLSPACING = "cellspacing";
+
+/** attribute of the table tag */
+ public static final String OFFSET = "offset";
+
+/** attribute of the table tag */
+ public static final String WIDTHS = "widths";
+
+/** attribute of the table tag */
+ public static final String TABLEFITSPAGE = "tablefitspage";
+
+/** attribute of the table tag */
+ public static final String CELLSFITPAGE = "cellsfitpage";
+
+/** attribute of the cell tag */
+ public static final String HORIZONTALALIGN = "horizontalalign";
+
+/** attribute of the cell tag */
+ public static final String VERTICALALIGN = "verticalalign";
+
+/** attribute of the cell tag */
+ public static final String COLSPAN = "colspan";
+
+/** attribute of the cell tag */
+ public static final String ROWSPAN = "rowspan";
+
+/** attribute of the cell tag */
+ public static final String HEADER = "header";
+
+/** attribute of the cell tag */
+ public static final String NOWRAP = "nowrap";
+
+/** attribute of the table/cell tag */
+ public static final String BORDERWIDTH = "borderwidth";
+
+/** attribute of the table/cell tag */
+ public static final String TOP = "top";
+
+/** attribute of the table/cell tag */
+ public static final String BOTTOM = "bottom";
+
+/** attribute of the table/cell tag */
+ public static final String WIDTH = "width";
+
+/** attribute of the table/cell tag */
+ public static final String BORDERCOLOR = "bordercolor";
+
+/** attribute of the table/cell tag */
+ public static final String BACKGROUNDCOLOR = "backgroundcolor";
+
+/** attribute of the table/cell tag */
+ public static final String BGRED = "bgred";
+
+/** attribute of the table/cell tag */
+ public static final String BGGREEN = "bggreen";
+
+/** attribute of the table/cell tag */
+ public static final String BGBLUE = "bgblue";
+
+/** attribute of the table/cell tag */
+ public static final String GRAYFILL = "grayfill";
+
+ // Misc
+
+/** the image tag */
+ public static final String IMAGE = "image";
+
+/** attribute of the image and annotation tag */
+ public static final String URL = "url";
+
+/** attribute of the image tag */
+ public static final String UNDERLYING = "underlying";
+
+/** attribute of the image tag */
+ public static final String TEXTWRAP = "textwrap";
+
+/** attribute of the image tag */
+ public static final String ALT = "alt";
+
+/** attribute of the image tag */
+ public static final String ABSOLUTEX = "absolutex";
+
+/** attribute of the image tag */
+ public static final String ABSOLUTEY = "absolutey";
+
+/** attribute of the image tag */
+ public static final String PLAINWIDTH = "plainwidth";
+
+/** attribute of the image tag */
+ public static final String PLAINHEIGHT = "plainheight";
+
+/** attribute of the image tag */
+ public static final String SCALEDWIDTH = "scaledwidth";
+
+/** attribute of the image tag */
+ public static final String SCALEDHEIGHT = "scaledheight";
+
+/** attribute of the image tag */
+ public static final String ROTATION = "rotation";
+
+/** the newpage tag */
+ public static final String NEWPAGE = "newpage";
+
+/** the newpage tag */
+ public static final String NEWLINE = "newline";
+
+/** the annotation tag */
+ public static final String ANNOTATION = "annotation";
+
+/** attribute of the annotation tag */
+ public static String FILE = "file";
+
+/** attribute of the annotation tag */
+ public static String DESTINATION = "destination";
+
+/** attribute of the annotation tag */
+ public static String PAGE = "page";
+
+/** attribute of the annotation tag */
+ public static String NAMED = "named";
+
+/** attribute of the annotation tag */
+ public static String APPLICATION = "application";
+
+/** attribute of the annotation tag */
+ public static String PARAMETERS = "parameters";
+
+/** attribute of the annotation tag */
+ public static String OPERATION = "operation";
+
+/** attribute of the annotation tag */
+ public static String DEFAULTDIR = "defaultdir";
+
+/** attribute of the annotation tag */
+ public static String LLX = "llx";
+
+/** attribute of the annotation tag */
+ public static String LLY = "lly";
+
+/** attribute of the annotation tag */
+ public static String URX = "urx";
+
+/** attribute of the annotation tag */
+ public static String URY = "ury";
+
+/** attribute of the annotation tag */
+ public static final String CONTENT = "content";
+
+ // alignment attribute values
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_LEFT = "Left";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_CENTER = "Center";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_RIGHT = "Right";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_JUSTIFIED = "Justify";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_JUSTIFIED_ALL = "JustifyAll";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_TOP = "Top";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_MIDDLE = "Middle";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_BOTTOM = "Bottom";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_BASELINE = "Baseline";
+
+/** the possible value of an alignment attribute */
+ public static final String DEFAULT = "Default";
+
+/** the possible value of an alignment attribute */
+ public static final String UNKNOWN = "unknown";
+
+/** the possible value of an alignment attribute */
+ public static final String FONT = "font";
+
+/** the possible value of an alignment attribute */
+ public static final String SIZE = "size";
+
+/** the possible value of an alignment attribute */
+ public static final String STYLE = "fontstyle";
+
+/** the possible value of a tag */
+ public static final String HORIZONTALRULE = "horizontalrule";
+
+ /** the possible value of a tag */
+ public static final String PAGE_SIZE = "pagesize";
+
+ /** the possible value of a tag */
+ public static final String ORIENTATION = "orientation";
+
+ // methods
+
+/**
+ * Translates the alignment value.
+ *
+ * @param alignment the alignment value
+ * @return the translated value
+ */
+
+ public static String getAlignment(int alignment) {
+ switch(alignment) {
+ case Element.ALIGN_LEFT:
+ return ALIGN_LEFT;
+ case Element.ALIGN_CENTER:
+ return ALIGN_CENTER;
+ case Element.ALIGN_RIGHT:
+ return ALIGN_RIGHT;
+ case Element.ALIGN_JUSTIFIED:
+ case Element.ALIGN_JUSTIFIED_ALL:
+ return ALIGN_JUSTIFIED;
+ case Element.ALIGN_TOP:
+ return ALIGN_TOP;
+ case Element.ALIGN_MIDDLE:
+ return ALIGN_MIDDLE;
+ case Element.ALIGN_BOTTOM:
+ return ALIGN_BOTTOM;
+ case Element.ALIGN_BASELINE:
+ return ALIGN_BASELINE;
+ default:
+ return DEFAULT;
+ }
+ }
+
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Entities.java pdftk-2.01/java/pdftk/com/lowagie/text/Entities.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Entities.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Entities.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,377 @@
+/*
+ * $Id: Entities.java,v 1.43 2004/12/14 11:52:46 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.util.HashMap;
+
+/**
+ * This class contains entities that can be used in an entity tag.
+ */
+
+public class Entities {
+
+ /** This is a map that contains all possible id values of the entity tag. */
+ public static final HashMap map;
+
+ static {
+ map = new HashMap();
+ map.put("169", new Integer(227));
+ map.put("172", new Integer(216));
+ map.put("174", new Integer(210));
+ map.put("177", new Integer(177));
+ map.put("215", new Integer(180));
+ map.put("247", new Integer(184));
+ map.put("8230", new Integer(188));
+ map.put("8242", new Integer(162));
+ map.put("8243", new Integer(178));
+ map.put("8260", new Integer(164));
+ map.put("8364", new Integer(240));
+ map.put("8465", new Integer(193));
+ map.put("8472", new Integer(195));
+ map.put("8476", new Integer(194));
+ map.put("8482", new Integer(212));
+ map.put("8501", new Integer(192));
+ map.put("8592", new Integer(172));
+ map.put("8593", new Integer(173));
+ map.put("8594", new Integer(174));
+ map.put("8595", new Integer(175));
+ map.put("8596", new Integer(171));
+ map.put("8629", new Integer(191));
+ map.put("8656", new Integer(220));
+ map.put("8657", new Integer(221));
+ map.put("8658", new Integer(222));
+ map.put("8659", new Integer(223));
+ map.put("8660", new Integer(219));
+ map.put("8704", new Integer(34));
+ map.put("8706", new Integer(182));
+ map.put("8707", new Integer(36));
+ map.put("8709", new Integer(198));
+ map.put("8711", new Integer(209));
+ map.put("8712", new Integer(206));
+ map.put("8713", new Integer(207));
+ map.put("8717", new Integer(39));
+ map.put("8719", new Integer(213));
+ map.put("8721", new Integer(229));
+ map.put("8722", new Integer(45));
+ map.put("8727", new Integer(42));
+ map.put("8729", new Integer(183));
+ map.put("8730", new Integer(214));
+ map.put("8733", new Integer(181));
+ map.put("8734", new Integer(165));
+ map.put("8736", new Integer(208));
+ map.put("8743", new Integer(217));
+ map.put("8744", new Integer(218));
+ map.put("8745", new Integer(199));
+ map.put("8746", new Integer(200));
+ map.put("8747", new Integer(242));
+ map.put("8756", new Integer(92));
+ map.put("8764", new Integer(126));
+ map.put("8773", new Integer(64));
+ map.put("8776", new Integer(187));
+ map.put("8800", new Integer(185));
+ map.put("8801", new Integer(186));
+ map.put("8804", new Integer(163));
+ map.put("8805", new Integer(179));
+ map.put("8834", new Integer(204));
+ map.put("8835", new Integer(201));
+ map.put("8836", new Integer(203));
+ map.put("8838", new Integer(205));
+ map.put("8839", new Integer(202));
+ map.put("8853", new Integer(197));
+ map.put("8855", new Integer(196));
+ map.put("8869", new Integer(94));
+ map.put("8901", new Integer(215));
+ map.put("8992", new Integer(243));
+ map.put("8993", new Integer(245));
+ map.put("9001", new Integer(225));
+ map.put("9002", new Integer(241));
+ map.put("913", new Integer(65));
+ map.put("914", new Integer(66));
+ map.put("915", new Integer(71));
+ map.put("916", new Integer(68));
+ map.put("917", new Integer(69));
+ map.put("918", new Integer(90));
+ map.put("919", new Integer(72));
+ map.put("920", new Integer(81));
+ map.put("921", new Integer(73));
+ map.put("922", new Integer(75));
+ map.put("923", new Integer(76));
+ map.put("924", new Integer(77));
+ map.put("925", new Integer(78));
+ map.put("926", new Integer(88));
+ map.put("927", new Integer(79));
+ map.put("928", new Integer(80));
+ map.put("929", new Integer(82));
+ map.put("931", new Integer(83));
+ map.put("932", new Integer(84));
+ map.put("933", new Integer(85));
+ map.put("934", new Integer(70));
+ map.put("935", new Integer(67));
+ map.put("936", new Integer(89));
+ map.put("937", new Integer(87));
+ map.put("945", new Integer(97));
+ map.put("946", new Integer(98));
+ map.put("947", new Integer(103));
+ map.put("948", new Integer(100));
+ map.put("949", new Integer(101));
+ map.put("950", new Integer(122));
+ map.put("951", new Integer(104));
+ map.put("952", new Integer(113));
+ map.put("953", new Integer(105));
+ map.put("954", new Integer(107));
+ map.put("955", new Integer(108));
+ map.put("956", new Integer(109));
+ map.put("957", new Integer(110));
+ map.put("958", new Integer(120));
+ map.put("959", new Integer(111));
+ map.put("960", new Integer(112));
+ map.put("961", new Integer(114));
+ map.put("962", new Integer(86));
+ map.put("963", new Integer(115));
+ map.put("964", new Integer(116));
+ map.put("965", new Integer(117));
+ map.put("966", new Integer(102));
+ map.put("967", new Integer(99));
+ map.put("9674", new Integer(224));
+ map.put("968", new Integer(121));
+ map.put("969", new Integer(119));
+ map.put("977", new Integer(74));
+ map.put("978", new Integer(161));
+ map.put("981", new Integer(106));
+ map.put("982", new Integer(118));
+ map.put("9824", new Integer(170));
+ map.put("9827", new Integer(167));
+ map.put("9829", new Integer(169));
+ map.put("9830", new Integer(168));
+ map.put("Alpha", new Integer(65));
+ map.put("Beta", new Integer(66));
+ map.put("Chi", new Integer(67));
+ map.put("Delta", new Integer(68));
+ map.put("Epsilon", new Integer(69));
+ map.put("Eta", new Integer(72));
+ map.put("Gamma", new Integer(71));
+ map.put("Iota", new Integer(73));
+ map.put("Kappa", new Integer(75));
+ map.put("Lambda", new Integer(76));
+ map.put("Mu", new Integer(77));
+ map.put("Nu", new Integer(78));
+ map.put("Omega", new Integer(87));
+ map.put("Omicron", new Integer(79));
+ map.put("Phi", new Integer(70));
+ map.put("Pi", new Integer(80));
+ map.put("Prime", new Integer(178));
+ map.put("Psi", new Integer(89));
+ map.put("Rho", new Integer(82));
+ map.put("Sigma", new Integer(83));
+ map.put("Tau", new Integer(84));
+ map.put("Theta", new Integer(81));
+ map.put("Upsilon", new Integer(85));
+ map.put("Xi", new Integer(88));
+ map.put("Zeta", new Integer(90));
+ map.put("alefsym", new Integer(192));
+ map.put("alpha", new Integer(97));
+ map.put("and", new Integer(217));
+ map.put("ang", new Integer(208));
+ map.put("asymp", new Integer(187));
+ map.put("beta", new Integer(98));
+ map.put("cap", new Integer(199));
+ map.put("chi", new Integer(99));
+ map.put("clubs", new Integer(167));
+ map.put("cong", new Integer(64));
+ map.put("copy", new Integer(211));
+ map.put("crarr", new Integer(191));
+ map.put("cup", new Integer(200));
+ map.put("dArr", new Integer(223));
+ map.put("darr", new Integer(175));
+ map.put("delta", new Integer(100));
+ map.put("diams", new Integer(168));
+ map.put("divide", new Integer(184));
+ map.put("empty", new Integer(198));
+ map.put("epsilon", new Integer(101));
+ map.put("equiv", new Integer(186));
+ map.put("eta", new Integer(104));
+ map.put("euro", new Integer(240));
+ map.put("exist", new Integer(36));
+ map.put("forall", new Integer(34));
+ map.put("frasl", new Integer(164));
+ map.put("gamma", new Integer(103));
+ map.put("ge", new Integer(179));
+ map.put("hArr", new Integer(219));
+ map.put("harr", new Integer(171));
+ map.put("hearts", new Integer(169));
+ map.put("hellip", new Integer(188));
+ map.put("horizontal arrow extender", new Integer(190));
+ map.put("image", new Integer(193));
+ map.put("infin", new Integer(165));
+ map.put("int", new Integer(242));
+ map.put("iota", new Integer(105));
+ map.put("isin", new Integer(206));
+ map.put("kappa", new Integer(107));
+ map.put("lArr", new Integer(220));
+ map.put("lambda", new Integer(108));
+ map.put("lang", new Integer(225));
+ map.put("large brace extender", new Integer(239));
+ map.put("large integral extender", new Integer(244));
+ map.put("large left brace (bottom)", new Integer(238));
+ map.put("large left brace (middle)", new Integer(237));
+ map.put("large left brace (top)", new Integer(236));
+ map.put("large left bracket (bottom)", new Integer(235));
+ map.put("large left bracket (extender)", new Integer(234));
+ map.put("large left bracket (top)", new Integer(233));
+ map.put("large left parenthesis (bottom)", new Integer(232));
+ map.put("large left parenthesis (extender)", new Integer(231));
+ map.put("large left parenthesis (top)", new Integer(230));
+ map.put("large right brace (bottom)", new Integer(254));
+ map.put("large right brace (middle)", new Integer(253));
+ map.put("large right brace (top)", new Integer(252));
+ map.put("large right bracket (bottom)", new Integer(251));
+ map.put("large right bracket (extender)", new Integer(250));
+ map.put("large right bracket (top)", new Integer(249));
+ map.put("large right parenthesis (bottom)", new Integer(248));
+ map.put("large right parenthesis (extender)", new Integer(247));
+ map.put("large right parenthesis (top)", new Integer(246));
+ map.put("larr", new Integer(172));
+ map.put("le", new Integer(163));
+ map.put("lowast", new Integer(42));
+ map.put("loz", new Integer(224));
+ map.put("minus", new Integer(45));
+ map.put("mu", new Integer(109));
+ map.put("nabla", new Integer(209));
+ map.put("ne", new Integer(185));
+ map.put("not", new Integer(216));
+ map.put("notin", new Integer(207));
+ map.put("nsub", new Integer(203));
+ map.put("nu", new Integer(110));
+ map.put("omega", new Integer(119));
+ map.put("omicron", new Integer(111));
+ map.put("oplus", new Integer(197));
+ map.put("or", new Integer(218));
+ map.put("otimes", new Integer(196));
+ map.put("part", new Integer(182));
+ map.put("perp", new Integer(94));
+ map.put("phi", new Integer(102));
+ map.put("pi", new Integer(112));
+ map.put("piv", new Integer(118));
+ map.put("plusmn", new Integer(177));
+ map.put("prime", new Integer(162));
+ map.put("prod", new Integer(213));
+ map.put("prop", new Integer(181));
+ map.put("psi", new Integer(121));
+ map.put("rArr", new Integer(222));
+ map.put("radic", new Integer(214));
+ map.put("radical extender", new Integer(96));
+ map.put("rang", new Integer(241));
+ map.put("rarr", new Integer(174));
+ map.put("real", new Integer(194));
+ map.put("reg", new Integer(210));
+ map.put("rho", new Integer(114));
+ map.put("sdot", new Integer(215));
+ map.put("sigma", new Integer(115));
+ map.put("sigmaf", new Integer(86));
+ map.put("sim", new Integer(126));
+ map.put("spades", new Integer(170));
+ map.put("sub", new Integer(204));
+ map.put("sube", new Integer(205));
+ map.put("sum", new Integer(229));
+ map.put("sup", new Integer(201));
+ map.put("supe", new Integer(202));
+ map.put("tau", new Integer(116));
+ map.put("there4", new Integer(92));
+ map.put("theta", new Integer(113));
+ map.put("thetasym", new Integer(74));
+ map.put("times", new Integer(180));
+ map.put("trade", new Integer(212));
+ map.put("uArr", new Integer(221));
+ map.put("uarr", new Integer(173));
+ map.put("upsih", new Integer(161));
+ map.put("upsilon", new Integer(117));
+ map.put("vertical arrow extender", new Integer(189));
+ map.put("weierp", new Integer(195));
+ map.put("xi", new Integer(120));
+ map.put("zeta", new Integer(122));
+ }
+
+ /**
+ * Gets a chunk with a symbol character.
+ * @param e a symbol value (see Entities class: alfa is greek alfa,...)
+ * @param font the font if the symbol isn't found (otherwise Font.SYMBIL)
+ * @return a Chunk
+ */
+ public static Chunk get(String e, Font font) {
+ int s = getCorrespondingSymbol(e);
+ if (s == -1) {
+ try {
+ return new Chunk(String.valueOf((char)Integer.parseInt(e)), font);
+ }
+ catch(Exception exception) {
+ return new Chunk(e, font);
+ }
+ }
+ Font symbol = new Font(Font.SYMBOL, font.size(), font.style(), font.color());
+ return new Chunk(String.valueOf((char)s), symbol);
+ }
+
+/**
+ * Looks for the corresponding symbol in the font Symbol.
+ *
+ * @param c the original ASCII-char
+ * @return the corresponding symbol in font Symbol
+ */
+
+ public static int getCorrespondingSymbol(String c) {
+ Integer integer = (Integer) map.get(c);
+ if (integer == null) {
+ return -1;
+ }
+ return integer.intValue();
+ }
+
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param tag the given tag
+ * @return true if the tag corresponds
+ */
+
+ public static boolean isTag(String tag) {
+ return ElementTags.ENTITY.equals(tag);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/ExceptionConverter.java pdftk-2.01/java/pdftk/com/lowagie/text/ExceptionConverter.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/ExceptionConverter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/ExceptionConverter.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,125 @@
+/*
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text;
+
+/**
+ * The ExceptionConverter changes a checked exception into an
+ * unchecked exception.
+ */
+public class ExceptionConverter extends RuntimeException {
+ /** we keep a handle to the wrapped exception */
+ private Exception ex;
+ /** prefix for the exception */
+ private String prefix;
+
+ /**
+ * Construct a RuntimeException based on another Exception
+ * @param ex the exception that has to be turned into a RuntimeException
+ */
+ public ExceptionConverter(Exception ex) {
+ this.ex = ex;
+ prefix = (ex instanceof RuntimeException) ? "" : "ExceptionConverter: ";
+ }
+
+ /**
+ * and allow the user of ExceptionConverter to get a handle to it.
+ * @return the original exception
+ */
+ public Exception getException() {
+ return ex;
+ }
+
+ /**
+ * We print the message of the checked exception
+ * @return message of the original exception
+ */
+ public String getMessage() {
+ return ex.getMessage();
+ }
+
+ /**
+ * and make sure we also produce a localized version
+ * @return localized version of the message
+ */
+ public String getLocalizedMessage() {
+ return ex.getLocalizedMessage();
+ }
+
+ /**
+ * The toString() is changed to be prefixed with ExceptionConverter
+ * @return Stringversion of the exception
+ */
+ public String toString() {
+ return prefix + ex;
+ }
+
+ /** we have to override this as well */
+ public void printStackTrace() {
+ printStackTrace(System.err);
+ }
+
+ /**
+ * here we prefix, with s.print(), not s.println(), the stack
+ * trace with "ExceptionConverter:"
+ * @param s
+ */
+ public void printStackTrace(java.io.PrintStream s) {
+ synchronized (s) {
+ s.print(prefix);
+ ex.printStackTrace(s);
+ }
+ }
+
+ /**
+ * Again, we prefix the stack trace with "ExceptionConverter:"
+ * @param s
+ */
+ public void printStackTrace(java.io.PrintWriter s) {
+ synchronized (s) {
+ s.print(prefix);
+ ex.printStackTrace(s);
+ }
+ }
+
+ /**
+ * requests to fill in the stack trace we will have to ignore.
+ * We can't throw an exception here, because this method
+ * is called by the constructor of Throwable
+ * @return a Throwable
+ */
+ public Throwable fillInStackTrace() {
+ return this;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Font.java pdftk-2.01/java/pdftk/com/lowagie/text/Font.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Font.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Font.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,796 @@
+/*
+ * $Id: Font.java,v 1.94 2005/10/05 14:16:04 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.awt.Color;
+
+import pdftk.com.lowagie.text.pdf.BaseFont;
+import pdftk.com.lowagie.text.markup.MarkupTags;
+
+/**
+ * Contains all the specifications of a font: fontfamily, size, style and color.
+ *
+ * Example:
+ *
+ *
+ *
+ * Paragraph p = new Paragraph("This is a paragraph", new
+ * Font(Font.HELVETICA, 18, Font.BOLDITALIC, new Color(0, 0, 255)) );
+ *
+ *
+ *
+ *
+ */
+
+public class Font implements Comparable {
+
+ // static membervariables for the different families
+
+ /** a possible value of a font family. */
+ public static final int COURIER = 0;
+
+ /** a possible value of a font family. */
+ public static final int HELVETICA = 1;
+
+ /** a possible value of a font family. */
+ public static final int TIMES_ROMAN = 2;
+
+ /** a possible value of a font family. */
+ public static final int SYMBOL = 3;
+
+ /** a possible value of a font family. */
+ public static final int ZAPFDINGBATS = 4;
+
+ // static membervariables for the different styles
+
+ /** this is a possible style. */
+ public static final int NORMAL = 0;
+
+ /** this is a possible style. */
+ public static final int BOLD = 1;
+
+ /** this is a possible style. */
+ public static final int ITALIC = 2;
+
+ /** this is a possible style. */
+ public static final int UNDERLINE = 4;
+
+ /** this is a possible style. */
+ public static final int STRIKETHRU = 8;
+
+ /** this is a possible style. */
+ public static final int BOLDITALIC = BOLD | ITALIC;
+
+ // static membervariables
+
+ /** the value of an undefined attribute. */
+ public static final int UNDEFINED = -1;
+
+ /** the value of the default size. */
+ public static final int DEFAULTSIZE = 12;
+
+ // membervariables
+
+ /** the value of the fontfamily. */
+ private int family = UNDEFINED;
+
+ /** the value of the fontsize. */
+ private float size = UNDEFINED;
+
+ /** the value of the style. */
+ private int style = UNDEFINED;
+
+ /** the value of the color. */
+ private Color color = null;
+
+ /** the external font */
+ private BaseFont baseFont = null;
+
+ // constructors
+
+ /**
+ * Copy constructor of a Font
+ *
+ * @param other
+ * the font that has to be copied
+ */
+ public Font(Font other) {
+ this.color = other.color;
+ this.family = other.family;
+ this.size = other.size;
+ this.style = other.style;
+ this.baseFont = other.baseFont;
+ }
+
+ /**
+ * Constructs a Font.
+ *
+ * @param family
+ * the family to which this font belongs
+ * @param size
+ * the size of this font
+ * @param style
+ * the style of this font
+ * @param color
+ * the Color
of this font.
+ */
+
+ public Font(int family, float size, int style, Color color) {
+ this.family = family;
+ this.size = size;
+ this.style = style;
+ this.color = color;
+ }
+
+ /**
+ * Constructs a Font.
+ *
+ * @param bf
+ * the external font
+ * @param size
+ * the size of this font
+ * @param style
+ * the style of this font
+ * @param color
+ * the Color
of this font.
+ */
+
+ public Font(BaseFont bf, float size, int style, Color color) {
+ this.baseFont = bf;
+ this.size = size;
+ this.style = style;
+ this.color = color;
+ }
+
+ /**
+ * Constructs a Font.
+ *
+ * @param bf
+ * the external font
+ * @param size
+ * the size of this font
+ * @param style
+ * the style of this font
+ */
+ public Font(BaseFont bf, float size, int style) {
+ this(bf, size, style, null);
+ }
+
+ /**
+ * Constructs a Font.
+ *
+ * @param bf
+ * the external font
+ * @param size
+ * the size of this font
+ */
+ public Font(BaseFont bf, float size) {
+ this(bf, size, UNDEFINED, null);
+ }
+
+ /**
+ * Constructs a Font.
+ *
+ * @param bf
+ * the external font
+ */
+ public Font(BaseFont bf) {
+ this(bf, UNDEFINED, UNDEFINED, null);
+ }
+
+ /**
+ * Constructs a Font.
+ *
+ * @param family
+ * the family to which this font belongs
+ * @param size
+ * the size of this font
+ * @param style
+ * the style of this font
+ */
+
+ public Font(int family, float size, int style) {
+ this(family, size, style, null);
+ }
+
+ /**
+ * Constructs a Font.
+ *
+ * @param family
+ * the family to which this font belongs
+ * @param size
+ * the size of this font
+ */
+
+ public Font(int family, float size) {
+ this(family, size, UNDEFINED, null);
+ }
+
+ /**
+ * Constructs a Font.
+ *
+ * @param family
+ * the family to which this font belongs
+ */
+
+ public Font(int family) {
+ this(family, UNDEFINED, UNDEFINED, null);
+ }
+
+ /**
+ * Constructs a Font.
+ */
+
+ public Font() {
+ this(UNDEFINED, UNDEFINED, UNDEFINED, null);
+ }
+
+ // implementation of the Comparable interface
+
+ /**
+ * Compares this Font
with another
+ *
+ * @param object
+ * the other Font
+ * @return a value
+ */
+
+ public int compareTo(Object object) {
+ if (object == null) {
+ return -1;
+ }
+ Font font;
+ try {
+ font = (Font) object;
+ if (baseFont != null && !baseFont.equals(font.getBaseFont())) {
+ return -2;
+ }
+ if (this.family != font.family()) {
+ return 1;
+ }
+ if (this.size != font.size()) {
+ return 2;
+ }
+ if (this.style != font.style()) {
+ return 3;
+ }
+ if (this.color == null) {
+ if (font.color == null) {
+ return 0;
+ }
+ return 4;
+ }
+ if (font.color == null) {
+ return 4;
+ }
+ if (this.color.equals(font.color())) {
+ return 0;
+ }
+ return 4;
+ } catch (ClassCastException cce) {
+ return -3;
+ }
+ }
+
+ // methods
+
+ /**
+ * Sets the family using a String
("Courier", "Helvetica",
+ * "Times New Roman", "Symbol" or "ZapfDingbats").
+ *
+ * @param family
+ * A String
representing a certain font-family.
+ */
+
+ public void setFamily(String family) {
+ this.family = getFamilyIndex(family);
+ }
+
+ /**
+ * Translates a String
-value of a certain family into the
+ * index that is used for this family in this class.
+ *
+ * @param family
+ * A String
representing a certain font-family
+ * @return the corresponding index
+ */
+
+ public static int getFamilyIndex(String family) {
+ if (family.equalsIgnoreCase(FontFactory.COURIER)) {
+ return COURIER;
+ }
+ if (family.equalsIgnoreCase(FontFactory.HELVETICA)) {
+ return HELVETICA;
+ }
+ if (family.equalsIgnoreCase(FontFactory.TIMES_ROMAN)) {
+ return TIMES_ROMAN;
+ }
+ if (family.equalsIgnoreCase(FontFactory.SYMBOL)) {
+ return SYMBOL;
+ }
+ if (family.equalsIgnoreCase(FontFactory.ZAPFDINGBATS)) {
+ return ZAPFDINGBATS;
+ }
+ return UNDEFINED;
+ }
+
+ /**
+ * Gets the familyname as a String.
+ *
+ * @return the familyname
+ */
+
+ public String getFamilyname() {
+ String tmp = "unknown";
+ switch (family()) {
+ case Font.COURIER:
+ return FontFactory.COURIER;
+ case Font.HELVETICA:
+ return FontFactory.HELVETICA;
+ case Font.TIMES_ROMAN:
+ return FontFactory.TIMES_ROMAN;
+ case Font.SYMBOL:
+ return FontFactory.SYMBOL;
+ case Font.ZAPFDINGBATS:
+ return FontFactory.ZAPFDINGBATS;
+ default:
+ if (baseFont != null) {
+ String[][] names = baseFont.getFamilyFontName();
+ for (int i = 0; i < names.length; i++) {
+ if ("0".equals(names[i][2])) {
+ return names[i][3];
+ }
+ if ("1033".equals(names[i][2])) {
+ tmp = names[i][3];
+ }
+ if ("".equals(names[i][2])) {
+ tmp = names[i][3];
+ }
+ }
+ }
+ }
+ return tmp;
+ }
+
+ /**
+ * Sets the size.
+ *
+ * @param size
+ * The new size of the font.
+ */
+
+ public void setSize(float size) {
+ this.size = size;
+ }
+
+ /**
+ * Sets the style using a String
containing one of more of
+ * the following values: normal, bold, italic, underline, strike.
+ *
+ * @param style
+ * A String
representing a certain style.
+ */
+
+ public void setStyle(String style) {
+ if (this.style == UNDEFINED)
+ this.style = NORMAL;
+ this.style |= getStyleValue(style);
+ }
+
+ /**
+ * Sets the style.
+ *
+ * @param style
+ * the style.
+ */
+
+ public void setStyle(int style) {
+ if (this.style == UNDEFINED)
+ this.style = NORMAL;
+ this.style |= style;
+ }
+
+ /**
+ * Translates a String
-value of a certain style into the
+ * index value is used for this style in this class.
+ *
+ * @param style
+ * A String
+ * @return the corresponding value
+ */
+
+ public static int getStyleValue(String style) {
+ int s = 0;
+ if (style.indexOf(MarkupTags.CSS_VALUE_NORMAL) != -1) {
+ s |= NORMAL;
+ }
+ if (style.indexOf(MarkupTags.CSS_VALUE_BOLD) != -1) {
+ s |= BOLD;
+ }
+ if (style.indexOf(MarkupTags.CSS_VALUE_ITALIC) != -1) {
+ s |= ITALIC;
+ }
+ if (style.indexOf(MarkupTags.CSS_VALUE_OBLIQUE) != -1) {
+ s |= ITALIC;
+ }
+ if (style.indexOf(MarkupTags.CSS_VALUE_UNDERLINE) != -1) {
+ s |= UNDERLINE;
+ }
+ if (style.indexOf(MarkupTags.CSS_VALUE_LINETHROUGH) != -1) {
+ s |= STRIKETHRU;
+ }
+ return s;
+ }
+
+ /**
+ * Sets the color.
+ *
+ * @param color
+ * the new color of the font
+ */
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ /**
+ * Sets the color.
+ *
+ * @param red
+ * the red-value of the new color
+ * @param green
+ * the green-value of the new color
+ * @param blue
+ * the blue-value of the new color
+ */
+
+ public void setColor(int red, int green, int blue) {
+ this.color = new Color(red, green, blue);
+ }
+
+ /**
+ * Gets the leading that can be used with this font.
+ *
+ * @param linespacing
+ * a certain linespacing
+ * @return the height of a line
+ */
+
+ public float leading(float linespacing) {
+ if (size == UNDEFINED) {
+ return linespacing * DEFAULTSIZE;
+ }
+ return linespacing * size;
+ }
+
+ /**
+ * Checks if the properties of this font are undefined or null.
+ *
+ * If so, the standard should be used.
+ *
+ * @return a boolean
+ */
+
+ public boolean isStandardFont() {
+ return (family == UNDEFINED && size == UNDEFINED && style == UNDEFINED
+ && color == null && baseFont == null);
+ }
+
+ /**
+ * Replaces the attributes that are equal to null with the
+ * attributes of a given font.
+ *
+ * @param font
+ * the font of a bigger element class
+ * @return a Font
+ */
+
+ public Font difference(Font font) {
+ // size
+ float dSize = font.size;
+ if (dSize == UNDEFINED) {
+ dSize = this.size;
+ }
+ // style
+ int dStyle = UNDEFINED;
+ int style1 = this.style;
+ int style2 = font.style();
+ if (style1 != UNDEFINED || style2 != UNDEFINED) {
+ if (style1 == UNDEFINED)
+ style1 = 0;
+ if (style2 == UNDEFINED)
+ style2 = 0;
+ dStyle = style1 | style2;
+ }
+ // color
+ Color dColor = font.color;
+ if (dColor == null) {
+ dColor = this.color;
+ }
+ // family
+ if (font.baseFont != null) {
+ return new Font(font.baseFont, dSize, dStyle, dColor);
+ }
+ if (font.family() != UNDEFINED) {
+ return new Font(font.family, dSize, dStyle, dColor);
+ }
+ if (this.baseFont != null) {
+ if (dStyle == style1) {
+ return new Font(this.baseFont, dSize, dStyle, dColor);
+ } else {
+ return FontFactory.getFont(this.getFamilyname(), dSize, dStyle,
+ dColor);
+ }
+ }
+ return new Font(this.family, dSize, dStyle, dColor);
+ }
+
+ // methods to retrieve the membervariables
+
+ /**
+ * Gets the family of this font.
+ *
+ * @return the value of the family
+ */
+
+ public int family() {
+ return family;
+ }
+
+ /**
+ * Gets the size of this font.
+ *
+ * @return a size
+ */
+
+ public float size() {
+ return size;
+ }
+
+ /**
+ * Gets the style of this font.
+ *
+ * @return a size
+ */
+
+ public int style() {
+ return style;
+ }
+
+ /**
+ * checks if this font is Bold.
+ *
+ * @return a boolean
+ */
+
+ public boolean isBold() {
+ if (style == UNDEFINED) {
+ return false;
+ }
+ return (style & BOLD) == BOLD;
+ }
+
+ /**
+ * checks if this font is Bold.
+ *
+ * @return a boolean
+ */
+
+ public boolean isItalic() {
+ if (style == UNDEFINED) {
+ return false;
+ }
+ return (style & ITALIC) == ITALIC;
+ }
+
+ /**
+ * checks if this font is underlined.
+ *
+ * @return a boolean
+ */
+
+ public boolean isUnderlined() {
+ if (style == UNDEFINED) {
+ return false;
+ }
+ return (style & UNDERLINE) == UNDERLINE;
+ }
+
+ /**
+ * checks if the style of this font is STRIKETHRU.
+ *
+ * @return a boolean
+ */
+
+ public boolean isStrikethru() {
+ if (style == UNDEFINED) {
+ return false;
+ }
+ return (style & STRIKETHRU) == STRIKETHRU;
+ }
+
+ /**
+ * Gets the color of this font.
+ *
+ * @return a color
+ */
+
+ public Color color() {
+ return color;
+ }
+
+ /**
+ * Gets the BaseFont
inside this object.
+ *
+ * @return the BaseFont
+ */
+
+ public BaseFont getBaseFont() {
+ return baseFont;
+ }
+
+ /**
+ * Gets the BaseFont
this class represents. For the built-in
+ * fonts a BaseFont
is calculated.
+ *
+ * @param specialEncoding
+ * true
to use the special encoding for Symbol and
+ * ZapfDingbats, false
to always use Cp1252
+ *
+ * @return the BaseFont
this class represents
+ */
+ public BaseFont getCalculatedBaseFont(boolean specialEncoding) {
+ if (baseFont != null)
+ return baseFont;
+ int style = this.style;
+ if (style == UNDEFINED) {
+ style = NORMAL;
+ }
+ String fontName = BaseFont.HELVETICA;
+ String encoding = BaseFont.WINANSI;
+ BaseFont cfont = null;
+ switch (family) {
+ case COURIER:
+ switch (style & BOLDITALIC) {
+ case BOLD:
+ fontName = BaseFont.COURIER_BOLD;
+ break;
+ case ITALIC:
+ fontName = BaseFont.COURIER_OBLIQUE;
+ break;
+ case BOLDITALIC:
+ fontName = BaseFont.COURIER_BOLDOBLIQUE;
+ break;
+ default:
+ //case NORMAL:
+ fontName = BaseFont.COURIER;
+ break;
+ }
+ break;
+ case TIMES_ROMAN:
+ switch (style & BOLDITALIC) {
+ case BOLD:
+ fontName = BaseFont.TIMES_BOLD;
+ break;
+ case ITALIC:
+ fontName = BaseFont.TIMES_ITALIC;
+ break;
+ case BOLDITALIC:
+ fontName = BaseFont.TIMES_BOLDITALIC;
+ break;
+ default:
+ case NORMAL:
+ fontName = BaseFont.TIMES_ROMAN;
+ break;
+ }
+ break;
+ case SYMBOL:
+ fontName = BaseFont.SYMBOL;
+ if (specialEncoding)
+ encoding = BaseFont.SYMBOL;
+ break;
+ case ZAPFDINGBATS:
+ fontName = BaseFont.ZAPFDINGBATS;
+ if (specialEncoding)
+ encoding = BaseFont.ZAPFDINGBATS;
+ break;
+ default:
+ case Font.HELVETICA:
+ switch (style & BOLDITALIC) {
+ case BOLD:
+ fontName = BaseFont.HELVETICA_BOLD;
+ break;
+ case ITALIC:
+ fontName = BaseFont.HELVETICA_OBLIQUE;
+ break;
+ case BOLDITALIC:
+ fontName = BaseFont.HELVETICA_BOLDOBLIQUE;
+ break;
+ default:
+ case NORMAL:
+ fontName = BaseFont.HELVETICA;
+ break;
+ }
+ break;
+ }
+ try {
+ cfont = BaseFont.createFont(fontName, encoding, false);
+ } catch (Exception ee) {
+ throw new ExceptionConverter(ee);
+ }
+ return cfont;
+ }
+
+ /**
+ * Gets the style that can be used with the calculated BaseFont
+ *
.
+ *
+ * @return the style that can be used with the calculated BaseFont
+ *
+ */
+ public int getCalculatedStyle() {
+ int style = this.style;
+ if (style == UNDEFINED) {
+ style = NORMAL;
+ }
+ if (baseFont != null)
+ return style;
+ if (family == SYMBOL || family == ZAPFDINGBATS)
+ return style;
+ else
+ return style & (~BOLDITALIC);
+ }
+
+ /**
+ * Gets the size that can be used with the calculated BaseFont
+ *
.
+ *
+ * @return the size that can be used with the calculated BaseFont
+ *
+ */
+ public float getCalculatedSize() {
+ float s = this.size;
+ if (s == UNDEFINED) {
+ s = DEFAULTSIZE;
+ }
+ return s;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/FontFactory.java pdftk-2.01/java/pdftk/com/lowagie/text/FontFactory.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/FontFactory.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/FontFactory.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,674 @@
+/*
+ * $Id: FontFactory.java,v 1.65 2005/05/03 13:03:47 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Enumeration;
+import java.io.File;
+import pdftk.com.lowagie.text.pdf.BaseFont;
+import pdftk.com.lowagie.text.markup.MarkupTags;
+import pdftk.com.lowagie.text.markup.MarkupParser;
+
+/**
+ * If you are using True Type fonts, you can declare the paths of the different ttf- and ttc-files
+ * to this static class first and then create fonts in your code using one of the static getFont-method
+ * without having to enter a path as parameter.
+ *
+ * @author Bruno Lowagie
+ */
+
+public class FontFactory extends java.lang.Object {
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String COURIER = BaseFont.COURIER;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String COURIER_BOLD = BaseFont.COURIER_BOLD;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String COURIER_OBLIQUE = BaseFont.COURIER_OBLIQUE;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String COURIER_BOLDOBLIQUE = BaseFont.COURIER_BOLDOBLIQUE;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String HELVETICA = BaseFont.HELVETICA;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String HELVETICA_BOLD = BaseFont.HELVETICA_BOLD;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String HELVETICA_OBLIQUE = BaseFont.HELVETICA_OBLIQUE;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String HELVETICA_BOLDOBLIQUE = BaseFont.HELVETICA_BOLDOBLIQUE;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String SYMBOL = BaseFont.SYMBOL;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String TIMES = "Times";
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String TIMES_ROMAN = BaseFont.TIMES_ROMAN;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String TIMES_BOLD = BaseFont.TIMES_BOLD;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String TIMES_ITALIC = BaseFont.TIMES_ITALIC;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String TIMES_BOLDITALIC = BaseFont.TIMES_BOLDITALIC;
+
+/** This is a possible value of a base 14 type 1 font */
+ public static final String ZAPFDINGBATS = BaseFont.ZAPFDINGBATS;
+
+/** This is a map of postscriptfontnames of True Type fonts and the path of their ttf- or ttc-file. */
+ private static Properties trueTypeFonts = new Properties();
+
+ private static String[] TTFamilyOrder = {
+ "3", "1", "1033",
+ "3", "0", "1033",
+ "1", "0", "0",
+ "0", "3", "0"
+ };
+
+ static {
+ trueTypeFonts.setProperty(COURIER.toLowerCase(), COURIER);
+ trueTypeFonts.setProperty(COURIER_BOLD.toLowerCase(), COURIER_BOLD);
+ trueTypeFonts.setProperty(COURIER_OBLIQUE.toLowerCase(), COURIER_OBLIQUE);
+ trueTypeFonts.setProperty(COURIER_BOLDOBLIQUE.toLowerCase(), COURIER_BOLDOBLIQUE);
+ trueTypeFonts.setProperty(HELVETICA.toLowerCase(), HELVETICA);
+ trueTypeFonts.setProperty(HELVETICA_BOLD.toLowerCase(), HELVETICA_BOLD);
+ trueTypeFonts.setProperty(HELVETICA_OBLIQUE.toLowerCase(), HELVETICA_OBLIQUE);
+ trueTypeFonts.setProperty(HELVETICA_BOLDOBLIQUE.toLowerCase(), HELVETICA_BOLDOBLIQUE);
+ trueTypeFonts.setProperty(SYMBOL.toLowerCase(), SYMBOL);
+ trueTypeFonts.setProperty(TIMES_ROMAN.toLowerCase(), TIMES_ROMAN);
+ trueTypeFonts.setProperty(TIMES_BOLD.toLowerCase(), TIMES_BOLD);
+ trueTypeFonts.setProperty(TIMES_ITALIC.toLowerCase(), TIMES_ITALIC);
+ trueTypeFonts.setProperty(TIMES_BOLDITALIC.toLowerCase(), TIMES_BOLDITALIC);
+ trueTypeFonts.setProperty(ZAPFDINGBATS.toLowerCase(), ZAPFDINGBATS);
+ }
+
+/** This is a map of fontfamilies. */
+ private static Hashtable fontFamilies = new Hashtable();
+
+ static {
+ ArrayList tmp;
+ tmp = new ArrayList();
+ tmp.add(COURIER);
+ tmp.add(COURIER_BOLD);
+ tmp.add(COURIER_OBLIQUE);
+ tmp.add(COURIER_BOLDOBLIQUE);
+ fontFamilies.put(COURIER.toLowerCase(), tmp);
+ tmp = new ArrayList();
+ tmp.add(HELVETICA);
+ tmp.add(HELVETICA_BOLD);
+ tmp.add(HELVETICA_OBLIQUE);
+ tmp.add(HELVETICA_BOLDOBLIQUE);
+ fontFamilies.put(HELVETICA.toLowerCase(), tmp);
+ tmp = new ArrayList();
+ tmp.add(SYMBOL);
+ fontFamilies.put(SYMBOL.toLowerCase(), tmp);
+ tmp = new ArrayList();
+ tmp.add(TIMES_ROMAN);
+ tmp.add(TIMES_BOLD);
+ tmp.add(TIMES_ITALIC);
+ tmp.add(TIMES_BOLDITALIC);
+ fontFamilies.put(TIMES.toLowerCase(), tmp);
+ fontFamilies.put(TIMES_ROMAN.toLowerCase(), tmp);
+ tmp = new ArrayList();
+ tmp.add(ZAPFDINGBATS);
+ fontFamilies.put(ZAPFDINGBATS.toLowerCase(), tmp);
+ }
+
+
+/** This is the default encoding to use. */
+ public static String defaultEncoding = BaseFont.WINANSI;
+
+/** This is the default value of the embedded variable. */
+ public static boolean defaultEmbedding = BaseFont.NOT_EMBEDDED;
+
+/** Creates new FontFactory */
+ private FontFactory() {
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param fontname the name of the font
+ * @param encoding the encoding of the font
+ * @param embedded true if the font is to be embedded in the PDF
+ * @param size the size of this font
+ * @param style the style of this font
+ * @param color the Color
of this font.
+ * @return the Font constructed based on the parameters
+ */
+
+ public static Font getFont(String fontname, String encoding, boolean embedded, float size, int style, Color color) {
+ if (fontname == null) return new Font(Font.UNDEFINED, size, style, color);
+ String lowercasefontname = fontname.toLowerCase();
+ ArrayList tmp = (ArrayList) fontFamilies.get(lowercasefontname);
+ if (tmp != null) {
+ // some bugs were fixed here by Daniel Marczisovszky
+ int s = style == Font.UNDEFINED ? Font.NORMAL : style;
+ int fs = Font.NORMAL;
+ boolean found = false;
+ for (Iterator i = tmp.iterator(); i.hasNext(); ) {
+ String f = (String) i.next();
+ String lcf = f.toLowerCase();
+ fs = Font.NORMAL;
+ if (lcf.toLowerCase().indexOf("bold") != -1) fs |= Font.BOLD;
+ if (lcf.toLowerCase().indexOf("italic") != -1 || lcf.toLowerCase().indexOf("oblique") != -1) fs |= Font.ITALIC;
+ if ((s & Font.BOLDITALIC) == fs) {
+ fontname = f;
+ found = true;
+ break;
+ }
+ }
+ if (style != Font.UNDEFINED && found) {
+ style &= ~fs;
+ }
+ }
+ BaseFont basefont = null;
+ try {
+ try {
+ // the font is a type 1 font or CJK font
+ basefont = BaseFont.createFont(fontname, encoding, embedded);
+ }
+ catch(DocumentException de) {
+ // the font is a true type font or an unknown font
+ fontname = trueTypeFonts.getProperty(fontname.toLowerCase());
+ // the font is not registered as truetype font
+ if (fontname == null) return new Font(Font.UNDEFINED, size, style, color);
+ // the font is registered as truetype font
+ basefont = BaseFont.createFont(fontname, encoding, embedded);
+ }
+ }
+ catch(DocumentException de) {
+ // this shouldn't happen
+ throw new ExceptionConverter(de);
+ }
+ catch(IOException ioe) {
+ // the font is registered as a true type font, but the path was wrong
+ return new Font(Font.UNDEFINED, size, style, color);
+ }
+ catch(NullPointerException npe) {
+ // null was entered as fontname and/or encoding
+ return new Font(Font.UNDEFINED, size, style, color);
+ }
+ return new Font(basefont, size, style, color);
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param attributes the attributes of a Font
object.
+ * @return the Font constructed based on the attributes
+ */
+
+ public static Font getFont(Properties attributes) {
+ String fontname = null;
+ String encoding = defaultEncoding;
+ boolean embedded = defaultEmbedding;
+ float size = Font.UNDEFINED;
+ int style = Font.NORMAL;
+ Color color = null;
+ String value = (String) attributes.remove(MarkupTags.HTML_ATTR_STYLE);
+ if (value != null && value.length() > 0) {
+ Properties styleAttributes = MarkupParser.parseAttributes(value);
+ if (styleAttributes.size() == 0) {
+ attributes.put(MarkupTags.HTML_ATTR_STYLE, value);
+ }
+ else {
+ fontname = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTFAMILY);
+ if (fontname != null) {
+ String tmp;
+ while (fontname.indexOf(",") != -1) {
+ tmp = fontname.substring(0, fontname.indexOf(","));
+ if (isRegistered(tmp)) {
+ fontname = tmp;
+ }
+ else {
+ fontname = fontname.substring(fontname.indexOf(",") + 1);
+ }
+ }
+ }
+ if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTSIZE)) != null) {
+ size = MarkupParser.parseLength(value);
+ }
+ if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTWEIGHT)) != null) {
+ style |= Font.getStyleValue(value);
+ }
+ if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_FONTSTYLE)) != null) {
+ style |= Font.getStyleValue(value);
+ }
+ if ((value = (String)styleAttributes.remove(MarkupTags.CSS_KEY_COLOR)) != null) {
+ color = MarkupParser.decodeColor(value);
+ }
+ attributes.putAll(styleAttributes);
+ for (Enumeration e = styleAttributes.keys(); e.hasMoreElements();) {
+ Object o = e.nextElement();
+ attributes.put(o, styleAttributes.get(o));
+ }
+ }
+ }
+ if ((value = (String)attributes.remove(ElementTags.ENCODING)) != null) {
+ encoding = value;
+ }
+ if ("true".equals(attributes.remove(ElementTags.EMBEDDED))) {
+ embedded = true;
+ }
+ if ((value = (String)attributes.remove(ElementTags.FONT)) != null) {
+ fontname = value;
+ }
+ if ((value = (String)attributes.remove(ElementTags.SIZE)) != null) {
+ size = Float.valueOf(value + "f").floatValue();
+ }
+ if ((value = (String)attributes.remove(MarkupTags.HTML_ATTR_STYLE)) != null) {
+ style |= Font.getStyleValue(value);
+ }
+ if ((value = (String)attributes.remove(ElementTags.STYLE)) != null) {
+ style |= Font.getStyleValue(value);
+ }
+ String r = (String)attributes.remove(ElementTags.RED);
+ String g = (String)attributes.remove(ElementTags.GREEN);
+ String b = (String)attributes.remove(ElementTags.BLUE);
+ if (r != null || g != null || b != null) {
+ int red = 0;
+ int green = 0;
+ int blue = 0;
+ if (r != null) red = Integer.parseInt(r);
+ if (g != null) green = Integer.parseInt(g);
+ if (b != null) blue = Integer.parseInt(b);
+ color = new Color(red, green, blue);
+ }
+ else if ((value = (String)attributes.remove(ElementTags.COLOR)) != null) {
+ color = MarkupParser.decodeColor(value);
+ }
+ if (fontname == null) {
+ return getFont(null, encoding, embedded, size, style, color);
+ }
+ return getFont(fontname, encoding, embedded, size, style, color);
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param fontname the name of the font
+ * @param encoding the encoding of the font
+ * @param embedded true if the font is to be embedded in the PDF
+ * @param size the size of this font
+ * @param style the style of this font
+ * @return the Font constructed based on the parameters
+ */
+
+ public static Font getFont(String fontname, String encoding, boolean embedded, float size, int style) {
+ return getFont(fontname, encoding, embedded, size, style, null);
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param fontname the name of the font
+ * @param encoding the encoding of the font
+ * @param embedded true if the font is to be embedded in the PDF
+ * @param size the size of this font
+ * @return the Font constructed based on the parameters
+ */
+
+ public static Font getFont(String fontname, String encoding, boolean embedded, float size) {
+ return getFont(fontname, encoding, embedded, size, Font.UNDEFINED, null);
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param fontname the name of the font
+ * @param encoding the encoding of the font
+ * @param embedded true if the font is to be embedded in the PDF
+ * @return the Font constructed based on the parameters
+ */
+
+ public static Font getFont(String fontname, String encoding, boolean embedded) {
+ return getFont(fontname, encoding, embedded, Font.UNDEFINED, Font.UNDEFINED, null);
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param fontname the name of the font
+ * @param encoding the encoding of the font
+ * @param size the size of this font
+ * @param style the style of this font
+ * @param color the Color
of this font.
+ * @return the Font constructed based on the parameters
+ */
+
+ public static Font getFont(String fontname, String encoding, float size, int style, Color color) {
+ return getFont(fontname, encoding, defaultEmbedding, size, style, color);
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param fontname the name of the font
+ * @param encoding the encoding of the font
+ * @param size the size of this font
+ * @param style the style of this font
+ * @return the Font constructed based on the parameters
+ */
+
+ public static Font getFont(String fontname, String encoding, float size, int style) {
+ return getFont(fontname, encoding, defaultEmbedding, size, style, null);
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param fontname the name of the font
+ * @param encoding the encoding of the font
+ * @param size the size of this font
+ * @return the Font constructed based on the parameters
+ */
+
+ public static Font getFont(String fontname, String encoding, float size) {
+ return getFont(fontname, encoding, defaultEmbedding, size, Font.UNDEFINED, null);
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param fontname the name of the font
+ * @param encoding the encoding of the font
+ * @return the Font constructed based on the parameters
+ */
+
+ public static Font getFont(String fontname, String encoding) {
+ return getFont(fontname, encoding, defaultEmbedding, Font.UNDEFINED, Font.UNDEFINED, null);
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param fontname the name of the font
+ * @param size the size of this font
+ * @param style the style of this font
+ * @param color the Color
of this font.
+ * @return the Font constructed based on the parameters
+ */
+
+ public static Font getFont(String fontname, float size, int style, Color color) {
+ return getFont(fontname, defaultEncoding, defaultEmbedding, size, style, color);
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param fontname the name of the font
+ * @param size the size of this font
+ * @param style the style of this font
+ * @return the Font constructed based on the parameters
+ */
+
+ public static Font getFont(String fontname, float size, int style) {
+ return getFont(fontname, defaultEncoding, defaultEmbedding, size, style, null);
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param fontname the name of the font
+ * @param size the size of this font
+ * @return the Font constructed based on the parameters
+ */
+
+ public static Font getFont(String fontname, float size) {
+ return getFont(fontname, defaultEncoding, defaultEmbedding, size, Font.UNDEFINED, null);
+ }
+
+/**
+ * Constructs a Font
-object.
+ *
+ * @param fontname the name of the font
+ * @return the Font constructed based on the parameters
+ */
+
+ public static Font getFont(String fontname) {
+ return getFont(fontname, defaultEncoding, defaultEmbedding, Font.UNDEFINED, Font.UNDEFINED, null);
+ }
+
+/**
+ * Register a ttf- or a ttc-file.
+ *
+ * @param path the path to a ttf- or ttc-file
+ */
+
+ public static void register(String path) {
+ register(path, null);
+ }
+
+/**
+ * Register a font file and use an alias for the font contained in it.
+ *
+ * @param path the path to a font file
+ * @param alias the alias you want to use for the font
+ */
+
+ public static void register(String path, String alias) {
+ try {
+ if (path.toLowerCase().endsWith(".ttf") || path.toLowerCase().endsWith(".otf") || path.toLowerCase().indexOf(".ttc,") > 0) {
+ Object allNames[] = BaseFont.getAllFontNames(path, BaseFont.WINANSI, null);
+ trueTypeFonts.setProperty(((String)allNames[0]).toLowerCase(), path);
+ if (alias != null) {
+ trueTypeFonts.setProperty(alias, path);
+ }
+ // register all the font names with all the locales
+ String[][] names = (String[][])allNames[2]; //full name
+ for (int i = 0; i < names.length; i++) {
+ trueTypeFonts.setProperty(names[i][3].toLowerCase(), path);
+ }
+ String fullName = null;
+ String familyName = null;
+ names = (String[][])allNames[1]; //family name
+ for (int k = 0; k < TTFamilyOrder.length; k += 3) {
+ for (int i = 0; i < names.length; i++) {
+ if (TTFamilyOrder[k].equals(names[i][0]) && TTFamilyOrder[k + 1].equals(names[i][1]) && TTFamilyOrder[k + 2].equals(names[i][2])) {
+ familyName = names[i][3].toLowerCase();
+ k = TTFamilyOrder.length;
+ break;
+ }
+ }
+ }
+ if (familyName != null) {
+ String lastName = "";
+ names = (String[][])allNames[2]; //full name
+ for (int i = 0; i < names.length; i++) {
+ for (int k = 0; k < TTFamilyOrder.length; k += 3) {
+ if (TTFamilyOrder[k].equals(names[i][0]) && TTFamilyOrder[k + 1].equals(names[i][1]) && TTFamilyOrder[k + 2].equals(names[i][2])) {
+ fullName = names[i][3];
+ if (fullName.equals(lastName))
+ continue;
+ lastName = fullName;
+ ArrayList tmp = (ArrayList) fontFamilies.get(familyName);
+ if (tmp == null) {
+ tmp = new ArrayList();
+ tmp.add(fullName);
+ fontFamilies.put(familyName, tmp);
+ }
+ else {
+ int fullNameLength = fullName.length();
+ boolean inserted = false;
+ for (int j = 0; j < tmp.size(); ++j) {
+ if (((String)tmp.get(j)).length() >= fullNameLength) {
+ tmp.add(j, fullName);
+ inserted = true;
+ break;
+ }
+ }
+ if (!inserted)
+ tmp.add(fullName);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if (path.toLowerCase().endsWith(".ttc")) {
+ if (alias != null)
+ System.err.println("class FontFactory: You can't define an alias for a true type collection.");
+ String[] names = BaseFont.enumerateTTCNames(path);
+ for (int i = 0; i < names.length; i++) {
+ register(path + "," + i);
+ }
+ }
+ else if (path.toLowerCase().endsWith(".afm")) {
+ BaseFont bf = BaseFont.createFont(path, BaseFont.CP1252, false);
+ trueTypeFonts.setProperty(bf.getPostscriptFontName().toLowerCase(), path);
+ trueTypeFonts.setProperty((bf.getFullFontName()[0][3]).toLowerCase(), path);
+ }
+ }
+ catch(DocumentException de) {
+ // this shouldn't happen
+ throw new ExceptionConverter(de);
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ }
+
+ /** Register all the fonts in a directory.
+ * @param dir the directory
+ * @return the number of fonts registered
+ */
+ public static int registerDirectory(String dir) {
+ int count = 0;
+ try {
+ File file = new File(dir);
+ if (!file.exists() || !file.isDirectory())
+ return 0;
+ String files[] = file.list();
+ if (files == null)
+ return 0;
+ for (int k = 0; k < files.length; ++k) {
+ try {
+ file = new File(dir, files[k]);
+ String name = file.getPath().toLowerCase();
+ if (name.endsWith(".ttf") || name.endsWith(".otf") || name.endsWith(".afm") || name.endsWith(".ttc")) {
+ register(file.getPath(), null);
+ ++count;
+ }
+ }
+ catch (Exception e) {
+ //empty on purpose
+ }
+ }
+ }
+ catch (Exception e) {
+ //empty on purpose
+ }
+ return count;
+ }
+
+ /** Register fonts in some probable directories. It usually works in Windows,
+ * Linux and Solaris.
+ * @return the number of fonts registered
+ */
+ public static int registerDirectories() {
+ int count = 0;
+ count += registerDirectory("c:/windows/fonts");
+ count += registerDirectory("c:/winnt/fonts");
+ count += registerDirectory("d:/windows/fonts");
+ count += registerDirectory("d:/winnt/fonts");
+ count += registerDirectory("/usr/X/lib/X11/fonts/TrueType");
+ count += registerDirectory("/usr/openwin/lib/X11/fonts/TrueType");
+ count += registerDirectory("/usr/share/fonts/default/TrueType");
+ count += registerDirectory("/usr/X11R6/lib/X11/fonts/ttf");
+ return count;
+ }
+
+/**
+ * Gets a set of registered fontnames.
+ * @return a set of registered fonts
+ */
+
+ public static Set getRegisteredFonts() {
+ return Chunk.getKeySet(trueTypeFonts);
+ }
+
+/**
+ * Gets a set of registered fontnames.
+ * @return a set of registered font families
+ */
+
+ public static Set getRegisteredFamilies() {
+ return Chunk.getKeySet(fontFamilies);
+ }
+
+/**
+ * Gets a set of registered fontnames.
+ * @param fontname of a font that may or may not be registered
+ * @return true if a given font is registered
+ */
+
+ public static boolean contains(String fontname) {
+ return trueTypeFonts.containsKey(fontname.toLowerCase());
+ }
+
+/**
+ * Checks if a certain font is registered.
+ *
+ * @param fontname the name of the font that has to be checked.
+ * @return true if the font is found
+ */
+
+ public static boolean isRegistered(String fontname) {
+ return trueTypeFonts.containsKey(fontname.toLowerCase());
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Greek.java pdftk-2.01/java/pdftk/com/lowagie/text/Greek.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Greek.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Greek.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,200 @@
+/*
+ * $Id: Greek.java,v 1.29 2002/06/20 13:30:24 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+/**
+ * This class contains the symbols that correspond with Greek letters.
+ *
+ * When you construct a Phrase
(or a derived object) using a String
,
+ * this String
can contain Greek Symbols. These are characters with an int value
+ * between 913 and 937 (except 930) and between 945 and 969. With this class the value of the
+ * corresponding character of the Font Symbol, can be retrieved.
+ *
+ * @see Phrase
+ *
+ * @author Bruno Lowagie
+ * @author Evelyne De Cordier
+ */
+
+public class Greek {
+
+/**
+ * Returns the first occurrence of a Greek symbol in a String
.
+ *
+ * @param string a String
+ * @return an index of -1 if no Greek symbol was found
+ */
+
+ public static int index(String string) {
+ int length = string.length();
+ for (int i = 0; i < length; i++) {
+ if (getCorrespondingSymbol(string.charAt(i)) != ' ') {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Gets a chunk with a symbol character.
+ */
+ public static Chunk get(char c, Font font) {
+ char greek = Greek.getCorrespondingSymbol(c);
+ if (greek == ' ') {
+ return new Chunk(String.valueOf(c), font);
+ }
+ Font symbol = new Font(Font.SYMBOL, font.size(), font.style(), font.color());
+ String s = String.valueOf(greek);
+ return new Chunk(s, symbol);
+ }
+
+/**
+ * Looks for the corresponding symbol in the font Symbol.
+ *
+ * @param c the original ASCII-char
+ * @return the corresponding symbol in font Symbol
+ */
+
+ public static char getCorrespondingSymbol(char c) {
+ switch(c) {
+ case 913:
+ return 'A'; // ALFA
+ case 914:
+ return 'B'; // BETA
+ case 915:
+ return 'G'; // GAMMA
+ case 916:
+ return 'D'; // DELTA
+ case 917:
+ return 'E'; // EPSILON
+ case 918:
+ return 'Z'; // ZETA
+ case 919:
+ return 'H'; // ETA
+ case 920:
+ return 'Q'; // THETA
+ case 921:
+ return 'I'; // IOTA
+ case 922:
+ return 'K'; // KAPPA
+ case 923:
+ return 'L'; // LAMBDA
+ case 924:
+ return 'M'; // MU
+ case 925:
+ return 'N'; // NU
+ case 926:
+ return 'X'; // XI
+ case 927:
+ return 'O'; // OMICRON
+ case 928:
+ return 'P'; // PI
+ case 929:
+ return 'R'; // RHO
+ case 931:
+ return 'S'; // SIGMA
+ case 932:
+ return 'T'; // TAU
+ case 933:
+ return 'U'; // UPSILON
+ case 934:
+ return 'J'; // PHI
+ case 935:
+ return 'C'; // CHI
+ case 936:
+ return 'Y'; // PSI
+ case 937:
+ return 'W'; // OMEGA
+ case 945:
+ return 'a'; // alfa
+ case 946:
+ return 'b'; // beta
+ case 947:
+ return 'g'; // gamma
+ case 948:
+ return 'd'; // delta
+ case 949:
+ return 'e'; // epsilon
+ case 950:
+ return 'z'; // zeta
+ case 951:
+ return 'h'; // eta
+ case 952:
+ return 'q'; // theta
+ case 953:
+ return 'i'; // iota
+ case 954:
+ return 'k'; // kappa
+ case 955:
+ return 'l'; // lambda
+ case 956:
+ return 'm'; // mu
+ case 957:
+ return 'n'; // nu
+ case 958:
+ return 'x'; // xi
+ case 959:
+ return 'o'; // omicron
+ case 960:
+ return 'p'; // pi
+ case 961:
+ return 'r'; // rho
+ case 962:
+ return 's'; // sigma
+ case 963:
+ return 's'; // sigma
+ case 964:
+ return 't'; // tau
+ case 965:
+ return 'u'; // upsilon
+ case 966:
+ return 'j'; // phi
+ case 967:
+ return 'c'; // chi
+ case 968:
+ return 'y'; // psi
+ case 969:
+ return 'w'; // omega
+ default:
+ return ' ';
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Header.java pdftk-2.01/java/pdftk/com/lowagie/text/Header.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Header.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Header.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,88 @@
+/*
+ * $Id: Header.java,v 1.29 2002/07/09 10:41:33 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+/**
+ * This is an Element
that contains
+ * some userdefined meta information about the document.
+ *
+ * Example:
+ *
+ * Header header = new Header("inspired by", "William Shakespeare");
+ *
+ *
+ * @see Element
+ * @see Meta
+ */
+
+public class Header extends Meta implements Element {
+
+ // membervariables
+
+/** This is the content of this chunk of text. */
+ private StringBuffer name;
+
+ // constructors
+
+/**
+ * Constructs a Meta
.
+ *
+ * @param name the name of the meta-information
+ * @param content the content
+ */
+
+ public Header(String name, String content) {
+ super(Element.HEADER, content);
+ this.name = new StringBuffer(name);
+ }
+
+ // methods to retrieve information
+
+/**
+ * Returns the name of the meta information.
+ *
+ * @return a String
+ */
+
+ public String name() {
+ return name.toString();
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/List.java pdftk-2.01/java/pdftk/com/lowagie/text/List.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/List.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/List.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,548 @@
+/*
+ * $Id: List.java,v 1.74 2005/04/13 09:17:14 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * A List
contains several ListItem
s.
+ *
+ * Example 1:
+ *
+ * List list = new List(true, 20);
+ * list.add(new ListItem("First line"));
+ * list.add(new ListItem("The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?"));
+ * list.add(new ListItem("Third line"));
+ *
+ *
+ * The result of this code looks like this:
+ *
+ *
+ * First line
+ *
+ *
+ * The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?
+ *
+ *
+ * Third line
+ *
+ *
+ *
+ * Example 2:
+ *
+ * List overview = new List(false, 10);
+ * overview.add(new ListItem("This is an item"));
+ * overview.add("This is another item");
+ *
+ *
+ * The result of this code looks like this:
+ *
+ *
+ * This is an item
+ *
+ *
+ * This is another item
+ *
+ *
+ *
+ * @see Element
+ * @see ListItem
+ */
+
+public class List implements TextElementArray, MarkupAttributes {
+
+ // membervariables
+ /** a possible value for the numbered parameter */
+ public static final boolean ORDERED = true;
+ /** a possible value for the numbered parameter */
+ public static final boolean UNORDERED = false;
+ /** a possible value for the lettered parameter */
+ public static final boolean NUMBERICAL = false;
+ /** a possible value for the lettered parameter */
+ public static final boolean ALPHABETICAL = true;
+
+
+/** This is the ArrayList
containing the different ListItem
s. */
+ protected ArrayList list = new ArrayList();
+
+/** This variable indicates if the list has to be numbered. */
+ protected boolean numbered;
+ protected boolean lettered;
+
+/** This variable indicates the first number of a numbered list. */
+ protected int first = 1;
+ protected char firstCh = 'A';
+ protected char lastCh = 'Z';
+
+/** This is the listsymbol of a list that is not numbered. */
+ protected Chunk symbol = new Chunk("-");
+
+/** The indentation of this list on the left side. */
+ protected float indentationLeft = 0;
+
+/** The indentation of this list on the right side. */
+ protected float indentationRight = 0;
+
+/** The indentation of the listitems. */
+ protected float symbolIndent;
+
+/** Contains extra markupAttributes */
+ protected Properties markupAttributes;
+
+ // constructors
+
+/**
+ * Constructs a List
.
+ *
+ * Remark: the parameter symbolIndent is important for instance when
+ * generating PDF-documents; it indicates the indentation of the listsymbol.
+ * It is not important for HTML-documents.
+ *
+ * @param numbered a boolean
+ * @param symbolIndent the indentation that has to be used for the listsymbol
+ */
+
+ public List(boolean numbered, float symbolIndent) {
+ this.numbered = numbered;
+ this.lettered = false;
+ this.symbolIndent = symbolIndent;
+ }
+
+ /**
+ * Creates a list
+ * @param numbered has the list to be numbered?
+ * @param lettered has the list to be 'numbered' with letters
+ * @param symbolIndent the indentation of the symbol
+ */
+ public List(boolean numbered, boolean lettered, float symbolIndent ) {
+ this.numbered = numbered;
+ this.lettered = lettered;
+ this.symbolIndent = symbolIndent;
+ }
+
+ /**
+ * Returns a List
that has been constructed taking in account
+ * the value of some attributes .
+ *
+ * @param attributes Some attributes
+ */
+
+ public List(Properties attributes) {
+ String value= (String)attributes.remove(ElementTags.LISTSYMBOL);
+ if (value == null) {
+ value = "-";
+ }
+ symbol = new Chunk(value, FontFactory.getFont(attributes));
+
+ this.numbered = false;
+ if ((value = (String)attributes.remove(ElementTags.NUMBERED)) != null) {
+ this.numbered = new Boolean(value).booleanValue();
+ if ( this.lettered && this.numbered )
+ this.lettered = false;
+ }
+ if ((value = (String)attributes.remove(ElementTags.LETTERED)) != null) {
+ this.lettered = new Boolean(value).booleanValue();
+ if ( this.numbered && this.lettered )
+ this.numbered = false;
+ }
+ this.symbolIndent = 0;
+ if ((value = (String)attributes.remove(ElementTags.SYMBOLINDENT)) != null) {
+ this.symbolIndent = Float.parseFloat(value);
+ }
+
+ if ((value = (String)attributes.remove(ElementTags.FIRST)) != null) {
+ char khar = value.charAt(0);
+ if ( Character.isLetter( khar ) ) {
+ setFirst( khar );
+ }
+ else {
+ setFirst(Integer.parseInt(value));
+ }
+ }
+ if ((value = (String)attributes.remove(ElementTags.INDENTATIONLEFT)) != null) {
+ setIndentationLeft(Float.valueOf(value + "f").floatValue());
+ }
+ if ((value = (String)attributes.remove(ElementTags.INDENTATIONRIGHT)) != null) {
+ setIndentationRight(Float.valueOf(value + "f").floatValue());
+ }
+ if (attributes.size() > 0) setMarkupAttributes(attributes);
+ }
+
+ // implementation of the Element-methods
+
+/**
+ * Processes the element by adding it (or the different parts) to an
+ * ElementListener
.
+ *
+ * @param listener an ElementListener
+ * @return true
if the element was processed successfully
+ */
+
+ public boolean process(ElementListener listener) {
+ try {
+ for (Iterator i = list.iterator(); i.hasNext(); ) {
+ listener.add((Element) i.next());
+ }
+ return true;
+ }
+ catch(DocumentException de) {
+ return false;
+ }
+ }
+
+/**
+ * Gets the type of the text element.
+ *
+ * @return a type
+ */
+
+ public int type() {
+ return Element.LIST;
+ }
+
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return an ArrayList
+ */
+
+ public ArrayList getChunks() {
+ ArrayList tmp = new ArrayList();
+ for (Iterator i = list.iterator(); i.hasNext(); ) {
+ tmp.addAll(((Element) i.next()).getChunks());
+ }
+ return tmp;
+ }
+
+ // methods to set the membervariables
+
+/**
+ * Adds an Object
to the List
.
+ *
+ * @param o the object to add.
+ * @return true if adding the object succeeded
+ */
+
+ public boolean add(Object o) {
+ if (o instanceof ListItem) {
+ ListItem item = (ListItem) o;
+ if (numbered || lettered) {
+ Chunk chunk;
+ if ( lettered )
+ chunk = new Chunk(nextLetter(), symbol.font());
+ else
+ chunk = new Chunk(String.valueOf(first + list.size()), symbol.font());
+ chunk.append(".");
+ item.setListSymbol(chunk);
+ }
+ else {
+ item.setListSymbol(symbol);
+ }
+ item.setIndentationLeft(symbolIndent);
+ item.setIndentationRight(0);
+ list.add(item);
+ }
+ else if (o instanceof List) {
+ List nested = (List) o;
+ nested.setIndentationLeft(nested.indentationLeft() + symbolIndent);
+ first--;
+ return list.add(nested);
+ }
+ else if (o instanceof String) {
+ return this.add(new ListItem((String) o));
+ }
+ return false;
+ }
+
+/**
+ * Sets the indentation of this paragraph on the left side.
+ *
+ * @param indentation the new indentation
+ */
+
+ public void setIndentationLeft(float indentation) {
+ this.indentationLeft = indentation;
+ }
+
+/**
+ * Sets the indentation of this paragraph on the right side.
+ *
+ * @param indentation the new indentation
+ */
+
+ public void setIndentationRight(float indentation) {
+ this.indentationRight = indentation;
+ }
+
+/**
+ * Sets the number that has to come first in the list.
+ *
+ * @param first a number
+ */
+
+ public void setFirst(int first) {
+ this.first = first;
+ }
+
+
+/**
+ * Sets the Letter that has to come first in the list.
+ *
+ * @param first a letter
+ */
+
+ public void setFirst(char first) {
+ this.firstCh = first;
+ if ( Character.isLowerCase( this.firstCh )) {
+ this.lastCh = 'z';
+ }
+ else {
+ this.lastCh = 'Z';
+ }
+ }
+
+/**
+ * Sets the listsymbol.
+ *
+ * @param symbol a Chunk
+ */
+
+ public void setListSymbol(Chunk symbol) {
+ this.symbol = symbol;
+ }
+
+/**
+ * Sets the listsymbol.
+ *
+ * This is a shortcut for setListSymbol(Chunk symbol)
.
+ *
+ * @param symbol a String
+ */
+
+ public void setListSymbol(String symbol) {
+ this.symbol = new Chunk(symbol);
+ }
+
+ // methods to retrieve information
+
+/**
+ * Gets all the items in the list.
+ *
+ * @return an ArrayList
containing ListItem
s.
+ */
+
+ public ArrayList getItems() {
+ return list;
+ }
+
+/**
+ * Gets the size of the list.
+ *
+ * @return a size
+ */
+
+ public int size() {
+ return list.size();
+ }
+
+/**
+ * Gets the leading of the first listitem.
+ *
+ * @return a leading
+ */
+
+ public float leading() {
+ if (list.size() < 1) {
+ return -1;
+ }
+ ListItem item = (ListItem) list.get(0);
+ return item.leading();
+ }
+
+/**
+ * Checks if the list is numbered.
+ *
+ * @return true
if the list is numbered, false
otherwise.
+ */
+
+ public boolean isNumbered() {
+ return numbered;
+ }
+
+/**
+ * Gets the symbol indentation.
+ * @return the symbol indentation
+ */
+
+ public float symbolIndent() {
+ return symbolIndent;
+ }
+
+/**
+ * Gets the Chunk containing the symbol.
+ * @return a Chunk with a symbol
+ */
+
+ public Chunk symbol() {
+ return symbol;
+ }
+
+/**
+ * Gets the first number .
+ * @return a number
+ */
+
+ public int first() {
+ return first;
+ }
+
+/**
+ * Gets the indentation of this paragraph on the left side.
+ *
+ * @return the indentation
+ */
+
+ public float indentationLeft() {
+ return indentationLeft;
+ }
+
+/**
+ * Gets the indentation of this paragraph on the right side.
+ *
+ * @return the indentation
+ */
+
+ public float indentationRight() {
+ return indentationRight;
+ }
+
+/**
+ * Checks if a given tag corresponds with the listsymbol tag of this object.
+ *
+ * @param tag the given tag
+ * @return true if the tag corresponds
+ */
+
+ public static boolean isSymbol(String tag) {
+ return ElementTags.LISTSYMBOL.equals(tag);
+ }
+
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param tag the given tag
+ * @return true if the tag corresponds
+ */
+
+ public static boolean isTag(String tag) {
+ return ElementTags.LIST.equals(tag);
+ }
+
+/**
+ * Retrieves the next letter in the sequence
+ *
+ * @return String contains the next character (A-Z or a-z)
+ */
+ private String nextLetter() {
+ int num_in_list = listItemsInList(); //list.size();
+ int max_ival = (lastCh + 0);
+ int ival = (firstCh + num_in_list);
+ while ( ival > max_ival ) {
+ ival -= 26;
+ }
+ char[] new_char = new char[1];
+ new_char[0] = (char) ival;
+ String ret = new String( new_char );
+ return ret;
+ }
+
+ /**
+ * Counts the number of ListItems in the list ommiting nested lists
+ *
+ * @return Integer number of ListItems in the list
+ */
+ private int listItemsInList() {
+ int result = 0;
+ for (Iterator i = list.iterator(); i.hasNext(); ) {
+ if (!(i.next() instanceof List)) result++;
+ }
+ return result;
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String, java.lang.String)
+ */
+ public void setMarkupAttribute(String name, String value) {
+ if (markupAttributes == null) markupAttributes = new Properties();
+ markupAttributes.put(name, value);
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+ */
+ public void setMarkupAttributes(Properties markupAttributes) {
+ this.markupAttributes = markupAttributes;
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+ */
+ public String getMarkupAttribute(String name) {
+ return (markupAttributes == null) ? null : String.valueOf(markupAttributes.get(name));
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+ */
+ public Set getMarkupAttributeNames() {
+ return Chunk.getKeySet(markupAttributes);
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+ */
+ public Properties getMarkupAttributes() {
+ return markupAttributes;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/ListItem.java pdftk-2.01/java/pdftk/com/lowagie/text/ListItem.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/ListItem.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/ListItem.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,281 @@
+/*
+ * $Id: ListItem.java,v 1.78 2005/05/03 13:03:48 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.util.Properties;
+
+import pdftk.com.lowagie.text.markup.MarkupTags;
+import pdftk.com.lowagie.text.markup.MarkupParser;
+
+/**
+ * A ListItem
is a Paragraph
+ * that can be added to a List
.
+ *
+ * Example 1:
+ *
+ * List list = new List(true, 20);
+ * list.add(new ListItem("First line") );
+ * list.add(new ListItem("The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?") );
+ * list.add(new ListItem("Third line") );
+ *
+ *
+ * The result of this code looks like this:
+ *
+ *
+ * First line
+ *
+ *
+ * The second line is longer to see what happens once the end of the line is reached. Will it start on a new line?
+ *
+ *
+ * Third line
+ *
+ *
+ *
+ * Example 2:
+ *
+ * List overview = new List(false, 10);
+ * overview.add(new ListItem("This is an item") );
+ * overview.add("This is another item");
+ *
+ *
+ * The result of this code looks like this:
+ *
+ *
+ * This is an item
+ *
+ *
+ * This is another item
+ *
+ *
+ *
+ * @see Element
+ * @see List
+ * @see Paragraph
+ */
+
+public class ListItem extends Paragraph implements TextElementArray, MarkupAttributes {
+
+ // membervariables
+
+/** this is the symbol that wil proceed the listitem. */
+ private Chunk symbol;
+
+ // constructors
+
+/**
+ * Constructs a ListItem
.
+ */
+
+ public ListItem() {
+ super();
+ }
+
+/**
+ * Constructs a ListItem
with a certain leading.
+ *
+ * @param leading the leading
+ */
+
+ public ListItem(float leading) {
+ super(leading);
+ }
+
+/**
+ * Constructs a ListItem
with a certain Chunk
.
+ *
+ * @param chunk a Chunk
+ */
+
+ public ListItem(Chunk chunk) {
+ super(chunk);
+ }
+
+/**
+ * Constructs a ListItem
with a certain String
.
+ *
+ * @param string a String
+ */
+
+ public ListItem(String string) {
+ super(string);
+ }
+
+/**
+ * Constructs a ListItem
with a certain String
+ * and a certain Font
.
+ *
+ * @param string a String
+ * @param font a String
+ */
+
+ public ListItem(String string, Font font) {
+ super(string, font);
+ }
+
+/**
+ * Constructs a ListItem
with a certain Chunk
+ * and a certain leading.
+ *
+ * @param leading the leading
+ * @param chunk a Chunk
+ */
+
+ public ListItem(float leading, Chunk chunk) {
+ super(leading, chunk);
+ }
+
+/**
+ * Constructs a ListItem
with a certain String
+ * and a certain leading.
+ *
+ * @param leading the leading
+ * @param string a String
+ */
+
+ public ListItem(float leading, String string) {
+ super(leading, string);
+ }
+
+/**
+ * Constructs a ListItem
with a certain leading, String
+ * and Font
.
+ *
+ * @param leading the leading
+ * @param string a String
+ * @param font a Font
+ */
+
+ public ListItem(float leading, String string, Font font) {
+ super(leading, string, font);
+ }
+
+/**
+ * Constructs a ListItem
with a certain Phrase
.
+ *
+ * @param phrase a Phrase
+ */
+
+ public ListItem(Phrase phrase) {
+ super(phrase);
+ }
+
+ /**
+ * Returns a ListItem
that has been constructed taking in account
+ * the value of some attributes .
+ *
+ * @param attributes Some attributes
+ */
+
+ public ListItem(Properties attributes) {
+ super("", FontFactory.getFont(attributes));
+ String value;
+ if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
+ add(new Chunk(value));
+ }
+ if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
+ setLeading(Float.valueOf(value + "f").floatValue());
+ }
+ else if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_LINEHEIGHT)) != null) {
+ setLeading(MarkupParser.parseLength(value));
+ }
+ if ((value = (String)attributes.remove(ElementTags.INDENTATIONLEFT)) != null) {
+ setIndentationLeft(Float.valueOf(value + "f").floatValue());
+ }
+ if ((value = (String)attributes.remove(ElementTags.INDENTATIONRIGHT)) != null) {
+ setIndentationRight(Float.valueOf(value + "f").floatValue());
+ }
+ if ((value = (String)attributes.remove(ElementTags.ALIGN)) != null) {
+ setAlignment(value);
+ }
+ if (attributes.size() > 0) setMarkupAttributes(attributes);
+ }
+
+ // implementation of the Element-methods
+
+/**
+ * Gets the type of the text element.
+ *
+ * @return a type
+ */
+
+ public int type() {
+ return Element.LISTITEM;
+ }
+
+ // methods
+
+/**
+ * Sets the listsymbol.
+ *
+ * @param symbol a Chunk
+ */
+
+ public void setListSymbol(Chunk symbol) {
+ this.symbol = symbol;
+ if (this.symbol.font().isStandardFont()) {
+ this.symbol.setFont(font);
+ }
+ }
+
+ // methods to retrieve information
+
+/**
+ * Returns the listsymbol.
+ *
+ * @return a Chunk
+ */
+
+ public Chunk listSymbol() {
+ return symbol;
+ }
+
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param tag the given tag
+ * @return true if the tag corresponds
+ */
+
+ public static boolean isTag(String tag) {
+ return ElementTags.LISTITEM.equals(tag);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/MarkupAttributes.java pdftk-2.01/java/pdftk/com/lowagie/text/MarkupAttributes.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/MarkupAttributes.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/MarkupAttributes.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2002 by Matt Benson.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+
+import java.util.Properties;
+import java.util.Set;
+
+
+/**
+ * Defines the interface for an Element
with markup attributes--
+ * that is, random String-to-String properties for representation in markup
+ * languages such as HTML and XML.
+ *
+ * @author Matt Benson
+ */
+public interface MarkupAttributes extends pdftk.com.lowagie.text.Element {
+
+/**
+ * Sets the specified attribute.
+ *
+ * @param name String
attribute name.
+ * @param value String
attribute value.
+ */
+ public void setMarkupAttribute(String name, String value);
+
+/**
+ * Sets the markupAttributes.
+ *
+ * @param markupAttributes a Properties
-object containing markupattributes
+ */
+ public void setMarkupAttributes(Properties markupAttributes);
+
+/**
+ * Returns the value of the specified attribute.
+ *
+ * @param name String
attribute name.
+ * @return String
.
+ */
+ public String getMarkupAttribute(String name);
+
+/**
+ * Returns a Set
of String
attribute names for the
+ * MarkupAttributes
implementor.
+ *
+ * @return Set
.
+ */
+ public Set getMarkupAttributeNames(); // ssteward: dropped in 1.44
+
+/**
+ * Return a Properties
-object containing all the markupAttributes.
+ *
+ * @return Properties
+ */
+ public Properties getMarkupAttributes();
+
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Meta.java pdftk-2.01/java/pdftk/com/lowagie/text/Meta.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Meta.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Meta.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,252 @@
+/*
+ * $Id: Meta.java,v 1.65 2005/04/13 09:17:11 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.util.ArrayList;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * This is an Element
that contains
+ * some meta information about the document.
+ *
+ * An object of type Meta
can not be constructed by the user.
+ * Userdefined meta information should be placed in a Header
-object.
+ * Meta
is reserved for: Subject, Keywords, Author, Title, Producer
+ * and Creationdate information.
+ *
+ * @see Element
+ * @see Header
+ */
+
+public class Meta implements Element, MarkupAttributes {
+
+ // membervariables
+
+/** This is the type of Meta-information this object contains. */
+ private int type;
+
+/** This is the content of the Meta-information. */
+ private StringBuffer content;
+
+/** Contains extra markupAttributes */
+ protected Properties markupAttributes;
+
+ // constructors
+
+/**
+ * Constructs a Meta
.
+ *
+ * @param type the type of meta-information
+ * @param content the content
+ */
+
+ Meta(int type, String content) {
+ this.type = type;
+ this.content = new StringBuffer(content);
+ }
+
+/**
+ * Constructs a Meta
.
+ *
+ * @param tag the tagname of the meta-information
+ * @param content the content
+ */
+
+ public Meta(String tag, String content) {
+ this.type = Meta.getType(tag);
+ this.content = new StringBuffer(content);
+ }
+
+ // implementation of the Element-methods
+
+/**
+ * Processes the element by adding it (or the different parts) to a
+ * ElementListener
.
+ *
+ * @param listener the ElementListener
+ * @return true
if the element was processed successfully
+ */
+
+ public boolean process(ElementListener listener) {
+ try {
+ return listener.add(this);
+ }
+ catch(DocumentException de) {
+ return false;
+ }
+ }
+
+/**
+ * Gets the type of the text element.
+ *
+ * @return a type
+ */
+
+ public int type() {
+ return type;
+ }
+
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return an ArrayList
+ */
+ public ArrayList getChunks() {
+ return new ArrayList();
+ }
+
+ // methods
+
+/**
+ * appends some text to this Meta
.
+ *
+ * @param string a String
+ * @return a StringBuffer
+ */
+
+ public StringBuffer append(String string) {
+ return content.append(string);
+ }
+
+ // methods to retrieve information
+
+/**
+ * Returns the content of the meta information.
+ *
+ * @return a String
+ */
+
+ public String content() {
+ return content.toString();
+ }
+
+/**
+ * Returns the name of the meta information.
+ *
+ * @return a String
+ */
+
+ public String name() {
+ switch (type) {
+ case Element.SUBJECT:
+ return ElementTags.SUBJECT;
+ case Element.KEYWORDS:
+ return ElementTags.KEYWORDS;
+ case Element.AUTHOR:
+ return ElementTags.AUTHOR;
+ case Element.TITLE:
+ return ElementTags.TITLE;
+ case Element.PRODUCER:
+ return ElementTags.PRODUCER;
+ case Element.CREATIONDATE:
+ return ElementTags.CREATIONDATE;
+ default:
+ return ElementTags.UNKNOWN;
+ }
+ }
+
+/**
+ * Returns the name of the meta information.
+ *
+ * @param tag iText tag for meta information
+ * @return the Element value corresponding with the given tag
+ */
+
+ public static int getType(String tag) {
+ if (ElementTags.SUBJECT.equals(tag)) {
+ return Element.SUBJECT;
+ }
+ if (ElementTags.KEYWORDS.equals(tag)) {
+ return Element.KEYWORDS;
+ }
+ if (ElementTags.AUTHOR.equals(tag)) {
+ return Element.AUTHOR;
+ }
+ if (ElementTags.TITLE.equals(tag)) {
+ return Element.TITLE;
+ }
+ if (ElementTags.PRODUCER.equals(tag)) {
+ return Element.PRODUCER;
+ }
+ if (ElementTags.CREATIONDATE.equals(tag)) {
+ return Element.CREATIONDATE;
+ }
+ return Element.HEADER;
+ }
+
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String, java.lang.String)
+ */
+ public void setMarkupAttribute(String name, String value) {
+ if (markupAttributes == null) markupAttributes = new Properties();
+ markupAttributes.put(name, value);
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+ */
+ public void setMarkupAttributes(Properties markupAttributes) {
+ this.markupAttributes = markupAttributes;
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+ */
+ public String getMarkupAttribute(String name) {
+ return (markupAttributes == null) ? null : String.valueOf(markupAttributes.get(name));
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+ */
+ public Set getMarkupAttributeNames() {
+ return Chunk.getKeySet(markupAttributes);
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+ */
+ public Properties getMarkupAttributes() {
+ return markupAttributes;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/PageSize.java pdftk-2.01/java/pdftk/com/lowagie/text/PageSize.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/PageSize.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/PageSize.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,142 @@
+/*
+ * $Id: PageSize.java,v 1.26 2002/06/20 13:30:24 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+/**
+ * The PageSize
-object contains a number of rectangles representing the most common papersizes.
+ *
+ * @see Rectangle
+ */
+
+public class PageSize {
+
+ // membervariables
+
+/** This is the letter format */
+ public static final Rectangle LETTER = new Rectangle(612,792);
+
+/** This is the note format */
+ public static final Rectangle NOTE = new Rectangle(540,720);
+
+/** This is the legal format */
+ public static final Rectangle LEGAL = new Rectangle(612,1008);
+
+/** This is the a0 format */
+ public static final Rectangle A0 = new Rectangle(2384,3370);
+
+/** This is the a1 format */
+ public static final Rectangle A1 = new Rectangle(1684,2384);
+
+/** This is the a2 format */
+ public static final Rectangle A2 = new Rectangle(1190,1684);
+
+/** This is the a3 format */
+ public static final Rectangle A3 = new Rectangle(842,1190);
+
+/** This is the a4 format */
+ public static final Rectangle A4 = new Rectangle(595,842);
+
+/** This is the a5 format */
+ public static final Rectangle A5 = new Rectangle(421,595);
+
+/** This is the a6 format */
+ public static final Rectangle A6 = new Rectangle(297,421);
+
+/** This is the a7 format */
+ public static final Rectangle A7 = new Rectangle(210,297);
+
+/** This is the a8 format */
+ public static final Rectangle A8 = new Rectangle(148,210);
+
+/** This is the a9 format */
+ public static final Rectangle A9 = new Rectangle(105,148);
+
+/** This is the a10 format */
+ public static final Rectangle A10 = new Rectangle(74,105);
+
+/** This is the b0 format */
+ public static final Rectangle B0 = new Rectangle(2836,4008);
+
+/** This is the b1 format */
+ public static final Rectangle B1 = new Rectangle(2004,2836);
+
+/** This is the b2 format */
+ public static final Rectangle B2 = new Rectangle(1418,2004);
+
+/** This is the b3 format */
+ public static final Rectangle B3 = new Rectangle(1002,1418);
+
+/** This is the b4 format */
+ public static final Rectangle B4 = new Rectangle(709,1002);
+
+/** This is the b5 format */
+ public static final Rectangle B5 = new Rectangle(501,709);
+
+/** This is the archE format */
+ public static final Rectangle ARCH_E = new Rectangle(2592,3456);
+
+/** This is the archD format */
+ public static final Rectangle ARCH_D = new Rectangle(1728,2592);
+
+/** This is the archC format */
+ public static final Rectangle ARCH_C = new Rectangle(1296,1728);
+
+/** This is the archB format */
+ public static final Rectangle ARCH_B = new Rectangle(864,1296);
+
+/** This is the archA format */
+ public static final Rectangle ARCH_A = new Rectangle(648,864);
+
+/** This is the flsa format */
+ public static final Rectangle FLSA = new Rectangle(612,936);
+
+/** This is the flse format */
+ public static final Rectangle FLSE = new Rectangle(612,936);
+
+/** This is the halfletter format */
+ public static final Rectangle HALFLETTER = new Rectangle(396,612);
+
+/** This is the 11x17 format */
+ public static final Rectangle _11X17 = new Rectangle(792,1224);
+
+/** This is the ledger format */
+ public static final Rectangle LEDGER = new Rectangle(1224,792);
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Paragraph.java pdftk-2.01/java/pdftk/com/lowagie/text/Paragraph.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Paragraph.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Paragraph.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,508 @@
+/*
+ * $Id: Paragraph.java,v 1.83 2005/05/03 13:03:48 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.util.Properties;
+
+import pdftk.com.lowagie.text.markup.MarkupTags;
+import pdftk.com.lowagie.text.markup.MarkupParser;
+
+/**
+ * A Paragraph
is a series of Chunk
s and/or Phrases
.
+ *
+ * A Paragraph
has the same qualities of a Phrase
, but also
+ * some additional layout-parameters:
+ *
+ * the indentation
+ * the alignment of the text
+ *
+ *
+ * Example:
+ *
+ * Paragraph p = new Paragraph("This is a paragraph",
+ * FontFactory.getFont(FontFactory.HELVETICA, 18, Font.BOLDITALIC, new Color(0, 0, 255)));
+ *
+ *
+ * @see Element
+ * @see Phrase
+ * @see ListItem
+ */
+
+public class Paragraph extends Phrase implements TextElementArray, MarkupAttributes {
+
+ // membervariables
+
+/** The alignment of the text. */
+ protected int alignment = Element.ALIGN_UNDEFINED;
+
+/** The indentation of this paragraph on the left side. */
+ protected float indentationLeft;
+
+/** The indentation of this paragraph on the right side. */
+ protected float indentationRight;
+
+/** The spacing before the paragraph. */
+ protected float spacingBefore;
+
+/** The spacing after the paragraph. */
+ protected float spacingAfter;
+
+/** Does the paragraph has to be kept together on 1 page. */
+ protected boolean keeptogether = false;
+
+ /** The text leading that is multiplied by the biggest font size in the line. */
+ protected float multipliedLeading = 0;
+
+ /**
+ * Holds value of property firstLineIndent.
+ */
+ private float firstLineIndent = 0;
+
+ /**
+ * Holds value of property extraParagraphSpace.
+ */
+ private float extraParagraphSpace = 0;
+
+ // constructors
+
+/**
+ * Constructs a Paragraph
.
+ */
+
+ public Paragraph() {
+ super();
+ }
+
+/**
+ * Constructs a Paragraph
with a certain leading.
+ *
+ * @param leading the leading
+ */
+
+ public Paragraph(float leading) {
+ super(leading);
+ }
+
+/**
+ * Constructs a Paragraph
with a certain Chunk
.
+ *
+ * @param chunk a Chunk
+ */
+
+ public Paragraph(Chunk chunk) {
+ super(chunk);
+ }
+
+/**
+ * Constructs a Paragraph
with a certain Chunk
+ * and a certain leading.
+ *
+ * @param leading the leading
+ * @param chunk a Chunk
+ */
+
+ public Paragraph(float leading, Chunk chunk) {
+ super(leading, chunk);
+ }
+
+/**
+ * Constructs a Paragraph
with a certain String
.
+ *
+ * @param string a String
+ */
+
+ public Paragraph(String string) {
+ super(string);
+ }
+
+/**
+ * Constructs a Paragraph
with a certain String
+ * and a certain Font
.
+ *
+ * @param string a String
+ * @param font a Font
+ */
+
+ public Paragraph(String string, Font font) {
+ super(string, font);
+ }
+
+/**
+ * Constructs a Paragraph
with a certain String
+ * and a certain leading.
+ *
+ * @param leading the leading
+ * @param string a String
+ */
+
+ public Paragraph(float leading, String string) {
+ super(leading, string);
+ }
+
+/**
+ * Constructs a Paragraph
with a certain leading, String
+ * and Font
.
+ *
+ * @param leading the leading
+ * @param string a String
+ * @param font a Font
+ */
+
+ public Paragraph(float leading, String string, Font font) {
+ super(leading, string, font);
+ }
+
+/**
+ * Constructs a Paragraph
with a certain Phrase
.
+ *
+ * @param phrase a Phrase
+ */
+
+ public Paragraph(Phrase phrase) {
+ super(phrase.leading, "", phrase.font());
+ super.add(phrase);
+ }
+
+/**
+ * Returns a Paragraph
that has been constructed taking in account
+ * the value of some attributes .
+ *
+ * @param attributes Some attributes
+ */
+
+ public Paragraph(Properties attributes) {
+ this("", FontFactory.getFont(attributes));
+ String value;
+ if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
+ Chunk chunk = new Chunk(value);
+ if ((value = (String)attributes.remove(ElementTags.GENERICTAG)) != null) {
+ chunk.setGenericTag(value);
+ }
+ add(chunk);
+ }
+ if ((value = (String)attributes.remove(ElementTags.ALIGN)) != null) {
+ setAlignment(value);
+ }
+ if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
+ setLeading(Float.valueOf(value + "f").floatValue());
+ }
+ else if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_LINEHEIGHT)) != null) {
+ setLeading(MarkupParser.parseLength(value));
+ }
+ else {
+ setLeading(16);
+ }
+ if ((value = (String)attributes.remove(ElementTags.INDENTATIONLEFT)) != null) {
+ setIndentationLeft(Float.valueOf(value + "f").floatValue());
+ }
+ if ((value = (String)attributes.remove(ElementTags.INDENTATIONRIGHT)) != null) {
+ setIndentationRight(Float.valueOf(value + "f").floatValue());
+ }
+ if ((value = (String)attributes.remove(ElementTags.KEEPTOGETHER)) != null) {
+ keeptogether = new Boolean(value).booleanValue();
+ }
+ if (attributes.size() > 0) setMarkupAttributes(attributes);
+ }
+
+ // implementation of the Element-methods
+
+/**
+ * Gets the type of the text element.
+ *
+ * @return a type
+ */
+
+ public int type() {
+ return Element.PARAGRAPH;
+ }
+
+ // methods
+
+/**
+ * Adds an Object
to the Paragraph
.
+ *
+ * @param o object the object to add.
+ * @return true is adding the object succeeded
+ */
+
+ public boolean add(Object o) {
+ if (o instanceof List) {
+ List list = (List) o;
+ list.setIndentationLeft(list.indentationLeft() + indentationLeft);
+ list.setIndentationRight(indentationRight);
+ return super.add(list);
+ }
+ /* ssteward: dropped in 1.44
+ else if (o instanceof Image) {
+ super.addSpecial((Image) o);
+ return true;
+ }
+ */
+ else if (o instanceof Paragraph) {
+ super.add(o);
+ super.add(Chunk.NEWLINE);
+ return true;
+ }
+ return super.add(o);
+ }
+
+ // setting the membervariables
+
+/**
+ * Sets the alignment of this paragraph.
+ *
+ * @param alignment the new alignment
+ */
+
+ public void setAlignment(int alignment) {
+ this.alignment = alignment;
+ }
+
+/**
+ * Sets the alignment of this paragraph.
+ *
+ * @param alignment the new alignment as a String
+ */
+
+ public void setAlignment(String alignment) {
+ if (ElementTags.ALIGN_CENTER.equalsIgnoreCase(alignment)) {
+ this.alignment = Element.ALIGN_CENTER;
+ return;
+ }
+ if (ElementTags.ALIGN_RIGHT.equalsIgnoreCase(alignment)) {
+ this.alignment = Element.ALIGN_RIGHT;
+ return;
+ }
+ if (ElementTags.ALIGN_JUSTIFIED.equalsIgnoreCase(alignment)) {
+ this.alignment = Element.ALIGN_JUSTIFIED;
+ return;
+ }
+ if (ElementTags.ALIGN_JUSTIFIED_ALL.equalsIgnoreCase(alignment)) {
+ this.alignment = Element.ALIGN_JUSTIFIED_ALL;
+ return;
+ }
+ this.alignment = Element.ALIGN_LEFT;
+ }
+
+/**
+ * Sets the indentation of this paragraph on the left side.
+ *
+ * @param indentation the new indentation
+ */
+
+ public void setIndentationLeft(float indentation) {
+ this.indentationLeft = indentation;
+ }
+
+/**
+ * Sets the indentation of this paragraph on the right side.
+ *
+ * @param indentation the new indentation
+ */
+
+ public void setIndentationRight(float indentation) {
+ this.indentationRight = indentation;
+ }
+
+/**
+ * Sets the spacing before this paragraph.
+ *
+ * @param spacing the new spacing
+ */
+
+ public void setSpacingBefore(float spacing) {
+ this.spacingBefore = spacing;
+ }
+
+/**
+ * Sets the spacing after this paragraph.
+ *
+ * @param spacing the new spacing
+ */
+
+ public void setSpacingAfter(float spacing) {
+ this.spacingAfter = spacing;
+ }
+
+/**
+ * Indicates that the paragraph has to be kept together on one page.
+ *
+ * @param keeptogether true of the paragraph may not be split over 2 pages
+ */
+
+ public void setKeepTogether(boolean keeptogether) {
+ this.keeptogether = keeptogether;
+ }
+
+/**
+ * Checks if this paragraph has to be kept together on one page.
+ *
+ * @return true if the paragraph may not be split over 2 pages.
+ */
+
+ public boolean getKeepTogether() {
+ return keeptogether;
+ }
+
+ // methods to retrieve information
+
+/**
+ * Gets the alignment of this paragraph.
+ *
+ * @return alignment
+ */
+
+ public int alignment() {
+ return alignment;
+ }
+
+/**
+ * Gets the indentation of this paragraph on the left side.
+ *
+ * @return the indentation
+ */
+
+ public float indentationLeft() {
+ return indentationLeft;
+ }
+
+/**
+ * Gets the indentation of this paragraph on the right side.
+ *
+ * @return the indentation
+ */
+
+ public float indentationRight() {
+ return indentationRight;
+ }
+
+/**
+ * Gets the spacing before this paragraph.
+ *
+ * @return the spacing
+ */
+
+ public float spacingBefore() {
+ return spacingBefore;
+ }
+
+/**
+ * Gets the spacing before this paragraph.
+ *
+ * @return the spacing
+ */
+
+ public float spacingAfter() {
+ return spacingAfter;
+ }
+
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param tag the given tag
+ * @return true if the tag corresponds
+ */
+
+ public static boolean isTag(String tag) {
+ return ElementTags.PARAGRAPH.equals(tag);
+ }
+
+ /**
+ * Sets the leading fixed and variable. The resultant leading will be
+ * fixedLeading+multipliedLeading*maxFontSize where maxFontSize is the
+ * size of the bigest font in the line.
+ * @param fixedLeading the fixed leading
+ * @param multipliedLeading the variable leading
+ */
+ public void setLeading(float fixedLeading, float multipliedLeading) {
+ this.leading = fixedLeading;
+ this.multipliedLeading = multipliedLeading;
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.Phrase#setLeading(float)
+ */
+ public void setLeading(float fixedLeading) {
+ this.leading = fixedLeading;
+ this.multipliedLeading = 0;
+ }
+
+ /**
+ * Gets the variable leading
+ * @return the leading
+ */
+ public float getMultipliedLeading() {
+ return multipliedLeading;
+ }
+
+ /**
+ * Getter for property firstLineIndent.
+ * @return Value of property firstLineIndent.
+ */
+ public float getFirstLineIndent() {
+ return this.firstLineIndent;
+ }
+
+ /**
+ * Setter for property firstLineIndent.
+ * @param firstLineIndent New value of property firstLineIndent.
+ */
+ public void setFirstLineIndent(float firstLineIndent) {
+ this.firstLineIndent = firstLineIndent;
+ }
+
+ /**
+ * Getter for property extraParagraphSpace.
+ * @return Value of property extraParagraphSpace.
+ */
+ public float getExtraParagraphSpace() {
+ return this.extraParagraphSpace;
+ }
+
+ /**
+ * Setter for property extraParagraphSpace.
+ * @param extraParagraphSpace New value of property extraParagraphSpace.
+ */
+ public void setExtraParagraphSpace(float extraParagraphSpace) {
+ this.extraParagraphSpace = extraParagraphSpace;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Phrase.java pdftk-2.01/java/pdftk/com/lowagie/text/Phrase.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Phrase.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Phrase.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,594 @@
+/*
+ * $Id: Phrase.java,v 1.104 2005/09/05 08:04:55 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+import pdftk.com.lowagie.text.markup.MarkupTags;
+import pdftk.com.lowagie.text.markup.MarkupParser;
+
+/**
+ * A Phrase
is a series of Chunk
s.
+ *
+ * A Phrase
has a main Font
, but some chunks
+ * within the phrase can have a Font
that differs from the
+ * main Font
. All the Chunk
s in a Phrase
+ * have the same leading
.
+ *
+ * Example:
+ *
+ * // When no parameters are passed, the default leading = 16
+ * Phrase phrase0 = new Phrase();
+ * Phrase phrase1 = new Phrase("this is a phrase");
+ * // In this example the leading is passed as a parameter
+ * Phrase phrase2 = new Phrase(16, "this is a phrase with leading 16");
+ * // When a Font is passed (explicitely or embedded in a chunk), the default leading = 1.5 * size of the font
+ * Phrase phrase3 = new Phrase("this is a phrase with a red, normal font Courier, size 12", FontFactory.getFont(FontFactory.COURIER, 12, Font.NORMAL, new Color(255, 0, 0)));
+ * Phrase phrase4 = new Phrase(new Chunk("this is a phrase"));
+ * Phrase phrase5 = new Phrase(18, new Chunk("this is a phrase", FontFactory.getFont(FontFactory.HELVETICA, 16, Font.BOLD, new Color(255, 0, 0)));
+ *
+ *
+ * @see Element
+ * @see Chunk
+ * @see Paragraph
+ * @see Anchor
+ */
+
+public class Phrase extends ArrayList implements TextElementArray, MarkupAttributes {
+
+ // membervariables
+
+/** This is the leading of this phrase. */
+ protected float leading = Float.NaN;
+
+/** This is the font of this phrase. */
+ protected Font font = new Font();
+
+/** Contains extra markupAttributes */
+ protected Properties markupAttributes;
+
+ // constructors
+
+/**
+ * Constructs a Phrase that can be used in the static getInstance() method.
+ * @param dummy a dummy parameter
+ */
+ private Phrase(boolean dummy) {
+ }
+
+/**
+ * Constructs a Phrase
without specifying a leading.
+ */
+
+ public Phrase() {
+ this(16);
+ }
+
+/**
+ * Constructs a Phrase
with a certain leading.
+ *
+ * @param leading the leading
+ */
+
+ public Phrase(float leading) {
+ this.leading = leading;
+ }
+
+/**
+ * Constructs a Phrase
with a certain Chunk
.
+ *
+ * @param chunk a Chunk
+ */
+
+ public Phrase(Chunk chunk) {
+ super.add(chunk);
+ }
+
+/**
+ * Constructs a Phrase
with a certain Chunk
+ * and a certain leading.
+ *
+ * @param leading the leading
+ * @param chunk a Chunk
+ */
+
+ public Phrase(float leading, Chunk chunk) {
+ this(leading);
+ super.add(chunk);
+ }
+
+/**
+ * Constructs a Phrase
with a certain String
.
+ *
+ * @param string a String
+ */
+
+ public Phrase(String string) {
+ this(Float.NaN, string, new Font());
+ }
+
+/**
+ * Constructs a Phrase
with a certain String
and a certain Font
.
+ *
+ * @param string a String
+ * @param font a Font
+ */
+
+ public Phrase(String string, Font font) {
+ this(Float.NaN, string, font);
+ this.font = font;
+ }
+
+/**
+ * Constructs a Phrase
with a certain leading and a certain String
.
+ *
+ * @param leading the leading
+ * @param string a String
+ */
+
+ public Phrase(float leading, String string) {
+ this(leading, string, new Font());
+ }
+
+/**
+ * Constructs a Phrase
with a certain leading, a certain String
+ * and a certain Font
.
+ *
+ * @param leading the leading
+ * @param string a String
+ * @param font a Font
+ */
+
+ public Phrase(float leading, String string, Font font) {
+ this(leading);
+ this.font = font;
+ /* bugfix by August Detlefsen */
+ if (string != null && string.length() != 0) {
+ super.add(new Chunk(string, font));
+ }
+ }
+
+ /**
+ * Gets a special kind of Phrase that changes some characters into corresponding symbols.
+ * @param string
+ * @return a newly constructed Phrase
+ */
+ public static final Phrase getInstance(String string) {
+ return getInstance(16, string, new Font());
+ }
+
+ /**
+ * Gets a special kind of Phrase that changes some characters into corresponding symbols.
+ * @param leading
+ * @param string
+ * @return a newly constructed Phrase
+ */
+ public static final Phrase getInstance(int leading, String string) {
+ return getInstance(leading, string, new Font());
+ }
+
+ /**
+ * Gets a special kind of Phrase that changes some characters into corresponding symbols.
+ * @param leading
+ * @param string
+ * @param font
+ * @return a newly constructed Phrase
+ */
+ public static final Phrase getInstance(int leading, String string, Font font) {
+ Phrase p = new Phrase(true);
+ p.setLeading(leading);
+ p.font = font;
+ if (font.family() != Font.SYMBOL && font.family() != Font.ZAPFDINGBATS && font.getBaseFont() == null) {
+ int index;
+ while((index = SpecialSymbol.index(string)) > -1) {
+ if (index > 0) {
+ String firstPart = string.substring(0, index);
+ /* bugfix [ #461272 ] CODE CHANGE REQUIRED IN Phrase.java
+ by Arekh Nambiar */
+ ((ArrayList)p).add(new Chunk(firstPart, font));
+ string = string.substring(index);
+ }
+ Font symbol = new Font(Font.SYMBOL, font.size(), font.style(), font.color());
+ StringBuffer buf = new StringBuffer();
+ buf.append(SpecialSymbol.getCorrespondingSymbol(string.charAt(0)));
+ string = string.substring(1);
+ while (SpecialSymbol.index(string) == 0) {
+ buf.append(SpecialSymbol.getCorrespondingSymbol(string.charAt(0)));
+ string = string.substring(1);
+ }
+ ((ArrayList)p).add(new Chunk(buf.toString(), symbol));
+ }
+ }
+ /* bugfix by August Detlefsen */
+ if (string != null && string.length() != 0) {
+ ((ArrayList)p).add(new Chunk(string, font));
+ }
+ return p;
+ }
+
+/**
+ * Returns a Phrase
that has been constructed taking in account
+ * the value of some attributes .
+ *
+ * @param attributes Some attributes
+ */
+
+ public Phrase(Properties attributes) {
+ this("", FontFactory.getFont(attributes));
+ clear();
+ String value;
+ if ((value = (String)attributes.remove(ElementTags.LEADING)) != null) {
+ setLeading(Float.valueOf(value + "f").floatValue());
+ }
+ else if ((value = (String)attributes.remove(MarkupTags.CSS_KEY_LINEHEIGHT)) != null) {
+ setLeading(MarkupParser.parseLength(value));
+ }
+ if ((value = (String)attributes.remove(ElementTags.ITEXT)) != null) {
+ Chunk chunk = new Chunk(value);
+ if ((value = (String)attributes.remove(ElementTags.GENERICTAG)) != null) {
+ chunk.setGenericTag(value);
+ }
+ add(chunk);
+ }
+ if (attributes.size() > 0) setMarkupAttributes(attributes);
+ }
+
+ // implementation of the Element-methods
+
+/**
+ * Processes the element by adding it (or the different parts) to an
+ * ElementListener
.
+ *
+ * @param listener an ElementListener
+ * @return true
if the element was processed successfully
+ */
+
+ public boolean process(ElementListener listener) {
+ try {
+ for (Iterator i = iterator(); i.hasNext(); ) {
+ listener.add((Element) i.next());
+ }
+ return true;
+ }
+ catch(DocumentException de) {
+ return false;
+ }
+ }
+
+/**
+ * Gets the type of the text element.
+ *
+ * @return a type
+ */
+
+ public int type() {
+ return Element.PHRASE;
+ }
+
+/**
+ * Gets all the chunks in this element.
+ *
+ * @return an ArrayList
+ */
+
+ public ArrayList getChunks() {
+ ArrayList tmp = new ArrayList();
+ for (Iterator i = iterator(); i.hasNext(); ) {
+ tmp.addAll(((Element) i.next()).getChunks());
+ }
+ return tmp;
+ }
+
+ // overriding some of the ArrayList-methods
+
+/**
+ * Adds a Chunk
, an Anchor
or another Phrase
+ * to this Phrase
.
+ *
+ * @param index index at which the specified element is to be inserted
+ * @param o an object of type Chunk
, Anchor
or Phrase
+ * @throws ClassCastException when you try to add something that isn't a Chunk
, Anchor
or Phrase
+ */
+
+ public void add(int index, Object o) {
+ if (o == null) return;
+ try {
+ Element element = (Element) o;
+ if (element.type() == Element.CHUNK) {
+ Chunk chunk = (Chunk) element;
+ if (!font.isStandardFont()) {
+ chunk.setFont(font.difference(chunk.font()));
+ }
+ super.add(index, chunk);
+ }
+ else if (element.type() == Element.PHRASE ||
+ element.type() == Element.ANCHOR ||
+ element.type() == Element.ANNOTATION ||
+ element.type() == Element.TABLE || // line added by David Freels
+ element.type() == Element.GRAPHIC) {
+ super.add(index, element);
+ }
+ else {
+ throw new ClassCastException(String.valueOf(element.type()));
+ }
+ }
+ catch(ClassCastException cce) {
+ throw new ClassCastException("Insertion of illegal Element: " + cce.getMessage());
+ }
+ }
+
+/**
+ * Adds a Chunk
, Anchor
or another Phrase
+ * to this Phrase
.
+ *
+ * @param o an object of type Chunk
, Anchor
or Phrase
+ * @return a boolean
+ * @throws ClassCastException when you try to add something that isn't a Chunk
, Anchor
or Phrase
+ */
+
+ public boolean add(Object o) {
+ if (o == null) return false;
+ if (o instanceof String) {
+ return super.add(new Chunk((String) o, font));
+ }
+ try {
+ Element element = (Element) o;
+ switch(element.type()) {
+ case Element.CHUNK:
+ return addChunk((Chunk) o);
+ case Element.PHRASE:
+ case Element.PARAGRAPH:
+ Phrase phrase = (Phrase) o;
+ boolean success = true;
+ Element e;
+ for (Iterator i = phrase.iterator(); i.hasNext(); ) {
+ e = (Element) i.next();
+ if (e instanceof Chunk) {
+ success &= addChunk((Chunk)e);
+ }
+ else {
+ success &= this.add(e);
+ }
+ }
+ return success;
+ case Element.ANCHOR:
+ return super.add(o);
+ case Element.ANNOTATION:
+ return super.add(o);
+ /* ssteward: dropped in 1.44
+ case Element.TABLE: // case added by David Freels
+ return super.add((Table) o);
+ case Element.PTABLE: // case added by mr. Karen Vardanyan
+ // This will only work for PDF!!! Not for RTF/HTML
+ return super.add((pdftk.com.lowagie.text.pdf.PdfPTable) o);
+ */
+ case Element.LIST:
+ return super.add(o);
+ /*
+ case Element.GRAPHIC: // suggested by Steven Balthazor
+ return super.add((Graphic) o);
+ */
+ default:
+ throw new ClassCastException(String.valueOf(element.type()));
+ }
+ }
+ catch(ClassCastException cce) {
+ throw new ClassCastException("Insertion of illegal Element: " + cce.getMessage());
+ }
+ }
+
+/**
+ * Adds a Chunk.
+ *
+ * This method is a hack to solve a problem I had with phrases that were split between chunks
+ * in the wrong place.
+ * @param chunk a Chunk to add to the Phrase
+ * @return true if adding the Chunk succeeded
+ */
+
+ private synchronized boolean addChunk(Chunk chunk) {
+ if (!font.isStandardFont()) {
+ chunk.setFont(font.difference(chunk.font()));
+ }
+ if (size() > 0 && !chunk.hasAttributes()) {
+ try {
+ Chunk previous = (Chunk) get(size() - 1);
+ if (!previous.hasAttributes() && previous.font().compareTo(chunk.font()) == 0 && !"".equals(previous.content().trim()) && !"".equals(chunk.content().trim())) {
+ previous.append(chunk.content());
+ return true;
+ }
+ }
+ catch(ClassCastException cce) {
+ }
+ }
+ return super.add(chunk);
+ }
+
+/**
+ * Adds a collection of Chunk
s
+ * to this Phrase
.
+ *
+ * @param collection a collection of Chunk
s, Anchor
s and Phrase
s.
+ * @return true
if the action succeeded, false
if not.
+ * @throws ClassCastException when you try to add something that isn't a Chunk
, Anchor
or Phrase
+ */
+
+ public boolean addAll(Collection collection) {
+ for (Iterator iterator = collection.iterator(); iterator.hasNext(); ) {
+ this.add(iterator.next());
+ }
+ return true;
+ }
+
+/**
+ * Adds a Object
to the Paragraph
.
+ *
+ * @param object the object to add.
+ */
+
+ protected void addSpecial(Object object) {
+ super.add(object);
+ }
+
+ // methods
+
+/**
+ * Sets the leading of this phrase.
+ *
+ * @param leading the new leading
+ */
+
+ public void setLeading(float leading) {
+ this.leading = leading;
+ }
+
+ // methods to retrieve information
+
+/**
+ * Checks is this Phrase
contains no or 1 empty Chunk
.
+ *
+ * @return false
if the Phrase
+ * contains more than one or more non-emptyChunk
s.
+ */
+
+ public boolean isEmpty() {
+ switch(size()) {
+ case 0:
+ return true;
+ case 1:
+ Element element = (Element) get(0);
+ if (element.type() == Element.CHUNK && ((Chunk) element).isEmpty()) {
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+ }
+
+/**
+ * Checks you if the leading of this phrase is defined.
+ *
+ * @return true if the leading is defined
+ */
+
+ public boolean leadingDefined() {
+ if (Float.isNaN(leading)) {
+ return false;
+ }
+ return true;
+ }
+
+/**
+ * Gets the leading of this phrase.
+ *
+ * @return the linespacing
+ */
+
+ public float leading() {
+ if (Float.isNaN(leading)) {
+ return font.leading(1.5f);
+ }
+ return leading;
+ }
+
+/**
+ * Gets the font of the first Chunk
that appears in this Phrase
.
+ *
+ * @return a Font
+ */
+
+ public Font font() {
+ return font;
+ }
+
+/**
+ * Checks if a given tag corresponds with this object.
+ *
+ * @param tag the given tag
+ * @return true if the tag corresponds
+ */
+
+ public static boolean isTag(String tag) {
+ return ElementTags.PHRASE.equals(tag);
+ }
+
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String, java.lang.String)
+ */
+ public void setMarkupAttribute(String name, String value) {
+ if (markupAttributes == null) markupAttributes = new Properties();
+ markupAttributes.put(name, value);
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+ */
+ public void setMarkupAttributes(Properties markupAttributes) {
+ this.markupAttributes = markupAttributes;
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+ */
+ public String getMarkupAttribute(String name) {
+ return (markupAttributes == null) ? null : String.valueOf(markupAttributes.get(name));
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+ */
+ public Set getMarkupAttributeNames() {
+ return Chunk.getKeySet(markupAttributes);
+ }
+
+/**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+ */
+ public Properties getMarkupAttributes() {
+ return markupAttributes;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/Rectangle.java pdftk-2.01/java/pdftk/com/lowagie/text/Rectangle.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/Rectangle.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/Rectangle.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,944 @@
+/*
+ * $Id: Rectangle.java,v 1.70 2005/08/09 14:07:29 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * A Rectangle
is the representation of a geometric figure.
+ *
+ * Rectangles support constant width borders using
+ * {@link #setBorderWidth(float)}and {@link #setBorder(int)}. They also
+ * support borders that vary in width/color on each side using methods like
+ * {@link #setBorderWidthLeft(float)}or
+ * {@link #setBorderColorLeft(java.awt.Color)}.
+ *
+ * @see Element
+ * @see Table
+ * @see Cell
+ * @see HeaderFooter
+ */
+
+public class Rectangle implements Element, MarkupAttributes {
+
+ // static membervariables (concerning the presence of borders)
+
+ /** This is the value that will be used as undefined . */
+ public static final int UNDEFINED = -1;
+
+ /** This represents one side of the border of the Rectangle
. */
+ public static final int TOP = 1;
+
+ /** This represents one side of the border of the Rectangle
. */
+ public static final int BOTTOM = 2;
+
+ /** This represents one side of the border of the Rectangle
. */
+ public static final int LEFT = 4;
+
+ /** This represents one side of the border of the Rectangle
. */
+ public static final int RIGHT = 8;
+
+ /** This represents a rectangle without borders. */
+ public static final int NO_BORDER = 0;
+
+ /** This represents a type of border. */
+ public static final int BOX = TOP + BOTTOM + LEFT + RIGHT;
+
+ // membervariables
+
+ /** the lower left x-coordinate. */
+ protected float llx;
+
+ /** the lower left y-coordinate. */
+ protected float lly;
+
+ /** the upper right x-coordinate. */
+ protected float urx;
+
+ /** the upper right y-coordinate. */
+ protected float ury;
+
+ /** This represents the status of the 4 sides of the rectangle. */
+ protected int border = UNDEFINED;
+
+ /** This is the width of the border around this rectangle. */
+ protected float borderWidth = UNDEFINED;
+
+ /** The color of the border of this rectangle. */
+ protected Color color = null;
+
+ /** The color of the left border of this rectangle. */
+ protected Color borderColorLeft = null;
+
+ /** The color of the right border of this rectangle. */
+ protected Color borderColorRight = null;
+
+ /** The color of the top border of this rectangle. */
+ protected Color borderColorTop = null;
+
+ /** The color of the bottom border of this rectangle. */
+ protected Color borderColorBottom = null;
+
+ /** The width of the left border of this rectangle. */
+ protected float borderWidthLeft = UNDEFINED;
+
+ /** The width of the right border of this rectangle. */
+ protected float borderWidthRight = UNDEFINED;
+
+ /** The width of the top border of this rectangle. */
+ protected float borderWidthTop = UNDEFINED;
+
+ /** The width of the bottom border of this rectangle. */
+ protected float borderWidthBottom = UNDEFINED;
+
+ /** Whether variable width borders are used. */
+ protected boolean useVariableBorders = false;
+
+ /** This is the color of the background of this rectangle. */
+ protected Color background = null;
+
+ /** This is the grayscale value of the background of this rectangle. */
+ protected float grayFill = 0;
+
+ protected int rotation = 0;
+
+ /** Contains extra markupAttributes */
+ protected Properties markupAttributes;
+
+ // constructors
+
+ /**
+ * Constructs a Rectangle
-object.
+ *
+ * @param llx
+ * lower left x
+ * @param lly
+ * lower left y
+ * @param urx
+ * upper right x
+ * @param ury
+ * upper right y
+ */
+
+ public Rectangle(float llx, float lly, float urx, float ury) {
+ this.llx = llx;
+ this.lly = lly;
+ this.urx = urx;
+ this.ury = ury;
+ }
+
+ /**
+ * Constructs a Rectangle
-object starting from the origin
+ * (0, 0).
+ *
+ * @param urx
+ * upper right x
+ * @param ury
+ * upper right y
+ */
+
+ public Rectangle(float urx, float ury) {
+ this(0, 0, urx, ury);
+ }
+
+ /**
+ * Constructs a Rectangle
-object.
+ *
+ * @param rect
+ * another Rectangle
+ */
+
+ public Rectangle(Rectangle rect) {
+ this(rect.llx, rect.lly, rect.urx, rect.ury);
+ cloneNonPositionParameters(rect);
+ }
+
+ /**
+ * Copies all of the parameters from a Rectangle
object
+ * except the position.
+ *
+ * @param rect
+ * Rectangle
to copy from
+ */
+
+ public void cloneNonPositionParameters(Rectangle rect) {
+ this.rotation = rect.rotation;
+ this.border = rect.border;
+ this.borderWidth = rect.borderWidth;
+ this.color = rect.color;
+ this.background = rect.background;
+ this.grayFill = rect.grayFill;
+ this.borderColorLeft = rect.borderColorLeft;
+ this.borderColorRight = rect.borderColorRight;
+ this.borderColorTop = rect.borderColorTop;
+ this.borderColorBottom = rect.borderColorBottom;
+ this.borderWidthLeft = rect.borderWidthLeft;
+ this.borderWidthRight = rect.borderWidthRight;
+ this.borderWidthTop = rect.borderWidthTop;
+ this.borderWidthBottom = rect.borderWidthBottom;
+ this.useVariableBorders = rect.useVariableBorders;
+ }
+
+ /**
+ * Copies all of the parameters from a Rectangle
object
+ * except the position.
+ *
+ * @param rect
+ * Rectangle
to copy from
+ */
+
+ public void softCloneNonPositionParameters(Rectangle rect) {
+ if (rect.rotation != 0)
+ this.rotation = rect.rotation;
+ if (rect.border != UNDEFINED)
+ this.border = rect.border;
+ if (rect.borderWidth != UNDEFINED)
+ this.borderWidth = rect.borderWidth;
+ if (rect.color != null)
+ this.color = rect.color;
+ if (rect.background != null)
+ this.background = rect.background;
+ if (rect.grayFill != 0)
+ this.grayFill = rect.grayFill;
+ if (rect.borderColorLeft != null)
+ this.borderColorLeft = rect.borderColorLeft;
+ if (rect.borderColorRight != null)
+ this.borderColorRight = rect.borderColorRight;
+ if (rect.borderColorTop != null)
+ this.borderColorTop = rect.borderColorTop;
+ if (rect.borderColorBottom != null)
+ this.borderColorBottom = rect.borderColorBottom;
+ if (rect.borderWidthLeft != UNDEFINED)
+ this.borderWidthLeft = rect.borderWidthLeft;
+ if (rect.borderWidthRight != UNDEFINED)
+ this.borderWidthRight = rect.borderWidthRight;
+ if (rect.borderWidthTop != UNDEFINED)
+ this.borderWidthTop = rect.borderWidthTop;
+ if (rect.borderWidthBottom != UNDEFINED)
+ this.borderWidthBottom = rect.borderWidthBottom;
+ if (useVariableBorders)
+ this.useVariableBorders = rect.useVariableBorders;
+ }
+
+ // implementation of the Element interface
+
+ /**
+ * Processes the element by adding it (or the different parts) to an
+ * ElementListener
.
+ *
+ * @param listener
+ * an ElementListener
+ * @return true
if the element was processed successfully
+ */
+
+ public boolean process(ElementListener listener) {
+ try {
+ return listener.add(this);
+ } catch (DocumentException de) {
+ return false;
+ }
+ }
+
+ /**
+ * Gets the type of the text element.
+ *
+ * @return a type
+ */
+
+ public int type() {
+ return Element.RECTANGLE;
+ }
+
+ /**
+ * Gets all the chunks in this element.
+ *
+ * @return an ArrayList
+ */
+ public ArrayList getChunks() {
+ return new ArrayList();
+ }
+
+ // methods
+
+ /**
+ * Switches lowerleft with upperright
+ */
+ public void normalize() {
+ if (llx > urx) {
+ float a = llx;
+ llx = urx;
+ urx = a;
+ }
+ if (lly > ury) {
+ float a = lly;
+ lly = ury;
+ ury = a;
+ }
+ }
+
+ /**
+ * Gets a Rectangle that is altered to fit on the page.
+ *
+ * @param top
+ * the top position
+ * @param bottom
+ * the bottom position
+ * @return a Rectangle
+ */
+
+ public Rectangle rectangle(float top, float bottom) {
+ Rectangle tmp = new Rectangle(this);
+ if (top() > top) {
+ tmp.setTop(top);
+ tmp.setBorder(border - (border & TOP));
+ }
+ if (bottom() < bottom) {
+ tmp.setBottom(bottom);
+ tmp.setBorder(border - (border & BOTTOM));
+ }
+ return tmp;
+ }
+
+ /**
+ * Swaps the values of urx and ury and of lly and llx in order to rotate the
+ * rectangle.
+ *
+ * @return a Rectangle
+ */
+
+ public Rectangle rotate() {
+ Rectangle rect = new Rectangle(lly, llx, ury, urx);
+ rect.rotation = rotation + 90;
+ rect.rotation %= 360;
+ return rect;
+ }
+
+ // methods to set the membervariables
+
+ /**
+ * Sets the lower left x-coordinate.
+ *
+ * @param value
+ * the new value
+ */
+
+ public void setLeft(float value) {
+ llx = value;
+ }
+
+ /**
+ * Sets the upper right x-coordinate.
+ *
+ * @param value
+ * the new value
+ */
+
+ public void setRight(float value) {
+ urx = value;
+ }
+
+ /**
+ * Sets the upper right y-coordinate.
+ *
+ * @param value
+ * the new value
+ */
+
+ public void setTop(float value) {
+ ury = value;
+ }
+
+ /**
+ * Sets the lower left y-coordinate.
+ *
+ * @param value
+ * the new value
+ */
+
+ public void setBottom(float value) {
+ lly = value;
+ }
+
+ /**
+ * Enables/Disables the border on the specified sides. The border is
+ * specified as an integer bitwise combination of the constants:
+ * LEFT, RIGHT, TOP, BOTTOM
.
+ *
+ * @see #enableBorderSide(int)
+ * @see #disableBorderSide(int)
+ * @param value
+ * the new value
+ */
+
+ public void setBorder(int value) {
+ border = value;
+ }
+
+ /**
+ * Enables the border on the specified side.
+ *
+ * @param side
+ * the side to enable. One of LEFT, RIGHT, TOP, BOTTOM
+ *
+ */
+ public void enableBorderSide(int side) {
+ if (border == UNDEFINED) {
+ border = 0;
+ }
+ border |= side;
+ }
+
+ /**
+ * Disables the border on the specified side.
+ *
+ * @param side
+ * the side to disable. One of LEFT, RIGHT, TOP, BOTTOM
+ *
+ */
+ public void disableBorderSide(int side) {
+ if (border == UNDEFINED) {
+ border = 0;
+ }
+ border &= ~side;
+ }
+
+ /**
+ * Sets the borderwidth of the table.
+ *
+ * @param value
+ * the new value
+ */
+
+ public void setBorderWidth(float value) {
+ borderWidth = value;
+ }
+
+ /**
+ * Sets the color of the border.
+ *
+ * @param value
+ * the new value
+ */
+
+ public void setBorderColor(Color value) {
+ color = value;
+ }
+
+ /**
+ * Sets the value of the border color
+ *
+ * @param value
+ * a color value
+ */
+ public void setBorderColorRight(Color value) {
+ borderColorRight = value;
+ }
+
+ /**
+ * Sets the value of the border color
+ *
+ * @param value
+ * a color value
+ */
+ public void setBorderColorLeft(Color value) {
+ borderColorLeft = value;
+ }
+
+ /**
+ * Sets the value of the border color
+ *
+ * @param value
+ * a color value
+ */
+ public void setBorderColorTop(Color value) {
+ borderColorTop = value;
+ }
+
+ /**
+ * Sets the value of the border color
+ *
+ * @param value
+ * a color value
+ */
+ public void setBorderColorBottom(Color value) {
+ borderColorBottom = value;
+ }
+
+ /**
+ * Sets the backgroundcolor of the rectangle.
+ *
+ * @param value
+ * the new value
+ */
+
+ public void setBackgroundColor(Color value) {
+ background = value;
+ }
+
+ /**
+ * Sets the grayscale of the rectangle.
+ *
+ * @param value
+ * the new value
+ */
+
+ public void setGrayFill(float value) {
+ if (value >= 0 && value <= 1.0) {
+ grayFill = value;
+ }
+ }
+
+ // methods to get the membervariables
+
+ /**
+ * Returns the lower left x-coordinate.
+ *
+ * @return the lower left x-coordinate
+ */
+
+ public float left() {
+ return llx;
+ }
+
+ /**
+ * Returns the upper right x-coordinate.
+ *
+ * @return the upper right x-coordinate
+ */
+
+ public float right() {
+ return urx;
+ }
+
+ /**
+ * Returns the upper right y-coordinate.
+ *
+ * @return the upper right y-coordinate
+ */
+
+ public float top() {
+ return ury;
+ }
+
+ /**
+ * Returns the lower left y-coordinate.
+ *
+ * @return the lower left y-coordinate
+ */
+
+ public float bottom() {
+ return lly;
+ }
+
+ /**
+ * Returns the lower left x-coordinate, considering a given margin.
+ *
+ * @param margin
+ * a margin
+ * @return the lower left x-coordinate
+ */
+
+ public float left(float margin) {
+ return llx + margin;
+ }
+
+ /**
+ * Returns the upper right x-coordinate, considering a given margin.
+ *
+ * @param margin
+ * a margin
+ * @return the upper right x-coordinate
+ */
+
+ public float right(float margin) {
+ return urx - margin;
+ }
+
+ /**
+ * Returns the upper right y-coordinate, considering a given margin.
+ *
+ * @param margin
+ * a margin
+ * @return the upper right y-coordinate
+ */
+
+ public float top(float margin) {
+ return ury - margin;
+ }
+
+ /**
+ * Returns the lower left y-coordinate, considering a given margin.
+ *
+ * @param margin
+ * a margin
+ * @return the lower left y-coordinate
+ */
+
+ public float bottom(float margin) {
+ return lly + margin;
+ }
+
+ /**
+ * Returns the width of the rectangle.
+ *
+ * @return a width
+ */
+
+ public float width() {
+ return urx - llx;
+ }
+
+ /**
+ * Returns the height of the rectangle.
+ *
+ * @return a height
+ */
+
+ public float height() {
+ return ury - lly;
+ }
+
+ /**
+ * Indicates if the table has borders.
+ *
+ * @return a boolean
+ */
+
+ public boolean hasBorders() {
+ return (border > 0)
+ && ((borderWidth > 0) || (borderWidthLeft > 0)
+ || (borderWidthRight > 0) || (borderWidthTop > 0) || (borderWidthBottom > 0));
+ }
+
+ /**
+ * Indicates if the table has a some type of border.
+ *
+ * @param type
+ * the type of border
+ * @return a boolean
+ */
+
+ public boolean hasBorder(int type) {
+ return border != UNDEFINED && (border & type) == type;
+ }
+
+ /**
+ * Returns the exact type of the border.
+ *
+ * @return a value
+ */
+
+ public int border() {
+ return border;
+ }
+
+ /**
+ * Gets the borderwidth.
+ *
+ * @return a value
+ */
+
+ public float borderWidth() {
+ return borderWidth;
+ }
+
+ /**
+ * Gets the color of the border.
+ *
+ * @return a value
+ */
+
+ public Color borderColor() {
+ return color;
+ }
+
+ /**
+ * Gets the backgroundcolor.
+ *
+ * @return a value
+ */
+
+ public Color backgroundColor() {
+ return background;
+ }
+
+ /**
+ * Gets the grayscale.
+ *
+ * @return a value
+ */
+
+ public float grayFill() {
+ return grayFill;
+ }
+
+ /**
+ * Gets the rotation of the rectangle
+ *
+ * @return a rotation value
+ */
+ public int getRotation() {
+ return rotation;
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String,
+ * java.lang.String)
+ */
+ public void setMarkupAttribute(String name, String value) {
+ if (markupAttributes == null)
+ markupAttributes = new Properties();
+ markupAttributes.put(name, value);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
+ */
+ public void setMarkupAttributes(Properties markupAttributes) {
+ this.markupAttributes = markupAttributes;
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
+ */
+ public String getMarkupAttribute(String name) {
+ return (markupAttributes == null) ? null : String
+ .valueOf(markupAttributes.get(name));
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
+ */
+ public Set getMarkupAttributeNames() {
+ return Chunk.getKeySet(markupAttributes);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.MarkupAttributes#getMarkupAttributes()
+ */
+ public Properties getMarkupAttributes() {
+ return markupAttributes;
+ }
+
+ /**
+ * Gets the color of a border.
+ *
+ * @return a color value
+ */
+ public Color getBorderColorLeft() {
+ return borderColorLeft;
+ }
+
+ /**
+ * Gets the color of a border.
+ *
+ * @return a color value
+ */
+ public Color getBorderColorRight() {
+ return borderColorRight;
+ }
+
+ /**
+ * Gets the color of a border.
+ *
+ * @return a color value
+ */
+ public Color getBorderColorTop() {
+ return borderColorTop;
+ }
+
+ /**
+ * Gets the color of a border.
+ *
+ * @return a color value
+ */
+ public Color getBorderColorBottom() {
+ return borderColorBottom;
+ }
+
+ /**
+ * Gets the width of a border.
+ *
+ * @return a width
+ */
+ public float getBorderWidthLeft() {
+ return getVariableBorderWidth(borderWidthLeft, LEFT);
+ }
+
+ /**
+ * Sets the width of a border
+ *
+ * @param borderWidthLeft
+ * a width
+ */
+ public void setBorderWidthLeft(float borderWidthLeft) {
+ this.borderWidthLeft = borderWidthLeft;
+ updateBorderBasedOnWidth(borderWidthLeft, LEFT);
+ }
+
+ /**
+ * Gets the width of a border.
+ *
+ * @return a width
+ */
+ public float getBorderWidthRight() {
+ return getVariableBorderWidth(borderWidthRight, RIGHT);
+ }
+
+ /**
+ * Sets the width of a border
+ *
+ * @param borderWidthRight
+ * a width
+ */
+ public void setBorderWidthRight(float borderWidthRight) {
+ this.borderWidthRight = borderWidthRight;
+ updateBorderBasedOnWidth(borderWidthRight, RIGHT);
+ }
+
+ /**
+ * Gets the width of a border.
+ *
+ * @return a width
+ */
+ public float getBorderWidthTop() {
+ return getVariableBorderWidth(borderWidthTop, TOP);
+ }
+
+ /**
+ * Sets the width of a border
+ *
+ * @param borderWidthTop
+ * a width
+ */
+ public void setBorderWidthTop(float borderWidthTop) {
+ this.borderWidthTop = borderWidthTop;
+ updateBorderBasedOnWidth(borderWidthTop, TOP);
+ }
+
+ /**
+ * Gets the width of a border.
+ *
+ * @return a width
+ */
+ public float getBorderWidthBottom() {
+ return getVariableBorderWidth(borderWidthBottom, BOTTOM);
+ }
+
+ /**
+ * Sets the width of a border
+ *
+ * @param borderWidthBottom
+ * a width
+ */
+ public void setBorderWidthBottom(float borderWidthBottom) {
+ this.borderWidthBottom = borderWidthBottom;
+ updateBorderBasedOnWidth(borderWidthBottom, BOTTOM);
+ }
+
+ /**
+ * Updates the border flag for a side based on the specified width. A width
+ * of 0 will disable the border on that side. Any other width enables it.
+ *
+ * @param width
+ * width of border
+ * @param side
+ * border side constant
+ */
+
+ private void updateBorderBasedOnWidth(float width, int side) {
+ useVariableBorders = true;
+ if (width > 0) {
+ enableBorderSide(side);
+ } else {
+ disableBorderSide(side);
+ }
+ }
+
+ private float getVariableBorderWidth(float variableWidthValue, int side) {
+ if ((border & side) != 0) {
+ return variableWidthValue != UNDEFINED ? variableWidthValue
+ : borderWidth;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Indicates whether variable width borders are being used. Returns true if
+ * setBorderWidthLeft, setBorderWidthRight, setBorderWidthTop, or
+ * setBorderWidthBottom
has been called.
+ *
+ * @return true if variable width borders are in use
+ *
+ */
+ public boolean isUseVariableBorders() {
+ return useVariableBorders;
+ }
+
+ /**
+ * Sets a parameter indicating if the rectangle has variable borders
+ *
+ * @param useVariableBorders
+ * indication if the rectangle has variable borders
+ */
+ public void setUseVariableBorders(boolean useVariableBorders) {
+ this.useVariableBorders = useVariableBorders;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer("Rectangle: ");
+ buf.append(width());
+ buf.append("x");
+ buf.append(height());
+ buf.append(" (rot: ");
+ buf.append(rotation);
+ buf.append(" degrees)");
+ return buf.toString();
+ }
+
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/SpecialSymbol.java pdftk-2.01/java/pdftk/com/lowagie/text/SpecialSymbol.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/SpecialSymbol.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/SpecialSymbol.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,204 @@
+/*
+ * $Id: SpecialSymbol.java,v 1.1 2004/12/23 09:14:47 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+/**
+ * This class contains the symbols that correspond with special symbols.
+ *
+ * When you construct a Phrase
with Phrase.getInstance using a String
,
+ * this String
can contain special Symbols. These are characters with an int value
+ * between 913 and 937 (except 930) and between 945 and 969. With this class the value of the
+ * corresponding character of the Font Symbol, can be retrieved.
+ *
+ * @see Phrase
+ *
+ * @author Bruno Lowagie
+ * @author Evelyne De Cordier
+ */
+
+public class SpecialSymbol {
+
+/**
+ * Returns the first occurrence of a special symbol in a String
.
+ *
+ * @param string a String
+ * @return an index of -1 if no special symbol was found
+ */
+
+ public static int index(String string) {
+ int length = string.length();
+ for (int i = 0; i < length; i++) {
+ if (getCorrespondingSymbol(string.charAt(i)) != ' ') {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+/**
+ * Gets a chunk with a symbol character.
+ * @param c a character that has to be changed into a symbol
+ * @param font Font if there is no SYMBOL character corresponding with c
+ * @return a SYMBOL version of a character
+ */
+
+ public static Chunk get(char c, Font font) {
+ char greek = SpecialSymbol.getCorrespondingSymbol(c);
+ if (greek == ' ') {
+ return new Chunk(String.valueOf(c), font);
+ }
+ Font symbol = new Font(Font.SYMBOL, font.size(), font.style(), font.color());
+ String s = String.valueOf(greek);
+ return new Chunk(s, symbol);
+ }
+
+/**
+ * Looks for the corresponding symbol in the font Symbol.
+ *
+ * @param c the original ASCII-char
+ * @return the corresponding symbol in font Symbol
+ */
+
+ public static char getCorrespondingSymbol(char c) {
+ switch(c) {
+ case 913:
+ return 'A'; // ALFA
+ case 914:
+ return 'B'; // BETA
+ case 915:
+ return 'G'; // GAMMA
+ case 916:
+ return 'D'; // DELTA
+ case 917:
+ return 'E'; // EPSILON
+ case 918:
+ return 'Z'; // ZETA
+ case 919:
+ return 'H'; // ETA
+ case 920:
+ return 'Q'; // THETA
+ case 921:
+ return 'I'; // IOTA
+ case 922:
+ return 'K'; // KAPPA
+ case 923:
+ return 'L'; // LAMBDA
+ case 924:
+ return 'M'; // MU
+ case 925:
+ return 'N'; // NU
+ case 926:
+ return 'X'; // XI
+ case 927:
+ return 'O'; // OMICRON
+ case 928:
+ return 'P'; // PI
+ case 929:
+ return 'R'; // RHO
+ case 931:
+ return 'S'; // SIGMA
+ case 932:
+ return 'T'; // TAU
+ case 933:
+ return 'U'; // UPSILON
+ case 934:
+ return 'J'; // PHI
+ case 935:
+ return 'C'; // CHI
+ case 936:
+ return 'Y'; // PSI
+ case 937:
+ return 'W'; // OMEGA
+ case 945:
+ return 'a'; // alfa
+ case 946:
+ return 'b'; // beta
+ case 947:
+ return 'g'; // gamma
+ case 948:
+ return 'd'; // delta
+ case 949:
+ return 'e'; // epsilon
+ case 950:
+ return 'z'; // zeta
+ case 951:
+ return 'h'; // eta
+ case 952:
+ return 'q'; // theta
+ case 953:
+ return 'i'; // iota
+ case 954:
+ return 'k'; // kappa
+ case 955:
+ return 'l'; // lambda
+ case 956:
+ return 'm'; // mu
+ case 957:
+ return 'n'; // nu
+ case 958:
+ return 'x'; // xi
+ case 959:
+ return 'o'; // omicron
+ case 960:
+ return 'p'; // pi
+ case 961:
+ return 'r'; // rho
+ case 962:
+ return 's'; // sigma
+ case 963:
+ return 's'; // sigma
+ case 964:
+ return 't'; // tau
+ case 965:
+ return 'u'; // upsilon
+ case 966:
+ return 'j'; // phi
+ case 967:
+ return 'c'; // chi
+ case 968:
+ return 'y'; // psi
+ case 969:
+ return 'w'; // omega
+ default:
+ return ' ';
+ }
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/SplitCharacter.java pdftk-2.01/java/pdftk/com/lowagie/text/SplitCharacter.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/SplitCharacter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/SplitCharacter.java 2013-06-06 07:32:04.000000000 +0000
@@ -0,0 +1,88 @@
+/*
+ * $Id: SplitCharacter.java,v 1.12 2002/06/20 13:30:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import pdftk.com.lowagie.text.pdf.PdfChunk;
+
+/** Interface for customizing the split character.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+
+public interface SplitCharacter {
+
+ /**
+ * Returns true
if the character can split a line. The splitting implementation
+ * is free to look ahead or look behind characters to make a decision.
+ *
+ * The default implementation is:
+ *
+ *
+ * public boolean isSplitCharacter(int start, int current, int end, char[] cc, PdfChunk[] ck) {
+ * char c;
+ * if (ck == null)
+ * c = cc[current];
+ * else
+ * c = ck[Math.min(current, ck.length - 1)].getUnicodeEquivalent(cc[current]);
+ * if (c <= ' ' || c == '-') {
+ * return true;
+ * }
+ * if (c < 0x2e80)
+ * return false;
+ * return ((c >= 0x2e80 && c < 0xd7a0)
+ * || (c >= 0xf900 && c < 0xfb00)
+ * || (c >= 0xfe30 && c < 0xfe50)
+ * || (c >= 0xff61 && c < 0xffa0));
+ * }
+ *
+ * @param start the lower limit of cc
inclusive
+ * @param current the pointer to the character in cc
+ * @param end the upper limit of cc
exclusive
+ * @param cc an array of characters at least end
sized
+ * @param ck an array of PdfChunk
. The main use is to be able to call
+ * {@link PdfChunk#getUnicodeEquivalent(char)}. It may be null
+ * or shorter than end
. If null
no convertion takes place.
+ * If shorter than end
the last element is used
+ * @return true
if the character(s) can split a line
+ */
+
+ public boolean isSplitCharacter(int start, int current, int end, char cc[], PdfChunk ck[]);
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/StringCompare.java pdftk-2.01/java/pdftk/com/lowagie/text/StringCompare.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/StringCompare.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/StringCompare.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,67 @@
+/*
+ * $Id: StringCompare.java,v 1.22 2002/07/09 10:41:40 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * Copyright (c) 2000 Volker Richert
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+import java.util.Comparator;
+
+/**
+ * This class was used in the 1.1-version of iText (by Volker Richert).
+ * Paulo Soares suggested I should add it to the original library, so
+ * that in the future it would be easier to port it to the JDK1.1.x.
+ */
+
+public class StringCompare implements Comparator {
+
+/**
+ * Compares 2 objects.
+ *
+ * @param o1 a first object
+ * @param o2 a second object
+ * @return a value
+ * @throws ClassCastException if the objects aren't Strings
+ */
+
+ public int compare(Object o1, Object o2) {
+ return ((String)o1).compareTo((String)o2);
+ }
+
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/TextElementArray.java pdftk-2.01/java/pdftk/com/lowagie/text/TextElementArray.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/TextElementArray.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/TextElementArray.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,65 @@
+/*
+ * $Id: TextElementArray.java,v 1.27 2002/06/20 13:30:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright (c) 1999, 2000, 2001, 2002 Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text;
+
+/**
+ * Interface for a text element to which other objects can be added.
+ *
+ * @see Phrase
+ * @see Paragraph
+ * @see Section
+ * @see ListItem
+ * @see Chapter
+ * @see Anchor
+ * @see Cell
+ */
+
+public interface TextElementArray extends Element {
+
+ /**
+ * Adds an object to the TextElementArray
.
+ *
+ * @param o an object that has to be added
+ * @return true
if the addition succeeded; false
otherwise
+ */
+
+ public boolean add(Object o);
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/exceptions/BadPasswordException.java pdftk-2.01/java/pdftk/com/lowagie/text/exceptions/BadPasswordException.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/exceptions/BadPasswordException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/exceptions/BadPasswordException.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,60 @@
+/*
+ * $Id$
+ *
+ * Copyright 2007 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.exceptions;
+
+import java.io.IOException;
+
+/**
+ * Typed exception used when opening an existing PDF document.
+ * Gets thrown when the document isn't a valid PDF document.
+ * @since 2.1.5 It was written for iText 2.0.8, but moved to another package
+ */
+public class BadPasswordException extends IOException {
+
+ /** Serial Version UID. */
+ private static final long serialVersionUID = -4333706268155063964L;
+
+ /**
+ * Creates an exception saying the user password was incorrect.
+ */
+ public BadPasswordException(String message) {
+ super(message);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/exceptions/IllegalPdfSyntaxException.java pdftk-2.01/java/pdftk/com/lowagie/text/exceptions/IllegalPdfSyntaxException.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/exceptions/IllegalPdfSyntaxException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/exceptions/IllegalPdfSyntaxException.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * Copyright 2009 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2009 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2009 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.exceptions;
+
+/**
+ * Typed exception used when creating PDF syntax that isn't valid.
+ * @since 2.1.6
+ */
+public class IllegalPdfSyntaxException extends IllegalArgumentException {
+
+ /** Serial version ID */
+ private static final long serialVersionUID = -643024246596031671L;
+
+ /**
+ * Creates an exception saying the PDF syntax isn't correct.
+ * @param message some extra info about the exception
+ */
+ public IllegalPdfSyntaxException(String message) {
+ super(message);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/exceptions/InvalidPdfException.java pdftk-2.01/java/pdftk/com/lowagie/text/exceptions/InvalidPdfException.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/exceptions/InvalidPdfException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/exceptions/InvalidPdfException.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,61 @@
+/*
+ * $Id$
+ *
+ * Copyright 2009 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2009 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2009 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.exceptions;
+
+import java.io.IOException;
+
+/**
+ * Typed exception used when opening an existing PDF document.
+ * Gets thrown when the document isn't a valid PDF document.
+ * @since 2.1.5
+ */
+public class InvalidPdfException extends IOException {
+
+ /** a serial version UID */
+ private static final long serialVersionUID = -2319614911517026938L;
+
+ /**
+ * Creates an instance of a NoPdfException.
+ * @param message the reason why the document isn't a PDF document according to iText.
+ */
+ public InvalidPdfException(String message) {
+ super(message);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/exceptions/UnsupportedPdfException.java pdftk-2.01/java/pdftk/com/lowagie/text/exceptions/UnsupportedPdfException.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/exceptions/UnsupportedPdfException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/exceptions/UnsupportedPdfException.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,62 @@
+/*
+ * $Id$
+ *
+ * Copyright 2009 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2009 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2009 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.exceptions;
+/**
+ * Typed exception used when opening an existing PDF document.
+ * Gets thrown when the document isn't a valid PDF document according to iText,
+ * but it's different from the InvalidPdfException in the sense that it may
+ * be an iText limitation (most of the times it isn't but you might have
+ * bumped into something that has been added to the PDF specs, but that isn't
+ * supported in iText yet).
+ * @since 2.1.5
+ */
+public class UnsupportedPdfException extends InvalidPdfException {
+
+ /** a serial version UID */
+ private static final long serialVersionUID = 2180764250839096628L;
+
+ /**
+ * Creates an instance of an UnsupportedPdfException.
+ * @param message the reason why the document isn't a PDF document according to iText.
+ */
+ public UnsupportedPdfException(String message) {
+ super(message);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/markup/MarkupParser.java pdftk-2.01/java/pdftk/com/lowagie/text/markup/MarkupParser.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/markup/MarkupParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/markup/MarkupParser.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,733 @@
+/*
+ * $Id: MarkupParser.java,v 1.53 2005/05/09 08:40:41 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.markup;
+
+import java.awt.Color;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import pdftk.com.lowagie.text.Element;
+import pdftk.com.lowagie.text.ExceptionConverter;
+import pdftk.com.lowagie.text.Font;
+import pdftk.com.lowagie.text.FontFactory;
+import pdftk.com.lowagie.text.ListItem;
+import pdftk.com.lowagie.text.Paragraph;
+import pdftk.com.lowagie.text.Phrase;
+import pdftk.com.lowagie.text.Rectangle;
+// import pdftk.com.lowagie.text.SimpleCell; ssteward: dropped in 1.44
+// import pdftk.com.lowagie.text.SimpleTable; ssteward: dropped in 1.44
+
+/**
+ * This class is a HashMap that contains selectors (String) and styles (a
+ * Properties object). Given a tag and its attributes (id/class), this class can
+ * return an iText object with the according style.
+ *
+ * @author blowagie
+ */
+public class MarkupParser extends HashMap {
+ /**
+ * HashMap with styles for each known combination of tag/id/class. The key
+ * is a String-combination, the value a Properties object.
+ */
+ protected HashMap stylecache = new HashMap();
+
+ /**
+ * HashMap with fonts for each known combination of tag/id/class. The key is
+ * the same String-combination used for the stylecache.
+ */
+ protected HashMap fontcache = new HashMap();
+
+ // processing CSS
+
+ /**
+ * Creates new MarkupParser
+ *
+ * @param file
+ * the path to a CSS file.
+ */
+ public MarkupParser(String file) {
+ super();
+ try {
+ FileReader reader = new FileReader(file);
+ BufferedReader br = new BufferedReader(reader);
+ StringBuffer buf = new StringBuffer();
+ String line;
+ while ((line = br.readLine()) != null) {
+ buf.append(line.trim());
+ }
+ String string = buf.toString();
+ string = removeComment(string, "/*", "*/");
+ StringTokenizer tokenizer = new StringTokenizer(string, "}");
+ String tmp;
+ int pos;
+ String selector;
+ String attributes;
+ while (tokenizer.hasMoreTokens()) {
+ tmp = tokenizer.nextToken();
+ pos = tmp.indexOf("{");
+ if (pos > 0) {
+ selector = tmp.substring(0, pos).trim();
+ attributes = tmp.substring(pos + 1).trim();
+ if (attributes.endsWith("}"))
+ attributes = attributes.substring(0, attributes
+ .length() - 1);
+ put(selector, parseAttributes(attributes));
+ }
+ }
+ } catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ * Removes the comments sections of a String.
+ *
+ * @param string
+ * the original String
+ * @param startComment
+ * the String that marks the start of a Comment section
+ * @param endComment
+ * the String that marks the end of a Comment section.
+ * @return the String stripped of its comment section
+ */
+ public static String removeComment(String string, String startComment,
+ String endComment) {
+ StringBuffer result = new StringBuffer();
+ int pos = 0;
+ int end = endComment.length();
+ int start = string.indexOf(startComment, pos);
+ while (start > -1) {
+ result.append(string.substring(pos, start));
+ pos = string.indexOf(endComment, start) + end;
+ start = string.indexOf(startComment, pos);
+ }
+ result.append(string.substring(pos));
+ return result.toString();
+ }
+
+ /**
+ * This method parses a String with attributes and returns a Properties
+ * object.
+ *
+ * @param string
+ * a String of this form: 'key1="value1"; key2="value2";...
+ * keyN="valueN" '
+ * @return a Properties object
+ */
+ public static Properties parseAttributes(String string) {
+ Properties result = new Properties();
+ if (string == null)
+ return result;
+ StringTokenizer keyValuePairs = new StringTokenizer(string, ";");
+ StringTokenizer keyValuePair;
+ String key;
+ String value;
+ while (keyValuePairs.hasMoreTokens()) {
+ keyValuePair = new StringTokenizer(keyValuePairs.nextToken(), ":");
+ if (keyValuePair.hasMoreTokens())
+ key = keyValuePair.nextToken().trim();
+ else
+ continue;
+ if (keyValuePair.hasMoreTokens())
+ value = keyValuePair.nextToken().trim();
+ else
+ continue;
+ if (value.startsWith("\""))
+ value = value.substring(1);
+ if (value.endsWith("\""))
+ value = value.substring(0, value.length() - 1);
+ result.setProperty(key, value);
+ }
+ return result;
+ }
+
+ // reading attributevalues
+
+ /**
+ * Parses a length.
+ *
+ * @param string
+ * a length in the form of an optional + or -, followed by a
+ * number and a unit.
+ * @return a float
+ */
+
+ public static float parseLength(String string) {
+ int pos = 0;
+ int length = string.length();
+ boolean ok = true;
+ while (ok && pos < length) {
+ switch (string.charAt(pos)) {
+ case '+':
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '.':
+ pos++;
+ break;
+ default:
+ ok = false;
+ }
+ }
+ if (pos == 0)
+ return 0f;
+ if (pos == length)
+ return Float.valueOf(string + "f").floatValue();
+ float f = Float.valueOf(string.substring(0, pos) + "f").floatValue();
+ string = string.substring(pos);
+ // inches
+ if (string.startsWith("in")) {
+ return f * 72f;
+ }
+ // centimeters
+ if (string.startsWith("cm")) {
+ return (f / 2.54f) * 72f;
+ }
+ // millimeters
+ if (string.startsWith("mm")) {
+ return (f / 25.4f) * 72f;
+ }
+ // picas
+ if (string.startsWith("pc")) {
+ return f * 12f;
+ }
+ // default: we assume the length was measured in points
+ return f;
+ }
+
+ /**
+ * Converts a Color
into a HTML representation of this
+ * Color
.
+ *
+ * @param color
+ * the Color
that has to be converted.
+ * @return the HTML representation of this Color
+ */
+
+ public static Color decodeColor(String color) {
+ int red = 0;
+ int green = 0;
+ int blue = 0;
+ try {
+ red = Integer.parseInt(color.substring(1, 3), 16);
+ green = Integer.parseInt(color.substring(3, 5), 16);
+ blue = Integer.parseInt(color.substring(5), 16);
+ } catch (Exception sioobe) {
+ // empty on purpose
+ }
+ return new Color(red, green, blue);
+ }
+
+ // helper methods
+
+ /**
+ * Generates a key for an tag/id/class combination and adds the style
+ * attributes to the stylecache.
+ *
+ * @param attributes
+ * a Properties object with the tagname and the attributes of the
+ * tag.
+ * @return a key
+ */
+ private String getKey(Properties attributes) {
+ String tag = attributes.getProperty(MarkupTags.ITEXT_TAG);
+ String id = attributes.getProperty(MarkupTags.HTML_ATTR_CSS_ID);
+ String cl = attributes.getProperty(MarkupTags.HTML_ATTR_CSS_CLASS);
+ if (id == null) {
+ id = "";
+ } else {
+ id = "#" + id;
+ }
+ if (cl == null) {
+ cl = "";
+ } else {
+ cl = "." + cl;
+ }
+ String key = tag + id + cl;
+ if (!stylecache.containsKey(key) && key.length() > 0) {
+ Properties props = new Properties();
+ Properties tagprops = (Properties) get(tag);
+ Properties idprops = (Properties) get(id);
+ Properties clprops = (Properties) get(cl);
+ Properties tagidprops = (Properties) get(tag + id);
+ Properties tagclprops = (Properties) get(tag + cl);
+ if (tagprops != null)
+ props.putAll(tagprops);
+ if (idprops != null)
+ props.putAll(idprops);
+ if (clprops != null)
+ props.putAll(clprops);
+ if (tagidprops != null)
+ props.putAll(tagidprops);
+ if (tagclprops != null)
+ props.putAll(tagclprops);
+ stylecache.put(key, props);
+ }
+ return key;
+ }
+
+ // getting the objects based on the tag and its attributes
+
+ /**
+ * Returns pagebreak information.
+ *
+ * @param attributes
+ * @return true if a page break is needed before the tag
+ */
+ public boolean getPageBreakBefore(Properties attributes) {
+ String key = getKey(attributes);
+ Properties styleattributes = (Properties) stylecache.get(key);
+ if (styleattributes != null
+ && MarkupTags.CSS_VALUE_ALWAYS.equals(styleattributes
+ .getProperty(MarkupTags.CSS_KEY_PAGE_BREAK_BEFORE))) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns pagebreak information.
+ *
+ * @param attributes
+ * @return true if a page break is needed after the tag
+ */
+ public boolean getPageBreakAfter(Properties attributes) {
+ String key = getKey(attributes);
+ Properties styleattributes = (Properties) stylecache.get(key);
+ if (styleattributes != null
+ && MarkupTags.CSS_VALUE_ALWAYS.equals(styleattributes
+ .getProperty(MarkupTags.CSS_KEY_PAGE_BREAK_AFTER))) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns an object based on a tag and its attributes.
+ *
+ * @param attributes
+ * a Properties object with the tagname and the attributes of the
+ * tag.
+ * @return an iText object
+ */
+ public Element getObject(Properties attributes) {
+ String key = getKey(attributes);
+ Properties styleattributes = (Properties) stylecache.get(key);
+ if (styleattributes != null
+ && MarkupTags.CSS_VALUE_HIDDEN.equals(styleattributes
+ .get(MarkupTags.CSS_KEY_VISIBILITY))) {
+ return null;
+ }
+ String display = styleattributes
+ .getProperty(MarkupTags.CSS_KEY_DISPLAY);
+ Element element = null;
+ if (MarkupTags.CSS_VALUE_INLINE.equals(display)) {
+ element = retrievePhrase(getFont(attributes), styleattributes);
+ } else if (MarkupTags.CSS_VALUE_BLOCK.equals(display)) {
+ element = retrieveParagraph(getFont(attributes), styleattributes);
+ } else if (MarkupTags.CSS_VALUE_LISTITEM.equals(display)) {
+ element = retrieveListItem(getFont(attributes), styleattributes);
+ } /* ssteward: dropped in pdftk 1.44:
+ else if (MarkupTags.CSS_VALUE_TABLECELL.equals(display)) {
+ element = retrieveTableCell(attributes, styleattributes);
+ } else if (MarkupTags.CSS_VALUE_TABLEROW.equals(display)) {
+ element = retrieveTableRow(attributes, styleattributes);
+ } else if (MarkupTags.CSS_VALUE_TABLE.equals(display)) {
+ element = retrieveTable(attributes, styleattributes);
+ } */
+ return element;
+ }
+
+ /**
+ * Returns a font based on the ID and CLASS attributes of a tag.
+ *
+ * @param attributes
+ * a Properties object with the tagname and the attributes of the
+ * tag.
+ * @return an iText Font;
+ */
+ public Font getFont(Properties attributes) {
+ String key = getKey(attributes);
+ Font f = (Font) fontcache.get(key);
+ if (f != null) {
+ return f;
+ } else {
+ Properties styleattributes = (Properties) stylecache.get(key);
+ f = retrieveFont(styleattributes);
+ fontcache.put(key, f);
+ }
+ return f;
+ }
+
+ /**
+ * Returns a rectangle based on the width and height attributes of a tag,
+ * can be overridden by the ID and CLASS attributes.
+ *
+ * @param attrs
+ * the attributes that came with the tag
+ * @return an iText Rectangle object
+ */
+ public Rectangle getRectangle(Properties attrs) {
+ String width = null;
+ String height = null;
+ String key = getKey(attrs);
+ Properties styleattributes = (Properties) stylecache.get(key);
+ if (styleattributes != null) {
+ width = styleattributes.getProperty(MarkupTags.HTML_ATTR_WIDTH);
+ height = styleattributes.getProperty(MarkupTags.HTML_ATTR_HEIGHT);
+ }
+ if (width == null)
+ width = attrs.getProperty(MarkupTags.HTML_ATTR_WIDTH);
+ if (height == null)
+ height = attrs.getProperty(MarkupTags.HTML_ATTR_HEIGHT);
+ if (width == null || height == null)
+ return null;
+ return new Rectangle(parseLength(width), parseLength(height));
+ }
+
+ // retrieving objects based on the styleAttributes
+
+ /**
+ * Retrieves a Phrase based on some style attributes.
+ *
+ * @param font
+ * @param styleattributes
+ * a Properties object containing keys and values
+ * @return an iText Phrase object
+ */
+ public Element retrievePhrase(Font font, Properties styleattributes) {
+ Phrase p = new Phrase("", font);
+ if (styleattributes == null)
+ return p;
+ String leading = styleattributes
+ .getProperty(MarkupTags.CSS_KEY_LINEHEIGHT);
+ if (leading != null) {
+ if (leading.endsWith("%")) {
+ p.setLeading(p.font().size() * (parseLength(leading) / 100f));
+ } else {
+ p.setLeading(parseLength(leading));
+ }
+ }
+ return p;
+ }
+
+ /**
+ * Retrieves a Paragraph based on some style attributes.
+ *
+ * @param font
+ * @param styleattributes
+ * a Properties object containing keys and values
+ * @return an iText Paragraph object
+ */
+ public Element retrieveParagraph(Font font, Properties styleattributes) {
+ Paragraph p = new Paragraph((Phrase) retrievePhrase(font,
+ styleattributes));
+ if (styleattributes == null)
+ return p;
+ String margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGIN);
+ float f;
+ if (margin != null) {
+ f = parseLength(margin);
+ p.setIndentationLeft(f);
+ p.setIndentationRight(f);
+ p.setSpacingBefore(f);
+ p.setSpacingAfter(f);
+ }
+ margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINLEFT);
+ if (margin != null) {
+ f = parseLength(margin);
+ p.setIndentationLeft(f);
+ }
+ margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINRIGHT);
+ if (margin != null) {
+ f = parseLength(margin);
+ p.setIndentationRight(f);
+ }
+ margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINTOP);
+ if (margin != null) {
+ f = parseLength(margin);
+ p.setSpacingBefore(f);
+ }
+ margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINBOTTOM);
+ if (margin != null) {
+ f = parseLength(margin);
+ p.setSpacingAfter(f);
+ }
+ String align = styleattributes
+ .getProperty(MarkupTags.CSS_KEY_TEXTALIGN);
+ if (MarkupTags.CSS_VALUE_TEXTALIGNLEFT.equals(align)) {
+ p.setAlignment(Element.ALIGN_LEFT);
+ } else if (MarkupTags.CSS_VALUE_TEXTALIGNRIGHT.equals(align)) {
+ p.setAlignment(Element.ALIGN_RIGHT);
+ } else if (MarkupTags.CSS_VALUE_TEXTALIGNCENTER.equals(align)) {
+ p.setAlignment(Element.ALIGN_CENTER);
+ } else if (MarkupTags.CSS_VALUE_TEXTALIGNJUSTIFY.equals(align)) {
+ p.setAlignment(Element.ALIGN_JUSTIFIED);
+ }
+ return p;
+ }
+
+ /**
+ * Gets a table based on the styleattributes.
+ *
+ * @param attributes
+ * @param styleattributes
+ * @return an iText Table
+ */
+ /* ssteward: dropped in 1.44
+ private Element retrieveTable(Properties attributes,
+ Properties styleattributes) {
+ SimpleTable table = new SimpleTable();
+ applyBordersColors(table, attributes, styleattributes);
+ return table;
+ }
+ */
+
+ /**
+ * Returns a Cell based on the styleattributes.
+ *
+ * @param attributes
+ * @param styleattributes
+ * @return an iText Cell
+ */
+ /* ssteward: dropped in 1.44
+ private Element retrieveTableRow(Properties attributes,
+ Properties styleattributes) {
+ SimpleCell row = new SimpleCell(SimpleCell.ROW);
+ applyBordersColors(row, attributes, styleattributes);
+ String width = null;
+ if (attributes != null)
+ width = attributes.getProperty(MarkupTags.HTML_ATTR_WIDTH);
+ if (width == null)
+ width = styleattributes.getProperty(MarkupTags.HTML_ATTR_WIDTH);
+ if (width != null) {
+ if (width.endsWith("%")) {
+ row.setWidthpercentage(parseLength(width));
+ } else {
+ row.setWidth(parseLength(width));
+ }
+ }
+ String margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGIN);
+ float f;
+ if (margin != null) {
+ f = parseLength(margin);
+ row.setSpacing(f);
+ }
+ margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINLEFT);
+ if (margin != null) {
+ f = parseLength(margin);
+ row.setSpacing_left(f);
+ }
+ margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINRIGHT);
+ if (margin != null) {
+ f = parseLength(margin);
+ row.setSpacing_right(f);
+ }
+ margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINTOP);
+ if (margin != null) {
+ f = parseLength(margin);
+ row.setSpacing_top(f);
+ }
+ margin = styleattributes.getProperty(MarkupTags.CSS_KEY_MARGINBOTTOM);
+ if (margin != null) {
+ f = parseLength(margin);
+ row.setSpacing_bottom(f);
+ }
+ String padding = styleattributes.getProperty(MarkupTags.CSS_KEY_PADDING);
+ if (padding != null) {
+ f = parseLength(padding);
+ row.setPadding(f);
+ }
+ padding = styleattributes.getProperty(MarkupTags.CSS_KEY_PADDINGLEFT);
+ if (padding != null) {
+ f = parseLength(padding);
+ row.setSpacing_left(f);
+ }
+ padding = styleattributes.getProperty(MarkupTags.CSS_KEY_PADDINGRIGHT);
+ if (padding != null) {
+ f = parseLength(padding);
+ row.setSpacing_right(f);
+ }
+ padding = styleattributes.getProperty(MarkupTags.CSS_KEY_PADDINGTOP);
+ if (padding != null) {
+ f = parseLength(padding);
+ row.setSpacing_top(f);
+ }
+ padding = styleattributes.getProperty(MarkupTags.CSS_KEY_PADDINGBOTTOM);
+ if (padding != null) {
+ f = parseLength(padding);
+ row.setSpacing_bottom(f);
+ }
+ return row;
+ }
+ */
+
+ /**
+ * Returns a Cell based on the styleattributes.
+ *
+ * @param attributes
+ * @param styleattributes
+ * @return an iText Cell
+ */
+ /* ssteward: dropped in 1.44
+ private Element retrieveTableCell(Properties attributes,
+ Properties styleattributes) {
+ SimpleCell cell = (SimpleCell) retrieveTableRow(attributes,
+ styleattributes);
+ cell.setCellgroup(false);
+ return cell;
+ }
+ */
+
+ /**
+ * Returns a ListItem based on the styleattributes.
+ *
+ * @param font
+ * @param styleattributes
+ * @return an iText ListItem
+ */
+ private Element retrieveListItem(Font font, Properties styleattributes) {
+ ListItem li = new ListItem();
+ return li;
+ }
+
+ /**
+ * Applies colors to a Rectangle object.
+ * @param rect
+ * @param attributes
+ * @param styleattributes
+ */
+ private void applyBordersColors(Rectangle rect, Properties attributes, Properties styleattributes) {
+ String s = styleattributes.getProperty(MarkupTags.CSS_KEY_BORDERWIDTH);
+ float f;
+ if (s != null) {
+ f = parseLength(s);
+ rect.setBorderWidth(f);
+ }
+ s = styleattributes.getProperty(MarkupTags.CSS_KEY_BORDERWIDTHLEFT);
+ if (s != null) {
+ f = parseLength(s);
+ rect.setBorderWidthLeft(f);
+ }
+ s = styleattributes.getProperty(MarkupTags.CSS_KEY_BORDERWIDTHRIGHT);
+ if (s != null) {
+ f = parseLength(s);
+ rect.setBorderWidthRight(f);
+ }
+ s = styleattributes.getProperty(MarkupTags.CSS_KEY_BORDERWIDTHTOP);
+ if (s != null) {
+ f = parseLength(s);
+ rect.setBorderWidthTop(f);
+ }
+ s = styleattributes.getProperty(MarkupTags.CSS_KEY_BORDERWIDTHBOTTOM);
+ if (s != null) {
+ f = parseLength(s);
+ rect.setBorderWidthBottom(f);
+ }
+ s = styleattributes.getProperty(MarkupTags.CSS_KEY_BORDERCOLOR);
+ if (s != null) {
+ rect.setBorderColor(decodeColor(s));
+ }
+ }
+
+ /**
+ * Retrieves a font from the FontFactory based on some style attributes.
+ * Looks for the font-family, font-size, font-weight, font-style and color.
+ * Takes the default encoding and embedded value.
+ *
+ * @param styleAttributes
+ * a Properties object containing keys and values
+ * @return an iText Font object
+ */
+
+ public Font retrieveFont(Properties styleAttributes) {
+ String fontname = null;
+ String encoding = FontFactory.defaultEncoding;
+ boolean embedded = FontFactory.defaultEmbedding;
+ float size = Font.UNDEFINED;
+ int style = Font.NORMAL;
+ Color color = null;
+ String value = (String) styleAttributes
+ .get(MarkupTags.CSS_KEY_FONTFAMILY);
+ if (value != null) {
+ if (value.indexOf(",") == -1) {
+ fontname = value.trim();
+ } else {
+ String tmp;
+ while (value.indexOf(",") != -1) {
+ tmp = value.substring(0, value.indexOf(",")).trim();
+ if (FontFactory.isRegistered(tmp)) {
+ fontname = tmp;
+ break;
+ } else {
+ value = value.substring(value.indexOf(",") + 1);
+ }
+ }
+ }
+ }
+ if ((value = (String) styleAttributes.get(MarkupTags.CSS_KEY_FONTSIZE)) != null) {
+ size = MarkupParser.parseLength(value);
+ }
+ if ((value = (String) styleAttributes
+ .get(MarkupTags.CSS_KEY_FONTWEIGHT)) != null) {
+ style |= Font.getStyleValue(value);
+ }
+ if ((value = (String) styleAttributes.get(MarkupTags.CSS_KEY_FONTSTYLE)) != null) {
+ style |= Font.getStyleValue(value);
+ }
+ if ((value = (String) styleAttributes.get(MarkupTags.CSS_KEY_COLOR)) != null) {
+ color = MarkupParser.decodeColor(value);
+ }
+ return FontFactory.getFont(fontname, encoding, embedded, size, style,
+ color);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/markup/MarkupTags.java pdftk-2.01/java/pdftk/com/lowagie/text/markup/MarkupTags.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/markup/MarkupTags.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/markup/MarkupTags.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,256 @@
+/*
+ * $Id: MarkupTags.java,v 1.50 2005/05/03 14:44:38 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.markup;
+
+/**
+ * A class that contains all the possible tagnames and their attributes.
+ */
+
+public class MarkupTags {
+
+ // iText specific
+
+ /** the key for any tag */
+ public static final String ITEXT_TAG = "tag";
+
+ // HTML tags
+
+ /** the markup for the body part of a file */
+ public static final String HTML_TAG_BODY = "body";
+
+ /** The DIV tag. */
+ public static final String HTML_TAG_DIV = "div";
+
+ /** This is a possible HTML-tag. */
+ public static final String HTML_TAG_LINK = "link";
+
+ /** The SPAN tag. */
+ public static final String HTML_TAG_SPAN = "span";
+
+ // HTML attributes
+
+ /** the height attribute. */
+ public static final String HTML_ATTR_HEIGHT = "height";
+
+ /** the hyperlink reference attribute. */
+ public static final String HTML_ATTR_HREF = "href";
+
+ /** This is a possible HTML attribute for the LINK tag. */
+ public static final String HTML_ATTR_REL = "rel";
+
+ /** This is used for inline css style information */
+ public static final String HTML_ATTR_STYLE = "style";
+
+ /** This is a possible HTML attribute for the LINK tag. */
+ public static final String HTML_ATTR_TYPE = "type";
+
+ /** This is a possible HTML attribute. */
+ public static final String HTML_ATTR_STYLESHEET = "stylesheet";
+
+ /** the width attribute. */
+ public static final String HTML_ATTR_WIDTH = "width";
+
+ /** attribute for specifying externally defined CSS class */
+ public static final String HTML_ATTR_CSS_CLASS = "class";
+
+ /** The ID attribute. */
+ public static final String HTML_ATTR_CSS_ID = "id";
+
+ // HTML values
+
+ /** This is a possible value for the language attribute (SCRIPT tag). */
+ public static final String HTML_VALUE_JAVASCRIPT = "text/javascript";
+
+ /** This is a possible HTML attribute for the LINK tag. */
+ public static final String HTML_VALUE_CSS = "text/css";
+
+ // CSS keys
+
+ /** the CSS tag for background color */
+ public static final String CSS_KEY_BGCOLOR = "background-color";
+
+ /** the CSS tag for text color */
+ public static final String CSS_KEY_COLOR = "color";
+
+ /** CSS key that indicate the way something has to be displayed */
+ public static final String CSS_KEY_DISPLAY = "display";
+
+ /** the CSS tag for the font family */
+ public static final String CSS_KEY_FONTFAMILY = "font-family";
+
+ /** the CSS tag for the font size */
+ public static final String CSS_KEY_FONTSIZE = "font-size";
+
+ /** the CSS tag for the font style */
+ public static final String CSS_KEY_FONTSTYLE = "font-style";
+
+ /** the CSS tag for the font weight */
+ public static final String CSS_KEY_FONTWEIGHT = "font-weight";
+
+ /** the CSS tag for text decorations */
+ public static final String CSS_KEY_LINEHEIGHT = "line-height";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_MARGIN = "margin";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_MARGINLEFT = "margin-left";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_MARGINRIGHT = "margin-right";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_MARGINTOP = "margin-top";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_MARGINBOTTOM = "margin-bottom";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_PADDING = "padding";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_PADDINGLEFT = "padding-left";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_PADDINGRIGHT = "padding-right";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_PADDINGTOP = "padding-top";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_PADDINGBOTTOM = "padding-bottom";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_BORDERCOLOR = "border-color";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_BORDERWIDTH = "border-width";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_BORDERWIDTHLEFT = "border-left-width";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_BORDERWIDTHRIGHT = "border-right-width";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_BORDERWIDTHTOP = "border-top-width";
+
+ /** the CSS tag for the margin of an object */
+ public static final String CSS_KEY_BORDERWIDTHBOTTOM = "border-bottom-width";
+
+ /** the CSS tag for adding a page break when the document is printed */
+ public static final String CSS_KEY_PAGE_BREAK_AFTER = "page-break-after";
+
+ /** the CSS tag for adding a page break when the document is printed */
+ public static final String CSS_KEY_PAGE_BREAK_BEFORE = "page-break-before";
+
+ /** the CSS tag for the horizontal alignment of an object */
+ public static final String CSS_KEY_TEXTALIGN = "text-align";
+
+ /** the CSS tag for text decorations */
+ public static final String CSS_KEY_TEXTDECORATION = "text-decoration";
+
+ /** the CSS tag for text decorations */
+ public static final String CSS_KEY_VERTICALALIGN = "vertical-align";
+
+ /** the CSS tag for the visibility of objects */
+ public static final String CSS_KEY_VISIBILITY = "visibility";
+
+ // CSS values
+
+ /** value for the CSS tag for adding a page break when the document is printed */
+ public static final String CSS_VALUE_ALWAYS = "always";
+
+ /** A possible value for the DISPLAY key */
+ public static final String CSS_VALUE_BLOCK = "block";
+
+ /** a CSS value for text font weight */
+ public static final String CSS_VALUE_BOLD = "bold";
+
+ /** the value if you want to hide objects. */
+ public static final String CSS_VALUE_HIDDEN = "hidden";
+
+ /** A possible value for the DISPLAY key */
+ public static final String CSS_VALUE_INLINE = "inline";
+
+ /** a CSS value for text font style */
+ public static final String CSS_VALUE_ITALIC = "italic";
+
+ /** a CSS value for text decoration */
+ public static final String CSS_VALUE_LINETHROUGH = "line-through";
+
+ /** A possible value for the DISPLAY key */
+ public static final String CSS_VALUE_LISTITEM = "list-item";
+
+ /** a CSS value */
+ public static final String CSS_VALUE_NONE = "none";
+
+ /** a CSS value */
+ public static final String CSS_VALUE_NORMAL = "normal";
+
+ /** a CSS value for text font style */
+ public static final String CSS_VALUE_OBLIQUE = "oblique";
+
+ /** A possible value for the DISPLAY key */
+ public static final String CSS_VALUE_TABLE = "table";
+
+ /** A possible value for the DISPLAY key */
+ public static final String CSS_VALUE_TABLEROW = "table-row";
+
+ /** A possible value for the DISPLAY key */
+ public static final String CSS_VALUE_TABLECELL = "table-cell";
+
+ /** the CSS value for a horizontal alignment of an object */
+ public static final String CSS_VALUE_TEXTALIGNLEFT = "left";
+
+ /** the CSS value for a horizontal alignment of an object */
+ public static final String CSS_VALUE_TEXTALIGNRIGHT = "right";
+
+ /** the CSS value for a horizontal alignment of an object */
+ public static final String CSS_VALUE_TEXTALIGNCENTER = "center";
+
+ /** the CSS value for a horizontal alignment of an object */
+ public static final String CSS_VALUE_TEXTALIGNJUSTIFY = "justify";
+
+ /** a CSS value for text decoration */
+ public static final String CSS_VALUE_UNDERLINE = "underline";
+
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/AcroFields.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/AcroFields.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/AcroFields.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/AcroFields.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,1748 @@
+/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.Comparator;
+import java.util.Collections;
+import pdftk.com.lowagie.text.Rectangle;
+import pdftk.com.lowagie.text.Element;
+import pdftk.com.lowagie.text.ExceptionConverter;
+import pdftk.com.lowagie.text.DocumentException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.awt.Color;
+
+/** Query and change fields in existing documents either by method
+ * calls or by FDF merging.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class AcroFields {
+
+ PdfReader reader;
+ PdfWriter writer;
+ HashMap fields;
+ private int topFirst;
+ private HashMap sigNames;
+ private boolean append;
+ static private final int DA_FONT = 0;
+ static private final int DA_SIZE = 1;
+ static private final int DA_COLOR = 2;
+ /**
+ * A field type invalid or not found.
+ */
+ public static final int FIELD_TYPE_NONE = 0;
+ /**
+ * A field type.
+ */
+ public static final int FIELD_TYPE_PUSHBUTTON = 1;
+ /**
+ * A field type.
+ */
+ public static final int FIELD_TYPE_CHECKBOX = 2;
+ /**
+ * A field type.
+ */
+ public static final int FIELD_TYPE_RADIOBUTTON = 3;
+ /**
+ * A field type.
+ */
+ public static final int FIELD_TYPE_TEXT = 4;
+ /**
+ * A field type.
+ */
+ public static final int FIELD_TYPE_LIST = 5;
+ /**
+ * A field type.
+ */
+ public static final int FIELD_TYPE_COMBO = 6;
+ /**
+ * A field type.
+ */
+ public static final int FIELD_TYPE_SIGNATURE = 7;
+
+ private boolean lastWasString;
+
+ /** Holds value of property generateAppearances. */
+ private boolean generateAppearances = true;
+
+ private HashMap localFonts = new HashMap();
+
+ private float extraMarginLeft;
+ private float extraMarginTop;
+
+ AcroFields(PdfReader reader, PdfWriter writer) {
+ this.reader = reader;
+ this.writer = writer;
+ if (writer instanceof PdfStamperImp) {
+ append = ((PdfStamperImp)writer).isAppend();
+ }
+ fill();
+ }
+
+ void fill() {
+ fields = new HashMap();
+ PdfDictionary top = (PdfDictionary)PdfReader.getPdfObjectRelease(reader.getCatalog().get(PdfName.ACROFORM));
+ if (top == null)
+ return;
+ PdfArray arrfds = (PdfArray)PdfReader.getPdfObjectRelease(top.get(PdfName.FIELDS));
+ if (arrfds == null || arrfds.size() == 0)
+ return;
+ arrfds = null;
+ for (int k = 1; k <= reader.getNumberOfPages(); ++k) {
+ if ((k % 100) == 0)
+ System.out.println(k);
+ PdfDictionary page = reader.getPageNRelease(k);
+ PdfArray annots = (PdfArray)PdfReader.getPdfObjectRelease(page.get(PdfName.ANNOTS), page);
+ if (annots == null)
+ continue;
+ ArrayList arr = annots.getArrayList();
+ for (int j = 0; j < arr.size(); ++j) {
+ PdfObject annoto = PdfReader.getPdfObject((PdfObject)arr.get(j), annots);
+ if ((annoto instanceof PdfIndirectReference) && !annoto.isIndirect()) {
+ PdfReader.releaseLastXrefPartial((PdfObject)arr.get(j));
+ continue;
+ }
+ // ssteward: because we've seen a PDF where an annot array item was null
+ if( !annoto.isDictionary() )
+ continue;
+ PdfDictionary annot = (PdfDictionary)annoto;
+ if (!PdfName.WIDGET.equals(annot.get(PdfName.SUBTYPE))) {
+ PdfReader.releaseLastXrefPartial((PdfObject)arr.get(j));
+ continue;
+ }
+ PdfDictionary widget = annot;
+ PdfDictionary dic = new PdfDictionary();
+ dic.putAll(annot);
+ String name = "";
+ PdfDictionary value = null;
+ PdfObject lastV = null;
+ while (annot != null) {
+ dic.mergeDifferent(annot);
+ PdfString t = (PdfString)PdfReader.getPdfObject(annot.get(PdfName.T));
+ if (t != null)
+ name = t.toUnicodeString() + "." + name;
+ if (lastV == null && annot.get(PdfName.V) != null)
+ lastV = PdfReader.getPdfObjectRelease(annot.get(PdfName.V));
+ if (value == null && t != null) {
+ value = annot;
+ if (annot.get(PdfName.V) == null && lastV != null)
+ value.put(PdfName.V, lastV);
+ }
+ annot = (PdfDictionary)PdfReader.getPdfObject(annot.get(PdfName.PARENT), annot);
+ }
+ if (name.length() > 0)
+ name = name.substring(0, name.length() - 1);
+ Item item = (Item)fields.get(name);
+ if (item == null) {
+ item = new Item();
+ fields.put(name, item);
+ }
+ if (value == null)
+ item.values.add(widget);
+ else
+ item.values.add(value);
+ item.widgets.add(widget);
+ item.widget_refs.add(arr.get(j)); // must be a reference
+ if (top != null)
+ dic.mergeDifferent(top);
+ item.merged.add(dic);
+ item.page.add(new Integer(k));
+ item.tabOrder.add(new Integer(j));
+ }
+ }
+ }
+
+ /** Gets the list of appearance names. Use it to get the names allowed
+ * with radio and checkbox fields. If the /Opt key exists the values will
+ * also be included. The name 'Off' may also be valid
+ * even if not returned in the list.
+ * @param fieldName the fully qualified field name
+ * @return the list of names or null
if the field does not exist
+ */
+ public String[] getAppearanceStates(String fieldName) {
+ Item fd = (Item)fields.get(fieldName);
+ if (fd == null)
+ return null;
+ HashMap names = new HashMap();
+ PdfDictionary vals = (PdfDictionary)fd.values.get(0);
+ PdfObject opts = PdfReader.getPdfObject(vals.get(PdfName.OPT));
+ if (opts != null) {
+ if (opts.isString())
+ names.put(((PdfString)opts).toUnicodeString(), null);
+ else if (opts.isArray()) {
+ ArrayList list = ((PdfArray)opts).getArrayList();
+ for (int k = 0; k < list.size(); ++k) {
+ PdfObject v = PdfReader.getPdfObject((PdfObject)list.get(k));
+ if (v != null && v.isString())
+ names.put(((PdfString)v).toUnicodeString(), null);
+ }
+ }
+ }
+ ArrayList wd = fd.widgets;
+ for (int k = 0; k < wd.size(); ++k) {
+ PdfDictionary dic = (PdfDictionary)wd.get(k);
+ dic = (PdfDictionary)PdfReader.getPdfObject(dic.get(PdfName.AP));
+ if (dic == null)
+ continue;
+ PdfObject ob = PdfReader.getPdfObject(dic.get(PdfName.N));
+ if (ob == null || !ob.isDictionary())
+ continue;
+ dic = (PdfDictionary)ob;
+ for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
+ String name = PdfName.decodeName(((PdfName)it.next()).toString());
+ names.put(name, null);
+ }
+ }
+ String out[] = new String[names.size()];
+ return (String[])names.keySet().toArray(out);
+ }
+
+ /**
+ * Gets the field type. The type can be one of: FIELD_TYPE_PUSHBUTTON
,
+ * FIELD_TYPE_CHECKBOX
, FIELD_TYPE_RADIOBUTTON
,
+ * FIELD_TYPE_TEXT
, FIELD_TYPE_LIST
,
+ * FIELD_TYPE_COMBO
or FIELD_TYPE_SIGNATURE
.
+ *
+ * If the field does not exist or is invalid it returns
+ * FIELD_TYPE_NONE
.
+ * @param fieldName the field name
+ * @return the field type
+ */
+ public int getFieldType(String fieldName) {
+ Item fd = (Item)fields.get(fieldName);
+ if (fd == null)
+ return FIELD_TYPE_NONE;
+ PdfObject type = PdfReader.getPdfObject(((PdfDictionary)fd.merged.get(0)).get(PdfName.FT));
+ if (type == null)
+ return FIELD_TYPE_NONE;
+ int ff = 0;
+ PdfObject ffo = PdfReader.getPdfObject(((PdfDictionary)fd.merged.get(0)).get(PdfName.FF));
+ if (ffo != null && ffo.type() == PdfObject.NUMBER)
+ ff = ((PdfNumber)ffo).intValue();
+ if (PdfName.BTN.equals(type)) {
+ if ((ff & PdfFormField.FF_PUSHBUTTON) != 0)
+ return FIELD_TYPE_PUSHBUTTON;
+ if ((ff & PdfFormField.FF_RADIO) != 0)
+ return FIELD_TYPE_RADIOBUTTON;
+ else
+ return FIELD_TYPE_CHECKBOX;
+ }
+ else if (PdfName.TX.equals(type)) {
+ return FIELD_TYPE_TEXT;
+ }
+ else if (PdfName.CH.equals(type)) {
+ if ((ff & PdfFormField.FF_COMBO) != 0)
+ return FIELD_TYPE_COMBO;
+ else
+ return FIELD_TYPE_LIST;
+ }
+ else if (PdfName.SIG.equals(type)) {
+ return FIELD_TYPE_SIGNATURE;
+ }
+ return FIELD_TYPE_NONE;
+ }
+
+ /**
+ * Export the fields as a FDF.
+ * @param writer the FDF writer
+ */
+ public void exportAsFdf(FdfWriter writer) {
+ for (Iterator it = fields.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry)it.next();
+ Item item = (Item)entry.getValue();
+ String name = (String)entry.getKey();
+ // PdfObject v = PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.V));
+ // ssteward: moved this logic to getField, where lastWasString is set;
+ // we also want to output empty fields, too;
+ //if (v != null)
+ String value = getField(name);
+ if (lastWasString)
+ writer.setFieldAsString(name, value);
+ else /* ssteward: TODO: if (!value.isEmpty())*/
+ writer.setFieldAsName(name, value);
+ }
+ }
+
+ /**
+ * Renames a field. Only the last part of the name can be renamed. For example,
+ * if the original field is "ab.cd.ef" only the "ef" part can be renamed.
+ * @param oldName the old field name
+ * @param newName the new field name
+ * @return true
if the renaming was successful, false
+ * otherwise
+ */
+ public boolean renameField(String oldName, String newName) {
+ int idx1 = oldName.lastIndexOf('.') + 1;
+ int idx2 = newName.lastIndexOf('.') + 1;
+ if (idx1 != idx2)
+ return false;
+ if (!oldName.substring(0, idx1).equals(newName.substring(0, idx2)))
+ return false;
+ if (fields.containsKey(newName))
+ return false;
+ Item item = (Item)fields.get(oldName);
+ if (item == null)
+ return false;
+ newName = newName.substring(idx2);
+ PdfString ss = new PdfString(newName, PdfObject.TEXT_UNICODE);
+ for (int k = 0; k < item.merged.size(); ++k) {
+ PdfDictionary dic = (PdfDictionary)item.values.get(k);
+ dic.put(PdfName.T, ss);
+ markUsed(dic);
+ dic = (PdfDictionary)item.merged.get(k);
+ dic.put(PdfName.T, ss);
+ }
+ fields.remove(oldName);
+ fields.put(newName, item);
+ return true;
+ }
+
+ static private Object[] splitDAelements(String da) {
+ try {
+ PRTokeniser tk = new PRTokeniser(PdfEncodings.convertToBytes(da, null));
+ ArrayList stack = new ArrayList();
+ Object ret[] = new Object[3];
+ while (tk.nextToken()) {
+ if (tk.getTokenType() == PRTokeniser.TK_COMMENT)
+ continue;
+ if (tk.getTokenType() == PRTokeniser.TK_OTHER) {
+ String operator = tk.getStringValue();
+ if (operator.equals("Tf")) {
+ if (stack.size() >= 2) {
+ ret[DA_FONT] = stack.get(stack.size() - 2);
+ ret[DA_SIZE] = new Float((String)stack.get(stack.size() - 1));
+ }
+ }
+ else if (operator.equals("g")) {
+ if (stack.size() >= 1) {
+ float gray = new Float((String)stack.get(stack.size() - 1)).floatValue();
+ if (gray != 0)
+ ret[DA_COLOR] = new GrayColor(gray);
+ }
+ }
+ else if (operator.equals("rg")) {
+ if (stack.size() >= 3) {
+ float red = new Float((String)stack.get(stack.size() - 3)).floatValue();
+ float green = new Float((String)stack.get(stack.size() - 2)).floatValue();
+ float blue = new Float((String)stack.get(stack.size() - 1)).floatValue();
+ ret[DA_COLOR] = new Color(red, green, blue);
+ }
+ }
+ else if (operator.equals("k")) {
+ if (stack.size() >= 4) {
+ float cyan = new Float((String)stack.get(stack.size() - 4)).floatValue();
+ float magenta = new Float((String)stack.get(stack.size() - 3)).floatValue();
+ float yellow = new Float((String)stack.get(stack.size() - 2)).floatValue();
+ float black = new Float((String)stack.get(stack.size() - 1)).floatValue();
+ ret[DA_COLOR] = new CMYKColor(cyan, magenta, yellow, black);
+ }
+ }
+ stack.clear();
+ }
+ else
+ stack.add(tk.getStringValue());
+ }
+ return ret;
+ }
+ catch (IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ }
+
+ PdfAppearance getAppearance(PdfDictionary merged, String text, String fieldName) throws IOException, DocumentException {
+ topFirst = 0;
+ int flags = 0;
+ TextField tx = null;
+ if (fieldCache == null || !fieldCache.containsKey(fieldName)) {
+ tx = new TextField(writer, null, null);
+ tx.setExtraMargin(extraMarginLeft, extraMarginTop);
+ tx.setBorderWidth(0);
+ // the text size and color
+ PdfString da = (PdfString)PdfReader.getPdfObject(merged.get(PdfName.DA));
+ if (da != null) {
+ Object dab[] = splitDAelements(da.toUnicodeString());
+ if (dab[DA_SIZE] != null)
+ tx.setFontSize(((Float)dab[DA_SIZE]).floatValue());
+ if (dab[DA_COLOR] != null)
+ tx.setTextColor((Color)dab[DA_COLOR]);
+ if (dab[DA_FONT] != null) {
+ PdfDictionary font = (PdfDictionary)PdfReader.getPdfObject(merged.get(PdfName.DR));
+ if (font != null) {
+ font = (PdfDictionary)PdfReader.getPdfObject(font.get(PdfName.FONT));
+ if (font != null) {
+ PdfObject po = font.get(new PdfName((String)dab[DA_FONT]));
+ if (po != null && po.type() == PdfObject.INDIRECT)
+ tx.setFont(new DocumentFont((PRIndirectReference)po));
+ else {
+ BaseFont bf = (BaseFont)localFonts.get(dab[DA_FONT]);
+ if (bf == null) {
+ String fn[] = (String[])stdFieldFontNames.get(dab[DA_FONT]);
+ if (fn != null) {
+ try {
+ String enc = "winansi";
+ if (fn.length > 1)
+ enc = fn[1];
+ bf = BaseFont.createFont(fn[0], enc, false);
+ tx.setFont(bf);
+ }
+ catch (Exception e) {
+ // empty
+ }
+ }
+ }
+ else
+ tx.setFont(bf);
+ }
+ }
+ }
+ }
+ }
+ //rotation, border and backgound color
+ PdfDictionary mk = (PdfDictionary)PdfReader.getPdfObject(merged.get(PdfName.MK));
+ if (mk != null) {
+ PdfArray ar = (PdfArray)PdfReader.getPdfObject(mk.get(PdfName.BC));
+ Color border = getMKColor(ar);
+ tx.setBorderColor(border);
+ if (border != null)
+ tx.setBorderWidth(1);
+ ar = (PdfArray)PdfReader.getPdfObject(mk.get(PdfName.BG));
+ tx.setBackgroundColor(getMKColor(ar));
+ PdfNumber rotation = (PdfNumber)PdfReader.getPdfObject(mk.get(PdfName.R));
+ if (rotation != null)
+ tx.setRotation(rotation.intValue());
+ }
+ //multiline
+ PdfNumber nfl = (PdfNumber)PdfReader.getPdfObject(merged.get(PdfName.FF));
+ if (nfl != null)
+ flags = nfl.intValue();
+ tx.setOptions(((flags & PdfFormField.FF_MULTILINE) == 0 ? 0 : TextField.MULTILINE) | ((flags & PdfFormField.FF_COMB) == 0 ? 0 : TextField.COMB));
+ if ((flags & PdfFormField.FF_COMB) != 0) {
+ PdfNumber maxLen = (PdfNumber)PdfReader.getPdfObject(merged.get(PdfName.MAXLEN));
+ int len = 0;
+ if (maxLen != null)
+ len = maxLen.intValue();
+ tx.setMaxCharacterLength(len);
+ }
+ //alignment
+ nfl = (PdfNumber)PdfReader.getPdfObject(merged.get(PdfName.Q));
+ if (nfl != null) {
+ if (nfl.intValue() == PdfFormField.Q_CENTER)
+ tx.setAlignment(Element.ALIGN_CENTER);
+ else if (nfl.intValue() == PdfFormField.Q_RIGHT)
+ tx.setAlignment(Element.ALIGN_RIGHT);
+ }
+ //border styles
+ PdfDictionary bs = (PdfDictionary)PdfReader.getPdfObject(merged.get(PdfName.BS));
+ if (bs != null) {
+ PdfNumber w = (PdfNumber)PdfReader.getPdfObject(bs.get(PdfName.W));
+ if (w != null)
+ tx.setBorderWidth(w.floatValue());
+ PdfName s = (PdfName)PdfReader.getPdfObject(bs.get(PdfName.S));
+ if (PdfName.D.equals(s))
+ tx.setBorderStyle(PdfBorderDictionary.STYLE_DASHED);
+ else if (PdfName.B.equals(s))
+ tx.setBorderStyle(PdfBorderDictionary.STYLE_BEVELED);
+ else if (PdfName.I.equals(s))
+ tx.setBorderStyle(PdfBorderDictionary.STYLE_INSET);
+ else if (PdfName.U.equals(s))
+ tx.setBorderStyle(PdfBorderDictionary.STYLE_UNDERLINE);
+ }
+ else {
+ PdfArray bd = (PdfArray)PdfReader.getPdfObject(merged.get(PdfName.BORDER));
+ if (bd != null) {
+ ArrayList ar = bd.getArrayList();
+ if (ar.size() >= 3)
+ tx.setBorderWidth(((PdfNumber)ar.get(2)).floatValue());
+ if (ar.size() >= 4)
+ tx.setBorderStyle(PdfBorderDictionary.STYLE_DASHED);
+ }
+ }
+ //rect
+ PdfArray rect = (PdfArray)PdfReader.getPdfObject(merged.get(PdfName.RECT));
+ Rectangle box = PdfReader.getNormalizedRectangle(rect);
+ if (tx.getRotation() == 90 || tx.getRotation() == 270)
+ box = box.rotate();
+ tx.setBox(box);
+ if (fieldCache != null)
+ fieldCache.put(fieldName, tx);
+ }
+ else {
+ tx = (TextField)fieldCache.get(fieldName);
+ tx.setWriter(writer);
+ }
+ PdfName fieldType = (PdfName)PdfReader.getPdfObject(merged.get(PdfName.FT));
+ if (PdfName.TX.equals(fieldType)) {
+ tx.setText(text);
+ return tx.getAppearance();
+ }
+ if (!PdfName.CH.equals(fieldType))
+ throw new DocumentException("An appearance was requested without a variable text field.");
+ PdfArray opt = (PdfArray)PdfReader.getPdfObject(merged.get(PdfName.OPT));
+ if ((flags & PdfFormField.FF_COMBO) != 0 && opt == null) {
+ tx.setText(text);
+ return tx.getAppearance();
+ }
+ if (opt != null) {
+ ArrayList op = opt.getArrayList();
+ String choices[] = new String[op.size()];
+ String choicesExp[] = new String[op.size()];
+ for (int k = 0; k < op.size(); ++k) {
+ PdfObject obj = (PdfObject)op.get(k);
+ if (obj.isString()) {
+ choices[k] = choicesExp[k] = ((PdfString)obj).toUnicodeString();
+ }
+ else {
+ ArrayList opar = ((PdfArray)obj).getArrayList();
+ choicesExp[k] = ((PdfString)opar.get(0)).toUnicodeString();
+ choices[k] = ((PdfString)opar.get(1)).toUnicodeString();
+ }
+ }
+ if ((flags & PdfFormField.FF_COMBO) != 0) {
+ for (int k = 0; k < choices.length; ++k) {
+ if (text.equals(choicesExp[k])) {
+ text = choices[k];
+ break;
+ }
+ }
+ tx.setText(text);
+ return tx.getAppearance();
+ }
+ int idx = 0;
+ for (int k = 0; k < choicesExp.length; ++k) {
+ if (text.equals(choicesExp[k])) {
+ idx = k;
+ break;
+ }
+ }
+ tx.setChoices(choices);
+ tx.setChoiceExports(choicesExp);
+ tx.setChoiceSelection(idx);
+ }
+ PdfAppearance app = tx.getListAppearance();
+ topFirst = tx.getTopFirst();
+ return app;
+ }
+
+ Color getMKColor(PdfArray ar) {
+ if (ar == null)
+ return null;
+ ArrayList cc = ar.getArrayList();
+ switch (cc.size()) {
+ case 1:
+ return new GrayColor(((PdfNumber)cc.get(0)).floatValue());
+ case 3:
+ return new Color(((PdfNumber)cc.get(0)).floatValue(), ((PdfNumber)cc.get(1)).floatValue(), ((PdfNumber)cc.get(2)).floatValue());
+ case 4:
+ return new CMYKColor(((PdfNumber)cc.get(0)).floatValue(), ((PdfNumber)cc.get(1)).floatValue(), ((PdfNumber)cc.get(2)).floatValue(), ((PdfNumber)cc.get(3)).floatValue());
+ default:
+ return null;
+ }
+ }
+
+ /** Gets the field value.
+ * @param name the fully qualified field name
+ * @return the field value
+ */
+ public String getField(String name) {
+ Item item = (Item)fields.get(name);
+ if (item == null)
+ return null;
+ lastWasString = true; // ssteward: default was false
+ PdfObject v = PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.V));
+ // ssteward: test VT before returning
+ //if (v == null)
+ // return "";
+ PdfName type = (PdfName)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.FT));
+ if (PdfName.BTN.equals(type)) {
+ lastWasString = false; // ssteward
+ PdfNumber ff = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.FF));
+ int flags = 0;
+ if (ff != null)
+ flags = ff.intValue();
+ if ((flags & PdfFormField.FF_PUSHBUTTON) != 0)
+ return "";
+ String value = "";
+ if (v != null) { // ssteward
+ if (v.isName())
+ value = PdfName.decodeName(v.toString());
+ else if (v.isString())
+ value = ((PdfString)v).toUnicodeString();
+ }
+ PdfObject opts = PdfReader.getPdfObject(((PdfDictionary)item.values.get(0)).get(PdfName.OPT));
+ if (opts != null && opts.isArray()) {
+ ArrayList list = ((PdfArray)opts).getArrayList();
+ int idx = 0;
+ try {
+ idx = Integer.parseInt(value);
+ PdfString ps = (PdfString)list.get(idx);
+ value = ps.toUnicodeString();
+ lastWasString = true;
+ }
+ catch (Exception e) {
+ }
+ }
+ return value;
+ }
+
+ if (v == null) { // ssteward
+ return "";
+ }
+ if (v.isString()) {
+ return ((PdfString)v).toUnicodeString();
+ }
+ lastWasString = false;
+ return PdfName.decodeName(v.toString());
+ }
+
+ /**
+ * Sets a field property. Valid property names are:
+ *
+ *
+ * textfont - sets the text font. The value for this entry is a BaseFont
.
+ * textcolor - sets the text color. The value for this entry is a java.awt.Color
.
+ * textsize - sets the text size. The value for this entry is a Float
.
+ * bgcolor - sets the background color. The value for this entry is a java.awt.Color
.
+ * If null
removes the background.
+ * bordercolor - sets the border color. The value for this entry is a java.awt.Color
.
+ * If null
removes the border.
+ *
+ * @param field the field name
+ * @param name the property name
+ * @param value the property value
+ * @param inst an array of int
indexing into AcroField.Item.merged
elements to process.
+ * Set to null
to process all
+ * @return true
if the property exists, false
otherwise
+ */
+ public boolean setFieldProperty(String field, String name, Object value, int inst[]) {
+ if (writer == null)
+ throw new RuntimeException("This AcroFields instance is read-only.");
+ try {
+ Item item = (Item)fields.get(field);
+ if (item == null)
+ return false;
+ InstHit hit = new InstHit(inst);
+ if (name.equalsIgnoreCase("textfont")) {
+ for (int k = 0; k < item.merged.size(); ++k) {
+ if (hit.isHit(k)) {
+ PdfString da = (PdfString)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(k)).get(PdfName.DA));
+ PdfDictionary dr = (PdfDictionary)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(k)).get(PdfName.DR));
+ if (da != null && dr != null) {
+ Object dao[] = splitDAelements(da.toUnicodeString());
+ PdfAppearance cb = new PdfAppearance();
+ if (dao[DA_FONT] != null) {
+ BaseFont bf = (BaseFont)value;
+ PdfName psn = (PdfName)PdfAppearance.stdFieldFontNames.get(bf.getPostscriptFontName());
+ if (psn == null) {
+ psn = new PdfName(bf.getPostscriptFontName());
+ }
+ PdfDictionary fonts = (PdfDictionary)PdfReader.getPdfObject(dr.get(PdfName.FONT));
+ if (fonts == null) {
+ fonts = new PdfDictionary();
+ dr.put(PdfName.FONT, fonts);
+ }
+ PdfIndirectReference fref = (PdfIndirectReference)fonts.get(psn);
+ PdfDictionary top = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM));
+ markUsed(top);
+ dr = (PdfDictionary)PdfReader.getPdfObject(top.get(PdfName.DR));
+ if (dr == null) {
+ dr = new PdfDictionary();
+ top.put(PdfName.DR, dr);
+ }
+ markUsed(dr);
+ PdfDictionary fontsTop = (PdfDictionary)PdfReader.getPdfObject(dr.get(PdfName.FONT));
+ if (fontsTop == null) {
+ fontsTop = new PdfDictionary();
+ dr.put(PdfName.FONT, fontsTop);
+ }
+ markUsed(fontsTop);
+ PdfIndirectReference frefTop = (PdfIndirectReference)fontsTop.get(psn);
+ if (frefTop != null) {
+ if (fref == null)
+ fonts.put(psn, frefTop);
+ }
+ else if (fref == null) {
+ FontDetails fd;
+ if (bf.getFontType() == BaseFont.FONT_TYPE_DOCUMENT) {
+ fd = new FontDetails(null, ((DocumentFont)bf).getIndirectReference(), bf);
+ }
+ else {
+ bf.setSubset(false);
+ fd = writer.addSimple(bf);
+ localFonts.put(psn.toString().substring(1), bf);
+ }
+ fontsTop.put(psn, fd.getIndirectReference());
+ fonts.put(psn, fd.getIndirectReference());
+ }
+ ByteBuffer buf = cb.getInternalBuffer();
+ buf.append(psn.getBytes()).append(' ').append(((Float)dao[DA_SIZE]).floatValue()).append(" Tf ");
+ if (dao[DA_COLOR] != null)
+ cb.setColorFill((Color)dao[DA_COLOR]);
+ PdfString s = new PdfString(cb.toString());
+ ((PdfDictionary)item.merged.get(k)).put(PdfName.DA, s);
+ ((PdfDictionary)item.widgets.get(k)).put(PdfName.DA, s);
+ markUsed((PdfDictionary)item.widgets.get(k));
+ }
+ }
+ }
+ }
+ }
+ else if (name.equalsIgnoreCase("textcolor")) {
+ for (int k = 0; k < item.merged.size(); ++k) {
+ if (hit.isHit(k)) {
+ PdfString da = (PdfString)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(k)).get(PdfName.DA));
+ if (da != null) {
+ Object dao[] = splitDAelements(da.toUnicodeString());
+ PdfAppearance cb = new PdfAppearance();
+ if (dao[DA_FONT] != null) {
+ ByteBuffer buf = cb.getInternalBuffer();
+ buf.append(new PdfName((String)dao[DA_FONT]).getBytes()).append(' ').append(((Float)dao[DA_SIZE]).floatValue()).append(" Tf ");
+ cb.setColorFill((Color)value);
+ PdfString s = new PdfString(cb.toString());
+ ((PdfDictionary)item.merged.get(k)).put(PdfName.DA, s);
+ ((PdfDictionary)item.widgets.get(k)).put(PdfName.DA, s);
+ markUsed((PdfDictionary)item.widgets.get(k));
+ }
+ }
+ }
+ }
+ }
+ else if (name.equalsIgnoreCase("textsize")) {
+ for (int k = 0; k < item.merged.size(); ++k) {
+ if (hit.isHit(k)) {
+ PdfString da = (PdfString)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(k)).get(PdfName.DA));
+ if (da != null) {
+ Object dao[] = splitDAelements(da.toUnicodeString());
+ PdfAppearance cb = new PdfAppearance();
+ if (dao[DA_FONT] != null) {
+ ByteBuffer buf = cb.getInternalBuffer();
+ buf.append(new PdfName((String)dao[DA_FONT]).getBytes()).append(' ').append(((Float)value).floatValue()).append(" Tf ");
+ if (dao[DA_COLOR] != null)
+ cb.setColorFill((Color)dao[DA_COLOR]);
+ PdfString s = new PdfString(cb.toString());
+ ((PdfDictionary)item.merged.get(k)).put(PdfName.DA, s);
+ ((PdfDictionary)item.widgets.get(k)).put(PdfName.DA, s);
+ markUsed((PdfDictionary)item.widgets.get(k));
+ }
+ }
+ }
+ }
+ }
+ else if (name.equalsIgnoreCase("bgcolor") || name.equalsIgnoreCase("bordercolor")) {
+ PdfName dname = (name.equalsIgnoreCase("bgcolor") ? PdfName.BG : PdfName.BC);
+ for (int k = 0; k < item.merged.size(); ++k) {
+ if (hit.isHit(k)) {
+ PdfObject obj = PdfReader.getPdfObject(((PdfDictionary)item.merged.get(k)).get(PdfName.MK));
+ markUsed(obj);
+ PdfDictionary mk = (PdfDictionary)obj;
+ if (mk == null) {
+ if (value == null)
+ return true;
+ mk = new PdfDictionary();
+ ((PdfDictionary)item.merged.get(k)).put(PdfName.MK, mk);
+ ((PdfDictionary)item.widgets.get(k)).put(PdfName.MK, mk);
+ markUsed((PdfDictionary)item.widgets.get(k));
+ }
+ if (value == null)
+ mk.remove(dname);
+ else
+ mk.put(dname, PdfFormField.getMKColor((Color)value));
+ }
+ }
+ }
+ else
+ return false;
+ return true;
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ * Sets a field property. Valid property names are:
+ *
+ *
+ * flags - a set of flags specifying various characteristics of the field's widget annotation.
+ * The value of this entry replaces that of the F entry in the form's corresponding annotation dictionary.
+ * setflags - a set of flags to be set (turned on) in the F entry of the form's corresponding
+ * widget annotation dictionary. Bits equal to 1 cause the corresponding bits in F to be set to 1.
+ * clrflags - a set of flags to be cleared (turned off) in the F entry of the form's corresponding
+ * widget annotation dictionary. Bits equal to 1 cause the corresponding
+ * bits in F to be set to 0.
+ * fflags - a set of flags specifying various characteristics of the field. The value
+ * of this entry replaces that of the Ff entry in the form's corresponding field dictionary.
+ * setfflags - a set of flags to be set (turned on) in the Ff entry of the form's corresponding
+ * field dictionary. Bits equal to 1 cause the corresponding bits in Ff to be set to 1.
+ * clrfflags - a set of flags to be cleared (turned off) in the Ff entry of the form's corresponding
+ * field dictionary. Bits equal to 1 cause the corresponding bits in Ff
+ * to be set to 0.
+ *
+ * @param field the field name
+ * @param name the property name
+ * @param value the property value
+ * @param inst an array of int
indexing into AcroField.Item.merged
elements to process.
+ * Set to null
to process all
+ * @return true
if the property exists, false
otherwise
+ */
+ public boolean setFieldProperty(String field, String name, int value, int inst[]) {
+ if (writer == null)
+ throw new RuntimeException("This AcroFields instance is read-only.");
+ Item item = (Item)fields.get(field);
+ if (item == null)
+ return false;
+ InstHit hit = new InstHit(inst);
+ if (name.equalsIgnoreCase("flags")) {
+ PdfNumber num = new PdfNumber(value);
+ for (int k = 0; k < item.merged.size(); ++k) {
+ if (hit.isHit(k)) {
+ ((PdfDictionary)item.merged.get(k)).put(PdfName.F, num);
+ ((PdfDictionary)item.widgets.get(k)).put(PdfName.F, num);
+ markUsed((PdfDictionary)item.widgets.get(k));
+ }
+ }
+ }
+ else if (name.equalsIgnoreCase("setflags")) {
+ for (int k = 0; k < item.merged.size(); ++k) {
+ if (hit.isHit(k)) {
+ PdfNumber num = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.widgets.get(k)).get(PdfName.F));
+ int val = 0;
+ if (num != null)
+ val = num.intValue();
+ num = new PdfNumber(val | value);
+ ((PdfDictionary)item.merged.get(k)).put(PdfName.F, num);
+ ((PdfDictionary)item.widgets.get(k)).put(PdfName.F, num);
+ markUsed((PdfDictionary)item.widgets.get(k));
+ }
+ }
+ }
+ else if (name.equalsIgnoreCase("clrflags")) {
+ for (int k = 0; k < item.merged.size(); ++k) {
+ if (hit.isHit(k)) {
+ PdfNumber num = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.widgets.get(k)).get(PdfName.F));
+ int val = 0;
+ if (num != null)
+ val = num.intValue();
+ num = new PdfNumber(val & (~value));
+ ((PdfDictionary)item.merged.get(k)).put(PdfName.F, num);
+ ((PdfDictionary)item.widgets.get(k)).put(PdfName.F, num);
+ markUsed((PdfDictionary)item.widgets.get(k));
+ }
+ }
+ }
+ else if (name.equalsIgnoreCase("fflags")) {
+ PdfNumber num = new PdfNumber(value);
+ for (int k = 0; k < item.merged.size(); ++k) {
+ if (hit.isHit(k)) {
+ ((PdfDictionary)item.merged.get(k)).put(PdfName.FF, num);
+ ((PdfDictionary)item.values.get(k)).put(PdfName.FF, num);
+ markUsed((PdfDictionary)item.values.get(k));
+ }
+ }
+ }
+ else if (name.equalsIgnoreCase("setfflags")) {
+ for (int k = 0; k < item.merged.size(); ++k) {
+ if (hit.isHit(k)) {
+ PdfNumber num = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.values.get(k)).get(PdfName.FF));
+ int val = 0;
+ if (num != null)
+ val = num.intValue();
+ num = new PdfNumber(val | value);
+ ((PdfDictionary)item.merged.get(k)).put(PdfName.FF, num);
+ ((PdfDictionary)item.values.get(k)).put(PdfName.FF, num);
+ markUsed((PdfDictionary)item.values.get(k));
+ }
+ }
+ }
+ else if (name.equalsIgnoreCase("clrfflags")) {
+ for (int k = 0; k < item.merged.size(); ++k) {
+ if (hit.isHit(k)) {
+ PdfNumber num = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.values.get(k)).get(PdfName.FF));
+ int val = 0;
+ if (num != null)
+ val = num.intValue();
+ num = new PdfNumber(val & (~value));
+ ((PdfDictionary)item.merged.get(k)).put(PdfName.FF, num);
+ ((PdfDictionary)item.values.get(k)).put(PdfName.FF, num);
+ markUsed((PdfDictionary)item.values.get(k));
+ }
+ }
+ }
+ else
+ return false;
+ return true;
+ }
+
+ /** Sets the fields by FDF merging.
+ * @param fdf the FDF form
+ * @throws IOException on error
+ * @throws DocumentException on error
+ */
+ public boolean setFields(FdfReader fdf) throws IOException, DocumentException {
+ boolean ret_val_b= false; // ssteward
+ fdf.getFields();
+ for (Iterator i = fields.keySet().iterator(); i.hasNext();) {
+ String f = (String)i.next();
+ String v = fdf.getFieldValue(f);
+ String rv = fdf.getFieldRichValue(f); // ssteward
+ if (rv != null)
+ ret_val_b= true;
+ if (v != null)
+ setField(f, v, v, rv); // ssteward
+ }
+ return ret_val_b; // ssteward
+ }
+
+ /** Sets the fields by XFDF merging.
+ * @param xfdf the XFDF form
+ * @throws IOException on error
+ * @throws DocumentException on error
+ */
+ public boolean setFields(XfdfReader xfdf) throws IOException, DocumentException {
+ boolean ret_val_b= false; // ssteward
+ xfdf.getFields();
+ for (Iterator i = fields.keySet().iterator(); i.hasNext();) {
+ String f = (String)i.next();
+ String v = xfdf.getFieldValue(f);
+ String rv = xfdf.getFieldRichValue(f); // ssteward
+ if (rv != null)
+ ret_val_b= true;
+ if (v != null)
+ setField(f, v, v, rv); // ssteward
+ }
+ return ret_val_b; // ssteward
+ }
+
+ /** Sets the field value.
+ * @param name the fully qualified field name
+ * @param value the field value
+ * @throws IOException on error
+ * @throws DocumentException on error
+ * @return true
if the field was found and changed,
+ * false
otherwise
+ */
+ public boolean setField(String name, String value) throws IOException, DocumentException {
+ return setField(name, value, value, null); // ssteward
+ }
+ // ssteward; added for backward compatibility
+ public boolean setField(String name, String value, String display) throws IOException, DocumentException {
+ return setField(name, value, display, null);
+ }
+
+ /** Sets the field value and the display string. The display string
+ * is used to build the appearance in the cases where the value
+ * is modified by Acrobat with JavaScript and the algorithm is
+ * known.
+ * @param name the fully qualified field name
+ * @param value the field value
+ * @param display the string that is used for the appearance
+ * @param rich_value (ssteward)
+ * @return true
if the field was found and changed,
+ * false
otherwise
+ * @throws IOException on error
+ * @throws DocumentException on error
+ */
+ public boolean setField(String name, String value, String display, String rich_value) throws IOException, DocumentException {
+ if (writer == null)
+ throw new DocumentException("This AcroFields instance is read-only.");
+ Item item = (Item)fields.get(name);
+ if (item == null)
+ return false;
+ PdfName type = (PdfName)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.FT));
+ if (PdfName.TX.equals(type)) {
+ PdfNumber maxLen = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.MAXLEN));
+ int len = 0;
+ if (maxLen != null)
+ len = maxLen.intValue();
+ if (len > 0)
+ value = value.substring(0, Math.min(len, value.length()));
+ }
+ if (PdfName.TX.equals(type) || PdfName.CH.equals(type)) {
+ PdfString v = new PdfString(value, PdfObject.TEXT_UNICODE);
+ // ssteward
+ PdfString rv = null;
+ if( rich_value != null )
+ rv = new PdfString(rich_value, PdfObject.TEXT_UNICODE); // ssteward
+ for (int idx = 0; idx < item.values.size(); ++idx) {
+
+ PdfDictionary item_value= (PdfDictionary)item.values.get(idx);
+ item_value.put(PdfName.V, v);
+ markUsed(item_value);
+ if( rich_value != null ) // ssteward
+ item_value.put(PdfName.RV, rv);
+ item_value.remove(PdfName.I); // ssteward; it might disagree w/ V in a Ch widget
+ // PDF spec this shouldn't matter, but Reader 9 gives I precedence over V
+
+ PdfDictionary merged = (PdfDictionary)item.merged.get(idx);
+ merged.put(PdfName.V, v);
+ if( rich_value != null ) // ssteward
+ merged.put(PdfName.RV, rv);
+ merged.remove(PdfName.I); // ssteward
+
+ PdfDictionary widget = (PdfDictionary)item.widgets.get(idx);
+ if (generateAppearances) {
+ PdfAppearance app = getAppearance(merged, display, name);
+ if (PdfName.CH.equals(type)) {
+ PdfNumber n = new PdfNumber(topFirst);
+ widget.put(PdfName.TI, n);
+ merged.put(PdfName.TI, n);
+ }
+ PdfDictionary appDic = (PdfDictionary)PdfReader.getPdfObject(widget.get(PdfName.AP));
+ if (appDic == null) {
+ appDic = new PdfDictionary();
+ widget.put(PdfName.AP, appDic);
+ merged.put(PdfName.AP, appDic);
+ }
+ appDic.put(PdfName.N, app.getIndirectReference());
+ writer.releaseTemplate(app);
+ }
+ else {
+ widget.remove(PdfName.AP);
+ merged.remove(PdfName.AP);
+ }
+ markUsed(widget);
+ }
+ return true;
+ }
+ else if (PdfName.BTN.equals(type)) {
+ PdfNumber ff = (PdfNumber)PdfReader.getPdfObject(((PdfDictionary)item.merged.get(0)).get(PdfName.FF));
+ int flags = 0;
+ if (ff != null)
+ flags = ff.intValue();
+ if ((flags & PdfFormField.FF_PUSHBUTTON) != 0)
+ return true;
+ PdfName v = new PdfName(value);
+ if ((flags & PdfFormField.FF_RADIO) == 0) {
+ for (int idx = 0; idx < item.values.size(); ++idx) {
+ ((PdfDictionary)item.values.get(idx)).put(PdfName.V, v);
+ markUsed((PdfDictionary)item.values.get(idx));
+ PdfDictionary merged = (PdfDictionary)item.merged.get(idx);
+ merged.put(PdfName.V, v);
+ merged.put(PdfName.AS, v);
+ PdfDictionary widget = (PdfDictionary)item.widgets.get(idx);
+ if (isInAP(widget, v))
+ widget.put(PdfName.AS, v);
+ else
+ widget.put(PdfName.AS, PdfName.Off);
+ markUsed(widget);
+ }
+ }
+ else {
+ ArrayList lopt = new ArrayList();
+ PdfObject opts = PdfReader.getPdfObject(((PdfDictionary)item.values.get(0)).get(PdfName.OPT));
+ if (opts != null && opts.isArray()) {
+ ArrayList list = ((PdfArray)opts).getArrayList();
+ for (int k = 0; k < list.size(); ++k) {
+ PdfObject vv = PdfReader.getPdfObject((PdfObject)list.get(k));
+ if (vv != null && vv.isString())
+ lopt.add(((PdfString)vv).toUnicodeString());
+ else
+ lopt.add(null);
+ }
+ }
+ int vidx = lopt.indexOf(value);
+ PdfName valt = null;
+ PdfName vt;
+ if (vidx >= 0) {
+ vt = valt = new PdfName(String.valueOf(vidx));
+ }
+ else
+ vt = v;
+ for (int idx = 0; idx < item.values.size(); ++idx) {
+ PdfDictionary merged = (PdfDictionary)item.merged.get(idx);
+ PdfDictionary widget = (PdfDictionary)item.widgets.get(idx);
+ markUsed((PdfDictionary)item.values.get(idx));
+ if (valt != null) {
+ PdfString ps = new PdfString(value, PdfObject.TEXT_UNICODE);
+ ((PdfDictionary)item.values.get(idx)).put(PdfName.V, ps);
+ merged.put(PdfName.V, ps);
+ }
+ else {
+ ((PdfDictionary)item.values.get(idx)).put(PdfName.V, v);
+ merged.put(PdfName.V, v);
+ }
+ markUsed(widget);
+ if (isInAP(widget, vt)) {
+ merged.put(PdfName.AS, vt);
+ widget.put(PdfName.AS, vt);
+ }
+ else {
+ merged.put(PdfName.AS, PdfName.Off);
+ widget.put(PdfName.AS, PdfName.Off);
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ boolean isInAP(PdfDictionary dic, PdfName check) {
+ PdfDictionary appDic = (PdfDictionary)PdfReader.getPdfObject(dic.get(PdfName.AP));
+ if (appDic == null)
+ return false;
+ PdfDictionary NDic = (PdfDictionary)PdfReader.getPdfObject(appDic.get(PdfName.N));
+ return (NDic != null && NDic.get(check) != null);
+ }
+
+ /** Gets all the fields. The fields are keyed by the fully qualified field name and
+ * the value is an instance of AcroFields.Item
.
+ * @return all the fields
+ */
+ public HashMap getFields() {
+ return fields;
+ }
+
+ /**
+ * Gets the field structure.
+ * @param name the name of the field
+ * @return the field structure or null
if the field
+ * does not exist
+ */
+ public Item getFieldItem(String name) {
+ return (Item)fields.get(name);
+ }
+
+ /**
+ * Gets the field box positions in the document. The return is an array of float
+ * multiple of 5. For each of this groups the values are: [page, llx, lly, urx,
+ * ury].
+ * @param name the field name
+ * @return the positions or null
if field does not exist
+ */
+ public float[] getFieldPositions(String name) {
+ Item item = (Item)fields.get(name);
+ if (item == null)
+ return null;
+ float ret[] = new float[item.page.size() * 5];
+ int ptr = 0;
+ for (int k = 0; k < item.page.size(); ++k) {
+ try {
+ PdfDictionary wd = (PdfDictionary)item.widgets.get(k);
+ PdfArray rect = (PdfArray)wd.get(PdfName.RECT);
+ if (rect == null)
+ continue;
+ Rectangle r = PdfReader.getNormalizedRectangle(rect);
+ ret[ptr] = ((Integer)item.page.get(k)).floatValue();
+ ++ptr;
+ ret[ptr++] = r.left();
+ ret[ptr++] = r.bottom();
+ ret[ptr++] = r.right();
+ ret[ptr++] = r.top();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ if (ptr < ret.length) {
+ float ret2[] = new float[ptr];
+ System.arraycopy(ret, 0, ret2, 0, ptr);
+ return ret2;
+ }
+ return ret;
+ }
+
+ private int removeRefFromArray(PdfArray array, PdfObject refo) {
+ ArrayList ar = array.getArrayList();
+ if (refo == null || !refo.isIndirect())
+ return ar.size();
+ PdfIndirectReference ref = (PdfIndirectReference)refo;
+ for (int j = 0; j < ar.size(); ++j) {
+ PdfObject obj = (PdfObject)ar.get(j);
+ if (!obj.isIndirect())
+ continue;
+ if (((PdfIndirectReference)obj).getNumber() == ref.getNumber())
+ ar.remove(j--);
+ }
+ return ar.size();
+ }
+
+ /**
+ * Removes all the fields from page
.
+ * @param page the page to remove the fields from
+ * @return true
if any field was removed, false otherwise
+ */
+ public boolean removeFieldsFromPage(int page) {
+ if (page < 1)
+ return false;
+ String names[] = new String[fields.size()];
+ fields.keySet().toArray(names);
+ boolean found = false;
+ for (int k = 0; k < names.length; ++k) {
+ boolean fr = removeField(names[k], page);
+ found = (found || fr);
+ }
+ return found;
+ }
+
+ /**
+ * Removes a field from the document. If page equals -1 all the fields with this
+ * name
are removed from the document otherwise only the fields in
+ * that particular page are removed.
+ * @param name the field name
+ * @param page the page to remove the field from or -1 to remove it from all the pages
+ * @return true
if the field exists, false otherwise
+ */
+ public boolean removeField(String name, int page) {
+ Item item = (Item)fields.get(name);
+ if (item == null)
+ return false;
+ PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM), reader.getCatalog());
+
+ if (acroForm == null)
+ return false;
+ PdfArray arrayf = (PdfArray)PdfReader.getPdfObject(acroForm.get(PdfName.FIELDS), acroForm);
+ if (arrayf == null)
+ return false;
+ for (int k = 0; k < item.widget_refs.size(); ++k) {
+ int pageV = ((Integer)item.page.get(k)).intValue();
+ if (page != -1 && page != pageV)
+ continue;
+ PdfIndirectReference ref = (PdfIndirectReference)item.widget_refs.get(k);
+ PdfDictionary wd = (PdfDictionary)PdfReader.getPdfObject(ref);
+ PdfDictionary pageDic = reader.getPageN(pageV);
+ PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS), pageDic);
+ if (annots != null) {
+ if (removeRefFromArray(annots, ref) == 0) {
+ pageDic.remove(PdfName.ANNOTS);
+ markUsed(pageDic);
+ }
+ else
+ markUsed(annots);
+ }
+ PdfReader.killIndirect(ref);
+ PdfIndirectReference kid = ref;
+ while ((ref = (PdfIndirectReference)wd.get(PdfName.PARENT)) != null) {
+ wd = (PdfDictionary)PdfReader.getPdfObject(ref);
+ PdfArray kids = (PdfArray)PdfReader.getPdfObject(wd.get(PdfName.KIDS));
+ if (removeRefFromArray(kids, kid) != 0)
+ break;
+ kid = ref;
+ PdfReader.killIndirect(ref);
+ }
+ if (ref == null) {
+ removeRefFromArray(arrayf, kid);
+ markUsed(arrayf);
+ }
+ if (page != -1) {
+ item.merged.remove(k);
+ item.page.remove(k);
+ item.values.remove(k);
+ item.widget_refs.remove(k);
+ item.widgets.remove(k);
+ --k;
+ }
+ }
+ if (page == -1 || item.merged.size() == 0)
+ fields.remove(name);
+ return true;
+ }
+
+ /**
+ * Removes a field from the document.
+ * @param name the field name
+ * @return true
if the field exists, false otherwise
+ */
+ public boolean removeField(String name) {
+ return removeField(name, -1);
+ }
+
+ /** Gets the property generateAppearances.
+ * @return the property generateAppearances
+ */
+ public boolean isGenerateAppearances() {
+ return this.generateAppearances;
+ }
+
+ /** Sets the option to generate appearances. Not generating apperances
+ * will speed-up form filling but the results can be
+ * unexpected in Acrobat. Don't use it unless your environment is well
+ * controlled. The default is true
.
+ * @param generateAppearances the option to generate appearances
+ */
+ public void setGenerateAppearances(boolean generateAppearances) {
+ this.generateAppearances = generateAppearances;
+ PdfDictionary top = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM));
+ if (generateAppearances)
+ top.remove(PdfName.NEEDAPPEARANCES);
+ else
+ top.put(PdfName.NEEDAPPEARANCES, PdfBoolean.PDFTRUE);
+ }
+
+ /** The field representations for retrieval and modification. */
+ public static class Item {
+ /** An array of PdfDictionary
where the value tag /V
+ * is present.
+ */
+ public ArrayList values = new ArrayList();
+ /** An array of PdfDictionary
with the widgets.
+ */
+ public ArrayList widgets = new ArrayList();
+ /** An array of PdfDictionary
with the widget references.
+ */
+ public ArrayList widget_refs = new ArrayList();
+ /** An array of PdfDictionary
with all the field
+ * and widget tags merged.
+ */
+ public ArrayList merged = new ArrayList();
+ /** An array of Integer
with the page numbers where
+ * the widgets are displayed.
+ */
+ public ArrayList page = new ArrayList();
+ /** An array of Integer
with the tab order of the field in the page.
+ */
+ public ArrayList tabOrder = new ArrayList();
+ }
+
+ private static class InstHit {
+ IntHashtable hits;
+ public InstHit(int inst[]) {
+ if (inst == null)
+ return;
+ hits = new IntHashtable();
+ for (int k = 0; k < inst.length; ++k)
+ hits.put(inst[k], 1);
+ }
+
+ public boolean isHit(int n) {
+ if (hits == null)
+ return true;
+ return hits.containsKey(n);
+ }
+ }
+
+ /**
+ * Gets the field names that have signatures and are signed.
+ * @return the field names that have signatures and are signed
+ */
+ public ArrayList getSignatureNames() {
+ if (sigNames != null)
+ return new ArrayList(sigNames.keySet());
+ sigNames = new HashMap();
+ ArrayList sorter = new ArrayList();
+ for (Iterator it = fields.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry)it.next();
+ Item item = (Item)entry.getValue();
+ PdfDictionary merged = (PdfDictionary)item.merged.get(0);
+ if (!PdfName.SIG.equals(merged.get(PdfName.FT)))
+ continue;
+ PdfObject vo = PdfReader.getPdfObject(merged.get(PdfName.V));
+ if (vo == null || vo.type() != PdfObject.DICTIONARY)
+ continue;
+ PdfDictionary v = (PdfDictionary)vo;
+ PdfObject contents = v.get(PdfName.CONTENTS);
+ if (contents == null || contents.type() != PdfObject.STRING)
+ continue;
+ PdfObject ro = v.get(PdfName.BYTERANGE);
+ if (ro == null || ro.type() != PdfObject.ARRAY)
+ continue;
+ ArrayList ra = ((PdfArray)ro).getArrayList();
+ if (ra.size() < 2)
+ continue;
+ int length = ((PdfNumber)ra.get(ra.size() - 1)).intValue() + ((PdfNumber)ra.get(ra.size() - 2)).intValue();
+ sorter.add(new Object[]{entry.getKey(), new int[]{length, 0}});
+ }
+ Collections.sort(sorter, new AcroFields.SorterComparator());
+ if (sorter.size() > 0) {
+ if (((int[])((Object[])sorter.get(sorter.size() - 1))[1])[0] == reader.getFileLength())
+ totalRevisions = sorter.size();
+ else
+ totalRevisions = sorter.size() + 1;
+ for (int k = 0; k < sorter.size(); ++k) {
+ Object objs[] = (Object[])sorter.get(k);
+ String name = (String)objs[0];
+ int p[] = (int[])objs[1];
+ p[1] = k + 1;
+ sigNames.put(name, p);
+ }
+ }
+ return new ArrayList(sigNames.keySet());
+ }
+
+ /**
+ * Gets the field names that have blank signatures.
+ * @return the field names that have blank signatures
+ */
+ public ArrayList getBlankSignatureNames() {
+ getSignatureNames();
+ ArrayList sigs = new ArrayList();
+ for (Iterator it = fields.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry)it.next();
+ Item item = (Item)entry.getValue();
+ PdfDictionary merged = (PdfDictionary)item.merged.get(0);
+ if (!PdfName.SIG.equals(merged.get(PdfName.FT)))
+ continue;
+ if (sigNames.containsKey(entry.getKey()))
+ continue;
+ sigs.add(entry.getKey());
+ }
+ return sigs;
+ }
+
+ /**
+ * Gets the signature dictionary, the one keyed by /V.
+ * @param name the field name
+ * @return the signature dictionary keyed by /V or null
if the field is not
+ * a signature
+ */
+ public PdfDictionary getSignatureDictionary(String name) {
+ getSignatureNames();
+ if (!sigNames.containsKey(name))
+ return null;
+ Item item = (Item)fields.get(name);
+ PdfDictionary merged = (PdfDictionary)item.merged.get(0);
+ // PdfObject vo = PdfReader.getPdfObject(merged.get(PdfName.V));
+ return (PdfDictionary)PdfReader.getPdfObject(merged.get(PdfName.V));
+ }
+
+ /**
+ * Checks is the signature covers the entire document or just part of it.
+ * @param name the signature field name
+ * @return true
if the signature covers the entire document,
+ * false
otherwise
+ */
+ public boolean signatureCoversWholeDocument(String name) {
+ getSignatureNames();
+ if (!sigNames.containsKey(name))
+ return false;
+ return ((int[])sigNames.get(name))[0] == reader.getFileLength();
+ }
+
+ /**
+ * Verifies a signature. An example usage is:
+ *
+ *
+ * KeyStore kall = PdfPKCS7.loadCacertsKeyStore();
+ * PdfReader reader = new PdfReader("my_signed_doc.pdf");
+ * AcroFields af = reader.getAcroFields();
+ * ArrayList names = af.getSignatureNames();
+ * for (int k = 0; k < names.size(); ++k) {
+ * String name = (String)names.get(k);
+ * System.out.println("Signature name: " + name);
+ * System.out.println("Signature covers whole document: " + af.signatureCoversWholeDocument(name));
+ * PdfPKCS7 pk = af.verifySignature(name);
+ * Calendar cal = pk.getSignDate();
+ * Certificate pkc[] = pk.getCertificates();
+ * System.out.println("Subject: " + PdfPKCS7.getSubjectFields(pk.getSigningCertificate()));
+ * System.out.println("Document modified: " + !pk.verify());
+ * Object fails[] = PdfPKCS7.verifyCertificates(pkc, kall, null, cal);
+ * if (fails == null)
+ * System.out.println("Certificates verified against the KeyStore");
+ * else
+ * System.out.println("Certificate failed: " + fails[1]);
+ * }
+ *
+ * @param name the signature field name
+ * @return a PdfPKCS7
class to continue the verification
+ */
+ public PdfPKCS7 verifySignature(String name) {
+ return verifySignature(name, null);
+ }
+
+ /**
+ * Verifies a signature. An example usage is:
+ *
+ *
+ * KeyStore kall = PdfPKCS7.loadCacertsKeyStore();
+ * PdfReader reader = new PdfReader("my_signed_doc.pdf");
+ * AcroFields af = reader.getAcroFields();
+ * ArrayList names = af.getSignatureNames();
+ * for (int k = 0; k < names.size(); ++k) {
+ * String name = (String)names.get(k);
+ * System.out.println("Signature name: " + name);
+ * System.out.println("Signature covers whole document: " + af.signatureCoversWholeDocument(name));
+ * PdfPKCS7 pk = af.verifySignature(name);
+ * Calendar cal = pk.getSignDate();
+ * Certificate pkc[] = pk.getCertificates();
+ * System.out.println("Subject: " + PdfPKCS7.getSubjectFields(pk.getSigningCertificate()));
+ * System.out.println("Document modified: " + !pk.verify());
+ * Object fails[] = PdfPKCS7.verifyCertificates(pkc, kall, null, cal);
+ * if (fails == null)
+ * System.out.println("Certificates verified against the KeyStore");
+ * else
+ * System.out.println("Certificate failed: " + fails[1]);
+ * }
+ *
+ * @param name the signature field name
+ * @param provider the provider or null
for the default provider
+ * @return a PdfPKCS7
class to continue the verification
+ */
+ public PdfPKCS7 verifySignature(String name, String provider) {
+ PdfDictionary v = getSignatureDictionary(name);
+ if (v == null)
+ return null;
+ try {
+ PdfName sub = (PdfName)PdfReader.getPdfObject(v.get(PdfName.SUBFILTER));
+ PdfString contents = (PdfString)PdfReader.getPdfObject(v.get(PdfName.CONTENTS));
+ PdfPKCS7 pk = null;
+ if (sub.equals(PdfName.ADBE_X509_RSA_SHA1)) {
+ PdfString cert = (PdfString)PdfReader.getPdfObject(v.get(PdfName.CERT));
+ pk = new PdfPKCS7(contents.getOriginalBytes(), cert.getBytes(), provider);
+ }
+ else
+ pk = new PdfPKCS7(contents.getOriginalBytes(), provider);
+ updateByteRange(pk, v);
+ PdfString str = (PdfString)PdfReader.getPdfObject(v.get(PdfName.M));
+ if (str != null)
+ pk.setSignDate(PdfDate.decode(str.toString()));
+ str = (PdfString)PdfReader.getPdfObject(v.get(PdfName.NAME));
+ if (str != null)
+ pk.setSignName(str.toUnicodeString());
+ str = (PdfString)PdfReader.getPdfObject(v.get(PdfName.REASON));
+ if (str != null)
+ pk.setReason(str.toUnicodeString());
+ str = (PdfString)PdfReader.getPdfObject(v.get(PdfName.LOCATION));
+ if (str != null)
+ pk.setLocation(str.toUnicodeString());
+ return pk;
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ private void updateByteRange(PdfPKCS7 pkcs7, PdfDictionary v) {
+ PdfArray b = (PdfArray)PdfReader.getPdfObject(v.get(PdfName.BYTERANGE));
+ RandomAccessFileOrArray rf = reader.getSafeFile();
+ try {
+ rf.reOpen();
+ byte buf[] = new byte[8192];
+ ArrayList ar = b.getArrayList();
+ for (int k = 0; k < ar.size(); ++k) {
+ int start = ((PdfNumber)ar.get(k)).intValue();
+ int length = ((PdfNumber)ar.get(++k)).intValue();
+ rf.seek(start);
+ while (length > 0) {
+ int rd = rf.read(buf, 0, Math.min(length, buf.length));
+ if (rd <= 0)
+ break;
+ length -= rd;
+ pkcs7.update(buf, 0, rd);
+ }
+ }
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ finally {
+ try{rf.close();}catch(Exception e){}
+ }
+ }
+
+ private void markUsed(PdfObject obj) {
+ if (!append)
+ return;
+ ((PdfStamperImp)writer).markUsed(obj);
+ }
+
+ /**
+ * Gets the total number of revisions this document has.
+ * @return the total number of revisions
+ */
+ public int getTotalRevisions() {
+ getSignatureNames();
+ return this.totalRevisions;
+ }
+
+ /**
+ * Gets this field
revision.
+ * @param field the signature field name
+ * @return the revision or zero if it's not a signature field
+ */
+ public int getRevision(String field) {
+ getSignatureNames();
+ if (!sigNames.containsKey(field))
+ return 0;
+ return ((int[])sigNames.get(field))[1];
+ }
+
+ /**
+ * Extracts a revision from the document.
+ * @param field the signature field name
+ * @return an InputStream
covering the revision. Returns null
if
+ * it's not a signature field
+ * @throws IOException on error
+ */
+ public InputStream extractRevision(String field) throws IOException {
+ getSignatureNames();
+ int length = ((int[])sigNames.get(field))[0];
+ RandomAccessFileOrArray raf = reader.getSafeFile();
+ raf.reOpen();
+ raf.seek(0);
+ return new RevisionStream(raf, length);
+ }
+
+ /**
+ * Gets the appearances cache.
+ * @return the appearances cache
+ */
+ public HashMap getFieldCache() {
+ return this.fieldCache;
+ }
+
+ /**
+ * Sets a cache for field appearances. Parsing the existing PDF to
+ * create a new TextField is time expensive. For those tasks that repeatedly
+ * fill the same PDF with different field values the use of the cache has dramatic
+ * speed advantages. An example usage:
+ *
+ *
+ * String pdfFile = ...;// the pdf file used as template
+ * ArrayList xfdfFiles = ...;// the xfdf file names
+ * ArrayList pdfOutFiles = ...;// the output file names, one for each element in xpdfFiles
+ * HashMap cache = new HashMap();// the appearances cache
+ * PdfReader originalReader = new PdfReader(pdfFile);
+ * for (int k = 0; k < xfdfFiles.size(); ++k) {
+ * PdfReader reader = new PdfReader(originalReader);
+ * XfdfReader xfdf = new XfdfReader((String)xfdfFiles.get(k));
+ * PdfStamper stp = new PdfStamper(reader, new FileOutputStream((String)pdfOutFiles.get(k)));
+ * AcroFields af = stp.getAcroFields();
+ * af.setFieldCache(cache);
+ * af.setFields(xfdf);
+ * stp.close();
+ * }
+ *
+ * @param fieldCache an HasMap that will carry the cached appearances
+ */
+ public void setFieldCache(HashMap fieldCache) {
+ this.fieldCache = fieldCache;
+ }
+
+ /**
+ * Sets extra margins in text fields to better mimic the Acrobat layout.
+ * @param extraMarginLeft the extra marging left
+ * @param extraMarginTop the extra margin top
+ */
+ public void setExtraMargin(float extraMarginLeft, float extraMarginTop) {
+ this.extraMarginLeft = extraMarginLeft;
+ this.extraMarginTop = extraMarginTop;
+ }
+
+ private static final HashMap stdFieldFontNames = new HashMap();
+
+ /**
+ * Holds value of property totalRevisions.
+ */
+ private int totalRevisions;
+
+ /**
+ * Holds value of property fieldCache.
+ */
+ private HashMap fieldCache;
+
+ static {
+ stdFieldFontNames.put("CoBO", new String[]{"Courier-BoldOblique"});
+ stdFieldFontNames.put("CoBo", new String[]{"Courier-Bold"});
+ stdFieldFontNames.put("CoOb", new String[]{"Courier-Oblique"});
+ stdFieldFontNames.put("Cour", new String[]{"Courier"});
+ stdFieldFontNames.put("HeBO", new String[]{"Helvetica-BoldOblique"});
+ stdFieldFontNames.put("HeBo", new String[]{"Helvetica-Bold"});
+ stdFieldFontNames.put("HeOb", new String[]{"Helvetica-Oblique"});
+ stdFieldFontNames.put("Helv", new String[]{"Helvetica"});
+ stdFieldFontNames.put("Symb", new String[]{"Symbol"});
+ stdFieldFontNames.put("TiBI", new String[]{"Times-BoldItalic"});
+ stdFieldFontNames.put("TiBo", new String[]{"Times-Bold"});
+ stdFieldFontNames.put("TiIt", new String[]{"Times-Italic"});
+ stdFieldFontNames.put("TiRo", new String[]{"Times-Roman"});
+ stdFieldFontNames.put("ZaDb", new String[]{"ZapfDingbats"});
+ stdFieldFontNames.put("HySm", new String[]{"HYSMyeongJo-Medium", "UniKS-UCS2-H"});
+ stdFieldFontNames.put("HyGo", new String[]{"HYGoThic-Medium", "UniKS-UCS2-H"});
+ stdFieldFontNames.put("KaGo", new String[]{"HeiseiKakuGo-W5", "UniKS-UCS2-H"});
+ stdFieldFontNames.put("KaMi", new String[]{"HeiseiMin-W3", "UniJIS-UCS2-H"});
+ stdFieldFontNames.put("MHei", new String[]{"MHei-Medium", "UniCNS-UCS2-H"});
+ stdFieldFontNames.put("MSun", new String[]{"MSung-Light", "UniCNS-UCS2-H"});
+ stdFieldFontNames.put("STSo", new String[]{"STSong-Light", "UniGB-UCS2-H"});
+ }
+
+ private static class RevisionStream extends InputStream {
+ private byte b[] = new byte[1];
+ private RandomAccessFileOrArray raf;
+ private int length;
+ private int rangePosition = 0;
+ private boolean closed;
+
+ private RevisionStream(RandomAccessFileOrArray raf, int length) {
+ this.raf = raf;
+ this.length = length;
+ }
+
+ public int read() throws IOException {
+ int n = read(b);
+ if (n != 1)
+ return -1;
+ return b[0] & 0xff;
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) > b.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+ if (rangePosition >= length) {
+ close();
+ return -1;
+ }
+ int elen = Math.min(len, length - rangePosition);
+ raf.readFully(b, off, elen);
+ rangePosition += elen;
+ return elen;
+ }
+
+ public void close() throws IOException {
+ if (!closed) {
+ raf.close();
+ closed = true;
+ }
+ }
+ }
+
+ private static class SorterComparator implements Comparator {
+ public int compare(Object o1, Object o2) {
+ int n1 = ((int[])((Object[])o1)[1])[0];
+ int n2 = ((int[])((Object[])o2)[1])[0];
+ return n1 - n2;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ArabicLigaturizer.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ArabicLigaturizer.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ArabicLigaturizer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ArabicLigaturizer.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,761 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+/** Shape arabic characters. This code was converted from a C version
+ * at www.pango.org.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class ArabicLigaturizer {
+
+ static boolean isVowel(char s) {
+ return ((s >= 0x064B) && (s <= 0x0655)) || (s == 0x0670);
+ }
+
+ static char charshape(char s, int which)
+ /* which 0=isolated 1=final 2=initial 3=medial */
+ {
+ int l, r, m;
+ if ((s >= 0x0621) && (s <= 0x06D3)) {
+ l = 0;
+ r = chartable.length - 1;
+ while (l <= r) {
+ m = (l + r) / 2;
+ if (s == chartable[m][0]) {
+ return chartable[m][which + 1];
+ }
+ else if (s < chartable[m][0]) {
+ r = m - 1;
+ }
+ else {
+ l = m + 1;
+ }
+ }
+ }
+ else if (s >= 0xfef5 && s <= 0xfefb)
+ return (char)(s + which);
+ return s;
+ }
+
+ static int shapecount(char s) {
+ int l, r, m;
+ if ((s >= 0x0621) && (s <= 0x06D3) && !isVowel(s)) {
+ l = 0;
+ r = chartable.length - 1;
+ while (l <= r) {
+ m = (l + r) / 2;
+ if (s == chartable[m][0]) {
+ return chartable[m].length - 1;
+ }
+ else if (s < chartable[m][0]) {
+ r = m - 1;
+ }
+ else {
+ l = m + 1;
+ }
+ }
+ }
+ else if (s == ZWJ) {
+ return 4;
+ }
+ return 1;
+ }
+
+ static int ligature(char newchar, charstruct oldchar) {
+ /* 0 == no ligature possible; 1 == vowel; 2 == two chars; 3 == Lam+Alef */
+ int retval = 0;
+
+ if (oldchar.basechar == 0)
+ return 0;
+ if (isVowel(newchar)) {
+ retval = 1;
+ if ((oldchar.vowel != 0) && (newchar != SHADDA)) {
+ retval = 2; /* we eliminate the old vowel .. */
+ }
+ switch (newchar) {
+ case SHADDA:
+ if (oldchar.mark1 == 0) {
+ oldchar.mark1 = SHADDA;
+ }
+ else {
+ return 0; /* no ligature possible */
+ }
+ break;
+ case HAMZABELOW:
+ switch (oldchar.basechar) {
+ case ALEF:
+ oldchar.basechar = ALEFHAMZABELOW;
+ retval = 2;
+ break;
+ case LAM_ALEF:
+ oldchar.basechar = LAM_ALEFHAMZABELOW;
+ retval = 2;
+ break;
+ default:
+ oldchar.mark1 = HAMZABELOW;
+ break;
+ }
+ break;
+ case HAMZAABOVE:
+ switch (oldchar.basechar) {
+ case ALEF:
+ oldchar.basechar = ALEFHAMZA;
+ retval = 2;
+ break;
+ case LAM_ALEF:
+ oldchar.basechar = LAM_ALEFHAMZA;
+ retval = 2;
+ break;
+ case WAW:
+ oldchar.basechar = WAWHAMZA;
+ retval = 2;
+ break;
+ case YEH:
+ case ALEFMAKSURA:
+ case FARSIYEH:
+ oldchar.basechar = YEHHAMZA;
+ retval = 2;
+ break;
+ default: /* whatever sense this may make .. */
+ oldchar.mark1 = HAMZAABOVE;
+ break;
+ }
+ break;
+ case MADDA:
+ switch (oldchar.basechar) {
+ case ALEF:
+ oldchar.basechar = ALEFMADDA;
+ retval = 2;
+ break;
+ }
+ break;
+ default:
+ oldchar.vowel = newchar;
+ break;
+ }
+ if (retval == 1) {
+ oldchar.lignum++;
+ }
+ return retval;
+ }
+ if (oldchar.vowel != 0) { /* if we already joined a vowel, we can't join a Hamza */
+ return 0;
+ }
+
+ switch (oldchar.basechar) {
+ case LAM:
+ switch (newchar) {
+ case ALEF:
+ oldchar.basechar = LAM_ALEF;
+ oldchar.numshapes = 2;
+ retval = 3;
+ break;
+ case ALEFHAMZA:
+ oldchar.basechar = LAM_ALEFHAMZA;
+ oldchar.numshapes = 2;
+ retval = 3;
+ break;
+ case ALEFHAMZABELOW:
+ oldchar.basechar = LAM_ALEFHAMZABELOW;
+ oldchar.numshapes = 2;
+ retval = 3;
+ break;
+ case ALEFMADDA:
+ oldchar.basechar = LAM_ALEFMADDA;
+ oldchar.numshapes = 2;
+ retval = 3;
+ break;
+ }
+ break;
+ case 0:
+ oldchar.basechar = newchar;
+ oldchar.numshapes = shapecount(newchar);
+ retval = 1;
+ break;
+ }
+ return retval;
+ }
+
+ static void copycstostring(StringBuffer string, charstruct s, int level) {
+ /* s is a shaped charstruct; i is the index into the string */
+ if (s.basechar == 0)
+ return;
+
+ string.append(s.basechar);
+ s.lignum--;
+ if (s.mark1 != 0) {
+ if ((level & ar_novowel) == 0) {
+ string.append(s.mark1);
+ s.lignum--;
+ }
+ else {
+ s.lignum--;
+ }
+ }
+ if (s.vowel != 0) {
+ if ((level & ar_novowel) == 0) {
+ string.append(s.vowel);
+ s.lignum--;
+ }
+ else { /* vowel elimination */
+ s.lignum--;
+ }
+ }
+// while (s.lignum > 0) { /* NULL-insertion for Langbox-font */
+// string[i] = 0;
+// i++;
+// (s.lignum)--;
+// }
+// return i;
+ }
+
+ // return len
+ static void doublelig(StringBuffer string, int level)
+ /* Ok. We have presentation ligatures in our font. */
+ {
+ int len;
+ int olen = len = string.length();
+ int j = 0, si = 1;
+ char lapresult;
+
+ while (si < olen) {
+ lapresult = 0;
+ if ((level & ar_composedtashkeel) != 0) {
+ switch (string.charAt(j)) {
+ case SHADDA:
+ switch (string.charAt(si)) {
+ case KASRA:
+ lapresult = 0xFC62;
+ break;
+ case FATHA:
+ lapresult = 0xFC60;
+ break;
+ case DAMMA:
+ lapresult = 0xFC61;
+ break;
+ case 0x064C:
+ lapresult = 0xFC5E;
+ break;
+ case 0x064D:
+ lapresult = 0xFC5F;
+ break;
+ }
+ break;
+ case KASRA:
+ if (string.charAt(si) == SHADDA)
+ lapresult = 0xFC62;
+ break;
+ case FATHA:
+ if (string.charAt(si) == SHADDA)
+ lapresult = 0xFC60;
+ break;
+ case DAMMA:
+ if (string.charAt(si) == SHADDA)
+ lapresult = 0xFC61;
+ break;
+ }
+ }
+
+ if ((level & ar_lig) != 0) {
+ switch (string.charAt(j)) {
+ case 0xFEDF: /* LAM initial */
+ switch (string.charAt(si)) {
+ case 0xFE9E:
+ lapresult = 0xFC3F;
+ break; /* JEEM final */
+ case 0xFEA0:
+ lapresult = 0xFCC9;
+ break; /* JEEM medial */
+ case 0xFEA2:
+ lapresult = 0xFC40;
+ break; /* HAH final */
+ case 0xFEA4:
+ lapresult = 0xFCCA;
+ break; /* HAH medial */
+ case 0xFEA6:
+ lapresult = 0xFC41;
+ break; /* KHAH final */
+ case 0xFEA8:
+ lapresult = 0xFCCB;
+ break; /* KHAH medial */
+ case 0xFEE2:
+ lapresult = 0xFC42;
+ break; /* MEEM final */
+ case 0xFEE4:
+ lapresult = 0xFCCC;
+ break; /* MEEM medial */
+ }
+ break;
+ case 0xFE97: /* TEH inital */
+ switch (string.charAt(si)) {
+ case 0xFEA0:
+ lapresult = 0xFCA1;
+ break; /* JEEM medial */
+ case 0xFEA4:
+ lapresult = 0xFCA2;
+ break; /* HAH medial */
+ case 0xFEA8:
+ lapresult = 0xFCA3;
+ break; /* KHAH medial */
+ }
+ break;
+ case 0xFE91: /* BEH inital */
+ switch (string.charAt(si)) {
+ case 0xFEA0:
+ lapresult = 0xFC9C;
+ break; /* JEEM medial */
+ case 0xFEA4:
+ lapresult = 0xFC9D;
+ break; /* HAH medial */
+ case 0xFEA8:
+ lapresult = 0xFC9E;
+ break; /* KHAH medial */
+ }
+ break;
+ case 0xFEE7: /* NOON inital */
+ switch (string.charAt(si)) {
+ case 0xFEA0:
+ lapresult = 0xFCD2;
+ break; /* JEEM initial */
+ case 0xFEA4:
+ lapresult = 0xFCD3;
+ break; /* HAH medial */
+ case 0xFEA8:
+ lapresult = 0xFCD4;
+ break; /* KHAH medial */
+ }
+ break;
+
+ case 0xFEE8: /* NOON medial */
+ switch (string.charAt(si)) {
+ case 0xFEAE:
+ lapresult = 0xFC8A;
+ break; /* REH final */
+ case 0xFEB0:
+ lapresult = 0xFC8B;
+ break; /* ZAIN final */
+ }
+ break;
+ case 0xFEE3: /* MEEM initial */
+ switch (string.charAt(si)) {
+ case 0xFEA0:
+ lapresult = 0xFCCE;
+ break; /* JEEM medial */
+ case 0xFEA4:
+ lapresult = 0xFCCF;
+ break; /* HAH medial */
+ case 0xFEA8:
+ lapresult = 0xFCD0;
+ break; /* KHAH medial */
+ case 0xFEE4:
+ lapresult = 0xFCD1;
+ break; /* MEEM medial */
+ }
+ break;
+
+ case 0xFED3: /* FEH initial */
+ switch (string.charAt(si)) {
+ case 0xFEF2:
+ lapresult = 0xFC32;
+ break; /* YEH final */
+ }
+ break;
+
+ default:
+ break;
+ } /* end switch string[si] */
+ }
+ if (lapresult != 0) {
+ string.setCharAt(j, lapresult);
+ len--;
+ si++; /* jump over one character */
+ /* we'll have to change this, too. */
+ }
+ else {
+ j++;
+ string.setCharAt(j, string.charAt(si));
+ si++;
+ }
+ }
+ string.setLength(len);
+ }
+
+ static boolean connects_to_left(charstruct a) {
+ return a.numshapes > 2;
+ }
+
+ static void shape(char text[], StringBuffer string, int level) {
+ /* string is assumed to be empty and big enough.
+ * text is the original text.
+ * This routine does the basic arabic reshaping.
+ * *len the number of non-null characters.
+ *
+ * Note: We have to unshape each character first!
+ */
+ int join;
+ int which;
+ char nextletter;
+
+ int p = 0; /* initialize for output */
+ charstruct oldchar = new charstruct();
+ charstruct curchar = new charstruct();
+ while (p < text.length) {
+ nextletter = text[p++];
+ //nextletter = unshape (nextletter);
+
+ join = ligature(nextletter, curchar);
+ if (join == 0) { /* shape curchar */
+ int nc = shapecount(nextletter);
+ //(*len)++;
+ if (nc == 1) {
+ which = 0; /* final or isolated */
+ }
+ else {
+ which = 2; /* medial or initial */
+ }
+ if (connects_to_left(oldchar)) {
+ which++;
+ }
+
+ which = which % (curchar.numshapes);
+ curchar.basechar = charshape(curchar.basechar, which);
+
+ /* get rid of oldchar */
+ copycstostring(string, oldchar, level);
+ oldchar = curchar; /* new values in oldchar */
+
+ /* init new curchar */
+ curchar = new charstruct();
+ curchar.basechar = nextletter;
+ curchar.numshapes = nc;
+ curchar.lignum++;
+ // (*len) += unligature (&curchar, level);
+ }
+ else if (join == 1) {
+ }
+ // else
+ // {
+ // (*len) += unligature (&curchar, level);
+ // }
+ // p = g_utf8_next_char (p);
+ }
+
+ /* Handle last char */
+ if (connects_to_left(oldchar))
+ which = 1;
+ else
+ which = 0;
+ which = which % (curchar.numshapes);
+ curchar.basechar = charshape(curchar.basechar, which);
+
+ /* get rid of oldchar */
+ copycstostring(string, oldchar, level);
+ copycstostring(string, curchar, level);
+ }
+
+ static int arabic_shape(char src[], int srcoffset, int srclength, char dest[], int destoffset, int destlength, int level) {
+ char str[] = new char[srclength];
+ for (int k = srclength + srcoffset - 1; k >= srcoffset; --k)
+ str[k - srcoffset] = src[k];
+ StringBuffer string = new StringBuffer(srclength);
+ shape(str, string, level);
+ if ((level & (ar_composedtashkeel | ar_lig)) != 0)
+ doublelig(string, level);
+// string.reverse();
+ System.arraycopy(string.toString().toCharArray(), 0, dest, destoffset, string.length());
+ return string.length();
+ }
+
+ static void processNumbers(char text[], int offset, int length, int options) {
+ int limit = offset + length;
+ if ((options & DIGITS_MASK) != 0) {
+ char digitBase = '\u0030'; // European digits
+ switch (options & DIGIT_TYPE_MASK) {
+ case DIGIT_TYPE_AN:
+ digitBase = '\u0660'; // Arabic-Indic digits
+ break;
+
+ case DIGIT_TYPE_AN_EXTENDED:
+ digitBase = '\u06f0'; // Eastern Arabic-Indic digits (Persian and Urdu)
+ break;
+
+ default:
+ break;
+ }
+
+ switch (options & DIGITS_MASK) {
+ case DIGITS_EN2AN: {
+ int digitDelta = digitBase - '\u0030';
+ for (int i = offset; i < limit; ++i) {
+ char ch = text[i];
+ if (ch <= '\u0039' && ch >= '\u0030') {
+ text[i] += digitDelta;
+ }
+ }
+ }
+ break;
+
+ case DIGITS_AN2EN: {
+ char digitTop = (char)(digitBase + 9);
+ int digitDelta = '\u0030' - digitBase;
+ for (int i = offset; i < limit; ++i) {
+ char ch = text[i];
+ if (ch <= digitTop && ch >= digitBase) {
+ text[i] += digitDelta;
+ }
+ }
+ }
+ break;
+
+ case DIGITS_EN2AN_INIT_LR:
+ shapeToArabicDigitsWithContext(text, 0, length, digitBase, false);
+ break;
+
+ case DIGITS_EN2AN_INIT_AL:
+ shapeToArabicDigitsWithContext(text, 0, length, digitBase, true);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ static void shapeToArabicDigitsWithContext(char[] dest, int start, int length, char digitBase, boolean lastStrongWasAL) {
+ digitBase -= '0'; // move common adjustment out of loop
+
+ int limit = start + length;
+ for(int i = start; i < limit; ++i) {
+ char ch = dest[i];
+ switch (BidiOrder.getDirection(ch)) {
+ case BidiOrder.L:
+ case BidiOrder.R:
+ lastStrongWasAL = false;
+ break;
+ case BidiOrder.AL:
+ lastStrongWasAL = true;
+ break;
+ case BidiOrder.EN:
+ if (lastStrongWasAL && ch <= '\u0039') {
+ dest[i] = (char)(ch + digitBase);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private static final char ALEF = 0x0627;
+ private static final char ALEFHAMZA = 0x0623;
+ private static final char ALEFHAMZABELOW = 0x0625;
+ private static final char ALEFMADDA = 0x0622;
+ private static final char LAM = 0x0644;
+ private static final char HAMZA = 0x0621;
+ private static final char TATWEEL = 0x0640;
+ private static final char ZWJ = 0x200D;
+
+ private static final char HAMZAABOVE = 0x0654;
+ private static final char HAMZABELOW = 0x0655;
+
+ private static final char WAWHAMZA = 0x0624;
+ private static final char YEHHAMZA = 0x0626;
+ private static final char WAW = 0x0648;
+ private static final char ALEFMAKSURA = 0x0649;
+ private static final char YEH = 0x064A;
+ private static final char FARSIYEH = 0x06CC;
+
+ private static final char SHADDA = 0x0651;
+ private static final char KASRA = 0x0650;
+ private static final char FATHA = 0x064E;
+ private static final char DAMMA = 0x064F;
+ private static final char MADDA = 0x0653;
+
+ private static final char LAM_ALEF = 0xFEFB;
+ private static final char LAM_ALEFHAMZA = 0xFEF7;
+ private static final char LAM_ALEFHAMZABELOW = 0xFEF9;
+ private static final char LAM_ALEFMADDA = 0xFEF5;
+
+ private static final char chartable[][] = {
+ {0x0621, 0xFE80}, /* HAMZA */
+ {0x0622, 0xFE81, 0xFE82}, /* ALEF WITH MADDA ABOVE */
+ {0x0623, 0xFE83, 0xFE84}, /* ALEF WITH HAMZA ABOVE */
+ {0x0624, 0xFE85, 0xFE86}, /* WAW WITH HAMZA ABOVE */
+ {0x0625, 0xFE87, 0xFE88}, /* ALEF WITH HAMZA BELOW */
+ {0x0626, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C}, /* YEH WITH HAMZA ABOVE */
+ {0x0627, 0xFE8D, 0xFE8E}, /* ALEF */
+ {0x0628, 0xFE8F, 0xFE90, 0xFE91, 0xFE92}, /* BEH */
+ {0x0629, 0xFE93, 0xFE94}, /* TEH MARBUTA */
+ {0x062A, 0xFE95, 0xFE96, 0xFE97, 0xFE98}, /* TEH */
+ {0x062B, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C}, /* THEH */
+ {0x062C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0}, /* JEEM */
+ {0x062D, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4}, /* HAH */
+ {0x062E, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8}, /* KHAH */
+ {0x062F, 0xFEA9, 0xFEAA}, /* DAL */
+ {0x0630, 0xFEAB, 0xFEAC}, /* THAL */
+ {0x0631, 0xFEAD, 0xFEAE}, /* REH */
+ {0x0632, 0xFEAF, 0xFEB0}, /* ZAIN */
+ {0x0633, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4}, /* SEEN */
+ {0x0634, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8}, /* SHEEN */
+ {0x0635, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC}, /* SAD */
+ {0x0636, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0}, /* DAD */
+ {0x0637, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4}, /* TAH */
+ {0x0638, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8}, /* ZAH */
+ {0x0639, 0xFEC9, 0xFECA, 0xFECB, 0xFECC}, /* AIN */
+ {0x063A, 0xFECD, 0xFECE, 0xFECF, 0xFED0}, /* GHAIN */
+ {0x0640, 0x0640, 0x0640, 0x0640, 0x0640}, /* TATWEEL */
+ {0x0641, 0xFED1, 0xFED2, 0xFED3, 0xFED4}, /* FEH */
+ {0x0642, 0xFED5, 0xFED6, 0xFED7, 0xFED8}, /* QAF */
+ {0x0643, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC}, /* KAF */
+ {0x0644, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0}, /* LAM */
+ {0x0645, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4}, /* MEEM */
+ {0x0646, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8}, /* NOON */
+ {0x0647, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC}, /* HEH */
+ {0x0648, 0xFEED, 0xFEEE}, /* WAW */
+ {0x0649, 0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9}, /* ALEF MAKSURA */
+ {0x064A, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4}, /* YEH */
+ {0x0671, 0xFB50, 0xFB51}, /* ALEF WASLA */
+ {0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69}, /* TTEH */
+ {0x067A, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61}, /* TTEHEH */
+ {0x067B, 0xFB52, 0xFB53, 0xFB54, 0xFB55}, /* BEEH */
+ {0x067E, 0xFB56, 0xFB57, 0xFB58, 0xFB59}, /* PEH */
+ {0x067F, 0xFB62, 0xFB63, 0xFB64, 0xFB65}, /* TEHEH */
+ {0x0680, 0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D}, /* BEHEH */
+ {0x0683, 0xFB76, 0xFB77, 0xFB78, 0xFB79}, /* NYEH */
+ {0x0684, 0xFB72, 0xFB73, 0xFB74, 0xFB75}, /* DYEH */
+ {0x0686, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D}, /* TCHEH */
+ {0x0687, 0xFB7E, 0xFB7F, 0xFB80, 0xFB81}, /* TCHEHEH */
+ {0x0688, 0xFB88, 0xFB89}, /* DDAL */
+ {0x068C, 0xFB84, 0xFB85}, /* DAHAL */
+ {0x068D, 0xFB82, 0xFB83}, /* DDAHAL */
+ {0x068E, 0xFB86, 0xFB87}, /* DUL */
+ {0x0691, 0xFB8C, 0xFB8D}, /* RREH */
+ {0x0698, 0xFB8A, 0xFB8B}, /* JEH */
+ {0x06A4, 0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D}, /* VEH */
+ {0x06A6, 0xFB6E, 0xFB6F, 0xFB70, 0xFB71}, /* PEHEH */
+ {0x06A9, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91}, /* KEHEH */
+ {0x06AD, 0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6}, /* NG */
+ {0x06AF, 0xFB92, 0xFB93, 0xFB94, 0xFB95}, /* GAF */
+ {0x06B1, 0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D}, /* NGOEH */
+ {0x06B3, 0xFB96, 0xFB97, 0xFB98, 0xFB99}, /* GUEH */
+ {0x06BA, 0xFB9E, 0xFB9F}, /* NOON GHUNNA */
+ {0x06BB, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3}, /* RNOON */
+ {0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD}, /* HEH DOACHASHMEE */
+ {0x06C0, 0xFBA4, 0xFBA5}, /* HEH WITH YEH ABOVE */
+ {0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9}, /* HEH GOAL */
+ {0x06C5, 0xFBE0, 0xFBE1}, /* KIRGHIZ OE */
+ {0x06C6, 0xFBD9, 0xFBDA}, /* OE */
+ {0x06C7, 0xFBD7, 0xFBD8}, /* U */
+ {0x06C8, 0xFBDB, 0xFBDC}, /* YU */
+ {0x06C9, 0xFBE2, 0xFBE3}, /* KIRGHIZ YU */
+ {0x06CB, 0xFBDE, 0xFBDF}, /* VE */
+ {0x06CC, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF}, /* FARSI YEH */
+ {0x06D0, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7}, /* E */
+ {0x06D2, 0xFBAE, 0xFBAF}, /* YEH BARREE */
+ {0x06D3, 0xFBB0, 0xFBB1} /* YEH BARREE WITH HAMZA ABOVE */
+ };
+
+ public static final int ar_nothing = 0x0;
+ public static final int ar_novowel = 0x1;
+ public static final int ar_composedtashkeel = 0x4;
+ public static final int ar_lig = 0x8;
+ /**
+ * Digit shaping option: Replace European digits (U+0030...U+0039) by Arabic-Indic digits.
+ */
+ public static final int DIGITS_EN2AN = 0x20;
+
+ /**
+ * Digit shaping option: Replace Arabic-Indic digits by European digits (U+0030...U+0039).
+ */
+ public static final int DIGITS_AN2EN = 0x40;
+
+ /**
+ * Digit shaping option:
+ * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
+ * if the most recent strongly directional character
+ * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
+ * The initial state at the start of the text is assumed to be not an Arabic,
+ * letter, so European digits at the start of the text will not change.
+ * Compare to DIGITS_ALEN2AN_INIT_AL.
+ */
+ public static final int DIGITS_EN2AN_INIT_LR = 0x60;
+
+ /**
+ * Digit shaping option:
+ * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
+ * if the most recent strongly directional character
+ * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
+ * The initial state at the start of the text is assumed to be an Arabic,
+ * letter, so European digits at the start of the text will change.
+ * Compare to DIGITS_ALEN2AN_INT_LR.
+ */
+ public static final int DIGITS_EN2AN_INIT_AL = 0x80;
+
+ /** Not a valid option value. */
+ private static final int DIGITS_RESERVED = 0xa0;
+
+ /**
+ * Bit mask for digit shaping options.
+ */
+ public static final int DIGITS_MASK = 0xe0;
+
+ /**
+ * Digit type option: Use Arabic-Indic digits (U+0660...U+0669).
+ */
+ public static final int DIGIT_TYPE_AN = 0;
+
+ /**
+ * Digit type option: Use Eastern (Extended) Arabic-Indic digits (U+06f0...U+06f9).
+ */
+ public static final int DIGIT_TYPE_AN_EXTENDED = 0x100;
+
+ /**
+ * Bit mask for digit type options.
+ */
+ public static final int DIGIT_TYPE_MASK = 0x0100; // 0x3f00?
+
+ static class charstruct {
+ char basechar;
+ char mark1; /* has to be initialized to zero */
+ char vowel;
+ int lignum; /* is a ligature with lignum aditional characters */
+ int numshapes = 1;
+ };
+
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/AsianFontMapper.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/AsianFontMapper.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/AsianFontMapper.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/AsianFontMapper.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2004 by Takenori.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.awt.Font;
+
+import pdftk.com.lowagie.text.pdf.BaseFont;
+import pdftk.com.lowagie.text.pdf.DefaultFontMapper;
+
+public class AsianFontMapper extends DefaultFontMapper {
+
+ public static String ChineseSimplifiedFont = "STSong-Light";
+ public static String ChineseSimplifiedEncoding_H = "UniGB-UCS2-H";
+ public static String ChineseSimplifiedEncoding_V = "UniGB-UCS2-V";
+
+ public static String ChineseTraditionalFont_MHei = "MHei-Medium";
+ public static String ChineseTraditionalFont_MSung = "MSung-Light";
+ public static String ChineseTraditionalEncoding_H = "UniCNS-UCS2-H";
+ public static String ChineseTraditionalEncoding_V = "UniCNS-UCS2-V";
+
+ public static String JapaneseFont_Go = "HeiseiKakuGo-W5";
+ public static String JapaneseFont_Min = "HeiseiMin-W3";
+ public static String JapaneseEncoding_H = "UniJIS-UCS2-H";
+ public static String JapaneseEncoding_V = "UniJIS-UCS2-V";
+ public static String JapaneseEncoding_HW_H = "UniJIS-UCS2-HW-H";
+ public static String JapaneseEncoding_HW_V = "UniJIS-UCS2-HW-V";
+
+ public static String KoreanFont_GoThic = "HYGoThic-Medium";
+ public static String KoreanFont_SMyeongJo = "HYSMyeongJo-Medium";
+ public static String KoreanEncoding_H = "UniKS-UCS2-H";
+ public static String KoreanEncoding_V = "UniKS-UCS2-V";
+
+ private String defaultFont;
+ private String encoding;
+
+ public AsianFontMapper(String font, String encoding) {
+ super();
+
+ this.defaultFont = font;
+ this.encoding = encoding;
+ }
+
+ public BaseFont awtToPdf(Font font) {
+ try {
+ BaseFontParameters p = getBaseFontParameters(font.getFontName());
+ if (p != null){
+ return BaseFont.createFont(p.fontName, p.encoding, p.embedded, p.cached, p.ttfAfm, p.pfb);
+ }else{
+ return BaseFont.createFont(defaultFont, encoding, true);
+ }
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BadPdfFormatException.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BadPdfFormatException.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BadPdfFormatException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BadPdfFormatException.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,76 @@
+/*
+ * $Id: BadPdfFormatException.java,v 1.22 2002/06/18 13:59:39 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * Signals that a bad PDF format has been used to construct a PdfObject
.
+ *
+ * @see PdfException
+ * @see PdfBoolean
+ * @see PdfNumber
+ * @see PdfString
+ * @see PdfName
+ * @see PdfDictionary
+ * @see PdfFont
+ */
+
+public class BadPdfFormatException extends PdfException {
+
+ // constructors
+
+/**
+ * Constructs a BadPdfFormatException
whithout a message.
+ */
+
+ BadPdfFormatException() {
+ super();
+ }
+
+/**
+ * Constructs a BadPdfFormatException
with a message.
+ *
+ * @param message a message describing the exception
+ */
+
+ BadPdfFormatException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/Barcode.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/Barcode.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/Barcode.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/Barcode.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,444 @@
+/*
+ * Copyright 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.Rectangle;
+// import pdftk.com.lowagie.text.Image; ssteward: dropped in 1.44
+import java.awt.Color;
+/** Base class containing properties and methods commom to all
+ * barcode types.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public abstract class Barcode {
+ /** A type of barcode */
+ public static final int EAN13 = 1;
+ /** A type of barcode */
+ public static final int EAN8 = 2;
+ /** A type of barcode */
+ public static final int UPCA = 3;
+ /** A type of barcode */
+ public static final int UPCE = 4;
+ /** A type of barcode */
+ public static final int SUPP2 = 5;
+ /** A type of barcode */
+ public static final int SUPP5 = 6;
+ /** A type of barcode */
+ public static final int POSTNET = 7;
+ /** A type of barcode */
+ public static final int PLANET = 8;
+ /** A type of barcode */
+ public static final int CODE128 = 9;
+ /** A type of barcode */
+ public static final int CODE128_UCC = 10;
+ /** A type of barcode */
+ public static final int CODE128_RAW = 11;
+ /** A type of barcode */
+ public static final int CODABAR = 12;
+
+ /** The minimum bar width.
+ */
+ protected float x;
+
+ /** The bar multiplier for wide bars or the distance between
+ * bars for Postnet and Planet.
+ */
+ protected float n;
+
+ /** The text font. null
if no text.
+ */
+ protected BaseFont font;
+
+ /** The size of the text or the height of the shorter bar
+ * in Postnet.
+ */
+ protected float size;
+
+ /** If positive, the text distance under the bars. If zero or negative,
+ * the text distance above the bars.
+ */
+ protected float baseline;
+
+ /** The height of the bars.
+ */
+ protected float barHeight;
+
+ /** The text alignment. Can be Element.ALIGN_LEFT
,
+ * Element.ALIGN_CENTER
or Element.ALIGN_RIGHT
.
+ */
+ protected int textAlignment;
+
+ /** The optional checksum generation.
+ */
+ protected boolean generateChecksum;
+
+ /** Shows the generated checksum in the the text.
+ */
+ protected boolean checksumText;
+
+ /** Show the start and stop character '*' in the text for
+ * the barcode 39 or 'ABCD' for codabar.
+ */
+ protected boolean startStopText;
+
+ /** Generates extended barcode 39.
+ */
+ protected boolean extended;
+
+ /** The code to generate.
+ */
+ protected String code = "";
+
+ /** Show the guard bars for barcode EAN.
+ */
+ protected boolean guardBars;
+
+ /** The code type.
+ */
+ protected int codeType;
+
+ /** The ink spreading. */
+ protected float inkSpreading = 0;
+
+ /** Gets the minimum bar width.
+ * @return the minimum bar width
+ */
+ public float getX() {
+ return x;
+ }
+
+ /** Sets the minimum bar width.
+ * @param x the minimum bar width
+ */
+ public void setX(float x) {
+ this.x = x;
+ }
+
+ /** Gets the bar multiplier for wide bars.
+ * @return the bar multiplier for wide bars
+ */
+ public float getN() {
+ return n;
+ }
+
+ /** Sets the bar multiplier for wide bars.
+ * @param n the bar multiplier for wide bars
+ */
+ public void setN(float n) {
+ this.n = n;
+ }
+
+ /** Gets the text font. null
if no text.
+ * @return the text font. null
if no text
+ */
+ public BaseFont getFont() {
+ return font;
+ }
+
+ /** Sets the text font.
+ * @param font the text font. Set to null
to suppress any text
+ */
+ public void setFont(BaseFont font) {
+ this.font = font;
+ }
+
+ /** Gets the size of the text.
+ * @return the size of the text
+ */
+ public float getSize() {
+ return size;
+ }
+
+ /** Sets the size of the text.
+ * @param size the size of the text
+ */
+ public void setSize(float size) {
+ this.size = size;
+ }
+
+ /** Gets the text baseline.
+ * If positive, the text distance under the bars. If zero or negative,
+ * the text distance above the bars.
+ * @return the baseline.
+ */
+ public float getBaseline() {
+ return baseline;
+ }
+
+ /** Sets the text baseline.
+ * If positive, the text distance under the bars. If zero or negative,
+ * the text distance above the bars.
+ * @param baseline the baseline.
+ */
+ public void setBaseline(float baseline) {
+ this.baseline = baseline;
+ }
+
+ /** Gets the height of the bars.
+ * @return the height of the bars
+ */
+ public float getBarHeight() {
+ return barHeight;
+ }
+
+ /** Sets the height of the bars.
+ * @param barHeight the height of the bars
+ */
+ public void setBarHeight(float barHeight) {
+ this.barHeight = barHeight;
+ }
+
+ /** Gets the text alignment. Can be Element.ALIGN_LEFT
,
+ * Element.ALIGN_CENTER
or Element.ALIGN_RIGHT
.
+ * @return the text alignment
+ */
+ public int getTextAlignment() {
+ return textAlignment;
+ }
+
+ /** Sets the text alignment. Can be Element.ALIGN_LEFT
,
+ * Element.ALIGN_CENTER
or Element.ALIGN_RIGHT
.
+ * @param textAlignment the text alignment
+ */
+ public void setTextAlignment(int textAlignment) {
+ this.textAlignment = textAlignment;
+ }
+
+ /** Gets the optional checksum generation.
+ * @return the optional checksum generation
+ */
+ public boolean isGenerateChecksum() {
+ return generateChecksum;
+ }
+
+ /** Setter for property generateChecksum.
+ * @param generateChecksum New value of property generateChecksum.
+ */
+ public void setGenerateChecksum(boolean generateChecksum) {
+ this.generateChecksum = generateChecksum;
+ }
+
+ /** Gets the property to show the generated checksum in the the text.
+ * @return value of property checksumText
+ */
+ public boolean isChecksumText() {
+ return checksumText;
+ }
+
+ /** Sets the property to show the generated checksum in the the text.
+ * @param checksumText new value of property checksumText
+ */
+ public void setChecksumText(boolean checksumText) {
+ this.checksumText = checksumText;
+ }
+
+ /** Sets the property to show the start and stop character '*' in the text for
+ * the barcode 39.
+ * @return value of property startStopText
+ */
+ public boolean isStartStopText() {
+ return startStopText;
+ }
+
+ /** Gets the property to show the start and stop character '*' in the text for
+ * the barcode 39.
+ * @param startStopText new value of property startStopText
+ */
+ public void setStartStopText(boolean startStopText) {
+ this.startStopText = startStopText;
+ }
+
+ /** Gets the property to generate extended barcode 39.
+ * @return value of property extended.
+ */
+ public boolean isExtended() {
+ return extended;
+ }
+
+ /** Sets the property to generate extended barcode 39.
+ * @param extended new value of property extended
+ */
+ public void setExtended(boolean extended) {
+ this.extended = extended;
+ }
+
+ /** Gets the code to generate.
+ * @return the code to generate
+ */
+ public String getCode() {
+ return code;
+ }
+
+ /** Sets the code to generate.
+ * @param code the code to generate
+ */
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ /** Gets the property to show the guard bars for barcode EAN.
+ * @return value of property guardBars
+ */
+ public boolean isGuardBars() {
+ return guardBars;
+ }
+
+ /** Sets the property to show the guard bars for barcode EAN.
+ * @param guardBars new value of property guardBars
+ */
+ public void setGuardBars(boolean guardBars) {
+ this.guardBars = guardBars;
+ }
+
+ /** Gets the code type.
+ * @return the code type
+ */
+ public int getCodeType() {
+ return codeType;
+ }
+
+ /** Sets the code type.
+ * @param codeType the code type
+ */
+ public void setCodeType(int codeType) {
+ this.codeType = codeType;
+ }
+
+ /** Gets the maximum area that the barcode and the text, if
+ * any, will occupy. The lower left corner is always (0, 0).
+ * @return the size the barcode occupies.
+ */
+ public abstract Rectangle getBarcodeSize();
+
+ /** Places the barcode in a PdfContentByte
. The
+ * barcode is always placed at coodinates (0, 0). Use the
+ * translation matrix to move it elsewhere.
+ * The bars and text are written in the following colors:
+ *
+ *
+ * barColor
+ * textColor
+ * Result
+ *
+ *
+ * null
+ * null
+ * bars and text painted with current fill color
+ *
+ *
+ * barColor
+ * null
+ * bars and text painted with barColor
+ *
+ *
+ * null
+ * textColor
+ * bars painted with current color text painted with textColor
+ *
+ *
+ * barColor
+ * textColor
+ * bars painted with barColor
text painted with textColor
+ *
+ *
+ * @param cb the PdfContentByte
where the barcode will be placed
+ * @param barColor the color of the bars. It can be null
+ * @param textColor the color of the text. It can be null
+ * @return the dimensions the barcode occupies
+ */
+ public abstract Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor);
+
+ /** Creates a template with the barcode.
+ * @param cb the PdfContentByte
to create the template. It
+ * serves no other use
+ * @param barColor the color of the bars. It can be null
+ * @param textColor the color of the text. It can be null
+ * @return the template
+ * @see #placeBarcode(PdfContentByte cb, Color barColor, Color textColor)
+ */
+ public PdfTemplate createTemplateWithBarcode(PdfContentByte cb, Color barColor, Color textColor) {
+ PdfTemplate tp = cb.createTemplate(0, 0);
+ Rectangle rect = placeBarcode(tp, barColor, textColor);
+ tp.setBoundingBox(rect);
+ return tp;
+ }
+
+ /** Creates an Image
with the barcode.
+ * @param cb the PdfContentByte
to create the Image
. It
+ * serves no other use
+ * @param barColor the color of the bars. It can be null
+ * @param textColor the color of the text. It can be null
+ * @return the Image
+ * @see #placeBarcode(PdfContentByte cb, Color barColor, Color textColor)
+ */
+ /* ssteward: dropped in 1.44
+ public Image createImageWithBarcode(PdfContentByte cb, Color barColor, Color textColor) {
+ try {
+ return Image.getInstance(createTemplateWithBarcode(cb, barColor, textColor));
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+ */
+
+ /** Creates a java.awt.Image
. This image only
+ * contains the bars without any text.
+ * @param foreground the color of the bars
+ * @param background the color of the background
+ * @return the image
+ */
+ public abstract java.awt.Image createAwtImage(Color foreground, Color background);
+
+ /** Gets the amount of ink spreading.
+ * @return the ink spreading
+ *
+ */
+ public float getInkSpreading() {
+ return this.inkSpreading;
+ }
+
+ /** Sets the amount of ink spreading. This value will be subtracted
+ * to the width of each bar. The actual value will depend on the ink
+ * and the printing medium.
+ * @param inkSpreading the ink spreading
+ *
+ */
+ public void setInkSpreading(float inkSpreading) {
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/Barcode128.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/Barcode128.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/Barcode128.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/Barcode128.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,813 @@
+/*
+ * Copyright 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+import pdftk.com.lowagie.text.Rectangle;
+import pdftk.com.lowagie.text.Element;
+import pdftk.com.lowagie.text.ExceptionConverter;
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.Canvas;
+import java.awt.image.MemoryImageSource;
+
+/**
+ * Implements the code 128 and UCC/EAN-128. Other symbologies are allowed in raw mode.
+ * The code types allowed are:
+ *
+ * CODE128 - plain barcode 128.
+ * CODE128_UCC - support for UCC/EAN-128 with a full list of AI.
+ * CODE128_RAW - raw mode. The code attribute has the actual codes from 0
+ * to 105 followed by '\uffff' and the human readable text.
+ *
+ * The default parameters are:
+ *
+ * x = 0.8f;
+ * font = BaseFont.createFont("Helvetica", "winansi", false);
+ * size = 8;
+ * baseline = size;
+ * barHeight = size * 3;
+ * textAlignment = Element.ALIGN_CENTER;
+ * codeType = CODE128;
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class Barcode128 extends Barcode{
+
+ /** The bars to generate the code.
+ */
+ static byte BARS[][] =
+ {
+ {2, 1, 2, 2, 2, 2},
+ {2, 2, 2, 1, 2, 2},
+ {2, 2, 2, 2, 2, 1},
+ {1, 2, 1, 2, 2, 3},
+ {1, 2, 1, 3, 2, 2},
+ {1, 3, 1, 2, 2, 2},
+ {1, 2, 2, 2, 1, 3},
+ {1, 2, 2, 3, 1, 2},
+ {1, 3, 2, 2, 1, 2},
+ {2, 2, 1, 2, 1, 3},
+ {2, 2, 1, 3, 1, 2},
+ {2, 3, 1, 2, 1, 2},
+ {1, 1, 2, 2, 3, 2},
+ {1, 2, 2, 1, 3, 2},
+ {1, 2, 2, 2, 3, 1},
+ {1, 1, 3, 2, 2, 2},
+ {1, 2, 3, 1, 2, 2},
+ {1, 2, 3, 2, 2, 1},
+ {2, 2, 3, 2, 1, 1},
+ {2, 2, 1, 1, 3, 2},
+ {2, 2, 1, 2, 3, 1},
+ {2, 1, 3, 2, 1, 2},
+ {2, 2, 3, 1, 1, 2},
+ {3, 1, 2, 1, 3, 1},
+ {3, 1, 1, 2, 2, 2},
+ {3, 2, 1, 1, 2, 2},
+ {3, 2, 1, 2, 2, 1},
+ {3, 1, 2, 2, 1, 2},
+ {3, 2, 2, 1, 1, 2},
+ {3, 2, 2, 2, 1, 1},
+ {2, 1, 2, 1, 2, 3},
+ {2, 1, 2, 3, 2, 1},
+ {2, 3, 2, 1, 2, 1},
+ {1, 1, 1, 3, 2, 3},
+ {1, 3, 1, 1, 2, 3},
+ {1, 3, 1, 3, 2, 1},
+ {1, 1, 2, 3, 1, 3},
+ {1, 3, 2, 1, 1, 3},
+ {1, 3, 2, 3, 1, 1},
+ {2, 1, 1, 3, 1, 3},
+ {2, 3, 1, 1, 1, 3},
+ {2, 3, 1, 3, 1, 1},
+ {1, 1, 2, 1, 3, 3},
+ {1, 1, 2, 3, 3, 1},
+ {1, 3, 2, 1, 3, 1},
+ {1, 1, 3, 1, 2, 3},
+ {1, 1, 3, 3, 2, 1},
+ {1, 3, 3, 1, 2, 1},
+ {3, 1, 3, 1, 2, 1},
+ {2, 1, 1, 3, 3, 1},
+ {2, 3, 1, 1, 3, 1},
+ {2, 1, 3, 1, 1, 3},
+ {2, 1, 3, 3, 1, 1},
+ {2, 1, 3, 1, 3, 1},
+ {3, 1, 1, 1, 2, 3},
+ {3, 1, 1, 3, 2, 1},
+ {3, 3, 1, 1, 2, 1},
+ {3, 1, 2, 1, 1, 3},
+ {3, 1, 2, 3, 1, 1},
+ {3, 3, 2, 1, 1, 1},
+ {3, 1, 4, 1, 1, 1},
+ {2, 2, 1, 4, 1, 1},
+ {4, 3, 1, 1, 1, 1},
+ {1, 1, 1, 2, 2, 4},
+ {1, 1, 1, 4, 2, 2},
+ {1, 2, 1, 1, 2, 4},
+ {1, 2, 1, 4, 2, 1},
+ {1, 4, 1, 1, 2, 2},
+ {1, 4, 1, 2, 2, 1},
+ {1, 1, 2, 2, 1, 4},
+ {1, 1, 2, 4, 1, 2},
+ {1, 2, 2, 1, 1, 4},
+ {1, 2, 2, 4, 1, 1},
+ {1, 4, 2, 1, 1, 2},
+ {1, 4, 2, 2, 1, 1},
+ {2, 4, 1, 2, 1, 1},
+ {2, 2, 1, 1, 1, 4},
+ {4, 1, 3, 1, 1, 1},
+ {2, 4, 1, 1, 1, 2},
+ {1, 3, 4, 1, 1, 1},
+ {1, 1, 1, 2, 4, 2},
+ {1, 2, 1, 1, 4, 2},
+ {1, 2, 1, 2, 4, 1},
+ {1, 1, 4, 2, 1, 2},
+ {1, 2, 4, 1, 1, 2},
+ {1, 2, 4, 2, 1, 1},
+ {4, 1, 1, 2, 1, 2},
+ {4, 2, 1, 1, 1, 2},
+ {4, 2, 1, 2, 1, 1},
+ {2, 1, 2, 1, 4, 1},
+ {2, 1, 4, 1, 2, 1},
+ {4, 1, 2, 1, 2, 1},
+ {1, 1, 1, 1, 4, 3},
+ {1, 1, 1, 3, 4, 1},
+ {1, 3, 1, 1, 4, 1},
+ {1, 1, 4, 1, 1, 3},
+ {1, 1, 4, 3, 1, 1},
+ {4, 1, 1, 1, 1, 3},
+ {4, 1, 1, 3, 1, 1},
+ {1, 1, 3, 1, 4, 1},
+ {1, 1, 4, 1, 3, 1},
+ {3, 1, 1, 1, 4, 1},
+ {4, 1, 1, 1, 3, 1},
+ {2, 1, 1, 4, 1, 2},
+ {2, 1, 1, 2, 1, 4},
+ {2, 1, 1, 2, 3, 2}
+ };
+
+ /** The stop bars.
+ */
+ static byte BARS_STOP[] = {2, 3, 3, 1, 1, 1, 2};
+ /** The charset code change.
+ */
+ public static final char CODE_AB_TO_C = 99;
+ /** The charset code change.
+ */
+ public static final char CODE_AC_TO_B = 100;
+ /** The charset code change.
+ */
+ public static final char CODE_BC_TO_A = 101;
+ /** The code for UCC/EAN-128.
+ */
+ public static final char FNC1_INDEX = 102;
+ /** The start code.
+ */
+ public static final char START_A = 103;
+ /** The start code.
+ */
+ public static final char START_B = 104;
+ /** The start code.
+ */
+ public static final char START_C = 105;
+
+ public static final char FNC1 = '\u00ca';
+ public static final char DEL = '\u00c3';
+ public static final char FNC3 = '\u00c4';
+ public static final char FNC2 = '\u00c5';
+ public static final char SHIFT = '\u00c6';
+ public static final char CODE_C = '\u00c7';
+ public static final char CODE_A = '\u00c8';
+ public static final char FNC4 = '\u00c8';
+ public static final char STARTA = '\u00cb';
+ public static final char STARTB = '\u00cc';
+ public static final char STARTC = '\u00cd';
+
+ private static final IntHashtable ais = new IntHashtable();
+ /** Creates new Barcode128 */
+ public Barcode128() {
+ try {
+ x = 0.8f;
+ font = BaseFont.createFont("Helvetica", "winansi", false);
+ size = 8;
+ baseline = size;
+ barHeight = size * 3;
+ textAlignment = Element.ALIGN_CENTER;
+ codeType = CODE128;
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ * Removes the FNC1 codes in the text.
+ * @param code the text to clean
+ * @return the cleaned text
+ */
+ public static String removeFNC1(String code) {
+ int len = code.length();
+ StringBuffer buf = new StringBuffer(len);
+ for (int k = 0; k < len; ++k) {
+ char c = code.charAt(k);
+ if (c >= 32 && c <= 126)
+ buf.append(c);
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Gets the human readable text of a sequence of AI.
+ * @param code the text
+ * @return the human readable text
+ */
+ public static String getHumanReadableUCCEAN(String code) {
+ StringBuffer buf = new StringBuffer();
+ String fnc1 = String.valueOf(FNC1);
+ try {
+ while (true) {
+ if (code.startsWith(fnc1)) {
+ code = code.substring(1);
+ continue;
+ }
+ int n = 0;
+ int idlen = 0;
+ for (int k = 2; k < 5; ++k) {
+ if (code.length() < k)
+ break;
+ if ((n = ais.get(Integer.parseInt(code.substring(0, k)))) != 0) {
+ idlen = k;
+ break;
+ }
+ }
+ if (idlen == 0)
+ break;
+ buf.append('(').append(code.substring(0, idlen)).append(')');
+ code = code.substring(idlen);
+ if (n > 0) {
+ n -= idlen;
+ if (code.length() <= n)
+ break;
+ buf.append(removeFNC1(code.substring(0, n)));
+ code = code.substring(n);
+ }
+ else {
+ int idx = code.indexOf(FNC1);
+ if (idx < 0)
+ break;
+ buf.append(code.substring(0,idx));
+ code = code.substring(idx + 1);
+ }
+ }
+ }
+ catch (Exception e) {
+ //empty
+ }
+ buf.append(removeFNC1(code));
+ return buf.toString();
+ }
+
+ /** Returns true
if the next numDigits
+ * starting from index textIndex
are numeric skipping any FNC1.
+ * @param text the text to check
+ * @param textIndex where to check from
+ * @param numDigits the number of digits to check
+ * @return the check result
+ */
+ static boolean isNextDigits(String text, int textIndex, int numDigits) {
+ int len = text.length();
+ while (textIndex < len && numDigits > 0) {
+ if (text.charAt(textIndex) == FNC1) {
+ ++textIndex;
+ continue;
+ }
+ int n = Math.min(2, numDigits);
+ if (textIndex + n > len)
+ return false;
+ while (n-- > 0) {
+ char c = text.charAt(textIndex++);
+ if (c < '0' || c > '9')
+ return false;
+ --numDigits;
+ }
+ }
+ return numDigits == 0;
+ }
+
+ /** Packs the digits for charset C also considering FNC1. It assumes that all the parameters
+ * are valid.
+ * @param text the text to pack
+ * @param textIndex where to pack from
+ * @param numDigits the number of digits to pack. It is always an even number
+ * @return the packed digits, two digits per character
+ */
+ static String getPackedRawDigits(String text, int textIndex, int numDigits) {
+ String out = "";
+ int start = textIndex;
+ while (numDigits > 0) {
+ if (text.charAt(textIndex) == FNC1) {
+ out += FNC1_INDEX;
+ ++textIndex;
+ continue;
+ }
+ numDigits -= 2;
+ int c1 = text.charAt(textIndex++) - '0';
+ int c2 = text.charAt(textIndex++) - '0';
+ out += (char)(c1 * 10 + c2);
+ }
+ return (char)(textIndex - start) + out;
+ }
+
+ /** Converts the human readable text to the characters needed to
+ * create a barcode. Some optimization is done to get the shortest code.
+ * @param text the text to convert
+ * @param ucc true
if it is an UCC/EAN-128. In this case
+ * the character FNC1 is added
+ * @return the code ready to be fed to getBarsCode128Raw()
+ */
+ public static String getRawText(String text, boolean ucc) {
+ String out = "";
+ int tLen = text.length();
+ if (tLen == 0) {
+ out += START_B;
+ if (ucc)
+ out += FNC1_INDEX;
+ return out;
+ }
+ int c = 0;
+ for (int k = 0; k < tLen; ++k) {
+ c = text.charAt(k);
+ if (c > 127 && c != FNC1)
+ throw new RuntimeException("There are illegal characters for barcode 128 in '" + text + "'.");
+ }
+ c = text.charAt(0);
+ char currentCode = START_B;
+ int index = 0;
+ if (isNextDigits(text, index, 2)) {
+ currentCode = START_C;
+ out += currentCode;
+ if (ucc)
+ out += FNC1_INDEX;
+ String out2 = getPackedRawDigits(text, index, 2);
+ index += (int)out2.charAt(0);
+ out += out2.substring(1);
+ }
+ else if (c < ' ') {
+ currentCode = START_A;
+ out += currentCode;
+ if (ucc)
+ out += FNC1_INDEX;
+ out += (char)(c + 64);
+ ++index;
+ }
+ else {
+ out += currentCode;
+ if (ucc)
+ out += FNC1_INDEX;
+ if (c == FNC1)
+ out += FNC1_INDEX;
+ else
+ out += (char)(c - ' ');
+ ++index;
+ }
+ while (index < tLen) {
+ switch (currentCode) {
+ case START_A:
+ {
+ if (isNextDigits(text, index, 4)) {
+ currentCode = START_C;
+ out += CODE_AB_TO_C;
+ String out2 = getPackedRawDigits(text, index, 4);
+ index += (int)out2.charAt(0);
+ out += out2.substring(1);
+ }
+ else {
+ c = text.charAt(index++);
+ if (c == FNC1)
+ out += FNC1_INDEX;
+ else if (c > '_') {
+ currentCode = START_B;
+ out += CODE_AC_TO_B;
+ out += (char)(c - ' ');
+ }
+ else if (c < ' ')
+ out += (char)(c + 64);
+ else
+ out += (char)(c - ' ');
+ }
+ }
+ break;
+ case START_B:
+ {
+ if (isNextDigits(text, index, 4)) {
+ currentCode = START_C;
+ out += CODE_AB_TO_C;
+ String out2 = getPackedRawDigits(text, index, 4);
+ index += (int)out2.charAt(0);
+ out += out2.substring(1);
+ }
+ else {
+ c = text.charAt(index++);
+ if (c == FNC1)
+ out += FNC1_INDEX;
+ else if (c < ' ') {
+ currentCode = START_A;
+ out += CODE_BC_TO_A;
+ out += (char)(c + 64);
+ }
+ else {
+ out += (char)(c - ' ');
+ }
+ }
+ }
+ break;
+ case START_C:
+ {
+ if (isNextDigits(text, index, 2)) {
+ String out2 = getPackedRawDigits(text, index, 2);
+ index += (int)out2.charAt(0);
+ out += out2.substring(1);
+ }
+ else {
+ c = text.charAt(index++);
+ if (c == FNC1)
+ out += FNC1_INDEX;
+ else if (c < ' ') {
+ currentCode = START_A;
+ out += CODE_BC_TO_A;
+ out += (char)(c + 64);
+ }
+ else {
+ currentCode = START_B;
+ out += CODE_AC_TO_B;
+ out += (char)(c - ' ');
+ }
+ }
+ }
+ break;
+ }
+ }
+ return out;
+ }
+
+ /** Generates the bars. The input has the actual barcodes, not
+ * the human readable text.
+ * @param text the barcode
+ * @return the bars
+ */
+ public static byte[] getBarsCode128Raw(String text) {
+ int idx = text.indexOf('\uffff');
+ if (idx >= 0)
+ text = text.substring(0, idx);
+ int chk = text.charAt(0);
+ for (int k = 1; k < text.length(); ++k)
+ chk += k * text.charAt(k);
+ chk = chk % 103;
+ text += (char)chk;
+ byte bars[] = new byte[(text.length() + 1) * 6 + 7];
+ int k;
+ for (k = 0; k < text.length(); ++k)
+ System.arraycopy(BARS[text.charAt(k)], 0, bars, k * 6, 6);
+ System.arraycopy(BARS_STOP, 0, bars, k * 6, 7);
+ return bars;
+ }
+
+ /** Gets the maximum area that the barcode and the text, if
+ * any, will occupy. The lower left corner is always (0, 0).
+ * @return the size the barcode occupies.
+ */
+ public Rectangle getBarcodeSize() {
+ float fontX = 0;
+ float fontY = 0;
+ String fullCode;
+ if (font != null) {
+ if (baseline > 0)
+ fontY = baseline - font.getFontDescriptor(BaseFont.DESCENT, size);
+ else
+ fontY = -baseline + size;
+ if (codeType == CODE128_RAW) {
+ int idx = code.indexOf('\uffff');
+ if (idx < 0)
+ fullCode = "";
+ else
+ fullCode = code.substring(idx + 1);
+ }
+ else if (codeType == CODE128_UCC)
+ fullCode = getHumanReadableUCCEAN(code);
+ else
+ fullCode = removeFNC1(code);
+ fontX = font.getWidthPoint(fullCode, size);
+ }
+ if (codeType == CODE128_RAW) {
+ int idx = code.indexOf('\uffff');
+ if (idx >= 0)
+ fullCode = code.substring(0, idx);
+ else
+ fullCode = code;
+ }
+ else {
+ fullCode = getRawText(code, codeType == CODE128_UCC);
+ }
+ int len = fullCode.length();
+ float fullWidth = (len + 2) * 11 * x + 2 * x;
+ fullWidth = Math.max(fullWidth, fontX);
+ float fullHeight = barHeight + fontY;
+ return new Rectangle(fullWidth, fullHeight);
+ }
+
+ /** Places the barcode in a PdfContentByte
. The
+ * barcode is always placed at coodinates (0, 0). Use the
+ * translation matrix to move it elsewhere.
+ * The bars and text are written in the following colors:
+ *
+ *
+ * barColor
+ * textColor
+ * Result
+ *
+ *
+ * null
+ * null
+ * bars and text painted with current fill color
+ *
+ *
+ * barColor
+ * null
+ * bars and text painted with barColor
+ *
+ *
+ * null
+ * textColor
+ * bars painted with current color text painted with textColor
+ *
+ *
+ * barColor
+ * textColor
+ * bars painted with barColor
text painted with textColor
+ *
+ *
+ * @param cb the PdfContentByte
where the barcode will be placed
+ * @param barColor the color of the bars. It can be null
+ * @param textColor the color of the text. It can be null
+ * @return the dimensions the barcode occupies
+ */
+ public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
+ String fullCode;
+ if (codeType == CODE128_RAW) {
+ int idx = code.indexOf('\uffff');
+ if (idx < 0)
+ fullCode = "";
+ else
+ fullCode = code.substring(idx + 1);
+ }
+ else if (codeType == CODE128_UCC)
+ fullCode = getHumanReadableUCCEAN(code);
+ else
+ fullCode = removeFNC1(code);
+ float fontX = 0;
+ if (font != null) {
+ fontX = font.getWidthPoint(fullCode, size);
+ }
+ String bCode;
+ if (codeType == CODE128_RAW) {
+ int idx = code.indexOf('\uffff');
+ if (idx >= 0)
+ bCode = code.substring(0, idx);
+ else
+ bCode = code;
+ }
+ else {
+ bCode = getRawText(code, codeType == CODE128_UCC);
+ }
+ int len = bCode.length();
+ float fullWidth = (len + 2) * 11 * x + 2 * x;
+ float barStartX = 0;
+ float textStartX = 0;
+ switch (textAlignment) {
+ case Element.ALIGN_LEFT:
+ break;
+ case Element.ALIGN_RIGHT:
+ if (fontX > fullWidth)
+ barStartX = fontX - fullWidth;
+ else
+ textStartX = fullWidth - fontX;
+ break;
+ default:
+ if (fontX > fullWidth)
+ barStartX = (fontX - fullWidth) / 2;
+ else
+ textStartX = (fullWidth - fontX) / 2;
+ break;
+ }
+ float barStartY = 0;
+ float textStartY = 0;
+ if (font != null) {
+ if (baseline <= 0)
+ textStartY = barHeight - baseline;
+ else {
+ textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size);
+ barStartY = textStartY + baseline;
+ }
+ }
+ byte bars[] = getBarsCode128Raw(bCode);
+ boolean print = true;
+ if (barColor != null)
+ cb.setColorFill(barColor);
+ for (int k = 0; k < bars.length; ++k) {
+ float w = bars[k] * x;
+ if (print)
+ cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight);
+ print = !print;
+ barStartX += w;
+ }
+ cb.fill();
+ if (font != null) {
+ if (textColor != null)
+ cb.setColorFill(textColor);
+ cb.beginText();
+ cb.setFontAndSize(font, size);
+ cb.setTextMatrix(textStartX, textStartY);
+ cb.showText(fullCode);
+ cb.endText();
+ }
+ return getBarcodeSize();
+ }
+
+ /** Creates a java.awt.Image
. This image only
+ * contains the bars without any text.
+ * @param foreground the color of the bars
+ * @param background the color of the background
+ * @return the image
+ */
+ public java.awt.Image createAwtImage(Color foreground, Color background) {
+ int f = foreground.getRGB();
+ int g = background.getRGB();
+ Canvas canvas = new Canvas();
+ String bCode;
+ if (codeType == CODE128_RAW) {
+ int idx = code.indexOf('\uffff');
+ if (idx >= 0)
+ bCode = code.substring(0, idx);
+ else
+ bCode = code;
+ }
+ else {
+ bCode = getRawText(code, codeType == CODE128_UCC);
+ }
+ int len = bCode.length();
+ int fullWidth = (len + 2) * 11 + 2;
+ byte bars[] = getBarsCode128Raw(bCode);
+
+ boolean print = true;
+ int ptr = 0;
+ int height = (int)barHeight;
+ int pix[] = new int[fullWidth * height];
+ for (int k = 0; k < bars.length; ++k) {
+ int w = bars[k];
+ int c = g;
+ if (print)
+ c = f;
+ print = !print;
+ for (int j = 0; j < w; ++j)
+ pix[ptr++] = c;
+ }
+ for (int k = fullWidth; k < pix.length; k += fullWidth) {
+ System.arraycopy(pix, 0, pix, k, fullWidth);
+ }
+ Image img = canvas.createImage(new MemoryImageSource(fullWidth, height, pix, 0, fullWidth));
+
+ return img;
+ }
+
+ /**
+ * Sets the code to generate. If it's an UCC code and starts with '(' it will
+ * be split by the AI. This code in UCC mode is valid:
+ *
+ * (01)00000090311314(10)ABC123(15)060916
+ * @param code the code to generate
+ */
+ public void setCode(String code) {
+ if (getCodeType() == Barcode128.CODE128_UCC && code.startsWith("(")) {
+ int idx = 0;
+ String ret = "";
+ while (idx >= 0) {
+ int end = code.indexOf(')', idx);
+ if (end < 0)
+ throw new IllegalArgumentException("Badly formed UCC string: " + code);
+ String sai = code.substring(idx + 1, end);
+ if (sai.length() < 2)
+ throw new IllegalArgumentException("AI too short: (" + sai + ")");
+ int ai = Integer.parseInt(sai);
+ int len = ais.get(ai);
+ if (len == 0)
+ throw new IllegalArgumentException("AI not found: (" + sai + ")");
+ sai = String.valueOf(ai);
+ if (sai.length() == 1)
+ sai = "0" + sai;
+ idx = code.indexOf('(', end);
+ int next = (idx < 0 ? code.length() : idx);
+ ret += sai + code.substring(end + 1, next);
+ if (len < 0) {
+ if (idx >= 0)
+ ret += FNC1;
+ }
+ else if (next - end - 1 + sai.length() != len)
+ throw new IllegalArgumentException("Invalid AI length: (" + sai + ")");
+ }
+ super.setCode(ret);
+ }
+ else
+ super.setCode(code);
+ }
+
+ static {
+ ais.put(0, 20);
+ ais.put(1, 16);
+ ais.put(2, 16);
+ ais.put(10, -1);
+ ais.put(11, 9);
+ ais.put(12, 8);
+ ais.put(13, 8);
+ ais.put(15, 8);
+ ais.put(17, 8);
+ ais.put(20, 4);
+ ais.put(21, -1);
+ ais.put(22, -1);
+ ais.put(23, -1);
+ ais.put(240, -1);
+ ais.put(241, -1);
+ ais.put(250, -1);
+ ais.put(251, -1);
+ ais.put(252, -1);
+ ais.put(30, -1);
+ for (int k = 3100; k < 3700; ++k)
+ ais.put(k, 10);
+ ais.put(37, -1);
+ for (int k = 3900; k < 3940; ++k)
+ ais.put(k, -1);
+ ais.put(400, -1);
+ ais.put(401, -1);
+ ais.put(402, 20);
+ ais.put(403, -1);
+ for (int k = 410; k < 416; ++k)
+ ais.put(k, 16);
+ ais.put(420, -1);
+ ais.put(421, -1);
+ ais.put(422, 6);
+ ais.put(423, -1);
+ ais.put(424, 6);
+ ais.put(425, 6);
+ ais.put(426, 6);
+ ais.put(7001, 17);
+ ais.put(7002, -1);
+ for (int k = 7030; k < 704; ++k)
+ ais.put(k, -1);
+ ais.put(8001, 18);
+ ais.put(8002, -1);
+ ais.put(8003, -1);
+ ais.put(8004, -1);
+ ais.put(8005, 10);
+ ais.put(8006, 22);
+ ais.put(8007, -1);
+ ais.put(8008, -1);
+ ais.put(8018, 22);
+ ais.put(8020, -1);
+ ais.put(8100, 10);
+ ais.put(8101, 14);
+ ais.put(8102, 6);
+ for (int k = 90; k < 100; ++k)
+ ais.put(k, -1);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/Barcode39.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/Barcode39.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/Barcode39.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/Barcode39.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.ExceptionConverter;
+import pdftk.com.lowagie.text.Element;
+import pdftk.com.lowagie.text.Rectangle;
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.Canvas;
+import java.awt.image.MemoryImageSource;
+
+/** Implements the code 39 and code 39 extended. The default parameters are:
+ *
+ *x = 0.8f;
+ *n = 2;
+ *font = BaseFont.createFont("Helvetica", "winansi", false);
+ *size = 8;
+ *baseline = size;
+ *barHeight = size * 3;
+ *textAlignment = Element.ALIGN_CENTER;
+ *generateChecksum = false;
+ *checksumText = false;
+ *startStopText = true;
+ *extended = false;
+ *
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class Barcode39 extends Barcode{
+
+ /** The bars to generate the code.
+ */
+ static byte BARS[][] =
+ {
+ {0,0,0,1,1,0,1,0,0},
+ {1,0,0,1,0,0,0,0,1},
+ {0,0,1,1,0,0,0,0,1},
+ {1,0,1,1,0,0,0,0,0},
+ {0,0,0,1,1,0,0,0,1},
+ {1,0,0,1,1,0,0,0,0},
+ {0,0,1,1,1,0,0,0,0},
+ {0,0,0,1,0,0,1,0,1},
+ {1,0,0,1,0,0,1,0,0},
+ {0,0,1,1,0,0,1,0,0},
+ {1,0,0,0,0,1,0,0,1},
+ {0,0,1,0,0,1,0,0,1},
+ {1,0,1,0,0,1,0,0,0},
+ {0,0,0,0,1,1,0,0,1},
+ {1,0,0,0,1,1,0,0,0},
+ {0,0,1,0,1,1,0,0,0},
+ {0,0,0,0,0,1,1,0,1},
+ {1,0,0,0,0,1,1,0,0},
+ {0,0,1,0,0,1,1,0,0},
+ {0,0,0,0,1,1,1,0,0},
+ {1,0,0,0,0,0,0,1,1},
+ {0,0,1,0,0,0,0,1,1},
+ {1,0,1,0,0,0,0,1,0},
+ {0,0,0,0,1,0,0,1,1},
+ {1,0,0,0,1,0,0,1,0},
+ {0,0,1,0,1,0,0,1,0},
+ {0,0,0,0,0,0,1,1,1},
+ {1,0,0,0,0,0,1,1,0},
+ {0,0,1,0,0,0,1,1,0},
+ {0,0,0,0,1,0,1,1,0},
+ {1,1,0,0,0,0,0,0,1},
+ {0,1,1,0,0,0,0,0,1},
+ {1,1,1,0,0,0,0,0,0},
+ {0,1,0,0,1,0,0,0,1},
+ {1,1,0,0,1,0,0,0,0},
+ {0,1,1,0,1,0,0,0,0},
+ {0,1,0,0,0,0,1,0,1},
+ {1,1,0,0,0,0,1,0,0},
+ {0,1,1,0,0,0,1,0,0},
+ {0,1,0,1,0,1,0,0,0},
+ {0,1,0,1,0,0,0,1,0},
+ {0,1,0,0,0,1,0,1,0},
+ {0,0,0,1,0,1,0,1,0},
+ {0,1,0,0,1,0,1,0,0}
+ };
+
+ /** The index chars to BARS
.
+ */
+ static String CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*";
+
+ /** The character combinations to make the code 39 extended.
+ */
+ static String EXTENDED = "%U" +
+ "$A$B$C$D$E$F$G$H$I$J$K$L$M$N$O$P$Q$R$S$T$U$V$W$X$Y$Z" +
+ "%A%B%C%D%E /A/B/C/D/E/F/G/H/I/J/K/L - ./O" +
+ " 0 1 2 3 4 5 6 7 8 9/Z%F%G%H%I%J%V" +
+ " A B C D E F G H I J K L M N O P Q R S T U V W X Y Z" +
+ "%K%L%M%N%O%W" +
+ "+A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+Z" +
+ "%P%Q%R%S%T";
+
+ /** Creates a new Barcode39.
+ */
+ public Barcode39() {
+ try {
+ x = 0.8f;
+ n = 2;
+ font = BaseFont.createFont("Helvetica", "winansi", false);
+ size = 8;
+ baseline = size;
+ barHeight = size * 3;
+ textAlignment = Element.ALIGN_CENTER;
+ generateChecksum = false;
+ checksumText = false;
+ startStopText = true;
+ extended = false;
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /** Creates the bars.
+ * @param text the text to create the bars. This text does not include the start and
+ * stop characters
+ * @return the bars
+ */
+ public static byte[] getBarsCode39(String text) {
+ text = "*" + text + "*";
+ byte bars[] = new byte[text.length() * 10 - 1];
+ for (int k = 0; k < text.length(); ++k) {
+ int idx = CHARS.indexOf(text.charAt(k));
+ if (idx < 0)
+ throw new IllegalArgumentException("The character '" + text.charAt(k) + "' is illegal in code 39.");
+ System.arraycopy(BARS[idx], 0, bars, k * 10, 9);
+ }
+ return bars;
+ }
+
+ /** Converts the extended text into a normal, escaped text,
+ * ready to generate bars.
+ * @param text the extended text
+ * @return the escaped text
+ */
+ public static String getCode39Ex(String text) {
+ String out = "";
+ for (int k = 0; k < text.length(); ++k) {
+ char c = text.charAt(k);
+ if (c > 127)
+ throw new IllegalArgumentException("The character '" + c + "' is illegal in code 39 extended.");
+ char c1 = EXTENDED.charAt(c * 2);
+ char c2 = EXTENDED.charAt(c * 2 + 1);
+ if (c1 != ' ')
+ out += c1;
+ out += c2;
+ }
+ return out;
+ }
+
+ /** Calculates the checksum.
+ * @param text the text
+ * @return the checksum
+ */
+ static char getChecksum(String text) {
+ int chk = 0;
+ for (int k = 0; k < text.length(); ++k) {
+ int idx = CHARS.indexOf(text.charAt(k));
+ if (idx < 0)
+ throw new IllegalArgumentException("The character '" + text.charAt(k) + "' is illegal in code 39.");
+ chk += idx;
+ }
+ return CHARS.charAt(chk % 43);
+ }
+
+ /** Gets the maximum area that the barcode and the text, if
+ * any, will occupy. The lower left corner is always (0, 0).
+ * @return the size the barcode occupies.
+ */
+ public Rectangle getBarcodeSize() {
+ float fontX = 0;
+ float fontY = 0;
+ if (font != null) {
+ if (baseline > 0)
+ fontY = baseline - font.getFontDescriptor(BaseFont.DESCENT, size);
+ else
+ fontY = -baseline + size;
+ String fullCode = code;
+ if (generateChecksum && checksumText)
+ fullCode += getChecksum(fullCode);
+ if (startStopText)
+ fullCode = "*" + fullCode + "*";
+ fontX = font.getWidthPoint(fullCode, size);
+ }
+ String fullCode = code;
+ if (extended)
+ fullCode = getCode39Ex(code);
+ int len = fullCode.length() + 2;
+ if (generateChecksum)
+ ++len;
+ float fullWidth = len * (6 * x + 3 * x * n) + (len - 1) * x;
+ fullWidth = Math.max(fullWidth, fontX);
+ float fullHeight = barHeight + fontY;
+ return new Rectangle(fullWidth, fullHeight);
+ }
+
+ /** Places the barcode in a PdfContentByte
. The
+ * barcode is always placed at coodinates (0, 0). Use the
+ * translation matrix to move it elsewhere.
+ * The bars and text are written in the following colors:
+ *
+ *
+ * barColor
+ * textColor
+ * Result
+ *
+ *
+ * null
+ * null
+ * bars and text painted with current fill color
+ *
+ *
+ * barColor
+ * null
+ * bars and text painted with barColor
+ *
+ *
+ * null
+ * textColor
+ * bars painted with current color text painted with textColor
+ *
+ *
+ * barColor
+ * textColor
+ * bars painted with barColor
text painted with textColor
+ *
+ *
+ * @param cb the PdfContentByte
where the barcode will be placed
+ * @param barColor the color of the bars. It can be null
+ * @param textColor the color of the text. It can be null
+ * @return the dimensions the barcode occupies
+ */
+ public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
+ String fullCode = code;
+ float fontX = 0;
+ if (font != null) {
+ if (generateChecksum && checksumText)
+ fullCode += getChecksum(fullCode);
+ if (startStopText)
+ fullCode = "*" + fullCode + "*";
+ fontX = font.getWidthPoint(fullCode, size);
+ }
+ String bCode = code;
+ if (extended)
+ bCode = getCode39Ex(code);
+ if (generateChecksum)
+ bCode += getChecksum(bCode);
+ int len = bCode.length() + 2;
+ float fullWidth = len * (6 * x + 3 * x * n) + (len - 1) * x;
+ float barStartX = 0;
+ float textStartX = 0;
+ switch (textAlignment) {
+ case Element.ALIGN_LEFT:
+ break;
+ case Element.ALIGN_RIGHT:
+ if (fontX > fullWidth)
+ barStartX = fontX - fullWidth;
+ else
+ textStartX = fullWidth - fontX;
+ break;
+ default:
+ if (fontX > fullWidth)
+ barStartX = (fontX - fullWidth) / 2;
+ else
+ textStartX = (fullWidth - fontX) / 2;
+ break;
+ }
+ float barStartY = 0;
+ float textStartY = 0;
+ if (font != null) {
+ if (baseline <= 0)
+ textStartY = barHeight - baseline;
+ else {
+ textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size);
+ barStartY = textStartY + baseline;
+ }
+ }
+ byte bars[] = getBarsCode39(bCode);
+ boolean print = true;
+ if (barColor != null)
+ cb.setColorFill(barColor);
+ for (int k = 0; k < bars.length; ++k) {
+ float w = (bars[k] == 0 ? x : x * n);
+ if (print)
+ cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight);
+ print = !print;
+ barStartX += w;
+ }
+ cb.fill();
+ if (font != null) {
+ if (textColor != null)
+ cb.setColorFill(textColor);
+ cb.beginText();
+ cb.setFontAndSize(font, size);
+ cb.setTextMatrix(textStartX, textStartY);
+ cb.showText(fullCode);
+ cb.endText();
+ }
+ return getBarcodeSize();
+ }
+
+ /** Creates a java.awt.Image
. This image only
+ * contains the bars without any text.
+ * @param foreground the color of the bars
+ * @param background the color of the background
+ * @return the image
+ */
+ public java.awt.Image createAwtImage(Color foreground, Color background) {
+ int f = foreground.getRGB();
+ int g = background.getRGB();
+ Canvas canvas = new Canvas();
+
+ String bCode = code;
+ if (extended)
+ bCode = getCode39Ex(code);
+ if (generateChecksum)
+ bCode += getChecksum(bCode);
+ int len = bCode.length() + 2;
+ int nn = (int)n;
+ int fullWidth = len * (6 + 3 * nn) + (len - 1);
+ byte bars[] = getBarsCode39(bCode);
+ boolean print = true;
+ int ptr = 0;
+ int height = (int)barHeight;
+ int pix[] = new int[fullWidth * height];
+ for (int k = 0; k < bars.length; ++k) {
+ int w = (bars[k] == 0 ? 1 : nn);
+ int c = g;
+ if (print)
+ c = f;
+ print = !print;
+ for (int j = 0; j < w; ++j)
+ pix[ptr++] = c;
+ }
+ for (int k = fullWidth; k < pix.length; k += fullWidth) {
+ System.arraycopy(pix, 0, pix, k, fullWidth);
+ }
+ Image img = canvas.createImage(new MemoryImageSource(fullWidth, height, pix, 0, fullWidth));
+
+ return img;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BarcodeCodabar.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BarcodeCodabar.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BarcodeCodabar.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BarcodeCodabar.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.ExceptionConverter;
+import pdftk.com.lowagie.text.Element;
+import pdftk.com.lowagie.text.Rectangle;
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.Canvas;
+import java.awt.image.MemoryImageSource;
+
+/** Implements the code codabar. The default parameters are:
+ *
+ *x = 0.8f;
+ *n = 2;
+ *font = BaseFont.createFont("Helvetica", "winansi", false);
+ *size = 8;
+ *baseline = size;
+ *barHeight = size * 3;
+ *textAlignment = Element.ALIGN_CENTER;
+ *generateChecksum = false;
+ *checksumText = false;
+ *startStopText = false;
+ *
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class BarcodeCodabar extends Barcode{
+
+ /** The bars to generate the code.
+ */
+ static byte BARS[][] =
+ {
+ {0,0,0,0,0,1,1}, // 0
+ {0,0,0,0,1,1,0}, // 1
+ {0,0,0,1,0,0,1}, // 2
+ {1,1,0,0,0,0,0}, // 3
+ {0,0,1,0,0,1,0}, // 4
+ {1,0,0,0,0,1,0}, // 5
+ {0,1,0,0,0,0,1}, // 6
+ {0,1,0,0,1,0,0}, // 7
+ {0,1,1,0,0,0,0}, // 8
+ {1,0,0,1,0,0,0}, // 9
+ {0,0,0,1,1,0,0}, // -
+ {0,0,1,1,0,0,0}, // $
+ {1,0,0,0,1,0,1}, // :
+ {1,0,1,0,0,0,1}, // /
+ {1,0,1,0,1,0,0}, // .
+ {0,0,1,0,1,0,1}, // +
+ {0,0,1,1,0,1,0}, // a
+ {0,1,0,1,0,0,1}, // b
+ {0,0,0,1,0,1,1}, // c
+ {0,0,0,1,1,1,0} // d
+ };
+
+ /** The index chars to BARS
.
+ */
+ static String CHARS = "0123456789-$:/.+ABCD";
+
+ static final int START_STOP_IDX = 16;
+ /** Creates a new BarcodeCodabar.
+ */
+ public BarcodeCodabar() {
+ try {
+ x = 0.8f;
+ n = 2;
+ font = BaseFont.createFont("Helvetica", "winansi", false);
+ size = 8;
+ baseline = size;
+ barHeight = size * 3;
+ textAlignment = Element.ALIGN_CENTER;
+ generateChecksum = false;
+ checksumText = false;
+ startStopText = false;
+ codeType = CODABAR;
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /** Creates the bars.
+ * @param text the text to create the bars
+ * @return the bars
+ */
+ public static byte[] getBarsCodabar(String text) {
+ text = text.toUpperCase();
+ int len = text.length();
+ if (len < 2)
+ throw new IllegalArgumentException("Codabar must have at least a start and stop character.");
+ if (CHARS.indexOf(text.charAt(0)) < START_STOP_IDX || CHARS.indexOf(text.charAt(len - 1)) < START_STOP_IDX)
+ throw new IllegalArgumentException("Codabar must have one of 'ABCD' as start/stop character.");
+ byte bars[] = new byte[text.length() * 8 - 1];
+ for (int k = 0; k < len; ++k) {
+ int idx = CHARS.indexOf(text.charAt(k));
+ if (idx >= START_STOP_IDX && k > 0 && k < len - 1)
+ throw new IllegalArgumentException("In codabar, start/stop characters are only allowed at the extremes.");
+ if (idx < 0)
+ throw new IllegalArgumentException("The character '" + text.charAt(k) + "' is illegal in codabar.");
+ System.arraycopy(BARS[idx], 0, bars, k * 8, 7);
+ }
+ return bars;
+ }
+
+ public static String calculateChecksum(String code) {
+ if (code.length() < 2)
+ return code;
+ String text = code.toUpperCase();
+ int sum = 0;
+ int len = text.length();
+ for (int k = 0; k < len; ++k)
+ sum += CHARS.indexOf(text.charAt(k));
+ sum = (sum + 15) / 16 * 16 - sum;
+ return code.substring(0, len - 1) + CHARS.charAt(sum) + code.substring(len - 1);
+ }
+
+ /** Gets the maximum area that the barcode and the text, if
+ * any, will occupy. The lower left corner is always (0, 0).
+ * @return the size the barcode occupies.
+ */
+ public Rectangle getBarcodeSize() {
+ float fontX = 0;
+ float fontY = 0;
+ String text = code;
+ if (generateChecksum && checksumText)
+ text = calculateChecksum(code);
+ if (!startStopText)
+ text = text.substring(1, text.length() - 1);
+ if (font != null) {
+ if (baseline > 0)
+ fontY = baseline - font.getFontDescriptor(BaseFont.DESCENT, size);
+ else
+ fontY = -baseline + size;
+ fontX = font.getWidthPoint(text, size);
+ }
+ text = code;
+ if (generateChecksum)
+ text = calculateChecksum(code);
+ byte bars[] = getBarsCodabar(text);
+ int wide = 0;
+ for (int k = 0; k < bars.length; ++k) {
+ wide += (int)bars[k];
+ }
+ int narrow = bars.length - wide;
+ float fullWidth = x * (narrow + wide * n);
+ fullWidth = Math.max(fullWidth, fontX);
+ float fullHeight = barHeight + fontY;
+ return new Rectangle(fullWidth, fullHeight);
+ }
+
+ /** Places the barcode in a PdfContentByte
. The
+ * barcode is always placed at coodinates (0, 0). Use the
+ * translation matrix to move it elsewhere.
+ * The bars and text are written in the following colors:
+ *
+ *
+ * barColor
+ * textColor
+ * Result
+ *
+ *
+ * null
+ * null
+ * bars and text painted with current fill color
+ *
+ *
+ * barColor
+ * null
+ * bars and text painted with barColor
+ *
+ *
+ * null
+ * textColor
+ * bars painted with current color text painted with textColor
+ *
+ *
+ * barColor
+ * textColor
+ * bars painted with barColor
text painted with textColor
+ *
+ *
+ * @param cb the PdfContentByte
where the barcode will be placed
+ * @param barColor the color of the bars. It can be null
+ * @param textColor the color of the text. It can be null
+ * @return the dimensions the barcode occupies
+ */
+ public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
+ String fullCode = code;
+ if (generateChecksum && checksumText)
+ fullCode = calculateChecksum(code);
+ if (!startStopText)
+ fullCode = fullCode.substring(1, fullCode.length() - 1);
+ float fontX = 0;
+ if (font != null) {
+ fontX = font.getWidthPoint(fullCode, size);
+ }
+ byte bars[] = getBarsCodabar(generateChecksum ? calculateChecksum(code) : code);
+ int wide = 0;
+ for (int k = 0; k < bars.length; ++k) {
+ wide += (int)bars[k];
+ }
+ int narrow = bars.length - wide;
+ float fullWidth = x * (narrow + wide * n);
+ float barStartX = 0;
+ float textStartX = 0;
+ switch (textAlignment) {
+ case Element.ALIGN_LEFT:
+ break;
+ case Element.ALIGN_RIGHT:
+ if (fontX > fullWidth)
+ barStartX = fontX - fullWidth;
+ else
+ textStartX = fullWidth - fontX;
+ break;
+ default:
+ if (fontX > fullWidth)
+ barStartX = (fontX - fullWidth) / 2;
+ else
+ textStartX = (fullWidth - fontX) / 2;
+ break;
+ }
+ float barStartY = 0;
+ float textStartY = 0;
+ if (font != null) {
+ if (baseline <= 0)
+ textStartY = barHeight - baseline;
+ else {
+ textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size);
+ barStartY = textStartY + baseline;
+ }
+ }
+ boolean print = true;
+ if (barColor != null)
+ cb.setColorFill(barColor);
+ for (int k = 0; k < bars.length; ++k) {
+ float w = (bars[k] == 0 ? x : x * n);
+ if (print)
+ cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight);
+ print = !print;
+ barStartX += w;
+ }
+ cb.fill();
+ if (font != null) {
+ if (textColor != null)
+ cb.setColorFill(textColor);
+ cb.beginText();
+ cb.setFontAndSize(font, size);
+ cb.setTextMatrix(textStartX, textStartY);
+ cb.showText(fullCode);
+ cb.endText();
+ }
+ return getBarcodeSize();
+ }
+
+ /** Creates a java.awt.Image
. This image only
+ * contains the bars without any text.
+ * @param foreground the color of the bars
+ * @param background the color of the background
+ * @return the image
+ */
+ public java.awt.Image createAwtImage(Color foreground, Color background) {
+ int f = foreground.getRGB();
+ int g = background.getRGB();
+ Canvas canvas = new Canvas();
+
+ String fullCode = code;
+ if (generateChecksum && checksumText)
+ fullCode = calculateChecksum(code);
+ if (!startStopText)
+ fullCode = fullCode.substring(1, fullCode.length() - 1);
+ byte bars[] = getBarsCodabar(generateChecksum ? calculateChecksum(code) : code);
+ int wide = 0;
+ for (int k = 0; k < bars.length; ++k) {
+ wide += (int)bars[k];
+ }
+ int narrow = bars.length - wide;
+ int fullWidth = narrow + wide * (int)n;
+ boolean print = true;
+ int ptr = 0;
+ int height = (int)barHeight;
+ int pix[] = new int[fullWidth * height];
+ for (int k = 0; k < bars.length; ++k) {
+ int w = (bars[k] == 0 ? 1 : (int)n);
+ int c = g;
+ if (print)
+ c = f;
+ print = !print;
+ for (int j = 0; j < w; ++j)
+ pix[ptr++] = c;
+ }
+ for (int k = fullWidth; k < pix.length; k += fullWidth) {
+ System.arraycopy(pix, 0, pix, k, fullWidth);
+ }
+ Image img = canvas.createImage(new MemoryImageSource(fullWidth, height, pix, 0, fullWidth));
+
+ return img;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BarcodeEAN.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BarcodeEAN.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BarcodeEAN.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BarcodeEAN.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,708 @@
+/*
+ * Copyright 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.Rectangle;
+import pdftk.com.lowagie.text.ExceptionConverter;
+import java.util.Arrays;
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.Canvas;
+import java.awt.image.MemoryImageSource;
+
+/** Generates barcodes in several formats: EAN13, EAN8, UPCA, UPCE,
+ * supplemental 2 and 5. The default parameters are:
+ *
+ *x = 0.8f;
+ *font = BaseFont.createFont("Helvetica", "winansi", false);
+ *size = 8;
+ *baseline = size;
+ *barHeight = size * 3;
+ *guardBars = true;
+ *codeType = EAN13;
+ *code = "";
+ *
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class BarcodeEAN extends Barcode{
+
+ /** The bar positions that are guard bars.*/
+ static int GUARD_EMPTY[] = {};
+ /** The bar positions that are guard bars.*/
+ static int GUARD_UPCA[] = {0, 2, 4, 6, 28, 30, 52, 54, 56, 58};
+ /** The bar positions that are guard bars.*/
+ static int GUARD_EAN13[] = {0, 2, 28, 30, 56, 58};
+ /** The bar positions that are guard bars.*/
+ static int GUARD_EAN8[] = {0, 2, 20, 22, 40, 42};
+ /** The bar positions that are guard bars.*/
+ static int GUARD_UPCE[] = {0, 2, 28, 30, 32};
+ /** The x coordinates to place the text.*/
+ static float TEXTPOS_EAN13[] = {6.5f, 13.5f, 20.5f, 27.5f, 34.5f, 41.5f, 53.5f, 60.5f, 67.5f, 74.5f, 81.5f, 88.5f};
+ /** The x coordinates to place the text.*/
+ static float TEXTPOS_EAN8[] = {6.5f, 13.5f, 20.5f, 27.5f, 39.5f, 46.5f, 53.5f, 60.5f};
+ /** The basic bar widths.*/
+ static byte BARS[][] =
+ {
+ {3, 2, 1, 1}, // 0
+ {2, 2, 2, 1}, // 1
+ {2, 1, 2, 2}, // 2
+ {1, 4, 1, 1}, // 3
+ {1, 1, 3, 2}, // 4
+ {1, 2, 3, 1}, // 5
+ {1, 1, 1, 4}, // 6
+ {1, 3, 1, 2}, // 7
+ {1, 2, 1, 3}, // 8
+ {3, 1, 1, 2} // 9
+ };
+
+ /** The total number of bars for EAN13.*/
+ static final int TOTALBARS_EAN13 = 11 + 12 * 4;
+ /** The total number of bars for EAN8.*/
+ static final int TOTALBARS_EAN8 = 11 + 8 * 4;
+ /** The total number of bars for UPCE.*/
+ static final int TOTALBARS_UPCE = 9 + 6 * 4;
+ /** The total number of bars for supplemental 2.*/
+ static final int TOTALBARS_SUPP2 = 13;
+ /** The total number of bars for supplemental 5.*/
+ static final int TOTALBARS_SUPP5 = 31;
+ /** Marker for odd parity.*/
+ static final int ODD = 0;
+ /** Marker for even parity.*/
+ static final int EVEN = 1;
+
+ /** Sequence of parities to be used with EAN13.*/
+ static byte PARITY13[][] =
+ {
+ {ODD, ODD, ODD, ODD, ODD, ODD}, // 0
+ {ODD, ODD, EVEN, ODD, EVEN, EVEN}, // 1
+ {ODD, ODD, EVEN, EVEN, ODD, EVEN}, // 2
+ {ODD, ODD, EVEN, EVEN, EVEN, ODD}, // 3
+ {ODD, EVEN, ODD, ODD, EVEN, EVEN}, // 4
+ {ODD, EVEN, EVEN, ODD, ODD, EVEN}, // 5
+ {ODD, EVEN, EVEN, EVEN, ODD, ODD}, // 6
+ {ODD, EVEN, ODD, EVEN, ODD, EVEN}, // 7
+ {ODD, EVEN, ODD, EVEN, EVEN, ODD}, // 8
+ {ODD, EVEN, EVEN, ODD, EVEN, ODD} // 9
+ };
+
+ /** Sequence of parities to be used with supplemental 2.*/
+ static byte PARITY2[][] =
+ {
+ {ODD, ODD}, // 0
+ {ODD, EVEN}, // 1
+ {EVEN, ODD}, // 2
+ {EVEN, EVEN} // 3
+ };
+
+ /** Sequence of parities to be used with supplemental 2.*/
+ static byte PARITY5[][] =
+ {
+ {EVEN, EVEN, ODD, ODD, ODD}, // 0
+ {EVEN, ODD, EVEN, ODD, ODD}, // 1
+ {EVEN, ODD, ODD, EVEN, ODD}, // 2
+ {EVEN, ODD, ODD, ODD, EVEN}, // 3
+ {ODD, EVEN, EVEN, ODD, ODD}, // 4
+ {ODD, ODD, EVEN, EVEN, ODD}, // 5
+ {ODD, ODD, ODD, EVEN, EVEN}, // 6
+ {ODD, EVEN, ODD, EVEN, ODD}, // 7
+ {ODD, EVEN, ODD, ODD, EVEN}, // 8
+ {ODD, ODD, EVEN, ODD, EVEN} // 9
+ };
+
+ /** Sequence of parities to be used with UPCE.*/
+ static byte PARITYE[][] =
+ {
+ {EVEN, EVEN, EVEN, ODD, ODD, ODD}, // 0
+ {EVEN, EVEN, ODD, EVEN, ODD, ODD}, // 1
+ {EVEN, EVEN, ODD, ODD, EVEN, ODD}, // 2
+ {EVEN, EVEN, ODD, ODD, ODD, EVEN}, // 3
+ {EVEN, ODD, EVEN, EVEN, ODD, ODD}, // 4
+ {EVEN, ODD, ODD, EVEN, EVEN, ODD}, // 5
+ {EVEN, ODD, ODD, ODD, EVEN, EVEN}, // 6
+ {EVEN, ODD, EVEN, ODD, EVEN, ODD}, // 7
+ {EVEN, ODD, EVEN, ODD, ODD, EVEN}, // 8
+ {EVEN, ODD, ODD, EVEN, ODD, EVEN} // 9
+ };
+
+ /** Creates new BarcodeEAN */
+ public BarcodeEAN() {
+ try {
+ x = 0.8f;
+ font = BaseFont.createFont("Helvetica", "winansi", false);
+ size = 8;
+ baseline = size;
+ barHeight = size * 3;
+ guardBars = true;
+ codeType = EAN13;
+ code = "";
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /** Calculates the EAN parity character.
+ * @param code the code
+ * @return the parity character
+ */
+ public static int calculateEANParity(String code) {
+ int mul = 3;
+ int total = 0;
+ for (int k = code.length() - 1; k >= 0; --k) {
+ int n = code.charAt(k) - '0';
+ total += mul * n;
+ mul ^= 2;
+ }
+ return (10 - (total % 10)) % 10;
+ }
+
+ /** Converts an UPCA code into an UPCE code. If the code can not
+ * be converted a null
is returned.
+ * @param text the code to convert. It must have 12 numeric characters
+ * @return the 8 converted digits or null
if the
+ * code could not be converted
+ */
+ static public String convertUPCAtoUPCE(String text) {
+ if (text.length() != 12 || !(text.startsWith("0") || text.startsWith("1")))
+ return null;
+ if (text.substring(3, 6).equals("000") || text.substring(3, 6).equals("100")
+ || text.substring(3, 6).equals("200")) {
+ if (text.substring(6, 8).equals("00"))
+ return text.substring(0, 1) + text.substring(1, 3) + text.substring(8, 11) + text.substring(3, 4) + text.substring(11);
+ }
+ else if (text.substring(4, 6).equals("00")) {
+ if (text.substring(6, 9).equals("000"))
+ return text.substring(0, 1) + text.substring(1, 4) + text.substring(9, 11) + "3" + text.substring(11);
+ }
+ else if (text.substring(5, 6).equals("0")) {
+ if (text.substring(6, 10).equals("0000"))
+ return text.substring(0, 1) + text.substring(1, 5) + text.substring(10, 11) + "4" + text.substring(11);
+ }
+ else if (text.charAt(10) >= '5') {
+ if (text.substring(6, 10).equals("0000"))
+ return text.substring(0, 1) + text.substring(1, 6) + text.substring(10, 11) + text.substring(11);
+ }
+ return null;
+ }
+
+ /** Creates the bars for the barcode EAN13 and UPCA.
+ * @param _code the text with 13 digits
+ * @return the barcode
+ */
+ public static byte[] getBarsEAN13(String _code) {
+ int code[] = new int[_code.length()];
+ for (int k = 0; k < code.length; ++k)
+ code[k] = _code.charAt(k) - '0';
+ byte bars[] = new byte[TOTALBARS_EAN13];
+ int pb = 0;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ byte sequence[] = PARITY13[code[0]];
+ for (int k = 0; k < sequence.length; ++k) {
+ int c = code[k + 1];
+ byte stripes[] = BARS[c];
+ if (sequence[k] == ODD) {
+ bars[pb++] = stripes[0];
+ bars[pb++] = stripes[1];
+ bars[pb++] = stripes[2];
+ bars[pb++] = stripes[3];
+ }
+ else {
+ bars[pb++] = stripes[3];
+ bars[pb++] = stripes[2];
+ bars[pb++] = stripes[1];
+ bars[pb++] = stripes[0];
+ }
+ }
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ for (int k = 7; k < 13; ++k) {
+ int c = code[k];
+ byte stripes[] = BARS[c];
+ bars[pb++] = stripes[0];
+ bars[pb++] = stripes[1];
+ bars[pb++] = stripes[2];
+ bars[pb++] = stripes[3];
+ }
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ return bars;
+ }
+
+ /** Creates the bars for the barcode EAN8.
+ * @param _code the text with 8 digits
+ * @return the barcode
+ */
+ public static byte[] getBarsEAN8(String _code) {
+ int code[] = new int[_code.length()];
+ for (int k = 0; k < code.length; ++k)
+ code[k] = _code.charAt(k) - '0';
+ byte bars[] = new byte[TOTALBARS_EAN8];
+ int pb = 0;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ for (int k = 0; k < 4; ++k) {
+ int c = code[k];
+ byte stripes[] = BARS[c];
+ bars[pb++] = stripes[0];
+ bars[pb++] = stripes[1];
+ bars[pb++] = stripes[2];
+ bars[pb++] = stripes[3];
+ }
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ for (int k = 4; k < 8; ++k) {
+ int c = code[k];
+ byte stripes[] = BARS[c];
+ bars[pb++] = stripes[0];
+ bars[pb++] = stripes[1];
+ bars[pb++] = stripes[2];
+ bars[pb++] = stripes[3];
+ }
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ return bars;
+ }
+
+ /** Creates the bars for the barcode UPCE.
+ * @param _code the text with 8 digits
+ * @return the barcode
+ */
+ public static byte[] getBarsUPCE(String _code) {
+ int code[] = new int[_code.length()];
+ for (int k = 0; k < code.length; ++k)
+ code[k] = _code.charAt(k) - '0';
+ byte bars[] = new byte[TOTALBARS_UPCE];
+ boolean flip = (code[0] != 0);
+ int pb = 0;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ byte sequence[] = PARITYE[code[code.length - 1]];
+ for (int k = 1; k < code.length - 1; ++k) {
+ int c = code[k];
+ byte stripes[] = BARS[c];
+ if (sequence[k - 1] == (flip ? EVEN : ODD)) {
+ bars[pb++] = stripes[0];
+ bars[pb++] = stripes[1];
+ bars[pb++] = stripes[2];
+ bars[pb++] = stripes[3];
+ }
+ else {
+ bars[pb++] = stripes[3];
+ bars[pb++] = stripes[2];
+ bars[pb++] = stripes[1];
+ bars[pb++] = stripes[0];
+ }
+ }
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ return bars;
+ }
+
+ /** Creates the bars for the barcode supplemental 2.
+ * @param _code the text with 2 digits
+ * @return the barcode
+ */
+ public static byte[] getBarsSupplemental2(String _code) {
+ int code[] = new int[2];
+ for (int k = 0; k < code.length; ++k)
+ code[k] = _code.charAt(k) - '0';
+ byte bars[] = new byte[TOTALBARS_SUPP2];
+ int pb = 0;
+ int parity = (code[0] * 10 + code[1]) % 4;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 2;
+ byte sequence[] = PARITY2[parity];
+ for (int k = 0; k < sequence.length; ++k) {
+ if (k == 1) {
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ }
+ int c = code[k];
+ byte stripes[] = BARS[c];
+ if (sequence[k] == ODD) {
+ bars[pb++] = stripes[0];
+ bars[pb++] = stripes[1];
+ bars[pb++] = stripes[2];
+ bars[pb++] = stripes[3];
+ }
+ else {
+ bars[pb++] = stripes[3];
+ bars[pb++] = stripes[2];
+ bars[pb++] = stripes[1];
+ bars[pb++] = stripes[0];
+ }
+ }
+ return bars;
+ }
+
+ /** Creates the bars for the barcode supplemental 5.
+ * @param _code the text with 5 digits
+ * @return the barcode
+ */
+ public static byte[] getBarsSupplemental5(String _code) {
+ int code[] = new int[5];
+ for (int k = 0; k < code.length; ++k)
+ code[k] = _code.charAt(k) - '0';
+ byte bars[] = new byte[TOTALBARS_SUPP5];
+ int pb = 0;
+ int parity = (((code[0] + code[2] + code[4]) * 3) + ((code[1] + code[3]) * 9)) % 10;
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ bars[pb++] = 2;
+ byte sequence[] = PARITY5[parity];
+ for (int k = 0; k < sequence.length; ++k) {
+ if (k != 0) {
+ bars[pb++] = 1;
+ bars[pb++] = 1;
+ }
+ int c = code[k];
+ byte stripes[] = BARS[c];
+ if (sequence[k] == ODD) {
+ bars[pb++] = stripes[0];
+ bars[pb++] = stripes[1];
+ bars[pb++] = stripes[2];
+ bars[pb++] = stripes[3];
+ }
+ else {
+ bars[pb++] = stripes[3];
+ bars[pb++] = stripes[2];
+ bars[pb++] = stripes[1];
+ bars[pb++] = stripes[0];
+ }
+ }
+ return bars;
+ }
+
+ /** Gets the maximum area that the barcode and the text, if
+ * any, will occupy. The lower left corner is always (0, 0).
+ * @return the size the barcode occupies.
+ */
+ public Rectangle getBarcodeSize() {
+ float width = 0;
+ float height = barHeight;
+ if (font != null) {
+ if (baseline <= 0)
+ height += -baseline + size;
+ else
+ height += baseline - font.getFontDescriptor(BaseFont.DESCENT, size);
+ }
+ switch (codeType) {
+ case EAN13:
+ width = x * (11 + 12 * 7);
+ if (font != null) {
+ width += font.getWidthPoint(code.charAt(0), size);
+ }
+ break;
+ case EAN8:
+ width = x * (11 + 8 * 7);
+ break;
+ case UPCA:
+ width = x * (11 + 12 * 7);
+ if (font != null) {
+ width += font.getWidthPoint(code.charAt(0), size) + font.getWidthPoint(code.charAt(11), size);
+ }
+ break;
+ case UPCE:
+ width = x * (9 + 6 * 7);
+ if (font != null) {
+ width += font.getWidthPoint(code.charAt(0), size) + font.getWidthPoint(code.charAt(7), size);
+ }
+ break;
+ case SUPP2:
+ width = x * (6 + 2 * 7);
+ break;
+ case SUPP5:
+ width = x * (4 + 5 * 7 + 4 * 2);
+ break;
+ default:
+ throw new RuntimeException("Invalid code type.");
+ }
+ return new Rectangle(width, height);
+ }
+
+ /** Places the barcode in a PdfContentByte
. The
+ * barcode is always placed at coodinates (0, 0). Use the
+ * translation matrix to move it elsewhere.
+ * The bars and text are written in the following colors:
+ *
+ *
+ * barColor
+ * textColor
+ * Result
+ *
+ *
+ * null
+ * null
+ * bars and text painted with current fill color
+ *
+ *
+ * barColor
+ * null
+ * bars and text painted with barColor
+ *
+ *
+ * null
+ * textColor
+ * bars painted with current color text painted with textColor
+ *
+ *
+ * barColor
+ * textColor
+ * bars painted with barColor
text painted with textColor
+ *
+ *
+ * @param cb the PdfContentByte
where the barcode will be placed
+ * @param barColor the color of the bars. It can be null
+ * @param textColor the color of the text. It can be null
+ * @return the dimensions the barcode occupies
+ */
+ public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
+ Rectangle rect = getBarcodeSize();
+ float barStartX = 0;
+ float barStartY = 0;
+ float textStartY = 0;
+ if (font != null) {
+ if (baseline <= 0)
+ textStartY = barHeight - baseline;
+ else {
+ textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size);
+ barStartY = textStartY + baseline;
+ }
+ }
+ switch (codeType) {
+ case EAN13:
+ case UPCA:
+ case UPCE:
+ if (font != null)
+ barStartX += font.getWidthPoint(code.charAt(0), size);
+ break;
+ }
+ byte bars[] = null;
+ int guard[] = GUARD_EMPTY;
+ switch (codeType) {
+ case EAN13:
+ bars = getBarsEAN13(code);
+ guard = GUARD_EAN13;
+ break;
+ case EAN8:
+ bars = getBarsEAN8(code);
+ guard = GUARD_EAN8;
+ break;
+ case UPCA:
+ bars = getBarsEAN13("0" + code);
+ guard = GUARD_UPCA;
+ break;
+ case UPCE:
+ bars = getBarsUPCE(code);
+ guard = GUARD_UPCE;
+ break;
+ case SUPP2:
+ bars = getBarsSupplemental2(code);
+ break;
+ case SUPP5:
+ bars = getBarsSupplemental5(code);
+ break;
+ }
+ float keepBarX = barStartX;
+ boolean print = true;
+ float gd = 0;
+ if (font != null && baseline > 0 && guardBars) {
+ gd = baseline / 2;
+ }
+ if (barColor != null)
+ cb.setColorFill(barColor);
+ for (int k = 0; k < bars.length; ++k) {
+ float w = bars[k] * x;
+ if (print) {
+ if (Arrays.binarySearch(guard, k) >= 0)
+ cb.rectangle(barStartX, barStartY - gd, w - inkSpreading, barHeight + gd);
+ else
+ cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight);
+ }
+ print = !print;
+ barStartX += w;
+ }
+ cb.fill();
+ if (font != null) {
+ if (textColor != null)
+ cb.setColorFill(textColor);
+ cb.beginText();
+ cb.setFontAndSize(font, size);
+ switch (codeType) {
+ case EAN13:
+ cb.setTextMatrix(0, textStartY);
+ cb.showText(code.substring(0, 1));
+ for (int k = 1; k < 13; ++k) {
+ String c = code.substring(k, k + 1);
+ float len = font.getWidthPoint(c, size);
+ float pX = keepBarX + TEXTPOS_EAN13[k - 1] * x - len / 2;
+ cb.setTextMatrix(pX, textStartY);
+ cb.showText(c);
+ }
+ break;
+ case EAN8:
+ for (int k = 0; k < 8; ++k) {
+ String c = code.substring(k, k + 1);
+ float len = font.getWidthPoint(c, size);
+ float pX = TEXTPOS_EAN8[k] * x - len / 2;
+ cb.setTextMatrix(pX, textStartY);
+ cb.showText(c);
+ }
+ break;
+ case UPCA:
+ cb.setTextMatrix(0, textStartY);
+ cb.showText(code.substring(0, 1));
+ for (int k = 1; k < 11; ++k) {
+ String c = code.substring(k, k + 1);
+ float len = font.getWidthPoint(c, size);
+ float pX = keepBarX + TEXTPOS_EAN13[k] * x - len / 2;
+ cb.setTextMatrix(pX, textStartY);
+ cb.showText(c);
+ }
+ cb.setTextMatrix(keepBarX + x * (11 + 12 * 7), textStartY);
+ cb.showText(code.substring(11, 12));
+ break;
+ case UPCE:
+ cb.setTextMatrix(0, textStartY);
+ cb.showText(code.substring(0, 1));
+ for (int k = 1; k < 7; ++k) {
+ String c = code.substring(k, k + 1);
+ float len = font.getWidthPoint(c, size);
+ float pX = keepBarX + TEXTPOS_EAN13[k - 1] * x - len / 2;
+ cb.setTextMatrix(pX, textStartY);
+ cb.showText(c);
+ }
+ cb.setTextMatrix(keepBarX + x * (9 + 6 * 7), textStartY);
+ cb.showText(code.substring(7, 8));
+ break;
+ case SUPP2:
+ case SUPP5:
+ for (int k = 0; k < code.length(); ++k) {
+ String c = code.substring(k, k + 1);
+ float len = font.getWidthPoint(c, size);
+ float pX = (7.5f + (9 * k)) * x - len / 2;
+ cb.setTextMatrix(pX, textStartY);
+ cb.showText(c);
+ }
+ break;
+ }
+ cb.endText();
+ }
+ return rect;
+ }
+
+ /** Creates a java.awt.Image
. This image only
+ * contains the bars without any text.
+ * @param foreground the color of the bars
+ * @param background the color of the background
+ * @return the image
+ */
+ public java.awt.Image createAwtImage(Color foreground, Color background) {
+ int f = foreground.getRGB();
+ int g = background.getRGB();
+ Canvas canvas = new Canvas();
+
+ int width = 0;
+ byte bars[] = null;
+ switch (codeType) {
+ case EAN13:
+ bars = getBarsEAN13(code);
+ width = 11 + 12 * 7;
+ break;
+ case EAN8:
+ bars = getBarsEAN8(code);
+ width = 11 + 8 * 7;
+ break;
+ case UPCA:
+ bars = getBarsEAN13("0" + code);
+ width = 11 + 12 * 7;
+ break;
+ case UPCE:
+ bars = getBarsUPCE(code);
+ width = 9 + 6 * 7;
+ break;
+ case SUPP2:
+ bars = getBarsSupplemental2(code);
+ width = 6 + 2 * 7;
+ break;
+ case SUPP5:
+ bars = getBarsSupplemental5(code);
+ width = 4 + 5 * 7 + 4 * 2;
+ break;
+ default:
+ throw new RuntimeException("Invalid code type.");
+ }
+
+ boolean print = true;
+ int ptr = 0;
+ int height = (int)barHeight;
+ int pix[] = new int[width * height];
+ for (int k = 0; k < bars.length; ++k) {
+ int w = bars[k];
+ int c = g;
+ if (print)
+ c = f;
+ print = !print;
+ for (int j = 0; j < w; ++j)
+ pix[ptr++] = c;
+ }
+ for (int k = width; k < pix.length; k += width) {
+ System.arraycopy(pix, 0, pix, k, width);
+ }
+ Image img = canvas.createImage(new MemoryImageSource(width, height, pix, 0, width));
+
+ return img;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BarcodeEANSUPP.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BarcodeEANSUPP.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BarcodeEANSUPP.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BarcodeEANSUPP.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+import pdftk.com.lowagie.text.Rectangle;
+import java.awt.Color;
+
+/** This class takes 2 barcodes, an EAN/UPC and a supplemental
+ * and creates a single barcode with both combined in the
+ * expected layout. The UPC/EAN should have a positive text
+ * baseline and the supplemental a negative one (in the supplemental
+ * the text is on the top of the barcode.
+ * The default parameters are:
+ *
+ *n = 8; // horizontal distance between the two barcodes
+ *
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class BarcodeEANSUPP extends Barcode{
+
+ /** The barcode with the EAN/UPC.
+ */
+ protected Barcode ean;
+ /** The barcode with the supplemental.
+ */
+ protected Barcode supp;
+
+ /** Creates new combined barcode.
+ * @param ean the EAN/UPC barcode
+ * @param supp the supplemental barcode
+ */
+ public BarcodeEANSUPP(Barcode ean, Barcode supp) {
+ n = 8; // horizontal distance between the two barcodes
+ this.ean = ean;
+ this.supp = supp;
+ }
+
+ /** Gets the maximum area that the barcode and the text, if
+ * any, will occupy. The lower left corner is always (0, 0).
+ * @return the size the barcode occupies.
+ */
+ public Rectangle getBarcodeSize() {
+ Rectangle rect = ean.getBarcodeSize();
+ rect.setRight(rect.width() + supp.getBarcodeSize().width() + n);
+ return rect;
+ }
+
+ /** Places the barcode in a PdfContentByte
. The
+ * barcode is always placed at coodinates (0, 0). Use the
+ * translation matrix to move it elsewhere.
+ * The bars and text are written in the following colors:
+ *
+ *
+ * barColor
+ * textColor
+ * Result
+ *
+ *
+ * null
+ * null
+ * bars and text painted with current fill color
+ *
+ *
+ * barColor
+ * null
+ * bars and text painted with barColor
+ *
+ *
+ * null
+ * textColor
+ * bars painted with current color text painted with textColor
+ *
+ *
+ * barColor
+ * textColor
+ * bars painted with barColor
text painted with textColor
+ *
+ *
+ * @param cb the PdfContentByte
where the barcode will be placed
+ * @param barColor the color of the bars. It can be null
+ * @param textColor the color of the text. It can be null
+ * @return the dimensions the barcode occupies
+ */
+ public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
+ if (supp.getFont() != null)
+ supp.setBarHeight(ean.getBarHeight() + supp.getBaseline() - supp.getFont().getFontDescriptor(BaseFont.CAPHEIGHT, supp.getSize()));
+ else
+ supp.setBarHeight(ean.getBarHeight());
+ Rectangle eanR = ean.getBarcodeSize();
+ cb.saveState();
+ ean.placeBarcode(cb, barColor, textColor);
+ cb.restoreState();
+ cb.saveState();
+ cb.concatCTM(1, 0, 0, 1, eanR.width() + n, eanR.height() - ean.getBarHeight());
+ supp.placeBarcode(cb, barColor, textColor);
+ cb.restoreState();
+ return getBarcodeSize();
+ }
+
+ /** Creates a java.awt.Image
. This image only
+ * contains the bars without any text.
+ * @param foreground the color of the bars
+ * @param background the color of the background
+ * @return the image
+ */
+ public java.awt.Image createAwtImage(Color foreground, Color background) {
+ throw new UnsupportedOperationException("The two barcodes must be composed externally.");
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BarcodeInter25.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BarcodeInter25.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BarcodeInter25.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BarcodeInter25.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.ExceptionConverter;
+import pdftk.com.lowagie.text.Element;
+import pdftk.com.lowagie.text.Rectangle;
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.Canvas;
+import java.awt.image.MemoryImageSource;
+
+/** Implements the code interleaved 2 of 5. The text can include
+ * non numeric characters that are printed but do not generate bars.
+ * The default parameters are:
+ *
+ *x = 0.8f;
+ *n = 2;
+ *font = BaseFont.createFont("Helvetica", "winansi", false);
+ *size = 8;
+ *baseline = size;
+ *barHeight = size * 3;
+ *textAlignment = Element.ALIGN_CENTER;
+ *generateChecksum = false;
+ *checksumText = false;
+ *
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class BarcodeInter25 extends Barcode{
+
+ /** The bars to generate the code.
+ */
+ static byte BARS[][] =
+ {
+ {0,0,1,1,0},
+ {1,0,0,0,1},
+ {0,1,0,0,1},
+ {1,1,0,0,0},
+ {0,0,1,0,1},
+ {1,0,1,0,0},
+ {0,1,1,0,0},
+ {0,0,0,1,1},
+ {1,0,0,1,0},
+ {0,1,0,1,0}
+ };
+
+ /** Creates new BarcodeInter25 */
+ public BarcodeInter25() {
+ try {
+ x = 0.8f;
+ n = 2;
+ font = BaseFont.createFont("Helvetica", "winansi", false);
+ size = 8;
+ baseline = size;
+ barHeight = size * 3;
+ textAlignment = Element.ALIGN_CENTER;
+ generateChecksum = false;
+ checksumText = false;
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /** Deletes all the non numeric characters from text
.
+ * @param text the text
+ * @return a String
with only numeric characters
+ */
+ public static String keepNumbers(String text) {
+ StringBuffer sb = new StringBuffer();
+ for (int k = 0; k < text.length(); ++k) {
+ char c = text.charAt(k);
+ if (c >= '0' && c <= '9')
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ /** Calculates the checksum.
+ * @param text the numeric text
+ * @return the checksum
+ */
+ public static char getChecksum(String text) {
+ int mul = 3;
+ int total = 0;
+ for (int k = text.length() - 1; k >= 0; --k) {
+ int n = text.charAt(k) - '0';
+ total += mul * n;
+ mul ^= 2;
+ }
+ return (char)(((10 - (total % 10)) % 10) + '0');
+ }
+
+ /** Creates the bars for the barcode.
+ * @param text the text. It can contain non numeric characters
+ * @return the barcode
+ */
+ public static byte[] getBarsInter25(String text) {
+ text = keepNumbers(text);
+ if ((text.length() & 1) != 0)
+ throw new IllegalArgumentException("The text length must be even.");
+ byte bars[] = new byte[text.length() * 5 + 7];
+ int pb = 0;
+ bars[pb++] = 0;
+ bars[pb++] = 0;
+ bars[pb++] = 0;
+ bars[pb++] = 0;
+ int len = text.length() / 2;
+ for (int k = 0; k < len; ++k) {
+ int c1 = text.charAt(k * 2) - '0';
+ int c2 = text.charAt(k * 2 + 1) - '0';
+ byte b1[] = BARS[c1];
+ byte b2[] = BARS[c2];
+ for (int j = 0; j < 5; ++j) {
+ bars[pb++] = b1[j];
+ bars[pb++] = b2[j];
+ }
+ }
+ bars[pb++] = 1;
+ bars[pb++] = 0;
+ bars[pb++] = 0;
+ return bars;
+ }
+
+ /** Gets the maximum area that the barcode and the text, if
+ * any, will occupy. The lower left corner is always (0, 0).
+ * @return the size the barcode occupies.
+ */
+ public Rectangle getBarcodeSize() {
+ float fontX = 0;
+ float fontY = 0;
+ if (font != null) {
+ if (baseline > 0)
+ fontY = baseline - font.getFontDescriptor(BaseFont.DESCENT, size);
+ else
+ fontY = -baseline + size;
+ String fullCode = code;
+ if (generateChecksum && checksumText)
+ fullCode += getChecksum(fullCode);
+ fontX = font.getWidthPoint(fullCode, size);
+ }
+ String fullCode = keepNumbers(code);
+ int len = fullCode.length();
+ if (generateChecksum)
+ ++len;
+ float fullWidth = len * (3 * x + 2 * x * n) + (6 + n ) * x;
+ fullWidth = Math.max(fullWidth, fontX);
+ float fullHeight = barHeight + fontY;
+ return new Rectangle(fullWidth, fullHeight);
+ }
+
+ /** Places the barcode in a PdfContentByte
. The
+ * barcode is always placed at coodinates (0, 0). Use the
+ * translation matrix to move it elsewhere.
+ * The bars and text are written in the following colors:
+ *
+ *
+ * barColor
+ * textColor
+ * Result
+ *
+ *
+ * null
+ * null
+ * bars and text painted with current fill color
+ *
+ *
+ * barColor
+ * null
+ * bars and text painted with barColor
+ *
+ *
+ * null
+ * textColor
+ * bars painted with current color text painted with textColor
+ *
+ *
+ * barColor
+ * textColor
+ * bars painted with barColor
text painted with textColor
+ *
+ *
+ * @param cb the PdfContentByte
where the barcode will be placed
+ * @param barColor the color of the bars. It can be null
+ * @param textColor the color of the text. It can be null
+ * @return the dimensions the barcode occupies
+ */
+ public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
+ String fullCode = code;
+ float fontX = 0;
+ if (font != null) {
+ if (generateChecksum && checksumText)
+ fullCode += getChecksum(fullCode);
+ fontX = font.getWidthPoint(fullCode, size);
+ }
+ String bCode = keepNumbers(code);
+ if (generateChecksum)
+ bCode += getChecksum(bCode);
+ int len = bCode.length();
+ float fullWidth = len * (3 * x + 2 * x * n) + (6 + n ) * x;
+ float barStartX = 0;
+ float textStartX = 0;
+ switch (textAlignment) {
+ case Element.ALIGN_LEFT:
+ break;
+ case Element.ALIGN_RIGHT:
+ if (fontX > fullWidth)
+ barStartX = fontX - fullWidth;
+ else
+ textStartX = fullWidth - fontX;
+ break;
+ default:
+ if (fontX > fullWidth)
+ barStartX = (fontX - fullWidth) / 2;
+ else
+ textStartX = (fullWidth - fontX) / 2;
+ break;
+ }
+ float barStartY = 0;
+ float textStartY = 0;
+ if (font != null) {
+ if (baseline <= 0)
+ textStartY = barHeight - baseline;
+ else {
+ textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size);
+ barStartY = textStartY + baseline;
+ }
+ }
+ byte bars[] = getBarsInter25(bCode);
+ boolean print = true;
+ if (barColor != null)
+ cb.setColorFill(barColor);
+ for (int k = 0; k < bars.length; ++k) {
+ float w = (bars[k] == 0 ? x : x * n);
+ if (print)
+ cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight);
+ print = !print;
+ barStartX += w;
+ }
+ cb.fill();
+ if (font != null) {
+ if (textColor != null)
+ cb.setColorFill(textColor);
+ cb.beginText();
+ cb.setFontAndSize(font, size);
+ cb.setTextMatrix(textStartX, textStartY);
+ cb.showText(fullCode);
+ cb.endText();
+ }
+ return getBarcodeSize();
+ }
+
+ /** Creates a java.awt.Image
. This image only
+ * contains the bars without any text.
+ * @param foreground the color of the bars
+ * @param background the color of the background
+ * @return the image
+ */
+ public java.awt.Image createAwtImage(Color foreground, Color background) {
+ int f = foreground.getRGB();
+ int g = background.getRGB();
+ Canvas canvas = new Canvas();
+
+ String bCode = keepNumbers(code);
+ if (generateChecksum)
+ bCode += getChecksum(bCode);
+ int len = bCode.length();
+ int nn = (int)n;
+ int fullWidth = len * (3 + 2 * nn) + (6 + nn );
+ byte bars[] = getBarsInter25(bCode);
+ boolean print = true;
+ int ptr = 0;
+ int height = (int)barHeight;
+ int pix[] = new int[fullWidth * height];
+ for (int k = 0; k < bars.length; ++k) {
+ int w = (bars[k] == 0 ? 1 : nn);
+ int c = g;
+ if (print)
+ c = f;
+ print = !print;
+ for (int j = 0; j < w; ++j)
+ pix[ptr++] = c;
+ }
+ for (int k = fullWidth; k < pix.length; k += fullWidth) {
+ System.arraycopy(pix, 0, pix, k, fullWidth);
+ }
+ Image img = canvas.createImage(new MemoryImageSource(fullWidth, height, pix, 0, fullWidth));
+
+ return img;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BarcodePDF417.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BarcodePDF417.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BarcodePDF417.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BarcodePDF417.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,1588 @@
+/*
+ *
+ * Copyright 2003 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+// import pdftk.com.lowagie.text.Image; ssteward: dropped in 1.44
+// import pdftk.com.lowagie.text.BadElementException;
+import java.util.ArrayList;
+// import pdftk.com.lowagie.text.pdf.codec.CCITTG4Encoder; ssteward: dropped in 1.44
+import java.awt.Color;
+import java.awt.Canvas;
+import java.awt.image.MemoryImageSource;
+
+/** Generates the 2D barcode PDF417. Supports dimensioning auto-sizing, fixed
+ * and variable sizes, automatic and manual error levels, raw codeword input,
+ * codeword size optimization and bitmap inversion. The output can
+ * be a CCITT G4 Image
or a raw bitmap.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class BarcodePDF417 {
+
+ /** Auto-size is made based on aspectRatio
and yHeight
. */
+ public static final int PDF417_USE_ASPECT_RATIO = 0;
+ /** The size of the barcode will be at least codeColumns*codeRows
. */
+ public static final int PDF417_FIXED_RECTANGLE = 1;
+ /** The size will be at least codeColumns
+ * with a variable number of codeRows
.
+ */
+ public static final int PDF417_FIXED_COLUMNS = 2;
+ /** The size will be at least codeRows
+ * with a variable number of codeColumns
.
+ */
+ public static final int PDF417_FIXED_ROWS = 4;
+ /** The error level correction is set automatically according
+ * to ISO 15438 recomendations.
+ */
+ public static final int PDF417_AUTO_ERROR_LEVEL = 0;
+ /** The error level correction is set by the user. It can be 0 to 8. */
+ public static final int PDF417_USE_ERROR_LEVEL = 16;
+ /** No text
interpretation is done and the content of codewords
+ * is used directly.
+ */
+ public static final int PDF417_USE_RAW_CODEWORDS = 64;
+ /** Inverts the output bits of the raw bitmap that is normally
+ * bit one for black. It has only effect for the raw bitmap.
+ */
+ public static final int PDF417_INVERT_BITMAP = 128;
+ /** Use Macro PDF417 Encoding
+ * @see #setMacroFileId(String)
+ * @see #setMacroSegmentId(int)
+ * @see #setMacroSegmentCount(int)
+ */
+ public static final int PDF417_USE_MACRO = 256;
+
+
+ private int macroSegmentCount=0;
+ private int macroSegmentId=-1;
+ private String macroFileId;
+ protected int bitPtr;
+ protected int cwPtr;
+ protected SegmentList segmentList;
+
+ /** Creates a new BarcodePDF417
with the default settings. */
+ public BarcodePDF417() {
+ setDefaultParameters();
+ }
+
+ /**
+ * Sets the segment id for macro PDF417 encoding
+ * @param id the id (starting at 0)
+ * @see #setMacroSegmentCount(int)
+ */
+ public void setMacroSegmentId(int id) {
+ this.macroSegmentId = id;
+ }
+
+ /**
+ * Sets the segment count for macro PDF417 encoding
+ * @param cnt the number of macro segments
+ * @see #setMacroSegmentId(int)
+ */
+ public void setMacroSegmentCount(int cnt) {
+ this.macroSegmentCount = cnt;
+ }
+
+ /**
+ * Sets the File ID for macro PDF417 encoding
+ * @param id the file id
+ */
+ public void setMacroFileId(String id) {
+ this.macroFileId = id;
+ }
+
+ protected boolean checkSegmentType(Segment segment, char type) {
+ if (segment == null)
+ return false;
+ return segment.type == type;
+ }
+
+ protected int getSegmentLength(Segment segment) {
+ if (segment == null)
+ return 0;
+ return segment.end - segment.start;
+ }
+
+ /** Set the default settings that correspond to PDF417_USE_ASPECT_RATIO
+ * and PDF417_AUTO_ERROR_LEVEL
.
+ */
+ public void setDefaultParameters() {
+ options = 0;
+ outBits = null;
+ text = new byte[0];
+ yHeight = 3;
+ aspectRatio = 0.5f;
+ }
+
+ protected void outCodeword17(int codeword) {
+ int bytePtr = bitPtr / 8;
+ int bit = bitPtr - bytePtr * 8;
+ outBits[bytePtr++] |= codeword >> (9 + bit);
+ outBits[bytePtr++] |= codeword >> (1 + bit);
+ codeword <<= 8;
+ outBits[bytePtr] |= codeword >> (1 + bit);
+ bitPtr += 17;
+ }
+
+ protected void outCodeword18(int codeword) {
+ int bytePtr = bitPtr / 8;
+ int bit = bitPtr - bytePtr * 8;
+ outBits[bytePtr++] |= codeword >> (10 + bit);
+ outBits[bytePtr++] |= codeword >> (2 + bit);
+ codeword <<= 8;
+ outBits[bytePtr] |= codeword >> (2 + bit);
+ if (bit == 7)
+ outBits[++bytePtr] |= 0x80;
+ bitPtr += 18;
+ }
+
+ protected void outCodeword(int codeword) {
+ outCodeword17(codeword);
+ }
+
+ protected void outStopPattern() {
+ outCodeword18(STOP_PATTERN);
+ }
+
+ protected void outStartPattern() {
+ outCodeword17(START_PATTERN);
+ }
+
+ protected void outPaintCode() {
+ int codePtr = 0;
+ bitColumns = START_CODE_SIZE * (codeColumns + 3) + STOP_SIZE;
+ int lenBits = ((bitColumns - 1) / 8 + 1) * codeRows;
+ outBits = new byte[lenBits];
+ for (int row = 0; row < codeRows; ++row) {
+ bitPtr = ((bitColumns - 1) / 8 + 1) * 8 * row;
+ int rowMod = row % 3;
+ int cluster[] = CLUSTERS[rowMod];
+ outStartPattern();
+ int edge = 0;
+ switch (rowMod) {
+ case 0:
+ edge = 30 * (row / 3) + ((codeRows - 1) / 3);
+ break;
+ case 1:
+ edge = 30 * (row / 3) + errorLevel * 3 + ((codeRows - 1) % 3);
+ break;
+ default:
+ edge = 30 * (row / 3) + codeColumns - 1;
+ break;
+ }
+ outCodeword(cluster[edge]);
+
+ for (int column = 0; column < codeColumns; ++column) {
+ outCodeword(cluster[codewords[codePtr++]]);
+ }
+
+ switch (rowMod) {
+ case 0:
+ edge = 30 * (row / 3) + codeColumns - 1;
+ break;
+ case 1:
+ edge = 30 * (row / 3) + ((codeRows - 1) / 3);
+ break;
+ default:
+ edge = 30 * (row / 3) + errorLevel * 3 + ((codeRows - 1) % 3);
+ break;
+ }
+ outCodeword(cluster[edge]);
+ outStopPattern();
+ }
+ if ((options & PDF417_INVERT_BITMAP) != 0) {
+ for (int k = 0; k < outBits.length; ++k)
+ outBits[k] ^= 0xff;
+ }
+ }
+
+ protected void calculateErrorCorrection(int dest) {
+ if (errorLevel < 0 || errorLevel > 8)
+ errorLevel = 0;
+ int A[] = ERROR_LEVEL[errorLevel];
+ int Alength = 2 << errorLevel;
+ for (int k = 0; k < Alength; ++k)
+ codewords[dest + k] = 0;
+ int lastE = Alength - 1;
+ for (int k = 0; k < lenCodewords; ++k) {
+ int t1 = codewords[k] + codewords[dest];
+ for (int e = 0; e <= lastE; ++e) {
+ int t2 = (t1 * A[lastE - e]) % MOD;
+ int t3 = MOD - t2;
+ codewords[dest + e] = ((e == lastE ? 0 : codewords[dest + e + 1]) + t3) % MOD;
+ }
+ }
+ for (int k = 0; k < Alength; ++k)
+ codewords[dest + k] = (MOD - codewords[dest + k]) % MOD;
+ }
+
+ private static int getTextTypeAndValue(byte[] input, int maxLength, int idx) {
+ if (idx >= maxLength)
+ return 0;
+ char c = (char)(input[idx] & 0xff);
+ if (c >= 'A' && c <= 'Z')
+ return (ALPHA + c - 'A');
+ if (c >= 'a' && c <= 'z')
+ return (LOWER + c - 'a');
+ if (c == ' ')
+ return (ALPHA + LOWER + MIXED + SPACE);
+ int ms = MIXED_SET.indexOf(c);
+ int ps = PUNCTUATION_SET.indexOf(c);
+ if (ms < 0 && ps < 0)
+ return (ISBYTE + c);
+ if (ms == ps)
+ return (MIXED + PUNCTUATION + ms);
+ if (ms >= 0)
+ return (MIXED + ms);
+ return (PUNCTUATION + ps);
+ }
+
+ protected int getTextTypeAndValue(int maxLength, int idx) {
+ return getTextTypeAndValue(text, maxLength,idx);
+ }
+
+ private void textCompaction(byte[] input, int start, int length) {
+ int dest[] = new int[ABSOLUTE_MAX_TEXT_SIZE * 2];
+ int mode = ALPHA;
+ int ptr = 0;
+ int fullBytes = 0;
+ int v = 0;
+ int k;
+ int size;
+ length += start;
+ for (k = start; k < length; ++k) {
+ v = getTextTypeAndValue(input, length, k);
+ if ((v & mode) != 0) {
+ dest[ptr++] = v & 0xff;
+ continue;
+ }
+ if ((v & ISBYTE) != 0) {
+ if ((ptr & 1) != 0) {
+ dest[ptr++] = (mode & PUNCTUATION) != 0 ? PAL : PS;
+ mode = (mode & PUNCTUATION) != 0 ? ALPHA : mode;
+ }
+ dest[ptr++] = BYTESHIFT;
+ dest[ptr++] = v & 0xff;
+ fullBytes += 2;
+ continue;
+ }
+ switch (mode) {
+ case ALPHA:
+ if ((v & LOWER) != 0) {
+ dest[ptr++] = LL;
+ dest[ptr++] = v & 0xff;
+ mode = LOWER;
+ }
+ else if ((v & MIXED) != 0) {
+ dest[ptr++] = ML;
+ dest[ptr++] = v & 0xff;
+ mode = MIXED;
+ }
+ else if ((getTextTypeAndValue(input, length, k + 1) & getTextTypeAndValue(input, length, k + 2) & PUNCTUATION) != 0) {
+ dest[ptr++] = ML;
+ dest[ptr++] = PL;
+ dest[ptr++] = v & 0xff;
+ mode = PUNCTUATION;
+ }
+ else {
+ dest[ptr++] = PS;
+ dest[ptr++] = v & 0xff;
+ }
+ break;
+ case LOWER:
+ if ((v & ALPHA) != 0) {
+ if ((getTextTypeAndValue(input, length, k + 1) & getTextTypeAndValue(input, length, k + 2) & ALPHA) != 0) {
+ dest[ptr++] = ML;
+ dest[ptr++] = AL;
+ mode = ALPHA;
+ }
+ else {
+ dest[ptr++] = AS;
+ }
+ dest[ptr++] = v & 0xff;
+ }
+ else if ((v & MIXED) != 0) {
+ dest[ptr++] = ML;
+ dest[ptr++] = v & 0xff;
+ mode = MIXED;
+ }
+ else if ((getTextTypeAndValue(input, length, k + 1) & getTextTypeAndValue(input, length, k + 2) & PUNCTUATION) != 0) {
+ dest[ptr++] = ML;
+ dest[ptr++] = PL;
+ dest[ptr++] = v & 0xff;
+ mode = PUNCTUATION;
+ }
+ else {
+ dest[ptr++] = PS;
+ dest[ptr++] = v & 0xff;
+ }
+ break;
+ case MIXED:
+ if ((v & LOWER) != 0) {
+ dest[ptr++] = LL;
+ dest[ptr++] = v & 0xff;
+ mode = LOWER;
+ }
+ else if ((v & ALPHA) != 0) {
+ dest[ptr++] = AL;
+ dest[ptr++] = v & 0xff;
+ mode = ALPHA;
+ }
+ else if ((getTextTypeAndValue(input, length, k + 1) & getTextTypeAndValue(input, length, k + 2) & PUNCTUATION) != 0) {
+ dest[ptr++] = PL;
+ dest[ptr++] = v & 0xff;
+ mode = PUNCTUATION;
+ }
+ else {
+ dest[ptr++] = PS;
+ dest[ptr++] = v & 0xff;
+ }
+ break;
+ case PUNCTUATION:
+ dest[ptr++] = PAL;
+ mode = ALPHA;
+ --k;
+ break;
+ }
+ }
+ if ((ptr & 1) != 0)
+ dest[ptr++] = PS;
+ size = (ptr + fullBytes) / 2;
+ if (size + cwPtr > MAX_DATA_CODEWORDS) {
+ throw new IndexOutOfBoundsException("The text is too big.");
+ }
+ length = ptr;
+ ptr = 0;
+ while (ptr < length) {
+ v = dest[ptr++];
+ if (v >= 30) {
+ codewords[cwPtr++] = v;
+ codewords[cwPtr++] = dest[ptr++];
+ }
+ else
+ codewords[cwPtr++] = v * 30 + dest[ptr++];
+ }
+ }
+ protected void textCompaction(int start, int length) {
+ textCompaction(text, start, length);
+ }
+
+ protected void basicNumberCompaction(int start, int length) {
+ basicNumberCompaction(text, start, length);
+ }
+
+ private void basicNumberCompaction(byte[] input, int start, int length) {
+ int ret = cwPtr;
+ int retLast = length / 3;
+ int ni, k;
+ cwPtr += retLast + 1;
+ for (k = 0; k <= retLast; ++k)
+ codewords[ret + k] = 0;
+ codewords[ret + retLast] = 1;
+ length += start;
+ for (ni = start; ni < length; ++ni) {
+ // multiply by 10
+ for (k = retLast; k >= 0; --k)
+ codewords[ret + k] *= 10;
+ // add the digit
+ codewords[ret + retLast] += input[ni] - '0';
+ // propagate carry
+ for (k = retLast; k > 0; --k) {
+ codewords[ret + k - 1] += codewords[ret + k] / 900;
+ codewords[ret + k] %= 900;
+ }
+ }
+ }
+
+ private void numberCompaction(byte[] input, int start, int length) {
+ int full = (length / 44) * 15;
+ int size = length % 44;
+ int k;
+ if (size == 0)
+ size = full;
+ else
+ size = full + size / 3 + 1;
+ if (size + cwPtr > MAX_DATA_CODEWORDS) {
+ throw new IndexOutOfBoundsException("The text is too big.");
+ }
+ length += start;
+ for (k = start; k < length; k += 44) {
+ size = length - k < 44 ? length - k : 44;
+ basicNumberCompaction(input, k, size);
+ }
+ }
+
+ protected void numberCompaction(int start, int length) {
+ numberCompaction(text, start, length);
+ }
+
+ protected void byteCompaction6(int start) {
+ int length = 6;
+ int ret = cwPtr;
+ int retLast = 4;
+ int ni, k;
+ cwPtr += retLast + 1;
+ for (k = 0; k <= retLast ; ++k)
+ codewords[ret + k] = 0;
+ length += start;
+ for (ni = start; ni < length; ++ni) {
+ // multiply by 256
+ for (k = retLast; k >= 0; --k)
+ codewords[ret + k] *= 256;
+ // add the digit
+ codewords[ret + retLast] += (int)text[ni] & 0xff;
+ // propagate carry
+ for (k = retLast; k > 0; --k) {
+ codewords[ret + k - 1] += codewords[ret + k] / 900;
+ codewords[ret + k] %= 900;
+ }
+ }
+ }
+
+ void byteCompaction(int start, int length) {
+ int k, j;
+ int size = (length / 6) * 5 + (length % 6);
+ if (size + cwPtr > MAX_DATA_CODEWORDS) {
+ throw new IndexOutOfBoundsException("The text is too big.");
+ }
+ length += start;
+ for (k = start; k < length; k += 6) {
+ size = length - k < 44 ? length - k : 6;
+ if (size < 6) {
+ for (j = 0; j < size; ++j)
+ codewords[cwPtr++] = (int)text[k + j] & 0xff;
+ }
+ else {
+ byteCompaction6(k);
+ }
+ }
+ }
+
+ void breakString() {
+ int textLength = text.length;
+ int lastP = 0;
+ int startN = 0;
+ int nd = 0;
+ char c = 0;
+ int k, j;
+ boolean lastTxt, txt;
+ Segment v;
+ Segment vp;
+ Segment vn;
+ for (k = 0; k < textLength; ++k) {
+ c = (char)(text[k] & 0xff);
+ if (c >= '0' && c <= '9') {
+ if (nd == 0)
+ startN = k;
+ ++nd;
+ continue;
+ }
+ if (nd >= 13) {
+ if (lastP != startN) {
+ c = (char)(text[lastP] & 0xff);
+ // ptrS = lastP;
+ lastTxt = (c >= ' ' && c < 127) || c == '\r' || c == '\n' || c == '\t';
+ for (j = lastP; j < startN; ++j) {
+ c = (char)(text[j] & 0xff);
+ txt = (c >= ' ' && c < 127) || c == '\r' || c == '\n' || c == '\t';
+ if (txt != lastTxt) {
+ segmentList.add(lastTxt ? 'T' : 'B', lastP, j);
+ lastP = j;
+ lastTxt = txt;
+ }
+ }
+ segmentList.add(lastTxt ? 'T' : 'B', lastP, startN);
+ }
+ segmentList.add('N', startN, k);
+ lastP = k;
+ }
+ nd = 0;
+ }
+ if (nd < 13)
+ startN = textLength;
+ if (lastP != startN) {
+ c = (char)(text[lastP] & 0xff);
+ // ptrS = lastP;
+ lastTxt = (c >= ' ' && c < 127) || c == '\r' || c == '\n' || c == '\t';
+ for (j = lastP; j < startN; ++j) {
+ c = (char)(text[j] & 0xff);
+ txt = (c >= ' ' && c < 127) || c == '\r' || c == '\n' || c == '\t';
+ if (txt != lastTxt) {
+ segmentList.add(lastTxt ? 'T' : 'B', lastP, j);
+ lastP = j;
+ lastTxt = txt;
+ }
+ }
+ segmentList.add(lastTxt ? 'T' : 'B', lastP, startN);
+ }
+ if (nd >= 13)
+ segmentList.add('N', startN, textLength);
+ //optimize
+ //merge short binary
+ for (k = 0; k < segmentList.size(); ++k) {
+ v = segmentList.get(k);
+ vp = segmentList.get(k - 1);
+ vn = segmentList.get(k + 1);;
+ if (checkSegmentType(v, 'B') && getSegmentLength(v) == 1) {
+ if (checkSegmentType(vp, 'T') && checkSegmentType(vn, 'T')
+ && getSegmentLength(vp) + getSegmentLength(vn) >= 3) {
+ vp.end = vn.end;
+ segmentList.remove(k);
+ segmentList.remove(k);
+ k = -1;
+ continue;
+ }
+ }
+ }
+ //merge text sections
+ for (k = 0; k < segmentList.size(); ++k) {
+ v = segmentList.get(k);
+ vp = segmentList.get(k - 1);
+ vn = segmentList.get(k + 1);;
+ if (checkSegmentType(v, 'T') && getSegmentLength(v) >= 5) {
+ boolean redo = false;
+ if ((checkSegmentType(vp, 'B') && getSegmentLength(vp) == 1) || checkSegmentType(vp, 'T')) {
+ redo = true;
+ v.start = vp.start;
+ segmentList.remove(k - 1);
+ --k;
+ }
+ if ((checkSegmentType(vn, 'B') && getSegmentLength(vn) == 1) || checkSegmentType(vn, 'T')) {
+ redo = true;
+ v.end = vn.end;
+ segmentList.remove(k + 1);
+ }
+ if (redo) {
+ k = -1;
+ continue;
+ }
+ }
+ }
+ //merge binary sections
+ for (k = 0; k < segmentList.size(); ++k) {
+ v = segmentList.get(k);
+ vp = segmentList.get(k - 1);
+ vn = segmentList.get(k + 1);;
+ if (checkSegmentType(v, 'B')) {
+ boolean redo = false;
+ if ((checkSegmentType(vp, 'T') && getSegmentLength(vp) < 5) || checkSegmentType(vp, 'B')) {
+ redo = true;
+ v.start = vp.start;
+ segmentList.remove(k - 1);
+ --k;
+ }
+ if ((checkSegmentType(vn, 'T') && getSegmentLength(vn) < 5) || checkSegmentType(vn, 'B')) {
+ redo = true;
+ v.end = vn.end;
+ segmentList.remove(k + 1);
+ }
+ if (redo) {
+ k = -1;
+ continue;
+ }
+ }
+ }
+ // check if all numbers
+ if (segmentList.size() == 1 && (v = segmentList.get(0)).type == 'T' && getSegmentLength(v) >= 8) {
+ for (k = v.start; k < v.end; ++k) {
+ c = (char)(text[k] & 0xff);
+ if (c < '0' || c > '9')
+ break;
+ }
+ if (k == v.end)
+ v.type = 'N';
+ }
+ }
+
+ protected void assemble() {
+ int k;
+ if (segmentList.size() == 0)
+ return;
+ cwPtr = 1;
+ for (k = 0; k < segmentList.size(); ++k) {
+ Segment v = segmentList.get(k);
+ switch (v.type) {
+ case 'T':
+ if (k != 0)
+ codewords[cwPtr++] = TEXT_MODE;
+ textCompaction(v.start, getSegmentLength(v));
+ break;
+ case 'N':
+ codewords[cwPtr++] = NUMERIC_MODE;
+ numberCompaction(v.start, getSegmentLength(v));
+ break;
+ case 'B':
+ codewords[cwPtr++] = (getSegmentLength(v) % 6) != 0 ? BYTE_MODE : BYTE_MODE_6;
+ byteCompaction(v.start, getSegmentLength(v));
+ break;
+ }
+ }
+
+ if ((options & PDF417_USE_MACRO) != 0) {
+ macroCodes();
+ }
+
+ }
+
+ private void macroCodes() {
+ if (macroSegmentId < 0) {
+ throw new IllegalStateException("macroSegmentId must be >=0");
+ }
+ if (macroSegmentId >= macroSegmentCount) {
+ throw new IllegalStateException("macroSegmentId must be < macroSemgentCount");
+ }
+ if (macroSegmentCount < 1) {
+ throw new IllegalStateException("macroSemgentCount must be > 0");
+ }
+
+ codewords[cwPtr++] = MACRO_SEGMENT_ID;
+ append(macroSegmentId, 5);
+
+ if (macroFileId != null) {
+ append(macroFileId);
+ }
+
+ codewords[cwPtr++] = MACRO_SEGMENT_COUNT;
+ codewords[cwPtr++] = 1;
+ append(macroSegmentCount, 5);
+
+ if (macroSegmentId >= macroSegmentCount-1) {
+ codewords[cwPtr++] = MACRO_LAST_SEGMENT;
+ }
+
+ }
+
+ private void append(int in, int len) {
+ StringBuffer sb = new StringBuffer(len+1);
+ sb.append(Integer.toString(in));
+ for(int i = sb.length(); i < len; i++) {
+ sb.insert(0, "0");
+ }
+
+ byte[] bytes = PdfEncodings.convertToBytes(sb.toString(), "cp437");
+ numberCompaction(bytes, 0, bytes.length);
+ }
+
+ private void append(String s) {
+ byte[] bytes = PdfEncodings.convertToBytes(s, "cp437");
+ textCompaction(bytes, 0, bytes.length);
+ }
+
+
+ protected static int maxPossibleErrorLevel(int remain) {
+ int level = 8;
+ int size = 512;
+ while (level > 0) {
+ if (remain >= size)
+ return level;
+ --level;
+ size >>= 1;
+ }
+ return 0;
+ }
+
+ protected void dumpList() {
+ if (segmentList.size() == 0)
+ return;
+ for (int k = 0; k < segmentList.size(); ++k) {
+ Segment v = segmentList.get(k);
+ int len = getSegmentLength(v);
+ char c[] = new char[len];
+ for (int j = 0; j < len; ++j) {
+ c[j] = (char)(text[v.start + j] & 0xff);
+ if (c[j] == '\r')
+ c[j] = '\n';
+ }
+ System.out.println("" + v.type + new String(c));
+ }
+ }
+
+ protected int getMaxSquare() {
+ if (codeColumns > 21) {
+ codeColumns = 29;
+ codeRows = 32;
+ }
+ else {
+ codeColumns = 16;
+ codeRows = 58;
+ }
+ return MAX_DATA_CODEWORDS + 2;
+ }
+
+ /** Paints the barcode. If no exception was thrown a valid barcode is available. */
+ public void paintCode() {
+ int maxErr, lenErr, tot, pad;
+ if ((options & PDF417_USE_RAW_CODEWORDS) != 0) {
+ if (lenCodewords > MAX_DATA_CODEWORDS || lenCodewords < 1 || lenCodewords != codewords[0]) {
+ throw new IllegalArgumentException("Invalid codeword size.");
+ }
+ }
+ else {
+ if (text == null)
+ throw new NullPointerException("Text cannot be null.");
+ if (text.length > ABSOLUTE_MAX_TEXT_SIZE) {
+ throw new IndexOutOfBoundsException("The text is too big.");
+ }
+ segmentList = new SegmentList();
+ breakString();
+ //dumpList();
+ assemble();
+ segmentList = null;
+ codewords[0] = lenCodewords = cwPtr;
+ }
+ maxErr = maxPossibleErrorLevel(MAX_DATA_CODEWORDS + 2 - lenCodewords);
+ if ((options & PDF417_USE_ERROR_LEVEL) == 0) {
+ if (lenCodewords < 41)
+ errorLevel = 2;
+ else if (lenCodewords < 161)
+ errorLevel = 3;
+ else if (lenCodewords < 321)
+ errorLevel = 4;
+ else
+ errorLevel = 5;
+ }
+ if (errorLevel < 0)
+ errorLevel = 0;
+ else if (errorLevel > maxErr)
+ errorLevel = maxErr;
+ if (codeColumns < 1)
+ codeColumns = 1;
+ else if (codeColumns > 30)
+ codeColumns = 30;
+ if (codeRows < 3)
+ codeRows = 3;
+ else if (codeRows > 90)
+ codeRows = 90;
+ lenErr = 2 << errorLevel;
+ boolean fixedColumn = (options & PDF417_FIXED_ROWS) == 0;
+ boolean skipRowColAdjust = false;
+ tot = lenCodewords + lenErr;
+ if ((options & PDF417_FIXED_RECTANGLE) != 0) {
+ tot = codeColumns * codeRows;
+ if (tot > MAX_DATA_CODEWORDS + 2) {
+ tot = getMaxSquare();
+ }
+ if (tot < lenCodewords + lenErr)
+ tot = lenCodewords + lenErr;
+ else
+ skipRowColAdjust = true;
+ }
+ else if ((options & (PDF417_FIXED_COLUMNS | PDF417_FIXED_ROWS)) == 0) {
+ double c, b;
+ fixedColumn = true;
+ if (aspectRatio < 0.001)
+ aspectRatio = 0.001f;
+ else if (aspectRatio > 1000)
+ aspectRatio = 1000;
+ b = 73 * aspectRatio - 4;
+ c = (-b + Math.sqrt(b * b + 4 * 17 * aspectRatio * (lenCodewords + lenErr) * yHeight)) / (2 * 17 * aspectRatio);
+ codeColumns = (int)(c + 0.5);
+ if (codeColumns < 1)
+ codeColumns = 1;
+ else if (codeColumns > 30)
+ codeColumns = 30;
+ }
+ if (!skipRowColAdjust) {
+ if (fixedColumn) {
+ codeRows = (tot - 1) / codeColumns + 1;
+ if (codeRows < 3)
+ codeRows = 3;
+ else if (codeRows > 90) {
+ codeRows = 90;
+ codeColumns = (tot - 1) / 90 + 1;
+ }
+ }
+ else {
+ codeColumns = (tot - 1) / codeRows + 1;
+ if (codeColumns > 30) {
+ codeColumns = 30;
+ codeRows = (tot - 1) / 30 + 1;
+ }
+ }
+ tot = codeRows * codeColumns;
+ }
+ if (tot > MAX_DATA_CODEWORDS + 2) {
+ tot = getMaxSquare();
+ }
+ errorLevel = maxPossibleErrorLevel(tot - lenCodewords);
+ lenErr = 2 << errorLevel;
+ pad = tot - lenErr - lenCodewords;
+ cwPtr = lenCodewords;
+ while (pad-- != 0)
+ codewords[cwPtr++] = TEXT_MODE;
+ codewords[0] = lenCodewords = cwPtr;
+ calculateErrorCorrection(lenCodewords);
+ lenCodewords = tot;
+ outPaintCode();
+ }
+
+ /** Gets an Image
with the barcode. The image will have to be
+ * scaled in the Y direction by yHeight
for the barcode
+ * to have the right printing aspect.
+ * @return the barcode Image
+ * @throws BadElementException on error
+ */
+ /* ssteward: dropped in 1.44
+ public Image getImage() throws BadElementException {
+ paintCode();
+ byte g4[] = CCITTG4Encoder.compress(outBits, bitColumns, codeRows);
+ return Image.getInstance(bitColumns, codeRows, false, Image.CCITTG4, (options & PDF417_INVERT_BITMAP) == 0 ? 0 : Image.CCITT_BLACKIS1, g4, null);
+ }
+ */
+
+ /** Creates a java.awt.Image
.
+ * @param foreground the color of the bars
+ * @param background the color of the background
+ * @return the image
+ */
+ public java.awt.Image createAwtImage(Color foreground, Color background) {
+ int f = foreground.getRGB();
+ int g = background.getRGB();
+ Canvas canvas = new Canvas();
+
+ paintCode();
+ int h = (int)yHeight;
+ int pix[] = new int[bitColumns * codeRows * h];
+ int stride = (bitColumns + 7) / 8;
+ int ptr = 0;
+ for (int k = 0; k < codeRows; ++k) {
+ int p = k * stride;
+ for (int j = 0; j < bitColumns; ++j) {
+ int b = outBits[p + (j / 8)] & 0xff;
+ b <<= j % 8;
+ pix[ptr++] = (b & 0x80) == 0 ? g : f;
+ }
+ for (int j = 1; j < h; ++j) {
+ System.arraycopy(pix, ptr - bitColumns, pix, ptr + bitColumns * (j - 1), bitColumns);
+ }
+ ptr += bitColumns * (h - 1);
+ }
+
+ java.awt.Image img = canvas.createImage(new MemoryImageSource(bitColumns, codeRows * h, pix, 0, bitColumns));
+ return img;
+ }
+
+ /** Gets the raw image bits of the barcode. The image will have to
+ * be scaled in the Y direction by yHeight
.
+ * @return The raw barcode image
+ */
+ public byte[] getOutBits() {
+ return this.outBits;
+ }
+
+ /** Gets the number of X pixels of outBits
.
+ * @return the number of X pixels of outBits
+ */
+ public int getBitColumns() {
+ return this.bitColumns;
+ }
+
+ /** Gets the number of Y pixels of outBits
.
+ * It is also the number of rows in the barcode.
+ * @return the number of Y pixels of outBits
+ */
+ public int getCodeRows() {
+ return this.codeRows;
+ }
+
+ /** Sets the number of barcode rows. This number may be changed
+ * to keep the barcode valid.
+ * @param codeRows the number of barcode rows
+ */
+ public void setCodeRows(int codeRows) {
+ this.codeRows = codeRows;
+ }
+
+ /** Gets the number of barcode data columns.
+ * @return he number of barcode data columns
+ */
+ public int getCodeColumns() {
+ return this.codeColumns;
+ }
+
+ /** Sets the number of barcode data columns.
+ * This number may be changed to keep the barcode valid.
+ * @param codeColumns the number of barcode data columns
+ */
+ public void setCodeColumns(int codeColumns) {
+ this.codeColumns = codeColumns;
+ }
+
+ /** Gets the codeword array. This array is always 928 elements long.
+ * It can be writen to if the option PDF417_USE_RAW_CODEWORDS
+ * is set.
+ * @return the codeword array
+ */
+ public int[] getCodewords() {
+ return this.codewords;
+ }
+
+ /** Gets the length of the codewords.
+ * @return the length of the codewords
+ */
+ public int getLenCodewords() {
+ return this.lenCodewords;
+ }
+
+ /** Sets the length of the codewords.
+ * @param lenCodewords the length of the codewords
+ */
+ public void setLenCodewords(int lenCodewords) {
+ this.lenCodewords = lenCodewords;
+ }
+
+ /** Gets the error level correction used for the barcode. It may different
+ * from the previously set value.
+ * @return the error level correction used for the barcode
+ */
+ public int getErrorLevel() {
+ return this.errorLevel;
+ }
+
+ /** Sets the error level correction for the barcode.
+ * @param errorLevel the error level correction for the barcode
+ */
+ public void setErrorLevel(int errorLevel) {
+ this.errorLevel = errorLevel;
+ }
+
+ /** Gets the bytes that form the barcode. This bytes should
+ * be interpreted in the codepage Cp437.
+ * @return the bytes that form the barcode
+ */
+ public byte[] getText() {
+ return this.text;
+ }
+
+ /** Sets the bytes that form the barcode. This bytes should
+ * be interpreted in the codepage Cp437.
+ * @param text the bytes that form the barcode
+ */
+ public void setText(byte[] text) {
+ this.text = text;
+ }
+
+ /** Sets the text that will form the barcode. This text is converted
+ * to bytes using the encoding Cp437.
+ * @param s the text that will form the barcode
+ * @throws UnsupportedEncodingException if the encoding Cp437 is not supported
+ */
+ public void setText(String s) {
+ this.text = PdfEncodings.convertToBytes(s, "cp437");
+ }
+
+ /** Gets the options to generate the barcode.
+ * @return the options to generate the barcode
+ */
+ public int getOptions() {
+ return this.options;
+ }
+
+ /** Sets the options to generate the barcode. This can be all
+ * the PDF417_*
constants.
+ * @param options the options to generate the barcode
+ */
+ public void setOptions(int options) {
+ this.options = options;
+ }
+
+ /** Gets the barcode aspect ratio.
+ * @return the barcode aspect ratio
+ */
+ public float getAspectRatio() {
+ return this.aspectRatio;
+ }
+
+ /** Sets the barcode aspect ratio. A ratio or 0.5 will make the
+ * barcode width twice as large as the height.
+ * @param aspectRatio the barcode aspect ratio
+ */
+ public void setAspectRatio(float aspectRatio) {
+ this.aspectRatio = aspectRatio;
+ }
+
+ /** Gets the Y pixel height relative to X.
+ * @return the Y pixel height relative to X
+ */
+ public float getYHeight() {
+ return this.yHeight;
+ }
+
+ /** Sets the Y pixel height relative to X. It is usually 3.
+ * @param yHeight the Y pixel height relative to X
+ */
+ public void setYHeight(float yHeight) {
+ this.yHeight = yHeight;
+ }
+
+ protected static final int START_PATTERN = 0x1fea8;
+ protected static final int STOP_PATTERN = 0x3fa29;
+ protected static final int START_CODE_SIZE = 17;
+ protected static final int STOP_SIZE = 18;
+ protected static final int MOD = 929;
+ protected static final int ALPHA = 0x10000;
+ protected static final int LOWER = 0x20000;
+ protected static final int MIXED = 0x40000;
+ protected static final int PUNCTUATION = 0x80000;
+ protected static final int ISBYTE = 0x100000;
+ protected static final int BYTESHIFT = 913;
+ protected static final int PL = 25;
+ protected static final int LL = 27;
+ protected static final int AS = 27;
+ protected static final int ML = 28;
+ protected static final int AL = 28;
+ protected static final int PS = 29;
+ protected static final int PAL = 29;
+ protected static final int SPACE = 26;
+ protected static final int TEXT_MODE = 900;
+ protected static final int BYTE_MODE_6 = 924;
+ protected static final int BYTE_MODE = 901;
+ protected static final int NUMERIC_MODE = 902;
+ protected static final int ABSOLUTE_MAX_TEXT_SIZE = 5420;
+ protected static final int MAX_DATA_CODEWORDS = 926;
+ protected static final int MACRO_SEGMENT_ID=928;
+ protected static final int MACRO_SEGMENT_COUNT=923;
+ protected static final int MACRO_LAST_SEGMENT=922;
+
+ static String MIXED_SET = "0123456789&\r\t,:#-.$/+%*=^";
+ static String PUNCTUATION_SET = ";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'";
+
+ static int CLUSTERS[][] =
+ {{
+ 0x1d5c0, 0x1eaf0, 0x1f57c, 0x1d4e0, 0x1ea78, 0x1f53e, 0x1a8c0, 0x1d470,
+ 0x1a860, 0x15040, 0x1a830, 0x15020, 0x1adc0, 0x1d6f0, 0x1eb7c, 0x1ace0,
+ 0x1d678, 0x1eb3e, 0x158c0, 0x1ac70, 0x15860, 0x15dc0, 0x1aef0, 0x1d77c,
+ 0x15ce0, 0x1ae78, 0x1d73e, 0x15c70, 0x1ae3c, 0x15ef0, 0x1af7c, 0x15e78,
+ 0x1af3e, 0x15f7c, 0x1f5fa, 0x1d2e0, 0x1e978, 0x1f4be, 0x1a4c0, 0x1d270,
+ 0x1e93c, 0x1a460, 0x1d238, 0x14840, 0x1a430, 0x1d21c, 0x14820, 0x1a418,
+ 0x14810, 0x1a6e0, 0x1d378, 0x1e9be, 0x14cc0, 0x1a670, 0x1d33c, 0x14c60,
+ 0x1a638, 0x1d31e, 0x14c30, 0x1a61c, 0x14ee0, 0x1a778, 0x1d3be, 0x14e70,
+ 0x1a73c, 0x14e38, 0x1a71e, 0x14f78, 0x1a7be, 0x14f3c, 0x14f1e, 0x1a2c0,
+ 0x1d170, 0x1e8bc, 0x1a260, 0x1d138, 0x1e89e, 0x14440, 0x1a230, 0x1d11c,
+ 0x14420, 0x1a218, 0x14410, 0x14408, 0x146c0, 0x1a370, 0x1d1bc, 0x14660,
+ 0x1a338, 0x1d19e, 0x14630, 0x1a31c, 0x14618, 0x1460c, 0x14770, 0x1a3bc,
+ 0x14738, 0x1a39e, 0x1471c, 0x147bc, 0x1a160, 0x1d0b8, 0x1e85e, 0x14240,
+ 0x1a130, 0x1d09c, 0x14220, 0x1a118, 0x1d08e, 0x14210, 0x1a10c, 0x14208,
+ 0x1a106, 0x14360, 0x1a1b8, 0x1d0de, 0x14330, 0x1a19c, 0x14318, 0x1a18e,
+ 0x1430c, 0x14306, 0x1a1de, 0x1438e, 0x14140, 0x1a0b0, 0x1d05c, 0x14120,
+ 0x1a098, 0x1d04e, 0x14110, 0x1a08c, 0x14108, 0x1a086, 0x14104, 0x141b0,
+ 0x14198, 0x1418c, 0x140a0, 0x1d02e, 0x1a04c, 0x1a046, 0x14082, 0x1cae0,
+ 0x1e578, 0x1f2be, 0x194c0, 0x1ca70, 0x1e53c, 0x19460, 0x1ca38, 0x1e51e,
+ 0x12840, 0x19430, 0x12820, 0x196e0, 0x1cb78, 0x1e5be, 0x12cc0, 0x19670,
+ 0x1cb3c, 0x12c60, 0x19638, 0x12c30, 0x12c18, 0x12ee0, 0x19778, 0x1cbbe,
+ 0x12e70, 0x1973c, 0x12e38, 0x12e1c, 0x12f78, 0x197be, 0x12f3c, 0x12fbe,
+ 0x1dac0, 0x1ed70, 0x1f6bc, 0x1da60, 0x1ed38, 0x1f69e, 0x1b440, 0x1da30,
+ 0x1ed1c, 0x1b420, 0x1da18, 0x1ed0e, 0x1b410, 0x1da0c, 0x192c0, 0x1c970,
+ 0x1e4bc, 0x1b6c0, 0x19260, 0x1c938, 0x1e49e, 0x1b660, 0x1db38, 0x1ed9e,
+ 0x16c40, 0x12420, 0x19218, 0x1c90e, 0x16c20, 0x1b618, 0x16c10, 0x126c0,
+ 0x19370, 0x1c9bc, 0x16ec0, 0x12660, 0x19338, 0x1c99e, 0x16e60, 0x1b738,
+ 0x1db9e, 0x16e30, 0x12618, 0x16e18, 0x12770, 0x193bc, 0x16f70, 0x12738,
+ 0x1939e, 0x16f38, 0x1b79e, 0x16f1c, 0x127bc, 0x16fbc, 0x1279e, 0x16f9e,
+ 0x1d960, 0x1ecb8, 0x1f65e, 0x1b240, 0x1d930, 0x1ec9c, 0x1b220, 0x1d918,
+ 0x1ec8e, 0x1b210, 0x1d90c, 0x1b208, 0x1b204, 0x19160, 0x1c8b8, 0x1e45e,
+ 0x1b360, 0x19130, 0x1c89c, 0x16640, 0x12220, 0x1d99c, 0x1c88e, 0x16620,
+ 0x12210, 0x1910c, 0x16610, 0x1b30c, 0x19106, 0x12204, 0x12360, 0x191b8,
+ 0x1c8de, 0x16760, 0x12330, 0x1919c, 0x16730, 0x1b39c, 0x1918e, 0x16718,
+ 0x1230c, 0x12306, 0x123b8, 0x191de, 0x167b8, 0x1239c, 0x1679c, 0x1238e,
+ 0x1678e, 0x167de, 0x1b140, 0x1d8b0, 0x1ec5c, 0x1b120, 0x1d898, 0x1ec4e,
+ 0x1b110, 0x1d88c, 0x1b108, 0x1d886, 0x1b104, 0x1b102, 0x12140, 0x190b0,
+ 0x1c85c, 0x16340, 0x12120, 0x19098, 0x1c84e, 0x16320, 0x1b198, 0x1d8ce,
+ 0x16310, 0x12108, 0x19086, 0x16308, 0x1b186, 0x16304, 0x121b0, 0x190dc,
+ 0x163b0, 0x12198, 0x190ce, 0x16398, 0x1b1ce, 0x1638c, 0x12186, 0x16386,
+ 0x163dc, 0x163ce, 0x1b0a0, 0x1d858, 0x1ec2e, 0x1b090, 0x1d84c, 0x1b088,
+ 0x1d846, 0x1b084, 0x1b082, 0x120a0, 0x19058, 0x1c82e, 0x161a0, 0x12090,
+ 0x1904c, 0x16190, 0x1b0cc, 0x19046, 0x16188, 0x12084, 0x16184, 0x12082,
+ 0x120d8, 0x161d8, 0x161cc, 0x161c6, 0x1d82c, 0x1d826, 0x1b042, 0x1902c,
+ 0x12048, 0x160c8, 0x160c4, 0x160c2, 0x18ac0, 0x1c570, 0x1e2bc, 0x18a60,
+ 0x1c538, 0x11440, 0x18a30, 0x1c51c, 0x11420, 0x18a18, 0x11410, 0x11408,
+ 0x116c0, 0x18b70, 0x1c5bc, 0x11660, 0x18b38, 0x1c59e, 0x11630, 0x18b1c,
+ 0x11618, 0x1160c, 0x11770, 0x18bbc, 0x11738, 0x18b9e, 0x1171c, 0x117bc,
+ 0x1179e, 0x1cd60, 0x1e6b8, 0x1f35e, 0x19a40, 0x1cd30, 0x1e69c, 0x19a20,
+ 0x1cd18, 0x1e68e, 0x19a10, 0x1cd0c, 0x19a08, 0x1cd06, 0x18960, 0x1c4b8,
+ 0x1e25e, 0x19b60, 0x18930, 0x1c49c, 0x13640, 0x11220, 0x1cd9c, 0x1c48e,
+ 0x13620, 0x19b18, 0x1890c, 0x13610, 0x11208, 0x13608, 0x11360, 0x189b8,
+ 0x1c4de, 0x13760, 0x11330, 0x1cdde, 0x13730, 0x19b9c, 0x1898e, 0x13718,
+ 0x1130c, 0x1370c, 0x113b8, 0x189de, 0x137b8, 0x1139c, 0x1379c, 0x1138e,
+ 0x113de, 0x137de, 0x1dd40, 0x1eeb0, 0x1f75c, 0x1dd20, 0x1ee98, 0x1f74e,
+ 0x1dd10, 0x1ee8c, 0x1dd08, 0x1ee86, 0x1dd04, 0x19940, 0x1ccb0, 0x1e65c,
+ 0x1bb40, 0x19920, 0x1eedc, 0x1e64e, 0x1bb20, 0x1dd98, 0x1eece, 0x1bb10,
+ 0x19908, 0x1cc86, 0x1bb08, 0x1dd86, 0x19902, 0x11140, 0x188b0, 0x1c45c,
+ 0x13340, 0x11120, 0x18898, 0x1c44e, 0x17740, 0x13320, 0x19998, 0x1ccce,
+ 0x17720, 0x1bb98, 0x1ddce, 0x18886, 0x17710, 0x13308, 0x19986, 0x17708,
+ 0x11102, 0x111b0, 0x188dc, 0x133b0, 0x11198, 0x188ce, 0x177b0, 0x13398,
+ 0x199ce, 0x17798, 0x1bbce, 0x11186, 0x13386, 0x111dc, 0x133dc, 0x111ce,
+ 0x177dc, 0x133ce, 0x1dca0, 0x1ee58, 0x1f72e, 0x1dc90, 0x1ee4c, 0x1dc88,
+ 0x1ee46, 0x1dc84, 0x1dc82, 0x198a0, 0x1cc58, 0x1e62e, 0x1b9a0, 0x19890,
+ 0x1ee6e, 0x1b990, 0x1dccc, 0x1cc46, 0x1b988, 0x19884, 0x1b984, 0x19882,
+ 0x1b982, 0x110a0, 0x18858, 0x1c42e, 0x131a0, 0x11090, 0x1884c, 0x173a0,
+ 0x13190, 0x198cc, 0x18846, 0x17390, 0x1b9cc, 0x11084, 0x17388, 0x13184,
+ 0x11082, 0x13182, 0x110d8, 0x1886e, 0x131d8, 0x110cc, 0x173d8, 0x131cc,
+ 0x110c6, 0x173cc, 0x131c6, 0x110ee, 0x173ee, 0x1dc50, 0x1ee2c, 0x1dc48,
+ 0x1ee26, 0x1dc44, 0x1dc42, 0x19850, 0x1cc2c, 0x1b8d0, 0x19848, 0x1cc26,
+ 0x1b8c8, 0x1dc66, 0x1b8c4, 0x19842, 0x1b8c2, 0x11050, 0x1882c, 0x130d0,
+ 0x11048, 0x18826, 0x171d0, 0x130c8, 0x19866, 0x171c8, 0x1b8e6, 0x11042,
+ 0x171c4, 0x130c2, 0x171c2, 0x130ec, 0x171ec, 0x171e6, 0x1ee16, 0x1dc22,
+ 0x1cc16, 0x19824, 0x19822, 0x11028, 0x13068, 0x170e8, 0x11022, 0x13062,
+ 0x18560, 0x10a40, 0x18530, 0x10a20, 0x18518, 0x1c28e, 0x10a10, 0x1850c,
+ 0x10a08, 0x18506, 0x10b60, 0x185b8, 0x1c2de, 0x10b30, 0x1859c, 0x10b18,
+ 0x1858e, 0x10b0c, 0x10b06, 0x10bb8, 0x185de, 0x10b9c, 0x10b8e, 0x10bde,
+ 0x18d40, 0x1c6b0, 0x1e35c, 0x18d20, 0x1c698, 0x18d10, 0x1c68c, 0x18d08,
+ 0x1c686, 0x18d04, 0x10940, 0x184b0, 0x1c25c, 0x11b40, 0x10920, 0x1c6dc,
+ 0x1c24e, 0x11b20, 0x18d98, 0x1c6ce, 0x11b10, 0x10908, 0x18486, 0x11b08,
+ 0x18d86, 0x10902, 0x109b0, 0x184dc, 0x11bb0, 0x10998, 0x184ce, 0x11b98,
+ 0x18dce, 0x11b8c, 0x10986, 0x109dc, 0x11bdc, 0x109ce, 0x11bce, 0x1cea0,
+ 0x1e758, 0x1f3ae, 0x1ce90, 0x1e74c, 0x1ce88, 0x1e746, 0x1ce84, 0x1ce82,
+ 0x18ca0, 0x1c658, 0x19da0, 0x18c90, 0x1c64c, 0x19d90, 0x1cecc, 0x1c646,
+ 0x19d88, 0x18c84, 0x19d84, 0x18c82, 0x19d82, 0x108a0, 0x18458, 0x119a0,
+ 0x10890, 0x1c66e, 0x13ba0, 0x11990, 0x18ccc, 0x18446, 0x13b90, 0x19dcc,
+ 0x10884, 0x13b88, 0x11984, 0x10882, 0x11982, 0x108d8, 0x1846e, 0x119d8,
+ 0x108cc, 0x13bd8, 0x119cc, 0x108c6, 0x13bcc, 0x119c6, 0x108ee, 0x119ee,
+ 0x13bee, 0x1ef50, 0x1f7ac, 0x1ef48, 0x1f7a6, 0x1ef44, 0x1ef42, 0x1ce50,
+ 0x1e72c, 0x1ded0, 0x1ef6c, 0x1e726, 0x1dec8, 0x1ef66, 0x1dec4, 0x1ce42,
+ 0x1dec2, 0x18c50, 0x1c62c, 0x19cd0, 0x18c48, 0x1c626, 0x1bdd0, 0x19cc8,
+ 0x1ce66, 0x1bdc8, 0x1dee6, 0x18c42, 0x1bdc4, 0x19cc2, 0x1bdc2, 0x10850,
+ 0x1842c, 0x118d0, 0x10848, 0x18426, 0x139d0, 0x118c8, 0x18c66, 0x17bd0,
+ 0x139c8, 0x19ce6, 0x10842, 0x17bc8, 0x1bde6, 0x118c2, 0x17bc4, 0x1086c,
+ 0x118ec, 0x10866, 0x139ec, 0x118e6, 0x17bec, 0x139e6, 0x17be6, 0x1ef28,
+ 0x1f796, 0x1ef24, 0x1ef22, 0x1ce28, 0x1e716, 0x1de68, 0x1ef36, 0x1de64,
+ 0x1ce22, 0x1de62, 0x18c28, 0x1c616, 0x19c68, 0x18c24, 0x1bce8, 0x19c64,
+ 0x18c22, 0x1bce4, 0x19c62, 0x1bce2, 0x10828, 0x18416, 0x11868, 0x18c36,
+ 0x138e8, 0x11864, 0x10822, 0x179e8, 0x138e4, 0x11862, 0x179e4, 0x138e2,
+ 0x179e2, 0x11876, 0x179f6, 0x1ef12, 0x1de34, 0x1de32, 0x19c34, 0x1bc74,
+ 0x1bc72, 0x11834, 0x13874, 0x178f4, 0x178f2, 0x10540, 0x10520, 0x18298,
+ 0x10510, 0x10508, 0x10504, 0x105b0, 0x10598, 0x1058c, 0x10586, 0x105dc,
+ 0x105ce, 0x186a0, 0x18690, 0x1c34c, 0x18688, 0x1c346, 0x18684, 0x18682,
+ 0x104a0, 0x18258, 0x10da0, 0x186d8, 0x1824c, 0x10d90, 0x186cc, 0x10d88,
+ 0x186c6, 0x10d84, 0x10482, 0x10d82, 0x104d8, 0x1826e, 0x10dd8, 0x186ee,
+ 0x10dcc, 0x104c6, 0x10dc6, 0x104ee, 0x10dee, 0x1c750, 0x1c748, 0x1c744,
+ 0x1c742, 0x18650, 0x18ed0, 0x1c76c, 0x1c326, 0x18ec8, 0x1c766, 0x18ec4,
+ 0x18642, 0x18ec2, 0x10450, 0x10cd0, 0x10448, 0x18226, 0x11dd0, 0x10cc8,
+ 0x10444, 0x11dc8, 0x10cc4, 0x10442, 0x11dc4, 0x10cc2, 0x1046c, 0x10cec,
+ 0x10466, 0x11dec, 0x10ce6, 0x11de6, 0x1e7a8, 0x1e7a4, 0x1e7a2, 0x1c728,
+ 0x1cf68, 0x1e7b6, 0x1cf64, 0x1c722, 0x1cf62, 0x18628, 0x1c316, 0x18e68,
+ 0x1c736, 0x19ee8, 0x18e64, 0x18622, 0x19ee4, 0x18e62, 0x19ee2, 0x10428,
+ 0x18216, 0x10c68, 0x18636, 0x11ce8, 0x10c64, 0x10422, 0x13de8, 0x11ce4,
+ 0x10c62, 0x13de4, 0x11ce2, 0x10436, 0x10c76, 0x11cf6, 0x13df6, 0x1f7d4,
+ 0x1f7d2, 0x1e794, 0x1efb4, 0x1e792, 0x1efb2, 0x1c714, 0x1cf34, 0x1c712,
+ 0x1df74, 0x1cf32, 0x1df72, 0x18614, 0x18e34, 0x18612, 0x19e74, 0x18e32,
+ 0x1bef4
+ }, {
+ 0x1f560, 0x1fab8, 0x1ea40, 0x1f530, 0x1fa9c, 0x1ea20, 0x1f518, 0x1fa8e,
+ 0x1ea10, 0x1f50c, 0x1ea08, 0x1f506, 0x1ea04, 0x1eb60, 0x1f5b8, 0x1fade,
+ 0x1d640, 0x1eb30, 0x1f59c, 0x1d620, 0x1eb18, 0x1f58e, 0x1d610, 0x1eb0c,
+ 0x1d608, 0x1eb06, 0x1d604, 0x1d760, 0x1ebb8, 0x1f5de, 0x1ae40, 0x1d730,
+ 0x1eb9c, 0x1ae20, 0x1d718, 0x1eb8e, 0x1ae10, 0x1d70c, 0x1ae08, 0x1d706,
+ 0x1ae04, 0x1af60, 0x1d7b8, 0x1ebde, 0x15e40, 0x1af30, 0x1d79c, 0x15e20,
+ 0x1af18, 0x1d78e, 0x15e10, 0x1af0c, 0x15e08, 0x1af06, 0x15f60, 0x1afb8,
+ 0x1d7de, 0x15f30, 0x1af9c, 0x15f18, 0x1af8e, 0x15f0c, 0x15fb8, 0x1afde,
+ 0x15f9c, 0x15f8e, 0x1e940, 0x1f4b0, 0x1fa5c, 0x1e920, 0x1f498, 0x1fa4e,
+ 0x1e910, 0x1f48c, 0x1e908, 0x1f486, 0x1e904, 0x1e902, 0x1d340, 0x1e9b0,
+ 0x1f4dc, 0x1d320, 0x1e998, 0x1f4ce, 0x1d310, 0x1e98c, 0x1d308, 0x1e986,
+ 0x1d304, 0x1d302, 0x1a740, 0x1d3b0, 0x1e9dc, 0x1a720, 0x1d398, 0x1e9ce,
+ 0x1a710, 0x1d38c, 0x1a708, 0x1d386, 0x1a704, 0x1a702, 0x14f40, 0x1a7b0,
+ 0x1d3dc, 0x14f20, 0x1a798, 0x1d3ce, 0x14f10, 0x1a78c, 0x14f08, 0x1a786,
+ 0x14f04, 0x14fb0, 0x1a7dc, 0x14f98, 0x1a7ce, 0x14f8c, 0x14f86, 0x14fdc,
+ 0x14fce, 0x1e8a0, 0x1f458, 0x1fa2e, 0x1e890, 0x1f44c, 0x1e888, 0x1f446,
+ 0x1e884, 0x1e882, 0x1d1a0, 0x1e8d8, 0x1f46e, 0x1d190, 0x1e8cc, 0x1d188,
+ 0x1e8c6, 0x1d184, 0x1d182, 0x1a3a0, 0x1d1d8, 0x1e8ee, 0x1a390, 0x1d1cc,
+ 0x1a388, 0x1d1c6, 0x1a384, 0x1a382, 0x147a0, 0x1a3d8, 0x1d1ee, 0x14790,
+ 0x1a3cc, 0x14788, 0x1a3c6, 0x14784, 0x14782, 0x147d8, 0x1a3ee, 0x147cc,
+ 0x147c6, 0x147ee, 0x1e850, 0x1f42c, 0x1e848, 0x1f426, 0x1e844, 0x1e842,
+ 0x1d0d0, 0x1e86c, 0x1d0c8, 0x1e866, 0x1d0c4, 0x1d0c2, 0x1a1d0, 0x1d0ec,
+ 0x1a1c8, 0x1d0e6, 0x1a1c4, 0x1a1c2, 0x143d0, 0x1a1ec, 0x143c8, 0x1a1e6,
+ 0x143c4, 0x143c2, 0x143ec, 0x143e6, 0x1e828, 0x1f416, 0x1e824, 0x1e822,
+ 0x1d068, 0x1e836, 0x1d064, 0x1d062, 0x1a0e8, 0x1d076, 0x1a0e4, 0x1a0e2,
+ 0x141e8, 0x1a0f6, 0x141e4, 0x141e2, 0x1e814, 0x1e812, 0x1d034, 0x1d032,
+ 0x1a074, 0x1a072, 0x1e540, 0x1f2b0, 0x1f95c, 0x1e520, 0x1f298, 0x1f94e,
+ 0x1e510, 0x1f28c, 0x1e508, 0x1f286, 0x1e504, 0x1e502, 0x1cb40, 0x1e5b0,
+ 0x1f2dc, 0x1cb20, 0x1e598, 0x1f2ce, 0x1cb10, 0x1e58c, 0x1cb08, 0x1e586,
+ 0x1cb04, 0x1cb02, 0x19740, 0x1cbb0, 0x1e5dc, 0x19720, 0x1cb98, 0x1e5ce,
+ 0x19710, 0x1cb8c, 0x19708, 0x1cb86, 0x19704, 0x19702, 0x12f40, 0x197b0,
+ 0x1cbdc, 0x12f20, 0x19798, 0x1cbce, 0x12f10, 0x1978c, 0x12f08, 0x19786,
+ 0x12f04, 0x12fb0, 0x197dc, 0x12f98, 0x197ce, 0x12f8c, 0x12f86, 0x12fdc,
+ 0x12fce, 0x1f6a0, 0x1fb58, 0x16bf0, 0x1f690, 0x1fb4c, 0x169f8, 0x1f688,
+ 0x1fb46, 0x168fc, 0x1f684, 0x1f682, 0x1e4a0, 0x1f258, 0x1f92e, 0x1eda0,
+ 0x1e490, 0x1fb6e, 0x1ed90, 0x1f6cc, 0x1f246, 0x1ed88, 0x1e484, 0x1ed84,
+ 0x1e482, 0x1ed82, 0x1c9a0, 0x1e4d8, 0x1f26e, 0x1dba0, 0x1c990, 0x1e4cc,
+ 0x1db90, 0x1edcc, 0x1e4c6, 0x1db88, 0x1c984, 0x1db84, 0x1c982, 0x1db82,
+ 0x193a0, 0x1c9d8, 0x1e4ee, 0x1b7a0, 0x19390, 0x1c9cc, 0x1b790, 0x1dbcc,
+ 0x1c9c6, 0x1b788, 0x19384, 0x1b784, 0x19382, 0x1b782, 0x127a0, 0x193d8,
+ 0x1c9ee, 0x16fa0, 0x12790, 0x193cc, 0x16f90, 0x1b7cc, 0x193c6, 0x16f88,
+ 0x12784, 0x16f84, 0x12782, 0x127d8, 0x193ee, 0x16fd8, 0x127cc, 0x16fcc,
+ 0x127c6, 0x16fc6, 0x127ee, 0x1f650, 0x1fb2c, 0x165f8, 0x1f648, 0x1fb26,
+ 0x164fc, 0x1f644, 0x1647e, 0x1f642, 0x1e450, 0x1f22c, 0x1ecd0, 0x1e448,
+ 0x1f226, 0x1ecc8, 0x1f666, 0x1ecc4, 0x1e442, 0x1ecc2, 0x1c8d0, 0x1e46c,
+ 0x1d9d0, 0x1c8c8, 0x1e466, 0x1d9c8, 0x1ece6, 0x1d9c4, 0x1c8c2, 0x1d9c2,
+ 0x191d0, 0x1c8ec, 0x1b3d0, 0x191c8, 0x1c8e6, 0x1b3c8, 0x1d9e6, 0x1b3c4,
+ 0x191c2, 0x1b3c2, 0x123d0, 0x191ec, 0x167d0, 0x123c8, 0x191e6, 0x167c8,
+ 0x1b3e6, 0x167c4, 0x123c2, 0x167c2, 0x123ec, 0x167ec, 0x123e6, 0x167e6,
+ 0x1f628, 0x1fb16, 0x162fc, 0x1f624, 0x1627e, 0x1f622, 0x1e428, 0x1f216,
+ 0x1ec68, 0x1f636, 0x1ec64, 0x1e422, 0x1ec62, 0x1c868, 0x1e436, 0x1d8e8,
+ 0x1c864, 0x1d8e4, 0x1c862, 0x1d8e2, 0x190e8, 0x1c876, 0x1b1e8, 0x1d8f6,
+ 0x1b1e4, 0x190e2, 0x1b1e2, 0x121e8, 0x190f6, 0x163e8, 0x121e4, 0x163e4,
+ 0x121e2, 0x163e2, 0x121f6, 0x163f6, 0x1f614, 0x1617e, 0x1f612, 0x1e414,
+ 0x1ec34, 0x1e412, 0x1ec32, 0x1c834, 0x1d874, 0x1c832, 0x1d872, 0x19074,
+ 0x1b0f4, 0x19072, 0x1b0f2, 0x120f4, 0x161f4, 0x120f2, 0x161f2, 0x1f60a,
+ 0x1e40a, 0x1ec1a, 0x1c81a, 0x1d83a, 0x1903a, 0x1b07a, 0x1e2a0, 0x1f158,
+ 0x1f8ae, 0x1e290, 0x1f14c, 0x1e288, 0x1f146, 0x1e284, 0x1e282, 0x1c5a0,
+ 0x1e2d8, 0x1f16e, 0x1c590, 0x1e2cc, 0x1c588, 0x1e2c6, 0x1c584, 0x1c582,
+ 0x18ba0, 0x1c5d8, 0x1e2ee, 0x18b90, 0x1c5cc, 0x18b88, 0x1c5c6, 0x18b84,
+ 0x18b82, 0x117a0, 0x18bd8, 0x1c5ee, 0x11790, 0x18bcc, 0x11788, 0x18bc6,
+ 0x11784, 0x11782, 0x117d8, 0x18bee, 0x117cc, 0x117c6, 0x117ee, 0x1f350,
+ 0x1f9ac, 0x135f8, 0x1f348, 0x1f9a6, 0x134fc, 0x1f344, 0x1347e, 0x1f342,
+ 0x1e250, 0x1f12c, 0x1e6d0, 0x1e248, 0x1f126, 0x1e6c8, 0x1f366, 0x1e6c4,
+ 0x1e242, 0x1e6c2, 0x1c4d0, 0x1e26c, 0x1cdd0, 0x1c4c8, 0x1e266, 0x1cdc8,
+ 0x1e6e6, 0x1cdc4, 0x1c4c2, 0x1cdc2, 0x189d0, 0x1c4ec, 0x19bd0, 0x189c8,
+ 0x1c4e6, 0x19bc8, 0x1cde6, 0x19bc4, 0x189c2, 0x19bc2, 0x113d0, 0x189ec,
+ 0x137d0, 0x113c8, 0x189e6, 0x137c8, 0x19be6, 0x137c4, 0x113c2, 0x137c2,
+ 0x113ec, 0x137ec, 0x113e6, 0x137e6, 0x1fba8, 0x175f0, 0x1bafc, 0x1fba4,
+ 0x174f8, 0x1ba7e, 0x1fba2, 0x1747c, 0x1743e, 0x1f328, 0x1f996, 0x132fc,
+ 0x1f768, 0x1fbb6, 0x176fc, 0x1327e, 0x1f764, 0x1f322, 0x1767e, 0x1f762,
+ 0x1e228, 0x1f116, 0x1e668, 0x1e224, 0x1eee8, 0x1f776, 0x1e222, 0x1eee4,
+ 0x1e662, 0x1eee2, 0x1c468, 0x1e236, 0x1cce8, 0x1c464, 0x1dde8, 0x1cce4,
+ 0x1c462, 0x1dde4, 0x1cce2, 0x1dde2, 0x188e8, 0x1c476, 0x199e8, 0x188e4,
+ 0x1bbe8, 0x199e4, 0x188e2, 0x1bbe4, 0x199e2, 0x1bbe2, 0x111e8, 0x188f6,
+ 0x133e8, 0x111e4, 0x177e8, 0x133e4, 0x111e2, 0x177e4, 0x133e2, 0x177e2,
+ 0x111f6, 0x133f6, 0x1fb94, 0x172f8, 0x1b97e, 0x1fb92, 0x1727c, 0x1723e,
+ 0x1f314, 0x1317e, 0x1f734, 0x1f312, 0x1737e, 0x1f732, 0x1e214, 0x1e634,
+ 0x1e212, 0x1ee74, 0x1e632, 0x1ee72, 0x1c434, 0x1cc74, 0x1c432, 0x1dcf4,
+ 0x1cc72, 0x1dcf2, 0x18874, 0x198f4, 0x18872, 0x1b9f4, 0x198f2, 0x1b9f2,
+ 0x110f4, 0x131f4, 0x110f2, 0x173f4, 0x131f2, 0x173f2, 0x1fb8a, 0x1717c,
+ 0x1713e, 0x1f30a, 0x1f71a, 0x1e20a, 0x1e61a, 0x1ee3a, 0x1c41a, 0x1cc3a,
+ 0x1dc7a, 0x1883a, 0x1987a, 0x1b8fa, 0x1107a, 0x130fa, 0x171fa, 0x170be,
+ 0x1e150, 0x1f0ac, 0x1e148, 0x1f0a6, 0x1e144, 0x1e142, 0x1c2d0, 0x1e16c,
+ 0x1c2c8, 0x1e166, 0x1c2c4, 0x1c2c2, 0x185d0, 0x1c2ec, 0x185c8, 0x1c2e6,
+ 0x185c4, 0x185c2, 0x10bd0, 0x185ec, 0x10bc8, 0x185e6, 0x10bc4, 0x10bc2,
+ 0x10bec, 0x10be6, 0x1f1a8, 0x1f8d6, 0x11afc, 0x1f1a4, 0x11a7e, 0x1f1a2,
+ 0x1e128, 0x1f096, 0x1e368, 0x1e124, 0x1e364, 0x1e122, 0x1e362, 0x1c268,
+ 0x1e136, 0x1c6e8, 0x1c264, 0x1c6e4, 0x1c262, 0x1c6e2, 0x184e8, 0x1c276,
+ 0x18de8, 0x184e4, 0x18de4, 0x184e2, 0x18de2, 0x109e8, 0x184f6, 0x11be8,
+ 0x109e4, 0x11be4, 0x109e2, 0x11be2, 0x109f6, 0x11bf6, 0x1f9d4, 0x13af8,
+ 0x19d7e, 0x1f9d2, 0x13a7c, 0x13a3e, 0x1f194, 0x1197e, 0x1f3b4, 0x1f192,
+ 0x13b7e, 0x1f3b2, 0x1e114, 0x1e334, 0x1e112, 0x1e774, 0x1e332, 0x1e772,
+ 0x1c234, 0x1c674, 0x1c232, 0x1cef4, 0x1c672, 0x1cef2, 0x18474, 0x18cf4,
+ 0x18472, 0x19df4, 0x18cf2, 0x19df2, 0x108f4, 0x119f4, 0x108f2, 0x13bf4,
+ 0x119f2, 0x13bf2, 0x17af0, 0x1bd7c, 0x17a78, 0x1bd3e, 0x17a3c, 0x17a1e,
+ 0x1f9ca, 0x1397c, 0x1fbda, 0x17b7c, 0x1393e, 0x17b3e, 0x1f18a, 0x1f39a,
+ 0x1f7ba, 0x1e10a, 0x1e31a, 0x1e73a, 0x1ef7a, 0x1c21a, 0x1c63a, 0x1ce7a,
+ 0x1defa, 0x1843a, 0x18c7a, 0x19cfa, 0x1bdfa, 0x1087a, 0x118fa, 0x139fa,
+ 0x17978, 0x1bcbe, 0x1793c, 0x1791e, 0x138be, 0x179be, 0x178bc, 0x1789e,
+ 0x1785e, 0x1e0a8, 0x1e0a4, 0x1e0a2, 0x1c168, 0x1e0b6, 0x1c164, 0x1c162,
+ 0x182e8, 0x1c176, 0x182e4, 0x182e2, 0x105e8, 0x182f6, 0x105e4, 0x105e2,
+ 0x105f6, 0x1f0d4, 0x10d7e, 0x1f0d2, 0x1e094, 0x1e1b4, 0x1e092, 0x1e1b2,
+ 0x1c134, 0x1c374, 0x1c132, 0x1c372, 0x18274, 0x186f4, 0x18272, 0x186f2,
+ 0x104f4, 0x10df4, 0x104f2, 0x10df2, 0x1f8ea, 0x11d7c, 0x11d3e, 0x1f0ca,
+ 0x1f1da, 0x1e08a, 0x1e19a, 0x1e3ba, 0x1c11a, 0x1c33a, 0x1c77a, 0x1823a,
+ 0x1867a, 0x18efa, 0x1047a, 0x10cfa, 0x11dfa, 0x13d78, 0x19ebe, 0x13d3c,
+ 0x13d1e, 0x11cbe, 0x13dbe, 0x17d70, 0x1bebc, 0x17d38, 0x1be9e, 0x17d1c,
+ 0x17d0e, 0x13cbc, 0x17dbc, 0x13c9e, 0x17d9e, 0x17cb8, 0x1be5e, 0x17c9c,
+ 0x17c8e, 0x13c5e, 0x17cde, 0x17c5c, 0x17c4e, 0x17c2e, 0x1c0b4, 0x1c0b2,
+ 0x18174, 0x18172, 0x102f4, 0x102f2, 0x1e0da, 0x1c09a, 0x1c1ba, 0x1813a,
+ 0x1837a, 0x1027a, 0x106fa, 0x10ebe, 0x11ebc, 0x11e9e, 0x13eb8, 0x19f5e,
+ 0x13e9c, 0x13e8e, 0x11e5e, 0x13ede, 0x17eb0, 0x1bf5c, 0x17e98, 0x1bf4e,
+ 0x17e8c, 0x17e86, 0x13e5c, 0x17edc, 0x13e4e, 0x17ece, 0x17e58, 0x1bf2e,
+ 0x17e4c, 0x17e46, 0x13e2e, 0x17e6e, 0x17e2c, 0x17e26, 0x10f5e, 0x11f5c,
+ 0x11f4e, 0x13f58, 0x19fae, 0x13f4c, 0x13f46, 0x11f2e, 0x13f6e, 0x13f2c,
+ 0x13f26
+ }, {
+ 0x1abe0, 0x1d5f8, 0x153c0, 0x1a9f0, 0x1d4fc, 0x151e0, 0x1a8f8, 0x1d47e,
+ 0x150f0, 0x1a87c, 0x15078, 0x1fad0, 0x15be0, 0x1adf8, 0x1fac8, 0x159f0,
+ 0x1acfc, 0x1fac4, 0x158f8, 0x1ac7e, 0x1fac2, 0x1587c, 0x1f5d0, 0x1faec,
+ 0x15df8, 0x1f5c8, 0x1fae6, 0x15cfc, 0x1f5c4, 0x15c7e, 0x1f5c2, 0x1ebd0,
+ 0x1f5ec, 0x1ebc8, 0x1f5e6, 0x1ebc4, 0x1ebc2, 0x1d7d0, 0x1ebec, 0x1d7c8,
+ 0x1ebe6, 0x1d7c4, 0x1d7c2, 0x1afd0, 0x1d7ec, 0x1afc8, 0x1d7e6, 0x1afc4,
+ 0x14bc0, 0x1a5f0, 0x1d2fc, 0x149e0, 0x1a4f8, 0x1d27e, 0x148f0, 0x1a47c,
+ 0x14878, 0x1a43e, 0x1483c, 0x1fa68, 0x14df0, 0x1a6fc, 0x1fa64, 0x14cf8,
+ 0x1a67e, 0x1fa62, 0x14c7c, 0x14c3e, 0x1f4e8, 0x1fa76, 0x14efc, 0x1f4e4,
+ 0x14e7e, 0x1f4e2, 0x1e9e8, 0x1f4f6, 0x1e9e4, 0x1e9e2, 0x1d3e8, 0x1e9f6,
+ 0x1d3e4, 0x1d3e2, 0x1a7e8, 0x1d3f6, 0x1a7e4, 0x1a7e2, 0x145e0, 0x1a2f8,
+ 0x1d17e, 0x144f0, 0x1a27c, 0x14478, 0x1a23e, 0x1443c, 0x1441e, 0x1fa34,
+ 0x146f8, 0x1a37e, 0x1fa32, 0x1467c, 0x1463e, 0x1f474, 0x1477e, 0x1f472,
+ 0x1e8f4, 0x1e8f2, 0x1d1f4, 0x1d1f2, 0x1a3f4, 0x1a3f2, 0x142f0, 0x1a17c,
+ 0x14278, 0x1a13e, 0x1423c, 0x1421e, 0x1fa1a, 0x1437c, 0x1433e, 0x1f43a,
+ 0x1e87a, 0x1d0fa, 0x14178, 0x1a0be, 0x1413c, 0x1411e, 0x141be, 0x140bc,
+ 0x1409e, 0x12bc0, 0x195f0, 0x1cafc, 0x129e0, 0x194f8, 0x1ca7e, 0x128f0,
+ 0x1947c, 0x12878, 0x1943e, 0x1283c, 0x1f968, 0x12df0, 0x196fc, 0x1f964,
+ 0x12cf8, 0x1967e, 0x1f962, 0x12c7c, 0x12c3e, 0x1f2e8, 0x1f976, 0x12efc,
+ 0x1f2e4, 0x12e7e, 0x1f2e2, 0x1e5e8, 0x1f2f6, 0x1e5e4, 0x1e5e2, 0x1cbe8,
+ 0x1e5f6, 0x1cbe4, 0x1cbe2, 0x197e8, 0x1cbf6, 0x197e4, 0x197e2, 0x1b5e0,
+ 0x1daf8, 0x1ed7e, 0x169c0, 0x1b4f0, 0x1da7c, 0x168e0, 0x1b478, 0x1da3e,
+ 0x16870, 0x1b43c, 0x16838, 0x1b41e, 0x1681c, 0x125e0, 0x192f8, 0x1c97e,
+ 0x16de0, 0x124f0, 0x1927c, 0x16cf0, 0x1b67c, 0x1923e, 0x16c78, 0x1243c,
+ 0x16c3c, 0x1241e, 0x16c1e, 0x1f934, 0x126f8, 0x1937e, 0x1fb74, 0x1f932,
+ 0x16ef8, 0x1267c, 0x1fb72, 0x16e7c, 0x1263e, 0x16e3e, 0x1f274, 0x1277e,
+ 0x1f6f4, 0x1f272, 0x16f7e, 0x1f6f2, 0x1e4f4, 0x1edf4, 0x1e4f2, 0x1edf2,
+ 0x1c9f4, 0x1dbf4, 0x1c9f2, 0x1dbf2, 0x193f4, 0x193f2, 0x165c0, 0x1b2f0,
+ 0x1d97c, 0x164e0, 0x1b278, 0x1d93e, 0x16470, 0x1b23c, 0x16438, 0x1b21e,
+ 0x1641c, 0x1640e, 0x122f0, 0x1917c, 0x166f0, 0x12278, 0x1913e, 0x16678,
+ 0x1b33e, 0x1663c, 0x1221e, 0x1661e, 0x1f91a, 0x1237c, 0x1fb3a, 0x1677c,
+ 0x1233e, 0x1673e, 0x1f23a, 0x1f67a, 0x1e47a, 0x1ecfa, 0x1c8fa, 0x1d9fa,
+ 0x191fa, 0x162e0, 0x1b178, 0x1d8be, 0x16270, 0x1b13c, 0x16238, 0x1b11e,
+ 0x1621c, 0x1620e, 0x12178, 0x190be, 0x16378, 0x1213c, 0x1633c, 0x1211e,
+ 0x1631e, 0x121be, 0x163be, 0x16170, 0x1b0bc, 0x16138, 0x1b09e, 0x1611c,
+ 0x1610e, 0x120bc, 0x161bc, 0x1209e, 0x1619e, 0x160b8, 0x1b05e, 0x1609c,
+ 0x1608e, 0x1205e, 0x160de, 0x1605c, 0x1604e, 0x115e0, 0x18af8, 0x1c57e,
+ 0x114f0, 0x18a7c, 0x11478, 0x18a3e, 0x1143c, 0x1141e, 0x1f8b4, 0x116f8,
+ 0x18b7e, 0x1f8b2, 0x1167c, 0x1163e, 0x1f174, 0x1177e, 0x1f172, 0x1e2f4,
+ 0x1e2f2, 0x1c5f4, 0x1c5f2, 0x18bf4, 0x18bf2, 0x135c0, 0x19af0, 0x1cd7c,
+ 0x134e0, 0x19a78, 0x1cd3e, 0x13470, 0x19a3c, 0x13438, 0x19a1e, 0x1341c,
+ 0x1340e, 0x112f0, 0x1897c, 0x136f0, 0x11278, 0x1893e, 0x13678, 0x19b3e,
+ 0x1363c, 0x1121e, 0x1361e, 0x1f89a, 0x1137c, 0x1f9ba, 0x1377c, 0x1133e,
+ 0x1373e, 0x1f13a, 0x1f37a, 0x1e27a, 0x1e6fa, 0x1c4fa, 0x1cdfa, 0x189fa,
+ 0x1bae0, 0x1dd78, 0x1eebe, 0x174c0, 0x1ba70, 0x1dd3c, 0x17460, 0x1ba38,
+ 0x1dd1e, 0x17430, 0x1ba1c, 0x17418, 0x1ba0e, 0x1740c, 0x132e0, 0x19978,
+ 0x1ccbe, 0x176e0, 0x13270, 0x1993c, 0x17670, 0x1bb3c, 0x1991e, 0x17638,
+ 0x1321c, 0x1761c, 0x1320e, 0x1760e, 0x11178, 0x188be, 0x13378, 0x1113c,
+ 0x17778, 0x1333c, 0x1111e, 0x1773c, 0x1331e, 0x1771e, 0x111be, 0x133be,
+ 0x177be, 0x172c0, 0x1b970, 0x1dcbc, 0x17260, 0x1b938, 0x1dc9e, 0x17230,
+ 0x1b91c, 0x17218, 0x1b90e, 0x1720c, 0x17206, 0x13170, 0x198bc, 0x17370,
+ 0x13138, 0x1989e, 0x17338, 0x1b99e, 0x1731c, 0x1310e, 0x1730e, 0x110bc,
+ 0x131bc, 0x1109e, 0x173bc, 0x1319e, 0x1739e, 0x17160, 0x1b8b8, 0x1dc5e,
+ 0x17130, 0x1b89c, 0x17118, 0x1b88e, 0x1710c, 0x17106, 0x130b8, 0x1985e,
+ 0x171b8, 0x1309c, 0x1719c, 0x1308e, 0x1718e, 0x1105e, 0x130de, 0x171de,
+ 0x170b0, 0x1b85c, 0x17098, 0x1b84e, 0x1708c, 0x17086, 0x1305c, 0x170dc,
+ 0x1304e, 0x170ce, 0x17058, 0x1b82e, 0x1704c, 0x17046, 0x1302e, 0x1706e,
+ 0x1702c, 0x17026, 0x10af0, 0x1857c, 0x10a78, 0x1853e, 0x10a3c, 0x10a1e,
+ 0x10b7c, 0x10b3e, 0x1f0ba, 0x1e17a, 0x1c2fa, 0x185fa, 0x11ae0, 0x18d78,
+ 0x1c6be, 0x11a70, 0x18d3c, 0x11a38, 0x18d1e, 0x11a1c, 0x11a0e, 0x10978,
+ 0x184be, 0x11b78, 0x1093c, 0x11b3c, 0x1091e, 0x11b1e, 0x109be, 0x11bbe,
+ 0x13ac0, 0x19d70, 0x1cebc, 0x13a60, 0x19d38, 0x1ce9e, 0x13a30, 0x19d1c,
+ 0x13a18, 0x19d0e, 0x13a0c, 0x13a06, 0x11970, 0x18cbc, 0x13b70, 0x11938,
+ 0x18c9e, 0x13b38, 0x1191c, 0x13b1c, 0x1190e, 0x13b0e, 0x108bc, 0x119bc,
+ 0x1089e, 0x13bbc, 0x1199e, 0x13b9e, 0x1bd60, 0x1deb8, 0x1ef5e, 0x17a40,
+ 0x1bd30, 0x1de9c, 0x17a20, 0x1bd18, 0x1de8e, 0x17a10, 0x1bd0c, 0x17a08,
+ 0x1bd06, 0x17a04, 0x13960, 0x19cb8, 0x1ce5e, 0x17b60, 0x13930, 0x19c9c,
+ 0x17b30, 0x1bd9c, 0x19c8e, 0x17b18, 0x1390c, 0x17b0c, 0x13906, 0x17b06,
+ 0x118b8, 0x18c5e, 0x139b8, 0x1189c, 0x17bb8, 0x1399c, 0x1188e, 0x17b9c,
+ 0x1398e, 0x17b8e, 0x1085e, 0x118de, 0x139de, 0x17bde, 0x17940, 0x1bcb0,
+ 0x1de5c, 0x17920, 0x1bc98, 0x1de4e, 0x17910, 0x1bc8c, 0x17908, 0x1bc86,
+ 0x17904, 0x17902, 0x138b0, 0x19c5c, 0x179b0, 0x13898, 0x19c4e, 0x17998,
+ 0x1bcce, 0x1798c, 0x13886, 0x17986, 0x1185c, 0x138dc, 0x1184e, 0x179dc,
+ 0x138ce, 0x179ce, 0x178a0, 0x1bc58, 0x1de2e, 0x17890, 0x1bc4c, 0x17888,
+ 0x1bc46, 0x17884, 0x17882, 0x13858, 0x19c2e, 0x178d8, 0x1384c, 0x178cc,
+ 0x13846, 0x178c6, 0x1182e, 0x1386e, 0x178ee, 0x17850, 0x1bc2c, 0x17848,
+ 0x1bc26, 0x17844, 0x17842, 0x1382c, 0x1786c, 0x13826, 0x17866, 0x17828,
+ 0x1bc16, 0x17824, 0x17822, 0x13816, 0x17836, 0x10578, 0x182be, 0x1053c,
+ 0x1051e, 0x105be, 0x10d70, 0x186bc, 0x10d38, 0x1869e, 0x10d1c, 0x10d0e,
+ 0x104bc, 0x10dbc, 0x1049e, 0x10d9e, 0x11d60, 0x18eb8, 0x1c75e, 0x11d30,
+ 0x18e9c, 0x11d18, 0x18e8e, 0x11d0c, 0x11d06, 0x10cb8, 0x1865e, 0x11db8,
+ 0x10c9c, 0x11d9c, 0x10c8e, 0x11d8e, 0x1045e, 0x10cde, 0x11dde, 0x13d40,
+ 0x19eb0, 0x1cf5c, 0x13d20, 0x19e98, 0x1cf4e, 0x13d10, 0x19e8c, 0x13d08,
+ 0x19e86, 0x13d04, 0x13d02, 0x11cb0, 0x18e5c, 0x13db0, 0x11c98, 0x18e4e,
+ 0x13d98, 0x19ece, 0x13d8c, 0x11c86, 0x13d86, 0x10c5c, 0x11cdc, 0x10c4e,
+ 0x13ddc, 0x11cce, 0x13dce, 0x1bea0, 0x1df58, 0x1efae, 0x1be90, 0x1df4c,
+ 0x1be88, 0x1df46, 0x1be84, 0x1be82, 0x13ca0, 0x19e58, 0x1cf2e, 0x17da0,
+ 0x13c90, 0x19e4c, 0x17d90, 0x1becc, 0x19e46, 0x17d88, 0x13c84, 0x17d84,
+ 0x13c82, 0x17d82, 0x11c58, 0x18e2e, 0x13cd8, 0x11c4c, 0x17dd8, 0x13ccc,
+ 0x11c46, 0x17dcc, 0x13cc6, 0x17dc6, 0x10c2e, 0x11c6e, 0x13cee, 0x17dee,
+ 0x1be50, 0x1df2c, 0x1be48, 0x1df26, 0x1be44, 0x1be42, 0x13c50, 0x19e2c,
+ 0x17cd0, 0x13c48, 0x19e26, 0x17cc8, 0x1be66, 0x17cc4, 0x13c42, 0x17cc2,
+ 0x11c2c, 0x13c6c, 0x11c26, 0x17cec, 0x13c66, 0x17ce6, 0x1be28, 0x1df16,
+ 0x1be24, 0x1be22, 0x13c28, 0x19e16, 0x17c68, 0x13c24, 0x17c64, 0x13c22,
+ 0x17c62, 0x11c16, 0x13c36, 0x17c76, 0x1be14, 0x1be12, 0x13c14, 0x17c34,
+ 0x13c12, 0x17c32, 0x102bc, 0x1029e, 0x106b8, 0x1835e, 0x1069c, 0x1068e,
+ 0x1025e, 0x106de, 0x10eb0, 0x1875c, 0x10e98, 0x1874e, 0x10e8c, 0x10e86,
+ 0x1065c, 0x10edc, 0x1064e, 0x10ece, 0x11ea0, 0x18f58, 0x1c7ae, 0x11e90,
+ 0x18f4c, 0x11e88, 0x18f46, 0x11e84, 0x11e82, 0x10e58, 0x1872e, 0x11ed8,
+ 0x18f6e, 0x11ecc, 0x10e46, 0x11ec6, 0x1062e, 0x10e6e, 0x11eee, 0x19f50,
+ 0x1cfac, 0x19f48, 0x1cfa6, 0x19f44, 0x19f42, 0x11e50, 0x18f2c, 0x13ed0,
+ 0x19f6c, 0x18f26, 0x13ec8, 0x11e44, 0x13ec4, 0x11e42, 0x13ec2, 0x10e2c,
+ 0x11e6c, 0x10e26, 0x13eec, 0x11e66, 0x13ee6, 0x1dfa8, 0x1efd6, 0x1dfa4,
+ 0x1dfa2, 0x19f28, 0x1cf96, 0x1bf68, 0x19f24, 0x1bf64, 0x19f22, 0x1bf62,
+ 0x11e28, 0x18f16, 0x13e68, 0x11e24, 0x17ee8, 0x13e64, 0x11e22, 0x17ee4,
+ 0x13e62, 0x17ee2, 0x10e16, 0x11e36, 0x13e76, 0x17ef6, 0x1df94, 0x1df92,
+ 0x19f14, 0x1bf34, 0x19f12, 0x1bf32, 0x11e14, 0x13e34, 0x11e12, 0x17e74,
+ 0x13e32, 0x17e72, 0x1df8a, 0x19f0a, 0x1bf1a, 0x11e0a, 0x13e1a, 0x17e3a,
+ 0x1035c, 0x1034e, 0x10758, 0x183ae, 0x1074c, 0x10746, 0x1032e, 0x1076e,
+ 0x10f50, 0x187ac, 0x10f48, 0x187a6, 0x10f44, 0x10f42, 0x1072c, 0x10f6c,
+ 0x10726, 0x10f66, 0x18fa8, 0x1c7d6, 0x18fa4, 0x18fa2, 0x10f28, 0x18796,
+ 0x11f68, 0x18fb6, 0x11f64, 0x10f22, 0x11f62, 0x10716, 0x10f36, 0x11f76,
+ 0x1cfd4, 0x1cfd2, 0x18f94, 0x19fb4, 0x18f92, 0x19fb2, 0x10f14, 0x11f34,
+ 0x10f12, 0x13f74, 0x11f32, 0x13f72, 0x1cfca, 0x18f8a, 0x19f9a, 0x10f0a,
+ 0x11f1a, 0x13f3a, 0x103ac, 0x103a6, 0x107a8, 0x183d6, 0x107a4, 0x107a2,
+ 0x10396, 0x107b6, 0x187d4, 0x187d2, 0x10794, 0x10fb4, 0x10792, 0x10fb2,
+ 0x1c7ea
+ }};
+
+ static int ERROR_LEVEL[][] =
+ {{
+ 27, 917
+ }, {
+ 522, 568, 723, 809
+ }, {
+ 237, 308, 436, 284, 646, 653, 428, 379
+ }, {
+ 274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, 42, 176, 65
+ }, {
+ 361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517,
+ 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410
+ }, {
+ 539, 422, 6, 93, 862, 771, 453, 106, 610, 287, 107, 505, 733, 877, 381, 612,
+ 723, 476, 462, 172, 430, 609, 858, 822, 543, 376, 511, 400, 672, 762, 283, 184,
+ 440, 35, 519, 31, 460, 594, 225, 535, 517, 352, 605, 158, 651, 201, 488, 502,
+ 648, 733, 717, 83, 404, 97, 280, 771, 840, 629, 4, 381, 843, 623, 264, 543
+ }, {
+ 521, 310, 864, 547, 858, 580, 296, 379, 53, 779, 897, 444, 400, 925, 749, 415,
+ 822, 93, 217, 208, 928, 244, 583, 620, 246, 148, 447, 631, 292, 908, 490, 704,
+ 516, 258, 457, 907, 594, 723, 674, 292, 272, 96, 684, 432, 686, 606, 860, 569,
+ 193, 219, 129, 186, 236, 287, 192, 775, 278, 173, 40, 379, 712, 463, 646, 776,
+ 171, 491, 297, 763, 156, 732, 95, 270, 447, 90, 507, 48, 228, 821, 808, 898,
+ 784, 663, 627, 378, 382, 262, 380, 602, 754, 336, 89, 614, 87, 432, 670, 616,
+ 157, 374, 242, 726, 600, 269, 375, 898, 845, 454, 354, 130, 814, 587, 804, 34,
+ 211, 330, 539, 297, 827, 865, 37, 517, 834, 315, 550, 86, 801, 4, 108, 539
+ }, {
+ 524, 894, 75, 766, 882, 857, 74, 204, 82, 586, 708, 250, 905, 786, 138, 720,
+ 858, 194, 311, 913, 275, 190, 375, 850, 438, 733, 194, 280, 201, 280, 828, 757,
+ 710, 814, 919, 89, 68, 569, 11, 204, 796, 605, 540, 913, 801, 700, 799, 137,
+ 439, 418, 592, 668, 353, 859, 370, 694, 325, 240, 216, 257, 284, 549, 209, 884,
+ 315, 70, 329, 793, 490, 274, 877, 162, 749, 812, 684, 461, 334, 376, 849, 521,
+ 307, 291, 803, 712, 19, 358, 399, 908, 103, 511, 51, 8, 517, 225, 289, 470,
+ 637, 731, 66, 255, 917, 269, 463, 830, 730, 433, 848, 585, 136, 538, 906, 90,
+ 2, 290, 743, 199, 655, 903, 329, 49, 802, 580, 355, 588, 188, 462, 10, 134,
+ 628, 320, 479, 130, 739, 71, 263, 318, 374, 601, 192, 605, 142, 673, 687, 234,
+ 722, 384, 177, 752, 607, 640, 455, 193, 689, 707, 805, 641, 48, 60, 732, 621,
+ 895, 544, 261, 852, 655, 309, 697, 755, 756, 60, 231, 773, 434, 421, 726, 528,
+ 503, 118, 49, 795, 32, 144, 500, 238, 836, 394, 280, 566, 319, 9, 647, 550,
+ 73, 914, 342, 126, 32, 681, 331, 792, 620, 60, 609, 441, 180, 791, 893, 754,
+ 605, 383, 228, 749, 760, 213, 54, 297, 134, 54, 834, 299, 922, 191, 910, 532,
+ 609, 829, 189, 20, 167, 29, 872, 449, 83, 402, 41, 656, 505, 579, 481, 173,
+ 404, 251, 688, 95, 497, 555, 642, 543, 307, 159, 924, 558, 648, 55, 497, 10
+ }, {
+ 352, 77, 373, 504, 35, 599, 428, 207, 409, 574, 118, 498, 285, 380, 350, 492,
+ 197, 265, 920, 155, 914, 299, 229, 643, 294, 871, 306, 88, 87, 193, 352, 781,
+ 846, 75, 327, 520, 435, 543, 203, 666, 249, 346, 781, 621, 640, 268, 794, 534,
+ 539, 781, 408, 390, 644, 102, 476, 499, 290, 632, 545, 37, 858, 916, 552, 41,
+ 542, 289, 122, 272, 383, 800, 485, 98, 752, 472, 761, 107, 784, 860, 658, 741,
+ 290, 204, 681, 407, 855, 85, 99, 62, 482, 180, 20, 297, 451, 593, 913, 142,
+ 808, 684, 287, 536, 561, 76, 653, 899, 729, 567, 744, 390, 513, 192, 516, 258,
+ 240, 518, 794, 395, 768, 848, 51, 610, 384, 168, 190, 826, 328, 596, 786, 303,
+ 570, 381, 415, 641, 156, 237, 151, 429, 531, 207, 676, 710, 89, 168, 304, 402,
+ 40, 708, 575, 162, 864, 229, 65, 861, 841, 512, 164, 477, 221, 92, 358, 785,
+ 288, 357, 850, 836, 827, 736, 707, 94, 8, 494, 114, 521, 2, 499, 851, 543,
+ 152, 729, 771, 95, 248, 361, 578, 323, 856, 797, 289, 51, 684, 466, 533, 820,
+ 669, 45, 902, 452, 167, 342, 244, 173, 35, 463, 651, 51, 699, 591, 452, 578,
+ 37, 124, 298, 332, 552, 43, 427, 119, 662, 777, 475, 850, 764, 364, 578, 911,
+ 283, 711, 472, 420, 245, 288, 594, 394, 511, 327, 589, 777, 699, 688, 43, 408,
+ 842, 383, 721, 521, 560, 644, 714, 559, 62, 145, 873, 663, 713, 159, 672, 729,
+ 624, 59, 193, 417, 158, 209, 563, 564, 343, 693, 109, 608, 563, 365, 181, 772,
+ 677, 310, 248, 353, 708, 410, 579, 870, 617, 841, 632, 860, 289, 536, 35, 777,
+ 618, 586, 424, 833, 77, 597, 346, 269, 757, 632, 695, 751, 331, 247, 184, 45,
+ 787, 680, 18, 66, 407, 369, 54, 492, 228, 613, 830, 922, 437, 519, 644, 905,
+ 789, 420, 305, 441, 207, 300, 892, 827, 141, 537, 381, 662, 513, 56, 252, 341,
+ 242, 797, 838, 837, 720, 224, 307, 631, 61, 87, 560, 310, 756, 665, 397, 808,
+ 851, 309, 473, 795, 378, 31, 647, 915, 459, 806, 590, 731, 425, 216, 548, 249,
+ 321, 881, 699, 535, 673, 782, 210, 815, 905, 303, 843, 922, 281, 73, 469, 791,
+ 660, 162, 498, 308, 155, 422, 907, 817, 187, 62, 16, 425, 535, 336, 286, 437,
+ 375, 273, 610, 296, 183, 923, 116, 667, 751, 353, 62, 366, 691, 379, 687, 842,
+ 37, 357, 720, 742, 330, 5, 39, 923, 311, 424, 242, 749, 321, 54, 669, 316,
+ 342, 299, 534, 105, 667, 488, 640, 672, 576, 540, 316, 486, 721, 610, 46, 656,
+ 447, 171, 616, 464, 190, 531, 297, 321, 762, 752, 533, 175, 134, 14, 381, 433,
+ 717, 45, 111, 20, 596, 284, 736, 138, 646, 411, 877, 669, 141, 919, 45, 780,
+ 407, 164, 332, 899, 165, 726, 600, 325, 498, 655, 357, 752, 768, 223, 849, 647,
+ 63, 310, 863, 251, 366, 304, 282, 738, 675, 410, 389, 244, 31, 121, 303, 263
+ }};
+
+ /** Holds value of property outBits. */
+ private byte[] outBits;
+
+ /** Holds value of property bitColumns. */
+ private int bitColumns;
+
+ /** Holds value of property codeRows. */
+ private int codeRows;
+
+ /** Holds value of property codeColumns. */
+ private int codeColumns;
+
+ /** Holds value of property codewords. */
+ private int[] codewords = new int[MAX_DATA_CODEWORDS + 2];
+
+ /** Holds value of property lenCodewords. */
+ private int lenCodewords;
+
+ /** Holds value of property errorLevel. */
+ private int errorLevel;
+
+ /** Holds value of property text. */
+ private byte[] text;
+
+ /** Holds value of property options. */
+ private int options;
+
+ /** Holds value of property aspectRatio. */
+ private float aspectRatio;
+
+ /** Holds value of property yHeight. */
+ private float yHeight;
+
+ protected static class Segment {
+ public char type;
+ public int start;
+ public int end;
+
+ public Segment(char type, int start, int end) {
+ this.type = type;
+ this.start = start;
+ this.end = end;
+ }
+ }
+
+ protected static class SegmentList {
+ protected ArrayList list = new ArrayList();
+
+ public void add(char type, int start, int end) {
+ list.add(new Segment(type, start, end));
+ }
+
+ public Segment get(int idx) {
+ if (idx < 0 || idx >= list.size())
+ return null;
+ return (Segment)list.get(idx);
+ }
+
+ public void remove(int idx) {
+ if (idx < 0 || idx >= list.size())
+ return;
+ list.remove(idx);
+ }
+
+ public int size() {
+ return list.size();
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BarcodePostnet.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BarcodePostnet.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BarcodePostnet.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BarcodePostnet.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+import pdftk.com.lowagie.text.Rectangle;
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.Canvas;
+import java.awt.image.MemoryImageSource;
+
+/** Implements the Postnet and Planet barcodes. The default parameters are:
+ *
+ *n = 72f / 22f; // distance between bars
+ *x = 0.02f * 72f; // bar width
+ *barHeight = 0.125f * 72f; // height of the tall bars
+ *size = 0.05f * 72f; // height of the short bars
+ *codeType = POSTNET; // type of code
+ *
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class BarcodePostnet extends Barcode{
+
+ /** The bars for each character.
+ */
+ static byte BARS[][] =
+ {
+ {1,1,0,0,0},
+ {0,0,0,1,1},
+ {0,0,1,0,1},
+ {0,0,1,1,0},
+ {0,1,0,0,1},
+ {0,1,0,1,0},
+ {0,1,1,0,0},
+ {1,0,0,0,1},
+ {1,0,0,1,0},
+ {1,0,1,0,0}
+ };
+
+ /** Creates new BarcodePostnet */
+ public BarcodePostnet() {
+ n = 72f / 22f; // distance between bars
+ x = 0.02f * 72f; // bar width
+ barHeight = 0.125f * 72f; // height of the tall bars
+ size = 0.05f * 72f; // height of the short bars
+ codeType = POSTNET; // type of code
+ }
+
+ /** Creates the bars for Postnet.
+ * @param text the code to be created without checksum
+ * @return the bars
+ */
+ public static byte[] getBarsPostnet(String text) {
+ int total = 0;
+ for (int k = text.length() - 1; k >= 0; --k) {
+ int n = text.charAt(k) - '0';
+ total += n;
+ }
+ text += (char)(((10 - (total % 10)) % 10) + '0');
+ byte bars[] = new byte[text.length() * 5 + 2];
+ bars[0] = 1;
+ bars[bars.length - 1] = 1;
+ for (int k = 0; k < text.length(); ++k) {
+ int c = text.charAt(k) - '0';
+ System.arraycopy(BARS[c], 0, bars, k * 5 + 1, 5);
+ }
+ return bars;
+ }
+
+ /** Gets the maximum area that the barcode and the text, if
+ * any, will occupy. The lower left corner is always (0, 0).
+ * @return the size the barcode occupies.
+ */
+ public Rectangle getBarcodeSize() {
+ float width = ((code.length() + 1) * 5 + 1) * n + x;
+ return new Rectangle(width, barHeight);
+ }
+
+ /** Places the barcode in a PdfContentByte
. The
+ * barcode is always placed at coodinates (0, 0). Use the
+ * translation matrix to move it elsewhere.
+ * The bars and text are written in the following colors:
+ *
+ *
+ * barColor
+ * textColor
+ * Result
+ *
+ *
+ * null
+ * null
+ * bars and text painted with current fill color
+ *
+ *
+ * barColor
+ * null
+ * bars and text painted with barColor
+ *
+ *
+ * null
+ * textColor
+ * bars painted with current color text painted with textColor
+ *
+ *
+ * barColor
+ * textColor
+ * bars painted with barColor
text painted with textColor
+ *
+ *
+ * @param cb the PdfContentByte
where the barcode will be placed
+ * @param barColor the color of the bars. It can be null
+ * @param textColor the color of the text. It can be null
+ * @return the dimensions the barcode occupies
+ */
+ public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) {
+ if (barColor != null)
+ cb.setColorFill(barColor);
+ byte bars[] = getBarsPostnet(code);
+ byte flip = 1;
+ if (codeType == PLANET) {
+ flip = 0;
+ bars[0] = 0;
+ bars[bars.length - 1] = 0;
+ }
+ float startX = 0;
+ for (int k = 0; k < bars.length; ++k) {
+ cb.rectangle(startX, 0, x - inkSpreading, bars[k] == flip ? barHeight : size);
+ startX += n;
+ }
+ cb.fill();
+ return getBarcodeSize();
+ }
+
+ /** Creates a java.awt.Image
. This image only
+ * contains the bars without any text.
+ * @param foreground the color of the bars
+ * @param background the color of the background
+ * @return the image
+ *
+ */
+ public java.awt.Image createAwtImage(Color foreground, Color background) {
+ int f = foreground.getRGB();
+ int g = background.getRGB();
+ Canvas canvas = new Canvas();
+ int barWidth = (int)x;
+ if (barWidth <= 0)
+ barWidth = 1;
+ int barDistance = (int)n;
+ if (barDistance <= barWidth)
+ barDistance = barWidth + 1;
+ int barShort = (int)size;
+ if (barShort <= 0)
+ barShort = 1;
+ int barTall = (int)barHeight;
+ if (barTall <= barShort)
+ barTall = barShort + 1;
+ int width = ((code.length() + 1) * 5 + 1) * barDistance + barWidth;
+ int pix[] = new int[width * barTall];
+ byte bars[] = getBarsPostnet(code);
+ byte flip = 1;
+ if (codeType == PLANET) {
+ flip = 0;
+ bars[0] = 0;
+ bars[bars.length - 1] = 0;
+ }
+ int idx = 0;
+ for (int k = 0; k < bars.length; ++k) {
+ boolean dot = (bars[k] == flip);
+ for (int j = 0; j < barDistance; ++j) {
+ pix[idx + j] = ((dot && j < barWidth) ? f : g);
+ }
+ idx += barDistance;
+ }
+ int limit = width * (barTall - barShort);
+ for (int k = width; k < limit; k += width)
+ System.arraycopy(pix, 0, pix, k, width);
+ idx = limit;
+ for (int k = 0; k < bars.length; ++k) {
+ for (int j = 0; j < barDistance; ++j) {
+ pix[idx + j] = ((j < barWidth) ? f : g);
+ }
+ idx += barDistance;
+ }
+ for (int k = limit + width; k < pix.length; k += width)
+ System.arraycopy(pix, limit, pix, k, width);
+ Image img = canvas.createImage(new MemoryImageSource(width, barTall, pix, 0, width));
+
+ return img;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BaseField.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BaseField.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BaseField.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BaseField.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,655 @@
+/*
+ * Copyright 2005 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.awt.Color;
+import pdftk.com.lowagie.text.Element;
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.Rectangle;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.HashMap;
+
+/** Common field variables.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public abstract class BaseField {
+
+ /** A thin border with 1 point width. */
+ public static final float BORDER_WIDTH_THIN = 1;
+ /** A medium border with 2 point width. */
+ public static final float BORDER_WIDTH_MEDIUM = 2;
+ /** A thick border with 3 point width. */
+ public static final float BORDER_WIDTH_THICK = 3;
+ /** The field is visible. */
+ public static final int VISIBLE = 0;
+ /** The field is hidden. */
+ public static final int HIDDEN = 1;
+ /** The field is visible but does not print. */
+ public static final int VISIBLE_BUT_DOES_NOT_PRINT = 2;
+ /** The field is hidden but is printable. */
+ public static final int HIDDEN_BUT_PRINTABLE = 3;
+ /** The user may not change the value of the field. */
+ public static final int READ_ONLY = 1;
+ /** The field must have a value at the time it is exported by a submit-form
+ * action.
+ */
+ public static final int REQUIRED = 2;
+ /** The field may contain multiple lines of text.
+ * This flag is only meaningful with text fields.
+ */
+ public static final int MULTILINE = 4;
+ /** The field will not scroll (horizontally for single-line
+ * fields, vertically for multiple-line fields) to accommodate more text
+ * than will fit within its annotation rectangle. Once the field is full, no
+ * further text will be accepted.
+ */
+ public static final int DO_NOT_SCROLL = 8;
+ /** The field is intended for entering a secure password that should
+ * not be echoed visibly to the screen.
+ */
+ public static final int PASSWORD = 16;
+ /** The text entered in the field represents the pathname of
+ * a file whose contents are to be submitted as the value of the field.
+ */
+ public static final int FILE_SELECTION = 32;
+ /** The text entered in the field will not be spell-checked.
+ * This flag is meaningful only in text fields and in combo
+ * fields with the EDIT
flag set.
+ */
+ public static final int DO_NOT_SPELL_CHECK = 64;
+ /** If set the combo box includes an editable text box as well as a drop list; if
+ * clear, it includes only a drop list.
+ * This flag is only meaningful with combo fields.
+ */
+ public static final int EDIT = 128;
+
+ /**
+ * combo box flag.
+ */
+ public static final int COMB = 256;
+
+ protected float borderWidth = BORDER_WIDTH_THIN;
+ protected int borderStyle = PdfBorderDictionary.STYLE_SOLID;
+ protected Color borderColor;
+ protected Color backgroundColor;
+ protected Color textColor;
+ protected BaseFont font;
+ protected float fontSize = 0;
+ protected int alignment = Element.ALIGN_LEFT;
+ protected PdfWriter writer;
+ protected String text;
+ protected Rectangle box;
+
+ /** Holds value of property rotation. */
+ protected int rotation = 0;
+
+ /** Holds value of property visibility. */
+ protected int visibility;
+
+ /** Holds value of property fieldName. */
+ protected String fieldName;
+
+ /** Holds value of property options. */
+ protected int options;
+
+ /** Holds value of property maxCharacterLength. */
+ protected int maxCharacterLength;
+
+ private final static HashMap fieldKeys = new HashMap();
+
+ static {
+ fieldKeys.putAll(PdfCopyFieldsImp.fieldKeys);
+ fieldKeys.put(PdfName.T, new Integer(1));
+ }
+ /** Creates a new TextField
.
+ * @param writer the document PdfWriter
+ * @param box the field location and dimensions
+ * @param fieldName the field name. If null
only the widget keys
+ * will be included in the field allowing it to be used as a kid field.
+ */
+ public BaseField(PdfWriter writer, Rectangle box, String fieldName) {
+ this.writer = writer;
+ this.box = box;
+ this.fieldName = fieldName;
+ }
+
+ protected BaseFont getRealFont() throws IOException, DocumentException {
+ if (font == null)
+ return BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, false);
+ else
+ return font;
+ }
+
+ protected PdfAppearance getBorderAppearance() throws IOException, DocumentException {
+ PdfAppearance app = writer.getDirectContent().createAppearance(box.width(), box.height());
+ switch (rotation) {
+ case 90:
+ app.setMatrix(0, 1, -1, 0, box.height(), 0);
+ break;
+ case 180:
+ app.setMatrix(-1, 0, 0, -1, box.width(), box.height());
+ break;
+ case 270:
+ app.setMatrix(0, -1, 1, 0, 0, box.width());
+ break;
+ }
+ // background
+ if (backgroundColor != null) {
+ app.setColorFill(backgroundColor);
+ app.rectangle(0, 0, box.width(), box.height());
+ app.fill();
+ }
+ // border
+ if (borderStyle == PdfBorderDictionary.STYLE_UNDERLINE) {
+ if (borderWidth != 0 && borderColor != null) {
+ app.setColorStroke(borderColor);
+ app.setLineWidth(borderWidth);
+ app.moveTo(0, borderWidth / 2);
+ app.lineTo(box.width(), borderWidth / 2);
+ app.stroke();
+ }
+ }
+ else if (borderStyle == PdfBorderDictionary.STYLE_BEVELED) {
+ if (borderWidth != 0 && borderColor != null) {
+ app.setColorStroke(borderColor);
+ app.setLineWidth(borderWidth);
+ app.rectangle(borderWidth / 2, borderWidth / 2, box.width() - borderWidth, box.height() - borderWidth);
+ app.stroke();
+ }
+ // beveled
+ Color actual = backgroundColor;
+ if (actual == null)
+ actual = Color.white;
+ app.setGrayFill(1);
+ drawTopFrame(app);
+ app.setColorFill(actual.darker());
+ drawBottomFrame(app);
+ }
+ else if (borderStyle == PdfBorderDictionary.STYLE_INSET) {
+ if (borderWidth != 0 && borderColor != null) {
+ app.setColorStroke(borderColor);
+ app.setLineWidth(borderWidth);
+ app.rectangle(borderWidth / 2, borderWidth / 2, box.width() - borderWidth, box.height() - borderWidth);
+ app.stroke();
+ }
+ // inset
+ app.setGrayFill(0.5f);
+ drawTopFrame(app);
+ app.setGrayFill(0.75f);
+ drawBottomFrame(app);
+ }
+ else {
+ if (borderWidth != 0 && borderColor != null) {
+ if (borderStyle == PdfBorderDictionary.STYLE_DASHED)
+ app.setLineDash(3, 0);
+ app.setColorStroke(borderColor);
+ app.setLineWidth(borderWidth);
+ app.rectangle(borderWidth / 2, borderWidth / 2, box.width() - borderWidth, box.height() - borderWidth);
+ app.stroke();
+ if ((options & COMB) != 0 && maxCharacterLength > 1) {
+ float step = box.width() / maxCharacterLength;
+ float yb = borderWidth / 2;
+ float yt = box.height() - borderWidth / 2;
+ for (int k = 1; k < maxCharacterLength; ++k) {
+ float x = step * k;
+ app.moveTo(x, yb);
+ app.lineTo(x, yt);
+ }
+ app.stroke();
+ }
+ }
+ }
+ return app;
+ }
+
+ protected static ArrayList getHardBreaks(String text) {
+ ArrayList arr = new ArrayList();
+ char cs[] = text.toCharArray();
+ int len = cs.length;
+ StringBuffer buf = new StringBuffer();
+ for (int k = 0; k < len; ++k) {
+ char c = cs[k];
+ if (c == '\r') {
+ if (k + 1 < len && cs[k + 1] == '\n')
+ ++k;
+ arr.add(buf.toString());
+ buf = new StringBuffer();
+ }
+ else if (c == '\n') {
+ arr.add(buf.toString());
+ buf = new StringBuffer();
+ }
+ else
+ buf.append(c);
+ }
+ arr.add(buf.toString());
+ return arr;
+ }
+
+ protected static void trimRight(StringBuffer buf) {
+ int len = buf.length();
+ while (true) {
+ if (len == 0)
+ return;
+ if (buf.charAt(--len) != ' ')
+ return;
+ buf.setLength(len);
+ }
+ }
+
+ protected static ArrayList breakLines(ArrayList breaks, BaseFont font, float fontSize, float width) {
+ ArrayList lines = new ArrayList();
+ StringBuffer buf = new StringBuffer();
+ for (int ck = 0; ck < breaks.size(); ++ck) {
+ buf.setLength(0);
+ float w = 0;
+ char cs[] = ((String)breaks.get(ck)).toCharArray();
+ int len = cs.length;
+ // 0 inline first, 1 inline, 2 spaces
+ int state = 0;
+ int lastspace = -1;
+ char c = 0;
+ int refk = 0;
+ for (int k = 0; k < len; ++k) {
+ c = cs[k];
+ switch (state) {
+ case 0:
+ w += font.getWidthPoint(c, fontSize);
+ buf.append(c);
+ if (w > width) {
+ w = 0;
+ if (buf.length() > 1) {
+ --k;
+ buf.setLength(buf.length() - 1);
+ }
+ lines.add(buf.toString());
+ buf.setLength(0);
+ refk = k;
+ if (c == ' ')
+ state = 2;
+ else
+ state = 1;
+ }
+ else {
+ if (c != ' ')
+ state = 1;
+ }
+ break;
+ case 1:
+ w += font.getWidthPoint(c, fontSize);
+ buf.append(c);
+ if (c == ' ')
+ lastspace = k;
+ if (w > width) {
+ w = 0;
+ if (lastspace >= 0) {
+ k = lastspace;
+ buf.setLength(lastspace - refk);
+ trimRight(buf);
+ lines.add(buf.toString());
+ buf.setLength(0);
+ refk = k;
+ lastspace = -1;
+ state = 2;
+ }
+ else {
+ if (buf.length() > 1) {
+ --k;
+ buf.setLength(buf.length() - 1);
+ }
+ lines.add(buf.toString());
+ buf.setLength(0);
+ refk = k;
+ if (c == ' ')
+ state = 2;
+ }
+ }
+ break;
+ case 2:
+ if (c != ' ') {
+ w = 0;
+ --k;
+ state = 1;
+ }
+ break;
+ }
+ }
+ trimRight(buf);
+ lines.add(buf.toString());
+ }
+ return lines;
+ }
+
+ private void drawTopFrame(PdfAppearance app) {
+ app.moveTo(borderWidth, borderWidth);
+ app.lineTo(borderWidth, box.height() - borderWidth);
+ app.lineTo(box.width() - borderWidth, box.height() - borderWidth);
+ app.lineTo(box.width() - 2 * borderWidth, box.height() - 2 * borderWidth);
+ app.lineTo(2 * borderWidth, box.height() - 2 * borderWidth);
+ app.lineTo(2 * borderWidth, 2 * borderWidth);
+ app.lineTo(borderWidth, borderWidth);
+ app.fill();
+ }
+
+ private void drawBottomFrame(PdfAppearance app) {
+ app.moveTo(borderWidth, borderWidth);
+ app.lineTo(box.width() - borderWidth, borderWidth);
+ app.lineTo(box.width() - borderWidth, box.height() - borderWidth);
+ app.lineTo(box.width() - 2 * borderWidth, box.height() - 2 * borderWidth);
+ app.lineTo(box.width() - 2 * borderWidth, 2 * borderWidth);
+ app.lineTo(2 * borderWidth, 2 * borderWidth);
+ app.lineTo(borderWidth, borderWidth);
+ app.fill();
+ }
+ /** Gets the border width in points.
+ * @return the border width in points
+ */
+ public float getBorderWidth() {
+ return this.borderWidth;
+ }
+
+ /** Sets the border width in points. To eliminate the border
+ * set the border color to null
.
+ * @param borderWidth the border width in points
+ */
+ public void setBorderWidth(float borderWidth) {
+ this.borderWidth = borderWidth;
+ }
+
+ /** Gets the border style.
+ * @return the border style
+ */
+ public int getBorderStyle() {
+ return this.borderStyle;
+ }
+
+ /** Sets the border style. The styles are found in PdfBorderDictionary
+ * and can be STYLE_SOLID
, STYLE_DASHED
,
+ * STYLE_BEVELED
, STYLE_INSET
and
+ * STYLE_UNDERLINE
.
+ * @param borderStyle the border style
+ */
+ public void setBorderStyle(int borderStyle) {
+ this.borderStyle = borderStyle;
+ }
+
+ /** Gets the border color.
+ * @return the border color
+ */
+ public Color getBorderColor() {
+ return this.borderColor;
+ }
+
+ /** Sets the border color. Set to null
to remove
+ * the border.
+ * @param borderColor the border color
+ */
+ public void setBorderColor(Color borderColor) {
+ this.borderColor = borderColor;
+ }
+
+ /** Gets the background color.
+ * @return the background color
+ */
+ public Color getBackgroundColor() {
+ return this.backgroundColor;
+ }
+
+ /** Sets the background color. Set to null
for
+ * transparent background.
+ * @param backgroundColor the background color
+ */
+ public void setBackgroundColor(Color backgroundColor) {
+ this.backgroundColor = backgroundColor;
+ }
+
+ /** Gets the text color.
+ * @return the text color
+ */
+ public Color getTextColor() {
+ return this.textColor;
+ }
+
+ /** Sets the text color. If null
the color used
+ * will be black.
+ * @param textColor the text color
+ */
+ public void setTextColor(Color textColor) {
+ this.textColor = textColor;
+ }
+
+ /** Gets the text font.
+ * @return the text font
+ */
+ public BaseFont getFont() {
+ return this.font;
+ }
+
+ /** Sets the text font. If null
then Helvetica
+ * will be used.
+ * @param font the text font
+ */
+ public void setFont(BaseFont font) {
+ this.font = font;
+ }
+
+ /** Gets the font size.
+ * @return the font size
+ */
+ public float getFontSize() {
+ return this.fontSize;
+ }
+
+ /** Sets the font size. If 0 then auto-sizing will be used but
+ * only for text fields.
+ * @param fontSize the font size
+ */
+ public void setFontSize(float fontSize) {
+ this.fontSize = fontSize;
+ }
+
+ /** Gets the text horizontal alignment.
+ * @return the text horizontal alignment
+ */
+ public int getAlignment() {
+ return this.alignment;
+ }
+
+ /** Sets the text horizontal alignment. It can be Element.ALIGN_LEFT
,
+ * Element.ALIGN_CENTER
and Element.ALIGN_RIGHT
.
+ * @param alignment the text horizontal alignment
+ */
+ public void setAlignment(int alignment) {
+ this.alignment = alignment;
+ }
+
+ /** Gets the text.
+ * @return the text
+ */
+ public String getText() {
+ return this.text;
+ }
+
+ /** Sets the text for text fields.
+ * @param text the text
+ */
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ /** Gets the field dimension and position.
+ * @return the field dimension and position
+ */
+ public Rectangle getBox() {
+ return this.box;
+ }
+
+ /** Sets the field dimension and position.
+ * @param box the field dimension and position
+ */
+ public void setBox(Rectangle box) {
+ this.box = box;
+ }
+
+ /** Gets the field rotation.
+ * @return the field rotation
+ */
+ public int getRotation() {
+ return this.rotation;
+ }
+
+ /** Sets the field rotation. This value should be the same as
+ * the page rotation where the field will be shown.
+ * @param rotation the field rotation
+ */
+ public void setRotation(int rotation) {
+ if (rotation % 90 != 0)
+ throw new IllegalArgumentException("Rotation must be a multiple of 90.");
+ rotation %= 360;
+ if (rotation < 0)
+ rotation += 360;
+ this.rotation = rotation;
+ }
+
+ /** Convenience method to set the field rotation the same as the
+ * page rotation.
+ * @param page the page
+ */
+ public void setRotationFromPage(Rectangle page) {
+ setRotation(page.getRotation());
+ }
+
+ /** Gets the field visibility flag.
+ * @return the field visibility flag
+ */
+ public int getVisibility() {
+ return this.visibility;
+ }
+
+ /** Sets the field visibility flag. This flags can be one of
+ * VISIBLE
, HIDDEN
, VISIBLE_BUT_DOES_NOT_PRINT
+ * and HIDDEN_BUT_PRINTABLE
.
+ * @param visibility field visibility flag
+ */
+ public void setVisibility(int visibility) {
+ this.visibility = visibility;
+ }
+
+ /** Gets the field name.
+ * @return the field name
+ */
+ public String getFieldName() {
+ return this.fieldName;
+ }
+
+ /** Sets the field name.
+ * @param fieldName the field name. If null
only the widget keys
+ * will be included in the field allowing it to be used as a kid field.
+ */
+ public void setFieldName(String fieldName) {
+ this.fieldName = fieldName;
+ }
+
+ /** Gets the option flags.
+ * @return the option flags
+ */
+ public int getOptions() {
+ return this.options;
+ }
+
+ /** Sets the option flags. The option flags can be a combination by oring of
+ * READ_ONLY
, REQUIRED
,
+ * MULTILINE
, DO_NOT_SCROLL
,
+ * PASSWORD
, FILE_SELECTION
,
+ * DO_NOT_SPELL_CHECK
and EDIT
.
+ * @param options the option flags
+ */
+ public void setOptions(int options) {
+ this.options = options;
+ }
+
+ /** Gets the maximum length of the field's text, in characters.
+ * @return the maximum length of the field's text, in characters.
+ */
+ public int getMaxCharacterLength() {
+ return this.maxCharacterLength;
+ }
+
+ /** Sets the maximum length of the field's text, in characters.
+ * It is only meaningful for text fields.
+ * @param maxCharacterLength the maximum length of the field's text, in characters
+ */
+ public void setMaxCharacterLength(int maxCharacterLength) {
+ this.maxCharacterLength = maxCharacterLength;
+ }
+
+ /**
+ * Getter for property writer.
+ * @return Value of property writer.
+ */
+ public PdfWriter getWriter() {
+ return writer;
+ }
+
+ /**
+ * Setter for property writer.
+ * @param writer New value of property writer.
+ */
+ public void setWriter(PdfWriter writer) {
+ this.writer = writer;
+ }
+
+ /**
+ * Moves the field keys from from
to to
. The moved keys
+ * are removed from from
.
+ * @param from the source
+ * @param to the destination. It may be null
+ */
+ public static void moveFields(PdfDictionary from, PdfDictionary to) {
+ for (Iterator i = from.getKeys().iterator(); i.hasNext();) {
+ PdfName key = (PdfName)i.next();
+ if (fieldKeys.containsKey(key)) {
+ if (to != null)
+ to.put(key, from.get(key));
+ i.remove();
+ }
+ }
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BaseFont.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BaseFont.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BaseFont.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BaseFont.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,1108 @@
+/*
+ * $Id: BaseFont.java,v 1.67 2005/07/26 17:32:39 psoares33 Exp $
+ * $Name: $
+ *
+ * Copyright 2000, 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import java.io.*;
+import pdftk.com.lowagie.text.DocumentException;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * Base class for the several font types supported
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+
+public abstract class BaseFont {
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String COURIER = "Courier";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String COURIER_BOLD = "Courier-Bold";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String COURIER_OBLIQUE = "Courier-Oblique";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String COURIER_BOLDOBLIQUE = "Courier-BoldOblique";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String HELVETICA = "Helvetica";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String HELVETICA_BOLD = "Helvetica-Bold";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String HELVETICA_OBLIQUE = "Helvetica-Oblique";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String HELVETICA_BOLDOBLIQUE = "Helvetica-BoldOblique";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String SYMBOL = "Symbol";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String TIMES_ROMAN = "Times-Roman";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String TIMES_BOLD = "Times-Bold";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String TIMES_ITALIC = "Times-Italic";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String TIMES_BOLDITALIC = "Times-BoldItalic";
+
+ /** This is a possible value of a base 14 type 1 font */
+ public static final String ZAPFDINGBATS = "ZapfDingbats";
+
+ /** The maximum height above the baseline reached by glyphs in this
+ * font, excluding the height of glyphs for accented characters.
+ */
+ public static final int ASCENT = 1;
+ /** The y coordinate of the top of flat capital letters, measured from
+ * the baseline.
+ */
+ public static final int CAPHEIGHT = 2;
+ /** The maximum depth below the baseline reached by glyphs in this
+ * font. The value is a negative number.
+ */
+ public static final int DESCENT = 3;
+ /** The angle, expressed in degrees counterclockwise from the vertical,
+ * of the dominant vertical strokes of the font. The value is
+ * negative for fonts that slope to the right, as almost all italic fonts do.
+ */
+ public static final int ITALICANGLE = 4;
+ /** The lower left x glyph coordinate.
+ */
+ public static final int BBOXLLX = 5;
+ /** The lower left y glyph coordinate.
+ */
+ public static final int BBOXLLY = 6;
+ /** The upper right x glyph coordinate.
+ */
+ public static final int BBOXURX = 7;
+ /** The upper right y glyph coordinate.
+ */
+ public static final int BBOXURY = 8;
+
+ /** java.awt.Font property */
+ public static final int AWT_ASCENT = 9;
+ /** java.awt.Font property */
+ public static final int AWT_DESCENT = 10;
+ /** java.awt.Font property */
+ public static final int AWT_LEADING = 11;
+ /** java.awt.Font property */
+ public static final int AWT_MAXADVANCE = 12;
+
+ /** The font is Type 1.
+ */
+ public static final int FONT_TYPE_T1 = 0;
+ /** The font is True Type with a standard encoding.
+ */
+ public static final int FONT_TYPE_TT = 1;
+ /** The font is CJK.
+ */
+ public static final int FONT_TYPE_CJK = 2;
+ /** The font is True Type with a Unicode encoding.
+ */
+ public static final int FONT_TYPE_TTUNI = 3;
+ /** A font already inside the document.
+ */
+ public static final int FONT_TYPE_DOCUMENT = 4;
+ /** A Type3 font.
+ */
+ public static final int FONT_TYPE_T3 = 5;
+ /** The Unicode encoding with horizontal writing.
+ */
+ public static final String IDENTITY_H = "Identity-H";
+ /** The Unicode encoding with vertical writing.
+ */
+ public static final String IDENTITY_V = "Identity-V";
+
+ /** A possible encoding. */
+ public static final String CP1250 = "Cp1250";
+
+ /** A possible encoding. */
+ public static final String CP1252 = "Cp1252";
+
+ /** A possible encoding. */
+ public static final String CP1257 = "Cp1257";
+
+ /** A possible encoding. */
+ public static final String WINANSI = "Cp1252";
+
+ /** A possible encoding. */
+ public static final String MACROMAN = "MacRoman";
+
+
+/** if the font has to be embedded */
+ public static final boolean EMBEDDED = true;
+
+/** if the font doesn't have to be embedded */
+ public static final boolean NOT_EMBEDDED = false;
+/** if the font has to be cached */
+ public static final boolean CACHED = true;
+/** if the font doesn't have to be cached */
+ public static final boolean NOT_CACHED = false;
+
+ /** The path to the font resources. */
+ public static final String RESOURCE_PATH = "pdftk/com/lowagie/text/pdf/fonts/";
+ /** The fake CID code that represents a newline. */
+ public static final char CID_NEWLINE = '\u7fff';
+
+ /** The font type.
+ */
+ int fontType;
+/** a not defined character in a custom PDF encoding */
+ public static final String notdef = ".notdef";
+
+/** table of characters widths for this encoding */
+ protected int widths[] = new int[256];
+
+/** encoding names */
+ protected String differences[] = new String[256];
+/** same as differences but with the unicode codes */
+ protected char unicodeDifferences[] = new char[256];
+
+ protected int charBBoxes[][] = new int[256][];
+/** encoding used with this font */
+ protected String encoding;
+
+/** true if the font is to be embedded in the PDF */
+ protected boolean embedded;
+
+/**
+ * true if the font must use it's built in encoding. In that case the
+ * encoding
is only used to map a char to the position inside
+ * the font, not to the expected char name.
+ */
+ protected boolean fontSpecific = true;
+
+/** cache for the fonts already used. */
+ protected static HashMap fontCache = new HashMap();
+
+/** list of the 14 built in fonts. */
+ protected static final HashMap BuiltinFonts14 = new HashMap();
+
+ /** Forces the output of the width array. Only matters for the 14
+ * built-in fonts.
+ */
+ protected boolean forceWidthsOutput = false;
+
+ /** Converts char
directly to byte
+ * by casting.
+ */
+ protected boolean directTextToByte = false;
+
+ /** Indicates if all the glyphs and widths for that particular
+ * encoding should be included in the document.
+ */
+ protected boolean subset = true;
+
+ protected boolean fastWinansi = false;
+
+ static {
+ BuiltinFonts14.put(COURIER, PdfName.COURIER);
+ BuiltinFonts14.put(COURIER_BOLD, PdfName.COURIER_BOLD);
+ BuiltinFonts14.put(COURIER_BOLDOBLIQUE, PdfName.COURIER_BOLDOBLIQUE);
+ BuiltinFonts14.put(COURIER_OBLIQUE, PdfName.COURIER_OBLIQUE);
+ BuiltinFonts14.put(HELVETICA, PdfName.HELVETICA);
+ BuiltinFonts14.put(HELVETICA_BOLD, PdfName.HELVETICA_BOLD);
+ BuiltinFonts14.put(HELVETICA_BOLDOBLIQUE, PdfName.HELVETICA_BOLDOBLIQUE);
+ BuiltinFonts14.put(HELVETICA_OBLIQUE, PdfName.HELVETICA_OBLIQUE);
+ BuiltinFonts14.put(SYMBOL, PdfName.SYMBOL);
+ BuiltinFonts14.put(TIMES_ROMAN, PdfName.TIMES_ROMAN);
+ BuiltinFonts14.put(TIMES_BOLD, PdfName.TIMES_BOLD);
+ BuiltinFonts14.put(TIMES_BOLDITALIC, PdfName.TIMES_BOLDITALIC);
+ BuiltinFonts14.put(TIMES_ITALIC, PdfName.TIMES_ITALIC);
+ BuiltinFonts14.put(ZAPFDINGBATS, PdfName.ZAPFDINGBATS);
+ }
+
+ /** Generates the PDF stream with the Type1 and Truetype fonts returning
+ * a PdfStream.
+ */
+ static class StreamFont extends PdfStream {
+
+ /** Generates the PDF stream with the Type1 and Truetype fonts returning
+ * a PdfStream.
+ * @param contents the content of the stream
+ * @param lengths an array of int that describes the several lengths of each part of the font
+ * @throws DocumentException error in the stream compression
+ */
+ public StreamFont(byte contents[], int lengths[]) throws DocumentException {
+ try {
+ bytes = contents;
+ put(PdfName.LENGTH, new PdfNumber(bytes.length));
+ for (int k = 0; k < lengths.length; ++k) {
+ put(new PdfName("Length" + (k + 1)), new PdfNumber(lengths[k]));
+ }
+ flateCompress();
+ }
+ catch (Exception e) {
+ throw new DocumentException(e);
+ }
+ }
+
+ /**
+ * Generates the PDF stream for a font.
+ * @param contents the content of a stream
+ * @param subType the subtype of the font.
+ * @throws DocumentException
+ */
+ public StreamFont(byte contents[], String subType) throws DocumentException {
+ try {
+ bytes = contents;
+ put(PdfName.LENGTH, new PdfNumber(bytes.length));
+ if (subType != null)
+ put(PdfName.SUBTYPE, new PdfName(subType));
+ flateCompress();
+ }
+ catch (Exception e) {
+ throw new DocumentException(e);
+ }
+ }
+ }
+
+ /**
+ *Creates new BaseFont
+ */
+ protected BaseFont() {
+ }
+
+ /** Creates a new font. This font can be one of the 14 built in types,
+ * a Type1 font referred by an AFM file, a TrueType font (simple or collection) or a CJK font from the
+ * Adobe Asian Font Pack. TrueType fonts and CJK fonts can have an optional style modifier
+ * appended to the name. These modifiers are: Bold, Italic and BoldItalic. An
+ * example would be "STSong-Light,Bold". Note that this modifiers do not work if
+ * the font is embedded. Fonts in TrueType collections are addressed by index such as "msgothic.ttc,1".
+ * This would get the second font (indexes start at 0), in this case "MS PGothic".
+ *
+ * The fonts are cached and if they already exist they are extracted from the cache,
+ * not parsed again.
+ *
+ * This method calls:
+ *
+ * createFont(name, encoding, embedded, true, null, null);
+ *
+ * @param name the name of the font or it's location on file
+ * @param encoding the encoding to be applied to this font
+ * @param embedded true if the font is to be embedded in the PDF
+ * @return returns a new font. This font may come from the cache
+ * @throws DocumentException the font is invalid
+ * @throws IOException the font file could not be read
+ */
+ public static BaseFont createFont(String name, String encoding, boolean embedded) throws DocumentException, IOException {
+ return createFont(name, encoding, embedded, true, null, null);
+ }
+
+ /** Creates a new font. This font can be one of the 14 built in types,
+ * a Type1 font referred by an AFM file, a TrueType font (simple or collection) or a CJK font from the
+ * Adobe Asian Font Pack. TrueType fonts and CJK fonts can have an optional style modifier
+ * appended to the name. These modifiers are: Bold, Italic and BoldItalic. An
+ * example would be "STSong-Light,Bold". Note that this modifiers do not work if
+ * the font is embedded. Fonts in TrueType collections are addressed by index such as "msgothic.ttc,1".
+ * This would get the second font (indexes start at 0), in this case "MS PGothic".
+ *
+ * The fonts may or may not be cached depending on the flag cached
.
+ * If the byte
arrays are present the font will be
+ * read from them instead of the name. The name is still required to identify
+ * the font type.
+ * @param name the name of the font or it's location on file
+ * @param encoding the encoding to be applied to this font
+ * @param embedded true if the font is to be embedded in the PDF
+ * @param cached true if the font comes from the cache or is added to
+ * the cache if new, false if the font is always created new
+ * @param ttfAfm the true type font or the afm in a byte array
+ * @param pfb the pfb in a byte array
+ * @return returns a new font. This font may come from the cache but only if cached
+ * is true, otherwise it will always be created new
+ * @throws DocumentException the font is invalid
+ * @throws IOException the font file could not be read
+ */
+ public static BaseFont createFont(String name, String encoding, boolean embedded, boolean cached, byte ttfAfm[], byte pfb[]) throws DocumentException, IOException {
+ String nameBase = getBaseName(name);
+ encoding = normalizeEncoding(encoding);
+ boolean isBuiltinFonts14 = BuiltinFonts14.containsKey(name);
+ boolean isCJKFont = isBuiltinFonts14 ? false : CJKFont.isCJKFont(nameBase, encoding);
+ if (isBuiltinFonts14 || isCJKFont)
+ embedded = false;
+ else if (encoding.equals(IDENTITY_H) || encoding.equals(IDENTITY_V))
+ embedded = true;
+ BaseFont fontFound = null;
+ BaseFont fontBuilt = null;
+ String key = name + "\n" + encoding + "\n" + embedded;
+ if (cached) {
+ synchronized (fontCache) {
+ fontFound = (BaseFont)fontCache.get(key);
+ }
+ if (fontFound != null)
+ return fontFound;
+ }
+ if (isBuiltinFonts14 || name.toLowerCase().endsWith(".afm") || name.toLowerCase().endsWith(".pfm")) {
+ fontBuilt = new Type1Font(name, encoding, embedded, ttfAfm, pfb);
+ fontBuilt.fastWinansi = encoding.equals(CP1252);
+ }
+ else if (nameBase.toLowerCase().endsWith(".ttf") || nameBase.toLowerCase().endsWith(".otf") || nameBase.toLowerCase().indexOf(".ttc,") > 0) {
+ if (encoding.equals(IDENTITY_H) || encoding.equals(IDENTITY_V))
+ fontBuilt = new TrueTypeFontUnicode(name, encoding, embedded, ttfAfm);
+ else {
+ fontBuilt = new TrueTypeFont(name, encoding, embedded, ttfAfm);
+ fontBuilt.fastWinansi = encoding.equals(CP1252);
+ }
+ }
+ else if (isCJKFont)
+ fontBuilt = new CJKFont(name, encoding, embedded);
+ else
+ throw new DocumentException("Font '" + name + "' with '" + encoding + "' is not recognized.");
+ if (cached) {
+ synchronized (fontCache) {
+ fontFound = (BaseFont)fontCache.get(key);
+ if (fontFound != null)
+ return fontFound;
+ fontCache.put(key, fontBuilt);
+ }
+ }
+ return fontBuilt;
+ }
+
+ /**
+ * Creates a font based on an existing document font. The created font font may not
+ * behave as expected, depending on the encoding or subset.
+ * @param fontRef the reference to the document font
+ * @return the font
+ */
+ public static BaseFont createFont(PRIndirectReference fontRef) {
+ return new DocumentFont(fontRef);
+ }
+
+ /**
+ * Gets the name without the modifiers Bold, Italic or BoldItalic.
+ * @param name the full name of the font
+ * @return the name without the modifiers Bold, Italic or BoldItalic
+ */
+ protected static String getBaseName(String name) {
+ if (name.endsWith(",Bold"))
+ return name.substring(0, name.length() - 5);
+ else if (name.endsWith(",Italic"))
+ return name.substring(0, name.length() - 7);
+ else if (name.endsWith(",BoldItalic"))
+ return name.substring(0, name.length() - 11);
+ else
+ return name;
+ }
+
+ /**
+ * Normalize the encoding names. "winansi" is changed to "Cp1252" and
+ * "macroman" is changed to "MacRoman".
+ * @param enc the encoding to be normalized
+ * @return the normalized encoding
+ */
+ protected static String normalizeEncoding(String enc) {
+ if (enc.equals("winansi") || enc.equals(""))
+ return CP1252;
+ else if (enc.equals("macroman"))
+ return MACROMAN;
+ else
+ return enc;
+ }
+
+ /**
+ * Creates the widths
and the differences
arrays
+ */
+ protected void createEncoding() {
+ if (fontSpecific) {
+ for (int k = 0; k < 256; ++k) {
+ widths[k] = getRawWidth(k, null);
+ charBBoxes[k] = getRawCharBBox(k, null);
+ }
+ }
+ else {
+ String s;
+ String name;
+ char c;
+ byte b[] = new byte[1];
+ for (int k = 0; k < 256; ++k) {
+ b[0] = (byte)k;
+ s = PdfEncodings.convertToString(b, encoding);
+ if (s.length() > 0) {
+ c = s.charAt(0);
+ }
+ else {
+ c = '?';
+ }
+ name = GlyphList.unicodeToName(c);
+ if (name == null)
+ name = notdef;
+ differences[k] = name;
+ unicodeDifferences[k] = c;
+ widths[k] = getRawWidth(c, name);
+ charBBoxes[k] = getRawCharBBox(c, name);
+ }
+ }
+ }
+
+ /**
+ * Gets the width from the font according to the Unicode char c
+ * or the name
. If the name
is null it's a symbolic font.
+ * @param c the unicode char
+ * @param name the glyph name
+ * @return the width of the char
+ */
+ abstract int getRawWidth(int c, String name);
+
+ /**
+ * Gets the kerning between two Unicode chars.
+ * @param char1 the first char
+ * @param char2 the second char
+ * @return the kerning to be applied in normalized 1000 units
+ */
+ public abstract int getKerning(char char1, char char2);
+
+ /**
+ * Sets the kerning between two Unicode chars.
+ * @param char1 the first char
+ * @param char2 the second char
+ * @param kern the kerning to apply in normalized 1000 units
+ * @return true
if the kerning was applied, false
otherwise
+ */
+ public abstract boolean setKerning(char char1, char char2, int kern);
+
+ /**
+ * Gets the width of a char
in normalized 1000 units.
+ * @param char1 the unicode char
to get the width of
+ * @return the width in normalized 1000 units
+ */
+ public int getWidth(char char1) {
+ if (fastWinansi) {
+ if (char1 < 128 || (char1 >= 160 && char1 <= 255))
+ return widths[char1];
+ return widths[PdfEncodings.winansi.get(char1)];
+ }
+ return getWidth(new String(new char[]{char1}));
+ }
+
+ /**
+ * Gets the width of a String
in normalized 1000 units.
+ * @param text the String
to get the witdth of
+ * @return the width in normalized 1000 units
+ */
+ public int getWidth(String text) {
+ int total = 0;
+ if (fastWinansi) {
+ int len = text.length();
+ for (int k = 0; k < len; ++k) {
+ char char1 = text.charAt(k);
+ if (char1 < 128 || (char1 >= 160 && char1 <= 255))
+ total += widths[char1];
+ else
+ total += widths[PdfEncodings.winansi.get(char1)];
+ }
+ return total;
+ }
+ else {
+ byte mbytes[] = convertToBytes(text);
+ for (int k = 0; k < mbytes.length; ++k)
+ total += widths[0xff & mbytes[k]];
+ }
+ return total;
+ }
+
+/**
+ * Gets the descent of a String
in normalized 1000 units. The descent will always be
+ * less than or equal to zero even if all the characters have an higher descent.
+ * @param text the String
to get the descent of
+ * @return the dexcent in normalized 1000 units
+ */
+ public int getDescent(String text) {
+ int min = 0;
+ char chars[] = text.toCharArray();
+ for (int k = 0; k < chars.length; ++k) {
+ int bbox[] = getCharBBox(chars[k]);
+ if (bbox != null && bbox[1] < min)
+ min = bbox[1];
+ }
+ return min;
+ }
+
+/**
+ * Gets the ascent of a String
in normalized 1000 units. The ascent will always be
+ * greater than or equal to zero even if all the characters have a lower ascent.
+ * @param text the String
to get the ascent of
+ * @return the ascent in normalized 1000 units
+ */
+ public int getAscent(String text) {
+ int max = 0;
+ char chars[] = text.toCharArray();
+ for (int k = 0; k < chars.length; ++k) {
+ int bbox[] = getCharBBox(chars[k]);
+ if (bbox != null && bbox[3] > max)
+ max = bbox[3];
+ }
+ return max;
+ }
+
+/**
+ * Gets the descent of a String
in points. The descent will always be
+ * less than or equal to zero even if all the characters have an higher descent.
+ * @param text the String
to get the descent of
+ * @param fontSize the size of the font
+ * @return the dexcent in points
+ */
+ public float getDescentPoint(String text, float fontSize)
+ {
+ return 0.001f * getDescent(text) * fontSize;
+ }
+
+/**
+ * Gets the ascent of a String
in points. The ascent will always be
+ * greater than or equal to zero even if all the characters have a lower ascent.
+ * @param text the String
to get the ascent of
+ * @param fontSize the size of the font
+ * @return the ascent in points
+ */
+ public float getAscentPoint(String text, float fontSize)
+ {
+ return 0.001f * getAscent(text) * fontSize;
+ }
+// ia>
+
+ /**
+ * Gets the width of a String
in points taking kerning
+ * into account.
+ * @param text the String
to get the witdth of
+ * @param fontSize the font size
+ * @return the width in points
+ */
+ public float getWidthPointKerned(String text, float fontSize) {
+ float size = 0.001f * getWidth(text) * fontSize;
+ if (!hasKernPairs())
+ return size;
+ int len = text.length() - 1;
+ int kern = 0;
+ char c[] = text.toCharArray();
+ for (int k = 0; k < len; ++k) {
+ kern += getKerning(c[k], c[k + 1]);
+ }
+ return size + kern * 0.001f * fontSize;
+ }
+
+ /**
+ * Gets the width of a String
in points.
+ * @param text the String
to get the witdth of
+ * @param fontSize the font size
+ * @return the width in points
+ */
+ public float getWidthPoint(String text, float fontSize) {
+ return 0.001f * getWidth(text) * fontSize;
+ }
+
+ /**
+ * Gets the width of a char
in points.
+ * @param char1 the char
to get the witdth of
+ * @param fontSize the font size
+ * @return the width in points
+ */
+ public float getWidthPoint(char char1, float fontSize) {
+ return getWidth(char1) * 0.001f * fontSize;
+ }
+
+ /**
+ * Converts a String
to a
byte
array according
+ * to the font's encoding.
+ * @param text the String
to be converted
+ * @return an array of byte
representing the conversion according to the font's encoding
+ */
+ byte[] convertToBytes(String text) {
+ if (directTextToByte)
+ return PdfEncodings.convertToBytes(text, null);
+ return PdfEncodings.convertToBytes(text, encoding);
+ }
+
+ /** Outputs to the writer the font dictionaries and streams.
+ * @param writer the writer for this document
+ * @param ref the font indirect reference
+ * @param params several parameters that depend on the font type
+ * @throws IOException on error
+ * @throws DocumentException error in generating the object
+ */
+ abstract void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException;
+
+ /** Gets the encoding used to convert String
into byte[]
.
+ * @return the encoding name
+ */
+ public String getEncoding() {
+ return encoding;
+ }
+
+ /** Gets the font parameter identified by key
. Valid values
+ * for key
are ASCENT
, AWT_ASCENT
, CAPHEIGHT
,
+ * DESCENT
, AWT_DESCENT
,
+ * ITALICANGLE
, BBOXLLX
, BBOXLLY
, BBOXURX
+ * and BBOXURY
.
+ * @param key the parameter to be extracted
+ * @param fontSize the font size in points
+ * @return the parameter in points
+ */
+ public abstract float getFontDescriptor(int key, float fontSize);
+
+ /** Gets the font type. The font types can be: FONT_TYPE_T1,
+ * FONT_TYPE_TT, FONT_TYPE_CJK and FONT_TYPE_TTUNI.
+ * @return the font type
+ */
+ public int getFontType() {
+ return fontType;
+ }
+
+ /** Gets the embedded flag.
+ * @return true
if the font is embedded.
+ */
+ public boolean isEmbedded() {
+ return embedded;
+ }
+
+ /** Gets the symbolic flag of the font.
+ * @return true
if the font is symbolic
+ */
+ public boolean isFontSpecific() {
+ return fontSpecific;
+ }
+
+ /** Creates a unique subset prefix to be added to the font name when the font is embedded and subset.
+ * @return the subset prefix
+ */
+ public static String createSubsetPrefix() {
+ String s = "";
+ for (int k = 0; k < 6; ++k)
+ s += (char)(Math.random() * 26 + 'A');
+ return s + "+";
+ }
+
+ /** Gets the Unicode character corresponding to the byte output to the pdf stream.
+ * @param index the byte index
+ * @return the Unicode character
+ */
+ char getUnicodeDifferences(int index) {
+ return unicodeDifferences[index];
+ }
+
+ /** Gets the postscript font name.
+ * @return the postscript font name
+ */
+ public abstract String getPostscriptFontName();
+
+ /**
+ * Sets the font name that will appear in the pdf font dictionary.
+ * Use with care as it can easily make a font unreadable if not embedded.
+ * @param name the new font name
+ */
+ public abstract void setPostscriptFontName(String name);
+
+ /** Gets the full name of the font. If it is a True Type font
+ * each array element will have {Platform ID, Platform Encoding ID,
+ * Language ID, font name}. The interpretation of this values can be
+ * found in the Open Type specification, chapter 2, in the 'name' table.
+ * For the other fonts the array has a single element with {"", "", "",
+ * font name}.
+ * @return the full name of the font
+ */
+ public abstract String[][] getFullFontName();
+
+ /** Gets the full name of the font. If it is a True Type font
+ * each array element will have {Platform ID, Platform Encoding ID,
+ * Language ID, font name}. The interpretation of this values can be
+ * found in the Open Type specification, chapter 2, in the 'name' table.
+ * For the other fonts the array has a single element with {"", "", "",
+ * font name}.
+ * @param name the name of the font
+ * @param encoding the encoding of the font
+ * @param ttfAfm the true type font or the afm in a byte array
+ * @throws DocumentException on error
+ * @throws IOException on error
+ * @return the full name of the font
+ */
+ public static String[][] getFullFontName(String name, String encoding, byte ttfAfm[]) throws DocumentException, IOException {
+ String nameBase = getBaseName(name);
+ BaseFont fontBuilt = null;
+ if (nameBase.toLowerCase().endsWith(".ttf") || nameBase.toLowerCase().endsWith(".otf") || nameBase.toLowerCase().indexOf(".ttc,") > 0)
+ fontBuilt = new TrueTypeFont(name, CP1252, false, ttfAfm, true);
+ else
+ fontBuilt = createFont(name, encoding, false, false, ttfAfm, null);
+ return fontBuilt.getFullFontName();
+ }
+
+ /** Gets all the names from the font. Only the required tables are read.
+ * @param name the name of the font
+ * @param encoding the encoding of the font
+ * @param ttfAfm the true type font or the afm in a byte array
+ * @throws DocumentException on error
+ * @throws IOException on error
+ * @return an array of Object[] built with {getPostscriptFontName(), getFamilyFontName(), getFullFontName()}
+ */
+ public static Object[] getAllFontNames(String name, String encoding, byte ttfAfm[]) throws DocumentException, IOException {
+ String nameBase = getBaseName(name);
+ BaseFont fontBuilt = null;
+ if (nameBase.toLowerCase().endsWith(".ttf") || nameBase.toLowerCase().endsWith(".otf") || nameBase.toLowerCase().indexOf(".ttc,") > 0)
+ fontBuilt = new TrueTypeFont(name, CP1252, false, ttfAfm, true);
+ else
+ fontBuilt = createFont(name, encoding, false, false, ttfAfm, null);
+ return new Object[]{fontBuilt.getPostscriptFontName(), fontBuilt.getFamilyFontName(), fontBuilt.getFullFontName()};
+ }
+
+ /** Gets the family name of the font. If it is a True Type font
+ * each array element will have {Platform ID, Platform Encoding ID,
+ * Language ID, font name}. The interpretation of this values can be
+ * found in the Open Type specification, chapter 2, in the 'name' table.
+ * For the other fonts the array has a single element with {"", "", "",
+ * font name}.
+ * @return the family name of the font
+ */
+ public abstract String[][] getFamilyFontName();
+
+ /** Gets the code pages supported by the font. This has only meaning
+ * with True Type fonts.
+ * @return the code pages supported by the font
+ */
+ public String[] getCodePagesSupported() {
+ return new String[0];
+ }
+
+ /** Enumerates the postscript font names present inside a
+ * True Type Collection.
+ * @param ttcFile the file name of the font
+ * @throws DocumentException on error
+ * @throws IOException on error
+ * @return the postscript font names
+ */
+ public static String[] enumerateTTCNames(String ttcFile) throws DocumentException, IOException {
+ return new EnumerateTTC(ttcFile).getNames();
+ }
+
+ /** Enumerates the postscript font names present inside a
+ * True Type Collection.
+ * @param ttcArray the font as a byte
array
+ * @throws DocumentException on error
+ * @throws IOException on error
+ * @return the postscript font names
+ */
+ public static String[] enumerateTTCNames(byte ttcArray[]) throws DocumentException, IOException {
+ return new EnumerateTTC(ttcArray).getNames();
+ }
+
+ /** Gets the font width array.
+ * @return the font width array
+ */
+ public int[] getWidths() {
+ return widths;
+ }
+
+ /** Gets the array with the names of the characters.
+ * @return the array with the names of the characters
+ */
+ public String[] getDifferences() {
+ return differences;
+ }
+
+ /** Gets the array with the unicode characters.
+ * @return the array with the unicode characters
+ */
+ public char[] getUnicodeDifferences() {
+ return unicodeDifferences;
+ }
+
+ /** Gets the state of the property.
+ * @return value of property forceWidthsOutput
+ */
+ public boolean isForceWidthsOutput() {
+ return forceWidthsOutput;
+ }
+
+ /** Set to true
to force the generation of the
+ * widths array.
+ * @param forceWidthsOutput true
to force the generation of the
+ * widths array
+ */
+ public void setForceWidthsOutput(boolean forceWidthsOutput) {
+ this.forceWidthsOutput = forceWidthsOutput;
+ }
+
+ /** Gets the direct conversion of char
to byte
.
+ * @return value of property directTextToByte.
+ * @see #setDirectTextToByte(boolean directTextToByte)
+ */
+ public boolean isDirectTextToByte() {
+ return directTextToByte;
+ }
+
+ /** Sets the conversion of char
directly to byte
+ * by casting. This is a low level feature to put the bytes directly in
+ * the content stream without passing through String.getBytes().
+ * @param directTextToByte New value of property directTextToByte.
+ */
+ public void setDirectTextToByte(boolean directTextToByte) {
+ this.directTextToByte = directTextToByte;
+ }
+
+ /** Indicates if all the glyphs and widths for that particular
+ * encoding should be included in the document.
+ * @return false
to include all the glyphs and widths.
+ */
+ public boolean isSubset() {
+ return subset;
+ }
+
+ /** Indicates if all the glyphs and widths for that particular
+ * encoding should be included in the document. Set to false
+ * to include all.
+ * @param subset new value of property subset
+ */
+ public void setSubset(boolean subset) {
+ this.subset = subset;
+ }
+
+ /** Gets the font resources.
+ * @param key the full name of the resource
+ * @return the InputStream
to get the resource or
+ * null
if not found
+ */
+ public static InputStream getResourceStream(String key) {
+ return getResourceStream(key, null);
+ }
+
+ /** Gets the font resources.
+ * @param key the full name of the resource
+ * @param loader the ClassLoader to load the resource or null to try the ones available
+ * @return the InputStream
to get the resource or
+ * null
if not found
+ */
+ public static InputStream getResourceStream(String key, ClassLoader loader) {
+ if (key.startsWith("/"))
+ key = key.substring(1);
+ InputStream is = null;
+ if (loader != null) {
+ is = loader.getResourceAsStream(key);
+ if (is != null)
+ return is;
+ }
+ // Try to use Context Class Loader to load the properties file.
+ try {
+ java.lang.reflect.Method getCCL =
+ Thread.class.getMethod("getContextClassLoader", new Class[0]);
+ if (getCCL != null) {
+ ClassLoader contextClassLoader =
+ (ClassLoader)getCCL.invoke(Thread.currentThread(),
+ new Object[0]);
+ if (contextClassLoader != null)
+ is = contextClassLoader.getResourceAsStream(key);
+ }
+ } catch (Throwable e) {}
+
+ if (is == null) {
+ is = BaseFont.class.getResourceAsStream("/" + key);
+ }
+ if (is == null) {
+ is = ClassLoader.getSystemResourceAsStream(key);
+ }
+ return is;
+ }
+
+ /** Gets the Unicode equivalent to a CID.
+ * The (inexistent) CID is translated as '\n'.
+ * It has only meaning with CJK fonts with Identity encoding.
+ * @param c the CID code
+ * @return the Unicode equivalent
+ */
+ public char getUnicodeEquivalent(char c) {
+ return c;
+ }
+
+ /** Gets the CID code given an Unicode.
+ * It has only meaning with CJK fonts.
+ * @param c the Unicode
+ * @return the CID equivalent
+ */
+ public char getCidCode(char c) {
+ return c;
+ }
+
+ /** Checks if the font has any kerning pairs.
+ * @return true
if the font has any kerning pairs
+ */
+ public abstract boolean hasKernPairs();
+
+ /**
+ * Checks if a character exists in this font.
+ * @param c the character to check
+ * @return true
if the character has a glyph,
+ * false
otherwise
+ */
+ public boolean charExists(char c) {
+ byte b[] = convertToBytes(new String(new char[]{c}));
+ return b.length > 0;
+ }
+
+ /**
+ * Sets the character advance.
+ * @param c the character
+ * @param advance the character advance normalized to 1000 units
+ * @return true
if the advance was set,
+ * false
otherwise
+ */
+ public boolean setCharAdvance(char c, int advance) {
+ byte b[] = convertToBytes(new String(new char[]{c}));
+ if (b.length == 0)
+ return false;
+ widths[0xff & b[0]] = advance;
+ return true;
+ }
+
+ private static void addFont(PRIndirectReference fontRef, IntHashtable hits, ArrayList fonts) {
+ PdfObject obj = PdfReader.getPdfObject(fontRef);
+ if (!obj.isDictionary())
+ return;
+ PdfDictionary font = (PdfDictionary)obj;
+ PdfName subtype = (PdfName)PdfReader.getPdfObject(font.get(PdfName.SUBTYPE));
+ if (!PdfName.TYPE1.equals(subtype) && !PdfName.TRUETYPE.equals(subtype))
+ return;
+ PdfName name = (PdfName)PdfReader.getPdfObject(font.get(PdfName.BASEFONT));
+ fonts.add(new Object[]{PdfName.decodeName(name.toString()), fontRef});
+ hits.put(fontRef.getNumber(), 1);
+ }
+
+ private static void recourseFonts(PdfDictionary page, IntHashtable hits, ArrayList fonts, int level) {
+ ++level;
+ if (level > 50) // in case we have an endless loop
+ return;
+ PdfDictionary resources = (PdfDictionary)PdfReader.getPdfObject(page.get(PdfName.RESOURCES));
+ if (resources == null)
+ return;
+ PdfDictionary font = (PdfDictionary)PdfReader.getPdfObject(resources.get(PdfName.FONT));
+ if (font != null) {
+ for (Iterator it = font.getKeys().iterator(); it.hasNext();) {
+ PdfObject ft = font.get((PdfName)it.next());
+ if (ft == null || !ft.isIndirect())
+ continue;
+ int hit = ((PRIndirectReference)ft).getNumber();
+ if (hits.containsKey(hit))
+ continue;
+ addFont((PRIndirectReference)ft, hits, fonts);
+ }
+ }
+ PdfDictionary xobj = (PdfDictionary)PdfReader.getPdfObject(resources.get(PdfName.XOBJECT));
+ if (xobj != null) {
+ for (Iterator it = xobj.getKeys().iterator(); it.hasNext();) {
+ recourseFonts((PdfDictionary)PdfReader.getPdfObject(xobj.get((PdfName)it.next())), hits, fonts, level);
+ }
+ }
+ }
+
+ /**
+ * Gets a list of all document fonts. Each element of the ArrayList
+ * contains a Object[]{String,PRIndirectReference}
with the font name
+ * and the indirect reference to it.
+ * @param reader the document where the fonts are to be listed from
+ * @return the list of fonts and references
+ */
+ public static ArrayList getDocumentFonts(PdfReader reader) {
+ IntHashtable hits = new IntHashtable();
+ ArrayList fonts = new ArrayList();
+ int npages = reader.getNumberOfPages();
+ for (int k = 1; k <= npages; ++k)
+ recourseFonts(reader.getPageN(k), hits, fonts, 1);
+ return fonts;
+ }
+
+ /**
+ * Gets a list of the document fonts in a particular page. Each element of the ArrayList
+ * contains a Object[]{String,PRIndirectReference}
with the font name
+ * and the indirect reference to it.
+ * @param reader the document where the fonts are to be listed from
+ * @param page the page to list the fonts from
+ * @return the list of fonts and references
+ */
+ public static ArrayList getDocumentFonts(PdfReader reader, int page) {
+ IntHashtable hits = new IntHashtable();
+ ArrayList fonts = new ArrayList();
+ recourseFonts(reader.getPageN(page), hits, fonts, 1);
+ return fonts;
+ }
+
+ /**
+ * Gets the smallest box enclosing the character contours. It will return
+ * null
if the font has not the information or the character has no
+ * contours, as in the case of the space, for example. Characters with no contours may
+ * also return [0,0,0,0].
+ * @param c the character to get the contour bounding box from
+ * @return an array of four floats with the bounding box in the format [llx,lly,urx,ury] or
+ * null
+ */
+ public int[] getCharBBox(char c) {
+ byte b[] = convertToBytes(new String(new char[]{c}));
+ if (b.length == 0)
+ return null;
+ else
+ return charBBoxes[b[0] & 0xff];
+ }
+
+ protected abstract int[] getRawCharBBox(int c, String name);
+
+ /**
+ * iText expects Arabic Diactrics (tashkeel) to have zero advance but some fonts,
+ * most notably those that come with Windows, like times.ttf, have non-zero
+ * advance for those characters. This method makes those character to have zero
+ * width advance and work correctly in the iText Arabic shaping and reordering
+ * context.
+ */
+ public void correctArabicAdvance() {
+ for (char c = '\u064b'; c <= '\u0658'; ++c)
+ setCharAdvance(c, 0);
+ setCharAdvance('\u0670', 0);
+ for (char c = '\u06d6'; c <= '\u06dc'; ++c)
+ setCharAdvance(c, 0);
+ for (char c = '\u06df'; c <= '\u06e4'; ++c)
+ setCharAdvance(c, 0);
+ for (char c = '\u06e7'; c <= '\u06e8'; ++c)
+ setCharAdvance(c, 0);
+ for (char c = '\u06ea'; c <= '\u06ed'; ++c)
+ setCharAdvance(c, 0);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BidiLine.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BidiLine.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BidiLine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BidiLine.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,909 @@
+/*
+ *
+ * Copyright 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+
+import pdftk.com.lowagie.text.Chunk;
+
+/** Does all the line bidirectional processing with PdfChunk assembly.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class BidiLine {
+
+ protected int runDirection;
+ protected int pieceSize = 2048;
+ protected char text[] = new char[pieceSize];
+ protected PdfChunk detailChunks[] = new PdfChunk[pieceSize];
+ protected int totalTextLength = 0;
+
+ protected byte orderLevels[] = new byte[pieceSize];
+ protected int indexChars[] = new int[pieceSize];
+
+ protected ArrayList chunks = new ArrayList();
+ protected int indexChunk = 0;
+ protected int indexChunkChar = 0;
+ protected int currentChar = 0;
+
+ protected int storedRunDirection;
+ protected char storedText[] = new char[0];
+ protected PdfChunk storedDetailChunks[] = new PdfChunk[0];
+ protected int storedTotalTextLength = 0;
+
+ protected byte storedOrderLevels[] = new byte[0];
+ protected int storedIndexChars[] = new int[0];
+
+ protected int storedIndexChunk = 0;
+ protected int storedIndexChunkChar = 0;
+ protected int storedCurrentChar = 0;
+
+ protected boolean shortStore;
+// protected ArabicShaping arabic = new ArabicShaping(ArabicShaping.LETTERS_SHAPE | ArabicShaping.LENGTH_GROW_SHRINK | ArabicShaping.TEXT_DIRECTION_LOGICAL);
+ protected static final IntHashtable mirrorChars = new IntHashtable();
+ protected int arabicOptions;
+
+ /** Creates new BidiLine */
+ public BidiLine() {
+ }
+
+ public BidiLine(BidiLine org) {
+ runDirection = org.runDirection;
+ pieceSize = org.pieceSize;
+ text = (char[])org.text.clone();
+ detailChunks = (PdfChunk[])org.detailChunks.clone();
+ totalTextLength = org.totalTextLength;
+
+ orderLevels = (byte[])org.orderLevels.clone();
+ indexChars = (int[])org.indexChars.clone();
+
+ chunks = new ArrayList(org.chunks);
+ indexChunk = org.indexChunk;
+ indexChunkChar = org.indexChunkChar;
+ currentChar = org.currentChar;
+
+ storedRunDirection = org.storedRunDirection;
+ storedText = (char[])org.storedText.clone();
+ storedDetailChunks = (PdfChunk[])org.storedDetailChunks.clone();
+ storedTotalTextLength = org.storedTotalTextLength;
+
+ storedOrderLevels = (byte[])org.storedOrderLevels.clone();
+ storedIndexChars = (int[])org.storedIndexChars.clone();
+
+ storedIndexChunk = org.storedIndexChunk;
+ storedIndexChunkChar = org.storedIndexChunkChar;
+ storedCurrentChar = org.storedCurrentChar;
+
+ shortStore = org.shortStore;
+ arabicOptions = org.arabicOptions;
+ }
+
+ public boolean isEmpty() {
+ return (currentChar >= totalTextLength && indexChunk >= chunks.size());
+ }
+
+ public void clearChunks() {
+ chunks.clear();
+ totalTextLength = 0;
+ currentChar = 0;
+ }
+
+ public boolean getParagraph(int runDirection) {
+ this.runDirection = runDirection;
+ currentChar = 0;
+ totalTextLength = 0;
+ boolean hasText = false;
+ char c;
+ char uniC;
+ BaseFont bf;
+ for (; indexChunk < chunks.size(); ++indexChunk) {
+ PdfChunk ck = (PdfChunk)chunks.get(indexChunk);
+ bf = ck.font().getFont();
+ String s = ck.toString();
+ int len = s.length();
+ for (; indexChunkChar < len; ++indexChunkChar) {
+ c = s.charAt(indexChunkChar);
+ uniC = bf.getUnicodeEquivalent(c);
+ if (uniC == '\r' || uniC == '\n') {
+ // next condition is never true for CID
+ if (uniC == '\r' && indexChunkChar + 1 < len && s.charAt(indexChunkChar + 1) == '\n')
+ ++indexChunkChar;
+ ++indexChunkChar;
+ if (indexChunkChar >= len) {
+ indexChunkChar = 0;
+ ++indexChunk;
+ }
+ hasText = true;
+ if (totalTextLength == 0)
+ detailChunks[0] = ck;
+ break;
+ }
+ addPiece(c, ck);
+ }
+ if (hasText)
+ break;
+ indexChunkChar = 0;
+ }
+ if (totalTextLength == 0)
+ return hasText;
+
+ // remove trailing WS
+ totalTextLength = trimRight(0, totalTextLength - 1) + 1;
+ if (totalTextLength == 0)
+ return true;
+
+ if (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
+ if (orderLevels.length < totalTextLength) {
+ orderLevels = new byte[pieceSize];
+ indexChars = new int[pieceSize];
+ }
+ ArabicLigaturizer.processNumbers(text, 0, totalTextLength, arabicOptions);
+ BidiOrder order = new BidiOrder(text, 0, totalTextLength, (byte)(runDirection == PdfWriter.RUN_DIRECTION_RTL ? 1 : 0));
+ byte od[] = order.getLevels();
+ for (int k = 0; k < totalTextLength; ++k) {
+ orderLevels[k] = od[k];
+ indexChars[k] = k;
+ }
+ doArabicShapping();
+ mirrorGlyphs();
+ }
+ totalTextLength = trimRightEx(0, totalTextLength - 1) + 1;
+ return true;
+ }
+
+ public void addChunk(PdfChunk chunk) {
+ chunks.add(chunk);
+ }
+
+ public void addChunks(ArrayList chunks) {
+ this.chunks.addAll(chunks);
+ }
+
+ public void addPiece(char c, PdfChunk chunk) {
+ if (totalTextLength >= pieceSize) {
+ char tempText[] = text;
+ PdfChunk tempDetailChunks[] = detailChunks;
+ pieceSize *= 2;
+ text = new char[pieceSize];
+ detailChunks = new PdfChunk[pieceSize];
+ System.arraycopy(tempText, 0, text, 0, totalTextLength);
+ System.arraycopy(tempDetailChunks, 0, detailChunks, 0, totalTextLength);
+ }
+ text[totalTextLength] = c;
+ detailChunks[totalTextLength++] = chunk;
+ }
+
+ public void save() {
+ if (indexChunk > 0) {
+ if (indexChunk >= chunks.size())
+ chunks.clear();
+ else {
+ for (--indexChunk; indexChunk >= 0; --indexChunk)
+ chunks.remove(indexChunk);
+ }
+ indexChunk = 0;
+ }
+ storedRunDirection = runDirection;
+ storedTotalTextLength = totalTextLength;
+ storedIndexChunk = indexChunk;
+ storedIndexChunkChar = indexChunkChar;
+ storedCurrentChar = currentChar;
+ shortStore = (currentChar < totalTextLength);
+ if (!shortStore) {
+ // long save
+ if (storedText.length < totalTextLength) {
+ storedText = new char[totalTextLength];
+ storedDetailChunks = new PdfChunk[totalTextLength];
+ }
+ System.arraycopy(text, 0, storedText, 0, totalTextLength);
+ System.arraycopy(detailChunks, 0, storedDetailChunks, 0, totalTextLength);
+ }
+ if (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
+ if (storedOrderLevels.length < totalTextLength) {
+ storedOrderLevels = new byte[totalTextLength];
+ storedIndexChars = new int[totalTextLength];
+ }
+ System.arraycopy(orderLevels, currentChar, storedOrderLevels, currentChar, totalTextLength - currentChar);
+ System.arraycopy(indexChars, currentChar, storedIndexChars, currentChar, totalTextLength - currentChar);
+ }
+ }
+
+ public void restore() {
+ runDirection = storedRunDirection;
+ totalTextLength = storedTotalTextLength;
+ indexChunk = storedIndexChunk;
+ indexChunkChar = storedIndexChunkChar;
+ currentChar = storedCurrentChar;
+ if (!shortStore) {
+ // long restore
+ System.arraycopy(storedText, 0, text, 0, totalTextLength);
+ System.arraycopy(storedDetailChunks, 0, detailChunks, 0, totalTextLength);
+ }
+ if (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
+ System.arraycopy(storedOrderLevels, currentChar, orderLevels, currentChar, totalTextLength - currentChar);
+ System.arraycopy(storedIndexChars, currentChar, indexChars, currentChar, totalTextLength - currentChar);
+ }
+ }
+
+ public void mirrorGlyphs() {
+ for (int k = 0; k < totalTextLength; ++k) {
+ if ((orderLevels[k] & 1) == 1) {
+ int mirror = mirrorChars.get(text[k]);
+ if (mirror != 0)
+ text[k] = (char)mirror;
+ }
+ }
+ }
+
+ public void doArabicShapping() {
+ int src = 0;
+ int dest = 0;
+ for (;;) {
+ while (src < totalTextLength) {
+ char c = text[src];
+ if (c >= 0x0600 && c <= 0x06ff)
+ break;
+ if (src != dest) {
+ text[dest] = text[src];
+ detailChunks[dest] = detailChunks[src];
+ orderLevels[dest] = orderLevels[src];
+ }
+ ++src;
+ ++dest;
+ }
+ if (src >= totalTextLength) {
+ totalTextLength = dest;
+ return;
+ }
+ int startArabicIdx = src;
+ ++src;
+ while (src < totalTextLength) {
+ char c = text[src];
+ if (c < 0x0600 || c > 0x06ff)
+ break;
+ ++src;
+ }
+ int arabicWordSize = src - startArabicIdx;
+ int size = ArabicLigaturizer.arabic_shape(text, startArabicIdx, arabicWordSize, text, dest, arabicWordSize, arabicOptions /*PangoArabicShapping.ar_novowel PangoArabicShapping.ar_lig | PangoArabicShapping.ar_composedtashkeel*/);
+ if (startArabicIdx != dest) {
+ for (int k = 0; k < size; ++k) {
+ detailChunks[dest] = detailChunks[startArabicIdx];
+ orderLevels[dest++] = orderLevels[startArabicIdx++];
+ }
+ }
+ else
+ dest += size;
+ }
+ }
+
+ public PdfLine processLine(float width, int alignment, int runDirection, int arabicOptions) {
+ this.arabicOptions = arabicOptions;
+ save();
+ boolean isRTL = (runDirection == PdfWriter.RUN_DIRECTION_RTL);
+ if (currentChar >= totalTextLength) {
+ boolean hasText = getParagraph(runDirection);
+ if (!hasText)
+ return null;
+ if (totalTextLength == 0) {
+ ArrayList ar = new ArrayList();
+ PdfChunk ck = new PdfChunk("", detailChunks[0]);
+ ar.add(ck);
+ return new PdfLine(0, 0, alignment, true, ar, isRTL);
+ }
+ }
+ float originalWidth = width;
+ int lastSplit = -1;
+ if (currentChar != 0)
+ currentChar = trimLeftEx(currentChar, totalTextLength - 1);
+ int oldCurrentChar = currentChar;
+ char c = 0;
+ char uniC = 0;
+ PdfChunk ck = null;
+ float charWidth = 0;
+ PdfChunk lastValidChunk = null;
+ for (; currentChar < totalTextLength; ++currentChar) {
+ c = text[currentChar];
+ ck = detailChunks[currentChar];
+ uniC = ck.getUnicodeEquivalent(c);
+ if (PdfChunk.noPrint(uniC))
+ continue;
+ charWidth = ck.getCharWidth(c);
+ if (ck.isExtSplitCharacter(oldCurrentChar, currentChar, totalTextLength, text, detailChunks))
+ lastSplit = currentChar;
+ if (width - charWidth < 0)
+ break;
+ width -= charWidth;
+ lastValidChunk = ck;
+ }
+ if (lastValidChunk == null) {
+ // not even a single char fit; must output the first char
+ ++currentChar;
+ return new PdfLine(0, 0, alignment, false, createArrayOfPdfChunks(currentChar - 1, currentChar - 1), isRTL);
+ }
+ if (currentChar >= totalTextLength) {
+ // there was more line than text
+ return new PdfLine(0, width, alignment, true, createArrayOfPdfChunks(oldCurrentChar, totalTextLength - 1), isRTL);
+ }
+ int newCurrentChar = trimRightEx(oldCurrentChar, currentChar - 1);
+ if (newCurrentChar < oldCurrentChar) {
+ // only WS
+ return new PdfLine(0, width, alignment, false, createArrayOfPdfChunks(oldCurrentChar, currentChar - 1), isRTL);
+ }
+ if (newCurrentChar == currentChar - 1) { // middle of word
+ HyphenationEvent he = (HyphenationEvent)lastValidChunk.getAttribute(Chunk.HYPHENATION);
+ if (he != null) {
+ int word[] = getWord(oldCurrentChar, newCurrentChar);
+ if (word != null) {
+ float testWidth = width + getWidth(word[0], currentChar - 1);
+ String pre = he.getHyphenatedWordPre(new String(text, word[0], word[1] - word[0]), lastValidChunk.font().getFont(), lastValidChunk.font().size(), testWidth);
+ String post = he.getHyphenatedWordPost();
+ if (pre.length() > 0) {
+ PdfChunk extra = new PdfChunk(pre, lastValidChunk);
+ currentChar = word[1] - post.length();
+ return new PdfLine(0, testWidth - lastValidChunk.font().width(pre), alignment, false, createArrayOfPdfChunks(oldCurrentChar, word[0] - 1, extra), isRTL);
+ }
+ }
+ }
+ }
+ if (lastSplit == -1 || lastSplit >= newCurrentChar) {
+ // no split point or split point ahead of end
+ return new PdfLine(0, width + getWidth(newCurrentChar + 1, currentChar - 1), alignment, false, createArrayOfPdfChunks(oldCurrentChar, newCurrentChar), isRTL);
+ }
+ // standard split
+ currentChar = lastSplit + 1;
+ newCurrentChar = trimRightEx(oldCurrentChar, lastSplit);
+ if (newCurrentChar < oldCurrentChar) {
+ // only WS again
+ newCurrentChar = currentChar - 1;
+ }
+ return new PdfLine(0, originalWidth - getWidth(oldCurrentChar, newCurrentChar), alignment, false, createArrayOfPdfChunks(oldCurrentChar, newCurrentChar), isRTL);
+ }
+
+ /** Gets the width of a range of characters.
+ * @param startIdx the first index to calculate
+ * @param lastIdx the last inclusive index to calculate
+ * @return the sum of all widths
+ */
+ public float getWidth(int startIdx, int lastIdx) {
+ char c = 0;
+ char uniC;
+ PdfChunk ck = null;
+ float width = 0;
+ for (; startIdx <= lastIdx; ++startIdx) {
+ c = text[startIdx];
+ ck = detailChunks[startIdx];
+ uniC = ck.getUnicodeEquivalent(c);
+ if (PdfChunk.noPrint(uniC))
+ continue;
+ width += detailChunks[startIdx].getCharWidth(c);
+ }
+ return width;
+ }
+
+ public ArrayList createArrayOfPdfChunks(int startIdx, int endIdx) {
+ return createArrayOfPdfChunks(startIdx, endIdx, null);
+ }
+
+ public ArrayList createArrayOfPdfChunks(int startIdx, int endIdx, PdfChunk extraPdfChunk) {
+ boolean bidi = (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL);
+ if (bidi)
+ reorder(startIdx, endIdx);
+ ArrayList ar = new ArrayList();
+ PdfChunk refCk = detailChunks[startIdx];
+ PdfChunk ck = null;
+ StringBuffer buf = new StringBuffer();
+ char c;
+ int idx = 0;
+ for (; startIdx <= endIdx; ++startIdx) {
+ idx = bidi ? indexChars[startIdx] : startIdx;
+ c = text[idx];
+ ck = detailChunks[idx];
+ if (PdfChunk.noPrint(ck.getUnicodeEquivalent(c)))
+ continue;
+ /* ssteward: dropped in 1.44
+ if (ck.isImage()) {
+ if (buf.length() > 0) {
+ ar.add(new PdfChunk(buf.toString(), refCk));
+ buf = new StringBuffer();
+ }
+ ar.add(ck);
+ }
+ else */
+ if (ck == refCk) {
+ buf.append(c);
+ }
+ else {
+ if (buf.length() > 0) {
+ ar.add(new PdfChunk(buf.toString(), refCk));
+ buf = new StringBuffer();
+ }
+ /* ssteward: dropped in 1.44
+ if (!ck.isImage())
+ buf.append(c);
+ refCk = ck;
+ */
+ }
+ }
+ if (buf.length() > 0) {
+ ar.add(new PdfChunk(buf.toString(), refCk));
+ }
+ if (extraPdfChunk != null)
+ ar.add(extraPdfChunk);
+ return ar;
+ }
+
+ public int[] getWord(int startIdx, int idx) {
+ int last = idx;
+ int first = idx;
+ // forward
+ for (; last < totalTextLength; ++last) {
+ if (!Character.isLetter(text[last]))
+ break;
+ }
+ if (last == idx)
+ return null;
+ // backward
+ for (; first >= startIdx; --first) {
+ if (!Character.isLetter(text[first]))
+ break;
+ }
+ ++first;
+ return new int[]{first, last};
+ }
+
+ public int trimRight(int startIdx, int endIdx) {
+ int idx = endIdx;
+ char c;
+ for (; idx >= startIdx; --idx) {
+ c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
+ if (!isWS(c))
+ break;
+ }
+ return idx;
+ }
+
+ public int trimLeft(int startIdx, int endIdx) {
+ int idx = startIdx;
+ char c;
+ for (; idx <= endIdx; ++idx) {
+ c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
+ if (!isWS(c))
+ break;
+ }
+ return idx;
+ }
+
+ public int trimRightEx(int startIdx, int endIdx) {
+ int idx = endIdx;
+ char c = 0;
+ for (; idx >= startIdx; --idx) {
+ c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
+ if (!isWS(c) && !PdfChunk.noPrint(c))
+ break;
+ }
+ return idx;
+ }
+
+ public int trimLeftEx(int startIdx, int endIdx) {
+ int idx = startIdx;
+ char c = 0;
+ for (; idx <= endIdx; ++idx) {
+ c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
+ if (!isWS(c) && !PdfChunk.noPrint(c))
+ break;
+ }
+ return idx;
+ }
+
+ public void reorder(int start, int end) {
+ byte maxLevel = orderLevels[start];
+ byte minLevel = maxLevel;
+ byte onlyOddLevels = maxLevel;
+ byte onlyEvenLevels = maxLevel;
+ for (int k = start + 1; k <= end; ++k) {
+ byte b = orderLevels[k];
+ if (b > maxLevel)
+ maxLevel = b;
+ else if (b < minLevel)
+ minLevel = b;
+ onlyOddLevels &= b;
+ onlyEvenLevels |= b;
+ }
+ if ((onlyEvenLevels & 1) == 0) // nothing to do
+ return;
+ if ((onlyOddLevels & 1) == 1) { // single inversion
+ flip(start, end + 1);
+ return;
+ }
+ minLevel |= 1;
+ for (; maxLevel >= minLevel; --maxLevel) {
+ int pstart = start;
+ for (;;) {
+ for (;pstart <= end; ++pstart) {
+ if (orderLevels[pstart] >= maxLevel)
+ break;
+ }
+ if (pstart > end)
+ break;
+ int pend = pstart + 1;
+ for (; pend <= end; ++pend) {
+ if (orderLevels[pend] < maxLevel)
+ break;
+ }
+ flip(pstart, pend);
+ pstart = pend + 1;
+ }
+ }
+ }
+
+ public void flip(int start, int end) {
+ int mid = (start + end) / 2;
+ --end;
+ for (; start < mid; ++start, --end) {
+ int temp = indexChars[start];
+ indexChars[start] = indexChars[end];
+ indexChars[end] = temp;
+ }
+ }
+
+ public static boolean isWS(char c) {
+ return (c <= ' ');
+ }
+
+ static {
+ mirrorChars.put(0x0028, 0x0029); // LEFT PARENTHESIS
+ mirrorChars.put(0x0029, 0x0028); // RIGHT PARENTHESIS
+ mirrorChars.put(0x003C, 0x003E); // LESS-THAN SIGN
+ mirrorChars.put(0x003E, 0x003C); // GREATER-THAN SIGN
+ mirrorChars.put(0x005B, 0x005D); // LEFT SQUARE BRACKET
+ mirrorChars.put(0x005D, 0x005B); // RIGHT SQUARE BRACKET
+ mirrorChars.put(0x007B, 0x007D); // LEFT CURLY BRACKET
+ mirrorChars.put(0x007D, 0x007B); // RIGHT CURLY BRACKET
+ mirrorChars.put(0x00AB, 0x00BB); // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ mirrorChars.put(0x00BB, 0x00AB); // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+ mirrorChars.put(0x2039, 0x203A); // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+ mirrorChars.put(0x203A, 0x2039); // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+ mirrorChars.put(0x2045, 0x2046); // LEFT SQUARE BRACKET WITH QUILL
+ mirrorChars.put(0x2046, 0x2045); // RIGHT SQUARE BRACKET WITH QUILL
+ mirrorChars.put(0x207D, 0x207E); // SUPERSCRIPT LEFT PARENTHESIS
+ mirrorChars.put(0x207E, 0x207D); // SUPERSCRIPT RIGHT PARENTHESIS
+ mirrorChars.put(0x208D, 0x208E); // SUBSCRIPT LEFT PARENTHESIS
+ mirrorChars.put(0x208E, 0x208D); // SUBSCRIPT RIGHT PARENTHESIS
+ mirrorChars.put(0x2208, 0x220B); // ELEMENT OF
+ mirrorChars.put(0x2209, 0x220C); // NOT AN ELEMENT OF
+ mirrorChars.put(0x220A, 0x220D); // SMALL ELEMENT OF
+ mirrorChars.put(0x220B, 0x2208); // CONTAINS AS MEMBER
+ mirrorChars.put(0x220C, 0x2209); // DOES NOT CONTAIN AS MEMBER
+ mirrorChars.put(0x220D, 0x220A); // SMALL CONTAINS AS MEMBER
+ mirrorChars.put(0x2215, 0x29F5); // DIVISION SLASH
+ mirrorChars.put(0x223C, 0x223D); // TILDE OPERATOR
+ mirrorChars.put(0x223D, 0x223C); // REVERSED TILDE
+ mirrorChars.put(0x2243, 0x22CD); // ASYMPTOTICALLY EQUAL TO
+ mirrorChars.put(0x2252, 0x2253); // APPROXIMATELY EQUAL TO OR THE IMAGE OF
+ mirrorChars.put(0x2253, 0x2252); // IMAGE OF OR APPROXIMATELY EQUAL TO
+ mirrorChars.put(0x2254, 0x2255); // COLON EQUALS
+ mirrorChars.put(0x2255, 0x2254); // EQUALS COLON
+ mirrorChars.put(0x2264, 0x2265); // LESS-THAN OR EQUAL TO
+ mirrorChars.put(0x2265, 0x2264); // GREATER-THAN OR EQUAL TO
+ mirrorChars.put(0x2266, 0x2267); // LESS-THAN OVER EQUAL TO
+ mirrorChars.put(0x2267, 0x2266); // GREATER-THAN OVER EQUAL TO
+ mirrorChars.put(0x2268, 0x2269); // [BEST FIT] LESS-THAN BUT NOT EQUAL TO
+ mirrorChars.put(0x2269, 0x2268); // [BEST FIT] GREATER-THAN BUT NOT EQUAL TO
+ mirrorChars.put(0x226A, 0x226B); // MUCH LESS-THAN
+ mirrorChars.put(0x226B, 0x226A); // MUCH GREATER-THAN
+ mirrorChars.put(0x226E, 0x226F); // [BEST FIT] NOT LESS-THAN
+ mirrorChars.put(0x226F, 0x226E); // [BEST FIT] NOT GREATER-THAN
+ mirrorChars.put(0x2270, 0x2271); // [BEST FIT] NEITHER LESS-THAN NOR EQUAL TO
+ mirrorChars.put(0x2271, 0x2270); // [BEST FIT] NEITHER GREATER-THAN NOR EQUAL TO
+ mirrorChars.put(0x2272, 0x2273); // [BEST FIT] LESS-THAN OR EQUIVALENT TO
+ mirrorChars.put(0x2273, 0x2272); // [BEST FIT] GREATER-THAN OR EQUIVALENT TO
+ mirrorChars.put(0x2274, 0x2275); // [BEST FIT] NEITHER LESS-THAN NOR EQUIVALENT TO
+ mirrorChars.put(0x2275, 0x2274); // [BEST FIT] NEITHER GREATER-THAN NOR EQUIVALENT TO
+ mirrorChars.put(0x2276, 0x2277); // LESS-THAN OR GREATER-THAN
+ mirrorChars.put(0x2277, 0x2276); // GREATER-THAN OR LESS-THAN
+ mirrorChars.put(0x2278, 0x2279); // NEITHER LESS-THAN NOR GREATER-THAN
+ mirrorChars.put(0x2279, 0x2278); // NEITHER GREATER-THAN NOR LESS-THAN
+ mirrorChars.put(0x227A, 0x227B); // PRECEDES
+ mirrorChars.put(0x227B, 0x227A); // SUCCEEDS
+ mirrorChars.put(0x227C, 0x227D); // PRECEDES OR EQUAL TO
+ mirrorChars.put(0x227D, 0x227C); // SUCCEEDS OR EQUAL TO
+ mirrorChars.put(0x227E, 0x227F); // [BEST FIT] PRECEDES OR EQUIVALENT TO
+ mirrorChars.put(0x227F, 0x227E); // [BEST FIT] SUCCEEDS OR EQUIVALENT TO
+ mirrorChars.put(0x2280, 0x2281); // [BEST FIT] DOES NOT PRECEDE
+ mirrorChars.put(0x2281, 0x2280); // [BEST FIT] DOES NOT SUCCEED
+ mirrorChars.put(0x2282, 0x2283); // SUBSET OF
+ mirrorChars.put(0x2283, 0x2282); // SUPERSET OF
+ mirrorChars.put(0x2284, 0x2285); // [BEST FIT] NOT A SUBSET OF
+ mirrorChars.put(0x2285, 0x2284); // [BEST FIT] NOT A SUPERSET OF
+ mirrorChars.put(0x2286, 0x2287); // SUBSET OF OR EQUAL TO
+ mirrorChars.put(0x2287, 0x2286); // SUPERSET OF OR EQUAL TO
+ mirrorChars.put(0x2288, 0x2289); // [BEST FIT] NEITHER A SUBSET OF NOR EQUAL TO
+ mirrorChars.put(0x2289, 0x2288); // [BEST FIT] NEITHER A SUPERSET OF NOR EQUAL TO
+ mirrorChars.put(0x228A, 0x228B); // [BEST FIT] SUBSET OF WITH NOT EQUAL TO
+ mirrorChars.put(0x228B, 0x228A); // [BEST FIT] SUPERSET OF WITH NOT EQUAL TO
+ mirrorChars.put(0x228F, 0x2290); // SQUARE IMAGE OF
+ mirrorChars.put(0x2290, 0x228F); // SQUARE ORIGINAL OF
+ mirrorChars.put(0x2291, 0x2292); // SQUARE IMAGE OF OR EQUAL TO
+ mirrorChars.put(0x2292, 0x2291); // SQUARE ORIGINAL OF OR EQUAL TO
+ mirrorChars.put(0x2298, 0x29B8); // CIRCLED DIVISION SLASH
+ mirrorChars.put(0x22A2, 0x22A3); // RIGHT TACK
+ mirrorChars.put(0x22A3, 0x22A2); // LEFT TACK
+ mirrorChars.put(0x22A6, 0x2ADE); // ASSERTION
+ mirrorChars.put(0x22A8, 0x2AE4); // TRUE
+ mirrorChars.put(0x22A9, 0x2AE3); // FORCES
+ mirrorChars.put(0x22AB, 0x2AE5); // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+ mirrorChars.put(0x22B0, 0x22B1); // PRECEDES UNDER RELATION
+ mirrorChars.put(0x22B1, 0x22B0); // SUCCEEDS UNDER RELATION
+ mirrorChars.put(0x22B2, 0x22B3); // NORMAL SUBGROUP OF
+ mirrorChars.put(0x22B3, 0x22B2); // CONTAINS AS NORMAL SUBGROUP
+ mirrorChars.put(0x22B4, 0x22B5); // NORMAL SUBGROUP OF OR EQUAL TO
+ mirrorChars.put(0x22B5, 0x22B4); // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
+ mirrorChars.put(0x22B6, 0x22B7); // ORIGINAL OF
+ mirrorChars.put(0x22B7, 0x22B6); // IMAGE OF
+ mirrorChars.put(0x22C9, 0x22CA); // LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
+ mirrorChars.put(0x22CA, 0x22C9); // RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
+ mirrorChars.put(0x22CB, 0x22CC); // LEFT SEMIDIRECT PRODUCT
+ mirrorChars.put(0x22CC, 0x22CB); // RIGHT SEMIDIRECT PRODUCT
+ mirrorChars.put(0x22CD, 0x2243); // REVERSED TILDE EQUALS
+ mirrorChars.put(0x22D0, 0x22D1); // DOUBLE SUBSET
+ mirrorChars.put(0x22D1, 0x22D0); // DOUBLE SUPERSET
+ mirrorChars.put(0x22D6, 0x22D7); // LESS-THAN WITH DOT
+ mirrorChars.put(0x22D7, 0x22D6); // GREATER-THAN WITH DOT
+ mirrorChars.put(0x22D8, 0x22D9); // VERY MUCH LESS-THAN
+ mirrorChars.put(0x22D9, 0x22D8); // VERY MUCH GREATER-THAN
+ mirrorChars.put(0x22DA, 0x22DB); // LESS-THAN EQUAL TO OR GREATER-THAN
+ mirrorChars.put(0x22DB, 0x22DA); // GREATER-THAN EQUAL TO OR LESS-THAN
+ mirrorChars.put(0x22DC, 0x22DD); // EQUAL TO OR LESS-THAN
+ mirrorChars.put(0x22DD, 0x22DC); // EQUAL TO OR GREATER-THAN
+ mirrorChars.put(0x22DE, 0x22DF); // EQUAL TO OR PRECEDES
+ mirrorChars.put(0x22DF, 0x22DE); // EQUAL TO OR SUCCEEDS
+ mirrorChars.put(0x22E0, 0x22E1); // [BEST FIT] DOES NOT PRECEDE OR EQUAL
+ mirrorChars.put(0x22E1, 0x22E0); // [BEST FIT] DOES NOT SUCCEED OR EQUAL
+ mirrorChars.put(0x22E2, 0x22E3); // [BEST FIT] NOT SQUARE IMAGE OF OR EQUAL TO
+ mirrorChars.put(0x22E3, 0x22E2); // [BEST FIT] NOT SQUARE ORIGINAL OF OR EQUAL TO
+ mirrorChars.put(0x22E4, 0x22E5); // [BEST FIT] SQUARE IMAGE OF OR NOT EQUAL TO
+ mirrorChars.put(0x22E5, 0x22E4); // [BEST FIT] SQUARE ORIGINAL OF OR NOT EQUAL TO
+ mirrorChars.put(0x22E6, 0x22E7); // [BEST FIT] LESS-THAN BUT NOT EQUIVALENT TO
+ mirrorChars.put(0x22E7, 0x22E6); // [BEST FIT] GREATER-THAN BUT NOT EQUIVALENT TO
+ mirrorChars.put(0x22E8, 0x22E9); // [BEST FIT] PRECEDES BUT NOT EQUIVALENT TO
+ mirrorChars.put(0x22E9, 0x22E8); // [BEST FIT] SUCCEEDS BUT NOT EQUIVALENT TO
+ mirrorChars.put(0x22EA, 0x22EB); // [BEST FIT] NOT NORMAL SUBGROUP OF
+ mirrorChars.put(0x22EB, 0x22EA); // [BEST FIT] DOES NOT CONTAIN AS NORMAL SUBGROUP
+ mirrorChars.put(0x22EC, 0x22ED); // [BEST FIT] NOT NORMAL SUBGROUP OF OR EQUAL TO
+ mirrorChars.put(0x22ED, 0x22EC); // [BEST FIT] DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+ mirrorChars.put(0x22F0, 0x22F1); // UP RIGHT DIAGONAL ELLIPSIS
+ mirrorChars.put(0x22F1, 0x22F0); // DOWN RIGHT DIAGONAL ELLIPSIS
+ mirrorChars.put(0x22F2, 0x22FA); // ELEMENT OF WITH LONG HORIZONTAL STROKE
+ mirrorChars.put(0x22F3, 0x22FB); // ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+ mirrorChars.put(0x22F4, 0x22FC); // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+ mirrorChars.put(0x22F6, 0x22FD); // ELEMENT OF WITH OVERBAR
+ mirrorChars.put(0x22F7, 0x22FE); // SMALL ELEMENT OF WITH OVERBAR
+ mirrorChars.put(0x22FA, 0x22F2); // CONTAINS WITH LONG HORIZONTAL STROKE
+ mirrorChars.put(0x22FB, 0x22F3); // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+ mirrorChars.put(0x22FC, 0x22F4); // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+ mirrorChars.put(0x22FD, 0x22F6); // CONTAINS WITH OVERBAR
+ mirrorChars.put(0x22FE, 0x22F7); // SMALL CONTAINS WITH OVERBAR
+ mirrorChars.put(0x2308, 0x2309); // LEFT CEILING
+ mirrorChars.put(0x2309, 0x2308); // RIGHT CEILING
+ mirrorChars.put(0x230A, 0x230B); // LEFT FLOOR
+ mirrorChars.put(0x230B, 0x230A); // RIGHT FLOOR
+ mirrorChars.put(0x2329, 0x232A); // LEFT-POINTING ANGLE BRACKET
+ mirrorChars.put(0x232A, 0x2329); // RIGHT-POINTING ANGLE BRACKET
+ mirrorChars.put(0x2768, 0x2769); // MEDIUM LEFT PARENTHESIS ORNAMENT
+ mirrorChars.put(0x2769, 0x2768); // MEDIUM RIGHT PARENTHESIS ORNAMENT
+ mirrorChars.put(0x276A, 0x276B); // MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT
+ mirrorChars.put(0x276B, 0x276A); // MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT
+ mirrorChars.put(0x276C, 0x276D); // MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT
+ mirrorChars.put(0x276D, 0x276C); // MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT
+ mirrorChars.put(0x276E, 0x276F); // HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT
+ mirrorChars.put(0x276F, 0x276E); // HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT
+ mirrorChars.put(0x2770, 0x2771); // HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT
+ mirrorChars.put(0x2771, 0x2770); // HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT
+ mirrorChars.put(0x2772, 0x2773); // LIGHT LEFT TORTOISE SHELL BRACKET
+ mirrorChars.put(0x2773, 0x2772); // LIGHT RIGHT TORTOISE SHELL BRACKET
+ mirrorChars.put(0x2774, 0x2775); // MEDIUM LEFT CURLY BRACKET ORNAMENT
+ mirrorChars.put(0x2775, 0x2774); // MEDIUM RIGHT CURLY BRACKET ORNAMENT
+ mirrorChars.put(0x27D5, 0x27D6); // LEFT OUTER JOIN
+ mirrorChars.put(0x27D6, 0x27D5); // RIGHT OUTER JOIN
+ mirrorChars.put(0x27DD, 0x27DE); // LONG RIGHT TACK
+ mirrorChars.put(0x27DE, 0x27DD); // LONG LEFT TACK
+ mirrorChars.put(0x27E2, 0x27E3); // WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK
+ mirrorChars.put(0x27E3, 0x27E2); // WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK
+ mirrorChars.put(0x27E4, 0x27E5); // WHITE SQUARE WITH LEFTWARDS TICK
+ mirrorChars.put(0x27E5, 0x27E4); // WHITE SQUARE WITH RIGHTWARDS TICK
+ mirrorChars.put(0x27E6, 0x27E7); // MATHEMATICAL LEFT WHITE SQUARE BRACKET
+ mirrorChars.put(0x27E7, 0x27E6); // MATHEMATICAL RIGHT WHITE SQUARE BRACKET
+ mirrorChars.put(0x27E8, 0x27E9); // MATHEMATICAL LEFT ANGLE BRACKET
+ mirrorChars.put(0x27E9, 0x27E8); // MATHEMATICAL RIGHT ANGLE BRACKET
+ mirrorChars.put(0x27EA, 0x27EB); // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
+ mirrorChars.put(0x27EB, 0x27EA); // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
+ mirrorChars.put(0x2983, 0x2984); // LEFT WHITE CURLY BRACKET
+ mirrorChars.put(0x2984, 0x2983); // RIGHT WHITE CURLY BRACKET
+ mirrorChars.put(0x2985, 0x2986); // LEFT WHITE PARENTHESIS
+ mirrorChars.put(0x2986, 0x2985); // RIGHT WHITE PARENTHESIS
+ mirrorChars.put(0x2987, 0x2988); // Z NOTATION LEFT IMAGE BRACKET
+ mirrorChars.put(0x2988, 0x2987); // Z NOTATION RIGHT IMAGE BRACKET
+ mirrorChars.put(0x2989, 0x298A); // Z NOTATION LEFT BINDING BRACKET
+ mirrorChars.put(0x298A, 0x2989); // Z NOTATION RIGHT BINDING BRACKET
+ mirrorChars.put(0x298B, 0x298C); // LEFT SQUARE BRACKET WITH UNDERBAR
+ mirrorChars.put(0x298C, 0x298B); // RIGHT SQUARE BRACKET WITH UNDERBAR
+ mirrorChars.put(0x298D, 0x2990); // LEFT SQUARE BRACKET WITH TICK IN TOP CORNER
+ mirrorChars.put(0x298E, 0x298F); // RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
+ mirrorChars.put(0x298F, 0x298E); // LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
+ mirrorChars.put(0x2990, 0x298D); // RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER
+ mirrorChars.put(0x2991, 0x2992); // LEFT ANGLE BRACKET WITH DOT
+ mirrorChars.put(0x2992, 0x2991); // RIGHT ANGLE BRACKET WITH DOT
+ mirrorChars.put(0x2993, 0x2994); // LEFT ARC LESS-THAN BRACKET
+ mirrorChars.put(0x2994, 0x2993); // RIGHT ARC GREATER-THAN BRACKET
+ mirrorChars.put(0x2995, 0x2996); // DOUBLE LEFT ARC GREATER-THAN BRACKET
+ mirrorChars.put(0x2996, 0x2995); // DOUBLE RIGHT ARC LESS-THAN BRACKET
+ mirrorChars.put(0x2997, 0x2998); // LEFT BLACK TORTOISE SHELL BRACKET
+ mirrorChars.put(0x2998, 0x2997); // RIGHT BLACK TORTOISE SHELL BRACKET
+ mirrorChars.put(0x29B8, 0x2298); // CIRCLED REVERSE SOLIDUS
+ mirrorChars.put(0x29C0, 0x29C1); // CIRCLED LESS-THAN
+ mirrorChars.put(0x29C1, 0x29C0); // CIRCLED GREATER-THAN
+ mirrorChars.put(0x29C4, 0x29C5); // SQUARED RISING DIAGONAL SLASH
+ mirrorChars.put(0x29C5, 0x29C4); // SQUARED FALLING DIAGONAL SLASH
+ mirrorChars.put(0x29CF, 0x29D0); // LEFT TRIANGLE BESIDE VERTICAL BAR
+ mirrorChars.put(0x29D0, 0x29CF); // VERTICAL BAR BESIDE RIGHT TRIANGLE
+ mirrorChars.put(0x29D1, 0x29D2); // BOWTIE WITH LEFT HALF BLACK
+ mirrorChars.put(0x29D2, 0x29D1); // BOWTIE WITH RIGHT HALF BLACK
+ mirrorChars.put(0x29D4, 0x29D5); // TIMES WITH LEFT HALF BLACK
+ mirrorChars.put(0x29D5, 0x29D4); // TIMES WITH RIGHT HALF BLACK
+ mirrorChars.put(0x29D8, 0x29D9); // LEFT WIGGLY FENCE
+ mirrorChars.put(0x29D9, 0x29D8); // RIGHT WIGGLY FENCE
+ mirrorChars.put(0x29DA, 0x29DB); // LEFT DOUBLE WIGGLY FENCE
+ mirrorChars.put(0x29DB, 0x29DA); // RIGHT DOUBLE WIGGLY FENCE
+ mirrorChars.put(0x29F5, 0x2215); // REVERSE SOLIDUS OPERATOR
+ mirrorChars.put(0x29F8, 0x29F9); // BIG SOLIDUS
+ mirrorChars.put(0x29F9, 0x29F8); // BIG REVERSE SOLIDUS
+ mirrorChars.put(0x29FC, 0x29FD); // LEFT-POINTING CURVED ANGLE BRACKET
+ mirrorChars.put(0x29FD, 0x29FC); // RIGHT-POINTING CURVED ANGLE BRACKET
+ mirrorChars.put(0x2A2B, 0x2A2C); // MINUS SIGN WITH FALLING DOTS
+ mirrorChars.put(0x2A2C, 0x2A2B); // MINUS SIGN WITH RISING DOTS
+ mirrorChars.put(0x2A2D, 0x2A2C); // PLUS SIGN IN LEFT HALF CIRCLE
+ mirrorChars.put(0x2A2E, 0x2A2D); // PLUS SIGN IN RIGHT HALF CIRCLE
+ mirrorChars.put(0x2A34, 0x2A35); // MULTIPLICATION SIGN IN LEFT HALF CIRCLE
+ mirrorChars.put(0x2A35, 0x2A34); // MULTIPLICATION SIGN IN RIGHT HALF CIRCLE
+ mirrorChars.put(0x2A3C, 0x2A3D); // INTERIOR PRODUCT
+ mirrorChars.put(0x2A3D, 0x2A3C); // RIGHTHAND INTERIOR PRODUCT
+ mirrorChars.put(0x2A64, 0x2A65); // Z NOTATION DOMAIN ANTIRESTRICTION
+ mirrorChars.put(0x2A65, 0x2A64); // Z NOTATION RANGE ANTIRESTRICTION
+ mirrorChars.put(0x2A79, 0x2A7A); // LESS-THAN WITH CIRCLE INSIDE
+ mirrorChars.put(0x2A7A, 0x2A79); // GREATER-THAN WITH CIRCLE INSIDE
+ mirrorChars.put(0x2A7D, 0x2A7E); // LESS-THAN OR SLANTED EQUAL TO
+ mirrorChars.put(0x2A7E, 0x2A7D); // GREATER-THAN OR SLANTED EQUAL TO
+ mirrorChars.put(0x2A7F, 0x2A80); // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
+ mirrorChars.put(0x2A80, 0x2A7F); // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
+ mirrorChars.put(0x2A81, 0x2A82); // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
+ mirrorChars.put(0x2A82, 0x2A81); // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
+ mirrorChars.put(0x2A83, 0x2A84); // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT
+ mirrorChars.put(0x2A84, 0x2A83); // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT
+ mirrorChars.put(0x2A8B, 0x2A8C); // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN
+ mirrorChars.put(0x2A8C, 0x2A8B); // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
+ mirrorChars.put(0x2A91, 0x2A92); // LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL
+ mirrorChars.put(0x2A92, 0x2A91); // GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL
+ mirrorChars.put(0x2A93, 0x2A94); // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL
+ mirrorChars.put(0x2A94, 0x2A93); // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL
+ mirrorChars.put(0x2A95, 0x2A96); // SLANTED EQUAL TO OR LESS-THAN
+ mirrorChars.put(0x2A96, 0x2A95); // SLANTED EQUAL TO OR GREATER-THAN
+ mirrorChars.put(0x2A97, 0x2A98); // SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE
+ mirrorChars.put(0x2A98, 0x2A97); // SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE
+ mirrorChars.put(0x2A99, 0x2A9A); // DOUBLE-LINE EQUAL TO OR LESS-THAN
+ mirrorChars.put(0x2A9A, 0x2A99); // DOUBLE-LINE EQUAL TO OR GREATER-THAN
+ mirrorChars.put(0x2A9B, 0x2A9C); // DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN
+ mirrorChars.put(0x2A9C, 0x2A9B); // DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN
+ mirrorChars.put(0x2AA1, 0x2AA2); // DOUBLE NESTED LESS-THAN
+ mirrorChars.put(0x2AA2, 0x2AA1); // DOUBLE NESTED GREATER-THAN
+ mirrorChars.put(0x2AA6, 0x2AA7); // LESS-THAN CLOSED BY CURVE
+ mirrorChars.put(0x2AA7, 0x2AA6); // GREATER-THAN CLOSED BY CURVE
+ mirrorChars.put(0x2AA8, 0x2AA9); // LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
+ mirrorChars.put(0x2AA9, 0x2AA8); // GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
+ mirrorChars.put(0x2AAA, 0x2AAB); // SMALLER THAN
+ mirrorChars.put(0x2AAB, 0x2AAA); // LARGER THAN
+ mirrorChars.put(0x2AAC, 0x2AAD); // SMALLER THAN OR EQUAL TO
+ mirrorChars.put(0x2AAD, 0x2AAC); // LARGER THAN OR EQUAL TO
+ mirrorChars.put(0x2AAF, 0x2AB0); // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
+ mirrorChars.put(0x2AB0, 0x2AAF); // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
+ mirrorChars.put(0x2AB3, 0x2AB4); // PRECEDES ABOVE EQUALS SIGN
+ mirrorChars.put(0x2AB4, 0x2AB3); // SUCCEEDS ABOVE EQUALS SIGN
+ mirrorChars.put(0x2ABB, 0x2ABC); // DOUBLE PRECEDES
+ mirrorChars.put(0x2ABC, 0x2ABB); // DOUBLE SUCCEEDS
+ mirrorChars.put(0x2ABD, 0x2ABE); // SUBSET WITH DOT
+ mirrorChars.put(0x2ABE, 0x2ABD); // SUPERSET WITH DOT
+ mirrorChars.put(0x2ABF, 0x2AC0); // SUBSET WITH PLUS SIGN BELOW
+ mirrorChars.put(0x2AC0, 0x2ABF); // SUPERSET WITH PLUS SIGN BELOW
+ mirrorChars.put(0x2AC1, 0x2AC2); // SUBSET WITH MULTIPLICATION SIGN BELOW
+ mirrorChars.put(0x2AC2, 0x2AC1); // SUPERSET WITH MULTIPLICATION SIGN BELOW
+ mirrorChars.put(0x2AC3, 0x2AC4); // SUBSET OF OR EQUAL TO WITH DOT ABOVE
+ mirrorChars.put(0x2AC4, 0x2AC3); // SUPERSET OF OR EQUAL TO WITH DOT ABOVE
+ mirrorChars.put(0x2AC5, 0x2AC6); // SUBSET OF ABOVE EQUALS SIGN
+ mirrorChars.put(0x2AC6, 0x2AC5); // SUPERSET OF ABOVE EQUALS SIGN
+ mirrorChars.put(0x2ACD, 0x2ACE); // SQUARE LEFT OPEN BOX OPERATOR
+ mirrorChars.put(0x2ACE, 0x2ACD); // SQUARE RIGHT OPEN BOX OPERATOR
+ mirrorChars.put(0x2ACF, 0x2AD0); // CLOSED SUBSET
+ mirrorChars.put(0x2AD0, 0x2ACF); // CLOSED SUPERSET
+ mirrorChars.put(0x2AD1, 0x2AD2); // CLOSED SUBSET OR EQUAL TO
+ mirrorChars.put(0x2AD2, 0x2AD1); // CLOSED SUPERSET OR EQUAL TO
+ mirrorChars.put(0x2AD3, 0x2AD4); // SUBSET ABOVE SUPERSET
+ mirrorChars.put(0x2AD4, 0x2AD3); // SUPERSET ABOVE SUBSET
+ mirrorChars.put(0x2AD5, 0x2AD6); // SUBSET ABOVE SUBSET
+ mirrorChars.put(0x2AD6, 0x2AD5); // SUPERSET ABOVE SUPERSET
+ mirrorChars.put(0x2ADE, 0x22A6); // SHORT LEFT TACK
+ mirrorChars.put(0x2AE3, 0x22A9); // DOUBLE VERTICAL BAR LEFT TURNSTILE
+ mirrorChars.put(0x2AE4, 0x22A8); // VERTICAL BAR DOUBLE LEFT TURNSTILE
+ mirrorChars.put(0x2AE5, 0x22AB); // DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE
+ mirrorChars.put(0x2AEC, 0x2AED); // DOUBLE STROKE NOT SIGN
+ mirrorChars.put(0x2AED, 0x2AEC); // REVERSED DOUBLE STROKE NOT SIGN
+ mirrorChars.put(0x2AF7, 0x2AF8); // TRIPLE NESTED LESS-THAN
+ mirrorChars.put(0x2AF8, 0x2AF7); // TRIPLE NESTED GREATER-THAN
+ mirrorChars.put(0x2AF9, 0x2AFA); // DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO
+ mirrorChars.put(0x2AFA, 0x2AF9); // DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO
+ mirrorChars.put(0x3008, 0x3009); // LEFT ANGLE BRACKET
+ mirrorChars.put(0x3009, 0x3008); // RIGHT ANGLE BRACKET
+ mirrorChars.put(0x300A, 0x300B); // LEFT DOUBLE ANGLE BRACKET
+ mirrorChars.put(0x300B, 0x300A); // RIGHT DOUBLE ANGLE BRACKET
+ mirrorChars.put(0x300C, 0x300D); // [BEST FIT] LEFT CORNER BRACKET
+ mirrorChars.put(0x300D, 0x300C); // [BEST FIT] RIGHT CORNER BRACKET
+ mirrorChars.put(0x300E, 0x300F); // [BEST FIT] LEFT WHITE CORNER BRACKET
+ mirrorChars.put(0x300F, 0x300E); // [BEST FIT] RIGHT WHITE CORNER BRACKET
+ mirrorChars.put(0x3010, 0x3011); // LEFT BLACK LENTICULAR BRACKET
+ mirrorChars.put(0x3011, 0x3010); // RIGHT BLACK LENTICULAR BRACKET
+ mirrorChars.put(0x3014, 0x3015); // LEFT TORTOISE SHELL BRACKET
+ mirrorChars.put(0x3015, 0x3014); // RIGHT TORTOISE SHELL BRACKET
+ mirrorChars.put(0x3016, 0x3017); // LEFT WHITE LENTICULAR BRACKET
+ mirrorChars.put(0x3017, 0x3016); // RIGHT WHITE LENTICULAR BRACKET
+ mirrorChars.put(0x3018, 0x3019); // LEFT WHITE TORTOISE SHELL BRACKET
+ mirrorChars.put(0x3019, 0x3018); // RIGHT WHITE TORTOISE SHELL BRACKET
+ mirrorChars.put(0x301A, 0x301B); // LEFT WHITE SQUARE BRACKET
+ mirrorChars.put(0x301B, 0x301A); // RIGHT WHITE SQUARE BRACKET
+ mirrorChars.put(0xFF08, 0xFF09); // FULLWIDTH LEFT PARENTHESIS
+ mirrorChars.put(0xFF09, 0xFF08); // FULLWIDTH RIGHT PARENTHESIS
+ mirrorChars.put(0xFF1C, 0xFF1E); // FULLWIDTH LESS-THAN SIGN
+ mirrorChars.put(0xFF1E, 0xFF1C); // FULLWIDTH GREATER-THAN SIGN
+ mirrorChars.put(0xFF3B, 0xFF3D); // FULLWIDTH LEFT SQUARE BRACKET
+ mirrorChars.put(0xFF3D, 0xFF3B); // FULLWIDTH RIGHT SQUARE BRACKET
+ mirrorChars.put(0xFF5B, 0xFF5D); // FULLWIDTH LEFT CURLY BRACKET
+ mirrorChars.put(0xFF5D, 0xFF5B); // FULLWIDTH RIGHT CURLY BRACKET
+ mirrorChars.put(0xFF5F, 0xFF60); // FULLWIDTH LEFT WHITE PARENTHESIS
+ mirrorChars.put(0xFF60, 0xFF5F); // FULLWIDTH RIGHT WHITE PARENTHESIS
+ mirrorChars.put(0xFF62, 0xFF63); // [BEST FIT] HALFWIDTH LEFT CORNER BRACKET
+ mirrorChars.put(0xFF63, 0xFF62); // [BEST FIT] HALFWIDTH RIGHT CORNER BRACKET
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BidiOrder.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BidiOrder.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/BidiOrder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/BidiOrder.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,1230 @@
+package pdftk.com.lowagie.text.pdf;
+
+/*
+ *
+ * Copyright 2003 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+/*
+ * (C) Copyright IBM Corp. 1999, All Rights Reserved
+ *
+ * version 1.1
+ */
+
+/**
+ * Reference implementation of the Unicode 3.0 Bidi algorithm.
+ *
+ *
+ * This implementation is not optimized for performance. It is intended
+ * as a reference implementation that closely follows the specification
+ * of the Bidirectional Algorithm in The Unicode Standard version 3.0.
+ *
+ * Input:
+ * There are two levels of input to the algorithm, since clients may prefer
+ * to supply some information from out-of-band sources rather than relying on
+ * the default behavior.
+ *
+ * unicode type array
+ * unicode type array, with externally supplied base line direction
+ *
+ * Output:
+ * Output is separated into several stages as well, to better enable clients
+ * to evaluate various aspects of implementation conformance.
+ *
+ * levels array over entire paragraph
+ * reordering array over entire paragraph
+ * levels array over line
+ * reordering array over line
+ *
+ * Note that for conformance, algorithms are only required to generate correct
+ * reordering and character directionality (odd or even levels) over a line.
+ * Generating identical level arrays over a line is not required. Bidi
+ * explicit format codes (LRE, RLE, LRO, RLO, PDF) and BN can be assigned
+ * arbitrary levels and positions as long as the other text matches.
+ *
+ * As the algorithm is defined to operate on a single paragraph at a time,
+ * this implementation is written to handle single paragraphs. Thus
+ * rule P1 is presumed by this implementation-- the data provided to the
+ * implementation is assumed to be a single paragraph, and either contains no
+ * 'B' codes, or a single 'B' code at the end of the input. 'B' is allowed
+ * as input to illustrate how the algorithm assigns it a level.
+ *
+ * Also note that rules L3 and L4 depend on the rendering engine that uses
+ * the result of the bidi algorithm. This implementation assumes that the
+ * rendering engine expects combining marks in visual order (e.g. to the
+ * left of their base character in RTL runs) and that it adjust the glyphs
+ * used to render mirrored characters that are in RTL runs so that they
+ * render appropriately.
+ *
+ * @author Doug Felt
+ */
+
+public final class BidiOrder {
+ private byte[] initialTypes;
+ private byte[] embeddings; // generated from processing format codes
+ private byte paragraphEmbeddingLevel = -1; // undefined
+
+ private int textLength; // for convenience
+ private byte[] resultTypes; // for paragraph, not lines
+ private byte[] resultLevels; // for paragraph, not lines
+
+ // The bidi types
+
+ /** Left-to-right*/
+ public static final byte L = 0;
+
+ /** Left-to-Right Embedding */
+ public static final byte LRE = 1;
+
+ /** Left-to-Right Override */
+ public static final byte LRO = 2;
+
+ /** Right-to-Left */
+ public static final byte R = 3;
+
+ /** Right-to-Left Arabic */
+ public static final byte AL = 4;
+
+ /** Right-to-Left Embedding */
+ public static final byte RLE = 5;
+
+ /** Right-to-Left Override */
+ public static final byte RLO = 6;
+
+ /** Pop Directional Format */
+ public static final byte PDF = 7;
+
+ /** European Number */
+ public static final byte EN = 8;
+
+ /** European Number Separator */
+ public static final byte ES = 9;
+
+ /** European Number Terminator */
+ public static final byte ET = 10;
+
+ /** Arabic Number */
+ public static final byte AN = 11;
+
+ /** Common Number Separator */
+ public static final byte CS = 12;
+
+ /** Non-Spacing Mark */
+ public static final byte NSM = 13;
+
+ /** Boundary Neutral */
+ public static final byte BN = 14;
+
+ /** Paragraph Separator */
+ public static final byte B = 15;
+
+ /** Segment Separator */
+ public static final byte S = 16;
+
+ /** Whitespace */
+ public static final byte WS = 17;
+
+ /** Other Neutrals */
+ public static final byte ON = 18;
+
+ /** Minimum bidi type value. */
+ public static final byte TYPE_MIN = 0;
+
+ /** Maximum bidi type value. */
+ public static final byte TYPE_MAX = 18;
+
+ //
+ // Input
+ //
+
+ /**
+ * Initialize using an array of direction types. Types range from TYPE_MIN to TYPE_MAX inclusive
+ * and represent the direction codes of the characters in the text.
+ *
+ * @param types the types array
+ */
+ public BidiOrder(byte[] types) {
+ validateTypes(types);
+
+ this.initialTypes = (byte[])types.clone(); // client type array remains unchanged
+
+ runAlgorithm();
+ }
+
+ /**
+ * Initialize using an array of direction types and an externally supplied paragraph embedding level.
+ * The embedding level may be -1, 0, or 1. -1 means to apply the default algorithm (rules P2 and P3),
+ * 0 is for LTR paragraphs, and 1 is for RTL paragraphs.
+ *
+ * @param types the types array
+ * @param paragraphEmbeddingLevel the externally supplied paragraph embedding level.
+ */
+ public BidiOrder(byte[] types, byte paragraphEmbeddingLevel) {
+ validateTypes(types);
+ validateParagraphEmbeddingLevel(paragraphEmbeddingLevel);
+
+ this.initialTypes = (byte[])types.clone(); // client type array remains unchanged
+ this.paragraphEmbeddingLevel = paragraphEmbeddingLevel;
+
+ runAlgorithm();
+ }
+
+ public BidiOrder(char text[], int offset, int length, byte paragraphEmbeddingLevel) {
+ initialTypes = new byte[length];
+ for (int k = 0; k < length; ++k) {
+ initialTypes[k] = rtypes[text[offset + k]];
+ }
+ validateParagraphEmbeddingLevel(paragraphEmbeddingLevel);
+
+ this.paragraphEmbeddingLevel = paragraphEmbeddingLevel;
+
+ runAlgorithm();
+ }
+
+ public final static byte getDirection(char c) {
+ return rtypes[c];
+ }
+
+ /**
+ * The algorithm.
+ * Does not include line-based processing (Rules L1, L2).
+ * These are applied later in the line-based phase of the algorithm.
+ */
+ private void runAlgorithm() {
+ textLength = initialTypes.length;
+
+ // Initialize output types.
+ // Result types initialized to input types.
+ resultTypes = (byte[])initialTypes.clone();
+
+
+ // 1) determining the paragraph level
+ // Rule P1 is the requirement for entering this algorithm.
+ // Rules P2, P3.
+ // If no externally supplied paragraph embedding level, use default.
+ if (paragraphEmbeddingLevel == -1) {
+ determineParagraphEmbeddingLevel();
+ }
+
+ // Initialize result levels to paragraph embedding level.
+ resultLevels = new byte[textLength];
+ setLevels(0, textLength, paragraphEmbeddingLevel);
+
+ // 2) Explicit levels and directions
+ // Rules X1-X8.
+ determineExplicitEmbeddingLevels();
+
+ // Rule X9.
+ textLength = removeExplicitCodes();
+
+ // Rule X10.
+ // Run remainder of algorithm one level run at a time
+ byte prevLevel = paragraphEmbeddingLevel;
+ int start = 0;
+ while (start < textLength) {
+ byte level = resultLevels[start];
+ byte prevType = typeForLevel(Math.max(prevLevel, level));
+
+ int limit = start + 1;
+ while (limit < textLength && resultLevels[limit] == level) {
+ ++limit;
+ }
+
+ byte succLevel = limit < textLength ? resultLevels[limit] : paragraphEmbeddingLevel;
+ byte succType = typeForLevel(Math.max(succLevel, level));
+
+ // 3) resolving weak types
+ // Rules W1-W7.
+ resolveWeakTypes(start, limit, level, prevType, succType);
+
+ // 4) resolving neutral types
+ // Rules N1-N3.
+ resolveNeutralTypes(start, limit, level, prevType, succType);
+
+ // 5) resolving implicit embedding levels
+ // Rules I1, I2.
+ resolveImplicitLevels(start, limit, level, prevType, succType);
+
+ prevLevel = level;
+ start = limit;
+ }
+
+ // Reinsert explicit codes and assign appropriate levels to 'hide' them.
+ // This is for convenience, so the resulting level array maps 1-1
+ // with the initial array.
+ // See the implementation suggestions section of TR#9 for guidelines on
+ // how to implement the algorithm without removing and reinserting the codes.
+ textLength = reinsertExplicitCodes(textLength);
+ }
+
+ /**
+ * 1) determining the paragraph level.
+ *
+ * Rules P2, P3.
+ *
+ * At the end of this function, the member variable paragraphEmbeddingLevel is set to either 0 or 1.
+ */
+ private void determineParagraphEmbeddingLevel() {
+ byte strongType = -1; // unknown
+
+ // Rule P2.
+ for (int i = 0; i < textLength; ++i) {
+ byte t = resultTypes[i];
+ if (t == L || t == AL || t == R) {
+ strongType = t;
+ break;
+ }
+ }
+
+ // Rule P3.
+ if (strongType == -1) { // none found
+ // default embedding level when no strong types found is 0.
+ paragraphEmbeddingLevel = 0;
+ } else if (strongType == L) {
+ paragraphEmbeddingLevel = 0;
+ } else { // AL, R
+ paragraphEmbeddingLevel = 1;
+ }
+ }
+
+ /**
+ * Process embedding format codes.
+ *
+ * Calls processEmbeddings to generate an embedding array from the explicit format codes. The
+ * embedding overrides in the array are then applied to the result types, and the result levels are
+ * initialized.
+ * @see #processEmbeddings
+ */
+ private void determineExplicitEmbeddingLevels() {
+ embeddings = processEmbeddings(resultTypes, paragraphEmbeddingLevel);
+
+ for (int i = 0; i < textLength; ++i) {
+ byte level = embeddings[i];
+ if ((level & 0x80) != 0) {
+ level &= 0x7f;
+ resultTypes[i] = typeForLevel(level);
+ }
+ resultLevels[i] = level;
+ }
+ }
+
+ /**
+ * Rules X9.
+ * Remove explicit codes so that they may be ignored during the remainder
+ * of the main portion of the algorithm. The length of the resulting text
+ * is returned.
+ * @return the length of the data excluding explicit codes and BN.
+ */
+ private int removeExplicitCodes() {
+ int w = 0;
+ for (int i = 0; i < textLength; ++i) {
+ byte t = initialTypes[i];
+ if (!(t == LRE || t == RLE || t == LRO || t == RLO || t == PDF || t == BN)) {
+ embeddings[w] = embeddings[i];
+ resultTypes[w] = resultTypes[i];
+ resultLevels[w] = resultLevels[i];
+ w++;
+ }
+ }
+ return w; // new textLength while explicit levels are removed
+ }
+
+ /**
+ * Reinsert levels information for explicit codes.
+ * This is for ease of relating the level information
+ * to the original input data. Note that the levels
+ * assigned to these codes are arbitrary, they're
+ * chosen so as to avoid breaking level runs.
+ * @param textLength the length of the data after compression
+ * @return the length of the data (original length of
+ * types array supplied to constructor)
+ */
+ private int reinsertExplicitCodes(int textLength) {
+ for (int i = initialTypes.length; --i >= 0;) {
+ byte t = initialTypes[i];
+ if (t == LRE || t == RLE || t == LRO || t == RLO || t == PDF || t == BN) {
+ embeddings[i] = 0;
+ resultTypes[i] = t;
+ resultLevels[i] = -1;
+ } else {
+ --textLength;
+ embeddings[i] = embeddings[textLength];
+ resultTypes[i] = resultTypes[textLength];
+ resultLevels[i] = resultLevels[textLength];
+ }
+ }
+
+ // now propagate forward the levels information (could have
+ // propagated backward, the main thing is not to introduce a level
+ // break where one doesn't already exist).
+
+ if (resultLevels[0] == -1) {
+ resultLevels[0] = paragraphEmbeddingLevel;
+ }
+ for (int i = 1; i < initialTypes.length; ++i) {
+ if (resultLevels[i] == -1) {
+ resultLevels[i] = resultLevels[i-1];
+ }
+ }
+
+ // Embedding information is for informational purposes only
+ // so need not be adjusted.
+
+ return initialTypes.length;
+ }
+
+ /**
+ * 2) determining explicit levels
+ * Rules X1 - X8
+ *
+ * The interaction of these rules makes handling them a bit complex.
+ * This examines resultTypes but does not modify it. It returns embedding and
+ * override information in the result array. The low 7 bits are the level, the high
+ * bit is set if the level is an override, and clear if it is an embedding.
+ */
+ private static byte[] processEmbeddings(byte[] resultTypes, byte paragraphEmbeddingLevel) {
+ final int EXPLICIT_LEVEL_LIMIT = 62;
+
+ int textLength = resultTypes.length;
+ byte[] embeddings = new byte[textLength];
+
+ // This stack will store the embedding levels and override status in a single byte
+ // as described above.
+ byte[] embeddingValueStack = new byte[EXPLICIT_LEVEL_LIMIT];
+ int stackCounter = 0;
+
+ // An LRE or LRO at level 60 is invalid, since the new level 62 is invalid. But
+ // an RLE at level 60 is valid, since the new level 61 is valid. The current wording
+ // of the rules requires that the RLE remain valid even if a previous LRE is invalid.
+ // This keeps track of ignored LRE or LRO codes at level 60, so that the matching PDFs
+ // will not try to pop the stack.
+ int overflowAlmostCounter = 0;
+
+ // This keeps track of ignored pushes at level 61 or higher, so that matching PDFs will
+ // not try to pop the stack.
+ int overflowCounter = 0;
+
+ // Rule X1.
+
+ // Keep the level separate from the value (level | override status flag) for ease of access.
+ byte currentEmbeddingLevel = paragraphEmbeddingLevel;
+ byte currentEmbeddingValue = paragraphEmbeddingLevel;
+
+ // Loop through types, handling all remaining rules
+ for (int i = 0; i < textLength; ++i) {
+
+ embeddings[i] = currentEmbeddingValue;
+
+ byte t = resultTypes[i];
+
+ // Rules X2, X3, X4, X5
+ switch (t) {
+ case RLE:
+ case LRE:
+ case RLO:
+ case LRO:
+ // Only need to compute new level if current level is valid
+ if (overflowCounter == 0) {
+ byte newLevel;
+ if (t == RLE || t == RLO) {
+ newLevel = (byte)((currentEmbeddingLevel + 1) | 1); // least greater odd
+ } else { // t == LRE || t == LRO
+ newLevel = (byte)((currentEmbeddingLevel + 2) & ~1); // least greater even
+ }
+
+ // If the new level is valid, push old embedding level and override status
+ // No check for valid stack counter, since the level check suffices.
+ if (newLevel < EXPLICIT_LEVEL_LIMIT) {
+ embeddingValueStack[stackCounter] = currentEmbeddingValue;
+ stackCounter++;
+
+ currentEmbeddingLevel = newLevel;
+ if (t == LRO || t == RLO) { // override
+ currentEmbeddingValue = (byte)(newLevel | 0x80);
+ } else {
+ currentEmbeddingValue = newLevel;
+ }
+
+ // Adjust level of format mark (for expositional purposes only, this gets
+ // removed later).
+ embeddings[i] = currentEmbeddingValue;
+ break;
+ }
+
+ // Otherwise new level is invalid, but a valid level can still be achieved if this
+ // level is 60 and we encounter an RLE or RLO further on. So record that we
+ // 'almost' overflowed.
+ if (currentEmbeddingLevel == 60) {
+ overflowAlmostCounter++;
+ break;
+ }
+ }
+
+ // Otherwise old or new level is invalid.
+ overflowCounter++;
+ break;
+
+ case PDF:
+ // The only case where this did not actually overflow but may have almost overflowed
+ // is when there was an RLE or RLO on level 60, which would result in level 61. So we
+ // only test the almost overflow condition in that case.
+ //
+ // Also note that there may be a PDF without any pushes at all.
+
+ if (overflowCounter > 0) {
+ --overflowCounter;
+ } else if (overflowAlmostCounter > 0 && currentEmbeddingLevel != 61) {
+ --overflowAlmostCounter;
+ } else if (stackCounter > 0) {
+ --stackCounter;
+ currentEmbeddingValue = embeddingValueStack[stackCounter];
+ currentEmbeddingLevel = (byte)(currentEmbeddingValue & 0x7f);
+ }
+ break;
+
+ case B:
+ // Rule X8.
+
+ // These values are reset for clarity, in this implementation B can only
+ // occur as the last code in the array.
+ stackCounter = 0;
+ overflowCounter = 0;
+ overflowAlmostCounter = 0;
+ currentEmbeddingLevel = paragraphEmbeddingLevel;
+ currentEmbeddingValue = paragraphEmbeddingLevel;
+
+ embeddings[i] = paragraphEmbeddingLevel;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return embeddings;
+ }
+
+
+ /**
+ * 3) resolving weak types
+ * Rules W1-W7.
+ *
+ * Note that some weak types (EN, AN) remain after this processing is complete.
+ */
+ private void resolveWeakTypes(int start, int limit, byte level, byte sor, byte eor) {
+
+ // Rule W1.
+ // Changes all NSMs.
+ byte preceedingCharacterType = sor;
+ for (int i = start; i < limit; ++i) {
+ byte t = resultTypes[i];
+ if (t == NSM) {
+ resultTypes[i] = preceedingCharacterType;
+ } else {
+ preceedingCharacterType = t;
+ }
+ }
+
+ // Rule W2.
+ // EN does not change at the start of the run, because sor != AL.
+ for (int i = start; i < limit; ++i) {
+ if (resultTypes[i] == EN) {
+ for (int j = i - 1; j >= start; --j) {
+ byte t = resultTypes[j];
+ if (t == L || t == R || t == AL) {
+ if (t == AL) {
+ resultTypes[i] = AN;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Rule W3.
+ for (int i = start; i < limit; ++i) {
+ if (resultTypes[i] == AL) {
+ resultTypes[i] = R;
+ }
+ }
+
+ // Rule W4.
+ // Since there must be values on both sides for this rule to have an
+ // effect, the scan skips the first and last value.
+ //
+ // Although the scan proceeds left to right, and changes the type values
+ // in a way that would appear to affect the computations later in the scan,
+ // there is actually no problem. A change in the current value can only
+ // affect the value to its immediate right, and only affect it if it is
+ // ES or CS. But the current value can only change if the value to its
+ // right is not ES or CS. Thus either the current value will not change,
+ // or its change will have no effect on the remainder of the analysis.
+
+ for (int i = start + 1; i < limit - 1; ++i) {
+ if (resultTypes[i] == ES || resultTypes[i] == CS) {
+ byte prevSepType = resultTypes[i-1];
+ byte succSepType = resultTypes[i+1];
+ if (prevSepType == EN && succSepType == EN) {
+ resultTypes[i] = EN;
+ } else if (resultTypes[i] == CS && prevSepType == AN && succSepType == AN) {
+ resultTypes[i] = AN;
+ }
+ }
+ }
+
+ // Rule W5.
+ for (int i = start; i < limit; ++i) {
+ if (resultTypes[i] == ET) {
+ // locate end of sequence
+ int runstart = i;
+ int runlimit = findRunLimit(runstart, limit, new byte[] { ET });
+
+ // check values at ends of sequence
+ byte t = runstart == start ? sor : resultTypes[runstart - 1];
+
+ if (t != EN) {
+ t = runlimit == limit ? eor : resultTypes[runlimit];
+ }
+
+ if (t == EN) {
+ setTypes(runstart, runlimit, EN);
+ }
+
+ // continue at end of sequence
+ i = runlimit;
+ }
+ }
+
+ // Rule W6.
+ for (int i = start; i < limit; ++i) {
+ byte t = resultTypes[i];
+ if (t == ES || t == ET || t == CS) {
+ resultTypes[i] = ON;
+ }
+ }
+
+ // Rule W7.
+ for (int i = start; i < limit; ++i) {
+ if (resultTypes[i] == EN) {
+ // set default if we reach start of run
+ byte prevStrongType = sor;
+ for (int j = i - 1; j >= start; --j) {
+ byte t = resultTypes[j];
+ if (t == L || t == R) { // AL's have been removed
+ prevStrongType = t;
+ break;
+ }
+ }
+ if (prevStrongType == L) {
+ resultTypes[i] = L;
+ }
+ }
+ }
+ }
+
+ /**
+ * 6) resolving neutral types
+ * Rules N1-N2.
+ */
+ private void resolveNeutralTypes(int start, int limit, byte level, byte sor, byte eor) {
+
+ for (int i = start; i < limit; ++i) {
+ byte t = resultTypes[i];
+ if (t == WS || t == ON || t == B || t == S) {
+ // find bounds of run of neutrals
+ int runstart = i;
+ int runlimit = findRunLimit(runstart, limit, new byte[] {B, S, WS, ON});
+
+ // determine effective types at ends of run
+ byte leadingType;
+ byte trailingType;
+
+ if (runstart == start) {
+ leadingType = sor;
+ } else {
+ leadingType = resultTypes[runstart - 1];
+ if (leadingType == L || leadingType == R) {
+ // found the strong type
+ } else if (leadingType == AN) {
+ leadingType = R;
+ } else if (leadingType == EN) {
+ // Since EN's with previous strong L types have been changed
+ // to L in W7, the leadingType must be R.
+ leadingType = R;
+ }
+ }
+
+ if (runlimit == limit) {
+ trailingType = eor;
+ } else {
+ trailingType = resultTypes[runlimit];
+ if (trailingType == L || trailingType == R) {
+ // found the strong type
+ } else if (trailingType == AN) {
+ trailingType = R;
+ } else if (trailingType == EN) {
+ trailingType = R;
+ }
+ }
+
+ byte resolvedType;
+ if (leadingType == trailingType) {
+ // Rule N1.
+ resolvedType = leadingType;
+ } else {
+ // Rule N2.
+ // Notice the embedding level of the run is used, not
+ // the paragraph embedding level.
+ resolvedType = typeForLevel(level);
+ }
+
+ setTypes(runstart, runlimit, resolvedType);
+
+ // skip over run of (former) neutrals
+ i = runlimit;
+ }
+ }
+ }
+
+ /**
+ * 7) resolving implicit embedding levels
+ * Rules I1, I2.
+ */
+ private void resolveImplicitLevels(int start, int limit, byte level, byte sor, byte eor) {
+ if ((level & 1) == 0) { // even level
+ for (int i = start; i < limit; ++i) {
+ byte t = resultTypes[i];
+ // Rule I1.
+ if (t == L ) {
+ // no change
+ } else if (t == R) {
+ resultLevels[i] += 1;
+ } else { // t == AN || t == EN
+ resultLevels[i] += 2;
+ }
+ }
+ } else { // odd level
+ for (int i = start; i < limit; ++i) {
+ byte t = resultTypes[i];
+ // Rule I2.
+ if (t == R) {
+ // no change
+ } else { // t == L || t == AN || t == EN
+ resultLevels[i] += 1;
+ }
+ }
+ }
+ }
+
+ //
+ // Output
+ //
+
+ public byte[] getLevels() {
+ return getLevels(new int[]{textLength});
+ }
+
+ /**
+ * Return levels array breaking lines at offsets in linebreaks.
+ * Rule L1.
+ *
+ * The returned levels array contains the resolved level for each
+ * bidi code passed to the constructor.
+ *
+ * The linebreaks array must include at least one value.
+ * The values must be in strictly increasing order (no duplicates)
+ * between 1 and the length of the text, inclusive. The last value
+ * must be the length of the text.
+ *
+ * @param linebreaks the offsets at which to break the paragraph
+ * @return the resolved levels of the text
+ */
+ public byte[] getLevels(int[] linebreaks) {
+
+ // Note that since the previous processing has removed all
+ // P, S, and WS values from resultTypes, the values referred to
+ // in these rules are the initial types, before any processing
+ // has been applied (including processing of overrides).
+ //
+ // This example implementation has reinserted explicit format codes
+ // and BN, in order that the levels array correspond to the
+ // initial text. Their final placement is not normative.
+ // These codes are treated like WS in this implementation,
+ // so they don't interrupt sequences of WS.
+
+ validateLineBreaks(linebreaks, textLength);
+
+ byte[] result = (byte[])resultLevels.clone(); // will be returned to caller
+
+ // don't worry about linebreaks since if there is a break within
+ // a series of WS values preceeding S, the linebreak itself
+ // causes the reset.
+ for (int i = 0; i < result.length; ++i) {
+ byte t = initialTypes[i];
+ if (t == B || t == S) {
+ // Rule L1, clauses one and two.
+ result[i] = paragraphEmbeddingLevel;
+
+ // Rule L1, clause three.
+ for (int j = i - 1; j >= 0; --j) {
+ if (isWhitespace(initialTypes[j])) { // including format codes
+ result[j] = paragraphEmbeddingLevel;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ // Rule L1, clause four.
+ int start = 0;
+ for (int i = 0; i < linebreaks.length; ++i) {
+ int limit = linebreaks[i];
+ for (int j = limit - 1; j >= start; --j) {
+ if (isWhitespace(initialTypes[j])) { // including format codes
+ result[j] = paragraphEmbeddingLevel;
+ } else {
+ break;
+ }
+ }
+
+ start = limit;
+ }
+
+ return result;
+ }
+
+ /**
+ * Return reordering array breaking lines at offsets in linebreaks.
+ *
+ * The reordering array maps from a visual index to a logical index.
+ * Lines are concatenated from left to right. So for example, the
+ * fifth character from the left on the third line is
+ *
getReordering(linebreaks)[linebreaks[1] + 4]
+ * (linebreaks[1] is the position after the last character of the
+ * second line, which is also the index of the first character on the
+ * third line, and adding four gets the fifth character from the left).
+ *
+ * The linebreaks array must include at least one value.
+ * The values must be in strictly increasing order (no duplicates)
+ * between 1 and the length of the text, inclusive. The last value
+ * must be the length of the text.
+ *
+ * @param linebreaks the offsets at which to break the paragraph.
+ */
+ public int[] getReordering(int[] linebreaks) {
+ validateLineBreaks(linebreaks, textLength);
+
+ byte[] levels = getLevels(linebreaks);
+
+ return computeMultilineReordering(levels, linebreaks);
+ }
+
+ /**
+ * Return multiline reordering array for a given level array.
+ * Reordering does not occur across a line break.
+ */
+ private static int[] computeMultilineReordering(byte[] levels, int[] linebreaks) {
+ int[] result = new int[levels.length];
+
+ int start = 0;
+ for (int i = 0; i < linebreaks.length; ++i) {
+ int limit = linebreaks[i];
+
+ byte[] templevels = new byte[limit - start];
+ System.arraycopy(levels, start, templevels, 0, templevels.length);
+
+ int[] temporder = computeReordering(templevels);
+ for (int j = 0; j < temporder.length; ++j) {
+ result[start + j] = temporder[j] + start;
+ }
+
+ start = limit;
+ }
+
+ return result;
+ }
+
+ /**
+ * Return reordering array for a given level array. This reorders a single line.
+ * The reordering is a visual to logical map. For example,
+ * the leftmost char is string.charAt(order[0]).
+ * Rule L2.
+ */
+ private static int[] computeReordering(byte[] levels) {
+ int lineLength = levels.length;
+
+ int[] result = new int[lineLength];
+
+ // initialize order
+ for (int i = 0; i < lineLength; ++i) {
+ result[i] = i;
+ }
+
+ // locate highest level found on line.
+ // Note the rules say text, but no reordering across line bounds is performed,
+ // so this is sufficient.
+ byte highestLevel = 0;
+ byte lowestOddLevel = 63;
+ for (int i = 0; i < lineLength; ++i) {
+ byte level = levels[i];
+ if (level > highestLevel) {
+ highestLevel = level;
+ }
+ if (((level & 1) != 0) && level < lowestOddLevel) {
+ lowestOddLevel = level;
+ }
+ }
+
+ for (int level = highestLevel; level >= lowestOddLevel; --level) {
+ for (int i = 0; i < lineLength; ++i) {
+ if (levels[i] >= level) {
+ // find range of text at or above this level
+ int start = i;
+ int limit = i + 1;
+ while (limit < lineLength && levels[limit] >= level) {
+ ++limit;
+ }
+
+ // reverse run
+ for (int j = start, k = limit - 1; j < k; ++j, --k) {
+ int temp = result[j];
+ result[j] = result[k];
+ result[k] = temp;
+ }
+
+ // skip to end of level run
+ i = limit;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Return the base level of the paragraph.
+ */
+ public byte getBaseLevel() {
+ return paragraphEmbeddingLevel;
+ }
+
+ // --- internal utilities -------------------------------------------------
+
+ /**
+ * Return true if the type is considered a whitespace type for the line break rules.
+ */
+ private static boolean isWhitespace(byte biditype) {
+ switch (biditype) {
+ case LRE:
+ case RLE:
+ case LRO:
+ case RLO:
+ case PDF:
+ case BN:
+ case WS:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Return the strong type (L or R) corresponding to the level.
+ */
+ private static byte typeForLevel(int level) {
+ return ((level & 0x1) == 0) ? L : R;
+ }
+
+ /**
+ * Return the limit of the run starting at index that includes only resultTypes in validSet.
+ * This checks the value at index, and will return index if that value is not in validSet.
+ */
+ private int findRunLimit(int index, int limit, byte[] validSet) {
+ --index;
+ loop:
+ while (++index < limit) {
+ byte t = resultTypes[index];
+ for (int i = 0; i < validSet.length; ++i) {
+ if (t == validSet[i]) {
+ continue loop;
+ }
+ }
+ // didn't find a match in validSet
+ return index;
+ }
+ return limit;
+ }
+
+ /**
+ * Return the start of the run including index that includes only resultTypes in validSet.
+ * This assumes the value at index is valid, and does not check it.
+ */
+ private int findRunStart(int index, byte[] validSet) {
+ loop:
+ while (--index >= 0) {
+ byte t = resultTypes[index];
+ for (int i = 0; i < validSet.length; ++i) {
+ if (t == validSet[i]) {
+ continue loop;
+ }
+ }
+ return index + 1;
+ }
+ return 0;
+ }
+
+ /**
+ * Set resultTypes from start up to (but not including) limit to newType.
+ */
+ private void setTypes(int start, int limit, byte newType) {
+ for (int i = start; i < limit; ++i) {
+ resultTypes[i] = newType;
+ }
+ }
+
+ /**
+ * Set resultLevels from start up to (but not including) limit to newLevel.
+ */
+ private void setLevels(int start, int limit, byte newLevel) {
+ for (int i = start; i < limit; ++i) {
+ resultLevels[i] = newLevel;
+ }
+ }
+
+ // --- input validation ---------------------------------------------------
+
+ /**
+ * Throw exception if type array is invalid.
+ */
+ private static void validateTypes(byte[] types) {
+ if (types == null) {
+ throw new IllegalArgumentException("types is null");
+ }
+ for (int i = 0; i < types.length; ++i) {
+ if (types[i] < TYPE_MIN || types[i] > TYPE_MAX) {
+ throw new IllegalArgumentException("illegal type value at " + i + ": " + types[i]);
+ }
+ }
+ for (int i = 0; i < types.length - 1; ++i) {
+ if (types[i] == B) {
+ throw new IllegalArgumentException("B type before end of paragraph at index: " + i);
+ }
+ }
+ }
+
+ /**
+ * Throw exception if paragraph embedding level is invalid. Special allowance for -1 so that
+ * default processing can still be performed when using this API.
+ */
+ private static void validateParagraphEmbeddingLevel(byte paragraphEmbeddingLevel) {
+ if (paragraphEmbeddingLevel != -1 &&
+ paragraphEmbeddingLevel != 0 &&
+ paragraphEmbeddingLevel != 1) {
+ throw new IllegalArgumentException("illegal paragraph embedding level: " + paragraphEmbeddingLevel);
+ }
+ }
+
+ /**
+ * Throw exception if line breaks array is invalid.
+ */
+ private static void validateLineBreaks(int[] linebreaks, int textLength) {
+ int prev = 0;
+ for (int i = 0; i < linebreaks.length; ++i) {
+ int next = linebreaks[i];
+ if (next <= prev) {
+ throw new IllegalArgumentException("bad linebreak: " + next + " at index: " + i);
+ }
+ prev = next;
+ }
+ if (prev != textLength) {
+ throw new IllegalArgumentException("last linebreak must be at " + textLength);
+ }
+ }
+
+ private static final byte rtypes[] = new byte[0x10000];
+
+ private static char baseTypes[] = {
+ 0, 8, (char)BN, 9, 9, (char)S, 10, 10, (char)B, 11, 11, (char)S, 12, 12, (char)WS, 13, 13, (char)B,
+ 14, 27, (char)BN, 28, 30, (char)B, 31, 31, (char)S, 32, 32, (char)WS, 33, 34, (char)ON, 35, 37, (char)ET,
+ 38, 42, (char)ON, 43, 43, (char)ET, 44, 44, (char)CS, 45, 45, (char)ET, 46, 46, (char)CS, 47, 47, (char)ES,
+ 48, 57, (char)EN, 58, 58, (char)CS, 59, 64, (char)ON, 65, 90, (char)L, 91, 96, (char)ON, 97, 122, (char)L,
+ 123, 126, (char)ON, 127, 132, (char)BN, 133, 133, (char)B, 134, 159, (char)BN, 160, 160, (char)CS,
+ 161, 161, (char)ON, 162, 165, (char)ET, 166, 169, (char)ON, 170, 170, (char)L, 171, 175, (char)ON,
+ 176, 177, (char)ET, 178, 179, (char)EN, 180, 180, (char)ON, 181, 181, (char)L, 182, 184, (char)ON,
+ 185, 185, (char)EN, 186, 186, (char)L, 187, 191, (char)ON, 192, 214, (char)L, 215, 215, (char)ON,
+ 216, 246, (char)L, 247, 247, (char)ON, 248, 696, (char)L, 697, 698, (char)ON, 699, 705, (char)L,
+ 706, 719, (char)ON, 720, 721, (char)L, 722, 735, (char)ON, 736, 740, (char)L, 741, 749, (char)ON,
+ 750, 750, (char)L, 751, 767, (char)ON, 768, 855, (char)NSM, 856, 860, (char)L, 861, 879, (char)NSM,
+ 880, 883, (char)L, 884, 885, (char)ON, 886, 893, (char)L, 894, 894, (char)ON, 895, 899, (char)L,
+ 900, 901, (char)ON, 902, 902, (char)L, 903, 903, (char)ON, 904, 1013, (char)L, 1014, 1014, (char)ON,
+ 1015, 1154, (char)L, 1155, 1158, (char)NSM, 1159, 1159, (char)L, 1160, 1161, (char)NSM,
+ 1162, 1417, (char)L, 1418, 1418, (char)ON, 1419, 1424, (char)L, 1425, 1441, (char)NSM,
+ 1442, 1442, (char)L, 1443, 1465, (char)NSM, 1466, 1466, (char)L, 1467, 1469, (char)NSM,
+ 1470, 1470, (char)R, 1471, 1471, (char)NSM, 1472, 1472, (char)R, 1473, 1474, (char)NSM,
+ 1475, 1475, (char)R, 1476, 1476, (char)NSM, 1477, 1487, (char)L, 1488, 1514, (char)R,
+ 1515, 1519, (char)L, 1520, 1524, (char)R, 1525, 1535, (char)L, 1536, 1539, (char)AL,
+ 1540, 1547, (char)L, 1548, 1548, (char)CS, 1549, 1549, (char)AL, 1550, 1551, (char)ON,
+ 1552, 1557, (char)NSM, 1558, 1562, (char)L, 1563, 1563, (char)AL, 1564, 1566, (char)L,
+ 1567, 1567, (char)AL, 1568, 1568, (char)L, 1569, 1594, (char)AL, 1595, 1599, (char)L,
+ 1600, 1610, (char)AL, 1611, 1624, (char)NSM, 1625, 1631, (char)L, 1632, 1641, (char)AN,
+ 1642, 1642, (char)ET, 1643, 1644, (char)AN, 1645, 1647, (char)AL, 1648, 1648, (char)NSM,
+ 1649, 1749, (char)AL, 1750, 1756, (char)NSM, 1757, 1757, (char)AL, 1758, 1764, (char)NSM,
+ 1765, 1766, (char)AL, 1767, 1768, (char)NSM, 1769, 1769, (char)ON, 1770, 1773, (char)NSM,
+ 1774, 1775, (char)AL, 1776, 1785, (char)EN, 1786, 1805, (char)AL, 1806, 1806, (char)L,
+ 1807, 1807, (char)BN, 1808, 1808, (char)AL, 1809, 1809, (char)NSM, 1810, 1839, (char)AL,
+ 1840, 1866, (char)NSM, 1867, 1868, (char)L, 1869, 1871, (char)AL, 1872, 1919, (char)L,
+ 1920, 1957, (char)AL, 1958, 1968, (char)NSM, 1969, 1969, (char)AL, 1970, 2304, (char)L,
+ 2305, 2306, (char)NSM, 2307, 2363, (char)L, 2364, 2364, (char)NSM, 2365, 2368, (char)L,
+ 2369, 2376, (char)NSM, 2377, 2380, (char)L, 2381, 2381, (char)NSM, 2382, 2384, (char)L,
+ 2385, 2388, (char)NSM, 2389, 2401, (char)L, 2402, 2403, (char)NSM, 2404, 2432, (char)L,
+ 2433, 2433, (char)NSM, 2434, 2491, (char)L, 2492, 2492, (char)NSM, 2493, 2496, (char)L,
+ 2497, 2500, (char)NSM, 2501, 2508, (char)L, 2509, 2509, (char)NSM, 2510, 2529, (char)L,
+ 2530, 2531, (char)NSM, 2532, 2545, (char)L, 2546, 2547, (char)ET, 2548, 2560, (char)L,
+ 2561, 2562, (char)NSM, 2563, 2619, (char)L, 2620, 2620, (char)NSM, 2621, 2624, (char)L,
+ 2625, 2626, (char)NSM, 2627, 2630, (char)L, 2631, 2632, (char)NSM, 2633, 2634, (char)L,
+ 2635, 2637, (char)NSM, 2638, 2671, (char)L, 2672, 2673, (char)NSM, 2674, 2688, (char)L,
+ 2689, 2690, (char)NSM, 2691, 2747, (char)L, 2748, 2748, (char)NSM, 2749, 2752, (char)L,
+ 2753, 2757, (char)NSM, 2758, 2758, (char)L, 2759, 2760, (char)NSM, 2761, 2764, (char)L,
+ 2765, 2765, (char)NSM, 2766, 2785, (char)L, 2786, 2787, (char)NSM, 2788, 2800, (char)L,
+ 2801, 2801, (char)ET, 2802, 2816, (char)L, 2817, 2817, (char)NSM, 2818, 2875, (char)L,
+ 2876, 2876, (char)NSM, 2877, 2878, (char)L, 2879, 2879, (char)NSM, 2880, 2880, (char)L,
+ 2881, 2883, (char)NSM, 2884, 2892, (char)L, 2893, 2893, (char)NSM, 2894, 2901, (char)L,
+ 2902, 2902, (char)NSM, 2903, 2945, (char)L, 2946, 2946, (char)NSM, 2947, 3007, (char)L,
+ 3008, 3008, (char)NSM, 3009, 3020, (char)L, 3021, 3021, (char)NSM, 3022, 3058, (char)L,
+ 3059, 3064, (char)ON, 3065, 3065, (char)ET, 3066, 3066, (char)ON, 3067, 3133, (char)L,
+ 3134, 3136, (char)NSM, 3137, 3141, (char)L, 3142, 3144, (char)NSM, 3145, 3145, (char)L,
+ 3146, 3149, (char)NSM, 3150, 3156, (char)L, 3157, 3158, (char)NSM, 3159, 3259, (char)L,
+ 3260, 3260, (char)NSM, 3261, 3275, (char)L, 3276, 3277, (char)NSM, 3278, 3392, (char)L,
+ 3393, 3395, (char)NSM, 3396, 3404, (char)L, 3405, 3405, (char)NSM, 3406, 3529, (char)L,
+ 3530, 3530, (char)NSM, 3531, 3537, (char)L, 3538, 3540, (char)NSM, 3541, 3541, (char)L,
+ 3542, 3542, (char)NSM, 3543, 3632, (char)L, 3633, 3633, (char)NSM, 3634, 3635, (char)L,
+ 3636, 3642, (char)NSM, 3643, 3646, (char)L, 3647, 3647, (char)ET, 3648, 3654, (char)L,
+ 3655, 3662, (char)NSM, 3663, 3760, (char)L, 3761, 3761, (char)NSM, 3762, 3763, (char)L,
+ 3764, 3769, (char)NSM, 3770, 3770, (char)L, 3771, 3772, (char)NSM, 3773, 3783, (char)L,
+ 3784, 3789, (char)NSM, 3790, 3863, (char)L, 3864, 3865, (char)NSM, 3866, 3892, (char)L,
+ 3893, 3893, (char)NSM, 3894, 3894, (char)L, 3895, 3895, (char)NSM, 3896, 3896, (char)L,
+ 3897, 3897, (char)NSM, 3898, 3901, (char)ON, 3902, 3952, (char)L, 3953, 3966, (char)NSM,
+ 3967, 3967, (char)L, 3968, 3972, (char)NSM, 3973, 3973, (char)L, 3974, 3975, (char)NSM,
+ 3976, 3983, (char)L, 3984, 3991, (char)NSM, 3992, 3992, (char)L, 3993, 4028, (char)NSM,
+ 4029, 4037, (char)L, 4038, 4038, (char)NSM, 4039, 4140, (char)L, 4141, 4144, (char)NSM,
+ 4145, 4145, (char)L, 4146, 4146, (char)NSM, 4147, 4149, (char)L, 4150, 4151, (char)NSM,
+ 4152, 4152, (char)L, 4153, 4153, (char)NSM, 4154, 4183, (char)L, 4184, 4185, (char)NSM,
+ 4186, 5759, (char)L, 5760, 5760, (char)WS, 5761, 5786, (char)L, 5787, 5788, (char)ON,
+ 5789, 5905, (char)L, 5906, 5908, (char)NSM, 5909, 5937, (char)L, 5938, 5940, (char)NSM,
+ 5941, 5969, (char)L, 5970, 5971, (char)NSM, 5972, 6001, (char)L, 6002, 6003, (char)NSM,
+ 6004, 6070, (char)L, 6071, 6077, (char)NSM, 6078, 6085, (char)L, 6086, 6086, (char)NSM,
+ 6087, 6088, (char)L, 6089, 6099, (char)NSM, 6100, 6106, (char)L, 6107, 6107, (char)ET,
+ 6108, 6108, (char)L, 6109, 6109, (char)NSM, 6110, 6127, (char)L, 6128, 6137, (char)ON,
+ 6138, 6143, (char)L, 6144, 6154, (char)ON, 6155, 6157, (char)NSM, 6158, 6158, (char)WS,
+ 6159, 6312, (char)L, 6313, 6313, (char)NSM, 6314, 6431, (char)L, 6432, 6434, (char)NSM,
+ 6435, 6438, (char)L, 6439, 6443, (char)NSM, 6444, 6449, (char)L, 6450, 6450, (char)NSM,
+ 6451, 6456, (char)L, 6457, 6459, (char)NSM, 6460, 6463, (char)L, 6464, 6464, (char)ON,
+ 6465, 6467, (char)L, 6468, 6469, (char)ON, 6470, 6623, (char)L, 6624, 6655, (char)ON,
+ 6656, 8124, (char)L, 8125, 8125, (char)ON, 8126, 8126, (char)L, 8127, 8129, (char)ON,
+ 8130, 8140, (char)L, 8141, 8143, (char)ON, 8144, 8156, (char)L, 8157, 8159, (char)ON,
+ 8160, 8172, (char)L, 8173, 8175, (char)ON, 8176, 8188, (char)L, 8189, 8190, (char)ON,
+ 8191, 8191, (char)L, 8192, 8202, (char)WS, 8203, 8205, (char)BN, 8206, 8206, (char)L,
+ 8207, 8207, (char)R, 8208, 8231, (char)ON, 8232, 8232, (char)WS, 8233, 8233, (char)B,
+ 8234, 8234, (char)LRE, 8235, 8235, (char)RLE, 8236, 8236, (char)PDF, 8237, 8237, (char)LRO,
+ 8238, 8238, (char)RLO, 8239, 8239, (char)WS, 8240, 8244, (char)ET, 8245, 8276, (char)ON,
+ 8277, 8278, (char)L, 8279, 8279, (char)ON, 8280, 8286, (char)L, 8287, 8287, (char)WS,
+ 8288, 8291, (char)BN, 8292, 8297, (char)L, 8298, 8303, (char)BN, 8304, 8304, (char)EN,
+ 8305, 8307, (char)L, 8308, 8313, (char)EN, 8314, 8315, (char)ET, 8316, 8318, (char)ON,
+ 8319, 8319, (char)L, 8320, 8329, (char)EN, 8330, 8331, (char)ET, 8332, 8334, (char)ON,
+ 8335, 8351, (char)L, 8352, 8369, (char)ET, 8370, 8399, (char)L, 8400, 8426, (char)NSM,
+ 8427, 8447, (char)L, 8448, 8449, (char)ON, 8450, 8450, (char)L, 8451, 8454, (char)ON,
+ 8455, 8455, (char)L, 8456, 8457, (char)ON, 8458, 8467, (char)L, 8468, 8468, (char)ON,
+ 8469, 8469, (char)L, 8470, 8472, (char)ON, 8473, 8477, (char)L, 8478, 8483, (char)ON,
+ 8484, 8484, (char)L, 8485, 8485, (char)ON, 8486, 8486, (char)L, 8487, 8487, (char)ON,
+ 8488, 8488, (char)L, 8489, 8489, (char)ON, 8490, 8493, (char)L, 8494, 8494, (char)ET,
+ 8495, 8497, (char)L, 8498, 8498, (char)ON, 8499, 8505, (char)L, 8506, 8507, (char)ON,
+ 8508, 8511, (char)L, 8512, 8516, (char)ON, 8517, 8521, (char)L, 8522, 8523, (char)ON,
+ 8524, 8530, (char)L, 8531, 8543, (char)ON, 8544, 8591, (char)L, 8592, 8721, (char)ON,
+ 8722, 8723, (char)ET, 8724, 9013, (char)ON, 9014, 9082, (char)L, 9083, 9108, (char)ON,
+ 9109, 9109, (char)L, 9110, 9168, (char)ON, 9169, 9215, (char)L, 9216, 9254, (char)ON,
+ 9255, 9279, (char)L, 9280, 9290, (char)ON, 9291, 9311, (char)L, 9312, 9371, (char)EN,
+ 9372, 9449, (char)L, 9450, 9450, (char)EN, 9451, 9751, (char)ON, 9752, 9752, (char)L,
+ 9753, 9853, (char)ON, 9854, 9855, (char)L, 9856, 9873, (char)ON, 9874, 9887, (char)L,
+ 9888, 9889, (char)ON, 9890, 9984, (char)L, 9985, 9988, (char)ON, 9989, 9989, (char)L,
+ 9990, 9993, (char)ON, 9994, 9995, (char)L, 9996, 10023, (char)ON, 10024, 10024, (char)L,
+ 10025, 10059, (char)ON, 10060, 10060, (char)L, 10061, 10061, (char)ON, 10062, 10062, (char)L,
+ 10063, 10066, (char)ON, 10067, 10069, (char)L, 10070, 10070, (char)ON, 10071, 10071, (char)L,
+ 10072, 10078, (char)ON, 10079, 10080, (char)L, 10081, 10132, (char)ON, 10133, 10135, (char)L,
+ 10136, 10159, (char)ON, 10160, 10160, (char)L, 10161, 10174, (char)ON, 10175, 10191, (char)L,
+ 10192, 10219, (char)ON, 10220, 10223, (char)L, 10224, 11021, (char)ON, 11022, 11903, (char)L,
+ 11904, 11929, (char)ON, 11930, 11930, (char)L, 11931, 12019, (char)ON, 12020, 12031, (char)L,
+ 12032, 12245, (char)ON, 12246, 12271, (char)L, 12272, 12283, (char)ON, 12284, 12287, (char)L,
+ 12288, 12288, (char)WS, 12289, 12292, (char)ON, 12293, 12295, (char)L, 12296, 12320, (char)ON,
+ 12321, 12329, (char)L, 12330, 12335, (char)NSM, 12336, 12336, (char)ON, 12337, 12341, (char)L,
+ 12342, 12343, (char)ON, 12344, 12348, (char)L, 12349, 12351, (char)ON, 12352, 12440, (char)L,
+ 12441, 12442, (char)NSM, 12443, 12444, (char)ON, 12445, 12447, (char)L, 12448, 12448, (char)ON,
+ 12449, 12538, (char)L, 12539, 12539, (char)ON, 12540, 12828, (char)L, 12829, 12830, (char)ON,
+ 12831, 12879, (char)L, 12880, 12895, (char)ON, 12896, 12923, (char)L, 12924, 12925, (char)ON,
+ 12926, 12976, (char)L, 12977, 12991, (char)ON, 12992, 13003, (char)L, 13004, 13007, (char)ON,
+ 13008, 13174, (char)L, 13175, 13178, (char)ON, 13179, 13277, (char)L, 13278, 13279, (char)ON,
+ 13280, 13310, (char)L, 13311, 13311, (char)ON, 13312, 19903, (char)L, 19904, 19967, (char)ON,
+ 19968, 42127, (char)L, 42128, 42182, (char)ON, 42183, 64284, (char)L, 64285, 64285, (char)R,
+ 64286, 64286, (char)NSM, 64287, 64296, (char)R, 64297, 64297, (char)ET, 64298, 64310, (char)R,
+ 64311, 64311, (char)L, 64312, 64316, (char)R, 64317, 64317, (char)L, 64318, 64318, (char)R,
+ 64319, 64319, (char)L, 64320, 64321, (char)R, 64322, 64322, (char)L, 64323, 64324, (char)R,
+ 64325, 64325, (char)L, 64326, 64335, (char)R, 64336, 64433, (char)AL, 64434, 64466, (char)L,
+ 64467, 64829, (char)AL, 64830, 64831, (char)ON, 64832, 64847, (char)L, 64848, 64911, (char)AL,
+ 64912, 64913, (char)L, 64914, 64967, (char)AL, 64968, 65007, (char)L, 65008, 65020, (char)AL,
+ 65021, 65021, (char)ON, 65022, 65023, (char)L, 65024, 65039, (char)NSM, 65040, 65055, (char)L,
+ 65056, 65059, (char)NSM, 65060, 65071, (char)L, 65072, 65103, (char)ON, 65104, 65104, (char)CS,
+ 65105, 65105, (char)ON, 65106, 65106, (char)CS, 65107, 65107, (char)L, 65108, 65108, (char)ON,
+ 65109, 65109, (char)CS, 65110, 65118, (char)ON, 65119, 65119, (char)ET, 65120, 65121, (char)ON,
+ 65122, 65123, (char)ET, 65124, 65126, (char)ON, 65127, 65127, (char)L, 65128, 65128, (char)ON,
+ 65129, 65130, (char)ET, 65131, 65131, (char)ON, 65132, 65135, (char)L, 65136, 65140, (char)AL,
+ 65141, 65141, (char)L, 65142, 65276, (char)AL, 65277, 65278, (char)L, 65279, 65279, (char)BN,
+ 65280, 65280, (char)L, 65281, 65282, (char)ON, 65283, 65285, (char)ET, 65286, 65290, (char)ON,
+ 65291, 65291, (char)ET, 65292, 65292, (char)CS, 65293, 65293, (char)ET, 65294, 65294, (char)CS,
+ 65295, 65295, (char)ES, 65296, 65305, (char)EN, 65306, 65306, (char)CS, 65307, 65312, (char)ON,
+ 65313, 65338, (char)L, 65339, 65344, (char)ON, 65345, 65370, (char)L, 65371, 65381, (char)ON,
+ 65382, 65503, (char)L, 65504, 65505, (char)ET, 65506, 65508, (char)ON, 65509, 65510, (char)ET,
+ 65511, 65511, (char)L, 65512, 65518, (char)ON, 65519, 65528, (char)L, 65529, 65531, (char)BN,
+ 65532, 65533, (char)ON, 65534, 65535, (char)L};
+
+ static {
+ for (int k = 0; k < baseTypes.length; ++k) {
+ int start = baseTypes[k];
+ int end = baseTypes[++k];
+ byte b = (byte)baseTypes[++k];
+ while (start <= end)
+ rtypes[start++] = b;
+ }
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ByteBuffer.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ByteBuffer.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ByteBuffer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ByteBuffer.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,587 @@
+/*
+ * $Id: ByteBuffer.java,v 1.34 2002/06/18 13:59:39 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2000, 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import java.io.UnsupportedEncodingException;
+import java.io.OutputStream;
+import java.io.IOException;
+import pdftk.com.lowagie.text.DocWriter;
+
+/**
+ * Acts like a StringBuffer
but works with byte
arrays.
+ * Floating point is converted to a format suitable to the PDF.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+
+public class ByteBuffer extends OutputStream {
+ /** The count of bytes in the buffer. */
+ protected int count;
+
+ /** The buffer where the bytes are stored. */
+ protected byte buf[];
+
+ private static int byteCacheSize = 0;
+
+ private static byte[][] byteCache = new byte[byteCacheSize][];
+ public static byte ZERO = (byte)'0';
+ private static final char[] chars = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
+ private static final byte[] bytes = new byte[] {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102};
+
+ /** Creates new ByteBuffer with capacity 128 */
+ public ByteBuffer() {
+ this(128);
+ }
+
+ /**
+ * Creates a byte buffer with a certain capacity.
+ * @param size the initial capacity
+ */
+ public ByteBuffer(int size) {
+ if (size < 1)
+ size = 128;
+ buf = new byte[size];
+ }
+
+ /**
+ * Sets the cache size.
+ *
+ * This can only be used to increment the size.
+ * If the size that is passed through is smaller than the current size, nothing happens.
+ *
+ * @param size the size of the cache
+ */
+
+ public static void setCacheSize(int size) {
+ if (size > 3276700) size = 3276700;
+ if (size <= byteCacheSize) return;
+ byte[][] tmpCache = new byte[size][];
+ for (int i = 0; i < byteCacheSize; i++) {
+ tmpCache[i] = byteCache[i];
+ }
+ byteCache = tmpCache;
+ byteCacheSize = size;
+ }
+
+ /**
+ * You can fill the cache in advance if you want to.
+ *
+ * @param decimals
+ */
+
+ public static void fillCache(int decimals) {
+ int step = 1;
+ switch(decimals) {
+ case 0:
+ step = 100;
+ break;
+ case 1:
+ step = 10;
+ break;
+ }
+ for (int i = 1; i < byteCacheSize; i += step) {
+ if (byteCache[i] != null) continue;
+ byteCache[i] = convertToBytes(i);
+ }
+ }
+
+ /**
+ * Converts an double (multiplied by 100 and cast to an int) into an array of bytes.
+ *
+ * @param i the int
+ * @return a bytearray
+ */
+
+ private static byte[] convertToBytes(int i) {
+ int size = (int)Math.floor(Math.log(i) / Math.log(10));
+ if (i % 100 != 0) {
+ size += 2;
+ }
+ if (i % 10 != 0) {
+ size++;
+ }
+ if (i < 100) {
+ size++;
+ if (i < 10) {
+ size++;
+ }
+ }
+ size--;
+ byte[] cache = new byte[size];
+ size --;
+ if (i < 100) {
+ cache[0] = (byte)'0';
+ }
+ if (i % 10 != 0) {
+ cache[size--] = bytes[i % 10];
+ }
+ if (i % 100 != 0) {
+ cache[size--] = bytes[(i / 10) % 10];
+ cache[size--] = (byte)'.';
+ }
+ size = (int)Math.floor(Math.log(i) / Math.log(10)) - 1;
+ int add = 0;
+ while (add < size) {
+ cache[add] = bytes[(i / (int)Math.pow(10, size - add + 1)) % 10];
+ add++;
+ }
+ return cache;
+ }
+
+ /**
+ * Appends an int
. The size of the array will grow by one.
+ * @param b the int to be appended
+ * @return a reference to this ByteBuffer
object
+ */
+ public ByteBuffer append_i(int b) {
+ int newcount = count + 1;
+ if (newcount > buf.length) {
+ byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)];
+ System.arraycopy(buf, 0, newbuf, 0, count);
+ buf = newbuf;
+ }
+ buf[count] = (byte)b;
+ count = newcount;
+ return this;
+ }
+
+ /**
+ * Appends the subarray of the byte
array. The buffer will grow by
+ * len
bytes.
+ * @param b the array to be appended
+ * @param off the offset to the start of the array
+ * @param len the length of bytes to append
+ * @return a reference to this ByteBuffer
object
+ */
+ public ByteBuffer append(byte b[], int off, int len) {
+ if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) > b.length) || ((off + len) < 0) || len == 0)
+ return this;
+ int newcount = count + len;
+ if (newcount > buf.length) {
+ byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)];
+ System.arraycopy(buf, 0, newbuf, 0, count);
+ buf = newbuf;
+ }
+ System.arraycopy(b, off, buf, count, len);
+ count = newcount;
+ return this;
+ }
+
+ /**
+ * Appends an array of bytes.
+ * @param b the array to be appended
+ * @return a reference to this ByteBuffer
object
+ */
+ public ByteBuffer append(byte b[]) {
+ return append(b, 0, b.length);
+ }
+
+ /**
+ * Appends a String
to the buffer. The String
is
+ * converted according to the encoding ISO-8859-1.
+ * @param str the String
to be appended
+ * @return a reference to this ByteBuffer
object
+ */
+ public ByteBuffer append(String str) {
+ if (str != null)
+ return append(DocWriter.getISOBytes(str));
+ return this;
+ }
+
+ /**
+ * Appends a char
to the buffer. The char
is
+ * converted according to the encoding ISO-8859-1.
+ * @param c the char
to be appended
+ * @return a reference to this ByteBuffer
object
+ */
+ public ByteBuffer append(char c) {
+ return append_i(c);
+ }
+
+ /**
+ * Appends another ByteBuffer
to this buffer.
+ * @param buf the ByteBuffer
to be appended
+ * @return a reference to this ByteBuffer
object
+ */
+ public ByteBuffer append(ByteBuffer buf) {
+ return append(buf.buf, 0, buf.count);
+ }
+
+ /**
+ * Appends the string representation of an int
.
+ * @param i the int
to be appended
+ * @return a reference to this ByteBuffer
object
+ */
+ public ByteBuffer append(int i) {
+ return append((double)i);
+ }
+
+ public ByteBuffer append(byte b) {
+ return append_i(b);
+ }
+
+ public ByteBuffer appendHex(byte b) {
+ append(bytes[(b >> 4) & 0x0f]);
+ return append(bytes[b & 0x0f]);
+ }
+
+ /**
+ * Appends a string representation of a float
according
+ * to the Pdf conventions.
+ * @param i the float
to be appended
+ * @return a reference to this ByteBuffer
object
+ */
+ public ByteBuffer append(float i) {
+ return append((double)i);
+ }
+
+ /**
+ * Appends a string representation of a double
according
+ * to the Pdf conventions.
+ * @param d the double
to be appended
+ * @return a reference to this ByteBuffer
object
+ */
+ public ByteBuffer append(double d) {
+ append(formatDouble(d, this));
+ return this;
+ }
+
+ /**
+ * Outputs a double
into a format suitable for the PDF.
+ * @param d a double
+ * @return the String
representation of the double
+ */
+ public static String formatDouble(double d) {
+ return formatDouble(d, null);
+ }
+
+ /**
+ * Outputs a double
into a format suitable for the PDF.
+ * @param d a double
+ * @return the String
representation of the double
if
+ * d
is null
. If d
is not null
,
+ * then the double is appended directly to the buffer and this methods returns null
.
+ */
+ public static String formatDouble(double d, ByteBuffer buf) {
+ boolean negative = false;
+ if (Math.abs(d) < 0.000015) {
+ if (buf != null) {
+ buf.append((byte)ZERO);
+ return null;
+ } else {
+ return "0";
+ }
+ }
+ if (d < 0) {
+ negative = true;
+ d = -d;
+ }
+ if (d < 1.0) {
+ d += 0.000005;
+ if (d >= 1) {
+ if (negative) {
+ if (buf != null) {
+ buf.append((byte)'-');
+ buf.append((byte)'1');
+ return null;
+ } else {
+ return "-1";
+ }
+ } else {
+ if (buf != null) {
+ buf.append((byte)'1');
+ return null;
+ } else {
+ return "1";
+ }
+ }
+ }
+ if (buf != null) {
+ int v = (int) (d * 100000);
+
+ if (negative) buf.append((byte)'-');
+ buf.append((byte)'0');
+ buf.append((byte)'.');
+
+ buf.append( (byte)(v / 10000 + ZERO) );
+ if (v % 10000 != 0) {
+ buf.append( (byte)((v / 1000) % 10 + ZERO) );
+ if (v % 1000 != 0) {
+ buf.append( (byte)((v / 100) % 10 + ZERO) );
+ if (v % 100 != 0) {
+ buf.append((byte)((v / 10) % 10 + ZERO) );
+ if (v % 10 != 0) {
+ buf.append((byte)((v) % 10 + ZERO) );
+ }
+ }
+ }
+ }
+ return null;
+ } else {
+ int x = 100000;
+ int v = (int) (d * x);
+
+ StringBuffer res = new StringBuffer();
+ if (negative) res.append('-');
+ res.append("0.");
+
+ while( v < x/10 ) {
+ res.append('0');
+ x /= 10;
+ }
+ res.append(v);
+ int cut = res.length() - 1;
+ while (res.charAt(cut) == '0') {
+ --cut;
+ }
+ res.setLength(cut + 1);
+ return res.toString();
+ }
+ } else if (d <= 32767) {
+ d += 0.005;
+ int v = (int) (d * 100);
+
+ if (v < byteCacheSize && byteCache[v] != null) {
+ if (buf != null) {
+ if (negative) buf.append((byte)'-');
+ buf.append(byteCache[v]);
+ return null;
+ } else {
+ String tmp = PdfEncodings.convertToString(byteCache[v], null);
+ if (negative) tmp = "-" + tmp;
+ return tmp;
+ }
+ }
+ if (buf != null) {
+ if (v < byteCacheSize) {
+ //create the cachebyte[]
+ byte[] cache;
+ int size = 0;
+ if (v >= 1000000) {
+ //the original number is >=10000, we need 5 more bytes
+ size += 5;
+ } else if (v >= 100000) {
+ //the original number is >=1000, we need 4 more bytes
+ size += 4;
+ } else if (v >= 10000) {
+ //the original number is >=100, we need 3 more bytes
+ size += 3;
+ } else if (v >= 1000) {
+ //the original number is >=10, we need 2 more bytes
+ size += 2;
+ } else if (v >= 100) {
+ //the original number is >=1, we need 1 more bytes
+ size += 1;
+ }
+
+ //now we must check if we have a decimal number
+ if (v % 100 != 0) {
+ //yes, do not forget the "."
+ size += 2;
+ }
+ if (v % 10 != 0) {
+ size++;
+ }
+ cache = new byte[size];
+ int add = 0;
+ if (v >= 1000000) {
+ cache[add++] = bytes[(v / 1000000)];
+ }
+ if (v >= 100000) {
+ cache[add++] = bytes[(v / 100000) % 10];
+ }
+ if (v >= 10000) {
+ cache[add++] = bytes[(v / 10000) % 10];
+ }
+ if (v >= 1000) {
+ cache[add++] = bytes[(v / 1000) % 10];
+ }
+ if (v >= 100) {
+ cache[add++] = bytes[(v / 100) % 10];
+ }
+
+ if (v % 100 != 0) {
+ cache[add++] = (byte)'.';
+ cache[add++] = bytes[(v / 10) % 10];
+ if (v % 10 != 0) {
+ cache[add++] = bytes[v % 10];
+ }
+ }
+ byteCache[v] = cache;
+ }
+
+ if (negative) buf.append((byte)'-');
+ if (v >= 1000000) {
+ buf.append( bytes[(v / 1000000)] );
+ }
+ if (v >= 100000) {
+ buf.append( bytes[(v / 100000) % 10] );
+ }
+ if (v >= 10000) {
+ buf.append( bytes[(v / 10000) % 10] );
+ }
+ if (v >= 1000) {
+ buf.append( bytes[(v / 1000) % 10] );
+ }
+ if (v >= 100) {
+ buf.append( bytes[(v / 100) % 10] );
+ }
+
+ if (v % 100 != 0) {
+ buf.append((byte)'.');
+ buf.append( bytes[(v / 10) % 10] );
+ if (v % 10 != 0) {
+ buf.append( bytes[v % 10] );
+ }
+ }
+ return null;
+ } else {
+ StringBuffer res = new StringBuffer();
+ if (negative) res.append((char)'-');
+ if (v >= 1000000) {
+ res.append( chars[(v / 1000000)] );
+ }
+ if (v >= 100000) {
+ res.append( chars[(v / 100000) % 10] );
+ }
+ if (v >= 10000) {
+ res.append( chars[(v / 10000) % 10] );
+ }
+ if (v >= 1000) {
+ res.append( chars[(v / 1000) % 10] );
+ }
+ if (v >= 100) {
+ res.append( chars[(v / 100) % 10] );
+ }
+
+ if (v % 100 != 0) {
+ res.append((char)'.');
+ res.append( chars[(v / 10) % 10] );
+ if (v % 10 != 0) {
+ res.append( chars[v % 10] );
+ }
+ }
+ return res.toString();
+ }
+ } else {
+ StringBuffer res = new StringBuffer();
+ if (negative) res.append('-');
+ d += 0.5;
+ long v = (long) d;
+ return res.append(v).toString();
+ }
+ }
+
+ /**
+ * Sets the size to zero.
+ */
+ public void reset() {
+ count = 0;
+ }
+
+ /**
+ * Creates a newly allocated byte array. Its size is the current
+ * size of this output stream and the valid contents of the buffer
+ * have been copied into it.
+ *
+ * @return the current contents of this output stream, as a byte array.
+ */
+ public byte[] toByteArray() {
+ byte newbuf[] = new byte[count];
+ System.arraycopy(buf, 0, newbuf, 0, count);
+ return newbuf;
+ }
+
+ /**
+ * Returns the current size of the buffer.
+ *
+ * @return the value of the count
field, which is the number of valid bytes in this byte buffer.
+ */
+ public int size() {
+ return count;
+ }
+
+ /**
+ * Converts the buffer's contents into a string, translating bytes into
+ * characters according to the platform's default character encoding.
+ *
+ * @return String translated from the buffer's contents.
+ */
+ public String toString() {
+ return new String(buf, 0, count);
+ }
+
+ /**
+ * Converts the buffer's contents into a string, translating bytes into
+ * characters according to the specified character encoding.
+ *
+ * @param enc a character-encoding name.
+ * @return String translated from the buffer's contents.
+ * @throws UnsupportedEncodingException
+ * If the named encoding is not supported.
+ */
+ public String toString(String enc) throws UnsupportedEncodingException {
+ return new String(buf, 0, count, enc);
+ }
+
+ /**
+ * Writes the complete contents of this byte buffer output to
+ * the specified output stream argument, as if by calling the output
+ * stream's write method using out.write(buf, 0, count)
.
+ *
+ * @param out the output stream to which to write the data.
+ * @exception IOException if an I/O error occurs.
+ */
+ public void writeTo(OutputStream out) throws IOException {
+ out.write(buf, 0, count);
+ }
+
+ public void write(int b) throws IOException {
+ append((byte)b);
+ }
+
+ public void write(byte[] b, int off, int len) {
+ append(b, off, len);
+ }
+
+ public byte[] getBuffer() {
+ return buf;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/CFFFont.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/CFFFont.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/CFFFont.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/CFFFont.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,1171 @@
+/*
+ *
+ * Copyright 2003 Sivan Toledo
+ *
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ */
+
+/*
+ * Comments by Sivan Toledo:
+ * I created this class in order to add to iText the ability to utilize
+ * OpenType fonts with CFF glyphs (these usually have an .otf extension).
+ * The CFF font within the CFF table of the OT font might be either a CID
+ * or a Type1 font. (CFF fonts may also contain multiple fonts; I do not
+ * know if this is allowed in an OT table). The PDF spec, however, only
+ * allow a CID font with an Identity-H or Identity-V encoding. Otherwise,
+ * you are limited to an 8-bit encoding.
+ * Adobe fonts come in both flavors. That is, the OTFs sometimes have
+ * a CID CFF inside (for Japanese fonts), and sometimes a Type1 CFF
+ * (virtually all the others, Latin/Greek/Cyrillic). So to easily use
+ * all the glyphs in the latter, without creating multiple 8-bit encoding,
+ * I wrote this class, whose main purpose is to convert a Type1 font inside
+ * a CFF container (which might include other fonts) into a CID CFF font
+ * that can be directly embeded in the PDF.
+ *
+ * Limitations of the current version:
+ * 1. It does not extract a single CID font from a CFF that contains that
+ * particular CID along with other fonts. The Adobe Japanese OTF's that
+ * I have only have one font in the CFF table, so these can be
+ * embeded in the PDF as is.
+ * 2. It does not yet subset fonts.
+ * 3. It may or may not work on CFF fonts that are not within OTF's.
+ * I didn't try that. In any case, that would probably only be
+ * useful for subsetting CID fonts, not for CFF Type1 fonts (I don't
+ * think there are any available.
+ * I plan to extend the class to support these three features at some
+ * future time.
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * @author stoledo
+ */
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+public class CFFFont {
+
+ static final String operatorNames[] = {
+ "version", "Notice", "FullName", "FamilyName",
+ "Weight", "FontBBox", "BlueValues", "OtherBlues",
+ "FamilyBlues", "FamilyOtherBlues", "StdHW", "StdVW",
+ "UNKNOWN_12", "UniqueID", "XUID", "charset",
+ "Encoding", "CharStrings", "Private", "Subrs",
+ "defaultWidthX", "nominalWidthX", "UNKNOWN_22", "UNKNOWN_23",
+ "UNKNOWN_24", "UNKNOWN_25", "UNKNOWN_26", "UNKNOWN_27",
+ "UNKNOWN_28", "UNKNOWN_29", "UNKNOWN_30", "UNKNOWN_31",
+ "Copyright", "isFixedPitch", "ItalicAngle", "UnderlinePosition",
+ "UnderlineThickness", "PaintType", "CharstringType", "FontMatrix",
+ "StrokeWidth", "BlueScale", "BlueShift", "BlueFuzz",
+ "StemSnapH", "StemSnapV", "ForceBold", "UNKNOWN_12_15",
+ "UNKNOWN_12_16", "LanguageGroup", "ExpansionFactor", "initialRandomSeed",
+ "SyntheticBase", "PostScript", "BaseFontName", "BaseFontBlend",
+ "UNKNOWN_12_24", "UNKNOWN_12_25", "UNKNOWN_12_26", "UNKNOWN_12_27",
+ "UNKNOWN_12_28", "UNKNOWN_12_29", "ROS", "CIDFontVersion",
+ "CIDFontRevision", "CIDFontType", "CIDCount", "UIDBase",
+ "FDArray", "FDSelect", "FontName"
+ };
+
+ static final String standardStrings[] = {
+ // Automatically generated from Appendix A of the CFF specification; do
+ // not edit. Size should be 391.
+ ".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar",
+ "percent", "ampersand", "quoteright", "parenleft", "parenright",
+ "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one",
+ "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon",
+ "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C",
+ "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
+ "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash",
+ "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c",
+ "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
+ "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright",
+ "asciitilde", "exclamdown", "cent", "sterling", "fraction", "yen",
+ "florin", "section", "currency", "quotesingle", "quotedblleft",
+ "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash",
+ "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet",
+ "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright",
+ "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex",
+ "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla",
+ "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash",
+ "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe",
+ "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth",
+ "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar",
+ "degree", "thorn", "threequarters", "twosuperior", "registered", "minus",
+ "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex",
+ "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute",
+ "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis",
+ "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve",
+ "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave",
+ "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis",
+ "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex",
+ "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave",
+ "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde",
+ "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute",
+ "ydieresis", "zcaron", "exclamsmall", "Hungarumlautsmall",
+ "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
+ "parenleftsuperior", "parenrightsuperior", "twodotenleader",
+ "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle",
+ "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle",
+ "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior",
+ "threequartersemdash", "periodsuperior", "questionsmall", "asuperior",
+ "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior",
+ "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior",
+ "ssuperior", "tsuperior", "ff", "ffi", "ffl", "parenleftinferior",
+ "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall",
+ "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall",
+ "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall",
+ "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
+ "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary",
+ "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle",
+ "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall",
+ "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash",
+ "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall",
+ "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths",
+ "seveneighths", "onethird", "twothirds", "zerosuperior", "foursuperior",
+ "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior",
+ "ninesuperior", "zeroinferior", "oneinferior", "twoinferior",
+ "threeinferior", "fourinferior", "fiveinferior", "sixinferior",
+ "seveninferior", "eightinferior", "nineinferior", "centinferior",
+ "dollarinferior", "periodinferior", "commainferior", "Agravesmall",
+ "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall",
+ "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall",
+ "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall",
+ "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
+ "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall",
+ "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall",
+ "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall",
+ "Ydieresissmall", "001.000", "001.001", "001.002", "001.003", "Black",
+ "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold"
+ };
+
+ //private String[] strings;
+ public String getString(char sid) {
+ if (sid < standardStrings.length) return standardStrings[sid];
+ if (sid >= standardStrings.length+(stringOffsets.length-1)) return null;
+ int j = sid - standardStrings.length;
+ //java.lang.System.err.println("going for "+j);
+ int p = getPosition();
+ seek(stringOffsets[j]);
+ StringBuffer s = new StringBuffer();
+ for (int k=stringOffsets[j]; k count in the index header. 1->offset size in index header
+ + 2+1
+ //offset array size * offset size
+ + (count+1)*indexOffSize
+ //???zero <-> one base
+ - 1
+ // read object offset relative to object array base
+ + getOffset(indexOffSize);
+ }
+ //nextIndexOffset = offsets[count];
+ return offsets;
+ }
+
+ protected String key;
+ protected Object[] args = new Object[48];
+ protected int arg_count = 0;
+
+ protected void getDictItem() {
+ for (int i=0; i= 32 && b0 <= 246) {
+ byte item = (byte) (b0-139);
+ args[arg_count] = new Integer(item);
+ arg_count++;
+ //System.err.println(item+" ");
+ continue;
+ }
+ if (b0 >= 247 && b0 <= 250) {
+ char b1 = getCard8();
+ short item = (short) ((b0-247)*256+b1+108);
+ args[arg_count] = new Integer(item);
+ arg_count++;
+ //System.err.println(item+" ");
+ continue;
+ }
+ if (b0 >= 251 && b0 <= 254) {
+ char b1 = getCard8();
+ short item = (short) (-(b0-251)*256-b1-108);
+ args[arg_count] = new Integer(item);
+ arg_count++;
+ //System.err.println(item+" ");
+ continue;
+ }
+ if (b0 == 30) {
+ String item = "";
+ boolean done = false;
+ char buffer = 0;
+ byte avail = 0;
+ int nibble = 0;
+ while (!done) {
+ // get a nibble
+ if (avail==0) { buffer = getCard8(); avail=2; }
+ if (avail==1) { nibble = (buffer / 16); avail--; }
+ if (avail==2) { nibble = (buffer % 16); avail--; }
+ switch (nibble) {
+ case 0xa: item += "." ; break;
+ case 0xb: item += "E" ; break;
+ case 0xc: item += "E-"; break;
+ case 0xe: item += "-" ; break;
+ case 0xf: done=true ; break;
+ default:
+ if (nibble >= 0 && nibble <= 9)
+ item += String.valueOf(nibble);
+ else {
+ item += "";
+ done = true;
+ }
+ break;
+ }
+ }
+ args[arg_count] = item;
+ arg_count++;
+ //System.err.println(" real=["+item+"]");
+ continue;
+ }
+ if (b0 <= 21) {
+ gotKey=true;
+ if (b0 != 12) key = operatorNames[b0];
+ else key = operatorNames[32 + getCard8()];
+ //for (int i=0; i>> 24) & 0xff);
+ i++;
+ case 3:
+ buffer[myOffset+i] = (byte) ((value >>> 16) & 0xff);
+ i++;
+ case 2:
+ buffer[myOffset+i] = (byte) ((value >>> 8) & 0xff);
+ i++;
+ case 1:
+ buffer[myOffset+i] = (byte) ((value >>> 0) & 0xff);
+ i++;
+ }
+ /*
+ int mask = 0xff;
+ for (int i=size-1; i>=0; i--) {
+ buffer[myOffset+i] = (byte) (value & mask);
+ mask <<= 8;
+ }
+ */
+ }
+ }
+
+ static protected final class IndexBaseItem extends Item {
+ public IndexBaseItem() {}
+ }
+
+ static protected final class IndexMarkerItem extends Item {
+ private OffsetItem offItem;
+ private IndexBaseItem indexBase;
+ public IndexMarkerItem(OffsetItem offItem, IndexBaseItem indexBase) {
+ this.offItem = offItem;
+ this.indexBase = indexBase;
+ }
+ public void xref() {
+ //System.err.println("index marker item, base="+indexBase.myOffset+" my="+this.myOffset);
+ offItem.set(this.myOffset-indexBase.myOffset+1);
+ }
+ }
+ /**
+ *
+ * @author orly manor
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+ static protected final class SubrMarkerItem extends Item {
+ private OffsetItem offItem;
+ private IndexBaseItem indexBase;
+ public SubrMarkerItem(OffsetItem offItem, IndexBaseItem indexBase) {
+ this.offItem = offItem;
+ this.indexBase = indexBase;
+ }
+ public void xref() {
+ //System.err.println("index marker item, base="+indexBase.myOffset+" my="+this.myOffset);
+ offItem.set(this.myOffset-indexBase.myOffset);
+ }
+ }
+
+
+ /** an unknown offset in a dictionary for the list.
+ * We will fix up the offset later; for now, assume it's large.
+ */
+ static protected final class DictOffsetItem extends OffsetItem {
+ public final int size;
+ public DictOffsetItem() {this.size=5; }
+
+ public void increment(int[] currentOffset) {
+ super.increment(currentOffset);
+ currentOffset[0] += size;
+ }
+ // this is incomplete!
+ public void emit(byte[] buffer) {
+ if (size==5) {
+ buffer[myOffset] = 29;
+ buffer[myOffset+1] = (byte) ((value >>> 24) & 0xff);
+ buffer[myOffset+2] = (byte) ((value >>> 16) & 0xff);
+ buffer[myOffset+3] = (byte) ((value >>> 8) & 0xff);
+ buffer[myOffset+4] = (byte) ((value >>> 0) & 0xff);
+ }
+ }
+ }
+
+ /** Card24 item.
+ */
+
+ static protected final class UInt24Item extends Item {
+ public int value;
+ public UInt24Item(int value) {this.value=value;}
+
+ public void increment(int[] currentOffset) {
+ super.increment(currentOffset);
+ currentOffset[0] += 3;
+ }
+ // this is incomplete!
+ public void emit(byte[] buffer) {
+ buffer[myOffset+0] = (byte) ((value >>> 16) & 0xff);
+ buffer[myOffset+1] = (byte) ((value >>> 8) & 0xff);
+ buffer[myOffset+2] = (byte) ((value >>> 0) & 0xff);
+ }
+ }
+
+ /** Card32 item.
+ */
+
+ static protected final class UInt32Item extends Item {
+ public int value;
+ public UInt32Item(int value) {this.value=value;}
+
+ public void increment(int[] currentOffset) {
+ super.increment(currentOffset);
+ currentOffset[0] += 4;
+ }
+ // this is incomplete!
+ public void emit(byte[] buffer) {
+ buffer[myOffset+0] = (byte) ((value >>> 24) & 0xff);
+ buffer[myOffset+1] = (byte) ((value >>> 16) & 0xff);
+ buffer[myOffset+2] = (byte) ((value >>> 8) & 0xff);
+ buffer[myOffset+3] = (byte) ((value >>> 0) & 0xff);
+ }
+ }
+
+ /** A SID or Card16 item.
+ */
+
+ static protected final class UInt16Item extends Item {
+ public char value;
+ public UInt16Item(char value) {this.value=value;}
+
+ public void increment(int[] currentOffset) {
+ super.increment(currentOffset);
+ currentOffset[0] += 2;
+ }
+ // this is incomplete!
+ public void emit(byte[] buffer) {
+ buffer[myOffset+0] = (byte) ((value >>> 8) & 0xff);
+ buffer[myOffset+1] = (byte) ((value >>> 0) & 0xff);
+ }
+ }
+
+ /** A Card8 item.
+ */
+
+ static protected final class UInt8Item extends Item {
+ public char value;
+ public UInt8Item(char value) {this.value=value;}
+
+ public void increment(int[] currentOffset) {
+ super.increment(currentOffset);
+ currentOffset[0] += 1;
+ }
+ // this is incomplete!
+ public void emit(byte[] buffer) {
+ buffer[myOffset+0] = (byte) ((value >>> 0) & 0xff);
+ }
+ }
+
+ static protected final class StringItem extends Item {
+ public String s;
+ public StringItem(String s) {this.s=s;}
+
+ public void increment(int[] currentOffset) {
+ super.increment(currentOffset);
+ currentOffset[0] += s.length();
+ }
+ public void emit(byte[] buffer) {
+ for (int i=0; i>> 24) & 0xff);
+ buffer[myOffset+2] = (byte) ((value >>> 16) & 0xff);
+ buffer[myOffset+3] = (byte) ((value >>> 8) & 0xff);
+ buffer[myOffset+4] = (byte) ((value >>> 0) & 0xff);
+ }
+ }
+ }
+
+ /** An offset-marker item for the list.
+ * It is used to mark an offset and to set the offset list item.
+ */
+
+ static protected final class MarkerItem extends Item {
+ OffsetItem p;
+ public MarkerItem(OffsetItem pointerToMarker) {p=pointerToMarker;}
+ public void xref() {
+ p.set(this.myOffset);
+ }
+ }
+
+ /** a utility that creates a range item for an entire index
+ *
+ * @param indexOffset where the index is
+ * @return a range item representing the entire index
+ */
+
+ protected RangeItem getEntireIndexRange(int indexOffset) {
+ seek(indexOffset);
+ int count = getCard16();
+ if (count==0) {
+ return new RangeItem(buf,indexOffset,2);
+ } else {
+ int indexOffSize = getCard8();
+ seek(indexOffset+2+1+count*indexOffSize);
+ int size = getOffset(indexOffSize)-1;
+ return new RangeItem(buf,indexOffset,
+ 2+1+(count+1)*indexOffSize+size);
+ }
+ }
+
+
+ /** get a single CID font. The PDF architecture (1.4)
+ * supports 16-bit strings only with CID CFF fonts, not
+ * in Type-1 CFF fonts, so we convert the font to CID if
+ * it is in the Type-1 format.
+ * Two other tasks that we need to do are to select
+ * only a single font from the CFF package (this again is
+ * a PDF restriction) and to subset the CharStrings glyph
+ * description.
+ */
+
+
+ public byte[] getCID(String fontName)
+ //throws java.io.FileNotFoundException
+ {
+ int j;
+ for (j=0; j 127)
+ fdFontName = fdFontName.substring(0,127);
+ String extraStrings = "Adobe"+"Identity"+fdFontName;
+
+ int origStringsLen = stringOffsets[stringOffsets.length-1]
+ - stringOffsets[0];
+ int stringsBaseOffset = stringOffsets[0]-1;
+
+ byte stringsIndexOffSize;
+ if (origStringsLen+extraStrings.length() <= 0xff) stringsIndexOffSize = 1;
+ else if (origStringsLen+extraStrings.length() <= 0xffff) stringsIndexOffSize = 2;
+ else if (origStringsLen+extraStrings.length() <= 0xffffff) stringsIndexOffSize = 3;
+ else stringsIndexOffSize = 4;
+
+ l.addLast(new UInt16Item((char)((stringOffsets.length-1)+3))); // count
+ l.addLast(new UInt8Item((char)stringsIndexOffSize)); // offSize
+ for (int i=0; i= 0) {
+ //System.err.println("has subrs="+fonts[j].privateSubrs+" ,len="+fonts[j].privateLength);
+ l.addLast(getEntireIndexRange(fonts[j].privateSubrs));
+ }
+ }
+
+ // copy the charstring index
+
+ l.addLast(new MarkerItem(charstringsRef));
+ l.addLast(getEntireIndexRange(fonts[j].charstringsOffset));
+
+ // now create the new CFF font
+
+ int[] currentOffset = new int[1];
+ currentOffset[0] = 0;
+
+ Iterator listIter = l.iterator();
+ while ( listIter.hasNext() ) {
+ Item item = (Item) listIter.next();
+ item.increment(currentOffset);
+ }
+
+ listIter = l.iterator();
+ while ( listIter.hasNext() ) {
+ Item item = (Item) listIter.next();
+ item.xref();
+ }
+
+ int size = currentOffset[0];
+ byte[] b = new byte[size];
+
+ listIter = l.iterator();
+ while ( listIter.hasNext() ) {
+ Item item = (Item) listIter.next();
+ item.emit(b);
+ }
+
+ return b;
+ }
+
+
+ public boolean isCID(String fontName) {
+ int j;
+ for (j=0; j");
+ }
+
+ // string index
+
+ //strings = new String[stringOffsets.length-1];
+ /*
+ System.err.println("std strings = "+standardStrings.length);
+ System.err.println("fnt strings = "+(stringOffsets.length-1));
+ for (char j=0; j");
+ }
+ */
+
+ // top dict
+
+ for (int j=0; j= 0) {
+ //System.err.println("PRIVATE::");
+ seek(fonts[j].privateOffset);
+ while (getPosition() < fonts[j].privateOffset+fonts[j].privateLength) {
+ getDictItem();
+ if (key=="Subrs")
+ //Add the private offset to the lsubrs since the offset is
+ // relative to the begining of the PrivateDict
+ fonts[j].privateSubrs = ((Integer)args[0]).intValue()+fonts[j].privateOffset;
+ }
+ }
+
+ // fdarray index
+ if (fonts[j].fdarrayOffset >= 0) {
+ int[] fdarrayOffsets = getIndex(fonts[j].fdarrayOffset);
+
+ fonts[j].fdprivateOffsets = new int[fdarrayOffsets.length-1];
+ fonts[j].fdprivateLengths = new int[fdarrayOffsets.length-1];
+
+ //System.err.println("FD Font::");
+
+ for (int k=0; k
+ * @author Oren Manor & Ygal Blum
+ */
+public class CFFFontSubset extends CFFFont {
+
+ /**
+ * The Strings in this array represent Type1/Type2 operator names
+ */
+ static final String SubrsFunctions[] = {
+ "RESERVED_0","hstem","RESERVED_2","vstem","vmoveto","rlineto","hlineto","vlineto",
+ "rrcurveto","RESERVED_9","callsubr","return","escape","RESERVED_13",
+ "endchar","RESERVED_15","RESERVED_16","RESERVED_17","hstemhm","hintmask",
+ "cntrmask","rmoveto","hmoveto","vstemhm","rcurveline","rlinecurve","vvcurveto",
+ "hhcurveto","shortint","callgsubr","vhcurveto","hvcurveto"
+ };
+ /**
+ * The Strings in this array represent Type1/Type2 escape operator names
+ */
+ static final String SubrsEscapeFuncs[] = {
+ "RESERVED_0","RESERVED_1","RESERVED_2","and","or","not","RESERVED_6",
+ "RESERVED_7","RESERVED_8","abs","add","sub","div","RESERVED_13","neg",
+ "eq","RESERVED_16","RESERVED_17","drop","RESERVED_19","put","get","ifelse",
+ "random","mul","RESERVED_25","sqrt","dup","exch","index","roll","RESERVED_31",
+ "RESERVED_32","RESERVED_33","hflex","flex","hflex1","flex1","RESERVED_REST"
+ };
+
+ /**
+ * A HashMap containing the glyphs used in the text after being converted
+ * to glyph number by the CMap
+ */
+ HashMap GlyphsUsed;
+ /**
+ * The GlyphsUsed keys as an ArrayList
+ */
+ ArrayList glyphsInList;
+ /**
+ * A HashMap for keeping the FDArrays being used by the font
+ */
+ HashMap FDArrayUsed = new HashMap();
+ /**
+ * A HashMaps array for keeping the subroutines used in each FontDict
+ */
+ HashMap[] hSubrsUsed;
+ /**
+ * The SubroutinesUsed HashMaps as ArrayLists
+ */
+ ArrayList[] lSubrsUsed;
+ /**
+ * A HashMap for keeping the Global subroutines used in the font
+ */
+ HashMap hGSubrsUsed = new HashMap();
+ /**
+ * The Global SubroutinesUsed HashMaps as ArrayLists
+ */
+ ArrayList lGSubrsUsed = new ArrayList();
+ /**
+ * A HashMap for keeping the subroutines used in a non-cid font
+ */
+ HashMap hSubrsUsedNonCID = new HashMap();
+ /**
+ * The SubroutinesUsed HashMap as ArrayList
+ */
+ ArrayList lSubrsUsedNonCID = new ArrayList();
+ /**
+ * An array of the new Indexs for the local Subr. One index for each FontDict
+ */
+ byte[][] NewLSubrsIndex;
+ /**
+ * The new subroutines index for a non-cid font
+ */
+ byte[] NewSubrsIndexNonCID;
+ /**
+ * The new global subroutines index of the font
+ */
+ byte[] NewGSubrsIndex;
+ /**
+ * The new CharString of the font
+ */
+ byte[] NewCharStringsIndex;
+
+ /**
+ * The bias for the global subroutines
+ */
+ int GBias = 0;
+
+ /**
+ * The linked list for generating the new font stream
+ */
+ LinkedList OutputList;
+
+ /**
+ * Number of arguments to the stem operators in a subroutine calculated recursivly
+ */
+ int NumOfHints=0;
+
+
+ /**
+ * C'tor for CFFFontSubset
+ * @param rf - The font file
+ * @param GlyphsUsed - a HashMap that contains the glyph used in the subset
+ */
+ public CFFFontSubset(RandomAccessFileOrArray rf,HashMap GlyphsUsed){
+ // Use CFFFont c'tor in order to parse the font file.
+ super(rf);
+ this.GlyphsUsed = GlyphsUsed;
+ //Put the glyphs into a list
+ glyphsInList = new ArrayList(GlyphsUsed.keySet());
+
+
+ for (int i=0;i=0)
+ {
+ // Proces the FDSelect
+ readFDSelect(i);
+ // Build the FDArrayUsed hashmap
+ BuildFDArrayUsed(i);
+ }
+ if (fonts[i].isCID)
+ // Build the FD Array used Hash Map
+ ReadFDArray(i);
+ // compute the charset length
+ fonts[i].CharsetLength = CountCharset(fonts[i].charsetOffset,fonts[i].nglyphs);
+ }
+ }
+
+ /**
+ * Calculates the length of the charset according to its format
+ * @param Offset The Charset Offset
+ * @param NumofGlyphs Number of glyphs in the font
+ * @return the length of the Charset
+ */
+ int CountCharset(int Offset,int NumofGlyphs){
+ int format;
+ int Length=0;
+ seek(Offset);
+ // Read the format
+ format = getCard8();
+ // Calc according to format
+ switch (format){
+ case 0:
+ Length = 1+2*NumofGlyphs;
+ break;
+ case 1:
+ Length = 1+3*CountRange(NumofGlyphs,1);
+ break;
+ case 2:
+ Length = 1+4*CountRange(NumofGlyphs,2);
+ break;
+ default:
+ break;
+ }
+ return Length;
+ }
+
+ /**
+ * Function calculates the number of ranges in the Charset
+ * @param NumofGlyphs The number of glyphs in the font
+ * @param Type The format of the Charset
+ * @return The number of ranges in the Charset data structure
+ */
+ int CountRange(int NumofGlyphs,int Type){
+ int num=0;
+ int i=1,Sid,nLeft;
+ while (i= 0)
+ GBias = CalcBias(gsubrIndexOffset,j);
+
+ // Prepare the new CharStrings Index
+ BuildNewCharString(j);
+ // Prepare the new Global and Local Subrs Indices
+ BuildNewLGSubrs(j);
+ // Build the new file
+ byte[] Ret = BuildNewFile(j);
+ return Ret;
+ }
+ finally {
+ try {
+ buf.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ }
+
+ /**
+ * Function calcs bias according to the CharString type and the count
+ * of the subrs
+ * @param Offset The offset to the relevent subrs index
+ * @param Font the font
+ * @return The calculated Bias
+ */
+ protected int CalcBias(int Offset,int Font)
+ {
+ seek(Offset);
+ int nSubrs = getCard16();
+ // If type==1 -> bias=0
+ if (fonts[Font].CharstringType == 1)
+ return 0;
+ // else calc according to the count
+ else if (nSubrs < 1240)
+ return 107;
+ else if (nSubrs < 33900)
+ return 1131;
+ else
+ return 32768;
+ }
+
+ /**
+ *Function uses BuildNewIndex to create the new index of the subset charstrings
+ * @param FontIndex the font
+ * @throws IOException
+ */
+ protected void BuildNewCharString(int FontIndex) throws IOException
+ {
+ NewCharStringsIndex = BuildNewIndex(fonts[FontIndex].charstringsOffsets,GlyphsUsed);
+ }
+
+ /**
+ * Function builds the new local & global subsrs indices. IF CID then All of
+ * the FD Array lsubrs will be subsetted.
+ * @param Font the font
+ * @throws IOException
+ */
+ protected void BuildNewLGSubrs(int Font)throws IOException
+ {
+ // If the font is CID then the lsubrs are divided into FontDicts.
+ // for each FD array the lsubrs will be subsetted.
+ if(fonts[Font].isCID)
+ {
+ // Init the hasmap-array and the arraylist-array to hold the subrs used
+ // in each private dict.
+ hSubrsUsed = new HashMap[fonts[Font].fdprivateOffsets.length];
+ lSubrsUsed = new ArrayList[fonts[Font].fdprivateOffsets.length];
+ // A [][] which will store the byte array for each new FD Array lsubs index
+ NewLSubrsIndex = new byte[fonts[Font].fdprivateOffsets.length][];
+ // An array to hold the offset for each Lsubr index
+ fonts[Font].PrivateSubrsOffset = new int[fonts[Font].fdprivateOffsets.length];
+ // A [][] which will store the offset array for each lsubr index
+ fonts[Font].PrivateSubrsOffsetsArray = new int[fonts[Font].fdprivateOffsets.length][];
+
+ // Put the FDarrayUsed into a list
+ ArrayList FDInList = new ArrayList(FDArrayUsed.keySet());
+ // For each FD array which is used subset the lsubr
+ for (int j=0;j=0)
+ {
+ //Scans the Charsting data storing the used Local and Global subroutines
+ // by the glyphs. Scans the Subrs recursivley.
+ BuildSubrUsed(Font,FD,fonts[Font].PrivateSubrsOffset[FD],fonts[Font].PrivateSubrsOffsetsArray[FD],hSubrsUsed[FD],lSubrsUsed[FD]);
+ // Builds the New Local Subrs index
+ NewLSubrsIndex[FD] = BuildNewIndex(fonts[Font].PrivateSubrsOffsetsArray[FD],hSubrsUsed[FD]);
+ }
+ }
+ }
+ // If the font is not CID && the Private Subr exists then subset:
+ else if (fonts[Font].privateSubrs>=0)
+ {
+ // Build the subrs offsets;
+ fonts[Font].SubrsOffsets = getIndex(fonts[Font].privateSubrs);
+ //Scans the Charsting data storing the used Local and Global subroutines
+ // by the glyphs. Scans the Subrs recursivley.
+ BuildSubrUsed(Font,-1,fonts[Font].privateSubrs,fonts[Font].SubrsOffsets,hSubrsUsedNonCID,lSubrsUsedNonCID);
+ }
+ // For all fonts susbset the Global Subroutines
+ // Scan the Global Subr Hashmap recursivly on the Gsubrs
+ BuildGSubrsUsed(Font);
+ if (fonts[Font].privateSubrs>=0)
+ // Builds the New Local Subrs index
+ NewSubrsIndexNonCID = BuildNewIndex(fonts[Font].SubrsOffsets,hSubrsUsedNonCID);
+ //Builds the New Global Subrs index
+ NewGSubrsIndex = BuildNewIndex(gsubrOffsets,hGSubrsUsed);
+ }
+
+ /**
+ * The function finds for the FD array processed the local subr offset and its
+ * offset array.
+ * @param Font the font
+ * @param FD The FDARRAY processed
+ */
+ protected void BuildFDSubrsOffsets(int Font,int FD)
+ {
+ // Initiate to -1 to indicate lsubr operator present
+ fonts[Font].PrivateSubrsOffset[FD] = -1;
+ // Goto begining of objects
+ seek(fonts[Font].fdprivateOffsets[FD]);
+ // While in the same object:
+ while (getPosition() < fonts[Font].fdprivateOffsets[FD]+fonts[Font].fdprivateLengths[FD])
+ {
+ getDictItem();
+ // If the dictItem is the "Subrs" then find and store offset,
+ if (key=="Subrs")
+ fonts[Font].PrivateSubrsOffset[FD] = ((Integer)args[0]).intValue()+fonts[Font].fdprivateOffsets[FD];
+ }
+ //Read the lsub index if the lsubr was found
+ if (fonts[Font].PrivateSubrsOffset[FD] >= 0)
+ fonts[Font].PrivateSubrsOffsetsArray[FD] = getIndex(fonts[Font].PrivateSubrsOffset[FD]);
+ }
+
+ /**
+ * Function uses ReadAsubr on the glyph used to build the LSubr & Gsubr HashMap.
+ * The HashMap (of the lsub only) is then scaned recursivly for Lsubr & Gsubrs
+ * calls.
+ * @param Font the font
+ * @param FD FD array processed. 0 indicates function was called by non CID font
+ * @param SubrOffset the offset to the subr index to calc the bias
+ * @param SubrsOffsets the offset array of the subr index
+ * @param hSubr HashMap of the subrs used
+ * @param lSubr ArrayList of the subrs used
+ */
+ protected void BuildSubrUsed(int Font,int FD,int SubrOffset,int[] SubrsOffsets,HashMap hSubr,ArrayList lSubr)
+ {
+
+ // Calc the Bias for the subr index
+ int LBias = CalcBias(SubrOffset,Font);
+
+ // For each glyph used find its GID, start & end pos
+ for (int i=0;i= 0)
+ {
+ EmptyStack();
+ NumOfHints=0;
+ // Using FDSELECT find the FD Array the glyph belongs to.
+ int GlyphFD = fonts[Font].FDSelect[glyph];
+ // If the Glyph is part of the FD being processed
+ if (GlyphFD == FD)
+ // Find the Subrs called by the glyph and insert to hash:
+ ReadASubr(Start,End,GBias,LBias,hSubr,lSubr,SubrsOffsets);
+ }
+ else
+ // If the font is not CID
+ //Find the Subrs called by the glyph and insert to hash:
+ ReadASubr(Start,End,GBias,LBias,hSubr,lSubr,SubrsOffsets);
+ }
+ // For all Lsubrs used, check recusrivly for Lsubr & Gsubr used
+ for (int i=0;i=0)
+ {
+ // Read and process the subr
+ int Start = SubrsOffsets[Subr];
+ int End = SubrsOffsets[Subr+1];
+ ReadASubr(Start,End,GBias,LBias,hSubr,lSubr,SubrsOffsets);
+ }
+ }
+ }
+
+ /**
+ * Function scans the Glsubr used ArrayList to find recursive calls
+ * to Gsubrs and adds to Hashmap & ArrayList
+ * @param Font the font
+ */
+ protected void BuildGSubrsUsed(int Font)
+ {
+ int LBias = 0;
+ int SizeOfNonCIDSubrsUsed = 0;
+ if (fonts[Font].privateSubrs>=0)
+ {
+ LBias = CalcBias(fonts[Font].privateSubrs,Font);
+ SizeOfNonCIDSubrsUsed = lSubrsUsedNonCID.size();
+ }
+
+ // For each global subr used
+ for (int i=0;i=0)
+ {
+ // Read the subr and process
+ int Start = gsubrOffsets[Subr];
+ int End = gsubrOffsets[Subr+1];
+
+ if (fonts[Font].isCID)
+ ReadASubr(Start,End,GBias,0,hGSubrsUsed,lGSubrsUsed,null);
+ else
+ {
+ ReadASubr(Start,End,GBias,LBias,hSubrsUsedNonCID,lSubrsUsedNonCID,fonts[Font].SubrsOffsets);
+ if (SizeOfNonCIDSubrsUsed < lSubrsUsedNonCID.size())
+ {
+ for (int j=SizeOfNonCIDSubrsUsed;j=0)
+ {
+ // Read the subr and process
+ int LStart = fonts[Font].SubrsOffsets[LSubr];
+ int LEnd = fonts[Font].SubrsOffsets[LSubr+1];
+ ReadASubr(LStart,LEnd,GBias,LBias,hSubrsUsedNonCID,lSubrsUsedNonCID,fonts[Font].SubrsOffsets);
+ }
+ }
+ SizeOfNonCIDSubrsUsed = lSubrsUsedNonCID.size();
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * The function reads a subrs (glyph info) between begin and end.
+ * Adds calls to a Lsubr to the hSubr and lSubrs.
+ * Adds calls to a Gsubr to the hGSubr and lGSubrs.
+ * @param begin the start point of the subr
+ * @param end the end point of the subr
+ * @param GBias the bias of the Global Subrs
+ * @param LBias the bias of the Local Subrs
+ * @param hSubr the HashMap for the lSubrs
+ * @param lSubr the ArrayList for the lSubrs
+ */
+ protected void ReadASubr(int begin,int end,int GBias,int LBias,HashMap hSubr,ArrayList lSubr,int[] LSubrsOffsets)
+ {
+ // Clear the stack for the subrs
+ EmptyStack();
+ NumOfHints = 0;
+ // Goto begining of the subr
+ seek(begin);
+ while (getPosition() < end)
+ {
+ // Read the next command
+ ReadCommand();
+ int pos = getPosition();
+ Object TopElement=null;
+ if (arg_count > 0)
+ TopElement = args[arg_count-1];
+ int NumOfArgs = arg_count;
+ // Check the modification needed on the Argument Stack according to key;
+ HandelStack();
+ // a call to a Lsubr
+ if (key=="callsubr")
+ {
+ // Verify that arguments are passed
+ if (NumOfArgs > 0)
+ {
+ // Calc the index of the Subrs
+ int Subr = ((Integer)TopElement).intValue() + LBias;
+ // If the subr isn't in the HashMap -> Put in
+ if (!hSubr.containsKey(new Integer (Subr)))
+ {
+ hSubr.put(new Integer(Subr),null);
+ lSubr.add(new Integer(Subr));
+ }
+ CalcHints(LSubrsOffsets[Subr],LSubrsOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
+ seek(pos);
+ }
+ }
+ // a call to a Gsubr
+ else if (key=="callgsubr")
+ {
+ // Verify that arguments are passed
+ if (NumOfArgs > 0)
+ {
+ // Calc the index of the Subrs
+ int Subr = ((Integer)TopElement).intValue() + GBias;
+ // If the subr isn't in the HashMap -> Put in
+ if (!hGSubrsUsed.containsKey(new Integer (Subr)))
+ {
+ hGSubrsUsed.put(new Integer(Subr),null);
+ lGSubrsUsed.add(new Integer(Subr));
+ }
+ CalcHints(gsubrOffsets[Subr],gsubrOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
+ seek(pos);
+ }
+ }
+ // A call to "stem"
+ else if (key == "hstem" || key == "vstem" || key == "hstemhm" || key == "vstemhm")
+ // Increment the NumOfHints by the number couples of of arguments
+ NumOfHints += NumOfArgs/2;
+ // A call to "mask"
+ else if (key == "hintmask" || key == "cntrmask")
+ {
+ // Compute the size of the mask
+ int SizeOfMask = NumOfHints/8;
+ if (NumOfHints%8 != 0 || SizeOfMask == 0)
+ SizeOfMask++;
+ // Continue the pointer in SizeOfMask steps
+ for (int i=0;i flush the stack
+ */
+ protected int StackOpp()
+ {
+ if (key == "ifelse")
+ return -3;
+ if (key == "roll" || key == "put")
+ return -2;
+ if (key == "callsubr" || key == "callgsubr" || key == "add" || key == "sub" ||
+ key == "div" || key == "mul" || key == "drop" || key == "and" ||
+ key == "or" || key == "eq")
+ return -1;
+ if (key == "abs" || key == "neg" || key == "sqrt" || key == "exch" ||
+ key == "index" || key == "get" || key == "not" || key == "return")
+ return 0;
+ if (key == "random" || key == "dup")
+ return 1;
+ return 2;
+ }
+
+ /**
+ * Empty the Type2 Stack
+ *
+ */
+ protected void EmptyStack()
+ {
+ // Null the arguments
+ for (int i=0; i0)
+ {
+ args[arg_count-1]=null;
+ arg_count--;
+ }
+ }
+
+ /**
+ * Add an item to the stack
+ *
+ */
+ protected void PushStack()
+ {
+ arg_count++;
+ }
+
+ /**
+ * The function reads the next command after the file pointer is set
+ */
+ protected void ReadCommand()
+ {
+ key = null;
+ boolean gotKey = false;
+ // Until a key is found
+ while (!gotKey) {
+ // Read the first Char
+ char b0 = getCard8();
+ // decode according to the type1/type2 format
+ if (b0 == 28) // the two next bytes represent a short int;
+ {
+ int first = getCard8();
+ int second = getCard8();
+ args[arg_count] = new Integer(first<<8 | second);
+ arg_count++;
+ continue;
+ }
+ if (b0 >= 32 && b0 <= 246) // The byte read is the byte;
+ {
+ args[arg_count] = new Integer(b0 - 139);
+ arg_count++;
+ continue;
+ }
+ if (b0 >= 247 && b0 <= 250) // The byte read and the next byte constetute a short int
+ {
+ int w = getCard8();
+ args[arg_count] = new Integer((b0-247)*256 + w + 108);
+ arg_count++;
+ continue;
+ }
+ if (b0 >= 251 && b0 <= 254)// Same as above except negative
+ {
+ int w = getCard8();
+ args[arg_count] = new Integer(-(b0-251)*256 - w - 108);
+ arg_count++;
+ continue;
+ }
+ if (b0 == 255)// The next for bytes represent a double.
+ {
+ int first = getCard8();
+ int second = getCard8();
+ int third = getCard8();
+ int fourth = getCard8();
+ args[arg_count] = new Integer(first<<24 | second<<16 | third<<8 | fourth);
+ arg_count++;
+ continue;
+ }
+ if (b0<=31 && b0 != 28) // An operator was found.. Set Key.
+ {
+ gotKey=true;
+ // 12 is an escape command therefor the next byte is a part
+ // of this command
+ if (b0 == 12)
+ {
+ int b1 = getCard8();
+ if (b1>SubrsEscapeFuncs.length-1)
+ b1 = SubrsEscapeFuncs.length-1;
+ key = SubrsEscapeFuncs[b1];
+ }
+ else
+ key = SubrsFunctions[b0];
+ continue;
+ }
+ }
+ }
+
+ /**
+ * The function reads the subroutine and returns the number of the hint in it.
+ * If a call to another subroutine is found the function calls recursively.
+ * @param begin the start point of the subr
+ * @param end the end point of the subr
+ * @param LBias the bias of the Local Subrs
+ * @param GBias the bias of the Global Subrs
+ * @param LSubrsOffsets The Offsets array of the subroutines
+ * @return The number of hints in the subroutine read.
+ */
+ protected int CalcHints(int begin,int end,int LBias,int GBias,int[] LSubrsOffsets)
+ {
+ // Goto begining of the subr
+ seek(begin);
+ while (getPosition() < end)
+ {
+ // Read the next command
+ ReadCommand();
+ int pos = getPosition();
+ Object TopElement = null;
+ if (arg_count>0)
+ TopElement = args[arg_count-1];
+ int NumOfArgs = arg_count;
+ //Check the modification needed on the Argument Stack according to key;
+ HandelStack();
+ // a call to a Lsubr
+ if (key=="callsubr")
+ {
+ if (NumOfArgs>0)
+ {
+ int Subr = ((Integer)TopElement).intValue() + LBias;
+ CalcHints(LSubrsOffsets[Subr],LSubrsOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
+ seek(pos);
+ }
+ }
+ // a call to a Gsubr
+ else if (key=="callgsubr")
+ {
+ if (NumOfArgs>0)
+ {
+ int Subr = ((Integer)TopElement).intValue() + GBias;
+ CalcHints(gsubrOffsets[Subr],gsubrOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
+ seek(pos);
+ }
+ }
+ // A call to "stem"
+ else if (key == "hstem" || key == "vstem" || key == "hstemhm" || key == "vstemhm")
+ // Increment the NumOfHints by the number couples of of arguments
+ NumOfHints += NumOfArgs/2;
+ // A call to "mask"
+ else if (key == "hintmask" || key == "cntrmask")
+ {
+ // Compute the size of the mask
+ int SizeOfMask = NumOfHints/8;
+ if (NumOfHints%8 != 0 || SizeOfMask == 0)
+ SizeOfMask++;
+ // Continue the pointer in SizeOfMask steps
+ for (int i=0;i>> 8) & 0xff);
+ NewIndex[Place++] = (byte) ((Count >>> 0) & 0xff);
+ // Write the offsize field
+ NewIndex[Place++] = Offsize;
+ // Write the offset array according to the offsize
+ for (int i=0;i>> 24) & 0xff);
+ case 3:
+ NewIndex[Place++] = (byte) ((Num >>> 16) & 0xff);
+ case 2:
+ NewIndex[Place++] = (byte) ((Num >>> 8) & 0xff);
+ case 1:
+ NewIndex[Place++] = (byte) ((Num >>> 0) & 0xff);
+ }
+ }
+ // Write the new object array one by one
+ for (int i=0;i=0)
+ OutputList.addLast(new RangeItem(buf,fonts[Font].fdselectOffset,fonts[Font].FDSelectLength));
+ // Else create a new one
+ else
+ CreateFDSelect(fdselectRef,fonts[Font].nglyphs);
+
+ // Copy the Charset
+ // Mark the beginning and copy entirly
+ OutputList.addLast(new MarkerItem(charsetRef));
+ OutputList.addLast(new RangeItem(buf,fonts[Font].charsetOffset,fonts[Font].CharsetLength));
+
+ // Copy the FDArray
+ // If an FDArray exists
+ if (fonts[Font].fdarrayOffset>=0)
+ {
+ // Mark the beginning
+ OutputList.addLast(new MarkerItem(fdarrayRef));
+ // Build a new FDArray with its private dicts and their LSubrs
+ Reconstruct(Font);
+ }
+ else
+ // Else create a new one
+ CreateFDArray(fdarrayRef,privateRef,Font);
+
+ }
+ // If the font is not CID
+ else
+ {
+ // create FDSelect
+ CreateFDSelect(fdselectRef,fonts[Font].nglyphs);
+ // recreate a new charset
+ CreateCharset(charsetRef,fonts[Font].nglyphs);
+ // create a font dict index (fdarray)
+ CreateFDArray(fdarrayRef,privateRef,Font);
+ }
+
+ // if a private dict exists insert its subsetted version
+ if (fonts[Font].privateOffset>=0)
+ {
+ // Mark the beginning of the private dict
+ IndexBaseItem PrivateBase = new IndexBaseItem();
+ OutputList.addLast(PrivateBase);
+ OutputList.addLast(new MarkerItem(privateRef));
+
+ OffsetItem Subr = new DictOffsetItem();
+ // Build and copy the new private dict
+ CreateNonCIDPrivate(Font,Subr);
+ // Copy the new LSubrs index
+ CreateNonCIDSubrs(Font,PrivateBase,Subr);
+ }
+
+ // copy the charstring index
+ OutputList.addLast(new MarkerItem(charstringsRef));
+
+ // Add the subsetted charstring
+ OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewCharStringsIndex),0,NewCharStringsIndex.length));
+
+ // now create the new CFF font
+ int[] currentOffset = new int[1];
+ currentOffset[0] = 0;
+ // Count and save the offset for each item
+ Iterator listIter = OutputList.iterator();
+ while ( listIter.hasNext() ) {
+ Item item = (Item) listIter.next();
+ item.increment(currentOffset);
+ }
+ // Compute the Xref for each of the offset items
+ listIter = OutputList.iterator();
+ while ( listIter.hasNext() ) {
+ Item item = (Item) listIter.next();
+ item.xref();
+ }
+
+ int size = currentOffset[0];
+ byte[] b = new byte[size];
+
+ // Emit all the items into the new byte array
+ listIter = OutputList.iterator();
+ while ( listIter.hasNext() ) {
+ Item item = (Item) listIter.next();
+ item.emit(b);
+ }
+ // Return the new stream
+ return b;
+ }
+
+ /**
+ * Function Copies the header from the original fileto the output list
+ */
+ protected void CopyHeader()
+ {
+ seek(0);
+ int major = getCard8();
+ int minor = getCard8();
+ int hdrSize = getCard8();
+ int offSize = getCard8();
+ nextIndexOffset = hdrSize;
+ OutputList.addLast(new RangeItem(buf,0,hdrSize));
+ }
+
+ /**
+ * Function Build the header of an index
+ * @param Count the count field of the index
+ * @param Offsize the offsize field of the index
+ * @param First the first offset of the index
+ */
+ protected void BuildIndexHeader(int Count,int Offsize,int First)
+ {
+ // Add the count field
+ OutputList.addLast(new UInt16Item((char)Count)); // count
+ // Add the offsize field
+ OutputList.addLast(new UInt8Item((char)Offsize)); // offSize
+ // Add the first offset according to the offsize
+ switch(Offsize){
+ case 1:
+ OutputList.addLast(new UInt8Item((char)First)); // first offset
+ break;
+ case 2:
+ OutputList.addLast(new UInt16Item((char)First)); // first offset
+ break;
+ case 3:
+ OutputList.addLast(new UInt24Item((char)First)); // first offset
+ break;
+ case 4:
+ OutputList.addLast(new UInt32Item((char)First)); // first offset
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Function adds the keys into the TopDict
+ * @param fdarrayRef OffsetItem for the FDArray
+ * @param fdselectRef OffsetItem for the FDSelect
+ * @param charsetRef OffsetItem for the CharSet
+ * @param charstringsRef OffsetItem for the CharString
+ */
+ protected void CreateKeys(OffsetItem fdarrayRef,OffsetItem fdselectRef,OffsetItem charsetRef,OffsetItem charstringsRef)
+ {
+ // create an FDArray key
+ OutputList.addLast(fdarrayRef);
+ OutputList.addLast(new UInt8Item((char)12));
+ OutputList.addLast(new UInt8Item((char)36));
+ // create an FDSelect key
+ OutputList.addLast(fdselectRef);
+ OutputList.addLast(new UInt8Item((char)12));
+ OutputList.addLast(new UInt8Item((char)37));
+ // create an charset key
+ OutputList.addLast(charsetRef);
+ OutputList.addLast(new UInt8Item((char)15));
+ // create a CharStrings key
+ OutputList.addLast(charstringsRef);
+ OutputList.addLast(new UInt8Item((char)17));
+ }
+
+ /**
+ * Function takes the original string item and adds the new strings
+ * to accomodate the CID rules
+ * @param Font the font
+ */
+ protected void CreateNewStringIndex(int Font)
+ {
+ String fdFontName = fonts[Font].name+"-OneRange";
+ if (fdFontName.length() > 127)
+ fdFontName = fdFontName.substring(0,127);
+ String extraStrings = "Adobe"+"Identity"+fdFontName;
+
+ int origStringsLen = stringOffsets[stringOffsets.length-1]
+ - stringOffsets[0];
+ int stringsBaseOffset = stringOffsets[0]-1;
+
+ byte stringsIndexOffSize;
+ if (origStringsLen+extraStrings.length() <= 0xff) stringsIndexOffSize = 1;
+ else if (origStringsLen+extraStrings.length() <= 0xffff) stringsIndexOffSize = 2;
+ else if (origStringsLen+extraStrings.length() <= 0xffffff) stringsIndexOffSize = 3;
+ else stringsIndexOffSize = 4;
+
+ OutputList.addLast(new UInt16Item((char)((stringOffsets.length-1)+3))); // count
+ OutputList.addLast(new UInt8Item((char)stringsIndexOffSize)); // offSize
+ for (int i=0; i= 0)
+ {
+ OutputList.addLast(new SubrMarkerItem(fdSubrs[i],fdPrivateBase[i]));
+ OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewLSubrsIndex[i]),0,NewLSubrsIndex[i].length));
+ }
+ }
+ }
+
+ /**
+ * Calculates how many byte it took to write the offset for the subrs in a specific
+ * private dict.
+ * @param Offset The Offset for the private dict
+ * @param Size The size of the private dict
+ * @return The size of the offset of the subrs in the private dict
+ */
+ int CalcSubrOffsetSize(int Offset,int Size)
+ {
+ // Set the size to 0
+ int OffsetSize = 0;
+ // Go to the beginning of the private dict
+ seek(Offset);
+ // Go until the end of the private dict
+ while (getPosition() < Offset+Size)
+ {
+ int p1 = getPosition();
+ getDictItem();
+ int p2 = getPosition();
+ // When reached to the subrs offset
+ if (key=="Subrs") {
+ // The Offsize (minus the subrs key)
+ OffsetSize = p2-p1-1;
+ }
+ // All other keys are ignored
+ }
+ // return the size
+ return OffsetSize;
+ }
+
+ /**
+ * Function computes the size of an index
+ * @param indexOffset The offset for the computed index
+ * @return The size of the index
+ */
+ protected int countEntireIndexRange(int indexOffset)
+ {
+ // Go to the beginning of the index
+ seek(indexOffset);
+ // Read the count field
+ int count = getCard16();
+ // If count==0 -> size=2
+ if (count==0)
+ return 2;
+ else
+ {
+ // Read the offsize field
+ int indexOffSize = getCard8();
+ // Go to the last element of the offset array
+ seek(indexOffset+2+1+count*indexOffSize);
+ // The size of the object array is the value of the last element-1
+ int size = getOffset(indexOffSize)-1;
+ // Return the size of the entire index
+ return 2+1+(count+1)*indexOffSize+size;
+ }
+ }
+
+ /**
+ * The function creates a private dict for a font that was not CID
+ * All the keys are copied as is except for the subrs key
+ * @param Font the font
+ * @param Subr The OffsetItem for the subrs of the private
+ */
+ void CreateNonCIDPrivate(int Font,OffsetItem Subr)
+ {
+ // Go to the beginning of the private dict and read untill the end
+ seek(fonts[Font].privateOffset);
+ while (getPosition() < fonts[Font].privateOffset+fonts[Font].privateLength)
+ {
+ int p1 = getPosition();
+ getDictItem();
+ int p2 = getPosition();
+ // If the dictItem is the "Subrs" then,
+ // use marker for offset and write operator number
+ if (key=="Subrs") {
+ OutputList.addLast(Subr);
+ OutputList.addLast(new UInt8Item((char)19)); // Subrs
+ }
+ // Else copy the entire range
+ else
+ OutputList.addLast(new RangeItem(buf,p1,p2-p1));
+ }
+ }
+
+ /**
+ * the function marks the beginning of the subrs index and adds the subsetted subrs
+ * index to the output list.
+ * @param Font the font
+ * @param PrivateBase IndexBaseItem for the private that's referencing to the subrs
+ * @param Subrs OffsetItem for the subrs
+ * @throws IOException
+ */
+ void CreateNonCIDSubrs(int Font,IndexBaseItem PrivateBase,OffsetItem Subrs)throws IOException
+ {
+ // Mark the beginning of the Subrs index
+ OutputList.addLast(new SubrMarkerItem(Subrs,PrivateBase));
+ // Put the subsetted new subrs index
+ OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewSubrsIndexNonCID),0,NewSubrsIndexNonCID.length));
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/CJKFont.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/CJKFont.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/CJKFont.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/CJKFont.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,616 @@
+/*
+ * $Id: CJKFont.java,v 1.29 2002/07/09 11:28:22 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2000, 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.DocumentException;
+import java.io.*;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Enumeration;
+
+/**
+ * Creates a CJK font compatible with the fonts in the Adobe Asian font Pack.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+
+class CJKFont extends BaseFont {
+ /** The encoding used in the PDF document for CJK fonts
+ */
+ static final String CJK_ENCODING = "UnicodeBigUnmarked";
+ private static final int FIRST = 0;
+ private static final int BRACKET = 1;
+ private static final int SERIAL = 2;
+ private static final int V1Y = 880;
+
+ static Properties cjkFonts = new Properties();
+ static Properties cjkEncodings = new Properties();
+ static Hashtable allCMaps = new Hashtable();
+ static Hashtable allFonts = new Hashtable();
+ private static boolean propertiesLoaded = false;
+
+ /** The font name */
+ private String fontName;
+ /** The style modifier */
+ private String style = "";
+ /** The CMap name associated with this font */
+ private String CMap;
+
+ private boolean cidDirect = false;
+
+ private char[] translationMap;
+ private IntHashtable vMetrics;
+ private IntHashtable hMetrics;
+ private HashMap fontDesc;
+ private boolean vertical = false;
+
+ private static void loadProperties() {
+ if (propertiesLoaded)
+ return;
+ synchronized (allFonts) {
+ if (propertiesLoaded)
+ return;
+ try {
+ InputStream is = getResourceStream(RESOURCE_PATH + "cjkfonts.properties");
+ cjkFonts.load(is);
+ is.close();
+ is = getResourceStream(RESOURCE_PATH + "cjkencodings.properties");
+ cjkEncodings.load(is);
+ is.close();
+ }
+ catch (Exception e) {
+ cjkFonts = new Properties();
+ cjkEncodings = new Properties();
+ }
+ propertiesLoaded = true;
+ }
+ }
+
+ /** Creates a CJK font.
+ * @param fontName the name of the font
+ * @param enc the encoding of the font
+ * @param emb always false
. CJK font and not embedded
+ * @throws DocumentException on error
+ * @throws IOException on error
+ */
+ CJKFont(String fontName, String enc, boolean emb) throws DocumentException, IOException {
+ loadProperties();
+ fontType = FONT_TYPE_CJK;
+ String nameBase = getBaseName(fontName);
+ if (!isCJKFont(nameBase, enc))
+ throw new DocumentException("Font '" + fontName + "' with '" + enc + "' encoding is not a CJK font.");
+ if (nameBase.length() < fontName.length()) {
+ style = fontName.substring(nameBase.length());
+ fontName = nameBase;
+ }
+ this.fontName = fontName;
+ encoding = CJK_ENCODING;
+ vertical = enc.endsWith("V");
+ CMap = enc;
+ if (enc.startsWith("Identity-")) {
+ cidDirect = true;
+ String s = cjkFonts.getProperty(fontName);
+ s = s.substring(0, s.indexOf('_'));
+ char c[] = (char[])allCMaps.get(s);
+ if (c == null) {
+ c = readCMap(s);
+ if (c == null)
+ throw new DocumentException("The cmap " + s + " does not exist as a resource.");
+ c[CID_NEWLINE] = '\n';
+ allCMaps.put(s, c);
+ }
+ translationMap = c;
+ }
+ else {
+ char c[] = (char[])allCMaps.get(enc);
+ if (c == null) {
+ String s = cjkEncodings.getProperty(enc);
+ if (s == null)
+ throw new DocumentException("The resource cjkencodings.properties does not contain the encoding " + enc);
+ StringTokenizer tk = new StringTokenizer(s);
+ String nt = tk.nextToken();
+ c = (char[])allCMaps.get(nt);
+ if (c == null) {
+ c = readCMap(nt);
+ allCMaps.put(nt, c);
+ }
+ if (tk.hasMoreTokens()) {
+ String nt2 = tk.nextToken();
+ char m2[] = readCMap(nt2);
+ for (int k = 0; k < 0x10000; ++k) {
+ if (m2[k] == 0)
+ m2[k] = c[k];
+ }
+ allCMaps.put(enc, m2);
+ c = m2;
+ }
+ }
+ translationMap = c;
+ }
+ fontDesc = (HashMap)allFonts.get(fontName);
+ if (fontDesc == null) {
+ fontDesc = readFontProperties(fontName);
+ allFonts.put(fontName, fontDesc);
+ }
+ hMetrics = (IntHashtable)fontDesc.get("W");
+ vMetrics = (IntHashtable)fontDesc.get("W2");
+ }
+
+ /** Checks if its a valid CJK font.
+ * @param fontName the font name
+ * @param enc the encoding
+ * @return true
if it is CJK font
+ */
+ public static boolean isCJKFont(String fontName, String enc) {
+ loadProperties();
+ String encodings = cjkFonts.getProperty(fontName);
+ return (encodings != null && (enc.equals("Identity-H") || enc.equals("Identity-V") || encodings.indexOf("_" + enc + "_") >= 0));
+ }
+
+ public int getWidth(String text) {
+ int total = 0;
+ for (int k = 0; k < text.length(); ++k) {
+ int c = text.charAt(k);
+ if (!cidDirect)
+ c = translationMap[c];
+ int v;
+ if (vertical)
+ v = vMetrics.get(c);
+ else
+ v = hMetrics.get(c);
+ if (v > 0)
+ total += v;
+ else
+ total += 1000;
+ }
+ return total;
+ }
+
+ int getRawWidth(int c, String name) {
+ return 0;
+ }
+
+ public int getKerning(char char1, char char2) {
+ return 0;
+ }
+
+ private PdfDictionary getFontDescriptor() {
+ PdfDictionary dic = new PdfDictionary(PdfName.FONTDESCRIPTOR);
+ dic.put(PdfName.ASCENT, new PdfLiteral((String)fontDesc.get("Ascent")));
+ dic.put(PdfName.CAPHEIGHT, new PdfLiteral((String)fontDesc.get("CapHeight")));
+ dic.put(PdfName.DESCENT, new PdfLiteral((String)fontDesc.get("Descent")));
+ dic.put(PdfName.FLAGS, new PdfLiteral((String)fontDesc.get("Flags")));
+ dic.put(PdfName.FONTBBOX, new PdfLiteral((String)fontDesc.get("FontBBox")));
+ dic.put(PdfName.FONTNAME, new PdfName(fontName + style));
+ dic.put(PdfName.ITALICANGLE, new PdfLiteral((String)fontDesc.get("ItalicAngle")));
+ dic.put(PdfName.STEMV, new PdfLiteral((String)fontDesc.get("StemV")));
+ PdfDictionary pdic = new PdfDictionary();
+ pdic.put(PdfName.PANOSE, new PdfString((String)fontDesc.get("Panose"), null));
+ dic.put(PdfName.STYLE, pdic);
+ return dic;
+ }
+
+ private PdfDictionary getCIDFont(PdfIndirectReference fontDescriptor, IntHashtable cjkTag) {
+ PdfDictionary dic = new PdfDictionary(PdfName.FONT);
+ dic.put(PdfName.SUBTYPE, PdfName.CIDFONTTYPE0);
+ dic.put(PdfName.BASEFONT, new PdfName(fontName + style));
+ dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
+ int keys[] = cjkTag.toOrderedKeys();
+ String w = convertToHCIDMetrics(keys, hMetrics);
+ if (w != null)
+ dic.put(PdfName.W, new PdfLiteral(w));
+ if (vertical) {
+ w = convertToVCIDMetrics(keys, vMetrics, hMetrics);;
+ if (w != null)
+ dic.put(PdfName.W2, new PdfLiteral(w));
+ }
+ else
+ dic.put(PdfName.DW, new PdfNumber(1000));
+ PdfDictionary cdic = new PdfDictionary();
+ cdic.put(PdfName.REGISTRY, new PdfString((String)fontDesc.get("Registry"), null));
+ cdic.put(PdfName.ORDERING, new PdfString((String)fontDesc.get("Ordering"), null));
+ cdic.put(PdfName.SUPPLEMENT, new PdfLiteral((String)fontDesc.get("Supplement")));
+ dic.put(PdfName.CIDSYSTEMINFO, cdic);
+ return dic;
+ }
+
+ private PdfDictionary getFontBaseType(PdfIndirectReference CIDFont) {
+ PdfDictionary dic = new PdfDictionary(PdfName.FONT);
+ dic.put(PdfName.SUBTYPE, PdfName.TYPE0);
+ String name = fontName;
+ if (style.length() > 0)
+ name += "-" + style.substring(1);
+ name += "-" + CMap;
+ dic.put(PdfName.BASEFONT, new PdfName(name));
+ dic.put(PdfName.ENCODING, new PdfName(CMap));
+ dic.put(PdfName.DESCENDANTFONTS, new PdfArray(CIDFont));
+ return dic;
+ }
+
+ void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
+ IntHashtable cjkTag = (IntHashtable)params[0];
+ PdfIndirectReference ind_font = null;
+ PdfObject pobj = null;
+ PdfIndirectObject obj = null;
+ pobj = getFontDescriptor();
+ if (pobj != null){
+ obj = writer.addToBody(pobj);
+ ind_font = obj.getIndirectReference();
+ }
+ pobj = getCIDFont(ind_font, cjkTag);
+ if (pobj != null){
+ obj = writer.addToBody(pobj);
+ ind_font = obj.getIndirectReference();
+ }
+ pobj = getFontBaseType(ind_font);
+ writer.addToBody(pobj, ref);
+ }
+
+ private float getDescNumber(String name) {
+ return Integer.parseInt((String)fontDesc.get(name));
+ }
+
+ private float getBBox(int idx) {
+ String s = (String)fontDesc.get("FontBBox");
+ StringTokenizer tk = new StringTokenizer(s, " []\r\n\t\f");
+ String ret = tk.nextToken();
+ for (int k = 0; k < idx; ++k)
+ ret = tk.nextToken();
+ return Integer.parseInt(ret);
+ }
+
+ /** Gets the font parameter identified by key
. Valid values
+ * for key
are ASCENT
, CAPHEIGHT
, DESCENT
+ * and ITALICANGLE
.
+ * @param key the parameter to be extracted
+ * @param fontSize the font size in points
+ * @return the parameter in points
+ */
+ public float getFontDescriptor(int key, float fontSize) {
+ switch (key) {
+ case AWT_ASCENT:
+ case ASCENT:
+ return getDescNumber("Ascent") * fontSize / 1000;
+ case CAPHEIGHT:
+ return getDescNumber("CapHeight") * fontSize / 1000;
+ case AWT_DESCENT:
+ case DESCENT:
+ return getDescNumber("Descent") * fontSize / 1000;
+ case ITALICANGLE:
+ return getDescNumber("ItalicAngle");
+ case BBOXLLX:
+ return fontSize * getBBox(0) / 1000;
+ case BBOXLLY:
+ return fontSize * getBBox(1) / 1000;
+ case BBOXURX:
+ return fontSize * getBBox(2) / 1000;
+ case BBOXURY:
+ return fontSize * getBBox(3) / 1000;
+ case AWT_LEADING:
+ return 0;
+ case AWT_MAXADVANCE:
+ return fontSize * (getBBox(2) - getBBox(0)) / 1000;
+ }
+ return 0;
+ }
+
+ public String getPostscriptFontName() {
+ return fontName;
+ }
+
+ /** Gets the full name of the font. If it is a True Type font
+ * each array element will have {Platform ID, Platform Encoding ID,
+ * Language ID, font name}. The interpretation of this values can be
+ * found in the Open Type specification, chapter 2, in the 'name' table.
+ * For the other fonts the array has a single element with {"", "", "",
+ * font name}.
+ * @return the full name of the font
+ */
+ public String[][] getFullFontName() {
+ return new String[][]{{"", "", "", fontName}};
+ }
+
+ /** Gets the family name of the font. If it is a True Type font
+ * each array element will have {Platform ID, Platform Encoding ID,
+ * Language ID, font name}. The interpretation of this values can be
+ * found in the Open Type specification, chapter 2, in the 'name' table.
+ * For the other fonts the array has a single element with {"", "", "",
+ * font name}.
+ * @return the family name of the font
+ */
+ public String[][] getFamilyFontName() {
+ return getFullFontName();
+ }
+
+ static char[] readCMap(String name) {
+ try {
+ name = name + ".cmap";
+ InputStream is = getResourceStream(RESOURCE_PATH + name);
+ char c[] = new char[0x10000];
+ for (int k = 0; k < 0x10000; ++k)
+ c[k] = (char)((is.read() << 8) + is.read());
+ return c;
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ return null;
+ }
+
+ static IntHashtable createMetric(String s) {
+ IntHashtable h = new IntHashtable();
+ StringTokenizer tk = new StringTokenizer(s);
+ while (tk.hasMoreTokens()) {
+ int n1 = Integer.parseInt(tk.nextToken());
+ h.put(n1, Integer.parseInt(tk.nextToken()));
+ }
+ return h;
+ }
+
+ static String convertToHCIDMetrics(int keys[], IntHashtable h) {
+ if (keys.length == 0)
+ return null;
+ int lastCid = 0;
+ int lastValue = 0;
+ int start;
+ for (start = 0; start < keys.length; ++start) {
+ lastCid = keys[start];
+ lastValue = h.get(lastCid);
+ if (lastValue != 0) {
+ ++start;
+ break;
+ }
+ }
+ if (lastValue == 0)
+ return null;
+ StringBuffer buf = new StringBuffer();
+ buf.append('[');
+ buf.append(lastCid);
+ int state = FIRST;
+ for (int k = start; k < keys.length; ++k) {
+ int cid = keys[k];
+ int value = h.get(cid);
+ if (value == 0)
+ continue;
+ switch (state) {
+ case FIRST: {
+ if (cid == lastCid + 1 && value == lastValue) {
+ state = SERIAL;
+ }
+ else if (cid == lastCid + 1) {
+ state = BRACKET;
+ buf.append('[').append(lastValue);
+ }
+ else {
+ buf.append('[').append(lastValue).append(']').append(cid);
+ }
+ break;
+ }
+ case BRACKET: {
+ if (cid == lastCid + 1 && value == lastValue) {
+ state = SERIAL;
+ buf.append(']').append(lastCid);
+ }
+ else if (cid == lastCid + 1) {
+ buf.append(' ').append(lastValue);
+ }
+ else {
+ state = FIRST;
+ buf.append(' ').append(lastValue).append(']').append(cid);
+ }
+ break;
+ }
+ case SERIAL: {
+ if (cid != lastCid + 1 || value != lastValue) {
+ buf.append(' ').append(lastCid).append(' ').append(lastValue).append(' ').append(cid);
+ state = FIRST;
+ }
+ break;
+ }
+ }
+ lastValue = value;
+ lastCid = cid;
+ }
+ switch (state) {
+ case FIRST: {
+ buf.append('[').append(lastValue).append("]]");
+ break;
+ }
+ case BRACKET: {
+ buf.append(' ').append(lastValue).append("]]");
+ break;
+ }
+ case SERIAL: {
+ buf.append(' ').append(lastCid).append(' ').append(lastValue).append(']');
+ break;
+ }
+ }
+ return buf.toString();
+ }
+
+ static String convertToVCIDMetrics(int keys[], IntHashtable v, IntHashtable h) {
+ if (keys.length == 0)
+ return null;
+ int lastCid = 0;
+ int lastValue = 0;
+ int lastHValue = 0;
+ int start;
+ for (start = 0; start < keys.length; ++start) {
+ lastCid = keys[start];
+ lastValue = v.get(lastCid);
+ if (lastValue != 0) {
+ ++start;
+ break;
+ }
+ else
+ lastHValue = h.get(lastCid);
+ }
+ if (lastValue == 0)
+ return null;
+ if (lastHValue == 0)
+ lastHValue = 1000;
+ StringBuffer buf = new StringBuffer();
+ buf.append('[');
+ buf.append(lastCid);
+ int state = FIRST;
+ for (int k = start; k < keys.length; ++k) {
+ int cid = keys[k];
+ int value = v.get(cid);
+ if (value == 0)
+ continue;
+ int hValue = h.get(lastCid);
+ if (hValue == 0)
+ hValue = 1000;
+ switch (state) {
+ case FIRST: {
+ if (cid == lastCid + 1 && value == lastValue && hValue == lastHValue) {
+ state = SERIAL;
+ }
+ else {
+ buf.append(' ').append(lastCid).append(' ').append(-lastValue).append(' ').append(lastHValue / 2).append(' ').append(V1Y).append(' ').append(cid);
+ }
+ break;
+ }
+ case SERIAL: {
+ if (cid != lastCid + 1 || value != lastValue || hValue != lastHValue) {
+ buf.append(' ').append(lastCid).append(' ').append(-lastValue).append(' ').append(lastHValue / 2).append(' ').append(V1Y).append(' ').append(cid);
+ state = FIRST;
+ }
+ break;
+ }
+ }
+ lastValue = value;
+ lastCid = cid;
+ lastHValue = hValue;
+ }
+ buf.append(' ').append(lastCid).append(' ').append(-lastValue).append(' ').append(lastHValue / 2).append(' ').append(V1Y).append(" ]");
+ return buf.toString();
+ }
+
+ static HashMap readFontProperties(String name) {
+ try {
+ name += ".properties";
+ InputStream is = getResourceStream(RESOURCE_PATH + name);
+ Properties p = new Properties();
+ p.load(is);
+ is.close();
+ IntHashtable W = createMetric(p.getProperty("W"));
+ p.remove("W");
+ IntHashtable W2 = createMetric(p.getProperty("W2"));
+ p.remove("W2");
+ HashMap map = new HashMap();
+ for (Enumeration e = p.keys(); e.hasMoreElements();) {
+ Object obj = e.nextElement();
+ map.put(obj, p.getProperty((String)obj));
+ }
+ map.put("W", W);
+ map.put("W2", W2);
+ return map;
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ return null;
+ }
+
+ public char getUnicodeEquivalent(char c) {
+ if (cidDirect)
+ return translationMap[c];
+ return c;
+ }
+
+ public char getCidCode(char c) {
+ if (cidDirect)
+ return c;
+ return translationMap[c];
+ }
+
+ /** Checks if the font has any kerning pairs.
+ * @return always false
+ */
+ public boolean hasKernPairs() {
+ return false;
+ }
+
+ /**
+ * Checks if a character exists in this font.
+ * @param c the character to check
+ * @return true
if the character has a glyph,
+ * false
otherwise
+ */
+ public boolean charExists(char c) {
+ return translationMap[c] != 0;
+ }
+
+ /**
+ * Sets the character advance.
+ * @param c the character
+ * @param advance the character advance normalized to 1000 units
+ * @return true
if the advance was set,
+ * false
otherwise. Will always return false
+ */
+ public boolean setCharAdvance(char c, int advance) {
+ return false;
+ }
+
+ /**
+ * Sets the font name that will appear in the pdf font dictionary.
+ * Use with care as it can easily make a font unreadable if not embedded.
+ * @param name the new font name
+ */
+ public void setPostscriptFontName(String name) {
+ fontName = name;
+ }
+
+ public boolean setKerning(char char1, char char2, int kern) {
+ return false;
+ }
+
+ public int[] getCharBBox(char c) {
+ return null;
+ }
+
+ protected int[] getRawCharBBox(int c, String name) {
+ return null;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/CMYKColor.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/CMYKColor.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/CMYKColor.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/CMYKColor.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,108 @@
+/*
+ * $Id: CMYKColor.java,v 1.43 2005/05/02 11:12:44 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class CMYKColor extends ExtendedColor {
+
+ float cyan;
+ float magenta;
+ float yellow;
+ float black;
+
+ /**
+ * Constructs a CMYK Color beased on 4 colorvalues (values are integers from 0 to 255).
+ * @param intCyan
+ * @param intMagenta
+ * @param intYellow
+ * @param intBlack
+ */
+ public CMYKColor(int intCyan, int intMagenta, int intYellow, int intBlack) {
+ this((float)intCyan / 255f, (float)intMagenta / 255f, (float)intYellow / 255f, (float)intBlack / 255f);
+ }
+
+ /**
+ * Construct a CMYK Color.
+ * @param floatCyan
+ * @param floatMagenta
+ * @param floatYellow
+ * @param floatBlack
+ */
+ public CMYKColor(float floatCyan, float floatMagenta, float floatYellow, float floatBlack) {
+ super(TYPE_CMYK, 1f - floatCyan - floatBlack, 1f - floatMagenta - floatBlack, 1f - floatYellow - floatBlack);
+ cyan = normalize(floatCyan);
+ magenta = normalize(floatMagenta);
+ yellow = normalize(floatYellow);
+ black = normalize(floatBlack);
+ }
+
+ /**
+ * @return the cyan value
+ */
+ public float getCyan() {
+ return cyan;
+ }
+
+ /**
+ * @return the magenta value
+ */
+ public float getMagenta() {
+ return magenta;
+ }
+
+ /**
+ * @return the yellow value
+ */
+ public float getYellow() {
+ return yellow;
+ }
+
+ /**
+ * @return the black value
+ */
+ public float getBlack() {
+ return black;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ColorDetails.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ColorDetails.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ColorDetails.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ColorDetails.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,91 @@
+/*
+ * $Id: ColorDetails.java,v 1.11 2002/06/20 13:06:47 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+/** Each spotcolor in the document will have an instance of this class
+ *
+ * @author Phillip Pan (phillip@formstar.com)
+ */
+class ColorDetails {
+
+ /** The indirect reference to this color
+ */
+ PdfIndirectReference indirectReference;
+ /** The color name that appears in the document body stream
+ */
+ PdfName colorName;
+ /** The color
+ */
+ PdfSpotColor spotcolor;
+
+ /** Each spot color used in a document has an instance of this class.
+ * @param colorName the color name
+ * @param indirectReference the indirect reference to the font
+ * @param scolor the PDfSpotColor
+ */
+ ColorDetails(PdfName colorName, PdfIndirectReference indirectReference, PdfSpotColor scolor) {
+ this.colorName = colorName;
+ this.indirectReference = indirectReference;
+ this.spotcolor = scolor;
+ }
+
+ /** Gets the indirect reference to this color.
+ * @return the indirect reference to this color
+ */
+ PdfIndirectReference getIndirectReference() {
+ return indirectReference;
+ }
+
+ /** Gets the color name as it appears in the document body.
+ * @return the color name
+ */
+ PdfName getColorName() {
+ return colorName;
+ }
+
+ /** Gets the SpotColor
object.
+ * @return the PdfSpotColor
+ */
+ PdfObject getSpotColor(PdfWriter writer) throws IOException {
+ return spotcolor.getSpotObject(writer);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ColumnText.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ColumnText.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ColumnText.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ColumnText.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,1429 @@
+/*
+ * $Id: ColumnText.java,v 1.58 2005/01/11 14:14:58 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.Stack;
+import java.util.Iterator;
+import pdftk.com.lowagie.text.Phrase;
+import pdftk.com.lowagie.text.Chunk;
+import pdftk.com.lowagie.text.Paragraph;
+// import pdftk.com.lowagie.text.Graphic; ssteward: dropped in 1.44
+import pdftk.com.lowagie.text.ListItem;
+import pdftk.com.lowagie.text.Element;
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.ExceptionConverter;
+// import pdftk.com.lowagie.text.Image; ssteward: dropped in 1.44
+
+/**
+ * Formats text in a columnwise form. The text is bound
+ * on the left and on the right by a sequence of lines. This allows the column
+ * to have any shape, not only rectangular.
+ *
+ * Several parameters can be set like the first paragraph line indent and
+ * extra space between paragraphs.
+ *
+ * A call to the method go
will return one of the following
+ * situations: the column ended or the text ended.
+ *
+ * I the column ended, a new column definition can be loaded with the method
+ * setColumns
and the method go
can be called again.
+ *
+ * If the text ended, more text can be loaded with addText
+ * and the method go
can be called again.
+ * The only limitation is that one or more complete paragraphs must be loaded
+ * each time.
+ *
+ * Full bidirectional reordering is supported. If the run direction is
+ * PdfWriter.RUN_DIRECTION_RTL
the meaning of the horizontal
+ * alignments and margins is mirrored.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+
+public class ColumnText {
+ /** Eliminate the arabic vowels */
+ public static final int AR_NOVOWEL = ArabicLigaturizer.ar_novowel;
+ /** Compose the tashkeel in the ligatures. */
+ public static final int AR_COMPOSEDTASHKEEL = ArabicLigaturizer.ar_composedtashkeel;
+ /** Do some extra double ligatures. */
+ public static final int AR_LIG = ArabicLigaturizer.ar_lig;
+ /**
+ * Digit shaping option: Replace European digits (U+0030...U+0039) by Arabic-Indic digits.
+ */
+ public static final int DIGITS_EN2AN = ArabicLigaturizer.DIGITS_EN2AN;
+
+ /**
+ * Digit shaping option: Replace Arabic-Indic digits by European digits (U+0030...U+0039).
+ */
+ public static final int DIGITS_AN2EN = ArabicLigaturizer.DIGITS_AN2EN;
+
+ /**
+ * Digit shaping option:
+ * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
+ * if the most recent strongly directional character
+ * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
+ * The initial state at the start of the text is assumed to be not an Arabic,
+ * letter, so European digits at the start of the text will not change.
+ * Compare to DIGITS_ALEN2AN_INIT_AL.
+ */
+ public static final int DIGITS_EN2AN_INIT_LR = ArabicLigaturizer.DIGITS_EN2AN_INIT_LR;
+
+ /**
+ * Digit shaping option:
+ * Replace European digits (U+0030...U+0039) by Arabic-Indic digits
+ * if the most recent strongly directional character
+ * is an Arabic letter (its Bidi direction value is RIGHT_TO_LEFT_ARABIC).
+ * The initial state at the start of the text is assumed to be an Arabic,
+ * letter, so European digits at the start of the text will change.
+ * Compare to DIGITS_ALEN2AN_INT_LR.
+ */
+ public static final int DIGITS_EN2AN_INIT_AL = ArabicLigaturizer.DIGITS_EN2AN_INIT_AL;
+
+ /**
+ * Digit type option: Use Arabic-Indic digits (U+0660...U+0669).
+ */
+ public static final int DIGIT_TYPE_AN = ArabicLigaturizer.DIGIT_TYPE_AN;
+
+ /**
+ * Digit type option: Use Eastern (Extended) Arabic-Indic digits (U+06f0...U+06f9).
+ */
+ public static final int DIGIT_TYPE_AN_EXTENDED = ArabicLigaturizer.DIGIT_TYPE_AN_EXTENDED;
+
+ protected int runDirection = PdfWriter.RUN_DIRECTION_DEFAULT;
+
+ /** the space char ratio */
+ public static final float GLOBAL_SPACE_CHAR_RATIO = 0;
+
+ /** Signals that there is no more text available. */
+ public static final int NO_MORE_TEXT = 1;
+
+ /** Signals that there is no more column. */
+ public static final int NO_MORE_COLUMN = 2;
+
+ /** The column is valid. */
+ protected static final int LINE_STATUS_OK = 0;
+
+ /** The line is out the column limits. */
+ protected static final int LINE_STATUS_OFFLIMITS = 1;
+
+ /** The line cannot fit this column position. */
+ protected static final int LINE_STATUS_NOLINE = 2;
+
+ /** Upper bound of the column. */
+ protected float maxY;
+
+ /** Lower bound of the column. */
+ protected float minY;
+
+ protected float leftX;
+
+ protected float rightX;
+
+ /** The column alignment. Default is left alignment. */
+ protected int alignment = Element.ALIGN_LEFT;
+
+ /** The left column bound. */
+ protected ArrayList leftWall;
+
+ /** The right column bound. */
+ protected ArrayList rightWall;
+
+ /** The chunks that form the text. */
+// protected ArrayList chunks = new ArrayList();
+ protected BidiLine bidiLine;
+
+ /** The current y line location. Text will be written at this line minus the leading. */
+ protected float yLine;
+
+ /** The leading for the current line. */
+ protected float currentLeading = 16;
+
+ /** The fixed text leading. */
+ protected float fixedLeading = 16;
+
+ /** The text leading that is multiplied by the biggest font size in the line. */
+ protected float multipliedLeading = 0;
+
+ /** The PdfContent
where the text will be written to. */
+ protected PdfContentByte canvas;
+
+ /** The line status when trying to fit a line to a column. */
+ protected int lineStatus;
+
+ /** The first paragraph line indent. */
+ protected float indent = 0;
+
+ /** The following paragraph lines indent. */
+ protected float followingIndent = 0;
+
+ /** The right paragraph lines indent. */
+ protected float rightIndent = 0;
+
+ /** The extra space between paragraphs. */
+ protected float extraParagraphSpace = 0;
+
+ /** The width of the line when the column is defined as a simple rectangle. */
+ protected float rectangularWidth = -1;
+
+ protected boolean rectangularMode = false;
+ /** Holds value of property spaceCharRatio. */
+ private float spaceCharRatio = GLOBAL_SPACE_CHAR_RATIO;
+
+ private boolean lastWasNewline = true;
+
+ /** Holds value of property linesWritten. */
+ private int linesWritten;
+
+ private float firstLineY;
+ private boolean firstLineYDone = false;
+
+ /** Holds value of property arabicOptions. */
+ private int arabicOptions = 0;
+
+ protected float descender;
+
+ protected boolean composite = false;
+
+ protected ColumnText compositeColumn;
+
+ protected LinkedList compositeElements;
+
+ protected int listIdx = 0;
+
+ private boolean splittedRow;
+
+ protected Phrase waitPhrase;
+
+ /** if true, first line height is adjusted so that the max ascender touches the top */
+ private boolean useAscender = false;
+
+ /**
+ * Creates a ColumnText
.
+ * @param canvas the place where the text will be written to. Can
+ * be a template.
+ */
+ public ColumnText(PdfContentByte canvas) {
+ this.canvas = canvas;
+ }
+
+ /** Creates an independent duplicated of the instance org
.
+ * @param org the original ColumnText
+ * @return the duplicated
+ */
+ public static ColumnText duplicate(ColumnText org) {
+ ColumnText ct = new ColumnText(null);
+ ct.setACopy(org);
+ return ct;
+ }
+
+ /** Makes this instance an independent copy of org
.
+ * @param org the original ColumnText
+ * @return itself
+ */
+ public ColumnText setACopy(ColumnText org) {
+ setSimpleVars(org);
+ if (org.bidiLine != null)
+ bidiLine = new BidiLine(org.bidiLine);
+ return this;
+ }
+
+ protected void setSimpleVars(ColumnText org) {
+ maxY = org.maxY;
+ minY = org.minY;
+ alignment = org.alignment;
+ leftWall = null;
+ if (org.leftWall != null)
+ leftWall = new ArrayList(org.leftWall);
+ rightWall = null;
+ if (org.rightWall != null)
+ rightWall = new ArrayList(org.rightWall);
+ yLine = org.yLine;
+ currentLeading = org.currentLeading;
+ fixedLeading = org.fixedLeading;
+ multipliedLeading = org.multipliedLeading;
+ canvas = org.canvas;
+ lineStatus = org.lineStatus;
+ indent = org.indent;
+ followingIndent = org.followingIndent;
+ rightIndent = org.rightIndent;
+ extraParagraphSpace = org.extraParagraphSpace;
+ rectangularWidth = org.rectangularWidth;
+ rectangularMode = org.rectangularMode;
+ spaceCharRatio = org.spaceCharRatio;
+ lastWasNewline = org.lastWasNewline;
+ linesWritten = org.linesWritten;
+ arabicOptions = org.arabicOptions;
+ runDirection = org.runDirection;
+ descender = org.descender;
+ composite = org.composite;
+ splittedRow = org.splittedRow;
+ if (org.composite) {
+ compositeElements = new LinkedList(org.compositeElements);
+ /* ssteward: dropped in 1.44
+ if (splittedRow) {
+ PdfPTable table = (PdfPTable)compositeElements.getFirst();
+ compositeElements.set(0, new PdfPTable(table));
+ }
+ */
+ if (org.compositeColumn != null)
+ compositeColumn = duplicate(org.compositeColumn);
+ }
+ listIdx = org.listIdx;
+ firstLineY = org.firstLineY;
+ leftX = org.leftX;
+ rightX = org.rightX;
+ firstLineYDone = org.firstLineYDone;
+ waitPhrase = org.waitPhrase;
+ useAscender = org.useAscender;
+ }
+
+ private void addWaitingPhrase() {
+ if (bidiLine == null && waitPhrase != null) {
+ bidiLine = new BidiLine();
+ for (Iterator j = waitPhrase.getChunks().iterator(); j.hasNext();) {
+ bidiLine.addChunk(new PdfChunk((Chunk)j.next(), null));
+ }
+ waitPhrase = null;
+ }
+ }
+
+ /**
+ * Adds a Phrase
to the current text array.
+ * Will not have any effect if addElement() was called before.
+ * @param phrase the text
+ */
+ public void addText(Phrase phrase) {
+ if (phrase == null || composite)
+ return;
+ addWaitingPhrase();
+ if (bidiLine == null) {
+ waitPhrase = phrase;
+ return;
+ }
+ for (Iterator j = phrase.getChunks().iterator(); j.hasNext();) {
+ bidiLine.addChunk(new PdfChunk((Chunk)j.next(), null));
+ }
+ }
+
+ /**
+ * Replaces the current text array with this Phrase
.
+ * Anything added previously with addElement() is lost.
+ * @param phrase the text
+ */
+ public void setText(Phrase phrase) {
+ bidiLine = null;
+ composite = false;
+ compositeColumn = null;
+ compositeElements = null;
+ listIdx = 0;
+ splittedRow = false;
+ waitPhrase = phrase;
+ }
+
+ /**
+ * Adds a Chunk
to the current text array.
+ * Will not have any effect if addElement() was called before.
+ * @param chunk the text
+ */
+ public void addText(Chunk chunk) {
+ if (chunk == null || composite)
+ return;
+ addText(new Phrase(chunk));
+ }
+
+ /**
+ * Adds an element. Elements supported are Paragraph
,
+ * List
, PdfPTable
, Image
and
+ * Graphic
.
+ *
+ * It removes all the text placed with addText()
.
+ * @param element the Element
+ */
+ public void addElement(Element element) {
+ if (element == null)
+ return;
+ /* ssteward: dropped in 1.44
+ if (element instanceof Image) {
+ Image img = (Image)element;
+ PdfPTable t = new PdfPTable(1);
+ float w = img.getWidthPercentage();
+ if (w == 0) {
+ t.setTotalWidth(img.scaledWidth());
+ t.setLockedWidth(true);
+ }
+ else
+ t.setWidthPercentage(w);
+ t.setSpacingAfter(img.spacingAfter());
+ t.setSpacingBefore(img.spacingBefore());
+ switch (img.alignment()) {
+ case Image.LEFT:
+ t.setHorizontalAlignment(Element.ALIGN_LEFT);
+ break;
+ case Image.RIGHT:
+ t.setHorizontalAlignment(Element.ALIGN_RIGHT);
+ break;
+ default:
+ t.setHorizontalAlignment(Element.ALIGN_CENTER);
+ break;
+ }
+ PdfPCell c = new PdfPCell(img, true);
+ c.setPadding(0);
+ c.setBorder(img.border());
+ c.setBorderColor(img.borderColor());
+ c.setBorderWidth(img.borderWidth());
+ c.setBackgroundColor(img.backgroundColor());
+ c.setGrayFill(img.grayFill());
+ t.addCell(c);
+ element = t;
+ }
+ */
+ if (element.type() == Element.CHUNK) {
+ element = new Paragraph((Chunk)element);
+ }
+ else if (element.type() == Element.PHRASE) {
+ element = new Paragraph((Phrase)element);
+ }
+ if (element.type() != Element.PARAGRAPH && element.type() != Element.LIST && element.type() != Element.PTABLE && element.type() != Element.GRAPHIC)
+ throw new IllegalArgumentException("Element not allowed.");
+ if (!composite) {
+ composite = true;
+ compositeElements = new LinkedList();
+ bidiLine = null;
+ waitPhrase = null;
+ }
+ compositeElements.add(element);
+ }
+
+ /**
+ * Converts a sequence of lines representing one of the column bounds into
+ * an internal format.
+ *
+ * Each array element will contain a float[4]
representing
+ * the line x = ax + b.
+ * @param cLine the column array
+ * @return the converted array
+ */
+ protected ArrayList convertColumn(float cLine[]) {
+ if (cLine.length < 4)
+ throw new RuntimeException("No valid column line found.");
+ ArrayList cc = new ArrayList();
+ for (int k = 0; k < cLine.length - 2; k += 2) {
+ float x1 = cLine[k];
+ float y1 = cLine[k + 1];
+ float x2 = cLine[k + 2];
+ float y2 = cLine[k + 3];
+ if (y1 == y2)
+ continue;
+ // x = ay + b
+ float a = (x1 - x2) / (y1 - y2);
+ float b = x1 - a * y1;
+ float r[] = new float[4];
+ r[0] = Math.min(y1, y2);
+ r[1] = Math.max(y1, y2);
+ r[2] = a;
+ r[3] = b;
+ cc.add(r);
+ maxY = Math.max(maxY, r[1]);
+ minY = Math.min(minY, r[0]);
+ }
+ if (cc.size() == 0)
+ throw new RuntimeException("No valid column line found.");
+ return cc;
+ }
+
+ /**
+ * Finds the intersection between the yLine
and the column. It will
+ * set the lineStatus
apropriatly.
+ * @param wall the column to intersect
+ * @return the x coordinate of the intersection
+ */
+ protected float findLimitsPoint(ArrayList wall) {
+ lineStatus = LINE_STATUS_OK;
+ if (yLine < minY || yLine > maxY) {
+ lineStatus = LINE_STATUS_OFFLIMITS;
+ return 0;
+ }
+ for (int k = 0; k < wall.size(); ++k) {
+ float r[] = (float[])wall.get(k);
+ if (yLine < r[0] || yLine > r[1])
+ continue;
+ return r[2] * yLine + r[3];
+ }
+ lineStatus = LINE_STATUS_NOLINE;
+ return 0;
+ }
+
+ /**
+ * Finds the intersection between the yLine
and the two
+ * column bounds. It will set the lineStatus
apropriatly.
+ * @return a float[2]
with the x coordinates of the intersection
+ */
+ protected float[] findLimitsOneLine() {
+ float x1 = findLimitsPoint(leftWall);
+ if (lineStatus == LINE_STATUS_OFFLIMITS || lineStatus == LINE_STATUS_NOLINE)
+ return null;
+ float x2 = findLimitsPoint(rightWall);
+ if (lineStatus == LINE_STATUS_NOLINE)
+ return null;
+ return new float[]{x1, x2};
+ }
+
+ /**
+ * Finds the intersection between the yLine
,
+ * the yLine-leading
and the two
+ * column bounds. It will set the lineStatus
apropriatly.
+ * @return a float[4]
with the x coordinates of the intersection
+ */
+ protected float[] findLimitsTwoLines() {
+ boolean repeat = false;
+ for (;;) {
+ if (repeat && currentLeading == 0)
+ return null;
+ repeat = true;
+ float x1[] = findLimitsOneLine();
+ if (lineStatus == LINE_STATUS_OFFLIMITS)
+ return null;
+ yLine -= currentLeading;
+ if (lineStatus == LINE_STATUS_NOLINE) {
+ continue;
+ }
+ float x2[] = findLimitsOneLine();
+ if (lineStatus == LINE_STATUS_OFFLIMITS)
+ return null;
+ if (lineStatus == LINE_STATUS_NOLINE) {
+ yLine -= currentLeading;
+ continue;
+ }
+ if (x1[0] >= x2[1] || x2[0] >= x1[1])
+ continue;
+ return new float[]{x1[0], x1[1], x2[0], x2[1]};
+ }
+ }
+
+ /**
+ * Sets the columns bounds. Each column bound is described by a
+ * float[]
with the line points [x1,y1,x2,y2,...].
+ * The array must have at least 4 elements.
+ * @param leftLine the left column bound
+ * @param rightLine the right column bound
+ */
+ public void setColumns(float leftLine[], float rightLine[]) {
+ maxY = -10e20f;
+ minY = 10e20f;
+ rightWall = convertColumn(rightLine);
+ leftWall = convertColumn(leftLine);
+ rectangularWidth = -1;
+ rectangularMode = false;
+ }
+
+ /**
+ * Simplified method for rectangular columns.
+ * @param phrase a Phrase
+ * @param llx the lower left x corner
+ * @param lly the lower left y corner
+ * @param urx the upper right x corner
+ * @param ury the upper right y corner
+ * @param leading the leading
+ * @param alignment the column alignment
+ */
+ public void setSimpleColumn(Phrase phrase, float llx, float lly, float urx, float ury, float leading, int alignment) {
+ addText(phrase);
+ setSimpleColumn(llx, lly, urx, ury, leading, alignment);
+ }
+
+ /**
+ * Simplified method for rectangular columns.
+ * @param llx the lower left x corner
+ * @param lly the lower left y corner
+ * @param urx the upper right x corner
+ * @param ury the upper right y corner
+ * @param leading the leading
+ * @param alignment the column alignment
+ */
+ public void setSimpleColumn(float llx, float lly, float urx, float ury, float leading, int alignment) {
+ setLeading(leading);
+ this.alignment = alignment;
+ setSimpleColumn(llx, lly, urx, ury);
+ }
+
+ /**
+ * Simplified method for rectangular columns.
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ */
+ public void setSimpleColumn(float llx, float lly, float urx, float ury) {
+ leftX = Math.min(llx, urx);
+ maxY = Math.max(lly, ury);
+ minY = Math.min(lly, ury);
+ rightX = Math.max(llx, urx);
+ yLine = maxY;
+ rectangularWidth = rightX - leftX;
+ if (rectangularWidth < 0)
+ rectangularWidth = 0;
+ rectangularMode = true;
+ }
+ /**
+ * Sets the leading to fixed
+ * @param leading the leading
+ */
+ public void setLeading(float leading) {
+ fixedLeading = leading;
+ multipliedLeading = 0;
+ }
+
+ /**
+ * Sets the leading fixed and variable. The resultant leading will be
+ * fixedLeading+multipliedLeading*maxFontSize where maxFontSize is the
+ * size of the bigest font in the line.
+ * @param fixedLeading the fixed leading
+ * @param multipliedLeading the variable leading
+ */
+ public void setLeading(float fixedLeading, float multipliedLeading) {
+ this.fixedLeading = fixedLeading;
+ this.multipliedLeading = multipliedLeading;
+ }
+
+ /**
+ * Gets the fixed leading
+ * @return the leading
+ */
+ public float getLeading() {
+ return fixedLeading;
+ }
+
+ /**
+ * Gets the variable leading
+ * @return the leading
+ */
+ public float getMultipliedLeading() {
+ return multipliedLeading;
+ }
+
+ /**
+ * Sets the yLine. The line will be written to yLine-leading.
+ * @param yLine the yLine
+ */
+ public void setYLine(float yLine) {
+ this.yLine = yLine;
+ }
+
+ /**
+ * Gets the yLine.
+ * @return the yLine
+ */
+ public float getYLine() {
+ return yLine;
+ }
+
+ /**
+ * Sets the alignment.
+ * @param alignment the alignment
+ */
+ public void setAlignment(int alignment) {
+ this.alignment = alignment;
+ }
+
+ /**
+ * Gets the alignment.
+ * @return the alignment
+ */
+ public int getAlignment() {
+ return alignment;
+ }
+
+ /**
+ * Sets the first paragraph line indent.
+ * @param indent the indent
+ */
+ public void setIndent(float indent) {
+ this.indent = indent;
+ lastWasNewline = true;
+ }
+
+ /**
+ * Gets the first paragraph line indent.
+ * @return the indent
+ */
+ public float getIndent() {
+ return indent;
+ }
+
+ /**
+ * Sets the following paragraph lines indent.
+ * @param indent the indent
+ */
+ public void setFollowingIndent(float indent) {
+ this.followingIndent = indent;
+ lastWasNewline = true;
+ }
+
+ /**
+ * Gets the following paragraph lines indent.
+ * @return the indent
+ */
+ public float getFollowingIndent() {
+ return followingIndent;
+ }
+
+ /**
+ * Sets the right paragraph lines indent.
+ * @param indent the indent
+ */
+ public void setRightIndent(float indent) {
+ this.rightIndent = indent;
+ lastWasNewline = true;
+ }
+
+ /**
+ * Gets the right paragraph lines indent.
+ * @return the indent
+ */
+ public float getRightIndent() {
+ return rightIndent;
+ }
+
+ /**
+ * Outputs the lines to the document. It is equivalent to go(false)
.
+ * @return returns the result of the operation. It can be NO_MORE_TEXT
+ * and/or NO_MORE_COLUMN
+ * @throws DocumentException on error
+ */
+ public int go() throws DocumentException {
+ return go(false);
+ }
+
+ /**
+ * Outputs the lines to the document. The output can be simulated.
+ * @param simulate true
to simulate the writting to the document
+ * @return returns the result of the operation. It can be NO_MORE_TEXT
+ * and/or NO_MORE_COLUMN
+ * @throws DocumentException on error
+ */
+ public int go(boolean simulate) throws DocumentException {
+ if (composite)
+ return goComposite(simulate);
+ addWaitingPhrase();
+ if (bidiLine == null)
+ return NO_MORE_TEXT;
+ descender = 0;
+ linesWritten = 0;
+ boolean dirty = false;
+ float ratio = spaceCharRatio;
+ Object currentValues[] = new Object[2];
+ PdfFont currentFont = null;
+ Float lastBaseFactor = new Float(0);
+ currentValues[1] = lastBaseFactor;
+ PdfDocument pdf = null;
+ PdfContentByte graphics = null;
+ PdfContentByte text = null;
+ firstLineY = Float.NaN;
+ int localRunDirection = PdfWriter.RUN_DIRECTION_NO_BIDI;
+ if (runDirection != PdfWriter.RUN_DIRECTION_DEFAULT)
+ localRunDirection = runDirection;
+ if (canvas != null) {
+ graphics = canvas;
+ pdf = canvas.getPdfDocument();
+ text = canvas.getDuplicate();
+ }
+ else if (!simulate)
+ throw new NullPointerException("ColumnText.go with simulate==false and text==null.");
+ if (!simulate) {
+ if (ratio == GLOBAL_SPACE_CHAR_RATIO)
+ ratio = text.getPdfWriter().getSpaceCharRatio();
+ else if (ratio < 0.001f)
+ ratio = 0.001f;
+ }
+ float firstIndent = 0;
+
+ int status = 0;
+ if (rectangularMode) {
+ for (;;) {
+ firstIndent = (lastWasNewline ? indent : followingIndent);
+ if (rectangularWidth <= firstIndent + rightIndent) {
+ status = NO_MORE_COLUMN;
+ if (bidiLine.isEmpty())
+ status |= NO_MORE_TEXT;
+ break;
+ }
+ if (bidiLine.isEmpty()) {
+ status = NO_MORE_TEXT;
+ break;
+ }
+ PdfLine line = bidiLine.processLine(rectangularWidth - firstIndent - rightIndent, alignment, localRunDirection, arabicOptions);
+ if (line == null) {
+ status = NO_MORE_TEXT;
+ break;
+ }
+ float maxSize = line.getMaxSizeSimple();
+ if (isUseAscender() && Float.isNaN(firstLineY)) {
+ currentLeading = line.getAscender();
+ }
+ else {
+ currentLeading = fixedLeading + maxSize * multipliedLeading;
+ }
+ if (yLine > maxY || yLine - currentLeading < minY ) {
+ status = NO_MORE_COLUMN;
+ bidiLine.restore();
+ break;
+ }
+ yLine -= currentLeading;
+ if (!simulate && !dirty) {
+ text.beginText();
+ dirty = true;
+ }
+ if (Float.isNaN(firstLineY)) {
+ firstLineY = yLine;
+ }
+ if (!simulate) {
+ currentValues[0] = currentFont;
+ text.setTextMatrix(leftX + (line.isRTL() ? rightIndent : firstIndent) + line.indentLeft(), yLine);
+ pdf.writeLineToContent(line, text, graphics, currentValues, ratio);
+ currentFont = (PdfFont)currentValues[0];
+ }
+ lastWasNewline = line.isNewlineSplit();
+ yLine -= line.isNewlineSplit() ? extraParagraphSpace : 0;
+ ++linesWritten;
+ descender = line.getDescender();
+ }
+ }
+ else {
+ currentLeading = fixedLeading;
+ for (;;) {
+ firstIndent = (lastWasNewline ? indent : followingIndent);
+ float yTemp = yLine;
+ float xx[] = findLimitsTwoLines();
+ if (xx == null) {
+ status = NO_MORE_COLUMN;
+ if (bidiLine.isEmpty())
+ status |= NO_MORE_TEXT;
+ yLine = yTemp;
+ break;
+ }
+ if (bidiLine.isEmpty()) {
+ status = NO_MORE_TEXT;
+ yLine = yTemp;
+ break;
+ }
+ float x1 = Math.max(xx[0], xx[2]);
+ float x2 = Math.min(xx[1], xx[3]);
+ if (x2 - x1 <= firstIndent + rightIndent)
+ continue;
+ if (!simulate && !dirty) {
+ text.beginText();
+ dirty = true;
+ }
+ PdfLine line = bidiLine.processLine(x2 - x1 - firstIndent - rightIndent, alignment, localRunDirection, arabicOptions);
+ if (line == null) {
+ status = NO_MORE_TEXT;
+ yLine = yTemp;
+ break;
+ }
+ if (!simulate) {
+ currentValues[0] = currentFont;
+ text.setTextMatrix(x1 + (line.isRTL() ? rightIndent : firstIndent) + line.indentLeft(), yLine);
+ pdf.writeLineToContent(line, text, graphics, currentValues, ratio);
+ currentFont = (PdfFont)currentValues[0];
+ }
+ lastWasNewline = line.isNewlineSplit();
+ yLine -= line.isNewlineSplit() ? extraParagraphSpace : 0;
+ ++linesWritten;
+ descender = line.getDescender();
+ }
+ }
+ if (dirty) {
+ text.endText();
+ canvas.add(text);
+ }
+ return status;
+ }
+
+ /**
+ * Sets the extra space between paragraphs.
+ * @return the extra space between paragraphs
+ */
+ public float getExtraParagraphSpace() {
+ return extraParagraphSpace;
+ }
+
+ /**
+ * Sets the extra space between paragraphs.
+ * @param extraParagraphSpace the extra space between paragraphs
+ */
+ public void setExtraParagraphSpace(float extraParagraphSpace) {
+ this.extraParagraphSpace = extraParagraphSpace;
+ }
+
+ /**
+ * Clears the chunk array. A call to go()
will always return
+ * NO_MORE_TEXT.
+ */
+ public void clearChunks() {
+ if (bidiLine != null)
+ bidiLine.clearChunks();
+ }
+
+ /** Gets the space/character extra spacing ratio for
+ * fully justified text.
+ * @return the space/character extra spacing ratio
+ */
+ public float getSpaceCharRatio() {
+ return spaceCharRatio;
+ }
+
+ /** Sets the ratio between the extra word spacing and the extra character spacing
+ * when the text is fully justified.
+ * Extra word spacing will grow spaceCharRatio
times more than extra character spacing.
+ * If the ratio is PdfWriter.NO_SPACE_CHAR_RATIO
then the extra character spacing
+ * will be zero.
+ * @param spaceCharRatio the ratio between the extra word spacing and the extra character spacing
+ */
+ public void setSpaceCharRatio(float spaceCharRatio) {
+ this.spaceCharRatio = spaceCharRatio;
+ }
+
+ /** Sets the run direction.
+ * @param runDirection the run direction
+ */
+ public void setRunDirection(int runDirection) {
+ if (runDirection < PdfWriter.RUN_DIRECTION_DEFAULT || runDirection > PdfWriter.RUN_DIRECTION_RTL)
+ throw new RuntimeException("Invalid run direction: " + runDirection);
+ this.runDirection = runDirection;
+ }
+
+ /** Gets the run direction.
+ * @return the run direction
+ */
+ public int getRunDirection() {
+ return runDirection;
+ }
+
+ /** Gets the number of lines written.
+ * @return the number of lines written
+ */
+ public int getLinesWritten() {
+ return this.linesWritten;
+ }
+
+ /** Gets the arabic shaping options.
+ * @return the arabic shaping options
+ */
+ public int getArabicOptions() {
+ return this.arabicOptions;
+ }
+
+ /** Sets the arabic shaping options. The option can be AR_NOVOWEL,
+ * AR_COMPOSEDTASHKEEL and AR_LIG.
+ * @param arabicOptions the arabic shaping options
+ */
+ public void setArabicOptions(int arabicOptions) {
+ this.arabicOptions = arabicOptions;
+ }
+
+ /** Gets the biggest descender value of the last line written.
+ * @return the biggest descender value of the last line written
+ */
+ public float getDescender() {
+ return descender;
+ }
+
+ /** Gets the width that the line will occupy after writing.
+ * Only the width of the first line is returned.
+ * @param phrase the Phrase
containing the line
+ * @param runDirection the run direction
+ * @param arabicOptions the options for the arabic shaping
+ * @return the width of the line
+ */
+ public static float getWidth(Phrase phrase, int runDirection, int arabicOptions) {
+ ColumnText ct = new ColumnText(null);
+ ct.addText(phrase);
+ ct.addWaitingPhrase();
+ PdfLine line = ct.bidiLine.processLine(20000, Element.ALIGN_LEFT, runDirection, arabicOptions);
+ if (line == null)
+ return 0;
+ else
+ return 20000 - line.widthLeft();
+ }
+
+ /** Gets the width that the line will occupy after writing.
+ * Only the width of the first line is returned.
+ * @param phrase the Phrase
containing the line
+ * @return the width of the line
+ */
+ public static float getWidth(Phrase phrase) {
+ return getWidth(phrase, PdfWriter.RUN_DIRECTION_NO_BIDI, 0);
+ }
+
+ /** Shows a line of text. Only the first line is written.
+ * @param canvas where the text is to be written to
+ * @param alignment the alignment. It is not influenced by the run direction
+ * @param phrase the Phrase
with the text
+ * @param x the x reference position
+ * @param y the y reference position
+ * @param rotation the rotation to be applied in degrees counterclockwise
+ * @param runDirection the run direction
+ * @param arabicOptions the options for the arabic shaping
+ */
+ public static void showTextAligned(PdfContentByte canvas, int alignment, Phrase phrase, float x, float y, float rotation, int runDirection, int arabicOptions) {
+ if (alignment != Element.ALIGN_LEFT && alignment != Element.ALIGN_CENTER
+ && alignment != Element.ALIGN_RIGHT)
+ alignment = Element.ALIGN_LEFT;
+ canvas.saveState();
+ ColumnText ct = new ColumnText(canvas);
+ if (rotation == 0) {
+ if (alignment == Element.ALIGN_LEFT)
+ ct.setSimpleColumn(phrase, x, y - 1, 20000 + x, y + 2, 2, alignment);
+ else if (alignment == Element.ALIGN_RIGHT)
+ ct.setSimpleColumn(phrase, x-20000, y-1, x, y+2, 2, alignment);
+ else
+ ct.setSimpleColumn(phrase, x-20000, y-1, x+20000, y+2, 2, alignment);
+ }
+ else {
+ double alpha = rotation * Math.PI / 180.0;
+ float cos = (float)Math.cos(alpha);
+ float sin = (float)Math.sin(alpha);
+ canvas.concatCTM(cos, sin, -sin, cos, x, y);
+ if (alignment == Element.ALIGN_LEFT)
+ ct.setSimpleColumn(phrase, 0, -1, 20000, 2, 2, alignment);
+ else if (alignment == Element.ALIGN_RIGHT)
+ ct.setSimpleColumn(phrase, -20000, -1, 0, 2, 2, alignment);
+ else
+ ct.setSimpleColumn(phrase, -20000, -1, 20000, 2, 2, alignment);
+ }
+ if (runDirection == PdfWriter.RUN_DIRECTION_RTL) {
+ if (alignment == Element.ALIGN_LEFT)
+ alignment = Element.ALIGN_RIGHT;
+ else if (alignment == Element.ALIGN_RIGHT)
+ alignment = Element.ALIGN_LEFT;
+ }
+ ct.setAlignment(alignment);
+ ct.setArabicOptions(arabicOptions);
+ ct.setRunDirection(runDirection);
+ try {
+ ct.go();
+ }
+ catch (DocumentException e) {
+ throw new ExceptionConverter(e);
+ }
+ canvas.restoreState();
+ }
+
+ /** Shows a line of text. Only the first line is written.
+ * @param canvas where the text is to be written to
+ * @param alignment the alignment
+ * @param phrase the Phrase
with the text
+ * @param x the x reference position
+ * @param y the y reference position
+ * @param rotation the rotation to be applied in degrees counterclockwise
+ */
+ public static void showTextAligned(PdfContentByte canvas, int alignment, Phrase phrase, float x, float y, float rotation) {
+ showTextAligned(canvas, alignment, phrase, x, y, rotation, PdfWriter.RUN_DIRECTION_NO_BIDI, 0);
+ }
+
+ protected int goComposite(boolean simulate) throws DocumentException {
+ if (!rectangularMode)
+ throw new DocumentException("Irregular columns are not supported in composite mode.");
+ linesWritten = 0;
+ descender = 0;
+ boolean firstPass = true;
+ main_loop:
+ while (true) {
+ if (compositeElements.isEmpty())
+ return NO_MORE_TEXT;
+ Element element = (Element)compositeElements.getFirst();
+ if (element.type() == Element.PARAGRAPH) {
+ Paragraph para = (Paragraph)element;
+ int status = 0;
+ for (int keep = 0; keep < 2; ++keep) {
+ float lastY = yLine;
+ boolean createHere = false;
+ if (compositeColumn == null) {
+ compositeColumn = new ColumnText(canvas);
+ compositeColumn.setUseAscender(firstPass ? useAscender : false);
+ compositeColumn.setAlignment(para.alignment());
+ compositeColumn.setIndent(para.indentationLeft() + para.getFirstLineIndent());
+ compositeColumn.setExtraParagraphSpace(para.getExtraParagraphSpace());
+ compositeColumn.setFollowingIndent(para.indentationLeft());
+ compositeColumn.setRightIndent(para.indentationRight());
+ compositeColumn.setLeading(para.leading(), para.getMultipliedLeading());
+ compositeColumn.setRunDirection(runDirection);
+ compositeColumn.setArabicOptions(arabicOptions);
+ compositeColumn.setSpaceCharRatio(spaceCharRatio);
+ compositeColumn.addText(para);
+ if (!firstPass) {
+ yLine -= para.spacingBefore();
+ }
+ createHere = true;
+ }
+ compositeColumn.leftX = leftX;
+ compositeColumn.rightX = rightX;
+ compositeColumn.yLine = yLine;
+ compositeColumn.rectangularWidth = rectangularWidth;
+ compositeColumn.rectangularMode = rectangularMode;
+ compositeColumn.minY = minY;
+ compositeColumn.maxY = maxY;
+ boolean keepCandidate = (para.getKeepTogether() && createHere && !firstPass);
+ status = compositeColumn.go(simulate || (keepCandidate && keep == 0));
+ if ((status & NO_MORE_TEXT) == 0 && keepCandidate) {
+ compositeColumn = null;
+ yLine = lastY;
+ return NO_MORE_COLUMN;
+ }
+ if (simulate || !keepCandidate)
+ break;
+ if (keep == 0) {
+ compositeColumn = null;
+ yLine = lastY;
+ }
+ }
+ firstPass = false;
+ yLine = compositeColumn.yLine;
+ linesWritten += compositeColumn.linesWritten;
+ descender = compositeColumn.descender;
+ if ((status & NO_MORE_TEXT) != 0) {
+ compositeColumn = null;
+ compositeElements.removeFirst();
+ yLine -= para.spacingAfter();
+ }
+ if ((status & NO_MORE_COLUMN) != 0) {
+ return NO_MORE_COLUMN;
+ }
+ }
+ else if (element.type() == Element.LIST) {
+ pdftk.com.lowagie.text.List list = (pdftk.com.lowagie.text.List)element;
+ ArrayList items = list.getItems();
+ ListItem item = null;
+ float listIndentation = list.indentationLeft();
+ int count = 0;
+ Stack stack = new Stack();
+ for (int k = 0; k < items.size(); ++k) {
+ Object obj = items.get(k);
+ if (obj instanceof ListItem) {
+ if (count == listIdx) {
+ item = (ListItem)obj;
+ break;
+ }
+ else ++count;
+ }
+ else if (obj instanceof pdftk.com.lowagie.text.List) {
+ stack.push(new Object[]{list, new Integer(k), new Float(listIndentation)});
+ list = (pdftk.com.lowagie.text.List)obj;
+ items = list.getItems();
+ listIndentation += list.indentationLeft();
+ k = -1;
+ continue;
+ }
+ if (k == items.size() - 1) {
+ if (!stack.isEmpty()) {
+ Object objs[] = (Object[])stack.pop();
+ list = (pdftk.com.lowagie.text.List)objs[0];
+ items = list.getItems();
+ k = ((Integer)objs[1]).intValue();
+ listIndentation = ((Float)objs[2]).floatValue();
+ }
+ }
+ }
+ int status = 0;
+ for (int keep = 0; keep < 2; ++keep) {
+ float lastY = yLine;
+ boolean createHere = false;
+ if (compositeColumn == null) {
+ if (item == null) {
+ listIdx = 0;
+ compositeElements.removeFirst();
+ continue main_loop;
+ }
+ compositeColumn = new ColumnText(canvas);
+ compositeColumn.setUseAscender(firstPass ? useAscender : false);
+ compositeColumn.setAlignment(item.alignment());
+ compositeColumn.setIndent(item.indentationLeft() + listIndentation + item.getFirstLineIndent());
+ compositeColumn.setExtraParagraphSpace(item.getExtraParagraphSpace());
+ compositeColumn.setFollowingIndent(compositeColumn.getIndent());
+ compositeColumn.setRightIndent(item.indentationRight() + list.indentationRight());
+ compositeColumn.setLeading(item.leading(), item.getMultipliedLeading());
+ compositeColumn.setRunDirection(runDirection);
+ compositeColumn.setArabicOptions(arabicOptions);
+ compositeColumn.setSpaceCharRatio(spaceCharRatio);
+ compositeColumn.addText(item);
+ if (!firstPass) {
+ yLine -= item.spacingBefore();
+ }
+ createHere = true;
+ }
+ compositeColumn.leftX = leftX;
+ compositeColumn.rightX = rightX;
+ compositeColumn.yLine = yLine;
+ compositeColumn.rectangularWidth = rectangularWidth;
+ compositeColumn.rectangularMode = rectangularMode;
+ compositeColumn.minY = minY;
+ compositeColumn.maxY = maxY;
+ boolean keepCandidate = (item.getKeepTogether() && createHere && !firstPass);
+ status = compositeColumn.go(simulate || (keepCandidate && keep == 0));
+ if ((status & NO_MORE_TEXT) == 0 && keepCandidate) {
+ compositeColumn = null;
+ yLine = lastY;
+ return NO_MORE_COLUMN;
+ }
+ if (simulate || !keepCandidate)
+ break;
+ if (keep == 0) {
+ compositeColumn = null;
+ yLine = lastY;
+ }
+ }
+ firstPass = false;
+ yLine = compositeColumn.yLine;
+ linesWritten += compositeColumn.linesWritten;
+ descender = compositeColumn.descender;
+ if (!Float.isNaN(compositeColumn.firstLineY) && !compositeColumn.firstLineYDone) {
+ if (!simulate)
+ showTextAligned(canvas, Element.ALIGN_LEFT, new Phrase(item.listSymbol()), compositeColumn.leftX + listIndentation, compositeColumn.firstLineY, 0);
+ compositeColumn.firstLineYDone = true;
+ }
+ if ((status & NO_MORE_TEXT) != 0) {
+ compositeColumn = null;
+ ++listIdx;
+ yLine -= item.spacingAfter();
+ }
+ if ((status & NO_MORE_COLUMN) != 0) {
+ return NO_MORE_COLUMN;
+ }
+ }
+ /* ssteward: dropped in 1.44
+ else if (element.type() == Element.PTABLE) {
+ if (yLine < minY || yLine > maxY)
+ return NO_MORE_COLUMN;
+ PdfPTable table = (PdfPTable)element;
+ if (table.size() <= table.getHeaderRows()) {
+ compositeElements.removeFirst();
+ continue;
+ }
+ float yTemp = yLine;
+ float yLineWrite = yLine;
+ if (!firstPass && listIdx == 0) {
+ yTemp -= table.spacingBefore();
+ yLineWrite = yTemp;
+ }
+ currentLeading = 0;
+ if (yTemp < minY || yTemp > maxY)
+ return NO_MORE_COLUMN;
+ float x1 = leftX;
+ float tableWidth;
+ if (table.isLockedWidth())
+ tableWidth = table.getTotalWidth();
+ else {
+ tableWidth = rectangularWidth * table.getWidthPercentage() / 100f;
+ table.setTotalWidth(tableWidth);
+ }
+ int k;
+ boolean skipHeader = (!firstPass && table.isSkipFirstHeader() && listIdx <= table.getHeaderRows());
+ if (!skipHeader) {
+ yTemp -= table.getHeaderHeight();
+ if (yTemp < minY || yTemp > maxY) {
+ if (firstPass) {
+ compositeElements.removeFirst();
+ continue;
+ }
+ return NO_MORE_COLUMN;
+ }
+ }
+ if (listIdx < table.getHeaderRows())
+ listIdx = table.getHeaderRows();
+ for (k = listIdx; k < table.size(); ++k) {
+ float rowHeight = table.getRowHeight(k);
+ if (yTemp - rowHeight < minY)
+ break;
+ yTemp -= rowHeight;
+ }
+ if (k < table.size()) {
+ if (table.isSplitRows() && (!table.isSplitLate() || (k == listIdx && firstPass))) {
+ if (!splittedRow) {
+ splittedRow = true;
+ table = new PdfPTable(table);
+ compositeElements.set(0, table);
+ ArrayList rows = table.getRows();
+ for (int i = table.getHeaderRows(); i < listIdx; ++i)
+ rows.set(i, null);
+ }
+ float h = yTemp - minY;
+ PdfPRow newRow = table.getRow(k).splitRow(h);
+ if (newRow == null) {
+ if (k == listIdx)
+ return NO_MORE_COLUMN;
+ }
+ else {
+ yTemp = minY;
+ table.getRows().add(++k, newRow);
+ }
+ }
+ else if (!table.isSplitRows() && k == listIdx && firstPass) {
+ compositeElements.removeFirst();
+ splittedRow = false;
+ continue;
+ }
+ else if (k == listIdx && !firstPass && (!table.isSplitRows() || table.isSplitLate())) {
+ return NO_MORE_COLUMN;
+ }
+ }
+ firstPass = false;
+ if (!simulate) {
+ switch (table.getHorizontalAlignment()) {
+ case Element.ALIGN_LEFT:
+ break;
+ case Element.ALIGN_RIGHT:
+ x1 += rectangularWidth - tableWidth;
+ break;
+ default:
+ x1 += (rectangularWidth - tableWidth) / 2f;
+ }
+ PdfPTable nt = PdfPTable.shallowCopy(table);
+ ArrayList rows = table.getRows();
+ ArrayList sub = nt.getRows();
+ if (!skipHeader) {
+ for (int j = 0; j < table.getHeaderRows(); ++j)
+ sub.add(rows.get(j));
+ }
+ else
+ nt.setHeaderRows(0);
+ for (int j = listIdx; j < k; ++j)
+ sub.add(rows.get(j));
+ float rowHeight = 0;
+ if (table.isExtendLastRow()) {
+ PdfPRow last = (PdfPRow)sub.get(sub.size() - 1);
+ rowHeight = last.getMaxHeights();
+ last.setMaxHeights(yTemp - minY + rowHeight);
+ yTemp = minY;
+ }
+ nt.writeSelectedRows(0, -1, x1, yLineWrite, canvas);
+ if (table.isExtendLastRow()) {
+ PdfPRow last = (PdfPRow)sub.get(sub.size() - 1);
+ last.setMaxHeights(rowHeight);
+ }
+ }
+ else if (table.isExtendLastRow() && minY > PdfPRow.BOTTOM_LIMIT)
+ yTemp = minY;
+ yLine = yTemp;
+ if (k >= table.size()) {
+ yLine -= table.spacingAfter();
+ compositeElements.removeFirst();
+ splittedRow = false;
+ listIdx = 0;
+ }
+ else {
+ if (splittedRow) {
+ ArrayList rows = table.getRows();
+ for (int i = listIdx; i < k; ++i)
+ rows.set(i, null);
+ }
+ listIdx = k;
+ return NO_MORE_COLUMN;
+ }
+ }
+ */
+ /* ssteward: dropped in 1.44
+ else if (element.type() == Element.GRAPHIC) {
+ if (!simulate) {
+ Graphic gr = (Graphic)element;
+ ByteBuffer bf = gr.getInternalBuffer();
+ ByteBuffer store = null;
+ if (bf.size() > 0) {
+ store = new ByteBuffer();
+ store.append(bf);
+ bf.reset();
+ }
+ gr.processAttributes(leftX, minY, rightX, maxY, yLine);
+ canvas.add(gr);
+ bf.reset();
+ if (store != null) {
+ bf.append(store);
+ }
+ }
+ compositeElements.removeFirst();
+ }
+ */
+ else
+ compositeElements.removeFirst();
+ }
+ }
+
+ /**
+ * Gets the canvas.
+ * @return a PdfContentByte.
+ */
+ public PdfContentByte getCanvas() {
+ return canvas;
+ }
+
+ /**
+ * Sets the canvas.
+ * @param canvas
+ */
+ public void setCanvas(PdfContentByte canvas) {
+ this.canvas = canvas;
+ if (compositeColumn != null)
+ compositeColumn.setCanvas(canvas);
+ }
+
+ /**
+ * Checks if the element has a height of 0.
+ * @return true or false
+ */
+ public boolean zeroHeightElement() {
+ return composite == true && compositeElements.size() > 0 && ((Element)compositeElements.getFirst()).type() == Element.GRAPHIC;
+ }
+
+ /**
+ * Checks if UseAscender is enabled/disabled.
+ * @return true is the adjustment of the first line height is based on max ascender.
+ */
+ public boolean isUseAscender() {
+ return useAscender;
+ }
+
+ /**
+ * Enables/Disables adjustment of first line height based on max ascender.
+ * @param use enable adjustment if true
+ */
+ public void setUseAscender(boolean use) {
+ useAscender = use;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/DefaultFontMapper.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/DefaultFontMapper.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/DefaultFontMapper.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/DefaultFontMapper.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.awt.Font;
+import pdftk.com.lowagie.text.ExceptionConverter;
+import java.util.HashMap;
+import java.io.File;
+/** Default class to map awt fonts to BaseFont.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+
+public class DefaultFontMapper implements FontMapper {
+
+ /** A representation of BaseFont parameters.
+ */
+ public static class BaseFontParameters {
+ /** The font name.
+ */
+ public String fontName;
+ /** The encoding for that font.
+ */
+ public String encoding;
+ /** The embedding for that font.
+ */
+ public boolean embedded;
+ /** Whether the font is cached of not.
+ */
+ public boolean cached;
+ /** The font bytes for ttf and afm.
+ */
+ public byte ttfAfm[];
+ /** The font bytes for pfb.
+ */
+ public byte pfb[];
+
+ /** Constructs default BaseFont parameters.
+ * @param fontName the font name or location
+ */
+ public BaseFontParameters(String fontName) {
+ this.fontName = fontName;
+ encoding = BaseFont.CP1252;
+ embedded = BaseFont.EMBEDDED;
+ cached = BaseFont.CACHED;
+ }
+ }
+
+ /** Maps aliases to names.
+ */
+ private HashMap aliases = new HashMap();
+ /** Maps names to BaseFont parameters.
+ */
+ private HashMap mapper = new HashMap();
+ /**
+ * Returns a BaseFont which can be used to represent the given AWT Font
+ *
+ * @param font the font to be converted
+ * @return a BaseFont which has similar properties to the provided Font
+ */
+
+ public BaseFont awtToPdf(Font font) {
+ try {
+ BaseFontParameters p = getBaseFontParameters(font.getFontName());
+ if (p != null)
+ return BaseFont.createFont(p.fontName, p.encoding, p.embedded, p.cached, p.ttfAfm, p.pfb);
+ String fontKey = null;
+ String logicalName = font.getName();
+
+ if (logicalName.equalsIgnoreCase("DialogInput") || logicalName.equalsIgnoreCase("Monospaced") || logicalName.equalsIgnoreCase("Courier")) {
+
+ if (font.isItalic()) {
+ if (font.isBold()) {
+ fontKey = BaseFont.COURIER_BOLDOBLIQUE;
+
+ } else {
+ fontKey = BaseFont.COURIER_OBLIQUE;
+ }
+
+ } else {
+ if (font.isBold()) {
+ fontKey = BaseFont.COURIER_BOLD;
+
+ } else {
+ fontKey = BaseFont.COURIER;
+ }
+ }
+
+ } else if (logicalName.equalsIgnoreCase("Serif") || logicalName.equalsIgnoreCase("TimesRoman")) {
+
+ if (font.isItalic()) {
+ if (font.isBold()) {
+ fontKey = BaseFont.TIMES_BOLDITALIC;
+
+ } else {
+ fontKey = BaseFont.TIMES_ITALIC;
+ }
+
+ } else {
+ if (font.isBold()) {
+ fontKey = BaseFont.TIMES_BOLD;
+
+ } else {
+ fontKey = BaseFont.TIMES_ROMAN;
+ }
+ }
+
+ } else { // default, this catches Dialog and SansSerif
+
+ if (font.isItalic()) {
+ if (font.isBold()) {
+ fontKey = BaseFont.HELVETICA_BOLDOBLIQUE;
+
+ } else {
+ fontKey = BaseFont.HELVETICA_OBLIQUE;
+ }
+
+ } else {
+ if (font.isBold()) {
+ fontKey = BaseFont.HELVETICA_BOLD;
+ } else {
+ fontKey = BaseFont.HELVETICA;
+ }
+ }
+ }
+ return BaseFont.createFont(fontKey, BaseFont.CP1252, false);
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ * Returns an AWT Font which can be used to represent the given BaseFont
+ *
+ * @param font the font to be converted
+ * @param size the desired point size of the resulting font
+ * @return a Font which has similar properties to the provided BaseFont
+ */
+
+ public Font pdfToAwt(BaseFont font, int size) {
+ String names[][] = font.getFullFontName();
+ if (names.length == 1)
+ return new Font(names[0][3], 0, size);
+ String name10 = null;
+ String name3x = null;
+ for (int k = 0; k < names.length; ++k) {
+ String name[] = names[k];
+ if (name[0].equals("1") && name[1].equals("0"))
+ name10 = name[3];
+ else if (name[2].equals("1033")) {
+ name3x = name[3];
+ break;
+ }
+ }
+ String finalName = name3x;
+ if (finalName == null)
+ finalName = name10;
+ if (finalName == null)
+ finalName = names[0][3];
+ return new Font(finalName, 0, size);
+ }
+
+ /** Maps a name to a BaseFont parameter.
+ * @param awtName the name
+ * @param parameters the BaseFont parameter
+ */
+ public void putName(String awtName, BaseFontParameters parameters) {
+ mapper.put(awtName, parameters);
+ }
+
+ /** Maps an alias to a name.
+ * @param alias the alias
+ * @param awtName the name
+ */
+ public void putAlias(String alias, String awtName) {
+ aliases.put(alias, awtName);
+ }
+
+ /** Looks for a BaseFont parameter associated with a name.
+ * @param name the name
+ * @return the BaseFont parameter or null
if not found.
+ */
+ public BaseFontParameters getBaseFontParameters(String name) {
+ String alias = (String)aliases.get(name);
+ if (alias == null)
+ return (BaseFontParameters)mapper.get(name);
+ BaseFontParameters p = (BaseFontParameters)mapper.get(alias);
+ if (p == null)
+ return (BaseFontParameters)mapper.get(name);
+ else
+ return p;
+ }
+
+ /**
+ * Inserts the names in this map.
+ * @param allNames the returned value of calling {@link BaseFont#getAllFontNames(String, String, byte[])}
+ * @param path the full path to the font
+ */
+ public void insertNames(Object allNames[], String path) {
+ String names[][] = (String[][])allNames[2];
+ String main = null;
+ for (int k = 0; k < names.length; ++k) {
+ String name[] = names[k];
+ if (name[2].equals("1033")) {
+ main = name[3];
+ break;
+ }
+ }
+ if (main == null)
+ main = names[0][3];
+ BaseFontParameters p = new BaseFontParameters(path);
+ mapper.put(main, p);
+ for (int k = 0; k < names.length; ++k) {
+ aliases.put(names[k][3], main);
+ }
+ aliases.put((String)allNames[0], main);
+ }
+
+ /** Inserts all the fonts recognized by iText in the
+ * directory
into the map. The encoding
+ * will be BaseFont.CP1252
but can be
+ * changed later.
+ * @param dir the directory to scan
+ * @return the number of files processed
+ */
+ public int insertDirectory(String dir) {
+ File file = new File(dir);
+ if (!file.exists() || !file.isDirectory())
+ return 0;
+ File files[] = file.listFiles();
+ int count = 0;
+ for (int k = 0; k < files.length; ++k) {
+ file = files[k];
+ String name = file.getPath().toLowerCase();
+ try {
+ if (name.endsWith(".ttf") || name.endsWith(".otf") || name.endsWith(".afm")) {
+ Object allNames[] = BaseFont.getAllFontNames(file.getPath(), BaseFont.CP1252, null);
+ insertNames(allNames, file.getPath());
+ ++count;
+ }
+ else if (name.endsWith(".ttc")) {
+ String ttcs[] = BaseFont.enumerateTTCNames(file.getPath());
+ for (int j = 0; j < ttcs.length; ++j) {
+ String nt = file.getPath() + "," + j;
+ Object allNames[] = BaseFont.getAllFontNames(nt, BaseFont.CP1252, null);
+ insertNames(allNames, nt);
+ }
+ ++count;
+ }
+ }
+ catch (Exception e) {
+ }
+ }
+ return count;
+ }
+
+ public HashMap getMapper() {
+ return mapper;
+ }
+
+ public HashMap getAliases() {
+ return aliases;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/DocumentFont.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/DocumentFont.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/DocumentFont.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/DocumentFont.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,403 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+/**
+ *
+ * @author psoares
+ */
+public class DocumentFont extends BaseFont {
+
+ String fontName;
+ PRIndirectReference refFont;
+ PdfDictionary font;
+ IntHashtable uni2byte = new IntHashtable();
+ float Ascender = 800;
+ float CapHeight = 700;
+ float Descender = -200;
+ float ItalicAngle = 0;
+ float llx = -50;
+ float lly = -200;
+ float urx = 100;
+ float ury = 900;
+
+ BaseFont cjkMirror;
+
+ String cjkNames[] = {"HeiseiMin-W3", "HeiseiKakuGo-W5", "STSong-Light", "MHei-Medium",
+ "MSung-Light", "HYGoThic-Medium", "HYSMyeongJo-Medium", "MSungStd-Light", "STSongStd-Light",
+ "HYSMyeongJoStd-Medium", "KozMinPro-Regular"};
+
+ String cjkEncs[] = {"UniJIS-UCS2-H", "UniJIS-UCS2-H", "UniGB-UCS2-H", "UniCNS-UCS2-H",
+ "UniCNS-UCS2-H", "UniKS-UCS2-H", "UniKS-UCS2-H", "UniCNS-UCS2-H", "UniGB-UCS2-H",
+ "UniKS-UCS2-H", "UniJIS-UCS2-H"};
+
+ static final int stdEnc[] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 32,33,34,35,36,37,38,8217,40,41,42,43,44,45,46,47,
+ 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
+ 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
+ 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
+ 8216,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,161,162,163,8260,165,402,167,164,39,8220,171,8249,8250,64257,64258,
+ 0,8211,8224,8225,183,0,182,8226,8218,8222,8221,187,8230,8240,0,191,
+ 0,96,180,710,732,175,728,729,168,0,730,184,0,733,731,711,
+ 8212,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,198,0,170,0,0,0,0,321,216,338,186,0,0,0,0,
+ 0,230,0,0,0,305,0,0,322,248,339,223,0,0,0,0};
+
+ /** Creates a new instance of DocumentFont */
+ DocumentFont(PRIndirectReference refFont) {
+ encoding = "";
+ fontSpecific = false;
+ this.refFont = refFont;
+ fontType = FONT_TYPE_DOCUMENT;
+ font = (PdfDictionary)PdfReader.getPdfObject(refFont);
+ fontName = PdfName.decodeName(((PdfName)PdfReader.getPdfObject(font.get(PdfName.BASEFONT))).toString());
+ PdfName subType = (PdfName)PdfReader.getPdfObject(font.get(PdfName.SUBTYPE));
+ if (PdfName.TYPE1.equals(subType) || PdfName.TRUETYPE.equals(subType))
+ doType1TT();
+ else {
+ for (int k = 0; k < cjkNames.length; ++k) {
+ if (fontName.startsWith(cjkNames[k])) {
+ fontName = cjkNames[k];
+ try {
+ cjkMirror = BaseFont.createFont(fontName, cjkEncs[k], false);
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ return;
+ }
+ }
+ }
+ }
+
+ public void doType1TT() {
+ PdfObject enc = PdfReader.getPdfObject(font.get(PdfName.ENCODING));
+ if (enc == null)
+ fillEncoding(null);
+ else {
+ if (enc.isName())
+ fillEncoding((PdfName)enc);
+ else {
+ PdfDictionary encDic = (PdfDictionary)enc;
+ enc = PdfReader.getPdfObject(encDic.get(PdfName.BASEENCODING));
+ if (enc == null)
+ fillEncoding(null);
+ else
+ fillEncoding((PdfName)enc);
+ PdfArray diffs = (PdfArray)PdfReader.getPdfObject(encDic.get(PdfName.DIFFERENCES));
+ if (diffs != null) {
+ ArrayList dif = diffs.getArrayList();
+ int currentNumber = 0;
+ for (int k = 0; k < dif.size(); ++k) {
+ PdfObject obj = (PdfObject)dif.get(k);
+ if (obj.isNumber())
+ currentNumber = ((PdfNumber)obj).intValue();
+ else {
+ int c[] = GlyphList.nameToUnicode(PdfName.decodeName(((PdfName)obj).toString()));
+ if (c != null && c.length > 0)
+ uni2byte.put(c[0], currentNumber);
+ ++currentNumber;
+ }
+ }
+ }
+ }
+ }
+ PdfArray newWidths = (PdfArray)PdfReader.getPdfObject(font.get(PdfName.WIDTHS));
+ PdfNumber first = (PdfNumber)PdfReader.getPdfObject(font.get(PdfName.FIRSTCHAR));
+ PdfNumber last = (PdfNumber)PdfReader.getPdfObject(font.get(PdfName.LASTCHAR));
+ if (BuiltinFonts14.containsKey(fontName)) {
+ BaseFont bf;
+ try {
+ bf = BaseFont.createFont(fontName, WINANSI, false);
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ int e[] = uni2byte.toOrderedKeys();
+ for (int k = 0; k < e.length; ++k) {
+ int n = uni2byte.get(e[k]);
+ widths[n] = bf.getRawWidth(n, GlyphList.unicodeToName(e[k]));
+ }
+ Ascender = bf.getFontDescriptor(ASCENT, 1000);
+ CapHeight = bf.getFontDescriptor(CAPHEIGHT, 1000);
+ Descender = bf.getFontDescriptor(DESCENT, 1000);
+ ItalicAngle = bf.getFontDescriptor(ITALICANGLE, 1000);
+ llx = bf.getFontDescriptor(BBOXLLX, 1000);
+ lly = bf.getFontDescriptor(BBOXLLY, 1000);
+ urx = bf.getFontDescriptor(BBOXURX, 1000);
+ ury = bf.getFontDescriptor(BBOXURY, 1000);
+ }
+ if (first != null && last != null && newWidths != null) {
+ int f = ((PdfNumber)first).intValue();
+ ArrayList ar = ((PdfArray)newWidths).getArrayList();
+ for (int k = 0; k < ar.size(); ++k) {
+ widths[f + k] = ((PdfNumber)ar.get(k)).intValue();
+ }
+ }
+ fillFontDesc();
+ }
+
+ void fillFontDesc() {
+ PdfDictionary fontDesc = (PdfDictionary)PdfReader.getPdfObject(font.get(PdfName.FONTDESCRIPTOR));
+ if (fontDesc == null)
+ return;
+ PdfNumber v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.ASCENT));
+ if (v != null)
+ Ascender = v.floatValue();
+ v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.CAPHEIGHT));
+ if (v != null)
+ CapHeight = v.floatValue();
+ v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.DESCENT));
+ if (v != null)
+ Descender = v.floatValue();
+ v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.ITALICANGLE));
+ if (v != null)
+ ItalicAngle = v.floatValue();
+ PdfArray bbox = (PdfArray)PdfReader.getPdfObject(fontDesc.get(PdfName.FONTBBOX));
+ if (bbox != null) {
+ ArrayList ar = bbox.getArrayList();
+ llx = ((PdfNumber)ar.get(0)).floatValue();
+ lly = ((PdfNumber)ar.get(1)).floatValue();
+ urx = ((PdfNumber)ar.get(2)).floatValue();
+ ury = ((PdfNumber)ar.get(3)).floatValue();
+ if (llx > urx) {
+ float t = llx;
+ llx = urx;
+ urx = t;
+ }
+ if (lly > ury) {
+ float t = lly;
+ lly = ury;
+ ury = t;
+ }
+ }
+ }
+
+ void fillEncoding(PdfName encoding) {
+ if (PdfName.MAC_ROMAN_ENCODING.equals(encoding) || PdfName.WIN_ANSI_ENCODING.equals(encoding)) {
+ byte b[] = new byte[256];
+ for (int k = 0; k < 256; ++k)
+ b[k] = (byte)k;
+ String enc = WINANSI;
+ if (PdfName.MAC_ROMAN_ENCODING.equals(encoding))
+ enc = MACROMAN;
+ String cv = PdfEncodings.convertToString(b, enc);
+ char arr[] = cv.toCharArray();
+ for (int k = 0; k < 256; ++k)
+ uni2byte.put(arr[k], k);
+ }
+ else {
+ for (int k = 0; k < 256; ++k)
+ uni2byte.put(stdEnc[k], k);
+ }
+ }
+
+ /** Gets the family name of the font. If it is a True Type font
+ * each array element will have {Platform ID, Platform Encoding ID,
+ * Language ID, font name}. The interpretation of this values can be
+ * found in the Open Type specification, chapter 2, in the 'name' table.
+ * For the other fonts the array has a single element with {"", "", "",
+ * font name}.
+ * @return the family name of the font
+ *
+ */
+ public String[][] getFamilyFontName() {
+ return null;
+ }
+
+ /** Gets the font parameter identified by key
. Valid values
+ * for key
are ASCENT
, CAPHEIGHT
, DESCENT
,
+ * ITALICANGLE
, BBOXLLX
, BBOXLLY
, BBOXURX
+ * and BBOXURY
.
+ * @param key the parameter to be extracted
+ * @param fontSize the font size in points
+ * @return the parameter in points
+ *
+ */
+ public float getFontDescriptor(int key, float fontSize) {
+ if (cjkMirror != null)
+ return cjkMirror.getFontDescriptor(key, fontSize);
+ switch (key) {
+ case AWT_ASCENT:
+ case ASCENT:
+ return Ascender * fontSize / 1000;
+ case CAPHEIGHT:
+ return CapHeight * fontSize / 1000;
+ case AWT_DESCENT:
+ case DESCENT:
+ return Descender * fontSize / 1000;
+ case ITALICANGLE:
+ return ItalicAngle;
+ case BBOXLLX:
+ return llx * fontSize / 1000;
+ case BBOXLLY:
+ return lly * fontSize / 1000;
+ case BBOXURX:
+ return urx * fontSize / 1000;
+ case BBOXURY:
+ return ury * fontSize / 1000;
+ case AWT_LEADING:
+ return 0;
+ case AWT_MAXADVANCE:
+ return (urx - llx) * fontSize / 1000;
+ }
+ return 0;
+ }
+
+ /** Gets the full name of the font. If it is a True Type font
+ * each array element will have {Platform ID, Platform Encoding ID,
+ * Language ID, font name}. The interpretation of this values can be
+ * found in the Open Type specification, chapter 2, in the 'name' table.
+ * For the other fonts the array has a single element with {"", "", "",
+ * font name}.
+ * @return the full name of the font
+ *
+ */
+ public String[][] getFullFontName() {
+ return null;
+ }
+
+ /** Gets the kerning between two Unicode chars.
+ * @param char1 the first char
+ * @param char2 the second char
+ * @return the kerning to be applied
+ *
+ */
+ public int getKerning(char char1, char char2) {
+ return 0;
+ }
+
+ /** Gets the postscript font name.
+ * @return the postscript font name
+ *
+ */
+ public String getPostscriptFontName() {
+ return fontName;
+ }
+
+ /** Gets the width from the font according to the Unicode char c
+ * or the name
. If the name
is null it's a symbolic font.
+ * @param c the unicode char
+ * @param name the glyph name
+ * @return the width of the char
+ *
+ */
+ int getRawWidth(int c, String name) {
+ return 0;
+ }
+
+ /** Checks if the font has any kerning pairs.
+ * @return true
if the font has any kerning pairs
+ *
+ */
+ public boolean hasKernPairs() {
+ return false;
+ }
+
+ /** Outputs to the writer the font dictionaries and streams.
+ * @param writer the writer for this document
+ * @param ref the font indirect reference
+ * @param params several parameters that depend on the font type
+ * @throws IOException on error
+ * @throws DocumentException error in generating the object
+ *
+ */
+ void writeFont(PdfWriter writer, PdfIndirectReference ref, Object[] params) throws DocumentException, IOException {
+ }
+
+ public int getWidth(String text) {
+ if (cjkMirror != null)
+ return cjkMirror.getWidth(text);
+ else
+ return super.getWidth(text);
+ }
+
+ byte[] convertToBytes(String text) {
+ if (cjkMirror != null)
+ return PdfEncodings.convertToBytes(text, CJKFont.CJK_ENCODING);
+ else {
+ char cc[] = text.toCharArray();
+ byte b[] = new byte[cc.length];
+ for (int k = 0; k < cc.length; ++k)
+ b[k] = (byte)uni2byte.get(cc[k]);
+ return b;
+ }
+ }
+
+ PdfIndirectReference getIndirectReference() {
+ return refFont;
+ }
+
+ public boolean charExists(char c) {
+ if (cjkMirror != null)
+ return cjkMirror.charExists(c);
+ else
+ return super.charExists(c);
+ }
+
+ /**
+ * Sets the font name that will appear in the pdf font dictionary.
+ * It does nothing in this case as the font is already in the document.
+ * @param name the new font name
+ */
+ public void setPostscriptFontName(String name) {
+ }
+
+ public boolean setKerning(char char1, char char2, int kern) {
+ return false;
+ }
+
+ public int[] getCharBBox(char c) {
+ return null;
+ }
+
+ protected int[] getRawCharBBox(int c, String name) {
+ return null;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/EnumerateTTC.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/EnumerateTTC.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/EnumerateTTC.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/EnumerateTTC.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,108 @@
+/*
+ * $Id: EnumerateTTC.java,v 1.13 2002/06/20 13:04:40 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.*;
+import java.util.HashMap;
+import pdftk.com.lowagie.text.DocumentException;
+/** Enumerates all the fonts inside a True Type Collection.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+class EnumerateTTC extends TrueTypeFont{
+
+ protected String[] names;
+
+ EnumerateTTC(String ttcFile) throws DocumentException, IOException {
+ fileName = ttcFile;
+ rf = new RandomAccessFileOrArray(ttcFile);
+ findNames();
+ }
+
+ EnumerateTTC(byte ttcArray[]) throws DocumentException, IOException {
+ fileName = "Byte array TTC";
+ rf = new RandomAccessFileOrArray(ttcArray);
+ findNames();
+ }
+
+ void findNames() throws DocumentException, IOException {
+ tables = new HashMap();
+
+ try {
+ String mainTag = readStandardString(4);
+ if (!mainTag.equals("ttcf"))
+ throw new DocumentException(fileName + " is not a valid TTC file.");
+ rf.skipBytes(4);
+ int dirCount = rf.readInt();
+ names = new String[dirCount];
+ int dirPos = rf.getFilePointer();
+ for (int dirIdx = 0; dirIdx < dirCount; ++dirIdx) {
+ tables.clear();
+ rf.seek(dirPos);
+ rf.skipBytes(dirIdx * 4);
+ directoryOffset = rf.readInt();
+ rf.seek(directoryOffset);
+ if (rf.readInt() != 0x00010000)
+ throw new DocumentException(fileName + " is not a valid TTF file.");
+ int num_tables = rf.readUnsignedShort();
+ rf.skipBytes(6);
+ for (int k = 0; k < num_tables; ++k) {
+ String tag = readStandardString(4);
+ rf.skipBytes(4);
+ int table_location[] = new int[2];
+ table_location[0] = rf.readInt();
+ table_location[1] = rf.readInt();
+ tables.put(tag, table_location);
+ }
+ names[dirIdx] = getBaseFont();
+ }
+ }
+ finally {
+ if (rf != null)
+ rf.close();
+ }
+ }
+
+ String[] getNames() {
+ return names;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ExtendedColor.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ExtendedColor.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ExtendedColor.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ExtendedColor.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,112 @@
+/*
+ * $Id: ExtendedColor.java,v 1.43 2005/03/29 14:08:15 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.awt.Color;
+/**
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class ExtendedColor extends Color{
+
+ /** a type of extended color. */
+ public static final int TYPE_RGB = 0;
+ /** a type of extended color. */
+ public static final int TYPE_GRAY = 1;
+ /** a type of extended color. */
+ public static final int TYPE_CMYK = 2;
+ /** a type of extended color. */
+ public static final int TYPE_SEPARATION = 3;
+ /** a type of extended color. */
+ public static final int TYPE_PATTERN = 4;
+ /** a type of extended color. */
+ public static final int TYPE_SHADING = 5;
+
+ protected int type;
+
+ /**
+ * Constructs an extended color of a certain type.
+ * @param type
+ */
+ public ExtendedColor(int type) {
+ super(0, 0, 0);
+ this.type = type;
+ }
+
+ /**
+ * Constructs an extended color of a certain type and a certain color.
+ * @param type
+ * @param red
+ * @param green
+ * @param blue
+ */
+ public ExtendedColor(int type, float red, float green, float blue) {
+ super(normalize(red), normalize(green), normalize(blue));
+ this.type = type;
+ }
+
+ /**
+ * Gets the type of this color.
+ * @return one of the types (see constants)
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Gets the type of a given color.
+ * @param color
+ * @return one of the types (see constants)
+ */
+ public static int getType(Color color) {
+ if (color instanceof ExtendedColor)
+ return ((ExtendedColor)color).getType();
+ return TYPE_RGB;
+ }
+
+ static final float normalize(float value) {
+ if (value < 0)
+ return 0;
+ if (value > 1)
+ return 1;
+ return value;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ExtraEncoding.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ExtraEncoding.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ExtraEncoding.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ExtraEncoding.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * Classes implementing this interface can create custom encodings or
+ * replace existing ones. It is used in the context of PdfEncoding
.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public interface ExtraEncoding {
+
+ /**
+ * Converts an Unicode string to a byte array according to some encoding.
+ * @param text the Unicode string
+ * @param encoding the requested encoding. It's mainly of use if the same class
+ * supports more than one encoding.
+ * @return the conversion or null
if no conversion is supported
+ */
+ public byte[] charToByte(String text, String encoding);
+
+ /**
+ * Converts a byte array to an Unicode string according to some encoding.
+ * @param b the input byte array
+ * @param encoding the requested encoding. It's mainly of use if the same class
+ * supports more than one encoding.
+ * @return the conversion or null
if no conversion is supported
+ */
+ public String byteToChar(byte b[], String encoding);
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/FdfReader.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/FdfReader.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/FdfReader.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/FdfReader.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,223 @@
+/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.net.URL;
+/** Reads an FDF form and makes the fields available
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class FdfReader extends PdfReader {
+
+ HashMap fields;
+ String fileSpec;
+ PdfName encoding;
+
+ /** Reads an FDF form.
+ * @param filename the file name of the form
+ * @throws IOException on error
+ */
+ public FdfReader(String filename) throws IOException {
+ super(filename);
+ }
+
+ /** Reads an FDF form.
+ * @param pdfIn the byte array with the form
+ * @throws IOException on error
+ */
+ public FdfReader(byte pdfIn[]) throws IOException {
+ super(pdfIn);
+ }
+
+ /** Reads an FDF form.
+ * @param url the URL of the document
+ * @throws IOException on error
+ */
+ public FdfReader(URL url) throws IOException {
+ super(url);
+ }
+
+ /** Reads an FDF form.
+ * @param is the InputStream
containing the document. The stream is read to the
+ * end but is not closed
+ * @throws IOException on error
+ */
+ public FdfReader(InputStream is) throws IOException {
+ super(is);
+ }
+
+ protected void readPdf() throws IOException {
+ fields = new HashMap();
+ try {
+ tokens.checkFdfHeader();
+ rebuildXref();
+ readDocObj();
+ }
+ finally {
+ try {
+ tokens.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ readFields();
+ }
+
+ protected void kidNode(PdfDictionary merged, String name) {
+ PdfArray kids = (PdfArray)getPdfObject(merged.get(PdfName.KIDS));
+ if (kids == null || kids.getArrayList().size() == 0) {
+ if (name.length() > 0)
+ name = name.substring(1);
+ fields.put(name, merged);
+ }
+ else {
+ merged.remove(PdfName.KIDS);
+ ArrayList ar = kids.getArrayList();
+ for (int k = 0; k < ar.size(); ++k) {
+ PdfDictionary dic = new PdfDictionary();
+ dic.merge(merged);
+ PdfDictionary newDic = (PdfDictionary)getPdfObject((PdfObject)ar.get(k));
+ PdfString t = (PdfString)getPdfObject(newDic.get(PdfName.T));
+ String newName = name;
+ if (t != null)
+ newName += "." + t.toUnicodeString();
+ dic.merge(newDic);
+ dic.remove(PdfName.T);
+ kidNode(dic, newName);
+ }
+ }
+ }
+
+ protected void readFields() throws IOException {
+ catalog = (PdfDictionary)getPdfObject(trailer.get(PdfName.ROOT));
+ PdfDictionary fdf = (PdfDictionary)getPdfObject(catalog.get(PdfName.FDF));
+ PdfString fs = (PdfString)getPdfObject(fdf.get(PdfName.F));
+ if (fs != null)
+ fileSpec = fs.toUnicodeString();
+ PdfArray fld = (PdfArray)getPdfObject(fdf.get(PdfName.FIELDS));
+ if (fld == null)
+ return;
+ encoding = (PdfName)getPdfObject(fdf.get(PdfName.ENCODING));
+ PdfDictionary merged = new PdfDictionary();
+ merged.put(PdfName.KIDS, fld);
+ kidNode(merged, "");
+ }
+
+ /** Gets all the fields. The map is keyed by the fully qualified
+ * field name and the value is a merged PdfDictionary
+ * with the field content.
+ * @return all the fields
+ */
+ public HashMap getFields() {
+ return fields;
+ }
+
+ /** Gets the field dictionary.
+ * @param name the fully qualified field name
+ * @return the field dictionary
+ */
+ public PdfDictionary getField(String name) {
+ return (PdfDictionary)fields.get(name);
+ }
+
+ /** Gets the field value or null
if the field does not
+ * exist or has no value defined.
+ * @param name the fully qualified field name
+ * @return the field value or null
+ */
+ public String getFieldValue(String name) {
+ PdfDictionary field = (PdfDictionary)fields.get(name);
+ if (field == null)
+ return null;
+ PdfObject v = getPdfObject(field.get(PdfName.V));
+ if (v == null)
+ return null;
+ if (v.isName())
+ return PdfName.decodeName(((PdfName)v).toString());
+ else if (v.isString()) {
+ PdfString vs = (PdfString)v;
+ if (encoding == null || vs.getEncoding() != null)
+ return vs.toUnicodeString();
+ byte b[] = vs.getBytes();
+ if (b.length >= 2 && b[0] == (byte)254 && b[1] == (byte)255)
+ return vs.toUnicodeString();
+ try {
+ if (encoding.equals(PdfName.SHIFT_JIS))
+ return new String(b, "SJIS");
+ else if (encoding.equals(PdfName.UHC))
+ return new String(b, "MS949");
+ else if (encoding.equals(PdfName.GBK))
+ return new String(b, "GBK");
+ else if (encoding.equals(PdfName.BIGFIVE))
+ return new String(b, "Big5");
+ }
+ catch (Exception e) {
+ }
+ return vs.toUnicodeString();
+ }
+ return null;
+ }
+
+ // ssteward
+ // in a PDF, the Rich Text value of a field may be stored in
+ // a string or a stream; I wonder if this applied to FDF, too?
+ public String getFieldRichValue(String name) {
+ PdfDictionary field = (PdfDictionary)fields.get(name);
+ if (field == null)
+ return null;
+ PdfObject rv = getPdfObject(field.get(PdfName.RV));
+ if (rv == null)
+ return null;
+ if (rv.isName())
+ return PdfName.decodeName(((PdfName)rv).toString());
+ else if (rv.isString())
+ return ((PdfString)rv).toUnicodeString();
+ else
+ return null;
+ }
+
+ /** Gets the PDF file specification contained in the FDF.
+ * @return the PDF file specification contained in the FDF
+ */
+ public String getFileSpec() {
+ return fileSpec;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/FdfWriter.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/FdfWriter.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/FdfWriter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/FdfWriter.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,323 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import pdftk.com.lowagie.text.DocWriter;
+import pdftk.com.lowagie.text.DocumentException;
+
+/** Writes an FDF form.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class FdfWriter {
+ static byte[] HEADER_FDF = DocWriter.getISOBytes("%FDF-1.2\n%\u00e2\u00e3\u00cf\u00d3"); // ssteward
+ HashMap fields = new HashMap();
+
+ /** The PDF file associated with the FDF. */
+ private String file;
+
+ /** Creates a new FdfWriter. */
+ public FdfWriter() {
+ }
+
+ /** Writes the content to a stream.
+ * @param os the stream
+ * @throws DocumentException on error
+ * @throws IOException on error
+ */
+ public void writeTo(OutputStream os) throws DocumentException, IOException {
+ Wrt wrt = new Wrt(os, this);
+ wrt.writeTo();
+ }
+
+ boolean setField(String field, PdfObject value) {
+ HashMap map = fields;
+ StringTokenizer tk = new StringTokenizer(field, ".");
+ if (!tk.hasMoreTokens())
+ return false;
+ while (true) {
+ String s = tk.nextToken();
+ Object obj = map.get(s);
+ if (tk.hasMoreTokens()) {
+ if (obj == null) {
+ obj = new HashMap();
+ map.put(s, obj);
+ map = (HashMap)obj;
+ continue;
+ }
+ else if (obj instanceof HashMap)
+ map = (HashMap)obj;
+ else
+ return false;
+ }
+ else {
+ if (obj == null || !(obj instanceof HashMap)) {
+ map.put(s, value);
+ return true;
+ }
+ else
+ return false;
+ }
+ }
+ }
+
+ void iterateFields(HashMap values, HashMap map, String name) {
+ for (Iterator it = map.keySet().iterator(); it.hasNext();) {
+ String s = (String)it.next();
+ Object obj = map.get(s);
+ if (obj instanceof HashMap)
+ iterateFields(values, (HashMap)obj, name + "." + s);
+ else
+ values.put((name + "." + s).substring(1), obj);
+ }
+ }
+
+ /** Removes the field value.
+ * @param field the field name
+ * @return true
if the field was found and removed,
+ * false
otherwise
+ */
+ public boolean removeField(String field) {
+ HashMap map = fields;
+ StringTokenizer tk = new StringTokenizer(field, ".");
+ if (!tk.hasMoreTokens())
+ return false;
+ ArrayList hist = new ArrayList();
+ while (true) {
+ String s = tk.nextToken();
+ Object obj = map.get(s);
+ if (obj == null)
+ return false;
+ hist.add(map);
+ hist.add(s);
+ if (tk.hasMoreTokens()) {
+ if (obj instanceof HashMap)
+ map = (HashMap)obj;
+ else
+ return false;
+ }
+ else {
+ if (obj instanceof HashMap)
+ return false;
+ else
+ break;
+ }
+ }
+ for (int k = hist.size() - 2; k >= 0; k -= 2) {
+ map = (HashMap)hist.get(k);
+ String s = (String)hist.get(k + 1);
+ map.remove(s);
+ if (map.size() > 0)
+ break;
+ }
+ return true;
+ }
+
+ /** Gets all the fields. The map is keyed by the fully qualified
+ * field name and the values are PdfObject
.
+ * @return a map with all the fields
+ */
+ public HashMap getFields() {
+ HashMap values = new HashMap();
+ iterateFields(values, fields, "");
+ return values;
+ }
+
+ /** Gets the field value.
+ * @param field the field name
+ * @return the field value or null
if not found
+ */
+ public String getField(String field) {
+ HashMap map = fields;
+ StringTokenizer tk = new StringTokenizer(field, ".");
+ if (!tk.hasMoreTokens())
+ return null;
+ while (true) {
+ String s = tk.nextToken();
+ Object obj = map.get(s);
+ if (obj == null)
+ return null;
+ if (tk.hasMoreTokens()) {
+ if (obj instanceof HashMap)
+ map = (HashMap)obj;
+ else
+ return null;
+ }
+ else {
+ if (obj instanceof HashMap)
+ return null;
+ else {
+ if (((PdfObject)obj).isString())
+ return ((PdfString)obj).toUnicodeString();
+ else
+ return PdfName.decodeName(obj.toString());
+ }
+ }
+ }
+ }
+
+ /** Sets the field value as a name.
+ * @param field the fully qualified field name
+ * @param value the value
+ * @return true
if the value was inserted,
+ * false
if the name is incompatible with
+ * an existing field
+ */
+ public boolean setFieldAsName(String field, String value) {
+ return setField(field, new PdfName(value));
+ }
+
+ /** Sets the field value as a string.
+ * @param field the fully qualified field name
+ * @param value the value
+ * @return true
if the value was inserted,
+ * false
if the name is incompatible with
+ * an existing field
+ */
+ public boolean setFieldAsString(String field, String value) {
+ return setField(field, new PdfString(value /* ssteward , PdfObject.TEXT_UNICODE */ ));
+ }
+
+ /** Sets all the fields from this FdfReader
+ * @param fdf the FdfReader
+ */
+ public void setFields(FdfReader fdf) {
+ HashMap map = fdf.getFields();
+ for (Iterator it = map.keySet().iterator(); it.hasNext();) {
+ String key = (String)it.next();
+ PdfDictionary dic = (PdfDictionary)map.get(key);
+ PdfObject v = dic.get(PdfName.V);
+ if (v != null) {
+ setField(key, v);
+ }
+ }
+ }
+
+ /** Sets all the fields from this PdfReader
+ * @param pdf the PdfReader
+ */
+ public void setFields(PdfReader pdf) {
+ setFields(pdf.getAcroFields());
+ }
+
+ /** Sets all the fields from this AcroFields
+ * @param af the AcroFields
+ */
+ public void setFields(AcroFields af) {
+ for (Iterator it = af.getFields().entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry)it.next();
+ String fn = (String)entry.getKey();
+ AcroFields.Item item = (AcroFields.Item)entry.getValue();
+ PdfDictionary dic = (PdfDictionary)item.merged.get(0);
+ PdfObject v = PdfReader.getPdfObjectRelease(dic.get(PdfName.V));
+ if (v == null)
+ continue;
+ PdfObject ft = PdfReader.getPdfObjectRelease(dic.get(PdfName.FT));
+ if (ft == null || PdfName.SIG.equals(ft))
+ continue;
+ setField(fn, v);
+ }
+ }
+
+ /** Gets the PDF file name associated with the FDF.
+ * @return the PDF file name associated with the FDF
+ */
+ public String getFile() {
+ return this.file;
+ }
+
+ /** Sets the PDF file name associated with the FDF.
+ * @param file the PDF file name associated with the FDF
+ *
+ */
+ public void setFile(String file) {
+ this.file = file;
+ }
+
+ static class Wrt extends PdfWriter {
+ private FdfWriter fdf;
+
+ Wrt(OutputStream os, FdfWriter fdf) throws DocumentException, IOException {
+ super(new PdfDocument(), os);
+ this.fdf = fdf;
+ this.os.write(HEADER_FDF);
+ body = new PdfBody(this);
+ }
+
+ void writeTo() throws DocumentException, IOException {
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.FIELDS, calculate(fdf.fields));
+ if (fdf.file != null)
+ dic.put(PdfName.F, new PdfString(fdf.file /* ssteward, PdfObject.TEXT_UNICODE */ ));
+ PdfDictionary fd = new PdfDictionary();
+ fd.put(PdfName.FDF, dic);
+ PdfIndirectReference ref = addToBody(fd).getIndirectReference();
+ os.write(getISOBytes("\ntrailer\n")); // ssteward
+ PdfDictionary trailer = new PdfDictionary();
+ trailer.put(PdfName.ROOT, ref);
+ trailer.toPdf(null, os);
+ os.write(getISOBytes("\n%%EOF\n"));
+ os.close();
+ }
+
+
+ PdfArray calculate(HashMap map) throws IOException {
+ PdfArray ar = new PdfArray();
+ for (Iterator it = map.keySet().iterator(); it.hasNext();) {
+ String key = (String)it.next();
+ Object v = map.get(key);
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.T, new PdfString(key /* ssteward , PdfObject.TEXT_UNICODE */));
+ if (v instanceof HashMap) {
+ dic.put(PdfName.KIDS, calculate((HashMap)v));
+ }
+ else {
+ dic.put(PdfName.V, (PdfObject)v);
+ }
+ ar.add(dic);
+ }
+ return ar;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/FontDetails.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/FontDetails.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/FontDetails.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/FontDetails.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,273 @@
+/*
+ * $Id: FontDetails.java,v 1.44 2005/05/04 14:32:23 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.ExceptionConverter;
+import java.util.HashMap;
+import java.io.UnsupportedEncodingException;
+/** Each font in the document will have an instance of this class
+ * where the characters used will be represented.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+class FontDetails {
+
+ /** The indirect reference to this font
+ */
+ PdfIndirectReference indirectReference;
+ /** The font name that appears in the document body stream
+ */
+ PdfName fontName;
+ /** The font
+ */
+ BaseFont baseFont;
+ /** The font if its an instance of TrueTypeFontUnicode
+ */
+ TrueTypeFontUnicode ttu;
+
+ CJKFont cjkFont;
+ /** The array used with single byte encodings
+ */
+ byte shortTag[];
+ /** The map used with double byte encodings. The key is Integer(glyph) and the
+ * value is int[]{glyph, width, Unicode code}
+ */
+ HashMap longTag;
+
+ IntHashtable cjkTag;
+ /** The font type
+ */
+ int fontType;
+ /** true
if the font is symbolic
+ */
+ boolean symbolic;
+ /** Indicates if all the glyphs and widths for that particular
+ * encoding should be included in the document.
+ */
+ protected boolean subset = true;
+ /** Each font used in a document has an instance of this class.
+ * This class stores the characters used in the document and other
+ * specifics unique to the current working document.
+ * @param fontName the font name
+ * @param indirectReference the indirect reference to the font
+ * @param baseFont the BaseFont
+ */
+ FontDetails(PdfName fontName, PdfIndirectReference indirectReference, BaseFont baseFont) {
+ this.fontName = fontName;
+ this.indirectReference = indirectReference;
+ this.baseFont = baseFont;
+ fontType = baseFont.getFontType();
+ switch (fontType) {
+ case BaseFont.FONT_TYPE_T1:
+ case BaseFont.FONT_TYPE_TT:
+ shortTag = new byte[256];
+ break;
+ case BaseFont.FONT_TYPE_CJK:
+ cjkTag = new IntHashtable();
+ cjkFont = (CJKFont)baseFont;
+ break;
+ case BaseFont.FONT_TYPE_TTUNI:
+ longTag = new HashMap();
+ ttu = (TrueTypeFontUnicode)baseFont;
+ symbolic = baseFont.isFontSpecific();
+ break;
+ }
+ }
+
+ /** Gets the indirect reference to this font.
+ * @return the indirect reference to this font
+ */
+ PdfIndirectReference getIndirectReference() {
+ return indirectReference;
+ }
+
+ /** Gets the font name as it appears in the document body.
+ * @return the font name
+ */
+ PdfName getFontName() {
+ return fontName;
+ }
+
+ /** Gets the BaseFont
of this font.
+ * @return the BaseFont
of this font
+ */
+ BaseFont getBaseFont() {
+ return baseFont;
+ }
+
+ /** Converts the text into bytes to be placed in the document.
+ * The conversion is done according to the font and the encoding and the characters
+ * used are stored.
+ * @param text the text to convert
+ * @return the conversion
+ */
+ byte[] convertToBytes(String text) {
+ byte b[] = null;
+ switch (fontType) {
+ case BaseFont.FONT_TYPE_T3:
+ return baseFont.convertToBytes(text);
+ case BaseFont.FONT_TYPE_T1:
+ case BaseFont.FONT_TYPE_TT: {
+ b = baseFont.convertToBytes(text);
+ int len = b.length;
+ for (int k = 0; k < len; ++k)
+ shortTag[((int)b[k]) & 0xff] = 1;
+ break;
+ }
+ case BaseFont.FONT_TYPE_CJK: {
+ int len = text.length();
+ for (int k = 0; k < len; ++k)
+ cjkTag.put(cjkFont.getCidCode(text.charAt(k)), 0);
+ b = baseFont.convertToBytes(text);
+ break;
+ }
+ case BaseFont.FONT_TYPE_DOCUMENT: {
+ b = baseFont.convertToBytes(text);
+ break;
+ }
+ case BaseFont.FONT_TYPE_TTUNI: {
+ try {
+ int len = text.length();
+ int metrics[] = null;
+ char glyph[] = new char[len];
+ int i = 0;
+ if (symbolic) {
+ b = PdfEncodings.convertToBytes(text, "symboltt");
+ len = b.length;
+ for (int k = 0; k < len; ++k) {
+ metrics = ttu.getMetricsTT(b[k] & 0xff);
+ if (metrics == null)
+ continue;
+ longTag.put(new Integer(metrics[0]), new int[]{metrics[0], metrics[1], ttu.getUnicodeDifferences(b[k] & 0xff)});
+ glyph[i++] = (char)metrics[0];
+ }
+ }
+ else {
+ for (int k = 0; k < len; ++k) {
+ char c = text.charAt(k);
+ metrics = ttu.getMetricsTT(c);
+ if (metrics == null)
+ continue;
+ int m0 = metrics[0];
+ Integer gl = new Integer(m0);
+ if (!longTag.containsKey(gl))
+ longTag.put(gl, new int[]{m0, metrics[1], c});
+ glyph[i++] = (char)m0;
+ }
+ }
+ String s = new String(glyph, 0, i);
+ b = s.getBytes(CJKFont.CJK_ENCODING);
+ }
+ catch (UnsupportedEncodingException e) {
+ throw new ExceptionConverter(e);
+ }
+ break;
+ }
+ }
+ return b;
+ }
+
+ /** Writes the font definition to the document.
+ * @param writer the PdfWriter
of this document
+ */
+ void writeFont(PdfWriter writer) {
+ try {
+ switch (fontType) {
+ case BaseFont.FONT_TYPE_T3:
+ baseFont.writeFont(writer, indirectReference, null);
+ break;
+ case BaseFont.FONT_TYPE_T1:
+ case BaseFont.FONT_TYPE_TT: {
+ int firstChar;
+ int lastChar;
+ if (subset) {
+ for (firstChar = 0; firstChar < 256; ++firstChar) {
+ if (shortTag[firstChar] != 0)
+ break;
+ }
+ for (lastChar = 255; lastChar >= firstChar; --lastChar) {
+ if (shortTag[lastChar] != 0)
+ break;
+ }
+ if (firstChar > 255) {
+ firstChar = 255;
+ lastChar = 255;
+ }
+ }
+ else {
+ for (int k = 0; k < shortTag.length; ++k)
+ shortTag[k] = 1;
+ firstChar = 0;
+ lastChar = shortTag.length - 1;
+ }
+ baseFont.writeFont(writer, indirectReference, new Object[]{new Integer(firstChar), new Integer(lastChar), shortTag});
+ break;
+ }
+ case BaseFont.FONT_TYPE_CJK:
+ baseFont.writeFont(writer, indirectReference, new Object[]{cjkTag});
+ break;
+ case BaseFont.FONT_TYPE_TTUNI:
+ baseFont.writeFont(writer, indirectReference, new Object[]{longTag});
+ break;
+ }
+ }
+ catch(Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /** Indicates if all the glyphs and widths for that particular
+ * encoding should be included in the document.
+ * @return false
to include all the glyphs and widths.
+ */
+ public boolean isSubset() {
+ return subset;
+ }
+
+ /** Indicates if all the glyphs and widths for that particular
+ * encoding should be included in the document. Set to false
+ * to include all.
+ * @param subset new value of property subset
+ */
+ public void setSubset(boolean subset) {
+ this.subset = subset;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/FontMapper.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/FontMapper.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/FontMapper.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/FontMapper.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2002 by Jeremy Bowman .
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.awt.Font;
+
+/**
+ * A FontMapper implementation handles mappings between AWT Fonts and PDF
+ * fonts. An interface is used instead of a fixed class because there isn't
+ * an exact correlation between the font types, so each application is free
+ * to define a mapping which is appropriate for it.
+ */
+
+public interface FontMapper {
+
+ /**
+ * Returns a BaseFont which can be used to represent the given AWT Font
+ *
+ * @param font the font to be converted
+ * @return a BaseFont which has similar properties to the provided Font
+ */
+
+ public BaseFont awtToPdf(Font font);
+
+ /**
+ * Returns an AWT Font which can be used to represent the given BaseFont
+ *
+ * @param font the font to be converted
+ * @param size the desired point size of the resulting font
+ * @return a Font which has similar properties to the provided BaseFont
+ */
+
+ public Font pdfToAwt(BaseFont font, int size);
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/GlyphList.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/GlyphList.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/GlyphList.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/GlyphList.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,2190 @@
+/*
+ * $Id: GlyphList.java,v 1.20 2002/06/18 13:59:40 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.HashMap;
+
+public class GlyphList
+{
+ private static HashMap unicode2names = new HashMap();
+ private static HashMap names2unicode = new HashMap();
+
+ private static final int unicode[] =
+ {
+ 0x0041,
+ 0x00C6,
+ 0x01FC,
+ 0xF7E6,
+ 0x00C1,
+ 0xF7E1,
+ 0x0102,
+ 0x00C2,
+ 0xF7E2,
+ 0xF6C9,
+ 0xF7B4,
+ 0x00C4,
+ 0xF7E4,
+ 0x00C0,
+ 0xF7E0,
+ 0x0391,
+ 0x0386,
+ 0x0100,
+ 0x0104,
+ 0x00C5,
+ 0x01FA,
+ 0xF7E5,
+ 0xF761,
+ 0x00C3,
+ 0xF7E3,
+ 0x0042,
+ 0x0392,
+ 0xF6F4,
+ 0xF762,
+ 0x0043,
+ 0x0106,
+ 0xF6CA,
+ 0xF6F5,
+ 0x010C,
+ 0x00C7,
+ 0xF7E7,
+ 0x0108,
+ 0x010A,
+ 0xF7B8,
+ 0x03A7,
+ 0xF6F6,
+ 0xF763,
+ 0x0044,
+ 0x010E,
+ 0x0110,
+ 0x2206,
+ 0x0394,
+ 0xF6CB,
+ 0xF6CC,
+ 0xF6CD,
+ 0xF7A8,
+ 0xF6F7,
+ 0xF764,
+ 0x0045,
+ 0x00C9,
+ 0xF7E9,
+ 0x0114,
+ 0x011A,
+ 0x00CA,
+ 0xF7EA,
+ 0x00CB,
+ 0xF7EB,
+ 0x0116,
+ 0x00C8,
+ 0xF7E8,
+ 0x0112,
+ 0x014A,
+ 0x0118,
+ 0x0395,
+ 0x0388,
+ 0xF765,
+ 0x0397,
+ 0x0389,
+ 0x00D0,
+ 0xF7F0,
+ 0x20AC,
+ 0x0046,
+ 0xF766,
+ 0x0047,
+ 0x0393,
+ 0x011E,
+ 0x01E6,
+ 0x011C,
+ 0x0122,
+ 0x0120,
+ 0xF6CE,
+ 0xF760,
+ 0xF767,
+ 0x0048,
+ 0x25CF,
+ 0x25AA,
+ 0x25AB,
+ 0x25A1,
+ 0x0126,
+ 0x0124,
+ 0xF768,
+ 0xF6CF,
+ 0xF6F8,
+ 0x0049,
+ 0x0132,
+ 0x00CD,
+ 0xF7ED,
+ 0x012C,
+ 0x00CE,
+ 0xF7EE,
+ 0x00CF,
+ 0xF7EF,
+ 0x0130,
+ 0x2111,
+ 0x00CC,
+ 0xF7EC,
+ 0x012A,
+ 0x012E,
+ 0x0399,
+ 0x03AA,
+ 0x038A,
+ 0xF769,
+ 0x0128,
+ 0x004A,
+ 0x0134,
+ 0xF76A,
+ 0x004B,
+ 0x039A,
+ 0x0136,
+ 0xF76B,
+ 0x004C,
+ 0xF6BF,
+ 0x0139,
+ 0x039B,
+ 0x013D,
+ 0x013B,
+ 0x013F,
+ 0x0141,
+ 0xF6F9,
+ 0xF76C,
+ 0x004D,
+ 0xF6D0,
+ 0xF7AF,
+ 0xF76D,
+ 0x039C,
+ 0x004E,
+ 0x0143,
+ 0x0147,
+ 0x0145,
+ 0xF76E,
+ 0x00D1,
+ 0xF7F1,
+ 0x039D,
+ 0x004F,
+ 0x0152,
+ 0xF6FA,
+ 0x00D3,
+ 0xF7F3,
+ 0x014E,
+ 0x00D4,
+ 0xF7F4,
+ 0x00D6,
+ 0xF7F6,
+ 0xF6FB,
+ 0x00D2,
+ 0xF7F2,
+ 0x01A0,
+ 0x0150,
+ 0x014C,
+ 0x2126,
+ 0x03A9,
+ 0x038F,
+ 0x039F,
+ 0x038C,
+ 0x00D8,
+ 0x01FE,
+ 0xF7F8,
+ 0xF76F,
+ 0x00D5,
+ 0xF7F5,
+ 0x0050,
+ 0x03A6,
+ 0x03A0,
+ 0x03A8,
+ 0xF770,
+ 0x0051,
+ 0xF771,
+ 0x0052,
+ 0x0154,
+ 0x0158,
+ 0x0156,
+ 0x211C,
+ 0x03A1,
+ 0xF6FC,
+ 0xF772,
+ 0x0053,
+ 0x250C,
+ 0x2514,
+ 0x2510,
+ 0x2518,
+ 0x253C,
+ 0x252C,
+ 0x2534,
+ 0x251C,
+ 0x2524,
+ 0x2500,
+ 0x2502,
+ 0x2561,
+ 0x2562,
+ 0x2556,
+ 0x2555,
+ 0x2563,
+ 0x2551,
+ 0x2557,
+ 0x255D,
+ 0x255C,
+ 0x255B,
+ 0x255E,
+ 0x255F,
+ 0x255A,
+ 0x2554,
+ 0x2569,
+ 0x2566,
+ 0x2560,
+ 0x2550,
+ 0x256C,
+ 0x2567,
+ 0x2568,
+ 0x2564,
+ 0x2565,
+ 0x2559,
+ 0x2558,
+ 0x2552,
+ 0x2553,
+ 0x256B,
+ 0x256A,
+ 0x015A,
+ 0x0160,
+ 0xF6FD,
+ 0x015E,
+ 0xF6C1,
+ 0x015C,
+ 0x0218,
+ 0x03A3,
+ 0xF773,
+ 0x0054,
+ 0x03A4,
+ 0x0166,
+ 0x0164,
+ 0x0162,
+ 0x021A,
+ 0x0398,
+ 0x00DE,
+ 0xF7FE,
+ 0xF6FE,
+ 0xF774,
+ 0x0055,
+ 0x00DA,
+ 0xF7FA,
+ 0x016C,
+ 0x00DB,
+ 0xF7FB,
+ 0x00DC,
+ 0xF7FC,
+ 0x00D9,
+ 0xF7F9,
+ 0x01AF,
+ 0x0170,
+ 0x016A,
+ 0x0172,
+ 0x03A5,
+ 0x03D2,
+ 0x03AB,
+ 0x038E,
+ 0x016E,
+ 0xF775,
+ 0x0168,
+ 0x0056,
+ 0xF776,
+ 0x0057,
+ 0x1E82,
+ 0x0174,
+ 0x1E84,
+ 0x1E80,
+ 0xF777,
+ 0x0058,
+ 0x039E,
+ 0xF778,
+ 0x0059,
+ 0x00DD,
+ 0xF7FD,
+ 0x0176,
+ 0x0178,
+ 0xF7FF,
+ 0x1EF2,
+ 0xF779,
+ 0x005A,
+ 0x0179,
+ 0x017D,
+ 0xF6FF,
+ 0x017B,
+ 0x0396,
+ 0xF77A,
+ 0x0061,
+ 0x00E1,
+ 0x0103,
+ 0x00E2,
+ 0x00B4,
+ 0x0301,
+ 0x00E4,
+ 0x00E6,
+ 0x01FD,
+ 0x2015,
+ 0x0410,
+ 0x0411,
+ 0x0412,
+ 0x0413,
+ 0x0414,
+ 0x0415,
+ 0x0401,
+ 0x0416,
+ 0x0417,
+ 0x0418,
+ 0x0419,
+ 0x041A,
+ 0x041B,
+ 0x041C,
+ 0x041D,
+ 0x041E,
+ 0x041F,
+ 0x0420,
+ 0x0421,
+ 0x0422,
+ 0x0423,
+ 0x0424,
+ 0x0425,
+ 0x0426,
+ 0x0427,
+ 0x0428,
+ 0x0429,
+ 0x042A,
+ 0x042B,
+ 0x042C,
+ 0x042D,
+ 0x042E,
+ 0x042F,
+ 0x0490,
+ 0x0402,
+ 0x0403,
+ 0x0404,
+ 0x0405,
+ 0x0406,
+ 0x0407,
+ 0x0408,
+ 0x0409,
+ 0x040A,
+ 0x040B,
+ 0x040C,
+ 0x040E,
+ 0xF6C4,
+ 0xF6C5,
+ 0x0430,
+ 0x0431,
+ 0x0432,
+ 0x0433,
+ 0x0434,
+ 0x0435,
+ 0x0451,
+ 0x0436,
+ 0x0437,
+ 0x0438,
+ 0x0439,
+ 0x043A,
+ 0x043B,
+ 0x043C,
+ 0x043D,
+ 0x043E,
+ 0x043F,
+ 0x0440,
+ 0x0441,
+ 0x0442,
+ 0x0443,
+ 0x0444,
+ 0x0445,
+ 0x0446,
+ 0x0447,
+ 0x0448,
+ 0x0449,
+ 0x044A,
+ 0x044B,
+ 0x044C,
+ 0x044D,
+ 0x044E,
+ 0x044F,
+ 0x0491,
+ 0x0452,
+ 0x0453,
+ 0x0454,
+ 0x0455,
+ 0x0456,
+ 0x0457,
+ 0x0458,
+ 0x0459,
+ 0x045A,
+ 0x045B,
+ 0x045C,
+ 0x045E,
+ 0x040F,
+ 0x0462,
+ 0x0472,
+ 0x0474,
+ 0xF6C6,
+ 0x045F,
+ 0x0463,
+ 0x0473,
+ 0x0475,
+ 0xF6C7,
+ 0xF6C8,
+ 0x04D9,
+ 0x200E,
+ 0x200F,
+ 0x200D,
+ 0x066A,
+ 0x060C,
+ 0x0660,
+ 0x0661,
+ 0x0662,
+ 0x0663,
+ 0x0664,
+ 0x0665,
+ 0x0666,
+ 0x0667,
+ 0x0668,
+ 0x0669,
+ 0x061B,
+ 0x061F,
+ 0x0621,
+ 0x0622,
+ 0x0623,
+ 0x0624,
+ 0x0625,
+ 0x0626,
+ 0x0627,
+ 0x0628,
+ 0x0629,
+ 0x062A,
+ 0x062B,
+ 0x062C,
+ 0x062D,
+ 0x062E,
+ 0x062F,
+ 0x0630,
+ 0x0631,
+ 0x0632,
+ 0x0633,
+ 0x0634,
+ 0x0635,
+ 0x0636,
+ 0x0637,
+ 0x0638,
+ 0x0639,
+ 0x063A,
+ 0x0640,
+ 0x0641,
+ 0x0642,
+ 0x0643,
+ 0x0644,
+ 0x0645,
+ 0x0646,
+ 0x0648,
+ 0x0649,
+ 0x064A,
+ 0x064B,
+ 0x064C,
+ 0x064D,
+ 0x064E,
+ 0x064F,
+ 0x0650,
+ 0x0651,
+ 0x0652,
+ 0x0647,
+ 0x06A4,
+ 0x067E,
+ 0x0686,
+ 0x0698,
+ 0x06AF,
+ 0x0679,
+ 0x0688,
+ 0x0691,
+ 0x06BA,
+ 0x06D2,
+ 0x06D5,
+ 0x20AA,
+ 0x05BE,
+ 0x05C3,
+ 0x05D0,
+ 0x05D1,
+ 0x05D2,
+ 0x05D3,
+ 0x05D4,
+ 0x05D5,
+ 0x05D6,
+ 0x05D7,
+ 0x05D8,
+ 0x05D9,
+ 0x05DA,
+ 0x05DB,
+ 0x05DC,
+ 0x05DD,
+ 0x05DE,
+ 0x05DF,
+ 0x05E0,
+ 0x05E1,
+ 0x05E2,
+ 0x05E3,
+ 0x05E4,
+ 0x05E5,
+ 0x05E6,
+ 0x05E7,
+ 0x05E8,
+ 0x05E9,
+ 0x05EA,
+ 0xFB2A,
+ 0xFB2B,
+ 0xFB4B,
+ 0xFB1F,
+ 0x05F0,
+ 0x05F1,
+ 0x05F2,
+ 0xFB35,
+ 0x05B4,
+ 0x05B5,
+ 0x05B6,
+ 0x05BB,
+ 0x05B8,
+ 0x05B7,
+ 0x05B0,
+ 0x05B2,
+ 0x05B1,
+ 0x05B3,
+ 0x05C2,
+ 0x05C1,
+ 0x05B9,
+ 0x05BC,
+ 0x05BD,
+ 0x05BF,
+ 0x05C0,
+ 0x02BC,
+ 0x2105,
+ 0x2113,
+ 0x2116,
+ 0x202C,
+ 0x202D,
+ 0x202E,
+ 0x200C,
+ 0x066D,
+ 0x02BD,
+ 0x00E0,
+ 0x2135,
+ 0x03B1,
+ 0x03AC,
+ 0x0101,
+ 0x0026,
+ 0xF726,
+ 0x2220,
+ 0x2329,
+ 0x232A,
+ 0x0387,
+ 0x0105,
+ 0x2248,
+ 0x00E5,
+ 0x01FB,
+ 0x2194,
+ 0x21D4,
+ 0x21D3,
+ 0x21D0,
+ 0x21D2,
+ 0x21D1,
+ 0x2193,
+ 0xF8E7,
+ 0x2190,
+ 0x2192,
+ 0x2191,
+ 0x2195,
+ 0x21A8,
+ 0xF8E6,
+ 0x005E,
+ 0x007E,
+ 0x002A,
+ 0x2217,
+ 0xF6E9,
+ 0x0040,
+ 0x00E3,
+ 0x0062,
+ 0x005C,
+ 0x007C,
+ 0x03B2,
+ 0x2588,
+ 0xF8F4,
+ 0x007B,
+ 0xF8F3,
+ 0xF8F2,
+ 0xF8F1,
+ 0x007D,
+ 0xF8FE,
+ 0xF8FD,
+ 0xF8FC,
+ 0x005B,
+ 0xF8F0,
+ 0xF8EF,
+ 0xF8EE,
+ 0x005D,
+ 0xF8FB,
+ 0xF8FA,
+ 0xF8F9,
+ 0x02D8,
+ 0x00A6,
+ 0xF6EA,
+ 0x2022,
+ 0x0063,
+ 0x0107,
+ 0x02C7,
+ 0x21B5,
+ 0x010D,
+ 0x00E7,
+ 0x0109,
+ 0x010B,
+ 0x00B8,
+ 0x00A2,
+ 0xF6DF,
+ 0xF7A2,
+ 0xF6E0,
+ 0x03C7,
+ 0x25CB,
+ 0x2297,
+ 0x2295,
+ 0x02C6,
+ 0x2663,
+ 0x003A,
+ 0x20A1,
+ 0x002C,
+ 0xF6C3,
+ 0xF6E1,
+ 0xF6E2,
+ 0x2245,
+ 0x00A9,
+ 0xF8E9,
+ 0xF6D9,
+ 0x00A4,
+ 0xF6D1,
+ 0xF6D2,
+ 0xF6D4,
+ 0xF6D5,
+ 0x0064,
+ 0x2020,
+ 0x2021,
+ 0xF6D3,
+ 0xF6D6,
+ 0x010F,
+ 0x0111,
+ 0x00B0,
+ 0x03B4,
+ 0x2666,
+ 0x00A8,
+ 0xF6D7,
+ 0xF6D8,
+ 0x0385,
+ 0x00F7,
+ 0x2593,
+ 0x2584,
+ 0x0024,
+ 0xF6E3,
+ 0xF724,
+ 0xF6E4,
+ 0x20AB,
+ 0x02D9,
+ 0x0323,
+ 0x0131,
+ 0xF6BE,
+ 0x22C5,
+ 0xF6EB,
+ 0x0065,
+ 0x00E9,
+ 0x0115,
+ 0x011B,
+ 0x00EA,
+ 0x00EB,
+ 0x0117,
+ 0x00E8,
+ 0x0038,
+ 0x2088,
+ 0xF738,
+ 0x2078,
+ 0x2208,
+ 0x2026,
+ 0x0113,
+ 0x2014,
+ 0x2205,
+ 0x2013,
+ 0x014B,
+ 0x0119,
+ 0x03B5,
+ 0x03AD,
+ 0x003D,
+ 0x2261,
+ 0x212E,
+ 0xF6EC,
+ 0x03B7,
+ 0x03AE,
+ 0x00F0,
+ 0x0021,
+ 0x203C,
+ 0x00A1,
+ 0xF7A1,
+ 0xF721,
+ 0x2203,
+ 0x0066,
+ 0x2640,
+ 0xFB00,
+ 0xFB03,
+ 0xFB04,
+ 0xFB01,
+ 0x2012,
+ 0x25A0,
+ 0x25AC,
+ 0x0035,
+ 0x215D,
+ 0x2085,
+ 0xF735,
+ 0x2075,
+ 0xFB02,
+ 0x0192,
+ 0x0034,
+ 0x2084,
+ 0xF734,
+ 0x2074,
+ 0x2044,
+ 0x2215,
+ 0x20A3,
+ 0x0067,
+ 0x03B3,
+ 0x011F,
+ 0x01E7,
+ 0x011D,
+ 0x0123,
+ 0x0121,
+ 0x00DF,
+ 0x2207,
+ 0x0060,
+ 0x0300,
+ 0x003E,
+ 0x2265,
+ 0x00AB,
+ 0x00BB,
+ 0x2039,
+ 0x203A,
+ 0x0068,
+ 0x0127,
+ 0x0125,
+ 0x2665,
+ 0x0309,
+ 0x2302,
+ 0x02DD,
+ 0x002D,
+ 0x00AD,
+ 0xF6E5,
+ 0xF6E6,
+ 0x0069,
+ 0x00ED,
+ 0x012D,
+ 0x00EE,
+ 0x00EF,
+ 0x00EC,
+ 0x0133,
+ 0x012B,
+ 0x221E,
+ 0x222B,
+ 0x2321,
+ 0xF8F5,
+ 0x2320,
+ 0x2229,
+ 0x25D8,
+ 0x25D9,
+ 0x263B,
+ 0x012F,
+ 0x03B9,
+ 0x03CA,
+ 0x0390,
+ 0x03AF,
+ 0xF6ED,
+ 0x0129,
+ 0x006A,
+ 0x0135,
+ 0x006B,
+ 0x03BA,
+ 0x0137,
+ 0x0138,
+ 0x006C,
+ 0x013A,
+ 0x03BB,
+ 0x013E,
+ 0x013C,
+ 0x0140,
+ 0x003C,
+ 0x2264,
+ 0x258C,
+ 0x20A4,
+ 0xF6C0,
+ 0x2227,
+ 0x00AC,
+ 0x2228,
+ 0x017F,
+ 0x25CA,
+ 0x0142,
+ 0xF6EE,
+ 0x2591,
+ 0x006D,
+ 0x00AF,
+ 0x02C9,
+ 0x2642,
+ 0x2212,
+ 0x2032,
+ 0xF6EF,
+ 0x00B5,
+ 0x03BC,
+ 0x00D7,
+ 0x266A,
+ 0x266B,
+ 0x006E,
+ 0x0144,
+ 0x0149,
+ 0x0148,
+ 0x0146,
+ 0x0039,
+ 0x2089,
+ 0xF739,
+ 0x2079,
+ 0x2209,
+ 0x2260,
+ 0x2284,
+ 0x207F,
+ 0x00F1,
+ 0x03BD,
+ 0x0023,
+ 0x006F,
+ 0x00F3,
+ 0x014F,
+ 0x00F4,
+ 0x00F6,
+ 0x0153,
+ 0x02DB,
+ 0x00F2,
+ 0x01A1,
+ 0x0151,
+ 0x014D,
+ 0x03C9,
+ 0x03D6,
+ 0x03CE,
+ 0x03BF,
+ 0x03CC,
+ 0x0031,
+ 0x2024,
+ 0x215B,
+ 0xF6DC,
+ 0x00BD,
+ 0x2081,
+ 0xF731,
+ 0x00BC,
+ 0x00B9,
+ 0x2153,
+ 0x25E6,
+ 0x00AA,
+ 0x00BA,
+ 0x221F,
+ 0x00F8,
+ 0x01FF,
+ 0xF6F0,
+ 0x00F5,
+ 0x0070,
+ 0x00B6,
+ 0x0028,
+ 0xF8ED,
+ 0xF8EC,
+ 0x208D,
+ 0x207D,
+ 0xF8EB,
+ 0x0029,
+ 0xF8F8,
+ 0xF8F7,
+ 0x208E,
+ 0x207E,
+ 0xF8F6,
+ 0x2202,
+ 0x0025,
+ 0x002E,
+ 0x00B7,
+ 0x2219,
+ 0xF6E7,
+ 0xF6E8,
+ 0x22A5,
+ 0x2030,
+ 0x20A7,
+ 0x03C6,
+ 0x03D5,
+ 0x03C0,
+ 0x002B,
+ 0x00B1,
+ 0x211E,
+ 0x220F,
+ 0x2282,
+ 0x2283,
+ 0x221D,
+ 0x03C8,
+ 0x0071,
+ 0x003F,
+ 0x00BF,
+ 0xF7BF,
+ 0xF73F,
+ 0x0022,
+ 0x201E,
+ 0x201C,
+ 0x201D,
+ 0x2018,
+ 0x201B,
+ 0x2019,
+ 0x201A,
+ 0x0027,
+ 0x0072,
+ 0x0155,
+ 0x221A,
+ 0xF8E5,
+ 0x0159,
+ 0x0157,
+ 0x2286,
+ 0x2287,
+ 0x00AE,
+ 0xF8E8,
+ 0xF6DA,
+ 0x2310,
+ 0x03C1,
+ 0x02DA,
+ 0xF6F1,
+ 0x2590,
+ 0xF6DD,
+ 0x0073,
+ 0x015B,
+ 0x0161,
+ 0x015F,
+ 0xF6C2,
+ 0x015D,
+ 0x0219,
+ 0x2033,
+ 0x00A7,
+ 0x003B,
+ 0x0037,
+ 0x215E,
+ 0x2087,
+ 0xF737,
+ 0x2077,
+ 0x2592,
+ 0x03C3,
+ 0x03C2,
+ 0x223C,
+ 0x0036,
+ 0x2086,
+ 0xF736,
+ 0x2076,
+ 0x002F,
+ 0x263A,
+ 0x0020,
+ 0x00A0,
+ 0x2660,
+ 0xF6F2,
+ 0x00A3,
+ 0x220B,
+ 0x2211,
+ 0x263C,
+ 0x0074,
+ 0x03C4,
+ 0x0167,
+ 0x0165,
+ 0x0163,
+ 0x021B,
+ 0x2234,
+ 0x03B8,
+ 0x03D1,
+ 0x00FE,
+ 0x0033,
+ 0x215C,
+ 0x2083,
+ 0xF733,
+ 0x00BE,
+ 0xF6DE,
+ 0x00B3,
+ 0x02DC,
+ 0x0303,
+ 0x0384,
+ 0x2122,
+ 0xF8EA,
+ 0xF6DB,
+ 0x25BC,
+ 0x25C4,
+ 0x25BA,
+ 0x25B2,
+ 0xF6F3,
+ 0x0032,
+ 0x2025,
+ 0x2082,
+ 0xF732,
+ 0x00B2,
+ 0x2154,
+ 0x0075,
+ 0x00FA,
+ 0x016D,
+ 0x00FB,
+ 0x00FC,
+ 0x00F9,
+ 0x01B0,
+ 0x0171,
+ 0x016B,
+ 0x005F,
+ 0x2017,
+ 0x222A,
+ 0x2200,
+ 0x0173,
+ 0x2580,
+ 0x03C5,
+ 0x03CB,
+ 0x03B0,
+ 0x03CD,
+ 0x016F,
+ 0x0169,
+ 0x0076,
+ 0x0077,
+ 0x1E83,
+ 0x0175,
+ 0x1E85,
+ 0x2118,
+ 0x1E81,
+ 0x0078,
+ 0x03BE,
+ 0x0079,
+ 0x00FD,
+ 0x0177,
+ 0x00FF,
+ 0x00A5,
+ 0x1EF3,
+ 0x007A,
+ 0x017A,
+ 0x017E,
+ 0x017C,
+ 0x0030,
+ 0x2080,
+ 0xF730,
+ 0x2070,
+ 0x03B6
+ };
+
+ private static final String names[] =
+ {
+ "A",
+ "AE",
+ "AEacute",
+ "AEsmall",
+ "Aacute",
+ "Aacutesmall",
+ "Abreve",
+ "Acircumflex",
+ "Acircumflexsmall",
+ "Acute",
+ "Acutesmall",
+ "Adieresis",
+ "Adieresissmall",
+ "Agrave",
+ "Agravesmall",
+ "Alpha",
+ "Alphatonos",
+ "Amacron",
+ "Aogonek",
+ "Aring",
+ "Aringacute",
+ "Aringsmall",
+ "Asmall",
+ "Atilde",
+ "Atildesmall",
+ "B",
+ "Beta",
+ "Brevesmall",
+ "Bsmall",
+ "C",
+ "Cacute",
+ "Caron",
+ "Caronsmall",
+ "Ccaron",
+ "Ccedilla",
+ "Ccedillasmall",
+ "Ccircumflex",
+ "Cdotaccent",
+ "Cedillasmall",
+ "Chi",
+ "Circumflexsmall",
+ "Csmall",
+ "D",
+ "Dcaron",
+ "Dcroat",
+ "Delta",
+ "Delta",
+ "Dieresis",
+ "DieresisAcute",
+ "DieresisGrave",
+ "Dieresissmall",
+ "Dotaccentsmall",
+ "Dsmall",
+ "E",
+ "Eacute",
+ "Eacutesmall",
+ "Ebreve",
+ "Ecaron",
+ "Ecircumflex",
+ "Ecircumflexsmall",
+ "Edieresis",
+ "Edieresissmall",
+ "Edotaccent",
+ "Egrave",
+ "Egravesmall",
+ "Emacron",
+ "Eng",
+ "Eogonek",
+ "Epsilon",
+ "Epsilontonos",
+ "Esmall",
+ "Eta",
+ "Etatonos",
+ "Eth",
+ "Ethsmall",
+ "Euro",
+ "F",
+ "Fsmall",
+ "G",
+ "Gamma",
+ "Gbreve",
+ "Gcaron",
+ "Gcircumflex",
+ "Gcommaaccent",
+ "Gdotaccent",
+ "Grave",
+ "Gravesmall",
+ "Gsmall",
+ "H",
+ "H18533",
+ "H18543",
+ "H18551",
+ "H22073",
+ "Hbar",
+ "Hcircumflex",
+ "Hsmall",
+ "Hungarumlaut",
+ "Hungarumlautsmall",
+ "I",
+ "IJ",
+ "Iacute",
+ "Iacutesmall",
+ "Ibreve",
+ "Icircumflex",
+ "Icircumflexsmall",
+ "Idieresis",
+ "Idieresissmall",
+ "Idotaccent",
+ "Ifraktur",
+ "Igrave",
+ "Igravesmall",
+ "Imacron",
+ "Iogonek",
+ "Iota",
+ "Iotadieresis",
+ "Iotatonos",
+ "Ismall",
+ "Itilde",
+ "J",
+ "Jcircumflex",
+ "Jsmall",
+ "K",
+ "Kappa",
+ "Kcommaaccent",
+ "Ksmall",
+ "L",
+ "LL",
+ "Lacute",
+ "Lambda",
+ "Lcaron",
+ "Lcommaaccent",
+ "Ldot",
+ "Lslash",
+ "Lslashsmall",
+ "Lsmall",
+ "M",
+ "Macron",
+ "Macronsmall",
+ "Msmall",
+ "Mu",
+ "N",
+ "Nacute",
+ "Ncaron",
+ "Ncommaaccent",
+ "Nsmall",
+ "Ntilde",
+ "Ntildesmall",
+ "Nu",
+ "O",
+ "OE",
+ "OEsmall",
+ "Oacute",
+ "Oacutesmall",
+ "Obreve",
+ "Ocircumflex",
+ "Ocircumflexsmall",
+ "Odieresis",
+ "Odieresissmall",
+ "Ogoneksmall",
+ "Ograve",
+ "Ogravesmall",
+ "Ohorn",
+ "Ohungarumlaut",
+ "Omacron",
+ "Omega",
+ "Omega",
+ "Omegatonos",
+ "Omicron",
+ "Omicrontonos",
+ "Oslash",
+ "Oslashacute",
+ "Oslashsmall",
+ "Osmall",
+ "Otilde",
+ "Otildesmall",
+ "P",
+ "Phi",
+ "Pi",
+ "Psi",
+ "Psmall",
+ "Q",
+ "Qsmall",
+ "R",
+ "Racute",
+ "Rcaron",
+ "Rcommaaccent",
+ "Rfraktur",
+ "Rho",
+ "Ringsmall",
+ "Rsmall",
+ "S",
+ "SF010000",
+ "SF020000",
+ "SF030000",
+ "SF040000",
+ "SF050000",
+ "SF060000",
+ "SF070000",
+ "SF080000",
+ "SF090000",
+ "SF100000",
+ "SF110000",
+ "SF190000",
+ "SF200000",
+ "SF210000",
+ "SF220000",
+ "SF230000",
+ "SF240000",
+ "SF250000",
+ "SF260000",
+ "SF270000",
+ "SF280000",
+ "SF360000",
+ "SF370000",
+ "SF380000",
+ "SF390000",
+ "SF400000",
+ "SF410000",
+ "SF420000",
+ "SF430000",
+ "SF440000",
+ "SF450000",
+ "SF460000",
+ "SF470000",
+ "SF480000",
+ "SF490000",
+ "SF500000",
+ "SF510000",
+ "SF520000",
+ "SF530000",
+ "SF540000",
+ "Sacute",
+ "Scaron",
+ "Scaronsmall",
+ "Scedilla",
+ "Scedilla",
+ "Scircumflex",
+ "Scommaaccent",
+ "Sigma",
+ "Ssmall",
+ "T",
+ "Tau",
+ "Tbar",
+ "Tcaron",
+ "Tcommaaccent",
+ "Tcommaaccent",
+ "Theta",
+ "Thorn",
+ "Thornsmall",
+ "Tildesmall",
+ "Tsmall",
+ "U",
+ "Uacute",
+ "Uacutesmall",
+ "Ubreve",
+ "Ucircumflex",
+ "Ucircumflexsmall",
+ "Udieresis",
+ "Udieresissmall",
+ "Ugrave",
+ "Ugravesmall",
+ "Uhorn",
+ "Uhungarumlaut",
+ "Umacron",
+ "Uogonek",
+ "Upsilon",
+ "Upsilon1",
+ "Upsilondieresis",
+ "Upsilontonos",
+ "Uring",
+ "Usmall",
+ "Utilde",
+ "V",
+ "Vsmall",
+ "W",
+ "Wacute",
+ "Wcircumflex",
+ "Wdieresis",
+ "Wgrave",
+ "Wsmall",
+ "X",
+ "Xi",
+ "Xsmall",
+ "Y",
+ "Yacute",
+ "Yacutesmall",
+ "Ycircumflex",
+ "Ydieresis",
+ "Ydieresissmall",
+ "Ygrave",
+ "Ysmall",
+ "Z",
+ "Zacute",
+ "Zcaron",
+ "Zcaronsmall",
+ "Zdotaccent",
+ "Zeta",
+ "Zsmall",
+ "a",
+ "aacute",
+ "abreve",
+ "acircumflex",
+ "acute",
+ "acutecomb",
+ "adieresis",
+ "ae",
+ "aeacute",
+ "afii00208",
+ "afii10017",
+ "afii10018",
+ "afii10019",
+ "afii10020",
+ "afii10021",
+ "afii10022",
+ "afii10023",
+ "afii10024",
+ "afii10025",
+ "afii10026",
+ "afii10027",
+ "afii10028",
+ "afii10029",
+ "afii10030",
+ "afii10031",
+ "afii10032",
+ "afii10033",
+ "afii10034",
+ "afii10035",
+ "afii10036",
+ "afii10037",
+ "afii10038",
+ "afii10039",
+ "afii10040",
+ "afii10041",
+ "afii10042",
+ "afii10043",
+ "afii10044",
+ "afii10045",
+ "afii10046",
+ "afii10047",
+ "afii10048",
+ "afii10049",
+ "afii10050",
+ "afii10051",
+ "afii10052",
+ "afii10053",
+ "afii10054",
+ "afii10055",
+ "afii10056",
+ "afii10057",
+ "afii10058",
+ "afii10059",
+ "afii10060",
+ "afii10061",
+ "afii10062",
+ "afii10063",
+ "afii10064",
+ "afii10065",
+ "afii10066",
+ "afii10067",
+ "afii10068",
+ "afii10069",
+ "afii10070",
+ "afii10071",
+ "afii10072",
+ "afii10073",
+ "afii10074",
+ "afii10075",
+ "afii10076",
+ "afii10077",
+ "afii10078",
+ "afii10079",
+ "afii10080",
+ "afii10081",
+ "afii10082",
+ "afii10083",
+ "afii10084",
+ "afii10085",
+ "afii10086",
+ "afii10087",
+ "afii10088",
+ "afii10089",
+ "afii10090",
+ "afii10091",
+ "afii10092",
+ "afii10093",
+ "afii10094",
+ "afii10095",
+ "afii10096",
+ "afii10097",
+ "afii10098",
+ "afii10099",
+ "afii10100",
+ "afii10101",
+ "afii10102",
+ "afii10103",
+ "afii10104",
+ "afii10105",
+ "afii10106",
+ "afii10107",
+ "afii10108",
+ "afii10109",
+ "afii10110",
+ "afii10145",
+ "afii10146",
+ "afii10147",
+ "afii10148",
+ "afii10192",
+ "afii10193",
+ "afii10194",
+ "afii10195",
+ "afii10196",
+ "afii10831",
+ "afii10832",
+ "afii10846",
+ "afii299",
+ "afii300",
+ "afii301",
+ "afii57381",
+ "afii57388",
+ "afii57392",
+ "afii57393",
+ "afii57394",
+ "afii57395",
+ "afii57396",
+ "afii57397",
+ "afii57398",
+ "afii57399",
+ "afii57400",
+ "afii57401",
+ "afii57403",
+ "afii57407",
+ "afii57409",
+ "afii57410",
+ "afii57411",
+ "afii57412",
+ "afii57413",
+ "afii57414",
+ "afii57415",
+ "afii57416",
+ "afii57417",
+ "afii57418",
+ "afii57419",
+ "afii57420",
+ "afii57421",
+ "afii57422",
+ "afii57423",
+ "afii57424",
+ "afii57425",
+ "afii57426",
+ "afii57427",
+ "afii57428",
+ "afii57429",
+ "afii57430",
+ "afii57431",
+ "afii57432",
+ "afii57433",
+ "afii57434",
+ "afii57440",
+ "afii57441",
+ "afii57442",
+ "afii57443",
+ "afii57444",
+ "afii57445",
+ "afii57446",
+ "afii57448",
+ "afii57449",
+ "afii57450",
+ "afii57451",
+ "afii57452",
+ "afii57453",
+ "afii57454",
+ "afii57455",
+ "afii57456",
+ "afii57457",
+ "afii57458",
+ "afii57470",
+ "afii57505",
+ "afii57506",
+ "afii57507",
+ "afii57508",
+ "afii57509",
+ "afii57511",
+ "afii57512",
+ "afii57513",
+ "afii57514",
+ "afii57519",
+ "afii57534",
+ "afii57636",
+ "afii57645",
+ "afii57658",
+ "afii57664",
+ "afii57665",
+ "afii57666",
+ "afii57667",
+ "afii57668",
+ "afii57669",
+ "afii57670",
+ "afii57671",
+ "afii57672",
+ "afii57673",
+ "afii57674",
+ "afii57675",
+ "afii57676",
+ "afii57677",
+ "afii57678",
+ "afii57679",
+ "afii57680",
+ "afii57681",
+ "afii57682",
+ "afii57683",
+ "afii57684",
+ "afii57685",
+ "afii57686",
+ "afii57687",
+ "afii57688",
+ "afii57689",
+ "afii57690",
+ "afii57694",
+ "afii57695",
+ "afii57700",
+ "afii57705",
+ "afii57716",
+ "afii57717",
+ "afii57718",
+ "afii57723",
+ "afii57793",
+ "afii57794",
+ "afii57795",
+ "afii57796",
+ "afii57797",
+ "afii57798",
+ "afii57799",
+ "afii57800",
+ "afii57801",
+ "afii57802",
+ "afii57803",
+ "afii57804",
+ "afii57806",
+ "afii57807",
+ "afii57839",
+ "afii57841",
+ "afii57842",
+ "afii57929",
+ "afii61248",
+ "afii61289",
+ "afii61352",
+ "afii61573",
+ "afii61574",
+ "afii61575",
+ "afii61664",
+ "afii63167",
+ "afii64937",
+ "agrave",
+ "aleph",
+ "alpha",
+ "alphatonos",
+ "amacron",
+ "ampersand",
+ "ampersandsmall",
+ "angle",
+ "angleleft",
+ "angleright",
+ "anoteleia",
+ "aogonek",
+ "approxequal",
+ "aring",
+ "aringacute",
+ "arrowboth",
+ "arrowdblboth",
+ "arrowdbldown",
+ "arrowdblleft",
+ "arrowdblright",
+ "arrowdblup",
+ "arrowdown",
+ "arrowhorizex",
+ "arrowleft",
+ "arrowright",
+ "arrowup",
+ "arrowupdn",
+ "arrowupdnbse",
+ "arrowvertex",
+ "asciicircum",
+ "asciitilde",
+ "asterisk",
+ "asteriskmath",
+ "asuperior",
+ "at",
+ "atilde",
+ "b",
+ "backslash",
+ "bar",
+ "beta",
+ "block",
+ "braceex",
+ "braceleft",
+ "braceleftbt",
+ "braceleftmid",
+ "bracelefttp",
+ "braceright",
+ "bracerightbt",
+ "bracerightmid",
+ "bracerighttp",
+ "bracketleft",
+ "bracketleftbt",
+ "bracketleftex",
+ "bracketlefttp",
+ "bracketright",
+ "bracketrightbt",
+ "bracketrightex",
+ "bracketrighttp",
+ "breve",
+ "brokenbar",
+ "bsuperior",
+ "bullet",
+ "c",
+ "cacute",
+ "caron",
+ "carriagereturn",
+ "ccaron",
+ "ccedilla",
+ "ccircumflex",
+ "cdotaccent",
+ "cedilla",
+ "cent",
+ "centinferior",
+ "centoldstyle",
+ "centsuperior",
+ "chi",
+ "circle",
+ "circlemultiply",
+ "circleplus",
+ "circumflex",
+ "club",
+ "colon",
+ "colonmonetary",
+ "comma",
+ "commaaccent",
+ "commainferior",
+ "commasuperior",
+ "congruent",
+ "copyright",
+ "copyrightsans",
+ "copyrightserif",
+ "currency",
+ "cyrBreve",
+ "cyrFlex",
+ "cyrbreve",
+ "cyrflex",
+ "d",
+ "dagger",
+ "daggerdbl",
+ "dblGrave",
+ "dblgrave",
+ "dcaron",
+ "dcroat",
+ "degree",
+ "delta",
+ "diamond",
+ "dieresis",
+ "dieresisacute",
+ "dieresisgrave",
+ "dieresistonos",
+ "divide",
+ "dkshade",
+ "dnblock",
+ "dollar",
+ "dollarinferior",
+ "dollaroldstyle",
+ "dollarsuperior",
+ "dong",
+ "dotaccent",
+ "dotbelowcomb",
+ "dotlessi",
+ "dotlessj",
+ "dotmath",
+ "dsuperior",
+ "e",
+ "eacute",
+ "ebreve",
+ "ecaron",
+ "ecircumflex",
+ "edieresis",
+ "edotaccent",
+ "egrave",
+ "eight",
+ "eightinferior",
+ "eightoldstyle",
+ "eightsuperior",
+ "element",
+ "ellipsis",
+ "emacron",
+ "emdash",
+ "emptyset",
+ "endash",
+ "eng",
+ "eogonek",
+ "epsilon",
+ "epsilontonos",
+ "equal",
+ "equivalence",
+ "estimated",
+ "esuperior",
+ "eta",
+ "etatonos",
+ "eth",
+ "exclam",
+ "exclamdbl",
+ "exclamdown",
+ "exclamdownsmall",
+ "exclamsmall",
+ "existential",
+ "f",
+ "female",
+ "ff",
+ "ffi",
+ "ffl",
+ "fi",
+ "figuredash",
+ "filledbox",
+ "filledrect",
+ "five",
+ "fiveeighths",
+ "fiveinferior",
+ "fiveoldstyle",
+ "fivesuperior",
+ "fl",
+ "florin",
+ "four",
+ "fourinferior",
+ "fouroldstyle",
+ "foursuperior",
+ "fraction",
+ "fraction",
+ "franc",
+ "g",
+ "gamma",
+ "gbreve",
+ "gcaron",
+ "gcircumflex",
+ "gcommaaccent",
+ "gdotaccent",
+ "germandbls",
+ "gradient",
+ "grave",
+ "gravecomb",
+ "greater",
+ "greaterequal",
+ "guillemotleft",
+ "guillemotright",
+ "guilsinglleft",
+ "guilsinglright",
+ "h",
+ "hbar",
+ "hcircumflex",
+ "heart",
+ "hookabovecomb",
+ "house",
+ "hungarumlaut",
+ "hyphen",
+ "hyphen",
+ "hypheninferior",
+ "hyphensuperior",
+ "i",
+ "iacute",
+ "ibreve",
+ "icircumflex",
+ "idieresis",
+ "igrave",
+ "ij",
+ "imacron",
+ "infinity",
+ "integral",
+ "integralbt",
+ "integralex",
+ "integraltp",
+ "intersection",
+ "invbullet",
+ "invcircle",
+ "invsmileface",
+ "iogonek",
+ "iota",
+ "iotadieresis",
+ "iotadieresistonos",
+ "iotatonos",
+ "isuperior",
+ "itilde",
+ "j",
+ "jcircumflex",
+ "k",
+ "kappa",
+ "kcommaaccent",
+ "kgreenlandic",
+ "l",
+ "lacute",
+ "lambda",
+ "lcaron",
+ "lcommaaccent",
+ "ldot",
+ "less",
+ "lessequal",
+ "lfblock",
+ "lira",
+ "ll",
+ "logicaland",
+ "logicalnot",
+ "logicalor",
+ "longs",
+ "lozenge",
+ "lslash",
+ "lsuperior",
+ "ltshade",
+ "m",
+ "macron",
+ "macron",
+ "male",
+ "minus",
+ "minute",
+ "msuperior",
+ "mu",
+ "mu",
+ "multiply",
+ "musicalnote",
+ "musicalnotedbl",
+ "n",
+ "nacute",
+ "napostrophe",
+ "ncaron",
+ "ncommaaccent",
+ "nine",
+ "nineinferior",
+ "nineoldstyle",
+ "ninesuperior",
+ "notelement",
+ "notequal",
+ "notsubset",
+ "nsuperior",
+ "ntilde",
+ "nu",
+ "numbersign",
+ "o",
+ "oacute",
+ "obreve",
+ "ocircumflex",
+ "odieresis",
+ "oe",
+ "ogonek",
+ "ograve",
+ "ohorn",
+ "ohungarumlaut",
+ "omacron",
+ "omega",
+ "omega1",
+ "omegatonos",
+ "omicron",
+ "omicrontonos",
+ "one",
+ "onedotenleader",
+ "oneeighth",
+ "onefitted",
+ "onehalf",
+ "oneinferior",
+ "oneoldstyle",
+ "onequarter",
+ "onesuperior",
+ "onethird",
+ "openbullet",
+ "ordfeminine",
+ "ordmasculine",
+ "orthogonal",
+ "oslash",
+ "oslashacute",
+ "osuperior",
+ "otilde",
+ "p",
+ "paragraph",
+ "parenleft",
+ "parenleftbt",
+ "parenleftex",
+ "parenleftinferior",
+ "parenleftsuperior",
+ "parenlefttp",
+ "parenright",
+ "parenrightbt",
+ "parenrightex",
+ "parenrightinferior",
+ "parenrightsuperior",
+ "parenrighttp",
+ "partialdiff",
+ "percent",
+ "period",
+ "periodcentered",
+ "periodcentered",
+ "periodinferior",
+ "periodsuperior",
+ "perpendicular",
+ "perthousand",
+ "peseta",
+ "phi",
+ "phi1",
+ "pi",
+ "plus",
+ "plusminus",
+ "prescription",
+ "product",
+ "propersubset",
+ "propersuperset",
+ "proportional",
+ "psi",
+ "q",
+ "question",
+ "questiondown",
+ "questiondownsmall",
+ "questionsmall",
+ "quotedbl",
+ "quotedblbase",
+ "quotedblleft",
+ "quotedblright",
+ "quoteleft",
+ "quotereversed",
+ "quoteright",
+ "quotesinglbase",
+ "quotesingle",
+ "r",
+ "racute",
+ "radical",
+ "radicalex",
+ "rcaron",
+ "rcommaaccent",
+ "reflexsubset",
+ "reflexsuperset",
+ "registered",
+ "registersans",
+ "registerserif",
+ "revlogicalnot",
+ "rho",
+ "ring",
+ "rsuperior",
+ "rtblock",
+ "rupiah",
+ "s",
+ "sacute",
+ "scaron",
+ "scedilla",
+ "scedilla",
+ "scircumflex",
+ "scommaaccent",
+ "second",
+ "section",
+ "semicolon",
+ "seven",
+ "seveneighths",
+ "seveninferior",
+ "sevenoldstyle",
+ "sevensuperior",
+ "shade",
+ "sigma",
+ "sigma1",
+ "similar",
+ "six",
+ "sixinferior",
+ "sixoldstyle",
+ "sixsuperior",
+ "slash",
+ "smileface",
+ "space",
+ "space",
+ "spade",
+ "ssuperior",
+ "sterling",
+ "suchthat",
+ "summation",
+ "sun",
+ "t",
+ "tau",
+ "tbar",
+ "tcaron",
+ "tcommaaccent",
+ "tcommaaccent",
+ "therefore",
+ "theta",
+ "theta1",
+ "thorn",
+ "three",
+ "threeeighths",
+ "threeinferior",
+ "threeoldstyle",
+ "threequarters",
+ "threequartersemdash",
+ "threesuperior",
+ "tilde",
+ "tildecomb",
+ "tonos",
+ "trademark",
+ "trademarksans",
+ "trademarkserif",
+ "triagdn",
+ "triaglf",
+ "triagrt",
+ "triagup",
+ "tsuperior",
+ "two",
+ "twodotenleader",
+ "twoinferior",
+ "twooldstyle",
+ "twosuperior",
+ "twothirds",
+ "u",
+ "uacute",
+ "ubreve",
+ "ucircumflex",
+ "udieresis",
+ "ugrave",
+ "uhorn",
+ "uhungarumlaut",
+ "umacron",
+ "underscore",
+ "underscoredbl",
+ "union",
+ "universal",
+ "uogonek",
+ "upblock",
+ "upsilon",
+ "upsilondieresis",
+ "upsilondieresistonos",
+ "upsilontonos",
+ "uring",
+ "utilde",
+ "v",
+ "w",
+ "wacute",
+ "wcircumflex",
+ "wdieresis",
+ "weierstrass",
+ "wgrave",
+ "x",
+ "xi",
+ "y",
+ "yacute",
+ "ycircumflex",
+ "ydieresis",
+ "yen",
+ "ygrave",
+ "z",
+ "zacute",
+ "zcaron",
+ "zdotaccent",
+ "zero",
+ "zeroinferior",
+ "zerooldstyle",
+ "zerosuperior",
+ "zeta"
+ };
+
+ static
+ {
+ for (int k = 0; k < unicode.length; ++k)
+ {
+ Integer num = new Integer(unicode[k]);
+ unicode2names.put(num, names[k]);
+ int code[] = (int[])names2unicode.get(names[k]);
+ if (code == null)
+ {
+ names2unicode.put(names[k], new int[]{unicode[k]});
+ }
+ else
+ {
+ int code2[] = new int[code.length + 1];
+ System.arraycopy(code, 0, code2, 0, code.length);
+ code2[code.length] = unicode[k];
+ names2unicode.put(names[k], code2);
+ }
+ }
+ }
+
+ public static int[] nameToUnicode(String name)
+ {
+ return (int[])names2unicode.get(name);
+ }
+
+ public static String unicodeToName(int num)
+ {
+ return (String)unicode2names.get(new Integer(num));
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/GrayColor.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/GrayColor.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/GrayColor.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/GrayColor.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,64 @@
+/*
+ * $Id: GrayColor.java,v 1.10 2002/06/18 13:59:40 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class GrayColor extends ExtendedColor {
+
+ float gray;
+
+ public GrayColor(int intGray) {
+ this((float)intGray / 255f);
+ }
+
+ public GrayColor(float floatGray) {
+ super(TYPE_GRAY, floatGray, floatGray, floatGray);
+ gray = normalize(floatGray);
+ }
+
+ public float getGray() {
+ return gray;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/HyphenationEvent.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/HyphenationEvent.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/HyphenationEvent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/HyphenationEvent.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/** Called by Chunk
to hyphenate a word.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public interface HyphenationEvent {
+
+ /** Gets the hyphen symbol.
+ * @return the hyphen symbol
+ */
+ public String getHyphenSymbol();
+
+ /** Hyphenates a word and returns the first part of it. To get
+ * the second part of the hyphenated word call getHyphenatedWordPost()
.
+ * @param word the word to hyphenate
+ * @param font the font used by this word
+ * @param fontSize the font size used by this word
+ * @param remainingWidth the width available to fit this word in
+ * @return the first part of the hyphenated word including
+ * the hyphen symbol, if any
+ */
+ public String getHyphenatedWordPre(String word, BaseFont font, float fontSize, float remainingWidth);
+
+ /** Gets the second part of the hyphenated word. Must be called
+ * after getHyphenatedWordPre()
.
+ * @return the second part of the hyphenated word
+ */
+ public String getHyphenatedWordPost();
+}
+
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ICC_Profile.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ICC_Profile.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ICC_Profile.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ICC_Profile.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,25 @@
+package pdftk.com.lowagie.text.pdf;
+
+public class ICC_Profile {
+
+ protected byte data[];
+ protected int numComponents;
+
+ protected ICC_Profile() {
+ }
+
+ public static ICC_Profile getInstance(byte data[], int numComponents) {
+ ICC_Profile icc = new ICC_Profile();
+ icc.data = data;
+ icc.numComponents = numComponents;
+ return icc;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+ public int getNumComponents() {
+ return numComponents;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/IntHashtable.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/IntHashtable.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/IntHashtable.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/IntHashtable.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,475 @@
+/*
+ * This class is based on org.apache.IntHashMap.commons.lang
+ * http://jakarta.apache.org/commons/lang/xref/org/apache/commons/lang/IntHashMap.html
+ * It was adapted by Bruno Lowagie for use in iText,
+ * reusing methods that were written by Paulo Soares.
+ * Instead of being a hashtable that stores objects with an int as key,
+ * it stores int values with an int as key.
+ *
+ * This is the original license of the original class IntHashMap:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Note: originally released under the GNU LGPL v2.1,
+ * but rereleased by the original author under the ASF license (above).
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/***
+ * A hash map that uses primitive ints for the key rather than objects.
+ *
+ * Note that this class is for internal optimization purposes only, and may
+ * not be supported in future releases of Jakarta Commons Lang. Utilities of
+ * this sort may be included in future releases of Jakarta Commons Collections.
+ *
+ * @author Justin Couch
+ * @author Alex Chaffee (alex@apache.org)
+ * @author Stephen Colebourne
+ * @author Bruno Lowagie (change Objects as keys into int values)
+ * @author Paulo Soares (added extra methods)
+ */
+public class IntHashtable implements Cloneable {
+
+ /***
+ * The hash table data.
+ */
+ private transient Entry table[];
+
+ /***
+ * The total number of entries in the hash table.
+ */
+ private transient int count;
+
+ /***
+ * The table is rehashed when its size exceeds this threshold. (The
+ * value of this field is (int)(capacity * loadFactor).)
+ *
+ * @serial
+ */
+ private int threshold;
+
+ /***
+ * The load factor for the hashtable.
+ *
+ * @serial
+ */
+ private float loadFactor;
+
+ /***
+ * Constructs a new, empty hashtable with a default capacity and load
+ * factor, which is 20
and 0.75
respectively.
+ */
+ public IntHashtable() {
+ this(150, 0.75f);
+ }
+
+ /***
+ * Constructs a new, empty hashtable with the specified initial capacity
+ * and default load factor, which is 0.75
.
+ *
+ * @param initialCapacity the initial capacity of the hashtable.
+ * @throws IllegalArgumentException if the initial capacity is less
+ * than zero.
+ */
+ public IntHashtable(int initialCapacity) {
+ this(initialCapacity, 0.75f);
+ }
+
+ /***
+ * Constructs a new, empty hashtable with the specified initial
+ * capacity and the specified load factor.
+ *
+ * @param initialCapacity the initial capacity of the hashtable.
+ * @param loadFactor the load factor of the hashtable.
+ * @throws IllegalArgumentException if the initial capacity is less
+ * than zero, or if the load factor is nonpositive.
+ */
+ public IntHashtable(int initialCapacity, float loadFactor) {
+ super();
+ if (initialCapacity < 0) {
+ throw new IllegalArgumentException("illegal.capacity.1");
+ }
+ if (loadFactor <= 0) {
+ throw new IllegalArgumentException("illegal.load.1");
+ }
+ if (initialCapacity == 0) {
+ initialCapacity = 1;
+ }
+ this.loadFactor = loadFactor;
+ table = new Entry[initialCapacity];
+ threshold = (int) (initialCapacity * loadFactor);
+ }
+
+ /***
+ * Returns the number of keys in this hashtable.
+ *
+ * @return the number of keys in this hashtable.
+ */
+ public int size() {
+ return count;
+ }
+
+ /***
+ * Tests if this hashtable maps no keys to values.
+ *
+ * @return true
if this hashtable maps no keys to values;
+ * false
otherwise.
+ */
+ public boolean isEmpty() {
+ return count == 0;
+ }
+
+ /***
+ * Tests if some key maps into the specified value in this hashtable.
+ * This operation is more expensive than the containsKey
+ * method.
+ *
+ * Note that this method is identical in functionality to containsValue,
+ * (which is part of the Map interface in the collections framework).
+ *
+ * @param value a value to search for.
+ * @return true
if and only if some key maps to the
+ * value
argument in this hashtable as
+ * determined by the equals method;
+ * false
otherwise.
+ * @throws NullPointerException if the value is null
.
+ * @see #containsKey(int)
+ * @see #containsValue(int)
+ * @see java.util.Map
+ */
+ public boolean contains(int value) {
+
+ Entry tab[] = table;
+ for (int i = tab.length; i-- > 0;) {
+ for (Entry e = tab[i]; e != null; e = e.next) {
+ if (e.value == value) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /***
+ * Returns true
if this HashMap maps one or more keys
+ * to this value.
+ *
+ * Note that this method is identical in functionality to contains
+ * (which predates the Map interface).
+ *
+ * @param value value whose presence in this HashMap is to be tested.
+ * @return boolean true
if the value is contained
+ * @see java.util.Map
+ * @since JDK1.2
+ */
+ public boolean containsValue(int value) {
+ return contains(value);
+ }
+
+ /***
+ * Tests if the specified int is a key in this hashtable.
+ *
+ * @param key possible key.
+ * @return true
if and only if the specified int is a
+ * key in this hashtable, as determined by the equals
+ * method; false
otherwise.
+ * @see #contains(int)
+ */
+ public boolean containsKey(int key) {
+ Entry tab[] = table;
+ int hash = key;
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+ for (Entry e = tab[index]; e != null; e = e.next) {
+ if (e.hash == hash && e.key == key) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /***
+ * Returns the value to which the specified key is mapped in this map.
+ *
+ * @param key a key in the hashtable.
+ * @return the value to which the key is mapped in this hashtable;
+ * null
if the key is not mapped to any value in
+ * this hashtable.
+ * @see #put(int, int)
+ */
+ public int get(int key) {
+ Entry tab[] = table;
+ int hash = key;
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+ for (Entry e = tab[index]; e != null; e = e.next) {
+ if (e.hash == hash && e.key == key) {
+ return e.value;
+ }
+ }
+ return 0;
+ }
+
+ /***
+ * Increases the capacity of and internally reorganizes this
+ * hashtable, in order to accommodate and access its entries more
+ * efficiently.
+ *
+ * This method is called automatically when the number of keys
+ * in the hashtable exceeds this hashtable's capacity and load
+ * factor.
+ */
+ protected void rehash() {
+ int oldCapacity = table.length;
+ Entry oldMap[] = table;
+
+ int newCapacity = oldCapacity * 2 + 1;
+ Entry newMap[] = new Entry[newCapacity];
+
+ threshold = (int) (newCapacity * loadFactor);
+ table = newMap;
+
+ for (int i = oldCapacity; i-- > 0;) {
+ for (Entry old = oldMap[i]; old != null;) {
+ Entry e = old;
+ old = old.next;
+
+ int index = (e.hash & 0x7FFFFFFF) % newCapacity;
+ e.next = newMap[index];
+ newMap[index] = e;
+ }
+ }
+ }
+
+ /***
+ * Maps the specified key
to the specified
+ * value
in this hashtable. The key cannot be
+ * null
.
+ *
+ * The value can be retrieved by calling the get
method
+ * with a key that is equal to the original key.
+ *
+ * @param key the hashtable key.
+ * @param value the value.
+ * @return the previous value of the specified key in this hashtable,
+ * or null
if it did not have one.
+ * @throws NullPointerException if the key is null
.
+ * @see #get(int)
+ */
+ public int put(int key, int value) {
+ // Makes sure the key is not already in the hashtable.
+ Entry tab[] = table;
+ int hash = key;
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+ for (Entry e = tab[index]; e != null; e = e.next) {
+ if (e.hash == hash && e.key == key) {
+ int old = e.value;
+ e.value = value;
+ return old;
+ }
+ }
+
+ if (count >= threshold) {
+ // Rehash the table if the threshold is exceeded
+ rehash();
+
+ tab = table;
+ index = (hash & 0x7FFFFFFF) % tab.length;
+ }
+
+ // Creates the new entry.
+ Entry e = new Entry(hash, key, value, tab[index]);
+ tab[index] = e;
+ count++;
+ return 0;
+ }
+
+ /***
+ * Removes the key (and its corresponding value) from this
+ * hashtable.
+ *
+ * This method does nothing if the key is not present in the
+ * hashtable.
+ *
+ * @param key the key that needs to be removed.
+ * @return the value to which the key had been mapped in this hashtable,
+ * or null
if the key did not have a mapping.
+ */
+ public int remove(int key) {
+ Entry tab[] = table;
+ int hash = key;
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+ for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) {
+ if (e.hash == hash && e.key == key) {
+ if (prev != null) {
+ prev.next = e.next;
+ } else {
+ tab[index] = e.next;
+ }
+ count--;
+ int oldValue = e.value;
+ e.value = 0;
+ return oldValue;
+ }
+ }
+ return 0;
+ }
+
+ /***
+ * Clears this hashtable so that it contains no keys.
+ */
+ public void clear() {
+ Entry tab[] = table;
+ for (int index = tab.length; --index >= 0;) {
+ tab[index] = null;
+ }
+ count = 0;
+ }
+
+ /***
+ * Innerclass that acts as a datastructure to create a new entry in the
+ * table.
+ */
+ static class Entry {
+ int hash;
+ int key;
+ int value;
+ Entry next;
+
+ /***
+ * Create a new entry with the given values.
+ *
+ * @param hash The code used to hash the int with
+ * @param key The key used to enter this in the table
+ * @param value The value for this key
+ * @param next A reference to the next entry in the table
+ */
+ protected Entry(int hash, int key, int value, Entry next) {
+ this.hash = hash;
+ this.key = key;
+ this.value = value;
+ this.next = next;
+ }
+
+ // extra methods for inner class Entry by Paulo
+ public int getKey() {
+ return key;
+ }
+ public int getValue() {
+ return value;
+ }
+ protected Object clone() {
+ Entry entry = new Entry(hash, key, value, (next != null) ? (Entry)next.clone() : null);
+ return entry;
+ }
+ }
+
+ // extra inner class by Paulo
+ static class IntHashtableIterator implements Iterator {
+ int index;
+ Entry table[];
+ Entry entry;
+
+ IntHashtableIterator(Entry table[]) {
+ this.table = table;
+ this.index = table.length;
+ }
+ public boolean hasNext() {
+ if (entry != null) {
+ return true;
+ }
+ while (index-- > 0) {
+ if ((entry = table[index]) != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Object next() {
+ if (entry == null) {
+ while ((index-- > 0) && ((entry = table[index]) == null));
+ }
+ if (entry != null) {
+ Entry e = entry;
+ entry = e.next;
+ return e;
+ }
+ throw new NoSuchElementException("inthashtableiterator");
+ }
+ public void remove() {
+ throw new UnsupportedOperationException("remove.not.supported");
+ }
+ }
+
+// extra methods by Paulo Soares:
+
+ public Iterator getEntryIterator() {
+ return new IntHashtableIterator(table);
+ }
+
+ public int[] toOrderedKeys() {
+ int res[] = getKeys();
+ Arrays.sort(res);
+ return res;
+ }
+
+ public int[] getKeys() {
+ int res[] = new int[count];
+ int ptr = 0;
+ int index = table.length;
+ Entry entry = null;
+ while (true) {
+ if (entry == null)
+ while ((index-- > 0) && ((entry = table[index]) == null));
+ if (entry == null)
+ break;
+ Entry e = entry;
+ entry = e.next;
+ res[ptr++] = e.key;
+ }
+ return res;
+ }
+
+ public int getOneKey() {
+ if (count == 0)
+ return 0;
+ int index = table.length;
+ Entry entry = null;
+ while ((index-- > 0) && ((entry = table[index]) == null));
+ if (entry == null)
+ return 0;
+ return entry.key;
+ }
+
+ public Object clone() {
+ try {
+ IntHashtable t = (IntHashtable)super.clone();
+ t.table = new Entry[table.length];
+ for (int i = table.length ; i-- > 0 ; ) {
+ t.table[i] = (table[i] != null)
+ ? (Entry)table[i].clone() : null;
+ }
+ return t;
+ } catch (CloneNotSupportedException e) {
+ // this shouldn't happen, since we are Cloneable
+ throw new InternalError();
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/OutputStreamCounter.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/OutputStreamCounter.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/OutputStreamCounter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/OutputStreamCounter.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ *
+ * @author psoares
+ */
+public class OutputStreamCounter extends OutputStream {
+
+ protected OutputStream out;
+ protected int counter = 0;
+
+ /** Creates a new instance of OutputStreamCounter */
+ public OutputStreamCounter(OutputStream out) {
+ this.out = out;
+ }
+
+ /** Closes this output stream and releases any system resources
+ * associated with this stream. The general contract of close
+ * is that it closes the output stream. A closed stream cannot perform
+ * output operations and cannot be reopened.
+ *
+ * The close
method of OutputStream
does nothing.
+ *
+ * @exception IOException if an I/O error occurs.
+ *
+ */
+ public void close() throws IOException {
+ out.close();
+ }
+
+ /** Flushes this output stream and forces any buffered output bytes
+ * to be written out. The general contract of flush
is
+ * that calling it is an indication that, if any bytes previously
+ * written have been buffered by the implementation of the output
+ * stream, such bytes should immediately be written to their
+ * intended destination.
+ *
+ * The flush
method of OutputStream
does nothing.
+ *
+ * @exception IOException if an I/O error occurs.
+ *
+ */
+ public void flush() throws IOException {
+ out.flush();
+ }
+
+ /** Writes b.length
bytes from the specified byte array
+ * to this output stream. The general contract for write(b)
+ * is that it should have exactly the same effect as the call
+ * write(b, 0, b.length)
.
+ *
+ * @param b the data.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.OutputStream#write(byte[], int, int)
+ *
+ */
+ public void write(byte[] b) throws IOException {
+ counter += b.length;
+ out.write(b);
+ }
+
+ /** Writes the specified byte to this output stream. The general
+ * contract for write
is that one byte is written
+ * to the output stream. The byte to be written is the eight
+ * low-order bits of the argument b
. The 24
+ * high-order bits of b
are ignored.
+ *
+ * Subclasses of OutputStream
must provide an
+ * implementation for this method.
+ *
+ * @param b the byte
.
+ * @exception IOException if an I/O error occurs. In particular,
+ * an IOException
may be thrown if the
+ * output stream has been closed.
+ *
+ */
+ public void write(int b) throws IOException {
+ ++counter;
+ out.write(b);
+ }
+
+ /** Writes len
bytes from the specified byte array
+ * starting at offset off
to this output stream.
+ * The general contract for write(b, off, len)
is that
+ * some of the bytes in the array b
are written to the
+ * output stream in order; element b[off]
is the first
+ * byte written and b[off+len-1]
is the last byte written
+ * by this operation.
+ *
+ * The write
method of OutputStream
calls
+ * the write method of one argument on each of the bytes to be
+ * written out. Subclasses are encouraged to override this method and
+ * provide a more efficient implementation.
+ *
+ * If b
is null
, a
+ * NullPointerException
is thrown.
+ *
+ * If off
is negative, or len
is negative, or
+ * off+len
is greater than the length of the array
+ * b
, then an IndexOutOfBoundsException is thrown.
+ *
+ * @param b the data.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
+ * @exception IOException if an I/O error occurs. In particular,
+ * an IOException
is thrown if the output
+ * stream is closed.
+ *
+ */
+ public void write(byte[] b, int off, int len) throws IOException {
+ counter += len;
+ out.write(b, off, len);
+ }
+
+ public int getCounter() {
+ return counter;
+ }
+
+ public void resetCounter() {
+ counter = 0;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/OutputStreamEncryption.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/OutputStreamEncryption.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/OutputStreamEncryption.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/OutputStreamEncryption.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,208 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+import pdftk.com.lowagie.text.ExceptionConverter;
+import pdftk.com.lowagie.text.pdf.crypto.AESCipher;
+import pdftk.com.lowagie.text.pdf.crypto.IVGenerator;
+import pdftk.com.lowagie.text.pdf.crypto.ARCFOUREncryption;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class OutputStreamEncryption extends OutputStream {
+
+ protected OutputStream out;
+ protected ARCFOUREncryption arcfour;
+ protected AESCipher cipher;
+ private byte[] sb = new byte[1];
+ private static final int AES_128 = 4;
+ private boolean aes;
+ private boolean finished;
+
+ /** Creates a new instance of OutputStreamCounter */
+ public OutputStreamEncryption(OutputStream out, byte key[], int off, int len, int revision) {
+ try {
+ this.out = out;
+ aes = revision == AES_128;
+ if (aes) {
+ byte[] iv = IVGenerator.getIV();
+ byte[] nkey = new byte[len];
+ System.arraycopy(key, off, nkey, 0, len);
+ cipher = new AESCipher(true, nkey, iv);
+ write(iv);
+ }
+ else {
+ arcfour = new ARCFOUREncryption();
+ arcfour.prepareARCFOURKey(key, off, len);
+ }
+ } catch (Exception ex) {
+ throw new ExceptionConverter(ex);
+ }
+ }
+
+ public OutputStreamEncryption(OutputStream out, byte key[], int revision) {
+ this(out, key, 0, key.length, revision);
+ }
+
+ /** Closes this output stream and releases any system resources
+ * associated with this stream. The general contract of close
+ * is that it closes the output stream. A closed stream cannot perform
+ * output operations and cannot be reopened.
+ *
+ * The close
method of OutputStream
does nothing.
+ *
+ * @exception IOException if an I/O error occurs.
+ *
+ */
+ public void close() throws IOException {
+ finish();
+ out.close();
+ }
+
+ /** Flushes this output stream and forces any buffered output bytes
+ * to be written out. The general contract of flush
is
+ * that calling it is an indication that, if any bytes previously
+ * written have been buffered by the implementation of the output
+ * stream, such bytes should immediately be written to their
+ * intended destination.
+ *
+ * The flush
method of OutputStream
does nothing.
+ *
+ * @exception IOException if an I/O error occurs.
+ *
+ */
+ public void flush() throws IOException {
+ out.flush();
+ }
+
+ /** Writes b.length
bytes from the specified byte array
+ * to this output stream. The general contract for write(b)
+ * is that it should have exactly the same effect as the call
+ * write(b, 0, b.length)
.
+ *
+ * @param b the data.
+ * @exception IOException if an I/O error occurs.
+ * @see java.io.OutputStream#write(byte[], int, int)
+ *
+ */
+ public void write(byte[] b) throws IOException {
+ write(b, 0, b.length);
+ }
+
+ /** Writes the specified byte to this output stream. The general
+ * contract for write
is that one byte is written
+ * to the output stream. The byte to be written is the eight
+ * low-order bits of the argument b
. The 24
+ * high-order bits of b
are ignored.
+ *
+ * Subclasses of OutputStream
must provide an
+ * implementation for this method.
+ *
+ * @param b the byte
.
+ * @exception IOException if an I/O error occurs. In particular,
+ * an IOException
may be thrown if the
+ * output stream has been closed.
+ *
+ */
+ public void write(int b) throws IOException {
+ sb[0] = (byte)b;
+ write(sb, 0, 1);
+ }
+
+ /** Writes len
bytes from the specified byte array
+ * starting at offset off
to this output stream.
+ * The general contract for write(b, off, len)
is that
+ * some of the bytes in the array b
are written to the
+ * output stream in order; element b[off]
is the first
+ * byte written and b[off+len-1]
is the last byte written
+ * by this operation.
+ *
+ * The write
method of OutputStream
calls
+ * the write method of one argument on each of the bytes to be
+ * written out. Subclasses are encouraged to override this method and
+ * provide a more efficient implementation.
+ *
+ * If b
is null
, a
+ * NullPointerException
is thrown.
+ *
+ * If off
is negative, or len
is negative, or
+ * off+len
is greater than the length of the array
+ * b
, then an IndexOutOfBoundsException is thrown.
+ *
+ * @param b the data.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
+ * @exception IOException if an I/O error occurs. In particular,
+ * an IOException
is thrown if the output
+ * stream is closed.
+ *
+ */
+ public void write(byte[] b, int off, int len) throws IOException {
+ if (aes) {
+ byte[] b2 = cipher.update(b, off, len);
+ if (b2 == null || b2.length == 0)
+ return;
+ out.write(b2, 0, b2.length);
+ }
+ else {
+ byte[] b2 = new byte[Math.min(len, 4192)];
+ while (len > 0) {
+ int sz = Math.min(len, b2.length);
+ arcfour.encryptARCFOUR(b, off, sz, b2, 0);
+ out.write(b2, 0, sz);
+ len -= sz;
+ off += sz;
+ }
+ }
+ }
+
+ public void finish() throws IOException {
+ if (!finished) {
+ finished = true;
+ if (aes) {
+ byte[] b;
+ try {
+ b = cipher.doFinal();
+ } catch (Exception ex) {
+ throw new ExceptionConverter(ex);
+ }
+ out.write(b, 0, b.length);
+ }
+ }
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PRAcroForm.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PRAcroForm.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PRAcroForm.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PRAcroForm.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,200 @@
+/*
+ * $Id: PRAcroForm.java,v 1.11 2003/05/02 09:01:12 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * This class written by Mark Thompson, Copyright (C) 2002 by Mark Thompson.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.HashMap;
+
+/**
+ * This class captures an AcroForm on input. Basically, it extends Dictionary
+ * by indexing the fields of an AcroForm
+ * @author Mark Thompson
+ */
+
+public class PRAcroForm extends PdfDictionary {
+
+ /**
+ * This class holds the information for a single field
+ */
+ public static class FieldInformation {
+ String name;
+ PdfDictionary info;
+ PRIndirectReference ref;
+
+ FieldInformation(String name, PdfDictionary info, PRIndirectReference ref) {
+ this.name = name; this.info = info; this.ref = ref;
+ }
+ public String getName() { return name; }
+ public PdfDictionary getInfo() { return info; }
+ public PRIndirectReference getRef() { return ref; }
+ };
+ ArrayList fields;
+ ArrayList stack;
+ HashMap fieldByName;
+ PdfReader reader;
+
+ /**
+ * Constructor
+ * @param reader reader of the input file
+ */
+ public PRAcroForm(PdfReader reader) {
+ this.reader = reader;
+ fields = new ArrayList();
+ fieldByName = new HashMap();
+ stack = new ArrayList();
+ }
+ /**
+ * Number of fields found
+ * @return size
+ */
+ public int size() {
+ return fields.size();
+ }
+
+ public ArrayList getFields() {
+ return fields;
+ }
+
+ public FieldInformation getField(String name) {
+ return (FieldInformation)fieldByName.get(name);
+ }
+
+ /**
+ * Given the title (/T) of a reference, return the associated reference
+ * @param name a string containing the path
+ * @return a reference to the field, or null
+ */
+ public PRIndirectReference getRefByName(String name) {
+ FieldInformation fi = (FieldInformation)fieldByName.get(name);
+ if (fi == null) return null;
+ return fi.getRef();
+ }
+ /**
+ * Read, and comprehend the acroform
+ * @param root the docment root
+ */
+ public void readAcroForm(PdfDictionary root) {
+ hashMap = root.hashMap;
+ pushAttrib(root);
+ PdfArray fieldlist = (PdfArray)PdfReader.getPdfObjectRelease(root.get(PdfName.FIELDS));
+ iterateFields(fieldlist, null, null);
+ }
+
+ /**
+ * After reading, we index all of the fields. Recursive.
+ * @param fieldlist An array of fields
+ * @param fieldDict the last field dictionary we encountered (recursively)
+ * @param title the pathname of the field, up to this point or null
+ */
+ protected void iterateFields(PdfArray fieldlist, PRIndirectReference fieldDict, String title) {
+ for (Iterator it = fieldlist.getArrayList().iterator(); it.hasNext();) {
+ PRIndirectReference ref = (PRIndirectReference)it.next();
+ PdfDictionary dict = (PdfDictionary) PdfReader.getPdfObjectRelease(ref);
+
+ // if we are not a field dictionary, pass our parent's values
+ PRIndirectReference myFieldDict = fieldDict;
+ String myTitle = title;
+ PdfString tField = (PdfString)dict.get(PdfName.T);
+ boolean isFieldDict = tField != null;
+
+ if (isFieldDict) {
+ myFieldDict = ref;
+ if (title == null) myTitle = tField.toString();
+ else myTitle = title + '.' + tField.toString();
+ }
+
+ PdfArray kids = (PdfArray)dict.get(PdfName.KIDS);
+ if (kids != null) {
+ pushAttrib(dict);
+ iterateFields(kids, myFieldDict, myTitle);
+ stack.remove(stack.size() - 1); // pop
+ }
+ else { // leaf node
+ if (myFieldDict != null) {
+ PdfDictionary mergedDict = (PdfDictionary)stack.get(stack.size() - 1);
+ if (isFieldDict)
+ mergedDict = mergeAttrib(mergedDict, dict);
+
+ mergedDict.put(PdfName.T, new PdfString(myTitle));
+ FieldInformation fi = new FieldInformation(myTitle, mergedDict, myFieldDict);
+ fields.add(fi);
+ fieldByName.put(myTitle, fi);
+ }
+ }
+ }
+ }
+ /**
+ * merge field attributes from two dictionaries
+ * @param parent one dictionary
+ * @param child the other dictionary
+ * @return a merged dictionary
+ */
+ protected PdfDictionary mergeAttrib(PdfDictionary parent, PdfDictionary child) {
+ PdfDictionary targ = new PdfDictionary();
+ if (parent != null) targ.putAll(parent);
+
+ for (Iterator it = child.getKeys().iterator(); it.hasNext();) {
+ PdfName key = (PdfName) it.next();
+ if (key.equals(PdfName.DR) || key.equals(PdfName.DA) ||
+ key.equals(PdfName.Q) || key.equals(PdfName.FF) ||
+ key.equals(PdfName.DV) || key.equals(PdfName.V)
+ || key.equals(PdfName.FT)
+ || key.equals(PdfName.F)) {
+ targ.put(key,child.get(key));
+ }
+ }
+ return targ;
+ }
+ /**
+ * stack a level of dictionary. Merge in a dictionary from this level
+ */
+ protected void pushAttrib(PdfDictionary dict) {
+ PdfDictionary dic = null;
+ if (stack.size() != 0) {
+ dic = (PdfDictionary)stack.get(stack.size() - 1);
+ }
+ dic = mergeAttrib(dic, dict);
+ stack.add(dic);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PRIndirectReference.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PRIndirectReference.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PRIndirectReference.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PRIndirectReference.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,93 @@
+/*
+ * $Id: PRIndirectReference.java,v 1.12 2002/07/09 11:28:22 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import java.io.OutputStream;
+import java.io.IOException;
+
+public class PRIndirectReference extends PdfIndirectReference {
+
+ protected PdfReader reader;
+ // membervariables
+
+ // constructors
+
+/**
+ * Constructs a PdfIndirectReference
.
+ *
+ * @param reader a PdfReader
+ * @param number the object number.
+ * @param generation the generation number.
+ */
+
+ PRIndirectReference(PdfReader reader, int number, int generation) {
+ type = INDIRECT;
+ this.number = number;
+ this.generation = generation;
+ this.reader = reader;
+ }
+
+/**
+ * Constructs a PdfIndirectReference
.
+ *
+ * @param reader a PdfReader
+ * @param number the object number.
+ */
+
+ PRIndirectReference(PdfReader reader, int number) {
+ this(reader, number, 0);
+ }
+
+ // methods
+
+ public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+ int n = writer.getNewObjectNumber(reader, number, generation);
+ os.write(PdfEncodings.convertToBytes(new StringBuffer().append(n).append(" 0 R").toString(), null));
+ }
+
+ public PdfReader getReader() {
+ return reader;
+ }
+
+ public void setNumber(int number, int generation) {
+ this.number = number;
+ this.generation = generation;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PRStream.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PRStream.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PRStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PRStream.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,272 @@
+/*
+ * $Id: PRStream.java,v 1.12 2002/06/20 13:30:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import java.util.ArrayList; // ssteward
+
+import pdftk.com.lowagie.text.Document;
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+public class PRStream extends PdfStream {
+
+ protected PdfReader reader;
+ protected int offset;
+ protected int length;
+
+ //added by ujihara for decryption
+ protected int objNum = 0;
+ protected int objGen = 0;
+
+ public PRStream(PRStream stream, PdfDictionary newDic) {
+ reader = stream.reader;
+ offset = stream.offset;
+ length = stream.length;
+ compressed = stream.compressed;
+ compressionLevel = stream.compressionLevel;
+ streamBytes = stream.streamBytes;
+ bytes = stream.bytes;
+ objNum = stream.objNum;
+ objGen = stream.objGen;
+ if (newDic != null)
+ putAll(newDic);
+ else
+ hashMap.putAll(stream.hashMap);
+ }
+
+ public PRStream(PRStream stream, PdfDictionary newDic, PdfReader reader) {
+ this(stream, newDic);
+ this.reader = reader;
+ }
+
+ public PRStream(PdfReader reader, int offset) {
+ this.reader = reader;
+ this.offset = offset;
+ }
+
+ public PRStream(PdfReader reader, byte conts[]) {
+ this(reader, conts, DEFAULT_COMPRESSION);
+ }
+
+ /**
+ * Creates a new PDF stream object that will replace a stream
+ * in a existing PDF file.
+ * @param reader the reader that holds the existing PDF
+ * @param conts the new content
+ * @param compressionLevel the compression level for the content
+ * @since 2.1.3 (replacing the existing constructor without param compressionLevel)
+ */
+ public PRStream(PdfReader reader, byte[] conts, int compressionLevel) {
+ this.reader = reader;
+ this.offset = -1;
+ if (Document.compress) {
+ try {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ Deflater deflater = new Deflater(compressionLevel);
+ DeflaterOutputStream zip = new DeflaterOutputStream(stream, deflater);
+ zip.write(conts);
+ zip.close();
+ deflater.end();
+ bytes = stream.toByteArray();
+ }
+ catch (IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ put(PdfName.FILTER, PdfName.FLATEDECODE);
+ }
+ else
+ bytes = conts;
+ setLength(bytes.length);
+ }
+
+ /**
+ * Sets the data associated with the stream, either compressed or
+ * uncompressed. Note that the data will never be compressed if
+ * Document.compress is set to false.
+ *
+ * @param data raw data, decrypted and uncompressed.
+ * @param compress true if you want the stream to be compressed.
+ * @since iText 2.1.1
+ */
+ public void setData(byte[] data, boolean compress) {
+ setData(data, compress, DEFAULT_COMPRESSION);
+ }
+
+ /**
+ * Sets the data associated with the stream, either compressed or
+ * uncompressed. Note that the data will never be compressed if
+ * Document.compress is set to false.
+ *
+ * @param data raw data, decrypted and uncompressed.
+ * @param compress true if you want the stream to be compressed.
+ * @param compressionLevel a value between -1 and 9 (ignored if compress == false)
+ * @since iText 2.1.3
+ */
+ public void setData(byte[] data, boolean compress, int compressionLevel) {
+ remove(PdfName.FILTER);
+ remove(PdfName.DECODEPARMS); // ssteward, pdftk 1.46
+ this.offset = -1;
+ if (Document.compress && compress) {
+ try {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ Deflater deflater = new Deflater(compressionLevel);
+ DeflaterOutputStream zip = new DeflaterOutputStream(stream, deflater);
+ zip.write(data);
+ zip.close();
+ deflater.end();
+ bytes = stream.toByteArray();
+ this.compressionLevel = compressionLevel;
+ }
+ catch (IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ put(PdfName.FILTER, PdfName.FLATEDECODE);
+ }
+ else
+ bytes = data;
+ setLength(bytes.length);
+ }
+
+ /**Sets the data associated with the stream
+ * @param data raw data, decrypted and uncompressed.
+ */
+ public void setData(byte[] data) {
+ setData(data, true);
+ }
+
+ public void setLength(int length) {
+ this.length = length;
+ put(PdfName.LENGTH, new PdfNumber(length));
+ }
+
+ public int getOffset() {
+ return offset;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ public PdfReader getReader() {
+ return reader;
+ }
+
+ public byte[] getBytes() {
+ return bytes;
+ }
+
+ public void setObjNum(int objNum, int objGen) {
+ this.objNum = objNum;
+ this.objGen = objGen;
+ }
+
+ int getObjNum() {
+ return objNum;
+ }
+
+ int getObjGen() {
+ return objGen;
+ }
+
+ // ssteward: added code to perform uncompression (filtering) or compression of streams
+ public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+
+ // 4.2.0
+ byte[] b= new byte[0];
+ if( ( writer.filterStreams || writer.compressStreams ) && filtersAreKnown() ) { // ssteward
+ setData( PdfReader.getStreamBytes( this ), // apply filters to yield clear text
+ writer.compressStreams, DEFAULT_COMPRESSION );
+ b= bytes;
+ }
+ else { // use temp
+ b= PdfReader.getStreamBytesRaw( this );
+ }
+ PdfEncryption crypto = null;
+ if (writer != null)
+ crypto = writer.getEncryption();
+ PdfObject objLen = get(PdfName.LENGTH);
+ int nn = b.length;
+ if (crypto != null)
+ nn = crypto.calculateStreamSize(nn);
+ put(PdfName.LENGTH, new PdfNumber(nn));
+ superToPdf(writer, os);
+ put(PdfName.LENGTH, objLen);
+ os.write(STARTSTREAM);
+ if (length > 0) {
+ if (crypto != null && !crypto.isEmbeddedFilesOnly())
+ b = crypto.encryptByteArray(b);
+ os.write(b);
+ }
+ os.write(ENDSTREAM);
+ }
+
+ // ssteward
+ // do we know how to apply all of the stream filters?
+ public boolean filtersAreKnown() {
+ boolean retVal= true;
+
+ PdfObject filter = reader.getPdfObjectRelease(get(PdfName.FILTER));
+ ArrayList filters = new ArrayList();
+ if (filter != null) {
+ if (filter.isName())
+ filters.add(filter);
+ else if (filter.isArray())
+ filters = ((PdfArray)filter).getArrayList();
+ }
+
+ String name;
+ for (int j = 0; j < filters.size(); ++j) {
+ name = ((PdfName)reader.getPdfObjectRelease((PdfObject)filters.get(j))).toString();
+ retVal = retVal &&
+ ( (name.equals("/FlateDecode") || name.equals("/Fl")) ||
+ (name.equals("/ASCIIHexDecode") || name.equals("/AHx")) ||
+ (name.equals("/ASCII85Decode") || name.equals("/A85")) ||
+ (name.equals("/LZWDecode")) );
+ }
+
+ return retVal;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PRTokeniser.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PRTokeniser.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PRTokeniser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PRTokeniser.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,593 @@
+/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * $Id: PRTokeniser.java,v 1.15 2002/06/20 13:30:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+import pdftk.com.lowagie.text.exceptions.InvalidPdfException;
+/**
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PRTokeniser {
+
+ public static final int TK_NUMBER = 1;
+ public static final int TK_STRING = 2;
+ public static final int TK_NAME = 3;
+ public static final int TK_COMMENT = 4;
+ public static final int TK_START_ARRAY = 5;
+ public static final int TK_END_ARRAY = 6;
+ public static final int TK_START_DIC = 7;
+ public static final int TK_END_DIC = 8;
+ public static final int TK_REF = 9;
+ public static final int TK_OTHER = 10;
+ public static final int TK_ENDOFFILE = 11;
+ public static final boolean delims[] = {
+ true, true, false, false, false, false, false, false, false, false,
+ true, true, false, true, true, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, true, false, false, false, false, true, false,
+ false, true, true, false, false, false, false, false, true, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, true, false, true, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, true, false, true, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false};
+
+ static final String EMPTY = "";
+
+
+ protected RandomAccessFileOrArray file;
+ protected int type;
+ protected String stringValue;
+ protected int reference;
+ protected int generation;
+ protected boolean hexString;
+
+ public PRTokeniser(String filename) throws IOException {
+ file = new RandomAccessFileOrArray(filename);
+ }
+
+ public PRTokeniser(byte pdfIn[]) {
+ file = new RandomAccessFileOrArray(pdfIn);
+ }
+
+ public PRTokeniser(RandomAccessFileOrArray file) {
+ this.file = file;
+ }
+
+ public void seek(int pos) throws IOException {
+ file.seek(pos);
+ }
+
+ public int getFilePointer() throws IOException {
+ return file.getFilePointer();
+ }
+
+ public void close() throws IOException {
+ file.close();
+ }
+
+ public int length() throws IOException {
+ return file.length();
+ }
+
+ public int read() throws IOException {
+ return file.read();
+ }
+
+ public RandomAccessFileOrArray getSafeFile() {
+ return new RandomAccessFileOrArray(file);
+ }
+
+ public RandomAccessFileOrArray getFile() {
+ return file;
+ }
+
+ public String readString(int size) throws IOException {
+ StringBuffer buf = new StringBuffer();
+ int ch;
+ while ((size--) > 0) {
+ ch = file.read();
+ if (ch == -1)
+ break;
+ buf.append((char)ch);
+ }
+ return buf.toString();
+ }
+
+ public static final boolean isWhitespace(int ch) {
+ return (ch == 0 || ch == 9 || ch == 10 || ch == 12 || ch == 13 || ch == 32);
+ }
+
+ public static final boolean isDelimiter(int ch) {
+ return (ch == '(' || ch == ')' || ch == '<' || ch == '>' || ch == '[' || ch == ']' || ch == '/' || ch == '%');
+ }
+
+ public static final boolean isDelimiterWhitespace(int ch) {
+ return delims[ch + 1];
+ }
+
+ public int getTokenType() {
+ return type;
+ }
+
+ public String getStringValue() {
+ return stringValue;
+ }
+
+ public int getReference() {
+ return reference;
+ }
+
+ public int getGeneration() {
+ return generation;
+ }
+
+ public void backOnePosition(int ch) {
+ if (ch != -1)
+ file.pushBack((byte)ch);
+ }
+
+ public void throwError(String error) throws IOException {
+ throw new InvalidPdfException(error + " at file pointer " + file.getFilePointer());
+ }
+
+ public char checkPdfHeader() throws IOException {
+ file.setStartOffset(0);
+ String str = readString(1024);
+ int idx = str.indexOf("%PDF-");
+ if (idx < 0)
+ throw new InvalidPdfException("PDF header signature not found.");
+ file.setStartOffset(idx);
+ return str.charAt(idx + 7);
+ }
+
+ public void checkFdfHeader() throws IOException {
+ file.setStartOffset(0);
+ String str = readString(1024);
+ int idx = str.indexOf("%FDF-1.2");
+ if (idx < 0)
+ throw new InvalidPdfException("FDF header signature not found.");
+ file.setStartOffset(idx);
+ }
+
+ public int getStartxref() throws IOException {
+ int size = Math.min(1024, file.length());
+ int pos = file.length() - size;
+ file.seek(pos);
+ String str = readString(1024);
+ int idx = str.lastIndexOf("startxref");
+ if (idx < 0)
+ throw new InvalidPdfException("PDF startxref not found.");
+ return pos + idx;
+ }
+
+ public static int getHex(int v) {
+ if (v >= '0' && v <= '9')
+ return v - '0';
+ if (v >= 'A' && v <= 'F')
+ return v - 'A' + 10;
+ if (v >= 'a' && v <= 'f')
+ return v - 'a' + 10;
+ return -1;
+ }
+
+ public void nextValidToken() throws IOException {
+ int level = 0;
+ String n1 = null;
+ String n2 = null;
+ int ptr = 0;
+ while (nextToken()) {
+ if (type == TK_COMMENT)
+ continue;
+ switch (level) {
+ case 0:
+ {
+ if (type != TK_NUMBER)
+ return;
+ ptr = file.getFilePointer();
+ n1 = stringValue;
+ ++level;
+ break;
+ }
+ case 1:
+ {
+ if (type != TK_NUMBER) {
+ file.seek(ptr);
+ type = TK_NUMBER;
+ stringValue = n1;
+ return;
+ }
+ n2 = stringValue;
+ ++level;
+ break;
+ }
+ default:
+ {
+ if (type != TK_OTHER || !stringValue.equals("R")) {
+ file.seek(ptr);
+ type = TK_NUMBER;
+ stringValue = n1;
+ return;
+ }
+ type = TK_REF;
+ reference = Integer.parseInt(n1);
+ generation = Integer.parseInt(n2);
+ return;
+ }
+ }
+ }
+ // http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=687669#20
+ if (level > 0) {
+ type = TK_NUMBER;
+ file.seek(ptr);
+ stringValue = n1;
+ return;
+ }
+ throwError("Unexpected end of file");
+ }
+
+ public boolean nextToken() throws IOException {
+ int ch = 0;
+ do {
+ ch = file.read();
+ } while (ch != -1 && isWhitespace(ch));
+ if (ch == -1){
+ type = TK_ENDOFFILE;
+ return false;
+ }
+
+ // Note: We have to initialize stringValue here, after we've looked for the end of the stream,
+ // to ensure that we don't lose the value of a token that might end exactly at the end
+ // of the stream
+ StringBuffer outBuf = null;
+ stringValue = EMPTY;
+
+ switch (ch) {
+ case '[':
+ type = TK_START_ARRAY;
+ break;
+ case ']':
+ type = TK_END_ARRAY;
+ break;
+ case '/':
+ {
+ outBuf = new StringBuffer();
+ type = TK_NAME;
+ while (true) {
+ ch = file.read();
+ if (delims[ch + 1])
+ break;
+ if (ch == '#') {
+ ch = (getHex(file.read()) << 4) + getHex(file.read());
+ }
+ outBuf.append((char)ch);
+ }
+ backOnePosition(ch);
+ break;
+ }
+ case '>':
+ ch = file.read();
+ if (ch != '>')
+ throwError("'>' not expected");
+ type = TK_END_DIC;
+ break;
+ case '<':
+ {
+ int v1 = file.read();
+ if (v1 == '<') {
+ type = TK_START_DIC;
+ break;
+ }
+ outBuf = new StringBuffer();
+ type = TK_STRING;
+ hexString = true;
+ int v2 = 0;
+ while (true) {
+ while (isWhitespace(v1))
+ v1 = file.read();
+ if (v1 == '>')
+ break;
+ v1 = getHex(v1);
+ if (v1 < 0)
+ break;
+ v2 = file.read();
+ while (isWhitespace(v2))
+ v2 = file.read();
+ if (v2 == '>') {
+ ch = v1 << 4;
+ outBuf.append((char)ch);
+ break;
+ }
+ v2 = getHex(v2);
+ if (v2 < 0)
+ break;
+ ch = (v1 << 4) + v2;
+ outBuf.append((char)ch);
+ v1 = file.read();
+ }
+ if (v1 < 0 || v2 < 0)
+ throwError("Error reading string");
+ break;
+ }
+ case '%':
+ type = TK_COMMENT;
+ do {
+ ch = file.read();
+ } while (ch != -1 && ch != '\r' && ch != '\n');
+ break;
+ case '(':
+ {
+ outBuf = new StringBuffer();
+ type = TK_STRING;
+ hexString = false;
+ int nesting = 0;
+ while (true) {
+ ch = file.read();
+ if (ch == -1)
+ break;
+ if (ch == '(') {
+ ++nesting;
+ }
+ else if (ch == ')') {
+ --nesting;
+ }
+ else if (ch == '\\') {
+ boolean lineBreak = false;
+ ch = file.read();
+ switch (ch) {
+ case 'n':
+ ch = '\n';
+ break;
+ case 'r':
+ ch = '\r';
+ break;
+ case 't':
+ ch = '\t';
+ break;
+ case 'b':
+ ch = '\b';
+ break;
+ case 'f':
+ ch = '\f';
+ break;
+ case '(':
+ case ')':
+ case '\\':
+ break;
+ case '\r':
+ lineBreak = true;
+ ch = file.read();
+ if (ch != '\n')
+ backOnePosition(ch);
+ break;
+ case '\n':
+ lineBreak = true;
+ break;
+ default:
+ {
+ if (ch < '0' || ch > '7') {
+ break;
+ }
+ int octal = ch - '0';
+ ch = file.read();
+ if (ch < '0' || ch > '7') {
+ backOnePosition(ch);
+ ch = octal;
+ break;
+ }
+ octal = (octal << 3) + ch - '0';
+ ch = file.read();
+ if (ch < '0' || ch > '7') {
+ backOnePosition(ch);
+ ch = octal;
+ break;
+ }
+ octal = (octal << 3) + ch - '0';
+ ch = octal & 0xff;
+ break;
+ }
+ }
+ if (lineBreak)
+ continue;
+ if (ch < 0)
+ break;
+ }
+ else if (ch == '\r') {
+ ch = file.read();
+ if (ch < 0)
+ break;
+ if (ch != '\n') {
+ backOnePosition(ch);
+ ch = '\n';
+ }
+ }
+ if (nesting == -1)
+ break;
+ outBuf.append((char)ch);
+ }
+ if (ch == -1)
+ throwError("Error reading string");
+ break;
+ }
+ default:
+ {
+ outBuf = new StringBuffer();
+ if (ch == '-' || ch == '+' || ch == '.' || (ch >= '0' && ch <= '9')) {
+ type = TK_NUMBER;
+ do {
+ outBuf.append((char)ch);
+ ch = file.read();
+ } while (ch != -1 && ((ch >= '0' && ch <= '9') || ch == '.'));
+ }
+ else {
+ type = TK_OTHER;
+ do {
+ outBuf.append((char)ch);
+ ch = file.read();
+ } while (!delims[ch + 1]);
+ }
+ backOnePosition(ch);
+ break;
+ }
+ }
+ if (outBuf != null)
+ stringValue = outBuf.toString();
+ return true;
+ }
+
+ public int intValue() {
+ return Integer.parseInt(stringValue);
+ }
+
+ public boolean readLineSegment(byte input[]) throws IOException {
+ int c = -1;
+ boolean eol = false;
+ int ptr = 0;
+ int len = input.length;
+
+ // ssteward, pdftk-1.10, 040922:
+ // skip initial whitespace; added this because PdfReader.rebuildXref()
+ // assumes that line provided by readLineSegment does not have init. whitespace;
+ if ( ptr < len ) {
+ while ( isWhitespace( (c = read()) ) );
+ }
+ while ( !eol && ptr < len ) {
+ switch (c) {
+ case -1:
+ case '\n':
+ eol = true;
+ break;
+ case '\r':
+ eol = true;
+ int cur = getFilePointer();
+ if ((read()) != '\n') {
+ seek(cur);
+ }
+ break;
+ default:
+ input[ptr++] = (byte)c;
+ break;
+ }
+
+ // break loop? do it before we read() again
+ if( eol || len <= ptr ) {
+ break;
+ }
+ else {
+ c = read();
+ }
+ }
+
+ if( len <= ptr ) {
+ eol = false;
+ while (!eol) {
+ switch (c = read()) {
+ case -1:
+ case '\n':
+ eol = true;
+ break;
+ case '\r':
+ eol = true;
+ int cur = getFilePointer();
+ if ((read()) != '\n') {
+ seek(cur);
+ }
+ break;
+ }
+ }
+ }
+
+ if ((c == -1) && (ptr == 0)) {
+ return false;
+ }
+ if (ptr + 2 <= len) {
+ input[ptr++] = (byte)' ';
+ input[ptr] = (byte)'X';
+ }
+ return true;
+ }
+
+ public static int[] checkObjectStart(byte line[]) {
+ try {
+ PRTokeniser tk = new PRTokeniser(line);
+ int num = 0;
+ int gen = 0;
+ if (!tk.nextToken() || tk.getTokenType() != TK_NUMBER)
+ return null;
+ num = tk.intValue();
+ if (!tk.nextToken() || tk.getTokenType() != TK_NUMBER)
+ return null;
+ gen = tk.intValue();
+ if (!tk.nextToken())
+ return null;
+ if (!tk.getStringValue().equals("obj"))
+ return null;
+ return new int[]{num, gen};
+ }
+ catch (Exception ioe) {
+ // empty on purpose
+ }
+ return null;
+ }
+
+ public boolean isHexString() {
+ return this.hexString;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PageResources.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PageResources.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PageResources.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PageResources.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,177 @@
+/*
+ * $Id: PRTokeniser.java,v 1.15 2002/06/20 13:30:25 blowagie Exp $
+ *
+ * Copyright 2003-2005 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+class PageResources {
+
+ protected PdfDictionary fontDictionary = new PdfDictionary();
+ protected PdfDictionary xObjectDictionary = new PdfDictionary();
+ protected PdfDictionary colorDictionary = new PdfDictionary();
+ protected PdfDictionary patternDictionary = new PdfDictionary();
+ protected PdfDictionary shadingDictionary = new PdfDictionary();
+ protected PdfDictionary extGStateDictionary = new PdfDictionary();
+ protected PdfDictionary propertyDictionary = new PdfDictionary();
+ protected HashMap forbiddenNames;
+ protected PdfDictionary originalResources;
+ protected int namePtr[] = {0};
+ protected HashMap usedNames;
+
+ PageResources() {
+ }
+
+ void setOriginalResources(PdfDictionary resources, int newNamePtr[]) {
+ if (newNamePtr != null)
+ namePtr = newNamePtr;
+ originalResources = resources;
+ forbiddenNames = new HashMap();
+ usedNames = new HashMap();
+ if (resources == null)
+ return;
+ for (Iterator i = resources.getKeys().iterator(); i.hasNext();) {
+ PdfObject sub = PdfReader.getPdfObject(resources.get((PdfName)i.next()));
+ if (sub.isDictionary()) {
+ PdfDictionary dic = (PdfDictionary)sub;
+ for (Iterator j = dic.getKeys().iterator(); j.hasNext();) {
+ forbiddenNames.put(j.next(), null);
+ }
+ }
+ }
+ }
+
+ PdfName translateName(PdfName name) {
+ PdfName translated = name;
+ if (forbiddenNames != null) {
+ translated = (PdfName)usedNames.get(name);
+ if (translated == null) {
+ while (true) {
+ translated = new PdfName("Xi" + (namePtr[0]++));
+ if (!forbiddenNames.containsKey(translated))
+ break;
+ }
+ usedNames.put(name, translated);
+ }
+ }
+ return translated;
+ }
+
+ PdfName addFont(PdfName name, PdfIndirectReference reference) {
+ name = translateName(name);
+ fontDictionary.put(name, reference);
+ return name;
+ }
+
+ PdfName addXObject(PdfName name, PdfIndirectReference reference) {
+ name = translateName(name);
+ xObjectDictionary.put(name, reference);
+ return name;
+ }
+
+ PdfName addColor(PdfName name, PdfIndirectReference reference) {
+ name = translateName(name);
+ colorDictionary.put(name, reference);
+ return name;
+ }
+
+ void addDefaultColor(PdfName name, PdfObject obj) {
+ if (obj == null || obj.isNull())
+ colorDictionary.remove(name);
+ else
+ colorDictionary.put(name, obj);
+ }
+
+ void addDefaultColor(PdfDictionary dic) {
+ colorDictionary.merge(dic);
+ }
+
+ void addDefaultColorDiff(PdfDictionary dic) {
+ colorDictionary.mergeDifferent(dic);
+ }
+
+ PdfName addShading(PdfName name, PdfIndirectReference reference) {
+ name = translateName(name);
+ shadingDictionary.put(name, reference);
+ return name;
+ }
+
+ PdfName addPattern(PdfName name, PdfIndirectReference reference) {
+ name = translateName(name);
+ patternDictionary.put(name, reference);
+ return name;
+ }
+
+ PdfName addExtGState(PdfName name, PdfIndirectReference reference) {
+ name = translateName(name);
+ extGStateDictionary.put(name, reference);
+ return name;
+ }
+
+ PdfName addProperty(PdfName name, PdfIndirectReference reference) {
+ name = translateName(name);
+ propertyDictionary.put(name, reference);
+ return name;
+ }
+
+ PdfDictionary getResources() {
+ PdfResources resources = new PdfResources();
+ if (originalResources != null)
+ resources.putAll(originalResources);
+ resources.put(PdfName.PROCSET, new PdfLiteral("[/PDF /Text /ImageB /ImageC /ImageI]"));
+ resources.add(PdfName.FONT, fontDictionary);
+ resources.add(PdfName.XOBJECT, xObjectDictionary);
+ resources.add(PdfName.COLORSPACE, colorDictionary);
+ resources.add(PdfName.PATTERN, patternDictionary);
+ resources.add(PdfName.SHADING, shadingDictionary);
+ resources.add(PdfName.EXTGSTATE, extGStateDictionary);
+ resources.add(PdfName.PROPERTIES, propertyDictionary);
+ return resources;
+ }
+
+ boolean hasResources() {
+ return (fontDictionary.size() > 0
+ || xObjectDictionary.size() > 0
+ || colorDictionary.size() > 0
+ || patternDictionary.size() > 0
+ || shadingDictionary.size() > 0
+ || extGStateDictionary.size() > 0
+ || propertyDictionary.size() > 0);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PangoArabicShapping.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PangoArabicShapping.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PangoArabicShapping.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PangoArabicShapping.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,636 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+/** Shape arabic characters. This code was converted from a C version
+ * at www.pango.org.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PangoArabicShapping {
+
+ /** Creates a new instance of PangoArabicShapping */
+ public PangoArabicShapping() {
+ }
+
+ static boolean isVowel(char s) {
+ return ((s >= 0x064B) && (s <= 0x0655)) || (s == 0x0670);
+ }
+
+ static char charshape(char s, int which)
+ /* which 0=isolated 1=final 2=initial 3=medial */
+ {
+ int l, r, m;
+ if ((s >= 0x0621) && (s <= 0x06D3)) {
+ l = 0;
+ r = chartable.length - 1;
+ while (l <= r) {
+ m = (l + r) / 2;
+ if (s == chartable[m][0]) {
+ return chartable[m][which + 1];
+ }
+ else if (s < chartable[m][0]) {
+ r = m - 1;
+ }
+ else {
+ l = m + 1;
+ }
+ }
+ }
+ return s;
+ }
+
+ static int shapecount(char s) {
+ int l, r, m;
+ if ((s >= 0x0621) && (s <= 0x06D3) && !isVowel(s)) {
+ l = 0;
+ r = chartable.length - 1;
+ while (l <= r) {
+ m = (l + r) / 2;
+ if (s == chartable[m][0]) {
+ return chartable[m].length - 1;
+ }
+ else if (s < chartable[m][0]) {
+ r = m - 1;
+ }
+ else {
+ l = m + 1;
+ }
+ }
+ }
+ else if (s == ZWJ) {
+ return 4;
+ }
+ return 1;
+ }
+
+ static int ligature(char newchar, charstruct oldchar) {
+ /* 0 == no ligature possible; 1 == vowel; 2 == two chars; 3 == Lam+Alef */
+ int retval = 0;
+
+ if (oldchar.basechar == 0)
+ return 0;
+ if (isVowel(newchar)) {
+ retval = 1;
+ if ((oldchar.vowel != 0) && (newchar != SHADDA)) {
+ retval = 2; /* we eliminate the old vowel .. */
+ }
+ switch (newchar) {
+ case SHADDA:
+ if (oldchar.mark1 == 0) {
+ oldchar.mark1 = SHADDA;
+ }
+ else {
+ return 0; /* no ligature possible */
+ }
+ break;
+ case HAMZABELOW:
+ switch (oldchar.basechar) {
+ case ALEF:
+ oldchar.basechar = ALEFHAMZABELOW;
+ retval = 2;
+ break;
+ case LAM_ALEF:
+ oldchar.basechar = LAM_ALEFHAMZABELOW;
+ retval = 2;
+ break;
+ default:
+ oldchar.mark1 = HAMZABELOW;
+ break;
+ }
+ break;
+ case HAMZAABOVE:
+ switch (oldchar.basechar) {
+ case ALEF:
+ oldchar.basechar = ALEFHAMZA;
+ retval = 2;
+ break;
+ case LAM_ALEF:
+ oldchar.basechar = LAM_ALEFHAMZA;
+ retval = 2;
+ break;
+ case WAW:
+ oldchar.basechar = WAWHAMZA;
+ retval = 2;
+ break;
+ case YEH:
+ case ALEFMAKSURA:
+ case FARSIYEH:
+ oldchar.basechar = YEHHAMZA;
+ retval = 2;
+ break;
+ default: /* whatever sense this may make .. */
+ oldchar.mark1 = HAMZAABOVE;
+ break;
+ }
+ break;
+ case MADDA:
+ switch (oldchar.basechar) {
+ case ALEF:
+ oldchar.basechar = ALEFMADDA;
+ retval = 2;
+ break;
+ }
+ break;
+ default:
+ oldchar.vowel = newchar;
+ break;
+ }
+ if (retval == 1) {
+ oldchar.lignum++;
+ }
+ return retval;
+ }
+ if (oldchar.vowel != 0) { /* if we already joined a vowel, we can't join a Hamza */
+ return 0;
+ }
+
+ switch (oldchar.basechar) {
+ case LAM:
+ switch (newchar) {
+ case ALEF:
+ oldchar.basechar = LAM_ALEF;
+ oldchar.numshapes = 2;
+ retval = 3;
+ break;
+ case ALEFHAMZA:
+ oldchar.basechar = LAM_ALEFHAMZA;
+ oldchar.numshapes = 2;
+ retval = 3;
+ break;
+ case ALEFHAMZABELOW:
+ oldchar.basechar = LAM_ALEFHAMZABELOW;
+ oldchar.numshapes = 2;
+ retval = 3;
+ break;
+ case ALEFMADDA:
+ oldchar.basechar = LAM_ALEFMADDA;
+ oldchar.numshapes = 2;
+ retval = 3;
+ break;
+ }
+ break;
+ case 0:
+ oldchar.basechar = newchar;
+ oldchar.numshapes = shapecount(newchar);
+ retval = 1;
+ break;
+ }
+ return retval;
+ }
+
+ static void copycstostring(StringBuffer string, charstruct s, int level) {
+ /* s is a shaped charstruct; i is the index into the string */
+ if (s.basechar == 0)
+ return;
+
+ string.append(s.basechar);
+ (s.lignum)--;
+ if (s.mark1 != 0) {
+ if ((level & ar_novowel) == 0) {
+ string.append(s.mark1);
+ (s.lignum)--;
+ }
+ else {
+ (s.lignum)--;
+ }
+ }
+ if (s.vowel != 0) {
+ if ((level & ar_novowel) == 0) {
+ string.append(s.vowel);
+ (s.lignum)--;
+ }
+ else { /* vowel elimination */
+ (s.lignum)--;
+ }
+ }
+// while (s.lignum > 0) { /* NULL-insertion for Langbox-font */
+// string[i] = 0;
+// i++;
+// (s.lignum)--;
+// }
+// return i;
+ }
+
+ // return len
+ static void doublelig(StringBuffer string, int level)
+ /* Ok. We have presentation ligatures in our font. */
+ {
+ int len;
+ int olen = len = string.length();
+ int j = 0, si = 1;
+ char lapresult;
+
+ while (si < olen) {
+ lapresult = 0;
+ if ((level & ar_composedtashkeel) != 0) {
+ switch (string.charAt(j)) {
+ case SHADDA:
+ switch (string.charAt(si)) {
+ case KASRA:
+ lapresult = 0xFC62;
+ break;
+ case FATHA:
+ lapresult = 0xFC60;
+ break;
+ case DAMMA:
+ lapresult = 0xFC61;
+ break;
+ case 0x064C:
+ lapresult = 0xFC5E;
+ break;
+ case 0x064D:
+ lapresult = 0xFC5F;
+ break;
+ }
+ break;
+ case KASRA:
+ if (string.charAt(si) == SHADDA)
+ lapresult = 0xFC62;
+ break;
+ case FATHA:
+ if (string.charAt(si) == SHADDA)
+ lapresult = 0xFC60;
+ break;
+ case DAMMA:
+ if (string.charAt(si) == SHADDA)
+ lapresult = 0xFC61;
+ break;
+ }
+ }
+
+ if ((level & ar_lig) != 0) {
+ switch (string.charAt(j)) {
+ case 0xFEDF: /* LAM initial */
+ switch (string.charAt(si)) {
+ case 0xFE9E:
+ lapresult = 0xFC3F;
+ break; /* JEEM final */
+ case 0xFEA0:
+ lapresult = 0xFCC9;
+ break; /* JEEM medial */
+ case 0xFEA2:
+ lapresult = 0xFC40;
+ break; /* HAH final */
+ case 0xFEA4:
+ lapresult = 0xFCCA;
+ break; /* HAH medial */
+ case 0xFEA6:
+ lapresult = 0xFC41;
+ break; /* KHAH final */
+ case 0xFEA8:
+ lapresult = 0xFCCB;
+ break; /* KHAH medial */
+ case 0xFEE2:
+ lapresult = 0xFC42;
+ break; /* MEEM final */
+ case 0xFEE4:
+ lapresult = 0xFCCC;
+ break; /* MEEM medial */
+ }
+ break;
+ case 0xFE97: /* TEH inital */
+ switch (string.charAt(si)) {
+ case 0xFEA0:
+ lapresult = 0xFCA1;
+ break; /* JEEM medial */
+ case 0xFEA4:
+ lapresult = 0xFCA2;
+ break; /* HAH medial */
+ case 0xFEA8:
+ lapresult = 0xFCA3;
+ break; /* KHAH medial */
+ }
+ break;
+ case 0xFE91: /* BEH inital */
+ switch (string.charAt(si)) {
+ case 0xFEA0:
+ lapresult = 0xFC9C;
+ break; /* JEEM medial */
+ case 0xFEA4:
+ lapresult = 0xFC9D;
+ break; /* HAH medial */
+ case 0xFEA8:
+ lapresult = 0xFC9E;
+ break; /* KHAH medial */
+ }
+ break;
+ case 0xFEE7: /* NOON inital */
+ switch (string.charAt(si)) {
+ case 0xFEA0:
+ lapresult = 0xFCD2;
+ break; /* JEEM initial */
+ case 0xFEA4:
+ lapresult = 0xFCD3;
+ break; /* HAH medial */
+ case 0xFEA8:
+ lapresult = 0xFCD4;
+ break; /* KHAH medial */
+ }
+ break;
+
+ case 0xFEE8: /* NOON medial */
+ switch (string.charAt(si)) {
+ case 0xFEAE:
+ lapresult = 0xFC8A;
+ break; /* REH final */
+ case 0xFEB0:
+ lapresult = 0xFC8B;
+ break; /* ZAIN final */
+ }
+ break;
+ case 0xFEE3: /* MEEM initial */
+ switch (string.charAt(si)) {
+ case 0xFEA0:
+ lapresult = 0xFCCE;
+ break; /* JEEM medial */
+ case 0xFEA4:
+ lapresult = 0xFCCF;
+ break; /* HAH medial */
+ case 0xFEA8:
+ lapresult = 0xFCD0;
+ break; /* KHAH medial */
+ case 0xFEE4:
+ lapresult = 0xFCD1;
+ break; /* MEEM medial */
+ }
+ break;
+
+ case 0xFED3: /* FEH initial */
+ switch (string.charAt(si)) {
+ case 0xFEF2:
+ lapresult = 0xFC32;
+ break; /* YEH final */
+ }
+ break;
+
+ default:
+ break;
+ } /* end switch string[si] */
+ }
+ if (lapresult != 0) {
+ string.setCharAt(j, lapresult);
+ len--;
+ si++; /* jump over one character */
+ /* we'll have to change this, too. */
+ }
+ else {
+ j++;
+ string.setCharAt(j, string.charAt(si));
+ si++;
+ }
+ }
+ string.setLength(len);
+ }
+
+ static boolean connects_to_left(charstruct a) {
+ return a.numshapes > 2;
+ }
+
+ static void shape(char text[], StringBuffer string, int level) {
+ /* string is assumed to be empty and big enough.
+ * text is the original text.
+ * This routine does the basic arabic reshaping.
+ * *len the number of non-null characters.
+ *
+ * Note: We have to unshape each character first!
+ */
+ int join;
+ int which;
+ char nextletter;
+
+ int p = 0; /* initialize for output */
+ charstruct oldchar = new charstruct();
+ charstruct curchar = new charstruct();
+ while (p < text.length) {
+ nextletter = text[p++];
+ //nextletter = unshape (nextletter);
+
+ join = ligature(nextletter, curchar);
+ if (join == 0) { /* shape curchar */
+ int nc = shapecount(nextletter);
+ //(*len)++;
+ if (nc == 1) {
+ which = 0; /* final or isolated */
+ }
+ else {
+ which = 2; /* medial or initial */
+ }
+ if (connects_to_left(oldchar)) {
+ which++;
+ }
+
+ which = which % (curchar.numshapes);
+ curchar.basechar = charshape(curchar.basechar, which);
+
+ /* get rid of oldchar */
+ copycstostring(string, oldchar, level);
+ oldchar = curchar; /* new values in oldchar */
+
+ /* init new curchar */
+ curchar = new charstruct();
+ curchar.basechar = nextletter;
+ curchar.numshapes = nc;
+ curchar.lignum++;
+ // (*len) += unligature (&curchar, level);
+ }
+ else if ((join == 3) && (level & ar_lboxfont) != 0) { /* Lam+Alef extra in langbox-font */
+ curchar.lignum++;
+ }
+ else if (join == 1) {
+ }
+ // else
+ // {
+ // (*len) += unligature (&curchar, level);
+ // }
+ // p = g_utf8_next_char (p);
+ }
+
+ /* Handle last char */
+ if (connects_to_left(oldchar))
+ which = 1;
+ else
+ which = 0;
+ which = which % (curchar.numshapes);
+ curchar.basechar = charshape(curchar.basechar, which);
+
+ /* get rid of oldchar */
+ copycstostring(string, oldchar, level);
+ copycstostring(string, curchar, level);
+ }
+
+ static int arabic_shape(char src[], int srcoffset, int srclength, char dest[], int destoffset, int destlength, int level) {
+ char str[] = new char[srclength];
+ for (int k = srclength + srcoffset - 1; k >= srcoffset; --k)
+ str[k - srcoffset] = src[k];
+ StringBuffer string = new StringBuffer(srclength);
+ shape(str, string, level);
+ if ((level & (ar_composedtashkeel | ar_lig)) != 0)
+ doublelig(string, level);
+// string.reverse();
+ System.arraycopy(string.toString().toCharArray(), 0, dest, destoffset, string.length());
+ return string.length();
+ }
+
+ private static final char ALEF = 0x0627;
+ private static final char ALEFHAMZA = 0x0623;
+ private static final char ALEFHAMZABELOW = 0x0625;
+ private static final char ALEFMADDA = 0x0622;
+ private static final char LAM = 0x0644;
+ private static final char HAMZA = 0x0621;
+ private static final char TATWEEL = 0x0640;
+ private static final char ZWJ = 0x200D;
+
+ private static final char HAMZAABOVE = 0x0654;
+ private static final char HAMZABELOW = 0x0655;
+
+ private static final char WAWHAMZA = 0x0624;
+ private static final char YEHHAMZA = 0x0626;
+ private static final char WAW = 0x0648;
+ private static final char ALEFMAKSURA = 0x0649;
+ private static final char YEH = 0x064A;
+ private static final char FARSIYEH = 0x06CC;
+
+ private static final char SHADDA = 0x0651;
+ private static final char KASRA = 0x0650;
+ private static final char FATHA = 0x064E;
+ private static final char DAMMA = 0x064F;
+ private static final char MADDA = 0x0653;
+
+ private static final char LAM_ALEF = 0xFEFB;
+ private static final char LAM_ALEFHAMZA = 0xFEF7;
+ private static final char LAM_ALEFHAMZABELOW = 0xFEF9;
+ private static final char LAM_ALEFMADDA = 0xFEF5;
+
+ private static final char chartable[][] = {
+ {0x0621, 0xFE80}, /* HAMZA */
+ {0x0622, 0xFE81, 0xFE82}, /* ALEF WITH MADDA ABOVE */
+ {0x0623, 0xFE83, 0xFE84}, /* ALEF WITH HAMZA ABOVE */
+ {0x0624, 0xFE85, 0xFE86}, /* WAW WITH HAMZA ABOVE */
+ {0x0625, 0xFE87, 0xFE88}, /* ALEF WITH HAMZA BELOW */
+ {0x0626, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C}, /* YEH WITH HAMZA ABOVE */
+ {0x0627, 0xFE8D, 0xFE8E}, /* ALEF */
+ {0x0628, 0xFE8F, 0xFE90, 0xFE91, 0xFE92}, /* BEH */
+ {0x0629, 0xFE93, 0xFE94}, /* TEH MARBUTA */
+ {0x062A, 0xFE95, 0xFE96, 0xFE97, 0xFE98}, /* TEH */
+ {0x062B, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C}, /* THEH */
+ {0x062C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0}, /* JEEM */
+ {0x062D, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4}, /* HAH */
+ {0x062E, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8}, /* KHAH */
+ {0x062F, 0xFEA9, 0xFEAA}, /* DAL */
+ {0x0630, 0xFEAB, 0xFEAC}, /* THAL */
+ {0x0631, 0xFEAD, 0xFEAE}, /* REH */
+ {0x0632, 0xFEAF, 0xFEB0}, /* ZAIN */
+ {0x0633, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4}, /* SEEN */
+ {0x0634, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8}, /* SHEEN */
+ {0x0635, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC}, /* SAD */
+ {0x0636, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0}, /* DAD */
+ {0x0637, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4}, /* TAH */
+ {0x0638, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8}, /* ZAH */
+ {0x0639, 0xFEC9, 0xFECA, 0xFECB, 0xFECC}, /* AIN */
+ {0x063A, 0xFECD, 0xFECE, 0xFECF, 0xFED0}, /* GHAIN */
+ {0x0640, 0x0640, 0x0640, 0x0640, 0x0640}, /* TATWEEL */
+ {0x0641, 0xFED1, 0xFED2, 0xFED3, 0xFED4}, /* FEH */
+ {0x0642, 0xFED5, 0xFED6, 0xFED7, 0xFED8}, /* QAF */
+ {0x0643, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC}, /* KAF */
+ {0x0644, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0}, /* LAM */
+ {0x0645, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4}, /* MEEM */
+ {0x0646, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8}, /* NOON */
+ {0x0647, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC}, /* HEH */
+ {0x0648, 0xFEED, 0xFEEE}, /* WAW */
+ {0x0649, 0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9}, /* ALEF MAKSURA */
+ {0x064A, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4}, /* YEH */
+ {0x0671, 0xFB50, 0xFB51}, /* ALEF WASLA */
+ {0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69}, /* TTEH */
+ {0x067A, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61}, /* TTEHEH */
+ {0x067B, 0xFB52, 0xFB53, 0xFB54, 0xFB55}, /* BEEH */
+ {0x067E, 0xFB56, 0xFB57, 0xFB58, 0xFB59}, /* PEH */
+ {0x067F, 0xFB62, 0xFB63, 0xFB64, 0xFB65}, /* TEHEH */
+ {0x0680, 0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D}, /* BEHEH */
+ {0x0683, 0xFB76, 0xFB77, 0xFB78, 0xFB79}, /* NYEH */
+ {0x0684, 0xFB72, 0xFB73, 0xFB74, 0xFB75}, /* DYEH */
+ {0x0686, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D}, /* TCHEH */
+ {0x0687, 0xFB7E, 0xFB7F, 0xFB80, 0xFB81}, /* TCHEHEH */
+ {0x0688, 0xFB88, 0xFB89}, /* DDAL */
+ {0x068C, 0xFB84, 0xFB85}, /* DAHAL */
+ {0x068D, 0xFB82, 0xFB83}, /* DDAHAL */
+ {0x068E, 0xFB86, 0xFB87}, /* DUL */
+ {0x0691, 0xFB8C, 0xFB8D}, /* RREH */
+ {0x0698, 0xFB8A, 0xFB8B}, /* JEH */
+ {0x06A4, 0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D}, /* VEH */
+ {0x06A6, 0xFB6E, 0xFB6F, 0xFB70, 0xFB71}, /* PEHEH */
+ {0x06A9, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91}, /* KEHEH */
+ {0x06AD, 0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6}, /* NG */
+ {0x06AF, 0xFB92, 0xFB93, 0xFB94, 0xFB95}, /* GAF */
+ {0x06B1, 0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D}, /* NGOEH */
+ {0x06B3, 0xFB96, 0xFB97, 0xFB98, 0xFB99}, /* GUEH */
+ {0x06BB, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3}, /* RNOON */
+ {0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD}, /* HEH DOACHASHMEE */
+ {0x06C0, 0xFBA4, 0xFBA5}, /* HEH WITH YEH ABOVE */
+ {0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9}, /* HEH GOAL */
+ {0x06C5, 0xFBE0, 0xFBE1}, /* KIRGHIZ OE */
+ {0x06C6, 0xFBD9, 0xFBDA}, /* OE */
+ {0x06C7, 0xFBD7, 0xFBD8}, /* U */
+ {0x06C8, 0xFBDB, 0xFBDC}, /* YU */
+ {0x06C9, 0xFBE2, 0xFBE3}, /* KIRGHIZ YU */
+ {0x06CB, 0xFBDE, 0xFBDF}, /* VE */
+ {0x06CC, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF}, /* FARSI YEH */
+ {0x06D0, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7}, /* E */
+ {0x06D2, 0xFBAE, 0xFBAF}, /* YEH BARREE */
+ {0x06D3, 0xFBB0, 0xFBB1} /* YEH BARREE WITH HAMZA ABOVE */
+ };
+
+ static final int ar_nothing = 0x0;
+ static final int ar_novowel = 0x1;
+ static final int ar_standard = 0x2;
+ static final int ar_composedtashkeel = 0x4;
+ static final int ar_lig = 0x8;
+ static final int ar_mulefont = 0x10;
+ static final int ar_lboxfont = 0x20;
+ static final int ar_unifont = 0x40;
+ static final int ar_naqshfont = 0x80;
+
+ static class charstruct {
+ char basechar;
+ char mark1; /* has to be initialized to zero */
+ char vowel;
+ int lignum; /* is a ligature with lignum aditional characters */
+ int numshapes = 1;
+ };
+
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PatternColor.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PatternColor.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PatternColor.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PatternColor.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+/** Represents a pattern. Can be used in high-level constructs (Paragraph, Cell, etc.).
+ */
+public class PatternColor extends ExtendedColor {
+ /**
+ * The actual pattern.
+ */
+ PdfPatternPainter painter;
+
+ /** Creates a color representing a pattern.
+ * @param painter the actual pattern
+ */
+ public PatternColor(PdfPatternPainter painter) {
+ super(TYPE_PATTERN, .5f, .5f, .5f);
+ this.painter = painter;
+ }
+
+ /** Gets the pattern.
+ * @return the pattern
+ */
+ public PdfPatternPainter getPainter() {
+ return this.painter;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfAcroForm.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfAcroForm.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfAcroForm.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfAcroForm.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,736 @@
+/*
+ * $Id: PdfAcroForm.java,v 1.44 2005/03/30 10:10:58 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.Iterator;
+import java.util.HashMap;
+
+import pdftk.com.lowagie.text.Rectangle;
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+/**
+ * Each PDF document can contain maximum 1 AcroForm.
+ */
+
+public class PdfAcroForm extends PdfDictionary {
+
+ private PdfWriter writer;
+
+
+ /** This is a map containing FieldTemplates. */
+ private HashMap fieldTemplates = new HashMap();
+
+ /** This is an array containing DocumentFields. */
+ private PdfArray documentFields = new PdfArray();
+
+ /** This is an array containing the calculationorder of the fields. */
+ private PdfArray calculationOrder = new PdfArray();
+
+ /** Contains the signature flags. */
+ private int sigFlags = 0;
+
+ /** Creates new PdfAcroForm
+ * @param writer*/
+ PdfAcroForm(PdfWriter writer) {
+ super();
+ this.writer = writer;
+ }
+
+ /**
+ * Adds fieldTemplates.
+ * @param ft
+ */
+
+ void addFieldTemplates(HashMap ft) {
+ fieldTemplates.putAll(ft);
+ }
+
+ /**
+ * Adds documentFields.
+ * @param ref
+ */
+
+ void addDocumentField(PdfIndirectReference ref) {
+ // ssteward; added test to support my code in PdfCopy
+ if( !documentFields.contains(ref) )
+ documentFields.add(ref);
+ }
+
+ /**
+ * Checks if the Acroform is valid
+ * @return true if the Acroform is valid
+ */
+
+ boolean isValid() {
+ if (documentFields.size() == 0) return false;
+ put(PdfName.FIELDS, documentFields);
+ if (sigFlags != 0)
+ put(PdfName.SIGFLAGS, new PdfNumber(sigFlags));
+ if (calculationOrder.size() > 0)
+ put(PdfName.CO, calculationOrder);
+ if (fieldTemplates.size() == 0) return true;
+ PdfDictionary dic = new PdfDictionary();
+ for (Iterator it = fieldTemplates.keySet().iterator(); it.hasNext();) {
+ PdfTemplate template = (PdfTemplate)it.next();
+ PdfFormField.mergeResources(dic, (PdfDictionary)template.getResources());
+ }
+ put(PdfName.DR, dic);
+ PdfDictionary fonts = (PdfDictionary)dic.get(PdfName.FONT);
+ if (fonts != null) {
+ put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
+ writer.eliminateFontSubset(fonts);
+ }
+ return true;
+ }
+
+ /**
+ * Adds an object to the calculationOrder.
+ * @param formField
+ */
+
+ public void addCalculationOrder(PdfFormField formField) {
+ calculationOrder.add(formField.getIndirectReference());
+ }
+
+ /**
+ * Sets the signature flags.
+ * @param f
+ */
+
+ public void setSigFlags(int f) {
+ sigFlags |= f;
+ }
+
+ /**
+ * Adds a formfield to the AcroForm.
+ * @param formField
+ */
+
+ public void addFormField(PdfFormField formField) {
+ writer.addAnnotation(formField);
+ }
+
+ /**
+ * @param name
+ * @param caption
+ * @param value
+ * @param url
+ * @param font
+ * @param fontSize
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return a PdfFormField
+ */
+ public PdfFormField addHtmlPostButton(String name, String caption, String value, String url, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+ PdfAction action = PdfAction.createSubmitForm(url, null, PdfAction.SUBMIT_HTML_FORMAT);
+ PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
+ setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, value);
+ drawButton(button, caption, font, fontSize, llx, lly, urx, ury);
+ addFormField(button);
+ return button;
+ }
+
+ /**
+ * @param name
+ * @param caption
+ * @param value
+ * @param font
+ * @param fontSize
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return a PdfFormField
+ */
+ public PdfFormField addResetButton(String name, String caption, String value, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+ PdfAction action = PdfAction.createResetForm(null, 0);
+ PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
+ setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, value);
+ drawButton(button, caption, font, fontSize, llx, lly, urx, ury);
+ addFormField(button);
+ return button;
+ }
+
+ /**
+ * @param name
+ * @param value
+ * @param url
+ * @param appearance
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return a PdfFormField
+ */
+ public PdfFormField addMap(String name, String value, String url, PdfContentByte appearance, float llx, float lly, float urx, float ury) {
+ PdfAction action = PdfAction.createSubmitForm(url, null, PdfAction.SUBMIT_HTML_FORMAT | PdfAction.SUBMIT_COORDINATES);
+ PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
+ setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, null);
+ PdfContentByte cb = writer.getDirectContent();
+ PdfAppearance pa = cb.createAppearance(urx - llx, ury - lly);
+ pa.add(appearance);
+ button.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pa);
+ addFormField(button);
+ return button;
+ }
+
+ /**
+ * @param button
+ * @param characteristics
+ * @param name
+ * @param value
+ */
+ public void setButtonParams(PdfFormField button, int characteristics, String name, String value) {
+ button.setButton(characteristics);
+ button.setFlags(PdfAnnotation.FLAGS_PRINT);
+ button.setPage();
+ button.setFieldName(name);
+ if (value != null) button.setValueAsString(value);
+ }
+
+ /**
+ * @param button
+ * @param caption
+ * @param font
+ * @param fontSize
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ */
+ public void drawButton(PdfFormField button, String caption, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+ PdfContentByte cb = writer.getDirectContent();
+ PdfAppearance pa = cb.createAppearance(urx - llx, ury - lly);
+ pa.drawButton(0f, 0f, urx - llx, ury - lly, caption, font, fontSize);
+ button.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pa);
+ }
+
+ /**
+ * @param name
+ * @param value
+ * @return a PdfFormField
+ */
+ public PdfFormField addHiddenField(String name, String value) {
+ PdfFormField hidden = PdfFormField.createEmpty(writer);
+ hidden.setFieldName(name);
+ hidden.setValueAsName(value);
+ addFormField(hidden);
+ return hidden;
+ }
+
+ /**
+ * @param name
+ * @param text
+ * @param font
+ * @param fontSize
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return a PdfFormField
+ */
+ public PdfFormField addSingleLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+ PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.SINGLELINE, PdfFormField.PLAINTEXT, 0);
+ setTextFieldParams(field, text, name, llx, lly, urx, ury);
+ drawSingleLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
+ addFormField(field);
+ return field;
+ }
+
+ /**
+ * @param name
+ * @param text
+ * @param font
+ * @param fontSize
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return a PdfFormField
+ */
+ public PdfFormField addMultiLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+ PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.MULTILINE, PdfFormField.PLAINTEXT, 0);
+ setTextFieldParams(field, text, name, llx, lly, urx, ury);
+ drawMultiLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
+ addFormField(field);
+ return field;
+ }
+
+ /**
+ * @param name
+ * @param text
+ * @param font
+ * @param fontSize
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return PdfFormField
+ */
+ public PdfFormField addSingleLinePasswordField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+ PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.SINGLELINE, PdfFormField.PASSWORD, 0);
+ setTextFieldParams(field, text, name, llx, lly, urx, ury);
+ drawSingleLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
+ addFormField(field);
+ return field;
+ }
+
+ /**
+ * @param field
+ * @param text
+ * @param name
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ */
+ public void setTextFieldParams(PdfFormField field, String text, String name, float llx, float lly, float urx, float ury) {
+ field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
+ field.setValueAsString(text);
+ field.setDefaultValueAsString(text);
+ field.setFieldName(name);
+ field.setFlags(PdfAnnotation.FLAGS_PRINT);
+ field.setPage();
+ }
+
+ /**
+ * @param field
+ * @param text
+ * @param font
+ * @param fontSize
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ */
+ public void drawSingleLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+ PdfContentByte cb = writer.getDirectContent();
+ PdfAppearance tp = cb.createAppearance(urx - llx, ury - lly);
+ PdfAppearance tp2 = (PdfAppearance)tp.getDuplicate();
+ tp2.setFontAndSize(font, fontSize);
+ tp2.resetRGBColorFill();
+ field.setDefaultAppearanceString(tp2);
+ tp.drawTextField(0f, 0f, urx - llx, ury - lly);
+ tp.beginVariableText();
+ tp.saveState();
+ tp.rectangle(3f, 3f, urx - llx - 6f, ury - lly - 6f);
+ tp.clip();
+ tp.newPath();
+ tp.beginText();
+ tp.setFontAndSize(font, fontSize);
+ tp.resetRGBColorFill();
+ tp.setTextMatrix(4, (ury - lly) / 2 - (fontSize * 0.3f));
+ tp.showText(text);
+ tp.endText();
+ tp.restoreState();
+ tp.endVariableText();
+ field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
+ }
+
+ /**
+ * @param field
+ * @param text
+ * @param font
+ * @param fontSize
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ */
+ public void drawMultiLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+ PdfContentByte cb = writer.getDirectContent();
+ PdfAppearance tp = cb.createAppearance(urx - llx, ury - lly);
+ PdfAppearance tp2 = (PdfAppearance)tp.getDuplicate();
+ tp2.setFontAndSize(font, fontSize);
+ tp2.resetRGBColorFill();
+ field.setDefaultAppearanceString(tp2);
+ tp.drawTextField(0f, 0f, urx - llx, ury - lly);
+ tp.beginVariableText();
+ tp.saveState();
+ tp.rectangle(3f, 3f, urx - llx - 6f, ury - lly - 6f);
+ tp.clip();
+ tp.newPath();
+ tp.beginText();
+ tp.setFontAndSize(font, fontSize);
+ tp.resetRGBColorFill();
+ tp.setTextMatrix(4, 5);
+ java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(text, "\n");
+ float yPos = ury - lly;
+ while (tokenizer.hasMoreTokens()) {
+ yPos -= fontSize * 1.2f;
+ tp.showTextAligned(PdfContentByte.ALIGN_LEFT, tokenizer.nextToken(), 3, yPos, 0);
+ }
+ tp.endText();
+ tp.restoreState();
+ tp.endVariableText();
+ field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
+ }
+
+ /**
+ * @param name
+ * @param value
+ * @param status
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return a PdfFormField
+ */
+ public PdfFormField addCheckBox(String name, String value, boolean status, float llx, float lly, float urx, float ury) {
+ PdfFormField field = PdfFormField.createCheckBox(writer);
+ setCheckBoxParams(field, name, value, status, llx, lly, urx, ury);
+ drawCheckBoxAppearences(field, value, llx, lly, urx, ury);
+ addFormField(field);
+ return field;
+ }
+
+ /**
+ * @param field
+ * @param name
+ * @param value
+ * @param status
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ */
+ public void setCheckBoxParams(PdfFormField field, String name, String value, boolean status, float llx, float lly, float urx, float ury) {
+ field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_TOGGLE);
+ field.setFieldName(name);
+ if (status) {
+ field.setValueAsName(value);
+ field.setAppearanceState(value);
+ }
+ else {
+ field.setValueAsName("Off");
+ field.setAppearanceState("Off");
+ }
+ field.setFlags(PdfAnnotation.FLAGS_PRINT);
+ field.setPage();
+ field.setBorderStyle(new PdfBorderDictionary(1, PdfBorderDictionary.STYLE_SOLID));
+ }
+
+ /**
+ * @param field
+ * @param value
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ */
+ public void drawCheckBoxAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury) {
+ BaseFont font = null;
+ try {
+ font = BaseFont.createFont(BaseFont.ZAPFDINGBATS, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
+ }
+ catch(Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ float size = (ury - lly);
+ PdfContentByte cb = writer.getDirectContent();
+ PdfAppearance tpOn = cb.createAppearance(urx - llx, ury - lly);
+ PdfAppearance tp2 = (PdfAppearance)tpOn.getDuplicate();
+ tp2.setFontAndSize(font, size);
+ tp2.resetRGBColorFill();
+ field.setDefaultAppearanceString(tp2);
+ tpOn.drawTextField(0f, 0f, urx - llx, ury - lly);
+ tpOn.saveState();
+ tpOn.resetRGBColorFill();
+ tpOn.beginText();
+ tpOn.setFontAndSize(font, size);
+ tpOn.showTextAligned(PdfContentByte.ALIGN_CENTER, "4", (urx - llx) / 2, (ury - lly) / 2 - (size * 0.3f), 0);
+ tpOn.endText();
+ tpOn.restoreState();
+ field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, value, tpOn);
+ PdfAppearance tpOff = cb.createAppearance(urx - llx, ury - lly);
+ tpOff.drawTextField(0f, 0f, urx - llx, ury - lly);
+ field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpOff);
+ }
+
+ /**
+ * @param name
+ * @param defaultValue
+ * @param noToggleToOff
+ * @return a PdfFormField
+ */
+ public PdfFormField getRadioGroup(String name, String defaultValue, boolean noToggleToOff) {
+ PdfFormField radio = PdfFormField.createRadioButton(writer, noToggleToOff);
+ radio.setFieldName(name);
+ radio.setValueAsName(defaultValue);
+ return radio;
+ }
+
+ /**
+ * @param radiogroup
+ */
+ public void addRadioGroup(PdfFormField radiogroup) {
+ addFormField(radiogroup);
+ }
+
+ /**
+ * @param radiogroup
+ * @param value
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return a PdfFormField
+ */
+ public PdfFormField addRadioButton(PdfFormField radiogroup, String value, float llx, float lly, float urx, float ury) {
+ PdfFormField radio = PdfFormField.createEmpty(writer);
+ radio.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_TOGGLE);
+ String name = ((PdfName)radiogroup.get(PdfName.V)).toString().substring(1);
+ if (name.equals(value)) {
+ radio.setAppearanceState(value);
+ }
+ else {
+ radio.setAppearanceState("Off");
+ }
+ drawRadioAppearences(radio, value, llx, lly, urx, ury);
+ radiogroup.addKid(radio);
+ return radio;
+ }
+
+ /**
+ * @param field
+ * @param value
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ */
+ public void drawRadioAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury) {
+ PdfContentByte cb = writer.getDirectContent();
+ PdfAppearance tpOn = cb.createAppearance(urx - llx, ury - lly);
+ tpOn.drawRadioField(0f, 0f, urx - llx, ury - lly, true);
+ field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, value, tpOn);
+ PdfAppearance tpOff = cb.createAppearance(urx - llx, ury - lly);
+ tpOff.drawRadioField(0f, 0f, urx - llx, ury - lly, false);
+ field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpOff);
+ }
+
+ /**
+ * @param name
+ * @param options
+ * @param defaultValue
+ * @param font
+ * @param fontSize
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return a PdfFormField
+ */
+ public PdfFormField addSelectList(String name, String[] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+ PdfFormField choice = PdfFormField.createList(writer, options, 0);
+ setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
+ StringBuffer text = new StringBuffer();
+ for (int i = 0; i < options.length; i++) {
+ text.append(options[i]).append("\n");
+ }
+ drawMultiLineOfText(choice, text.toString(), font, fontSize, llx, lly, urx, ury);
+ addFormField(choice);
+ return choice;
+ }
+
+ /**
+ * @param name
+ * @param options
+ * @param defaultValue
+ * @param font
+ * @param fontSize
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return a PdfFormField
+ */
+ public PdfFormField addSelectList(String name, String[][] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+ PdfFormField choice = PdfFormField.createList(writer, options, 0);
+ setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
+ StringBuffer text = new StringBuffer();
+ for (int i = 0; i < options.length; i++) {
+ text.append(options[i][1]).append("\n");
+ }
+ drawMultiLineOfText(choice, text.toString(), font, fontSize, llx, lly, urx, ury);
+ addFormField(choice);
+ return choice;
+ }
+
+ /**
+ * @param name
+ * @param options
+ * @param defaultValue
+ * @param editable
+ * @param font
+ * @param fontSize
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return a PdfFormField
+ */
+ public PdfFormField addComboBox(String name, String[] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+ PdfFormField choice = PdfFormField.createCombo(writer, editable, options, 0);
+ setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
+ if (defaultValue == null) {
+ defaultValue = options[0];
+ }
+ drawSingleLineOfText(choice, defaultValue, font, fontSize, llx, lly, urx, ury);
+ addFormField(choice);
+ return choice;
+ }
+
+ /**
+ * @param name
+ * @param options
+ * @param defaultValue
+ * @param editable
+ * @param font
+ * @param fontSize
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return a PdfFormField
+ */
+ public PdfFormField addComboBox(String name, String[][] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
+ PdfFormField choice = PdfFormField.createCombo(writer, editable, options, 0);
+ setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
+ String value = null;
+ for (int i = 0; i < options.length; i++) {
+ if (options[i][0].equals(defaultValue)) {
+ value = options[i][1];
+ break;
+ }
+ }
+ if (value == null) {
+ value = options[0][1];
+ }
+ drawSingleLineOfText(choice, value, font, fontSize, llx, lly, urx, ury);
+ addFormField(choice);
+ return choice;
+ }
+
+ /**
+ * @param field
+ * @param name
+ * @param defaultValue
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ */
+ public void setChoiceParams(PdfFormField field, String name, String defaultValue, float llx, float lly, float urx, float ury) {
+ field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
+ if (defaultValue != null) {
+ field.setValueAsString(defaultValue);
+ field.setDefaultValueAsString(defaultValue);
+ }
+ field.setFieldName(name);
+ field.setFlags(PdfAnnotation.FLAGS_PRINT);
+ field.setPage();
+ field.setBorderStyle(new PdfBorderDictionary(2, PdfBorderDictionary.STYLE_SOLID));
+ }
+
+ /**
+ * @param name
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @return a PdfFormField
+ */
+ public PdfFormField addSignature(String name,
+ float llx, float lly, float urx, float ury) {
+ PdfFormField signature = PdfFormField.createSignature(writer);
+ setSignatureParams(signature, name, llx, lly, urx, ury);
+ drawSignatureAppearences(signature, llx, lly, urx, ury);
+ addFormField(signature);
+ return signature;
+ }
+
+ /**
+ * @param field
+ * @param name
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ */
+ public void setSignatureParams(PdfFormField field, String name,
+ float llx, float lly, float urx, float ury) {
+ field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
+ field.setFieldName(name);
+ field.setFlags(PdfAnnotation.FLAGS_PRINT);
+ field.setPage();
+ field.setMKBorderColor(java.awt.Color.black);
+ field.setMKBackgroundColor(java.awt.Color.white);
+ }
+
+ /**
+ * @param field
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ */
+ public void drawSignatureAppearences(PdfFormField field,
+ float llx, float lly, float urx, float ury) {
+ PdfContentByte cb = writer.getDirectContent();
+ PdfAppearance tp = cb.createAppearance(urx - llx, ury - lly);
+ tp.setGrayFill(1.0f);
+ tp.rectangle(0, 0, urx - llx, ury - lly);
+ tp.fill();
+ tp.setGrayStroke(0);
+ tp.setLineWidth(1);
+ tp.rectangle(0.5f, 0.5f, urx - llx - 0.5f, ury - lly - 0.5f);
+ tp.closePathStroke();
+ tp.saveState();
+ tp.rectangle(1, 1, urx - llx - 2, ury - lly - 2);
+ tp.clip();
+ tp.newPath();
+ tp.restoreState();
+ field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfAction.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfAction.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfAction.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfAction.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,548 @@
+/*
+ * $Id: PdfAction.java,v 1.64 2005/01/06 09:40:10 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.net.URL;
+import pdftk.com.lowagie.text.ExceptionConverter;
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * A PdfAction
defines an action that can be triggered from a PDF file.
+ *
+ * @see PdfDictionary
+ */
+
+public class PdfAction extends PdfDictionary {
+
+ /** A named action to go to the first page.
+ */
+ public static final int FIRSTPAGE = 1;
+ /** A named action to go to the previous page.
+ */
+ public static final int PREVPAGE = 2;
+ /** A named action to go to the next page.
+ */
+ public static final int NEXTPAGE = 3;
+ /** A named action to go to the last page.
+ */
+ public static final int LASTPAGE = 4;
+
+ /** A named action to open a print dialog.
+ */
+ public static final int PRINTDIALOG = 5;
+
+ /** a possible submitvalue */
+ public static final int SUBMIT_EXCLUDE = 1;
+ /** a possible submitvalue */
+ public static final int SUBMIT_INCLUDE_NO_VALUE_FIELDS = 2;
+ /** a possible submitvalue */
+ public static final int SUBMIT_HTML_FORMAT = 4;
+ /** a possible submitvalue */
+ public static final int SUBMIT_HTML_GET = 8;
+ /** a possible submitvalue */
+ public static final int SUBMIT_COORDINATES = 16;
+ /** a possible submitvalue */
+ public static final int SUBMIT_XFDF = 32;
+ /** a possible submitvalue */
+ public static final int SUBMIT_INCLUDE_APPEND_SAVES = 64;
+ /** a possible submitvalue */
+ public static final int SUBMIT_INCLUDE_ANNOTATIONS = 128;
+ /** a possible submitvalue */
+ public static final int SUBMIT_PDF = 256;
+ /** a possible submitvalue */
+ public static final int SUBMIT_CANONICAL_FORMAT = 512;
+ /** a possible submitvalue */
+ public static final int SUBMIT_EXCL_NON_USER_ANNOTS = 1024;
+ /** a possible submitvalue */
+ public static final int SUBMIT_EXCL_F_KEY = 2048;
+ /** a possible submitvalue */
+ public static final int SUBMIT_EMBED_FORM = 8196;
+ /** a possible submitvalue */
+ public static final int RESET_EXCLUDE = 1;
+
+ // constructors
+
+ /** Create an empty action.
+ */
+ public PdfAction() {
+ }
+
+ /**
+ * Constructs a new PdfAction
of Subtype URI.
+ *
+ * @param url the Url to go to
+ */
+
+ public PdfAction(URL url) {
+ this(url.toExternalForm());
+ }
+
+ /**
+ * Construct a new PdfAction
of Subtype URI that accepts the x and y coordinate of the position that was clicked.
+ * @param url
+ * @param isMap
+ */
+ public PdfAction(URL url, boolean isMap) {
+ this(url.toExternalForm(), isMap);
+ }
+
+ /**
+ * Constructs a new PdfAction
of Subtype URI.
+ *
+ * @param url the url to go to
+ */
+
+ public PdfAction(String url) {
+ this(url, false);
+ }
+
+ /**
+ * Construct a new PdfAction
of Subtype URI that accepts the x and y coordinate of the position that was clicked.
+ * @param url
+ * @param isMap
+ */
+
+ public PdfAction(String url, boolean isMap) {
+ put(PdfName.S, PdfName.URI);
+ put(PdfName.URI, new PdfString(url));
+ if (isMap)
+ put(PdfName.ISMAP, PdfBoolean.PDFTRUE);
+ }
+
+ /**
+ * Constructs a new PdfAction
of Subtype GoTo.
+ * @param destination the destination to go to
+ */
+
+ PdfAction(PdfIndirectReference destination) {
+ put(PdfName.S, PdfName.GOTO);
+ put(PdfName.D, destination);
+ }
+
+ /**
+ * Constructs a new PdfAction
of Subtype GoToR.
+ * @param filename the file name to go to
+ * @param name the named destination to go to
+ */
+
+ public PdfAction(String filename, String name) {
+ put(PdfName.S, PdfName.GOTOR);
+ put(PdfName.F, new PdfString(filename));
+ put(PdfName.D, new PdfString(name));
+ }
+
+ /**
+ * Constructs a new PdfAction
of Subtype GoToR.
+ * @param filename the file name to go to
+ * @param page the page destination to go to
+ */
+
+ public PdfAction(String filename, int page) {
+ put(PdfName.S, PdfName.GOTOR);
+ put(PdfName.F, new PdfString(filename));
+ put(PdfName.D, new PdfLiteral("[" + (page - 1) + " /FitH 10000]"));
+ }
+
+ /** Implements name actions. The action can be FIRSTPAGE, LASTPAGE,
+ * NEXTPAGE, PREVPAGE and PRINTDIALOG.
+ * @param named the named action
+ */
+ public PdfAction(int named) {
+ put(PdfName.S, PdfName.NAMED);
+ switch (named) {
+ case FIRSTPAGE:
+ put(PdfName.N, PdfName.FIRSTPAGE);
+ break;
+ case LASTPAGE:
+ put(PdfName.N, PdfName.LASTPAGE);
+ break;
+ case NEXTPAGE:
+ put(PdfName.N, PdfName.NEXTPAGE);
+ break;
+ case PREVPAGE:
+ put(PdfName.N, PdfName.PREVPAGE);
+ break;
+ case PRINTDIALOG:
+ put(PdfName.S, PdfName.JAVASCRIPT);
+ put(PdfName.JS, new PdfString("this.print(true);\r"));
+ break;
+ default:
+ throw new RuntimeException("Invalid named action.");
+ }
+ }
+
+ /** Launchs an application or a document.
+ * @param application the application to be launched or the document to be opened or printed.
+ * @param parameters (Windows-specific) A parameter string to be passed to the application.
+ * It can be null
.
+ * @param operation (Windows-specific) the operation to perform: "open" - Open a document,
+ * "print" - Print a document.
+ * It can be null
.
+ * @param defaultDir (Windows-specific) the default directory in standard DOS syntax.
+ * It can be null
.
+ */
+ public PdfAction(String application, String parameters, String operation, String defaultDir) {
+ put(PdfName.S, PdfName.LAUNCH);
+ if (parameters == null && operation == null && defaultDir == null)
+ put(PdfName.F, new PdfString(application));
+ else {
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.F, new PdfString(application));
+ if (parameters != null)
+ dic.put(PdfName.P, new PdfString(parameters));
+ if (operation != null)
+ dic.put(PdfName.O, new PdfString(operation));
+ if (defaultDir != null)
+ dic.put(PdfName.D, new PdfString(defaultDir));
+ put(PdfName.WIN, dic);
+ }
+ }
+
+ /** Launchs an application or a document.
+ * @param application the application to be launched or the document to be opened or printed.
+ * @param parameters (Windows-specific) A parameter string to be passed to the application.
+ * It can be null
.
+ * @param operation (Windows-specific) the operation to perform: "open" - Open a document,
+ * "print" - Print a document.
+ * It can be null
.
+ * @param defaultDir (Windows-specific) the default directory in standard DOS syntax.
+ * It can be null
.
+ * @return a Launch action
+ */
+ public static PdfAction createLaunch(String application, String parameters, String operation, String defaultDir) {
+ return new PdfAction(application, parameters, operation, defaultDir);
+ }
+
+ /**Creates a Rendition action
+ * @param file
+ * @param fs
+ * @param mimeType
+ * @param ref
+ * @return a Media Clip action
+ * @throws IOException
+ */
+ public static PdfAction rendition(String file, PdfFileSpecification fs, String mimeType, PdfIndirectReference ref) throws IOException {
+ PdfAction js = new PdfAction();
+ js.put(PdfName.S, PdfName.RENDITION);
+ js.put(PdfName.R, new PdfRendition(file, fs, mimeType));
+ js.put(new PdfName("OP"), new PdfNumber(0));
+ js.put(new PdfName("AN"), ref);
+ return js;
+ }
+
+ /** Creates a JavaScript action. If the JavaScript is smaller than
+ * 50 characters it will be placed as a string, otherwise it will
+ * be placed as a compressed stream.
+ * @param code the JavaScript code
+ * @param writer the writer for this action
+ * @param unicode select JavaScript unicode. Note that the internal
+ * Acrobat JavaScript engine does not support unicode,
+ * so this may or may not work for you
+ * @return the JavaScript action
+ */
+ public static PdfAction javaScript(String code, PdfWriter writer, boolean unicode) {
+ PdfAction js = new PdfAction();
+ js.put(PdfName.S, PdfName.JAVASCRIPT);
+ if (unicode && code.length() < 50) {
+ js.put(PdfName.JS, new PdfString(code, PdfObject.TEXT_UNICODE));
+ }
+ else if (!unicode && code.length() < 100) {
+ js.put(PdfName.JS, new PdfString(code));
+ }
+ else {
+ try {
+ byte b[] = PdfEncodings.convertToBytes(code, unicode ? PdfObject.TEXT_UNICODE : PdfObject.TEXT_PDFDOCENCODING);
+ PdfStream stream = new PdfStream(b);
+ stream.flateCompress();
+ js.put(PdfName.JS, writer.addToBody(stream).getIndirectReference());
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+ return js;
+ }
+
+ /** Creates a JavaScript action. If the JavaScript is smaller than
+ * 50 characters it will be place as a string, otherwise it will
+ * be placed as a compressed stream.
+ * @param code the JavaScript code
+ * @param writer the writer for this action
+ * @return the JavaScript action
+ */
+ public static PdfAction javaScript(String code, PdfWriter writer) {
+ return javaScript(code, writer, false);
+ }
+
+ /**
+ * A Hide action hides or shows an object.
+ * @param obj object to hide or show
+ * @param hide true is hide, false is show
+ * @return a Hide Action
+ */
+ static PdfAction createHide(PdfObject obj, boolean hide) {
+ PdfAction action = new PdfAction();
+ action.put(PdfName.S, PdfName.HIDE);
+ action.put(PdfName.T, obj);
+ if (!hide)
+ action.put(PdfName.H, PdfBoolean.PDFFALSE);
+ return action;
+ }
+
+ /**
+ * A Hide action hides or shows an annotation.
+ * @param annot
+ * @param hide
+ * @return A Hide Action
+ */
+ public static PdfAction createHide(PdfAnnotation annot, boolean hide) {
+ return createHide(annot.getIndirectReference(), hide);
+ }
+
+ /**
+ * A Hide action hides or shows an annotation.
+ * @param name
+ * @param hide
+ * @return A Hide Action
+ */
+ public static PdfAction createHide(String name, boolean hide) {
+ return createHide(new PdfString(name), hide);
+ }
+
+ static PdfArray buildArray(Object names[]) {
+ PdfArray array = new PdfArray();
+ for (int k = 0; k < names.length; ++k) {
+ Object obj = names[k];
+ if (obj instanceof String)
+ array.add(new PdfString((String)obj));
+ else if (obj instanceof PdfAnnotation)
+ array.add(((PdfAnnotation)obj).getIndirectReference());
+ else
+ throw new RuntimeException("The array must contain String or PdfAnnotation.");
+ }
+ return array;
+ }
+
+ /**
+ * A Hide action hides or shows objects.
+ * @param names
+ * @param hide
+ * @return A Hide Action
+ */
+ public static PdfAction createHide(Object names[], boolean hide) {
+ return createHide(buildArray(names), hide);
+ }
+
+ /**
+ * Creates a submit form.
+ * @param file the URI to submit the form to
+ * @param names the objects to submit
+ * @param flags submit properties
+ * @return A PdfAction
+ */
+ public static PdfAction createSubmitForm(String file, Object names[], int flags) {
+ PdfAction action = new PdfAction();
+ action.put(PdfName.S, PdfName.SUBMITFORM);
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.F, new PdfString(file));
+ dic.put(PdfName.FS, PdfName.URL);
+ action.put(PdfName.F, dic);
+ if (names != null)
+ action.put(PdfName.FIELDS, buildArray(names));
+ action.put(PdfName.FLAGS, new PdfNumber(flags));
+ return action;
+ }
+
+ /**
+ * Creates a resetform.
+ * @param names the objects to reset
+ * @param flags submit properties
+ * @return A PdfAction
+ */
+ public static PdfAction createResetForm(Object names[], int flags) {
+ PdfAction action = new PdfAction();
+ action.put(PdfName.S, PdfName.RESETFORM);
+ if (names != null)
+ action.put(PdfName.FIELDS, buildArray(names));
+ action.put(PdfName.FLAGS, new PdfNumber(flags));
+ return action;
+ }
+
+ /**
+ * Creates an Import field.
+ * @param file
+ * @return A PdfAction
+ */
+ public static PdfAction createImportData(String file) {
+ PdfAction action = new PdfAction();
+ action.put(PdfName.S, PdfName.IMPORTDATA);
+ action.put(PdfName.F, new PdfString(file));
+ return action;
+ }
+
+ /** Add a chained action.
+ * @param na the next action
+ */
+ public void next(PdfAction na) {
+ PdfObject nextAction = get(PdfName.NEXT);
+ if (nextAction == null)
+ put(PdfName.NEXT, na);
+ else if (nextAction.isDictionary()) {
+ PdfArray array = new PdfArray(nextAction);
+ array.add(na);
+ put(PdfName.NEXT, array);
+ }
+ else {
+ ((PdfArray)nextAction).add(na);
+ }
+ }
+
+ /** Creates a GoTo action to an internal page.
+ * @param page the page to go. First page is 1
+ * @param dest the destination for the page
+ * @param writer the writer for this action
+ * @return a GoTo action
+ */
+ public static PdfAction gotoLocalPage(int page, PdfDestination dest, PdfWriter writer) {
+ PdfIndirectReference ref = writer.getPageReference(page);
+ dest.addPage(ref);
+ PdfAction action = new PdfAction();
+ action.put(PdfName.S, PdfName.GOTO);
+ action.put(PdfName.D, dest);
+ return action;
+ }
+
+ /**
+ * Creates a GoTo action to a named destination.
+ * @param dest the named destination
+ * @param isName if true sets the destination as a name, if false sets it as a String
+ * @return a GoToR action
+ */
+ public static PdfAction gotoLocalPage(String dest, boolean isName) {
+ PdfAction action = new PdfAction();
+ action.put(PdfName.S, PdfName.GOTO);
+ if (isName)
+ action.put(PdfName.D, new PdfName(dest));
+ else
+ action.put(PdfName.D, new PdfString(dest, null));
+ return action;
+ }
+
+ /**
+ * Creates a GoToR action to a named destination.
+ * @param filename the file name to go to
+ * @param dest the destination name
+ * @param isName if true sets the destination as a name, if false sets it as a String
+ * @param newWindow open the document in a new window if true
, if false the current document is replaced by the new document.
+ * @return a GoToR action
+ */
+ public static PdfAction gotoRemotePage(String filename, String dest, boolean isName, boolean newWindow) {
+ PdfAction action = new PdfAction();
+ action.put(PdfName.F, new PdfString(filename));
+ action.put(PdfName.S, PdfName.GOTOR);
+ if (isName)
+ action.put(PdfName.D, new PdfName(dest));
+ else
+ action.put(PdfName.D, new PdfString(dest, null));
+ if (newWindow)
+ action.put(PdfName.NEWWINDOW, PdfBoolean.PDFTRUE);
+ return action;
+ }
+
+ /**
+ * A set-OCG-state action (PDF 1.5) sets the state of one or more optional content
+ * groups.
+ * @param state an array consisting of any number of sequences beginning with a PdfName
+ * or String
(ON, OFF, or Toggle) followed by one or more optional content group dictionaries
+ * PdfLayer
or a PdfIndirectReference
to a PdfLayer
.
+ * The array elements are processed from left to right; each name is applied
+ * to the subsequent groups until the next name is encountered:
+ *
+ * ON sets the state of subsequent groups to ON
+ * OFF sets the state of subsequent groups to OFF
+ * Toggle reverses the state of subsequent groups
+ *
+ * @param preserveRB if true
, indicates that radio-button state relationships between optional
+ * content groups (as specified by the RBGroups entry in the current configuration
+ * dictionary) should be preserved when the states in the
+ * state
array are applied. That is, if a group is set to ON (either by ON or Toggle) during
+ * processing of the state
array, any other groups belong to the same radio-button
+ * group are turned OFF. If a group is set to OFF, there is no effect on other groups.
+ * If false
, radio-button state relationships, if any, are ignored
+ * @return the action
+ */
+ public static PdfAction setOCGstate(ArrayList state, boolean preserveRB) {
+ PdfAction action = new PdfAction();
+ action.put(PdfName.S, PdfName.SETOCGSTATE);
+ PdfArray a = new PdfArray();
+ for (int k = 0; k < state.size(); ++k) {
+ Object o = state.get(k);
+ if (o == null)
+ continue;
+ if (o instanceof PdfIndirectReference)
+ a.add((PdfIndirectReference)o);
+ else if (o instanceof PdfLayer)
+ a.add(((PdfLayer)o).getRef());
+ else if (o instanceof PdfName)
+ a.add((PdfName)o);
+ else if (o instanceof String) {
+ PdfName name = null;
+ String s = (String)o;
+ if (s.equalsIgnoreCase("on"))
+ name = PdfName.ON;
+ else if (s.equalsIgnoreCase("off"))
+ name = PdfName.OFF;
+ else if (s.equalsIgnoreCase("toggle"))
+ name = PdfName.TOGGLE;
+ else
+ throw new IllegalArgumentException("A string '" + s + " was passed in state. Only 'ON', 'OFF' and 'Toggle' are allowed.");
+ a.add(name);
+ }
+ else
+ throw new IllegalArgumentException("Invalid type was passed in state: " + o.getClass().getName());
+ }
+ action.put(PdfName.STATE, a);
+ if (!preserveRB)
+ action.put(PdfName.PRESERVERB, PdfBoolean.PDFFALSE);
+ return action;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfAnnotation.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfAnnotation.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfAnnotation.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfAnnotation.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,731 @@
+/*
+ * $Id: PdfAnnotation.java,v 1.57 2005/01/06 13:42:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.Rectangle;
+import java.util.HashMap;
+import java.awt.Color;
+import java.io.*;
+/**
+ * A PdfAnnotation
is a note that is associated with a page.
+ *
+ * @see PdfDictionary
+ */
+
+public class PdfAnnotation extends PdfDictionary {
+ /** highlight attributename */
+ public static final PdfName HIGHLIGHT_NONE = PdfName.N;
+ /** highlight attributename */
+ public static final PdfName HIGHLIGHT_INVERT = PdfName.I;
+ /** highlight attributename */
+ public static final PdfName HIGHLIGHT_OUTLINE = PdfName.O;
+ /** highlight attributename */
+ public static final PdfName HIGHLIGHT_PUSH = PdfName.P;
+ /** highlight attributename */
+ public static final PdfName HIGHLIGHT_TOGGLE = PdfName.T;
+ /** flagvalue */
+ public static final int FLAGS_INVISIBLE = 1;
+ /** flagvalue */
+ public static final int FLAGS_HIDDEN = 2;
+ /** flagvalue */
+ public static final int FLAGS_PRINT = 4;
+ /** flagvalue */
+ public static final int FLAGS_NOZOOM = 8;
+ /** flagvalue */
+ public static final int FLAGS_NOROTATE = 16;
+ /** flagvalue */
+ public static final int FLAGS_NOVIEW = 32;
+ /** flagvalue */
+ public static final int FLAGS_READONLY = 64;
+ /** flagvalue */
+ public static final int FLAGS_LOCKED = 128;
+ /** flagvalue */
+ public static final int FLAGS_TOGGLENOVIEW = 256;
+ /** appearance attributename */
+ public static final PdfName APPEARANCE_NORMAL = PdfName.N;
+ /** appearance attributename */
+ public static final PdfName APPEARANCE_ROLLOVER = PdfName.R;
+ /** appearance attributename */
+ public static final PdfName APPEARANCE_DOWN = PdfName.D;
+ /** attributevalue */
+ public static final PdfName AA_ENTER = PdfName.E;
+ /** attributevalue */
+ public static final PdfName AA_EXIT = PdfName.X;
+ /** attributevalue */
+ public static final PdfName AA_DOWN = PdfName.D;
+ /** attributevalue */
+ public static final PdfName AA_UP = PdfName.U;
+ /** attributevalue */
+ public static final PdfName AA_FOCUS = PdfName.FO;
+ /** attributevalue */
+ public static final PdfName AA_BLUR = PdfName.BL;
+ /** attributevalue */
+ public static final PdfName AA_JS_KEY = PdfName.K;
+ /** attributevalue */
+ public static final PdfName AA_JS_FORMAT = PdfName.F;
+ /** attributevalue */
+ public static final PdfName AA_JS_CHANGE = PdfName.V;
+ /** attributevalue */
+ public static final PdfName AA_JS_OTHER_CHANGE = PdfName.C;
+ /** attributevalue */
+ public static final int MARKUP_HIGHLIGHT = 0;
+ /** attributevalue */
+ public static final int MARKUP_UNDERLINE = 1;
+ /** attributevalue */
+ public static final int MARKUP_STRIKEOUT = 2;
+
+ protected PdfWriter writer;
+ protected PdfIndirectReference reference;
+ protected HashMap templates;
+ protected boolean form = false;
+ protected boolean annotation = true;
+
+ /** Holds value of property used. */
+ protected boolean used = false;
+
+ /** Holds value of property placeInPage. */
+ private int placeInPage = -1;
+
+ // constructors
+ public PdfAnnotation(PdfWriter writer, Rectangle rect) {
+ this.writer = writer;
+ if (rect != null)
+ put(PdfName.RECT, new PdfRectangle(rect));
+ }
+
+/**
+ * Constructs a new PdfAnnotation
of subtype text.
+ * @param writer
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @param title
+ * @param content
+ */
+
+ PdfAnnotation(PdfWriter writer, float llx, float lly, float urx, float ury, PdfString title, PdfString content) {
+ this.writer = writer;
+ put(PdfName.SUBTYPE, PdfName.TEXT);
+ put(PdfName.T, title);
+ put(PdfName.RECT, new PdfRectangle(llx, lly, urx, ury));
+ put(PdfName.CONTENTS, content);
+ }
+
+/**
+ * Constructs a new PdfAnnotation
of subtype link (Action).
+ * @param writer
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @param action
+ */
+
+ public PdfAnnotation(PdfWriter writer, float llx, float lly, float urx, float ury, PdfAction action) {
+ this.writer = writer;
+ put(PdfName.SUBTYPE, PdfName.LINK);
+ put(PdfName.RECT, new PdfRectangle(llx, lly, urx, ury));
+ put(PdfName.A, action);
+ put(PdfName.BORDER, new PdfBorderArray(0, 0, 0));
+ put(PdfName.C, new PdfColor(0x00, 0x00, 0xFF));
+ }
+
+ /**
+ * Creates a screen PdfAnnotation
+ * @param writer
+ * @param rect
+ * @param clipTitle
+ * @param fs
+ * @param mimeType
+ * @param playOnDisplay
+ * @return a screen PdfAnnotation
+ * @throws IOException
+ */
+ public static PdfAnnotation createScreen(PdfWriter writer, Rectangle rect, String clipTitle, PdfFileSpecification fs,
+ String mimeType, boolean playOnDisplay) throws IOException {
+ PdfAnnotation ann = new PdfAnnotation(writer, rect);
+ ann.put(PdfName.SUBTYPE, PdfName.SCREEN);
+ ann.put (PdfName.F, new PdfNumber(FLAGS_PRINT));
+ ann.put(PdfName.TYPE, PdfName.ANNOT);
+ ann.setPage();
+ PdfIndirectReference ref = ann.getIndirectReference();
+ PdfAction action = PdfAction.rendition(clipTitle,fs,mimeType, ref);
+ PdfIndirectReference actionRef = writer.addToBody(action).getIndirectReference();
+ // for play on display add trigger event
+ if (playOnDisplay)
+ {
+ PdfDictionary aa = new PdfDictionary();
+ aa.put(new PdfName("PV"), actionRef);
+ ann.put(PdfName.AA, aa);
+ }
+ ann.put(PdfName.A, actionRef);
+ return ann;
+ }
+
+ PdfIndirectReference getIndirectReference() {
+ if (reference == null) {
+ reference = writer.getPdfIndirectReference();
+ }
+ return reference;
+ }
+
+ /**
+ * @param writer
+ * @param rect
+ * @param title
+ * @param contents
+ * @param open
+ * @param icon
+ * @return a PdfAnnotation
+ */
+ public static PdfAnnotation createText(PdfWriter writer, Rectangle rect, String title, String contents, boolean open, String icon) {
+ PdfAnnotation annot = new PdfAnnotation(writer, rect);
+ annot.put(PdfName.SUBTYPE, PdfName.TEXT);
+ if (title != null)
+ annot.put(PdfName.T, new PdfString(title, PdfObject.TEXT_UNICODE));
+ if (contents != null)
+ annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+ if (open)
+ annot.put(PdfName.OPEN, PdfBoolean.PDFTRUE);
+ if (icon != null) {
+ annot.put(PdfName.NAME, new PdfName(icon));
+ }
+ return annot;
+ }
+
+ /**
+ * Creates a link.
+ * @param writer
+ * @param rect
+ * @param highlight
+ * @return A PdfAnnotation
+ */
+ protected static PdfAnnotation createLink(PdfWriter writer, Rectangle rect, PdfName highlight) {
+ PdfAnnotation annot = new PdfAnnotation(writer, rect);
+ annot.put(PdfName.SUBTYPE, PdfName.LINK);
+ if (!highlight.equals(HIGHLIGHT_INVERT))
+ annot.put(PdfName.H, highlight);
+ return annot;
+ }
+
+ /**
+ * Creates an Annotation with an Action.
+ * @param writer
+ * @param rect
+ * @param highlight
+ * @param action
+ * @return A PdfAnnotation
+ */
+ public static PdfAnnotation createLink(PdfWriter writer, Rectangle rect, PdfName highlight, PdfAction action) {
+ PdfAnnotation annot = createLink(writer, rect, highlight);
+ annot.putEx(PdfName.A, action);
+ return annot;
+ }
+
+ /**
+ * Creates an Annotation with an local destination.
+ * @param writer
+ * @param rect
+ * @param highlight
+ * @param namedDestination
+ * @return A PdfAnnotation
+ */
+ public static PdfAnnotation createLink(PdfWriter writer, Rectangle rect, PdfName highlight, String namedDestination) {
+ PdfAnnotation annot = createLink(writer, rect, highlight);
+ annot.put(PdfName.DEST, new PdfString(namedDestination));
+ return annot;
+ }
+
+ /**
+ * Creates an Annotation with a PdfDestination.
+ * @param writer
+ * @param rect
+ * @param highlight
+ * @param page
+ * @param dest
+ * @return A PdfAnnotation
+ */
+ public static PdfAnnotation createLink(PdfWriter writer, Rectangle rect, PdfName highlight, int page, PdfDestination dest) {
+ PdfAnnotation annot = createLink(writer, rect, highlight);
+ PdfIndirectReference ref = writer.getPageReference(page);
+ dest.addPage(ref);
+ annot.put(PdfName.DEST, dest);
+ return annot;
+ }
+
+ /**
+ * Add some free text to the document.
+ * @param writer
+ * @param rect
+ * @param contents
+ * @param defaultAppearance
+ * @return A PdfAnnotation
+ */
+ public static PdfAnnotation createFreeText(PdfWriter writer, Rectangle rect, String contents, PdfContentByte defaultAppearance) {
+ PdfAnnotation annot = new PdfAnnotation(writer, rect);
+ annot.put(PdfName.SUBTYPE, PdfName.FREETEXT);
+ annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+ annot.setDefaultAppearanceString(defaultAppearance);
+ return annot;
+ }
+
+ /**
+ * Adds a line to the document. Move over the line and a tooltip is shown.
+ * @param writer
+ * @param rect
+ * @param contents
+ * @param x1
+ * @param y1
+ * @param x2
+ * @param y2
+ * @return A PdfAnnotation
+ */
+ public static PdfAnnotation createLine(PdfWriter writer, Rectangle rect, String contents, float x1, float y1, float x2, float y2) {
+ PdfAnnotation annot = new PdfAnnotation(writer, rect);
+ annot.put(PdfName.SUBTYPE, PdfName.LINE);
+ annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+ PdfArray array = new PdfArray(new PdfNumber(x1));
+ array.add(new PdfNumber(y1));
+ array.add(new PdfNumber(x2));
+ array.add(new PdfNumber(y2));
+ annot.put(PdfName.L, array);
+ return annot;
+ }
+
+ /**
+ * Adds a circle or a square that shows a tooltip when you pass over it.
+ * @param writer
+ * @param rect
+ * @param contents The tooltip
+ * @param square true if you want a square, false if you want a circle
+ * @return A PdfAnnotation
+ */
+ public static PdfAnnotation createSquareCircle(PdfWriter writer, Rectangle rect, String contents, boolean square) {
+ PdfAnnotation annot = new PdfAnnotation(writer, rect);
+ if (square)
+ annot.put(PdfName.SUBTYPE, PdfName.SQUARE);
+ else
+ annot.put(PdfName.SUBTYPE, PdfName.CIRCLE);
+ annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+ return annot;
+ }
+
+ public static PdfAnnotation createMarkup(PdfWriter writer, Rectangle rect, String contents, int type, float quadPoints[]) {
+ PdfAnnotation annot = new PdfAnnotation(writer, rect);
+ PdfName name = PdfName.HIGHLIGHT;
+ switch (type) {
+ case MARKUP_UNDERLINE:
+ name = PdfName.UNDERLINE;
+ break;
+ case MARKUP_STRIKEOUT:
+ name = PdfName.STRIKEOUT;
+ break;
+ }
+ annot.put(PdfName.SUBTYPE, name);
+ annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+ PdfArray array = new PdfArray();
+ for (int k = 0; k < quadPoints.length; ++k)
+ array.add(new PdfNumber(quadPoints[k]));
+ annot.put(PdfName.QUADPOINTS, array);
+ return annot;
+ }
+
+ /**
+ * Adds a Stamp to your document. Move over the stamp and a tooltip is shown
+ * @param writer
+ * @param rect
+ * @param contents
+ * @param name
+ * @return A PdfAnnotation
+ */
+ public static PdfAnnotation createStamp(PdfWriter writer, Rectangle rect, String contents, String name) {
+ PdfAnnotation annot = new PdfAnnotation(writer, rect);
+ annot.put(PdfName.SUBTYPE, PdfName.STAMP);
+ annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+ annot.put(PdfName.NAME, new PdfName(name));
+ return annot;
+ }
+
+ public static PdfAnnotation createInk(PdfWriter writer, Rectangle rect, String contents, float inkList[][]) {
+ PdfAnnotation annot = new PdfAnnotation(writer, rect);
+ annot.put(PdfName.SUBTYPE, PdfName.INK);
+ annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+ PdfArray outer = new PdfArray();
+ for (int k = 0; k < inkList.length; ++k) {
+ PdfArray inner = new PdfArray();
+ float deep[] = inkList[k];
+ for (int j = 0; j < deep.length; ++j)
+ inner.add(new PdfNumber(deep[j]));
+ outer.add(inner);
+ }
+ annot.put(PdfName.INKLIST, outer);
+ return annot;
+ }
+
+ /** Creates a file attachment annotation.
+ * @param writer the PdfWriter
+ * @param rect the dimensions in the page of the annotation
+ * @param contents the file description
+ * @param fileStore an array with the file. If it's null
+ * the file will be read from the disk
+ * @param file the path to the file. It will only be used if
+ * fileStore
is not null
+ * @param fileDisplay the actual file name stored in the pdf
+ * @throws IOException on error
+ * @return the annotation
+ */
+ public static PdfAnnotation createFileAttachment(PdfWriter writer, Rectangle rect, String contents, byte fileStore[], String file, String fileDisplay) throws IOException {
+ return createFileAttachment(writer, rect, contents, PdfFileSpecification.fileEmbedded(writer, file, fileDisplay, fileStore));
+ }
+
+ /** Creates a file attachment annotation
+ * @param writer
+ * @param rect
+ * @param contents
+ * @param fs
+ * @return the annotation
+ * @throws IOException
+ */
+ public static PdfAnnotation createFileAttachment(PdfWriter writer, Rectangle rect, String contents, PdfFileSpecification fs) throws IOException {
+ PdfAnnotation annot = new PdfAnnotation(writer, rect);
+ annot.put(PdfName.SUBTYPE, PdfName.FILEATTACHMENT);
+ annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+ annot.put(PdfName.FS, fs.getReference());
+ return annot;
+ }
+
+ /**
+ * Adds a popup to your document.
+ * @param writer
+ * @param rect
+ * @param contents
+ * @param open
+ * @return A PdfAnnotation
+ */
+ public static PdfAnnotation createPopup(PdfWriter writer, Rectangle rect, String contents, boolean open) {
+ PdfAnnotation annot = new PdfAnnotation(writer, rect);
+ annot.put(PdfName.SUBTYPE, PdfName.POPUP);
+ if (contents != null)
+ annot.put(PdfName.CONTENTS, new PdfString(contents, PdfObject.TEXT_UNICODE));
+ if (open)
+ annot.put(PdfName.OPEN, PdfBoolean.PDFTRUE);
+ return annot;
+ }
+
+ public void setDefaultAppearanceString(PdfContentByte cb) {
+ byte b[] = cb.getInternalBuffer().toByteArray();
+ int len = b.length;
+ for (int k = 0; k < len; ++k) {
+ if (b[k] == '\n')
+ b[k] = 32;
+ }
+ put(PdfName.DA, new PdfString( b, PdfObject.NOTHING )); // ssteward: added encoding
+ }
+
+ public void setFlags(int flags) {
+ if (flags == 0)
+ remove(PdfName.F);
+ else
+ put(PdfName.F, new PdfNumber(flags));
+ }
+
+ public void setBorder(PdfBorderArray border) {
+ putDel(PdfName.BORDER, border);
+ }
+
+ public void setBorderStyle(PdfBorderDictionary border) {
+ putDel(PdfName.BS, border);
+ }
+
+ /**
+ * Sets the annotation's highlighting mode. The values can be
+ * HIGHLIGHT_NONE
, HIGHLIGHT_INVERT
,
+ * HIGHLIGHT_OUTLINE
and HIGHLIGHT_PUSH
;
+ * @param highlight the annotation's highlighting mode
+ */
+ public void setHighlighting(PdfName highlight) {
+ if (highlight.equals(HIGHLIGHT_INVERT))
+ remove(PdfName.H);
+ else
+ put(PdfName.H, highlight);
+ }
+
+ public void setAppearance(PdfName ap, PdfTemplate template) {
+ PdfDictionary dic = (PdfDictionary)get(PdfName.AP);
+ if (dic == null)
+ dic = new PdfDictionary();
+ dic.put(ap, template.getIndirectReference());
+ put(PdfName.AP, dic);
+ if (!form)
+ return;
+ if (templates == null)
+ templates = new HashMap();
+ templates.put(template, null);
+ }
+
+ public void setAppearance(PdfName ap, String state, PdfTemplate template) {
+ PdfDictionary dicAp = (PdfDictionary)get(PdfName.AP);
+ if (dicAp == null)
+ dicAp = new PdfDictionary();
+
+ PdfDictionary dic;
+ PdfObject obj = dicAp.get(ap);
+ if (obj != null && obj.isDictionary())
+ dic = (PdfDictionary)obj;
+ else
+ dic = new PdfDictionary();
+ dic.put(new PdfName(state), template.getIndirectReference());
+ dicAp.put(ap, dic);
+ put(PdfName.AP, dicAp);
+ if (!form)
+ return;
+ if (templates == null)
+ templates = new HashMap();
+ templates.put(template, null);
+ }
+
+ public void setAppearanceState(String state) {
+ if (state == null) {
+ remove(PdfName.AS);
+ return;
+ }
+ put(PdfName.AS, new PdfName(state));
+ }
+
+ public void setColor(Color color) {
+ putDel(PdfName.C, new PdfColor(color));
+ }
+
+ public void setTitle(String title) {
+ if (title == null) {
+ remove(PdfName.T);
+ return;
+ }
+ put(PdfName.T, new PdfString(title, PdfObject.TEXT_UNICODE));
+ }
+
+ public void setPopup(PdfAnnotation popup) {
+ put(PdfName.POPUP, popup.getIndirectReference());
+ popup.put(PdfName.PARENT, getIndirectReference());
+ }
+
+ public void setAction(PdfAction action) {
+ putDel(PdfName.A, action);
+ }
+
+ public void setAdditionalActions(PdfName key, PdfAction action) {
+ PdfDictionary dic;
+ PdfObject obj = get(PdfName.AA);
+ if (obj != null && obj.isDictionary())
+ dic = (PdfDictionary)obj;
+ else
+ dic = new PdfDictionary();
+ dic.put(key, action);
+ put(PdfName.AA, dic);
+ }
+
+ /** Getter for property used.
+ * @return Value of property used.
+ */
+ public boolean isUsed() {
+ return used;
+ }
+
+ /** Setter for property used.
+ */
+ void setUsed() {
+ used = true;
+ }
+
+ HashMap getTemplates() {
+ return templates;
+ }
+
+ /** Getter for property form.
+ * @return Value of property form.
+ */
+ public boolean isForm() {
+ return form;
+ }
+
+ /** Getter for property annotation.
+ * @return Value of property annotation.
+ */
+ public boolean isAnnotation() {
+ return annotation;
+ }
+
+ public void setPage(int page) {
+ put(PdfName.P, writer.getPageReference(page));
+ }
+
+ public void setPage() {
+ put(PdfName.P, writer.getCurrentPage());
+ }
+
+ /** Getter for property placeInPage.
+ * @return Value of property placeInPage.
+ */
+ public int getPlaceInPage() {
+ return placeInPage;
+ }
+
+ /** Places the annotation in a specified page that must be greater
+ * or equal to the current one. With PdfStamper
the page
+ * can be any. The first page is 1.
+ * @param placeInPage New value of property placeInPage.
+ */
+ public void setPlaceInPage(int placeInPage) {
+ this.placeInPage = placeInPage;
+ }
+
+ public void setRotate(int v) {
+ put(PdfName.ROTATE, new PdfNumber(v));
+ }
+
+ PdfDictionary getMK() {
+ PdfDictionary mk = (PdfDictionary)get(PdfName.MK);
+ if (mk == null) {
+ mk = new PdfDictionary();
+ put(PdfName.MK, mk);
+ }
+ return mk;
+ }
+
+ public void setMKRotation(int rotation) {
+ getMK().put(PdfName.R, new PdfNumber(rotation));
+ }
+
+ public static PdfArray getMKColor(Color color) {
+ PdfArray array = new PdfArray();
+ int type = ExtendedColor.getType(color);
+ switch (type) {
+ case ExtendedColor.TYPE_GRAY: {
+ array.add(new PdfNumber(((GrayColor)color).getGray()));
+ break;
+ }
+ case ExtendedColor.TYPE_CMYK: {
+ CMYKColor cmyk = (CMYKColor)color;
+ array.add(new PdfNumber(cmyk.getCyan()));
+ array.add(new PdfNumber(cmyk.getMagenta()));
+ array.add(new PdfNumber(cmyk.getYellow()));
+ array.add(new PdfNumber(cmyk.getBlack()));
+ break;
+ }
+ case ExtendedColor.TYPE_SEPARATION:
+ case ExtendedColor.TYPE_PATTERN:
+ case ExtendedColor.TYPE_SHADING:
+ throw new RuntimeException("Separations, patterns and shadings are not allowed in MK dictionary.");
+ default:
+ array.add(new PdfNumber(color.getRed() / 255f));
+ array.add(new PdfNumber(color.getGreen() / 255f));
+ array.add(new PdfNumber(color.getBlue() / 255f));
+ }
+ return array;
+ }
+
+ public void setMKBorderColor(Color color) {
+ if (color == null)
+ getMK().remove(PdfName.BC);
+ else
+ getMK().put(PdfName.BC, getMKColor(color));
+ }
+
+ public void setMKBackgroundColor(Color color) {
+ if (color == null)
+ getMK().remove(PdfName.BG);
+ else
+ getMK().put(PdfName.BG, getMKColor(color));
+ }
+
+ public void setMKNormalCaption(String caption) {
+ getMK().put(PdfName.CA, new PdfString(caption, PdfObject.TEXT_UNICODE));
+ }
+
+ public void setMKRolloverCaption(String caption) {
+ getMK().put(PdfName.RC, new PdfString(caption, PdfObject.TEXT_UNICODE));
+ }
+
+ public void setMKAlternateCaption(String caption) {
+ getMK().put(PdfName.AC, new PdfString(caption, PdfObject.TEXT_UNICODE));
+ }
+
+ public void setMKNormalIcon(PdfTemplate template) {
+ getMK().put(PdfName.I, template.getIndirectReference());
+ }
+
+ public void setMKRolloverIcon(PdfTemplate template) {
+ getMK().put(PdfName.RI, template.getIndirectReference());
+ }
+
+ public void setMKAlternateIcon(PdfTemplate template) {
+ getMK().put(PdfName.IX, template.getIndirectReference());
+ }
+
+ public void setMKIconFit(PdfName scale, PdfName scalingType, float leftoverLeft, float leftoverBottom, boolean fitInBounds) {
+ PdfDictionary dic = new PdfDictionary();
+ if (!scale.equals(PdfName.A))
+ dic.put(PdfName.SW, scale);
+ if (!scalingType.equals(PdfName.P))
+ dic.put(PdfName.S, scalingType);
+ if (leftoverLeft != 0.5f || leftoverBottom != 0.5f) {
+ PdfArray array = new PdfArray(new PdfNumber(leftoverLeft));
+ array.add(new PdfNumber(leftoverBottom));
+ dic.put(PdfName.A, array);
+ }
+ if (fitInBounds)
+ dic.put(PdfName.FB, PdfBoolean.PDFTRUE);
+ getMK().put(PdfName.IF, dic);
+ }
+
+ public void setMKTextPosition(int tp) {
+ getMK().put(PdfName.TP, new PdfNumber(tp));
+ }
+
+ /**
+ * Sets the layer this annotation belongs to.
+ * @param layer the layer this annotation belongs to
+ */
+ public void setLayer(PdfOCG layer) {
+ put(PdfName.OC, layer.getRef());
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfAppearance.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfAppearance.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfAppearance.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfAppearance.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,142 @@
+/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import pdftk.com.lowagie.text.Rectangle;
+import java.util.HashMap;
+
+/**
+ * Implements the appearance stream to be used with form fields..
+ */
+
+public class PdfAppearance extends PdfTemplate {
+
+ public static final HashMap stdFieldFontNames = new HashMap();
+ static {
+ stdFieldFontNames.put("Courier-BoldOblique", new PdfName("CoBO"));
+ stdFieldFontNames.put("Courier-Bold", new PdfName("CoBo"));
+ stdFieldFontNames.put("Courier-Oblique", new PdfName("CoOb"));
+ stdFieldFontNames.put("Courier", new PdfName("Cour"));
+ stdFieldFontNames.put("Helvetica-BoldOblique", new PdfName("HeBO"));
+ stdFieldFontNames.put("Helvetica-Bold", new PdfName("HeBo"));
+ stdFieldFontNames.put("Helvetica-Oblique", new PdfName("HeOb"));
+ stdFieldFontNames.put("Helvetica", new PdfName("Helv"));
+ stdFieldFontNames.put("Symbol", new PdfName("Symb"));
+ stdFieldFontNames.put("Times-BoldItalic", new PdfName("TiBI"));
+ stdFieldFontNames.put("Times-Bold", new PdfName("TiBo"));
+ stdFieldFontNames.put("Times-Italic", new PdfName("TiIt"));
+ stdFieldFontNames.put("Times-Roman", new PdfName("TiRo"));
+ stdFieldFontNames.put("ZapfDingbats", new PdfName("ZaDb"));
+ stdFieldFontNames.put("HYSMyeongJo-Medium", new PdfName("HySm"));
+ stdFieldFontNames.put("HYGoThic-Medium", new PdfName("HyGo"));
+ stdFieldFontNames.put("HeiseiKakuGo-W5", new PdfName("KaGo"));
+ stdFieldFontNames.put("HeiseiMin-W3", new PdfName("KaMi"));
+ stdFieldFontNames.put("MHei-Medium", new PdfName("MHei"));
+ stdFieldFontNames.put("MSung-Light", new PdfName("MSun"));
+ stdFieldFontNames.put("STSong-Light", new PdfName("STSo"));
+ stdFieldFontNames.put("MSungStd-Light", new PdfName("MSun"));
+ stdFieldFontNames.put("STSongStd-Light", new PdfName("STSo"));
+ stdFieldFontNames.put("HYSMyeongJoStd-Medium", new PdfName("HySm"));
+ stdFieldFontNames.put("KozMinPro-Regular", new PdfName("KaMi"));
+ }
+
+ /**
+ *Creates a PdfAppearance
.
+ */
+
+ PdfAppearance() {
+ super();
+ separator = ' ';
+ }
+
+ PdfAppearance(PdfIndirectReference iref) {
+ thisReference = iref;
+ }
+
+ /**
+ * Creates new PdfTemplate
+ *
+ * @param wr the PdfWriter
+ */
+
+ PdfAppearance(PdfWriter wr) {
+ super(wr);
+ separator = ' ';
+ }
+
+ /**
+ * Set the font and the size for the subsequent text writing.
+ *
+ * @param bf the font
+ * @param size the font size in points
+ */
+ public void setFontAndSize(BaseFont bf, float size) {
+ checkWriter();
+ state.size = size;
+ if (bf.getFontType() == BaseFont.FONT_TYPE_DOCUMENT) {
+ state.fontDetails = new FontDetails(null, ((DocumentFont)bf).getIndirectReference(), bf);
+ }
+ else
+ state.fontDetails = writer.addSimple(bf);
+ PdfName psn = (PdfName)stdFieldFontNames.get(bf.getPostscriptFontName());
+ if (psn == null) {
+ psn = new PdfName(bf.getPostscriptFontName());
+ bf.setSubset(false);
+ }
+ PageResources prs = getPageResources();
+// PdfName name = state.fontDetails.getFontName();
+ prs.addFont(psn, state.fontDetails.getIndirectReference());
+ content.append(psn.getBytes()).append(' ').append(size).append(" Tf").append_i(separator);
+ }
+
+ public PdfContentByte getDuplicate() {
+ PdfAppearance tpl = new PdfAppearance();
+ tpl.writer = writer;
+ tpl.pdf = pdf;
+ tpl.thisReference = thisReference;
+ tpl.pageResources = pageResources;
+ tpl.bBox = new Rectangle(bBox);
+ tpl.group = group;
+ tpl.layer = layer;
+ if (matrix != null) {
+ tpl.matrix = new PdfArray(matrix);
+ }
+ tpl.separator = separator;
+ return tpl;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfArray.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfArray.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfArray.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfArray.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,496 @@
+/*
+ * $Id: PdfArray.java,v 1.37 2003/05/02 09:01:13 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.ListIterator;
+
+/**
+ * PdfArray
is the PDF Array object.
+ *
+ * An array is a sequence of PDF objects. An array may contain a mixture of object types.
+ * An array is written as a left square bracket ([), followed by a sequence of objects,
+ * followed by a right square bracket (]).
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.6 (page 40).
+ *
+ * @see PdfObject
+ */
+
+public class PdfArray extends PdfObject {
+
+ // membervariables
+
+/** this is the actual array of PdfObjects */
+ protected ArrayList arrayList;
+
+ // constructors
+
+/**
+ * Constructs an empty PdfArray
-object.
+ */
+
+ public PdfArray() {
+ super(ARRAY);
+ arrayList = new ArrayList();
+ }
+
+/**
+ * Constructs an PdfArray
-object, containing 1 PdfObject
.
+ *
+ * @param object a PdfObject
that has to be added to the array
+ */
+
+ public PdfArray(PdfObject object) {
+ super(ARRAY);
+ arrayList = new ArrayList();
+ arrayList.add(object);
+ }
+
+ public PdfArray(float values[]) {
+ super(ARRAY);
+ arrayList = new ArrayList();
+ add(values);
+ }
+
+ public PdfArray(int values[]) {
+ super(ARRAY);
+ arrayList = new ArrayList();
+ add(values);
+ }
+
+ /**
+ * Constructs a PdfArray
, containing all elements of a
+ * specified ArrayList
.
+ *
+ * @param l an ArrayList
with PdfObject
s to be
+ * added to the array
+ * @throws ClassCastException if the ArrayList
contains
+ * something that isn't a PdfObject
+ * @since 2.1.3
+ */
+ public PdfArray(ArrayList l) {
+ this();
+ for (Iterator i = l.iterator(); i.hasNext(); )
+ add((PdfObject)i.next());
+ }
+
+/**
+ * Constructs an PdfArray
-object, containing all the PdfObject
s in a given PdfArray
.
+ *
+ * @param array a PdfArray
that has to be added to the array
+ */
+
+ public PdfArray(PdfArray array) {
+ super(ARRAY);
+ arrayList = new ArrayList(array.getArrayList());
+ }
+
+ // methods overriding some methods in PdfObject
+
+/**
+ * Returns the PDF representation of this PdfArray
.
+ *
+ * @return an array of byte
s
+ */
+
+ public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+ os.write('[');
+
+ Iterator i = arrayList.iterator();
+ PdfObject object;
+ // int type = 0; // ssteward
+ if (i.hasNext()) {
+ object = (PdfObject) i.next();
+ object.toPdf(writer, os);
+ }
+ while (i.hasNext()) {
+ object = (PdfObject) i.next();
+ // ssteward
+ //type = object.type();
+ //if (type != PdfObject.ARRAY && type != PdfObject.DICTIONARY && type != PdfObject.NAME && type != PdfObject.STRING)
+ os.write(' ');
+ object.toPdf(writer, os);
+ }
+ os.write(']');
+ }
+
+ /**
+ * Returns a string representation of this PdfArray
.
+ *
+ * The string representation consists of a list of all
+ * PdfObject
s contained in this PdfArray
,
+ * enclosed in square brackets ("[]"). Adjacent elements are separated
+ * by the characters ", " (comma and space).
+ *
+ * @return the string representation of this PdfArray
+ */
+ public String toString() {
+ return arrayList.toString();
+ }
+
+ // methods concerning the ArrayList-membervalue
+
+ /**
+ * Overwrites a specified location of the array, returning the previous
+ * value
+ *
+ * @param idx The index of the element to be overwritten
+ * @param obj new value for the specified index
+ * @throws IndexOutOfBoundsException if the specified position doesn't exist
+ * @return the previous value
+ * @since 2.1.5
+ */
+ public PdfObject set(int idx, PdfObject obj) {
+ return (PdfObject) arrayList.set(idx, obj);
+ }
+
+ /**
+ * Remove the element at the specified position from the array.
+ *
+ * Shifts any subsequent elements to the left (subtracts one from their
+ * indices).
+ *
+ * @param idx The index of the element to be removed.
+ * @throws IndexOutOfBoundsException the specified position doesn't exist
+ * @since 2.1.5
+ */
+ public PdfObject remove(int idx) {
+ return (PdfObject) arrayList.remove(idx);
+ }
+
+/**
+ * Returns an ArrayList containing PdfObject
s.
+ *
+ * @return an ArrayList
+ */
+
+ public ArrayList getArrayList() {
+ return arrayList;
+ }
+
+/**
+ * Returns the number of entries in the array.
+ *
+ * @return the size of the ArrayList
+ */
+
+ public int size() {
+ return arrayList.size();
+ }
+
+ /**
+ * Returns true
if the array is empty.
+ *
+ * @return true
if the array is empty
+ * @since 2.1.5
+ */
+ public boolean isEmpty() {
+ return arrayList.isEmpty();
+ }
+
+/**
+ * Adds a PdfObject
to the PdfArray
.
+ *
+ * @param object PdfObject
to add
+ * @return true
+ */
+
+ public boolean add(PdfObject object) {
+ return arrayList.add(object);
+ }
+
+ public boolean add(float values[]) {
+ for (int k = 0; k < values.length; ++k)
+ arrayList.add(new PdfNumber(values[k]));
+ return true;
+ }
+
+ public boolean add(int values[]) {
+ for (int k = 0; k < values.length; ++k)
+ arrayList.add(new PdfNumber(values[k]));
+ return true;
+ }
+
+ /**
+ * Inserts the specified element at the specified position.
+ *
+ * Shifts the element currently at that position (if any) and
+ * any subsequent elements to the right (adds one to their indices).
+ *
+ * @param index The index at which the specified element is to be inserted
+ * @param element The element to be inserted
+ * @throws IndexOutOfBoundsException if the specified index is larger than the
+ * last position currently set, plus 1.
+ * @since 2.1.5
+ */
+ public void add(int index, PdfObject element) {
+ arrayList.add(index, element);
+ }
+
+/**
+ * Adds a PdfObject
to the PdfArray
.
+ *
+ * The newly added object will be the first element in the ArrayList
.
+ *
+ * @param object PdfObject
to add
+ */
+
+ public void addFirst(PdfObject object) {
+ arrayList.add(0, object);
+ }
+
+/**
+ * Checks if the PdfArray
already contains a certain PdfObject
.
+ *
+ * @param object PdfObject
to check
+ * @return true
+ */
+
+ public boolean contains(PdfObject object) {
+ return arrayList.contains(object);
+ }
+
+ public ListIterator listIterator() {
+ return arrayList.listIterator();
+ }
+
+ /**
+ * Returns the PdfObject
with the specified index.
+ *
+ * A possible indirect references is not resolved, so the returned
+ * PdfObject
may be either a direct object or an indirect
+ * reference, depending on how the object is stored in the
+ * PdfArray
.
+ *
+ * @param idx The index of the PdfObject
to be returned
+ * @return A PdfObject
+ */
+ public PdfObject getPdfObject(int idx) {
+ return (PdfObject)arrayList.get(idx);
+ }
+
+ /**
+ * Returns the PdfObject
with the specified index, resolving
+ * a possible indirect reference to a direct object.
+ *
+ * Thus this method will never return a PdfIndirectReference
+ * object.
+ *
+ * @param idx The index of the PdfObject
to be returned
+ * @return A direct PdfObject
or null
+ */
+ public PdfObject getDirectObject(int idx) {
+ return PdfReader.getPdfObject(getPdfObject(idx));
+ }
+
+ // DOWNCASTING GETTERS
+ // @author Mark A Storer (2/17/06)
+
+ /**
+ * Returns a PdfObject
as a PdfDictionary
,
+ * resolving indirect references.
+ *
+ * The object corresponding to the specified index is retrieved and
+ * resolvedto a direct object.
+ * If it is a PdfDictionary
, it is cast down and returned as such.
+ * Otherwise null
is returned.
+ *
+ * @param idx The index of the PdfObject
to be returned
+ * @return the corresponding PdfDictionary
object,
+ * or null
+ */
+ public PdfDictionary getAsDict(int idx) {
+ PdfDictionary dict = null;
+ PdfObject orig = getDirectObject(idx);
+ if (orig != null && orig.isDictionary())
+ dict = (PdfDictionary) orig;
+ return dict;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfArray
,
+ * resolving indirect references.
+ *
+ * The object corresponding to the specified index is retrieved and
+ * resolved to a direct object.
+ * If it is a PdfArray
, it is cast down and returned as such.
+ * Otherwise null
is returned.
+ *
+ * @param idx The index of the PdfObject
to be returned
+ * @return the corresponding PdfArray
object,
+ * or null
+ */
+ public PdfArray getAsArray(int idx) {
+ PdfArray array = null;
+ PdfObject orig = getDirectObject(idx);
+ if (orig != null && orig.isArray())
+ array = (PdfArray) orig;
+ return array;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfStream
,
+ * resolving indirect references.
+ *
+ * The object corresponding to the specified index is retrieved and
+ * resolved to a direct object.
+ * If it is a PdfStream
, it is cast down and returned as such.
+ * Otherwise null
is returned.
+ *
+ * @param idx The index of the PdfObject
to be returned
+ * @return the corresponding PdfStream
object,
+ * or null
+ */
+ public PdfStream getAsStream(int idx) {
+ PdfStream stream = null;
+ PdfObject orig = getDirectObject(idx);
+ if (orig != null && orig.isStream())
+ stream = (PdfStream) orig;
+ return stream;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfString
,
+ * resolving indirect references.
+ *
+ * The object corresponding to the specified index is retrieved and
+ * resolved to a direct object.
+ * If it is a PdfString
, it is cast down and returned as such.
+ * Otherwise null
is returned.
+ *
+ * @param idx The index of the PdfObject
to be returned
+ * @return the corresponding PdfString
object,
+ * or null
+ */
+ public PdfString getAsString(int idx) {
+ PdfString string = null;
+ PdfObject orig = getDirectObject(idx);
+ if (orig != null && orig.isString())
+ string = (PdfString) orig;
+ return string;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfNumber
,
+ * resolving indirect references.
+ *
+ * The object corresponding to the specified index is retrieved and
+ * resolved to a direct object.
+ * If it is a PdfNumber
, it is cast down and returned as such.
+ * Otherwise null
is returned.
+ *
+ * @param idx The index of the PdfObject
to be returned
+ * @return the corresponding PdfNumber
object,
+ * or null
+ */
+ public PdfNumber getAsNumber(int idx) {
+ PdfNumber number = null;
+ PdfObject orig = getDirectObject(idx);
+ if (orig != null && orig.isNumber())
+ number = (PdfNumber) orig;
+ return number;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfName
,
+ * resolving indirect references.
+ *
+ * The object corresponding to the specified index is retrieved and
+ * resolved to a direct object.
+ * If it is a PdfName
, it is cast down and returned as such.
+ * Otherwise null
is returned.
+ *
+ * @param idx The index of the PdfObject
to be returned
+ * @return the corresponding PdfName
object,
+ * or null
+ */
+ public PdfName getAsName(int idx) {
+ PdfName name = null;
+ PdfObject orig = getDirectObject(idx);
+ if (orig != null && orig.isName())
+ name = (PdfName) orig;
+ return name;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfBoolean
,
+ * resolving indirect references.
+ *
+ * The object corresponding to the specified index is retrieved and
+ * resolved to a direct object.
+ * If it is a PdfBoolean
, it is cast down and returned as
+ * such. Otherwise null
is returned.
+ *
+ * @param idx The index of the PdfObject
to be returned
+ * @return the corresponding PdfBoolean
object,
+ * or null
+ */
+ public PdfBoolean getAsBoolean(int idx) {
+ PdfBoolean bool = null;
+ PdfObject orig = getDirectObject(idx);
+ if (orig != null && orig.isBoolean())
+ bool = (PdfBoolean) orig;
+ return bool;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfIndirectReference
.
+ *
+ * The object corresponding to the specified index is retrieved.
+ * If it is a PdfIndirectReference
, it is cast down and
+ * returned as such. Otherwise null
is returned.
+ *
+ * @param idx The index of the PdfObject
to be returned
+ * @return the corresponding PdfIndirectReference
object,
+ * or null
+ */
+ public PdfIndirectReference getAsIndirectObject(int idx) {
+ PdfIndirectReference ref = null;
+ PdfObject orig = getPdfObject(idx); // not getDirect this time.
+ if (orig != null && orig.isIndirect())
+ ref = (PdfIndirectReference) orig;
+ return ref;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfBarcode.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfBarcode.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfBarcode.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfBarcode.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,215 @@
+/*
+ * $Id: PdfBarcode.java,v 1.16 2002/06/20 13:28:22 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+
+/**
+ * A barcode is a Chunk with a certain type of barcode font.
+ *
+ * With this class you can construct several types of barcode
+ * in different sizes, representing any 'product' or 'article' number.
+ */
+
+public class PdfBarcode extends pdftk.com.lowagie.text.Chunk {
+
+ /** This is a type of barcode. */
+ public static final int CODE39 = 1;
+
+ /** This is a type of barcode. */
+ public static final int UPCA = 2;
+
+ /** This is a type of barcode. */
+ public static final int EAN13 = 3;
+
+ /** This is a type of barcode. */
+ public static final int INTERLEAVED_2_OF_5 = 4;
+
+ /** The variable parity table in EAN 13 */
+ public static final int[][] variableParity =
+ { {0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2},
+ {0, 0, 1, 0, 1, 1, 2, 2, 2, 2, 2, 2},
+ {0, 0, 1, 1, 0, 1, 2, 2, 2, 2, 2, 2},
+ {0, 0, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2},
+ {0, 1, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2},
+ {0, 1, 1, 0, 0, 1, 2, 2, 2, 2, 2, 2},
+ {0, 1, 1, 1, 0, 0, 2, 2, 2, 2, 2, 2},
+ {0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 2, 2},
+ {0, 1, 0, 1, 1, 0, 2, 2, 2, 2, 2, 2},
+ {0, 1, 1, 0, 1, 0, 2, 2, 2, 2, 2, 2} };
+
+ /**
+ * Creates a new Barcode.
+ *
+ * @param ttf the ttf file representing the barcode font
+ * @param size the size of the barcode
+ * @param number the number you want to convert to a barcode in String format
+ */
+
+ public PdfBarcode(String ttf, int type, int size, String number) throws pdftk.com.lowagie.text.BadElementException, pdftk.com.lowagie.text.DocumentException, java.io.IOException {
+ super(convertToCode(type, number), new pdftk.com.lowagie.text.Font(BaseFont.createFont(ttf, "winansi", true), size));
+ }
+
+ /**
+ * Creates a new Barcode.
+ *
+ * @param ttf the ttf file representing the barcode font
+ * @param size the size of the barcode
+ * @param number the number you want to convert to a barcode in long format
+ */
+
+ public PdfBarcode(String ttf, int type, int size, long number) throws pdftk.com.lowagie.text.BadElementException, pdftk.com.lowagie.text.DocumentException, java.io.IOException {
+ super(convertToCode(type, String.valueOf(number)), new pdftk.com.lowagie.text.Font(BaseFont.createFont(ttf, "winansi", true), size));
+ }
+
+ /**
+ * Converts a String representing a number to a barcode with a specific barcode font.
+ *
+ * @param type the type of barcode
+ * @param number the number you want to convert to a barcode in long format
+ */
+
+ private static String convertToCode(int type, String number) throws pdftk.com.lowagie.text.BadElementException {
+ StringBuffer code = new StringBuffer();
+ int length = number.length();
+ int digit;
+ int pos = 0;
+ try {
+ switch(type) {
+ case CODE39:
+ code.append('*');
+ while (pos < length) {
+ code.append(number.substring(pos, ++pos));
+ }
+ code.append('*');
+ break;
+ case UPCA:
+ if (length > 12) throw new pdftk.com.lowagie.text.BadElementException("An UPC-A barcode can only encode a 12 digit number (your number was " + number + ").");
+ number = addZero(number, 12);
+ digit = Integer.parseInt(number.substring(pos, ++pos));
+ code.append((char) (digit + 80));
+ while (pos < 6) {
+ digit = Integer.parseInt(number.substring(pos, ++pos));
+ code.append((char) (digit + 48));
+ }
+ code.append((char) 112);
+ while (pos < 11) {
+ digit = Integer.parseInt(number.substring(pos, ++pos));
+ code.append((char) (digit + 64));
+ }
+ digit = Integer.parseInt(number.substring(11));
+ code.append((char) (digit + 96));
+ break;
+ case EAN13:
+ if (length > 13) throw new pdftk.com.lowagie.text.BadElementException("An EAN-13 barcode can only encode a 13 digit number (your number was " + number + ").");
+ number = addZero(number, 13);
+ int firstdigit = Integer.parseInt(number.substring(pos, ++pos));
+ code.append((char) (firstdigit + 33));
+ digit = Integer.parseInt(number.substring(pos, ++pos));
+ code.append((char) (digit + 96));
+ while (pos < 7) {
+ digit = Integer.parseInt(number.substring(pos, ++pos));
+ code.append((char) (digit + 48 + 16 * variableParity[firstdigit][pos - 2]));
+ }
+ code.append((char) 124);
+ while (pos < 12) {
+ digit = Integer.parseInt(number.substring(pos, ++pos));
+ code.append((char) (digit + 48 + 16 * variableParity[firstdigit][pos - 2]));
+ }
+ digit = Integer.parseInt(number.substring(12));
+ code.append((char) (digit + 112));
+ break;
+ case INTERLEAVED_2_OF_5:
+ if (length % 2 == 1) {
+ number = addZero(number, length + 1);
+ }
+ code.append('(');
+ while (number.length() > 2) {
+ digit = Integer.parseInt(number.substring(0, 2));
+ code.append(convertInterleaved(digit));
+ pos += 2;
+ number = number.substring(2);
+ }
+ digit = Integer.parseInt(number);
+ code.append(convertInterleaved(digit));
+ code.append(')');
+ break;
+ default:
+ throw new pdftk.com.lowagie.text.BadElementException("This type of barcode is not supported yet: " + type);
+ }
+ }
+ catch(NumberFormatException nfe) {
+ throw new pdftk.com.lowagie.text.BadElementException("NumberFormatException at position " + pos + " in " + number + ": " + nfe.getMessage());
+ }
+ return code.toString();
+ }
+
+ /**
+ * Converts an int to a convert interleaved character.
+ */
+
+ private static char convertInterleaved(int digits) throws NumberFormatException {
+ int i;
+ if (digits < 50) {
+ i = 48;
+ }
+ else if (digits < 100) {
+ i = 142;
+ }
+ else {
+ throw new NumberFormatException(String.valueOf(digits));
+ }
+ return (char)(digits + i);
+ }
+
+ /**
+ * Adds leading zeros.
+ */
+
+ private static String addZero(String number, int length) {
+ StringBuffer buf = new StringBuffer();
+ int zeros = length - number.length();
+ for (int i = 0; i < zeros; i++) {
+ buf.append('0');
+ }
+ buf.append(number);
+ return buf.toString();
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfBoolean.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfBoolean.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfBoolean.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfBoolean.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,120 @@
+/*
+ * $Id: PdfBoolean.java,v 1.22 2002/06/20 13:28:22 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * PdfBoolean
is the boolean object represented by the keywords true or false .
+ *
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.2 (page 37).
+ *
+ * @see PdfObject
+ * @see BadPdfFormatException
+ */
+
+public class PdfBoolean extends PdfObject {
+
+ // static membervariables (possible values of a boolean object)
+ public static final PdfBoolean PDFTRUE = new PdfBoolean(true);
+ public static final PdfBoolean PDFFALSE = new PdfBoolean(false);
+/** A possible value of PdfBoolean
*/
+ public static final String TRUE = "true";
+
+/** A possible value of PdfBoolean
*/
+ public static final String FALSE = "false";
+
+ // membervariables
+
+/** the boolean value of this object */
+ private boolean value;
+
+ // constructors
+
+/**
+ * Constructs a PdfBoolean
-object.
+ *
+ * @param value the value of the new PdfObject
+ */
+
+ public PdfBoolean(boolean value) {
+ super(BOOLEAN);
+ if (value) {
+ setContent(TRUE);
+ }
+ else {
+ setContent(FALSE);
+ }
+ this.value = value;
+ }
+
+/**
+ * Constructs a PdfBoolean
-object.
+ *
+ * @param value the value of the new PdfObject
, represented as a String
+ *
+ * @throws BadPdfFormatException thrown if the value isn't 'true
' or 'false
'
+ */
+
+ public PdfBoolean(String value) throws BadPdfFormatException {
+ super(BOOLEAN, value);
+ if (value.equals(TRUE)) {
+ this.value = true;
+ }
+ else if (value.equals(FALSE)) {
+ this.value = false;
+ }
+ else {
+ throw new BadPdfFormatException("The value has to be 'true' of 'false', instead of '" + value + "'.");
+ }
+ }
+
+ // methods returning the value of this object
+
+/**
+ * Returns the primitive value of the PdfBoolean
-object.
+ *
+ * @return the actual value of the object.
+ */
+
+ public boolean booleanValue() {
+ return value;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfBorderArray.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfBorderArray.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfBorderArray.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfBorderArray.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,72 @@
+/*
+ * $Id: PdfBorderArray.java,v 1.23 2002/07/09 11:28:22 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * A PdfBorderArray
defines the border of a PdfAnnotation
.
+ *
+ * @see PdfArray
+ */
+
+public class PdfBorderArray extends PdfArray {
+
+ // constructors
+
+/**
+ * Constructs a new PdfBorderArray
.
+ */
+
+ public PdfBorderArray(float hRadius, float vRadius, float width) {
+ this(hRadius, vRadius, width, null);
+ }
+
+/**
+ * Constructs a new PdfBorderArray
.
+ */
+
+ public PdfBorderArray(float hRadius, float vRadius, float width, PdfDashPattern dash) {
+ super(new PdfNumber(hRadius));
+ add(new PdfNumber(vRadius));
+ add(new PdfNumber(width));
+ if (dash != null)
+ add(dash);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfBorderDictionary.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfBorderDictionary.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfBorderDictionary.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfBorderDictionary.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,90 @@
+/*
+ * $Id: PdfBorderDictionary.java,v 1.22 2002/06/20 13:28:20 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * A PdfBorderDictionary
define the appearance of a Border (Annotations).
+ *
+ * @see PdfDictionary
+ */
+
+public class PdfBorderDictionary extends PdfDictionary {
+
+ public static final int STYLE_SOLID = 0;
+ public static final int STYLE_DASHED = 1;
+ public static final int STYLE_BEVELED = 2;
+ public static final int STYLE_INSET = 3;
+ public static final int STYLE_UNDERLINE = 4;
+ // constructors
+
+/**
+ * Constructs a PdfBorderDictionary
.
+ */
+
+ public PdfBorderDictionary(float borderWidth, int borderStyle, PdfDashPattern dashes) {
+ put(PdfName.W, new PdfNumber(borderWidth));
+ switch (borderStyle) {
+ case STYLE_SOLID:
+ put(PdfName.S, PdfName.S);
+ break;
+ case STYLE_DASHED:
+ if (dashes != null)
+ put(PdfName.D, dashes);
+ put(PdfName.S, PdfName.D);
+ break;
+ case STYLE_BEVELED:
+ put(PdfName.S, PdfName.B);
+ break;
+ case STYLE_INSET:
+ put(PdfName.S, PdfName.I);
+ break;
+ case STYLE_UNDERLINE:
+ put(PdfName.S, PdfName.U);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid border style.");
+ }
+ }
+
+ public PdfBorderDictionary(float borderWidth, int borderStyle) {
+ this(borderWidth, borderStyle, null);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfChunk.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfChunk.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfChunk.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfChunk.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,784 @@
+/*
+ * $Id: PdfChunk.java,v 1.70 2004/12/20 11:39:08 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.awt.Color;
+
+import pdftk.com.lowagie.text.Chunk;
+import pdftk.com.lowagie.text.Font;
+//import pdftk.com.lowagie.text.Image; ssteward: dropped in 1.44
+import pdftk.com.lowagie.text.SplitCharacter;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * A PdfChunk
is the PDF translation of a Chunk
.
+ *
+ * A PdfChunk
is a PdfString
in a certain
+ * PdfFont
and Color
.
+ *
+ * @see PdfString
+ * @see PdfFont
+ * @see pdftk.com.lowagie.text.Chunk
+ * @see pdftk.com.lowagie.text.Font
+ */
+
+public class PdfChunk implements SplitCharacter{
+
+ private static final char singleSpace[] = {' '};
+ private static final PdfChunk thisChunk[] = new PdfChunk[1];
+ private static final float ITALIC_ANGLE = 0.21256f;
+/** The allowed attributes in variable attributes
. */
+ private static final HashMap keysAttributes = new HashMap();
+
+/** The allowed attributes in variable noStroke
. */
+ private static final HashMap keysNoStroke = new HashMap();
+
+ static {
+ keysAttributes.put(Chunk.ACTION, null);
+ keysAttributes.put(Chunk.UNDERLINE, null);
+ keysAttributes.put(Chunk.REMOTEGOTO, null);
+ keysAttributes.put(Chunk.LOCALGOTO, null);
+ keysAttributes.put(Chunk.LOCALDESTINATION, null);
+ keysAttributes.put(Chunk.GENERICTAG, null);
+ keysAttributes.put(Chunk.NEWPAGE, null);
+ keysAttributes.put(Chunk.IMAGE, null);
+ keysAttributes.put(Chunk.BACKGROUND, null);
+ keysAttributes.put(Chunk.PDFANNOTATION, null);
+ keysAttributes.put(Chunk.SKEW, null);
+ keysAttributes.put(Chunk.HSCALE, null);
+ keysNoStroke.put(Chunk.SUBSUPSCRIPT, null);
+ keysNoStroke.put(Chunk.SPLITCHARACTER, null);
+ keysNoStroke.put(Chunk.HYPHENATION, null);
+ keysNoStroke.put(Chunk.TEXTRENDERMODE, null);
+ }
+
+ // membervariables
+
+ /** The value of this object. */
+ protected String value = PdfObject.NOTHING;
+
+ /** The encoding. */
+ protected String encoding = BaseFont.WINANSI;
+
+
+/** The font for this PdfChunk
. */
+ protected PdfFont font;
+
+ protected BaseFont baseFont;
+
+ protected SplitCharacter splitCharacter;
+/**
+ * Metric attributes.
+ *
+ * This attributes require the mesurement of characters widths when rendering
+ * such as underline.
+ */
+ protected HashMap attributes = new HashMap();
+
+/**
+ * Non metric attributes.
+ *
+ * This attributes do not require the mesurement of characters widths when rendering
+ * such as Color.
+ */
+ protected HashMap noStroke = new HashMap();
+
+/** true
if the chunk split was cause by a newline. */
+ protected boolean newlineSplit;
+
+/** The image in this PdfChunk
, if it has one */
+ // protected Image image; ssteward: dropped in 1.44
+
+/** The offset in the x direction for the image */
+ protected float offsetX;
+
+/** The offset in the y direction for the image */
+ protected float offsetY;
+
+/** Indicates if the height and offset of the Image has to be taken into account */
+ protected boolean changeLeading = false;
+
+ // constructors
+
+/**
+ * Constructs a PdfChunk
-object.
+ *
+ * @param string the content of the PdfChunk
-object
+ * @param other Chunk with the same style you want for the new Chunk
+ */
+
+ PdfChunk(String string, PdfChunk other) {
+ thisChunk[0] = this;
+ value = string;
+ this.font = other.font;
+ this.attributes = other.attributes;
+ this.noStroke = other.noStroke;
+ this.baseFont = other.baseFont;
+ Object obj[] = (Object[])attributes.get(Chunk.IMAGE);
+ if (obj == null) {
+ // image = null; ssteward: dropped in 1.44
+ }
+ else {
+ // image = (Image)obj[0]; ssteward: dropped in 1.44
+ offsetX = ((Float)obj[1]).floatValue();
+ offsetY = ((Float)obj[2]).floatValue();
+ changeLeading = ((Boolean)obj[3]).booleanValue();
+ }
+ encoding = font.getFont().getEncoding();
+ splitCharacter = (SplitCharacter)noStroke.get(Chunk.SPLITCHARACTER);
+ if (splitCharacter == null)
+ splitCharacter = this;
+ }
+
+/**
+ * Constructs a PdfChunk
-object.
+ *
+ * @param chunk the original Chunk
-object
+ * @param action the PdfAction
if the Chunk
comes from an Anchor
+ */
+
+ PdfChunk(Chunk chunk, PdfAction action) {
+ thisChunk[0] = this;
+ value = chunk.content();
+
+ Font f = chunk.font();
+ float size = f.size();
+ if (size == Font.UNDEFINED)
+ size = 12;
+ baseFont = f.getBaseFont();
+ int style = f.style();
+ if (style == Font.UNDEFINED) {
+ style = Font.NORMAL;
+ }
+ if (baseFont == null) {
+ // translation of the font-family to a PDF font-family
+ baseFont = f.getCalculatedBaseFont(false);
+ }
+ else {
+ // bold simulation
+ if ((style & Font.BOLD) != 0)
+ attributes.put(Chunk.TEXTRENDERMODE, new Object[]{new Integer(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE), new Float(size / 30f), null});
+ // italic simulation
+ if ((style & Font.ITALIC) != 0)
+ attributes.put(Chunk.SKEW, new float[]{0, ITALIC_ANGLE});
+ }
+ font = new PdfFont(baseFont, size);
+ // other style possibilities
+ HashMap attr = chunk.getAttributes();
+ if (attr != null) {
+ for (Iterator i = attr.keySet().iterator(); i.hasNext();) {
+ Object name = i.next();
+ if (keysAttributes.containsKey(name)) {
+ attributes.put(name, attr.get(name));
+ }
+ else if (keysNoStroke.containsKey(name)) {
+ noStroke.put(name, attr.get(name));
+ }
+ }
+ if ("".equals(attr.get(Chunk.GENERICTAG))) {
+ attributes.put(Chunk.GENERICTAG, chunk.content());
+ }
+ }
+ if (f.isUnderlined()) {
+ Object obj[] = {null, new float[]{0, 1f / 15, 0, -1f / 3, 0}};
+ Object unders[][] = Chunk.addToArray((Object[][])attributes.get(Chunk.UNDERLINE), obj);
+ attributes.put(Chunk.UNDERLINE, unders);
+ }
+ if (f.isStrikethru()) {
+ Object obj[] = {null, new float[]{0, 1f / 15, 0, 1f / 3, 0}};
+ Object unders[][] = Chunk.addToArray((Object[][])attributes.get(Chunk.UNDERLINE), obj);
+ attributes.put(Chunk.UNDERLINE, unders);
+ }
+ if (action != null)
+ attributes.put(Chunk.ACTION, action);
+ // the color can't be stored in a PdfFont
+ noStroke.put(Chunk.COLOR, f.color());
+ noStroke.put(Chunk.ENCODING, font.getFont().getEncoding());
+ Object obj[] = (Object[])attributes.get(Chunk.IMAGE);
+ if (obj == null) {
+ // image = null; ssteward: dropped in 1.44
+ }
+ else {
+ attributes.remove(Chunk.HSCALE); // images are scaled in other ways
+ // image = (Image)obj[0]; ssteward: dropped in 1.44
+ offsetX = ((Float)obj[1]).floatValue();
+ offsetY = ((Float)obj[2]).floatValue();
+ changeLeading = ((Boolean)obj[3]).booleanValue();
+ }
+ // font.setImage(image); ssteward: dropped in 1.44
+ Float hs = (Float)attributes.get(Chunk.HSCALE);
+ if (hs != null)
+ font.setHorizontalScaling(hs.floatValue());
+ encoding = font.getFont().getEncoding();
+ splitCharacter = (SplitCharacter)noStroke.get(Chunk.SPLITCHARACTER);
+ if (splitCharacter == null)
+ splitCharacter = this;
+ }
+
+ // methods
+
+ /** Gets the Unicode equivalent to a CID.
+ * The (inexistent) CID is translated as '\n'.
+ * It has only meaning with CJK fonts with Identity encoding.
+ * @param c the CID code
+ * @return the Unicode equivalent
+ */
+ public char getUnicodeEquivalent(char c) {
+ return baseFont.getUnicodeEquivalent(c);
+ }
+
+ protected int getWord(String text, int start) {
+ int len = text.length();
+ while (start < len) {
+ if (!Character.isLetter(text.charAt(start)))
+ break;
+ ++start;
+ }
+ return start;
+ }
+
+/**
+ * Splits this PdfChunk
if it's too long for the given width.
+ *
+ * Returns null if the PdfChunk
wasn't truncated.
+ *
+ * @param width a given width
+ * @return the PdfChunk
that doesn't fit into the width.
+ */
+
+ PdfChunk split(float width) {
+ newlineSplit = false;
+ /* ssteward: dropped in 1.44
+ if (image != null) {
+ if (image.scaledWidth() > width) {
+ PdfChunk pc = new PdfChunk(Chunk.OBJECT_REPLACEMENT_CHARACTER, this);
+ value = "";
+ attributes = new HashMap();
+ image = null;
+ font = PdfFont.getDefaultFont();
+ return pc;
+ }
+ else
+ return null;
+ }
+ */
+ HyphenationEvent hyphenationEvent = (HyphenationEvent)noStroke.get(Chunk.HYPHENATION);
+ int currentPosition = 0;
+ int splitPosition = -1;
+ float currentWidth = 0;
+
+ // loop over all the characters of a string
+ // or until the totalWidth is reached
+ int lastSpace = -1;
+ float lastSpaceWidth = 0;
+ int length = value.length();
+ char valueArray[] = value.toCharArray();
+ char character = 0;
+ BaseFont ft = font.getFont();
+ if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
+ while (currentPosition < length) {
+ // the width of every character is added to the currentWidth
+ char cidChar = valueArray[currentPosition];
+ character = ft.getUnicodeEquivalent(cidChar);
+ // if a newLine or carriageReturn is encountered
+ if (character == '\n') {
+ newlineSplit = true;
+ String returnValue = value.substring(currentPosition + 1);
+ value = value.substring(0, currentPosition);
+ if (value.length() < 1) {
+ value = "\u0001";
+ }
+ PdfChunk pc = new PdfChunk(returnValue, this);
+ return pc;
+ }
+ currentWidth += font.width(cidChar);
+ if (character == ' ') {
+ lastSpace = currentPosition + 1;
+ lastSpaceWidth = currentWidth;
+ }
+ if (currentWidth > width)
+ break;
+ // if a split-character is encountered, the splitPosition is altered
+ if (splitCharacter.isSplitCharacter(0, currentPosition, length, valueArray, thisChunk))
+ splitPosition = currentPosition + 1;
+ currentPosition++;
+ }
+ }
+ else {
+ while (currentPosition < length) {
+ // the width of every character is added to the currentWidth
+ character = valueArray[currentPosition];
+ // if a newLine or carriageReturn is encountered
+ if (character == '\r' || character == '\n') {
+ newlineSplit = true;
+ int inc = 1;
+ if (character == '\r' && currentPosition + 1 < length && valueArray[currentPosition + 1] == '\n')
+ inc = 2;
+ String returnValue = value.substring(currentPosition + inc);
+ value = value.substring(0, currentPosition);
+ if (value.length() < 1) {
+ value = " ";
+ }
+ PdfChunk pc = new PdfChunk(returnValue, this);
+ return pc;
+ }
+ currentWidth += font.width(character);
+ if (character == ' ') {
+ lastSpace = currentPosition + 1;
+ lastSpaceWidth = currentWidth;
+ }
+ if (currentWidth > width)
+ break;
+ // if a split-character is encountered, the splitPosition is altered
+ if (splitCharacter.isSplitCharacter(0, currentPosition, length, valueArray, null))
+ splitPosition = currentPosition + 1;
+ currentPosition++;
+ }
+ }
+
+ // if all the characters fit in the total width, null is returned (there is no overflow)
+ if (currentPosition == length) {
+ return null;
+ }
+ // otherwise, the string has to be truncated
+ if (splitPosition < 0) {
+ String returnValue = value;
+ value = "";
+ PdfChunk pc = new PdfChunk(returnValue, this);
+ return pc;
+ }
+ if (lastSpace > splitPosition && splitCharacter.isSplitCharacter(0, 0, 1, singleSpace, null))
+ splitPosition = lastSpace;
+ if (hyphenationEvent != null && lastSpace < currentPosition) {
+ int wordIdx = getWord(value, lastSpace);
+ if (wordIdx > lastSpace) {
+ String pre = hyphenationEvent.getHyphenatedWordPre(value.substring(lastSpace, wordIdx), font.getFont(), font.size(), width - lastSpaceWidth);
+ String post = hyphenationEvent.getHyphenatedWordPost();
+ if (pre.length() > 0) {
+ String returnValue = post + value.substring(wordIdx);
+ value = trim(value.substring(0, lastSpace) + pre);
+ PdfChunk pc = new PdfChunk(returnValue, this);
+ return pc;
+ }
+ }
+ }
+ String returnValue = value.substring(splitPosition);
+ value = trim(value.substring(0, splitPosition));
+ PdfChunk pc = new PdfChunk(returnValue, this);
+ return pc;
+ }
+
+/**
+ * Truncates this PdfChunk
if it's too long for the given width.
+ *
+ * Returns null if the PdfChunk
wasn't truncated.
+ *
+ * @param width a given width
+ * @return the PdfChunk
that doesn't fit into the width.
+ */
+
+ PdfChunk truncate(float width) {
+ /* ssteward: dropped in 1.44
+ if (image != null) {
+ if (image.scaledWidth() > width) {
+ PdfChunk pc = new PdfChunk("", this);
+ value = "";
+ attributes.remove(Chunk.IMAGE);
+ image = null;
+ font = PdfFont.getDefaultFont();
+ return pc;
+ }
+ else
+ return null;
+ }
+ */
+
+ int currentPosition = 0;
+ float currentWidth = 0;
+
+ // it's no use trying to split if there isn't even enough place for a space
+ if (width < font.width()) {
+ String returnValue = value.substring(1);
+ value = value.substring(0, 1);
+ PdfChunk pc = new PdfChunk(returnValue, this);
+ return pc;
+ }
+
+ // loop over all the characters of a string
+ // or until the totalWidth is reached
+ int length = value.length();
+ char character;
+ while (currentPosition < length) {
+ // the width of every character is added to the currentWidth
+ character = value.charAt(currentPosition);
+ currentWidth += font.width(character);
+ if (currentWidth > width)
+ break;
+ currentPosition++;
+ }
+
+ // if all the characters fit in the total width, null is returned (there is no overflow)
+ if (currentPosition == length) {
+ return null;
+ }
+
+ // otherwise, the string has to be truncated
+ //currentPosition -= 2;
+ // we have to chop off minimum 1 character from the chunk
+ if (currentPosition == 0) {
+ currentPosition = 1;
+ }
+ String returnValue = value.substring(currentPosition);
+ value = value.substring(0, currentPosition);
+ PdfChunk pc = new PdfChunk(returnValue, this);
+ return pc;
+ }
+
+ // methods to retrieve the membervariables
+
+/**
+ * Returns the font of this Chunk
.
+ *
+ * @return a PdfFont
+ */
+
+ PdfFont font() {
+ return font;
+ }
+
+/**
+ * Returns the color of this Chunk
.
+ *
+ * @return a Color
+ */
+
+ Color color() {
+ return (Color)noStroke.get(Chunk.COLOR);
+ }
+
+/**
+ * Returns the width of this PdfChunk
.
+ *
+ * @return a width
+ */
+
+ float width() {
+ return font.width(value);
+ }
+
+/**
+ * Checks if the PdfChunk
split was caused by a newline.
+ * @return true
if the PdfChunk
split was caused by a newline.
+ */
+
+ public boolean isNewlineSplit()
+ {
+ return newlineSplit;
+ }
+
+/**
+ * Gets the width of the PdfChunk
taking into account the
+ * extra character and word spacing.
+ * @param charSpacing the extra character spacing
+ * @param wordSpacing the extra word spacing
+ * @return the calculated width
+ */
+
+ public float getWidthCorrected(float charSpacing, float wordSpacing)
+ {
+ /* ssteward: dropped in 1.44
+ if (image != null) {
+ return image.scaledWidth() + charSpacing;
+ }
+ */
+ int numberOfSpaces = 0;
+ int idx = -1;
+ while ((idx = value.indexOf(' ', idx + 1)) >= 0)
+ ++numberOfSpaces;
+ return width() + (value.length() * charSpacing + numberOfSpaces * wordSpacing);
+ }
+
+ /**
+ * Gets the text displacement relatiev to the baseline.
+ * @return a displacement in points
+ */
+ public float getTextRise() {
+ Float f = (Float) getAttribute(Chunk.SUBSUPSCRIPT);
+ if (f != null) {
+ return f.floatValue();
+ }
+ return 0.0f;
+ }
+
+/**
+ * Trims the last space.
+ * @return the width of the space trimmed, otherwise 0
+ */
+
+ public float trimLastSpace()
+ {
+ BaseFont ft = font.getFont();
+ if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
+ if (value.length() > 1 && value.endsWith("\u0001")) {
+ value = value.substring(0, value.length() - 1);
+ return font.width('\u0001');
+ }
+ }
+ else {
+ if (value.length() > 1 && value.endsWith(" ")) {
+ value = value.substring(0, value.length() - 1);
+ return font.width(' ');
+ }
+ }
+ return 0;
+ }
+
+/**
+ * Gets an attribute. The search is made in attributes
+ * and noStroke
.
+ * @param name the attribute key
+ * @return the attribute value or null if not found
+ */
+
+ Object getAttribute(String name)
+ {
+ if (attributes.containsKey(name))
+ return attributes.get(name);
+ return noStroke.get(name);
+ }
+
+/**
+ *Checks if the attribute exists.
+ * @param name the attribute key
+ * @return true
if the attribute exists
+ */
+
+ boolean isAttribute(String name)
+ {
+ if (attributes.containsKey(name))
+ return true;
+ return noStroke.containsKey(name);
+ }
+
+/**
+ * Checks if this PdfChunk
needs some special metrics handling.
+ * @return true
if this PdfChunk
needs some special metrics handling.
+ */
+
+ boolean isStroked()
+ {
+ return (attributes.size() > 0);
+ }
+
+/**
+ * Checks if there is an image in the PdfChunk
.
+ * @return true
if an image is present
+ */
+ /* ssteward: dropped in 1.44
+ boolean isImage()
+ {
+ return image != null;
+ }
+ */
+
+/**
+ * Gets the image in the PdfChunk
.
+ * @return the image or null
+ */
+ /* ssteward: dropped in 1.44
+ Image getImage()
+ {
+ return image;
+ }
+ */
+
+/**
+ * Sets the image offset in the x direction
+ * @param offsetX the image offset in the x direction
+ */
+ /* ssteward: dropped in 1.44
+ void setImageOffsetX(float offsetX)
+ {
+ this.offsetX = offsetX;
+ }
+ */
+
+/**
+ * Gets the image offset in the x direction
+ * @return the image offset in the x direction
+ */
+ /* ssteward: dropped in 1.44
+ float getImageOffsetX()
+ {
+ return offsetX;
+ }
+ */
+
+/**
+ * Sets the image offset in the y direction
+ * @param offsetY the image offset in the y direction
+ */
+ /* ssteward: dropped in 1.44
+ void setImageOffsetY(float offsetY)
+ {
+ this.offsetY = offsetY;
+ }
+ */
+
+/**
+ * Gets the image offset in the y direction
+ * @return Gets the image offset in the y direction
+ */
+
+ float getImageOffsetY()
+ {
+ return offsetY;
+ }
+
+/**
+ * sets the value.
+ * @param value content of the Chunk
+ */
+
+ void setValue(String value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return value;
+ }
+
+ /**
+ * Tells you if this string is in Chinese, Japanese, Korean or Identity-H.
+ * @return true if the Chunk has a special encoding
+ */
+
+ boolean isSpecialEncoding() {
+ return encoding.equals(CJKFont.CJK_ENCODING) || encoding.equals(BaseFont.IDENTITY_H);
+ }
+
+ /**
+ * Gets the encoding of this string.
+ *
+ * @return a String
+ */
+
+ String getEncoding() {
+ return encoding;
+ }
+
+ int length() {
+ return value.length();
+ }
+/**
+ * Checks if a character can be used to split a PdfString
.
+ *
+ * for the moment every character less than or equal to SPACE and the character '-' are 'splitCharacters'.
+ *
+ * @param start start position in the array
+ * @param current current position in the array
+ * @param end end position in the array
+ * @param cc the character array that has to be checked
+ * @param ck chunk array
+ * @return true
if the character can be used to split a string, false
otherwise
+ */
+ public boolean isSplitCharacter(int start, int current, int end, char[] cc, PdfChunk[] ck) {
+ char c;
+ if (ck == null)
+ c = cc[current];
+ else
+ c = ck[Math.min(current, ck.length - 1)].getUnicodeEquivalent(cc[current]);
+ if (c <= ' ' || c == '-') {
+ return true;
+ }
+ if (c < 0x2e80)
+ return false;
+ return ((c >= 0x2e80 && c < 0xd7a0)
+ || (c >= 0xf900 && c < 0xfb00)
+ || (c >= 0xfe30 && c < 0xfe50)
+ || (c >= 0xff61 && c < 0xffa0));
+ }
+
+ boolean isExtSplitCharacter(int start, int current, int end, char[] cc, PdfChunk[] ck) {
+ return splitCharacter.isSplitCharacter(start, current, end, cc, ck);
+ }
+
+/**
+ * Removes all the ' ' and '-' -characters on the right of a String
.
+ *
+ * @param string the String that has to be trimmed.
+ * @return the trimmed String
+ */
+ String trim(String string) {
+ BaseFont ft = font.getFont();
+ if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') {
+ while (string.endsWith("\u0001")) {
+ string = string.substring(0, string.length() - 1);
+ }
+ }
+ else {
+ while (string.endsWith(" ") || string.endsWith("\t")) {
+ string = string.substring(0, string.length() - 1);
+ }
+ }
+ return string;
+ }
+
+ public boolean changeLeading() {
+ return changeLeading;
+ }
+
+ float getCharWidth(char c) {
+ if (noPrint(c))
+ return 0;
+ return font.width(c);
+ }
+
+ public static boolean noPrint(char c) {
+ return ((c >= 0x200b && c <= 0x200f) || (c >= 0x202a && c <= 0x202e));
+ }
+
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfColor.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfColor.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfColor.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfColor.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,70 @@
+/*
+ * $Id: PdfColor.java,v 1.22 2002/06/20 13:28:22 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import java.awt.Color;
+/**
+ * A PdfColor
defines a Color (it's a PdfArray
containing 3 values).
+ *
+ * @see PdfDictionary
+ */
+
+class PdfColor extends PdfArray {
+
+ // constructors
+
+/**
+ * Constructs a new PdfColor
.
+ *
+ * @param red a value between 0 and 255
+ * @param green a value between 0 and 255
+ * @param blue a value between 0 and 255
+ */
+
+ PdfColor(int red, int green, int blue) {
+ super(new PdfNumber((double)(red & 0xFF) / 0xFF));
+ add(new PdfNumber((double)(green & 0xFF) / 0xFF));
+ add(new PdfNumber((double)(blue & 0xFF) / 0xFF));
+ }
+
+ PdfColor(Color color) {
+ this(color.getRed(), color.getGreen(), color.getBlue());
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfContentByte.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfContentByte.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfContentByte.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfContentByte.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,2956 @@
+/*
+ * $Id: PdfContentByte.java,v 1.91 2005/07/19 18:24:27 psoares33 Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.HashMap;
+// import java.util.Iterator;
+import java.awt.geom.AffineTransform;
+// import java.awt.print.PrinterJob;
+
+// import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.Element;
+// import pdftk.com.lowagie.text.Image; ssteward: dropped in 1.44
+import pdftk.com.lowagie.text.Rectangle;
+// import pdftk.com.lowagie.text.Annotation;
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+/**
+ * PdfContentByte
is an object containing the user positioned
+ * text and graphic contents of a page. It knows how to apply the proper
+ * font encoding.
+ */
+
+public class PdfContentByte {
+
+ /**
+ * This class keeps the graphic state of the current page
+ */
+
+ static class GraphicState {
+
+ /** This is the font in use */
+ FontDetails fontDetails;
+
+ /** This is the color in use */
+ ColorDetails colorDetails;
+
+ /** This is the font size in use */
+ float size;
+
+ /** The x position of the text line matrix. */
+ protected float xTLM = 0;
+ /** The y position of the text line matrix. */
+ protected float yTLM = 0;
+
+ /** The current text leading. */
+ protected float leading = 0;
+ }
+
+ /** The alignement is center */
+ public static final int ALIGN_CENTER = Element.ALIGN_CENTER;
+
+ /** The alignement is left */
+ public static final int ALIGN_LEFT = Element.ALIGN_LEFT;
+
+ /** The alignement is right */
+ public static final int ALIGN_RIGHT = Element.ALIGN_RIGHT;
+
+ /** A possible line cap value */
+ public static final int LINE_CAP_BUTT = 0;
+ /** A possible line cap value */
+ public static final int LINE_CAP_ROUND = 1;
+ /** A possible line cap value */
+ public static final int LINE_CAP_PROJECTING_SQUARE = 2;
+
+ /** A possible line join value */
+ public static final int LINE_JOIN_MITER = 0;
+ /** A possible line join value */
+ public static final int LINE_JOIN_ROUND = 1;
+ /** A possible line join value */
+ public static final int LINE_JOIN_BEVEL = 2;
+
+ /** A possible text rendering value */
+ public static final int TEXT_RENDER_MODE_FILL = 0;
+ /** A possible text rendering value */
+ public static final int TEXT_RENDER_MODE_STROKE = 1;
+ /** A possible text rendering value */
+ public static final int TEXT_RENDER_MODE_FILL_STROKE = 2;
+ /** A possible text rendering value */
+ public static final int TEXT_RENDER_MODE_INVISIBLE = 3;
+ /** A possible text rendering value */
+ public static final int TEXT_RENDER_MODE_FILL_CLIP = 4;
+ /** A possible text rendering value */
+ public static final int TEXT_RENDER_MODE_STROKE_CLIP = 5;
+ /** A possible text rendering value */
+ public static final int TEXT_RENDER_MODE_FILL_STROKE_CLIP = 6;
+ /** A possible text rendering value */
+ public static final int TEXT_RENDER_MODE_CLIP = 7;
+
+ // private static final float[] unitRect = {0, 0, 0, 1, 1, 0, 1, 1};
+ // membervariables
+
+ /** This is the actual content */
+ protected ByteBuffer content = new ByteBuffer();
+
+ /** This is the writer */
+ protected PdfWriter writer;
+
+ /** This is the PdfDocument */
+ protected PdfDocument pdf;
+
+ /** This is the GraphicState in use */
+ protected GraphicState state = new GraphicState();
+
+ /** The list were we save/restore the state */
+ protected ArrayList stateList = new ArrayList();
+
+ /** The list were we save/restore the layer depth */
+ protected ArrayList layerDepth;
+
+ /** The separator between commands.
+ */
+ protected int separator = '\n';
+
+ private static HashMap abrev = new HashMap();
+
+ static {
+ abrev.put(PdfName.BITSPERCOMPONENT, "/BPC ");
+ abrev.put(PdfName.COLORSPACE, "/CS ");
+ abrev.put(PdfName.DECODE, "/D ");
+ abrev.put(PdfName.DECODEPARMS, "/DP ");
+ abrev.put(PdfName.FILTER, "/F ");
+ abrev.put(PdfName.HEIGHT, "/H ");
+ abrev.put(PdfName.IMAGEMASK, "/IM ");
+ abrev.put(PdfName.INTENT, "/Intent ");
+ abrev.put(PdfName.INTERPOLATE, "/I ");
+ abrev.put(PdfName.WIDTH, "/W ");
+ }
+
+ // constructors
+
+ /**
+ * Constructs a new PdfContentByte
-object.
+ *
+ * @param wr the writer associated to this content
+ */
+
+ public PdfContentByte(PdfWriter wr) {
+ if (wr != null) {
+ writer = wr;
+ pdf = writer.getPdfDocument();
+ }
+ }
+
+ // methods to get the content of this object
+
+ /**
+ * Returns the String
representation of this PdfContentByte
-object.
+ *
+ * @return a String
+ */
+
+ public String toString() {
+ return content.toString();
+ }
+
+ /**
+ * Gets the internal buffer.
+ * @return the internal buffer
+ */
+ public ByteBuffer getInternalBuffer() {
+ return content;
+ }
+
+ /** Returns the PDF representation of this PdfContentByte
-object.
+ *
+ * @param writer the PdfWriter
+ * @return a byte
array with the representation
+ */
+
+ public byte[] toPdf(PdfWriter writer) {
+ return content.toByteArray();
+ }
+
+ // methods to add graphical content
+
+ /**
+ * Adds the content of another PdfContent
-object to this object.
+ *
+ * @param other another PdfByteContent
-object
+ */
+
+ public void add(PdfContentByte other) {
+ if (other.writer != null && writer != other.writer)
+ throw new RuntimeException("Inconsistent writers. Are you mixing two documents?");
+ content.append(other.content);
+ }
+
+ /**
+ * Gets the x position of the text line matrix.
+ *
+ * @return the x position of the text line matrix
+ */
+ public float getXTLM() {
+ return state.xTLM;
+ }
+
+ /**
+ * Gets the y position of the text line matrix.
+ *
+ * @return the y position of the text line matrix
+ */
+ public float getYTLM() {
+ return state.yTLM;
+ }
+
+ /**
+ * Gets the current text leading.
+ *
+ * @return the current text leading
+ */
+ public float getLeading() {
+ return state.leading;
+ }
+
+ /**
+ * Changes the Flatness .
+ *
+ * Flatness sets the maximum permitted distance in device pixels between the
+ * mathematically correct path and an approximation constructed from straight line segments.
+ *
+ * @param flatness a value
+ */
+
+ public void setFlatness(float flatness) {
+ if (flatness >= 0 && flatness <= 100) {
+ content.append(flatness).append(" i").append_i(separator);
+ }
+ }
+
+ /**
+ * Changes the Line cap style .
+ *
+ * The line cap style specifies the shape to be used at the end of open subpaths
+ * when they are stroked.
+ * Allowed values are LINE_CAP_BUTT, LINE_CAP_ROUND and LINE_CAP_PROJECTING_SQUARE.
+ *
+ * @param style a value
+ */
+
+ public void setLineCap(int style) {
+ if (style >= 0 && style <= 2) {
+ content.append(style).append(" J").append_i(separator);
+ }
+ }
+
+ /**
+ * Changes the value of the line dash pattern .
+ *
+ * The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
+ * It is specified by an array and a phase . The array specifies the length
+ * of the alternating dashes and gaps. The phase specifies the distance into the dash
+ * pattern to start the dash.
+ *
+ * @param phase the value of the phase
+ */
+
+ public void setLineDash(float phase) {
+ content.append("[] ").append(phase).append(" d").append_i(separator);
+ }
+
+ /**
+ * Changes the value of the line dash pattern .
+ *
+ * The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
+ * It is specified by an array and a phase . The array specifies the length
+ * of the alternating dashes and gaps. The phase specifies the distance into the dash
+ * pattern to start the dash.
+ *
+ * @param phase the value of the phase
+ * @param unitsOn the number of units that must be 'on' (equals the number of units that must be 'off').
+ */
+
+ public void setLineDash(float unitsOn, float phase) {
+ content.append("[").append(unitsOn).append("] ").append(phase).append(" d").append_i(separator);
+ }
+
+ /**
+ * Changes the value of the line dash pattern .
+ *
+ * The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
+ * It is specified by an array and a phase . The array specifies the length
+ * of the alternating dashes and gaps. The phase specifies the distance into the dash
+ * pattern to start the dash.
+ *
+ * @param phase the value of the phase
+ * @param unitsOn the number of units that must be 'on'
+ * @param unitsOff the number of units that must be 'off'
+ */
+
+ public void setLineDash(float unitsOn, float unitsOff, float phase) {
+ content.append("[").append(unitsOn).append(' ').append(unitsOff).append("] ").append(phase).append(" d").append_i(separator);
+ }
+
+ /**
+ * Changes the value of the line dash pattern .
+ *
+ * The line dash pattern controls the pattern of dashes and gaps used to stroke paths.
+ * It is specified by an array and a phase . The array specifies the length
+ * of the alternating dashes and gaps. The phase specifies the distance into the dash
+ * pattern to start the dash.
+ *
+ * @param array length of the alternating dashes and gaps
+ * @param phase the value of the phase
+ */
+
+ public final void setLineDash(float[] array, float phase) {
+ content.append("[");
+ for (int i = 0; i < array.length; i++) {
+ content.append(array[i]);
+ if (i < array.length - 1) content.append(' ');
+ }
+ content.append("] ").append(phase).append(" d").append_i(separator);
+ }
+
+ /**
+ * Changes the Line join style .
+ *
+ * The line join style specifies the shape to be used at the corners of paths
+ * that are stroked.
+ * Allowed values are LINE_JOIN_MITER (Miter joins), LINE_JOIN_ROUND (Round joins) and LINE_JOIN_BEVEL (Bevel joins).
+ *
+ * @param style a value
+ */
+
+ public void setLineJoin(int style) {
+ if (style >= 0 && style <= 2) {
+ content.append(style).append(" j").append_i(separator);
+ }
+ }
+
+ /**
+ * Changes the line width .
+ *
+ * The line width specifies the thickness of the line used to stroke a path and is measured
+ * in used space units.
+ *
+ * @param w a width
+ */
+
+ public void setLineWidth(float w) {
+ content.append(w).append(" w").append_i(separator);
+ }
+
+ /**
+ * Changes the Miter limit .
+ *
+ * When two line segments meet at a sharp angle and mitered joins have been specified as the
+ * line join style, it is possible for the miter to extend far beyond the thickness of the line
+ * stroking path. The miter limit imposes a maximum on the ratio of the miter length to the line
+ * witdh. When the limit is exceeded, the join is converted from a miter to a bevel.
+ *
+ * @param miterLimit a miter limit
+ */
+
+ public void setMiterLimit(float miterLimit) {
+ if (miterLimit > 1) {
+ content.append(miterLimit).append(" M").append_i(separator);
+ }
+ }
+
+ /**
+ * Modify the current clipping path by intersecting it with the current path, using the
+ * nonzero winding number rule to determine which regions lie inside the clipping
+ * path.
+ */
+
+ public void clip() {
+ content.append("W").append_i(separator);
+ }
+
+ /**
+ * Modify the current clipping path by intersecting it with the current path, using the
+ * even-odd rule to determine which regions lie inside the clipping path.
+ */
+
+ public void eoClip() {
+ content.append("W*").append_i(separator);
+ }
+
+ /**
+ * Changes the currentgray tint for filling paths (device dependent colors!).
+ *
+ * Sets the color space to DeviceGray (or the DefaultGray color space),
+ * and sets the gray tint to use for filling paths.
+ *
+ * @param gray a value between 0 (black) and 1 (white)
+ */
+
+ public void setGrayFill(float gray) {
+ content.append(gray).append(" g").append_i(separator);
+ }
+
+ /**
+ * Changes the current gray tint for filling paths to black.
+ */
+
+ public void resetGrayFill() {
+ content.append("0 g").append_i(separator);
+ }
+
+ /**
+ * Changes the currentgray tint for stroking paths (device dependent colors!).
+ *
+ * Sets the color space to DeviceGray (or the DefaultGray color space),
+ * and sets the gray tint to use for stroking paths.
+ *
+ * @param gray a value between 0 (black) and 1 (white)
+ */
+
+ public void setGrayStroke(float gray) {
+ content.append(gray).append(" G").append_i(separator);
+ }
+
+ /**
+ * Changes the current gray tint for stroking paths to black.
+ */
+
+ public void resetGrayStroke() {
+ content.append("0 G").append_i(separator);
+ }
+
+ /**
+ * Helper to validate and write the RGB color components
+ * @param red the intensity of red. A value between 0 and 1
+ * @param green the intensity of green. A value between 0 and 1
+ * @param blue the intensity of blue. A value between 0 and 1
+ */
+ private void HelperRGB(float red, float green, float blue) {
+ PdfWriter.checkPDFXConformance(writer, PdfWriter.PDFXKEY_RGB, null);
+ if (red < 0)
+ red = 0.0f;
+ else if (red > 1.0f)
+ red = 1.0f;
+ if (green < 0)
+ green = 0.0f;
+ else if (green > 1.0f)
+ green = 1.0f;
+ if (blue < 0)
+ blue = 0.0f;
+ else if (blue > 1.0f)
+ blue = 1.0f;
+ content.append(red).append(' ').append(green).append(' ').append(blue);
+ }
+
+ /**
+ * Changes the current color for filling paths (device dependent colors!).
+ *
+ * Sets the color space to DeviceRGB (or the DefaultRGB color space),
+ * and sets the color to use for filling paths.
+ *
+ * Following the PDF manual, each operand must be a number between 0 (minimum intensity) and
+ * 1 (maximum intensity).
+ *
+ * @param red the intensity of red. A value between 0 and 1
+ * @param green the intensity of green. A value between 0 and 1
+ * @param blue the intensity of blue. A value between 0 and 1
+ */
+
+ public void setRGBColorFillF(float red, float green, float blue) {
+ HelperRGB(red, green, blue);
+ content.append(" rg").append_i(separator);
+ }
+
+ /**
+ * Changes the current color for filling paths to black.
+ */
+
+ public void resetRGBColorFill() {
+ content.append("0 g").append_i(separator);
+ }
+
+ /**
+ * Changes the current color for stroking paths (device dependent colors!).
+ *
+ * Sets the color space to DeviceRGB (or the DefaultRGB color space),
+ * and sets the color to use for stroking paths.
+ *
+ * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
+ * 1 (maximum intensity).
+ *
+ * @param red the intensity of red. A value between 0 and 1
+ * @param green the intensity of green. A value between 0 and 1
+ * @param blue the intensity of blue. A value between 0 and 1
+ */
+
+ public void setRGBColorStrokeF(float red, float green, float blue) {
+ HelperRGB(red, green, blue);
+ content.append(" RG").append_i(separator);
+ }
+
+ /**
+ * Changes the current color for stroking paths to black.
+ *
+ */
+
+ public void resetRGBColorStroke() {
+ content.append("0 G").append_i(separator);
+ }
+
+ /**
+ * Helper to validate and write the CMYK color components.
+ *
+ * @param cyan the intensity of cyan. A value between 0 and 1
+ * @param magenta the intensity of magenta. A value between 0 and 1
+ * @param yellow the intensity of yellow. A value between 0 and 1
+ * @param black the intensity of black. A value between 0 and 1
+ */
+ private void HelperCMYK(float cyan, float magenta, float yellow, float black) {
+ if (cyan < 0)
+ cyan = 0.0f;
+ else if (cyan > 1.0f)
+ cyan = 1.0f;
+ if (magenta < 0)
+ magenta = 0.0f;
+ else if (magenta > 1.0f)
+ magenta = 1.0f;
+ if (yellow < 0)
+ yellow = 0.0f;
+ else if (yellow > 1.0f)
+ yellow = 1.0f;
+ if (black < 0)
+ black = 0.0f;
+ else if (black > 1.0f)
+ black = 1.0f;
+ content.append(cyan).append(' ').append(magenta).append(' ').append(yellow).append(' ').append(black);
+ }
+
+ /**
+ * Changes the current color for filling paths (device dependent colors!).
+ *
+ * Sets the color space to DeviceCMYK (or the DefaultCMYK color space),
+ * and sets the color to use for filling paths.
+ *
+ * Following the PDF manual, each operand must be a number between 0 (no ink) and
+ * 1 (maximum ink).
+ *
+ * @param cyan the intensity of cyan. A value between 0 and 1
+ * @param magenta the intensity of magenta. A value between 0 and 1
+ * @param yellow the intensity of yellow. A value between 0 and 1
+ * @param black the intensity of black. A value between 0 and 1
+ */
+
+ public void setCMYKColorFillF(float cyan, float magenta, float yellow, float black) {
+ HelperCMYK(cyan, magenta, yellow, black);
+ content.append(" k").append_i(separator);
+ }
+
+ /**
+ * Changes the current color for filling paths to black.
+ *
+ */
+
+ public void resetCMYKColorFill() {
+ content.append("0 0 0 1 k").append_i(separator);
+ }
+
+ /**
+ * Changes the current color for stroking paths (device dependent colors!).
+ *
+ * Sets the color space to DeviceCMYK (or the DefaultCMYK color space),
+ * and sets the color to use for stroking paths.
+ *
+ * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
+ * 1 (maximum intensity).
+ *
+ * @param cyan the intensity of cyan. A value between 0 and 1
+ * @param magenta the intensity of magenta. A value between 0 and 1
+ * @param yellow the intensity of yellow. A value between 0 and 1
+ * @param black the intensity of black. A value between 0 and 1
+ */
+
+ public void setCMYKColorStrokeF(float cyan, float magenta, float yellow, float black) {
+ HelperCMYK(cyan, magenta, yellow, black);
+ content.append(" K").append_i(separator);
+ }
+
+ /**
+ * Changes the current color for stroking paths to black.
+ *
+ */
+
+ public void resetCMYKColorStroke() {
+ content.append("0 0 0 1 K").append_i(separator);
+ }
+
+ /**
+ * Move the current point (x, y) , omitting any connecting line segment.
+ *
+ * @param x new x-coordinate
+ * @param y new y-coordinate
+ */
+
+ public void moveTo(float x, float y) {
+ content.append(x).append(' ').append(y).append(" m").append_i(separator);
+ }
+
+ /**
+ * Appends a straight line segment from the current point (x, y) . The new current
+ * point is (x, y) .
+ *
+ * @param x new x-coordinate
+ * @param y new y-coordinate
+ */
+
+ public void lineTo(float x, float y) {
+ content.append(x).append(' ').append(y).append(" l").append_i(separator);
+ }
+
+ /**
+ * Appends a Bêzier curve to the path, starting from the current point.
+ *
+ * @param x1 x-coordinate of the first control point
+ * @param y1 y-coordinate of the first control point
+ * @param x2 x-coordinate of the second control point
+ * @param y2 y-coordinate of the second control point
+ * @param x3 x-coordinaat of the ending point (= new current point)
+ * @param y3 y-coordinaat of the ending point (= new current point)
+ */
+
+ public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) {
+ content.append(x1).append(' ').append(y1).append(' ').append(x2).append(' ').append(y2).append(' ').append(x3).append(' ').append(y3).append(" c").append_i(separator);
+ }
+
+ /**
+ * Appends a Bêzier curve to the path, starting from the current point.
+ *
+ * @param x2 x-coordinate of the second control point
+ * @param y2 y-coordinate of the second control point
+ * @param x3 x-coordinaat of the ending point (= new current point)
+ * @param y3 y-coordinaat of the ending point (= new current point)
+ */
+
+ public void curveTo(float x2, float y2, float x3, float y3) {
+ content.append(x2).append(' ').append(y2).append(' ').append(x3).append(' ').append(y3).append(" v").append_i(separator);
+ }
+
+ /**
+ * Appends a Bêzier curve to the path, starting from the current point.
+ *
+ * @param x1 x-coordinate of the first control point
+ * @param y1 y-coordinate of the first control point
+ * @param x3 x-coordinaat of the ending point (= new current point)
+ * @param y3 y-coordinaat of the ending point (= new current point)
+ */
+
+ public void curveFromTo(float x1, float y1, float x3, float y3) {
+ content.append(x1).append(' ').append(y1).append(' ').append(x3).append(' ').append(y3).append(" y").append_i(separator);
+ }
+
+ /** Draws a circle. The endpoint will (x+r, y).
+ *
+ * @param x x center of circle
+ * @param y y center of circle
+ * @param r radius of circle
+ */
+ public void circle(float x, float y, float r) {
+ float b = 0.5523f;
+ moveTo(x + r, y);
+ curveTo(x + r, y + r * b, x + r * b, y + r, x, y + r);
+ curveTo(x - r * b, y + r, x - r, y + r * b, x - r, y);
+ curveTo(x - r, y - r * b, x - r * b, y - r, x, y - r);
+ curveTo(x + r * b, y - r, x + r, y - r * b, x + r, y);
+ }
+
+
+
+ /**
+ * Adds a rectangle to the current path.
+ *
+ * @param x x-coordinate of the starting point
+ * @param y y-coordinate of the starting point
+ * @param w width
+ * @param h height
+ */
+
+ public void rectangle(float x, float y, float w, float h) {
+ content.append(x).append(' ').append(y).append(' ').append(w).append(' ').append(h).append(" re").append_i(separator);
+ }
+
+
+ // Contribution by Barry Richards and Prabhakar Chaganti
+ /**
+ * Adds a variable width border to the current path.
+ * Only use if {@link pdftk.com.lowagie.text.Rectangle#isUseVariableBorders() Rectangle.isUseVariableBorders}
+ * = true.
+ * @param rect a Rectangle
+ */
+ public void variableRectangle(Rectangle rect) {
+ float limit = 0f;
+ float startX = rect.left();
+ float startY = rect.bottom();
+
+ // start at the origin
+ // draw bottom
+ if (rect.getBorderWidthBottom() > limit) {
+ moveTo(startX, startY);
+ if (rect.getBorderColorBottom() == null)
+ resetRGBColorFill();
+ else
+ setColorFill(rect.getBorderColorBottom());
+ // DRAW BOTTOM EDGE.
+ lineTo(startX + rect.width(), startY);
+ // DRAW RIGHT EDGE.
+ lineTo((startX + rect.width()) - rect.getBorderWidthRight(), startY + rect.getBorderWidthBottom());
+ //DRAW TOP EDGE.
+ lineTo((startX + rect.getBorderWidthLeft()), startY + rect.getBorderWidthBottom());
+ lineTo(startX, startY);
+ fill();
+ }
+
+ // Draw left
+ if (rect.getBorderWidthLeft() > limit) {
+ moveTo(startX, startY);
+ if (rect.getBorderColorLeft() == null)
+ resetRGBColorFill();
+ else
+ setColorFill(rect.getBorderColorLeft());
+ // DRAW BOTTOM EDGE.
+ lineTo(startX, startY + rect.height());
+ // DRAW RIGHT EDGE.
+ lineTo(startX + rect.getBorderWidthLeft(), (startY + rect.height()) - rect.getBorderWidthTop());
+ //DRAW TOP EDGE.
+ lineTo(startX + rect.getBorderWidthLeft(), startY + rect.getBorderWidthBottom());
+
+ lineTo(startX, startY);
+ fill();
+ }
+
+
+ startX = startX + rect.width();
+ startY = startY + rect.height();
+
+ // Draw top
+ if (rect.getBorderWidthTop() > limit) {
+ moveTo(startX, startY);
+ if (rect.getBorderColorTop() == null)
+ resetRGBColorFill();
+ else
+ setColorFill(rect.getBorderColorTop());
+ // DRAW LONG EDGE.
+ lineTo(startX - rect.width(), startY);
+ // DRAW LEFT EDGE.
+ lineTo(startX - rect.width() + rect.getBorderWidthLeft(), startY - rect.getBorderWidthTop());
+ //DRAW SHORT EDGE.
+ lineTo(startX - rect.getBorderWidthRight(), startY - rect.getBorderWidthTop());
+
+ lineTo(startX, startY);
+ fill();
+ }
+
+ // Draw Right
+ if (rect.getBorderWidthRight() > limit) {
+ moveTo(startX, startY);
+ if (rect.getBorderColorRight() == null)
+ resetRGBColorFill();
+ else
+ setColorFill(rect.getBorderColorRight());
+ // DRAW LONG EDGE.
+ lineTo(startX, startY - rect.height());
+ // DRAW LEFT EDGE.
+ lineTo(startX - rect.getBorderWidthRight(), startY - rect.height() + rect.getBorderWidthBottom());
+ //DRAW SHORT EDGE.
+ lineTo(startX - rect.getBorderWidthRight(), startY - rect.getBorderWidthTop());
+
+ lineTo(startX, startY);
+ fill();
+ }
+ resetRGBColorFill();
+ }
+
+ /**
+ * Adds a border (complete or partially) to the current path..
+ *
+ * @param rectangle a Rectangle
+ */
+
+ public void rectangle(Rectangle rectangle) {
+ // the coordinates of the border are retrieved
+ float x1 = rectangle.left();
+ float y1 = rectangle.bottom();
+ float x2 = rectangle.right();
+ float y2 = rectangle.top();
+
+ // the backgroundcolor is set
+ Color background = rectangle.backgroundColor();
+ if (background != null) {
+ setColorFill(background);
+ rectangle(x1, y1, x2 - x1, y2 - y1);
+ fill();
+ resetRGBColorFill();
+ }
+ else if (rectangle.grayFill() > 0.0) {
+ setGrayFill(rectangle.grayFill());
+ rectangle(x1, y1, x2 - x1, y2 - y1);
+ fill();
+ resetGrayFill();
+ }
+
+
+ // if the element hasn't got any borders, nothing is added
+ if (! rectangle.hasBorders()) {
+ return;
+ }
+
+ // if any of the individual border colors are set
+ // we draw the borders all around using the
+ // different colors
+ if (rectangle.isUseVariableBorders()) {
+ variableRectangle(rectangle);
+ }
+ else {
+ // the width is set to the width of the element
+ if (rectangle.borderWidth() != Rectangle.UNDEFINED) {
+ setLineWidth(rectangle.borderWidth());
+ }
+
+ // the color is set to the color of the element
+ Color color = rectangle.borderColor();
+ if (color != null) {
+ setColorStroke(color);
+ }
+
+ // if the box is a rectangle, it is added as a rectangle
+ if (rectangle.hasBorder(Rectangle.BOX)) {
+ rectangle(x1, y1, x2 - x1, y2 - y1);
+ }
+ // if the border isn't a rectangle, the different sides are added apart
+ else {
+ if (rectangle.hasBorder(Rectangle.RIGHT)) {
+ moveTo(x2, y1);
+ lineTo(x2, y2);
+ }
+ if (rectangle.hasBorder(Rectangle.LEFT)) {
+ moveTo(x1, y1);
+ lineTo(x1, y2);
+ }
+ if (rectangle.hasBorder(Rectangle.BOTTOM)) {
+ moveTo(x1, y1);
+ lineTo(x2, y1);
+ }
+ if (rectangle.hasBorder(Rectangle.TOP)) {
+ moveTo(x1, y2);
+ lineTo(x2, y2);
+ }
+ }
+
+ stroke();
+
+ if (color != null) {
+ resetRGBColorStroke();
+ }
+ }
+ }
+
+ /**
+ * Closes the current subpath by appending a straight line segment from the current point
+ * to the starting point of the subpath.
+ */
+
+ public void closePath() {
+ content.append("h").append_i(separator);
+ }
+
+ /**
+ * Ends the path without filling or stroking it.
+ */
+
+ public void newPath() {
+ content.append("n").append_i(separator);
+ }
+
+ /**
+ * Strokes the path.
+ */
+
+ public void stroke() {
+ content.append("S").append_i(separator);
+ }
+
+ /**
+ * Closes the path and strokes it.
+ */
+
+ public void closePathStroke() {
+ content.append("s").append_i(separator);
+ }
+
+ /**
+ * Fills the path, using the non-zero winding number rule to determine the region to fill.
+ */
+
+ public void fill() {
+ content.append("f").append_i(separator);
+ }
+
+ /**
+ * Fills the path, using the even-odd rule to determine the region to fill.
+ */
+
+ public void eoFill() {
+ content.append("f*").append_i(separator);
+ }
+
+ /**
+ * Fills the path using the non-zero winding number rule to determine the region to fill and strokes it.
+ */
+
+ public void fillStroke() {
+ content.append("B").append_i(separator);
+ }
+
+ /**
+ * Closes the path, fills it using the non-zero winding number rule to determine the region to fill and strokes it.
+ */
+
+ public void closePathFillStroke() {
+ content.append("b").append_i(separator);
+ }
+
+ /**
+ * Fills the path, using the even-odd rule to determine the region to fill and strokes it.
+ */
+
+ public void eoFillStroke() {
+ content.append("B*").append_i(separator);
+ }
+
+ /**
+ * Closes the path, fills it using the even-odd rule to determine the region to fill and strokes it.
+ */
+
+ public void closePathEoFillStroke() {
+ content.append("b*").append_i(separator);
+ }
+
+ /**
+ * Adds an Image
to the page. The Image
must have
+ * absolute positioning.
+ * @param image the Image
object
+ * @throws DocumentException if the Image
does not have absolute positioning
+ */
+ /* ssteward: dropped in 1.44
+ public void addImage(Image image) throws DocumentException {
+ addImage(image, false);
+ }
+ */
+
+ /**
+ * Adds an Image
to the page. The Image
must have
+ * absolute positioning. The image can be placed inline.
+ * @param image the Image
object
+ * @param inlineImage true
to place this image inline, false
otherwise
+ * @throws DocumentException if the Image
does not have absolute positioning
+ */
+ /* ssteward: dropped in 1.44
+ public void addImage(Image image, boolean inlineImage) throws DocumentException {
+ if (!image.hasAbsolutePosition())
+ throw new DocumentException("The image must have absolute positioning.");
+ float matrix[] = image.matrix();
+ matrix[Image.CX] = image.absoluteX() - matrix[Image.CX];
+ matrix[Image.CY] = image.absoluteY() - matrix[Image.CY];
+ addImage(image, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5], inlineImage);
+ }
+ */
+
+ /**
+ * Adds an Image
to the page. The positioning of the Image
+ * is done with the transformation matrix. To position an image
at (x,y)
+ * use addImage(image, image_width, 0, 0, image_height, x, y).
+ * @param image the Image
object
+ * @param a an element of the transformation matrix
+ * @param b an element of the transformation matrix
+ * @param c an element of the transformation matrix
+ * @param d an element of the transformation matrix
+ * @param e an element of the transformation matrix
+ * @param f an element of the transformation matrix
+ * @throws DocumentException on error
+ */
+ /* ssteward: dropped in 1.44
+ public void addImage(Image image, float a, float b, float c, float d, float e, float f) throws DocumentException {
+ addImage(image, a, b, c, d, e, f, false);
+ }
+ */
+
+ /**
+ * Adds an Image
to the page. The positioning of the Image
+ * is done with the transformation matrix. To position an image
at (x,y)
+ * use addImage(image, image_width, 0, 0, image_height, x, y). The image can be placed inline.
+ * @param image the Image
object
+ * @param a an element of the transformation matrix
+ * @param b an element of the transformation matrix
+ * @param c an element of the transformation matrix
+ * @param d an element of the transformation matrix
+ * @param e an element of the transformation matrix
+ * @param f an element of the transformation matrix
+ * @param inlineImage true
to place this image inline, false
otherwise
+ * @throws DocumentException on error
+ */
+ /*
+ public void addImage(Image image, float a, float b, float c, float d, float e, float f, boolean inlineImage) throws DocumentException {
+ try {
+ if (image.getLayer() != null)
+ beginLayer(image.getLayer());
+ if (image.isImgTemplate()) {
+ writer.addDirectImageSimple(image);
+ PdfTemplate template = image.templateData();
+ float w = template.getWidth();
+ float h = template.getHeight();
+ addTemplate(template, a / w, b / w, c / h, d / h, e, f);
+ }
+ else {
+ content.append("q ");
+ content.append(a).append(' ');
+ content.append(b).append(' ');
+ content.append(c).append(' ');
+ content.append(d).append(' ');
+ content.append(e).append(' ');
+ content.append(f).append(" cm");
+ if (inlineImage) {
+ content.append("\nBI\n");
+ PdfImage pimage = new PdfImage(image, "", null);
+ for (Iterator it = pimage.getKeys().iterator(); it.hasNext();) {
+ PdfName key = (PdfName)it.next();
+ PdfObject value = pimage.get(key);
+ String s = (String)abrev.get(key);
+ if (s == null)
+ continue;
+ content.append(s);
+ boolean check = true;
+ if (key.equals(PdfName.COLORSPACE) && value.isArray()) {
+ ArrayList ar = ((PdfArray)value).getArrayList();
+ if (ar.size() == 4
+ && PdfName.INDEXED.equals(ar.get(0))
+ && ((PdfObject)ar.get(1)).isName()
+ && ((PdfObject)ar.get(2)).isNumber()
+ && ((PdfObject)ar.get(3)).isString()
+ ) {
+ check = false;
+ }
+
+ }
+ if (check && key.equals(PdfName.COLORSPACE) && !value.isName()) {
+ PdfName cs = writer.getColorspaceName();
+ PageResources prs = getPageResources();
+ prs.addColor(cs, writer.addToBody(value).getIndirectReference());
+ value = cs;
+ }
+ value.toPdf(null, content);
+ content.append('\n');
+ }
+ content.append("ID\n");
+ pimage.writeContent(content);
+ content.append("\nEI\nQ").append_i(separator);
+ }
+ else {
+ PdfName name;
+ PageResources prs = getPageResources();
+ Image maskImage = image.getImageMask();
+ if (maskImage != null) {
+ name = writer.addDirectImageSimple(maskImage);
+ prs.addXObject(name, writer.getImageReference(name));
+ }
+ name = writer.addDirectImageSimple(image);
+ name = prs.addXObject(name, writer.getImageReference(name));
+ content.append(' ').append(name.getBytes()).append(" Do Q").append_i(separator);
+ }
+ }
+ if (image.hasBorders()) {
+ saveState();
+ float w = image.width();
+ float h = image.height();
+ concatCTM(a / w, b / w, c / h, d / h, e, f);
+ rectangle(image);
+ restoreState();
+ }
+ if (image.getLayer() != null)
+ endLayer();
+ Annotation annot = image.annotation();
+ if (annot == null)
+ return;
+ float[] r = new float[unitRect.length];
+ for (int k = 0; k < unitRect.length; k += 2) {
+ r[k] = a * unitRect[k] + c * unitRect[k + 1] + e;
+ r[k + 1] = b * unitRect[k] + d * unitRect[k + 1] + f;
+ }
+ float llx = r[0];
+ float lly = r[1];
+ float urx = llx;
+ float ury = lly;
+ for (int k = 2; k < r.length; k += 2) {
+ llx = Math.min(llx, r[k]);
+ lly = Math.min(lly, r[k + 1]);
+ urx = Math.max(urx, r[k]);
+ ury = Math.max(ury, r[k + 1]);
+ }
+ annot = new Annotation(annot);
+ annot.setDimensions(llx, lly, urx, ury);
+ PdfAnnotation an = PdfDocument.convertAnnotation(writer, annot);
+ if (an == null)
+ return;
+ addAnnotation(an);
+ }
+ catch (Exception ee) {
+ throw new DocumentException(ee);
+ }
+ }
+ */
+
+ /**
+ * Makes this PdfContentByte
empty.
+ */
+ public void reset() {
+ content.reset();
+ stateList.clear();
+ state = new GraphicState();
+ }
+
+ /**
+ * Starts the writing of text.
+ */
+ public void beginText() {
+ state.xTLM = 0;
+ state.yTLM = 0;
+ content.append("BT").append_i(separator);
+ }
+
+ /**
+ * Ends the writing of text and makes the current font invalid.
+ */
+ public void endText() {
+ content.append("ET").append_i(separator);
+ }
+
+ /**
+ * Saves the graphic state. saveState
and
+ * restoreState
must be balanced.
+ */
+ public void saveState() {
+ content.append("q").append_i(separator);
+ stateList.add(state);
+ }
+
+ /**
+ * Restores the graphic state. saveState
and
+ * restoreState
must be balanced.
+ */
+ public void restoreState() {
+ content.append("Q").append_i(separator);
+ int idx = stateList.size() - 1;
+ if (idx < 0)
+ throw new RuntimeException("Unbalanced save/restore state operators.");
+ state = (GraphicState)stateList.get(idx);
+ stateList.remove(idx);
+ }
+
+ /**
+ * Sets the character spacing parameter.
+ *
+ * @param charSpace a parameter
+ */
+ public void setCharacterSpacing(float charSpace) {
+ content.append(charSpace).append(" Tc").append_i(separator);
+ }
+
+ /**
+ * Sets the word spacing parameter.
+ *
+ * @param wordSpace a parameter
+ */
+ public void setWordSpacing(float wordSpace) {
+ content.append(wordSpace).append(" Tw").append_i(separator);
+ }
+
+ /**
+ * Sets the horizontal scaling parameter.
+ *
+ * @param scale a parameter
+ */
+ public void setHorizontalScaling(float scale) {
+ content.append(scale).append(" Tz").append_i(separator);
+ }
+
+ /**
+ * Sets the text leading parameter.
+ *
+ * The leading parameter is measured in text space units. It specifies the vertical distance
+ * between the baselines of adjacent lines of text.
+ *
+ * @param leading the new leading
+ */
+ public void setLeading(float leading) {
+ state.leading = leading;
+ content.append(leading).append(" TL").append_i(separator);
+ }
+
+ /**
+ * Set the font and the size for the subsequent text writing.
+ *
+ * @param bf the font
+ * @param size the font size in points
+ */
+ public void setFontAndSize(BaseFont bf, float size) {
+ checkWriter();
+ state.size = size;
+ state.fontDetails = writer.addSimple(bf);
+ PageResources prs = getPageResources();
+ PdfName name = state.fontDetails.getFontName();
+ name = prs.addFont(name, state.fontDetails.getIndirectReference());
+ content.append(name.getBytes()).append(' ').append(size).append(" Tf").append_i(separator);
+ }
+
+ /**
+ * Sets the text rendering parameter.
+ *
+ * @param rendering a parameter
+ */
+ public void setTextRenderingMode(int rendering) {
+ content.append(rendering).append(" Tr").append_i(separator);
+ }
+
+ /**
+ * Sets the text rise parameter.
+ *
+ * This allows to write text in subscript or superscript mode.
+ *
+ * @param rise a parameter
+ */
+ public void setTextRise(float rise) {
+ content.append(rise).append(" Ts").append_i(separator);
+ }
+
+ /**
+ * A helper to insert into the content stream the text
+ * converted to bytes according to the font's encoding.
+ *
+ * @param text the text to write
+ */
+ private void showText2(String text) {
+ if (state.fontDetails == null)
+ throw new NullPointerException("Font and size must be set before writing any text");
+ byte b[] = state.fontDetails.convertToBytes(text);
+ escapeString(b, content);
+ }
+
+ /**
+ * Shows the text
.
+ *
+ * @param text the text to write
+ */
+ public void showText(String text) {
+ showText2(text);
+ content.append("Tj").append_i(separator);
+ }
+
+ /**
+ * Constructs a kern array for a text in a certain font
+ * @param text the text
+ * @param font the font
+ * @return a PdfTextArray
+ */
+ public static PdfTextArray getKernArray(String text, BaseFont font) {
+ PdfTextArray pa = new PdfTextArray();
+ StringBuffer acc = new StringBuffer();
+ int len = text.length() - 1;
+ char c[] = text.toCharArray();
+ if (len >= 0)
+ acc.append(c, 0, 1);
+ for (int k = 0; k < len; ++k) {
+ char c2 = c[k + 1];
+ int kern = font.getKerning(c[k], c2);
+ if (kern == 0) {
+ acc.append(c2);
+ }
+ else {
+ pa.add(acc.toString());
+ acc.setLength(0);
+ acc.append(c, k + 1, 1);
+ pa.add(-kern);
+ }
+ }
+ pa.add(acc.toString());
+ return pa;
+ }
+
+ /**
+ * Shows the text
kerned.
+ *
+ * @param text the text to write
+ */
+ public void showTextKerned(String text) {
+ if (state.fontDetails == null)
+ throw new NullPointerException("Font and size must be set before writing any text");
+ BaseFont bf = state.fontDetails.getBaseFont();
+ if (bf.hasKernPairs())
+ showText(getKernArray(text, bf));
+ else
+ showText(text);
+ }
+
+ /**
+ * Moves to the next line and shows text
.
+ *
+ * @param text the text to write
+ */
+ public void newlineShowText(String text) {
+ state.yTLM -= state.leading;
+ showText2(text);
+ content.append("'").append_i(separator);
+ }
+
+ /**
+ * Moves to the next line and shows text string, using the given values of the character and word spacing parameters.
+ *
+ * @param wordSpacing a parameter
+ * @param charSpacing a parameter
+ * @param text the text to write
+ */
+ public void newlineShowText(float wordSpacing, float charSpacing, String text) {
+ state.yTLM -= state.leading;
+ content.append(wordSpacing).append(' ').append(charSpacing);
+ showText2(text);
+ content.append("\"").append_i(separator);
+ }
+
+ /**
+ * Changes the text matrix.
+ *
+ * Remark: this operation also initializes the current point position.
+ *
+ * @param a operand 1,1 in the matrix
+ * @param b operand 1,2 in the matrix
+ * @param c operand 2,1 in the matrix
+ * @param d operand 2,2 in the matrix
+ * @param x operand 3,1 in the matrix
+ * @param y operand 3,2 in the matrix
+ */
+ public void setTextMatrix(float a, float b, float c, float d, float x, float y) {
+ state.xTLM = x;
+ state.yTLM = y;
+ content.append(a).append(' ').append(b).append_i(' ')
+ .append(c).append_i(' ').append(d).append_i(' ')
+ .append(x).append_i(' ').append(y).append(" Tm").append_i(separator);
+ }
+
+ /**
+ * Changes the text matrix. The first four parameters are {1,0,0,1}.
+ *
+ * Remark: this operation also initializes the current point position.
+ *
+ * @param x operand 3,1 in the matrix
+ * @param y operand 3,2 in the matrix
+ */
+ public void setTextMatrix(float x, float y) {
+ setTextMatrix(1, 0, 0, 1, x, y);
+ }
+
+ /**
+ * Moves to the start of the next line, offset from the start of the current line.
+ *
+ * @param x x-coordinate of the new current point
+ * @param y y-coordinate of the new current point
+ */
+ public void moveText(float x, float y) {
+ state.xTLM += x;
+ state.yTLM += y;
+ content.append(x).append(' ').append(y).append(" Td").append_i(separator);
+ }
+
+ /**
+ * Moves to the start of the next line, offset from the start of the current line.
+ *
+ * As a side effect, this sets the leading parameter in the text state.
+ *
+ * @param x offset of the new current point
+ * @param y y-coordinate of the new current point
+ */
+ public void moveTextWithLeading(float x, float y) {
+ state.xTLM += x;
+ state.yTLM += y;
+ state.leading = -y;
+ content.append(x).append(' ').append(y).append(" TD").append_i(separator);
+ }
+
+ /**
+ * Moves to the start of the next line.
+ */
+ public void newlineText() {
+ state.yTLM -= state.leading;
+ content.append("T*").append_i(separator);
+ }
+
+ /**
+ * Gets the size of this content.
+ *
+ * @return the size of the content
+ */
+ int size() {
+ return content.size();
+ }
+
+ /**
+ * Escapes a byte
array according to the PDF conventions.
+ *
+ * @param b the byte
array to escape
+ * @return an escaped byte
array
+ */
+ static byte[] escapeString(byte b[]) {
+ ByteBuffer content = new ByteBuffer();
+ escapeString(b, content);
+ return content.toByteArray();
+ }
+
+ /**
+ * Escapes a byte
array according to the PDF conventions.
+ *
+ * @param b the byte
array to escape
+ * @param content the content
+ */
+ static void escapeString(byte b[], ByteBuffer content) {
+ content.append_i('(');
+ for (int k = 0; k < b.length; ++k) {
+ byte c = b[k];
+ switch (c) {
+ case '\r':
+ content.append("\\r");
+ break;
+ case '\n':
+ content.append("\\n");
+ break;
+ case '\t':
+ content.append("\\t");
+ break;
+ case '\b':
+ content.append("\\b");
+ break;
+ case '\f':
+ content.append("\\f");
+ break;
+ case '(':
+ case ')':
+ case '\\':
+ content.append_i('\\').append_i(c);
+ break;
+ default:
+ content.append_i(c);
+ }
+ }
+ content.append(")");
+ }
+
+ /**
+ * Adds an outline to the document.
+ *
+ * @param outline the outline
+ * @deprecated not needed anymore. The outlines are extracted
+ * from the root outline
+ */
+ public void addOutline(PdfOutline outline) {
+ // for compatibility
+ }
+ /**
+ * Adds a named outline to the document.
+ *
+ * @param outline the outline
+ * @param name the name for the local destination
+ */
+ public void addOutline(PdfOutline outline, String name) {
+ checkWriter();
+ pdf.addOutline(outline, name);
+ }
+ /**
+ * Gets the root outline.
+ *
+ * @return the root outline
+ */
+ public PdfOutline getRootOutline() {
+ checkWriter();
+ return pdf.getRootOutline();
+ }
+
+ /**
+ * Shows text right, left or center aligned with rotation.
+ * @param alignment the alignment can be ALIGN_CENTER, ALIGN_RIGHT or ALIGN_LEFT
+ * @param text the text to show
+ * @param x the x pivot position
+ * @param y the y pivot position
+ * @param rotation the rotation to be applied in degrees counterclockwise
+ */
+ public void showTextAligned(int alignment, String text, float x, float y, float rotation) {
+ if (state.fontDetails == null)
+ throw new NullPointerException("Font and size must be set before writing any text");
+ BaseFont bf = state.fontDetails.getBaseFont();
+ if (rotation == 0) {
+ switch (alignment) {
+ case ALIGN_CENTER:
+ x -= bf.getWidthPoint(text, state.size) / 2;
+ break;
+ case ALIGN_RIGHT:
+ x -= bf.getWidthPoint(text, state.size);
+ break;
+ }
+ setTextMatrix(x, y);
+ showText(text);
+ }
+ else {
+ double alpha = rotation * Math.PI / 180.0;
+ float cos = (float)Math.cos(alpha);
+ float sin = (float)Math.sin(alpha);
+ float len;
+ switch (alignment) {
+ case ALIGN_CENTER:
+ len = bf.getWidthPoint(text, state.size) / 2;
+ x -= len * cos;
+ y -= len * sin;
+ break;
+ case ALIGN_RIGHT:
+ len = bf.getWidthPoint(text, state.size);
+ x -= len * cos;
+ y -= len * sin;
+ break;
+ }
+ setTextMatrix(cos, sin, -sin, cos, x, y);
+ showText(text);
+ setTextMatrix(0f, 0f);
+ }
+ }
+
+ /**
+ * Shows text kerned right, left or center aligned with rotation.
+ * @param alignement the alignment can be ALIGN_CENTER, ALIGN_RIGHT or ALIGN_LEFT
+ * @param text the text to show
+ * @param x the x pivot position
+ * @param y the y pivot position
+ * @param rotation the rotation to be applied in degrees counterclockwise
+ */
+ public void showTextAlignedKerned(int alignement, String text, float x, float y, float rotation) {
+ if (state.fontDetails == null)
+ throw new NullPointerException("Font and size must be set before writing any text");
+ BaseFont bf = state.fontDetails.getBaseFont();
+ if (rotation == 0) {
+ switch (alignement) {
+ case ALIGN_CENTER:
+ x -= bf.getWidthPointKerned(text, state.size) / 2;
+ break;
+ case ALIGN_RIGHT:
+ x -= bf.getWidthPointKerned(text, state.size);
+ break;
+ }
+ setTextMatrix(x, y);
+ showTextKerned(text);
+ }
+ else {
+ double alpha = rotation * Math.PI / 180.0;
+ float cos = (float)Math.cos(alpha);
+ float sin = (float)Math.sin(alpha);
+ float len;
+ switch (alignement) {
+ case ALIGN_CENTER:
+ len = bf.getWidthPointKerned(text, state.size) / 2;
+ x -= len * cos;
+ y -= len * sin;
+ break;
+ case ALIGN_RIGHT:
+ len = bf.getWidthPointKerned(text, state.size);
+ x -= len * cos;
+ y -= len * sin;
+ break;
+ }
+ setTextMatrix(cos, sin, -sin, cos, x, y);
+ showTextKerned(text);
+ setTextMatrix(0f, 0f);
+ }
+ }
+
+ /**
+ * Concatenate a matrix to the current transformation matrix.
+ * @param a an element of the transformation matrix
+ * @param b an element of the transformation matrix
+ * @param c an element of the transformation matrix
+ * @param d an element of the transformation matrix
+ * @param e an element of the transformation matrix
+ * @param f an element of the transformation matrix
+ **/
+ public void concatCTM(float a, float b, float c, float d, float e, float f) {
+ content.append(a).append(' ').append(b).append(' ').append(c).append(' ');
+ content.append(d).append(' ').append(e).append(' ').append(f).append(" cm").append_i(separator);
+ }
+
+ /**
+ * Generates an array of bezier curves to draw an arc.
+ *
+ * (x1, y1) and (x2, y2) are the corners of the enclosing rectangle.
+ * Angles, measured in degrees, start with 0 to the right (the positive X
+ * axis) and increase counter-clockwise. The arc extends from startAng
+ * to startAng+extent. I.e. startAng=0 and extent=180 yields an openside-down
+ * semi-circle.
+ *
+ * The resulting coordinates are of the form float[]{x1,y1,x2,y2,x3,y3, x4,y4}
+ * such that the curve goes from (x1, y1) to (x4, y4) with (x2, y2) and
+ * (x3, y3) as their respective Bezier control points.
+ *
+ * Note: this code was taken from ReportLab (www.reportlab.com), an excelent
+ * PDF generator for Python.
+ *
+ * @param x1 a corner of the enclosing rectangle
+ * @param y1 a corner of the enclosing rectangle
+ * @param x2 a corner of the enclosing rectangle
+ * @param y2 a corner of the enclosing rectangle
+ * @param startAng starting angle in degrees
+ * @param extent angle extent in degrees
+ * @return a list of float[] with the bezier curves
+ */
+ public static ArrayList bezierArc(float x1, float y1, float x2, float y2, float startAng, float extent) {
+ float tmp;
+ if (x1 > x2) {
+ tmp = x1;
+ x1 = x2;
+ x2 = tmp;
+ }
+ if (y2 > y1) {
+ tmp = y1;
+ y1 = y2;
+ y2 = tmp;
+ }
+
+ float fragAngle;
+ int Nfrag;
+ if (Math.abs(extent) <= 90f) {
+ fragAngle = extent;
+ Nfrag = 1;
+ }
+ else {
+ Nfrag = (int)(Math.ceil(Math.abs(extent)/90f));
+ fragAngle = extent / Nfrag;
+ }
+ float x_cen = (x1+x2)/2f;
+ float y_cen = (y1+y2)/2f;
+ float rx = (x2-x1)/2f;
+ float ry = (y2-y1)/2f;
+ float halfAng = (float)(fragAngle * Math.PI / 360.);
+ float kappa = (float)(Math.abs(4. / 3. * (1. - Math.cos(halfAng)) / Math.sin(halfAng)));
+ ArrayList pointList = new ArrayList();
+ for (int i = 0; i < Nfrag; ++i) {
+ float theta0 = (float)((startAng + i*fragAngle) * Math.PI / 180.);
+ float theta1 = (float)((startAng + (i+1)*fragAngle) * Math.PI / 180.);
+ float cos0 = (float)Math.cos(theta0);
+ float cos1 = (float)Math.cos(theta1);
+ float sin0 = (float)Math.sin(theta0);
+ float sin1 = (float)Math.sin(theta1);
+ if (fragAngle > 0f) {
+ pointList.add(new float[]{x_cen + rx * cos0,
+ y_cen - ry * sin0,
+ x_cen + rx * (cos0 - kappa * sin0),
+ y_cen - ry * (sin0 + kappa * cos0),
+ x_cen + rx * (cos1 + kappa * sin1),
+ y_cen - ry * (sin1 - kappa * cos1),
+ x_cen + rx * cos1,
+ y_cen - ry * sin1});
+ }
+ else {
+ pointList.add(new float[]{x_cen + rx * cos0,
+ y_cen - ry * sin0,
+ x_cen + rx * (cos0 + kappa * sin0),
+ y_cen - ry * (sin0 - kappa * cos0),
+ x_cen + rx * (cos1 - kappa * sin1),
+ y_cen - ry * (sin1 + kappa * cos1),
+ x_cen + rx * cos1,
+ y_cen - ry * sin1});
+ }
+ }
+ return pointList;
+ }
+
+ /**
+ * Draws a partial ellipse inscribed within the rectangle x1,y1,x2,y2,
+ * starting at startAng degrees and covering extent degrees. Angles
+ * start with 0 to the right (+x) and increase counter-clockwise.
+ *
+ * @param x1 a corner of the enclosing rectangle
+ * @param y1 a corner of the enclosing rectangle
+ * @param x2 a corner of the enclosing rectangle
+ * @param y2 a corner of the enclosing rectangle
+ * @param startAng starting angle in degrees
+ * @param extent angle extent in degrees
+ */
+ public void arc(float x1, float y1, float x2, float y2, float startAng, float extent) {
+ ArrayList ar = bezierArc(x1, y1, x2, y2, startAng, extent);
+ if (ar.size() == 0)
+ return;
+ float pt[] = (float [])ar.get(0);
+ moveTo(pt[0], pt[1]);
+ for (int k = 0; k < ar.size(); ++k) {
+ pt = (float [])ar.get(k);
+ curveTo(pt[2], pt[3], pt[4], pt[5], pt[6], pt[7]);
+ }
+ }
+
+ /**
+ * Draws an ellipse inscribed within the rectangle x1,y1,x2,y2.
+ *
+ * @param x1 a corner of the enclosing rectangle
+ * @param y1 a corner of the enclosing rectangle
+ * @param x2 a corner of the enclosing rectangle
+ * @param y2 a corner of the enclosing rectangle
+ */
+ public void ellipse(float x1, float y1, float x2, float y2) {
+ arc(x1, y1, x2, y2, 0f, 360f);
+ }
+
+ /**
+ * Create a new colored tiling pattern.
+ *
+ * @param width the width of the pattern
+ * @param height the height of the pattern
+ * @param xstep the desired horizontal spacing between pattern cells.
+ * May be either positive or negative, but not zero.
+ * @param ystep the desired vertical spacing between pattern cells.
+ * May be either positive or negative, but not zero.
+ * @return the PdfPatternPainter
where the pattern will be created
+ */
+
+ public PdfPatternPainter createPattern(float width, float height, float xstep, float ystep) {
+ checkWriter();
+ if ( xstep == 0.0f || ystep == 0.0f )
+ throw new RuntimeException("XStep or YStep can not be ZERO.");
+ PdfPatternPainter painter = new PdfPatternPainter(writer);
+ painter.setWidth(width);
+ painter.setHeight(height);
+ painter.setXStep(xstep);
+ painter.setYStep(ystep);
+ writer.addSimplePattern(painter);
+ return painter;
+ }
+
+ /**
+ * Create a new colored tiling pattern. Variables xstep and ystep are set to the same values
+ * of width and height.
+ * @param width the width of the pattern
+ * @param height the height of the pattern
+ * @return the PdfPatternPainter
where the pattern will be created
+ */
+ public PdfPatternPainter createPattern(float width, float height) {
+ return createPattern(width, height, width, height);
+ }
+
+ /**
+ * Create a new uncolored tiling pattern.
+ *
+ * @param width the width of the pattern
+ * @param height the height of the pattern
+ * @param xstep the desired horizontal spacing between pattern cells.
+ * May be either positive or negative, but not zero.
+ * @param ystep the desired vertical spacing between pattern cells.
+ * May be either positive or negative, but not zero.
+ * @param color the default color. Can be null
+ * @return the PdfPatternPainter
where the pattern will be created
+ */
+ public PdfPatternPainter createPattern(float width, float height, float xstep, float ystep, Color color) {
+ checkWriter();
+ if ( xstep == 0.0f || ystep == 0.0f )
+ throw new RuntimeException("XStep or YStep can not be ZERO.");
+ PdfPatternPainter painter = new PdfPatternPainter(writer, color);
+ painter.setWidth(width);
+ painter.setHeight(height);
+ painter.setXStep(xstep);
+ painter.setYStep(ystep);
+ writer.addSimplePattern(painter);
+ return painter;
+ }
+
+ /**
+ * Create a new uncolored tiling pattern.
+ * Variables xstep and ystep are set to the same values
+ * of width and height.
+ * @param width the width of the pattern
+ * @param height the height of the pattern
+ * @param color the default color. Can be null
+ * @return the PdfPatternPainter
where the pattern will be created
+ */
+ public PdfPatternPainter createPattern(float width, float height, Color color) {
+ return createPattern(width, height, width, height, color);
+ }
+
+ /**
+ * Creates a new template.
+ *
+ * Creates a new template that is nothing more than a form XObject. This template can be included
+ * in this PdfContentByte
or in another template. Templates are only written
+ * to the output when the document is closed permitting things like showing text in the first page
+ * that is only defined in the last page.
+ *
+ * @param width the bounding box width
+ * @param height the bounding box height
+ * @return the templated created
+ */
+ public PdfTemplate createTemplate(float width, float height) {
+ return createTemplate(width, height, null);
+ }
+
+ PdfTemplate createTemplate(float width, float height, PdfName forcedName) {
+ checkWriter();
+ PdfTemplate template = new PdfTemplate(writer);
+ template.setWidth(width);
+ template.setHeight(height);
+ writer.addDirectTemplateSimple(template, forcedName);
+ return template;
+ }
+
+ /**
+ * Creates a new appearance to be used with form fields.
+ *
+ * @param width the bounding box width
+ * @param height the bounding box height
+ * @return the appearance created
+ */
+ public PdfAppearance createAppearance(float width, float height) {
+ return createAppearance(width, height, null);
+ }
+
+ PdfAppearance createAppearance(float width, float height, PdfName forcedName) {
+ checkWriter();
+ PdfAppearance template = new PdfAppearance(writer);
+ template.setWidth(width);
+ template.setHeight(height);
+ writer.addDirectTemplateSimple(template, forcedName);
+ return template;
+ }
+
+ /**
+ * Adds a PostScript XObject to this content.
+ *
+ * @param psobject the object
+ */
+ public void addPSXObject(PdfPSXObject psobject) {
+ checkWriter();
+ PdfName name = writer.addDirectTemplateSimple(psobject, null);
+ PageResources prs = getPageResources();
+ name = prs.addXObject(name, psobject.getIndirectReference());
+ content.append(name.getBytes()).append(" Do").append_i(separator);
+ }
+
+ /**
+ * Adds a template to this content.
+ *
+ * @param template the template
+ * @param a an element of the transformation matrix
+ * @param b an element of the transformation matrix
+ * @param c an element of the transformation matrix
+ * @param d an element of the transformation matrix
+ * @param e an element of the transformation matrix
+ * @param f an element of the transformation matrix
+ */
+ public void addTemplate(PdfTemplate template, float a, float b, float c, float d, float e, float f) {
+ checkWriter();
+ checkNoPattern(template);
+ PdfName name = writer.addDirectTemplateSimple(template, null);
+ PageResources prs = getPageResources();
+ name = prs.addXObject(name, template.getIndirectReference());
+ content.append("q ");
+ content.append(a).append(' ');
+ content.append(b).append(' ');
+ content.append(c).append(' ');
+ content.append(d).append(' ');
+ content.append(e).append(' ');
+ content.append(f).append(" cm ");
+ content.append(name.getBytes()).append(" Do Q").append_i(separator);
+ }
+
+ /**
+ * Adds a template to this content.
+ *
+ * @param template the template
+ * @param x the x location of this template
+ * @param y the y location of this template
+ */
+ public void addTemplate(PdfTemplate template, float x, float y) {
+ addTemplate(template, 1, 0, 0, 1, x, y);
+ }
+
+ /**
+ * Changes the current color for filling paths (device dependent colors!).
+ *
+ * Sets the color space to DeviceCMYK (or the DefaultCMYK color space),
+ * and sets the color to use for filling paths.
+ *
+ * This method is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 8.5.2.1 (page 331).
+ *
+ * Following the PDF manual, each operand must be a number between 0 (no ink) and
+ * 1 (maximum ink). This method however accepts only integers between 0x00 and 0xFF.
+ *
+ * @param cyan the intensity of cyan
+ * @param magenta the intensity of magenta
+ * @param yellow the intensity of yellow
+ * @param black the intensity of black
+ */
+
+ public void setCMYKColorFill(int cyan, int magenta, int yellow, int black) {
+ content.append((float)(cyan & 0xFF) / 0xFF);
+ content.append(' ');
+ content.append((float)(magenta & 0xFF) / 0xFF);
+ content.append(' ');
+ content.append((float)(yellow & 0xFF) / 0xFF);
+ content.append(' ');
+ content.append((float)(black & 0xFF) / 0xFF);
+ content.append(" k").append_i(separator);
+ }
+ /**
+ * Changes the current color for stroking paths (device dependent colors!).
+ *
+ * Sets the color space to DeviceCMYK (or the DefaultCMYK color space),
+ * and sets the color to use for stroking paths.
+ *
+ * This method is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 8.5.2.1 (page 331).
+ * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
+ * 1 (maximum intensity). This method however accepts only integers between 0x00 and 0xFF.
+ *
+ * @param cyan the intensity of red
+ * @param magenta the intensity of green
+ * @param yellow the intensity of blue
+ * @param black the intensity of black
+ */
+
+ public void setCMYKColorStroke(int cyan, int magenta, int yellow, int black) {
+ content.append((float)(cyan & 0xFF) / 0xFF);
+ content.append(' ');
+ content.append((float)(magenta & 0xFF) / 0xFF);
+ content.append(' ');
+ content.append((float)(yellow & 0xFF) / 0xFF);
+ content.append(' ');
+ content.append((float)(black & 0xFF) / 0xFF);
+ content.append(" K").append_i(separator);
+ }
+
+ /**
+ * Changes the current color for filling paths (device dependent colors!).
+ *
+ * Sets the color space to DeviceRGB (or the DefaultRGB color space),
+ * and sets the color to use for filling paths.
+ *
+ * This method is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 8.5.2.1 (page 331).
+ *
+ * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
+ * 1 (maximum intensity). This method however accepts only integers between 0x00 and 0xFF.
+ *
+ * @param red the intensity of red
+ * @param green the intensity of green
+ * @param blue the intensity of blue
+ */
+
+ public void setRGBColorFill(int red, int green, int blue) {
+ HelperRGB((float)(red & 0xFF) / 0xFF, (float)(green & 0xFF) / 0xFF, (float)(blue & 0xFF) / 0xFF);
+ content.append(" rg").append_i(separator);
+ }
+
+ /**
+ * Changes the current color for stroking paths (device dependent colors!).
+ *
+ * Sets the color space to DeviceRGB (or the DefaultRGB color space),
+ * and sets the color to use for stroking paths.
+ *
+ * This method is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 8.5.2.1 (page 331).
+ * Following the PDF manual, each operand must be a number between 0 (miniumum intensity) and
+ * 1 (maximum intensity). This method however accepts only integers between 0x00 and 0xFF.
+ *
+ * @param red the intensity of red
+ * @param green the intensity of green
+ * @param blue the intensity of blue
+ */
+
+ public void setRGBColorStroke(int red, int green, int blue) {
+ HelperRGB((float)(red & 0xFF) / 0xFF, (float)(green & 0xFF) / 0xFF, (float)(blue & 0xFF) / 0xFF);
+ content.append(" RG").append_i(separator);
+ }
+
+ /** Sets the stroke color. color
can be an
+ * ExtendedColor
.
+ * @param color the color
+ */
+ public void setColorStroke(Color color) {
+ PdfWriter.checkPDFXConformance(writer, PdfWriter.PDFXKEY_COLOR, color);
+ int type = ExtendedColor.getType(color);
+ switch (type) {
+ case ExtendedColor.TYPE_GRAY: {
+ setGrayStroke(((GrayColor)color).getGray());
+ break;
+ }
+ case ExtendedColor.TYPE_CMYK: {
+ CMYKColor cmyk = (CMYKColor)color;
+ setCMYKColorStrokeF(cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack());
+ break;
+ }
+ case ExtendedColor.TYPE_SEPARATION: {
+ SpotColor spot = (SpotColor)color;
+ setColorStroke(spot.getPdfSpotColor(), spot.getTint());
+ break;
+ }
+ case ExtendedColor.TYPE_PATTERN: {
+ PatternColor pat = (PatternColor) color;
+ setPatternStroke(pat.getPainter());
+ break;
+ }
+ case ExtendedColor.TYPE_SHADING: {
+ ShadingColor shading = (ShadingColor) color;
+ setShadingStroke(shading.getPdfShadingPattern());
+ break;
+ }
+ default:
+ setRGBColorStroke(color.getRed(), color.getGreen(), color.getBlue());
+ }
+ }
+
+ /** Sets the fill color. color
can be an
+ * ExtendedColor
.
+ * @param color the color
+ */
+ public void setColorFill(Color color) {
+ PdfWriter.checkPDFXConformance(writer, PdfWriter.PDFXKEY_COLOR, color);
+ int type = ExtendedColor.getType(color);
+ switch (type) {
+ case ExtendedColor.TYPE_GRAY: {
+ setGrayFill(((GrayColor)color).getGray());
+ break;
+ }
+ case ExtendedColor.TYPE_CMYK: {
+ CMYKColor cmyk = (CMYKColor)color;
+ setCMYKColorFillF(cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack());
+ break;
+ }
+ case ExtendedColor.TYPE_SEPARATION: {
+ SpotColor spot = (SpotColor)color;
+ setColorFill(spot.getPdfSpotColor(), spot.getTint());
+ break;
+ }
+ case ExtendedColor.TYPE_PATTERN: {
+ PatternColor pat = (PatternColor) color;
+ setPatternFill(pat.getPainter());
+ break;
+ }
+ case ExtendedColor.TYPE_SHADING: {
+ ShadingColor shading = (ShadingColor) color;
+ setShadingFill(shading.getPdfShadingPattern());
+ break;
+ }
+ default:
+ setRGBColorFill(color.getRed(), color.getGreen(), color.getBlue());
+ }
+ }
+
+ /** Sets the fill color to a spot color.
+ * @param sp the spot color
+ * @param tint the tint for the spot color. 0 is no color and 1
+ * is 100% color
+ */
+ public void setColorFill(PdfSpotColor sp, float tint) {
+ checkWriter();
+ state.colorDetails = writer.addSimple(sp);
+ PageResources prs = getPageResources();
+ PdfName name = state.colorDetails.getColorName();
+ name = prs.addColor(name, state.colorDetails.getIndirectReference());
+ content.append(name.getBytes()).append(" cs ").append(tint).append(" scn").append_i(separator);
+ }
+
+ /** Sets the stroke color to a spot color.
+ * @param sp the spot color
+ * @param tint the tint for the spot color. 0 is no color and 1
+ * is 100% color
+ */
+ public void setColorStroke(PdfSpotColor sp, float tint) {
+ checkWriter();
+ state.colorDetails = writer.addSimple(sp);
+ PageResources prs = getPageResources();
+ PdfName name = state.colorDetails.getColorName();
+ name = prs.addColor(name, state.colorDetails.getIndirectReference());
+ content.append(name.getBytes()).append(" CS ").append(tint).append(" SCN").append_i(separator);
+ }
+
+ /** Sets the fill color to a pattern. The pattern can be
+ * colored or uncolored.
+ * @param p the pattern
+ */
+ public void setPatternFill(PdfPatternPainter p) {
+ if (p.isStencil()) {
+ setPatternFill(p, p.getDefaultColor());
+ return;
+ }
+ checkWriter();
+ PageResources prs = getPageResources();
+ PdfName name = writer.addSimplePattern(p);
+ name = prs.addPattern(name, p.getIndirectReference());
+ content.append(PdfName.PATTERN.getBytes()).append(" cs ").append(name.getBytes()).append(" scn").append_i(separator);
+ }
+
+ /** Outputs the color values to the content.
+ * @param color The color
+ * @param tint the tint if it is a spot color, ignored otherwise
+ */
+ void outputColorNumbers(Color color, float tint) {
+ PdfWriter.checkPDFXConformance(writer, PdfWriter.PDFXKEY_COLOR, color);
+ int type = ExtendedColor.getType(color);
+ switch (type) {
+ case ExtendedColor.TYPE_RGB:
+ content.append((float)(color.getRed()) / 0xFF);
+ content.append(' ');
+ content.append((float)(color.getGreen()) / 0xFF);
+ content.append(' ');
+ content.append((float)(color.getBlue()) / 0xFF);
+ break;
+ case ExtendedColor.TYPE_GRAY:
+ content.append(((GrayColor)color).getGray());
+ break;
+ case ExtendedColor.TYPE_CMYK: {
+ CMYKColor cmyk = (CMYKColor)color;
+ content.append(cmyk.getCyan()).append(' ').append(cmyk.getMagenta());
+ content.append(' ').append(cmyk.getYellow()).append(' ').append(cmyk.getBlack());
+ break;
+ }
+ case ExtendedColor.TYPE_SEPARATION:
+ content.append(tint);
+ break;
+ default:
+ throw new RuntimeException("Invalid color type.");
+ }
+ }
+
+ /** Sets the fill color to an uncolored pattern.
+ * @param p the pattern
+ * @param color the color of the pattern
+ */
+ public void setPatternFill(PdfPatternPainter p, Color color) {
+ if (ExtendedColor.getType(color) == ExtendedColor.TYPE_SEPARATION)
+ setPatternFill(p, color, ((SpotColor)color).getTint());
+ else
+ setPatternFill(p, color, 0);
+ }
+
+ /** Sets the fill color to an uncolored pattern.
+ * @param p the pattern
+ * @param color the color of the pattern
+ * @param tint the tint if the color is a spot color, ignored otherwise
+ */
+ public void setPatternFill(PdfPatternPainter p, Color color, float tint) {
+ checkWriter();
+ if (!p.isStencil())
+ throw new RuntimeException("An uncolored pattern was expected.");
+ PageResources prs = getPageResources();
+ PdfName name = writer.addSimplePattern(p);
+ name = prs.addPattern(name, p.getIndirectReference());
+ ColorDetails csDetail = writer.addSimplePatternColorspace(color);
+ PdfName cName = prs.addColor(csDetail.getColorName(), csDetail.getIndirectReference());
+ content.append(cName.getBytes()).append(" cs").append_i(separator);
+ outputColorNumbers(color, tint);
+ content.append(' ').append(name.getBytes()).append(" scn").append_i(separator);
+ }
+
+ /** Sets the stroke color to an uncolored pattern.
+ * @param p the pattern
+ * @param color the color of the pattern
+ */
+ public void setPatternStroke(PdfPatternPainter p, Color color) {
+ if (ExtendedColor.getType(color) == ExtendedColor.TYPE_SEPARATION)
+ setPatternStroke(p, color, ((SpotColor)color).getTint());
+ else
+ setPatternStroke(p, color, 0);
+ }
+
+ /** Sets the stroke color to an uncolored pattern.
+ * @param p the pattern
+ * @param color the color of the pattern
+ * @param tint the tint if the color is a spot color, ignored otherwise
+ */
+ public void setPatternStroke(PdfPatternPainter p, Color color, float tint) {
+ checkWriter();
+ if (!p.isStencil())
+ throw new RuntimeException("An uncolored pattern was expected.");
+ PageResources prs = getPageResources();
+ PdfName name = writer.addSimplePattern(p);
+ name = prs.addPattern(name, p.getIndirectReference());
+ ColorDetails csDetail = writer.addSimplePatternColorspace(color);
+ PdfName cName = prs.addColor(csDetail.getColorName(), csDetail.getIndirectReference());
+ content.append(cName.getBytes()).append(" CS").append_i(separator);
+ outputColorNumbers(color, tint);
+ content.append(' ').append(name.getBytes()).append(" SCN").append_i(separator);
+ }
+
+ /** Sets the stroke color to a pattern. The pattern can be
+ * colored or uncolored.
+ * @param p the pattern
+ */
+ public void setPatternStroke(PdfPatternPainter p) {
+ if (p.isStencil()) {
+ setPatternStroke(p, p.getDefaultColor());
+ return;
+ }
+ checkWriter();
+ PageResources prs = getPageResources();
+ PdfName name = writer.addSimplePattern(p);
+ name = prs.addPattern(name, p.getIndirectReference());
+ content.append(PdfName.PATTERN.getBytes()).append(" CS ").append(name.getBytes()).append(" SCN").append_i(separator);
+ }
+
+ /**
+ * Paints using a shading object.
+ * @param shading the shading object
+ */
+ public void paintShading(PdfShading shading) {
+ writer.addSimpleShading(shading);
+ PageResources prs = getPageResources();
+ PdfName name = prs.addShading(shading.getShadingName(), shading.getShadingReference());
+ content.append(name.getBytes()).append(" sh").append_i(separator);
+ ColorDetails details = shading.getColorDetails();
+ if (details != null)
+ prs.addColor(details.getColorName(), details.getIndirectReference());
+ }
+
+ /**
+ * Paints using a shading pattern.
+ * @param shading the shading pattern
+ */
+ public void paintShading(PdfShadingPattern shading) {
+ paintShading(shading.getShading());
+ }
+
+ /**
+ * Sets the shading fill pattern.
+ * @param shading the shading pattern
+ */
+ public void setShadingFill(PdfShadingPattern shading) {
+ writer.addSimpleShadingPattern(shading);
+ PageResources prs = getPageResources();
+ PdfName name = prs.addPattern(shading.getPatternName(), shading.getPatternReference());
+ content.append(PdfName.PATTERN.getBytes()).append(" cs ").append(name.getBytes()).append(" scn").append_i(separator);
+ ColorDetails details = shading.getColorDetails();
+ if (details != null)
+ prs.addColor(details.getColorName(), details.getIndirectReference());
+ }
+
+ /**
+ * Sets the shading stroke pattern
+ * @param shading the shading pattern
+ */
+ public void setShadingStroke(PdfShadingPattern shading) {
+ writer.addSimpleShadingPattern(shading);
+ PageResources prs = getPageResources();
+ PdfName name = prs.addPattern(shading.getPatternName(), shading.getPatternReference());
+ content.append(PdfName.PATTERN.getBytes()).append(" CS ").append(name.getBytes()).append(" SCN").append_i(separator);
+ ColorDetails details = shading.getColorDetails();
+ if (details != null)
+ prs.addColor(details.getColorName(), details.getIndirectReference());
+ }
+
+ /** Check if we have a valid PdfWriter.
+ *
+ */
+ protected void checkWriter() {
+ if (writer == null)
+ throw new NullPointerException("The writer in PdfContentByte is null.");
+ }
+
+ /**
+ * Show an array of text.
+ * @param text array of text
+ */
+ public void showText(PdfTextArray text) {
+ if (state.fontDetails == null)
+ throw new NullPointerException("Font and size must be set before writing any text");
+ content.append("[");
+ ArrayList arrayList = text.getArrayList();
+ boolean lastWasNumber = false;
+ for (int k = 0; k < arrayList.size(); ++k) {
+ Object obj = arrayList.get(k);
+ if (obj instanceof String) {
+ showText2((String)obj);
+ lastWasNumber = false;
+ }
+ else {
+ if (lastWasNumber)
+ content.append(' ');
+ else
+ lastWasNumber = true;
+ content.append(((Float)obj).floatValue());
+ }
+ }
+ content.append("]TJ").append_i(separator);
+ }
+
+ /**
+ * Gets the PdfWriter
in use by this object.
+ * @return the PdfWriter
in use by this object
+ */
+ public PdfWriter getPdfWriter() {
+ return writer;
+ }
+
+ /**
+ * Gets the PdfDocument
in use by this object.
+ * @return the PdfDocument
in use by this object
+ */
+ public PdfDocument getPdfDocument() {
+ return pdf;
+ }
+
+ /**
+ * Implements a link to other part of the document. The jump will
+ * be made to a local destination with the same name, that must exist.
+ * @param name the name for this link
+ * @param llx the lower left x corner of the activation area
+ * @param lly the lower left y corner of the activation area
+ * @param urx the upper right x corner of the activation area
+ * @param ury the upper right y corner of the activation area
+ */
+ public void localGoto(String name, float llx, float lly, float urx, float ury) {
+ pdf.localGoto(name, llx, lly, urx, ury);
+ }
+
+ /**
+ * The local destination to where a local goto with the same
+ * name will jump.
+ * @param name the name of this local destination
+ * @param destination the PdfDestination
with the jump coordinates
+ * @return true
if the local destination was added,
+ * false
if a local destination with the same name
+ * already exists
+ */
+ public boolean localDestination(String name, PdfDestination destination) {
+ return pdf.localDestination(name, destination);
+ }
+
+ /**
+ * Gets a duplicate of this PdfContentByte
. All
+ * the members are copied by reference but the buffer stays different.
+ *
+ * @return a copy of this PdfContentByte
+ */
+ public PdfContentByte getDuplicate() {
+ return new PdfContentByte(writer);
+ }
+
+ /**
+ * Implements a link to another document.
+ * @param filename the filename for the remote document
+ * @param name the name to jump to
+ * @param llx the lower left x corner of the activation area
+ * @param lly the lower left y corner of the activation area
+ * @param urx the upper right x corner of the activation area
+ * @param ury the upper right y corner of the activation area
+ */
+ public void remoteGoto(String filename, String name, float llx, float lly, float urx, float ury) {
+ pdf.remoteGoto(filename, name, llx, lly, urx, ury);
+ }
+
+ /**
+ * Implements a link to another document.
+ * @param filename the filename for the remote document
+ * @param page the page to jump to
+ * @param llx the lower left x corner of the activation area
+ * @param lly the lower left y corner of the activation area
+ * @param urx the upper right x corner of the activation area
+ * @param ury the upper right y corner of the activation area
+ */
+ public void remoteGoto(String filename, int page, float llx, float lly, float urx, float ury) {
+ pdf.remoteGoto(filename, page, llx, lly, urx, ury);
+ }
+ /**
+ * Adds a round rectangle to the current path.
+ *
+ * @param x x-coordinate of the starting point
+ * @param y y-coordinate of the starting point
+ * @param w width
+ * @param h height
+ * @param r radius of the arc corner
+ */
+ public void roundRectangle(float x, float y, float w, float h, float r) {
+ if (w < 0) {
+ x += w;
+ w = -w;
+ }
+ if (h < 0) {
+ y += h;
+ h = -h;
+ }
+ if (r < 0)
+ r = -r;
+ float b = 0.4477f;
+ moveTo(x + r, y);
+ lineTo(x + w - r, y);
+ curveTo(x + w - r * b, y, x + w, y + r * b, x + w, y + r);
+ lineTo(x + w, y + h - r);
+ curveTo(x + w, y + h - r * b, x + w - r * b, y + h, x + w - r, y + h);
+ lineTo(x + r, y + h);
+ curveTo(x + r * b, y + h, x, y + h - r * b, x, y + h - r);
+ lineTo(x, y + r);
+ curveTo(x, y + r * b, x + r * b, y, x + r, y);
+ }
+
+ /** Implements an action in an area.
+ * @param action the PdfAction
+ * @param llx the lower left x corner of the activation area
+ * @param lly the lower left y corner of the activation area
+ * @param urx the upper right x corner of the activation area
+ * @param ury the upper right y corner of the activation area
+ */
+ public void setAction(PdfAction action, float llx, float lly, float urx, float ury) {
+ pdf.setAction(action, llx, lly, urx, ury);
+ }
+
+ /** Outputs a String
directly to the content.
+ * @param s the String
+ */
+ public void setLiteral(String s) {
+ content.append(s);
+ }
+
+ /** Outputs a char
directly to the content.
+ * @param c the char
+ */
+ public void setLiteral(char c) {
+ content.append(c);
+ }
+
+ /** Outputs a float
directly to the content.
+ * @param n the float
+ */
+ public void setLiteral(float n) {
+ content.append(n);
+ }
+
+ /** Throws an error if it is a pattern.
+ * @param t the object to check
+ */
+ void checkNoPattern(PdfTemplate t) {
+ if (t.getType() == PdfTemplate.TYPE_PATTERN)
+ throw new RuntimeException("Invalid use of a pattern. A template was expected.");
+ }
+
+ /**
+ * Draws a TextField.
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @param on
+ */
+ public void drawRadioField(float llx, float lly, float urx, float ury, boolean on) {
+ if (llx > urx) { float x = llx; llx = urx; urx = x; }
+ if (lly > ury) { float y = lly; lly = ury; ury = y; }
+ // silver circle
+ setLineWidth(1);
+ setLineCap(1);
+ setColorStroke(new Color(0xC0, 0xC0, 0xC0));
+ arc(llx + 1f, lly + 1f, urx - 1f, ury - 1f, 0f, 360f);
+ stroke();
+ // gray circle-segment
+ setLineWidth(1);
+ setLineCap(1);
+ setColorStroke(new Color(0xA0, 0xA0, 0xA0));
+ arc(llx + 0.5f, lly + 0.5f, urx - 0.5f, ury - 0.5f, 45, 180);
+ stroke();
+ // black circle-segment
+ setLineWidth(1);
+ setLineCap(1);
+ setColorStroke(new Color(0x00, 0x00, 0x00));
+ arc(llx + 1.5f, lly + 1.5f, urx - 1.5f, ury - 1.5f, 45, 180);
+ stroke();
+ if (on) {
+ // gray circle
+ setLineWidth(1);
+ setLineCap(1);
+ setColorFill(new Color(0x00, 0x00, 0x00));
+ arc(llx + 4f, lly + 4f, urx - 4f, ury - 4f, 0, 360);
+ fill();
+ }
+ }
+
+ /**
+ * Draws a TextField.
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ */
+ public void drawTextField(float llx, float lly, float urx, float ury) {
+ if (llx > urx) { float x = llx; llx = urx; urx = x; }
+ if (lly > ury) { float y = lly; lly = ury; ury = y; }
+ // silver rectangle not filled
+ setColorStroke(new Color(0xC0, 0xC0, 0xC0));
+ setLineWidth(1);
+ setLineCap(0);
+ rectangle(llx, lly, urx - llx, ury - lly);
+ stroke();
+ // white rectangle filled
+ setLineWidth(1);
+ setLineCap(0);
+ setColorFill(new Color(0xFF, 0xFF, 0xFF));
+ rectangle(llx + 0.5f, lly + 0.5f, urx - llx - 1f, ury -lly - 1f);
+ fill();
+ // silver lines
+ setColorStroke(new Color(0xC0, 0xC0, 0xC0));
+ setLineWidth(1);
+ setLineCap(0);
+ moveTo(llx + 1f, lly + 1.5f);
+ lineTo(urx - 1.5f, lly + 1.5f);
+ lineTo(urx - 1.5f, ury - 1f);
+ stroke();
+ // gray lines
+ setColorStroke(new Color(0xA0, 0xA0, 0xA0));
+ setLineWidth(1);
+ setLineCap(0);
+ moveTo(llx + 1f, lly + 1);
+ lineTo(llx + 1f, ury - 1f);
+ lineTo(urx - 1f, ury - 1f);
+ stroke();
+ // black lines
+ setColorStroke(new Color(0x00, 0x00, 0x00));
+ setLineWidth(1);
+ setLineCap(0);
+ moveTo(llx + 2f, lly + 2f);
+ lineTo(llx + 2f, ury - 2f);
+ lineTo(urx - 2f, ury - 2f);
+ stroke();
+ }
+
+ /**
+ * Draws a button.
+ * @param llx
+ * @param lly
+ * @param urx
+ * @param ury
+ * @param text
+ * @param bf
+ * @param size
+ */
+ public void drawButton(float llx, float lly, float urx, float ury, String text, BaseFont bf, float size) {
+ if (llx > urx) { float x = llx; llx = urx; urx = x; }
+ if (lly > ury) { float y = lly; lly = ury; ury = y; }
+ // black rectangle not filled
+ setColorStroke(new Color(0x00, 0x00, 0x00));
+ setLineWidth(1);
+ setLineCap(0);
+ rectangle(llx, lly, urx - llx, ury - lly);
+ stroke();
+ // silver rectangle filled
+ setLineWidth(1);
+ setLineCap(0);
+ setColorFill(new Color(0xC0, 0xC0, 0xC0));
+ rectangle(llx + 0.5f, lly + 0.5f, urx - llx - 1f, ury -lly - 1f);
+ fill();
+ // white lines
+ setColorStroke(new Color(0xFF, 0xFF, 0xFF));
+ setLineWidth(1);
+ setLineCap(0);
+ moveTo(llx + 1f, lly + 1f);
+ lineTo(llx + 1f, ury - 1f);
+ lineTo(urx - 1f, ury - 1f);
+ stroke();
+ // dark grey lines
+ setColorStroke(new Color(0xA0, 0xA0, 0xA0));
+ setLineWidth(1);
+ setLineCap(0);
+ moveTo(llx + 1f, lly + 1f);
+ lineTo(urx - 1f, lly + 1f);
+ lineTo(urx - 1f, ury - 1f);
+ stroke();
+ // text
+ resetRGBColorFill();
+ beginText();
+ setFontAndSize(bf, size);
+ showTextAligned(PdfContentByte.ALIGN_CENTER, text, llx + (urx - llx) / 2, lly + (ury - lly - size) / 2, 0);
+ endText();
+ }
+
+ /** Gets a Graphics2D
to write on. The graphics
+ * are translated to PDF commands as shapes. No PDF fonts will appear.
+ * @param width the width of the panel
+ * @param height the height of the panel
+ * @return a Graphics2D
+ */
+ /* ssteward: dropped in 1.44
+ public java.awt.Graphics2D createGraphicsShapes(float width, float height) {
+ return new PdfGraphics2D(this, width, height, null, true, false, 0);
+ }
+ */
+
+ /** Gets a Graphics2D
to print on. The graphics
+ * are translated to PDF commands as shapes. No PDF fonts will appear.
+ * @param width the width of the panel
+ * @param height the height of the panel
+ * @param printerJob a printer job
+ * @return a Graphics2D
+ */
+ /* ssteward: dropped in 1.44
+ public java.awt.Graphics2D createPrinterGraphicsShapes(float width, float height, PrinterJob printerJob) {
+ return new PdfPrinterGraphics2D(this, width, height, null, true, false, 0, printerJob);
+ }
+ */
+
+ /** Gets a Graphics2D
to write on. The graphics
+ * are translated to PDF commands.
+ * @param width the width of the panel
+ * @param height the height of the panel
+ * @return a Graphics2D
+ */
+ /* ssteward: dropped in 1.44
+ public java.awt.Graphics2D createGraphics(float width, float height) {
+ return new PdfGraphics2D(this, width, height, null, false, false, 0);
+ }
+ */
+
+ /** Gets a Graphics2D
to print on. The graphics
+ * are translated to PDF commands.
+ * @param width the width of the panel
+ * @param height the height of the panel
+ * @param printerJob
+ * @return a Graphics2D
+ */
+ /* ssteward: dropped in 1.44
+ public java.awt.Graphics2D createPrinterGraphics(float width, float height, PrinterJob printerJob) {
+ return new PdfPrinterGraphics2D(this, width, height, null, false, false, 0, printerJob);
+ }
+ */
+
+ /** Gets a Graphics2D
to write on. The graphics
+ * are translated to PDF commands.
+ * @param width the width of the panel
+ * @param height the height of the panel
+ * @param convertImagesToJPEG
+ * @param quality
+ * @return a Graphics2D
+ */
+ /* ssteward: dropped in 1.44
+ public java.awt.Graphics2D createGraphics(float width, float height, boolean convertImagesToJPEG, float quality) {
+ return new PdfGraphics2D(this, width, height, null, false, convertImagesToJPEG, quality);
+ }
+ */
+
+ /** Gets a Graphics2D
to print on. The graphics
+ * are translated to PDF commands.
+ * @param width the width of the panel
+ * @param height the height of the panel
+ * @param convertImagesToJPEG
+ * @param quality
+ * @param printerJob
+ * @return a Graphics2D
+ */
+ /* ssteward: dropped in 1.44
+ public java.awt.Graphics2D createPrinterGraphics(float width, float height, boolean convertImagesToJPEG, float quality, PrinterJob printerJob) {
+ return new PdfPrinterGraphics2D(this, width, height, null, false, convertImagesToJPEG, quality, printerJob);
+ }
+ */
+
+ /** Gets a Graphics2D
to print on. The graphics
+ * are translated to PDF commands.
+ * @param width
+ * @param height
+ * @param convertImagesToJPEG
+ * @param quality
+ * @return A Graphics2D object
+ */
+ /* ssteward: dropped in 1.44
+ public java.awt.Graphics2D createGraphicsShapes(float width, float height, boolean convertImagesToJPEG, float quality) {
+ return new PdfGraphics2D(this, width, height, null, true, convertImagesToJPEG, quality);
+ }
+ */
+
+ /** Gets a Graphics2D
to print on. The graphics
+ * are translated to PDF commands.
+ * @param width
+ * @param height
+ * @param convertImagesToJPEG
+ * @param quality
+ * @param printerJob
+ * @return a Graphics2D object
+ */
+ /* ssteward: dropped in 1.44
+ public java.awt.Graphics2D createPrinterGraphicsShapes(float width, float height, boolean convertImagesToJPEG, float quality, PrinterJob printerJob) {
+ return new PdfPrinterGraphics2D(this, width, height, null, true, convertImagesToJPEG, quality, printerJob);
+ }
+ */
+
+ /** Gets a Graphics2D
to write on. The graphics
+ * are translated to PDF commands.
+ * @param width the width of the panel
+ * @param height the height of the panel
+ * @param fontMapper the mapping from awt fonts to BaseFont
+ * @return a Graphics2D
+ */
+ /* ssteward: dropped in 1.44
+ public java.awt.Graphics2D createGraphics(float width, float height, FontMapper fontMapper) {
+ return new PdfGraphics2D(this, width, height, fontMapper, false, false, 0);
+ }
+ */
+
+ /** Gets a Graphics2D
to print on. The graphics
+ * are translated to PDF commands.
+ * @param width the width of the panel
+ * @param height the height of the panel
+ * @param fontMapper the mapping from awt fonts to BaseFont
+ * @param printerJob a printer job
+ * @return a Graphics2D
+ */
+ /* ssteward: dropped in 1.44
+ public java.awt.Graphics2D createPrinterGraphics(float width, float height, FontMapper fontMapper, PrinterJob printerJob) {
+ return new PdfPrinterGraphics2D(this, width, height, fontMapper, false, false, 0, printerJob);
+ }
+ */
+
+ /** Gets a Graphics2D
to write on. The graphics
+ * are translated to PDF commands.
+ * @param width the width of the panel
+ * @param height the height of the panel
+ * @param fontMapper the mapping from awt fonts to BaseFont
+ * @param convertImagesToJPEG converts awt images to jpeg before inserting in pdf
+ * @param quality the quality of the jpeg
+ * @return a Graphics2D
+ */
+ /* ssteward: dropped in 1.44
+ public java.awt.Graphics2D createGraphics(float width, float height, FontMapper fontMapper, boolean convertImagesToJPEG, float quality) {
+ return new PdfGraphics2D(this, width, height, fontMapper, false, convertImagesToJPEG, quality);
+ }
+ */
+
+ /** Gets a Graphics2D
to print on. The graphics
+ * are translated to PDF commands.
+ * @param width the width of the panel
+ * @param height the height of the panel
+ * @param fontMapper the mapping from awt fonts to BaseFont
+ * @param convertImagesToJPEG converts awt images to jpeg before inserting in pdf
+ * @param quality the quality of the jpeg
+ * @param printerJob a printer job
+ * @return a Graphics2D
+ */
+ /* ssteward: dropped in 1.44
+ public java.awt.Graphics2D createPrinterGraphics(float width, float height, FontMapper fontMapper, boolean convertImagesToJPEG, float quality, PrinterJob printerJob) {
+ return new PdfPrinterGraphics2D(this, width, height, fontMapper, false, convertImagesToJPEG, quality, printerJob);
+ }
+ */
+
+ PageResources getPageResources() {
+ return pdf.getPageResources();
+ }
+
+ /** Sets the graphic state
+ * @param gstate the graphic state
+ */
+ public void setGState(PdfGState gstate) {
+ PdfObject obj[] = writer.addSimpleExtGState(gstate);
+ PageResources prs = getPageResources();
+ PdfName name = prs.addExtGState((PdfName)obj[0], (PdfIndirectReference)obj[1]);
+ content.append(name.getBytes()).append(" gs").append_i(separator);
+ }
+
+ /**
+ * Begins a graphic block whose visibility is controled by the layer
.
+ * Blocks can be nested. Each block must be terminated by an {@link #endLayer()}.
+ * Note that nested layers with {@link PdfLayer#addChild(PdfLayer)} only require a single
+ * call to this method and a single call to {@link #endLayer()}; all the nesting control
+ * is built in.
+ * @param layer the layer
+ */
+ public void beginLayer(PdfOCG layer) {
+ if ((layer instanceof PdfLayer) && ((PdfLayer)layer).getTitle() != null)
+ throw new IllegalArgumentException("A title is not a layer");
+ if (layerDepth == null)
+ layerDepth = new ArrayList();
+ if (layer instanceof PdfLayerMembership) {
+ layerDepth.add(new Integer(1));
+ beginLayer2(layer);
+ return;
+ }
+ int n = 0;
+ PdfLayer la = (PdfLayer)layer;
+ while (la != null) {
+ if (la.getTitle() == null) {
+ beginLayer2(la);
+ ++n;
+ }
+ la = la.getParent();
+ }
+ layerDepth.add(new Integer(n));
+ }
+
+ private void beginLayer2(PdfOCG layer) {
+ PdfName name = (PdfName)writer.addSimpleProperty(layer, layer.getRef())[0];
+ PageResources prs = getPageResources();
+ name = prs.addProperty(name, layer.getRef());
+ content.append("/OC ").append(name.getBytes()).append(" BDC").append_i(separator);
+ }
+
+ /**
+ * Ends a layer controled graphic block. It will end the most recent open block.
+ */
+ public void endLayer() {
+ int n = 1;
+ if (layerDepth != null && layerDepth.size() > 0) {
+ n = ((Integer)layerDepth.get(layerDepth.size() - 1)).intValue();
+ layerDepth.remove(layerDepth.size() - 1);
+ }
+ while (n-- > 0)
+ content.append("EMC").append_i(separator);
+ }
+
+ /** Concatenates a transformation to the current transformation
+ * matrix.
+ * @param af the transformation
+ */
+ public void transform(AffineTransform af) {
+ double arr[] = new double[6];
+ af.getMatrix(arr);
+ content.append(arr[0]).append(' ').append(arr[1]).append(' ').append(arr[2]).append(' ');
+ content.append(arr[3]).append(' ').append(arr[4]).append(' ').append(arr[5]).append(" cm").append_i(separator);
+ }
+
+ void addAnnotation(PdfAnnotation annot) {
+ writer.addAnnotation(annot);
+ }
+
+ /**
+ * Sets the default colorspace.
+ * @param name the name of the colorspace. It can be PdfName.DEFAULTGRAY
, PdfName.DEFAULTRGB
+ * or PdfName.DEFAULTCMYK
+ * @param obj the colorspace. A null
or PdfNull
removes any colorspace with the same name
+ */
+ public void setDefaultColorspace(PdfName name, PdfObject obj) {
+ PageResources prs = getPageResources();
+ prs.addDefaultColor(name, obj);
+ }
+
+ /**
+ * Begins a marked content sequence. This sequence will be tagged with the structure struc
.
+ * The same structure can be used several times to connect text that belongs to the same logical segment
+ * but is in a different location, like the same paragraph crossing to another page, for example.
+ * @param struc the tagging structure
+ */
+ public void beginMarkedContentSequence(PdfStructureElement struc) {
+ PdfObject obj = struc.get(PdfName.K);
+ int mark = pdf.getMarkPoint();
+ if (obj != null) {
+ PdfArray ar = null;
+ if (obj.isNumber()) {
+ ar = new PdfArray();
+ ar.add(obj);
+ struc.put(PdfName.K, ar);
+ }
+ else if (obj.isArray()) {
+ ar = (PdfArray)obj;
+ if (!((PdfObject)ar.getArrayList().get(0)).isNumber())
+ throw new IllegalArgumentException("The structure has kids.");
+ }
+ else
+ throw new IllegalArgumentException("Unknown object at /K " + obj.getClass().toString());
+ PdfDictionary dic = new PdfDictionary(PdfName.MCR);
+ dic.put(PdfName.PG, writer.getCurrentPage());
+ dic.put(PdfName.MCID, new PdfNumber(mark));
+ ar.add(dic);
+ struc.setPageMark(writer.getPageNumber() - 1, -1);
+ }
+ else {
+ struc.setPageMark(writer.getPageNumber() - 1, mark);
+ struc.put(PdfName.PG, writer.getCurrentPage());
+ }
+ pdf.incMarkPoint();
+ content.append(struc.get(PdfName.S).getBytes()).append(" <> BDC").append_i(separator);
+ }
+
+ /**
+ * Ends a marked content sequence
+ */
+ public void endMarkedContentSequence() {
+ content.append("EMC").append_i(separator);
+ }
+
+ /**
+ * Begins a marked content sequence. If property is null
the mark will be of the type
+ * BMC
otherwise it will be BDC
.
+ * @param tag the tag
+ * @param property the property
+ * @param inline true
to include the property in the content or false
+ * to include the property in the resource dictionary with the possibility of reusing
+ */
+ public void beginMarkedContentSequence(PdfName tag, PdfDictionary property, boolean inline) {
+ if (property == null) {
+ content.append(tag.getBytes()).append(" BMC").append_i(separator);
+ return;
+ }
+ content.append(tag.getBytes()).append(' ');
+ if (inline)
+ try {
+ property.toPdf(writer, content);
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ else {
+ PdfObject[] objs;
+ if (writer.propertyExists(property))
+ objs = writer.addSimpleProperty(property, null);
+ else
+ objs = writer.addSimpleProperty(property, writer.getPdfIndirectReference());
+ PdfName name = (PdfName)objs[0];
+ PageResources prs = getPageResources();
+ name = prs.addProperty(name, (PdfIndirectReference)objs[1]);
+ content.append(name.getBytes());
+ }
+ content.append(" BDC").append_i(separator);
+ }
+
+ /**
+ * This is just a shorthand to beginMarkedContentSequence(tag, null, false)
.
+ * @param tag the tag
+ */
+ public void beginMarkedContentSequence(PdfName tag) {
+ beginMarkedContentSequence(tag, null, false);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfContents.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfContents.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfContents.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfContents.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,137 @@
+/*
+ * $Id: PdfContents.java,v 1.26 2002/06/20 13:28:22 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.DocWriter;
+import pdftk.com.lowagie.text.Document;
+import pdftk.com.lowagie.text.Rectangle;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.util.zip.DeflaterOutputStream;
+
+/**
+ * PdfContents
is a PdfStream
containing the contents (text + graphics) of a PdfPage
.
+ */
+
+class PdfContents extends PdfStream {
+
+ static final byte SAVESTATE[] = DocWriter.getISOBytes("q\n");
+ static final byte RESTORESTATE[] = DocWriter.getISOBytes("Q\n");
+ static final byte ROTATE90[] = DocWriter.getISOBytes("0 1 -1 0 ");
+ static final byte ROTATE180[] = DocWriter.getISOBytes("-1 0 0 -1 ");
+ static final byte ROTATE270[] = DocWriter.getISOBytes("0 -1 1 0 ");
+ static final byte ROTATEFINAL[] = DocWriter.getISOBytes(" cm\n");
+ // constructor
+
+/**
+ * Constructs a PdfContents
-object, containing text and general graphics.
+ *
+ * @param under the direct content that is under all others
+ * @param content the graphics in a page
+ * @param text the text in a page
+ * @param secondContent the direct content that is over all others
+ * @throws BadPdfFormatException on error
+ */
+
+ PdfContents(PdfContentByte under, PdfContentByte content, PdfContentByte text, PdfContentByte secondContent, Rectangle page) throws BadPdfFormatException {
+ super();
+ try {
+ OutputStream out = null;
+ streamBytes = new ByteArrayOutputStream();
+ if (Document.compress)
+ {
+ compressed = true;
+ out = new DeflaterOutputStream(streamBytes);
+ }
+ else
+ out = streamBytes;
+ int rotation = page.getRotation();
+ switch (rotation) {
+ case 90:
+ out.write(ROTATE90);
+ out.write(DocWriter.getISOBytes(ByteBuffer.formatDouble(page.top())));
+ out.write(' ');
+ out.write('0');
+ out.write(ROTATEFINAL);
+ break;
+ case 180:
+ out.write(ROTATE180);
+ out.write(DocWriter.getISOBytes(ByteBuffer.formatDouble(page.right())));
+ out.write(' ');
+ out.write(DocWriter.getISOBytes(ByteBuffer.formatDouble(page.top())));
+ out.write(ROTATEFINAL);
+ break;
+ case 270:
+ out.write(ROTATE270);
+ out.write('0');
+ out.write(' ');
+ out.write(DocWriter.getISOBytes(ByteBuffer.formatDouble(page.right())));
+ out.write(ROTATEFINAL);
+ break;
+ }
+ if (under.size() > 0) {
+ out.write(SAVESTATE);
+ under.getInternalBuffer().writeTo(out);
+ out.write(RESTORESTATE);
+ }
+ if (content.size() > 0) {
+ out.write(SAVESTATE);
+ content.getInternalBuffer().writeTo(out);
+ out.write(RESTORESTATE);
+ }
+ if (text != null) {
+ out.write(SAVESTATE);
+ text.getInternalBuffer().writeTo(out);
+ out.write(RESTORESTATE);
+ }
+ if (secondContent.size() > 0) {
+ secondContent.getInternalBuffer().writeTo(out);
+ }
+ out.close();
+ }
+ catch (Exception e) {
+ throw new BadPdfFormatException(e.getMessage());
+ }
+ put(PdfName.LENGTH, new PdfNumber(streamBytes.size()));
+ if (compressed)
+ put(PdfName.FILTER, PdfName.FLATEDECODE);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfCopy.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfCopy.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfCopy.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfCopy.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,765 @@
+/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * $Id: PdfCopy.java,v 1.35 2005/05/04 14:32:21 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ * Co-Developer of the code is Sid Steward. Portions created by the Co-Developer
+ * are Copyright (C) 2004, 2010 by Sid Steward. All Rights Reserved.
+ *
+ * This module by Mark Thompson. Copyright (C) 2002 Mark Thompson
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
+import java.io.*;
+import pdftk.com.lowagie.text.ExceptionConverter;
+import pdftk.com.lowagie.text.Document;
+import pdftk.com.lowagie.text.DocumentException;
+
+import java.util.HashSet;
+
+/**
+ * Make copies of PDF documents. Documents can be edited after reading and
+ * before writing them out.
+ * @author Mark Thompson
+ */
+
+public class PdfCopy extends PdfWriter {
+ /**
+ * This class holds information about indirect references, since they are
+ * renumbered by iText.
+ */
+ static class IndirectReferences {
+ PdfIndirectReference theRef;
+ boolean hasCopied;
+ IndirectReferences(PdfIndirectReference ref) {
+ theRef = ref;
+ hasCopied = false;
+ }
+ void setCopied() { hasCopied = true; }
+ boolean getCopied() { return hasCopied; }
+ PdfIndirectReference getRef() { return theRef; }
+ };
+ protected HashMap indirects;
+ protected HashMap indirectMap;
+ protected int currentObjectNum = 1;
+ protected PdfReader reader;
+ // ssteward: why does PdfCopy have an acroForm, when PdfDocument already has one
+ //protected PdfIndirectReference acroForm;
+ protected PdfIndirectReference topPageParent;
+ protected ArrayList pageNumbersToRefs = new ArrayList();
+ //protected List newBookmarks; // ssteward: pdftk 1.46
+ protected PdfIndirectReference m_new_bookmarks; // ssteward: pdftk 1.46
+ protected PdfIndirectReference m_new_extensions; // ssteward: pdftk 1.46
+
+ // ssteward: pdftk 1.10; to ensure unique form field names, as pages are added
+ protected HashSet fullFormFieldNames; // all full field names; track to prevent collision
+ protected HashSet topFormFieldNames; // across all readers; track to prevent collision
+ protected class TopFormFieldData {
+ HashMap newNamesRefs; // map new top parent field names to refs
+ HashMap newNamesKids; // map new top parent field names to kids PdfArray
+ HashSet allNames; // ~all~ names, new and not-new
+ public TopFormFieldData() {
+ newNamesRefs= new HashMap();
+ newNamesKids= new HashMap();
+ allNames= new HashSet();
+ }
+ };
+ protected HashMap topFormFieldReadersData; // I wish this was C++, where I could templates
+
+ /**
+ * A key to allow us to hash indirect references
+ */
+ protected static class RefKey {
+ int num;
+ int gen;
+ RefKey(int num, int gen) {
+ this.num = num;
+ this.gen = gen;
+ }
+ RefKey(PdfIndirectReference ref) {
+ num = ref.getNumber();
+ gen = ref.getGeneration();
+ }
+ RefKey(PRIndirectReference ref) {
+ num = ref.getNumber();
+ gen = ref.getGeneration();
+ }
+ public int hashCode() {
+ return (gen<<16)+num;
+ }
+ public boolean equals(Object o) {
+ RefKey other = (RefKey)o;
+ return this.gen == other.gen && this.num == other.num;
+ }
+ public String toString() {
+ return "" + num + " " + gen;
+ }
+ }
+
+ /**
+ * Constructor
+ * @param document
+ * @param os outputstream
+ */
+ public PdfCopy(Document document, OutputStream os) throws DocumentException {
+ super(new PdfDocument(), os);
+ document.addDocListener(pdf);
+ pdf.addWriter(this);
+ indirectMap = new HashMap();
+
+ // ssteward: pdftk 1.10
+ fullFormFieldNames = new HashSet();
+ topFormFieldNames = new HashSet();
+ topFormFieldReadersData = new HashMap();
+ }
+ public void open() {
+ super.open();
+ topPageParent = getPdfIndirectReference();
+ root.setLinearMode(topPageParent);
+ }
+
+ /**
+ * Grabs a page from the input document
+ * @param reader the reader of the document
+ * @param pageNumber which page to get
+ * @return the page
+ */
+ public PdfImportedPage getImportedPage(PdfReader reader, int pageNumber) {
+ if (currentPdfReaderInstance != null) {
+ if (currentPdfReaderInstance.getReader() != reader) {
+ try {
+ currentPdfReaderInstance.getReader().close();
+ currentPdfReaderInstance.getReaderFile().close();
+ }
+ catch (IOException ioe) {
+ // empty on purpose
+ }
+ currentPdfReaderInstance = reader.getPdfReaderInstance(this);
+ }
+ }
+ else {
+ currentPdfReaderInstance = reader.getPdfReaderInstance(this);
+ }
+ return currentPdfReaderInstance.getImportedPage(pageNumber);
+ }
+
+
+ /**
+ * Translate a PRIndirectReference to a PdfIndirectReference
+ * In addition, translates the object numbers, and copies the
+ * referenced object to the output file.
+ * NB: PRIndirectReferences (and PRIndirectObjects) really need to know what
+ * file they came from, because each file has its own namespace. The translation
+ * we do from their namespace to ours is *at best* heuristic, and guaranteed to
+ * fail under some circumstances.
+ */
+ protected PdfIndirectReference copyIndirect(PRIndirectReference in) throws IOException, BadPdfFormatException {
+ RefKey key = new RefKey(in);
+ IndirectReferences iRef = (IndirectReferences)indirects.get(key);
+ boolean recurse_b= true; // ssteward
+
+ PdfIndirectReference retVal;
+ if (iRef != null) {
+ retVal = iRef.getRef();
+ if (iRef.getCopied()) { // we've already copied this
+ return retVal;
+ }
+ }
+ else {
+ retVal = body.getPdfIndirectReference();
+ iRef = new IndirectReferences(retVal);
+ indirects.put(key, iRef);
+ }
+
+ // ssteward; if this is a ref to a dictionary with a parent,
+ // and we haven't copied the parent yet, then don't recurse
+ // into this dictionary; wait to recurse via the parent;
+ // this was written to fix a problem with references to pages
+ // inside pdf destinations; this problem caused pdf bloat;
+ // the pdf spec says broken indirect ref.s (ref, but no obj) are okay;
+ //
+ // update: we /do/ want to recurse up form field parents (see addPage()),
+ // just /not/ pages with parents
+ //
+ // note: copying an indirect reference to a dictionary is
+ // more suspect than copying a dictionary
+ //
+ // simplify this by not recursing into /any/ type==page via indirect ref?
+
+ PdfObject in_obj= (PdfObject)reader.getPdfObject( in );
+ if( in_obj!= null && in_obj.isDictionary() ) {
+ PdfDictionary in_dict= (PdfDictionary)in_obj;
+
+ PdfName type= (PdfName)in_dict.get( PdfName.TYPE );
+ if( type!= null && type.isName() && type.equals( PdfName.PAGE ) ) {
+
+ PdfObject parent_obj=
+ (PdfObject)in_dict.get( PdfName.PARENT );
+ if( parent_obj!= null && parent_obj.isIndirect() ) {
+ PRIndirectReference parent_iref= (PRIndirectReference)parent_obj;
+
+ RefKey parent_key= new RefKey( parent_iref );
+ IndirectReferences parent_ref= (IndirectReferences)indirects.get( parent_key );
+
+ if( parent_ref== null || !parent_ref.getCopied() ) {
+ // parent has not been copied yet, so we've jumped here somehow;
+ recurse_b= false;
+ }
+ }
+ }
+ }
+
+ if( recurse_b ) {
+ iRef.setCopied();
+ PdfObject obj = copyObject((PdfObject)PdfReader.getPdfObjectRelease(in));
+ addToBody(obj, retVal);
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Translate a PRDictionary to a PdfDictionary. Also translate all of the
+ * objects contained in it.
+ */
+ protected PdfDictionary copyDictionary(PdfDictionary in)
+ throws IOException, BadPdfFormatException {
+ PdfDictionary out = new PdfDictionary();
+ PdfName type = (PdfName)in.get(PdfName.TYPE);
+
+ for (Iterator it = in.getKeys().iterator(); it.hasNext();) {
+ PdfName key = (PdfName)it.next();
+ PdfObject value = in.get(key);
+ // System.err.println("Copy " + key); // debug
+ if (type != null && PdfName.PAGE.equals(type)) {
+ if (key.equals(PdfName.PARENT))
+ out.put(PdfName.PARENT, topPageParent);
+ else if (!key.equals(PdfName.B))
+ out.put(key, copyObject(value));
+ }
+ else
+ out.put(key, copyObject(value));
+ }
+ return out;
+ }
+
+ /**
+ * Translate a PRStream to a PdfStream. The data part copies itself.
+ */
+ protected PdfStream copyStream(PRStream in) throws IOException, BadPdfFormatException {
+ PRStream out = new PRStream(in, null);
+
+ for (Iterator it = in.getKeys().iterator(); it.hasNext();) {
+ PdfName key = (PdfName) it.next();
+ PdfObject value = in.get(key);
+ out.put(key, copyObject(value));
+ }
+
+ return out;
+ }
+
+
+ /**
+ * Translate a PRArray to a PdfArray. Also translate all of the objects contained
+ * in it
+ */
+ protected PdfArray copyArray(PdfArray in) throws IOException, BadPdfFormatException {
+ PdfArray out = new PdfArray();
+
+ for (Iterator i = in.getArrayList().iterator(); i.hasNext();) {
+ PdfObject value = (PdfObject)i.next();
+ out.add(copyObject(value));
+ }
+ return out;
+ }
+
+ /**
+ * Translate a PR-object to a Pdf-object
+ */
+ protected PdfObject copyObject(PdfObject in) throws IOException,BadPdfFormatException {
+ switch (in.type) {
+ case PdfObject.DICTIONARY:
+ // System.err.println("Dictionary: " + in.toString());
+ return copyDictionary((PdfDictionary)in);
+ case PdfObject.INDIRECT:
+ return copyIndirect((PRIndirectReference)in);
+ case PdfObject.ARRAY:
+ return copyArray((PdfArray)in);
+ case PdfObject.NUMBER:
+ case PdfObject.NAME:
+ case PdfObject.STRING:
+ case PdfObject.m_NULL: // ssteward
+ case PdfObject.BOOLEAN:
+ return in;
+ case PdfObject.STREAM:
+ return copyStream((PRStream)in);
+ // return in;
+ default:
+ if (in.type < 0) {
+ String lit = ((PdfLiteral)in).toString();
+ if (lit.equals("true") || lit.equals("false")) {
+ return new PdfBoolean(lit);
+ }
+ return new PdfLiteral(lit);
+ }
+ System.err.println("CANNOT COPY type " + in.type);
+ return null;
+ }
+ }
+
+ /**
+ * convenience method. Given an importedpage, set our "globals"
+ */
+ protected int setFromIPage(PdfImportedPage iPage) {
+ int pageNum = iPage.getPageNumber();
+ PdfReaderInstance inst = currentPdfReaderInstance = iPage.getPdfReaderInstance();
+ reader = inst.getReader();
+ setFromReader(reader);
+ return pageNum;
+ }
+
+ /**
+ * convenience method. Given a reader, set our "globals"
+ */
+ protected void setFromReader(PdfReader reader) {
+ this.reader = reader;
+ indirects = (HashMap)indirectMap.get(reader);
+ if (indirects == null) {
+ indirects = new HashMap();
+ indirectMap.put(reader,indirects);
+ PdfDictionary catalog = reader.getCatalog();
+ PRIndirectReference ref = (PRIndirectReference)catalog.get(PdfName.PAGES);
+ indirects.put(new RefKey(ref), new IndirectReferences(topPageParent));
+ /* ssteward: why PdfCopy.acroForm when PdfDocument.acroForm?
+ ref = (PRIndirectReference)catalog.get(PdfName.ACROFORM);
+ if (ref != null) {
+ if (acroForm == null) acroForm = body.getPdfIndirectReference();
+ indirects.put(new RefKey(ref), new IndirectReferences(acroForm));
+ }
+ */
+ }
+ }
+ /**
+ * Add an imported page to our output
+ * @param iPage an imported page
+ * @throws IOException, BadPdfFormatException
+ */
+ public void addPage(PdfImportedPage iPage) throws IOException, BadPdfFormatException {
+ int pageNum = setFromIPage(iPage); // sets this.reader
+
+ PdfDictionary thePage = reader.getPageN(pageNum);
+ PRIndirectReference origRef = reader.getPageOrigRef(pageNum);
+ reader.releasePage(pageNum);
+ RefKey key = new RefKey(origRef);
+ PdfIndirectReference pageRef;
+ IndirectReferences iRef = (IndirectReferences)indirects.get(key);
+ // if we already have an iref for the page (we got here by another link)
+ if (iRef != null) {
+ pageRef = iRef.getRef();
+ }
+ else {
+ pageRef = body.getPdfIndirectReference();
+ iRef = new IndirectReferences(pageRef);
+ indirects.put(key, iRef);
+ }
+ pageReferences.add(pageRef);
+ ++currentPageNumber;
+ if (! iRef.getCopied()) {
+ iRef.setCopied();
+
+ // ssteward
+ if( !this.topFormFieldReadersData.containsKey( reader ) ) { // add
+ this.topFormFieldReadersData.put( reader, new TopFormFieldData() );
+ }
+ TopFormFieldData readerData= (TopFormFieldData)topFormFieldReadersData.get(reader);
+
+ // ssteward
+ // if duplicate form field names are encountered
+ // make names unique by inserting a new top parent "field";
+ // insert this new parent into the PdfReader of the input document,
+ // since any PdfWriter material may have been written already; our
+ // changes to the PdfReader will be copied, below, into the PdfWriter;
+ //
+ {
+ PdfArray annots= (PdfArray)reader.getPdfObject(thePage.get(PdfName.ANNOTS));
+ if( annots!= null && annots.isArray() ) {
+ ArrayList annots_arr= annots.getArrayList();
+ for( int ii= 0; ii< annots_arr.size(); ++ii ) {
+ // an annotation may be direct or indirect; ours must be indirect
+ PdfObject annot_obj= (PdfObject)annots_arr.get(ii);
+ if( annot_obj!= null && annot_obj.isIndirect() ) {
+ PdfIndirectReference annot_ref= (PdfIndirectReference)annot_obj;
+ if( annot_ref!= null ) {
+ PdfDictionary annot= (PdfDictionary)reader.getPdfObject(annot_ref);
+ if( annot!= null && annot.isDictionary() ) {
+ PdfName subtype= (PdfName)reader.getPdfObject(annot.get(PdfName.SUBTYPE));
+ if( subtype!= null && subtype.isName() && subtype.equals(PdfName.WIDGET) ) {
+ // we have a form field
+
+ // get its full name
+ //
+ String full_name= ""; // construct a full name from partial names using '.', e.g.: foo.bar.
+ String top_name= "";
+ boolean is_unicode_b= false; // if names are unicode, they must all be unicode
+ PdfString tt= (PdfString)reader.getPdfObject(annot.get(PdfName.T));
+ if( tt!= null && tt.isString() ) {
+ top_name= tt.toString();
+ is_unicode_b= ( is_unicode_b || PdfString.isUnicode( tt.getBytes() ) );
+ }
+ //
+ // dig upwards, parent-wise; replace annot as we go with the
+ // top-most form field dictionary
+ PdfIndirectReference parent_ref=
+ (PdfIndirectReference)annot.get(PdfName.PARENT);
+ while( parent_ref!= null && parent_ref.isIndirect() )
+ {
+ annot_ref= parent_ref;
+ annot= (PdfDictionary)reader.getPdfObject(annot_ref);
+ parent_ref= (PdfIndirectReference)annot.get(PdfName.PARENT);
+
+ tt= (PdfString)reader.getPdfObject(annot.get(PdfName.T));
+ if( tt!= null && tt.isString() ) {
+ if( top_name.length()!= 0 ) {
+ full_name+= top_name;
+ full_name+= ".";
+ }
+ top_name= tt.toString();
+ }
+
+ is_unicode_b= ( is_unicode_b || PdfString.isUnicode( tt.getBytes() ) );
+ }
+
+ // once we have seen a top-level field parent, we wave
+ // it through and assume that it harbors no illegal field duplicates;
+ // this is good, because sometimes authors want a single field
+ // represented by more than one annotation on the page; this logic
+ // respects that programming
+ //
+ //System.err.println( full_name+ top_name+ "." ); // debug
+ if( readerData.allNames.contains( top_name ) )
+ { // a parent we have seen or created in this reader
+ this.fullFormFieldNames.add( full_name+ top_name+ "." ); // tally
+ }
+ else {
+ if( this.fullFormFieldNames.contains( full_name+ top_name+ "." ) ) {
+ // insert new, top-most parent
+
+ // name for new parent
+ int new_parent_name_ii= 1;
+ String new_parent_name= Integer.toString( new_parent_name_ii );
+ while( this.fullFormFieldNames.contains( full_name+ top_name+ "."+ new_parent_name+ "." ) ||
+ this.topFormFieldNames.contains( new_parent_name ) &&
+ !readerData.newNamesKids.containsKey( new_parent_name ) )
+ {
+ new_parent_name= Integer.toString( ++new_parent_name_ii );
+ }
+
+ PdfIndirectReference new_parent_ref= null;
+ PdfArray new_parent_kids= null;
+ //
+ if( readerData.newNamesKids.containsKey( new_parent_name ) ) {
+ // a new parent we already created
+ new_parent_ref= (PdfIndirectReference)
+ readerData.newNamesRefs.get( new_parent_name );
+ new_parent_kids= (PdfArray)
+ readerData.newNamesKids.get( new_parent_name );
+ }
+ else { // create a new parent using this name
+ PdfDictionary new_parent= new PdfDictionary();
+ PdfString new_parent_name_pdf= new PdfString( new_parent_name );
+ if( is_unicode_b ) { // if names are unicode, they must all be unicode
+ new_parent_name_pdf= new PdfString( new_parent_name, PdfObject.TEXT_UNICODE );
+ }
+ new_parent_ref= reader.getPRIndirectReference( new_parent );
+ new_parent.put( PdfName.T, new_parent_name_pdf );
+
+ new_parent_kids= new PdfArray();
+ PdfIndirectReference new_parent_kids_ref=
+ reader.getPRIndirectReference( new_parent_kids );
+ new_parent.put(PdfName.KIDS, new_parent_kids_ref);
+
+ // tally new parent
+ readerData.newNamesRefs.put( new_parent_name, new_parent_ref );
+ readerData.newNamesKids.put( new_parent_name, new_parent_kids );
+ readerData.allNames.add( new_parent_name );
+ this.topFormFieldNames.add( new_parent_name );
+ }
+
+ // wire annot and new parent together
+ annot.put( PdfName.PARENT, new_parent_ref );
+ new_parent_kids.add( annot_ref ); // the new parent must point at the field, too
+
+ // tally full field name
+ this.fullFormFieldNames.add( full_name+ top_name+ "."+ new_parent_name+ "." );
+ }
+ else {
+ // tally parent
+ readerData.allNames.add( top_name );
+ this.topFormFieldNames.add( top_name );
+
+ // tally full field name
+ this.fullFormFieldNames.add( full_name+ top_name+ "." );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // copy the page; this will copy our work, above, into the target document
+ PdfDictionary newPage = copyDictionary(thePage);
+
+
+ // ssteward: pdftk-1.00;
+ // copy page form field ref.s into document AcroForm
+ // dig down into source page to find indirect ref., then
+ // look up ref. in dest page.; store ref.s in the PdfDocument acroForm,
+ // not the PdfCopy acroForm (which isn't really a PdfAcroForm, anyhow);
+ //
+ // dig down to annot, and then dig up to topmost Parent
+ {
+ PdfArray annots= (PdfArray)reader.getPdfObject(thePage.get(PdfName.ANNOTS));
+ if( annots!= null && annots.isArray() ) {
+ ArrayList annots_arr= annots.getArrayList();
+ for( int ii= 0; ii< annots_arr.size(); ++ii ) {
+ // an annotation may be direct or indirect; ours must be indirect
+ PdfObject annot_obj= (PdfObject)annots_arr.get(ii);
+ if( annot_obj!= null && annot_obj.isIndirect() ) {
+ PdfIndirectReference annot_ref= (PdfIndirectReference)annots_arr.get(ii);
+ if( annot_ref!= null ) {
+ PdfDictionary annot= (PdfDictionary)reader.getPdfObject(annot_ref);
+ if( annot!= null && annot.isDictionary() ) {
+ PdfName subtype= (PdfName)reader.getPdfObject(annot.get(PdfName.SUBTYPE));
+ if( subtype!= null && subtype.isName() && subtype.equals(PdfName.WIDGET) ) {
+ // we have a form field
+
+ // dig upwards, parent-wise
+ PdfIndirectReference parent_ref=
+ (PdfIndirectReference)annot.get(PdfName.PARENT);
+ while( parent_ref!= null && parent_ref.isIndirect() ) {
+ annot_ref= parent_ref;
+ annot= (PdfDictionary)reader.getPdfObject(annot_ref);
+ parent_ref= (PdfIndirectReference)annot.get(PdfName.PARENT);
+ }
+
+ RefKey annot_key= new RefKey(annot_ref);
+ IndirectReferences annot_iRef= (IndirectReferences)indirects.get(annot_key);
+ PdfAcroForm acroForm= this.getAcroForm();
+ acroForm.addDocumentField( annot_iRef.getRef() );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // ssteward: pdftk-1.00;
+ // merge the reader AcroForm/DR dictionary with the target
+ //
+ // pdftk-1.10: I noticed that the PdfAcroForm.isValid() apprears to stomp on this (TODO)
+ //
+ PdfDictionary catalog= reader.getCatalog();
+ if( catalog!= null && catalog.isDictionary() ) {
+ PdfDictionary acroForm= (PdfDictionary)reader.getPdfObject(catalog.get(PdfName.ACROFORM));
+ if( acroForm!= null && acroForm.isDictionary() ) {
+ PdfDictionary dr= (PdfDictionary)reader.getPdfObject(acroForm.get(PdfName.DR));
+ if( dr!= null && dr.isDictionary() ) {
+ PdfDictionary acroForm_target= this.getAcroForm();
+ PdfDictionary dr_target= (PdfDictionary)reader.getPdfObject(acroForm_target.get(PdfName.DR));
+ if( dr_target== null ) {
+ PdfDictionary dr_copy= copyDictionary( dr );
+ acroForm_target.put( PdfName.DR, dr_copy );
+ }
+ else {
+ for( Iterator it= dr.getKeys().iterator(); it.hasNext(); ) {
+ PdfName dr_key= (PdfName)it.next();
+ PdfObject dr_val= (PdfObject)dr.get(dr_key);
+ if( !dr_target.contains( dr_key ) ) { // copy key/value to dr_target
+ dr_target.put( dr_key, copyObject( dr_val ) );
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ newPage.put(PdfName.PARENT, topPageParent);
+ addToBody(newPage, pageRef);
+ }
+ root.addPage(pageRef);
+ pageNumbersToRefs.add(pageRef);
+ }
+
+ public PdfIndirectReference getPageReference(int page) {
+ if (page < 0 || page > pageNumbersToRefs.size())
+ throw new IllegalArgumentException("Invalid page number " + page);
+ return (PdfIndirectReference)pageNumbersToRefs.get(page - 1);
+ }
+
+ /**
+ * Copy the acroform for an input document. Note that you can only have one,
+ * we make no effort to merge them.
+ * @param reader The reader of the input file that is being copied
+ * @throws IOException, BadPdfFormatException
+ */
+ /* ssteward: why PdfCopy.acroForm when PdfDocument.acroForm?
+ public void copyAcroForm(PdfReader reader) throws IOException, BadPdfFormatException {
+ setFromReader(reader);
+
+ PdfDictionary catalog = reader.getCatalog();
+ PRIndirectReference hisRef = null;
+ PdfObject o = catalog.get(PdfName.ACROFORM);
+ if (o != null && o.type() == PdfObject.INDIRECT)
+ hisRef = (PRIndirectReference)o;
+ RefKey key = new RefKey(hisRef);
+ PdfIndirectReference myRef;
+ IndirectReferences iRef = (IndirectReferences)indirects.get(key);
+ if (iRef != null) {
+ acroForm = myRef = iRef.getRef();
+ }
+ else {
+ acroForm = myRef = body.getPdfIndirectReference();
+ iRef = new IndirectReferences(myRef);
+ indirects.put(key, iRef);
+ }
+ if (! iRef.getCopied()) {
+ iRef.setCopied();
+ PdfDictionary theForm = copyDictionary((PdfDictionary)PdfReader.getPdfObject(hisRef));
+ PdfIndirectObject myObj = addToBody(theForm, myRef);
+ }
+ }
+ */
+
+ /*
+ * the getCatalog method is part of PdfWriter.
+ * we wrap this so that we can extend it
+ */
+ protected PdfDictionary getCatalog( PdfIndirectReference rootObj ) {
+ //try {
+ PdfDictionary catalog= ((PdfDocument)document).getCatalog( rootObj );
+
+ // ssteward: this just overwrites the ACROFORM entry added by
+ // PdfDocument.getCatalog(); dropped, because we use PdfDocument.acroForm, above;
+ //if (acroForm != null) catalog.put(PdfName.ACROFORM, acroForm);
+
+ /* ssteward: replacing with our own bookmark-fu
+ if (newBookmarks == null || newBookmarks.size() == 0)
+ return catalog;
+ PdfDictionary top = new PdfDictionary();
+ PdfIndirectReference topRef = getPdfIndirectReference();
+ Object kids[] = SimpleBookmark.iterateOutlines(this, topRef, newBookmarks, false);
+ top.put(PdfName.FIRST, (PdfIndirectReference)kids[0]);
+ top.put(PdfName.LAST, (PdfIndirectReference)kids[1]);
+ top.put(PdfName.COUNT, new PdfNumber(((Integer)kids[2]).intValue()));
+ addToBody(top, topRef);
+ catalog.put(PdfName.OUTLINES, topRef);
+ */
+
+ if( m_new_bookmarks!= null ) {
+ catalog.put( PdfName.OUTLINES, m_new_bookmarks );
+ }
+ if( m_new_extensions!= null ) {
+ catalog.put( PdfName.EXTENSIONS, m_new_extensions );
+ }
+
+ return catalog;
+ /*
+ }
+ catch (IOException e) {
+ throw new ExceptionConverter(e);
+ }
+ */
+ }
+
+ /**
+ * Sets the bookmarks. The list structure is defined in
+ * SimpleBookmark#
.
+ * @param outlines the bookmarks or null
to remove any
+ */
+ /*
+ public void setOutlines(List outlines) {
+ newBookmarks = outlines;
+ }
+ */
+ // ssteward: pdftk 1.46
+ public void setOutlines( PdfIndirectReference outlines ) {
+ m_new_bookmarks= outlines;
+ }
+ public void setExtensions( PdfIndirectReference extensions ) {
+ m_new_extensions= extensions;
+ }
+
+ /**
+ * Signals that the Document
was closed and that no other
+ * Elements
will be added.
+ *
+ * The pages-tree is built and written to the outputstream.
+ * A Catalog is constructed, as well as an Info-object,
+ * the referencetable is composed and everything is written
+ * to the outputstream embedded in a Trailer.
+ */
+
+ public void close() {
+ if (open) {
+ PdfReaderInstance ri = currentPdfReaderInstance;
+ pdf.close();
+ super.close();
+ if (ri != null) {
+ try {
+ ri.getReader().close();
+ ri.getReaderFile().close();
+ }
+ catch (IOException ioe) {
+ // empty on purpose
+ }
+ }
+ }
+ }
+ // PdfIndirectReference add(PdfImage pdfImage) throws PdfException { return null; } ssteward: dropped in 1.44
+ public PdfIndirectReference add(PdfOutline outline) { return null; }
+ public void addAnnotation(PdfAnnotation annot) { }
+ PdfIndirectReference add(PdfPage page, PdfContents contents) throws PdfException { return null; }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfCopyFieldsImp.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfCopyFieldsImp.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfCopyFieldsImp.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfCopyFieldsImp.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,629 @@
+/*
+ * $Id: PdfCopyFieldsImp.java,v 1.10 2005/05/17 11:21:46 blowagie Exp $
+ * $Name: $
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.ExceptionConverter;
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.Document;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ *
+ * @author psoares
+ */
+class PdfCopyFieldsImp extends PdfWriter {
+
+ private static final PdfName iTextTag = new PdfName("_iTextTag_");
+ private static final Integer zero = new Integer(0);
+ ArrayList readers = new ArrayList();
+ HashMap readers2intrefs = new HashMap();
+ HashMap pages2intrefs = new HashMap();
+ HashMap visited = new HashMap();
+ ArrayList fields = new ArrayList();
+ RandomAccessFileOrArray file;
+ HashMap fieldTree = new HashMap();
+ ArrayList pageRefs = new ArrayList();
+ ArrayList pageDics = new ArrayList();
+ PdfDictionary resources = new PdfDictionary();
+ PdfDictionary form;
+ protected List newBookmarks;
+ boolean closing = false;
+ Document nd;
+ private HashMap tabOrder;
+ private ArrayList calculationOrder = new ArrayList();
+ private ArrayList calculationOrderRefs;
+
+ PdfCopyFieldsImp(OutputStream os) throws DocumentException, IOException {
+ this(os, '\0');
+ }
+
+ PdfCopyFieldsImp(OutputStream os, char pdfVersion) throws DocumentException, IOException {
+ super(new PdfDocument(), os);
+ pdf.addWriter(this);
+ if (pdfVersion != 0)
+ super.setPdfVersion(pdfVersion);
+ nd = new Document();
+ nd.addDocListener(pdf);
+ }
+
+ void addDocument(PdfReader reader, List pagesToKeep) throws DocumentException {
+ if (!readers2intrefs.containsKey(reader) && reader.isTampered())
+ throw new DocumentException("The document was reused.");
+ reader = new PdfReader(reader);
+ reader.selectPages(pagesToKeep);
+ if (reader.getNumberOfPages() == 0)
+ return;
+ reader.setTampered(false);
+ addDocument(reader);
+ }
+
+ void addDocument(PdfReader reader) throws DocumentException {
+ openDoc();
+ if (readers2intrefs.containsKey(reader)) {
+ reader = new PdfReader(reader);
+ }
+ else {
+ if (reader.isTampered())
+ throw new DocumentException("The document was reused.");
+ reader.consolidateNamedDestinations();
+ reader.setTampered(true);
+ }
+ reader.shuffleSubsetNames();
+ readers2intrefs.put(reader, new IntHashtable());
+ readers.add(reader);
+ int len = reader.getNumberOfPages();
+ IntHashtable refs = new IntHashtable();
+ for (int p = 1; p <= len; ++p) {
+ refs.put(reader.getPageOrigRef(p).getNumber(), 1);
+ reader.releasePage(p);
+ }
+ pages2intrefs.put(reader, refs);
+ visited.put(reader, new IntHashtable());
+ fields.add(reader.getAcroFields());
+ updateCalculationOrder(reader);
+ }
+
+ private static String getCOName(PdfReader reader, PRIndirectReference ref) {
+ String name = "";
+ while (ref != null) {
+ PdfObject obj = PdfReader.getPdfObject(ref);
+ if (obj == null || obj.type() != PdfObject.DICTIONARY)
+ break;
+ PdfDictionary dic = (PdfDictionary)obj;
+ PdfString t = (PdfString)PdfReader.getPdfObject(dic.get(PdfName.T));
+ if (t != null) {
+ name = t.toUnicodeString()+ "." + name;
+ }
+ ref = (PRIndirectReference)dic.get(PdfName.PARENT);
+ }
+ if (name.endsWith("."))
+ name = name.substring(0, name.length() - 1);
+ return name;
+ }
+
+ private void updateCalculationOrder(PdfReader reader) {
+ PdfDictionary catalog = reader.getCatalog();
+ PdfDictionary acro = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.ACROFORM));
+ if (acro == null)
+ return;
+ PdfArray co = (PdfArray)PdfReader.getPdfObject(acro.get(PdfName.CO));
+ if (co == null || co.size() == 0)
+ return;
+ AcroFields af = reader.getAcroFields();
+ ArrayList coa = co.getArrayList();
+ for (int k = 0; k < coa.size(); ++k) {
+ PdfObject obj = (PdfObject)coa.get(k);
+ if (obj == null || !obj.isIndirect())
+ continue;
+ String name = getCOName(reader, (PRIndirectReference)obj);
+ if (af.getFieldItem(name) == null)
+ continue;
+ name = "." + name;
+ if (calculationOrder.contains(name))
+ continue;
+ calculationOrder.add(name);
+ }
+ }
+
+ void propagate(PdfObject obj, PdfIndirectReference refo, boolean restricted) throws IOException {
+ if (obj == null)
+ return;
+// if (refo != null)
+// addToBody(obj, refo);
+ if (obj instanceof PdfIndirectReference)
+ return;
+ switch (obj.type()) {
+ case PdfObject.DICTIONARY:
+ case PdfObject.STREAM: {
+ PdfDictionary dic = (PdfDictionary)obj;
+ for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
+ PdfName key = (PdfName)it.next();
+ if (restricted && (key.equals(PdfName.PARENT) || key.equals(PdfName.KIDS)))
+ continue;
+ PdfObject ob = dic.get(key);
+ if (ob != null && ob.isIndirect()) {
+ PRIndirectReference ind = (PRIndirectReference)ob;
+ if (!setVisited(ind) && !isPage(ind)) {
+ PdfIndirectReference ref = getNewReference(ind);
+ propagate(PdfReader.getPdfObjectRelease(ind), ref, restricted);
+ }
+ }
+ else
+ propagate(ob, null, restricted);
+ }
+ break;
+ }
+ case PdfObject.ARRAY: {
+ ArrayList list = ((PdfArray)obj).getArrayList();
+ //PdfArray arr = new PdfArray();
+ for (Iterator it = list.iterator(); it.hasNext();) {
+ PdfObject ob = (PdfObject)it.next();
+ if (ob != null && ob.isIndirect()) {
+ PRIndirectReference ind = (PRIndirectReference)ob;
+ if (!isVisited(ind) && !isPage(ind)) {
+ PdfIndirectReference ref = getNewReference(ind);
+ propagate(PdfReader.getPdfObjectRelease(ind), ref, restricted);
+ }
+ }
+ else
+ propagate(ob, null, restricted);
+ }
+ break;
+ }
+ case PdfObject.INDIRECT: {
+ throw new RuntimeException("Reference pointing to reference.");
+ }
+ }
+ }
+
+ private void adjustTabOrder(PdfArray annots, PdfIndirectReference ind, PdfNumber nn) {
+ int v = nn.intValue();
+ ArrayList t = (ArrayList)tabOrder.get(annots);
+ if (t == null) {
+ t = new ArrayList();
+ int size = annots.size() - 1;
+ for (int k = 0; k < size; ++k) {
+ t.add(zero);
+ }
+ t.add(new Integer(v));
+ tabOrder.put(annots, t);
+ annots.add(ind);
+ }
+ else {
+ int size = t.size() - 1;
+ for (int k = size; k >= 0; --k) {
+ if (((Integer)t.get(k)).intValue() <= v) {
+ t.add(k + 1, new Integer(v));
+ annots.getArrayList().add(k + 1, ind);
+ size = -2;
+ break;
+ }
+ }
+ if (size != -2) {
+ t.add(0, new Integer(v));
+ annots.getArrayList().add(0, ind);
+ }
+ }
+ }
+
+ protected PdfArray branchForm(HashMap level, PdfIndirectReference parent, String fname) throws IOException {
+ PdfArray arr = new PdfArray();
+ for (Iterator it = level.keySet().iterator(); it.hasNext();) {
+ String name = (String)it.next();
+ Object obj = level.get(name);
+ PdfIndirectReference ind = getPdfIndirectReference();
+ PdfDictionary dic = new PdfDictionary();
+ if (parent != null)
+ dic.put(PdfName.PARENT, parent);
+ dic.put(PdfName.T, new PdfString(name, PdfObject.TEXT_UNICODE));
+ String fname2 = fname + "." + name;
+ int coidx = calculationOrder.indexOf(fname2);
+ if (coidx >= 0)
+ calculationOrderRefs.set(coidx, ind);
+ if (obj instanceof HashMap) {
+ dic.put(PdfName.KIDS, branchForm((HashMap)obj, ind, fname2));
+ arr.add(ind);
+ addToBody(dic, ind);
+ }
+ else {
+ ArrayList list = (ArrayList)obj;
+ dic.mergeDifferent((PdfDictionary)list.get(0));
+ if (list.size() == 3) {
+ dic.mergeDifferent((PdfDictionary)list.get(2));
+ int page = ((Integer)list.get(1)).intValue();
+ PdfDictionary pageDic = (PdfDictionary)pageDics.get(page - 1);
+ PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
+ if (annots == null) {
+ annots = new PdfArray();
+ pageDic.put(PdfName.ANNOTS, annots);
+ }
+ PdfNumber nn = (PdfNumber)dic.get(iTextTag);
+ dic.remove(iTextTag);
+ adjustTabOrder(annots, ind, nn);
+ }
+ else {
+ PdfArray kids = new PdfArray();
+ for (int k = 1; k < list.size(); k += 2) {
+ int page = ((Integer)list.get(k)).intValue();
+ PdfDictionary pageDic = (PdfDictionary)pageDics.get(page - 1);
+ PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
+ if (annots == null) {
+ annots = new PdfArray();
+ pageDic.put(PdfName.ANNOTS, annots);
+ }
+ PdfDictionary widget = new PdfDictionary();
+ widget.merge((PdfDictionary)list.get(k + 1));
+ widget.put(PdfName.PARENT, ind);
+ PdfNumber nn = (PdfNumber)widget.get(iTextTag);
+ widget.remove(iTextTag);
+ PdfIndirectReference wref = addToBody(widget).getIndirectReference();
+ adjustTabOrder(annots, wref, nn);
+ kids.add(wref);
+ propagate(widget, null, false);
+ }
+ dic.put(PdfName.KIDS, kids);
+ }
+ arr.add(ind);
+ addToBody(dic, ind);
+ propagate(dic, null, false);
+ }
+ }
+ return arr;
+ }
+
+ protected void createAcroForms() throws IOException {
+ if (fieldTree.size() == 0)
+ return;
+ form = new PdfDictionary();
+ form.put(PdfName.DR, resources);
+ propagate(resources, null, false);
+ form.put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
+ tabOrder = new HashMap();
+ calculationOrderRefs = new ArrayList(calculationOrder);
+ form.put(PdfName.FIELDS, branchForm(fieldTree, null, ""));
+ PdfArray co = new PdfArray();
+ for (int k = 0; k < calculationOrderRefs.size(); ++k) {
+ Object obj = calculationOrderRefs.get(k);
+ if (obj instanceof PdfIndirectReference)
+ co.add((PdfIndirectReference)obj);
+ }
+ if (co.size() > 0)
+ form.put(PdfName.CO, co);
+ }
+
+ public void close() {
+ if (closing) {
+ super.close();
+ return;
+ }
+ closing = true;
+ try {
+ closeIt();
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ protected void closeIt() throws DocumentException, IOException {
+ for (int k = 0; k < readers.size(); ++k) {
+ ((PdfReader)readers.get(k)).removeFields();
+ }
+ for (int r = 0; r < readers.size(); ++r) {
+ PdfReader reader = (PdfReader)readers.get(r);
+ for (int page = 1; page <= reader.getNumberOfPages(); ++page) {
+ pageRefs.add(getNewReference(reader.getPageOrigRef(page)));
+ pageDics.add(reader.getPageN(page));
+ }
+ }
+ mergeFields();
+ createAcroForms();
+ for (int r = 0; r < readers.size(); ++r) {
+ PdfReader reader = (PdfReader)readers.get(r);
+ for (int page = 1; page <= reader.getNumberOfPages(); ++page) {
+ PdfDictionary dic = reader.getPageN(page);
+ PdfIndirectReference pageRef = getNewReference(reader.getPageOrigRef(page));
+ PdfIndirectReference parent = root.addPageRef(pageRef);
+ dic.put(PdfName.PARENT, parent);
+ propagate(dic, pageRef, false);
+ }
+ }
+ for (Iterator it = readers2intrefs.keySet().iterator(); it.hasNext();) {
+ PdfReader reader = (PdfReader)it.next();
+ try {
+ file = reader.getSafeFile();
+ file.reOpen();
+ IntHashtable t = (IntHashtable)readers2intrefs.get(reader);
+ int keys[] = t.toOrderedKeys();
+ for (int k = 0; k < keys.length; ++k) {
+ PRIndirectReference ref = new PRIndirectReference(reader, keys[k]);
+ addToBody(PdfReader.getPdfObjectRelease(ref), t.get(keys[k]));
+ }
+ }
+ finally {
+ try {
+ file.close();
+ reader.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ }
+ pdf.close();
+ }
+
+ void addPageOffsetToField(HashMap fd, int pageOffset) {
+ if (pageOffset == 0)
+ return;
+ for (Iterator it = fd.values().iterator(); it.hasNext();) {
+ ArrayList page = ((AcroFields.Item)it.next()).page;
+ for (int k = 0; k < page.size(); ++k)
+ page.set(k, new Integer(((Integer)page.get(k)).intValue() + pageOffset));
+ }
+ }
+
+ void createWidgets(ArrayList list, AcroFields.Item item) {
+ for (int k = 0; k < item.merged.size(); ++k) {
+ list.add(item.page.get(k));
+ PdfDictionary merged = (PdfDictionary)item.merged.get(k);
+ PdfObject dr = merged.get(PdfName.DR);
+ if (dr != null)
+ PdfFormField.mergeResources(resources, (PdfDictionary)PdfReader.getPdfObject(dr));
+ PdfDictionary widget = new PdfDictionary();
+ for (Iterator it = merged.getKeys().iterator(); it.hasNext();) {
+ PdfName key = (PdfName)it.next();
+ if (widgetKeys.containsKey(key))
+ widget.put(key, merged.get(key));
+ }
+ widget.put(iTextTag, new PdfNumber(((Integer)item.tabOrder.get(k)).intValue() + 1));
+ list.add(widget);
+ }
+ }
+
+ void mergeField(String name, AcroFields.Item item) {
+ HashMap map = fieldTree;
+ StringTokenizer tk = new StringTokenizer(name, ".");
+ if (!tk.hasMoreTokens())
+ return;
+ while (true) {
+ String s = tk.nextToken();
+ Object obj = map.get(s);
+ if (tk.hasMoreTokens()) {
+ if (obj == null) {
+ obj = new HashMap();
+ map.put(s, obj);
+ map = (HashMap)obj;
+ continue;
+ }
+ else if (obj instanceof HashMap)
+ map = (HashMap)obj;
+ else
+ return;
+ }
+ else {
+ if (obj instanceof HashMap)
+ return;
+ PdfDictionary merged = (PdfDictionary)item.merged.get(0);
+ if (obj == null) {
+ PdfDictionary field = new PdfDictionary();
+ for (Iterator it = merged.getKeys().iterator(); it.hasNext();) {
+ PdfName key = (PdfName)it.next();
+ if (fieldKeys.containsKey(key))
+ field.put(key, merged.get(key));
+ }
+ ArrayList list = new ArrayList();
+ list.add(field);
+ createWidgets(list, item);
+ map.put(s, list);
+ }
+ else {
+ ArrayList list = (ArrayList)obj;
+ PdfDictionary field = (PdfDictionary)list.get(0);
+ PdfName type1 = (PdfName)field.get(PdfName.FT);
+ PdfName type2 = (PdfName)merged.get(PdfName.FT);
+ if (type1 == null || !type1.equals(type2))
+ return;
+ int flag1 = 0;
+ PdfObject f1 = field.get(PdfName.FF);
+ if (f1 != null && f1.isNumber())
+ flag1 = ((PdfNumber)f1).intValue();
+ int flag2 = 0;
+ PdfObject f2 = merged.get(PdfName.FF);
+ if (f2 != null && f2.isNumber())
+ flag2 = ((PdfNumber)f2).intValue();
+ if (type1.equals(PdfName.BTN)) {
+ if (((flag1 ^ flag2) & PdfFormField.FF_PUSHBUTTON) != 0)
+ return;
+ if ((flag1 & PdfFormField.FF_PUSHBUTTON) == 0 && ((flag1 ^ flag2) & PdfFormField.FF_RADIO) != 0)
+ return;
+ }
+ else if (type1.equals(PdfName.CH)) {
+ if (((flag1 ^ flag2) & PdfFormField.FF_COMBO) != 0)
+ return;
+ }
+ createWidgets(list, item);
+ }
+ return;
+ }
+ }
+ }
+
+ void mergeWithMaster(HashMap fd) {
+ for (Iterator it = fd.keySet().iterator(); it.hasNext();) {
+ String name = (String)it.next();
+ mergeField(name, (AcroFields.Item)fd.get(name));
+ }
+ }
+
+ void mergeFields() {
+ int pageOffset = 0;
+ for (int k = 0; k < fields.size(); ++k) {
+ HashMap fd = ((AcroFields)fields.get(k)).getFields();
+ addPageOffsetToField(fd, pageOffset);
+ mergeWithMaster(fd);
+ pageOffset += ((PdfReader)readers.get(k)).getNumberOfPages();
+ }
+ }
+
+ public PdfIndirectReference getPageReference(int page) {
+ return (PdfIndirectReference)pageRefs.get(page - 1);
+ }
+
+ protected PdfDictionary getCatalog(PdfIndirectReference rootObj) {
+ try {
+ PdfDictionary cat = ((PdfDocument)document).getCatalog(rootObj);
+ if (form != null) {
+ PdfIndirectReference ref = addToBody(form).getIndirectReference();
+ cat.put(PdfName.ACROFORM, ref);
+ }
+ if (newBookmarks == null || newBookmarks.size() == 0)
+ return cat;
+ PdfDictionary top = new PdfDictionary();
+ PdfIndirectReference topRef = getPdfIndirectReference();
+ Object kids[] = SimpleBookmark.iterateOutlines(this, topRef, newBookmarks, false);
+ top.put(PdfName.FIRST, (PdfIndirectReference)kids[0]);
+ top.put(PdfName.LAST, (PdfIndirectReference)kids[1]);
+ top.put(PdfName.COUNT, new PdfNumber(((Integer)kids[2]).intValue()));
+ addToBody(top, topRef);
+ cat.put(PdfName.OUTLINES, topRef);
+ return cat;
+ }
+ catch (IOException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ protected PdfIndirectReference getNewReference(PRIndirectReference ref) {
+ return new PdfIndirectReference(0, getNewObjectNumber(ref.getReader(), ref.getNumber(), 0));
+ }
+
+ protected int getNewObjectNumber(PdfReader reader, int number, int generation) {
+ IntHashtable refs = (IntHashtable)readers2intrefs.get(reader);
+ int n = refs.get(number);
+ if (n == 0) {
+ n = getIndirectReferenceNumber();
+ refs.put(number, n);
+ }
+ return n;
+ }
+
+ protected boolean isVisited(PdfReader reader, int number, int generation) {
+ IntHashtable refs = (IntHashtable)readers2intrefs.get(reader);
+ return refs.containsKey(number);
+ }
+
+ protected boolean isVisited(PRIndirectReference ref) {
+ IntHashtable refs = (IntHashtable)visited.get(ref.getReader());
+ return refs.containsKey(ref.getNumber());
+ }
+
+ protected boolean setVisited(PRIndirectReference ref) {
+ IntHashtable refs = (IntHashtable)visited.get(ref.getReader());
+ return (refs.put(ref.getNumber(), 1) != 0);
+ }
+
+ protected boolean isPage(PRIndirectReference ref) {
+ IntHashtable refs = (IntHashtable)pages2intrefs.get(ref.getReader());
+ return refs.containsKey(ref.getNumber());
+ }
+
+ RandomAccessFileOrArray getReaderFile(PdfReader reader) {
+ return file;
+ }
+
+ /**
+ * Sets the bookmarks. The list structure is defined in
+ * SimpleBookmark#
.
+ * @param outlines the bookmarks or null
to remove any
+ */
+ public void setOutlines(List outlines) {
+ newBookmarks = outlines;
+ }
+
+ public void openDoc() {
+ if (!nd.isOpen())
+ nd.open();
+ }
+
+ protected static final HashMap widgetKeys = new HashMap();
+ protected static final HashMap fieldKeys = new HashMap();
+ static {
+ Integer one = new Integer(1);
+ widgetKeys.put(PdfName.SUBTYPE, one);
+ widgetKeys.put(PdfName.CONTENTS, one);
+ widgetKeys.put(PdfName.RECT, one);
+ widgetKeys.put(PdfName.NM, one);
+ widgetKeys.put(PdfName.M, one);
+ widgetKeys.put(PdfName.F, one);
+ widgetKeys.put(PdfName.BS, one);
+ widgetKeys.put(PdfName.BORDER, one);
+ widgetKeys.put(PdfName.AP, one);
+ widgetKeys.put(PdfName.AS, one);
+ widgetKeys.put(PdfName.C, one);
+ widgetKeys.put(PdfName.A, one);
+ widgetKeys.put(PdfName.STRUCTPARENT, one);
+ widgetKeys.put(PdfName.OC, one);
+ widgetKeys.put(PdfName.H, one);
+ widgetKeys.put(PdfName.MK, one);
+ widgetKeys.put(PdfName.DA, one);
+ widgetKeys.put(PdfName.Q, one);
+ fieldKeys.put(PdfName.AA, one);
+ fieldKeys.put(PdfName.FT, one);
+ fieldKeys.put(PdfName.TU, one);
+ fieldKeys.put(PdfName.TM, one);
+ fieldKeys.put(PdfName.FF, one);
+ fieldKeys.put(PdfName.V, one);
+ fieldKeys.put(PdfName.DV, one);
+ fieldKeys.put(PdfName.DS, one);
+ fieldKeys.put(PdfName.RV, one);
+ fieldKeys.put(PdfName.OPT, one);
+ fieldKeys.put(PdfName.MAXLEN, one);
+ fieldKeys.put(PdfName.TI, one);
+ fieldKeys.put(PdfName.I, one);
+ fieldKeys.put(PdfName.LOCK, one);
+ fieldKeys.put(PdfName.SV, one);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfDashPattern.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfDashPattern.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfDashPattern.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfDashPattern.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,134 @@
+/*
+ * $Id: PdfDashPattern.java,v 1.33 2003/05/02 09:01:18 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A PdfDashPattern
defines a dash pattern as described in
+ * the PDF Reference Manual version 1.3 p 325 (section 8.4.3).
+ *
+ * @see PdfArray
+ */
+
+public class PdfDashPattern extends PdfArray {
+
+ // membervariables
+
+/** This is the length of a dash. */
+ private float dash = -1;
+
+/** This is the length of a gap. */
+ private float gap = -1;
+
+/** This is the phase. */
+ private float phase = -1;
+
+ // constructors
+
+/**
+ * Constructs a new PdfDashPattern
.
+ */
+
+ public PdfDashPattern() {
+ super();
+ }
+
+/**
+ * Constructs a new PdfDashPattern
.
+ */
+
+ public PdfDashPattern(float dash) {
+ super(new PdfNumber(dash));
+ this.dash = dash;
+ }
+
+/**
+ * Constructs a new PdfDashPattern
.
+ */
+
+ public PdfDashPattern(float dash, float gap) {
+ super(new PdfNumber(dash));
+ add(new PdfNumber(gap));
+ this.dash = dash;
+ this.gap = gap;
+ }
+
+/**
+ * Constructs a new PdfDashPattern
.
+ */
+
+ public PdfDashPattern(float dash, float gap, float phase) {
+ super(new PdfNumber(dash));
+ add(new PdfNumber(gap));
+ this.dash = dash;
+ this.gap = gap;
+ this.phase = phase;
+ }
+
+ public void add(float n) {
+ add(new PdfNumber(n));
+ }
+
+/**
+ * Returns the PDF representation of this PdfArray
.
+ *
+ * @return an array of byte
s
+ */
+
+ public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+ os.write('[');
+
+ if (dash >= 0) {
+ new PdfNumber(dash).toPdf(writer, os);
+ if (gap >= 0) {
+ os.write(' ');
+ new PdfNumber(gap).toPdf(writer, os);
+ }
+ }
+ os.write(']');
+ if (phase >=0) {
+ os.write(' ');
+ new PdfNumber(phase).toPdf(writer, os);
+ }
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfDate.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfDate.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfDate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfDate.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,205 @@
+/*
+ * $Id: PdfDate.java,v 1.63 2005/09/04 16:20:01 psoares33 Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.text.SimpleDateFormat;
+import java.util.GregorianCalendar;
+import java.util.Calendar;
+import java.util.SimpleTimeZone;
+
+/**
+ * PdfDate
is the PDF date object.
+ *
+ * PDF defines a standard date format. The PDF date format closely follows the format
+ * defined by the international standard ASN.1 (Abstract Syntax Notation One, defined
+ * in CCITT X.208 or ISO/IEC 8824). A date is a PdfString
of the form:
+ *
+ * (D: YYYYMMDDHHmmSSOHH'mm')
+ *
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 7.2 (page 183-184)
+ *
+ * @see PdfString
+ * @see java.util.GregorianCalendar
+ */
+
+public class PdfDate extends PdfString {
+
+ // ssteward; static builds of pdftk (Windows, gcc 3.3.1) would
+ // omit this class because of its reference by reflection;
+ // this treatment ensures that ld will include it
+ private static Class c1= java.util.Calendar.class; //gnu.java.locale.Calendar.class;
+
+ private static final int dateSpace[] = {Calendar.YEAR, 4, 0, Calendar.MONTH, 2, -1, Calendar.DAY_OF_MONTH, 2, 0,
+ Calendar.HOUR_OF_DAY, 2, 0, Calendar.MINUTE, 2, 0, Calendar.SECOND, 2, 0};
+
+ // constructors
+
+/**
+ * Constructs a PdfDate
-object.
+ *
+ * @param d the date that has to be turned into a PdfDate
-object
+ */
+
+ public PdfDate(Calendar d) {
+ super();
+ StringBuffer date = new StringBuffer("D:");
+ date.append(setLength(d.get(Calendar.YEAR), 4));
+ date.append(setLength(d.get(Calendar.MONTH) + 1, 2));
+ date.append(setLength(d.get(Calendar.DATE), 2));
+ date.append(setLength(d.get(Calendar.HOUR_OF_DAY), 2));
+ date.append(setLength(d.get(Calendar.MINUTE), 2));
+ date.append(setLength(d.get(Calendar.SECOND), 2));
+ int timezone = (d.get(Calendar.ZONE_OFFSET) + d.get(Calendar.DST_OFFSET)) / (60 * 60 * 1000);
+ if (timezone == 0) {
+ date.append("Z");
+ }
+ else if (timezone < 0) {
+ date.append("-");
+ timezone = -timezone;
+ }
+ else {
+ date.append("+");
+ }
+ if (timezone != 0) {
+ date.append(setLength(timezone, 2)).append("'");
+ int zone = Math.abs((d.get(Calendar.ZONE_OFFSET) + d.get(Calendar.DST_OFFSET)) / (60 * 1000)) - (timezone * 60);
+ date.append(setLength(zone, 2)).append("'");
+ }
+ value = date.toString();
+ }
+
+/**
+ * Constructs a PdfDate
-object, representing the current day and time.
+ */
+
+ public PdfDate() {
+ this(new GregorianCalendar());
+ }
+
+/**
+ * Adds a number of leading zeros to a given String
in order to get a String
+ * of a certain length.
+ *
+ * @param i a given number
+ * @param length the length of the resulting String
+ * @return the resulting String
+ */
+
+ private String setLength(int i, int length) { // 1.3-1.4 problem fixed by Finn Bock
+ StringBuffer tmp = new StringBuffer();
+ tmp.append(i);
+ while (tmp.length() < length) {
+ tmp.insert(0, "0");
+ }
+ tmp.setLength(length);
+ return tmp.toString();
+ }
+
+ /**
+ * Gives the W3C format of the PdfDate.
+ * @return a formatted date
+ */
+ public String getW3CDate() {
+ return getW3CDate(value);
+ }
+
+ /**
+ * Gives the W3C format of the PdfDate.
+ * @param d
+ * @return a formatted date
+ */
+ public static String getW3CDate(String d) {
+ SimpleDateFormat w3c = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+ Calendar c = decode(d);
+ return w3c.format(c.getTime());
+ }
+
+ /**
+ * Converts a PDF string representing a date into a Calendar.
+ * @param s the PDF string representing a date
+ * @return a Calendar
representing the date or null
if the string
+ * was not a date
+ */
+ public static Calendar decode(String s) {
+ try {
+ if (s.startsWith("D:"))
+ s = s.substring(2);
+ GregorianCalendar calendar;
+ int slen = s.length();
+ int idx = s.indexOf('Z');
+ if (idx >= 0) {
+ slen = idx;
+ calendar = new GregorianCalendar(new SimpleTimeZone(0, "ZPDF"));
+ }
+ else {
+ int sign = 1;
+ idx = s.indexOf('+');
+ if (idx < 0) {
+ idx = s.indexOf('-');
+ if (idx >= 0)
+ sign = -1;
+ }
+ if (idx < 0)
+ calendar = new GregorianCalendar();
+ else {
+ int offset = Integer.parseInt(s.substring(idx + 1, idx + 3)) * 60;
+ if (idx + 5 < s.length())
+ offset += Integer.parseInt(s.substring(idx + 4, idx + 6));
+ calendar = new GregorianCalendar(new SimpleTimeZone(offset * sign * 60000, "ZPDF"));
+ slen = idx;
+ }
+ }
+ calendar.clear();
+ idx = 0;
+ for (int k = 0; k < dateSpace.length; k += 3) {
+ if (idx >= slen)
+ break;
+ calendar.set(dateSpace[k], Integer.parseInt(s.substring(idx, idx + dateSpace[k + 1])) + dateSpace[k + 2]);
+ idx += dateSpace[k + 1];
+ }
+ return calendar;
+ }
+ catch (Exception e) {
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfDestination.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfDestination.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfDestination.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfDestination.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,211 @@
+/*
+ * $Id: PdfDestination.java,v 1.22 2002/06/20 13:28:22 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * A PdfColor
defines a Color (it's a PdfArray
containing 3 values).
+ *
+ * @see PdfDictionary
+ */
+
+public class PdfDestination extends PdfArray {
+
+ // public static final member-variables
+
+/** This is a possible destination type */
+ public static final int XYZ = 0;
+
+/** This is a possible destination type */
+ public static final int FIT = 1;
+
+/** This is a possible destination type */
+ public static final int FITH = 2;
+
+/** This is a possible destination type */
+ public static final int FITV = 3;
+
+/** This is a possible destination type */
+ public static final int FITR = 4;
+
+/** This is a possible destination type */
+ public static final int FITB = 5;
+
+/** This is a possible destination type */
+ public static final int FITBH = 6;
+
+/** This is a possible destination type */
+ public static final int FITBV = 7;
+
+ // member variables
+
+/** Is the indirect reference to a page already added? */
+ private boolean status = false;
+
+ // constructors
+
+/**
+ * Constructs a new PdfDestination
.
+ *
+ * If type equals FITB , the bounding box of a page
+ * will fit the window of the Reader. Otherwise the type will be set to
+ * FIT so that the entire page will fit to the window.
+ *
+ * @param type The destination type
+ */
+
+ public PdfDestination(int type) {
+ super();
+ if (type == FITB) {
+ add(PdfName.FITB);
+ }
+ else {
+ add(PdfName.FIT);
+ }
+ }
+
+/**
+ * Constructs a new PdfDestination
.
+ *
+ * If type equals FITBH / FITBV ,
+ * the width / height of the bounding box of a page will fit the window
+ * of the Reader. The parameter will specify the y / x coordinate of the
+ * top / left edge of the window. If the type equals FITH
+ * or FITV the width / height of the entire page will fit
+ * the window and the parameter will specify the y / x coordinate of the
+ * top / left edge. In all other cases the type will be set to FITH .
+ *
+ * @param type the destination type
+ * @param parameter a parameter to combined with the destination type
+ */
+
+ public PdfDestination(int type, float parameter) {
+ super(new PdfNumber(parameter));
+ switch(type) {
+ default:
+ addFirst(PdfName.FITH);
+ break;
+ case FITV:
+ addFirst(PdfName.FITV);
+ break;
+ case FITBH:
+ addFirst(PdfName.FITBH);
+ break;
+ case FITBV:
+ addFirst(PdfName.FITBV);
+ }
+ }
+
+/** Constructs a new PdfDestination
.
+ *
+ * Display the page, with the coordinates (left, top) positioned
+ * at the top-left corner of the window and the contents of the page magnified
+ * by the factor zoom. A negative value for any of the parameters left or top, or a
+ * zoom value of 0 specifies that the current value of that parameter is to be retained unchanged.
+ * @param type must be a PdfDestination.XYZ
+ * @param left the left value. Negative to place a null
+ * @param top the top value. Negative to place a null
+ * @param zoom The zoom factor. A value of 0 keeps the current value
+ */
+
+ public PdfDestination(int type, float left, float top, float zoom) {
+ super(PdfName.XYZ);
+ if (left < 0)
+ add(PdfNull.PDFNULL);
+ else
+ add(new PdfNumber(left));
+ if (top < 0)
+ add(PdfNull.PDFNULL);
+ else
+ add(new PdfNumber(top));
+ add(new PdfNumber(zoom));
+ }
+
+/** Constructs a new PdfDestination
.
+ *
+ * Display the page, with its contents magnified just enough
+ * to fit the rectangle specified by the coordinates left, bottom, right, and top
+ * entirely within the window both horizontally and vertically. If the required
+ * horizontal and vertical magnification factors are different, use the smaller of
+ * the two, centering the rectangle within the window in the other dimension.
+ *
+ * @param type must be PdfDestination.FITR
+ * @param left a parameter
+ * @param bottom a parameter
+ * @param right a parameter
+ * @param top a parameter
+ * @since iText0.38
+ */
+
+ public PdfDestination(int type, float left, float bottom, float right, float top) {
+ super(PdfName.FITR);
+ add(new PdfNumber(left));
+ add(new PdfNumber(bottom));
+ add(new PdfNumber(right));
+ add(new PdfNumber(top));
+ }
+
+ // methods
+
+/**
+ * Checks if an indirect reference to a page has been added.
+ *
+ * @return true
or false
+ */
+
+ public boolean hasPage() {
+ return status;
+ }
+
+/** Adds the indirect reference of the destination page.
+ *
+ * @param page an indirect reference
+ * @return true if the page reference was added
+ */
+
+ public boolean addPage(PdfIndirectReference page) {
+ if (!status) {
+ addFirst(page);
+ status = true;
+ return true;
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfDeveloperExtension.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfDeveloperExtension.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfDeveloperExtension.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfDeveloperExtension.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,116 @@
+/*
+ * $Id: $
+ *
+ * Copyright 2009 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2009 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2009 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * Beginning with BaseVersion 1.7, the extensions dictionary lets developers
+ * designate that a given document contains extensions to PDF. The presence
+ * of the extension dictionary in a document indicates that it may contain
+ * developer-specific PDF properties that extend a particular base version
+ * of the PDF specification.
+ * The extensions dictionary enables developers to identify their own extensions
+ * relative to a base version of PDF. Additionally, the convention identifies
+ * extension levels relative to that base version. The intent of this dictionary
+ * is to enable developers of PDF-producing applications to identify company-specific
+ * specifications (such as this one) that PDF-consuming applications use to
+ * interpret the extensions.
+ * @since 2.1.6
+ */
+public class PdfDeveloperExtension {
+
+ /** An instance of this class for Adobe 1.7 Extension level 3. */
+ public static final PdfDeveloperExtension ADOBE_1_7_EXTENSIONLEVEL3 =
+ new PdfDeveloperExtension(PdfName.ADBE, PdfWriter.PDF_VERSION_1_7, 3);
+
+ /** The prefix used in the Extensions dictionary added to the Catalog. */
+ protected PdfName prefix;
+ /** The base version. */
+ protected PdfName baseversion;
+ /** The extension level within the baseversion. */
+ protected int extensionLevel;
+
+ /**
+ * Creates a PdfDeveloperExtension object.
+ * @param prefix the prefix referring to the developer
+ * @param baseversion the number of the base version
+ * @param extensionLevel the extension level within the baseverion.
+ */
+ public PdfDeveloperExtension(PdfName prefix, PdfName baseversion, int extensionLevel) {
+ this.prefix = prefix;
+ this.baseversion = baseversion;
+ this.extensionLevel = extensionLevel;
+ }
+
+ /**
+ * Gets the prefix name.
+ * @return a PdfName
+ */
+ public PdfName getPrefix() {
+ return prefix;
+ }
+
+ /**
+ * Gets the baseversion name.
+ * @return a PdfName
+ */
+ public PdfName getBaseversion() {
+ return baseversion;
+ }
+
+ /**
+ * Gets the extension level within the baseversion.
+ * @return an integer
+ */
+ public int getExtensionLevel() {
+ return extensionLevel;
+ }
+
+ /**
+ * Generations the developer extension dictionary corresponding
+ * with the prefix.
+ * @return a PdfDictionary
+ */
+ public PdfDictionary getDeveloperExtensions() {
+ PdfDictionary developerextensions = new PdfDictionary();
+ developerextensions.put(PdfName.BASEVERSION, baseversion);
+ developerextensions.put(PdfName.EXTENSIONLEVEL, new PdfNumber(extensionLevel));
+ return developerextensions;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfDictionary.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfDictionary.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfDictionary.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfDictionary.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,497 @@
+/*
+ * $Id: PdfDictionary.java,v 1.27 2002/07/09 11:28:22 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.Set;
+
+/**
+ * PdfDictionary
is the Pdf dictionary object.
+ *
+ * A dictionary is an associative table containing pairs of objects. The first element
+ * of each pair is called the key and the second element is called the value .
+ * Unlike dictionaries in the PostScript language, a key must be a PdfName
.
+ * A value can be any kind of PdfObject
, including a dictionary. A dictionary is
+ * generally used to collect and tie together the attributes of a complex object, with each
+ * key-value pair specifying the name and value of an attribute.
+ * A dictionary is represented by two left angle brackets (<<), followed by a sequence of
+ * key-value pairs, followed by two right angle brackets (>>).
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.7 (page 40-41).
+ *
+ *
+ * @see PdfObject
+ * @see PdfName
+ * @see BadPdfFormatException
+ */
+
+public class PdfDictionary extends PdfObject {
+
+ // static membervariables (types of dictionary's)
+
+/** This is a possible type of dictionary */
+ public static final PdfName FONT = PdfName.FONT;
+
+/** This is a possible type of dictionary */
+ public static final PdfName OUTLINES = PdfName.OUTLINES;
+
+/** This is a possible type of dictionary */
+ public static final PdfName PAGE = PdfName.PAGE;
+
+/** This is a possible type of dictionary */
+ public static final PdfName PAGES = PdfName.PAGES;
+
+/** This is a possible type of dictionary */
+ public static final PdfName CATALOG = PdfName.CATALOG;
+
+ // membervariables
+
+/** This is the type of this dictionary */
+ private PdfName dictionaryType = null;
+
+/** This is the hashmap that contains all the values and keys of the dictionary */
+ protected HashMap hashMap;
+
+ // constructors
+
+/**
+ * Constructs an empty PdfDictionary
-object.
+ */
+
+ public PdfDictionary() {
+ super(DICTIONARY);
+ hashMap = new HashMap();
+ }
+
+/**
+ * Constructs a PdfDictionary
-object of a certain type.
+ *
+ * @param type a PdfName
+ */
+
+ public PdfDictionary(PdfName type) {
+ this();
+ dictionaryType = type;
+ put(PdfName.TYPE, dictionaryType);
+ }
+
+ // methods overriding some methods in PdfObject
+
+/**
+ * Returns the PDF representation of this PdfDictionary
.
+ *
+ * @return an array of byte
+ */
+
+ public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+ os.write('\n'); // ssteward
+ os.write('<');
+ os.write('<');
+
+ // loop over all the object-pairs in the HashMap
+ PdfName key;
+ PdfObject value;
+ //int type = 0; // ssteward
+ for (Iterator i = hashMap.keySet().iterator(); i.hasNext(); ) {
+ os.write('\n');
+ key = (PdfName) i.next();
+ value = (PdfObject) hashMap.get(key);
+ key.toPdf(writer, os);
+ // ssteward: I liked the old syntax formatting
+ //type = value.type();
+ //if (type != PdfObject.ARRAY && type != PdfObject.DICTIONARY && type != PdfObject.NAME && type != PdfObject.STRING)
+ os.write(' ');
+ value.toPdf(writer, os);
+ }
+ os.write('\n'); // ssteward
+ os.write('>');
+ os.write('>');
+ }
+
+ // methods concerning the HashMap member value
+
+/**
+ * Adds a PdfObject
and its key to the PdfDictionary
.
+ *
+ * @param key key of the entry (a PdfName
)
+ * @param value value of the entry (a PdfObject
)
+ * @return the previous
PdfObject
corresponding with the key
+ */
+
+ public void put(PdfName key, PdfObject object) {
+ if (object == null || object.isNull())
+ hashMap.remove(key);
+ else
+ hashMap.put(key, object);
+ }
+
+/**
+ * Adds a PdfObject
and its key to the PdfDictionary
.
+ * If the value is null it does nothing.
+ *
+ * @param key key of the entry (a PdfName
)
+ * @param value value of the entry (a PdfObject
)
+ * @return the previous
PdfObject
corresponding with the key
+ */
+ public void putEx(PdfName key, PdfObject value) {
+ if (value == null)
+ return;
+ hashMap.put(key, value);
+ }
+
+ public void putAll(PdfDictionary dic) {
+ hashMap.putAll(dic.hashMap);
+ }
+
+/**
+ * Adds a PdfObject
and its key to the PdfDictionary
.
+ * If the value is null the key is deleted.
+ *
+ * @param key key of the entry (a PdfName
)
+ * @param value value of the entry (a PdfObject
)
+ * @return the previous
PdfObject
corresponding with the key
+ */
+ public void putDel(PdfName key, PdfObject object) {
+ if (object == null || object.isNull())
+ hashMap.remove(key);
+ else
+ hashMap.put(key, object);
+ }
+
+/**
+ * Removes a PdfObject
and its key from the PdfDictionary
.
+ *
+ * @param key key of the entry (a PdfName
)
+ * @return the previous
PdfObject
corresponding with the key
+ */
+
+ public void remove(PdfName key) {
+ hashMap.remove(key);
+ }
+
+/**
+ * Gets a PdfObject
with a certain key from the PdfDictionary
.
+ *
+ * @param key key of the entry (a PdfName
)
+ * @return the previous
PdfObject
corresponding with the key
+ */
+
+ public PdfObject get(PdfName key) {
+ return (PdfObject) hashMap.get(key);
+ }
+
+ // methods concerning the type of Dictionary
+
+ /**
+ * Returns the PdfObject
associated to the specified
+ * key , resolving a possible indirect reference to a direct
+ * object.
+ *
+ * This method will never return a PdfIndirectReference
+ * object.
+ *
+ * @param key A key for the PdfObject
to be returned
+ * @return A direct PdfObject
or null
+ */
+ public PdfObject getDirectObject(PdfName key) {
+ return PdfReader.getPdfObject(get(key));
+ }
+
+ public Set getKeys() {
+ return hashMap.keySet();
+ }
+
+ public int size() {
+ return hashMap.size();
+ }
+
+ public boolean contains(PdfName key) {
+ return hashMap.containsKey(key);
+ }
+
+/**
+ * Checks if a PdfDictionary
is of a certain type.
+ *
+ * @param type a type of dictionary
+ * @return true
of false
+ *
+ * @deprecated
+ */
+
+ public boolean isDictionaryType(PdfName type) {
+ return dictionaryType.compareTo(type) == 0;
+ }
+
+/**
+ * Checks if a Dictionary
is of the type FONT.
+ *
+ * @return true
if it is, false
if it isn't.
+ */
+
+ public boolean isFont() {
+ return dictionaryType.compareTo(FONT) == 0;
+ }
+
+/**
+ * Checks if a Dictionary
is of the type PAGE.
+ *
+ * @return true
if it is, false
if it isn't.
+ */
+
+ public boolean isPage() {
+ return dictionaryType.compareTo(PAGE) == 0;
+ }
+
+/**
+ * Checks if a Dictionary
is of the type PAGES.
+ *
+ * @return true
if it is, false
if it isn't.
+ */
+
+ public boolean isPages() {
+ return dictionaryType.compareTo(PAGES) == 0;
+ }
+
+/**
+ * Checks if a Dictionary
is of the type CATALOG.
+ *
+ * @return true
if it is, false
if it isn't.
+ */
+
+ public boolean isCatalog() {
+ return dictionaryType.compareTo(CATALOG) == 0;
+ }
+
+/**
+ * Checks if a Dictionary
is of the type OUTLINES.
+ *
+ * @return true
if it is, false
if it isn't.
+ */
+
+ public boolean isOutlineTree() {
+ return dictionaryType.compareTo(OUTLINES) == 0;
+ }
+
+ public void merge(PdfDictionary other) {
+ hashMap.putAll(other.hashMap);
+ }
+
+ public void mergeDifferent(PdfDictionary other) {
+ for (Iterator i = other.hashMap.keySet().iterator(); i.hasNext();) {
+ Object key = i.next();
+ if (!hashMap.containsKey(key)) {
+ hashMap.put(key, other.hashMap.get(key));
+ }
+ }
+ }
+
+ // DOWNCASTING GETTERS
+ // @author Mark A Storer (2/17/06)
+
+ /**
+ * Returns a PdfObject
as a PdfDictionary
,
+ * resolving indirect references.
+ *
+ * The object associated with the PdfName
given is retrieved
+ * and resolved to a direct object.
+ * If it is a PdfDictionary
, it is cast down and returned as
+ * such. Otherwise null
is returned.
+ *
+ * @param key A PdfName
+ * @return the associated PdfDictionary
object,
+ * or null
+ */
+ public PdfDictionary getAsDict(PdfName key) {
+ PdfDictionary dict = null;
+ PdfObject orig = getDirectObject(key);
+ if (orig != null && orig.isDictionary())
+ dict = (PdfDictionary) orig;
+ return dict;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfArray
,
+ * resolving indirect references.
+ *
+ * The object associated with the PdfName
given is retrieved
+ * and resolved to a direct object.
+ * If it is a PdfArray
, it is cast down and returned as such.
+ * Otherwise null
is returned.
+ *
+ * @param key A PdfName
+ * @return the associated PdfArray
object,
+ * or null
+ */
+ public PdfArray getAsArray(PdfName key) {
+ PdfArray array = null;
+ PdfObject orig = getDirectObject(key);
+ if (orig != null && orig.isArray())
+ array = (PdfArray) orig;
+ return array;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfStream
,
+ * resolving indirect references.
+ *
+ * The object associated with the PdfName
given is retrieved
+ * and resolved to a direct object.
+ * If it is a PdfStream
, it is cast down and returned as such.
+ * Otherwise null
is returned.
+ *
+ * @param key A PdfName
+ * @return the associated PdfStream
object,
+ * or null
+ */
+ public PdfStream getAsStream(PdfName key) {
+ PdfStream stream = null;
+ PdfObject orig = getDirectObject(key);
+ if (orig != null && orig.isStream())
+ stream = (PdfStream) orig;
+ return stream;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfString
,
+ * resolving indirect references.
+ *
+ * The object associated with the PdfName
given is retrieved
+ * and resolved to a direct object.
+ * If it is a PdfString
, it is cast down and returned as such.
+ * Otherwise null
is returned.
+ *
+ * @param key A PdfName
+ * @return the associated PdfString
object,
+ * or null
+ */
+ public PdfString getAsString(PdfName key) {
+ PdfString string = null;
+ PdfObject orig = getDirectObject(key);
+ if (orig != null && orig.isString())
+ string = (PdfString) orig;
+ return string;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfNumber
,
+ * resolving indirect references.
+ *
+ * The object associated with the PdfName
given is retrieved
+ * and resolved to a direct object.
+ * If it is a PdfNumber
, it is cast down and returned as such.
+ * Otherwise null
is returned.
+ *
+ * @param key A PdfName
+ * @return the associated PdfNumber
object,
+ * or null
+ */
+ public PdfNumber getAsNumber(PdfName key) {
+ PdfNumber number = null;
+ PdfObject orig = getDirectObject(key);
+ if (orig != null && orig.isNumber())
+ number = (PdfNumber) orig;
+ return number;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfName
,
+ * resolving indirect references.
+ *
+ * The object associated with the PdfName
given is retrieved
+ * and resolved to a direct object.
+ * If it is a PdfName
, it is cast down and returned as such.
+ * Otherwise null
is returned.
+ *
+ * @param key A PdfName
+ * @return the associated PdfName
object,
+ * or null
+ */
+ public PdfName getAsName(PdfName key) {
+ PdfName name = null;
+ PdfObject orig = getDirectObject(key);
+ if (orig != null && orig.isName())
+ name = (PdfName) orig;
+ return name;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfBoolean
,
+ * resolving indirect references.
+ *
+ * The object associated with the PdfName
given is retrieved
+ * and resolved to a direct object.
+ * If it is a PdfBoolean
, it is cast down and returned as such.
+ * Otherwise null
is returned.
+ *
+ * @param key A PdfName
+ * @return the associated PdfBoolean
object,
+ * or null
+ */
+ public PdfBoolean getAsBoolean(PdfName key) {
+ PdfBoolean bool = null;
+ PdfObject orig = getDirectObject(key);
+ if (orig != null && orig.isBoolean())
+ bool = (PdfBoolean)orig;
+ return bool;
+ }
+
+ /**
+ * Returns a PdfObject
as a PdfIndirectReference
.
+ *
+ * The object associated with the PdfName
given is retrieved
+ * If it is a PdfIndirectReference
, it is cast down and returned
+ * as such. Otherwise null
is returned.
+ *
+ * @param key A PdfName
+ * @return the associated PdfIndirectReference
object,
+ * or null
+ */
+ public PdfIndirectReference getAsIndirectObject(PdfName key) {
+ PdfIndirectReference ref = null;
+ PdfObject orig = get(key); // not getDirect this time.
+ if (orig != null && orig.isIndirect())
+ ref = (PdfIndirectReference) orig;
+ return ref;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfDocument.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfDocument.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfDocument.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfDocument.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,2987 @@
+/*
+ * $Name: $
+ * $Id: PdfDocument.java,v 1.209 2005/09/02 11:32:59 blowagie Exp $
+ *
+ * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.awt.Color;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.TreeMap;
+
+import pdftk.com.lowagie.text.Anchor;
+import pdftk.com.lowagie.text.Annotation;
+import pdftk.com.lowagie.text.BadElementException;
+// import pdftk.com.lowagie.text.Cell; ssteward: dropped in 1.44
+import pdftk.com.lowagie.text.Chunk;
+import pdftk.com.lowagie.text.DocListener;
+import pdftk.com.lowagie.text.Document;
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.Element;
+import pdftk.com.lowagie.text.ExceptionConverter;
+// import pdftk.com.lowagie.text.Graphic; ssteward: dropped in 1.44
+// import pdftk.com.lowagie.text.HeaderFooter; ssteward: dropped in 1.44
+// import pdftk.com.lowagie.text.Image; ssteward: dropped in 1.44
+import pdftk.com.lowagie.text.List;
+import pdftk.com.lowagie.text.ListItem;
+import pdftk.com.lowagie.text.Meta;
+import pdftk.com.lowagie.text.Paragraph;
+import pdftk.com.lowagie.text.Phrase;
+import pdftk.com.lowagie.text.Rectangle;
+// import pdftk.com.lowagie.text.Section; ssteward: dropped in 1.44
+// import pdftk.com.lowagie.text.SimpleTable; ssteward: dropped in 1.44
+import pdftk.com.lowagie.text.StringCompare;
+// import pdftk.com.lowagie.text.Table; ssteward: dropped in 1.44
+// import pdftk.com.lowagie.text.Watermark; ssteward: dropped in 1.44
+import pdftk.com.lowagie.text.xml.xmp.XmpWriter;
+
+/**
+ * PdfDocument
is the class that is used by PdfWriter
+ * to translate a Document
into a PDF with different pages.
+ *
+ * A PdfDocument
always listens to a Document
+ * and adds the Pdf representation of every Element
that is
+ * added to the Document
.
+ *
+ * @see pdftk.com.lowagie.text.Document
+ * @see pdftk.com.lowagie.text.DocListener
+ * @see PdfWriter
+ */
+
+class PdfDocument extends Document implements DocListener {
+
+ /**
+ * PdfInfo
is the PDF InfoDictionary.
+ *
+ * A document's trailer may contain a reference to an Info dictionary that provides information
+ * about the document. This optional dictionary may contain one or more keys, whose values
+ * should be strings.
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 6.10 (page 120-121)
+ */
+
+ public static class PdfInfo extends PdfDictionary {
+
+ // constructors
+
+ /**
+ * Construct a PdfInfo
-object.
+ */
+
+ PdfInfo() {
+ super();
+ addProducer();
+ addCreationDate();
+ }
+
+ /**
+ * Constructs a PdfInfo
-object.
+ *
+ * @param author name of the author of the document
+ * @param title title of the document
+ * @param subject subject of the document
+ */
+
+ PdfInfo(String author, String title, String subject) {
+ this();
+ addTitle(title);
+ addSubject(subject);
+ addAuthor(author);
+ }
+
+ /**
+ * Adds the title of the document.
+ *
+ * @param title the title of the document
+ */
+
+ void addTitle(String title) {
+ put(PdfName.TITLE, new PdfString(title/*ssteward , PdfObject.TEXT_UNICODE*/));
+ }
+
+ /**
+ * Adds the subject to the document.
+ *
+ * @param subject the subject of the document
+ */
+
+ void addSubject(String subject) {
+ put(PdfName.SUBJECT, new PdfString(subject/*ssteward, PdfObject.TEXT_UNICODE*/));
+ }
+
+ /**
+ * Adds some keywords to the document.
+ *
+ * @param keywords the keywords of the document
+ */
+
+ void addKeywords(String keywords) {
+ put(PdfName.KEYWORDS, new PdfString(keywords/*ssteward, PdfObject.TEXT_UNICODE*/));
+ }
+
+ /**
+ * Adds the name of the author to the document.
+ *
+ * @param author the name of the author
+ */
+
+ void addAuthor(String author) {
+ put(PdfName.AUTHOR, new PdfString(author/*ssteward, PdfObject.TEXT_UNICODE*/));
+ }
+
+ /**
+ * Adds the name of the creator to the document.
+ *
+ * @param creator the name of the creator
+ */
+
+ void addCreator(String creator) {
+ put(PdfName.CREATOR, new PdfString(creator/*, PdfObject.TEXT_UNICODE ssteward*/));
+ }
+
+ /**
+ * Adds the name of the producer to the document.
+ */
+
+ void addProducer() {
+ // This line may only be changed by Bruno Lowagie or Paulo Soares
+ put(PdfName.PRODUCER, new PdfString(getVersion()));
+ // Do not edit the line above!
+ }
+
+ /**
+ * Adds the date of creation to the document.
+ */
+
+ void addCreationDate() {
+ PdfString date = new PdfDate();
+ put(PdfName.CREATIONDATE, date);
+ put(PdfName.MODDATE, date);
+ }
+
+ void addkey(String key, String value) {
+ if (key.equals("Producer") || key.equals("CreationDate"))
+ return;
+ put(new PdfName(key), new PdfString(value/*ssteward, PdfObject.TEXT_UNICODE*/));
+ }
+ }
+
+ /**
+ * PdfCatalog
is the PDF Catalog-object.
+ *
+ * The Catalog is a dictionary that is the root node of the document. It contains a reference
+ * to the tree of pages contained in the document, a reference to the tree of objects representing
+ * the document's outline, a reference to the document's article threads, and the list of named
+ * destinations. In addition, the Catalog indicates whether the document's outline or thumbnail
+ * page images should be displayed automatically when the document is viewed and wether some location
+ * other than the first page should be shown when the document is opened.
+ * In this class however, only the reference to the tree of pages is implemented.
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 6.2 (page 67-71)
+ */
+
+ static class PdfCatalog extends PdfDictionary {
+
+ PdfWriter writer;
+ // constructors
+
+ /**
+ * Constructs a PdfCatalog
.
+ *
+ * @param pages an indirect reference to the root of the document's Pages tree.
+ * @param writer the writer the catalog applies to
+ */
+
+ PdfCatalog(PdfIndirectReference pages, PdfWriter writer) {
+ super(CATALOG);
+ this.writer = writer;
+ put(PdfName.PAGES, pages);
+ }
+
+ /**
+ * Constructs a PdfCatalog
.
+ *
+ * @param pages an indirect reference to the root of the document's Pages tree.
+ * @param outlines an indirect reference to the outline tree.
+ * @param writer the writer the catalog applies to
+ */
+
+ PdfCatalog(PdfIndirectReference pages, PdfIndirectReference outlines, PdfWriter writer) {
+ super(CATALOG);
+ this.writer = writer;
+ put(PdfName.PAGES, pages);
+ put(PdfName.PAGEMODE, PdfName.USEOUTLINES);
+ put(PdfName.OUTLINES, outlines);
+ }
+
+ /**
+ * Adds the names of the named destinations to the catalog.
+ * @param localDestinations the local destinations
+ * @param documentJavaScript the javascript used in the document
+ * @param writer the writer the catalog applies to
+ */
+ void addNames(TreeMap localDestinations, ArrayList documentJavaScript, PdfWriter writer) {
+ if (localDestinations.size() == 0 && documentJavaScript.size() == 0)
+ return;
+ try {
+ PdfDictionary names = new PdfDictionary();
+ if (localDestinations.size() > 0) {
+ PdfArray ar = new PdfArray();
+ for (Iterator i = localDestinations.keySet().iterator(); i.hasNext();) {
+ String name = (String)i.next();
+ Object obj[] = (Object[])localDestinations.get(name);
+ PdfIndirectReference ref = (PdfIndirectReference)obj[1];
+ ar.add(new PdfString(name));
+ ar.add(ref);
+ }
+ PdfDictionary dests = new PdfDictionary();
+ dests.put(PdfName.NAMES, ar);
+ names.put(PdfName.DESTS, writer.addToBody(dests).getIndirectReference());
+ }
+ if (documentJavaScript.size() > 0) {
+ String s[] = new String[documentJavaScript.size()];
+ for (int k = 0; k < s.length; ++k)
+ s[k] = Integer.toHexString(k);
+ Arrays.sort(s, new StringCompare());
+ PdfArray ar = new PdfArray();
+ for (int k = 0; k < s.length; ++k) {
+ ar.add(new PdfString(s[k]));
+ ar.add((PdfIndirectReference)documentJavaScript.get(k));
+ }
+ PdfDictionary js = new PdfDictionary();
+ js.put(PdfName.NAMES, ar);
+ names.put(PdfName.JAVASCRIPT, writer.addToBody(js).getIndirectReference());
+ }
+ put(PdfName.NAMES, writer.addToBody(names).getIndirectReference());
+ }
+ catch (IOException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /** Sets the viewer preferences as the sum of several constants.
+ * @param preferences the viewer preferences
+ * @see PdfWriter#setViewerPreferences
+ */
+ /* ssteward: debug
+ void setViewerPreferences(int preferences) {
+ PdfReader.setViewerPreferences(preferences, this);
+ }
+ */
+
+ void setOpenAction(PdfAction action) {
+ put(PdfName.OPENACTION, action);
+ }
+
+
+ /** Sets the document level additional actions.
+ * @param actions dictionary of actions
+ */
+ void setAdditionalActions(PdfDictionary actions) {
+ try {
+ put(PdfName.AA, writer.addToBody(actions).getIndirectReference());
+ } catch (Exception e) {
+ new ExceptionConverter(e);
+ }
+ }
+
+
+ void setPageLabels(PdfPageLabels pageLabels) {
+ put(PdfName.PAGELABELS, pageLabels.getDictionary());
+ }
+
+ void setAcroForm(PdfObject fields) {
+ put(PdfName.ACROFORM, fields);
+ }
+ }
+
+ // membervariables
+ private PdfIndirectReference thumb;
+
+ /** The characters to be applied the hanging ponctuation. */
+ static final String hangingPunctuation = ".,;:'";
+
+ /** The PdfWriter
. */
+ private PdfWriter writer;
+
+ /** some meta information about the Document. */
+ private PdfInfo info = new PdfInfo();
+
+ /** Signals that OnOpenDocument should be called. */
+ private boolean firstPageEvent = true;
+
+ /** Signals that onParagraph is valid. */
+ private boolean isParagraph = true;
+
+ // Horizontal line
+
+ /** The line that is currently being written. */
+ private PdfLine line = null;
+
+ /** This represents the current indentation of the PDF Elements on the left side. */
+ private float indentLeft = 0;
+
+ /** This represents the current indentation of the PDF Elements on the right side. */
+ private float indentRight = 0;
+
+ /** This represents the current indentation of the PDF Elements on the left side. */
+ private float listIndentLeft = 0;
+
+ /** This represents the current alignment of the PDF Elements. */
+ private int alignment = Element.ALIGN_LEFT;
+
+ // Vertical lines
+
+ /** This is the PdfContentByte object, containing the text. */
+ private PdfContentByte text;
+
+ /** This is the PdfContentByte object, containing the borders and other Graphics. */
+ private PdfContentByte graphics;
+
+ /** The lines that are written until now. */
+ private ArrayList lines = new ArrayList();
+
+ /** This represents the leading of the lines. */
+ private float leading = 0;
+
+ /** This is the current height of the document. */
+ private float currentHeight = 0;
+
+ /** This represents the current indentation of the PDF Elements on the top side. */
+ private float indentTop = 0;
+
+ /** This represents the current indentation of the PDF Elements on the bottom side. */
+ private float indentBottom = 0;
+
+ /** This checks if the page is empty. */
+ private boolean pageEmpty = true;
+
+ private int textEmptySize;
+ // resources
+
+ /** This is the size of the next page. */
+ protected Rectangle nextPageSize = null;
+
+ /** This is the size of the several boxes of the current Page. */
+ protected HashMap thisBoxSize = new HashMap();
+
+ /** This is the size of the several boxes that will be used in
+ * the next page. */
+ protected HashMap boxSize = new HashMap();
+
+ /** This are the page resources of the current Page. */
+ protected PageResources pageResources;
+
+ // images
+
+ /** This is the image that could not be shown on a previous page. */
+ //private Image imageWait = null; ssteward: dropped in 1.44
+
+ /** This is the position where the image ends. */
+ private float imageEnd = -1;
+
+ /** This is the indentation caused by an image on the left. */
+ private float imageIndentLeft = 0;
+
+ /** This is the indentation caused by an image on the right. */
+ private float imageIndentRight = 0;
+
+ // annotations and outlines
+
+ /** This is the array containing the references to the annotations. */
+ private ArrayList annotations;
+
+ /** This is an array containg references to some delayed annotations. */
+ private ArrayList delayedAnnotations = new ArrayList();
+
+ /** This is the AcroForm object. */
+ PdfAcroForm acroForm;
+
+ /** This is the root outline of the document. */
+ private PdfOutline rootOutline;
+
+ /** This is the current PdfOutline
in the hierarchy of outlines. */
+ private PdfOutline currentOutline;
+
+ /** The current active PdfAction
when processing an Anchor
. */
+ private PdfAction currentAction = null;
+
+ /**
+ * Stores the destinations keyed by name. Value is
+ * Object[]{PdfAction,PdfIndirectReference,PdfDestintion}
.
+ */
+ private TreeMap localDestinations = new TreeMap(new StringCompare());
+
+ private ArrayList documentJavaScript = new ArrayList();
+
+ /** these are the viewerpreferences of the document */
+ private int viewerPreferences = 0;
+
+ private String openActionName;
+ private PdfAction openActionAction;
+ private PdfDictionary additionalActions;
+ private PdfPageLabels pageLabels;
+
+ //add by Jin-Hsia Yang
+ private boolean isNewpage = false;
+
+ private float paraIndent = 0;
+ //end add by Jin-Hsia Yang
+
+ /** margin in x direction starting from the left. Will be valid in the next page */
+ protected float nextMarginLeft;
+
+ /** margin in x direction starting from the right. Will be valid in the next page */
+ protected float nextMarginRight;
+
+ /** margin in y direction starting from the top. Will be valid in the next page */
+ protected float nextMarginTop;
+
+ /** margin in y direction starting from the bottom. Will be valid in the next page */
+ protected float nextMarginBottom;
+
+/** The duration of the page */
+ protected int duration=-1; // negative values will indicate no duration
+
+/** The page transition */
+ protected PdfTransition transition=null;
+
+ protected PdfDictionary pageAA = null;
+
+ /** Holds value of property strictImageSequence. */
+ private boolean strictImageSequence = false;
+
+ /** Holds the type of the last element, that has been added to the document. */
+ private int lastElementType = -1;
+
+ protected int markPoint;
+
+ // constructors
+
+ /**
+ * Constructs a new PDF document.
+ * @throws DocumentException on error
+ */
+
+ public PdfDocument() throws DocumentException {
+ super();
+ addProducer();
+ addCreationDate();
+ }
+
+ // listener methods
+
+ /**
+ * Adds a PdfWriter
to the PdfDocument
.
+ *
+ * @param writer the PdfWriter
that writes everything
+ * what is added to this document to an outputstream.
+ * @throws DocumentException on error
+ */
+
+ public void addWriter(PdfWriter writer) throws DocumentException {
+ if (this.writer == null) {
+ this.writer = writer;
+ acroForm = new PdfAcroForm(writer);
+ return;
+ }
+ throw new DocumentException("You can only add a writer to a PdfDocument once.");
+ }
+
+ /**
+ * Sets the pagesize.
+ *
+ * @param pageSize the new pagesize
+ * @return true
if the page size was set
+ */
+
+ public boolean setPageSize(Rectangle pageSize) {
+ if (writer != null && writer.isPaused()) {
+ return false;
+ }
+ nextPageSize = new Rectangle(pageSize);
+ return true;
+ }
+
+ /**
+ * Changes the header of this document.
+ *
+ * @param header the new header
+ */
+ /* ssteward: dropped in 1.44
+ public void setHeader(HeaderFooter header) {
+ if (writer != null && writer.isPaused()) {
+ return;
+ }
+ super.setHeader(header);
+ }
+ */
+
+ /**
+ * Resets the header of this document.
+ */
+ /* ssteward: dropped in 1.44
+ public void resetHeader() {
+ if (writer != null && writer.isPaused()) {
+ return;
+ }
+ super.resetHeader();
+ }
+ */
+ /**
+ * Changes the footer of this document.
+ *
+ * @param footer the new footer
+ */
+ /* ssteward: dropped in 1.44
+ public void setFooter(HeaderFooter footer) {
+ if (writer != null && writer.isPaused()) {
+ return;
+ }
+ super.setFooter(footer);
+ }
+ */
+ /**
+ * Resets the footer of this document.
+ */
+ /* ssteward: dropped in 1.44
+ public void resetFooter() {
+ if (writer != null && writer.isPaused()) {
+ return;
+ }
+ super.resetFooter();
+ }
+ */
+ /**
+ * Sets the page number to 0.
+ */
+
+ public void resetPageCount() {
+ if (writer != null && writer.isPaused()) {
+ return;
+ }
+ super.resetPageCount();
+ }
+
+ /**
+ * Sets the page number.
+ *
+ * @param pageN the new page number
+ */
+
+ public void setPageCount(int pageN) {
+ if (writer != null && writer.isPaused()) {
+ return;
+ }
+ super.setPageCount(pageN);
+ }
+
+ /**
+ * Sets the Watermark
.
+ *
+ * @param watermark the watermark to add
+ * @return true
if the element was added, false
if not.
+ */
+ /* ssteward: dropped in 1.44
+ public boolean add(Watermark watermark) {
+ if (writer != null && writer.isPaused()) {
+ return false;
+ }
+ this.watermark = watermark;
+ return true;
+ }
+ */
+
+ /**
+ * Removes the Watermark
.
+ */
+ /* ssteward: dropped in 1.44
+ public void removeWatermark() {
+ if (writer != null && writer.isPaused()) {
+ return;
+ }
+ this.watermark = null;
+ }
+ */
+
+ /**
+ * Sets the margins.
+ *
+ * @param marginLeft the margin on the left
+ * @param marginRight the margin on the right
+ * @param marginTop the margin on the top
+ * @param marginBottom the margin on the bottom
+ * @return a boolean
+ */
+
+ public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom) {
+ if (writer != null && writer.isPaused()) {
+ return false;
+ }
+ nextMarginLeft = marginLeft;
+ nextMarginRight = marginRight;
+ nextMarginTop = marginTop;
+ nextMarginBottom = marginBottom;
+ return true;
+ }
+
+ protected PdfArray rotateAnnotations() {
+ PdfArray array = new PdfArray();
+ int rotation = pageSize.getRotation() % 360;
+ int currentPage = writer.getCurrentPageNumber();
+ for (int k = 0; k < annotations.size(); ++k) {
+ PdfAnnotation dic = (PdfAnnotation)annotations.get(k);
+ int page = dic.getPlaceInPage();
+ if (page > currentPage) {
+ delayedAnnotations.add(dic);
+ continue;
+ }
+ if (dic.isForm()) {
+ if (!dic.isUsed()) {
+ HashMap templates = dic.getTemplates();
+ if (templates != null)
+ acroForm.addFieldTemplates(templates);
+ }
+ PdfFormField field = (PdfFormField)dic;
+ if (field.getParent() == null)
+ acroForm.addDocumentField(field.getIndirectReference());
+ }
+ if (dic.isAnnotation()) {
+ array.add(dic.getIndirectReference());
+ if (!dic.isUsed()) {
+ PdfRectangle rect = (PdfRectangle)dic.get(PdfName.RECT);
+ if (rect != null) {
+ switch (rotation) {
+ case 90:
+ dic.put(PdfName.RECT, new PdfRectangle(
+ pageSize.top() - rect.bottom(),
+ rect.left(),
+ pageSize.top() - rect.top(),
+ rect.right()));
+ break;
+ case 180:
+ dic.put(PdfName.RECT, new PdfRectangle(
+ pageSize.right() - rect.left(),
+ pageSize.top() - rect.bottom(),
+ pageSize.right() - rect.right(),
+ pageSize.top() - rect.top()));
+ break;
+ case 270:
+ dic.put(PdfName.RECT, new PdfRectangle(
+ rect.bottom(),
+ pageSize.right() - rect.left(),
+ rect.top(),
+ pageSize.right() - rect.right()));
+ break;
+ }
+ }
+ }
+ }
+ if (!dic.isUsed()) {
+ dic.setUsed();
+ try {
+ writer.addToBody(dic, dic.getIndirectReference());
+ }
+ catch (IOException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+ }
+ return array;
+ }
+
+ /**
+ * Makes a new page and sends it to the PdfWriter
.
+ *
+ * @return a boolean
+ * @throws DocumentException on error
+ */
+
+ public boolean newPage() throws DocumentException {
+ lastElementType = -1;
+ //add by Jin-Hsia Yang
+ isNewpage = true;
+ //end add by Jin-Hsia Yang
+ if (writer.getDirectContent().size() == 0 && writer.getDirectContentUnder().size() == 0 && (pageEmpty || (writer != null && writer.isPaused()))) {
+ return false;
+ }
+ PdfPageEvent pageEvent = writer.getPageEvent();
+ if (pageEvent != null)
+ pageEvent.onEndPage(writer, this);
+
+ //Added to inform any listeners that we are moving to a new page (added by David Freels)
+ super.newPage();
+
+ // the following 2 lines were added by Pelikan Stephan
+ imageIndentLeft = 0;
+ imageIndentRight = 0;
+
+ // we flush the arraylist with recently written lines
+ flushLines();
+ // we assemble the resources of this pages
+ pageResources.addDefaultColorDiff(writer.getDefaultColorspace());
+ PdfDictionary resources = pageResources.getResources();
+ // we make a new page and add it to the document
+ if (writer.getPDFXConformance() != PdfWriter.PDFXNONE) {
+ if (thisBoxSize.containsKey("art") && thisBoxSize.containsKey("trim"))
+ throw new PdfXConformanceException("Only one of ArtBox or TrimBox can exist in the page.");
+ if (!thisBoxSize.containsKey("art") && !thisBoxSize.containsKey("trim")) {
+ if (thisBoxSize.containsKey("crop"))
+ thisBoxSize.put("trim", thisBoxSize.get("crop"));
+ else
+ thisBoxSize.put("trim", new PdfRectangle(pageSize, pageSize.getRotation()));
+ }
+ }
+ PdfPage page;
+ int rotation = pageSize.getRotation();
+ page = new PdfPage(new PdfRectangle(pageSize, rotation), thisBoxSize, resources, rotation);
+ if (writer.isTagged())
+ page.put(PdfName.STRUCTPARENTS, new PdfNumber(writer.getCurrentPageNumber() - 1));
+ // we add the transitions
+ if (this.transition!=null) {
+ page.put(PdfName.TRANS, this.transition.getTransitionDictionary());
+ transition = null;
+ }
+ if (this.duration>0) {
+ page.put(PdfName.DUR,new PdfNumber(this.duration));
+ duration = 0;
+ }
+ // we add the page object additional actions
+ if (pageAA != null) {
+ try {
+ page.put(PdfName.AA, writer.addToBody(pageAA).getIndirectReference());
+ }
+ catch (IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ pageAA = null;
+ }
+ // we check if the userunit is defined
+ if (writer.getUserunit() > 0f) {
+ page.put(PdfName.USERUNIT, new PdfNumber(writer.getUserunit()));
+ }
+ // we add the annotations
+ if (annotations.size() > 0) {
+ PdfArray array = rotateAnnotations();
+ if (array.size() != 0)
+ page.put(PdfName.ANNOTS, array);
+ }
+ // we add the thumbs
+ if (thumb != null) {
+ page.put(PdfName.THUMB, thumb);
+ thumb = null;
+ }
+ if (!open || close) {
+ throw new PdfException("The document isn't open.");
+ }
+ if (text.size() > textEmptySize)
+ text.endText();
+ else
+ text = null;
+ writer.add(page, new PdfContents(writer.getDirectContentUnder(), graphics, text, writer.getDirectContent(), pageSize));
+ // we initialize the new page
+ initPage();
+
+ //add by Jin-Hsia Yang
+ isNewpage = false;
+ //end add by Jin-Hsia Yang
+
+ return true;
+ }
+
+ // methods to open and close a document
+
+ /**
+ * Opens the document.
+ *
+ * You have to open the document before you can begin to add content
+ * to the body of the document.
+ */
+
+ public void open() {
+ if (!open) {
+ super.open();
+ writer.open();
+ rootOutline = new PdfOutline(writer);
+ currentOutline = rootOutline;
+ }
+ try {
+ initPage();
+ }
+ catch(DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+ void outlineTree(PdfOutline outline) throws IOException {
+ outline.setIndirectReference(writer.getPdfIndirectReference());
+ if (outline.parent() != null)
+ outline.put(PdfName.PARENT, outline.parent().indirectReference());
+ ArrayList kids = outline.getKids();
+ int size = kids.size();
+ for (int k = 0; k < size; ++k)
+ outlineTree((PdfOutline)kids.get(k));
+ for (int k = 0; k < size; ++k) {
+ if (k > 0)
+ ((PdfOutline)kids.get(k)).put(PdfName.PREV, ((PdfOutline)kids.get(k - 1)).indirectReference());
+ if (k < size - 1)
+ ((PdfOutline)kids.get(k)).put(PdfName.NEXT, ((PdfOutline)kids.get(k + 1)).indirectReference());
+ }
+ if (size > 0) {
+ outline.put(PdfName.FIRST, ((PdfOutline)kids.get(0)).indirectReference());
+ outline.put(PdfName.LAST, ((PdfOutline)kids.get(size - 1)).indirectReference());
+ }
+ for (int k = 0; k < size; ++k) {
+ PdfOutline kid = (PdfOutline)kids.get(k);
+ writer.addToBody(kid, kid.indirectReference());
+ }
+ }
+
+ void writeOutlines() throws IOException {
+ if (rootOutline.getKids().size() == 0)
+ return;
+ outlineTree(rootOutline);
+ writer.addToBody(rootOutline, rootOutline.indirectReference());
+ }
+
+ void traverseOutlineCount(PdfOutline outline) {
+ ArrayList kids = outline.getKids();
+ PdfOutline parent = outline.parent();
+ if (kids.size() == 0) {
+ if (parent != null) {
+ parent.setCount(parent.getCount() + 1);
+ }
+ }
+ else {
+ for (int k = 0; k < kids.size(); ++k) {
+ traverseOutlineCount((PdfOutline)kids.get(k));
+ }
+ if (parent != null) {
+ if (outline.isOpen()) {
+ parent.setCount(outline.getCount() + parent.getCount() + 1);
+ }
+ else {
+ parent.setCount(parent.getCount() + 1);
+ outline.setCount(-outline.getCount());
+ }
+ }
+ }
+ }
+
+ void calculateOutlineCount() {
+ if (rootOutline.getKids().size() == 0)
+ return;
+ traverseOutlineCount(rootOutline);
+ }
+ /**
+ * Closes the document.
+ *
+ * Once all the content has been written in the body, you have to close
+ * the body. After that nothing can be written to the body anymore.
+ */
+
+ public void close() {
+ if (close) {
+ return;
+ }
+ try {
+ boolean wasImage = false; // (imageWait != null); ssteward: dropped in 1.44
+ newPage();
+ if ( false || wasImage) newPage(); // imageWait != null ssteward: dropped in 1.44
+ if (annotations.size() > 0)
+ throw new RuntimeException(annotations.size() + " annotations had invalid placement pages.");
+ PdfPageEvent pageEvent = writer.getPageEvent();
+ if (pageEvent != null)
+ pageEvent.onCloseDocument(writer, this);
+ super.close();
+
+ writer.addLocalDestinations(localDestinations);
+ calculateOutlineCount();
+ writeOutlines();
+ }
+ catch(Exception e) {
+ throw new ExceptionConverter(e);
+ }
+
+ writer.close();
+ }
+
+ PageResources getPageResources() {
+ return pageResources;
+ }
+
+ /** Adds a PdfPTable
to the document.
+ * @param ptable the PdfPTable
to be added to the document.
+ * @throws DocumentException on error
+ */
+ /* ssteward: dropped in 1.44
+ void addPTable(PdfPTable ptable) throws DocumentException {
+ ColumnText ct = new ColumnText(writer.getDirectContent());
+ if (currentHeight > 0) {
+ Paragraph p = new Paragraph();
+ p.setLeading(0);
+ ct.addElement(p);
+ }
+ ct.addElement(ptable);
+ boolean he = ptable.isHeadersInEvent();
+ ptable.setHeadersInEvent(true);
+ int loop = 0;
+ while (true) {
+ ct.setSimpleColumn(indentLeft(), indentBottom(), indentRight(), indentTop() - currentHeight);
+ int status = ct.go();
+ if ((status & ColumnText.NO_MORE_TEXT) != 0) {
+ text.moveText(0, ct.getYLine() - indentTop() + currentHeight);
+ currentHeight = indentTop() - ct.getYLine();
+ break;
+ }
+ if (indentTop() - currentHeight == ct.getYLine())
+ ++loop;
+ else
+ loop = 0;
+ if (loop == 3) {
+ add(new Paragraph("ERROR: Infinite table loop"));
+ break;
+ }
+ newPage();
+ }
+ ptable.setHeadersInEvent(he);
+ }
+ */
+
+ /**
+ * Gets a PdfTable object
+ * (contributed by dperezcar@fcc.es)
+ * @param table a high level table object
+ * @param supportRowAdditions
+ * @return returns a PdfTable object
+ * @see PdfWriter#getPdfTable(Table)
+ */
+ /* ssteward: dropped in 1.44
+ PdfTable getPdfTable(Table table, boolean supportRowAdditions) {
+ return new PdfTable(table, indentLeft(), indentRight(), indentTop() - currentHeight, supportRowAdditions);
+ }
+ */
+
+ /**
+ * @see PdfWriter#breakTableIfDoesntFit(PdfTable)
+ * (contributed by dperezcar@fcc.es)
+ * @param table Table to add
+ * @return true if the table will be broken
+ * @throws DocumentException
+ */
+ /* ssteward: dropped in 1.44
+ boolean breakTableIfDoesntFit(PdfTable table) throws DocumentException {
+ table.updateRowAdditions();
+ // Do we have any full page available?
+ if (!table.hasToFitPageTable() && table.bottom() <= indentBottom) {
+ // Then output that page
+ add(table, true);
+ return true;
+ }
+ return false;
+ }
+ */
+
+ /**
+ * Adds a new table to
+ * @param table Table to add. Rendered rows will be deleted after processing.
+ * @param onlyFirstPage Render only the first full page
+ * @throws DocumentException
+ */
+ /* ssteward: dropped in 1.44
+ private void add(PdfTable table, boolean onlyFirstPage) throws DocumentException {
+ // before every table, we flush all lines
+ flushLines();
+
+ // initialisation of parameters
+ float pagetop = indentTop();
+ float oldHeight = currentHeight;
+ float cellDisplacement;
+ PdfCell cell;
+ PdfContentByte cellGraphics = new PdfContentByte(writer);
+ boolean tableHasToFit =
+ table.hasToFitPageTable() ? (table.bottom() < indentBottom() && table.height() < (top() - bottom())) : false;
+ if (pageEmpty)
+ tableHasToFit = false;
+ boolean cellsHaveToFit = table.hasToFitPageCells();
+
+ // drawing the table
+ ArrayList cells = table.getCells();
+ ArrayList headercells = table.getHeaderCells();
+ // Check if we have removed header cells in a previous call
+ if (headercells.size() > 0 && (cells.size() == 0 || cells.get(0) != headercells.get(0))) {
+ ArrayList allCells = new ArrayList(cells.size()+headercells.size());
+ allCells.addAll(headercells);
+ allCells.addAll(cells);
+ cells = allCells;
+ }
+ while (!cells.isEmpty()) {
+ // initialisation of some extra parameters;
+ float lostTableBottom = 0;
+
+ // loop over the cells
+ boolean cellsShown = false;
+ int currentGroupNumber = 0;
+ boolean headerChecked = false;
+ for (ListIterator iterator = cells.listIterator(); iterator.hasNext() && !tableHasToFit;) {
+ cell = (PdfCell) iterator.next();
+ boolean atLeastOneFits = false;
+ if( cellsHaveToFit ) {
+ if( !cell.isHeader() ) {
+ if (cell.getGroupNumber() != currentGroupNumber) {
+ boolean cellsFit = true;
+ currentGroupNumber = cell.getGroupNumber();
+ cellsHaveToFit = table.hasToFitPageCells();
+ int cellCount = 0;
+ while (cell.getGroupNumber() == currentGroupNumber && cellsFit && iterator.hasNext()) {
+ if (cell.bottom() < indentBottom()) {
+ cellsFit = false;
+ }
+ else {
+ atLeastOneFits |= true;
+ }
+ cell = (PdfCell) iterator.next();
+ cellCount++;
+ }
+ if (!atLeastOneFits) {
+ cellsHaveToFit = false;
+ }
+ if (!cellsFit) {
+ break;
+ }
+ for (int i = cellCount; i >= 0; i--) {
+ cell = (PdfCell) iterator.previous();
+ }
+ }
+ }
+ else {
+ if( !headerChecked ) {
+ headerChecked = true;
+ boolean cellsFit = true;
+ int cellCount = 0;
+ float firstTop = cell.top();
+ while (cell.isHeader() && cellsFit && iterator.hasNext()) {
+ if (firstTop - cell.bottom(0) > indentTop() - currentHeight - indentBottom()) {
+ cellsFit = false;
+ }
+ cell = (PdfCell) iterator.next();
+ cellCount++;
+ }
+ currentGroupNumber = cell.getGroupNumber();
+ while (cell.getGroupNumber() == currentGroupNumber && cellsFit && iterator.hasNext()) {
+ if (firstTop - cell.bottom(0) > indentTop() - currentHeight - indentBottom() - 10.0) {
+ cellsFit = false;
+ }
+ cell = (PdfCell) iterator.next();
+ cellCount++;
+ }
+ for (int i = cellCount; i >= 0; i--) {
+ cell = (PdfCell) iterator.previous();
+ }
+ if (!cellsFit) {
+ while( cell.isHeader() ) {
+ iterator.remove();
+ cell = (PdfCell) iterator.next();
+ }
+ break;
+ }
+ }
+ }
+ }
+ lines = cell.getLines(pagetop, indentBottom());
+ // if there are lines to add, add them
+ if (lines != null && lines.size() > 0) {
+ // we paint the borders of the cells
+ cellsShown = true;
+ cellGraphics.rectangle(cell.rectangle(pagetop, indentBottom()));
+ lostTableBottom = Math.max(cell.bottom(), indentBottom());
+
+ // we write the text
+ float cellTop = cell.top(pagetop - oldHeight);
+ text.moveText(0, cellTop);
+ cellDisplacement = flushLines() - cellTop;
+ text.moveText(0, cellDisplacement);
+ if (oldHeight + cellDisplacement > currentHeight) {
+ currentHeight = oldHeight + cellDisplacement;
+ }
+ }
+ ArrayList images = cell.getImages(pagetop, indentBottom());
+ for (Iterator i = images.iterator(); i.hasNext();) {
+ cellsShown = true;
+ Image image = (Image) i.next();
+ graphics.addImage(image);
+ }
+ // if a cell is allready added completely, remove it
+ if (cell.mayBeRemoved()) {
+ iterator.remove();
+ }
+ }
+ tableHasToFit = false;
+ // we paint the graphics of the table after looping through all the cells
+ if (cellsShown) {
+ Rectangle tablerec = new Rectangle(table);
+ tablerec.setBorder(table.border());
+ tablerec.setBorderWidth(table.borderWidth());
+ tablerec.setBorderColor(table.borderColor());
+ tablerec.setBackgroundColor(table.backgroundColor());
+ tablerec.setGrayFill(table.grayFill());
+ PdfContentByte under = writer.getDirectContentUnder();
+ under.rectangle(tablerec.rectangle(top(), indentBottom()));
+ under.add(cellGraphics);
+ // bugfix by Gerald Fehringer: now again add the border for the table
+ // since it might have been covered by cell backgrounds
+ tablerec.setGrayFill(0);
+ tablerec.setBackgroundColor(null);
+ under.rectangle(tablerec.rectangle(top(), indentBottom()));
+ // end bugfix
+ }
+ cellGraphics = new PdfContentByte(null);
+ // if the table continues on the next page
+ if (!cells.isEmpty()) {
+ graphics.setLineWidth(table.borderWidth());
+ if (cellsShown && (table.border() & Rectangle.BOTTOM) == Rectangle.BOTTOM) {
+ // Draw the bottom line
+
+ // the color is set to the color of the element
+ Color tColor = table.borderColor();
+ if (tColor != null) {
+ graphics.setColorStroke(tColor);
+ }
+ graphics.moveTo(table.left(), Math.max(table.bottom(), indentBottom()));
+ graphics.lineTo(table.right(), Math.max(table.bottom(), indentBottom()));
+ graphics.stroke();
+ if (tColor != null) {
+ graphics.resetRGBColorStroke();
+ }
+ }
+
+ // old page
+ pageEmpty = false;
+ float difference = lostTableBottom;
+
+ // new page
+ newPage();
+ // G.F.: if something added in page event i.e. currentHeight > 0
+ float heightCorrection = 0;
+ boolean somethingAdded = false;
+ if (currentHeight > 0) {
+ heightCorrection = 6;
+ currentHeight += heightCorrection;
+ somethingAdded = true;
+ newLine();
+ flushLines();
+ indentTop = currentHeight - leading;
+ currentHeight = 0;
+ }
+ else {
+ flushLines();
+ }
+
+ // this part repeats the table headers (if any)
+ int size = headercells.size();
+ if (size > 0) {
+ // this is the top of the headersection
+ cell = (PdfCell) headercells.get(0);
+ float oldTop = cell.top(0);
+ // loop over all the cells of the table header
+ for (int i = 0; i < size; i++) {
+ cell = (PdfCell) headercells.get(i);
+ // calculation of the new cellpositions
+ cell.setTop(indentTop() - oldTop + cell.top(0));
+ cell.setBottom(indentTop() - oldTop + cell.bottom(0));
+ pagetop = cell.bottom();
+ // we paint the borders of the cell
+ cellGraphics.rectangle(cell.rectangle(indentTop(), indentBottom()));
+ // we write the text of the cell
+ ArrayList images = cell.getImages(indentTop(), indentBottom());
+ for (Iterator im = images.iterator(); im.hasNext();) {
+ cellsShown = true;
+ Image image = (Image) im.next();
+ graphics.addImage(image);
+ }
+ lines = cell.getLines(indentTop(), indentBottom());
+ float cellTop = cell.top(indentTop());
+ text.moveText(0, cellTop-heightCorrection);
+ cellDisplacement = flushLines() - cellTop+heightCorrection;
+ text.moveText(0, cellDisplacement);
+ }
+ currentHeight = indentTop() - pagetop + table.cellspacing();
+ text.moveText(0, pagetop - indentTop() - currentHeight);
+ }
+ else {
+ if (somethingAdded) {
+ pagetop = indentTop();
+ text.moveText(0, -table.cellspacing());
+ }
+ }
+ oldHeight = currentHeight - heightCorrection;
+
+ // calculating the new positions of the table and the cells
+ size = Math.min(cells.size(), table.columns());
+ int i = 0;
+ while (i < size) {
+ cell = (PdfCell) cells.get(i);
+ if (cell.top(-table.cellspacing()) > lostTableBottom) {
+ float newBottom = pagetop - difference + cell.bottom();
+ float neededHeight = cell.remainingHeight();
+ if (newBottom > pagetop - neededHeight) {
+ difference += newBottom - (pagetop - neededHeight);
+ }
+ }
+ i++;
+ }
+ size = cells.size();
+ table.setTop(indentTop());
+ table.setBottom(pagetop - difference + table.bottom(table.cellspacing()));
+ for (i = 0; i < size; i++) {
+ cell = (PdfCell) cells.get(i);
+ float newBottom = pagetop - difference + cell.bottom();
+ float newTop = pagetop - difference + cell.top(-table.cellspacing());
+ if (newTop > indentTop() - currentHeight) {
+ newTop = indentTop() - currentHeight;
+ }
+ //float newBottom = newTop - cell.height();
+ cell.setTop(newTop );
+ cell.setBottom(newBottom );
+ }
+ if (onlyFirstPage) {
+ break;
+ }
+ }
+ }
+
+ float tableHeight = table.top() - table.bottom();
+ currentHeight = oldHeight + tableHeight;
+ text.moveText(0, -tableHeight );
+ pageEmpty = false;
+ }
+ */
+
+ /**
+ * Signals that an Element
was added to the Document
.
+ *
+ * @param element the element to add
+ * @return true
if the element was added, false
if not.
+ * @throws DocumentException when a document isn't open yet, or has been closed
+ */
+ public boolean add(Element element) throws DocumentException {
+ if (writer != null && writer.isPaused()) {
+ return false;
+ }
+ try {
+
+ switch(element.type()) {
+
+ // Information (headers)
+ case Element.HEADER:
+ info.addkey(((Meta)element).name(), ((Meta)element).content());
+ break;
+ case Element.TITLE:
+ info.addTitle(((Meta)element).content());
+ break;
+ case Element.SUBJECT:
+ info.addSubject(((Meta)element).content());
+ break;
+ case Element.KEYWORDS:
+ info.addKeywords(((Meta)element).content());
+ break;
+ case Element.AUTHOR:
+ info.addAuthor(((Meta)element).content());
+ break;
+ case Element.CREATOR:
+ info.addCreator(((Meta)element).content());
+ break;
+ case Element.PRODUCER:
+ // you can not change the name of the producer
+ info.addProducer();
+ break;
+ case Element.CREATIONDATE:
+ // you can not set the creation date, only reset it
+ info.addCreationDate();
+ break;
+
+ case Element.CHUNK: {
+ // if there isn't a current line available, we make one
+ if (line == null) {
+ carriageReturn();
+ }
+
+ // we cast the element to a chunk
+ PdfChunk chunk = new PdfChunk((Chunk) element, currentAction);
+ // we try to add the chunk to the line, until we succeed
+ {
+ PdfChunk overflow;
+ while ((overflow = line.add(chunk)) != null) {
+ carriageReturn();
+ chunk = overflow;
+ }
+ }
+ pageEmpty = false;
+ if (chunk.isAttribute(Chunk.NEWPAGE)) {
+ newPage();
+ }
+ break;
+ }
+ case Element.ANCHOR: {
+ Anchor anchor = (Anchor) element;
+ String url = anchor.reference();
+ leading = anchor.leading();
+ if (url != null) {
+ currentAction = new PdfAction(url);
+ }
+
+ // we process the element
+ element.process(this);
+ currentAction = null;
+ break;
+ }
+ case Element.ANNOTATION: {
+ if (line == null) {
+ carriageReturn();
+ }
+ Annotation annot = (Annotation) element;
+ PdfAnnotation an = convertAnnotation(writer, annot);
+ annotations.add(an);
+ pageEmpty = false;
+ break;
+ }
+ case Element.PHRASE: {
+ // we cast the element to a phrase and set the leading of the document
+ leading = ((Phrase) element).leading();
+ // we process the element
+ element.process(this);
+ break;
+ }
+ case Element.PARAGRAPH: {
+ // we cast the element to a paragraph
+ Paragraph paragraph = (Paragraph) element;
+
+ float spacingBefore = paragraph.spacingBefore();
+ if (spacingBefore != 0) {
+ leading = spacingBefore;
+ carriageReturn();
+ if (!pageEmpty) {
+ /*
+ * Don't add spacing before a paragraph if it's the first
+ * on the page
+ */
+ Chunk space = new Chunk(" ");
+ space.process(this);
+ carriageReturn();
+ }
+ }
+
+ // we adjust the parameters of the document
+ alignment = paragraph.alignment();
+ leading = paragraph.leading();
+
+ carriageReturn();
+ // we don't want to make orphans/widows
+ if (currentHeight + line.height() + leading > indentTop() - indentBottom()) {
+ newPage();
+ }
+
+ // Begin added: Bonf (Marc Schneider) 2003-07-29
+ //carriageReturn();
+ // End added: Bonf (Marc Schneider) 2003-07-29
+
+ indentLeft += paragraph.indentationLeft();
+ indentRight += paragraph.indentationRight();
+
+ // Begin removed: Bonf (Marc Schneider) 2003-07-29
+ carriageReturn();
+ // End removed: Bonf (Marc Schneider) 2003-07-29
+
+
+ //add by Jin-Hsia Yang
+
+ paraIndent += paragraph.indentationLeft();
+ //end add by Jin-Hsia Yang
+
+ PdfPageEvent pageEvent = writer.getPageEvent();
+ if (pageEvent != null && isParagraph)
+ pageEvent.onParagraph(writer, this, indentTop() - currentHeight);
+
+ /* ssteward: dropped in 1.44
+ // if a paragraph has to be kept together, we wrap it in a table object
+ if (paragraph.getKeepTogether()) {
+ Table table = new Table(1, 1);
+ table.setOffset(0f);
+ table.setBorder(Table.NO_BORDER);
+ table.setWidth(100f);
+ table.setTableFitsPage(true);
+ Cell cell = new Cell(paragraph);
+ cell.setBorder(Table.NO_BORDER);
+ //patch by Matt Benson 11/01/2002 - 14:32:00
+ cell.setHorizontalAlignment(paragraph.alignment());
+ //end patch by Matt Benson
+ table.addCell(cell);
+ this.add(table);
+ break;
+ }
+ else
+ */
+ // we process the paragraph
+ element.process(this);
+
+ //add by Jin-Hsia Yang and blowagie
+ paraIndent -= paragraph.indentationLeft();
+ //end add by Jin-Hsia Yang and blowagie
+
+ // Begin removed: Bonf (Marc Schneider) 2003-07-29
+ // carriageReturn();
+ // End removed: Bonf (Marc Schneider) 2003-07-29
+
+ float spacingAfter = paragraph.spacingAfter();
+ if (spacingAfter != 0) {
+ leading = spacingAfter;
+ carriageReturn();
+ if (currentHeight + line.height() + leading < indentTop() - indentBottom()) {
+ /*
+ * Only add spacing after a paragraph if the extra
+ * spacing fits on the page.
+ */
+ Chunk space = new Chunk(" ");
+ space.process(this);
+ carriageReturn();
+ }
+ leading = paragraph.leading(); // restore original leading
+ }
+
+ if (pageEvent != null && isParagraph)
+ pageEvent.onParagraphEnd(writer, this, indentTop() - currentHeight);
+
+ alignment = Element.ALIGN_LEFT;
+ indentLeft -= paragraph.indentationLeft();
+ indentRight -= paragraph.indentationRight();
+
+ // Begin added: Bonf (Marc Schneider) 2003-07-29
+ carriageReturn();
+ // End added: Bonf (Marc Schneider) 2003-07-29
+
+ //add by Jin-Hsia Yang
+
+ //end add by Jin-Hsia Yang
+
+ break;
+ }
+ /* ssteward: dropped in 1.44
+ case Element.SECTION:
+ case Element.CHAPTER: {
+ // Chapters and Sections only differ in their constructor
+ // so we cast both to a Section
+ Section section = (Section) element;
+
+ boolean hasTitle = section.title() != null;
+
+ // if the section is a chapter, we begin a new page
+ if (section.isChapter()) {
+ newPage();
+ }
+ // otherwise, we begin a new line
+ else {
+ newLine();
+ }
+
+ if (hasTitle) {
+ float fith = indentTop() - currentHeight;
+ int rotation = pageSize.getRotation();
+ if (rotation == 90 || rotation == 180)
+ fith = pageSize.height() - fith;
+ PdfDestination destination = new PdfDestination(PdfDestination.FITH, fith);
+ while (currentOutline.level() >= section.depth()) {
+ currentOutline = currentOutline.parent();
+ }
+ PdfOutline outline = new PdfOutline(currentOutline, destination, section.getBookmarkTitle(), section.isBookmarkOpen());
+ currentOutline = outline;
+ }
+
+ // some values are set
+ carriageReturn();
+ indentLeft += section.indentationLeft();
+ indentRight += section.indentationRight();
+
+ PdfPageEvent pageEvent = writer.getPageEvent();
+ if (pageEvent != null)
+ if (element.type() == Element.CHAPTER)
+ pageEvent.onChapter(writer, this, indentTop() - currentHeight, section.title());
+ else
+ pageEvent.onSection(writer, this, indentTop() - currentHeight, section.depth(), section.title());
+
+ // the title of the section (if any has to be printed)
+ if (hasTitle) {
+ isParagraph = false;
+ add(section.title());
+ isParagraph = true;
+ }
+ indentLeft += section.indentation();
+ // we process the section
+ element.process(this);
+ // some parameters are set back to normal again
+ indentLeft -= section.indentationLeft() + section.indentation();
+ indentRight -= section.indentationRight();
+
+ if (pageEvent != null)
+ if (element.type() == Element.CHAPTER)
+ pageEvent.onChapterEnd(writer, this, indentTop() - currentHeight);
+ else
+ pageEvent.onSectionEnd(writer, this, indentTop() - currentHeight);
+
+ break;
+ }
+*/
+ case Element.LIST: {
+ // we cast the element to a List
+ List list = (List) element;
+ // we adjust the document
+ listIndentLeft += list.indentationLeft();
+ indentRight += list.indentationRight();
+ // we process the items in the list
+ element.process(this);
+ // some parameters are set back to normal again
+ listIndentLeft -= list.indentationLeft();
+ indentRight -= list.indentationRight();
+ break;
+ }
+ case Element.LISTITEM: {
+ // we cast the element to a ListItem
+ ListItem listItem = (ListItem) element;
+
+ float spacingBefore = listItem.spacingBefore();
+ if (spacingBefore != 0) {
+ leading = spacingBefore;
+ carriageReturn();
+ if (!pageEmpty) {
+ /*
+ * Don't add spacing before a paragraph if it's the first
+ * on the page
+ */
+ Chunk space = new Chunk(" ");
+ space.process(this);
+ carriageReturn();
+ }
+ }
+
+ // we adjust the document
+ alignment = listItem.alignment();
+ listIndentLeft += listItem.indentationLeft();
+ indentRight += listItem.indentationRight();
+ leading = listItem.leading();
+ carriageReturn();
+ // we prepare the current line to be able to show us the listsymbol
+ line.setListItem(listItem);
+ // we process the item
+ element.process(this);
+
+ float spacingAfter = listItem.spacingAfter();
+ if (spacingAfter != 0) {
+ leading = spacingAfter;
+ carriageReturn();
+ if (currentHeight + line.height() + leading < indentTop() - indentBottom()) {
+ /*
+ * Only add spacing after a paragraph if the extra
+ * spacing fits on the page.
+ */
+ Chunk space = new Chunk(" ");
+ space.process(this);
+ carriageReturn();
+ }
+ leading = listItem.leading(); // restore original leading
+ }
+
+ // if the last line is justified, it should be aligned to the left
+ // if (line.hasToBeJustified()) {
+ // line.resetAlignment();
+ // }
+ // some parameters are set back to normal again
+ carriageReturn();
+ listIndentLeft -= listItem.indentationLeft();
+ indentRight -= listItem.indentationRight();
+ break;
+ }
+ case Element.RECTANGLE: {
+ Rectangle rectangle = (Rectangle) element;
+ graphics.rectangle(rectangle);
+ pageEmpty = false;
+ break;
+ }
+ /* ssteward: dropped in 1.44
+ case Element.PTABLE: {
+ PdfPTable ptable = (PdfPTable)element;
+ if (ptable.size() <= ptable.getHeaderRows())
+ break; //nothing to do
+
+ // before every table, we add a new line and flush all lines
+ ensureNewLine();
+ flushLines();
+ addPTable(ptable);
+ pageEmpty = false;
+ break;
+ }
+ case Element.MULTI_COLUMN_TEXT: {
+ ensureNewLine();
+ flushLines();
+ MultiColumnText multiText = (MultiColumnText) element;
+ float height = multiText.write(writer.getDirectContent(), this, indentTop() - currentHeight);
+ currentHeight += height;
+ text.moveText(0, -1f* height);
+ pageEmpty = false;
+ break;
+ }
+ case Element.TABLE : {
+
+ *//*
+ * This is a list of people who worked on the Table functionality.
+ * To see who did what, please check the CVS repository:
+ *
+ * Leslie Baski
+ * Matt Benson
+ * Francesco De Milato
+ * David Freels
+ * Bruno Lowagie
+ * Veerendra Namineni
+ * Geert Poels
+ * Tom Ring
+ * Paulo Soares
+ * Gerald Fehringer
+ * Steve Appling
+ *//*
+
+ PdfTable table;
+ if (element instanceof PdfTable) {
+ // Already pre-rendered
+ table = (PdfTable)element;
+ table.updateRowAdditions();
+ } else if (element instanceof SimpleTable) {
+ PdfPTable ptable = ((SimpleTable)element).createPdfPTable();
+ if (ptable.size() <= ptable.getHeaderRows())
+ break; //nothing to do
+
+ // before every table, we add a new line and flush all lines
+ ensureNewLine();
+ flushLines();
+ addPTable(ptable);
+ pageEmpty = false;
+ break;
+ } else if (element instanceof Table) {
+
+ try {
+ PdfPTable ptable = ((Table)element).createPdfPTable();
+ if (ptable.size() <= ptable.getHeaderRows())
+ break; //nothing to do
+
+ // before every table, we add a new line and flush all lines
+ ensureNewLine();
+ flushLines();
+ addPTable(ptable);
+ pageEmpty = false;
+ break;
+ }
+ catch(BadElementException bee) {
+ // constructing the PdfTable
+ // Before the table, add a blank line using offset or default leading
+ float offset = ((Table)element).getOffset();
+ if (Float.isNaN(offset))
+ offset = leading;
+ carriageReturn();
+ lines.add(new PdfLine(indentLeft(), indentRight(), alignment, offset));
+ currentHeight += offset;
+ table = getPdfTable((Table)element, false);
+ }
+ } else {
+ return false;
+ }
+ add(table, false);
+ break;
+ }
+ case Element.JPEG:
+ case Element.IMGRAW:
+ case Element.IMGTEMPLATE: {
+ //carriageReturn(); suggestion by Marc Campforts
+ add((Image) element);
+ break;
+ }
+ case Element.GRAPHIC: {
+ Graphic graphic = (Graphic) element;
+ graphic.processAttributes(indentLeft(), indentBottom(), indentRight(), indentTop(), indentTop() - currentHeight);
+ graphics.add(graphic);
+ pageEmpty = false;
+ break;
+ }
+ */
+ default:
+ return false;
+ }
+ lastElementType = element.type();
+ return true;
+ }
+ catch(Exception e) {
+ throw new DocumentException(e);
+ }
+ }
+
+ // methods to add Content
+
+ /**
+ * Adds an image to the document.
+ * @param image the Image
to add
+ * @throws PdfException on error
+ * @throws DocumentException on error
+ */
+ /* ssteward: dropped in 1.44
+ private void add(Image image) throws PdfException, DocumentException {
+
+ if (image.hasAbsolutePosition()) {
+ graphics.addImage(image);
+ pageEmpty = false;
+ return;
+ }
+
+ // if there isn't enough room for the image on this page, save it for the next page
+ if (currentHeight != 0 && indentTop() - currentHeight - image.scaledHeight() < indentBottom()) {
+ if (!strictImageSequence && imageWait == null) {
+ imageWait = image;
+ return;
+ }
+ newPage();
+ if (currentHeight != 0 && indentTop() - currentHeight - image.scaledHeight() < indentBottom()) {
+ imageWait = image;
+ return;
+ }
+ }
+ pageEmpty = false;
+ // avoid endless loops
+ if (image == imageWait)
+ imageWait = null;
+ boolean textwrap = (image.alignment() & Image.TEXTWRAP) == Image.TEXTWRAP
+ && !((image.alignment() & Image.MIDDLE) == Image.MIDDLE);
+ boolean underlying = (image.alignment() & Image.UNDERLYING) == Image.UNDERLYING;
+ float diff = leading / 2;
+ if (textwrap) {
+ diff += leading;
+ }
+ float lowerleft = indentTop() - currentHeight - image.scaledHeight() -diff;
+ float mt[] = image.matrix();
+ float startPosition = indentLeft() - mt[4];
+ if ((image.alignment() & Image.RIGHT) == Image.RIGHT) startPosition = indentRight() - image.scaledWidth() - mt[4];
+ if ((image.alignment() & Image.MIDDLE) == Image.MIDDLE) startPosition = indentLeft() + ((indentRight() - indentLeft() - image.scaledWidth()) / 2) - mt[4];
+ if (image.hasAbsoluteX()) startPosition = image.absoluteX();
+ graphics.addImage(image, mt[0], mt[1], mt[2], mt[3], startPosition, lowerleft - mt[5]);
+ if (textwrap) {
+ if (imageEnd < 0 || imageEnd < currentHeight + image.scaledHeight() + diff) {
+ imageEnd = currentHeight + image.scaledHeight() + diff;
+ }
+ if ((image.alignment() & Image.RIGHT) == Image.RIGHT) {
+ // indentation suggested by Pelikan Stephan
+ imageIndentRight += image.scaledWidth() + image.indentationLeft();
+ }
+ else {
+ // indentation suggested by Pelikan Stephan
+ imageIndentLeft += image.scaledWidth() + image.indentationRight();
+ }
+ }
+ if (!(textwrap || underlying)) {
+ currentHeight += image.scaledHeight() + diff;
+ flushLines();
+ text.moveText(0, - (image.scaledHeight() + diff));
+ newLine();
+ }
+ }
+ */
+
+ /**
+ * Initializes a page.
+ *
+ * If the footer/header is set, it is printed.
+ * @throws DocumentException on error
+ */
+
+ private void initPage() throws DocumentException {
+
+ // initialisation of some page objects
+ markPoint = 0;
+ annotations = delayedAnnotations;
+ delayedAnnotations = new ArrayList();
+ pageResources = new PageResources();
+ writer.resetContent();
+
+ // the pagenumber is incremented
+ pageN++;
+
+ // graphics and text are initialized
+ float oldleading = leading;
+ int oldAlignment = alignment;
+
+ if (marginMirroring && (getPageNumber() & 1) == 0) {
+ marginRight = nextMarginLeft;
+ marginLeft = nextMarginRight;
+ }
+ else {
+ marginLeft = nextMarginLeft;
+ marginRight = nextMarginRight;
+ }
+ marginTop = nextMarginTop;
+ marginBottom = nextMarginBottom;
+ imageEnd = -1;
+ imageIndentRight = 0;
+ imageIndentLeft = 0;
+ graphics = new PdfContentByte(writer);
+ text = new PdfContentByte(writer);
+ text.beginText();
+ text.moveText(left(), top());
+ textEmptySize = text.size();
+ text.reset();
+ text.beginText();
+ leading = 16;
+ indentBottom = 0;
+ indentTop = 0;
+ currentHeight = 0;
+
+ // backgroundcolors, etc...
+ pageSize = nextPageSize;
+ thisBoxSize = new HashMap(boxSize);
+ if (pageSize.backgroundColor() != null
+ || pageSize.hasBorders()
+ || pageSize.borderColor() != null
+ || pageSize.grayFill() > 0) {
+ add(pageSize);
+ }
+
+ // if there is a watermark, the watermark is added
+ /*
+ if (watermark != null) {
+ float mt[] = watermark.matrix();
+ graphics.addImage(watermark, mt[0], mt[1], mt[2], mt[3], watermark.offsetX() - mt[4], watermark.offsetY() - mt[5]);
+ }
+ */
+
+ // if there is a footer, the footer is added
+ /* ssteward: dropped in 1.44
+ if (footer != null) {
+ // Avoid footer identation
+ float tmpIndentLeft = indentLeft;
+ float tmpIndentRight = indentRight;
+ // Begin added: Bonf (Marc Schneider) 2003-07-29
+ float tmpListIndentLeft = listIndentLeft;
+ float tmpImageIndentLeft = imageIndentLeft;
+ float tmpImageIndentRight = imageIndentRight;
+ // End added: Bonf (Marc Schneider) 2003-07-29
+
+ indentLeft = indentRight = 0;
+ // Begin added: Bonf (Marc Schneider) 2003-07-29
+ listIndentLeft = 0;
+ imageIndentLeft = 0;
+ imageIndentRight = 0;
+ // End added: Bonf (Marc Schneider) 2003-07-29
+
+ footer.setPageNumber(pageN);
+ leading = footer.paragraph().leading();
+ add(footer.paragraph());
+ // adding the footer limits the height
+ indentBottom = currentHeight;
+ text.moveText(left(), indentBottom());
+ flushLines();
+ text.moveText(-left(), -bottom());
+ footer.setTop(bottom(currentHeight));
+ footer.setBottom(bottom() - (0.75f * leading));
+ footer.setLeft(left());
+ footer.setRight(right());
+ graphics.rectangle(footer);
+ indentBottom = currentHeight + leading * 2;
+ currentHeight = 0;
+
+ indentLeft = tmpIndentLeft;
+ indentRight = tmpIndentRight;
+ // Begin added: Bonf (Marc Schneider) 2003-07-29
+ listIndentLeft = tmpListIndentLeft;
+ imageIndentLeft = tmpImageIndentLeft;
+ imageIndentRight = tmpImageIndentRight;
+ // End added: Bonf (Marc Schneider) 2003-07-29
+ }
+ */
+
+ // we move to the left/top position of the page
+ text.moveText(left(), top());
+
+ /* ssteward: dropped in 1.44
+ // if there is a header, the header = added
+ if (header != null) {
+ // Avoid header identation
+ float tmpIndentLeft = indentLeft;
+ float tmpIndentRight = indentRight;
+ // Begin added: Bonf (Marc Schneider) 2003-07-29
+ float tmpListIndentLeft = listIndentLeft;
+ float tmpImageIndentLeft = imageIndentLeft;
+ float tmpImageIndentRight = imageIndentRight;
+ // End added: Bonf (Marc Schneider) 2003-07-29
+
+ indentLeft = indentRight = 0;
+ // Added: Bonf
+ listIndentLeft = 0;
+ imageIndentLeft = 0;
+ imageIndentRight = 0;
+ // End added: Bonf
+
+ header.setPageNumber(pageN);
+ leading = header.paragraph().leading();
+ text.moveText(0, leading);
+ add(header.paragraph());
+ newLine();
+ indentTop = currentHeight - leading;
+ header.setTop(top() + leading);
+ header.setBottom(indentTop() + leading * 2 / 3);
+ header.setLeft(left());
+ header.setRight(right());
+ graphics.rectangle(header);
+ flushLines();
+ currentHeight = 0;
+
+ // Restore identation
+ indentLeft = tmpIndentLeft;
+ indentRight = tmpIndentRight;
+ // Begin added: Bonf (Marc Schneider) 2003-07-29
+ listIndentLeft = tmpListIndentLeft;
+ imageIndentLeft = tmpImageIndentLeft;
+ imageIndentRight = tmpImageIndentRight;
+ // End added: Bonf (Marc Schneider) 2003-07-29
+ }
+ */
+
+ pageEmpty = true;
+
+ // if there is an image waiting to be drawn, draw it
+ /* ssteward: dropped in 1.44
+ try {
+ if (imageWait != null) {
+ add(imageWait);
+ imageWait = null;
+ }
+ }
+ catch(Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ */
+
+ leading = oldleading;
+ alignment = oldAlignment;
+ carriageReturn();
+ PdfPageEvent pageEvent = writer.getPageEvent();
+ if (pageEvent != null) {
+ if (firstPageEvent) {
+ pageEvent.onOpenDocument(writer, this);
+ }
+ pageEvent.onStartPage(writer, this);
+ }
+ firstPageEvent = false;
+ }
+
+ /**
+ * If the current line is not empty or null, it is added to the arraylist
+ * of lines and a new empty line is added.
+ * @throws DocumentException on error
+ */
+ private void carriageReturn() throws DocumentException {
+ // the arraylist with lines may not be null
+ if (lines == null) {
+ lines = new ArrayList();
+ }
+ // If the current line is not null
+ if (line != null) {
+ // we check if the end of the page is reached (bugfix by Francois Gravel)
+ if (currentHeight + line.height() + leading < indentTop() - indentBottom()) {
+ // if so nonempty lines are added and the heigt is augmented
+ if (line.size() > 0) {
+ currentHeight += line.height();
+ lines.add(line);
+ pageEmpty = false;
+ }
+ }
+ // if the end of the line is reached, we start a new page
+ else {
+ newPage();
+ }
+ }
+ if (imageEnd > -1 && currentHeight > imageEnd) {
+ imageEnd = -1;
+ imageIndentRight = 0;
+ imageIndentLeft = 0;
+ }
+ // a new current line is constructed
+ line = new PdfLine(indentLeft(), indentRight(), alignment, leading);
+ }
+
+ /**
+ * Adds the current line to the list of lines and also adds an empty line.
+ * @throws DocumentException on error
+ */
+ private void newLine() throws DocumentException {
+ lastElementType = -1;
+ carriageReturn();
+ if (lines != null && lines.size() > 0) {
+ lines.add(line);
+ currentHeight += line.height();
+ }
+ line = new PdfLine(indentLeft(), indentRight(), alignment, leading);
+ }
+
+ /**
+ * Writes all the lines to the text-object.
+ *
+ * @return the displacement that was caused
+ * @throws DocumentException on error
+ */
+ private float flushLines() throws DocumentException {
+
+ // checks if the ArrayList with the lines is not null
+ if (lines == null) {
+ return 0;
+ }
+
+ //add by Jin-Hsia Yang
+ boolean newline=false;
+ //end add by Jin-Hsia Yang
+
+ // checks if a new Line has to be made.
+ if (line != null && line.size() > 0) {
+ lines.add(line);
+ line = new PdfLine(indentLeft(), indentRight(), alignment, leading);
+
+ //add by Jin-Hsia Yang
+ newline=true;
+ //end add by Jin-Hsia Yang
+
+ }
+
+ // checks if the ArrayList with the lines is empty
+ if (lines.size() == 0) {
+ return 0;
+ }
+
+ // initialisation of some parameters
+ Object currentValues[] = new Object[2];
+ PdfFont currentFont = null;
+ float displacement = 0;
+ PdfLine l;
+ PdfChunk chunk;
+ Float lastBaseFactor = new Float(0);
+ currentValues[1] = lastBaseFactor;
+ // looping over all the lines
+ for (Iterator i = lines.iterator(); i.hasNext(); ) {
+
+ // this is a line in the loop
+ l = (PdfLine) i.next();
+
+ if(isNewpage && newline) { // fix Ken@PDI
+ newline=false;
+ text.moveText(l.indentLeft() - indentLeft() + listIndentLeft + paraIndent,-l.height());
+ }
+ else {
+ text.moveText(l.indentLeft() - indentLeft() + listIndentLeft, -l.height());
+ }
+
+ // is the line preceeded by a symbol?
+ if (l.listSymbol() != null) {
+ chunk = l.listSymbol();
+ text.moveText(- l.listIndent(), 0);
+ if (chunk.font().compareTo(currentFont) != 0) {
+ currentFont = chunk.font();
+ text.setFontAndSize(currentFont.getFont(), currentFont.size());
+ }
+ if (chunk.color() != null) {
+ Color color = chunk.color();
+ text.setColorFill(color);
+ text.showText(chunk.toString());
+ text.resetRGBColorFill();
+ }
+ /* ssteward: dropped in 1.44
+ else if (chunk.isImage()) {
+ Image image = chunk.getImage();
+ float matrix[] = image.matrix();
+ float xMarker = text.getXTLM();
+ float yMarker = text.getYTLM();
+ matrix[Image.CX] = xMarker + chunk.getImageOffsetX() - matrix[Image.CX];
+ matrix[Image.CY] = yMarker + chunk.getImageOffsetY() - matrix[Image.CY];
+ graphics.addImage(image, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+ }
+ */
+ else {
+ text.showText(chunk.toString());
+ }
+ text.moveText(l.listIndent(), 0);
+ }
+
+ currentValues[0] = currentFont;
+
+ writeLineToContent(l, text, graphics, currentValues, writer.getSpaceCharRatio());
+
+ currentFont = (PdfFont)currentValues[0];
+
+ displacement += l.height();
+ if (indentLeft() - listIndentLeft != l.indentLeft()) {
+ text.moveText(indentLeft() - l.indentLeft() - listIndentLeft, 0);
+ }
+
+ }
+ lines = new ArrayList();
+ return displacement;
+ }
+
+ // methods to retrieve information
+
+ /**
+ * Gets the PdfInfo
-object.
+ *
+ * @return PdfInfo
+ */
+
+ PdfInfo getInfo() {
+ return info;
+ }
+
+ /**
+ * Gets the PdfCatalog
-object.
+ *
+ * @param pages an indirect reference to this document pages
+ * @return PdfCatalog
+ */
+
+ PdfCatalog getCatalog(PdfIndirectReference pages) {
+ PdfCatalog catalog;
+ if (rootOutline.getKids().size() > 0) {
+ catalog = new PdfCatalog(pages, rootOutline.indirectReference(), writer);
+ }
+ else
+ catalog = new PdfCatalog(pages, writer);
+ if (openActionName != null) {
+ PdfAction action = getLocalGotoAction(openActionName);
+ catalog.setOpenAction(action);
+ }
+ else if (openActionAction != null)
+ catalog.setOpenAction(openActionAction);
+
+ if (additionalActions != null) {
+ catalog.setAdditionalActions(additionalActions);
+ }
+
+ if (pageLabels != null)
+ catalog.setPageLabels(pageLabels);
+ catalog.addNames(localDestinations, documentJavaScript, writer);
+ // ssteward: debug; catalog.setViewerPreferences(viewerPreferences);
+ if (acroForm.isValid()) {
+ try {
+ catalog.setAcroForm(writer.addToBody(acroForm).getIndirectReference());
+ }
+ catch (IOException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+ return catalog;
+ }
+
+ // methods concerning the layout
+
+ /**
+ * Returns the bottomvalue of a Table
if it were added to this document.
+ *
+ * @param table the table that may or may not be added to this document
+ * @return a bottom value
+ */
+ /* ssteward: dropped in 1.44
+ float bottom(Table table) {
+ // where will the table begin?
+ float h = (currentHeight > 0) ? indentTop() - currentHeight - 2f * leading : indentTop();
+ // constructing a PdfTable
+ PdfTable tmp = getPdfTable(table, false);
+ return tmp.bottom();
+ }
+ */
+
+ /**
+ * Checks if a PdfPTable
fits the current page of the PdfDocument
.
+ *
+ * @param table the table that has to be checked
+ * @param margin a certain margin
+ * @return true
if the PdfPTable
fits the page, false
otherwise.
+ */
+ /* ssteward: dropped in 1.44
+ boolean fitsPage(PdfPTable table, float margin) {
+ if (!table.isLockedWidth()) {
+ float totalWidth = (indentRight() - indentLeft()) * table.getWidthPercentage() / 100;
+ table.setTotalWidth(totalWidth);
+ }
+ // ensuring that a new line has been started.
+ ensureNewLine();
+ return table.getTotalHeight() <= indentTop() - currentHeight - indentBottom() - margin;
+ }
+ */
+
+
+ /**
+ * Gets the current vertical page position.
+ * @param ensureNewLine Tells whether a new line shall be enforced. This may cause side effects
+ * for elements that do not terminate the lines they've started because those lines will get
+ * terminated.
+ * @return The current vertical page position.
+ */
+ public float getVerticalPosition(boolean ensureNewLine) {
+ // ensuring that a new line has been started.
+ if (ensureNewLine) {
+ ensureNewLine();
+ }
+ return top() - currentHeight - indentTop;
+ }
+
+ /**
+ * Ensures that a new line has been started.
+ */
+ private void ensureNewLine() {
+ try {
+ if ((lastElementType == Element.PHRASE) ||
+ (lastElementType == Element.CHUNK)) {
+ newLine();
+ flushLines();
+ }
+ } catch (DocumentException ex) {
+ throw new ExceptionConverter(ex);
+ }
+ }
+
+ /**
+ * Gets the indentation on the left side.
+ *
+ * @return a margin
+ */
+
+ private float indentLeft() {
+ return left(indentLeft + listIndentLeft + imageIndentLeft);
+ }
+
+ /**
+ * Gets the indentation on the right side.
+ *
+ * @return a margin
+ */
+
+ private float indentRight() {
+ return right(indentRight + imageIndentRight);
+ }
+
+ /**
+ * Gets the indentation on the top side.
+ *
+ * @return a margin
+ */
+
+ private float indentTop() {
+ return top(indentTop);
+ }
+
+ /**
+ * Gets the indentation on the bottom side.
+ *
+ * @return a margin
+ */
+
+ float indentBottom() {
+ return bottom(indentBottom);
+ }
+
+ /**
+ * Adds a named outline to the document .
+ * @param outline the outline to be added
+ * @param name the name of this local destination
+ */
+ void addOutline(PdfOutline outline, String name) {
+ localDestination(name, outline.getPdfDestination());
+ }
+
+ /**
+ * Gets the AcroForm object.
+ * @return the PdfAcroform object of the PdfDocument
+ */
+
+ public PdfAcroForm getAcroForm() {
+ return acroForm;
+ }
+
+ /**
+ * Gets the root outline. All the outlines must be created with a parent.
+ * The first level is created with this outline.
+ * @return the root outline
+ */
+ public PdfOutline getRootOutline() {
+ return rootOutline;
+ }
+
+ /**
+ * Writes a text line to the document. It takes care of all the attributes.
+ *
+ * Before entering the line position must have been established and the
+ * text
argument must be in text object scope (beginText()
).
+ * @param line the line to be written
+ * @param text the PdfContentByte
where the text will be written to
+ * @param graphics the PdfContentByte
where the graphics will be written to
+ * @param currentValues the current font and extra spacing values
+ * @param ratio
+ * @throws DocumentException on error
+ */
+ void writeLineToContent(PdfLine line, PdfContentByte text, PdfContentByte graphics, Object currentValues[], float ratio) throws DocumentException {
+ PdfFont currentFont = (PdfFont)(currentValues[0]);
+ float lastBaseFactor = ((Float)(currentValues[1])).floatValue();
+ PdfChunk chunk;
+ int numberOfSpaces;
+ int lineLen;
+ boolean isJustified;
+ float hangingCorrection = 0;
+ float hScale = 1;
+ float lastHScale = Float.NaN;
+ float baseWordSpacing = 0;
+ float baseCharacterSpacing = 0;
+
+ numberOfSpaces = line.numberOfSpaces();
+ lineLen = line.toString().length();
+ // does the line need to be justified?
+ isJustified = line.hasToBeJustified() && (numberOfSpaces != 0 || lineLen > 1);
+ if (isJustified) {
+ if (line.isNewlineSplit() && line.widthLeft() >= (lastBaseFactor * (ratio * numberOfSpaces + lineLen - 1))) {
+ if (line.isRTL()) {
+ text.moveText(line.widthLeft() - lastBaseFactor * (ratio * numberOfSpaces + lineLen - 1), 0);
+ }
+ baseWordSpacing = ratio * lastBaseFactor;
+ baseCharacterSpacing = lastBaseFactor;
+ }
+ else {
+ float width = line.widthLeft();
+ PdfChunk last = line.getChunk(line.size() - 1);
+ if (last != null) {
+ String s = last.toString();
+ char c;
+ if (s.length() > 0 && hangingPunctuation.indexOf((c = s.charAt(s.length() - 1))) >= 0) {
+ float oldWidth = width;
+ width += last.font().width(c) * 0.4f;
+ hangingCorrection = width - oldWidth;
+ }
+ }
+ float baseFactor = width / (ratio * numberOfSpaces + lineLen - 1);
+ baseWordSpacing = ratio * baseFactor;
+ baseCharacterSpacing = baseFactor;
+ lastBaseFactor = baseFactor;
+ }
+ }
+
+ int lastChunkStroke = line.getLastStrokeChunk();
+ int chunkStrokeIdx = 0;
+ float xMarker = text.getXTLM();
+ float baseXMarker = xMarker;
+ float yMarker = text.getYTLM();
+ boolean adjustMatrix = false;
+
+ // looping over all the chunks in 1 line
+ for (Iterator j = line.iterator(); j.hasNext(); ) {
+ chunk = (PdfChunk) j.next();
+ Color color = chunk.color();
+ hScale = 1;
+
+ if (chunkStrokeIdx <= lastChunkStroke) {
+ float width;
+ if (isJustified) {
+ width = chunk.getWidthCorrected(baseCharacterSpacing, baseWordSpacing);
+ }
+ else
+ width = chunk.width();
+ if (chunk.isStroked()) {
+ PdfChunk nextChunk = line.getChunk(chunkStrokeIdx + 1);
+ if (chunk.isAttribute(Chunk.BACKGROUND)) {
+ float subtract = lastBaseFactor;
+ if (nextChunk != null && nextChunk.isAttribute(Chunk.BACKGROUND))
+ subtract = 0;
+ if (nextChunk == null)
+ subtract += hangingCorrection;
+ float fontSize = chunk.font().size();
+ float ascender = chunk.font().getFont().getFontDescriptor(BaseFont.ASCENT, fontSize);
+ float descender = chunk.font().getFont().getFontDescriptor(BaseFont.DESCENT, fontSize);
+ Object bgr[] = (Object[])chunk.getAttribute(Chunk.BACKGROUND);
+ graphics.setColorFill((Color)bgr[0]);
+ float extra[] = (float[])bgr[1];
+ graphics.rectangle(xMarker - extra[0],
+ yMarker + descender - extra[1] + chunk.getTextRise(),
+ width - subtract + extra[0] + extra[2],
+ ascender - descender + extra[1] + extra[3]);
+ graphics.fill();
+ graphics.setGrayFill(0);
+ }
+ if (chunk.isAttribute(Chunk.UNDERLINE)) {
+ float subtract = lastBaseFactor;
+ if (nextChunk != null && nextChunk.isAttribute(Chunk.UNDERLINE))
+ subtract = 0;
+ if (nextChunk == null)
+ subtract += hangingCorrection;
+ Object unders[][] = (Object[][])chunk.getAttribute(Chunk.UNDERLINE);
+ Color scolor = null;
+ for (int k = 0; k < unders.length; ++k) {
+ Object obj[] = unders[k];
+ scolor = (Color)obj[0];
+ float ps[] = (float[])obj[1];
+ if (scolor == null)
+ scolor = color;
+ if (scolor != null)
+ graphics.setColorStroke(scolor);
+ float fsize = chunk.font().size();
+ graphics.setLineWidth(ps[0] + fsize * ps[1]);
+ float shift = ps[2] + fsize * ps[3];
+ int cap2 = (int)ps[4];
+ if (cap2 != 0)
+ graphics.setLineCap(cap2);
+ graphics.moveTo(xMarker, yMarker + shift);
+ graphics.lineTo(xMarker + width - subtract, yMarker + shift);
+ graphics.stroke();
+ if (scolor != null)
+ graphics.resetGrayStroke();
+ if (cap2 != 0)
+ graphics.setLineCap(0);
+ }
+ graphics.setLineWidth(1);
+ }
+ if (chunk.isAttribute(Chunk.ACTION)) {
+ float subtract = lastBaseFactor;
+ if (nextChunk != null && nextChunk.isAttribute(Chunk.ACTION))
+ subtract = 0;
+ if (nextChunk == null)
+ subtract += hangingCorrection;
+ text.addAnnotation(new PdfAnnotation(writer, xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size(), (PdfAction)chunk.getAttribute(Chunk.ACTION)));
+ }
+ if (chunk.isAttribute(Chunk.REMOTEGOTO)) {
+ float subtract = lastBaseFactor;
+ if (nextChunk != null && nextChunk.isAttribute(Chunk.REMOTEGOTO))
+ subtract = 0;
+ if (nextChunk == null)
+ subtract += hangingCorrection;
+ Object obj[] = (Object[])chunk.getAttribute(Chunk.REMOTEGOTO);
+ String filename = (String)obj[0];
+ if (obj[1] instanceof String)
+ remoteGoto(filename, (String)obj[1], xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size());
+ else
+ remoteGoto(filename, ((Integer)obj[1]).intValue(), xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size());
+ }
+ if (chunk.isAttribute(Chunk.LOCALGOTO)) {
+ float subtract = lastBaseFactor;
+ if (nextChunk != null && nextChunk.isAttribute(Chunk.LOCALGOTO))
+ subtract = 0;
+ if (nextChunk == null)
+ subtract += hangingCorrection;
+ localGoto((String)chunk.getAttribute(Chunk.LOCALGOTO), xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size());
+ }
+ if (chunk.isAttribute(Chunk.LOCALDESTINATION)) {
+ float subtract = lastBaseFactor;
+ if (nextChunk != null && nextChunk.isAttribute(Chunk.LOCALDESTINATION))
+ subtract = 0;
+ if (nextChunk == null)
+ subtract += hangingCorrection;
+ localDestination((String)chunk.getAttribute(Chunk.LOCALDESTINATION), new PdfDestination(PdfDestination.XYZ, xMarker, yMarker + chunk.font().size(), 0));
+ }
+ if (chunk.isAttribute(Chunk.GENERICTAG)) {
+ float subtract = lastBaseFactor;
+ if (nextChunk != null && nextChunk.isAttribute(Chunk.GENERICTAG))
+ subtract = 0;
+ if (nextChunk == null)
+ subtract += hangingCorrection;
+ Rectangle rect = new Rectangle(xMarker, yMarker, xMarker + width - subtract, yMarker + chunk.font().size());
+ PdfPageEvent pev = writer.getPageEvent();
+ if (pev != null)
+ pev.onGenericTag(writer, this, rect, (String)chunk.getAttribute(Chunk.GENERICTAG));
+ }
+ if (chunk.isAttribute(Chunk.PDFANNOTATION)) {
+ float subtract = lastBaseFactor;
+ if (nextChunk != null && nextChunk.isAttribute(Chunk.PDFANNOTATION))
+ subtract = 0;
+ if (nextChunk == null)
+ subtract += hangingCorrection;
+ float fontSize = chunk.font().size();
+ float ascender = chunk.font().getFont().getFontDescriptor(BaseFont.ASCENT, fontSize);
+ float descender = chunk.font().getFont().getFontDescriptor(BaseFont.DESCENT, fontSize);
+ PdfAnnotation annot = PdfFormField.shallowDuplicate((PdfAnnotation)chunk.getAttribute(Chunk.PDFANNOTATION));
+ annot.put(PdfName.RECT, new PdfRectangle(xMarker, yMarker + descender, xMarker + width - subtract, yMarker + ascender));
+ text.addAnnotation(annot);
+ }
+ float params[] = (float[])chunk.getAttribute(Chunk.SKEW);
+ Float hs = (Float)chunk.getAttribute(Chunk.HSCALE);
+ if (params != null || hs != null) {
+ float b = 0, c = 0;
+ if (params != null) {
+ b = params[0];
+ c = params[1];
+ }
+ if (hs != null)
+ hScale = hs.floatValue();
+ text.setTextMatrix(hScale, b, c, 1, xMarker, yMarker);
+ }
+ /* ssteward: dropped in 1.44
+ if (chunk.isImage()) {
+ Image image = chunk.getImage();
+ float matrix[] = image.matrix();
+ matrix[Image.CX] = xMarker + chunk.getImageOffsetX() - matrix[Image.CX];
+ matrix[Image.CY] = yMarker + chunk.getImageOffsetY() - matrix[Image.CY];
+ graphics.addImage(image, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+ text.moveText(xMarker + lastBaseFactor + image.scaledWidth() - text.getXTLM(), 0);
+ }
+ */
+ }
+ xMarker += width;
+ ++chunkStrokeIdx;
+ }
+
+ if (chunk.font().compareTo(currentFont) != 0) {
+ currentFont = chunk.font();
+ text.setFontAndSize(currentFont.getFont(), currentFont.size());
+ }
+ float rise = 0;
+ Object textRender[] = (Object[])chunk.getAttribute(Chunk.TEXTRENDERMODE);
+ int tr = 0;
+ float strokeWidth = 1;
+ Color strokeColor = null;
+ Float fr = (Float)chunk.getAttribute(Chunk.SUBSUPSCRIPT);
+ if (textRender != null) {
+ tr = ((Integer)textRender[0]).intValue() & 3;
+ if (tr != PdfContentByte.TEXT_RENDER_MODE_FILL)
+ text.setTextRenderingMode(tr);
+ if (tr == PdfContentByte.TEXT_RENDER_MODE_STROKE || tr == PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE) {
+ strokeWidth = ((Float)textRender[1]).floatValue();
+ if (strokeWidth != 1)
+ text.setLineWidth(strokeWidth);
+ strokeColor = (Color)textRender[2];
+ if (strokeColor == null)
+ strokeColor = color;
+ if (strokeColor != null)
+ text.setColorStroke(strokeColor);
+ }
+ }
+ if (fr != null)
+ rise = fr.floatValue();
+ if (color != null)
+ text.setColorFill(color);
+ if (rise != 0)
+ text.setTextRise(rise);
+ /* ssteward: dropped in 1.44
+ if (chunk.isImage()) {
+ adjustMatrix = true;
+ }
+ */
+ // If it is a CJK chunk or Unicode TTF we will have to simulate the
+ // space adjustment.
+ else if (isJustified && numberOfSpaces > 0 && chunk.isSpecialEncoding()) {
+ if (hScale != lastHScale) {
+ lastHScale = hScale;
+ text.setWordSpacing(baseWordSpacing / hScale);
+ text.setCharacterSpacing(baseCharacterSpacing / hScale);
+ }
+ String s = chunk.toString();
+ int idx = s.indexOf(' ');
+ if (idx < 0)
+ text.showText(chunk.toString());
+ else {
+ float spaceCorrection = - baseWordSpacing * 1000f / chunk.font.size() / hScale;
+ PdfTextArray textArray = new PdfTextArray(s.substring(0, idx));
+ int lastIdx = idx;
+ while ((idx = s.indexOf(' ', lastIdx + 1)) >= 0) {
+ textArray.add(spaceCorrection);
+ textArray.add(s.substring(lastIdx, idx));
+ lastIdx = idx;
+ }
+ textArray.add(spaceCorrection);
+ textArray.add(s.substring(lastIdx));
+ text.showText(textArray);
+ }
+ }
+ else {
+ if (isJustified && hScale != lastHScale) {
+ lastHScale = hScale;
+ text.setWordSpacing(baseWordSpacing / hScale);
+ text.setCharacterSpacing(baseCharacterSpacing / hScale);
+ }
+ text.showText(chunk.toString());
+ }
+
+ if (rise != 0)
+ text.setTextRise(0);
+ if (color != null)
+ text.resetRGBColorFill();
+ if (tr != PdfContentByte.TEXT_RENDER_MODE_FILL)
+ text.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL);
+ if (strokeColor != null)
+ text.resetRGBColorStroke();
+ if (strokeWidth != 1)
+ text.setLineWidth(1);
+ if (chunk.isAttribute(Chunk.SKEW) || chunk.isAttribute(Chunk.HSCALE)) {
+ adjustMatrix = true;
+ text.setTextMatrix(xMarker, yMarker);
+ }
+ }
+ if (isJustified) {
+ text.setWordSpacing(0);
+ text.setCharacterSpacing(0);
+ if (line.isNewlineSplit())
+ lastBaseFactor = 0;
+ }
+ if (adjustMatrix)
+ text.moveText(baseXMarker - text.getXTLM(), 0);
+ currentValues[0] = currentFont;
+ currentValues[1] = new Float(lastBaseFactor);
+ }
+
+ /**
+ * Implements a link to other part of the document. The jump will
+ * be made to a local destination with the same name, that must exist.
+ * @param name the name for this link
+ * @param llx the lower left x corner of the activation area
+ * @param lly the lower left y corner of the activation area
+ * @param urx the upper right x corner of the activation area
+ * @param ury the upper right y corner of the activation area
+ */
+ void localGoto(String name, float llx, float lly, float urx, float ury) {
+ PdfAction action = getLocalGotoAction(name);
+ annotations.add(new PdfAnnotation(writer, llx, lly, urx, ury, action));
+ }
+
+ PdfAction getLocalGotoAction(String name) {
+ PdfAction action;
+ Object obj[] = (Object[])localDestinations.get(name);
+ if (obj == null)
+ obj = new Object[3];
+ if (obj[0] == null) {
+ if (obj[1] == null) {
+ obj[1] = writer.getPdfIndirectReference();
+ }
+ action = new PdfAction((PdfIndirectReference)obj[1]);
+ obj[0] = action;
+ localDestinations.put(name, obj);
+ }
+ else {
+ action = (PdfAction)obj[0];
+ }
+ return action;
+ }
+
+ /**
+ * The local destination to where a local goto with the same
+ * name will jump to.
+ * @param name the name of this local destination
+ * @param destination the PdfDestination
with the jump coordinates
+ * @return true
if the local destination was added,
+ * false
if a local destination with the same name
+ * already existed
+ */
+ boolean localDestination(String name, PdfDestination destination) {
+ Object obj[] = (Object[])localDestinations.get(name);
+ if (obj == null)
+ obj = new Object[3];
+ if (obj[2] != null)
+ return false;
+ obj[2] = destination;
+ localDestinations.put(name, obj);
+ destination.addPage(writer.getCurrentPage());
+ return true;
+ }
+
+ /**
+ * Implements a link to another document.
+ * @param filename the filename for the remote document
+ * @param name the name to jump to
+ * @param llx the lower left x corner of the activation area
+ * @param lly the lower left y corner of the activation area
+ * @param urx the upper right x corner of the activation area
+ * @param ury the upper right y corner of the activation area
+ */
+ void remoteGoto(String filename, String name, float llx, float lly, float urx, float ury) {
+ annotations.add(new PdfAnnotation(writer, llx, lly, urx, ury, new PdfAction(filename, name)));
+ }
+
+ /**
+ * Implements a link to another document.
+ * @param filename the filename for the remote document
+ * @param page the page to jump to
+ * @param llx the lower left x corner of the activation area
+ * @param lly the lower left y corner of the activation area
+ * @param urx the upper right x corner of the activation area
+ * @param ury the upper right y corner of the activation area
+ */
+ void remoteGoto(String filename, int page, float llx, float lly, float urx, float ury) {
+ writer.addAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury, new PdfAction(filename, page)));
+ }
+
+ /** Sets the viewer preferences as the sum of several constants.
+ * @param preferences the viewer preferences
+ * @see PdfWriter#setViewerPreferences
+ */
+
+ public void setViewerPreferences(int preferences) {
+ viewerPreferences |= preferences;
+ }
+
+ /** Implements an action in an area.
+ * @param action the PdfAction
+ * @param llx the lower left x corner of the activation area
+ * @param lly the lower left y corner of the activation area
+ * @param urx the upper right x corner of the activation area
+ * @param ury the upper right y corner of the activation area
+ */
+ void setAction(PdfAction action, float llx, float lly, float urx, float ury) {
+ writer.addAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury, action));
+ }
+
+ void setOpenAction(String name) {
+ openActionName = name;
+ openActionAction = null;
+ }
+
+ void setOpenAction(PdfAction action) {
+ openActionAction = action;
+ openActionName = null;
+ }
+
+ void addAdditionalAction(PdfName actionType, PdfAction action) {
+ if (additionalActions == null) {
+ additionalActions = new PdfDictionary();
+ }
+ if (action == null)
+ additionalActions.remove(actionType);
+ else
+ additionalActions.put(actionType, action);
+ if (additionalActions.size() == 0)
+ additionalActions = null;
+ }
+
+ void setPageLabels(PdfPageLabels pageLabels) {
+ this.pageLabels = pageLabels;
+ }
+
+ void addJavaScript(PdfAction js) {
+ if (js.get(PdfName.JS) == null)
+ throw new RuntimeException("Only JavaScript actions are allowed.");
+ try {
+ documentJavaScript.add(writer.addToBody(js).getIndirectReference());
+ }
+ catch (IOException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ void setCropBoxSize(Rectangle crop) {
+ setBoxSize("crop", crop);
+ }
+
+ void setBoxSize(String boxName, Rectangle size) {
+ if (size == null)
+ boxSize.remove(boxName);
+ else
+ boxSize.put(boxName, new PdfRectangle(size));
+ }
+
+ void addCalculationOrder(PdfFormField formField) {
+ acroForm.addCalculationOrder(formField);
+ }
+
+ void setSigFlags(int f) {
+ acroForm.setSigFlags(f);
+ }
+
+ void addFormFieldRaw(PdfFormField field) {
+ annotations.add(field);
+ ArrayList kids = field.getKids();
+ if (kids != null) {
+ for (int k = 0; k < kids.size(); ++k)
+ addFormFieldRaw((PdfFormField)kids.get(k));
+ }
+ }
+
+ void addAnnotation(PdfAnnotation annot) {
+ pageEmpty = false;
+ if (annot.isForm()) {
+ PdfFormField field = (PdfFormField)annot;
+ if (field.getParent() == null)
+ addFormFieldRaw(field);
+ }
+ else
+ annotations.add(annot);
+ }
+
+ /**
+ * Sets the display duration for the page (for presentations)
+ * @param seconds the number of seconds to display the page
+ */
+ void setDuration(int seconds) {
+ if (seconds > 0)
+ this.duration=seconds;
+ else
+ this.duration=-1;
+ }
+
+ /**
+ * Sets the transition for the page
+ * @param transition the PdfTransition object
+ */
+ void setTransition(PdfTransition transition) {
+ this.transition=transition;
+ }
+
+ void setPageAction(PdfName actionType, PdfAction action) {
+ if (pageAA == null) {
+ pageAA = new PdfDictionary();
+ }
+ pageAA.put(actionType, action);
+ }
+
+ /** Getter for property strictImageSequence.
+ * @return Value of property strictImageSequence.
+ *
+ */
+ boolean isStrictImageSequence() {
+ return this.strictImageSequence;
+ }
+
+ /** Setter for property strictImageSequence.
+ * @param strictImageSequence New value of property strictImageSequence.
+ *
+ */
+ void setStrictImageSequence(boolean strictImageSequence) {
+ this.strictImageSequence = strictImageSequence;
+ }
+
+ void setPageEmpty(boolean pageEmpty) {
+ this.pageEmpty = pageEmpty;
+ }
+ /**
+ * Method added by Pelikan Stephan
+ * @see pdftk.com.lowagie.text.DocListener#clearTextWrap()
+ */
+ /* ssteward: dropped in 1.44
+ public void clearTextWrap() throws DocumentException {
+ super.clearTextWrap();
+ float tmpHeight = imageEnd - currentHeight;
+ if (line != null) {
+ tmpHeight += line.height();
+ }
+ if ((imageEnd > -1) && (tmpHeight > 0)) {
+ carriageReturn();
+ currentHeight += tmpHeight;
+ }
+ }
+ */
+
+ ArrayList getDocumentJavaScript() {
+ return documentJavaScript;
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.DocListener#setMarginMirroring(boolean)
+ */
+ public boolean setMarginMirroring(boolean MarginMirroring) {
+ if (writer != null && writer.isPaused()) {
+ return false;
+ }
+ return super.setMarginMirroring(MarginMirroring);
+ }
+ /* ssteward: dropped in 1.44
+ void setThumbnail(Image image) throws PdfException, DocumentException {
+ thumb = writer.getImageReference(writer.addDirectImageSimple(image));
+ }
+ */
+ static PdfAnnotation convertAnnotation(PdfWriter writer, Annotation annot) throws IOException {
+ switch(annot.annotationType()) {
+ case Annotation.URL_NET:
+ return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((URL) annot.attributes().get(Annotation.URL)));
+ case Annotation.URL_AS_STRING:
+ return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.FILE)));
+ case Annotation.FILE_DEST:
+ return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.FILE), (String) annot.attributes().get(Annotation.DESTINATION)));
+ case Annotation.SCREEN:
+ boolean sparams[] = (boolean[])annot.attributes().get(Annotation.PARAMETERS);
+ String fname = (String) annot.attributes().get(Annotation.FILE);
+ String mimetype = (String) annot.attributes().get(Annotation.MIMETYPE);
+ PdfFileSpecification fs;
+ if (sparams[0])
+ fs = PdfFileSpecification.fileEmbedded(writer, fname, fname, null);
+ else
+ fs = PdfFileSpecification.fileExtern(writer, fname);
+ PdfAnnotation ann = PdfAnnotation.createScreen(writer, new Rectangle(annot.llx(), annot.lly(), annot.urx(), annot.ury()),
+ fname, fs, mimetype, sparams[1]);
+ return ann;
+ case Annotation.FILE_PAGE:
+ return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.FILE), ((Integer) annot.attributes().get(Annotation.PAGE)).intValue()));
+ case Annotation.NAMED_DEST:
+ return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction(((Integer) annot.attributes().get(Annotation.NAMED)).intValue()));
+ case Annotation.LAUNCH:
+ return new PdfAnnotation(writer, annot.llx(), annot.lly(), annot.urx(), annot.ury(), new PdfAction((String) annot.attributes().get(Annotation.APPLICATION),(String) annot.attributes().get(Annotation.PARAMETERS),(String) annot.attributes().get(Annotation.OPERATION),(String) annot.attributes().get(Annotation.DEFAULTDIR)));
+ default:
+ PdfDocument doc = writer.getPdfDocument();
+ if (doc.line == null)
+ return null;
+ PdfAnnotation an = new PdfAnnotation(writer, annot.llx(doc.indentRight() - doc.line.widthLeft()), annot.lly(doc.indentTop() - doc.currentHeight), annot.urx(doc.indentRight() - doc.line.widthLeft() + 20), annot.ury(doc.indentTop() - doc.currentHeight - 20), new PdfString(annot.title()), new PdfString(annot.content()));
+ return an;
+ }
+ }
+
+ /**
+ * @return an XmpMetadata byte array
+ */
+ public byte[] createXmpMetadata() {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ XmpWriter xmp = new XmpWriter(baos, getInfo());
+ xmp.close();
+ }
+ catch(IOException ioe) {
+ ioe.printStackTrace();
+ }
+ return baos.toByteArray();
+ }
+
+ int getMarkPoint() {
+ return markPoint;
+ }
+
+ void incMarkPoint() {
+ ++markPoint;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfEncodings.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfEncodings.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfEncodings.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfEncodings.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,738 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import pdftk.com.lowagie.text.ExceptionConverter;
+import java.io.UnsupportedEncodingException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+/** Supports fast encodings for winansi and PDFDocEncoding.
+ * Supports conversions from CJK encodings to CID.
+ * Supports custom encodings.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfEncodings {
+
+ // ssteward
+ //protected static Class c1= gnu.gcj.convert.Input_UnicodeBig.class;
+
+ protected static final int CIDNONE = 0;
+ protected static final int CIDRANGE = 1;
+ protected static final int CIDCHAR = 2;
+
+ static final char winansiByteToChar[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 8364, 65533, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 65533, 381, 65533,
+ 65533, 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250, 339, 65533, 382, 376,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
+
+ static final char pdfEncodingByteToChar[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018,
+ 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 65533,
+ 0x20ac, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
+
+ static final IntHashtable winansi = new IntHashtable();
+
+ static final IntHashtable pdfEncoding = new IntHashtable();
+
+ static final HashMap extraEncodings = new HashMap();
+
+ static {
+ for (int k = 128; k < 160; ++k) {
+ char c = winansiByteToChar[k];
+ if (c != 65533)
+ winansi.put(c, k);
+ }
+
+ for (int k = 128; k < 161; ++k) {
+ char c = pdfEncodingByteToChar[k];
+ if (c != 65533)
+ pdfEncoding.put(c, k);
+ }
+
+ addExtraEncoding("Wingdings", new WingdingsConversion());
+ addExtraEncoding("Symbol", new SymbolConversion(true));
+ addExtraEncoding("ZapfDingbats", new SymbolConversion(false));
+ addExtraEncoding("SymbolTT", new SymbolTTConversion());
+ addExtraEncoding("Cp437", new Cp437Conversion());
+ }
+
+ /** Converts a String
to a
byte
array according
+ * to the font's encoding.
+ * @return an array of byte
representing the conversion according to the font's encoding
+ * @param encoding the encoding fo the return byte array
+ * @param text the String
to be converted
+ */
+ public static final byte[] convertToBytes(String text, String encoding) {
+ if (text == null)
+ return new byte[0];
+ if (encoding == null || encoding.length() == 0) {
+ int len = text.length();
+ byte b[] = new byte[len];
+ for (int k = 0; k < len; ++k) {
+ b[k] = (byte)text.charAt(k);
+ }
+ return b;
+ }
+ ExtraEncoding extra = null;
+ synchronized (extraEncodings) {
+ extra = (ExtraEncoding)extraEncodings.get(encoding.toLowerCase());
+ }
+ if (extra != null) {
+ byte b[] = extra.charToByte(text, encoding);
+ if (b != null)
+ return b;
+ }
+ IntHashtable hash = null;
+ if (encoding.equals(BaseFont.WINANSI))
+ hash = winansi;
+ else if (encoding.equals(PdfObject.TEXT_PDFDOCENCODING))
+ hash = pdfEncoding;
+ if (hash != null) {
+ char cc[] = text.toCharArray();
+ int len = cc.length;
+ int ptr = 0;
+ byte b[] = new byte[len];
+ int c = 0;
+ for (int k = 0; k < len; ++k) {
+ char char1 = cc[k];
+ if (char1 < 128 || (char1 >= 160 && char1 <= 255))
+ c = char1;
+ else
+ c = hash.get(char1);
+ if (c != 0)
+ b[ptr++] = (byte)c;
+ }
+ if (ptr == len)
+ return b;
+ byte b2[] = new byte[ptr];
+ System.arraycopy(b, 0, b2, 0, ptr);
+ return b2;
+ }
+ if (encoding.equals(PdfObject.TEXT_UNICODE)) {
+ // workaround for jdk 1.2.2 bug
+ char cc[] = text.toCharArray();
+ int len = cc.length;
+ byte b[] = new byte[cc.length * 2 + 2];
+ b[0] = -2;
+ b[1] = -1;
+ int bptr = 2;
+ for (int k = 0; k < len; ++k) {
+ char c = cc[k];
+ b[bptr++] = (byte)(c >> 8);
+ b[bptr++] = (byte)(c & 0xff);
+ }
+ return b;
+ }
+ try {
+ return text.getBytes(encoding);
+ }
+ catch (UnsupportedEncodingException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /** Converts a
byte
array to a String
according
+ * to the some encoding.
+ * @param bytes the bytes to convert
+ * @param encoding the encoding of input bytes
+ * @return the converted String
+ */
+ // ssteward: reorganized for 1.45, added TEXT_UNICODE case
+ public static final String convertToString( byte bytes[], String encoding ) {
+
+ String ret_val= PdfObject.NOTHING;
+ char[] ch= null;
+
+ if( bytes!= null ) {
+
+ if( encoding== null || encoding.length()== 0 ) {
+ char cc[]= new char[bytes.length];
+ for( int ii = 0; ii < bytes.length; ++ii ) {
+ cc[ii]= (char)(bytes[ii] & 0xff);
+ }
+ ret_val=new String( cc );
+ }
+ else if( encoding== PdfObject.TEXT_UNICODE ) {
+ // ssteward: we aren't really decoding UTF-16, but simply converting 8-bit splits into UTF-16;
+ // added this in 1.45 because of trouble with String( byte, encoding ) in older gcj (3.4.5)
+
+ int jj= 0;
+ if( bytes.length>= 2 && bytes[0]== (byte)254 && bytes[1]== (byte)255 ) {
+ jj= 2;
+ }
+ int cc_len= (int)Math.floor( (bytes.length- jj)/ 2 );
+ char cc[]= new char[cc_len];
+ for( int ii= 0; ii< cc_len; ++ii, ++jj ) {
+ cc[ii]= (char)( (((int)bytes[ jj] & 0xff) << 8) +
+ ((int)bytes[++jj] & 0xff) );
+ }
+ ret_val= new String( cc );
+ }
+ else if( encoding== PdfObject.TEXT_PDFDOCENCODING && (ch= pdfEncodingByteToChar)!= null ||
+ encoding== BaseFont.WINANSI && (ch= winansiByteToChar)!= null )
+ {
+ char cc[]= new char[bytes.length];
+ for( int ii= 0; ii< bytes.length; ++ii ) {
+ cc[ii]= ch[ bytes[ii] & 0xff ];
+ }
+ ret_val= new String( cc );
+ }
+ else {
+ ExtraEncoding extra= null;
+ synchronized (extraEncodings) {
+ extra = (ExtraEncoding)extraEncodings.get( encoding.toLowerCase() );
+ }
+
+ if( extra!= null ) {
+ String text = extra.byteToChar(bytes, encoding);
+ if (text != null)
+ ret_val= text;
+ }
+ else {
+ try {
+ ret_val= new String( bytes, encoding );
+ }
+ catch( UnsupportedEncodingException e ) {
+ throw new ExceptionConverter( e );
+ }
+ }
+ }
+ }
+
+ return ret_val;
+ }
+
+ /** Checks is text
only has PdfDocEncoding characters.
+ * @param text the String
to test
+ * @return true
if only PdfDocEncoding characters are present
+ */
+ // text is unicode, right?
+ public static boolean isPdfDocEncoding(String text) {
+ if (text == null)
+ return true;
+ int len = text.length();
+ for (int k = 0; k < len; ++k) {
+ char char1 = text.charAt(k);
+ if (char1 < 128 || (char1 >= 160 && char1 <= 255))
+ continue;
+ if (!pdfEncoding.containsKey(char1))
+ return false;
+ }
+ return true;
+ }
+
+ static final HashMap cmaps = new HashMap();
+ /** Assumes that '\\n' and '\\r\\n' are the newline sequences. It may not work for
+ * all CJK encodings. To be used with loadCmap().
+ */
+ public static final byte CRLF_CID_NEWLINE[][] = new byte[][]{{(byte)'\n'}, {(byte)'\r', (byte)'\n'}};
+
+ /** Clears the CJK cmaps from the cache. If name
is the
+ * empty string then all the cache is cleared. Calling this method
+ * has no consequences other than the need to reload the cmap
+ * if needed.
+ * @param name the name of the cmap to clear or all the cmaps if the empty string
+ */
+ public static void clearCmap(String name) {
+ synchronized (cmaps) {
+ if (name.length() == 0)
+ cmaps.clear();
+ else
+ cmaps.remove(name);
+ }
+ }
+
+ /** Loads a CJK cmap to the cache with the option of associating
+ * sequences to the newline.
+ * @param name the CJK cmap name
+ * @param newline the sequences to be replaced bi a newline in the resulting CID. See CRLF_CID_NEWLINE
+ */
+ public static void loadCmap(String name, byte newline[][]) {
+ try {
+ char planes[][] = null;
+ synchronized (cmaps) {
+ planes = (char[][])cmaps.get(name);
+ }
+ if (planes == null) {
+ planes = readCmap(name, (byte[][])newline);
+ synchronized (cmaps) {
+ cmaps.put(name, planes);
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /** Converts a byte
array encoded as name
+ * to a CID string. This is needed to reach some CJK characters
+ * that don't exist in 16 bit Unicode.
+ * The font to use this result must use the encoding "Identity-H"
+ * or "Identity-V".
+ * See ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/.
+ * @param name the CJK encoding name
+ * @param seq the byte
array to be decoded
+ * @return the CID string
+ */
+ public static String convertCmap(String name, byte seq[]) {
+ return convertCmap(name, seq, 0, seq.length);
+ }
+
+ /** Converts a byte
array encoded as name
+ * to a CID string. This is needed to reach some CJK characters
+ * that don't exist in 16 bit Unicode.
+ * The font to use this result must use the encoding "Identity-H"
+ * or "Identity-V".
+ * See ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/.
+ * @param name the CJK encoding name
+ * @param start the start offset in the data
+ * @param length the number of bytes to convert
+ * @param seq the byte
array to be decoded
+ * @return the CID string
+ */
+ public static String convertCmap(String name, byte seq[], int start, int length) {
+ try {
+ char planes[][] = null;
+ synchronized (cmaps) {
+ planes = (char[][])cmaps.get(name);
+ }
+ if (planes == null) {
+ planes = readCmap(name, (byte[][])null);
+ synchronized (cmaps) {
+ cmaps.put(name, planes);
+ }
+ }
+ return decodeSequence(seq, start, length, planes);
+ }
+ catch (IOException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ static String decodeSequence(byte seq[], int start, int length, char planes[][]) {
+ StringBuffer buf = new StringBuffer();
+ int end = start + length;
+ int currentPlane = 0;
+ for (int k = start; k < end; ++k) {
+ int one = (int)seq[k] & 0xff;
+ char plane[] = planes[currentPlane];
+ int cid = plane[one];
+ if ((cid & 0x8000) == 0) {
+ buf.append((char)cid);
+ currentPlane = 0;
+ }
+ else
+ currentPlane = cid & 0x7fff;
+ }
+ return buf.toString();
+ }
+
+ static char[][] readCmap(String name, byte newline[][]) throws IOException {
+ ArrayList planes = new ArrayList();
+ planes.add(new char[256]);
+ readCmap(name, planes);
+ if (newline != null) {
+ for (int k = 0; k < newline.length; ++k)
+ encodeSequence(newline[k].length, newline[k], BaseFont.CID_NEWLINE, planes);
+ }
+ char ret[][] = new char[planes.size()][];
+ return (char[][])planes.toArray(ret);
+ }
+
+ static void readCmap(String name, ArrayList planes) throws IOException {
+ String fullName = BaseFont.RESOURCE_PATH + "cmaps/" + name;
+ InputStream in = BaseFont.getResourceStream(fullName);
+ if (in == null)
+ throw new IOException("The Cmap " + name + " was not found.");
+ encodeStream(in, planes);
+ in.close();
+ }
+
+ static void encodeStream(InputStream in, ArrayList planes) throws IOException {
+ BufferedReader rd = new BufferedReader(new InputStreamReader(in, "iso-8859-1"));
+ String line = null;
+ int state = CIDNONE;
+ byte seqs[] = new byte[7];
+ while ((line = rd.readLine()) != null) {
+ if (line.length() < 6)
+ continue;
+ switch (state) {
+ case CIDNONE: {
+ if (line.indexOf("begincidrange") >= 0)
+ state = CIDRANGE;
+ else if (line.indexOf("begincidchar") >= 0)
+ state = CIDCHAR;
+ else if (line.indexOf("usecmap") >= 0) {
+ StringTokenizer tk = new StringTokenizer(line);
+ String t = tk.nextToken();
+ readCmap(t.substring(1), planes);
+ }
+ break;
+ }
+ case CIDRANGE: {
+ if (line.indexOf("endcidrange") >= 0) {
+ state = CIDNONE;
+ break;
+ }
+ StringTokenizer tk = new StringTokenizer(line);
+ String t = tk.nextToken();
+ int size = t.length() / 2 - 1;
+ long start = Long.parseLong(t.substring(1, t.length() - 1), 16);
+ t = tk.nextToken();
+ long end = Long.parseLong(t.substring(1, t.length() - 1), 16);
+ t = tk.nextToken();
+ int cid = Integer.parseInt(t);
+ for (long k = start; k <= end; ++k) {
+ breakLong(k, size, seqs);
+ encodeSequence(size, seqs, (char)cid, planes);
+ ++cid;
+ }
+ break;
+ }
+ case CIDCHAR: {
+ if (line.indexOf("endcidchar") >= 0) {
+ state = CIDNONE;
+ break;
+ }
+ StringTokenizer tk = new StringTokenizer(line);
+ String t = tk.nextToken();
+ int size = t.length() / 2 - 1;
+ long start = Long.parseLong(t.substring(1, t.length() - 1), 16);
+ t = tk.nextToken();
+ int cid = Integer.parseInt(t);
+ breakLong(start, size, seqs);
+ encodeSequence(size, seqs, (char)cid, planes);
+ break;
+ }
+ }
+ }
+ }
+
+ static void breakLong(long n, int size, byte seqs[]) {
+ for (int k = 0; k < size; ++k) {
+ seqs[k] = (byte)(n >> ((size - 1 - k) * 8));
+ }
+ }
+
+ static void encodeSequence(int size, byte seqs[], char cid, ArrayList planes) {
+ --size;
+ int nextPlane = 0;
+ for (int idx = 0; idx < size; ++idx) {
+ char plane[] = (char[])planes.get(nextPlane);
+ int one = (int)seqs[idx] & 0xff;
+ char c = plane[one];
+ if (c != 0 && (c & 0x8000) == 0)
+ throw new RuntimeException("Inconsistent mapping.");
+ if (c == 0) {
+ planes.add(new char[256]);
+ c = (char)((planes.size() - 1) | 0x8000);
+ plane[one] = c;
+ }
+ nextPlane = c & 0x7fff;
+ }
+ char plane[] = (char[])planes.get(nextPlane);
+ int one = (int)seqs[size] & 0xff;
+ char c = plane[one];
+ if ((c & 0x8000) != 0)
+ throw new RuntimeException("Inconsistent mapping.");
+ plane[one] = cid;
+ }
+
+ /** Adds an extra encoding.
+ * @param name the name of the encoding. The encoding recognition is case insensitive
+ * @param enc the conversion class
+ */
+ public static void addExtraEncoding(String name, ExtraEncoding enc) {
+ synchronized (extraEncodings) {
+ extraEncodings.put(name.toLowerCase(), enc);
+ }
+ }
+
+ private static class WingdingsConversion implements ExtraEncoding {
+
+ public byte[] charToByte(String text, String encoding) {
+ char cc[] = text.toCharArray();
+ byte b[] = new byte[cc.length];
+ int ptr = 0;
+ int len = cc.length;
+ for (int k = 0; k < len; ++k) {
+ char c = cc[k];
+ if (c == ' ')
+ b[ptr++] = (byte)c;
+ else if (c >= '\u2701' && c <= '\u27BE') {
+ byte v = table[c - 0x2700];
+ if (v != 0)
+ b[ptr++] = v;
+ }
+ }
+ if (ptr == len)
+ return b;
+ byte b2[] = new byte[ptr];
+ System.arraycopy(b, 0, b2, 0, ptr);
+ return b2;
+ }
+
+ public String byteToChar(byte[] b, String encoding) {
+ return null;
+ }
+
+ private final static byte table[] = {
+ 0, 35, 34, 0, 0, 0, 41, 62, 81, 42,
+ 0, 0, 65, 63, 0, 0, 0, 0, 0, -4,
+ 0, 0, 0, -5, 0, 0, 0, 0, 0, 0,
+ 86, 0, 88, 89, 0, 0, 0, 0, 0, 0,
+ 0, 0, -75, 0, 0, 0, 0, 0, -74, 0,
+ 0, 0, -83, -81, -84, 0, 0, 0, 0, 0,
+ 0, 0, 0, 124, 123, 0, 0, 0, 84, 0,
+ 0, 0, 0, 0, 0, 0, 0, -90, 0, 0,
+ 0, 113, 114, 0, 0, 0, 117, 0, 0, 0,
+ 0, 0, 0, 125, 126, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, -116, -115,
+ -114, -113, -112, -111, -110, -109, -108, -107, -127, -126,
+ -125, -124, -123, -122, -121, -120, -119, -118, -116, -115,
+ -114, -113, -112, -111, -110, -109, -108, -107, -24, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, -24, -40, 0, 0, -60, -58, 0, 0, -16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -36,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0
+ };
+ }
+
+ private static class Cp437Conversion implements ExtraEncoding {
+ private static IntHashtable c2b = new IntHashtable();
+
+ public byte[] charToByte(String text, String encoding) {
+ char cc[] = text.toCharArray();
+ byte b[] = new byte[cc.length];
+ int ptr = 0;
+ int len = cc.length;
+ for (int k = 0; k < len; ++k) {
+ char c = cc[k];
+ if (c < ' ')
+ continue;
+ if (c < 128)
+ b[ptr++] = (byte)c;
+ else {
+ byte v = (byte)c2b.get(c);
+ if (v != 0)
+ b[ptr++] = v;
+ }
+ }
+ if (ptr == len)
+ return b;
+ byte b2[] = new byte[ptr];
+ System.arraycopy(b, 0, b2, 0, ptr);
+ return b2;
+ }
+
+ public String byteToChar(byte[] b, String encoding) {
+ int len = b.length;
+ char cc[] = new char[len];
+ int ptr = 0;
+ for (int k = 0; k < len; ++k) {
+ int c = b[k] & 0xff;
+ if (c < ' ')
+ continue;
+ if (c < 128)
+ cc[ptr++] = (char)c;
+ else {
+ char v = table[c - 128];
+ cc[ptr++] = v;
+ }
+ }
+ return new String(cc, 0, ptr);
+ }
+
+ private final static char table[] = {
+ '\u00C7', '\u00FC', '\u00E9', '\u00E2', '\u00E4', '\u00E0', '\u00E5', '\u00E7', '\u00EA', '\u00EB', '\u00E8', '\u00EF', '\u00EE', '\u00EC', '\u00C4', '\u00C5',
+ '\u00C9', '\u00E6', '\u00C6', '\u00F4', '\u00F6', '\u00F2', '\u00FB', '\u00F9', '\u00FF', '\u00D6', '\u00DC', '\u00A2', '\u00A3', '\u00A5', '\u20A7', '\u0192',
+ '\u00E1', '\u00ED', '\u00F3', '\u00FA', '\u00F1', '\u00D1', '\u00AA', '\u00BA', '\u00BF', '\u2310', '\u00AC', '\u00BD', '\u00BC', '\u00A1', '\u00AB', '\u00BB',
+ '\u2591', '\u2592', '\u2593', '\u2502', '\u2524', '\u2561', '\u2562', '\u2556', '\u2555', '\u2563', '\u2551', '\u2557', '\u255D', '\u255C', '\u255B', '\u2510',
+ '\u2514', '\u2534', '\u252C', '\u251C', '\u2500', '\u253C', '\u255E', '\u255F', '\u255A', '\u2554', '\u2569', '\u2566', '\u2560', '\u2550', '\u256C', '\u2567',
+ '\u2568', '\u2564', '\u2565', '\u2559', '\u2558', '\u2552', '\u2553', '\u256B', '\u256A', '\u2518', '\u250C', '\u2588', '\u2584', '\u258C', '\u2590', '\u2580',
+ '\u03B1', '\u00DF', '\u0393', '\u03C0', '\u03A3', '\u03C3', '\u00B5', '\u03C4', '\u03A6', '\u0398', '\u03A9', '\u03B4', '\u221E', '\u03C6', '\u03B5', '\u2229',
+ '\u2261', '\u00B1', '\u2265', '\u2264', '\u2320', '\u2321', '\u00F7', '\u2248', '\u00B0', '\u2219', '\u00B7', '\u221A', '\u207F', '\u00B2', '\u25A0', '\u00A0'
+ };
+
+ static {
+ for (int k = 0; k < table.length; ++k)
+ c2b.put(table[k], k + 128);
+ }
+ }
+
+ private static class SymbolConversion implements ExtraEncoding {
+
+ private static final IntHashtable t1 = new IntHashtable();
+ private static final IntHashtable t2 = new IntHashtable();
+ private IntHashtable translation;
+
+ SymbolConversion(boolean symbol) {
+ if (symbol)
+ translation = t1;
+ else
+ translation = t2;
+ }
+
+ public byte[] charToByte(String text, String encoding) {
+ char cc[] = text.toCharArray();
+ byte b[] = new byte[cc.length];
+ int ptr = 0;
+ int len = cc.length;
+ for (int k = 0; k < len; ++k) {
+ char c = cc[k];
+ byte v = (byte)translation.get((int)c);
+ if (v != 0)
+ b[ptr++] = v;
+ }
+ if (ptr == len)
+ return b;
+ byte b2[] = new byte[ptr];
+ System.arraycopy(b, 0, b2, 0, ptr);
+ return b2;
+ }
+
+ public String byteToChar(byte[] b, String encoding) {
+ return null;
+ }
+
+ private final static char table1[] = {
+ ' ','!','\u2200','#','\u2203','%','&','\u220b','(',')','*','+',',','-','.','/',
+ '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
+ '\u2245','\u0391','\u0392','\u03a7','\u0394','\u0395','\u03a6','\u0393','\u0397','\u0399','\u03d1','\u039a','\u039b','\u039c','\u039d','\u039f',
+ '\u03a0','\u0398','\u03a1','\u03a3','\u03a4','\u03a5','\u03c2','\u03a9','\u039e','\u03a8','\u0396','[','\u2234',']','\u22a5','_',
+ '\u0305','\u03b1','\u03b2','\u03c7','\u03b4','\u03b5','\u03d5','\u03b3','\u03b7','\u03b9','\u03c6','\u03ba','\u03bb','\u03bc','\u03bd','\u03bf',
+ '\u03c0','\u03b8','\u03c1','\u03c3','\u03c4','\u03c5','\u03d6','\u03c9','\u03be','\u03c8','\u03b6','{','|','}','~','\0',
+ '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
+ '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
+ '\u20ac','\u03d2','\u2032','\u2264','\u2044','\u221e','\u0192','\u2663','\u2666','\u2665','\u2660','\u2194','\u2190','\u2191','\u2192','\u2193',
+ '\u00b0','\u00b1','\u2033','\u2265','\u00d7','\u221d','\u2202','\u2022','\u00f7','\u2260','\u2261','\u2248','\u2026','\u2502','\u2500','\u21b5',
+ '\u2135','\u2111','\u211c','\u2118','\u2297','\u2295','\u2205','\u2229','\u222a','\u2283','\u2287','\u2284','\u2282','\u2286','\u2208','\u2209',
+ '\u2220','\u2207','\u00ae','\u00a9','\u2122','\u220f','\u221a','\u2022','\u00ac','\u2227','\u2228','\u21d4','\u21d0','\u21d1','\u21d2','\u21d3',
+ '\u25ca','\u2329','\0','\0','\0','\u2211','\u239b','\u239c','\u239d','\u23a1','\u23a2','\u23a3','\u23a7','\u23a8','\u23a9','\u23aa',
+ '\0','\u232a','\u222b','\u2320','\u23ae','\u2321','\u239e','\u239f','\u23a0','\u23a4','\u23a5','\u23a6','\u23ab','\u23ac','\u23ad','\0'
+ };
+
+ private final static char table2[] = {
+ '\u0020','\u2701','\u2702','\u2703','\u2704','\u260e','\u2706','\u2707','\u2708','\u2709','\u261b','\u261e','\u270C','\u270D','\u270E','\u270F',
+ '\u2710','\u2711','\u2712','\u2713','\u2714','\u2715','\u2716','\u2717','\u2718','\u2719','\u271A','\u271B','\u271C','\u271D','\u271E','\u271F',
+ '\u2720','\u2721','\u2722','\u2723','\u2724','\u2725','\u2726','\u2727','\u2605','\u2729','\u272A','\u272B','\u272C','\u272D','\u272E','\u272F',
+ '\u2730','\u2731','\u2732','\u2733','\u2734','\u2735','\u2736','\u2737','\u2738','\u2739','\u273A','\u273B','\u273C','\u273D','\u273E','\u273F',
+ '\u2740','\u2741','\u2742','\u2743','\u2744','\u2745','\u2746','\u2747','\u2748','\u2749','\u274A','\u274B','\u25cf','\u274D','\u25a0','\u274F',
+ '\u2750','\u2751','\u2752','\u25b2','\u25bc','\u25c6','\u2756','\u25d7','\u2758','\u2759','\u275A','\u275B','\u275C','\u275D','\u275E','\u0000',
+ '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
+ '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
+ '\u0000','\u2761','\u2762','\u2763','\u2764','\u2765','\u2766','\u2767','\u2663','\u2666','\u2665','\u2660','\u2460','\u2461','\u2462','\u2463',
+ '\u2464','\u2465','\u2466','\u2467','\u2468','\u2469','\u2776','\u2777','\u2778','\u2779','\u277A','\u277B','\u277C','\u277D','\u277E','\u277F',
+ '\u2780','\u2781','\u2782','\u2783','\u2784','\u2785','\u2786','\u2787','\u2788','\u2789','\u278A','\u278B','\u278C','\u278D','\u278E','\u278F',
+ '\u2790','\u2791','\u2792','\u2793','\u2794','\u2192','\u2194','\u2195','\u2798','\u2799','\u279A','\u279B','\u279C','\u279D','\u279E','\u279F',
+ '\u27A0','\u27A1','\u27A2','\u27A3','\u27A4','\u27A5','\u27A6','\u27A7','\u27A8','\u27A9','\u27AA','\u27AB','\u27AC','\u27AD','\u27AE','\u27AF',
+ '\u0000','\u27B1','\u27B2','\u27B3','\u27B4','\u27B5','\u27B6','\u27B7','\u27B8','\u27B9','\u27BA','\u27BB','\u27BC','\u27BD','\u27BE','\u0000'
+ };
+
+ static {
+ for (int k = 0; k < table1.length; ++k) {
+ int v = (int)table1[k];
+ if (v != 0)
+ t1.put(v, k + 32);
+ }
+ for (int k = 0; k < table2.length; ++k) {
+ int v = (int)table2[k];
+ if (v != 0)
+ t2.put(v, k + 32);
+ }
+ }
+ }
+
+ private static class SymbolTTConversion implements ExtraEncoding {
+
+ public byte[] charToByte(String text, String encoding) {
+ char ch[] = text.toCharArray();
+ byte b[] = new byte[ch.length];
+ int ptr = 0;
+ int len = ch.length;
+ for (int k = 0; k < len; ++k) {
+ char c = ch[k];
+ if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
+ b[ptr++] = (byte)c;
+ }
+ if (ptr == len)
+ return b;
+ byte b2[] = new byte[ptr];
+ System.arraycopy(b, 0, b2, 0, ptr);
+ return b2;
+ }
+
+ public String byteToChar(byte[] b, String encoding) {
+ return null;
+ }
+
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfEncryption.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfEncryption.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfEncryption.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfEncryption.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,649 @@
+/* -*- java -*-
+ * $Id: PdfEncryption.java,v 1.53 2005/08/05 23:13:44 psoares33 Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.pdf.crypto.ARCFOUREncryption;
+
+import java.security.MessageDigest;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.ByteArrayOutputStream;
+
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+/**
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ * @author Kazuya Ujihara
+ */
+public class PdfEncryption {
+
+ public static final int STANDARD_ENCRYPTION_40 = 2;
+
+ public static final int STANDARD_ENCRYPTION_128 = 3;
+
+ public static final int AES_128 = 4;
+
+ private static final byte[] pad = { (byte) 0x28, (byte) 0xBF, (byte) 0x4E,
+ (byte) 0x5E, (byte) 0x4E, (byte) 0x75, (byte) 0x8A, (byte) 0x41,
+ (byte) 0x64, (byte) 0x00, (byte) 0x4E, (byte) 0x56, (byte) 0xFF,
+ (byte) 0xFA, (byte) 0x01, (byte) 0x08, (byte) 0x2E, (byte) 0x2E,
+ (byte) 0x00, (byte) 0xB6, (byte) 0xD0, (byte) 0x68, (byte) 0x3E,
+ (byte) 0x80, (byte) 0x2F, (byte) 0x0C, (byte) 0xA9, (byte) 0xFE,
+ (byte) 0x64, (byte) 0x53, (byte) 0x69, (byte) 0x7A };
+
+ private static final byte[] salt = { (byte) 0x73, (byte) 0x41, (byte) 0x6c,
+ (byte) 0x54 };
+
+ private static final byte[] metadataPad = { (byte) 255, (byte) 255,
+ (byte) 255, (byte) 255 };
+
+ /** The encryption key for a particular object/generation */
+ byte key[];
+
+ /** The encryption key length for a particular object/generation */
+ int keySize;
+
+ /** The global encryption key */
+ byte mkey[];
+
+ /** Work area to prepare the object/generation bytes */
+ byte extra[] = new byte[5];
+
+ /** The message digest algorithm MD5 */
+ MessageDigest md5;
+
+ /** The encryption key for the owner */
+ byte ownerKey[] = new byte[32];
+
+ /** The encryption key for the user */
+ byte userKey[] = new byte[32];
+
+ /** The public key security handler for certificate encryption */
+ // 4.2.0: protected PdfPublicKeySecurityHandler publicKeyHandler = null;
+
+ int permissions;
+
+ byte documentID[];
+
+ static long seq = System.currentTimeMillis();
+
+ private int revision;
+
+ private ARCFOUREncryption arcfour = new ARCFOUREncryption();
+
+ /** The generic key length. It may be 40 or 128. */
+ private int keyLength;
+
+ private boolean encryptMetadata;
+
+ // Indicates if the encryption is only necessary for embedded files.
+ private boolean embeddedFilesOnly;
+
+ private int cryptoMode;
+
+ public PdfEncryption() {
+ try {
+ md5 = MessageDigest.getInstance("MD5");
+ } catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ // 4.2.0: publicKeyHandler = new PdfPublicKeySecurityHandler();
+ }
+
+ public PdfEncryption(PdfEncryption enc) {
+ this();
+ mkey = (byte[]) enc.mkey.clone();
+ ownerKey = (byte[]) enc.ownerKey.clone();
+ userKey = (byte[]) enc.userKey.clone();
+ permissions = enc.permissions;
+ if (enc.documentID != null)
+ documentID = (byte[]) enc.documentID.clone();
+ revision = enc.revision;
+ keyLength = enc.keyLength;
+ encryptMetadata = enc.encryptMetadata;
+ embeddedFilesOnly = enc.embeddedFilesOnly;
+ // 4.2.0: publicKeyHandler = enc.publicKeyHandler;
+ }
+
+ public void setCryptoMode(int mode, int kl) {
+ cryptoMode = mode;
+ encryptMetadata = (mode & PdfWriter.DO_NOT_ENCRYPT_METADATA) == 0;
+ embeddedFilesOnly = (mode & PdfWriter.EMBEDDED_FILES_ONLY) != 0;
+ mode &= PdfWriter.ENCRYPTION_MASK;
+ switch (mode) {
+ case PdfWriter.STANDARD_ENCRYPTION_40:
+ encryptMetadata = true;
+ embeddedFilesOnly = false;
+ keyLength = 40;
+ revision = STANDARD_ENCRYPTION_40;
+ break;
+ case PdfWriter.STANDARD_ENCRYPTION_128:
+ embeddedFilesOnly = false;
+ if (kl > 0)
+ keyLength = kl;
+ else
+ keyLength = 128;
+ revision = STANDARD_ENCRYPTION_128;
+ break;
+ case PdfWriter.ENCRYPTION_AES_128:
+ keyLength = 128;
+ revision = AES_128;
+ break;
+ default:
+ throw new IllegalArgumentException("no.valid.encryption.mode");
+ }
+ }
+
+ public int getCryptoMode() {
+ return cryptoMode;
+ }
+
+ public boolean isMetadataEncrypted() {
+ return encryptMetadata;
+ }
+
+ /**
+ * Indicates if only the embedded files have to be encrypted.
+ * @return if true only the embedded files will be encrypted
+ * @since 2.1.3
+ */
+ public boolean isEmbeddedFilesOnly() {
+ return embeddedFilesOnly;
+ }
+
+ /**
+ */
+ private byte[] padPassword(byte userPassword[]) {
+ byte userPad[] = new byte[32];
+ if (userPassword == null) {
+ System.arraycopy(pad, 0, userPad, 0, 32);
+ } else {
+ System.arraycopy(userPassword, 0, userPad, 0, Math.min(
+ userPassword.length, 32));
+ if (userPassword.length < 32)
+ System.arraycopy(pad, 0, userPad, userPassword.length,
+ 32 - userPassword.length);
+ }
+
+ return userPad;
+ }
+
+ /**
+ */
+ private byte[] computeOwnerKey(byte userPad[], byte ownerPad[]) {
+ byte ownerKey[] = new byte[32];
+
+ byte digest[] = md5.digest(ownerPad);
+ if (revision == STANDARD_ENCRYPTION_128 || revision == AES_128) {
+ byte mkey[] = new byte[keyLength / 8];
+ // only use for the input as many bit as the key consists of
+ for (int k = 0; k < 50; ++k)
+ System.arraycopy(md5.digest(digest), 0, digest, 0, mkey.length);
+ System.arraycopy(userPad, 0, ownerKey, 0, 32);
+ for (int i = 0; i < 20; ++i) {
+ for (int j = 0; j < mkey.length; ++j)
+ mkey[j] = (byte) (digest[j] ^ i);
+ arcfour.prepareARCFOURKey(mkey);
+ arcfour.encryptARCFOUR(ownerKey);
+ }
+ } else {
+ arcfour.prepareARCFOURKey(digest, 0, 5);
+ arcfour.encryptARCFOUR(userPad, ownerKey);
+ }
+
+ return ownerKey;
+ }
+
+ /**
+ *
+ * ownerKey, documentID must be setup
+ */
+ private void setupGlobalEncryptionKey(byte[] documentID, byte userPad[],
+ byte ownerKey[], int permissions) {
+ this.documentID = documentID;
+ this.ownerKey = ownerKey;
+ this.permissions = permissions;
+ // use variable keylength
+ mkey = new byte[keyLength / 8];
+
+ // fixed by ujihara in order to follow PDF reference
+ md5.reset();
+ md5.update(userPad);
+ md5.update(ownerKey);
+
+ byte ext[] = new byte[4];
+ ext[0] = (byte) permissions;
+ ext[1] = (byte) (permissions >> 8);
+ ext[2] = (byte) (permissions >> 16);
+ ext[3] = (byte) (permissions >> 24);
+ md5.update(ext, 0, 4);
+ if (documentID != null)
+ md5.update(documentID);
+ if (!encryptMetadata)
+ md5.update(metadataPad);
+
+ byte digest[] = new byte[mkey.length];
+ System.arraycopy(md5.digest(), 0, digest, 0, mkey.length);
+
+ // only use the really needed bits as input for the hash
+ if (revision == STANDARD_ENCRYPTION_128 || revision == AES_128) {
+ for (int k = 0; k < 50; ++k)
+ System.arraycopy(md5.digest(digest), 0, digest, 0, mkey.length);
+ }
+
+ System.arraycopy(digest, 0, mkey, 0, mkey.length);
+ }
+
+ /**
+ *
+ * mkey must be setup
+ */
+ // use the revision to choose the setup method
+ private void setupUserKey() {
+ if (revision == STANDARD_ENCRYPTION_128 || revision == AES_128) {
+ md5.update(pad);
+ byte digest[] = md5.digest(documentID);
+ System.arraycopy(digest, 0, userKey, 0, 16);
+ for (int k = 16; k < 32; ++k)
+ userKey[k] = 0;
+ for (int i = 0; i < 20; ++i) {
+ for (int j = 0; j < mkey.length; ++j)
+ digest[j] = (byte) (mkey[j] ^ i);
+ arcfour.prepareARCFOURKey(digest, 0, mkey.length);
+ arcfour.encryptARCFOUR(userKey, 0, 16);
+ }
+ } else {
+ arcfour.prepareARCFOURKey(mkey);
+ arcfour.encryptARCFOUR(pad, userKey);
+ }
+ }
+
+ public void setupAllKeys(byte userPassword[], byte ownerPassword[], int permissions) {
+ // ssteward: this 'random' owner PW is generally unexpected behavior
+ // and could lead to unpleasant surprises; as noted, below,
+ // if no owner password is given, use the user password in its place;
+ //if (ownerPassword == null || ownerPassword.length == 0)
+ // ownerPassword = md5.digest(createDocumentId());
+ if( ownerPassword== null || ownerPassword.length== 0 ) {
+ ownerPassword= new byte[userPassword.length];
+ System.arraycopy( userPassword, 0, ownerPassword, 0, userPassword.length );
+ }
+ // PDF 1.3 ref. (40 bit enc.) says to set unused, upper bits to 1
+ permissions |= (revision == STANDARD_ENCRYPTION_128 || revision == AES_128) ? 0xfffff0c0 : 0xffffffc0;
+ permissions &= 0xfffffffc;
+ //PDF reference 3.5.2 Standard Security Handler, Algorithm 3.3-1
+ //If there is no owner password, use the user password instead.
+ byte userPad[] = padPassword(userPassword);
+ byte ownerPad[] = padPassword(ownerPassword);
+
+ this.ownerKey = computeOwnerKey(userPad, ownerPad);
+ documentID = createDocumentId();
+ setupByUserPad(this.documentID, userPad, this.ownerKey, permissions);
+ }
+
+ public static byte[] createDocumentId() {
+ MessageDigest md5;
+ try {
+ md5 = MessageDigest.getInstance("MD5");
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ long time = System.currentTimeMillis();
+ long mem = Runtime.getRuntime().freeMemory();
+ String s = time + "+" + mem + "+" + (seq++);
+ return md5.digest(s.getBytes());
+ }
+
+ /**
+ */
+ public void setupByUserPassword(byte[] documentID, byte userPassword[], byte ownerKey[], int permissions) {
+ setupByUserPad(documentID, padPassword(userPassword), ownerKey, permissions);
+ }
+
+ /**
+ */
+ private void setupByUserPad(byte[] documentID, byte userPad[], byte ownerKey[], int permissions) {
+ setupGlobalEncryptionKey(documentID, userPad, ownerKey, permissions);
+ setupUserKey();
+ }
+
+ /**
+ */
+ public void setupByOwnerPassword(byte[] documentID, byte ownerPassword[], byte userKey[], byte ownerKey[], int permissions) {
+ setupByOwnerPad(documentID, padPassword(ownerPassword), userKey, ownerKey, permissions);
+ }
+
+ private void setupByOwnerPad(byte[] documentID, byte ownerPad[], byte userKey[], byte ownerKey[], int permissions) {
+ byte userPad[] = computeOwnerKey(ownerKey, ownerPad); //userPad will be set in this.ownerKey
+ setupGlobalEncryptionKey(documentID, userPad, ownerKey, permissions); //step 3
+ setupUserKey();
+ }
+
+ public void setupByEncryptionKey(byte[] key, int keylength) {
+ mkey = new byte[keylength / 8];
+ System.arraycopy(key, 0, mkey, 0, mkey.length);
+ }
+
+ public void setHashKey(int number, int generation) {
+ md5.reset(); // added by ujihara
+ extra[0] = (byte) number;
+ extra[1] = (byte) (number >> 8);
+ extra[2] = (byte) (number >> 16);
+ extra[3] = (byte) generation;
+ extra[4] = (byte) (generation >> 8);
+ md5.update(mkey);
+ md5.update(extra);
+ if (revision == AES_128)
+ md5.update(salt);
+ key = md5.digest();
+ keySize = mkey.length + 5;
+ if (keySize > 16)
+ keySize = 16;
+ }
+
+ public static PdfObject createInfoId(byte id[]) {
+ ByteBuffer buf = new ByteBuffer(90);
+ buf.append('[').append('<');
+ for (int k = 0; k < 16; ++k)
+ buf.appendHex(id[k]);
+ buf.append('>').append('<');
+ id = createDocumentId();
+ for (int k = 0; k < 16; ++k)
+ buf.appendHex(id[k]);
+ buf.append('>').append(']');
+ return new PdfLiteral(buf.toByteArray());
+ }
+
+ public PdfDictionary getEncryptionDictionary() {
+ PdfDictionary dic = new PdfDictionary();
+
+ /*
+ if (publicKeyHandler.getRecipientsSize() > 0) {
+ PdfArray recipients = null;
+
+ dic.put(PdfName.FILTER, PdfName.PUBSEC);
+ dic.put(PdfName.R, new PdfNumber(revision));
+
+ try {
+ recipients = publicKeyHandler.getEncodedRecipients();
+ } catch (Exception f) {
+ throw new ExceptionConverter(f);
+ }
+
+ if (revision == STANDARD_ENCRYPTION_40) {
+ dic.put(PdfName.V, new PdfNumber(1));
+ dic.put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_S4);
+ dic.put(PdfName.RECIPIENTS, recipients);
+ } else if (revision == STANDARD_ENCRYPTION_128 && encryptMetadata) {
+ dic.put(PdfName.V, new PdfNumber(2));
+ dic.put(PdfName.LENGTH, new PdfNumber(128));
+ dic.put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_S4);
+ dic.put(PdfName.RECIPIENTS, recipients);
+ } else {
+ dic.put(PdfName.R, new PdfNumber(AES_128));
+ dic.put(PdfName.V, new PdfNumber(4));
+ dic.put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_S5);
+
+ PdfDictionary stdcf = new PdfDictionary();
+ stdcf.put(PdfName.RECIPIENTS, recipients);
+ if (!encryptMetadata)
+ stdcf.put(PdfName.ENCRYPTMETADATA, PdfBoolean.PDFFALSE);
+
+ if (revision == AES_128)
+ stdcf.put(PdfName.CFM, PdfName.AESV2);
+ else
+ stdcf.put(PdfName.CFM, PdfName.V2);
+ PdfDictionary cf = new PdfDictionary();
+ cf.put(PdfName.DEFAULTCRYPTFILTER, stdcf);
+ dic.put(PdfName.CF, cf);if (embeddedFilesOnly) {
+ dic.put(PdfName.EFF, PdfName.DEFAULTCRYPTFILTER);
+ dic.put(PdfName.STRF, PdfName.IDENTITY);
+ dic.put(PdfName.STMF, PdfName.IDENTITY);
+ }
+ else {
+ dic.put(PdfName.STRF, PdfName.DEFAULTCRYPTFILTER);
+ dic.put(PdfName.STMF, PdfName.DEFAULTCRYPTFILTER);
+ }
+ }
+
+ MessageDigest md = null;
+ byte[] encodedRecipient = null;
+
+ try {
+ md = MessageDigest.getInstance("SHA-1");
+ md.update(publicKeyHandler.getSeed());
+ for (int i = 0; i < publicKeyHandler.getRecipientsSize(); i++) {
+ encodedRecipient = publicKeyHandler.getEncodedRecipient(i);
+ md.update(encodedRecipient);
+ }
+ if (!encryptMetadata)
+ md.update(new byte[] { (byte) 255, (byte) 255, (byte) 255,
+ (byte) 255 });
+ } catch (Exception f) {
+ throw new ExceptionConverter(f);
+ }
+
+ byte[] mdResult = md.digest();
+
+ setupByEncryptionKey(mdResult, keyLength);
+ } else {
+ */
+ dic.put(PdfName.FILTER, PdfName.STANDARD);
+ dic.put(PdfName.O, new PdfLiteral(PdfContentByte.escapeString(ownerKey)));
+ dic.put(PdfName.U, new PdfLiteral(PdfContentByte.escapeString(userKey)));
+ dic.put(PdfName.P, new PdfNumber(permissions));
+ dic.put(PdfName.R, new PdfNumber(revision));
+
+ if (revision == STANDARD_ENCRYPTION_40) {
+ dic.put(PdfName.V, new PdfNumber(1));
+ }
+ else if (revision == STANDARD_ENCRYPTION_128 && encryptMetadata) {
+ dic.put(PdfName.V, new PdfNumber(2));
+ dic.put(PdfName.LENGTH, new PdfNumber(128));
+
+ }
+ else {
+ if (!encryptMetadata)
+ dic.put(PdfName.ENCRYPTMETADATA, PdfBoolean.PDFFALSE);
+ dic.put(PdfName.R, new PdfNumber(AES_128));
+ dic.put(PdfName.V, new PdfNumber(4));
+ dic.put(PdfName.LENGTH, new PdfNumber(128));
+ PdfDictionary stdcf = new PdfDictionary();
+ stdcf.put(PdfName.LENGTH, new PdfNumber(16));
+ if (embeddedFilesOnly) {
+ stdcf.put(PdfName.AUTHEVENT, PdfName.EFOPEN);
+ dic.put(PdfName.EFF, PdfName.STDCF);
+ dic.put(PdfName.STRF, PdfName.IDENTITY);
+ dic.put(PdfName.STMF, PdfName.IDENTITY);
+ }
+ else {
+ stdcf.put(PdfName.AUTHEVENT, PdfName.DOCOPEN);
+ dic.put(PdfName.STRF, PdfName.STDCF);
+ dic.put(PdfName.STMF, PdfName.STDCF);
+ }
+ if (revision == AES_128)
+ stdcf.put(PdfName.CFM, PdfName.AESV2);
+ else
+ stdcf.put(PdfName.CFM, PdfName.V2);
+ PdfDictionary cf = new PdfDictionary();
+ cf.put(PdfName.STDCF, stdcf);
+ dic.put(PdfName.CF, cf);
+ }
+ //}
+
+ return dic;
+ }
+
+ public PdfObject getFileID() {
+ return createInfoId(documentID);
+ }
+
+ public OutputStreamEncryption getEncryptionStream(OutputStream os) {
+ return new OutputStreamEncryption(os, key, 0, keySize, revision);
+ }
+
+ public int calculateStreamSize(int n) {
+ if (revision == AES_128)
+ return (n & 0x7ffffff0) + 32;
+ else
+ return n;
+ }
+
+ public byte[] encryptByteArray(byte[] b) {
+ try {
+ ByteArrayOutputStream ba = new ByteArrayOutputStream();
+ OutputStreamEncryption os2 = getEncryptionStream(ba);
+ os2.write(b);
+ os2.finish();
+ return ba.toByteArray();
+ } catch (IOException ex) {
+ throw new ExceptionConverter(ex);
+ }
+ }
+
+ public StandardDecryption getDecryptor() {
+ return new StandardDecryption(key, 0, keySize, revision);
+ }
+
+ public byte[] decryptByteArray(byte[] b) {
+ try {
+ ByteArrayOutputStream ba = new ByteArrayOutputStream();
+ StandardDecryption dec = getDecryptor();
+ byte[] b2 = dec.update(b, 0, b.length);
+ if (b2 != null)
+ ba.write(b2);
+ b2 = dec.finish();
+ if (b2 != null)
+ ba.write(b2);
+ return ba.toByteArray();
+ } catch (IOException ex) {
+ throw new ExceptionConverter(ex);
+ }
+ }
+
+ /* 4.2.0
+ public void addRecipient(Certificate cert, int permission) {
+ documentID = createDocumentId();
+ publicKeyHandler.addRecipient(new PdfPublicKeyRecipient(cert,
+ permission));
+ }
+ */
+
+ public byte[] computeUserPassword(byte[] ownerPassword) {
+ byte[] userPad = computeOwnerKey(ownerKey, padPassword(ownerPassword));
+ for (int i = 0; i < userPad.length; i++) {
+ boolean match = true;
+ for (int j = 0; j < userPad.length - i; j++) {
+ if (userPad[i + j] != pad[j]) {
+ match = false;
+ break;
+ }
+ }
+ if (!match) continue;
+ byte[] userPassword = new byte[i];
+ System.arraycopy(userPad, 0, userPassword, 0, i);
+ return userPassword;
+ }
+ return userPad;
+ }
+
+ ////
+ // legacy code that should be eventually removed;
+ // callers should instead use ARCFOUREncryption
+
+ byte state[] = new byte[256];
+ int x;
+ int y;
+
+ public void prepareKey() {
+ prepareRC4Key(key, 0, keySize);
+ }
+
+ public void prepareRC4Key(byte kk[]) {
+ prepareRC4Key(kk, 0, kk.length);
+ }
+
+ public void prepareRC4Key(byte kk[], int off, int len) {
+ int index1 = 0;
+ int index2 = 0;
+ for (int k = 0; k < 256; ++k)
+ state[k] = (byte)k;
+ x = 0;
+ y = 0;
+ byte tmp;
+ for (int k = 0; k < 256; ++k) {
+ index2 = (kk[index1 + off] + state[k] + index2) & 255;
+ tmp = state[k];
+ state[k] = state[index2];
+ state[index2] = tmp;
+ index1 = (index1 + 1) % len;
+ }
+ }
+
+ public void encryptRC4(byte dataIn[], int off, int len, byte dataOut[]) {
+ int length = len + off;
+ byte tmp;
+ for (int k = off; k < length; ++k) {
+ x = (x + 1) & 255;
+ y = (state[x] + y) & 255;
+ tmp = state[x];
+ state[x] = state[y];
+ state[y] = tmp;
+ dataOut[k] = (byte)(dataIn[k] ^ state[(state[x] + state[y]) & 255]);
+ }
+ }
+
+ public void encryptRC4(byte data[], int off, int len) {
+ encryptRC4(data, off, len, data);
+ }
+
+ public void encryptRC4(byte dataIn[], byte dataOut[]) {
+ encryptRC4(dataIn, 0, dataIn.length, dataOut);
+ }
+
+ public void encryptRC4(byte data[]) {
+ encryptRC4(data, 0, data.length, data);
+ }
+
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfEncryptionStream.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfEncryptionStream.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfEncryptionStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfEncryptionStream.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,75 @@
+/*
+ * $Id: PdfEncryptionStream.java,v 1.3 2005/02/17 09:20:54 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2004 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.FilterOutputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+public class PdfEncryptionStream extends FilterOutputStream {
+
+ protected PdfEncryption enc;
+ private byte buf[] = new byte[1];
+
+ public PdfEncryptionStream(OutputStream out, PdfEncryption enc) {
+ super(out);
+ this.enc = enc;
+ }
+
+ public void write(byte[] b, int off, int len) throws IOException {
+ if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
+ throw new IndexOutOfBoundsException();
+ enc.encryptRC4(b, off, len);
+ out.write(b, off, len);
+ }
+
+ public void close() throws IOException {
+ }
+
+ public void write(int b) throws IOException {
+ buf[0] = (byte)b;
+ write(buf);
+ }
+
+ public void flush() throws IOException {
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfException.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfException.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfException.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,76 @@
+/*
+ * $Id: PdfException.java,v 1.22 2002/06/20 13:30:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.DocumentException;
+
+/**
+ * Signals that an unspecified problem while constructing a PDF document.
+ *
+ * @see BadPdfFormatException
+ */
+
+public class PdfException extends DocumentException {
+
+ // constructors
+
+ public PdfException(Exception ex) {
+ super(ex);
+ }
+
+ /**
+ * Constructs a PdfException
whithout a message.
+ */
+
+ PdfException() {
+ super();
+ }
+
+/**
+ * Constructs a PdfException
with a message.
+ *
+ * @param message a message describing the exception
+ */
+
+ PdfException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfFileSpecification.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfFileSpecification.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfFileSpecification.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfFileSpecification.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.*;
+import java.net.URL;
+/** Specifies a file or an URL. The file can be extern or embedded.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfFileSpecification extends PdfDictionary {
+ protected PdfWriter writer;
+ protected PdfIndirectReference ref;
+
+ /** Creates a new instance of PdfFileSpecification. The static methods are preferred. */
+ public PdfFileSpecification() {
+
+ // ssteward: for Acrobat 5 compatibility, set Type to "F" instead
+ // of the (more correct) "Filesec"; this quirk is documented
+ // in Implementation Note 38 on page 955 of the PDF Ref. ver. 1.5;
+ // Acrobat 6 (and later) accept either "Filespec" or "F"
+ //super(PdfName.FILESPEC);
+ super(PdfName.F);
+ }
+
+ /**
+ * Creates a file specification of type URL.
+ * @param writer the PdfWriter
+ * @param url the URL
+ * @return the file specification
+ */
+ public static PdfFileSpecification url(PdfWriter writer, String url) {
+ PdfFileSpecification fs = new PdfFileSpecification();
+ fs.writer = writer;
+ fs.put(PdfName.FS, PdfName.URL);
+ fs.put(PdfName.F, new PdfString(url));
+ return fs;
+ }
+
+ /**
+ * Creates a file specification with the file embedded. The file may
+ * come from the file system or from a byte array. The data is flate compressed.
+ * @param writer the PdfWriter
+ * @param filePath the file path
+ * @param fileDisplay the file information that is presented to the user
+ * @param fileStore the byte array with the file. If it is not null
+ * it takes precedence over filePath
+ * @throws IOException on error
+ * @return the file specification
+ */
+ public static PdfFileSpecification fileEmbedded(PdfWriter writer, String filePath, String fileDisplay, byte fileStore[]) throws IOException {
+ return fileEmbedded(writer, filePath, fileDisplay, fileStore, true);
+ }
+
+
+ /**
+ * Creates a file specification with the file embedded. The file may
+ * come from the file system or from a byte array.
+ * @param writer the PdfWriter
+ * @param filePath the file path
+ * @param fileDisplay the file information that is presented to the user
+ * @param fileStore the byte array with the file. If it is not null
+ * it takes precedence over filePath
+ * @param compress sets the compression on the data. Multimedia content will benefit little
+ * from compression
+ * @throws IOException on error
+ * @return the file specification
+ */
+ public static PdfFileSpecification fileEmbedded(PdfWriter writer, String filePath, String fileDisplay, byte fileStore[], boolean compress) throws IOException {
+ PdfFileSpecification fs = new PdfFileSpecification();
+ fs.writer = writer;
+
+ PdfString fileDisplayPdf= new PdfString( fileDisplay, PdfObject.TEXT_PDFDOCENCODING );
+ PdfString fileDisplayPdfUnicode= new PdfString( fileDisplay, PdfObject.TEXT_UNICODE );
+ fs.put(PdfName.F, fileDisplayPdf);
+ fs.put(PdfName.UF, fileDisplayPdfUnicode); // introduced in PDF 1.7
+
+ PdfStream stream;
+ InputStream in = null;
+ PdfIndirectReference ref;
+ PdfIndirectReference refFileLength;
+ try {
+ refFileLength = writer.getPdfIndirectReference();
+ if (fileStore == null) {
+ File file = new File(filePath);
+ if (file.canRead()) {
+ in = new FileInputStream(filePath);
+ }
+ else {
+ if (filePath.startsWith("file:/") || filePath.startsWith("http://") || filePath.startsWith("https://") || filePath.startsWith("jar:")) {
+ in = new URL(filePath).openStream();
+ }
+ else {
+ in = BaseFont.getResourceStream(filePath);
+ if (in == null)
+ throw new IOException(filePath + " not found as file or resource.");
+ }
+ }
+ stream = new PdfStream(in, writer);
+ }
+ else
+ stream = new PdfStream(fileStore);
+ stream.put(PdfName.TYPE, PdfName.EMBEDDEDFILE);
+ if (compress)
+ stream.flateCompress();
+ stream.put(PdfName.PARAMS, refFileLength);
+ ref = writer.addToBody(stream).getIndirectReference();
+ if (fileStore == null) {
+ stream.writeLength();
+ }
+ PdfDictionary params = new PdfDictionary();
+ params.put(PdfName.SIZE, new PdfNumber(stream.getRawLength()));
+ writer.addToBody(params, refFileLength);
+ }
+ finally {
+ if (in != null)
+ try{in.close();}catch(Exception e){}
+ }
+ PdfDictionary f = new PdfDictionary();
+ f.put(PdfName.F, ref);
+ fs.put(PdfName.EF, f);
+ return fs;
+ }
+
+ /**
+ * Creates a file specification for an external file.
+ * @param writer the PdfWriter
+ * @param filePath the file path
+ * @return the file specification
+ */
+ public static PdfFileSpecification fileExtern(PdfWriter writer, String filePath) {
+ PdfFileSpecification fs = new PdfFileSpecification();
+ fs.writer = writer;
+ fs.put(PdfName.F, new PdfString(filePath));
+ return fs;
+ }
+
+ /**
+ * Gets the indirect reference to this file specification.
+ * Multiple invocations will retrieve the same value.
+ * @throws IOException on error
+ * @return the indirect reference
+ */
+ public PdfIndirectReference getReference() throws IOException {
+ if (ref != null)
+ return ref;
+ ref = writer.addToBody(this).getIndirectReference();
+ return ref;
+ }
+
+ /**
+ * Sets the file name (the key /F) string as an hex representation
+ * to support multi byte file names. The name must heve th slash and
+ * backslash escaped according to the file specification rules
+ * @param fileName the file name as a byte array
+ */
+ /* ssteward: appears that fileName should hold the multi-byte data -- it isn't converted,
+ but is packed literally into the PDF;
+ public void setMultiByteFileName(byte fileName[]) {
+ put(PdfName.F, new PdfString(fileName).setHexWriting(true));
+ }
+ */
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfFont.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfFont.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfFont.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfFont.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,190 @@
+/*
+ * $Id: PdfFont.java,v 1.30 2002/07/09 11:28:23 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+// import pdftk.com.lowagie.text.Image; ssteward: dropped in 1.44
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+/**
+ * PdfFont
is the Pdf Font object.
+ *
+ * Limitation: in this class only base 14 Type 1 fonts (courier, courier bold, courier oblique,
+ * courier boldoblique, helvetica, helvetica bold, helvetica oblique, helvetica boldoblique,
+ * symbol, times roman, times bold, times italic, times bolditalic, zapfdingbats) and their
+ * standard encoding (standard, MacRoman, (MacExpert,) WinAnsi) are supported.
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 7.7 (page 198-203).
+ *
+ * @see PdfName
+ * @see PdfDictionary
+ * @see BadPdfFormatException
+ */
+
+class PdfFont implements Comparable {
+
+
+ /** the font metrics. */
+ private BaseFont font;
+
+ /** the size. */
+ private float size;
+
+ /** an image. */
+ // protected Image image; ssteward: dropped in 1.44
+
+ protected float hScale = 1;
+
+ // constructors
+
+ PdfFont(BaseFont bf, float size) {
+ this.size = size;
+ font = bf;
+ }
+
+ // methods
+
+ /**
+ * Compares this PdfFont
with another
+ *
+ * @param object the other PdfFont
+ * @return a value
+ */
+
+ public int compareTo(Object object) {
+ /* ssteward: dropped in 1.44
+ if (image != null)
+ return 0;
+ */
+ if (object == null) {
+ return -1;
+ }
+ PdfFont pdfFont;
+ try {
+ pdfFont = (PdfFont) object;
+ if (font != pdfFont.font) {
+ return 1;
+ }
+ if (this.size() != pdfFont.size()) {
+ return 2;
+ }
+ return 0;
+ }
+ catch(ClassCastException cce) {
+ return -2;
+ }
+ }
+
+ /**
+ * Returns the size of this font.
+ *
+ * @return a size
+ */
+
+ float size() {
+ return size;
+ /* ssteward: dropped in 1.44
+ if (image == null)
+ return size;
+ else {
+ return image.scaledHeight();
+ }
+ */
+ }
+
+ /**
+ * Returns the approximative width of 1 character of this font.
+ *
+ * @return a width in Text Space
+ */
+
+ float width() {
+ return width(' ');
+ }
+
+ /**
+ * Returns the width of a certain character of this font.
+ *
+ * @param character a certain character
+ * @return a width in Text Space
+ */
+
+ float width(char character) {
+ return font.getWidthPoint(character, size) * hScale;
+ /* ssteward: dropped in 1.44
+ if (image == null)
+ return font.getWidthPoint(character, size) * hScale;
+ else
+ return image.scaledWidth();
+ */
+ }
+
+ float width(String s) {
+ return font.getWidthPoint(s, size) * hScale;
+ /* ssteward: dropped in 1.44
+ if (image == null)
+ return font.getWidthPoint(s, size) * hScale;
+ else
+ return image.scaledWidth();
+ */
+ }
+
+ BaseFont getFont() {
+ return font;
+ }
+ /* ssteward: dropped in 1.44
+ void setImage(Image image) {
+ this.image = image;
+ }
+ */
+
+ static PdfFont getDefaultFont() {
+ try {
+ BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.WINANSI, false);
+ return new PdfFont(bf, 12);
+ }
+ catch (Exception ee) {
+ throw new ExceptionConverter(ee);
+ }
+ }
+ void setHorizontalScaling(float hScale) {
+ this.hScale = hScale;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfFormField.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfFormField.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfFormField.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfFormField.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,337 @@
+/*
+ * Copyright 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import pdftk.com.lowagie.text.Rectangle;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/** Implements form fields.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfFormField extends PdfAnnotation {
+
+ public static final int FF_READ_ONLY = 1;
+ public static final int FF_REQUIRED = 2;
+ public static final int FF_NO_EXPORT = 4;
+ public static final int FF_NO_TOGGLE_TO_OFF = 16384;
+ public static final int FF_RADIO = 32768;
+ public static final int FF_PUSHBUTTON = 65536;
+ public static final int FF_MULTILINE = 4096;
+ public static final int FF_PASSWORD = 8192;
+ public static final int FF_COMBO = 131072;
+ public static final int FF_EDIT = 262144;
+ public static final int FF_FILESELECT = 1048576;
+ public static final int FF_MULTISELECT = 2097152;
+ public static final int FF_DONOTSPELLCHECK = 4194304;
+ public static final int FF_DONOTSCROLL = 8388608;
+ public static final int FF_COMB = 16777216;
+ public static final int FF_RADIOSINUNISON = 1 << 25;
+ public static final int Q_LEFT = 0;
+ public static final int Q_CENTER = 1;
+ public static final int Q_RIGHT = 2;
+ public static final int MK_NO_ICON = 0;
+ public static final int MK_NO_CAPTION = 1;
+ public static final int MK_CAPTION_BELOW = 2;
+ public static final int MK_CAPTION_ABOVE = 3;
+ public static final int MK_CAPTION_RIGHT = 4;
+ public static final int MK_CAPTION_LEFT = 5;
+ public static final int MK_CAPTION_OVERLAID = 6;
+ public static final PdfName IF_SCALE_ALWAYS = PdfName.A;
+ public static final PdfName IF_SCALE_BIGGER = PdfName.B;
+ public static final PdfName IF_SCALE_SMALLER = PdfName.S;
+ public static final PdfName IF_SCALE_NEVER = PdfName.N;
+ public static final PdfName IF_SCALE_ANAMORPHIC = PdfName.A;
+ public static final PdfName IF_SCALE_PROPORTIONAL = PdfName.P;
+ public static final boolean MULTILINE = true;
+ public static final boolean SINGLELINE = false;
+ public static final boolean PLAINTEXT = false;
+ public static final boolean PASSWORD = true;
+ static PdfName mergeTarget[] = {PdfName.FONT, PdfName.XOBJECT, PdfName.COLORSPACE, PdfName.PATTERN};
+
+ /** Holds value of property parent. */
+ protected PdfFormField parent;
+
+ protected ArrayList kids;
+
+/**
+ * Constructs a new PdfAnnotation
of subtype link (Action).
+ */
+
+ public PdfFormField(PdfWriter writer, float llx, float lly, float urx, float ury, PdfAction action) {
+ super(writer, llx, lly, urx, ury, action);
+ put(PdfName.TYPE, PdfName.ANNOT);
+ put(PdfName.SUBTYPE, PdfName.WIDGET);
+ annotation = true;
+ }
+
+ /** Creates new PdfFormField */
+ protected PdfFormField(PdfWriter writer) {
+ super(writer, null);
+ form = true;
+ annotation = false;
+ }
+
+ public void setWidget(Rectangle rect, PdfName highlight) {
+ put(PdfName.TYPE, PdfName.ANNOT);
+ put(PdfName.SUBTYPE, PdfName.WIDGET);
+ put(PdfName.RECT, new PdfRectangle(rect));
+ annotation = true;
+ if (highlight != null && !highlight.equals(HIGHLIGHT_INVERT))
+ put(PdfName.H, highlight);
+ }
+
+ public static PdfFormField createEmpty(PdfWriter writer) {
+ PdfFormField field = new PdfFormField(writer);
+ return field;
+ }
+
+ public void setButton(int flags) {
+ put(PdfName.FT, PdfName.BTN);
+ if (flags != 0)
+ put(PdfName.FF, new PdfNumber(flags));
+ }
+
+ protected static PdfFormField createButton(PdfWriter writer, int flags) {
+ PdfFormField field = new PdfFormField(writer);
+ field.setButton(flags);
+ return field;
+ }
+
+ public static PdfFormField createPushButton(PdfWriter writer) {
+ return createButton(writer, FF_PUSHBUTTON);
+ }
+
+ public static PdfFormField createCheckBox(PdfWriter writer) {
+ return createButton(writer, 0);
+ }
+
+ public static PdfFormField createRadioButton(PdfWriter writer, boolean noToggleToOff) {
+ return createButton(writer, FF_RADIO + (noToggleToOff ? FF_NO_TOGGLE_TO_OFF : 0));
+ }
+
+ public static PdfFormField createTextField(PdfWriter writer, boolean multiline, boolean password, int maxLen) {
+ PdfFormField field = new PdfFormField(writer);
+ field.put(PdfName.FT, PdfName.TX);
+ int flags = (multiline ? FF_MULTILINE : 0);
+ flags += (password ? FF_PASSWORD : 0);
+ field.put(PdfName.FF, new PdfNumber(flags));
+ if (maxLen > 0)
+ field.put(PdfName.MAXLEN, new PdfNumber(maxLen));
+ return field;
+ }
+
+ protected static PdfFormField createChoice(PdfWriter writer, int flags, PdfArray options, int topIndex) {
+ PdfFormField field = new PdfFormField(writer);
+ field.put(PdfName.FT, PdfName.CH);
+ field.put(PdfName.FF, new PdfNumber(flags));
+ field.put(PdfName.OPT, options);
+ if (topIndex > 0)
+ field.put(PdfName.TI, new PdfNumber(topIndex));
+ return field;
+ }
+
+ public static PdfFormField createList(PdfWriter writer, String options[], int topIndex) {
+ return createChoice(writer, 0, processOptions(options), topIndex);
+ }
+
+ public static PdfFormField createList(PdfWriter writer, String options[][], int topIndex) {
+ return createChoice(writer, 0, processOptions(options), topIndex);
+ }
+
+ public static PdfFormField createCombo(PdfWriter writer, boolean edit, String options[], int topIndex) {
+ return createChoice(writer, FF_COMBO + (edit ? FF_EDIT : 0), processOptions(options), topIndex);
+ }
+
+ public static PdfFormField createCombo(PdfWriter writer, boolean edit, String options[][], int topIndex) {
+ return createChoice(writer, FF_COMBO + (edit ? FF_EDIT : 0), processOptions(options), topIndex);
+ }
+
+ protected static PdfArray processOptions(String options[]) {
+ PdfArray array = new PdfArray();
+ for (int k = 0; k < options.length; ++k) {
+ array.add(new PdfString(options[k], PdfObject.TEXT_UNICODE));
+ }
+ return array;
+ }
+
+ protected static PdfArray processOptions(String options[][]) {
+ PdfArray array = new PdfArray();
+ for (int k = 0; k < options.length; ++k) {
+ String subOption[] = options[k];
+ PdfArray ar2 = new PdfArray(new PdfString(subOption[0], PdfObject.TEXT_UNICODE));
+ ar2.add(new PdfString(subOption[1], PdfObject.TEXT_UNICODE));
+ array.add(ar2);
+ }
+ return array;
+ }
+
+ public static PdfFormField createSignature(PdfWriter writer) {
+ PdfFormField field = new PdfFormField(writer);
+ field.put(PdfName.FT, PdfName.SIG);
+ return field;
+ }
+
+ /** Getter for property parent.
+ * @return Value of property parent.
+ */
+ public PdfFormField getParent() {
+ return parent;
+ }
+
+ public void addKid(PdfFormField field) {
+ field.parent = this;
+ if (kids == null)
+ kids = new ArrayList();
+ kids.add(field);
+ }
+
+ ArrayList getKids() {
+ return kids;
+ }
+
+ public int setFieldFlags(int flags) {
+ PdfNumber obj = (PdfNumber)get(PdfName.FF);
+ int old;
+ if (obj == null)
+ old = 0;
+ else
+ old = obj.intValue();
+ int v = old | flags;
+ put(PdfName.FF, new PdfNumber(v));
+ return old;
+ }
+
+ public void setValueAsString(String s) {
+ put(PdfName.V, new PdfString(s, PdfObject.TEXT_UNICODE));
+ }
+
+ public void setValueAsName(String s) {
+ put(PdfName.V, new PdfName(s));
+ }
+
+ public void setValue(PdfSignature sig) {
+ put(PdfName.V, sig);
+ }
+
+ public void setDefaultValueAsString(String s) {
+ put(PdfName.DV, new PdfString(s, PdfObject.TEXT_UNICODE));
+ }
+
+ public void setDefaultValueAsName(String s) {
+ put(PdfName.DV, new PdfName(s));
+ }
+
+ public void setFieldName(String s) {
+ if (s != null)
+ put(PdfName.T, new PdfString(s, PdfObject.TEXT_UNICODE));
+ }
+
+ public void setUserName(String s) {
+ put(PdfName.TU, new PdfString(s, PdfObject.TEXT_UNICODE));
+ }
+
+ public void setMappingName(String s) {
+ put(PdfName.TM, new PdfString(s, PdfObject.TEXT_UNICODE));
+ }
+
+ public void setQuadding(int v) {
+ put(PdfName.Q, new PdfNumber(v));
+ }
+
+ static void mergeResources(PdfDictionary result, PdfDictionary source, PdfStamperImp writer) {
+ PdfDictionary dic = null;
+ PdfDictionary res = null;
+ PdfName target = null;
+ for (int k = 0; k < mergeTarget.length; ++k) {
+ target = mergeTarget[k];
+ PdfDictionary pdfDict = (PdfDictionary)PdfReader.getPdfObject(source.get(target));
+ if ((dic = pdfDict) != null) {
+ if ((res = (PdfDictionary)PdfReader.getPdfObject(result.get(target), result)) == null) {
+ res = new PdfDictionary();
+ }
+ res.mergeDifferent(dic);
+ result.put(target, res);
+ if (writer != null)
+ writer.markUsed(res);
+ }
+ }
+ }
+
+ static void mergeResources(PdfDictionary result, PdfDictionary source) {
+ mergeResources(result, source, null);
+ }
+
+ void setUsed() {
+ used = true;
+ if (parent != null)
+ put(PdfName.PARENT, parent.getIndirectReference());
+ if (kids != null) {
+ PdfArray array = new PdfArray();
+ for (int k = 0; k < kids.size(); ++k)
+ array.add(((PdfFormField)kids.get(k)).getIndirectReference());
+ put(PdfName.KIDS, array);
+ }
+ if (templates == null)
+ return;
+ PdfDictionary dic = new PdfDictionary();
+ for (Iterator it = templates.keySet().iterator(); it.hasNext();) {
+ PdfTemplate template = (PdfTemplate)it.next();
+ mergeResources(dic, (PdfDictionary)template.getResources());
+ }
+ put(PdfName.DR, dic);
+ }
+
+ public static PdfAnnotation shallowDuplicate(PdfAnnotation annot) {
+ PdfAnnotation dup;
+ if (annot.isForm()) {
+ dup = new PdfFormField(annot.writer);
+ PdfFormField dupField = (PdfFormField)dup;
+ PdfFormField srcField = (PdfFormField)annot;
+ dupField.parent = srcField.parent;
+ dupField.kids = srcField.kids;
+ }
+ else
+ dup = new PdfAnnotation(annot.writer, null);
+ dup.merge(annot);
+ dup.form = annot.form;
+ dup.annotation = annot.annotation;
+ dup.templates = annot.templates;
+ return dup;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfFormXObject.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfFormXObject.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfFormXObject.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfFormXObject.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,93 @@
+/*
+ * $Id: PdfFormXObject.java,v 1.58 2005/07/16 16:49:22 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * PdfFormObject
is a type of XObject containing a template-object.
+ */
+
+public class PdfFormXObject extends PdfStream {
+
+ // public static final variables
+
+/** This is a PdfNumber representing 0. */
+ public static final PdfNumber ZERO = new PdfNumber(0);
+
+/** This is a PdfNumber representing 1. */
+ public static final PdfNumber ONE = new PdfNumber(1);
+
+/** This is the 1 - matrix. */
+ public static final PdfLiteral MATRIX = new PdfLiteral("[1 0 0 1 0 0]");
+
+ // membervariables
+
+
+ // constructor
+
+/**
+ * Constructs a PdfFormXObject
-object.
+ *
+ * @param template the template
+ */
+
+ PdfFormXObject(PdfTemplate template) // throws BadPdfFormatException
+ {
+ super();
+ put(PdfName.TYPE, PdfName.XOBJECT);
+ put(PdfName.SUBTYPE, PdfName.FORM);
+ put(PdfName.RESOURCES, template.getResources());
+ put(PdfName.BBOX, new PdfRectangle(template.getBoundingBox()));
+ put(PdfName.FORMTYPE, ONE);
+ if (template.getLayer() != null)
+ put(PdfName.OC, template.getLayer().getRef());
+ if (template.getGroup() != null)
+ put(PdfName.GROUP, template.getGroup());
+ PdfArray matrix = template.getMatrix();
+ if (matrix == null)
+ put(PdfName.MATRIX, MATRIX);
+ else
+ put(PdfName.MATRIX, matrix);
+ bytes = template.toPdf(null);
+ put(PdfName.LENGTH, new PdfNumber(bytes.length));
+ flateCompress();
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfFunction.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfFunction.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfFunction.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfFunction.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.ExceptionConverter;
+import java.io.IOException;
+/** Implements PDF functions.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfFunction {
+
+ protected PdfWriter writer;
+
+ protected PdfIndirectReference reference;
+
+ protected PdfDictionary dictionary;
+
+ /** Creates new PdfFunction */
+ protected PdfFunction(PdfWriter writer) {
+ this.writer = writer;
+ }
+
+ PdfIndirectReference getReference() {
+ try {
+ if (reference == null) {
+ reference = writer.addToBody(dictionary).getIndirectReference();
+ }
+ }
+ catch (IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ return reference;
+ }
+
+ public static PdfFunction type0(PdfWriter writer, float domain[], float range[], int size[],
+ int bitsPerSample, int order, float encode[], float decode[], byte stream[]) {
+ PdfFunction func = new PdfFunction(writer);
+ func.dictionary = new PdfStream(stream);
+ ((PdfStream)func.dictionary).flateCompress();
+ func.dictionary.put(PdfName.FUNCTIONTYPE, new PdfNumber(0));
+ func.dictionary.put(PdfName.m_DOMAIN, new PdfArray(domain)); // ssteward
+ func.dictionary.put(PdfName.RANGE, new PdfArray(range));
+ func.dictionary.put(PdfName.SIZE, new PdfArray(size));
+ func.dictionary.put(PdfName.BITSPERSAMPLE, new PdfNumber(bitsPerSample));
+ if (order != 1)
+ func.dictionary.put(PdfName.ORDER, new PdfNumber(order));
+ if (encode != null)
+ func.dictionary.put(PdfName.ENCODE, new PdfArray(encode));
+ if (decode != null)
+ func.dictionary.put(PdfName.DECODE, new PdfArray(decode));
+ return func;
+ }
+
+ public static PdfFunction type2(PdfWriter writer, float domain[], float range[], float c0[], float c1[], float n) {
+ PdfFunction func = new PdfFunction(writer);
+ func.dictionary = new PdfDictionary();
+ func.dictionary.put(PdfName.FUNCTIONTYPE, new PdfNumber(2));
+ func.dictionary.put(PdfName.m_DOMAIN, new PdfArray(domain)); // ssteward
+ if (range != null)
+ func.dictionary.put(PdfName.RANGE, new PdfArray(range));
+ if (c0 != null)
+ func.dictionary.put(PdfName.C0, new PdfArray(c0));
+ if (c1 != null)
+ func.dictionary.put(PdfName.C1, new PdfArray(c1));
+ func.dictionary.put(PdfName.N, new PdfNumber(n));
+ return func;
+ }
+
+ public static PdfFunction type3(PdfWriter writer, float domain[], float range[], PdfFunction functions[], float bounds[], float encode[]) {
+ PdfFunction func = new PdfFunction(writer);
+ func.dictionary = new PdfDictionary();
+ func.dictionary.put(PdfName.FUNCTIONTYPE, new PdfNumber(3));
+ func.dictionary.put(PdfName.m_DOMAIN, new PdfArray(domain)); // ssteward
+ if (range != null)
+ func.dictionary.put(PdfName.RANGE, new PdfArray(range));
+ PdfArray array = new PdfArray();
+ for (int k = 0; k < functions.length; ++k)
+ array.add(functions[k].getReference());
+ func.dictionary.put(PdfName.FUNCTIONS, array);
+ func.dictionary.put(PdfName.BOUNDS, new PdfArray(bounds));
+ func.dictionary.put(PdfName.ENCODE, new PdfArray(encode));
+ return func;
+ }
+
+ public static PdfFunction type4(PdfWriter writer, float domain[], float range[], String postscript) {
+ byte b[] = new byte[postscript.length()];
+ for (int k = 0; k < b.length; ++k)
+ b[k] = (byte)postscript.charAt(k);
+ PdfFunction func = new PdfFunction(writer);
+ func.dictionary = new PdfStream(b);
+ ((PdfStream)func.dictionary).flateCompress();
+ func.dictionary.put(PdfName.FUNCTIONTYPE, new PdfNumber(4));
+ func.dictionary.put(PdfName.m_DOMAIN, new PdfArray(domain)); // ssteward
+ func.dictionary.put(PdfName.RANGE, new PdfArray(range));
+ return func;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfGState.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfGState.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfGState.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfGState.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+/** The graphic state dictionary.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfGState extends PdfDictionary {
+ /** A possible blend mode */
+ public static final PdfName BM_NORMAL = new PdfName("Normal");
+ /** A possible blend mode */
+ public static final PdfName BM_COMPATIBLE = new PdfName("Compatible");
+ /** A possible blend mode */
+ public static final PdfName BM_MULTIPLY = new PdfName("Multiply");
+ /** A possible blend mode */
+ public static final PdfName BM_SCREEN = new PdfName("Screen");
+ /** A possible blend mode */
+ public static final PdfName BM_OVERLAY = new PdfName("Overlay");
+ /** A possible blend mode */
+ public static final PdfName BM_DARKEN = new PdfName("Darken");
+ /** A possible blend mode */
+ public static final PdfName BM_LIGHTEN = new PdfName("Lighten");
+ /** A possible blend mode */
+ public static final PdfName BM_COLORDODGE = new PdfName("ColorDodge");
+ /** A possible blend mode */
+ public static final PdfName BM_COLORBURN = new PdfName("ColorBurn");
+ /** A possible blend mode */
+ public static final PdfName BM_HARDLIGHT = new PdfName("HardLight");
+ /** A possible blend mode */
+ public static final PdfName BM_SOFTLIGHT = new PdfName("SoftLight");
+ /** A possible blend mode */
+ public static final PdfName BM_DIFFERENCE = new PdfName("Difference");
+ /** A possible blend mode */
+ public static final PdfName BM_EXCLUSION = new PdfName("Exclusion");
+
+ /**
+ * Sets the flag whether to apply overprint for stroking.
+ * @param ov
+ */
+ public void setOverPrintStroking(boolean ov) {
+ put(PdfName.OP, ov ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
+ }
+
+ /**
+ * Sets the flag whether to apply overprint for non stroking painting operations.
+ * @param ov
+ */
+ public void setOverPrintNonStroking(boolean ov) {
+ put(PdfName.op, ov ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
+ }
+
+ /**
+ * Sets the current stroking alpha constant, specifying the constant shape or
+ * constant opacity value to be used for stroking operations in the transparent
+ * imaging model.
+ * @param n
+ */
+ public void setStrokeOpacity(float n) {
+ put(PdfName.CA, new PdfNumber(n));
+ }
+
+ /**
+ * Sets the current stroking alpha constant, specifying the constant shape or
+ * constant opacity value to be used for nonstroking operations in the transparent
+ * imaging model.
+ * @param n
+ */
+ public void setFillOpacity(float n) {
+ put(PdfName.ca, new PdfNumber(n));
+ }
+
+ /**
+ * The alpha source flag specifying whether the current soft mask
+ * and alpha constant are to be interpreted as shape values (true)
+ * or opacity values (false).
+ * @param v
+ */
+ public void setAlphaIsShape(boolean v) {
+ put(PdfName.AIS, v ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
+ }
+
+ /**
+ * Determines the behaviour of overlapping glyphs within a text object
+ * in the transparent imaging model.
+ * @param v
+ */
+ public void setTextKnockout(boolean v) {
+ put(PdfName.TK, v ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
+ }
+
+ /**
+ * The current blend mode to be used in the transparent imaging model.
+ * @param bm
+ */
+ public void setBlendMode(PdfName bm) {
+ put(PdfName.BM, bm);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfImportedPage.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfImportedPage.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfImportedPage.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfImportedPage.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,140 @@
+/*
+ * $Id: PdfImportedPage.java,v 1.14 2002/06/20 13:30:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+// import pdftk.com.lowagie.text.Image; ssteward: dropped in 1.44
+import java.io.IOException;
+
+/** Represents an imported page.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfImportedPage extends pdftk.com.lowagie.text.pdf.PdfTemplate {
+
+ PdfReaderInstance readerInstance;
+ int pageNumber;
+
+ PdfImportedPage(PdfReaderInstance readerInstance, PdfWriter writer, int pageNumber) {
+ this.readerInstance = readerInstance;
+ this.pageNumber = pageNumber;
+ thisReference = writer.getPdfIndirectReference();
+ bBox = readerInstance.getReader().getPageSize(pageNumber);
+ type = TYPE_IMPORTED;
+ }
+
+ /** Reads the content from this PdfImportedPage
-object from a reader.
+ *
+ * @return self
+ *
+ */
+ public PdfImportedPage getFromReader() {
+ return this;
+ }
+
+ public int getPageNumber() {
+ return pageNumber;
+ }
+
+
+ /** Always throws an error. This operation is not allowed.
+ * @param image dummy
+ * @param a dummy
+ * @param b dummy
+ * @param c dummy
+ * @param d dummy
+ * @param e dummy
+ * @param f dummy
+ * @throws DocumentException dummy */
+ /* ssteward: dropped in 1.44
+ public void addImage(Image image, float a, float b, float c, float d, float e, float f) throws DocumentException {
+ throwError();
+ }
+ */
+
+ /** Always throws an error. This operation is not allowed.
+ * @param template dummy
+ * @param a dummy
+ * @param b dummy
+ * @param c dummy
+ * @param d dummy
+ * @param e dummy
+ * @param f dummy */
+ public void addTemplate(PdfTemplate template, float a, float b, float c, float d, float e, float f) {
+ throwError();
+ }
+
+ /** Always throws an error. This operation is not allowed.
+ * @return dummy */
+ public PdfContentByte getDuplicate() {
+ throwError();
+ return null;
+ }
+
+ PdfStream getFormXObject() throws IOException {
+ return readerInstance.getFormXObject(pageNumber);
+ }
+
+ public void setColorFill(PdfSpotColor sp, float tint) {
+ throwError();
+ }
+
+ public void setColorStroke(PdfSpotColor sp, float tint) {
+ throwError();
+ }
+
+ PdfObject getResources() {
+ return readerInstance.getResources(pageNumber);
+ }
+
+ /** Always throws an error. This operation is not allowed.
+ * @param bf dummy
+ * @param size dummy */
+ public void setFontAndSize(BaseFont bf, float size) {
+ throwError();
+ }
+
+ void throwError() {
+ throw new RuntimeException("Content can not be added to a PdfImportedPage.");
+ }
+
+ PdfReaderInstance getPdfReaderInstance() {
+ return readerInstance;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfIndirectObject.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfIndirectObject.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfIndirectObject.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfIndirectObject.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,162 @@
+/*
+ * $Id: PdfIndirectObject.java,v 1.35 2003/05/02 09:01:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import pdftk.com.lowagie.text.DocWriter;
+
+/**
+ * PdfIndirectObject
is the Pdf indirect object.
+ *
+ * An indirect object is an object that has been labeled so that it can be referenced by
+ * other objects. Any type of PdfObject
may be labeled as an indirect object.
+ * An indirect object consists of an object identifier, a direct object, and the endobj
+ * keyword. The object identifier consists of an integer object number , an integer
+ * generation number , and the obj keyword.
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.10 (page 53).
+ *
+ * @see PdfObject
+ * @see PdfIndirectReference
+ */
+
+public class PdfIndirectObject {
+
+ // membervariables
+
+/** The object number */
+ protected int number;
+
+/** the generation number */
+ protected int generation = 0;
+
+ static final byte STARTOBJ[] = DocWriter.getISOBytes(" obj "); // ssteward
+ static final byte ENDOBJ[] = DocWriter.getISOBytes("\nendobj "); // ssteward
+ static final int SIZEOBJ = STARTOBJ.length + ENDOBJ.length;
+ PdfObject object;
+ PdfWriter writer;
+
+ // constructors
+
+/**
+ * Constructs a PdfIndirectObject
.
+ *
+ * @param number the object number
+ * @param object the direct object
+ */
+
+ PdfIndirectObject(int number, PdfObject object, PdfWriter writer) {
+ this(number, 0, object, writer);
+ }
+
+ PdfIndirectObject(PdfIndirectReference ref, PdfObject object, PdfWriter writer) {
+ this(ref.getNumber(),ref.getGeneration(),object,writer);
+ }
+/**
+ * Constructs a PdfIndirectObject
.
+ *
+ * @param number the object number
+ * @param generation the generation number
+ * @param object the direct object
+ */
+
+ PdfIndirectObject(int number, int generation, PdfObject object, PdfWriter writer) {
+ this.writer = writer;
+ this.number = number;
+ this.generation = generation;
+ this.object = object;
+ PdfEncryption crypto = null;
+ if (writer != null)
+ crypto = writer.getEncryption();
+ if (crypto != null) {
+ crypto.setHashKey(number, generation);
+ }
+ }
+
+ // methods
+
+/**
+ * Return the length of this PdfIndirectObject
.
+ *
+ * @return the length of the PDF-representation of this indirect object.
+ */
+
+// public int length() {
+// if (isStream)
+// return bytes.size() + SIZEOBJ + stream.getStreamLength(writer);
+// else
+// return bytes.size();
+// }
+
+
+/**
+ * Returns a PdfIndirectReference
to this PdfIndirectObject
.
+ *
+ * @return a PdfIndirectReference
+ */
+
+ public PdfIndirectReference getIndirectReference() {
+ return new PdfIndirectReference(object.type(), number, generation);
+ }
+
+/**
+ * Writes eficiently to a stream
+ *
+ * @param os the stream to write to
+ * @throws IOException on write error
+ */
+ void writeTo(OutputStream os) throws IOException
+ {
+ // ssteward: don't os.write() anything here, before the number, or you'll throw off the xref position
+ os.write(DocWriter.getISOBytes(String.valueOf(number)));
+ os.write(' ');
+ os.write(DocWriter.getISOBytes(String.valueOf(generation)));
+ os.write(STARTOBJ);
+ // ssteward
+ //int type = object.type();
+ //if (type != PdfObject.ARRAY && type != PdfObject.DICTIONARY && type != PdfObject.NAME && type != PdfObject.STRING)
+ // os.write(' ');
+ object.toPdf(writer, os);
+ os.write(ENDOBJ);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfIndirectReference.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfIndirectReference.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfIndirectReference.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfIndirectReference.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,119 @@
+/*
+ * $Id: PdfIndirectReference.java,v 1.22 2002/06/20 13:30:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * PdfIndirectReference
contains a reference to a PdfIndirectObject
.
+ *
+ * Any object used as an element of an array or as a value in a dictionary may be specified
+ * by either a direct object of an indirect reference. An indirect reference is a reference
+ * to an indirect object, and consists of the indirect object's object number, generation number
+ * and the R keyword.
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.11 (page 54).
+ *
+ * @see PdfObject
+ * @see PdfIndirectObject
+ */
+
+public class PdfIndirectReference extends PdfObject {
+
+ // membervariables
+
+/** the object number */
+ protected int number;
+
+/** the generation number */
+ protected int generation = 0;
+
+ // constructors
+
+ protected PdfIndirectReference() {
+ super(0);
+ }
+
+/**
+ * Constructs a PdfIndirectReference
.
+ *
+ * @param type the type of the PdfObject
that is referenced to
+ * @param number the object number.
+ * @param generation the generation number.
+ */
+
+ PdfIndirectReference(int type, int number, int generation) {
+ super(0, new StringBuffer().append(number).append(" ").append(generation).append(" R").toString());
+ this.number = number;
+ this.generation = generation;
+ }
+
+/**
+ * Constructs a PdfIndirectReference
.
+ *
+ * @param type the type of the PdfObject
that is referenced to
+ * @param number the object number.
+ */
+
+ PdfIndirectReference(int type, int number) {
+ this(type, number, 0);
+ }
+
+ // methods
+
+/**
+ * Returns the number of the object.
+ *
+ * @return a number.
+ */
+
+ public int getNumber() {
+ return number;
+ }
+
+/**
+ * Returns the generation of the object.
+ *
+ * @return a number.
+ */
+
+ public int getGeneration() {
+ return generation;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfLayer.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfLayer.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfLayer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfLayer.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+/**
+ * An optional content group is a dictionary representing a collection of graphics
+ * that can be made visible or invisible dynamically by users of viewer applications.
+ * In iText they are referenced as layers.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfLayer extends PdfDictionary implements PdfOCG {
+ protected PdfIndirectReference ref;
+ protected ArrayList children;
+ protected PdfLayer parent;
+ protected String title;
+
+ /**
+ * Holds value of property on.
+ */
+ private boolean on = true;
+
+ /**
+ * Holds value of property onPanel.
+ */
+ private boolean onPanel = true;
+
+ PdfLayer(String title) {
+ this.title = title;
+ }
+
+ /**
+ * Creates a title layer. A title layer is not really a layer but a collection of layers
+ * under the same title heading.
+ * @param title the title text
+ * @param writer the PdfWriter
+ * @return the title layer
+ */
+ public static PdfLayer createTitle(String title, PdfWriter writer) {
+ if (title == null)
+ throw new NullPointerException("Title cannot be null.");
+ PdfLayer layer = new PdfLayer(title);
+ writer.registerLayer(layer);
+ return layer;
+ }
+ /**
+ * Creates a new layer.
+ * @param name the name of the layer
+ * @param writer the writer
+ */
+ public PdfLayer(String name, PdfWriter writer) {
+ super(PdfName.OCG);
+ setName(name);
+ ref = writer.getPdfIndirectReference();
+ writer.registerLayer(this);
+ }
+
+ String getTitle() {
+ return title;
+ }
+
+ /**
+ * Adds a child layer. Nested layers can only have one parent.
+ * @param child the child layer
+ */
+ public void addChild(PdfLayer child) {
+ if (child.parent != null)
+ throw new IllegalArgumentException("The layer '" + ((PdfString)child.get(PdfName.NAME)).toUnicodeString() + "' already has a parent.");
+ child.parent = this;
+ if (children == null)
+ children = new ArrayList();
+ children.add(child);
+ }
+
+
+ /**
+ * Gets the parent layer.
+ * @return the parent layer or null
if the layer has no parent
+ */
+ public PdfLayer getParent() {
+ return parent;
+ }
+
+ /**
+ * Gets the children layers.
+ * @return the children layers or null
if the layer has no children
+ */
+ public ArrayList getChildren() {
+ return children;
+ }
+
+ /**
+ * Gets the PdfIndirectReference
that represents this layer.
+ * @return the PdfIndirectReference
that represents this layer
+ */
+ public PdfIndirectReference getRef() {
+ return ref;
+ }
+
+ /**
+ * Sets the name of this layer.
+ * @param name the name of this layer
+ */
+ public void setName(String name) {
+ put(PdfName.NAME, new PdfString(name, PdfObject.TEXT_UNICODE));
+ }
+
+ /**
+ * Gets the dictionary representing the layer. It just returns this
.
+ * @return the dictionary representing the layer
+ */
+ public PdfObject getPdfObject() {
+ return this;
+ }
+
+ /**
+ * Gets the initial visibility of the layer.
+ * @return the initial visibility of the layer
+ */
+ public boolean isOn() {
+ return this.on;
+ }
+
+ /**
+ * Sets the initial visibility of the layer.
+ * @param on the initial visibility of the layer
+ */
+ public void setOn(boolean on) {
+ this.on = on;
+ }
+
+ private PdfDictionary getUsage() {
+ PdfDictionary usage = (PdfDictionary)get(PdfName.USAGE);
+ if (usage == null) {
+ usage = new PdfDictionary();
+ put(PdfName.USAGE, usage);
+ }
+ return usage;
+ }
+
+ /**
+ * Used by the creating application to store application-specific
+ * data associated with this optional content group.
+ * @param creator a text string specifying the application that created the group
+ * @param subtype a string defining the type of content controlled by the group. Suggested
+ * values include but are not limited to Artwork , for graphic-design or publishing
+ * applications, and Technical , for technical designs such as building plans or
+ * schematics
+ */
+ public void setCreatorInfo(String creator, String subtype) {
+ PdfDictionary usage = getUsage();
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.CREATOR, new PdfString(creator, PdfObject.TEXT_UNICODE));
+ dic.put(PdfName.SUBTYPE, new PdfName(subtype));
+ usage.put(PdfName.CREATORINFO, dic);
+ }
+
+ /**
+ * Specifies the language of the content controlled by this
+ * optional content group
+ * @param lang a language string which specifies a language and possibly a locale
+ * (for example, es-MX represents Mexican Spanish)
+ * @param preferred used by viewer applications when there is a partial match but no exact
+ * match between the system language and the language strings in all usage dictionaries
+ */
+ public void setLanguage(String lang, boolean preferred) {
+ PdfDictionary usage = getUsage();
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.LANG, new PdfString(lang, PdfObject.TEXT_UNICODE));
+ if (preferred)
+ dic.put(PdfName.PREFERRED, PdfName.ON);
+ usage.put(PdfName.LANGUAGE, dic);
+ }
+
+ /**
+ * Specifies the recommended state for content in this
+ * group when the document (or part of it) is saved by a viewer application to a format
+ * that does not support optional content (for example, an earlier version of
+ * PDF or a raster image format).
+ * @param export the export state
+ */
+ public void setExport(boolean export) {
+ PdfDictionary usage = getUsage();
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.EXPORTSTATE, export ? PdfName.ON : PdfName.OFF);
+ usage.put(PdfName.EXPORT, dic);
+ }
+
+ /**
+ * Specifies a range of magnifications at which the content
+ * in this optional content group is best viewed.
+ * @param min the minimum recommended magnification factors at which the group
+ * should be ON. A negative value will set the default to 0
+ * @param max the maximum recommended magnification factor at which the group
+ * should be ON. A negative value will set the largest possible magnification supported by the
+ * viewer application
+ */
+ public void setZoom(float min, float max) {
+ if (min <= 0 && max < 0)
+ return;
+ PdfDictionary usage = getUsage();
+ PdfDictionary dic = new PdfDictionary();
+ if (min > 0)
+ dic.put(PdfName.MIN_LOWER_CASE, new PdfNumber(min));
+ if (max >= 0)
+ dic.put(PdfName.MAX_LOWER_CASE, new PdfNumber(max));
+ usage.put(PdfName.ZOOM, dic);
+ }
+
+ /**
+ * Specifies that the content in this group is intended for
+ * use in printing
+ * @param subtype a name specifying the kind of content controlled by the group;
+ * for example, Trapping , PrintersMarks and Watermark
+ * @param printstate indicates that the group should be
+ * set to that state when the document is printed from a viewer application
+ */
+ public void setPrint(String subtype, boolean printstate) {
+ PdfDictionary usage = getUsage();
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.SUBTYPE, new PdfName(subtype));
+ dic.put(PdfName.PRINTSTATE, printstate ? PdfName.ON : PdfName.OFF);
+ usage.put(PdfName.PRINT, dic);
+ }
+
+ /**
+ * Indicates that the group should be set to that state when the
+ * document is opened in a viewer application.
+ * @param view the view state
+ */
+ public void setView(boolean view) {
+ PdfDictionary usage = getUsage();
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.VIEWSTATE, view ? PdfName.ON : PdfName.OFF);
+ usage.put(PdfName.VIEW, dic);
+ }
+
+ /**
+ * Gets the layer visibility in Acrobat's layer panel
+ * @return the layer visibility in Acrobat's layer panel
+ */
+ public boolean isOnPanel() {
+ return this.onPanel;
+ }
+
+ /**
+ * Sets the visibility of the layer in Acrobat's layer panel. If false
+ * the layer cannot be directly manipulated by the user. Note that any children layers will
+ * also be absent from the panel.
+ * @param onPanel the visibility of the layer in Acrobat's layer panel
+ */
+ public void setOnPanel(boolean onPanel) {
+ this.onPanel = onPanel;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfLayerMembership.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfLayerMembership.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfLayerMembership.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfLayerMembership.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.HashSet;
+import java.util.Collection;
+
+/**
+ * Content typically belongs to a single optional content group,
+ * and is visible when the group is ON and invisible when it is OFF . To express more
+ * complex visibility policies, content should not declare itself to belong to an optional
+ * content group directly, but rather to an optional content membership dictionary
+ * represented by this class.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfLayerMembership extends PdfDictionary implements PdfOCG {
+
+ /**
+ * Visible only if all of the entries are ON .
+ */
+ public static PdfName ALLON = new PdfName("AllOn");
+ /**
+ * Visible if any of the entries are ON .
+ */
+ public static PdfName ANYON = new PdfName("AnyOn");
+ /**
+ * Visible if any of the entries are OFF .
+ */
+ public static PdfName ANYOFF = new PdfName("AnyOff");
+ /**
+ * Visible only if all of the entries are OFF .
+ */
+ public static PdfName ALLOFF = new PdfName("AllOff");
+
+ PdfIndirectReference ref;
+ PdfArray members = new PdfArray();
+ HashSet layers = new HashSet();
+
+ /**
+ * Creates a new, empty, membership layer.
+ * @param writer the writer
+ */
+ public PdfLayerMembership(PdfWriter writer) {
+ super(PdfName.OCMD);
+ put(PdfName.OCGS, members);
+ ref = writer.getPdfIndirectReference();
+ }
+
+ /**
+ * Gets the PdfIndirectReference
that represents this membership layer.
+ * @return the PdfIndirectReference
that represents this layer
+ */
+ public PdfIndirectReference getRef() {
+ return ref;
+ }
+
+ /**
+ * Adds a new member to the layer.
+ * @param layer the new member to the layer
+ */
+ public void addMember(PdfLayer layer) {
+ if (!layers.contains(layer)) {
+ members.add(layer.getRef());
+ layers.add(layer);
+ }
+ }
+
+ /**
+ * Gets the member layers.
+ * @return the member layers
+ */
+ public Collection getLayers() {
+ return layers;
+ }
+
+ /**
+ * Sets the visibility policy for content belonging to this
+ * membership dictionary. Possible values are ALLON, ANYON, ANYOFF and ALLOFF.
+ * The default value is ANYON.
+ * @param type the visibility policy
+ */
+ public void setVisibilityPolicy(PdfName type) {
+ put(PdfName.P, type);
+ }
+
+ /**
+ * Gets the dictionary representing the membership layer. It just returns this
.
+ * @return the dictionary representing the layer
+ */
+ public PdfObject getPdfObject() {
+ return this;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfLine.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfLine.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfLine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfLine.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,478 @@
+/*
+ * $Id: PdfLine.java,v 1.65 2005/04/08 07:33:22 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import pdftk.com.lowagie.text.Element;
+import pdftk.com.lowagie.text.ListItem;
+
+/**
+ * PdfLine
defines an array with PdfChunk
-objects
+ * that fit into 1 line.
+ */
+
+public class PdfLine {
+
+ // membervariables
+
+ /** The arraylist containing the chunks. */
+ protected ArrayList line;
+
+ /** The left indentation of the line. */
+ protected float left;
+
+ /** The width of the line. */
+ protected float width;
+
+ /** The alignment of the line. */
+ protected int alignment;
+
+ /** The heigth of the line. */
+ protected float height;
+
+ /** The listsymbol (if necessary). */
+ protected PdfChunk listSymbol = null;
+
+ /** The listsymbol (if necessary). */
+ protected float symbolIndent;
+
+ /** true
if the chunk splitting was caused by a newline. */
+ protected boolean newlineSplit = false;
+
+ /** The original width. */
+ protected float originalWidth;
+
+ protected boolean isRTL = false;
+
+ // constructors
+
+ /**
+ * Constructs a new PdfLine
-object.
+ *
+ * @param left the limit of the line at the left
+ * @param right the limit of the line at the right
+ * @param alignment the alignment of the line
+ * @param height the height of the line
+ */
+
+ PdfLine(float left, float right, int alignment, float height) {
+ this.left = left;
+ this.width = right - left;
+ this.originalWidth = this.width;
+ this.alignment = alignment;
+ this.height = height;
+ this.line = new ArrayList();
+ }
+
+ PdfLine(float left, float remainingWidth, int alignment, boolean newlineSplit, ArrayList line, boolean isRTL) {
+ this.left = left;
+ this.width = remainingWidth;
+ this.alignment = alignment;
+ this.line = line;
+ this.newlineSplit = newlineSplit;
+ this.isRTL = isRTL;
+ }
+
+ // methods
+
+ /**
+ * Adds a PdfChunk
to the PdfLine
.
+ *
+ * @param chunk the PdfChunk
to add
+ * @return null
if the chunk could be added completely; if not
+ * a PdfChunk
containing the part of the chunk that could
+ * not be added is returned
+ */
+
+ PdfChunk add(PdfChunk chunk) {
+ // nothing happens if the chunk is null.
+ if (chunk == null || chunk.toString().equals("")) {
+ return null;
+ }
+
+ // we split the chunk to be added
+ PdfChunk overflow = chunk.split(width);
+ newlineSplit = (chunk.isNewlineSplit() || overflow == null);
+ // if (chunk.isNewlineSplit() && alignment == Element.ALIGN_JUSTIFIED)
+ // alignment = Element.ALIGN_LEFT;
+
+
+ // if the length of the chunk > 0 we add it to the line
+ if (chunk.length() > 0) {
+ if (overflow != null)
+ chunk.trimLastSpace();
+ width -= chunk.width();
+ line.add(chunk);
+ }
+
+ // if the length == 0 and there were no other chunks added to the line yet,
+ // we risk to end up in an endless loop trying endlessly to add the same chunk
+ else if (line.size() < 1) {
+ chunk = overflow;
+ overflow = chunk.truncate(width);
+ width -= chunk.width();
+ if (chunk.length() > 0) {
+ line.add(chunk);
+ return overflow;
+ }
+ // if the chunck couldn't even be truncated, we add everything, so be it
+ else {
+ if (overflow != null)
+ line.add(overflow);
+ return null;
+ }
+ }
+ else {
+ width += ((PdfChunk)(line.get(line.size() - 1))).trimLastSpace();
+ }
+ return overflow;
+ }
+
+ // methods to retrieve information
+
+ /**
+ * Returns the number of chunks in the line.
+ *
+ * @return a value
+ */
+
+ public int size() {
+ return line.size();
+ }
+
+ /**
+ * Returns an iterator of PdfChunk
s.
+ *
+ * @return an Iterator
+ */
+
+ public Iterator iterator() {
+ return line.iterator();
+ }
+
+ /**
+ * Returns the height of the line.
+ *
+ * @return a value
+ */
+
+ float height() {
+ return height;
+ }
+
+ /**
+ * Returns the left indentation of the line taking the alignment of the line into account.
+ *
+ * @return a value
+ */
+
+ float indentLeft() {
+ if (isRTL) {
+ switch (alignment) {
+ case Element.ALIGN_LEFT:
+ return left + width;
+ case Element.ALIGN_CENTER:
+ return left + (width / 2f);
+ default:
+ return left;
+ }
+ }
+ else {
+ switch (alignment) {
+ case Element.ALIGN_RIGHT:
+ return left + width;
+ case Element.ALIGN_CENTER:
+ return left + (width / 2f);
+ default:
+ return left;
+ }
+ }
+ }
+
+ /**
+ * Checks if this line has to be justified.
+ *
+ * @return true
if the alignment equals ALIGN_JUSTIFIED and there is some width left.
+ */
+
+ public boolean hasToBeJustified() {
+ return ((alignment == Element.ALIGN_JUSTIFIED || alignment == Element.ALIGN_JUSTIFIED_ALL) && width != 0);
+ }
+
+ /**
+ * Resets the alignment of this line.
+ *
+ * The alignment of the last line of for instance a Paragraph
+ * that has to be justified, has to be reset to ALIGN_LEFT .
+ */
+
+ public void resetAlignment() {
+ if (alignment == Element.ALIGN_JUSTIFIED) {
+ alignment = Element.ALIGN_LEFT;
+ }
+ }
+
+ /**
+ * Returns the width that is left, after a maximum of characters is added to the line.
+ *
+ * @return a value
+ */
+
+ float widthLeft() {
+ return width;
+ }
+
+ /**
+ * Returns the number of space-characters in this line.
+ *
+ * @return a value
+ */
+
+ int numberOfSpaces() {
+ String string = toString();
+ int length = string.length();
+ int numberOfSpaces = 0;
+ for (int i = 0; i < length; i++) {
+ if (string.charAt(i) == ' ') {
+ numberOfSpaces++;
+ }
+ }
+ return numberOfSpaces;
+ }
+
+ /**
+ * Sets the listsymbol of this line.
+ *
+ * This is only necessary for the first line of a ListItem
.
+ *
+ * @param listItem the list symbol
+ */
+
+ public void setListItem(ListItem listItem) {
+ this.listSymbol = new PdfChunk(listItem.listSymbol(), null);
+ this.symbolIndent = listItem.indentationLeft();
+ }
+
+ /**
+ * Returns the listsymbol of this line.
+ *
+ * @return a PdfChunk
if the line has a listsymbol; null
otherwise
+ */
+
+ public PdfChunk listSymbol() {
+ return listSymbol;
+ }
+
+ /**
+ * Return the indentation needed to show the listsymbol.
+ *
+ * @return a value
+ */
+
+ public float listIndent() {
+ return symbolIndent;
+ }
+
+ /**
+ * Get the string representation of what is in this line.
+ *
+ * @return a String
+ */
+
+ public String toString() {
+ StringBuffer tmp = new StringBuffer();
+ for (Iterator i = line.iterator(); i.hasNext(); ) {
+ tmp.append(((PdfChunk) i.next()).toString());
+ }
+ return tmp.toString();
+ }
+
+ /**
+ * Checks if a newline caused the line split.
+ * @return true
if a newline caused the line split
+ */
+ public boolean isNewlineSplit() {
+ return newlineSplit && (alignment != Element.ALIGN_JUSTIFIED_ALL);
+ }
+
+ /**
+ * Gets the index of the last PdfChunk
with metric attributes
+ * @return the last PdfChunk
with metric attributes
+ */
+ public int getLastStrokeChunk() {
+ int lastIdx = line.size() - 1;
+ for (; lastIdx >= 0; --lastIdx) {
+ PdfChunk chunk = (PdfChunk)line.get(lastIdx);
+ if (chunk.isStroked())
+ break;
+ }
+ return lastIdx;
+ }
+
+ /**
+ * Gets a PdfChunk
by index.
+ * @param idx the index
+ * @return the PdfChunk
or null if beyond the array
+ */
+ public PdfChunk getChunk(int idx) {
+ if (idx < 0 || idx >= line.size())
+ return null;
+ return (PdfChunk)line.get(idx);
+ }
+
+ /**
+ * Gets the original width of the line.
+ * @return the original width of the line
+ */
+ public float getOriginalWidth() {
+ return originalWidth;
+ }
+
+ /**
+ * Gets the maximum size of all the fonts used in this line
+ * including images (if there are images in the line and if
+ * the leading has to be changed).
+ * @return maximum size of all the fonts used in this line
+ */
+ float getMaxSize() {
+ float maxSize = 0;
+ for (int k = 0; k < line.size(); ++k) {
+ PdfChunk chunk = (PdfChunk)line.get(k);
+ if ( /*!chunk.isImage() ssteward: dropped in 1.44 */ true || !chunk.changeLeading()) {
+ maxSize = Math.max(chunk.font().size(), maxSize);
+ }
+ /* ssteward: dropped in 1.44
+ else {
+ maxSize = Math.max(chunk.getImage().scaledHeight() + chunk.getImageOffsetY() , maxSize);
+ }
+ */
+ }
+ return maxSize;
+ }
+
+ /**
+ * Gets the maximum size of all the fonts used in this line
+ * including images.
+ * @return maximum size of all the fonts used in this line
+ */
+ float getMaxSizeSimple() {
+ float maxSize = 0;
+ for (int k = 0; k < line.size(); ++k) {
+ PdfChunk chunk = (PdfChunk)line.get(k);
+ if ( /*!chunk.isImage() ssteward: dropped in 1.44 */ true ) {
+ maxSize = Math.max(chunk.font().size(), maxSize);
+ }
+ /* ssteward: dropped in 1.44
+ else {
+ maxSize = Math.max(chunk.getImage().scaledHeight() + chunk.getImageOffsetY() , maxSize);
+ }
+ */
+ }
+ return maxSize;
+ }
+
+ boolean isRTL() {
+ return isRTL;
+ }
+
+ /**
+ * Gets a width corrected with a charSpacing and wordSpacing.
+ * @param charSpacing
+ * @param wordSpacing
+ * @return a corrected width
+ */
+ public float getWidthCorrected(float charSpacing, float wordSpacing) {
+ float total = 0;
+ for (int k = 0; k < line.size(); ++k) {
+ PdfChunk ck = (PdfChunk)line.get(k);
+ total += ck.getWidthCorrected(charSpacing, wordSpacing);
+ }
+ return total;
+ }
+
+/**
+ * Gets the maximum size of the ascender for all the fonts used
+ * in this line.
+ * @return maximum size of all the ascenders used in this line
+ */
+ public float getAscender() {
+ float ascender = 0;
+ for (int k = 0; k < line.size(); ++k) {
+ PdfChunk ck = (PdfChunk)line.get(k);
+ /* ssteward: dropped in 1.44
+ if (ck.isImage())
+ ascender = Math.max(ascender, ck.getImage().scaledHeight() + ck.getImageOffsetY());
+ else {
+ */
+ PdfFont font = ck.font();
+ ascender = Math.max(ascender, font.getFont().getFontDescriptor(BaseFont.ASCENT, font.size()));
+ /*
+ }
+ */
+ }
+ return ascender;
+ }
+
+/**
+ * Gets the biggest descender for all the fonts used
+ * in this line. Note that this is a negative number.
+ * @return maximum size of all the ascenders used in this line
+ */
+ public float getDescender() {
+ float descender = 0;
+ for (int k = 0; k < line.size(); ++k) {
+ PdfChunk ck = (PdfChunk)line.get(k);
+ /* ssteward: dropped in 1.44
+ if (ck.isImage())
+ descender = Math.min(descender, ck.getImageOffsetY());
+ else {
+ */
+ PdfFont font = ck.font();
+ descender = Math.min(descender, font.getFont().getFontDescriptor(BaseFont.DESCENT, font.size()));
+ /*
+ }
+ */
+ }
+ return descender;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfLister.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfLister.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfLister.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfLister.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,177 @@
+/*
+ * $Id: PdfLister.java,v 1.33 2005/02/01 14:30:50 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * This class by Mark Thompson. Copyright (C) 2002 Mark Thompson
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+ package pdftk.com.lowagie.text.pdf;
+
+import java.io.*;
+import java.util.Iterator;
+/**
+ * List a PDF file in human-readable form (for debugging reasons mostly)
+ * @author Mark Thompson
+ */
+
+public class PdfLister {
+
+ /** the printStream you want to write the output to. */
+ PrintStream out;
+
+ /**
+ * Create a new lister object.
+ * @param out
+ */
+ public PdfLister(PrintStream out) {
+ this.out = out;
+ }
+
+ /**
+ * Visualizes a PDF object.
+ * @param object a pdftk.com.lowagie.text.pdf object
+ */
+ public void listAnyObject(PdfObject object)
+ {
+ switch (object.type()) {
+ case PdfObject.ARRAY:
+ listArray((PdfArray)object);
+ break;
+ case PdfObject.DICTIONARY:
+ listDict((PdfDictionary) object);
+ break;
+ case PdfObject.STRING:
+ out.println("(" + object.toString() + ")");
+ break;
+ default:
+ out.println(object.toString());
+ break;
+ }
+ }
+ /**
+ * Visualizes a PdfDictionary object.
+ * @param dictionary a pdftk.com.lowagie.text.pdf.PdfDictionary object
+ */
+ public void listDict(PdfDictionary dictionary)
+ {
+ out.println("<<");
+ PdfName key;
+ PdfObject value;
+ for (Iterator i = dictionary.getKeys().iterator(); i.hasNext(); ) {
+ key = (PdfName) i.next();
+ value = (PdfObject) dictionary.get(key);
+ out.print(key.toString());
+ out.print(' ');
+ listAnyObject(value);
+ }
+ out.println(">>");
+ }
+
+ /**
+ * Visualizes a PdfArray object.
+ * @param array a pdftk.com.lowagie.text.pdf.PdfArray object
+ */
+ public void listArray(PdfArray array)
+ {
+ out.println('[');
+ for (Iterator i = array.getArrayList().iterator(); i.hasNext(); ) {
+ PdfObject item = (PdfObject)i.next();
+ listAnyObject(item);
+ }
+ out.println(']');
+ }
+ /**
+ * Visualizes a Stream.
+ * @param stream
+ * @param reader
+ */
+ public void listStream(PRStream stream, PdfReaderInstance reader)
+ {
+ try {
+ listDict(stream);
+ out.println("startstream");
+ byte[] b = PdfReader.getStreamBytes(stream);
+// byte buf[] = new byte[Math.min(stream.getLength(), 4096)];
+// int r = 0;
+// stream.openStream(reader);
+// for (;;) {
+// r = stream.readStream(buf, 0, buf.length);
+// if (r == 0) break;
+// out.write(buf, 0, r);
+// }
+// stream.closeStream();
+ int len = b.length - 1;
+ for (int k = 0; k < len; ++k) {
+ if (b[k] == '\r' && b[k + 1] != '\n')
+ b[k] = (byte)'\n';
+ }
+ out.println(new String(b));
+ out.println("endstream");
+ } catch (IOException e) {
+ System.err.println("I/O exception: " + e);
+// } catch (java.util.zip.DataFormatException e) {
+// System.err.println("Data Format Exception: " + e);
+ }
+ }
+ /**
+ * Visualizes an imported page
+ * @param iPage
+ */
+ public void listPage(PdfImportedPage iPage)
+ {
+ int pageNum = iPage.getPageNumber();
+ PdfReaderInstance readerInst = iPage.getPdfReaderInstance();
+ PdfReader reader = readerInst.getReader();
+
+ PdfDictionary page = reader.getPageN(pageNum);
+ listDict(page);
+ PdfObject obj = PdfReader.getPdfObject(page.get(PdfName.CONTENTS));
+ switch (obj.type) {
+ case PdfObject.STREAM:
+ listStream((PRStream)obj, readerInst);
+ break;
+ case PdfObject.ARRAY:
+ for (Iterator i = ((PdfArray)obj).getArrayList().iterator(); i.hasNext();) {
+ PdfObject o = PdfReader.getPdfObject((PdfObject)i.next());
+ listStream((PRStream)o, readerInst);
+ out.println("-----------");
+ }
+ break;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfLiteral.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfLiteral.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfLiteral.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfLiteral.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,101 @@
+/*
+ * $Id: PdfLiteral.java,v 1.21 2002/06/20 13:30:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * a Literal
+ */
+
+public class PdfLiteral extends PdfObject {
+
+ /**
+ * Holds value of property position.
+ */
+ private int position;
+
+ public PdfLiteral(String text) {
+ super(0, text);
+ }
+
+ public PdfLiteral(byte b[]) {
+ super(0, b);
+ }
+
+ public PdfLiteral(int size) {
+ super(0, (byte[])null);
+ bytes = new byte[size];
+ java.util.Arrays.fill(bytes, (byte)32);
+ }
+
+ public PdfLiteral(int type, String text) {
+ super(type, text);
+ }
+
+ public PdfLiteral(int type, byte b[]) {
+ super(type, b);
+ }
+
+ public void toPdf(PdfWriter writer, java.io.OutputStream os) throws java.io.IOException {
+ if (os instanceof OutputStreamCounter)
+ position = ((OutputStreamCounter)os).getCounter();
+ super.toPdf(writer, os);
+ }
+
+ /**
+ * Getter for property position.
+ * @return Value of property position.
+ */
+ public int getPosition() {
+ return this.position;
+ }
+
+ /**
+ * Getter for property posLength.
+ * @return Value of property posLength.
+ */
+ public int getPosLength() {
+ if (bytes != null)
+ return bytes.length;
+ else
+ return 0;
+ }
+
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfMediaClipData.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfMediaClipData.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfMediaClipData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfMediaClipData.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2003 Galo Gimenez
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+
+public class PdfMediaClipData extends PdfDictionary {
+
+ PdfMediaClipData(String file, PdfFileSpecification fs, String mimeType) throws IOException {
+ put(PdfName.TYPE,new PdfName("MediaClip"));
+ put(PdfName.S, new PdfName("MCD"));
+ put(PdfName.N, new PdfString("Media clip for "+file));
+ put(new PdfName("CT"), new PdfString(mimeType));
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(new PdfName("TF"), new PdfString("TEMPACCESS"));
+ put(new PdfName("P"), dic);
+ put(PdfName.D, fs.getReference());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfName.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfName.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfName.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfName.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,1946 @@
+/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * $Id: PdfName.java,v 1.74 2005/07/15 13:04:21 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999-2006 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.*;
+
+/**
+ * PdfName
is an object that can be used as a name in a PDF-file.
+ *
+ * A name, like a string, is a sequence of characters.
+ * It must begin with a slash followed by a sequence of ASCII characters in
+ * the range 32 through 136 except %, (, ), [, ], <, >, {, }, / and #.
+ * Any character except 0x00 may be included in a name by writing its
+ * two character hex code, preceded by #. The maximum number of characters
+ * in a name is 127.
+ * This object is described in the 'Portable Document Format Reference Manual
+ * version 1.7' section 3.2.4 (page 56-58).
+ *
+ *
+ * @see PdfObject
+ * @see PdfDictionary
+ * @see BadPdfFormatException
+ */
+
+public class PdfName extends PdfObject implements Comparable{
+
+ // CLASS CONSTANTS (a variety of standard names used in PDF))
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName _3D = new PdfName("3D");
+ /** A name */
+ public static final PdfName A = new PdfName("A");
+ /** A name */
+ public static final PdfName AA = new PdfName("AA");
+ /**
+ * A name
+ * @since 2.1.5 renamed from ABSOLUTECALORIMETRIC
+ */
+ public static final PdfName ABSOLUTECOLORIMETRIC = new PdfName("AbsoluteColorimetric");
+ /** A name */
+ public static final PdfName AC = new PdfName("AC");
+ /** A name */
+ public static final PdfName ACROFORM = new PdfName("AcroForm");
+ /** A name */
+ public static final PdfName ACTION = new PdfName("Action");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName ACTIVATION = new PdfName("Activation");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName ADBE = new PdfName("ADBE");
+ /**
+ * a name used in PDF structure
+ * @since 2.1.6
+ */
+ public static final PdfName ACTUALTEXT = new PdfName("ActualText");
+ /** A name */
+ public static final PdfName ADBE_PKCS7_DETACHED = new PdfName("adbe.pkcs7.detached");
+ /** A name */
+ public static final PdfName ADBE_PKCS7_S4 =new PdfName("adbe.pkcs7.s4");
+ /** A name */
+ public static final PdfName ADBE_PKCS7_S5 =new PdfName("adbe.pkcs7.s5");
+ /** A name */
+ public static final PdfName ADBE_PKCS7_SHA1 = new PdfName("adbe.pkcs7.sha1");
+ /** A name */
+ public static final PdfName ADBE_X509_RSA_SHA1 = new PdfName("adbe.x509.rsa_sha1");
+ /** A name */
+ public static final PdfName ADOBE_PPKLITE = new PdfName("Adobe.PPKLite");
+ /** A name */
+ public static final PdfName ADOBE_PPKMS = new PdfName("Adobe.PPKMS");
+ /** A name */
+ public static final PdfName AESV2 = new PdfName("AESV2");
+ /** A name */
+ public static final PdfName AIS = new PdfName("AIS");
+ /** A name */
+ public static final PdfName ALLPAGES = new PdfName("AllPages");
+ /** A name */
+ public static final PdfName ALT = new PdfName("Alt");
+ /** A name */
+ public static final PdfName ALTERNATE = new PdfName("Alternate");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName ANIMATION = new PdfName("Animation");
+ /** A name */
+ public static final PdfName ANNOT = new PdfName("Annot");
+ /** A name */
+ public static final PdfName ANNOTS = new PdfName("Annots");
+ /** A name */
+ public static final PdfName ANTIALIAS = new PdfName("AntiAlias");
+ /** A name */
+ public static final PdfName AP = new PdfName("AP");
+ /** A name */
+ public static final PdfName APPDEFAULT = new PdfName("AppDefault");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName ART = new PdfName("Art");
+ /** A name */
+ public static final PdfName ARTBOX = new PdfName("ArtBox");
+ /** A name */
+ public static final PdfName ASCENT = new PdfName("Ascent");
+ /** A name */
+ public static final PdfName AS = new PdfName("AS");
+ /** A name */
+ public static final PdfName ASCII85DECODE = new PdfName("ASCII85Decode");
+ /** A name */
+ public static final PdfName ASCIIHEXDECODE = new PdfName("ASCIIHexDecode");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName ASSET = new PdfName("Asset");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName ASSETS = new PdfName("Assets");
+ /** A name */
+ public static final PdfName AUTHEVENT = new PdfName("AuthEvent");
+ /** A name */
+ public static final PdfName AUTHOR = new PdfName("Author");
+ /** A name */
+ public static final PdfName B = new PdfName("B");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName BACKGROUND = new PdfName("Background");
+ /** A name */
+ public static final PdfName BASE = new PdfName("Base"); // used in the URI dictionary
+ /** A name */
+ public static final PdfName BASEENCODING = new PdfName("BaseEncoding");
+ /** A name */
+ public static final PdfName BASEFONT = new PdfName("BaseFont");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName BASEVERSION = new PdfName("BaseVersion");
+ /** A name */
+ public static final PdfName BBOX = new PdfName("BBox");
+ /** A name */
+ public static final PdfName BC = new PdfName("BC");
+ /** A name */
+ public static final PdfName BG = new PdfName("BG");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName BIBENTRY = new PdfName("BibEntry");
+ /** A name */
+ public static final PdfName BIGFIVE = new PdfName("BigFive");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName BINDING = new PdfName("Binding");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName BINDINGMATERIALNAME = new PdfName("BindingMaterialName");
+ /** A name */
+ public static final PdfName BITSPERCOMPONENT = new PdfName("BitsPerComponent");
+ /** A name */
+ public static final PdfName BITSPERSAMPLE = new PdfName("BitsPerSample");
+ /** A name */
+ public static final PdfName BL = new PdfName("Bl");
+ /** A name */
+ public static final PdfName BLACKIS1 = new PdfName("BlackIs1");
+ /** A name */
+ public static final PdfName BLACKPOINT = new PdfName("BlackPoint");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName BLOCKQUOTE = new PdfName("BlockQuote");
+ /** A name */
+ public static final PdfName BLEEDBOX = new PdfName("BleedBox");
+ /** A name */
+ public static final PdfName BLINDS = new PdfName("Blinds");
+ /** A name */
+ public static final PdfName BM = new PdfName("BM");
+ /** A name */
+ public static final PdfName BORDER = new PdfName("Border");
+ /** A name */
+ public static final PdfName BOUNDS = new PdfName("Bounds");
+ /** A name */
+ public static final PdfName BOX = new PdfName("Box");
+ /** A name */
+ public static final PdfName BS = new PdfName("BS");
+ /** A name */
+ public static final PdfName BTN = new PdfName("Btn");
+ /** A name */
+ public static final PdfName BYTERANGE = new PdfName("ByteRange");
+ /** A name */
+ public static final PdfName C = new PdfName("C");
+ /** A name */
+ public static final PdfName C0 = new PdfName("C0");
+ /** A name */
+ public static final PdfName C1 = new PdfName("C1");
+ /** A name */
+ public static final PdfName CA = new PdfName("CA");
+ /** A name */
+ public static final PdfName ca = new PdfName("ca");
+ /** A name */
+ public static final PdfName CALGRAY = new PdfName("CalGray");
+ /** A name */
+ public static final PdfName CALRGB = new PdfName("CalRGB");
+ /** A name */
+ public static final PdfName CAPHEIGHT = new PdfName("CapHeight");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName CAPTION = new PdfName("Caption");
+ /** A name */
+ public static final PdfName CATALOG = new PdfName("Catalog");
+ /** A name */
+ public static final PdfName CATEGORY = new PdfName("Category");
+ /** A name */
+ public static final PdfName CCITTFAXDECODE = new PdfName("CCITTFaxDecode");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName CENTER = new PdfName("Center");
+ /** A name */
+ public static final PdfName CENTERWINDOW = new PdfName("CenterWindow");
+ /** A name */
+ public static final PdfName CERT = new PdfName("Cert");
+ /** A name */
+ public static final PdfName CF = new PdfName("CF");
+ /** A name */
+ public static final PdfName CFM = new PdfName("CFM");
+ /** A name */
+ public static final PdfName CH = new PdfName("Ch");
+ /** A name */
+ public static final PdfName CHARPROCS = new PdfName("CharProcs");
+ /** A name */
+ public static final PdfName CHECKSUM = new PdfName("CheckSum");
+ /** A name */
+ public static final PdfName CI = new PdfName("CI");
+ /** A name */
+ public static final PdfName CIDFONTTYPE0 = new PdfName("CIDFontType0");
+ /** A name */
+ public static final PdfName CIDFONTTYPE2 = new PdfName("CIDFontType2");
+ /**
+ * A name
+ * @since 2.0.7
+ */
+ public static final PdfName CIDSET = new PdfName("CIDSet");
+ /** A name */
+ public static final PdfName CIDSYSTEMINFO = new PdfName("CIDSystemInfo");
+ /** A name */
+ public static final PdfName CIDTOGIDMAP = new PdfName("CIDToGIDMap");
+ /** A name */
+ public static final PdfName CIRCLE = new PdfName("Circle");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName CMD = new PdfName("CMD");
+ /** A name */
+ public static final PdfName CO = new PdfName("CO");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName CODE = new PdfName("Code");
+ /** A name */
+ public static final PdfName COLORS = new PdfName("Colors");
+ /** A name */
+ public static final PdfName COLORSPACE = new PdfName("ColorSpace");
+ /** A name */
+ public static final PdfName COLLECTION = new PdfName("Collection");
+ /** A name */
+ public static final PdfName COLLECTIONFIELD = new PdfName("CollectionField");
+ /** A name */
+ public static final PdfName COLLECTIONITEM = new PdfName("CollectionItem");
+ /** A name */
+ public static final PdfName COLLECTIONSCHEMA = new PdfName("CollectionSchema");
+ /** A name */
+ public static final PdfName COLLECTIONSORT = new PdfName("CollectionSort");
+ /** A name */
+ public static final PdfName COLLECTIONSUBITEM = new PdfName("CollectionSubitem");
+ /** A name */
+ public static final PdfName COLUMNS = new PdfName("Columns");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName CONDITION = new PdfName("Condition");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName CONFIGURATION = new PdfName("Configuration");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName CONFIGURATIONS = new PdfName("Configurations");
+ /** A name */
+ public static final PdfName CONTACTINFO = new PdfName("ContactInfo");
+ /** A name */
+ public static final PdfName CONTENT = new PdfName("Content");
+ /** A name */
+ public static final PdfName CONTENTS = new PdfName("Contents");
+ /** A name */
+ public static final PdfName COORDS = new PdfName("Coords");
+ /** A name */
+ public static final PdfName COUNT = new PdfName("Count");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName COURIER = new PdfName("Courier");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName COURIER_BOLD = new PdfName("Courier-Bold");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName COURIER_OBLIQUE = new PdfName("Courier-Oblique");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName COURIER_BOLDOBLIQUE = new PdfName("Courier-BoldOblique");
+ /** A name */
+ public static final PdfName CREATIONDATE = new PdfName("CreationDate");
+ /** A name */
+ public static final PdfName CREATOR = new PdfName("Creator");
+ /** A name */
+ public static final PdfName CREATORINFO = new PdfName("CreatorInfo");
+ /** A name */
+ public static final PdfName CROPBOX = new PdfName("CropBox");
+ /** A name */
+ public static final PdfName CRYPT = new PdfName("Crypt");
+ /** A name */
+ public static final PdfName CS = new PdfName("CS");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName CUEPOINT = new PdfName("CuePoint");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName CUEPOINTS = new PdfName("CuePoints");
+ /** A name */
+ public static final PdfName D = new PdfName("D");
+ /** A name */
+ public static final PdfName DA = new PdfName("DA");
+ /** A name */
+ public static final PdfName DATA = new PdfName("Data");
+ /** A name */
+ public static final PdfName DC = new PdfName("DC");
+ /** A name */
+ public static final PdfName DCTDECODE = new PdfName("DCTDecode");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName DEACTIVATION = new PdfName("Deactivation");
+ /** A name */
+ public static final PdfName DECODE = new PdfName("Decode");
+ /** A name */
+ public static final PdfName DECODEPARMS = new PdfName("DecodeParms");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName DEFAULT = new PdfName("Default");
+ /**
+ * A name
+ * @since 2.1.5 renamed from DEFAULTCRYPTFILER
+ */
+ public static final PdfName DEFAULTCRYPTFILTER = new PdfName("DefaultCryptFilter");
+ /** A name */
+ public static final PdfName DEFAULTCMYK = new PdfName("DefaultCMYK");
+ /** A name */
+ public static final PdfName DEFAULTGRAY = new PdfName("DefaultGray");
+ /** A name */
+ public static final PdfName DEFAULTRGB = new PdfName("DefaultRGB");
+ /** A name */
+ public static final PdfName DESC = new PdfName("Desc");
+ /** A name */
+ public static final PdfName DESCENDANTFONTS = new PdfName("DescendantFonts");
+ /** A name */
+ public static final PdfName DESCENT = new PdfName("Descent");
+ /** A name */
+ public static final PdfName DEST = new PdfName("Dest");
+ /** A name */
+ public static final PdfName DESTOUTPUTPROFILE = new PdfName("DestOutputProfile");
+ /** A name */
+ public static final PdfName DESTS = new PdfName("Dests");
+ /** A name */
+ public static final PdfName DEVICEGRAY = new PdfName("DeviceGray");
+ /** A name */
+ public static final PdfName DEVICERGB = new PdfName("DeviceRGB");
+ /** A name */
+ public static final PdfName DEVICECMYK = new PdfName("DeviceCMYK");
+ /** A name */
+ public static final PdfName DI = new PdfName("Di");
+ /** A name */
+ public static final PdfName DIFFERENCES = new PdfName("Differences");
+ /** A name */
+ public static final PdfName DISSOLVE = new PdfName("Dissolve");
+ /** A name */
+ public static final PdfName DIRECTION = new PdfName("Direction");
+ /** A name */
+ public static final PdfName DISPLAYDOCTITLE = new PdfName("DisplayDocTitle");
+ /** A name */
+ public static final PdfName DIV = new PdfName("Div");
+ /** A name */
+ public static final PdfName DL = new PdfName("DL");
+ /** A name */
+ public static final PdfName DM = new PdfName("Dm");
+ /** A name */
+ public static final PdfName DOCMDP = new PdfName("DocMDP");
+ /** A name */
+ public static final PdfName DOCOPEN = new PdfName("DocOpen");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName DOCUMENT = new PdfName( "Document" );
+ /** A name */
+ //public static final PdfName DOMAIN = new PdfName("Domain");
+ // changed this member name to prevent confusion on gcj (ssteward)
+ public static final PdfName m_DOMAIN = new PdfName("Domain");
+ /** A name */
+ public static final PdfName DP = new PdfName("DP");
+ /** A name */
+ public static final PdfName DR = new PdfName("DR");
+ /** A name */
+ public static final PdfName DS = new PdfName("DS");
+ /** A name */
+ public static final PdfName DUR = new PdfName("Dur");
+ /** A name */
+ public static final PdfName DUPLEX = new PdfName("Duplex");
+ /** A name */
+ public static final PdfName DUPLEXFLIPSHORTEDGE = new PdfName("DuplexFlipShortEdge");
+ /** A name */
+ public static final PdfName DUPLEXFLIPLONGEDGE = new PdfName("DuplexFlipLongEdge");
+ /** A name */
+ public static final PdfName DV = new PdfName("DV");
+ /** A name */
+ public static final PdfName DW = new PdfName("DW");
+ /** A name */
+ public static final PdfName E = new PdfName("E");
+ /** A name */
+ public static final PdfName EARLYCHANGE = new PdfName("EarlyChange");
+ /** A name */
+ public static final PdfName EF = new PdfName("EF");
+ /**
+ * A name
+ * @since 2.1.3
+ */
+ public static final PdfName EFF = new PdfName("EFF");
+ /**
+ * A name
+ * @since 2.1.3
+ */
+ public static final PdfName EFOPEN = new PdfName("EFOpen");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName EMBEDDED = new PdfName("Embedded");
+ /** A name */
+ public static final PdfName EMBEDDEDFILE = new PdfName("EmbeddedFile");
+ /** A name */
+ public static final PdfName EMBEDDEDFILES = new PdfName("EmbeddedFiles");
+ /** A name */
+ public static final PdfName ENCODE = new PdfName("Encode");
+ /** A name */
+ public static final PdfName ENCODEDBYTEALIGN = new PdfName("EncodedByteAlign");
+ /** A name */
+ public static final PdfName ENCODING = new PdfName("Encoding");
+ /** A name */
+ public static final PdfName ENCRYPT = new PdfName("Encrypt");
+ /** A name */
+ public static final PdfName ENCRYPTMETADATA = new PdfName("EncryptMetadata");
+ /** A name */
+ public static final PdfName ENDOFBLOCK = new PdfName("EndOfBlock");
+ /** A name */
+ public static final PdfName ENDOFLINE = new PdfName("EndOfLine");
+ /** A name */
+ public static final PdfName EXTEND = new PdfName("Extend");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName EXTENSIONS = new PdfName("Extensions");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName EXTENSIONLEVEL = new PdfName("ExtensionLevel");
+ /** A name */
+ public static final PdfName EXTGSTATE = new PdfName("ExtGState");
+ /** A name */
+ public static final PdfName EXPORT = new PdfName("Export");
+ /** A name */
+ public static final PdfName EXPORTSTATE = new PdfName("ExportState");
+ /** A name */
+ public static final PdfName EVENT = new PdfName("Event");
+ /** A name */
+ public static final PdfName F = new PdfName("F");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName FAR = new PdfName("Far");
+ /** A name */
+ public static final PdfName FB = new PdfName("FB");
+ /** A name */
+ public static final PdfName FDECODEPARMS = new PdfName("FDecodeParms");
+ /** A name */
+ public static final PdfName FDF = new PdfName("FDF");
+ /** A name */
+ public static final PdfName FF = new PdfName("Ff");
+ /** A name */
+ public static final PdfName FFILTER = new PdfName("FFilter");
+ /** A name */
+ public static final PdfName FIELDS = new PdfName("Fields");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName FIGURE = new PdfName( "Figure" );
+ /** A name */
+ public static final PdfName FILEATTACHMENT = new PdfName("FileAttachment");
+ /** A name */
+ public static final PdfName FILESPEC = new PdfName("Filespec");
+ /** A name */
+ public static final PdfName FILTER = new PdfName("Filter");
+ /** A name */
+ public static final PdfName FIRST = new PdfName("First");
+ /** A name */
+ public static final PdfName FIRSTCHAR = new PdfName("FirstChar");
+ /** A name */
+ public static final PdfName FIRSTPAGE = new PdfName("FirstPage");
+ /** A name */
+ public static final PdfName FIT = new PdfName("Fit");
+ /** A name */
+ public static final PdfName FITH = new PdfName("FitH");
+ /** A name */
+ public static final PdfName FITV = new PdfName("FitV");
+ /** A name */
+ public static final PdfName FITR = new PdfName("FitR");
+ /** A name */
+ public static final PdfName FITB = new PdfName("FitB");
+ /** A name */
+ public static final PdfName FITBH = new PdfName("FitBH");
+ /** A name */
+ public static final PdfName FITBV = new PdfName("FitBV");
+ /** A name */
+ public static final PdfName FITWINDOW = new PdfName("FitWindow");
+ /** A name */
+ public static final PdfName FLAGS = new PdfName("Flags");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName FLASH = new PdfName("Flash");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName FLASHVARS = new PdfName("FlashVars");
+ /** A name */
+ public static final PdfName FLATEDECODE = new PdfName("FlateDecode");
+ /** A name */
+ public static final PdfName FO = new PdfName("Fo");
+ /** A name */
+ public static final PdfName FONT = new PdfName("Font");
+ /** A name */
+ public static final PdfName FONTBBOX = new PdfName("FontBBox");
+ /** A name */
+ public static final PdfName FONTDESCRIPTOR = new PdfName("FontDescriptor");
+ /** A name */
+ public static final PdfName FONTFILE = new PdfName("FontFile");
+ /** A name */
+ public static final PdfName FONTFILE2 = new PdfName("FontFile2");
+ /** A name */
+ public static final PdfName FONTFILE3 = new PdfName("FontFile3");
+ /** A name */
+ public static final PdfName FONTMATRIX = new PdfName("FontMatrix");
+ /** A name */
+ public static final PdfName FONTNAME = new PdfName("FontName");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName FOREGROUND = new PdfName("Foreground");
+ /** A name */
+ public static final PdfName FORM = new PdfName("Form");
+ /** A name */
+ public static final PdfName FORMTYPE = new PdfName("FormType");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName FORMULA = new PdfName( "Formula" );
+ /** A name */
+ public static final PdfName FREETEXT = new PdfName("FreeText");
+ /** A name */
+ public static final PdfName FRM = new PdfName("FRM");
+ /** A name */
+ public static final PdfName FS = new PdfName("FS");
+ /** A name */
+ public static final PdfName FT = new PdfName("FT");
+ /** A name */
+ public static final PdfName FULLSCREEN = new PdfName("FullScreen");
+ /** A name */
+ public static final PdfName FUNCTION = new PdfName("Function");
+ /** A name */
+ public static final PdfName FUNCTIONS = new PdfName("Functions");
+ /** A name */
+ public static final PdfName FUNCTIONTYPE = new PdfName("FunctionType");
+ /** A name of an attribute. */
+ public static final PdfName GAMMA = new PdfName("Gamma");
+ /** A name of an attribute. */
+ public static final PdfName GBK = new PdfName("GBK");
+ /** A name of an attribute. */
+ public static final PdfName GLITTER = new PdfName("Glitter");
+ /** A name of an attribute. */
+ public static final PdfName GOTO = new PdfName("GoTo");
+ /** A name of an attribute. */
+ public static final PdfName GOTOE = new PdfName("GoToE");
+ /** A name of an attribute. */
+ public static final PdfName GOTOR = new PdfName("GoToR");
+ /** A name of an attribute. */
+ public static final PdfName GROUP = new PdfName("Group");
+ /** A name of an attribute. */
+ public static final PdfName GTS_PDFA1 = new PdfName("GTS_PDFA1");
+ /** A name of an attribute. */
+ public static final PdfName GTS_PDFX = new PdfName("GTS_PDFX");
+ /** A name of an attribute. */
+ public static final PdfName GTS_PDFXVERSION = new PdfName("GTS_PDFXVersion");
+ /** A name of an attribute. */
+ public static final PdfName H = new PdfName("H");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName H1 = new PdfName( "H1" );
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName H2 = new PdfName("H2");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName H3 = new PdfName("H3");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName H4 = new PdfName("H4");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName H5 = new PdfName("H5");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName H6 = new PdfName("H6");
+
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName HALIGN = new PdfName("HAlign");
+ /** A name of an attribute. */
+ public static final PdfName HEIGHT = new PdfName("Height");
+ /** A name */
+ public static final PdfName HELV = new PdfName("Helv");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName HELVETICA = new PdfName("Helvetica");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName HELVETICA_BOLD = new PdfName("Helvetica-Bold");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName HELVETICA_OBLIQUE = new PdfName("Helvetica-Oblique");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName HELVETICA_BOLDOBLIQUE = new PdfName("Helvetica-BoldOblique");
+ /** A name */
+ public static final PdfName HID = new PdfName("Hid");
+ /** A name */
+ public static final PdfName HIDE = new PdfName("Hide");
+ /** A name */
+ public static final PdfName HIDEMENUBAR = new PdfName("HideMenubar");
+ /** A name */
+ public static final PdfName HIDETOOLBAR = new PdfName("HideToolbar");
+ /** A name */
+ public static final PdfName HIDEWINDOWUI = new PdfName("HideWindowUI");
+ /** A name */
+ public static final PdfName HIGHLIGHT = new PdfName("Highlight");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName HOFFSET = new PdfName("HOffset");
+ /** A name */
+ public static final PdfName I = new PdfName("I");
+ /** A name */
+ public static final PdfName ICCBASED = new PdfName("ICCBased");
+ /** A name */
+ public static final PdfName ID = new PdfName("ID");
+ /** A name */
+ public static final PdfName IDENTITY = new PdfName("Identity");
+ /** A name */
+ public static final PdfName IF = new PdfName("IF");
+ /** A name */
+ public static final PdfName IMAGE = new PdfName("Image");
+ /** A name */
+ public static final PdfName IMAGEB = new PdfName("ImageB");
+ /** A name */
+ public static final PdfName IMAGEC = new PdfName("ImageC");
+ /** A name */
+ public static final PdfName IMAGEI = new PdfName("ImageI");
+ /** A name */
+ public static final PdfName IMAGEMASK = new PdfName("ImageMask");
+ /** A name */
+ public static final PdfName INDEX = new PdfName("Index");
+ /** A name */
+ public static final PdfName INDEXED = new PdfName("Indexed");
+ /** A name */
+ public static final PdfName INFO = new PdfName("Info");
+ /** A name */
+ public static final PdfName INK = new PdfName("Ink");
+ /** A name */
+ public static final PdfName INKLIST = new PdfName("InkList");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName INSTANCES = new PdfName("Instances");
+ /** A name */
+ public static final PdfName IMPORTDATA = new PdfName("ImportData");
+ /** A name */
+ public static final PdfName INTENT = new PdfName("Intent");
+ /** A name */
+ public static final PdfName INTERPOLATE = new PdfName("Interpolate");
+ /** A name */
+ public static final PdfName ISMAP = new PdfName("IsMap");
+ /** A name */
+ public static final PdfName IRT = new PdfName("IRT");
+ /** A name */
+ public static final PdfName ITALICANGLE = new PdfName("ItalicAngle");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName ITXT = new PdfName("ITXT");
+ /** A name */
+ public static final PdfName IX = new PdfName("IX");
+ /** A name */
+ public static final PdfName JAVASCRIPT = new PdfName("JavaScript");
+ /**
+ * A name
+ * @since 2.1.5
+ */
+ public static final PdfName JBIG2DECODE = new PdfName("JBIG2Decode");
+ /**
+ * A name
+ * @since 2.1.5
+ */
+ public static final PdfName JBIG2GLOBALS = new PdfName("JBIG2Globals");
+ /** A name */
+ public static final PdfName JPXDECODE = new PdfName("JPXDecode");
+ /** A name */
+ public static final PdfName JS = new PdfName("JS");
+ /** A name */
+ public static final PdfName K = new PdfName("K");
+ /** A name */
+ public static final PdfName KEYWORDS = new PdfName("Keywords");
+ /** A name */
+ public static final PdfName KIDS = new PdfName("Kids");
+ /** A name */
+ public static final PdfName L = new PdfName("L");
+ /** A name */
+ public static final PdfName L2R = new PdfName("L2R");
+ /** A name */
+ public static final PdfName LANG = new PdfName("Lang");
+ /** A name */
+ public static final PdfName LANGUAGE = new PdfName("Language");
+ /** A name */
+ public static final PdfName LAST = new PdfName("Last");
+ /** A name */
+ public static final PdfName LASTCHAR = new PdfName("LastChar");
+ /** A name */
+ public static final PdfName LASTPAGE = new PdfName("LastPage");
+ /** A name */
+ public static final PdfName LAUNCH = new PdfName("Launch");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName LBL = new PdfName("Lbl");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName LBODY = new PdfName("LBody");
+ /** A name */
+ public static final PdfName LENGTH = new PdfName("Length");
+ /** A name */
+ public static final PdfName LENGTH1 = new PdfName("Length1");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName LI = new PdfName("LI");
+ /** A name */
+ public static final PdfName LIMITS = new PdfName("Limits");
+ /** A name */
+ public static final PdfName LINE = new PdfName("Line");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName LINEAR = new PdfName("Linear");
+ /** A name */
+ public static final PdfName LINK = new PdfName("Link");
+ /** A name */
+ public static final PdfName LISTMODE = new PdfName("ListMode");
+ /** A name */
+ public static final PdfName LOCATION = new PdfName("Location");
+ /** A name */
+ public static final PdfName LOCK = new PdfName("Lock");
+ /**
+ * A name
+ * @since 2.1.2
+ */
+ public static final PdfName LOCKED = new PdfName("Locked");
+ /** A name */
+ public static final PdfName LZWDECODE = new PdfName("LZWDecode");
+ /** A name */
+ public static final PdfName M = new PdfName("M");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName MATERIAL = new PdfName("Material");
+ /** A name */
+ public static final PdfName MATRIX = new PdfName("Matrix");
+ /** A name of an encoding */
+ public static final PdfName MAC_EXPERT_ENCODING = new PdfName("MacExpertEncoding");
+ /** A name of an encoding */
+ public static final PdfName MAC_ROMAN_ENCODING = new PdfName("MacRomanEncoding");
+ /** A name */
+ public static final PdfName MARKED = new PdfName("Marked");
+ /** A name */
+ public static final PdfName MARKINFO = new PdfName("MarkInfo");
+ /** A name */
+ public static final PdfName MASK = new PdfName("Mask");
+ /**
+ * A name
+ * @since 2.1.6 renamed from MAX
+ */
+ public static final PdfName MAX_LOWER_CASE = new PdfName("max");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName MAX_CAMEL_CASE = new PdfName("Max");
+ /** A name */
+ public static final PdfName MAXLEN = new PdfName("MaxLen");
+ /** A name */
+ public static final PdfName MEDIABOX = new PdfName("MediaBox");
+ /** A name */
+ public static final PdfName MCID = new PdfName("MCID");
+ /** A name */
+ public static final PdfName MCR = new PdfName("MCR");
+ /** A name */
+ public static final PdfName METADATA = new PdfName("Metadata");
+ /**
+ * A name
+ * @since 2.1.6 renamed from MIN
+ */
+ public static final PdfName MIN_LOWER_CASE = new PdfName("min");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName MIN_CAMEL_CASE = new PdfName("Min");
+ /** A name */
+ public static final PdfName MK = new PdfName("MK");
+ /** A name */
+ public static final PdfName MMTYPE1 = new PdfName("MMType1");
+ /** A name */
+ public static final PdfName MODDATE = new PdfName("ModDate");
+ /** A name */
+ public static final PdfName N = new PdfName("N");
+ /** A name */
+ public static final PdfName N0 = new PdfName("n0");
+ /** A name */
+ public static final PdfName N1 = new PdfName("n1");
+ /** A name */
+ public static final PdfName N2 = new PdfName("n2");
+ /** A name */
+ public static final PdfName N3 = new PdfName("n3");
+ /** A name */
+ public static final PdfName N4 = new PdfName("n4");
+ /** A name */
+ public static final PdfName NAME = new PdfName("Name");
+ /** A name */
+ public static final PdfName NAMED = new PdfName("Named");
+ /** A name */
+ public static final PdfName NAMES = new PdfName("Names");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName NAVIGATION = new PdfName("Navigation");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName NAVIGATIONPANE = new PdfName("NavigationPane");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName NEAR = new PdfName("Near");
+ /** A name */
+ public static final PdfName NEEDAPPEARANCES = new PdfName("NeedAppearances");
+ /** A name */
+ public static final PdfName NEWWINDOW = new PdfName("NewWindow");
+ /** A name */
+ public static final PdfName NEXT = new PdfName("Next");
+ /** A name */
+ public static final PdfName NEXTPAGE = new PdfName("NextPage");
+ /** A name */
+ public static final PdfName NM = new PdfName("NM");
+ /** A name */
+ public static final PdfName NONE = new PdfName("None");
+ /** A name */
+ public static final PdfName NONFULLSCREENPAGEMODE = new PdfName("NonFullScreenPageMode");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName NONSTRUCT = new PdfName("NonStruct");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName NOTE = new PdfName("Note");
+ /** A name */
+ public static final PdfName NUMCOPIES = new PdfName("NumCopies");
+ /** A name */
+ public static final PdfName NUMS = new PdfName("Nums");
+ /** A name */
+ public static final PdfName O = new PdfName("O");
+ /**
+ * A name used with Document Structure
+ * @since 2.1.5
+ */
+ public static final PdfName OBJ = new PdfName("Obj");
+ /**
+ * a name used with Doucment Structure
+ * @since 2.1.5
+ */
+ public static final PdfName OBJR = new PdfName("OBJR");
+ /** A name */
+ public static final PdfName OBJSTM = new PdfName("ObjStm");
+ /** A name */
+ public static final PdfName OC = new PdfName("OC");
+ /** A name */
+ public static final PdfName OCG = new PdfName("OCG");
+ /** A name */
+ public static final PdfName OCGS = new PdfName("OCGs");
+ /** A name */
+ public static final PdfName OCMD = new PdfName("OCMD");
+ /** A name */
+ public static final PdfName OCPROPERTIES = new PdfName("OCProperties");
+ /** A name */
+ public static final PdfName Off = new PdfName("Off");
+ /** A name */
+ public static final PdfName OFF = new PdfName("OFF");
+ /** A name */
+ public static final PdfName ON = new PdfName("ON");
+ /** A name */
+ public static final PdfName ONECOLUMN = new PdfName("OneColumn");
+ /** A name */
+ public static final PdfName OPEN = new PdfName("Open");
+ /** A name */
+ public static final PdfName OPENACTION = new PdfName("OpenAction");
+ /** A name */
+ public static final PdfName OP = new PdfName("OP");
+ /** A name */
+ public static final PdfName op = new PdfName("op");
+ /** A name */
+ public static final PdfName OPM = new PdfName("OPM");
+ /** A name */
+ public static final PdfName OPT = new PdfName("Opt");
+ /** A name */
+ public static final PdfName ORDER = new PdfName("Order");
+ /** A name */
+ public static final PdfName ORDERING = new PdfName("Ordering");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName OSCILLATING = new PdfName("Oscillating");
+
+ /** A name */
+ public static final PdfName OUTLINES = new PdfName("Outlines");
+ /** A name */
+ public static final PdfName OUTPUTCONDITION = new PdfName("OutputCondition");
+ /** A name */
+ public static final PdfName OUTPUTCONDITIONIDENTIFIER = new PdfName("OutputConditionIdentifier");
+ /** A name */
+ public static final PdfName OUTPUTINTENT = new PdfName("OutputIntent");
+ /** A name */
+ public static final PdfName OUTPUTINTENTS = new PdfName("OutputIntents");
+ /** A name */
+ public static final PdfName P = new PdfName("P");
+ /** A name */
+ public static final PdfName PAGE = new PdfName("Page");
+ /** A name */
+ public static final PdfName PAGELABELS = new PdfName("PageLabels");
+ /** A name */
+ public static final PdfName PAGELAYOUT = new PdfName("PageLayout");
+ /** A name */
+ public static final PdfName PAGEMODE = new PdfName("PageMode");
+ /** A name */
+ public static final PdfName PAGES = new PdfName("Pages");
+ /** A name */
+ public static final PdfName PAINTTYPE = new PdfName("PaintType");
+ /** A name */
+ public static final PdfName PANOSE = new PdfName("Panose");
+ /** A name */
+ public static final PdfName PARAMS = new PdfName("Params");
+ /** A name */
+ public static final PdfName PARENT = new PdfName("Parent");
+ /** A name */
+ public static final PdfName PARENTTREE = new PdfName("ParentTree");
+ /**
+ * A name used in defining Document Structure.
+ * @since 2.1.5
+ */
+ public static final PdfName PARENTTREENEXTKEY = new PdfName( "ParentTreeNextKey" );
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName PART = new PdfName( "Part" );
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName PASSCONTEXTCLICK = new PdfName("PassContextClick");
+ /** A name */
+ public static final PdfName PATTERN = new PdfName("Pattern");
+ /** A name */
+ public static final PdfName PATTERNTYPE = new PdfName("PatternType");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName PC = new PdfName("PC");
+ /** A name */
+ public static final PdfName PDF = new PdfName("PDF");
+ /** A name */
+ public static final PdfName PDFDOCENCODING = new PdfName("PDFDocEncoding");
+ /** A name */
+ public static final PdfName PERCEPTUAL = new PdfName("Perceptual");
+ /** A name */
+ public static final PdfName PERMS = new PdfName("Perms");
+ /** A name */
+ public static final PdfName PG = new PdfName("Pg");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName PI = new PdfName("PI");
+ /** A name */
+ public static final PdfName PICKTRAYBYPDFSIZE = new PdfName("PickTrayByPDFSize");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName PLAYCOUNT = new PdfName("PlayCount");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName PO = new PdfName("PO");
+ /** A name */
+ public static final PdfName POPUP = new PdfName("Popup");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName POSITION = new PdfName("Position");
+ /** A name */
+ public static final PdfName PREDICTOR = new PdfName("Predictor");
+ /** A name */
+ public static final PdfName PREFERRED = new PdfName("Preferred");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName PRESENTATION = new PdfName("Presentation");
+ /** A name */
+ public static final PdfName PRESERVERB = new PdfName("PreserveRB");
+ /** A name */
+ public static final PdfName PREV = new PdfName("Prev");
+ /** A name */
+ public static final PdfName PREVPAGE = new PdfName("PrevPage");
+ /** A name */
+ public static final PdfName PRINT = new PdfName("Print");
+ /** A name */
+ public static final PdfName PRINTAREA = new PdfName("PrintArea");
+ /** A name */
+ public static final PdfName PRINTCLIP = new PdfName("PrintClip");
+ /** A name */
+ public static final PdfName PRINTPAGERANGE = new PdfName("PrintPageRange");
+ /** A name */
+ public static final PdfName PRINTSCALING = new PdfName("PrintScaling");
+ /** A name */
+ public static final PdfName PRINTSTATE = new PdfName("PrintState");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName PRIVATE = new PdfName("Private");
+ /** A name */
+ public static final PdfName PROCSET = new PdfName("ProcSet");
+ /** A name */
+ public static final PdfName PRODUCER = new PdfName("Producer");
+ /** A name */
+ public static final PdfName PROPERTIES = new PdfName("Properties");
+ /** A name */
+ public static final PdfName PS = new PdfName("PS");
+ /** A name */
+ public static final PdfName PUBSEC = new PdfName("Adobe.PubSec");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName PV = new PdfName("PV");
+ /** A name */
+ public static final PdfName Q = new PdfName("Q");
+ /** A name */
+ public static final PdfName QUADPOINTS = new PdfName("QuadPoints");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName QUOTE = new PdfName("Quote");
+ /** A name */
+ public static final PdfName R = new PdfName("R");
+ /** A name */
+ public static final PdfName R2L = new PdfName("R2L");
+ /** A name */
+ public static final PdfName RANGE = new PdfName("Range");
+ /** A name */
+ public static final PdfName RC = new PdfName("RC");
+ /** A name */
+ public static final PdfName RBGROUPS = new PdfName("RBGroups");
+ /** A name */
+ public static final PdfName REASON = new PdfName("Reason");
+ /** A name */
+ public static final PdfName RECIPIENTS = new PdfName("Recipients");
+ /** A name */
+ public static final PdfName RECT = new PdfName("Rect");
+ /** A name */
+ public static final PdfName REFERENCE = new PdfName("Reference");
+ /** A name */
+ public static final PdfName REGISTRY = new PdfName("Registry");
+ /** A name */
+ public static final PdfName REGISTRYNAME = new PdfName("RegistryName");
+ /**
+ * A name
+ * @since 2.1.5 renamed from RELATIVECALORIMETRIC
+ */
+ public static final PdfName RELATIVECOLORIMETRIC = new PdfName("RelativeColorimetric");
+ /** A name */
+ public static final PdfName RENDITION = new PdfName("Rendition");
+ /** A name */
+ public static final PdfName RESETFORM = new PdfName("ResetForm");
+ /** A name */
+ public static final PdfName RESOURCES = new PdfName("Resources");
+ /** A name */
+ public static final PdfName RI = new PdfName("RI");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIA = new PdfName("RichMedia");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIAACTIVATION = new PdfName("RichMediaActivation");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIAANIMATION = new PdfName("RichMediaAnimation");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIACOMMAND = new PdfName("RichMediaCommand");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIACONFIGURATION = new PdfName("RichMediaConfiguration");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIACONTENT = new PdfName("RichMediaContent");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIADEACTIVATION = new PdfName("RichMediaDeactivation");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIAEXECUTE = new PdfName("RichMediaExecute");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIAINSTANCE = new PdfName("RichMediaInstance");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIAPARAMS = new PdfName("RichMediaParams");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIAPOSITION = new PdfName("RichMediaPosition");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIAPRESENTATION = new PdfName("RichMediaPresentation");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIASETTINGS = new PdfName("RichMediaSettings");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName RICHMEDIAWINDOW = new PdfName("RichMediaWindow");
+ /** A name */
+ public static final PdfName ROLEMAP = new PdfName("RoleMap");
+ /** A name */
+ public static final PdfName ROOT = new PdfName("Root");
+ /** A name */
+ public static final PdfName ROTATE = new PdfName("Rotate");
+ /** A name */
+ public static final PdfName ROWS = new PdfName("Rows");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName RUBY = new PdfName( "Ruby" );
+ /** A name */
+ public static final PdfName RUNLENGTHDECODE = new PdfName("RunLengthDecode");
+ /** A name */
+ public static final PdfName RV = new PdfName("RV");
+ /** A name */
+ public static final PdfName S = new PdfName("S");
+ /** A name */
+ public static final PdfName SATURATION = new PdfName("Saturation");
+ /** A name */
+ public static final PdfName SCHEMA = new PdfName("Schema");
+ /** A name */
+ public static final PdfName SCREEN = new PdfName("Screen");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName SCRIPTS = new PdfName("Scripts");
+ /** A name */
+ public static final PdfName SECT = new PdfName("Sect");
+ /** A name */
+ public static final PdfName SEPARATION = new PdfName("Separation");
+ /** A name */
+ public static final PdfName SETOCGSTATE = new PdfName("SetOCGState");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName SETTINGS = new PdfName("Settings");
+ /** A name */
+ public static final PdfName SHADING = new PdfName("Shading");
+ /** A name */
+ public static final PdfName SHADINGTYPE = new PdfName("ShadingType");
+ /** A name */
+ public static final PdfName SHIFT_JIS = new PdfName("Shift-JIS");
+ /** A name */
+ public static final PdfName SIG = new PdfName("Sig");
+ /** A name */
+ public static final PdfName SIGFLAGS = new PdfName("SigFlags");
+ /** A name */
+ public static final PdfName SIGREF = new PdfName("SigRef");
+ /** A name */
+ public static final PdfName SIMPLEX = new PdfName("Simplex");
+ /** A name */
+ public static final PdfName SINGLEPAGE = new PdfName("SinglePage");
+ /** A name */
+ public static final PdfName SIZE = new PdfName("Size");
+ /** A name */
+ public static final PdfName SMASK = new PdfName("SMask");
+ /** A name */
+ public static final PdfName SORT = new PdfName("Sort");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName SOUND = new PdfName("Sound");
+ /** A name */
+ public static final PdfName SPAN = new PdfName("Span");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName SPEED = new PdfName("Speed");
+ /** A name */
+ public static final PdfName SPLIT = new PdfName("Split");
+ /** A name */
+ public static final PdfName SQUARE = new PdfName("Square");
+ /**
+ * A name
+ * @since 2.1.3
+ */
+ public static final PdfName SQUIGGLY = new PdfName("Squiggly");
+ /** A name */
+ public static final PdfName ST = new PdfName("St");
+ /** A name */
+ public static final PdfName STAMP = new PdfName("Stamp");
+ /** A name */
+ public static final PdfName STANDARD = new PdfName("Standard");
+ /** A name */
+ public static final PdfName STATE = new PdfName("State");
+ /** A name */
+ public static final PdfName STDCF = new PdfName("StdCF");
+ /** A name */
+ public static final PdfName STEMV = new PdfName("StemV");
+ /** A name */
+ public static final PdfName STMF = new PdfName("StmF");
+ /** A name */
+ public static final PdfName STRF = new PdfName("StrF");
+ /** A name */
+ public static final PdfName STRIKEOUT = new PdfName("StrikeOut");
+ /** A name */
+ public static final PdfName STRUCTPARENT = new PdfName("StructParent");
+ /** A name */
+ public static final PdfName STRUCTPARENTS = new PdfName("StructParents");
+ /** A name */
+ public static final PdfName STRUCTTREEROOT = new PdfName("StructTreeRoot");
+ /** A name */
+ public static final PdfName STYLE = new PdfName("Style");
+ /** A name */
+ public static final PdfName SUBFILTER = new PdfName("SubFilter");
+ /** A name */
+ public static final PdfName SUBJECT = new PdfName("Subject");
+ /** A name */
+ public static final PdfName SUBMITFORM = new PdfName("SubmitForm");
+ /** A name */
+ public static final PdfName SUBTYPE = new PdfName("Subtype");
+ /** A name */
+ public static final PdfName SUPPLEMENT = new PdfName("Supplement");
+ /** A name */
+ public static final PdfName SV = new PdfName("SV");
+ /** A name */
+ public static final PdfName SW = new PdfName("SW");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName SYMBOL = new PdfName("Symbol");
+ /** A name */
+ public static final PdfName T = new PdfName("T");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName TA = new PdfName("TA");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName TABLE = new PdfName("Table");
+ /**
+ * A name
+ * @since 2.1.5
+ */
+ public static final PdfName TABS = new PdfName("Tabs");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName TBODY = new PdfName("TBody");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName TD = new PdfName("TD");
+ /** A name */
+ public static final PdfName TEXT = new PdfName("Text");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName TFOOT = new PdfName("TFoot");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName TH = new PdfName("TH");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName THEAD = new PdfName("THead");
+ /** A name */
+ public static final PdfName THUMB = new PdfName("Thumb");
+ /** A name */
+ public static final PdfName THREADS = new PdfName("Threads");
+ /** A name */
+ public static final PdfName TI = new PdfName("TI");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName TIME = new PdfName("Time");
+ /** A name */
+ public static final PdfName TILINGTYPE = new PdfName("TilingType");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName TIMES_ROMAN = new PdfName("Times-Roman");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName TIMES_BOLD = new PdfName("Times-Bold");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName TIMES_ITALIC = new PdfName("Times-Italic");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName TIMES_BOLDITALIC = new PdfName("Times-BoldItalic");
+ /** A name */
+ public static final PdfName TITLE = new PdfName("Title");
+ /** A name */
+ public static final PdfName TK = new PdfName("TK");
+ /** A name */
+ public static final PdfName TM = new PdfName("TM");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName TOC = new PdfName("TOC");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName TOCI = new PdfName("TOCI");
+ /** A name */
+ public static final PdfName TOGGLE = new PdfName("Toggle");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName TOOLBAR = new PdfName("Toolbar");
+ /** A name */
+ public static final PdfName TOUNICODE = new PdfName("ToUnicode");
+ /** A name */
+ public static final PdfName TP = new PdfName("TP");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName TABLEROW = new PdfName( "TR" );
+ /** A name */
+ public static final PdfName TRANS = new PdfName("Trans");
+ /** A name */
+ public static final PdfName TRANSFORMPARAMS = new PdfName("TransformParams");
+ /** A name */
+ public static final PdfName TRANSFORMMETHOD = new PdfName("TransformMethod");
+ /** A name */
+ public static final PdfName TRANSPARENCY = new PdfName("Transparency");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName TRANSPARENT = new PdfName("Transparent");
+ /** A name */
+ public static final PdfName TRAPPED = new PdfName("Trapped");
+ /** A name */
+ public static final PdfName TRIMBOX = new PdfName("TrimBox");
+ /** A name */
+ public static final PdfName TRUETYPE = new PdfName("TrueType");
+ /** A name */
+ public static final PdfName TU = new PdfName("TU");
+ /** A name */
+ public static final PdfName TWOCOLUMNLEFT = new PdfName("TwoColumnLeft");
+ /** A name */
+ public static final PdfName TWOCOLUMNRIGHT = new PdfName("TwoColumnRight");
+ /** A name */
+ public static final PdfName TWOPAGELEFT = new PdfName("TwoPageLeft");
+ /** A name */
+ public static final PdfName TWOPAGERIGHT = new PdfName("TwoPageRight");
+ /** A name */
+ public static final PdfName TX = new PdfName("Tx");
+ /** A name */
+ public static final PdfName TYPE = new PdfName("Type");
+ /** A name */
+ public static final PdfName TYPE0 = new PdfName("Type0");
+ /** A name */
+ public static final PdfName TYPE1 = new PdfName("Type1");
+ /** A name of an attribute. */
+ public static final PdfName TYPE3 = new PdfName("Type3");
+ /** A name of an attribute. */
+ public static final PdfName U = new PdfName("U");
+ /** A name of an attribute. */
+ public static final PdfName UF = new PdfName("UF");
+ /** A name of an attribute. */
+ public static final PdfName UHC = new PdfName("UHC");
+ /** A name of an attribute. */
+ public static final PdfName UNDERLINE = new PdfName("Underline");
+ /** A name */
+ public static final PdfName UR = new PdfName("UR");
+ /** A name */
+ public static final PdfName UR3 = new PdfName("UR3");
+ /** A name */
+ public static final PdfName URI = new PdfName("URI");
+ /** A name */
+ public static final PdfName URL = new PdfName("URL");
+ /** A name */
+ public static final PdfName USAGE = new PdfName("Usage");
+ /** A name */
+ public static final PdfName USEATTACHMENTS = new PdfName("UseAttachments");
+ /** A name */
+ public static final PdfName USENONE = new PdfName("UseNone");
+ /** A name */
+ public static final PdfName USEOC = new PdfName("UseOC");
+ /** A name */
+ public static final PdfName USEOUTLINES = new PdfName("UseOutlines");
+ /** A name */
+ public static final PdfName USER = new PdfName("User");
+ /** A name */
+ public static final PdfName USERPROPERTIES = new PdfName("UserProperties");
+ /** A name */
+ public static final PdfName USERUNIT = new PdfName("UserUnit");
+ /** A name */
+ public static final PdfName USETHUMBS = new PdfName("UseThumbs");
+ /** A name */
+ public static final PdfName V = new PdfName("V");
+ /** A name */
+ public static final PdfName V2 = new PdfName("V2");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName VALIGN = new PdfName("VAlign");
+ /** A name */
+ public static final PdfName VERISIGN_PPKVS = new PdfName("VeriSign.PPKVS");
+ /** A name */
+ public static final PdfName VERSION = new PdfName("Version");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName VIDEO = new PdfName("Video");
+ /** A name */
+ public static final PdfName VIEW = new PdfName("View");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName VIEWS = new PdfName("Views");
+ /** A name */
+ public static final PdfName VIEWAREA = new PdfName("ViewArea");
+ /** A name */
+ public static final PdfName VIEWCLIP = new PdfName("ViewClip");
+ /** A name */
+ public static final PdfName VIEWERPREFERENCES = new PdfName("ViewerPreferences");
+ /** A name */
+ public static final PdfName VIEWSTATE = new PdfName("ViewState");
+ /** A name */
+ public static final PdfName VISIBLEPAGES = new PdfName("VisiblePages");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName VOFFSET = new PdfName("VOffset");
+ /** A name of an attribute. */
+ public static final PdfName W = new PdfName("W");
+ /** A name of an attribute. */
+ public static final PdfName W2 = new PdfName("W2");
+ /**
+ * A name
+ * @since 2.1.6
+ */
+ public static final PdfName WARICHU = new PdfName("Warichu");
+ /** A name of an attribute. */
+ public static final PdfName WC = new PdfName("WC");
+ /** A name of an attribute. */
+ public static final PdfName WIDGET = new PdfName("Widget");
+ /** A name of an attribute. */
+ public static final PdfName WIDTH = new PdfName("Width");
+ /** A name */
+ public static final PdfName WIDTHS = new PdfName("Widths");
+ /** A name of an encoding */
+ public static final PdfName WIN = new PdfName("Win");
+ /** A name of an encoding */
+ public static final PdfName WIN_ANSI_ENCODING = new PdfName("WinAnsiEncoding");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName WINDOW = new PdfName("Window");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName WINDOWED = new PdfName("Windowed");
+ /** A name of an encoding */
+ public static final PdfName WIPE = new PdfName("Wipe");
+ /** A name */
+ public static final PdfName WHITEPOINT = new PdfName("WhitePoint");
+ /** A name */
+ public static final PdfName WP = new PdfName("WP");
+ /** A name of an encoding */
+ public static final PdfName WS = new PdfName("WS");
+ /** A name */
+ public static final PdfName X = new PdfName("X");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName XA = new PdfName("XA");
+ /**
+ * A name.
+ * @since 2.1.6
+ */
+ public static final PdfName XD = new PdfName("XD");
+ /** A name */
+ public static final PdfName XFA = new PdfName("XFA");
+ /** A name */
+ public static final PdfName XML = new PdfName("XML");
+ /** A name */
+ public static final PdfName XOBJECT = new PdfName("XObject");
+ /** A name */
+ public static final PdfName XSTEP = new PdfName("XStep");
+ /** A name */
+ public static final PdfName XREF = new PdfName("XRef");
+ /** A name */
+ public static final PdfName XREFSTM = new PdfName("XRefStm");
+ /** A name */
+ public static final PdfName XYZ = new PdfName("XYZ");
+ /** A name */
+ public static final PdfName YSTEP = new PdfName("YStep");
+ /** A name */
+ public static final PdfName ZADB = new PdfName("ZaDb");
+ /** A name of a base 14 type 1 font */
+ public static final PdfName ZAPFDINGBATS = new PdfName("ZapfDingbats");
+ /** A name */
+ public static final PdfName ZOOM = new PdfName("Zoom");
+ // ssteward: added VERSION* for pdftk 1.46
+ /** A name */
+ public static final PdfName VERSION_1_0 = new PdfName("1.0");
+ /** A name */
+ public static final PdfName VERSION_1_1 = new PdfName("1.1");
+ /** A name */
+ public static final PdfName VERSION_1_2 = new PdfName("1.2");
+ /** A name */
+ public static final PdfName VERSION_1_3 = new PdfName("1.3");
+ /** A name */
+ public static final PdfName VERSION_1_4 = new PdfName("1.4");
+ /** A name */
+ public static final PdfName VERSION_1_5 = new PdfName("1.5");
+ /** A name */
+ public static final PdfName VERSION_1_6 = new PdfName("1.6");
+ /** A name */
+ public static final PdfName VERSION_1_7 = new PdfName("1.7");
+
+
+ /**
+ * map strings to all known static names
+ * @since 2.1.6
+ */
+ public static Map staticNames;
+
+ /**
+ * Use reflection to cache all the static public final names so
+ * future PdfName
additions don't have to be "added twice".
+ * A bit less efficient (around 50ms spent here on a 2.2ghz machine),
+ * but Much Less error prone.
+ * @since 2.1.6
+ */
+
+ static {
+ Field fields[] = PdfName.class.getDeclaredFields();
+ staticNames = new HashMap( fields.length );
+ final int flags = Modifier.STATIC | Modifier.PUBLIC | Modifier.FINAL;
+ try {
+ for (int fldIdx = 0; fldIdx < fields.length; ++fldIdx) {
+ Field curFld = fields[fldIdx];
+ if ((curFld.getModifiers() & flags) == flags &&
+ curFld.getType().equals( PdfName.class )) {
+ PdfName name = (PdfName)curFld.get( null );
+ staticNames.put( decodeName( name.toString() ), name );
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ // CLASS VARIABLES
+
+ private int hash = 0;
+
+ // CONSTRUCTORS
+
+ /**
+ * Constructs a new PdfName
. The name length will be checked.
+ *
+ * @param name the new name
+ */
+ public PdfName(String name) {
+ this(name, true);
+ }
+
+ /**
+ * Constructs a new PdfName
.
+ * @param name the new name
+ * @param lengthCheck if true
check the length validity,
+ * if false
the name can have any length
+ */
+ public PdfName(String name, boolean lengthCheck) {
+ super(PdfObject.NAME);
+ // The minimum number of characters in a name is 0, the maximum is 127 (the '/' not included)
+ int length = name.length();
+ if (lengthCheck && length > 127)
+ throw new IllegalArgumentException("the.name.1.is.too.long.2.characters: "+ String.valueOf(length));
+ bytes = encodeName(name);
+ }
+
+ /**
+ * Constructs a PdfName.
+ *
+ * @param bytes the byte representation of the name
+ */
+ public PdfName(byte bytes[]) {
+ super(PdfObject.NAME, bytes);
+ }
+
+ // CLASS METHODS
+
+ /**
+ * Compares this object with the specified object for order.
+ * Returns a negative integer, zero, or a positive integer as this object
+ * is less than, equal to, or greater than the specified object.
+ *
+ * @param object the Object to be compared.
+ * @return a negative integer, zero, or a positive integer as this object
+ * is less than, equal to, or greater than the specified object.
+ * @throws ClassCastException if the specified object's type prevents it
+ * from being compared to this Object.
+ */
+ public int compareTo(Object object) {
+ PdfName name = (PdfName) object;
+ byte myBytes[] = bytes;
+ byte objBytes[] = name.bytes;
+ int len = Math.min(myBytes.length, objBytes.length);
+ for(int i = 0; i < len; i++) {
+ if (myBytes[i] > objBytes[i])
+ return 1;
+ if (myBytes[i] < objBytes[i])
+ return -1;
+ }
+ if (myBytes.length < objBytes.length)
+ return -1;
+ if (myBytes.length > objBytes.length)
+ return 1;
+ return 0;
+ }
+
+ /**
+ * Indicates whether some other object is "equal to" this one.
+ *
+ * @param obj the reference object with which to compare.
+ * @return true
if this object is the same as the obj
+ * argument; false
otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj instanceof PdfName)
+ return compareTo(obj) == 0;
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for the object.
+ * This method is supported for the benefit of hashtables such as those provided by
+ * java.util.Hashtable
.
+ *
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ int h = hash;
+ if (h == 0) {
+ int ptr = 0;
+ int len = bytes.length;
+ for (int i = 0; i < len; i++)
+ h = 31*h + (bytes[ptr++] & 0xff);
+ hash = h;
+ }
+ return h;
+ }
+
+ /**
+ * Encodes a plain name given in the unescaped form "AB CD" into "/AB#20CD".
+ *
+ * @param name the name to encode
+ * @return the encoded name
+ * @since 2.1.5
+ */
+ public static byte[] encodeName(String name) {
+ int length = name.length();
+ ByteBuffer buf = new ByteBuffer(length + 20);
+ buf.append('/');
+ char c;
+ char chars[] = name.toCharArray();
+ for (int k = 0; k < length; k++) {
+ c = (char)(chars[k] & 0xff);
+ // Escape special characters
+ switch (c) {
+ case ' ':
+ case '%':
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '{':
+ case '}':
+ case '/':
+ case '#':
+ buf.append('#');
+ buf.append(Integer.toString(c, 16));
+ break;
+ default:
+ if (c >= 32 && c <= 126)
+ buf.append(c);
+ else {
+ buf.append('#');
+ if (c < 16)
+ buf.append('0');
+ buf.append(Integer.toString(c, 16));
+ }
+ break;
+ }
+ }
+ return buf.toByteArray();
+ }
+
+ /**
+ * Decodes an escaped name given in the form "/AB#20CD" into "AB CD".
+ *
+ * @param name the name to decode
+ * @return the decoded name
+ */
+ public static String decodeName(String name) {
+ StringBuffer buf = new StringBuffer();
+ try {
+ int len = name.length();
+ for (int k = 1; k < len; ++k) {
+ char c = name.charAt(k);
+ if (c == '#') {
+ char c1 = name.charAt(k + 1);
+ char c2 = name.charAt(k + 2);
+ c = (char)((PRTokeniser.getHex(c1) << 4) + PRTokeniser.getHex(c2));
+ k += 2;
+ }
+ buf.append(c);
+ }
+ }
+ catch (IndexOutOfBoundsException e) {
+ // empty on purpose
+ }
+ return buf.toString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfNameTree.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfNameTree.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfNameTree.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfNameTree.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.HashMap;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.io.IOException;
+import pdftk.com.lowagie.text.StringCompare;
+
+/**
+ * Creates a name tree.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfNameTree {
+
+ private static final int leafSize = 64;
+ private static final StringCompare stringCompare = new StringCompare();
+
+ /**
+ * Creates a name tree.
+ * @param items the item of the name tree. The key is a String
+ * and the value is a PdfIndirectReference
. Note that although the
+ * keys are strings only the lower byte is used and no check is made for chars
+ * with the same lower byte and different upper byte. This will generate a wrong
+ * tree name.
+ * @param writer the writer
+ * @throws IOException on error
+ * @return the dictionary with the name tree. This dictionary is the one
+ * generally pointed to by the key /Dests
+ */
+ public static PdfDictionary writeTree(HashMap items, PdfWriter writer) throws IOException {
+ if (items.size() == 0)
+ return null;
+ String names[] = new String[items.size()];
+ names = (String[])items.keySet().toArray(names);
+ Arrays.sort(names, stringCompare);
+ if (names.length <= leafSize) {
+ PdfDictionary dic = new PdfDictionary();
+ PdfArray ar = new PdfArray();
+ for (int k = 0; k < names.length; ++k) {
+ // ar.add(new PdfString(names[k], null));
+ // ssteward, pdftk 1.0: Acrobat 5 expects unicode encoded text strings in
+ // its EmbeddedFiles name tree, so I added the TEXT_UNICODE option here and throughout;
+ // looks like an Acro5 bug to me;
+ ar.add(new PdfString(names[k], PdfObject.TEXT_UNICODE )); // ssteward
+ ar.add((PdfIndirectReference)items.get(names[k]));
+ }
+ dic.put(PdfName.NAMES, ar);
+ return dic;
+ }
+ int skip = leafSize;
+ PdfIndirectReference kids[] = new PdfIndirectReference[(names.length + leafSize - 1) / leafSize];
+ for (int k = 0; k < kids.length; ++k) {
+ int offset = k * leafSize;
+ int end = Math.min(offset + leafSize, names.length);
+ PdfDictionary dic = new PdfDictionary();
+ PdfArray arr = new PdfArray();
+ //arr.add(new PdfString(names[offset], null));
+ arr.add(new PdfString(names[offset], PdfObject.TEXT_UNICODE)); // ssteward
+ //arr.add(new PdfString(names[end - 1], null));
+ arr.add(new PdfString(names[end - 1], PdfObject.TEXT_UNICODE)); // ssteward
+ dic.put(PdfName.LIMITS, arr);
+ arr = new PdfArray();
+ for (; offset < end; ++offset) {
+ //arr.add(new PdfString(names[offset], null));
+ arr.add(new PdfString(names[offset], PdfObject.TEXT_UNICODE)); // ssteward
+ arr.add((PdfIndirectReference)items.get(names[offset]));
+ }
+ dic.put(PdfName.NAMES, arr);
+ kids[k] = writer.addToBody(dic).getIndirectReference();
+ }
+ int top = kids.length;
+ while (true) {
+ if (top <= leafSize) {
+ PdfArray arr = new PdfArray();
+ for (int k = 0; k < top; ++k)
+ arr.add(kids[k]);
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.KIDS, arr);
+ return dic;
+ }
+ skip *= leafSize;
+ int tt = (names.length + skip - 1 )/ skip;
+ for (int k = 0; k < tt; ++k) {
+ int offset = k * leafSize;
+ int end = Math.min(offset + leafSize, top);
+ PdfDictionary dic = new PdfDictionary();
+ PdfArray arr = new PdfArray();
+ //arr.add(new PdfString(names[k * skip], null));
+ arr.add(new PdfString(names[k * skip], PdfObject.TEXT_UNICODE)); // ssteward
+ //arr.add(new PdfString(names[Math.min((k + 1) * skip, names.length) - 1], null));
+ arr.add(new PdfString(names[Math.min((k + 1) * skip, names.length) - 1], PdfObject.TEXT_UNICODE)); // ssteward
+ dic.put(PdfName.LIMITS, arr);
+ arr = new PdfArray();
+ for (; offset < end; ++offset) {
+ arr.add(kids[offset]);
+ }
+ dic.put(PdfName.KIDS, arr);
+ kids[k] = writer.addToBody(dic).getIndirectReference();
+ }
+ top = tt;
+ }
+ }
+
+ private static void iterateItems(PdfDictionary dic, HashMap items) {
+ PdfArray nn = (PdfArray)PdfReader.getPdfObjectRelease(dic.get(PdfName.NAMES));
+ if (nn != null) {
+ ArrayList arr = nn.getArrayList();
+ for (int k = 0; k < arr.size(); ++k) {
+ PdfString s = (PdfString)PdfReader.getPdfObjectRelease((PdfObject)arr.get(k++));
+ //items.put(s.toString(), arr.get(k));
+ items.put(s.toUnicodeString(), arr.get(k)); // ssteward; to match above changes
+ }
+ }
+ else if ((nn = (PdfArray)PdfReader.getPdfObjectRelease(dic.get(PdfName.KIDS))) != null) {
+ ArrayList arr = nn.getArrayList();
+ for (int k = 0; k < arr.size(); ++k) {
+ PdfDictionary kid = (PdfDictionary)PdfReader.getPdfObjectRelease((PdfObject)arr.get(k));
+ iterateItems(kid, items);
+ }
+ }
+ }
+
+ public static HashMap readTree(PdfDictionary dic) {
+ HashMap items = new HashMap();
+ if (dic != null)
+ iterateItems(dic, items);
+ return items;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfNull.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfNull.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfNull.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfNull.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,73 @@
+/*
+ * $Id: PdfNull.java,v 1.22 2002/06/20 13:30:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * PdfNull
is the Null object represented by the keyword null .
+ *
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.9 (page 53).
+ *
+ * @see PdfObject
+ */
+
+public class PdfNull extends PdfObject {
+
+ // static membervariables
+
+/** This is an instance of the PdfNull
-object. */
+ public static final PdfNull PDFNULL = new PdfNull();
+
+/** This is the content of a PdfNull
-object. */
+ private static final String CONTENT = "null";
+
+ // constructors
+
+/**
+ * Constructs a PdfNull
-object.
+ *
+ * You never need to do this yourself, you can always use the static final object PDFNULL .
+ */
+
+ public PdfNull() {
+ super(m_NULL, CONTENT); // ssteward
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfNumber.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfNumber.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfNumber.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfNumber.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,149 @@
+/*
+ * $Id: PdfNumber.java,v 1.24 2002/07/09 11:28:23 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * PdfNumber
provides two types of numbers, integer and real.
+ *
+ * Integers may be specified by signed or unsigned constants. Reals may only be
+ * in decimal format.
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 4.3 (page 37).
+ *
+ * @see PdfObject
+ * @see BadPdfFormatException
+ */
+
+public class PdfNumber extends PdfObject {
+
+/** actual value of this PdfNumber
, represented as a double
*/
+ private double value;
+
+ // constructors
+
+/**
+ * Constructs a PdfNumber
-object.
+ *
+ * @param content value of the new PdfNumber
-object
+ */
+
+ public PdfNumber(String content) {
+ super(NUMBER);
+ try {
+ value = Double.valueOf(content.trim()).doubleValue();
+ setContent(content);
+ }
+ catch (NumberFormatException nfe){
+ throw new RuntimeException(content + " is not a valid number - " + nfe.toString());
+ }
+ }
+
+/**
+ * Constructs a new INTEGER PdfNumber
-object.
+ *
+ * @param value value of the new PdfNumber
-object
+ */
+
+ public PdfNumber(int value) {
+ super(NUMBER);
+ this.value = value;
+ setContent(String.valueOf(value));
+ }
+
+/**
+ * Constructs a new REAL PdfNumber
-object.
+ *
+ * @param value value of the new PdfNumber
-object
+ */
+
+ public PdfNumber(double value) {
+ super(NUMBER);
+ this.value = value;
+ setContent(ByteBuffer.formatDouble(value));
+ }
+
+/**
+ * Constructs a new REAL PdfNumber
-object.
+ *
+ * @param value value of the new PdfNumber
-object
+ */
+
+ public PdfNumber(float value) {
+ this((double)value);
+ }
+
+ // methods returning the value of this object
+
+/**
+ * Returns the primitive int
value of this object.
+ *
+ * @return a value
+ */
+
+ public int intValue() {
+ return (int) value;
+ }
+
+/**
+ * Returns the primitive double
value of this object.
+ *
+ * @return a value
+ */
+
+ public double doubleValue() {
+ return value;
+ }
+
+ public float floatValue() {
+ return (float)value;
+ }
+
+ // other methods
+
+/**
+ * Increments the value of the PdfNumber
-object with 1.
+ */
+
+ public void increment() {
+ value += 1.0;
+ setContent(ByteBuffer.formatDouble(value));
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfNumberTree.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfNumberTree.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfNumberTree.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfNumberTree.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2005 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.HashMap;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.io.IOException;
+
+/**
+ * Creates a number tree.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfNumberTree {
+
+ private static final int leafSize = 64;
+
+ /**
+ * Creates a number tree.
+ * @param items the item of the number tree. The key is an Integer
+ * and the value is a PdfIndirectReference
.
+ * @param writer the writer
+ * @throws IOException on error
+ * @return the dictionary with the number tree.
+ */
+ public static PdfDictionary writeTree(HashMap items, PdfWriter writer) throws IOException {
+ if (items.size() == 0)
+ return null;
+ Integer numbers[] = new Integer[items.size()];
+ numbers = (Integer[])items.keySet().toArray(numbers);
+ Arrays.sort(numbers);
+ if (numbers.length <= leafSize) {
+ PdfDictionary dic = new PdfDictionary();
+ PdfArray ar = new PdfArray();
+ for (int k = 0; k < numbers.length; ++k) {
+ ar.add(new PdfNumber(numbers[k].intValue()));
+ ar.add((PdfIndirectReference)items.get(numbers[k]));
+ }
+ dic.put(PdfName.NUMS, ar);
+ return dic;
+ }
+ int skip = leafSize;
+ PdfIndirectReference kids[] = new PdfIndirectReference[(numbers.length + leafSize - 1) / leafSize];
+ for (int k = 0; k < kids.length; ++k) {
+ int offset = k * leafSize;
+ int end = Math.min(offset + leafSize, numbers.length);
+ PdfDictionary dic = new PdfDictionary();
+ PdfArray arr = new PdfArray();
+ arr.add(new PdfNumber(numbers[offset].intValue()));
+ arr.add(new PdfNumber(numbers[end - 1].intValue()));
+ dic.put(PdfName.LIMITS, arr);
+ arr = new PdfArray();
+ for (; offset < end; ++offset) {
+ arr.add(new PdfNumber(numbers[offset].intValue()));
+ arr.add((PdfIndirectReference)items.get(numbers[offset]));
+ }
+ dic.put(PdfName.NUMS, arr);
+ kids[k] = writer.addToBody(dic).getIndirectReference();
+ }
+ int top = kids.length;
+ while (true) {
+ if (top <= leafSize) {
+ PdfArray arr = new PdfArray();
+ for (int k = 0; k < top; ++k)
+ arr.add(kids[k]);
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.KIDS, arr);
+ return dic;
+ }
+ skip *= leafSize;
+ int tt = (numbers.length + skip - 1 )/ skip;
+ for (int k = 0; k < tt; ++k) {
+ int offset = k * leafSize;
+ int end = Math.min(offset + leafSize, top);
+ PdfDictionary dic = new PdfDictionary();
+ PdfArray arr = new PdfArray();
+ arr.add(new PdfNumber(numbers[k * skip].intValue()));
+ arr.add(new PdfNumber(numbers[Math.min((k + 1) * skip, numbers.length) - 1].intValue()));
+ dic.put(PdfName.LIMITS, arr);
+ arr = new PdfArray();
+ for (; offset < end; ++offset) {
+ arr.add(kids[offset]);
+ }
+ dic.put(PdfName.KIDS, arr);
+ kids[k] = writer.addToBody(dic).getIndirectReference();
+ }
+ top = tt;
+ }
+ }
+
+ private static void iterateItems(PdfDictionary dic, HashMap items) {
+ PdfArray nn = (PdfArray)PdfReader.getPdfObjectRelease(dic.get(PdfName.NUMS));
+ if (nn != null) {
+ ArrayList arr = nn.getArrayList();
+ for (int k = 0; k < arr.size(); ++k) {
+ PdfNumber s = (PdfNumber)PdfReader.getPdfObjectRelease((PdfObject)arr.get(k++));
+ items.put(new Integer(s.intValue()), arr.get(k));
+ }
+ }
+ else if ((nn = (PdfArray)PdfReader.getPdfObjectRelease(dic.get(PdfName.KIDS))) != null) {
+ ArrayList arr = nn.getArrayList();
+ for (int k = 0; k < arr.size(); ++k) {
+ PdfDictionary kid = (PdfDictionary)PdfReader.getPdfObjectRelease((PdfObject)arr.get(k));
+ iterateItems(kid, items);
+ }
+ }
+ }
+
+ public static HashMap readTree(PdfDictionary dic) {
+ HashMap items = new HashMap();
+ if (dic != null)
+ iterateItems(dic, items);
+ return items;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfOCG.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfOCG.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfOCG.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfOCG.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * The interface common to all layer types.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public interface PdfOCG {
+
+ /**
+ * Gets the PdfIndirectReference
that represents this layer.
+ * @return the PdfIndirectReference
that represents this layer
+ */
+ public PdfIndirectReference getRef();
+
+ /**
+ * Gets the object representing the layer.
+ * @return the object representing the layer
+ */
+ public PdfObject getPdfObject();
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfOCProperties.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfOCProperties.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfOCProperties.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfOCProperties.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * This class represents the /OCProperties entry in the document catalog
+ * and holds the optional content properties dictionary, which contains
+ * a list of all the optional content groups in the document, as well as information
+ * about the default and alternate configurations for optional content.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfOCProperties extends PdfDictionary {
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfObject.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfObject.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfObject.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfObject.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,365 @@
+/*
+ * $Id: PdfObject.java,v 1.26 2002/07/09 11:28:23 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * PdfObject
is the abstract superclass of all PDF objects.
+ *
+ * PDF supports seven basic types of objects: Booleans, numbers, strings, names,
+ * arrays, dictionaries and streams. In addition, PDF provides a null object.
+ * Objects may be labeled so that they can be referred to by other objects.
+ * All these basic PDF objects are described in the 'Portable Document Format
+ * Reference Manual version 1.3' Chapter 4 (pages 37-54).
+ *
+ * @see PdfNull
+ * @see PdfBoolean
+ * @see PdfNumber
+ * @see PdfString
+ * @see PdfName
+ * @see PdfArray
+ * @see PdfDictionary
+ * @see PdfStream
+ * @see PdfIndirectReference
+ */
+
+public abstract class PdfObject {
+
+ // static membervariables (all the possible types of a PdfObject)
+
+/** a possible type of PdfObject
*/
+ public static final int BOOLEAN = 1;
+
+/** a possible type of PdfObject
*/
+ public static final int NUMBER = 2;
+
+/** a possible type of PdfObject
*/
+ public static final int STRING = 3;
+
+/** a possible type of PdfObject
*/
+ public static final int NAME = 4;
+
+/** a possible type of PdfObject
*/
+ public static final int ARRAY = 5;
+
+/** a possible type of PdfObject
*/
+ public static final int DICTIONARY = 6;
+
+/** a possible type of PdfObject
*/
+ public static final int STREAM = 7;
+
+/** a possible type of PdfObject
*/
+ // ssteward
+ //public static final int NULL = 8;
+ // renamed this member to m_NULL to prevent confusion w/ gcj
+ public static final int m_NULL = 8;
+
+ /** a possible type of PdfObject
*/
+ public static final int INDIRECT = 10;
+
+/** This is an empty string used for the PdfNull
-object and for an empty PdfString
-object. */
+ public static final String NOTHING = "";
+
+/** This is the default encoding to be used for converting Strings into bytes and vice versa.
+ * The default encoding is PdfDocEncoding.
+ */
+ public static final String TEXT_PDFDOCENCODING = "PDF";
+
+/** This is the encoding to be used to output text in Unicode. */
+ //public static final String TEXT_UNICODE = "UnicodeBig";
+ public static final String TEXT_UNICODE = "UTF-16"; // ssteward; uses byte order mark
+
+ // membervariables
+
+/** the content of this PdfObject
*/
+ protected byte[] bytes;
+
+/** the type of this PdfObject
*/
+ protected int type;
+
+ /**
+ * Holds value of property indRef.
+ */
+ protected PRIndirectReference indRef;
+
+ // constructors
+
+/**
+ * Constructs a PdfObject
of a certain type without any content .
+ *
+ * @param type type of the new PdfObject
+ */
+
+ protected PdfObject(int type) {
+ this.type = type;
+ this.bytes = null;
+ }
+
+/**
+ * Constructs a PdfObject
of a certain type with a certain content .
+ *
+ * @param type type of the new PdfObject
+ * @param content content of the new PdfObject
as a String
.
+ */
+
+ protected PdfObject(int type, String content) {
+ this.type = type;
+ bytes = PdfEncodings.convertToBytes(content, null);
+ }
+
+/**
+ * Constructs a PdfObject
of a certain type with a certain content .
+ *
+ * @param type type of the new PdfObject
+ * @param bytes content of the new PdfObject
as an array of byte
.
+ */
+
+ protected PdfObject(int type, byte[] bytes) {
+ this.bytes = bytes;
+ this.type = type;
+ }
+
+ // methods dealing with the content of this object
+
+/**
+ * Writes the PDF representation of this PdfObject
as an array of byte
s to the writer.
+ * @param writer for backwards compatibility
+ * @param os the outputstream to write the bytes to.
+ * @throws IOException
+ */
+
+ public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+ if (bytes != null)
+ os.write(bytes);
+ }
+
+ /**
+ * Gets the presentation of this object in a byte array
+ * @return a byte array
+ */
+ public byte[] getBytes() {
+ return bytes;
+ }
+
+ /**
+ * Can this object be in an object stream?
+ * @return true if this object can be in an object stream.
+ */
+ public boolean canBeInObjStm() {
+ return (type >= 1 && type <= 6) || type == 8;
+ }
+
+/**
+ * Returns the length of the PDF representation of the PdfObject
.
+ *
+ * In some cases, namely for PdfString
and PdfStream
,
+ * this method differs from the method length
because length
+ * returns the length of the actual content of the PdfObject
.
+ *
+ * Remark: the actual content of an object is in most cases identical to its representation.
+ * The following statement is always true: length() >= pdfLength().
+ *
+ * @return a length
+ */
+
+// public int pdfLength() {
+// return toPdf(null).length;
+// }
+
+/**
+ * Returns the String
-representation of this PdfObject
.
+ *
+ * @return a String
+ */
+
+ public String toString() {
+ if (bytes == null)
+ return super.toString();
+ else
+ return PdfEncodings.convertToString(bytes, null);
+ }
+
+/**
+ * Returns the length of the actual content of the PdfObject
.
+ *
+ * In some cases, namely for PdfString
and PdfStream
,
+ * this method differs from the method pdfLength
because pdfLength
+ * returns the length of the PDF representation of the object, not of the actual content
+ * as does the method length
.
+ *
+ * Remark: the actual content of an object is in some cases identical to its representation.
+ * The following statement is always true: length() >= pdfLength().
+ *
+ * @return a length
+ */
+
+ public int length() {
+ return toString().length();
+ }
+
+/**
+ * Changes the content of this PdfObject
.
+ *
+ * @param content the new content of this PdfObject
+ */
+
+ protected void setContent(String content) {
+ bytes = PdfEncodings.convertToBytes(content, null);
+ }
+
+ // methods dealing with the type of this object
+
+/**
+ * Returns the type of this PdfObject
.
+ *
+ * @return a type
+ */
+
+ public int type() {
+ return type;
+ }
+
+/**
+ * Checks if this PdfObject
is of the type PdfNull
.
+ *
+ * @return true
or false
+ */
+
+ public boolean isNull() {
+ return (this.type == m_NULL); // ssteward
+ }
+
+/**
+ * Checks if this PdfObject
is of the type PdfBoolean
.
+ *
+ * @return true
or false
+ */
+
+ public boolean isBoolean() {
+ return (this.type == BOOLEAN);
+ }
+
+/**
+ * Checks if this PdfObject
is of the type PdfNumber
.
+ *
+ * @return true
or false
+ */
+
+ public boolean isNumber() {
+ return (this.type == NUMBER);
+ }
+
+/**
+ * Checks if this PdfObject
is of the type PdfString
.
+ *
+ * @return true
or false
+ */
+
+ public boolean isString() {
+ return (this.type == STRING);
+ }
+
+/**
+ * Checks if this PdfObject
is of the type PdfName
.
+ *
+ * @return true
or false
+ */
+
+ public boolean isName() {
+ return (this.type == NAME);
+ }
+
+/**
+ * Checks if this PdfObject
is of the type PdfArray
.
+ *
+ * @return true
or false
+ */
+
+ public boolean isArray() {
+ return (this.type == ARRAY);
+ }
+
+/**
+ * Checks if this PdfObject
is of the type PdfDictionary
.
+ *
+ * @return true
or false
+ */
+
+ public boolean isDictionary() {
+ return (this.type == DICTIONARY);
+ }
+
+/**
+ * Checks if this PdfObject
is of the type PdfStream
.
+ *
+ * @return true
or false
+ */
+
+ public boolean isStream() {
+ return (this.type == STREAM);
+ }
+
+ /**
+ * Checks if this is an indirect object.
+ * @return true if this is an indirect object
+ */
+ public boolean isIndirect() {
+ return (this.type == INDIRECT);
+ }
+
+ /**
+ * Getter for property indRef.
+ * @return Value of property indRef.
+ */
+ public PRIndirectReference getIndRef() {
+ return this.indRef;
+ }
+
+ /**
+ * Setter for property indRef.
+ * @param indRef New value of property indRef.
+ */
+ public void setIndRef(PRIndirectReference indRef) {
+ this.indRef = indRef;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfOutline.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfOutline.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfOutline.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfOutline.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,532 @@
+/*
+ * $Id: PdfOutline.java,v 1.51 2005/01/05 10:05:20 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.Iterator;
+
+import pdftk.com.lowagie.text.Chunk;
+import pdftk.com.lowagie.text.Paragraph;
+import java.util.ArrayList;
+import java.awt.Color;
+import pdftk.com.lowagie.text.Font;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * PdfOutline
is an object that represents a PDF outline entry.
+ *
+ * An outline allows a user to access views of a document by name.
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 6.7 (page 104-106)
+ *
+ * @see PdfDictionary
+ */
+
+public class PdfOutline extends PdfDictionary {
+
+ // membervariables
+
+ /** the PdfIndirectReference
of this object */
+ private PdfIndirectReference reference;
+
+ /** value of the Count -key */
+ private int count = 0;
+
+ /** value of the Parent -key */
+ private PdfOutline parent;
+
+ /** value of the Destination -key */
+ private PdfDestination destination;
+
+ /** The PdfAction
for this outline.
+ */
+ private PdfAction action;
+
+ protected ArrayList kids = new ArrayList();
+
+ protected PdfWriter writer;
+
+ /** Holds value of property tag. */
+ private String tag;
+
+ /** Holds value of property open. */
+ private boolean open;
+
+ /** Holds value of property color. */
+ private Color color;
+
+ /** Holds value of property style. */
+ private int style = 0;
+
+ // constructors
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for the outlines object
.
+ *
+ * @param writer The PdfWriter you are adding the outline to
+ */
+
+ PdfOutline(PdfWriter writer) {
+ super(OUTLINES);
+ open = true;
+ parent = null;
+ this.writer = writer;
+ }
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for an outline entry
. The open mode is
+ * true
.
+ *
+ * @param parent the parent of this outline item
+ * @param action the PdfAction
for this outline item
+ * @param title the title of this outline item
+ */
+
+ public PdfOutline(PdfOutline parent, PdfAction action, String title) {
+ this(parent, action, title, true);
+ }
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for an outline entry
.
+ *
+ * @param parent the parent of this outline item
+ * @param action the PdfAction
for this outline item
+ * @param title the title of this outline item
+ * @param open true
if the children are visible
+ */
+ public PdfOutline(PdfOutline parent, PdfAction action, String title, boolean open) {
+ super();
+ this.action = action;
+ initOutline(parent, title, open);
+ }
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for an outline entry
. The open mode is
+ * true
.
+ *
+ * @param parent the parent of this outline item
+ * @param destination the destination for this outline item
+ * @param title the title of this outline item
+ */
+
+ public PdfOutline(PdfOutline parent, PdfDestination destination, String title) {
+ this(parent, destination, title, true);
+ }
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for an outline entry
.
+ *
+ * @param parent the parent of this outline item
+ * @param destination the destination for this outline item
+ * @param title the title of this outline item
+ * @param open true
if the children are visible
+ */
+ public PdfOutline(PdfOutline parent, PdfDestination destination, String title, boolean open) {
+ super();
+ this.destination = destination;
+ initOutline(parent, title, open);
+ }
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for an outline entry
. The open mode is
+ * true
.
+ *
+ * @param parent the parent of this outline item
+ * @param action the PdfAction
for this outline item
+ * @param title the title of this outline item
+ */
+ public PdfOutline(PdfOutline parent, PdfAction action, PdfString title) {
+ this(parent, action, title, true);
+ }
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for an outline entry
.
+ *
+ * @param parent the parent of this outline item
+ * @param action the PdfAction
for this outline item
+ * @param title the title of this outline item
+ * @param open true
if the children are visible
+ */
+ public PdfOutline(PdfOutline parent, PdfAction action, PdfString title, boolean open) {
+ this(parent, action, title.toString(), true);
+ }
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for an outline entry
. The open mode is
+ * true
.
+ *
+ * @param parent the parent of this outline item
+ * @param destination the destination for this outline item
+ * @param title the title of this outline item
+ */
+
+ public PdfOutline(PdfOutline parent, PdfDestination destination, PdfString title) {
+ this(parent, destination, title, true);
+ }
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for an outline entry
.
+ *
+ * @param parent the parent of this outline item
+ * @param destination the destination for this outline item
+ * @param title the title of this outline item
+ * @param open true
if the children are visible
+ */
+ public PdfOutline(PdfOutline parent, PdfDestination destination, PdfString title, boolean open) {
+ this(parent, destination, title.toString(), true);
+ }
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for an outline entry
. The open mode is
+ * true
.
+ *
+ * @param parent the parent of this outline item
+ * @param action the PdfAction
for this outline item
+ * @param title the title of this outline item
+ */
+
+ public PdfOutline(PdfOutline parent, PdfAction action, Paragraph title) {
+ this(parent, action, title, true);
+ }
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for an outline entry
.
+ *
+ * @param parent the parent of this outline item
+ * @param action the PdfAction
for this outline item
+ * @param title the title of this outline item
+ * @param open true
if the children are visible
+ */
+ public PdfOutline(PdfOutline parent, PdfAction action, Paragraph title, boolean open) {
+ super();
+ StringBuffer buf = new StringBuffer();
+ for (Iterator i = title.getChunks().iterator(); i.hasNext(); ) {
+ Chunk chunk = (Chunk) i.next();
+ buf.append(chunk.content());
+ }
+ this.action = action;
+ initOutline(parent, buf.toString(), open);
+ }
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for an outline entry
. The open mode is
+ * true
.
+ *
+ * @param parent the parent of this outline item
+ * @param destination the destination for this outline item
+ * @param title the title of this outline item
+ */
+
+ public PdfOutline(PdfOutline parent, PdfDestination destination, Paragraph title) {
+ this(parent, destination, title, true);
+ }
+
+ /**
+ * Constructs a PdfOutline
.
+ *
+ * This is the constructor for an outline entry
.
+ *
+ * @param parent the parent of this outline item
+ * @param destination the destination for this outline item
+ * @param title the title of this outline item
+ * @param open true
if the children are visible
+ */
+ public PdfOutline(PdfOutline parent, PdfDestination destination, Paragraph title, boolean open) {
+ super();
+ StringBuffer buf = new StringBuffer();
+ for (Iterator i = title.getChunks().iterator(); i.hasNext(); ) {
+ Chunk chunk = (Chunk) i.next();
+ buf.append(chunk.content());
+ }
+ this.destination = destination;
+ initOutline(parent, buf.toString(), open);
+ }
+
+
+ // methods
+
+ /** Helper for the constructors.
+ * @param parent the parent outline
+ * @param title the title for this outline
+ * @param open true
if the children are visible
+ */
+ void initOutline(PdfOutline parent, String title, boolean open) {
+ this.open = open;
+ this.parent = parent;
+ writer = parent.writer;
+ put(PdfName.TITLE, new PdfString(title, PdfObject.TEXT_UNICODE));
+ parent.addKid(this);
+ if (destination != null && !destination.hasPage()) // bugfix Finn Bock
+ setDestinationPage(writer.getCurrentPage());
+ }
+
+ /**
+ * Sets the indirect reference of this PdfOutline
.
+ *
+ * @param reference the PdfIndirectReference
to this outline.
+ */
+
+ public void setIndirectReference(PdfIndirectReference reference) {
+ this.reference = reference;
+ }
+
+ /**
+ * Gets the indirect reference of this PdfOutline
.
+ *
+ * @return the PdfIndirectReference
to this outline.
+ */
+
+ public PdfIndirectReference indirectReference() {
+ return reference;
+ }
+
+ /**
+ * Gets the parent of this PdfOutline
.
+ *
+ * @return the PdfOutline
that is the parent of this outline.
+ */
+
+ public PdfOutline parent() {
+ return parent;
+ }
+
+ /**
+ * Set the page of the PdfDestination
-object.
+ *
+ * @param pageReference indirect reference to the page
+ * @return true
if this page was set as the PdfDestination
-page.
+ */
+
+ public boolean setDestinationPage(PdfIndirectReference pageReference) {
+ if (destination == null) {
+ return false;
+ }
+ return destination.addPage(pageReference);
+ }
+
+ /**
+ * Gets the destination for this outline.
+ * @return the destination
+ */
+ public PdfDestination getPdfDestination() {
+ return destination;
+ }
+
+ int getCount() {
+ return count;
+ }
+
+ void setCount(int count) {
+ this.count = count;
+ }
+
+ /**
+ * returns the level of this outline.
+ *
+ * @return a level
+ */
+
+ public int level() {
+ if (parent == null) {
+ return 0;
+ }
+ return (parent.level() + 1);
+ }
+
+ /**
+ * Returns the PDF representation of this PdfOutline
.
+ *
+ * @param writer the encryption information
+ * @param os
+ * @throws IOException
+ */
+
+ public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+ if (color != null && !color.equals(Color.black)) {
+ put(PdfName.C, new PdfArray(new float[]{color.getRed()/255f,color.getGreen()/255f,color.getBlue()/255f}));
+ }
+ int flag = 0;
+ if ((style & Font.BOLD) != 0)
+ flag |= 2;
+ if ((style & Font.ITALIC) != 0)
+ flag |= 1;
+ if (flag != 0)
+ put(PdfName.F, new PdfNumber(flag));
+ if (parent != null) {
+ put(PdfName.PARENT, parent.indirectReference());
+ }
+ if (destination != null && destination.hasPage()) {
+ put(PdfName.DEST, destination);
+ }
+ if (action != null)
+ put(PdfName.A, action);
+ if (count != 0) {
+ put(PdfName.COUNT, new PdfNumber(count));
+ }
+ super.toPdf(writer, os);
+ }
+
+ /**
+ * Adds a kid to the outline
+ * @param outline
+ */
+ public void addKid(PdfOutline outline) {
+ kids.add(outline);
+ }
+
+ /**
+ * Returns the kids of this outline
+ * @return an ArrayList with PdfOutlines
+ */
+ public ArrayList getKids() {
+ return kids;
+ }
+
+ /**
+ * Sets the kids of this outline
+ * @param kids
+ */
+ public void setKids(ArrayList kids) {
+ this.kids = kids;
+ }
+
+ /** Getter for property tag.
+ * @return Value of property tag.
+ */
+ public String getTag() {
+ return tag;
+ }
+
+ /** Setter for property tag.
+ * @param tag New value of property tag.
+ */
+ public void setTag(String tag) {
+ this.tag = tag;
+ }
+
+ /**
+ * Gets the title of this outline
+ * @return the title as a String
+ */
+ public String getTitle() {
+ PdfString title = (PdfString)get(PdfName.TITLE);
+ return title.toString();
+ }
+
+ /**
+ * Sets the title of this outline
+ * @param title
+ */
+ public void setTitle(String title) {
+ put(PdfName.TITLE, new PdfString(title, PdfObject.TEXT_UNICODE));
+ }
+
+ /** Getter for property open.
+ * @return Value of property open.
+ */
+ public boolean isOpen() {
+ return open;
+ }
+
+ /** Setter for property open.
+ * @param open New value of property open.
+ */
+ public void setOpen(boolean open) {
+ this.open = open;
+ }
+
+ /** Getter for property color.
+ * @return Value of property color.
+ *
+ */
+ public Color getColor() {
+ return this.color;
+ }
+
+ /** Setter for property color.
+ * @param color New value of property color.
+ *
+ */
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ /** Getter for property style.
+ * @return Value of property style.
+ *
+ */
+ public int getStyle() {
+ return this.style;
+ }
+
+ /** Setter for property style.
+ * @param style New value of property style.
+ *
+ */
+ public void setStyle(int style) {
+ this.style = style;
+ }
+
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPKCS7.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPKCS7.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPKCS7.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPKCS7.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,1266 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.FileInputStream;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.MessageDigest;
+import java.security.SignatureException;
+import java.security.cert.CRL;
+import java.security.cert.CRLException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.security.KeyStore;
+import java.io.File;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+import pdftk.org.bouncycastle.asn1.ASN1InputStream;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSet;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERNull;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.DERSet;
+import pdftk.org.bouncycastle.asn1.ASN1String;
+import pdftk.org.bouncycastle.asn1.DERUTCTime;
+import pdftk.org.bouncycastle.asn1.ASN1OutputStream;
+
+/**
+ * This class does all the processing related to signing and verifying a PKCS#7
+ * signature.
+ *
+ * It's based in code found at pdftk.org.bouncycastle.
+ */
+public class PdfPKCS7 {
+
+ private byte sigAttr[];
+ private byte digestAttr[];
+ private int version, signerversion;
+ private Set digestalgos;
+ private Collection certs, crls;
+ private X509Certificate signCert;
+ private byte[] digest;
+ private MessageDigest messageDigest;
+ private String digestAlgorithm, digestEncryptionAlgorithm;
+ private Signature sig;
+ private transient PrivateKey privKey;
+ private byte RSAdata[];
+ private boolean verified;
+ private boolean verifyResult;
+ private byte externalDigest[];
+ private byte externalRSAdata[];
+
+ private static final String ID_PKCS7_DATA = "1.2.840.113549.1.7.1";
+ private static final String ID_PKCS7_SIGNED_DATA = "1.2.840.113549.1.7.2";
+ private static final String ID_MD5 = "1.2.840.113549.2.5";
+ private static final String ID_MD2 = "1.2.840.113549.2.2";
+ private static final String ID_SHA1 = "1.3.14.3.2.26";
+ private static final String ID_RSA = "1.2.840.113549.1.1.1";
+ private static final String ID_DSA = "1.2.840.10040.4.1";
+ private static final String ID_CONTENT_TYPE = "1.2.840.113549.1.9.3";
+ private static final String ID_MESSAGE_DIGEST = "1.2.840.113549.1.9.4";
+ private static final String ID_SIGNING_TIME = "1.2.840.113549.1.9.5";
+ private static final String ID_MD2RSA = "1.2.840.113549.1.1.2";
+ private static final String ID_MD5RSA = "1.2.840.113549.1.1.4";
+ private static final String ID_SHA1RSA = "1.2.840.113549.1.1.5";
+ /**
+ * Holds value of property reason.
+ */
+ private String reason;
+
+ /**
+ * Holds value of property location.
+ */
+ private String location;
+
+ /**
+ * Holds value of property signDate.
+ */
+ private Calendar signDate;
+
+ /**
+ * Holds value of property signName.
+ */
+ private String signName;
+
+ /**
+ * Verifies a signature using the sub-filter adbe.x509.rsa_sha1.
+ * @param contentsKey the /Contents key
+ * @param certsKey the /Cert key
+ * @param provider the provider or null
for the default provider
+ * @throws SecurityException on error
+ * @throws CRLException on error
+ * @throws InvalidKeyException on error
+ * @throws CertificateException on error
+ * @throws NoSuchProviderException on error
+ * @throws NoSuchAlgorithmException on error
+ * @throws IOException on error
+ */
+ public PdfPKCS7(byte[] contentsKey, byte[] certsKey, String provider) throws SecurityException, CRLException, InvalidKeyException, CertificateException, NoSuchProviderException, NoSuchAlgorithmException, IOException {
+ CertificateFactory cf;
+ if (provider == null)
+ cf = CertificateFactory.getInstance("X.509");
+ else
+ cf = CertificateFactory.getInstance("X.509", provider);
+ if (provider == null)
+ certs = cf.generateCertificates(new ByteArrayInputStream(certsKey));
+ signCert = (X509Certificate)certs.iterator().next();
+ crls = new ArrayList();
+ ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(contentsKey));
+ digest = ((DEROctetString)in.readObject()).getOctets();
+ if (provider == null)
+ sig = Signature.getInstance("SHA1withRSA");
+ else
+ sig = Signature.getInstance("SHA1withRSA", provider);
+ sig.initVerify(signCert.getPublicKey());
+ }
+
+ /**
+ * Verifies a signature using the sub-filter adbe.pkcs7.detached or
+ * adbe.pkcs7.sha1.
+ * @param contentsKey the /Contents key
+ * @param provider the provider or null
for the default provider
+ * @throws SecurityException on error
+ * @throws CRLException on error
+ * @throws InvalidKeyException on error
+ * @throws CertificateException on error
+ * @throws NoSuchProviderException on error
+ * @throws NoSuchAlgorithmException on error
+ */
+ public PdfPKCS7(byte[] contentsKey, String provider) throws SecurityException, CRLException, InvalidKeyException, CertificateException, NoSuchProviderException, NoSuchAlgorithmException {
+ ASN1InputStream din = new ASN1InputStream(new ByteArrayInputStream(contentsKey));
+
+ //
+ // Basic checks to make sure it's a PKCS#7 SignedData Object
+ //
+ ASN1Primitive pkcs;
+
+ try {
+ pkcs = din.readObject();
+ }
+ catch (IOException e) {
+ throw new SecurityException("can't decode PKCS7SignedData object");
+ }
+ if (!(pkcs instanceof ASN1Sequence)) {
+ throw new SecurityException("Not a valid PKCS#7 object - not a sequence");
+ }
+ ASN1Sequence signedData = (ASN1Sequence)pkcs;
+ ASN1ObjectIdentifier objId = (ASN1ObjectIdentifier)signedData.getObjectAt(0);
+ if (!objId.getId().equals(ID_PKCS7_SIGNED_DATA))
+ throw new SecurityException("Not a valid PKCS#7 object - not signed data");
+ ASN1Sequence content = (ASN1Sequence)((DERTaggedObject)signedData.getObjectAt(1)).getObject();
+ // the positions that we care are:
+ // 0 - version
+ // 1 - digestAlgorithms
+ // 2 - possible ID_PKCS7_DATA
+ // (the certificates and crls are taken out by other means)
+ // last - signerInfos
+
+ // the version
+ version = ((ASN1Integer)content.getObjectAt(0)).getValue().intValue();
+
+ // the digestAlgorithms
+ digestalgos = new HashSet();
+ Enumeration e = ((ASN1Set)content.getObjectAt(1)).getObjects();
+ while (e.hasMoreElements())
+ {
+ ASN1Sequence s = (ASN1Sequence)e.nextElement();
+ ASN1ObjectIdentifier o = (ASN1ObjectIdentifier)s.getObjectAt(0);
+ digestalgos.add(o.getId());
+ }
+
+ // the certificates and crls
+ CertificateFactory cf;
+ if (provider == null)
+ cf = CertificateFactory.getInstance("X.509");
+ else
+ cf = CertificateFactory.getInstance("X.509", provider);
+ certs = cf.generateCertificates(new ByteArrayInputStream(contentsKey));
+ crls = cf.generateCRLs(new ByteArrayInputStream(contentsKey));
+
+ // the possible ID_PKCS7_DATA
+ ASN1Sequence rsaData = (ASN1Sequence)content.getObjectAt(2);
+ if (rsaData.size() > 1) {
+ DEROctetString rsaDataContent = (DEROctetString)((DERTaggedObject)rsaData.getObjectAt(1)).getObject();
+ RSAdata = rsaDataContent.getOctets();
+ }
+
+ // the signerInfos
+ int next = 3;
+ while (content.getObjectAt(next) instanceof DERTaggedObject)
+ ++next;
+ ASN1Set signerInfos = (ASN1Set)content.getObjectAt(next);
+ if (signerInfos.size() != 1)
+ throw new SecurityException("This PKCS#7 object has multiple SignerInfos - only one is supported at this time");
+ ASN1Sequence signerInfo = (ASN1Sequence)signerInfos.getObjectAt(0);
+ // the positions that we care are
+ // 0 - version
+ // 1 - the signing certificate serial number
+ // 2 - the digest algorithm
+ // 3 or 4 - digestEncryptionAlgorithm
+ // 4 or 5 - encryptedDigest
+ signerversion = ((ASN1Integer)signerInfo.getObjectAt(0)).getValue().intValue();
+ // Get the signing certificate
+ ASN1Sequence issuerAndSerialNumber = (ASN1Sequence)signerInfo.getObjectAt(1);
+ BigInteger serialNumber = ((ASN1Integer)issuerAndSerialNumber.getObjectAt(1)).getValue();
+ for (Iterator i = certs.iterator(); i.hasNext();) {
+ X509Certificate cert = (X509Certificate)i.next();
+ if (serialNumber.equals(cert.getSerialNumber())) {
+ signCert = cert;
+ break;
+ }
+ }
+ if (signCert == null) {
+ throw new SecurityException("Can't find signing certificate with serial " + serialNumber.toString(16));
+ }
+ digestAlgorithm = ((ASN1ObjectIdentifier)((ASN1Sequence)signerInfo.getObjectAt(2)).getObjectAt(0)).getId();
+ next = 3;
+ if (signerInfo.getObjectAt(next) instanceof ASN1TaggedObject) {
+ ASN1TaggedObject tagsig = (ASN1TaggedObject)signerInfo.getObjectAt(next);
+ ASN1Sequence sseq = (ASN1Sequence)tagsig.getObject();
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream dout = new ASN1OutputStream(bOut);
+ try {
+ ASN1EncodableVector attribute = new ASN1EncodableVector();
+ for (int k = 0; k < sseq.size(); ++k) {
+ attribute.add(sseq.getObjectAt(k));
+ }
+ dout.writeObject(new DERSet(attribute));
+ dout.close();
+ }
+ catch (IOException ioe){}
+ sigAttr = bOut.toByteArray();
+
+ for (int k = 0; k < sseq.size(); ++k) {
+ ASN1Sequence seq2 = (ASN1Sequence)sseq.getObjectAt(k);
+ if (((ASN1ObjectIdentifier)seq2.getObjectAt(0)).getId().equals(ID_MESSAGE_DIGEST)) {
+ ASN1Set set = (ASN1Set)seq2.getObjectAt(1);
+ digestAttr = ((DEROctetString)set.getObjectAt(0)).getOctets();
+ break;
+ }
+ }
+ if (digestAttr == null)
+ throw new SecurityException("Authenticated attribute is missing the digest.");
+ ++next;
+ }
+ digestEncryptionAlgorithm = ((ASN1ObjectIdentifier)((ASN1Sequence)signerInfo.getObjectAt(next++)).getObjectAt(0)).getId();
+ digest = ((DEROctetString)signerInfo.getObjectAt(next)).getOctets();
+ if (RSAdata != null || digestAttr != null) {
+ if (provider == null || provider.startsWith("SunPKCS11"))
+ messageDigest = MessageDigest.getInstance(getHashAlgorithm());
+ else
+ messageDigest = MessageDigest.getInstance(getHashAlgorithm(), provider);
+ }
+ if (provider == null)
+ sig = Signature.getInstance(getDigestAlgorithm());
+ else
+ sig = Signature.getInstance(getDigestAlgorithm(), provider);
+ sig.initVerify(signCert.getPublicKey());
+ }
+
+ /**
+ * Generates a signature.
+ * @param privKey the private key
+ * @param certChain the certificate chain
+ * @param crlList the certificate revocation list
+ * @param hashAlgorithm the hash algorithm
+ * @param provider the provider or null
for the default provider
+ * @param hasRSAdata true
if the sub-filter is adbe.pkcs7.sha1
+ * @throws SecurityException on error
+ * @throws InvalidKeyException on error
+ * @throws NoSuchProviderException on error
+ * @throws NoSuchAlgorithmException on error
+ */
+ public PdfPKCS7(PrivateKey privKey, Certificate[] certChain, CRL[] crlList,
+ String hashAlgorithm, String provider, boolean hasRSAdata)
+ throws SecurityException, InvalidKeyException, NoSuchProviderException,
+ NoSuchAlgorithmException
+ {
+ this.privKey = privKey;
+
+ if (hashAlgorithm.equals("MD5")) {
+ digestAlgorithm = ID_MD5;
+ }
+ else if (hashAlgorithm.equals("MD2")) {
+ digestAlgorithm = ID_MD2;
+ }
+ else if (hashAlgorithm.equals("SHA")) {
+ digestAlgorithm = ID_SHA1;
+ }
+ else if (hashAlgorithm.equals("SHA1")) {
+ digestAlgorithm = ID_SHA1;
+ }
+ else {
+ throw new NoSuchAlgorithmException("Unknown Hash Algorithm "+hashAlgorithm);
+ }
+
+ version = signerversion = 1;
+ certs = new ArrayList();
+ crls = new ArrayList();
+ digestalgos = new HashSet();
+ digestalgos.add(digestAlgorithm);
+
+ //
+ // Copy in the certificates and crls used to sign the private key.
+ //
+ signCert = (X509Certificate)certChain[0];
+ for (int i = 0;i < certChain.length;i++) {
+ certs.add(certChain[i]);
+ }
+
+ if (crlList != null) {
+ for (int i = 0;i < crlList.length;i++) {
+ crls.add(crlList[i]);
+ }
+ }
+
+ if (privKey != null) {
+ //
+ // Now we have private key, find out what the digestEncryptionAlgorithm is.
+ //
+ digestEncryptionAlgorithm = privKey.getAlgorithm();
+ if (digestEncryptionAlgorithm.equals("RSA")) {
+ digestEncryptionAlgorithm = ID_RSA;
+ }
+ else if (digestEncryptionAlgorithm.equals("DSA")) {
+ digestEncryptionAlgorithm = ID_DSA;
+ }
+ else {
+ throw new NoSuchAlgorithmException("Unknown Key Algorithm "+digestEncryptionAlgorithm);
+ }
+ }
+ if (hasRSAdata) {
+ RSAdata = new byte[0];
+ if (provider == null || provider.startsWith("SunPKCS11"))
+ messageDigest = MessageDigest.getInstance(getHashAlgorithm());
+ else
+ messageDigest = MessageDigest.getInstance(getHashAlgorithm(), provider);
+ }
+
+ if (privKey != null) {
+ if (provider == null)
+ sig = Signature.getInstance(getDigestAlgorithm());
+ else
+ sig = Signature.getInstance(getDigestAlgorithm(), provider);
+
+ sig.initSign(privKey);
+ }
+ }
+
+ /**
+ * Update the digest with the specified bytes. This method is used both for signing and verifying
+ * @param buf the data buffer
+ * @param off the offset in the data buffer
+ * @param len the data length
+ * @throws SignatureException on error
+ */
+ public void update(byte[] buf, int off, int len) throws SignatureException {
+ if (RSAdata != null || digestAttr != null)
+ messageDigest.update(buf, off, len);
+ else
+ sig.update(buf, off, len);
+ }
+
+ /**
+ * Verify the digest.
+ * @throws SignatureException on error
+ * @return true
if the signature checks out, false
otherwise
+ */
+ public boolean verify() throws SignatureException {
+ if (verified)
+ return verifyResult;
+ if (sigAttr != null) {
+ sig.update(sigAttr);
+ if (RSAdata != null) {
+ byte msd[] = messageDigest.digest();
+ messageDigest.update(msd);
+ }
+ verifyResult = (Arrays.equals(messageDigest.digest(), digestAttr) && sig.verify(digest));
+ }
+ else {
+ if (RSAdata != null)
+ sig.update(messageDigest.digest());
+ verifyResult = sig.verify(digest);
+ }
+ verified = true;
+ return verifyResult;
+ }
+
+ /**
+ * Get the X.509 certificates associated with this PKCS#7 object
+ * @return the X.509 certificates associated with this PKCS#7 object
+ */
+ public Certificate[] getCertificates() {
+ return (X509Certificate[])certs.toArray(new X509Certificate[0]);
+ }
+
+ /**
+ * Get the X.509 certificate revocation lists associated with this PKCS#7 object
+ * @return the X.509 certificate revocation lists associated with this PKCS#7 object
+ */
+ public Collection getCRLs() {
+ return crls;
+ }
+
+ /**
+ * Get the X.509 certificate actually used to sign the digest.
+ * @return the X.509 certificate actually used to sign the digest
+ */
+ public X509Certificate getSigningCertificate() {
+ return signCert;
+ }
+
+ /**
+ * Get the version of the PKCS#7 object. Always 1
+ * @return the version of the PKCS#7 object. Always 1
+ */
+ public int getVersion() {
+ return version;
+ }
+
+ /**
+ * Get the version of the PKCS#7 "SignerInfo" object. Always 1
+ * @return the version of the PKCS#7 "SignerInfo" object. Always 1
+ */
+ public int getSigningInfoVersion() {
+ return signerversion;
+ }
+
+ /**
+ * Get the algorithm used to calculate the message digest
+ * @return the algorithm used to calculate the message digest
+ */
+ public String getDigestAlgorithm() {
+ String dea = digestEncryptionAlgorithm;
+
+ if (digestEncryptionAlgorithm.equals(ID_RSA)) {
+ dea = "RSA";
+ }
+ else if (digestEncryptionAlgorithm.equals(ID_DSA)) {
+ dea = "DSA";
+ }
+
+ return getHashAlgorithm() + "with" + dea;
+ }
+
+ /**
+ * Returns the algorithm.
+ * @return the digest algorithm
+ */
+ public String getHashAlgorithm() {
+ String da = digestAlgorithm;
+
+ if (digestAlgorithm.equals(ID_MD5) || digestAlgorithm.equals(ID_MD5RSA)) {
+ da = "MD5";
+ }
+ else if (digestAlgorithm.equals(ID_MD2) || digestAlgorithm.equals(ID_MD2RSA)) {
+ da = "MD2";
+ }
+ else if (digestAlgorithm.equals(ID_SHA1) || digestAlgorithm.equals(ID_SHA1RSA)) {
+ da = "SHA1";
+ }
+ return da;
+ }
+
+ /**
+ * Loads the default root certificates at <java.home>/lib/security/cacerts
+ * with the default provider.
+ * @return a KeyStore
+ */
+ public static KeyStore loadCacertsKeyStore() {
+ return loadCacertsKeyStore(null);
+ }
+
+ /**
+ * Loads the default root certificates at <java.home>/lib/security/cacerts.
+ * @param provider the provider or null
for the default provider
+ * @return a KeyStore
+ */
+ public static KeyStore loadCacertsKeyStore(String provider) {
+ File file = new File(System.getProperty("java.home"), "lib");
+ file = new File(file, "security");
+ file = new File(file, "cacerts");
+ FileInputStream fin = null;
+ try {
+ fin = new FileInputStream(file);
+ KeyStore k;
+ if (provider == null)
+ k = KeyStore.getInstance("JKS");
+ else
+ k = KeyStore.getInstance("JKS", provider);
+ k.load(fin, null);
+ return k;
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ finally {
+ try{fin.close();}catch(Exception ex){}
+ }
+ }
+
+ /**
+ * Verifies a single certificate.
+ * @param cert the certificate to verify
+ * @param crls the certificate revocation list or null
+ * @param calendar the date or null
for the current date
+ * @return a String
with the error description or null
+ * if no error
+ */
+ public static String verifyCertificate(X509Certificate cert, Collection crls, Calendar calendar) {
+ if (calendar == null)
+ calendar = new GregorianCalendar();
+ if (cert.hasUnsupportedCriticalExtension())
+ return "Has unsupported critical extension";
+ try {
+ cert.checkValidity(calendar.getTime());
+ }
+ catch (Exception e) {
+ return e.getMessage();
+ }
+ if (crls != null) {
+ for (Iterator it = crls.iterator(); it.hasNext();) {
+ if (((CRL)it.next()).isRevoked(cert))
+ return "Certificate revoked";
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Verifies a certificate chain against a KeyStore.
+ * @param certs the certificate chain
+ * @param keystore the KeyStore
+ * @param crls the certificate revocation list or null
+ * @param calendar the date or null
for the current date
+ * @return null
if the certificate chain could be validade or a
+ * Object[]{cert,error}
where cert
is the
+ * failed certificate and error
is the error message
+ */
+ public static Object[] verifyCertificates(Certificate certs[], KeyStore keystore, Collection crls, Calendar calendar) {
+ if (calendar == null)
+ calendar = new GregorianCalendar();
+ for (int k = 0; k < certs.length; ++k) {
+ X509Certificate cert = (X509Certificate)certs[k];
+ String err = verifyCertificate(cert, crls, calendar);
+ if (err != null)
+ return new Object[]{cert, err};
+ try {
+ for (Enumeration aliases = keystore.aliases(); aliases.hasMoreElements();) {
+ try {
+ String alias = (String)aliases.nextElement();
+ if (!keystore.isCertificateEntry(alias))
+ continue;
+ X509Certificate certStoreX509 = (X509Certificate)keystore.getCertificate(alias);
+ if (verifyCertificate(certStoreX509, crls, calendar) != null)
+ continue;
+ try {
+ cert.verify(certStoreX509.getPublicKey());
+ return null;
+ }
+ catch (Exception e) {
+ continue;
+ }
+ }
+ catch (Exception ex) {
+ }
+ }
+ }
+ catch (Exception e) {
+ }
+ int j;
+ for (j = 0; j < certs.length; ++j) {
+ if (j == k)
+ continue;
+ X509Certificate certNext = (X509Certificate)certs[j];
+ try {
+ cert.verify(certNext.getPublicKey());
+ break;
+ }
+ catch (Exception e) {
+ }
+ }
+ if (j == certs.length)
+ return new Object[]{cert, "Cannot be verified against the KeyStore or the certificate chain"};
+ }
+ return new Object[]{null, "Invalid state. Possible circular certificate chain"};
+ }
+
+ /**
+ * Get the "issuer" from the TBSCertificate bytes that are passed in
+ * @param enc a TBSCertificate in a byte array
+ * @return a ASN1Primitive
+ */
+ private static ASN1Primitive getIssuer(byte[] enc) {
+ try {
+ ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(enc));
+ ASN1Sequence seq = (ASN1Sequence)in.readObject();
+ return (ASN1Primitive)seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 3 : 2);
+ }
+ catch (IOException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ * Get the "subject" from the TBSCertificate bytes that are passed in
+ * @param enc A TBSCertificate in a byte array
+ * @return a ASN1Primitive
+ */
+ private static ASN1Primitive getSubject(byte[] enc) {
+ try {
+ ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(enc));
+ ASN1Sequence seq = (ASN1Sequence)in.readObject();
+ return (ASN1Primitive)seq.getObjectAt(seq.getObjectAt(0) instanceof DERTaggedObject ? 5 : 4);
+ }
+ catch (IOException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ * Get the issuer fields from an X509 Certificate
+ * @param cert an X509Certificate
+ * @return an X500Name
+ */
+ public static X500Name getIssuerFields(X509Certificate cert) {
+ try {
+ return new X500Name((ASN1Sequence)getIssuer(cert.getTBSCertificate()));
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ * Get the subject fields from an X509 Certificate
+ * @param cert an X509Certificate
+ * @return an X500Name
+ */
+ public static X500Name getSubjectFields(X509Certificate cert) {
+ try {
+ return new X500Name((ASN1Sequence)getSubject(cert.getTBSCertificate()));
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ * Gets the bytes for the PKCS#1 object.
+ * @return a byte array
+ */
+ public byte[] getEncodedPKCS1() {
+ try {
+ if (externalDigest != null)
+ digest = externalDigest;
+ else
+ digest = sig.sign();
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ ASN1OutputStream dout = new ASN1OutputStream(bOut);
+ dout.writeObject(new DEROctetString(digest));
+ dout.close();
+
+ return bOut.toByteArray();
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ * Sets the digest/signature to an external calculated value.
+ * @param digest the digest. This is the actual signature
+ * @param RSAdata the extra data that goes into the data tag in PKCS#7
+ * @param digestEncryptionAlgorithm the encryption algorithm. It may must be null
if the digest
+ * is also null
. If the digest
is not null
+ * then it may be "RSA" or "DSA"
+ */
+ public void setExternalDigest(byte digest[], byte RSAdata[], String digestEncryptionAlgorithm) {
+ externalDigest = digest;
+ externalRSAdata = RSAdata;
+ if (digestEncryptionAlgorithm != null) {
+ if (digestEncryptionAlgorithm.equals("RSA")) {
+ this.digestEncryptionAlgorithm = ID_RSA;
+ }
+ else if (digestEncryptionAlgorithm.equals("DSA")) {
+ this.digestEncryptionAlgorithm = ID_DSA;
+ }
+ else
+ throw new ExceptionConverter(new NoSuchAlgorithmException("Unknown Key Algorithm "+digestEncryptionAlgorithm));
+ }
+ }
+
+ /**
+ * Gets the bytes for the PKCS7SignedData object.
+ * @return the bytes for the PKCS7SignedData object
+ */
+ public byte[] getEncodedPKCS7() {
+ return getEncodedPKCS7(null, null);
+ }
+
+ /**
+ * Gets the bytes for the PKCS7SignedData object. Optionally the authenticatedAttributes
+ * in the signerInfo can also be set. If either of the parameters is null
, none will be used.
+ * @param secondDigest the digest in the authenticatedAttributes
+ * @param signingTime the signing time in the authenticatedAttributes
+ * @return the bytes for the PKCS7SignedData object
+ */
+ public byte[] getEncodedPKCS7(byte secondDigest[], Calendar signingTime) {
+ try {
+ if (externalDigest != null) {
+ digest = externalDigest;
+ if (RSAdata != null)
+ RSAdata = externalRSAdata;
+ }
+ else if (externalRSAdata != null && RSAdata != null) {
+ RSAdata = externalRSAdata;
+ sig.update(RSAdata);
+ digest = sig.sign();
+ }
+ else {
+ if (RSAdata != null) {
+ RSAdata = messageDigest.digest();
+ sig.update(RSAdata);
+ }
+ digest = sig.sign();
+ }
+
+ // Create the set of Hash algorithms
+ DERSet digestAlgorithms = new DERSet();
+ for(Iterator it = digestalgos.iterator(); it.hasNext();) {
+ ASN1EncodableVector algos = new ASN1EncodableVector();
+ algos.add(new ASN1ObjectIdentifier((String)it.next()));
+ algos.add(new DERNull());
+ digestAlgorithms.addObject(new DERSequence(algos));
+ }
+
+ // Create the contentInfo.
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(new ASN1ObjectIdentifier(ID_PKCS7_DATA));
+ if (RSAdata != null)
+ v.add(new DERTaggedObject(0, new DEROctetString(RSAdata)));
+ DERSequence contentinfo = new DERSequence(v);
+
+ // Get all the certificates
+ //
+ v = new ASN1EncodableVector();
+ for (Iterator i = certs.iterator(); i.hasNext();) {
+ ASN1InputStream tempstream = new ASN1InputStream(new ByteArrayInputStream(((X509Certificate)i.next()).getEncoded()));
+ v.add(tempstream.readObject());
+ }
+
+ DERSet dercertificates = new DERSet(v);
+
+ // Create signerinfo structure.
+ //
+ ASN1EncodableVector signerinfo = new ASN1EncodableVector();
+
+ // Add the signerInfo version
+ //
+ signerinfo.add(new ASN1Integer(signerversion));
+
+ v = new ASN1EncodableVector();
+ v.add(getIssuer(signCert.getTBSCertificate()));
+ v.add(new ASN1Integer(signCert.getSerialNumber()));
+ signerinfo.add(new DERSequence(v));
+
+ // Add the digestAlgorithm
+ v = new ASN1EncodableVector();
+ v.add(new ASN1ObjectIdentifier(digestAlgorithm));
+ v.add(new DERNull());
+ signerinfo.add(new DERSequence(v));
+
+ // add the authenticated attribute if present
+ if (secondDigest != null && signingTime != null) {
+ ASN1EncodableVector attribute = new ASN1EncodableVector();
+ v = new ASN1EncodableVector();
+ v.add(new ASN1ObjectIdentifier(ID_CONTENT_TYPE));
+ v.add(new DERSet(new ASN1ObjectIdentifier(ID_PKCS7_DATA)));
+ attribute.add(new DERSequence(v));
+ v = new ASN1EncodableVector();
+ v.add(new ASN1ObjectIdentifier(ID_SIGNING_TIME));
+ v.add(new DERSet(new DERUTCTime(signingTime.getTime())));
+ attribute.add(new DERSequence(v));
+ v = new ASN1EncodableVector();
+ v.add(new ASN1ObjectIdentifier(ID_MESSAGE_DIGEST));
+ v.add(new DERSet(new DEROctetString(secondDigest)));
+ attribute.add(new DERSequence(v));
+ signerinfo.add(new DERTaggedObject(false, 0, new DERSet(attribute)));
+ }
+ // Add the digestEncryptionAlgorithm
+ v = new ASN1EncodableVector();
+ v.add(new ASN1ObjectIdentifier(digestEncryptionAlgorithm));
+ v.add(new DERNull());
+ signerinfo.add(new DERSequence(v));
+
+ // Add the digest
+ signerinfo.add(new DEROctetString(digest));
+
+
+ // Finally build the body out of all the components above
+ ASN1EncodableVector body = new ASN1EncodableVector();
+ body.add(new ASN1Integer(version));
+ body.add(digestAlgorithms);
+ body.add(contentinfo);
+ body.add(new DERTaggedObject(false, 0, dercertificates));
+
+ if (crls.size() > 0) {
+ v = new ASN1EncodableVector();
+ for (Iterator i = crls.iterator();i.hasNext();) {
+ ASN1InputStream t = new ASN1InputStream(new ByteArrayInputStream((((X509CRL)i.next()).getEncoded())));
+ v.add(t.readObject());
+ }
+ DERSet dercrls = new DERSet(v);
+ body.add(new DERTaggedObject(false, 1, dercrls));
+ }
+
+ // Only allow one signerInfo
+ body.add(new DERSet(new DERSequence(signerinfo)));
+
+ // Now we have the body, wrap it in it's PKCS7Signed shell
+ // and return it
+ //
+ ASN1EncodableVector whole = new ASN1EncodableVector();
+ whole.add(new ASN1ObjectIdentifier(ID_PKCS7_SIGNED_DATA));
+ whole.add(new DERTaggedObject(0, new DERSequence(body)));
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ ASN1OutputStream dout = new ASN1OutputStream(bOut);
+ dout.writeObject(new DERSequence(whole));
+ dout.close();
+
+ return bOut.toByteArray();
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+
+ /**
+ * When using authenticatedAttributes the authentication process is different.
+ * The document digest is generated and put inside the attribute. The signing is done over the DER encoded
+ * authenticatedAttributes. This method provides that encoding and the parameters must be
+ * exactly the same as in {@link #getEncodedPKCS7(byte[],Calendar)}.
+ *
+ * A simple example:
+ *
+ *
+ * Calendar cal = Calendar.getInstance();
+ * PdfPKCS7 pk7 = new PdfPKCS7(key, chain, null, "SHA1", null, false);
+ * MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
+ * byte buf[] = new byte[8192];
+ * int n;
+ * InputStream inp = sap.getRangeStream();
+ * while ((n = inp.read(buf)) > 0) {
+ * messageDigest.update(buf, 0, n);
+ * }
+ * byte hash[] = messageDigest.digest();
+ * byte sh[] = pk7.getAuthenticatedAttributeBytes(hash, cal);
+ * pk7.update(sh, 0, sh.length);
+ * byte sg[] = pk7.getEncodedPKCS7(hash, cal);
+ *
+ * @param secondDigest the content digest
+ * @param signingTime the signing time
+ * @return the byte array representation of the authenticatedAttributes ready to be signed
+ */
+ public byte[] getAuthenticatedAttributeBytes(byte secondDigest[], Calendar signingTime) {
+ try {
+ ASN1EncodableVector attribute = new ASN1EncodableVector();
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(new ASN1ObjectIdentifier(ID_CONTENT_TYPE));
+ v.add(new DERSet(new ASN1ObjectIdentifier(ID_PKCS7_DATA)));
+ attribute.add(new DERSequence(v));
+ v = new ASN1EncodableVector();
+ v.add(new ASN1ObjectIdentifier(ID_SIGNING_TIME));
+ v.add(new DERSet(new DERUTCTime(signingTime.getTime())));
+ attribute.add(new DERSequence(v));
+ v = new ASN1EncodableVector();
+ v.add(new ASN1ObjectIdentifier(ID_MESSAGE_DIGEST));
+ v.add(new DERSet(new DEROctetString(secondDigest)));
+ attribute.add(new DERSequence(v));
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ ASN1OutputStream dout = new ASN1OutputStream(bOut);
+ dout.writeObject(new DERSet(attribute));
+ dout.close();
+
+ return bOut.toByteArray();
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+ /**
+ * Getter for property reason.
+ * @return Value of property reason.
+ */
+ public String getReason() {
+ return this.reason;
+ }
+
+ /**
+ * Setter for property reason.
+ * @param reason New value of property reason.
+ */
+ public void setReason(String reason) {
+ this.reason = reason;
+ }
+
+ /**
+ * Getter for property location.
+ * @return Value of property location.
+ */
+ public String getLocation() {
+ return this.location;
+ }
+
+ /**
+ * Setter for property location.
+ * @param location New value of property location.
+ */
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ /**
+ * Getter for property signDate.
+ * @return Value of property signDate.
+ */
+ public Calendar getSignDate() {
+ return this.signDate;
+ }
+
+ /**
+ * Setter for property signDate.
+ * @param signDate New value of property signDate.
+ */
+ public void setSignDate(Calendar signDate) {
+ this.signDate = signDate;
+ }
+
+ /**
+ * Getter for property sigName.
+ * @return Value of property sigName.
+ */
+ public String getSignName() {
+ return this.signName;
+ }
+
+ /**
+ * Setter for property sigName.
+ * @param signName New value of property sigName.
+ */
+ public void setSignName(String signName) {
+ this.signName = signName;
+ }
+
+ /**
+ * a class that holds an X509 name
+ */
+ public static class X500Name {
+ /**
+ * country code - StringType(SIZE(2))
+ */
+ public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6");
+
+ /**
+ * organization - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10");
+
+ /**
+ * organizational unit name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11");
+
+ /**
+ * Title
+ */
+ public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12");
+
+ /**
+ * common name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5");
+
+ /**
+ * locality name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7");
+
+ /**
+ * state, or province name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8");
+
+ /** Naming attribute of type X520name */
+ public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4");
+ /** Naming attribute of type X520name */
+ public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42");
+ /** Naming attribute of type X520name */
+ public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43");
+ /** Naming attribute of type X520name */
+ public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44");
+ /** Naming attribute of type X520name */
+ public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45");
+
+ /**
+ * Email address (RSA PKCS#9 extension) - IA5String.
+ * Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
+ */
+ public static final ASN1ObjectIdentifier EmailAddress = new ASN1ObjectIdentifier("1.2.840.113549.1.9.1");
+
+ /**
+ * email address in Verisign certificates
+ */
+ public static final ASN1ObjectIdentifier E = EmailAddress;
+
+ /** object identifier */
+ public static final ASN1ObjectIdentifier DC = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
+
+ /** LDAP User id. */
+ public static final ASN1ObjectIdentifier UID = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
+
+ /** A HashMap with default symbols */
+ public static HashMap DefaultSymbols = new HashMap();
+
+ static {
+ DefaultSymbols.put(C, "C");
+ DefaultSymbols.put(O, "O");
+ DefaultSymbols.put(T, "T");
+ DefaultSymbols.put(OU, "OU");
+ DefaultSymbols.put(CN, "CN");
+ DefaultSymbols.put(L, "L");
+ DefaultSymbols.put(ST, "ST");
+ DefaultSymbols.put(SN, "SN");
+ DefaultSymbols.put(EmailAddress, "E");
+ DefaultSymbols.put(DC, "DC");
+ DefaultSymbols.put(UID, "UID");
+ DefaultSymbols.put(SURNAME, "SURNAME");
+ DefaultSymbols.put(GIVENNAME, "GIVENNAME");
+ DefaultSymbols.put(INITIALS, "INITIALS");
+ DefaultSymbols.put(GENERATION, "GENERATION");
+ }
+ /** A HashMap with values */
+ public HashMap values = new HashMap();
+
+ /**
+ * Constructs an X509 name
+ * @param seq an ASN1 Sequence
+ */
+ public X500Name(ASN1Sequence seq) {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements()) {
+ ASN1Set set = (ASN1Set)e.nextElement();
+
+ for (int i = 0; i < set.size(); i++) {
+ ASN1Sequence s = (ASN1Sequence)set.getObjectAt(i);
+ String id = (String)DefaultSymbols.get(s.getObjectAt(0));
+ if (id == null)
+ continue;
+ ArrayList vs = (ArrayList)values.get(id);
+ if (vs == null) {
+ vs = new ArrayList();
+ values.put(id, vs);
+ }
+ vs.add(((ASN1String)s.getObjectAt(1)).getString());
+ }
+ }
+ }
+ /**
+ * Constructs an X509 name
+ * @param dirName a directory name
+ */
+ public X500Name(String dirName) {
+ X509NameTokenizer nTok = new X509NameTokenizer(dirName);
+
+ while (nTok.hasMoreTokens()) {
+ String token = nTok.nextToken();
+ int index = token.indexOf('=');
+
+ if (index == -1) {
+ throw new IllegalArgumentException("badly formated directory string");
+ }
+
+ String id = token.substring(0, index).toUpperCase();
+ String value = token.substring(index + 1);
+ ArrayList vs = (ArrayList)values.get(id);
+ if (vs == null) {
+ vs = new ArrayList();
+ values.put(id, vs);
+ }
+ vs.add(value);
+ }
+
+ }
+
+ public String getField(String name) {
+ ArrayList vs = (ArrayList)values.get(name);
+ return vs == null ? null : (String)vs.get(0);
+ }
+
+ /**
+ * gets a field array from the values Hashmap
+ * @param name
+ * @return an ArrayList
+ */
+ public ArrayList getFieldArray(String name) {
+ ArrayList vs = (ArrayList)values.get(name);
+ return vs == null ? null : vs;
+ }
+
+ /**
+ * getter for values
+ * @return a HashMap with the fields of the X509 name
+ */
+ public HashMap getFields() {
+ return values;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return values.toString();
+ }
+ }
+
+ /**
+ * class for breaking up an X500 Name into it's component tokens, ala
+ * java.util.StringTokenizer. We need this class as some of the
+ * lightweight Java environment don't support classes like
+ * StringTokenizer.
+ */
+ public static class X509NameTokenizer {
+ private String oid;
+ private int index;
+ private StringBuffer buf = new StringBuffer();
+
+ public X509NameTokenizer(
+ String oid) {
+ this.oid = oid;
+ this.index = -1;
+ }
+
+ public boolean hasMoreTokens() {
+ return (index != oid.length());
+ }
+
+ public String nextToken() {
+ if (index == oid.length()) {
+ return null;
+ }
+
+ int end = index + 1;
+ boolean quoted = false;
+ boolean escaped = false;
+
+ buf.setLength(0);
+
+ while (end != oid.length()) {
+ char c = oid.charAt(end);
+
+ if (c == '"') {
+ if (!escaped) {
+ quoted = !quoted;
+ }
+ else {
+ buf.append(c);
+ }
+ escaped = false;
+ }
+ else {
+ if (escaped || quoted) {
+ buf.append(c);
+ escaped = false;
+ }
+ else if (c == '\\') {
+ escaped = true;
+ }
+ else if (c == ',') {
+ break;
+ }
+ else {
+ buf.append(c);
+ }
+ }
+ end++;
+ }
+
+ index = end;
+ return buf.toString().trim();
+ }
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPSXObject.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPSXObject.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPSXObject.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPSXObject.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2005 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+
+/**
+ * Implements the PostScript XObject.
+ */
+public class PdfPSXObject extends PdfTemplate {
+
+ /** Creates a new instance of PdfPSXObject */
+ protected PdfPSXObject() {
+ super();
+ }
+
+ /**
+ * Constructs a PSXObject
+ * @param wr
+ */
+ public PdfPSXObject(PdfWriter wr) {
+ super(wr);
+ }
+
+ /**
+ * Gets the stream representing this object.
+ *
+ * @return the stream representing this object
+ * @throws IOException
+ */
+
+ PdfStream getFormXObject() throws IOException {
+ PdfStream s = new PdfStream(content.toByteArray());
+ s.put(PdfName.TYPE, PdfName.XOBJECT);
+ s.put(PdfName.SUBTYPE, PdfName.PS);
+ s.flateCompress();
+ return s;
+ }
+
+ /**
+ * Gets a duplicate of this PdfPSXObject
. All
+ * the members are copied by reference but the buffer stays different.
+ * @return a copy of this PdfPSXObject
+ */
+
+ public PdfContentByte getDuplicate() {
+ PdfPSXObject tpl = new PdfPSXObject();
+ tpl.writer = writer;
+ tpl.pdf = pdf;
+ tpl.thisReference = thisReference;
+ tpl.pageResources = pageResources;
+ tpl.separator = separator;
+ return tpl;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPage.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPage.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPage.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPage.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,188 @@
+/*
+ * $Id: PdfPage.java,v 1.47 2004/11/29 14:07:03 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import java.util.HashMap;
+/**
+ * PdfPage
is the PDF Page-object.
+ *
+ * A Page object is a dictionary whose keys describe a single page containing text,
+ * graphics, and images. A Page onjects is a leaf of the Pages tree.
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 6.4 (page 73-81)
+ *
+ * @see PdfPageElement
+ * @see PdfPages
+ */
+
+public class PdfPage extends PdfDictionary {
+
+ private static final String boxStrings[] = {"crop", "trim", "art", "bleed"};
+ private static final PdfName boxNames[] = {PdfName.CROPBOX, PdfName.TRIMBOX, PdfName.ARTBOX, PdfName.BLEEDBOX};
+ // membervariables
+
+/** value of the Rotate key for a page in PORTRAIT */
+ public static final PdfNumber PORTRAIT = new PdfNumber(0);
+
+/** value of the Rotate key for a page in LANDSCAPE */
+ public static final PdfNumber LANDSCAPE = new PdfNumber(90);
+
+/** value of the Rotate key for a page in INVERTEDPORTRAIT */
+ public static final PdfNumber INVERTEDPORTRAIT = new PdfNumber(180);
+
+/** value of the Rotate key for a page in SEASCAPE */
+ public static final PdfNumber SEASCAPE = new PdfNumber(270);
+
+/** value of the MediaBox key */
+ PdfRectangle mediaBox;
+
+ // constructors
+
+/**
+ * Constructs a PdfPage
.
+ *
+ * @param mediaBox a value for the MediaBox key
+ * @param resources an indirect reference to a PdfResources
-object
+ * @param rotate a value for the Rotate key
+ */
+
+// PdfPage(PdfRectangle mediaBox, Rectangle cropBox, PdfIndirectReference resources, PdfNumber rotate) {
+// super(PAGE);
+// this.mediaBox = mediaBox;
+// put(PdfName.MEDIABOX, mediaBox);
+// put(PdfName.RESOURCES, resources);
+// if (rotate != null) {
+// put(PdfName.ROTATE, rotate);
+// }
+// if (cropBox != null)
+// put(PdfName.CROPBOX, new PdfRectangle(cropBox));
+// }
+
+/**
+ * Constructs a PdfPage
.
+ *
+ * @param mediaBox a value for the MediaBox key
+ * @param resources an indirect reference to a PdfResources
-object
+ * @param rotate a value for the Rotate key
+ */
+
+ PdfPage(PdfRectangle mediaBox, HashMap boxSize, PdfDictionary resources, int rotate) {
+ super(PAGE);
+ this.mediaBox = mediaBox;
+ put(PdfName.MEDIABOX, mediaBox);
+ put(PdfName.RESOURCES, resources);
+ if (rotate != 0) {
+ put(PdfName.ROTATE, new PdfNumber(rotate));
+ }
+ for (int k = 0; k < boxStrings.length; ++k) {
+ PdfObject rect = (PdfObject)boxSize.get(boxStrings[k]);
+ if (rect != null)
+ put(boxNames[k], rect);
+ }
+ }
+
+/**
+ * Constructs a PdfPage
.
+ *
+ * @param mediaBox a value for the MediaBox key
+ * @param resources an indirect reference to a PdfResources
-object
+ */
+
+// PdfPage(PdfRectangle mediaBox, Rectangle cropBox, PdfIndirectReference resources) {
+// this(mediaBox, cropBox, resources, null);
+// }
+
+/**
+ * Constructs a PdfPage
.
+ *
+ * @param mediaBox a value for the MediaBox key
+ * @param resources an indirect reference to a PdfResources
-object
+ */
+
+ PdfPage(PdfRectangle mediaBox, HashMap boxSize, PdfDictionary resources) {
+ this(mediaBox, boxSize, resources, 0);
+ }
+
+/**
+ * Checks if this page element is a tree of pages.
+ *
+ * This method allways returns false
.
+ *
+ * @return false
because this is a single page
+ */
+
+ public boolean isParent() {
+ return false;
+ }
+
+ // methods
+
+/**
+ * Adds an indirect reference pointing to a PdfContents
-object.
+ *
+ * @param contents an indirect reference to a PdfContents
-object
+ */
+
+ void add(PdfIndirectReference contents) {
+ put(PdfName.CONTENTS, contents);
+ }
+
+/**
+ * Rotates the mediabox, but not the text in it.
+ *
+ * @return a PdfRectangle
+ */
+
+ PdfRectangle rotateMediaBox() {
+ this.mediaBox = mediaBox.rotate();
+ put(PdfName.MEDIABOX, this.mediaBox);
+ return this.mediaBox;
+ }
+
+/**
+ * Returns the MediaBox of this Page.
+ *
+ * @return a PdfRectangle
+ */
+
+ PdfRectangle getMediaBox() {
+ return mediaBox;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPageElement.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPageElement.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPageElement.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPageElement.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,68 @@
+/*
+ * $Id: PdfPageElement.java,v 1.24 2002/07/09 11:28:23 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * The PdfPageElement
interface has to be implemented by PdfPage
and PdfPages
.
+ *
+ * @see PdfPage
+ * @see PdfPages
+ */
+
+interface PdfPageElement {
+
+/**
+ * Set the value for the Parent key in the Page or Pages Dictionary.
+ *
+ * @param reference an indirect reference to a PdfPages
-object
+ */
+
+ public void setParent(PdfIndirectReference reference);
+
+/**
+ * Checks if this page element is a tree of pages.
+ *
+ * @return true
if it's a tree of pages;
+ * false
if it's a single page
+ */
+
+ public boolean isParent();
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPageEvent.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPageEvent.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPageEvent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPageEvent.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,180 @@
+/*
+ * $Id: PdfPageEvent.java,v 1.23 2002/07/09 11:28:24 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import pdftk.com.lowagie.text.Document;
+import pdftk.com.lowagie.text.Rectangle;
+import pdftk.com.lowagie.text.Paragraph;
+
+/**
+ * Allows a class to catch several document events.
+ *
+ * Note: do not use Document.add() inside a page event.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+
+public interface PdfPageEvent {
+
+/**
+ * Called when the document is opened.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ */
+ public void onOpenDocument(PdfWriter writer, Document document);
+
+/**
+ * Called when a page is initialized.
+ *
+ * Note that if even if a page is not written this method is still
+ * called. It is preferable to use onEndPage
to avoid
+ * infinite loops.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ */
+ public void onStartPage(PdfWriter writer, Document document);
+
+/**
+ * Called when a page is finished, just before being written to the document.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ */
+ public void onEndPage(PdfWriter writer, Document document);
+
+/**
+ * Called when the document is closed.
+ *
+ * Note that this method is called with the page number equal
+ * to the last page plus one.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ */
+ public void onCloseDocument(PdfWriter writer, Document document);
+
+/**
+ * Called when a Paragraph is written.
+ *
+ * paragraphPosition
will hold the height at which the
+ * paragraph will be written to. This is useful to insert bookmarks with
+ * more control.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param paragraphPosition the position the paragraph will be written to
+ */
+ public void onParagraph(PdfWriter writer, Document document, float paragraphPosition);
+
+/**
+ * Called when a Paragraph is written.
+ *
+ * paragraphPosition
will hold the height of the end of the paragraph.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param paragraphPosition the position of the end of the paragraph
+ */
+ public void onParagraphEnd(PdfWriter writer,Document document,float paragraphPosition);
+
+/**
+ * Called when a Chapter is written.
+ *
+ * position
will hold the height at which the
+ * chapter will be written to.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param paragraphPosition the position the chapter will be written to
+ * @param title the title of the Chapter
+ */
+ public void onChapter(PdfWriter writer,Document document,float paragraphPosition, Paragraph title);
+
+/**
+ * Called when the end of a Chapter is reached.
+ *
+ * position
will hold the height of the end of the chapter.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param paragraphPosition the position the chapter will be written to
+ */
+ public void onChapterEnd(PdfWriter writer,Document document,float paragraphPosition);
+
+/**
+ * Called when a Section is written.
+ *
+ * position
will hold the height at which the
+ * section will be written to.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param paragraphPosition the position the section will be written to
+ * @param depth the number depth of the section
+ * @param title the title of the section
+ */
+ public void onSection(PdfWriter writer,Document document,float paragraphPosition, int depth, Paragraph title);
+
+/**
+ * Called when the end of a Section is reached.
+ *
+ * position
will hold the height of the section end.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param paragraphPosition the position the section will be written to
+ */
+ public void onSectionEnd(PdfWriter writer,Document document,float paragraphPosition);
+
+/**
+ * Called when a Chunk
with a generic tag is written.
+ *
+ * It is usefull to pinpoint the Chunk
location to generate
+ * bookmarks, for example.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param rect the Rectangle
containing the Chunk
+ * @param text the text of the tag
+ */
+ public void onGenericTag(PdfWriter writer, Document document, Rectangle rect, String text);
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPageEventHelper.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPageEventHelper.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPageEventHelper.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPageEventHelper.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,192 @@
+/*
+ * $Id: PdfPageEventHelper.java,v 1.23 2002/07/09 11:28:24 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import pdftk.com.lowagie.text.Document;
+import pdftk.com.lowagie.text.Rectangle;
+import pdftk.com.lowagie.text.Paragraph;
+
+/**
+ * Helps the use of PdfPageEvent
by implementing all the interface methods.
+ * A class can extend PdfPageEventHelper
and only implement the
+ * needed methods.
+ *
+ * Note: do not use Document.add() inside a page event.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+
+public class PdfPageEventHelper implements PdfPageEvent {
+
+/**
+ * Called when the document is opened.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ */
+ public void onOpenDocument(PdfWriter writer,Document document) {
+ }
+
+/**
+ * Called when a page is initialized.
+ *
+ * Note that if even if a page is not written this method is still
+ * called. It is preferable to use onEndPage
to avoid
+ * infinite loops.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ */
+ public void onStartPage(PdfWriter writer,Document document) {
+ }
+
+/**
+ * Called when a page is finished, just before being written to the document.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ */
+ public void onEndPage(PdfWriter writer,Document document) {
+ }
+
+/**
+ * Called when the document is closed.
+ *
+ * Note that this method is called with the page number equal
+ * to the last page plus one.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ */
+ public void onCloseDocument(PdfWriter writer,Document document) {
+ }
+
+/**
+ * Called when a Paragraph is written.
+ *
+ * paragraphPosition
will hold the height at which the
+ * paragraph will be written to. This is useful to insert bookmarks with
+ * more control.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param paragraphPosition the position the paragraph will be written to
+ */
+ public void onParagraph(PdfWriter writer,Document document,float paragraphPosition) {
+ }
+
+/**
+ * Called when a Paragraph is written.
+ *
+ * paragraphPosition
will hold the height of the end of the paragraph.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param paragraphPosition the position of the end of the paragraph
+ */
+ public void onParagraphEnd(PdfWriter writer,Document document,float paragraphPosition) {
+ }
+
+/**
+ * Called when a Chapter is written.
+ *
+ * position
will hold the height at which the
+ * chapter will be written to.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param paragraphPosition the position the chapter will be written to
+ * @param title the title of the Chapter
+ */
+ public void onChapter(PdfWriter writer,Document document,float paragraphPosition,Paragraph title) {
+ }
+
+/**
+ * Called when the end of a Chapter is reached.
+ *
+ * position
will hold the height of the end of the chapter.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param position the position of the end of the chapter.
+ */
+ public void onChapterEnd(PdfWriter writer,Document document,float position) {
+ }
+
+/**
+ * Called when a Section is written.
+ *
+ * position
will hold the height at which the
+ * section will be written to.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param paragraphPosition the position the section will be written to
+ * @param depth the number depth of the Section
+ * @param title the title of the section
+ */
+ public void onSection(PdfWriter writer,Document document,float paragraphPosition,int depth,Paragraph title) {
+ }
+
+/**
+ * Called when the end of a Section is reached.
+ *
+ * position
will hold the height of the section end.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param position the position of the end of the section
+ */
+ public void onSectionEnd(PdfWriter writer,Document document,float position) {
+ }
+
+/**
+ * Called when a Chunk
with a generic tag is written.
+ *
+ * It is usefull to pinpoint the Chunk
location to generate
+ * bookmarks, for example.
+ *
+ * @param writer the PdfWriter
for this document
+ * @param document the document
+ * @param rect the Rectangle
containing the Chunk
+ * @param text the text of the tag
+ */
+ public void onGenericTag(PdfWriter writer,Document document,Rectangle rect,String text) {
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPageLabels.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPageLabels.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPageLabels.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPageLabels.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,181 @@
+/*
+ * $Id: PdfPageLabels.java,v 1.14 2002/07/09 11:28:24 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.Comparator;
+import java.util.TreeMap;
+import java.util.Iterator;
+
+/** Page labels are used to identify each
+ * page visually on the screen or in print.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfPageLabels implements Comparator {
+
+ /** Logical pages will have the form 1,2,3,...
+ */
+ public static int DECIMAL_ARABIC_NUMERALS = 0;
+ /** Logical pages will have the form I,II,III,IV,...
+ */
+ public static int UPPERCASE_ROMAN_NUMERALS = 1;
+ /** Logical pages will have the form i,ii,iii,iv,...
+ */
+ public static int LOWERCASE_ROMAN_NUMERALS = 2;
+ /** Logical pages will have the form of uppercase letters
+ * (A to Z for the first 26 pages, AA to ZZ for the next 26, and so on)
+ */
+ public static int UPPERCASE_LETTERS = 3;
+ /** Logical pages will have the form of uppercase letters
+ * (a to z for the first 26 pages, aa to zz for the next 26, and so on)
+ */
+ public static int LOWERCASE_LETTERS = 4;
+ /** No logical page numbers are generated but fixed text may
+ * still exist
+ */
+ public static int EMPTY = 5;
+ /** Dictionary values to set the logical page styles
+ */
+ static PdfName numberingStyle[] = new PdfName[]{PdfName.D, PdfName.R,
+ new PdfName("r"), PdfName.A, new PdfName("a")};
+ /** The sequence of logical pages. Will contain at least a value for page 1
+ */
+ TreeMap map;
+
+ /** Creates a new PdfPageLabel with a default logical page 1
+ */
+ public PdfPageLabels() {
+ map = new TreeMap(this);
+ addPageLabel(1, DECIMAL_ARABIC_NUMERALS, null, 1);
+ }
+
+ /** Compares two Integer
.
+ * @param obj the first Integer
+ * @param obj1 the second Integer
+ * @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second
+ */
+ public int compare(Object obj, Object obj1) {
+ int v1 = ((Integer)obj).intValue();
+ int v2 = ((Integer)obj1).intValue();
+ if (v1 < v2)
+ return -1;
+ if (v1 == v2)
+ return 0;
+ return 1;
+ }
+
+ /** Not used
+ * @param obj not used
+ * @return always true
+ */
+ public boolean equals(Object obj) {
+ return true;
+ }
+
+ /** Adds or replaces a page label.
+ * @param page the real page to start the numbering. First page is 1
+ * @param numberStyle the numbering style such as LOWERCASE_ROMAN_NUMERALS
+ * @param text the text to prefix the number. Can be null
or empty
+ * @param firstPage the first logical page number
+ */
+ public void addPageLabel(int page, int numberStyle, String text, int firstPage) {
+ if (page < 1 || firstPage < 1)
+ throw new IllegalArgumentException("In a page label the page numbers must be greater or equal to 1.");
+ PdfName pdfName = null;
+ if (numberStyle >= 0 && numberStyle < numberingStyle.length)
+ pdfName = numberingStyle[numberStyle];
+ Integer iPage = new Integer(page);
+ Object obj = new Object[]{iPage, pdfName, text, new Integer(firstPage)};
+ map.put(iPage, obj);
+ }
+
+ /** Adds or replaces a page label. The first logical page has the default
+ * of 1.
+ * @param page the real page to start the numbering. First page is 1
+ * @param numberStyle the numbering style such as LOWERCASE_ROMAN_NUMERALS
+ * @param text the text to prefix the number. Can be null
or empty
+ */
+ public void addPageLabel(int page, int numberStyle, String text) {
+ addPageLabel(page, numberStyle, text, 1);
+ }
+
+ /** Adds or replaces a page label. There is no text prefix and the first
+ * logical page has the default of 1.
+ * @param page the real page to start the numbering. First page is 1
+ * @param numberStyle the numbering style such as LOWERCASE_ROMAN_NUMERALS
+ */
+ public void addPageLabel(int page, int numberStyle) {
+ addPageLabel(page, numberStyle, null, 1);
+ }
+
+ /** Removes a page label. The first page label can not be removed, only changed.
+ * @param page the real page to remove
+ */
+ public void removePageLabel(int page) {
+ if (page <= 1)
+ return;
+ map.remove(new Integer(page));
+ }
+
+ /** Gets the page label dictionary to insert into the document.
+ * @return the page label dictionary
+ */
+ PdfDictionary getDictionary() {
+ PdfDictionary dic = new PdfDictionary();
+ PdfArray array = new PdfArray();
+ for (Iterator it = map.values().iterator(); it.hasNext();) {
+ Object obj[] = (Object[])it.next();
+ PdfDictionary subDic = new PdfDictionary();
+ PdfName pName = (PdfName)obj[1];
+ if (pName != null)
+ subDic.put(PdfName.S, pName);
+ String text = (String)obj[2];
+ if (text != null)
+ subDic.put(PdfName.P, new PdfString(text, PdfObject.TEXT_UNICODE));
+ int st = ((Integer)obj[3]).intValue();
+ if (st != 1)
+ subDic.put(PdfName.ST, new PdfNumber(st));
+ array.add(new PdfNumber(((Integer)obj[0]).intValue() - 1));
+ array.add(subDic);
+ }
+ dic.put(PdfName.NUMS, array);
+ return dic;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPages.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPages.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPages.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPages.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,196 @@
+/*
+ * $Id: PdfPages.java,v 1.33 2003/05/02 09:01:26 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+/**
+ * PdfPages
is the PDF Pages-object.
+ *
+ * The Pages of a document are accessible through a tree of nodes known as the Pages tree.
+ * This tree defines the ordering of the pages in the document.
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 6.3 (page 71-73)
+ *
+ * @see PdfPageElement
+ * @see PdfPage
+ */
+
+public class PdfPages {
+
+ private ArrayList pages = new ArrayList();
+ private ArrayList parents = new ArrayList();
+ private int leafSize = 10;
+ private PdfWriter writer;
+ private PdfIndirectReference topParent;
+
+ // constructors
+
+/**
+ * Constructs a PdfPages
-object.
+ */
+
+ PdfPages(PdfWriter writer) {
+ this.writer = writer;
+ }
+
+ void addPage(PdfDictionary page) {
+ try {
+ if ((pages.size() % leafSize) == 0)
+ parents.add(writer.getPdfIndirectReference());
+ PdfIndirectReference parent = (PdfIndirectReference)parents.get(parents.size() - 1);
+ page.put(PdfName.PARENT, parent);
+ PdfIndirectReference current = writer.getCurrentPage();
+ writer.addToBody(page, current);
+ pages.add(current);
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ PdfIndirectReference addPageRef(PdfIndirectReference pageRef) {
+ try {
+ if ((pages.size() % leafSize) == 0)
+ parents.add(writer.getPdfIndirectReference());
+ pages.add(pageRef);
+ return (PdfIndirectReference)parents.get(parents.size() - 1);
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ // returns the top parent to include in the catalog
+ PdfIndirectReference writePageTree() throws IOException {
+ if (pages.size() == 0)
+ throw new IOException("The document has no pages.");
+ int leaf = 1;
+ ArrayList tParents = parents;
+ ArrayList tPages = pages;
+ ArrayList nextParents = new ArrayList();
+ while (true) {
+ leaf *= leafSize;
+ int stdCount = leafSize;
+ int rightCount = tPages.size() % leafSize;
+ if (rightCount == 0)
+ rightCount = leafSize;
+ for (int p = 0; p < tParents.size(); ++p) {
+ int count;
+ int thisLeaf = leaf;
+ if (p == tParents.size() - 1) {
+ count = rightCount;
+ thisLeaf = pages.size() % leaf;
+ if (thisLeaf == 0)
+ thisLeaf = leaf;
+ }
+ else
+ count = stdCount;
+ PdfDictionary top = new PdfDictionary(PdfName.PAGES);
+ top.put(PdfName.COUNT, new PdfNumber(thisLeaf));
+ PdfArray kids = new PdfArray();
+ ArrayList internal = kids.getArrayList();
+ internal.addAll(tPages.subList(p * stdCount, p * stdCount + count));
+ top.put(PdfName.KIDS, kids);
+ if (tParents.size() > 1) {
+ if ((p % leafSize) == 0)
+ nextParents.add(writer.getPdfIndirectReference());
+ top.put(PdfName.PARENT, (PdfIndirectReference)nextParents.get(p / leafSize));
+ }
+ writer.addToBody(top, (PdfIndirectReference)tParents.get(p));
+ }
+ if (tParents.size() == 1) {
+ topParent = (PdfIndirectReference)tParents.get(0);
+ return topParent;
+ }
+ tPages = tParents;
+ tParents = nextParents;
+ nextParents = new ArrayList();
+ }
+ }
+
+ PdfIndirectReference getTopParent() {
+ return topParent;
+ }
+
+ void setLinearMode(PdfIndirectReference topParent) {
+ if (parents.size() > 1)
+ throw new RuntimeException("Linear page mode can only be called with a single parent.");
+ if (topParent != null) {
+ this.topParent = topParent;
+ parents.clear();
+ parents.add(topParent);
+ }
+ leafSize = 10000000;
+ }
+
+ void addPage(PdfIndirectReference page) {
+ pages.add(page);
+ }
+
+ int reorderPages(int order[]) throws DocumentException {
+ if (order == null)
+ return pages.size();
+ if (parents.size() > 1)
+ throw new DocumentException("Page reordering requires a single parent in the page tree. Call PdfWriter.setLinearMode() after open.");
+ if (order.length != pages.size())
+ throw new DocumentException("Page reordering requires an array with the same size as the number of pages.");
+ int max = pages.size();
+ boolean temp[] = new boolean[max];
+ for (int k = 0; k < max; ++k) {
+ int p = order[k];
+ if (p < 1 || p > max)
+ throw new DocumentException("Page reordering requires pages between 1 and " + max + ". Found " + p + ".");
+ if (temp[p - 1])
+ throw new DocumentException("Page reordering requires no page repetition. Page " + p + " is repeated.");
+ temp[p - 1] = true;
+ }
+ Object copy[] = pages.toArray();
+ for (int k = 0; k < max; ++k) {
+ pages.set(k, copy[order[k] - 1]);
+ }
+ return max;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPattern.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPattern.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPattern.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPattern.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,73 @@
+/*
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+/**
+ * A PdfPattern
defines a ColorSpace
+ *
+ * @see PdfStream
+ */
+
+public class PdfPattern extends PdfStream {
+
+ PdfPattern(PdfPatternPainter painter) {
+ super();
+ PdfNumber one = new PdfNumber(1);
+ PdfArray matrix = painter.getMatrix();
+ if ( matrix != null ) {
+ put(PdfName.MATRIX, matrix);
+ }
+ put(PdfName.TYPE, PdfName.PATTERN);
+ put(PdfName.BBOX, new PdfRectangle(painter.getBoundingBox()));
+ put(PdfName.RESOURCES, painter.getResources());
+ put(PdfName.TILINGTYPE, one);
+ put(PdfName.PATTERNTYPE, one);
+ if (painter.isStencil())
+ put(PdfName.PAINTTYPE, new PdfNumber(2));
+ else
+ put(PdfName.PAINTTYPE, one);
+ put(PdfName.XSTEP, new PdfNumber(painter.getXStep()));
+ put(PdfName.YSTEP, new PdfNumber(painter.getYStep()));
+ bytes = painter.toPdf(null);
+ put(PdfName.LENGTH, new PdfNumber(bytes.length));
+ try {
+ flateCompress();
+ } catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPatternPainter.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPatternPainter.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfPatternPainter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfPatternPainter.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,383 @@
+/*
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+// import pdftk.com.lowagie.text.DocumentException;
+// import pdftk.com.lowagie.text.Image; ssteward: dropped in 1.44
+import pdftk.com.lowagie.text.Rectangle;
+import java.awt.Color;
+
+/**
+ * Implements the pattern.
+ */
+
+public class PdfPatternPainter extends PdfTemplate {
+
+ protected float xstep, ystep;
+ protected boolean stencil = false;
+ protected Color defaultColor;
+
+ /**
+ *Creates a PdfPattern
.
+ */
+
+ private PdfPatternPainter() {
+ super(null);
+ type = TYPE_PATTERN;
+ }
+
+ /**
+ * Creates new PdfPattern
+ *
+ * @param wr the PdfWriter
+ */
+
+ PdfPatternPainter(PdfWriter wr) {
+ super(wr);
+ type = TYPE_PATTERN;
+ }
+
+ PdfPatternPainter(PdfWriter wr, Color defaultColor) {
+ this(wr);
+ stencil = true;
+ if (defaultColor == null)
+ this.defaultColor = Color.gray;
+ else
+ this.defaultColor = defaultColor;
+ }
+
+ /**
+ * Sets the horizontal interval of this pattern.
+ *
+ * @param xstep the xstep in horizontal painting
+ */
+
+ public void setXStep(float xstep) {
+ this.xstep = xstep;
+ }
+
+ /**
+ * Sets the vertical interval of this pattern.
+ *
+ * @param ystep in vertical painting
+ */
+
+ public void setYStep(float ystep) {
+ this.ystep = ystep;
+ }
+
+ /**
+ * Returns the horizontal interval when repeating the pattern.
+ * @return a value
+ */
+ public float getXStep() {
+ return this.xstep;
+ }
+
+ /**
+ * Returns the vertical interval when repeating the pattern.
+ * @return a value
+ */
+ public float getYStep() {
+ return this.ystep;
+ }
+
+ /**
+ * Tells you if this pattern is colored/uncolored (stencil = uncolored, you need to set a default color).
+ * @return true if the pattern is an uncolored tiling pattern (stencil).
+ */
+ public boolean isStencil() {
+ return stencil;
+ }
+
+ /**
+ * Sets the transformation matrix for the pattern.
+ * @param a
+ * @param b
+ * @param c
+ * @param d
+ * @param e
+ * @param f
+ */
+ public void setPatternMatrix(float a, float b, float c, float d, float e, float f) {
+ setMatrix(a, b, c, d, e, f);
+ }
+ /**
+ * Gets the stream representing this pattern
+ *
+ * @return the stream representing this pattern
+ */
+
+ PdfPattern getPattern() {
+ return new PdfPattern(this);
+ }
+
+ /**
+ * Gets a duplicate of this PdfPatternPainter
. All
+ * the members are copied by reference but the buffer stays different.
+ * @return a copy of this PdfPatternPainter
+ */
+
+ public PdfContentByte getDuplicate() {
+ PdfPatternPainter tpl = new PdfPatternPainter();
+ tpl.writer = writer;
+ tpl.pdf = pdf;
+ tpl.thisReference = thisReference;
+ tpl.pageResources = pageResources;
+ tpl.bBox = new Rectangle(bBox);
+ tpl.xstep = xstep;
+ tpl.ystep = ystep;
+ tpl.matrix = matrix;
+ tpl.stencil = stencil;
+ tpl.defaultColor = defaultColor;
+ return tpl;
+ }
+
+ /**
+ * Returns the default color of the pattern.
+ * @return a Color
+ */
+ public Color getDefaultColor() {
+ return defaultColor;
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setGrayFill(float)
+ */
+ public void setGrayFill(float gray) {
+ checkNoColor();
+ super.setGrayFill(gray);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#resetGrayFill()
+ */
+ public void resetGrayFill() {
+ checkNoColor();
+ super.resetGrayFill();
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setGrayStroke(float)
+ */
+ public void setGrayStroke(float gray) {
+ checkNoColor();
+ super.setGrayStroke(gray);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#resetGrayStroke()
+ */
+ public void resetGrayStroke() {
+ checkNoColor();
+ super.resetGrayStroke();
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setRGBColorFillF(float, float, float)
+ */
+ public void setRGBColorFillF(float red, float green, float blue) {
+ checkNoColor();
+ super.setRGBColorFillF(red, green, blue);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#resetRGBColorFill()
+ */
+ public void resetRGBColorFill() {
+ checkNoColor();
+ super.resetRGBColorFill();
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setRGBColorStrokeF(float, float, float)
+ */
+ public void setRGBColorStrokeF(float red, float green, float blue) {
+ checkNoColor();
+ super.setRGBColorStrokeF(red, green, blue);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#resetRGBColorStroke()
+ */
+ public void resetRGBColorStroke() {
+ checkNoColor();
+ super.resetRGBColorStroke();
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setCMYKColorFillF(float, float, float, float)
+ */
+ public void setCMYKColorFillF(float cyan, float magenta, float yellow, float black) {
+ checkNoColor();
+ super.setCMYKColorFillF(cyan, magenta, yellow, black);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#resetCMYKColorFill()
+ */
+ public void resetCMYKColorFill() {
+ checkNoColor();
+ super.resetCMYKColorFill();
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setCMYKColorStrokeF(float, float, float, float)
+ */
+ public void setCMYKColorStrokeF(float cyan, float magenta, float yellow, float black) {
+ checkNoColor();
+ super.setCMYKColorStrokeF(cyan, magenta, yellow, black);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#resetCMYKColorStroke()
+ */
+ public void resetCMYKColorStroke() {
+ checkNoColor();
+ super.resetCMYKColorStroke();
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#addImage(pdftk.com.lowagie.text.Image, float, float, float, float, float, float)
+ */
+ /* ssteward: dropped in 1.44
+ public void addImage(Image image, float a, float b, float c, float d, float e, float f) throws DocumentException {
+ if (stencil && !image.isMask())
+ checkNoColor();
+ super.addImage(image, a, b, c, d, e, f);
+ }
+ */
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setCMYKColorFill(int, int, int, int)
+ */
+ public void setCMYKColorFill(int cyan, int magenta, int yellow, int black) {
+ checkNoColor();
+ super.setCMYKColorFill(cyan, magenta, yellow, black);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setCMYKColorStroke(int, int, int, int)
+ */
+ public void setCMYKColorStroke(int cyan, int magenta, int yellow, int black) {
+ checkNoColor();
+ super.setCMYKColorStroke(cyan, magenta, yellow, black);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setRGBColorFill(int, int, int)
+ */
+ public void setRGBColorFill(int red, int green, int blue) {
+ checkNoColor();
+ super.setRGBColorFill(red, green, blue);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setRGBColorStroke(int, int, int)
+ */
+ public void setRGBColorStroke(int red, int green, int blue) {
+ checkNoColor();
+ super.setRGBColorStroke(red, green, blue);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setColorStroke(java.awt.Color)
+ */
+ public void setColorStroke(Color color) {
+ checkNoColor();
+ super.setColorStroke(color);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setColorFill(java.awt.Color)
+ */
+ public void setColorFill(Color color) {
+ checkNoColor();
+ super.setColorFill(color);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setColorFill(pdftk.com.lowagie.text.pdf.PdfSpotColor, float)
+ */
+ public void setColorFill(PdfSpotColor sp, float tint) {
+ checkNoColor();
+ super.setColorFill(sp, tint);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setColorStroke(pdftk.com.lowagie.text.pdf.PdfSpotColor, float)
+ */
+ public void setColorStroke(PdfSpotColor sp, float tint) {
+ checkNoColor();
+ super.setColorStroke(sp, tint);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setPatternFill(pdftk.com.lowagie.text.pdf.PdfPatternPainter)
+ */
+ public void setPatternFill(PdfPatternPainter p) {
+ checkNoColor();
+ super.setPatternFill(p);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setPatternFill(pdftk.com.lowagie.text.pdf.PdfPatternPainter, java.awt.Color, float)
+ */
+ public void setPatternFill(PdfPatternPainter p, Color color, float tint) {
+ checkNoColor();
+ super.setPatternFill(p, color, tint);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setPatternStroke(pdftk.com.lowagie.text.pdf.PdfPatternPainter, java.awt.Color, float)
+ */
+ public void setPatternStroke(PdfPatternPainter p, Color color, float tint) {
+ checkNoColor();
+ super.setPatternStroke(p, color, tint);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfContentByte#setPatternStroke(pdftk.com.lowagie.text.pdf.PdfPatternPainter)
+ */
+ public void setPatternStroke(PdfPatternPainter p) {
+ checkNoColor();
+ super.setPatternStroke(p);
+ }
+
+ void checkNoColor() {
+ if (stencil)
+ throw new RuntimeException("Colors are not allowed in uncolored tile patterns.");
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfReader.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfReader.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfReader.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfReader.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,3598 @@
+/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * $Id: PdfReader.java,v 1.64 2005/10/13 09:36:06 psoares33 Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.InflaterInputStream;
+import java.util.Stack;
+
+import pdftk.com.lowagie.text.exceptions.BadPasswordException;
+import pdftk.com.lowagie.text.exceptions.InvalidPdfException;
+import pdftk.com.lowagie.text.exceptions.UnsupportedPdfException;
+
+import pdftk.com.lowagie.text.pdf.interfaces.PdfViewerPreferences;
+import pdftk.com.lowagie.text.pdf.internal.PdfViewerPreferencesImp;
+
+import pdftk.com.lowagie.text.Rectangle;
+import pdftk.com.lowagie.text.PageSize;
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+/** Reads a PDF document.
+ * @author Paulo Soares (psoares@consiste.pt)
+ * @author Kazuya Ujihara
+ */
+public class PdfReader implements PdfViewerPreferences {
+
+ static final PdfName pageInhCandidates[] = {
+ PdfName.MEDIABOX, PdfName.ROTATE, PdfName.RESOURCES, PdfName.CROPBOX
+ };
+
+ static final PdfName vpnames[] = {PdfName.HIDETOOLBAR, PdfName.HIDEMENUBAR,
+ PdfName.HIDEWINDOWUI, PdfName.FITWINDOW, PdfName.CENTERWINDOW, PdfName.DISPLAYDOCTITLE};
+ static final int vpints[] = {PdfWriter.HideToolbar, PdfWriter.HideMenubar,
+ PdfWriter.HideWindowUI, PdfWriter.FitWindow, PdfWriter.CenterWindow, PdfWriter.DisplayDocTitle};
+
+ static final byte endstream[] = PdfEncodings.convertToBytes("endstream", null);
+ static final byte endobj[] = PdfEncodings.convertToBytes("endobj", null);
+ protected PRTokeniser tokens;
+ // Each xref pair is a position
+ // type 0 -> -1, 0
+ // type 1 -> offset, 0
+ // type 2 -> index, obj num
+ protected int xref[];
+ protected HashMap objStmMark;
+ protected IntHashtable objStmToOffset;
+ protected boolean newXrefType;
+ private ArrayList xrefObj;
+ PdfDictionary rootPages;
+ protected PdfDictionary trailer;
+ protected PdfDictionary catalog;
+ protected PageRefs pageRefs;
+ protected PRAcroForm acroForm = null;
+ protected boolean acroFormParsed = false;
+ protected boolean encrypted = false;
+ protected boolean rebuilt = false;
+ protected int freeXref;
+ protected boolean tampered = false;
+ protected int lastXref;
+ protected int eofPos;
+ protected char pdfVersion;
+ protected PdfEncryption decrypt;
+ protected byte password[] = null; //added by ujihara for decryption
+ protected boolean ownerPasswordUsed= false;
+ protected ArrayList strings = new ArrayList();
+ protected boolean sharedStreams = true;
+ protected boolean consolidateNamedDestinations = false;
+ protected boolean remoteToLocalNamedDestinations = false;
+ protected int rValue;
+ protected int pValue;
+ private int objNum;
+ private int objGen;
+ private int fileLength;
+ private boolean hybridXref;
+ private int lastXrefPartial = -1;
+ private boolean partial;
+
+ private PRIndirectReference cryptoRef;
+ private PdfViewerPreferencesImp viewerPreferences = new PdfViewerPreferencesImp();
+ private boolean encryptionError;
+
+ /**
+ * Holds value of property appendable.
+ */
+ private boolean appendable;
+
+ protected PdfReader() {
+ }
+
+ /** Reads and parses a PDF document.
+ * @param filename the file name of the document
+ * @throws IOException on error
+ */
+ public PdfReader(String filename) throws IOException {
+ this(filename, null);
+ }
+
+ /** Reads and parses a PDF document.
+ * @param filename the file name of the document
+ * @param ownerPassword the password to read the document
+ * @throws IOException on error
+ */
+ public PdfReader(String filename, byte ownerPassword[]) throws IOException {
+ password = ownerPassword;
+ tokens = new PRTokeniser(filename);
+ readPdf();
+ }
+
+ /** Reads and parses a PDF document.
+ * @param pdfIn the byte array with the document
+ * @throws IOException on error
+ */
+ public PdfReader(byte pdfIn[]) throws IOException {
+ this(pdfIn, null);
+ }
+
+ /** Reads and parses a PDF document.
+ * @param pdfIn the byte array with the document
+ * @param ownerPassword the password to read the document
+ * @throws IOException on error
+ */
+ public PdfReader(byte pdfIn[], byte ownerPassword[]) throws IOException {
+ password = ownerPassword;
+ tokens = new PRTokeniser(pdfIn);
+ readPdf();
+ }
+
+ /** Reads and parses a PDF document.
+ * @param url the URL of the document
+ * @throws IOException on error
+ */
+ public PdfReader(URL url) throws IOException {
+ this(url, null);
+ }
+
+ /** Reads and parses a PDF document.
+ * @param url the URL of the document
+ * @param ownerPassword the password to read the document
+ * @throws IOException on error
+ */
+ public PdfReader(URL url, byte ownerPassword[]) throws IOException {
+ password = ownerPassword;
+ tokens = new PRTokeniser(new RandomAccessFileOrArray(url));
+ readPdf();
+ }
+
+ /**
+ * Reads and parses a PDF document.
+ * @param is the InputStream
containing the document. The stream is read to the
+ * end but is not closed
+ * @param ownerPassword the password to read the document
+ * @throws IOException on error
+ */
+ public PdfReader(InputStream is, byte ownerPassword[]) throws IOException {
+ password = ownerPassword;
+ tokens = new PRTokeniser(new RandomAccessFileOrArray(is));
+ readPdf();
+ }
+
+ /**
+ * Reads and parses a PDF document.
+ * @param is the InputStream
containing the document. The stream is read to the
+ * end but is not closed
+ * @throws IOException on error
+ */
+ public PdfReader(InputStream is) throws IOException {
+ this(is, null);
+ }
+
+ /**
+ * Reads and parses a pdf document. Contrary to the other constructors only the xref is read
+ * into memory. The reader is said to be working in "partial" mode as only parts of the pdf
+ * are read as needed. The pdf is left open but may be closed at any time with
+ * PdfReader.close()
, reopen is automatic.
+ * @param raf the document location
+ * @param ownerPassword the password or null
for no password
+ * @throws IOException on error
+ */
+ public PdfReader(RandomAccessFileOrArray raf, byte ownerPassword[]) throws IOException {
+ password = ownerPassword;
+ partial = true;
+ tokens = new PRTokeniser(raf);
+ readPdfPartial();
+ }
+
+ /** Creates an independent duplicate.
+ * @param reader the PdfReader
to duplicate
+ */
+ public PdfReader(PdfReader reader) {
+ this.appendable = reader.appendable;
+ this.consolidateNamedDestinations = reader.consolidateNamedDestinations;
+ this.encrypted = reader.encrypted;
+ this.rebuilt = reader.rebuilt;
+ this.sharedStreams = reader.sharedStreams;
+ this.tampered = reader.tampered;
+ this.password = reader.password;
+ this.pdfVersion = reader.pdfVersion;
+ this.eofPos = reader.eofPos;
+ this.freeXref = reader.freeXref;
+ this.lastXref = reader.lastXref;
+ this.tokens = new PRTokeniser(reader.tokens.getSafeFile());
+ if (reader.decrypt != null)
+ this.decrypt = new PdfEncryption(reader.decrypt);
+ this.pValue = reader.pValue;
+ this.rValue = reader.rValue;
+ this.xrefObj = new ArrayList(reader.xrefObj);
+ for (int k = 0; k < reader.xrefObj.size(); ++k) {
+ this.xrefObj.set(k, duplicatePdfObject((PdfObject)reader.xrefObj.get(k), this));
+ }
+ this.pageRefs = new PageRefs(reader.pageRefs, this);
+ this.trailer = (PdfDictionary)duplicatePdfObject(reader.trailer, this);
+ this.catalog = trailer.getAsDict(PdfName.ROOT);
+ this.rootPages = catalog.getAsDict(PdfName.PAGES);
+ this.fileLength = reader.fileLength;
+ this.partial = reader.partial;
+ this.hybridXref = reader.hybridXref;
+ this.objStmToOffset = reader.objStmToOffset;
+ this.xref = reader.xref;
+ this.cryptoRef = (PRIndirectReference)duplicatePdfObject(reader.cryptoRef, this);
+ this.ownerPasswordUsed = reader.ownerPasswordUsed;
+ }
+
+ /** Gets a new file instance of the original PDF
+ * document.
+ * @return a new file instance of the original PDF document
+ */
+ public RandomAccessFileOrArray getSafeFile() {
+ return tokens.getSafeFile();
+ }
+
+ protected PdfReaderInstance getPdfReaderInstance(PdfWriter writer) {
+ return new PdfReaderInstance(this, writer);
+ }
+
+ /** Gets the number of pages in the document.
+ * @return the number of pages in the document
+ */
+ public int getNumberOfPages() {
+ return pageRefs.size();
+ }
+
+ /** Returns the document's catalog. This dictionary is not a copy,
+ * any changes will be reflected in the catalog.
+ * @return the document's catalog
+ */
+ public PdfDictionary getCatalog() {
+ return catalog;
+ }
+
+ /** Returns the document's acroform, if it has one.
+ * @return the document's acroform
+ */
+ public PRAcroForm getAcroForm() {
+ if (!acroFormParsed) {
+ acroFormParsed = true;
+ PdfObject form = catalog.get(PdfName.ACROFORM);
+ if (form != null) {
+ try {
+ acroForm = new PRAcroForm(this);
+ acroForm.readAcroForm((PdfDictionary)getPdfObject(form));
+ }
+ catch (Exception e) {
+ acroForm = null;
+ }
+ }
+ }
+ return acroForm;
+ }
+ /**
+ * Gets the page rotation. This value can be 0, 90, 180 or 270.
+ * @param index the page number. The first page is 1
+ * @return the page rotation
+ */
+ public int getPageRotation(int index) {
+ return getPageRotation(pageRefs.getPageNRelease(index));
+ }
+
+ int getPageRotation(PdfDictionary page) {
+ PdfNumber rotate = page.getAsNumber(PdfName.ROTATE);
+ if (rotate == null)
+ return 0;
+ else {
+ int n = rotate.intValue();
+ n %= 360;
+ return n < 0 ? n + 360 : n;
+ }
+ }
+ /** Gets the page size, taking rotation into account. This
+ * is a Rectangle
with the value of the /MediaBox and the /Rotate key.
+ * @param index the page number. The first page is 1
+ * @return a Rectangle
+ */
+ public Rectangle getPageSizeWithRotation(int index) {
+ return getPageSizeWithRotation(pageRefs.getPageNRelease(index));
+ }
+
+ /**
+ * Gets the rotated page from a page dictionary.
+ * @param page the page dictionary
+ * @return the rotated page
+ */
+ public Rectangle getPageSizeWithRotation(PdfDictionary page) {
+ Rectangle rect = getPageSize(page);
+ int rotation = getPageRotation(page);
+ while (rotation > 0) {
+ rect = rect.rotate();
+ rotation -= 90;
+ }
+ return rect;
+ }
+
+ /** Gets the page size without taking rotation into account. This
+ * is the value of the /MediaBox key.
+ * @param index the page number. The first page is 1
+ * @return the page size
+ */
+ public Rectangle getPageSize(int index) {
+ return getPageSize(pageRefs.getPageNRelease(index));
+ }
+
+ /**
+ * Gets the page from a page dictionary
+ * @param page the page dictionary
+ * @return the page
+ */
+ public Rectangle getPageSize(PdfDictionary page) {
+ PdfArray mediaBox = page.getAsArray(PdfName.MEDIABOX);
+ return getNormalizedRectangle(mediaBox);
+ }
+
+ /** Gets the crop box without taking rotation into account. This
+ * is the value of the /CropBox key. The crop box is the part
+ * of the document to be displayed or printed. It usually is the same
+ * as the media box but may be smaller. If the page doesn't have a crop
+ * box the page size will be returned.
+ * @param index the page number. The first page is 1
+ * @return the crop box
+ */
+ public Rectangle getCropBox(int index) {
+ return getCropBox(pageRefs.getPageNRelease(index));
+ }
+ public Rectangle getCropBox(PdfDictionary page) {
+ PdfArray cropBox = (PdfArray)getPdfObjectRelease(page.get(PdfName.CROPBOX));
+ if (cropBox == null)
+ return getPageSize(page);
+ return getNormalizedRectangle(cropBox);
+ }
+
+ /** Gets the box size. Allowed names are: "crop", "trim", "art", "bleed" and "media".
+ * @param index the page number. The first page is 1
+ * @param boxName the box name
+ * @return the box rectangle or null
+ */
+ public Rectangle getBoxSize(int index, String boxName) {
+ return getBoxSize(pageRefs.getPageNRelease(index), boxName);
+ }
+ public Rectangle getBoxSize(PdfDictionary page, String boxName) {
+ if (boxName.equals("media"))
+ return getBoxSize(page, PdfName.MEDIABOX);
+ else if (boxName.equals("crop"))
+ return getBoxSize(page, PdfName.CROPBOX);
+ else if (boxName.equals("trim"))
+ return getBoxSize(page, PdfName.TRIMBOX);
+ else if (boxName.equals("art"))
+ return getBoxSize(page, PdfName.ARTBOX);
+ else if (boxName.equals("bleed"))
+ return getBoxSize(page, PdfName.BLEEDBOX);
+ return null;
+ }
+ public Rectangle getBoxSize(PdfDictionary page, PdfName boxName) {
+ PdfArray box = (PdfArray)getPdfObjectRelease(page.get(boxName));
+ return getNormalizedRectangle(box);
+ }
+
+ /** Returns the content of the document information dictionary as a HashMap
+ * of String
.
+ * @return content of the document information dictionary
+ */
+ public HashMap getInfo() {
+ HashMap map = new HashMap();
+ PdfDictionary info = trailer.getAsDict(PdfName.INFO);
+ if (info == null)
+ return map;
+ for (Iterator it = info.getKeys().iterator(); it.hasNext();) {
+ PdfName key = (PdfName)it.next();
+ PdfObject obj = getPdfObject(info.get(key));
+ if (obj == null)
+ continue;
+ String value = obj.toString();
+ switch (obj.type()) {
+ case PdfObject.STRING: {
+ value = ((PdfString)obj).toUnicodeString();
+ break;
+ }
+ case PdfObject.NAME: {
+ value = PdfName.decodeName(value);
+ break;
+ }
+ }
+ map.put(PdfName.decodeName(key.toString()), value);
+ }
+ return map;
+ }
+
+ /** Normalizes a Rectangle
so that llx and lly are smaller than urx and ury.
+ * @param box the original rectangle
+ * @return a normalized Rectangle
+ */
+ public static Rectangle getNormalizedRectangle(PdfArray box) {
+ if( box== null )
+ return null;
+ float llx = ((PdfNumber)getPdfObjectRelease(box.getPdfObject(0))).floatValue();
+ float lly = ((PdfNumber)getPdfObjectRelease(box.getPdfObject(1))).floatValue();
+ float urx = ((PdfNumber)getPdfObjectRelease(box.getPdfObject(2))).floatValue();
+ float ury = ((PdfNumber)getPdfObjectRelease(box.getPdfObject(3))).floatValue();
+ return new Rectangle(Math.min(llx, urx), Math.min(lly, ury),
+ Math.max(llx, urx), Math.max(lly, ury));
+ }
+
+ protected void readPdf() throws IOException {
+ try {
+ fileLength = tokens.getFile().length();
+ pdfVersion = tokens.checkPdfHeader();
+ try {
+ readXref();
+ }
+ catch (Exception e) {
+ try {
+ rebuilt = true;
+ rebuildXref();
+ lastXref = -1;
+ }
+ catch (Exception ne) {
+ throw new InvalidPdfException("Rebuild failed: " + ne.getMessage() + "; Original message: " + e.getMessage());
+ }
+ }
+ try {
+ readDocObj();
+ }
+ catch (Exception e) {
+ if (e instanceof BadPasswordException)
+ throw new BadPasswordException(e.getMessage());
+ if (rebuilt || encryptionError)
+ throw new InvalidPdfException(e.getMessage());
+ rebuilt = true;
+ encrypted = false;
+ rebuildXref();
+ lastXref = -1;
+ readDocObj();
+ }
+
+ strings.clear();
+ readPages();
+ eliminateSharedStreams();
+ removeUnusedObjects();
+ }
+ finally {
+ try {
+ tokens.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ }
+
+ protected void readPdfPartial() throws IOException {
+ try {
+ fileLength = tokens.getFile().length();
+ pdfVersion = tokens.checkPdfHeader();
+ try {
+ readXref();
+ }
+ catch (Exception e) {
+ try {
+ rebuilt = true;
+ rebuildXref();
+ lastXref = -1;
+ }
+ catch (Exception ne) {
+ throw new InvalidPdfException("Rebuild failed: " + ne.getMessage() + "; Original message: " + e.getMessage());
+ }
+ }
+ readDocObjPartial();
+ readPages();
+ }
+ catch (IOException e) {
+ try{tokens.close();}catch(Exception ee){}
+ throw e;
+ }
+ }
+
+ private boolean equalsArray(byte ar1[], byte ar2[], int size) {
+ for (int k = 0; k < size; ++k) {
+ if (ar1[k] != ar2[k])
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @throws IOException
+ */
+ private void readDecryptedDocObj() throws IOException {
+ if (encrypted)
+ return;
+ PdfObject encDic = trailer.get(PdfName.ENCRYPT);
+ if (encDic == null || encDic.toString().equals("null"))
+ return;
+ encryptionError = true;
+ // byte[] encryptionKey = null;
+ encrypted = true;
+ PdfDictionary enc = (PdfDictionary)getPdfObject(encDic);
+
+ PdfObject o;
+
+ /*
+ // pdftk 1.45
+ // ssteward: updated to suit modified PdfString
+ PdfArray documentIDs = (PdfArray)getPdfObject(trailer.get(PdfName.ID));
+ byte documentID[] = null;
+ if (documentIDs != null) {
+ o = (PdfObject)documentIDs.getArrayList().get(0);
+ documentID= o.getBytes(); // ssteward
+ }
+ */
+
+ // 4.2.0
+ PdfArray documentIDs = trailer.getAsArray(PdfName.ID);
+ byte documentID[] = null;
+ if (documentIDs != null) {
+ o = documentIDs.getPdfObject(0);
+ strings.remove(o);
+ documentID= o.getBytes(); // ssteward: DocWriter.getISOBytes(String) doesn't work, here
+ if (documentIDs.size() > 1)
+ strings.remove(documentIDs.getPdfObject(1));
+ }
+ // just in case we have a broken producer
+ if (documentID == null)
+ documentID = new byte[0];
+
+ /*
+ // pdftk 1.45
+ byte uValue[]= enc.get(PdfName.U).getBytes(); // ssteward
+ byte oValue[]= enc.get(PdfName.O).getBytes(); // ssteward
+ //
+ o = enc.get(PdfName.R);
+ if (!o.isNumber()) throw new IOException("Illegal R value.");
+ rValue = ((PdfNumber)o).intValue();
+ if (rValue != 2 && rValue != 3) throw new IOException("Unknown encryption type (" + rValue + ")");
+ //
+ o = enc.get(PdfName.P);
+ if (!o.isNumber()) throw new IOException("Illegal P value.");
+ pValue = ((PdfNumber)o).intValue();
+ //
+ int cryptoMode= PdfWriter.STANDARD_ENCRYPTION_40;
+ int lengthValue= 40;
+ if( rValue== 3 ) {
+ cryptoMode= PdfWriter.STANDARD_ENCRYPTION_128;
+ lengthValue= 128;
+ }
+ */
+
+ // 4.2.0
+ byte uValue[] = null;
+ byte oValue[] = null;
+ int cryptoMode = 0; // default: error; PdfWriter.STANDARD_ENCRYPTION_40;
+ int lengthValue = 0;
+
+ // 4.2.0
+ PdfObject filter = getPdfObjectRelease(enc.get(PdfName.FILTER));
+
+ if (filter.equals(PdfName.STANDARD)) {
+ uValue= enc.get(PdfName.U).getBytes(); // ssteward
+ strings.remove(enc.get(PdfName.U));
+
+ oValue= enc.get(PdfName.O).getBytes(); // ssteward
+ strings.remove(enc.get(PdfName.O));
+
+ o = enc.get(PdfName.P);
+ if (!o.isNumber())
+ throw new InvalidPdfException("illegal.p.value");
+ pValue = ((PdfNumber)o).intValue();
+
+ o = enc.get(PdfName.R);
+ if (!o.isNumber())
+ throw new InvalidPdfException("illegal.r.value");
+ rValue = ((PdfNumber)o).intValue();
+
+ switch (rValue) {
+ case 2:
+ cryptoMode = PdfWriter.STANDARD_ENCRYPTION_40;
+ break;
+ case 3:
+ o = enc.get(PdfName.LENGTH);
+ if (!o.isNumber())
+ throw new InvalidPdfException("illegal.length.value");
+ lengthValue = ( (PdfNumber) o).intValue();
+ if (lengthValue > 128 || lengthValue < 40 || lengthValue % 8 != 0)
+ throw new InvalidPdfException("illegal.length.value");
+ cryptoMode = PdfWriter.STANDARD_ENCRYPTION_128;
+ break;
+ case 4:
+ PdfDictionary dic = (PdfDictionary)enc.get(PdfName.CF);
+ if (dic == null)
+ throw new InvalidPdfException("cf.not.found.encryption");
+ dic = (PdfDictionary)dic.get(PdfName.STDCF);
+ if (dic == null)
+ throw new InvalidPdfException("stdcf.not.found.encryption");
+ if (PdfName.V2.equals(dic.get(PdfName.CFM)))
+ cryptoMode = PdfWriter.STANDARD_ENCRYPTION_128;
+ else if (PdfName.AESV2.equals(dic.get(PdfName.CFM)))
+ cryptoMode = PdfWriter.ENCRYPTION_AES_128;
+ else
+ throw new UnsupportedPdfException("no.compatible.encryption.found");
+ PdfObject em = enc.get(PdfName.ENCRYPTMETADATA);
+ if (em != null && em.toString().equals("false"))
+ cryptoMode |= PdfWriter.DO_NOT_ENCRYPT_METADATA;
+ break;
+ default:
+ cryptoMode= 0;
+ }
+ }
+ else {
+ throw new UnsupportedPdfException("unknown.encryption");
+ }
+ if( cryptoMode== 0 ) {
+ throw new UnsupportedPdfException("unknown.encryption.type.r");
+ }
+
+ decrypt = new PdfEncryption();
+ decrypt.setCryptoMode(cryptoMode, lengthValue);
+
+ //check by owner password, first, to ensure greatest authorization
+ decrypt.setupByOwnerPassword(documentID, password, uValue, oValue, pValue);
+ if (equalsArray(uValue, decrypt.userKey, ((rValue == 3 || rValue == 4) ? 16 : 32))) {
+ ownerPasswordUsed= true;
+ }
+ else {
+ //check by user password
+ decrypt.setupByUserPassword(documentID, password, oValue, pValue);
+ if (!equalsArray(uValue, decrypt.userKey, ((rValue == 3 || rValue == 4) ? 16 : 32))) {
+
+ throw new IOException("Bad password");
+ }
+ }
+
+ for (int k = 0; k < strings.size(); ++k) {
+ PdfString str = (PdfString)strings.get(k);
+ str.decrypt(this);
+ }
+
+ if (encDic.isIndirect()) {
+ cryptoRef = (PRIndirectReference)encDic;
+ xrefObj.set(cryptoRef.getNumber(), null);
+ }
+ encryptionError = false;
+ }
+
+ /**
+ * @param obj
+ * @return a PdfObject
+ */
+ public static PdfObject getPdfObjectRelease(PdfObject obj) {
+ PdfObject obj2 = getPdfObject(obj);
+ releaseLastXrefPartial(obj);
+ return obj2;
+ }
+
+
+ /**
+ * Reads a PdfObject
resolving an indirect reference
+ * if needed.
+ * @param obj the PdfObject
to read
+ * @return the resolved PdfObject
+ */
+ public static PdfObject getPdfObject(PdfObject obj) {
+ if (obj == null)
+ return null;
+ if (!obj.isIndirect())
+ return obj;
+ try {
+ PRIndirectReference ref = (PRIndirectReference)obj;
+ int idx = ref.getNumber();
+ boolean appendable = ref.getReader().appendable;
+ obj = ref.getReader().getPdfObject(idx);
+ if (obj == null) {
+ if (appendable) {
+ obj = new PdfNull();
+ obj.setIndRef(ref);
+ return obj;
+ }
+ else
+ return PdfNull.PDFNULL;
+ }
+ else {
+ if (appendable) {
+ switch (obj.type()) {
+ case PdfObject.m_NULL:
+ obj = new PdfNull();
+ break;
+ case PdfObject.BOOLEAN:
+ obj = new PdfBoolean(((PdfBoolean)obj).booleanValue());
+ break;
+ case PdfObject.NAME:
+ obj = new PdfName(obj.getBytes());
+ break;
+ }
+ obj.setIndRef(ref);
+ }
+ return obj;
+ }
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ * Reads a PdfObject
resolving an indirect reference
+ * if needed. If the reader was opened in partial mode the object will be released
+ * to save memory.
+ * @param obj the PdfObject
to read
+ * @param parent
+ * @return a PdfObject
+ */
+ public static PdfObject getPdfObjectRelease(PdfObject obj, PdfObject parent) {
+ PdfObject obj2 = getPdfObject(obj, parent);
+ releaseLastXrefPartial(obj);
+ return obj2;
+ }
+
+ /**
+ * @param obj
+ * @param parent
+ * @return a PdfObject
+ */
+ public static PdfObject getPdfObject(PdfObject obj, PdfObject parent) {
+ if (obj == null)
+ return null;
+ if (!obj.isIndirect()) {
+ PRIndirectReference ref = null;
+ if (parent != null && (ref = parent.getIndRef()) != null && ref.getReader().isAppendable()) {
+ switch (obj.type()) {
+ case PdfObject.m_NULL: // ssteward
+ obj = new PdfNull();
+ break;
+ case PdfObject.BOOLEAN:
+ obj = new PdfBoolean(((PdfBoolean)obj).booleanValue());
+ break;
+ case PdfObject.NAME:
+ obj = new PdfName(obj.getBytes());
+ break;
+ }
+ obj.setIndRef(ref);
+ }
+ return obj;
+ }
+ return getPdfObject(obj);
+ }
+
+ /**
+ * @param idx
+ * @return a PdfObject
+ */
+ public PdfObject getPdfObjectRelease(int idx) {
+ PdfObject obj = getPdfObject(idx);
+ releaseLastXrefPartial();
+ return obj;
+ }
+
+ /**
+ * @param idx
+ * @return aPdfObject
+ */
+ public PdfObject getPdfObject(int idx) {
+ try {
+ lastXrefPartial = -1;
+ if (idx < 0 || idx >= xrefObj.size())
+ return null;
+ PdfObject obj = (PdfObject)xrefObj.get(idx);
+ if (!partial || obj != null)
+ return obj;
+ if (idx * 2 >= xref.length)
+ return null;
+ obj = readSingleObject(idx);
+ lastXrefPartial = -1;
+ if (obj != null)
+ lastXrefPartial = idx;
+ return obj;
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ *
+ */
+ public void resetLastXrefPartial() {
+ lastXrefPartial = -1;
+ }
+
+ /**
+ *
+ */
+ public void releaseLastXrefPartial() {
+ if (partial && lastXrefPartial != -1) {
+ xrefObj.set(lastXrefPartial, null);
+ lastXrefPartial = -1;
+ }
+ }
+
+ /**
+ * @param obj
+ */
+ public static void releaseLastXrefPartial(PdfObject obj) {
+ if (obj == null)
+ return;
+ if (!obj.isIndirect())
+ return;
+ if (!(obj instanceof PRIndirectReference))
+ return;
+
+ PRIndirectReference ref = (PRIndirectReference)obj;
+ PdfReader reader = ref.getReader();
+ if (reader.partial && reader.lastXrefPartial != -1 && reader.lastXrefPartial == ref.getNumber()) {
+ reader.xrefObj.set(reader.lastXrefPartial, null);
+ }
+ reader.lastXrefPartial = -1;
+ }
+
+ private void setXrefPartialObject(int idx, PdfObject obj) {
+ if (!partial || idx < 0)
+ return;
+ xrefObj.set(idx, obj);
+ }
+
+ /**
+ * @param obj
+ * @return an indirect reference
+ */
+ public PRIndirectReference addPdfObject(PdfObject obj) {
+ xrefObj.add(obj);
+ return new PRIndirectReference(this, xrefObj.size() - 1);
+ }
+
+ protected void readPages() throws IOException {
+ catalog = trailer.getAsDict(PdfName.ROOT);
+ rootPages = catalog.getAsDict(PdfName.PAGES);
+ pageRefs = new PageRefs(this);
+ }
+
+ /*
+ protected PRIndirectReference getSinglePage(int n) throws IOException {
+ PdfDictionary acc = new PdfDictionary();
+ PdfDictionary top = rootPages;
+ int base = 0;
+ while (true) {
+ break;
+ }
+ return null;
+ }
+ */
+
+ /*
+ protected void PRSimpleRecursive(PdfObject obj) throws IOException {
+ switch (obj.type()) {
+ case PdfObject.DICTIONARY:
+ case PdfObject.STREAM:
+ PdfDictionary dic = (PdfDictionary)obj;
+ for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
+ PdfName key = (PdfName)it.next();
+ PRSimpleRecursive(dic.get(key));
+ }
+ break;
+ case PdfObject.ARRAY:
+ ArrayList list = ((PdfArray)obj).getArrayList();
+ for (int k = 0; k < list.size(); ++k) {
+ PRSimpleRecursive((PdfObject)list.get(k));
+ }
+ break;
+ case PdfObject.INDIRECT:
+ PRIndirectReference ref = (PRIndirectReference)obj;
+ int num = ref.getNumber();
+ if (!visited[num]) {
+ visited[num] = true;
+ newHits.put(num, 1);
+ }
+ break;
+ }
+ }
+ */
+
+ protected void readDocObjPartial() throws IOException {
+ xrefObj = new ArrayList(xref.length / 2);
+ xrefObj.addAll(Collections.nCopies(xref.length / 2, null));
+ readDecryptedDocObj();
+ if (objStmToOffset != null) {
+ int keys[] = objStmToOffset.getKeys();
+ for (int k = 0; k < keys.length; ++k) {
+ int n = keys[k];
+ objStmToOffset.put(n, xref[n * 2]);
+ xref[n * 2] = -1;
+ }
+ }
+ }
+
+ protected PdfObject readSingleObject(int k) throws IOException {
+ strings.clear();
+ int k2 = k * 2;
+ int pos = xref[k2];
+ if (pos < 0)
+ return null;
+ if (xref[k2 + 1] > 0)
+ pos = objStmToOffset.get(xref[k2 + 1]);
+ if (pos == 0)
+ return null;
+ tokens.seek(pos);
+ tokens.nextValidToken();
+ if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+ tokens.throwError("Invalid object number.");
+ objNum = tokens.intValue();
+ tokens.nextValidToken();
+ if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+ tokens.throwError("Invalid generation number.");
+ objGen = tokens.intValue();
+ tokens.nextValidToken();
+ if (!tokens.getStringValue().equals("obj"))
+ tokens.throwError("Token 'obj' expected.");
+ PdfObject obj;
+ try {
+ obj = readPRObject();
+ for (int j = 0; j < strings.size(); ++j) {
+ PdfString str = (PdfString)strings.get(j);
+ str.decrypt(this);
+ }
+ if (obj.isStream()) {
+ checkPRStreamLength((PRStream)obj);
+ }
+ }
+ catch (Exception e) {
+ obj = null;
+ }
+ if (xref[k2 + 1] > 0) {
+ obj = readOneObjStm((PRStream)obj, xref[k2]);
+ }
+ xrefObj.set(k, obj);
+ return obj;
+ }
+
+ protected PdfObject readOneObjStm(PRStream stream, int idx) throws IOException {
+ int first = stream.getAsNumber(PdfName.FIRST).intValue();
+ byte b[] = getStreamBytes(stream, tokens.getFile());
+ PRTokeniser saveTokens = tokens;
+ tokens = new PRTokeniser(b);
+ try {
+ int address = 0;
+ boolean ok = true;
+ ++idx;
+ for (int k = 0; k < idx; ++k) {
+ ok = tokens.nextToken();
+ if (!ok)
+ break;
+ if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) {
+ ok = false;
+ break;
+ }
+ ok = tokens.nextToken();
+ if (!ok)
+ break;
+ if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) {
+ ok = false;
+ break;
+ }
+ address = tokens.intValue() + first;
+ }
+ if (!ok)
+ throw new InvalidPdfException("Error reading ObjStm");
+ tokens.seek(address);
+ return readPRObject();
+ }
+ finally {
+ tokens = saveTokens;
+ }
+ }
+
+ /**
+ * @return the percentage of the cross reference table that has been read
+ */
+ public double dumpPerc() {
+ int total = 0;
+ for (int k = 0; k < xrefObj.size(); ++k) {
+ if (xrefObj.get(k) != null)
+ ++total;
+ }
+ return (total * 100.0 / xrefObj.size());
+ }
+
+ protected void readDocObj() throws IOException {
+ ArrayList streams = new ArrayList();
+ xrefObj = new ArrayList(xref.length / 2);
+ xrefObj.addAll(Collections.nCopies(xref.length / 2, null));
+ for (int k = 2; k < xref.length; k += 2) {
+ int pos = xref[k];
+ if (pos <= 0 || xref[k + 1] > 0)
+ continue;
+ tokens.seek(pos);
+ tokens.nextValidToken();
+ if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+ tokens.throwError("Invalid object number.");
+ objNum = tokens.intValue();
+ tokens.nextValidToken();
+ if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+ tokens.throwError("Invalid generation number.");
+ objGen = tokens.intValue();
+ tokens.nextValidToken();
+ if (!tokens.getStringValue().equals("obj"))
+ tokens.throwError("Token 'obj' expected.");
+ PdfObject obj;
+ try {
+ obj = readPRObject();
+ if (obj.isStream()) {
+ streams.add(obj);
+ }
+ }
+ catch (Exception e) {
+ obj = null;
+ }
+ xrefObj.set(k / 2, obj);
+ }
+ for (int k = 0; k < streams.size(); ++k) {
+ checkPRStreamLength((PRStream)streams.get(k));
+ }
+ readDecryptedDocObj();
+ if (objStmMark != null) {
+ for (Iterator i = objStmMark.entrySet().iterator(); i.hasNext();) {
+ Map.Entry entry = (Map.Entry)i.next();
+ int n = ((Integer)entry.getKey()).intValue();
+ IntHashtable h = (IntHashtable)entry.getValue();
+ readObjStm((PRStream)xrefObj.get(n), h);
+ xrefObj.set(n, null);
+ }
+ objStmMark = null;
+ }
+ xref = null;
+ }
+
+ private void checkPRStreamLength(PRStream stream) throws IOException {
+ int fileLength = tokens.length();
+ int start = stream.getOffset();
+ boolean calc = false;
+ int streamLength = 0;
+ PdfObject obj = getPdfObjectRelease(stream.get(PdfName.LENGTH));
+ if (obj != null && obj.type() == PdfObject.NUMBER) {
+ streamLength = ((PdfNumber)obj).intValue();
+ if (streamLength + start > fileLength - 20)
+ calc = true;
+ else {
+ tokens.seek(start + streamLength);
+ String line = tokens.readString(20);
+ if (!line.startsWith("\nendstream") &&
+ !line.startsWith("\r\nendstream") &&
+ !line.startsWith("\rendstream") &&
+ !line.startsWith("endstream"))
+ calc = true;
+ }
+ }
+ else
+ calc = true;
+ if (calc) {
+ byte tline[] = new byte[16];
+ tokens.seek(start);
+ while (true) {
+ int pos = tokens.getFilePointer();
+ if (!tokens.readLineSegment(tline))
+ break;
+ if (equalsn(tline, endstream)) {
+ streamLength = pos - start;
+ break;
+ }
+ if (equalsn(tline, endobj)) {
+ tokens.seek(pos - 16);
+ String s = tokens.readString(16);
+ int index = s.indexOf("endstream");
+ if (index >= 0)
+ pos = pos - 16 + index;
+ streamLength = pos - start;
+ break;
+ }
+ }
+ }
+ stream.setLength(streamLength);
+ }
+
+ protected void readObjStm(PRStream stream, IntHashtable map) throws IOException {
+ int first = stream.getAsNumber(PdfName.FIRST).intValue();
+ int n = stream.getAsNumber(PdfName.N).intValue();
+ byte b[] = getStreamBytes(stream, tokens.getFile());
+ PRTokeniser saveTokens = tokens;
+ tokens = new PRTokeniser(b);
+ try {
+ int address[] = new int[n];
+ int objNumber[] = new int[n];
+ boolean ok = true;
+ for (int k = 0; k < n; ++k) {
+ ok = tokens.nextToken();
+ if (!ok)
+ break;
+ if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) {
+ ok = false;
+ break;
+ }
+ objNumber[k] = tokens.intValue();
+ ok = tokens.nextToken();
+ if (!ok)
+ break;
+ if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) {
+ ok = false;
+ break;
+ }
+ address[k] = tokens.intValue() + first;
+ }
+ if (!ok)
+ throw new InvalidPdfException("Error reading ObjStm");
+ for (int k = 0; k < n; ++k) {
+ if (map.containsKey(k)) {
+ tokens.seek(address[k]);
+ PdfObject obj = readPRObject();
+ xrefObj.set(objNumber[k], obj);
+ }
+ }
+ }
+ finally {
+ tokens = saveTokens;
+ }
+ }
+
+ /**
+ * Eliminates the reference to the object freeing the memory used by it and clearing
+ * the xref entry.
+ * @param obj the object. If it's an indirect reference it will be eliminated
+ * @return the object or the already erased dereferenced object
+ */
+ public static PdfObject killIndirect(PdfObject obj) {
+ if (obj == null || obj.isNull())
+ return null;
+ PdfObject ret = getPdfObjectRelease(obj);
+ if (obj.isIndirect()) {
+ PRIndirectReference ref = (PRIndirectReference)obj;
+ PdfReader reader = ref.getReader();
+ int n = ref.getNumber();
+ reader.xrefObj.set(n, null);
+ if (reader.partial)
+ reader.xref[n * 2] = -1;
+ }
+ return ret;
+ }
+
+ private void ensureXrefSize(int size) {
+ if (size == 0)
+ return;
+ if (xref == null)
+ xref = new int[size];
+ else {
+ if (xref.length < size) {
+ int xref2[] = new int[size];
+ System.arraycopy(xref, 0, xref2, 0, xref.length);
+ xref = xref2;
+ }
+ }
+ }
+
+ protected void readXref() throws IOException {
+ hybridXref = false;
+ newXrefType = false;
+ tokens.seek(tokens.getStartxref());
+ tokens.nextToken();
+ if (!tokens.getStringValue().equals("startxref"))
+ throw new InvalidPdfException("startxref not found.");
+ tokens.nextToken();
+ if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+ throw new InvalidPdfException("startxref is not followed by a number.");
+ int startxref = tokens.intValue();
+ lastXref = startxref;
+ eofPos = tokens.getFilePointer();
+ try {
+ if (readXRefStream(startxref)) {
+ newXrefType = true;
+ return;
+ }
+ }
+ catch (Exception e) {}
+ xref = null;
+ tokens.seek(startxref);
+ trailer = readXrefSection();
+ PdfDictionary trailer2 = trailer;
+ while (true) {
+ PdfNumber prev = (PdfNumber)trailer2.get(PdfName.PREV);
+ if (prev == null)
+ break;
+ tokens.seek(prev.intValue());
+ trailer2 = readXrefSection();
+ }
+ }
+
+ protected PdfDictionary readXrefSection() throws IOException {
+ tokens.nextValidToken();
+ if (!tokens.getStringValue().equals("xref"))
+ tokens.throwError("xref subsection not found");
+ int start = 0;
+ int end = 0;
+ int pos = 0;
+ int gen = 0;
+ while (true) {
+ tokens.nextValidToken();
+ if (tokens.getStringValue().equals("trailer"))
+ break;
+ if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+ tokens.throwError("Object number of the first object in this xref subsection not found");
+ start = tokens.intValue();
+ tokens.nextValidToken();
+ if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+ tokens.throwError("Number of entries in this xref subsection not found");
+ end = tokens.intValue() + start;
+ if (start == 1) { // fix incorrect start number
+ int back = tokens.getFilePointer();
+ tokens.nextValidToken();
+ pos = tokens.intValue();
+ tokens.nextValidToken();
+ gen = tokens.intValue();
+ if (pos == 0 && gen == PdfWriter.GENERATION_MAX) {
+ --start;
+ --end;
+ }
+ tokens.seek(back);
+ }
+ ensureXrefSize(end * 2);
+ for (int k = start; k < end; ++k) {
+ tokens.nextValidToken();
+ pos = tokens.intValue();
+ tokens.nextValidToken();
+ gen = tokens.intValue();
+ tokens.nextValidToken();
+ int p = k * 2;
+ if (tokens.getStringValue().equals("n")) {
+ if (xref[p] == 0 && xref[p + 1] == 0) {
+// if (pos == 0)
+// tokens.throwError("File position 0 cross-reference entry in this xref subsection");
+ xref[p] = pos;
+ }
+ }
+ else if (tokens.getStringValue().equals("f")) {
+ if (xref[p] == 0 && xref[p + 1] == 0)
+ xref[p] = -1;
+ }
+ else
+ tokens.throwError("Invalid cross-reference entry in this xref subsection");
+ }
+ }
+ PdfDictionary trailer = (PdfDictionary)readPRObject();
+ PdfNumber xrefSize = (PdfNumber)trailer.get(PdfName.SIZE);
+ ensureXrefSize(xrefSize.intValue() * 2);
+ PdfObject xrs = trailer.get(PdfName.XREFSTM);
+ if (xrs != null && xrs.isNumber()) {
+ int loc = ((PdfNumber)xrs).intValue();
+ try {
+ readXRefStream(loc);
+ newXrefType = true;
+ hybridXref = true;
+ }
+ catch (IOException e) {
+ xref = null;
+ throw e;
+ }
+ }
+ return trailer;
+ }
+
+ protected boolean readXRefStream(int ptr) throws IOException {
+ tokens.seek(ptr);
+ int thisStream = 0;
+ if (!tokens.nextToken())
+ return false;
+ if (tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+ return false;
+ thisStream = tokens.intValue();
+ if (!tokens.nextToken() || tokens.getTokenType() != PRTokeniser.TK_NUMBER)
+ return false;
+ if (!tokens.nextToken() || !tokens.getStringValue().equals("obj"))
+ return false;
+ PdfObject object = readPRObject();
+ PRStream stm = null;
+ if (object.isStream()) {
+ stm = (PRStream)object;
+ if (!PdfName.XREF.equals(stm.get(PdfName.TYPE)))
+ return false;
+ }
+ else
+ return false;
+ if (trailer == null) {
+ trailer = new PdfDictionary();
+ trailer.putAll(stm);
+ }
+ stm.setLength(((PdfNumber)stm.get(PdfName.LENGTH)).intValue());
+ int size = ((PdfNumber)stm.get(PdfName.SIZE)).intValue();
+ PdfArray index;
+ PdfObject obj = stm.get(PdfName.INDEX);
+ if (obj == null) {
+ index = new PdfArray();
+ index.add(new int[]{0, size});
+ }
+ else
+ index = (PdfArray)obj;
+ PdfArray w = (PdfArray)stm.get(PdfName.W);
+ int prev = -1;
+ obj = stm.get(PdfName.PREV);
+ if (obj != null)
+ prev = ((PdfNumber)obj).intValue();
+ // Each xref pair is a position
+ // type 0 -> -1, 0
+ // type 1 -> offset, 0
+ // type 2 -> index, obj num
+ ensureXrefSize(size * 2);
+ if (objStmMark == null && !partial)
+ objStmMark = new HashMap();
+ if (objStmToOffset == null && partial)
+ objStmToOffset = new IntHashtable();
+ byte b[] = getStreamBytes(stm, tokens.getFile());
+ int bptr = 0;
+ int wc[] = new int[3];
+ for (int k = 0; k < 3; ++k)
+ wc[k] = w.getAsNumber(k).intValue();
+ for (int idx = 0; idx < index.size(); idx += 2) {
+ int start = index.getAsNumber(idx).intValue();
+ int length = index.getAsNumber(idx + 1).intValue();
+ ensureXrefSize((start + length) * 2);
+ while (length-- > 0) {
+ int type = 1;
+ if (wc[0] > 0) {
+ type = 0;
+ for (int k = 0; k < wc[0]; ++k)
+ type = (type << 8) + (b[bptr++] & 0xff);
+ }
+ int field2 = 0;
+ for (int k = 0; k < wc[1]; ++k)
+ field2 = (field2 << 8) + (b[bptr++] & 0xff);
+ int field3 = 0;
+ for (int k = 0; k < wc[2]; ++k)
+ field3 = (field3 << 8) + (b[bptr++] & 0xff);
+ int base = start * 2;
+ if (xref[base] == 0 && xref[base + 1] == 0) {
+ switch (type) {
+ case 0:
+ xref[base] = -1;
+ break;
+ case 1:
+ xref[base] = field2;
+ break;
+ case 2:
+ xref[base] = field3;
+ xref[base + 1] = field2;
+ if (partial) {
+ objStmToOffset.put(field2, 0);
+ }
+ else {
+ Integer on = new Integer(field2);
+ IntHashtable seq = (IntHashtable)objStmMark.get(on);
+ if (seq == null) {
+ seq = new IntHashtable();
+ seq.put(field3, 1);
+ objStmMark.put(on, seq);
+ }
+ else
+ seq.put(field3, 1);
+ }
+ break;
+ }
+ }
+ ++start;
+ }
+ }
+ thisStream *= 2;
+ if (thisStream < xref.length)
+ xref[thisStream] = -1;
+
+ if (prev == -1)
+ return true;
+ return readXRefStream(prev);
+ }
+
+ protected void rebuildXref() throws IOException {
+ hybridXref = false;
+ newXrefType = false;
+ tokens.seek(0);
+ int xr[][] = new int[1024][];
+ int top = 0;
+ trailer = null;
+ byte line[] = new byte[64];
+ for (;;) {
+ int pos = tokens.getFilePointer();
+ if (!tokens.readLineSegment(line))
+ break;
+ if (line[0] == 't') {
+ if (!PdfEncodings.convertToString(line, null).startsWith("trailer"))
+ continue;
+ tokens.seek(pos);
+ tokens.nextToken();
+ pos = tokens.getFilePointer();
+ try {
+ PdfDictionary dic = (PdfDictionary)readPRObject();
+ if (dic.get(PdfName.ROOT) != null)
+ trailer = dic;
+ else
+ tokens.seek(pos);
+ }
+ catch (Exception e) {
+ tokens.seek(pos);
+ }
+ }
+ else if (line[0] >= '0' && line[0] <= '9') {
+ int obj[] = PRTokeniser.checkObjectStart(line);
+ if (obj == null)
+ continue;
+ int num = obj[0];
+ int gen = obj[1];
+ if (num >= xr.length) {
+ int newLength = num * 2;
+ int xr2[][] = new int[newLength][];
+ System.arraycopy(xr, 0, xr2, 0, top);
+ xr = xr2;
+ }
+ if (num >= top)
+ top = num + 1;
+ if (xr[num] == null || gen >= xr[num][1]) {
+ obj[0] = pos;
+ xr[num] = obj;
+ }
+ }
+ }
+ if (trailer == null)
+ throw new InvalidPdfException("trailer not found.");
+ xref = new int[top * 2];
+ for (int k = 0; k < top; ++k) {
+ int obj[] = xr[k];
+ if (obj != null)
+ xref[k * 2] = obj[0];
+ }
+ }
+
+ protected PdfDictionary readDictionary() throws IOException {
+ PdfDictionary dic = new PdfDictionary();
+ while (true) {
+ tokens.nextValidToken();
+ if (tokens.getTokenType() == PRTokeniser.TK_END_DIC)
+ break;
+ if (tokens.getTokenType() != PRTokeniser.TK_NAME)
+ tokens.throwError("Dictionary key is not a name.");
+ PdfName name = new PdfName(tokens.getStringValue(), false);
+ PdfObject obj = readPRObject();
+ int type = obj.type();
+ if (-type == PRTokeniser.TK_END_DIC)
+ tokens.throwError("Unexpected '>>'");
+ if (-type == PRTokeniser.TK_END_ARRAY)
+ tokens.throwError("Unexpected ']'");
+ dic.put(name, obj);
+ }
+ return dic;
+ }
+
+ protected PdfArray readArray() throws IOException {
+ PdfArray array = new PdfArray();
+ while (true) {
+ PdfObject obj = readPRObject();
+ int type = obj.type();
+ if (-type == PRTokeniser.TK_END_ARRAY)
+ break;
+ if (-type == PRTokeniser.TK_END_DIC)
+ tokens.throwError("Unexpected '>>'");
+ array.add(obj);
+ }
+ return array;
+ }
+
+ // Track how deeply nested the current object is, so
+ // we know when to return an individual null or boolean, or
+ // reuse one of the static ones.
+ private int readDepth = 0;
+
+ protected PdfObject readPRObject() throws IOException {
+ tokens.nextValidToken();
+ int type = tokens.getTokenType();
+ switch (type) {
+ case PRTokeniser.TK_START_DIC: {
+ ++readDepth;
+ PdfDictionary dic = readDictionary();
+ --readDepth;
+ int pos = tokens.getFilePointer();
+ // be careful in the trailer. May not be a "next" token.
+ if (tokens.nextToken() && tokens.getStringValue().equals("stream")) {
+ // ssteward - 6/21/10
+ // stream should be followed by a LF or a CRLF, but not just a CR, per the PDF spec.
+ // however, I have encountered a generated PDF (Microsoft Reporting Services 10.0.0.0)
+ // that added a space after "stream" but before the CR; so gobble up unexpected chars
+ // until we find a LF
+ // ssteward - 10/30/12
+ // I have been given a PDF with a stream with a CR but no LF -- I should have foreseen this case;
+ int ch = tokens.read();
+ /* original code
+ if (ch != '\n')
+ ch = tokens.read();
+ if (ch != '\n')
+ tokens.backOnePosition(ch);
+ */
+ // ssteward -- 6/21/10 fix
+ //while (ch != '\n')
+ // ch = tokens.read();
+ // ssteward -- 10/31/12 fix
+ // eat whitespace until we hit a LF, which is supposed to mark the beginning of the stream;
+ // this logic should work even if there is no w/s padding around the stream data
+ while( PRTokeniser.isWhitespace( ch ) ) {
+ if( ch== '\n' )
+ break;
+ ch= tokens.read();
+ }
+ // PRStream(), below, seems to assume that our position is one before the data; testing for
+ // whitespace catches case where there is a CR no LF used to delim stream data
+ if( !PRTokeniser.isWhitespace( ch ) )
+ tokens.backOnePosition( ch );
+
+ PRStream stream = new PRStream(this, tokens.getFilePointer());
+ stream.putAll(dic);
+ // crypto handling
+ stream.setObjNum(objNum, objGen);
+
+ return stream;
+ }
+ else {
+ tokens.seek(pos);
+ return dic;
+ }
+ }
+ case PRTokeniser.TK_START_ARRAY: {
+ ++readDepth;
+ PdfArray arr = readArray();
+ --readDepth;
+ return arr;
+ }
+ case PRTokeniser.TK_NUMBER:
+ return new PdfNumber(tokens.getStringValue());
+ case PRTokeniser.TK_STRING:
+ // ssteward: change from String to byte array input to PdfString()
+ //PdfString str = new PdfString(tokens.getStringValue(), null).setHexWriting(tokens.isHexString());
+ PdfString str = new PdfString( PdfEncodings.convertToBytes( tokens.getStringValue(), null) ).setHexWriting(tokens.isHexString());
+ str.setObjNum(objNum, objGen);
+ if (strings != null)
+ strings.add(str);
+
+ return str;
+ case PRTokeniser.TK_NAME: {
+ PdfName cachedName = (PdfName)PdfName.staticNames.get( tokens.getStringValue() );
+ if (readDepth > 0 && cachedName != null) {
+ return cachedName;
+ } else {
+ // an indirect name (how odd...), or a non-standard one
+ return new PdfName(tokens.getStringValue(), false);
+ }
+ }
+ case PRTokeniser.TK_REF:
+ int num = tokens.getReference();
+ PRIndirectReference ref = new PRIndirectReference(this, num, tokens.getGeneration());
+ return ref;
+ case PRTokeniser.TK_ENDOFFILE:
+ throw new IOException("unexpected.end.of.file");
+ default:
+ String sv = tokens.getStringValue();
+ if ("null".equals(sv)) {
+ if (readDepth == 0) {
+ return new PdfNull();
+ } //else
+ return PdfNull.PDFNULL;
+ }
+ else if ("true".equals(sv)) {
+ if (readDepth == 0) {
+ return new PdfBoolean( true );
+ } //else
+ return PdfBoolean.PDFTRUE;
+ }
+ else if ("false".equals(sv)) {
+ if (readDepth == 0) {
+ return new PdfBoolean( false );
+ } //else
+ return PdfBoolean.PDFFALSE;
+ }
+ return new PdfLiteral(-type, tokens.getStringValue());
+ }
+ }
+
+ /** Decodes a stream that has the FlateDecode filter.
+ * @param in the input data
+ * @return the decoded data
+ */
+ public static byte[] FlateDecode(byte in[]) {
+ byte b[] = FlateDecode(in, true);
+ if (b == null)
+ return FlateDecode(in, false);
+ return b;
+ }
+
+ /**
+ * @param in
+ * @param dicPar
+ * @return a byte array
+ */
+ public static byte[] decodePredictor(byte in[], PdfObject dicPar) {
+ if (dicPar == null || !dicPar.isDictionary())
+ return in;
+ PdfDictionary dic = (PdfDictionary)dicPar;
+ PdfObject obj = getPdfObject(dic.get(PdfName.PREDICTOR));
+ if (obj == null || !obj.isNumber())
+ return in;
+ int predictor = ((PdfNumber)obj).intValue();
+ if (predictor < 10)
+ return in;
+ int width = 1;
+ obj = getPdfObject(dic.get(PdfName.COLUMNS));
+ if (obj != null && obj.isNumber())
+ width = ((PdfNumber)obj).intValue();
+ int colors = 1;
+ obj = getPdfObject(dic.get(PdfName.COLORS));
+ if (obj != null && obj.isNumber())
+ colors = ((PdfNumber)obj).intValue();
+ int bpc = 8;
+ obj = getPdfObject(dic.get(PdfName.BITSPERCOMPONENT));
+ if (obj != null && obj.isNumber())
+ bpc = ((PdfNumber)obj).intValue();
+ DataInputStream dataStream = new DataInputStream(new ByteArrayInputStream(in));
+ ByteArrayOutputStream fout = new ByteArrayOutputStream(in.length);
+ int bytesPerPixel = colors * bpc / 8;
+ int bytesPerRow = (colors*width*bpc + 7)/8;
+ byte[] curr = new byte[bytesPerRow];
+ byte[] prior = new byte[bytesPerRow];
+
+ // Decode the (sub)image row-by-row
+ while (true) {
+ // Read the filter type byte and a row of data
+ int filter = 0;
+ try {
+ filter = dataStream.read();
+ if (filter < 0) {
+ return fout.toByteArray();
+ }
+ dataStream.readFully(curr, 0, bytesPerRow);
+ } catch (Exception e) {
+ return fout.toByteArray();
+ }
+
+ switch (filter) {
+ case 0: //PNG_FILTER_NONE
+ break;
+ case 1: //PNG_FILTER_SUB
+ for (int i = bytesPerPixel; i < bytesPerRow; i++) {
+ curr[i] += curr[i - bytesPerPixel];
+ }
+ break;
+ case 2: //PNG_FILTER_UP
+ for (int i = 0; i < bytesPerRow; i++) {
+ curr[i] += prior[i];
+ }
+ break;
+ case 3: //PNG_FILTER_AVERAGE
+ for (int i = 0; i < bytesPerPixel; i++) {
+ curr[i] += prior[i] / 2;
+ }
+ for (int i = bytesPerPixel; i < bytesPerRow; i++) {
+ curr[i] += ((curr[i - bytesPerPixel] & 0xff) + (prior[i] & 0xff))/2;
+ }
+ break;
+ case 4: //PNG_FILTER_PAETH
+ for (int i = 0; i < bytesPerPixel; i++) {
+ curr[i] += prior[i];
+ }
+
+ for (int i = bytesPerPixel; i < bytesPerRow; i++) {
+ int a = curr[i - bytesPerPixel] & 0xff;
+ int b = prior[i] & 0xff;
+ int c = prior[i - bytesPerPixel] & 0xff;
+
+ int p = a + b - c;
+ int pa = Math.abs(p - a);
+ int pb = Math.abs(p - b);
+ int pc = Math.abs(p - c);
+
+ int ret;
+
+ if ((pa <= pb) && (pa <= pc)) {
+ ret = a;
+ } else if (pb <= pc) {
+ ret = b;
+ } else {
+ ret = c;
+ }
+ curr[i] += (byte)(ret);
+ }
+ break;
+ default:
+ // Error -- unknown filter type
+ throw new RuntimeException("PNG filter unknown.");
+ }
+ try {
+ fout.write(curr);
+ }
+ catch (IOException ioe) {
+ // Never happens
+ }
+
+ // Swap curr and prior
+ byte[] tmp = prior;
+ prior = curr;
+ curr = tmp;
+ }
+ }
+
+ /** A helper to FlateDecode.
+ * @param in the input data
+ * @param strict true
to read a correct stream. false
+ * to try to read a corrupted stream
+ * @return the decoded data
+ */
+ public static byte[] FlateDecode(byte in[], boolean strict) {
+ ByteArrayInputStream stream = new ByteArrayInputStream(in);
+ InflaterInputStream zip = new InflaterInputStream(stream);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte b[] = new byte[strict ? 4092 : 1];
+ try {
+ int n;
+ while ((n = zip.read(b)) >= 0) {
+ out.write(b, 0, n);
+ }
+ zip.close();
+ out.close();
+ return out.toByteArray();
+ }
+ catch (Exception e) {
+ if (strict)
+ return null;
+ return out.toByteArray();
+ }
+ }
+
+ /** Decodes a stream that has the ASCIIHexDecode filter.
+ * @param in the input data
+ * @return the decoded data
+ */
+ public static byte[] ASCIIHexDecode(byte in[]) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ boolean first = true;
+ int n1 = 0;
+ for (int k = 0; k < in.length; ++k) {
+ int ch = in[k] & 0xff;
+ if (ch == '>')
+ break;
+ if (PRTokeniser.isWhitespace(ch))
+ continue;
+ int n = PRTokeniser.getHex(ch);
+ if (n == -1)
+ throw new RuntimeException("Illegal character in ASCIIHexDecode.");
+ if (first)
+ n1 = n;
+ else
+ out.write((byte)((n1 << 4) + n));
+ first = !first;
+ }
+ if (!first)
+ out.write((byte)(n1 << 4));
+ return out.toByteArray();
+ }
+
+ /** Decodes a stream that has the ASCII85Decode filter.
+ * @param in the input data
+ * @return the decoded data
+ */
+ public static byte[] ASCII85Decode(byte in[]) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int state = 0;
+ int chn[] = new int[5];
+ for (int k = 0; k < in.length; ++k) {
+ int ch = in[k] & 0xff;
+ if (ch == '~')
+ break;
+ if (PRTokeniser.isWhitespace(ch))
+ continue;
+ if (ch == 'z' && state == 0) {
+ out.write(0);
+ out.write(0);
+ out.write(0);
+ out.write(0);
+ continue;
+ }
+ if (ch < '!' || ch > 'u')
+ throw new RuntimeException("Illegal character in ASCII85Decode.");
+ chn[state] = ch - '!';
+ ++state;
+ if (state == 5) {
+ state = 0;
+ int r = 0;
+ for (int j = 0; j < 5; ++j)
+ r = r * 85 + chn[j];
+ out.write((byte)(r >> 24));
+ out.write((byte)(r >> 16));
+ out.write((byte)(r >> 8));
+ out.write((byte)r);
+ }
+ }
+ int r = 0;
+ // We'll ignore the next two lines for the sake of perpetuating broken PDFs
+// if (state == 1)
+// throw new RuntimeException("Illegal length in ASCII85Decode.");
+ if (state == 2) {
+ r = chn[0] * 85 * 85 * 85 * 85 + chn[1] * 85 * 85 * 85 + 85 * 85 * 85 + 85 * 85 + 85;
+ out.write((byte)(r >> 24));
+ }
+ else if (state == 3) {
+ r = chn[0] * 85 * 85 * 85 * 85 + chn[1] * 85 * 85 * 85 + chn[2] * 85 * 85 + 85 * 85 + 85;
+ out.write((byte)(r >> 24));
+ out.write((byte)(r >> 16));
+ }
+ else if (state == 4) {
+ r = chn[0] * 85 * 85 * 85 * 85 + chn[1] * 85 * 85 * 85 + chn[2] * 85 * 85 + chn[3] * 85 + 85;
+ out.write((byte)(r >> 24));
+ out.write((byte)(r >> 16));
+ out.write((byte)(r >> 8));
+ }
+ return out.toByteArray();
+ }
+
+ /** Decodes a stream that has the LZWDecode filter.
+ * @param in the input data
+ * @return the decoded data
+ */
+ public static byte[] LZWDecode(byte in[]) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ // ssteward: pdftk 1.44
+ /* uses old Sun code
+ LZWDecoder lzw = new LZWDecoder();
+ lzw.decode(in, out);
+ */
+ // new Apache Batik code
+ TIFFLZWDecoder tlzw= new TIFFLZWDecoder();
+ tlzw.decode( in, out );
+
+ return out.toByteArray();
+ }
+
+ /** Checks if the document had errors and was rebuilt.
+ * @return true if rebuilt.
+ *
+ */
+ public boolean isRebuilt() {
+ return this.rebuilt;
+ }
+
+ /** Gets the dictionary that represents a page.
+ * @param pageNum the page number. 1 is the first
+ * @return the page dictionary
+ */
+ public PdfDictionary getPageN(int pageNum) {
+ PdfDictionary dic = pageRefs.getPageN(pageNum);
+ if (dic == null)
+ return null;
+ if (appendable)
+ dic.setIndRef(pageRefs.getPageOrigRef(pageNum));
+ return dic;
+ }
+
+ /**
+ * @param pageNum
+ * @return a Dictionary object
+ */
+ public PdfDictionary getPageNRelease(int pageNum) {
+ PdfDictionary dic = getPageN(pageNum);
+ pageRefs.releasePage(pageNum);
+ return dic;
+ }
+
+ /**
+ * @param pageNum
+ */
+ public void releasePage(int pageNum) {
+ pageRefs.releasePage(pageNum);
+ }
+
+ /**
+ *
+ */
+ public void resetReleasePage() {
+ pageRefs.resetReleasePage();
+ }
+
+ /** Gets the page reference to this page.
+ * @param pageNum the page number. 1 is the first
+ * @return the page reference
+ */
+ public PRIndirectReference getPageOrigRef(int pageNum) {
+ return pageRefs.getPageOrigRef(pageNum);
+ }
+
+ /** Gets the contents of the page.
+ * @param pageNum the page number. 1 is the first
+ * @param file the location of the PDF document
+ * @throws IOException on error
+ * @return the content
+ */
+ public byte[] getPageContent(int pageNum, RandomAccessFileOrArray file) throws IOException{
+ PdfDictionary page = getPageNRelease(pageNum);
+ if (page == null)
+ return null;
+ PdfObject contents = getPdfObjectRelease(page.get(PdfName.CONTENTS));
+ if (contents == null)
+ return new byte[0];
+ ByteArrayOutputStream bout = null;
+ if (contents.isStream()) {
+ return getStreamBytes((PRStream)contents, file);
+ }
+ else if (contents.isArray()) {
+ PdfArray array = (PdfArray)contents;
+ bout = new ByteArrayOutputStream();
+ for (int k = 0; k < array.size(); ++k) {
+ PdfObject item = getPdfObjectRelease(array.getPdfObject(k));
+ if (item == null || !item.isStream())
+ continue;
+ byte[] b = getStreamBytes((PRStream)item, file);
+ bout.write(b);
+ if (k != array.size() - 1)
+ bout.write('\n');
+ }
+ return bout.toByteArray();
+ }
+ else
+ return new byte[0];
+ }
+
+ /** Gets the contents of the page.
+ * @param pageNum the page number. 1 is the first
+ * @throws IOException on error
+ * @return the content
+ */
+ public byte[] getPageContent(int pageNum) throws IOException{
+ RandomAccessFileOrArray rf = getSafeFile();
+ try {
+ rf.reOpen();
+ return getPageContent(pageNum, rf);
+ }
+ finally {
+ try{rf.close();}catch(Exception e){}
+ }
+ }
+
+ protected void killXref(PdfObject obj) {
+ if (obj == null)
+ return;
+ if ((obj instanceof PdfIndirectReference) && !obj.isIndirect())
+ return;
+ switch (obj.type()) {
+ case PdfObject.INDIRECT: {
+ int xr = ((PRIndirectReference)obj).getNumber();
+ obj = (PdfObject)xrefObj.get(xr);
+ xrefObj.set(xr, null);
+ freeXref = xr;
+ killXref(obj);
+ break;
+ }
+ case PdfObject.ARRAY: {
+ PdfArray t = (PdfArray)obj;
+ for (int i = 0; i < t.size(); ++i)
+ killXref(t.getPdfObject(i));
+ break;
+ }
+ case PdfObject.STREAM:
+ case PdfObject.DICTIONARY: {
+ PdfDictionary dic = (PdfDictionary)obj;
+ for (Iterator i = dic.getKeys().iterator(); i.hasNext();){
+ killXref(dic.get((PdfName)i.next()));
+ }
+ break;
+ }
+ }
+ }
+
+ // ssteward
+ public PRIndirectReference getPRIndirectReference( PdfObject obj ) {
+ //int xref= getFreeXref();
+ //this.xrefObj[ xref ]= obj;
+ xrefObj.add(obj);
+ return new PRIndirectReference(this, xrefObj.size() - 1);
+ }
+
+ /** Sets the contents of the page.
+ * @param content the new page content
+ * @param pageNum the page number. 1 is the first
+ */
+ public void setPageContent(int pageNum, byte content[]) {
+ setPageContent(pageNum, content, PdfStream.DEFAULT_COMPRESSION);
+ }
+ /** Sets the contents of the page.
+ * @param content the new page content
+ * @param pageNum the page number. 1 is the first
+ * @since 2.1.3 (the method already existed without param compressionLevel)
+ */
+ public void setPageContent(int pageNum, byte content[], int compressionLevel) {
+ PdfDictionary page = getPageN(pageNum);
+ if (page == null)
+ return;
+ PdfObject contents = page.get(PdfName.CONTENTS);
+ freeXref = -1;
+ killXref(contents);
+ if (freeXref == -1) {
+ xrefObj.add(null);
+ freeXref = xrefObj.size() - 1;
+ }
+ page.put(PdfName.CONTENTS, new PRIndirectReference(this, freeXref));
+ xrefObj.set(freeXref, new PRStream(this, content, compressionLevel));
+ }
+
+ /** Get the content from a stream applying the required filters.
+ * @param stream the stream
+ * @param file the location where the stream is
+ * @throws IOException on error
+ * @return the stream content
+ */
+ public static byte[] getStreamBytes(PRStream stream, RandomAccessFileOrArray file) throws IOException {
+ PdfObject filter = getPdfObjectRelease(stream.get(PdfName.FILTER));
+ byte[] b = getStreamBytesRaw(stream, file);
+ ArrayList filters = new ArrayList();
+ if (filter != null) {
+ if (filter.isName())
+ filters.add(filter);
+ else if (filter.isArray())
+ filters = ((PdfArray)filter).getArrayList();
+ }
+ ArrayList dp = new ArrayList();
+ PdfObject dpo = getPdfObjectRelease(stream.get(PdfName.DECODEPARMS));
+ if (dpo == null || (!dpo.isDictionary() && !dpo.isArray()))
+ dpo = getPdfObjectRelease(stream.get(PdfName.DP));
+ if (dpo != null) {
+ if (dpo.isDictionary())
+ dp.add(dpo);
+ else if (dpo.isArray())
+ dp = ((PdfArray)dpo).getArrayList();
+ }
+ String name;
+ for (int j = 0; j < filters.size(); ++j) {
+ name = ((PdfName)getPdfObjectRelease((PdfObject)filters.get(j))).toString();
+ if (name.equals("/FlateDecode") || name.equals("/Fl")) {
+ b = FlateDecode(b);
+ PdfObject dicParam = null;
+ if (j < dp.size()) {
+ dicParam = (PdfObject)dp.get(j);
+ b = decodePredictor(b, dicParam);
+ }
+ }
+ else if (name.equals("/ASCIIHexDecode") || name.equals("/AHx"))
+ b = ASCIIHexDecode(b);
+ else if (name.equals("/ASCII85Decode") || name.equals("/A85"))
+ b = ASCII85Decode(b);
+ else if (name.equals("/LZWDecode")) {
+ b = LZWDecode(b);
+ PdfObject dicParam = null;
+ if (j < dp.size()) {
+ dicParam = (PdfObject)dp.get(j);
+ b = decodePredictor(b, dicParam);
+ }
+ }
+ else if (name.equals("/Crypt")) {
+ }
+ else
+ throw new UnsupportedPdfException("The filter " + name + " is not supported.");
+ }
+ return b;
+ }
+
+ /** Get the content from a stream applying the required filters.
+ * @param stream the stream
+ * @throws IOException on error
+ * @return the stream content
+ */
+ public static byte[] getStreamBytes(PRStream stream) throws IOException {
+ RandomAccessFileOrArray rf = stream.getReader().getSafeFile();
+ try {
+ rf.reOpen();
+ return getStreamBytes(stream, rf);
+ }
+ finally {
+ try{rf.close();}catch(Exception e){}
+ }
+ }
+
+ /** Get the content from a stream as it is without applying any filter.
+ * @param stream the stream
+ * @param file the location where the stream is
+ * @throws IOException on error
+ * @return the stream content
+ */
+ public static byte[] getStreamBytesRaw(PRStream stream, RandomAccessFileOrArray file) throws IOException {
+ PdfReader reader = stream.getReader();
+ byte b[];
+ if (stream.getOffset() < 0)
+ b = stream.getBytes();
+ else {
+ b = new byte[stream.getLength()];
+ file.seek(stream.getOffset());
+ file.readFully(b);
+ PdfEncryption decrypt = reader.getDecrypt();
+ if (decrypt != null) {
+ PdfObject filter = getPdfObjectRelease(stream.get(PdfName.FILTER));
+ ArrayList filters = new ArrayList();
+ if (filter != null) {
+ if (filter.isName())
+ filters.add(filter);
+ else if (filter.isArray())
+ filters = ((PdfArray)filter).getArrayList();
+ }
+ boolean skip = false;
+ for (int k = 0; k < filters.size(); ++k) {
+ PdfObject obj = getPdfObjectRelease((PdfObject)filters.get(k));
+ if (obj != null && obj.toString().equals("/Crypt")) {
+ skip = true;
+ break;
+ }
+ }
+ if (!skip) {
+ decrypt.setHashKey(stream.getObjNum(), stream.getObjGen());
+ b = decrypt.decryptByteArray(b);
+ }
+ }
+ }
+ return b;
+ }
+
+ /** Get the content from a stream as it is without applying any filter.
+ * @param stream the stream
+ * @throws IOException on error
+ * @return the stream content
+ */
+ public static byte[] getStreamBytesRaw(PRStream stream) throws IOException {
+ RandomAccessFileOrArray rf = stream.getReader().getSafeFile();
+ try {
+ rf.reOpen();
+ return getStreamBytesRaw(stream, rf);
+ }
+ finally {
+ try{rf.close();}catch(Exception e){}
+ }
+ }
+
+ /** Eliminates shared streams if they exist. */
+ public void eliminateSharedStreams() {
+ if (!sharedStreams)
+ return;
+ sharedStreams = false;
+ if (pageRefs.size() == 1)
+ return;
+ ArrayList newRefs = new ArrayList();
+ ArrayList newStreams = new ArrayList();
+ IntHashtable visited = new IntHashtable();
+ for (int k = 1; k <= pageRefs.size(); ++k) {
+ PdfDictionary page = pageRefs.getPageN(k);
+ if (page == null)
+ continue;
+ PdfObject contents = getPdfObject(page.get(PdfName.CONTENTS));
+ if (contents == null)
+ continue;
+ if (contents.isStream()) {
+ PRIndirectReference ref = (PRIndirectReference)page.get(PdfName.CONTENTS);
+ if (visited.containsKey(ref.getNumber())) {
+ // need to duplicate
+ newRefs.add(ref);
+ newStreams.add(new PRStream((PRStream)contents, null));
+ }
+ else
+ visited.put(ref.getNumber(), 1);
+ }
+ else if (contents.isArray()) {
+ PdfArray array = (PdfArray)contents;
+ for (int j = 0; j < array.size(); ++j) {
+ PRIndirectReference ref = (PRIndirectReference)array.getPdfObject(j);
+ if (visited.containsKey(ref.getNumber())) {
+ // need to duplicate
+ newRefs.add(ref);
+ newStreams.add(new PRStream((PRStream)getPdfObject(ref), null));
+ }
+ else
+ visited.put(ref.getNumber(), 1);
+ }
+ }
+ }
+ if (newStreams.isEmpty())
+ return;
+ for (int k = 0; k < newStreams.size(); ++k) {
+ xrefObj.add(newStreams.get(k));
+ PRIndirectReference ref = (PRIndirectReference)newRefs.get(k);
+ ref.setNumber(xrefObj.size() - 1, 0);
+ }
+ }
+
+ /** Checks if the document was changed.
+ * @return true
if the document was changed,
+ * false
otherwise
+ */
+ public boolean isTampered() {
+ return tampered;
+ }
+
+ /**
+ * Sets the tampered state. A tampered PdfReader cannot be reused in PdfStamper.
+ * @param tampered the tampered state
+ */
+ public void setTampered(boolean tampered) {
+ this.tampered = tampered;
+ pageRefs.keepPages();
+ }
+
+ /** Gets the XML metadata.
+ * @throws IOException on error
+ * @return the XML metadata
+ */
+ public byte[] getMetadata() throws IOException {
+ PdfObject obj = getPdfObject(catalog.get(PdfName.METADATA));
+ if (!(obj instanceof PRStream))
+ return null;
+ RandomAccessFileOrArray rf = getSafeFile();
+ byte b[] = null;
+ try {
+ rf.reOpen();
+ b = getStreamBytes((PRStream)obj, rf);
+ }
+ finally {
+ try {
+ rf.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ return b;
+ }
+
+ /**
+ * Gets the byte address of the last xref table.
+ * @return the byte address of the last xref table
+ */
+ public int getLastXref() {
+ return lastXref;
+ }
+
+ /**
+ * Gets the number of xref objects.
+ * @return the number of xref objects
+ */
+ public int getXrefSize() {
+ return xrefObj.size();
+ }
+
+ /**
+ * Gets the byte address of the %%EOF marker.
+ * @return the byte address of the %%EOF marker
+ */
+ public int getEofPos() {
+ return eofPos;
+ }
+
+ /**
+ * Gets the PDF version. Only the last version char is returned. For example
+ * version 1.4 is returned as '4'.
+ * @return the PDF version
+ */
+ public char getPdfVersion() {
+ return pdfVersion;
+ }
+
+ /**
+ * Returns true
if the PDF is encrypted.
+ * @return true
if the PDF is encrypted
+ */
+ public boolean isEncrypted() {
+ return encrypted;
+ }
+
+ /**
+ * Gets the encryption permissions. It can be used directly in
+ * PdfWriter.setEncryption()
.
+ * @return the encryption permissions
+ */
+ public int getPermissions() {
+ return pValue;
+ }
+
+ /**
+ * Returns true
if the PDF has a 128 bit key encryption.
+ * @return true
if the PDF has a 128 bit key encryption
+ */
+ public boolean is128Key() {
+ return rValue == 3;
+ }
+
+ /**
+ * Gets the trailer dictionary
+ * @return the trailer dictionary
+ */
+ public PdfDictionary getTrailer() {
+ return trailer;
+ }
+
+ PdfEncryption getDecrypt() {
+ return decrypt;
+ }
+
+ static boolean equalsn(byte a1[], byte a2[]) {
+ int length = a2.length;
+ for (int k = 0; k < length; ++k) {
+ if (a1[k] != a2[k])
+ return false;
+ }
+ return true;
+ }
+
+ static boolean existsName(PdfDictionary dic, PdfName key, PdfName value) {
+ PdfObject type = getPdfObjectRelease(dic.get(key));
+ if (type == null || !type.isName())
+ return false;
+ PdfName name = (PdfName)type;
+ return name.equals(value);
+ }
+
+ static String getFontName(PdfDictionary dic) {
+ if (dic == null)
+ return null;
+ PdfObject type = getPdfObjectRelease(dic.get(PdfName.BASEFONT));
+ if (type == null || !type.isName())
+ return null;
+ return PdfName.decodeName(type.toString());
+ }
+
+ static String getSubsetPrefix(PdfDictionary dic) {
+ if (dic == null)
+ return null;
+ String s = getFontName(dic);
+ if (s == null)
+ return null;
+ if (s.length() < 8 || s.charAt(6) != '+')
+ return null;
+ for (int k = 0; k < 6; ++k) {
+ char c = s.charAt(k);
+ if (c < 'A' || c > 'Z')
+ return null;
+ }
+ return s;
+ }
+
+ /** Finds all the font subsets and changes the prefixes to some
+ * random values.
+ * @return the number of font subsets altered
+ */
+ public int shuffleSubsetNames() {
+ int total = 0;
+ for (int k = 1; k < xrefObj.size(); ++k) {
+ PdfObject obj = getPdfObjectRelease(k);
+ if (obj == null || !obj.isDictionary())
+ continue;
+ PdfDictionary dic = (PdfDictionary)obj;
+ if (!existsName(dic, PdfName.TYPE, PdfName.FONT))
+ continue;
+ if (existsName(dic, PdfName.SUBTYPE, PdfName.TYPE1)
+ || existsName(dic, PdfName.SUBTYPE, PdfName.MMTYPE1)
+ || existsName(dic, PdfName.SUBTYPE, PdfName.TRUETYPE)) {
+ String s = getSubsetPrefix(dic);
+ if (s == null)
+ continue;
+ String ns = BaseFont.createSubsetPrefix() + s.substring(7);
+ PdfName newName = new PdfName(ns);
+ dic.put(PdfName.BASEFONT, newName);
+ setXrefPartialObject(k, dic);
+ ++total;
+ PdfDictionary fd = dic.getAsDict(PdfName.FONTDESCRIPTOR);
+ if (fd == null)
+ continue;
+ fd.put(PdfName.FONTNAME, newName);
+ }
+ else if (existsName(dic, PdfName.SUBTYPE, PdfName.TYPE0)) {
+ String s = getSubsetPrefix(dic);
+ PdfArray arr = dic.getAsArray(PdfName.DESCENDANTFONTS);
+ if (arr == null)
+ continue;
+ if (arr.isEmpty())
+ continue;
+ PdfDictionary desc = arr.getAsDict(0);
+ String sde = getSubsetPrefix(desc);
+ if (sde == null)
+ continue;
+ String ns = BaseFont.createSubsetPrefix();
+ if (s != null)
+ dic.put(PdfName.BASEFONT, new PdfName(ns + s.substring(7)));
+ setXrefPartialObject(k, dic);
+ PdfName newName = new PdfName(ns + sde.substring(7));
+ desc.put(PdfName.BASEFONT, newName);
+ ++total;
+ PdfDictionary fd = desc.getAsDict(PdfName.FONTDESCRIPTOR);
+ if (fd == null)
+ continue;
+ fd.put(PdfName.FONTNAME, newName);
+ }
+ }
+ return total;
+ }
+
+ /** Finds all the fonts not subset but embedded and marks them as subset.
+ * @return the number of fonts altered
+ */
+ public int createFakeFontSubsets() {
+ int total = 0;
+ for (int k = 1; k < xrefObj.size(); ++k) {
+ PdfObject obj = getPdfObjectRelease(k);
+ if (obj == null || !obj.isDictionary())
+ continue;
+ PdfDictionary dic = (PdfDictionary)obj;
+ if (!existsName(dic, PdfName.TYPE, PdfName.FONT))
+ continue;
+ if (existsName(dic, PdfName.SUBTYPE, PdfName.TYPE1)
+ || existsName(dic, PdfName.SUBTYPE, PdfName.MMTYPE1)
+ || existsName(dic, PdfName.SUBTYPE, PdfName.TRUETYPE)) {
+ String s = getSubsetPrefix(dic);
+ if (s != null)
+ continue;
+ s = getFontName(dic);
+ if (s == null)
+ continue;
+ String ns = BaseFont.createSubsetPrefix() + s;
+ PdfDictionary fd = (PdfDictionary)getPdfObjectRelease(dic.get(PdfName.FONTDESCRIPTOR));
+ if (fd == null)
+ continue;
+ if (fd.get(PdfName.FONTFILE) == null && fd.get(PdfName.FONTFILE2) == null
+ && fd.get(PdfName.FONTFILE3) == null)
+ continue;
+ fd = dic.getAsDict(PdfName.FONTDESCRIPTOR);
+ PdfName newName = new PdfName(ns);
+ dic.put(PdfName.BASEFONT, newName);
+ fd.put(PdfName.FONTNAME, newName);
+ setXrefPartialObject(k, dic);
+ ++total;
+ }
+ }
+ return total;
+ }
+
+ private static PdfArray getNameArray(PdfObject obj) {
+ if (obj == null)
+ return null;
+ obj = getPdfObjectRelease(obj);
+ if (obj == null)
+ return null;
+ if (obj.isArray())
+ return (PdfArray)obj;
+ else if (obj.isDictionary()) {
+ PdfObject arr2 = getPdfObjectRelease(((PdfDictionary)obj).get(PdfName.D));
+ if (arr2 != null && arr2.isArray())
+ return (PdfArray)arr2;
+ }
+ return null;
+ }
+
+ /**
+ * Gets all the named destinations as an HashMap
. The key is the name
+ * and the value is the destinations array.
+ * @return gets all the named destinations
+ */
+ public HashMap getNamedDestination() {
+ return getNamedDestination(false);
+ }
+
+ /**
+ * Gets all the named destinations as an HashMap
. The key is the name
+ * and the value is the destinations array.
+ * @param keepNames true if you want the keys to be real PdfNames instead of Strings
+ * @return gets all the named destinations
+ * @since 2.1.6
+ */
+ public HashMap getNamedDestination(boolean keepNames) {
+ HashMap names = getNamedDestinationFromNames(keepNames);
+ names.putAll(getNamedDestinationFromStrings());
+ return names;
+ }
+
+ /**
+ * Gets the named destinations from the /Dests key in the catalog as an HashMap
. The key is the name
+ * and the value is the destinations array.
+ * @return gets the named destinations
+ */
+ public HashMap getNamedDestinationFromNames() {
+ return getNamedDestinationFromNames(false);
+ }
+
+ /**
+ * Gets the named destinations from the /Dests key in the catalog as an HashMap
. The key is the name
+ * and the value is the destinations array.
+ * @param keepNames true if you want the keys to be real PdfNames instead of Strings
+ * @return gets the named destinations
+ * @since 2.1.6
+ */
+ public HashMap getNamedDestinationFromNames(boolean keepNames) {
+ HashMap names = new HashMap();
+ if (catalog.get(PdfName.DESTS) != null) {
+ PdfDictionary dic = (PdfDictionary)getPdfObjectRelease(catalog.get(PdfName.DESTS));
+ if (dic == null)
+ return names;
+ Set keys = dic.getKeys();
+ for (Iterator it = keys.iterator(); it.hasNext();) {
+ PdfName key = (PdfName)it.next();
+ PdfArray arr = getNameArray(dic.get(key));
+ if (arr == null)
+ continue;
+ if (keepNames) {
+ names.put(key, arr);
+ }
+ else {
+ String name = PdfName.decodeName(key.toString());
+ names.put(name, arr);
+ }
+ }
+ }
+ return names;
+ }
+
+ /**
+ * Gets the named destinations from the /Names key in the catalog as an HashMap
. The key is the name
+ * and the value is the destinations array.
+ * @return gets the named destinations
+ */
+ public HashMap getNamedDestinationFromStrings() {
+ if (catalog.get(PdfName.NAMES) != null) {
+ PdfDictionary dic = (PdfDictionary)getPdfObjectRelease(catalog.get(PdfName.NAMES));
+ if (dic != null) {
+ dic = (PdfDictionary)getPdfObjectRelease(dic.get(PdfName.DESTS));
+ if (dic != null) {
+ HashMap names = PdfNameTree.readTree(dic);
+ for (Iterator it = names.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry)it.next();
+ PdfArray arr = getNameArray((PdfObject)entry.getValue());
+ if (arr != null)
+ entry.setValue(arr);
+ else
+ it.remove();
+ }
+ return names;
+ }
+ }
+ }
+ return new HashMap();
+ }
+
+ /**
+ * Removes all the fields from the document.
+ */
+ public void removeFields() {
+ pageRefs.resetReleasePage();
+ for (int k = 1; k <= pageRefs.size(); ++k) {
+ PdfDictionary page = pageRefs.getPageN(k);
+ PdfArray annots = page.getAsArray(PdfName.ANNOTS);
+ if (annots == null) {
+ pageRefs.releasePage(k);
+ continue;
+ }
+ for (int j = 0; j < annots.size(); ++j) {
+ PdfObject obj = getPdfObjectRelease(annots.getPdfObject(j));
+ if (obj == null || !obj.isDictionary())
+ continue;
+ PdfDictionary annot = (PdfDictionary)obj;
+ if (PdfName.WIDGET.equals(annot.get(PdfName.SUBTYPE)))
+ annots.remove(j--);
+ }
+ if (annots.isEmpty())
+ page.remove(PdfName.ANNOTS);
+ else
+ pageRefs.releasePage(k);
+ }
+ catalog.remove(PdfName.ACROFORM);
+ pageRefs.resetReleasePage();
+ }
+
+ /**
+ * Removes all the annotations and fields from the document.
+ */
+ public void removeAnnotations() {
+ pageRefs.resetReleasePage();
+ for (int k = 1; k <= pageRefs.size(); ++k) {
+ PdfDictionary page = pageRefs.getPageN(k);
+ if (page.get(PdfName.ANNOTS) == null)
+ pageRefs.releasePage(k);
+ else
+ page.remove(PdfName.ANNOTS);
+ }
+ catalog.remove(PdfName.ACROFORM);
+ pageRefs.resetReleasePage();
+ }
+
+ /* ssteward
+ public ArrayList getLinks(int page) {
+ pageRefs.resetReleasePage();
+ ArrayList result = new ArrayList();
+ PdfDictionary pageDic = pageRefs.getPageN(page);
+ if (pageDic.get(PdfName.ANNOTS) != null) {
+ PdfArray annots = pageDic.getAsArray(PdfName.ANNOTS);
+ for (int j = 0; j < annots.size(); ++j) {
+ PdfDictionary annot = (PdfDictionary)getPdfObjectRelease(annots.getPdfObject(j));
+
+ if (PdfName.LINK.equals(annot.get(PdfName.SUBTYPE))) {
+ result.add(new PdfAnnotation.PdfImportedLink(annot));
+ }
+ }
+ }
+ pageRefs.releasePage(page);
+ pageRefs.resetReleasePage();
+ return result;
+ }
+ */
+
+ private void iterateBookmarks(PdfObject outlineRef, HashMap names) {
+ while (outlineRef != null) {
+ replaceNamedDestination(outlineRef, names);
+ PdfDictionary outline = (PdfDictionary)getPdfObjectRelease(outlineRef);
+ PdfObject first = outline.get(PdfName.FIRST);
+ if (first != null) {
+ iterateBookmarks(first, names);
+ }
+ outlineRef = outline.get(PdfName.NEXT);
+ }
+ }
+
+ /**
+ * Replaces remote named links with local destinations that have the same name.
+ * @since 5.0
+ */
+ public void makeRemoteNamedDestinationsLocal() {
+ if (remoteToLocalNamedDestinations)
+ return;
+ remoteToLocalNamedDestinations = true;
+ HashMap names = getNamedDestination(true);
+ if (names.isEmpty())
+ return;
+ for (int k = 1; k <= pageRefs.size(); ++k) {
+ PdfDictionary page = pageRefs.getPageN(k);
+ PdfObject annotsRef;
+ PdfArray annots = (PdfArray)getPdfObject(annotsRef = page.get(PdfName.ANNOTS));
+ int annotIdx = lastXrefPartial;
+ releaseLastXrefPartial();
+ if (annots == null) {
+ pageRefs.releasePage(k);
+ continue;
+ }
+ boolean commitAnnots = false;
+ for (int an = 0; an < annots.size(); ++an) {
+ PdfObject objRef = annots.getPdfObject(an);
+ if (convertNamedDestination(objRef, names) && !objRef.isIndirect())
+ commitAnnots = true;
+ }
+ if (commitAnnots)
+ setXrefPartialObject(annotIdx, annots);
+ if (!commitAnnots || annotsRef.isIndirect())
+ pageRefs.releasePage(k);
+ }
+ }
+
+ /**
+ * Converts a remote named destination GoToR with a local named destination
+ * if there's a corresponding name.
+ * @param obj an annotation that needs to be screened for links to external named destinations.
+ * @param names a map with names of local named destinations
+ * @since iText 5.0
+ */
+ private boolean convertNamedDestination(PdfObject obj, HashMap names) {
+ obj = getPdfObject(obj);
+ int objIdx = lastXrefPartial;
+ releaseLastXrefPartial();
+ if (obj != null && obj.isDictionary()) {
+ PdfObject ob2 = getPdfObject(((PdfDictionary)obj).get(PdfName.A));
+ if (ob2 != null) {
+ int obj2Idx = lastXrefPartial;
+ releaseLastXrefPartial();
+ PdfDictionary dic = (PdfDictionary)ob2;
+ PdfName type = (PdfName)getPdfObjectRelease(dic.get(PdfName.S));
+ if (PdfName.GOTOR.equals(type)) {
+ PdfObject ob3 = getPdfObjectRelease(dic.get(PdfName.D));
+ Object name = null;
+ if (ob3 != null) {
+ if (ob3.isName())
+ name = ob3;
+ else if (ob3.isString())
+ name = ob3.toString();
+ PdfArray dest = (PdfArray)names.get(name);
+ if (dest != null) {
+ dic.remove(PdfName.F);
+ dic.remove(PdfName.NEWWINDOW);
+ dic.put(PdfName.S, PdfName.GOTO);
+ setXrefPartialObject(obj2Idx, ob2);
+ setXrefPartialObject(objIdx, obj);
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /** Replaces all the local named links with the actual destinations. */
+ public void consolidateNamedDestinations() {
+ if (consolidateNamedDestinations)
+ return;
+ consolidateNamedDestinations = true;
+ HashMap names = getNamedDestination(true);
+ if (names.isEmpty())
+ return;
+ for (int k = 1; k <= pageRefs.size(); ++k) {
+ PdfDictionary page = pageRefs.getPageN(k);
+ PdfObject annotsRef;
+ PdfArray annots = (PdfArray)getPdfObject(annotsRef = page.get(PdfName.ANNOTS));
+ int annotIdx = lastXrefPartial;
+ releaseLastXrefPartial();
+ if (annots == null) {
+ pageRefs.releasePage(k);
+ continue;
+ }
+ boolean commitAnnots = false;
+ for (int an = 0; an < annots.size(); ++an) {
+ PdfObject objRef = annots.getPdfObject(an);
+ if (replaceNamedDestination(objRef, names) && !objRef.isIndirect())
+ commitAnnots = true;
+ }
+ if (commitAnnots)
+ setXrefPartialObject(annotIdx, annots);
+ if (!commitAnnots || annotsRef.isIndirect())
+ pageRefs.releasePage(k);
+ }
+ PdfDictionary outlines = (PdfDictionary)getPdfObjectRelease(catalog.get(PdfName.OUTLINES));
+ if (outlines == null)
+ return;
+ iterateBookmarks(outlines.get(PdfName.FIRST), names);
+ }
+
+ private boolean replaceNamedDestination(PdfObject obj, HashMap names) {
+ obj = getPdfObject(obj);
+ int objIdx = lastXrefPartial;
+ releaseLastXrefPartial();
+ if (obj != null && obj.isDictionary()) {
+ PdfObject ob2 = getPdfObjectRelease(((PdfDictionary)obj).get(PdfName.DEST));
+ Object name = null;
+ if (ob2 != null) {
+ if (ob2.isName())
+ name = ob2;
+ else if (ob2.isString())
+ name = ob2.toString();
+ PdfArray dest = (PdfArray)names.get(name);
+ if (dest != null) {
+ ((PdfDictionary)obj).put(PdfName.DEST, dest);
+ setXrefPartialObject(objIdx, obj);
+ return true;
+ }
+ }
+ else if ((ob2 = getPdfObject(((PdfDictionary)obj).get(PdfName.A))) != null) {
+ int obj2Idx = lastXrefPartial;
+ releaseLastXrefPartial();
+ PdfDictionary dic = (PdfDictionary)ob2;
+ PdfName type = (PdfName)getPdfObjectRelease(dic.get(PdfName.S));
+ if (PdfName.GOTO.equals(type)) {
+ PdfObject ob3 = getPdfObjectRelease(dic.get(PdfName.D));
+ if (ob3 != null) {
+ if (ob3.isName())
+ name = ob3;
+ else if (ob3.isString())
+ name = ob3.toString();
+ }
+ PdfArray dest = (PdfArray)names.get(name);
+ if (dest != null) {
+ dic.put(PdfName.D, dest);
+ setXrefPartialObject(obj2Idx, ob2);
+ setXrefPartialObject(objIdx, obj);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ protected static PdfDictionary duplicatePdfDictionary(PdfDictionary original, PdfDictionary copy, PdfReader newReader) {
+ if (copy == null)
+ copy = new PdfDictionary();
+ for (Iterator it = original.getKeys().iterator(); it.hasNext();) {
+ PdfName key = (PdfName)it.next();
+ copy.put(key, duplicatePdfObject(original.get(key), newReader));
+ }
+ return copy;
+ }
+
+ protected static PdfObject duplicatePdfObject(PdfObject original, PdfReader newReader) {
+ if (original == null)
+ return null;
+ switch (original.type()) {
+ case PdfObject.DICTIONARY: {
+ return duplicatePdfDictionary((PdfDictionary)original, null, newReader);
+ }
+ case PdfObject.STREAM: {
+ PRStream org = (PRStream)original;
+ PRStream stream = new PRStream(org, null, newReader);
+ duplicatePdfDictionary(org, stream, newReader);
+ return stream;
+ }
+ case PdfObject.ARRAY: {
+ PdfArray arr = new PdfArray();
+ for (Iterator it = ((PdfArray)original).listIterator(); it.hasNext();) {
+ arr.add(duplicatePdfObject((PdfObject)it.next(), newReader));
+ }
+ return arr;
+ }
+ case PdfObject.INDIRECT: {
+ PRIndirectReference org = (PRIndirectReference)original;
+ return new PRIndirectReference(newReader, org.getNumber(), org.getGeneration());
+ }
+ default:
+ return original;
+ }
+ }
+
+ /**
+ * Closes the reader
+ */
+ public void close() {
+ if (!partial)
+ return;
+ try {
+ tokens.close();
+ }
+ catch (IOException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ // 4.2.0
+ protected void removeUnusedNode(PdfObject obj, boolean hits[]) {
+ Stack state = new Stack();
+ state.push(obj);
+ while (!state.empty()) {
+ Object current = state.pop();
+ if (current == null)
+ continue;
+ ArrayList ar = null;
+ PdfDictionary dic = null;
+ PdfName[] keys = null;
+ Object[] objs = null;
+ int idx = 0;
+ if (current instanceof PdfObject) {
+ obj = (PdfObject)current;
+ boolean continue_b= false; // ssteward: workaround for unreachable code warning from gcj
+ switch (obj.type()) {
+ case PdfObject.DICTIONARY:
+ case PdfObject.STREAM:
+ dic = (PdfDictionary)obj;
+ keys = new PdfName[dic.size()];
+ dic.getKeys().toArray(keys);
+ break;
+ case PdfObject.ARRAY:
+ ar = ((PdfArray)obj).getArrayList();
+ break;
+ case PdfObject.INDIRECT:
+ PRIndirectReference ref = (PRIndirectReference)obj;
+ int num = ref.getNumber();
+ if (!hits[num]) {
+ hits[num] = true;
+ state.push(getPdfObjectRelease(ref));
+ }
+ continue_b= true;
+ default:
+ continue_b= true;
+ }
+ if( continue_b )
+ continue;
+ }
+ else {
+ objs = (Object[])current;
+ if (objs[0] instanceof ArrayList) {
+ ar = (ArrayList)objs[0];
+ idx = ((Integer)objs[1]).intValue();
+ }
+ else {
+ keys = (PdfName[])objs[0];
+ dic = (PdfDictionary)objs[1];
+ idx = ((Integer)objs[2]).intValue();
+ }
+ }
+ if (ar != null) {
+ for (int k = idx; k < ar.size(); ++k) {
+ PdfObject v = (PdfObject)ar.get(k);
+ if (v.isIndirect()) {
+ int num = ((PRIndirectReference)v).getNumber();
+ if (num >= xrefObj.size() || (!partial && xrefObj.get(num) == null)) {
+ ar.set(k, PdfNull.PDFNULL);
+ continue;
+ }
+ }
+ if (objs == null)
+ state.push(new Object[]{ar, new Integer(k + 1)});
+ else {
+ objs[1] = new Integer(k + 1);
+ state.push(objs);
+ }
+ state.push(v);
+ break;
+ }
+ }
+ else {
+ for (int k = idx; k < keys.length; ++k) {
+ PdfName key = keys[k];
+ PdfObject v = dic.get(key);
+ if (v.isIndirect()) {
+ int num = ((PRIndirectReference)v).getNumber();
+ if (num >= xrefObj.size() || (!partial && xrefObj.get(num) == null)) {
+ dic.put(key, PdfNull.PDFNULL);
+ continue;
+ }
+ }
+ if (objs == null)
+ state.push(new Object[]{keys, dic, new Integer(k + 1)});
+ else {
+ objs[2] = new Integer(k + 1);
+ state.push(objs);
+ }
+ state.push(v);
+ break;
+ }
+ }
+ }
+ }
+
+ /** Removes all the unreachable objects.
+ * @return the number of indirect objects removed
+ */
+ public int removeUnusedObjects() {
+ boolean hits[] = new boolean[xrefObj.size()];
+ removeUnusedNode(trailer, hits);
+ int total = 0;
+ if (partial) {
+ for (int k = 1; k < hits.length; ++k) {
+ if (!hits[k]) {
+ xref[k * 2] = -1;
+ xref[k * 2 + 1] = 0;
+ xrefObj.set(k, null);
+ ++total;
+ }
+ }
+ }
+ else {
+ for (int k = 1; k < hits.length; ++k) {
+ if (!hits[k]) {
+ xrefObj.set(k, null);
+ ++total;
+ }
+ }
+ }
+ return total;
+ }
+
+ /** Gets a read-only version of AcroFields
.
+ * @return a read-only version of AcroFields
+ */
+ public AcroFields getAcroFields() {
+ return new AcroFields(this, null);
+ }
+
+ /**
+ * Gets the global document JavaScript.
+ * @param file the document file
+ * @throws IOException on error
+ * @return the global document JavaScript
+ */
+ public String getJavaScript(RandomAccessFileOrArray file) throws IOException {
+ PdfDictionary names = (PdfDictionary)getPdfObjectRelease(catalog.get(PdfName.NAMES));
+ if (names == null)
+ return null;
+ PdfDictionary js = (PdfDictionary)getPdfObjectRelease(names.get(PdfName.JAVASCRIPT));
+ if (js == null)
+ return null;
+ HashMap jscript = PdfNameTree.readTree(js);
+ String sortedNames[] = new String[jscript.size()];
+ sortedNames = (String[])jscript.keySet().toArray(sortedNames);
+ Arrays.sort(sortedNames);
+ StringBuffer buf = new StringBuffer();
+ for (int k = 0; k < sortedNames.length; ++k) {
+ PdfDictionary j = (PdfDictionary)getPdfObjectRelease((PdfIndirectReference)jscript.get(sortedNames[k]));
+ if (j == null)
+ continue;
+ PdfObject obj = getPdfObjectRelease(j.get(PdfName.JS));
+ if (obj != null) {
+ if (obj.isString())
+ buf.append(((PdfString)obj).toUnicodeString()).append('\n');
+ else if (obj.isStream()) {
+ byte bytes[] = getStreamBytes((PRStream)obj, file);
+ if (bytes.length >= 2 && bytes[0] == (byte)254 && bytes[1] == (byte)255)
+ buf.append(PdfEncodings.convertToString(bytes, PdfObject.TEXT_UNICODE));
+ else
+ buf.append(PdfEncodings.convertToString(bytes, PdfObject.TEXT_PDFDOCENCODING));
+ buf.append('\n');
+ }
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Gets the global document JavaScript.
+ * @throws IOException on error
+ * @return the global document JavaScript
+ */
+ public String getJavaScript() throws IOException {
+ RandomAccessFileOrArray rf = getSafeFile();
+ try {
+ rf.reOpen();
+ return getJavaScript(rf);
+ }
+ finally {
+ try{rf.close();}catch(Exception e){}
+ }
+ }
+
+ /**
+ * Selects the pages to keep in the document. The pages are described as
+ * ranges. The page ordering can be changed but
+ * no page repetitions are allowed. Note that it may be very slow in partial mode.
+ * @param ranges the comma separated ranges as described in {@link SequenceList}
+ */
+ public void selectPages(String ranges) {
+ selectPages(SequenceList.expand(ranges, getNumberOfPages()));
+ }
+
+ /**
+ * Selects the pages to keep in the document. The pages are described as a
+ * List
of Integer
. The page ordering can be changed but
+ * no page repetitions are allowed. Note that it may be very slow in partial mode.
+ * @param pagesToKeep the pages to keep in the document
+ */
+ public void selectPages(List pagesToKeep) {
+ pageRefs.selectPages(pagesToKeep);
+ removeUnusedObjects();
+ }
+
+ /** Sets the viewer preferences as the sum of several constants.
+ * @param preferences the viewer preferences
+ * @see PdfViewerPreferences#setViewerPreferences
+ */
+ public void setViewerPreferences(int preferences) {
+ this.viewerPreferences.setViewerPreferences(preferences);
+ setViewerPreferences(this.viewerPreferences);
+ }
+
+ /** Adds a viewer preference
+ * @param key a key for a viewer preference
+ * @param value a value for the viewer preference
+ * @see PdfViewerPreferences#addViewerPreference
+ */
+ public void addViewerPreference(PdfName key, PdfObject value) {
+ this.viewerPreferences.addViewerPreference(key, value);
+ setViewerPreferences(this.viewerPreferences);
+ }
+
+ void setViewerPreferences(PdfViewerPreferencesImp vp) {
+ vp.addToCatalog(catalog);
+ }
+
+ /**
+ * Returns a bitset representing the PageMode and PageLayout viewer preferences.
+ * Doesn't return any information about the ViewerPreferences dictionary.
+ * @return an int that contains the Viewer Preferences.
+ */
+ public int getSimpleViewerPreferences() {
+ return PdfViewerPreferencesImp.getViewerPreferences(catalog).getPageLayoutAndMode();
+ }
+
+ /**
+ * Getter for property appendable.
+ * @return Value of property appendable.
+ */
+ public boolean isAppendable() {
+ return this.appendable;
+ }
+
+ /**
+ * Setter for property appendable.
+ * @param appendable New value of property appendable.
+ */
+ public void setAppendable(boolean appendable) {
+ this.appendable = appendable;
+ if (appendable)
+ getPdfObject(trailer.get(PdfName.ROOT));
+ }
+
+ /**
+ * Getter for property newXrefType.
+ * @return Value of property newXrefType.
+ */
+ public boolean isNewXrefType() {
+ return newXrefType;
+ }
+
+ /**
+ * Getter for property fileLength.
+ * @return Value of property fileLength.
+ */
+ public int getFileLength() {
+ return fileLength;
+ }
+
+ /**
+ * Getter for property hybridXref.
+ * @return Value of property hybridXref.
+ */
+ public boolean isHybridXref() {
+ return hybridXref;
+ }
+
+ static class PageRefs {
+ private PdfReader reader;
+ /** ArrayList with the indirect references to every page. Element 0 = page 1; 1 = page 2;... Not used for partial reading. */
+ private ArrayList refsn;
+ /** The number of pages, updated only in case of partial reading. */
+ private int sizep;
+ /** intHashtable that does the same thing as refsn in case of partial reading: major difference: not all the pages are read. */
+ private IntHashtable refsp;
+ /** Page number of the last page that was read (partial reading only) */
+ private int lastPageRead = -1;
+ /** stack to which pages dictionaries are pushed to keep track of the current page attributes */
+ private ArrayList pageInh;
+ private boolean keepPages;
+
+ private PageRefs(PdfReader reader) throws IOException {
+ this.reader = reader;
+ if (reader.partial) {
+ refsp = new IntHashtable();
+ PdfNumber npages = (PdfNumber)PdfReader.getPdfObjectRelease(reader.rootPages.get(PdfName.COUNT));
+ sizep = npages.intValue();
+ }
+ else {
+ readPages();
+ }
+ }
+
+ PageRefs(PageRefs other, PdfReader reader) {
+ this.reader = reader;
+ this.sizep = other.sizep;
+ if (other.refsn != null) {
+ refsn = new ArrayList(other.refsn);
+ for (int k = 0; k < refsn.size(); ++k) {
+ refsn.set(k, duplicatePdfObject((PdfObject)refsn.get(k), reader));
+ }
+ }
+ else
+ this.refsp = (IntHashtable)other.refsp.clone();
+ }
+
+ int size() {
+ if (refsn != null)
+ return refsn.size();
+ else
+ return sizep;
+ }
+
+ void readPages() throws IOException {
+ if (refsn != null)
+ return;
+ refsp = null;
+ refsn = new ArrayList();
+ pageInh = new ArrayList();
+ iteratePages((PRIndirectReference)reader.catalog.get(PdfName.PAGES));
+ pageInh = null;
+ reader.rootPages.put(PdfName.COUNT, new PdfNumber(refsn.size()));
+ }
+
+ void reReadPages() throws IOException {
+ refsn = null;
+ readPages();
+ }
+
+ /** Gets the dictionary that represents a page.
+ * @param pageNum the page number. 1 is the first
+ * @return the page dictionary
+ */
+ public PdfDictionary getPageN(int pageNum) {
+ PRIndirectReference ref = getPageOrigRef(pageNum);
+ return (PdfDictionary)PdfReader.getPdfObject(ref);
+ }
+
+ /**
+ * @param pageNum
+ * @return a dictionary object
+ */
+ public PdfDictionary getPageNRelease(int pageNum) {
+ PdfDictionary page = getPageN(pageNum);
+ releasePage(pageNum);
+ return page;
+ }
+
+ /**
+ * @param pageNum
+ * @return an indirect reference
+ */
+ public PRIndirectReference getPageOrigRefRelease(int pageNum) {
+ PRIndirectReference ref = getPageOrigRef(pageNum);
+ releasePage(pageNum);
+ return ref;
+ }
+
+ /**
+ * Gets the page reference to this page.
+ * @param pageNum the page number. 1 is the first
+ * @return the page reference
+ */
+ public PRIndirectReference getPageOrigRef(int pageNum) {
+ try {
+ --pageNum;
+ if (pageNum < 0 || pageNum >= size())
+ return null;
+ if (refsn != null)
+ return (PRIndirectReference)refsn.get(pageNum);
+ else {
+ int n = refsp.get(pageNum);
+ if (n == 0) {
+ PRIndirectReference ref = getSinglePage(pageNum);
+ if (reader.lastXrefPartial == -1)
+ lastPageRead = -1;
+ else
+ lastPageRead = pageNum;
+ reader.lastXrefPartial = -1;
+ refsp.put(pageNum, ref.getNumber());
+ if (keepPages)
+ lastPageRead = -1;
+ return ref;
+ }
+ else {
+ if (lastPageRead != pageNum)
+ lastPageRead = -1;
+ if (keepPages)
+ lastPageRead = -1;
+ return new PRIndirectReference(reader, n);
+ }
+ }
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ void keepPages() {
+ if (refsp == null || keepPages)
+ return;
+ keepPages = true;
+ refsp.clear();
+ }
+
+ /**
+ * @param pageNum
+ */
+ public void releasePage(int pageNum) {
+ if (refsp == null)
+ return;
+ --pageNum;
+ if (pageNum < 0 || pageNum >= size())
+ return;
+ if (pageNum != lastPageRead)
+ return;
+ lastPageRead = -1;
+ reader.lastXrefPartial = refsp.get(pageNum);
+ reader.releaseLastXrefPartial();
+ refsp.remove(pageNum);
+ }
+
+ /**
+ *
+ */
+ public void resetReleasePage() {
+ if (refsp == null)
+ return;
+ lastPageRead = -1;
+ }
+
+ void insertPage(int pageNum, PRIndirectReference ref) {
+ --pageNum;
+ if (refsn != null) {
+ if (pageNum >= refsn.size())
+ refsn.add(ref);
+ else
+ refsn.add(pageNum, ref);
+ }
+ else {
+ ++sizep;
+ lastPageRead = -1;
+ if (pageNum >= size()) {
+ refsp.put(size(), ref.getNumber());
+ }
+ else {
+ IntHashtable refs2 = new IntHashtable((refsp.size() + 1) * 2);
+ for (Iterator it = refsp.getEntryIterator(); it.hasNext();) {
+ IntHashtable.Entry entry = (IntHashtable.Entry)it.next();
+ int p = entry.getKey();
+ refs2.put(p >= pageNum ? p + 1 : p, entry.getValue());
+ }
+ refs2.put(pageNum, ref.getNumber());
+ refsp = refs2;
+ }
+ }
+ }
+
+ /**
+ * Adds a PdfDictionary to the pageInh stack to keep track of the page attributes.
+ * @param nodePages a Pages dictionary
+ */
+ private void pushPageAttributes(PdfDictionary nodePages) {
+ PdfDictionary dic = new PdfDictionary();
+ if (!pageInh.isEmpty()) {
+ dic.putAll((PdfDictionary)pageInh.get(pageInh.size() - 1));
+ }
+ for (int k = 0; k < pageInhCandidates.length; ++k) {
+ PdfObject obj = nodePages.get(pageInhCandidates[k]);
+ if (obj != null)
+ dic.put(pageInhCandidates[k], obj);
+ }
+ pageInh.add(dic);
+ }
+
+ /**
+ * Removes the last PdfDictionary that was pushed to the pageInh stack.
+ */
+ private void popPageAttributes() {
+ pageInh.remove(pageInh.size() - 1);
+ }
+
+ private void iteratePages(PRIndirectReference rpage) throws IOException {
+ PdfDictionary page = (PdfDictionary)getPdfObject(rpage);
+ PdfArray kidsPR = page.getAsArray(PdfName.KIDS);
+ // reference to a leaf
+ if (kidsPR == null) {
+ page.put(PdfName.TYPE, PdfName.PAGE);
+ PdfDictionary dic = (PdfDictionary)pageInh.get(pageInh.size() - 1);
+ PdfName key;
+ for (Iterator i = dic.getKeys().iterator(); i.hasNext();) {
+ key = (PdfName)i.next();
+ if (page.get(key) == null)
+ page.put(key, dic.get(key));
+ }
+ if (page.get(PdfName.MEDIABOX) == null) {
+ PdfArray arr = new PdfArray(new float[]{0,0,PageSize.LETTER.width(),PageSize.LETTER.height()});
+ page.put(PdfName.MEDIABOX, arr);
+ }
+ refsn.add(rpage);
+ }
+ // reference to a branch
+ else {
+ page.put(PdfName.TYPE, PdfName.PAGES);
+ pushPageAttributes(page);
+ for (int k = 0; k < kidsPR.size(); ++k){
+ PdfObject obj = kidsPR.getPdfObject(k);
+ if (!obj.isIndirect()) {
+ while (k < kidsPR.size())
+ kidsPR.remove(k);
+ break;
+ }
+ iteratePages((PRIndirectReference)obj);
+ }
+ popPageAttributes();
+ }
+ }
+
+ protected PRIndirectReference getSinglePage(int n) {
+ PdfDictionary acc = new PdfDictionary();
+ PdfDictionary top = reader.rootPages;
+ int base = 0;
+ while (true) {
+ for (int k = 0; k < pageInhCandidates.length; ++k) {
+ PdfObject obj = top.get(pageInhCandidates[k]);
+ if (obj != null)
+ acc.put(pageInhCandidates[k], obj);
+ }
+ PdfArray kids = (PdfArray)PdfReader.getPdfObjectRelease(top.get(PdfName.KIDS));
+ for (Iterator it = kids.listIterator(); it.hasNext();) {
+ PRIndirectReference ref = (PRIndirectReference)it.next();
+ PdfDictionary dic = (PdfDictionary)getPdfObject(ref);
+ int last = reader.lastXrefPartial;
+ PdfObject count = getPdfObjectRelease(dic.get(PdfName.COUNT));
+ reader.lastXrefPartial = last;
+ int acn = 1;
+ if (count != null && count.type() == PdfObject.NUMBER)
+ acn = ((PdfNumber)count).intValue();
+ if (n < base + acn) {
+ if (count == null) {
+ dic.mergeDifferent(acc);
+ return ref;
+ }
+ reader.releaseLastXrefPartial();
+ top = dic;
+ break;
+ }
+ reader.releaseLastXrefPartial();
+ base += acn;
+ }
+ }
+ }
+
+ private void selectPages(List pagesToKeep) {
+ IntHashtable pg = new IntHashtable();
+ ArrayList finalPages = new ArrayList();
+ int psize = size();
+ for (Iterator it = pagesToKeep.iterator(); it.hasNext();) {
+ Integer pi = (Integer)it.next();
+ int p = pi.intValue();
+ if (p >= 1 && p <= psize && pg.put(p, 1) == 0)
+ finalPages.add(pi);
+ }
+ if (reader.partial) {
+ for (int k = 1; k <= psize; ++k) {
+ getPageOrigRef(k);
+ resetReleasePage();
+ }
+ }
+ PRIndirectReference parent = (PRIndirectReference)reader.catalog.get(PdfName.PAGES);
+ PdfDictionary topPages = (PdfDictionary)PdfReader.getPdfObject(parent);
+ ArrayList newPageRefs = new ArrayList(finalPages.size());
+ PdfArray kids = new PdfArray();
+ for (int k = 0; k < finalPages.size(); ++k) {
+ int p = ((Integer)finalPages.get(k)).intValue();
+ PRIndirectReference pref = getPageOrigRef(p);
+ resetReleasePage();
+ kids.add(pref);
+ newPageRefs.add(pref);
+ getPageN(p).put(PdfName.PARENT, parent);
+ }
+ AcroFields af = reader.getAcroFields();
+ boolean removeFields = (af.getFields().size() > 0);
+ for (int k = 1; k <= psize; ++k) {
+ if (!pg.containsKey(k)) {
+ if (removeFields)
+ af.removeFieldsFromPage(k);
+ PRIndirectReference pref = getPageOrigRef(k);
+ int nref = pref.getNumber();
+ reader.xrefObj.set(nref, null);
+ if (reader.partial) {
+ reader.xref[nref * 2] = -1;
+ reader.xref[nref * 2 + 1] = 0;
+ }
+ }
+ }
+ topPages.put(PdfName.COUNT, new PdfNumber(finalPages.size()));
+ topPages.put(PdfName.KIDS, kids);
+ refsp = null;
+ refsn = newPageRefs;
+ }
+ }
+
+ PdfIndirectReference getCryptoRef() {
+ if (cryptoRef == null)
+ return null;
+ return new PdfIndirectReference(0, cryptoRef.getNumber(), cryptoRef.getGeneration());
+ }
+
+ /**
+ * Removes any usage rights that this PDF may have. Only Adobe can grant usage rights
+ * and any PDF modification with iText will invalidate them. Invalidated usage rights may
+ * confuse Acrobat and it's advisable to remove them altogether.
+ */
+ public void removeUsageRights() {
+ PdfDictionary perms = catalog.getAsDict(PdfName.PERMS);
+ if (perms == null)
+ return;
+ perms.remove(PdfName.UR);
+ perms.remove(PdfName.UR3);
+ if (perms.size() == 0)
+ catalog.remove(PdfName.PERMS);
+ }
+
+ /**
+ * Gets the certification level for this document. The return values can be PdfSignatureAppearance.NOT_CERTIFIED
,
+ * PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED
,
+ * PdfSignatureAppearance.CERTIFIED_FORM_FILLING
and
+ * PdfSignatureAppearance.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS
.
+ *
+ * No signature validation is made, use the methods available for that in AcroFields
.
+ *
+ * @return gets the certification level for this document
+ */
+ /* ssteward
+ public int getCertificationLevel() {
+ PdfDictionary dic = catalog.getAsDict(PdfName.PERMS);
+ if (dic == null)
+ return PdfSignatureAppearance.NOT_CERTIFIED;
+ dic = dic.getAsDict(PdfName.DOCMDP);
+ if (dic == null)
+ return PdfSignatureAppearance.NOT_CERTIFIED;
+ PdfArray arr = dic.getAsArray(PdfName.REFERENCE);
+ if (arr == null || arr.size() == 0)
+ return PdfSignatureAppearance.NOT_CERTIFIED;
+ dic = arr.getAsDict(0);
+ if (dic == null)
+ return PdfSignatureAppearance.NOT_CERTIFIED;
+ dic = dic.getAsDict(PdfName.TRANSFORMPARAMS);
+ if (dic == null)
+ return PdfSignatureAppearance.NOT_CERTIFIED;
+ PdfNumber p = dic.getAsNumber(PdfName.P);
+ if (p == null)
+ return PdfSignatureAppearance.NOT_CERTIFIED;
+ return p.intValue();
+ }
+ */
+
+ /**
+ * Checks if the document was opened with the owner password so that the end application
+ * can decide what level of access restrictions to apply. If the document is not encrypted
+ * it will return true
.
+ * @return true
if the document was opened with the owner password or if it's not encrypted,
+ * false
if the document was opened with the user password
+ */
+ public final boolean isOpenedWithFullPermissions() {
+ return !encrypted || ownerPasswordUsed;
+ }
+
+ public int getCryptoMode() {
+ if (decrypt == null)
+ return -1;
+ else
+ return decrypt.getCryptoMode();
+ }
+
+ public boolean isMetadataEncrypted() {
+ if (decrypt == null)
+ return false;
+ else
+ return decrypt.isMetadataEncrypted();
+ }
+
+ public byte[] computeUserPassword() {
+ if (!encrypted || !ownerPasswordUsed) return null;
+ return decrypt.computeUserPassword(password);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfReaderInstance.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfReaderInstance.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfReaderInstance.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfReaderInstance.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,172 @@
+/*
+ * $Id: PdfReaderInstance.java,v 1.27 2003/05/02 09:01:27 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.io.*;
+/**
+ * Instance of PdfReader in each output document.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+class PdfReaderInstance {
+ static final PdfLiteral IDENTITYMATRIX = new PdfLiteral("[1 0 0 1 0 0]");
+ static final PdfNumber ONE = new PdfNumber(1);
+ int myXref[];
+ PdfReader reader;
+ RandomAccessFileOrArray file;
+ HashMap importedPages = new HashMap();
+ PdfWriter writer;
+ HashMap visited = new HashMap();
+ ArrayList nextRound = new ArrayList();
+
+ PdfReaderInstance(PdfReader reader, PdfWriter writer) {
+ this.reader = reader;
+ this.writer = writer;
+ file = reader.getSafeFile();
+ myXref = new int[reader.getXrefSize()];
+ }
+
+ PdfReader getReader() {
+ return reader;
+ }
+
+ PdfImportedPage getImportedPage(int pageNumber) {
+ if (pageNumber < 1 || pageNumber > reader.getNumberOfPages())
+ throw new IllegalArgumentException("Invalid page number");
+ Integer i = new Integer(pageNumber);
+ PdfImportedPage pageT = (PdfImportedPage)importedPages.get(i);
+ if (pageT == null) {
+ pageT = new PdfImportedPage(this, writer, pageNumber);
+ importedPages.put(i, pageT);
+ }
+ return pageT;
+ }
+
+ int getNewObjectNumber(int number, int generation) {
+ if (myXref[number] == 0) {
+ myXref[number] = writer.getIndirectReferenceNumber();
+ nextRound.add(new Integer(number));
+ }
+ return myXref[number];
+ }
+
+ RandomAccessFileOrArray getReaderFile() {
+ return file;
+ }
+
+ PdfObject getResources(int pageNumber) {
+ PdfObject obj = PdfReader.getPdfObjectRelease(reader.getPageNRelease(pageNumber).get(PdfName.RESOURCES));
+ return obj;
+ }
+
+
+ PdfStream getFormXObject(int pageNumber) throws IOException {
+ PdfDictionary page = reader.getPageNRelease(pageNumber);
+ PdfObject contents = PdfReader.getPdfObjectRelease(page.get(PdfName.CONTENTS));
+ PdfDictionary dic = new PdfDictionary();
+ byte bout[] = null;
+ if (contents != null) {
+ if (contents.isStream())
+ dic.putAll((PRStream)contents);
+ else
+ bout = reader.getPageContent(pageNumber, file);
+ }
+ else
+ bout = new byte[0];
+ dic.put(PdfName.RESOURCES, PdfReader.getPdfObjectRelease(page.get(PdfName.RESOURCES)));
+ dic.put(PdfName.TYPE, PdfName.XOBJECT);
+ dic.put(PdfName.SUBTYPE, PdfName.FORM);
+ PdfImportedPage impPage = (PdfImportedPage)importedPages.get(new Integer(pageNumber));
+ dic.put(PdfName.BBOX, new PdfRectangle(impPage.getBoundingBox()));
+ PdfArray matrix = impPage.getMatrix();
+ if (matrix == null)
+ dic.put(PdfName.MATRIX, IDENTITYMATRIX);
+ else
+ dic.put(PdfName.MATRIX, matrix);
+ dic.put(PdfName.FORMTYPE, ONE);
+ PRStream stream;
+ if (bout == null) {
+ stream = new PRStream((PRStream)contents, dic);
+ }
+ else {
+ stream = new PRStream(reader, bout);
+ stream.putAll(dic);
+ }
+ return stream;
+ }
+
+ void writeAllVisited() throws IOException {
+ while (nextRound.size() > 0) {
+ ArrayList vec = nextRound;
+ nextRound = new ArrayList();
+ for (int k = 0; k < vec.size(); ++k) {
+ Integer i = (Integer)vec.get(k);
+ if (!visited.containsKey(i)) {
+ visited.put(i, null);
+ int n = i.intValue();
+ writer.addToBody(reader.getPdfObjectRelease(n), myXref[n]);
+ }
+ }
+ }
+ }
+
+ void writeAllPages() throws IOException {
+ try {
+ file.reOpen();
+ for (Iterator it = importedPages.values().iterator(); it.hasNext();) {
+ PdfImportedPage ip = (PdfImportedPage)it.next();
+ writer.addToBody(ip.getFormXObject(), ip.getIndirectReference());
+ }
+ writeAllVisited();
+ }
+ finally {
+ try {
+ reader.close();
+ file.close();
+ }
+ catch (Exception e) {
+ //Empty on purpose
+ }
+ }
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfRectangle.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfRectangle.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfRectangle.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfRectangle.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,267 @@
+/*
+ * $Id: PdfRectangle.java,v 1.26 2002/07/09 11:28:24 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.Rectangle;
+
+/**
+ * PdfRectangle
is the PDF Rectangle object.
+ *
+ * Rectangles are used to describe locations on the page and bounding boxes for several
+ * objects in PDF, such as fonts. A rectangle is represented as an array
of
+ * four numbers, specifying the lower lef x , lower left y , upper right x ,
+ * and upper right y coordinates of the rectangle, in that order.
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 7.1 (page 183).
+ *
+ * @see pdftk.com.lowagie.text.Rectangle
+ * @see PdfArray
+ */
+
+public class PdfRectangle extends PdfArray {
+
+ // membervariables
+
+/** lower left x */
+ private float llx = 0;
+
+/** lower left y */
+ private float lly = 0;
+
+/** upper right x */
+ private float urx = 0;
+
+/** upper right y */
+ private float ury = 0;
+
+ // constructors
+
+/**
+ * Constructs a PdfRectangle
-object.
+ *
+ * @param llx lower left x
+ * @param lly lower left y
+ * @param urx upper right x
+ * @param ury upper right y
+ *
+ * @since rugPdf0.10
+ */
+
+ public PdfRectangle(float llx, float lly, float urx, float ury, int rotation) {
+ super();
+ if (rotation == 90 || rotation == 270) {
+ this.llx = lly;
+ this.lly = llx;
+ this.urx = ury;
+ this.ury = urx;
+ }
+ else {
+ this.llx = llx;
+ this.lly = lly;
+ this.urx = urx;
+ this.ury = ury;
+ }
+ super.add(new PdfNumber(this.llx));
+ super.add(new PdfNumber(this.lly));
+ super.add(new PdfNumber(this.urx));
+ super.add(new PdfNumber(this.ury));
+ }
+
+ public PdfRectangle(float llx, float lly, float urx, float ury) {
+ this(llx, lly, urx, ury, 0);
+ }
+
+/**
+ * Constructs a PdfRectangle
-object starting from the origin (0, 0).
+ *
+ * @param urx upper right x
+ * @param ury upper right y
+ */
+
+ public PdfRectangle(float urx, float ury, int rotation) {
+ this(0, 0, urx, ury, rotation);
+ }
+
+ public PdfRectangle(float urx, float ury) {
+ this(0, 0, urx, ury, 0);
+ }
+
+/**
+ * Constructs a PdfRectangle
-object with a Rectangle
-object.
+ *
+ * @param rectangle a Rectangle
+ */
+
+ public PdfRectangle(Rectangle rectangle, int rotation) {
+ this(rectangle.left(), rectangle.bottom(), rectangle.right(), rectangle.top(), rotation);
+ }
+
+ public PdfRectangle(Rectangle rectangle) {
+ this(rectangle.left(), rectangle.bottom(), rectangle.right(), rectangle.top(), 0);
+ }
+
+ // methods
+
+/**
+ * Overrides the add
-method in PdfArray
in order to prevent the adding of extra object to the array.
+ *
+ * @param object PdfObject
to add (will not be added here)
+ * @return false
+ */
+
+ public boolean add(PdfObject object) {
+ return false;
+ }
+
+/**
+ * Returns the lower left x-coordinate.
+ *
+ * @return the lower left x-coordinaat
+ */
+
+ public float left() {
+ return llx;
+ }
+
+/**
+ * Returns the upper right x-coordinate.
+ *
+ * @return the upper right x-coordinate
+ */
+
+ public float right() {
+ return urx;
+ }
+
+/**
+ * Returns the upper right y-coordinate.
+ *
+ * @return the upper right y-coordinate
+ */
+
+ public float top() {
+ return ury;
+ }
+
+/**
+ * Returns the lower left y-coordinate.
+ *
+ * @return the lower left y-coordinate
+ */
+
+ public float bottom() {
+ return lly;
+ }
+
+/**
+ * Returns the lower left x-coordinate, considering a given margin.
+ *
+ * @param margin a margin
+ * @return the lower left x-coordinate
+ */
+
+ public float left(int margin) {
+ return llx + margin;
+ }
+
+/**
+ * Returns the upper right x-coordinate, considering a given margin.
+ *
+ * @param margin a margin
+ * @return the upper right x-coordinate
+ */
+
+ public float right(int margin) {
+ return urx - margin;
+ }
+
+/**
+ * Returns the upper right y-coordinate, considering a given margin.
+ *
+ * @param margin a margin
+ * @return the upper right y-coordinate
+ */
+
+ public float top(int margin) {
+ return ury - margin;
+ }
+
+/**
+ * Returns the lower left y-coordinate, considering a given margin.
+ *
+ * @param margin a margin
+ * @return the lower left y-coordinate
+ */
+
+ public float bottom(int margin) {
+ return lly + margin;
+ }
+
+/**
+ * Returns the width of the rectangle.
+ *
+ * @return a width
+ */
+
+ public float width() {
+ return urx - llx;
+ }
+
+/**
+ * Returns the height of the rectangle.
+ *
+ * @return a height
+ */
+
+ public float height() {
+ return ury - lly;
+ }
+
+/**
+ * Swaps the values of urx and ury and of lly and llx in order to rotate the rectangle.
+ *
+ * @return a PdfRectangle
+ */
+
+ public PdfRectangle rotate() {
+ return new PdfRectangle(lly, llx, ury, urx, 0);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfRendition.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfRendition.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfRendition.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfRendition.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2003 Galo Gimenez
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+
+/**
+ * A Rendition dictionary (pdf spec 1.5)
+ */
+public class PdfRendition extends PdfDictionary {
+ PdfRendition(String file, PdfFileSpecification fs, String mimeType) throws IOException{
+ put(PdfName.S, new PdfName("MR"));
+ put(PdfName.N, new PdfString("Rendition for "+file));
+ put(PdfName.C, new PdfMediaClipData(file, fs, mimeType));
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfResources.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfResources.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfResources.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfResources.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,81 @@
+/*
+ * $Id: PdfResources.java,v 1.22 2002/06/20 13:30:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * PdfResources
is the PDF Resources-object.
+ *
+ * The marking operations for drawing a page are stored in a stream that is the value of the
+ * Contents key in the Page object's dictionary. Each marking context includes a list
+ * of the named resources it uses. This resource list is stored as a dictionary that is the
+ * value of the context's Resources key, and it serves two functions: it enumerates
+ * the named resources in the contents stream, and it established the mapping from the names
+ * to the objects used by the marking operations.
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 7.5 (page 195-197).
+ *
+ * @see PdfPage
+ */
+
+class PdfResources extends PdfDictionary {
+
+ // constructor
+
+/**
+ * Constructs a PDF ResourcesDictionary.
+ */
+
+ PdfResources() {
+ super();
+ }
+
+ // methods
+
+ void add(PdfName key, PdfDictionary resource) {
+ if (resource.size() == 0)
+ return;
+ PdfDictionary dic = (PdfDictionary)PdfReader.getPdfObject(get(key));
+ if (dic == null)
+ put(key, resource);
+ else
+ dic.putAll(resource);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfShading.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfShading.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfShading.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfShading.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,252 @@
+/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.awt.Color;
+import java.io.IOException;
+/** Implements the shading dictionary (or stream).
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfShading {
+
+ protected PdfDictionary shading;
+
+ protected PdfWriter writer;
+
+ protected int shadingType;
+
+ protected ColorDetails colorDetails;
+
+ protected PdfName shadingName;
+
+ protected PdfIndirectReference shadingReference;
+
+ private Color cspace;
+
+ /** Holds value of property bBox. */
+ protected float[] bBox;
+
+ /** Holds value of property antiAlias. */
+ protected boolean antiAlias = false;
+
+ /** Creates new PdfShading */
+ protected PdfShading(PdfWriter writer) {
+ this.writer = writer;
+ }
+
+ protected void setColorSpace(Color color) {
+ cspace = color;
+ int type = ExtendedColor.getType(color);
+ PdfObject colorSpace = null;
+ switch (type) {
+ case ExtendedColor.TYPE_GRAY: {
+ colorSpace = PdfName.DEVICEGRAY;
+ break;
+ }
+ case ExtendedColor.TYPE_CMYK: {
+ colorSpace = PdfName.DEVICECMYK;
+ break;
+ }
+ case ExtendedColor.TYPE_SEPARATION: {
+ SpotColor spot = (SpotColor)color;
+ colorDetails = writer.addSimple(spot.getPdfSpotColor());
+ colorSpace = colorDetails.getIndirectReference();
+ break;
+ }
+ case ExtendedColor.TYPE_PATTERN:
+ case ExtendedColor.TYPE_SHADING: {
+ throwColorSpaceError();
+ }
+ default:
+ colorSpace = PdfName.DEVICERGB;
+ break;
+ }
+ shading.put(PdfName.COLORSPACE, colorSpace);
+ }
+
+ Color getColorSpace() {
+ return cspace;
+ }
+
+ public static void throwColorSpaceError() {
+ throw new IllegalArgumentException("A tiling or shading pattern cannot be used as a color space in a shading pattern");
+ }
+
+ public static void checkCompatibleColors(Color c1, Color c2) {
+ int type1 = ExtendedColor.getType(c1);
+ int type2 = ExtendedColor.getType(c2);
+ if (type1 != type2)
+ throw new IllegalArgumentException("Both colors must be of the same type.");
+ if (type1 == ExtendedColor.TYPE_SEPARATION && ((SpotColor)c1).getPdfSpotColor() != ((SpotColor)c2).getPdfSpotColor())
+ throw new IllegalArgumentException("The spot color must be the same, only the tint can vary.");
+ if (type1 == ExtendedColor.TYPE_PATTERN || type1 == ExtendedColor.TYPE_SHADING)
+ throwColorSpaceError();
+ }
+
+ public static float[] getColorArray(Color color) {
+ int type = ExtendedColor.getType(color);
+ switch (type) {
+ case ExtendedColor.TYPE_GRAY: {
+ return new float[]{((GrayColor)color).getGray()};
+ }
+ case ExtendedColor.TYPE_CMYK: {
+ CMYKColor cmyk = (CMYKColor)color;
+ return new float[]{cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack()};
+ }
+ case ExtendedColor.TYPE_SEPARATION: {
+ return new float[]{((SpotColor)color).getTint()};
+ }
+ case ExtendedColor.TYPE_RGB: {
+ return new float[]{color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f};
+ }
+ }
+ throwColorSpaceError();
+ return null;
+ }
+
+ public static PdfShading type1(PdfWriter writer, Color colorSpace, float domain[], float tMatrix[], PdfFunction function) {
+ PdfShading sp = new PdfShading(writer);
+ sp.shading = new PdfDictionary();
+ sp.shadingType = 1;
+ sp.shading.put(PdfName.SHADINGTYPE, new PdfNumber(sp.shadingType));
+ sp.setColorSpace(colorSpace);
+ if (domain != null)
+ sp.shading.put(PdfName.m_DOMAIN, new PdfArray(domain)); // ssteward
+ if (tMatrix != null)
+ sp.shading.put(PdfName.MATRIX, new PdfArray(tMatrix));
+ sp.shading.put(PdfName.FUNCTION, function.getReference());
+ return sp;
+ }
+
+ public static PdfShading type2(PdfWriter writer, Color colorSpace, float coords[], float domain[], PdfFunction function, boolean extend[]) {
+ PdfShading sp = new PdfShading(writer);
+ sp.shading = new PdfDictionary();
+ sp.shadingType = 2;
+ sp.shading.put(PdfName.SHADINGTYPE, new PdfNumber(sp.shadingType));
+ sp.setColorSpace(colorSpace);
+ sp.shading.put(PdfName.COORDS, new PdfArray(coords));
+ if (domain != null)
+ sp.shading.put(PdfName.m_DOMAIN, new PdfArray(domain)); // ssteward
+ sp.shading.put(PdfName.FUNCTION, function.getReference());
+ if (extend != null && (extend[0] || extend[1])) {
+ PdfArray array = new PdfArray(extend[0] ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
+ array.add(extend[1] ? PdfBoolean.PDFTRUE : PdfBoolean.PDFFALSE);
+ sp.shading.put(PdfName.EXTEND, array);
+ }
+ return sp;
+ }
+
+ public static PdfShading type3(PdfWriter writer, Color colorSpace, float coords[], float domain[], PdfFunction function, boolean extend[]) {
+ PdfShading sp = type2(writer, colorSpace, coords, domain, function, extend);
+ sp.shadingType = 3;
+ sp.shading.put(PdfName.SHADINGTYPE, new PdfNumber(sp.shadingType));
+ return sp;
+ }
+
+ public static PdfShading simpleAxial(PdfWriter writer, float x0, float y0, float x1, float y1, Color startColor, Color endColor, boolean extendStart, boolean extendEnd) {
+ checkCompatibleColors(startColor, endColor);
+ PdfFunction function = PdfFunction.type2(writer, new float[]{0, 1}, null, getColorArray(startColor),
+ getColorArray(endColor), 1);
+ return type2(writer, startColor, new float[]{x0, y0, x1, y1}, null, function, new boolean[]{extendStart, extendEnd});
+ }
+
+ public static PdfShading simpleAxial(PdfWriter writer, float x0, float y0, float x1, float y1, Color startColor, Color endColor) {
+ return simpleAxial(writer, x0, y0, x1, y1, startColor, endColor, true, true);
+ }
+
+ public static PdfShading simpleRadial(PdfWriter writer, float x0, float y0, float r0, float x1, float y1, float r1, Color startColor, Color endColor, boolean extendStart, boolean extendEnd) {
+ checkCompatibleColors(startColor, endColor);
+ PdfFunction function = PdfFunction.type2(writer, new float[]{0, 1}, null, getColorArray(startColor),
+ getColorArray(endColor), 1);
+ return type3(writer, startColor, new float[]{x0, y0, r0, x1, y1, r1}, null, function, new boolean[]{extendStart, extendEnd});
+ }
+
+ public static PdfShading simpleRadial(PdfWriter writer, float x0, float y0, float r0, float x1, float y1, float r1, Color startColor, Color endColor) {
+ return simpleRadial(writer, x0, y0, r0, x1, y1, r1, startColor, endColor, true, true);
+ }
+
+ PdfName getShadingName() {
+ return shadingName;
+ }
+
+ PdfIndirectReference getShadingReference() {
+ if (shadingReference == null)
+ shadingReference = writer.getPdfIndirectReference();
+ return shadingReference;
+ }
+
+ void setName(int number) {
+ shadingName = new PdfName("Sh" + number);
+ }
+
+ void addToBody() throws IOException {
+ if (bBox != null)
+ shading.put(PdfName.BBOX, new PdfArray(bBox));
+ if (antiAlias)
+ shading.put(PdfName.ANTIALIAS, PdfBoolean.PDFTRUE);
+ writer.addToBody(shading, getShadingReference());
+ }
+
+ PdfWriter getWriter() {
+ return writer;
+ }
+
+ ColorDetails getColorDetails() {
+ return colorDetails;
+ }
+
+ public float[] getBBox() {
+ return bBox;
+ }
+
+ public void setBBox(float[] bBox) {
+ if (bBox.length != 4)
+ throw new IllegalArgumentException("BBox must be a 4 element array.");
+ this.bBox = bBox;
+ }
+
+ public boolean isAntiAlias() {
+ return antiAlias;
+ }
+
+ public void setAntiAlias(boolean antiAlias) {
+ this.antiAlias = antiAlias;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfShadingPattern.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfShadingPattern.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfShadingPattern.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfShadingPattern.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+/** Implements the shading pattern dictionary.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfShadingPattern extends PdfDictionary {
+
+ protected PdfShading shading;
+
+ protected PdfWriter writer;
+
+ protected float matrix[] = {1, 0, 0, 1, 0, 0};
+
+ protected PdfName patternName;
+
+ protected PdfIndirectReference patternReference;
+
+ /** Creates new PdfShadingPattern */
+ public PdfShadingPattern(PdfShading shading) {
+ writer = shading.getWriter();
+ put(PdfName.PATTERNTYPE, new PdfNumber(2));
+ this.shading = shading;
+ }
+
+ PdfName getPatternName() {
+ return patternName;
+ }
+
+ PdfName getShadingName() {
+ return shading.getShadingName();
+ }
+
+ PdfIndirectReference getPatternReference() {
+ if (patternReference == null)
+ patternReference = writer.getPdfIndirectReference();
+ return patternReference;
+ }
+
+ PdfIndirectReference getShadingReference() {
+ return shading.getShadingReference();
+ }
+
+ void setName(int number) {
+ patternName = new PdfName("P" + number);
+ }
+
+ void addToBody() throws IOException {
+ put(PdfName.SHADING, getShadingReference());
+ put(PdfName.MATRIX, new PdfArray(matrix));
+ writer.addToBody(this, getPatternReference());
+ }
+
+ public void setMatrix(float matrix[]) {
+ if (matrix.length != 6)
+ throw new RuntimeException("The matrix size must be 6.");
+ this.matrix = matrix;
+ }
+
+ public float[] getMatrix() {
+ return matrix;
+ }
+
+ PdfShading getShading() {
+ return shading;
+ }
+
+ ColorDetails getColorDetails() {
+ return shading.getColorDetails();
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfSigGenericPKCS.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfSigGenericPKCS.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfSigGenericPKCS.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfSigGenericPKCS.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.security.cert.Certificate;
+import java.security.cert.CRL;
+import java.security.PrivateKey;
+import pdftk.com.lowagie.text.ExceptionConverter;
+import java.io.ByteArrayOutputStream;
+
+/**
+ * A signature dictionary representation for the standard filters.
+ */
+public abstract class PdfSigGenericPKCS extends PdfSignature {
+ /**
+ * The hash algorith, for example "SHA1"
+ */
+ protected String hashAlgorithm;
+ /**
+ * The crypto provider
+ */
+ protected String provider = null;
+ /**
+ * The class instance that calculates the PKCS#1 and PKCS#7
+ */
+ protected PdfPKCS7 pkcs;
+ /**
+ * The subject name in the signing certificate (the element "CN")
+ */
+ protected String name;
+
+ private byte externalDigest[];
+ private byte externalRSAdata[];
+ private String digestEncryptionAlgorithm;
+
+ /**
+ * Creates a generic standard filter.
+ * @param filter the filter name
+ * @param subFilter the sub-filter name
+ */
+ public PdfSigGenericPKCS(PdfName filter, PdfName subFilter) {
+ super(filter, subFilter);
+ }
+
+ /**
+ * Sets the crypto information to sign.
+ * @param privKey the private key
+ * @param certChain the certificate chain
+ * @param crlList the certificate revocation list. It can be null
+ */
+ public void setSignInfo(PrivateKey privKey, Certificate[] certChain, CRL[] crlList) {
+ try {
+ pkcs = new PdfPKCS7(privKey, certChain, crlList, hashAlgorithm, provider, PdfName.ADBE_PKCS7_SHA1.equals(get(PdfName.SUBFILTER)));
+ pkcs.setExternalDigest(externalDigest, externalRSAdata, digestEncryptionAlgorithm);
+ if (PdfName.ADBE_X509_RSA_SHA1.equals(get(PdfName.SUBFILTER))) {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ for (int k = 0; k < certChain.length; ++k) {
+ bout.write(certChain[k].getEncoded());
+ }
+ bout.close();
+ setCert(bout.toByteArray());
+ setContents(pkcs.getEncodedPKCS1());
+ }
+ else
+ setContents(pkcs.getEncodedPKCS7());
+ name = PdfPKCS7.getSubjectFields(pkcs.getSigningCertificate()).getField("CN");
+ if (name != null)
+ put(PdfName.NAME, new PdfString(name, PdfObject.TEXT_UNICODE));
+ pkcs = new PdfPKCS7(privKey, certChain, crlList, hashAlgorithm, provider, PdfName.ADBE_PKCS7_SHA1.equals(get(PdfName.SUBFILTER)));
+ pkcs.setExternalDigest(externalDigest, externalRSAdata, digestEncryptionAlgorithm);
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ * Sets the digest/signature to an external calculated value.
+ * @param digest the digest. This is the actual signature
+ * @param RSAdata the extra data that goes into the data tag in PKCS#7
+ * @param digestEncryptionAlgorithm the encryption algorithm. It may must be null
if the digest
+ * is also null
. If the digest
is not null
+ * then it may be "RSA" or "DSA"
+ */
+ public void setExternalDigest(byte digest[], byte RSAdata[], String digestEncryptionAlgorithm) {
+ externalDigest = digest;
+ externalRSAdata = RSAdata;
+ this.digestEncryptionAlgorithm = digestEncryptionAlgorithm;
+ }
+
+ /**
+ * Gets the subject name in the signing certificate (the element "CN")
+ * @return the subject name in the signing certificate (the element "CN")
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets the class instance that does the actual signing.
+ * @return the class instance that does the actual signing
+ */
+ public PdfPKCS7 getSigner() {
+ return pkcs;
+ }
+
+ /**
+ * Gets the signature content. This can be a PKCS#1 or a PKCS#7. It corresponds to
+ * the /Contents key.
+ * @return the signature content
+ */
+ public byte[] getSignerContents() {
+ if (PdfName.ADBE_X509_RSA_SHA1.equals(get(PdfName.SUBFILTER)))
+ return pkcs.getEncodedPKCS1();
+ else
+ return pkcs.getEncodedPKCS7();
+ }
+
+ /**
+ * Creates a standard filter of the type VeriSign.
+ */
+ public static class VeriSign extends PdfSigGenericPKCS {
+ /**
+ * The constructor for the default provider.
+ */
+ public VeriSign() {
+ super(PdfName.VERISIGN_PPKVS, PdfName.ADBE_PKCS7_DETACHED);
+ hashAlgorithm = "MD5";
+ put(PdfName.R, new PdfNumber(65537));
+ }
+
+ /**
+ * The constructor for an explicit provider.
+ * @param provider the crypto provider
+ */
+ public VeriSign(String provider) {
+ this();
+ this.provider = provider;
+ }
+ }
+
+ /**
+ * Creates a standard filter of the type self signed.
+ */
+ public static class PPKLite extends PdfSigGenericPKCS {
+ /**
+ * The constructor for the default provider.
+ */
+ public PPKLite() {
+ super(PdfName.ADOBE_PPKLITE, PdfName.ADBE_X509_RSA_SHA1);
+ hashAlgorithm = "SHA1";
+ put(PdfName.R, new PdfNumber(65541));
+ }
+
+ /**
+ * The constructor for an explicit provider.
+ * @param provider the crypto provider
+ */
+ public PPKLite(String provider) {
+ this();
+ this.provider = provider;
+ }
+ }
+
+ /**
+ * Creates a standard filter of the type Windows Certificate.
+ */
+ public static class PPKMS extends PdfSigGenericPKCS {
+ /**
+ * The constructor for the default provider.
+ */
+ public PPKMS() {
+ super(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_SHA1);
+ hashAlgorithm = "SHA1";
+ }
+
+ /**
+ * The constructor for an explicit provider.
+ * @param provider the crypto provider
+ */
+ public PPKMS(String provider) {
+ this();
+ this.provider = provider;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfSignature.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfSignature.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfSignature.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfSignature.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/** Implements the signature dictionary.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfSignature extends PdfDictionary {
+
+ /** Creates new PdfSignature */
+ public PdfSignature(PdfName filter, PdfName subFilter) {
+ super(PdfName.SIG);
+ put(PdfName.FILTER, filter);
+ put(PdfName.SUBFILTER, subFilter);
+ }
+
+ public void setByteRange(int range[]) {
+ PdfArray array = new PdfArray();
+ for (int k = 0; k < range.length; ++k)
+ array.add(new PdfNumber(range[k]));
+ put(PdfName.BYTERANGE, array);
+ }
+
+ public void setContents(byte contents[]) {
+ put(PdfName.CONTENTS, new PdfString(contents, PdfObject.NOTHING).setHexWriting(true)); // ssteward: added encoding
+ }
+
+ public void setCert(byte cert[]) {
+ put(PdfName.CERT, new PdfString(cert, PdfObject.NOTHING)); // ssteward: added encoding
+ }
+
+ public void setName(String name) {
+ put(PdfName.NAME, new PdfString(name, PdfObject.TEXT_UNICODE));
+ }
+
+ public void setDate(PdfDate date) {
+ put(PdfName.M, date);
+ }
+
+ public void setLocation(String name) {
+ put(PdfName.LOCATION, new PdfString(name, PdfObject.TEXT_UNICODE));
+ }
+
+ public void setReason(String name) {
+ put(PdfName.REASON, new PdfString(name, PdfObject.TEXT_UNICODE));
+ }
+
+ public void setContact(String name) {
+ put(PdfName.CONTACTINFO, new PdfString(name, PdfObject.TEXT_UNICODE));
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfSignatureAppearance.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfSignatureAppearance.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfSignatureAppearance.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfSignatureAppearance.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,1287 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.Rectangle;
+import pdftk.com.lowagie.text.ExceptionConverter;
+import pdftk.com.lowagie.text.Phrase;
+import pdftk.com.lowagie.text.Font;
+import pdftk.com.lowagie.text.Element;
+// import pdftk.com.lowagie.text.Image; ssteward: dropped in 1.44
+import pdftk.com.lowagie.text.DocumentException;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Iterator;
+import java.text.SimpleDateFormat;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.cert.CRL;
+import java.security.PrivateKey;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.io.EOFException;
+import java.io.RandomAccessFile;
+import java.io.File;
+import java.io.InputStream;
+
+/**
+ * This class takes care of the cryptographic options and appearances that form a signature.
+ */
+public class PdfSignatureAppearance {
+
+ /**
+ * The self signed filter.
+ */
+ public static final PdfName SELF_SIGNED = PdfName.ADOBE_PPKLITE;
+ /**
+ * The VeriSign filter.
+ */
+ public static final PdfName VERISIGN_SIGNED = PdfName.VERISIGN_PPKVS;
+ /**
+ * The Windows Certificate Security.
+ */
+ public static final PdfName WINCER_SIGNED = PdfName.ADOBE_PPKMS;
+
+ private static final float topSection = 0.3f;
+ private static final float margin = 2;
+ private Rectangle rect;
+ private Rectangle pageRect;
+ private PdfTemplate app[] = new PdfTemplate[5];
+ private PdfTemplate frm;
+ private PdfStamperImp writer;
+ private String layer2Text;
+ private String reason;
+ private String location;
+ private Calendar signDate;
+ private String provider;
+ private int page = 1;
+ private String fieldName;
+ private PrivateKey privKey;
+ private Certificate[] certChain;
+ private CRL[] crlList;
+ private PdfName filter;
+ private boolean newField;
+ private ByteBuffer sigout;
+ private OutputStream originalout;
+ private File tempFile;
+ private PdfDictionary cryptoDictionary;
+ private PdfStamper stamper;
+ private boolean preClosed = false;
+ private PdfSigGenericPKCS sigStandard;
+ private int range[];
+ private RandomAccessFile raf;
+ private int rangePosition = 0;
+ private byte bout[];
+ private int boutLen;
+ private byte externalDigest[];
+ private byte externalRSAdata[];
+ private String digestEncryptionAlgorithm;
+ private HashMap exclusionLocations;
+
+ PdfSignatureAppearance(PdfStamperImp writer) {
+ this.writer = writer;
+ signDate = new GregorianCalendar();
+ fieldName = getNewSigName();
+ }
+
+ /**
+ * Sets the signature text identifying the signer.
+ * @param text the signature text identifying the signer. If null
or not set
+ * a standard description will be used
+ */
+ public void setLayer2Text(String text) {
+ layer2Text = text;
+ }
+
+ /**
+ * Gets the signature text identifying the signer if set by setLayer2Text().
+ * @return the signature text identifying the signer
+ */
+ public String getLayer2Text() {
+ return layer2Text;
+ }
+
+ /**
+ * Sets the text identifying the signature status.
+ * @param text the text identifying the signature status. If null
or not set
+ * the description "Signature Not Verified" will be used
+ */
+ public void setLayer4Text(String text) {
+ layer4Text = text;
+ }
+
+ /**
+ * Gets the text identifying the signature status if set by setLayer4Text().
+ * @return the text identifying the signature status
+ */
+ public String getLayer4Text() {
+ return layer4Text;
+ }
+
+ /**
+ * Gets the rectangle representing the signature dimensions.
+ * @return the rectangle representing the signature dimensions. It may be null
+ * or have zero width or height for invisible signatures
+ */
+ public Rectangle getRect() {
+ return rect;
+ }
+
+ /**
+ * Gets the visibility status of the signature.
+ * @return the visibility status of the signature
+ */
+ public boolean isInvisible() {
+ return (rect == null || rect.width() == 0 || rect.height() == 0);
+ }
+
+ /**
+ * Sets the cryptographic parameters.
+ * @param privKey the private key
+ * @param certChain the certificate chain
+ * @param crlList the certificate revocation list. It may be null
+ * @param filter the crytographic filter type. It can be SELF_SIGNED, VERISIGN_SIGNED or WINCER_SIGNED
+ */
+ public void setCrypto(PrivateKey privKey, Certificate[] certChain, CRL[] crlList, PdfName filter) {
+ this.privKey = privKey;
+ this.certChain = certChain;
+ this.crlList = crlList;
+ this.filter = filter;
+ }
+
+ /**
+ * Sets the signature to be visible. It creates a new visible signature field.
+ * @param pageRect the position and dimension of the field in the page
+ * @param page the page to place the field. The fist page is 1
+ * @param fieldName the field name or null
to generate automatically a new field name
+ */
+ public void setVisibleSignature(Rectangle pageRect, int page, String fieldName) {
+ if (fieldName != null) {
+ AcroFields af = writer.getAcroFields();
+ AcroFields.Item item = af.getFieldItem(fieldName);
+ if (item != null)
+ throw new IllegalArgumentException("The field " + fieldName + " already exists.");
+ this.fieldName = fieldName;
+ }
+ if (page < 1 || page > writer.reader.getNumberOfPages())
+ throw new IllegalArgumentException("Invalid page number: " + page);
+ this.pageRect = new Rectangle(pageRect);
+ this.pageRect.normalize();
+ rect = new Rectangle(this.pageRect.width(), this.pageRect.height());
+ this.page = page;
+ newField = true;
+ }
+
+ /**
+ * Sets the signature to be visible. An empty signature field with the same name must already exist.
+ * @param fieldName the existing empty signature field name
+ */
+ public void setVisibleSignature(String fieldName) {
+ AcroFields af = writer.getAcroFields();
+ AcroFields.Item item = af.getFieldItem(fieldName);
+ if (item == null)
+ throw new IllegalArgumentException("The field " + fieldName + " does not exist.");
+ PdfDictionary merged = (PdfDictionary)item.merged.get(0);
+ if (!PdfName.SIG.equals(PdfReader.getPdfObject(merged.get(PdfName.FT))))
+ throw new IllegalArgumentException("The field " + fieldName + " is not a signature field.");
+ this.fieldName = fieldName;
+ PdfArray r = (PdfArray)PdfReader.getPdfObject(merged.get(PdfName.RECT));
+ ArrayList ar = r.getArrayList();
+ float llx = ((PdfNumber)PdfReader.getPdfObject((PdfObject)ar.get(0))).floatValue();
+ float lly = ((PdfNumber)PdfReader.getPdfObject((PdfObject)ar.get(1))).floatValue();
+ float urx = ((PdfNumber)PdfReader.getPdfObject((PdfObject)ar.get(2))).floatValue();
+ float ury = ((PdfNumber)PdfReader.getPdfObject((PdfObject)ar.get(3))).floatValue();
+ pageRect = new Rectangle(llx, lly, urx, ury);
+ pageRect.normalize();
+ page = ((Integer)item.page.get(0)).intValue();
+ int rotation = writer.reader.getPageRotation(page);
+ Rectangle pageSize = writer.reader.getPageSizeWithRotation(page);
+ switch (rotation) {
+ case 90:
+ pageRect = new Rectangle(
+ pageRect.bottom(),
+ pageSize.top() - pageRect.left(),
+ pageRect.top(),
+ pageSize.top() - pageRect.right());
+ break;
+ case 180:
+ pageRect = new Rectangle(
+ pageSize.right() - pageRect.left(),
+ pageSize.top() - pageRect.bottom(),
+ pageSize.right() - pageRect.right(),
+ pageSize.top() - pageRect.top());
+ break;
+ case 270:
+ pageRect = new Rectangle(
+ pageSize.right() - pageRect.bottom(),
+ pageRect.left(),
+ pageSize.right() - pageRect.top(),
+ pageRect.right());
+ break;
+ }
+ if (rotation != 0)
+ pageRect.normalize();
+ rect = new Rectangle(this.pageRect.width(), this.pageRect.height());
+ }
+
+ /**
+ * Gets a template layer to create a signature appearance. The layers can go from 0 to 4.
+ *
+ * Consult PPKAppearances.pdf
+ * for further details.
+ * @param layer the layer
+ * @return a template
+ */
+ public PdfTemplate getLayer(int layer) {
+ if (layer < 0 || layer >= app.length)
+ return null;
+ PdfTemplate t = app[layer];
+ if (t == null) {
+ t = app[layer] = new PdfTemplate(writer);
+ t.setBoundingBox(rect);
+ writer.addDirectTemplateSimple(t, new PdfName("n" + layer));
+ }
+ return t;
+ }
+
+ /**
+ * Gets the template that aggregates all appearance layers. This corresponds to the /FRM resource.
+ *
+ * Consult PPKAppearances.pdf
+ * for further details.
+ * @return the template that aggregates all appearance layers
+ */
+ public PdfTemplate getTopLayer() {
+ if (frm == null) {
+ frm = new PdfTemplate(writer);
+ frm.setBoundingBox(rect);
+ writer.addDirectTemplateSimple(frm, new PdfName("FRM"));
+ }
+ return frm;
+ }
+
+ /**
+ * Gets the main appearance layer.
+ *
+ * Consult PPKAppearances.pdf
+ * for further details.
+ * @return the main appearance layer
+ * @throws DocumentException on error
+ * @throws IOException on error
+ */
+ public PdfTemplate getAppearance() throws DocumentException, IOException {
+ if (app[0] == null) {
+ PdfTemplate t = app[0] = new PdfTemplate(writer);
+ t.setBoundingBox(new Rectangle(100, 100));
+ writer.addDirectTemplateSimple(t, new PdfName("n0"));
+ t.setLiteral("% DSBlank\n");
+ }
+ if (app[1] == null && !acro6Layers) {
+ PdfTemplate t = app[1] = new PdfTemplate(writer);
+ t.setBoundingBox(new Rectangle(100, 100));
+ writer.addDirectTemplateSimple(t, new PdfName("n1"));
+ t.setLiteral(questionMark);
+ }
+ if (app[2] == null) {
+ String text;
+ if (layer2Text == null) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("Digitally signed by ").append(PdfPKCS7.getSubjectFields((X509Certificate)certChain[0]).getField("CN")).append("\n");
+ SimpleDateFormat sd = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
+ buf.append("Date: ").append(sd.format(signDate.getTime()));
+ if (reason != null)
+ buf.append("\n").append("Reason: ").append(reason);
+ if (location != null)
+ buf.append("\n").append("Location: ").append(location);
+ text = buf.toString();
+ }
+ else
+ text = layer2Text;
+ PdfTemplate t = app[2] = new PdfTemplate(writer);
+ t.setBoundingBox(rect);
+ writer.addDirectTemplateSimple(t, new PdfName("n2"));
+ /* ssteward: dropped in 1.44
+ if (image != null) {
+ if (imageScale == 0) {
+ t.addImage(image, rect.width(), 0, 0, rect.height(), 0, 0);
+ }
+ else {
+ float usableScale = imageScale;
+ if (imageScale < 0)
+ usableScale = Math.min(rect.width() / image.width(), rect.height() / image.height());
+ float w = image.width() * usableScale;
+ float h = image.height() * usableScale;
+ float x = (rect.width() - w) / 2;
+ float y = (rect.height() - h) / 2;
+ t.addImage(image, w, 0, 0, h, x, y);
+ }
+ }
+ */
+ Font font;
+ if (layer2Font == null)
+ font = new Font();
+ else
+ font = new Font(layer2Font);
+ float size = font.size();
+ if (size <= 0) {
+ Rectangle sr = new Rectangle(rect.width() - 2 * margin, rect.height() * (1 - topSection) - 2 * margin);
+ size = fitText(font, text, sr, 12, runDirection);
+ }
+ ColumnText ct = new ColumnText(t);
+ ct.setRunDirection(runDirection);
+ ct.setSimpleColumn(new Phrase(text, font), margin, 0, rect.width() - margin, rect.height() * (1 - topSection) - margin, size, Element.ALIGN_LEFT);
+ ct.go();
+ }
+ if (app[3] == null && !acro6Layers) {
+ PdfTemplate t = app[3] = new PdfTemplate(writer);
+ t.setBoundingBox(new Rectangle(100, 100));
+ writer.addDirectTemplateSimple(t, new PdfName("n3"));
+ t.setLiteral("% DSBlank\n");
+ }
+ if (app[4] == null && !acro6Layers) {
+ PdfTemplate t = app[4] = new PdfTemplate(writer);
+ t.setBoundingBox(new Rectangle(0, rect.height() * (1 - topSection), rect.right(), rect.top()));
+ writer.addDirectTemplateSimple(t, new PdfName("n4"));
+ Font font;
+ if (layer2Font == null)
+ font = new Font();
+ else
+ font = new Font(layer2Font);
+ float size = font.size();
+ String text = "Signature Not Verified";
+ if (layer4Text != null)
+ text = layer4Text;
+ Rectangle sr = new Rectangle(rect.width() - 2 * margin, rect.height() * topSection - 2 * margin);
+ size = fitText(font, text, sr, 15, runDirection);
+ ColumnText ct = new ColumnText(t);
+ ct.setRunDirection(runDirection);
+ ct.setSimpleColumn(new Phrase(text, font), margin, 0, rect.width() - margin, rect.height() - margin, size, Element.ALIGN_LEFT);
+ ct.go();
+ }
+ int rotation = writer.reader.getPageRotation(page);
+ Rectangle rotated = new Rectangle(rect);
+ int n = rotation;
+ while (n > 0) {
+ rotated = rotated.rotate();
+ n -= 90;
+ }
+ if (frm == null) {
+ frm = new PdfTemplate(writer);
+ frm.setBoundingBox(rotated);
+ writer.addDirectTemplateSimple(frm, new PdfName("FRM"));
+ float scale = Math.min(rect.width(), rect.height()) * 0.9f;
+ float x = (rect.width() - scale) / 2;
+ float y = (rect.height() - scale) / 2;
+ scale /= 100;
+ if (rotation == 90)
+ frm.concatCTM(0, 1, -1, 0, rect.height(), 0);
+ else if (rotation == 180)
+ frm.concatCTM(-1, 0, 0, -1, rect.width(), rect.height());
+ else if (rotation == 270)
+ frm.concatCTM(0, -1, 1, 0, 0, rect.width());
+ frm.addTemplate(app[0], 0, 0);
+ if (!acro6Layers)
+ frm.addTemplate(app[1], scale, 0, 0, scale, x, y);
+ frm.addTemplate(app[2], 0, 0);
+ if (!acro6Layers) {
+ frm.addTemplate(app[3], scale, 0, 0, scale, x, y);
+ frm.addTemplate(app[4], 0, 0);
+ }
+ }
+ PdfTemplate napp = new PdfTemplate(writer);
+ napp.setBoundingBox(rotated);
+ writer.addDirectTemplateSimple(napp, null);
+ napp.addTemplate(frm, 0, 0);
+ return napp;
+ }
+
+ /**
+ * Fits the text to some rectangle adjusting the font size as needed.
+ * @param font the font to use
+ * @param text the text
+ * @param rect the rectangle where the text must fit
+ * @param maxFontSize the maximum font size
+ * @param runDirection the run direction
+ * @return the calculated font size that makes the text fit
+ */
+ public static float fitText(Font font, String text, Rectangle rect, float maxFontSize, int runDirection) {
+ try {
+ ColumnText ct = null;
+ int status = 0;
+ if (maxFontSize <= 0) {
+ int cr = 0;
+ int lf = 0;
+ char t[] = text.toCharArray();
+ for (int k = 0; k < t.length; ++k) {
+ if (t[k] == '\n')
+ ++lf;
+ else if (t[k] == '\r')
+ ++cr;
+ }
+ int minLines = Math.max(cr, lf) + 1;
+ maxFontSize = Math.abs(rect.height()) / minLines - 0.001f;
+ }
+ font.setSize(maxFontSize);
+ Phrase ph = new Phrase(text, font);
+ ct = new ColumnText(null);
+ ct.setSimpleColumn(ph, rect.left(), rect.bottom(), rect.right(), rect.top(), maxFontSize, Element.ALIGN_LEFT);
+ ct.setRunDirection(runDirection);
+ status = ct.go(true);
+ if ((status & ColumnText.NO_MORE_TEXT) != 0)
+ return maxFontSize;
+ float precision = 0.1f;
+ float min = 0;
+ float max = maxFontSize;
+ float size = maxFontSize;
+ for (int k = 0; k < 50; ++k) { //just in case it doesn't converge
+ size = (min + max) / 2;
+ ct = new ColumnText(null);
+ font.setSize(size);
+ ct.setSimpleColumn(new Phrase(text, font), rect.left(), rect.bottom(), rect.right(), rect.top(), size, Element.ALIGN_LEFT);
+ ct.setRunDirection(runDirection);
+ status = ct.go(true);
+ if ((status & ColumnText.NO_MORE_TEXT) != 0) {
+ if (max - min < size * precision)
+ return size;
+ min = size;
+ }
+ else
+ max = size;
+ }
+ return size;
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /**
+ * Sets the digest/signature to an external calculated value.
+ * @param digest the digest. This is the actual signature
+ * @param RSAdata the extra data that goes into the data tag in PKCS#7
+ * @param digestEncryptionAlgorithm the encryption algorithm. It may must be null
if the digest
+ * is also null
. If the digest
is not null
+ * then it may be "RSA" or "DSA"
+ */
+ public void setExternalDigest(byte digest[], byte RSAdata[], String digestEncryptionAlgorithm) {
+ externalDigest = digest;
+ externalRSAdata = RSAdata;
+ this.digestEncryptionAlgorithm = digestEncryptionAlgorithm;
+ }
+
+ /**
+ * Gets the signing reason.
+ * @return the signing reason
+ */
+ public String getReason() {
+ return this.reason;
+ }
+
+ /**
+ * Sets the signing reason.
+ * @param reason the signing reason
+ */
+ public void setReason(String reason) {
+ this.reason = reason;
+ }
+
+ /**
+ * Gets the signing location.
+ * @return the signing location
+ */
+ public String getLocation() {
+ return this.location;
+ }
+
+ /**
+ * Sets the signing location.
+ * @param location the signing location
+ */
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ /**
+ * Returns the Cryptographic Service Provider that will sign the document.
+ * @return provider the name of the provider, for example "SUN",
+ * or null
to use the default provider.
+ */
+ public String getProvider() {
+ return this.provider;
+ }
+
+ /**
+ * Sets the Cryptographic Service Provider that will sign the document.
+ *
+ * @param provider the name of the provider, for example "SUN", or
+ * null
to use the default provider.
+ */
+ public void setProvider(String provider) {
+ this.provider = provider;
+ }
+
+ /**
+ * Gets the private key.
+ * @return the private key
+ */
+ public java.security.PrivateKey getPrivKey() {
+ return privKey;
+ }
+
+ /**
+ * Gets the certificate chain.
+ * @return the certificate chain
+ */
+ public java.security.cert.Certificate[] getCertChain() {
+ return this.certChain;
+ }
+
+ /**
+ * Gets the certificate revocation list.
+ * @return the certificate revocation list
+ */
+ public java.security.cert.CRL[] getCrlList() {
+ return this.crlList;
+ }
+
+ /**
+ * Gets the filter used to sign the document.
+ * @return the filter used to sign the document
+ */
+ public pdftk.com.lowagie.text.pdf.PdfName getFilter() {
+ return filter;
+ }
+
+ /**
+ * Checks if a new field was created.
+ * @return true
if a new field was created, false
if signing
+ * an existing field or if the signature is invisible
+ */
+ public boolean isNewField() {
+ return this.newField;
+ }
+
+ /**
+ * Gets the page number of the field.
+ * @return the page number of the field
+ */
+ public int getPage() {
+ return page;
+ }
+
+ /**
+ * Gets the field name.
+ * @return the field name
+ */
+ public java.lang.String getFieldName() {
+ return fieldName;
+ }
+
+ /**
+ * Gets the rectangle that represent the position and dimension of the signature in the page.
+ * @return the rectangle that represent the position and dimension of the signature in the page
+ */
+ public pdftk.com.lowagie.text.Rectangle getPageRect() {
+ return pageRect;
+ }
+
+ /**
+ * Gets the signature date.
+ * @return the signature date
+ */
+ public java.util.Calendar getSignDate() {
+ return signDate;
+ }
+
+ /**
+ * Sets the signature date.
+ * @param signDate the signature date
+ */
+ public void setSignDate(java.util.Calendar signDate) {
+ this.signDate = signDate;
+ }
+
+ pdftk.com.lowagie.text.pdf.ByteBuffer getSigout() {
+ return sigout;
+ }
+
+ void setSigout(pdftk.com.lowagie.text.pdf.ByteBuffer sigout) {
+ this.sigout = sigout;
+ }
+
+ java.io.OutputStream getOriginalout() {
+ return originalout;
+ }
+
+ void setOriginalout(java.io.OutputStream originalout) {
+ this.originalout = originalout;
+ }
+
+ /**
+ * Gets the temporary file.
+ * @return the temporary file or null
is the document is created in memory
+ */
+ public java.io.File getTempFile() {
+ return tempFile;
+ }
+
+ void setTempFile(java.io.File tempFile) {
+ this.tempFile = tempFile;
+ }
+
+ /**
+ * Gets a new signature fied name that doesn't clash with any existing name.
+ * @return a new signature fied name
+ */
+ public String getNewSigName() {
+ AcroFields af = writer.getAcroFields();
+ String name = "Signature";
+ int step = 0;
+ boolean found = false;
+ while (!found) {
+ ++step;
+ String n1 = name + step;
+ if (af.getFieldItem(n1) != null)
+ continue;
+ n1 += ".";
+ found = true;
+ for (Iterator it = af.getFields().keySet().iterator(); it.hasNext();) {
+ String fn = (String)it.next();
+ if (fn.startsWith(n1)) {
+ found = false;
+ break;
+ }
+ }
+ }
+ name += step;
+ return name;
+ }
+
+ /**
+ * This is the first method to be called when using external signatures. The general sequence is:
+ * preClose(), getDocumentBytes() and close().
+ *
+ * If calling preClose() dont't call PdfStamper.close().
+ *
+ * No external signatures are allowed if this methos is called.
+ * @throws IOException on error
+ * @throws DocumentException on error
+ */
+ public void preClose() throws IOException, DocumentException {
+ preClose(null);
+ }
+ /**
+ * This is the first method to be called when using external signatures. The general sequence is:
+ * preClose(), getDocumentBytes() and close().
+ *
+ * If calling preClose() dont't call PdfStamper.close().
+ *
+ * If using an external signature exclusionSizes
must contain at least
+ * the PdfName.CONTENTS
key with the size that it will take in the
+ * document. Note that due to the hex string coding this size should be
+ * byte_size*2+2.
+ * @param exclusionSizes a HashMap
with names and sizes to be excluded in the signature
+ * calculation. The key is a PdfName
and the value an
+ * Integer
. At least the PdfName.CONTENTS
must be present
+ * @throws IOException on error
+ * @throws DocumentException on error
+ */
+ public void preClose(HashMap exclusionSizes) throws IOException, DocumentException {
+ if (preClosed)
+ throw new DocumentException("Document already pre closed.");
+ preClosed = true;
+ AcroFields af = writer.getAcroFields();
+ String name = getFieldName();
+ boolean fieldExists = !(isInvisible() || isNewField());
+ int flags = 132;
+ if (fieldExists) {
+ flags = 0;
+ ArrayList merged = af.getFieldItem(name).merged;
+ PdfObject obj = PdfReader.getPdfObjectRelease(((PdfDictionary)merged.get(0)).get(PdfName.F));
+ if (obj != null && obj.isNumber())
+ flags = ((PdfNumber)obj).intValue();
+ af.removeField(name);
+ }
+ writer.setSigFlags(3);
+ PdfFormField sigField = PdfFormField.createSignature(writer);
+ sigField.setFieldName(name);
+ PdfIndirectReference refSig = writer.getPdfIndirectReference();
+ sigField.put(PdfName.V, refSig);
+ sigField.setFlags(flags);
+
+ int pagen = getPage();
+ // PdfReader reader = writer.reader;
+ if (!isInvisible()) {
+ sigField.setWidget(getPageRect(), null);
+ sigField.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, getAppearance());
+ }
+ else
+ sigField.setWidget(new Rectangle(0, 0), null);
+ sigField.setPage(pagen);
+ writer.addAnnotation(sigField, pagen);
+
+ exclusionLocations = new HashMap();
+ if (cryptoDictionary == null) {
+ if (PdfName.ADOBE_PPKLITE.equals(getFilter()))
+ sigStandard = new PdfSigGenericPKCS.PPKLite(getProvider());
+ else if (PdfName.ADOBE_PPKMS.equals(getFilter()))
+ sigStandard = new PdfSigGenericPKCS.PPKMS(getProvider());
+ else if (PdfName.VERISIGN_PPKVS.equals(getFilter()))
+ sigStandard = new PdfSigGenericPKCS.VeriSign(getProvider());
+ else
+ throw new IllegalArgumentException("Unknown filter: " + getFilter());
+ sigStandard.setExternalDigest(externalDigest, externalRSAdata, digestEncryptionAlgorithm);
+ if (getReason() != null)
+ sigStandard.setReason(getReason());
+ if (getLocation() != null)
+ sigStandard.setLocation(getLocation());
+ if (getContact() != null)
+ sigStandard.setContact(getContact());
+ sigStandard.put(PdfName.M, new PdfDate(getSignDate()));
+ sigStandard.setSignInfo(getPrivKey(), getCertChain(), getCrlList());
+ PdfString contents = (PdfString)sigStandard.get(PdfName.CONTENTS);
+ PdfLiteral lit = new PdfLiteral((contents.toString().length() + (PdfName.ADOBE_PPKLITE.equals(getFilter())?0:64)) * 2 + 2);
+ exclusionLocations.put(PdfName.CONTENTS, lit);
+ sigStandard.put(PdfName.CONTENTS, lit);
+ lit = new PdfLiteral(80);
+ exclusionLocations.put(PdfName.BYTERANGE, lit);
+ sigStandard.put(PdfName.BYTERANGE, lit);
+ if (signatureEvent != null)
+ signatureEvent.getSignatureDictionary(sigStandard);
+ writer.addToBody(sigStandard, refSig, false);
+ }
+ else {
+ PdfLiteral lit = new PdfLiteral(80);
+ exclusionLocations.put(PdfName.BYTERANGE, lit);
+ cryptoDictionary.put(PdfName.BYTERANGE, lit);
+ for (Iterator it = exclusionSizes.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry)it.next();
+ PdfName key = (PdfName)entry.getKey();
+ Integer v = (Integer)entry.getValue();
+ lit = new PdfLiteral(v.intValue());
+ exclusionLocations.put(key, lit);
+ cryptoDictionary.put(key, lit);
+ }
+ if (signatureEvent != null)
+ signatureEvent.getSignatureDictionary(cryptoDictionary);
+ writer.addToBody(cryptoDictionary, refSig, false);
+ }
+ writer.close(stamper.getMoreInfo());
+
+ range = new int[exclusionLocations.size() * 2];
+ int byteRangePosition = ((PdfLiteral)exclusionLocations.get(PdfName.BYTERANGE)).getPosition();
+ exclusionLocations.remove(PdfName.BYTERANGE);
+ int idx = 1;
+ for (Iterator it = exclusionLocations.values().iterator(); it.hasNext();) {
+ PdfLiteral lit = (PdfLiteral)it.next();
+ int n = lit.getPosition();
+ range[idx++] = n;
+ range[idx++] = lit.getPosLength() + n;
+ }
+ Arrays.sort(range, 1, range.length - 1);
+ for (int k = 3; k < range.length - 2; k += 2)
+ range[k] -= range[k - 1];
+
+ if (tempFile == null) {
+ bout = sigout.getBuffer();
+ boutLen = sigout.size();
+ range[range.length - 1] = boutLen - range[range.length - 2];
+ ByteBuffer bf = new ByteBuffer();
+ bf.append('[');
+ for (int k = 0; k < range.length; ++k)
+ bf.append(range[k]).append(' ');
+ bf.append(']');
+ System.arraycopy(bf.getBuffer(), 0, bout, byteRangePosition, bf.size());
+ }
+ else {
+ try {
+ raf = new RandomAccessFile(tempFile, "rw");
+ int boutLen = (int)raf.length();
+ range[range.length - 1] = boutLen - range[range.length - 2];
+ ByteBuffer bf = new ByteBuffer();
+ bf.append('[');
+ for (int k = 0; k < range.length; ++k)
+ bf.append(range[k]).append(' ');
+ bf.append(']');
+ raf.seek(byteRangePosition);
+ raf.write(bf.getBuffer(), 0, bf.size());
+ }
+ catch (IOException e) {
+ try{raf.close();}catch(Exception ee){}
+ try{tempFile.delete();}catch(Exception ee){}
+ throw e;
+ }
+ }
+ }
+
+ /**
+ * This is the last method to be called when using external signatures. The general sequence is:
+ * preClose(), getDocumentBytes() and close().
+ *
+ * update
is a PdfDictionary
that must have exactly the
+ * same keys as the ones provided in {@link #preClose(HashMap)}.
+ * @param update a PdfDictionary
with the key/value that will fill the holes defined
+ * in {@link #preClose(HashMap)}
+ * @throws DocumentException on error
+ * @throws IOException on error
+ */
+ public void close(PdfDictionary update) throws IOException, DocumentException {
+ try {
+ if (!preClosed)
+ throw new DocumentException("preClose() must be called first.");
+ ByteBuffer bf = new ByteBuffer();
+ for (Iterator it = update.getKeys().iterator(); it.hasNext();) {
+ PdfName key = (PdfName)it.next();
+ PdfObject obj = update.get(key);
+ PdfLiteral lit = (PdfLiteral)exclusionLocations.get(key);
+ if (lit == null)
+ throw new IllegalArgumentException("The key " + key.toString() + " didn't reserve space in preClose().");
+ bf.reset();
+ obj.toPdf(null, bf);
+ if (bf.size() > lit.getPosLength())
+ throw new IllegalArgumentException("The key " + key.toString() + " is too big. Is " + bf.size() + ", reserved " + lit.getPosLength());
+ if (tempFile == null)
+ System.arraycopy(bf.getBuffer(), 0, bout, lit.getPosition(), bf.size());
+ else {
+ raf.seek(lit.getPosition());
+ raf.write(bf.getBuffer(), 0, bf.size());
+ }
+ }
+ if (update.size() != exclusionLocations.size())
+ throw new IllegalArgumentException("The update dictionary has less keys than required.");
+ if (tempFile == null) {
+ originalout.write(bout, 0, boutLen);
+ }
+ else {
+ if (originalout != null) {
+ raf.seek(0);
+ int length = (int)raf.length();
+ byte buf[] = new byte[8192];
+ while (length > 0) {
+ int r = raf.read(buf, 0, Math.min(buf.length, length));
+ if (r < 0)
+ throw new EOFException("Unexpected EOF");
+ originalout.write(buf, 0, r);
+ length -= r;
+ }
+ }
+ }
+ }
+ finally {
+ if (tempFile != null) {
+ try{raf.close();}catch(Exception ee){}
+ if (originalout != null)
+ try{tempFile.delete();}catch(Exception ee){}
+ }
+ if (originalout != null)
+ try{originalout.close();}catch(Exception e){}
+ }
+ }
+
+ private static int indexArray(byte bout[], int position, String search) {
+ byte ss[] = PdfEncodings.convertToBytes(search, null);
+ while (true) {
+ int k;
+ for (k = 0; k < ss.length; ++k) {
+ if (ss[k] != bout[position + k])
+ break;
+ }
+ if (k == ss.length)
+ return position;
+ ++position;
+ }
+ }
+
+ private static int indexFile(RandomAccessFile raf, int position, String search) throws IOException {
+ byte ss[] = PdfEncodings.convertToBytes(search, null);
+ while (true) {
+ raf.seek(position);
+ int k;
+ for (k = 0; k < ss.length; ++k) {
+ int b = raf.read();
+ if (b < 0)
+ throw new EOFException("Unexpected EOF");
+ if (ss[k] != (byte)b)
+ break;
+ }
+ if (k == ss.length)
+ return position;
+ ++position;
+ }
+ }
+
+ /**
+ * Gets the document bytes that are hashable when using external signatures. The general sequence is:
+ * preClose(), getRangeStream() and close().
+ *
+ * @return the document bytes that are hashable
+ */
+ public InputStream getRangeStream() {
+ return new PdfSignatureAppearance.RangeStream(raf, bout, range);
+ }
+
+ /**
+ * Gets the user made signature dictionary. This is the dictionary at the /V key.
+ * @return the user made signature dictionary
+ */
+ public pdftk.com.lowagie.text.pdf.PdfDictionary getCryptoDictionary() {
+ return cryptoDictionary;
+ }
+
+ /**
+ * Sets a user made signature dictionary. This is the dictionary at the /V key.
+ * @param cryptoDictionary a user made signature dictionary
+ */
+ public void setCryptoDictionary(pdftk.com.lowagie.text.pdf.PdfDictionary cryptoDictionary) {
+ this.cryptoDictionary = cryptoDictionary;
+ }
+
+ /**
+ * Gets the PdfStamper
associated with this instance.
+ * @return the PdfStamper
associated with this instance
+ */
+ public pdftk.com.lowagie.text.pdf.PdfStamper getStamper() {
+ return stamper;
+ }
+
+ void setStamper(pdftk.com.lowagie.text.pdf.PdfStamper stamper) {
+ this.stamper = stamper;
+ }
+
+ /**
+ * Checks if the document is in the process of closing.
+ * @return true
if the document is in the process of closing,
+ * false
otherwise
+ */
+ public boolean isPreClosed() {
+ return preClosed;
+ }
+
+ /**
+ * Gets the instance of the standard signature dictionary. This instance
+ * is only available after pre close.
+ *
+ * The main use is to insert external signatures.
+ * @return the instance of the standard signature dictionary
+ */
+ public pdftk.com.lowagie.text.pdf.PdfSigGenericPKCS getSigStandard() {
+ return sigStandard;
+ }
+
+ /**
+ * Gets the signing contact.
+ * @return the signing contact
+ */
+ public String getContact() {
+ return this.contact;
+ }
+
+ /**
+ * Sets the signing contact.
+ * @param contact the signing contact
+ */
+ public void setContact(String contact) {
+ this.contact = contact;
+ }
+
+ /**
+ * Gets the n2 and n4 layer font.
+ * @return the n2 and n4 layer font
+ */
+ public Font getLayer2Font() {
+ return this.layer2Font;
+ }
+
+ /**
+ * Sets the n2 and n4 layer font. If the font size is zero, auto-fit will be used.
+ * @param layer2Font the n2 and n4 font
+ */
+ public void setLayer2Font(Font layer2Font) {
+ this.layer2Font = layer2Font;
+ }
+
+ /**
+ * Gets the Acrobat 6.0 layer mode.
+ * @return the Acrobat 6.0 layer mode
+ */
+ public boolean isAcro6Layers() {
+ return this.acro6Layers;
+ }
+
+ /**
+ * Acrobat 6.0 and higher recomends that only layer n2 and n4 be present. This method sets that mode.
+ * @param acro6Layers if true
only the layers n2 and n4 will be present
+ */
+ public void setAcro6Layers(boolean acro6Layers) {
+ this.acro6Layers = acro6Layers;
+ }
+
+ /** Sets the run direction in the n2 and n4 layer.
+ * @param runDirection the run direction
+ */
+ public void setRunDirection(int runDirection) {
+ if (runDirection < PdfWriter.RUN_DIRECTION_DEFAULT || runDirection > PdfWriter.RUN_DIRECTION_RTL)
+ throw new RuntimeException("Invalid run direction: " + runDirection);
+ this.runDirection = runDirection;
+ }
+
+ /** Gets the run direction.
+ * @return the run direction
+ */
+ public int getRunDirection() {
+ return runDirection;
+ }
+
+ /**
+ * Getter for property signatureEvent.
+ * @return Value of property signatureEvent.
+ */
+ public SignatureEvent getSignatureEvent() {
+ return this.signatureEvent;
+ }
+
+ /**
+ * Sets the signature event to allow modification of the signature dictionary.
+ * @param signatureEvent the signature event
+ */
+ public void setSignatureEvent(SignatureEvent signatureEvent) {
+ this.signatureEvent = signatureEvent;
+ }
+
+ /**
+ * Gets the background image for the layer 2.
+ * @return the background image for the layer 2
+ */
+ /* ssteward: dropped in 1.44
+ public Image getImage() {
+ return this.image;
+ }
+ */
+
+ /**
+ * Sets the background image for the layer 2.
+ * @param image the background image for the layer 2
+ */
+ /* ssteward: dropped in 1.44
+ public void setImage(Image image) {
+ this.image = image;
+ }
+ */
+
+ /**
+ * Gets the scaling to be applied to the background image.
+ * @return the scaling to be applied to the background image
+ */
+ public float getImageScale() {
+ return this.imageScale;
+ }
+
+ /**
+ * Sets the scaling to be applied to the background image. If it's zero the image
+ * will fully fill the rectangle. If it's less than zero the image will fill the rectangle but
+ * will keep the proportions. If it's greater than zero that scaling will be applied.
+ * In any of the cases the image will always be centered. It's zero by default.
+ * @param imageScale the scaling to be applied to the background image
+ */
+ public void setImageScale(float imageScale) {
+ this.imageScale = imageScale;
+ }
+
+ /**
+ * Commands to draw a yellow question mark in a stream content
+ */
+ public static final String questionMark =
+ "% DSUnknown\n" +
+ "q\n" +
+ "1 G\n" +
+ "1 g\n" +
+ "0.1 0 0 0.1 9 0 cm\n" +
+ "0 J 0 j 4 M []0 d\n" +
+ "1 i \n" +
+ "0 g\n" +
+ "313 292 m\n" +
+ "313 404 325 453 432 529 c\n" +
+ "478 561 504 597 504 645 c\n" +
+ "504 736 440 760 391 760 c\n" +
+ "286 760 271 681 265 626 c\n" +
+ "265 625 l\n" +
+ "100 625 l\n" +
+ "100 828 253 898 381 898 c\n" +
+ "451 898 679 878 679 650 c\n" +
+ "679 555 628 499 538 435 c\n" +
+ "488 399 467 376 467 292 c\n" +
+ "313 292 l\n" +
+ "h\n" +
+ "308 214 170 -164 re\n" +
+ "f\n" +
+ "0.44 G\n" +
+ "1.2 w\n" +
+ "1 1 0.4 rg\n" +
+ "287 318 m\n" +
+ "287 430 299 479 406 555 c\n" +
+ "451 587 478 623 478 671 c\n" +
+ "478 762 414 786 365 786 c\n" +
+ "260 786 245 707 239 652 c\n" +
+ "239 651 l\n" +
+ "74 651 l\n" +
+ "74 854 227 924 355 924 c\n" +
+ "425 924 653 904 653 676 c\n" +
+ "653 581 602 525 512 461 c\n" +
+ "462 425 441 402 441 318 c\n" +
+ "287 318 l\n" +
+ "h\n" +
+ "282 240 170 -164 re\n" +
+ "B\n" +
+ "Q\n";
+
+ /**
+ * Holds value of property contact.
+ */
+ private String contact;
+
+ /**
+ * Holds value of property layer2Font.
+ */
+ private Font layer2Font;
+
+ /**
+ * Holds value of property layer4Text.
+ */
+ private String layer4Text;
+
+ /**
+ * Holds value of property acro6Layers.
+ */
+ private boolean acro6Layers;
+
+ /**
+ * Holds value of property runDirection.
+ */
+ private int runDirection = PdfWriter.RUN_DIRECTION_NO_BIDI;
+
+ /**
+ * Holds value of property signatureEvent.
+ */
+ private SignatureEvent signatureEvent;
+
+ /**
+ * Holds value of property image.
+ */
+ // private Image image; ssteward: dropped in 1.44
+
+ /**
+ * Holds value of property imageScale.
+ */
+ private float imageScale;
+
+ /**
+ *
+ */
+ private static class RangeStream extends InputStream {
+ private byte b[] = new byte[1];
+ private RandomAccessFile raf;
+ private byte bout[];
+ private int range[];
+ private int rangePosition = 0;
+
+ private RangeStream(RandomAccessFile raf, byte bout[], int range[]) {
+ this.raf = raf;
+ this.bout = bout;
+ this.range = range;
+ }
+
+ /**
+ * @see java.io.InputStream#read()
+ */
+ public int read() throws IOException {
+ int n = read(b);
+ if (n != 1)
+ return -1;
+ return b[0] & 0xff;
+ }
+
+ /**
+ * @see java.io.InputStream#read(byte[], int, int)
+ */
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) > b.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+ if (rangePosition >= range[range.length - 2] + range[range.length - 1]) {
+ return -1;
+ }
+ for (int k = 0; k < range.length; k += 2) {
+ int start = range[k];
+ int end = start + range[k + 1];
+ if (rangePosition < start)
+ rangePosition = start;
+ if (rangePosition >= start && rangePosition < end) {
+ int lenf = Math.min(len, end - rangePosition);
+ if (raf == null)
+ System.arraycopy(bout, rangePosition, b, off, lenf);
+ else {
+ raf.seek(rangePosition);
+ raf.readFully(b, off, lenf);
+ }
+ rangePosition += lenf;
+ return lenf;
+ }
+ }
+ return -1;
+ }
+ }
+
+ /**
+ * An interface to retrieve the signature dictionary for modification.
+ */
+ public interface SignatureEvent {
+ /**
+ * Allows modification of the signature dictionary.
+ * @param sig the signature dictionary
+ */
+ public void getSignatureDictionary(PdfDictionary sig);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfSpotColor.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfSpotColor.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfSpotColor.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfSpotColor.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,132 @@
+/*
+ * $Id: PdfSpotColor.java,v 1.45 2005/03/24 12:38:19 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.awt.Color;
+import java.io.IOException;
+/**
+ * A PdfSpotColor
defines a ColorSpace
+ *
+ * @see PdfDictionary
+ */
+
+public class PdfSpotColor{
+
+/* The tint value */
+ protected float tint;
+
+/** The color name */
+ public PdfName name;
+
+/** The alternative color space */
+ public Color altcs;
+ // constructors
+
+ /**
+ * Constructs a new PdfSpotColor
.
+ *
+ * @param name a String value
+ * @param tint a tint value between 0 and 1
+ * @param altcs a altnative colorspace value
+ */
+
+ public PdfSpotColor(String name, float tint, Color altcs) {
+ this.name = new PdfName(name);
+ this.tint = tint;
+ this.altcs = altcs;
+ }
+
+ /**
+ * Gets the tint of the SpotColor.
+ * @return a float
+ */
+ public float getTint() {
+ return tint;
+ }
+
+ /**
+ * Gets the alternative ColorSpace.
+ * @return a Colot
+ */
+ public Color getAlternativeCS() {
+ return altcs;
+ }
+
+ protected PdfObject getSpotObject(PdfWriter writer) throws IOException {
+ PdfArray array = new PdfArray(PdfName.SEPARATION);
+ array.add(name);
+ PdfFunction func = null;
+ if (altcs instanceof ExtendedColor) {
+ int type = ((ExtendedColor)altcs).type;
+
+ // ssteward
+ // having trouble with unreachable bytecode in switch default (per gcj 4.4)
+ // so try a clumsier workaround
+ boolean handled_b= false;
+ switch (type) {
+ case ExtendedColor.TYPE_GRAY:
+ array.add(PdfName.DEVICEGRAY);
+ func = PdfFunction.type2(writer, new float[]{0, 1}, null, new float[]{0}, new float[]{((GrayColor)altcs).getGray()}, 1);
+ handled_b= true;
+ break;
+ case ExtendedColor.TYPE_CMYK:
+ array.add(PdfName.DEVICECMYK);
+ CMYKColor cmyk = (CMYKColor)altcs;
+ func = PdfFunction.type2(writer, new float[]{0, 1}, null, new float[]{0, 0, 0, 0},
+ new float[]{cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack()}, 1);
+ handled_b= true;
+ break;
+// default:
+// throw new RuntimeException("Only RGB, Gray and CMYK are supported as alternative color spaces.");
+ }
+ if( !handled_b ) {
+ throw new RuntimeException("Only RGB, Gray and CMYK are supported as alternative color spaces.");
+ }
+ }
+ else {
+ array.add(PdfName.DEVICERGB);
+ func = PdfFunction.type2(writer, new float[]{0, 1}, null, new float[]{1, 1, 1},
+ new float[]{(float)altcs.getRed() / 255, (float)altcs.getGreen() / 255, (float)altcs.getBlue() / 255}, 1);
+ }
+ array.add(func.getReference());
+ return array;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfStamper.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfStamper.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfStamper.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfStamper.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,663 @@
+/*
+ * Copyright 2003, 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.security.SignatureException;
+import java.io.OutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.EOFException;
+import java.io.RandomAccessFile;
+import java.io.File;
+import java.io.InputStream;
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.ExceptionConverter;
+import pdftk.com.lowagie.text.DocWriter;
+import pdftk.com.lowagie.text.Rectangle;
+// import pdftk.com.lowagie.text.Image; ssteward: dropped in 1.44
+import java.util.HashMap;
+import java.util.List;
+import java.util.Iterator;
+
+/** Applies extra content to the pages of a PDF document.
+ * This extra content can be all the objects allowed in PdfContentByte
+ * including pages from other Pdfs. The original PDF will keep
+ * all the interactive elements including bookmarks, links and form fields.
+ *
+ * It is also possible to change the field values and to
+ * flatten them. New fields can be added but not flattened.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfStamper {
+ /**
+ * The writer
+ */
+ protected PdfStamperImp stamper;
+ private HashMap moreInfo;
+ private boolean hasSignature;
+ private PdfSignatureAppearance sigApp;
+
+ /** Starts the process of adding extra content to an existing PDF
+ * document.
+ * @param reader the original document. It cannot be reused
+ * @param os the output stream
+ * @throws DocumentException on error
+ * @throws IOException on error
+ */
+ public PdfStamper(PdfReader reader, OutputStream os) throws DocumentException, IOException {
+ stamper = new PdfStamperImp(reader, os, '\0', false);
+ }
+
+ /**
+ * Starts the process of adding extra content to an existing PDF
+ * document.
+ * @param reader the original document. It cannot be reused
+ * @param os the output stream
+ * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
+ * document
+ * @throws DocumentException on error
+ * @throws IOException on error
+ */
+ public PdfStamper(PdfReader reader, OutputStream os, char pdfVersion) throws DocumentException, IOException {
+ stamper = new PdfStamperImp(reader, os, pdfVersion, false);
+ }
+
+ /**
+ * Starts the process of adding extra content to an existing PDF
+ * document, possibly as a new revision.
+ * @param reader the original document. It cannot be reused
+ * @param os the output stream
+ * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
+ * document
+ * @param append if true
appends the document changes as a new revision. This is
+ * only useful for multiple signatures as nothing is gained in speed or memory
+ * @throws DocumentException on error
+ * @throws IOException on error
+ */
+ public PdfStamper(PdfReader reader, OutputStream os, char pdfVersion, boolean append) throws DocumentException, IOException {
+ stamper = new PdfStamperImp(reader, os, pdfVersion, append);
+ }
+
+ /** Gets the optional String
map to add or change values in
+ * the info dictionary.
+ * @return the map or null
+ *
+ */
+ public HashMap getMoreInfo() {
+ return this.moreInfo;
+ }
+
+ /** An optional String
map to add or change values in
+ * the info dictionary. Entries with null
+ * values delete the key in the original info dictionary
+ * @param moreInfo additional entries to the info dictionary
+ *
+ */
+ public void setMoreInfo(HashMap moreInfo) {
+ this.moreInfo = moreInfo;
+ }
+
+ /**
+ * Inserts a blank page. All the pages above and including pageNumber
will
+ * be shifted up. If pageNumber
is bigger than the total number of pages
+ * the new page will be the last one.
+ * @param pageNumber the page number position where the new page will be inserted
+ * @param mediabox the size of the new page
+ */
+ public void insertPage(int pageNumber, Rectangle mediabox) {
+ stamper.insertPage(pageNumber, mediabox);
+ }
+
+ /**
+ * Gets the signing instance. The appearances and other parameters can the be set.
+ * @return the signing instance
+ */
+ public PdfSignatureAppearance getSignatureAppearance() {
+ return sigApp;
+ }
+
+ private String getNewSigName() {
+ AcroFields af = getAcroFields();
+ String name = "Signature";
+ int step = 0;
+ boolean found = false;
+ while (!found) {
+ ++step;
+ String n1 = name + step;
+ if (af.getFieldItem(n1) != null)
+ continue;
+ n1 += ".";
+ found = true;
+ for (Iterator it = af.getFields().keySet().iterator(); it.hasNext();) {
+ String fn = (String)it.next();
+ if (fn.startsWith(n1)) {
+ found = false;
+ break;
+ }
+ }
+ }
+ name += step;
+ return name;
+ }
+ /**
+ * Closes the document. No more content can be written after the
+ * document is closed.
+ *
+ * If closing a signed document with an external signature the closing must be done
+ * in the PdfSignatureAppearance
instance.
+ * @throws DocumentException on error
+ * @throws IOException on error
+ */
+ public void close() throws DocumentException, IOException {
+ if (!hasSignature) {
+ stamper.close(moreInfo);
+ return;
+ }
+ sigApp.preClose();
+ PdfSigGenericPKCS sig = sigApp.getSigStandard();
+ PdfLiteral lit = (PdfLiteral)sig.get(PdfName.CONTENTS);
+ int totalBuf = (lit.getPosLength() - 2) / 2;
+ byte buf[] = new byte[8192];
+ int n;
+ InputStream inp = sigApp.getRangeStream();
+ try {
+ while ((n = inp.read(buf)) > 0) {
+ sig.getSigner().update(buf, 0, n);
+ }
+ }
+ catch (SignatureException se) {
+ throw new ExceptionConverter(se);
+ }
+ buf = new byte[totalBuf];
+ byte[] bsig = sig.getSignerContents();
+ System.arraycopy(bsig, 0, buf, 0, bsig.length);
+ PdfString str = new PdfString(buf);
+ str.setHexWriting(true);
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.CONTENTS, str);
+ sigApp.close(dic);
+ stamper.reader.close();
+ }
+
+ private static int indexArray(byte bout[], int position, String search) {
+ byte ss[] = PdfEncodings.convertToBytes(search, null);
+ while (true) {
+ int k;
+ for (k = 0; k < ss.length; ++k) {
+ if (ss[k] != bout[position + k])
+ break;
+ }
+ if (k == ss.length)
+ return position;
+ ++position;
+ }
+ }
+
+ private static int indexFile(RandomAccessFile raf, int position, String search) throws IOException {
+ byte ss[] = PdfEncodings.convertToBytes(search, null);
+ while (true) {
+ raf.seek(position);
+ int k;
+ for (k = 0; k < ss.length; ++k) {
+ int b = raf.read();
+ if (b < 0)
+ throw new EOFException("Unexpected EOF");
+ if (ss[k] != (byte)b)
+ break;
+ }
+ if (k == ss.length)
+ return position;
+ ++position;
+ }
+ }
+
+ /** Gets a PdfContentByte
to write under the page of
+ * the original document.
+ * @param pageNum the page number where the extra content is written
+ * @return a PdfContentByte
to write under the page of
+ * the original document
+ */
+ public PdfContentByte getUnderContent(int pageNum) {
+ return stamper.getUnderContent(pageNum);
+ }
+
+ /** Gets a PdfContentByte
to write over the page of
+ * the original document.
+ * @param pageNum the page number where the extra content is written
+ * @return a PdfContentByte
to write over the page of
+ * the original document
+ */
+ public PdfContentByte getOverContent(int pageNum) {
+ return stamper.getOverContent(pageNum);
+ }
+
+ /** Checks if the content is automatically adjusted to compensate
+ * the original page rotation.
+ * @return the auto-rotation status
+ */
+ public boolean isRotateContents() {
+ return stamper.isRotateContents();
+ }
+
+ /** Flags the content to be automatically adjusted to compensate
+ * the original page rotation. The default is true
.
+ * @param rotateContents true
to set auto-rotation, false
+ * otherwise
+ */
+ public void setRotateContents(boolean rotateContents) {
+ stamper.setRotateContents(rotateContents);
+ }
+
+ /** Sets the encryption options for this document. The userPassword and the
+ * ownerPassword can be null or have zero length. In this case the ownerPassword
+ * is replaced by a random string. The open permissions for the document can be
+ * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
+ * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
+ * The permissions can be combined by ORing them.
+ * @param userPassword the user password. Can be null or empty
+ * @param ownerPassword the owner password. Can be null or empty
+ * @param permissions the user permissions
+ * @param strength128Bits true
for 128 bit key length, false
for 40 bit key length
+ * @throws DocumentException if anything was already written to the output
+ */
+ // legacy
+ public void setEncryption(byte userPassword[], byte ownerPassword[], int permissions, boolean strength128Bits) throws DocumentException {
+ if (stamper.isAppend())
+ throw new DocumentException("Append mode does not support changing the encryption status.");
+ if (stamper.isContentWritten())
+ throw new DocumentException("Content was already written to the output.");
+ stamper.setEncryption(userPassword, ownerPassword, permissions, strength128Bits ? PdfWriter.STANDARD_ENCRYPTION_128 : PdfWriter.STANDARD_ENCRYPTION_40);
+ }
+
+ /** Sets the encryption options for this document. The userPassword and the
+ * ownerPassword can be null or have zero length. In this case the ownerPassword
+ * is replaced by a random string. The open permissions for the document can be
+ * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
+ * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
+ * The permissions can be combined by ORing them.
+ * @param userPassword the user password. Can be null or empty
+ * @param ownerPassword the owner password. Can be null or empty
+ * @param permissions the user permissions
+ * @param encryptionType the type of encryption. It can be one of STANDARD_ENCRYPTION_40, STANDARD_ENCRYPTION_128 or ENCRYPTION_AES128.
+ * Optionally DO_NOT_ENCRYPT_METADATA can be ored to output the metadata in cleartext
+ * @throws DocumentException if the document is already open
+ */
+ // preferred
+ public void setEncryption(byte userPassword[], byte ownerPassword[], int permissions, int encryptionType) throws DocumentException {
+ if (stamper.isAppend())
+ throw new DocumentException("Append mode does not support changing the encryption status.");
+ if (stamper.isContentWritten())
+ throw new DocumentException("Content was already written to the output.");
+ stamper.setEncryption(userPassword, ownerPassword, permissions, encryptionType);
+ }
+
+ /**
+ * Sets the encryption options for this document. The userPassword and the
+ * ownerPassword can be null or have zero length. In this case the ownerPassword
+ * is replaced by a random string. The open permissions for the document can be
+ * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
+ * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
+ * The permissions can be combined by ORing them.
+ * @param strength true
for 128 bit key length, false
for 40 bit key length
+ * @param userPassword the user password. Can be null or empty
+ * @param ownerPassword the owner password. Can be null or empty
+ * @param permissions the user permissions
+ * @throws DocumentException if anything was already written to the output
+ */
+ /*
+ public void setEncryption(boolean strength, String userPassword, String ownerPassword, int permissions) throws DocumentException {
+ setEncryption(DocWriter.getISOBytes(userPassword), DocWriter.getISOBytes(ownerPassword), permissions, strength);
+ }
+ */
+
+ /** Gets a page from other PDF document. Note that calling this method more than
+ * once with the same parameters will retrieve the same object.
+ * @param reader the PDF document where the page is
+ * @param pageNumber the page number. The first page is 1
+ * @return the template representing the imported page
+ */
+ public PdfImportedPage getImportedPage(PdfReader reader, int pageNumber) {
+ return stamper.getImportedPage(reader, pageNumber);
+ }
+
+ /** Gets the underlying PdfWriter.
+ * @return the underlying PdfWriter
+ */
+ public PdfWriter getWriter() {
+ return stamper;
+ }
+
+ /** Gets the underlying PdfReader.
+ * @return the underlying PdfReader
+ */
+ public PdfReader getReader() {
+ return stamper.reader;
+ }
+
+ /** Gets the AcroFields
object that allows to get and set field values
+ * and to merge FDF forms.
+ * @return the AcroFields
object
+ */
+ public AcroFields getAcroFields() {
+ return stamper.getAcroFields();
+ }
+
+ /** Determines if the fields are flattened on close. The fields added with
+ * {@link #addAnnotation(PdfAnnotation,int)} will never be flattened.
+ * @param flat true
to flatten the fields, false
+ * to keep the fields
+ */
+ public void setFormFlattening(boolean flat) {
+ stamper.setFormFlattening(flat);
+ }
+
+ /** Determines if the FreeText annotations are flattened on close.
+ * @param flat true
to flatten the FreeText annotations, false
+ * (the default) to keep the FreeText annotations as active content.
+ */
+ public void setFreeTextFlattening(boolean flat) {
+ stamper.setFreeTextFlattening(flat);
+ }
+
+ /**
+ * Adds an annotation of form field in a specific page. This page number
+ * can be overridden with {@link PdfAnnotation#setPlaceInPage(int)}.
+ * @param annot the annotation
+ * @param page the page
+ */
+ public void addAnnotation(PdfAnnotation annot, int page) {
+ stamper.addAnnotation(annot, page);
+ }
+
+ /**
+ * Adds the comments present in an FDF file.
+ * @param fdf the FDF file
+ * @throws IOException on error
+ */
+ public void addComments(FdfReader fdf) throws IOException {
+ stamper.addComments(fdf);
+ }
+
+ /**
+ * Sets the bookmarks. The list structure is defined in
+ * {@link SimpleBookmark}.
+ * @param outlines the bookmarks or null
to remove any
+ * @throws IOException on error
+ */
+ public void setOutlines(List outlines) throws IOException {
+ stamper.setOutlines(outlines);
+ }
+
+ /**
+ * Sets the thumbnail image for a page.
+ * @param image the image
+ * @param page the page
+ * @throws PdfException on error
+ * @throws DocumentException on error
+ */
+ /*
+ public void setThumbnail(Image image, int page) throws PdfException, DocumentException {
+ stamper.setThumbnail(image, page);
+ }
+ */
+
+ /**
+ * Adds name
to the list of fields that will be flattened on close,
+ * all the other fields will remain. If this method is never called or is called
+ * with invalid field names, all the fields will be flattened.
+ *
+ * Calling setFormFlattening(true)
is needed to have any kind of
+ * flattening.
+ * @param name the field name
+ * @return true
if the field exists, false
otherwise
+ */
+ public boolean partialFormFlattening(String name) {
+ return stamper.partialFormFlattening(name);
+ }
+
+ /** Adds a JavaScript action at the document level. When the document
+ * opens all this JavaScript runs.
+ * @param js the JavaScript code
+ */
+ public void addJavaScript(String js) {
+ stamper.addJavaScript(js, !PdfEncodings.isPdfDocEncoding(js));
+ }
+
+ /**
+ * Sets the viewer preferences.
+ * @param preferences the viewer preferences
+ * @see PdfWriter#setViewerPreferences(int)
+ */
+ public void setViewerPreferences(int preferences) {
+ stamper.setViewerPreferences(preferences);
+ }
+
+ /**
+ * Sets the XMP metadata.
+ * @param xmp
+ * @see PdfWriter#setXmpMetadata(byte[])
+ */
+ public void setXmpMetadata(byte[] xmp) {
+ stamper.setXmpMetadata(xmp);
+ }
+
+ /**
+ * Gets the 1.5 compression status.
+ * @return true
if the 1.5 compression is on
+ */
+ public boolean isFullCompression() {
+ return stamper.isFullCompression();
+ }
+
+ /**
+ * Sets the document's compression to the new 1.5 mode with object streams and xref
+ * streams. It can be set at any time but once set it can't be unset.
+ */
+ public void setFullCompression() {
+ if (stamper.isAppend())
+ return;
+ stamper.setFullCompression();
+ }
+
+ /**
+ * Sets the open and close page additional action.
+ * @param actionType the action type. It can be PdfWriter.PAGE_OPEN
+ * or PdfWriter.PAGE_CLOSE
+ * @param action the action to perform
+ * @param page the page where the action will be applied. The first page is 1
+ * @throws PdfException if the action type is invalid
+ */
+ public void setPageAction(PdfName actionType, PdfAction action, int page) throws PdfException {
+ stamper.setPageAction(actionType, action, page);
+ }
+
+ /**
+ * Sets the display duration for the page (for presentations)
+ * @param seconds the number of seconds to display the page. A negative value removes the entry
+ * @param page the page where the duration will be applied. The first page is 1
+ */
+ public void setDuration(int seconds, int page) {
+ stamper.setDuration(seconds, page);
+ }
+
+ /**
+ * Sets the transition for the page
+ * @param transition the transition object. A null
removes the transition
+ * @param page the page where the transition will be applied. The first page is 1
+ */
+ public void setTransition(PdfTransition transition, int page) {
+ stamper.setTransition(transition, page);
+ }
+
+ /**
+ * Applies a digital signature to a document, possibly as a new revision, making
+ * possible multiple signatures. The returned PdfStamper
+ * can be used normally as the signature is only applied when closing.
+ *
+ * A possible use for adding a signature without invalidating an existing one is:
+ *
+ *
+ * KeyStore ks = KeyStore.getInstance("pkcs12");
+ * ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
+ * String alias = (String)ks.aliases().nextElement();
+ * PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
+ * Certificate[] chain = ks.getCertificateChain(alias);
+ * PdfReader reader = new PdfReader("original.pdf");
+ * FileOutputStream fout = new FileOutputStream("signed.pdf");
+ * PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0', new
+ * File("/temp"), true);
+ * PdfSignatureAppearance sap = stp.getSignatureAppearance();
+ * sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
+ * sap.setReason("I'm the author");
+ * sap.setLocation("Lisbon");
+ * // comment next line to have an invisible signature
+ * sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
+ * stp.close();
+ *
+ * @param reader the original document
+ * @param os the output stream or null
to keep the document in the temporary file
+ * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
+ * document
+ * @param tempFile location of the temporary file. If it's a directory a temporary file will be created there.
+ * If it's a file it will be used directly. The file will be deleted on exit unless os
is null.
+ * In that case the document can be retrieved directly from the temporary file. If it's null
+ * no temporary file will be created and memory will be used
+ * @param append if true
the signature and all the other content will be added as a
+ * new revision thus not invalidating existing signatures
+ * @return a PdfStamper
+ * @throws DocumentException on error
+ * @throws IOException on error
+ */
+ public static PdfStamper createSignature(PdfReader reader, OutputStream os, char pdfVersion, File tempFile, boolean append) throws DocumentException, IOException {
+ PdfStamper stp;
+ if (tempFile == null) {
+ ByteBuffer bout = new ByteBuffer();
+ stp = new PdfStamper(reader, bout, pdfVersion, append);
+ stp.sigApp = new PdfSignatureAppearance(stp.stamper);
+ stp.sigApp.setSigout(bout);
+ }
+ else {
+ if (tempFile.isDirectory())
+ tempFile = File.createTempFile("pdf", null, tempFile);
+ FileOutputStream fout = new FileOutputStream(tempFile);
+ stp = new PdfStamper(reader, fout, pdfVersion, append);
+ stp.sigApp = new PdfSignatureAppearance(stp.stamper);
+ stp.sigApp.setTempFile(tempFile);
+ }
+ stp.sigApp.setOriginalout(os);
+ stp.sigApp.setStamper(stp);
+ stp.hasSignature = true;
+ return stp;
+ }
+
+ /**
+ * Applies a digital signature to a document. The returned PdfStamper
+ * can be used normally as the signature is only applied when closing.
+ *
+ * Note that the pdf is created in memory.
+ *
+ * A possible use is:
+ *
+ *
+ * KeyStore ks = KeyStore.getInstance("pkcs12");
+ * ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
+ * String alias = (String)ks.aliases().nextElement();
+ * PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
+ * Certificate[] chain = ks.getCertificateChain(alias);
+ * PdfReader reader = new PdfReader("original.pdf");
+ * FileOutputStream fout = new FileOutputStream("signed.pdf");
+ * PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
+ * PdfSignatureAppearance sap = stp.getSignatureAppearance();
+ * sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
+ * sap.setReason("I'm the author");
+ * sap.setLocation("Lisbon");
+ * // comment next line to have an invisible signature
+ * sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
+ * stp.close();
+ *
+ * @param reader the original document
+ * @param os the output stream
+ * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
+ * document
+ * @throws DocumentException on error
+ * @throws IOException on error
+ * @return a PdfStamper
+ */
+ public static PdfStamper createSignature(PdfReader reader, OutputStream os, char pdfVersion) throws DocumentException, IOException {
+ return createSignature(reader, os, pdfVersion, null, false);
+ }
+
+ /**
+ * Applies a digital signature to a document. The returned PdfStamper
+ * can be used normally as the signature is only applied when closing.
+ *
+ * A possible use is:
+ *
+ *
+ * KeyStore ks = KeyStore.getInstance("pkcs12");
+ * ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
+ * String alias = (String)ks.aliases().nextElement();
+ * PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
+ * Certificate[] chain = ks.getCertificateChain(alias);
+ * PdfReader reader = new PdfReader("original.pdf");
+ * FileOutputStream fout = new FileOutputStream("signed.pdf");
+ * PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0', new File("/temp"));
+ * PdfSignatureAppearance sap = stp.getSignatureAppearance();
+ * sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
+ * sap.setReason("I'm the author");
+ * sap.setLocation("Lisbon");
+ * // comment next line to have an invisible signature
+ * sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
+ * stp.close();
+ *
+ * @param reader the original document
+ * @param os the output stream or null
to keep the document in the temporary file
+ * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
+ * document
+ * @param tempFile location of the temporary file. If it's a directory a temporary file will be created there.
+ * If it's a file it will be used directly. The file will be deleted on exit unless os
is null.
+ * In that case the document can be retrieved directly from the temporary file. If it's null
+ * no temporary file will be created and memory will be used
+ * @return a PdfStamper
+ * @throws DocumentException on error
+ * @throws IOException on error
+ */
+ public static PdfStamper createSignature(PdfReader reader, OutputStream os, char pdfVersion, File tempFile) throws DocumentException, IOException
+ {
+ return createSignature(reader, os, pdfVersion, tempFile, false);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfStamperImp.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfStamperImp.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfStamperImp.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfStamperImp.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,1371 @@
+/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.Rectangle;
+// import pdftk.com.lowagie.text.Image; ssteward: dropped in 1.44
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+class PdfStamperImp extends PdfWriter {
+ HashMap readers2intrefs = new HashMap();
+ HashMap readers2file = new HashMap();
+ RandomAccessFileOrArray file;
+ PdfReader reader;
+ IntHashtable myXref = new IntHashtable();
+ /** Integer(page number) -> PageStamp */
+ HashMap pagesToContent = new HashMap();
+ boolean closed = false;
+ /** Holds value of property rotateContents. */
+ private boolean rotateContents = true;
+ protected AcroFields acroFields;
+ protected boolean flat = false;
+ protected boolean flatFreeText = false;
+ protected int namePtr[] = {0};
+ protected boolean namedAsNames;
+ protected List newBookmarks;
+ protected HashSet partialFlattening = new HashSet();
+ protected boolean useVp = false;
+ protected int vp = 0;
+ protected HashMap fieldTemplates = new HashMap();
+ protected boolean fieldsAdded = false;
+ protected int sigFlags = 0;
+ protected boolean append;
+ protected IntHashtable marked;
+ protected int initialXrefSize;
+ protected PdfAction openAction;
+
+ /** Creates new PdfStamperImp.
+ * @param reader the read PDF
+ * @param os the output destination
+ * @param pdfVersion the new pdf version or '\0' to keep the same version as the original
+ * document
+ * @param append
+ * @throws DocumentException on error
+ * @throws IOException
+ */
+ PdfStamperImp(PdfReader reader, OutputStream os, char pdfVersion, boolean append) throws DocumentException, IOException {
+ super(new PdfDocument(), os);
+ if (reader.isTampered())
+ throw new DocumentException("The original document was reused. Read it again from file.");
+ reader.setTampered(true);
+ this.reader = reader;
+ file = reader.getSafeFile();
+ this.append = append;
+ if (append) {
+ if (reader.isRebuilt())
+ throw new DocumentException("Append mode requires a document without errors even if recovery was possible.");
+ if (reader.isEncrypted())
+ crypto = new PdfEncryption(reader.getDecrypt());
+ HEADER = getISOBytes("\n");
+ file.reOpen();
+ byte buf[] = new byte[8192];
+ int n;
+ while ((n = file.read(buf)) > 0)
+ this.os.write(buf, 0, n);
+ file.close();
+ prevxref = reader.getLastXref();
+ reader.setAppendable(true);
+ }
+ else {
+ if (pdfVersion == 0)
+ super.setPdfVersion(reader.getPdfVersion());
+ else
+ super.setPdfVersion(pdfVersion);
+ }
+ super.open();
+ pdf.addWriter(this);
+ if (append) {
+ body.setRefnum(reader.getXrefSize());
+ marked = new IntHashtable();
+ if (reader.isNewXrefType())
+ fullCompression = true;
+ if (reader.isHybridXref())
+ fullCompression = false;
+ }
+ initialXrefSize = reader.getXrefSize();
+ }
+
+ void close(HashMap moreInfo) throws DocumentException, IOException {
+ if (closed)
+ return;
+ if (useVp) {
+ reader.setViewerPreferences(vp);
+ markUsed(reader.getTrailer().get(PdfName.ROOT));
+ }
+ if (flat)
+ flatFields();
+ if (flatFreeText)
+ flatFreeTextFields();
+ addFieldResources();
+ if (sigFlags != 0) {
+ PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM), reader.getCatalog());
+ if (acroForm != null) {
+ acroForm.put(PdfName.SIGFLAGS, new PdfNumber(sigFlags));
+ markUsed(acroForm);
+ }
+ }
+ closed = true;
+ addSharedObjectsToBody();
+ setOutlines();
+ setJavaScript();
+ if (openAction != null) {
+ reader.getCatalog().put(PdfName.OPENACTION, openAction);
+ }
+ // if there is XMP data to add: add it
+ if (xmpMetadata != null) {
+ PdfDictionary catalog = reader.getCatalog();
+ PdfStream xmp = new PdfStream(xmpMetadata);
+ xmp.put(PdfName.TYPE, PdfName.METADATA);
+ xmp.put(PdfName.SUBTYPE, PdfName.XML);
+ catalog.put(PdfName.METADATA, body.add(xmp).getIndirectReference());
+ markUsed(catalog);
+ }
+ PRIndirectReference iInfo = null;
+ try {
+ file.reOpen();
+ alterContents();
+ iInfo = (PRIndirectReference)reader.trailer.get(PdfName.INFO);
+ int skip = -1;
+ if (iInfo != null)
+ skip = iInfo.getNumber();
+ int rootN = ((PRIndirectReference)reader.trailer.get(PdfName.ROOT)).getNumber();
+ if (append) {
+ int keys[] = marked.getKeys();
+ for (int k = 0; k < keys.length; ++k) {
+ int j = keys[k];
+ PdfObject obj = reader.getPdfObjectRelease(j);
+ if (obj != null && skip != j && j < initialXrefSize) {
+ addToBody(obj, j, j != rootN);
+ }
+ }
+ for (int k = initialXrefSize; k < reader.getXrefSize(); ++k) {
+ PdfObject obj = reader.getPdfObject(k);
+ if (obj != null) {
+ addToBody(obj, getNewObjectNumber(reader, k, 0));
+ }
+ }
+ }
+ else {
+ for (int k = 1; k < reader.getXrefSize(); ++k) {
+ PdfObject obj = reader.getPdfObjectRelease(k);
+ if (obj != null && skip != k) {
+ addToBody(obj, getNewObjectNumber(reader, k, 0), k != rootN);
+ }
+ }
+ }
+ }
+ finally {
+ try {
+ file.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ PdfIndirectReference encryption = null;
+ PdfObject fileID = null;
+ if (crypto != null) {
+ if (append) {
+ PdfIndirectReference cryref = (PdfIndirectReference)reader.trailer.get(PdfName.ENCRYPT);
+ encryption = new PdfIndirectReference(0, cryref.getNumber(), cryref.getGeneration());
+ }
+ else {
+ PdfIndirectObject encryptionObject = addToBody(crypto.getEncryptionDictionary(), false);
+ encryption = encryptionObject.getIndirectReference();
+ }
+ fileID = crypto.getFileID();
+ }
+ else { // ssteward: carry ID over from reader
+ fileID = reader.trailer.get(PdfName.ID);
+ }
+ PRIndirectReference iRoot = (PRIndirectReference)reader.trailer.get(PdfName.ROOT);
+ PdfIndirectReference root = new PdfIndirectReference(0, getNewObjectNumber(reader, iRoot.getNumber(), 0));
+ PdfIndirectReference info = null;
+ PdfDictionary oldInfo = (PdfDictionary)PdfReader.getPdfObject(iInfo);
+ PdfDictionary newInfo = new PdfDictionary();
+ if (oldInfo != null) {
+ for (Iterator i = oldInfo.getKeys().iterator(); i.hasNext();) {
+ PdfName key = (PdfName)i.next();
+ PdfObject value = PdfReader.getPdfObject(oldInfo.get(key));
+ newInfo.put(key, value);
+ }
+ }
+ if (moreInfo != null) {
+ for (Iterator i = moreInfo.keySet().iterator(); i.hasNext();) {
+ String key = (String)i.next();
+ PdfName keyName = new PdfName(key);
+ String value = (String)moreInfo.get(key);
+ if (value == null)
+ newInfo.remove(keyName);
+ else
+ newInfo.put(keyName, new PdfString(value, PdfObject.TEXT_UNICODE));
+ }
+ }
+ if (append) {
+ if (iInfo == null)
+ info = addToBody(newInfo, false).getIndirectReference();
+ else
+ info = addToBody(newInfo, iInfo.getNumber(), false).getIndirectReference();
+ }
+ else {
+ if (!newInfo.getKeys().isEmpty())
+ info = addToBody(newInfo, false).getIndirectReference();
+ }
+ // write the cross-reference table of the body
+ body.writeCrossReferenceTable(os, root, info, encryption, fileID, prevxref);
+ if (fullCompression) {
+ os.write(getISOBytes("startxref\n"));
+ os.write(getISOBytes(String.valueOf(body.offset())));
+ os.write(getISOBytes("\n%%EOF\n"));
+ }
+ else {
+ PdfTrailer trailer = new PdfTrailer(body.size(),
+ body.offset(),
+ root,
+ info,
+ encryption,
+ fileID, prevxref);
+ trailer.toPdf(this, os);
+ }
+ os.flush();
+ if (isCloseStream())
+ os.close();
+ reader.close();
+ }
+
+ // added by ssteward to match PdfWriter::close()
+ public void close() { try {close(null);}catch(Exception e){throw new ExceptionConverter(e);} }
+
+ void applyRotation(PdfDictionary pageN, ByteBuffer out) {
+ if (!rotateContents)
+ return;
+ Rectangle page = reader.getPageSizeWithRotation(pageN);
+ int rotation = page.getRotation();
+ switch (rotation) {
+ case 90:
+ out.append(PdfContents.ROTATE90);
+ out.append(page.top());
+ out.append(' ').append('0').append(PdfContents.ROTATEFINAL);
+ break;
+ case 180:
+ out.append(PdfContents.ROTATE180);
+ out.append(page.right());
+ out.append(' ');
+ out.append(page.top());
+ out.append(PdfContents.ROTATEFINAL);
+ break;
+ case 270:
+ out.append(PdfContents.ROTATE270);
+ out.append('0').append(' ');
+ out.append(page.right());
+ out.append(PdfContents.ROTATEFINAL);
+ break;
+ }
+ }
+
+ void alterContents() throws IOException {
+ for (Iterator i = pagesToContent.values().iterator(); i.hasNext();) {
+ PageStamp ps = (PageStamp)i.next();
+ PdfDictionary pageN = ps.pageN;
+ markUsed(pageN);
+ PdfArray ar = null;
+ PdfObject content = PdfReader.getPdfObject(pageN.get(PdfName.CONTENTS), pageN);
+ if (content == null) {
+ ar = new PdfArray();
+ pageN.put(PdfName.CONTENTS, ar);
+ }
+ else if (content.isArray()) {
+ ar = (PdfArray)content;
+ markUsed(ar);
+ }
+ else if (content.isStream()) {
+ ar = new PdfArray();
+ ar.add(pageN.get(PdfName.CONTENTS));
+ pageN.put(PdfName.CONTENTS, ar);
+ }
+ else {
+ ar = new PdfArray();
+ pageN.put(PdfName.CONTENTS, ar);
+ }
+ ByteBuffer out = new ByteBuffer();
+ if (ps.under != null) {
+ out.append(PdfContents.SAVESTATE);
+ applyRotation(pageN, out);
+ out.append(ps.under.getInternalBuffer());
+ out.append(PdfContents.RESTORESTATE);
+ }
+ if (ps.over != null)
+ out.append(PdfContents.SAVESTATE);
+ PdfStream stream = new PdfStream(out.toByteArray());
+ try{stream.flateCompress();}catch(Exception e){throw new ExceptionConverter(e);}
+ ar.addFirst(addToBody(stream).getIndirectReference());
+ out.reset();
+ if (ps.over != null) {
+ out.append(' ');
+ out.append(PdfContents.RESTORESTATE);
+ out.append(PdfContents.SAVESTATE);
+ applyRotation(pageN, out);
+ out.append(ps.over.getInternalBuffer());
+ out.append(PdfContents.RESTORESTATE);
+ stream = new PdfStream(out.toByteArray());
+ try{stream.flateCompress();}catch(Exception e){throw new ExceptionConverter(e);}
+ ar.add(addToBody(stream).getIndirectReference());
+ }
+ alterResources(ps);
+ }
+ }
+
+ void alterResources(PageStamp ps) {
+ ps.pageN.put(PdfName.RESOURCES, ps.pageResources.getResources());
+ }
+
+ protected int getNewObjectNumber(PdfReader reader, int number, int generation) {
+ IntHashtable ref = (IntHashtable)readers2intrefs.get(reader);
+ if (ref != null) {
+ int n = ref.get(number);
+ if (n == 0) {
+ n = getIndirectReferenceNumber();
+ ref.put(number, n);
+ }
+ return n;
+ }
+ if (currentPdfReaderInstance == null) {
+ if (append && number < initialXrefSize)
+ return number;
+ int n = myXref.get(number);
+ if (n == 0) {
+ n = getIndirectReferenceNumber();
+ myXref.put(number, n);
+ }
+ return n;
+ }
+ else
+ return currentPdfReaderInstance.getNewObjectNumber(number, generation);
+ }
+
+ RandomAccessFileOrArray getReaderFile(PdfReader reader) {
+ if (readers2intrefs.containsKey(reader)) {
+ RandomAccessFileOrArray raf = (RandomAccessFileOrArray)readers2file.get(reader);
+ if (raf != null)
+ return raf;
+ return reader.getSafeFile();
+ }
+ if (currentPdfReaderInstance == null)
+ return file;
+ else
+ return currentPdfReaderInstance.getReaderFile();
+ }
+
+ /**
+ * @param reader
+ * @param openFile
+ * @throws IOException
+ */
+ public void registerReader(PdfReader reader, boolean openFile) throws IOException {
+ if (readers2intrefs.containsKey(reader))
+ return;
+ readers2intrefs.put(reader, new IntHashtable());
+ if (openFile) {
+ RandomAccessFileOrArray raf = reader.getSafeFile();
+ readers2file.put(reader, raf);
+ raf.reOpen();
+ }
+ }
+
+ /**
+ * @param reader
+ */
+ public void unRegisterReader(PdfReader reader) {
+ if (!readers2intrefs.containsKey(reader))
+ return;
+ readers2intrefs.remove(reader);
+ RandomAccessFileOrArray raf = (RandomAccessFileOrArray)readers2file.get(reader);
+ if (raf == null)
+ return;
+ readers2file.remove(reader);
+ try{raf.close();}catch(Exception e){}
+ }
+
+ static void findAllObjects(PdfReader reader, PdfObject obj, IntHashtable hits) {
+ if (obj == null)
+ return;
+ switch (obj.type()) {
+ case PdfObject.INDIRECT:
+ PRIndirectReference iref = (PRIndirectReference)obj;
+ if (reader != iref.getReader())
+ return;
+ if (hits.containsKey(iref.getNumber()))
+ return;
+ hits.put(iref.getNumber(), 1);
+ findAllObjects(reader, PdfReader.getPdfObject(obj), hits);
+ return;
+ case PdfObject.ARRAY:
+ ArrayList lst = ((PdfArray)obj).getArrayList();
+ for (int k = 0; k < lst.size(); ++k) {
+ findAllObjects(reader, (PdfObject)lst.get(k), hits);
+ }
+ return;
+ case PdfObject.DICTIONARY:
+ case PdfObject.STREAM:
+ PdfDictionary dic = (PdfDictionary)obj;
+ for (Iterator it = dic.getKeys().iterator(); it.hasNext();) {
+ PdfName name = (PdfName)it.next();
+ findAllObjects(reader, dic.get(name), hits);
+ }
+ return;
+ }
+ }
+
+ /**
+ * @param fdf
+ * @throws IOException
+ */
+ public void addComments(FdfReader fdf) throws IOException{
+ if (readers2intrefs.containsKey(fdf))
+ return;
+ PdfDictionary catalog = fdf.getCatalog();
+ catalog = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.FDF));
+ if (catalog == null)
+ return;
+ PdfArray annots = (PdfArray)PdfReader.getPdfObject(catalog.get(PdfName.ANNOTS));
+ if (annots == null || annots.size() == 0)
+ return;
+ registerReader(fdf, false);
+ IntHashtable hits = new IntHashtable();
+ HashMap irt = new HashMap();
+ ArrayList an = new ArrayList();
+ ArrayList ar = annots.getArrayList();
+ for (int k = 0; k < ar.size(); ++k) {
+ PdfObject obj = (PdfObject)ar.get(k);
+ PdfDictionary annot = (PdfDictionary)PdfReader.getPdfObject(obj);
+ PdfNumber page = (PdfNumber)PdfReader.getPdfObject(annot.get(PdfName.PAGE));
+ if (page == null || page.intValue() >= reader.getNumberOfPages())
+ continue;
+ findAllObjects(fdf, obj, hits);
+ an.add(obj);
+ if (obj.type() == PdfObject.INDIRECT) {
+ PdfObject nm = PdfReader.getPdfObject(annot.get(PdfName.NM));
+ if (nm != null && nm.type() == PdfObject.STRING)
+ irt.put(nm.toString(), obj);
+ }
+ }
+ int arhits[] = hits.getKeys();
+ for (int k = 0; k < arhits.length; ++k) {
+ int n = arhits[k];
+ PdfObject obj = fdf.getPdfObject(n);
+ if (obj.type() == PdfObject.DICTIONARY) {
+ PdfObject str = PdfReader.getPdfObject(((PdfDictionary)obj).get(PdfName.IRT));
+ if (str != null && str.type() == PdfObject.STRING) {
+ PdfObject i = (PdfObject)irt.get(str.toString());
+ if (i != null) {
+ PdfDictionary dic2 = new PdfDictionary();
+ dic2.merge((PdfDictionary)obj);
+ dic2.put(PdfName.IRT, i);
+ obj = dic2;
+ }
+ }
+ }
+ addToBody(obj, getNewObjectNumber(fdf, n, 0));
+ }
+ for (int k = 0; k < an.size(); ++k) {
+ PdfObject obj = (PdfObject)an.get(k);
+ PdfDictionary annot = (PdfDictionary)PdfReader.getPdfObject(obj);
+ PdfNumber page = (PdfNumber)PdfReader.getPdfObject(annot.get(PdfName.PAGE));
+ PdfDictionary dic = reader.getPageN(page.intValue() + 1);
+ PdfArray annotsp = (PdfArray)PdfReader.getPdfObject(dic.get(PdfName.ANNOTS), dic);
+ if (annotsp == null) {
+ annotsp = new PdfArray();
+ dic.put(PdfName.ANNOTS, annotsp);
+ markUsed(dic);
+ }
+ markUsed(annotsp);
+ annotsp.add(obj);
+ }
+ }
+
+ PageStamp getPageStamp(int pageNum) {
+ PdfDictionary pageN = reader.getPageN(pageNum);
+ PageStamp ps = (PageStamp)pagesToContent.get(pageN);
+ if (ps == null) {
+ ps = new PageStamp(this, reader, pageN);
+ pagesToContent.put(pageN, ps);
+ }
+ return ps;
+ }
+
+ PdfContentByte getUnderContent(int pageNum) {
+ if (pageNum < 1 || pageNum > reader.getNumberOfPages())
+ return null;
+ PageStamp ps = getPageStamp(pageNum);
+ if (ps.under == null)
+ ps.under = new StampContent(this, ps);
+ return ps.under;
+ }
+
+ PdfContentByte getOverContent(int pageNum) {
+ if (pageNum < 1 || pageNum > reader.getNumberOfPages())
+ return null;
+ PageStamp ps = getPageStamp(pageNum);
+ if (ps.over == null)
+ ps.over = new StampContent(this, ps);
+ return ps.over;
+ }
+
+ void correctAcroFieldPages(int page) {
+ if (acroFields == null)
+ return;
+ if (page > reader.getNumberOfPages())
+ return;
+ HashMap fields = acroFields.getFields();
+ for (Iterator it = fields.values().iterator(); it.hasNext();) {
+ AcroFields.Item item = (AcroFields.Item)it.next();
+ ArrayList pages = item.page;
+ for (int k = 0; k < pages.size(); ++k) {
+ int p = ((Integer)pages.get(k)).intValue();
+ if (p >= page)
+ pages.set(k, new Integer(p + 1));
+ }
+ }
+ }
+
+ void insertPage(int pageNumber, Rectangle mediabox) {
+ Rectangle media = new Rectangle(mediabox);
+ int rotation = media.getRotation() % 360;
+ PdfDictionary page = new PdfDictionary(PdfName.PAGE);
+ PdfDictionary resources = new PdfDictionary();
+ PdfArray procset = new PdfArray();
+ procset.add(PdfName.PDF);
+ procset.add(PdfName.TEXT);
+ procset.add(PdfName.IMAGEB);
+ procset.add(PdfName.IMAGEC);
+ procset.add(PdfName.IMAGEI);
+ resources.put(PdfName.PROCSET, procset);
+ page.put(PdfName.RESOURCES, resources);
+ page.put(PdfName.ROTATE, new PdfNumber(rotation));
+ page.put(PdfName.MEDIABOX, new PdfRectangle(media, rotation));
+ PRIndirectReference pref = reader.addPdfObject(page);
+ PdfDictionary parent;
+ PRIndirectReference parentRef;
+ if (pageNumber > reader.getNumberOfPages()) {
+ PdfDictionary lastPage = reader.getPageNRelease(reader.getNumberOfPages());
+ parentRef = (PRIndirectReference)lastPage.get(PdfName.PARENT);
+ parentRef = new PRIndirectReference(reader, parentRef.getNumber());
+ parent = (PdfDictionary)PdfReader.getPdfObject(parentRef);
+ PdfArray kids = (PdfArray)PdfReader.getPdfObject(parent.get(PdfName.KIDS), parent);
+ kids.add(pref);
+ markUsed(kids);
+ reader.pageRefs.insertPage(pageNumber, pref);
+ }
+ else {
+ if (pageNumber < 1)
+ pageNumber = 1;
+ PdfDictionary firstPage = reader.getPageN(pageNumber);
+ PRIndirectReference firstPageRef = (PRIndirectReference)reader.getPageOrigRef(pageNumber);
+ reader.releasePage(pageNumber);
+ parentRef = (PRIndirectReference)firstPage.get(PdfName.PARENT);
+ parentRef = new PRIndirectReference(reader, parentRef.getNumber());
+ parent = (PdfDictionary)PdfReader.getPdfObject(parentRef);
+ PdfArray kids = (PdfArray)PdfReader.getPdfObject(parent.get(PdfName.KIDS), parent);
+ ArrayList ar = kids.getArrayList();
+ int len = ar.size();
+ int num = firstPageRef.getNumber();
+ for (int k = 0; k < len; ++k) {
+ PRIndirectReference cur = (PRIndirectReference)ar.get(k);
+ if (num == cur.getNumber()) {
+ ar.add(k, pref);
+ break;
+ }
+ }
+ if (len == ar.size())
+ throw new RuntimeException("Internal inconsistence.");
+ markUsed(kids);
+ reader.pageRefs.insertPage(pageNumber, pref);
+ correctAcroFieldPages(pageNumber);
+ }
+ page.put(PdfName.PARENT, parentRef);
+ while (parent != null) {
+ markUsed(parent);
+ PdfNumber count = (PdfNumber)PdfReader.getPdfObjectRelease(parent.get(PdfName.COUNT));
+ parent.put(PdfName.COUNT, new PdfNumber(count.intValue() + 1));
+ parent = (PdfDictionary)PdfReader.getPdfObject(parent.get(PdfName.PARENT));
+ }
+ }
+
+ /** Getter for property rotateContents.
+ * @return Value of property rotateContents.
+ *
+ */
+ boolean isRotateContents() {
+ return this.rotateContents;
+ }
+
+ /** Setter for property rotateContents.
+ * @param rotateContents New value of property rotateContents.
+ *
+ */
+ void setRotateContents(boolean rotateContents) {
+ this.rotateContents = rotateContents;
+ }
+
+ boolean isContentWritten() {
+ return body.size() > 1;
+ }
+
+ AcroFields getAcroFields() {
+ if (acroFields == null) {
+ acroFields = new AcroFields(reader, this);
+ }
+ return acroFields;
+ }
+
+ void setFormFlattening(boolean flat) {
+ this.flat = flat;
+ }
+
+ void setFreeTextFlattening(boolean flat) {
+ this.flatFreeText = flat;
+ }
+
+ boolean partialFormFlattening(String name) {
+ getAcroFields();
+ if (!acroFields.getFields().containsKey(name))
+ return false;
+ partialFlattening.add(name);
+ return true;
+ }
+
+ void flatFields() {
+ if (append)
+ throw new IllegalArgumentException("Field flattening is not supported in append mode.");
+ getAcroFields();
+ HashMap fields = acroFields.getFields();
+ if (fieldsAdded && partialFlattening.isEmpty()) {
+ for (Iterator i = fields.keySet().iterator(); i.hasNext();) {
+ partialFlattening.add(i.next());
+ }
+ }
+ PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.ACROFORM));
+ ArrayList acroFds = null;
+ if (acroForm != null) {
+ PdfArray array = (PdfArray)PdfReader.getPdfObject(acroForm.get(PdfName.FIELDS), acroForm);
+ if (array != null)
+ acroFds = array.getArrayList();
+ }
+ for (Iterator i = fields.keySet().iterator(); i.hasNext();) {
+ String name = (String)i.next();
+ if (!partialFlattening.isEmpty() && !partialFlattening.contains(name))
+ continue;
+ AcroFields.Item item = (AcroFields.Item)fields.get(name);
+ for (int k = 0; k < item.merged.size(); ++k) {
+ PdfDictionary merged = (PdfDictionary)item.merged.get(k);
+ PdfNumber ff = (PdfNumber)PdfReader.getPdfObject(merged.get(PdfName.F));
+ int flags = 0;
+ if (ff != null)
+ flags = ff.intValue();
+ int page = ((Integer)item.page.get(k)).intValue();
+ PdfDictionary appDic = (PdfDictionary)PdfReader.getPdfObject(merged.get(PdfName.AP));
+ if (appDic != null && (flags & PdfFormField.FLAGS_PRINT) != 0 && (flags & PdfFormField.FLAGS_HIDDEN) == 0) {
+ PdfObject obj = appDic.get(PdfName.N);
+ PdfAppearance app = null;
+ PdfObject objReal = PdfReader.getPdfObject(obj);
+ if (obj instanceof PdfIndirectReference && !obj.isIndirect())
+ app = new PdfAppearance((PdfIndirectReference)obj);
+ else if (objReal instanceof PdfStream) {
+ ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
+ app = new PdfAppearance((PdfIndirectReference)obj);
+ }
+ else {
+ if (objReal.isDictionary()) {
+ PdfName as = (PdfName)PdfReader.getPdfObject(merged.get(PdfName.AS));
+ if (as != null) {
+ PdfIndirectReference iref = (PdfIndirectReference)((PdfDictionary)objReal).get(as);
+ if (iref != null) {
+ app = new PdfAppearance(iref);
+ if (iref.isIndirect()) {
+ objReal = PdfReader.getPdfObject(iref);
+ ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
+ }
+ }
+ }
+ }
+ }
+ if (app != null) {
+ Rectangle box = PdfReader.getNormalizedRectangle((PdfArray)PdfReader.getPdfObject(merged.get(PdfName.RECT)));
+ PdfContentByte cb = getOverContent(page);
+ cb.setLiteral("Q ");
+ cb.addTemplate(app, box.left(), box.bottom());
+ cb.setLiteral("q ");
+ }
+ }
+ if (partialFlattening.isEmpty())
+ continue;
+ PdfDictionary pageDic = reader.getPageN(page);
+ PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
+ if (annots == null)
+ continue;
+ ArrayList ar = annots.getArrayList();
+ for (int idx = 0; idx < ar.size(); ++idx) {
+ PdfObject ran = (PdfObject)ar.get(idx);
+ if (!ran.isIndirect())
+ continue;
+ PdfObject ran2 = (PdfObject)item.widget_refs.get(k);
+ if (!ran2.isIndirect())
+ continue;
+ if (((PRIndirectReference)ran).getNumber() == ((PRIndirectReference)ran2).getNumber()) {
+ ar.remove(idx--);
+ PRIndirectReference wdref = (PRIndirectReference)ran2;
+ while (true) {
+ PdfDictionary wd = (PdfDictionary)PdfReader.getPdfObject(wdref);
+ PRIndirectReference parentRef = (PRIndirectReference)wd.get(PdfName.PARENT);
+ PdfReader.killIndirect(wdref);
+ if (parentRef == null) { // reached AcroForm
+ for (int fr = 0; fr < acroFds.size(); ++fr) {
+ PdfObject h = (PdfObject)acroFds.get(fr);
+ if (h.isIndirect() && ((PRIndirectReference)h).getNumber() == wdref.getNumber()) {
+ acroFds.remove(fr);
+ --fr;
+ }
+ }
+ break;
+ }
+ PdfDictionary parent = (PdfDictionary)PdfReader.getPdfObject(parentRef);
+ PdfArray kids = (PdfArray)PdfReader.getPdfObject(parent.get(PdfName.KIDS));
+ ArrayList kar = kids.getArrayList();
+ for (int fr = 0; fr < kar.size(); ++fr) {
+ PdfObject h = (PdfObject)kar.get(fr);
+ if (h.isIndirect() && ((PRIndirectReference)h).getNumber() == wdref.getNumber()) {
+ kar.remove(fr);
+ --fr;
+ }
+ }
+ if (!kar.isEmpty())
+ break;
+ wdref = parentRef;
+ }
+ }
+ }
+ if (ar.size() == 0) {
+ PdfReader.killIndirect(pageDic.get(PdfName.ANNOTS));
+ pageDic.remove(PdfName.ANNOTS);
+ }
+ }
+ }
+ if (!fieldsAdded && partialFlattening.isEmpty()) {
+ for (int page = 1; page <= reader.getNumberOfPages(); ++page) {
+ PdfDictionary pageDic = reader.getPageN(page);
+ PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
+ if (annots == null)
+ continue;
+ ArrayList ar = annots.getArrayList();
+ for (int idx = 0; idx < ar.size(); ++idx) {
+ PdfObject annoto = PdfReader.getPdfObject((PdfObject)ar.get(idx));
+ if ((annoto instanceof PdfIndirectReference) && !annoto.isIndirect())
+ continue;
+ PdfDictionary annot = (PdfDictionary)annoto;
+ if (PdfName.WIDGET.equals(annot.get(PdfName.SUBTYPE))) {
+ ar.remove(idx);
+ --idx;
+ }
+ }
+ if (ar.size() == 0) {
+ PdfReader.killIndirect(pageDic.get(PdfName.ANNOTS));
+ pageDic.remove(PdfName.ANNOTS);
+ }
+ }
+ eliminateAcroformObjects();
+ }
+ }
+
+ void eliminateAcroformObjects() {
+ PdfObject acro = reader.getCatalog().get(PdfName.ACROFORM);
+ if (acro == null)
+ return;
+ PdfDictionary acrodic = (PdfDictionary)PdfReader.getPdfObject(acro);
+ PdfObject iFields = acrodic.get(PdfName.FIELDS);
+ if (iFields != null) {
+ PdfDictionary kids = new PdfDictionary();
+ kids.put(PdfName.KIDS, iFields);
+ sweepKids(kids);
+ PdfReader.killIndirect(iFields);
+ acrodic.put(PdfName.FIELDS, new PdfArray());
+ }
+// PdfReader.killIndirect(acro);
+// reader.getCatalog().remove(PdfName.ACROFORM);
+ }
+
+ void sweepKids(PdfObject obj) {
+ PdfObject oo = PdfReader.killIndirect(obj);
+ if (oo == null || !oo.isDictionary())
+ return;
+ PdfDictionary dic = (PdfDictionary)oo;
+ PdfArray kids = (PdfArray)PdfReader.killIndirect(dic.get(PdfName.KIDS));
+ if (kids == null)
+ return;
+ ArrayList ar = kids.getArrayList();
+ for (int k = 0; k < ar.size(); ++k) {
+ sweepKids((PdfObject)ar.get(k));
+ }
+ }
+
+ private void flatFreeTextFields()
+ {
+ if (append)
+ throw new IllegalArgumentException("FreeText flattening is not supported in append mode.");
+
+ for (int page = 1; page <= reader.getNumberOfPages(); ++page)
+ {
+ PdfDictionary pageDic = reader.getPageN(page);
+ PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageDic.get(PdfName.ANNOTS));
+ if (annots == null)
+ continue;
+ ArrayList ar = annots.getArrayList();
+ for (int idx = 0; idx < ar.size(); ++idx)
+ {
+ PdfObject annoto = PdfReader.getPdfObject((PdfObject)ar.get(idx));
+ if ((annoto instanceof PdfIndirectReference) && !annoto.isIndirect())
+ continue;
+
+ PdfDictionary annDic = (PdfDictionary)annoto;
+ if (!((PdfName)annDic.get(PdfName.SUBTYPE)).equals(PdfName.FREETEXT))
+ continue;
+ PdfNumber ff = (PdfNumber)PdfReader.getPdfObject(annDic.get(PdfName.F));
+ int flags = (ff != null) ? ff.intValue() : 0;
+
+ if ( (flags & PdfFormField.FLAGS_PRINT) != 0 && (flags & PdfFormField.FLAGS_HIDDEN) == 0)
+ {
+ PdfObject obj1 = (PdfObject) annDic.get(PdfName.AP);
+ if (obj1 == null)
+ continue;
+ PdfDictionary appDic = (obj1 instanceof PdfIndirectReference) ?
+ (PdfDictionary) PdfReader.getPdfObject((PdfIndirectReference) obj1) : (PdfDictionary) obj1;
+ PdfObject obj = appDic.get(PdfName.N);
+ PdfAppearance app = null;
+ PdfObject objReal = PdfReader.getPdfObject(obj);
+
+ if (obj instanceof PdfIndirectReference && !obj.isIndirect())
+ app = new PdfAppearance((PdfIndirectReference)obj);
+ else if (objReal instanceof PdfStream)
+ {
+ ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
+ app = new PdfAppearance((PdfIndirectReference)obj);
+ }
+ else
+ {
+ if (objReal.isDictionary())
+ {
+ PdfName as_p = (PdfName)PdfReader.getPdfObject(appDic.get(PdfName.AS));
+ if (as_p != null)
+ {
+ PdfIndirectReference iref = (PdfIndirectReference)((PdfDictionary)objReal).get(as_p);
+ if (iref != null)
+ {
+ app = new PdfAppearance(iref);
+ if (iref.isIndirect())
+ {
+ objReal = PdfReader.getPdfObject(iref);
+ ((PdfDictionary)objReal).put(PdfName.SUBTYPE, PdfName.FORM);
+ }
+ }
+ }
+ }
+ }
+ if (app != null)
+ {
+ Rectangle box = PdfReader.getNormalizedRectangle((PdfArray)PdfReader.getPdfObject(annDic.get(PdfName.RECT)));
+ PdfContentByte cb = getOverContent(page);
+ cb.setLiteral("Q ");
+ cb.addTemplate(app, box.left(), box.bottom());
+ cb.setLiteral("q ");
+ }
+ }
+ if (partialFlattening.size() == 0)
+ continue;
+ }
+ for (int idx = 0; idx < ar.size(); ++idx)
+ {
+ PdfObject annoto = PdfReader.getPdfObject((PdfObject)ar.get(idx));
+ if ((annoto instanceof PdfIndirectReference) && annoto.isIndirect())
+ {
+ PdfDictionary annot = (PdfDictionary)annoto;
+ if (PdfName.FREETEXT.equals(annot.get(PdfName.SUBTYPE)))
+ {
+ ar.remove(idx);
+ --idx;
+ }
+ }
+ }
+ if (ar.size() == 0)
+ {
+ PdfReader.killIndirect(pageDic.get(PdfName.ANNOTS));
+ pageDic.remove(PdfName.ANNOTS);
+ }
+ }
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfWriter#getPageReference(int)
+ */
+ public PdfIndirectReference getPageReference(int page) {
+ PdfIndirectReference ref = reader.getPageOrigRef(page);
+ if (ref == null)
+ throw new IllegalArgumentException("Invalid page number " + page);
+ return ref;
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfWriter#addAnnotation(pdftk.com.lowagie.text.pdf.PdfAnnotation)
+ */
+ public void addAnnotation(PdfAnnotation annot) {
+ throw new RuntimeException("Unsupported in this context. Use PdfStamper.addAnnotation()");
+ }
+
+ void addDocumentField(PdfIndirectReference ref) {
+ PdfDictionary catalog = reader.getCatalog();
+ PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.ACROFORM), catalog);
+ if (acroForm == null) {
+ acroForm = new PdfDictionary();
+ catalog.put(PdfName.ACROFORM, acroForm);
+ markUsed(catalog);
+ }
+ PdfArray fields = (PdfArray)PdfReader.getPdfObject(acroForm.get(PdfName.FIELDS), acroForm);
+ if (fields == null) {
+ fields = new PdfArray();
+ acroForm.put(PdfName.FIELDS, fields);
+ markUsed(acroForm);
+ }
+ fields.add(ref);
+ markUsed(fields);
+ }
+
+ void addFieldResources() {
+ if (fieldTemplates.size() == 0)
+ return;
+ PdfDictionary catalog = reader.getCatalog();
+ PdfDictionary acroForm = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.ACROFORM), catalog);
+ if (acroForm == null) {
+ acroForm = new PdfDictionary();
+ catalog.put(PdfName.ACROFORM, acroForm);
+ markUsed(catalog);
+ }
+ PdfDictionary dr = (PdfDictionary)PdfReader.getPdfObject(acroForm.get(PdfName.DR), acroForm);
+ if (dr == null) {
+ dr = new PdfDictionary();
+ acroForm.put(PdfName.DR, dr);
+ markUsed(acroForm);
+ }
+ markUsed(dr);
+ for (Iterator it = fieldTemplates.keySet().iterator(); it.hasNext();) {
+ PdfTemplate template = (PdfTemplate)it.next();
+ PdfFormField.mergeResources(dr, (PdfDictionary)template.getResources(), this);
+ }
+ PdfDictionary fonts = (PdfDictionary)PdfReader.getPdfObject(dr.get(PdfName.FONT));
+ if (fonts != null && acroForm.get(PdfName.DA) == null) {
+ acroForm.put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
+ markUsed(acroForm);
+ }
+ }
+
+ void expandFields(PdfFormField field, ArrayList allAnnots) {
+ allAnnots.add(field);
+ ArrayList kids = field.getKids();
+ if (kids != null) {
+ for (int k = 0; k < kids.size(); ++k)
+ expandFields((PdfFormField)kids.get(k), allAnnots);
+ }
+ }
+
+ void addAnnotation(PdfAnnotation annot, PdfDictionary pageN) {
+ try {
+ ArrayList allAnnots = new ArrayList();
+ if (annot.isForm()) {
+ fieldsAdded = true;
+ getAcroFields();
+ PdfFormField field = (PdfFormField)annot;
+ if (field.getParent() != null)
+ return;
+ expandFields(field, allAnnots);
+ }
+ else
+ allAnnots.add(annot);
+ for (int k = 0; k < allAnnots.size(); ++k) {
+ annot = (PdfAnnotation)allAnnots.get(k);
+ if (annot.getPlaceInPage() > 0)
+ pageN = reader.getPageN(annot.getPlaceInPage());
+ if (annot.isForm()) {
+ if (!annot.isUsed()) {
+ HashMap templates = annot.getTemplates();
+ if (templates != null)
+ fieldTemplates.putAll(templates);
+ }
+ PdfFormField field = (PdfFormField)annot;
+ if (field.getParent() == null)
+ addDocumentField(field.getIndirectReference());
+ }
+ if (annot.isAnnotation()) {
+ PdfArray annots = (PdfArray)PdfReader.getPdfObject(pageN.get(PdfName.ANNOTS), pageN);
+ if (annots == null) {
+ annots = new PdfArray();
+ pageN.put(PdfName.ANNOTS, annots);
+ markUsed(pageN);
+ }
+ annots.add(annot.getIndirectReference());
+ markUsed(annots);
+ if (!annot.isUsed()) {
+ PdfRectangle rect = (PdfRectangle)annot.get(PdfName.RECT);
+ if (rect != null && (rect.left() != 0 || rect.right() != 0 || rect.top() != 0 || rect.bottom() != 0)) {
+ int rotation = reader.getPageRotation(pageN);
+ Rectangle pageSize = reader.getPageSizeWithRotation(pageN);
+ switch (rotation) {
+ case 90:
+ annot.put(PdfName.RECT, new PdfRectangle(
+ pageSize.top() - rect.bottom(),
+ rect.left(),
+ pageSize.top() - rect.top(),
+ rect.right()));
+ break;
+ case 180:
+ annot.put(PdfName.RECT, new PdfRectangle(
+ pageSize.right() - rect.left(),
+ pageSize.top() - rect.bottom(),
+ pageSize.right() - rect.right(),
+ pageSize.top() - rect.top()));
+ break;
+ case 270:
+ annot.put(PdfName.RECT, new PdfRectangle(
+ rect.bottom(),
+ pageSize.right() - rect.left(),
+ rect.top(),
+ pageSize.right() - rect.right()));
+ break;
+ }
+ }
+ }
+ }
+ if (!annot.isUsed()) {
+ annot.setUsed();
+ addToBody(annot, annot.getIndirectReference());
+ }
+ }
+ }
+ catch (IOException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ void addAnnotation(PdfAnnotation annot, int page) {
+ addAnnotation(annot, reader.getPageN(page));
+ }
+
+ private void outlineTravel(PRIndirectReference outline) {
+ while (outline != null) {
+ PdfDictionary outlineR = (PdfDictionary)PdfReader.getPdfObjectRelease(outline);
+ PRIndirectReference first = (PRIndirectReference)outlineR.get(PdfName.FIRST);
+ if (first != null) {
+ outlineTravel(first);
+ }
+ PdfReader.killIndirect(outlineR.get(PdfName.DEST));
+ PdfReader.killIndirect(outlineR.get(PdfName.A));
+ PdfReader.killIndirect(outline);
+ outline = (PRIndirectReference)outlineR.get(PdfName.NEXT);
+ }
+ }
+
+ void deleteOutlines() {
+ PdfDictionary catalog = reader.getCatalog();
+ PRIndirectReference outlines = (PRIndirectReference)catalog.get(PdfName.OUTLINES);
+ if (outlines == null)
+ return;
+ outlineTravel(outlines);
+ PdfReader.killIndirect(outlines);
+ catalog.remove(PdfName.OUTLINES);
+ markUsed(catalog);
+ }
+
+ void setJavaScript() throws IOException {
+ ArrayList djs = pdf.getDocumentJavaScript();
+ if (djs.size() == 0)
+ return;
+ PdfDictionary catalog = reader.getCatalog();
+ PdfDictionary names = (PdfDictionary)PdfReader.getPdfObject(catalog.get(PdfName.NAMES), catalog);
+ if (names == null) {
+ names = new PdfDictionary();
+ catalog.put(PdfName.NAMES, names);
+ markUsed(catalog);
+ }
+ markUsed(names);
+ String s = String.valueOf(djs.size() - 1);
+ int n = s.length();
+ String pad = "000000000000000";
+ HashMap maptree = new HashMap();
+ for (int k = 0; k < djs.size(); ++k) {
+ s = String.valueOf(k);
+ s = pad.substring(0, n - s.length()) + s;
+ maptree.put(s, djs.get(k));
+ }
+ PdfDictionary tree = PdfNameTree.writeTree(maptree, this);
+ names.put(PdfName.JAVASCRIPT, addToBody(tree).getIndirectReference());
+ }
+
+ void setOutlines() throws IOException {
+ if (newBookmarks == null)
+ return;
+ deleteOutlines();
+ if (newBookmarks.size() == 0)
+ return;
+ namedAsNames = (reader.getCatalog().get(PdfName.DESTS) != null);
+ PdfDictionary top = new PdfDictionary();
+ PdfIndirectReference topRef = getPdfIndirectReference();
+ Object kids[] = SimpleBookmark.iterateOutlines(this, topRef, newBookmarks, namedAsNames);
+ top.put(PdfName.FIRST, (PdfIndirectReference)kids[0]);
+ top.put(PdfName.LAST, (PdfIndirectReference)kids[1]);
+ top.put(PdfName.COUNT, new PdfNumber(((Integer)kids[2]).intValue()));
+ addToBody(top, topRef);
+ reader.getCatalog().put(PdfName.OUTLINES, topRef);
+ markUsed(reader.getCatalog());
+ }
+
+ void setOutlines(List outlines) {
+ newBookmarks = outlines;
+ }
+
+ /**
+ * Sets the viewer preferences.
+ * @param preferences the viewer preferences
+ * @see PdfWriter#setViewerPreferences(int)
+ */
+ public void setViewerPreferences(int preferences) {
+ useVp = true;
+ vp |= preferences;
+ }
+
+ /**
+ * Set the signature flags.
+ * @param f the flags. This flags are ORed with current ones
+ */
+ public void setSigFlags(int f) {
+ sigFlags |= f;
+ }
+
+ /** Always throws an UnsupportedOperationException
.
+ * @param actionType ignore
+ * @param action ignore
+ * @throws PdfException ignore
+ * @see PdfStamper#setPageAction(PdfName, PdfAction, int)
+ */
+ public void setPageAction(PdfName actionType, PdfAction action) throws PdfException {
+ throw new UnsupportedOperationException("Use setPageAction(PdfName actionType, PdfAction action, int page)");
+ }
+
+ /**
+ * Sets the open and close page additional action.
+ * @param actionType the action type. It can be PdfWriter.PAGE_OPEN
+ * or PdfWriter.PAGE_CLOSE
+ * @param action the action to perform
+ * @param page the page where the action will be applied. The first page is 1
+ * @throws PdfException if the action type is invalid
+ */
+ void setPageAction(PdfName actionType, PdfAction action, int page) throws PdfException {
+ if (!actionType.equals(PAGE_OPEN) && !actionType.equals(PAGE_CLOSE))
+ throw new PdfException("Invalid page additional action type: " + actionType.toString());
+ PdfDictionary pg = reader.getPageN(page);
+ PdfDictionary aa = (PdfDictionary)PdfReader.getPdfObject(pg.get(PdfName.AA), pg);
+ if (aa == null) {
+ aa = new PdfDictionary();
+ pg.put(PdfName.AA, aa);
+ markUsed(pg);
+ }
+ aa.put(actionType, action);
+ markUsed(aa);
+ }
+
+ /**
+ * Always throws an UnsupportedOperationException
.
+ * @param seconds ignore
+ */
+ public void setDuration(int seconds) {
+ throw new UnsupportedOperationException("Use setPageAction(PdfName actionType, PdfAction action, int page)");
+ }
+
+ /**
+ * Always throws an UnsupportedOperationException
.
+ * @param transition ignore
+ */
+ public void setTransition(PdfTransition transition) {
+ throw new UnsupportedOperationException("Use setPageAction(PdfName actionType, PdfAction action, int page)");
+ }
+
+ /**
+ * Sets the display duration for the page (for presentations)
+ * @param seconds the number of seconds to display the page. A negative value removes the entry
+ * @param page the page where the duration will be applied. The first page is 1
+ */
+ void setDuration(int seconds, int page) {
+ PdfDictionary pg = reader.getPageN(page);
+ if (seconds < 0)
+ pg.remove(PdfName.DUR);
+ else
+ pg.put(PdfName.DUR, new PdfNumber(seconds));
+ markUsed(pg);
+ }
+
+ /**
+ * Sets the transition for the page
+ * @param transition the transition object. A null
removes the transition
+ * @param page the page where the transition will be applied. The first page is 1
+ */
+ void setTransition(PdfTransition transition, int page) {
+ PdfDictionary pg = reader.getPageN(page);
+ if (transition == null)
+ pg.remove(PdfName.TRANS);
+ else
+ pg.put(PdfName.TRANS, transition.getTransitionDictionary());
+ markUsed(pg);
+ }
+
+ protected void markUsed(PdfObject obj) {
+ if (append && obj != null) {
+ PRIndirectReference ref = null;
+ if (obj.type() == PdfObject.INDIRECT)
+ ref = (PRIndirectReference)obj;
+ else
+ ref = obj.getIndRef();
+ if (ref != null)
+ marked.put(ref.getNumber(), 1);
+ }
+ }
+
+ protected void markUsed(int num) {
+ if (append)
+ marked.put(num, 1);
+ }
+
+ /**
+ * Getter for property append.
+ * @return Value of property append.
+ */
+ boolean isAppend() {
+ return append;
+ }
+
+ /** Additional-actions defining the actions to be taken in
+ * response to various trigger events affecting the document
+ * as a whole. The actions types allowed are: DOCUMENT_CLOSE
,
+ * WILL_SAVE
, DID_SAVE
, WILL_PRINT
+ * and DID_PRINT
.
+ *
+ * @param actionType the action type
+ * @param action the action to execute in response to the trigger
+ * @throws PdfException on invalid action type
+ */
+ public void setAdditionalAction(PdfName actionType, PdfAction action) throws PdfException {
+ if (!(actionType.equals(DOCUMENT_CLOSE) ||
+ actionType.equals(WILL_SAVE) ||
+ actionType.equals(DID_SAVE) ||
+ actionType.equals(WILL_PRINT) ||
+ actionType.equals(DID_PRINT))) {
+ throw new PdfException("Invalid additional action type: " + actionType.toString());
+ }
+ PdfDictionary aa = (PdfDictionary)PdfReader.getPdfObject(reader.getCatalog().get(PdfName.AA));
+ if (aa == null) {
+ if (action == null)
+ return;
+ aa = new PdfDictionary();
+ reader.getCatalog().put(PdfName.AA, aa);
+ }
+ markUsed(aa);
+ if (action == null)
+ aa.remove(actionType);
+ else
+ aa.put(actionType, action);
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfWriter#setOpenAction(pdftk.com.lowagie.text.pdf.PdfAction)
+ */
+ public void setOpenAction(PdfAction action) {
+ openAction = action;
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfWriter#setOpenAction(java.lang.String)
+ */
+ public void setOpenAction(String name) {
+ throw new UnsupportedOperationException("Open actions by name are not supported.");
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.PdfWriter#setThumbnail(pdftk.com.lowagie.text.Image)
+ */
+ /* ssteward: dropped in 1.44
+ public void setThumbnail(pdftk.com.lowagie.text.Image image) {
+ throw new UnsupportedOperationException("Use PdfStamper.setThumbnail().");
+ }
+
+ void setThumbnail(Image image, int page) throws PdfException, DocumentException {
+ PdfIndirectReference thumb = getImageReference(addDirectImageSimple(image));
+ reader.resetReleasePage();
+ PdfDictionary dic = reader.getPageN(page);
+ dic.put(PdfName.THUMB, thumb);
+ reader.resetReleasePage();
+ }
+ */
+
+ static class PageStamp {
+
+ PdfDictionary pageN;
+ StampContent under;
+ StampContent over;
+ PageResources pageResources;
+
+ PageStamp(PdfStamperImp stamper, PdfReader reader, PdfDictionary pageN) {
+ this.pageN = pageN;
+ pageResources = new PageResources();
+ PdfDictionary resources = (PdfDictionary)PdfReader.getPdfObject(pageN.get(PdfName.RESOURCES));
+ pageResources.setOriginalResources(resources, stamper.namePtr);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfStream.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfStream.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfStream.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,376 @@
+/*
+ * $Id: PdfStream.java,v 1.53 2004/12/14 15:15:59 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+
+import pdftk.com.lowagie.text.DocWriter;
+import pdftk.com.lowagie.text.Document;
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+/**
+ * PdfStream
is the Pdf stream object.
+ *
+ * A stream, like a string, is a sequence of characters. However, an application can
+ * read a small portion of a stream at a time, while a string must be read in its entirety.
+ * For this reason, objects with potentially large amounts of data, such as images and
+ * page descriptions, are represented as streams.
+ * A stream consists of a dictionary that describes a sequence of characters, followed by
+ * the keyword stream , followed by zero or more lines of characters, followed by
+ * the keyword endstream .
+ * All streams must be PdfIndirectObject
s. The stream dictionary must be a direct
+ * object. The keyword stream that follows the stream dictionary should be followed by
+ * a carriage return and linefeed or just a linefeed.
+ * Remark: In this version only the FLATEDECODE-filter is supported.
+ * This object is described in the 'Portable Document Format Reference Manual version 1.7'
+ * section 3.2.7 (page 60-63).
+ *
+ * @see PdfObject
+ * @see PdfDictionary
+ */
+
+public class PdfStream extends PdfDictionary {
+
+ // membervariables
+
+ /**
+ * A possible compression level.
+ * @since 2.1.3
+ */
+ public static final int DEFAULT_COMPRESSION = -1;
+ /**
+ * A possible compression level.
+ * @since 2.1.3
+ */
+ public static final int NO_COMPRESSION = 0;
+ /**
+ * A possible compression level.
+ * @since 2.1.3
+ */
+ public static final int BEST_SPEED = 1;
+ /**
+ * A possible compression level.
+ * @since 2.1.3
+ */
+ public static final int BEST_COMPRESSION = 9;
+
+
+/** is the stream compressed? */
+ protected boolean compressed = false;
+ /**
+ * The level of compression.
+ * @since 2.1.3
+ */
+ protected int compressionLevel = NO_COMPRESSION;
+
+ protected ByteArrayOutputStream streamBytes = null;
+ protected InputStream inputStream;
+ protected PdfIndirectReference ref;
+ protected int inputStreamLength = -1;
+ protected PdfWriter writer;
+ protected int rawLength;
+
+ static final byte STARTSTREAM[] = DocWriter.getISOBytes("\nstream\n"); // ssteward
+ static final byte ENDSTREAM[] = DocWriter.getISOBytes("\nendstream "); // ssteward
+ static final int SIZESTREAM = STARTSTREAM.length + ENDSTREAM.length;
+
+ // constructors
+
+/**
+ * Constructs a PdfStream
-object.
+ *
+ * @param bytes content of the new PdfObject
as an array of byte
.
+ */
+
+ public PdfStream(byte[] bytes) {
+ super();
+ type = STREAM;
+ this.bytes = bytes;
+ rawLength = bytes.length;
+ put(PdfName.LENGTH, new PdfNumber(bytes.length));
+ }
+
+ /**
+ * Creates an efficient stream. No temporary array is ever created. The InputStream
+ * is totally consumed but is not closed. The general usage is:
+ *
+ *
+ * InputStream in = ...;
+ * PdfStream stream = new PdfStream(in, writer);
+ * stream.flateCompress();
+ * writer.addToBody(stream);
+ * stream.writeLength();
+ * in.close();
+ *
+ * @param inputStream the data to write to this stream
+ * @param writer the PdfWriter
for this stream
+ */
+ public PdfStream(InputStream inputStream, PdfWriter writer) {
+ super();
+ type = STREAM;
+ this.inputStream = inputStream;
+ this.writer = writer;
+ ref = writer.getPdfIndirectReference();
+ put(PdfName.LENGTH, ref);
+ }
+
+/**
+ * Constructs a PdfStream
-object.
+ */
+
+ protected PdfStream() {
+ super();
+ type = STREAM;
+ }
+
+ /**
+ * Writes the stream length to the PdfWriter
.
+ *
+ * This method must be called and can only be called if the constructor {@link #PdfStream(InputStream,PdfWriter)}
+ * is used to create the stream.
+ * @throws IOException on error
+ * @see #PdfStream(InputStream,PdfWriter)
+ */
+ public void writeLength() throws IOException {
+ if (inputStream == null)
+ throw new UnsupportedOperationException("writeLength() can only be called in a contructed PdfStream(InputStream,PdfWriter).");
+ if (inputStreamLength == -1)
+ throw new IOException("writeLength() can only be called after output of the stream body.");
+ writer.addToBody(new PdfNumber(inputStreamLength), ref, false);
+ }
+
+ /**
+ * Gets the raw length of the stream.
+ * @return the raw length of the stream
+ */
+ public int getRawLength() {
+ return rawLength;
+ }
+
+ /**
+ * Compresses the stream.
+ */
+ public void flateCompress() {
+ flateCompress(DEFAULT_COMPRESSION);
+ }
+
+ /**
+ * Compresses the stream.
+ * @param compressionLevel the compression level (0 = best speed, 9 = best compression, -1 is default)
+ * @since 2.1.3
+ */
+ public void flateCompress(int compressionLevel) {
+ if (!Document.compress)
+ return;
+ // check if the flateCompress-method has already been
+ if (compressed) {
+ return;
+ }
+ this.compressionLevel = compressionLevel;
+ if (inputStream != null) {
+ compressed = true;
+ return;
+ }
+ // check if a filter already exists
+ PdfObject filter = PdfReader.getPdfObject(get(PdfName.FILTER));
+ if (filter != null) {
+ if (filter.isName()) {
+ if (PdfName.FLATEDECODE.equals(filter))
+ return;
+ }
+ else if (filter.isArray()) {
+ if (((PdfArray) filter).contains(PdfName.FLATEDECODE))
+ return;
+ }
+ else {
+ throw new RuntimeException("Stream could not be compressed: filter is not a name or array.");
+ }
+ }
+ try {
+ // compress
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ Deflater deflater = new Deflater(compressionLevel);
+ DeflaterOutputStream zip = new DeflaterOutputStream(stream, deflater);
+ if (streamBytes != null)
+ streamBytes.writeTo(zip);
+ else
+ zip.write(bytes);
+ zip.close();
+ deflater.end();
+ // update the object
+ streamBytes = stream;
+ bytes = null;
+ put(PdfName.LENGTH, new PdfNumber(streamBytes.size()));
+ if (filter == null) {
+ put(PdfName.FILTER, PdfName.FLATEDECODE);
+ }
+ else {
+ PdfArray filters = new PdfArray(filter);
+ filters.add(PdfName.FLATEDECODE);
+ put(PdfName.FILTER, filters);
+ }
+ compressed = true;
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ }
+
+// public int getStreamLength(PdfWriter writer) {
+// if (dicBytes == null)
+// toPdf(writer);
+// if (streamBytes != null)
+// return streamBytes.size() + dicBytes.length + SIZESTREAM;
+// else
+// return bytes.length + dicBytes.length + SIZESTREAM;
+// }
+
+ protected void superToPdf(PdfWriter writer, OutputStream os) throws IOException {
+ super.toPdf(writer, os);
+ }
+
+ /**
+ * @see com.lowagie.text.pdf.PdfDictionary#toPdf(com.lowagie.text.pdf.PdfWriter, java.io.OutputStream)
+ */
+ public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+ if (inputStream != null && compressed)
+ put(PdfName.FILTER, PdfName.FLATEDECODE);
+ PdfEncryption crypto = null;
+ if (writer != null)
+ crypto = writer.getEncryption();
+ if (crypto != null) {
+ PdfObject filter = get(PdfName.FILTER);
+ if (filter != null) {
+ if (PdfName.CRYPT.equals(filter))
+ crypto = null;
+ else if (filter.isArray()) {
+ PdfArray a = (PdfArray)filter;
+ if (!a.isEmpty() && PdfName.CRYPT.equals(a.getPdfObject(0)))
+ crypto = null;
+ }
+ }
+ }
+ PdfObject nn = get(PdfName.LENGTH);
+ if (crypto != null && nn != null && nn.isNumber()) {
+ int sz = ((PdfNumber)nn).intValue();
+ put(PdfName.LENGTH, new PdfNumber(crypto.calculateStreamSize(sz)));
+ superToPdf(writer, os);
+ put(PdfName.LENGTH, nn);
+ }
+ else
+ superToPdf(writer, os);
+ os.write(STARTSTREAM);
+ if (inputStream != null) {
+ rawLength = 0;
+ DeflaterOutputStream def = null;
+ OutputStreamCounter osc = new OutputStreamCounter(os);
+ OutputStreamEncryption ose = null;
+ OutputStream fout = osc;
+ if (crypto != null && !crypto.isEmbeddedFilesOnly())
+ fout = ose = crypto.getEncryptionStream(fout);
+ Deflater deflater = null;
+ if (compressed) {
+ deflater = new Deflater(compressionLevel);
+ fout = def = new DeflaterOutputStream(fout, deflater, 0x8000);
+ }
+
+ byte buf[] = new byte[4192];
+ while (true) {
+ int n = inputStream.read(buf);
+ if (n <= 0)
+ break;
+ fout.write(buf, 0, n);
+ rawLength += n;
+ }
+ if (def != null) {
+ def.finish();
+ deflater.end();
+ }
+ if (ose != null)
+ ose.finish();
+ inputStreamLength = osc.getCounter();
+ }
+ else {
+ if (crypto != null && !crypto.isEmbeddedFilesOnly()) {
+ byte b[];
+ if (streamBytes != null) {
+ b = crypto.encryptByteArray(streamBytes.toByteArray());
+ }
+ else {
+ b = crypto.encryptByteArray(bytes);
+ }
+ os.write(b);
+ }
+ else {
+ if (streamBytes != null)
+ streamBytes.writeTo(os);
+ else
+ os.write(bytes);
+ }
+ }
+ os.write(ENDSTREAM);
+ }
+
+ /**
+ * Writes the data content to an OutputStream
.
+ * @param os the destination to write to
+ * @throws IOException on error
+ */
+ public void writeContent(OutputStream os) throws IOException {
+ if (streamBytes != null)
+ streamBytes.writeTo(os);
+ else if (bytes != null)
+ os.write(bytes);
+ }
+
+ /**
+ * @see com.lowagie.text.pdf.PdfObject#toString()
+ */
+ public String toString() {
+ if (get(PdfName.TYPE) == null) return "Stream";
+ return "Stream of type: " + get(PdfName.TYPE);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfString.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfString.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfString.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,287 @@
+/*
+ * $Id$
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ * Co-Developer of the code is Sid Steward. Portions created by the Co-Developer
+ * are Copyright (C) 2010 by Sid Steward. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A PdfString
-class is the PDF-equivalent of a JAVA-String
-object.
+ *
+ * A string is a sequence of characters delimited by parenthesis.
+ * If a string is too long to be conveniently placed on a single line, it may
+ * be split across multiple lines by using the backslash character (\) at the
+ * end of a line to indicate that the string continues on the following line.
+ * Within a string, the backslash character is used as an escape to specify
+ * unbalanced parenthesis, non-printing ASCII characters, and the backslash
+ * character itself. Use of the \ddd escape sequence is the preferred
+ * way to represent characters outside the printable ASCII character set.
+ * This object is described in the 'Portable Document Format Reference Manual
+ * version 1.7' section 3.2.3 (page 53-56).
+ *
+ * @see PdfObject
+ * @see BadPdfFormatException
+ */
+public class PdfString extends PdfObject {
+
+ // CLASS VARIABLES
+
+ /** The value of this object. */
+ // these start out *uninitialized*
+ protected String value= null;
+ //
+ protected byte[] originalBytes= null;
+
+ /** The encoding. */
+ // the encoding indicates how to encode the data in the PDF file;
+ // this starts out *uninitialized*
+ // encodings:
+ // null => not set
+ // NOTHING => literal bytes; used with hex output
+ // TEXT_UNICODE => UTF-16
+ // TEXT_PDFDOCENCODING => PdfDoc encoding
+ //
+ protected String encoding= null;
+
+ protected int objNum = 0;
+
+ protected int objGen = 0;
+
+ protected boolean hexWriting = false;
+
+ // CONSTRUCTORS
+
+ /**
+ * Constructs an empty PdfString
-object.
+ */
+ public PdfString() {
+ super(STRING);
+ }
+
+ /**
+ * Constructs a PdfString
-object containing a string in the
+ * standard encoding TEXT_PDFDOCENCODING
.
+ *
+ * @param value the content of the string
+ */
+ public PdfString(String value) {
+ super(STRING);
+ this.value = value;
+ // guess the encoding
+ }
+
+ /**
+ * Constructs a PdfString
-object containing a string in the
+ * specified encoding.
+ *
+ * @param value the content of the string
+ * @param encoding an encoding
+ */
+
+ // ssteward: rewrite for pdftk 1.45
+ public PdfString(String value, String encoding) {
+ super(STRING);
+ this.value = value;
+ this.encoding = encoding;
+ }
+
+ /**
+ * Constructs a PdfString
-object.
+ *
+ * @param bytes an array of byte
+ */
+ // ssteward: rewrite for pdftk 1.45
+ public PdfString(byte[] bytes) {
+ super(STRING);
+ this.bytes = bytes;
+ // guess the encoding
+ }
+
+ // construct from bytes, not value;
+ // ssteward: rewrite for pdftk 1.45
+ public PdfString(byte[] bytes, String encoding) {
+ super(STRING);
+ this.bytes = bytes;
+ this.encoding = encoding;
+ }
+
+ // methods overriding some methods in PdfObject
+
+ /**
+ * Writes the PDF representation of this PdfString
as an array
+ * of byte
to the specified OutputStream
.
+ *
+ * @param writer for backwards compatibility
+ * @param os The OutputStream
to write the bytes to.
+ */
+ public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+ byte b[] = getBytes();
+ PdfEncryption crypto = null;
+ if (writer != null)
+ crypto = writer.getEncryption();
+ if (crypto != null && !crypto.isEmbeddedFilesOnly())
+ b = crypto.encryptByteArray(b);
+ if (hexWriting) {
+ ByteBuffer buf = new ByteBuffer();
+ buf.append('<');
+ int len = b.length;
+ for (int k = 0; k < len; ++k)
+ buf.appendHex(b[k]);
+ buf.append('>');
+ os.write(buf.toByteArray());
+ }
+ else
+ os.write(PdfContentByte.escapeString(b));
+ }
+
+ /**
+ * Returns the String
value of this PdfString
-object.
+ *
+ * @return A String
+ */
+ public String toString() {
+ return getValue();
+ }
+
+ // sets bytes and encoding based on value, if necessary
+ // ssteward: rewrite for pdftk 1.45
+ public byte[] getBytes() {
+ if( bytes== null && value!= null ) { // convert from value
+ if( encoding== null ) {
+ if( PdfEncodings.isPdfDocEncoding( value ) ) {
+ encoding= TEXT_PDFDOCENCODING;
+ }
+ else {
+ encoding= TEXT_UNICODE;
+ }
+ }
+ bytes= PdfEncodings.convertToBytes( value, encoding );
+ }
+ return bytes;
+ }
+
+ // ssteward: added for pdftk 1.45
+ private String getValue() {
+ if( value== null && bytes!= null ) { // convert from bytes
+ if( encoding== null ) {
+ if( isUnicode( bytes ) ) {
+ encoding= TEXT_UNICODE;
+ }
+ else {
+ encoding= TEXT_PDFDOCENCODING;
+ }
+ }
+ value= PdfEncodings.convertToString( bytes, encoding );
+ }
+ return value;
+ }
+
+ // other methods
+
+ /**
+ * Returns the Unicode String
value of this
+ * PdfString
-object.
+ *
+ * @return A String
+ */
+ // ssteward: rewrite for pdftk 1.45
+ public String toUnicodeString() {
+ return getValue();
+ }
+
+ /**
+ * Gets the encoding of this string.
+ *
+ * @return a String
+ */
+ public String getEncoding() {
+ return encoding;
+ }
+
+ void setObjNum(int objNum, int objGen) {
+ this.objNum = objNum;
+ this.objGen = objGen;
+ }
+
+ /**
+ * Decrypt an encrypted PdfString
+ */
+ // ssteward: rewrite for pdftk 1.45
+ void decrypt(PdfReader reader) {
+ PdfEncryption decrypt = reader.getDecrypt();
+ if (decrypt != null) {
+
+ getBytes();
+ originalBytes= new byte[ bytes.length ];
+ System.arraycopy( bytes, 0, originalBytes, 0, bytes.length );
+
+ decrypt.setHashKey(objNum, objGen);
+ bytes = decrypt.decryptByteArray(bytes);
+
+ // reset
+ value = null;
+ encoding = null;
+ }
+ }
+
+
+ // ssteward: rewrite for pdftk 1.45
+ public byte[] getOriginalBytes() {
+ if( originalBytes!= null ) {
+ return originalBytes;
+ }
+ return getBytes();
+ }
+
+ public PdfString setHexWriting(boolean hexWriting) {
+ this.hexWriting = hexWriting;
+ return this;
+ }
+
+ public boolean isHexWriting() {
+ return hexWriting;
+ }
+
+ // ssteward: rewrite for pdftk 1.45
+ public static boolean isUnicode( byte[] bb ) {
+ return( bb.length >= 2 && bb[0] == (byte)254 && bb[1] == (byte)255 );
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfStructureElement.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfStructureElement.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfStructureElement.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfStructureElement.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,121 @@
+/*
+ * $Id: PRTokeniser.java,v 1.15 2002/06/20 13:30:25 blowagie Exp $
+ *
+ * Copyright 2005 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+//import java.util.ArrayList;
+/**
+ * This is a node in a document logical structure. It may contain a mark point or it may contain
+ * other nodes.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfStructureElement extends PdfDictionary {
+
+ /**
+ * Holds value of property kids.
+ */
+ private PdfStructureElement parent;
+ private PdfStructureTreeRoot top;
+
+ /**
+ * Holds value of property reference.
+ */
+ private PdfIndirectReference reference;
+
+ /**
+ * Creates a new instance of PdfStructureElement.
+ * @param parent the parent of this node
+ * @param structureType the type of structure. It may be a standard type or a user type mapped by the role map
+ */
+ public PdfStructureElement(PdfStructureElement parent, PdfName structureType) {
+ top = parent.top;
+ init(parent, structureType);
+ this.parent = parent;
+ put(PdfName.P, parent.reference);
+ }
+
+ /**
+ * Creates a new instance of PdfStructureElement.
+ * @param parent the parent of this node
+ * @param structureType the type of structure. It may be a standard type or a user type mapped by the role map
+ */
+ public PdfStructureElement(PdfStructureTreeRoot parent, PdfName structureType) {
+ top = parent;
+ init(parent, structureType);
+ put(PdfName.P, parent.getReference());
+ }
+
+ private void init(PdfDictionary parent, PdfName structureType) {
+ PdfObject kido = parent.get(PdfName.K);
+ PdfArray kids = null;
+ if (kido != null && !kido.isArray())
+ throw new IllegalArgumentException("The parent has already another function.");
+ if (kido == null) {
+ kids = new PdfArray();
+ parent.put(PdfName.K, kids);
+ }
+ else
+ kids = (PdfArray)kido;
+ kids.add(this);
+ put(PdfName.S, structureType);
+ reference = top.getWriter().getPdfIndirectReference();
+ }
+
+ /**
+ * Gets the parent of this node.
+ * @return the parent of this node
+ */
+ public PdfDictionary getParent() {
+ return parent;
+ }
+
+ void setPageMark(int page, int mark) {
+ if (mark >= 0)
+ put(PdfName.K, new PdfNumber(mark));
+ top.setPageMark(page, reference);
+ }
+
+ /**
+ * Gets the reference this object will be written to.
+ * @return the reference this object will be written to
+ */
+ public PdfIndirectReference getReference() {
+ return this.reference;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfStructureTreeRoot.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfStructureTreeRoot.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfStructureTreeRoot.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfStructureTreeRoot.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,136 @@
+/*
+ * $Id: PRTokeniser.java,v 1.15 2002/06/20 13:30:25 blowagie Exp $
+ *
+ * Copyright 2005 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.io.IOException;
+
+/**
+ * The structure tree root corresponds to the highest hierarchy level in a tagged PDF.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfStructureTreeRoot extends PdfDictionary {
+
+ private HashMap parentTree = new HashMap();
+ private PdfIndirectReference reference;
+
+ /**
+ * Holds value of property writer.
+ */
+ private PdfWriter writer;
+
+ /** Creates a new instance of PdfStructureTreeRoot */
+ PdfStructureTreeRoot(PdfWriter writer) {
+ super(PdfName.STRUCTTREEROOT);
+ this.writer = writer;
+ reference = writer.getPdfIndirectReference();
+ }
+
+ /**
+ * Maps the user tags to the standard tags. The mapping will allow a standard application to make some sense of the tagged
+ * document whatever the user tags may be.
+ * @param used the user tag
+ * @param standard the standard tag
+ */
+ public void mapRole(PdfName used, PdfName standard) {
+ PdfDictionary rm = (PdfDictionary)get(PdfName.ROLEMAP);
+ if (rm == null) {
+ rm = new PdfDictionary();
+ put(PdfName.ROLEMAP, rm);
+ }
+ rm.put(used, standard);
+ }
+
+ /**
+ * Gets the writer.
+ * @return the writer
+ */
+ public PdfWriter getWriter() {
+ return this.writer;
+ }
+
+ /**
+ * Gets the reference this object will be written to.
+ * @return the reference this object will be written to
+ */
+ public PdfIndirectReference getReference() {
+ return this.reference;
+ }
+
+ void setPageMark(int page, PdfIndirectReference struc) {
+ Integer i = new Integer(page);
+ PdfArray ar = (PdfArray)parentTree.get(i);
+ if (ar == null) {
+ ar = new PdfArray();
+ parentTree.put(i, ar);
+ }
+ ar.add(struc);
+ }
+
+ private void nodeProcess(PdfDictionary struc, PdfIndirectReference reference) throws IOException {
+ PdfObject obj = struc.get(PdfName.K);
+ if (obj != null && obj.isArray() && !((PdfObject)((PdfArray)obj).getArrayList().get(0)).isNumber()) {
+ PdfArray ar = (PdfArray)obj;
+ ArrayList a = ar.getArrayList();
+ for (int k = 0; k < a.size(); ++k) {
+ PdfStructureElement e = (PdfStructureElement)a.get(k);
+ a.set(k, e.getReference());
+ nodeProcess(e, e.getReference());
+ }
+ }
+ if (reference != null)
+ writer.addToBody(struc, reference);
+ }
+
+ void buildTree() throws IOException {
+ HashMap numTree = new HashMap();
+ for (Iterator it = parentTree.keySet().iterator(); it.hasNext();) {
+ Integer i = (Integer)it.next();
+ PdfArray ar = (PdfArray)parentTree.get(i);
+ numTree.put(i, writer.addToBody(ar).getIndirectReference());
+ }
+ PdfDictionary dicTree = PdfNumberTree.writeTree(numTree, writer);
+ if (dicTree != null)
+ put(PdfName.PARENTTREE, writer.addToBody(dicTree).getIndirectReference());
+
+ nodeProcess(this, reference);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfTemplate.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfTemplate.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfTemplate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfTemplate.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,257 @@
+/*
+ * $Id: PdfTemplate.java,v 1.36 2003/05/02 09:01:28 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+import java.io.IOException;
+
+import pdftk.com.lowagie.text.Rectangle;
+
+/**
+ * Implements the form XObject.
+ */
+
+public class PdfTemplate extends PdfContentByte {
+ public static final int TYPE_TEMPLATE = 1;
+ public static final int TYPE_IMPORTED = 2;
+ public static final int TYPE_PATTERN = 3;
+ protected int type;
+ /** The indirect reference to this template */
+ protected PdfIndirectReference thisReference;
+
+ /** The resources used by this template */
+ protected PageResources pageResources;
+
+
+ /** The bounding box of this template */
+ protected Rectangle bBox = new Rectangle(0, 0);
+
+ protected PdfArray matrix;
+
+ protected PdfTransparencyGroup group;
+
+ protected PdfOCG layer;
+
+ /**
+ *Creates a PdfTemplate
.
+ */
+
+ protected PdfTemplate() {
+ super(null);
+ type = TYPE_TEMPLATE;
+ }
+
+ /**
+ * Creates new PdfTemplate
+ *
+ * @param wr the PdfWriter
+ */
+
+ PdfTemplate(PdfWriter wr) {
+ super(wr);
+ type = TYPE_TEMPLATE;
+ pageResources = new PageResources();
+ pageResources.addDefaultColor(wr.getDefaultColorspace());
+ thisReference = writer.getPdfIndirectReference();
+ }
+
+ /**
+ * Sets the bounding width of this template.
+ *
+ * @param width the bounding width
+ */
+
+ public void setWidth(float width) {
+ bBox.setLeft(0);
+ bBox.setRight(width);
+ }
+
+ /**
+ * Sets the bounding heigth of this template.
+ *
+ * @param height the bounding height
+ */
+
+ public void setHeight(float height) {
+ bBox.setBottom(0);
+ bBox.setTop(height);
+ }
+
+ /**
+ * Gets the bounding width of this template.
+ *
+ * @return width the bounding width
+ */
+ public float getWidth() {
+ return bBox.width();
+ }
+
+ /**
+ * Gets the bounding heigth of this template.
+ *
+ * @return heigth the bounding height
+ */
+
+ public float getHeight() {
+ return bBox.height();
+ }
+
+ public Rectangle getBoundingBox() {
+ return bBox;
+ }
+
+ public void setBoundingBox(Rectangle bBox) {
+ this.bBox = bBox;
+ }
+
+ /**
+ * Sets the layer this template belongs to.
+ * @param layer the layer this template belongs to
+ */
+ public void setLayer(PdfOCG layer) {
+ this.layer = layer;
+ }
+
+ /**
+ * Gets the layer this template belongs to.
+ * @return the layer this template belongs to or null
for no layer defined
+ */
+ public PdfOCG getLayer() {
+ return layer;
+ }
+
+ public void setMatrix(float a, float b, float c, float d, float e, float f) {
+ matrix = new PdfArray();
+ matrix.add(new PdfNumber(a));
+ matrix.add(new PdfNumber(b));
+ matrix.add(new PdfNumber(c));
+ matrix.add(new PdfNumber(d));
+ matrix.add(new PdfNumber(e));
+ matrix.add(new PdfNumber(f));
+ }
+
+ PdfArray getMatrix() {
+ return matrix;
+ }
+
+ /**
+ * Gets the indirect reference to this template.
+ *
+ * @return the indirect reference to this template
+ */
+
+ PdfIndirectReference getIndirectReference() {
+ return thisReference;
+ }
+
+ public void beginVariableText() {
+ content.append("/Tx BMC ");
+ }
+
+ public void endVariableText() {
+ content.append("EMC ");
+ }
+
+ /**
+ * Constructs the resources used by this template.
+ *
+ * @return the resources used by this template
+ */
+
+ PdfObject getResources() {
+ return getPageResources().getResources();
+ }
+
+ /**
+ * Gets the stream representing this template.
+ *
+ * @return the stream representing this template
+ */
+
+ PdfStream getFormXObject() throws IOException {
+ return new PdfFormXObject(this);
+ }
+
+ /**
+ * Gets a duplicate of this PdfTemplate
. All
+ * the members are copied by reference but the buffer stays different.
+ * @return a copy of this PdfTemplate
+ */
+
+ public PdfContentByte getDuplicate() {
+ PdfTemplate tpl = new PdfTemplate();
+ tpl.writer = writer;
+ tpl.pdf = pdf;
+ tpl.thisReference = thisReference;
+ tpl.pageResources = pageResources;
+ tpl.bBox = new Rectangle(bBox);
+ tpl.group = group;
+ tpl.layer = layer;
+ if (matrix != null) {
+ tpl.matrix = new PdfArray(matrix);
+ }
+ tpl.separator = separator;
+ return tpl;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ PageResources getPageResources() {
+ return pageResources;
+ }
+
+ /** Getter for property group.
+ * @return Value of property group.
+ *
+ */
+ public PdfTransparencyGroup getGroup() {
+ return this.group;
+ }
+
+ /** Setter for property group.
+ * @param group New value of property group.
+ *
+ */
+ public void setGroup(PdfTransparencyGroup group) {
+ this.group = group;
+ }
+
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfTextArray.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfTextArray.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfTextArray.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfTextArray.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,89 @@
+/*
+ * $Id: PdfTextArray.java,v 1.24 2002/07/09 11:28:24 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.ArrayList;
+
+/**
+ * PdfTextArray
defines an array with displacements and PdfString
-objects.
+ *
+ * A TextArray
is used with the operator TJ in PdfText
.
+ * The first object in this array has to be a PdfString
;
+ * see reference manual version 1.3 section 8.7.5, pages 346-347.
+ */
+
+public class PdfTextArray{
+ ArrayList arrayList = new ArrayList();
+ // constructors
+
+
+ public PdfTextArray(String str) {
+ arrayList.add(str);
+ }
+
+ public PdfTextArray() {
+ }
+
+/**
+ * Adds a PdfNumber
to the PdfArray
.
+ *
+ * @param number displacement of the string
+ */
+
+ public void add(PdfNumber number)
+ {
+ arrayList.add(new Float(number.doubleValue()));
+ }
+
+ public void add(float number)
+ {
+ arrayList.add(new Float(number));
+ }
+
+ public void add(String str)
+ {
+ arrayList.add(str);
+ }
+
+ ArrayList getArrayList() {
+ return arrayList;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfTransition.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfTransition.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfTransition.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfTransition.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2002 by Josselin PUJO.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+public class PdfTransition {
+ /**
+ * Out Vertical Split
+ */
+ public static final int SPLITVOUT = 1;
+ /**
+ * Out Horizontal Split
+ */
+ public static final int SPLITHOUT = 2;
+ /**
+ * In Vertical Split
+ */
+ public static final int SPLITVIN = 3;
+ /**
+ * IN Horizontal Split
+ */
+ public static final int SPLITHIN = 4;
+ /**
+ * Vertical Blinds
+ */
+ public static final int BLINDV = 5;
+ /**
+ * Vertical Blinds
+ */
+ public static final int BLINDH = 6;
+ /**
+ * Inward Box
+ */
+ public static final int INBOX = 7;
+ /**
+ * Outward Box
+ */
+ public static final int OUTBOX = 8;
+ /**
+ * Left-Right Wipe
+ */
+ public static final int LRWIPE = 9;
+ /**
+ * Right-Left Wipe
+ */
+ public static final int RLWIPE = 10;
+ /**
+ * Bottom-Top Wipe
+ */
+ public static final int BTWIPE = 11;
+ /**
+ * Top-Bottom Wipe
+ */
+ public static final int TBWIPE = 12;
+ /**
+ * Dissolve
+ */
+ public static final int DISSOLVE = 13;
+ /**
+ * Left-Right Glitter
+ */
+ public static final int LRGLITTER = 14;
+ /**
+ * Top-Bottom Glitter
+ */
+ public static final int TBGLITTER = 15;
+ /**
+ * Diagonal Glitter
+ */
+ public static final int DGLITTER = 16;
+
+ /**
+ * duration of the transition effect
+ */
+ protected int duration;
+ /**
+ * type of the transition effect
+ */
+ protected int type;
+
+ /**
+ * Constructs a Transition
.
+ *
+ */
+ public PdfTransition() {
+ this(BLINDH);
+ }
+
+ /**
+ * Constructs a Transition
.
+ *
+ *@param type type of the transition effect
+ */
+ public PdfTransition(int type) {
+ this(type,1);
+ }
+
+ /**
+ * Constructs a Transition
.
+ *
+ *@param type type of the transition effect
+ *@param duration duration of the transition effect
+ */
+ public PdfTransition(int type, int duration) {
+ this.duration = duration;
+ this.type = type;
+ }
+
+
+ public int getDuration() {
+ return duration;
+ }
+
+
+ public int getType() {
+ return type;
+ }
+
+ public PdfDictionary getTransitionDictionary() {
+ PdfDictionary trans = new PdfDictionary(PdfName.TRANS);
+ switch (type) {
+ case SPLITVOUT:
+ trans.put(PdfName.S,PdfName.SPLIT);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DM,PdfName.V);
+ trans.put(PdfName.M,PdfName.O);
+ break;
+ case SPLITHOUT:
+ trans.put(PdfName.S,PdfName.SPLIT);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DM,PdfName.H);
+ trans.put(PdfName.M,PdfName.O);
+ break;
+ case SPLITVIN:
+ trans.put(PdfName.S,PdfName.SPLIT);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DM,PdfName.V);
+ trans.put(PdfName.M,PdfName.I);
+ break;
+ case SPLITHIN:
+ trans.put(PdfName.S,PdfName.SPLIT);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DM,PdfName.H);
+ trans.put(PdfName.M,PdfName.I);
+ break;
+ case BLINDV:
+ trans.put(PdfName.S,PdfName.BLINDS);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DM,PdfName.V);
+ break;
+ case BLINDH:
+ trans.put(PdfName.S,PdfName.BLINDS);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DM,PdfName.H);
+ break;
+ case INBOX:
+ trans.put(PdfName.S,PdfName.BOX);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.M,PdfName.I);
+ break;
+ case OUTBOX:
+ trans.put(PdfName.S,PdfName.BOX);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.M,PdfName.O);
+ break;
+ case LRWIPE:
+ trans.put(PdfName.S,PdfName.WIPE);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DI,new PdfNumber(0));
+ break;
+ case RLWIPE:
+ trans.put(PdfName.S,PdfName.WIPE);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DI,new PdfNumber(180));
+ break;
+ case BTWIPE:
+ trans.put(PdfName.S,PdfName.WIPE);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DI,new PdfNumber(90));
+ break;
+ case TBWIPE:
+ trans.put(PdfName.S,PdfName.WIPE);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DI,new PdfNumber(270));
+ break;
+ case DISSOLVE:
+ trans.put(PdfName.S,PdfName.DISSOLVE);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ break;
+ case LRGLITTER:
+ trans.put(PdfName.S,PdfName.GLITTER);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DI,new PdfNumber(0));
+ break;
+ case TBGLITTER:
+ trans.put(PdfName.S,PdfName.GLITTER);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DI,new PdfNumber(270));
+ break;
+ case DGLITTER:
+ trans.put(PdfName.S,PdfName.GLITTER);
+ trans.put(PdfName.D,new PdfNumber(duration));
+ trans.put(PdfName.DI,new PdfNumber(315));
+ break;
+ }
+ return trans;
+ }
+}
+
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfTransparencyGroup.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfTransparencyGroup.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfTransparencyGroup.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfTransparencyGroup.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+/** The transparency group dictionary.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class PdfTransparencyGroup extends PdfDictionary {
+
+ /**
+ * Constructs a transparencyGroup.
+ */
+ public PdfTransparencyGroup() {
+ super();
+ put(PdfName.S, PdfName.TRANSPARENCY);
+ }
+
+ /**
+ * Determining the initial backdrop against which its stack is composited.
+ * @param isolated
+ */
+ public void setIsolated(boolean isolated) {
+ if (isolated)
+ put(PdfName.I, PdfBoolean.PDFTRUE);
+ else
+ remove(PdfName.I);
+ }
+
+ /**
+ * Determining whether the objects within the stack are composited with one another or only with the group's backdrop.
+ * @param knockout
+ */
+ public void setKnockout(boolean knockout) {
+ if (knockout)
+ put(PdfName.K, PdfBoolean.PDFTRUE);
+ else
+ remove(PdfName.K);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfWriter.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfWriter.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfWriter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfWriter.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,2801 @@
+/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ * $Id: PdfWriter.java,v 1.104 2005/09/10 10:52:41 psoares33 Exp $
+ * $Name: $
+ *
+ * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.HashSet;
+
+import pdftk.com.lowagie.text.DocListener;
+import pdftk.com.lowagie.text.DocWriter;
+import pdftk.com.lowagie.text.Document;
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.ExceptionConverter;
+// import pdftk.com.lowagie.text.Image; // ssteward: dropped in 1.44
+// import pdftk.com.lowagie.text.ImgWMF; // ssteward: dropped in 1.44
+import pdftk.com.lowagie.text.Rectangle;
+// import pdftk.com.lowagie.text.Table; ssteward: dropped in 1.44
+// import pdftk.com.lowagie.text.ImgPostscript; ssteward: dropped in 1.44
+
+/**
+ * A DocWriter
class for PDF.
+ *
+ * When this PdfWriter
is added
+ * to a certain PdfDocument
, the PDF representation of every Element
+ * added to this Document will be written to the outputstream.
+ */
+
+public class PdfWriter extends DocWriter {
+
+ /**
+ * The highest generation number possible.
+ * @since iText 2.1.6
+ */
+ public static final int GENERATION_MAX = 65535;
+
+ // inner classes
+
+ /**
+ * This class generates the structure of a PDF document.
+ *
+ * This class covers the third section of Chapter 5 in the 'Portable Document Format
+ * Reference Manual version 1.3' (page 55-60). It contains the body of a PDF document
+ * (section 5.14) and it can also generate a Cross-reference Table (section 5.15).
+ *
+ * @see PdfWriter
+ * @see PdfObject
+ * @see PdfIndirectObject
+ */
+
+ public static class PdfBody {
+
+ // inner classes
+
+ /**
+ * PdfCrossReference
is an entry in the PDF Cross-Reference table.
+ */
+
+ static class PdfCrossReference implements Comparable {
+
+ // membervariables
+ private int type;
+
+ /** Byte offset in the PDF file. */
+ private int offset;
+
+ private int refnum;
+ /** generation of the object. */
+ private int generation;
+
+ // constructors
+ /**
+ * Constructs a cross-reference element for a PdfIndirectObject.
+ * @param refnum
+ * @param offset byte offset of the object
+ * @param generation generationnumber of the object
+ */
+
+ PdfCrossReference(int refnum, int offset, int generation) {
+ type = 0;
+ this.offset = offset;
+ this.refnum = refnum;
+ this.generation = generation;
+ }
+
+ /**
+ * Constructs a cross-reference element for a PdfIndirectObject.
+ * @param refnum
+ * @param offset byte offset of the object
+ */
+
+ PdfCrossReference(int refnum, int offset) {
+ type = 1;
+ this.offset = offset;
+ this.refnum = refnum;
+ this.generation = 0;
+ }
+
+ PdfCrossReference(int type, int refnum, int offset, int generation) {
+ this.type = type;
+ this.offset = offset;
+ this.refnum = refnum;
+ this.generation = generation;
+ }
+
+ int getRefnum() {
+ return refnum;
+ }
+
+ /**
+ * Returns the PDF representation of this PdfObject
.
+ * @param os
+ * @throws IOException
+ */
+
+ public void toPdf(OutputStream os) throws IOException {
+ // This code makes it more difficult to port the lib to JDK1.1.x:
+ // StringBuffer off = new StringBuffer("0000000000").append(offset);
+ // off.delete(0, off.length() - 10);
+ // StringBuffer gen = new StringBuffer("00000").append(generation);
+ // gen.delete(0, gen.length() - 5);
+ // so it was changed into this:
+ String s = "0000000000" + offset;
+ StringBuffer off = new StringBuffer(s.substring(s.length() - 10));
+ s = "00000" + generation;
+ String gen = s.substring(s.length() - 5);
+ if (generation == GENERATION_MAX) {
+ os.write(getISOBytes(off.append(' ').append(gen).append(" f \n").toString()));
+ }
+ else
+ os.write(getISOBytes(off.append(' ').append(gen).append(" n \n").toString()));
+ }
+
+ /**
+ * Writes PDF syntax to the OutputStream
+ * @param midSize
+ * @param os
+ * @throws IOException
+ */
+ public void toPdf(int midSize, OutputStream os) throws IOException {
+ os.write((byte)type);
+ while (--midSize >= 0)
+ os.write((byte)((offset >>> (8 * midSize)) & 0xff));
+ os.write((byte)((generation >>> 8) & 0xff));
+ os.write((byte)(generation & 0xff));
+ }
+
+ /**
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(Object o) {
+ PdfCrossReference other = (PdfCrossReference)o;
+ return (refnum < other.refnum ? -1 : (refnum==other.refnum ? 0 : 1));
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof PdfCrossReference) {
+ PdfCrossReference other = (PdfCrossReference)obj;
+ return (refnum == other.refnum);
+ }
+ else
+ return false;
+ }
+
+ }
+
+ // membervariables
+
+ /** array containing the cross-reference table of the normal objects. */
+ private TreeSet xrefs;
+ private int refnum;
+ /** the current byteposition in the body. */
+ private int position;
+ private PdfWriter writer;
+ // constructors
+
+ /**
+ * Constructs a new PdfBody
.
+ * @param writer
+ */
+ PdfBody(PdfWriter writer) {
+ xrefs = new TreeSet();
+ xrefs.add(new PdfCrossReference(0, 0, GENERATION_MAX));
+ position = writer.getOs().getCounter();
+ refnum = 1;
+ this.writer = writer;
+ }
+
+ void setRefnum(int refnum) {
+ this.refnum = refnum;
+ }
+
+ // methods
+
+ private static final int OBJSINSTREAM = 200;
+
+ private ByteBuffer index;
+ private ByteBuffer streamObjects;
+ private int currentObjNum;
+ private int numObj = 0;
+
+ private PdfWriter.PdfBody.PdfCrossReference addToObjStm(PdfObject obj, int nObj) throws IOException {
+ if (numObj >= OBJSINSTREAM)
+ flushObjStm();
+ if (index == null) {
+ index = new ByteBuffer();
+ streamObjects = new ByteBuffer();
+ currentObjNum = getIndirectReferenceNumber();
+ numObj = 0;
+ }
+ int p = streamObjects.size();
+ int idx = numObj++;
+ PdfEncryption enc = writer.crypto;
+ writer.crypto = null;
+ obj.toPdf(writer, streamObjects);
+ writer.crypto = enc;
+ streamObjects.append(' ');
+ index.append(nObj).append(' ').append(p).append(' ');
+ return new PdfWriter.PdfBody.PdfCrossReference(2, nObj, currentObjNum, idx);
+ }
+
+ private void flushObjStm() throws IOException {
+ if (numObj == 0)
+ return;
+ int first = index.size();
+ index.append(streamObjects);
+ PdfStream stream = new PdfStream(index.toByteArray());
+ stream.flateCompress();
+ stream.put(PdfName.TYPE, PdfName.OBJSTM);
+ stream.put(PdfName.N, new PdfNumber(numObj));
+ stream.put(PdfName.FIRST, new PdfNumber(first));
+ add(stream, currentObjNum);
+ index = null;
+ streamObjects = null;
+ numObj = 0;
+ }
+
+ /**
+ * Adds a PdfObject
to the body.
+ *
+ * This methods creates a PdfIndirectObject
with a
+ * certain number, containing the given PdfObject
.
+ * It also adds a PdfCrossReference
for this object
+ * to an ArrayList
that will be used to build the
+ * Cross-reference Table.
+ *
+ * @param object a PdfObject
+ * @return a PdfIndirectObject
+ * @throws IOException
+ */
+
+ PdfIndirectObject add(PdfObject object) throws IOException {
+ return add(object, getIndirectReferenceNumber());
+ }
+
+ PdfIndirectObject add(PdfObject object, boolean inObjStm) throws IOException {
+ return add(object, getIndirectReferenceNumber(), inObjStm);
+ }
+
+ /**
+ * Gets a PdfIndirectReference for an object that will be created in the future.
+ * @return a PdfIndirectReference
+ */
+
+ PdfIndirectReference getPdfIndirectReference() {
+ return new PdfIndirectReference( 0, getIndirectReferenceNumber() );
+ }
+
+ int getIndirectReferenceNumber() {
+ int n = refnum++;
+ xrefs.add(new PdfCrossReference(n, 0, GENERATION_MAX));
+ return n;
+ }
+
+ /**
+ * Adds a PdfObject
to the body given an already existing
+ * PdfIndirectReference.
+ *
+ * This methods creates a PdfIndirectObject
with the number given by
+ * ref
, containing the given PdfObject
.
+ * It also adds a PdfCrossReference
for this object
+ * to an ArrayList
that will be used to build the
+ * Cross-reference Table.
+ *
+ * @param object a PdfObject
+ * @param ref a PdfIndirectReference
+ * @return a PdfIndirectObject
+ * @throws IOException
+ */
+
+ PdfIndirectObject add(PdfObject object, PdfIndirectReference ref) throws IOException {
+ return add(object, ref.getNumber());
+ }
+
+ PdfIndirectObject add(PdfObject object, PdfIndirectReference ref, boolean inObjStm) throws IOException {
+ return add(object, ref.getNumber(), inObjStm);
+ }
+
+ PdfIndirectObject add(PdfObject object, int refNumber) throws IOException {
+ return add(object, refNumber, true); // to false
+ }
+
+ PdfIndirectObject add(PdfObject object, int refNumber, boolean inObjStm) throws IOException {
+ if (inObjStm && object.canBeInObjStm() && writer.isFullCompression()) {
+ PdfCrossReference pxref = addToObjStm(object, refNumber);
+ PdfIndirectObject indirect = new PdfIndirectObject(refNumber, object, writer);
+ if (!xrefs.add(pxref)) {
+ xrefs.remove(pxref);
+ xrefs.add(pxref);
+ }
+ return indirect;
+ }
+ else {
+ PdfIndirectObject indirect = new PdfIndirectObject(refNumber, object, writer);
+ writer.getOs().write('\n'); // ssteward: for pretty pdf
+ PdfCrossReference pxref = new PdfCrossReference(refNumber, position+ 1); // ssteward: +1 for newline
+ if (!xrefs.add(pxref)) {
+ xrefs.remove(pxref);
+ xrefs.add(pxref);
+ }
+ indirect.writeTo(writer.getOs());
+ position = writer.getOs().getCounter();
+ return indirect;
+ }
+ }
+
+ /**
+ * Adds a PdfResources
object to the body.
+ *
+ * @param object the PdfResources
+ * @return a PdfIndirectObject
+ */
+
+// PdfIndirectObject add(PdfResources object) {
+// return add(object);
+// }
+
+ /**
+ * Adds a PdfPages
object to the body.
+ *
+ * @param object the root of the document
+ * @return a PdfIndirectObject
+ */
+
+// PdfIndirectObject add(PdfPages object) throws IOException {
+// PdfIndirectObject indirect = new PdfIndirectObject(PdfWriter.ROOT, object, writer);
+// rootOffset = position;
+// indirect.writeTo(writer.getOs());
+// position = writer.getOs().getCounter();
+// return indirect;
+// }
+
+ /**
+ * Returns the offset of the Cross-Reference table.
+ *
+ * @return an offset
+ */
+
+ int offset() {
+ return position;
+ }
+
+ /**
+ * Returns the total number of objects contained in the CrossReferenceTable of this Body
.
+ *
+ * @return a number of objects
+ */
+
+ int size() {
+ return Math.max(((PdfCrossReference)xrefs.last()).getRefnum() + 1, refnum);
+ }
+
+ /**
+ * Returns the CrossReferenceTable of the Body
.
+ * @param os
+ * @param root
+ * @param info
+ * @param encryption
+ * @param fileID
+ * @param prevxref
+ * @throws IOException
+ */
+
+ void writeCrossReferenceTable(OutputStream os, PdfIndirectReference root, PdfIndirectReference info, PdfIndirectReference encryption, PdfObject fileID, int prevxref) throws IOException {
+ int refNumber = 0;
+ if (writer.isFullCompression()) {
+ flushObjStm();
+ refNumber = getIndirectReferenceNumber();
+ xrefs.add(new PdfCrossReference(refNumber, position));
+ }
+ PdfCrossReference entry = (PdfCrossReference)xrefs.first();
+ int first = entry.getRefnum();
+ int len = 0;
+ ArrayList sections = new ArrayList();
+ for (Iterator i = xrefs.iterator(); i.hasNext(); ) {
+ entry = (PdfCrossReference)i.next();
+ if (first + len == entry.getRefnum())
+ ++len;
+ else {
+ sections.add(new Integer(first));
+ sections.add(new Integer(len));
+ first = entry.getRefnum();
+ len = 1;
+ }
+ }
+ sections.add(new Integer(first));
+ sections.add(new Integer(len));
+ if (writer.isFullCompression()) {
+ int mid = 4;
+ int mask = 0xff000000;
+ for (; mid > 1; --mid) {
+ if ((mask & position) != 0)
+ break;
+ mask >>>= 8;
+ }
+ ByteBuffer buf = new ByteBuffer();
+
+ for (Iterator i = xrefs.iterator(); i.hasNext(); ) {
+ entry = (PdfCrossReference) i.next();
+ entry.toPdf(mid, buf);
+ }
+ PdfStream xr = new PdfStream(buf.toByteArray());
+ buf = null;
+ xr.flateCompress();
+ xr.put(PdfName.SIZE, new PdfNumber(size()));
+ xr.put(PdfName.ROOT, root);
+ if (info != null) {
+ xr.put(PdfName.INFO, info);
+ }
+ if (encryption != null)
+ xr.put(PdfName.ENCRYPT, encryption);
+ if (fileID != null)
+ xr.put(PdfName.ID, fileID);
+ xr.put(PdfName.W, new PdfArray(new int[]{1, mid, 2}));
+ xr.put(PdfName.TYPE, PdfName.XREF);
+ PdfArray idx = new PdfArray();
+ for (int k = 0; k < sections.size(); ++k)
+ idx.add(new PdfNumber(((Integer)sections.get(k)).intValue()));
+ xr.put(PdfName.INDEX, idx);
+ if (prevxref > 0)
+ xr.put(PdfName.PREV, new PdfNumber(prevxref));
+ PdfEncryption enc = writer.crypto;
+ writer.crypto = null;
+ PdfIndirectObject indirect = new PdfIndirectObject(refNumber, xr, writer);
+ indirect.writeTo(writer.getOs());
+ writer.crypto = enc;
+ }
+ else {
+ os.write(getISOBytes("xref\n"));
+ Iterator i = xrefs.iterator();
+ for (int k = 0; k < sections.size(); k += 2) {
+ first = ((Integer)sections.get(k)).intValue();
+ len = ((Integer)sections.get(k + 1)).intValue();
+ os.write(getISOBytes(String.valueOf(first)));
+ os.write(getISOBytes(" "));
+ os.write(getISOBytes(String.valueOf(len)));
+ os.write('\n');
+ while (len-- > 0) {
+ entry = (PdfCrossReference) i.next();
+ entry.toPdf(os);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * PdfTrailer
is the PDF Trailer object.
+ *
+ * This object is described in the 'Portable Document Format Reference Manual version 1.3'
+ * section 5.16 (page 59-60).
+ */
+
+ static class PdfTrailer extends PdfDictionary {
+
+ // membervariables
+
+ int offset;
+
+ // constructors
+
+ /**
+ * Constructs a PDF-Trailer.
+ *
+ * @param size the number of entries in the PdfCrossReferenceTable
+ * @param offset offset of the PdfCrossReferenceTable
+ * @param root an indirect reference to the root of the PDF document
+ * @param info an indirect reference to the info object of the PDF document
+ * @param encryption
+ * @param fileID
+ * @param prevxref
+ */
+
+ PdfTrailer(int size, int offset, PdfIndirectReference root, PdfIndirectReference info, PdfIndirectReference encryption, PdfObject fileID, int prevxref) {
+ this.offset = offset;
+ put(PdfName.SIZE, new PdfNumber(size));
+ put(PdfName.ROOT, root);
+ if (info != null) {
+ put(PdfName.INFO, info);
+ }
+ if (encryption != null)
+ put(PdfName.ENCRYPT, encryption);
+ if (fileID != null)
+ put(PdfName.ID, fileID);
+ if (prevxref > 0)
+ put(PdfName.PREV, new PdfNumber(prevxref));
+ }
+
+ /**
+ * Returns the PDF representation of this PdfObject
.
+ * @param writer
+ * @param os
+ * @throws IOException
+ */
+ public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
+ os.write(getISOBytes("trailer\n")); // ssteward: 1.44 - preserve newline after trailer
+ super.toPdf(writer, os);
+ os.write(getISOBytes("\nstartxref\n"));
+ os.write(getISOBytes(String.valueOf(offset)));
+ os.write(getISOBytes("\n%%EOF\n"));
+ }
+ }
+ // static membervariables
+
+ /** A viewer preference */
+ public static final int PageLayoutSinglePage = 1;
+ /** A viewer preference */
+ public static final int PageLayoutOneColumn = 2;
+ /** A viewer preference */
+ public static final int PageLayoutTwoColumnLeft = 4;
+ /** A viewer preference */
+ public static final int PageLayoutTwoColumnRight = 8;
+ /** A viewer preference */
+ public static final int PageLayoutTwoPageLeft = 16;
+ /** A viewer preference */
+ public static final int PageLayoutTwoPageRight = 32;
+
+ /** A viewer preference */
+ public static final int PageModeUseNone = 16;
+ /** A viewer preference */
+ public static final int PageModeUseOutlines = 32;
+ /** A viewer preference */
+ public static final int PageModeUseThumbs = 64;
+ /** A viewer preference */
+ public static final int PageModeFullScreen = 128;
+ /** A viewer preference */
+ public static final int PageModeUseOC = 1 << 20;
+ /** A viewer preference */
+ public static final int PageModeUseAttachments = 2048;
+
+ /** A viewer preference */
+ public static final int HideToolbar = 256;
+ /** A viewer preference */
+ public static final int HideMenubar = 512;
+ /** A viewer preference */
+ public static final int HideWindowUI = 1024;
+ /** A viewer preference */
+ public static final int FitWindow = 2048;
+ /** A viewer preference */
+ public static final int CenterWindow = 4096;
+ /** A viewer preference */
+ public static final int DisplayDocTitle = 1 << 17;
+
+ /** A viewer preference */
+ public static final int NonFullScreenPageModeUseNone = 8192;
+ /** A viewer preference */
+ public static final int NonFullScreenPageModeUseOutlines = 16384;
+ /** A viewer preference */
+ public static final int NonFullScreenPageModeUseThumbs = 32768;
+ /** A viewer preference */
+ public static final int NonFullScreenPageModeUseOC = 1 << 19;
+
+ /** A viewer preference */
+ public static final int DirectionL2R = 1 << 16;
+ /** A viewer preference */
+ public static final int DirectionR2L = 1 << 17;
+ /** A viewer preference */
+ public static final int PrintScalingNone = 1 << 21;
+
+ /** The mask to decide if a ViewerPreferences dictionary is needed */
+ static final int ViewerPreferencesMask = 0xffff00;
+ /** The operation permitted when the document is opened with the user password */
+ public static final int AllowPrinting = 4 + 2048;
+ /** The operation permitted when the document is opened with the user password */
+ public static final int AllowModifyContents = 8;
+ /** The operation permitted when the document is opened with the user password */
+ public static final int AllowCopy = 16;
+ /** The operation permitted when the document is opened with the user password */
+ public static final int AllowModifyAnnotations = 32;
+ /** The operation permitted when the document is opened with the user password */
+ public static final int AllowFillIn = 256;
+ /** The operation permitted when the document is opened with the user password */
+ public static final int AllowScreenReaders = 512;
+ /** The operation permitted when the document is opened with the user password */
+ public static final int AllowAssembly = 1024;
+ /** The operation permitted when the document is opened with the user password */
+ public static final int AllowDegradedPrinting = 4;
+ /** Type of encryption */
+ public static final boolean STRENGTH40BITS = false;
+ /** Type of encryption */
+ public static final boolean STRENGTH128BITS = true;
+ /** action value */
+ public static final PdfName DOCUMENT_CLOSE = PdfName.WC;
+ /** action value */
+ public static final PdfName WILL_SAVE = PdfName.WS;
+ /** action value */
+ public static final PdfName DID_SAVE = PdfName.DS;
+ /** action value */
+ public static final PdfName WILL_PRINT = PdfName.WP;
+ /** action value */
+ public static final PdfName DID_PRINT = PdfName.DP;
+ /** action value */
+ public static final PdfName PAGE_OPEN = PdfName.O;
+ /** action value */
+ public static final PdfName PAGE_CLOSE = PdfName.C;
+
+ /** signature value */
+ public static final int SIGNATURE_EXISTS = 1;
+ /** signature value */
+ public static final int SIGNATURE_APPEND_ONLY = 2;
+
+ /** possible PDF version */
+ public static final char VERSION_1_0 = '0';
+ /** possible PDF version */
+ public static final char VERSION_1_1 = '1';
+ /** possible PDF version */
+ public static final char VERSION_1_2 = '2';
+ /** possible PDF version */
+ public static final char VERSION_1_3 = '3';
+ /** possible PDF version */
+ public static final char VERSION_1_4 = '4';
+ /** possible PDF version */
+ public static final char VERSION_1_5 = '5';
+ /** possible PDF version */
+ public static final char VERSION_1_6 = '6';
+ /** possible PDF version */
+ public static final char VERSION_1_7 = '7';
+
+ /** possible PDF version (catalog) */
+ public static final PdfName PDF_VERSION_1_2 = new PdfName("1.2");
+ /** possible PDF version (catalog) */
+ public static final PdfName PDF_VERSION_1_3 = new PdfName("1.3");
+ /** possible PDF version (catalog) */
+ public static final PdfName PDF_VERSION_1_4 = new PdfName("1.4");
+ /** possible PDF version (catalog) */
+ public static final PdfName PDF_VERSION_1_5 = new PdfName("1.5");
+ /** possible PDF version (catalog) */
+ public static final PdfName PDF_VERSION_1_6 = new PdfName("1.6");
+ /** possible PDF version (catalog) */
+ public static final PdfName PDF_VERSION_1_7 = new PdfName("1.7");
+
+ private static final int VPOINT = 7;
+ /** this is the header of a PDF document */
+ protected byte[] HEADER = getISOBytes("%PDF-1.4\n%\u00e2\u00e3\u00cf\u00d3"); // ssteward: dropped trailing \n
+
+ protected int prevxref = 0;
+
+ protected PdfPages root = new PdfPages(this);
+
+ /** Dictionary, containing all the images of the PDF document */
+ protected PdfDictionary imageDictionary = new PdfDictionary();
+
+ /** This is the list with all the images in the document. */
+ // private HashMap images = new HashMap();
+
+ /** The form XObjects in this document. The key is the xref and the value
+ is Object[]{PdfName, template}.*/
+ protected HashMap formXObjects = new HashMap();
+
+ /** The name counter for the form XObjects name. */
+ protected int formXObjectsCounter = 1;
+
+ /** The font number counter for the fonts in the document. */
+ protected int fontNumber = 1;
+
+ /** The color number counter for the colors in the document. */
+ protected int colorNumber = 1;
+
+ /** The patten number counter for the colors in the document. */
+ protected int patternNumber = 1;
+
+ /** The direct content in this document. */
+ protected PdfContentByte directContent;
+
+ /** The direct content under in this document. */
+ protected PdfContentByte directContentUnder;
+
+ /** The fonts of this document */
+ protected HashMap documentFonts = new HashMap();
+
+ /** The colors of this document */
+ protected HashMap documentColors = new HashMap();
+
+ /** The patterns of this document */
+ protected HashMap documentPatterns = new HashMap();
+
+ protected HashMap documentShadings = new HashMap();
+
+ protected HashMap documentShadingPatterns = new HashMap();
+
+ protected ColorDetails patternColorspaceRGB;
+ protected ColorDetails patternColorspaceGRAY;
+ protected ColorDetails patternColorspaceCMYK;
+ protected HashMap documentSpotPatterns = new HashMap();
+
+ protected HashMap documentExtGState = new HashMap();
+
+ protected HashMap documentProperties = new HashMap();
+ protected HashSet documentOCG = new HashSet();
+ protected ArrayList documentOCGorder = new ArrayList();
+ protected PdfOCProperties OCProperties;
+ protected PdfArray OCGRadioGroup = new PdfArray();
+
+ protected PdfDictionary defaultColorspace = new PdfDictionary();
+ protected float userunit = 0f;
+
+ /** PDF/X value */
+ public static final int PDFXNONE = 0;
+ /** PDF/X value */
+ public static final int PDFX1A2001 = 1;
+ /** PDF/X value */
+ public static final int PDFX32002 = 2;
+
+ private int pdfxConformance = PDFXNONE;
+
+ static final int PDFXKEY_COLOR = 1;
+ static final int PDFXKEY_CMYK = 2;
+ static final int PDFXKEY_RGB = 3;
+ static final int PDFXKEY_FONT = 4;
+ static final int PDFXKEY_IMAGE = 5;
+ static final int PDFXKEY_GSTATE = 6;
+ static final int PDFXKEY_LAYER = 7;
+
+ // membervariables
+
+ /** body of the PDF document */
+ protected PdfBody body;
+
+ /** the pdfdocument object. */
+ protected PdfDocument pdf;
+
+ /** The PdfPageEvent
for this document. */
+ private PdfPageEvent pageEvent;
+
+ protected HashMap importedPages = new HashMap();
+
+ protected PdfReaderInstance currentPdfReaderInstance;
+
+ /** The PdfIndirectReference to the pages. */
+ protected ArrayList pageReferences = new ArrayList();
+
+ protected int currentPageNumber = 1;
+
+ protected PdfDictionary group;
+
+ /** The default space-char ratio. */
+ public static final float SPACE_CHAR_RATIO_DEFAULT = 2.5f;
+ /** Disable the inter-character spacing. */
+ public static final float NO_SPACE_CHAR_RATIO = 10000000f;
+
+ /** Use the default run direction. */
+ public static final int RUN_DIRECTION_DEFAULT = 0;
+ /** Do not use bidirectional reordering. */
+ public static final int RUN_DIRECTION_NO_BIDI = 1;
+ /** Use bidirectional reordering with left-to-right
+ * preferential run direction.
+ */
+ public static final int RUN_DIRECTION_LTR = 2;
+ /** Use bidirectional reordering with right-to-left
+ * preferential run direction.
+ */
+ public static final int RUN_DIRECTION_RTL = 3;
+ protected int runDirection = RUN_DIRECTION_NO_BIDI;
+ /**
+ * The ratio between the extra word spacing and the extra character spacing.
+ * Extra word spacing will grow ratio
times more than extra character spacing.
+ */
+ private float spaceCharRatio = SPACE_CHAR_RATIO_DEFAULT;
+
+ /** Holds value of property extraCatalog. */
+ private PdfDictionary extraCatalog;
+
+ // ssteward: for PRStream.toPdf()
+ public boolean filterStreams = false; // apply decode filters to some streams upon output
+ public boolean compressStreams = false; // add compression to some stream upon output
+
+ /** XMP Metadata for the document. */
+ protected byte[] xmpMetadata = null;
+ /**
+ * Holds value of property fullCompression.
+ */
+ protected boolean fullCompression = false;
+
+ protected boolean tagged = false;
+
+ protected PdfObject fileID = null; // ssteward: allow setting of fileID
+
+ protected PdfStructureTreeRoot structureTreeRoot;
+
+ // constructor
+
+ protected PdfWriter() {
+ }
+
+ /**
+ * Constructs a PdfWriter
.
+ *
+ * Remark: a PdfWriter can only be constructed by calling the method
+ * getInstance(Document document, OutputStream os)
.
+ *
+ * @param document The PdfDocument
that has to be written
+ * @param os The OutputStream
the writer has to write to.
+ */
+
+ protected PdfWriter(PdfDocument document, OutputStream os) {
+ super(document, os);
+ pdf = document;
+ directContent = new PdfContentByte(this);
+ directContentUnder = new PdfContentByte(this);
+ }
+
+ // get an instance of the PdfWriter
+
+ /**
+ * Gets an instance of the PdfWriter
.
+ *
+ * @param document The Document
that has to be written
+ * @param os The OutputStream
the writer has to write to.
+ * @return a new PdfWriter
+ *
+ * @throws DocumentException on error
+ */
+
+ public static PdfWriter getInstance(Document document, OutputStream os)
+ throws DocumentException {
+ PdfDocument pdf = new PdfDocument();
+ document.addDocListener(pdf);
+ PdfWriter writer = new PdfWriter(pdf, os);
+ pdf.addWriter(writer);
+ return writer;
+ }
+
+ /** Gets an instance of the PdfWriter
.
+ *
+ * @return a new PdfWriter
+ * @param document The Document
that has to be written
+ * @param os The OutputStream
the writer has to write to.
+ * @param listener A DocListener
to pass to the PdfDocument.
+ * @throws DocumentException on error
+ */
+
+ public static PdfWriter getInstance(Document document, OutputStream os, DocListener listener)
+ throws DocumentException {
+ PdfDocument pdf = new PdfDocument();
+ pdf.addDocListener(listener);
+ document.addDocListener(pdf);
+ PdfWriter writer = new PdfWriter(pdf, os);
+ pdf.addWriter(writer);
+ return writer;
+ }
+
+ // methods to write objects to the outputstream
+
+ /**
+ * Adds some PdfContents
to this Writer.
+ *
+ * The document has to be open before you can begin to add content
+ * to the body of the document.
+ *
+ * @return a PdfIndirectReference
+ * @param page the PdfPage
to add
+ * @param contents the PdfContents
of the page
+ * @throws PdfException on error
+ */
+
+ PdfIndirectReference add(PdfPage page, PdfContents contents) throws PdfException {
+ if (!open) {
+ throw new PdfException("The document isn't open.");
+ }
+ PdfIndirectObject object;
+ try {
+ object = addToBody(contents);
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ page.add(object.getIndirectReference());
+ if (group != null) {
+ page.put(PdfName.GROUP, group);
+ group = null;
+ }
+ root.addPage(page);
+ currentPageNumber++;
+ return null;
+ }
+
+ /** Adds an image to the document but not to the page resources. It is used with
+ * templates and Document.add(Image)
.
+ * @param image the Image
to add
+ * @return the name of the image added
+ * @throws PdfException on error
+ * @throws DocumentException on error
+ */
+ /* ssteward: dropped in 1.44
+ PdfName addDirectImageSimple(Image image) throws PdfException, DocumentException {
+ PdfName name;
+ // if the images is already added, just retrieve the name
+ if (images.containsKey(image.getMySerialId())) {
+ name = (PdfName) images.get(image.getMySerialId());
+ }
+ // if it's a new image, add it to the document
+ else {
+ if (image.isImgTemplate()) {
+ name = new PdfName("img" + images.size());
+ if (image.templateData() == null) {
+ if(image instanceof ImgWMF){
+ try {
+ ImgWMF wmf = (ImgWMF)image;
+ wmf.readWMF(getDirectContent().createTemplate(0, 0));
+ }
+ catch (Exception e) {
+ throw new DocumentException(e);
+ }
+ }else{
+ try {
+ ((ImgPostscript)image).readPostscript(getDirectContent().createTemplate(0, 0));
+ }
+ catch (Exception e) {
+ throw new DocumentException(e);
+ }
+
+ }
+ }
+ }
+ else {
+ Image maskImage = image.getImageMask();
+ PdfIndirectReference maskRef = null;
+ if (maskImage != null) {
+ PdfName mname = (PdfName)images.get(maskImage.getMySerialId());
+ maskRef = getImageReference(mname);
+ }
+ PdfImage i = new PdfImage(image, "img" + images.size(), maskRef);
+ if (image.hasICCProfile()) {
+ PdfICCBased icc = new PdfICCBased(image.getICCProfile());
+ PdfIndirectReference iccRef = add(icc);
+ PdfArray iccArray = new PdfArray();
+ iccArray.add(PdfName.ICCBASED);
+ iccArray.add(iccRef);
+ PdfObject colorspace = i.get(PdfName.COLORSPACE);
+ if (colorspace != null && colorspace.isArray()) {
+ ArrayList ar = ((PdfArray)colorspace).getArrayList();
+ if (ar.size() > 1 && PdfName.INDEXED.equals(ar.get(0)))
+ ar.set(1, iccArray);
+ else
+ i.put(PdfName.COLORSPACE, iccArray);
+ }
+ else
+ i.put(PdfName.COLORSPACE, iccArray);
+ }
+ add(i);
+ name = i.name();
+ }
+ images.put(image.getMySerialId(), name);
+ }
+ return name;
+ }
+ */
+
+ /**
+ * Writes a PdfImage
to the outputstream.
+ *
+ * @param pdfImage the image to be added
+ * @return a PdfIndirectReference
to the encapsulated image
+ * @throws PdfException when a document isn't open yet, or has been closed
+ */
+ /* ssteward: dropped in 1.44
+ PdfIndirectReference add(PdfImage pdfImage) throws PdfException {
+ if (! imageDictionary.contains(pdfImage.name())) {
+ checkPDFXConformance(this, PDFXKEY_IMAGE, pdfImage);
+ PdfIndirectObject object;
+ try {
+ object = addToBody(pdfImage);
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ imageDictionary.put(pdfImage.name(), object.getIndirectReference());
+ return object.getIndirectReference();
+ }
+ return (PdfIndirectReference) imageDictionary.get(pdfImage.name());
+ }
+ */
+ /* ssteward: gcc 3.4.0 doesn't have ICC_Profile
+ protected PdfIndirectReference add(PdfICCBased icc) throws PdfException {
+ PdfIndirectObject object;
+ try {
+ object = addToBody(icc);
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ return object.getIndirectReference();
+ }
+ */
+
+ /**
+ * return the PdfIndirectReference
to the image with a given name.
+ *
+ * @param name the name of the image
+ * @return a PdfIndirectReference
+ */
+
+ PdfIndirectReference getImageReference(PdfName name) {
+ return (PdfIndirectReference) imageDictionary.get(name);
+ }
+
+ // methods to open and close the writer
+
+ /**
+ * Signals that the Document
has been opened and that
+ * Elements
can be added.
+ *
+ * When this method is called, the PDF-document header is
+ * written to the outputstream.
+ */
+
+ public void open() {
+ super.open();
+ try {
+ os.write(HEADER);
+ body = new PdfBody(this);
+ if (pdfxConformance == PDFX32002) {
+ PdfDictionary sec = new PdfDictionary();
+ sec.put(PdfName.GAMMA, new PdfArray(new float[]{2.2f,2.2f,2.2f}));
+ sec.put(PdfName.MATRIX, new PdfArray(new float[]{0.4124f,0.2126f,0.0193f,0.3576f,0.7152f,0.1192f,0.1805f,0.0722f,0.9505f}));
+ sec.put(PdfName.WHITEPOINT, new PdfArray(new float[]{0.9505f,1f,1.089f}));
+ PdfArray arr = new PdfArray(PdfName.CALRGB);
+ arr.add(sec);
+ setDefaultColorspace(PdfName.DEFAULTRGB, addToBody(arr).getIndirectReference());
+ }
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ }
+
+ private static void getOCGOrder(PdfArray order, PdfLayer layer) {
+ if (!layer.isOnPanel())
+ return;
+ if (layer.getTitle() == null)
+ order.add(layer.getRef());
+ ArrayList children = layer.getChildren();
+ if (children == null)
+ return;
+ PdfArray kids = new PdfArray();
+ if (layer.getTitle() != null)
+ kids.add(new PdfString(layer.getTitle(), PdfObject.TEXT_UNICODE));
+ for (int k = 0; k < children.size(); ++k) {
+ getOCGOrder(kids, (PdfLayer)children.get(k));
+ }
+ if (kids.size() > 0)
+ order.add(kids);
+ }
+
+ private void addASEvent(PdfName event, PdfName category) {
+ PdfArray arr = new PdfArray();
+ for (Iterator it = documentOCG.iterator(); it.hasNext();) {
+ PdfLayer layer = (PdfLayer)it.next();
+ PdfDictionary usage = (PdfDictionary)layer.get(PdfName.USAGE);
+ if (usage != null && usage.get(category) != null)
+ arr.add(layer.getRef());
+ }
+ if (arr.size() == 0)
+ return;
+ PdfDictionary d = (PdfDictionary)OCProperties.get(PdfName.D);
+ PdfArray arras = (PdfArray)d.get(PdfName.AS);
+ if (arras == null) {
+ arras = new PdfArray();
+ d.put(PdfName.AS, arras);
+ }
+ PdfDictionary as = new PdfDictionary();
+ as.put(PdfName.EVENT, event);
+ as.put(PdfName.CATEGORY, new PdfArray(category));
+ as.put(PdfName.OCGS, arr);
+ arras.add(as);
+ }
+
+ private void fillOCProperties(boolean erase) {
+ if (OCProperties == null)
+ OCProperties = new PdfOCProperties();
+ if (erase) {
+ OCProperties.remove(PdfName.OCGS);
+ OCProperties.remove(PdfName.D);
+ }
+ if (OCProperties.get(PdfName.OCGS) == null) {
+ PdfArray gr = new PdfArray();
+ for (Iterator it = documentOCG.iterator(); it.hasNext();) {
+ PdfLayer layer = (PdfLayer)it.next();
+ gr.add(layer.getRef());
+ }
+ OCProperties.put(PdfName.OCGS, gr);
+ }
+ if (OCProperties.get(PdfName.D) != null)
+ return;
+ ArrayList docOrder = new ArrayList(documentOCGorder);
+ for (Iterator it = docOrder.iterator(); it.hasNext();) {
+ PdfLayer layer = (PdfLayer)it.next();
+ if (layer.getParent() != null)
+ it.remove();
+ }
+ PdfArray order = new PdfArray();
+ for (Iterator it = docOrder.iterator(); it.hasNext();) {
+ PdfLayer layer = (PdfLayer)it.next();
+ getOCGOrder(order, layer);
+ }
+ PdfDictionary d = new PdfDictionary();
+ OCProperties.put(PdfName.D, d);
+ d.put(PdfName.ORDER, order);
+ PdfArray gr = new PdfArray();
+ for (Iterator it = documentOCG.iterator(); it.hasNext();) {
+ PdfLayer layer = (PdfLayer)it.next();
+ if (!layer.isOn())
+ gr.add(layer.getRef());
+ }
+ if (gr.size() > 0)
+ d.put(PdfName.OFF, gr);
+ if (OCGRadioGroup.size() > 0)
+ d.put(PdfName.RBGROUPS, OCGRadioGroup);
+ addASEvent(PdfName.VIEW, PdfName.ZOOM);
+ addASEvent(PdfName.VIEW, PdfName.VIEW);
+ addASEvent(PdfName.PRINT, PdfName.PRINT);
+ addASEvent(PdfName.EXPORT, PdfName.EXPORT);
+ d.put(PdfName.LISTMODE, PdfName.VISIBLEPAGES);
+ }
+
+ protected PdfDictionary getCatalog(PdfIndirectReference rootObj)
+ {
+ PdfDictionary catalog = ((PdfDocument)document).getCatalog(rootObj);
+ if (tagged) {
+ try {
+ getStructureTreeRoot().buildTree();
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ catalog.put(PdfName.STRUCTTREEROOT, structureTreeRoot.getReference());
+ PdfDictionary mi = new PdfDictionary();
+ mi.put(PdfName.MARKED, PdfBoolean.PDFTRUE);
+ catalog.put(PdfName.MARKINFO, mi);
+ }
+ if (documentOCG.size() == 0)
+ return catalog;
+ fillOCProperties(false);
+ catalog.put(PdfName.OCPROPERTIES, OCProperties);
+ return catalog;
+ }
+
+ protected void addSharedObjectsToBody() throws IOException {
+ // add the fonts
+ for (Iterator it = documentFonts.values().iterator(); it.hasNext();) {
+ FontDetails details = (FontDetails)it.next();
+ details.writeFont(this);
+ }
+ // add the form XObjects
+ for (Iterator it = formXObjects.values().iterator(); it.hasNext();) {
+ Object objs[] = (Object[])it.next();
+ PdfTemplate template = (PdfTemplate)objs[1];
+ if (template != null && template.getIndirectReference() instanceof PRIndirectReference)
+ continue;
+ if (template != null && template.getType() == PdfTemplate.TYPE_TEMPLATE) {
+ addToBody(template.getFormXObject(), template.getIndirectReference());
+ }
+ }
+ // add all the dependencies in the imported pages
+ for (Iterator it = importedPages.values().iterator(); it.hasNext();) {
+ currentPdfReaderInstance = (PdfReaderInstance)it.next();
+ currentPdfReaderInstance.writeAllPages();
+ }
+ currentPdfReaderInstance = null;
+ // add the color
+ for (Iterator it = documentColors.values().iterator(); it.hasNext();) {
+ ColorDetails color = (ColorDetails)it.next();
+ addToBody(color.getSpotColor(this), color.getIndirectReference());
+ }
+ // add the pattern
+ for (Iterator it = documentPatterns.keySet().iterator(); it.hasNext();) {
+ PdfPatternPainter pat = (PdfPatternPainter)it.next();
+ addToBody(pat.getPattern(), pat.getIndirectReference());
+ }
+ // add the shading patterns
+ for (Iterator it = documentShadingPatterns.keySet().iterator(); it.hasNext();) {
+ PdfShadingPattern shadingPattern = (PdfShadingPattern)it.next();
+ shadingPattern.addToBody();
+ }
+ // add the shadings
+ for (Iterator it = documentShadings.keySet().iterator(); it.hasNext();) {
+ PdfShading shading = (PdfShading)it.next();
+ shading.addToBody();
+ }
+ // add the extgstate
+ for (Iterator it = documentExtGState.keySet().iterator(); it.hasNext();) {
+ PdfDictionary gstate = (PdfDictionary)it.next();
+ PdfObject obj[] = (PdfObject[])documentExtGState.get(gstate);
+ addToBody(gstate, (PdfIndirectReference)obj[1]);
+ }
+ // add the properties
+ for (Iterator it = documentProperties.keySet().iterator(); it.hasNext();) {
+ Object prop = it.next();
+ PdfObject[] obj = (PdfObject[])documentProperties.get(prop);
+ if (prop instanceof PdfLayerMembership){
+ PdfLayerMembership layer = (PdfLayerMembership)prop;
+ addToBody(layer.getPdfObject(), layer.getRef());
+ }
+ else if ((prop instanceof PdfDictionary) && !(prop instanceof PdfLayer)){
+ addToBody((PdfDictionary)prop, (PdfIndirectReference)obj[1]);
+ }
+ }
+ for (Iterator it = documentOCG.iterator(); it.hasNext();) {
+ PdfOCG layer = (PdfOCG)it.next();
+ addToBody(layer.getPdfObject(), layer.getRef());
+ }
+ }
+
+ /**
+ * Signals that the Document
was closed and that no other
+ * Elements
will be added.
+ *
+ * The pages-tree is built and written to the outputstream.
+ * A Catalog is constructed, as well as an Info-object,
+ * the referencetable is composed and everything is written
+ * to the outputstream embedded in a Trailer.
+ */
+
+ public void close() {
+ if (open) {
+ if ((currentPageNumber - 1) != pageReferences.size())
+ throw new RuntimeException("The page " + pageReferences.size() +
+ " was requested but the document has only " + (currentPageNumber - 1) + " pages.");
+ pdf.close();
+ try {
+ addSharedObjectsToBody();
+ // add the root to the body
+ PdfIndirectReference rootRef = root.writePageTree();
+ // make the catalog-object and add it to the body
+ PdfDictionary catalog = getCatalog(rootRef);
+ // if there is XMP data to add: add it
+ if (xmpMetadata != null) {
+ PdfStream xmp = new PdfStream(xmpMetadata);
+ xmp.put(PdfName.TYPE, PdfName.METADATA);
+ xmp.put(PdfName.SUBTYPE, PdfName.XML);
+ catalog.put(PdfName.METADATA, body.add(xmp).getIndirectReference());
+ }
+ // make pdfx conformant
+ PdfDictionary info = getInfo();
+ if (pdfxConformance != PDFXNONE) {
+ if (info.get(PdfName.GTS_PDFXVERSION) == null) {
+ if (pdfxConformance == PDFX1A2001) {
+ info.put(PdfName.GTS_PDFXVERSION, new PdfString("PDF/X-1:2001"));
+ info.put(new PdfName("GTS_PDFXConformance"), new PdfString("PDF/X-1a:2001"));
+ }
+ else if (pdfxConformance == PDFX32002)
+ info.put(PdfName.GTS_PDFXVERSION, new PdfString("PDF/X-3:2002"));
+ }
+ if (info.get(PdfName.TITLE) == null) {
+ info.put(PdfName.TITLE, new PdfString("Pdf document"));
+ }
+ if (info.get(PdfName.CREATOR) == null) {
+ info.put(PdfName.CREATOR, new PdfString("Unknown"));
+ }
+ if (info.get(PdfName.TRAPPED) == null) {
+ info.put(PdfName.TRAPPED, new PdfName("False"));
+ }
+ getExtraCatalog();
+ if (extraCatalog.get(PdfName.OUTPUTINTENTS) == null) {
+ PdfDictionary out = new PdfDictionary(PdfName.OUTPUTINTENT);
+ out.put(PdfName.OUTPUTCONDITION, new PdfString("SWOP CGATS TR 001-1995"));
+ out.put(PdfName.OUTPUTCONDITIONIDENTIFIER, new PdfString("CGATS TR 001"));
+ out.put(PdfName.REGISTRYNAME, new PdfString("http://www.color.org"));
+ out.put(PdfName.INFO, new PdfString(""));
+ out.put(PdfName.S, PdfName.GTS_PDFX);
+ extraCatalog.put(PdfName.OUTPUTINTENTS, new PdfArray(out));
+ }
+ }
+ if (extraCatalog != null) {
+ catalog.mergeDifferent(extraCatalog);
+ }
+ PdfIndirectObject indirectCatalog = addToBody(catalog, false);
+ // add the info-object to the body
+ PdfIndirectObject infoObj = addToBody(info, false);
+ PdfIndirectReference encryption = null;
+ //PdfObject fileID = null; // ssteward: moved this out into PdfWriter
+ body.flushObjStm();
+ if (crypto != null) {
+ PdfIndirectObject encryptionObject = addToBody(crypto.getEncryptionDictionary(), false);
+ encryption = encryptionObject.getIndirectReference();
+ fileID = crypto.getFileID();
+ }
+ else if (fileID == null) // ssteward
+ fileID = PdfEncryption.createInfoId(PdfEncryption.createDocumentId());
+
+ // write the cross-reference table of the body
+ body.writeCrossReferenceTable(os, indirectCatalog.getIndirectReference(),
+ infoObj.getIndirectReference(), encryption, fileID, prevxref);
+
+ // make the trailer
+ if (fullCompression) {
+ os.write(getISOBytes("startxref\n"));
+ os.write(getISOBytes(String.valueOf(body.offset())));
+ os.write(getISOBytes("\n%%EOF\n"));
+ }
+ else {
+ PdfTrailer trailer = new PdfTrailer(body.size(),
+ body.offset(),
+ indirectCatalog.getIndirectReference(),
+ infoObj.getIndirectReference(),
+ encryption,
+ fileID, prevxref);
+ trailer.toPdf(this, os);
+ }
+ super.close();
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ }
+ }
+
+ // methods
+
+ /**
+ * Sometimes it is necessary to know where the just added Table
ends.
+ *
+ * For instance to avoid to add another table in a page that is ending up, because
+ * the new table will be probably splitted just after the header (it is an
+ * unpleasant effect, isn't it?).
+ *
+ * Added on September 8th, 2001
+ * by Francesco De Milato
+ * francesco.demilato@tiscalinet.it
+ * @param table the Table
+ * @return the bottom height of the just added table
+ */
+ /* ssteward: dropped in 1.44
+ public float getTableBottom(Table table) {
+ return pdf.bottom(table) - pdf.indentBottom();
+ }
+ */
+
+ /**
+ * Gets a pre-rendered table.
+ * (Contributed by dperezcar@fcc.es)
+ * @param table Contains the table definition. Its contents are deleted, after being pre-rendered.
+ * @return a PdfTable
+ */
+ /* ssteward: dropped in 1.44
+ public PdfTable getPdfTable(Table table) {
+ return pdf.getPdfTable(table, true);
+ }
+ */
+
+ /**
+ * Row additions to the original {@link Table} used to build the {@link PdfTable} are processed and pre-rendered,
+ * and then the contents are deleted.
+ * If the pre-rendered table doesn't fit, then it is fully rendered and its data discarded.
+ * There shouldn't be any column change in the underlying {@link Table} object.
+ * (Contributed by dperezcar@fcc.es)
+ *
+ * @param table The pre-rendered table obtained from {@link #getPdfTable(Table)}
+ * @return true if the table is rendered and emptied.
+ * @throws DocumentException
+ * @see #getPdfTable(Table)
+ */
+ /* ssteward: dropped in 1.44
+ public boolean breakTableIfDoesntFit(PdfTable table) throws DocumentException {
+ return pdf.breakTableIfDoesntFit(table);
+ }
+ */
+ /**
+ * Checks if a Table
fits the current page of the PdfDocument
.
+ *
+ * @param table the table that has to be checked
+ * @param margin a certain margin
+ * @return true
if the Table
fits the page, false
otherwise.
+ */
+ /* ssteward: dropped in 1.44
+ public boolean fitsPage(Table table, float margin) {
+ return pdf.bottom(table) > pdf.indentBottom() + margin;
+ }
+ */
+
+ /**
+ * Checks if a Table
fits the current page of the PdfDocument
.
+ *
+ * @param table the table that has to be checked
+ * @return true
if the Table
fits the page, false
otherwise.
+ */
+ /* ssteward: dropped in 1.44
+ public boolean fitsPage(Table table) {
+ return fitsPage(table, 0);
+ }
+ */
+
+ /**
+ * Checks if a PdfPTable
fits the current page of the PdfDocument
.
+ *
+ * @param table the table that has to be checked
+ * @param margin a certain margin
+ * @return true
if the PdfPTable
fits the page, false
otherwise.
+ */
+ /* ssteward: dropped in 1.44
+ public boolean fitsPage(PdfPTable table, float margin) {
+ return pdf.fitsPage(table, margin);
+ }
+ */
+
+ /**
+ * Checks if a PdfPTable
fits the current page of the PdfDocument
.
+ *
+ * @param table the table that has to be checked
+ * @return true
if the PdfPTable
fits the page, false
otherwise.
+ */
+ /* ssteward: dropped in 1.44
+ public boolean fitsPage(PdfPTable table) {
+ return pdf.fitsPage(table, 0);
+ }
+ */
+
+ /**
+ * Gets the current vertical page position.
+ * @param ensureNewLine Tells whether a new line shall be enforced. This may cause side effects
+ * for elements that do not terminate the lines they've started because those lines will get
+ * terminated.
+ * @return The current vertical page position.
+ */
+ public float getVerticalPosition(boolean ensureNewLine) {
+ return pdf.getVerticalPosition(ensureNewLine);
+ }
+
+ /**
+ * Checks if writing is paused.
+ *
+ * @return true
if writing temporarely has to be paused, false
otherwise.
+ */
+
+ boolean isPaused() {
+ // ssteward: changed from "pause" to "m_pause" to
+ // bring in line with DocWriter
+ return m_pause;
+ }
+
+ /**
+ * Gets the direct content for this document. There is only one direct content,
+ * multiple calls to this method will allways retrieve the same.
+ * @return the direct content
+ */
+
+ public PdfContentByte getDirectContent() {
+ if (!open)
+ throw new RuntimeException("The document is not open.");
+ return directContent;
+ }
+
+ /**
+ * Gets the direct content under for this document. There is only one direct content,
+ * multiple calls to this method will allways retrieve the same.
+ * @return the direct content
+ */
+
+ public PdfContentByte getDirectContentUnder() {
+ if (!open)
+ throw new RuntimeException("The document is not open.");
+ return directContentUnder;
+ }
+
+ /**
+ * Resets all the direct contents to empty. This happens when a new page is started.
+ */
+
+ void resetContent() {
+ directContent.reset();
+ directContentUnder.reset();
+ }
+
+ /** Gets the AcroForm object.
+ * @return the PdfAcroForm
+ */
+
+ public PdfAcroForm getAcroForm() {
+ return pdf.getAcroForm();
+ }
+
+ /** Gets the root outline.
+ * @return the root outline
+ */
+
+ public PdfOutline getRootOutline() {
+ return directContent.getRootOutline();
+ }
+
+ /**
+ * Returns the outputStreamCounter.
+ * @return the outputStreamCounter
+ */
+ public OutputStreamCounter getOs() {
+ return os;
+ }
+
+ /**
+ * Adds a BaseFont
to the document but not to the page resources.
+ * It is used for templates.
+ * @param bf the BaseFont
to add
+ * @return an Object[]
where position 0 is a PdfName
+ * and position 1 is an PdfIndirectReference
+ */
+
+ FontDetails addSimple(BaseFont bf) {
+ if (bf.getFontType() == BaseFont.FONT_TYPE_DOCUMENT) {
+ return new FontDetails(new PdfName("F" + (fontNumber++)), ((DocumentFont)bf).getIndirectReference(), bf);
+ }
+ FontDetails ret = (FontDetails)documentFonts.get(bf);
+ if (ret == null) {
+ checkPDFXConformance(this, PDFXKEY_FONT, bf);
+ ret = new FontDetails(new PdfName("F" + (fontNumber++)), body.getPdfIndirectReference(), bf);
+ documentFonts.put(bf, ret);
+ }
+ return ret;
+ }
+
+ void eliminateFontSubset(PdfDictionary fonts) {
+ for (Iterator it = documentFonts.values().iterator(); it.hasNext();) {
+ FontDetails ft = (FontDetails)it.next();
+ if (fonts.get(ft.getFontName()) != null)
+ ft.setSubset(false);
+ }
+ }
+
+ PdfName getColorspaceName() {
+ return new PdfName("CS" + (colorNumber++));
+ }
+
+ /**
+ * Adds a SpotColor
to the document but not to the page resources.
+ * @param spc the SpotColor
to add
+ * @return an Object[]
where position 0 is a PdfName
+ * and position 1 is an PdfIndirectReference
+ */
+
+ ColorDetails addSimple(PdfSpotColor spc) {
+ ColorDetails ret = (ColorDetails)documentColors.get(spc);
+ if (ret == null) {
+ ret = new ColorDetails(getColorspaceName(), body.getPdfIndirectReference(), spc);
+ documentColors.put(spc, ret);
+ }
+ return ret;
+ }
+
+ ColorDetails addSimplePatternColorspace(Color color) {
+ int type = ExtendedColor.getType(color);
+ if (type == ExtendedColor.TYPE_PATTERN || type == ExtendedColor.TYPE_SHADING)
+ throw new RuntimeException("An uncolored tile pattern can not have another pattern or shading as color.");
+ try {
+ switch (type) {
+ case ExtendedColor.TYPE_RGB:
+ if (patternColorspaceRGB == null) {
+ patternColorspaceRGB = new ColorDetails(getColorspaceName(), body.getPdfIndirectReference(), null);
+ PdfArray array = new PdfArray(PdfName.PATTERN);
+ array.add(PdfName.DEVICERGB);
+ addToBody(array, patternColorspaceRGB.getIndirectReference());
+ }
+ return patternColorspaceRGB;
+ case ExtendedColor.TYPE_CMYK:
+ if (patternColorspaceCMYK == null) {
+ patternColorspaceCMYK = new ColorDetails(getColorspaceName(), body.getPdfIndirectReference(), null);
+ PdfArray array = new PdfArray(PdfName.PATTERN);
+ array.add(PdfName.DEVICECMYK);
+ addToBody(array, patternColorspaceCMYK.getIndirectReference());
+ }
+ return patternColorspaceCMYK;
+ case ExtendedColor.TYPE_GRAY:
+ if (patternColorspaceGRAY == null) {
+ patternColorspaceGRAY = new ColorDetails(getColorspaceName(), body.getPdfIndirectReference(), null);
+ PdfArray array = new PdfArray(PdfName.PATTERN);
+ array.add(PdfName.DEVICEGRAY);
+ addToBody(array, patternColorspaceGRAY.getIndirectReference());
+ }
+ return patternColorspaceGRAY;
+ case ExtendedColor.TYPE_SEPARATION: {
+ ColorDetails details = addSimple(((SpotColor)color).getPdfSpotColor());
+ ColorDetails patternDetails = (ColorDetails)documentSpotPatterns.get(details);
+ if (patternDetails == null) {
+ patternDetails = new ColorDetails(getColorspaceName(), body.getPdfIndirectReference(), null);
+ PdfArray array = new PdfArray(PdfName.PATTERN);
+ array.add(details.getIndirectReference());
+ addToBody(array, patternDetails.getIndirectReference());
+ documentSpotPatterns.put(details, patternDetails);
+ }
+ return patternDetails;
+ }
+ default:
+ throw new RuntimeException("Invalid color type in PdfWriter.addSimplePatternColorspace().");
+ }
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ void addSimpleShadingPattern(PdfShadingPattern shading) {
+ if (!documentShadingPatterns.containsKey(shading)) {
+ shading.setName(patternNumber);
+ ++patternNumber;
+ documentShadingPatterns.put(shading, null);
+ addSimpleShading(shading.getShading());
+ }
+ }
+
+ void addSimpleShading(PdfShading shading) {
+ if (!documentShadings.containsKey(shading)) {
+ documentShadings.put(shading, null);
+ shading.setName(documentShadings.size());
+ }
+ }
+
+ PdfObject[] addSimpleExtGState(PdfDictionary gstate) {
+ if (!documentExtGState.containsKey(gstate)) {
+ checkPDFXConformance(this, PDFXKEY_GSTATE, gstate);
+ documentExtGState.put(gstate, new PdfObject[]{new PdfName("GS" + (documentExtGState.size() + 1)), getPdfIndirectReference()});
+ }
+ return (PdfObject[])documentExtGState.get(gstate);
+ }
+
+ void registerLayer(PdfOCG layer) {
+ checkPDFXConformance(this, PDFXKEY_LAYER, null);
+ if (layer instanceof PdfLayer) {
+ PdfLayer la = (PdfLayer)layer;
+ if (la.getTitle() == null) {
+ if (!documentOCG.contains(layer)) {
+ documentOCG.add(layer);
+ documentOCGorder.add(layer);
+ }
+ }
+ else {
+ documentOCGorder.add(layer);
+ }
+ }
+ else
+ throw new IllegalArgumentException("Only PdfLayer is accepted.");
+ }
+
+ PdfObject[] addSimpleProperty(Object prop, PdfIndirectReference refi) {
+ if (!documentProperties.containsKey(prop)) {
+ if (prop instanceof PdfOCG)
+ checkPDFXConformance(this, PDFXKEY_LAYER, null);
+ documentProperties.put(prop, new PdfObject[]{new PdfName("Pr" + (documentProperties.size() + 1)), refi});
+ }
+ return (PdfObject[])documentProperties.get(prop);
+ }
+
+ boolean propertyExists(Object prop) {
+ return documentProperties.containsKey(prop);
+ }
+ /**
+ * Gets the PdfDocument
associated with this writer.
+ * @return the PdfDocument
+ */
+
+ PdfDocument getPdfDocument() {
+ return pdf;
+ }
+
+ /**
+ * Gets a PdfIndirectReference
for an object that
+ * will be created in the future.
+ * @return the PdfIndirectReference
+ */
+
+ public PdfIndirectReference getPdfIndirectReference() {
+ return body.getPdfIndirectReference();
+ }
+ /*
+ // ssteward: pdftk 1.46; complement to PdfReader.getPRIndirectReference( PdfObject )
+ PdfIndirectReference getPdfIndirectReference( PdfObject obj ) {
+ PdfIndirectReference rr= body.getPdfIndirectReference();
+ try {
+ addToBody( obj, rr );
+ }
+ catch( IOException ioe ) {
+ rr= null;
+ }
+ return rr;
+ }
+ */
+
+ int getIndirectReferenceNumber() {
+ return body.getIndirectReferenceNumber();
+ }
+
+ PdfName addSimplePattern(PdfPatternPainter painter) {
+ PdfName name = (PdfName)documentPatterns.get(painter);
+ try {
+ if ( name == null ) {
+ name = new PdfName("P" + patternNumber);
+ ++patternNumber;
+ documentPatterns.put(painter, name);
+ }
+ } catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ return name;
+ }
+
+ /**
+ * Adds a template to the document but not to the page resources.
+ * @param template the template to add
+ * @param forcedName the template name, rather than a generated one. Can be null
+ * @return the PdfName
for this template
+ */
+
+ PdfName addDirectTemplateSimple(PdfTemplate template, PdfName forcedName) {
+ PdfIndirectReference ref = template.getIndirectReference();
+ Object obj[] = (Object[])formXObjects.get(ref);
+ PdfName name = null;
+ try {
+ if (obj == null) {
+ if (forcedName == null) {
+ name = new PdfName("Xf" + formXObjectsCounter);
+ ++formXObjectsCounter;
+ }
+ else
+ name = forcedName;
+ if (template.getType() == PdfTemplate.TYPE_IMPORTED)
+ template = null;
+ formXObjects.put(ref, new Object[]{name, template});
+ }
+ else
+ name = (PdfName)obj[0];
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ return name;
+ }
+
+ /**
+ * Sets the PdfPageEvent
for this document.
+ * @param pageEvent the PdfPageEvent
for this document
+ */
+
+ public void setPageEvent(PdfPageEvent pageEvent) {
+ this.pageEvent = pageEvent;
+ }
+
+ /**
+ * Gets the PdfPageEvent
for this document or null
+ * if none is set.
+ * @return the PdfPageEvent
for this document or null
+ * if none is set
+ */
+
+ public PdfPageEvent getPageEvent() {
+ return pageEvent;
+ }
+
+ /**
+ * Adds the local destinations to the body of the document.
+ * @param dest the HashMap
containing the destinations
+ * @throws IOException on error
+ */
+
+ void addLocalDestinations(TreeMap dest) throws IOException {
+ for (Iterator i = dest.keySet().iterator(); i.hasNext();) {
+ String name = (String)i.next();
+ Object obj[] = (Object[])dest.get(name);
+ PdfDestination destination = (PdfDestination)obj[2];
+ if (destination == null)
+ throw new RuntimeException("The name '" + name + "' has no local destination.");
+ if (obj[1] == null)
+ obj[1] = getPdfIndirectReference();
+ addToBody(destination, (PdfIndirectReference)obj[1]);
+ }
+ }
+
+ /**
+ * Gets the current pagenumber of this document.
+ *
+ * @return a page number
+ */
+
+ public int getPageNumber() {
+ return pdf.getPageNumber();
+ }
+
+ /**
+ * Sets the viewer preferences by ORing some constants.
+ *
+ *
+ * The page layout to be used when the document is opened (choose one).
+ *
+ * PageLayoutSinglePage - Display one page at a time. (default)
+ * PageLayoutOneColumn - Display the pages in one column.
+ * PageLayoutTwoColumnLeft - Display the pages in two columns, with
+ * oddnumbered pages on the left.
+ * PageLayoutTwoColumnRight - Display the pages in two columns, with
+ * oddnumbered pages on the right.
+ *
+ * The page mode how the document should be displayed
+ * when opened (choose one).
+ *
+ * PageModeUseNone - Neither document outline nor thumbnail images visible. (default)
+ * PageModeUseOutlines - Document outline visible.
+ * PageModeUseThumbs - Thumbnail images visible.
+ * PageModeFullScreen - Full-screen mode, with no menu bar, window
+ * controls, or any other window visible.
+ * PageModeUseOC - Optional content group panel visible
+ *
+ * HideToolbar - A flag specifying whether to hide the viewer application's tool
+ * bars when the document is active.
+ * HideMenubar - A flag specifying whether to hide the viewer application's
+ * menu bar when the document is active.
+ * HideWindowUI - A flag specifying whether to hide user interface elements in
+ * the document's window (such as scroll bars and navigation controls),
+ * leaving only the document's contents displayed.
+ * FitWindow - A flag specifying whether to resize the document's window to
+ * fit the size of the first displayed page.
+ * CenterWindow - A flag specifying whether to position the document's window
+ * in the center of the screen.
+ * DisplayDocTitle - A flag specifying whether to display the document's title
+ * in the top bar.
+ * The predominant reading order for text. This entry has no direct effect on the
+ * document's contents or page numbering, but can be used to determine the relative
+ * positioning of pages when displayed side by side or printed n-up (choose one).
+ *
+ * DirectionL2R - Left to right
+ * DirectionR2L - Right to left (including vertical writing systems such as
+ * Chinese, Japanese, and Korean)
+ *
+ * The document's page mode, specifying how to display the
+ * document on exiting full-screen mode. It is meaningful only
+ * if the page mode is PageModeFullScreen (choose one).
+ *
+ * NonFullScreenPageModeUseNone - Neither document outline nor thumbnail images
+ * visible
+ * NonFullScreenPageModeUseOutlines - Document outline visible
+ * NonFullScreenPageModeUseThumbs - Thumbnail images visible
+ * NonFullScreenPageModeUseOC - Optional content group panel visible
+ *
+ * PrintScalingNone - Indicates that the print dialog should reflect no page scaling.
+ *
+ * @param preferences the viewer preferences
+ */
+
+ public void setViewerPreferences(int preferences) {
+ pdf.setViewerPreferences(preferences);
+ }
+
+ // types of encryption
+
+ /** Type of encryption */
+ public static final int STANDARD_ENCRYPTION_40 = 0;
+ /** Type of encryption */
+ public static final int STANDARD_ENCRYPTION_128 = 1;
+ /** Type of encryption */
+ public static final int ENCRYPTION_AES_128 = 2;
+ /** Mask to separate the encryption type from the encryption mode. */
+ static final int ENCRYPTION_MASK = 7;
+ /** Add this to the mode to keep the metadata in clear text */
+ public static final int DO_NOT_ENCRYPT_METADATA = 8;
+ /**
+ * Add this to the mode to keep encrypt only the embedded files.
+ * @since 2.1.3
+ */
+ public static final int EMBEDDED_FILES_ONLY = 24;
+
+ // permissions
+
+ /** The operation permitted when the document is opened with the user password
+ */
+ public static final int ALLOW_PRINTING = 4 + 2048;
+
+ /** The operation permitted when the document is opened with the user password
+ */
+ public static final int ALLOW_MODIFY_CONTENTS = 8;
+
+ /** The operation permitted when the document is opened with the user password
+ */
+ public static final int ALLOW_COPY = 16;
+
+ /** The operation permitted when the document is opened with the user password
+ */
+ public static final int ALLOW_MODIFY_ANNOTATIONS = 32;
+
+ /** The operation permitted when the document is opened with the user password
+ */
+ public static final int ALLOW_FILL_IN = 256;
+
+ /** The operation permitted when the document is opened with the user password
+ */
+ public static final int ALLOW_SCREENREADERS = 512;
+
+ /** The operation permitted when the document is opened with the user password
+ */
+ public static final int ALLOW_ASSEMBLY = 1024;
+
+ /** The operation permitted when the document is opened with the user password
+ */
+ public static final int ALLOW_DEGRADED_PRINTING = 4;
+
+ protected PdfEncryption crypto;
+ PdfEncryption getEncryption() {
+ return crypto;
+ }
+
+ /** Sets the encryption options for this document. The userPassword and the
+ * ownerPassword can be null or have zero length. In this case the ownerPassword
+ * is replaced by a random string. The open permissions for the document can be
+ * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
+ * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
+ * The permissions can be combined by ORing them.
+ * @param userPassword the user password. Can be null or empty
+ * @param ownerPassword the owner password. Can be null or empty
+ * @param permissions the user permissions
+ * @param strength128Bits true
for 128 bit key length, false
for 40 bit key length
+ * @throws DocumentException if the document is already open
+ */
+ public void setEncryption(byte userPassword[], byte ownerPassword[], int permissions, boolean strength128Bits) throws DocumentException {
+ setEncryption(userPassword, ownerPassword, permissions, strength128Bits ? STANDARD_ENCRYPTION_128 : STANDARD_ENCRYPTION_40);
+ }
+ //
+ public void setEncryption(byte userPassword[], byte ownerPassword[], int permissions, int encryptionType) throws DocumentException {
+ if (pdf.isOpen())
+ throw new DocumentException("Encryption can only be added before opening the document.");
+ crypto = new PdfEncryption();
+ crypto.setCryptoMode(encryptionType, 0);
+ crypto.setupAllKeys(userPassword, ownerPassword, permissions);
+ }
+
+ /**
+ * Sets the encryption options for this document. The userPassword and the
+ * ownerPassword can be null or have zero length. In this case the ownerPassword
+ * is replaced by a random string. The open permissions for the document can be
+ * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
+ * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
+ * The permissions can be combined by ORing them.
+ * @param strength true
for 128 bit key length, false
for 40 bit key length
+ * @param userPassword the user password. Can be null or empty
+ * @param ownerPassword the owner password. Can be null or empty
+ * @param permissions the user permissions
+ * @throws DocumentException if the document is already open
+ */
+ /*
+ public void setEncryption(boolean strength, String userPassword, String ownerPassword, int permissions) throws DocumentException {
+ setEncryption(getISOBytes(userPassword), getISOBytes(ownerPassword), permissions, strength);
+ }
+ */
+
+ /**
+ * Adds an object to the PDF body.
+ * @param object
+ * @return a PdfIndirectObject
+ * @throws IOException
+ */
+ public PdfIndirectObject addToBody(PdfObject object) throws IOException {
+ PdfIndirectObject iobj = body.add(object);
+ return iobj;
+ }
+
+ /**
+ * Adds an object to the PDF body.
+ * @param object
+ * @param inObjStm
+ * @return a PdfIndirectObject
+ * @throws IOException
+ */
+ public PdfIndirectObject addToBody(PdfObject object, boolean inObjStm) throws IOException {
+ PdfIndirectObject iobj = body.add(object, inObjStm);
+ return iobj;
+ }
+
+ /**
+ * Adds an object to the PDF body.
+ * @param object
+ * @param ref
+ * @return a PdfIndirectObject
+ * @throws IOException
+ */
+ public PdfIndirectObject addToBody(PdfObject object, PdfIndirectReference ref) throws IOException {
+ PdfIndirectObject iobj = body.add(object, ref);
+ return iobj;
+ }
+
+ /**
+ * Adds an object to the PDF body.
+ * @param object
+ * @param ref
+ * @param inObjStm
+ * @return a PdfIndirectObject
+ * @throws IOException
+ */
+ public PdfIndirectObject addToBody(PdfObject object, PdfIndirectReference ref, boolean inObjStm) throws IOException {
+ PdfIndirectObject iobj = body.add(object, ref, inObjStm);
+ return iobj;
+ }
+
+ /**
+ * Adds an object to the PDF body.
+ * @param object
+ * @param refNumber
+ * @return a PdfIndirectObject
+ * @throws IOException
+ */
+ public PdfIndirectObject addToBody(PdfObject object, int refNumber) throws IOException {
+ PdfIndirectObject iobj = body.add(object, refNumber);
+ return iobj;
+ }
+
+ /**
+ * Adds an object to the PDF body.
+ * @param object
+ * @param refNumber
+ * @param inObjStm
+ * @return a PdfIndirectObject
+ * @throws IOException
+ */
+ public PdfIndirectObject addToBody(PdfObject object, int refNumber, boolean inObjStm) throws IOException {
+ PdfIndirectObject iobj = body.add(object, refNumber, inObjStm);
+ return iobj;
+ }
+
+ /** When the document opens it will jump to the destination with
+ * this name.
+ * @param name the name of the destination to jump to
+ */
+ public void setOpenAction(String name) {
+ pdf.setOpenAction(name);
+ }
+
+ /** Additional-actions defining the actions to be taken in
+ * response to various trigger events affecting the document
+ * as a whole. The actions types allowed are: DOCUMENT_CLOSE
,
+ * WILL_SAVE
, DID_SAVE
, WILL_PRINT
+ * and DID_PRINT
.
+ *
+ * @param actionType the action type
+ * @param action the action to execute in response to the trigger
+ * @throws PdfException on invalid action type
+ */
+ public void setAdditionalAction(PdfName actionType, PdfAction action) throws PdfException {
+ if (!(actionType.equals(DOCUMENT_CLOSE) ||
+ actionType.equals(WILL_SAVE) ||
+ actionType.equals(DID_SAVE) ||
+ actionType.equals(WILL_PRINT) ||
+ actionType.equals(DID_PRINT))) {
+ throw new PdfException("Invalid additional action type: " + actionType.toString());
+ }
+ pdf.addAdditionalAction(actionType, action);
+ }
+
+ /** When the document opens this action
will be
+ * invoked.
+ * @param action the action to be invoked
+ */
+ public void setOpenAction(PdfAction action) {
+ pdf.setOpenAction(action);
+ }
+
+ /** Sets the page labels
+ * @param pageLabels the page labels
+ */
+ public void setPageLabels(PdfPageLabels pageLabels) {
+ pdf.setPageLabels(pageLabels);
+ }
+
+ RandomAccessFileOrArray getReaderFile(PdfReader reader) {
+ return currentPdfReaderInstance.getReaderFile();
+ }
+
+ protected int getNewObjectNumber(PdfReader reader, int number, int generation) {
+ return currentPdfReaderInstance.getNewObjectNumber(number, generation);
+ }
+
+ /** Gets a page from other PDF document. The page can be used as
+ * any other PdfTemplate. Note that calling this method more than
+ * once with the same parameters will retrieve the same object.
+ * @param reader the PDF document where the page is
+ * @param pageNumber the page number. The first page is 1
+ * @return the template representing the imported page
+ */
+ public PdfImportedPage getImportedPage(PdfReader reader, int pageNumber) {
+ PdfReaderInstance inst = (PdfReaderInstance)importedPages.get(reader);
+ if (inst == null) {
+ inst = reader.getPdfReaderInstance(this);
+ importedPages.put(reader, inst);
+ }
+ return inst.getImportedPage(pageNumber);
+ }
+
+ /** Adds a JavaScript action at the document level. When the document
+ * opens all this JavaScript runs.
+ * @param js The JavaScrip action
+ */
+ public void addJavaScript(PdfAction js) {
+ pdf.addJavaScript(js);
+ }
+
+ /** Adds a JavaScript action at the document level. When the document
+ * opens all this JavaScript runs.
+ * @param code the JavaScript code
+ * @param unicode select JavaScript unicode. Note that the internal
+ * Acrobat JavaScript engine does not support unicode,
+ * so this may or may not work for you
+ */
+ public void addJavaScript(String code, boolean unicode) {
+ addJavaScript(PdfAction.javaScript(code, this, unicode));
+ }
+
+ /** Adds a JavaScript action at the document level. When the document
+ * opens all this JavaScript runs.
+ * @param code the JavaScript code
+ */
+ public void addJavaScript(String code) {
+ addJavaScript(code, false);
+ }
+
+ /** Sets the crop box. The crop box should not be rotated even if the
+ * page is rotated. This change only takes effect in the next
+ * page.
+ * @param crop the crop box
+ */
+ public void setCropBoxSize(Rectangle crop) {
+ pdf.setCropBoxSize(crop);
+ }
+
+ /** Gets a reference to a page existing or not. If the page does not exist
+ * yet the reference will be created in advance. If on closing the document, a
+ * page number greater than the total number of pages was requested, an
+ * exception is thrown.
+ * @param page the page number. The first page is 1
+ * @return the reference to the page
+ */
+ public PdfIndirectReference getPageReference(int page) {
+ --page;
+ if (page < 0)
+ throw new IndexOutOfBoundsException("The page numbers start at 1.");
+ PdfIndirectReference ref;
+ if (page < pageReferences.size()) {
+ ref = (PdfIndirectReference)pageReferences.get(page);
+ if (ref == null) {
+ ref = body.getPdfIndirectReference();
+ pageReferences.set(page, ref);
+ }
+ }
+ else {
+ int empty = page - pageReferences.size();
+ for (int k = 0; k < empty; ++k)
+ pageReferences.add(null);
+ ref = body.getPdfIndirectReference();
+ pageReferences.add(ref);
+ }
+ return ref;
+ }
+
+ PdfIndirectReference getCurrentPage() {
+ return getPageReference(currentPageNumber);
+ }
+
+ int getCurrentPageNumber() {
+ return currentPageNumber;
+ }
+
+ /** Adds the PdfAnnotation
to the calculation order
+ * array.
+ * @param annot the PdfAnnotation
to be added
+ */
+ public void addCalculationOrder(PdfFormField annot) {
+ pdf.addCalculationOrder(annot);
+ }
+
+ /** Set the signature flags.
+ * @param f the flags. This flags are ORed with current ones
+ */
+ public void setSigFlags(int f) {
+ pdf.setSigFlags(f);
+ }
+
+ /** Adds a PdfAnnotation
or a PdfFormField
+ * to the document. Only the top parent of a PdfFormField
+ * needs to be added.
+ * @param annot the PdfAnnotation
or the PdfFormField
to add
+ */
+ public void addAnnotation(PdfAnnotation annot) {
+ pdf.addAnnotation(annot);
+ }
+
+ void addAnnotation(PdfAnnotation annot, int page) {
+ addAnnotation(annot);
+ }
+
+ /** Sets the PDF version. Must be used right before the document
+ * is opened. Valid options are VERSION_1_2, VERSION_1_3,
+ * VERSION_1_4, VERSION_1_5 and VERSION_1_6. VERSION_1_4 is the default.
+ * @param version the version number
+ */
+ public void setPdfVersion(char version) {
+ if (HEADER.length > VPOINT)
+ HEADER[VPOINT] = (byte)version;
+ }
+
+ /** Reorder the pages in the document. A null
argument value
+ * only returns the number of pages to process. It is
+ * advisable to issue a Document.newPage()
+ * before using this method.
+ * @return the total number of pages
+ * @param order an array with the new page sequence. It must have the
+ * same size as the number of pages.
+ * @throws DocumentException if all the pages are not present in the array
+ */
+ public int reorderPages(int order[]) throws DocumentException {
+ return root.reorderPages(order);
+ }
+
+ /** Gets the space/character extra spacing ratio for
+ * fully justified text.
+ * @return the space/character extra spacing ratio
+ */
+ public float getSpaceCharRatio() {
+ return spaceCharRatio;
+ }
+
+ /** Sets the ratio between the extra word spacing and the extra character spacing
+ * when the text is fully justified.
+ * Extra word spacing will grow spaceCharRatio
times more than extra character spacing.
+ * If the ratio is PdfWriter.NO_SPACE_CHAR_RATIO
then the extra character spacing
+ * will be zero.
+ * @param spaceCharRatio the ratio between the extra word spacing and the extra character spacing
+ */
+ public void setSpaceCharRatio(float spaceCharRatio) {
+ if (spaceCharRatio < 0.001f)
+ this.spaceCharRatio = 0.001f;
+ else
+ this.spaceCharRatio = spaceCharRatio;
+ }
+
+ /** Sets the run direction. This is only used as a placeholder
+ * as it does not affect anything.
+ * @param runDirection the run direction
+ */
+ public void setRunDirection(int runDirection) {
+ if (runDirection < RUN_DIRECTION_NO_BIDI || runDirection > RUN_DIRECTION_RTL)
+ throw new RuntimeException("Invalid run direction: " + runDirection);
+ this.runDirection = runDirection;
+ }
+
+ /** Gets the run direction.
+ * @return the run direction
+ */
+ public int getRunDirection() {
+ return runDirection;
+ }
+
+ /**
+ * Sets the display duration for the page (for presentations)
+ * @param seconds the number of seconds to display the page
+ */
+ public void setDuration(int seconds) {
+ pdf.setDuration(seconds);
+ }
+
+ /**
+ * Sets the transition for the page
+ * @param transition the Transition object
+ */
+ public void setTransition(PdfTransition transition) {
+ pdf.setTransition(transition);
+ }
+
+ /** Writes the reader to the document and frees the memory used by it.
+ * The main use is when concatenating multiple documents to keep the
+ * memory usage restricted to the current appending document.
+ * @param reader the PdfReader
to free
+ * @throws IOException on error
+ */
+ public void freeReader(PdfReader reader) throws IOException {
+ currentPdfReaderInstance = (PdfReaderInstance)importedPages.get(reader);
+ if (currentPdfReaderInstance == null)
+ return;
+ currentPdfReaderInstance.writeAllPages();
+ currentPdfReaderInstance = null;
+ importedPages.remove(reader);
+ }
+
+ /** Sets the open and close page additional action.
+ * @param actionType the action type. It can be PdfWriter.PAGE_OPEN
+ * or PdfWriter.PAGE_CLOSE
+ * @param action the action to perform
+ * @throws PdfException if the action type is invalid
+ */
+ public void setPageAction(PdfName actionType, PdfAction action) throws PdfException {
+ if (!actionType.equals(PAGE_OPEN) && !actionType.equals(PAGE_CLOSE))
+ throw new PdfException("Invalid page additional action type: " + actionType.toString());
+ pdf.setPageAction(actionType, action);
+ }
+
+ /** Gets the current document size. This size only includes
+ * the data already writen to the output stream, it does not
+ * include templates or fonts. It is usefull if used with
+ * freeReader()
when concatenating many documents
+ * and an idea of the current size is needed.
+ * @return the approximate size without fonts or templates
+ */
+ public int getCurrentDocumentSize() {
+ return body.offset() + body.size() * 20 + 0x48;
+ }
+
+ /** Getter for property strictImageSequence.
+ * @return value of property strictImageSequence
+ *
+ */
+ public boolean isStrictImageSequence() {
+ return pdf.isStrictImageSequence();
+ }
+
+ /** Sets the image sequence to follow the text in strict order.
+ * @param strictImageSequence new value of property strictImageSequence
+ *
+ */
+ public void setStrictImageSequence(boolean strictImageSequence) {
+ pdf.setStrictImageSequence(strictImageSequence);
+ }
+
+ /**
+ * If you use setPageEmpty(false), invoking newPage() after a blank page will add a newPage.
+ * @param pageEmpty the state
+ */
+ public void setPageEmpty(boolean pageEmpty) {
+ pdf.setPageEmpty(pageEmpty);
+ }
+
+ /** Gets the info dictionary for changing.
+ * @return the info dictionary
+ */
+ public PdfDictionary getInfo() {
+ return ((PdfDocument)document).getInfo();
+ }
+
+ /**
+ * Sets extra keys to the catalog.
+ * @return the catalog to change
+ */
+ public PdfDictionary getExtraCatalog() {
+ if (extraCatalog == null)
+ extraCatalog = new PdfDictionary();
+ return this.extraCatalog;
+ }
+
+ /**
+ * Sets the document in a suitable way to do page reordering.
+ */
+ public void setLinearPageMode() {
+ root.setLinearMode(null);
+ }
+
+ /** Getter for property group.
+ * @return Value of property group.
+ *
+ */
+ public PdfDictionary getGroup() {
+ return this.group;
+ }
+
+ /** Setter for property group.
+ * @param group New value of property group.
+ *
+ */
+ public void setGroup(PdfDictionary group) {
+ this.group = group;
+ }
+
+ /**
+ * Sets the PDFX conformance level. Allowed values are PDFX1A2001 and PDFX32002. It
+ * must be called before opening the document.
+ * @param pdfxConformance the conformance level
+ */
+ public void setPDFXConformance(int pdfxConformance) {
+ if (this.pdfxConformance == pdfxConformance)
+ return;
+ if (pdf.isOpen())
+ throw new PdfXConformanceException("PDFX conformance can only be set before opening the document.");
+ if (crypto != null)
+ throw new PdfXConformanceException("A PDFX conforming document cannot be encrypted.");
+ if (pdfxConformance != PDFXNONE)
+ setPdfVersion(VERSION_1_3);
+ this.pdfxConformance = pdfxConformance;
+ }
+
+ /**
+ * Gets the PDFX conformance level.
+ * @return the PDFX conformance level
+ */
+ public int getPDFXConformance() {
+ return pdfxConformance;
+ }
+
+ static void checkPDFXConformance(PdfWriter writer, int key, Object obj1) {
+ if (writer == null || writer.pdfxConformance == PDFXNONE)
+ return;
+ int conf = writer.pdfxConformance;
+ switch (key) {
+ case PDFXKEY_COLOR:
+ switch (conf) {
+ case PDFX1A2001:
+ if (obj1 instanceof ExtendedColor) {
+ ExtendedColor ec = (ExtendedColor)obj1;
+ switch (ec.getType()) {
+ case ExtendedColor.TYPE_CMYK:
+ case ExtendedColor.TYPE_GRAY:
+ return;
+ case ExtendedColor.TYPE_RGB:
+ throw new PdfXConformanceException("Colorspace RGB is not allowed.");
+ case ExtendedColor.TYPE_SEPARATION:
+ SpotColor sc = (SpotColor)ec;
+ checkPDFXConformance(writer, PDFXKEY_COLOR, sc.getPdfSpotColor().getAlternativeCS());
+ break;
+ case ExtendedColor.TYPE_SHADING:
+ ShadingColor xc = (ShadingColor)ec;
+ checkPDFXConformance(writer, PDFXKEY_COLOR, xc.getPdfShadingPattern().getShading().getColorSpace());
+ break;
+ case ExtendedColor.TYPE_PATTERN:
+ PatternColor pc = (PatternColor)ec;
+ checkPDFXConformance(writer, PDFXKEY_COLOR, pc.getPainter().getDefaultColor());
+ break;
+ }
+ }
+ else if (obj1 instanceof Color)
+ throw new PdfXConformanceException("Colorspace RGB is not allowed.");
+ break;
+ }
+ break;
+ case PDFXKEY_CMYK:
+ break;
+ case PDFXKEY_RGB:
+ if (conf == PDFX1A2001)
+ throw new PdfXConformanceException("Colorspace RGB is not allowed.");
+ break;
+ case PDFXKEY_FONT:
+ if (!((BaseFont)obj1).isEmbedded())
+ throw new PdfXConformanceException("All the fonts must be embedded.");
+ break;
+ case PDFXKEY_IMAGE:
+ break;
+ /*
+ PdfImage image = (PdfImage)obj1;
+ if (image.get(PdfName.SMASK) != null)
+ throw new PdfXConformanceException("The /SMask key is not allowed in images.");
+ switch (conf) {
+ case PDFX1A2001:
+ PdfObject cs = image.get(PdfName.COLORSPACE);
+ if (cs == null)
+ return;
+ if (cs.isName()) {
+ if (PdfName.DEVICERGB.equals(cs))
+ throw new PdfXConformanceException("Colorspace RGB is not allowed.");
+ }
+ else if (cs.isArray()) {
+ if (PdfName.CALRGB.equals((PdfObject)((PdfArray)cs).getArrayList().get(0)))
+ throw new PdfXConformanceException("Colorspace CalRGB is not allowed.");
+ }
+ break;
+ }
+ */
+ case PDFXKEY_GSTATE:
+ PdfDictionary gs = (PdfDictionary)obj1;
+ PdfObject obj = gs.get(PdfName.BM);
+ if (obj != null && !PdfGState.BM_NORMAL.equals(obj) && !PdfGState.BM_COMPATIBLE.equals(obj))
+ throw new PdfXConformanceException("Blend mode " + obj.toString() + " not allowed.");
+ obj = gs.get(PdfName.CA);
+ double v = 0.0;
+ if (obj != null && (v = ((PdfNumber)obj).doubleValue()) != 1.0)
+ throw new PdfXConformanceException("Transparency is not allowed: /CA = " + v);
+ obj = gs.get(PdfName.ca);
+ v = 0.0;
+ if (obj != null && (v = ((PdfNumber)obj).doubleValue()) != 1.0)
+ throw new PdfXConformanceException("Transparency is not allowed: /ca = " + v);
+ break;
+ case PDFXKEY_LAYER:
+ throw new PdfXConformanceException("Layers are not allowed.");
+ }
+ }
+
+ /**
+ * Sets the values of the output intent dictionary. Null values are allowed to
+ * suppress any key.
+ * @param outputConditionIdentifier a value
+ * @param outputCondition a value
+ * @param registryName a value
+ * @param info a value
+ * @param destOutputProfile a value
+ * @throws IOException on error
+ */
+ public void setOutputIntents(String outputConditionIdentifier, String outputCondition, String registryName, String info, byte destOutputProfile[]) throws IOException {
+ getExtraCatalog();
+ PdfDictionary out = new PdfDictionary(PdfName.OUTPUTINTENT);
+ if (outputCondition != null)
+ out.put(PdfName.OUTPUTCONDITION, new PdfString(outputCondition, PdfObject.TEXT_UNICODE));
+ if (outputConditionIdentifier != null)
+ out.put(PdfName.OUTPUTCONDITIONIDENTIFIER, new PdfString(outputConditionIdentifier, PdfObject.TEXT_UNICODE));
+ if (registryName != null)
+ out.put(PdfName.REGISTRYNAME, new PdfString(registryName, PdfObject.TEXT_UNICODE));
+ if (info != null)
+ out.put(PdfName.INFO, new PdfString(registryName, PdfObject.TEXT_UNICODE));
+ if (destOutputProfile != null) {
+ PdfStream stream = new PdfStream(destOutputProfile);
+ stream.flateCompress();
+ out.put(PdfName.DESTOUTPUTPROFILE, addToBody(stream).getIndirectReference());
+ }
+ out.put(PdfName.S, PdfName.GTS_PDFX);
+ extraCatalog.put(PdfName.OUTPUTINTENTS, new PdfArray(out));
+ }
+
+ private static String getNameString(PdfDictionary dic, PdfName key) {
+ PdfObject obj = PdfReader.getPdfObject(dic.get(key));
+ if (obj == null || !obj.isString())
+ return null;
+ return ((PdfString)obj).toUnicodeString();
+ }
+
+ /**
+ * Copies the output intent dictionary from other document to this one.
+ * @param reader the other document
+ * @param checkExistence true
to just check for the existence of a valid output intent
+ * dictionary, false
to insert the dictionary if it exists
+ * @throws IOException on error
+ * @return true
if the output intent dictionary exists, false
+ * otherwise
+ */
+ public boolean setOutputIntents(PdfReader reader, boolean checkExistence) throws IOException {
+ PdfDictionary catalog = reader.getCatalog();
+ PdfArray outs = (PdfArray)PdfReader.getPdfObject(catalog.get(PdfName.OUTPUTINTENTS));
+ if (outs == null)
+ return false;
+ ArrayList arr = outs.getArrayList();
+ if (arr.size() == 0)
+ return false;
+ PdfDictionary out = (PdfDictionary)PdfReader.getPdfObject((PdfObject)arr.get(0));
+ PdfObject obj = PdfReader.getPdfObject(out.get(PdfName.S));
+ if (obj == null || !PdfName.GTS_PDFX.equals(obj))
+ return false;
+ if (checkExistence)
+ return true;
+ PRStream stream = (PRStream)PdfReader.getPdfObject(out.get(PdfName.DESTOUTPUTPROFILE));
+ byte destProfile[] = null;
+ if (stream != null) {
+ destProfile = PdfReader.getStreamBytes(stream);
+ }
+ setOutputIntents(getNameString(out, PdfName.OUTPUTCONDITIONIDENTIFIER), getNameString(out, PdfName.OUTPUTCONDITION),
+ getNameString(out, PdfName.REGISTRYNAME), getNameString(out, PdfName.INFO), destProfile);
+ return true;
+ }
+
+ /**
+ * Sets the page box sizes. Allowed names are: "crop", "trim", "art" and "bleed".
+ * @param boxName the box size
+ * @param size the size
+ */
+ public void setBoxSize(String boxName, Rectangle size) {
+ pdf.setBoxSize(boxName, size);
+ }
+
+ /**
+ * Gets the default colorspaces.
+ * @return the default colorspaces
+ */
+ public PdfDictionary getDefaultColorspace() {
+ return defaultColorspace;
+ }
+
+ /**
+ * Sets the default colorspace that will be applied to all the document.
+ * The colorspace is only applied if another colorspace with the same name
+ * is not present in the content.
+ *
+ * The colorspace is applied immediately when creating templates and at the page
+ * end for the main document content.
+ * @param key the name of the colorspace. It can be PdfName.DEFAULTGRAY
, PdfName.DEFAULTRGB
+ * or PdfName.DEFAULTCMYK
+ * @param cs the colorspace. A null
or PdfNull
removes any colorspace with the same name
+ */
+ public void setDefaultColorspace(PdfName key, PdfObject cs) {
+ if (cs == null || cs.isNull())
+ defaultColorspace.remove(key);
+ defaultColorspace.put(key, cs);
+ }
+
+ /**
+ * Gets the 1.5 compression status.
+ * @return true
if the 1.5 compression is on
+ */
+ public boolean isFullCompression() {
+ return this.fullCompression;
+ }
+
+ /**
+ * Sets the document's compression to the new 1.5 mode with object streams and xref
+ * streams. It can be set at any time but once set it can't be unset.
+ *
+ * If set before opening the document it will also set the pdf version to 1.5.
+ */
+ public void setFullCompression() {
+ this.fullCompression = true;
+ setPdfVersion(VERSION_1_5);
+ }
+
+ /**
+ * Gets the Optional Content Properties Dictionary . Each call fills the dictionary with the current layer
+ * state. It's advisable to only call this method right before close and do any modifications
+ * at that time.
+ * @return the Optional Content Properties Dictionary
+ */
+ public PdfOCProperties getOCProperties() {
+ fillOCProperties(true);
+ return OCProperties;
+ }
+
+ /**
+ * Sets a collection of optional content groups whose states are intended to follow
+ * a "radio button" paradigm. That is, the state of at most one optional
+ * content group in the array should be ON at a time: if one group is turned
+ * ON, all others must be turned OFF.
+ * @param group the radio group
+ */
+ public void addOCGRadioGroup(ArrayList group) {
+ PdfArray ar = new PdfArray();
+ for (int k = 0; k < group.size(); ++k) {
+ PdfLayer layer = (PdfLayer)group.get(k);
+ if (layer.getTitle() == null)
+ ar.add(layer.getRef());
+ }
+ if (ar.size() == 0)
+ return;
+ OCGRadioGroup.add(ar);
+ }
+
+ /**
+ * Sets the the thumbnail image for the current page.
+ * @param image the image
+ * @throws PdfException on error
+ * @throws DocumentException or error
+ */
+ /* ssteward: dropped in 1.44
+ public void setThumbnail(Image image) throws PdfException, DocumentException {
+ pdf.setThumbnail(image);
+ }
+ */
+
+ /**
+ * A UserUnit is a value that defines the default user space unit.
+ * The minimum UserUnit is 1 (1 unit = 1/72 inch).
+ * The maximum UserUnit is 75,000.
+ * Remark that this userunit only works starting with PDF1.6!
+ * @return Returns the userunit.
+ */
+ public float getUserunit() {
+ return userunit;
+ }
+ /**
+ * A UserUnit is a value that defines the default user space unit.
+ * The minimum UserUnit is 1 (1 unit = 1/72 inch).
+ * The maximum UserUnit is 75,000.
+ * Remark that this userunit only works starting with PDF1.6!
+ * @param userunit The userunit to set.
+ * @throws DocumentException
+ */
+ public void setUserunit(float userunit) throws DocumentException {
+ if (userunit < 1f || userunit > 75000f) throw new DocumentException("UserUnit should be a value between 1 and 75000.");
+ this.userunit = userunit;
+ setPdfVersion(VERSION_1_6);
+ }
+
+ /**
+ * Sets XMP Metadata.
+ * @param xmpMetadata The xmpMetadata to set.
+ */
+ public void setXmpMetadata(byte[] xmpMetadata) {
+ this.xmpMetadata = xmpMetadata;
+ }
+
+ /**
+ * Creates XMP Metadata based on the metadata in the PdfDocument.
+ */
+ public void createXmpMetadata() {
+ setXmpMetadata(pdf.createXmpMetadata());
+ }
+
+ /**
+ * Releases the memory used by a template by writing it to the output. The template
+ * can still be added to any content but changes to the template itself won't have
+ * any effect.
+ * @param tp the template to release
+ * @throws IOException on error
+ */
+ public void releaseTemplate(PdfTemplate tp) throws IOException {
+ PdfIndirectReference ref = tp.getIndirectReference();
+ Object[] objs = (Object[])formXObjects.get(ref);
+ if (objs == null || objs[1] == null)
+ return;
+ PdfTemplate template = (PdfTemplate)objs[1];
+ if (template.getIndirectReference() instanceof PRIndirectReference)
+ return;
+ if (template.getType() == PdfTemplate.TYPE_TEMPLATE) {
+ addToBody(template.getFormXObject(), template.getIndirectReference());
+ objs[1] = null;
+ }
+ }
+
+ /**
+ * Mark this document for tagging. It must be called before open.
+ */
+ public void setTagged() {
+ if (open)
+ throw new IllegalArgumentException("Tagging must be set before opening the document.");
+ tagged = true;
+ }
+
+ /**
+ * Check if the document is marked for tagging.
+ * @return true
if the document is marked for tagging
+ */
+ public boolean isTagged() {
+ return tagged;
+ }
+
+ /**
+ * Set the PDF ID; ssteward
+ */
+ public void setFileID( PdfObject fileID ) {
+ this.fileID = fileID;
+ }
+
+ /**
+ * Get the pre-set PDF ID; ssteward
+ */
+ public PdfObject getFileID() {
+ return( this.fileID );
+ }
+
+ /**
+ * Gets the structure tree root. If the document is not marked for tagging it will return null
.
+ * @return the structure tree root
+ */
+ public PdfStructureTreeRoot getStructureTreeRoot() {
+ if (tagged && structureTreeRoot == null)
+ structureTreeRoot = new PdfStructureTreeRoot(this);
+ return structureTreeRoot;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfXConformanceException.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfXConformanceException.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/PdfXConformanceException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/PdfXConformanceException.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,60 @@
+/*
+ * $Id: PdfXConformanceException.java,v 1.2 2005/02/17 09:20:54 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2004 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ *
+ * @author psoares
+ */
+public class PdfXConformanceException extends RuntimeException {
+
+ /** Creates a new instance of PdfXConformanceException. */
+ public PdfXConformanceException() {
+ }
+
+ /**
+ * Creates a new instance of PdfXConformanceException.
+ * @param s
+ */
+ public PdfXConformanceException(String s) {
+ super(s);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/Pfm2afm.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/Pfm2afm.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/Pfm2afm.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/Pfm2afm.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,763 @@
+/*
+ * Copyright 2005 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+/********************************************************************
+ * *
+ * Title: pfm2afm - Convert Windows .pfm files to .afm files *
+ * *
+ * Author: Ken Borgendale 10/9/91 Version 1.0 *
+ * *
+ * Function: *
+ * Convert a Windows .pfm (Printer Font Metrics) file to a *
+ * .afm (Adobe Font Metrics) file. The purpose of this is *
+ * to allow fonts put out for Windows to be used with OS/2. *
+ * *
+ * Syntax: *
+ * pfm2afm infile [outfile] -a *
+ * *
+ * Copyright: *
+ * pfm2afm - Copyright (C) IBM Corp., 1991 *
+ * *
+ * This code is released for public use as long as the *
+ * copyright remains intact. This code is provided asis *
+ * without any warrenties, express or implied. *
+ * *
+ * Notes: *
+ * 1. Much of the information in the original .afm file is *
+ * lost when the .pfm file is created, and thus cannot be *
+ * reconstructed by this utility. This is especially true *
+ * of data for characters not in the Windows character set. *
+ * *
+ * 2. This module is coded to be compiled by the MSC 6.0. *
+ * For other compilers, be careful of the packing of the *
+ * PFM structure. *
+ * *
+ ********************************************************************/
+
+/********************************************************************
+ * *
+ * Modifications by Rod Smith, 5/22/96 *
+ * *
+ * These changes look for the strings "italic", "bold", "black", *
+ * and "light" in the font's name and set the weight accordingly *
+ * and adds an ItalicAngle line with a value of "0" or "-12.00". *
+ * This allows OS/2 programs such as DeScribe to handle the bold *
+ * and italic attributes appropriately, which was not the case *
+ * when I used the original version on fonts from the KeyFonts *
+ * Pro 2002 font CD. *
+ * *
+ * I've also increased the size of the buffer used to load the *
+ * .PFM file; the old size was inadequate for most of the fonts *
+ * from the SoftKey collection. *
+ * *
+ * Compiled with Watcom C 10.6 *
+ * *
+ ********************************************************************/
+
+/********************************************************************
+ * *
+ * Further modifications, 4/21/98, by Rod Smith *
+ * *
+ * Minor changes to get the program to compile with gcc under *
+ * Linux (Red Hat 5.0, to be precise). I had to add an itoa *
+ * function from the net (the function was buggy, so I had to fix *
+ * it, too!). I also made the program more friendly towards *
+ * files with mixed-case filenames. *
+ * *
+ ********************************************************************/
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.*;
+
+/**
+ * Converts a PFM file into an AFM file.
+ */
+public class Pfm2afm {
+ private RandomAccessFileOrArray in;
+ private PrintWriter out;
+
+ /** Creates a new instance of Pfm2afm */
+ private Pfm2afm(RandomAccessFileOrArray in, OutputStream out) throws IOException {
+ this.in = in;
+ this.out = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1"));
+ }
+
+ /**
+ * Converts a PFM file into an AFM file.
+ * @param in the PFM file
+ * @param out the AFM file
+ * @throws IOException on error
+ */
+ public static void convert(RandomAccessFileOrArray in, OutputStream out) throws IOException {
+ Pfm2afm p = new Pfm2afm(in, out);
+ p.openpfm();
+ p.putheader();
+ p.putchartab();
+ p.putkerntab();
+ p.puttrailer();
+ p.out.flush();
+ }
+
+ public static void main(String[] args) {
+ try {
+ RandomAccessFileOrArray in = new RandomAccessFileOrArray(args[0]);
+ OutputStream out = new FileOutputStream(args[1]);
+ convert(in, out);
+ in.close();
+ out.close();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String readString(int n) throws IOException {
+ byte b[] = new byte[n];
+ in.readFully(b);
+ int k;
+ for (k = 0; k < b.length; ++k) {
+ if (b[k] == 0)
+ break;
+ }
+ return new String(b, 0, k, "ISO-8859-1");
+ }
+
+ private String readString() throws IOException {
+ StringBuffer buf = new StringBuffer();
+ while (true) {
+ int c = in.read();
+ if (c <= 0)
+ break;
+ buf.append((char)c);
+ }
+ return buf.toString();
+ }
+
+ private void outval(int n) {
+ out.print(' ');
+ out.print(n);
+ }
+
+ /*
+ * Output a character entry
+ */
+ private void outchar(int code, int width, String name) {
+ out.print("C ");
+ outval(code);
+ out.print(" ; WX ");
+ outval(width);
+ if (name != null) {
+ out.print(" ; N ");
+ out.print(name);
+ }
+ out.print(" ;\n");
+ }
+
+ private void openpfm() throws IOException {
+ in.seek(0);
+ vers = in.readShortLE();
+ h_len = in.readIntLE();
+ copyright = readString(60);
+ type = in.readShortLE();
+ points = in.readShortLE();
+ verres = in.readShortLE();
+ horres = in.readShortLE();
+ ascent = in.readShortLE();
+ intleading = in.readShortLE();
+ extleading = in.readShortLE();
+ italic = (byte)in.read();
+ uline = (byte)in.read();
+ overs = (byte)in.read();
+ weight = in.readShortLE();
+ charset = (byte)in.read();
+ pixwidth = in.readShortLE();
+ pixheight = in.readShortLE();
+ kind = (byte)in.read();
+ avgwidth = in.readShortLE();
+ maxwidth = in.readShortLE();
+ firstchar = in.read();
+ lastchar = in.read();
+ defchar = (byte)in.read();
+ brkchar = (byte)in.read();
+ widthby = in.readShortLE();
+ device = in.readIntLE();
+ face = in.readIntLE();
+ bits = in.readIntLE();
+ bitoff = in.readIntLE();
+ extlen = in.readShortLE();
+ psext = in.readIntLE();
+ chartab = in.readIntLE();
+ res1 = in.readIntLE();
+ kernpairs = in.readIntLE();
+ res2 = in.readIntLE();
+ fontname = in.readIntLE();
+ if (h_len != in.length() || extlen != 30 || fontname < 75 || fontname > 512)
+ throw new IOException("Not a valid PFM file.");
+ in.seek(psext + 14);
+ capheight = in.readShortLE();
+ xheight = in.readShortLE();
+ ascender = in.readShortLE();
+ descender = in.readShortLE();
+ }
+
+ private void putheader() throws IOException {
+ out.print("StartFontMetrics 2.0\n");
+ if (copyright.length() > 0)
+ out.print("Comment " + copyright + '\n');
+ out.print("FontName ");
+ in.seek(fontname);
+ String fname = readString();
+ out.print(fname);
+ out.print("\nEncodingScheme ");
+ if (charset != 0)
+ out.print("FontSpecific\n");
+ else
+ out.print("AdobeStandardEncoding\n");
+ /*
+ * The .pfm is missing full name, so construct from font name by
+ * changing the hyphen to a space. This actually works in a lot
+ * of cases.
+ */
+ out.print("FullName " + fname.replace('-', ' '));
+ if (face != 0) {
+ in.seek(face);
+ out.print("\nFamilyName " + readString());
+ }
+
+ out.print("\nWeight ");
+ if (weight > 475 || fname.toLowerCase().indexOf("bold") >= 0)
+ out.print("Bold");
+ else if ((weight < 325 && weight != 0) || fname.toLowerCase().indexOf("light") >= 0)
+ out.print("Light");
+ else if (fname.toLowerCase().indexOf("black") >= 0)
+ out.print("Black");
+ else
+ out.print("Medium");
+
+ out.print("\nItalicAngle ");
+ if (italic != 0 || fname.toLowerCase().indexOf("italic") >= 0)
+ out.print("-12.00");
+ /* this is a typical value; something else may work better for a
+ specific font */
+ else
+ out.print("0");
+
+ /*
+ * The mono flag in the pfm actually indicates whether there is a
+ * table of font widths, not if they are all the same.
+ */
+ out.print("\nIsFixedPitch ");
+ if ((kind & 1) == 0 || /* Flag for mono */
+ avgwidth == maxwidth ) { /* Avg width = max width */
+ out.print("true");
+ isMono = true;
+ }
+ else {
+ out.print("false");
+ isMono = false;
+ }
+
+ /*
+ * The font bounding box is lost, but try to reconstruct it.
+ * Much of this is just guess work. The bounding box is required in
+ * the .afm, but is not used by the PM font installer.
+ */
+ out.print("\nFontBBox");
+ if (isMono)
+ outval(-20); /* Just guess at left bounds */
+ else
+ outval(-100);
+ outval(-(descender+5)); /* Descender is given as positive value */
+ outval(maxwidth+10);
+ outval(ascent+5);
+
+ /*
+ * Give other metrics that were kept
+ */
+ out.print("\nCapHeight");
+ outval(capheight);
+ out.print("\nXHeight");
+ outval(xheight);
+ out.print("\nDescender");
+ outval(descender);
+ out.print("\nAscender");
+ outval(ascender);
+ out.print('\n');
+ }
+
+ private void putchartab() throws IOException {
+ int count = lastchar - firstchar + 1;
+ int ctabs[] = new int[count];
+ in.seek(chartab);
+ for (int k = 0; k < count; ++k)
+ ctabs[k] = in.readUnsignedShortLE();
+ int back[] = new int[256];
+ if (charset == 0) {
+ for (int i = firstchar; i <= lastchar; ++i) {
+ if (Win2PSStd[i] != 0)
+ back[Win2PSStd[i]] = i;
+ }
+ }
+ /* Put out the header */
+ out.print("StartCharMetrics");
+ outval(count);
+ out.print('\n');
+
+ /* Put out all encoded chars */
+ if (charset != 0) {
+ /*
+ * If the charset is not the Windows standard, just put out
+ * unnamed entries.
+ */
+ for (int i = firstchar; i <= lastchar; i++) {
+ if (ctabs[i - firstchar] != 0) {
+ outchar(i, ctabs[i - firstchar], null);
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < 256; i++) {
+ int j = back[i];
+ if (j != 0) {
+ outchar(i, ctabs[j - firstchar], WinChars[j]);
+ ctabs[j - firstchar] = 0;
+ }
+ }
+ /* Put out all non-encoded chars */
+ for (int i = firstchar; i <= lastchar; i++) {
+ if (ctabs[i - firstchar] != 0) {
+ outchar(-1, ctabs[i - firstchar], WinChars[i]);
+ }
+ }
+ }
+ /* Put out the trailer */
+ out.print("EndCharMetrics\n");
+
+ }
+
+ private void putkerntab() throws IOException {
+ if (kernpairs == 0)
+ return;
+ in.seek(kernpairs);
+ int count = in.readUnsignedShortLE();
+ int nzero = 0;
+ int kerns[] = new int[count * 3];
+ for (int k = 0; k < kerns.length;) {
+ kerns[k++] = in.read();
+ kerns[k++] = in.read();
+ if ((kerns[k++] = in.readShortLE()) != 0)
+ ++nzero;
+ }
+ if (nzero == 0)
+ return;
+ out.print("StartKernData\nStartKernPairs");
+ outval(nzero);
+ out.print('\n');
+ for (int k = 0; k < kerns.length; k += 3) {
+ if (kerns[k + 2] != 0) {
+ out.print("KPX ");
+ out.print(WinChars[kerns[k]]);
+ out.print(' ');
+ out.print(WinChars[kerns[k + 1]]);
+ outval(kerns[k + 2]);
+ out.print('\n');
+ }
+ }
+ /* Put out trailer */
+ out.print("EndKernPairs\nEndKernData\n");
+ }
+
+
+ private void puttrailer() {
+ out.print("EndFontMetrics\n");
+ }
+
+ private short vers;
+ private int h_len; /* Total length of .pfm file */
+ private String copyright; /* Copyright string [60]*/
+ private short type;
+ private short points;
+ private short verres;
+ private short horres;
+ private short ascent;
+ private short intleading;
+ private short extleading;
+ private byte italic;
+ private byte uline;
+ private byte overs;
+ private short weight;
+ private byte charset; /* 0=windows, otherwise nomap */
+ private short pixwidth; /* Width for mono fonts */
+ private short pixheight;
+ private byte kind; /* Lower bit off in mono */
+ private short avgwidth; /* Mono if avg=max width */
+ private short maxwidth; /* Use to compute bounding box */
+ private int firstchar; /* First char in table */
+ private int lastchar; /* Last char in table */
+ private byte defchar;
+ private byte brkchar;
+ private short widthby;
+ private int device;
+ private int face; /* Face name */
+ private int bits;
+ private int bitoff;
+ private short extlen;
+ private int psext; /* PostScript extension */
+ private int chartab; /* Character width tables */
+ private int res1;
+ private int kernpairs; /* Kerning pairs */
+ private int res2;
+ private int fontname; /* Font name */
+
+/*
+ * Some metrics from the PostScript extension
+ */
+ private short capheight; /* Cap height */
+ private short xheight; /* X height */
+ private short ascender; /* Ascender */
+ private short descender; /* Descender (positive) */
+
+
+ private boolean isMono;
+/*
+ * Translate table from 1004 to psstd. 1004 is an extension of the
+ * Windows translate table used in PM.
+ */
+ private int Win2PSStd[] = {
+ 0, 0, 0, 0, 197, 198, 199, 0, 202, 0, 205, 206, 207, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 32, 33, 34, 35, 36, 37, 38, 169, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 193, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 0, 0, 184, 0, 185, 188, 178, 179, 94, 189, 0, 172, 234, 0, 0, 0,
+ 0, 96, 0, 170, 186, 0, 177, 208, 126, 0, 0, 173, 250, 0, 0, 0,
+ 0, 161, 162, 163, 168, 165, 0, 167, 200, 0, 227, 171, 0, 0, 0, 0,
+ 0, 0, 0, 0, 194, 0, 182, 180, 203, 0, 235, 187, 0, 0, 0, 191,
+ 0, 0, 0, 0, 0, 0, 225, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 251,
+ 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 0, 0, 0, 0, 0
+ };
+
+/*
+ * Character class. This is a minor attempt to overcome the problem that
+ * in the pfm file, all unused characters are given the width of space.
+ */
+ private int WinClass[] = {
+ 0, 0, 0, 0, 2, 2, 2, 0, 2, 0, 2, 2, 2, 0, 0, 0, /* 00 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, /* 70 */
+ 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, /* 80 */
+ 0, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, /* 90 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a0 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b0 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* c0 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* d0 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e0 */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* f0 */
+ };
+
+/*
+ * Windows chararacter names. Give a name to the usused locations
+ * for when the all flag is specified.
+ */
+ private String WinChars[] = {
+ "W00", /* 00 */
+ "W01", /* 01 */
+ "W02", /* 02 */
+ "W03", /* 03 */
+ "macron", /* 04 */
+ "breve", /* 05 */
+ "dotaccent", /* 06 */
+ "W07", /* 07 */
+ "ring", /* 08 */
+ "W09", /* 09 */
+ "W0a", /* 0a */
+ "W0b", /* 0b */
+ "W0c", /* 0c */
+ "W0d", /* 0d */
+ "W0e", /* 0e */
+ "W0f", /* 0f */
+ "hungarumlaut", /* 10 */
+ "ogonek", /* 11 */
+ "caron", /* 12 */
+ "W13", /* 13 */
+ "W14", /* 14 */
+ "W15", /* 15 */
+ "W16", /* 16 */
+ "W17", /* 17 */
+ "W18", /* 18 */
+ "W19", /* 19 */
+ "W1a", /* 1a */
+ "W1b", /* 1b */
+ "W1c", /* 1c */
+ "W1d", /* 1d */
+ "W1e", /* 1e */
+ "W1f", /* 1f */
+ "space", /* 20 */
+ "exclam", /* 21 */
+ "quotedbl", /* 22 */
+ "numbersign", /* 23 */
+ "dollar", /* 24 */
+ "percent", /* 25 */
+ "ampersand", /* 26 */
+ "quotesingle", /* 27 */
+ "parenleft", /* 28 */
+ "parenright", /* 29 */
+ "asterisk", /* 2A */
+ "plus", /* 2B */
+ "comma", /* 2C */
+ "hyphen", /* 2D */
+ "period", /* 2E */
+ "slash", /* 2F */
+ "zero", /* 30 */
+ "one", /* 31 */
+ "two", /* 32 */
+ "three", /* 33 */
+ "four", /* 34 */
+ "five", /* 35 */
+ "six", /* 36 */
+ "seven", /* 37 */
+ "eight", /* 38 */
+ "nine", /* 39 */
+ "colon", /* 3A */
+ "semicolon", /* 3B */
+ "less", /* 3C */
+ "equal", /* 3D */
+ "greater", /* 3E */
+ "question", /* 3F */
+ "at", /* 40 */
+ "A", /* 41 */
+ "B", /* 42 */
+ "C", /* 43 */
+ "D", /* 44 */
+ "E", /* 45 */
+ "F", /* 46 */
+ "G", /* 47 */
+ "H", /* 48 */
+ "I", /* 49 */
+ "J", /* 4A */
+ "K", /* 4B */
+ "L", /* 4C */
+ "M", /* 4D */
+ "N", /* 4E */
+ "O", /* 4F */
+ "P", /* 50 */
+ "Q", /* 51 */
+ "R", /* 52 */
+ "S", /* 53 */
+ "T", /* 54 */
+ "U", /* 55 */
+ "V", /* 56 */
+ "W", /* 57 */
+ "X", /* 58 */
+ "Y", /* 59 */
+ "Z", /* 5A */
+ "bracketleft", /* 5B */
+ "backslash", /* 5C */
+ "bracketright", /* 5D */
+ "asciicircum", /* 5E */
+ "underscore", /* 5F */
+ "grave", /* 60 */
+ "a", /* 61 */
+ "b", /* 62 */
+ "c", /* 63 */
+ "d", /* 64 */
+ "e", /* 65 */
+ "f", /* 66 */
+ "g", /* 67 */
+ "h", /* 68 */
+ "i", /* 69 */
+ "j", /* 6A */
+ "k", /* 6B */
+ "l", /* 6C */
+ "m", /* 6D */
+ "n", /* 6E */
+ "o", /* 6F */
+ "p", /* 70 */
+ "q", /* 71 */
+ "r", /* 72 */
+ "s", /* 73 */
+ "t", /* 74 */
+ "u", /* 75 */
+ "v", /* 76 */
+ "w", /* 77 */
+ "x", /* 78 */
+ "y", /* 79 */
+ "z", /* 7A */
+ "braceleft", /* 7B */
+ "bar", /* 7C */
+ "braceright", /* 7D */
+ "asciitilde", /* 7E */
+ "W7f", /* 7F */
+ "W80", /* 80 */
+ "W81", /* 81 */
+ "quotesinglbase", /* 82 */
+ "W83", /* 83 */
+ "quotedblbase", /* 84 */
+ "ellipsis", /* 85 */
+ "dagger", /* 86 */
+ "daggerdbl", /* 87 */
+ "asciicircum", /* 88 */
+ "perthousand", /* 89 */
+ "Scaron", /* 8A */
+ "guilsinglleft", /* 8B */
+ "OE", /* 8C */
+ "W8d", /* 8D */
+ "W8e", /* 8E */
+ "W8f", /* 8F */
+ "W90", /* 90 */
+ "quoteleft", /* 91 */
+ "quoteright", /* 92 */
+ "quotedblleft", /* 93 */
+ "quotedblright", /* 94 */
+ "bullet1", /* 95 */
+ "endash", /* 96 */
+ "emdash", /* 97 */
+ "asciitilde", /* 98 */
+ "trademark", /* 99 */
+ "scaron", /* 9A */
+ "guilsinglright", /* 9B */
+ "oe", /* 9C */
+ "W9d", /* 9D */
+ "W9e", /* 9E */
+ "Ydieresis", /* 9F */
+ "reqspace", /* A0 */
+ "exclamdown", /* A1 */
+ "cent", /* A2 */
+ "sterling", /* A3 */
+ "currency", /* A4 */
+ "yen", /* A5 */
+ "brokenbar", /* A6 */
+ "section", /* A7 */
+ "dieresis", /* A8 */
+ "copyright", /* A9 */
+ "ordfeminine", /* AA */
+ "guillemotleft", /* AB */
+ "logicalnot", /* AC */
+ "syllable", /* AD */
+ "registered", /* AE */
+ "overbar", /* AF */
+ "degree", /* B0 */
+ "plusminus", /* B1 */
+ "twosuperior", /* B2 */
+ "threesuperior", /* B3 */
+ "acute", /* B4 */
+ "mu", /* B5 */
+ "paragraph", /* B6 */
+ "periodcentered", /* B7 */
+ "cedilla", /* B8 */
+ "onesuperior", /* B9 */
+ "ordmasculine", /* BA */
+ "guillemotright", /* BB */
+ "onequarter", /* BC */
+ "onehalf", /* BD */
+ "threequarters", /* BE */
+ "questiondown", /* BF */
+ "Agrave", /* C0 */
+ "Aacute", /* C1 */
+ "Acircumflex", /* C2 */
+ "Atilde", /* C3 */
+ "Adieresis", /* C4 */
+ "Aring", /* C5 */
+ "AE", /* C6 */
+ "Ccedilla", /* C7 */
+ "Egrave", /* C8 */
+ "Eacute", /* C9 */
+ "Ecircumflex", /* CA */
+ "Edieresis", /* CB */
+ "Igrave", /* CC */
+ "Iacute", /* CD */
+ "Icircumflex", /* CE */
+ "Idieresis", /* CF */
+ "Eth", /* D0 */
+ "Ntilde", /* D1 */
+ "Ograve", /* D2 */
+ "Oacute", /* D3 */
+ "Ocircumflex", /* D4 */
+ "Otilde", /* D5 */
+ "Odieresis", /* D6 */
+ "multiply", /* D7 */
+ "Oslash", /* D8 */
+ "Ugrave", /* D9 */
+ "Uacute", /* DA */
+ "Ucircumflex", /* DB */
+ "Udieresis", /* DC */
+ "Yacute", /* DD */
+ "Thorn", /* DE */
+ "germandbls", /* DF */
+ "agrave", /* E0 */
+ "aacute", /* E1 */
+ "acircumflex", /* E2 */
+ "atilde", /* E3 */
+ "adieresis", /* E4 */
+ "aring", /* E5 */
+ "ae", /* E6 */
+ "ccedilla", /* E7 */
+ "egrave", /* E8 */
+ "eacute", /* E9 */
+ "ecircumflex", /* EA */
+ "edieresis", /* EB */
+ "igrave", /* EC */
+ "iacute", /* ED */
+ "icircumflex", /* EE */
+ "idieresis", /* EF */
+ "eth", /* F0 */
+ "ntilde", /* F1 */
+ "ograve", /* F2 */
+ "oacute", /* F3 */
+ "ocircumflex", /* F4 */
+ "otilde", /* F5 */
+ "odieresis", /* F6 */
+ "divide", /* F7 */
+ "oslash", /* F8 */
+ "ugrave", /* F9 */
+ "uacute", /* FA */
+ "ucircumflex", /* FB */
+ "udieresis", /* FC */
+ "yacute", /* FD */
+ "thorn", /* FE */
+ "ydieresis" /* FF */
+ };
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/RandomAccessFileOrArray.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/RandomAccessFileOrArray.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/RandomAccessFileOrArray.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/RandomAccessFileOrArray.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,606 @@
+/*
+ * $Id: RandomAccessFileOrArray.java,v 1.48 2005/09/11 08:38:18 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.DataInputStream;
+import java.io.DataInput;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.EOFException;
+import java.io.RandomAccessFile;
+import java.io.File;
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.net.URL;
+/** An implementation of a RandomAccessFile for input only
+ * that accepts a file or a byte array as data source.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class RandomAccessFileOrArray implements DataInput {
+
+ RandomAccessFile rf;
+ String filename;
+ byte arrayIn[];
+ int arrayInPtr;
+ byte back;
+ boolean isBack = false;
+
+ /** Holds value of property startOffset. */
+ private int startOffset = 0;
+
+ public RandomAccessFileOrArray(String filename) throws IOException {
+ this(filename, false);
+ }
+
+ public RandomAccessFileOrArray(String filename, boolean forceRead) throws IOException {
+ File file = new File(filename);
+ if (!file.canRead()) {
+ if (filename.startsWith("file:/") || filename.startsWith("http://") || filename.startsWith("https://") || filename.startsWith("jar:")) {
+ InputStream is = new URL(filename).openStream();
+ try {
+ this.arrayIn = InputStreamToArray(is);
+ return;
+ }
+ finally {
+ try {is.close();}catch(IOException ioe){}
+ }
+ }
+ else {
+ InputStream is;
+ if( filename.equals("-") ) {
+ // ssteward, pdftk 1.10; patch provided by Bart Orbons to permit stdin input via pdftk
+ is = System.in;
+ }
+ else {
+ is = BaseFont.getResourceStream(filename);
+ }
+ if (is == null)
+ throw new IOException(filename + " not found as file or resource.");
+ try {
+ this.arrayIn = InputStreamToArray(is);
+ return;
+ }
+ finally {
+ try {is.close();}catch(IOException ioe){}
+ }
+ }
+ }
+ else if (forceRead) {
+ InputStream s = null;
+ try {
+ s = new FileInputStream(file);
+ this.arrayIn = InputStreamToArray(s);
+ }
+ finally {
+ try {s.close();}catch(Exception e){}
+ }
+ return;
+ }
+ this.filename = filename;
+ rf = new RandomAccessFile(filename, "r");
+ }
+
+ public RandomAccessFileOrArray(URL url) throws IOException {
+ InputStream is = url.openStream();
+ try {
+ this.arrayIn = InputStreamToArray(is);
+ }
+ finally {
+ try {is.close();}catch(IOException ioe){}
+ }
+ }
+
+ public RandomAccessFileOrArray(InputStream is) throws IOException {
+ this.arrayIn = InputStreamToArray(is);
+ }
+
+ public static byte[] InputStreamToArray(InputStream is) throws IOException {
+ byte b[] = new byte[8192];
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ while (true) {
+ int read = is.read(b);
+ if (read < 1)
+ break;
+ out.write(b, 0, read);
+ }
+ return out.toByteArray();
+ }
+
+ public RandomAccessFileOrArray(byte arrayIn[]) {
+ this.arrayIn = arrayIn;
+ }
+
+ public RandomAccessFileOrArray(RandomAccessFileOrArray file) {
+ filename = file.filename;
+ arrayIn = file.arrayIn;
+ startOffset = file.startOffset;
+ }
+
+ public void pushBack(byte b) {
+ back = b;
+ isBack = true;
+ }
+
+ public int read() throws IOException {
+ if(isBack) {
+ isBack = false;
+ return back & 0xff;
+ }
+ if (arrayIn == null)
+ return rf.read();
+ else {
+ if (arrayInPtr >= arrayIn.length)
+ return -1;
+ return arrayIn[arrayInPtr++] & 0xff;
+ }
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (len == 0)
+ return 0;
+ int n = 0;
+ if (isBack) {
+ isBack = false;
+ if (len == 1) {
+ b[off] = back;
+ return 1;
+ }
+ else {
+ n = 1;
+ b[off++] = back;
+ --len;
+ }
+ }
+ if (arrayIn == null) {
+ return rf.read(b, off, len) + n;
+ }
+ else {
+ if (arrayInPtr >= arrayIn.length)
+ return -1;
+ if (arrayInPtr + len > arrayIn.length)
+ len = arrayIn.length - arrayInPtr;
+ System.arraycopy(arrayIn, arrayInPtr, b, off, len);
+ arrayInPtr += len;
+ return len + n;
+ }
+ }
+
+ public int read(byte b[]) throws IOException {
+ return read(b, 0, b.length);
+ }
+
+ public void readFully(byte b[]) throws IOException {
+ readFully(b, 0, b.length);
+ }
+
+ public void readFully(byte b[], int off, int len) throws IOException {
+ int n = 0;
+ do {
+ int count = read(b, off + n, len - n);
+ if (count < 0)
+ throw new EOFException();
+ n += count;
+ } while (n < len);
+ }
+
+ public long skip(long n) throws IOException {
+ return skipBytes((int)n);
+ }
+
+ public int skipBytes(int n) throws IOException {
+ if (n <= 0) {
+ return 0;
+ }
+ int adj = 0;
+ if (isBack) {
+ isBack = false;
+ if (n == 1) {
+ return 1;
+ }
+ else {
+ --n;
+ adj = 1;
+ }
+ }
+ int pos;
+ int len;
+ int newpos;
+
+ pos = getFilePointer();
+ len = length();
+ newpos = pos + n;
+ if (newpos > len) {
+ newpos = len;
+ }
+ seek(newpos);
+
+ /* return the actual number of bytes skipped */
+ return newpos - pos + adj;
+ }
+
+ public void reOpen() throws IOException {
+ if (filename != null && rf == null)
+ rf = new RandomAccessFile(filename, "r");
+ seek(0);
+ }
+
+ protected void insureOpen() throws IOException {
+ if (filename != null && rf == null) {
+ reOpen();
+ }
+ }
+
+ public boolean isOpen() {
+ return (filename == null || rf != null);
+ }
+
+ public void close() throws IOException {
+ isBack = false;
+ if (rf != null) {
+ rf.close();
+ rf = null;
+ }
+ }
+
+ public int length() throws IOException {
+ if (arrayIn == null) {
+ insureOpen();
+ return (int)rf.length() - startOffset;
+ }
+ else
+ return arrayIn.length - startOffset;
+ }
+
+ public void seek(int pos) throws IOException {
+ pos += startOffset;
+ isBack = false;
+ if (arrayIn == null) {
+ insureOpen();
+ rf.seek(pos);
+ }
+ else
+ arrayInPtr = pos;
+ }
+
+ public void seek(long pos) throws IOException {
+ seek((int)pos);
+ }
+
+ public int getFilePointer() throws IOException {
+ insureOpen();
+ int n = isBack ? 1 : 0;
+ if (arrayIn == null) {
+ return (int)rf.getFilePointer() - n - startOffset;
+ }
+ else
+ return arrayInPtr - n - startOffset;
+ }
+
+ public boolean readBoolean() throws IOException {
+ int ch = this.read();
+ if (ch < 0)
+ throw new EOFException();
+ return (ch != 0);
+ }
+
+ public byte readByte() throws IOException {
+ int ch = this.read();
+ if (ch < 0)
+ throw new EOFException();
+ return (byte)(ch);
+ }
+
+ public int readUnsignedByte() throws IOException {
+ int ch = this.read();
+ if (ch < 0)
+ throw new EOFException();
+ return ch;
+ }
+
+ public short readShort() throws IOException {
+ int ch1 = this.read();
+ int ch2 = this.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ return (short)((ch1 << 8) + ch2);
+ }
+
+ /**
+ * Reads a signed 16-bit number from this stream in little-endian order.
+ * The method reads two
+ * bytes from this stream, starting at the current stream pointer.
+ * If the two bytes read, in order, are
+ * b1
and b2
, where each of the two values is
+ * between 0
and 255
, inclusive, then the
+ * result is equal to:
+ *
+ * (short)((b2 << 8) | b1)
+ *
+ *
+ * This method blocks until the two bytes are read, the end of the
+ * stream is detected, or an exception is thrown.
+ *
+ * @return the next two bytes of this stream, interpreted as a signed
+ * 16-bit number.
+ * @exception EOFException if this stream reaches the end before reading
+ * two bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ public final short readShortLE() throws IOException {
+ int ch1 = this.read();
+ int ch2 = this.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ return (short)((ch2 << 8) + (ch1 << 0));
+ }
+
+ public int readUnsignedShort() throws IOException {
+ int ch1 = this.read();
+ int ch2 = this.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ return (ch1 << 8) + ch2;
+ }
+
+ /**
+ * Reads an unsigned 16-bit number from this stream in little-endian order.
+ * This method reads
+ * two bytes from the stream, starting at the current stream pointer.
+ * If the bytes read, in order, are
+ * b1
and b2
, where
+ * 0 <= b1, b2 <= 255
,
+ * then the result is equal to:
+ *
+ * (b2 << 8) | b1
+ *
+ *
+ * This method blocks until the two bytes are read, the end of the
+ * stream is detected, or an exception is thrown.
+ *
+ * @return the next two bytes of this stream, interpreted as an
+ * unsigned 16-bit integer.
+ * @exception EOFException if this stream reaches the end before reading
+ * two bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ public final int readUnsignedShortLE() throws IOException {
+ int ch1 = this.read();
+ int ch2 = this.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ return (ch2 << 8) + (ch1 << 0);
+ }
+
+ public char readChar() throws IOException {
+ int ch1 = this.read();
+ int ch2 = this.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ return (char)((ch1 << 8) + ch2);
+ }
+
+ /**
+ * Reads a Unicode character from this stream in little-endian order.
+ * This method reads two
+ * bytes from the stream, starting at the current stream pointer.
+ * If the bytes read, in order, are
+ * b1
and b2
, where
+ * 0 <= b1, b2 <= 255
,
+ * then the result is equal to:
+ *
+ * (char)((b2 << 8) | b1)
+ *
+ *
+ * This method blocks until the two bytes are read, the end of the
+ * stream is detected, or an exception is thrown.
+ *
+ * @return the next two bytes of this stream as a Unicode character.
+ * @exception EOFException if this stream reaches the end before reading
+ * two bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ public final char readCharLE() throws IOException {
+ int ch1 = this.read();
+ int ch2 = this.read();
+ if ((ch1 | ch2) < 0)
+ throw new EOFException();
+ return (char)((ch2 << 8) + (ch1 << 0));
+ }
+
+ public int readInt() throws IOException {
+ int ch1 = this.read();
+ int ch2 = this.read();
+ int ch3 = this.read();
+ int ch4 = this.read();
+ if ((ch1 | ch2 | ch3 | ch4) < 0)
+ throw new EOFException();
+ return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4);
+ }
+
+ /**
+ * Reads a signed 32-bit integer from this stream in little-endian order.
+ * This method reads 4
+ * bytes from the stream, starting at the current stream pointer.
+ * If the bytes read, in order, are b1
,
+ * b2
, b3
, and b4
, where
+ * 0 <= b1, b2, b3, b4 <= 255
,
+ * then the result is equal to:
+ *
+ * (b4 << 24) | (b3 << 16) + (b2 << 8) + b1
+ *
+ *
+ * This method blocks until the four bytes are read, the end of the
+ * stream is detected, or an exception is thrown.
+ *
+ * @return the next four bytes of this stream, interpreted as an
+ * int
.
+ * @exception EOFException if this stream reaches the end before reading
+ * four bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ public final int readIntLE() throws IOException {
+ int ch1 = this.read();
+ int ch2 = this.read();
+ int ch3 = this.read();
+ int ch4 = this.read();
+ if ((ch1 | ch2 | ch3 | ch4) < 0)
+ throw new EOFException();
+ return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
+ }
+
+ /**
+ * Reads an unsigned 32-bit integer from this stream. This method reads 4
+ * bytes from the stream, starting at the current stream pointer.
+ * If the bytes read, in order, are b1
,
+ * b2
, b3
, and b4
, where
+ * 0 <= b1, b2, b3, b4 <= 255
,
+ * then the result is equal to:
+ *
+ * (b1 << 24) | (b2 << 16) + (b3 << 8) + b4
+ *
+ *
+ * This method blocks until the four bytes are read, the end of the
+ * stream is detected, or an exception is thrown.
+ *
+ * @return the next four bytes of this stream, interpreted as a
+ * long
.
+ * @exception EOFException if this stream reaches the end before reading
+ * four bytes.
+ * @exception IOException if an I/O error occurs.
+ */
+ public final long readUnsignedInt() throws IOException {
+ long ch1 = this.read();
+ long ch2 = this.read();
+ long ch3 = this.read();
+ long ch4 = this.read();
+ if ((ch1 | ch2 | ch3 | ch4) < 0)
+ throw new EOFException();
+ return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
+ }
+
+ public final long readUnsignedIntLE() throws IOException {
+ long ch1 = this.read();
+ long ch2 = this.read();
+ long ch3 = this.read();
+ long ch4 = this.read();
+ if ((ch1 | ch2 | ch3 | ch4) < 0)
+ throw new EOFException();
+ return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
+ }
+
+ public long readLong() throws IOException {
+ return ((long)(readInt()) << 32) + (readInt() & 0xFFFFFFFFL);
+ }
+
+ public final long readLongLE() throws IOException {
+ int i1 = readIntLE();
+ int i2 = readIntLE();
+ return ((long)i2 << 32) + (i1 & 0xFFFFFFFFL);
+ }
+
+ public float readFloat() throws IOException {
+ return Float.intBitsToFloat(readInt());
+ }
+
+ public final float readFloatLE() throws IOException {
+ return Float.intBitsToFloat(readIntLE());
+ }
+
+ public double readDouble() throws IOException {
+ return Double.longBitsToDouble(readLong());
+ }
+
+ public final double readDoubleLE() throws IOException {
+ return Double.longBitsToDouble(readLongLE());
+ }
+
+ public String readLine() throws IOException {
+ StringBuffer input = new StringBuffer();
+ int c = -1;
+ boolean eol = false;
+
+ while (!eol) {
+ switch (c = read()) {
+ case -1:
+ case '\n':
+ eol = true;
+ break;
+ case '\r':
+ eol = true;
+ int cur = getFilePointer();
+ if ((read()) != '\n') {
+ seek(cur);
+ }
+ break;
+ default:
+ input.append((char)c);
+ break;
+ }
+ }
+
+ if ((c == -1) && (input.length() == 0)) {
+ return null;
+ }
+ return input.toString();
+ }
+
+ public String readUTF() throws IOException {
+ return DataInputStream.readUTF(this);
+ }
+
+ /** Getter for property startOffset.
+ * @return Value of property startOffset.
+ *
+ */
+ public int getStartOffset() {
+ return this.startOffset;
+ }
+
+ /** Setter for property startOffset.
+ * @param startOffset New value of property startOffset.
+ *
+ */
+ public void setStartOffset(int startOffset) {
+ this.startOffset = startOffset;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SequenceList.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SequenceList.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SequenceList.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SequenceList.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.List;
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+/**
+ * This class expands a string into a list of numbers. The main use is to select a
+ * range of pages.
+ *
+ * The general systax is:
+ * [!][o][odd][e][even]start-end
+ *
+ * You can have multiple ranges separated by commas ','. The '!' modifier removes the
+ * range from what is already selected. The range changes are incremental, that is,
+ * numbers are added or deleted as the range appears. The start or the end, but not both, can be ommited.
+ */
+public class SequenceList {
+ protected static final int COMMA = 1;
+ protected static final int MINUS = 2;
+ protected static final int NOT = 3;
+ protected static final int TEXT = 4;
+ protected static final int NUMBER = 5;
+ protected static final int END = 6;
+ protected static final char EOT = '\uffff';
+
+ private static final int FIRST = 0;
+ private static final int DIGIT = 1;
+ private static final int OTHER = 2;
+ private static final int DIGIT2 = 3;
+ private static final String NOT_OTHER = "-,!0123456789";
+
+ protected char text[];
+ protected int ptr;
+ protected int number;
+ protected String other;
+
+ protected int low;
+ protected int high;
+ protected boolean odd;
+ protected boolean even;
+ protected boolean inverse;
+
+ protected SequenceList(String range) {
+ ptr = 0;
+ text = range.toCharArray();
+ }
+
+ protected char nextChar() {
+ while (true) {
+ if (ptr >= text.length)
+ return EOT;
+ char c = text[ptr++];
+ if (c > ' ')
+ return c;
+ }
+ }
+
+ protected void putBack() {
+ --ptr;
+ if (ptr < 0)
+ ptr = 0;
+ }
+
+ protected int getType() {
+ StringBuffer buf = new StringBuffer();
+ int state = FIRST;
+ while (true) {
+ char c = nextChar();
+ if (c == EOT) {
+ if (state == DIGIT) {
+ number = Integer.parseInt(other = buf.toString());
+ return NUMBER;
+ }
+ else if (state == OTHER) {
+ other = buf.toString().toLowerCase();
+ return TEXT;
+ }
+ return END;
+ }
+ switch (state) {
+ case FIRST:
+ switch (c) {
+ case '!':
+ return NOT;
+ case '-':
+ return MINUS;
+ case ',':
+ return COMMA;
+ }
+ buf.append(c);
+ if (c >= '0' && c <= '9')
+ state = DIGIT;
+ else
+ state = OTHER;
+ break;
+ case DIGIT:
+ if (c >= '0' && c <= '9')
+ buf.append(c);
+ else {
+ putBack();
+ number = Integer.parseInt(other = buf.toString());
+ return NUMBER;
+ }
+ break;
+ case OTHER:
+ if (NOT_OTHER.indexOf(c) < 0)
+ buf.append(c);
+ else {
+ putBack();
+ other = buf.toString().toLowerCase();
+ return TEXT;
+ }
+ break;
+ }
+ }
+ }
+
+ private void otherProc() {
+ if (other.equals("odd") || other.equals("o")) {
+ odd = true;
+ even = false;
+ }
+ else if (other.equals("even") || other.equals("e")) {
+ odd = false;
+ even = true;
+ }
+ }
+
+ protected boolean getAttributes() {
+ low = -1;
+ high = -1;
+ odd = even = inverse = false;
+ int state = OTHER;
+ while (true) {
+ int type = getType();
+ if (type == END || type == COMMA) {
+ if (state == DIGIT)
+ high = low;
+ return (type == END);
+ }
+ switch (state) {
+ case OTHER:
+ switch (type) {
+ case NOT:
+ inverse = true;
+ break;
+ case MINUS:
+ state = DIGIT2;
+ break;
+ default:
+ if (type == NUMBER) {
+ low = number;
+ state = DIGIT;
+ }
+ else
+ otherProc();
+ break;
+ }
+ break;
+ case DIGIT:
+ switch (type) {
+ case NOT:
+ inverse = true;
+ state = OTHER;
+ high = low;
+ break;
+ case MINUS:
+ state = DIGIT2;
+ break;
+ default:
+ high = low;
+ state = OTHER;
+ otherProc();
+ break;
+ }
+ break;
+ case DIGIT2:
+ switch (type) {
+ case NOT:
+ inverse = true;
+ state = OTHER;
+ break;
+ case MINUS:
+ break;
+ case NUMBER:
+ high = number;
+ state = OTHER;
+ break;
+ default:
+ state = OTHER;
+ otherProc();
+ break;
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Generates a list of numbers from a string.
+ * @param ranges the comma separated ranges
+ * @param maxNumber the maximum number in the range
+ * @return a list with the numbers as Integer
+ */
+ public static List expand(String ranges, int maxNumber) {
+ SequenceList parse = new SequenceList(ranges);
+ LinkedList list = new LinkedList();
+ boolean sair = false;
+ while (!sair) {
+ sair = parse.getAttributes();
+ if (parse.low == -1 && parse.high == -1 && !parse.even && !parse.odd)
+ continue;
+ if (parse.low < 1)
+ parse.low = 1;
+ if (parse.high < 1 || parse.high > maxNumber)
+ parse.high = maxNumber;
+ if (parse.low > maxNumber)
+ parse.low = maxNumber;
+
+ //System.out.println("low="+parse.low+",high="+parse.high+",odd="+parse.odd+",even="+parse.even+",inverse="+parse.inverse);
+ int inc = 1;
+ if (parse.inverse) {
+ if (parse.low > parse.high) {
+ int t = parse.low;
+ parse.low = parse.high;
+ parse.high = t;
+ }
+ for (ListIterator it = list.listIterator(); it.hasNext();) {
+ int n = ((Integer)it.next()).intValue();
+ if (parse.even && (n & 1) == 1)
+ continue;
+ if (parse.odd && (n & 1) == 0)
+ continue;
+ if (n >= parse.low && n <= parse.high)
+ it.remove();
+ }
+ }
+ else {
+ if (parse.low > parse.high) {
+ inc = -1;
+ if (parse.odd || parse.even) {
+ --inc;
+ if (parse.even)
+ parse.low &= ~1;
+ else
+ parse.low -= ((parse.low & 1) == 1 ? 0 : 1);
+ }
+ for (int k = parse.low; k >= parse.high; k += inc)
+ list.add(new Integer(k));
+ }
+ else {
+ if (parse.odd || parse.even) {
+ ++inc;
+ if (parse.odd)
+ parse.low |= 1;
+ else
+ parse.low += ((parse.low & 1) == 1 ? 1 : 0);
+ }
+ for (int k = parse.low; k <= parse.high; k += inc) {
+ list.add(new Integer(k));
+ }
+ }
+ }
+// for (int k = 0; k < list.size(); ++k)
+// System.out.print(((Integer)list.get(k)).intValue() + ",");
+// System.out.println();
+ }
+ return list;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ShadingColor.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ShadingColor.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/ShadingColor.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/ShadingColor.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/** Implements a shading pattern as a Color
.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class ShadingColor extends ExtendedColor {
+
+ PdfShadingPattern shadingPattern;
+
+ /**
+ * Creates a shading color.
+ * @param shadingPattern
+ */
+ public ShadingColor(PdfShadingPattern shadingPattern) {
+ super(TYPE_SHADING, .5f, .5f, .5f);
+ this.shadingPattern = shadingPattern;
+ }
+
+ /**
+ * Gets the shading pattern.
+ * @return a shading pattern.
+ */
+ public PdfShadingPattern getPdfShadingPattern() {
+ return shadingPattern;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SimpleBookmark.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SimpleBookmark.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SimpleBookmark.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SimpleBookmark.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,735 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.Writer;
+import java.io.Reader;
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
+import java.util.Stack;
+/**
+ * Bookmark processing in a simple way. It has some limitations, mainly the only
+ * action types supported are GoTo, GoToR, URI and Launch.
+ *
+ * The list structure is composed by a number of HashMap, keyed by strings, one HashMap
+ * for each bookmark.
+ * The element values are all strings with the exception of the key "Kids" that has
+ * another list for the child bookmarks.
+ *
+ * All the bookmarks have a "Title" with the
+ * bookmark title and optionally a "Style" that can be "bold", "italic" or a
+ * combination of both. They can also have a "Color" key with a value of three
+ * floats separated by spaces. The key "Open" can have the values "true" or "false" and
+ * signals the open status of the children. It's "true" by default.
+ *
+ * The actions and the parameters can be:
+ *
+ * "Action" = "GoTo" - "Page" | "Named"
+ *
+ * "Page" = "3 XYZ 70 400 null" - page number followed by a destination (/XYZ is also accepted)
+ * "Named" = "named_destination"
+ *
+ * "Action" = "GoToR" - "Page" | "Named" | "NamedN", "File", ["NewWindow"]
+ *
+ * "Page" = "3 XYZ 70 400 null" - page number followed by a destination (/XYZ is also accepted)
+ * "Named" = "named_destination_as_a_string"
+ * "NamedN" = "named_destination_as_a_name"
+ * "File" - "the_file_to_open"
+ * "NewWindow" - "true" or "false"
+ *
+ * "Action" = "URI" - "URI"
+ *
+ * "URI" = "http://sf.net" - URI to jump to
+ *
+ * "Action" = "Launch" - "File"
+ *
+ * "File" - "the_file_to_open_or_execute"
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class SimpleBookmark implements SimpleXMLDocHandler {
+
+ private ArrayList topList;
+ private Stack attr = new Stack();
+
+ /** Creates a new instance of SimpleBookmark */
+ private SimpleBookmark() {
+ }
+
+ private static List bookmarkDepth(PdfReader reader, PdfDictionary outline, IntHashtable pages) {
+ ArrayList list = new ArrayList();
+ while (outline != null) {
+ HashMap map = new HashMap();
+ PdfString title = (PdfString)PdfReader.getPdfObjectRelease(outline.get(PdfName.TITLE));
+ map.put("Title", title.toUnicodeString());
+ PdfArray color = (PdfArray)PdfReader.getPdfObjectRelease(outline.get(PdfName.C));
+ if (color != null && color.getArrayList().size() == 3) {
+ ByteBuffer out = new ByteBuffer();
+ ArrayList arr = color.getArrayList();
+ out.append(((PdfNumber)arr.get(0)).floatValue()).append(' ');
+ out.append(((PdfNumber)arr.get(1)).floatValue()).append(' ');
+ out.append(((PdfNumber)arr.get(2)).floatValue());
+ map.put("Color", PdfEncodings.convertToString(out.toByteArray(), null));
+ }
+ PdfNumber style = (PdfNumber)PdfReader.getPdfObjectRelease(outline.get(PdfName.F));
+ if (style != null) {
+ int f = style.intValue();
+ String s = "";
+ if ((f & 1) != 0)
+ s += "italic ";
+ if ((f & 2) != 0)
+ s += "bold ";
+ s = s.trim();
+ if (s.length() != 0)
+ map.put("Style", s);
+ }
+ PdfNumber count = (PdfNumber)PdfReader.getPdfObjectRelease(outline.get(PdfName.COUNT));
+ if (count != null && count.intValue() < 0)
+ map.put("Open", "false");
+ try {
+ PdfObject dest = PdfReader.getPdfObjectRelease(outline.get(PdfName.DEST));
+ if (dest != null) {
+ mapGotoBookmark(map, dest, pages); //changed by ujihara 2004-06-13
+ }
+ else {
+ PdfDictionary action = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.A));
+ if (action != null) {
+ if (PdfName.GOTO.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
+ dest = PdfReader.getPdfObjectRelease(action.get(PdfName.D));
+ if (dest != null) {
+ mapGotoBookmark(map, dest, pages);
+ }
+ }
+ else if (PdfName.URI.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
+ map.put("Action", "URI");
+ map.put("URI", ((PdfString)PdfReader.getPdfObjectRelease(action.get(PdfName.URI))).toUnicodeString());
+ }
+ else if (PdfName.GOTOR.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
+ dest = PdfReader.getPdfObjectRelease(action.get(PdfName.D));
+ if (dest != null) {
+ if (dest.isString())
+ map.put("Named", dest.toString());
+ else if (dest.isName())
+ map.put("NamedN", PdfName.decodeName(dest.toString()));
+ else if (dest.isArray()) {
+ ArrayList arr = ((PdfArray)dest).getArrayList();
+ StringBuffer s = new StringBuffer();
+ s.append(arr.get(0).toString());
+ s.append(' ').append(arr.get(1).toString());
+ for (int k = 2; k < arr.size(); ++k)
+ s.append(' ').append(arr.get(k).toString());
+ map.put("Page", s.toString());
+ }
+ }
+ map.put("Action", "GoToR");
+ PdfObject file = PdfReader.getPdfObjectRelease(action.get(PdfName.F));
+ if (file != null) {
+ if (file.isString())
+ map.put("File", ((PdfString)file).toUnicodeString());
+ else if (file.isDictionary()) {
+ file = PdfReader.getPdfObject(((PdfDictionary)file).get(PdfName.F));
+ if (file.isString())
+ map.put("File", ((PdfString)file).toUnicodeString());
+ }
+ }
+ PdfObject newWindow = PdfReader.getPdfObjectRelease(action.get(PdfName.NEWWINDOW));
+ if (newWindow != null)
+ map.put("NewWindow", newWindow.toString());
+ }
+ else if (PdfName.LAUNCH.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
+ map.put("Action", "Launch");
+ PdfObject file = PdfReader.getPdfObjectRelease(action.get(PdfName.F));
+ if (file == null)
+ file = PdfReader.getPdfObjectRelease(action.get(PdfName.WIN));
+ if (file != null) {
+ if (file.isString())
+ map.put("File", ((PdfString)file).toUnicodeString());
+ else if (file.isDictionary()) {
+ file = PdfReader.getPdfObjectRelease(((PdfDictionary)file).get(PdfName.F));
+ if (file.isString())
+ map.put("File", ((PdfString)file).toUnicodeString());
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e) {
+ //empty on purpose
+ }
+ PdfDictionary first = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.FIRST));
+ if (first != null) {
+ map.put("Kids", bookmarkDepth(reader, first, pages));
+ }
+ list.add(map);
+ outline = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.NEXT));
+ }
+ return list;
+ }
+
+ private static void mapGotoBookmark(HashMap map, PdfObject dest, IntHashtable pages)
+ {
+ if (dest.isString())
+ map.put("Named", dest.toString());
+ else if (dest.isName())
+ map.put("Named", PdfName.decodeName(dest.toString()));
+ else if (dest.isArray())
+ map.put("Page", makeBookmarkParam((PdfArray)dest, pages)); //changed by ujihara 2004-06-13
+ map.put("Action", "GoTo");
+ }
+
+ private static String makeBookmarkParam(PdfArray dest, IntHashtable pages)
+ {
+ ArrayList arr = ((PdfArray)dest).getArrayList();
+ StringBuffer s = new StringBuffer();
+ s.append(pages.get(getNumber((PdfIndirectReference)arr.get(0)))); //changed by ujihara 2004-06-13
+ s.append(' ').append(arr.get(1).toString().substring(1));
+ for (int k = 2; k < arr.size(); ++k)
+ s.append(' ').append(arr.get(k).toString());
+ return s.toString();
+ }
+
+ /**
+ * Gets number of indirect. If type of directed indirect is PAGES, it refers PAGE object through KIDS.
+ * (Contributed by Kazuya Ujihara)
+ * @param indirect
+ * 2004-06-13
+ */
+ private static int getNumber(PdfIndirectReference indirect)
+ {
+ PdfDictionary pdfObj = (PdfDictionary)PdfReader.getPdfObjectRelease(indirect);
+ if (pdfObj.contains(PdfName.TYPE) && pdfObj.get(PdfName.TYPE).equals(PdfName.PAGES) && pdfObj.contains(PdfName.KIDS))
+ {
+ PdfArray kids = (PdfArray)pdfObj.get(PdfName.KIDS);
+ indirect = (PdfIndirectReference)kids.arrayList.get(0);
+ }
+ return indirect.getNumber();
+ }
+
+ /**
+ * Gets a List
with the bookmarks. It returns null
if
+ * the document doesn't have any bookmarks.
+ * @param reader the document
+ * @return a List
with the bookmarks or null
if the
+ * document doesn't have any
+ */
+ public static List getBookmark(PdfReader reader) {
+ PdfDictionary catalog = reader.getCatalog();
+ PdfObject obj = PdfReader.getPdfObjectRelease(catalog.get(PdfName.OUTLINES));
+ if (obj == null || !obj.isDictionary())
+ return null;
+ PdfDictionary outlines = (PdfDictionary)obj;
+ IntHashtable pages = new IntHashtable();
+ int numPages = reader.getNumberOfPages();
+ for (int k = 1; k <= numPages; ++k) {
+ pages.put(reader.getPageOrigRef(k).getNumber(), k);
+ reader.releasePage(k);
+ }
+ return bookmarkDepth(reader, (PdfDictionary)PdfReader.getPdfObjectRelease(outlines.get(PdfName.FIRST)), pages);
+ }
+
+ /**
+ * Removes the bookmark entries for a number of page ranges. The page ranges
+ * consists of a number of pairs with the start/end page range. The page numbers
+ * are inclusive.
+ * @param list the bookmarks
+ * @param pageRange the page ranges, always in pairs.
+ */
+ public static void eliminatePages(List list, int pageRange[]) {
+ if (list == null)
+ return;
+ for (Iterator it = list.listIterator(); it.hasNext();) {
+ HashMap map = (HashMap)it.next();
+ boolean hit = false;
+ if ("GoTo".equals(map.get("Action"))) {
+ String page = (String)map.get("Page");
+ if (page != null) {
+ page = page.trim();
+ int idx = page.indexOf(' ');
+ int pageNum;
+ if (idx < 0)
+ pageNum = Integer.parseInt(page);
+ else
+ pageNum = Integer.parseInt(page.substring(0, idx));
+ int len = pageRange.length & 0xfffffffe;
+ for (int k = 0; k < len; k += 2) {
+ if (pageNum >= pageRange[k] && pageNum <= pageRange[k + 1]) {
+ hit = true;
+ break;
+ }
+ }
+ }
+ }
+ List kids = (List)map.get("Kids");
+ if (kids != null) {
+ eliminatePages(kids, pageRange);
+ if (kids.size() == 0) {
+ map.remove("Kids");
+ kids = null;
+ }
+ }
+ if (hit) {
+ if (kids == null)
+ it.remove();
+ else {
+ map.remove("Action");
+ map.remove("Page");
+ map.remove("Named");
+ }
+ }
+ }
+ }
+
+ /**
+ * For the pages in range add the pageShift
to the page number.
+ * The page ranges
+ * consists of a number of pairs with the start/end page range. The page numbers
+ * are inclusive.
+ * @param list the bookmarks
+ * @param pageShift the number to add to the pages in range
+ * @param pageRange the page ranges, always in pairs. It can be null
+ * to include all the pages
+ */
+ public static void shiftPageNumbers(List list, int pageShift, int pageRange[]) {
+ if (list == null)
+ return;
+ for (Iterator it = list.listIterator(); it.hasNext();) {
+ HashMap map = (HashMap)it.next();
+ if ("GoTo".equals(map.get("Action"))) {
+ String page = (String)map.get("Page");
+ if (page != null) {
+ page = page.trim();
+ int idx = page.indexOf(' ');
+ int pageNum;
+ if (idx < 0)
+ pageNum = Integer.parseInt(page);
+ else
+ pageNum = Integer.parseInt(page.substring(0, idx));
+ boolean hit = false;
+ if (pageRange == null)
+ hit = true;
+ else {
+ int len = pageRange.length & 0xfffffffe;
+ for (int k = 0; k < len; k += 2) {
+ if (pageNum >= pageRange[k] && pageNum <= pageRange[k + 1]) {
+ hit = true;
+ break;
+ }
+ }
+ }
+ if (hit) {
+ if (idx < 0)
+ page = (pageNum + pageShift) + "";
+ else
+ page = (pageNum + pageShift) + page.substring(idx);
+ }
+ map.put("Page", page);
+ }
+ }
+ List kids = (List)map.get("Kids");
+ if (kids != null)
+ shiftPageNumbers(kids, pageShift, pageRange);
+ }
+ }
+
+ static void createOutlineAction(PdfDictionary outline, HashMap map, PdfWriter writer, boolean namedAsNames) throws IOException {
+ try {
+ String action = (String)map.get("Action");
+ if ("GoTo".equals(action)) {
+ String p;
+ if ((p = (String)map.get("Named")) != null) {
+ if (namedAsNames)
+ outline.put(PdfName.DEST, new PdfName(p));
+ else
+ outline.put(PdfName.DEST, new PdfString(p, null));
+ }
+ else if ((p = (String)map.get("Page")) != null) {
+ PdfArray ar = new PdfArray();
+ StringTokenizer tk = new StringTokenizer(p);
+ int n = Integer.parseInt(tk.nextToken());
+ ar.add(writer.getPageReference(n));
+ if (!tk.hasMoreTokens()) {
+ ar.add(PdfName.XYZ);
+ ar.add(new float[]{0, 10000, 0});
+ }
+ else {
+ String fn = tk.nextToken();
+ if (fn.startsWith("/"))
+ fn = fn.substring(1);
+ ar.add(new PdfName(fn));
+ for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) {
+ fn = tk.nextToken();
+ if (fn.equals("null"))
+ ar.add(PdfNull.PDFNULL);
+ else
+ ar.add(new PdfNumber(fn));
+ }
+ }
+ outline.put(PdfName.DEST, ar);
+ }
+ }
+ else if ("GoToR".equals(action)) {
+ String p;
+ PdfDictionary dic = new PdfDictionary();
+ if ((p = (String)map.get("Named")) != null)
+ dic.put(PdfName.D, new PdfString(p, null));
+ else if ((p = (String)map.get("NamedN")) != null)
+ dic.put(PdfName.D, new PdfName(p));
+ else if ((p = (String)map.get("Page")) != null){
+ PdfArray ar = new PdfArray();
+ StringTokenizer tk = new StringTokenizer(p);
+ ar.add(new PdfNumber(tk.nextToken()));
+ if (!tk.hasMoreTokens()) {
+ ar.add(PdfName.XYZ);
+ ar.add(new float[]{0, 10000, 0});
+ }
+ else {
+ String fn = tk.nextToken();
+ if (fn.startsWith("/"))
+ fn = fn.substring(1);
+ ar.add(new PdfName(fn));
+ for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) {
+ fn = tk.nextToken();
+ if (fn.equals("null"))
+ ar.add(PdfNull.PDFNULL);
+ else
+ ar.add(new PdfNumber(fn));
+ }
+ }
+ dic.put(PdfName.D, ar);
+ }
+ String file = (String)map.get("File");
+ if (dic.size() > 0 && file != null) {
+ dic.put(PdfName.S, PdfName.GOTOR);
+ dic.put(PdfName.F, new PdfString(file));
+ String nw = (String)map.get("NewWindow");
+ if (nw != null) {
+ if (nw.equals("true"))
+ dic.put(PdfName.NEWWINDOW, PdfBoolean.PDFTRUE);
+ else if (nw.equals("false"))
+ dic.put(PdfName.NEWWINDOW, PdfBoolean.PDFFALSE);
+ }
+ outline.put(PdfName.A, dic);
+ }
+ }
+ else if ("URI".equals(action)) {
+ String uri = (String)map.get("URI");
+ if (uri != null) {
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.S, PdfName.URI);
+ dic.put(PdfName.URI, new PdfString(uri));
+ outline.put(PdfName.A, dic);
+ }
+ }
+ else if ("Launch".equals(action)) {
+ String file = (String)map.get("File");
+ if (file != null) {
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.S, PdfName.LAUNCH);
+ dic.put(PdfName.F, new PdfString(file));
+ outline.put(PdfName.A, dic);
+ }
+ }
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+
+ public static Object[] iterateOutlines(PdfWriter writer, PdfIndirectReference parent, List kids, boolean namedAsNames) throws IOException {
+ PdfIndirectReference refs[] = new PdfIndirectReference[kids.size()];
+ for (int k = 0; k < refs.length; ++k)
+ refs[k] = writer.getPdfIndirectReference();
+ int ptr = 0;
+ int count = 0;
+ for (Iterator it = kids.listIterator(); it.hasNext(); ++ptr) {
+ HashMap map = (HashMap)it.next();
+ Object lower[] = null;
+ List subKid = (List)map.get("Kids");
+ if (subKid != null && subKid.size() > 0)
+ lower = iterateOutlines(writer, refs[ptr], subKid, namedAsNames);
+ PdfDictionary outline = new PdfDictionary();
+ ++count;
+ if (lower != null) {
+ outline.put(PdfName.FIRST, (PdfIndirectReference)lower[0]);
+ outline.put(PdfName.LAST, (PdfIndirectReference)lower[1]);
+ int n = ((Integer)lower[2]).intValue();
+ if ("false".equals(map.get("Open"))) {
+ outline.put(PdfName.COUNT, new PdfNumber(-n));
+ }
+ else {
+ outline.put(PdfName.COUNT, new PdfNumber(n));
+ count += n;
+ }
+ }
+ outline.put(PdfName.PARENT, parent);
+ if (ptr > 0)
+ outline.put(PdfName.PREV, refs[ptr - 1]);
+ if (ptr < refs.length - 1)
+ outline.put(PdfName.NEXT, refs[ptr + 1]);
+ outline.put(PdfName.TITLE, new PdfString((String)map.get("Title"), PdfObject.TEXT_UNICODE));
+ String color = (String)map.get("Color");
+ if (color != null) {
+ try {
+ PdfArray arr = new PdfArray();
+ StringTokenizer tk = new StringTokenizer(color);
+ for (int k = 0; k < 3; ++k) {
+ float f = Float.valueOf(tk.nextToken()).intValue();
+ if (f < 0) f = 0;
+ if (f > 1) f = 1;
+ arr.add(new PdfNumber(f));
+ }
+ outline.put(PdfName.C, arr);
+ } catch(Exception e){} //in case it's malformed
+ }
+ String style = (String)map.get("Style");
+ if (style != null) {
+ style = style.toLowerCase();
+ int bits = 0;
+ if (style.indexOf("italic") >= 0)
+ bits |= 1;
+ if (style.indexOf("bold") >= 0)
+ bits |= 2;
+ if (bits != 0)
+ outline.put(PdfName.F, new PdfNumber(bits));
+ }
+ createOutlineAction(outline, map, writer, namedAsNames);
+ writer.addToBody(outline, refs[ptr]);
+ }
+ return new Object[]{refs[0], refs[refs.length - 1], new Integer(count)};
+ }
+
+ /**
+ * Exports the bookmarks to XML. Only of use if the generation is to be include in
+ * some other XML document.
+ * @param list the bookmarks
+ * @param out the export destination. The writer is not closed
+ * @param indent the indentation level. Pretty printing significant only
+ * @param onlyASCII codes above 127 will always be escaped with &#nn; if true
,
+ * whatever the encoding
+ * @throws IOException on error
+ */
+ public static void exportToXMLNode(List list, Writer out, int indent, boolean onlyASCII) throws IOException {
+ String dep = "";
+ for (int k = 0; k < indent; ++k)
+ dep += " ";
+ for (Iterator it = list.iterator(); it.hasNext();) {
+ HashMap map = (HashMap)it.next();
+ String title = null;
+ out.write(dep);
+ out.write("");
+ if (title == null)
+ title = "";
+ out.write(SimpleXMLParser.escapeXML(title, onlyASCII));
+ if (kids != null) {
+ out.write("\n");
+ exportToXMLNode(kids, out, indent + 1, onlyASCII);
+ out.write(dep);
+ }
+ out.write(" \n");
+ }
+ }
+
+ /**
+ * Exports the bookmarks to XML. The DTD for this XML is:
+ *
+ *
+ * <?xml version='1.0' encoding='UTF-8'?>
+ * <!ELEMENT Title (#PCDATA|Title)*>
+ * <!ATTLIST Title
+ * Action CDATA #IMPLIED
+ * Open CDATA #IMPLIED
+ * Page CDATA #IMPLIED
+ * URI CDATA #IMPLIED
+ * File CDATA #IMPLIED
+ * Named CDATA #IMPLIED
+ * NamedN CDATA #IMPLIED
+ * NewWindow CDATA #IMPLIED
+ * Style CDATA #IMPLIED
+ * Color CDATA #IMPLIED
+ * >
+ * <!ELEMENT Bookmark (Title)*>
+ *
+ * @param list the bookmarks
+ * @param out the export destination. The stream is not closed
+ * @param encoding the encoding according to IANA conventions
+ * @param onlyASCII codes above 127 will always be escaped with &#nn; if true
,
+ * whatever the encoding
+ * @throws IOException on error
+ */
+ public static void exportToXML(List list, OutputStream out, String encoding, boolean onlyASCII) throws IOException {
+ String jenc = SimpleXMLParser.getJavaEncoding(encoding);
+ Writer wrt = new BufferedWriter(new OutputStreamWriter(out, jenc));
+ exportToXML(list, wrt, encoding, onlyASCII);
+ }
+
+ /**
+ * Exports the bookmarks to XML.
+ * @param list the bookmarks
+ * @param wrt the export destination. The writer is not closed
+ * @param encoding the encoding according to IANA conventions
+ * @param onlyASCII codes above 127 will always be escaped with &#nn; if true
,
+ * whatever the encoding
+ * @throws IOException on error
+ */
+ public static void exportToXML(List list, Writer wrt, String encoding, boolean onlyASCII) throws IOException {
+ wrt.write("\n\n");
+ exportToXMLNode(list, wrt, 1, onlyASCII);
+ wrt.write(" \n");
+ wrt.flush();
+ }
+
+ /**
+ * Import the bookmarks from XML.
+ * @param in the XML source. The stream is not closed
+ * @throws IOException on error
+ * @return the bookmarks
+ */
+ public static List importFromXML(InputStream in) throws IOException {
+ SimpleBookmark book = new SimpleBookmark();
+ SimpleXMLParser.parse(book, in);
+ return book.topList;
+ }
+
+ /**
+ * Import the bookmarks from XML.
+ * @param in the XML source. The reader is not closed
+ * @throws IOException on error
+ * @return the bookmarks
+ */
+ public static List importFromXML(Reader in) throws IOException {
+ SimpleBookmark book = new SimpleBookmark();
+ SimpleXMLParser.parse(book, in);
+ return book.topList;
+ }
+
+ public void endDocument() {
+ }
+
+ public void endElement(String tag) {
+ if (tag.equals("Bookmark")) {
+ if (attr.isEmpty())
+ return;
+ else
+ throw new RuntimeException("Bookmark end tag out of place.");
+ }
+ if (!tag.equals("Title"))
+ throw new RuntimeException("Invalid end tag - " + tag);
+ HashMap attributes = (HashMap)attr.pop();
+ String title = (String)attributes.get("Title");
+ attributes.put("Title", title.trim());
+ String named = (String)attributes.get("Named");
+ if (named != null)
+ attributes.put("Named", SimpleNamedDestination.unEscapeBinaryString(named));
+ named = (String)attributes.get("NamedN");
+ if (named != null)
+ attributes.put("NamedN", SimpleNamedDestination.unEscapeBinaryString(named));
+ if (attr.isEmpty())
+ topList.add(attributes);
+ else {
+ HashMap parent = (HashMap)attr.peek();
+ List kids = (List)parent.get("Kids");
+ if (kids == null) {
+ kids = new ArrayList();
+ parent.put("Kids", kids);
+ }
+ kids.add(attributes);
+ }
+ }
+
+ public void startDocument() {
+ }
+
+ public void startElement(String tag, HashMap h) {
+ if (topList == null) {
+ if (tag.equals("Bookmark")) {
+ topList = new ArrayList();
+ return;
+ }
+ else
+ throw new RuntimeException("Root element is not Bookmark.");
+ }
+ if (!tag.equals("Title"))
+ throw new RuntimeException("Tag " + tag + " not allowed.");
+ HashMap attributes = new HashMap(h);
+ attributes.put("Title", "");
+ attributes.remove("Kids");
+ attr.push(attributes);
+ }
+
+ public void text(String str) {
+ if (attr.isEmpty())
+ return;
+ HashMap attributes = (HashMap)attr.peek();
+ String title = (String)attributes.get("Title");
+ title += str;
+ attributes.put("Title", title);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SimpleNamedDestination.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SimpleNamedDestination.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SimpleNamedDestination.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SimpleNamedDestination.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.io.BufferedWriter;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class SimpleNamedDestination implements SimpleXMLDocHandler {
+
+ private HashMap xmlNames;
+ private HashMap xmlLast;
+
+ private SimpleNamedDestination() {
+ }
+
+ public static HashMap getNamedDestination(PdfReader reader, boolean fromNames) {
+ IntHashtable pages = new IntHashtable();
+ int numPages = reader.getNumberOfPages();
+ for (int k = 1; k <= numPages; ++k)
+ pages.put(reader.getPageOrigRef(k).getNumber(), k);
+ HashMap names = fromNames ? reader.getNamedDestinationFromNames() : reader.getNamedDestinationFromStrings();
+ for (Iterator it = names.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry)it.next();
+ ArrayList arr = ((PdfArray)entry.getValue()).getArrayList();
+ StringBuffer s = new StringBuffer();
+ try {
+ s.append(pages.get(((PdfIndirectReference)arr.get(0)).getNumber()));
+ s.append(' ').append(arr.get(1).toString().substring(1));
+ for (int k = 2; k < arr.size(); ++k)
+ s.append(' ').append(arr.get(k).toString());
+ entry.setValue(s.toString());
+ }
+ catch (Exception e) {
+ it.remove();
+ }
+ }
+ return names;
+ }
+
+ /**
+ * Exports the bookmarks to XML. The DTD for this XML is:
+ *
+ *
+ * <?xml version='1.0' encoding='UTF-8'?>
+ * <!ELEMENT Name (#PCDATA)>
+ * <!ATTLIST Name
+ * Page CDATA #IMPLIED
+ * >
+ * <!ELEMENT Destination (Name)*>
+ *
+ * @param names the names
+ * @param out the export destination. The stream is not closed
+ * @param encoding the encoding according to IANA conventions
+ * @param onlyASCII codes above 127 will always be escaped with &#nn; if true
,
+ * whatever the encoding
+ * @throws IOException on error
+ */
+ public static void exportToXML(HashMap names, OutputStream out, String encoding, boolean onlyASCII) throws IOException {
+ String jenc = SimpleXMLParser.getJavaEncoding(encoding);
+ Writer wrt = new BufferedWriter(new OutputStreamWriter(out, jenc));
+ exportToXML(names, wrt, encoding, onlyASCII);
+ }
+
+ /**
+ * Exports the bookmarks to XML.
+ * @param names the names
+ * @param wrt the export destination. The writer is not closed
+ * @param encoding the encoding according to IANA conventions
+ * @param onlyASCII codes above 127 will always be escaped with &#nn; if true
,
+ * whatever the encoding
+ * @throws IOException on error
+ */
+ public static void exportToXML(HashMap names, Writer wrt, String encoding, boolean onlyASCII) throws IOException {
+ wrt.write("\n\n");
+ for (Iterator it = names.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry)it.next();
+ String key = (String)entry.getKey();
+ String value = (String)entry.getValue();
+ wrt.write(" ");
+ wrt.write(SimpleXMLParser.escapeXML(escapeBinaryString(key), onlyASCII));
+ wrt.write(" \n");
+ }
+ wrt.write(" \n");
+ wrt.flush();
+ }
+
+ /**
+ * Import the names from XML.
+ * @param in the XML source. The stream is not closed
+ * @throws IOException on error
+ * @return the names
+ */
+ public static HashMap importFromXML(InputStream in) throws IOException {
+ SimpleNamedDestination names = new SimpleNamedDestination();
+ SimpleXMLParser.parse(names, in);
+ return names.xmlNames;
+ }
+
+ /**
+ * Import the names from XML.
+ * @param in the XML source. The reader is not closed
+ * @throws IOException on error
+ * @return the names
+ */
+ public static HashMap importFromXML(Reader in) throws IOException {
+ SimpleNamedDestination names = new SimpleNamedDestination();
+ SimpleXMLParser.parse(names, in);
+ return names.xmlNames;
+ }
+
+ static PdfArray createDestinationArray(String value, PdfWriter writer) throws IOException {
+ PdfArray ar = new PdfArray();
+ StringTokenizer tk = new StringTokenizer(value);
+ int n = Integer.parseInt(tk.nextToken());
+ ar.add(writer.getPageReference(n));
+ if (!tk.hasMoreTokens()) {
+ ar.add(PdfName.XYZ);
+ ar.add(new float[]{0, 10000, 0});
+ }
+ else {
+ String fn = tk.nextToken();
+ if (fn.startsWith("/"))
+ fn = fn.substring(1);
+ ar.add(new PdfName(fn));
+ for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) {
+ fn = tk.nextToken();
+ if (fn.equals("null"))
+ ar.add(PdfNull.PDFNULL);
+ else
+ ar.add(new PdfNumber(fn));
+ }
+ }
+ return ar;
+ }
+
+ public static PdfDictionary outputNamedDestinationAsNames(HashMap names, PdfWriter writer) throws IOException {
+ PdfDictionary dic = new PdfDictionary();
+ for (Iterator it = names.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry)it.next();
+ try {
+ String key = (String)entry.getKey();
+ String value = (String)entry.getValue();
+ PdfArray ar = createDestinationArray(value, writer);
+ PdfName kn = new PdfName(key);
+ dic.put(kn, ar);
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ return dic;
+ }
+
+ public static PdfDictionary outputNamedDestinationAsStrings(HashMap names, PdfWriter writer) throws IOException {
+ HashMap n2 = new HashMap(names);
+ for (Iterator it = n2.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry)it.next();
+ try {
+ String value = (String)entry.getValue();
+ PdfArray ar = createDestinationArray(value, writer);
+ entry.setValue(writer.addToBody(ar).getIndirectReference());
+ }
+ catch (Exception e) {
+ it.remove();
+ }
+ }
+ return PdfNameTree.writeTree(n2, writer);
+ }
+
+ public static String escapeBinaryString(String s) {
+ StringBuffer buf = new StringBuffer();
+ char cc[] = s.toCharArray();
+ int len = cc.length;
+ for (int k = 0; k < len; ++k) {
+ char c = cc[k];
+ if (c < ' ') {
+ buf.append('\\');
+ String octal = "00" + Integer.toOctalString((int)c);
+ buf.append(octal.substring(octal.length() - 3));
+ }
+ else if (c == '\\')
+ buf.append("\\\\");
+ else
+ buf.append(c);
+ }
+ return buf.toString();
+ }
+
+ public static String unEscapeBinaryString(String s) {
+ StringBuffer buf = new StringBuffer();
+ char cc[] = s.toCharArray();
+ int len = cc.length;
+ for (int k = 0; k < len; ++k) {
+ char c = cc[k];
+ if (c == '\\') {
+ if (++k >= len) {
+ buf.append('\\');
+ break;
+ }
+ c = cc[k];
+ if (c >= '0' && c <= '7') {
+ int n = c - '0';
+ ++k;
+ for (int j = 0; j < 2 && k < len; ++j) {
+ c = cc[k];
+ if (c >= '0' && c <= '7') {
+ ++k;
+ n = n * 8 + c - '0';
+ }
+ else {
+ break;
+ }
+ }
+ --k;
+ buf.append((char)n);
+ }
+ else
+ buf.append(c);
+ }
+ else
+ buf.append(c);
+ }
+ return buf.toString();
+ }
+
+ public void endDocument() {
+ }
+
+ public void endElement(String tag) {
+ if (tag.equals("Destination")) {
+ if (xmlLast == null && xmlNames != null)
+ return;
+ else
+ throw new RuntimeException("Destination end tag out of place.");
+ }
+ if (!tag.equals("Name"))
+ throw new RuntimeException("Invalid end tag - " + tag);
+ if (xmlLast == null || xmlNames == null)
+ throw new RuntimeException("Name end tag out of place.");
+ if (!xmlLast.containsKey("Page"))
+ throw new RuntimeException("Page attribute missing.");
+ xmlNames.put(unEscapeBinaryString((String)xmlLast.get("Name")), xmlLast.get("Page"));
+ xmlLast = null;
+ }
+
+ public void startDocument() {
+ }
+
+ public void startElement(String tag, HashMap h) {
+ if (xmlNames == null) {
+ if (tag.equals("Destination")) {
+ xmlNames = new HashMap();
+ return;
+ }
+ else
+ throw new RuntimeException("Root element is not Destination.");
+ }
+ if (!tag.equals("Name"))
+ throw new RuntimeException("Tag " + tag + " not allowed.");
+ if (xmlLast != null)
+ throw new RuntimeException("Nested tags are not allowed.");
+ xmlLast = new HashMap(h);
+ xmlLast.put("Name", "");
+ }
+
+ public void text(String str) {
+ if (xmlLast == null)
+ return;
+ String name = (String)xmlLast.get("Name");
+ name += str;
+ xmlLast.put("Name", name);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SimpleXMLDocHandler.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SimpleXMLDocHandler.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SimpleXMLDocHandler.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SimpleXMLDocHandler.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.util.HashMap;
+
+/**
+ * The handler for the events fired by SimpleXMLParser
.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public interface SimpleXMLDocHandler {
+ /**
+ * Called when a start tag is found.
+ * @param tag the tag name
+ * @param h the tag's attributes
+ */
+ public void startElement(String tag, HashMap h);
+ /**
+ * Called when an end tag is found.
+ * @param tag the tag name
+ */
+ public void endElement(String tag);
+ /**
+ * Called when the document starts to be parsed.
+ */
+ public void startDocument();
+ /**
+ * Called after the document is parsed.
+ */
+ public void endDocument();
+ /**
+ * Called when a text element is found.
+ * @param str the text element, probably a fragment.
+ */
+ public void text(String str);
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SimpleXMLDocHandlerComment.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SimpleXMLDocHandlerComment.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SimpleXMLDocHandlerComment.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SimpleXMLDocHandlerComment.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ * The handler for the events fired by SimpleXMLParser
.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public interface SimpleXMLDocHandlerComment {
+ /**
+ * Called when a comment is found.
+ * @param text the comment text
+ */
+ public void comment(String text);
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SimpleXMLParser.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SimpleXMLParser.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SimpleXMLParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SimpleXMLParser.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,1174 @@
+/*
+ * Copyright 2003 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.*;
+import java.util.Stack;
+import java.util.HashMap;
+
+/**
+ * A simple XML and HTML parser. This parser is, like the SAX parser,
+ * an event based parser, but with much less functionality.
+ *
+ * The parser can:
+ *
+ *
+ * It recognizes the encoding used
+ * It recognizes all the elements' start tags and end tags
+ * It lists attributes, where attribute values can be enclosed in single or double quotes
+ * It recognizes the <[CDATA[ ... ]]>
construct
+ * It recognizes the standard entities: &, <, >, ", and ', as well as numeric entities
+ * It maps lines ending in \r\n
and \r
to \n
on input, in accordance with the XML Specification, Section 2.11
+ *
+ *
+ * The code is based on
+ * http://www.javaworld.com/javaworld/javatips/javatip128/ with some extra
+ * code from XERCES to recognize the encoding.
+ */
+public class SimpleXMLParser {
+
+ // ssteward
+ // Input_UTF8 was being omitted from Windows static builds
+ private static Class c1= gnu.gcj.convert.Input_UTF8.class;
+ private static Class c2= gnu.gcj.convert.Input_8859_1.class;
+ private static Class c3= gnu.gcj.convert.Input_ASCII.class;
+
+ private static final HashMap fIANA2JavaMap = new HashMap();
+ private static final HashMap entityMap = new HashMap();
+
+ private static int popMode(Stack st) {
+ if(!st.empty())
+ return ((Integer)st.pop()).intValue();
+ else
+ return PRE;
+ }
+
+ private final static int
+ TEXT = 1,
+ ENTITY = 2,
+ OPEN_TAG = 3,
+ CLOSE_TAG = 4,
+ START_TAG = 5,
+ ATTRIBUTE_LVALUE = 6,
+ ATTRIBUTE_EQUAL = 9,
+ ATTRIBUTE_RVALUE = 10,
+ QUOTE = 7,
+ IN_TAG = 8,
+ SINGLE_TAG = 12,
+ COMMENT = 13,
+ DONE = 11,
+ DOCTYPE = 14,
+ PRE = 15,
+ CDATA = 16;
+
+ private SimpleXMLParser() {
+ }
+
+ /**
+ * Parses the XML document firing the events to the handler.
+ * @param doc the document handler
+ * @param in the document. The encoding is deduced from the stream. The stream is not closed
+ * @throws IOException on error
+ */
+ public static void parse(SimpleXMLDocHandler doc, InputStream in) throws IOException {
+ byte b4[] = new byte[4];
+ int count = in.read(b4);
+ if (count != 4)
+ throw new IOException("Insufficient length.");
+ String encoding = getEncodingName(b4);
+ String decl = null;
+ if (encoding.equals("UTF-8")) {
+ StringBuffer sb = new StringBuffer();
+ int c;
+ while ((c = in.read()) != -1) {
+ if (c == '>')
+ break;
+ sb.append((char)c);
+ }
+ decl = sb.toString();
+ }
+ else if (encoding.equals("CP037")) {
+ ByteArrayOutputStream bi = new ByteArrayOutputStream();
+ int c;
+ while ((c = in.read()) != -1) {
+ if (c == 0x6e) // that's '>' in ebcdic
+ break;
+ bi.write(c);
+ }
+ decl = new String(bi.toByteArray(), "CP037");
+ }
+ if (decl != null) {
+ decl = getDeclaredEncoding(decl);
+ if (decl != null)
+ encoding = decl;
+ }
+ parse(doc, new InputStreamReader(in, getJavaEncoding(encoding)));
+ }
+
+ private static String getDeclaredEncoding(String decl) {
+ if (decl == null)
+ return null;
+ int idx = decl.indexOf("encoding");
+ if (idx < 0)
+ return null;
+ int idx1 = decl.indexOf('"', idx);
+ int idx2 = decl.indexOf('\'', idx);
+ if (idx1 == idx2)
+ return null;
+ if ((idx1 < 0 && idx2 > 0) || (idx2 > 0 && idx2 < idx1)) {
+ int idx3 = decl.indexOf('\'', idx2 + 1);
+ if (idx3 < 0)
+ return null;
+ return decl.substring(idx2 + 1, idx3);
+ }
+ if ((idx2 < 0 && idx1 > 0) || (idx1 > 0 && idx1 < idx2)) {
+ int idx3 = decl.indexOf('"', idx1 + 1);
+ if (idx3 < 0)
+ return null;
+ return decl.substring(idx1 + 1, idx3);
+ }
+ return null;
+ }
+
+ /**
+ * Gets the java encoding from the IANA encoding. If the encoding cannot be found
+ * it returns the input.
+ * @param iana the IANA encoding
+ * @return the java encoding
+ */
+ public static String getJavaEncoding(String iana) {
+ String IANA = iana.toUpperCase();
+ String jdec = (String)fIANA2JavaMap.get(IANA);
+ if (jdec == null)
+ jdec = iana;
+ return jdec;
+ }
+
+ public static void parse(SimpleXMLDocHandler doc,Reader r) throws IOException {
+ parse(doc, null, r, false);
+ }
+
+ /**
+ * Parses the XML document firing the events to the handler.
+ * @param doc the document handler
+ * @param r the document. The encoding is already resolved. The reader is not closed
+ * @throws IOException on error
+ */
+ public static void parse(SimpleXMLDocHandler doc, SimpleXMLDocHandlerComment comment, Reader r, boolean html) throws IOException {
+ BufferedReader reader;
+ if (r instanceof BufferedReader)
+ reader = (BufferedReader)r;
+ else
+ reader = new BufferedReader(r);
+ Stack st = new Stack();
+ int depth = 0;
+ int mode = PRE;
+ int c = 0;
+ int quotec = '"';
+ depth = 0;
+ StringBuffer sb = new StringBuffer();
+ StringBuffer etag = new StringBuffer();
+ String tagName = null;
+ String lvalue = null;
+ String rvalue = null;
+ HashMap attrs = null;
+ st = new Stack();
+ doc.startDocument();
+ int line=1, col=0;
+ boolean eol = false;
+ if (html)
+ mode = TEXT;
+ int pushBack = -1;
+ while(true) {
+ if (pushBack != -1) {
+ c = pushBack;
+ pushBack = -1;
+ }
+ else
+ c = reader.read();
+ if (c == -1)
+ break;
+
+ // We need to map \r, \r\n, and \n to \n
+ // See XML spec section 2.11
+ if(c == '\n' && eol) {
+ eol = false;
+ continue;
+ } else if(eol) {
+ eol = false;
+ } else if(c == '\n') {
+ line++;
+ col=0;
+ } else if(c == '\r') {
+ eol = true;
+ c = '\n';
+ line++;
+ col=0;
+ } else {
+ col++;
+ }
+
+ if(mode == DONE) {
+ doc.endDocument();
+ return;
+
+ // We are between tags collecting text.
+ } else if(mode == TEXT) {
+ if(c == '<') {
+ st.push(new Integer(mode));
+ mode = START_TAG;
+ if(sb.length() > 0) {
+ doc.text(sb.toString());
+ sb.setLength(0);
+ }
+ } else if(c == '&') {
+ st.push(new Integer(mode));
+ mode = ENTITY;
+ etag.setLength(0);
+ } else
+ sb.append((char)c);
+
+ // we are processing a closing tag: e.g.
+ } else if(mode == CLOSE_TAG) {
+ if(c == '>') {
+ mode = popMode(st);
+ tagName = sb.toString();
+ if (html)
+ tagName = tagName.toLowerCase();
+ sb.setLength(0);
+ depth--;
+ if(!html && depth==0)
+ mode = DONE;
+ doc.endElement(tagName);
+ } else {
+ if (!Character.isWhitespace((char)c))
+ sb.append((char)c);
+ }
+
+ // we are processing CDATA
+ } else if(mode == CDATA) {
+ if(c == '>'
+ && sb.toString().endsWith("]]")) {
+ sb.setLength(sb.length()-2);
+ doc.text(sb.toString());
+ sb.setLength(0);
+ mode = popMode(st);
+ } else
+ sb.append((char)c);
+
+ // we are processing a comment. We are inside
+ // the looking for the -->.
+ } else if(mode == COMMENT) {
+ if(c == '>'
+ && sb.toString().endsWith("--")) {
+ if (comment != null) {
+ sb.setLength(sb.length() - 2);
+ comment.comment(sb.toString());
+ }
+ sb.setLength(0);
+ mode = popMode(st);
+ } else
+ sb.append((char)c);
+
+ // We are outside the root tag element
+ } else if(mode == PRE) {
+ if(c == '<') {
+ mode = TEXT;
+ st.push(new Integer(mode));
+ mode = START_TAG;
+ }
+
+ // We are inside one of these ... ?>
+ // or one of these
+ } else if(mode == DOCTYPE) {
+ if(c == '>') {
+ mode = popMode(st);
+ if(mode == TEXT) mode = PRE;
+ }
+
+ // we have just seen a < and
+ // are wondering what we are looking at
+ // , , , etc.
+ } else if(mode == START_TAG) {
+ mode = popMode(st);
+ if(c == '/') {
+ st.push(new Integer(mode));
+ mode = CLOSE_TAG;
+ } else if (c == '?') {
+ mode = DOCTYPE;
+ } else {
+ st.push(new Integer(mode));
+ mode = OPEN_TAG;
+ tagName = null;
+ attrs = new HashMap();
+ sb.append((char)c);
+ }
+
+ // we are processing an entity, e.g. <, », etc.
+ } else if(mode == ENTITY) {
+ if(c == ';') {
+ mode = popMode(st);
+ String cent = etag.toString();
+ etag.setLength(0);
+ if(cent.startsWith("#x")) {
+ try {
+ char ci = (char)Integer.parseInt(cent.substring(2),16);
+ sb.append(ci);
+ }
+ catch (Exception es) {
+ sb.append('&').append(cent).append(';');
+ }
+ }
+ else if(cent.startsWith("#")) {
+ try {
+ char ci = (char)Integer.parseInt(cent.substring(1));
+ sb.append(ci);
+ }
+ catch (Exception es) {
+ sb.append('&').append(cent).append(';');
+ }
+ }
+ else {
+ char ce = decodeEntity(cent);
+ if (ce == '\0')
+ sb.append('&').append(cent).append(';');
+ else
+ sb.append(ce);
+ }
+ } else if ((c != '#' && (c < '0' || c > '9') && (c < 'a' || c > 'z')
+ && (c < 'A' || c > 'Z')) || etag.length() >= 7) {
+ mode = popMode(st);
+ pushBack = c;
+ sb.append('&').append(etag.toString());
+ etag.setLength(0);
+ }
+ else {
+ etag.append((char)c);
+ }
+
+ // we have just seen something like this:
+ // .
+ } else if(mode == SINGLE_TAG) {
+ if(tagName == null)
+ tagName = sb.toString();
+ if (html)
+ tagName = tagName.toLowerCase();
+ if(c != '>')
+ exc("Expected > for tag: <"+tagName+"/>",line,col);
+ doc.startElement(tagName,attrs);
+ doc.endElement(tagName);
+ if(!html && depth==0) {
+ doc.endDocument();
+ return;
+ }
+ sb.setLength(0);
+ attrs = new HashMap();
+ tagName = null;
+ mode = popMode(st);
+
+ // we are processing something
+ // like this . It could
+ // still be a or something.
+ } else if(mode == OPEN_TAG) {
+ if(c == '>') {
+ if(tagName == null)
+ tagName = sb.toString();
+ if (html)
+ tagName = tagName.toLowerCase();
+ sb.setLength(0);
+ depth++;
+ doc.startElement(tagName,attrs);
+ tagName = null;
+ attrs = new HashMap();
+ mode = popMode(st);
+ } else if(c == '/') {
+ mode = SINGLE_TAG;
+ } else if(c == '-' && sb.toString().equals("!-")) {
+ mode = COMMENT;
+ sb.setLength(0);
+ } else if(c == '[' && sb.toString().equals("![CDATA")) {
+ mode = CDATA;
+ sb.setLength(0);
+ } else if(c == 'E' && sb.toString().equals("!DOCTYP")) {
+ sb.setLength(0);
+ mode = DOCTYPE;
+ } else if(Character.isWhitespace((char)c)) {
+ tagName = sb.toString();
+ if (html)
+ tagName = tagName.toLowerCase();
+ sb.setLength(0);
+ mode = IN_TAG;
+ } else {
+ sb.append((char)c);
+ }
+
+ // We are processing the quoted right-hand side
+ // of an element's attribute.
+ } else if(mode == QUOTE) {
+ if (html && quotec == ' ' && c == '>') {
+ rvalue = sb.toString();
+ sb.setLength(0);
+ attrs.put(lvalue,rvalue);
+ mode = popMode(st);
+ doc.startElement(tagName,attrs);
+ depth++;
+ tagName = null;
+ attrs = new HashMap();
+ }
+ else if (html && quotec == ' ' && Character.isWhitespace((char)c)) {
+ rvalue = sb.toString();
+ sb.setLength(0);
+ attrs.put(lvalue,rvalue);
+ mode = IN_TAG;
+ }
+ else if (html && quotec == ' ') {
+ sb.append((char)c);
+ }
+ else if(c == quotec) {
+ rvalue = sb.toString();
+ sb.setLength(0);
+ attrs.put(lvalue,rvalue);
+ mode = IN_TAG;
+ // See section the XML spec, section 3.3.3
+ // on normalization processing.
+ } else if(" \r\n\u0009".indexOf(c)>=0) {
+ sb.append(' ');
+ } else if(c == '&') {
+ st.push(new Integer(mode));
+ mode = ENTITY;
+ etag.setLength(0);
+ } else {
+ sb.append((char)c);
+ }
+
+ } else if(mode == ATTRIBUTE_RVALUE) {
+ if(c == '"' || c == '\'') {
+ quotec = c;
+ mode = QUOTE;
+ } else if(Character.isWhitespace((char)c)) {
+ ;
+ } else if (html && c == '>') {
+ attrs.put(lvalue,sb.toString());
+ sb.setLength(0);
+ mode = popMode(st);
+ doc.startElement(tagName,attrs);
+ depth++;
+ tagName = null;
+ attrs = new HashMap();
+ } else if (html) {
+ sb.append((char)c);
+ quotec = ' ';
+ mode = QUOTE;
+ } else {
+ exc("Error in attribute processing",line,col);
+ }
+
+ } else if(mode == ATTRIBUTE_LVALUE) {
+ if(Character.isWhitespace((char)c)) {
+ lvalue = sb.toString();
+ if (html)
+ lvalue = lvalue.toLowerCase();
+ sb.setLength(0);
+ mode = ATTRIBUTE_EQUAL;
+ } else if(c == '=') {
+ lvalue = sb.toString();
+ if (html)
+ lvalue = lvalue.toLowerCase();
+ sb.setLength(0);
+ mode = ATTRIBUTE_RVALUE;
+ } else if (html && c == '>') {
+ sb.setLength(0);
+ mode = popMode(st);
+ doc.startElement(tagName,attrs);
+ depth++;
+ tagName = null;
+ attrs = new HashMap();
+ } else {
+ sb.append((char)c);
+ }
+
+ } else if(mode == ATTRIBUTE_EQUAL) {
+ if(c == '=') {
+ mode = ATTRIBUTE_RVALUE;
+ } else if(Character.isWhitespace((char)c)) {
+ ;
+ } else if (html && c == '>') {
+ sb.setLength(0);
+ mode = popMode(st);
+ doc.startElement(tagName,attrs);
+ depth++;
+ tagName = null;
+ attrs = new HashMap();
+ } else if (html && c == '/') {
+ sb.setLength(0);
+ mode = SINGLE_TAG;
+ } else if (html) {
+ sb.setLength(0);
+ sb.append((char)c);
+ mode = ATTRIBUTE_LVALUE;
+ } else {
+ exc("Error in attribute processing.",line,col);
+ }
+
+ } else if(mode == IN_TAG) {
+ if(c == '>') {
+ mode = popMode(st);
+ doc.startElement(tagName,attrs);
+ depth++;
+ tagName = null;
+ attrs = new HashMap();
+ } else if(c == '/') {
+ mode = SINGLE_TAG;
+ } else if(Character.isWhitespace((char)c)) {
+ ;
+ } else {
+ mode = ATTRIBUTE_LVALUE;
+ sb.append((char)c);
+ }
+ }
+ }
+ if(html || mode == DONE) {
+ if (html && mode == TEXT)
+ doc.text(sb.toString());
+ doc.endDocument();
+ }
+ else
+ exc("missing end tag",line,col);
+ }
+ private static void exc(String s,int line,int col) throws IOException {
+ throw new IOException(s+" near line "+line+", column "+col);
+ }
+
+ /**
+ * Escapes a string with the appropriated XML codes.
+ * @param s the string to be escaped
+ * @param onlyASCII codes above 127 will always be escaped with &#nn; if true
+ * @return the escaped string
+ */
+ public static String escapeXML(String s, boolean onlyASCII) {
+ char cc[] = s.toCharArray();
+ int len = cc.length;
+ StringBuffer sb = new StringBuffer();
+ for (int k = 0; k < len; ++k) {
+ int c = cc[k];
+ switch (c) {
+ case '<':
+ sb.append("<");
+ break;
+ case '>':
+ sb.append(">");
+ break;
+ case '&':
+ sb.append("&");
+ break;
+ case '"':
+ sb.append(""");
+ break;
+ case '\'':
+ sb.append("'");
+ break;
+ default:
+ if (onlyASCII && c > 127)
+ sb.append("").append(c).append(";");
+ else
+ sb.append((char)c);
+ }
+ }
+ return sb.toString();
+ }
+
+ public static char decodeEntity(String s) {
+ Character c = (Character)entityMap.get(s);
+ if (c == null)
+ return '\0';
+ else
+ return c.charValue();
+ }
+
+ private static String getEncodingName(byte[] b4) {
+
+ // UTF-16, with BOM
+ int b0 = b4[0] & 0xFF;
+ int b1 = b4[1] & 0xFF;
+ if (b0 == 0xFE && b1 == 0xFF) {
+ // UTF-16, big-endian
+ return "UTF-16BE";
+ }
+ if (b0 == 0xFF && b1 == 0xFE) {
+ // UTF-16, little-endian
+ return "UTF-16LE";
+ }
+
+ // UTF-8 with a BOM
+ int b2 = b4[2] & 0xFF;
+ if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
+ return "UTF-8";
+ }
+
+ // other encodings
+ int b3 = b4[3] & 0xFF;
+ if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
+ // UCS-4, big endian (1234)
+ return "ISO-10646-UCS-4";
+ }
+ if (b0 == 0x3C && b1 == 0x00 && b2 == 0x00 && b3 == 0x00) {
+ // UCS-4, little endian (4321)
+ return "ISO-10646-UCS-4";
+ }
+ if (b0 == 0x00 && b1 == 0x00 && b2 == 0x3C && b3 == 0x00) {
+ // UCS-4, unusual octet order (2143)
+ // REVISIT: What should this be?
+ return "ISO-10646-UCS-4";
+ }
+ if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x00) {
+ // UCS-4, unusual octect order (3412)
+ // REVISIT: What should this be?
+ return "ISO-10646-UCS-4";
+ }
+ if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
+ // UTF-16, big-endian, no BOM
+ // (or could turn out to be UCS-2...
+ // REVISIT: What should this be?
+ return "UTF-16BE";
+ }
+ if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
+ // UTF-16, little-endian, no BOM
+ // (or could turn out to be UCS-2...
+ return "UTF-16LE";
+ }
+ if (b0 == 0x4C && b1 == 0x6F && b2 == 0xA7 && b3 == 0x94) {
+ // EBCDIC
+ // a la xerces1, return CP037 instead of EBCDIC here
+ return "CP037";
+ }
+
+ // default encoding
+ return "UTF-8";
+ }
+
+ static {
+ // add IANA to Java encoding mappings.
+ fIANA2JavaMap.put("BIG5", "Big5");
+ fIANA2JavaMap.put("CSBIG5", "Big5");
+ fIANA2JavaMap.put("CP037", "CP037");
+ fIANA2JavaMap.put("IBM037", "CP037");
+ fIANA2JavaMap.put("CSIBM037", "CP037");
+ fIANA2JavaMap.put("EBCDIC-CP-US", "CP037");
+ fIANA2JavaMap.put("EBCDIC-CP-CA", "CP037");
+ fIANA2JavaMap.put("EBCDIC-CP-NL", "CP037");
+ fIANA2JavaMap.put("EBCDIC-CP-WT", "CP037");
+ fIANA2JavaMap.put("IBM277", "CP277");
+ fIANA2JavaMap.put("CP277", "CP277");
+ fIANA2JavaMap.put("CSIBM277", "CP277");
+ fIANA2JavaMap.put("EBCDIC-CP-DK", "CP277");
+ fIANA2JavaMap.put("EBCDIC-CP-NO", "CP277");
+ fIANA2JavaMap.put("IBM278", "CP278");
+ fIANA2JavaMap.put("CP278", "CP278");
+ fIANA2JavaMap.put("CSIBM278", "CP278");
+ fIANA2JavaMap.put("EBCDIC-CP-FI", "CP278");
+ fIANA2JavaMap.put("EBCDIC-CP-SE", "CP278");
+ fIANA2JavaMap.put("IBM280", "CP280");
+ fIANA2JavaMap.put("CP280", "CP280");
+ fIANA2JavaMap.put("CSIBM280", "CP280");
+ fIANA2JavaMap.put("EBCDIC-CP-IT", "CP280");
+ fIANA2JavaMap.put("IBM284", "CP284");
+ fIANA2JavaMap.put("CP284", "CP284");
+ fIANA2JavaMap.put("CSIBM284", "CP284");
+ fIANA2JavaMap.put("EBCDIC-CP-ES", "CP284");
+ fIANA2JavaMap.put("EBCDIC-CP-GB", "CP285");
+ fIANA2JavaMap.put("IBM285", "CP285");
+ fIANA2JavaMap.put("CP285", "CP285");
+ fIANA2JavaMap.put("CSIBM285", "CP285");
+ fIANA2JavaMap.put("EBCDIC-CP-FR", "CP297");
+ fIANA2JavaMap.put("IBM297", "CP297");
+ fIANA2JavaMap.put("CP297", "CP297");
+ fIANA2JavaMap.put("CSIBM297", "CP297");
+ fIANA2JavaMap.put("EBCDIC-CP-AR1", "CP420");
+ fIANA2JavaMap.put("IBM420", "CP420");
+ fIANA2JavaMap.put("CP420", "CP420");
+ fIANA2JavaMap.put("CSIBM420", "CP420");
+ fIANA2JavaMap.put("EBCDIC-CP-HE", "CP424");
+ fIANA2JavaMap.put("IBM424", "CP424");
+ fIANA2JavaMap.put("CP424", "CP424");
+ fIANA2JavaMap.put("CSIBM424", "CP424");
+ fIANA2JavaMap.put("EBCDIC-CP-CH", "CP500");
+ fIANA2JavaMap.put("IBM500", "CP500");
+ fIANA2JavaMap.put("CP500", "CP500");
+ fIANA2JavaMap.put("CSIBM500", "CP500");
+ fIANA2JavaMap.put("EBCDIC-CP-CH", "CP500");
+ fIANA2JavaMap.put("EBCDIC-CP-BE", "CP500");
+ fIANA2JavaMap.put("IBM868", "CP868");
+ fIANA2JavaMap.put("CP868", "CP868");
+ fIANA2JavaMap.put("CSIBM868", "CP868");
+ fIANA2JavaMap.put("CP-AR", "CP868");
+ fIANA2JavaMap.put("IBM869", "CP869");
+ fIANA2JavaMap.put("CP869", "CP869");
+ fIANA2JavaMap.put("CSIBM869", "CP869");
+ fIANA2JavaMap.put("CP-GR", "CP869");
+ fIANA2JavaMap.put("IBM870", "CP870");
+ fIANA2JavaMap.put("CP870", "CP870");
+ fIANA2JavaMap.put("CSIBM870", "CP870");
+ fIANA2JavaMap.put("EBCDIC-CP-ROECE", "CP870");
+ fIANA2JavaMap.put("EBCDIC-CP-YU", "CP870");
+ fIANA2JavaMap.put("IBM871", "CP871");
+ fIANA2JavaMap.put("CP871", "CP871");
+ fIANA2JavaMap.put("CSIBM871", "CP871");
+ fIANA2JavaMap.put("EBCDIC-CP-IS", "CP871");
+ fIANA2JavaMap.put("IBM918", "CP918");
+ fIANA2JavaMap.put("CP918", "CP918");
+ fIANA2JavaMap.put("CSIBM918", "CP918");
+ fIANA2JavaMap.put("EBCDIC-CP-AR2", "CP918");
+ fIANA2JavaMap.put("EUC-JP", "EUCJIS");
+ fIANA2JavaMap.put("CSEUCPkdFmtJapanese", "EUCJIS");
+ fIANA2JavaMap.put("EUC-KR", "KSC5601");
+ fIANA2JavaMap.put("GB2312", "GB2312");
+ fIANA2JavaMap.put("CSGB2312", "GB2312");
+ fIANA2JavaMap.put("ISO-2022-JP", "JIS");
+ fIANA2JavaMap.put("CSISO2022JP", "JIS");
+ fIANA2JavaMap.put("ISO-2022-KR", "ISO2022KR");
+ fIANA2JavaMap.put("CSISO2022KR", "ISO2022KR");
+ fIANA2JavaMap.put("ISO-2022-CN", "ISO2022CN");
+
+ fIANA2JavaMap.put("X0201", "JIS0201");
+ fIANA2JavaMap.put("CSISO13JISC6220JP", "JIS0201");
+ fIANA2JavaMap.put("X0208", "JIS0208");
+ fIANA2JavaMap.put("ISO-IR-87", "JIS0208");
+ fIANA2JavaMap.put("X0208dbiJIS_X0208-1983", "JIS0208");
+ fIANA2JavaMap.put("CSISO87JISX0208", "JIS0208");
+ fIANA2JavaMap.put("X0212", "JIS0212");
+ fIANA2JavaMap.put("ISO-IR-159", "JIS0212");
+ fIANA2JavaMap.put("CSISO159JISX02121990", "JIS0212");
+ fIANA2JavaMap.put("SHIFT_JIS", "SJIS");
+ fIANA2JavaMap.put("CSSHIFT_JIS", "SJIS");
+ fIANA2JavaMap.put("MS_Kanji", "SJIS");
+
+ // Add support for Cp1252 and its friends
+ fIANA2JavaMap.put("WINDOWS-1250", "Cp1250");
+ fIANA2JavaMap.put("WINDOWS-1251", "Cp1251");
+ fIANA2JavaMap.put("WINDOWS-1252", "Cp1252");
+ fIANA2JavaMap.put("WINDOWS-1253", "Cp1253");
+ fIANA2JavaMap.put("WINDOWS-1254", "Cp1254");
+ fIANA2JavaMap.put("WINDOWS-1255", "Cp1255");
+ fIANA2JavaMap.put("WINDOWS-1256", "Cp1256");
+ fIANA2JavaMap.put("WINDOWS-1257", "Cp1257");
+ fIANA2JavaMap.put("WINDOWS-1258", "Cp1258");
+ fIANA2JavaMap.put("TIS-620", "TIS620");
+
+ fIANA2JavaMap.put("ISO-8859-1", "ISO8859_1");
+ fIANA2JavaMap.put("ISO-IR-100", "ISO8859_1");
+ fIANA2JavaMap.put("ISO_8859-1", "ISO8859_1");
+ fIANA2JavaMap.put("LATIN1", "ISO8859_1");
+ fIANA2JavaMap.put("CSISOLATIN1", "ISO8859_1");
+ fIANA2JavaMap.put("L1", "ISO8859_1");
+ fIANA2JavaMap.put("IBM819", "ISO8859_1");
+ fIANA2JavaMap.put("CP819", "ISO8859_1");
+
+ fIANA2JavaMap.put("ISO-8859-2", "ISO8859_2");
+ fIANA2JavaMap.put("ISO-IR-101", "ISO8859_2");
+ fIANA2JavaMap.put("ISO_8859-2", "ISO8859_2");
+ fIANA2JavaMap.put("LATIN2", "ISO8859_2");
+ fIANA2JavaMap.put("CSISOLATIN2", "ISO8859_2");
+ fIANA2JavaMap.put("L2", "ISO8859_2");
+
+ fIANA2JavaMap.put("ISO-8859-3", "ISO8859_3");
+ fIANA2JavaMap.put("ISO-IR-109", "ISO8859_3");
+ fIANA2JavaMap.put("ISO_8859-3", "ISO8859_3");
+ fIANA2JavaMap.put("LATIN3", "ISO8859_3");
+ fIANA2JavaMap.put("CSISOLATIN3", "ISO8859_3");
+ fIANA2JavaMap.put("L3", "ISO8859_3");
+
+ fIANA2JavaMap.put("ISO-8859-4", "ISO8859_4");
+ fIANA2JavaMap.put("ISO-IR-110", "ISO8859_4");
+ fIANA2JavaMap.put("ISO_8859-4", "ISO8859_4");
+ fIANA2JavaMap.put("LATIN4", "ISO8859_4");
+ fIANA2JavaMap.put("CSISOLATIN4", "ISO8859_4");
+ fIANA2JavaMap.put("L4", "ISO8859_4");
+
+ fIANA2JavaMap.put("ISO-8859-5", "ISO8859_5");
+ fIANA2JavaMap.put("ISO-IR-144", "ISO8859_5");
+ fIANA2JavaMap.put("ISO_8859-5", "ISO8859_5");
+ fIANA2JavaMap.put("CYRILLIC", "ISO8859_5");
+ fIANA2JavaMap.put("CSISOLATINCYRILLIC", "ISO8859_5");
+
+ fIANA2JavaMap.put("ISO-8859-6", "ISO8859_6");
+ fIANA2JavaMap.put("ISO-IR-127", "ISO8859_6");
+ fIANA2JavaMap.put("ISO_8859-6", "ISO8859_6");
+ fIANA2JavaMap.put("ECMA-114", "ISO8859_6");
+ fIANA2JavaMap.put("ASMO-708", "ISO8859_6");
+ fIANA2JavaMap.put("ARABIC", "ISO8859_6");
+ fIANA2JavaMap.put("CSISOLATINARABIC", "ISO8859_6");
+
+ fIANA2JavaMap.put("ISO-8859-7", "ISO8859_7");
+ fIANA2JavaMap.put("ISO-IR-126", "ISO8859_7");
+ fIANA2JavaMap.put("ISO_8859-7", "ISO8859_7");
+ fIANA2JavaMap.put("ELOT_928", "ISO8859_7");
+ fIANA2JavaMap.put("ECMA-118", "ISO8859_7");
+ fIANA2JavaMap.put("GREEK", "ISO8859_7");
+ fIANA2JavaMap.put("CSISOLATINGREEK", "ISO8859_7");
+ fIANA2JavaMap.put("GREEK8", "ISO8859_7");
+
+ fIANA2JavaMap.put("ISO-8859-8", "ISO8859_8");
+ fIANA2JavaMap.put("ISO-8859-8-I", "ISO8859_8"); // added since this encoding only differs w.r.t. presentation
+ fIANA2JavaMap.put("ISO-IR-138", "ISO8859_8");
+ fIANA2JavaMap.put("ISO_8859-8", "ISO8859_8");
+ fIANA2JavaMap.put("HEBREW", "ISO8859_8");
+ fIANA2JavaMap.put("CSISOLATINHEBREW", "ISO8859_8");
+
+ fIANA2JavaMap.put("ISO-8859-9", "ISO8859_9");
+ fIANA2JavaMap.put("ISO-IR-148", "ISO8859_9");
+ fIANA2JavaMap.put("ISO_8859-9", "ISO8859_9");
+ fIANA2JavaMap.put("LATIN5", "ISO8859_9");
+ fIANA2JavaMap.put("CSISOLATIN5", "ISO8859_9");
+ fIANA2JavaMap.put("L5", "ISO8859_9");
+
+ fIANA2JavaMap.put("KOI8-R", "KOI8_R");
+ fIANA2JavaMap.put("CSKOI8-R", "KOI8_R");
+ fIANA2JavaMap.put("US-ASCII", "ASCII");
+ fIANA2JavaMap.put("ISO-IR-6", "ASCII");
+ fIANA2JavaMap.put("ANSI_X3.4-1986", "ASCII");
+ fIANA2JavaMap.put("ISO_646.IRV:1991", "ASCII");
+ fIANA2JavaMap.put("ASCII", "ASCII");
+ fIANA2JavaMap.put("CSASCII", "ASCII");
+ fIANA2JavaMap.put("ISO646-US", "ASCII");
+ fIANA2JavaMap.put("US", "ASCII");
+ fIANA2JavaMap.put("IBM367", "ASCII");
+ fIANA2JavaMap.put("CP367", "ASCII");
+ fIANA2JavaMap.put("UTF-8", "UTF8");
+ fIANA2JavaMap.put("UTF-16", "Unicode");
+ fIANA2JavaMap.put("UTF-16BE", "UnicodeBig");
+ fIANA2JavaMap.put("UTF-16LE", "UnicodeLittle");
+
+ entityMap.put("nbsp", new Character('\u00a0')); // no-break space = non-breaking space, U+00A0 ISOnum
+ entityMap.put("iexcl", new Character('\u00a1')); // inverted exclamation mark, U+00A1 ISOnum
+ entityMap.put("cent", new Character('\u00a2')); // cent sign, U+00A2 ISOnum
+ entityMap.put("pound", new Character('\u00a3')); // pound sign, U+00A3 ISOnum
+ entityMap.put("curren", new Character('\u00a4')); // currency sign, U+00A4 ISOnum
+ entityMap.put("yen", new Character('\u00a5')); // yen sign = yuan sign, U+00A5 ISOnum
+ entityMap.put("brvbar", new Character('\u00a6')); // broken bar = broken vertical bar, U+00A6 ISOnum
+ entityMap.put("sect", new Character('\u00a7')); // section sign, U+00A7 ISOnum
+ entityMap.put("uml", new Character('\u00a8')); // diaeresis = spacing diaeresis, U+00A8 ISOdia
+ entityMap.put("copy", new Character('\u00a9')); // copyright sign, U+00A9 ISOnum
+ entityMap.put("ordf", new Character('\u00aa')); // feminine ordinal indicator, U+00AA ISOnum
+ entityMap.put("laquo", new Character('\u00ab')); // left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum
+ entityMap.put("not", new Character('\u00ac')); // not sign, U+00AC ISOnum
+ entityMap.put("shy", new Character('\u00ad')); // soft hyphen = discretionary hyphen, U+00AD ISOnum
+ entityMap.put("reg", new Character('\u00ae')); // registered sign = registered trade mark sign, U+00AE ISOnum
+ entityMap.put("macr", new Character('\u00af')); // macron = spacing macron = overline = APL overbar, U+00AF ISOdia
+ entityMap.put("deg", new Character('\u00b0')); // degree sign, U+00B0 ISOnum
+ entityMap.put("plusmn", new Character('\u00b1')); // plus-minus sign = plus-or-minus sign, U+00B1 ISOnum
+ entityMap.put("sup2", new Character('\u00b2')); // superscript two = superscript digit two = squared, U+00B2 ISOnum
+ entityMap.put("sup3", new Character('\u00b3')); // superscript three = superscript digit three = cubed, U+00B3 ISOnum
+ entityMap.put("acute", new Character('\u00b4')); // acute accent = spacing acute, U+00B4 ISOdia
+ entityMap.put("micro", new Character('\u00b5')); // micro sign, U+00B5 ISOnum
+ entityMap.put("para", new Character('\u00b6')); // pilcrow sign = paragraph sign, U+00B6 ISOnum
+ entityMap.put("middot", new Character('\u00b7')); // middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum
+ entityMap.put("cedil", new Character('\u00b8')); // cedilla = spacing cedilla, U+00B8 ISOdia
+ entityMap.put("sup1", new Character('\u00b9')); // superscript one = superscript digit one, U+00B9 ISOnum
+ entityMap.put("ordm", new Character('\u00ba')); // masculine ordinal indicator, U+00BA ISOnum
+ entityMap.put("raquo", new Character('\u00bb')); // right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum
+ entityMap.put("frac14", new Character('\u00bc')); // vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum
+ entityMap.put("frac12", new Character('\u00bd')); // vulgar fraction one half = fraction one half, U+00BD ISOnum
+ entityMap.put("frac34", new Character('\u00be')); // vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum
+ entityMap.put("iquest", new Character('\u00bf')); // inverted question mark = turned question mark, U+00BF ISOnum
+ entityMap.put("Agrave", new Character('\u00c0')); // latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1
+ entityMap.put("Aacute", new Character('\u00c1')); // latin capital letter A with acute, U+00C1 ISOlat1
+ entityMap.put("Acirc", new Character('\u00c2')); // latin capital letter A with circumflex, U+00C2 ISOlat1
+ entityMap.put("Atilde", new Character('\u00c3')); // latin capital letter A with tilde, U+00C3 ISOlat1
+ entityMap.put("Auml", new Character('\u00c4')); // latin capital letter A with diaeresis, U+00C4 ISOlat1
+ entityMap.put("Aring", new Character('\u00c5')); // latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1
+ entityMap.put("AElig", new Character('\u00c6')); // latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1
+ entityMap.put("Ccedil", new Character('\u00c7')); // latin capital letter C with cedilla, U+00C7 ISOlat1
+ entityMap.put("Egrave", new Character('\u00c8')); // latin capital letter E with grave, U+00C8 ISOlat1
+ entityMap.put("Eacute", new Character('\u00c9')); // latin capital letter E with acute, U+00C9 ISOlat1
+ entityMap.put("Ecirc", new Character('\u00ca')); // latin capital letter E with circumflex, U+00CA ISOlat1
+ entityMap.put("Euml", new Character('\u00cb')); // latin capital letter E with diaeresis, U+00CB ISOlat1
+ entityMap.put("Igrave", new Character('\u00cc')); // latin capital letter I with grave, U+00CC ISOlat1
+ entityMap.put("Iacute", new Character('\u00cd')); // latin capital letter I with acute, U+00CD ISOlat1
+ entityMap.put("Icirc", new Character('\u00ce')); // latin capital letter I with circumflex, U+00CE ISOlat1
+ entityMap.put("Iuml", new Character('\u00cf')); // latin capital letter I with diaeresis, U+00CF ISOlat1
+ entityMap.put("ETH", new Character('\u00d0')); // latin capital letter ETH, U+00D0 ISOlat1
+ entityMap.put("Ntilde", new Character('\u00d1')); // latin capital letter N with tilde, U+00D1 ISOlat1
+ entityMap.put("Ograve", new Character('\u00d2')); // latin capital letter O with grave, U+00D2 ISOlat1
+ entityMap.put("Oacute", new Character('\u00d3')); // latin capital letter O with acute, U+00D3 ISOlat1
+ entityMap.put("Ocirc", new Character('\u00d4')); // latin capital letter O with circumflex, U+00D4 ISOlat1
+ entityMap.put("Otilde", new Character('\u00d5')); // latin capital letter O with tilde, U+00D5 ISOlat1
+ entityMap.put("Ouml", new Character('\u00d6')); // latin capital letter O with diaeresis, U+00D6 ISOlat1
+ entityMap.put("times", new Character('\u00d7')); // multiplication sign, U+00D7 ISOnum
+ entityMap.put("Oslash", new Character('\u00d8')); // latin capital letter O with stroke = latin capital letter O slash, U+00D8 ISOlat1
+ entityMap.put("Ugrave", new Character('\u00d9')); // latin capital letter U with grave, U+00D9 ISOlat1
+ entityMap.put("Uacute", new Character('\u00da')); // latin capital letter U with acute, U+00DA ISOlat1
+ entityMap.put("Ucirc", new Character('\u00db')); // latin capital letter U with circumflex, U+00DB ISOlat1
+ entityMap.put("Uuml", new Character('\u00dc')); // latin capital letter U with diaeresis, U+00DC ISOlat1
+ entityMap.put("Yacute", new Character('\u00dd')); // latin capital letter Y with acute, U+00DD ISOlat1
+ entityMap.put("THORN", new Character('\u00de')); // latin capital letter THORN, U+00DE ISOlat1
+ entityMap.put("szlig", new Character('\u00df')); // latin small letter sharp s = ess-zed, U+00DF ISOlat1
+ entityMap.put("agrave", new Character('\u00e0')); // latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1
+ entityMap.put("aacute", new Character('\u00e1')); // latin small letter a with acute, U+00E1 ISOlat1
+ entityMap.put("acirc", new Character('\u00e2')); // latin small letter a with circumflex, U+00E2 ISOlat1
+ entityMap.put("atilde", new Character('\u00e3')); // latin small letter a with tilde, U+00E3 ISOlat1
+ entityMap.put("auml", new Character('\u00e4')); // latin small letter a with diaeresis, U+00E4 ISOlat1
+ entityMap.put("aring", new Character('\u00e5')); // latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1
+ entityMap.put("aelig", new Character('\u00e6')); // latin small letter ae = latin small ligature ae, U+00E6 ISOlat1
+ entityMap.put("ccedil", new Character('\u00e7')); // latin small letter c with cedilla, U+00E7 ISOlat1
+ entityMap.put("egrave", new Character('\u00e8')); // latin small letter e with grave, U+00E8 ISOlat1
+ entityMap.put("eacute", new Character('\u00e9')); // latin small letter e with acute, U+00E9 ISOlat1
+ entityMap.put("ecirc", new Character('\u00ea')); // latin small letter e with circumflex, U+00EA ISOlat1
+ entityMap.put("euml", new Character('\u00eb')); // latin small letter e with diaeresis, U+00EB ISOlat1
+ entityMap.put("igrave", new Character('\u00ec')); // latin small letter i with grave, U+00EC ISOlat1
+ entityMap.put("iacute", new Character('\u00ed')); // latin small letter i with acute, U+00ED ISOlat1
+ entityMap.put("icirc", new Character('\u00ee')); // latin small letter i with circumflex, U+00EE ISOlat1
+ entityMap.put("iuml", new Character('\u00ef')); // latin small letter i with diaeresis, U+00EF ISOlat1
+ entityMap.put("eth", new Character('\u00f0')); // latin small letter eth, U+00F0 ISOlat1
+ entityMap.put("ntilde", new Character('\u00f1')); // latin small letter n with tilde, U+00F1 ISOlat1
+ entityMap.put("ograve", new Character('\u00f2')); // latin small letter o with grave, U+00F2 ISOlat1
+ entityMap.put("oacute", new Character('\u00f3')); // latin small letter o with acute, U+00F3 ISOlat1
+ entityMap.put("ocirc", new Character('\u00f4')); // latin small letter o with circumflex, U+00F4 ISOlat1
+ entityMap.put("otilde", new Character('\u00f5')); // latin small letter o with tilde, U+00F5 ISOlat1
+ entityMap.put("ouml", new Character('\u00f6')); // latin small letter o with diaeresis, U+00F6 ISOlat1
+ entityMap.put("divide", new Character('\u00f7')); // division sign, U+00F7 ISOnum
+ entityMap.put("oslash", new Character('\u00f8')); // latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1
+ entityMap.put("ugrave", new Character('\u00f9')); // latin small letter u with grave, U+00F9 ISOlat1
+ entityMap.put("uacute", new Character('\u00fa')); // latin small letter u with acute, U+00FA ISOlat1
+ entityMap.put("ucirc", new Character('\u00fb')); // latin small letter u with circumflex, U+00FB ISOlat1
+ entityMap.put("uuml", new Character('\u00fc')); // latin small letter u with diaeresis, U+00FC ISOlat1
+ entityMap.put("yacute", new Character('\u00fd')); // latin small letter y with acute, U+00FD ISOlat1
+ entityMap.put("thorn", new Character('\u00fe')); // latin small letter thorn, U+00FE ISOlat1
+ entityMap.put("yuml", new Character('\u00ff')); // latin small letter y with diaeresis, U+00FF ISOlat1
+ // Latin Extended-B
+ entityMap.put("fnof", new Character('\u0192')); // latin small f with hook = function = florin, U+0192 ISOtech
+ // Greek
+ entityMap.put("Alpha", new Character('\u0391')); // greek capital letter alpha, U+0391
+ entityMap.put("Beta", new Character('\u0392')); // greek capital letter beta, U+0392
+ entityMap.put("Gamma", new Character('\u0393')); // greek capital letter gamma, U+0393 ISOgrk3
+ entityMap.put("Delta", new Character('\u0394')); // greek capital letter delta, U+0394 ISOgrk3
+ entityMap.put("Epsilon", new Character('\u0395')); // greek capital letter epsilon, U+0395
+ entityMap.put("Zeta", new Character('\u0396')); // greek capital letter zeta, U+0396
+ entityMap.put("Eta", new Character('\u0397')); // greek capital letter eta, U+0397
+ entityMap.put("Theta", new Character('\u0398')); // greek capital letter theta, U+0398 ISOgrk3
+ entityMap.put("Iota", new Character('\u0399')); // greek capital letter iota, U+0399
+ entityMap.put("Kappa", new Character('\u039a')); // greek capital letter kappa, U+039A
+ entityMap.put("Lambda", new Character('\u039b')); // greek capital letter lambda, U+039B ISOgrk3
+ entityMap.put("Mu", new Character('\u039c')); // greek capital letter mu, U+039C
+ entityMap.put("Nu", new Character('\u039d')); // greek capital letter nu, U+039D
+ entityMap.put("Xi", new Character('\u039e')); // greek capital letter xi, U+039E ISOgrk3
+ entityMap.put("Omicron", new Character('\u039f')); // greek capital letter omicron, U+039F
+ entityMap.put("Pi", new Character('\u03a0')); // greek capital letter pi, U+03A0 ISOgrk3
+ entityMap.put("Rho", new Character('\u03a1')); // greek capital letter rho, U+03A1
+ // there is no Sigmaf, and no U+03A2 character either
+ entityMap.put("Sigma", new Character('\u03a3')); // greek capital letter sigma, U+03A3 ISOgrk3
+ entityMap.put("Tau", new Character('\u03a4')); // greek capital letter tau, U+03A4
+ entityMap.put("Upsilon", new Character('\u03a5')); // greek capital letter upsilon, U+03A5 ISOgrk3
+ entityMap.put("Phi", new Character('\u03a6')); // greek capital letter phi, U+03A6 ISOgrk3
+ entityMap.put("Chi", new Character('\u03a7')); // greek capital letter chi, U+03A7
+ entityMap.put("Psi", new Character('\u03a8')); // greek capital letter psi, U+03A8 ISOgrk3
+ entityMap.put("Omega", new Character('\u03a9')); // greek capital letter omega, U+03A9 ISOgrk3
+ entityMap.put("alpha", new Character('\u03b1')); // greek small letter alpha, U+03B1 ISOgrk3
+ entityMap.put("beta", new Character('\u03b2')); // greek small letter beta, U+03B2 ISOgrk3
+ entityMap.put("gamma", new Character('\u03b3')); // greek small letter gamma, U+03B3 ISOgrk3
+ entityMap.put("delta", new Character('\u03b4')); // greek small letter delta, U+03B4 ISOgrk3
+ entityMap.put("epsilon", new Character('\u03b5')); // greek small letter epsilon, U+03B5 ISOgrk3
+ entityMap.put("zeta", new Character('\u03b6')); // greek small letter zeta, U+03B6 ISOgrk3
+ entityMap.put("eta", new Character('\u03b7')); // greek small letter eta, U+03B7 ISOgrk3
+ entityMap.put("theta", new Character('\u03b8')); // greek small letter theta, U+03B8 ISOgrk3
+ entityMap.put("iota", new Character('\u03b9')); // greek small letter iota, U+03B9 ISOgrk3
+ entityMap.put("kappa", new Character('\u03ba')); // greek small letter kappa, U+03BA ISOgrk3
+ entityMap.put("lambda", new Character('\u03bb')); // greek small letter lambda, U+03BB ISOgrk3
+ entityMap.put("mu", new Character('\u03bc')); // greek small letter mu, U+03BC ISOgrk3
+ entityMap.put("nu", new Character('\u03bd')); // greek small letter nu, U+03BD ISOgrk3
+ entityMap.put("xi", new Character('\u03be')); // greek small letter xi, U+03BE ISOgrk3
+ entityMap.put("omicron", new Character('\u03bf')); // greek small letter omicron, U+03BF NEW
+ entityMap.put("pi", new Character('\u03c0')); // greek small letter pi, U+03C0 ISOgrk3
+ entityMap.put("rho", new Character('\u03c1')); // greek small letter rho, U+03C1 ISOgrk3
+ entityMap.put("sigmaf", new Character('\u03c2')); // greek small letter final sigma, U+03C2 ISOgrk3
+ entityMap.put("sigma", new Character('\u03c3')); // greek small letter sigma, U+03C3 ISOgrk3
+ entityMap.put("tau", new Character('\u03c4')); // greek small letter tau, U+03C4 ISOgrk3
+ entityMap.put("upsilon", new Character('\u03c5')); // greek small letter upsilon, U+03C5 ISOgrk3
+ entityMap.put("phi", new Character('\u03c6')); // greek small letter phi, U+03C6 ISOgrk3
+ entityMap.put("chi", new Character('\u03c7')); // greek small letter chi, U+03C7 ISOgrk3
+ entityMap.put("psi", new Character('\u03c8')); // greek small letter psi, U+03C8 ISOgrk3
+ entityMap.put("omega", new Character('\u03c9')); // greek small letter omega, U+03C9 ISOgrk3
+ entityMap.put("thetasym", new Character('\u03d1')); // greek small letter theta symbol, U+03D1 NEW
+ entityMap.put("upsih", new Character('\u03d2')); // greek upsilon with hook symbol, U+03D2 NEW
+ entityMap.put("piv", new Character('\u03d6')); // greek pi symbol, U+03D6 ISOgrk3
+ // General Punctuation
+ entityMap.put("bull", new Character('\u2022')); // bullet = black small circle, U+2022 ISOpub
+ // bullet is NOT the same as bullet operator, U+2219
+ entityMap.put("hellip", new Character('\u2026')); // horizontal ellipsis = three dot leader, U+2026 ISOpub
+ entityMap.put("prime", new Character('\u2032')); // prime = minutes = feet, U+2032 ISOtech
+ entityMap.put("Prime", new Character('\u2033')); // double prime = seconds = inches, U+2033 ISOtech
+ entityMap.put("oline", new Character('\u203e')); // overline = spacing overscore, U+203E NEW
+ entityMap.put("frasl", new Character('\u2044')); // fraction slash, U+2044 NEW
+ // Letterlike Symbols
+ entityMap.put("weierp", new Character('\u2118')); // script capital P = power set = Weierstrass p, U+2118 ISOamso
+ entityMap.put("image", new Character('\u2111')); // blackletter capital I = imaginary part, U+2111 ISOamso
+ entityMap.put("real", new Character('\u211c')); // blackletter capital R = real part symbol, U+211C ISOamso
+ entityMap.put("trade", new Character('\u2122')); // trade mark sign, U+2122 ISOnum
+ entityMap.put("alefsym", new Character('\u2135')); // alef symbol = first transfinite cardinal, U+2135 NEW
+ // alef symbol is NOT the same as hebrew letter alef,
+ // U+05D0 although the same glyph could be used to depict both characters
+ // Arrows
+ entityMap.put("larr", new Character('\u2190')); // leftwards arrow, U+2190 ISOnum
+ entityMap.put("uarr", new Character('\u2191')); // upwards arrow, U+2191 ISOnum
+ entityMap.put("rarr", new Character('\u2192')); // rightwards arrow, U+2192 ISOnum
+ entityMap.put("darr", new Character('\u2193')); // downwards arrow, U+2193 ISOnum
+ entityMap.put("harr", new Character('\u2194')); // left right arrow, U+2194 ISOamsa
+ entityMap.put("crarr", new Character('\u21b5')); // downwards arrow with corner leftwards = carriage return, U+21B5 NEW
+ entityMap.put("lArr", new Character('\u21d0')); // leftwards double arrow, U+21D0 ISOtech
+ // ISO 10646 does not say that lArr is the same as the 'is implied by' arrow
+ // but also does not have any other character for that function. So ? lArr can
+ // be used for 'is implied by' as ISOtech suggests
+ entityMap.put("uArr", new Character('\u21d1')); // upwards double arrow, U+21D1 ISOamsa
+ entityMap.put("rArr", new Character('\u21d2')); // rightwards double arrow, U+21D2 ISOtech
+ // ISO 10646 does not say this is the 'implies' character but does not have
+ // another character with this function so ?
+ // rArr can be used for 'implies' as ISOtech suggests
+ entityMap.put("dArr", new Character('\u21d3')); // downwards double arrow, U+21D3 ISOamsa
+ entityMap.put("hArr", new Character('\u21d4')); // left right double arrow, U+21D4 ISOamsa
+ // Mathematical Operators
+ entityMap.put("forall", new Character('\u2200')); // for all, U+2200 ISOtech
+ entityMap.put("part", new Character('\u2202')); // partial differential, U+2202 ISOtech
+ entityMap.put("exist", new Character('\u2203')); // there exists, U+2203 ISOtech
+ entityMap.put("empty", new Character('\u2205')); // empty set = null set = diameter, U+2205 ISOamso
+ entityMap.put("nabla", new Character('\u2207')); // nabla = backward difference, U+2207 ISOtech
+ entityMap.put("isin", new Character('\u2208')); // element of, U+2208 ISOtech
+ entityMap.put("notin", new Character('\u2209')); // not an element of, U+2209 ISOtech
+ entityMap.put("ni", new Character('\u220b')); // contains as member, U+220B ISOtech
+ // should there be a more memorable name than 'ni'?
+ entityMap.put("prod", new Character('\u220f')); // n-ary product = product sign, U+220F ISOamsb
+ // prod is NOT the same character as U+03A0 'greek capital letter pi' though
+ // the same glyph might be used for both
+ entityMap.put("sum", new Character('\u2211')); // n-ary sumation, U+2211 ISOamsb
+ // sum is NOT the same character as U+03A3 'greek capital letter sigma'
+ // though the same glyph might be used for both
+ entityMap.put("minus", new Character('\u2212')); // minus sign, U+2212 ISOtech
+ entityMap.put("lowast", new Character('\u2217')); // asterisk operator, U+2217 ISOtech
+ entityMap.put("radic", new Character('\u221a')); // square root = radical sign, U+221A ISOtech
+ entityMap.put("prop", new Character('\u221d')); // proportional to, U+221D ISOtech
+ entityMap.put("infin", new Character('\u221e')); // infinity, U+221E ISOtech
+ entityMap.put("ang", new Character('\u2220')); // angle, U+2220 ISOamso
+ entityMap.put("and", new Character('\u2227')); // logical and = wedge, U+2227 ISOtech
+ entityMap.put("or", new Character('\u2228')); // logical or = vee, U+2228 ISOtech
+ entityMap.put("cap", new Character('\u2229')); // intersection = cap, U+2229 ISOtech
+ entityMap.put("cup", new Character('\u222a')); // union = cup, U+222A ISOtech
+ entityMap.put("int", new Character('\u222b')); // integral, U+222B ISOtech
+ entityMap.put("there4", new Character('\u2234')); // therefore, U+2234 ISOtech
+ entityMap.put("sim", new Character('\u223c')); // tilde operator = varies with = similar to, U+223C ISOtech
+ // tilde operator is NOT the same character as the tilde, U+007E,
+ // although the same glyph might be used to represent both
+ entityMap.put("cong", new Character('\u2245')); // approximately equal to, U+2245 ISOtech
+ entityMap.put("asymp", new Character('\u2248')); // almost equal to = asymptotic to, U+2248 ISOamsr
+ entityMap.put("ne", new Character('\u2260')); // not equal to, U+2260 ISOtech
+ entityMap.put("equiv", new Character('\u2261')); // identical to, U+2261 ISOtech
+ entityMap.put("le", new Character('\u2264')); // less-than or equal to, U+2264 ISOtech
+ entityMap.put("ge", new Character('\u2265')); // greater-than or equal to, U+2265 ISOtech
+ entityMap.put("sub", new Character('\u2282')); // subset of, U+2282 ISOtech
+ entityMap.put("sup", new Character('\u2283')); // superset of, U+2283 ISOtech
+ // note that nsup, 'not a superset of, U+2283' is not covered by the Symbol
+ // font encoding and is not included. Should it be, for symmetry?
+ // It is in ISOamsn
+ entityMap.put("nsub", new Character('\u2284')); // not a subset of, U+2284 ISOamsn
+ entityMap.put("sube", new Character('\u2286')); // subset of or equal to, U+2286 ISOtech
+ entityMap.put("supe", new Character('\u2287')); // superset of or equal to, U+2287 ISOtech
+ entityMap.put("oplus", new Character('\u2295')); // circled plus = direct sum, U+2295 ISOamsb
+ entityMap.put("otimes", new Character('\u2297')); // circled times = vector product, U+2297 ISOamsb
+ entityMap.put("perp", new Character('\u22a5')); // up tack = orthogonal to = perpendicular, U+22A5 ISOtech
+ entityMap.put("sdot", new Character('\u22c5')); // dot operator, U+22C5 ISOamsb
+ // dot operator is NOT the same character as U+00B7 middle dot
+ // Miscellaneous Technical
+ entityMap.put("lceil", new Character('\u2308')); // left ceiling = apl upstile, U+2308 ISOamsc
+ entityMap.put("rceil", new Character('\u2309')); // right ceiling, U+2309 ISOamsc
+ entityMap.put("lfloor", new Character('\u230a')); // left floor = apl downstile, U+230A ISOamsc
+ entityMap.put("rfloor", new Character('\u230b')); // right floor, U+230B ISOamsc
+ entityMap.put("lang", new Character('\u2329')); // left-pointing angle bracket = bra, U+2329 ISOtech
+ // lang is NOT the same character as U+003C 'less than'
+ // or U+2039 'single left-pointing angle quotation mark'
+ entityMap.put("rang", new Character('\u232a')); // right-pointing angle bracket = ket, U+232A ISOtech
+ // rang is NOT the same character as U+003E 'greater than'
+ // or U+203A 'single right-pointing angle quotation mark'
+ // Geometric Shapes
+ entityMap.put("loz", new Character('\u25ca')); // lozenge, U+25CA ISOpub
+ // Miscellaneous Symbols
+ entityMap.put("spades", new Character('\u2660')); // black spade suit, U+2660 ISOpub
+ // black here seems to mean filled as opposed to hollow
+ entityMap.put("clubs", new Character('\u2663')); // black club suit = shamrock, U+2663 ISOpub
+ entityMap.put("hearts", new Character('\u2665')); // black heart suit = valentine, U+2665 ISOpub
+ entityMap.put("diams", new Character('\u2666')); // black diamond suit, U+2666 ISOpub
+ // C0 Controls and Basic Latin
+ entityMap.put("quot", new Character('\u0022')); // quotation mark = APL quote, U+0022 ISOnum
+ entityMap.put("amp", new Character('\u0026')); // ampersand, U+0026 ISOnum
+ entityMap.put("apos", new Character('\''));
+ entityMap.put("lt", new Character('\u003c')); // less-than sign, U+003C ISOnum
+ entityMap.put("gt", new Character('\u003e')); // greater-than sign, U+003E ISOnum
+ // Latin Extended-A
+ entityMap.put("OElig", new Character('\u0152')); // latin capital ligature OE, U+0152 ISOlat2
+ entityMap.put("oelig", new Character('\u0153')); // latin small ligature oe, U+0153 ISOlat2
+ // ligature is a misnomer, this is a separate character in some languages
+ entityMap.put("Scaron", new Character('\u0160')); // latin capital letter S with caron, U+0160 ISOlat2
+ entityMap.put("scaron", new Character('\u0161')); // latin small letter s with caron, U+0161 ISOlat2
+ entityMap.put("Yuml", new Character('\u0178')); // latin capital letter Y with diaeresis, U+0178 ISOlat2
+ // Spacing Modifier Letters
+ entityMap.put("circ", new Character('\u02c6')); // modifier letter circumflex accent, U+02C6 ISOpub
+ entityMap.put("tilde", new Character('\u02dc')); // small tilde, U+02DC ISOdia
+ // General Punctuation
+ entityMap.put("ensp", new Character('\u2002')); // en space, U+2002 ISOpub
+ entityMap.put("emsp", new Character('\u2003')); // em space, U+2003 ISOpub
+ entityMap.put("thinsp", new Character('\u2009')); // thin space, U+2009 ISOpub
+ entityMap.put("zwnj", new Character('\u200c')); // zero width non-joiner, U+200C NEW RFC 2070
+ entityMap.put("zwj", new Character('\u200d')); // zero width joiner, U+200D NEW RFC 2070
+ entityMap.put("lrm", new Character('\u200e')); // left-to-right mark, U+200E NEW RFC 2070
+ entityMap.put("rlm", new Character('\u200f')); // right-to-left mark, U+200F NEW RFC 2070
+ entityMap.put("ndash", new Character('\u2013')); // en dash, U+2013 ISOpub
+ entityMap.put("mdash", new Character('\u2014')); // em dash, U+2014 ISOpub
+ entityMap.put("lsquo", new Character('\u2018')); // left single quotation mark, U+2018 ISOnum
+ entityMap.put("rsquo", new Character('\u2019')); // right single quotation mark, U+2019 ISOnum
+ entityMap.put("sbquo", new Character('\u201a')); // single low-9 quotation mark, U+201A NEW
+ entityMap.put("ldquo", new Character('\u201c')); // left double quotation mark, U+201C ISOnum
+ entityMap.put("rdquo", new Character('\u201d')); // right double quotation mark, U+201D ISOnum
+ entityMap.put("bdquo", new Character('\u201e')); // double low-9 quotation mark, U+201E NEW
+ entityMap.put("dagger", new Character('\u2020')); // dagger, U+2020 ISOpub
+ entityMap.put("Dagger", new Character('\u2021')); // double dagger, U+2021 ISOpub
+ entityMap.put("permil", new Character('\u2030')); // per mille sign, U+2030 ISOtech
+ entityMap.put("lsaquo", new Character('\u2039')); // single left-pointing angle quotation mark, U+2039 ISO proposed
+ // lsaquo is proposed but not yet ISO standardized
+ entityMap.put("rsaquo", new Character('\u203a')); // single right-pointing angle quotation mark, U+203A ISO proposed
+ // rsaquo is proposed but not yet ISO standardized
+ entityMap.put("euro", new Character('\u20ac')); // euro sign, U+20AC NEW
+
+
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SpotColor.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SpotColor.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/SpotColor.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/SpotColor.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,73 @@
+/*
+ * $Id: SpotColor.java,v 1.13 2002/07/09 11:28:24 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+/**
+ *
+ * @author psoares
+ */
+public class SpotColor extends ExtendedColor {
+
+ PdfSpotColor spot;
+ float tint;
+
+ public SpotColor(PdfSpotColor spot, float tint) {
+ super(TYPE_SEPARATION,
+ ((float)spot.getAlternativeCS().getRed() / 255f - 1f) * tint + 1,
+ ((float)spot.getAlternativeCS().getGreen() / 255f - 1f) * tint + 1,
+ ((float)spot.getAlternativeCS().getBlue() / 255f - 1f) * tint + 1);
+ this.spot = spot;
+ this.tint = tint;
+ }
+
+ public SpotColor(PdfSpotColor spot) {
+ this(spot, spot.getTint());
+ }
+
+ public PdfSpotColor getPdfSpotColor() {
+ return spot;
+ }
+
+ public float getTint() {
+ return tint;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/StampContent.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/StampContent.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/StampContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/StampContent.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2003 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+public class StampContent extends PdfContentByte {
+ PdfStamperImp.PageStamp ps;
+ PageResources pageResources;
+
+ /** Creates a new instance of StampContent */
+ StampContent(PdfStamperImp stamper, PdfStamperImp.PageStamp ps) {
+ super(stamper);
+ this.ps = ps;
+ pageResources = ps.pageResources;
+ }
+
+ public void setAction(PdfAction action, float llx, float lly, float urx, float ury) {
+ ((PdfStamperImp)writer).addAnnotation(new PdfAnnotation(writer, llx, lly, urx, ury, action), ps.pageN);
+ }
+
+ /**
+ * Gets a duplicate of this PdfContentByte
. All
+ * the members are copied by reference but the buffer stays different.
+ *
+ * @return a copy of this PdfContentByte
+ */
+ public PdfContentByte getDuplicate() {
+ return new StampContent((PdfStamperImp)writer, ps);
+ }
+
+ PageResources getPageResources() {
+ return pageResources;
+ }
+
+ void addAnnotation(PdfAnnotation annot) {
+ ((PdfStamperImp)writer).addAnnotation(annot, ps.pageN);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/StandardDecryption.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/StandardDecryption.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/StandardDecryption.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/StandardDecryption.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,100 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.pdf.crypto.AESCipher;
+import pdftk.com.lowagie.text.pdf.crypto.ARCFOUREncryption;
+
+public class StandardDecryption {
+ protected ARCFOUREncryption arcfour;
+ protected AESCipher cipher;
+ private byte[] key;
+ private static final int AES_128 = 4;
+ private boolean aes;
+ private boolean initiated;
+ private byte[] iv = new byte[16];
+ private int ivptr;
+
+ /** Creates a new instance of StandardDecryption */
+ public StandardDecryption(byte key[], int off, int len, int revision) {
+ aes = revision == AES_128;
+ if (aes) {
+ this.key = new byte[len];
+ System.arraycopy(key, off, this.key, 0, len);
+ }
+ else {
+ arcfour = new ARCFOUREncryption();
+ arcfour.prepareARCFOURKey(key, off, len);
+ }
+ }
+
+ public byte[] update(byte[] b, int off, int len) {
+ if (aes) {
+ if (initiated)
+ return cipher.update(b, off, len);
+ else {
+ int left = Math.min(iv.length - ivptr, len);
+ System.arraycopy(b, off, iv, ivptr, left);
+ off += left;
+ len -= left;
+ ivptr += left;
+ if (ivptr == iv.length) {
+ cipher = new AESCipher(false, key, iv);
+ initiated = true;
+ if (len > 0)
+ return cipher.update(b, off, len);
+ }
+ return null;
+ }
+ }
+ else {
+ byte[] b2 = new byte[len];
+ arcfour.encryptARCFOUR(b, off, len, b2, 0);
+ return b2;
+ }
+ }
+
+ public byte[] finish() {
+ if (aes) {
+ return cipher.doFinal();
+ }
+ else
+ return null;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/TIFFLZWDecoder.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/TIFFLZWDecoder.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/TIFFLZWDecoder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/TIFFLZWDecoder.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,261 @@
+/*
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+// ssteward
+//package org.apache.batik.ext.awt.image.codec.tiff;
+package pdftk.com.lowagie.text.pdf;
+
+// ssteward
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * A class for performing LZW decoding.
+ *
+ * @version $Id: TIFFLZWDecoder.java 498740 2007-01-22 18:35:57Z dvholten $
+ */
+public class TIFFLZWDecoder {
+
+ byte[][] stringTable;
+ byte[] data = null;
+ // ssteward
+ // byte[] uncompData;
+ OutputStream uncompData;
+ int tableIndex, bitsToGet = 9;
+ int bytePointer, bitPointer;
+ int dstIndex;
+ // int w, h;
+ // int predictor, samplesPerPixel;
+ int nextData = 0;
+ int nextBits = 0;
+
+ int[] andTable = {
+ 511,
+ 1023,
+ 2047,
+ 4095
+ };
+
+ // ssteward: dropped w, predictor, samplesPerPixel because we won't use them
+ public TIFFLZWDecoder( /* int w, int predictor, int samplesPerPixel */ ) {
+ // this.w = w;
+ // this.predictor = predictor;
+ // this.samplesPerPixel = samplesPerPixel;
+ }
+
+ /**
+ * Method to decode LZW compressed data.
+ *
+ * @param data The compressed data.
+ * @param uncompData Array to return the uncompressed data in.
+ * @param h The number of rows the compressed data contains.
+ */
+ // ssteward: replaced byte[] with OutputStream for uncompData and return value
+ // dropped input h
+ public OutputStream decode(byte[] data, OutputStream uncompData /*, int h */ ) {
+
+ if(data[0] == (byte)0x00 && data[1] == (byte)0x01) {
+ throw new UnsupportedOperationException("TIFFLZWDecoder0");
+ }
+
+ initializeStringTable();
+
+ this.data = data;
+ // this.h = h;
+ this.uncompData = uncompData;
+
+ // Initialize pointers
+ bytePointer = 0;
+ bitPointer = 0;
+ dstIndex = 0;
+
+
+ nextData = 0;
+ nextBits = 0;
+
+ int code, oldCode = 0;
+ byte[] string;
+
+ while ( ((code = getNextCode()) != 257) /* && dstIndex != uncompData.length */ ) {
+
+ if (code == 256) {
+
+ initializeStringTable();
+ code = getNextCode();
+
+ if (code == 257) {
+ break;
+ }
+
+ writeString(stringTable[code]);
+ oldCode = code;
+
+ } else {
+
+ if (code < tableIndex) {
+
+ string = stringTable[code];
+
+ writeString(string);
+ addStringToTable(stringTable[oldCode], string[0]);
+ oldCode = code;
+
+ } else {
+
+ string = stringTable[oldCode];
+ string = composeString(string, string[0]);
+ writeString(string);
+ addStringToTable(string);
+ oldCode = code;
+ }
+
+ }
+
+ }
+
+ /* ssteward
+ // Horizontal Differencing Predictor
+ if (predictor == 2) {
+
+ int count;
+ for (int j = 0; j < h; j++) {
+
+ count = samplesPerPixel * (j * w + 1);
+
+ for (int i = samplesPerPixel; i < w * samplesPerPixel; i++) {
+
+ uncompData[count] += uncompData[count - samplesPerPixel];
+ count++;
+ }
+ }
+ }
+ */
+
+ return uncompData;
+ }
+
+
+ /**
+ * Initialize the string table.
+ */
+ public void initializeStringTable() {
+
+ stringTable = new byte[4096][];
+
+ for (int i=0; i<256; i++) {
+ stringTable[i] = new byte[1];
+ stringTable[i][0] = (byte)i;
+ }
+
+ tableIndex = 258;
+ bitsToGet = 9;
+ }
+
+ /**
+ * Write out the string just uncompressed.
+ */
+ public void writeString(byte[] string) {
+ /* ssteward
+ for (int i=0; inewString to the end of oldString
.
+ */
+ public byte[] composeString(byte[] oldString, byte newString) {
+ int length = oldString.length;
+ byte[] string = new byte[length + 1];
+ System.arraycopy(oldString, 0, string, 0, length);
+ string[length] = newString;
+
+ return string;
+ }
+
+ // Returns the next 9, 10, 11 or 12 bits
+ public int getNextCode() {
+ // Attempt to get the next code. The exception is caught to make
+ // this robust to cases wherein the EndOfInformation code has been
+ // omitted from a strip. Examples of such cases have been observed
+ // in practice.
+ try {
+ nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
+ nextBits += 8;
+
+ if (nextBits < bitsToGet) {
+ nextData = (nextData << 8) | (data[bytePointer++] & 0xff);
+ nextBits += 8;
+ }
+
+ int code =
+ (nextData >> (nextBits - bitsToGet)) & andTable[bitsToGet-9];
+ nextBits -= bitsToGet;
+
+ return code;
+ } catch(ArrayIndexOutOfBoundsException e) {
+ // Strip not terminated as expected: return EndOfInformation code.
+ return 257;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/TextField.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/TextField.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/TextField.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/TextField.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,568 @@
+/*
+ * Copyright 2003-2005 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.awt.Color;
+import pdftk.com.lowagie.text.Element;
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.Rectangle;
+import java.io.IOException;
+import java.util.ArrayList;
+
+/** Supports text, combo and list fields generating the correct appearances.
+ * All the option in the Acrobat GUI are supported in an easy to use API.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class TextField extends BaseField {
+
+ /** Holds value of property defaultText. */
+ private String defaultText;
+
+ /** Holds value of property choices. */
+ private String[] choices;
+
+ /** Holds value of property choiceExports. */
+ private String[] choiceExports;
+
+ /** Holds value of property choiceSelection. */
+ private int choiceSelection;
+
+ private int topFirst;
+
+ private float extraMarginLeft;
+ private float extraMarginTop;
+
+ /** Creates a new TextField
.
+ * @param writer the document PdfWriter
+ * @param box the field location and dimensions
+ * @param fieldName the field name. If null
only the widget keys
+ * will be included in the field allowing it to be used as a kid field.
+ */
+ public TextField(PdfWriter writer, Rectangle box, String fieldName) {
+ super(writer, box, fieldName);
+ }
+
+ /**
+ * Gets the appearance for this TextField.
+ * @return the appearance object for this TextField
+ * @throws IOException
+ * @throws DocumentException
+ */
+ public PdfAppearance getAppearance() throws IOException, DocumentException {
+ PdfAppearance app = getBorderAppearance();
+ app.beginVariableText();
+ if (text == null || text.length() == 0) {
+ app.endVariableText();
+ return app;
+ }
+ BaseFont ufont = getRealFont();
+ boolean borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET;
+ float h = box.height() - borderWidth * 2;
+ float bw2 = borderWidth;
+ if (borderExtra) {
+ h -= borderWidth * 2;
+ bw2 *= 2;
+ }
+ h -= extraMarginTop;
+ float offsetX = (borderExtra ? 2 * borderWidth : borderWidth);
+ offsetX = Math.max(offsetX, 1);
+ float offX = Math.min(bw2, offsetX);
+ app.saveState();
+ app.rectangle(offX, offX, box.width() - 2 * offX, box.height() - 2 * offX);
+ app.clip();
+ app.newPath();
+ if (textColor == null)
+ app.setGrayFill(0);
+ else
+ app.setColorFill(textColor);
+ app.beginText();
+ String ptext = text; //fixed by Kazuya Ujihara (ujihara.jp)
+ if ((options & PASSWORD) != 0) {
+ char[] pchar = new char[text.length()];
+ for (int i = 0; i < text.length(); i++)
+ pchar[i] = '*';
+ ptext = new String(pchar);
+ }
+ if ((options & MULTILINE) != 0) {
+ float usize = fontSize;
+ float width = box.width() - 3 * offsetX - extraMarginLeft;
+ ArrayList breaks = getHardBreaks(ptext);
+ ArrayList lines = breaks;
+ float factor = ufont.getFontDescriptor(BaseFont.BBOXURY, 1) - ufont.getFontDescriptor(BaseFont.BBOXLLY, 1);
+ if (usize == 0) {
+ usize = h / breaks.size() / factor;
+ if (usize > 4) {
+ if (usize > 12)
+ usize = 12;
+ float step = Math.max((usize - 4) / 10, 0.2f);
+ for (; usize > 4; usize -= step) {
+ lines = breakLines(breaks, ufont, usize, width);
+ if (lines.size() * usize * factor <= h)
+ break;
+ }
+ }
+ if (usize <= 4) {
+ usize = 4;
+ lines = breakLines(breaks, ufont, usize, width);
+ }
+ }
+ else
+ lines = breakLines(breaks, ufont, usize, width);
+ app.setFontAndSize(ufont, usize);
+ app.setLeading(usize * factor);
+ float offsetY = offsetX + h - ufont.getFontDescriptor(BaseFont.BBOXURY, usize);
+ String nt = (String)lines.get(0);
+ if (alignment == Element.ALIGN_RIGHT) {
+ float wd = ufont.getWidthPoint(nt, usize);
+ app.moveText(extraMarginLeft + box.width() - 2 * offsetX - wd, offsetY);
+ }
+ else if (alignment == Element.ALIGN_CENTER) {
+ nt = nt.trim();
+ float wd = ufont.getWidthPoint(nt, usize);
+ app.moveText(extraMarginLeft + box.width() / 2 - wd / 2, offsetY);
+ }
+ else
+ app.moveText(extraMarginLeft + 2 * offsetX, offsetY);
+ app.showText(nt);
+ int maxline = (int)(h / usize / factor) + 1;
+ maxline = Math.min(maxline, lines.size());
+ for (int k = 1; k < maxline; ++k) {
+ nt = (String)lines.get(k);
+ if (alignment == Element.ALIGN_RIGHT) {
+ float wd = ufont.getWidthPoint(nt, usize);
+ app.moveText(extraMarginLeft + box.width() - 2 * offsetX - wd - app.getXTLM(), 0);
+ }
+ else if (alignment == Element.ALIGN_CENTER) {
+ nt = nt.trim();
+ float wd = ufont.getWidthPoint(nt, usize);
+ app.moveText(extraMarginLeft + box.width() / 2 - wd / 2 - app.getXTLM(), 0);
+ }
+ app.newlineShowText(nt);
+ }
+ }
+ else {
+ float usize = fontSize;
+ if (usize == 0) {
+ float maxCalculatedSize = h / (ufont.getFontDescriptor(BaseFont.BBOXURX, 1) - ufont.getFontDescriptor(BaseFont.BBOXLLY, 1));
+ float wd = ufont.getWidthPoint(ptext, 1);
+ if (wd == 0)
+ usize = maxCalculatedSize;
+ else
+ usize = (box.width() - extraMarginLeft - 2 * offsetX) / wd;
+ if (usize > maxCalculatedSize)
+ usize = maxCalculatedSize;
+ if (usize < 4)
+ usize = 4;
+ }
+ app.setFontAndSize(ufont, usize);
+ float offsetY = offX + ((box.height() - 2*offX) - ufont.getFontDescriptor(BaseFont.ASCENT, usize)) / 2;
+ if (offsetY < offX)
+ offsetY = offX;
+ if (offsetY - offX < -ufont.getFontDescriptor(BaseFont.DESCENT, usize)) {
+ float ny = -ufont.getFontDescriptor(BaseFont.DESCENT, usize) + offX;
+ float dy = box.height() - offX - ufont.getFontDescriptor(BaseFont.ASCENT, usize);
+ offsetY = Math.min(ny, Math.max(offsetY, dy));
+ }
+ if ((options & COMB) != 0 && maxCharacterLength > 0) {
+ int textLen = Math.min(maxCharacterLength, ptext.length());
+ int position = 0;
+ if (alignment == Element.ALIGN_RIGHT) {
+ position = maxCharacterLength - textLen;
+ }
+ else if (alignment == Element.ALIGN_CENTER) {
+ position = (maxCharacterLength - textLen) / 2;
+ }
+ float step = (box.width() - extraMarginLeft) / maxCharacterLength;
+ float start = step / 2 + position * step;
+ for (int k = 0; k < textLen; ++k) {
+ String c = ptext.substring(k, k + 1);
+ float wd = ufont.getWidthPoint(c, usize);
+ app.setTextMatrix(extraMarginLeft + start - wd / 2, offsetY - extraMarginTop);
+ app.showText(c);
+ start += step;
+ }
+ }
+ else {
+ if (alignment == Element.ALIGN_RIGHT) {
+ float wd = ufont.getWidthPoint(ptext, usize);
+ app.moveText(extraMarginLeft + box.width() - 2 * offsetX - wd, offsetY - extraMarginTop);
+ }
+ else if (alignment == Element.ALIGN_CENTER) {
+ float wd = ufont.getWidthPoint(ptext, usize);
+ app.moveText(extraMarginLeft + box.width() / 2 - wd / 2, offsetY - extraMarginTop);
+ }
+ else
+ app.moveText(extraMarginLeft + 2 * offsetX, offsetY - extraMarginTop);
+ app.showText(ptext);
+ }
+ }
+ app.endText();
+ app.restoreState();
+ app.endVariableText();
+ return app;
+ }
+
+ PdfAppearance getListAppearance() throws IOException, DocumentException {
+ PdfAppearance app = getBorderAppearance();
+ app.beginVariableText();
+ if (choices == null || choices.length == 0) {
+ app.endVariableText();
+ return app;
+ }
+ int topChoice = choiceSelection;
+ if (topChoice >= choices.length) {
+ topChoice = choices.length - 1;
+ }
+ if (topChoice < 0)
+ topChoice = 0;
+ BaseFont ufont = getRealFont();
+ float usize = fontSize;
+ if (usize == 0)
+ usize = 12;
+ boolean borderExtra = borderStyle == PdfBorderDictionary.STYLE_BEVELED || borderStyle == PdfBorderDictionary.STYLE_INSET;
+ float h = box.height() - borderWidth * 2;
+ if (borderExtra)
+ h -= borderWidth * 2;
+ float offsetX = (borderExtra ? 2 * borderWidth : borderWidth);
+ float leading = ufont.getFontDescriptor(BaseFont.BBOXURY, usize) - ufont.getFontDescriptor(BaseFont.BBOXLLY, usize);
+ int maxFit = (int)(h / leading) + 1;
+ int first = 0;
+ int last = 0;
+ last = topChoice + maxFit / 2 + 1;
+ first = last - maxFit;
+ if (first < 0) {
+ last += first;
+ first = 0;
+ }
+// first = topChoice;
+ last = first + maxFit;
+ if (last > choices.length)
+ last = choices.length;
+ topFirst = first;
+ app.saveState();
+ app.rectangle(offsetX, offsetX, box.width() - 2 * offsetX, box.height() - 2 * offsetX);
+ app.clip();
+ app.newPath();
+ Color mColor;
+ if (textColor == null)
+ mColor = new GrayColor(0);
+ else
+ mColor = textColor;
+ app.setColorFill(new Color(10, 36, 106));
+ app.rectangle(offsetX, offsetX + h - (topChoice - first + 1) * leading, box.width() - 2 * offsetX, leading);
+ app.fill();
+ app.beginText();
+ app.setFontAndSize(ufont, usize);
+ app.setLeading(leading);
+ app.moveText(offsetX * 2, offsetX + h - ufont.getFontDescriptor(BaseFont.BBOXURY, usize) + leading);
+ app.setColorFill(mColor);
+ for (int idx = first; idx < last; ++idx) {
+ if (idx == topChoice) {
+ app.setGrayFill(1);
+ app.newlineShowText(choices[idx]);
+ app.setColorFill(mColor);
+ }
+ else
+ app.newlineShowText(choices[idx]);
+ }
+ app.endText();
+ app.restoreState();
+ app.endVariableText();
+ return app;
+ }
+
+ /** Gets a new text field.
+ * @throws IOException on error
+ * @throws DocumentException on error
+ * @return a new text field
+ */
+ public PdfFormField getTextField() throws IOException, DocumentException {
+ if (maxCharacterLength <= 0)
+ options &= ~COMB;
+ if ((options & COMB) != 0)
+ options &= ~MULTILINE;
+ PdfFormField field = PdfFormField.createTextField(writer, false, false, maxCharacterLength);
+ field.setWidget(box, PdfAnnotation.HIGHLIGHT_INVERT);
+ switch (alignment) {
+ case Element.ALIGN_CENTER:
+ field.setQuadding(PdfFormField.Q_CENTER);
+ break;
+ case Element.ALIGN_RIGHT:
+ field.setQuadding(PdfFormField.Q_RIGHT);
+ break;
+ }
+ if (rotation != 0)
+ field.setMKRotation(rotation);
+ if (fieldName != null) {
+ field.setFieldName(fieldName);
+ field.setValueAsString(text);
+ if (defaultText != null)
+ field.setDefaultValueAsString(defaultText);
+ if ((options & READ_ONLY) != 0)
+ field.setFieldFlags(PdfFormField.FF_READ_ONLY);
+ if ((options & REQUIRED) != 0)
+ field.setFieldFlags(PdfFormField.FF_REQUIRED);
+ if ((options & MULTILINE) != 0)
+ field.setFieldFlags(PdfFormField.FF_MULTILINE);
+ if ((options & DO_NOT_SCROLL) != 0)
+ field.setFieldFlags(PdfFormField.FF_DONOTSCROLL);
+ if ((options & PASSWORD) != 0)
+ field.setFieldFlags(PdfFormField.FF_PASSWORD);
+ if ((options & FILE_SELECTION) != 0)
+ field.setFieldFlags(PdfFormField.FF_FILESELECT);
+ if ((options & DO_NOT_SPELL_CHECK) != 0)
+ field.setFieldFlags(PdfFormField.FF_DONOTSPELLCHECK);
+ if ((options & COMB) != 0)
+ field.setFieldFlags(PdfFormField.FF_COMB);
+ }
+ field.setBorderStyle(new PdfBorderDictionary(borderWidth, borderStyle, new PdfDashPattern(3)));
+ PdfAppearance tp = getAppearance();
+ field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
+ PdfAppearance da = (PdfAppearance)tp.getDuplicate();
+ da.setFontAndSize(getRealFont(), fontSize);
+ if (textColor == null)
+ da.setGrayFill(0);
+ else
+ da.setColorFill(textColor);
+ field.setDefaultAppearanceString(da);
+ if (borderColor != null)
+ field.setMKBorderColor(borderColor);
+ if (backgroundColor != null)
+ field.setMKBackgroundColor(backgroundColor);
+ switch (visibility) {
+ case HIDDEN:
+ field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_HIDDEN);
+ break;
+ case VISIBLE_BUT_DOES_NOT_PRINT:
+ break;
+ case HIDDEN_BUT_PRINTABLE:
+ field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_NOVIEW);
+ break;
+ default:
+ field.setFlags(PdfAnnotation.FLAGS_PRINT);
+ break;
+ }
+ return field;
+ }
+
+ /** Gets a new combo field.
+ * @throws IOException on error
+ * @throws DocumentException on error
+ * @return a new combo field
+ */
+ public PdfFormField getComboField() throws IOException, DocumentException {
+ return getChoiceField(false);
+ }
+
+ /** Gets a new list field.
+ * @throws IOException on error
+ * @throws DocumentException on error
+ * @return a new list field
+ */
+ public PdfFormField getListField() throws IOException, DocumentException {
+ return getChoiceField(true);
+ }
+
+ protected PdfFormField getChoiceField(boolean isList) throws IOException, DocumentException {
+ options &= (~MULTILINE) & (~COMB);
+ String uchoices[] = choices;
+ if (uchoices == null)
+ uchoices = new String[0];
+ int topChoice = choiceSelection;
+ if (topChoice >= uchoices.length)
+ topChoice = uchoices.length - 1;
+ if (text == null) text = ""; //fixed by Kazuya Ujihara (ujihara.jp)
+ if (topChoice >= 0)
+ text = uchoices[topChoice];
+ if (topChoice < 0)
+ topChoice = 0;
+ PdfFormField field = null;
+ String mix[][] = null;
+ if (choiceExports == null) {
+ if (isList)
+ field = PdfFormField.createList(writer, uchoices, topChoice);
+ else
+ field = PdfFormField.createCombo(writer, (options & EDIT) != 0, uchoices, topChoice);
+ }
+ else {
+ mix = new String[uchoices.length][2];
+ for (int k = 0; k < mix.length; ++k)
+ mix[k][0] = mix[k][1] = uchoices[k];
+ int top = Math.min(uchoices.length, choiceExports.length);
+ for (int k = 0; k < top; ++k) {
+ if (choiceExports[k] != null)
+ mix[k][0] = choiceExports[k];
+ }
+ if (isList)
+ field = PdfFormField.createList(writer, mix, topChoice);
+ else
+ field = PdfFormField.createCombo(writer, (options & EDIT) != 0, mix, topChoice);
+ }
+ field.setWidget(box, PdfAnnotation.HIGHLIGHT_INVERT);
+ if (rotation != 0)
+ field.setMKRotation(rotation);
+ if (fieldName != null) {
+ field.setFieldName(fieldName);
+ if (uchoices.length > 0) {
+ if (mix != null) {
+ field.setValueAsString(mix[topChoice][0]);
+ field.setDefaultValueAsString(mix[topChoice][0]);
+ }
+ else {
+ field.setValueAsString(text);
+ field.setDefaultValueAsString(text);
+ }
+ }
+ if ((options & READ_ONLY) != 0)
+ field.setFieldFlags(PdfFormField.FF_READ_ONLY);
+ if ((options & REQUIRED) != 0)
+ field.setFieldFlags(PdfFormField.FF_REQUIRED);
+ if ((options & DO_NOT_SPELL_CHECK) != 0)
+ field.setFieldFlags(PdfFormField.FF_DONOTSPELLCHECK);
+ }
+ field.setBorderStyle(new PdfBorderDictionary(borderWidth, borderStyle, new PdfDashPattern(3)));
+ PdfAppearance tp;
+ if (isList) {
+ tp = getListAppearance();
+ if (topFirst > 0)
+ field.put(PdfName.TI, new PdfNumber(topFirst));
+ }
+ else
+ tp = getAppearance();
+ field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
+ PdfAppearance da = (PdfAppearance)tp.getDuplicate();
+ da.setFontAndSize(getRealFont(), fontSize);
+ if (textColor == null)
+ da.setGrayFill(0);
+ else
+ da.setColorFill(textColor);
+ field.setDefaultAppearanceString(da);
+ if (borderColor != null)
+ field.setMKBorderColor(borderColor);
+ if (backgroundColor != null)
+ field.setMKBackgroundColor(backgroundColor);
+ switch (visibility) {
+ case HIDDEN:
+ field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_HIDDEN);
+ break;
+ case VISIBLE_BUT_DOES_NOT_PRINT:
+ break;
+ case HIDDEN_BUT_PRINTABLE:
+ field.setFlags(PdfAnnotation.FLAGS_PRINT | PdfAnnotation.FLAGS_NOVIEW);
+ break;
+ default:
+ field.setFlags(PdfAnnotation.FLAGS_PRINT);
+ break;
+ }
+ return field;
+ }
+
+ /** Gets the default text.
+ * @return the default text
+ */
+ public String getDefaultText() {
+ return this.defaultText;
+ }
+
+ /** Sets the default text. It is only meaningful for text fields.
+ * @param defaultText the default text
+ */
+ public void setDefaultText(String defaultText) {
+ this.defaultText = defaultText;
+ }
+
+ /** Gets the choices to be presented to the user in list/combo
+ * fields.
+ * @return the choices to be presented to the user
+ */
+ public String[] getChoices() {
+ return this.choices;
+ }
+
+ /** Sets the choices to be presented to the user in list/combo
+ * fields.
+ * @param choices the choices to be presented to the user
+ */
+ public void setChoices(String[] choices) {
+ this.choices = choices;
+ }
+
+ /** Gets the export values in list/combo fields.
+ * @return the export values in list/combo fields
+ */
+ public String[] getChoiceExports() {
+ return this.choiceExports;
+ }
+
+ /** Sets the export values in list/combo fields. If this array
+ * is null
then the choice values will also be used
+ * as the export values.
+ * @param choiceExports the export values in list/combo fields
+ */
+ public void setChoiceExports(String[] choiceExports) {
+ this.choiceExports = choiceExports;
+ }
+
+ /** Gets the zero based index of the selected item.
+ * @return the zero based index of the selected item
+ */
+ public int getChoiceSelection() {
+ return this.choiceSelection;
+ }
+
+ /** Sets the zero based index of the selected item.
+ * @param choiceSelection the zero based index of the selected item
+ */
+ public void setChoiceSelection(int choiceSelection) {
+ this.choiceSelection = choiceSelection;
+ }
+
+ int getTopFirst() {
+ return topFirst;
+ }
+
+ /**
+ * Sets extra margins in text fields to better mimic the Acrobat layout.
+ * @param extraMarginLeft the extra marging left
+ * @param extraMarginTop the extra margin top
+ */
+ public void setExtraMargin(float extraMarginLeft, float extraMarginTop) {
+ this.extraMarginLeft = extraMarginLeft;
+ this.extraMarginTop = extraMarginTop;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/TrueTypeFont.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/TrueTypeFont.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/TrueTypeFont.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/TrueTypeFont.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,1290 @@
+/*
+ * $Id: TrueTypeFont.java,v 1.55 2004/12/14 15:15:59 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.ArrayList;
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.ExceptionConverter;
+/** Reads a Truetype font
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+class TrueTypeFont extends BaseFont {
+
+ /** The code pages possible for a True Type font.
+ */
+ static final String codePages[] = {
+ "1252 Latin 1",
+ "1250 Latin 2: Eastern Europe",
+ "1251 Cyrillic",
+ "1253 Greek",
+ "1254 Turkish",
+ "1255 Hebrew",
+ "1256 Arabic",
+ "1257 Windows Baltic",
+ "1258 Vietnamese",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "874 Thai",
+ "932 JIS/Japan",
+ "936 Chinese: Simplified chars--PRC and Singapore",
+ "949 Korean Wansung",
+ "950 Chinese: Traditional chars--Taiwan and Hong Kong",
+ "1361 Korean Johab",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "Macintosh Character Set (US Roman)",
+ "OEM Character Set",
+ "Symbol Character Set",
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ "869 IBM Greek",
+ "866 MS-DOS Russian",
+ "865 MS-DOS Nordic",
+ "864 Arabic",
+ "863 MS-DOS Canadian French",
+ "862 Hebrew",
+ "861 MS-DOS Icelandic",
+ "860 MS-DOS Portuguese",
+ "857 IBM Turkish",
+ "855 IBM Cyrillic; primarily Russian",
+ "852 Latin 2",
+ "775 MS-DOS Baltic",
+ "737 Greek; former 437 G",
+ "708 Arabic; ASMO 708",
+ "850 WE/Latin 1",
+ "437 US"};
+
+ protected boolean justNames = false;
+ /** Contains the location of the several tables. The key is the name of
+ * the table and the value is an int[2]
where position 0
+ * is the offset from the start of the file and position 1 is the length
+ * of the table.
+ */
+ protected HashMap tables;
+ /** The file in use.
+ */
+ protected RandomAccessFileOrArray rf;
+ /** The file name.
+ */
+ protected String fileName;
+
+ protected boolean cff = false;
+
+ protected int cffOffset;
+
+ protected int cffLength;
+
+ /** The offset from the start of the file to the table directory.
+ * It is 0 for TTF and may vary for TTC depending on the chosen font.
+ */
+ protected int directoryOffset;
+ /** The index for the TTC font. It is an empty String
for a
+ * TTF file.
+ */
+ protected String ttcIndex;
+ /** The style modifier */
+ protected String style = "";
+ /** The content of table 'head'.
+ */
+ protected FontHeader head = new FontHeader();
+ /** The content of table 'hhea'.
+ */
+ protected HorizontalHeader hhea = new HorizontalHeader();
+ /** The content of table 'OS/2'.
+ */
+ protected WindowsMetrics os_2 = new WindowsMetrics();
+ /** The width of the glyphs. This is essentially the content of table
+ * 'hmtx' normalized to 1000 units.
+ */
+ protected int GlyphWidths[];
+
+ protected int bboxes[][];
+ /** The map containing the code information for the table 'cmap', encoding 1.0.
+ * The key is the code and the value is an int[2]
where position 0
+ * is the glyph number and position 1 is the glyph width normalized to 1000
+ * units.
+ */
+ protected HashMap cmap10;
+ /** The map containing the code information for the table 'cmap', encoding 3.1
+ * in Unicode.
+ *
+ * The key is the code and the value is an int
[2] where position 0
+ * is the glyph number and position 1 is the glyph width normalized to 1000
+ * units.
+ */
+ protected HashMap cmap31;
+ /** The map containing the kerning information. It represents the content of
+ * table 'kern'. The key is an Integer
where the top 16 bits
+ * are the glyph number for the first character and the lower 16 bits are the
+ * glyph number for the second character. The value is the amount of kerning in
+ * normalized 1000 units as an Integer
. This value is usually negative.
+ */
+ protected IntHashtable kerning = new IntHashtable();
+ /**
+ * The font name.
+ * This name is usually extracted from the table 'name' with
+ * the 'Name ID' 6.
+ */
+ protected String fontName;
+
+ /** The full name of the font
+ */
+ protected String fullName[][];
+
+ /** The family name of the font
+ */
+ protected String familyName[][];
+ /** The italic angle. It is usually extracted from the 'post' table or in it's
+ * absence with the code:
+ *
+ *
+ * -Math.atan2(hhea.caretSlopeRun, hhea.caretSlopeRise) * 180 / Math.PI
+ *
+ */
+ protected double italicAngle;
+ /** true
if all the glyphs have the same width.
+ */
+ protected boolean isFixedPitch = false;
+
+ /** The components of table 'head'.
+ */
+ protected static class FontHeader {
+ /** A variable. */
+ int flags;
+ /** A variable. */
+ int unitsPerEm;
+ /** A variable. */
+ short xMin;
+ /** A variable. */
+ short yMin;
+ /** A variable. */
+ short xMax;
+ /** A variable. */
+ short yMax;
+ /** A variable. */
+ int macStyle;
+ }
+
+ /** The components of table 'hhea'.
+ */
+ protected static class HorizontalHeader {
+ /** A variable. */
+ short Ascender;
+ /** A variable. */
+ short Descender;
+ /** A variable. */
+ short LineGap;
+ /** A variable. */
+ int advanceWidthMax;
+ /** A variable. */
+ short minLeftSideBearing;
+ /** A variable. */
+ short minRightSideBearing;
+ /** A variable. */
+ short xMaxExtent;
+ /** A variable. */
+ short caretSlopeRise;
+ /** A variable. */
+ short caretSlopeRun;
+ /** A variable. */
+ int numberOfHMetrics;
+ }
+
+ /** The components of table 'OS/2'.
+ */
+ protected static class WindowsMetrics {
+ /** A variable. */
+ short xAvgCharWidth;
+ /** A variable. */
+ int usWeightClass;
+ /** A variable. */
+ int usWidthClass;
+ /** A variable. */
+ short fsType;
+ /** A variable. */
+ short ySubscriptXSize;
+ /** A variable. */
+ short ySubscriptYSize;
+ /** A variable. */
+ short ySubscriptXOffset;
+ /** A variable. */
+ short ySubscriptYOffset;
+ /** A variable. */
+ short ySuperscriptXSize;
+ /** A variable. */
+ short ySuperscriptYSize;
+ /** A variable. */
+ short ySuperscriptXOffset;
+ /** A variable. */
+ short ySuperscriptYOffset;
+ /** A variable. */
+ short yStrikeoutSize;
+ /** A variable. */
+ short yStrikeoutPosition;
+ /** A variable. */
+ short sFamilyClass;
+ /** A variable. */
+ byte panose[] = new byte[10];
+ /** A variable. */
+ byte achVendID[] = new byte[4];
+ /** A variable. */
+ int fsSelection;
+ /** A variable. */
+ int usFirstCharIndex;
+ /** A variable. */
+ int usLastCharIndex;
+ /** A variable. */
+ short sTypoAscender;
+ /** A variable. */
+ short sTypoDescender;
+ /** A variable. */
+ short sTypoLineGap;
+ /** A variable. */
+ int usWinAscent;
+ /** A variable. */
+ int usWinDescent;
+ /** A variable. */
+ int ulCodePageRange1;
+ /** A variable. */
+ int ulCodePageRange2;
+ /** A variable. */
+ int sCapHeight;
+ }
+
+ /** This constructor is present to allow extending the class.
+ */
+ protected TrueTypeFont() {
+ }
+
+ TrueTypeFont(String ttFile, String enc, boolean emb, byte ttfAfm[]) throws DocumentException, IOException {
+ this(ttFile, enc, emb, ttfAfm, false);
+ }
+
+ /** Creates a new TrueType font.
+ * @param ttFile the location of the font on file. The file must end in '.ttf' or
+ * '.ttc' but can have modifiers after the name
+ * @param enc the encoding to be applied to this font
+ * @param emb true if the font is to be embedded in the PDF
+ * @param ttfAfm the font as a byte
array
+ * @throws DocumentException the font is invalid
+ * @throws IOException the font file could not be read
+ */
+ TrueTypeFont(String ttFile, String enc, boolean emb, byte ttfAfm[], boolean justNames) throws DocumentException, IOException {
+ this.justNames = justNames;
+ String nameBase = getBaseName(ttFile);
+ String ttcName = getTTCName(nameBase);
+ if (nameBase.length() < ttFile.length()) {
+ style = ttFile.substring(nameBase.length());
+ }
+ encoding = enc;
+ embedded = emb;
+ fileName = ttcName;
+ fontType = FONT_TYPE_TT;
+ ttcIndex = "";
+ if (ttcName.length() < nameBase.length())
+ ttcIndex = nameBase.substring(ttcName.length() + 1);
+ if (fileName.toLowerCase().endsWith(".ttf") || fileName.toLowerCase().endsWith(".otf") || fileName.toLowerCase().endsWith(".ttc")) {
+ process(ttfAfm);
+ if (!justNames && embedded && os_2.fsType == 2)
+ throw new DocumentException(fileName + style + " cannot be embedded due to licensing restrictions.");
+ }
+ else
+ throw new DocumentException(fileName + style + " is not a TTF, OTF or TTC font file.");
+ PdfEncodings.convertToBytes(" ", enc); // check if the encoding exists
+ createEncoding();
+ }
+
+ /** Gets the name from a composed TTC file name.
+ * If I have for input "myfont.ttc,2" the return will
+ * be "myfont.ttc".
+ * @param name the full name
+ * @return the simple file name
+ */
+ protected static String getTTCName(String name) {
+ int idx = name.toLowerCase().indexOf(".ttc,");
+ if (idx < 0)
+ return name;
+ else
+ return name.substring(0, idx + 4);
+ }
+
+
+ /**
+ * Reads the tables 'head', 'hhea', 'OS/2' and 'post' filling several variables.
+ * @throws DocumentException the font is invalid
+ * @throws IOException the font file could not be read
+ */
+ void fillTables() throws DocumentException, IOException {
+ int table_location[];
+ table_location = (int[])tables.get("head");
+ if (table_location == null)
+ throw new DocumentException("Table 'head' does not exist in " + fileName + style);
+ rf.seek(table_location[0] + 16);
+ head.flags = rf.readUnsignedShort();
+ head.unitsPerEm = rf.readUnsignedShort();
+ rf.skipBytes(16);
+ head.xMin = rf.readShort();
+ head.yMin = rf.readShort();
+ head.xMax = rf.readShort();
+ head.yMax = rf.readShort();
+ head.macStyle = rf.readUnsignedShort();
+
+ table_location = (int[])tables.get("hhea");
+ if (table_location == null)
+ throw new DocumentException("Table 'hhea' does not exist " + fileName + style);
+ rf.seek(table_location[0] + 4);
+ hhea.Ascender = rf.readShort();
+ hhea.Descender = rf.readShort();
+ hhea.LineGap = rf.readShort();
+ hhea.advanceWidthMax = rf.readUnsignedShort();
+ hhea.minLeftSideBearing = rf.readShort();
+ hhea.minRightSideBearing = rf.readShort();
+ hhea.xMaxExtent = rf.readShort();
+ hhea.caretSlopeRise = rf.readShort();
+ hhea.caretSlopeRun = rf.readShort();
+ rf.skipBytes(12);
+ hhea.numberOfHMetrics = rf.readUnsignedShort();
+
+ table_location = (int[])tables.get("OS/2");
+ if (table_location == null)
+ throw new DocumentException("Table 'OS/2' does not exist in " + fileName + style);
+ rf.seek(table_location[0]);
+ int version = rf.readUnsignedShort();
+ os_2.xAvgCharWidth = rf.readShort();
+ os_2.usWeightClass = rf.readUnsignedShort();
+ os_2.usWidthClass = rf.readUnsignedShort();
+ os_2.fsType = rf.readShort();
+ os_2.ySubscriptXSize = rf.readShort();
+ os_2.ySubscriptYSize = rf.readShort();
+ os_2.ySubscriptXOffset = rf.readShort();
+ os_2.ySubscriptYOffset = rf.readShort();
+ os_2.ySuperscriptXSize = rf.readShort();
+ os_2.ySuperscriptYSize = rf.readShort();
+ os_2.ySuperscriptXOffset = rf.readShort();
+ os_2.ySuperscriptYOffset = rf.readShort();
+ os_2.yStrikeoutSize = rf.readShort();
+ os_2.yStrikeoutPosition = rf.readShort();
+ os_2.sFamilyClass = rf.readShort();
+ rf.readFully(os_2.panose);
+ rf.skipBytes(16);
+ rf.readFully(os_2.achVendID);
+ os_2.fsSelection = rf.readUnsignedShort();
+ os_2.usFirstCharIndex = rf.readUnsignedShort();
+ os_2.usLastCharIndex = rf.readUnsignedShort();
+ os_2.sTypoAscender = rf.readShort();
+ os_2.sTypoDescender = rf.readShort();
+ if (os_2.sTypoDescender > 0)
+ os_2.sTypoDescender = (short)(-os_2.sTypoDescender);
+ os_2.sTypoLineGap = rf.readShort();
+ os_2.usWinAscent = rf.readUnsignedShort();
+ os_2.usWinDescent = rf.readUnsignedShort();
+ os_2.ulCodePageRange1 = 0;
+ os_2.ulCodePageRange2 = 0;
+ if (version > 0) {
+ os_2.ulCodePageRange1 = rf.readInt();
+ os_2.ulCodePageRange2 = rf.readInt();
+ }
+ if (version > 1) {
+ rf.skipBytes(2);
+ os_2.sCapHeight = rf.readShort();
+ }
+ else
+ os_2.sCapHeight = (int)(0.7 * head.unitsPerEm);
+
+ table_location = (int[])tables.get("post");
+ if (table_location == null) {
+ italicAngle = -Math.atan2(hhea.caretSlopeRun, hhea.caretSlopeRise) * 180 / Math.PI;
+ return;
+ }
+ rf.seek(table_location[0] + 4);
+ short mantissa = rf.readShort();
+ int fraction = rf.readUnsignedShort();
+ italicAngle = (double)mantissa + (double)fraction / 16384.0;
+ rf.skipBytes(4);
+ isFixedPitch = rf.readInt() != 0;
+ }
+
+ /**
+ * Gets the Postscript font name.
+ * @throws DocumentException the font is invalid
+ * @throws IOException the font file could not be read
+ * @return the Postscript font name
+ */
+ String getBaseFont() throws DocumentException, IOException {
+ int table_location[];
+ table_location = (int[])tables.get("name");
+ if (table_location == null)
+ throw new DocumentException("Table 'name' does not exist in " + fileName + style);
+ rf.seek(table_location[0] + 2);
+ int numRecords = rf.readUnsignedShort();
+ int startOfStorage = rf.readUnsignedShort();
+ for (int k = 0; k < numRecords; ++k) {
+ int platformID = rf.readUnsignedShort();
+ int platformEncodingID = rf.readUnsignedShort();
+ int languageID = rf.readUnsignedShort();
+ int nameID = rf.readUnsignedShort();
+ int length = rf.readUnsignedShort();
+ int offset = rf.readUnsignedShort();
+ if (nameID == 6) {
+ rf.seek(table_location[0] + startOfStorage + offset);
+ if (platformID == 0 || platformID == 3)
+ return readUnicodeString(length);
+ else
+ return readStandardString(length);
+ }
+ }
+ File file = new File(fileName);
+ return file.getName().replace(' ', '-');
+ }
+
+ /** Extracts the names of the font in all the languages available.
+ * @param id the name id to retrieve
+ * @throws DocumentException on error
+ * @throws IOException on error
+ */
+ String[][] getNames(int id) throws DocumentException, IOException {
+ int table_location[];
+ table_location = (int[])tables.get("name");
+ if (table_location == null)
+ throw new DocumentException("Table 'name' does not exist in " + fileName + style);
+ rf.seek(table_location[0] + 2);
+ int numRecords = rf.readUnsignedShort();
+ int startOfStorage = rf.readUnsignedShort();
+ ArrayList names = new ArrayList();
+ for (int k = 0; k < numRecords; ++k) {
+ int platformID = rf.readUnsignedShort();
+ int platformEncodingID = rf.readUnsignedShort();
+ int languageID = rf.readUnsignedShort();
+ int nameID = rf.readUnsignedShort();
+ int length = rf.readUnsignedShort();
+ int offset = rf.readUnsignedShort();
+ if (nameID == id) {
+ int pos = rf.getFilePointer();
+ rf.seek(table_location[0] + startOfStorage + offset);
+ String name;
+ if (platformID == 0 || platformID == 3 || (platformID == 2 && platformEncodingID == 1)){
+ name = readUnicodeString(length);
+ }
+ else {
+ name = readStandardString(length);
+ }
+ names.add(new String[]{String.valueOf(platformID),
+ String.valueOf(platformEncodingID), String.valueOf(languageID), name});
+ rf.seek(pos);
+ }
+ }
+ String thisName[][] = new String[names.size()][];
+ for (int k = 0; k < names.size(); ++k)
+ thisName[k] = (String[])names.get(k);
+ return thisName;
+ }
+
+ void checkCff() throws DocumentException, IOException {
+ int table_location[];
+ table_location = (int[])tables.get("CFF ");
+ if (table_location != null) {
+ cff = true;
+ cffOffset = table_location[0];
+ cffLength = table_location[1];
+ }
+ }
+
+ /** Reads the font data.
+ * @param ttfAfm the font as a byte
array, possibly null
+ * @throws DocumentException the font is invalid
+ * @throws IOException the font file could not be read
+ */
+ void process(byte ttfAfm[]) throws DocumentException, IOException {
+ tables = new HashMap();
+
+ try {
+ if (ttfAfm == null)
+ rf = new RandomAccessFileOrArray(fileName);
+ else
+ rf = new RandomAccessFileOrArray(ttfAfm);
+ if (ttcIndex.length() > 0) {
+ int dirIdx = Integer.parseInt(ttcIndex);
+ if (dirIdx < 0)
+ throw new DocumentException("The font index for " + fileName + " must be positive.");
+ String mainTag = readStandardString(4);
+ if (!mainTag.equals("ttcf"))
+ throw new DocumentException(fileName + " is not a valid TTC file.");
+ rf.skipBytes(4);
+ int dirCount = rf.readInt();
+ if (dirIdx >= dirCount)
+ throw new DocumentException("The font index for " + fileName + " must be between 0 and " + (dirCount - 1) + ". It was " + dirIdx + ".");
+ rf.skipBytes(dirIdx * 4);
+ directoryOffset = rf.readInt();
+ }
+ rf.seek(directoryOffset);
+ int ttId = rf.readInt();
+ if (ttId != 0x00010000 && ttId != 0x4F54544F)
+ throw new DocumentException(fileName + " is not a valid TTF or OTF file.");
+ int num_tables = rf.readUnsignedShort();
+ rf.skipBytes(6);
+ for (int k = 0; k < num_tables; ++k) {
+ String tag = readStandardString(4);
+ rf.skipBytes(4);
+ int table_location[] = new int[2];
+ table_location[0] = rf.readInt();
+ table_location[1] = rf.readInt();
+ tables.put(tag, table_location);
+ }
+ checkCff();
+ fontName = getBaseFont();
+ fullName = getNames(4); //full name
+ familyName = getNames(1); //family name
+ if (!justNames) {
+ fillTables();
+ readGlyphWidths();
+ readCMaps();
+ readKerning();
+ readBbox();
+ GlyphWidths = null;
+ }
+ }
+ finally {
+ if (rf != null) {
+ rf.close();
+ if (!embedded)
+ rf = null;
+ }
+ }
+ }
+
+ /** Reads a String
from the font file as bytes using the Cp1252
+ * encoding.
+ * @param length the length of bytes to read
+ * @return the String
read
+ * @throws IOException the font file could not be read
+ */
+ protected String readStandardString(int length) throws IOException {
+ byte buf[] = new byte[length];
+ rf.readFully(buf);
+ try {
+ return new String(buf, WINANSI);
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ /** Reads a Unicode String
from the font file. Each character is
+ * represented by two bytes.
+ * @param length the length of bytes to read. The String
will have length
/2
+ * characters
+ * @return the String
read
+ * @throws IOException the font file could not be read
+ */
+ protected String readUnicodeString(int length) throws IOException {
+ StringBuffer buf = new StringBuffer();
+ length /= 2;
+ for (int k = 0; k < length; ++k) {
+ buf.append(rf.readChar());
+ }
+ return buf.toString();
+ }
+
+ /** Reads the glyphs widths. The widths are extracted from the table 'hmtx'.
+ * The glyphs are normalized to 1000 units.
+ * @throws DocumentException the font is invalid
+ * @throws IOException the font file could not be read
+ */
+ protected void readGlyphWidths() throws DocumentException, IOException {
+ int table_location[];
+ table_location = (int[])tables.get("hmtx");
+ if (table_location == null)
+ throw new DocumentException("Table 'hmtx' does not exist in " + fileName + style);
+ rf.seek(table_location[0]);
+ GlyphWidths = new int[hhea.numberOfHMetrics];
+ for (int k = 0; k < hhea.numberOfHMetrics; ++k) {
+ GlyphWidths[k] = (rf.readUnsignedShort() * 1000) / head.unitsPerEm;
+ rf.readUnsignedShort();
+ }
+ }
+
+ /** Gets a glyph width.
+ * @param glyph the glyph to get the width of
+ * @return the width of the glyph in normalized 1000 units
+ */
+ protected int getGlyphWidth(int glyph) {
+ if (glyph >= GlyphWidths.length)
+ glyph = GlyphWidths.length - 1;
+ return GlyphWidths[glyph];
+ }
+
+ private void readBbox() throws DocumentException, IOException {
+ int tableLocation[];
+ tableLocation = (int[])tables.get("head");
+ if (tableLocation == null)
+ throw new DocumentException("Table 'head' does not exist in " + fileName + style);
+ rf.seek(tableLocation[0] + TrueTypeFontSubSet.HEAD_LOCA_FORMAT_OFFSET);
+ boolean locaShortTable = (rf.readUnsignedShort() == 0);
+ tableLocation = (int[])tables.get("loca");
+ if (tableLocation == null)
+ return;
+ rf.seek(tableLocation[0]);
+ int locaTable[];
+ if (locaShortTable) {
+ int entries = tableLocation[1] / 2;
+ locaTable = new int[entries];
+ for (int k = 0; k < entries; ++k)
+ locaTable[k] = rf.readUnsignedShort() * 2;
+ }
+ else {
+ int entries = tableLocation[1] / 4;
+ locaTable = new int[entries];
+ for (int k = 0; k < entries; ++k)
+ locaTable[k] = rf.readInt();
+ }
+ tableLocation = (int[])tables.get("glyf");
+ if (tableLocation == null)
+ throw new DocumentException("Table 'glyf' does not exist in " + fileName + style);
+ int tableGlyphOffset = tableLocation[0];
+ bboxes = new int[locaTable.length - 1][];
+ for (int glyph = 0; glyph < locaTable.length - 1; ++glyph) {
+ int start = locaTable[glyph];
+ if (start != locaTable[glyph + 1]) {
+ rf.seek(tableGlyphOffset + start + 2);
+ bboxes[glyph] = new int[]{
+ (rf.readShort() * 1000) / head.unitsPerEm,
+ (rf.readShort() * 1000) / head.unitsPerEm,
+ (rf.readShort() * 1000) / head.unitsPerEm,
+ (rf.readShort() * 1000) / head.unitsPerEm};
+ }
+ }
+ }
+
+ /** Reads the several maps from the table 'cmap'. The maps of interest are 1.0 for symbolic
+ * fonts and 3.1 for all others. A symbolic font is defined as having the map 3.0.
+ * @throws DocumentException the font is invalid
+ * @throws IOException the font file could not be read
+ */
+ void readCMaps() throws DocumentException, IOException {
+ int table_location[];
+ table_location = (int[])tables.get("cmap");
+ if (table_location == null)
+ throw new DocumentException("Table 'cmap' does not exist in " + fileName + style);
+ rf.seek(table_location[0]);
+ rf.skipBytes(2);
+ int num_tables = rf.readUnsignedShort();
+ fontSpecific = false;
+ int map10 = 0;
+ int map31 = 0;
+ int map30 = 0;
+ for (int k = 0; k < num_tables; ++k) {
+ int platId = rf.readUnsignedShort();
+ int platSpecId = rf.readUnsignedShort();
+ int offset = rf.readInt();
+ if (platId == 3 && platSpecId == 0) {
+ fontSpecific = true;
+ map30 = offset;
+ }
+ else if (platId == 3 && platSpecId == 1) {
+ map31 = offset;
+ }
+ if (platId == 1 && platSpecId == 0) {
+ map10 = offset;
+ }
+ }
+ if (map10 > 0) {
+ rf.seek(table_location[0] + map10);
+ int format = rf.readUnsignedShort();
+ switch (format) {
+ case 0:
+ cmap10 = readFormat0();
+ break;
+ case 4:
+ cmap10 = readFormat4();
+ break;
+ case 6:
+ cmap10 = readFormat6();
+ break;
+ }
+ }
+ if (map31 > 0) {
+ rf.seek(table_location[0] + map31);
+ int format = rf.readUnsignedShort();
+ if (format == 4) {
+ cmap31 = readFormat4();
+ }
+ }
+ if (map30 > 0) {
+ rf.seek(table_location[0] + map30);
+ int format = rf.readUnsignedShort();
+ if (format == 4) {
+ cmap10 = readFormat4();
+ }
+ }
+ }
+
+ /** The information in the maps of the table 'cmap' is coded in several formats.
+ * Format 0 is the Apple standard character to glyph index mapping table.
+ * @return a HashMap
representing this map
+ * @throws IOException the font file could not be read
+ */
+ HashMap readFormat0() throws IOException {
+ HashMap h = new HashMap();
+ rf.skipBytes(4);
+ for (int k = 0; k < 256; ++k) {
+ int r[] = new int[2];
+ r[0] = rf.readUnsignedByte();
+ r[1] = getGlyphWidth(r[0]);
+ h.put(new Integer(k), r);
+ }
+ return h;
+ }
+
+ /** The information in the maps of the table 'cmap' is coded in several formats.
+ * Format 4 is the Microsoft standard character to glyph index mapping table.
+ * @return a HashMap
representing this map
+ * @throws IOException the font file could not be read
+ */
+ HashMap readFormat4() throws IOException {
+ HashMap h = new HashMap();
+ int table_lenght = rf.readUnsignedShort();
+ rf.skipBytes(2);
+ int segCount = rf.readUnsignedShort() / 2;
+ rf.skipBytes(6);
+ int endCount[] = new int[segCount];
+ for (int k = 0; k < segCount; ++k) {
+ endCount[k] = rf.readUnsignedShort();
+ }
+ rf.skipBytes(2);
+ int startCount[] = new int[segCount];
+ for (int k = 0; k < segCount; ++k) {
+ startCount[k] = rf.readUnsignedShort();
+ }
+ int idDelta[] = new int[segCount];
+ for (int k = 0; k < segCount; ++k) {
+ idDelta[k] = rf.readUnsignedShort();
+ }
+ int idRO[] = new int[segCount];
+ for (int k = 0; k < segCount; ++k) {
+ idRO[k] = rf.readUnsignedShort();
+ }
+ int glyphId[] = new int[table_lenght / 2 - 8 - segCount * 4];
+ for (int k = 0; k < glyphId.length; ++k) {
+ glyphId[k] = rf.readUnsignedShort();
+ }
+ for (int k = 0; k < segCount; ++k) {
+ int glyph;
+ for (int j = startCount[k]; j <= endCount[k] && j != 0xFFFF; ++j) {
+ if (idRO[k] == 0) {
+ glyph = (j + idDelta[k]) & 0xFFFF;
+ }
+ else {
+ int idx = k + idRO[k] / 2 - segCount + j - startCount[k];
+ if (idx >= glyphId.length)
+ continue;
+ glyph = (glyphId[idx] + idDelta[k]) & 0xFFFF;
+ }
+ int r[] = new int[2];
+ r[0] = glyph;
+ r[1] = getGlyphWidth(r[0]);
+ h.put(new Integer(fontSpecific ? ((j & 0xff00) == 0xf000 ? j & 0xff : j) : j), r);
+ }
+ }
+ return h;
+ }
+
+ /** The information in the maps of the table 'cmap' is coded in several formats.
+ * Format 6 is a trimmed table mapping. It is similar to format 0 but can have
+ * less than 256 entries.
+ * @return a HashMap
representing this map
+ * @throws IOException the font file could not be read
+ */
+ HashMap readFormat6() throws IOException {
+ HashMap h = new HashMap();
+ rf.skipBytes(4);
+ int start_code = rf.readUnsignedShort();
+ int code_count = rf.readUnsignedShort();
+ for (int k = 0; k < code_count; ++k) {
+ int r[] = new int[2];
+ r[0] = rf.readUnsignedShort();
+ r[1] = getGlyphWidth(r[0]);
+ h.put(new Integer(k + start_code), r);
+ }
+ return h;
+ }
+
+ /** Reads the kerning information from the 'kern' table.
+ * @throws IOException the font file could not be read
+ */
+ void readKerning() throws IOException {
+ int table_location[];
+ table_location = (int[])tables.get("kern");
+ if (table_location == null)
+ return;
+ rf.seek(table_location[0] + 2);
+ int nTables = rf.readUnsignedShort();
+ int checkpoint = table_location[0] + 4;
+ int length = 0;
+ for (int k = 0; k < nTables; ++k) {
+ checkpoint += length;
+ rf.seek(checkpoint);
+ rf.skipBytes(2);
+ length = rf.readUnsignedShort();
+ int coverage = rf.readUnsignedShort();
+ if ((coverage & 0xfff7) == 0x0001) {
+ int nPairs = rf.readUnsignedShort();
+ rf.skipBytes(6);
+ for (int j = 0; j < nPairs; ++j) {
+ int pair = rf.readInt();
+ int value = ((int)rf.readShort() * 1000) / head.unitsPerEm;
+ kerning.put(pair, value);
+ }
+ }
+ }
+ }
+
+ /** Gets the kerning between two Unicode chars.
+ * @param char1 the first char
+ * @param char2 the second char
+ * @return the kerning to be applied
+ */
+ public int getKerning(char char1, char char2) {
+ int metrics[] = getMetricsTT(char1);
+ if (metrics == null)
+ return 0;
+ int c1 = metrics[0];
+ metrics = getMetricsTT(char2);
+ if (metrics == null)
+ return 0;
+ int c2 = metrics[0];
+ return kerning.get((c1 << 16) + c2);
+ }
+
+ /** Gets the width from the font according to the unicode char c
.
+ * If the name
is null it's a symbolic font.
+ * @param c the unicode char
+ * @param name the glyph name
+ * @return the width of the char
+ */
+ int getRawWidth(int c, String name) {
+ HashMap map = null;
+ if (name == null || cmap31 == null)
+ map = cmap10;
+ else
+ map = cmap31;
+ if (map == null)
+ return 0;
+ int metric[] = (int[])map.get(new Integer(c));
+ if (metric == null)
+ return 0;
+ return metric[1];
+ }
+
+ /** Generates the font descriptor for this font.
+ * @return the PdfDictionary containing the font descriptor or null
+ * @param subsetPrefix the subset prefix
+ * @param fontStream the indirect reference to a PdfStream containing the font or null
+ * @throws DocumentException if there is an error
+ */
+ protected PdfDictionary getFontDescriptor(PdfIndirectReference fontStream, String subsetPrefix) throws DocumentException {
+ PdfDictionary dic = new PdfDictionary(PdfName.FONTDESCRIPTOR);
+ dic.put(PdfName.ASCENT, new PdfNumber((int)os_2.sTypoAscender * 1000 / head.unitsPerEm));
+ dic.put(PdfName.CAPHEIGHT, new PdfNumber((int)os_2.sCapHeight * 1000 / head.unitsPerEm));
+ dic.put(PdfName.DESCENT, new PdfNumber((int)os_2.sTypoDescender * 1000 / head.unitsPerEm));
+ dic.put(PdfName.FONTBBOX, new PdfRectangle(
+ (int)head.xMin * 1000 / head.unitsPerEm,
+ (int)head.yMin * 1000 / head.unitsPerEm,
+ (int)head.xMax * 1000 / head.unitsPerEm,
+ (int)head.yMax * 1000 / head.unitsPerEm));
+ if (cff) {
+ if (encoding.startsWith("Identity-"))
+ dic.put(PdfName.FONTNAME, new PdfName(subsetPrefix + fontName+"-"+encoding));
+ else
+ dic.put(PdfName.FONTNAME, new PdfName(subsetPrefix + fontName + style));
+ }
+ else
+ dic.put(PdfName.FONTNAME, new PdfName(subsetPrefix + fontName + style));
+ dic.put(PdfName.ITALICANGLE, new PdfNumber(italicAngle));
+ dic.put(PdfName.STEMV, new PdfNumber(80));
+ if (fontStream != null) {
+ if (cff)
+ dic.put(PdfName.FONTFILE3, fontStream);
+ else
+ dic.put(PdfName.FONTFILE2, fontStream);
+ }
+ int flags = 0;
+ if (isFixedPitch)
+ flags |= 1;
+ flags |= fontSpecific ? 4 : 32;
+ if ((head.macStyle & 2) != 0)
+ flags |= 64;
+ if ((head.macStyle & 1) != 0)
+ flags |= 262144;
+ dic.put(PdfName.FLAGS, new PdfNumber(flags));
+
+ return dic;
+ }
+
+ /** Generates the font dictionary for this font.
+ * @return the PdfDictionary containing the font dictionary
+ * @param subsetPrefix the subset prefx
+ * @param firstChar the first valid character
+ * @param lastChar the last valid character
+ * @param shortTag a 256 bytes long byte
array where each unused byte is represented by 0
+ * @param fontDescriptor the indirect reference to a PdfDictionary containing the font descriptor or null
+ * @throws DocumentException if there is an error
+ */
+ protected PdfDictionary getFontBaseType(PdfIndirectReference fontDescriptor, String subsetPrefix, int firstChar, int lastChar, byte shortTag[]) throws DocumentException {
+ PdfDictionary dic = new PdfDictionary(PdfName.FONT);
+ if (cff) {
+ dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
+ dic.put(PdfName.BASEFONT, new PdfName(fontName + style));
+ }
+ else {
+ dic.put(PdfName.SUBTYPE, PdfName.TRUETYPE);
+ dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName + style));
+ }
+ dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName + style));
+ if (!fontSpecific) {
+ for (int k = firstChar; k <= lastChar; ++k) {
+ if (!differences[k].equals(notdef)) {
+ firstChar = k;
+ break;
+ }
+ }
+ if (encoding.equals("Cp1252") || encoding.equals("MacRoman"))
+ dic.put(PdfName.ENCODING, encoding.equals("Cp1252") ? PdfName.WIN_ANSI_ENCODING : PdfName.MAC_ROMAN_ENCODING);
+ else {
+ PdfDictionary enc = new PdfDictionary(PdfName.ENCODING);
+ PdfArray dif = new PdfArray();
+ boolean gap = true;
+ for (int k = firstChar; k <= lastChar; ++k) {
+ if (shortTag[k] != 0) {
+ if (gap) {
+ dif.add(new PdfNumber(k));
+ gap = false;
+ }
+ dif.add(new PdfName(differences[k]));
+ }
+ else
+ gap = true;
+ }
+ enc.put(PdfName.DIFFERENCES, dif);
+ dic.put(PdfName.ENCODING, enc);
+ }
+ }
+ dic.put(PdfName.FIRSTCHAR, new PdfNumber(firstChar));
+ dic.put(PdfName.LASTCHAR, new PdfNumber(lastChar));
+ PdfArray wd = new PdfArray();
+ for (int k = firstChar; k <= lastChar; ++k) {
+ if (shortTag[k] == 0)
+ wd.add(new PdfNumber(0));
+ else
+ wd.add(new PdfNumber(widths[k]));
+ }
+ dic.put(PdfName.WIDTHS, wd);
+ if (fontDescriptor != null)
+ dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
+ return dic;
+ }
+
+ private byte[] getFullFont() throws IOException {
+ RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf);
+ rf2.reOpen();
+ byte b[] = new byte[rf2.length()];
+ rf2.readFully(b);
+ rf2.close();
+ return b;
+ }
+
+ /** Outputs to the writer the font dictionaries and streams.
+ * @param writer the writer for this document
+ * @param ref the font indirect reference
+ * @param params several parameters that depend on the font type
+ * @throws IOException on error
+ * @throws DocumentException error in generating the object
+ */
+ void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
+ int firstChar = ((Integer)params[0]).intValue();
+ int lastChar = ((Integer)params[1]).intValue();
+ byte shortTag[] = (byte[])params[2];
+ if (!subset) {
+ firstChar = 0;
+ lastChar = shortTag.length - 1;
+ for (int k = 0; k < shortTag.length; ++k)
+ shortTag[k] = 1;
+ }
+ PdfIndirectReference ind_font = null;
+ PdfObject pobj = null;
+ PdfIndirectObject obj = null;
+ String subsetPrefix = "";
+ if (embedded) {
+ if (cff) {
+ RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf);
+ byte b[] = new byte[cffLength];
+ try {
+ rf2.reOpen();
+ rf2.seek(cffOffset);
+ rf2.readFully(b);
+ }
+ finally {
+ try {
+ rf2.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ pobj = new StreamFont(b, "Type1C");
+ obj = writer.addToBody(pobj);
+ ind_font = obj.getIndirectReference();
+ }
+ else {
+ if (subset)
+ subsetPrefix = createSubsetPrefix();
+ HashMap glyphs = new HashMap();
+ for (int k = firstChar; k <= lastChar; ++k) {
+ if (shortTag[k] != 0) {
+ int metrics[];
+ if (fontSpecific)
+ metrics = getMetricsTT(k);
+ else
+ metrics = getMetricsTT(unicodeDifferences[k]);
+ if (metrics != null)
+ glyphs.put(new Integer(metrics[0]), null);
+ }
+ }
+ TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, new RandomAccessFileOrArray(rf), glyphs, directoryOffset, true);
+ byte b[] = sb.process();
+ int lengths[] = new int[]{b.length};
+ pobj = new StreamFont(b, lengths);
+ obj = writer.addToBody(pobj);
+ ind_font = obj.getIndirectReference();
+ }
+ }
+ pobj = getFontDescriptor(ind_font, subsetPrefix);
+ if (pobj != null){
+ obj = writer.addToBody(pobj);
+ ind_font = obj.getIndirectReference();
+ }
+ pobj = getFontBaseType(ind_font, subsetPrefix, firstChar, lastChar, shortTag);
+ writer.addToBody(pobj, ref);
+ }
+
+ /** Gets the font parameter identified by key
. Valid values
+ * for key
are ASCENT
, CAPHEIGHT
, DESCENT
+ * and ITALICANGLE
.
+ * @param key the parameter to be extracted
+ * @param fontSize the font size in points
+ * @return the parameter in points
+ */
+ public float getFontDescriptor(int key, float fontSize) {
+ switch (key) {
+ case ASCENT:
+ return (float)os_2.sTypoAscender * fontSize / (float)head.unitsPerEm;
+ case CAPHEIGHT:
+ return (float)os_2.sCapHeight * fontSize / (float)head.unitsPerEm;
+ case DESCENT:
+ return (float)os_2.sTypoDescender * fontSize / (float)head.unitsPerEm;
+ case ITALICANGLE:
+ return (float)italicAngle;
+ case BBOXLLX:
+ return fontSize * (int)head.xMin / head.unitsPerEm;
+ case BBOXLLY:
+ return fontSize * (int)head.yMin / head.unitsPerEm;
+ case BBOXURX:
+ return fontSize * (int)head.xMax / head.unitsPerEm;
+ case BBOXURY:
+ return fontSize * (int)head.yMax / head.unitsPerEm;
+ case AWT_ASCENT:
+ return fontSize * (int)hhea.Ascender / head.unitsPerEm;
+ case AWT_DESCENT:
+ return fontSize * (int)hhea.Descender / head.unitsPerEm;
+ case AWT_LEADING:
+ return fontSize * (int)hhea.LineGap / head.unitsPerEm;
+ case AWT_MAXADVANCE:
+ return fontSize * (int)hhea.advanceWidthMax / head.unitsPerEm;
+ }
+ return 0;
+ }
+
+ /** Gets the glyph index and metrics for a character.
+ * @param c the character
+ * @return an int
array with {glyph index, width}
+ */
+ public int[] getMetricsTT(int c) {
+ if (!fontSpecific && cmap31 != null)
+ return (int[])cmap31.get(new Integer(c));
+ if (fontSpecific && cmap10 != null)
+ return (int[])cmap10.get(new Integer(c));
+ if (cmap31 != null)
+ return (int[])cmap31.get(new Integer(c));
+ if (cmap10 != null)
+ return (int[])cmap10.get(new Integer(c));
+ return null;
+ }
+
+ /** Gets the postscript font name.
+ * @return the postscript font name
+ */
+ public String getPostscriptFontName() {
+ return fontName;
+ }
+
+ /** Gets the code pages supported by the font.
+ * @return the code pages supported by the font
+ */
+ public String[] getCodePagesSupported() {
+ long cp = (((long)os_2.ulCodePageRange2) << 32) + ((long)os_2.ulCodePageRange1 & 0xffffffffL);
+ int count = 0;
+ long bit = 1;
+ for (int k = 0; k < 64; ++k) {
+ if ((cp & bit) != 0 && codePages[k] != null)
+ ++count;
+ bit <<= 1;
+ }
+ String ret[] = new String[count];
+ count = 0;
+ bit = 1;
+ for (int k = 0; k < 64; ++k) {
+ if ((cp & bit) != 0 && codePages[k] != null)
+ ret[count++] = codePages[k];
+ bit <<= 1;
+ }
+ return ret;
+ }
+
+ /** Gets the full name of the font. If it is a True Type font
+ * each array element will have {Platform ID, Platform Encoding ID,
+ * Language ID, font name}. The interpretation of this values can be
+ * found in the Open Type specification, chapter 2, in the 'name' table.
+ * For the other fonts the array has a single element with {"", "", "",
+ * font name}.
+ * @return the full name of the font
+ */
+ public String[][] getFullFontName() {
+ return fullName;
+ }
+
+ /** Gets the family name of the font. If it is a True Type font
+ * each array element will have {Platform ID, Platform Encoding ID,
+ * Language ID, font name}. The interpretation of this values can be
+ * found in the Open Type specification, chapter 2, in the 'name' table.
+ * For the other fonts the array has a single element with {"", "", "",
+ * font name}.
+ * @return the family name of the font
+ */
+ public String[][] getFamilyFontName() {
+ return familyName;
+ }
+
+ /** Checks if the font has any kerning pairs.
+ * @return true
if the font has any kerning pairs
+ */
+ public boolean hasKernPairs() {
+ return kerning.size() > 0;
+ }
+
+ /**
+ * Sets the font name that will appear in the pdf font dictionary.
+ * Use with care as it can easily make a font unreadable if not embedded.
+ * @param name the new font name
+ */
+ public void setPostscriptFontName(String name) {
+ fontName = name;
+ }
+
+ /**
+ * Sets the kerning between two Unicode chars.
+ * @param char1 the first char
+ * @param char2 the second char
+ * @param kern the kerning to apply in normalized 1000 units
+ * @return true
if the kerning was applied, false
otherwise
+ */
+ public boolean setKerning(char char1, char char2, int kern) {
+ int metrics[] = getMetricsTT(char1);
+ if (metrics == null)
+ return false;
+ int c1 = metrics[0];
+ metrics = getMetricsTT(char2);
+ if (metrics == null)
+ return false;
+ int c2 = metrics[0];
+ kerning.put((c1 << 16) + c2, kern);
+ return true;
+ }
+
+ protected int[] getRawCharBBox(int c, String name) {
+ HashMap map = null;
+ if (name == null || cmap31 == null)
+ map = cmap10;
+ else
+ map = cmap31;
+ if (map == null)
+ return null;
+ int metric[] = (int[])map.get(new Integer(c));
+ if (metric == null || bboxes == null)
+ return null;
+ return bboxes[metric[0]];
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/TrueTypeFontSubSet.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/TrueTypeFontSubSet.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/TrueTypeFontSubSet.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/TrueTypeFontSubSet.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,410 @@
+/*
+ * $Id: TrueTypeFontSubSet.java,v 1.15 2002/07/09 11:28:24 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.ExceptionConverter;
+
+/** Subsets a True Type font by removing the unneeded glyphs from
+ * the font.
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+class TrueTypeFontSubSet {
+ static final String tableNamesSimple[] = {"cvt ", "fpgm", "glyf", "head",
+ "hhea", "hmtx", "loca", "maxp", "prep"};
+ static final String tableNamesCmap[] = {"cmap", "cvt ", "fpgm", "glyf", "head",
+ "hhea", "hmtx", "loca", "maxp", "prep"};
+ static final int entrySelectors[] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4};
+ static final int TABLE_CHECKSUM = 0;
+ static final int TABLE_OFFSET = 1;
+ static final int TABLE_LENGTH = 2;
+ static final int HEAD_LOCA_FORMAT_OFFSET = 51;
+
+ static final int ARG_1_AND_2_ARE_WORDS = 1;
+ static final int WE_HAVE_A_SCALE = 8;
+ static final int MORE_COMPONENTS = 32;
+ static final int WE_HAVE_AN_X_AND_Y_SCALE = 64;
+ static final int WE_HAVE_A_TWO_BY_TWO = 128;
+
+
+ /** Contains the location of the several tables. The key is the name of
+ * the table and the value is an int[3]
where position 0
+ * is the checksum, position 1 is the offset from the start of the file
+ * and position 2 is the length of the table.
+ */
+ protected HashMap tableDirectory;
+ /** The file in use.
+ */
+ protected RandomAccessFileOrArray rf;
+ /** The file name.
+ */
+ protected String fileName;
+ protected boolean includeCmap;
+ protected boolean locaShortTable;
+ protected int locaTable[];
+ protected HashMap glyphsUsed;
+ protected ArrayList glyphsInList;
+ protected int tableGlyphOffset;
+ protected int newLocaTable[];
+ protected byte newLocaTableOut[];
+ protected byte newGlyfTable[];
+ protected int glyfTableRealSize;
+ protected int locaTableRealSize;
+ protected byte outFont[];
+ protected int fontPtr;
+ protected int directoryOffset;
+
+ /** Creates a new TrueTypeFontSubSet
+ * @param directoryOffset The offset from the start of the file to the table directory
+ * @param fileName the file name of the font
+ * @param glyphsUsed the glyphs used
+ * @param includeCmap true
if the table cmap is to be included in the generated font
+ */
+ TrueTypeFontSubSet(String fileName, RandomAccessFileOrArray rf, HashMap glyphsUsed, int directoryOffset, boolean includeCmap) {
+ this.fileName = fileName;
+ this.rf = rf;
+ this.glyphsUsed = glyphsUsed;
+ this.includeCmap = includeCmap;
+ this.directoryOffset = directoryOffset;
+ glyphsInList = new ArrayList(glyphsUsed.keySet());
+ }
+
+ /** Does the actual work of subsetting the font.
+ * @throws IOException on error
+ * @throws DocumentException on error
+ * @return the subset font
+ */
+ byte[] process() throws IOException, DocumentException {
+ try {
+ rf.reOpen();
+ createTableDirectory();
+ readLoca();
+ flatGlyphs();
+ createNewGlyphTables();
+ locaTobytes();
+ assembleFont();
+ return outFont;
+ }
+ finally {
+ try {
+ rf.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ }
+
+ protected void assembleFont() throws IOException, DocumentException {
+ int tableLocation[];
+ int fullFontSize = 0;
+ String tableNames[];
+ if (includeCmap)
+ tableNames = tableNamesCmap;
+ else
+ tableNames = tableNamesSimple;
+ int tablesUsed = 2;
+ int len = 0;
+ for (int k = 0; k < tableNames.length; ++k) {
+ String name = tableNames[k];
+ if (name.equals("glyf") || name.equals("loca"))
+ continue;
+ tableLocation = (int[])tableDirectory.get(name);
+ if (tableLocation == null)
+ continue;
+ ++tablesUsed;
+ fullFontSize += (tableLocation[TABLE_LENGTH] + 3) & (~3);
+ }
+ fullFontSize += newLocaTableOut.length;
+ fullFontSize += newGlyfTable.length;
+ int ref = 16 * tablesUsed + 12;
+ fullFontSize += ref;
+ outFont = new byte[fullFontSize];
+ fontPtr = 0;
+ writeFontInt(0x00010000);
+ writeFontShort(tablesUsed);
+ int selector = entrySelectors[tablesUsed];
+ writeFontShort((1 << selector) * 16);
+ writeFontShort(selector);
+ writeFontShort((tablesUsed - (1 << selector)) * 16);
+ for (int k = 0; k < tableNames.length; ++k) {
+ String name = tableNames[k];
+ tableLocation = (int[])tableDirectory.get(name);
+ if (tableLocation == null)
+ continue;
+ writeFontString(name);
+ if (name.equals("glyf")) {
+ writeFontInt(calculateChecksum(newGlyfTable));
+ len = glyfTableRealSize;
+ }
+ else if (name.equals("loca")) {
+ writeFontInt(calculateChecksum(newLocaTableOut));
+ len = locaTableRealSize;
+ }
+ else {
+ writeFontInt(tableLocation[TABLE_CHECKSUM]);
+ len = tableLocation[TABLE_LENGTH];
+ }
+ writeFontInt(ref);
+ writeFontInt(len);
+ ref += (len + 3) & (~3);
+ }
+ for (int k = 0; k < tableNames.length; ++k) {
+ String name = tableNames[k];
+ tableLocation = (int[])tableDirectory.get(name);
+ if (tableLocation == null)
+ continue;
+ if (name.equals("glyf")) {
+ System.arraycopy(newGlyfTable, 0, outFont, fontPtr, newGlyfTable.length);
+ fontPtr += newGlyfTable.length;
+ newGlyfTable = null;
+ }
+ else if (name.equals("loca")) {
+ System.arraycopy(newLocaTableOut, 0, outFont, fontPtr, newLocaTableOut.length);
+ fontPtr += newLocaTableOut.length;
+ newLocaTableOut = null;
+ }
+ else {
+ rf.seek(tableLocation[TABLE_OFFSET]);
+ rf.readFully(outFont, fontPtr, tableLocation[TABLE_LENGTH]);
+ fontPtr += (tableLocation[TABLE_LENGTH] + 3) & (~3);
+ }
+ }
+ }
+
+ protected void createTableDirectory() throws IOException, DocumentException {
+ tableDirectory = new HashMap();
+ rf.seek(directoryOffset);
+ int id = rf.readInt();
+ if (id != 0x00010000)
+ throw new DocumentException(fileName + " is not a true type file.");
+ int num_tables = rf.readUnsignedShort();
+ rf.skipBytes(6);
+ for (int k = 0; k < num_tables; ++k) {
+ String tag = readStandardString(4);
+ int tableLocation[] = new int[3];
+ tableLocation[TABLE_CHECKSUM] = rf.readInt();
+ tableLocation[TABLE_OFFSET] = rf.readInt();
+ tableLocation[TABLE_LENGTH] = rf.readInt();
+ tableDirectory.put(tag, tableLocation);
+ }
+ }
+
+ protected void readLoca() throws IOException, DocumentException {
+ int tableLocation[];
+ tableLocation = (int[])tableDirectory.get("head");
+ if (tableLocation == null)
+ throw new DocumentException("Table 'head' does not exist in " + fileName);
+ rf.seek(tableLocation[TABLE_OFFSET] + HEAD_LOCA_FORMAT_OFFSET);
+ locaShortTable = (rf.readUnsignedShort() == 0);
+ tableLocation = (int[])tableDirectory.get("loca");
+ if (tableLocation == null)
+ throw new DocumentException("Table 'loca' does not exist in " + fileName);
+ rf.seek(tableLocation[TABLE_OFFSET]);
+ if (locaShortTable) {
+ int entries = tableLocation[TABLE_LENGTH] / 2;
+ locaTable = new int[entries];
+ for (int k = 0; k < entries; ++k)
+ locaTable[k] = rf.readUnsignedShort() * 2;
+ }
+ else {
+ int entries = tableLocation[TABLE_LENGTH] / 4;
+ locaTable = new int[entries];
+ for (int k = 0; k < entries; ++k)
+ locaTable[k] = rf.readInt();
+ }
+ }
+
+ protected void createNewGlyphTables() throws IOException {
+ newLocaTable = new int[locaTable.length];
+ int activeGlyphs[] = new int[glyphsInList.size()];
+ for (int k = 0; k < activeGlyphs.length; ++k)
+ activeGlyphs[k] = ((Integer)glyphsInList.get(k)).intValue();
+ Arrays.sort(activeGlyphs);
+ int glyfSize = 0;
+ for (int k = 0; k < activeGlyphs.length; ++k) {
+ int glyph = activeGlyphs[k];
+ glyfSize += locaTable[glyph + 1] - locaTable[glyph];
+ }
+ glyfTableRealSize = glyfSize;
+ glyfSize = (glyfSize + 3) & (~3);
+ newGlyfTable = new byte[glyfSize];
+ int glyfPtr = 0;
+ int listGlyf = 0;
+ for (int k = 0; k < newLocaTable.length; ++k) {
+ newLocaTable[k] = glyfPtr;
+ if (listGlyf < activeGlyphs.length && activeGlyphs[listGlyf] == k) {
+ ++listGlyf;
+ newLocaTable[k] = glyfPtr;
+ int start = locaTable[k];
+ int len = locaTable[k + 1] - start;
+ if (len > 0) {
+ rf.seek(tableGlyphOffset + start);
+ rf.readFully(newGlyfTable, glyfPtr, len);
+ glyfPtr += len;
+ }
+ }
+ }
+ }
+
+ protected void locaTobytes() {
+ if (locaShortTable)
+ locaTableRealSize = newLocaTable.length * 2;
+ else
+ locaTableRealSize = newLocaTable.length * 4;
+ newLocaTableOut = new byte[(locaTableRealSize + 3) & (~3)];
+ outFont = newLocaTableOut;
+ fontPtr = 0;
+ for (int k = 0; k < newLocaTable.length; ++k) {
+ if (locaShortTable)
+ writeFontShort(newLocaTable[k] / 2);
+ else
+ writeFontInt(newLocaTable[k]);
+ }
+
+ }
+
+ protected void flatGlyphs() throws IOException, DocumentException {
+ int tableLocation[];
+ tableLocation = (int[])tableDirectory.get("glyf");
+ if (tableLocation == null)
+ throw new DocumentException("Table 'glyf' does not exist in " + fileName);
+ Integer glyph0 = new Integer(0);
+ if (!glyphsUsed.containsKey(glyph0)) {
+ glyphsUsed.put(glyph0, null);
+ glyphsInList.add(glyph0);
+ }
+ tableGlyphOffset = tableLocation[TABLE_OFFSET];
+ for (int k = 0; k < glyphsInList.size(); ++k) {
+ int glyph = ((Integer)glyphsInList.get(k)).intValue();
+ checkGlyphComposite(glyph);
+ }
+ }
+
+ protected void checkGlyphComposite(int glyph) throws IOException {
+ int start = locaTable[glyph];
+ if (start == locaTable[glyph + 1]) // no contour
+ return;
+ rf.seek(tableGlyphOffset + start);
+ int numContours = rf.readShort();
+ if (numContours >= 0)
+ return;
+ rf.skipBytes(8);
+ for(;;) {
+ int flags = rf.readUnsignedShort();
+ Integer cGlyph = new Integer(rf.readUnsignedShort());
+ if (!glyphsUsed.containsKey(cGlyph)) {
+ glyphsUsed.put(cGlyph, null);
+ glyphsInList.add(cGlyph);
+ }
+ if ((flags & MORE_COMPONENTS) == 0)
+ return;
+ int skip;
+ if ((flags & ARG_1_AND_2_ARE_WORDS) != 0)
+ skip = 4;
+ else
+ skip = 2;
+ if ((flags & WE_HAVE_A_SCALE) != 0)
+ skip += 2;
+ else if ((flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0)
+ skip += 4;
+ if ((flags & WE_HAVE_A_TWO_BY_TWO) != 0)
+ skip += 8;
+ rf.skipBytes(skip);
+ }
+ }
+
+ /** Reads a String
from the font file as bytes using the Cp1252
+ * encoding.
+ * @param length the length of bytes to read
+ * @return the String
read
+ * @throws IOException the font file could not be read
+ */
+ protected String readStandardString(int length) throws IOException {
+ byte buf[] = new byte[length];
+ rf.readFully(buf);
+ try {
+ return new String(buf, BaseFont.WINANSI);
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ protected void writeFontShort(int n) {
+ outFont[fontPtr++] = (byte)(n >> 8);
+ outFont[fontPtr++] = (byte)(n);
+ }
+
+ protected void writeFontInt(int n) {
+ outFont[fontPtr++] = (byte)(n >> 24);
+ outFont[fontPtr++] = (byte)(n >> 16);
+ outFont[fontPtr++] = (byte)(n >> 8);
+ outFont[fontPtr++] = (byte)(n);
+ }
+
+ protected void writeFontString(String s) {
+ byte b[] = PdfEncodings.convertToBytes(s, BaseFont.WINANSI);
+ System.arraycopy(b, 0, outFont, fontPtr, b.length);
+ fontPtr += b.length;
+ }
+
+ protected int calculateChecksum(byte b[]) {
+ int len = b.length / 4;
+ int v0 = 0;
+ int v1 = 0;
+ int v2 = 0;
+ int v3 = 0;
+ int ptr = 0;
+ for (int k = 0; k < len; ++k) {
+ v3 += (int)b[ptr++] & 0xff;
+ v2 += (int)b[ptr++] & 0xff;
+ v1 += (int)b[ptr++] & 0xff;
+ v0 += (int)b[ptr++] & 0xff;
+ }
+ return v0 + (v1 << 8) + (v2 << 16) + (v3 << 24);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/TrueTypeFontUnicode.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/TrueTypeFontUnicode.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/TrueTypeFontUnicode.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/TrueTypeFontUnicode.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,469 @@
+/*
+ * $Id: TrueTypeFontUnicode.java,v 1.3 2003/11/17 12:53:06 stoledo Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+
+import pdftk.com.lowagie.text.DocumentException;
+/** Represents a True Type font with Unicode encoding. All the character
+ * in the font can be used directly by using the encoding Identity-H or
+ * Identity-V. This is the only way to represent some character sets such
+ * as Thai.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+class TrueTypeFontUnicode extends TrueTypeFont implements Comparator{
+
+ /** true
if the encoding is vertical.
+ */
+ boolean vertical = false;
+
+ /** Creates a new TrueType font addressed by Unicode characters. The font
+ * will always be embedded.
+ * @param ttFile the location of the font on file. The file must end in '.ttf'.
+ * The modifiers after the name are ignored.
+ * @param enc the encoding to be applied to this font
+ * @param emb true if the font is to be embedded in the PDF
+ * @param ttfAfm the font as a byte
array
+ * @throws DocumentException the font is invalid
+ * @throws IOException the font file could not be read
+ */
+ TrueTypeFontUnicode(String ttFile, String enc, boolean emb, byte ttfAfm[]) throws DocumentException, IOException {
+ String nameBase = getBaseName(ttFile);
+ String ttcName = getTTCName(nameBase);
+ if (nameBase.length() < ttFile.length()) {
+ style = ttFile.substring(nameBase.length());
+ }
+ encoding = enc;
+ embedded = emb;
+ fileName = ttcName;
+ ttcIndex = "";
+ if (ttcName.length() < nameBase.length())
+ ttcIndex = nameBase.substring(ttcName.length() + 1);
+ fontType = FONT_TYPE_TTUNI;
+ if ((fileName.toLowerCase().endsWith(".ttf") || fileName.toLowerCase().endsWith(".otf") || fileName.toLowerCase().endsWith(".ttc")) && ((enc.equals(IDENTITY_H) || enc.equals(IDENTITY_V)) && emb)) {
+ process(ttfAfm);
+ if (os_2.fsType == 2)
+ throw new DocumentException(fileName + style + " cannot be embedded due to licensing restrictions.");
+ // Sivan
+ if ((cmap31 == null && !fontSpecific) || (cmap10 == null && fontSpecific))
+ directTextToByte=true;
+ //throw new DocumentException(fileName + " " + style + " does not contain an usable cmap.");
+ if (fontSpecific) {
+ fontSpecific = false;
+ String tempEncoding = encoding;
+ encoding = "";
+ createEncoding();
+ encoding = tempEncoding;
+ fontSpecific = true;
+ }
+ }
+ else
+ throw new DocumentException(fileName + " " + style + " is not a TTF font file.");
+ vertical = enc.endsWith("V");
+ }
+
+/**
+ * Gets the width of a String
in normalized 1000 units.
+ * @param text the String
to get the witdth of
+ * @return the width in normalized 1000 units
+ */
+ public int getWidth(String text)
+ {
+ if (vertical)
+ return text.length() * 1000;
+ int total = 0;
+ if (fontSpecific) {
+ char cc[] = text.toCharArray();
+ int len = cc.length;
+ for (int k = 0; k < len; ++k) {
+ char c = cc[k];
+ if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
+ total += getRawWidth(c & 0xff, null);
+ }
+ }
+ else {
+ int len = text.length();
+ for (int k = 0; k < len; ++k)
+ total += getRawWidth(text.charAt(k), encoding);
+ }
+ return total;
+ }
+
+ /** Creates a ToUnicode CMap to allow copy and paste from Acrobat.
+ * @param metrics metrics[0] contains the glyph index and metrics[2]
+ * contains the Unicode code
+ * @throws DocumentException on error
+ * @return the stream representing this CMap or null
+ */
+ private PdfStream getToUnicode(Object metrics[]) throws DocumentException {
+ if (metrics.length == 0)
+ return null;
+ StringBuffer buf = new StringBuffer(
+ "/CIDInit /ProcSet findresource begin\n" +
+ "12 dict begin\n" +
+ "begincmap\n" +
+ "/CIDSystemInfo\n" +
+ "<< /Registry (Adobe)\n" +
+ "/Ordering (UCS)\n" +
+ "/Supplement 0\n" +
+ ">> def\n" +
+ "/CMapName /Adobe-Identity-UCS def\n" +
+ "/CMapType 2 def\n" +
+ "1 begincodespacerange\n" +
+ toHex(((int[])metrics[0])[0]) + toHex(((int[])metrics[metrics.length - 1])[0]) + "\n" +
+ "endcodespacerange\n");
+ int size = 0;
+ for (int k = 0; k < metrics.length; ++k) {
+ if (size == 0) {
+ if (k != 0) {
+ buf.append("endbfrange\n");
+ }
+ size = Math.min(100, metrics.length - k);
+ buf.append(size).append(" beginbfrange\n");
+ }
+ --size;
+ int metric[] = (int[])metrics[k];
+ String fromTo = toHex(metric[0]);
+ buf.append(fromTo).append(fromTo).append(toHex(metric[2])).append("\n");
+ }
+ buf.append(
+ "endbfrange\n" +
+ "endcmap\n" +
+ "CMapName currentdict /CMap defineresource pop\n" +
+ "end end\n");
+ String s = buf.toString();
+ PdfStream stream = new PdfStream(PdfEncodings.convertToBytes(s, null));
+ stream.flateCompress();
+ return stream;
+ }
+
+ /** Gets an hex string in the format "<HHHH>".
+ * @param n the number
+ * @return the hex string
+ */
+ static String toHex(int n) {
+ String s = Integer.toHexString(n);
+ return "<0000".substring(0, 5 - s.length()) + s + ">";
+ }
+
+ /** Generates the CIDFontTyte2 dictionary.
+ * @param fontDescriptor the indirect reference to the font descriptor
+ * @param subsetPrefix the subset prefix
+ * @param metrics the horizontal width metrics
+ * @return a stream
+ */
+ private PdfDictionary getCIDFontType2(PdfIndirectReference fontDescriptor, String subsetPrefix, Object metrics[]) {
+ PdfDictionary dic = new PdfDictionary(PdfName.FONT);
+ // sivan; cff
+ if (cff) {
+ dic.put(PdfName.SUBTYPE, PdfName.CIDFONTTYPE0);
+ dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix+fontName+"-"+encoding));
+ }
+ else {
+ dic.put(PdfName.SUBTYPE, PdfName.CIDFONTTYPE2);
+ dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName));
+ }
+ dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
+ if (!cff)
+ dic.put(PdfName.CIDTOGIDMAP,PdfName.IDENTITY);
+ PdfDictionary cdic = new PdfDictionary();
+ cdic.put(PdfName.REGISTRY, new PdfString("Adobe"));
+ cdic.put(PdfName.ORDERING, new PdfString("Identity"));
+ cdic.put(PdfName.SUPPLEMENT, new PdfNumber(0));
+ dic.put(PdfName.CIDSYSTEMINFO, cdic);
+ if (!vertical) {
+ dic.put(PdfName.DW, new PdfNumber(1000));
+ StringBuffer buf = new StringBuffer("[");
+ int lastNumber = -10;
+ boolean firstTime = true;
+ for (int k = 0; k < metrics.length; ++k) {
+ int metric[] = (int[])metrics[k];
+ if (metric[1] == 1000)
+ continue;
+ int m = metric[0];
+ if (m == lastNumber + 1) {
+ buf.append(" ").append(metric[1]);
+ }
+ else {
+ if (!firstTime) {
+ buf.append("]");
+ }
+ firstTime = false;
+ buf.append(m).append("[").append(metric[1]);
+ }
+ lastNumber = m;
+ }
+ if (buf.length() > 1) {
+ buf.append("]]");
+ dic.put(PdfName.W, new PdfLiteral(buf.toString()));
+ }
+ }
+ return dic;
+ }
+
+ /** Generates the font dictionary.
+ * @param descendant the descendant dictionary
+ * @param subsetPrefix the subset prefix
+ * @param toUnicode the ToUnicode stream
+ * @return the stream
+ */
+ private PdfDictionary getFontBaseType(PdfIndirectReference descendant, String subsetPrefix, PdfIndirectReference toUnicode) {
+ PdfDictionary dic = new PdfDictionary(PdfName.FONT);
+
+ dic.put(PdfName.SUBTYPE, PdfName.TYPE0);
+ // The PDF Reference manual advises to add -encoding to CID font names
+ if (cff)
+ dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix+fontName+"-"+encoding));
+ //dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix+fontName));
+ else
+ dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName));
+ //dic.put(PdfName.BASEFONT, new PdfName(fontName));
+ dic.put(PdfName.ENCODING, new PdfName(encoding));
+ dic.put(PdfName.DESCENDANTFONTS, new PdfArray(descendant));
+ if (toUnicode != null)
+ dic.put(PdfName.TOUNICODE, toUnicode);
+ return dic;
+ }
+
+ /** The method used to sort the metrics array.
+ * @param o1 the first element
+ * @param o2 the second element
+ * @return the comparisation
+ */
+ public int compare(Object o1, Object o2) {
+ int m1 = ((int[])o1)[0];
+ int m2 = ((int[])o2)[0];
+ if (m1 < m2)
+ return -1;
+ if (m1 == m2)
+ return 0;
+ return 1;
+ }
+
+ /** Outputs to the writer the font dictionaries and streams.
+ * @param writer the writer for this document
+ * @param ref the font indirect reference
+ * @param params several parameters that depend on the font type
+ * @throws IOException on error
+ * @throws DocumentException error in generating the object
+ */
+ void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
+ HashMap longTag = (HashMap)params[0];
+ Object metrics[] = longTag.values().toArray();
+ Arrays.sort(metrics, this);
+ PdfIndirectReference ind_font = null;
+ PdfObject pobj = null;
+ PdfIndirectObject obj = null;
+ // sivan: cff
+ if (cff) {
+ RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf);
+ byte b[] = new byte[cffLength];
+ try {
+ rf2.reOpen();
+ rf2.seek(cffOffset);
+ rf2.readFully(b);
+ } finally {
+ try {
+ rf2.close();
+ } catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ /*
+ CFFFont cffFont = new CFFFont(new RandomAccessFileOrArray(b));
+ // test if we can find the font by name and if it's a type1 CFF
+ if (cffFont.exists(fontName) && !cffFont.isCID(fontName)) {
+ byte[] cid = cffFont.getCID( (cffFont.getNames())[0] );
+ if (cid != null) b=cid;
+ }
+
+ */
+
+ CFFFontSubset cff = new CFFFontSubset(new RandomAccessFileOrArray(b),longTag);
+ b = cff.Process( (cff.getNames())[0] );
+
+ // if the font is already CID, or not found by name, or
+ // getCID returned null, we just use the data in the CFF
+ // table and hope for the best.
+
+
+ // for debugging, force a reparsing
+ /*
+ java.lang.System.err.println("");
+ java.lang.System.err.println("");
+ java.lang.System.err.println("");
+ CFFFont dummy = new CFFFont(java.nio.ByteBuffer.wrap(b));
+ java.lang.System.err.println("");
+ java.lang.System.err.println("");
+ java.lang.System.err.println("");
+ */
+ pobj = new StreamFont(b, "CIDFontType0C");
+ obj = writer.addToBody(pobj);
+ ind_font = obj.getIndirectReference();
+ } else {
+ byte[] b;
+ if (subset || directoryOffset != 0) {
+ TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, new RandomAccessFileOrArray(rf), longTag, directoryOffset, false);
+ b = sb.process();
+ }
+ else {
+ RandomAccessFileOrArray r = new RandomAccessFileOrArray(rf);
+ b = new byte[r.length()];
+ r.readFully(b);
+ }
+ int lengths[] = new int[]{b.length};
+ pobj = new StreamFont(b, lengths);
+ obj = writer.addToBody(pobj);
+ ind_font = obj.getIndirectReference();
+ }
+ String subsetPrefix = createSubsetPrefix();
+ //if (cff) subsetPrefix = "";
+ PdfDictionary dic = getFontDescriptor(ind_font, subsetPrefix);
+ obj = writer.addToBody(dic);
+ ind_font = obj.getIndirectReference();
+
+ pobj = getCIDFontType2(ind_font, subsetPrefix, metrics);
+ obj = writer.addToBody(pobj);
+ ind_font = obj.getIndirectReference();
+
+ pobj = getToUnicode(metrics);
+ PdfIndirectReference toUnicodeRef = null;
+
+ if (pobj != null) {
+ obj = writer.addToBody(pobj);
+ toUnicodeRef = obj.getIndirectReference();
+ }
+
+ pobj = getFontBaseType(ind_font, subsetPrefix, toUnicodeRef);
+ writer.addToBody(pobj, ref);
+ }
+
+ /** A forbidden operation. Will throw a null pointer exception.
+ * @param text the text
+ * @return always null
+ */
+ byte[] convertToBytes(String text)
+ {
+ return null;
+ }
+
+ /**
+ * Checks if a character exists in this font.
+ * @param c the character to check
+ * @return true
if the character has a glyph,
+ * false
otherwise
+ */
+ public boolean charExists(char c) {
+ HashMap map = null;
+ if (fontSpecific)
+ map = cmap10;
+ else
+ map = cmap31;
+ if (map == null)
+ return false;
+ if (fontSpecific) {
+ if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
+ return map.get(new Integer(c & 0xff)) != null;
+ else
+ return false;
+ }
+ else
+ return map.get(new Integer(c)) != null;
+ }
+
+ /**
+ * Sets the character advance.
+ * @param c the character
+ * @param advance the character advance normalized to 1000 units
+ * @return true
if the advance was set,
+ * false
otherwise
+ */
+ public boolean setCharAdvance(char c, int advance) {
+ HashMap map = null;
+ if (fontSpecific)
+ map = cmap10;
+ else
+ map = cmap31;
+ if (map == null)
+ return false;
+ int m[] = null;
+ if (fontSpecific) {
+ if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
+ m = (int[])map.get(new Integer(c & 0xff));
+ else
+ return false;
+ }
+ else
+ m = (int[])map.get(new Integer(c));
+ if (m == null)
+ return false;
+ else
+ m[1] = advance;
+ return true;
+ }
+
+ public int[] getCharBBox(char c) {
+ if (bboxes == null)
+ return null;
+ HashMap map = null;
+ if (fontSpecific)
+ map = cmap10;
+ else
+ map = cmap31;
+ if (map == null)
+ return null;
+ int m[] = null;
+ if (fontSpecific) {
+ if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
+ m = (int[])map.get(new Integer(c & 0xff));
+ else
+ return null;
+ }
+ else
+ m = (int[])map.get(new Integer(c));
+ if (m == null)
+ return null;
+ return bboxes[m[0]];
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/Type1Font.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/Type1Font.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/Type1Font.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/Type1Font.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,796 @@
+/*
+ * $Id: Type1Font.java,v 1.64 2005/07/16 16:49:25 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2001, 2002 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import pdftk.com.lowagie.text.DocumentException;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import pdftk.com.lowagie.text.pdf.fonts.FontsResourceAnchor;
+import java.io.*;
+
+/** Reads a Type1 font
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+class Type1Font extends BaseFont
+{
+ private static FontsResourceAnchor resourceAnchor;
+
+ /** The PFB file if the input was made with a byte
array.
+ */
+ protected byte pfb[];
+/** The Postscript font name.
+ */
+ private String FontName;
+/** The full name of the font.
+ */
+ private String FullName;
+/** The family name of the font.
+ */
+ private String FamilyName;
+/** The weight of the font: normal, bold, etc.
+ */
+ private String Weight = "";
+/** The italic angle of the font, usually 0.0 or negative.
+ */
+ private float ItalicAngle = 0.0f;
+/** true
if all the characters have the same
+ * width.
+ */
+ private boolean IsFixedPitch = false;
+/** The character set of the font.
+ */
+ private String CharacterSet;
+/** The llx of the FontBox.
+ */
+ private int llx = -50;
+/** The lly of the FontBox.
+ */
+ private int lly = -200;
+/** The lurx of the FontBox.
+ */
+ private int urx = 1000;
+/** The ury of the FontBox.
+ */
+ private int ury = 900;
+/** The underline position.
+ */
+ private int UnderlinePosition = -100;
+/** The underline thickness.
+ */
+ private int UnderlineThickness = 50;
+/** The font's encoding name. This encoding is 'StandardEncoding' or
+ * 'AdobeStandardEncoding' for a font that can be totally encoded
+ * according to the characters names. For all other names the
+ * font is treated as symbolic.
+ */
+ private String EncodingScheme = "FontSpecific";
+/** A variable.
+ */
+ private int CapHeight = 700;
+/** A variable.
+ */
+ private int XHeight = 480;
+/** A variable.
+ */
+ private int Ascender = 800;
+/** A variable.
+ */
+ private int Descender = -200;
+/** A variable.
+ */
+ private int StdHW;
+/** A variable.
+ */
+ private int StdVW = 80;
+
+/** Represents the section CharMetrics in the AFM file. Each
+ * value of this array contains a Object[4]
with an
+ * Integer, Integer, String and int[]. This is the code, width, name and char bbox.
+ * The key is the name of the char and also an Integer with the char number.
+ */
+ private HashMap CharMetrics = new HashMap();
+/** Represents the section KernPairs in the AFM file. The key is
+ * the name of the first character and the value is a Object[]
+ * with 2 elements for each kern pair. Position 0 is the name of
+ * the second character and position 1 is the kerning distance. This is
+ * repeated for all the pairs.
+ */
+ private HashMap KernPairs = new HashMap();
+/** The file in use.
+ */
+ private String fileName;
+/** true
if this font is one of the 14 built in fonts.
+ */
+ private boolean builtinFont = false;
+/** Types of records in a PFB file. ASCII is 1 and BINARY is 2.
+ * They have to appear in the PFB file in this sequence.
+ */
+ private static final int pfbTypes[] = {1, 2, 1};
+
+ /** Creates a new Type1 font.
+ * @param ttfAfm the AFM file if the input is made with a byte
array
+ * @param pfb the PFB file if the input is made with a byte
array
+ * @param afmFile the name of one of the 14 built-in fonts or the location of an AFM file. The file must end in '.afm'
+ * @param enc the encoding to be applied to this font
+ * @param emb true if the font is to be embedded in the PDF
+ * @throws DocumentException the AFM file is invalid
+ * @throws IOException the AFM file could not be read
+ */
+ Type1Font(String afmFile, String enc, boolean emb, byte ttfAfm[], byte pfb[]) throws DocumentException, IOException
+ {
+ if (emb && ttfAfm != null && pfb == null)
+ throw new DocumentException("Two byte arrays are needed if the Type1 font is embedded.");
+ if (emb && ttfAfm != null)
+ this.pfb = pfb;
+ encoding = enc;
+ embedded = emb;
+ fileName = afmFile;
+ fontType = FONT_TYPE_T1;
+ RandomAccessFileOrArray rf = null;
+ InputStream is = null;
+ if (BuiltinFonts14.containsKey(afmFile)) {
+ embedded = false;
+ builtinFont = true;
+ byte buf[] = new byte[1024];
+ try {
+ if (resourceAnchor == null)
+ resourceAnchor = new FontsResourceAnchor();
+ is = getResourceStream(RESOURCE_PATH + afmFile + ".afm", resourceAnchor.getClass().getClassLoader());
+ if (is == null) {
+ String msg = afmFile + " not found as resource. (The *.afm files must exist as resources in the package pdftk.com.lowagie.text.pdf.fonts)";
+ System.err.println(msg);
+ throw new DocumentException(msg);
+ }
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ while (true) {
+ int size = is.read(buf);
+ if (size < 0)
+ break;
+ out.write(buf, 0, size);
+ }
+ buf = out.toByteArray();
+ }
+ finally {
+ if (is != null) {
+ try {
+ is.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ }
+ try {
+ rf = new RandomAccessFileOrArray(buf);
+ process(rf);
+ }
+ finally {
+ if (rf != null) {
+ try {
+ rf.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ }
+ }
+ else if (afmFile.toLowerCase().endsWith(".afm")) {
+ try {
+ if (ttfAfm == null)
+ rf = new RandomAccessFileOrArray(afmFile);
+ else
+ rf = new RandomAccessFileOrArray(ttfAfm);
+ process(rf);
+ }
+ finally {
+ if (rf != null) {
+ try {
+ rf.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ }
+ }
+ else if (afmFile.toLowerCase().endsWith(".pfm")) {
+ try {
+ ByteArrayOutputStream ba = new ByteArrayOutputStream();
+ if (ttfAfm == null)
+ rf = new RandomAccessFileOrArray(afmFile);
+ else
+ rf = new RandomAccessFileOrArray(ttfAfm);
+ Pfm2afm.convert(rf, ba);
+ rf.close();
+ rf = new RandomAccessFileOrArray(ba.toByteArray());
+ process(rf);
+ }
+ finally {
+ if (rf != null) {
+ try {
+ rf.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ }
+ }
+ else
+ throw new DocumentException(afmFile + " is not an AFM or PFM font file.");
+ try {
+ EncodingScheme = EncodingScheme.trim();
+ if (EncodingScheme.equals("AdobeStandardEncoding") || EncodingScheme.equals("StandardEncoding")) {
+ fontSpecific = false;
+ }
+ PdfEncodings.convertToBytes(" ", enc); // check if the encoding exists
+ createEncoding();
+ }
+ catch (RuntimeException re) {
+ throw re;
+ }
+ catch (Exception e) {
+ throw new DocumentException(e);
+ }
+ }
+
+/** Gets the width from the font according to the name
or,
+ * if the name
is null, meaning it is a symbolic font,
+ * the char c
.
+ * @param c the char if the font is symbolic
+ * @param name the glyph name
+ * @return the width of the char
+ */
+ int getRawWidth(int c, String name) {
+ Object metrics[];
+ if (name == null) { // font specific
+ metrics = (Object[])CharMetrics.get(new Integer(c));
+ }
+ else {
+ if (name.equals(".notdef"))
+ return 0;
+ metrics = (Object[])CharMetrics.get(name);
+ }
+ if (metrics != null)
+ return ((Integer)(metrics[1])).intValue();
+ return 0;
+ }
+
+/** Gets the kerning between two Unicode characters. The characters
+ * are converted to names and this names are used to find the kerning
+ * pairs in the HashMap
KernPairs
.
+ * @param char1 the first char
+ * @param char2 the second char
+ * @return the kerning to be applied
+ */
+ public int getKerning(char char1, char char2)
+ {
+ String first = GlyphList.unicodeToName(char1);
+ if (first == null)
+ return 0;
+ String second = GlyphList.unicodeToName(char2);
+ if (second == null)
+ return 0;
+ Object obj[] = (Object[])KernPairs.get(first);
+ if (obj == null)
+ return 0;
+ for (int k = 0; k < obj.length; k += 2) {
+ if (second.equals(obj[k]))
+ return ((Integer)obj[k + 1]).intValue();
+ }
+ return 0;
+ }
+
+
+ /** Reads the font metrics
+ * @param rf the AFM file
+ * @throws DocumentException the AFM file is invalid
+ * @throws IOException the AFM file could not be read
+ */
+ public void process(RandomAccessFileOrArray rf) throws DocumentException, IOException
+ {
+ String line;
+ boolean isMetrics = false;
+ while ((line = rf.readLine()) != null)
+ {
+ StringTokenizer tok = new StringTokenizer(line);
+ if (!tok.hasMoreTokens())
+ continue;
+ String ident = tok.nextToken();
+ if (ident.equals("FontName"))
+ FontName = tok.nextToken("\u00ff").substring(1);
+ else if (ident.equals("FullName"))
+ FullName = tok.nextToken("\u00ff").substring(1);
+ else if (ident.equals("FamilyName"))
+ FamilyName = tok.nextToken("\u00ff").substring(1);
+ else if (ident.equals("Weight"))
+ Weight = tok.nextToken("\u00ff").substring(1);
+ else if (ident.equals("ItalicAngle"))
+ ItalicAngle = Float.valueOf(tok.nextToken()).floatValue();
+ else if (ident.equals("IsFixedPitch"))
+ IsFixedPitch = tok.nextToken().equals("true");
+ else if (ident.equals("CharacterSet"))
+ CharacterSet = tok.nextToken("\u00ff").substring(1);
+ else if (ident.equals("FontBBox"))
+ {
+ llx = (int)Float.valueOf(tok.nextToken()).floatValue();
+ lly = (int)Float.valueOf(tok.nextToken()).floatValue();
+ urx = (int)Float.valueOf(tok.nextToken()).floatValue();
+ ury = (int)Float.valueOf(tok.nextToken()).floatValue();
+ }
+ else if (ident.equals("UnderlinePosition"))
+ UnderlinePosition = (int)Float.valueOf(tok.nextToken()).floatValue();
+ else if (ident.equals("UnderlineThickness"))
+ UnderlineThickness = (int)Float.valueOf(tok.nextToken()).floatValue();
+ else if (ident.equals("EncodingScheme"))
+ EncodingScheme = tok.nextToken("\u00ff").substring(1);
+ else if (ident.equals("CapHeight"))
+ CapHeight = (int)Float.valueOf(tok.nextToken()).floatValue();
+ else if (ident.equals("XHeight"))
+ XHeight = (int)Float.valueOf(tok.nextToken()).floatValue();
+ else if (ident.equals("Ascender"))
+ Ascender = (int)Float.valueOf(tok.nextToken()).floatValue();
+ else if (ident.equals("Descender"))
+ Descender = (int)Float.valueOf(tok.nextToken()).floatValue();
+ else if (ident.equals("StdHW"))
+ StdHW = (int)Float.valueOf(tok.nextToken()).floatValue();
+ else if (ident.equals("StdVW"))
+ StdVW = (int)Float.valueOf(tok.nextToken()).floatValue();
+ else if (ident.equals("StartCharMetrics"))
+ {
+ isMetrics = true;
+ break;
+ }
+ }
+ if (!isMetrics)
+ throw new DocumentException("Missing StartCharMetrics in " + fileName);
+ while ((line = rf.readLine()) != null)
+ {
+ StringTokenizer tok = new StringTokenizer(line);
+ if (!tok.hasMoreTokens())
+ continue;
+ String ident = tok.nextToken();
+ if (ident.equals("EndCharMetrics"))
+ {
+ isMetrics = false;
+ break;
+ }
+ Integer C = new Integer(-1);
+ Integer WX = new Integer(250);
+ String N = "";
+ int B[] = null;
+
+ tok = new StringTokenizer(line, ";");
+ while (tok.hasMoreTokens())
+ {
+ StringTokenizer tokc = new StringTokenizer(tok.nextToken());
+ if (!tokc.hasMoreTokens())
+ continue;
+ ident = tokc.nextToken();
+ if (ident.equals("C"))
+ C = Integer.valueOf(tokc.nextToken());
+ else if (ident.equals("WX"))
+ WX = new Integer(Float.valueOf(tokc.nextToken()).intValue());
+ else if (ident.equals("N"))
+ N = tokc.nextToken();
+ else if (ident.equals("B")) {
+ B = new int[]{Integer.parseInt(tokc.nextToken()),
+ Integer.parseInt(tokc.nextToken()),
+ Integer.parseInt(tokc.nextToken()),
+ Integer.parseInt(tokc.nextToken())};
+ }
+ }
+ Object metrics[] = new Object[]{C, WX, N, B};
+ if (C.intValue() >= 0)
+ CharMetrics.put(C, metrics);
+ CharMetrics.put(N, metrics);
+ }
+ if (isMetrics)
+ throw new DocumentException("Missing EndCharMetrics in " + fileName);
+ while ((line = rf.readLine()) != null)
+ {
+ StringTokenizer tok = new StringTokenizer(line);
+ if (!tok.hasMoreTokens())
+ continue;
+ String ident = tok.nextToken();
+ if (ident.equals("EndFontMetrics"))
+ return;
+ if (ident.equals("StartKernPairs"))
+ {
+ isMetrics = true;
+ break;
+ }
+ }
+ if (!isMetrics)
+ throw new DocumentException("Missing EndFontMetrics in " + fileName);
+ while ((line = rf.readLine()) != null)
+ {
+ StringTokenizer tok = new StringTokenizer(line);
+ if (!tok.hasMoreTokens())
+ continue;
+ String ident = tok.nextToken();
+ if (ident.equals("KPX"))
+ {
+ String first = tok.nextToken();
+ String second = tok.nextToken();
+ Integer width = new Integer(Float.valueOf(tok.nextToken()).intValue());
+ Object relates[] = (Object[])KernPairs.get(first);
+ if (relates == null)
+ KernPairs.put(first, new Object[]{second, width});
+ else
+ {
+ int n = relates.length;
+ Object relates2[] = new Object[n + 2];
+ System.arraycopy(relates, 0, relates2, 0, n);
+ relates2[n] = second;
+ relates2[n + 1] = width;
+ KernPairs.put(first, relates2);
+ }
+ }
+ else if (ident.equals("EndKernPairs"))
+ {
+ isMetrics = false;
+ break;
+ }
+ }
+ if (isMetrics)
+ throw new DocumentException("Missing EndKernPairs in " + fileName);
+ rf.close();
+ }
+
+/** If the embedded flag is false
or if the font is
+ * one of the 14 built in types, it returns null
,
+ * otherwise the font is read and output in a PdfStream object.
+ * @return the PdfStream containing the font or null
+ * @throws DocumentException if there is an error reading the font
+ */
+ private PdfStream getFontStream() throws DocumentException
+ {
+ if (builtinFont || !embedded)
+ return null;
+ RandomAccessFileOrArray rf = null;
+ try {
+ String filePfb = fileName.substring(0, fileName.length() - 3) + "pfb";
+ if (pfb == null)
+ rf = new RandomAccessFileOrArray(filePfb);
+ else
+ rf = new RandomAccessFileOrArray(pfb);
+ int fileLength = rf.length();
+ byte st[] = new byte[fileLength - 18];
+ int lengths[] = new int[3];
+ int bytePtr = 0;
+ for (int k = 0; k < 3; ++k) {
+ if (rf.read() != 0x80)
+ throw new DocumentException("Start marker missing in " + filePfb);
+ if (rf.read() != pfbTypes[k])
+ throw new DocumentException("Incorrect segment type in " + filePfb);
+ int size = rf.read();
+ size += rf.read() << 8;
+ size += rf.read() << 16;
+ size += rf.read() << 24;
+ lengths[k] = size;
+ while (size != 0) {
+ int got = rf.read(st, bytePtr, size);
+ if (got < 0)
+ throw new DocumentException("Premature end in " + filePfb);
+ bytePtr += got;
+ size -= got;
+ }
+ }
+ return new StreamFont(st, lengths);
+ }
+ catch (Exception e) {
+ throw new DocumentException(e);
+ }
+ finally {
+ if (rf != null) {
+ try {
+ rf.close();
+ }
+ catch (Exception e) {
+ // empty on purpose
+ }
+ }
+ }
+ }
+
+/** Generates the font descriptor for this font or null
if it is
+ * one of the 14 built in fonts.
+ * @param fontStream the indirect reference to a PdfStream containing the font or null
+ * @return the PdfDictionary containing the font descriptor or null
+ */
+ private PdfDictionary getFontDescriptor(PdfIndirectReference fontStream)
+ {
+ if (builtinFont)
+ return null;
+ PdfDictionary dic = new PdfDictionary(PdfName.FONTDESCRIPTOR);
+ dic.put(PdfName.ASCENT, new PdfNumber(Ascender));
+ dic.put(PdfName.CAPHEIGHT, new PdfNumber(CapHeight));
+ dic.put(PdfName.DESCENT, new PdfNumber(Descender));
+ dic.put(PdfName.FONTBBOX, new PdfRectangle(llx, lly, urx, ury));
+ dic.put(PdfName.FONTNAME, new PdfName(FontName));
+ dic.put(PdfName.ITALICANGLE, new PdfNumber(ItalicAngle));
+ dic.put(PdfName.STEMV, new PdfNumber(StdVW));
+ if (fontStream != null)
+ dic.put(PdfName.FONTFILE, fontStream);
+ int flags = 0;
+ if (IsFixedPitch)
+ flags |= 1;
+ flags |= fontSpecific ? 4 : 32;
+ if (ItalicAngle < 0)
+ flags |= 64;
+ if (FontName.indexOf("Caps") >= 0 || FontName.endsWith("SC"))
+ flags |= 131072;
+ if (Weight.equals("Bold"))
+ flags |= 262144;
+ dic.put(PdfName.FLAGS, new PdfNumber(flags));
+
+ return dic;
+ }
+
+ /** Generates the font dictionary for this font.
+ * @return the PdfDictionary containing the font dictionary
+ * @param firstChar the first valid character
+ * @param lastChar the last valid character
+ * @param shortTag a 256 bytes long byte
array where each unused byte is represented by 0
+ * @param fontDescriptor the indirect reference to a PdfDictionary containing the font descriptor or null
+ */
+ private PdfDictionary getFontBaseType(PdfIndirectReference fontDescriptor, int firstChar, int lastChar, byte shortTag[])
+ {
+ PdfDictionary dic = new PdfDictionary(PdfName.FONT);
+ dic.put(PdfName.SUBTYPE, PdfName.TYPE1);
+ dic.put(PdfName.BASEFONT, new PdfName(FontName));
+ boolean stdEncoding = encoding.equals("Cp1252") || encoding.equals("MacRoman");
+ if (!fontSpecific) {
+ for (int k = firstChar; k <= lastChar; ++k) {
+ if (!differences[k].equals(notdef)) {
+ firstChar = k;
+ break;
+ }
+ }
+ if (stdEncoding)
+ dic.put(PdfName.ENCODING, encoding.equals("Cp1252") ? PdfName.WIN_ANSI_ENCODING : PdfName.MAC_ROMAN_ENCODING);
+ else {
+ PdfDictionary enc = new PdfDictionary(PdfName.ENCODING);
+ PdfArray dif = new PdfArray();
+ boolean gap = true;
+ for (int k = firstChar; k <= lastChar; ++k) {
+ if (shortTag[k] != 0) {
+ if (gap) {
+ dif.add(new PdfNumber(k));
+ gap = false;
+ }
+ dif.add(new PdfName(differences[k]));
+ }
+ else
+ gap = true;
+ }
+ enc.put(PdfName.DIFFERENCES, dif);
+ dic.put(PdfName.ENCODING, enc);
+ }
+ }
+ if (forceWidthsOutput || !(builtinFont && (fontSpecific || stdEncoding))) {
+ dic.put(PdfName.FIRSTCHAR, new PdfNumber(firstChar));
+ dic.put(PdfName.LASTCHAR, new PdfNumber(lastChar));
+ PdfArray wd = new PdfArray();
+ for (int k = firstChar; k <= lastChar; ++k) {
+ if (shortTag[k] == 0)
+ wd.add(new PdfNumber(0));
+ else
+ wd.add(new PdfNumber(widths[k]));
+ }
+ dic.put(PdfName.WIDTHS, wd);
+ }
+ if (!builtinFont && fontDescriptor != null)
+ dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor);
+ return dic;
+ }
+
+ /** Outputs to the writer the font dictionaries and streams.
+ * @param writer the writer for this document
+ * @param ref the font indirect reference
+ * @param params several parameters that depend on the font type
+ * @throws IOException on error
+ * @throws DocumentException error in generating the object
+ */
+ void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException {
+ int firstChar = ((Integer)params[0]).intValue();
+ int lastChar = ((Integer)params[1]).intValue();
+ byte shortTag[] = (byte[])params[2];
+ if (!subset) {
+ firstChar = 0;
+ lastChar = shortTag.length - 1;
+ for (int k = 0; k < shortTag.length; ++k)
+ shortTag[k] = 1;
+ }
+ PdfIndirectReference ind_font = null;
+ PdfObject pobj = null;
+ PdfIndirectObject obj = null;
+ pobj = getFontStream();
+ if (pobj != null){
+ obj = writer.addToBody(pobj);
+ ind_font = obj.getIndirectReference();
+ }
+ pobj = getFontDescriptor(ind_font);
+ if (pobj != null){
+ obj = writer.addToBody(pobj);
+ ind_font = obj.getIndirectReference();
+ }
+ pobj = getFontBaseType(ind_font, firstChar, lastChar, shortTag);
+ writer.addToBody(pobj, ref);
+ }
+
+ /** Gets the font parameter identified by key
. Valid values
+ * for key
are ASCENT
, CAPHEIGHT
, DESCENT
,
+ * ITALICANGLE
, BBOXLLX
, BBOXLLY
, BBOXURX
+ * and BBOXURY
.
+ * @param key the parameter to be extracted
+ * @param fontSize the font size in points
+ * @return the parameter in points
+ */
+ public float getFontDescriptor(int key, float fontSize) {
+ switch (key) {
+ case AWT_ASCENT:
+ case ASCENT:
+ return Ascender * fontSize / 1000;
+ case CAPHEIGHT:
+ return CapHeight * fontSize / 1000;
+ case AWT_DESCENT:
+ case DESCENT:
+ return Descender * fontSize / 1000;
+ case ITALICANGLE:
+ return ItalicAngle;
+ case BBOXLLX:
+ return llx * fontSize / 1000;
+ case BBOXLLY:
+ return lly * fontSize / 1000;
+ case BBOXURX:
+ return urx * fontSize / 1000;
+ case BBOXURY:
+ return ury * fontSize / 1000;
+ case AWT_LEADING:
+ return 0;
+ case AWT_MAXADVANCE:
+ return (urx - llx) * fontSize / 1000;
+ }
+ return 0;
+ }
+
+ /** Gets the postscript font name.
+ * @return the postscript font name
+ */
+ public String getPostscriptFontName() {
+ return FontName;
+ }
+
+ /** Gets the full name of the font. If it is a True Type font
+ * each array element will have {Platform ID, Platform Encoding ID,
+ * Language ID, font name}. The interpretation of this values can be
+ * found in the Open Type specification, chapter 2, in the 'name' table.
+ * For the other fonts the array has a single element with {"", "", "",
+ * font name}.
+ * @return the full name of the font
+ */
+ public String[][] getFullFontName() {
+ return new String[][]{{"", "", "", FullName}};
+ }
+
+ /** Gets the family name of the font. If it is a True Type font
+ * each array element will have {Platform ID, Platform Encoding ID,
+ * Language ID, font name}. The interpretation of this values can be
+ * found in the Open Type specification, chapter 2, in the 'name' table.
+ * For the other fonts the array has a single element with {"", "", "",
+ * font name}.
+ * @return the family name of the font
+ */
+ public String[][] getFamilyFontName() {
+ return new String[][]{{"", "", "", FamilyName}};
+ }
+
+ /** Checks if the font has any kerning pairs.
+ * @return true
if the font has any kerning pairs
+ */
+ public boolean hasKernPairs() {
+ return KernPairs.size() > 0;
+ }
+
+ /**
+ * Sets the font name that will appear in the pdf font dictionary.
+ * Use with care as it can easily make a font unreadable if not embedded.
+ * @param name the new font name
+ */
+ public void setPostscriptFontName(String name) {
+ FontName = name;
+ }
+
+ /**
+ * Sets the kerning between two Unicode chars.
+ * @param char1 the first char
+ * @param char2 the second char
+ * @param kern the kerning to apply in normalized 1000 units
+ * @return true
if the kerning was applied, false
otherwise
+ */
+ public boolean setKerning(char char1, char char2, int kern) {
+ String first = GlyphList.unicodeToName(char1);
+ if (first == null)
+ return false;
+ String second = GlyphList.unicodeToName(char2);
+ if (second == null)
+ return false;
+ Object obj[] = (Object[])KernPairs.get(first);
+ if (obj == null) {
+ obj = new Object[]{second, new Integer(kern)};
+ KernPairs.put(first, obj);
+ return true;
+ }
+ for (int k = 0; k < obj.length; k += 2) {
+ if (second.equals(obj[k])) {
+ obj[k + 1] = new Integer(kern);
+ return true;
+ }
+ }
+ int size = obj.length;
+ Object obj2[] = new Object[size + 2];
+ System.arraycopy(obj, 0, obj2, 0, size);
+ obj2[size] = second;
+ obj2[size + 1] = new Integer(kern);
+ KernPairs.put(first, obj2);
+ return true;
+ }
+
+ protected int[] getRawCharBBox(int c, String name) {
+ Object metrics[];
+ if (name == null) { // font specific
+ metrics = (Object[])CharMetrics.get(new Integer(c));
+ }
+ else {
+ if (name.equals(".notdef"))
+ return null;
+ metrics = (Object[])CharMetrics.get(name);
+ }
+ if (metrics != null)
+ return ((int[])(metrics[3]));
+ return null;
+ }
+
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/VerticalText.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/VerticalText.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/VerticalText.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/VerticalText.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,339 @@
+/*
+ *
+ * Copyright 2002 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf;
+import java.util.ArrayList;
+import java.util.Iterator;
+import pdftk.com.lowagie.text.Phrase;
+import pdftk.com.lowagie.text.Chunk;
+import pdftk.com.lowagie.text.Element;
+import pdftk.com.lowagie.text.DocumentException;
+import java.awt.Color;
+
+/** Writes text vertically. Note that the naming is done according
+ * to horizontal text although it referrs to vertical text.
+ * A line with the alignment Element.LEFT_ALIGN will actually
+ * be top aligned.
+ */
+public class VerticalText {
+
+/** Signals that there are no more text available. */
+ public static final int NO_MORE_TEXT = 1;
+
+/** Signals that there is no more column. */
+ public static final int NO_MORE_COLUMN = 2;
+
+/** The chunks that form the text. */
+ protected ArrayList chunks = new ArrayList();
+
+ /** The PdfContent
where the text will be written to. */
+ protected PdfContentByte text;
+
+ /** The column alignment. Default is left alignment. */
+ protected int alignment = Element.ALIGN_LEFT;
+
+ /** Marks the chunks to be eliminated when the line is written. */
+ protected int currentChunkMarker = -1;
+
+ /** The chunk created by the splitting. */
+ protected PdfChunk currentStandbyChunk;
+
+ /** The chunk created by the splitting. */
+ protected String splittedChunkText;
+
+ /** The leading
+ */
+ protected float leading;
+
+ /** The X coordinate.
+ */
+ protected float startX;
+
+ /** The Y coordinate.
+ */
+ protected float startY;
+
+ /** The maximum number of vertical lines.
+ */
+ protected int maxLines;
+
+ /** The height of the text.
+ */
+ protected float height;
+
+ /** Creates new VerticalText
+ * @param text the place where the text will be written to. Can
+ * be a template.
+ */
+ public VerticalText(PdfContentByte text) {
+ this.text = text;
+ }
+
+ /**
+ * Adds a Phrase
to the current text array.
+ * @param phrase the text
+ */
+ public void addText(Phrase phrase) {
+ for (Iterator j = phrase.getChunks().iterator(); j.hasNext();) {
+ chunks.add(new PdfChunk((Chunk)j.next(), null));
+ }
+ }
+
+ /**
+ * Adds a Chunk
to the current text array.
+ * @param chunk the text
+ */
+ public void addText(Chunk chunk) {
+ chunks.add(new PdfChunk(chunk, null));
+ }
+
+ /** Sets the layout.
+ * @param startX the top right X line position
+ * @param startY the top right Y line position
+ * @param height the height of the lines
+ * @param maxLines the maximum number of lines
+ * @param leading the separation between the lines
+ */
+ public void setVerticalLayout(float startX, float startY, float height, int maxLines, float leading) {
+ this.startX = startX;
+ this.startY = startY;
+ this.height = height;
+ this.maxLines = maxLines;
+ setLeading(leading);
+ }
+
+ /** Sets the separation between the vertical lines.
+ * @param leading the vertical line separation
+ */
+ public void setLeading(float leading) {
+ this.leading = leading;
+ }
+
+ /** Gets the separation between the vertical lines.
+ * @return the vertical line separation
+ */
+ public float getLeading() {
+ return leading;
+ }
+
+ /**
+ * Creates a line from the chunk array.
+ * @param width the width of the line
+ * @return the line or null if no more chunks
+ */
+ protected PdfLine createLine(float width) {
+ if (chunks.size() == 0)
+ return null;
+ splittedChunkText = null;
+ currentStandbyChunk = null;
+ PdfLine line = new PdfLine(0, width, alignment, 0);
+ String total;
+ for (currentChunkMarker = 0; currentChunkMarker < chunks.size(); ++currentChunkMarker) {
+ PdfChunk original = (PdfChunk)(chunks.get(currentChunkMarker));
+ total = original.toString();
+ currentStandbyChunk = line.add(original);
+ if (currentStandbyChunk != null) {
+ splittedChunkText = original.toString();
+ original.setValue(total);
+ return line;
+ }
+ }
+ return line;
+ }
+
+ /**
+ * Normalizes the list of chunks when the line is accepted.
+ */
+ protected void shortenChunkArray() {
+ if (currentChunkMarker < 0)
+ return;
+ if (currentChunkMarker >= chunks.size()) {
+ chunks.clear();
+ return;
+ }
+ PdfChunk split = (PdfChunk)(chunks.get(currentChunkMarker));
+ split.setValue(splittedChunkText);
+ chunks.set(currentChunkMarker, currentStandbyChunk);
+ for (int j = currentChunkMarker - 1; j >= 0; --j)
+ chunks.remove(j);
+ }
+
+ /**
+ * Outputs the lines to the document. It is equivalent to go(false)
.
+ * @return returns the result of the operation. It can be NO_MORE_TEXT
+ * and/or NO_MORE_COLUMN
+ * @throws DocumentException on error
+ */
+ public int go() throws DocumentException {
+ return go(false);
+ }
+
+ /**
+ * Outputs the lines to the document. The output can be simulated.
+ * @param simulate true
to simulate the writting to the document
+ * @return returns the result of the operation. It can be NO_MORE_TEXT
+ * and/or NO_MORE_COLUMN
+ * @throws DocumentException on error
+ */
+ public int go(boolean simulate) throws DocumentException {
+ boolean dirty = false;
+ PdfContentByte graphics = null;
+ if (text != null) {
+ graphics = text.getDuplicate();
+ }
+ else if (simulate == false)
+ throw new NullPointerException("VerticalText.go with simulate==false and text==null.");
+ int status = 0;
+ for (;;) {
+ if (maxLines <= 0) {
+ status = NO_MORE_COLUMN;
+ if (chunks.size() == 0)
+ status |= NO_MORE_TEXT;
+ break;
+ }
+ if (chunks.size() == 0) {
+ status = NO_MORE_TEXT;
+ break;
+ }
+ PdfLine line = createLine(height);
+ if (!simulate && !dirty) {
+ text.beginText();
+ dirty = true;
+ }
+ shortenChunkArray();
+ if (!simulate) {
+ text.setTextMatrix(startX, startY - line.indentLeft());
+ writeLine(line, text, graphics);
+ }
+ --maxLines;
+ startX -= leading;
+ }
+ if (dirty) {
+ text.endText();
+ text.add(graphics);
+ }
+ return status;
+ }
+
+ void writeLine(PdfLine line, PdfContentByte text, PdfContentByte graphics) throws DocumentException {
+ PdfFont currentFont = null;
+ PdfChunk chunk;
+ for (Iterator j = line.iterator(); j.hasNext(); ) {
+ chunk = (PdfChunk) j.next();
+
+ if (chunk.font().compareTo(currentFont) != 0) {
+ currentFont = chunk.font();
+ text.setFontAndSize(currentFont.getFont(), currentFont.size());
+ }
+ Color color = chunk.color();
+ if (color != null)
+ text.setColorFill(color);
+ text.showText(chunk.toString());
+ if (color != null)
+ text.resetRGBColorFill();
+ }
+ }
+
+ /** Sets the new text origin.
+ * @param startX the X coordinate
+ * @param startY the Y coordinate
+ */
+ public void setOrigin(float startX, float startY) {
+ this.startX = startX;
+ this.startY = startY;
+ }
+
+ /** Gets the X coordinate where the next line will be writen. This value will change
+ * after each call to go()
.
+ * @return the X coordinate
+ */
+ public float getOriginX() {
+ return startX;
+ }
+
+ /** Gets the Y coordinate where the next line will be writen.
+ * @return the Y coordinate
+ */
+ public float getOriginY() {
+ return startY;
+ }
+
+ /** Gets the maximum number of available lines. This value will change
+ * after each call to go()
.
+ * @return Value of property maxLines.
+ */
+ public int getMaxLines() {
+ return maxLines;
+ }
+
+ /** Sets the maximum number of lines.
+ * @param maxLines the maximum number of lines
+ */
+ public void setMaxLines(int maxLines) {
+ this.maxLines = maxLines;
+ }
+
+ /** Gets the height of the line
+ * @return the height
+ */
+ public float getHeight() {
+ return height;
+ }
+
+ /** Sets the height of the line
+ * @param height the new height
+ */
+ public void setHeight(float height) {
+ this.height = height;
+ }
+
+ /**
+ * Sets the alignment.
+ * @param alignment the alignment
+ */
+ public void setAlignment(int alignment) {
+ this.alignment = alignment;
+ }
+
+ /**
+ * Gets the alignment.
+ * @return the alignment
+ */
+ public int getAlignment() {
+ return alignment;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/XfdfReader.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/XfdfReader.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/XfdfReader.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/XfdfReader.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,231 @@
+/* -*- Mode: Java; tab-width: 4; c-basic-offset: 4 -*- */
+/*
+ *
+ * Copyright 2004 by Leonard Rosenthol.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream; // ssteward
+import java.io.FileInputStream;
+import java.util.HashMap;
+import java.util.Stack;
+
+/**
+ * Reads a XFDF.
+ * @author Leonard Rosenthol (leonardr@pdfsages.com)
+ */
+public class XfdfReader implements SimpleXMLDocHandler {
+ // stuff used during parsing to handle state
+ private boolean foundRoot = false;
+ private Stack fieldNames = new Stack();
+ private Stack fieldValues = new Stack();
+
+ // storage for the field list and their values
+ HashMap fields;
+
+ // storage for the field list and their rich text; ssteward
+ HashMap fieldsRichText;
+
+ // storage for the path to referenced PDF, if any
+ String fileSpec;
+
+ /** Reads an XFDF form.
+ * @param filename the file name of the form
+ * @throws IOException on error
+ */
+ public XfdfReader(String filename) throws IOException {
+ InputStream fin = null; // ssteward: was FileInputStream
+ try {
+ // ssteward: added for stdin handling (also see RandomAccessFileOrArray.java)
+ if( filename.equals("-") ) {
+ fin = System.in;
+ }
+ else {
+ fin = new FileInputStream(filename);
+ }
+ SimpleXMLParser.parse(this, fin);
+ }
+ finally {
+ try{fin.close();}catch(Exception e){}
+ }
+ }
+
+ /** Reads an XFDF form.
+ * @param xfdfIn the byte array with the form
+ * @throws IOException on error
+ */
+ public XfdfReader(byte xfdfIn[]) throws IOException {
+ SimpleXMLParser.parse( this, new ByteArrayInputStream(xfdfIn));
+ }
+
+ /** Gets all the fields. The map is keyed by the fully qualified
+ * field name and the value is a merged PdfDictionary
+ * with the field content.
+ * @return all the fields
+ */
+ public HashMap getFields() {
+ return fields;
+ }
+
+ /** Gets the field value.
+ * @param name the fully qualified field name
+ * @return the field's value
+ */
+ public String getField(String name) {
+ return (String)fields.get(name);
+ }
+
+ /** Gets the field value or null
if the field does not
+ * exist or has no value defined.
+ * @param name the fully qualified field name
+ * @return the field value or null
+ */
+ public String getFieldValue(String name) {
+ String field = (String)fields.get(name);
+ if (field == null)
+ return null;
+ else
+ return field;
+ }
+
+ // ssteward
+ // for parity with FdfReader addition
+ public String getFieldRichValue(String name) {
+ String field = (String)fieldsRichText.get(name);
+ if (field == null)
+ return null;
+ else
+ return field;
+ }
+
+ /** Gets the PDF file specification contained in the FDF.
+ * @return the PDF file specification contained in the FDF
+ */
+ public String getFileSpec() {
+ return fileSpec;
+ }
+
+ /**
+ * Called when a start tag is found.
+ * @param tag the tag name
+ * @param h the tag's attributes
+ */
+ public void startElement(String tag, HashMap h)
+ {
+ if ( !foundRoot ) {
+ if (!tag.equals("xfdf"))
+ throw new RuntimeException("Root element is not Bookmark.");
+ else
+ foundRoot = true;
+ }
+
+ if ( tag.equals("xfdf") ){
+
+ } else if ( tag.equals("f") ) {
+ fileSpec = (String)h.get( "href" );
+ } else if ( tag.equals("fields") ) {
+ fields = new HashMap(); // init it!
+ fieldsRichText = new HashMap();
+ } else if ( tag.equals("field") ) {
+ String fName = (String) h.get( "name" );
+ fieldNames.push( fName );
+ } else if ( tag.equals("value") ||
+ tag.equals("value-richtext") ) // ssteward
+ {
+ fieldValues.push( (String)"" );
+ }
+ }
+
+ /**
+ * Called when an end tag is found.
+ * @param tag the tag name
+ */
+ public void endElement(String tag) {
+ if ( tag.equals("value") ||
+ tag.equals("value-richtext") ) // ssteward
+ {
+ String fName = "";
+ for (int k = 0; k < fieldNames.size(); ++k) {
+ fName += "." + (String)fieldNames.elementAt(k);
+ }
+ if (fName.startsWith("."))
+ fName = fName.substring(1);
+ String fVal = (String) fieldValues.pop();
+
+ if (tag.equals("value")) { // ssteward
+ fields.put( fName, fVal );
+ }
+ else { // rich text value
+ fieldsRichText.put( fName, fVal );
+ }
+ }
+ else if (tag.equals("field") ) {
+ if (!fieldNames.isEmpty())
+ fieldNames.pop();
+ }
+ }
+
+ /**
+ * Called when the document starts to be parsed.
+ */
+ public void startDocument()
+ {
+ fileSpec = new String(""); // and this too...
+ }
+ /**
+ * Called after the document is parsed.
+ */
+ public void endDocument()
+ {
+
+ }
+ /**
+ * Called when a text element is found.
+ * @param str the text element, probably a fragment.
+ */
+ public void text(String str)
+ {
+ if (fieldNames.isEmpty() || fieldValues.isEmpty())
+ return;
+
+ String val = (String)fieldValues.pop();
+ val += str;
+ fieldValues.push(val);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/codec/postscript/paparser.jj pdftk-2.01/java/pdftk/com/lowagie/text/pdf/codec/postscript/paparser.jj
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/codec/postscript/paparser.jj 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/codec/postscript/paparser.jj 2005-02-28 16:31:28.000000000 +0000
@@ -0,0 +1,289 @@
+options {
+ LOOKAHEAD=1;
+ JAVA_UNICODE_ESCAPE = true;
+ STATIC = false;
+}
+
+PARSER_BEGIN(PAParser)
+
+package com.lowagie.text.pdf.codec.postscript;
+
+import java.lang.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.color.*;
+import java.awt.font.*;
+
+import java.io.*;
+import java.net.URL;
+
+public class PAParser extends Object {
+
+}
+
+PARSER_END(PAParser)
+
+
+/* WHITE SPACE */
+
+SKIP :
+{
+ < WHITESPACE: " " | "\t" | "\n" | "\r" | "\f" >
+|
+ < "%" ( ~["\n"] )* "\n" >
+ |
+ < "%" ( ~["\r"] )* "\r" >
+}
+
+/* LITERALS */
+
+TOKEN :
+{
+ < INTEGER_LITERAL:
+ ("-")? ( (["l","L"])?
+ | (["l","L"])?
+ )
+ >
+|
+ < #DECIMAL_LITERAL: ["0"-"9"] (["0"-"9"])* >
+|
+ < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
+|
+ < FLOATING_POINT_LITERAL:
+ ((["0"-"9"])+ "." (["0"-"9"])* ()? (["f","F","d","D"])?)
+ | ("." (["0"-"9"])+ ()? (["f","F","d","D"])?)
+ | ((["0"-"9"])+ (["f","F","d","D"])?)
+ | ((["0"-"9"])+ ()? ["f","F","d","D"])
+ | ("-" (["0"-"9"])+ "." (["0"-"9"])* ()? (["f","F","d","D"])?)
+ | ("-" "." (["0"-"9"])+ ()? (["f","F","d","D"])?)
+ | ("-" (["0"-"9"])+ (["f","F","d","D"])?)
+ | ("-" (["0"-"9"])+ ()? ["f","F","d","D"])
+ >
+|
+ < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
+|
+ < STRING_LITERAL:
+ "("
+ ( (~[")","\\","\n","\r"])
+ | ("\\"
+ ( ["n","t","b","r","f","\\","'",")", "\n"]
+ | ["0"-"7"] ( ["0"-"7"] )?
+ | ["0"-"3"] ["0"-"7"] ["0"-"7"]
+ )
+ )
+ )*
+ ")"
+ >
+}
+
+/* IDENTIFIERS */
+
+TOKEN :
+{
+ < IDENTIFIER: (||"-"|".")* >
+|
+ < KEY_IDENTIFIER: "/" >
+|
+ < IMMEDIATE_IDENTIFIER: "//" >
+|
+ < #LETTER:
+ [
+ "\u0024",
+ "\u0041"-"\u005a",
+ "\u005f",
+ "\u0061"-"\u007a",
+ "\u00c0"-"\u00d6",
+ "\u00d8"-"\u00f6",
+ "\u00f8"-"\u00ff",
+ "\u0100"-"\u1fff",
+ "\u3040"-"\u318f",
+ "\u3300"-"\u337f",
+ "\u3400"-"\u3d2d",
+ "\u4e00"-"\u9fff",
+ "\uf900"-"\ufaff"
+ ]
+ >
+|
+ < #DIGIT:
+ [
+ "\u0030"-"\u0039",
+ "\u0660"-"\u0669",
+ "\u06f0"-"\u06f9",
+ "\u0966"-"\u096f",
+ "\u09e6"-"\u09ef",
+ "\u0a66"-"\u0a6f",
+ "\u0ae6"-"\u0aef",
+ "\u0b66"-"\u0b6f",
+ "\u0be7"-"\u0bef",
+ "\u0c66"-"\u0c6f",
+ "\u0ce6"-"\u0cef",
+ "\u0d66"-"\u0d6f",
+ "\u0e50"-"\u0e59",
+ "\u0ed0"-"\u0ed9",
+ "\u1040"-"\u1049"
+ ]
+ >
+}
+
+/* SEPARATORS */
+
+TOKEN :
+{
+
+ < LBRACE: "{" >
+| < RBRACE: "}" >
+| < LBRACKET: "[" >
+| < RBRACKET: "]" >
+
+}
+
+JAVACODE
+void error_skipto(int kind){
+ParseException e=generateParseException();
+Token t;
+String dump="";
+do{
+if(getToken(1).kind==kind)break;
+t=getNextToken();
+dump+=t.image;
+}while(t.kind!=kind);
+System.out.println("Ignoriere >"+dump+"<");
+}
+
+
+void parse(PAContext context) :
+{
+ Token x = null;
+}
+{
+ try{
+ (
+ (
+ ( (
+ x =
+ {
+ try {
+ context.engine.process(new Integer(x.image));
+ } catch(NumberFormatException e) {
+ throw new ParseException(e.toString());
+ } catch(PainterException e) {
+ throw new ParseException(e.toString());
+ }
+ }
+ )
+ |
+ (
+ x =
+ {
+ try {
+ context.engine.process(new Double(x.image));
+ } catch(NumberFormatException e) {
+ throw new ParseException(e.toString());
+ } catch(PainterException e) {
+ throw new ParseException(e.toString());
+ }
+ }
+ )
+ |
+ (
+ x =
+ {
+ try {
+ context.engine.process(x.image.substring(1, x.image.length() -1));
+ } catch(PainterException e) {
+ throw new ParseException(e.toString());
+ }
+ }
+ )
+ |
+ (
+ x =
+ {
+ try {
+ context.engine.process(new PAToken(x.image, PAToken.IDENTIFIER));
+ } catch(PainterException e) {
+ throw new ParseException(e.toString());
+ }
+ }
+ )
+ |
+ (
+ x =
+ {
+ try {
+ context.engine.process(new PAToken(x.image.substring(1, x.image.length()), PAToken.KEY));
+ } catch(PainterException e) {
+ throw new ParseException(e.toString());
+ }
+ }
+ )
+ |
+ (
+ x =
+ {
+ try {
+ context.engine.process(new PAToken(x.image.substring(2, x.image.length()), PAToken.IMMEDIATE));
+ } catch(PainterException e) {
+ throw new ParseException(e.toString());
+ }
+ }
+ ) )
+ |
+ (
+
+ {
+ try {
+ context.engine.process(new PAToken(null, PAToken.START_PROCEDURE));
+ } catch(PainterException e) {
+ throw new ParseException(e.toString());
+ }
+ }
+ )
+ |
+ (
+
+ {
+ try {
+ context.engine.process(new PAToken(null, PAToken.END_PROCEDURE));
+ } catch(PainterException e) {
+ throw new ParseException(e.toString());
+ }
+ }
+ )
+ |
+ (
+
+ {
+ try {
+ context.engine.process(new PAToken(null, PAToken.START_ARRAY));
+ } catch(PainterException e) {
+ throw new ParseException(e.toString());
+ }
+ }
+ )
+ |
+ (
+
+ {
+ try {
+ context.engine.process(new PAToken(null, PAToken.END_ARRAY));
+ } catch(PainterException e) {
+ throw new ParseException(e.toString());
+ }
+ }
+ )
+ )//{System.out.println(">>>"+token.image+"");System.out.flush();}
+ )*
+
+ }catch(ParseException e){
+ //System.out.println("Fehlerhaftes Element in Spalte "+e.currentToken.beginColumn+" in Eingabedatei in Zeile="+e.currentToken.next.beginLine+" in Zeichen Nr. "+e.currentToken.next.beginColumn+". >"+e.currentToken.next.image+"< wurde hier nicht erwartet.");
+ //System.err.println("Fehler:"+e);
+ e.printStackTrace();
+ error_skipto(WHITESPACE);
+ }
+}
+
+
+
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/crypto/AESCipher.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/crypto/AESCipher.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/crypto/AESCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/crypto/AESCipher.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,94 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf.crypto;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.engines.AESFastEngine;
+import pdftk.org.bouncycastle.crypto.modes.CBCBlockCipher;
+import pdftk.org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Creates an AES Cipher with CBC and padding PKCS5/7.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class AESCipher {
+ private PaddedBufferedBlockCipher bp;
+
+ /** Creates a new instance of AESCipher */
+ public AESCipher(boolean forEncryption, byte[] key, byte[] iv) {
+ BlockCipher aes = new AESFastEngine();
+ BlockCipher cbc = new CBCBlockCipher(aes);
+ bp = new PaddedBufferedBlockCipher(cbc);
+ KeyParameter kp = new KeyParameter(key);
+ ParametersWithIV piv = new ParametersWithIV(kp, iv);
+ bp.init(forEncryption, piv);
+ }
+
+ public byte[] update(byte[] inp, int inpOff, int inpLen) {
+ int neededLen = bp.getUpdateOutputSize(inpLen);
+ byte[] outp = null;
+ if (neededLen > 0)
+ outp = new byte[neededLen];
+ else
+ neededLen = 0;
+ bp.processBytes(inp, inpOff, inpLen, outp, 0);
+ return outp;
+ }
+
+ public byte[] doFinal() {
+ int neededLen = bp.getOutputSize(0);
+ byte[] outp = new byte[neededLen];
+ int n = 0;
+ try {
+ n = bp.doFinal(outp, 0);
+ } catch (Exception ex) {
+ return outp;
+ }
+ if (n != outp.length) {
+ byte[] outp2 = new byte[n];
+ System.arraycopy(outp, 0, outp2, 0, n);
+ return outp2;
+ }
+ else
+ return outp;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/crypto/ARCFOUREncryption.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/crypto/ARCFOUREncryption.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/crypto/ARCFOUREncryption.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/crypto/ARCFOUREncryption.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,95 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf.crypto;
+
+public class ARCFOUREncryption {
+ private byte state[] = new byte[256];
+ private int x;
+ private int y;
+
+ /** Creates a new instance of ARCFOUREncryption */
+ public ARCFOUREncryption() {
+ }
+
+ public void prepareARCFOURKey(byte key[]) {
+ prepareARCFOURKey(key, 0, key.length);
+ }
+
+ public void prepareARCFOURKey(byte key[], int off, int len) {
+ int index1 = 0;
+ int index2 = 0;
+ for (int k = 0; k < 256; ++k)
+ state[k] = (byte)k;
+ x = 0;
+ y = 0;
+ byte tmp;
+ for (int k = 0; k < 256; ++k) {
+ index2 = (key[index1 + off] + state[k] + index2) & 255;
+ tmp = state[k];
+ state[k] = state[index2];
+ state[index2] = tmp;
+ index1 = (index1 + 1) % len;
+ }
+ }
+
+ public void encryptARCFOUR(byte dataIn[], int off, int len, byte dataOut[], int offOut) {
+ int length = len + off;
+ byte tmp;
+ for (int k = off; k < length; ++k) {
+ x = (x + 1) & 255;
+ y = (state[x] + y) & 255;
+ tmp = state[x];
+ state[x] = state[y];
+ state[y] = tmp;
+ dataOut[k - off + offOut] = (byte)(dataIn[k] ^ state[(state[x] + state[y]) & 255]);
+ }
+ }
+
+ public void encryptARCFOUR(byte data[], int off, int len) {
+ encryptARCFOUR(data, off, len, data, off);
+ }
+
+ public void encryptARCFOUR(byte dataIn[], byte dataOut[]) {
+ encryptARCFOUR(dataIn, 0, dataIn.length, dataOut, 0);
+ }
+
+ public void encryptARCFOUR(byte data[]) {
+ encryptARCFOUR(data, 0, data.length, data, 0);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/crypto/IVGenerator.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/crypto/IVGenerator.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/crypto/IVGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/crypto/IVGenerator.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,81 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Paulo Soares
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf.crypto;
+
+/**
+ * An initialization vector generator for a CBC block encryption. It's a random generator based on ARCFOUR.
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public final class IVGenerator {
+
+ private static ARCFOUREncryption arcfour;
+
+ static {
+ arcfour = new ARCFOUREncryption();
+ long time = System.currentTimeMillis();
+ long mem = Runtime.getRuntime().freeMemory();
+ String s = time + "+" + mem;
+ arcfour.prepareARCFOURKey(s.getBytes());
+ }
+
+ /** Creates a new instance of IVGenerator */
+ private IVGenerator() {
+ }
+
+ /**
+ * Gets a 16 byte random initialization vector.
+ * @return a 16 byte random initialization vector
+ */
+ public static byte[] getIV() {
+ return getIV(16);
+ }
+
+ /**
+ * Gets a random initialization vector.
+ * @param len the length of the initialization vector
+ * @return a random initialization vector
+ */
+ public static byte[] getIV(int len) {
+ byte[] b = new byte[len];
+ synchronized (arcfour) {
+ arcfour.encryptARCFOUR(b);
+ }
+ return b;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Courier-Bold.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Courier-Bold.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Courier-Bold.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Courier-Bold.afm 2004-05-26 16:06:20.000000000 +0000
@@ -0,0 +1,342 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Mon Jun 23 16:28:00 1997
+Comment UniqueID 43048
+Comment VMusage 41139 52164
+FontName Courier-Bold
+FullName Courier Bold
+FamilyName Courier
+Weight Bold
+ItalicAngle 0
+IsFixedPitch true
+CharacterSet ExtendedRoman
+FontBBox -113 -250 749 801
+UnderlinePosition -100
+UnderlineThickness 50
+Version 003.000
+Notice Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 562
+XHeight 439
+Ascender 629
+Descender -157
+StdHW 84
+StdVW 106
+StartCharMetrics 315
+C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 600 ; N exclam ; B 202 -15 398 572 ;
+C 34 ; WX 600 ; N quotedbl ; B 135 277 465 562 ;
+C 35 ; WX 600 ; N numbersign ; B 56 -45 544 651 ;
+C 36 ; WX 600 ; N dollar ; B 82 -126 519 666 ;
+C 37 ; WX 600 ; N percent ; B 5 -15 595 616 ;
+C 38 ; WX 600 ; N ampersand ; B 36 -15 546 543 ;
+C 39 ; WX 600 ; N quoteright ; B 171 277 423 562 ;
+C 40 ; WX 600 ; N parenleft ; B 219 -102 461 616 ;
+C 41 ; WX 600 ; N parenright ; B 139 -102 381 616 ;
+C 42 ; WX 600 ; N asterisk ; B 91 219 509 601 ;
+C 43 ; WX 600 ; N plus ; B 71 39 529 478 ;
+C 44 ; WX 600 ; N comma ; B 123 -111 393 174 ;
+C 45 ; WX 600 ; N hyphen ; B 100 203 500 313 ;
+C 46 ; WX 600 ; N period ; B 192 -15 408 171 ;
+C 47 ; WX 600 ; N slash ; B 98 -77 502 626 ;
+C 48 ; WX 600 ; N zero ; B 87 -15 513 616 ;
+C 49 ; WX 600 ; N one ; B 81 0 539 616 ;
+C 50 ; WX 600 ; N two ; B 61 0 499 616 ;
+C 51 ; WX 600 ; N three ; B 63 -15 501 616 ;
+C 52 ; WX 600 ; N four ; B 53 0 507 616 ;
+C 53 ; WX 600 ; N five ; B 70 -15 521 601 ;
+C 54 ; WX 600 ; N six ; B 90 -15 521 616 ;
+C 55 ; WX 600 ; N seven ; B 55 0 494 601 ;
+C 56 ; WX 600 ; N eight ; B 83 -15 517 616 ;
+C 57 ; WX 600 ; N nine ; B 79 -15 510 616 ;
+C 58 ; WX 600 ; N colon ; B 191 -15 407 425 ;
+C 59 ; WX 600 ; N semicolon ; B 123 -111 408 425 ;
+C 60 ; WX 600 ; N less ; B 66 15 523 501 ;
+C 61 ; WX 600 ; N equal ; B 71 118 529 398 ;
+C 62 ; WX 600 ; N greater ; B 77 15 534 501 ;
+C 63 ; WX 600 ; N question ; B 98 -14 501 580 ;
+C 64 ; WX 600 ; N at ; B 16 -15 584 616 ;
+C 65 ; WX 600 ; N A ; B -9 0 609 562 ;
+C 66 ; WX 600 ; N B ; B 30 0 573 562 ;
+C 67 ; WX 600 ; N C ; B 22 -18 560 580 ;
+C 68 ; WX 600 ; N D ; B 30 0 594 562 ;
+C 69 ; WX 600 ; N E ; B 25 0 560 562 ;
+C 70 ; WX 600 ; N F ; B 39 0 570 562 ;
+C 71 ; WX 600 ; N G ; B 22 -18 594 580 ;
+C 72 ; WX 600 ; N H ; B 20 0 580 562 ;
+C 73 ; WX 600 ; N I ; B 77 0 523 562 ;
+C 74 ; WX 600 ; N J ; B 37 -18 601 562 ;
+C 75 ; WX 600 ; N K ; B 21 0 599 562 ;
+C 76 ; WX 600 ; N L ; B 39 0 578 562 ;
+C 77 ; WX 600 ; N M ; B -2 0 602 562 ;
+C 78 ; WX 600 ; N N ; B 8 -12 610 562 ;
+C 79 ; WX 600 ; N O ; B 22 -18 578 580 ;
+C 80 ; WX 600 ; N P ; B 48 0 559 562 ;
+C 81 ; WX 600 ; N Q ; B 32 -138 578 580 ;
+C 82 ; WX 600 ; N R ; B 24 0 599 562 ;
+C 83 ; WX 600 ; N S ; B 47 -22 553 582 ;
+C 84 ; WX 600 ; N T ; B 21 0 579 562 ;
+C 85 ; WX 600 ; N U ; B 4 -18 596 562 ;
+C 86 ; WX 600 ; N V ; B -13 0 613 562 ;
+C 87 ; WX 600 ; N W ; B -18 0 618 562 ;
+C 88 ; WX 600 ; N X ; B 12 0 588 562 ;
+C 89 ; WX 600 ; N Y ; B 12 0 589 562 ;
+C 90 ; WX 600 ; N Z ; B 62 0 539 562 ;
+C 91 ; WX 600 ; N bracketleft ; B 245 -102 475 616 ;
+C 92 ; WX 600 ; N backslash ; B 99 -77 503 626 ;
+C 93 ; WX 600 ; N bracketright ; B 125 -102 355 616 ;
+C 94 ; WX 600 ; N asciicircum ; B 108 250 492 616 ;
+C 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ;
+C 96 ; WX 600 ; N quoteleft ; B 178 277 428 562 ;
+C 97 ; WX 600 ; N a ; B 35 -15 570 454 ;
+C 98 ; WX 600 ; N b ; B 0 -15 584 626 ;
+C 99 ; WX 600 ; N c ; B 40 -15 545 459 ;
+C 100 ; WX 600 ; N d ; B 20 -15 591 626 ;
+C 101 ; WX 600 ; N e ; B 40 -15 563 454 ;
+C 102 ; WX 600 ; N f ; B 83 0 547 626 ; L i fi ; L l fl ;
+C 103 ; WX 600 ; N g ; B 30 -146 580 454 ;
+C 104 ; WX 600 ; N h ; B 5 0 592 626 ;
+C 105 ; WX 600 ; N i ; B 77 0 523 658 ;
+C 106 ; WX 600 ; N j ; B 63 -146 440 658 ;
+C 107 ; WX 600 ; N k ; B 20 0 585 626 ;
+C 108 ; WX 600 ; N l ; B 77 0 523 626 ;
+C 109 ; WX 600 ; N m ; B -22 0 626 454 ;
+C 110 ; WX 600 ; N n ; B 18 0 592 454 ;
+C 111 ; WX 600 ; N o ; B 30 -15 570 454 ;
+C 112 ; WX 600 ; N p ; B -1 -142 570 454 ;
+C 113 ; WX 600 ; N q ; B 20 -142 591 454 ;
+C 114 ; WX 600 ; N r ; B 47 0 580 454 ;
+C 115 ; WX 600 ; N s ; B 68 -17 535 459 ;
+C 116 ; WX 600 ; N t ; B 47 -15 532 562 ;
+C 117 ; WX 600 ; N u ; B -1 -15 569 439 ;
+C 118 ; WX 600 ; N v ; B -1 0 601 439 ;
+C 119 ; WX 600 ; N w ; B -18 0 618 439 ;
+C 120 ; WX 600 ; N x ; B 6 0 594 439 ;
+C 121 ; WX 600 ; N y ; B -4 -142 601 439 ;
+C 122 ; WX 600 ; N z ; B 81 0 520 439 ;
+C 123 ; WX 600 ; N braceleft ; B 160 -102 464 616 ;
+C 124 ; WX 600 ; N bar ; B 255 -250 345 750 ;
+C 125 ; WX 600 ; N braceright ; B 136 -102 440 616 ;
+C 126 ; WX 600 ; N asciitilde ; B 71 153 530 356 ;
+C 161 ; WX 600 ; N exclamdown ; B 202 -146 398 449 ;
+C 162 ; WX 600 ; N cent ; B 66 -49 518 614 ;
+C 163 ; WX 600 ; N sterling ; B 72 -28 558 611 ;
+C 164 ; WX 600 ; N fraction ; B 25 -60 576 661 ;
+C 165 ; WX 600 ; N yen ; B 10 0 590 562 ;
+C 166 ; WX 600 ; N florin ; B -30 -131 572 616 ;
+C 167 ; WX 600 ; N section ; B 83 -70 517 580 ;
+C 168 ; WX 600 ; N currency ; B 54 49 546 517 ;
+C 169 ; WX 600 ; N quotesingle ; B 227 277 373 562 ;
+C 170 ; WX 600 ; N quotedblleft ; B 71 277 535 562 ;
+C 171 ; WX 600 ; N guillemotleft ; B 8 70 553 446 ;
+C 172 ; WX 600 ; N guilsinglleft ; B 141 70 459 446 ;
+C 173 ; WX 600 ; N guilsinglright ; B 141 70 459 446 ;
+C 174 ; WX 600 ; N fi ; B 12 0 593 626 ;
+C 175 ; WX 600 ; N fl ; B 12 0 593 626 ;
+C 177 ; WX 600 ; N endash ; B 65 203 535 313 ;
+C 178 ; WX 600 ; N dagger ; B 106 -70 494 580 ;
+C 179 ; WX 600 ; N daggerdbl ; B 106 -70 494 580 ;
+C 180 ; WX 600 ; N periodcentered ; B 196 165 404 351 ;
+C 182 ; WX 600 ; N paragraph ; B 6 -70 576 580 ;
+C 183 ; WX 600 ; N bullet ; B 140 132 460 430 ;
+C 184 ; WX 600 ; N quotesinglbase ; B 175 -142 427 143 ;
+C 185 ; WX 600 ; N quotedblbase ; B 65 -142 529 143 ;
+C 186 ; WX 600 ; N quotedblright ; B 61 277 525 562 ;
+C 187 ; WX 600 ; N guillemotright ; B 47 70 592 446 ;
+C 188 ; WX 600 ; N ellipsis ; B 26 -15 574 116 ;
+C 189 ; WX 600 ; N perthousand ; B -113 -15 713 616 ;
+C 191 ; WX 600 ; N questiondown ; B 99 -146 502 449 ;
+C 193 ; WX 600 ; N grave ; B 132 508 395 661 ;
+C 194 ; WX 600 ; N acute ; B 205 508 468 661 ;
+C 195 ; WX 600 ; N circumflex ; B 103 483 497 657 ;
+C 196 ; WX 600 ; N tilde ; B 89 493 512 636 ;
+C 197 ; WX 600 ; N macron ; B 88 505 512 585 ;
+C 198 ; WX 600 ; N breve ; B 83 468 517 631 ;
+C 199 ; WX 600 ; N dotaccent ; B 230 498 370 638 ;
+C 200 ; WX 600 ; N dieresis ; B 128 498 472 638 ;
+C 202 ; WX 600 ; N ring ; B 198 481 402 678 ;
+C 203 ; WX 600 ; N cedilla ; B 205 -206 387 0 ;
+C 205 ; WX 600 ; N hungarumlaut ; B 68 488 588 661 ;
+C 206 ; WX 600 ; N ogonek ; B 169 -199 400 0 ;
+C 207 ; WX 600 ; N caron ; B 103 493 497 667 ;
+C 208 ; WX 600 ; N emdash ; B -10 203 610 313 ;
+C 225 ; WX 600 ; N AE ; B -29 0 602 562 ;
+C 227 ; WX 600 ; N ordfeminine ; B 147 196 453 580 ;
+C 232 ; WX 600 ; N Lslash ; B 39 0 578 562 ;
+C 233 ; WX 600 ; N Oslash ; B 22 -22 578 584 ;
+C 234 ; WX 600 ; N OE ; B -25 0 595 562 ;
+C 235 ; WX 600 ; N ordmasculine ; B 147 196 453 580 ;
+C 241 ; WX 600 ; N ae ; B -4 -15 601 454 ;
+C 245 ; WX 600 ; N dotlessi ; B 77 0 523 439 ;
+C 248 ; WX 600 ; N lslash ; B 77 0 523 626 ;
+C 249 ; WX 600 ; N oslash ; B 30 -24 570 463 ;
+C 250 ; WX 600 ; N oe ; B -18 -15 611 454 ;
+C 251 ; WX 600 ; N germandbls ; B 22 -15 596 626 ;
+C -1 ; WX 600 ; N Idieresis ; B 77 0 523 761 ;
+C -1 ; WX 600 ; N eacute ; B 40 -15 563 661 ;
+C -1 ; WX 600 ; N abreve ; B 35 -15 570 661 ;
+C -1 ; WX 600 ; N uhungarumlaut ; B -1 -15 628 661 ;
+C -1 ; WX 600 ; N ecaron ; B 40 -15 563 667 ;
+C -1 ; WX 600 ; N Ydieresis ; B 12 0 589 761 ;
+C -1 ; WX 600 ; N divide ; B 71 16 529 500 ;
+C -1 ; WX 600 ; N Yacute ; B 12 0 589 784 ;
+C -1 ; WX 600 ; N Acircumflex ; B -9 0 609 780 ;
+C -1 ; WX 600 ; N aacute ; B 35 -15 570 661 ;
+C -1 ; WX 600 ; N Ucircumflex ; B 4 -18 596 780 ;
+C -1 ; WX 600 ; N yacute ; B -4 -142 601 661 ;
+C -1 ; WX 600 ; N scommaaccent ; B 68 -250 535 459 ;
+C -1 ; WX 600 ; N ecircumflex ; B 40 -15 563 657 ;
+C -1 ; WX 600 ; N Uring ; B 4 -18 596 801 ;
+C -1 ; WX 600 ; N Udieresis ; B 4 -18 596 761 ;
+C -1 ; WX 600 ; N aogonek ; B 35 -199 586 454 ;
+C -1 ; WX 600 ; N Uacute ; B 4 -18 596 784 ;
+C -1 ; WX 600 ; N uogonek ; B -1 -199 585 439 ;
+C -1 ; WX 600 ; N Edieresis ; B 25 0 560 761 ;
+C -1 ; WX 600 ; N Dcroat ; B 30 0 594 562 ;
+C -1 ; WX 600 ; N commaaccent ; B 205 -250 397 -57 ;
+C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ;
+C -1 ; WX 600 ; N Emacron ; B 25 0 560 708 ;
+C -1 ; WX 600 ; N ccaron ; B 40 -15 545 667 ;
+C -1 ; WX 600 ; N aring ; B 35 -15 570 678 ;
+C -1 ; WX 600 ; N Ncommaaccent ; B 8 -250 610 562 ;
+C -1 ; WX 600 ; N lacute ; B 77 0 523 801 ;
+C -1 ; WX 600 ; N agrave ; B 35 -15 570 661 ;
+C -1 ; WX 600 ; N Tcommaaccent ; B 21 -250 579 562 ;
+C -1 ; WX 600 ; N Cacute ; B 22 -18 560 784 ;
+C -1 ; WX 600 ; N atilde ; B 35 -15 570 636 ;
+C -1 ; WX 600 ; N Edotaccent ; B 25 0 560 761 ;
+C -1 ; WX 600 ; N scaron ; B 68 -17 535 667 ;
+C -1 ; WX 600 ; N scedilla ; B 68 -206 535 459 ;
+C -1 ; WX 600 ; N iacute ; B 77 0 523 661 ;
+C -1 ; WX 600 ; N lozenge ; B 66 0 534 740 ;
+C -1 ; WX 600 ; N Rcaron ; B 24 0 599 790 ;
+C -1 ; WX 600 ; N Gcommaaccent ; B 22 -250 594 580 ;
+C -1 ; WX 600 ; N ucircumflex ; B -1 -15 569 657 ;
+C -1 ; WX 600 ; N acircumflex ; B 35 -15 570 657 ;
+C -1 ; WX 600 ; N Amacron ; B -9 0 609 708 ;
+C -1 ; WX 600 ; N rcaron ; B 47 0 580 667 ;
+C -1 ; WX 600 ; N ccedilla ; B 40 -206 545 459 ;
+C -1 ; WX 600 ; N Zdotaccent ; B 62 0 539 761 ;
+C -1 ; WX 600 ; N Thorn ; B 48 0 557 562 ;
+C -1 ; WX 600 ; N Omacron ; B 22 -18 578 708 ;
+C -1 ; WX 600 ; N Racute ; B 24 0 599 784 ;
+C -1 ; WX 600 ; N Sacute ; B 47 -22 553 784 ;
+C -1 ; WX 600 ; N dcaron ; B 20 -15 727 626 ;
+C -1 ; WX 600 ; N Umacron ; B 4 -18 596 708 ;
+C -1 ; WX 600 ; N uring ; B -1 -15 569 678 ;
+C -1 ; WX 600 ; N threesuperior ; B 138 222 433 616 ;
+C -1 ; WX 600 ; N Ograve ; B 22 -18 578 784 ;
+C -1 ; WX 600 ; N Agrave ; B -9 0 609 784 ;
+C -1 ; WX 600 ; N Abreve ; B -9 0 609 784 ;
+C -1 ; WX 600 ; N multiply ; B 81 39 520 478 ;
+C -1 ; WX 600 ; N uacute ; B -1 -15 569 661 ;
+C -1 ; WX 600 ; N Tcaron ; B 21 0 579 790 ;
+C -1 ; WX 600 ; N partialdiff ; B 63 -38 537 728 ;
+C -1 ; WX 600 ; N ydieresis ; B -4 -142 601 638 ;
+C -1 ; WX 600 ; N Nacute ; B 8 -12 610 784 ;
+C -1 ; WX 600 ; N icircumflex ; B 73 0 523 657 ;
+C -1 ; WX 600 ; N Ecircumflex ; B 25 0 560 780 ;
+C -1 ; WX 600 ; N adieresis ; B 35 -15 570 638 ;
+C -1 ; WX 600 ; N edieresis ; B 40 -15 563 638 ;
+C -1 ; WX 600 ; N cacute ; B 40 -15 545 661 ;
+C -1 ; WX 600 ; N nacute ; B 18 0 592 661 ;
+C -1 ; WX 600 ; N umacron ; B -1 -15 569 585 ;
+C -1 ; WX 600 ; N Ncaron ; B 8 -12 610 790 ;
+C -1 ; WX 600 ; N Iacute ; B 77 0 523 784 ;
+C -1 ; WX 600 ; N plusminus ; B 71 24 529 515 ;
+C -1 ; WX 600 ; N brokenbar ; B 255 -175 345 675 ;
+C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ;
+C -1 ; WX 600 ; N Gbreve ; B 22 -18 594 784 ;
+C -1 ; WX 600 ; N Idotaccent ; B 77 0 523 761 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 586 706 ;
+C -1 ; WX 600 ; N Egrave ; B 25 0 560 784 ;
+C -1 ; WX 600 ; N racute ; B 47 0 580 661 ;
+C -1 ; WX 600 ; N omacron ; B 30 -15 570 585 ;
+C -1 ; WX 600 ; N Zacute ; B 62 0 539 784 ;
+C -1 ; WX 600 ; N Zcaron ; B 62 0 539 790 ;
+C -1 ; WX 600 ; N greaterequal ; B 26 0 523 696 ;
+C -1 ; WX 600 ; N Eth ; B 30 0 594 562 ;
+C -1 ; WX 600 ; N Ccedilla ; B 22 -206 560 580 ;
+C -1 ; WX 600 ; N lcommaaccent ; B 77 -250 523 626 ;
+C -1 ; WX 600 ; N tcaron ; B 47 -15 532 703 ;
+C -1 ; WX 600 ; N eogonek ; B 40 -199 563 454 ;
+C -1 ; WX 600 ; N Uogonek ; B 4 -199 596 562 ;
+C -1 ; WX 600 ; N Aacute ; B -9 0 609 784 ;
+C -1 ; WX 600 ; N Adieresis ; B -9 0 609 761 ;
+C -1 ; WX 600 ; N egrave ; B 40 -15 563 661 ;
+C -1 ; WX 600 ; N zacute ; B 81 0 520 661 ;
+C -1 ; WX 600 ; N iogonek ; B 77 -199 523 658 ;
+C -1 ; WX 600 ; N Oacute ; B 22 -18 578 784 ;
+C -1 ; WX 600 ; N oacute ; B 30 -15 570 661 ;
+C -1 ; WX 600 ; N amacron ; B 35 -15 570 585 ;
+C -1 ; WX 600 ; N sacute ; B 68 -17 535 661 ;
+C -1 ; WX 600 ; N idieresis ; B 77 0 523 618 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 22 -18 578 780 ;
+C -1 ; WX 600 ; N Ugrave ; B 4 -18 596 784 ;
+C -1 ; WX 600 ; N Delta ; B 6 0 594 688 ;
+C -1 ; WX 600 ; N thorn ; B -14 -142 570 626 ;
+C -1 ; WX 600 ; N twosuperior ; B 143 230 436 616 ;
+C -1 ; WX 600 ; N Odieresis ; B 22 -18 578 761 ;
+C -1 ; WX 600 ; N mu ; B -1 -142 569 439 ;
+C -1 ; WX 600 ; N igrave ; B 77 0 523 661 ;
+C -1 ; WX 600 ; N ohungarumlaut ; B 30 -15 668 661 ;
+C -1 ; WX 600 ; N Eogonek ; B 25 -199 576 562 ;
+C -1 ; WX 600 ; N dcroat ; B 20 -15 591 626 ;
+C -1 ; WX 600 ; N threequarters ; B -47 -60 648 661 ;
+C -1 ; WX 600 ; N Scedilla ; B 47 -206 553 582 ;
+C -1 ; WX 600 ; N lcaron ; B 77 0 597 626 ;
+C -1 ; WX 600 ; N Kcommaaccent ; B 21 -250 599 562 ;
+C -1 ; WX 600 ; N Lacute ; B 39 0 578 784 ;
+C -1 ; WX 600 ; N trademark ; B -9 230 749 562 ;
+C -1 ; WX 600 ; N edotaccent ; B 40 -15 563 638 ;
+C -1 ; WX 600 ; N Igrave ; B 77 0 523 784 ;
+C -1 ; WX 600 ; N Imacron ; B 77 0 523 708 ;
+C -1 ; WX 600 ; N Lcaron ; B 39 0 637 562 ;
+C -1 ; WX 600 ; N onehalf ; B -47 -60 648 661 ;
+C -1 ; WX 600 ; N lessequal ; B 26 0 523 696 ;
+C -1 ; WX 600 ; N ocircumflex ; B 30 -15 570 657 ;
+C -1 ; WX 600 ; N ntilde ; B 18 0 592 636 ;
+C -1 ; WX 600 ; N Uhungarumlaut ; B 4 -18 638 784 ;
+C -1 ; WX 600 ; N Eacute ; B 25 0 560 784 ;
+C -1 ; WX 600 ; N emacron ; B 40 -15 563 585 ;
+C -1 ; WX 600 ; N gbreve ; B 30 -146 580 661 ;
+C -1 ; WX 600 ; N onequarter ; B -56 -60 656 661 ;
+C -1 ; WX 600 ; N Scaron ; B 47 -22 553 790 ;
+C -1 ; WX 600 ; N Scommaaccent ; B 47 -250 553 582 ;
+C -1 ; WX 600 ; N Ohungarumlaut ; B 22 -18 628 784 ;
+C -1 ; WX 600 ; N degree ; B 86 243 474 616 ;
+C -1 ; WX 600 ; N ograve ; B 30 -15 570 661 ;
+C -1 ; WX 600 ; N Ccaron ; B 22 -18 560 790 ;
+C -1 ; WX 600 ; N ugrave ; B -1 -15 569 661 ;
+C -1 ; WX 600 ; N radical ; B -19 -104 473 778 ;
+C -1 ; WX 600 ; N Dcaron ; B 30 0 594 790 ;
+C -1 ; WX 600 ; N rcommaaccent ; B 47 -250 580 454 ;
+C -1 ; WX 600 ; N Ntilde ; B 8 -12 610 759 ;
+C -1 ; WX 600 ; N otilde ; B 30 -15 570 636 ;
+C -1 ; WX 600 ; N Rcommaaccent ; B 24 -250 599 562 ;
+C -1 ; WX 600 ; N Lcommaaccent ; B 39 -250 578 562 ;
+C -1 ; WX 600 ; N Atilde ; B -9 0 609 759 ;
+C -1 ; WX 600 ; N Aogonek ; B -9 -199 625 562 ;
+C -1 ; WX 600 ; N Aring ; B -9 0 609 801 ;
+C -1 ; WX 600 ; N Otilde ; B 22 -18 578 759 ;
+C -1 ; WX 600 ; N zdotaccent ; B 81 0 520 638 ;
+C -1 ; WX 600 ; N Ecaron ; B 25 0 560 790 ;
+C -1 ; WX 600 ; N Iogonek ; B 77 -199 523 562 ;
+C -1 ; WX 600 ; N kcommaaccent ; B 20 -250 585 626 ;
+C -1 ; WX 600 ; N minus ; B 71 203 529 313 ;
+C -1 ; WX 600 ; N Icircumflex ; B 77 0 523 780 ;
+C -1 ; WX 600 ; N ncaron ; B 18 0 592 667 ;
+C -1 ; WX 600 ; N tcommaaccent ; B 47 -250 532 562 ;
+C -1 ; WX 600 ; N logicalnot ; B 71 103 529 413 ;
+C -1 ; WX 600 ; N odieresis ; B 30 -15 570 638 ;
+C -1 ; WX 600 ; N udieresis ; B -1 -15 569 638 ;
+C -1 ; WX 600 ; N notequal ; B 12 -47 537 563 ;
+C -1 ; WX 600 ; N gcommaaccent ; B 30 -146 580 714 ;
+C -1 ; WX 600 ; N eth ; B 58 -27 543 626 ;
+C -1 ; WX 600 ; N zcaron ; B 81 0 520 667 ;
+C -1 ; WX 600 ; N ncommaaccent ; B 18 -250 592 454 ;
+C -1 ; WX 600 ; N onesuperior ; B 153 230 447 616 ;
+C -1 ; WX 600 ; N imacron ; B 77 0 523 585 ;
+C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Courier-BoldOblique.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Courier-BoldOblique.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Courier-BoldOblique.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Courier-BoldOblique.afm 2004-05-26 16:06:20.000000000 +0000
@@ -0,0 +1,342 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Mon Jun 23 16:28:46 1997
+Comment UniqueID 43049
+Comment VMusage 17529 79244
+FontName Courier-BoldOblique
+FullName Courier Bold Oblique
+FamilyName Courier
+Weight Bold
+ItalicAngle -12
+IsFixedPitch true
+CharacterSet ExtendedRoman
+FontBBox -57 -250 869 801
+UnderlinePosition -100
+UnderlineThickness 50
+Version 003.000
+Notice Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 562
+XHeight 439
+Ascender 629
+Descender -157
+StdHW 84
+StdVW 106
+StartCharMetrics 315
+C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 600 ; N exclam ; B 215 -15 495 572 ;
+C 34 ; WX 600 ; N quotedbl ; B 211 277 585 562 ;
+C 35 ; WX 600 ; N numbersign ; B 88 -45 641 651 ;
+C 36 ; WX 600 ; N dollar ; B 87 -126 630 666 ;
+C 37 ; WX 600 ; N percent ; B 101 -15 625 616 ;
+C 38 ; WX 600 ; N ampersand ; B 61 -15 595 543 ;
+C 39 ; WX 600 ; N quoteright ; B 229 277 543 562 ;
+C 40 ; WX 600 ; N parenleft ; B 265 -102 592 616 ;
+C 41 ; WX 600 ; N parenright ; B 117 -102 444 616 ;
+C 42 ; WX 600 ; N asterisk ; B 179 219 598 601 ;
+C 43 ; WX 600 ; N plus ; B 114 39 596 478 ;
+C 44 ; WX 600 ; N comma ; B 99 -111 430 174 ;
+C 45 ; WX 600 ; N hyphen ; B 143 203 567 313 ;
+C 46 ; WX 600 ; N period ; B 206 -15 427 171 ;
+C 47 ; WX 600 ; N slash ; B 90 -77 626 626 ;
+C 48 ; WX 600 ; N zero ; B 135 -15 593 616 ;
+C 49 ; WX 600 ; N one ; B 93 0 562 616 ;
+C 50 ; WX 600 ; N two ; B 61 0 594 616 ;
+C 51 ; WX 600 ; N three ; B 71 -15 571 616 ;
+C 52 ; WX 600 ; N four ; B 81 0 559 616 ;
+C 53 ; WX 600 ; N five ; B 77 -15 621 601 ;
+C 54 ; WX 600 ; N six ; B 135 -15 652 616 ;
+C 55 ; WX 600 ; N seven ; B 147 0 622 601 ;
+C 56 ; WX 600 ; N eight ; B 115 -15 604 616 ;
+C 57 ; WX 600 ; N nine ; B 75 -15 592 616 ;
+C 58 ; WX 600 ; N colon ; B 205 -15 480 425 ;
+C 59 ; WX 600 ; N semicolon ; B 99 -111 481 425 ;
+C 60 ; WX 600 ; N less ; B 120 15 613 501 ;
+C 61 ; WX 600 ; N equal ; B 96 118 614 398 ;
+C 62 ; WX 600 ; N greater ; B 97 15 589 501 ;
+C 63 ; WX 600 ; N question ; B 183 -14 592 580 ;
+C 64 ; WX 600 ; N at ; B 65 -15 642 616 ;
+C 65 ; WX 600 ; N A ; B -9 0 632 562 ;
+C 66 ; WX 600 ; N B ; B 30 0 630 562 ;
+C 67 ; WX 600 ; N C ; B 74 -18 675 580 ;
+C 68 ; WX 600 ; N D ; B 30 0 664 562 ;
+C 69 ; WX 600 ; N E ; B 25 0 670 562 ;
+C 70 ; WX 600 ; N F ; B 39 0 684 562 ;
+C 71 ; WX 600 ; N G ; B 74 -18 675 580 ;
+C 72 ; WX 600 ; N H ; B 20 0 700 562 ;
+C 73 ; WX 600 ; N I ; B 77 0 643 562 ;
+C 74 ; WX 600 ; N J ; B 58 -18 721 562 ;
+C 75 ; WX 600 ; N K ; B 21 0 692 562 ;
+C 76 ; WX 600 ; N L ; B 39 0 636 562 ;
+C 77 ; WX 600 ; N M ; B -2 0 722 562 ;
+C 78 ; WX 600 ; N N ; B 8 -12 730 562 ;
+C 79 ; WX 600 ; N O ; B 74 -18 645 580 ;
+C 80 ; WX 600 ; N P ; B 48 0 643 562 ;
+C 81 ; WX 600 ; N Q ; B 83 -138 636 580 ;
+C 82 ; WX 600 ; N R ; B 24 0 617 562 ;
+C 83 ; WX 600 ; N S ; B 54 -22 673 582 ;
+C 84 ; WX 600 ; N T ; B 86 0 679 562 ;
+C 85 ; WX 600 ; N U ; B 101 -18 716 562 ;
+C 86 ; WX 600 ; N V ; B 84 0 733 562 ;
+C 87 ; WX 600 ; N W ; B 79 0 738 562 ;
+C 88 ; WX 600 ; N X ; B 12 0 690 562 ;
+C 89 ; WX 600 ; N Y ; B 109 0 709 562 ;
+C 90 ; WX 600 ; N Z ; B 62 0 637 562 ;
+C 91 ; WX 600 ; N bracketleft ; B 223 -102 606 616 ;
+C 92 ; WX 600 ; N backslash ; B 222 -77 496 626 ;
+C 93 ; WX 600 ; N bracketright ; B 103 -102 486 616 ;
+C 94 ; WX 600 ; N asciicircum ; B 171 250 556 616 ;
+C 95 ; WX 600 ; N underscore ; B -27 -125 585 -75 ;
+C 96 ; WX 600 ; N quoteleft ; B 297 277 487 562 ;
+C 97 ; WX 600 ; N a ; B 61 -15 593 454 ;
+C 98 ; WX 600 ; N b ; B 13 -15 636 626 ;
+C 99 ; WX 600 ; N c ; B 81 -15 631 459 ;
+C 100 ; WX 600 ; N d ; B 60 -15 645 626 ;
+C 101 ; WX 600 ; N e ; B 81 -15 605 454 ;
+C 102 ; WX 600 ; N f ; B 83 0 677 626 ; L i fi ; L l fl ;
+C 103 ; WX 600 ; N g ; B 40 -146 674 454 ;
+C 104 ; WX 600 ; N h ; B 18 0 615 626 ;
+C 105 ; WX 600 ; N i ; B 77 0 546 658 ;
+C 106 ; WX 600 ; N j ; B 36 -146 580 658 ;
+C 107 ; WX 600 ; N k ; B 33 0 643 626 ;
+C 108 ; WX 600 ; N l ; B 77 0 546 626 ;
+C 109 ; WX 600 ; N m ; B -22 0 649 454 ;
+C 110 ; WX 600 ; N n ; B 18 0 615 454 ;
+C 111 ; WX 600 ; N o ; B 71 -15 622 454 ;
+C 112 ; WX 600 ; N p ; B -32 -142 622 454 ;
+C 113 ; WX 600 ; N q ; B 60 -142 685 454 ;
+C 114 ; WX 600 ; N r ; B 47 0 655 454 ;
+C 115 ; WX 600 ; N s ; B 66 -17 608 459 ;
+C 116 ; WX 600 ; N t ; B 118 -15 567 562 ;
+C 117 ; WX 600 ; N u ; B 70 -15 592 439 ;
+C 118 ; WX 600 ; N v ; B 70 0 695 439 ;
+C 119 ; WX 600 ; N w ; B 53 0 712 439 ;
+C 120 ; WX 600 ; N x ; B 6 0 671 439 ;
+C 121 ; WX 600 ; N y ; B -21 -142 695 439 ;
+C 122 ; WX 600 ; N z ; B 81 0 614 439 ;
+C 123 ; WX 600 ; N braceleft ; B 203 -102 595 616 ;
+C 124 ; WX 600 ; N bar ; B 201 -250 505 750 ;
+C 125 ; WX 600 ; N braceright ; B 114 -102 506 616 ;
+C 126 ; WX 600 ; N asciitilde ; B 120 153 590 356 ;
+C 161 ; WX 600 ; N exclamdown ; B 196 -146 477 449 ;
+C 162 ; WX 600 ; N cent ; B 121 -49 605 614 ;
+C 163 ; WX 600 ; N sterling ; B 106 -28 650 611 ;
+C 164 ; WX 600 ; N fraction ; B 22 -60 708 661 ;
+C 165 ; WX 600 ; N yen ; B 98 0 710 562 ;
+C 166 ; WX 600 ; N florin ; B -57 -131 702 616 ;
+C 167 ; WX 600 ; N section ; B 74 -70 620 580 ;
+C 168 ; WX 600 ; N currency ; B 77 49 644 517 ;
+C 169 ; WX 600 ; N quotesingle ; B 303 277 493 562 ;
+C 170 ; WX 600 ; N quotedblleft ; B 190 277 594 562 ;
+C 171 ; WX 600 ; N guillemotleft ; B 62 70 639 446 ;
+C 172 ; WX 600 ; N guilsinglleft ; B 195 70 545 446 ;
+C 173 ; WX 600 ; N guilsinglright ; B 165 70 514 446 ;
+C 174 ; WX 600 ; N fi ; B 12 0 644 626 ;
+C 175 ; WX 600 ; N fl ; B 12 0 644 626 ;
+C 177 ; WX 600 ; N endash ; B 108 203 602 313 ;
+C 178 ; WX 600 ; N dagger ; B 175 -70 586 580 ;
+C 179 ; WX 600 ; N daggerdbl ; B 121 -70 587 580 ;
+C 180 ; WX 600 ; N periodcentered ; B 248 165 461 351 ;
+C 182 ; WX 600 ; N paragraph ; B 61 -70 700 580 ;
+C 183 ; WX 600 ; N bullet ; B 196 132 523 430 ;
+C 184 ; WX 600 ; N quotesinglbase ; B 144 -142 458 143 ;
+C 185 ; WX 600 ; N quotedblbase ; B 34 -142 560 143 ;
+C 186 ; WX 600 ; N quotedblright ; B 119 277 645 562 ;
+C 187 ; WX 600 ; N guillemotright ; B 71 70 647 446 ;
+C 188 ; WX 600 ; N ellipsis ; B 35 -15 587 116 ;
+C 189 ; WX 600 ; N perthousand ; B -45 -15 743 616 ;
+C 191 ; WX 600 ; N questiondown ; B 100 -146 509 449 ;
+C 193 ; WX 600 ; N grave ; B 272 508 503 661 ;
+C 194 ; WX 600 ; N acute ; B 312 508 609 661 ;
+C 195 ; WX 600 ; N circumflex ; B 212 483 607 657 ;
+C 196 ; WX 600 ; N tilde ; B 199 493 643 636 ;
+C 197 ; WX 600 ; N macron ; B 195 505 637 585 ;
+C 198 ; WX 600 ; N breve ; B 217 468 652 631 ;
+C 199 ; WX 600 ; N dotaccent ; B 348 498 493 638 ;
+C 200 ; WX 600 ; N dieresis ; B 246 498 595 638 ;
+C 202 ; WX 600 ; N ring ; B 319 481 528 678 ;
+C 203 ; WX 600 ; N cedilla ; B 168 -206 368 0 ;
+C 205 ; WX 600 ; N hungarumlaut ; B 171 488 729 661 ;
+C 206 ; WX 600 ; N ogonek ; B 143 -199 367 0 ;
+C 207 ; WX 600 ; N caron ; B 238 493 633 667 ;
+C 208 ; WX 600 ; N emdash ; B 33 203 677 313 ;
+C 225 ; WX 600 ; N AE ; B -29 0 708 562 ;
+C 227 ; WX 600 ; N ordfeminine ; B 188 196 526 580 ;
+C 232 ; WX 600 ; N Lslash ; B 39 0 636 562 ;
+C 233 ; WX 600 ; N Oslash ; B 48 -22 673 584 ;
+C 234 ; WX 600 ; N OE ; B 26 0 701 562 ;
+C 235 ; WX 600 ; N ordmasculine ; B 188 196 543 580 ;
+C 241 ; WX 600 ; N ae ; B 21 -15 652 454 ;
+C 245 ; WX 600 ; N dotlessi ; B 77 0 546 439 ;
+C 248 ; WX 600 ; N lslash ; B 77 0 587 626 ;
+C 249 ; WX 600 ; N oslash ; B 54 -24 638 463 ;
+C 250 ; WX 600 ; N oe ; B 18 -15 662 454 ;
+C 251 ; WX 600 ; N germandbls ; B 22 -15 629 626 ;
+C -1 ; WX 600 ; N Idieresis ; B 77 0 643 761 ;
+C -1 ; WX 600 ; N eacute ; B 81 -15 609 661 ;
+C -1 ; WX 600 ; N abreve ; B 61 -15 658 661 ;
+C -1 ; WX 600 ; N uhungarumlaut ; B 70 -15 769 661 ;
+C -1 ; WX 600 ; N ecaron ; B 81 -15 633 667 ;
+C -1 ; WX 600 ; N Ydieresis ; B 109 0 709 761 ;
+C -1 ; WX 600 ; N divide ; B 114 16 596 500 ;
+C -1 ; WX 600 ; N Yacute ; B 109 0 709 784 ;
+C -1 ; WX 600 ; N Acircumflex ; B -9 0 632 780 ;
+C -1 ; WX 600 ; N aacute ; B 61 -15 609 661 ;
+C -1 ; WX 600 ; N Ucircumflex ; B 101 -18 716 780 ;
+C -1 ; WX 600 ; N yacute ; B -21 -142 695 661 ;
+C -1 ; WX 600 ; N scommaaccent ; B 66 -250 608 459 ;
+C -1 ; WX 600 ; N ecircumflex ; B 81 -15 607 657 ;
+C -1 ; WX 600 ; N Uring ; B 101 -18 716 801 ;
+C -1 ; WX 600 ; N Udieresis ; B 101 -18 716 761 ;
+C -1 ; WX 600 ; N aogonek ; B 61 -199 593 454 ;
+C -1 ; WX 600 ; N Uacute ; B 101 -18 716 784 ;
+C -1 ; WX 600 ; N uogonek ; B 70 -199 592 439 ;
+C -1 ; WX 600 ; N Edieresis ; B 25 0 670 761 ;
+C -1 ; WX 600 ; N Dcroat ; B 30 0 664 562 ;
+C -1 ; WX 600 ; N commaaccent ; B 151 -250 385 -57 ;
+C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ;
+C -1 ; WX 600 ; N Emacron ; B 25 0 670 708 ;
+C -1 ; WX 600 ; N ccaron ; B 81 -15 633 667 ;
+C -1 ; WX 600 ; N aring ; B 61 -15 593 678 ;
+C -1 ; WX 600 ; N Ncommaaccent ; B 8 -250 730 562 ;
+C -1 ; WX 600 ; N lacute ; B 77 0 639 801 ;
+C -1 ; WX 600 ; N agrave ; B 61 -15 593 661 ;
+C -1 ; WX 600 ; N Tcommaaccent ; B 86 -250 679 562 ;
+C -1 ; WX 600 ; N Cacute ; B 74 -18 675 784 ;
+C -1 ; WX 600 ; N atilde ; B 61 -15 643 636 ;
+C -1 ; WX 600 ; N Edotaccent ; B 25 0 670 761 ;
+C -1 ; WX 600 ; N scaron ; B 66 -17 633 667 ;
+C -1 ; WX 600 ; N scedilla ; B 66 -206 608 459 ;
+C -1 ; WX 600 ; N iacute ; B 77 0 609 661 ;
+C -1 ; WX 600 ; N lozenge ; B 145 0 614 740 ;
+C -1 ; WX 600 ; N Rcaron ; B 24 0 659 790 ;
+C -1 ; WX 600 ; N Gcommaaccent ; B 74 -250 675 580 ;
+C -1 ; WX 600 ; N ucircumflex ; B 70 -15 597 657 ;
+C -1 ; WX 600 ; N acircumflex ; B 61 -15 607 657 ;
+C -1 ; WX 600 ; N Amacron ; B -9 0 633 708 ;
+C -1 ; WX 600 ; N rcaron ; B 47 0 655 667 ;
+C -1 ; WX 600 ; N ccedilla ; B 81 -206 631 459 ;
+C -1 ; WX 600 ; N Zdotaccent ; B 62 0 637 761 ;
+C -1 ; WX 600 ; N Thorn ; B 48 0 620 562 ;
+C -1 ; WX 600 ; N Omacron ; B 74 -18 663 708 ;
+C -1 ; WX 600 ; N Racute ; B 24 0 665 784 ;
+C -1 ; WX 600 ; N Sacute ; B 54 -22 673 784 ;
+C -1 ; WX 600 ; N dcaron ; B 60 -15 861 626 ;
+C -1 ; WX 600 ; N Umacron ; B 101 -18 716 708 ;
+C -1 ; WX 600 ; N uring ; B 70 -15 592 678 ;
+C -1 ; WX 600 ; N threesuperior ; B 193 222 526 616 ;
+C -1 ; WX 600 ; N Ograve ; B 74 -18 645 784 ;
+C -1 ; WX 600 ; N Agrave ; B -9 0 632 784 ;
+C -1 ; WX 600 ; N Abreve ; B -9 0 684 784 ;
+C -1 ; WX 600 ; N multiply ; B 104 39 606 478 ;
+C -1 ; WX 600 ; N uacute ; B 70 -15 599 661 ;
+C -1 ; WX 600 ; N Tcaron ; B 86 0 679 790 ;
+C -1 ; WX 600 ; N partialdiff ; B 91 -38 627 728 ;
+C -1 ; WX 600 ; N ydieresis ; B -21 -142 695 638 ;
+C -1 ; WX 600 ; N Nacute ; B 8 -12 730 784 ;
+C -1 ; WX 600 ; N icircumflex ; B 77 0 577 657 ;
+C -1 ; WX 600 ; N Ecircumflex ; B 25 0 670 780 ;
+C -1 ; WX 600 ; N adieresis ; B 61 -15 595 638 ;
+C -1 ; WX 600 ; N edieresis ; B 81 -15 605 638 ;
+C -1 ; WX 600 ; N cacute ; B 81 -15 649 661 ;
+C -1 ; WX 600 ; N nacute ; B 18 0 639 661 ;
+C -1 ; WX 600 ; N umacron ; B 70 -15 637 585 ;
+C -1 ; WX 600 ; N Ncaron ; B 8 -12 730 790 ;
+C -1 ; WX 600 ; N Iacute ; B 77 0 643 784 ;
+C -1 ; WX 600 ; N plusminus ; B 76 24 614 515 ;
+C -1 ; WX 600 ; N brokenbar ; B 217 -175 489 675 ;
+C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ;
+C -1 ; WX 600 ; N Gbreve ; B 74 -18 684 784 ;
+C -1 ; WX 600 ; N Idotaccent ; B 77 0 643 761 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 672 706 ;
+C -1 ; WX 600 ; N Egrave ; B 25 0 670 784 ;
+C -1 ; WX 600 ; N racute ; B 47 0 655 661 ;
+C -1 ; WX 600 ; N omacron ; B 71 -15 637 585 ;
+C -1 ; WX 600 ; N Zacute ; B 62 0 665 784 ;
+C -1 ; WX 600 ; N Zcaron ; B 62 0 659 790 ;
+C -1 ; WX 600 ; N greaterequal ; B 26 0 627 696 ;
+C -1 ; WX 600 ; N Eth ; B 30 0 664 562 ;
+C -1 ; WX 600 ; N Ccedilla ; B 74 -206 675 580 ;
+C -1 ; WX 600 ; N lcommaaccent ; B 77 -250 546 626 ;
+C -1 ; WX 600 ; N tcaron ; B 118 -15 627 703 ;
+C -1 ; WX 600 ; N eogonek ; B 81 -199 605 454 ;
+C -1 ; WX 600 ; N Uogonek ; B 101 -199 716 562 ;
+C -1 ; WX 600 ; N Aacute ; B -9 0 655 784 ;
+C -1 ; WX 600 ; N Adieresis ; B -9 0 632 761 ;
+C -1 ; WX 600 ; N egrave ; B 81 -15 605 661 ;
+C -1 ; WX 600 ; N zacute ; B 81 0 614 661 ;
+C -1 ; WX 600 ; N iogonek ; B 77 -199 546 658 ;
+C -1 ; WX 600 ; N Oacute ; B 74 -18 645 784 ;
+C -1 ; WX 600 ; N oacute ; B 71 -15 649 661 ;
+C -1 ; WX 600 ; N amacron ; B 61 -15 637 585 ;
+C -1 ; WX 600 ; N sacute ; B 66 -17 609 661 ;
+C -1 ; WX 600 ; N idieresis ; B 77 0 561 618 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 74 -18 645 780 ;
+C -1 ; WX 600 ; N Ugrave ; B 101 -18 716 784 ;
+C -1 ; WX 600 ; N Delta ; B 6 0 594 688 ;
+C -1 ; WX 600 ; N thorn ; B -32 -142 622 626 ;
+C -1 ; WX 600 ; N twosuperior ; B 191 230 542 616 ;
+C -1 ; WX 600 ; N Odieresis ; B 74 -18 645 761 ;
+C -1 ; WX 600 ; N mu ; B 49 -142 592 439 ;
+C -1 ; WX 600 ; N igrave ; B 77 0 546 661 ;
+C -1 ; WX 600 ; N ohungarumlaut ; B 71 -15 809 661 ;
+C -1 ; WX 600 ; N Eogonek ; B 25 -199 670 562 ;
+C -1 ; WX 600 ; N dcroat ; B 60 -15 712 626 ;
+C -1 ; WX 600 ; N threequarters ; B 8 -60 699 661 ;
+C -1 ; WX 600 ; N Scedilla ; B 54 -206 673 582 ;
+C -1 ; WX 600 ; N lcaron ; B 77 0 731 626 ;
+C -1 ; WX 600 ; N Kcommaaccent ; B 21 -250 692 562 ;
+C -1 ; WX 600 ; N Lacute ; B 39 0 636 784 ;
+C -1 ; WX 600 ; N trademark ; B 86 230 869 562 ;
+C -1 ; WX 600 ; N edotaccent ; B 81 -15 605 638 ;
+C -1 ; WX 600 ; N Igrave ; B 77 0 643 784 ;
+C -1 ; WX 600 ; N Imacron ; B 77 0 663 708 ;
+C -1 ; WX 600 ; N Lcaron ; B 39 0 757 562 ;
+C -1 ; WX 600 ; N onehalf ; B 22 -60 716 661 ;
+C -1 ; WX 600 ; N lessequal ; B 26 0 671 696 ;
+C -1 ; WX 600 ; N ocircumflex ; B 71 -15 622 657 ;
+C -1 ; WX 600 ; N ntilde ; B 18 0 643 636 ;
+C -1 ; WX 600 ; N Uhungarumlaut ; B 101 -18 805 784 ;
+C -1 ; WX 600 ; N Eacute ; B 25 0 670 784 ;
+C -1 ; WX 600 ; N emacron ; B 81 -15 637 585 ;
+C -1 ; WX 600 ; N gbreve ; B 40 -146 674 661 ;
+C -1 ; WX 600 ; N onequarter ; B 13 -60 707 661 ;
+C -1 ; WX 600 ; N Scaron ; B 54 -22 689 790 ;
+C -1 ; WX 600 ; N Scommaaccent ; B 54 -250 673 582 ;
+C -1 ; WX 600 ; N Ohungarumlaut ; B 74 -18 795 784 ;
+C -1 ; WX 600 ; N degree ; B 173 243 570 616 ;
+C -1 ; WX 600 ; N ograve ; B 71 -15 622 661 ;
+C -1 ; WX 600 ; N Ccaron ; B 74 -18 689 790 ;
+C -1 ; WX 600 ; N ugrave ; B 70 -15 592 661 ;
+C -1 ; WX 600 ; N radical ; B 67 -104 635 778 ;
+C -1 ; WX 600 ; N Dcaron ; B 30 0 664 790 ;
+C -1 ; WX 600 ; N rcommaaccent ; B 47 -250 655 454 ;
+C -1 ; WX 600 ; N Ntilde ; B 8 -12 730 759 ;
+C -1 ; WX 600 ; N otilde ; B 71 -15 643 636 ;
+C -1 ; WX 600 ; N Rcommaaccent ; B 24 -250 617 562 ;
+C -1 ; WX 600 ; N Lcommaaccent ; B 39 -250 636 562 ;
+C -1 ; WX 600 ; N Atilde ; B -9 0 669 759 ;
+C -1 ; WX 600 ; N Aogonek ; B -9 -199 632 562 ;
+C -1 ; WX 600 ; N Aring ; B -9 0 632 801 ;
+C -1 ; WX 600 ; N Otilde ; B 74 -18 669 759 ;
+C -1 ; WX 600 ; N zdotaccent ; B 81 0 614 638 ;
+C -1 ; WX 600 ; N Ecaron ; B 25 0 670 790 ;
+C -1 ; WX 600 ; N Iogonek ; B 77 -199 643 562 ;
+C -1 ; WX 600 ; N kcommaaccent ; B 33 -250 643 626 ;
+C -1 ; WX 600 ; N minus ; B 114 203 596 313 ;
+C -1 ; WX 600 ; N Icircumflex ; B 77 0 643 780 ;
+C -1 ; WX 600 ; N ncaron ; B 18 0 633 667 ;
+C -1 ; WX 600 ; N tcommaaccent ; B 118 -250 567 562 ;
+C -1 ; WX 600 ; N logicalnot ; B 135 103 617 413 ;
+C -1 ; WX 600 ; N odieresis ; B 71 -15 622 638 ;
+C -1 ; WX 600 ; N udieresis ; B 70 -15 595 638 ;
+C -1 ; WX 600 ; N notequal ; B 30 -47 626 563 ;
+C -1 ; WX 600 ; N gcommaaccent ; B 40 -146 674 714 ;
+C -1 ; WX 600 ; N eth ; B 93 -27 661 626 ;
+C -1 ; WX 600 ; N zcaron ; B 81 0 643 667 ;
+C -1 ; WX 600 ; N ncommaaccent ; B 18 -250 615 454 ;
+C -1 ; WX 600 ; N onesuperior ; B 212 230 514 616 ;
+C -1 ; WX 600 ; N imacron ; B 77 0 575 585 ;
+C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Courier-Oblique.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Courier-Oblique.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Courier-Oblique.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Courier-Oblique.afm 2004-05-26 16:06:20.000000000 +0000
@@ -0,0 +1,342 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu May 1 17:37:52 1997
+Comment UniqueID 43051
+Comment VMusage 16248 75829
+FontName Courier-Oblique
+FullName Courier Oblique
+FamilyName Courier
+Weight Medium
+ItalicAngle -12
+IsFixedPitch true
+CharacterSet ExtendedRoman
+FontBBox -27 -250 849 805
+UnderlinePosition -100
+UnderlineThickness 50
+Version 003.000
+Notice Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 562
+XHeight 426
+Ascender 629
+Descender -157
+StdHW 51
+StdVW 51
+StartCharMetrics 315
+C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 600 ; N exclam ; B 243 -15 464 572 ;
+C 34 ; WX 600 ; N quotedbl ; B 273 328 532 562 ;
+C 35 ; WX 600 ; N numbersign ; B 133 -32 596 639 ;
+C 36 ; WX 600 ; N dollar ; B 108 -126 596 662 ;
+C 37 ; WX 600 ; N percent ; B 134 -15 599 622 ;
+C 38 ; WX 600 ; N ampersand ; B 87 -15 580 543 ;
+C 39 ; WX 600 ; N quoteright ; B 283 328 495 562 ;
+C 40 ; WX 600 ; N parenleft ; B 313 -108 572 622 ;
+C 41 ; WX 600 ; N parenright ; B 137 -108 396 622 ;
+C 42 ; WX 600 ; N asterisk ; B 212 257 580 607 ;
+C 43 ; WX 600 ; N plus ; B 129 44 580 470 ;
+C 44 ; WX 600 ; N comma ; B 157 -112 370 122 ;
+C 45 ; WX 600 ; N hyphen ; B 152 231 558 285 ;
+C 46 ; WX 600 ; N period ; B 238 -15 382 109 ;
+C 47 ; WX 600 ; N slash ; B 112 -80 604 629 ;
+C 48 ; WX 600 ; N zero ; B 154 -15 575 622 ;
+C 49 ; WX 600 ; N one ; B 98 0 515 622 ;
+C 50 ; WX 600 ; N two ; B 70 0 568 622 ;
+C 51 ; WX 600 ; N three ; B 82 -15 538 622 ;
+C 52 ; WX 600 ; N four ; B 108 0 541 622 ;
+C 53 ; WX 600 ; N five ; B 99 -15 589 607 ;
+C 54 ; WX 600 ; N six ; B 155 -15 629 622 ;
+C 55 ; WX 600 ; N seven ; B 182 0 612 607 ;
+C 56 ; WX 600 ; N eight ; B 132 -15 588 622 ;
+C 57 ; WX 600 ; N nine ; B 93 -15 574 622 ;
+C 58 ; WX 600 ; N colon ; B 238 -15 441 385 ;
+C 59 ; WX 600 ; N semicolon ; B 157 -112 441 385 ;
+C 60 ; WX 600 ; N less ; B 96 42 610 472 ;
+C 61 ; WX 600 ; N equal ; B 109 138 600 376 ;
+C 62 ; WX 600 ; N greater ; B 85 42 599 472 ;
+C 63 ; WX 600 ; N question ; B 222 -15 583 572 ;
+C 64 ; WX 600 ; N at ; B 127 -15 582 622 ;
+C 65 ; WX 600 ; N A ; B 3 0 607 562 ;
+C 66 ; WX 600 ; N B ; B 43 0 616 562 ;
+C 67 ; WX 600 ; N C ; B 93 -18 655 580 ;
+C 68 ; WX 600 ; N D ; B 43 0 645 562 ;
+C 69 ; WX 600 ; N E ; B 53 0 660 562 ;
+C 70 ; WX 600 ; N F ; B 53 0 660 562 ;
+C 71 ; WX 600 ; N G ; B 83 -18 645 580 ;
+C 72 ; WX 600 ; N H ; B 32 0 687 562 ;
+C 73 ; WX 600 ; N I ; B 96 0 623 562 ;
+C 74 ; WX 600 ; N J ; B 52 -18 685 562 ;
+C 75 ; WX 600 ; N K ; B 38 0 671 562 ;
+C 76 ; WX 600 ; N L ; B 47 0 607 562 ;
+C 77 ; WX 600 ; N M ; B 4 0 715 562 ;
+C 78 ; WX 600 ; N N ; B 7 -13 712 562 ;
+C 79 ; WX 600 ; N O ; B 94 -18 625 580 ;
+C 80 ; WX 600 ; N P ; B 79 0 644 562 ;
+C 81 ; WX 600 ; N Q ; B 95 -138 625 580 ;
+C 82 ; WX 600 ; N R ; B 38 0 598 562 ;
+C 83 ; WX 600 ; N S ; B 76 -20 650 580 ;
+C 84 ; WX 600 ; N T ; B 108 0 665 562 ;
+C 85 ; WX 600 ; N U ; B 125 -18 702 562 ;
+C 86 ; WX 600 ; N V ; B 105 -13 723 562 ;
+C 87 ; WX 600 ; N W ; B 106 -13 722 562 ;
+C 88 ; WX 600 ; N X ; B 23 0 675 562 ;
+C 89 ; WX 600 ; N Y ; B 133 0 695 562 ;
+C 90 ; WX 600 ; N Z ; B 86 0 610 562 ;
+C 91 ; WX 600 ; N bracketleft ; B 246 -108 574 622 ;
+C 92 ; WX 600 ; N backslash ; B 249 -80 468 629 ;
+C 93 ; WX 600 ; N bracketright ; B 135 -108 463 622 ;
+C 94 ; WX 600 ; N asciicircum ; B 175 354 587 622 ;
+C 95 ; WX 600 ; N underscore ; B -27 -125 584 -75 ;
+C 96 ; WX 600 ; N quoteleft ; B 343 328 457 562 ;
+C 97 ; WX 600 ; N a ; B 76 -15 569 441 ;
+C 98 ; WX 600 ; N b ; B 29 -15 625 629 ;
+C 99 ; WX 600 ; N c ; B 106 -15 608 441 ;
+C 100 ; WX 600 ; N d ; B 85 -15 640 629 ;
+C 101 ; WX 600 ; N e ; B 106 -15 598 441 ;
+C 102 ; WX 600 ; N f ; B 114 0 662 629 ; L i fi ; L l fl ;
+C 103 ; WX 600 ; N g ; B 61 -157 657 441 ;
+C 104 ; WX 600 ; N h ; B 33 0 592 629 ;
+C 105 ; WX 600 ; N i ; B 95 0 515 657 ;
+C 106 ; WX 600 ; N j ; B 52 -157 550 657 ;
+C 107 ; WX 600 ; N k ; B 58 0 633 629 ;
+C 108 ; WX 600 ; N l ; B 95 0 515 629 ;
+C 109 ; WX 600 ; N m ; B -5 0 615 441 ;
+C 110 ; WX 600 ; N n ; B 26 0 585 441 ;
+C 111 ; WX 600 ; N o ; B 102 -15 588 441 ;
+C 112 ; WX 600 ; N p ; B -24 -157 605 441 ;
+C 113 ; WX 600 ; N q ; B 85 -157 682 441 ;
+C 114 ; WX 600 ; N r ; B 60 0 636 441 ;
+C 115 ; WX 600 ; N s ; B 78 -15 584 441 ;
+C 116 ; WX 600 ; N t ; B 167 -15 561 561 ;
+C 117 ; WX 600 ; N u ; B 101 -15 572 426 ;
+C 118 ; WX 600 ; N v ; B 90 -10 681 426 ;
+C 119 ; WX 600 ; N w ; B 76 -10 695 426 ;
+C 120 ; WX 600 ; N x ; B 20 0 655 426 ;
+C 121 ; WX 600 ; N y ; B -4 -157 683 426 ;
+C 122 ; WX 600 ; N z ; B 99 0 593 426 ;
+C 123 ; WX 600 ; N braceleft ; B 233 -108 569 622 ;
+C 124 ; WX 600 ; N bar ; B 222 -250 485 750 ;
+C 125 ; WX 600 ; N braceright ; B 140 -108 477 622 ;
+C 126 ; WX 600 ; N asciitilde ; B 116 197 600 320 ;
+C 161 ; WX 600 ; N exclamdown ; B 225 -157 445 430 ;
+C 162 ; WX 600 ; N cent ; B 151 -49 588 614 ;
+C 163 ; WX 600 ; N sterling ; B 124 -21 621 611 ;
+C 164 ; WX 600 ; N fraction ; B 84 -57 646 665 ;
+C 165 ; WX 600 ; N yen ; B 120 0 693 562 ;
+C 166 ; WX 600 ; N florin ; B -26 -143 671 622 ;
+C 167 ; WX 600 ; N section ; B 104 -78 590 580 ;
+C 168 ; WX 600 ; N currency ; B 94 58 628 506 ;
+C 169 ; WX 600 ; N quotesingle ; B 345 328 460 562 ;
+C 170 ; WX 600 ; N quotedblleft ; B 262 328 541 562 ;
+C 171 ; WX 600 ; N guillemotleft ; B 92 70 652 446 ;
+C 172 ; WX 600 ; N guilsinglleft ; B 204 70 540 446 ;
+C 173 ; WX 600 ; N guilsinglright ; B 170 70 506 446 ;
+C 174 ; WX 600 ; N fi ; B 3 0 619 629 ;
+C 175 ; WX 600 ; N fl ; B 3 0 619 629 ;
+C 177 ; WX 600 ; N endash ; B 124 231 586 285 ;
+C 178 ; WX 600 ; N dagger ; B 217 -78 546 580 ;
+C 179 ; WX 600 ; N daggerdbl ; B 163 -78 546 580 ;
+C 180 ; WX 600 ; N periodcentered ; B 275 189 434 327 ;
+C 182 ; WX 600 ; N paragraph ; B 100 -78 630 562 ;
+C 183 ; WX 600 ; N bullet ; B 224 130 485 383 ;
+C 184 ; WX 600 ; N quotesinglbase ; B 185 -134 397 100 ;
+C 185 ; WX 600 ; N quotedblbase ; B 115 -134 478 100 ;
+C 186 ; WX 600 ; N quotedblright ; B 213 328 576 562 ;
+C 187 ; WX 600 ; N guillemotright ; B 58 70 618 446 ;
+C 188 ; WX 600 ; N ellipsis ; B 46 -15 575 111 ;
+C 189 ; WX 600 ; N perthousand ; B 59 -15 627 622 ;
+C 191 ; WX 600 ; N questiondown ; B 105 -157 466 430 ;
+C 193 ; WX 600 ; N grave ; B 294 497 484 672 ;
+C 194 ; WX 600 ; N acute ; B 348 497 612 672 ;
+C 195 ; WX 600 ; N circumflex ; B 229 477 581 654 ;
+C 196 ; WX 600 ; N tilde ; B 212 489 629 606 ;
+C 197 ; WX 600 ; N macron ; B 232 525 600 565 ;
+C 198 ; WX 600 ; N breve ; B 279 501 576 609 ;
+C 199 ; WX 600 ; N dotaccent ; B 373 537 478 640 ;
+C 200 ; WX 600 ; N dieresis ; B 272 537 579 640 ;
+C 202 ; WX 600 ; N ring ; B 332 463 500 627 ;
+C 203 ; WX 600 ; N cedilla ; B 197 -151 344 10 ;
+C 205 ; WX 600 ; N hungarumlaut ; B 239 497 683 672 ;
+C 206 ; WX 600 ; N ogonek ; B 189 -172 377 4 ;
+C 207 ; WX 600 ; N caron ; B 262 492 614 669 ;
+C 208 ; WX 600 ; N emdash ; B 49 231 661 285 ;
+C 225 ; WX 600 ; N AE ; B 3 0 655 562 ;
+C 227 ; WX 600 ; N ordfeminine ; B 209 249 512 580 ;
+C 232 ; WX 600 ; N Lslash ; B 47 0 607 562 ;
+C 233 ; WX 600 ; N Oslash ; B 94 -80 625 629 ;
+C 234 ; WX 600 ; N OE ; B 59 0 672 562 ;
+C 235 ; WX 600 ; N ordmasculine ; B 210 249 535 580 ;
+C 241 ; WX 600 ; N ae ; B 41 -15 626 441 ;
+C 245 ; WX 600 ; N dotlessi ; B 95 0 515 426 ;
+C 248 ; WX 600 ; N lslash ; B 95 0 587 629 ;
+C 249 ; WX 600 ; N oslash ; B 102 -80 588 506 ;
+C 250 ; WX 600 ; N oe ; B 54 -15 615 441 ;
+C 251 ; WX 600 ; N germandbls ; B 48 -15 617 629 ;
+C -1 ; WX 600 ; N Idieresis ; B 96 0 623 753 ;
+C -1 ; WX 600 ; N eacute ; B 106 -15 612 672 ;
+C -1 ; WX 600 ; N abreve ; B 76 -15 576 609 ;
+C -1 ; WX 600 ; N uhungarumlaut ; B 101 -15 723 672 ;
+C -1 ; WX 600 ; N ecaron ; B 106 -15 614 669 ;
+C -1 ; WX 600 ; N Ydieresis ; B 133 0 695 753 ;
+C -1 ; WX 600 ; N divide ; B 136 48 573 467 ;
+C -1 ; WX 600 ; N Yacute ; B 133 0 695 805 ;
+C -1 ; WX 600 ; N Acircumflex ; B 3 0 607 787 ;
+C -1 ; WX 600 ; N aacute ; B 76 -15 612 672 ;
+C -1 ; WX 600 ; N Ucircumflex ; B 125 -18 702 787 ;
+C -1 ; WX 600 ; N yacute ; B -4 -157 683 672 ;
+C -1 ; WX 600 ; N scommaaccent ; B 78 -250 584 441 ;
+C -1 ; WX 600 ; N ecircumflex ; B 106 -15 598 654 ;
+C -1 ; WX 600 ; N Uring ; B 125 -18 702 760 ;
+C -1 ; WX 600 ; N Udieresis ; B 125 -18 702 753 ;
+C -1 ; WX 600 ; N aogonek ; B 76 -172 569 441 ;
+C -1 ; WX 600 ; N Uacute ; B 125 -18 702 805 ;
+C -1 ; WX 600 ; N uogonek ; B 101 -172 572 426 ;
+C -1 ; WX 600 ; N Edieresis ; B 53 0 660 753 ;
+C -1 ; WX 600 ; N Dcroat ; B 43 0 645 562 ;
+C -1 ; WX 600 ; N commaaccent ; B 145 -250 323 -58 ;
+C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ;
+C -1 ; WX 600 ; N Emacron ; B 53 0 660 698 ;
+C -1 ; WX 600 ; N ccaron ; B 106 -15 614 669 ;
+C -1 ; WX 600 ; N aring ; B 76 -15 569 627 ;
+C -1 ; WX 600 ; N Ncommaaccent ; B 7 -250 712 562 ;
+C -1 ; WX 600 ; N lacute ; B 95 0 640 805 ;
+C -1 ; WX 600 ; N agrave ; B 76 -15 569 672 ;
+C -1 ; WX 600 ; N Tcommaaccent ; B 108 -250 665 562 ;
+C -1 ; WX 600 ; N Cacute ; B 93 -18 655 805 ;
+C -1 ; WX 600 ; N atilde ; B 76 -15 629 606 ;
+C -1 ; WX 600 ; N Edotaccent ; B 53 0 660 753 ;
+C -1 ; WX 600 ; N scaron ; B 78 -15 614 669 ;
+C -1 ; WX 600 ; N scedilla ; B 78 -151 584 441 ;
+C -1 ; WX 600 ; N iacute ; B 95 0 612 672 ;
+C -1 ; WX 600 ; N lozenge ; B 94 0 519 706 ;
+C -1 ; WX 600 ; N Rcaron ; B 38 0 642 802 ;
+C -1 ; WX 600 ; N Gcommaaccent ; B 83 -250 645 580 ;
+C -1 ; WX 600 ; N ucircumflex ; B 101 -15 572 654 ;
+C -1 ; WX 600 ; N acircumflex ; B 76 -15 581 654 ;
+C -1 ; WX 600 ; N Amacron ; B 3 0 607 698 ;
+C -1 ; WX 600 ; N rcaron ; B 60 0 636 669 ;
+C -1 ; WX 600 ; N ccedilla ; B 106 -151 614 441 ;
+C -1 ; WX 600 ; N Zdotaccent ; B 86 0 610 753 ;
+C -1 ; WX 600 ; N Thorn ; B 79 0 606 562 ;
+C -1 ; WX 600 ; N Omacron ; B 94 -18 628 698 ;
+C -1 ; WX 600 ; N Racute ; B 38 0 670 805 ;
+C -1 ; WX 600 ; N Sacute ; B 76 -20 650 805 ;
+C -1 ; WX 600 ; N dcaron ; B 85 -15 849 629 ;
+C -1 ; WX 600 ; N Umacron ; B 125 -18 702 698 ;
+C -1 ; WX 600 ; N uring ; B 101 -15 572 627 ;
+C -1 ; WX 600 ; N threesuperior ; B 213 240 501 622 ;
+C -1 ; WX 600 ; N Ograve ; B 94 -18 625 805 ;
+C -1 ; WX 600 ; N Agrave ; B 3 0 607 805 ;
+C -1 ; WX 600 ; N Abreve ; B 3 0 607 732 ;
+C -1 ; WX 600 ; N multiply ; B 103 43 607 470 ;
+C -1 ; WX 600 ; N uacute ; B 101 -15 602 672 ;
+C -1 ; WX 600 ; N Tcaron ; B 108 0 665 802 ;
+C -1 ; WX 600 ; N partialdiff ; B 45 -38 546 710 ;
+C -1 ; WX 600 ; N ydieresis ; B -4 -157 683 620 ;
+C -1 ; WX 600 ; N Nacute ; B 7 -13 712 805 ;
+C -1 ; WX 600 ; N icircumflex ; B 95 0 551 654 ;
+C -1 ; WX 600 ; N Ecircumflex ; B 53 0 660 787 ;
+C -1 ; WX 600 ; N adieresis ; B 76 -15 575 620 ;
+C -1 ; WX 600 ; N edieresis ; B 106 -15 598 620 ;
+C -1 ; WX 600 ; N cacute ; B 106 -15 612 672 ;
+C -1 ; WX 600 ; N nacute ; B 26 0 602 672 ;
+C -1 ; WX 600 ; N umacron ; B 101 -15 600 565 ;
+C -1 ; WX 600 ; N Ncaron ; B 7 -13 712 802 ;
+C -1 ; WX 600 ; N Iacute ; B 96 0 640 805 ;
+C -1 ; WX 600 ; N plusminus ; B 96 44 594 558 ;
+C -1 ; WX 600 ; N brokenbar ; B 238 -175 469 675 ;
+C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ;
+C -1 ; WX 600 ; N Gbreve ; B 83 -18 645 732 ;
+C -1 ; WX 600 ; N Idotaccent ; B 96 0 623 753 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 670 706 ;
+C -1 ; WX 600 ; N Egrave ; B 53 0 660 805 ;
+C -1 ; WX 600 ; N racute ; B 60 0 636 672 ;
+C -1 ; WX 600 ; N omacron ; B 102 -15 600 565 ;
+C -1 ; WX 600 ; N Zacute ; B 86 0 670 805 ;
+C -1 ; WX 600 ; N Zcaron ; B 86 0 642 802 ;
+C -1 ; WX 600 ; N greaterequal ; B 98 0 594 710 ;
+C -1 ; WX 600 ; N Eth ; B 43 0 645 562 ;
+C -1 ; WX 600 ; N Ccedilla ; B 93 -151 658 580 ;
+C -1 ; WX 600 ; N lcommaaccent ; B 95 -250 515 629 ;
+C -1 ; WX 600 ; N tcaron ; B 167 -15 587 717 ;
+C -1 ; WX 600 ; N eogonek ; B 106 -172 598 441 ;
+C -1 ; WX 600 ; N Uogonek ; B 124 -172 702 562 ;
+C -1 ; WX 600 ; N Aacute ; B 3 0 660 805 ;
+C -1 ; WX 600 ; N Adieresis ; B 3 0 607 753 ;
+C -1 ; WX 600 ; N egrave ; B 106 -15 598 672 ;
+C -1 ; WX 600 ; N zacute ; B 99 0 612 672 ;
+C -1 ; WX 600 ; N iogonek ; B 95 -172 515 657 ;
+C -1 ; WX 600 ; N Oacute ; B 94 -18 640 805 ;
+C -1 ; WX 600 ; N oacute ; B 102 -15 612 672 ;
+C -1 ; WX 600 ; N amacron ; B 76 -15 600 565 ;
+C -1 ; WX 600 ; N sacute ; B 78 -15 612 672 ;
+C -1 ; WX 600 ; N idieresis ; B 95 0 545 620 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 94 -18 625 787 ;
+C -1 ; WX 600 ; N Ugrave ; B 125 -18 702 805 ;
+C -1 ; WX 600 ; N Delta ; B 6 0 598 688 ;
+C -1 ; WX 600 ; N thorn ; B -24 -157 605 629 ;
+C -1 ; WX 600 ; N twosuperior ; B 230 249 535 622 ;
+C -1 ; WX 600 ; N Odieresis ; B 94 -18 625 753 ;
+C -1 ; WX 600 ; N mu ; B 72 -157 572 426 ;
+C -1 ; WX 600 ; N igrave ; B 95 0 515 672 ;
+C -1 ; WX 600 ; N ohungarumlaut ; B 102 -15 723 672 ;
+C -1 ; WX 600 ; N Eogonek ; B 53 -172 660 562 ;
+C -1 ; WX 600 ; N dcroat ; B 85 -15 704 629 ;
+C -1 ; WX 600 ; N threequarters ; B 73 -56 659 666 ;
+C -1 ; WX 600 ; N Scedilla ; B 76 -151 650 580 ;
+C -1 ; WX 600 ; N lcaron ; B 95 0 667 629 ;
+C -1 ; WX 600 ; N Kcommaaccent ; B 38 -250 671 562 ;
+C -1 ; WX 600 ; N Lacute ; B 47 0 607 805 ;
+C -1 ; WX 600 ; N trademark ; B 75 263 742 562 ;
+C -1 ; WX 600 ; N edotaccent ; B 106 -15 598 620 ;
+C -1 ; WX 600 ; N Igrave ; B 96 0 623 805 ;
+C -1 ; WX 600 ; N Imacron ; B 96 0 628 698 ;
+C -1 ; WX 600 ; N Lcaron ; B 47 0 632 562 ;
+C -1 ; WX 600 ; N onehalf ; B 65 -57 669 665 ;
+C -1 ; WX 600 ; N lessequal ; B 98 0 645 710 ;
+C -1 ; WX 600 ; N ocircumflex ; B 102 -15 588 654 ;
+C -1 ; WX 600 ; N ntilde ; B 26 0 629 606 ;
+C -1 ; WX 600 ; N Uhungarumlaut ; B 125 -18 761 805 ;
+C -1 ; WX 600 ; N Eacute ; B 53 0 670 805 ;
+C -1 ; WX 600 ; N emacron ; B 106 -15 600 565 ;
+C -1 ; WX 600 ; N gbreve ; B 61 -157 657 609 ;
+C -1 ; WX 600 ; N onequarter ; B 65 -57 674 665 ;
+C -1 ; WX 600 ; N Scaron ; B 76 -20 672 802 ;
+C -1 ; WX 600 ; N Scommaaccent ; B 76 -250 650 580 ;
+C -1 ; WX 600 ; N Ohungarumlaut ; B 94 -18 751 805 ;
+C -1 ; WX 600 ; N degree ; B 214 269 576 622 ;
+C -1 ; WX 600 ; N ograve ; B 102 -15 588 672 ;
+C -1 ; WX 600 ; N Ccaron ; B 93 -18 672 802 ;
+C -1 ; WX 600 ; N ugrave ; B 101 -15 572 672 ;
+C -1 ; WX 600 ; N radical ; B 85 -15 765 792 ;
+C -1 ; WX 600 ; N Dcaron ; B 43 0 645 802 ;
+C -1 ; WX 600 ; N rcommaaccent ; B 60 -250 636 441 ;
+C -1 ; WX 600 ; N Ntilde ; B 7 -13 712 729 ;
+C -1 ; WX 600 ; N otilde ; B 102 -15 629 606 ;
+C -1 ; WX 600 ; N Rcommaaccent ; B 38 -250 598 562 ;
+C -1 ; WX 600 ; N Lcommaaccent ; B 47 -250 607 562 ;
+C -1 ; WX 600 ; N Atilde ; B 3 0 655 729 ;
+C -1 ; WX 600 ; N Aogonek ; B 3 -172 607 562 ;
+C -1 ; WX 600 ; N Aring ; B 3 0 607 750 ;
+C -1 ; WX 600 ; N Otilde ; B 94 -18 655 729 ;
+C -1 ; WX 600 ; N zdotaccent ; B 99 0 593 620 ;
+C -1 ; WX 600 ; N Ecaron ; B 53 0 660 802 ;
+C -1 ; WX 600 ; N Iogonek ; B 96 -172 623 562 ;
+C -1 ; WX 600 ; N kcommaaccent ; B 58 -250 633 629 ;
+C -1 ; WX 600 ; N minus ; B 129 232 580 283 ;
+C -1 ; WX 600 ; N Icircumflex ; B 96 0 623 787 ;
+C -1 ; WX 600 ; N ncaron ; B 26 0 614 669 ;
+C -1 ; WX 600 ; N tcommaaccent ; B 165 -250 561 561 ;
+C -1 ; WX 600 ; N logicalnot ; B 155 108 591 369 ;
+C -1 ; WX 600 ; N odieresis ; B 102 -15 588 620 ;
+C -1 ; WX 600 ; N udieresis ; B 101 -15 575 620 ;
+C -1 ; WX 600 ; N notequal ; B 43 -16 621 529 ;
+C -1 ; WX 600 ; N gcommaaccent ; B 61 -157 657 708 ;
+C -1 ; WX 600 ; N eth ; B 102 -15 639 629 ;
+C -1 ; WX 600 ; N zcaron ; B 99 0 624 669 ;
+C -1 ; WX 600 ; N ncommaaccent ; B 26 -250 585 441 ;
+C -1 ; WX 600 ; N onesuperior ; B 231 249 491 622 ;
+C -1 ; WX 600 ; N imacron ; B 95 0 543 565 ;
+C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Courier.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Courier.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Courier.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Courier.afm 2004-05-26 16:06:20.000000000 +0000
@@ -0,0 +1,342 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu May 1 17:27:09 1997
+Comment UniqueID 43050
+Comment VMusage 39754 50779
+FontName Courier
+FullName Courier
+FamilyName Courier
+Weight Medium
+ItalicAngle 0
+IsFixedPitch true
+CharacterSet ExtendedRoman
+FontBBox -23 -250 715 805
+UnderlinePosition -100
+UnderlineThickness 50
+Version 003.000
+Notice Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 562
+XHeight 426
+Ascender 629
+Descender -157
+StdHW 51
+StdVW 51
+StartCharMetrics 315
+C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 600 ; N exclam ; B 236 -15 364 572 ;
+C 34 ; WX 600 ; N quotedbl ; B 187 328 413 562 ;
+C 35 ; WX 600 ; N numbersign ; B 93 -32 507 639 ;
+C 36 ; WX 600 ; N dollar ; B 105 -126 496 662 ;
+C 37 ; WX 600 ; N percent ; B 81 -15 518 622 ;
+C 38 ; WX 600 ; N ampersand ; B 63 -15 538 543 ;
+C 39 ; WX 600 ; N quoteright ; B 213 328 376 562 ;
+C 40 ; WX 600 ; N parenleft ; B 269 -108 440 622 ;
+C 41 ; WX 600 ; N parenright ; B 160 -108 331 622 ;
+C 42 ; WX 600 ; N asterisk ; B 116 257 484 607 ;
+C 43 ; WX 600 ; N plus ; B 80 44 520 470 ;
+C 44 ; WX 600 ; N comma ; B 181 -112 344 122 ;
+C 45 ; WX 600 ; N hyphen ; B 103 231 497 285 ;
+C 46 ; WX 600 ; N period ; B 229 -15 371 109 ;
+C 47 ; WX 600 ; N slash ; B 125 -80 475 629 ;
+C 48 ; WX 600 ; N zero ; B 106 -15 494 622 ;
+C 49 ; WX 600 ; N one ; B 96 0 505 622 ;
+C 50 ; WX 600 ; N two ; B 70 0 471 622 ;
+C 51 ; WX 600 ; N three ; B 75 -15 466 622 ;
+C 52 ; WX 600 ; N four ; B 78 0 500 622 ;
+C 53 ; WX 600 ; N five ; B 92 -15 497 607 ;
+C 54 ; WX 600 ; N six ; B 111 -15 497 622 ;
+C 55 ; WX 600 ; N seven ; B 82 0 483 607 ;
+C 56 ; WX 600 ; N eight ; B 102 -15 498 622 ;
+C 57 ; WX 600 ; N nine ; B 96 -15 489 622 ;
+C 58 ; WX 600 ; N colon ; B 229 -15 371 385 ;
+C 59 ; WX 600 ; N semicolon ; B 181 -112 371 385 ;
+C 60 ; WX 600 ; N less ; B 41 42 519 472 ;
+C 61 ; WX 600 ; N equal ; B 80 138 520 376 ;
+C 62 ; WX 600 ; N greater ; B 66 42 544 472 ;
+C 63 ; WX 600 ; N question ; B 129 -15 492 572 ;
+C 64 ; WX 600 ; N at ; B 77 -15 533 622 ;
+C 65 ; WX 600 ; N A ; B 3 0 597 562 ;
+C 66 ; WX 600 ; N B ; B 43 0 559 562 ;
+C 67 ; WX 600 ; N C ; B 41 -18 540 580 ;
+C 68 ; WX 600 ; N D ; B 43 0 574 562 ;
+C 69 ; WX 600 ; N E ; B 53 0 550 562 ;
+C 70 ; WX 600 ; N F ; B 53 0 545 562 ;
+C 71 ; WX 600 ; N G ; B 31 -18 575 580 ;
+C 72 ; WX 600 ; N H ; B 32 0 568 562 ;
+C 73 ; WX 600 ; N I ; B 96 0 504 562 ;
+C 74 ; WX 600 ; N J ; B 34 -18 566 562 ;
+C 75 ; WX 600 ; N K ; B 38 0 582 562 ;
+C 76 ; WX 600 ; N L ; B 47 0 554 562 ;
+C 77 ; WX 600 ; N M ; B 4 0 596 562 ;
+C 78 ; WX 600 ; N N ; B 7 -13 593 562 ;
+C 79 ; WX 600 ; N O ; B 43 -18 557 580 ;
+C 80 ; WX 600 ; N P ; B 79 0 558 562 ;
+C 81 ; WX 600 ; N Q ; B 43 -138 557 580 ;
+C 82 ; WX 600 ; N R ; B 38 0 588 562 ;
+C 83 ; WX 600 ; N S ; B 72 -20 529 580 ;
+C 84 ; WX 600 ; N T ; B 38 0 563 562 ;
+C 85 ; WX 600 ; N U ; B 17 -18 583 562 ;
+C 86 ; WX 600 ; N V ; B -4 -13 604 562 ;
+C 87 ; WX 600 ; N W ; B -3 -13 603 562 ;
+C 88 ; WX 600 ; N X ; B 23 0 577 562 ;
+C 89 ; WX 600 ; N Y ; B 24 0 576 562 ;
+C 90 ; WX 600 ; N Z ; B 86 0 514 562 ;
+C 91 ; WX 600 ; N bracketleft ; B 269 -108 442 622 ;
+C 92 ; WX 600 ; N backslash ; B 118 -80 482 629 ;
+C 93 ; WX 600 ; N bracketright ; B 158 -108 331 622 ;
+C 94 ; WX 600 ; N asciicircum ; B 94 354 506 622 ;
+C 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ;
+C 96 ; WX 600 ; N quoteleft ; B 224 328 387 562 ;
+C 97 ; WX 600 ; N a ; B 53 -15 559 441 ;
+C 98 ; WX 600 ; N b ; B 14 -15 575 629 ;
+C 99 ; WX 600 ; N c ; B 66 -15 529 441 ;
+C 100 ; WX 600 ; N d ; B 45 -15 591 629 ;
+C 101 ; WX 600 ; N e ; B 66 -15 548 441 ;
+C 102 ; WX 600 ; N f ; B 114 0 531 629 ; L i fi ; L l fl ;
+C 103 ; WX 600 ; N g ; B 45 -157 566 441 ;
+C 104 ; WX 600 ; N h ; B 18 0 582 629 ;
+C 105 ; WX 600 ; N i ; B 95 0 505 657 ;
+C 106 ; WX 600 ; N j ; B 82 -157 410 657 ;
+C 107 ; WX 600 ; N k ; B 43 0 580 629 ;
+C 108 ; WX 600 ; N l ; B 95 0 505 629 ;
+C 109 ; WX 600 ; N m ; B -5 0 605 441 ;
+C 110 ; WX 600 ; N n ; B 26 0 575 441 ;
+C 111 ; WX 600 ; N o ; B 62 -15 538 441 ;
+C 112 ; WX 600 ; N p ; B 9 -157 555 441 ;
+C 113 ; WX 600 ; N q ; B 45 -157 591 441 ;
+C 114 ; WX 600 ; N r ; B 60 0 559 441 ;
+C 115 ; WX 600 ; N s ; B 80 -15 513 441 ;
+C 116 ; WX 600 ; N t ; B 87 -15 530 561 ;
+C 117 ; WX 600 ; N u ; B 21 -15 562 426 ;
+C 118 ; WX 600 ; N v ; B 10 -10 590 426 ;
+C 119 ; WX 600 ; N w ; B -4 -10 604 426 ;
+C 120 ; WX 600 ; N x ; B 20 0 580 426 ;
+C 121 ; WX 600 ; N y ; B 7 -157 592 426 ;
+C 122 ; WX 600 ; N z ; B 99 0 502 426 ;
+C 123 ; WX 600 ; N braceleft ; B 182 -108 437 622 ;
+C 124 ; WX 600 ; N bar ; B 275 -250 326 750 ;
+C 125 ; WX 600 ; N braceright ; B 163 -108 418 622 ;
+C 126 ; WX 600 ; N asciitilde ; B 63 197 540 320 ;
+C 161 ; WX 600 ; N exclamdown ; B 236 -157 364 430 ;
+C 162 ; WX 600 ; N cent ; B 96 -49 500 614 ;
+C 163 ; WX 600 ; N sterling ; B 84 -21 521 611 ;
+C 164 ; WX 600 ; N fraction ; B 92 -57 509 665 ;
+C 165 ; WX 600 ; N yen ; B 26 0 574 562 ;
+C 166 ; WX 600 ; N florin ; B 4 -143 539 622 ;
+C 167 ; WX 600 ; N section ; B 113 -78 488 580 ;
+C 168 ; WX 600 ; N currency ; B 73 58 527 506 ;
+C 169 ; WX 600 ; N quotesingle ; B 259 328 341 562 ;
+C 170 ; WX 600 ; N quotedblleft ; B 143 328 471 562 ;
+C 171 ; WX 600 ; N guillemotleft ; B 37 70 563 446 ;
+C 172 ; WX 600 ; N guilsinglleft ; B 149 70 451 446 ;
+C 173 ; WX 600 ; N guilsinglright ; B 149 70 451 446 ;
+C 174 ; WX 600 ; N fi ; B 3 0 597 629 ;
+C 175 ; WX 600 ; N fl ; B 3 0 597 629 ;
+C 177 ; WX 600 ; N endash ; B 75 231 525 285 ;
+C 178 ; WX 600 ; N dagger ; B 141 -78 459 580 ;
+C 179 ; WX 600 ; N daggerdbl ; B 141 -78 459 580 ;
+C 180 ; WX 600 ; N periodcentered ; B 222 189 378 327 ;
+C 182 ; WX 600 ; N paragraph ; B 50 -78 511 562 ;
+C 183 ; WX 600 ; N bullet ; B 172 130 428 383 ;
+C 184 ; WX 600 ; N quotesinglbase ; B 213 -134 376 100 ;
+C 185 ; WX 600 ; N quotedblbase ; B 143 -134 457 100 ;
+C 186 ; WX 600 ; N quotedblright ; B 143 328 457 562 ;
+C 187 ; WX 600 ; N guillemotright ; B 37 70 563 446 ;
+C 188 ; WX 600 ; N ellipsis ; B 37 -15 563 111 ;
+C 189 ; WX 600 ; N perthousand ; B 3 -15 600 622 ;
+C 191 ; WX 600 ; N questiondown ; B 108 -157 471 430 ;
+C 193 ; WX 600 ; N grave ; B 151 497 378 672 ;
+C 194 ; WX 600 ; N acute ; B 242 497 469 672 ;
+C 195 ; WX 600 ; N circumflex ; B 124 477 476 654 ;
+C 196 ; WX 600 ; N tilde ; B 105 489 503 606 ;
+C 197 ; WX 600 ; N macron ; B 120 525 480 565 ;
+C 198 ; WX 600 ; N breve ; B 153 501 447 609 ;
+C 199 ; WX 600 ; N dotaccent ; B 249 537 352 640 ;
+C 200 ; WX 600 ; N dieresis ; B 148 537 453 640 ;
+C 202 ; WX 600 ; N ring ; B 218 463 382 627 ;
+C 203 ; WX 600 ; N cedilla ; B 224 -151 362 10 ;
+C 205 ; WX 600 ; N hungarumlaut ; B 133 497 540 672 ;
+C 206 ; WX 600 ; N ogonek ; B 211 -172 407 4 ;
+C 207 ; WX 600 ; N caron ; B 124 492 476 669 ;
+C 208 ; WX 600 ; N emdash ; B 0 231 600 285 ;
+C 225 ; WX 600 ; N AE ; B 3 0 550 562 ;
+C 227 ; WX 600 ; N ordfeminine ; B 156 249 442 580 ;
+C 232 ; WX 600 ; N Lslash ; B 47 0 554 562 ;
+C 233 ; WX 600 ; N Oslash ; B 43 -80 557 629 ;
+C 234 ; WX 600 ; N OE ; B 7 0 567 562 ;
+C 235 ; WX 600 ; N ordmasculine ; B 157 249 443 580 ;
+C 241 ; WX 600 ; N ae ; B 19 -15 570 441 ;
+C 245 ; WX 600 ; N dotlessi ; B 95 0 505 426 ;
+C 248 ; WX 600 ; N lslash ; B 95 0 505 629 ;
+C 249 ; WX 600 ; N oslash ; B 62 -80 538 506 ;
+C 250 ; WX 600 ; N oe ; B 19 -15 559 441 ;
+C 251 ; WX 600 ; N germandbls ; B 48 -15 588 629 ;
+C -1 ; WX 600 ; N Idieresis ; B 96 0 504 753 ;
+C -1 ; WX 600 ; N eacute ; B 66 -15 548 672 ;
+C -1 ; WX 600 ; N abreve ; B 53 -15 559 609 ;
+C -1 ; WX 600 ; N uhungarumlaut ; B 21 -15 580 672 ;
+C -1 ; WX 600 ; N ecaron ; B 66 -15 548 669 ;
+C -1 ; WX 600 ; N Ydieresis ; B 24 0 576 753 ;
+C -1 ; WX 600 ; N divide ; B 87 48 513 467 ;
+C -1 ; WX 600 ; N Yacute ; B 24 0 576 805 ;
+C -1 ; WX 600 ; N Acircumflex ; B 3 0 597 787 ;
+C -1 ; WX 600 ; N aacute ; B 53 -15 559 672 ;
+C -1 ; WX 600 ; N Ucircumflex ; B 17 -18 583 787 ;
+C -1 ; WX 600 ; N yacute ; B 7 -157 592 672 ;
+C -1 ; WX 600 ; N scommaaccent ; B 80 -250 513 441 ;
+C -1 ; WX 600 ; N ecircumflex ; B 66 -15 548 654 ;
+C -1 ; WX 600 ; N Uring ; B 17 -18 583 760 ;
+C -1 ; WX 600 ; N Udieresis ; B 17 -18 583 753 ;
+C -1 ; WX 600 ; N aogonek ; B 53 -172 587 441 ;
+C -1 ; WX 600 ; N Uacute ; B 17 -18 583 805 ;
+C -1 ; WX 600 ; N uogonek ; B 21 -172 590 426 ;
+C -1 ; WX 600 ; N Edieresis ; B 53 0 550 753 ;
+C -1 ; WX 600 ; N Dcroat ; B 30 0 574 562 ;
+C -1 ; WX 600 ; N commaaccent ; B 198 -250 335 -58 ;
+C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ;
+C -1 ; WX 600 ; N Emacron ; B 53 0 550 698 ;
+C -1 ; WX 600 ; N ccaron ; B 66 -15 529 669 ;
+C -1 ; WX 600 ; N aring ; B 53 -15 559 627 ;
+C -1 ; WX 600 ; N Ncommaaccent ; B 7 -250 593 562 ;
+C -1 ; WX 600 ; N lacute ; B 95 0 505 805 ;
+C -1 ; WX 600 ; N agrave ; B 53 -15 559 672 ;
+C -1 ; WX 600 ; N Tcommaaccent ; B 38 -250 563 562 ;
+C -1 ; WX 600 ; N Cacute ; B 41 -18 540 805 ;
+C -1 ; WX 600 ; N atilde ; B 53 -15 559 606 ;
+C -1 ; WX 600 ; N Edotaccent ; B 53 0 550 753 ;
+C -1 ; WX 600 ; N scaron ; B 80 -15 513 669 ;
+C -1 ; WX 600 ; N scedilla ; B 80 -151 513 441 ;
+C -1 ; WX 600 ; N iacute ; B 95 0 505 672 ;
+C -1 ; WX 600 ; N lozenge ; B 18 0 443 706 ;
+C -1 ; WX 600 ; N Rcaron ; B 38 0 588 802 ;
+C -1 ; WX 600 ; N Gcommaaccent ; B 31 -250 575 580 ;
+C -1 ; WX 600 ; N ucircumflex ; B 21 -15 562 654 ;
+C -1 ; WX 600 ; N acircumflex ; B 53 -15 559 654 ;
+C -1 ; WX 600 ; N Amacron ; B 3 0 597 698 ;
+C -1 ; WX 600 ; N rcaron ; B 60 0 559 669 ;
+C -1 ; WX 600 ; N ccedilla ; B 66 -151 529 441 ;
+C -1 ; WX 600 ; N Zdotaccent ; B 86 0 514 753 ;
+C -1 ; WX 600 ; N Thorn ; B 79 0 538 562 ;
+C -1 ; WX 600 ; N Omacron ; B 43 -18 557 698 ;
+C -1 ; WX 600 ; N Racute ; B 38 0 588 805 ;
+C -1 ; WX 600 ; N Sacute ; B 72 -20 529 805 ;
+C -1 ; WX 600 ; N dcaron ; B 45 -15 715 629 ;
+C -1 ; WX 600 ; N Umacron ; B 17 -18 583 698 ;
+C -1 ; WX 600 ; N uring ; B 21 -15 562 627 ;
+C -1 ; WX 600 ; N threesuperior ; B 155 240 406 622 ;
+C -1 ; WX 600 ; N Ograve ; B 43 -18 557 805 ;
+C -1 ; WX 600 ; N Agrave ; B 3 0 597 805 ;
+C -1 ; WX 600 ; N Abreve ; B 3 0 597 732 ;
+C -1 ; WX 600 ; N multiply ; B 87 43 515 470 ;
+C -1 ; WX 600 ; N uacute ; B 21 -15 562 672 ;
+C -1 ; WX 600 ; N Tcaron ; B 38 0 563 802 ;
+C -1 ; WX 600 ; N partialdiff ; B 17 -38 459 710 ;
+C -1 ; WX 600 ; N ydieresis ; B 7 -157 592 620 ;
+C -1 ; WX 600 ; N Nacute ; B 7 -13 593 805 ;
+C -1 ; WX 600 ; N icircumflex ; B 94 0 505 654 ;
+C -1 ; WX 600 ; N Ecircumflex ; B 53 0 550 787 ;
+C -1 ; WX 600 ; N adieresis ; B 53 -15 559 620 ;
+C -1 ; WX 600 ; N edieresis ; B 66 -15 548 620 ;
+C -1 ; WX 600 ; N cacute ; B 66 -15 529 672 ;
+C -1 ; WX 600 ; N nacute ; B 26 0 575 672 ;
+C -1 ; WX 600 ; N umacron ; B 21 -15 562 565 ;
+C -1 ; WX 600 ; N Ncaron ; B 7 -13 593 802 ;
+C -1 ; WX 600 ; N Iacute ; B 96 0 504 805 ;
+C -1 ; WX 600 ; N plusminus ; B 87 44 513 558 ;
+C -1 ; WX 600 ; N brokenbar ; B 275 -175 326 675 ;
+C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ;
+C -1 ; WX 600 ; N Gbreve ; B 31 -18 575 732 ;
+C -1 ; WX 600 ; N Idotaccent ; B 96 0 504 753 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ;
+C -1 ; WX 600 ; N Egrave ; B 53 0 550 805 ;
+C -1 ; WX 600 ; N racute ; B 60 0 559 672 ;
+C -1 ; WX 600 ; N omacron ; B 62 -15 538 565 ;
+C -1 ; WX 600 ; N Zacute ; B 86 0 514 805 ;
+C -1 ; WX 600 ; N Zcaron ; B 86 0 514 802 ;
+C -1 ; WX 600 ; N greaterequal ; B 98 0 502 710 ;
+C -1 ; WX 600 ; N Eth ; B 30 0 574 562 ;
+C -1 ; WX 600 ; N Ccedilla ; B 41 -151 540 580 ;
+C -1 ; WX 600 ; N lcommaaccent ; B 95 -250 505 629 ;
+C -1 ; WX 600 ; N tcaron ; B 87 -15 530 717 ;
+C -1 ; WX 600 ; N eogonek ; B 66 -172 548 441 ;
+C -1 ; WX 600 ; N Uogonek ; B 17 -172 583 562 ;
+C -1 ; WX 600 ; N Aacute ; B 3 0 597 805 ;
+C -1 ; WX 600 ; N Adieresis ; B 3 0 597 753 ;
+C -1 ; WX 600 ; N egrave ; B 66 -15 548 672 ;
+C -1 ; WX 600 ; N zacute ; B 99 0 502 672 ;
+C -1 ; WX 600 ; N iogonek ; B 95 -172 505 657 ;
+C -1 ; WX 600 ; N Oacute ; B 43 -18 557 805 ;
+C -1 ; WX 600 ; N oacute ; B 62 -15 538 672 ;
+C -1 ; WX 600 ; N amacron ; B 53 -15 559 565 ;
+C -1 ; WX 600 ; N sacute ; B 80 -15 513 672 ;
+C -1 ; WX 600 ; N idieresis ; B 95 0 505 620 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 43 -18 557 787 ;
+C -1 ; WX 600 ; N Ugrave ; B 17 -18 583 805 ;
+C -1 ; WX 600 ; N Delta ; B 6 0 598 688 ;
+C -1 ; WX 600 ; N thorn ; B -6 -157 555 629 ;
+C -1 ; WX 600 ; N twosuperior ; B 177 249 424 622 ;
+C -1 ; WX 600 ; N Odieresis ; B 43 -18 557 753 ;
+C -1 ; WX 600 ; N mu ; B 21 -157 562 426 ;
+C -1 ; WX 600 ; N igrave ; B 95 0 505 672 ;
+C -1 ; WX 600 ; N ohungarumlaut ; B 62 -15 580 672 ;
+C -1 ; WX 600 ; N Eogonek ; B 53 -172 561 562 ;
+C -1 ; WX 600 ; N dcroat ; B 45 -15 591 629 ;
+C -1 ; WX 600 ; N threequarters ; B 8 -56 593 666 ;
+C -1 ; WX 600 ; N Scedilla ; B 72 -151 529 580 ;
+C -1 ; WX 600 ; N lcaron ; B 95 0 533 629 ;
+C -1 ; WX 600 ; N Kcommaaccent ; B 38 -250 582 562 ;
+C -1 ; WX 600 ; N Lacute ; B 47 0 554 805 ;
+C -1 ; WX 600 ; N trademark ; B -23 263 623 562 ;
+C -1 ; WX 600 ; N edotaccent ; B 66 -15 548 620 ;
+C -1 ; WX 600 ; N Igrave ; B 96 0 504 805 ;
+C -1 ; WX 600 ; N Imacron ; B 96 0 504 698 ;
+C -1 ; WX 600 ; N Lcaron ; B 47 0 554 562 ;
+C -1 ; WX 600 ; N onehalf ; B 0 -57 611 665 ;
+C -1 ; WX 600 ; N lessequal ; B 98 0 502 710 ;
+C -1 ; WX 600 ; N ocircumflex ; B 62 -15 538 654 ;
+C -1 ; WX 600 ; N ntilde ; B 26 0 575 606 ;
+C -1 ; WX 600 ; N Uhungarumlaut ; B 17 -18 590 805 ;
+C -1 ; WX 600 ; N Eacute ; B 53 0 550 805 ;
+C -1 ; WX 600 ; N emacron ; B 66 -15 548 565 ;
+C -1 ; WX 600 ; N gbreve ; B 45 -157 566 609 ;
+C -1 ; WX 600 ; N onequarter ; B 0 -57 600 665 ;
+C -1 ; WX 600 ; N Scaron ; B 72 -20 529 802 ;
+C -1 ; WX 600 ; N Scommaaccent ; B 72 -250 529 580 ;
+C -1 ; WX 600 ; N Ohungarumlaut ; B 43 -18 580 805 ;
+C -1 ; WX 600 ; N degree ; B 123 269 477 622 ;
+C -1 ; WX 600 ; N ograve ; B 62 -15 538 672 ;
+C -1 ; WX 600 ; N Ccaron ; B 41 -18 540 802 ;
+C -1 ; WX 600 ; N ugrave ; B 21 -15 562 672 ;
+C -1 ; WX 600 ; N radical ; B 3 -15 597 792 ;
+C -1 ; WX 600 ; N Dcaron ; B 43 0 574 802 ;
+C -1 ; WX 600 ; N rcommaaccent ; B 60 -250 559 441 ;
+C -1 ; WX 600 ; N Ntilde ; B 7 -13 593 729 ;
+C -1 ; WX 600 ; N otilde ; B 62 -15 538 606 ;
+C -1 ; WX 600 ; N Rcommaaccent ; B 38 -250 588 562 ;
+C -1 ; WX 600 ; N Lcommaaccent ; B 47 -250 554 562 ;
+C -1 ; WX 600 ; N Atilde ; B 3 0 597 729 ;
+C -1 ; WX 600 ; N Aogonek ; B 3 -172 608 562 ;
+C -1 ; WX 600 ; N Aring ; B 3 0 597 750 ;
+C -1 ; WX 600 ; N Otilde ; B 43 -18 557 729 ;
+C -1 ; WX 600 ; N zdotaccent ; B 99 0 502 620 ;
+C -1 ; WX 600 ; N Ecaron ; B 53 0 550 802 ;
+C -1 ; WX 600 ; N Iogonek ; B 96 -172 504 562 ;
+C -1 ; WX 600 ; N kcommaaccent ; B 43 -250 580 629 ;
+C -1 ; WX 600 ; N minus ; B 80 232 520 283 ;
+C -1 ; WX 600 ; N Icircumflex ; B 96 0 504 787 ;
+C -1 ; WX 600 ; N ncaron ; B 26 0 575 669 ;
+C -1 ; WX 600 ; N tcommaaccent ; B 87 -250 530 561 ;
+C -1 ; WX 600 ; N logicalnot ; B 87 108 513 369 ;
+C -1 ; WX 600 ; N odieresis ; B 62 -15 538 620 ;
+C -1 ; WX 600 ; N udieresis ; B 21 -15 562 620 ;
+C -1 ; WX 600 ; N notequal ; B 15 -16 540 529 ;
+C -1 ; WX 600 ; N gcommaaccent ; B 45 -157 566 708 ;
+C -1 ; WX 600 ; N eth ; B 62 -15 538 629 ;
+C -1 ; WX 600 ; N zcaron ; B 99 0 502 669 ;
+C -1 ; WX 600 ; N ncommaaccent ; B 26 -250 575 441 ;
+C -1 ; WX 600 ; N onesuperior ; B 172 249 428 622 ;
+C -1 ; WX 600 ; N imacron ; B 95 0 505 565 ;
+C -1 ; WX 600 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/FontsResourceAnchor.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/FontsResourceAnchor.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/FontsResourceAnchor.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/FontsResourceAnchor.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2004 by Paulo Soares.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+package pdftk.com.lowagie.text.pdf.fonts;
+
+/**
+ * A class to facilitate the loading of resources
+ *
+ * @author Paulo Soares (psoares@consiste.pt)
+ */
+public class FontsResourceAnchor {
+
+ /**
+ * Creates a FontsResourceAnchor
+ */
+ public FontsResourceAnchor() {
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica-Bold.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica-Bold.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica-Bold.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica-Bold.afm 2004-05-26 16:06:20.000000000 +0000
@@ -0,0 +1,2827 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu May 1 12:43:52 1997
+Comment UniqueID 43052
+Comment VMusage 37169 48194
+FontName Helvetica-Bold
+FullName Helvetica Bold
+FamilyName Helvetica
+Weight Bold
+ItalicAngle 0
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -170 -228 1003 962
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 532
+Ascender 718
+Descender -207
+StdHW 118
+StdVW 140
+StartCharMetrics 315
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 90 0 244 718 ;
+C 34 ; WX 474 ; N quotedbl ; B 98 447 376 718 ;
+C 35 ; WX 556 ; N numbersign ; B 18 0 538 698 ;
+C 36 ; WX 556 ; N dollar ; B 30 -115 523 775 ;
+C 37 ; WX 889 ; N percent ; B 28 -19 861 710 ;
+C 38 ; WX 722 ; N ampersand ; B 54 -19 701 718 ;
+C 39 ; WX 278 ; N quoteright ; B 69 445 209 718 ;
+C 40 ; WX 333 ; N parenleft ; B 35 -208 314 734 ;
+C 41 ; WX 333 ; N parenright ; B 19 -208 298 734 ;
+C 42 ; WX 389 ; N asterisk ; B 27 387 362 718 ;
+C 43 ; WX 584 ; N plus ; B 40 0 544 506 ;
+C 44 ; WX 278 ; N comma ; B 64 -168 214 146 ;
+C 45 ; WX 333 ; N hyphen ; B 27 215 306 345 ;
+C 46 ; WX 278 ; N period ; B 64 0 214 146 ;
+C 47 ; WX 278 ; N slash ; B -33 -19 311 737 ;
+C 48 ; WX 556 ; N zero ; B 32 -19 524 710 ;
+C 49 ; WX 556 ; N one ; B 69 0 378 710 ;
+C 50 ; WX 556 ; N two ; B 26 0 511 710 ;
+C 51 ; WX 556 ; N three ; B 27 -19 516 710 ;
+C 52 ; WX 556 ; N four ; B 27 0 526 710 ;
+C 53 ; WX 556 ; N five ; B 27 -19 516 698 ;
+C 54 ; WX 556 ; N six ; B 31 -19 520 710 ;
+C 55 ; WX 556 ; N seven ; B 25 0 528 698 ;
+C 56 ; WX 556 ; N eight ; B 32 -19 524 710 ;
+C 57 ; WX 556 ; N nine ; B 30 -19 522 710 ;
+C 58 ; WX 333 ; N colon ; B 92 0 242 512 ;
+C 59 ; WX 333 ; N semicolon ; B 92 -168 242 512 ;
+C 60 ; WX 584 ; N less ; B 38 -8 546 514 ;
+C 61 ; WX 584 ; N equal ; B 40 87 544 419 ;
+C 62 ; WX 584 ; N greater ; B 38 -8 546 514 ;
+C 63 ; WX 611 ; N question ; B 60 0 556 727 ;
+C 64 ; WX 975 ; N at ; B 118 -19 856 737 ;
+C 65 ; WX 722 ; N A ; B 20 0 702 718 ;
+C 66 ; WX 722 ; N B ; B 76 0 669 718 ;
+C 67 ; WX 722 ; N C ; B 44 -19 684 737 ;
+C 68 ; WX 722 ; N D ; B 76 0 685 718 ;
+C 69 ; WX 667 ; N E ; B 76 0 621 718 ;
+C 70 ; WX 611 ; N F ; B 76 0 587 718 ;
+C 71 ; WX 778 ; N G ; B 44 -19 713 737 ;
+C 72 ; WX 722 ; N H ; B 71 0 651 718 ;
+C 73 ; WX 278 ; N I ; B 64 0 214 718 ;
+C 74 ; WX 556 ; N J ; B 22 -18 484 718 ;
+C 75 ; WX 722 ; N K ; B 87 0 722 718 ;
+C 76 ; WX 611 ; N L ; B 76 0 583 718 ;
+C 77 ; WX 833 ; N M ; B 69 0 765 718 ;
+C 78 ; WX 722 ; N N ; B 69 0 654 718 ;
+C 79 ; WX 778 ; N O ; B 44 -19 734 737 ;
+C 80 ; WX 667 ; N P ; B 76 0 627 718 ;
+C 81 ; WX 778 ; N Q ; B 44 -52 737 737 ;
+C 82 ; WX 722 ; N R ; B 76 0 677 718 ;
+C 83 ; WX 667 ; N S ; B 39 -19 629 737 ;
+C 84 ; WX 611 ; N T ; B 14 0 598 718 ;
+C 85 ; WX 722 ; N U ; B 72 -19 651 718 ;
+C 86 ; WX 667 ; N V ; B 19 0 648 718 ;
+C 87 ; WX 944 ; N W ; B 16 0 929 718 ;
+C 88 ; WX 667 ; N X ; B 14 0 653 718 ;
+C 89 ; WX 667 ; N Y ; B 15 0 653 718 ;
+C 90 ; WX 611 ; N Z ; B 25 0 586 718 ;
+C 91 ; WX 333 ; N bracketleft ; B 63 -196 309 722 ;
+C 92 ; WX 278 ; N backslash ; B -33 -19 311 737 ;
+C 93 ; WX 333 ; N bracketright ; B 24 -196 270 722 ;
+C 94 ; WX 584 ; N asciicircum ; B 62 323 522 698 ;
+C 95 ; WX 556 ; N underscore ; B 0 -125 556 -75 ;
+C 96 ; WX 278 ; N quoteleft ; B 69 454 209 727 ;
+C 97 ; WX 556 ; N a ; B 29 -14 527 546 ;
+C 98 ; WX 611 ; N b ; B 61 -14 578 718 ;
+C 99 ; WX 556 ; N c ; B 34 -14 524 546 ;
+C 100 ; WX 611 ; N d ; B 34 -14 551 718 ;
+C 101 ; WX 556 ; N e ; B 23 -14 528 546 ;
+C 102 ; WX 333 ; N f ; B 10 0 318 727 ; L i fi ; L l fl ;
+C 103 ; WX 611 ; N g ; B 40 -217 553 546 ;
+C 104 ; WX 611 ; N h ; B 65 0 546 718 ;
+C 105 ; WX 278 ; N i ; B 69 0 209 725 ;
+C 106 ; WX 278 ; N j ; B 3 -214 209 725 ;
+C 107 ; WX 556 ; N k ; B 69 0 562 718 ;
+C 108 ; WX 278 ; N l ; B 69 0 209 718 ;
+C 109 ; WX 889 ; N m ; B 64 0 826 546 ;
+C 110 ; WX 611 ; N n ; B 65 0 546 546 ;
+C 111 ; WX 611 ; N o ; B 34 -14 578 546 ;
+C 112 ; WX 611 ; N p ; B 62 -207 578 546 ;
+C 113 ; WX 611 ; N q ; B 34 -207 552 546 ;
+C 114 ; WX 389 ; N r ; B 64 0 373 546 ;
+C 115 ; WX 556 ; N s ; B 30 -14 519 546 ;
+C 116 ; WX 333 ; N t ; B 10 -6 309 676 ;
+C 117 ; WX 611 ; N u ; B 66 -14 545 532 ;
+C 118 ; WX 556 ; N v ; B 13 0 543 532 ;
+C 119 ; WX 778 ; N w ; B 10 0 769 532 ;
+C 120 ; WX 556 ; N x ; B 15 0 541 532 ;
+C 121 ; WX 556 ; N y ; B 10 -214 539 532 ;
+C 122 ; WX 500 ; N z ; B 20 0 480 532 ;
+C 123 ; WX 389 ; N braceleft ; B 48 -196 365 722 ;
+C 124 ; WX 280 ; N bar ; B 84 -225 196 775 ;
+C 125 ; WX 389 ; N braceright ; B 24 -196 341 722 ;
+C 126 ; WX 584 ; N asciitilde ; B 61 163 523 343 ;
+C 161 ; WX 333 ; N exclamdown ; B 90 -186 244 532 ;
+C 162 ; WX 556 ; N cent ; B 34 -118 524 628 ;
+C 163 ; WX 556 ; N sterling ; B 28 -16 541 718 ;
+C 164 ; WX 167 ; N fraction ; B -170 -19 336 710 ;
+C 165 ; WX 556 ; N yen ; B -9 0 565 698 ;
+C 166 ; WX 556 ; N florin ; B -10 -210 516 737 ;
+C 167 ; WX 556 ; N section ; B 34 -184 522 727 ;
+C 168 ; WX 556 ; N currency ; B -3 76 559 636 ;
+C 169 ; WX 238 ; N quotesingle ; B 70 447 168 718 ;
+C 170 ; WX 500 ; N quotedblleft ; B 64 454 436 727 ;
+C 171 ; WX 556 ; N guillemotleft ; B 88 76 468 484 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 83 76 250 484 ;
+C 173 ; WX 333 ; N guilsinglright ; B 83 76 250 484 ;
+C 174 ; WX 611 ; N fi ; B 10 0 542 727 ;
+C 175 ; WX 611 ; N fl ; B 10 0 542 727 ;
+C 177 ; WX 556 ; N endash ; B 0 227 556 333 ;
+C 178 ; WX 556 ; N dagger ; B 36 -171 520 718 ;
+C 179 ; WX 556 ; N daggerdbl ; B 36 -171 520 718 ;
+C 180 ; WX 278 ; N periodcentered ; B 58 172 220 334 ;
+C 182 ; WX 556 ; N paragraph ; B -8 -191 539 700 ;
+C 183 ; WX 350 ; N bullet ; B 10 194 340 524 ;
+C 184 ; WX 278 ; N quotesinglbase ; B 69 -146 209 127 ;
+C 185 ; WX 500 ; N quotedblbase ; B 64 -146 436 127 ;
+C 186 ; WX 500 ; N quotedblright ; B 64 445 436 718 ;
+C 187 ; WX 556 ; N guillemotright ; B 88 76 468 484 ;
+C 188 ; WX 1000 ; N ellipsis ; B 92 0 908 146 ;
+C 189 ; WX 1000 ; N perthousand ; B -3 -19 1003 710 ;
+C 191 ; WX 611 ; N questiondown ; B 55 -195 551 532 ;
+C 193 ; WX 333 ; N grave ; B -23 604 225 750 ;
+C 194 ; WX 333 ; N acute ; B 108 604 356 750 ;
+C 195 ; WX 333 ; N circumflex ; B -10 604 343 750 ;
+C 196 ; WX 333 ; N tilde ; B -17 610 350 737 ;
+C 197 ; WX 333 ; N macron ; B -6 604 339 678 ;
+C 198 ; WX 333 ; N breve ; B -2 604 335 750 ;
+C 199 ; WX 333 ; N dotaccent ; B 104 614 230 729 ;
+C 200 ; WX 333 ; N dieresis ; B 6 614 327 729 ;
+C 202 ; WX 333 ; N ring ; B 59 568 275 776 ;
+C 203 ; WX 333 ; N cedilla ; B 6 -228 245 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 9 604 486 750 ;
+C 206 ; WX 333 ; N ogonek ; B 71 -228 304 0 ;
+C 207 ; WX 333 ; N caron ; B -10 604 343 750 ;
+C 208 ; WX 1000 ; N emdash ; B 0 227 1000 333 ;
+C 225 ; WX 1000 ; N AE ; B 5 0 954 718 ;
+C 227 ; WX 370 ; N ordfeminine ; B 22 401 347 737 ;
+C 232 ; WX 611 ; N Lslash ; B -20 0 583 718 ;
+C 233 ; WX 778 ; N Oslash ; B 33 -27 744 745 ;
+C 234 ; WX 1000 ; N OE ; B 37 -19 961 737 ;
+C 235 ; WX 365 ; N ordmasculine ; B 6 401 360 737 ;
+C 241 ; WX 889 ; N ae ; B 29 -14 858 546 ;
+C 245 ; WX 278 ; N dotlessi ; B 69 0 209 532 ;
+C 248 ; WX 278 ; N lslash ; B -18 0 296 718 ;
+C 249 ; WX 611 ; N oslash ; B 22 -29 589 560 ;
+C 250 ; WX 944 ; N oe ; B 34 -14 912 546 ;
+C 251 ; WX 611 ; N germandbls ; B 69 -14 579 731 ;
+C -1 ; WX 278 ; N Idieresis ; B -21 0 300 915 ;
+C -1 ; WX 556 ; N eacute ; B 23 -14 528 750 ;
+C -1 ; WX 556 ; N abreve ; B 29 -14 527 750 ;
+C -1 ; WX 611 ; N uhungarumlaut ; B 66 -14 625 750 ;
+C -1 ; WX 556 ; N ecaron ; B 23 -14 528 750 ;
+C -1 ; WX 667 ; N Ydieresis ; B 15 0 653 915 ;
+C -1 ; WX 584 ; N divide ; B 40 -42 544 548 ;
+C -1 ; WX 667 ; N Yacute ; B 15 0 653 936 ;
+C -1 ; WX 722 ; N Acircumflex ; B 20 0 702 936 ;
+C -1 ; WX 556 ; N aacute ; B 29 -14 527 750 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 72 -19 651 936 ;
+C -1 ; WX 556 ; N yacute ; B 10 -214 539 750 ;
+C -1 ; WX 556 ; N scommaaccent ; B 30 -228 519 546 ;
+C -1 ; WX 556 ; N ecircumflex ; B 23 -14 528 750 ;
+C -1 ; WX 722 ; N Uring ; B 72 -19 651 962 ;
+C -1 ; WX 722 ; N Udieresis ; B 72 -19 651 915 ;
+C -1 ; WX 556 ; N aogonek ; B 29 -224 545 546 ;
+C -1 ; WX 722 ; N Uacute ; B 72 -19 651 936 ;
+C -1 ; WX 611 ; N uogonek ; B 66 -228 545 532 ;
+C -1 ; WX 667 ; N Edieresis ; B 76 0 621 915 ;
+C -1 ; WX 722 ; N Dcroat ; B -5 0 685 718 ;
+C -1 ; WX 250 ; N commaaccent ; B 64 -228 199 -50 ;
+C -1 ; WX 737 ; N copyright ; B -11 -19 749 737 ;
+C -1 ; WX 667 ; N Emacron ; B 76 0 621 864 ;
+C -1 ; WX 556 ; N ccaron ; B 34 -14 524 750 ;
+C -1 ; WX 556 ; N aring ; B 29 -14 527 776 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B 69 -228 654 718 ;
+C -1 ; WX 278 ; N lacute ; B 69 0 329 936 ;
+C -1 ; WX 556 ; N agrave ; B 29 -14 527 750 ;
+C -1 ; WX 611 ; N Tcommaaccent ; B 14 -228 598 718 ;
+C -1 ; WX 722 ; N Cacute ; B 44 -19 684 936 ;
+C -1 ; WX 556 ; N atilde ; B 29 -14 527 737 ;
+C -1 ; WX 667 ; N Edotaccent ; B 76 0 621 915 ;
+C -1 ; WX 556 ; N scaron ; B 30 -14 519 750 ;
+C -1 ; WX 556 ; N scedilla ; B 30 -228 519 546 ;
+C -1 ; WX 278 ; N iacute ; B 69 0 329 750 ;
+C -1 ; WX 494 ; N lozenge ; B 10 0 484 745 ;
+C -1 ; WX 722 ; N Rcaron ; B 76 0 677 936 ;
+C -1 ; WX 778 ; N Gcommaaccent ; B 44 -228 713 737 ;
+C -1 ; WX 611 ; N ucircumflex ; B 66 -14 545 750 ;
+C -1 ; WX 556 ; N acircumflex ; B 29 -14 527 750 ;
+C -1 ; WX 722 ; N Amacron ; B 20 0 702 864 ;
+C -1 ; WX 389 ; N rcaron ; B 18 0 373 750 ;
+C -1 ; WX 556 ; N ccedilla ; B 34 -228 524 546 ;
+C -1 ; WX 611 ; N Zdotaccent ; B 25 0 586 915 ;
+C -1 ; WX 667 ; N Thorn ; B 76 0 627 718 ;
+C -1 ; WX 778 ; N Omacron ; B 44 -19 734 864 ;
+C -1 ; WX 722 ; N Racute ; B 76 0 677 936 ;
+C -1 ; WX 667 ; N Sacute ; B 39 -19 629 936 ;
+C -1 ; WX 743 ; N dcaron ; B 34 -14 750 718 ;
+C -1 ; WX 722 ; N Umacron ; B 72 -19 651 864 ;
+C -1 ; WX 611 ; N uring ; B 66 -14 545 776 ;
+C -1 ; WX 333 ; N threesuperior ; B 8 271 326 710 ;
+C -1 ; WX 778 ; N Ograve ; B 44 -19 734 936 ;
+C -1 ; WX 722 ; N Agrave ; B 20 0 702 936 ;
+C -1 ; WX 722 ; N Abreve ; B 20 0 702 936 ;
+C -1 ; WX 584 ; N multiply ; B 40 1 545 505 ;
+C -1 ; WX 611 ; N uacute ; B 66 -14 545 750 ;
+C -1 ; WX 611 ; N Tcaron ; B 14 0 598 936 ;
+C -1 ; WX 494 ; N partialdiff ; B 11 -21 494 750 ;
+C -1 ; WX 556 ; N ydieresis ; B 10 -214 539 729 ;
+C -1 ; WX 722 ; N Nacute ; B 69 0 654 936 ;
+C -1 ; WX 278 ; N icircumflex ; B -37 0 316 750 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 76 0 621 936 ;
+C -1 ; WX 556 ; N adieresis ; B 29 -14 527 729 ;
+C -1 ; WX 556 ; N edieresis ; B 23 -14 528 729 ;
+C -1 ; WX 556 ; N cacute ; B 34 -14 524 750 ;
+C -1 ; WX 611 ; N nacute ; B 65 0 546 750 ;
+C -1 ; WX 611 ; N umacron ; B 66 -14 545 678 ;
+C -1 ; WX 722 ; N Ncaron ; B 69 0 654 936 ;
+C -1 ; WX 278 ; N Iacute ; B 64 0 329 936 ;
+C -1 ; WX 584 ; N plusminus ; B 40 0 544 506 ;
+C -1 ; WX 280 ; N brokenbar ; B 84 -150 196 700 ;
+C -1 ; WX 737 ; N registered ; B -11 -19 748 737 ;
+C -1 ; WX 778 ; N Gbreve ; B 44 -19 713 936 ;
+C -1 ; WX 278 ; N Idotaccent ; B 64 0 214 915 ;
+C -1 ; WX 600 ; N summation ; B 14 -10 585 706 ;
+C -1 ; WX 667 ; N Egrave ; B 76 0 621 936 ;
+C -1 ; WX 389 ; N racute ; B 64 0 384 750 ;
+C -1 ; WX 611 ; N omacron ; B 34 -14 578 678 ;
+C -1 ; WX 611 ; N Zacute ; B 25 0 586 936 ;
+C -1 ; WX 611 ; N Zcaron ; B 25 0 586 936 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 523 704 ;
+C -1 ; WX 722 ; N Eth ; B -5 0 685 718 ;
+C -1 ; WX 722 ; N Ccedilla ; B 44 -228 684 737 ;
+C -1 ; WX 278 ; N lcommaaccent ; B 69 -228 213 718 ;
+C -1 ; WX 389 ; N tcaron ; B 10 -6 421 878 ;
+C -1 ; WX 556 ; N eogonek ; B 23 -228 528 546 ;
+C -1 ; WX 722 ; N Uogonek ; B 72 -228 651 718 ;
+C -1 ; WX 722 ; N Aacute ; B 20 0 702 936 ;
+C -1 ; WX 722 ; N Adieresis ; B 20 0 702 915 ;
+C -1 ; WX 556 ; N egrave ; B 23 -14 528 750 ;
+C -1 ; WX 500 ; N zacute ; B 20 0 480 750 ;
+C -1 ; WX 278 ; N iogonek ; B 16 -224 249 725 ;
+C -1 ; WX 778 ; N Oacute ; B 44 -19 734 936 ;
+C -1 ; WX 611 ; N oacute ; B 34 -14 578 750 ;
+C -1 ; WX 556 ; N amacron ; B 29 -14 527 678 ;
+C -1 ; WX 556 ; N sacute ; B 30 -14 519 750 ;
+C -1 ; WX 278 ; N idieresis ; B -21 0 300 729 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 44 -19 734 936 ;
+C -1 ; WX 722 ; N Ugrave ; B 72 -19 651 936 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 611 ; N thorn ; B 62 -208 578 718 ;
+C -1 ; WX 333 ; N twosuperior ; B 9 283 324 710 ;
+C -1 ; WX 778 ; N Odieresis ; B 44 -19 734 915 ;
+C -1 ; WX 611 ; N mu ; B 66 -207 545 532 ;
+C -1 ; WX 278 ; N igrave ; B -50 0 209 750 ;
+C -1 ; WX 611 ; N ohungarumlaut ; B 34 -14 625 750 ;
+C -1 ; WX 667 ; N Eogonek ; B 76 -224 639 718 ;
+C -1 ; WX 611 ; N dcroat ; B 34 -14 650 718 ;
+C -1 ; WX 834 ; N threequarters ; B 16 -19 799 710 ;
+C -1 ; WX 667 ; N Scedilla ; B 39 -228 629 737 ;
+C -1 ; WX 400 ; N lcaron ; B 69 0 408 718 ;
+C -1 ; WX 722 ; N Kcommaaccent ; B 87 -228 722 718 ;
+C -1 ; WX 611 ; N Lacute ; B 76 0 583 936 ;
+C -1 ; WX 1000 ; N trademark ; B 44 306 956 718 ;
+C -1 ; WX 556 ; N edotaccent ; B 23 -14 528 729 ;
+C -1 ; WX 278 ; N Igrave ; B -50 0 214 936 ;
+C -1 ; WX 278 ; N Imacron ; B -33 0 312 864 ;
+C -1 ; WX 611 ; N Lcaron ; B 76 0 583 718 ;
+C -1 ; WX 834 ; N onehalf ; B 26 -19 794 710 ;
+C -1 ; WX 549 ; N lessequal ; B 29 0 526 704 ;
+C -1 ; WX 611 ; N ocircumflex ; B 34 -14 578 750 ;
+C -1 ; WX 611 ; N ntilde ; B 65 0 546 737 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 72 -19 681 936 ;
+C -1 ; WX 667 ; N Eacute ; B 76 0 621 936 ;
+C -1 ; WX 556 ; N emacron ; B 23 -14 528 678 ;
+C -1 ; WX 611 ; N gbreve ; B 40 -217 553 750 ;
+C -1 ; WX 834 ; N onequarter ; B 26 -19 766 710 ;
+C -1 ; WX 667 ; N Scaron ; B 39 -19 629 936 ;
+C -1 ; WX 667 ; N Scommaaccent ; B 39 -228 629 737 ;
+C -1 ; WX 778 ; N Ohungarumlaut ; B 44 -19 734 936 ;
+C -1 ; WX 400 ; N degree ; B 57 426 343 712 ;
+C -1 ; WX 611 ; N ograve ; B 34 -14 578 750 ;
+C -1 ; WX 722 ; N Ccaron ; B 44 -19 684 936 ;
+C -1 ; WX 611 ; N ugrave ; B 66 -14 545 750 ;
+C -1 ; WX 549 ; N radical ; B 10 -46 512 850 ;
+C -1 ; WX 722 ; N Dcaron ; B 76 0 685 936 ;
+C -1 ; WX 389 ; N rcommaaccent ; B 64 -228 373 546 ;
+C -1 ; WX 722 ; N Ntilde ; B 69 0 654 923 ;
+C -1 ; WX 611 ; N otilde ; B 34 -14 578 737 ;
+C -1 ; WX 722 ; N Rcommaaccent ; B 76 -228 677 718 ;
+C -1 ; WX 611 ; N Lcommaaccent ; B 76 -228 583 718 ;
+C -1 ; WX 722 ; N Atilde ; B 20 0 702 923 ;
+C -1 ; WX 722 ; N Aogonek ; B 20 -224 742 718 ;
+C -1 ; WX 722 ; N Aring ; B 20 0 702 962 ;
+C -1 ; WX 778 ; N Otilde ; B 44 -19 734 923 ;
+C -1 ; WX 500 ; N zdotaccent ; B 20 0 480 729 ;
+C -1 ; WX 667 ; N Ecaron ; B 76 0 621 936 ;
+C -1 ; WX 278 ; N Iogonek ; B -11 -228 222 718 ;
+C -1 ; WX 556 ; N kcommaaccent ; B 69 -228 562 718 ;
+C -1 ; WX 584 ; N minus ; B 40 197 544 309 ;
+C -1 ; WX 278 ; N Icircumflex ; B -37 0 316 936 ;
+C -1 ; WX 611 ; N ncaron ; B 65 0 546 750 ;
+C -1 ; WX 333 ; N tcommaaccent ; B 10 -228 309 676 ;
+C -1 ; WX 584 ; N logicalnot ; B 40 108 544 419 ;
+C -1 ; WX 611 ; N odieresis ; B 34 -14 578 729 ;
+C -1 ; WX 611 ; N udieresis ; B 66 -14 545 729 ;
+C -1 ; WX 549 ; N notequal ; B 15 -49 540 570 ;
+C -1 ; WX 611 ; N gcommaaccent ; B 40 -217 553 850 ;
+C -1 ; WX 611 ; N eth ; B 34 -14 578 737 ;
+C -1 ; WX 500 ; N zcaron ; B 20 0 480 750 ;
+C -1 ; WX 611 ; N ncommaaccent ; B 65 -228 546 546 ;
+C -1 ; WX 333 ; N onesuperior ; B 26 283 237 710 ;
+C -1 ; WX 278 ; N imacron ; B -8 0 285 678 ;
+C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2481
+KPX A C -40
+KPX A Cacute -40
+KPX A Ccaron -40
+KPX A Ccedilla -40
+KPX A G -50
+KPX A Gbreve -50
+KPX A Gcommaaccent -50
+KPX A O -40
+KPX A Oacute -40
+KPX A Ocircumflex -40
+KPX A Odieresis -40
+KPX A Ograve -40
+KPX A Ohungarumlaut -40
+KPX A Omacron -40
+KPX A Oslash -40
+KPX A Otilde -40
+KPX A Q -40
+KPX A T -90
+KPX A Tcaron -90
+KPX A Tcommaaccent -90
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -80
+KPX A W -60
+KPX A Y -110
+KPX A Yacute -110
+KPX A Ydieresis -110
+KPX A u -30
+KPX A uacute -30
+KPX A ucircumflex -30
+KPX A udieresis -30
+KPX A ugrave -30
+KPX A uhungarumlaut -30
+KPX A umacron -30
+KPX A uogonek -30
+KPX A uring -30
+KPX A v -40
+KPX A w -30
+KPX A y -30
+KPX A yacute -30
+KPX A ydieresis -30
+KPX Aacute C -40
+KPX Aacute Cacute -40
+KPX Aacute Ccaron -40
+KPX Aacute Ccedilla -40
+KPX Aacute G -50
+KPX Aacute Gbreve -50
+KPX Aacute Gcommaaccent -50
+KPX Aacute O -40
+KPX Aacute Oacute -40
+KPX Aacute Ocircumflex -40
+KPX Aacute Odieresis -40
+KPX Aacute Ograve -40
+KPX Aacute Ohungarumlaut -40
+KPX Aacute Omacron -40
+KPX Aacute Oslash -40
+KPX Aacute Otilde -40
+KPX Aacute Q -40
+KPX Aacute T -90
+KPX Aacute Tcaron -90
+KPX Aacute Tcommaaccent -90
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -80
+KPX Aacute W -60
+KPX Aacute Y -110
+KPX Aacute Yacute -110
+KPX Aacute Ydieresis -110
+KPX Aacute u -30
+KPX Aacute uacute -30
+KPX Aacute ucircumflex -30
+KPX Aacute udieresis -30
+KPX Aacute ugrave -30
+KPX Aacute uhungarumlaut -30
+KPX Aacute umacron -30
+KPX Aacute uogonek -30
+KPX Aacute uring -30
+KPX Aacute v -40
+KPX Aacute w -30
+KPX Aacute y -30
+KPX Aacute yacute -30
+KPX Aacute ydieresis -30
+KPX Abreve C -40
+KPX Abreve Cacute -40
+KPX Abreve Ccaron -40
+KPX Abreve Ccedilla -40
+KPX Abreve G -50
+KPX Abreve Gbreve -50
+KPX Abreve Gcommaaccent -50
+KPX Abreve O -40
+KPX Abreve Oacute -40
+KPX Abreve Ocircumflex -40
+KPX Abreve Odieresis -40
+KPX Abreve Ograve -40
+KPX Abreve Ohungarumlaut -40
+KPX Abreve Omacron -40
+KPX Abreve Oslash -40
+KPX Abreve Otilde -40
+KPX Abreve Q -40
+KPX Abreve T -90
+KPX Abreve Tcaron -90
+KPX Abreve Tcommaaccent -90
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -80
+KPX Abreve W -60
+KPX Abreve Y -110
+KPX Abreve Yacute -110
+KPX Abreve Ydieresis -110
+KPX Abreve u -30
+KPX Abreve uacute -30
+KPX Abreve ucircumflex -30
+KPX Abreve udieresis -30
+KPX Abreve ugrave -30
+KPX Abreve uhungarumlaut -30
+KPX Abreve umacron -30
+KPX Abreve uogonek -30
+KPX Abreve uring -30
+KPX Abreve v -40
+KPX Abreve w -30
+KPX Abreve y -30
+KPX Abreve yacute -30
+KPX Abreve ydieresis -30
+KPX Acircumflex C -40
+KPX Acircumflex Cacute -40
+KPX Acircumflex Ccaron -40
+KPX Acircumflex Ccedilla -40
+KPX Acircumflex G -50
+KPX Acircumflex Gbreve -50
+KPX Acircumflex Gcommaaccent -50
+KPX Acircumflex O -40
+KPX Acircumflex Oacute -40
+KPX Acircumflex Ocircumflex -40
+KPX Acircumflex Odieresis -40
+KPX Acircumflex Ograve -40
+KPX Acircumflex Ohungarumlaut -40
+KPX Acircumflex Omacron -40
+KPX Acircumflex Oslash -40
+KPX Acircumflex Otilde -40
+KPX Acircumflex Q -40
+KPX Acircumflex T -90
+KPX Acircumflex Tcaron -90
+KPX Acircumflex Tcommaaccent -90
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -80
+KPX Acircumflex W -60
+KPX Acircumflex Y -110
+KPX Acircumflex Yacute -110
+KPX Acircumflex Ydieresis -110
+KPX Acircumflex u -30
+KPX Acircumflex uacute -30
+KPX Acircumflex ucircumflex -30
+KPX Acircumflex udieresis -30
+KPX Acircumflex ugrave -30
+KPX Acircumflex uhungarumlaut -30
+KPX Acircumflex umacron -30
+KPX Acircumflex uogonek -30
+KPX Acircumflex uring -30
+KPX Acircumflex v -40
+KPX Acircumflex w -30
+KPX Acircumflex y -30
+KPX Acircumflex yacute -30
+KPX Acircumflex ydieresis -30
+KPX Adieresis C -40
+KPX Adieresis Cacute -40
+KPX Adieresis Ccaron -40
+KPX Adieresis Ccedilla -40
+KPX Adieresis G -50
+KPX Adieresis Gbreve -50
+KPX Adieresis Gcommaaccent -50
+KPX Adieresis O -40
+KPX Adieresis Oacute -40
+KPX Adieresis Ocircumflex -40
+KPX Adieresis Odieresis -40
+KPX Adieresis Ograve -40
+KPX Adieresis Ohungarumlaut -40
+KPX Adieresis Omacron -40
+KPX Adieresis Oslash -40
+KPX Adieresis Otilde -40
+KPX Adieresis Q -40
+KPX Adieresis T -90
+KPX Adieresis Tcaron -90
+KPX Adieresis Tcommaaccent -90
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -80
+KPX Adieresis W -60
+KPX Adieresis Y -110
+KPX Adieresis Yacute -110
+KPX Adieresis Ydieresis -110
+KPX Adieresis u -30
+KPX Adieresis uacute -30
+KPX Adieresis ucircumflex -30
+KPX Adieresis udieresis -30
+KPX Adieresis ugrave -30
+KPX Adieresis uhungarumlaut -30
+KPX Adieresis umacron -30
+KPX Adieresis uogonek -30
+KPX Adieresis uring -30
+KPX Adieresis v -40
+KPX Adieresis w -30
+KPX Adieresis y -30
+KPX Adieresis yacute -30
+KPX Adieresis ydieresis -30
+KPX Agrave C -40
+KPX Agrave Cacute -40
+KPX Agrave Ccaron -40
+KPX Agrave Ccedilla -40
+KPX Agrave G -50
+KPX Agrave Gbreve -50
+KPX Agrave Gcommaaccent -50
+KPX Agrave O -40
+KPX Agrave Oacute -40
+KPX Agrave Ocircumflex -40
+KPX Agrave Odieresis -40
+KPX Agrave Ograve -40
+KPX Agrave Ohungarumlaut -40
+KPX Agrave Omacron -40
+KPX Agrave Oslash -40
+KPX Agrave Otilde -40
+KPX Agrave Q -40
+KPX Agrave T -90
+KPX Agrave Tcaron -90
+KPX Agrave Tcommaaccent -90
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -80
+KPX Agrave W -60
+KPX Agrave Y -110
+KPX Agrave Yacute -110
+KPX Agrave Ydieresis -110
+KPX Agrave u -30
+KPX Agrave uacute -30
+KPX Agrave ucircumflex -30
+KPX Agrave udieresis -30
+KPX Agrave ugrave -30
+KPX Agrave uhungarumlaut -30
+KPX Agrave umacron -30
+KPX Agrave uogonek -30
+KPX Agrave uring -30
+KPX Agrave v -40
+KPX Agrave w -30
+KPX Agrave y -30
+KPX Agrave yacute -30
+KPX Agrave ydieresis -30
+KPX Amacron C -40
+KPX Amacron Cacute -40
+KPX Amacron Ccaron -40
+KPX Amacron Ccedilla -40
+KPX Amacron G -50
+KPX Amacron Gbreve -50
+KPX Amacron Gcommaaccent -50
+KPX Amacron O -40
+KPX Amacron Oacute -40
+KPX Amacron Ocircumflex -40
+KPX Amacron Odieresis -40
+KPX Amacron Ograve -40
+KPX Amacron Ohungarumlaut -40
+KPX Amacron Omacron -40
+KPX Amacron Oslash -40
+KPX Amacron Otilde -40
+KPX Amacron Q -40
+KPX Amacron T -90
+KPX Amacron Tcaron -90
+KPX Amacron Tcommaaccent -90
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -80
+KPX Amacron W -60
+KPX Amacron Y -110
+KPX Amacron Yacute -110
+KPX Amacron Ydieresis -110
+KPX Amacron u -30
+KPX Amacron uacute -30
+KPX Amacron ucircumflex -30
+KPX Amacron udieresis -30
+KPX Amacron ugrave -30
+KPX Amacron uhungarumlaut -30
+KPX Amacron umacron -30
+KPX Amacron uogonek -30
+KPX Amacron uring -30
+KPX Amacron v -40
+KPX Amacron w -30
+KPX Amacron y -30
+KPX Amacron yacute -30
+KPX Amacron ydieresis -30
+KPX Aogonek C -40
+KPX Aogonek Cacute -40
+KPX Aogonek Ccaron -40
+KPX Aogonek Ccedilla -40
+KPX Aogonek G -50
+KPX Aogonek Gbreve -50
+KPX Aogonek Gcommaaccent -50
+KPX Aogonek O -40
+KPX Aogonek Oacute -40
+KPX Aogonek Ocircumflex -40
+KPX Aogonek Odieresis -40
+KPX Aogonek Ograve -40
+KPX Aogonek Ohungarumlaut -40
+KPX Aogonek Omacron -40
+KPX Aogonek Oslash -40
+KPX Aogonek Otilde -40
+KPX Aogonek Q -40
+KPX Aogonek T -90
+KPX Aogonek Tcaron -90
+KPX Aogonek Tcommaaccent -90
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -80
+KPX Aogonek W -60
+KPX Aogonek Y -110
+KPX Aogonek Yacute -110
+KPX Aogonek Ydieresis -110
+KPX Aogonek u -30
+KPX Aogonek uacute -30
+KPX Aogonek ucircumflex -30
+KPX Aogonek udieresis -30
+KPX Aogonek ugrave -30
+KPX Aogonek uhungarumlaut -30
+KPX Aogonek umacron -30
+KPX Aogonek uogonek -30
+KPX Aogonek uring -30
+KPX Aogonek v -40
+KPX Aogonek w -30
+KPX Aogonek y -30
+KPX Aogonek yacute -30
+KPX Aogonek ydieresis -30
+KPX Aring C -40
+KPX Aring Cacute -40
+KPX Aring Ccaron -40
+KPX Aring Ccedilla -40
+KPX Aring G -50
+KPX Aring Gbreve -50
+KPX Aring Gcommaaccent -50
+KPX Aring O -40
+KPX Aring Oacute -40
+KPX Aring Ocircumflex -40
+KPX Aring Odieresis -40
+KPX Aring Ograve -40
+KPX Aring Ohungarumlaut -40
+KPX Aring Omacron -40
+KPX Aring Oslash -40
+KPX Aring Otilde -40
+KPX Aring Q -40
+KPX Aring T -90
+KPX Aring Tcaron -90
+KPX Aring Tcommaaccent -90
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -80
+KPX Aring W -60
+KPX Aring Y -110
+KPX Aring Yacute -110
+KPX Aring Ydieresis -110
+KPX Aring u -30
+KPX Aring uacute -30
+KPX Aring ucircumflex -30
+KPX Aring udieresis -30
+KPX Aring ugrave -30
+KPX Aring uhungarumlaut -30
+KPX Aring umacron -30
+KPX Aring uogonek -30
+KPX Aring uring -30
+KPX Aring v -40
+KPX Aring w -30
+KPX Aring y -30
+KPX Aring yacute -30
+KPX Aring ydieresis -30
+KPX Atilde C -40
+KPX Atilde Cacute -40
+KPX Atilde Ccaron -40
+KPX Atilde Ccedilla -40
+KPX Atilde G -50
+KPX Atilde Gbreve -50
+KPX Atilde Gcommaaccent -50
+KPX Atilde O -40
+KPX Atilde Oacute -40
+KPX Atilde Ocircumflex -40
+KPX Atilde Odieresis -40
+KPX Atilde Ograve -40
+KPX Atilde Ohungarumlaut -40
+KPX Atilde Omacron -40
+KPX Atilde Oslash -40
+KPX Atilde Otilde -40
+KPX Atilde Q -40
+KPX Atilde T -90
+KPX Atilde Tcaron -90
+KPX Atilde Tcommaaccent -90
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -80
+KPX Atilde W -60
+KPX Atilde Y -110
+KPX Atilde Yacute -110
+KPX Atilde Ydieresis -110
+KPX Atilde u -30
+KPX Atilde uacute -30
+KPX Atilde ucircumflex -30
+KPX Atilde udieresis -30
+KPX Atilde ugrave -30
+KPX Atilde uhungarumlaut -30
+KPX Atilde umacron -30
+KPX Atilde uogonek -30
+KPX Atilde uring -30
+KPX Atilde v -40
+KPX Atilde w -30
+KPX Atilde y -30
+KPX Atilde yacute -30
+KPX Atilde ydieresis -30
+KPX B A -30
+KPX B Aacute -30
+KPX B Abreve -30
+KPX B Acircumflex -30
+KPX B Adieresis -30
+KPX B Agrave -30
+KPX B Amacron -30
+KPX B Aogonek -30
+KPX B Aring -30
+KPX B Atilde -30
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX D A -40
+KPX D Aacute -40
+KPX D Abreve -40
+KPX D Acircumflex -40
+KPX D Adieresis -40
+KPX D Agrave -40
+KPX D Amacron -40
+KPX D Aogonek -40
+KPX D Aring -40
+KPX D Atilde -40
+KPX D V -40
+KPX D W -40
+KPX D Y -70
+KPX D Yacute -70
+KPX D Ydieresis -70
+KPX D comma -30
+KPX D period -30
+KPX Dcaron A -40
+KPX Dcaron Aacute -40
+KPX Dcaron Abreve -40
+KPX Dcaron Acircumflex -40
+KPX Dcaron Adieresis -40
+KPX Dcaron Agrave -40
+KPX Dcaron Amacron -40
+KPX Dcaron Aogonek -40
+KPX Dcaron Aring -40
+KPX Dcaron Atilde -40
+KPX Dcaron V -40
+KPX Dcaron W -40
+KPX Dcaron Y -70
+KPX Dcaron Yacute -70
+KPX Dcaron Ydieresis -70
+KPX Dcaron comma -30
+KPX Dcaron period -30
+KPX Dcroat A -40
+KPX Dcroat Aacute -40
+KPX Dcroat Abreve -40
+KPX Dcroat Acircumflex -40
+KPX Dcroat Adieresis -40
+KPX Dcroat Agrave -40
+KPX Dcroat Amacron -40
+KPX Dcroat Aogonek -40
+KPX Dcroat Aring -40
+KPX Dcroat Atilde -40
+KPX Dcroat V -40
+KPX Dcroat W -40
+KPX Dcroat Y -70
+KPX Dcroat Yacute -70
+KPX Dcroat Ydieresis -70
+KPX Dcroat comma -30
+KPX Dcroat period -30
+KPX F A -80
+KPX F Aacute -80
+KPX F Abreve -80
+KPX F Acircumflex -80
+KPX F Adieresis -80
+KPX F Agrave -80
+KPX F Amacron -80
+KPX F Aogonek -80
+KPX F Aring -80
+KPX F Atilde -80
+KPX F a -20
+KPX F aacute -20
+KPX F abreve -20
+KPX F acircumflex -20
+KPX F adieresis -20
+KPX F agrave -20
+KPX F amacron -20
+KPX F aogonek -20
+KPX F aring -20
+KPX F atilde -20
+KPX F comma -100
+KPX F period -100
+KPX J A -20
+KPX J Aacute -20
+KPX J Abreve -20
+KPX J Acircumflex -20
+KPX J Adieresis -20
+KPX J Agrave -20
+KPX J Amacron -20
+KPX J Aogonek -20
+KPX J Aring -20
+KPX J Atilde -20
+KPX J comma -20
+KPX J period -20
+KPX J u -20
+KPX J uacute -20
+KPX J ucircumflex -20
+KPX J udieresis -20
+KPX J ugrave -20
+KPX J uhungarumlaut -20
+KPX J umacron -20
+KPX J uogonek -20
+KPX J uring -20
+KPX K O -30
+KPX K Oacute -30
+KPX K Ocircumflex -30
+KPX K Odieresis -30
+KPX K Ograve -30
+KPX K Ohungarumlaut -30
+KPX K Omacron -30
+KPX K Oslash -30
+KPX K Otilde -30
+KPX K e -15
+KPX K eacute -15
+KPX K ecaron -15
+KPX K ecircumflex -15
+KPX K edieresis -15
+KPX K edotaccent -15
+KPX K egrave -15
+KPX K emacron -15
+KPX K eogonek -15
+KPX K o -35
+KPX K oacute -35
+KPX K ocircumflex -35
+KPX K odieresis -35
+KPX K ograve -35
+KPX K ohungarumlaut -35
+KPX K omacron -35
+KPX K oslash -35
+KPX K otilde -35
+KPX K u -30
+KPX K uacute -30
+KPX K ucircumflex -30
+KPX K udieresis -30
+KPX K ugrave -30
+KPX K uhungarumlaut -30
+KPX K umacron -30
+KPX K uogonek -30
+KPX K uring -30
+KPX K y -40
+KPX K yacute -40
+KPX K ydieresis -40
+KPX Kcommaaccent O -30
+KPX Kcommaaccent Oacute -30
+KPX Kcommaaccent Ocircumflex -30
+KPX Kcommaaccent Odieresis -30
+KPX Kcommaaccent Ograve -30
+KPX Kcommaaccent Ohungarumlaut -30
+KPX Kcommaaccent Omacron -30
+KPX Kcommaaccent Oslash -30
+KPX Kcommaaccent Otilde -30
+KPX Kcommaaccent e -15
+KPX Kcommaaccent eacute -15
+KPX Kcommaaccent ecaron -15
+KPX Kcommaaccent ecircumflex -15
+KPX Kcommaaccent edieresis -15
+KPX Kcommaaccent edotaccent -15
+KPX Kcommaaccent egrave -15
+KPX Kcommaaccent emacron -15
+KPX Kcommaaccent eogonek -15
+KPX Kcommaaccent o -35
+KPX Kcommaaccent oacute -35
+KPX Kcommaaccent ocircumflex -35
+KPX Kcommaaccent odieresis -35
+KPX Kcommaaccent ograve -35
+KPX Kcommaaccent ohungarumlaut -35
+KPX Kcommaaccent omacron -35
+KPX Kcommaaccent oslash -35
+KPX Kcommaaccent otilde -35
+KPX Kcommaaccent u -30
+KPX Kcommaaccent uacute -30
+KPX Kcommaaccent ucircumflex -30
+KPX Kcommaaccent udieresis -30
+KPX Kcommaaccent ugrave -30
+KPX Kcommaaccent uhungarumlaut -30
+KPX Kcommaaccent umacron -30
+KPX Kcommaaccent uogonek -30
+KPX Kcommaaccent uring -30
+KPX Kcommaaccent y -40
+KPX Kcommaaccent yacute -40
+KPX Kcommaaccent ydieresis -40
+KPX L T -90
+KPX L Tcaron -90
+KPX L Tcommaaccent -90
+KPX L V -110
+KPX L W -80
+KPX L Y -120
+KPX L Yacute -120
+KPX L Ydieresis -120
+KPX L quotedblright -140
+KPX L quoteright -140
+KPX L y -30
+KPX L yacute -30
+KPX L ydieresis -30
+KPX Lacute T -90
+KPX Lacute Tcaron -90
+KPX Lacute Tcommaaccent -90
+KPX Lacute V -110
+KPX Lacute W -80
+KPX Lacute Y -120
+KPX Lacute Yacute -120
+KPX Lacute Ydieresis -120
+KPX Lacute quotedblright -140
+KPX Lacute quoteright -140
+KPX Lacute y -30
+KPX Lacute yacute -30
+KPX Lacute ydieresis -30
+KPX Lcommaaccent T -90
+KPX Lcommaaccent Tcaron -90
+KPX Lcommaaccent Tcommaaccent -90
+KPX Lcommaaccent V -110
+KPX Lcommaaccent W -80
+KPX Lcommaaccent Y -120
+KPX Lcommaaccent Yacute -120
+KPX Lcommaaccent Ydieresis -120
+KPX Lcommaaccent quotedblright -140
+KPX Lcommaaccent quoteright -140
+KPX Lcommaaccent y -30
+KPX Lcommaaccent yacute -30
+KPX Lcommaaccent ydieresis -30
+KPX Lslash T -90
+KPX Lslash Tcaron -90
+KPX Lslash Tcommaaccent -90
+KPX Lslash V -110
+KPX Lslash W -80
+KPX Lslash Y -120
+KPX Lslash Yacute -120
+KPX Lslash Ydieresis -120
+KPX Lslash quotedblright -140
+KPX Lslash quoteright -140
+KPX Lslash y -30
+KPX Lslash yacute -30
+KPX Lslash ydieresis -30
+KPX O A -50
+KPX O Aacute -50
+KPX O Abreve -50
+KPX O Acircumflex -50
+KPX O Adieresis -50
+KPX O Agrave -50
+KPX O Amacron -50
+KPX O Aogonek -50
+KPX O Aring -50
+KPX O Atilde -50
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -50
+KPX O X -50
+KPX O Y -70
+KPX O Yacute -70
+KPX O Ydieresis -70
+KPX O comma -40
+KPX O period -40
+KPX Oacute A -50
+KPX Oacute Aacute -50
+KPX Oacute Abreve -50
+KPX Oacute Acircumflex -50
+KPX Oacute Adieresis -50
+KPX Oacute Agrave -50
+KPX Oacute Amacron -50
+KPX Oacute Aogonek -50
+KPX Oacute Aring -50
+KPX Oacute Atilde -50
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -50
+KPX Oacute X -50
+KPX Oacute Y -70
+KPX Oacute Yacute -70
+KPX Oacute Ydieresis -70
+KPX Oacute comma -40
+KPX Oacute period -40
+KPX Ocircumflex A -50
+KPX Ocircumflex Aacute -50
+KPX Ocircumflex Abreve -50
+KPX Ocircumflex Acircumflex -50
+KPX Ocircumflex Adieresis -50
+KPX Ocircumflex Agrave -50
+KPX Ocircumflex Amacron -50
+KPX Ocircumflex Aogonek -50
+KPX Ocircumflex Aring -50
+KPX Ocircumflex Atilde -50
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -50
+KPX Ocircumflex X -50
+KPX Ocircumflex Y -70
+KPX Ocircumflex Yacute -70
+KPX Ocircumflex Ydieresis -70
+KPX Ocircumflex comma -40
+KPX Ocircumflex period -40
+KPX Odieresis A -50
+KPX Odieresis Aacute -50
+KPX Odieresis Abreve -50
+KPX Odieresis Acircumflex -50
+KPX Odieresis Adieresis -50
+KPX Odieresis Agrave -50
+KPX Odieresis Amacron -50
+KPX Odieresis Aogonek -50
+KPX Odieresis Aring -50
+KPX Odieresis Atilde -50
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -50
+KPX Odieresis X -50
+KPX Odieresis Y -70
+KPX Odieresis Yacute -70
+KPX Odieresis Ydieresis -70
+KPX Odieresis comma -40
+KPX Odieresis period -40
+KPX Ograve A -50
+KPX Ograve Aacute -50
+KPX Ograve Abreve -50
+KPX Ograve Acircumflex -50
+KPX Ograve Adieresis -50
+KPX Ograve Agrave -50
+KPX Ograve Amacron -50
+KPX Ograve Aogonek -50
+KPX Ograve Aring -50
+KPX Ograve Atilde -50
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -50
+KPX Ograve X -50
+KPX Ograve Y -70
+KPX Ograve Yacute -70
+KPX Ograve Ydieresis -70
+KPX Ograve comma -40
+KPX Ograve period -40
+KPX Ohungarumlaut A -50
+KPX Ohungarumlaut Aacute -50
+KPX Ohungarumlaut Abreve -50
+KPX Ohungarumlaut Acircumflex -50
+KPX Ohungarumlaut Adieresis -50
+KPX Ohungarumlaut Agrave -50
+KPX Ohungarumlaut Amacron -50
+KPX Ohungarumlaut Aogonek -50
+KPX Ohungarumlaut Aring -50
+KPX Ohungarumlaut Atilde -50
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -50
+KPX Ohungarumlaut X -50
+KPX Ohungarumlaut Y -70
+KPX Ohungarumlaut Yacute -70
+KPX Ohungarumlaut Ydieresis -70
+KPX Ohungarumlaut comma -40
+KPX Ohungarumlaut period -40
+KPX Omacron A -50
+KPX Omacron Aacute -50
+KPX Omacron Abreve -50
+KPX Omacron Acircumflex -50
+KPX Omacron Adieresis -50
+KPX Omacron Agrave -50
+KPX Omacron Amacron -50
+KPX Omacron Aogonek -50
+KPX Omacron Aring -50
+KPX Omacron Atilde -50
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -50
+KPX Omacron X -50
+KPX Omacron Y -70
+KPX Omacron Yacute -70
+KPX Omacron Ydieresis -70
+KPX Omacron comma -40
+KPX Omacron period -40
+KPX Oslash A -50
+KPX Oslash Aacute -50
+KPX Oslash Abreve -50
+KPX Oslash Acircumflex -50
+KPX Oslash Adieresis -50
+KPX Oslash Agrave -50
+KPX Oslash Amacron -50
+KPX Oslash Aogonek -50
+KPX Oslash Aring -50
+KPX Oslash Atilde -50
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -50
+KPX Oslash X -50
+KPX Oslash Y -70
+KPX Oslash Yacute -70
+KPX Oslash Ydieresis -70
+KPX Oslash comma -40
+KPX Oslash period -40
+KPX Otilde A -50
+KPX Otilde Aacute -50
+KPX Otilde Abreve -50
+KPX Otilde Acircumflex -50
+KPX Otilde Adieresis -50
+KPX Otilde Agrave -50
+KPX Otilde Amacron -50
+KPX Otilde Aogonek -50
+KPX Otilde Aring -50
+KPX Otilde Atilde -50
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -50
+KPX Otilde X -50
+KPX Otilde Y -70
+KPX Otilde Yacute -70
+KPX Otilde Ydieresis -70
+KPX Otilde comma -40
+KPX Otilde period -40
+KPX P A -100
+KPX P Aacute -100
+KPX P Abreve -100
+KPX P Acircumflex -100
+KPX P Adieresis -100
+KPX P Agrave -100
+KPX P Amacron -100
+KPX P Aogonek -100
+KPX P Aring -100
+KPX P Atilde -100
+KPX P a -30
+KPX P aacute -30
+KPX P abreve -30
+KPX P acircumflex -30
+KPX P adieresis -30
+KPX P agrave -30
+KPX P amacron -30
+KPX P aogonek -30
+KPX P aring -30
+KPX P atilde -30
+KPX P comma -120
+KPX P e -30
+KPX P eacute -30
+KPX P ecaron -30
+KPX P ecircumflex -30
+KPX P edieresis -30
+KPX P edotaccent -30
+KPX P egrave -30
+KPX P emacron -30
+KPX P eogonek -30
+KPX P o -40
+KPX P oacute -40
+KPX P ocircumflex -40
+KPX P odieresis -40
+KPX P ograve -40
+KPX P ohungarumlaut -40
+KPX P omacron -40
+KPX P oslash -40
+KPX P otilde -40
+KPX P period -120
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX Q comma 20
+KPX Q period 20
+KPX R O -20
+KPX R Oacute -20
+KPX R Ocircumflex -20
+KPX R Odieresis -20
+KPX R Ograve -20
+KPX R Ohungarumlaut -20
+KPX R Omacron -20
+KPX R Oslash -20
+KPX R Otilde -20
+KPX R T -20
+KPX R Tcaron -20
+KPX R Tcommaaccent -20
+KPX R U -20
+KPX R Uacute -20
+KPX R Ucircumflex -20
+KPX R Udieresis -20
+KPX R Ugrave -20
+KPX R Uhungarumlaut -20
+KPX R Umacron -20
+KPX R Uogonek -20
+KPX R Uring -20
+KPX R V -50
+KPX R W -40
+KPX R Y -50
+KPX R Yacute -50
+KPX R Ydieresis -50
+KPX Racute O -20
+KPX Racute Oacute -20
+KPX Racute Ocircumflex -20
+KPX Racute Odieresis -20
+KPX Racute Ograve -20
+KPX Racute Ohungarumlaut -20
+KPX Racute Omacron -20
+KPX Racute Oslash -20
+KPX Racute Otilde -20
+KPX Racute T -20
+KPX Racute Tcaron -20
+KPX Racute Tcommaaccent -20
+KPX Racute U -20
+KPX Racute Uacute -20
+KPX Racute Ucircumflex -20
+KPX Racute Udieresis -20
+KPX Racute Ugrave -20
+KPX Racute Uhungarumlaut -20
+KPX Racute Umacron -20
+KPX Racute Uogonek -20
+KPX Racute Uring -20
+KPX Racute V -50
+KPX Racute W -40
+KPX Racute Y -50
+KPX Racute Yacute -50
+KPX Racute Ydieresis -50
+KPX Rcaron O -20
+KPX Rcaron Oacute -20
+KPX Rcaron Ocircumflex -20
+KPX Rcaron Odieresis -20
+KPX Rcaron Ograve -20
+KPX Rcaron Ohungarumlaut -20
+KPX Rcaron Omacron -20
+KPX Rcaron Oslash -20
+KPX Rcaron Otilde -20
+KPX Rcaron T -20
+KPX Rcaron Tcaron -20
+KPX Rcaron Tcommaaccent -20
+KPX Rcaron U -20
+KPX Rcaron Uacute -20
+KPX Rcaron Ucircumflex -20
+KPX Rcaron Udieresis -20
+KPX Rcaron Ugrave -20
+KPX Rcaron Uhungarumlaut -20
+KPX Rcaron Umacron -20
+KPX Rcaron Uogonek -20
+KPX Rcaron Uring -20
+KPX Rcaron V -50
+KPX Rcaron W -40
+KPX Rcaron Y -50
+KPX Rcaron Yacute -50
+KPX Rcaron Ydieresis -50
+KPX Rcommaaccent O -20
+KPX Rcommaaccent Oacute -20
+KPX Rcommaaccent Ocircumflex -20
+KPX Rcommaaccent Odieresis -20
+KPX Rcommaaccent Ograve -20
+KPX Rcommaaccent Ohungarumlaut -20
+KPX Rcommaaccent Omacron -20
+KPX Rcommaaccent Oslash -20
+KPX Rcommaaccent Otilde -20
+KPX Rcommaaccent T -20
+KPX Rcommaaccent Tcaron -20
+KPX Rcommaaccent Tcommaaccent -20
+KPX Rcommaaccent U -20
+KPX Rcommaaccent Uacute -20
+KPX Rcommaaccent Ucircumflex -20
+KPX Rcommaaccent Udieresis -20
+KPX Rcommaaccent Ugrave -20
+KPX Rcommaaccent Uhungarumlaut -20
+KPX Rcommaaccent Umacron -20
+KPX Rcommaaccent Uogonek -20
+KPX Rcommaaccent Uring -20
+KPX Rcommaaccent V -50
+KPX Rcommaaccent W -40
+KPX Rcommaaccent Y -50
+KPX Rcommaaccent Yacute -50
+KPX Rcommaaccent Ydieresis -50
+KPX T A -90
+KPX T Aacute -90
+KPX T Abreve -90
+KPX T Acircumflex -90
+KPX T Adieresis -90
+KPX T Agrave -90
+KPX T Amacron -90
+KPX T Aogonek -90
+KPX T Aring -90
+KPX T Atilde -90
+KPX T O -40
+KPX T Oacute -40
+KPX T Ocircumflex -40
+KPX T Odieresis -40
+KPX T Ograve -40
+KPX T Ohungarumlaut -40
+KPX T Omacron -40
+KPX T Oslash -40
+KPX T Otilde -40
+KPX T a -80
+KPX T aacute -80
+KPX T abreve -80
+KPX T acircumflex -80
+KPX T adieresis -80
+KPX T agrave -80
+KPX T amacron -80
+KPX T aogonek -80
+KPX T aring -80
+KPX T atilde -80
+KPX T colon -40
+KPX T comma -80
+KPX T e -60
+KPX T eacute -60
+KPX T ecaron -60
+KPX T ecircumflex -60
+KPX T edieresis -60
+KPX T edotaccent -60
+KPX T egrave -60
+KPX T emacron -60
+KPX T eogonek -60
+KPX T hyphen -120
+KPX T o -80
+KPX T oacute -80
+KPX T ocircumflex -80
+KPX T odieresis -80
+KPX T ograve -80
+KPX T ohungarumlaut -80
+KPX T omacron -80
+KPX T oslash -80
+KPX T otilde -80
+KPX T period -80
+KPX T r -80
+KPX T racute -80
+KPX T rcommaaccent -80
+KPX T semicolon -40
+KPX T u -90
+KPX T uacute -90
+KPX T ucircumflex -90
+KPX T udieresis -90
+KPX T ugrave -90
+KPX T uhungarumlaut -90
+KPX T umacron -90
+KPX T uogonek -90
+KPX T uring -90
+KPX T w -60
+KPX T y -60
+KPX T yacute -60
+KPX T ydieresis -60
+KPX Tcaron A -90
+KPX Tcaron Aacute -90
+KPX Tcaron Abreve -90
+KPX Tcaron Acircumflex -90
+KPX Tcaron Adieresis -90
+KPX Tcaron Agrave -90
+KPX Tcaron Amacron -90
+KPX Tcaron Aogonek -90
+KPX Tcaron Aring -90
+KPX Tcaron Atilde -90
+KPX Tcaron O -40
+KPX Tcaron Oacute -40
+KPX Tcaron Ocircumflex -40
+KPX Tcaron Odieresis -40
+KPX Tcaron Ograve -40
+KPX Tcaron Ohungarumlaut -40
+KPX Tcaron Omacron -40
+KPX Tcaron Oslash -40
+KPX Tcaron Otilde -40
+KPX Tcaron a -80
+KPX Tcaron aacute -80
+KPX Tcaron abreve -80
+KPX Tcaron acircumflex -80
+KPX Tcaron adieresis -80
+KPX Tcaron agrave -80
+KPX Tcaron amacron -80
+KPX Tcaron aogonek -80
+KPX Tcaron aring -80
+KPX Tcaron atilde -80
+KPX Tcaron colon -40
+KPX Tcaron comma -80
+KPX Tcaron e -60
+KPX Tcaron eacute -60
+KPX Tcaron ecaron -60
+KPX Tcaron ecircumflex -60
+KPX Tcaron edieresis -60
+KPX Tcaron edotaccent -60
+KPX Tcaron egrave -60
+KPX Tcaron emacron -60
+KPX Tcaron eogonek -60
+KPX Tcaron hyphen -120
+KPX Tcaron o -80
+KPX Tcaron oacute -80
+KPX Tcaron ocircumflex -80
+KPX Tcaron odieresis -80
+KPX Tcaron ograve -80
+KPX Tcaron ohungarumlaut -80
+KPX Tcaron omacron -80
+KPX Tcaron oslash -80
+KPX Tcaron otilde -80
+KPX Tcaron period -80
+KPX Tcaron r -80
+KPX Tcaron racute -80
+KPX Tcaron rcommaaccent -80
+KPX Tcaron semicolon -40
+KPX Tcaron u -90
+KPX Tcaron uacute -90
+KPX Tcaron ucircumflex -90
+KPX Tcaron udieresis -90
+KPX Tcaron ugrave -90
+KPX Tcaron uhungarumlaut -90
+KPX Tcaron umacron -90
+KPX Tcaron uogonek -90
+KPX Tcaron uring -90
+KPX Tcaron w -60
+KPX Tcaron y -60
+KPX Tcaron yacute -60
+KPX Tcaron ydieresis -60
+KPX Tcommaaccent A -90
+KPX Tcommaaccent Aacute -90
+KPX Tcommaaccent Abreve -90
+KPX Tcommaaccent Acircumflex -90
+KPX Tcommaaccent Adieresis -90
+KPX Tcommaaccent Agrave -90
+KPX Tcommaaccent Amacron -90
+KPX Tcommaaccent Aogonek -90
+KPX Tcommaaccent Aring -90
+KPX Tcommaaccent Atilde -90
+KPX Tcommaaccent O -40
+KPX Tcommaaccent Oacute -40
+KPX Tcommaaccent Ocircumflex -40
+KPX Tcommaaccent Odieresis -40
+KPX Tcommaaccent Ograve -40
+KPX Tcommaaccent Ohungarumlaut -40
+KPX Tcommaaccent Omacron -40
+KPX Tcommaaccent Oslash -40
+KPX Tcommaaccent Otilde -40
+KPX Tcommaaccent a -80
+KPX Tcommaaccent aacute -80
+KPX Tcommaaccent abreve -80
+KPX Tcommaaccent acircumflex -80
+KPX Tcommaaccent adieresis -80
+KPX Tcommaaccent agrave -80
+KPX Tcommaaccent amacron -80
+KPX Tcommaaccent aogonek -80
+KPX Tcommaaccent aring -80
+KPX Tcommaaccent atilde -80
+KPX Tcommaaccent colon -40
+KPX Tcommaaccent comma -80
+KPX Tcommaaccent e -60
+KPX Tcommaaccent eacute -60
+KPX Tcommaaccent ecaron -60
+KPX Tcommaaccent ecircumflex -60
+KPX Tcommaaccent edieresis -60
+KPX Tcommaaccent edotaccent -60
+KPX Tcommaaccent egrave -60
+KPX Tcommaaccent emacron -60
+KPX Tcommaaccent eogonek -60
+KPX Tcommaaccent hyphen -120
+KPX Tcommaaccent o -80
+KPX Tcommaaccent oacute -80
+KPX Tcommaaccent ocircumflex -80
+KPX Tcommaaccent odieresis -80
+KPX Tcommaaccent ograve -80
+KPX Tcommaaccent ohungarumlaut -80
+KPX Tcommaaccent omacron -80
+KPX Tcommaaccent oslash -80
+KPX Tcommaaccent otilde -80
+KPX Tcommaaccent period -80
+KPX Tcommaaccent r -80
+KPX Tcommaaccent racute -80
+KPX Tcommaaccent rcommaaccent -80
+KPX Tcommaaccent semicolon -40
+KPX Tcommaaccent u -90
+KPX Tcommaaccent uacute -90
+KPX Tcommaaccent ucircumflex -90
+KPX Tcommaaccent udieresis -90
+KPX Tcommaaccent ugrave -90
+KPX Tcommaaccent uhungarumlaut -90
+KPX Tcommaaccent umacron -90
+KPX Tcommaaccent uogonek -90
+KPX Tcommaaccent uring -90
+KPX Tcommaaccent w -60
+KPX Tcommaaccent y -60
+KPX Tcommaaccent yacute -60
+KPX Tcommaaccent ydieresis -60
+KPX U A -50
+KPX U Aacute -50
+KPX U Abreve -50
+KPX U Acircumflex -50
+KPX U Adieresis -50
+KPX U Agrave -50
+KPX U Amacron -50
+KPX U Aogonek -50
+KPX U Aring -50
+KPX U Atilde -50
+KPX U comma -30
+KPX U period -30
+KPX Uacute A -50
+KPX Uacute Aacute -50
+KPX Uacute Abreve -50
+KPX Uacute Acircumflex -50
+KPX Uacute Adieresis -50
+KPX Uacute Agrave -50
+KPX Uacute Amacron -50
+KPX Uacute Aogonek -50
+KPX Uacute Aring -50
+KPX Uacute Atilde -50
+KPX Uacute comma -30
+KPX Uacute period -30
+KPX Ucircumflex A -50
+KPX Ucircumflex Aacute -50
+KPX Ucircumflex Abreve -50
+KPX Ucircumflex Acircumflex -50
+KPX Ucircumflex Adieresis -50
+KPX Ucircumflex Agrave -50
+KPX Ucircumflex Amacron -50
+KPX Ucircumflex Aogonek -50
+KPX Ucircumflex Aring -50
+KPX Ucircumflex Atilde -50
+KPX Ucircumflex comma -30
+KPX Ucircumflex period -30
+KPX Udieresis A -50
+KPX Udieresis Aacute -50
+KPX Udieresis Abreve -50
+KPX Udieresis Acircumflex -50
+KPX Udieresis Adieresis -50
+KPX Udieresis Agrave -50
+KPX Udieresis Amacron -50
+KPX Udieresis Aogonek -50
+KPX Udieresis Aring -50
+KPX Udieresis Atilde -50
+KPX Udieresis comma -30
+KPX Udieresis period -30
+KPX Ugrave A -50
+KPX Ugrave Aacute -50
+KPX Ugrave Abreve -50
+KPX Ugrave Acircumflex -50
+KPX Ugrave Adieresis -50
+KPX Ugrave Agrave -50
+KPX Ugrave Amacron -50
+KPX Ugrave Aogonek -50
+KPX Ugrave Aring -50
+KPX Ugrave Atilde -50
+KPX Ugrave comma -30
+KPX Ugrave period -30
+KPX Uhungarumlaut A -50
+KPX Uhungarumlaut Aacute -50
+KPX Uhungarumlaut Abreve -50
+KPX Uhungarumlaut Acircumflex -50
+KPX Uhungarumlaut Adieresis -50
+KPX Uhungarumlaut Agrave -50
+KPX Uhungarumlaut Amacron -50
+KPX Uhungarumlaut Aogonek -50
+KPX Uhungarumlaut Aring -50
+KPX Uhungarumlaut Atilde -50
+KPX Uhungarumlaut comma -30
+KPX Uhungarumlaut period -30
+KPX Umacron A -50
+KPX Umacron Aacute -50
+KPX Umacron Abreve -50
+KPX Umacron Acircumflex -50
+KPX Umacron Adieresis -50
+KPX Umacron Agrave -50
+KPX Umacron Amacron -50
+KPX Umacron Aogonek -50
+KPX Umacron Aring -50
+KPX Umacron Atilde -50
+KPX Umacron comma -30
+KPX Umacron period -30
+KPX Uogonek A -50
+KPX Uogonek Aacute -50
+KPX Uogonek Abreve -50
+KPX Uogonek Acircumflex -50
+KPX Uogonek Adieresis -50
+KPX Uogonek Agrave -50
+KPX Uogonek Amacron -50
+KPX Uogonek Aogonek -50
+KPX Uogonek Aring -50
+KPX Uogonek Atilde -50
+KPX Uogonek comma -30
+KPX Uogonek period -30
+KPX Uring A -50
+KPX Uring Aacute -50
+KPX Uring Abreve -50
+KPX Uring Acircumflex -50
+KPX Uring Adieresis -50
+KPX Uring Agrave -50
+KPX Uring Amacron -50
+KPX Uring Aogonek -50
+KPX Uring Aring -50
+KPX Uring Atilde -50
+KPX Uring comma -30
+KPX Uring period -30
+KPX V A -80
+KPX V Aacute -80
+KPX V Abreve -80
+KPX V Acircumflex -80
+KPX V Adieresis -80
+KPX V Agrave -80
+KPX V Amacron -80
+KPX V Aogonek -80
+KPX V Aring -80
+KPX V Atilde -80
+KPX V G -50
+KPX V Gbreve -50
+KPX V Gcommaaccent -50
+KPX V O -50
+KPX V Oacute -50
+KPX V Ocircumflex -50
+KPX V Odieresis -50
+KPX V Ograve -50
+KPX V Ohungarumlaut -50
+KPX V Omacron -50
+KPX V Oslash -50
+KPX V Otilde -50
+KPX V a -60
+KPX V aacute -60
+KPX V abreve -60
+KPX V acircumflex -60
+KPX V adieresis -60
+KPX V agrave -60
+KPX V amacron -60
+KPX V aogonek -60
+KPX V aring -60
+KPX V atilde -60
+KPX V colon -40
+KPX V comma -120
+KPX V e -50
+KPX V eacute -50
+KPX V ecaron -50
+KPX V ecircumflex -50
+KPX V edieresis -50
+KPX V edotaccent -50
+KPX V egrave -50
+KPX V emacron -50
+KPX V eogonek -50
+KPX V hyphen -80
+KPX V o -90
+KPX V oacute -90
+KPX V ocircumflex -90
+KPX V odieresis -90
+KPX V ograve -90
+KPX V ohungarumlaut -90
+KPX V omacron -90
+KPX V oslash -90
+KPX V otilde -90
+KPX V period -120
+KPX V semicolon -40
+KPX V u -60
+KPX V uacute -60
+KPX V ucircumflex -60
+KPX V udieresis -60
+KPX V ugrave -60
+KPX V uhungarumlaut -60
+KPX V umacron -60
+KPX V uogonek -60
+KPX V uring -60
+KPX W A -60
+KPX W Aacute -60
+KPX W Abreve -60
+KPX W Acircumflex -60
+KPX W Adieresis -60
+KPX W Agrave -60
+KPX W Amacron -60
+KPX W Aogonek -60
+KPX W Aring -60
+KPX W Atilde -60
+KPX W O -20
+KPX W Oacute -20
+KPX W Ocircumflex -20
+KPX W Odieresis -20
+KPX W Ograve -20
+KPX W Ohungarumlaut -20
+KPX W Omacron -20
+KPX W Oslash -20
+KPX W Otilde -20
+KPX W a -40
+KPX W aacute -40
+KPX W abreve -40
+KPX W acircumflex -40
+KPX W adieresis -40
+KPX W agrave -40
+KPX W amacron -40
+KPX W aogonek -40
+KPX W aring -40
+KPX W atilde -40
+KPX W colon -10
+KPX W comma -80
+KPX W e -35
+KPX W eacute -35
+KPX W ecaron -35
+KPX W ecircumflex -35
+KPX W edieresis -35
+KPX W edotaccent -35
+KPX W egrave -35
+KPX W emacron -35
+KPX W eogonek -35
+KPX W hyphen -40
+KPX W o -60
+KPX W oacute -60
+KPX W ocircumflex -60
+KPX W odieresis -60
+KPX W ograve -60
+KPX W ohungarumlaut -60
+KPX W omacron -60
+KPX W oslash -60
+KPX W otilde -60
+KPX W period -80
+KPX W semicolon -10
+KPX W u -45
+KPX W uacute -45
+KPX W ucircumflex -45
+KPX W udieresis -45
+KPX W ugrave -45
+KPX W uhungarumlaut -45
+KPX W umacron -45
+KPX W uogonek -45
+KPX W uring -45
+KPX W y -20
+KPX W yacute -20
+KPX W ydieresis -20
+KPX Y A -110
+KPX Y Aacute -110
+KPX Y Abreve -110
+KPX Y Acircumflex -110
+KPX Y Adieresis -110
+KPX Y Agrave -110
+KPX Y Amacron -110
+KPX Y Aogonek -110
+KPX Y Aring -110
+KPX Y Atilde -110
+KPX Y O -70
+KPX Y Oacute -70
+KPX Y Ocircumflex -70
+KPX Y Odieresis -70
+KPX Y Ograve -70
+KPX Y Ohungarumlaut -70
+KPX Y Omacron -70
+KPX Y Oslash -70
+KPX Y Otilde -70
+KPX Y a -90
+KPX Y aacute -90
+KPX Y abreve -90
+KPX Y acircumflex -90
+KPX Y adieresis -90
+KPX Y agrave -90
+KPX Y amacron -90
+KPX Y aogonek -90
+KPX Y aring -90
+KPX Y atilde -90
+KPX Y colon -50
+KPX Y comma -100
+KPX Y e -80
+KPX Y eacute -80
+KPX Y ecaron -80
+KPX Y ecircumflex -80
+KPX Y edieresis -80
+KPX Y edotaccent -80
+KPX Y egrave -80
+KPX Y emacron -80
+KPX Y eogonek -80
+KPX Y o -100
+KPX Y oacute -100
+KPX Y ocircumflex -100
+KPX Y odieresis -100
+KPX Y ograve -100
+KPX Y ohungarumlaut -100
+KPX Y omacron -100
+KPX Y oslash -100
+KPX Y otilde -100
+KPX Y period -100
+KPX Y semicolon -50
+KPX Y u -100
+KPX Y uacute -100
+KPX Y ucircumflex -100
+KPX Y udieresis -100
+KPX Y ugrave -100
+KPX Y uhungarumlaut -100
+KPX Y umacron -100
+KPX Y uogonek -100
+KPX Y uring -100
+KPX Yacute A -110
+KPX Yacute Aacute -110
+KPX Yacute Abreve -110
+KPX Yacute Acircumflex -110
+KPX Yacute Adieresis -110
+KPX Yacute Agrave -110
+KPX Yacute Amacron -110
+KPX Yacute Aogonek -110
+KPX Yacute Aring -110
+KPX Yacute Atilde -110
+KPX Yacute O -70
+KPX Yacute Oacute -70
+KPX Yacute Ocircumflex -70
+KPX Yacute Odieresis -70
+KPX Yacute Ograve -70
+KPX Yacute Ohungarumlaut -70
+KPX Yacute Omacron -70
+KPX Yacute Oslash -70
+KPX Yacute Otilde -70
+KPX Yacute a -90
+KPX Yacute aacute -90
+KPX Yacute abreve -90
+KPX Yacute acircumflex -90
+KPX Yacute adieresis -90
+KPX Yacute agrave -90
+KPX Yacute amacron -90
+KPX Yacute aogonek -90
+KPX Yacute aring -90
+KPX Yacute atilde -90
+KPX Yacute colon -50
+KPX Yacute comma -100
+KPX Yacute e -80
+KPX Yacute eacute -80
+KPX Yacute ecaron -80
+KPX Yacute ecircumflex -80
+KPX Yacute edieresis -80
+KPX Yacute edotaccent -80
+KPX Yacute egrave -80
+KPX Yacute emacron -80
+KPX Yacute eogonek -80
+KPX Yacute o -100
+KPX Yacute oacute -100
+KPX Yacute ocircumflex -100
+KPX Yacute odieresis -100
+KPX Yacute ograve -100
+KPX Yacute ohungarumlaut -100
+KPX Yacute omacron -100
+KPX Yacute oslash -100
+KPX Yacute otilde -100
+KPX Yacute period -100
+KPX Yacute semicolon -50
+KPX Yacute u -100
+KPX Yacute uacute -100
+KPX Yacute ucircumflex -100
+KPX Yacute udieresis -100
+KPX Yacute ugrave -100
+KPX Yacute uhungarumlaut -100
+KPX Yacute umacron -100
+KPX Yacute uogonek -100
+KPX Yacute uring -100
+KPX Ydieresis A -110
+KPX Ydieresis Aacute -110
+KPX Ydieresis Abreve -110
+KPX Ydieresis Acircumflex -110
+KPX Ydieresis Adieresis -110
+KPX Ydieresis Agrave -110
+KPX Ydieresis Amacron -110
+KPX Ydieresis Aogonek -110
+KPX Ydieresis Aring -110
+KPX Ydieresis Atilde -110
+KPX Ydieresis O -70
+KPX Ydieresis Oacute -70
+KPX Ydieresis Ocircumflex -70
+KPX Ydieresis Odieresis -70
+KPX Ydieresis Ograve -70
+KPX Ydieresis Ohungarumlaut -70
+KPX Ydieresis Omacron -70
+KPX Ydieresis Oslash -70
+KPX Ydieresis Otilde -70
+KPX Ydieresis a -90
+KPX Ydieresis aacute -90
+KPX Ydieresis abreve -90
+KPX Ydieresis acircumflex -90
+KPX Ydieresis adieresis -90
+KPX Ydieresis agrave -90
+KPX Ydieresis amacron -90
+KPX Ydieresis aogonek -90
+KPX Ydieresis aring -90
+KPX Ydieresis atilde -90
+KPX Ydieresis colon -50
+KPX Ydieresis comma -100
+KPX Ydieresis e -80
+KPX Ydieresis eacute -80
+KPX Ydieresis ecaron -80
+KPX Ydieresis ecircumflex -80
+KPX Ydieresis edieresis -80
+KPX Ydieresis edotaccent -80
+KPX Ydieresis egrave -80
+KPX Ydieresis emacron -80
+KPX Ydieresis eogonek -80
+KPX Ydieresis o -100
+KPX Ydieresis oacute -100
+KPX Ydieresis ocircumflex -100
+KPX Ydieresis odieresis -100
+KPX Ydieresis ograve -100
+KPX Ydieresis ohungarumlaut -100
+KPX Ydieresis omacron -100
+KPX Ydieresis oslash -100
+KPX Ydieresis otilde -100
+KPX Ydieresis period -100
+KPX Ydieresis semicolon -50
+KPX Ydieresis u -100
+KPX Ydieresis uacute -100
+KPX Ydieresis ucircumflex -100
+KPX Ydieresis udieresis -100
+KPX Ydieresis ugrave -100
+KPX Ydieresis uhungarumlaut -100
+KPX Ydieresis umacron -100
+KPX Ydieresis uogonek -100
+KPX Ydieresis uring -100
+KPX a g -10
+KPX a gbreve -10
+KPX a gcommaaccent -10
+KPX a v -15
+KPX a w -15
+KPX a y -20
+KPX a yacute -20
+KPX a ydieresis -20
+KPX aacute g -10
+KPX aacute gbreve -10
+KPX aacute gcommaaccent -10
+KPX aacute v -15
+KPX aacute w -15
+KPX aacute y -20
+KPX aacute yacute -20
+KPX aacute ydieresis -20
+KPX abreve g -10
+KPX abreve gbreve -10
+KPX abreve gcommaaccent -10
+KPX abreve v -15
+KPX abreve w -15
+KPX abreve y -20
+KPX abreve yacute -20
+KPX abreve ydieresis -20
+KPX acircumflex g -10
+KPX acircumflex gbreve -10
+KPX acircumflex gcommaaccent -10
+KPX acircumflex v -15
+KPX acircumflex w -15
+KPX acircumflex y -20
+KPX acircumflex yacute -20
+KPX acircumflex ydieresis -20
+KPX adieresis g -10
+KPX adieresis gbreve -10
+KPX adieresis gcommaaccent -10
+KPX adieresis v -15
+KPX adieresis w -15
+KPX adieresis y -20
+KPX adieresis yacute -20
+KPX adieresis ydieresis -20
+KPX agrave g -10
+KPX agrave gbreve -10
+KPX agrave gcommaaccent -10
+KPX agrave v -15
+KPX agrave w -15
+KPX agrave y -20
+KPX agrave yacute -20
+KPX agrave ydieresis -20
+KPX amacron g -10
+KPX amacron gbreve -10
+KPX amacron gcommaaccent -10
+KPX amacron v -15
+KPX amacron w -15
+KPX amacron y -20
+KPX amacron yacute -20
+KPX amacron ydieresis -20
+KPX aogonek g -10
+KPX aogonek gbreve -10
+KPX aogonek gcommaaccent -10
+KPX aogonek v -15
+KPX aogonek w -15
+KPX aogonek y -20
+KPX aogonek yacute -20
+KPX aogonek ydieresis -20
+KPX aring g -10
+KPX aring gbreve -10
+KPX aring gcommaaccent -10
+KPX aring v -15
+KPX aring w -15
+KPX aring y -20
+KPX aring yacute -20
+KPX aring ydieresis -20
+KPX atilde g -10
+KPX atilde gbreve -10
+KPX atilde gcommaaccent -10
+KPX atilde v -15
+KPX atilde w -15
+KPX atilde y -20
+KPX atilde yacute -20
+KPX atilde ydieresis -20
+KPX b l -10
+KPX b lacute -10
+KPX b lcommaaccent -10
+KPX b lslash -10
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX b v -20
+KPX b y -20
+KPX b yacute -20
+KPX b ydieresis -20
+KPX c h -10
+KPX c k -20
+KPX c kcommaaccent -20
+KPX c l -20
+KPX c lacute -20
+KPX c lcommaaccent -20
+KPX c lslash -20
+KPX c y -10
+KPX c yacute -10
+KPX c ydieresis -10
+KPX cacute h -10
+KPX cacute k -20
+KPX cacute kcommaaccent -20
+KPX cacute l -20
+KPX cacute lacute -20
+KPX cacute lcommaaccent -20
+KPX cacute lslash -20
+KPX cacute y -10
+KPX cacute yacute -10
+KPX cacute ydieresis -10
+KPX ccaron h -10
+KPX ccaron k -20
+KPX ccaron kcommaaccent -20
+KPX ccaron l -20
+KPX ccaron lacute -20
+KPX ccaron lcommaaccent -20
+KPX ccaron lslash -20
+KPX ccaron y -10
+KPX ccaron yacute -10
+KPX ccaron ydieresis -10
+KPX ccedilla h -10
+KPX ccedilla k -20
+KPX ccedilla kcommaaccent -20
+KPX ccedilla l -20
+KPX ccedilla lacute -20
+KPX ccedilla lcommaaccent -20
+KPX ccedilla lslash -20
+KPX ccedilla y -10
+KPX ccedilla yacute -10
+KPX ccedilla ydieresis -10
+KPX colon space -40
+KPX comma quotedblright -120
+KPX comma quoteright -120
+KPX comma space -40
+KPX d d -10
+KPX d dcroat -10
+KPX d v -15
+KPX d w -15
+KPX d y -15
+KPX d yacute -15
+KPX d ydieresis -15
+KPX dcroat d -10
+KPX dcroat dcroat -10
+KPX dcroat v -15
+KPX dcroat w -15
+KPX dcroat y -15
+KPX dcroat yacute -15
+KPX dcroat ydieresis -15
+KPX e comma 10
+KPX e period 20
+KPX e v -15
+KPX e w -15
+KPX e x -15
+KPX e y -15
+KPX e yacute -15
+KPX e ydieresis -15
+KPX eacute comma 10
+KPX eacute period 20
+KPX eacute v -15
+KPX eacute w -15
+KPX eacute x -15
+KPX eacute y -15
+KPX eacute yacute -15
+KPX eacute ydieresis -15
+KPX ecaron comma 10
+KPX ecaron period 20
+KPX ecaron v -15
+KPX ecaron w -15
+KPX ecaron x -15
+KPX ecaron y -15
+KPX ecaron yacute -15
+KPX ecaron ydieresis -15
+KPX ecircumflex comma 10
+KPX ecircumflex period 20
+KPX ecircumflex v -15
+KPX ecircumflex w -15
+KPX ecircumflex x -15
+KPX ecircumflex y -15
+KPX ecircumflex yacute -15
+KPX ecircumflex ydieresis -15
+KPX edieresis comma 10
+KPX edieresis period 20
+KPX edieresis v -15
+KPX edieresis w -15
+KPX edieresis x -15
+KPX edieresis y -15
+KPX edieresis yacute -15
+KPX edieresis ydieresis -15
+KPX edotaccent comma 10
+KPX edotaccent period 20
+KPX edotaccent v -15
+KPX edotaccent w -15
+KPX edotaccent x -15
+KPX edotaccent y -15
+KPX edotaccent yacute -15
+KPX edotaccent ydieresis -15
+KPX egrave comma 10
+KPX egrave period 20
+KPX egrave v -15
+KPX egrave w -15
+KPX egrave x -15
+KPX egrave y -15
+KPX egrave yacute -15
+KPX egrave ydieresis -15
+KPX emacron comma 10
+KPX emacron period 20
+KPX emacron v -15
+KPX emacron w -15
+KPX emacron x -15
+KPX emacron y -15
+KPX emacron yacute -15
+KPX emacron ydieresis -15
+KPX eogonek comma 10
+KPX eogonek period 20
+KPX eogonek v -15
+KPX eogonek w -15
+KPX eogonek x -15
+KPX eogonek y -15
+KPX eogonek yacute -15
+KPX eogonek ydieresis -15
+KPX f comma -10
+KPX f e -10
+KPX f eacute -10
+KPX f ecaron -10
+KPX f ecircumflex -10
+KPX f edieresis -10
+KPX f edotaccent -10
+KPX f egrave -10
+KPX f emacron -10
+KPX f eogonek -10
+KPX f o -20
+KPX f oacute -20
+KPX f ocircumflex -20
+KPX f odieresis -20
+KPX f ograve -20
+KPX f ohungarumlaut -20
+KPX f omacron -20
+KPX f oslash -20
+KPX f otilde -20
+KPX f period -10
+KPX f quotedblright 30
+KPX f quoteright 30
+KPX g e 10
+KPX g eacute 10
+KPX g ecaron 10
+KPX g ecircumflex 10
+KPX g edieresis 10
+KPX g edotaccent 10
+KPX g egrave 10
+KPX g emacron 10
+KPX g eogonek 10
+KPX g g -10
+KPX g gbreve -10
+KPX g gcommaaccent -10
+KPX gbreve e 10
+KPX gbreve eacute 10
+KPX gbreve ecaron 10
+KPX gbreve ecircumflex 10
+KPX gbreve edieresis 10
+KPX gbreve edotaccent 10
+KPX gbreve egrave 10
+KPX gbreve emacron 10
+KPX gbreve eogonek 10
+KPX gbreve g -10
+KPX gbreve gbreve -10
+KPX gbreve gcommaaccent -10
+KPX gcommaaccent e 10
+KPX gcommaaccent eacute 10
+KPX gcommaaccent ecaron 10
+KPX gcommaaccent ecircumflex 10
+KPX gcommaaccent edieresis 10
+KPX gcommaaccent edotaccent 10
+KPX gcommaaccent egrave 10
+KPX gcommaaccent emacron 10
+KPX gcommaaccent eogonek 10
+KPX gcommaaccent g -10
+KPX gcommaaccent gbreve -10
+KPX gcommaaccent gcommaaccent -10
+KPX h y -20
+KPX h yacute -20
+KPX h ydieresis -20
+KPX k o -15
+KPX k oacute -15
+KPX k ocircumflex -15
+KPX k odieresis -15
+KPX k ograve -15
+KPX k ohungarumlaut -15
+KPX k omacron -15
+KPX k oslash -15
+KPX k otilde -15
+KPX kcommaaccent o -15
+KPX kcommaaccent oacute -15
+KPX kcommaaccent ocircumflex -15
+KPX kcommaaccent odieresis -15
+KPX kcommaaccent ograve -15
+KPX kcommaaccent ohungarumlaut -15
+KPX kcommaaccent omacron -15
+KPX kcommaaccent oslash -15
+KPX kcommaaccent otilde -15
+KPX l w -15
+KPX l y -15
+KPX l yacute -15
+KPX l ydieresis -15
+KPX lacute w -15
+KPX lacute y -15
+KPX lacute yacute -15
+KPX lacute ydieresis -15
+KPX lcommaaccent w -15
+KPX lcommaaccent y -15
+KPX lcommaaccent yacute -15
+KPX lcommaaccent ydieresis -15
+KPX lslash w -15
+KPX lslash y -15
+KPX lslash yacute -15
+KPX lslash ydieresis -15
+KPX m u -20
+KPX m uacute -20
+KPX m ucircumflex -20
+KPX m udieresis -20
+KPX m ugrave -20
+KPX m uhungarumlaut -20
+KPX m umacron -20
+KPX m uogonek -20
+KPX m uring -20
+KPX m y -30
+KPX m yacute -30
+KPX m ydieresis -30
+KPX n u -10
+KPX n uacute -10
+KPX n ucircumflex -10
+KPX n udieresis -10
+KPX n ugrave -10
+KPX n uhungarumlaut -10
+KPX n umacron -10
+KPX n uogonek -10
+KPX n uring -10
+KPX n v -40
+KPX n y -20
+KPX n yacute -20
+KPX n ydieresis -20
+KPX nacute u -10
+KPX nacute uacute -10
+KPX nacute ucircumflex -10
+KPX nacute udieresis -10
+KPX nacute ugrave -10
+KPX nacute uhungarumlaut -10
+KPX nacute umacron -10
+KPX nacute uogonek -10
+KPX nacute uring -10
+KPX nacute v -40
+KPX nacute y -20
+KPX nacute yacute -20
+KPX nacute ydieresis -20
+KPX ncaron u -10
+KPX ncaron uacute -10
+KPX ncaron ucircumflex -10
+KPX ncaron udieresis -10
+KPX ncaron ugrave -10
+KPX ncaron uhungarumlaut -10
+KPX ncaron umacron -10
+KPX ncaron uogonek -10
+KPX ncaron uring -10
+KPX ncaron v -40
+KPX ncaron y -20
+KPX ncaron yacute -20
+KPX ncaron ydieresis -20
+KPX ncommaaccent u -10
+KPX ncommaaccent uacute -10
+KPX ncommaaccent ucircumflex -10
+KPX ncommaaccent udieresis -10
+KPX ncommaaccent ugrave -10
+KPX ncommaaccent uhungarumlaut -10
+KPX ncommaaccent umacron -10
+KPX ncommaaccent uogonek -10
+KPX ncommaaccent uring -10
+KPX ncommaaccent v -40
+KPX ncommaaccent y -20
+KPX ncommaaccent yacute -20
+KPX ncommaaccent ydieresis -20
+KPX ntilde u -10
+KPX ntilde uacute -10
+KPX ntilde ucircumflex -10
+KPX ntilde udieresis -10
+KPX ntilde ugrave -10
+KPX ntilde uhungarumlaut -10
+KPX ntilde umacron -10
+KPX ntilde uogonek -10
+KPX ntilde uring -10
+KPX ntilde v -40
+KPX ntilde y -20
+KPX ntilde yacute -20
+KPX ntilde ydieresis -20
+KPX o v -20
+KPX o w -15
+KPX o x -30
+KPX o y -20
+KPX o yacute -20
+KPX o ydieresis -20
+KPX oacute v -20
+KPX oacute w -15
+KPX oacute x -30
+KPX oacute y -20
+KPX oacute yacute -20
+KPX oacute ydieresis -20
+KPX ocircumflex v -20
+KPX ocircumflex w -15
+KPX ocircumflex x -30
+KPX ocircumflex y -20
+KPX ocircumflex yacute -20
+KPX ocircumflex ydieresis -20
+KPX odieresis v -20
+KPX odieresis w -15
+KPX odieresis x -30
+KPX odieresis y -20
+KPX odieresis yacute -20
+KPX odieresis ydieresis -20
+KPX ograve v -20
+KPX ograve w -15
+KPX ograve x -30
+KPX ograve y -20
+KPX ograve yacute -20
+KPX ograve ydieresis -20
+KPX ohungarumlaut v -20
+KPX ohungarumlaut w -15
+KPX ohungarumlaut x -30
+KPX ohungarumlaut y -20
+KPX ohungarumlaut yacute -20
+KPX ohungarumlaut ydieresis -20
+KPX omacron v -20
+KPX omacron w -15
+KPX omacron x -30
+KPX omacron y -20
+KPX omacron yacute -20
+KPX omacron ydieresis -20
+KPX oslash v -20
+KPX oslash w -15
+KPX oslash x -30
+KPX oslash y -20
+KPX oslash yacute -20
+KPX oslash ydieresis -20
+KPX otilde v -20
+KPX otilde w -15
+KPX otilde x -30
+KPX otilde y -20
+KPX otilde yacute -20
+KPX otilde ydieresis -20
+KPX p y -15
+KPX p yacute -15
+KPX p ydieresis -15
+KPX period quotedblright -120
+KPX period quoteright -120
+KPX period space -40
+KPX quotedblright space -80
+KPX quoteleft quoteleft -46
+KPX quoteright d -80
+KPX quoteright dcroat -80
+KPX quoteright l -20
+KPX quoteright lacute -20
+KPX quoteright lcommaaccent -20
+KPX quoteright lslash -20
+KPX quoteright quoteright -46
+KPX quoteright r -40
+KPX quoteright racute -40
+KPX quoteright rcaron -40
+KPX quoteright rcommaaccent -40
+KPX quoteright s -60
+KPX quoteright sacute -60
+KPX quoteright scaron -60
+KPX quoteright scedilla -60
+KPX quoteright scommaaccent -60
+KPX quoteright space -80
+KPX quoteright v -20
+KPX r c -20
+KPX r cacute -20
+KPX r ccaron -20
+KPX r ccedilla -20
+KPX r comma -60
+KPX r d -20
+KPX r dcroat -20
+KPX r g -15
+KPX r gbreve -15
+KPX r gcommaaccent -15
+KPX r hyphen -20
+KPX r o -20
+KPX r oacute -20
+KPX r ocircumflex -20
+KPX r odieresis -20
+KPX r ograve -20
+KPX r ohungarumlaut -20
+KPX r omacron -20
+KPX r oslash -20
+KPX r otilde -20
+KPX r period -60
+KPX r q -20
+KPX r s -15
+KPX r sacute -15
+KPX r scaron -15
+KPX r scedilla -15
+KPX r scommaaccent -15
+KPX r t 20
+KPX r tcommaaccent 20
+KPX r v 10
+KPX r y 10
+KPX r yacute 10
+KPX r ydieresis 10
+KPX racute c -20
+KPX racute cacute -20
+KPX racute ccaron -20
+KPX racute ccedilla -20
+KPX racute comma -60
+KPX racute d -20
+KPX racute dcroat -20
+KPX racute g -15
+KPX racute gbreve -15
+KPX racute gcommaaccent -15
+KPX racute hyphen -20
+KPX racute o -20
+KPX racute oacute -20
+KPX racute ocircumflex -20
+KPX racute odieresis -20
+KPX racute ograve -20
+KPX racute ohungarumlaut -20
+KPX racute omacron -20
+KPX racute oslash -20
+KPX racute otilde -20
+KPX racute period -60
+KPX racute q -20
+KPX racute s -15
+KPX racute sacute -15
+KPX racute scaron -15
+KPX racute scedilla -15
+KPX racute scommaaccent -15
+KPX racute t 20
+KPX racute tcommaaccent 20
+KPX racute v 10
+KPX racute y 10
+KPX racute yacute 10
+KPX racute ydieresis 10
+KPX rcaron c -20
+KPX rcaron cacute -20
+KPX rcaron ccaron -20
+KPX rcaron ccedilla -20
+KPX rcaron comma -60
+KPX rcaron d -20
+KPX rcaron dcroat -20
+KPX rcaron g -15
+KPX rcaron gbreve -15
+KPX rcaron gcommaaccent -15
+KPX rcaron hyphen -20
+KPX rcaron o -20
+KPX rcaron oacute -20
+KPX rcaron ocircumflex -20
+KPX rcaron odieresis -20
+KPX rcaron ograve -20
+KPX rcaron ohungarumlaut -20
+KPX rcaron omacron -20
+KPX rcaron oslash -20
+KPX rcaron otilde -20
+KPX rcaron period -60
+KPX rcaron q -20
+KPX rcaron s -15
+KPX rcaron sacute -15
+KPX rcaron scaron -15
+KPX rcaron scedilla -15
+KPX rcaron scommaaccent -15
+KPX rcaron t 20
+KPX rcaron tcommaaccent 20
+KPX rcaron v 10
+KPX rcaron y 10
+KPX rcaron yacute 10
+KPX rcaron ydieresis 10
+KPX rcommaaccent c -20
+KPX rcommaaccent cacute -20
+KPX rcommaaccent ccaron -20
+KPX rcommaaccent ccedilla -20
+KPX rcommaaccent comma -60
+KPX rcommaaccent d -20
+KPX rcommaaccent dcroat -20
+KPX rcommaaccent g -15
+KPX rcommaaccent gbreve -15
+KPX rcommaaccent gcommaaccent -15
+KPX rcommaaccent hyphen -20
+KPX rcommaaccent o -20
+KPX rcommaaccent oacute -20
+KPX rcommaaccent ocircumflex -20
+KPX rcommaaccent odieresis -20
+KPX rcommaaccent ograve -20
+KPX rcommaaccent ohungarumlaut -20
+KPX rcommaaccent omacron -20
+KPX rcommaaccent oslash -20
+KPX rcommaaccent otilde -20
+KPX rcommaaccent period -60
+KPX rcommaaccent q -20
+KPX rcommaaccent s -15
+KPX rcommaaccent sacute -15
+KPX rcommaaccent scaron -15
+KPX rcommaaccent scedilla -15
+KPX rcommaaccent scommaaccent -15
+KPX rcommaaccent t 20
+KPX rcommaaccent tcommaaccent 20
+KPX rcommaaccent v 10
+KPX rcommaaccent y 10
+KPX rcommaaccent yacute 10
+KPX rcommaaccent ydieresis 10
+KPX s w -15
+KPX sacute w -15
+KPX scaron w -15
+KPX scedilla w -15
+KPX scommaaccent w -15
+KPX semicolon space -40
+KPX space T -100
+KPX space Tcaron -100
+KPX space Tcommaaccent -100
+KPX space V -80
+KPX space W -80
+KPX space Y -120
+KPX space Yacute -120
+KPX space Ydieresis -120
+KPX space quotedblleft -80
+KPX space quoteleft -60
+KPX v a -20
+KPX v aacute -20
+KPX v abreve -20
+KPX v acircumflex -20
+KPX v adieresis -20
+KPX v agrave -20
+KPX v amacron -20
+KPX v aogonek -20
+KPX v aring -20
+KPX v atilde -20
+KPX v comma -80
+KPX v o -30
+KPX v oacute -30
+KPX v ocircumflex -30
+KPX v odieresis -30
+KPX v ograve -30
+KPX v ohungarumlaut -30
+KPX v omacron -30
+KPX v oslash -30
+KPX v otilde -30
+KPX v period -80
+KPX w comma -40
+KPX w o -20
+KPX w oacute -20
+KPX w ocircumflex -20
+KPX w odieresis -20
+KPX w ograve -20
+KPX w ohungarumlaut -20
+KPX w omacron -20
+KPX w oslash -20
+KPX w otilde -20
+KPX w period -40
+KPX x e -10
+KPX x eacute -10
+KPX x ecaron -10
+KPX x ecircumflex -10
+KPX x edieresis -10
+KPX x edotaccent -10
+KPX x egrave -10
+KPX x emacron -10
+KPX x eogonek -10
+KPX y a -30
+KPX y aacute -30
+KPX y abreve -30
+KPX y acircumflex -30
+KPX y adieresis -30
+KPX y agrave -30
+KPX y amacron -30
+KPX y aogonek -30
+KPX y aring -30
+KPX y atilde -30
+KPX y comma -80
+KPX y e -10
+KPX y eacute -10
+KPX y ecaron -10
+KPX y ecircumflex -10
+KPX y edieresis -10
+KPX y edotaccent -10
+KPX y egrave -10
+KPX y emacron -10
+KPX y eogonek -10
+KPX y o -25
+KPX y oacute -25
+KPX y ocircumflex -25
+KPX y odieresis -25
+KPX y ograve -25
+KPX y ohungarumlaut -25
+KPX y omacron -25
+KPX y oslash -25
+KPX y otilde -25
+KPX y period -80
+KPX yacute a -30
+KPX yacute aacute -30
+KPX yacute abreve -30
+KPX yacute acircumflex -30
+KPX yacute adieresis -30
+KPX yacute agrave -30
+KPX yacute amacron -30
+KPX yacute aogonek -30
+KPX yacute aring -30
+KPX yacute atilde -30
+KPX yacute comma -80
+KPX yacute e -10
+KPX yacute eacute -10
+KPX yacute ecaron -10
+KPX yacute ecircumflex -10
+KPX yacute edieresis -10
+KPX yacute edotaccent -10
+KPX yacute egrave -10
+KPX yacute emacron -10
+KPX yacute eogonek -10
+KPX yacute o -25
+KPX yacute oacute -25
+KPX yacute ocircumflex -25
+KPX yacute odieresis -25
+KPX yacute ograve -25
+KPX yacute ohungarumlaut -25
+KPX yacute omacron -25
+KPX yacute oslash -25
+KPX yacute otilde -25
+KPX yacute period -80
+KPX ydieresis a -30
+KPX ydieresis aacute -30
+KPX ydieresis abreve -30
+KPX ydieresis acircumflex -30
+KPX ydieresis adieresis -30
+KPX ydieresis agrave -30
+KPX ydieresis amacron -30
+KPX ydieresis aogonek -30
+KPX ydieresis aring -30
+KPX ydieresis atilde -30
+KPX ydieresis comma -80
+KPX ydieresis e -10
+KPX ydieresis eacute -10
+KPX ydieresis ecaron -10
+KPX ydieresis ecircumflex -10
+KPX ydieresis edieresis -10
+KPX ydieresis edotaccent -10
+KPX ydieresis egrave -10
+KPX ydieresis emacron -10
+KPX ydieresis eogonek -10
+KPX ydieresis o -25
+KPX ydieresis oacute -25
+KPX ydieresis ocircumflex -25
+KPX ydieresis odieresis -25
+KPX ydieresis ograve -25
+KPX ydieresis ohungarumlaut -25
+KPX ydieresis omacron -25
+KPX ydieresis oslash -25
+KPX ydieresis otilde -25
+KPX ydieresis period -80
+KPX z e 10
+KPX z eacute 10
+KPX z ecaron 10
+KPX z ecircumflex 10
+KPX z edieresis 10
+KPX z edotaccent 10
+KPX z egrave 10
+KPX z emacron 10
+KPX z eogonek 10
+KPX zacute e 10
+KPX zacute eacute 10
+KPX zacute ecaron 10
+KPX zacute ecircumflex 10
+KPX zacute edieresis 10
+KPX zacute edotaccent 10
+KPX zacute egrave 10
+KPX zacute emacron 10
+KPX zacute eogonek 10
+KPX zcaron e 10
+KPX zcaron eacute 10
+KPX zcaron ecaron 10
+KPX zcaron ecircumflex 10
+KPX zcaron edieresis 10
+KPX zcaron edotaccent 10
+KPX zcaron egrave 10
+KPX zcaron emacron 10
+KPX zcaron eogonek 10
+KPX zdotaccent e 10
+KPX zdotaccent eacute 10
+KPX zdotaccent ecaron 10
+KPX zdotaccent ecircumflex 10
+KPX zdotaccent edieresis 10
+KPX zdotaccent edotaccent 10
+KPX zdotaccent egrave 10
+KPX zdotaccent emacron 10
+KPX zdotaccent eogonek 10
+EndKernPairs
+EndKernData
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica-BoldOblique.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica-BoldOblique.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica-BoldOblique.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica-BoldOblique.afm 2004-05-26 16:06:20.000000000 +0000
@@ -0,0 +1,2827 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu May 1 12:45:12 1997
+Comment UniqueID 43053
+Comment VMusage 14482 68586
+FontName Helvetica-BoldOblique
+FullName Helvetica Bold Oblique
+FamilyName Helvetica
+Weight Bold
+ItalicAngle -12
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -174 -228 1114 962
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 532
+Ascender 718
+Descender -207
+StdHW 118
+StdVW 140
+StartCharMetrics 315
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 94 0 397 718 ;
+C 34 ; WX 474 ; N quotedbl ; B 193 447 529 718 ;
+C 35 ; WX 556 ; N numbersign ; B 60 0 644 698 ;
+C 36 ; WX 556 ; N dollar ; B 67 -115 622 775 ;
+C 37 ; WX 889 ; N percent ; B 136 -19 901 710 ;
+C 38 ; WX 722 ; N ampersand ; B 89 -19 732 718 ;
+C 39 ; WX 278 ; N quoteright ; B 167 445 362 718 ;
+C 40 ; WX 333 ; N parenleft ; B 76 -208 470 734 ;
+C 41 ; WX 333 ; N parenright ; B -25 -208 369 734 ;
+C 42 ; WX 389 ; N asterisk ; B 146 387 481 718 ;
+C 43 ; WX 584 ; N plus ; B 82 0 610 506 ;
+C 44 ; WX 278 ; N comma ; B 28 -168 245 146 ;
+C 45 ; WX 333 ; N hyphen ; B 73 215 379 345 ;
+C 46 ; WX 278 ; N period ; B 64 0 245 146 ;
+C 47 ; WX 278 ; N slash ; B -37 -19 468 737 ;
+C 48 ; WX 556 ; N zero ; B 86 -19 617 710 ;
+C 49 ; WX 556 ; N one ; B 173 0 529 710 ;
+C 50 ; WX 556 ; N two ; B 26 0 619 710 ;
+C 51 ; WX 556 ; N three ; B 65 -19 608 710 ;
+C 52 ; WX 556 ; N four ; B 60 0 598 710 ;
+C 53 ; WX 556 ; N five ; B 64 -19 636 698 ;
+C 54 ; WX 556 ; N six ; B 85 -19 619 710 ;
+C 55 ; WX 556 ; N seven ; B 125 0 676 698 ;
+C 56 ; WX 556 ; N eight ; B 69 -19 616 710 ;
+C 57 ; WX 556 ; N nine ; B 78 -19 615 710 ;
+C 58 ; WX 333 ; N colon ; B 92 0 351 512 ;
+C 59 ; WX 333 ; N semicolon ; B 56 -168 351 512 ;
+C 60 ; WX 584 ; N less ; B 82 -8 655 514 ;
+C 61 ; WX 584 ; N equal ; B 58 87 633 419 ;
+C 62 ; WX 584 ; N greater ; B 36 -8 609 514 ;
+C 63 ; WX 611 ; N question ; B 165 0 671 727 ;
+C 64 ; WX 975 ; N at ; B 186 -19 954 737 ;
+C 65 ; WX 722 ; N A ; B 20 0 702 718 ;
+C 66 ; WX 722 ; N B ; B 76 0 764 718 ;
+C 67 ; WX 722 ; N C ; B 107 -19 789 737 ;
+C 68 ; WX 722 ; N D ; B 76 0 777 718 ;
+C 69 ; WX 667 ; N E ; B 76 0 757 718 ;
+C 70 ; WX 611 ; N F ; B 76 0 740 718 ;
+C 71 ; WX 778 ; N G ; B 108 -19 817 737 ;
+C 72 ; WX 722 ; N H ; B 71 0 804 718 ;
+C 73 ; WX 278 ; N I ; B 64 0 367 718 ;
+C 74 ; WX 556 ; N J ; B 60 -18 637 718 ;
+C 75 ; WX 722 ; N K ; B 87 0 858 718 ;
+C 76 ; WX 611 ; N L ; B 76 0 611 718 ;
+C 77 ; WX 833 ; N M ; B 69 0 918 718 ;
+C 78 ; WX 722 ; N N ; B 69 0 807 718 ;
+C 79 ; WX 778 ; N O ; B 107 -19 823 737 ;
+C 80 ; WX 667 ; N P ; B 76 0 738 718 ;
+C 81 ; WX 778 ; N Q ; B 107 -52 823 737 ;
+C 82 ; WX 722 ; N R ; B 76 0 778 718 ;
+C 83 ; WX 667 ; N S ; B 81 -19 718 737 ;
+C 84 ; WX 611 ; N T ; B 140 0 751 718 ;
+C 85 ; WX 722 ; N U ; B 116 -19 804 718 ;
+C 86 ; WX 667 ; N V ; B 172 0 801 718 ;
+C 87 ; WX 944 ; N W ; B 169 0 1082 718 ;
+C 88 ; WX 667 ; N X ; B 14 0 791 718 ;
+C 89 ; WX 667 ; N Y ; B 168 0 806 718 ;
+C 90 ; WX 611 ; N Z ; B 25 0 737 718 ;
+C 91 ; WX 333 ; N bracketleft ; B 21 -196 462 722 ;
+C 92 ; WX 278 ; N backslash ; B 124 -19 307 737 ;
+C 93 ; WX 333 ; N bracketright ; B -18 -196 423 722 ;
+C 94 ; WX 584 ; N asciicircum ; B 131 323 591 698 ;
+C 95 ; WX 556 ; N underscore ; B -27 -125 540 -75 ;
+C 96 ; WX 278 ; N quoteleft ; B 165 454 361 727 ;
+C 97 ; WX 556 ; N a ; B 55 -14 583 546 ;
+C 98 ; WX 611 ; N b ; B 61 -14 645 718 ;
+C 99 ; WX 556 ; N c ; B 79 -14 599 546 ;
+C 100 ; WX 611 ; N d ; B 82 -14 704 718 ;
+C 101 ; WX 556 ; N e ; B 70 -14 593 546 ;
+C 102 ; WX 333 ; N f ; B 87 0 469 727 ; L i fi ; L l fl ;
+C 103 ; WX 611 ; N g ; B 38 -217 666 546 ;
+C 104 ; WX 611 ; N h ; B 65 0 629 718 ;
+C 105 ; WX 278 ; N i ; B 69 0 363 725 ;
+C 106 ; WX 278 ; N j ; B -42 -214 363 725 ;
+C 107 ; WX 556 ; N k ; B 69 0 670 718 ;
+C 108 ; WX 278 ; N l ; B 69 0 362 718 ;
+C 109 ; WX 889 ; N m ; B 64 0 909 546 ;
+C 110 ; WX 611 ; N n ; B 65 0 629 546 ;
+C 111 ; WX 611 ; N o ; B 82 -14 643 546 ;
+C 112 ; WX 611 ; N p ; B 18 -207 645 546 ;
+C 113 ; WX 611 ; N q ; B 80 -207 665 546 ;
+C 114 ; WX 389 ; N r ; B 64 0 489 546 ;
+C 115 ; WX 556 ; N s ; B 63 -14 584 546 ;
+C 116 ; WX 333 ; N t ; B 100 -6 422 676 ;
+C 117 ; WX 611 ; N u ; B 98 -14 658 532 ;
+C 118 ; WX 556 ; N v ; B 126 0 656 532 ;
+C 119 ; WX 778 ; N w ; B 123 0 882 532 ;
+C 120 ; WX 556 ; N x ; B 15 0 648 532 ;
+C 121 ; WX 556 ; N y ; B 42 -214 652 532 ;
+C 122 ; WX 500 ; N z ; B 20 0 583 532 ;
+C 123 ; WX 389 ; N braceleft ; B 94 -196 518 722 ;
+C 124 ; WX 280 ; N bar ; B 36 -225 361 775 ;
+C 125 ; WX 389 ; N braceright ; B -18 -196 407 722 ;
+C 126 ; WX 584 ; N asciitilde ; B 115 163 577 343 ;
+C 161 ; WX 333 ; N exclamdown ; B 50 -186 353 532 ;
+C 162 ; WX 556 ; N cent ; B 79 -118 599 628 ;
+C 163 ; WX 556 ; N sterling ; B 50 -16 635 718 ;
+C 164 ; WX 167 ; N fraction ; B -174 -19 487 710 ;
+C 165 ; WX 556 ; N yen ; B 60 0 713 698 ;
+C 166 ; WX 556 ; N florin ; B -50 -210 669 737 ;
+C 167 ; WX 556 ; N section ; B 61 -184 598 727 ;
+C 168 ; WX 556 ; N currency ; B 27 76 680 636 ;
+C 169 ; WX 238 ; N quotesingle ; B 165 447 321 718 ;
+C 170 ; WX 500 ; N quotedblleft ; B 160 454 588 727 ;
+C 171 ; WX 556 ; N guillemotleft ; B 135 76 571 484 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 130 76 353 484 ;
+C 173 ; WX 333 ; N guilsinglright ; B 99 76 322 484 ;
+C 174 ; WX 611 ; N fi ; B 87 0 696 727 ;
+C 175 ; WX 611 ; N fl ; B 87 0 695 727 ;
+C 177 ; WX 556 ; N endash ; B 48 227 627 333 ;
+C 178 ; WX 556 ; N dagger ; B 118 -171 626 718 ;
+C 179 ; WX 556 ; N daggerdbl ; B 46 -171 628 718 ;
+C 180 ; WX 278 ; N periodcentered ; B 110 172 276 334 ;
+C 182 ; WX 556 ; N paragraph ; B 98 -191 688 700 ;
+C 183 ; WX 350 ; N bullet ; B 83 194 420 524 ;
+C 184 ; WX 278 ; N quotesinglbase ; B 41 -146 236 127 ;
+C 185 ; WX 500 ; N quotedblbase ; B 36 -146 463 127 ;
+C 186 ; WX 500 ; N quotedblright ; B 162 445 589 718 ;
+C 187 ; WX 556 ; N guillemotright ; B 104 76 540 484 ;
+C 188 ; WX 1000 ; N ellipsis ; B 92 0 939 146 ;
+C 189 ; WX 1000 ; N perthousand ; B 76 -19 1038 710 ;
+C 191 ; WX 611 ; N questiondown ; B 53 -195 559 532 ;
+C 193 ; WX 333 ; N grave ; B 136 604 353 750 ;
+C 194 ; WX 333 ; N acute ; B 236 604 515 750 ;
+C 195 ; WX 333 ; N circumflex ; B 118 604 471 750 ;
+C 196 ; WX 333 ; N tilde ; B 113 610 507 737 ;
+C 197 ; WX 333 ; N macron ; B 122 604 483 678 ;
+C 198 ; WX 333 ; N breve ; B 156 604 494 750 ;
+C 199 ; WX 333 ; N dotaccent ; B 235 614 385 729 ;
+C 200 ; WX 333 ; N dieresis ; B 137 614 482 729 ;
+C 202 ; WX 333 ; N ring ; B 200 568 420 776 ;
+C 203 ; WX 333 ; N cedilla ; B -37 -228 220 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 137 604 645 750 ;
+C 206 ; WX 333 ; N ogonek ; B 41 -228 264 0 ;
+C 207 ; WX 333 ; N caron ; B 149 604 502 750 ;
+C 208 ; WX 1000 ; N emdash ; B 48 227 1071 333 ;
+C 225 ; WX 1000 ; N AE ; B 5 0 1100 718 ;
+C 227 ; WX 370 ; N ordfeminine ; B 125 401 465 737 ;
+C 232 ; WX 611 ; N Lslash ; B 34 0 611 718 ;
+C 233 ; WX 778 ; N Oslash ; B 35 -27 894 745 ;
+C 234 ; WX 1000 ; N OE ; B 99 -19 1114 737 ;
+C 235 ; WX 365 ; N ordmasculine ; B 123 401 485 737 ;
+C 241 ; WX 889 ; N ae ; B 56 -14 923 546 ;
+C 245 ; WX 278 ; N dotlessi ; B 69 0 322 532 ;
+C 248 ; WX 278 ; N lslash ; B 40 0 407 718 ;
+C 249 ; WX 611 ; N oslash ; B 22 -29 701 560 ;
+C 250 ; WX 944 ; N oe ; B 82 -14 977 546 ;
+C 251 ; WX 611 ; N germandbls ; B 69 -14 657 731 ;
+C -1 ; WX 278 ; N Idieresis ; B 64 0 494 915 ;
+C -1 ; WX 556 ; N eacute ; B 70 -14 627 750 ;
+C -1 ; WX 556 ; N abreve ; B 55 -14 606 750 ;
+C -1 ; WX 611 ; N uhungarumlaut ; B 98 -14 784 750 ;
+C -1 ; WX 556 ; N ecaron ; B 70 -14 614 750 ;
+C -1 ; WX 667 ; N Ydieresis ; B 168 0 806 915 ;
+C -1 ; WX 584 ; N divide ; B 82 -42 610 548 ;
+C -1 ; WX 667 ; N Yacute ; B 168 0 806 936 ;
+C -1 ; WX 722 ; N Acircumflex ; B 20 0 706 936 ;
+C -1 ; WX 556 ; N aacute ; B 55 -14 627 750 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 116 -19 804 936 ;
+C -1 ; WX 556 ; N yacute ; B 42 -214 652 750 ;
+C -1 ; WX 556 ; N scommaaccent ; B 63 -228 584 546 ;
+C -1 ; WX 556 ; N ecircumflex ; B 70 -14 593 750 ;
+C -1 ; WX 722 ; N Uring ; B 116 -19 804 962 ;
+C -1 ; WX 722 ; N Udieresis ; B 116 -19 804 915 ;
+C -1 ; WX 556 ; N aogonek ; B 55 -224 583 546 ;
+C -1 ; WX 722 ; N Uacute ; B 116 -19 804 936 ;
+C -1 ; WX 611 ; N uogonek ; B 98 -228 658 532 ;
+C -1 ; WX 667 ; N Edieresis ; B 76 0 757 915 ;
+C -1 ; WX 722 ; N Dcroat ; B 62 0 777 718 ;
+C -1 ; WX 250 ; N commaaccent ; B 16 -228 188 -50 ;
+C -1 ; WX 737 ; N copyright ; B 56 -19 835 737 ;
+C -1 ; WX 667 ; N Emacron ; B 76 0 757 864 ;
+C -1 ; WX 556 ; N ccaron ; B 79 -14 614 750 ;
+C -1 ; WX 556 ; N aring ; B 55 -14 583 776 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B 69 -228 807 718 ;
+C -1 ; WX 278 ; N lacute ; B 69 0 528 936 ;
+C -1 ; WX 556 ; N agrave ; B 55 -14 583 750 ;
+C -1 ; WX 611 ; N Tcommaaccent ; B 140 -228 751 718 ;
+C -1 ; WX 722 ; N Cacute ; B 107 -19 789 936 ;
+C -1 ; WX 556 ; N atilde ; B 55 -14 619 737 ;
+C -1 ; WX 667 ; N Edotaccent ; B 76 0 757 915 ;
+C -1 ; WX 556 ; N scaron ; B 63 -14 614 750 ;
+C -1 ; WX 556 ; N scedilla ; B 63 -228 584 546 ;
+C -1 ; WX 278 ; N iacute ; B 69 0 488 750 ;
+C -1 ; WX 494 ; N lozenge ; B 90 0 564 745 ;
+C -1 ; WX 722 ; N Rcaron ; B 76 0 778 936 ;
+C -1 ; WX 778 ; N Gcommaaccent ; B 108 -228 817 737 ;
+C -1 ; WX 611 ; N ucircumflex ; B 98 -14 658 750 ;
+C -1 ; WX 556 ; N acircumflex ; B 55 -14 583 750 ;
+C -1 ; WX 722 ; N Amacron ; B 20 0 718 864 ;
+C -1 ; WX 389 ; N rcaron ; B 64 0 530 750 ;
+C -1 ; WX 556 ; N ccedilla ; B 79 -228 599 546 ;
+C -1 ; WX 611 ; N Zdotaccent ; B 25 0 737 915 ;
+C -1 ; WX 667 ; N Thorn ; B 76 0 716 718 ;
+C -1 ; WX 778 ; N Omacron ; B 107 -19 823 864 ;
+C -1 ; WX 722 ; N Racute ; B 76 0 778 936 ;
+C -1 ; WX 667 ; N Sacute ; B 81 -19 722 936 ;
+C -1 ; WX 743 ; N dcaron ; B 82 -14 903 718 ;
+C -1 ; WX 722 ; N Umacron ; B 116 -19 804 864 ;
+C -1 ; WX 611 ; N uring ; B 98 -14 658 776 ;
+C -1 ; WX 333 ; N threesuperior ; B 91 271 441 710 ;
+C -1 ; WX 778 ; N Ograve ; B 107 -19 823 936 ;
+C -1 ; WX 722 ; N Agrave ; B 20 0 702 936 ;
+C -1 ; WX 722 ; N Abreve ; B 20 0 729 936 ;
+C -1 ; WX 584 ; N multiply ; B 57 1 635 505 ;
+C -1 ; WX 611 ; N uacute ; B 98 -14 658 750 ;
+C -1 ; WX 611 ; N Tcaron ; B 140 0 751 936 ;
+C -1 ; WX 494 ; N partialdiff ; B 43 -21 585 750 ;
+C -1 ; WX 556 ; N ydieresis ; B 42 -214 652 729 ;
+C -1 ; WX 722 ; N Nacute ; B 69 0 807 936 ;
+C -1 ; WX 278 ; N icircumflex ; B 69 0 444 750 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 76 0 757 936 ;
+C -1 ; WX 556 ; N adieresis ; B 55 -14 594 729 ;
+C -1 ; WX 556 ; N edieresis ; B 70 -14 594 729 ;
+C -1 ; WX 556 ; N cacute ; B 79 -14 627 750 ;
+C -1 ; WX 611 ; N nacute ; B 65 0 654 750 ;
+C -1 ; WX 611 ; N umacron ; B 98 -14 658 678 ;
+C -1 ; WX 722 ; N Ncaron ; B 69 0 807 936 ;
+C -1 ; WX 278 ; N Iacute ; B 64 0 528 936 ;
+C -1 ; WX 584 ; N plusminus ; B 40 0 625 506 ;
+C -1 ; WX 280 ; N brokenbar ; B 52 -150 345 700 ;
+C -1 ; WX 737 ; N registered ; B 55 -19 834 737 ;
+C -1 ; WX 778 ; N Gbreve ; B 108 -19 817 936 ;
+C -1 ; WX 278 ; N Idotaccent ; B 64 0 397 915 ;
+C -1 ; WX 600 ; N summation ; B 14 -10 670 706 ;
+C -1 ; WX 667 ; N Egrave ; B 76 0 757 936 ;
+C -1 ; WX 389 ; N racute ; B 64 0 543 750 ;
+C -1 ; WX 611 ; N omacron ; B 82 -14 643 678 ;
+C -1 ; WX 611 ; N Zacute ; B 25 0 737 936 ;
+C -1 ; WX 611 ; N Zcaron ; B 25 0 737 936 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 629 704 ;
+C -1 ; WX 722 ; N Eth ; B 62 0 777 718 ;
+C -1 ; WX 722 ; N Ccedilla ; B 107 -228 789 737 ;
+C -1 ; WX 278 ; N lcommaaccent ; B 30 -228 362 718 ;
+C -1 ; WX 389 ; N tcaron ; B 100 -6 608 878 ;
+C -1 ; WX 556 ; N eogonek ; B 70 -228 593 546 ;
+C -1 ; WX 722 ; N Uogonek ; B 116 -228 804 718 ;
+C -1 ; WX 722 ; N Aacute ; B 20 0 750 936 ;
+C -1 ; WX 722 ; N Adieresis ; B 20 0 716 915 ;
+C -1 ; WX 556 ; N egrave ; B 70 -14 593 750 ;
+C -1 ; WX 500 ; N zacute ; B 20 0 599 750 ;
+C -1 ; WX 278 ; N iogonek ; B -14 -224 363 725 ;
+C -1 ; WX 778 ; N Oacute ; B 107 -19 823 936 ;
+C -1 ; WX 611 ; N oacute ; B 82 -14 654 750 ;
+C -1 ; WX 556 ; N amacron ; B 55 -14 595 678 ;
+C -1 ; WX 556 ; N sacute ; B 63 -14 627 750 ;
+C -1 ; WX 278 ; N idieresis ; B 69 0 455 729 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 107 -19 823 936 ;
+C -1 ; WX 722 ; N Ugrave ; B 116 -19 804 936 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 611 ; N thorn ; B 18 -208 645 718 ;
+C -1 ; WX 333 ; N twosuperior ; B 69 283 449 710 ;
+C -1 ; WX 778 ; N Odieresis ; B 107 -19 823 915 ;
+C -1 ; WX 611 ; N mu ; B 22 -207 658 532 ;
+C -1 ; WX 278 ; N igrave ; B 69 0 326 750 ;
+C -1 ; WX 611 ; N ohungarumlaut ; B 82 -14 784 750 ;
+C -1 ; WX 667 ; N Eogonek ; B 76 -224 757 718 ;
+C -1 ; WX 611 ; N dcroat ; B 82 -14 789 718 ;
+C -1 ; WX 834 ; N threequarters ; B 99 -19 839 710 ;
+C -1 ; WX 667 ; N Scedilla ; B 81 -228 718 737 ;
+C -1 ; WX 400 ; N lcaron ; B 69 0 561 718 ;
+C -1 ; WX 722 ; N Kcommaaccent ; B 87 -228 858 718 ;
+C -1 ; WX 611 ; N Lacute ; B 76 0 611 936 ;
+C -1 ; WX 1000 ; N trademark ; B 179 306 1109 718 ;
+C -1 ; WX 556 ; N edotaccent ; B 70 -14 593 729 ;
+C -1 ; WX 278 ; N Igrave ; B 64 0 367 936 ;
+C -1 ; WX 278 ; N Imacron ; B 64 0 496 864 ;
+C -1 ; WX 611 ; N Lcaron ; B 76 0 643 718 ;
+C -1 ; WX 834 ; N onehalf ; B 132 -19 858 710 ;
+C -1 ; WX 549 ; N lessequal ; B 29 0 676 704 ;
+C -1 ; WX 611 ; N ocircumflex ; B 82 -14 643 750 ;
+C -1 ; WX 611 ; N ntilde ; B 65 0 646 737 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 116 -19 880 936 ;
+C -1 ; WX 667 ; N Eacute ; B 76 0 757 936 ;
+C -1 ; WX 556 ; N emacron ; B 70 -14 595 678 ;
+C -1 ; WX 611 ; N gbreve ; B 38 -217 666 750 ;
+C -1 ; WX 834 ; N onequarter ; B 132 -19 806 710 ;
+C -1 ; WX 667 ; N Scaron ; B 81 -19 718 936 ;
+C -1 ; WX 667 ; N Scommaaccent ; B 81 -228 718 737 ;
+C -1 ; WX 778 ; N Ohungarumlaut ; B 107 -19 908 936 ;
+C -1 ; WX 400 ; N degree ; B 175 426 467 712 ;
+C -1 ; WX 611 ; N ograve ; B 82 -14 643 750 ;
+C -1 ; WX 722 ; N Ccaron ; B 107 -19 789 936 ;
+C -1 ; WX 611 ; N ugrave ; B 98 -14 658 750 ;
+C -1 ; WX 549 ; N radical ; B 112 -46 689 850 ;
+C -1 ; WX 722 ; N Dcaron ; B 76 0 777 936 ;
+C -1 ; WX 389 ; N rcommaaccent ; B 26 -228 489 546 ;
+C -1 ; WX 722 ; N Ntilde ; B 69 0 807 923 ;
+C -1 ; WX 611 ; N otilde ; B 82 -14 646 737 ;
+C -1 ; WX 722 ; N Rcommaaccent ; B 76 -228 778 718 ;
+C -1 ; WX 611 ; N Lcommaaccent ; B 76 -228 611 718 ;
+C -1 ; WX 722 ; N Atilde ; B 20 0 741 923 ;
+C -1 ; WX 722 ; N Aogonek ; B 20 -224 702 718 ;
+C -1 ; WX 722 ; N Aring ; B 20 0 702 962 ;
+C -1 ; WX 778 ; N Otilde ; B 107 -19 823 923 ;
+C -1 ; WX 500 ; N zdotaccent ; B 20 0 583 729 ;
+C -1 ; WX 667 ; N Ecaron ; B 76 0 757 936 ;
+C -1 ; WX 278 ; N Iogonek ; B -41 -228 367 718 ;
+C -1 ; WX 556 ; N kcommaaccent ; B 69 -228 670 718 ;
+C -1 ; WX 584 ; N minus ; B 82 197 610 309 ;
+C -1 ; WX 278 ; N Icircumflex ; B 64 0 484 936 ;
+C -1 ; WX 611 ; N ncaron ; B 65 0 641 750 ;
+C -1 ; WX 333 ; N tcommaaccent ; B 58 -228 422 676 ;
+C -1 ; WX 584 ; N logicalnot ; B 105 108 633 419 ;
+C -1 ; WX 611 ; N odieresis ; B 82 -14 643 729 ;
+C -1 ; WX 611 ; N udieresis ; B 98 -14 658 729 ;
+C -1 ; WX 549 ; N notequal ; B 32 -49 630 570 ;
+C -1 ; WX 611 ; N gcommaaccent ; B 38 -217 666 850 ;
+C -1 ; WX 611 ; N eth ; B 82 -14 670 737 ;
+C -1 ; WX 500 ; N zcaron ; B 20 0 586 750 ;
+C -1 ; WX 611 ; N ncommaaccent ; B 65 -228 629 546 ;
+C -1 ; WX 333 ; N onesuperior ; B 148 283 388 710 ;
+C -1 ; WX 278 ; N imacron ; B 69 0 429 678 ;
+C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2481
+KPX A C -40
+KPX A Cacute -40
+KPX A Ccaron -40
+KPX A Ccedilla -40
+KPX A G -50
+KPX A Gbreve -50
+KPX A Gcommaaccent -50
+KPX A O -40
+KPX A Oacute -40
+KPX A Ocircumflex -40
+KPX A Odieresis -40
+KPX A Ograve -40
+KPX A Ohungarumlaut -40
+KPX A Omacron -40
+KPX A Oslash -40
+KPX A Otilde -40
+KPX A Q -40
+KPX A T -90
+KPX A Tcaron -90
+KPX A Tcommaaccent -90
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -80
+KPX A W -60
+KPX A Y -110
+KPX A Yacute -110
+KPX A Ydieresis -110
+KPX A u -30
+KPX A uacute -30
+KPX A ucircumflex -30
+KPX A udieresis -30
+KPX A ugrave -30
+KPX A uhungarumlaut -30
+KPX A umacron -30
+KPX A uogonek -30
+KPX A uring -30
+KPX A v -40
+KPX A w -30
+KPX A y -30
+KPX A yacute -30
+KPX A ydieresis -30
+KPX Aacute C -40
+KPX Aacute Cacute -40
+KPX Aacute Ccaron -40
+KPX Aacute Ccedilla -40
+KPX Aacute G -50
+KPX Aacute Gbreve -50
+KPX Aacute Gcommaaccent -50
+KPX Aacute O -40
+KPX Aacute Oacute -40
+KPX Aacute Ocircumflex -40
+KPX Aacute Odieresis -40
+KPX Aacute Ograve -40
+KPX Aacute Ohungarumlaut -40
+KPX Aacute Omacron -40
+KPX Aacute Oslash -40
+KPX Aacute Otilde -40
+KPX Aacute Q -40
+KPX Aacute T -90
+KPX Aacute Tcaron -90
+KPX Aacute Tcommaaccent -90
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -80
+KPX Aacute W -60
+KPX Aacute Y -110
+KPX Aacute Yacute -110
+KPX Aacute Ydieresis -110
+KPX Aacute u -30
+KPX Aacute uacute -30
+KPX Aacute ucircumflex -30
+KPX Aacute udieresis -30
+KPX Aacute ugrave -30
+KPX Aacute uhungarumlaut -30
+KPX Aacute umacron -30
+KPX Aacute uogonek -30
+KPX Aacute uring -30
+KPX Aacute v -40
+KPX Aacute w -30
+KPX Aacute y -30
+KPX Aacute yacute -30
+KPX Aacute ydieresis -30
+KPX Abreve C -40
+KPX Abreve Cacute -40
+KPX Abreve Ccaron -40
+KPX Abreve Ccedilla -40
+KPX Abreve G -50
+KPX Abreve Gbreve -50
+KPX Abreve Gcommaaccent -50
+KPX Abreve O -40
+KPX Abreve Oacute -40
+KPX Abreve Ocircumflex -40
+KPX Abreve Odieresis -40
+KPX Abreve Ograve -40
+KPX Abreve Ohungarumlaut -40
+KPX Abreve Omacron -40
+KPX Abreve Oslash -40
+KPX Abreve Otilde -40
+KPX Abreve Q -40
+KPX Abreve T -90
+KPX Abreve Tcaron -90
+KPX Abreve Tcommaaccent -90
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -80
+KPX Abreve W -60
+KPX Abreve Y -110
+KPX Abreve Yacute -110
+KPX Abreve Ydieresis -110
+KPX Abreve u -30
+KPX Abreve uacute -30
+KPX Abreve ucircumflex -30
+KPX Abreve udieresis -30
+KPX Abreve ugrave -30
+KPX Abreve uhungarumlaut -30
+KPX Abreve umacron -30
+KPX Abreve uogonek -30
+KPX Abreve uring -30
+KPX Abreve v -40
+KPX Abreve w -30
+KPX Abreve y -30
+KPX Abreve yacute -30
+KPX Abreve ydieresis -30
+KPX Acircumflex C -40
+KPX Acircumflex Cacute -40
+KPX Acircumflex Ccaron -40
+KPX Acircumflex Ccedilla -40
+KPX Acircumflex G -50
+KPX Acircumflex Gbreve -50
+KPX Acircumflex Gcommaaccent -50
+KPX Acircumflex O -40
+KPX Acircumflex Oacute -40
+KPX Acircumflex Ocircumflex -40
+KPX Acircumflex Odieresis -40
+KPX Acircumflex Ograve -40
+KPX Acircumflex Ohungarumlaut -40
+KPX Acircumflex Omacron -40
+KPX Acircumflex Oslash -40
+KPX Acircumflex Otilde -40
+KPX Acircumflex Q -40
+KPX Acircumflex T -90
+KPX Acircumflex Tcaron -90
+KPX Acircumflex Tcommaaccent -90
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -80
+KPX Acircumflex W -60
+KPX Acircumflex Y -110
+KPX Acircumflex Yacute -110
+KPX Acircumflex Ydieresis -110
+KPX Acircumflex u -30
+KPX Acircumflex uacute -30
+KPX Acircumflex ucircumflex -30
+KPX Acircumflex udieresis -30
+KPX Acircumflex ugrave -30
+KPX Acircumflex uhungarumlaut -30
+KPX Acircumflex umacron -30
+KPX Acircumflex uogonek -30
+KPX Acircumflex uring -30
+KPX Acircumflex v -40
+KPX Acircumflex w -30
+KPX Acircumflex y -30
+KPX Acircumflex yacute -30
+KPX Acircumflex ydieresis -30
+KPX Adieresis C -40
+KPX Adieresis Cacute -40
+KPX Adieresis Ccaron -40
+KPX Adieresis Ccedilla -40
+KPX Adieresis G -50
+KPX Adieresis Gbreve -50
+KPX Adieresis Gcommaaccent -50
+KPX Adieresis O -40
+KPX Adieresis Oacute -40
+KPX Adieresis Ocircumflex -40
+KPX Adieresis Odieresis -40
+KPX Adieresis Ograve -40
+KPX Adieresis Ohungarumlaut -40
+KPX Adieresis Omacron -40
+KPX Adieresis Oslash -40
+KPX Adieresis Otilde -40
+KPX Adieresis Q -40
+KPX Adieresis T -90
+KPX Adieresis Tcaron -90
+KPX Adieresis Tcommaaccent -90
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -80
+KPX Adieresis W -60
+KPX Adieresis Y -110
+KPX Adieresis Yacute -110
+KPX Adieresis Ydieresis -110
+KPX Adieresis u -30
+KPX Adieresis uacute -30
+KPX Adieresis ucircumflex -30
+KPX Adieresis udieresis -30
+KPX Adieresis ugrave -30
+KPX Adieresis uhungarumlaut -30
+KPX Adieresis umacron -30
+KPX Adieresis uogonek -30
+KPX Adieresis uring -30
+KPX Adieresis v -40
+KPX Adieresis w -30
+KPX Adieresis y -30
+KPX Adieresis yacute -30
+KPX Adieresis ydieresis -30
+KPX Agrave C -40
+KPX Agrave Cacute -40
+KPX Agrave Ccaron -40
+KPX Agrave Ccedilla -40
+KPX Agrave G -50
+KPX Agrave Gbreve -50
+KPX Agrave Gcommaaccent -50
+KPX Agrave O -40
+KPX Agrave Oacute -40
+KPX Agrave Ocircumflex -40
+KPX Agrave Odieresis -40
+KPX Agrave Ograve -40
+KPX Agrave Ohungarumlaut -40
+KPX Agrave Omacron -40
+KPX Agrave Oslash -40
+KPX Agrave Otilde -40
+KPX Agrave Q -40
+KPX Agrave T -90
+KPX Agrave Tcaron -90
+KPX Agrave Tcommaaccent -90
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -80
+KPX Agrave W -60
+KPX Agrave Y -110
+KPX Agrave Yacute -110
+KPX Agrave Ydieresis -110
+KPX Agrave u -30
+KPX Agrave uacute -30
+KPX Agrave ucircumflex -30
+KPX Agrave udieresis -30
+KPX Agrave ugrave -30
+KPX Agrave uhungarumlaut -30
+KPX Agrave umacron -30
+KPX Agrave uogonek -30
+KPX Agrave uring -30
+KPX Agrave v -40
+KPX Agrave w -30
+KPX Agrave y -30
+KPX Agrave yacute -30
+KPX Agrave ydieresis -30
+KPX Amacron C -40
+KPX Amacron Cacute -40
+KPX Amacron Ccaron -40
+KPX Amacron Ccedilla -40
+KPX Amacron G -50
+KPX Amacron Gbreve -50
+KPX Amacron Gcommaaccent -50
+KPX Amacron O -40
+KPX Amacron Oacute -40
+KPX Amacron Ocircumflex -40
+KPX Amacron Odieresis -40
+KPX Amacron Ograve -40
+KPX Amacron Ohungarumlaut -40
+KPX Amacron Omacron -40
+KPX Amacron Oslash -40
+KPX Amacron Otilde -40
+KPX Amacron Q -40
+KPX Amacron T -90
+KPX Amacron Tcaron -90
+KPX Amacron Tcommaaccent -90
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -80
+KPX Amacron W -60
+KPX Amacron Y -110
+KPX Amacron Yacute -110
+KPX Amacron Ydieresis -110
+KPX Amacron u -30
+KPX Amacron uacute -30
+KPX Amacron ucircumflex -30
+KPX Amacron udieresis -30
+KPX Amacron ugrave -30
+KPX Amacron uhungarumlaut -30
+KPX Amacron umacron -30
+KPX Amacron uogonek -30
+KPX Amacron uring -30
+KPX Amacron v -40
+KPX Amacron w -30
+KPX Amacron y -30
+KPX Amacron yacute -30
+KPX Amacron ydieresis -30
+KPX Aogonek C -40
+KPX Aogonek Cacute -40
+KPX Aogonek Ccaron -40
+KPX Aogonek Ccedilla -40
+KPX Aogonek G -50
+KPX Aogonek Gbreve -50
+KPX Aogonek Gcommaaccent -50
+KPX Aogonek O -40
+KPX Aogonek Oacute -40
+KPX Aogonek Ocircumflex -40
+KPX Aogonek Odieresis -40
+KPX Aogonek Ograve -40
+KPX Aogonek Ohungarumlaut -40
+KPX Aogonek Omacron -40
+KPX Aogonek Oslash -40
+KPX Aogonek Otilde -40
+KPX Aogonek Q -40
+KPX Aogonek T -90
+KPX Aogonek Tcaron -90
+KPX Aogonek Tcommaaccent -90
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -80
+KPX Aogonek W -60
+KPX Aogonek Y -110
+KPX Aogonek Yacute -110
+KPX Aogonek Ydieresis -110
+KPX Aogonek u -30
+KPX Aogonek uacute -30
+KPX Aogonek ucircumflex -30
+KPX Aogonek udieresis -30
+KPX Aogonek ugrave -30
+KPX Aogonek uhungarumlaut -30
+KPX Aogonek umacron -30
+KPX Aogonek uogonek -30
+KPX Aogonek uring -30
+KPX Aogonek v -40
+KPX Aogonek w -30
+KPX Aogonek y -30
+KPX Aogonek yacute -30
+KPX Aogonek ydieresis -30
+KPX Aring C -40
+KPX Aring Cacute -40
+KPX Aring Ccaron -40
+KPX Aring Ccedilla -40
+KPX Aring G -50
+KPX Aring Gbreve -50
+KPX Aring Gcommaaccent -50
+KPX Aring O -40
+KPX Aring Oacute -40
+KPX Aring Ocircumflex -40
+KPX Aring Odieresis -40
+KPX Aring Ograve -40
+KPX Aring Ohungarumlaut -40
+KPX Aring Omacron -40
+KPX Aring Oslash -40
+KPX Aring Otilde -40
+KPX Aring Q -40
+KPX Aring T -90
+KPX Aring Tcaron -90
+KPX Aring Tcommaaccent -90
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -80
+KPX Aring W -60
+KPX Aring Y -110
+KPX Aring Yacute -110
+KPX Aring Ydieresis -110
+KPX Aring u -30
+KPX Aring uacute -30
+KPX Aring ucircumflex -30
+KPX Aring udieresis -30
+KPX Aring ugrave -30
+KPX Aring uhungarumlaut -30
+KPX Aring umacron -30
+KPX Aring uogonek -30
+KPX Aring uring -30
+KPX Aring v -40
+KPX Aring w -30
+KPX Aring y -30
+KPX Aring yacute -30
+KPX Aring ydieresis -30
+KPX Atilde C -40
+KPX Atilde Cacute -40
+KPX Atilde Ccaron -40
+KPX Atilde Ccedilla -40
+KPX Atilde G -50
+KPX Atilde Gbreve -50
+KPX Atilde Gcommaaccent -50
+KPX Atilde O -40
+KPX Atilde Oacute -40
+KPX Atilde Ocircumflex -40
+KPX Atilde Odieresis -40
+KPX Atilde Ograve -40
+KPX Atilde Ohungarumlaut -40
+KPX Atilde Omacron -40
+KPX Atilde Oslash -40
+KPX Atilde Otilde -40
+KPX Atilde Q -40
+KPX Atilde T -90
+KPX Atilde Tcaron -90
+KPX Atilde Tcommaaccent -90
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -80
+KPX Atilde W -60
+KPX Atilde Y -110
+KPX Atilde Yacute -110
+KPX Atilde Ydieresis -110
+KPX Atilde u -30
+KPX Atilde uacute -30
+KPX Atilde ucircumflex -30
+KPX Atilde udieresis -30
+KPX Atilde ugrave -30
+KPX Atilde uhungarumlaut -30
+KPX Atilde umacron -30
+KPX Atilde uogonek -30
+KPX Atilde uring -30
+KPX Atilde v -40
+KPX Atilde w -30
+KPX Atilde y -30
+KPX Atilde yacute -30
+KPX Atilde ydieresis -30
+KPX B A -30
+KPX B Aacute -30
+KPX B Abreve -30
+KPX B Acircumflex -30
+KPX B Adieresis -30
+KPX B Agrave -30
+KPX B Amacron -30
+KPX B Aogonek -30
+KPX B Aring -30
+KPX B Atilde -30
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX D A -40
+KPX D Aacute -40
+KPX D Abreve -40
+KPX D Acircumflex -40
+KPX D Adieresis -40
+KPX D Agrave -40
+KPX D Amacron -40
+KPX D Aogonek -40
+KPX D Aring -40
+KPX D Atilde -40
+KPX D V -40
+KPX D W -40
+KPX D Y -70
+KPX D Yacute -70
+KPX D Ydieresis -70
+KPX D comma -30
+KPX D period -30
+KPX Dcaron A -40
+KPX Dcaron Aacute -40
+KPX Dcaron Abreve -40
+KPX Dcaron Acircumflex -40
+KPX Dcaron Adieresis -40
+KPX Dcaron Agrave -40
+KPX Dcaron Amacron -40
+KPX Dcaron Aogonek -40
+KPX Dcaron Aring -40
+KPX Dcaron Atilde -40
+KPX Dcaron V -40
+KPX Dcaron W -40
+KPX Dcaron Y -70
+KPX Dcaron Yacute -70
+KPX Dcaron Ydieresis -70
+KPX Dcaron comma -30
+KPX Dcaron period -30
+KPX Dcroat A -40
+KPX Dcroat Aacute -40
+KPX Dcroat Abreve -40
+KPX Dcroat Acircumflex -40
+KPX Dcroat Adieresis -40
+KPX Dcroat Agrave -40
+KPX Dcroat Amacron -40
+KPX Dcroat Aogonek -40
+KPX Dcroat Aring -40
+KPX Dcroat Atilde -40
+KPX Dcroat V -40
+KPX Dcroat W -40
+KPX Dcroat Y -70
+KPX Dcroat Yacute -70
+KPX Dcroat Ydieresis -70
+KPX Dcroat comma -30
+KPX Dcroat period -30
+KPX F A -80
+KPX F Aacute -80
+KPX F Abreve -80
+KPX F Acircumflex -80
+KPX F Adieresis -80
+KPX F Agrave -80
+KPX F Amacron -80
+KPX F Aogonek -80
+KPX F Aring -80
+KPX F Atilde -80
+KPX F a -20
+KPX F aacute -20
+KPX F abreve -20
+KPX F acircumflex -20
+KPX F adieresis -20
+KPX F agrave -20
+KPX F amacron -20
+KPX F aogonek -20
+KPX F aring -20
+KPX F atilde -20
+KPX F comma -100
+KPX F period -100
+KPX J A -20
+KPX J Aacute -20
+KPX J Abreve -20
+KPX J Acircumflex -20
+KPX J Adieresis -20
+KPX J Agrave -20
+KPX J Amacron -20
+KPX J Aogonek -20
+KPX J Aring -20
+KPX J Atilde -20
+KPX J comma -20
+KPX J period -20
+KPX J u -20
+KPX J uacute -20
+KPX J ucircumflex -20
+KPX J udieresis -20
+KPX J ugrave -20
+KPX J uhungarumlaut -20
+KPX J umacron -20
+KPX J uogonek -20
+KPX J uring -20
+KPX K O -30
+KPX K Oacute -30
+KPX K Ocircumflex -30
+KPX K Odieresis -30
+KPX K Ograve -30
+KPX K Ohungarumlaut -30
+KPX K Omacron -30
+KPX K Oslash -30
+KPX K Otilde -30
+KPX K e -15
+KPX K eacute -15
+KPX K ecaron -15
+KPX K ecircumflex -15
+KPX K edieresis -15
+KPX K edotaccent -15
+KPX K egrave -15
+KPX K emacron -15
+KPX K eogonek -15
+KPX K o -35
+KPX K oacute -35
+KPX K ocircumflex -35
+KPX K odieresis -35
+KPX K ograve -35
+KPX K ohungarumlaut -35
+KPX K omacron -35
+KPX K oslash -35
+KPX K otilde -35
+KPX K u -30
+KPX K uacute -30
+KPX K ucircumflex -30
+KPX K udieresis -30
+KPX K ugrave -30
+KPX K uhungarumlaut -30
+KPX K umacron -30
+KPX K uogonek -30
+KPX K uring -30
+KPX K y -40
+KPX K yacute -40
+KPX K ydieresis -40
+KPX Kcommaaccent O -30
+KPX Kcommaaccent Oacute -30
+KPX Kcommaaccent Ocircumflex -30
+KPX Kcommaaccent Odieresis -30
+KPX Kcommaaccent Ograve -30
+KPX Kcommaaccent Ohungarumlaut -30
+KPX Kcommaaccent Omacron -30
+KPX Kcommaaccent Oslash -30
+KPX Kcommaaccent Otilde -30
+KPX Kcommaaccent e -15
+KPX Kcommaaccent eacute -15
+KPX Kcommaaccent ecaron -15
+KPX Kcommaaccent ecircumflex -15
+KPX Kcommaaccent edieresis -15
+KPX Kcommaaccent edotaccent -15
+KPX Kcommaaccent egrave -15
+KPX Kcommaaccent emacron -15
+KPX Kcommaaccent eogonek -15
+KPX Kcommaaccent o -35
+KPX Kcommaaccent oacute -35
+KPX Kcommaaccent ocircumflex -35
+KPX Kcommaaccent odieresis -35
+KPX Kcommaaccent ograve -35
+KPX Kcommaaccent ohungarumlaut -35
+KPX Kcommaaccent omacron -35
+KPX Kcommaaccent oslash -35
+KPX Kcommaaccent otilde -35
+KPX Kcommaaccent u -30
+KPX Kcommaaccent uacute -30
+KPX Kcommaaccent ucircumflex -30
+KPX Kcommaaccent udieresis -30
+KPX Kcommaaccent ugrave -30
+KPX Kcommaaccent uhungarumlaut -30
+KPX Kcommaaccent umacron -30
+KPX Kcommaaccent uogonek -30
+KPX Kcommaaccent uring -30
+KPX Kcommaaccent y -40
+KPX Kcommaaccent yacute -40
+KPX Kcommaaccent ydieresis -40
+KPX L T -90
+KPX L Tcaron -90
+KPX L Tcommaaccent -90
+KPX L V -110
+KPX L W -80
+KPX L Y -120
+KPX L Yacute -120
+KPX L Ydieresis -120
+KPX L quotedblright -140
+KPX L quoteright -140
+KPX L y -30
+KPX L yacute -30
+KPX L ydieresis -30
+KPX Lacute T -90
+KPX Lacute Tcaron -90
+KPX Lacute Tcommaaccent -90
+KPX Lacute V -110
+KPX Lacute W -80
+KPX Lacute Y -120
+KPX Lacute Yacute -120
+KPX Lacute Ydieresis -120
+KPX Lacute quotedblright -140
+KPX Lacute quoteright -140
+KPX Lacute y -30
+KPX Lacute yacute -30
+KPX Lacute ydieresis -30
+KPX Lcommaaccent T -90
+KPX Lcommaaccent Tcaron -90
+KPX Lcommaaccent Tcommaaccent -90
+KPX Lcommaaccent V -110
+KPX Lcommaaccent W -80
+KPX Lcommaaccent Y -120
+KPX Lcommaaccent Yacute -120
+KPX Lcommaaccent Ydieresis -120
+KPX Lcommaaccent quotedblright -140
+KPX Lcommaaccent quoteright -140
+KPX Lcommaaccent y -30
+KPX Lcommaaccent yacute -30
+KPX Lcommaaccent ydieresis -30
+KPX Lslash T -90
+KPX Lslash Tcaron -90
+KPX Lslash Tcommaaccent -90
+KPX Lslash V -110
+KPX Lslash W -80
+KPX Lslash Y -120
+KPX Lslash Yacute -120
+KPX Lslash Ydieresis -120
+KPX Lslash quotedblright -140
+KPX Lslash quoteright -140
+KPX Lslash y -30
+KPX Lslash yacute -30
+KPX Lslash ydieresis -30
+KPX O A -50
+KPX O Aacute -50
+KPX O Abreve -50
+KPX O Acircumflex -50
+KPX O Adieresis -50
+KPX O Agrave -50
+KPX O Amacron -50
+KPX O Aogonek -50
+KPX O Aring -50
+KPX O Atilde -50
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -50
+KPX O X -50
+KPX O Y -70
+KPX O Yacute -70
+KPX O Ydieresis -70
+KPX O comma -40
+KPX O period -40
+KPX Oacute A -50
+KPX Oacute Aacute -50
+KPX Oacute Abreve -50
+KPX Oacute Acircumflex -50
+KPX Oacute Adieresis -50
+KPX Oacute Agrave -50
+KPX Oacute Amacron -50
+KPX Oacute Aogonek -50
+KPX Oacute Aring -50
+KPX Oacute Atilde -50
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -50
+KPX Oacute X -50
+KPX Oacute Y -70
+KPX Oacute Yacute -70
+KPX Oacute Ydieresis -70
+KPX Oacute comma -40
+KPX Oacute period -40
+KPX Ocircumflex A -50
+KPX Ocircumflex Aacute -50
+KPX Ocircumflex Abreve -50
+KPX Ocircumflex Acircumflex -50
+KPX Ocircumflex Adieresis -50
+KPX Ocircumflex Agrave -50
+KPX Ocircumflex Amacron -50
+KPX Ocircumflex Aogonek -50
+KPX Ocircumflex Aring -50
+KPX Ocircumflex Atilde -50
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -50
+KPX Ocircumflex X -50
+KPX Ocircumflex Y -70
+KPX Ocircumflex Yacute -70
+KPX Ocircumflex Ydieresis -70
+KPX Ocircumflex comma -40
+KPX Ocircumflex period -40
+KPX Odieresis A -50
+KPX Odieresis Aacute -50
+KPX Odieresis Abreve -50
+KPX Odieresis Acircumflex -50
+KPX Odieresis Adieresis -50
+KPX Odieresis Agrave -50
+KPX Odieresis Amacron -50
+KPX Odieresis Aogonek -50
+KPX Odieresis Aring -50
+KPX Odieresis Atilde -50
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -50
+KPX Odieresis X -50
+KPX Odieresis Y -70
+KPX Odieresis Yacute -70
+KPX Odieresis Ydieresis -70
+KPX Odieresis comma -40
+KPX Odieresis period -40
+KPX Ograve A -50
+KPX Ograve Aacute -50
+KPX Ograve Abreve -50
+KPX Ograve Acircumflex -50
+KPX Ograve Adieresis -50
+KPX Ograve Agrave -50
+KPX Ograve Amacron -50
+KPX Ograve Aogonek -50
+KPX Ograve Aring -50
+KPX Ograve Atilde -50
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -50
+KPX Ograve X -50
+KPX Ograve Y -70
+KPX Ograve Yacute -70
+KPX Ograve Ydieresis -70
+KPX Ograve comma -40
+KPX Ograve period -40
+KPX Ohungarumlaut A -50
+KPX Ohungarumlaut Aacute -50
+KPX Ohungarumlaut Abreve -50
+KPX Ohungarumlaut Acircumflex -50
+KPX Ohungarumlaut Adieresis -50
+KPX Ohungarumlaut Agrave -50
+KPX Ohungarumlaut Amacron -50
+KPX Ohungarumlaut Aogonek -50
+KPX Ohungarumlaut Aring -50
+KPX Ohungarumlaut Atilde -50
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -50
+KPX Ohungarumlaut X -50
+KPX Ohungarumlaut Y -70
+KPX Ohungarumlaut Yacute -70
+KPX Ohungarumlaut Ydieresis -70
+KPX Ohungarumlaut comma -40
+KPX Ohungarumlaut period -40
+KPX Omacron A -50
+KPX Omacron Aacute -50
+KPX Omacron Abreve -50
+KPX Omacron Acircumflex -50
+KPX Omacron Adieresis -50
+KPX Omacron Agrave -50
+KPX Omacron Amacron -50
+KPX Omacron Aogonek -50
+KPX Omacron Aring -50
+KPX Omacron Atilde -50
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -50
+KPX Omacron X -50
+KPX Omacron Y -70
+KPX Omacron Yacute -70
+KPX Omacron Ydieresis -70
+KPX Omacron comma -40
+KPX Omacron period -40
+KPX Oslash A -50
+KPX Oslash Aacute -50
+KPX Oslash Abreve -50
+KPX Oslash Acircumflex -50
+KPX Oslash Adieresis -50
+KPX Oslash Agrave -50
+KPX Oslash Amacron -50
+KPX Oslash Aogonek -50
+KPX Oslash Aring -50
+KPX Oslash Atilde -50
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -50
+KPX Oslash X -50
+KPX Oslash Y -70
+KPX Oslash Yacute -70
+KPX Oslash Ydieresis -70
+KPX Oslash comma -40
+KPX Oslash period -40
+KPX Otilde A -50
+KPX Otilde Aacute -50
+KPX Otilde Abreve -50
+KPX Otilde Acircumflex -50
+KPX Otilde Adieresis -50
+KPX Otilde Agrave -50
+KPX Otilde Amacron -50
+KPX Otilde Aogonek -50
+KPX Otilde Aring -50
+KPX Otilde Atilde -50
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -50
+KPX Otilde X -50
+KPX Otilde Y -70
+KPX Otilde Yacute -70
+KPX Otilde Ydieresis -70
+KPX Otilde comma -40
+KPX Otilde period -40
+KPX P A -100
+KPX P Aacute -100
+KPX P Abreve -100
+KPX P Acircumflex -100
+KPX P Adieresis -100
+KPX P Agrave -100
+KPX P Amacron -100
+KPX P Aogonek -100
+KPX P Aring -100
+KPX P Atilde -100
+KPX P a -30
+KPX P aacute -30
+KPX P abreve -30
+KPX P acircumflex -30
+KPX P adieresis -30
+KPX P agrave -30
+KPX P amacron -30
+KPX P aogonek -30
+KPX P aring -30
+KPX P atilde -30
+KPX P comma -120
+KPX P e -30
+KPX P eacute -30
+KPX P ecaron -30
+KPX P ecircumflex -30
+KPX P edieresis -30
+KPX P edotaccent -30
+KPX P egrave -30
+KPX P emacron -30
+KPX P eogonek -30
+KPX P o -40
+KPX P oacute -40
+KPX P ocircumflex -40
+KPX P odieresis -40
+KPX P ograve -40
+KPX P ohungarumlaut -40
+KPX P omacron -40
+KPX P oslash -40
+KPX P otilde -40
+KPX P period -120
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX Q comma 20
+KPX Q period 20
+KPX R O -20
+KPX R Oacute -20
+KPX R Ocircumflex -20
+KPX R Odieresis -20
+KPX R Ograve -20
+KPX R Ohungarumlaut -20
+KPX R Omacron -20
+KPX R Oslash -20
+KPX R Otilde -20
+KPX R T -20
+KPX R Tcaron -20
+KPX R Tcommaaccent -20
+KPX R U -20
+KPX R Uacute -20
+KPX R Ucircumflex -20
+KPX R Udieresis -20
+KPX R Ugrave -20
+KPX R Uhungarumlaut -20
+KPX R Umacron -20
+KPX R Uogonek -20
+KPX R Uring -20
+KPX R V -50
+KPX R W -40
+KPX R Y -50
+KPX R Yacute -50
+KPX R Ydieresis -50
+KPX Racute O -20
+KPX Racute Oacute -20
+KPX Racute Ocircumflex -20
+KPX Racute Odieresis -20
+KPX Racute Ograve -20
+KPX Racute Ohungarumlaut -20
+KPX Racute Omacron -20
+KPX Racute Oslash -20
+KPX Racute Otilde -20
+KPX Racute T -20
+KPX Racute Tcaron -20
+KPX Racute Tcommaaccent -20
+KPX Racute U -20
+KPX Racute Uacute -20
+KPX Racute Ucircumflex -20
+KPX Racute Udieresis -20
+KPX Racute Ugrave -20
+KPX Racute Uhungarumlaut -20
+KPX Racute Umacron -20
+KPX Racute Uogonek -20
+KPX Racute Uring -20
+KPX Racute V -50
+KPX Racute W -40
+KPX Racute Y -50
+KPX Racute Yacute -50
+KPX Racute Ydieresis -50
+KPX Rcaron O -20
+KPX Rcaron Oacute -20
+KPX Rcaron Ocircumflex -20
+KPX Rcaron Odieresis -20
+KPX Rcaron Ograve -20
+KPX Rcaron Ohungarumlaut -20
+KPX Rcaron Omacron -20
+KPX Rcaron Oslash -20
+KPX Rcaron Otilde -20
+KPX Rcaron T -20
+KPX Rcaron Tcaron -20
+KPX Rcaron Tcommaaccent -20
+KPX Rcaron U -20
+KPX Rcaron Uacute -20
+KPX Rcaron Ucircumflex -20
+KPX Rcaron Udieresis -20
+KPX Rcaron Ugrave -20
+KPX Rcaron Uhungarumlaut -20
+KPX Rcaron Umacron -20
+KPX Rcaron Uogonek -20
+KPX Rcaron Uring -20
+KPX Rcaron V -50
+KPX Rcaron W -40
+KPX Rcaron Y -50
+KPX Rcaron Yacute -50
+KPX Rcaron Ydieresis -50
+KPX Rcommaaccent O -20
+KPX Rcommaaccent Oacute -20
+KPX Rcommaaccent Ocircumflex -20
+KPX Rcommaaccent Odieresis -20
+KPX Rcommaaccent Ograve -20
+KPX Rcommaaccent Ohungarumlaut -20
+KPX Rcommaaccent Omacron -20
+KPX Rcommaaccent Oslash -20
+KPX Rcommaaccent Otilde -20
+KPX Rcommaaccent T -20
+KPX Rcommaaccent Tcaron -20
+KPX Rcommaaccent Tcommaaccent -20
+KPX Rcommaaccent U -20
+KPX Rcommaaccent Uacute -20
+KPX Rcommaaccent Ucircumflex -20
+KPX Rcommaaccent Udieresis -20
+KPX Rcommaaccent Ugrave -20
+KPX Rcommaaccent Uhungarumlaut -20
+KPX Rcommaaccent Umacron -20
+KPX Rcommaaccent Uogonek -20
+KPX Rcommaaccent Uring -20
+KPX Rcommaaccent V -50
+KPX Rcommaaccent W -40
+KPX Rcommaaccent Y -50
+KPX Rcommaaccent Yacute -50
+KPX Rcommaaccent Ydieresis -50
+KPX T A -90
+KPX T Aacute -90
+KPX T Abreve -90
+KPX T Acircumflex -90
+KPX T Adieresis -90
+KPX T Agrave -90
+KPX T Amacron -90
+KPX T Aogonek -90
+KPX T Aring -90
+KPX T Atilde -90
+KPX T O -40
+KPX T Oacute -40
+KPX T Ocircumflex -40
+KPX T Odieresis -40
+KPX T Ograve -40
+KPX T Ohungarumlaut -40
+KPX T Omacron -40
+KPX T Oslash -40
+KPX T Otilde -40
+KPX T a -80
+KPX T aacute -80
+KPX T abreve -80
+KPX T acircumflex -80
+KPX T adieresis -80
+KPX T agrave -80
+KPX T amacron -80
+KPX T aogonek -80
+KPX T aring -80
+KPX T atilde -80
+KPX T colon -40
+KPX T comma -80
+KPX T e -60
+KPX T eacute -60
+KPX T ecaron -60
+KPX T ecircumflex -60
+KPX T edieresis -60
+KPX T edotaccent -60
+KPX T egrave -60
+KPX T emacron -60
+KPX T eogonek -60
+KPX T hyphen -120
+KPX T o -80
+KPX T oacute -80
+KPX T ocircumflex -80
+KPX T odieresis -80
+KPX T ograve -80
+KPX T ohungarumlaut -80
+KPX T omacron -80
+KPX T oslash -80
+KPX T otilde -80
+KPX T period -80
+KPX T r -80
+KPX T racute -80
+KPX T rcommaaccent -80
+KPX T semicolon -40
+KPX T u -90
+KPX T uacute -90
+KPX T ucircumflex -90
+KPX T udieresis -90
+KPX T ugrave -90
+KPX T uhungarumlaut -90
+KPX T umacron -90
+KPX T uogonek -90
+KPX T uring -90
+KPX T w -60
+KPX T y -60
+KPX T yacute -60
+KPX T ydieresis -60
+KPX Tcaron A -90
+KPX Tcaron Aacute -90
+KPX Tcaron Abreve -90
+KPX Tcaron Acircumflex -90
+KPX Tcaron Adieresis -90
+KPX Tcaron Agrave -90
+KPX Tcaron Amacron -90
+KPX Tcaron Aogonek -90
+KPX Tcaron Aring -90
+KPX Tcaron Atilde -90
+KPX Tcaron O -40
+KPX Tcaron Oacute -40
+KPX Tcaron Ocircumflex -40
+KPX Tcaron Odieresis -40
+KPX Tcaron Ograve -40
+KPX Tcaron Ohungarumlaut -40
+KPX Tcaron Omacron -40
+KPX Tcaron Oslash -40
+KPX Tcaron Otilde -40
+KPX Tcaron a -80
+KPX Tcaron aacute -80
+KPX Tcaron abreve -80
+KPX Tcaron acircumflex -80
+KPX Tcaron adieresis -80
+KPX Tcaron agrave -80
+KPX Tcaron amacron -80
+KPX Tcaron aogonek -80
+KPX Tcaron aring -80
+KPX Tcaron atilde -80
+KPX Tcaron colon -40
+KPX Tcaron comma -80
+KPX Tcaron e -60
+KPX Tcaron eacute -60
+KPX Tcaron ecaron -60
+KPX Tcaron ecircumflex -60
+KPX Tcaron edieresis -60
+KPX Tcaron edotaccent -60
+KPX Tcaron egrave -60
+KPX Tcaron emacron -60
+KPX Tcaron eogonek -60
+KPX Tcaron hyphen -120
+KPX Tcaron o -80
+KPX Tcaron oacute -80
+KPX Tcaron ocircumflex -80
+KPX Tcaron odieresis -80
+KPX Tcaron ograve -80
+KPX Tcaron ohungarumlaut -80
+KPX Tcaron omacron -80
+KPX Tcaron oslash -80
+KPX Tcaron otilde -80
+KPX Tcaron period -80
+KPX Tcaron r -80
+KPX Tcaron racute -80
+KPX Tcaron rcommaaccent -80
+KPX Tcaron semicolon -40
+KPX Tcaron u -90
+KPX Tcaron uacute -90
+KPX Tcaron ucircumflex -90
+KPX Tcaron udieresis -90
+KPX Tcaron ugrave -90
+KPX Tcaron uhungarumlaut -90
+KPX Tcaron umacron -90
+KPX Tcaron uogonek -90
+KPX Tcaron uring -90
+KPX Tcaron w -60
+KPX Tcaron y -60
+KPX Tcaron yacute -60
+KPX Tcaron ydieresis -60
+KPX Tcommaaccent A -90
+KPX Tcommaaccent Aacute -90
+KPX Tcommaaccent Abreve -90
+KPX Tcommaaccent Acircumflex -90
+KPX Tcommaaccent Adieresis -90
+KPX Tcommaaccent Agrave -90
+KPX Tcommaaccent Amacron -90
+KPX Tcommaaccent Aogonek -90
+KPX Tcommaaccent Aring -90
+KPX Tcommaaccent Atilde -90
+KPX Tcommaaccent O -40
+KPX Tcommaaccent Oacute -40
+KPX Tcommaaccent Ocircumflex -40
+KPX Tcommaaccent Odieresis -40
+KPX Tcommaaccent Ograve -40
+KPX Tcommaaccent Ohungarumlaut -40
+KPX Tcommaaccent Omacron -40
+KPX Tcommaaccent Oslash -40
+KPX Tcommaaccent Otilde -40
+KPX Tcommaaccent a -80
+KPX Tcommaaccent aacute -80
+KPX Tcommaaccent abreve -80
+KPX Tcommaaccent acircumflex -80
+KPX Tcommaaccent adieresis -80
+KPX Tcommaaccent agrave -80
+KPX Tcommaaccent amacron -80
+KPX Tcommaaccent aogonek -80
+KPX Tcommaaccent aring -80
+KPX Tcommaaccent atilde -80
+KPX Tcommaaccent colon -40
+KPX Tcommaaccent comma -80
+KPX Tcommaaccent e -60
+KPX Tcommaaccent eacute -60
+KPX Tcommaaccent ecaron -60
+KPX Tcommaaccent ecircumflex -60
+KPX Tcommaaccent edieresis -60
+KPX Tcommaaccent edotaccent -60
+KPX Tcommaaccent egrave -60
+KPX Tcommaaccent emacron -60
+KPX Tcommaaccent eogonek -60
+KPX Tcommaaccent hyphen -120
+KPX Tcommaaccent o -80
+KPX Tcommaaccent oacute -80
+KPX Tcommaaccent ocircumflex -80
+KPX Tcommaaccent odieresis -80
+KPX Tcommaaccent ograve -80
+KPX Tcommaaccent ohungarumlaut -80
+KPX Tcommaaccent omacron -80
+KPX Tcommaaccent oslash -80
+KPX Tcommaaccent otilde -80
+KPX Tcommaaccent period -80
+KPX Tcommaaccent r -80
+KPX Tcommaaccent racute -80
+KPX Tcommaaccent rcommaaccent -80
+KPX Tcommaaccent semicolon -40
+KPX Tcommaaccent u -90
+KPX Tcommaaccent uacute -90
+KPX Tcommaaccent ucircumflex -90
+KPX Tcommaaccent udieresis -90
+KPX Tcommaaccent ugrave -90
+KPX Tcommaaccent uhungarumlaut -90
+KPX Tcommaaccent umacron -90
+KPX Tcommaaccent uogonek -90
+KPX Tcommaaccent uring -90
+KPX Tcommaaccent w -60
+KPX Tcommaaccent y -60
+KPX Tcommaaccent yacute -60
+KPX Tcommaaccent ydieresis -60
+KPX U A -50
+KPX U Aacute -50
+KPX U Abreve -50
+KPX U Acircumflex -50
+KPX U Adieresis -50
+KPX U Agrave -50
+KPX U Amacron -50
+KPX U Aogonek -50
+KPX U Aring -50
+KPX U Atilde -50
+KPX U comma -30
+KPX U period -30
+KPX Uacute A -50
+KPX Uacute Aacute -50
+KPX Uacute Abreve -50
+KPX Uacute Acircumflex -50
+KPX Uacute Adieresis -50
+KPX Uacute Agrave -50
+KPX Uacute Amacron -50
+KPX Uacute Aogonek -50
+KPX Uacute Aring -50
+KPX Uacute Atilde -50
+KPX Uacute comma -30
+KPX Uacute period -30
+KPX Ucircumflex A -50
+KPX Ucircumflex Aacute -50
+KPX Ucircumflex Abreve -50
+KPX Ucircumflex Acircumflex -50
+KPX Ucircumflex Adieresis -50
+KPX Ucircumflex Agrave -50
+KPX Ucircumflex Amacron -50
+KPX Ucircumflex Aogonek -50
+KPX Ucircumflex Aring -50
+KPX Ucircumflex Atilde -50
+KPX Ucircumflex comma -30
+KPX Ucircumflex period -30
+KPX Udieresis A -50
+KPX Udieresis Aacute -50
+KPX Udieresis Abreve -50
+KPX Udieresis Acircumflex -50
+KPX Udieresis Adieresis -50
+KPX Udieresis Agrave -50
+KPX Udieresis Amacron -50
+KPX Udieresis Aogonek -50
+KPX Udieresis Aring -50
+KPX Udieresis Atilde -50
+KPX Udieresis comma -30
+KPX Udieresis period -30
+KPX Ugrave A -50
+KPX Ugrave Aacute -50
+KPX Ugrave Abreve -50
+KPX Ugrave Acircumflex -50
+KPX Ugrave Adieresis -50
+KPX Ugrave Agrave -50
+KPX Ugrave Amacron -50
+KPX Ugrave Aogonek -50
+KPX Ugrave Aring -50
+KPX Ugrave Atilde -50
+KPX Ugrave comma -30
+KPX Ugrave period -30
+KPX Uhungarumlaut A -50
+KPX Uhungarumlaut Aacute -50
+KPX Uhungarumlaut Abreve -50
+KPX Uhungarumlaut Acircumflex -50
+KPX Uhungarumlaut Adieresis -50
+KPX Uhungarumlaut Agrave -50
+KPX Uhungarumlaut Amacron -50
+KPX Uhungarumlaut Aogonek -50
+KPX Uhungarumlaut Aring -50
+KPX Uhungarumlaut Atilde -50
+KPX Uhungarumlaut comma -30
+KPX Uhungarumlaut period -30
+KPX Umacron A -50
+KPX Umacron Aacute -50
+KPX Umacron Abreve -50
+KPX Umacron Acircumflex -50
+KPX Umacron Adieresis -50
+KPX Umacron Agrave -50
+KPX Umacron Amacron -50
+KPX Umacron Aogonek -50
+KPX Umacron Aring -50
+KPX Umacron Atilde -50
+KPX Umacron comma -30
+KPX Umacron period -30
+KPX Uogonek A -50
+KPX Uogonek Aacute -50
+KPX Uogonek Abreve -50
+KPX Uogonek Acircumflex -50
+KPX Uogonek Adieresis -50
+KPX Uogonek Agrave -50
+KPX Uogonek Amacron -50
+KPX Uogonek Aogonek -50
+KPX Uogonek Aring -50
+KPX Uogonek Atilde -50
+KPX Uogonek comma -30
+KPX Uogonek period -30
+KPX Uring A -50
+KPX Uring Aacute -50
+KPX Uring Abreve -50
+KPX Uring Acircumflex -50
+KPX Uring Adieresis -50
+KPX Uring Agrave -50
+KPX Uring Amacron -50
+KPX Uring Aogonek -50
+KPX Uring Aring -50
+KPX Uring Atilde -50
+KPX Uring comma -30
+KPX Uring period -30
+KPX V A -80
+KPX V Aacute -80
+KPX V Abreve -80
+KPX V Acircumflex -80
+KPX V Adieresis -80
+KPX V Agrave -80
+KPX V Amacron -80
+KPX V Aogonek -80
+KPX V Aring -80
+KPX V Atilde -80
+KPX V G -50
+KPX V Gbreve -50
+KPX V Gcommaaccent -50
+KPX V O -50
+KPX V Oacute -50
+KPX V Ocircumflex -50
+KPX V Odieresis -50
+KPX V Ograve -50
+KPX V Ohungarumlaut -50
+KPX V Omacron -50
+KPX V Oslash -50
+KPX V Otilde -50
+KPX V a -60
+KPX V aacute -60
+KPX V abreve -60
+KPX V acircumflex -60
+KPX V adieresis -60
+KPX V agrave -60
+KPX V amacron -60
+KPX V aogonek -60
+KPX V aring -60
+KPX V atilde -60
+KPX V colon -40
+KPX V comma -120
+KPX V e -50
+KPX V eacute -50
+KPX V ecaron -50
+KPX V ecircumflex -50
+KPX V edieresis -50
+KPX V edotaccent -50
+KPX V egrave -50
+KPX V emacron -50
+KPX V eogonek -50
+KPX V hyphen -80
+KPX V o -90
+KPX V oacute -90
+KPX V ocircumflex -90
+KPX V odieresis -90
+KPX V ograve -90
+KPX V ohungarumlaut -90
+KPX V omacron -90
+KPX V oslash -90
+KPX V otilde -90
+KPX V period -120
+KPX V semicolon -40
+KPX V u -60
+KPX V uacute -60
+KPX V ucircumflex -60
+KPX V udieresis -60
+KPX V ugrave -60
+KPX V uhungarumlaut -60
+KPX V umacron -60
+KPX V uogonek -60
+KPX V uring -60
+KPX W A -60
+KPX W Aacute -60
+KPX W Abreve -60
+KPX W Acircumflex -60
+KPX W Adieresis -60
+KPX W Agrave -60
+KPX W Amacron -60
+KPX W Aogonek -60
+KPX W Aring -60
+KPX W Atilde -60
+KPX W O -20
+KPX W Oacute -20
+KPX W Ocircumflex -20
+KPX W Odieresis -20
+KPX W Ograve -20
+KPX W Ohungarumlaut -20
+KPX W Omacron -20
+KPX W Oslash -20
+KPX W Otilde -20
+KPX W a -40
+KPX W aacute -40
+KPX W abreve -40
+KPX W acircumflex -40
+KPX W adieresis -40
+KPX W agrave -40
+KPX W amacron -40
+KPX W aogonek -40
+KPX W aring -40
+KPX W atilde -40
+KPX W colon -10
+KPX W comma -80
+KPX W e -35
+KPX W eacute -35
+KPX W ecaron -35
+KPX W ecircumflex -35
+KPX W edieresis -35
+KPX W edotaccent -35
+KPX W egrave -35
+KPX W emacron -35
+KPX W eogonek -35
+KPX W hyphen -40
+KPX W o -60
+KPX W oacute -60
+KPX W ocircumflex -60
+KPX W odieresis -60
+KPX W ograve -60
+KPX W ohungarumlaut -60
+KPX W omacron -60
+KPX W oslash -60
+KPX W otilde -60
+KPX W period -80
+KPX W semicolon -10
+KPX W u -45
+KPX W uacute -45
+KPX W ucircumflex -45
+KPX W udieresis -45
+KPX W ugrave -45
+KPX W uhungarumlaut -45
+KPX W umacron -45
+KPX W uogonek -45
+KPX W uring -45
+KPX W y -20
+KPX W yacute -20
+KPX W ydieresis -20
+KPX Y A -110
+KPX Y Aacute -110
+KPX Y Abreve -110
+KPX Y Acircumflex -110
+KPX Y Adieresis -110
+KPX Y Agrave -110
+KPX Y Amacron -110
+KPX Y Aogonek -110
+KPX Y Aring -110
+KPX Y Atilde -110
+KPX Y O -70
+KPX Y Oacute -70
+KPX Y Ocircumflex -70
+KPX Y Odieresis -70
+KPX Y Ograve -70
+KPX Y Ohungarumlaut -70
+KPX Y Omacron -70
+KPX Y Oslash -70
+KPX Y Otilde -70
+KPX Y a -90
+KPX Y aacute -90
+KPX Y abreve -90
+KPX Y acircumflex -90
+KPX Y adieresis -90
+KPX Y agrave -90
+KPX Y amacron -90
+KPX Y aogonek -90
+KPX Y aring -90
+KPX Y atilde -90
+KPX Y colon -50
+KPX Y comma -100
+KPX Y e -80
+KPX Y eacute -80
+KPX Y ecaron -80
+KPX Y ecircumflex -80
+KPX Y edieresis -80
+KPX Y edotaccent -80
+KPX Y egrave -80
+KPX Y emacron -80
+KPX Y eogonek -80
+KPX Y o -100
+KPX Y oacute -100
+KPX Y ocircumflex -100
+KPX Y odieresis -100
+KPX Y ograve -100
+KPX Y ohungarumlaut -100
+KPX Y omacron -100
+KPX Y oslash -100
+KPX Y otilde -100
+KPX Y period -100
+KPX Y semicolon -50
+KPX Y u -100
+KPX Y uacute -100
+KPX Y ucircumflex -100
+KPX Y udieresis -100
+KPX Y ugrave -100
+KPX Y uhungarumlaut -100
+KPX Y umacron -100
+KPX Y uogonek -100
+KPX Y uring -100
+KPX Yacute A -110
+KPX Yacute Aacute -110
+KPX Yacute Abreve -110
+KPX Yacute Acircumflex -110
+KPX Yacute Adieresis -110
+KPX Yacute Agrave -110
+KPX Yacute Amacron -110
+KPX Yacute Aogonek -110
+KPX Yacute Aring -110
+KPX Yacute Atilde -110
+KPX Yacute O -70
+KPX Yacute Oacute -70
+KPX Yacute Ocircumflex -70
+KPX Yacute Odieresis -70
+KPX Yacute Ograve -70
+KPX Yacute Ohungarumlaut -70
+KPX Yacute Omacron -70
+KPX Yacute Oslash -70
+KPX Yacute Otilde -70
+KPX Yacute a -90
+KPX Yacute aacute -90
+KPX Yacute abreve -90
+KPX Yacute acircumflex -90
+KPX Yacute adieresis -90
+KPX Yacute agrave -90
+KPX Yacute amacron -90
+KPX Yacute aogonek -90
+KPX Yacute aring -90
+KPX Yacute atilde -90
+KPX Yacute colon -50
+KPX Yacute comma -100
+KPX Yacute e -80
+KPX Yacute eacute -80
+KPX Yacute ecaron -80
+KPX Yacute ecircumflex -80
+KPX Yacute edieresis -80
+KPX Yacute edotaccent -80
+KPX Yacute egrave -80
+KPX Yacute emacron -80
+KPX Yacute eogonek -80
+KPX Yacute o -100
+KPX Yacute oacute -100
+KPX Yacute ocircumflex -100
+KPX Yacute odieresis -100
+KPX Yacute ograve -100
+KPX Yacute ohungarumlaut -100
+KPX Yacute omacron -100
+KPX Yacute oslash -100
+KPX Yacute otilde -100
+KPX Yacute period -100
+KPX Yacute semicolon -50
+KPX Yacute u -100
+KPX Yacute uacute -100
+KPX Yacute ucircumflex -100
+KPX Yacute udieresis -100
+KPX Yacute ugrave -100
+KPX Yacute uhungarumlaut -100
+KPX Yacute umacron -100
+KPX Yacute uogonek -100
+KPX Yacute uring -100
+KPX Ydieresis A -110
+KPX Ydieresis Aacute -110
+KPX Ydieresis Abreve -110
+KPX Ydieresis Acircumflex -110
+KPX Ydieresis Adieresis -110
+KPX Ydieresis Agrave -110
+KPX Ydieresis Amacron -110
+KPX Ydieresis Aogonek -110
+KPX Ydieresis Aring -110
+KPX Ydieresis Atilde -110
+KPX Ydieresis O -70
+KPX Ydieresis Oacute -70
+KPX Ydieresis Ocircumflex -70
+KPX Ydieresis Odieresis -70
+KPX Ydieresis Ograve -70
+KPX Ydieresis Ohungarumlaut -70
+KPX Ydieresis Omacron -70
+KPX Ydieresis Oslash -70
+KPX Ydieresis Otilde -70
+KPX Ydieresis a -90
+KPX Ydieresis aacute -90
+KPX Ydieresis abreve -90
+KPX Ydieresis acircumflex -90
+KPX Ydieresis adieresis -90
+KPX Ydieresis agrave -90
+KPX Ydieresis amacron -90
+KPX Ydieresis aogonek -90
+KPX Ydieresis aring -90
+KPX Ydieresis atilde -90
+KPX Ydieresis colon -50
+KPX Ydieresis comma -100
+KPX Ydieresis e -80
+KPX Ydieresis eacute -80
+KPX Ydieresis ecaron -80
+KPX Ydieresis ecircumflex -80
+KPX Ydieresis edieresis -80
+KPX Ydieresis edotaccent -80
+KPX Ydieresis egrave -80
+KPX Ydieresis emacron -80
+KPX Ydieresis eogonek -80
+KPX Ydieresis o -100
+KPX Ydieresis oacute -100
+KPX Ydieresis ocircumflex -100
+KPX Ydieresis odieresis -100
+KPX Ydieresis ograve -100
+KPX Ydieresis ohungarumlaut -100
+KPX Ydieresis omacron -100
+KPX Ydieresis oslash -100
+KPX Ydieresis otilde -100
+KPX Ydieresis period -100
+KPX Ydieresis semicolon -50
+KPX Ydieresis u -100
+KPX Ydieresis uacute -100
+KPX Ydieresis ucircumflex -100
+KPX Ydieresis udieresis -100
+KPX Ydieresis ugrave -100
+KPX Ydieresis uhungarumlaut -100
+KPX Ydieresis umacron -100
+KPX Ydieresis uogonek -100
+KPX Ydieresis uring -100
+KPX a g -10
+KPX a gbreve -10
+KPX a gcommaaccent -10
+KPX a v -15
+KPX a w -15
+KPX a y -20
+KPX a yacute -20
+KPX a ydieresis -20
+KPX aacute g -10
+KPX aacute gbreve -10
+KPX aacute gcommaaccent -10
+KPX aacute v -15
+KPX aacute w -15
+KPX aacute y -20
+KPX aacute yacute -20
+KPX aacute ydieresis -20
+KPX abreve g -10
+KPX abreve gbreve -10
+KPX abreve gcommaaccent -10
+KPX abreve v -15
+KPX abreve w -15
+KPX abreve y -20
+KPX abreve yacute -20
+KPX abreve ydieresis -20
+KPX acircumflex g -10
+KPX acircumflex gbreve -10
+KPX acircumflex gcommaaccent -10
+KPX acircumflex v -15
+KPX acircumflex w -15
+KPX acircumflex y -20
+KPX acircumflex yacute -20
+KPX acircumflex ydieresis -20
+KPX adieresis g -10
+KPX adieresis gbreve -10
+KPX adieresis gcommaaccent -10
+KPX adieresis v -15
+KPX adieresis w -15
+KPX adieresis y -20
+KPX adieresis yacute -20
+KPX adieresis ydieresis -20
+KPX agrave g -10
+KPX agrave gbreve -10
+KPX agrave gcommaaccent -10
+KPX agrave v -15
+KPX agrave w -15
+KPX agrave y -20
+KPX agrave yacute -20
+KPX agrave ydieresis -20
+KPX amacron g -10
+KPX amacron gbreve -10
+KPX amacron gcommaaccent -10
+KPX amacron v -15
+KPX amacron w -15
+KPX amacron y -20
+KPX amacron yacute -20
+KPX amacron ydieresis -20
+KPX aogonek g -10
+KPX aogonek gbreve -10
+KPX aogonek gcommaaccent -10
+KPX aogonek v -15
+KPX aogonek w -15
+KPX aogonek y -20
+KPX aogonek yacute -20
+KPX aogonek ydieresis -20
+KPX aring g -10
+KPX aring gbreve -10
+KPX aring gcommaaccent -10
+KPX aring v -15
+KPX aring w -15
+KPX aring y -20
+KPX aring yacute -20
+KPX aring ydieresis -20
+KPX atilde g -10
+KPX atilde gbreve -10
+KPX atilde gcommaaccent -10
+KPX atilde v -15
+KPX atilde w -15
+KPX atilde y -20
+KPX atilde yacute -20
+KPX atilde ydieresis -20
+KPX b l -10
+KPX b lacute -10
+KPX b lcommaaccent -10
+KPX b lslash -10
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX b v -20
+KPX b y -20
+KPX b yacute -20
+KPX b ydieresis -20
+KPX c h -10
+KPX c k -20
+KPX c kcommaaccent -20
+KPX c l -20
+KPX c lacute -20
+KPX c lcommaaccent -20
+KPX c lslash -20
+KPX c y -10
+KPX c yacute -10
+KPX c ydieresis -10
+KPX cacute h -10
+KPX cacute k -20
+KPX cacute kcommaaccent -20
+KPX cacute l -20
+KPX cacute lacute -20
+KPX cacute lcommaaccent -20
+KPX cacute lslash -20
+KPX cacute y -10
+KPX cacute yacute -10
+KPX cacute ydieresis -10
+KPX ccaron h -10
+KPX ccaron k -20
+KPX ccaron kcommaaccent -20
+KPX ccaron l -20
+KPX ccaron lacute -20
+KPX ccaron lcommaaccent -20
+KPX ccaron lslash -20
+KPX ccaron y -10
+KPX ccaron yacute -10
+KPX ccaron ydieresis -10
+KPX ccedilla h -10
+KPX ccedilla k -20
+KPX ccedilla kcommaaccent -20
+KPX ccedilla l -20
+KPX ccedilla lacute -20
+KPX ccedilla lcommaaccent -20
+KPX ccedilla lslash -20
+KPX ccedilla y -10
+KPX ccedilla yacute -10
+KPX ccedilla ydieresis -10
+KPX colon space -40
+KPX comma quotedblright -120
+KPX comma quoteright -120
+KPX comma space -40
+KPX d d -10
+KPX d dcroat -10
+KPX d v -15
+KPX d w -15
+KPX d y -15
+KPX d yacute -15
+KPX d ydieresis -15
+KPX dcroat d -10
+KPX dcroat dcroat -10
+KPX dcroat v -15
+KPX dcroat w -15
+KPX dcroat y -15
+KPX dcroat yacute -15
+KPX dcroat ydieresis -15
+KPX e comma 10
+KPX e period 20
+KPX e v -15
+KPX e w -15
+KPX e x -15
+KPX e y -15
+KPX e yacute -15
+KPX e ydieresis -15
+KPX eacute comma 10
+KPX eacute period 20
+KPX eacute v -15
+KPX eacute w -15
+KPX eacute x -15
+KPX eacute y -15
+KPX eacute yacute -15
+KPX eacute ydieresis -15
+KPX ecaron comma 10
+KPX ecaron period 20
+KPX ecaron v -15
+KPX ecaron w -15
+KPX ecaron x -15
+KPX ecaron y -15
+KPX ecaron yacute -15
+KPX ecaron ydieresis -15
+KPX ecircumflex comma 10
+KPX ecircumflex period 20
+KPX ecircumflex v -15
+KPX ecircumflex w -15
+KPX ecircumflex x -15
+KPX ecircumflex y -15
+KPX ecircumflex yacute -15
+KPX ecircumflex ydieresis -15
+KPX edieresis comma 10
+KPX edieresis period 20
+KPX edieresis v -15
+KPX edieresis w -15
+KPX edieresis x -15
+KPX edieresis y -15
+KPX edieresis yacute -15
+KPX edieresis ydieresis -15
+KPX edotaccent comma 10
+KPX edotaccent period 20
+KPX edotaccent v -15
+KPX edotaccent w -15
+KPX edotaccent x -15
+KPX edotaccent y -15
+KPX edotaccent yacute -15
+KPX edotaccent ydieresis -15
+KPX egrave comma 10
+KPX egrave period 20
+KPX egrave v -15
+KPX egrave w -15
+KPX egrave x -15
+KPX egrave y -15
+KPX egrave yacute -15
+KPX egrave ydieresis -15
+KPX emacron comma 10
+KPX emacron period 20
+KPX emacron v -15
+KPX emacron w -15
+KPX emacron x -15
+KPX emacron y -15
+KPX emacron yacute -15
+KPX emacron ydieresis -15
+KPX eogonek comma 10
+KPX eogonek period 20
+KPX eogonek v -15
+KPX eogonek w -15
+KPX eogonek x -15
+KPX eogonek y -15
+KPX eogonek yacute -15
+KPX eogonek ydieresis -15
+KPX f comma -10
+KPX f e -10
+KPX f eacute -10
+KPX f ecaron -10
+KPX f ecircumflex -10
+KPX f edieresis -10
+KPX f edotaccent -10
+KPX f egrave -10
+KPX f emacron -10
+KPX f eogonek -10
+KPX f o -20
+KPX f oacute -20
+KPX f ocircumflex -20
+KPX f odieresis -20
+KPX f ograve -20
+KPX f ohungarumlaut -20
+KPX f omacron -20
+KPX f oslash -20
+KPX f otilde -20
+KPX f period -10
+KPX f quotedblright 30
+KPX f quoteright 30
+KPX g e 10
+KPX g eacute 10
+KPX g ecaron 10
+KPX g ecircumflex 10
+KPX g edieresis 10
+KPX g edotaccent 10
+KPX g egrave 10
+KPX g emacron 10
+KPX g eogonek 10
+KPX g g -10
+KPX g gbreve -10
+KPX g gcommaaccent -10
+KPX gbreve e 10
+KPX gbreve eacute 10
+KPX gbreve ecaron 10
+KPX gbreve ecircumflex 10
+KPX gbreve edieresis 10
+KPX gbreve edotaccent 10
+KPX gbreve egrave 10
+KPX gbreve emacron 10
+KPX gbreve eogonek 10
+KPX gbreve g -10
+KPX gbreve gbreve -10
+KPX gbreve gcommaaccent -10
+KPX gcommaaccent e 10
+KPX gcommaaccent eacute 10
+KPX gcommaaccent ecaron 10
+KPX gcommaaccent ecircumflex 10
+KPX gcommaaccent edieresis 10
+KPX gcommaaccent edotaccent 10
+KPX gcommaaccent egrave 10
+KPX gcommaaccent emacron 10
+KPX gcommaaccent eogonek 10
+KPX gcommaaccent g -10
+KPX gcommaaccent gbreve -10
+KPX gcommaaccent gcommaaccent -10
+KPX h y -20
+KPX h yacute -20
+KPX h ydieresis -20
+KPX k o -15
+KPX k oacute -15
+KPX k ocircumflex -15
+KPX k odieresis -15
+KPX k ograve -15
+KPX k ohungarumlaut -15
+KPX k omacron -15
+KPX k oslash -15
+KPX k otilde -15
+KPX kcommaaccent o -15
+KPX kcommaaccent oacute -15
+KPX kcommaaccent ocircumflex -15
+KPX kcommaaccent odieresis -15
+KPX kcommaaccent ograve -15
+KPX kcommaaccent ohungarumlaut -15
+KPX kcommaaccent omacron -15
+KPX kcommaaccent oslash -15
+KPX kcommaaccent otilde -15
+KPX l w -15
+KPX l y -15
+KPX l yacute -15
+KPX l ydieresis -15
+KPX lacute w -15
+KPX lacute y -15
+KPX lacute yacute -15
+KPX lacute ydieresis -15
+KPX lcommaaccent w -15
+KPX lcommaaccent y -15
+KPX lcommaaccent yacute -15
+KPX lcommaaccent ydieresis -15
+KPX lslash w -15
+KPX lslash y -15
+KPX lslash yacute -15
+KPX lslash ydieresis -15
+KPX m u -20
+KPX m uacute -20
+KPX m ucircumflex -20
+KPX m udieresis -20
+KPX m ugrave -20
+KPX m uhungarumlaut -20
+KPX m umacron -20
+KPX m uogonek -20
+KPX m uring -20
+KPX m y -30
+KPX m yacute -30
+KPX m ydieresis -30
+KPX n u -10
+KPX n uacute -10
+KPX n ucircumflex -10
+KPX n udieresis -10
+KPX n ugrave -10
+KPX n uhungarumlaut -10
+KPX n umacron -10
+KPX n uogonek -10
+KPX n uring -10
+KPX n v -40
+KPX n y -20
+KPX n yacute -20
+KPX n ydieresis -20
+KPX nacute u -10
+KPX nacute uacute -10
+KPX nacute ucircumflex -10
+KPX nacute udieresis -10
+KPX nacute ugrave -10
+KPX nacute uhungarumlaut -10
+KPX nacute umacron -10
+KPX nacute uogonek -10
+KPX nacute uring -10
+KPX nacute v -40
+KPX nacute y -20
+KPX nacute yacute -20
+KPX nacute ydieresis -20
+KPX ncaron u -10
+KPX ncaron uacute -10
+KPX ncaron ucircumflex -10
+KPX ncaron udieresis -10
+KPX ncaron ugrave -10
+KPX ncaron uhungarumlaut -10
+KPX ncaron umacron -10
+KPX ncaron uogonek -10
+KPX ncaron uring -10
+KPX ncaron v -40
+KPX ncaron y -20
+KPX ncaron yacute -20
+KPX ncaron ydieresis -20
+KPX ncommaaccent u -10
+KPX ncommaaccent uacute -10
+KPX ncommaaccent ucircumflex -10
+KPX ncommaaccent udieresis -10
+KPX ncommaaccent ugrave -10
+KPX ncommaaccent uhungarumlaut -10
+KPX ncommaaccent umacron -10
+KPX ncommaaccent uogonek -10
+KPX ncommaaccent uring -10
+KPX ncommaaccent v -40
+KPX ncommaaccent y -20
+KPX ncommaaccent yacute -20
+KPX ncommaaccent ydieresis -20
+KPX ntilde u -10
+KPX ntilde uacute -10
+KPX ntilde ucircumflex -10
+KPX ntilde udieresis -10
+KPX ntilde ugrave -10
+KPX ntilde uhungarumlaut -10
+KPX ntilde umacron -10
+KPX ntilde uogonek -10
+KPX ntilde uring -10
+KPX ntilde v -40
+KPX ntilde y -20
+KPX ntilde yacute -20
+KPX ntilde ydieresis -20
+KPX o v -20
+KPX o w -15
+KPX o x -30
+KPX o y -20
+KPX o yacute -20
+KPX o ydieresis -20
+KPX oacute v -20
+KPX oacute w -15
+KPX oacute x -30
+KPX oacute y -20
+KPX oacute yacute -20
+KPX oacute ydieresis -20
+KPX ocircumflex v -20
+KPX ocircumflex w -15
+KPX ocircumflex x -30
+KPX ocircumflex y -20
+KPX ocircumflex yacute -20
+KPX ocircumflex ydieresis -20
+KPX odieresis v -20
+KPX odieresis w -15
+KPX odieresis x -30
+KPX odieresis y -20
+KPX odieresis yacute -20
+KPX odieresis ydieresis -20
+KPX ograve v -20
+KPX ograve w -15
+KPX ograve x -30
+KPX ograve y -20
+KPX ograve yacute -20
+KPX ograve ydieresis -20
+KPX ohungarumlaut v -20
+KPX ohungarumlaut w -15
+KPX ohungarumlaut x -30
+KPX ohungarumlaut y -20
+KPX ohungarumlaut yacute -20
+KPX ohungarumlaut ydieresis -20
+KPX omacron v -20
+KPX omacron w -15
+KPX omacron x -30
+KPX omacron y -20
+KPX omacron yacute -20
+KPX omacron ydieresis -20
+KPX oslash v -20
+KPX oslash w -15
+KPX oslash x -30
+KPX oslash y -20
+KPX oslash yacute -20
+KPX oslash ydieresis -20
+KPX otilde v -20
+KPX otilde w -15
+KPX otilde x -30
+KPX otilde y -20
+KPX otilde yacute -20
+KPX otilde ydieresis -20
+KPX p y -15
+KPX p yacute -15
+KPX p ydieresis -15
+KPX period quotedblright -120
+KPX period quoteright -120
+KPX period space -40
+KPX quotedblright space -80
+KPX quoteleft quoteleft -46
+KPX quoteright d -80
+KPX quoteright dcroat -80
+KPX quoteright l -20
+KPX quoteright lacute -20
+KPX quoteright lcommaaccent -20
+KPX quoteright lslash -20
+KPX quoteright quoteright -46
+KPX quoteright r -40
+KPX quoteright racute -40
+KPX quoteright rcaron -40
+KPX quoteright rcommaaccent -40
+KPX quoteright s -60
+KPX quoteright sacute -60
+KPX quoteright scaron -60
+KPX quoteright scedilla -60
+KPX quoteright scommaaccent -60
+KPX quoteright space -80
+KPX quoteright v -20
+KPX r c -20
+KPX r cacute -20
+KPX r ccaron -20
+KPX r ccedilla -20
+KPX r comma -60
+KPX r d -20
+KPX r dcroat -20
+KPX r g -15
+KPX r gbreve -15
+KPX r gcommaaccent -15
+KPX r hyphen -20
+KPX r o -20
+KPX r oacute -20
+KPX r ocircumflex -20
+KPX r odieresis -20
+KPX r ograve -20
+KPX r ohungarumlaut -20
+KPX r omacron -20
+KPX r oslash -20
+KPX r otilde -20
+KPX r period -60
+KPX r q -20
+KPX r s -15
+KPX r sacute -15
+KPX r scaron -15
+KPX r scedilla -15
+KPX r scommaaccent -15
+KPX r t 20
+KPX r tcommaaccent 20
+KPX r v 10
+KPX r y 10
+KPX r yacute 10
+KPX r ydieresis 10
+KPX racute c -20
+KPX racute cacute -20
+KPX racute ccaron -20
+KPX racute ccedilla -20
+KPX racute comma -60
+KPX racute d -20
+KPX racute dcroat -20
+KPX racute g -15
+KPX racute gbreve -15
+KPX racute gcommaaccent -15
+KPX racute hyphen -20
+KPX racute o -20
+KPX racute oacute -20
+KPX racute ocircumflex -20
+KPX racute odieresis -20
+KPX racute ograve -20
+KPX racute ohungarumlaut -20
+KPX racute omacron -20
+KPX racute oslash -20
+KPX racute otilde -20
+KPX racute period -60
+KPX racute q -20
+KPX racute s -15
+KPX racute sacute -15
+KPX racute scaron -15
+KPX racute scedilla -15
+KPX racute scommaaccent -15
+KPX racute t 20
+KPX racute tcommaaccent 20
+KPX racute v 10
+KPX racute y 10
+KPX racute yacute 10
+KPX racute ydieresis 10
+KPX rcaron c -20
+KPX rcaron cacute -20
+KPX rcaron ccaron -20
+KPX rcaron ccedilla -20
+KPX rcaron comma -60
+KPX rcaron d -20
+KPX rcaron dcroat -20
+KPX rcaron g -15
+KPX rcaron gbreve -15
+KPX rcaron gcommaaccent -15
+KPX rcaron hyphen -20
+KPX rcaron o -20
+KPX rcaron oacute -20
+KPX rcaron ocircumflex -20
+KPX rcaron odieresis -20
+KPX rcaron ograve -20
+KPX rcaron ohungarumlaut -20
+KPX rcaron omacron -20
+KPX rcaron oslash -20
+KPX rcaron otilde -20
+KPX rcaron period -60
+KPX rcaron q -20
+KPX rcaron s -15
+KPX rcaron sacute -15
+KPX rcaron scaron -15
+KPX rcaron scedilla -15
+KPX rcaron scommaaccent -15
+KPX rcaron t 20
+KPX rcaron tcommaaccent 20
+KPX rcaron v 10
+KPX rcaron y 10
+KPX rcaron yacute 10
+KPX rcaron ydieresis 10
+KPX rcommaaccent c -20
+KPX rcommaaccent cacute -20
+KPX rcommaaccent ccaron -20
+KPX rcommaaccent ccedilla -20
+KPX rcommaaccent comma -60
+KPX rcommaaccent d -20
+KPX rcommaaccent dcroat -20
+KPX rcommaaccent g -15
+KPX rcommaaccent gbreve -15
+KPX rcommaaccent gcommaaccent -15
+KPX rcommaaccent hyphen -20
+KPX rcommaaccent o -20
+KPX rcommaaccent oacute -20
+KPX rcommaaccent ocircumflex -20
+KPX rcommaaccent odieresis -20
+KPX rcommaaccent ograve -20
+KPX rcommaaccent ohungarumlaut -20
+KPX rcommaaccent omacron -20
+KPX rcommaaccent oslash -20
+KPX rcommaaccent otilde -20
+KPX rcommaaccent period -60
+KPX rcommaaccent q -20
+KPX rcommaaccent s -15
+KPX rcommaaccent sacute -15
+KPX rcommaaccent scaron -15
+KPX rcommaaccent scedilla -15
+KPX rcommaaccent scommaaccent -15
+KPX rcommaaccent t 20
+KPX rcommaaccent tcommaaccent 20
+KPX rcommaaccent v 10
+KPX rcommaaccent y 10
+KPX rcommaaccent yacute 10
+KPX rcommaaccent ydieresis 10
+KPX s w -15
+KPX sacute w -15
+KPX scaron w -15
+KPX scedilla w -15
+KPX scommaaccent w -15
+KPX semicolon space -40
+KPX space T -100
+KPX space Tcaron -100
+KPX space Tcommaaccent -100
+KPX space V -80
+KPX space W -80
+KPX space Y -120
+KPX space Yacute -120
+KPX space Ydieresis -120
+KPX space quotedblleft -80
+KPX space quoteleft -60
+KPX v a -20
+KPX v aacute -20
+KPX v abreve -20
+KPX v acircumflex -20
+KPX v adieresis -20
+KPX v agrave -20
+KPX v amacron -20
+KPX v aogonek -20
+KPX v aring -20
+KPX v atilde -20
+KPX v comma -80
+KPX v o -30
+KPX v oacute -30
+KPX v ocircumflex -30
+KPX v odieresis -30
+KPX v ograve -30
+KPX v ohungarumlaut -30
+KPX v omacron -30
+KPX v oslash -30
+KPX v otilde -30
+KPX v period -80
+KPX w comma -40
+KPX w o -20
+KPX w oacute -20
+KPX w ocircumflex -20
+KPX w odieresis -20
+KPX w ograve -20
+KPX w ohungarumlaut -20
+KPX w omacron -20
+KPX w oslash -20
+KPX w otilde -20
+KPX w period -40
+KPX x e -10
+KPX x eacute -10
+KPX x ecaron -10
+KPX x ecircumflex -10
+KPX x edieresis -10
+KPX x edotaccent -10
+KPX x egrave -10
+KPX x emacron -10
+KPX x eogonek -10
+KPX y a -30
+KPX y aacute -30
+KPX y abreve -30
+KPX y acircumflex -30
+KPX y adieresis -30
+KPX y agrave -30
+KPX y amacron -30
+KPX y aogonek -30
+KPX y aring -30
+KPX y atilde -30
+KPX y comma -80
+KPX y e -10
+KPX y eacute -10
+KPX y ecaron -10
+KPX y ecircumflex -10
+KPX y edieresis -10
+KPX y edotaccent -10
+KPX y egrave -10
+KPX y emacron -10
+KPX y eogonek -10
+KPX y o -25
+KPX y oacute -25
+KPX y ocircumflex -25
+KPX y odieresis -25
+KPX y ograve -25
+KPX y ohungarumlaut -25
+KPX y omacron -25
+KPX y oslash -25
+KPX y otilde -25
+KPX y period -80
+KPX yacute a -30
+KPX yacute aacute -30
+KPX yacute abreve -30
+KPX yacute acircumflex -30
+KPX yacute adieresis -30
+KPX yacute agrave -30
+KPX yacute amacron -30
+KPX yacute aogonek -30
+KPX yacute aring -30
+KPX yacute atilde -30
+KPX yacute comma -80
+KPX yacute e -10
+KPX yacute eacute -10
+KPX yacute ecaron -10
+KPX yacute ecircumflex -10
+KPX yacute edieresis -10
+KPX yacute edotaccent -10
+KPX yacute egrave -10
+KPX yacute emacron -10
+KPX yacute eogonek -10
+KPX yacute o -25
+KPX yacute oacute -25
+KPX yacute ocircumflex -25
+KPX yacute odieresis -25
+KPX yacute ograve -25
+KPX yacute ohungarumlaut -25
+KPX yacute omacron -25
+KPX yacute oslash -25
+KPX yacute otilde -25
+KPX yacute period -80
+KPX ydieresis a -30
+KPX ydieresis aacute -30
+KPX ydieresis abreve -30
+KPX ydieresis acircumflex -30
+KPX ydieresis adieresis -30
+KPX ydieresis agrave -30
+KPX ydieresis amacron -30
+KPX ydieresis aogonek -30
+KPX ydieresis aring -30
+KPX ydieresis atilde -30
+KPX ydieresis comma -80
+KPX ydieresis e -10
+KPX ydieresis eacute -10
+KPX ydieresis ecaron -10
+KPX ydieresis ecircumflex -10
+KPX ydieresis edieresis -10
+KPX ydieresis edotaccent -10
+KPX ydieresis egrave -10
+KPX ydieresis emacron -10
+KPX ydieresis eogonek -10
+KPX ydieresis o -25
+KPX ydieresis oacute -25
+KPX ydieresis ocircumflex -25
+KPX ydieresis odieresis -25
+KPX ydieresis ograve -25
+KPX ydieresis ohungarumlaut -25
+KPX ydieresis omacron -25
+KPX ydieresis oslash -25
+KPX ydieresis otilde -25
+KPX ydieresis period -80
+KPX z e 10
+KPX z eacute 10
+KPX z ecaron 10
+KPX z ecircumflex 10
+KPX z edieresis 10
+KPX z edotaccent 10
+KPX z egrave 10
+KPX z emacron 10
+KPX z eogonek 10
+KPX zacute e 10
+KPX zacute eacute 10
+KPX zacute ecaron 10
+KPX zacute ecircumflex 10
+KPX zacute edieresis 10
+KPX zacute edotaccent 10
+KPX zacute egrave 10
+KPX zacute emacron 10
+KPX zacute eogonek 10
+KPX zcaron e 10
+KPX zcaron eacute 10
+KPX zcaron ecaron 10
+KPX zcaron ecircumflex 10
+KPX zcaron edieresis 10
+KPX zcaron edotaccent 10
+KPX zcaron egrave 10
+KPX zcaron emacron 10
+KPX zcaron eogonek 10
+KPX zdotaccent e 10
+KPX zdotaccent eacute 10
+KPX zdotaccent ecaron 10
+KPX zdotaccent ecircumflex 10
+KPX zdotaccent edieresis 10
+KPX zdotaccent edotaccent 10
+KPX zdotaccent egrave 10
+KPX zdotaccent emacron 10
+KPX zdotaccent eogonek 10
+EndKernPairs
+EndKernData
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica-Oblique.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica-Oblique.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica-Oblique.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica-Oblique.afm 2004-05-26 16:06:20.000000000 +0000
@@ -0,0 +1,3051 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu May 1 12:44:31 1997
+Comment UniqueID 43055
+Comment VMusage 14960 69346
+FontName Helvetica-Oblique
+FullName Helvetica Oblique
+FamilyName Helvetica
+Weight Medium
+ItalicAngle -12
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -170 -225 1116 931
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 523
+Ascender 718
+Descender -207
+StdHW 76
+StdVW 88
+StartCharMetrics 315
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 278 ; N exclam ; B 90 0 340 718 ;
+C 34 ; WX 355 ; N quotedbl ; B 168 463 438 718 ;
+C 35 ; WX 556 ; N numbersign ; B 73 0 631 688 ;
+C 36 ; WX 556 ; N dollar ; B 69 -115 617 775 ;
+C 37 ; WX 889 ; N percent ; B 147 -19 889 703 ;
+C 38 ; WX 667 ; N ampersand ; B 77 -15 647 718 ;
+C 39 ; WX 222 ; N quoteright ; B 151 463 310 718 ;
+C 40 ; WX 333 ; N parenleft ; B 108 -207 454 733 ;
+C 41 ; WX 333 ; N parenright ; B -9 -207 337 733 ;
+C 42 ; WX 389 ; N asterisk ; B 165 431 475 718 ;
+C 43 ; WX 584 ; N plus ; B 85 0 606 505 ;
+C 44 ; WX 278 ; N comma ; B 56 -147 214 106 ;
+C 45 ; WX 333 ; N hyphen ; B 93 232 357 322 ;
+C 46 ; WX 278 ; N period ; B 87 0 214 106 ;
+C 47 ; WX 278 ; N slash ; B -21 -19 452 737 ;
+C 48 ; WX 556 ; N zero ; B 93 -19 608 703 ;
+C 49 ; WX 556 ; N one ; B 207 0 508 703 ;
+C 50 ; WX 556 ; N two ; B 26 0 617 703 ;
+C 51 ; WX 556 ; N three ; B 75 -19 610 703 ;
+C 52 ; WX 556 ; N four ; B 61 0 576 703 ;
+C 53 ; WX 556 ; N five ; B 68 -19 621 688 ;
+C 54 ; WX 556 ; N six ; B 91 -19 615 703 ;
+C 55 ; WX 556 ; N seven ; B 137 0 669 688 ;
+C 56 ; WX 556 ; N eight ; B 74 -19 607 703 ;
+C 57 ; WX 556 ; N nine ; B 82 -19 609 703 ;
+C 58 ; WX 278 ; N colon ; B 87 0 301 516 ;
+C 59 ; WX 278 ; N semicolon ; B 56 -147 301 516 ;
+C 60 ; WX 584 ; N less ; B 94 11 641 495 ;
+C 61 ; WX 584 ; N equal ; B 63 115 628 390 ;
+C 62 ; WX 584 ; N greater ; B 50 11 597 495 ;
+C 63 ; WX 556 ; N question ; B 161 0 610 727 ;
+C 64 ; WX 1015 ; N at ; B 215 -19 965 737 ;
+C 65 ; WX 667 ; N A ; B 14 0 654 718 ;
+C 66 ; WX 667 ; N B ; B 74 0 712 718 ;
+C 67 ; WX 722 ; N C ; B 108 -19 782 737 ;
+C 68 ; WX 722 ; N D ; B 81 0 764 718 ;
+C 69 ; WX 667 ; N E ; B 86 0 762 718 ;
+C 70 ; WX 611 ; N F ; B 86 0 736 718 ;
+C 71 ; WX 778 ; N G ; B 111 -19 799 737 ;
+C 72 ; WX 722 ; N H ; B 77 0 799 718 ;
+C 73 ; WX 278 ; N I ; B 91 0 341 718 ;
+C 74 ; WX 500 ; N J ; B 47 -19 581 718 ;
+C 75 ; WX 667 ; N K ; B 76 0 808 718 ;
+C 76 ; WX 556 ; N L ; B 76 0 555 718 ;
+C 77 ; WX 833 ; N M ; B 73 0 914 718 ;
+C 78 ; WX 722 ; N N ; B 76 0 799 718 ;
+C 79 ; WX 778 ; N O ; B 105 -19 826 737 ;
+C 80 ; WX 667 ; N P ; B 86 0 737 718 ;
+C 81 ; WX 778 ; N Q ; B 105 -56 826 737 ;
+C 82 ; WX 722 ; N R ; B 88 0 773 718 ;
+C 83 ; WX 667 ; N S ; B 90 -19 713 737 ;
+C 84 ; WX 611 ; N T ; B 148 0 750 718 ;
+C 85 ; WX 722 ; N U ; B 123 -19 797 718 ;
+C 86 ; WX 667 ; N V ; B 173 0 800 718 ;
+C 87 ; WX 944 ; N W ; B 169 0 1081 718 ;
+C 88 ; WX 667 ; N X ; B 19 0 790 718 ;
+C 89 ; WX 667 ; N Y ; B 167 0 806 718 ;
+C 90 ; WX 611 ; N Z ; B 23 0 741 718 ;
+C 91 ; WX 278 ; N bracketleft ; B 21 -196 403 722 ;
+C 92 ; WX 278 ; N backslash ; B 140 -19 291 737 ;
+C 93 ; WX 278 ; N bracketright ; B -14 -196 368 722 ;
+C 94 ; WX 469 ; N asciicircum ; B 42 264 539 688 ;
+C 95 ; WX 556 ; N underscore ; B -27 -125 540 -75 ;
+C 96 ; WX 222 ; N quoteleft ; B 165 470 323 725 ;
+C 97 ; WX 556 ; N a ; B 61 -15 559 538 ;
+C 98 ; WX 556 ; N b ; B 58 -15 584 718 ;
+C 99 ; WX 500 ; N c ; B 74 -15 553 538 ;
+C 100 ; WX 556 ; N d ; B 84 -15 652 718 ;
+C 101 ; WX 556 ; N e ; B 84 -15 578 538 ;
+C 102 ; WX 278 ; N f ; B 86 0 416 728 ; L i fi ; L l fl ;
+C 103 ; WX 556 ; N g ; B 42 -220 610 538 ;
+C 104 ; WX 556 ; N h ; B 65 0 573 718 ;
+C 105 ; WX 222 ; N i ; B 67 0 308 718 ;
+C 106 ; WX 222 ; N j ; B -60 -210 308 718 ;
+C 107 ; WX 500 ; N k ; B 67 0 600 718 ;
+C 108 ; WX 222 ; N l ; B 67 0 308 718 ;
+C 109 ; WX 833 ; N m ; B 65 0 852 538 ;
+C 110 ; WX 556 ; N n ; B 65 0 573 538 ;
+C 111 ; WX 556 ; N o ; B 83 -14 585 538 ;
+C 112 ; WX 556 ; N p ; B 14 -207 584 538 ;
+C 113 ; WX 556 ; N q ; B 84 -207 605 538 ;
+C 114 ; WX 333 ; N r ; B 77 0 446 538 ;
+C 115 ; WX 500 ; N s ; B 63 -15 529 538 ;
+C 116 ; WX 278 ; N t ; B 102 -7 368 669 ;
+C 117 ; WX 556 ; N u ; B 94 -15 600 523 ;
+C 118 ; WX 500 ; N v ; B 119 0 603 523 ;
+C 119 ; WX 722 ; N w ; B 125 0 820 523 ;
+C 120 ; WX 500 ; N x ; B 11 0 594 523 ;
+C 121 ; WX 500 ; N y ; B 15 -214 600 523 ;
+C 122 ; WX 500 ; N z ; B 31 0 571 523 ;
+C 123 ; WX 334 ; N braceleft ; B 92 -196 445 722 ;
+C 124 ; WX 260 ; N bar ; B 46 -225 332 775 ;
+C 125 ; WX 334 ; N braceright ; B 0 -196 354 722 ;
+C 126 ; WX 584 ; N asciitilde ; B 111 180 580 326 ;
+C 161 ; WX 333 ; N exclamdown ; B 77 -195 326 523 ;
+C 162 ; WX 556 ; N cent ; B 95 -115 584 623 ;
+C 163 ; WX 556 ; N sterling ; B 49 -16 634 718 ;
+C 164 ; WX 167 ; N fraction ; B -170 -19 482 703 ;
+C 165 ; WX 556 ; N yen ; B 81 0 699 688 ;
+C 166 ; WX 556 ; N florin ; B -52 -207 654 737 ;
+C 167 ; WX 556 ; N section ; B 76 -191 584 737 ;
+C 168 ; WX 556 ; N currency ; B 60 99 646 603 ;
+C 169 ; WX 191 ; N quotesingle ; B 157 463 285 718 ;
+C 170 ; WX 333 ; N quotedblleft ; B 138 470 461 725 ;
+C 171 ; WX 556 ; N guillemotleft ; B 146 108 554 446 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 137 108 340 446 ;
+C 173 ; WX 333 ; N guilsinglright ; B 111 108 314 446 ;
+C 174 ; WX 500 ; N fi ; B 86 0 587 728 ;
+C 175 ; WX 500 ; N fl ; B 86 0 585 728 ;
+C 177 ; WX 556 ; N endash ; B 51 240 623 313 ;
+C 178 ; WX 556 ; N dagger ; B 135 -159 622 718 ;
+C 179 ; WX 556 ; N daggerdbl ; B 52 -159 623 718 ;
+C 180 ; WX 278 ; N periodcentered ; B 129 190 257 315 ;
+C 182 ; WX 537 ; N paragraph ; B 126 -173 650 718 ;
+C 183 ; WX 350 ; N bullet ; B 91 202 413 517 ;
+C 184 ; WX 222 ; N quotesinglbase ; B 21 -149 180 106 ;
+C 185 ; WX 333 ; N quotedblbase ; B -6 -149 318 106 ;
+C 186 ; WX 333 ; N quotedblright ; B 124 463 448 718 ;
+C 187 ; WX 556 ; N guillemotright ; B 120 108 528 446 ;
+C 188 ; WX 1000 ; N ellipsis ; B 115 0 908 106 ;
+C 189 ; WX 1000 ; N perthousand ; B 88 -19 1029 703 ;
+C 191 ; WX 611 ; N questiondown ; B 85 -201 534 525 ;
+C 193 ; WX 333 ; N grave ; B 170 593 337 734 ;
+C 194 ; WX 333 ; N acute ; B 248 593 475 734 ;
+C 195 ; WX 333 ; N circumflex ; B 147 593 438 734 ;
+C 196 ; WX 333 ; N tilde ; B 125 606 490 722 ;
+C 197 ; WX 333 ; N macron ; B 143 627 468 684 ;
+C 198 ; WX 333 ; N breve ; B 167 595 476 731 ;
+C 199 ; WX 333 ; N dotaccent ; B 249 604 362 706 ;
+C 200 ; WX 333 ; N dieresis ; B 168 604 443 706 ;
+C 202 ; WX 333 ; N ring ; B 214 572 402 756 ;
+C 203 ; WX 333 ; N cedilla ; B 2 -225 232 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 157 593 565 734 ;
+C 206 ; WX 333 ; N ogonek ; B 43 -225 249 0 ;
+C 207 ; WX 333 ; N caron ; B 177 593 468 734 ;
+C 208 ; WX 1000 ; N emdash ; B 51 240 1067 313 ;
+C 225 ; WX 1000 ; N AE ; B 8 0 1097 718 ;
+C 227 ; WX 370 ; N ordfeminine ; B 127 405 449 737 ;
+C 232 ; WX 556 ; N Lslash ; B 41 0 555 718 ;
+C 233 ; WX 778 ; N Oslash ; B 43 -19 890 737 ;
+C 234 ; WX 1000 ; N OE ; B 98 -19 1116 737 ;
+C 235 ; WX 365 ; N ordmasculine ; B 141 405 468 737 ;
+C 241 ; WX 889 ; N ae ; B 61 -15 909 538 ;
+C 245 ; WX 278 ; N dotlessi ; B 95 0 294 523 ;
+C 248 ; WX 222 ; N lslash ; B 41 0 347 718 ;
+C 249 ; WX 611 ; N oslash ; B 29 -22 647 545 ;
+C 250 ; WX 944 ; N oe ; B 83 -15 964 538 ;
+C 251 ; WX 611 ; N germandbls ; B 67 -15 658 728 ;
+C -1 ; WX 278 ; N Idieresis ; B 91 0 458 901 ;
+C -1 ; WX 556 ; N eacute ; B 84 -15 587 734 ;
+C -1 ; WX 556 ; N abreve ; B 61 -15 578 731 ;
+C -1 ; WX 556 ; N uhungarumlaut ; B 94 -15 677 734 ;
+C -1 ; WX 556 ; N ecaron ; B 84 -15 580 734 ;
+C -1 ; WX 667 ; N Ydieresis ; B 167 0 806 901 ;
+C -1 ; WX 584 ; N divide ; B 85 -19 606 524 ;
+C -1 ; WX 667 ; N Yacute ; B 167 0 806 929 ;
+C -1 ; WX 667 ; N Acircumflex ; B 14 0 654 929 ;
+C -1 ; WX 556 ; N aacute ; B 61 -15 587 734 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 123 -19 797 929 ;
+C -1 ; WX 500 ; N yacute ; B 15 -214 600 734 ;
+C -1 ; WX 500 ; N scommaaccent ; B 63 -225 529 538 ;
+C -1 ; WX 556 ; N ecircumflex ; B 84 -15 578 734 ;
+C -1 ; WX 722 ; N Uring ; B 123 -19 797 931 ;
+C -1 ; WX 722 ; N Udieresis ; B 123 -19 797 901 ;
+C -1 ; WX 556 ; N aogonek ; B 61 -220 559 538 ;
+C -1 ; WX 722 ; N Uacute ; B 123 -19 797 929 ;
+C -1 ; WX 556 ; N uogonek ; B 94 -225 600 523 ;
+C -1 ; WX 667 ; N Edieresis ; B 86 0 762 901 ;
+C -1 ; WX 722 ; N Dcroat ; B 69 0 764 718 ;
+C -1 ; WX 250 ; N commaaccent ; B 39 -225 172 -40 ;
+C -1 ; WX 737 ; N copyright ; B 54 -19 837 737 ;
+C -1 ; WX 667 ; N Emacron ; B 86 0 762 879 ;
+C -1 ; WX 500 ; N ccaron ; B 74 -15 553 734 ;
+C -1 ; WX 556 ; N aring ; B 61 -15 559 756 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B 76 -225 799 718 ;
+C -1 ; WX 222 ; N lacute ; B 67 0 461 929 ;
+C -1 ; WX 556 ; N agrave ; B 61 -15 559 734 ;
+C -1 ; WX 611 ; N Tcommaaccent ; B 148 -225 750 718 ;
+C -1 ; WX 722 ; N Cacute ; B 108 -19 782 929 ;
+C -1 ; WX 556 ; N atilde ; B 61 -15 592 722 ;
+C -1 ; WX 667 ; N Edotaccent ; B 86 0 762 901 ;
+C -1 ; WX 500 ; N scaron ; B 63 -15 552 734 ;
+C -1 ; WX 500 ; N scedilla ; B 63 -225 529 538 ;
+C -1 ; WX 278 ; N iacute ; B 95 0 448 734 ;
+C -1 ; WX 471 ; N lozenge ; B 88 0 540 728 ;
+C -1 ; WX 722 ; N Rcaron ; B 88 0 773 929 ;
+C -1 ; WX 778 ; N Gcommaaccent ; B 111 -225 799 737 ;
+C -1 ; WX 556 ; N ucircumflex ; B 94 -15 600 734 ;
+C -1 ; WX 556 ; N acircumflex ; B 61 -15 559 734 ;
+C -1 ; WX 667 ; N Amacron ; B 14 0 677 879 ;
+C -1 ; WX 333 ; N rcaron ; B 77 0 508 734 ;
+C -1 ; WX 500 ; N ccedilla ; B 74 -225 553 538 ;
+C -1 ; WX 611 ; N Zdotaccent ; B 23 0 741 901 ;
+C -1 ; WX 667 ; N Thorn ; B 86 0 712 718 ;
+C -1 ; WX 778 ; N Omacron ; B 105 -19 826 879 ;
+C -1 ; WX 722 ; N Racute ; B 88 0 773 929 ;
+C -1 ; WX 667 ; N Sacute ; B 90 -19 713 929 ;
+C -1 ; WX 643 ; N dcaron ; B 84 -15 808 718 ;
+C -1 ; WX 722 ; N Umacron ; B 123 -19 797 879 ;
+C -1 ; WX 556 ; N uring ; B 94 -15 600 756 ;
+C -1 ; WX 333 ; N threesuperior ; B 90 270 436 703 ;
+C -1 ; WX 778 ; N Ograve ; B 105 -19 826 929 ;
+C -1 ; WX 667 ; N Agrave ; B 14 0 654 929 ;
+C -1 ; WX 667 ; N Abreve ; B 14 0 685 926 ;
+C -1 ; WX 584 ; N multiply ; B 50 0 642 506 ;
+C -1 ; WX 556 ; N uacute ; B 94 -15 600 734 ;
+C -1 ; WX 611 ; N Tcaron ; B 148 0 750 929 ;
+C -1 ; WX 476 ; N partialdiff ; B 41 -38 550 714 ;
+C -1 ; WX 500 ; N ydieresis ; B 15 -214 600 706 ;
+C -1 ; WX 722 ; N Nacute ; B 76 0 799 929 ;
+C -1 ; WX 278 ; N icircumflex ; B 95 0 411 734 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 86 0 762 929 ;
+C -1 ; WX 556 ; N adieresis ; B 61 -15 559 706 ;
+C -1 ; WX 556 ; N edieresis ; B 84 -15 578 706 ;
+C -1 ; WX 500 ; N cacute ; B 74 -15 559 734 ;
+C -1 ; WX 556 ; N nacute ; B 65 0 587 734 ;
+C -1 ; WX 556 ; N umacron ; B 94 -15 600 684 ;
+C -1 ; WX 722 ; N Ncaron ; B 76 0 799 929 ;
+C -1 ; WX 278 ; N Iacute ; B 91 0 489 929 ;
+C -1 ; WX 584 ; N plusminus ; B 39 0 618 506 ;
+C -1 ; WX 260 ; N brokenbar ; B 62 -150 316 700 ;
+C -1 ; WX 737 ; N registered ; B 54 -19 837 737 ;
+C -1 ; WX 778 ; N Gbreve ; B 111 -19 799 926 ;
+C -1 ; WX 278 ; N Idotaccent ; B 91 0 377 901 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 671 706 ;
+C -1 ; WX 667 ; N Egrave ; B 86 0 762 929 ;
+C -1 ; WX 333 ; N racute ; B 77 0 475 734 ;
+C -1 ; WX 556 ; N omacron ; B 83 -14 585 684 ;
+C -1 ; WX 611 ; N Zacute ; B 23 0 741 929 ;
+C -1 ; WX 611 ; N Zcaron ; B 23 0 741 929 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 620 674 ;
+C -1 ; WX 722 ; N Eth ; B 69 0 764 718 ;
+C -1 ; WX 722 ; N Ccedilla ; B 108 -225 782 737 ;
+C -1 ; WX 222 ; N lcommaaccent ; B 25 -225 308 718 ;
+C -1 ; WX 317 ; N tcaron ; B 102 -7 501 808 ;
+C -1 ; WX 556 ; N eogonek ; B 84 -225 578 538 ;
+C -1 ; WX 722 ; N Uogonek ; B 123 -225 797 718 ;
+C -1 ; WX 667 ; N Aacute ; B 14 0 683 929 ;
+C -1 ; WX 667 ; N Adieresis ; B 14 0 654 901 ;
+C -1 ; WX 556 ; N egrave ; B 84 -15 578 734 ;
+C -1 ; WX 500 ; N zacute ; B 31 0 571 734 ;
+C -1 ; WX 222 ; N iogonek ; B -61 -225 308 718 ;
+C -1 ; WX 778 ; N Oacute ; B 105 -19 826 929 ;
+C -1 ; WX 556 ; N oacute ; B 83 -14 587 734 ;
+C -1 ; WX 556 ; N amacron ; B 61 -15 580 684 ;
+C -1 ; WX 500 ; N sacute ; B 63 -15 559 734 ;
+C -1 ; WX 278 ; N idieresis ; B 95 0 416 706 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 105 -19 826 929 ;
+C -1 ; WX 722 ; N Ugrave ; B 123 -19 797 929 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 556 ; N thorn ; B 14 -207 584 718 ;
+C -1 ; WX 333 ; N twosuperior ; B 64 281 449 703 ;
+C -1 ; WX 778 ; N Odieresis ; B 105 -19 826 901 ;
+C -1 ; WX 556 ; N mu ; B 24 -207 600 523 ;
+C -1 ; WX 278 ; N igrave ; B 95 0 310 734 ;
+C -1 ; WX 556 ; N ohungarumlaut ; B 83 -14 677 734 ;
+C -1 ; WX 667 ; N Eogonek ; B 86 -220 762 718 ;
+C -1 ; WX 556 ; N dcroat ; B 84 -15 689 718 ;
+C -1 ; WX 834 ; N threequarters ; B 130 -19 861 703 ;
+C -1 ; WX 667 ; N Scedilla ; B 90 -225 713 737 ;
+C -1 ; WX 299 ; N lcaron ; B 67 0 464 718 ;
+C -1 ; WX 667 ; N Kcommaaccent ; B 76 -225 808 718 ;
+C -1 ; WX 556 ; N Lacute ; B 76 0 555 929 ;
+C -1 ; WX 1000 ; N trademark ; B 186 306 1056 718 ;
+C -1 ; WX 556 ; N edotaccent ; B 84 -15 578 706 ;
+C -1 ; WX 278 ; N Igrave ; B 91 0 351 929 ;
+C -1 ; WX 278 ; N Imacron ; B 91 0 483 879 ;
+C -1 ; WX 556 ; N Lcaron ; B 76 0 570 718 ;
+C -1 ; WX 834 ; N onehalf ; B 114 -19 839 703 ;
+C -1 ; WX 549 ; N lessequal ; B 26 0 666 674 ;
+C -1 ; WX 556 ; N ocircumflex ; B 83 -14 585 734 ;
+C -1 ; WX 556 ; N ntilde ; B 65 0 592 722 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 123 -19 801 929 ;
+C -1 ; WX 667 ; N Eacute ; B 86 0 762 929 ;
+C -1 ; WX 556 ; N emacron ; B 84 -15 580 684 ;
+C -1 ; WX 556 ; N gbreve ; B 42 -220 610 731 ;
+C -1 ; WX 834 ; N onequarter ; B 150 -19 802 703 ;
+C -1 ; WX 667 ; N Scaron ; B 90 -19 713 929 ;
+C -1 ; WX 667 ; N Scommaaccent ; B 90 -225 713 737 ;
+C -1 ; WX 778 ; N Ohungarumlaut ; B 105 -19 829 929 ;
+C -1 ; WX 400 ; N degree ; B 169 411 468 703 ;
+C -1 ; WX 556 ; N ograve ; B 83 -14 585 734 ;
+C -1 ; WX 722 ; N Ccaron ; B 108 -19 782 929 ;
+C -1 ; WX 556 ; N ugrave ; B 94 -15 600 734 ;
+C -1 ; WX 453 ; N radical ; B 79 -80 617 762 ;
+C -1 ; WX 722 ; N Dcaron ; B 81 0 764 929 ;
+C -1 ; WX 333 ; N rcommaaccent ; B 30 -225 446 538 ;
+C -1 ; WX 722 ; N Ntilde ; B 76 0 799 917 ;
+C -1 ; WX 556 ; N otilde ; B 83 -14 602 722 ;
+C -1 ; WX 722 ; N Rcommaaccent ; B 88 -225 773 718 ;
+C -1 ; WX 556 ; N Lcommaaccent ; B 76 -225 555 718 ;
+C -1 ; WX 667 ; N Atilde ; B 14 0 699 917 ;
+C -1 ; WX 667 ; N Aogonek ; B 14 -225 654 718 ;
+C -1 ; WX 667 ; N Aring ; B 14 0 654 931 ;
+C -1 ; WX 778 ; N Otilde ; B 105 -19 826 917 ;
+C -1 ; WX 500 ; N zdotaccent ; B 31 0 571 706 ;
+C -1 ; WX 667 ; N Ecaron ; B 86 0 762 929 ;
+C -1 ; WX 278 ; N Iogonek ; B -33 -225 341 718 ;
+C -1 ; WX 500 ; N kcommaaccent ; B 67 -225 600 718 ;
+C -1 ; WX 584 ; N minus ; B 85 216 606 289 ;
+C -1 ; WX 278 ; N Icircumflex ; B 91 0 452 929 ;
+C -1 ; WX 556 ; N ncaron ; B 65 0 580 734 ;
+C -1 ; WX 278 ; N tcommaaccent ; B 63 -225 368 669 ;
+C -1 ; WX 584 ; N logicalnot ; B 106 108 628 390 ;
+C -1 ; WX 556 ; N odieresis ; B 83 -14 585 706 ;
+C -1 ; WX 556 ; N udieresis ; B 94 -15 600 706 ;
+C -1 ; WX 549 ; N notequal ; B 34 -35 623 551 ;
+C -1 ; WX 556 ; N gcommaaccent ; B 42 -220 610 822 ;
+C -1 ; WX 556 ; N eth ; B 81 -15 617 737 ;
+C -1 ; WX 500 ; N zcaron ; B 31 0 571 734 ;
+C -1 ; WX 556 ; N ncommaaccent ; B 65 -225 573 538 ;
+C -1 ; WX 333 ; N onesuperior ; B 166 281 371 703 ;
+C -1 ; WX 278 ; N imacron ; B 95 0 417 684 ;
+C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2705
+KPX A C -30
+KPX A Cacute -30
+KPX A Ccaron -30
+KPX A Ccedilla -30
+KPX A G -30
+KPX A Gbreve -30
+KPX A Gcommaaccent -30
+KPX A O -30
+KPX A Oacute -30
+KPX A Ocircumflex -30
+KPX A Odieresis -30
+KPX A Ograve -30
+KPX A Ohungarumlaut -30
+KPX A Omacron -30
+KPX A Oslash -30
+KPX A Otilde -30
+KPX A Q -30
+KPX A T -120
+KPX A Tcaron -120
+KPX A Tcommaaccent -120
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -70
+KPX A W -50
+KPX A Y -100
+KPX A Yacute -100
+KPX A Ydieresis -100
+KPX A u -30
+KPX A uacute -30
+KPX A ucircumflex -30
+KPX A udieresis -30
+KPX A ugrave -30
+KPX A uhungarumlaut -30
+KPX A umacron -30
+KPX A uogonek -30
+KPX A uring -30
+KPX A v -40
+KPX A w -40
+KPX A y -40
+KPX A yacute -40
+KPX A ydieresis -40
+KPX Aacute C -30
+KPX Aacute Cacute -30
+KPX Aacute Ccaron -30
+KPX Aacute Ccedilla -30
+KPX Aacute G -30
+KPX Aacute Gbreve -30
+KPX Aacute Gcommaaccent -30
+KPX Aacute O -30
+KPX Aacute Oacute -30
+KPX Aacute Ocircumflex -30
+KPX Aacute Odieresis -30
+KPX Aacute Ograve -30
+KPX Aacute Ohungarumlaut -30
+KPX Aacute Omacron -30
+KPX Aacute Oslash -30
+KPX Aacute Otilde -30
+KPX Aacute Q -30
+KPX Aacute T -120
+KPX Aacute Tcaron -120
+KPX Aacute Tcommaaccent -120
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -70
+KPX Aacute W -50
+KPX Aacute Y -100
+KPX Aacute Yacute -100
+KPX Aacute Ydieresis -100
+KPX Aacute u -30
+KPX Aacute uacute -30
+KPX Aacute ucircumflex -30
+KPX Aacute udieresis -30
+KPX Aacute ugrave -30
+KPX Aacute uhungarumlaut -30
+KPX Aacute umacron -30
+KPX Aacute uogonek -30
+KPX Aacute uring -30
+KPX Aacute v -40
+KPX Aacute w -40
+KPX Aacute y -40
+KPX Aacute yacute -40
+KPX Aacute ydieresis -40
+KPX Abreve C -30
+KPX Abreve Cacute -30
+KPX Abreve Ccaron -30
+KPX Abreve Ccedilla -30
+KPX Abreve G -30
+KPX Abreve Gbreve -30
+KPX Abreve Gcommaaccent -30
+KPX Abreve O -30
+KPX Abreve Oacute -30
+KPX Abreve Ocircumflex -30
+KPX Abreve Odieresis -30
+KPX Abreve Ograve -30
+KPX Abreve Ohungarumlaut -30
+KPX Abreve Omacron -30
+KPX Abreve Oslash -30
+KPX Abreve Otilde -30
+KPX Abreve Q -30
+KPX Abreve T -120
+KPX Abreve Tcaron -120
+KPX Abreve Tcommaaccent -120
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -70
+KPX Abreve W -50
+KPX Abreve Y -100
+KPX Abreve Yacute -100
+KPX Abreve Ydieresis -100
+KPX Abreve u -30
+KPX Abreve uacute -30
+KPX Abreve ucircumflex -30
+KPX Abreve udieresis -30
+KPX Abreve ugrave -30
+KPX Abreve uhungarumlaut -30
+KPX Abreve umacron -30
+KPX Abreve uogonek -30
+KPX Abreve uring -30
+KPX Abreve v -40
+KPX Abreve w -40
+KPX Abreve y -40
+KPX Abreve yacute -40
+KPX Abreve ydieresis -40
+KPX Acircumflex C -30
+KPX Acircumflex Cacute -30
+KPX Acircumflex Ccaron -30
+KPX Acircumflex Ccedilla -30
+KPX Acircumflex G -30
+KPX Acircumflex Gbreve -30
+KPX Acircumflex Gcommaaccent -30
+KPX Acircumflex O -30
+KPX Acircumflex Oacute -30
+KPX Acircumflex Ocircumflex -30
+KPX Acircumflex Odieresis -30
+KPX Acircumflex Ograve -30
+KPX Acircumflex Ohungarumlaut -30
+KPX Acircumflex Omacron -30
+KPX Acircumflex Oslash -30
+KPX Acircumflex Otilde -30
+KPX Acircumflex Q -30
+KPX Acircumflex T -120
+KPX Acircumflex Tcaron -120
+KPX Acircumflex Tcommaaccent -120
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -70
+KPX Acircumflex W -50
+KPX Acircumflex Y -100
+KPX Acircumflex Yacute -100
+KPX Acircumflex Ydieresis -100
+KPX Acircumflex u -30
+KPX Acircumflex uacute -30
+KPX Acircumflex ucircumflex -30
+KPX Acircumflex udieresis -30
+KPX Acircumflex ugrave -30
+KPX Acircumflex uhungarumlaut -30
+KPX Acircumflex umacron -30
+KPX Acircumflex uogonek -30
+KPX Acircumflex uring -30
+KPX Acircumflex v -40
+KPX Acircumflex w -40
+KPX Acircumflex y -40
+KPX Acircumflex yacute -40
+KPX Acircumflex ydieresis -40
+KPX Adieresis C -30
+KPX Adieresis Cacute -30
+KPX Adieresis Ccaron -30
+KPX Adieresis Ccedilla -30
+KPX Adieresis G -30
+KPX Adieresis Gbreve -30
+KPX Adieresis Gcommaaccent -30
+KPX Adieresis O -30
+KPX Adieresis Oacute -30
+KPX Adieresis Ocircumflex -30
+KPX Adieresis Odieresis -30
+KPX Adieresis Ograve -30
+KPX Adieresis Ohungarumlaut -30
+KPX Adieresis Omacron -30
+KPX Adieresis Oslash -30
+KPX Adieresis Otilde -30
+KPX Adieresis Q -30
+KPX Adieresis T -120
+KPX Adieresis Tcaron -120
+KPX Adieresis Tcommaaccent -120
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -70
+KPX Adieresis W -50
+KPX Adieresis Y -100
+KPX Adieresis Yacute -100
+KPX Adieresis Ydieresis -100
+KPX Adieresis u -30
+KPX Adieresis uacute -30
+KPX Adieresis ucircumflex -30
+KPX Adieresis udieresis -30
+KPX Adieresis ugrave -30
+KPX Adieresis uhungarumlaut -30
+KPX Adieresis umacron -30
+KPX Adieresis uogonek -30
+KPX Adieresis uring -30
+KPX Adieresis v -40
+KPX Adieresis w -40
+KPX Adieresis y -40
+KPX Adieresis yacute -40
+KPX Adieresis ydieresis -40
+KPX Agrave C -30
+KPX Agrave Cacute -30
+KPX Agrave Ccaron -30
+KPX Agrave Ccedilla -30
+KPX Agrave G -30
+KPX Agrave Gbreve -30
+KPX Agrave Gcommaaccent -30
+KPX Agrave O -30
+KPX Agrave Oacute -30
+KPX Agrave Ocircumflex -30
+KPX Agrave Odieresis -30
+KPX Agrave Ograve -30
+KPX Agrave Ohungarumlaut -30
+KPX Agrave Omacron -30
+KPX Agrave Oslash -30
+KPX Agrave Otilde -30
+KPX Agrave Q -30
+KPX Agrave T -120
+KPX Agrave Tcaron -120
+KPX Agrave Tcommaaccent -120
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -70
+KPX Agrave W -50
+KPX Agrave Y -100
+KPX Agrave Yacute -100
+KPX Agrave Ydieresis -100
+KPX Agrave u -30
+KPX Agrave uacute -30
+KPX Agrave ucircumflex -30
+KPX Agrave udieresis -30
+KPX Agrave ugrave -30
+KPX Agrave uhungarumlaut -30
+KPX Agrave umacron -30
+KPX Agrave uogonek -30
+KPX Agrave uring -30
+KPX Agrave v -40
+KPX Agrave w -40
+KPX Agrave y -40
+KPX Agrave yacute -40
+KPX Agrave ydieresis -40
+KPX Amacron C -30
+KPX Amacron Cacute -30
+KPX Amacron Ccaron -30
+KPX Amacron Ccedilla -30
+KPX Amacron G -30
+KPX Amacron Gbreve -30
+KPX Amacron Gcommaaccent -30
+KPX Amacron O -30
+KPX Amacron Oacute -30
+KPX Amacron Ocircumflex -30
+KPX Amacron Odieresis -30
+KPX Amacron Ograve -30
+KPX Amacron Ohungarumlaut -30
+KPX Amacron Omacron -30
+KPX Amacron Oslash -30
+KPX Amacron Otilde -30
+KPX Amacron Q -30
+KPX Amacron T -120
+KPX Amacron Tcaron -120
+KPX Amacron Tcommaaccent -120
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -70
+KPX Amacron W -50
+KPX Amacron Y -100
+KPX Amacron Yacute -100
+KPX Amacron Ydieresis -100
+KPX Amacron u -30
+KPX Amacron uacute -30
+KPX Amacron ucircumflex -30
+KPX Amacron udieresis -30
+KPX Amacron ugrave -30
+KPX Amacron uhungarumlaut -30
+KPX Amacron umacron -30
+KPX Amacron uogonek -30
+KPX Amacron uring -30
+KPX Amacron v -40
+KPX Amacron w -40
+KPX Amacron y -40
+KPX Amacron yacute -40
+KPX Amacron ydieresis -40
+KPX Aogonek C -30
+KPX Aogonek Cacute -30
+KPX Aogonek Ccaron -30
+KPX Aogonek Ccedilla -30
+KPX Aogonek G -30
+KPX Aogonek Gbreve -30
+KPX Aogonek Gcommaaccent -30
+KPX Aogonek O -30
+KPX Aogonek Oacute -30
+KPX Aogonek Ocircumflex -30
+KPX Aogonek Odieresis -30
+KPX Aogonek Ograve -30
+KPX Aogonek Ohungarumlaut -30
+KPX Aogonek Omacron -30
+KPX Aogonek Oslash -30
+KPX Aogonek Otilde -30
+KPX Aogonek Q -30
+KPX Aogonek T -120
+KPX Aogonek Tcaron -120
+KPX Aogonek Tcommaaccent -120
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -70
+KPX Aogonek W -50
+KPX Aogonek Y -100
+KPX Aogonek Yacute -100
+KPX Aogonek Ydieresis -100
+KPX Aogonek u -30
+KPX Aogonek uacute -30
+KPX Aogonek ucircumflex -30
+KPX Aogonek udieresis -30
+KPX Aogonek ugrave -30
+KPX Aogonek uhungarumlaut -30
+KPX Aogonek umacron -30
+KPX Aogonek uogonek -30
+KPX Aogonek uring -30
+KPX Aogonek v -40
+KPX Aogonek w -40
+KPX Aogonek y -40
+KPX Aogonek yacute -40
+KPX Aogonek ydieresis -40
+KPX Aring C -30
+KPX Aring Cacute -30
+KPX Aring Ccaron -30
+KPX Aring Ccedilla -30
+KPX Aring G -30
+KPX Aring Gbreve -30
+KPX Aring Gcommaaccent -30
+KPX Aring O -30
+KPX Aring Oacute -30
+KPX Aring Ocircumflex -30
+KPX Aring Odieresis -30
+KPX Aring Ograve -30
+KPX Aring Ohungarumlaut -30
+KPX Aring Omacron -30
+KPX Aring Oslash -30
+KPX Aring Otilde -30
+KPX Aring Q -30
+KPX Aring T -120
+KPX Aring Tcaron -120
+KPX Aring Tcommaaccent -120
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -70
+KPX Aring W -50
+KPX Aring Y -100
+KPX Aring Yacute -100
+KPX Aring Ydieresis -100
+KPX Aring u -30
+KPX Aring uacute -30
+KPX Aring ucircumflex -30
+KPX Aring udieresis -30
+KPX Aring ugrave -30
+KPX Aring uhungarumlaut -30
+KPX Aring umacron -30
+KPX Aring uogonek -30
+KPX Aring uring -30
+KPX Aring v -40
+KPX Aring w -40
+KPX Aring y -40
+KPX Aring yacute -40
+KPX Aring ydieresis -40
+KPX Atilde C -30
+KPX Atilde Cacute -30
+KPX Atilde Ccaron -30
+KPX Atilde Ccedilla -30
+KPX Atilde G -30
+KPX Atilde Gbreve -30
+KPX Atilde Gcommaaccent -30
+KPX Atilde O -30
+KPX Atilde Oacute -30
+KPX Atilde Ocircumflex -30
+KPX Atilde Odieresis -30
+KPX Atilde Ograve -30
+KPX Atilde Ohungarumlaut -30
+KPX Atilde Omacron -30
+KPX Atilde Oslash -30
+KPX Atilde Otilde -30
+KPX Atilde Q -30
+KPX Atilde T -120
+KPX Atilde Tcaron -120
+KPX Atilde Tcommaaccent -120
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -70
+KPX Atilde W -50
+KPX Atilde Y -100
+KPX Atilde Yacute -100
+KPX Atilde Ydieresis -100
+KPX Atilde u -30
+KPX Atilde uacute -30
+KPX Atilde ucircumflex -30
+KPX Atilde udieresis -30
+KPX Atilde ugrave -30
+KPX Atilde uhungarumlaut -30
+KPX Atilde umacron -30
+KPX Atilde uogonek -30
+KPX Atilde uring -30
+KPX Atilde v -40
+KPX Atilde w -40
+KPX Atilde y -40
+KPX Atilde yacute -40
+KPX Atilde ydieresis -40
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX B comma -20
+KPX B period -20
+KPX C comma -30
+KPX C period -30
+KPX Cacute comma -30
+KPX Cacute period -30
+KPX Ccaron comma -30
+KPX Ccaron period -30
+KPX Ccedilla comma -30
+KPX Ccedilla period -30
+KPX D A -40
+KPX D Aacute -40
+KPX D Abreve -40
+KPX D Acircumflex -40
+KPX D Adieresis -40
+KPX D Agrave -40
+KPX D Amacron -40
+KPX D Aogonek -40
+KPX D Aring -40
+KPX D Atilde -40
+KPX D V -70
+KPX D W -40
+KPX D Y -90
+KPX D Yacute -90
+KPX D Ydieresis -90
+KPX D comma -70
+KPX D period -70
+KPX Dcaron A -40
+KPX Dcaron Aacute -40
+KPX Dcaron Abreve -40
+KPX Dcaron Acircumflex -40
+KPX Dcaron Adieresis -40
+KPX Dcaron Agrave -40
+KPX Dcaron Amacron -40
+KPX Dcaron Aogonek -40
+KPX Dcaron Aring -40
+KPX Dcaron Atilde -40
+KPX Dcaron V -70
+KPX Dcaron W -40
+KPX Dcaron Y -90
+KPX Dcaron Yacute -90
+KPX Dcaron Ydieresis -90
+KPX Dcaron comma -70
+KPX Dcaron period -70
+KPX Dcroat A -40
+KPX Dcroat Aacute -40
+KPX Dcroat Abreve -40
+KPX Dcroat Acircumflex -40
+KPX Dcroat Adieresis -40
+KPX Dcroat Agrave -40
+KPX Dcroat Amacron -40
+KPX Dcroat Aogonek -40
+KPX Dcroat Aring -40
+KPX Dcroat Atilde -40
+KPX Dcroat V -70
+KPX Dcroat W -40
+KPX Dcroat Y -90
+KPX Dcroat Yacute -90
+KPX Dcroat Ydieresis -90
+KPX Dcroat comma -70
+KPX Dcroat period -70
+KPX F A -80
+KPX F Aacute -80
+KPX F Abreve -80
+KPX F Acircumflex -80
+KPX F Adieresis -80
+KPX F Agrave -80
+KPX F Amacron -80
+KPX F Aogonek -80
+KPX F Aring -80
+KPX F Atilde -80
+KPX F a -50
+KPX F aacute -50
+KPX F abreve -50
+KPX F acircumflex -50
+KPX F adieresis -50
+KPX F agrave -50
+KPX F amacron -50
+KPX F aogonek -50
+KPX F aring -50
+KPX F atilde -50
+KPX F comma -150
+KPX F e -30
+KPX F eacute -30
+KPX F ecaron -30
+KPX F ecircumflex -30
+KPX F edieresis -30
+KPX F edotaccent -30
+KPX F egrave -30
+KPX F emacron -30
+KPX F eogonek -30
+KPX F o -30
+KPX F oacute -30
+KPX F ocircumflex -30
+KPX F odieresis -30
+KPX F ograve -30
+KPX F ohungarumlaut -30
+KPX F omacron -30
+KPX F oslash -30
+KPX F otilde -30
+KPX F period -150
+KPX F r -45
+KPX F racute -45
+KPX F rcaron -45
+KPX F rcommaaccent -45
+KPX J A -20
+KPX J Aacute -20
+KPX J Abreve -20
+KPX J Acircumflex -20
+KPX J Adieresis -20
+KPX J Agrave -20
+KPX J Amacron -20
+KPX J Aogonek -20
+KPX J Aring -20
+KPX J Atilde -20
+KPX J a -20
+KPX J aacute -20
+KPX J abreve -20
+KPX J acircumflex -20
+KPX J adieresis -20
+KPX J agrave -20
+KPX J amacron -20
+KPX J aogonek -20
+KPX J aring -20
+KPX J atilde -20
+KPX J comma -30
+KPX J period -30
+KPX J u -20
+KPX J uacute -20
+KPX J ucircumflex -20
+KPX J udieresis -20
+KPX J ugrave -20
+KPX J uhungarumlaut -20
+KPX J umacron -20
+KPX J uogonek -20
+KPX J uring -20
+KPX K O -50
+KPX K Oacute -50
+KPX K Ocircumflex -50
+KPX K Odieresis -50
+KPX K Ograve -50
+KPX K Ohungarumlaut -50
+KPX K Omacron -50
+KPX K Oslash -50
+KPX K Otilde -50
+KPX K e -40
+KPX K eacute -40
+KPX K ecaron -40
+KPX K ecircumflex -40
+KPX K edieresis -40
+KPX K edotaccent -40
+KPX K egrave -40
+KPX K emacron -40
+KPX K eogonek -40
+KPX K o -40
+KPX K oacute -40
+KPX K ocircumflex -40
+KPX K odieresis -40
+KPX K ograve -40
+KPX K ohungarumlaut -40
+KPX K omacron -40
+KPX K oslash -40
+KPX K otilde -40
+KPX K u -30
+KPX K uacute -30
+KPX K ucircumflex -30
+KPX K udieresis -30
+KPX K ugrave -30
+KPX K uhungarumlaut -30
+KPX K umacron -30
+KPX K uogonek -30
+KPX K uring -30
+KPX K y -50
+KPX K yacute -50
+KPX K ydieresis -50
+KPX Kcommaaccent O -50
+KPX Kcommaaccent Oacute -50
+KPX Kcommaaccent Ocircumflex -50
+KPX Kcommaaccent Odieresis -50
+KPX Kcommaaccent Ograve -50
+KPX Kcommaaccent Ohungarumlaut -50
+KPX Kcommaaccent Omacron -50
+KPX Kcommaaccent Oslash -50
+KPX Kcommaaccent Otilde -50
+KPX Kcommaaccent e -40
+KPX Kcommaaccent eacute -40
+KPX Kcommaaccent ecaron -40
+KPX Kcommaaccent ecircumflex -40
+KPX Kcommaaccent edieresis -40
+KPX Kcommaaccent edotaccent -40
+KPX Kcommaaccent egrave -40
+KPX Kcommaaccent emacron -40
+KPX Kcommaaccent eogonek -40
+KPX Kcommaaccent o -40
+KPX Kcommaaccent oacute -40
+KPX Kcommaaccent ocircumflex -40
+KPX Kcommaaccent odieresis -40
+KPX Kcommaaccent ograve -40
+KPX Kcommaaccent ohungarumlaut -40
+KPX Kcommaaccent omacron -40
+KPX Kcommaaccent oslash -40
+KPX Kcommaaccent otilde -40
+KPX Kcommaaccent u -30
+KPX Kcommaaccent uacute -30
+KPX Kcommaaccent ucircumflex -30
+KPX Kcommaaccent udieresis -30
+KPX Kcommaaccent ugrave -30
+KPX Kcommaaccent uhungarumlaut -30
+KPX Kcommaaccent umacron -30
+KPX Kcommaaccent uogonek -30
+KPX Kcommaaccent uring -30
+KPX Kcommaaccent y -50
+KPX Kcommaaccent yacute -50
+KPX Kcommaaccent ydieresis -50
+KPX L T -110
+KPX L Tcaron -110
+KPX L Tcommaaccent -110
+KPX L V -110
+KPX L W -70
+KPX L Y -140
+KPX L Yacute -140
+KPX L Ydieresis -140
+KPX L quotedblright -140
+KPX L quoteright -160
+KPX L y -30
+KPX L yacute -30
+KPX L ydieresis -30
+KPX Lacute T -110
+KPX Lacute Tcaron -110
+KPX Lacute Tcommaaccent -110
+KPX Lacute V -110
+KPX Lacute W -70
+KPX Lacute Y -140
+KPX Lacute Yacute -140
+KPX Lacute Ydieresis -140
+KPX Lacute quotedblright -140
+KPX Lacute quoteright -160
+KPX Lacute y -30
+KPX Lacute yacute -30
+KPX Lacute ydieresis -30
+KPX Lcaron T -110
+KPX Lcaron Tcaron -110
+KPX Lcaron Tcommaaccent -110
+KPX Lcaron V -110
+KPX Lcaron W -70
+KPX Lcaron Y -140
+KPX Lcaron Yacute -140
+KPX Lcaron Ydieresis -140
+KPX Lcaron quotedblright -140
+KPX Lcaron quoteright -160
+KPX Lcaron y -30
+KPX Lcaron yacute -30
+KPX Lcaron ydieresis -30
+KPX Lcommaaccent T -110
+KPX Lcommaaccent Tcaron -110
+KPX Lcommaaccent Tcommaaccent -110
+KPX Lcommaaccent V -110
+KPX Lcommaaccent W -70
+KPX Lcommaaccent Y -140
+KPX Lcommaaccent Yacute -140
+KPX Lcommaaccent Ydieresis -140
+KPX Lcommaaccent quotedblright -140
+KPX Lcommaaccent quoteright -160
+KPX Lcommaaccent y -30
+KPX Lcommaaccent yacute -30
+KPX Lcommaaccent ydieresis -30
+KPX Lslash T -110
+KPX Lslash Tcaron -110
+KPX Lslash Tcommaaccent -110
+KPX Lslash V -110
+KPX Lslash W -70
+KPX Lslash Y -140
+KPX Lslash Yacute -140
+KPX Lslash Ydieresis -140
+KPX Lslash quotedblright -140
+KPX Lslash quoteright -160
+KPX Lslash y -30
+KPX Lslash yacute -30
+KPX Lslash ydieresis -30
+KPX O A -20
+KPX O Aacute -20
+KPX O Abreve -20
+KPX O Acircumflex -20
+KPX O Adieresis -20
+KPX O Agrave -20
+KPX O Amacron -20
+KPX O Aogonek -20
+KPX O Aring -20
+KPX O Atilde -20
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -30
+KPX O X -60
+KPX O Y -70
+KPX O Yacute -70
+KPX O Ydieresis -70
+KPX O comma -40
+KPX O period -40
+KPX Oacute A -20
+KPX Oacute Aacute -20
+KPX Oacute Abreve -20
+KPX Oacute Acircumflex -20
+KPX Oacute Adieresis -20
+KPX Oacute Agrave -20
+KPX Oacute Amacron -20
+KPX Oacute Aogonek -20
+KPX Oacute Aring -20
+KPX Oacute Atilde -20
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -30
+KPX Oacute X -60
+KPX Oacute Y -70
+KPX Oacute Yacute -70
+KPX Oacute Ydieresis -70
+KPX Oacute comma -40
+KPX Oacute period -40
+KPX Ocircumflex A -20
+KPX Ocircumflex Aacute -20
+KPX Ocircumflex Abreve -20
+KPX Ocircumflex Acircumflex -20
+KPX Ocircumflex Adieresis -20
+KPX Ocircumflex Agrave -20
+KPX Ocircumflex Amacron -20
+KPX Ocircumflex Aogonek -20
+KPX Ocircumflex Aring -20
+KPX Ocircumflex Atilde -20
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -30
+KPX Ocircumflex X -60
+KPX Ocircumflex Y -70
+KPX Ocircumflex Yacute -70
+KPX Ocircumflex Ydieresis -70
+KPX Ocircumflex comma -40
+KPX Ocircumflex period -40
+KPX Odieresis A -20
+KPX Odieresis Aacute -20
+KPX Odieresis Abreve -20
+KPX Odieresis Acircumflex -20
+KPX Odieresis Adieresis -20
+KPX Odieresis Agrave -20
+KPX Odieresis Amacron -20
+KPX Odieresis Aogonek -20
+KPX Odieresis Aring -20
+KPX Odieresis Atilde -20
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -30
+KPX Odieresis X -60
+KPX Odieresis Y -70
+KPX Odieresis Yacute -70
+KPX Odieresis Ydieresis -70
+KPX Odieresis comma -40
+KPX Odieresis period -40
+KPX Ograve A -20
+KPX Ograve Aacute -20
+KPX Ograve Abreve -20
+KPX Ograve Acircumflex -20
+KPX Ograve Adieresis -20
+KPX Ograve Agrave -20
+KPX Ograve Amacron -20
+KPX Ograve Aogonek -20
+KPX Ograve Aring -20
+KPX Ograve Atilde -20
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -30
+KPX Ograve X -60
+KPX Ograve Y -70
+KPX Ograve Yacute -70
+KPX Ograve Ydieresis -70
+KPX Ograve comma -40
+KPX Ograve period -40
+KPX Ohungarumlaut A -20
+KPX Ohungarumlaut Aacute -20
+KPX Ohungarumlaut Abreve -20
+KPX Ohungarumlaut Acircumflex -20
+KPX Ohungarumlaut Adieresis -20
+KPX Ohungarumlaut Agrave -20
+KPX Ohungarumlaut Amacron -20
+KPX Ohungarumlaut Aogonek -20
+KPX Ohungarumlaut Aring -20
+KPX Ohungarumlaut Atilde -20
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -30
+KPX Ohungarumlaut X -60
+KPX Ohungarumlaut Y -70
+KPX Ohungarumlaut Yacute -70
+KPX Ohungarumlaut Ydieresis -70
+KPX Ohungarumlaut comma -40
+KPX Ohungarumlaut period -40
+KPX Omacron A -20
+KPX Omacron Aacute -20
+KPX Omacron Abreve -20
+KPX Omacron Acircumflex -20
+KPX Omacron Adieresis -20
+KPX Omacron Agrave -20
+KPX Omacron Amacron -20
+KPX Omacron Aogonek -20
+KPX Omacron Aring -20
+KPX Omacron Atilde -20
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -30
+KPX Omacron X -60
+KPX Omacron Y -70
+KPX Omacron Yacute -70
+KPX Omacron Ydieresis -70
+KPX Omacron comma -40
+KPX Omacron period -40
+KPX Oslash A -20
+KPX Oslash Aacute -20
+KPX Oslash Abreve -20
+KPX Oslash Acircumflex -20
+KPX Oslash Adieresis -20
+KPX Oslash Agrave -20
+KPX Oslash Amacron -20
+KPX Oslash Aogonek -20
+KPX Oslash Aring -20
+KPX Oslash Atilde -20
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -30
+KPX Oslash X -60
+KPX Oslash Y -70
+KPX Oslash Yacute -70
+KPX Oslash Ydieresis -70
+KPX Oslash comma -40
+KPX Oslash period -40
+KPX Otilde A -20
+KPX Otilde Aacute -20
+KPX Otilde Abreve -20
+KPX Otilde Acircumflex -20
+KPX Otilde Adieresis -20
+KPX Otilde Agrave -20
+KPX Otilde Amacron -20
+KPX Otilde Aogonek -20
+KPX Otilde Aring -20
+KPX Otilde Atilde -20
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -30
+KPX Otilde X -60
+KPX Otilde Y -70
+KPX Otilde Yacute -70
+KPX Otilde Ydieresis -70
+KPX Otilde comma -40
+KPX Otilde period -40
+KPX P A -120
+KPX P Aacute -120
+KPX P Abreve -120
+KPX P Acircumflex -120
+KPX P Adieresis -120
+KPX P Agrave -120
+KPX P Amacron -120
+KPX P Aogonek -120
+KPX P Aring -120
+KPX P Atilde -120
+KPX P a -40
+KPX P aacute -40
+KPX P abreve -40
+KPX P acircumflex -40
+KPX P adieresis -40
+KPX P agrave -40
+KPX P amacron -40
+KPX P aogonek -40
+KPX P aring -40
+KPX P atilde -40
+KPX P comma -180
+KPX P e -50
+KPX P eacute -50
+KPX P ecaron -50
+KPX P ecircumflex -50
+KPX P edieresis -50
+KPX P edotaccent -50
+KPX P egrave -50
+KPX P emacron -50
+KPX P eogonek -50
+KPX P o -50
+KPX P oacute -50
+KPX P ocircumflex -50
+KPX P odieresis -50
+KPX P ograve -50
+KPX P ohungarumlaut -50
+KPX P omacron -50
+KPX P oslash -50
+KPX P otilde -50
+KPX P period -180
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX R O -20
+KPX R Oacute -20
+KPX R Ocircumflex -20
+KPX R Odieresis -20
+KPX R Ograve -20
+KPX R Ohungarumlaut -20
+KPX R Omacron -20
+KPX R Oslash -20
+KPX R Otilde -20
+KPX R T -30
+KPX R Tcaron -30
+KPX R Tcommaaccent -30
+KPX R U -40
+KPX R Uacute -40
+KPX R Ucircumflex -40
+KPX R Udieresis -40
+KPX R Ugrave -40
+KPX R Uhungarumlaut -40
+KPX R Umacron -40
+KPX R Uogonek -40
+KPX R Uring -40
+KPX R V -50
+KPX R W -30
+KPX R Y -50
+KPX R Yacute -50
+KPX R Ydieresis -50
+KPX Racute O -20
+KPX Racute Oacute -20
+KPX Racute Ocircumflex -20
+KPX Racute Odieresis -20
+KPX Racute Ograve -20
+KPX Racute Ohungarumlaut -20
+KPX Racute Omacron -20
+KPX Racute Oslash -20
+KPX Racute Otilde -20
+KPX Racute T -30
+KPX Racute Tcaron -30
+KPX Racute Tcommaaccent -30
+KPX Racute U -40
+KPX Racute Uacute -40
+KPX Racute Ucircumflex -40
+KPX Racute Udieresis -40
+KPX Racute Ugrave -40
+KPX Racute Uhungarumlaut -40
+KPX Racute Umacron -40
+KPX Racute Uogonek -40
+KPX Racute Uring -40
+KPX Racute V -50
+KPX Racute W -30
+KPX Racute Y -50
+KPX Racute Yacute -50
+KPX Racute Ydieresis -50
+KPX Rcaron O -20
+KPX Rcaron Oacute -20
+KPX Rcaron Ocircumflex -20
+KPX Rcaron Odieresis -20
+KPX Rcaron Ograve -20
+KPX Rcaron Ohungarumlaut -20
+KPX Rcaron Omacron -20
+KPX Rcaron Oslash -20
+KPX Rcaron Otilde -20
+KPX Rcaron T -30
+KPX Rcaron Tcaron -30
+KPX Rcaron Tcommaaccent -30
+KPX Rcaron U -40
+KPX Rcaron Uacute -40
+KPX Rcaron Ucircumflex -40
+KPX Rcaron Udieresis -40
+KPX Rcaron Ugrave -40
+KPX Rcaron Uhungarumlaut -40
+KPX Rcaron Umacron -40
+KPX Rcaron Uogonek -40
+KPX Rcaron Uring -40
+KPX Rcaron V -50
+KPX Rcaron W -30
+KPX Rcaron Y -50
+KPX Rcaron Yacute -50
+KPX Rcaron Ydieresis -50
+KPX Rcommaaccent O -20
+KPX Rcommaaccent Oacute -20
+KPX Rcommaaccent Ocircumflex -20
+KPX Rcommaaccent Odieresis -20
+KPX Rcommaaccent Ograve -20
+KPX Rcommaaccent Ohungarumlaut -20
+KPX Rcommaaccent Omacron -20
+KPX Rcommaaccent Oslash -20
+KPX Rcommaaccent Otilde -20
+KPX Rcommaaccent T -30
+KPX Rcommaaccent Tcaron -30
+KPX Rcommaaccent Tcommaaccent -30
+KPX Rcommaaccent U -40
+KPX Rcommaaccent Uacute -40
+KPX Rcommaaccent Ucircumflex -40
+KPX Rcommaaccent Udieresis -40
+KPX Rcommaaccent Ugrave -40
+KPX Rcommaaccent Uhungarumlaut -40
+KPX Rcommaaccent Umacron -40
+KPX Rcommaaccent Uogonek -40
+KPX Rcommaaccent Uring -40
+KPX Rcommaaccent V -50
+KPX Rcommaaccent W -30
+KPX Rcommaaccent Y -50
+KPX Rcommaaccent Yacute -50
+KPX Rcommaaccent Ydieresis -50
+KPX S comma -20
+KPX S period -20
+KPX Sacute comma -20
+KPX Sacute period -20
+KPX Scaron comma -20
+KPX Scaron period -20
+KPX Scedilla comma -20
+KPX Scedilla period -20
+KPX Scommaaccent comma -20
+KPX Scommaaccent period -20
+KPX T A -120
+KPX T Aacute -120
+KPX T Abreve -120
+KPX T Acircumflex -120
+KPX T Adieresis -120
+KPX T Agrave -120
+KPX T Amacron -120
+KPX T Aogonek -120
+KPX T Aring -120
+KPX T Atilde -120
+KPX T O -40
+KPX T Oacute -40
+KPX T Ocircumflex -40
+KPX T Odieresis -40
+KPX T Ograve -40
+KPX T Ohungarumlaut -40
+KPX T Omacron -40
+KPX T Oslash -40
+KPX T Otilde -40
+KPX T a -120
+KPX T aacute -120
+KPX T abreve -60
+KPX T acircumflex -120
+KPX T adieresis -120
+KPX T agrave -120
+KPX T amacron -60
+KPX T aogonek -120
+KPX T aring -120
+KPX T atilde -60
+KPX T colon -20
+KPX T comma -120
+KPX T e -120
+KPX T eacute -120
+KPX T ecaron -120
+KPX T ecircumflex -120
+KPX T edieresis -120
+KPX T edotaccent -120
+KPX T egrave -60
+KPX T emacron -60
+KPX T eogonek -120
+KPX T hyphen -140
+KPX T o -120
+KPX T oacute -120
+KPX T ocircumflex -120
+KPX T odieresis -120
+KPX T ograve -120
+KPX T ohungarumlaut -120
+KPX T omacron -60
+KPX T oslash -120
+KPX T otilde -60
+KPX T period -120
+KPX T r -120
+KPX T racute -120
+KPX T rcaron -120
+KPX T rcommaaccent -120
+KPX T semicolon -20
+KPX T u -120
+KPX T uacute -120
+KPX T ucircumflex -120
+KPX T udieresis -120
+KPX T ugrave -120
+KPX T uhungarumlaut -120
+KPX T umacron -60
+KPX T uogonek -120
+KPX T uring -120
+KPX T w -120
+KPX T y -120
+KPX T yacute -120
+KPX T ydieresis -60
+KPX Tcaron A -120
+KPX Tcaron Aacute -120
+KPX Tcaron Abreve -120
+KPX Tcaron Acircumflex -120
+KPX Tcaron Adieresis -120
+KPX Tcaron Agrave -120
+KPX Tcaron Amacron -120
+KPX Tcaron Aogonek -120
+KPX Tcaron Aring -120
+KPX Tcaron Atilde -120
+KPX Tcaron O -40
+KPX Tcaron Oacute -40
+KPX Tcaron Ocircumflex -40
+KPX Tcaron Odieresis -40
+KPX Tcaron Ograve -40
+KPX Tcaron Ohungarumlaut -40
+KPX Tcaron Omacron -40
+KPX Tcaron Oslash -40
+KPX Tcaron Otilde -40
+KPX Tcaron a -120
+KPX Tcaron aacute -120
+KPX Tcaron abreve -60
+KPX Tcaron acircumflex -120
+KPX Tcaron adieresis -120
+KPX Tcaron agrave -120
+KPX Tcaron amacron -60
+KPX Tcaron aogonek -120
+KPX Tcaron aring -120
+KPX Tcaron atilde -60
+KPX Tcaron colon -20
+KPX Tcaron comma -120
+KPX Tcaron e -120
+KPX Tcaron eacute -120
+KPX Tcaron ecaron -120
+KPX Tcaron ecircumflex -120
+KPX Tcaron edieresis -120
+KPX Tcaron edotaccent -120
+KPX Tcaron egrave -60
+KPX Tcaron emacron -60
+KPX Tcaron eogonek -120
+KPX Tcaron hyphen -140
+KPX Tcaron o -120
+KPX Tcaron oacute -120
+KPX Tcaron ocircumflex -120
+KPX Tcaron odieresis -120
+KPX Tcaron ograve -120
+KPX Tcaron ohungarumlaut -120
+KPX Tcaron omacron -60
+KPX Tcaron oslash -120
+KPX Tcaron otilde -60
+KPX Tcaron period -120
+KPX Tcaron r -120
+KPX Tcaron racute -120
+KPX Tcaron rcaron -120
+KPX Tcaron rcommaaccent -120
+KPX Tcaron semicolon -20
+KPX Tcaron u -120
+KPX Tcaron uacute -120
+KPX Tcaron ucircumflex -120
+KPX Tcaron udieresis -120
+KPX Tcaron ugrave -120
+KPX Tcaron uhungarumlaut -120
+KPX Tcaron umacron -60
+KPX Tcaron uogonek -120
+KPX Tcaron uring -120
+KPX Tcaron w -120
+KPX Tcaron y -120
+KPX Tcaron yacute -120
+KPX Tcaron ydieresis -60
+KPX Tcommaaccent A -120
+KPX Tcommaaccent Aacute -120
+KPX Tcommaaccent Abreve -120
+KPX Tcommaaccent Acircumflex -120
+KPX Tcommaaccent Adieresis -120
+KPX Tcommaaccent Agrave -120
+KPX Tcommaaccent Amacron -120
+KPX Tcommaaccent Aogonek -120
+KPX Tcommaaccent Aring -120
+KPX Tcommaaccent Atilde -120
+KPX Tcommaaccent O -40
+KPX Tcommaaccent Oacute -40
+KPX Tcommaaccent Ocircumflex -40
+KPX Tcommaaccent Odieresis -40
+KPX Tcommaaccent Ograve -40
+KPX Tcommaaccent Ohungarumlaut -40
+KPX Tcommaaccent Omacron -40
+KPX Tcommaaccent Oslash -40
+KPX Tcommaaccent Otilde -40
+KPX Tcommaaccent a -120
+KPX Tcommaaccent aacute -120
+KPX Tcommaaccent abreve -60
+KPX Tcommaaccent acircumflex -120
+KPX Tcommaaccent adieresis -120
+KPX Tcommaaccent agrave -120
+KPX Tcommaaccent amacron -60
+KPX Tcommaaccent aogonek -120
+KPX Tcommaaccent aring -120
+KPX Tcommaaccent atilde -60
+KPX Tcommaaccent colon -20
+KPX Tcommaaccent comma -120
+KPX Tcommaaccent e -120
+KPX Tcommaaccent eacute -120
+KPX Tcommaaccent ecaron -120
+KPX Tcommaaccent ecircumflex -120
+KPX Tcommaaccent edieresis -120
+KPX Tcommaaccent edotaccent -120
+KPX Tcommaaccent egrave -60
+KPX Tcommaaccent emacron -60
+KPX Tcommaaccent eogonek -120
+KPX Tcommaaccent hyphen -140
+KPX Tcommaaccent o -120
+KPX Tcommaaccent oacute -120
+KPX Tcommaaccent ocircumflex -120
+KPX Tcommaaccent odieresis -120
+KPX Tcommaaccent ograve -120
+KPX Tcommaaccent ohungarumlaut -120
+KPX Tcommaaccent omacron -60
+KPX Tcommaaccent oslash -120
+KPX Tcommaaccent otilde -60
+KPX Tcommaaccent period -120
+KPX Tcommaaccent r -120
+KPX Tcommaaccent racute -120
+KPX Tcommaaccent rcaron -120
+KPX Tcommaaccent rcommaaccent -120
+KPX Tcommaaccent semicolon -20
+KPX Tcommaaccent u -120
+KPX Tcommaaccent uacute -120
+KPX Tcommaaccent ucircumflex -120
+KPX Tcommaaccent udieresis -120
+KPX Tcommaaccent ugrave -120
+KPX Tcommaaccent uhungarumlaut -120
+KPX Tcommaaccent umacron -60
+KPX Tcommaaccent uogonek -120
+KPX Tcommaaccent uring -120
+KPX Tcommaaccent w -120
+KPX Tcommaaccent y -120
+KPX Tcommaaccent yacute -120
+KPX Tcommaaccent ydieresis -60
+KPX U A -40
+KPX U Aacute -40
+KPX U Abreve -40
+KPX U Acircumflex -40
+KPX U Adieresis -40
+KPX U Agrave -40
+KPX U Amacron -40
+KPX U Aogonek -40
+KPX U Aring -40
+KPX U Atilde -40
+KPX U comma -40
+KPX U period -40
+KPX Uacute A -40
+KPX Uacute Aacute -40
+KPX Uacute Abreve -40
+KPX Uacute Acircumflex -40
+KPX Uacute Adieresis -40
+KPX Uacute Agrave -40
+KPX Uacute Amacron -40
+KPX Uacute Aogonek -40
+KPX Uacute Aring -40
+KPX Uacute Atilde -40
+KPX Uacute comma -40
+KPX Uacute period -40
+KPX Ucircumflex A -40
+KPX Ucircumflex Aacute -40
+KPX Ucircumflex Abreve -40
+KPX Ucircumflex Acircumflex -40
+KPX Ucircumflex Adieresis -40
+KPX Ucircumflex Agrave -40
+KPX Ucircumflex Amacron -40
+KPX Ucircumflex Aogonek -40
+KPX Ucircumflex Aring -40
+KPX Ucircumflex Atilde -40
+KPX Ucircumflex comma -40
+KPX Ucircumflex period -40
+KPX Udieresis A -40
+KPX Udieresis Aacute -40
+KPX Udieresis Abreve -40
+KPX Udieresis Acircumflex -40
+KPX Udieresis Adieresis -40
+KPX Udieresis Agrave -40
+KPX Udieresis Amacron -40
+KPX Udieresis Aogonek -40
+KPX Udieresis Aring -40
+KPX Udieresis Atilde -40
+KPX Udieresis comma -40
+KPX Udieresis period -40
+KPX Ugrave A -40
+KPX Ugrave Aacute -40
+KPX Ugrave Abreve -40
+KPX Ugrave Acircumflex -40
+KPX Ugrave Adieresis -40
+KPX Ugrave Agrave -40
+KPX Ugrave Amacron -40
+KPX Ugrave Aogonek -40
+KPX Ugrave Aring -40
+KPX Ugrave Atilde -40
+KPX Ugrave comma -40
+KPX Ugrave period -40
+KPX Uhungarumlaut A -40
+KPX Uhungarumlaut Aacute -40
+KPX Uhungarumlaut Abreve -40
+KPX Uhungarumlaut Acircumflex -40
+KPX Uhungarumlaut Adieresis -40
+KPX Uhungarumlaut Agrave -40
+KPX Uhungarumlaut Amacron -40
+KPX Uhungarumlaut Aogonek -40
+KPX Uhungarumlaut Aring -40
+KPX Uhungarumlaut Atilde -40
+KPX Uhungarumlaut comma -40
+KPX Uhungarumlaut period -40
+KPX Umacron A -40
+KPX Umacron Aacute -40
+KPX Umacron Abreve -40
+KPX Umacron Acircumflex -40
+KPX Umacron Adieresis -40
+KPX Umacron Agrave -40
+KPX Umacron Amacron -40
+KPX Umacron Aogonek -40
+KPX Umacron Aring -40
+KPX Umacron Atilde -40
+KPX Umacron comma -40
+KPX Umacron period -40
+KPX Uogonek A -40
+KPX Uogonek Aacute -40
+KPX Uogonek Abreve -40
+KPX Uogonek Acircumflex -40
+KPX Uogonek Adieresis -40
+KPX Uogonek Agrave -40
+KPX Uogonek Amacron -40
+KPX Uogonek Aogonek -40
+KPX Uogonek Aring -40
+KPX Uogonek Atilde -40
+KPX Uogonek comma -40
+KPX Uogonek period -40
+KPX Uring A -40
+KPX Uring Aacute -40
+KPX Uring Abreve -40
+KPX Uring Acircumflex -40
+KPX Uring Adieresis -40
+KPX Uring Agrave -40
+KPX Uring Amacron -40
+KPX Uring Aogonek -40
+KPX Uring Aring -40
+KPX Uring Atilde -40
+KPX Uring comma -40
+KPX Uring period -40
+KPX V A -80
+KPX V Aacute -80
+KPX V Abreve -80
+KPX V Acircumflex -80
+KPX V Adieresis -80
+KPX V Agrave -80
+KPX V Amacron -80
+KPX V Aogonek -80
+KPX V Aring -80
+KPX V Atilde -80
+KPX V G -40
+KPX V Gbreve -40
+KPX V Gcommaaccent -40
+KPX V O -40
+KPX V Oacute -40
+KPX V Ocircumflex -40
+KPX V Odieresis -40
+KPX V Ograve -40
+KPX V Ohungarumlaut -40
+KPX V Omacron -40
+KPX V Oslash -40
+KPX V Otilde -40
+KPX V a -70
+KPX V aacute -70
+KPX V abreve -70
+KPX V acircumflex -70
+KPX V adieresis -70
+KPX V agrave -70
+KPX V amacron -70
+KPX V aogonek -70
+KPX V aring -70
+KPX V atilde -70
+KPX V colon -40
+KPX V comma -125
+KPX V e -80
+KPX V eacute -80
+KPX V ecaron -80
+KPX V ecircumflex -80
+KPX V edieresis -80
+KPX V edotaccent -80
+KPX V egrave -80
+KPX V emacron -80
+KPX V eogonek -80
+KPX V hyphen -80
+KPX V o -80
+KPX V oacute -80
+KPX V ocircumflex -80
+KPX V odieresis -80
+KPX V ograve -80
+KPX V ohungarumlaut -80
+KPX V omacron -80
+KPX V oslash -80
+KPX V otilde -80
+KPX V period -125
+KPX V semicolon -40
+KPX V u -70
+KPX V uacute -70
+KPX V ucircumflex -70
+KPX V udieresis -70
+KPX V ugrave -70
+KPX V uhungarumlaut -70
+KPX V umacron -70
+KPX V uogonek -70
+KPX V uring -70
+KPX W A -50
+KPX W Aacute -50
+KPX W Abreve -50
+KPX W Acircumflex -50
+KPX W Adieresis -50
+KPX W Agrave -50
+KPX W Amacron -50
+KPX W Aogonek -50
+KPX W Aring -50
+KPX W Atilde -50
+KPX W O -20
+KPX W Oacute -20
+KPX W Ocircumflex -20
+KPX W Odieresis -20
+KPX W Ograve -20
+KPX W Ohungarumlaut -20
+KPX W Omacron -20
+KPX W Oslash -20
+KPX W Otilde -20
+KPX W a -40
+KPX W aacute -40
+KPX W abreve -40
+KPX W acircumflex -40
+KPX W adieresis -40
+KPX W agrave -40
+KPX W amacron -40
+KPX W aogonek -40
+KPX W aring -40
+KPX W atilde -40
+KPX W comma -80
+KPX W e -30
+KPX W eacute -30
+KPX W ecaron -30
+KPX W ecircumflex -30
+KPX W edieresis -30
+KPX W edotaccent -30
+KPX W egrave -30
+KPX W emacron -30
+KPX W eogonek -30
+KPX W hyphen -40
+KPX W o -30
+KPX W oacute -30
+KPX W ocircumflex -30
+KPX W odieresis -30
+KPX W ograve -30
+KPX W ohungarumlaut -30
+KPX W omacron -30
+KPX W oslash -30
+KPX W otilde -30
+KPX W period -80
+KPX W u -30
+KPX W uacute -30
+KPX W ucircumflex -30
+KPX W udieresis -30
+KPX W ugrave -30
+KPX W uhungarumlaut -30
+KPX W umacron -30
+KPX W uogonek -30
+KPX W uring -30
+KPX W y -20
+KPX W yacute -20
+KPX W ydieresis -20
+KPX Y A -110
+KPX Y Aacute -110
+KPX Y Abreve -110
+KPX Y Acircumflex -110
+KPX Y Adieresis -110
+KPX Y Agrave -110
+KPX Y Amacron -110
+KPX Y Aogonek -110
+KPX Y Aring -110
+KPX Y Atilde -110
+KPX Y O -85
+KPX Y Oacute -85
+KPX Y Ocircumflex -85
+KPX Y Odieresis -85
+KPX Y Ograve -85
+KPX Y Ohungarumlaut -85
+KPX Y Omacron -85
+KPX Y Oslash -85
+KPX Y Otilde -85
+KPX Y a -140
+KPX Y aacute -140
+KPX Y abreve -70
+KPX Y acircumflex -140
+KPX Y adieresis -140
+KPX Y agrave -140
+KPX Y amacron -70
+KPX Y aogonek -140
+KPX Y aring -140
+KPX Y atilde -140
+KPX Y colon -60
+KPX Y comma -140
+KPX Y e -140
+KPX Y eacute -140
+KPX Y ecaron -140
+KPX Y ecircumflex -140
+KPX Y edieresis -140
+KPX Y edotaccent -140
+KPX Y egrave -140
+KPX Y emacron -70
+KPX Y eogonek -140
+KPX Y hyphen -140
+KPX Y i -20
+KPX Y iacute -20
+KPX Y iogonek -20
+KPX Y o -140
+KPX Y oacute -140
+KPX Y ocircumflex -140
+KPX Y odieresis -140
+KPX Y ograve -140
+KPX Y ohungarumlaut -140
+KPX Y omacron -140
+KPX Y oslash -140
+KPX Y otilde -140
+KPX Y period -140
+KPX Y semicolon -60
+KPX Y u -110
+KPX Y uacute -110
+KPX Y ucircumflex -110
+KPX Y udieresis -110
+KPX Y ugrave -110
+KPX Y uhungarumlaut -110
+KPX Y umacron -110
+KPX Y uogonek -110
+KPX Y uring -110
+KPX Yacute A -110
+KPX Yacute Aacute -110
+KPX Yacute Abreve -110
+KPX Yacute Acircumflex -110
+KPX Yacute Adieresis -110
+KPX Yacute Agrave -110
+KPX Yacute Amacron -110
+KPX Yacute Aogonek -110
+KPX Yacute Aring -110
+KPX Yacute Atilde -110
+KPX Yacute O -85
+KPX Yacute Oacute -85
+KPX Yacute Ocircumflex -85
+KPX Yacute Odieresis -85
+KPX Yacute Ograve -85
+KPX Yacute Ohungarumlaut -85
+KPX Yacute Omacron -85
+KPX Yacute Oslash -85
+KPX Yacute Otilde -85
+KPX Yacute a -140
+KPX Yacute aacute -140
+KPX Yacute abreve -70
+KPX Yacute acircumflex -140
+KPX Yacute adieresis -140
+KPX Yacute agrave -140
+KPX Yacute amacron -70
+KPX Yacute aogonek -140
+KPX Yacute aring -140
+KPX Yacute atilde -70
+KPX Yacute colon -60
+KPX Yacute comma -140
+KPX Yacute e -140
+KPX Yacute eacute -140
+KPX Yacute ecaron -140
+KPX Yacute ecircumflex -140
+KPX Yacute edieresis -140
+KPX Yacute edotaccent -140
+KPX Yacute egrave -140
+KPX Yacute emacron -70
+KPX Yacute eogonek -140
+KPX Yacute hyphen -140
+KPX Yacute i -20
+KPX Yacute iacute -20
+KPX Yacute iogonek -20
+KPX Yacute o -140
+KPX Yacute oacute -140
+KPX Yacute ocircumflex -140
+KPX Yacute odieresis -140
+KPX Yacute ograve -140
+KPX Yacute ohungarumlaut -140
+KPX Yacute omacron -70
+KPX Yacute oslash -140
+KPX Yacute otilde -140
+KPX Yacute period -140
+KPX Yacute semicolon -60
+KPX Yacute u -110
+KPX Yacute uacute -110
+KPX Yacute ucircumflex -110
+KPX Yacute udieresis -110
+KPX Yacute ugrave -110
+KPX Yacute uhungarumlaut -110
+KPX Yacute umacron -110
+KPX Yacute uogonek -110
+KPX Yacute uring -110
+KPX Ydieresis A -110
+KPX Ydieresis Aacute -110
+KPX Ydieresis Abreve -110
+KPX Ydieresis Acircumflex -110
+KPX Ydieresis Adieresis -110
+KPX Ydieresis Agrave -110
+KPX Ydieresis Amacron -110
+KPX Ydieresis Aogonek -110
+KPX Ydieresis Aring -110
+KPX Ydieresis Atilde -110
+KPX Ydieresis O -85
+KPX Ydieresis Oacute -85
+KPX Ydieresis Ocircumflex -85
+KPX Ydieresis Odieresis -85
+KPX Ydieresis Ograve -85
+KPX Ydieresis Ohungarumlaut -85
+KPX Ydieresis Omacron -85
+KPX Ydieresis Oslash -85
+KPX Ydieresis Otilde -85
+KPX Ydieresis a -140
+KPX Ydieresis aacute -140
+KPX Ydieresis abreve -70
+KPX Ydieresis acircumflex -140
+KPX Ydieresis adieresis -140
+KPX Ydieresis agrave -140
+KPX Ydieresis amacron -70
+KPX Ydieresis aogonek -140
+KPX Ydieresis aring -140
+KPX Ydieresis atilde -70
+KPX Ydieresis colon -60
+KPX Ydieresis comma -140
+KPX Ydieresis e -140
+KPX Ydieresis eacute -140
+KPX Ydieresis ecaron -140
+KPX Ydieresis ecircumflex -140
+KPX Ydieresis edieresis -140
+KPX Ydieresis edotaccent -140
+KPX Ydieresis egrave -140
+KPX Ydieresis emacron -70
+KPX Ydieresis eogonek -140
+KPX Ydieresis hyphen -140
+KPX Ydieresis i -20
+KPX Ydieresis iacute -20
+KPX Ydieresis iogonek -20
+KPX Ydieresis o -140
+KPX Ydieresis oacute -140
+KPX Ydieresis ocircumflex -140
+KPX Ydieresis odieresis -140
+KPX Ydieresis ograve -140
+KPX Ydieresis ohungarumlaut -140
+KPX Ydieresis omacron -140
+KPX Ydieresis oslash -140
+KPX Ydieresis otilde -140
+KPX Ydieresis period -140
+KPX Ydieresis semicolon -60
+KPX Ydieresis u -110
+KPX Ydieresis uacute -110
+KPX Ydieresis ucircumflex -110
+KPX Ydieresis udieresis -110
+KPX Ydieresis ugrave -110
+KPX Ydieresis uhungarumlaut -110
+KPX Ydieresis umacron -110
+KPX Ydieresis uogonek -110
+KPX Ydieresis uring -110
+KPX a v -20
+KPX a w -20
+KPX a y -30
+KPX a yacute -30
+KPX a ydieresis -30
+KPX aacute v -20
+KPX aacute w -20
+KPX aacute y -30
+KPX aacute yacute -30
+KPX aacute ydieresis -30
+KPX abreve v -20
+KPX abreve w -20
+KPX abreve y -30
+KPX abreve yacute -30
+KPX abreve ydieresis -30
+KPX acircumflex v -20
+KPX acircumflex w -20
+KPX acircumflex y -30
+KPX acircumflex yacute -30
+KPX acircumflex ydieresis -30
+KPX adieresis v -20
+KPX adieresis w -20
+KPX adieresis y -30
+KPX adieresis yacute -30
+KPX adieresis ydieresis -30
+KPX agrave v -20
+KPX agrave w -20
+KPX agrave y -30
+KPX agrave yacute -30
+KPX agrave ydieresis -30
+KPX amacron v -20
+KPX amacron w -20
+KPX amacron y -30
+KPX amacron yacute -30
+KPX amacron ydieresis -30
+KPX aogonek v -20
+KPX aogonek w -20
+KPX aogonek y -30
+KPX aogonek yacute -30
+KPX aogonek ydieresis -30
+KPX aring v -20
+KPX aring w -20
+KPX aring y -30
+KPX aring yacute -30
+KPX aring ydieresis -30
+KPX atilde v -20
+KPX atilde w -20
+KPX atilde y -30
+KPX atilde yacute -30
+KPX atilde ydieresis -30
+KPX b b -10
+KPX b comma -40
+KPX b l -20
+KPX b lacute -20
+KPX b lcommaaccent -20
+KPX b lslash -20
+KPX b period -40
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX b v -20
+KPX b y -20
+KPX b yacute -20
+KPX b ydieresis -20
+KPX c comma -15
+KPX c k -20
+KPX c kcommaaccent -20
+KPX cacute comma -15
+KPX cacute k -20
+KPX cacute kcommaaccent -20
+KPX ccaron comma -15
+KPX ccaron k -20
+KPX ccaron kcommaaccent -20
+KPX ccedilla comma -15
+KPX ccedilla k -20
+KPX ccedilla kcommaaccent -20
+KPX colon space -50
+KPX comma quotedblright -100
+KPX comma quoteright -100
+KPX e comma -15
+KPX e period -15
+KPX e v -30
+KPX e w -20
+KPX e x -30
+KPX e y -20
+KPX e yacute -20
+KPX e ydieresis -20
+KPX eacute comma -15
+KPX eacute period -15
+KPX eacute v -30
+KPX eacute w -20
+KPX eacute x -30
+KPX eacute y -20
+KPX eacute yacute -20
+KPX eacute ydieresis -20
+KPX ecaron comma -15
+KPX ecaron period -15
+KPX ecaron v -30
+KPX ecaron w -20
+KPX ecaron x -30
+KPX ecaron y -20
+KPX ecaron yacute -20
+KPX ecaron ydieresis -20
+KPX ecircumflex comma -15
+KPX ecircumflex period -15
+KPX ecircumflex v -30
+KPX ecircumflex w -20
+KPX ecircumflex x -30
+KPX ecircumflex y -20
+KPX ecircumflex yacute -20
+KPX ecircumflex ydieresis -20
+KPX edieresis comma -15
+KPX edieresis period -15
+KPX edieresis v -30
+KPX edieresis w -20
+KPX edieresis x -30
+KPX edieresis y -20
+KPX edieresis yacute -20
+KPX edieresis ydieresis -20
+KPX edotaccent comma -15
+KPX edotaccent period -15
+KPX edotaccent v -30
+KPX edotaccent w -20
+KPX edotaccent x -30
+KPX edotaccent y -20
+KPX edotaccent yacute -20
+KPX edotaccent ydieresis -20
+KPX egrave comma -15
+KPX egrave period -15
+KPX egrave v -30
+KPX egrave w -20
+KPX egrave x -30
+KPX egrave y -20
+KPX egrave yacute -20
+KPX egrave ydieresis -20
+KPX emacron comma -15
+KPX emacron period -15
+KPX emacron v -30
+KPX emacron w -20
+KPX emacron x -30
+KPX emacron y -20
+KPX emacron yacute -20
+KPX emacron ydieresis -20
+KPX eogonek comma -15
+KPX eogonek period -15
+KPX eogonek v -30
+KPX eogonek w -20
+KPX eogonek x -30
+KPX eogonek y -20
+KPX eogonek yacute -20
+KPX eogonek ydieresis -20
+KPX f a -30
+KPX f aacute -30
+KPX f abreve -30
+KPX f acircumflex -30
+KPX f adieresis -30
+KPX f agrave -30
+KPX f amacron -30
+KPX f aogonek -30
+KPX f aring -30
+KPX f atilde -30
+KPX f comma -30
+KPX f dotlessi -28
+KPX f e -30
+KPX f eacute -30
+KPX f ecaron -30
+KPX f ecircumflex -30
+KPX f edieresis -30
+KPX f edotaccent -30
+KPX f egrave -30
+KPX f emacron -30
+KPX f eogonek -30
+KPX f o -30
+KPX f oacute -30
+KPX f ocircumflex -30
+KPX f odieresis -30
+KPX f ograve -30
+KPX f ohungarumlaut -30
+KPX f omacron -30
+KPX f oslash -30
+KPX f otilde -30
+KPX f period -30
+KPX f quotedblright 60
+KPX f quoteright 50
+KPX g r -10
+KPX g racute -10
+KPX g rcaron -10
+KPX g rcommaaccent -10
+KPX gbreve r -10
+KPX gbreve racute -10
+KPX gbreve rcaron -10
+KPX gbreve rcommaaccent -10
+KPX gcommaaccent r -10
+KPX gcommaaccent racute -10
+KPX gcommaaccent rcaron -10
+KPX gcommaaccent rcommaaccent -10
+KPX h y -30
+KPX h yacute -30
+KPX h ydieresis -30
+KPX k e -20
+KPX k eacute -20
+KPX k ecaron -20
+KPX k ecircumflex -20
+KPX k edieresis -20
+KPX k edotaccent -20
+KPX k egrave -20
+KPX k emacron -20
+KPX k eogonek -20
+KPX k o -20
+KPX k oacute -20
+KPX k ocircumflex -20
+KPX k odieresis -20
+KPX k ograve -20
+KPX k ohungarumlaut -20
+KPX k omacron -20
+KPX k oslash -20
+KPX k otilde -20
+KPX kcommaaccent e -20
+KPX kcommaaccent eacute -20
+KPX kcommaaccent ecaron -20
+KPX kcommaaccent ecircumflex -20
+KPX kcommaaccent edieresis -20
+KPX kcommaaccent edotaccent -20
+KPX kcommaaccent egrave -20
+KPX kcommaaccent emacron -20
+KPX kcommaaccent eogonek -20
+KPX kcommaaccent o -20
+KPX kcommaaccent oacute -20
+KPX kcommaaccent ocircumflex -20
+KPX kcommaaccent odieresis -20
+KPX kcommaaccent ograve -20
+KPX kcommaaccent ohungarumlaut -20
+KPX kcommaaccent omacron -20
+KPX kcommaaccent oslash -20
+KPX kcommaaccent otilde -20
+KPX m u -10
+KPX m uacute -10
+KPX m ucircumflex -10
+KPX m udieresis -10
+KPX m ugrave -10
+KPX m uhungarumlaut -10
+KPX m umacron -10
+KPX m uogonek -10
+KPX m uring -10
+KPX m y -15
+KPX m yacute -15
+KPX m ydieresis -15
+KPX n u -10
+KPX n uacute -10
+KPX n ucircumflex -10
+KPX n udieresis -10
+KPX n ugrave -10
+KPX n uhungarumlaut -10
+KPX n umacron -10
+KPX n uogonek -10
+KPX n uring -10
+KPX n v -20
+KPX n y -15
+KPX n yacute -15
+KPX n ydieresis -15
+KPX nacute u -10
+KPX nacute uacute -10
+KPX nacute ucircumflex -10
+KPX nacute udieresis -10
+KPX nacute ugrave -10
+KPX nacute uhungarumlaut -10
+KPX nacute umacron -10
+KPX nacute uogonek -10
+KPX nacute uring -10
+KPX nacute v -20
+KPX nacute y -15
+KPX nacute yacute -15
+KPX nacute ydieresis -15
+KPX ncaron u -10
+KPX ncaron uacute -10
+KPX ncaron ucircumflex -10
+KPX ncaron udieresis -10
+KPX ncaron ugrave -10
+KPX ncaron uhungarumlaut -10
+KPX ncaron umacron -10
+KPX ncaron uogonek -10
+KPX ncaron uring -10
+KPX ncaron v -20
+KPX ncaron y -15
+KPX ncaron yacute -15
+KPX ncaron ydieresis -15
+KPX ncommaaccent u -10
+KPX ncommaaccent uacute -10
+KPX ncommaaccent ucircumflex -10
+KPX ncommaaccent udieresis -10
+KPX ncommaaccent ugrave -10
+KPX ncommaaccent uhungarumlaut -10
+KPX ncommaaccent umacron -10
+KPX ncommaaccent uogonek -10
+KPX ncommaaccent uring -10
+KPX ncommaaccent v -20
+KPX ncommaaccent y -15
+KPX ncommaaccent yacute -15
+KPX ncommaaccent ydieresis -15
+KPX ntilde u -10
+KPX ntilde uacute -10
+KPX ntilde ucircumflex -10
+KPX ntilde udieresis -10
+KPX ntilde ugrave -10
+KPX ntilde uhungarumlaut -10
+KPX ntilde umacron -10
+KPX ntilde uogonek -10
+KPX ntilde uring -10
+KPX ntilde v -20
+KPX ntilde y -15
+KPX ntilde yacute -15
+KPX ntilde ydieresis -15
+KPX o comma -40
+KPX o period -40
+KPX o v -15
+KPX o w -15
+KPX o x -30
+KPX o y -30
+KPX o yacute -30
+KPX o ydieresis -30
+KPX oacute comma -40
+KPX oacute period -40
+KPX oacute v -15
+KPX oacute w -15
+KPX oacute x -30
+KPX oacute y -30
+KPX oacute yacute -30
+KPX oacute ydieresis -30
+KPX ocircumflex comma -40
+KPX ocircumflex period -40
+KPX ocircumflex v -15
+KPX ocircumflex w -15
+KPX ocircumflex x -30
+KPX ocircumflex y -30
+KPX ocircumflex yacute -30
+KPX ocircumflex ydieresis -30
+KPX odieresis comma -40
+KPX odieresis period -40
+KPX odieresis v -15
+KPX odieresis w -15
+KPX odieresis x -30
+KPX odieresis y -30
+KPX odieresis yacute -30
+KPX odieresis ydieresis -30
+KPX ograve comma -40
+KPX ograve period -40
+KPX ograve v -15
+KPX ograve w -15
+KPX ograve x -30
+KPX ograve y -30
+KPX ograve yacute -30
+KPX ograve ydieresis -30
+KPX ohungarumlaut comma -40
+KPX ohungarumlaut period -40
+KPX ohungarumlaut v -15
+KPX ohungarumlaut w -15
+KPX ohungarumlaut x -30
+KPX ohungarumlaut y -30
+KPX ohungarumlaut yacute -30
+KPX ohungarumlaut ydieresis -30
+KPX omacron comma -40
+KPX omacron period -40
+KPX omacron v -15
+KPX omacron w -15
+KPX omacron x -30
+KPX omacron y -30
+KPX omacron yacute -30
+KPX omacron ydieresis -30
+KPX oslash a -55
+KPX oslash aacute -55
+KPX oslash abreve -55
+KPX oslash acircumflex -55
+KPX oslash adieresis -55
+KPX oslash agrave -55
+KPX oslash amacron -55
+KPX oslash aogonek -55
+KPX oslash aring -55
+KPX oslash atilde -55
+KPX oslash b -55
+KPX oslash c -55
+KPX oslash cacute -55
+KPX oslash ccaron -55
+KPX oslash ccedilla -55
+KPX oslash comma -95
+KPX oslash d -55
+KPX oslash dcroat -55
+KPX oslash e -55
+KPX oslash eacute -55
+KPX oslash ecaron -55
+KPX oslash ecircumflex -55
+KPX oslash edieresis -55
+KPX oslash edotaccent -55
+KPX oslash egrave -55
+KPX oslash emacron -55
+KPX oslash eogonek -55
+KPX oslash f -55
+KPX oslash g -55
+KPX oslash gbreve -55
+KPX oslash gcommaaccent -55
+KPX oslash h -55
+KPX oslash i -55
+KPX oslash iacute -55
+KPX oslash icircumflex -55
+KPX oslash idieresis -55
+KPX oslash igrave -55
+KPX oslash imacron -55
+KPX oslash iogonek -55
+KPX oslash j -55
+KPX oslash k -55
+KPX oslash kcommaaccent -55
+KPX oslash l -55
+KPX oslash lacute -55
+KPX oslash lcommaaccent -55
+KPX oslash lslash -55
+KPX oslash m -55
+KPX oslash n -55
+KPX oslash nacute -55
+KPX oslash ncaron -55
+KPX oslash ncommaaccent -55
+KPX oslash ntilde -55
+KPX oslash o -55
+KPX oslash oacute -55
+KPX oslash ocircumflex -55
+KPX oslash odieresis -55
+KPX oslash ograve -55
+KPX oslash ohungarumlaut -55
+KPX oslash omacron -55
+KPX oslash oslash -55
+KPX oslash otilde -55
+KPX oslash p -55
+KPX oslash period -95
+KPX oslash q -55
+KPX oslash r -55
+KPX oslash racute -55
+KPX oslash rcaron -55
+KPX oslash rcommaaccent -55
+KPX oslash s -55
+KPX oslash sacute -55
+KPX oslash scaron -55
+KPX oslash scedilla -55
+KPX oslash scommaaccent -55
+KPX oslash t -55
+KPX oslash tcommaaccent -55
+KPX oslash u -55
+KPX oslash uacute -55
+KPX oslash ucircumflex -55
+KPX oslash udieresis -55
+KPX oslash ugrave -55
+KPX oslash uhungarumlaut -55
+KPX oslash umacron -55
+KPX oslash uogonek -55
+KPX oslash uring -55
+KPX oslash v -70
+KPX oslash w -70
+KPX oslash x -85
+KPX oslash y -70
+KPX oslash yacute -70
+KPX oslash ydieresis -70
+KPX oslash z -55
+KPX oslash zacute -55
+KPX oslash zcaron -55
+KPX oslash zdotaccent -55
+KPX otilde comma -40
+KPX otilde period -40
+KPX otilde v -15
+KPX otilde w -15
+KPX otilde x -30
+KPX otilde y -30
+KPX otilde yacute -30
+KPX otilde ydieresis -30
+KPX p comma -35
+KPX p period -35
+KPX p y -30
+KPX p yacute -30
+KPX p ydieresis -30
+KPX period quotedblright -100
+KPX period quoteright -100
+KPX period space -60
+KPX quotedblright space -40
+KPX quoteleft quoteleft -57
+KPX quoteright d -50
+KPX quoteright dcroat -50
+KPX quoteright quoteright -57
+KPX quoteright r -50
+KPX quoteright racute -50
+KPX quoteright rcaron -50
+KPX quoteright rcommaaccent -50
+KPX quoteright s -50
+KPX quoteright sacute -50
+KPX quoteright scaron -50
+KPX quoteright scedilla -50
+KPX quoteright scommaaccent -50
+KPX quoteright space -70
+KPX r a -10
+KPX r aacute -10
+KPX r abreve -10
+KPX r acircumflex -10
+KPX r adieresis -10
+KPX r agrave -10
+KPX r amacron -10
+KPX r aogonek -10
+KPX r aring -10
+KPX r atilde -10
+KPX r colon 30
+KPX r comma -50
+KPX r i 15
+KPX r iacute 15
+KPX r icircumflex 15
+KPX r idieresis 15
+KPX r igrave 15
+KPX r imacron 15
+KPX r iogonek 15
+KPX r k 15
+KPX r kcommaaccent 15
+KPX r l 15
+KPX r lacute 15
+KPX r lcommaaccent 15
+KPX r lslash 15
+KPX r m 25
+KPX r n 25
+KPX r nacute 25
+KPX r ncaron 25
+KPX r ncommaaccent 25
+KPX r ntilde 25
+KPX r p 30
+KPX r period -50
+KPX r semicolon 30
+KPX r t 40
+KPX r tcommaaccent 40
+KPX r u 15
+KPX r uacute 15
+KPX r ucircumflex 15
+KPX r udieresis 15
+KPX r ugrave 15
+KPX r uhungarumlaut 15
+KPX r umacron 15
+KPX r uogonek 15
+KPX r uring 15
+KPX r v 30
+KPX r y 30
+KPX r yacute 30
+KPX r ydieresis 30
+KPX racute a -10
+KPX racute aacute -10
+KPX racute abreve -10
+KPX racute acircumflex -10
+KPX racute adieresis -10
+KPX racute agrave -10
+KPX racute amacron -10
+KPX racute aogonek -10
+KPX racute aring -10
+KPX racute atilde -10
+KPX racute colon 30
+KPX racute comma -50
+KPX racute i 15
+KPX racute iacute 15
+KPX racute icircumflex 15
+KPX racute idieresis 15
+KPX racute igrave 15
+KPX racute imacron 15
+KPX racute iogonek 15
+KPX racute k 15
+KPX racute kcommaaccent 15
+KPX racute l 15
+KPX racute lacute 15
+KPX racute lcommaaccent 15
+KPX racute lslash 15
+KPX racute m 25
+KPX racute n 25
+KPX racute nacute 25
+KPX racute ncaron 25
+KPX racute ncommaaccent 25
+KPX racute ntilde 25
+KPX racute p 30
+KPX racute period -50
+KPX racute semicolon 30
+KPX racute t 40
+KPX racute tcommaaccent 40
+KPX racute u 15
+KPX racute uacute 15
+KPX racute ucircumflex 15
+KPX racute udieresis 15
+KPX racute ugrave 15
+KPX racute uhungarumlaut 15
+KPX racute umacron 15
+KPX racute uogonek 15
+KPX racute uring 15
+KPX racute v 30
+KPX racute y 30
+KPX racute yacute 30
+KPX racute ydieresis 30
+KPX rcaron a -10
+KPX rcaron aacute -10
+KPX rcaron abreve -10
+KPX rcaron acircumflex -10
+KPX rcaron adieresis -10
+KPX rcaron agrave -10
+KPX rcaron amacron -10
+KPX rcaron aogonek -10
+KPX rcaron aring -10
+KPX rcaron atilde -10
+KPX rcaron colon 30
+KPX rcaron comma -50
+KPX rcaron i 15
+KPX rcaron iacute 15
+KPX rcaron icircumflex 15
+KPX rcaron idieresis 15
+KPX rcaron igrave 15
+KPX rcaron imacron 15
+KPX rcaron iogonek 15
+KPX rcaron k 15
+KPX rcaron kcommaaccent 15
+KPX rcaron l 15
+KPX rcaron lacute 15
+KPX rcaron lcommaaccent 15
+KPX rcaron lslash 15
+KPX rcaron m 25
+KPX rcaron n 25
+KPX rcaron nacute 25
+KPX rcaron ncaron 25
+KPX rcaron ncommaaccent 25
+KPX rcaron ntilde 25
+KPX rcaron p 30
+KPX rcaron period -50
+KPX rcaron semicolon 30
+KPX rcaron t 40
+KPX rcaron tcommaaccent 40
+KPX rcaron u 15
+KPX rcaron uacute 15
+KPX rcaron ucircumflex 15
+KPX rcaron udieresis 15
+KPX rcaron ugrave 15
+KPX rcaron uhungarumlaut 15
+KPX rcaron umacron 15
+KPX rcaron uogonek 15
+KPX rcaron uring 15
+KPX rcaron v 30
+KPX rcaron y 30
+KPX rcaron yacute 30
+KPX rcaron ydieresis 30
+KPX rcommaaccent a -10
+KPX rcommaaccent aacute -10
+KPX rcommaaccent abreve -10
+KPX rcommaaccent acircumflex -10
+KPX rcommaaccent adieresis -10
+KPX rcommaaccent agrave -10
+KPX rcommaaccent amacron -10
+KPX rcommaaccent aogonek -10
+KPX rcommaaccent aring -10
+KPX rcommaaccent atilde -10
+KPX rcommaaccent colon 30
+KPX rcommaaccent comma -50
+KPX rcommaaccent i 15
+KPX rcommaaccent iacute 15
+KPX rcommaaccent icircumflex 15
+KPX rcommaaccent idieresis 15
+KPX rcommaaccent igrave 15
+KPX rcommaaccent imacron 15
+KPX rcommaaccent iogonek 15
+KPX rcommaaccent k 15
+KPX rcommaaccent kcommaaccent 15
+KPX rcommaaccent l 15
+KPX rcommaaccent lacute 15
+KPX rcommaaccent lcommaaccent 15
+KPX rcommaaccent lslash 15
+KPX rcommaaccent m 25
+KPX rcommaaccent n 25
+KPX rcommaaccent nacute 25
+KPX rcommaaccent ncaron 25
+KPX rcommaaccent ncommaaccent 25
+KPX rcommaaccent ntilde 25
+KPX rcommaaccent p 30
+KPX rcommaaccent period -50
+KPX rcommaaccent semicolon 30
+KPX rcommaaccent t 40
+KPX rcommaaccent tcommaaccent 40
+KPX rcommaaccent u 15
+KPX rcommaaccent uacute 15
+KPX rcommaaccent ucircumflex 15
+KPX rcommaaccent udieresis 15
+KPX rcommaaccent ugrave 15
+KPX rcommaaccent uhungarumlaut 15
+KPX rcommaaccent umacron 15
+KPX rcommaaccent uogonek 15
+KPX rcommaaccent uring 15
+KPX rcommaaccent v 30
+KPX rcommaaccent y 30
+KPX rcommaaccent yacute 30
+KPX rcommaaccent ydieresis 30
+KPX s comma -15
+KPX s period -15
+KPX s w -30
+KPX sacute comma -15
+KPX sacute period -15
+KPX sacute w -30
+KPX scaron comma -15
+KPX scaron period -15
+KPX scaron w -30
+KPX scedilla comma -15
+KPX scedilla period -15
+KPX scedilla w -30
+KPX scommaaccent comma -15
+KPX scommaaccent period -15
+KPX scommaaccent w -30
+KPX semicolon space -50
+KPX space T -50
+KPX space Tcaron -50
+KPX space Tcommaaccent -50
+KPX space V -50
+KPX space W -40
+KPX space Y -90
+KPX space Yacute -90
+KPX space Ydieresis -90
+KPX space quotedblleft -30
+KPX space quoteleft -60
+KPX v a -25
+KPX v aacute -25
+KPX v abreve -25
+KPX v acircumflex -25
+KPX v adieresis -25
+KPX v agrave -25
+KPX v amacron -25
+KPX v aogonek -25
+KPX v aring -25
+KPX v atilde -25
+KPX v comma -80
+KPX v e -25
+KPX v eacute -25
+KPX v ecaron -25
+KPX v ecircumflex -25
+KPX v edieresis -25
+KPX v edotaccent -25
+KPX v egrave -25
+KPX v emacron -25
+KPX v eogonek -25
+KPX v o -25
+KPX v oacute -25
+KPX v ocircumflex -25
+KPX v odieresis -25
+KPX v ograve -25
+KPX v ohungarumlaut -25
+KPX v omacron -25
+KPX v oslash -25
+KPX v otilde -25
+KPX v period -80
+KPX w a -15
+KPX w aacute -15
+KPX w abreve -15
+KPX w acircumflex -15
+KPX w adieresis -15
+KPX w agrave -15
+KPX w amacron -15
+KPX w aogonek -15
+KPX w aring -15
+KPX w atilde -15
+KPX w comma -60
+KPX w e -10
+KPX w eacute -10
+KPX w ecaron -10
+KPX w ecircumflex -10
+KPX w edieresis -10
+KPX w edotaccent -10
+KPX w egrave -10
+KPX w emacron -10
+KPX w eogonek -10
+KPX w o -10
+KPX w oacute -10
+KPX w ocircumflex -10
+KPX w odieresis -10
+KPX w ograve -10
+KPX w ohungarumlaut -10
+KPX w omacron -10
+KPX w oslash -10
+KPX w otilde -10
+KPX w period -60
+KPX x e -30
+KPX x eacute -30
+KPX x ecaron -30
+KPX x ecircumflex -30
+KPX x edieresis -30
+KPX x edotaccent -30
+KPX x egrave -30
+KPX x emacron -30
+KPX x eogonek -30
+KPX y a -20
+KPX y aacute -20
+KPX y abreve -20
+KPX y acircumflex -20
+KPX y adieresis -20
+KPX y agrave -20
+KPX y amacron -20
+KPX y aogonek -20
+KPX y aring -20
+KPX y atilde -20
+KPX y comma -100
+KPX y e -20
+KPX y eacute -20
+KPX y ecaron -20
+KPX y ecircumflex -20
+KPX y edieresis -20
+KPX y edotaccent -20
+KPX y egrave -20
+KPX y emacron -20
+KPX y eogonek -20
+KPX y o -20
+KPX y oacute -20
+KPX y ocircumflex -20
+KPX y odieresis -20
+KPX y ograve -20
+KPX y ohungarumlaut -20
+KPX y omacron -20
+KPX y oslash -20
+KPX y otilde -20
+KPX y period -100
+KPX yacute a -20
+KPX yacute aacute -20
+KPX yacute abreve -20
+KPX yacute acircumflex -20
+KPX yacute adieresis -20
+KPX yacute agrave -20
+KPX yacute amacron -20
+KPX yacute aogonek -20
+KPX yacute aring -20
+KPX yacute atilde -20
+KPX yacute comma -100
+KPX yacute e -20
+KPX yacute eacute -20
+KPX yacute ecaron -20
+KPX yacute ecircumflex -20
+KPX yacute edieresis -20
+KPX yacute edotaccent -20
+KPX yacute egrave -20
+KPX yacute emacron -20
+KPX yacute eogonek -20
+KPX yacute o -20
+KPX yacute oacute -20
+KPX yacute ocircumflex -20
+KPX yacute odieresis -20
+KPX yacute ograve -20
+KPX yacute ohungarumlaut -20
+KPX yacute omacron -20
+KPX yacute oslash -20
+KPX yacute otilde -20
+KPX yacute period -100
+KPX ydieresis a -20
+KPX ydieresis aacute -20
+KPX ydieresis abreve -20
+KPX ydieresis acircumflex -20
+KPX ydieresis adieresis -20
+KPX ydieresis agrave -20
+KPX ydieresis amacron -20
+KPX ydieresis aogonek -20
+KPX ydieresis aring -20
+KPX ydieresis atilde -20
+KPX ydieresis comma -100
+KPX ydieresis e -20
+KPX ydieresis eacute -20
+KPX ydieresis ecaron -20
+KPX ydieresis ecircumflex -20
+KPX ydieresis edieresis -20
+KPX ydieresis edotaccent -20
+KPX ydieresis egrave -20
+KPX ydieresis emacron -20
+KPX ydieresis eogonek -20
+KPX ydieresis o -20
+KPX ydieresis oacute -20
+KPX ydieresis ocircumflex -20
+KPX ydieresis odieresis -20
+KPX ydieresis ograve -20
+KPX ydieresis ohungarumlaut -20
+KPX ydieresis omacron -20
+KPX ydieresis oslash -20
+KPX ydieresis otilde -20
+KPX ydieresis period -100
+KPX z e -15
+KPX z eacute -15
+KPX z ecaron -15
+KPX z ecircumflex -15
+KPX z edieresis -15
+KPX z edotaccent -15
+KPX z egrave -15
+KPX z emacron -15
+KPX z eogonek -15
+KPX z o -15
+KPX z oacute -15
+KPX z ocircumflex -15
+KPX z odieresis -15
+KPX z ograve -15
+KPX z ohungarumlaut -15
+KPX z omacron -15
+KPX z oslash -15
+KPX z otilde -15
+KPX zacute e -15
+KPX zacute eacute -15
+KPX zacute ecaron -15
+KPX zacute ecircumflex -15
+KPX zacute edieresis -15
+KPX zacute edotaccent -15
+KPX zacute egrave -15
+KPX zacute emacron -15
+KPX zacute eogonek -15
+KPX zacute o -15
+KPX zacute oacute -15
+KPX zacute ocircumflex -15
+KPX zacute odieresis -15
+KPX zacute ograve -15
+KPX zacute ohungarumlaut -15
+KPX zacute omacron -15
+KPX zacute oslash -15
+KPX zacute otilde -15
+KPX zcaron e -15
+KPX zcaron eacute -15
+KPX zcaron ecaron -15
+KPX zcaron ecircumflex -15
+KPX zcaron edieresis -15
+KPX zcaron edotaccent -15
+KPX zcaron egrave -15
+KPX zcaron emacron -15
+KPX zcaron eogonek -15
+KPX zcaron o -15
+KPX zcaron oacute -15
+KPX zcaron ocircumflex -15
+KPX zcaron odieresis -15
+KPX zcaron ograve -15
+KPX zcaron ohungarumlaut -15
+KPX zcaron omacron -15
+KPX zcaron oslash -15
+KPX zcaron otilde -15
+KPX zdotaccent e -15
+KPX zdotaccent eacute -15
+KPX zdotaccent ecaron -15
+KPX zdotaccent ecircumflex -15
+KPX zdotaccent edieresis -15
+KPX zdotaccent edotaccent -15
+KPX zdotaccent egrave -15
+KPX zdotaccent emacron -15
+KPX zdotaccent eogonek -15
+KPX zdotaccent o -15
+KPX zdotaccent oacute -15
+KPX zdotaccent ocircumflex -15
+KPX zdotaccent odieresis -15
+KPX zdotaccent ograve -15
+KPX zdotaccent ohungarumlaut -15
+KPX zdotaccent omacron -15
+KPX zdotaccent oslash -15
+KPX zdotaccent otilde -15
+EndKernPairs
+EndKernData
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Helvetica.afm 2004-05-26 16:06:20.000000000 +0000
@@ -0,0 +1,3051 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu May 1 12:38:23 1997
+Comment UniqueID 43054
+Comment VMusage 37069 48094
+FontName Helvetica
+FullName Helvetica
+FamilyName Helvetica
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -166 -225 1000 931
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 523
+Ascender 718
+Descender -207
+StdHW 76
+StdVW 88
+StartCharMetrics 315
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 278 ; N exclam ; B 90 0 187 718 ;
+C 34 ; WX 355 ; N quotedbl ; B 70 463 285 718 ;
+C 35 ; WX 556 ; N numbersign ; B 28 0 529 688 ;
+C 36 ; WX 556 ; N dollar ; B 32 -115 520 775 ;
+C 37 ; WX 889 ; N percent ; B 39 -19 850 703 ;
+C 38 ; WX 667 ; N ampersand ; B 44 -15 645 718 ;
+C 39 ; WX 222 ; N quoteright ; B 53 463 157 718 ;
+C 40 ; WX 333 ; N parenleft ; B 68 -207 299 733 ;
+C 41 ; WX 333 ; N parenright ; B 34 -207 265 733 ;
+C 42 ; WX 389 ; N asterisk ; B 39 431 349 718 ;
+C 43 ; WX 584 ; N plus ; B 39 0 545 505 ;
+C 44 ; WX 278 ; N comma ; B 87 -147 191 106 ;
+C 45 ; WX 333 ; N hyphen ; B 44 232 289 322 ;
+C 46 ; WX 278 ; N period ; B 87 0 191 106 ;
+C 47 ; WX 278 ; N slash ; B -17 -19 295 737 ;
+C 48 ; WX 556 ; N zero ; B 37 -19 519 703 ;
+C 49 ; WX 556 ; N one ; B 101 0 359 703 ;
+C 50 ; WX 556 ; N two ; B 26 0 507 703 ;
+C 51 ; WX 556 ; N three ; B 34 -19 522 703 ;
+C 52 ; WX 556 ; N four ; B 25 0 523 703 ;
+C 53 ; WX 556 ; N five ; B 32 -19 514 688 ;
+C 54 ; WX 556 ; N six ; B 38 -19 518 703 ;
+C 55 ; WX 556 ; N seven ; B 37 0 523 688 ;
+C 56 ; WX 556 ; N eight ; B 38 -19 517 703 ;
+C 57 ; WX 556 ; N nine ; B 42 -19 514 703 ;
+C 58 ; WX 278 ; N colon ; B 87 0 191 516 ;
+C 59 ; WX 278 ; N semicolon ; B 87 -147 191 516 ;
+C 60 ; WX 584 ; N less ; B 48 11 536 495 ;
+C 61 ; WX 584 ; N equal ; B 39 115 545 390 ;
+C 62 ; WX 584 ; N greater ; B 48 11 536 495 ;
+C 63 ; WX 556 ; N question ; B 56 0 492 727 ;
+C 64 ; WX 1015 ; N at ; B 147 -19 868 737 ;
+C 65 ; WX 667 ; N A ; B 14 0 654 718 ;
+C 66 ; WX 667 ; N B ; B 74 0 627 718 ;
+C 67 ; WX 722 ; N C ; B 44 -19 681 737 ;
+C 68 ; WX 722 ; N D ; B 81 0 674 718 ;
+C 69 ; WX 667 ; N E ; B 86 0 616 718 ;
+C 70 ; WX 611 ; N F ; B 86 0 583 718 ;
+C 71 ; WX 778 ; N G ; B 48 -19 704 737 ;
+C 72 ; WX 722 ; N H ; B 77 0 646 718 ;
+C 73 ; WX 278 ; N I ; B 91 0 188 718 ;
+C 74 ; WX 500 ; N J ; B 17 -19 428 718 ;
+C 75 ; WX 667 ; N K ; B 76 0 663 718 ;
+C 76 ; WX 556 ; N L ; B 76 0 537 718 ;
+C 77 ; WX 833 ; N M ; B 73 0 761 718 ;
+C 78 ; WX 722 ; N N ; B 76 0 646 718 ;
+C 79 ; WX 778 ; N O ; B 39 -19 739 737 ;
+C 80 ; WX 667 ; N P ; B 86 0 622 718 ;
+C 81 ; WX 778 ; N Q ; B 39 -56 739 737 ;
+C 82 ; WX 722 ; N R ; B 88 0 684 718 ;
+C 83 ; WX 667 ; N S ; B 49 -19 620 737 ;
+C 84 ; WX 611 ; N T ; B 14 0 597 718 ;
+C 85 ; WX 722 ; N U ; B 79 -19 644 718 ;
+C 86 ; WX 667 ; N V ; B 20 0 647 718 ;
+C 87 ; WX 944 ; N W ; B 16 0 928 718 ;
+C 88 ; WX 667 ; N X ; B 19 0 648 718 ;
+C 89 ; WX 667 ; N Y ; B 14 0 653 718 ;
+C 90 ; WX 611 ; N Z ; B 23 0 588 718 ;
+C 91 ; WX 278 ; N bracketleft ; B 63 -196 250 722 ;
+C 92 ; WX 278 ; N backslash ; B -17 -19 295 737 ;
+C 93 ; WX 278 ; N bracketright ; B 28 -196 215 722 ;
+C 94 ; WX 469 ; N asciicircum ; B -14 264 483 688 ;
+C 95 ; WX 556 ; N underscore ; B 0 -125 556 -75 ;
+C 96 ; WX 222 ; N quoteleft ; B 65 470 169 725 ;
+C 97 ; WX 556 ; N a ; B 36 -15 530 538 ;
+C 98 ; WX 556 ; N b ; B 58 -15 517 718 ;
+C 99 ; WX 500 ; N c ; B 30 -15 477 538 ;
+C 100 ; WX 556 ; N d ; B 35 -15 499 718 ;
+C 101 ; WX 556 ; N e ; B 40 -15 516 538 ;
+C 102 ; WX 278 ; N f ; B 14 0 262 728 ; L i fi ; L l fl ;
+C 103 ; WX 556 ; N g ; B 40 -220 499 538 ;
+C 104 ; WX 556 ; N h ; B 65 0 491 718 ;
+C 105 ; WX 222 ; N i ; B 67 0 155 718 ;
+C 106 ; WX 222 ; N j ; B -16 -210 155 718 ;
+C 107 ; WX 500 ; N k ; B 67 0 501 718 ;
+C 108 ; WX 222 ; N l ; B 67 0 155 718 ;
+C 109 ; WX 833 ; N m ; B 65 0 769 538 ;
+C 110 ; WX 556 ; N n ; B 65 0 491 538 ;
+C 111 ; WX 556 ; N o ; B 35 -14 521 538 ;
+C 112 ; WX 556 ; N p ; B 58 -207 517 538 ;
+C 113 ; WX 556 ; N q ; B 35 -207 494 538 ;
+C 114 ; WX 333 ; N r ; B 77 0 332 538 ;
+C 115 ; WX 500 ; N s ; B 32 -15 464 538 ;
+C 116 ; WX 278 ; N t ; B 14 -7 257 669 ;
+C 117 ; WX 556 ; N u ; B 68 -15 489 523 ;
+C 118 ; WX 500 ; N v ; B 8 0 492 523 ;
+C 119 ; WX 722 ; N w ; B 14 0 709 523 ;
+C 120 ; WX 500 ; N x ; B 11 0 490 523 ;
+C 121 ; WX 500 ; N y ; B 11 -214 489 523 ;
+C 122 ; WX 500 ; N z ; B 31 0 469 523 ;
+C 123 ; WX 334 ; N braceleft ; B 42 -196 292 722 ;
+C 124 ; WX 260 ; N bar ; B 94 -225 167 775 ;
+C 125 ; WX 334 ; N braceright ; B 42 -196 292 722 ;
+C 126 ; WX 584 ; N asciitilde ; B 61 180 523 326 ;
+C 161 ; WX 333 ; N exclamdown ; B 118 -195 215 523 ;
+C 162 ; WX 556 ; N cent ; B 51 -115 513 623 ;
+C 163 ; WX 556 ; N sterling ; B 33 -16 539 718 ;
+C 164 ; WX 167 ; N fraction ; B -166 -19 333 703 ;
+C 165 ; WX 556 ; N yen ; B 3 0 553 688 ;
+C 166 ; WX 556 ; N florin ; B -11 -207 501 737 ;
+C 167 ; WX 556 ; N section ; B 43 -191 512 737 ;
+C 168 ; WX 556 ; N currency ; B 28 99 528 603 ;
+C 169 ; WX 191 ; N quotesingle ; B 59 463 132 718 ;
+C 170 ; WX 333 ; N quotedblleft ; B 38 470 307 725 ;
+C 171 ; WX 556 ; N guillemotleft ; B 97 108 459 446 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 88 108 245 446 ;
+C 173 ; WX 333 ; N guilsinglright ; B 88 108 245 446 ;
+C 174 ; WX 500 ; N fi ; B 14 0 434 728 ;
+C 175 ; WX 500 ; N fl ; B 14 0 432 728 ;
+C 177 ; WX 556 ; N endash ; B 0 240 556 313 ;
+C 178 ; WX 556 ; N dagger ; B 43 -159 514 718 ;
+C 179 ; WX 556 ; N daggerdbl ; B 43 -159 514 718 ;
+C 180 ; WX 278 ; N periodcentered ; B 77 190 202 315 ;
+C 182 ; WX 537 ; N paragraph ; B 18 -173 497 718 ;
+C 183 ; WX 350 ; N bullet ; B 18 202 333 517 ;
+C 184 ; WX 222 ; N quotesinglbase ; B 53 -149 157 106 ;
+C 185 ; WX 333 ; N quotedblbase ; B 26 -149 295 106 ;
+C 186 ; WX 333 ; N quotedblright ; B 26 463 295 718 ;
+C 187 ; WX 556 ; N guillemotright ; B 97 108 459 446 ;
+C 188 ; WX 1000 ; N ellipsis ; B 115 0 885 106 ;
+C 189 ; WX 1000 ; N perthousand ; B 7 -19 994 703 ;
+C 191 ; WX 611 ; N questiondown ; B 91 -201 527 525 ;
+C 193 ; WX 333 ; N grave ; B 14 593 211 734 ;
+C 194 ; WX 333 ; N acute ; B 122 593 319 734 ;
+C 195 ; WX 333 ; N circumflex ; B 21 593 312 734 ;
+C 196 ; WX 333 ; N tilde ; B -4 606 337 722 ;
+C 197 ; WX 333 ; N macron ; B 10 627 323 684 ;
+C 198 ; WX 333 ; N breve ; B 13 595 321 731 ;
+C 199 ; WX 333 ; N dotaccent ; B 121 604 212 706 ;
+C 200 ; WX 333 ; N dieresis ; B 40 604 293 706 ;
+C 202 ; WX 333 ; N ring ; B 75 572 259 756 ;
+C 203 ; WX 333 ; N cedilla ; B 45 -225 259 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 31 593 409 734 ;
+C 206 ; WX 333 ; N ogonek ; B 73 -225 287 0 ;
+C 207 ; WX 333 ; N caron ; B 21 593 312 734 ;
+C 208 ; WX 1000 ; N emdash ; B 0 240 1000 313 ;
+C 225 ; WX 1000 ; N AE ; B 8 0 951 718 ;
+C 227 ; WX 370 ; N ordfeminine ; B 24 405 346 737 ;
+C 232 ; WX 556 ; N Lslash ; B -20 0 537 718 ;
+C 233 ; WX 778 ; N Oslash ; B 39 -19 740 737 ;
+C 234 ; WX 1000 ; N OE ; B 36 -19 965 737 ;
+C 235 ; WX 365 ; N ordmasculine ; B 25 405 341 737 ;
+C 241 ; WX 889 ; N ae ; B 36 -15 847 538 ;
+C 245 ; WX 278 ; N dotlessi ; B 95 0 183 523 ;
+C 248 ; WX 222 ; N lslash ; B -20 0 242 718 ;
+C 249 ; WX 611 ; N oslash ; B 28 -22 537 545 ;
+C 250 ; WX 944 ; N oe ; B 35 -15 902 538 ;
+C 251 ; WX 611 ; N germandbls ; B 67 -15 571 728 ;
+C -1 ; WX 278 ; N Idieresis ; B 13 0 266 901 ;
+C -1 ; WX 556 ; N eacute ; B 40 -15 516 734 ;
+C -1 ; WX 556 ; N abreve ; B 36 -15 530 731 ;
+C -1 ; WX 556 ; N uhungarumlaut ; B 68 -15 521 734 ;
+C -1 ; WX 556 ; N ecaron ; B 40 -15 516 734 ;
+C -1 ; WX 667 ; N Ydieresis ; B 14 0 653 901 ;
+C -1 ; WX 584 ; N divide ; B 39 -19 545 524 ;
+C -1 ; WX 667 ; N Yacute ; B 14 0 653 929 ;
+C -1 ; WX 667 ; N Acircumflex ; B 14 0 654 929 ;
+C -1 ; WX 556 ; N aacute ; B 36 -15 530 734 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 79 -19 644 929 ;
+C -1 ; WX 500 ; N yacute ; B 11 -214 489 734 ;
+C -1 ; WX 500 ; N scommaaccent ; B 32 -225 464 538 ;
+C -1 ; WX 556 ; N ecircumflex ; B 40 -15 516 734 ;
+C -1 ; WX 722 ; N Uring ; B 79 -19 644 931 ;
+C -1 ; WX 722 ; N Udieresis ; B 79 -19 644 901 ;
+C -1 ; WX 556 ; N aogonek ; B 36 -220 547 538 ;
+C -1 ; WX 722 ; N Uacute ; B 79 -19 644 929 ;
+C -1 ; WX 556 ; N uogonek ; B 68 -225 519 523 ;
+C -1 ; WX 667 ; N Edieresis ; B 86 0 616 901 ;
+C -1 ; WX 722 ; N Dcroat ; B 0 0 674 718 ;
+C -1 ; WX 250 ; N commaaccent ; B 87 -225 181 -40 ;
+C -1 ; WX 737 ; N copyright ; B -14 -19 752 737 ;
+C -1 ; WX 667 ; N Emacron ; B 86 0 616 879 ;
+C -1 ; WX 500 ; N ccaron ; B 30 -15 477 734 ;
+C -1 ; WX 556 ; N aring ; B 36 -15 530 756 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B 76 -225 646 718 ;
+C -1 ; WX 222 ; N lacute ; B 67 0 264 929 ;
+C -1 ; WX 556 ; N agrave ; B 36 -15 530 734 ;
+C -1 ; WX 611 ; N Tcommaaccent ; B 14 -225 597 718 ;
+C -1 ; WX 722 ; N Cacute ; B 44 -19 681 929 ;
+C -1 ; WX 556 ; N atilde ; B 36 -15 530 722 ;
+C -1 ; WX 667 ; N Edotaccent ; B 86 0 616 901 ;
+C -1 ; WX 500 ; N scaron ; B 32 -15 464 734 ;
+C -1 ; WX 500 ; N scedilla ; B 32 -225 464 538 ;
+C -1 ; WX 278 ; N iacute ; B 95 0 292 734 ;
+C -1 ; WX 471 ; N lozenge ; B 10 0 462 728 ;
+C -1 ; WX 722 ; N Rcaron ; B 88 0 684 929 ;
+C -1 ; WX 778 ; N Gcommaaccent ; B 48 -225 704 737 ;
+C -1 ; WX 556 ; N ucircumflex ; B 68 -15 489 734 ;
+C -1 ; WX 556 ; N acircumflex ; B 36 -15 530 734 ;
+C -1 ; WX 667 ; N Amacron ; B 14 0 654 879 ;
+C -1 ; WX 333 ; N rcaron ; B 61 0 352 734 ;
+C -1 ; WX 500 ; N ccedilla ; B 30 -225 477 538 ;
+C -1 ; WX 611 ; N Zdotaccent ; B 23 0 588 901 ;
+C -1 ; WX 667 ; N Thorn ; B 86 0 622 718 ;
+C -1 ; WX 778 ; N Omacron ; B 39 -19 739 879 ;
+C -1 ; WX 722 ; N Racute ; B 88 0 684 929 ;
+C -1 ; WX 667 ; N Sacute ; B 49 -19 620 929 ;
+C -1 ; WX 643 ; N dcaron ; B 35 -15 655 718 ;
+C -1 ; WX 722 ; N Umacron ; B 79 -19 644 879 ;
+C -1 ; WX 556 ; N uring ; B 68 -15 489 756 ;
+C -1 ; WX 333 ; N threesuperior ; B 5 270 325 703 ;
+C -1 ; WX 778 ; N Ograve ; B 39 -19 739 929 ;
+C -1 ; WX 667 ; N Agrave ; B 14 0 654 929 ;
+C -1 ; WX 667 ; N Abreve ; B 14 0 654 926 ;
+C -1 ; WX 584 ; N multiply ; B 39 0 545 506 ;
+C -1 ; WX 556 ; N uacute ; B 68 -15 489 734 ;
+C -1 ; WX 611 ; N Tcaron ; B 14 0 597 929 ;
+C -1 ; WX 476 ; N partialdiff ; B 13 -38 463 714 ;
+C -1 ; WX 500 ; N ydieresis ; B 11 -214 489 706 ;
+C -1 ; WX 722 ; N Nacute ; B 76 0 646 929 ;
+C -1 ; WX 278 ; N icircumflex ; B -6 0 285 734 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 86 0 616 929 ;
+C -1 ; WX 556 ; N adieresis ; B 36 -15 530 706 ;
+C -1 ; WX 556 ; N edieresis ; B 40 -15 516 706 ;
+C -1 ; WX 500 ; N cacute ; B 30 -15 477 734 ;
+C -1 ; WX 556 ; N nacute ; B 65 0 491 734 ;
+C -1 ; WX 556 ; N umacron ; B 68 -15 489 684 ;
+C -1 ; WX 722 ; N Ncaron ; B 76 0 646 929 ;
+C -1 ; WX 278 ; N Iacute ; B 91 0 292 929 ;
+C -1 ; WX 584 ; N plusminus ; B 39 0 545 506 ;
+C -1 ; WX 260 ; N brokenbar ; B 94 -150 167 700 ;
+C -1 ; WX 737 ; N registered ; B -14 -19 752 737 ;
+C -1 ; WX 778 ; N Gbreve ; B 48 -19 704 926 ;
+C -1 ; WX 278 ; N Idotaccent ; B 91 0 188 901 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 586 706 ;
+C -1 ; WX 667 ; N Egrave ; B 86 0 616 929 ;
+C -1 ; WX 333 ; N racute ; B 77 0 332 734 ;
+C -1 ; WX 556 ; N omacron ; B 35 -14 521 684 ;
+C -1 ; WX 611 ; N Zacute ; B 23 0 588 929 ;
+C -1 ; WX 611 ; N Zcaron ; B 23 0 588 929 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 523 674 ;
+C -1 ; WX 722 ; N Eth ; B 0 0 674 718 ;
+C -1 ; WX 722 ; N Ccedilla ; B 44 -225 681 737 ;
+C -1 ; WX 222 ; N lcommaaccent ; B 67 -225 167 718 ;
+C -1 ; WX 317 ; N tcaron ; B 14 -7 329 808 ;
+C -1 ; WX 556 ; N eogonek ; B 40 -225 516 538 ;
+C -1 ; WX 722 ; N Uogonek ; B 79 -225 644 718 ;
+C -1 ; WX 667 ; N Aacute ; B 14 0 654 929 ;
+C -1 ; WX 667 ; N Adieresis ; B 14 0 654 901 ;
+C -1 ; WX 556 ; N egrave ; B 40 -15 516 734 ;
+C -1 ; WX 500 ; N zacute ; B 31 0 469 734 ;
+C -1 ; WX 222 ; N iogonek ; B -31 -225 183 718 ;
+C -1 ; WX 778 ; N Oacute ; B 39 -19 739 929 ;
+C -1 ; WX 556 ; N oacute ; B 35 -14 521 734 ;
+C -1 ; WX 556 ; N amacron ; B 36 -15 530 684 ;
+C -1 ; WX 500 ; N sacute ; B 32 -15 464 734 ;
+C -1 ; WX 278 ; N idieresis ; B 13 0 266 706 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 39 -19 739 929 ;
+C -1 ; WX 722 ; N Ugrave ; B 79 -19 644 929 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 556 ; N thorn ; B 58 -207 517 718 ;
+C -1 ; WX 333 ; N twosuperior ; B 4 281 323 703 ;
+C -1 ; WX 778 ; N Odieresis ; B 39 -19 739 901 ;
+C -1 ; WX 556 ; N mu ; B 68 -207 489 523 ;
+C -1 ; WX 278 ; N igrave ; B -13 0 184 734 ;
+C -1 ; WX 556 ; N ohungarumlaut ; B 35 -14 521 734 ;
+C -1 ; WX 667 ; N Eogonek ; B 86 -220 633 718 ;
+C -1 ; WX 556 ; N dcroat ; B 35 -15 550 718 ;
+C -1 ; WX 834 ; N threequarters ; B 45 -19 810 703 ;
+C -1 ; WX 667 ; N Scedilla ; B 49 -225 620 737 ;
+C -1 ; WX 299 ; N lcaron ; B 67 0 311 718 ;
+C -1 ; WX 667 ; N Kcommaaccent ; B 76 -225 663 718 ;
+C -1 ; WX 556 ; N Lacute ; B 76 0 537 929 ;
+C -1 ; WX 1000 ; N trademark ; B 46 306 903 718 ;
+C -1 ; WX 556 ; N edotaccent ; B 40 -15 516 706 ;
+C -1 ; WX 278 ; N Igrave ; B -13 0 188 929 ;
+C -1 ; WX 278 ; N Imacron ; B -17 0 296 879 ;
+C -1 ; WX 556 ; N Lcaron ; B 76 0 537 718 ;
+C -1 ; WX 834 ; N onehalf ; B 43 -19 773 703 ;
+C -1 ; WX 549 ; N lessequal ; B 26 0 523 674 ;
+C -1 ; WX 556 ; N ocircumflex ; B 35 -14 521 734 ;
+C -1 ; WX 556 ; N ntilde ; B 65 0 491 722 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 79 -19 644 929 ;
+C -1 ; WX 667 ; N Eacute ; B 86 0 616 929 ;
+C -1 ; WX 556 ; N emacron ; B 40 -15 516 684 ;
+C -1 ; WX 556 ; N gbreve ; B 40 -220 499 731 ;
+C -1 ; WX 834 ; N onequarter ; B 73 -19 756 703 ;
+C -1 ; WX 667 ; N Scaron ; B 49 -19 620 929 ;
+C -1 ; WX 667 ; N Scommaaccent ; B 49 -225 620 737 ;
+C -1 ; WX 778 ; N Ohungarumlaut ; B 39 -19 739 929 ;
+C -1 ; WX 400 ; N degree ; B 54 411 346 703 ;
+C -1 ; WX 556 ; N ograve ; B 35 -14 521 734 ;
+C -1 ; WX 722 ; N Ccaron ; B 44 -19 681 929 ;
+C -1 ; WX 556 ; N ugrave ; B 68 -15 489 734 ;
+C -1 ; WX 453 ; N radical ; B -4 -80 458 762 ;
+C -1 ; WX 722 ; N Dcaron ; B 81 0 674 929 ;
+C -1 ; WX 333 ; N rcommaaccent ; B 77 -225 332 538 ;
+C -1 ; WX 722 ; N Ntilde ; B 76 0 646 917 ;
+C -1 ; WX 556 ; N otilde ; B 35 -14 521 722 ;
+C -1 ; WX 722 ; N Rcommaaccent ; B 88 -225 684 718 ;
+C -1 ; WX 556 ; N Lcommaaccent ; B 76 -225 537 718 ;
+C -1 ; WX 667 ; N Atilde ; B 14 0 654 917 ;
+C -1 ; WX 667 ; N Aogonek ; B 14 -225 654 718 ;
+C -1 ; WX 667 ; N Aring ; B 14 0 654 931 ;
+C -1 ; WX 778 ; N Otilde ; B 39 -19 739 917 ;
+C -1 ; WX 500 ; N zdotaccent ; B 31 0 469 706 ;
+C -1 ; WX 667 ; N Ecaron ; B 86 0 616 929 ;
+C -1 ; WX 278 ; N Iogonek ; B -3 -225 211 718 ;
+C -1 ; WX 500 ; N kcommaaccent ; B 67 -225 501 718 ;
+C -1 ; WX 584 ; N minus ; B 39 216 545 289 ;
+C -1 ; WX 278 ; N Icircumflex ; B -6 0 285 929 ;
+C -1 ; WX 556 ; N ncaron ; B 65 0 491 734 ;
+C -1 ; WX 278 ; N tcommaaccent ; B 14 -225 257 669 ;
+C -1 ; WX 584 ; N logicalnot ; B 39 108 545 390 ;
+C -1 ; WX 556 ; N odieresis ; B 35 -14 521 706 ;
+C -1 ; WX 556 ; N udieresis ; B 68 -15 489 706 ;
+C -1 ; WX 549 ; N notequal ; B 12 -35 537 551 ;
+C -1 ; WX 556 ; N gcommaaccent ; B 40 -220 499 822 ;
+C -1 ; WX 556 ; N eth ; B 35 -15 522 737 ;
+C -1 ; WX 500 ; N zcaron ; B 31 0 469 734 ;
+C -1 ; WX 556 ; N ncommaaccent ; B 65 -225 491 538 ;
+C -1 ; WX 333 ; N onesuperior ; B 43 281 222 703 ;
+C -1 ; WX 278 ; N imacron ; B 5 0 272 684 ;
+C -1 ; WX 556 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2705
+KPX A C -30
+KPX A Cacute -30
+KPX A Ccaron -30
+KPX A Ccedilla -30
+KPX A G -30
+KPX A Gbreve -30
+KPX A Gcommaaccent -30
+KPX A O -30
+KPX A Oacute -30
+KPX A Ocircumflex -30
+KPX A Odieresis -30
+KPX A Ograve -30
+KPX A Ohungarumlaut -30
+KPX A Omacron -30
+KPX A Oslash -30
+KPX A Otilde -30
+KPX A Q -30
+KPX A T -120
+KPX A Tcaron -120
+KPX A Tcommaaccent -120
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -70
+KPX A W -50
+KPX A Y -100
+KPX A Yacute -100
+KPX A Ydieresis -100
+KPX A u -30
+KPX A uacute -30
+KPX A ucircumflex -30
+KPX A udieresis -30
+KPX A ugrave -30
+KPX A uhungarumlaut -30
+KPX A umacron -30
+KPX A uogonek -30
+KPX A uring -30
+KPX A v -40
+KPX A w -40
+KPX A y -40
+KPX A yacute -40
+KPX A ydieresis -40
+KPX Aacute C -30
+KPX Aacute Cacute -30
+KPX Aacute Ccaron -30
+KPX Aacute Ccedilla -30
+KPX Aacute G -30
+KPX Aacute Gbreve -30
+KPX Aacute Gcommaaccent -30
+KPX Aacute O -30
+KPX Aacute Oacute -30
+KPX Aacute Ocircumflex -30
+KPX Aacute Odieresis -30
+KPX Aacute Ograve -30
+KPX Aacute Ohungarumlaut -30
+KPX Aacute Omacron -30
+KPX Aacute Oslash -30
+KPX Aacute Otilde -30
+KPX Aacute Q -30
+KPX Aacute T -120
+KPX Aacute Tcaron -120
+KPX Aacute Tcommaaccent -120
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -70
+KPX Aacute W -50
+KPX Aacute Y -100
+KPX Aacute Yacute -100
+KPX Aacute Ydieresis -100
+KPX Aacute u -30
+KPX Aacute uacute -30
+KPX Aacute ucircumflex -30
+KPX Aacute udieresis -30
+KPX Aacute ugrave -30
+KPX Aacute uhungarumlaut -30
+KPX Aacute umacron -30
+KPX Aacute uogonek -30
+KPX Aacute uring -30
+KPX Aacute v -40
+KPX Aacute w -40
+KPX Aacute y -40
+KPX Aacute yacute -40
+KPX Aacute ydieresis -40
+KPX Abreve C -30
+KPX Abreve Cacute -30
+KPX Abreve Ccaron -30
+KPX Abreve Ccedilla -30
+KPX Abreve G -30
+KPX Abreve Gbreve -30
+KPX Abreve Gcommaaccent -30
+KPX Abreve O -30
+KPX Abreve Oacute -30
+KPX Abreve Ocircumflex -30
+KPX Abreve Odieresis -30
+KPX Abreve Ograve -30
+KPX Abreve Ohungarumlaut -30
+KPX Abreve Omacron -30
+KPX Abreve Oslash -30
+KPX Abreve Otilde -30
+KPX Abreve Q -30
+KPX Abreve T -120
+KPX Abreve Tcaron -120
+KPX Abreve Tcommaaccent -120
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -70
+KPX Abreve W -50
+KPX Abreve Y -100
+KPX Abreve Yacute -100
+KPX Abreve Ydieresis -100
+KPX Abreve u -30
+KPX Abreve uacute -30
+KPX Abreve ucircumflex -30
+KPX Abreve udieresis -30
+KPX Abreve ugrave -30
+KPX Abreve uhungarumlaut -30
+KPX Abreve umacron -30
+KPX Abreve uogonek -30
+KPX Abreve uring -30
+KPX Abreve v -40
+KPX Abreve w -40
+KPX Abreve y -40
+KPX Abreve yacute -40
+KPX Abreve ydieresis -40
+KPX Acircumflex C -30
+KPX Acircumflex Cacute -30
+KPX Acircumflex Ccaron -30
+KPX Acircumflex Ccedilla -30
+KPX Acircumflex G -30
+KPX Acircumflex Gbreve -30
+KPX Acircumflex Gcommaaccent -30
+KPX Acircumflex O -30
+KPX Acircumflex Oacute -30
+KPX Acircumflex Ocircumflex -30
+KPX Acircumflex Odieresis -30
+KPX Acircumflex Ograve -30
+KPX Acircumflex Ohungarumlaut -30
+KPX Acircumflex Omacron -30
+KPX Acircumflex Oslash -30
+KPX Acircumflex Otilde -30
+KPX Acircumflex Q -30
+KPX Acircumflex T -120
+KPX Acircumflex Tcaron -120
+KPX Acircumflex Tcommaaccent -120
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -70
+KPX Acircumflex W -50
+KPX Acircumflex Y -100
+KPX Acircumflex Yacute -100
+KPX Acircumflex Ydieresis -100
+KPX Acircumflex u -30
+KPX Acircumflex uacute -30
+KPX Acircumflex ucircumflex -30
+KPX Acircumflex udieresis -30
+KPX Acircumflex ugrave -30
+KPX Acircumflex uhungarumlaut -30
+KPX Acircumflex umacron -30
+KPX Acircumflex uogonek -30
+KPX Acircumflex uring -30
+KPX Acircumflex v -40
+KPX Acircumflex w -40
+KPX Acircumflex y -40
+KPX Acircumflex yacute -40
+KPX Acircumflex ydieresis -40
+KPX Adieresis C -30
+KPX Adieresis Cacute -30
+KPX Adieresis Ccaron -30
+KPX Adieresis Ccedilla -30
+KPX Adieresis G -30
+KPX Adieresis Gbreve -30
+KPX Adieresis Gcommaaccent -30
+KPX Adieresis O -30
+KPX Adieresis Oacute -30
+KPX Adieresis Ocircumflex -30
+KPX Adieresis Odieresis -30
+KPX Adieresis Ograve -30
+KPX Adieresis Ohungarumlaut -30
+KPX Adieresis Omacron -30
+KPX Adieresis Oslash -30
+KPX Adieresis Otilde -30
+KPX Adieresis Q -30
+KPX Adieresis T -120
+KPX Adieresis Tcaron -120
+KPX Adieresis Tcommaaccent -120
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -70
+KPX Adieresis W -50
+KPX Adieresis Y -100
+KPX Adieresis Yacute -100
+KPX Adieresis Ydieresis -100
+KPX Adieresis u -30
+KPX Adieresis uacute -30
+KPX Adieresis ucircumflex -30
+KPX Adieresis udieresis -30
+KPX Adieresis ugrave -30
+KPX Adieresis uhungarumlaut -30
+KPX Adieresis umacron -30
+KPX Adieresis uogonek -30
+KPX Adieresis uring -30
+KPX Adieresis v -40
+KPX Adieresis w -40
+KPX Adieresis y -40
+KPX Adieresis yacute -40
+KPX Adieresis ydieresis -40
+KPX Agrave C -30
+KPX Agrave Cacute -30
+KPX Agrave Ccaron -30
+KPX Agrave Ccedilla -30
+KPX Agrave G -30
+KPX Agrave Gbreve -30
+KPX Agrave Gcommaaccent -30
+KPX Agrave O -30
+KPX Agrave Oacute -30
+KPX Agrave Ocircumflex -30
+KPX Agrave Odieresis -30
+KPX Agrave Ograve -30
+KPX Agrave Ohungarumlaut -30
+KPX Agrave Omacron -30
+KPX Agrave Oslash -30
+KPX Agrave Otilde -30
+KPX Agrave Q -30
+KPX Agrave T -120
+KPX Agrave Tcaron -120
+KPX Agrave Tcommaaccent -120
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -70
+KPX Agrave W -50
+KPX Agrave Y -100
+KPX Agrave Yacute -100
+KPX Agrave Ydieresis -100
+KPX Agrave u -30
+KPX Agrave uacute -30
+KPX Agrave ucircumflex -30
+KPX Agrave udieresis -30
+KPX Agrave ugrave -30
+KPX Agrave uhungarumlaut -30
+KPX Agrave umacron -30
+KPX Agrave uogonek -30
+KPX Agrave uring -30
+KPX Agrave v -40
+KPX Agrave w -40
+KPX Agrave y -40
+KPX Agrave yacute -40
+KPX Agrave ydieresis -40
+KPX Amacron C -30
+KPX Amacron Cacute -30
+KPX Amacron Ccaron -30
+KPX Amacron Ccedilla -30
+KPX Amacron G -30
+KPX Amacron Gbreve -30
+KPX Amacron Gcommaaccent -30
+KPX Amacron O -30
+KPX Amacron Oacute -30
+KPX Amacron Ocircumflex -30
+KPX Amacron Odieresis -30
+KPX Amacron Ograve -30
+KPX Amacron Ohungarumlaut -30
+KPX Amacron Omacron -30
+KPX Amacron Oslash -30
+KPX Amacron Otilde -30
+KPX Amacron Q -30
+KPX Amacron T -120
+KPX Amacron Tcaron -120
+KPX Amacron Tcommaaccent -120
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -70
+KPX Amacron W -50
+KPX Amacron Y -100
+KPX Amacron Yacute -100
+KPX Amacron Ydieresis -100
+KPX Amacron u -30
+KPX Amacron uacute -30
+KPX Amacron ucircumflex -30
+KPX Amacron udieresis -30
+KPX Amacron ugrave -30
+KPX Amacron uhungarumlaut -30
+KPX Amacron umacron -30
+KPX Amacron uogonek -30
+KPX Amacron uring -30
+KPX Amacron v -40
+KPX Amacron w -40
+KPX Amacron y -40
+KPX Amacron yacute -40
+KPX Amacron ydieresis -40
+KPX Aogonek C -30
+KPX Aogonek Cacute -30
+KPX Aogonek Ccaron -30
+KPX Aogonek Ccedilla -30
+KPX Aogonek G -30
+KPX Aogonek Gbreve -30
+KPX Aogonek Gcommaaccent -30
+KPX Aogonek O -30
+KPX Aogonek Oacute -30
+KPX Aogonek Ocircumflex -30
+KPX Aogonek Odieresis -30
+KPX Aogonek Ograve -30
+KPX Aogonek Ohungarumlaut -30
+KPX Aogonek Omacron -30
+KPX Aogonek Oslash -30
+KPX Aogonek Otilde -30
+KPX Aogonek Q -30
+KPX Aogonek T -120
+KPX Aogonek Tcaron -120
+KPX Aogonek Tcommaaccent -120
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -70
+KPX Aogonek W -50
+KPX Aogonek Y -100
+KPX Aogonek Yacute -100
+KPX Aogonek Ydieresis -100
+KPX Aogonek u -30
+KPX Aogonek uacute -30
+KPX Aogonek ucircumflex -30
+KPX Aogonek udieresis -30
+KPX Aogonek ugrave -30
+KPX Aogonek uhungarumlaut -30
+KPX Aogonek umacron -30
+KPX Aogonek uogonek -30
+KPX Aogonek uring -30
+KPX Aogonek v -40
+KPX Aogonek w -40
+KPX Aogonek y -40
+KPX Aogonek yacute -40
+KPX Aogonek ydieresis -40
+KPX Aring C -30
+KPX Aring Cacute -30
+KPX Aring Ccaron -30
+KPX Aring Ccedilla -30
+KPX Aring G -30
+KPX Aring Gbreve -30
+KPX Aring Gcommaaccent -30
+KPX Aring O -30
+KPX Aring Oacute -30
+KPX Aring Ocircumflex -30
+KPX Aring Odieresis -30
+KPX Aring Ograve -30
+KPX Aring Ohungarumlaut -30
+KPX Aring Omacron -30
+KPX Aring Oslash -30
+KPX Aring Otilde -30
+KPX Aring Q -30
+KPX Aring T -120
+KPX Aring Tcaron -120
+KPX Aring Tcommaaccent -120
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -70
+KPX Aring W -50
+KPX Aring Y -100
+KPX Aring Yacute -100
+KPX Aring Ydieresis -100
+KPX Aring u -30
+KPX Aring uacute -30
+KPX Aring ucircumflex -30
+KPX Aring udieresis -30
+KPX Aring ugrave -30
+KPX Aring uhungarumlaut -30
+KPX Aring umacron -30
+KPX Aring uogonek -30
+KPX Aring uring -30
+KPX Aring v -40
+KPX Aring w -40
+KPX Aring y -40
+KPX Aring yacute -40
+KPX Aring ydieresis -40
+KPX Atilde C -30
+KPX Atilde Cacute -30
+KPX Atilde Ccaron -30
+KPX Atilde Ccedilla -30
+KPX Atilde G -30
+KPX Atilde Gbreve -30
+KPX Atilde Gcommaaccent -30
+KPX Atilde O -30
+KPX Atilde Oacute -30
+KPX Atilde Ocircumflex -30
+KPX Atilde Odieresis -30
+KPX Atilde Ograve -30
+KPX Atilde Ohungarumlaut -30
+KPX Atilde Omacron -30
+KPX Atilde Oslash -30
+KPX Atilde Otilde -30
+KPX Atilde Q -30
+KPX Atilde T -120
+KPX Atilde Tcaron -120
+KPX Atilde Tcommaaccent -120
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -70
+KPX Atilde W -50
+KPX Atilde Y -100
+KPX Atilde Yacute -100
+KPX Atilde Ydieresis -100
+KPX Atilde u -30
+KPX Atilde uacute -30
+KPX Atilde ucircumflex -30
+KPX Atilde udieresis -30
+KPX Atilde ugrave -30
+KPX Atilde uhungarumlaut -30
+KPX Atilde umacron -30
+KPX Atilde uogonek -30
+KPX Atilde uring -30
+KPX Atilde v -40
+KPX Atilde w -40
+KPX Atilde y -40
+KPX Atilde yacute -40
+KPX Atilde ydieresis -40
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX B comma -20
+KPX B period -20
+KPX C comma -30
+KPX C period -30
+KPX Cacute comma -30
+KPX Cacute period -30
+KPX Ccaron comma -30
+KPX Ccaron period -30
+KPX Ccedilla comma -30
+KPX Ccedilla period -30
+KPX D A -40
+KPX D Aacute -40
+KPX D Abreve -40
+KPX D Acircumflex -40
+KPX D Adieresis -40
+KPX D Agrave -40
+KPX D Amacron -40
+KPX D Aogonek -40
+KPX D Aring -40
+KPX D Atilde -40
+KPX D V -70
+KPX D W -40
+KPX D Y -90
+KPX D Yacute -90
+KPX D Ydieresis -90
+KPX D comma -70
+KPX D period -70
+KPX Dcaron A -40
+KPX Dcaron Aacute -40
+KPX Dcaron Abreve -40
+KPX Dcaron Acircumflex -40
+KPX Dcaron Adieresis -40
+KPX Dcaron Agrave -40
+KPX Dcaron Amacron -40
+KPX Dcaron Aogonek -40
+KPX Dcaron Aring -40
+KPX Dcaron Atilde -40
+KPX Dcaron V -70
+KPX Dcaron W -40
+KPX Dcaron Y -90
+KPX Dcaron Yacute -90
+KPX Dcaron Ydieresis -90
+KPX Dcaron comma -70
+KPX Dcaron period -70
+KPX Dcroat A -40
+KPX Dcroat Aacute -40
+KPX Dcroat Abreve -40
+KPX Dcroat Acircumflex -40
+KPX Dcroat Adieresis -40
+KPX Dcroat Agrave -40
+KPX Dcroat Amacron -40
+KPX Dcroat Aogonek -40
+KPX Dcroat Aring -40
+KPX Dcroat Atilde -40
+KPX Dcroat V -70
+KPX Dcroat W -40
+KPX Dcroat Y -90
+KPX Dcroat Yacute -90
+KPX Dcroat Ydieresis -90
+KPX Dcroat comma -70
+KPX Dcroat period -70
+KPX F A -80
+KPX F Aacute -80
+KPX F Abreve -80
+KPX F Acircumflex -80
+KPX F Adieresis -80
+KPX F Agrave -80
+KPX F Amacron -80
+KPX F Aogonek -80
+KPX F Aring -80
+KPX F Atilde -80
+KPX F a -50
+KPX F aacute -50
+KPX F abreve -50
+KPX F acircumflex -50
+KPX F adieresis -50
+KPX F agrave -50
+KPX F amacron -50
+KPX F aogonek -50
+KPX F aring -50
+KPX F atilde -50
+KPX F comma -150
+KPX F e -30
+KPX F eacute -30
+KPX F ecaron -30
+KPX F ecircumflex -30
+KPX F edieresis -30
+KPX F edotaccent -30
+KPX F egrave -30
+KPX F emacron -30
+KPX F eogonek -30
+KPX F o -30
+KPX F oacute -30
+KPX F ocircumflex -30
+KPX F odieresis -30
+KPX F ograve -30
+KPX F ohungarumlaut -30
+KPX F omacron -30
+KPX F oslash -30
+KPX F otilde -30
+KPX F period -150
+KPX F r -45
+KPX F racute -45
+KPX F rcaron -45
+KPX F rcommaaccent -45
+KPX J A -20
+KPX J Aacute -20
+KPX J Abreve -20
+KPX J Acircumflex -20
+KPX J Adieresis -20
+KPX J Agrave -20
+KPX J Amacron -20
+KPX J Aogonek -20
+KPX J Aring -20
+KPX J Atilde -20
+KPX J a -20
+KPX J aacute -20
+KPX J abreve -20
+KPX J acircumflex -20
+KPX J adieresis -20
+KPX J agrave -20
+KPX J amacron -20
+KPX J aogonek -20
+KPX J aring -20
+KPX J atilde -20
+KPX J comma -30
+KPX J period -30
+KPX J u -20
+KPX J uacute -20
+KPX J ucircumflex -20
+KPX J udieresis -20
+KPX J ugrave -20
+KPX J uhungarumlaut -20
+KPX J umacron -20
+KPX J uogonek -20
+KPX J uring -20
+KPX K O -50
+KPX K Oacute -50
+KPX K Ocircumflex -50
+KPX K Odieresis -50
+KPX K Ograve -50
+KPX K Ohungarumlaut -50
+KPX K Omacron -50
+KPX K Oslash -50
+KPX K Otilde -50
+KPX K e -40
+KPX K eacute -40
+KPX K ecaron -40
+KPX K ecircumflex -40
+KPX K edieresis -40
+KPX K edotaccent -40
+KPX K egrave -40
+KPX K emacron -40
+KPX K eogonek -40
+KPX K o -40
+KPX K oacute -40
+KPX K ocircumflex -40
+KPX K odieresis -40
+KPX K ograve -40
+KPX K ohungarumlaut -40
+KPX K omacron -40
+KPX K oslash -40
+KPX K otilde -40
+KPX K u -30
+KPX K uacute -30
+KPX K ucircumflex -30
+KPX K udieresis -30
+KPX K ugrave -30
+KPX K uhungarumlaut -30
+KPX K umacron -30
+KPX K uogonek -30
+KPX K uring -30
+KPX K y -50
+KPX K yacute -50
+KPX K ydieresis -50
+KPX Kcommaaccent O -50
+KPX Kcommaaccent Oacute -50
+KPX Kcommaaccent Ocircumflex -50
+KPX Kcommaaccent Odieresis -50
+KPX Kcommaaccent Ograve -50
+KPX Kcommaaccent Ohungarumlaut -50
+KPX Kcommaaccent Omacron -50
+KPX Kcommaaccent Oslash -50
+KPX Kcommaaccent Otilde -50
+KPX Kcommaaccent e -40
+KPX Kcommaaccent eacute -40
+KPX Kcommaaccent ecaron -40
+KPX Kcommaaccent ecircumflex -40
+KPX Kcommaaccent edieresis -40
+KPX Kcommaaccent edotaccent -40
+KPX Kcommaaccent egrave -40
+KPX Kcommaaccent emacron -40
+KPX Kcommaaccent eogonek -40
+KPX Kcommaaccent o -40
+KPX Kcommaaccent oacute -40
+KPX Kcommaaccent ocircumflex -40
+KPX Kcommaaccent odieresis -40
+KPX Kcommaaccent ograve -40
+KPX Kcommaaccent ohungarumlaut -40
+KPX Kcommaaccent omacron -40
+KPX Kcommaaccent oslash -40
+KPX Kcommaaccent otilde -40
+KPX Kcommaaccent u -30
+KPX Kcommaaccent uacute -30
+KPX Kcommaaccent ucircumflex -30
+KPX Kcommaaccent udieresis -30
+KPX Kcommaaccent ugrave -30
+KPX Kcommaaccent uhungarumlaut -30
+KPX Kcommaaccent umacron -30
+KPX Kcommaaccent uogonek -30
+KPX Kcommaaccent uring -30
+KPX Kcommaaccent y -50
+KPX Kcommaaccent yacute -50
+KPX Kcommaaccent ydieresis -50
+KPX L T -110
+KPX L Tcaron -110
+KPX L Tcommaaccent -110
+KPX L V -110
+KPX L W -70
+KPX L Y -140
+KPX L Yacute -140
+KPX L Ydieresis -140
+KPX L quotedblright -140
+KPX L quoteright -160
+KPX L y -30
+KPX L yacute -30
+KPX L ydieresis -30
+KPX Lacute T -110
+KPX Lacute Tcaron -110
+KPX Lacute Tcommaaccent -110
+KPX Lacute V -110
+KPX Lacute W -70
+KPX Lacute Y -140
+KPX Lacute Yacute -140
+KPX Lacute Ydieresis -140
+KPX Lacute quotedblright -140
+KPX Lacute quoteright -160
+KPX Lacute y -30
+KPX Lacute yacute -30
+KPX Lacute ydieresis -30
+KPX Lcaron T -110
+KPX Lcaron Tcaron -110
+KPX Lcaron Tcommaaccent -110
+KPX Lcaron V -110
+KPX Lcaron W -70
+KPX Lcaron Y -140
+KPX Lcaron Yacute -140
+KPX Lcaron Ydieresis -140
+KPX Lcaron quotedblright -140
+KPX Lcaron quoteright -160
+KPX Lcaron y -30
+KPX Lcaron yacute -30
+KPX Lcaron ydieresis -30
+KPX Lcommaaccent T -110
+KPX Lcommaaccent Tcaron -110
+KPX Lcommaaccent Tcommaaccent -110
+KPX Lcommaaccent V -110
+KPX Lcommaaccent W -70
+KPX Lcommaaccent Y -140
+KPX Lcommaaccent Yacute -140
+KPX Lcommaaccent Ydieresis -140
+KPX Lcommaaccent quotedblright -140
+KPX Lcommaaccent quoteright -160
+KPX Lcommaaccent y -30
+KPX Lcommaaccent yacute -30
+KPX Lcommaaccent ydieresis -30
+KPX Lslash T -110
+KPX Lslash Tcaron -110
+KPX Lslash Tcommaaccent -110
+KPX Lslash V -110
+KPX Lslash W -70
+KPX Lslash Y -140
+KPX Lslash Yacute -140
+KPX Lslash Ydieresis -140
+KPX Lslash quotedblright -140
+KPX Lslash quoteright -160
+KPX Lslash y -30
+KPX Lslash yacute -30
+KPX Lslash ydieresis -30
+KPX O A -20
+KPX O Aacute -20
+KPX O Abreve -20
+KPX O Acircumflex -20
+KPX O Adieresis -20
+KPX O Agrave -20
+KPX O Amacron -20
+KPX O Aogonek -20
+KPX O Aring -20
+KPX O Atilde -20
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -30
+KPX O X -60
+KPX O Y -70
+KPX O Yacute -70
+KPX O Ydieresis -70
+KPX O comma -40
+KPX O period -40
+KPX Oacute A -20
+KPX Oacute Aacute -20
+KPX Oacute Abreve -20
+KPX Oacute Acircumflex -20
+KPX Oacute Adieresis -20
+KPX Oacute Agrave -20
+KPX Oacute Amacron -20
+KPX Oacute Aogonek -20
+KPX Oacute Aring -20
+KPX Oacute Atilde -20
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -30
+KPX Oacute X -60
+KPX Oacute Y -70
+KPX Oacute Yacute -70
+KPX Oacute Ydieresis -70
+KPX Oacute comma -40
+KPX Oacute period -40
+KPX Ocircumflex A -20
+KPX Ocircumflex Aacute -20
+KPX Ocircumflex Abreve -20
+KPX Ocircumflex Acircumflex -20
+KPX Ocircumflex Adieresis -20
+KPX Ocircumflex Agrave -20
+KPX Ocircumflex Amacron -20
+KPX Ocircumflex Aogonek -20
+KPX Ocircumflex Aring -20
+KPX Ocircumflex Atilde -20
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -30
+KPX Ocircumflex X -60
+KPX Ocircumflex Y -70
+KPX Ocircumflex Yacute -70
+KPX Ocircumflex Ydieresis -70
+KPX Ocircumflex comma -40
+KPX Ocircumflex period -40
+KPX Odieresis A -20
+KPX Odieresis Aacute -20
+KPX Odieresis Abreve -20
+KPX Odieresis Acircumflex -20
+KPX Odieresis Adieresis -20
+KPX Odieresis Agrave -20
+KPX Odieresis Amacron -20
+KPX Odieresis Aogonek -20
+KPX Odieresis Aring -20
+KPX Odieresis Atilde -20
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -30
+KPX Odieresis X -60
+KPX Odieresis Y -70
+KPX Odieresis Yacute -70
+KPX Odieresis Ydieresis -70
+KPX Odieresis comma -40
+KPX Odieresis period -40
+KPX Ograve A -20
+KPX Ograve Aacute -20
+KPX Ograve Abreve -20
+KPX Ograve Acircumflex -20
+KPX Ograve Adieresis -20
+KPX Ograve Agrave -20
+KPX Ograve Amacron -20
+KPX Ograve Aogonek -20
+KPX Ograve Aring -20
+KPX Ograve Atilde -20
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -30
+KPX Ograve X -60
+KPX Ograve Y -70
+KPX Ograve Yacute -70
+KPX Ograve Ydieresis -70
+KPX Ograve comma -40
+KPX Ograve period -40
+KPX Ohungarumlaut A -20
+KPX Ohungarumlaut Aacute -20
+KPX Ohungarumlaut Abreve -20
+KPX Ohungarumlaut Acircumflex -20
+KPX Ohungarumlaut Adieresis -20
+KPX Ohungarumlaut Agrave -20
+KPX Ohungarumlaut Amacron -20
+KPX Ohungarumlaut Aogonek -20
+KPX Ohungarumlaut Aring -20
+KPX Ohungarumlaut Atilde -20
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -30
+KPX Ohungarumlaut X -60
+KPX Ohungarumlaut Y -70
+KPX Ohungarumlaut Yacute -70
+KPX Ohungarumlaut Ydieresis -70
+KPX Ohungarumlaut comma -40
+KPX Ohungarumlaut period -40
+KPX Omacron A -20
+KPX Omacron Aacute -20
+KPX Omacron Abreve -20
+KPX Omacron Acircumflex -20
+KPX Omacron Adieresis -20
+KPX Omacron Agrave -20
+KPX Omacron Amacron -20
+KPX Omacron Aogonek -20
+KPX Omacron Aring -20
+KPX Omacron Atilde -20
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -30
+KPX Omacron X -60
+KPX Omacron Y -70
+KPX Omacron Yacute -70
+KPX Omacron Ydieresis -70
+KPX Omacron comma -40
+KPX Omacron period -40
+KPX Oslash A -20
+KPX Oslash Aacute -20
+KPX Oslash Abreve -20
+KPX Oslash Acircumflex -20
+KPX Oslash Adieresis -20
+KPX Oslash Agrave -20
+KPX Oslash Amacron -20
+KPX Oslash Aogonek -20
+KPX Oslash Aring -20
+KPX Oslash Atilde -20
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -30
+KPX Oslash X -60
+KPX Oslash Y -70
+KPX Oslash Yacute -70
+KPX Oslash Ydieresis -70
+KPX Oslash comma -40
+KPX Oslash period -40
+KPX Otilde A -20
+KPX Otilde Aacute -20
+KPX Otilde Abreve -20
+KPX Otilde Acircumflex -20
+KPX Otilde Adieresis -20
+KPX Otilde Agrave -20
+KPX Otilde Amacron -20
+KPX Otilde Aogonek -20
+KPX Otilde Aring -20
+KPX Otilde Atilde -20
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -30
+KPX Otilde X -60
+KPX Otilde Y -70
+KPX Otilde Yacute -70
+KPX Otilde Ydieresis -70
+KPX Otilde comma -40
+KPX Otilde period -40
+KPX P A -120
+KPX P Aacute -120
+KPX P Abreve -120
+KPX P Acircumflex -120
+KPX P Adieresis -120
+KPX P Agrave -120
+KPX P Amacron -120
+KPX P Aogonek -120
+KPX P Aring -120
+KPX P Atilde -120
+KPX P a -40
+KPX P aacute -40
+KPX P abreve -40
+KPX P acircumflex -40
+KPX P adieresis -40
+KPX P agrave -40
+KPX P amacron -40
+KPX P aogonek -40
+KPX P aring -40
+KPX P atilde -40
+KPX P comma -180
+KPX P e -50
+KPX P eacute -50
+KPX P ecaron -50
+KPX P ecircumflex -50
+KPX P edieresis -50
+KPX P edotaccent -50
+KPX P egrave -50
+KPX P emacron -50
+KPX P eogonek -50
+KPX P o -50
+KPX P oacute -50
+KPX P ocircumflex -50
+KPX P odieresis -50
+KPX P ograve -50
+KPX P ohungarumlaut -50
+KPX P omacron -50
+KPX P oslash -50
+KPX P otilde -50
+KPX P period -180
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX R O -20
+KPX R Oacute -20
+KPX R Ocircumflex -20
+KPX R Odieresis -20
+KPX R Ograve -20
+KPX R Ohungarumlaut -20
+KPX R Omacron -20
+KPX R Oslash -20
+KPX R Otilde -20
+KPX R T -30
+KPX R Tcaron -30
+KPX R Tcommaaccent -30
+KPX R U -40
+KPX R Uacute -40
+KPX R Ucircumflex -40
+KPX R Udieresis -40
+KPX R Ugrave -40
+KPX R Uhungarumlaut -40
+KPX R Umacron -40
+KPX R Uogonek -40
+KPX R Uring -40
+KPX R V -50
+KPX R W -30
+KPX R Y -50
+KPX R Yacute -50
+KPX R Ydieresis -50
+KPX Racute O -20
+KPX Racute Oacute -20
+KPX Racute Ocircumflex -20
+KPX Racute Odieresis -20
+KPX Racute Ograve -20
+KPX Racute Ohungarumlaut -20
+KPX Racute Omacron -20
+KPX Racute Oslash -20
+KPX Racute Otilde -20
+KPX Racute T -30
+KPX Racute Tcaron -30
+KPX Racute Tcommaaccent -30
+KPX Racute U -40
+KPX Racute Uacute -40
+KPX Racute Ucircumflex -40
+KPX Racute Udieresis -40
+KPX Racute Ugrave -40
+KPX Racute Uhungarumlaut -40
+KPX Racute Umacron -40
+KPX Racute Uogonek -40
+KPX Racute Uring -40
+KPX Racute V -50
+KPX Racute W -30
+KPX Racute Y -50
+KPX Racute Yacute -50
+KPX Racute Ydieresis -50
+KPX Rcaron O -20
+KPX Rcaron Oacute -20
+KPX Rcaron Ocircumflex -20
+KPX Rcaron Odieresis -20
+KPX Rcaron Ograve -20
+KPX Rcaron Ohungarumlaut -20
+KPX Rcaron Omacron -20
+KPX Rcaron Oslash -20
+KPX Rcaron Otilde -20
+KPX Rcaron T -30
+KPX Rcaron Tcaron -30
+KPX Rcaron Tcommaaccent -30
+KPX Rcaron U -40
+KPX Rcaron Uacute -40
+KPX Rcaron Ucircumflex -40
+KPX Rcaron Udieresis -40
+KPX Rcaron Ugrave -40
+KPX Rcaron Uhungarumlaut -40
+KPX Rcaron Umacron -40
+KPX Rcaron Uogonek -40
+KPX Rcaron Uring -40
+KPX Rcaron V -50
+KPX Rcaron W -30
+KPX Rcaron Y -50
+KPX Rcaron Yacute -50
+KPX Rcaron Ydieresis -50
+KPX Rcommaaccent O -20
+KPX Rcommaaccent Oacute -20
+KPX Rcommaaccent Ocircumflex -20
+KPX Rcommaaccent Odieresis -20
+KPX Rcommaaccent Ograve -20
+KPX Rcommaaccent Ohungarumlaut -20
+KPX Rcommaaccent Omacron -20
+KPX Rcommaaccent Oslash -20
+KPX Rcommaaccent Otilde -20
+KPX Rcommaaccent T -30
+KPX Rcommaaccent Tcaron -30
+KPX Rcommaaccent Tcommaaccent -30
+KPX Rcommaaccent U -40
+KPX Rcommaaccent Uacute -40
+KPX Rcommaaccent Ucircumflex -40
+KPX Rcommaaccent Udieresis -40
+KPX Rcommaaccent Ugrave -40
+KPX Rcommaaccent Uhungarumlaut -40
+KPX Rcommaaccent Umacron -40
+KPX Rcommaaccent Uogonek -40
+KPX Rcommaaccent Uring -40
+KPX Rcommaaccent V -50
+KPX Rcommaaccent W -30
+KPX Rcommaaccent Y -50
+KPX Rcommaaccent Yacute -50
+KPX Rcommaaccent Ydieresis -50
+KPX S comma -20
+KPX S period -20
+KPX Sacute comma -20
+KPX Sacute period -20
+KPX Scaron comma -20
+KPX Scaron period -20
+KPX Scedilla comma -20
+KPX Scedilla period -20
+KPX Scommaaccent comma -20
+KPX Scommaaccent period -20
+KPX T A -120
+KPX T Aacute -120
+KPX T Abreve -120
+KPX T Acircumflex -120
+KPX T Adieresis -120
+KPX T Agrave -120
+KPX T Amacron -120
+KPX T Aogonek -120
+KPX T Aring -120
+KPX T Atilde -120
+KPX T O -40
+KPX T Oacute -40
+KPX T Ocircumflex -40
+KPX T Odieresis -40
+KPX T Ograve -40
+KPX T Ohungarumlaut -40
+KPX T Omacron -40
+KPX T Oslash -40
+KPX T Otilde -40
+KPX T a -120
+KPX T aacute -120
+KPX T abreve -60
+KPX T acircumflex -120
+KPX T adieresis -120
+KPX T agrave -120
+KPX T amacron -60
+KPX T aogonek -120
+KPX T aring -120
+KPX T atilde -60
+KPX T colon -20
+KPX T comma -120
+KPX T e -120
+KPX T eacute -120
+KPX T ecaron -120
+KPX T ecircumflex -120
+KPX T edieresis -120
+KPX T edotaccent -120
+KPX T egrave -60
+KPX T emacron -60
+KPX T eogonek -120
+KPX T hyphen -140
+KPX T o -120
+KPX T oacute -120
+KPX T ocircumflex -120
+KPX T odieresis -120
+KPX T ograve -120
+KPX T ohungarumlaut -120
+KPX T omacron -60
+KPX T oslash -120
+KPX T otilde -60
+KPX T period -120
+KPX T r -120
+KPX T racute -120
+KPX T rcaron -120
+KPX T rcommaaccent -120
+KPX T semicolon -20
+KPX T u -120
+KPX T uacute -120
+KPX T ucircumflex -120
+KPX T udieresis -120
+KPX T ugrave -120
+KPX T uhungarumlaut -120
+KPX T umacron -60
+KPX T uogonek -120
+KPX T uring -120
+KPX T w -120
+KPX T y -120
+KPX T yacute -120
+KPX T ydieresis -60
+KPX Tcaron A -120
+KPX Tcaron Aacute -120
+KPX Tcaron Abreve -120
+KPX Tcaron Acircumflex -120
+KPX Tcaron Adieresis -120
+KPX Tcaron Agrave -120
+KPX Tcaron Amacron -120
+KPX Tcaron Aogonek -120
+KPX Tcaron Aring -120
+KPX Tcaron Atilde -120
+KPX Tcaron O -40
+KPX Tcaron Oacute -40
+KPX Tcaron Ocircumflex -40
+KPX Tcaron Odieresis -40
+KPX Tcaron Ograve -40
+KPX Tcaron Ohungarumlaut -40
+KPX Tcaron Omacron -40
+KPX Tcaron Oslash -40
+KPX Tcaron Otilde -40
+KPX Tcaron a -120
+KPX Tcaron aacute -120
+KPX Tcaron abreve -60
+KPX Tcaron acircumflex -120
+KPX Tcaron adieresis -120
+KPX Tcaron agrave -120
+KPX Tcaron amacron -60
+KPX Tcaron aogonek -120
+KPX Tcaron aring -120
+KPX Tcaron atilde -60
+KPX Tcaron colon -20
+KPX Tcaron comma -120
+KPX Tcaron e -120
+KPX Tcaron eacute -120
+KPX Tcaron ecaron -120
+KPX Tcaron ecircumflex -120
+KPX Tcaron edieresis -120
+KPX Tcaron edotaccent -120
+KPX Tcaron egrave -60
+KPX Tcaron emacron -60
+KPX Tcaron eogonek -120
+KPX Tcaron hyphen -140
+KPX Tcaron o -120
+KPX Tcaron oacute -120
+KPX Tcaron ocircumflex -120
+KPX Tcaron odieresis -120
+KPX Tcaron ograve -120
+KPX Tcaron ohungarumlaut -120
+KPX Tcaron omacron -60
+KPX Tcaron oslash -120
+KPX Tcaron otilde -60
+KPX Tcaron period -120
+KPX Tcaron r -120
+KPX Tcaron racute -120
+KPX Tcaron rcaron -120
+KPX Tcaron rcommaaccent -120
+KPX Tcaron semicolon -20
+KPX Tcaron u -120
+KPX Tcaron uacute -120
+KPX Tcaron ucircumflex -120
+KPX Tcaron udieresis -120
+KPX Tcaron ugrave -120
+KPX Tcaron uhungarumlaut -120
+KPX Tcaron umacron -60
+KPX Tcaron uogonek -120
+KPX Tcaron uring -120
+KPX Tcaron w -120
+KPX Tcaron y -120
+KPX Tcaron yacute -120
+KPX Tcaron ydieresis -60
+KPX Tcommaaccent A -120
+KPX Tcommaaccent Aacute -120
+KPX Tcommaaccent Abreve -120
+KPX Tcommaaccent Acircumflex -120
+KPX Tcommaaccent Adieresis -120
+KPX Tcommaaccent Agrave -120
+KPX Tcommaaccent Amacron -120
+KPX Tcommaaccent Aogonek -120
+KPX Tcommaaccent Aring -120
+KPX Tcommaaccent Atilde -120
+KPX Tcommaaccent O -40
+KPX Tcommaaccent Oacute -40
+KPX Tcommaaccent Ocircumflex -40
+KPX Tcommaaccent Odieresis -40
+KPX Tcommaaccent Ograve -40
+KPX Tcommaaccent Ohungarumlaut -40
+KPX Tcommaaccent Omacron -40
+KPX Tcommaaccent Oslash -40
+KPX Tcommaaccent Otilde -40
+KPX Tcommaaccent a -120
+KPX Tcommaaccent aacute -120
+KPX Tcommaaccent abreve -60
+KPX Tcommaaccent acircumflex -120
+KPX Tcommaaccent adieresis -120
+KPX Tcommaaccent agrave -120
+KPX Tcommaaccent amacron -60
+KPX Tcommaaccent aogonek -120
+KPX Tcommaaccent aring -120
+KPX Tcommaaccent atilde -60
+KPX Tcommaaccent colon -20
+KPX Tcommaaccent comma -120
+KPX Tcommaaccent e -120
+KPX Tcommaaccent eacute -120
+KPX Tcommaaccent ecaron -120
+KPX Tcommaaccent ecircumflex -120
+KPX Tcommaaccent edieresis -120
+KPX Tcommaaccent edotaccent -120
+KPX Tcommaaccent egrave -60
+KPX Tcommaaccent emacron -60
+KPX Tcommaaccent eogonek -120
+KPX Tcommaaccent hyphen -140
+KPX Tcommaaccent o -120
+KPX Tcommaaccent oacute -120
+KPX Tcommaaccent ocircumflex -120
+KPX Tcommaaccent odieresis -120
+KPX Tcommaaccent ograve -120
+KPX Tcommaaccent ohungarumlaut -120
+KPX Tcommaaccent omacron -60
+KPX Tcommaaccent oslash -120
+KPX Tcommaaccent otilde -60
+KPX Tcommaaccent period -120
+KPX Tcommaaccent r -120
+KPX Tcommaaccent racute -120
+KPX Tcommaaccent rcaron -120
+KPX Tcommaaccent rcommaaccent -120
+KPX Tcommaaccent semicolon -20
+KPX Tcommaaccent u -120
+KPX Tcommaaccent uacute -120
+KPX Tcommaaccent ucircumflex -120
+KPX Tcommaaccent udieresis -120
+KPX Tcommaaccent ugrave -120
+KPX Tcommaaccent uhungarumlaut -120
+KPX Tcommaaccent umacron -60
+KPX Tcommaaccent uogonek -120
+KPX Tcommaaccent uring -120
+KPX Tcommaaccent w -120
+KPX Tcommaaccent y -120
+KPX Tcommaaccent yacute -120
+KPX Tcommaaccent ydieresis -60
+KPX U A -40
+KPX U Aacute -40
+KPX U Abreve -40
+KPX U Acircumflex -40
+KPX U Adieresis -40
+KPX U Agrave -40
+KPX U Amacron -40
+KPX U Aogonek -40
+KPX U Aring -40
+KPX U Atilde -40
+KPX U comma -40
+KPX U period -40
+KPX Uacute A -40
+KPX Uacute Aacute -40
+KPX Uacute Abreve -40
+KPX Uacute Acircumflex -40
+KPX Uacute Adieresis -40
+KPX Uacute Agrave -40
+KPX Uacute Amacron -40
+KPX Uacute Aogonek -40
+KPX Uacute Aring -40
+KPX Uacute Atilde -40
+KPX Uacute comma -40
+KPX Uacute period -40
+KPX Ucircumflex A -40
+KPX Ucircumflex Aacute -40
+KPX Ucircumflex Abreve -40
+KPX Ucircumflex Acircumflex -40
+KPX Ucircumflex Adieresis -40
+KPX Ucircumflex Agrave -40
+KPX Ucircumflex Amacron -40
+KPX Ucircumflex Aogonek -40
+KPX Ucircumflex Aring -40
+KPX Ucircumflex Atilde -40
+KPX Ucircumflex comma -40
+KPX Ucircumflex period -40
+KPX Udieresis A -40
+KPX Udieresis Aacute -40
+KPX Udieresis Abreve -40
+KPX Udieresis Acircumflex -40
+KPX Udieresis Adieresis -40
+KPX Udieresis Agrave -40
+KPX Udieresis Amacron -40
+KPX Udieresis Aogonek -40
+KPX Udieresis Aring -40
+KPX Udieresis Atilde -40
+KPX Udieresis comma -40
+KPX Udieresis period -40
+KPX Ugrave A -40
+KPX Ugrave Aacute -40
+KPX Ugrave Abreve -40
+KPX Ugrave Acircumflex -40
+KPX Ugrave Adieresis -40
+KPX Ugrave Agrave -40
+KPX Ugrave Amacron -40
+KPX Ugrave Aogonek -40
+KPX Ugrave Aring -40
+KPX Ugrave Atilde -40
+KPX Ugrave comma -40
+KPX Ugrave period -40
+KPX Uhungarumlaut A -40
+KPX Uhungarumlaut Aacute -40
+KPX Uhungarumlaut Abreve -40
+KPX Uhungarumlaut Acircumflex -40
+KPX Uhungarumlaut Adieresis -40
+KPX Uhungarumlaut Agrave -40
+KPX Uhungarumlaut Amacron -40
+KPX Uhungarumlaut Aogonek -40
+KPX Uhungarumlaut Aring -40
+KPX Uhungarumlaut Atilde -40
+KPX Uhungarumlaut comma -40
+KPX Uhungarumlaut period -40
+KPX Umacron A -40
+KPX Umacron Aacute -40
+KPX Umacron Abreve -40
+KPX Umacron Acircumflex -40
+KPX Umacron Adieresis -40
+KPX Umacron Agrave -40
+KPX Umacron Amacron -40
+KPX Umacron Aogonek -40
+KPX Umacron Aring -40
+KPX Umacron Atilde -40
+KPX Umacron comma -40
+KPX Umacron period -40
+KPX Uogonek A -40
+KPX Uogonek Aacute -40
+KPX Uogonek Abreve -40
+KPX Uogonek Acircumflex -40
+KPX Uogonek Adieresis -40
+KPX Uogonek Agrave -40
+KPX Uogonek Amacron -40
+KPX Uogonek Aogonek -40
+KPX Uogonek Aring -40
+KPX Uogonek Atilde -40
+KPX Uogonek comma -40
+KPX Uogonek period -40
+KPX Uring A -40
+KPX Uring Aacute -40
+KPX Uring Abreve -40
+KPX Uring Acircumflex -40
+KPX Uring Adieresis -40
+KPX Uring Agrave -40
+KPX Uring Amacron -40
+KPX Uring Aogonek -40
+KPX Uring Aring -40
+KPX Uring Atilde -40
+KPX Uring comma -40
+KPX Uring period -40
+KPX V A -80
+KPX V Aacute -80
+KPX V Abreve -80
+KPX V Acircumflex -80
+KPX V Adieresis -80
+KPX V Agrave -80
+KPX V Amacron -80
+KPX V Aogonek -80
+KPX V Aring -80
+KPX V Atilde -80
+KPX V G -40
+KPX V Gbreve -40
+KPX V Gcommaaccent -40
+KPX V O -40
+KPX V Oacute -40
+KPX V Ocircumflex -40
+KPX V Odieresis -40
+KPX V Ograve -40
+KPX V Ohungarumlaut -40
+KPX V Omacron -40
+KPX V Oslash -40
+KPX V Otilde -40
+KPX V a -70
+KPX V aacute -70
+KPX V abreve -70
+KPX V acircumflex -70
+KPX V adieresis -70
+KPX V agrave -70
+KPX V amacron -70
+KPX V aogonek -70
+KPX V aring -70
+KPX V atilde -70
+KPX V colon -40
+KPX V comma -125
+KPX V e -80
+KPX V eacute -80
+KPX V ecaron -80
+KPX V ecircumflex -80
+KPX V edieresis -80
+KPX V edotaccent -80
+KPX V egrave -80
+KPX V emacron -80
+KPX V eogonek -80
+KPX V hyphen -80
+KPX V o -80
+KPX V oacute -80
+KPX V ocircumflex -80
+KPX V odieresis -80
+KPX V ograve -80
+KPX V ohungarumlaut -80
+KPX V omacron -80
+KPX V oslash -80
+KPX V otilde -80
+KPX V period -125
+KPX V semicolon -40
+KPX V u -70
+KPX V uacute -70
+KPX V ucircumflex -70
+KPX V udieresis -70
+KPX V ugrave -70
+KPX V uhungarumlaut -70
+KPX V umacron -70
+KPX V uogonek -70
+KPX V uring -70
+KPX W A -50
+KPX W Aacute -50
+KPX W Abreve -50
+KPX W Acircumflex -50
+KPX W Adieresis -50
+KPX W Agrave -50
+KPX W Amacron -50
+KPX W Aogonek -50
+KPX W Aring -50
+KPX W Atilde -50
+KPX W O -20
+KPX W Oacute -20
+KPX W Ocircumflex -20
+KPX W Odieresis -20
+KPX W Ograve -20
+KPX W Ohungarumlaut -20
+KPX W Omacron -20
+KPX W Oslash -20
+KPX W Otilde -20
+KPX W a -40
+KPX W aacute -40
+KPX W abreve -40
+KPX W acircumflex -40
+KPX W adieresis -40
+KPX W agrave -40
+KPX W amacron -40
+KPX W aogonek -40
+KPX W aring -40
+KPX W atilde -40
+KPX W comma -80
+KPX W e -30
+KPX W eacute -30
+KPX W ecaron -30
+KPX W ecircumflex -30
+KPX W edieresis -30
+KPX W edotaccent -30
+KPX W egrave -30
+KPX W emacron -30
+KPX W eogonek -30
+KPX W hyphen -40
+KPX W o -30
+KPX W oacute -30
+KPX W ocircumflex -30
+KPX W odieresis -30
+KPX W ograve -30
+KPX W ohungarumlaut -30
+KPX W omacron -30
+KPX W oslash -30
+KPX W otilde -30
+KPX W period -80
+KPX W u -30
+KPX W uacute -30
+KPX W ucircumflex -30
+KPX W udieresis -30
+KPX W ugrave -30
+KPX W uhungarumlaut -30
+KPX W umacron -30
+KPX W uogonek -30
+KPX W uring -30
+KPX W y -20
+KPX W yacute -20
+KPX W ydieresis -20
+KPX Y A -110
+KPX Y Aacute -110
+KPX Y Abreve -110
+KPX Y Acircumflex -110
+KPX Y Adieresis -110
+KPX Y Agrave -110
+KPX Y Amacron -110
+KPX Y Aogonek -110
+KPX Y Aring -110
+KPX Y Atilde -110
+KPX Y O -85
+KPX Y Oacute -85
+KPX Y Ocircumflex -85
+KPX Y Odieresis -85
+KPX Y Ograve -85
+KPX Y Ohungarumlaut -85
+KPX Y Omacron -85
+KPX Y Oslash -85
+KPX Y Otilde -85
+KPX Y a -140
+KPX Y aacute -140
+KPX Y abreve -70
+KPX Y acircumflex -140
+KPX Y adieresis -140
+KPX Y agrave -140
+KPX Y amacron -70
+KPX Y aogonek -140
+KPX Y aring -140
+KPX Y atilde -140
+KPX Y colon -60
+KPX Y comma -140
+KPX Y e -140
+KPX Y eacute -140
+KPX Y ecaron -140
+KPX Y ecircumflex -140
+KPX Y edieresis -140
+KPX Y edotaccent -140
+KPX Y egrave -140
+KPX Y emacron -70
+KPX Y eogonek -140
+KPX Y hyphen -140
+KPX Y i -20
+KPX Y iacute -20
+KPX Y iogonek -20
+KPX Y o -140
+KPX Y oacute -140
+KPX Y ocircumflex -140
+KPX Y odieresis -140
+KPX Y ograve -140
+KPX Y ohungarumlaut -140
+KPX Y omacron -140
+KPX Y oslash -140
+KPX Y otilde -140
+KPX Y period -140
+KPX Y semicolon -60
+KPX Y u -110
+KPX Y uacute -110
+KPX Y ucircumflex -110
+KPX Y udieresis -110
+KPX Y ugrave -110
+KPX Y uhungarumlaut -110
+KPX Y umacron -110
+KPX Y uogonek -110
+KPX Y uring -110
+KPX Yacute A -110
+KPX Yacute Aacute -110
+KPX Yacute Abreve -110
+KPX Yacute Acircumflex -110
+KPX Yacute Adieresis -110
+KPX Yacute Agrave -110
+KPX Yacute Amacron -110
+KPX Yacute Aogonek -110
+KPX Yacute Aring -110
+KPX Yacute Atilde -110
+KPX Yacute O -85
+KPX Yacute Oacute -85
+KPX Yacute Ocircumflex -85
+KPX Yacute Odieresis -85
+KPX Yacute Ograve -85
+KPX Yacute Ohungarumlaut -85
+KPX Yacute Omacron -85
+KPX Yacute Oslash -85
+KPX Yacute Otilde -85
+KPX Yacute a -140
+KPX Yacute aacute -140
+KPX Yacute abreve -70
+KPX Yacute acircumflex -140
+KPX Yacute adieresis -140
+KPX Yacute agrave -140
+KPX Yacute amacron -70
+KPX Yacute aogonek -140
+KPX Yacute aring -140
+KPX Yacute atilde -70
+KPX Yacute colon -60
+KPX Yacute comma -140
+KPX Yacute e -140
+KPX Yacute eacute -140
+KPX Yacute ecaron -140
+KPX Yacute ecircumflex -140
+KPX Yacute edieresis -140
+KPX Yacute edotaccent -140
+KPX Yacute egrave -140
+KPX Yacute emacron -70
+KPX Yacute eogonek -140
+KPX Yacute hyphen -140
+KPX Yacute i -20
+KPX Yacute iacute -20
+KPX Yacute iogonek -20
+KPX Yacute o -140
+KPX Yacute oacute -140
+KPX Yacute ocircumflex -140
+KPX Yacute odieresis -140
+KPX Yacute ograve -140
+KPX Yacute ohungarumlaut -140
+KPX Yacute omacron -70
+KPX Yacute oslash -140
+KPX Yacute otilde -140
+KPX Yacute period -140
+KPX Yacute semicolon -60
+KPX Yacute u -110
+KPX Yacute uacute -110
+KPX Yacute ucircumflex -110
+KPX Yacute udieresis -110
+KPX Yacute ugrave -110
+KPX Yacute uhungarumlaut -110
+KPX Yacute umacron -110
+KPX Yacute uogonek -110
+KPX Yacute uring -110
+KPX Ydieresis A -110
+KPX Ydieresis Aacute -110
+KPX Ydieresis Abreve -110
+KPX Ydieresis Acircumflex -110
+KPX Ydieresis Adieresis -110
+KPX Ydieresis Agrave -110
+KPX Ydieresis Amacron -110
+KPX Ydieresis Aogonek -110
+KPX Ydieresis Aring -110
+KPX Ydieresis Atilde -110
+KPX Ydieresis O -85
+KPX Ydieresis Oacute -85
+KPX Ydieresis Ocircumflex -85
+KPX Ydieresis Odieresis -85
+KPX Ydieresis Ograve -85
+KPX Ydieresis Ohungarumlaut -85
+KPX Ydieresis Omacron -85
+KPX Ydieresis Oslash -85
+KPX Ydieresis Otilde -85
+KPX Ydieresis a -140
+KPX Ydieresis aacute -140
+KPX Ydieresis abreve -70
+KPX Ydieresis acircumflex -140
+KPX Ydieresis adieresis -140
+KPX Ydieresis agrave -140
+KPX Ydieresis amacron -70
+KPX Ydieresis aogonek -140
+KPX Ydieresis aring -140
+KPX Ydieresis atilde -70
+KPX Ydieresis colon -60
+KPX Ydieresis comma -140
+KPX Ydieresis e -140
+KPX Ydieresis eacute -140
+KPX Ydieresis ecaron -140
+KPX Ydieresis ecircumflex -140
+KPX Ydieresis edieresis -140
+KPX Ydieresis edotaccent -140
+KPX Ydieresis egrave -140
+KPX Ydieresis emacron -70
+KPX Ydieresis eogonek -140
+KPX Ydieresis hyphen -140
+KPX Ydieresis i -20
+KPX Ydieresis iacute -20
+KPX Ydieresis iogonek -20
+KPX Ydieresis o -140
+KPX Ydieresis oacute -140
+KPX Ydieresis ocircumflex -140
+KPX Ydieresis odieresis -140
+KPX Ydieresis ograve -140
+KPX Ydieresis ohungarumlaut -140
+KPX Ydieresis omacron -140
+KPX Ydieresis oslash -140
+KPX Ydieresis otilde -140
+KPX Ydieresis period -140
+KPX Ydieresis semicolon -60
+KPX Ydieresis u -110
+KPX Ydieresis uacute -110
+KPX Ydieresis ucircumflex -110
+KPX Ydieresis udieresis -110
+KPX Ydieresis ugrave -110
+KPX Ydieresis uhungarumlaut -110
+KPX Ydieresis umacron -110
+KPX Ydieresis uogonek -110
+KPX Ydieresis uring -110
+KPX a v -20
+KPX a w -20
+KPX a y -30
+KPX a yacute -30
+KPX a ydieresis -30
+KPX aacute v -20
+KPX aacute w -20
+KPX aacute y -30
+KPX aacute yacute -30
+KPX aacute ydieresis -30
+KPX abreve v -20
+KPX abreve w -20
+KPX abreve y -30
+KPX abreve yacute -30
+KPX abreve ydieresis -30
+KPX acircumflex v -20
+KPX acircumflex w -20
+KPX acircumflex y -30
+KPX acircumflex yacute -30
+KPX acircumflex ydieresis -30
+KPX adieresis v -20
+KPX adieresis w -20
+KPX adieresis y -30
+KPX adieresis yacute -30
+KPX adieresis ydieresis -30
+KPX agrave v -20
+KPX agrave w -20
+KPX agrave y -30
+KPX agrave yacute -30
+KPX agrave ydieresis -30
+KPX amacron v -20
+KPX amacron w -20
+KPX amacron y -30
+KPX amacron yacute -30
+KPX amacron ydieresis -30
+KPX aogonek v -20
+KPX aogonek w -20
+KPX aogonek y -30
+KPX aogonek yacute -30
+KPX aogonek ydieresis -30
+KPX aring v -20
+KPX aring w -20
+KPX aring y -30
+KPX aring yacute -30
+KPX aring ydieresis -30
+KPX atilde v -20
+KPX atilde w -20
+KPX atilde y -30
+KPX atilde yacute -30
+KPX atilde ydieresis -30
+KPX b b -10
+KPX b comma -40
+KPX b l -20
+KPX b lacute -20
+KPX b lcommaaccent -20
+KPX b lslash -20
+KPX b period -40
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX b v -20
+KPX b y -20
+KPX b yacute -20
+KPX b ydieresis -20
+KPX c comma -15
+KPX c k -20
+KPX c kcommaaccent -20
+KPX cacute comma -15
+KPX cacute k -20
+KPX cacute kcommaaccent -20
+KPX ccaron comma -15
+KPX ccaron k -20
+KPX ccaron kcommaaccent -20
+KPX ccedilla comma -15
+KPX ccedilla k -20
+KPX ccedilla kcommaaccent -20
+KPX colon space -50
+KPX comma quotedblright -100
+KPX comma quoteright -100
+KPX e comma -15
+KPX e period -15
+KPX e v -30
+KPX e w -20
+KPX e x -30
+KPX e y -20
+KPX e yacute -20
+KPX e ydieresis -20
+KPX eacute comma -15
+KPX eacute period -15
+KPX eacute v -30
+KPX eacute w -20
+KPX eacute x -30
+KPX eacute y -20
+KPX eacute yacute -20
+KPX eacute ydieresis -20
+KPX ecaron comma -15
+KPX ecaron period -15
+KPX ecaron v -30
+KPX ecaron w -20
+KPX ecaron x -30
+KPX ecaron y -20
+KPX ecaron yacute -20
+KPX ecaron ydieresis -20
+KPX ecircumflex comma -15
+KPX ecircumflex period -15
+KPX ecircumflex v -30
+KPX ecircumflex w -20
+KPX ecircumflex x -30
+KPX ecircumflex y -20
+KPX ecircumflex yacute -20
+KPX ecircumflex ydieresis -20
+KPX edieresis comma -15
+KPX edieresis period -15
+KPX edieresis v -30
+KPX edieresis w -20
+KPX edieresis x -30
+KPX edieresis y -20
+KPX edieresis yacute -20
+KPX edieresis ydieresis -20
+KPX edotaccent comma -15
+KPX edotaccent period -15
+KPX edotaccent v -30
+KPX edotaccent w -20
+KPX edotaccent x -30
+KPX edotaccent y -20
+KPX edotaccent yacute -20
+KPX edotaccent ydieresis -20
+KPX egrave comma -15
+KPX egrave period -15
+KPX egrave v -30
+KPX egrave w -20
+KPX egrave x -30
+KPX egrave y -20
+KPX egrave yacute -20
+KPX egrave ydieresis -20
+KPX emacron comma -15
+KPX emacron period -15
+KPX emacron v -30
+KPX emacron w -20
+KPX emacron x -30
+KPX emacron y -20
+KPX emacron yacute -20
+KPX emacron ydieresis -20
+KPX eogonek comma -15
+KPX eogonek period -15
+KPX eogonek v -30
+KPX eogonek w -20
+KPX eogonek x -30
+KPX eogonek y -20
+KPX eogonek yacute -20
+KPX eogonek ydieresis -20
+KPX f a -30
+KPX f aacute -30
+KPX f abreve -30
+KPX f acircumflex -30
+KPX f adieresis -30
+KPX f agrave -30
+KPX f amacron -30
+KPX f aogonek -30
+KPX f aring -30
+KPX f atilde -30
+KPX f comma -30
+KPX f dotlessi -28
+KPX f e -30
+KPX f eacute -30
+KPX f ecaron -30
+KPX f ecircumflex -30
+KPX f edieresis -30
+KPX f edotaccent -30
+KPX f egrave -30
+KPX f emacron -30
+KPX f eogonek -30
+KPX f o -30
+KPX f oacute -30
+KPX f ocircumflex -30
+KPX f odieresis -30
+KPX f ograve -30
+KPX f ohungarumlaut -30
+KPX f omacron -30
+KPX f oslash -30
+KPX f otilde -30
+KPX f period -30
+KPX f quotedblright 60
+KPX f quoteright 50
+KPX g r -10
+KPX g racute -10
+KPX g rcaron -10
+KPX g rcommaaccent -10
+KPX gbreve r -10
+KPX gbreve racute -10
+KPX gbreve rcaron -10
+KPX gbreve rcommaaccent -10
+KPX gcommaaccent r -10
+KPX gcommaaccent racute -10
+KPX gcommaaccent rcaron -10
+KPX gcommaaccent rcommaaccent -10
+KPX h y -30
+KPX h yacute -30
+KPX h ydieresis -30
+KPX k e -20
+KPX k eacute -20
+KPX k ecaron -20
+KPX k ecircumflex -20
+KPX k edieresis -20
+KPX k edotaccent -20
+KPX k egrave -20
+KPX k emacron -20
+KPX k eogonek -20
+KPX k o -20
+KPX k oacute -20
+KPX k ocircumflex -20
+KPX k odieresis -20
+KPX k ograve -20
+KPX k ohungarumlaut -20
+KPX k omacron -20
+KPX k oslash -20
+KPX k otilde -20
+KPX kcommaaccent e -20
+KPX kcommaaccent eacute -20
+KPX kcommaaccent ecaron -20
+KPX kcommaaccent ecircumflex -20
+KPX kcommaaccent edieresis -20
+KPX kcommaaccent edotaccent -20
+KPX kcommaaccent egrave -20
+KPX kcommaaccent emacron -20
+KPX kcommaaccent eogonek -20
+KPX kcommaaccent o -20
+KPX kcommaaccent oacute -20
+KPX kcommaaccent ocircumflex -20
+KPX kcommaaccent odieresis -20
+KPX kcommaaccent ograve -20
+KPX kcommaaccent ohungarumlaut -20
+KPX kcommaaccent omacron -20
+KPX kcommaaccent oslash -20
+KPX kcommaaccent otilde -20
+KPX m u -10
+KPX m uacute -10
+KPX m ucircumflex -10
+KPX m udieresis -10
+KPX m ugrave -10
+KPX m uhungarumlaut -10
+KPX m umacron -10
+KPX m uogonek -10
+KPX m uring -10
+KPX m y -15
+KPX m yacute -15
+KPX m ydieresis -15
+KPX n u -10
+KPX n uacute -10
+KPX n ucircumflex -10
+KPX n udieresis -10
+KPX n ugrave -10
+KPX n uhungarumlaut -10
+KPX n umacron -10
+KPX n uogonek -10
+KPX n uring -10
+KPX n v -20
+KPX n y -15
+KPX n yacute -15
+KPX n ydieresis -15
+KPX nacute u -10
+KPX nacute uacute -10
+KPX nacute ucircumflex -10
+KPX nacute udieresis -10
+KPX nacute ugrave -10
+KPX nacute uhungarumlaut -10
+KPX nacute umacron -10
+KPX nacute uogonek -10
+KPX nacute uring -10
+KPX nacute v -20
+KPX nacute y -15
+KPX nacute yacute -15
+KPX nacute ydieresis -15
+KPX ncaron u -10
+KPX ncaron uacute -10
+KPX ncaron ucircumflex -10
+KPX ncaron udieresis -10
+KPX ncaron ugrave -10
+KPX ncaron uhungarumlaut -10
+KPX ncaron umacron -10
+KPX ncaron uogonek -10
+KPX ncaron uring -10
+KPX ncaron v -20
+KPX ncaron y -15
+KPX ncaron yacute -15
+KPX ncaron ydieresis -15
+KPX ncommaaccent u -10
+KPX ncommaaccent uacute -10
+KPX ncommaaccent ucircumflex -10
+KPX ncommaaccent udieresis -10
+KPX ncommaaccent ugrave -10
+KPX ncommaaccent uhungarumlaut -10
+KPX ncommaaccent umacron -10
+KPX ncommaaccent uogonek -10
+KPX ncommaaccent uring -10
+KPX ncommaaccent v -20
+KPX ncommaaccent y -15
+KPX ncommaaccent yacute -15
+KPX ncommaaccent ydieresis -15
+KPX ntilde u -10
+KPX ntilde uacute -10
+KPX ntilde ucircumflex -10
+KPX ntilde udieresis -10
+KPX ntilde ugrave -10
+KPX ntilde uhungarumlaut -10
+KPX ntilde umacron -10
+KPX ntilde uogonek -10
+KPX ntilde uring -10
+KPX ntilde v -20
+KPX ntilde y -15
+KPX ntilde yacute -15
+KPX ntilde ydieresis -15
+KPX o comma -40
+KPX o period -40
+KPX o v -15
+KPX o w -15
+KPX o x -30
+KPX o y -30
+KPX o yacute -30
+KPX o ydieresis -30
+KPX oacute comma -40
+KPX oacute period -40
+KPX oacute v -15
+KPX oacute w -15
+KPX oacute x -30
+KPX oacute y -30
+KPX oacute yacute -30
+KPX oacute ydieresis -30
+KPX ocircumflex comma -40
+KPX ocircumflex period -40
+KPX ocircumflex v -15
+KPX ocircumflex w -15
+KPX ocircumflex x -30
+KPX ocircumflex y -30
+KPX ocircumflex yacute -30
+KPX ocircumflex ydieresis -30
+KPX odieresis comma -40
+KPX odieresis period -40
+KPX odieresis v -15
+KPX odieresis w -15
+KPX odieresis x -30
+KPX odieresis y -30
+KPX odieresis yacute -30
+KPX odieresis ydieresis -30
+KPX ograve comma -40
+KPX ograve period -40
+KPX ograve v -15
+KPX ograve w -15
+KPX ograve x -30
+KPX ograve y -30
+KPX ograve yacute -30
+KPX ograve ydieresis -30
+KPX ohungarumlaut comma -40
+KPX ohungarumlaut period -40
+KPX ohungarumlaut v -15
+KPX ohungarumlaut w -15
+KPX ohungarumlaut x -30
+KPX ohungarumlaut y -30
+KPX ohungarumlaut yacute -30
+KPX ohungarumlaut ydieresis -30
+KPX omacron comma -40
+KPX omacron period -40
+KPX omacron v -15
+KPX omacron w -15
+KPX omacron x -30
+KPX omacron y -30
+KPX omacron yacute -30
+KPX omacron ydieresis -30
+KPX oslash a -55
+KPX oslash aacute -55
+KPX oslash abreve -55
+KPX oslash acircumflex -55
+KPX oslash adieresis -55
+KPX oslash agrave -55
+KPX oslash amacron -55
+KPX oslash aogonek -55
+KPX oslash aring -55
+KPX oslash atilde -55
+KPX oslash b -55
+KPX oslash c -55
+KPX oslash cacute -55
+KPX oslash ccaron -55
+KPX oslash ccedilla -55
+KPX oslash comma -95
+KPX oslash d -55
+KPX oslash dcroat -55
+KPX oslash e -55
+KPX oslash eacute -55
+KPX oslash ecaron -55
+KPX oslash ecircumflex -55
+KPX oslash edieresis -55
+KPX oslash edotaccent -55
+KPX oslash egrave -55
+KPX oslash emacron -55
+KPX oslash eogonek -55
+KPX oslash f -55
+KPX oslash g -55
+KPX oslash gbreve -55
+KPX oslash gcommaaccent -55
+KPX oslash h -55
+KPX oslash i -55
+KPX oslash iacute -55
+KPX oslash icircumflex -55
+KPX oslash idieresis -55
+KPX oslash igrave -55
+KPX oslash imacron -55
+KPX oslash iogonek -55
+KPX oslash j -55
+KPX oslash k -55
+KPX oslash kcommaaccent -55
+KPX oslash l -55
+KPX oslash lacute -55
+KPX oslash lcommaaccent -55
+KPX oslash lslash -55
+KPX oslash m -55
+KPX oslash n -55
+KPX oslash nacute -55
+KPX oslash ncaron -55
+KPX oslash ncommaaccent -55
+KPX oslash ntilde -55
+KPX oslash o -55
+KPX oslash oacute -55
+KPX oslash ocircumflex -55
+KPX oslash odieresis -55
+KPX oslash ograve -55
+KPX oslash ohungarumlaut -55
+KPX oslash omacron -55
+KPX oslash oslash -55
+KPX oslash otilde -55
+KPX oslash p -55
+KPX oslash period -95
+KPX oslash q -55
+KPX oslash r -55
+KPX oslash racute -55
+KPX oslash rcaron -55
+KPX oslash rcommaaccent -55
+KPX oslash s -55
+KPX oslash sacute -55
+KPX oslash scaron -55
+KPX oslash scedilla -55
+KPX oslash scommaaccent -55
+KPX oslash t -55
+KPX oslash tcommaaccent -55
+KPX oslash u -55
+KPX oslash uacute -55
+KPX oslash ucircumflex -55
+KPX oslash udieresis -55
+KPX oslash ugrave -55
+KPX oslash uhungarumlaut -55
+KPX oslash umacron -55
+KPX oslash uogonek -55
+KPX oslash uring -55
+KPX oslash v -70
+KPX oslash w -70
+KPX oslash x -85
+KPX oslash y -70
+KPX oslash yacute -70
+KPX oslash ydieresis -70
+KPX oslash z -55
+KPX oslash zacute -55
+KPX oslash zcaron -55
+KPX oslash zdotaccent -55
+KPX otilde comma -40
+KPX otilde period -40
+KPX otilde v -15
+KPX otilde w -15
+KPX otilde x -30
+KPX otilde y -30
+KPX otilde yacute -30
+KPX otilde ydieresis -30
+KPX p comma -35
+KPX p period -35
+KPX p y -30
+KPX p yacute -30
+KPX p ydieresis -30
+KPX period quotedblright -100
+KPX period quoteright -100
+KPX period space -60
+KPX quotedblright space -40
+KPX quoteleft quoteleft -57
+KPX quoteright d -50
+KPX quoteright dcroat -50
+KPX quoteright quoteright -57
+KPX quoteright r -50
+KPX quoteright racute -50
+KPX quoteright rcaron -50
+KPX quoteright rcommaaccent -50
+KPX quoteright s -50
+KPX quoteright sacute -50
+KPX quoteright scaron -50
+KPX quoteright scedilla -50
+KPX quoteright scommaaccent -50
+KPX quoteright space -70
+KPX r a -10
+KPX r aacute -10
+KPX r abreve -10
+KPX r acircumflex -10
+KPX r adieresis -10
+KPX r agrave -10
+KPX r amacron -10
+KPX r aogonek -10
+KPX r aring -10
+KPX r atilde -10
+KPX r colon 30
+KPX r comma -50
+KPX r i 15
+KPX r iacute 15
+KPX r icircumflex 15
+KPX r idieresis 15
+KPX r igrave 15
+KPX r imacron 15
+KPX r iogonek 15
+KPX r k 15
+KPX r kcommaaccent 15
+KPX r l 15
+KPX r lacute 15
+KPX r lcommaaccent 15
+KPX r lslash 15
+KPX r m 25
+KPX r n 25
+KPX r nacute 25
+KPX r ncaron 25
+KPX r ncommaaccent 25
+KPX r ntilde 25
+KPX r p 30
+KPX r period -50
+KPX r semicolon 30
+KPX r t 40
+KPX r tcommaaccent 40
+KPX r u 15
+KPX r uacute 15
+KPX r ucircumflex 15
+KPX r udieresis 15
+KPX r ugrave 15
+KPX r uhungarumlaut 15
+KPX r umacron 15
+KPX r uogonek 15
+KPX r uring 15
+KPX r v 30
+KPX r y 30
+KPX r yacute 30
+KPX r ydieresis 30
+KPX racute a -10
+KPX racute aacute -10
+KPX racute abreve -10
+KPX racute acircumflex -10
+KPX racute adieresis -10
+KPX racute agrave -10
+KPX racute amacron -10
+KPX racute aogonek -10
+KPX racute aring -10
+KPX racute atilde -10
+KPX racute colon 30
+KPX racute comma -50
+KPX racute i 15
+KPX racute iacute 15
+KPX racute icircumflex 15
+KPX racute idieresis 15
+KPX racute igrave 15
+KPX racute imacron 15
+KPX racute iogonek 15
+KPX racute k 15
+KPX racute kcommaaccent 15
+KPX racute l 15
+KPX racute lacute 15
+KPX racute lcommaaccent 15
+KPX racute lslash 15
+KPX racute m 25
+KPX racute n 25
+KPX racute nacute 25
+KPX racute ncaron 25
+KPX racute ncommaaccent 25
+KPX racute ntilde 25
+KPX racute p 30
+KPX racute period -50
+KPX racute semicolon 30
+KPX racute t 40
+KPX racute tcommaaccent 40
+KPX racute u 15
+KPX racute uacute 15
+KPX racute ucircumflex 15
+KPX racute udieresis 15
+KPX racute ugrave 15
+KPX racute uhungarumlaut 15
+KPX racute umacron 15
+KPX racute uogonek 15
+KPX racute uring 15
+KPX racute v 30
+KPX racute y 30
+KPX racute yacute 30
+KPX racute ydieresis 30
+KPX rcaron a -10
+KPX rcaron aacute -10
+KPX rcaron abreve -10
+KPX rcaron acircumflex -10
+KPX rcaron adieresis -10
+KPX rcaron agrave -10
+KPX rcaron amacron -10
+KPX rcaron aogonek -10
+KPX rcaron aring -10
+KPX rcaron atilde -10
+KPX rcaron colon 30
+KPX rcaron comma -50
+KPX rcaron i 15
+KPX rcaron iacute 15
+KPX rcaron icircumflex 15
+KPX rcaron idieresis 15
+KPX rcaron igrave 15
+KPX rcaron imacron 15
+KPX rcaron iogonek 15
+KPX rcaron k 15
+KPX rcaron kcommaaccent 15
+KPX rcaron l 15
+KPX rcaron lacute 15
+KPX rcaron lcommaaccent 15
+KPX rcaron lslash 15
+KPX rcaron m 25
+KPX rcaron n 25
+KPX rcaron nacute 25
+KPX rcaron ncaron 25
+KPX rcaron ncommaaccent 25
+KPX rcaron ntilde 25
+KPX rcaron p 30
+KPX rcaron period -50
+KPX rcaron semicolon 30
+KPX rcaron t 40
+KPX rcaron tcommaaccent 40
+KPX rcaron u 15
+KPX rcaron uacute 15
+KPX rcaron ucircumflex 15
+KPX rcaron udieresis 15
+KPX rcaron ugrave 15
+KPX rcaron uhungarumlaut 15
+KPX rcaron umacron 15
+KPX rcaron uogonek 15
+KPX rcaron uring 15
+KPX rcaron v 30
+KPX rcaron y 30
+KPX rcaron yacute 30
+KPX rcaron ydieresis 30
+KPX rcommaaccent a -10
+KPX rcommaaccent aacute -10
+KPX rcommaaccent abreve -10
+KPX rcommaaccent acircumflex -10
+KPX rcommaaccent adieresis -10
+KPX rcommaaccent agrave -10
+KPX rcommaaccent amacron -10
+KPX rcommaaccent aogonek -10
+KPX rcommaaccent aring -10
+KPX rcommaaccent atilde -10
+KPX rcommaaccent colon 30
+KPX rcommaaccent comma -50
+KPX rcommaaccent i 15
+KPX rcommaaccent iacute 15
+KPX rcommaaccent icircumflex 15
+KPX rcommaaccent idieresis 15
+KPX rcommaaccent igrave 15
+KPX rcommaaccent imacron 15
+KPX rcommaaccent iogonek 15
+KPX rcommaaccent k 15
+KPX rcommaaccent kcommaaccent 15
+KPX rcommaaccent l 15
+KPX rcommaaccent lacute 15
+KPX rcommaaccent lcommaaccent 15
+KPX rcommaaccent lslash 15
+KPX rcommaaccent m 25
+KPX rcommaaccent n 25
+KPX rcommaaccent nacute 25
+KPX rcommaaccent ncaron 25
+KPX rcommaaccent ncommaaccent 25
+KPX rcommaaccent ntilde 25
+KPX rcommaaccent p 30
+KPX rcommaaccent period -50
+KPX rcommaaccent semicolon 30
+KPX rcommaaccent t 40
+KPX rcommaaccent tcommaaccent 40
+KPX rcommaaccent u 15
+KPX rcommaaccent uacute 15
+KPX rcommaaccent ucircumflex 15
+KPX rcommaaccent udieresis 15
+KPX rcommaaccent ugrave 15
+KPX rcommaaccent uhungarumlaut 15
+KPX rcommaaccent umacron 15
+KPX rcommaaccent uogonek 15
+KPX rcommaaccent uring 15
+KPX rcommaaccent v 30
+KPX rcommaaccent y 30
+KPX rcommaaccent yacute 30
+KPX rcommaaccent ydieresis 30
+KPX s comma -15
+KPX s period -15
+KPX s w -30
+KPX sacute comma -15
+KPX sacute period -15
+KPX sacute w -30
+KPX scaron comma -15
+KPX scaron period -15
+KPX scaron w -30
+KPX scedilla comma -15
+KPX scedilla period -15
+KPX scedilla w -30
+KPX scommaaccent comma -15
+KPX scommaaccent period -15
+KPX scommaaccent w -30
+KPX semicolon space -50
+KPX space T -50
+KPX space Tcaron -50
+KPX space Tcommaaccent -50
+KPX space V -50
+KPX space W -40
+KPX space Y -90
+KPX space Yacute -90
+KPX space Ydieresis -90
+KPX space quotedblleft -30
+KPX space quoteleft -60
+KPX v a -25
+KPX v aacute -25
+KPX v abreve -25
+KPX v acircumflex -25
+KPX v adieresis -25
+KPX v agrave -25
+KPX v amacron -25
+KPX v aogonek -25
+KPX v aring -25
+KPX v atilde -25
+KPX v comma -80
+KPX v e -25
+KPX v eacute -25
+KPX v ecaron -25
+KPX v ecircumflex -25
+KPX v edieresis -25
+KPX v edotaccent -25
+KPX v egrave -25
+KPX v emacron -25
+KPX v eogonek -25
+KPX v o -25
+KPX v oacute -25
+KPX v ocircumflex -25
+KPX v odieresis -25
+KPX v ograve -25
+KPX v ohungarumlaut -25
+KPX v omacron -25
+KPX v oslash -25
+KPX v otilde -25
+KPX v period -80
+KPX w a -15
+KPX w aacute -15
+KPX w abreve -15
+KPX w acircumflex -15
+KPX w adieresis -15
+KPX w agrave -15
+KPX w amacron -15
+KPX w aogonek -15
+KPX w aring -15
+KPX w atilde -15
+KPX w comma -60
+KPX w e -10
+KPX w eacute -10
+KPX w ecaron -10
+KPX w ecircumflex -10
+KPX w edieresis -10
+KPX w edotaccent -10
+KPX w egrave -10
+KPX w emacron -10
+KPX w eogonek -10
+KPX w o -10
+KPX w oacute -10
+KPX w ocircumflex -10
+KPX w odieresis -10
+KPX w ograve -10
+KPX w ohungarumlaut -10
+KPX w omacron -10
+KPX w oslash -10
+KPX w otilde -10
+KPX w period -60
+KPX x e -30
+KPX x eacute -30
+KPX x ecaron -30
+KPX x ecircumflex -30
+KPX x edieresis -30
+KPX x edotaccent -30
+KPX x egrave -30
+KPX x emacron -30
+KPX x eogonek -30
+KPX y a -20
+KPX y aacute -20
+KPX y abreve -20
+KPX y acircumflex -20
+KPX y adieresis -20
+KPX y agrave -20
+KPX y amacron -20
+KPX y aogonek -20
+KPX y aring -20
+KPX y atilde -20
+KPX y comma -100
+KPX y e -20
+KPX y eacute -20
+KPX y ecaron -20
+KPX y ecircumflex -20
+KPX y edieresis -20
+KPX y edotaccent -20
+KPX y egrave -20
+KPX y emacron -20
+KPX y eogonek -20
+KPX y o -20
+KPX y oacute -20
+KPX y ocircumflex -20
+KPX y odieresis -20
+KPX y ograve -20
+KPX y ohungarumlaut -20
+KPX y omacron -20
+KPX y oslash -20
+KPX y otilde -20
+KPX y period -100
+KPX yacute a -20
+KPX yacute aacute -20
+KPX yacute abreve -20
+KPX yacute acircumflex -20
+KPX yacute adieresis -20
+KPX yacute agrave -20
+KPX yacute amacron -20
+KPX yacute aogonek -20
+KPX yacute aring -20
+KPX yacute atilde -20
+KPX yacute comma -100
+KPX yacute e -20
+KPX yacute eacute -20
+KPX yacute ecaron -20
+KPX yacute ecircumflex -20
+KPX yacute edieresis -20
+KPX yacute edotaccent -20
+KPX yacute egrave -20
+KPX yacute emacron -20
+KPX yacute eogonek -20
+KPX yacute o -20
+KPX yacute oacute -20
+KPX yacute ocircumflex -20
+KPX yacute odieresis -20
+KPX yacute ograve -20
+KPX yacute ohungarumlaut -20
+KPX yacute omacron -20
+KPX yacute oslash -20
+KPX yacute otilde -20
+KPX yacute period -100
+KPX ydieresis a -20
+KPX ydieresis aacute -20
+KPX ydieresis abreve -20
+KPX ydieresis acircumflex -20
+KPX ydieresis adieresis -20
+KPX ydieresis agrave -20
+KPX ydieresis amacron -20
+KPX ydieresis aogonek -20
+KPX ydieresis aring -20
+KPX ydieresis atilde -20
+KPX ydieresis comma -100
+KPX ydieresis e -20
+KPX ydieresis eacute -20
+KPX ydieresis ecaron -20
+KPX ydieresis ecircumflex -20
+KPX ydieresis edieresis -20
+KPX ydieresis edotaccent -20
+KPX ydieresis egrave -20
+KPX ydieresis emacron -20
+KPX ydieresis eogonek -20
+KPX ydieresis o -20
+KPX ydieresis oacute -20
+KPX ydieresis ocircumflex -20
+KPX ydieresis odieresis -20
+KPX ydieresis ograve -20
+KPX ydieresis ohungarumlaut -20
+KPX ydieresis omacron -20
+KPX ydieresis oslash -20
+KPX ydieresis otilde -20
+KPX ydieresis period -100
+KPX z e -15
+KPX z eacute -15
+KPX z ecaron -15
+KPX z ecircumflex -15
+KPX z edieresis -15
+KPX z edotaccent -15
+KPX z egrave -15
+KPX z emacron -15
+KPX z eogonek -15
+KPX z o -15
+KPX z oacute -15
+KPX z ocircumflex -15
+KPX z odieresis -15
+KPX z ograve -15
+KPX z ohungarumlaut -15
+KPX z omacron -15
+KPX z oslash -15
+KPX z otilde -15
+KPX zacute e -15
+KPX zacute eacute -15
+KPX zacute ecaron -15
+KPX zacute ecircumflex -15
+KPX zacute edieresis -15
+KPX zacute edotaccent -15
+KPX zacute egrave -15
+KPX zacute emacron -15
+KPX zacute eogonek -15
+KPX zacute o -15
+KPX zacute oacute -15
+KPX zacute ocircumflex -15
+KPX zacute odieresis -15
+KPX zacute ograve -15
+KPX zacute ohungarumlaut -15
+KPX zacute omacron -15
+KPX zacute oslash -15
+KPX zacute otilde -15
+KPX zcaron e -15
+KPX zcaron eacute -15
+KPX zcaron ecaron -15
+KPX zcaron ecircumflex -15
+KPX zcaron edieresis -15
+KPX zcaron edotaccent -15
+KPX zcaron egrave -15
+KPX zcaron emacron -15
+KPX zcaron eogonek -15
+KPX zcaron o -15
+KPX zcaron oacute -15
+KPX zcaron ocircumflex -15
+KPX zcaron odieresis -15
+KPX zcaron ograve -15
+KPX zcaron ohungarumlaut -15
+KPX zcaron omacron -15
+KPX zcaron oslash -15
+KPX zcaron otilde -15
+KPX zdotaccent e -15
+KPX zdotaccent eacute -15
+KPX zdotaccent ecaron -15
+KPX zdotaccent ecircumflex -15
+KPX zdotaccent edieresis -15
+KPX zdotaccent edotaccent -15
+KPX zdotaccent egrave -15
+KPX zdotaccent emacron -15
+KPX zdotaccent eogonek -15
+KPX zdotaccent o -15
+KPX zdotaccent oacute -15
+KPX zdotaccent ocircumflex -15
+KPX zdotaccent odieresis -15
+KPX zdotaccent ograve -15
+KPX zdotaccent ohungarumlaut -15
+KPX zdotaccent omacron -15
+KPX zdotaccent oslash -15
+KPX zdotaccent otilde -15
+EndKernPairs
+EndKernData
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/License-Adobe.txt pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/License-Adobe.txt
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/License-Adobe.txt 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/License-Adobe.txt 2005-11-01 12:49:20.000000000 +0000
@@ -0,0 +1,65 @@
+This file and the 14 PostScript(R) AFM files it accompanies may be
+used, copied, and distributed for any purpose and without charge, with
+or without modification, provided that all copyright notices are
+retained; that the AFM files are not distributed without this file;
+that all modifications to this file or any of the AFM files are
+prominently noted in the modified file(s); and that this paragraph is
+not modified. Adobe Systems has no responsibility or obligation to
+support the use of the AFM files.
+
+
+Courier-Bold.afm:
+Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated.
+All Rights Reserved.
+
+Courier-BoldOblique.afm:
+Copyright (c) 1989, 1990, 1991, 1993, 1997 Adobe Systems Incorporated.
+All Rights Reserved.
+
+Courier-Oblique.afm:
+Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated.
+
+All Rights Reserved.
+Courier.afm:
+Copyright (c) 1989, 1990, 1991, 1992, 1993, 1997 Adobe Systems Incorporated.
+All Rights Reserved.
+
+Helvetica-Bold.afm:
+Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.
+All Rights Reserved.
+
+Helvetica-BoldOblique.afm:
+Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.
+All Rights Reserved.
+
+Helvetica-Oblique.afm:
+Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.
+All Rights Reserved.
+
+Helvetica.afm:
+Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.
+All Rights Reserved.
+
+Symbol.afm:
+Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated.
+All rights reserved.
+
+Times-Bold.afm:
+Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.
+All Rights Reserved.
+
+Times-BoldItalic.afm:
+Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.
+All Rights Reserved.
+
+Times-Italic.afm:
+Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.
+All Rights Reserved.
+
+Times-Roman.afm:
+Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated.
+All Rights Reserved.
+
+ZapfDingbats.afm:
+Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated.
+All Rights Reserved.
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Symbol.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Symbol.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Symbol.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Symbol.afm 2004-05-26 16:06:20.000000000 +0000
@@ -0,0 +1,213 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Thu May 1 15:12:25 1997
+Comment UniqueID 43064
+Comment VMusage 30820 39997
+FontName Symbol
+FullName Symbol
+FamilyName Symbol
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+CharacterSet Special
+FontBBox -180 -293 1090 1010
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.008
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1997 Adobe Systems Incorporated. All rights reserved.
+EncodingScheme FontSpecific
+StdHW 92
+StdVW 85
+StartCharMetrics 190
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 128 -17 240 672 ;
+C 34 ; WX 713 ; N universal ; B 31 0 681 705 ;
+C 35 ; WX 500 ; N numbersign ; B 20 -16 481 673 ;
+C 36 ; WX 549 ; N existential ; B 25 0 478 707 ;
+C 37 ; WX 833 ; N percent ; B 63 -36 771 655 ;
+C 38 ; WX 778 ; N ampersand ; B 41 -18 750 661 ;
+C 39 ; WX 439 ; N suchthat ; B 48 -17 414 500 ;
+C 40 ; WX 333 ; N parenleft ; B 53 -191 300 673 ;
+C 41 ; WX 333 ; N parenright ; B 30 -191 277 673 ;
+C 42 ; WX 500 ; N asteriskmath ; B 65 134 427 551 ;
+C 43 ; WX 549 ; N plus ; B 10 0 539 533 ;
+C 44 ; WX 250 ; N comma ; B 56 -152 194 104 ;
+C 45 ; WX 549 ; N minus ; B 11 233 535 288 ;
+C 46 ; WX 250 ; N period ; B 69 -17 181 95 ;
+C 47 ; WX 278 ; N slash ; B 0 -18 254 646 ;
+C 48 ; WX 500 ; N zero ; B 24 -14 476 685 ;
+C 49 ; WX 500 ; N one ; B 117 0 390 673 ;
+C 50 ; WX 500 ; N two ; B 25 0 475 685 ;
+C 51 ; WX 500 ; N three ; B 43 -14 435 685 ;
+C 52 ; WX 500 ; N four ; B 15 0 469 685 ;
+C 53 ; WX 500 ; N five ; B 32 -14 445 690 ;
+C 54 ; WX 500 ; N six ; B 34 -14 468 685 ;
+C 55 ; WX 500 ; N seven ; B 24 -16 448 673 ;
+C 56 ; WX 500 ; N eight ; B 56 -14 445 685 ;
+C 57 ; WX 500 ; N nine ; B 30 -18 459 685 ;
+C 58 ; WX 278 ; N colon ; B 81 -17 193 460 ;
+C 59 ; WX 278 ; N semicolon ; B 83 -152 221 460 ;
+C 60 ; WX 549 ; N less ; B 26 0 523 522 ;
+C 61 ; WX 549 ; N equal ; B 11 141 537 390 ;
+C 62 ; WX 549 ; N greater ; B 26 0 523 522 ;
+C 63 ; WX 444 ; N question ; B 70 -17 412 686 ;
+C 64 ; WX 549 ; N congruent ; B 11 0 537 475 ;
+C 65 ; WX 722 ; N Alpha ; B 4 0 684 673 ;
+C 66 ; WX 667 ; N Beta ; B 29 0 592 673 ;
+C 67 ; WX 722 ; N Chi ; B -9 0 704 673 ;
+C 68 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C 69 ; WX 611 ; N Epsilon ; B 32 0 617 673 ;
+C 70 ; WX 763 ; N Phi ; B 26 0 741 673 ;
+C 71 ; WX 603 ; N Gamma ; B 24 0 609 673 ;
+C 72 ; WX 722 ; N Eta ; B 39 0 729 673 ;
+C 73 ; WX 333 ; N Iota ; B 32 0 316 673 ;
+C 74 ; WX 631 ; N theta1 ; B 18 -18 623 689 ;
+C 75 ; WX 722 ; N Kappa ; B 35 0 722 673 ;
+C 76 ; WX 686 ; N Lambda ; B 6 0 680 688 ;
+C 77 ; WX 889 ; N Mu ; B 28 0 887 673 ;
+C 78 ; WX 722 ; N Nu ; B 29 -8 720 673 ;
+C 79 ; WX 722 ; N Omicron ; B 41 -17 715 685 ;
+C 80 ; WX 768 ; N Pi ; B 25 0 745 673 ;
+C 81 ; WX 741 ; N Theta ; B 41 -17 715 685 ;
+C 82 ; WX 556 ; N Rho ; B 28 0 563 673 ;
+C 83 ; WX 592 ; N Sigma ; B 5 0 589 673 ;
+C 84 ; WX 611 ; N Tau ; B 33 0 607 673 ;
+C 85 ; WX 690 ; N Upsilon ; B -8 0 694 673 ;
+C 86 ; WX 439 ; N sigma1 ; B 40 -233 436 500 ;
+C 87 ; WX 768 ; N Omega ; B 34 0 736 688 ;
+C 88 ; WX 645 ; N Xi ; B 40 0 599 673 ;
+C 89 ; WX 795 ; N Psi ; B 15 0 781 684 ;
+C 90 ; WX 611 ; N Zeta ; B 44 0 636 673 ;
+C 91 ; WX 333 ; N bracketleft ; B 86 -155 299 674 ;
+C 92 ; WX 863 ; N therefore ; B 163 0 701 487 ;
+C 93 ; WX 333 ; N bracketright ; B 33 -155 246 674 ;
+C 94 ; WX 658 ; N perpendicular ; B 15 0 652 674 ;
+C 95 ; WX 500 ; N underscore ; B -2 -125 502 -75 ;
+C 96 ; WX 500 ; N radicalex ; B 480 881 1090 917 ;
+C 97 ; WX 631 ; N alpha ; B 41 -18 622 500 ;
+C 98 ; WX 549 ; N beta ; B 61 -223 515 741 ;
+C 99 ; WX 549 ; N chi ; B 12 -231 522 499 ;
+C 100 ; WX 494 ; N delta ; B 40 -19 481 740 ;
+C 101 ; WX 439 ; N epsilon ; B 22 -19 427 502 ;
+C 102 ; WX 521 ; N phi ; B 28 -224 492 673 ;
+C 103 ; WX 411 ; N gamma ; B 5 -225 484 499 ;
+C 104 ; WX 603 ; N eta ; B 0 -202 527 514 ;
+C 105 ; WX 329 ; N iota ; B 0 -17 301 503 ;
+C 106 ; WX 603 ; N phi1 ; B 36 -224 587 499 ;
+C 107 ; WX 549 ; N kappa ; B 33 0 558 501 ;
+C 108 ; WX 549 ; N lambda ; B 24 -17 548 739 ;
+C 109 ; WX 576 ; N mu ; B 33 -223 567 500 ;
+C 110 ; WX 521 ; N nu ; B -9 -16 475 507 ;
+C 111 ; WX 549 ; N omicron ; B 35 -19 501 499 ;
+C 112 ; WX 549 ; N pi ; B 10 -19 530 487 ;
+C 113 ; WX 521 ; N theta ; B 43 -17 485 690 ;
+C 114 ; WX 549 ; N rho ; B 50 -230 490 499 ;
+C 115 ; WX 603 ; N sigma ; B 30 -21 588 500 ;
+C 116 ; WX 439 ; N tau ; B 10 -19 418 500 ;
+C 117 ; WX 576 ; N upsilon ; B 7 -18 535 507 ;
+C 118 ; WX 713 ; N omega1 ; B 12 -18 671 583 ;
+C 119 ; WX 686 ; N omega ; B 42 -17 684 500 ;
+C 120 ; WX 493 ; N xi ; B 27 -224 469 766 ;
+C 121 ; WX 686 ; N psi ; B 12 -228 701 500 ;
+C 122 ; WX 494 ; N zeta ; B 60 -225 467 756 ;
+C 123 ; WX 480 ; N braceleft ; B 58 -183 397 673 ;
+C 124 ; WX 200 ; N bar ; B 65 -293 135 707 ;
+C 125 ; WX 480 ; N braceright ; B 79 -183 418 673 ;
+C 126 ; WX 549 ; N similar ; B 17 203 529 307 ;
+C 160 ; WX 750 ; N Euro ; B 20 -12 714 685 ;
+C 161 ; WX 620 ; N Upsilon1 ; B -2 0 610 685 ;
+C 162 ; WX 247 ; N minute ; B 27 459 228 735 ;
+C 163 ; WX 549 ; N lessequal ; B 29 0 526 639 ;
+C 164 ; WX 167 ; N fraction ; B -180 -12 340 677 ;
+C 165 ; WX 713 ; N infinity ; B 26 124 688 404 ;
+C 166 ; WX 500 ; N florin ; B 2 -193 494 686 ;
+C 167 ; WX 753 ; N club ; B 86 -26 660 533 ;
+C 168 ; WX 753 ; N diamond ; B 142 -36 600 550 ;
+C 169 ; WX 753 ; N heart ; B 117 -33 631 532 ;
+C 170 ; WX 753 ; N spade ; B 113 -36 629 548 ;
+C 171 ; WX 1042 ; N arrowboth ; B 24 -15 1024 511 ;
+C 172 ; WX 987 ; N arrowleft ; B 32 -15 942 511 ;
+C 173 ; WX 603 ; N arrowup ; B 45 0 571 910 ;
+C 174 ; WX 987 ; N arrowright ; B 49 -15 959 511 ;
+C 175 ; WX 603 ; N arrowdown ; B 45 -22 571 888 ;
+C 176 ; WX 400 ; N degree ; B 50 385 350 685 ;
+C 177 ; WX 549 ; N plusminus ; B 10 0 539 645 ;
+C 178 ; WX 411 ; N second ; B 20 459 413 737 ;
+C 179 ; WX 549 ; N greaterequal ; B 29 0 526 639 ;
+C 180 ; WX 549 ; N multiply ; B 17 8 533 524 ;
+C 181 ; WX 713 ; N proportional ; B 27 123 639 404 ;
+C 182 ; WX 494 ; N partialdiff ; B 26 -20 462 746 ;
+C 183 ; WX 460 ; N bullet ; B 50 113 410 473 ;
+C 184 ; WX 549 ; N divide ; B 10 71 536 456 ;
+C 185 ; WX 549 ; N notequal ; B 15 -25 540 549 ;
+C 186 ; WX 549 ; N equivalence ; B 14 82 538 443 ;
+C 187 ; WX 549 ; N approxequal ; B 14 135 527 394 ;
+C 188 ; WX 1000 ; N ellipsis ; B 111 -17 889 95 ;
+C 189 ; WX 603 ; N arrowvertex ; B 280 -120 336 1010 ;
+C 190 ; WX 1000 ; N arrowhorizex ; B -60 220 1050 276 ;
+C 191 ; WX 658 ; N carriagereturn ; B 15 -16 602 629 ;
+C 192 ; WX 823 ; N aleph ; B 175 -18 661 658 ;
+C 193 ; WX 686 ; N Ifraktur ; B 10 -53 578 740 ;
+C 194 ; WX 795 ; N Rfraktur ; B 26 -15 759 734 ;
+C 195 ; WX 987 ; N weierstrass ; B 159 -211 870 573 ;
+C 196 ; WX 768 ; N circlemultiply ; B 43 -17 733 673 ;
+C 197 ; WX 768 ; N circleplus ; B 43 -15 733 675 ;
+C 198 ; WX 823 ; N emptyset ; B 39 -24 781 719 ;
+C 199 ; WX 768 ; N intersection ; B 40 0 732 509 ;
+C 200 ; WX 768 ; N union ; B 40 -17 732 492 ;
+C 201 ; WX 713 ; N propersuperset ; B 20 0 673 470 ;
+C 202 ; WX 713 ; N reflexsuperset ; B 20 -125 673 470 ;
+C 203 ; WX 713 ; N notsubset ; B 36 -70 690 540 ;
+C 204 ; WX 713 ; N propersubset ; B 37 0 690 470 ;
+C 205 ; WX 713 ; N reflexsubset ; B 37 -125 690 470 ;
+C 206 ; WX 713 ; N element ; B 45 0 505 468 ;
+C 207 ; WX 713 ; N notelement ; B 45 -58 505 555 ;
+C 208 ; WX 768 ; N angle ; B 26 0 738 673 ;
+C 209 ; WX 713 ; N gradient ; B 36 -19 681 718 ;
+C 210 ; WX 790 ; N registerserif ; B 50 -17 740 673 ;
+C 211 ; WX 790 ; N copyrightserif ; B 51 -15 741 675 ;
+C 212 ; WX 890 ; N trademarkserif ; B 18 293 855 673 ;
+C 213 ; WX 823 ; N product ; B 25 -101 803 751 ;
+C 214 ; WX 549 ; N radical ; B 10 -38 515 917 ;
+C 215 ; WX 250 ; N dotmath ; B 69 210 169 310 ;
+C 216 ; WX 713 ; N logicalnot ; B 15 0 680 288 ;
+C 217 ; WX 603 ; N logicaland ; B 23 0 583 454 ;
+C 218 ; WX 603 ; N logicalor ; B 30 0 578 477 ;
+C 219 ; WX 1042 ; N arrowdblboth ; B 27 -20 1023 510 ;
+C 220 ; WX 987 ; N arrowdblleft ; B 30 -15 939 513 ;
+C 221 ; WX 603 ; N arrowdblup ; B 39 2 567 911 ;
+C 222 ; WX 987 ; N arrowdblright ; B 45 -20 954 508 ;
+C 223 ; WX 603 ; N arrowdbldown ; B 44 -19 572 890 ;
+C 224 ; WX 494 ; N lozenge ; B 18 0 466 745 ;
+C 225 ; WX 329 ; N angleleft ; B 25 -198 306 746 ;
+C 226 ; WX 790 ; N registersans ; B 50 -20 740 670 ;
+C 227 ; WX 790 ; N copyrightsans ; B 49 -15 739 675 ;
+C 228 ; WX 786 ; N trademarksans ; B 5 293 725 673 ;
+C 229 ; WX 713 ; N summation ; B 14 -108 695 752 ;
+C 230 ; WX 384 ; N parenlefttp ; B 24 -293 436 926 ;
+C 231 ; WX 384 ; N parenleftex ; B 24 -85 108 925 ;
+C 232 ; WX 384 ; N parenleftbt ; B 24 -293 436 926 ;
+C 233 ; WX 384 ; N bracketlefttp ; B 0 -80 349 926 ;
+C 234 ; WX 384 ; N bracketleftex ; B 0 -79 77 925 ;
+C 235 ; WX 384 ; N bracketleftbt ; B 0 -80 349 926 ;
+C 236 ; WX 494 ; N bracelefttp ; B 209 -85 445 925 ;
+C 237 ; WX 494 ; N braceleftmid ; B 20 -85 284 935 ;
+C 238 ; WX 494 ; N braceleftbt ; B 209 -75 445 935 ;
+C 239 ; WX 494 ; N braceex ; B 209 -85 284 935 ;
+C 241 ; WX 329 ; N angleright ; B 21 -198 302 746 ;
+C 242 ; WX 274 ; N integral ; B 2 -107 291 916 ;
+C 243 ; WX 686 ; N integraltp ; B 308 -88 675 920 ;
+C 244 ; WX 686 ; N integralex ; B 308 -88 378 975 ;
+C 245 ; WX 686 ; N integralbt ; B 11 -87 378 921 ;
+C 246 ; WX 384 ; N parenrighttp ; B 54 -293 466 926 ;
+C 247 ; WX 384 ; N parenrightex ; B 382 -85 466 925 ;
+C 248 ; WX 384 ; N parenrightbt ; B 54 -293 466 926 ;
+C 249 ; WX 384 ; N bracketrighttp ; B 22 -80 371 926 ;
+C 250 ; WX 384 ; N bracketrightex ; B 294 -79 371 925 ;
+C 251 ; WX 384 ; N bracketrightbt ; B 22 -80 371 926 ;
+C 252 ; WX 494 ; N bracerighttp ; B 48 -85 284 925 ;
+C 253 ; WX 494 ; N bracerightmid ; B 209 -85 473 935 ;
+C 254 ; WX 494 ; N bracerightbt ; B 48 -75 284 935 ;
+C -1 ; WX 790 ; N apple ; B 56 -3 733 808 ;
+EndCharMetrics
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Times-Bold.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Times-Bold.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Times-Bold.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Times-Bold.afm 2004-05-26 16:06:22.000000000 +0000
@@ -0,0 +1,2588 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu May 1 12:52:56 1997
+Comment UniqueID 43065
+Comment VMusage 41636 52661
+FontName Times-Bold
+FullName Times Bold
+FamilyName Times
+Weight Bold
+ItalicAngle 0
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -168 -218 1000 935
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 676
+XHeight 461
+Ascender 683
+Descender -217
+StdHW 44
+StdVW 139
+StartCharMetrics 315
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 81 -13 251 691 ;
+C 34 ; WX 555 ; N quotedbl ; B 83 404 472 691 ;
+C 35 ; WX 500 ; N numbersign ; B 4 0 496 700 ;
+C 36 ; WX 500 ; N dollar ; B 29 -99 472 750 ;
+C 37 ; WX 1000 ; N percent ; B 124 -14 877 692 ;
+C 38 ; WX 833 ; N ampersand ; B 62 -16 787 691 ;
+C 39 ; WX 333 ; N quoteright ; B 79 356 263 691 ;
+C 40 ; WX 333 ; N parenleft ; B 46 -168 306 694 ;
+C 41 ; WX 333 ; N parenright ; B 27 -168 287 694 ;
+C 42 ; WX 500 ; N asterisk ; B 56 255 447 691 ;
+C 43 ; WX 570 ; N plus ; B 33 0 537 506 ;
+C 44 ; WX 250 ; N comma ; B 39 -180 223 155 ;
+C 45 ; WX 333 ; N hyphen ; B 44 171 287 287 ;
+C 46 ; WX 250 ; N period ; B 41 -13 210 156 ;
+C 47 ; WX 278 ; N slash ; B -24 -19 302 691 ;
+C 48 ; WX 500 ; N zero ; B 24 -13 476 688 ;
+C 49 ; WX 500 ; N one ; B 65 0 442 688 ;
+C 50 ; WX 500 ; N two ; B 17 0 478 688 ;
+C 51 ; WX 500 ; N three ; B 16 -14 468 688 ;
+C 52 ; WX 500 ; N four ; B 19 0 475 688 ;
+C 53 ; WX 500 ; N five ; B 22 -8 470 676 ;
+C 54 ; WX 500 ; N six ; B 28 -13 475 688 ;
+C 55 ; WX 500 ; N seven ; B 17 0 477 676 ;
+C 56 ; WX 500 ; N eight ; B 28 -13 472 688 ;
+C 57 ; WX 500 ; N nine ; B 26 -13 473 688 ;
+C 58 ; WX 333 ; N colon ; B 82 -13 251 472 ;
+C 59 ; WX 333 ; N semicolon ; B 82 -180 266 472 ;
+C 60 ; WX 570 ; N less ; B 31 -8 539 514 ;
+C 61 ; WX 570 ; N equal ; B 33 107 537 399 ;
+C 62 ; WX 570 ; N greater ; B 31 -8 539 514 ;
+C 63 ; WX 500 ; N question ; B 57 -13 445 689 ;
+C 64 ; WX 930 ; N at ; B 108 -19 822 691 ;
+C 65 ; WX 722 ; N A ; B 9 0 689 690 ;
+C 66 ; WX 667 ; N B ; B 16 0 619 676 ;
+C 67 ; WX 722 ; N C ; B 49 -19 687 691 ;
+C 68 ; WX 722 ; N D ; B 14 0 690 676 ;
+C 69 ; WX 667 ; N E ; B 16 0 641 676 ;
+C 70 ; WX 611 ; N F ; B 16 0 583 676 ;
+C 71 ; WX 778 ; N G ; B 37 -19 755 691 ;
+C 72 ; WX 778 ; N H ; B 21 0 759 676 ;
+C 73 ; WX 389 ; N I ; B 20 0 370 676 ;
+C 74 ; WX 500 ; N J ; B 3 -96 479 676 ;
+C 75 ; WX 778 ; N K ; B 30 0 769 676 ;
+C 76 ; WX 667 ; N L ; B 19 0 638 676 ;
+C 77 ; WX 944 ; N M ; B 14 0 921 676 ;
+C 78 ; WX 722 ; N N ; B 16 -18 701 676 ;
+C 79 ; WX 778 ; N O ; B 35 -19 743 691 ;
+C 80 ; WX 611 ; N P ; B 16 0 600 676 ;
+C 81 ; WX 778 ; N Q ; B 35 -176 743 691 ;
+C 82 ; WX 722 ; N R ; B 26 0 715 676 ;
+C 83 ; WX 556 ; N S ; B 35 -19 513 692 ;
+C 84 ; WX 667 ; N T ; B 31 0 636 676 ;
+C 85 ; WX 722 ; N U ; B 16 -19 701 676 ;
+C 86 ; WX 722 ; N V ; B 16 -18 701 676 ;
+C 87 ; WX 1000 ; N W ; B 19 -15 981 676 ;
+C 88 ; WX 722 ; N X ; B 16 0 699 676 ;
+C 89 ; WX 722 ; N Y ; B 15 0 699 676 ;
+C 90 ; WX 667 ; N Z ; B 28 0 634 676 ;
+C 91 ; WX 333 ; N bracketleft ; B 67 -149 301 678 ;
+C 92 ; WX 278 ; N backslash ; B -25 -19 303 691 ;
+C 93 ; WX 333 ; N bracketright ; B 32 -149 266 678 ;
+C 94 ; WX 581 ; N asciicircum ; B 73 311 509 676 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 333 ; N quoteleft ; B 70 356 254 691 ;
+C 97 ; WX 500 ; N a ; B 25 -14 488 473 ;
+C 98 ; WX 556 ; N b ; B 17 -14 521 676 ;
+C 99 ; WX 444 ; N c ; B 25 -14 430 473 ;
+C 100 ; WX 556 ; N d ; B 25 -14 534 676 ;
+C 101 ; WX 444 ; N e ; B 25 -14 426 473 ;
+C 102 ; WX 333 ; N f ; B 14 0 389 691 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B 28 -206 483 473 ;
+C 104 ; WX 556 ; N h ; B 16 0 534 676 ;
+C 105 ; WX 278 ; N i ; B 16 0 255 691 ;
+C 106 ; WX 333 ; N j ; B -57 -203 263 691 ;
+C 107 ; WX 556 ; N k ; B 22 0 543 676 ;
+C 108 ; WX 278 ; N l ; B 16 0 255 676 ;
+C 109 ; WX 833 ; N m ; B 16 0 814 473 ;
+C 110 ; WX 556 ; N n ; B 21 0 539 473 ;
+C 111 ; WX 500 ; N o ; B 25 -14 476 473 ;
+C 112 ; WX 556 ; N p ; B 19 -205 524 473 ;
+C 113 ; WX 556 ; N q ; B 34 -205 536 473 ;
+C 114 ; WX 444 ; N r ; B 29 0 434 473 ;
+C 115 ; WX 389 ; N s ; B 25 -14 361 473 ;
+C 116 ; WX 333 ; N t ; B 20 -12 332 630 ;
+C 117 ; WX 556 ; N u ; B 16 -14 537 461 ;
+C 118 ; WX 500 ; N v ; B 21 -14 485 461 ;
+C 119 ; WX 722 ; N w ; B 23 -14 707 461 ;
+C 120 ; WX 500 ; N x ; B 12 0 484 461 ;
+C 121 ; WX 500 ; N y ; B 16 -205 480 461 ;
+C 122 ; WX 444 ; N z ; B 21 0 420 461 ;
+C 123 ; WX 394 ; N braceleft ; B 22 -175 340 698 ;
+C 124 ; WX 220 ; N bar ; B 66 -218 154 782 ;
+C 125 ; WX 394 ; N braceright ; B 54 -175 372 698 ;
+C 126 ; WX 520 ; N asciitilde ; B 29 173 491 333 ;
+C 161 ; WX 333 ; N exclamdown ; B 82 -203 252 501 ;
+C 162 ; WX 500 ; N cent ; B 53 -140 458 588 ;
+C 163 ; WX 500 ; N sterling ; B 21 -14 477 684 ;
+C 164 ; WX 167 ; N fraction ; B -168 -12 329 688 ;
+C 165 ; WX 500 ; N yen ; B -64 0 547 676 ;
+C 166 ; WX 500 ; N florin ; B 0 -155 498 706 ;
+C 167 ; WX 500 ; N section ; B 57 -132 443 691 ;
+C 168 ; WX 500 ; N currency ; B -26 61 526 613 ;
+C 169 ; WX 278 ; N quotesingle ; B 75 404 204 691 ;
+C 170 ; WX 500 ; N quotedblleft ; B 32 356 486 691 ;
+C 171 ; WX 500 ; N guillemotleft ; B 23 36 473 415 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 51 36 305 415 ;
+C 173 ; WX 333 ; N guilsinglright ; B 28 36 282 415 ;
+C 174 ; WX 556 ; N fi ; B 14 0 536 691 ;
+C 175 ; WX 556 ; N fl ; B 14 0 536 691 ;
+C 177 ; WX 500 ; N endash ; B 0 181 500 271 ;
+C 178 ; WX 500 ; N dagger ; B 47 -134 453 691 ;
+C 179 ; WX 500 ; N daggerdbl ; B 45 -132 456 691 ;
+C 180 ; WX 250 ; N periodcentered ; B 41 248 210 417 ;
+C 182 ; WX 540 ; N paragraph ; B 0 -186 519 676 ;
+C 183 ; WX 350 ; N bullet ; B 35 198 315 478 ;
+C 184 ; WX 333 ; N quotesinglbase ; B 79 -180 263 155 ;
+C 185 ; WX 500 ; N quotedblbase ; B 14 -180 468 155 ;
+C 186 ; WX 500 ; N quotedblright ; B 14 356 468 691 ;
+C 187 ; WX 500 ; N guillemotright ; B 27 36 477 415 ;
+C 188 ; WX 1000 ; N ellipsis ; B 82 -13 917 156 ;
+C 189 ; WX 1000 ; N perthousand ; B 7 -29 995 706 ;
+C 191 ; WX 500 ; N questiondown ; B 55 -201 443 501 ;
+C 193 ; WX 333 ; N grave ; B 8 528 246 713 ;
+C 194 ; WX 333 ; N acute ; B 86 528 324 713 ;
+C 195 ; WX 333 ; N circumflex ; B -2 528 335 704 ;
+C 196 ; WX 333 ; N tilde ; B -16 547 349 674 ;
+C 197 ; WX 333 ; N macron ; B 1 565 331 637 ;
+C 198 ; WX 333 ; N breve ; B 15 528 318 691 ;
+C 199 ; WX 333 ; N dotaccent ; B 103 536 258 691 ;
+C 200 ; WX 333 ; N dieresis ; B -2 537 335 667 ;
+C 202 ; WX 333 ; N ring ; B 60 527 273 740 ;
+C 203 ; WX 333 ; N cedilla ; B 68 -218 294 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B -13 528 425 713 ;
+C 206 ; WX 333 ; N ogonek ; B 90 -193 319 24 ;
+C 207 ; WX 333 ; N caron ; B -2 528 335 704 ;
+C 208 ; WX 1000 ; N emdash ; B 0 181 1000 271 ;
+C 225 ; WX 1000 ; N AE ; B 4 0 951 676 ;
+C 227 ; WX 300 ; N ordfeminine ; B -1 397 301 688 ;
+C 232 ; WX 667 ; N Lslash ; B 19 0 638 676 ;
+C 233 ; WX 778 ; N Oslash ; B 35 -74 743 737 ;
+C 234 ; WX 1000 ; N OE ; B 22 -5 981 684 ;
+C 235 ; WX 330 ; N ordmasculine ; B 18 397 312 688 ;
+C 241 ; WX 722 ; N ae ; B 33 -14 693 473 ;
+C 245 ; WX 278 ; N dotlessi ; B 16 0 255 461 ;
+C 248 ; WX 278 ; N lslash ; B -22 0 303 676 ;
+C 249 ; WX 500 ; N oslash ; B 25 -92 476 549 ;
+C 250 ; WX 722 ; N oe ; B 22 -14 696 473 ;
+C 251 ; WX 556 ; N germandbls ; B 19 -12 517 691 ;
+C -1 ; WX 389 ; N Idieresis ; B 20 0 370 877 ;
+C -1 ; WX 444 ; N eacute ; B 25 -14 426 713 ;
+C -1 ; WX 500 ; N abreve ; B 25 -14 488 691 ;
+C -1 ; WX 556 ; N uhungarumlaut ; B 16 -14 557 713 ;
+C -1 ; WX 444 ; N ecaron ; B 25 -14 426 704 ;
+C -1 ; WX 722 ; N Ydieresis ; B 15 0 699 877 ;
+C -1 ; WX 570 ; N divide ; B 33 -31 537 537 ;
+C -1 ; WX 722 ; N Yacute ; B 15 0 699 923 ;
+C -1 ; WX 722 ; N Acircumflex ; B 9 0 689 914 ;
+C -1 ; WX 500 ; N aacute ; B 25 -14 488 713 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 16 -19 701 914 ;
+C -1 ; WX 500 ; N yacute ; B 16 -205 480 713 ;
+C -1 ; WX 389 ; N scommaaccent ; B 25 -218 361 473 ;
+C -1 ; WX 444 ; N ecircumflex ; B 25 -14 426 704 ;
+C -1 ; WX 722 ; N Uring ; B 16 -19 701 935 ;
+C -1 ; WX 722 ; N Udieresis ; B 16 -19 701 877 ;
+C -1 ; WX 500 ; N aogonek ; B 25 -193 504 473 ;
+C -1 ; WX 722 ; N Uacute ; B 16 -19 701 923 ;
+C -1 ; WX 556 ; N uogonek ; B 16 -193 539 461 ;
+C -1 ; WX 667 ; N Edieresis ; B 16 0 641 877 ;
+C -1 ; WX 722 ; N Dcroat ; B 6 0 690 676 ;
+C -1 ; WX 250 ; N commaaccent ; B 47 -218 203 -50 ;
+C -1 ; WX 747 ; N copyright ; B 26 -19 721 691 ;
+C -1 ; WX 667 ; N Emacron ; B 16 0 641 847 ;
+C -1 ; WX 444 ; N ccaron ; B 25 -14 430 704 ;
+C -1 ; WX 500 ; N aring ; B 25 -14 488 740 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B 16 -188 701 676 ;
+C -1 ; WX 278 ; N lacute ; B 16 0 297 923 ;
+C -1 ; WX 500 ; N agrave ; B 25 -14 488 713 ;
+C -1 ; WX 667 ; N Tcommaaccent ; B 31 -218 636 676 ;
+C -1 ; WX 722 ; N Cacute ; B 49 -19 687 923 ;
+C -1 ; WX 500 ; N atilde ; B 25 -14 488 674 ;
+C -1 ; WX 667 ; N Edotaccent ; B 16 0 641 901 ;
+C -1 ; WX 389 ; N scaron ; B 25 -14 363 704 ;
+C -1 ; WX 389 ; N scedilla ; B 25 -218 361 473 ;
+C -1 ; WX 278 ; N iacute ; B 16 0 289 713 ;
+C -1 ; WX 494 ; N lozenge ; B 10 0 484 745 ;
+C -1 ; WX 722 ; N Rcaron ; B 26 0 715 914 ;
+C -1 ; WX 778 ; N Gcommaaccent ; B 37 -218 755 691 ;
+C -1 ; WX 556 ; N ucircumflex ; B 16 -14 537 704 ;
+C -1 ; WX 500 ; N acircumflex ; B 25 -14 488 704 ;
+C -1 ; WX 722 ; N Amacron ; B 9 0 689 847 ;
+C -1 ; WX 444 ; N rcaron ; B 29 0 434 704 ;
+C -1 ; WX 444 ; N ccedilla ; B 25 -218 430 473 ;
+C -1 ; WX 667 ; N Zdotaccent ; B 28 0 634 901 ;
+C -1 ; WX 611 ; N Thorn ; B 16 0 600 676 ;
+C -1 ; WX 778 ; N Omacron ; B 35 -19 743 847 ;
+C -1 ; WX 722 ; N Racute ; B 26 0 715 923 ;
+C -1 ; WX 556 ; N Sacute ; B 35 -19 513 923 ;
+C -1 ; WX 672 ; N dcaron ; B 25 -14 681 682 ;
+C -1 ; WX 722 ; N Umacron ; B 16 -19 701 847 ;
+C -1 ; WX 556 ; N uring ; B 16 -14 537 740 ;
+C -1 ; WX 300 ; N threesuperior ; B 3 268 297 688 ;
+C -1 ; WX 778 ; N Ograve ; B 35 -19 743 923 ;
+C -1 ; WX 722 ; N Agrave ; B 9 0 689 923 ;
+C -1 ; WX 722 ; N Abreve ; B 9 0 689 901 ;
+C -1 ; WX 570 ; N multiply ; B 48 16 522 490 ;
+C -1 ; WX 556 ; N uacute ; B 16 -14 537 713 ;
+C -1 ; WX 667 ; N Tcaron ; B 31 0 636 914 ;
+C -1 ; WX 494 ; N partialdiff ; B 11 -21 494 750 ;
+C -1 ; WX 500 ; N ydieresis ; B 16 -205 480 667 ;
+C -1 ; WX 722 ; N Nacute ; B 16 -18 701 923 ;
+C -1 ; WX 278 ; N icircumflex ; B -37 0 300 704 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 16 0 641 914 ;
+C -1 ; WX 500 ; N adieresis ; B 25 -14 488 667 ;
+C -1 ; WX 444 ; N edieresis ; B 25 -14 426 667 ;
+C -1 ; WX 444 ; N cacute ; B 25 -14 430 713 ;
+C -1 ; WX 556 ; N nacute ; B 21 0 539 713 ;
+C -1 ; WX 556 ; N umacron ; B 16 -14 537 637 ;
+C -1 ; WX 722 ; N Ncaron ; B 16 -18 701 914 ;
+C -1 ; WX 389 ; N Iacute ; B 20 0 370 923 ;
+C -1 ; WX 570 ; N plusminus ; B 33 0 537 506 ;
+C -1 ; WX 220 ; N brokenbar ; B 66 -143 154 707 ;
+C -1 ; WX 747 ; N registered ; B 26 -19 721 691 ;
+C -1 ; WX 778 ; N Gbreve ; B 37 -19 755 901 ;
+C -1 ; WX 389 ; N Idotaccent ; B 20 0 370 901 ;
+C -1 ; WX 600 ; N summation ; B 14 -10 585 706 ;
+C -1 ; WX 667 ; N Egrave ; B 16 0 641 923 ;
+C -1 ; WX 444 ; N racute ; B 29 0 434 713 ;
+C -1 ; WX 500 ; N omacron ; B 25 -14 476 637 ;
+C -1 ; WX 667 ; N Zacute ; B 28 0 634 923 ;
+C -1 ; WX 667 ; N Zcaron ; B 28 0 634 914 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 523 704 ;
+C -1 ; WX 722 ; N Eth ; B 6 0 690 676 ;
+C -1 ; WX 722 ; N Ccedilla ; B 49 -218 687 691 ;
+C -1 ; WX 278 ; N lcommaaccent ; B 16 -218 255 676 ;
+C -1 ; WX 416 ; N tcaron ; B 20 -12 425 815 ;
+C -1 ; WX 444 ; N eogonek ; B 25 -193 426 473 ;
+C -1 ; WX 722 ; N Uogonek ; B 16 -193 701 676 ;
+C -1 ; WX 722 ; N Aacute ; B 9 0 689 923 ;
+C -1 ; WX 722 ; N Adieresis ; B 9 0 689 877 ;
+C -1 ; WX 444 ; N egrave ; B 25 -14 426 713 ;
+C -1 ; WX 444 ; N zacute ; B 21 0 420 713 ;
+C -1 ; WX 278 ; N iogonek ; B 16 -193 274 691 ;
+C -1 ; WX 778 ; N Oacute ; B 35 -19 743 923 ;
+C -1 ; WX 500 ; N oacute ; B 25 -14 476 713 ;
+C -1 ; WX 500 ; N amacron ; B 25 -14 488 637 ;
+C -1 ; WX 389 ; N sacute ; B 25 -14 361 713 ;
+C -1 ; WX 278 ; N idieresis ; B -37 0 300 667 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 35 -19 743 914 ;
+C -1 ; WX 722 ; N Ugrave ; B 16 -19 701 923 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 556 ; N thorn ; B 19 -205 524 676 ;
+C -1 ; WX 300 ; N twosuperior ; B 0 275 300 688 ;
+C -1 ; WX 778 ; N Odieresis ; B 35 -19 743 877 ;
+C -1 ; WX 556 ; N mu ; B 33 -206 536 461 ;
+C -1 ; WX 278 ; N igrave ; B -27 0 255 713 ;
+C -1 ; WX 500 ; N ohungarumlaut ; B 25 -14 529 713 ;
+C -1 ; WX 667 ; N Eogonek ; B 16 -193 644 676 ;
+C -1 ; WX 556 ; N dcroat ; B 25 -14 534 676 ;
+C -1 ; WX 750 ; N threequarters ; B 23 -12 733 688 ;
+C -1 ; WX 556 ; N Scedilla ; B 35 -218 513 692 ;
+C -1 ; WX 394 ; N lcaron ; B 16 0 412 682 ;
+C -1 ; WX 778 ; N Kcommaaccent ; B 30 -218 769 676 ;
+C -1 ; WX 667 ; N Lacute ; B 19 0 638 923 ;
+C -1 ; WX 1000 ; N trademark ; B 24 271 977 676 ;
+C -1 ; WX 444 ; N edotaccent ; B 25 -14 426 691 ;
+C -1 ; WX 389 ; N Igrave ; B 20 0 370 923 ;
+C -1 ; WX 389 ; N Imacron ; B 20 0 370 847 ;
+C -1 ; WX 667 ; N Lcaron ; B 19 0 652 682 ;
+C -1 ; WX 750 ; N onehalf ; B -7 -12 775 688 ;
+C -1 ; WX 549 ; N lessequal ; B 29 0 526 704 ;
+C -1 ; WX 500 ; N ocircumflex ; B 25 -14 476 704 ;
+C -1 ; WX 556 ; N ntilde ; B 21 0 539 674 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 16 -19 701 923 ;
+C -1 ; WX 667 ; N Eacute ; B 16 0 641 923 ;
+C -1 ; WX 444 ; N emacron ; B 25 -14 426 637 ;
+C -1 ; WX 500 ; N gbreve ; B 28 -206 483 691 ;
+C -1 ; WX 750 ; N onequarter ; B 28 -12 743 688 ;
+C -1 ; WX 556 ; N Scaron ; B 35 -19 513 914 ;
+C -1 ; WX 556 ; N Scommaaccent ; B 35 -218 513 692 ;
+C -1 ; WX 778 ; N Ohungarumlaut ; B 35 -19 743 923 ;
+C -1 ; WX 400 ; N degree ; B 57 402 343 688 ;
+C -1 ; WX 500 ; N ograve ; B 25 -14 476 713 ;
+C -1 ; WX 722 ; N Ccaron ; B 49 -19 687 914 ;
+C -1 ; WX 556 ; N ugrave ; B 16 -14 537 713 ;
+C -1 ; WX 549 ; N radical ; B 10 -46 512 850 ;
+C -1 ; WX 722 ; N Dcaron ; B 14 0 690 914 ;
+C -1 ; WX 444 ; N rcommaaccent ; B 29 -218 434 473 ;
+C -1 ; WX 722 ; N Ntilde ; B 16 -18 701 884 ;
+C -1 ; WX 500 ; N otilde ; B 25 -14 476 674 ;
+C -1 ; WX 722 ; N Rcommaaccent ; B 26 -218 715 676 ;
+C -1 ; WX 667 ; N Lcommaaccent ; B 19 -218 638 676 ;
+C -1 ; WX 722 ; N Atilde ; B 9 0 689 884 ;
+C -1 ; WX 722 ; N Aogonek ; B 9 -193 699 690 ;
+C -1 ; WX 722 ; N Aring ; B 9 0 689 935 ;
+C -1 ; WX 778 ; N Otilde ; B 35 -19 743 884 ;
+C -1 ; WX 444 ; N zdotaccent ; B 21 0 420 691 ;
+C -1 ; WX 667 ; N Ecaron ; B 16 0 641 914 ;
+C -1 ; WX 389 ; N Iogonek ; B 20 -193 370 676 ;
+C -1 ; WX 556 ; N kcommaaccent ; B 22 -218 543 676 ;
+C -1 ; WX 570 ; N minus ; B 33 209 537 297 ;
+C -1 ; WX 389 ; N Icircumflex ; B 20 0 370 914 ;
+C -1 ; WX 556 ; N ncaron ; B 21 0 539 704 ;
+C -1 ; WX 333 ; N tcommaaccent ; B 20 -218 332 630 ;
+C -1 ; WX 570 ; N logicalnot ; B 33 108 537 399 ;
+C -1 ; WX 500 ; N odieresis ; B 25 -14 476 667 ;
+C -1 ; WX 556 ; N udieresis ; B 16 -14 537 667 ;
+C -1 ; WX 549 ; N notequal ; B 15 -49 540 570 ;
+C -1 ; WX 500 ; N gcommaaccent ; B 28 -206 483 829 ;
+C -1 ; WX 500 ; N eth ; B 25 -14 476 691 ;
+C -1 ; WX 444 ; N zcaron ; B 21 0 420 704 ;
+C -1 ; WX 556 ; N ncommaaccent ; B 21 -218 539 473 ;
+C -1 ; WX 300 ; N onesuperior ; B 28 275 273 688 ;
+C -1 ; WX 278 ; N imacron ; B -8 0 272 637 ;
+C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2242
+KPX A C -55
+KPX A Cacute -55
+KPX A Ccaron -55
+KPX A Ccedilla -55
+KPX A G -55
+KPX A Gbreve -55
+KPX A Gcommaaccent -55
+KPX A O -45
+KPX A Oacute -45
+KPX A Ocircumflex -45
+KPX A Odieresis -45
+KPX A Ograve -45
+KPX A Ohungarumlaut -45
+KPX A Omacron -45
+KPX A Oslash -45
+KPX A Otilde -45
+KPX A Q -45
+KPX A T -95
+KPX A Tcaron -95
+KPX A Tcommaaccent -95
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -145
+KPX A W -130
+KPX A Y -100
+KPX A Yacute -100
+KPX A Ydieresis -100
+KPX A p -25
+KPX A quoteright -74
+KPX A u -50
+KPX A uacute -50
+KPX A ucircumflex -50
+KPX A udieresis -50
+KPX A ugrave -50
+KPX A uhungarumlaut -50
+KPX A umacron -50
+KPX A uogonek -50
+KPX A uring -50
+KPX A v -100
+KPX A w -90
+KPX A y -74
+KPX A yacute -74
+KPX A ydieresis -74
+KPX Aacute C -55
+KPX Aacute Cacute -55
+KPX Aacute Ccaron -55
+KPX Aacute Ccedilla -55
+KPX Aacute G -55
+KPX Aacute Gbreve -55
+KPX Aacute Gcommaaccent -55
+KPX Aacute O -45
+KPX Aacute Oacute -45
+KPX Aacute Ocircumflex -45
+KPX Aacute Odieresis -45
+KPX Aacute Ograve -45
+KPX Aacute Ohungarumlaut -45
+KPX Aacute Omacron -45
+KPX Aacute Oslash -45
+KPX Aacute Otilde -45
+KPX Aacute Q -45
+KPX Aacute T -95
+KPX Aacute Tcaron -95
+KPX Aacute Tcommaaccent -95
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -145
+KPX Aacute W -130
+KPX Aacute Y -100
+KPX Aacute Yacute -100
+KPX Aacute Ydieresis -100
+KPX Aacute p -25
+KPX Aacute quoteright -74
+KPX Aacute u -50
+KPX Aacute uacute -50
+KPX Aacute ucircumflex -50
+KPX Aacute udieresis -50
+KPX Aacute ugrave -50
+KPX Aacute uhungarumlaut -50
+KPX Aacute umacron -50
+KPX Aacute uogonek -50
+KPX Aacute uring -50
+KPX Aacute v -100
+KPX Aacute w -90
+KPX Aacute y -74
+KPX Aacute yacute -74
+KPX Aacute ydieresis -74
+KPX Abreve C -55
+KPX Abreve Cacute -55
+KPX Abreve Ccaron -55
+KPX Abreve Ccedilla -55
+KPX Abreve G -55
+KPX Abreve Gbreve -55
+KPX Abreve Gcommaaccent -55
+KPX Abreve O -45
+KPX Abreve Oacute -45
+KPX Abreve Ocircumflex -45
+KPX Abreve Odieresis -45
+KPX Abreve Ograve -45
+KPX Abreve Ohungarumlaut -45
+KPX Abreve Omacron -45
+KPX Abreve Oslash -45
+KPX Abreve Otilde -45
+KPX Abreve Q -45
+KPX Abreve T -95
+KPX Abreve Tcaron -95
+KPX Abreve Tcommaaccent -95
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -145
+KPX Abreve W -130
+KPX Abreve Y -100
+KPX Abreve Yacute -100
+KPX Abreve Ydieresis -100
+KPX Abreve p -25
+KPX Abreve quoteright -74
+KPX Abreve u -50
+KPX Abreve uacute -50
+KPX Abreve ucircumflex -50
+KPX Abreve udieresis -50
+KPX Abreve ugrave -50
+KPX Abreve uhungarumlaut -50
+KPX Abreve umacron -50
+KPX Abreve uogonek -50
+KPX Abreve uring -50
+KPX Abreve v -100
+KPX Abreve w -90
+KPX Abreve y -74
+KPX Abreve yacute -74
+KPX Abreve ydieresis -74
+KPX Acircumflex C -55
+KPX Acircumflex Cacute -55
+KPX Acircumflex Ccaron -55
+KPX Acircumflex Ccedilla -55
+KPX Acircumflex G -55
+KPX Acircumflex Gbreve -55
+KPX Acircumflex Gcommaaccent -55
+KPX Acircumflex O -45
+KPX Acircumflex Oacute -45
+KPX Acircumflex Ocircumflex -45
+KPX Acircumflex Odieresis -45
+KPX Acircumflex Ograve -45
+KPX Acircumflex Ohungarumlaut -45
+KPX Acircumflex Omacron -45
+KPX Acircumflex Oslash -45
+KPX Acircumflex Otilde -45
+KPX Acircumflex Q -45
+KPX Acircumflex T -95
+KPX Acircumflex Tcaron -95
+KPX Acircumflex Tcommaaccent -95
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -145
+KPX Acircumflex W -130
+KPX Acircumflex Y -100
+KPX Acircumflex Yacute -100
+KPX Acircumflex Ydieresis -100
+KPX Acircumflex p -25
+KPX Acircumflex quoteright -74
+KPX Acircumflex u -50
+KPX Acircumflex uacute -50
+KPX Acircumflex ucircumflex -50
+KPX Acircumflex udieresis -50
+KPX Acircumflex ugrave -50
+KPX Acircumflex uhungarumlaut -50
+KPX Acircumflex umacron -50
+KPX Acircumflex uogonek -50
+KPX Acircumflex uring -50
+KPX Acircumflex v -100
+KPX Acircumflex w -90
+KPX Acircumflex y -74
+KPX Acircumflex yacute -74
+KPX Acircumflex ydieresis -74
+KPX Adieresis C -55
+KPX Adieresis Cacute -55
+KPX Adieresis Ccaron -55
+KPX Adieresis Ccedilla -55
+KPX Adieresis G -55
+KPX Adieresis Gbreve -55
+KPX Adieresis Gcommaaccent -55
+KPX Adieresis O -45
+KPX Adieresis Oacute -45
+KPX Adieresis Ocircumflex -45
+KPX Adieresis Odieresis -45
+KPX Adieresis Ograve -45
+KPX Adieresis Ohungarumlaut -45
+KPX Adieresis Omacron -45
+KPX Adieresis Oslash -45
+KPX Adieresis Otilde -45
+KPX Adieresis Q -45
+KPX Adieresis T -95
+KPX Adieresis Tcaron -95
+KPX Adieresis Tcommaaccent -95
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -145
+KPX Adieresis W -130
+KPX Adieresis Y -100
+KPX Adieresis Yacute -100
+KPX Adieresis Ydieresis -100
+KPX Adieresis p -25
+KPX Adieresis quoteright -74
+KPX Adieresis u -50
+KPX Adieresis uacute -50
+KPX Adieresis ucircumflex -50
+KPX Adieresis udieresis -50
+KPX Adieresis ugrave -50
+KPX Adieresis uhungarumlaut -50
+KPX Adieresis umacron -50
+KPX Adieresis uogonek -50
+KPX Adieresis uring -50
+KPX Adieresis v -100
+KPX Adieresis w -90
+KPX Adieresis y -74
+KPX Adieresis yacute -74
+KPX Adieresis ydieresis -74
+KPX Agrave C -55
+KPX Agrave Cacute -55
+KPX Agrave Ccaron -55
+KPX Agrave Ccedilla -55
+KPX Agrave G -55
+KPX Agrave Gbreve -55
+KPX Agrave Gcommaaccent -55
+KPX Agrave O -45
+KPX Agrave Oacute -45
+KPX Agrave Ocircumflex -45
+KPX Agrave Odieresis -45
+KPX Agrave Ograve -45
+KPX Agrave Ohungarumlaut -45
+KPX Agrave Omacron -45
+KPX Agrave Oslash -45
+KPX Agrave Otilde -45
+KPX Agrave Q -45
+KPX Agrave T -95
+KPX Agrave Tcaron -95
+KPX Agrave Tcommaaccent -95
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -145
+KPX Agrave W -130
+KPX Agrave Y -100
+KPX Agrave Yacute -100
+KPX Agrave Ydieresis -100
+KPX Agrave p -25
+KPX Agrave quoteright -74
+KPX Agrave u -50
+KPX Agrave uacute -50
+KPX Agrave ucircumflex -50
+KPX Agrave udieresis -50
+KPX Agrave ugrave -50
+KPX Agrave uhungarumlaut -50
+KPX Agrave umacron -50
+KPX Agrave uogonek -50
+KPX Agrave uring -50
+KPX Agrave v -100
+KPX Agrave w -90
+KPX Agrave y -74
+KPX Agrave yacute -74
+KPX Agrave ydieresis -74
+KPX Amacron C -55
+KPX Amacron Cacute -55
+KPX Amacron Ccaron -55
+KPX Amacron Ccedilla -55
+KPX Amacron G -55
+KPX Amacron Gbreve -55
+KPX Amacron Gcommaaccent -55
+KPX Amacron O -45
+KPX Amacron Oacute -45
+KPX Amacron Ocircumflex -45
+KPX Amacron Odieresis -45
+KPX Amacron Ograve -45
+KPX Amacron Ohungarumlaut -45
+KPX Amacron Omacron -45
+KPX Amacron Oslash -45
+KPX Amacron Otilde -45
+KPX Amacron Q -45
+KPX Amacron T -95
+KPX Amacron Tcaron -95
+KPX Amacron Tcommaaccent -95
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -145
+KPX Amacron W -130
+KPX Amacron Y -100
+KPX Amacron Yacute -100
+KPX Amacron Ydieresis -100
+KPX Amacron p -25
+KPX Amacron quoteright -74
+KPX Amacron u -50
+KPX Amacron uacute -50
+KPX Amacron ucircumflex -50
+KPX Amacron udieresis -50
+KPX Amacron ugrave -50
+KPX Amacron uhungarumlaut -50
+KPX Amacron umacron -50
+KPX Amacron uogonek -50
+KPX Amacron uring -50
+KPX Amacron v -100
+KPX Amacron w -90
+KPX Amacron y -74
+KPX Amacron yacute -74
+KPX Amacron ydieresis -74
+KPX Aogonek C -55
+KPX Aogonek Cacute -55
+KPX Aogonek Ccaron -55
+KPX Aogonek Ccedilla -55
+KPX Aogonek G -55
+KPX Aogonek Gbreve -55
+KPX Aogonek Gcommaaccent -55
+KPX Aogonek O -45
+KPX Aogonek Oacute -45
+KPX Aogonek Ocircumflex -45
+KPX Aogonek Odieresis -45
+KPX Aogonek Ograve -45
+KPX Aogonek Ohungarumlaut -45
+KPX Aogonek Omacron -45
+KPX Aogonek Oslash -45
+KPX Aogonek Otilde -45
+KPX Aogonek Q -45
+KPX Aogonek T -95
+KPX Aogonek Tcaron -95
+KPX Aogonek Tcommaaccent -95
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -145
+KPX Aogonek W -130
+KPX Aogonek Y -100
+KPX Aogonek Yacute -100
+KPX Aogonek Ydieresis -100
+KPX Aogonek p -25
+KPX Aogonek quoteright -74
+KPX Aogonek u -50
+KPX Aogonek uacute -50
+KPX Aogonek ucircumflex -50
+KPX Aogonek udieresis -50
+KPX Aogonek ugrave -50
+KPX Aogonek uhungarumlaut -50
+KPX Aogonek umacron -50
+KPX Aogonek uogonek -50
+KPX Aogonek uring -50
+KPX Aogonek v -100
+KPX Aogonek w -90
+KPX Aogonek y -34
+KPX Aogonek yacute -34
+KPX Aogonek ydieresis -34
+KPX Aring C -55
+KPX Aring Cacute -55
+KPX Aring Ccaron -55
+KPX Aring Ccedilla -55
+KPX Aring G -55
+KPX Aring Gbreve -55
+KPX Aring Gcommaaccent -55
+KPX Aring O -45
+KPX Aring Oacute -45
+KPX Aring Ocircumflex -45
+KPX Aring Odieresis -45
+KPX Aring Ograve -45
+KPX Aring Ohungarumlaut -45
+KPX Aring Omacron -45
+KPX Aring Oslash -45
+KPX Aring Otilde -45
+KPX Aring Q -45
+KPX Aring T -95
+KPX Aring Tcaron -95
+KPX Aring Tcommaaccent -95
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -145
+KPX Aring W -130
+KPX Aring Y -100
+KPX Aring Yacute -100
+KPX Aring Ydieresis -100
+KPX Aring p -25
+KPX Aring quoteright -74
+KPX Aring u -50
+KPX Aring uacute -50
+KPX Aring ucircumflex -50
+KPX Aring udieresis -50
+KPX Aring ugrave -50
+KPX Aring uhungarumlaut -50
+KPX Aring umacron -50
+KPX Aring uogonek -50
+KPX Aring uring -50
+KPX Aring v -100
+KPX Aring w -90
+KPX Aring y -74
+KPX Aring yacute -74
+KPX Aring ydieresis -74
+KPX Atilde C -55
+KPX Atilde Cacute -55
+KPX Atilde Ccaron -55
+KPX Atilde Ccedilla -55
+KPX Atilde G -55
+KPX Atilde Gbreve -55
+KPX Atilde Gcommaaccent -55
+KPX Atilde O -45
+KPX Atilde Oacute -45
+KPX Atilde Ocircumflex -45
+KPX Atilde Odieresis -45
+KPX Atilde Ograve -45
+KPX Atilde Ohungarumlaut -45
+KPX Atilde Omacron -45
+KPX Atilde Oslash -45
+KPX Atilde Otilde -45
+KPX Atilde Q -45
+KPX Atilde T -95
+KPX Atilde Tcaron -95
+KPX Atilde Tcommaaccent -95
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -145
+KPX Atilde W -130
+KPX Atilde Y -100
+KPX Atilde Yacute -100
+KPX Atilde Ydieresis -100
+KPX Atilde p -25
+KPX Atilde quoteright -74
+KPX Atilde u -50
+KPX Atilde uacute -50
+KPX Atilde ucircumflex -50
+KPX Atilde udieresis -50
+KPX Atilde ugrave -50
+KPX Atilde uhungarumlaut -50
+KPX Atilde umacron -50
+KPX Atilde uogonek -50
+KPX Atilde uring -50
+KPX Atilde v -100
+KPX Atilde w -90
+KPX Atilde y -74
+KPX Atilde yacute -74
+KPX Atilde ydieresis -74
+KPX B A -30
+KPX B Aacute -30
+KPX B Abreve -30
+KPX B Acircumflex -30
+KPX B Adieresis -30
+KPX B Agrave -30
+KPX B Amacron -30
+KPX B Aogonek -30
+KPX B Aring -30
+KPX B Atilde -30
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX D A -35
+KPX D Aacute -35
+KPX D Abreve -35
+KPX D Acircumflex -35
+KPX D Adieresis -35
+KPX D Agrave -35
+KPX D Amacron -35
+KPX D Aogonek -35
+KPX D Aring -35
+KPX D Atilde -35
+KPX D V -40
+KPX D W -40
+KPX D Y -40
+KPX D Yacute -40
+KPX D Ydieresis -40
+KPX D period -20
+KPX Dcaron A -35
+KPX Dcaron Aacute -35
+KPX Dcaron Abreve -35
+KPX Dcaron Acircumflex -35
+KPX Dcaron Adieresis -35
+KPX Dcaron Agrave -35
+KPX Dcaron Amacron -35
+KPX Dcaron Aogonek -35
+KPX Dcaron Aring -35
+KPX Dcaron Atilde -35
+KPX Dcaron V -40
+KPX Dcaron W -40
+KPX Dcaron Y -40
+KPX Dcaron Yacute -40
+KPX Dcaron Ydieresis -40
+KPX Dcaron period -20
+KPX Dcroat A -35
+KPX Dcroat Aacute -35
+KPX Dcroat Abreve -35
+KPX Dcroat Acircumflex -35
+KPX Dcroat Adieresis -35
+KPX Dcroat Agrave -35
+KPX Dcroat Amacron -35
+KPX Dcroat Aogonek -35
+KPX Dcroat Aring -35
+KPX Dcroat Atilde -35
+KPX Dcroat V -40
+KPX Dcroat W -40
+KPX Dcroat Y -40
+KPX Dcroat Yacute -40
+KPX Dcroat Ydieresis -40
+KPX Dcroat period -20
+KPX F A -90
+KPX F Aacute -90
+KPX F Abreve -90
+KPX F Acircumflex -90
+KPX F Adieresis -90
+KPX F Agrave -90
+KPX F Amacron -90
+KPX F Aogonek -90
+KPX F Aring -90
+KPX F Atilde -90
+KPX F a -25
+KPX F aacute -25
+KPX F abreve -25
+KPX F acircumflex -25
+KPX F adieresis -25
+KPX F agrave -25
+KPX F amacron -25
+KPX F aogonek -25
+KPX F aring -25
+KPX F atilde -25
+KPX F comma -92
+KPX F e -25
+KPX F eacute -25
+KPX F ecaron -25
+KPX F ecircumflex -25
+KPX F edieresis -25
+KPX F edotaccent -25
+KPX F egrave -25
+KPX F emacron -25
+KPX F eogonek -25
+KPX F o -25
+KPX F oacute -25
+KPX F ocircumflex -25
+KPX F odieresis -25
+KPX F ograve -25
+KPX F ohungarumlaut -25
+KPX F omacron -25
+KPX F oslash -25
+KPX F otilde -25
+KPX F period -110
+KPX J A -30
+KPX J Aacute -30
+KPX J Abreve -30
+KPX J Acircumflex -30
+KPX J Adieresis -30
+KPX J Agrave -30
+KPX J Amacron -30
+KPX J Aogonek -30
+KPX J Aring -30
+KPX J Atilde -30
+KPX J a -15
+KPX J aacute -15
+KPX J abreve -15
+KPX J acircumflex -15
+KPX J adieresis -15
+KPX J agrave -15
+KPX J amacron -15
+KPX J aogonek -15
+KPX J aring -15
+KPX J atilde -15
+KPX J e -15
+KPX J eacute -15
+KPX J ecaron -15
+KPX J ecircumflex -15
+KPX J edieresis -15
+KPX J edotaccent -15
+KPX J egrave -15
+KPX J emacron -15
+KPX J eogonek -15
+KPX J o -15
+KPX J oacute -15
+KPX J ocircumflex -15
+KPX J odieresis -15
+KPX J ograve -15
+KPX J ohungarumlaut -15
+KPX J omacron -15
+KPX J oslash -15
+KPX J otilde -15
+KPX J period -20
+KPX J u -15
+KPX J uacute -15
+KPX J ucircumflex -15
+KPX J udieresis -15
+KPX J ugrave -15
+KPX J uhungarumlaut -15
+KPX J umacron -15
+KPX J uogonek -15
+KPX J uring -15
+KPX K O -30
+KPX K Oacute -30
+KPX K Ocircumflex -30
+KPX K Odieresis -30
+KPX K Ograve -30
+KPX K Ohungarumlaut -30
+KPX K Omacron -30
+KPX K Oslash -30
+KPX K Otilde -30
+KPX K e -25
+KPX K eacute -25
+KPX K ecaron -25
+KPX K ecircumflex -25
+KPX K edieresis -25
+KPX K edotaccent -25
+KPX K egrave -25
+KPX K emacron -25
+KPX K eogonek -25
+KPX K o -25
+KPX K oacute -25
+KPX K ocircumflex -25
+KPX K odieresis -25
+KPX K ograve -25
+KPX K ohungarumlaut -25
+KPX K omacron -25
+KPX K oslash -25
+KPX K otilde -25
+KPX K u -15
+KPX K uacute -15
+KPX K ucircumflex -15
+KPX K udieresis -15
+KPX K ugrave -15
+KPX K uhungarumlaut -15
+KPX K umacron -15
+KPX K uogonek -15
+KPX K uring -15
+KPX K y -45
+KPX K yacute -45
+KPX K ydieresis -45
+KPX Kcommaaccent O -30
+KPX Kcommaaccent Oacute -30
+KPX Kcommaaccent Ocircumflex -30
+KPX Kcommaaccent Odieresis -30
+KPX Kcommaaccent Ograve -30
+KPX Kcommaaccent Ohungarumlaut -30
+KPX Kcommaaccent Omacron -30
+KPX Kcommaaccent Oslash -30
+KPX Kcommaaccent Otilde -30
+KPX Kcommaaccent e -25
+KPX Kcommaaccent eacute -25
+KPX Kcommaaccent ecaron -25
+KPX Kcommaaccent ecircumflex -25
+KPX Kcommaaccent edieresis -25
+KPX Kcommaaccent edotaccent -25
+KPX Kcommaaccent egrave -25
+KPX Kcommaaccent emacron -25
+KPX Kcommaaccent eogonek -25
+KPX Kcommaaccent o -25
+KPX Kcommaaccent oacute -25
+KPX Kcommaaccent ocircumflex -25
+KPX Kcommaaccent odieresis -25
+KPX Kcommaaccent ograve -25
+KPX Kcommaaccent ohungarumlaut -25
+KPX Kcommaaccent omacron -25
+KPX Kcommaaccent oslash -25
+KPX Kcommaaccent otilde -25
+KPX Kcommaaccent u -15
+KPX Kcommaaccent uacute -15
+KPX Kcommaaccent ucircumflex -15
+KPX Kcommaaccent udieresis -15
+KPX Kcommaaccent ugrave -15
+KPX Kcommaaccent uhungarumlaut -15
+KPX Kcommaaccent umacron -15
+KPX Kcommaaccent uogonek -15
+KPX Kcommaaccent uring -15
+KPX Kcommaaccent y -45
+KPX Kcommaaccent yacute -45
+KPX Kcommaaccent ydieresis -45
+KPX L T -92
+KPX L Tcaron -92
+KPX L Tcommaaccent -92
+KPX L V -92
+KPX L W -92
+KPX L Y -92
+KPX L Yacute -92
+KPX L Ydieresis -92
+KPX L quotedblright -20
+KPX L quoteright -110
+KPX L y -55
+KPX L yacute -55
+KPX L ydieresis -55
+KPX Lacute T -92
+KPX Lacute Tcaron -92
+KPX Lacute Tcommaaccent -92
+KPX Lacute V -92
+KPX Lacute W -92
+KPX Lacute Y -92
+KPX Lacute Yacute -92
+KPX Lacute Ydieresis -92
+KPX Lacute quotedblright -20
+KPX Lacute quoteright -110
+KPX Lacute y -55
+KPX Lacute yacute -55
+KPX Lacute ydieresis -55
+KPX Lcommaaccent T -92
+KPX Lcommaaccent Tcaron -92
+KPX Lcommaaccent Tcommaaccent -92
+KPX Lcommaaccent V -92
+KPX Lcommaaccent W -92
+KPX Lcommaaccent Y -92
+KPX Lcommaaccent Yacute -92
+KPX Lcommaaccent Ydieresis -92
+KPX Lcommaaccent quotedblright -20
+KPX Lcommaaccent quoteright -110
+KPX Lcommaaccent y -55
+KPX Lcommaaccent yacute -55
+KPX Lcommaaccent ydieresis -55
+KPX Lslash T -92
+KPX Lslash Tcaron -92
+KPX Lslash Tcommaaccent -92
+KPX Lslash V -92
+KPX Lslash W -92
+KPX Lslash Y -92
+KPX Lslash Yacute -92
+KPX Lslash Ydieresis -92
+KPX Lslash quotedblright -20
+KPX Lslash quoteright -110
+KPX Lslash y -55
+KPX Lslash yacute -55
+KPX Lslash ydieresis -55
+KPX N A -20
+KPX N Aacute -20
+KPX N Abreve -20
+KPX N Acircumflex -20
+KPX N Adieresis -20
+KPX N Agrave -20
+KPX N Amacron -20
+KPX N Aogonek -20
+KPX N Aring -20
+KPX N Atilde -20
+KPX Nacute A -20
+KPX Nacute Aacute -20
+KPX Nacute Abreve -20
+KPX Nacute Acircumflex -20
+KPX Nacute Adieresis -20
+KPX Nacute Agrave -20
+KPX Nacute Amacron -20
+KPX Nacute Aogonek -20
+KPX Nacute Aring -20
+KPX Nacute Atilde -20
+KPX Ncaron A -20
+KPX Ncaron Aacute -20
+KPX Ncaron Abreve -20
+KPX Ncaron Acircumflex -20
+KPX Ncaron Adieresis -20
+KPX Ncaron Agrave -20
+KPX Ncaron Amacron -20
+KPX Ncaron Aogonek -20
+KPX Ncaron Aring -20
+KPX Ncaron Atilde -20
+KPX Ncommaaccent A -20
+KPX Ncommaaccent Aacute -20
+KPX Ncommaaccent Abreve -20
+KPX Ncommaaccent Acircumflex -20
+KPX Ncommaaccent Adieresis -20
+KPX Ncommaaccent Agrave -20
+KPX Ncommaaccent Amacron -20
+KPX Ncommaaccent Aogonek -20
+KPX Ncommaaccent Aring -20
+KPX Ncommaaccent Atilde -20
+KPX Ntilde A -20
+KPX Ntilde Aacute -20
+KPX Ntilde Abreve -20
+KPX Ntilde Acircumflex -20
+KPX Ntilde Adieresis -20
+KPX Ntilde Agrave -20
+KPX Ntilde Amacron -20
+KPX Ntilde Aogonek -20
+KPX Ntilde Aring -20
+KPX Ntilde Atilde -20
+KPX O A -40
+KPX O Aacute -40
+KPX O Abreve -40
+KPX O Acircumflex -40
+KPX O Adieresis -40
+KPX O Agrave -40
+KPX O Amacron -40
+KPX O Aogonek -40
+KPX O Aring -40
+KPX O Atilde -40
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -50
+KPX O X -40
+KPX O Y -50
+KPX O Yacute -50
+KPX O Ydieresis -50
+KPX Oacute A -40
+KPX Oacute Aacute -40
+KPX Oacute Abreve -40
+KPX Oacute Acircumflex -40
+KPX Oacute Adieresis -40
+KPX Oacute Agrave -40
+KPX Oacute Amacron -40
+KPX Oacute Aogonek -40
+KPX Oacute Aring -40
+KPX Oacute Atilde -40
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -50
+KPX Oacute X -40
+KPX Oacute Y -50
+KPX Oacute Yacute -50
+KPX Oacute Ydieresis -50
+KPX Ocircumflex A -40
+KPX Ocircumflex Aacute -40
+KPX Ocircumflex Abreve -40
+KPX Ocircumflex Acircumflex -40
+KPX Ocircumflex Adieresis -40
+KPX Ocircumflex Agrave -40
+KPX Ocircumflex Amacron -40
+KPX Ocircumflex Aogonek -40
+KPX Ocircumflex Aring -40
+KPX Ocircumflex Atilde -40
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -50
+KPX Ocircumflex X -40
+KPX Ocircumflex Y -50
+KPX Ocircumflex Yacute -50
+KPX Ocircumflex Ydieresis -50
+KPX Odieresis A -40
+KPX Odieresis Aacute -40
+KPX Odieresis Abreve -40
+KPX Odieresis Acircumflex -40
+KPX Odieresis Adieresis -40
+KPX Odieresis Agrave -40
+KPX Odieresis Amacron -40
+KPX Odieresis Aogonek -40
+KPX Odieresis Aring -40
+KPX Odieresis Atilde -40
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -50
+KPX Odieresis X -40
+KPX Odieresis Y -50
+KPX Odieresis Yacute -50
+KPX Odieresis Ydieresis -50
+KPX Ograve A -40
+KPX Ograve Aacute -40
+KPX Ograve Abreve -40
+KPX Ograve Acircumflex -40
+KPX Ograve Adieresis -40
+KPX Ograve Agrave -40
+KPX Ograve Amacron -40
+KPX Ograve Aogonek -40
+KPX Ograve Aring -40
+KPX Ograve Atilde -40
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -50
+KPX Ograve X -40
+KPX Ograve Y -50
+KPX Ograve Yacute -50
+KPX Ograve Ydieresis -50
+KPX Ohungarumlaut A -40
+KPX Ohungarumlaut Aacute -40
+KPX Ohungarumlaut Abreve -40
+KPX Ohungarumlaut Acircumflex -40
+KPX Ohungarumlaut Adieresis -40
+KPX Ohungarumlaut Agrave -40
+KPX Ohungarumlaut Amacron -40
+KPX Ohungarumlaut Aogonek -40
+KPX Ohungarumlaut Aring -40
+KPX Ohungarumlaut Atilde -40
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -50
+KPX Ohungarumlaut X -40
+KPX Ohungarumlaut Y -50
+KPX Ohungarumlaut Yacute -50
+KPX Ohungarumlaut Ydieresis -50
+KPX Omacron A -40
+KPX Omacron Aacute -40
+KPX Omacron Abreve -40
+KPX Omacron Acircumflex -40
+KPX Omacron Adieresis -40
+KPX Omacron Agrave -40
+KPX Omacron Amacron -40
+KPX Omacron Aogonek -40
+KPX Omacron Aring -40
+KPX Omacron Atilde -40
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -50
+KPX Omacron X -40
+KPX Omacron Y -50
+KPX Omacron Yacute -50
+KPX Omacron Ydieresis -50
+KPX Oslash A -40
+KPX Oslash Aacute -40
+KPX Oslash Abreve -40
+KPX Oslash Acircumflex -40
+KPX Oslash Adieresis -40
+KPX Oslash Agrave -40
+KPX Oslash Amacron -40
+KPX Oslash Aogonek -40
+KPX Oslash Aring -40
+KPX Oslash Atilde -40
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -50
+KPX Oslash X -40
+KPX Oslash Y -50
+KPX Oslash Yacute -50
+KPX Oslash Ydieresis -50
+KPX Otilde A -40
+KPX Otilde Aacute -40
+KPX Otilde Abreve -40
+KPX Otilde Acircumflex -40
+KPX Otilde Adieresis -40
+KPX Otilde Agrave -40
+KPX Otilde Amacron -40
+KPX Otilde Aogonek -40
+KPX Otilde Aring -40
+KPX Otilde Atilde -40
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -50
+KPX Otilde X -40
+KPX Otilde Y -50
+KPX Otilde Yacute -50
+KPX Otilde Ydieresis -50
+KPX P A -74
+KPX P Aacute -74
+KPX P Abreve -74
+KPX P Acircumflex -74
+KPX P Adieresis -74
+KPX P Agrave -74
+KPX P Amacron -74
+KPX P Aogonek -74
+KPX P Aring -74
+KPX P Atilde -74
+KPX P a -10
+KPX P aacute -10
+KPX P abreve -10
+KPX P acircumflex -10
+KPX P adieresis -10
+KPX P agrave -10
+KPX P amacron -10
+KPX P aogonek -10
+KPX P aring -10
+KPX P atilde -10
+KPX P comma -92
+KPX P e -20
+KPX P eacute -20
+KPX P ecaron -20
+KPX P ecircumflex -20
+KPX P edieresis -20
+KPX P edotaccent -20
+KPX P egrave -20
+KPX P emacron -20
+KPX P eogonek -20
+KPX P o -20
+KPX P oacute -20
+KPX P ocircumflex -20
+KPX P odieresis -20
+KPX P ograve -20
+KPX P ohungarumlaut -20
+KPX P omacron -20
+KPX P oslash -20
+KPX P otilde -20
+KPX P period -110
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX Q period -20
+KPX R O -30
+KPX R Oacute -30
+KPX R Ocircumflex -30
+KPX R Odieresis -30
+KPX R Ograve -30
+KPX R Ohungarumlaut -30
+KPX R Omacron -30
+KPX R Oslash -30
+KPX R Otilde -30
+KPX R T -40
+KPX R Tcaron -40
+KPX R Tcommaaccent -40
+KPX R U -30
+KPX R Uacute -30
+KPX R Ucircumflex -30
+KPX R Udieresis -30
+KPX R Ugrave -30
+KPX R Uhungarumlaut -30
+KPX R Umacron -30
+KPX R Uogonek -30
+KPX R Uring -30
+KPX R V -55
+KPX R W -35
+KPX R Y -35
+KPX R Yacute -35
+KPX R Ydieresis -35
+KPX Racute O -30
+KPX Racute Oacute -30
+KPX Racute Ocircumflex -30
+KPX Racute Odieresis -30
+KPX Racute Ograve -30
+KPX Racute Ohungarumlaut -30
+KPX Racute Omacron -30
+KPX Racute Oslash -30
+KPX Racute Otilde -30
+KPX Racute T -40
+KPX Racute Tcaron -40
+KPX Racute Tcommaaccent -40
+KPX Racute U -30
+KPX Racute Uacute -30
+KPX Racute Ucircumflex -30
+KPX Racute Udieresis -30
+KPX Racute Ugrave -30
+KPX Racute Uhungarumlaut -30
+KPX Racute Umacron -30
+KPX Racute Uogonek -30
+KPX Racute Uring -30
+KPX Racute V -55
+KPX Racute W -35
+KPX Racute Y -35
+KPX Racute Yacute -35
+KPX Racute Ydieresis -35
+KPX Rcaron O -30
+KPX Rcaron Oacute -30
+KPX Rcaron Ocircumflex -30
+KPX Rcaron Odieresis -30
+KPX Rcaron Ograve -30
+KPX Rcaron Ohungarumlaut -30
+KPX Rcaron Omacron -30
+KPX Rcaron Oslash -30
+KPX Rcaron Otilde -30
+KPX Rcaron T -40
+KPX Rcaron Tcaron -40
+KPX Rcaron Tcommaaccent -40
+KPX Rcaron U -30
+KPX Rcaron Uacute -30
+KPX Rcaron Ucircumflex -30
+KPX Rcaron Udieresis -30
+KPX Rcaron Ugrave -30
+KPX Rcaron Uhungarumlaut -30
+KPX Rcaron Umacron -30
+KPX Rcaron Uogonek -30
+KPX Rcaron Uring -30
+KPX Rcaron V -55
+KPX Rcaron W -35
+KPX Rcaron Y -35
+KPX Rcaron Yacute -35
+KPX Rcaron Ydieresis -35
+KPX Rcommaaccent O -30
+KPX Rcommaaccent Oacute -30
+KPX Rcommaaccent Ocircumflex -30
+KPX Rcommaaccent Odieresis -30
+KPX Rcommaaccent Ograve -30
+KPX Rcommaaccent Ohungarumlaut -30
+KPX Rcommaaccent Omacron -30
+KPX Rcommaaccent Oslash -30
+KPX Rcommaaccent Otilde -30
+KPX Rcommaaccent T -40
+KPX Rcommaaccent Tcaron -40
+KPX Rcommaaccent Tcommaaccent -40
+KPX Rcommaaccent U -30
+KPX Rcommaaccent Uacute -30
+KPX Rcommaaccent Ucircumflex -30
+KPX Rcommaaccent Udieresis -30
+KPX Rcommaaccent Ugrave -30
+KPX Rcommaaccent Uhungarumlaut -30
+KPX Rcommaaccent Umacron -30
+KPX Rcommaaccent Uogonek -30
+KPX Rcommaaccent Uring -30
+KPX Rcommaaccent V -55
+KPX Rcommaaccent W -35
+KPX Rcommaaccent Y -35
+KPX Rcommaaccent Yacute -35
+KPX Rcommaaccent Ydieresis -35
+KPX T A -90
+KPX T Aacute -90
+KPX T Abreve -90
+KPX T Acircumflex -90
+KPX T Adieresis -90
+KPX T Agrave -90
+KPX T Amacron -90
+KPX T Aogonek -90
+KPX T Aring -90
+KPX T Atilde -90
+KPX T O -18
+KPX T Oacute -18
+KPX T Ocircumflex -18
+KPX T Odieresis -18
+KPX T Ograve -18
+KPX T Ohungarumlaut -18
+KPX T Omacron -18
+KPX T Oslash -18
+KPX T Otilde -18
+KPX T a -92
+KPX T aacute -92
+KPX T abreve -52
+KPX T acircumflex -52
+KPX T adieresis -52
+KPX T agrave -52
+KPX T amacron -52
+KPX T aogonek -92
+KPX T aring -92
+KPX T atilde -52
+KPX T colon -74
+KPX T comma -74
+KPX T e -92
+KPX T eacute -92
+KPX T ecaron -92
+KPX T ecircumflex -92
+KPX T edieresis -52
+KPX T edotaccent -92
+KPX T egrave -52
+KPX T emacron -52
+KPX T eogonek -92
+KPX T hyphen -92
+KPX T i -18
+KPX T iacute -18
+KPX T iogonek -18
+KPX T o -92
+KPX T oacute -92
+KPX T ocircumflex -92
+KPX T odieresis -92
+KPX T ograve -92
+KPX T ohungarumlaut -92
+KPX T omacron -92
+KPX T oslash -92
+KPX T otilde -92
+KPX T period -90
+KPX T r -74
+KPX T racute -74
+KPX T rcaron -74
+KPX T rcommaaccent -74
+KPX T semicolon -74
+KPX T u -92
+KPX T uacute -92
+KPX T ucircumflex -92
+KPX T udieresis -92
+KPX T ugrave -92
+KPX T uhungarumlaut -92
+KPX T umacron -92
+KPX T uogonek -92
+KPX T uring -92
+KPX T w -74
+KPX T y -34
+KPX T yacute -34
+KPX T ydieresis -34
+KPX Tcaron A -90
+KPX Tcaron Aacute -90
+KPX Tcaron Abreve -90
+KPX Tcaron Acircumflex -90
+KPX Tcaron Adieresis -90
+KPX Tcaron Agrave -90
+KPX Tcaron Amacron -90
+KPX Tcaron Aogonek -90
+KPX Tcaron Aring -90
+KPX Tcaron Atilde -90
+KPX Tcaron O -18
+KPX Tcaron Oacute -18
+KPX Tcaron Ocircumflex -18
+KPX Tcaron Odieresis -18
+KPX Tcaron Ograve -18
+KPX Tcaron Ohungarumlaut -18
+KPX Tcaron Omacron -18
+KPX Tcaron Oslash -18
+KPX Tcaron Otilde -18
+KPX Tcaron a -92
+KPX Tcaron aacute -92
+KPX Tcaron abreve -52
+KPX Tcaron acircumflex -52
+KPX Tcaron adieresis -52
+KPX Tcaron agrave -52
+KPX Tcaron amacron -52
+KPX Tcaron aogonek -92
+KPX Tcaron aring -92
+KPX Tcaron atilde -52
+KPX Tcaron colon -74
+KPX Tcaron comma -74
+KPX Tcaron e -92
+KPX Tcaron eacute -92
+KPX Tcaron ecaron -92
+KPX Tcaron ecircumflex -92
+KPX Tcaron edieresis -52
+KPX Tcaron edotaccent -92
+KPX Tcaron egrave -52
+KPX Tcaron emacron -52
+KPX Tcaron eogonek -92
+KPX Tcaron hyphen -92
+KPX Tcaron i -18
+KPX Tcaron iacute -18
+KPX Tcaron iogonek -18
+KPX Tcaron o -92
+KPX Tcaron oacute -92
+KPX Tcaron ocircumflex -92
+KPX Tcaron odieresis -92
+KPX Tcaron ograve -92
+KPX Tcaron ohungarumlaut -92
+KPX Tcaron omacron -92
+KPX Tcaron oslash -92
+KPX Tcaron otilde -92
+KPX Tcaron period -90
+KPX Tcaron r -74
+KPX Tcaron racute -74
+KPX Tcaron rcaron -74
+KPX Tcaron rcommaaccent -74
+KPX Tcaron semicolon -74
+KPX Tcaron u -92
+KPX Tcaron uacute -92
+KPX Tcaron ucircumflex -92
+KPX Tcaron udieresis -92
+KPX Tcaron ugrave -92
+KPX Tcaron uhungarumlaut -92
+KPX Tcaron umacron -92
+KPX Tcaron uogonek -92
+KPX Tcaron uring -92
+KPX Tcaron w -74
+KPX Tcaron y -34
+KPX Tcaron yacute -34
+KPX Tcaron ydieresis -34
+KPX Tcommaaccent A -90
+KPX Tcommaaccent Aacute -90
+KPX Tcommaaccent Abreve -90
+KPX Tcommaaccent Acircumflex -90
+KPX Tcommaaccent Adieresis -90
+KPX Tcommaaccent Agrave -90
+KPX Tcommaaccent Amacron -90
+KPX Tcommaaccent Aogonek -90
+KPX Tcommaaccent Aring -90
+KPX Tcommaaccent Atilde -90
+KPX Tcommaaccent O -18
+KPX Tcommaaccent Oacute -18
+KPX Tcommaaccent Ocircumflex -18
+KPX Tcommaaccent Odieresis -18
+KPX Tcommaaccent Ograve -18
+KPX Tcommaaccent Ohungarumlaut -18
+KPX Tcommaaccent Omacron -18
+KPX Tcommaaccent Oslash -18
+KPX Tcommaaccent Otilde -18
+KPX Tcommaaccent a -92
+KPX Tcommaaccent aacute -92
+KPX Tcommaaccent abreve -52
+KPX Tcommaaccent acircumflex -52
+KPX Tcommaaccent adieresis -52
+KPX Tcommaaccent agrave -52
+KPX Tcommaaccent amacron -52
+KPX Tcommaaccent aogonek -92
+KPX Tcommaaccent aring -92
+KPX Tcommaaccent atilde -52
+KPX Tcommaaccent colon -74
+KPX Tcommaaccent comma -74
+KPX Tcommaaccent e -92
+KPX Tcommaaccent eacute -92
+KPX Tcommaaccent ecaron -92
+KPX Tcommaaccent ecircumflex -92
+KPX Tcommaaccent edieresis -52
+KPX Tcommaaccent edotaccent -92
+KPX Tcommaaccent egrave -52
+KPX Tcommaaccent emacron -52
+KPX Tcommaaccent eogonek -92
+KPX Tcommaaccent hyphen -92
+KPX Tcommaaccent i -18
+KPX Tcommaaccent iacute -18
+KPX Tcommaaccent iogonek -18
+KPX Tcommaaccent o -92
+KPX Tcommaaccent oacute -92
+KPX Tcommaaccent ocircumflex -92
+KPX Tcommaaccent odieresis -92
+KPX Tcommaaccent ograve -92
+KPX Tcommaaccent ohungarumlaut -92
+KPX Tcommaaccent omacron -92
+KPX Tcommaaccent oslash -92
+KPX Tcommaaccent otilde -92
+KPX Tcommaaccent period -90
+KPX Tcommaaccent r -74
+KPX Tcommaaccent racute -74
+KPX Tcommaaccent rcaron -74
+KPX Tcommaaccent rcommaaccent -74
+KPX Tcommaaccent semicolon -74
+KPX Tcommaaccent u -92
+KPX Tcommaaccent uacute -92
+KPX Tcommaaccent ucircumflex -92
+KPX Tcommaaccent udieresis -92
+KPX Tcommaaccent ugrave -92
+KPX Tcommaaccent uhungarumlaut -92
+KPX Tcommaaccent umacron -92
+KPX Tcommaaccent uogonek -92
+KPX Tcommaaccent uring -92
+KPX Tcommaaccent w -74
+KPX Tcommaaccent y -34
+KPX Tcommaaccent yacute -34
+KPX Tcommaaccent ydieresis -34
+KPX U A -60
+KPX U Aacute -60
+KPX U Abreve -60
+KPX U Acircumflex -60
+KPX U Adieresis -60
+KPX U Agrave -60
+KPX U Amacron -60
+KPX U Aogonek -60
+KPX U Aring -60
+KPX U Atilde -60
+KPX U comma -50
+KPX U period -50
+KPX Uacute A -60
+KPX Uacute Aacute -60
+KPX Uacute Abreve -60
+KPX Uacute Acircumflex -60
+KPX Uacute Adieresis -60
+KPX Uacute Agrave -60
+KPX Uacute Amacron -60
+KPX Uacute Aogonek -60
+KPX Uacute Aring -60
+KPX Uacute Atilde -60
+KPX Uacute comma -50
+KPX Uacute period -50
+KPX Ucircumflex A -60
+KPX Ucircumflex Aacute -60
+KPX Ucircumflex Abreve -60
+KPX Ucircumflex Acircumflex -60
+KPX Ucircumflex Adieresis -60
+KPX Ucircumflex Agrave -60
+KPX Ucircumflex Amacron -60
+KPX Ucircumflex Aogonek -60
+KPX Ucircumflex Aring -60
+KPX Ucircumflex Atilde -60
+KPX Ucircumflex comma -50
+KPX Ucircumflex period -50
+KPX Udieresis A -60
+KPX Udieresis Aacute -60
+KPX Udieresis Abreve -60
+KPX Udieresis Acircumflex -60
+KPX Udieresis Adieresis -60
+KPX Udieresis Agrave -60
+KPX Udieresis Amacron -60
+KPX Udieresis Aogonek -60
+KPX Udieresis Aring -60
+KPX Udieresis Atilde -60
+KPX Udieresis comma -50
+KPX Udieresis period -50
+KPX Ugrave A -60
+KPX Ugrave Aacute -60
+KPX Ugrave Abreve -60
+KPX Ugrave Acircumflex -60
+KPX Ugrave Adieresis -60
+KPX Ugrave Agrave -60
+KPX Ugrave Amacron -60
+KPX Ugrave Aogonek -60
+KPX Ugrave Aring -60
+KPX Ugrave Atilde -60
+KPX Ugrave comma -50
+KPX Ugrave period -50
+KPX Uhungarumlaut A -60
+KPX Uhungarumlaut Aacute -60
+KPX Uhungarumlaut Abreve -60
+KPX Uhungarumlaut Acircumflex -60
+KPX Uhungarumlaut Adieresis -60
+KPX Uhungarumlaut Agrave -60
+KPX Uhungarumlaut Amacron -60
+KPX Uhungarumlaut Aogonek -60
+KPX Uhungarumlaut Aring -60
+KPX Uhungarumlaut Atilde -60
+KPX Uhungarumlaut comma -50
+KPX Uhungarumlaut period -50
+KPX Umacron A -60
+KPX Umacron Aacute -60
+KPX Umacron Abreve -60
+KPX Umacron Acircumflex -60
+KPX Umacron Adieresis -60
+KPX Umacron Agrave -60
+KPX Umacron Amacron -60
+KPX Umacron Aogonek -60
+KPX Umacron Aring -60
+KPX Umacron Atilde -60
+KPX Umacron comma -50
+KPX Umacron period -50
+KPX Uogonek A -60
+KPX Uogonek Aacute -60
+KPX Uogonek Abreve -60
+KPX Uogonek Acircumflex -60
+KPX Uogonek Adieresis -60
+KPX Uogonek Agrave -60
+KPX Uogonek Amacron -60
+KPX Uogonek Aogonek -60
+KPX Uogonek Aring -60
+KPX Uogonek Atilde -60
+KPX Uogonek comma -50
+KPX Uogonek period -50
+KPX Uring A -60
+KPX Uring Aacute -60
+KPX Uring Abreve -60
+KPX Uring Acircumflex -60
+KPX Uring Adieresis -60
+KPX Uring Agrave -60
+KPX Uring Amacron -60
+KPX Uring Aogonek -60
+KPX Uring Aring -60
+KPX Uring Atilde -60
+KPX Uring comma -50
+KPX Uring period -50
+KPX V A -135
+KPX V Aacute -135
+KPX V Abreve -135
+KPX V Acircumflex -135
+KPX V Adieresis -135
+KPX V Agrave -135
+KPX V Amacron -135
+KPX V Aogonek -135
+KPX V Aring -135
+KPX V Atilde -135
+KPX V G -30
+KPX V Gbreve -30
+KPX V Gcommaaccent -30
+KPX V O -45
+KPX V Oacute -45
+KPX V Ocircumflex -45
+KPX V Odieresis -45
+KPX V Ograve -45
+KPX V Ohungarumlaut -45
+KPX V Omacron -45
+KPX V Oslash -45
+KPX V Otilde -45
+KPX V a -92
+KPX V aacute -92
+KPX V abreve -92
+KPX V acircumflex -92
+KPX V adieresis -92
+KPX V agrave -92
+KPX V amacron -92
+KPX V aogonek -92
+KPX V aring -92
+KPX V atilde -92
+KPX V colon -92
+KPX V comma -129
+KPX V e -100
+KPX V eacute -100
+KPX V ecaron -100
+KPX V ecircumflex -100
+KPX V edieresis -100
+KPX V edotaccent -100
+KPX V egrave -100
+KPX V emacron -100
+KPX V eogonek -100
+KPX V hyphen -74
+KPX V i -37
+KPX V iacute -37
+KPX V icircumflex -37
+KPX V idieresis -37
+KPX V igrave -37
+KPX V imacron -37
+KPX V iogonek -37
+KPX V o -100
+KPX V oacute -100
+KPX V ocircumflex -100
+KPX V odieresis -100
+KPX V ograve -100
+KPX V ohungarumlaut -100
+KPX V omacron -100
+KPX V oslash -100
+KPX V otilde -100
+KPX V period -145
+KPX V semicolon -92
+KPX V u -92
+KPX V uacute -92
+KPX V ucircumflex -92
+KPX V udieresis -92
+KPX V ugrave -92
+KPX V uhungarumlaut -92
+KPX V umacron -92
+KPX V uogonek -92
+KPX V uring -92
+KPX W A -120
+KPX W Aacute -120
+KPX W Abreve -120
+KPX W Acircumflex -120
+KPX W Adieresis -120
+KPX W Agrave -120
+KPX W Amacron -120
+KPX W Aogonek -120
+KPX W Aring -120
+KPX W Atilde -120
+KPX W O -10
+KPX W Oacute -10
+KPX W Ocircumflex -10
+KPX W Odieresis -10
+KPX W Ograve -10
+KPX W Ohungarumlaut -10
+KPX W Omacron -10
+KPX W Oslash -10
+KPX W Otilde -10
+KPX W a -65
+KPX W aacute -65
+KPX W abreve -65
+KPX W acircumflex -65
+KPX W adieresis -65
+KPX W agrave -65
+KPX W amacron -65
+KPX W aogonek -65
+KPX W aring -65
+KPX W atilde -65
+KPX W colon -55
+KPX W comma -92
+KPX W e -65
+KPX W eacute -65
+KPX W ecaron -65
+KPX W ecircumflex -65
+KPX W edieresis -65
+KPX W edotaccent -65
+KPX W egrave -65
+KPX W emacron -65
+KPX W eogonek -65
+KPX W hyphen -37
+KPX W i -18
+KPX W iacute -18
+KPX W iogonek -18
+KPX W o -75
+KPX W oacute -75
+KPX W ocircumflex -75
+KPX W odieresis -75
+KPX W ograve -75
+KPX W ohungarumlaut -75
+KPX W omacron -75
+KPX W oslash -75
+KPX W otilde -75
+KPX W period -92
+KPX W semicolon -55
+KPX W u -50
+KPX W uacute -50
+KPX W ucircumflex -50
+KPX W udieresis -50
+KPX W ugrave -50
+KPX W uhungarumlaut -50
+KPX W umacron -50
+KPX W uogonek -50
+KPX W uring -50
+KPX W y -60
+KPX W yacute -60
+KPX W ydieresis -60
+KPX Y A -110
+KPX Y Aacute -110
+KPX Y Abreve -110
+KPX Y Acircumflex -110
+KPX Y Adieresis -110
+KPX Y Agrave -110
+KPX Y Amacron -110
+KPX Y Aogonek -110
+KPX Y Aring -110
+KPX Y Atilde -110
+KPX Y O -35
+KPX Y Oacute -35
+KPX Y Ocircumflex -35
+KPX Y Odieresis -35
+KPX Y Ograve -35
+KPX Y Ohungarumlaut -35
+KPX Y Omacron -35
+KPX Y Oslash -35
+KPX Y Otilde -35
+KPX Y a -85
+KPX Y aacute -85
+KPX Y abreve -85
+KPX Y acircumflex -85
+KPX Y adieresis -85
+KPX Y agrave -85
+KPX Y amacron -85
+KPX Y aogonek -85
+KPX Y aring -85
+KPX Y atilde -85
+KPX Y colon -92
+KPX Y comma -92
+KPX Y e -111
+KPX Y eacute -111
+KPX Y ecaron -111
+KPX Y ecircumflex -111
+KPX Y edieresis -71
+KPX Y edotaccent -111
+KPX Y egrave -71
+KPX Y emacron -71
+KPX Y eogonek -111
+KPX Y hyphen -92
+KPX Y i -37
+KPX Y iacute -37
+KPX Y iogonek -37
+KPX Y o -111
+KPX Y oacute -111
+KPX Y ocircumflex -111
+KPX Y odieresis -111
+KPX Y ograve -111
+KPX Y ohungarumlaut -111
+KPX Y omacron -111
+KPX Y oslash -111
+KPX Y otilde -111
+KPX Y period -92
+KPX Y semicolon -92
+KPX Y u -92
+KPX Y uacute -92
+KPX Y ucircumflex -92
+KPX Y udieresis -92
+KPX Y ugrave -92
+KPX Y uhungarumlaut -92
+KPX Y umacron -92
+KPX Y uogonek -92
+KPX Y uring -92
+KPX Yacute A -110
+KPX Yacute Aacute -110
+KPX Yacute Abreve -110
+KPX Yacute Acircumflex -110
+KPX Yacute Adieresis -110
+KPX Yacute Agrave -110
+KPX Yacute Amacron -110
+KPX Yacute Aogonek -110
+KPX Yacute Aring -110
+KPX Yacute Atilde -110
+KPX Yacute O -35
+KPX Yacute Oacute -35
+KPX Yacute Ocircumflex -35
+KPX Yacute Odieresis -35
+KPX Yacute Ograve -35
+KPX Yacute Ohungarumlaut -35
+KPX Yacute Omacron -35
+KPX Yacute Oslash -35
+KPX Yacute Otilde -35
+KPX Yacute a -85
+KPX Yacute aacute -85
+KPX Yacute abreve -85
+KPX Yacute acircumflex -85
+KPX Yacute adieresis -85
+KPX Yacute agrave -85
+KPX Yacute amacron -85
+KPX Yacute aogonek -85
+KPX Yacute aring -85
+KPX Yacute atilde -85
+KPX Yacute colon -92
+KPX Yacute comma -92
+KPX Yacute e -111
+KPX Yacute eacute -111
+KPX Yacute ecaron -111
+KPX Yacute ecircumflex -111
+KPX Yacute edieresis -71
+KPX Yacute edotaccent -111
+KPX Yacute egrave -71
+KPX Yacute emacron -71
+KPX Yacute eogonek -111
+KPX Yacute hyphen -92
+KPX Yacute i -37
+KPX Yacute iacute -37
+KPX Yacute iogonek -37
+KPX Yacute o -111
+KPX Yacute oacute -111
+KPX Yacute ocircumflex -111
+KPX Yacute odieresis -111
+KPX Yacute ograve -111
+KPX Yacute ohungarumlaut -111
+KPX Yacute omacron -111
+KPX Yacute oslash -111
+KPX Yacute otilde -111
+KPX Yacute period -92
+KPX Yacute semicolon -92
+KPX Yacute u -92
+KPX Yacute uacute -92
+KPX Yacute ucircumflex -92
+KPX Yacute udieresis -92
+KPX Yacute ugrave -92
+KPX Yacute uhungarumlaut -92
+KPX Yacute umacron -92
+KPX Yacute uogonek -92
+KPX Yacute uring -92
+KPX Ydieresis A -110
+KPX Ydieresis Aacute -110
+KPX Ydieresis Abreve -110
+KPX Ydieresis Acircumflex -110
+KPX Ydieresis Adieresis -110
+KPX Ydieresis Agrave -110
+KPX Ydieresis Amacron -110
+KPX Ydieresis Aogonek -110
+KPX Ydieresis Aring -110
+KPX Ydieresis Atilde -110
+KPX Ydieresis O -35
+KPX Ydieresis Oacute -35
+KPX Ydieresis Ocircumflex -35
+KPX Ydieresis Odieresis -35
+KPX Ydieresis Ograve -35
+KPX Ydieresis Ohungarumlaut -35
+KPX Ydieresis Omacron -35
+KPX Ydieresis Oslash -35
+KPX Ydieresis Otilde -35
+KPX Ydieresis a -85
+KPX Ydieresis aacute -85
+KPX Ydieresis abreve -85
+KPX Ydieresis acircumflex -85
+KPX Ydieresis adieresis -85
+KPX Ydieresis agrave -85
+KPX Ydieresis amacron -85
+KPX Ydieresis aogonek -85
+KPX Ydieresis aring -85
+KPX Ydieresis atilde -85
+KPX Ydieresis colon -92
+KPX Ydieresis comma -92
+KPX Ydieresis e -111
+KPX Ydieresis eacute -111
+KPX Ydieresis ecaron -111
+KPX Ydieresis ecircumflex -111
+KPX Ydieresis edieresis -71
+KPX Ydieresis edotaccent -111
+KPX Ydieresis egrave -71
+KPX Ydieresis emacron -71
+KPX Ydieresis eogonek -111
+KPX Ydieresis hyphen -92
+KPX Ydieresis i -37
+KPX Ydieresis iacute -37
+KPX Ydieresis iogonek -37
+KPX Ydieresis o -111
+KPX Ydieresis oacute -111
+KPX Ydieresis ocircumflex -111
+KPX Ydieresis odieresis -111
+KPX Ydieresis ograve -111
+KPX Ydieresis ohungarumlaut -111
+KPX Ydieresis omacron -111
+KPX Ydieresis oslash -111
+KPX Ydieresis otilde -111
+KPX Ydieresis period -92
+KPX Ydieresis semicolon -92
+KPX Ydieresis u -92
+KPX Ydieresis uacute -92
+KPX Ydieresis ucircumflex -92
+KPX Ydieresis udieresis -92
+KPX Ydieresis ugrave -92
+KPX Ydieresis uhungarumlaut -92
+KPX Ydieresis umacron -92
+KPX Ydieresis uogonek -92
+KPX Ydieresis uring -92
+KPX a v -25
+KPX aacute v -25
+KPX abreve v -25
+KPX acircumflex v -25
+KPX adieresis v -25
+KPX agrave v -25
+KPX amacron v -25
+KPX aogonek v -25
+KPX aring v -25
+KPX atilde v -25
+KPX b b -10
+KPX b period -40
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX b v -15
+KPX comma quotedblright -45
+KPX comma quoteright -55
+KPX d w -15
+KPX dcroat w -15
+KPX e v -15
+KPX eacute v -15
+KPX ecaron v -15
+KPX ecircumflex v -15
+KPX edieresis v -15
+KPX edotaccent v -15
+KPX egrave v -15
+KPX emacron v -15
+KPX eogonek v -15
+KPX f comma -15
+KPX f dotlessi -35
+KPX f i -25
+KPX f o -25
+KPX f oacute -25
+KPX f ocircumflex -25
+KPX f odieresis -25
+KPX f ograve -25
+KPX f ohungarumlaut -25
+KPX f omacron -25
+KPX f oslash -25
+KPX f otilde -25
+KPX f period -15
+KPX f quotedblright 50
+KPX f quoteright 55
+KPX g period -15
+KPX gbreve period -15
+KPX gcommaaccent period -15
+KPX h y -15
+KPX h yacute -15
+KPX h ydieresis -15
+KPX i v -10
+KPX iacute v -10
+KPX icircumflex v -10
+KPX idieresis v -10
+KPX igrave v -10
+KPX imacron v -10
+KPX iogonek v -10
+KPX k e -10
+KPX k eacute -10
+KPX k ecaron -10
+KPX k ecircumflex -10
+KPX k edieresis -10
+KPX k edotaccent -10
+KPX k egrave -10
+KPX k emacron -10
+KPX k eogonek -10
+KPX k o -15
+KPX k oacute -15
+KPX k ocircumflex -15
+KPX k odieresis -15
+KPX k ograve -15
+KPX k ohungarumlaut -15
+KPX k omacron -15
+KPX k oslash -15
+KPX k otilde -15
+KPX k y -15
+KPX k yacute -15
+KPX k ydieresis -15
+KPX kcommaaccent e -10
+KPX kcommaaccent eacute -10
+KPX kcommaaccent ecaron -10
+KPX kcommaaccent ecircumflex -10
+KPX kcommaaccent edieresis -10
+KPX kcommaaccent edotaccent -10
+KPX kcommaaccent egrave -10
+KPX kcommaaccent emacron -10
+KPX kcommaaccent eogonek -10
+KPX kcommaaccent o -15
+KPX kcommaaccent oacute -15
+KPX kcommaaccent ocircumflex -15
+KPX kcommaaccent odieresis -15
+KPX kcommaaccent ograve -15
+KPX kcommaaccent ohungarumlaut -15
+KPX kcommaaccent omacron -15
+KPX kcommaaccent oslash -15
+KPX kcommaaccent otilde -15
+KPX kcommaaccent y -15
+KPX kcommaaccent yacute -15
+KPX kcommaaccent ydieresis -15
+KPX n v -40
+KPX nacute v -40
+KPX ncaron v -40
+KPX ncommaaccent v -40
+KPX ntilde v -40
+KPX o v -10
+KPX o w -10
+KPX oacute v -10
+KPX oacute w -10
+KPX ocircumflex v -10
+KPX ocircumflex w -10
+KPX odieresis v -10
+KPX odieresis w -10
+KPX ograve v -10
+KPX ograve w -10
+KPX ohungarumlaut v -10
+KPX ohungarumlaut w -10
+KPX omacron v -10
+KPX omacron w -10
+KPX oslash v -10
+KPX oslash w -10
+KPX otilde v -10
+KPX otilde w -10
+KPX period quotedblright -55
+KPX period quoteright -55
+KPX quotedblleft A -10
+KPX quotedblleft Aacute -10
+KPX quotedblleft Abreve -10
+KPX quotedblleft Acircumflex -10
+KPX quotedblleft Adieresis -10
+KPX quotedblleft Agrave -10
+KPX quotedblleft Amacron -10
+KPX quotedblleft Aogonek -10
+KPX quotedblleft Aring -10
+KPX quotedblleft Atilde -10
+KPX quoteleft A -10
+KPX quoteleft Aacute -10
+KPX quoteleft Abreve -10
+KPX quoteleft Acircumflex -10
+KPX quoteleft Adieresis -10
+KPX quoteleft Agrave -10
+KPX quoteleft Amacron -10
+KPX quoteleft Aogonek -10
+KPX quoteleft Aring -10
+KPX quoteleft Atilde -10
+KPX quoteleft quoteleft -63
+KPX quoteright d -20
+KPX quoteright dcroat -20
+KPX quoteright quoteright -63
+KPX quoteright r -20
+KPX quoteright racute -20
+KPX quoteright rcaron -20
+KPX quoteright rcommaaccent -20
+KPX quoteright s -37
+KPX quoteright sacute -37
+KPX quoteright scaron -37
+KPX quoteright scedilla -37
+KPX quoteright scommaaccent -37
+KPX quoteright space -74
+KPX quoteright v -20
+KPX r c -18
+KPX r cacute -18
+KPX r ccaron -18
+KPX r ccedilla -18
+KPX r comma -92
+KPX r e -18
+KPX r eacute -18
+KPX r ecaron -18
+KPX r ecircumflex -18
+KPX r edieresis -18
+KPX r edotaccent -18
+KPX r egrave -18
+KPX r emacron -18
+KPX r eogonek -18
+KPX r g -10
+KPX r gbreve -10
+KPX r gcommaaccent -10
+KPX r hyphen -37
+KPX r n -15
+KPX r nacute -15
+KPX r ncaron -15
+KPX r ncommaaccent -15
+KPX r ntilde -15
+KPX r o -18
+KPX r oacute -18
+KPX r ocircumflex -18
+KPX r odieresis -18
+KPX r ograve -18
+KPX r ohungarumlaut -18
+KPX r omacron -18
+KPX r oslash -18
+KPX r otilde -18
+KPX r p -10
+KPX r period -100
+KPX r q -18
+KPX r v -10
+KPX racute c -18
+KPX racute cacute -18
+KPX racute ccaron -18
+KPX racute ccedilla -18
+KPX racute comma -92
+KPX racute e -18
+KPX racute eacute -18
+KPX racute ecaron -18
+KPX racute ecircumflex -18
+KPX racute edieresis -18
+KPX racute edotaccent -18
+KPX racute egrave -18
+KPX racute emacron -18
+KPX racute eogonek -18
+KPX racute g -10
+KPX racute gbreve -10
+KPX racute gcommaaccent -10
+KPX racute hyphen -37
+KPX racute n -15
+KPX racute nacute -15
+KPX racute ncaron -15
+KPX racute ncommaaccent -15
+KPX racute ntilde -15
+KPX racute o -18
+KPX racute oacute -18
+KPX racute ocircumflex -18
+KPX racute odieresis -18
+KPX racute ograve -18
+KPX racute ohungarumlaut -18
+KPX racute omacron -18
+KPX racute oslash -18
+KPX racute otilde -18
+KPX racute p -10
+KPX racute period -100
+KPX racute q -18
+KPX racute v -10
+KPX rcaron c -18
+KPX rcaron cacute -18
+KPX rcaron ccaron -18
+KPX rcaron ccedilla -18
+KPX rcaron comma -92
+KPX rcaron e -18
+KPX rcaron eacute -18
+KPX rcaron ecaron -18
+KPX rcaron ecircumflex -18
+KPX rcaron edieresis -18
+KPX rcaron edotaccent -18
+KPX rcaron egrave -18
+KPX rcaron emacron -18
+KPX rcaron eogonek -18
+KPX rcaron g -10
+KPX rcaron gbreve -10
+KPX rcaron gcommaaccent -10
+KPX rcaron hyphen -37
+KPX rcaron n -15
+KPX rcaron nacute -15
+KPX rcaron ncaron -15
+KPX rcaron ncommaaccent -15
+KPX rcaron ntilde -15
+KPX rcaron o -18
+KPX rcaron oacute -18
+KPX rcaron ocircumflex -18
+KPX rcaron odieresis -18
+KPX rcaron ograve -18
+KPX rcaron ohungarumlaut -18
+KPX rcaron omacron -18
+KPX rcaron oslash -18
+KPX rcaron otilde -18
+KPX rcaron p -10
+KPX rcaron period -100
+KPX rcaron q -18
+KPX rcaron v -10
+KPX rcommaaccent c -18
+KPX rcommaaccent cacute -18
+KPX rcommaaccent ccaron -18
+KPX rcommaaccent ccedilla -18
+KPX rcommaaccent comma -92
+KPX rcommaaccent e -18
+KPX rcommaaccent eacute -18
+KPX rcommaaccent ecaron -18
+KPX rcommaaccent ecircumflex -18
+KPX rcommaaccent edieresis -18
+KPX rcommaaccent edotaccent -18
+KPX rcommaaccent egrave -18
+KPX rcommaaccent emacron -18
+KPX rcommaaccent eogonek -18
+KPX rcommaaccent g -10
+KPX rcommaaccent gbreve -10
+KPX rcommaaccent gcommaaccent -10
+KPX rcommaaccent hyphen -37
+KPX rcommaaccent n -15
+KPX rcommaaccent nacute -15
+KPX rcommaaccent ncaron -15
+KPX rcommaaccent ncommaaccent -15
+KPX rcommaaccent ntilde -15
+KPX rcommaaccent o -18
+KPX rcommaaccent oacute -18
+KPX rcommaaccent ocircumflex -18
+KPX rcommaaccent odieresis -18
+KPX rcommaaccent ograve -18
+KPX rcommaaccent ohungarumlaut -18
+KPX rcommaaccent omacron -18
+KPX rcommaaccent oslash -18
+KPX rcommaaccent otilde -18
+KPX rcommaaccent p -10
+KPX rcommaaccent period -100
+KPX rcommaaccent q -18
+KPX rcommaaccent v -10
+KPX space A -55
+KPX space Aacute -55
+KPX space Abreve -55
+KPX space Acircumflex -55
+KPX space Adieresis -55
+KPX space Agrave -55
+KPX space Amacron -55
+KPX space Aogonek -55
+KPX space Aring -55
+KPX space Atilde -55
+KPX space T -30
+KPX space Tcaron -30
+KPX space Tcommaaccent -30
+KPX space V -45
+KPX space W -30
+KPX space Y -55
+KPX space Yacute -55
+KPX space Ydieresis -55
+KPX v a -10
+KPX v aacute -10
+KPX v abreve -10
+KPX v acircumflex -10
+KPX v adieresis -10
+KPX v agrave -10
+KPX v amacron -10
+KPX v aogonek -10
+KPX v aring -10
+KPX v atilde -10
+KPX v comma -55
+KPX v e -10
+KPX v eacute -10
+KPX v ecaron -10
+KPX v ecircumflex -10
+KPX v edieresis -10
+KPX v edotaccent -10
+KPX v egrave -10
+KPX v emacron -10
+KPX v eogonek -10
+KPX v o -10
+KPX v oacute -10
+KPX v ocircumflex -10
+KPX v odieresis -10
+KPX v ograve -10
+KPX v ohungarumlaut -10
+KPX v omacron -10
+KPX v oslash -10
+KPX v otilde -10
+KPX v period -70
+KPX w comma -55
+KPX w o -10
+KPX w oacute -10
+KPX w ocircumflex -10
+KPX w odieresis -10
+KPX w ograve -10
+KPX w ohungarumlaut -10
+KPX w omacron -10
+KPX w oslash -10
+KPX w otilde -10
+KPX w period -70
+KPX y comma -55
+KPX y e -10
+KPX y eacute -10
+KPX y ecaron -10
+KPX y ecircumflex -10
+KPX y edieresis -10
+KPX y edotaccent -10
+KPX y egrave -10
+KPX y emacron -10
+KPX y eogonek -10
+KPX y o -25
+KPX y oacute -25
+KPX y ocircumflex -25
+KPX y odieresis -25
+KPX y ograve -25
+KPX y ohungarumlaut -25
+KPX y omacron -25
+KPX y oslash -25
+KPX y otilde -25
+KPX y period -70
+KPX yacute comma -55
+KPX yacute e -10
+KPX yacute eacute -10
+KPX yacute ecaron -10
+KPX yacute ecircumflex -10
+KPX yacute edieresis -10
+KPX yacute edotaccent -10
+KPX yacute egrave -10
+KPX yacute emacron -10
+KPX yacute eogonek -10
+KPX yacute o -25
+KPX yacute oacute -25
+KPX yacute ocircumflex -25
+KPX yacute odieresis -25
+KPX yacute ograve -25
+KPX yacute ohungarumlaut -25
+KPX yacute omacron -25
+KPX yacute oslash -25
+KPX yacute otilde -25
+KPX yacute period -70
+KPX ydieresis comma -55
+KPX ydieresis e -10
+KPX ydieresis eacute -10
+KPX ydieresis ecaron -10
+KPX ydieresis ecircumflex -10
+KPX ydieresis edieresis -10
+KPX ydieresis edotaccent -10
+KPX ydieresis egrave -10
+KPX ydieresis emacron -10
+KPX ydieresis eogonek -10
+KPX ydieresis o -25
+KPX ydieresis oacute -25
+KPX ydieresis ocircumflex -25
+KPX ydieresis odieresis -25
+KPX ydieresis ograve -25
+KPX ydieresis ohungarumlaut -25
+KPX ydieresis omacron -25
+KPX ydieresis oslash -25
+KPX ydieresis otilde -25
+KPX ydieresis period -70
+EndKernPairs
+EndKernData
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Times-BoldItalic.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Times-BoldItalic.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Times-BoldItalic.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Times-BoldItalic.afm 2004-05-26 16:06:22.000000000 +0000
@@ -0,0 +1,2384 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu May 1 13:04:06 1997
+Comment UniqueID 43066
+Comment VMusage 45874 56899
+FontName Times-BoldItalic
+FullName Times Bold Italic
+FamilyName Times
+Weight Bold
+ItalicAngle -15
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -200 -218 996 921
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 669
+XHeight 462
+Ascender 683
+Descender -217
+StdHW 42
+StdVW 121
+StartCharMetrics 315
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 389 ; N exclam ; B 67 -13 370 684 ;
+C 34 ; WX 555 ; N quotedbl ; B 136 398 536 685 ;
+C 35 ; WX 500 ; N numbersign ; B -33 0 533 700 ;
+C 36 ; WX 500 ; N dollar ; B -20 -100 497 733 ;
+C 37 ; WX 833 ; N percent ; B 39 -10 793 692 ;
+C 38 ; WX 778 ; N ampersand ; B 5 -19 699 682 ;
+C 39 ; WX 333 ; N quoteright ; B 98 369 302 685 ;
+C 40 ; WX 333 ; N parenleft ; B 28 -179 344 685 ;
+C 41 ; WX 333 ; N parenright ; B -44 -179 271 685 ;
+C 42 ; WX 500 ; N asterisk ; B 65 249 456 685 ;
+C 43 ; WX 570 ; N plus ; B 33 0 537 506 ;
+C 44 ; WX 250 ; N comma ; B -60 -182 144 134 ;
+C 45 ; WX 333 ; N hyphen ; B 2 166 271 282 ;
+C 46 ; WX 250 ; N period ; B -9 -13 139 135 ;
+C 47 ; WX 278 ; N slash ; B -64 -18 342 685 ;
+C 48 ; WX 500 ; N zero ; B 17 -14 477 683 ;
+C 49 ; WX 500 ; N one ; B 5 0 419 683 ;
+C 50 ; WX 500 ; N two ; B -27 0 446 683 ;
+C 51 ; WX 500 ; N three ; B -15 -13 450 683 ;
+C 52 ; WX 500 ; N four ; B -15 0 503 683 ;
+C 53 ; WX 500 ; N five ; B -11 -13 487 669 ;
+C 54 ; WX 500 ; N six ; B 23 -15 509 679 ;
+C 55 ; WX 500 ; N seven ; B 52 0 525 669 ;
+C 56 ; WX 500 ; N eight ; B 3 -13 476 683 ;
+C 57 ; WX 500 ; N nine ; B -12 -10 475 683 ;
+C 58 ; WX 333 ; N colon ; B 23 -13 264 459 ;
+C 59 ; WX 333 ; N semicolon ; B -25 -183 264 459 ;
+C 60 ; WX 570 ; N less ; B 31 -8 539 514 ;
+C 61 ; WX 570 ; N equal ; B 33 107 537 399 ;
+C 62 ; WX 570 ; N greater ; B 31 -8 539 514 ;
+C 63 ; WX 500 ; N question ; B 79 -13 470 684 ;
+C 64 ; WX 832 ; N at ; B 63 -18 770 685 ;
+C 65 ; WX 667 ; N A ; B -67 0 593 683 ;
+C 66 ; WX 667 ; N B ; B -24 0 624 669 ;
+C 67 ; WX 667 ; N C ; B 32 -18 677 685 ;
+C 68 ; WX 722 ; N D ; B -46 0 685 669 ;
+C 69 ; WX 667 ; N E ; B -27 0 653 669 ;
+C 70 ; WX 667 ; N F ; B -13 0 660 669 ;
+C 71 ; WX 722 ; N G ; B 21 -18 706 685 ;
+C 72 ; WX 778 ; N H ; B -24 0 799 669 ;
+C 73 ; WX 389 ; N I ; B -32 0 406 669 ;
+C 74 ; WX 500 ; N J ; B -46 -99 524 669 ;
+C 75 ; WX 667 ; N K ; B -21 0 702 669 ;
+C 76 ; WX 611 ; N L ; B -22 0 590 669 ;
+C 77 ; WX 889 ; N M ; B -29 -12 917 669 ;
+C 78 ; WX 722 ; N N ; B -27 -15 748 669 ;
+C 79 ; WX 722 ; N O ; B 27 -18 691 685 ;
+C 80 ; WX 611 ; N P ; B -27 0 613 669 ;
+C 81 ; WX 722 ; N Q ; B 27 -208 691 685 ;
+C 82 ; WX 667 ; N R ; B -29 0 623 669 ;
+C 83 ; WX 556 ; N S ; B 2 -18 526 685 ;
+C 84 ; WX 611 ; N T ; B 50 0 650 669 ;
+C 85 ; WX 722 ; N U ; B 67 -18 744 669 ;
+C 86 ; WX 667 ; N V ; B 65 -18 715 669 ;
+C 87 ; WX 889 ; N W ; B 65 -18 940 669 ;
+C 88 ; WX 667 ; N X ; B -24 0 694 669 ;
+C 89 ; WX 611 ; N Y ; B 73 0 659 669 ;
+C 90 ; WX 611 ; N Z ; B -11 0 590 669 ;
+C 91 ; WX 333 ; N bracketleft ; B -37 -159 362 674 ;
+C 92 ; WX 278 ; N backslash ; B -1 -18 279 685 ;
+C 93 ; WX 333 ; N bracketright ; B -56 -157 343 674 ;
+C 94 ; WX 570 ; N asciicircum ; B 67 304 503 669 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 333 ; N quoteleft ; B 128 369 332 685 ;
+C 97 ; WX 500 ; N a ; B -21 -14 455 462 ;
+C 98 ; WX 500 ; N b ; B -14 -13 444 699 ;
+C 99 ; WX 444 ; N c ; B -5 -13 392 462 ;
+C 100 ; WX 500 ; N d ; B -21 -13 517 699 ;
+C 101 ; WX 444 ; N e ; B 5 -13 398 462 ;
+C 102 ; WX 333 ; N f ; B -169 -205 446 698 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B -52 -203 478 462 ;
+C 104 ; WX 556 ; N h ; B -13 -9 498 699 ;
+C 105 ; WX 278 ; N i ; B 2 -9 263 684 ;
+C 106 ; WX 278 ; N j ; B -189 -207 279 684 ;
+C 107 ; WX 500 ; N k ; B -23 -8 483 699 ;
+C 108 ; WX 278 ; N l ; B 2 -9 290 699 ;
+C 109 ; WX 778 ; N m ; B -14 -9 722 462 ;
+C 110 ; WX 556 ; N n ; B -6 -9 493 462 ;
+C 111 ; WX 500 ; N o ; B -3 -13 441 462 ;
+C 112 ; WX 500 ; N p ; B -120 -205 446 462 ;
+C 113 ; WX 500 ; N q ; B 1 -205 471 462 ;
+C 114 ; WX 389 ; N r ; B -21 0 389 462 ;
+C 115 ; WX 389 ; N s ; B -19 -13 333 462 ;
+C 116 ; WX 278 ; N t ; B -11 -9 281 594 ;
+C 117 ; WX 556 ; N u ; B 15 -9 492 462 ;
+C 118 ; WX 444 ; N v ; B 16 -13 401 462 ;
+C 119 ; WX 667 ; N w ; B 16 -13 614 462 ;
+C 120 ; WX 500 ; N x ; B -46 -13 469 462 ;
+C 121 ; WX 444 ; N y ; B -94 -205 392 462 ;
+C 122 ; WX 389 ; N z ; B -43 -78 368 449 ;
+C 123 ; WX 348 ; N braceleft ; B 5 -187 436 686 ;
+C 124 ; WX 220 ; N bar ; B 66 -218 154 782 ;
+C 125 ; WX 348 ; N braceright ; B -129 -187 302 686 ;
+C 126 ; WX 570 ; N asciitilde ; B 54 173 516 333 ;
+C 161 ; WX 389 ; N exclamdown ; B 19 -205 322 492 ;
+C 162 ; WX 500 ; N cent ; B 42 -143 439 576 ;
+C 163 ; WX 500 ; N sterling ; B -32 -12 510 683 ;
+C 164 ; WX 167 ; N fraction ; B -169 -14 324 683 ;
+C 165 ; WX 500 ; N yen ; B 33 0 628 669 ;
+C 166 ; WX 500 ; N florin ; B -87 -156 537 707 ;
+C 167 ; WX 500 ; N section ; B 36 -143 459 685 ;
+C 168 ; WX 500 ; N currency ; B -26 34 526 586 ;
+C 169 ; WX 278 ; N quotesingle ; B 128 398 268 685 ;
+C 170 ; WX 500 ; N quotedblleft ; B 53 369 513 685 ;
+C 171 ; WX 500 ; N guillemotleft ; B 12 32 468 415 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 32 32 303 415 ;
+C 173 ; WX 333 ; N guilsinglright ; B 10 32 281 415 ;
+C 174 ; WX 556 ; N fi ; B -188 -205 514 703 ;
+C 175 ; WX 556 ; N fl ; B -186 -205 553 704 ;
+C 177 ; WX 500 ; N endash ; B -40 178 477 269 ;
+C 178 ; WX 500 ; N dagger ; B 91 -145 494 685 ;
+C 179 ; WX 500 ; N daggerdbl ; B 10 -139 493 685 ;
+C 180 ; WX 250 ; N periodcentered ; B 51 257 199 405 ;
+C 182 ; WX 500 ; N paragraph ; B -57 -193 562 669 ;
+C 183 ; WX 350 ; N bullet ; B 0 175 350 525 ;
+C 184 ; WX 333 ; N quotesinglbase ; B -5 -182 199 134 ;
+C 185 ; WX 500 ; N quotedblbase ; B -57 -182 403 134 ;
+C 186 ; WX 500 ; N quotedblright ; B 53 369 513 685 ;
+C 187 ; WX 500 ; N guillemotright ; B 12 32 468 415 ;
+C 188 ; WX 1000 ; N ellipsis ; B 40 -13 852 135 ;
+C 189 ; WX 1000 ; N perthousand ; B 7 -29 996 706 ;
+C 191 ; WX 500 ; N questiondown ; B 30 -205 421 492 ;
+C 193 ; WX 333 ; N grave ; B 85 516 297 697 ;
+C 194 ; WX 333 ; N acute ; B 139 516 379 697 ;
+C 195 ; WX 333 ; N circumflex ; B 40 516 367 690 ;
+C 196 ; WX 333 ; N tilde ; B 48 536 407 655 ;
+C 197 ; WX 333 ; N macron ; B 51 553 393 623 ;
+C 198 ; WX 333 ; N breve ; B 71 516 387 678 ;
+C 199 ; WX 333 ; N dotaccent ; B 163 550 298 684 ;
+C 200 ; WX 333 ; N dieresis ; B 55 550 402 684 ;
+C 202 ; WX 333 ; N ring ; B 127 516 340 729 ;
+C 203 ; WX 333 ; N cedilla ; B -80 -218 156 5 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 69 516 498 697 ;
+C 206 ; WX 333 ; N ogonek ; B 15 -183 244 34 ;
+C 207 ; WX 333 ; N caron ; B 79 516 411 690 ;
+C 208 ; WX 1000 ; N emdash ; B -40 178 977 269 ;
+C 225 ; WX 944 ; N AE ; B -64 0 918 669 ;
+C 227 ; WX 266 ; N ordfeminine ; B 16 399 330 685 ;
+C 232 ; WX 611 ; N Lslash ; B -22 0 590 669 ;
+C 233 ; WX 722 ; N Oslash ; B 27 -125 691 764 ;
+C 234 ; WX 944 ; N OE ; B 23 -8 946 677 ;
+C 235 ; WX 300 ; N ordmasculine ; B 56 400 347 685 ;
+C 241 ; WX 722 ; N ae ; B -5 -13 673 462 ;
+C 245 ; WX 278 ; N dotlessi ; B 2 -9 238 462 ;
+C 248 ; WX 278 ; N lslash ; B -7 -9 307 699 ;
+C 249 ; WX 500 ; N oslash ; B -3 -119 441 560 ;
+C 250 ; WX 722 ; N oe ; B 6 -13 674 462 ;
+C 251 ; WX 500 ; N germandbls ; B -200 -200 473 705 ;
+C -1 ; WX 389 ; N Idieresis ; B -32 0 450 862 ;
+C -1 ; WX 444 ; N eacute ; B 5 -13 435 697 ;
+C -1 ; WX 500 ; N abreve ; B -21 -14 471 678 ;
+C -1 ; WX 556 ; N uhungarumlaut ; B 15 -9 610 697 ;
+C -1 ; WX 444 ; N ecaron ; B 5 -13 467 690 ;
+C -1 ; WX 611 ; N Ydieresis ; B 73 0 659 862 ;
+C -1 ; WX 570 ; N divide ; B 33 -29 537 535 ;
+C -1 ; WX 611 ; N Yacute ; B 73 0 659 904 ;
+C -1 ; WX 667 ; N Acircumflex ; B -67 0 593 897 ;
+C -1 ; WX 500 ; N aacute ; B -21 -14 463 697 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 67 -18 744 897 ;
+C -1 ; WX 444 ; N yacute ; B -94 -205 435 697 ;
+C -1 ; WX 389 ; N scommaaccent ; B -19 -218 333 462 ;
+C -1 ; WX 444 ; N ecircumflex ; B 5 -13 423 690 ;
+C -1 ; WX 722 ; N Uring ; B 67 -18 744 921 ;
+C -1 ; WX 722 ; N Udieresis ; B 67 -18 744 862 ;
+C -1 ; WX 500 ; N aogonek ; B -21 -183 455 462 ;
+C -1 ; WX 722 ; N Uacute ; B 67 -18 744 904 ;
+C -1 ; WX 556 ; N uogonek ; B 15 -183 492 462 ;
+C -1 ; WX 667 ; N Edieresis ; B -27 0 653 862 ;
+C -1 ; WX 722 ; N Dcroat ; B -31 0 700 669 ;
+C -1 ; WX 250 ; N commaaccent ; B -36 -218 131 -50 ;
+C -1 ; WX 747 ; N copyright ; B 30 -18 718 685 ;
+C -1 ; WX 667 ; N Emacron ; B -27 0 653 830 ;
+C -1 ; WX 444 ; N ccaron ; B -5 -13 467 690 ;
+C -1 ; WX 500 ; N aring ; B -21 -14 455 729 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B -27 -218 748 669 ;
+C -1 ; WX 278 ; N lacute ; B 2 -9 392 904 ;
+C -1 ; WX 500 ; N agrave ; B -21 -14 455 697 ;
+C -1 ; WX 611 ; N Tcommaaccent ; B 50 -218 650 669 ;
+C -1 ; WX 667 ; N Cacute ; B 32 -18 677 904 ;
+C -1 ; WX 500 ; N atilde ; B -21 -14 491 655 ;
+C -1 ; WX 667 ; N Edotaccent ; B -27 0 653 862 ;
+C -1 ; WX 389 ; N scaron ; B -19 -13 424 690 ;
+C -1 ; WX 389 ; N scedilla ; B -19 -218 333 462 ;
+C -1 ; WX 278 ; N iacute ; B 2 -9 352 697 ;
+C -1 ; WX 494 ; N lozenge ; B 10 0 484 745 ;
+C -1 ; WX 667 ; N Rcaron ; B -29 0 623 897 ;
+C -1 ; WX 722 ; N Gcommaaccent ; B 21 -218 706 685 ;
+C -1 ; WX 556 ; N ucircumflex ; B 15 -9 492 690 ;
+C -1 ; WX 500 ; N acircumflex ; B -21 -14 455 690 ;
+C -1 ; WX 667 ; N Amacron ; B -67 0 593 830 ;
+C -1 ; WX 389 ; N rcaron ; B -21 0 424 690 ;
+C -1 ; WX 444 ; N ccedilla ; B -5 -218 392 462 ;
+C -1 ; WX 611 ; N Zdotaccent ; B -11 0 590 862 ;
+C -1 ; WX 611 ; N Thorn ; B -27 0 573 669 ;
+C -1 ; WX 722 ; N Omacron ; B 27 -18 691 830 ;
+C -1 ; WX 667 ; N Racute ; B -29 0 623 904 ;
+C -1 ; WX 556 ; N Sacute ; B 2 -18 531 904 ;
+C -1 ; WX 608 ; N dcaron ; B -21 -13 675 708 ;
+C -1 ; WX 722 ; N Umacron ; B 67 -18 744 830 ;
+C -1 ; WX 556 ; N uring ; B 15 -9 492 729 ;
+C -1 ; WX 300 ; N threesuperior ; B 17 265 321 683 ;
+C -1 ; WX 722 ; N Ograve ; B 27 -18 691 904 ;
+C -1 ; WX 667 ; N Agrave ; B -67 0 593 904 ;
+C -1 ; WX 667 ; N Abreve ; B -67 0 593 885 ;
+C -1 ; WX 570 ; N multiply ; B 48 16 522 490 ;
+C -1 ; WX 556 ; N uacute ; B 15 -9 492 697 ;
+C -1 ; WX 611 ; N Tcaron ; B 50 0 650 897 ;
+C -1 ; WX 494 ; N partialdiff ; B 11 -21 494 750 ;
+C -1 ; WX 444 ; N ydieresis ; B -94 -205 443 655 ;
+C -1 ; WX 722 ; N Nacute ; B -27 -15 748 904 ;
+C -1 ; WX 278 ; N icircumflex ; B -3 -9 324 690 ;
+C -1 ; WX 667 ; N Ecircumflex ; B -27 0 653 897 ;
+C -1 ; WX 500 ; N adieresis ; B -21 -14 476 655 ;
+C -1 ; WX 444 ; N edieresis ; B 5 -13 448 655 ;
+C -1 ; WX 444 ; N cacute ; B -5 -13 435 697 ;
+C -1 ; WX 556 ; N nacute ; B -6 -9 493 697 ;
+C -1 ; WX 556 ; N umacron ; B 15 -9 492 623 ;
+C -1 ; WX 722 ; N Ncaron ; B -27 -15 748 897 ;
+C -1 ; WX 389 ; N Iacute ; B -32 0 432 904 ;
+C -1 ; WX 570 ; N plusminus ; B 33 0 537 506 ;
+C -1 ; WX 220 ; N brokenbar ; B 66 -143 154 707 ;
+C -1 ; WX 747 ; N registered ; B 30 -18 718 685 ;
+C -1 ; WX 722 ; N Gbreve ; B 21 -18 706 885 ;
+C -1 ; WX 389 ; N Idotaccent ; B -32 0 406 862 ;
+C -1 ; WX 600 ; N summation ; B 14 -10 585 706 ;
+C -1 ; WX 667 ; N Egrave ; B -27 0 653 904 ;
+C -1 ; WX 389 ; N racute ; B -21 0 407 697 ;
+C -1 ; WX 500 ; N omacron ; B -3 -13 462 623 ;
+C -1 ; WX 611 ; N Zacute ; B -11 0 590 904 ;
+C -1 ; WX 611 ; N Zcaron ; B -11 0 590 897 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 523 704 ;
+C -1 ; WX 722 ; N Eth ; B -31 0 700 669 ;
+C -1 ; WX 667 ; N Ccedilla ; B 32 -218 677 685 ;
+C -1 ; WX 278 ; N lcommaaccent ; B -42 -218 290 699 ;
+C -1 ; WX 366 ; N tcaron ; B -11 -9 434 754 ;
+C -1 ; WX 444 ; N eogonek ; B 5 -183 398 462 ;
+C -1 ; WX 722 ; N Uogonek ; B 67 -183 744 669 ;
+C -1 ; WX 667 ; N Aacute ; B -67 0 593 904 ;
+C -1 ; WX 667 ; N Adieresis ; B -67 0 593 862 ;
+C -1 ; WX 444 ; N egrave ; B 5 -13 398 697 ;
+C -1 ; WX 389 ; N zacute ; B -43 -78 407 697 ;
+C -1 ; WX 278 ; N iogonek ; B -20 -183 263 684 ;
+C -1 ; WX 722 ; N Oacute ; B 27 -18 691 904 ;
+C -1 ; WX 500 ; N oacute ; B -3 -13 463 697 ;
+C -1 ; WX 500 ; N amacron ; B -21 -14 467 623 ;
+C -1 ; WX 389 ; N sacute ; B -19 -13 407 697 ;
+C -1 ; WX 278 ; N idieresis ; B 2 -9 364 655 ;
+C -1 ; WX 722 ; N Ocircumflex ; B 27 -18 691 897 ;
+C -1 ; WX 722 ; N Ugrave ; B 67 -18 744 904 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 500 ; N thorn ; B -120 -205 446 699 ;
+C -1 ; WX 300 ; N twosuperior ; B 2 274 313 683 ;
+C -1 ; WX 722 ; N Odieresis ; B 27 -18 691 862 ;
+C -1 ; WX 576 ; N mu ; B -60 -207 516 449 ;
+C -1 ; WX 278 ; N igrave ; B 2 -9 259 697 ;
+C -1 ; WX 500 ; N ohungarumlaut ; B -3 -13 582 697 ;
+C -1 ; WX 667 ; N Eogonek ; B -27 -183 653 669 ;
+C -1 ; WX 500 ; N dcroat ; B -21 -13 552 699 ;
+C -1 ; WX 750 ; N threequarters ; B 7 -14 726 683 ;
+C -1 ; WX 556 ; N Scedilla ; B 2 -218 526 685 ;
+C -1 ; WX 382 ; N lcaron ; B 2 -9 448 708 ;
+C -1 ; WX 667 ; N Kcommaaccent ; B -21 -218 702 669 ;
+C -1 ; WX 611 ; N Lacute ; B -22 0 590 904 ;
+C -1 ; WX 1000 ; N trademark ; B 32 263 968 669 ;
+C -1 ; WX 444 ; N edotaccent ; B 5 -13 398 655 ;
+C -1 ; WX 389 ; N Igrave ; B -32 0 406 904 ;
+C -1 ; WX 389 ; N Imacron ; B -32 0 461 830 ;
+C -1 ; WX 611 ; N Lcaron ; B -22 0 671 718 ;
+C -1 ; WX 750 ; N onehalf ; B -9 -14 723 683 ;
+C -1 ; WX 549 ; N lessequal ; B 29 0 526 704 ;
+C -1 ; WX 500 ; N ocircumflex ; B -3 -13 451 690 ;
+C -1 ; WX 556 ; N ntilde ; B -6 -9 504 655 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 67 -18 744 904 ;
+C -1 ; WX 667 ; N Eacute ; B -27 0 653 904 ;
+C -1 ; WX 444 ; N emacron ; B 5 -13 439 623 ;
+C -1 ; WX 500 ; N gbreve ; B -52 -203 478 678 ;
+C -1 ; WX 750 ; N onequarter ; B 7 -14 721 683 ;
+C -1 ; WX 556 ; N Scaron ; B 2 -18 553 897 ;
+C -1 ; WX 556 ; N Scommaaccent ; B 2 -218 526 685 ;
+C -1 ; WX 722 ; N Ohungarumlaut ; B 27 -18 723 904 ;
+C -1 ; WX 400 ; N degree ; B 83 397 369 683 ;
+C -1 ; WX 500 ; N ograve ; B -3 -13 441 697 ;
+C -1 ; WX 667 ; N Ccaron ; B 32 -18 677 897 ;
+C -1 ; WX 556 ; N ugrave ; B 15 -9 492 697 ;
+C -1 ; WX 549 ; N radical ; B 10 -46 512 850 ;
+C -1 ; WX 722 ; N Dcaron ; B -46 0 685 897 ;
+C -1 ; WX 389 ; N rcommaaccent ; B -67 -218 389 462 ;
+C -1 ; WX 722 ; N Ntilde ; B -27 -15 748 862 ;
+C -1 ; WX 500 ; N otilde ; B -3 -13 491 655 ;
+C -1 ; WX 667 ; N Rcommaaccent ; B -29 -218 623 669 ;
+C -1 ; WX 611 ; N Lcommaaccent ; B -22 -218 590 669 ;
+C -1 ; WX 667 ; N Atilde ; B -67 0 593 862 ;
+C -1 ; WX 667 ; N Aogonek ; B -67 -183 604 683 ;
+C -1 ; WX 667 ; N Aring ; B -67 0 593 921 ;
+C -1 ; WX 722 ; N Otilde ; B 27 -18 691 862 ;
+C -1 ; WX 389 ; N zdotaccent ; B -43 -78 368 655 ;
+C -1 ; WX 667 ; N Ecaron ; B -27 0 653 897 ;
+C -1 ; WX 389 ; N Iogonek ; B -32 -183 406 669 ;
+C -1 ; WX 500 ; N kcommaaccent ; B -23 -218 483 699 ;
+C -1 ; WX 606 ; N minus ; B 51 209 555 297 ;
+C -1 ; WX 389 ; N Icircumflex ; B -32 0 450 897 ;
+C -1 ; WX 556 ; N ncaron ; B -6 -9 523 690 ;
+C -1 ; WX 278 ; N tcommaaccent ; B -62 -218 281 594 ;
+C -1 ; WX 606 ; N logicalnot ; B 51 108 555 399 ;
+C -1 ; WX 500 ; N odieresis ; B -3 -13 471 655 ;
+C -1 ; WX 556 ; N udieresis ; B 15 -9 499 655 ;
+C -1 ; WX 549 ; N notequal ; B 15 -49 540 570 ;
+C -1 ; WX 500 ; N gcommaaccent ; B -52 -203 478 767 ;
+C -1 ; WX 500 ; N eth ; B -3 -13 454 699 ;
+C -1 ; WX 389 ; N zcaron ; B -43 -78 424 690 ;
+C -1 ; WX 556 ; N ncommaaccent ; B -6 -218 493 462 ;
+C -1 ; WX 300 ; N onesuperior ; B 30 274 301 683 ;
+C -1 ; WX 278 ; N imacron ; B 2 -9 294 623 ;
+C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2038
+KPX A C -65
+KPX A Cacute -65
+KPX A Ccaron -65
+KPX A Ccedilla -65
+KPX A G -60
+KPX A Gbreve -60
+KPX A Gcommaaccent -60
+KPX A O -50
+KPX A Oacute -50
+KPX A Ocircumflex -50
+KPX A Odieresis -50
+KPX A Ograve -50
+KPX A Ohungarumlaut -50
+KPX A Omacron -50
+KPX A Oslash -50
+KPX A Otilde -50
+KPX A Q -55
+KPX A T -55
+KPX A Tcaron -55
+KPX A Tcommaaccent -55
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -95
+KPX A W -100
+KPX A Y -70
+KPX A Yacute -70
+KPX A Ydieresis -70
+KPX A quoteright -74
+KPX A u -30
+KPX A uacute -30
+KPX A ucircumflex -30
+KPX A udieresis -30
+KPX A ugrave -30
+KPX A uhungarumlaut -30
+KPX A umacron -30
+KPX A uogonek -30
+KPX A uring -30
+KPX A v -74
+KPX A w -74
+KPX A y -74
+KPX A yacute -74
+KPX A ydieresis -74
+KPX Aacute C -65
+KPX Aacute Cacute -65
+KPX Aacute Ccaron -65
+KPX Aacute Ccedilla -65
+KPX Aacute G -60
+KPX Aacute Gbreve -60
+KPX Aacute Gcommaaccent -60
+KPX Aacute O -50
+KPX Aacute Oacute -50
+KPX Aacute Ocircumflex -50
+KPX Aacute Odieresis -50
+KPX Aacute Ograve -50
+KPX Aacute Ohungarumlaut -50
+KPX Aacute Omacron -50
+KPX Aacute Oslash -50
+KPX Aacute Otilde -50
+KPX Aacute Q -55
+KPX Aacute T -55
+KPX Aacute Tcaron -55
+KPX Aacute Tcommaaccent -55
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -95
+KPX Aacute W -100
+KPX Aacute Y -70
+KPX Aacute Yacute -70
+KPX Aacute Ydieresis -70
+KPX Aacute quoteright -74
+KPX Aacute u -30
+KPX Aacute uacute -30
+KPX Aacute ucircumflex -30
+KPX Aacute udieresis -30
+KPX Aacute ugrave -30
+KPX Aacute uhungarumlaut -30
+KPX Aacute umacron -30
+KPX Aacute uogonek -30
+KPX Aacute uring -30
+KPX Aacute v -74
+KPX Aacute w -74
+KPX Aacute y -74
+KPX Aacute yacute -74
+KPX Aacute ydieresis -74
+KPX Abreve C -65
+KPX Abreve Cacute -65
+KPX Abreve Ccaron -65
+KPX Abreve Ccedilla -65
+KPX Abreve G -60
+KPX Abreve Gbreve -60
+KPX Abreve Gcommaaccent -60
+KPX Abreve O -50
+KPX Abreve Oacute -50
+KPX Abreve Ocircumflex -50
+KPX Abreve Odieresis -50
+KPX Abreve Ograve -50
+KPX Abreve Ohungarumlaut -50
+KPX Abreve Omacron -50
+KPX Abreve Oslash -50
+KPX Abreve Otilde -50
+KPX Abreve Q -55
+KPX Abreve T -55
+KPX Abreve Tcaron -55
+KPX Abreve Tcommaaccent -55
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -95
+KPX Abreve W -100
+KPX Abreve Y -70
+KPX Abreve Yacute -70
+KPX Abreve Ydieresis -70
+KPX Abreve quoteright -74
+KPX Abreve u -30
+KPX Abreve uacute -30
+KPX Abreve ucircumflex -30
+KPX Abreve udieresis -30
+KPX Abreve ugrave -30
+KPX Abreve uhungarumlaut -30
+KPX Abreve umacron -30
+KPX Abreve uogonek -30
+KPX Abreve uring -30
+KPX Abreve v -74
+KPX Abreve w -74
+KPX Abreve y -74
+KPX Abreve yacute -74
+KPX Abreve ydieresis -74
+KPX Acircumflex C -65
+KPX Acircumflex Cacute -65
+KPX Acircumflex Ccaron -65
+KPX Acircumflex Ccedilla -65
+KPX Acircumflex G -60
+KPX Acircumflex Gbreve -60
+KPX Acircumflex Gcommaaccent -60
+KPX Acircumflex O -50
+KPX Acircumflex Oacute -50
+KPX Acircumflex Ocircumflex -50
+KPX Acircumflex Odieresis -50
+KPX Acircumflex Ograve -50
+KPX Acircumflex Ohungarumlaut -50
+KPX Acircumflex Omacron -50
+KPX Acircumflex Oslash -50
+KPX Acircumflex Otilde -50
+KPX Acircumflex Q -55
+KPX Acircumflex T -55
+KPX Acircumflex Tcaron -55
+KPX Acircumflex Tcommaaccent -55
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -95
+KPX Acircumflex W -100
+KPX Acircumflex Y -70
+KPX Acircumflex Yacute -70
+KPX Acircumflex Ydieresis -70
+KPX Acircumflex quoteright -74
+KPX Acircumflex u -30
+KPX Acircumflex uacute -30
+KPX Acircumflex ucircumflex -30
+KPX Acircumflex udieresis -30
+KPX Acircumflex ugrave -30
+KPX Acircumflex uhungarumlaut -30
+KPX Acircumflex umacron -30
+KPX Acircumflex uogonek -30
+KPX Acircumflex uring -30
+KPX Acircumflex v -74
+KPX Acircumflex w -74
+KPX Acircumflex y -74
+KPX Acircumflex yacute -74
+KPX Acircumflex ydieresis -74
+KPX Adieresis C -65
+KPX Adieresis Cacute -65
+KPX Adieresis Ccaron -65
+KPX Adieresis Ccedilla -65
+KPX Adieresis G -60
+KPX Adieresis Gbreve -60
+KPX Adieresis Gcommaaccent -60
+KPX Adieresis O -50
+KPX Adieresis Oacute -50
+KPX Adieresis Ocircumflex -50
+KPX Adieresis Odieresis -50
+KPX Adieresis Ograve -50
+KPX Adieresis Ohungarumlaut -50
+KPX Adieresis Omacron -50
+KPX Adieresis Oslash -50
+KPX Adieresis Otilde -50
+KPX Adieresis Q -55
+KPX Adieresis T -55
+KPX Adieresis Tcaron -55
+KPX Adieresis Tcommaaccent -55
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -95
+KPX Adieresis W -100
+KPX Adieresis Y -70
+KPX Adieresis Yacute -70
+KPX Adieresis Ydieresis -70
+KPX Adieresis quoteright -74
+KPX Adieresis u -30
+KPX Adieresis uacute -30
+KPX Adieresis ucircumflex -30
+KPX Adieresis udieresis -30
+KPX Adieresis ugrave -30
+KPX Adieresis uhungarumlaut -30
+KPX Adieresis umacron -30
+KPX Adieresis uogonek -30
+KPX Adieresis uring -30
+KPX Adieresis v -74
+KPX Adieresis w -74
+KPX Adieresis y -74
+KPX Adieresis yacute -74
+KPX Adieresis ydieresis -74
+KPX Agrave C -65
+KPX Agrave Cacute -65
+KPX Agrave Ccaron -65
+KPX Agrave Ccedilla -65
+KPX Agrave G -60
+KPX Agrave Gbreve -60
+KPX Agrave Gcommaaccent -60
+KPX Agrave O -50
+KPX Agrave Oacute -50
+KPX Agrave Ocircumflex -50
+KPX Agrave Odieresis -50
+KPX Agrave Ograve -50
+KPX Agrave Ohungarumlaut -50
+KPX Agrave Omacron -50
+KPX Agrave Oslash -50
+KPX Agrave Otilde -50
+KPX Agrave Q -55
+KPX Agrave T -55
+KPX Agrave Tcaron -55
+KPX Agrave Tcommaaccent -55
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -95
+KPX Agrave W -100
+KPX Agrave Y -70
+KPX Agrave Yacute -70
+KPX Agrave Ydieresis -70
+KPX Agrave quoteright -74
+KPX Agrave u -30
+KPX Agrave uacute -30
+KPX Agrave ucircumflex -30
+KPX Agrave udieresis -30
+KPX Agrave ugrave -30
+KPX Agrave uhungarumlaut -30
+KPX Agrave umacron -30
+KPX Agrave uogonek -30
+KPX Agrave uring -30
+KPX Agrave v -74
+KPX Agrave w -74
+KPX Agrave y -74
+KPX Agrave yacute -74
+KPX Agrave ydieresis -74
+KPX Amacron C -65
+KPX Amacron Cacute -65
+KPX Amacron Ccaron -65
+KPX Amacron Ccedilla -65
+KPX Amacron G -60
+KPX Amacron Gbreve -60
+KPX Amacron Gcommaaccent -60
+KPX Amacron O -50
+KPX Amacron Oacute -50
+KPX Amacron Ocircumflex -50
+KPX Amacron Odieresis -50
+KPX Amacron Ograve -50
+KPX Amacron Ohungarumlaut -50
+KPX Amacron Omacron -50
+KPX Amacron Oslash -50
+KPX Amacron Otilde -50
+KPX Amacron Q -55
+KPX Amacron T -55
+KPX Amacron Tcaron -55
+KPX Amacron Tcommaaccent -55
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -95
+KPX Amacron W -100
+KPX Amacron Y -70
+KPX Amacron Yacute -70
+KPX Amacron Ydieresis -70
+KPX Amacron quoteright -74
+KPX Amacron u -30
+KPX Amacron uacute -30
+KPX Amacron ucircumflex -30
+KPX Amacron udieresis -30
+KPX Amacron ugrave -30
+KPX Amacron uhungarumlaut -30
+KPX Amacron umacron -30
+KPX Amacron uogonek -30
+KPX Amacron uring -30
+KPX Amacron v -74
+KPX Amacron w -74
+KPX Amacron y -74
+KPX Amacron yacute -74
+KPX Amacron ydieresis -74
+KPX Aogonek C -65
+KPX Aogonek Cacute -65
+KPX Aogonek Ccaron -65
+KPX Aogonek Ccedilla -65
+KPX Aogonek G -60
+KPX Aogonek Gbreve -60
+KPX Aogonek Gcommaaccent -60
+KPX Aogonek O -50
+KPX Aogonek Oacute -50
+KPX Aogonek Ocircumflex -50
+KPX Aogonek Odieresis -50
+KPX Aogonek Ograve -50
+KPX Aogonek Ohungarumlaut -50
+KPX Aogonek Omacron -50
+KPX Aogonek Oslash -50
+KPX Aogonek Otilde -50
+KPX Aogonek Q -55
+KPX Aogonek T -55
+KPX Aogonek Tcaron -55
+KPX Aogonek Tcommaaccent -55
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -95
+KPX Aogonek W -100
+KPX Aogonek Y -70
+KPX Aogonek Yacute -70
+KPX Aogonek Ydieresis -70
+KPX Aogonek quoteright -74
+KPX Aogonek u -30
+KPX Aogonek uacute -30
+KPX Aogonek ucircumflex -30
+KPX Aogonek udieresis -30
+KPX Aogonek ugrave -30
+KPX Aogonek uhungarumlaut -30
+KPX Aogonek umacron -30
+KPX Aogonek uogonek -30
+KPX Aogonek uring -30
+KPX Aogonek v -74
+KPX Aogonek w -74
+KPX Aogonek y -34
+KPX Aogonek yacute -34
+KPX Aogonek ydieresis -34
+KPX Aring C -65
+KPX Aring Cacute -65
+KPX Aring Ccaron -65
+KPX Aring Ccedilla -65
+KPX Aring G -60
+KPX Aring Gbreve -60
+KPX Aring Gcommaaccent -60
+KPX Aring O -50
+KPX Aring Oacute -50
+KPX Aring Ocircumflex -50
+KPX Aring Odieresis -50
+KPX Aring Ograve -50
+KPX Aring Ohungarumlaut -50
+KPX Aring Omacron -50
+KPX Aring Oslash -50
+KPX Aring Otilde -50
+KPX Aring Q -55
+KPX Aring T -55
+KPX Aring Tcaron -55
+KPX Aring Tcommaaccent -55
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -95
+KPX Aring W -100
+KPX Aring Y -70
+KPX Aring Yacute -70
+KPX Aring Ydieresis -70
+KPX Aring quoteright -74
+KPX Aring u -30
+KPX Aring uacute -30
+KPX Aring ucircumflex -30
+KPX Aring udieresis -30
+KPX Aring ugrave -30
+KPX Aring uhungarumlaut -30
+KPX Aring umacron -30
+KPX Aring uogonek -30
+KPX Aring uring -30
+KPX Aring v -74
+KPX Aring w -74
+KPX Aring y -74
+KPX Aring yacute -74
+KPX Aring ydieresis -74
+KPX Atilde C -65
+KPX Atilde Cacute -65
+KPX Atilde Ccaron -65
+KPX Atilde Ccedilla -65
+KPX Atilde G -60
+KPX Atilde Gbreve -60
+KPX Atilde Gcommaaccent -60
+KPX Atilde O -50
+KPX Atilde Oacute -50
+KPX Atilde Ocircumflex -50
+KPX Atilde Odieresis -50
+KPX Atilde Ograve -50
+KPX Atilde Ohungarumlaut -50
+KPX Atilde Omacron -50
+KPX Atilde Oslash -50
+KPX Atilde Otilde -50
+KPX Atilde Q -55
+KPX Atilde T -55
+KPX Atilde Tcaron -55
+KPX Atilde Tcommaaccent -55
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -95
+KPX Atilde W -100
+KPX Atilde Y -70
+KPX Atilde Yacute -70
+KPX Atilde Ydieresis -70
+KPX Atilde quoteright -74
+KPX Atilde u -30
+KPX Atilde uacute -30
+KPX Atilde ucircumflex -30
+KPX Atilde udieresis -30
+KPX Atilde ugrave -30
+KPX Atilde uhungarumlaut -30
+KPX Atilde umacron -30
+KPX Atilde uogonek -30
+KPX Atilde uring -30
+KPX Atilde v -74
+KPX Atilde w -74
+KPX Atilde y -74
+KPX Atilde yacute -74
+KPX Atilde ydieresis -74
+KPX B A -25
+KPX B Aacute -25
+KPX B Abreve -25
+KPX B Acircumflex -25
+KPX B Adieresis -25
+KPX B Agrave -25
+KPX B Amacron -25
+KPX B Aogonek -25
+KPX B Aring -25
+KPX B Atilde -25
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX D A -25
+KPX D Aacute -25
+KPX D Abreve -25
+KPX D Acircumflex -25
+KPX D Adieresis -25
+KPX D Agrave -25
+KPX D Amacron -25
+KPX D Aogonek -25
+KPX D Aring -25
+KPX D Atilde -25
+KPX D V -50
+KPX D W -40
+KPX D Y -50
+KPX D Yacute -50
+KPX D Ydieresis -50
+KPX Dcaron A -25
+KPX Dcaron Aacute -25
+KPX Dcaron Abreve -25
+KPX Dcaron Acircumflex -25
+KPX Dcaron Adieresis -25
+KPX Dcaron Agrave -25
+KPX Dcaron Amacron -25
+KPX Dcaron Aogonek -25
+KPX Dcaron Aring -25
+KPX Dcaron Atilde -25
+KPX Dcaron V -50
+KPX Dcaron W -40
+KPX Dcaron Y -50
+KPX Dcaron Yacute -50
+KPX Dcaron Ydieresis -50
+KPX Dcroat A -25
+KPX Dcroat Aacute -25
+KPX Dcroat Abreve -25
+KPX Dcroat Acircumflex -25
+KPX Dcroat Adieresis -25
+KPX Dcroat Agrave -25
+KPX Dcroat Amacron -25
+KPX Dcroat Aogonek -25
+KPX Dcroat Aring -25
+KPX Dcroat Atilde -25
+KPX Dcroat V -50
+KPX Dcroat W -40
+KPX Dcroat Y -50
+KPX Dcroat Yacute -50
+KPX Dcroat Ydieresis -50
+KPX F A -100
+KPX F Aacute -100
+KPX F Abreve -100
+KPX F Acircumflex -100
+KPX F Adieresis -100
+KPX F Agrave -100
+KPX F Amacron -100
+KPX F Aogonek -100
+KPX F Aring -100
+KPX F Atilde -100
+KPX F a -95
+KPX F aacute -95
+KPX F abreve -95
+KPX F acircumflex -95
+KPX F adieresis -95
+KPX F agrave -95
+KPX F amacron -95
+KPX F aogonek -95
+KPX F aring -95
+KPX F atilde -95
+KPX F comma -129
+KPX F e -100
+KPX F eacute -100
+KPX F ecaron -100
+KPX F ecircumflex -100
+KPX F edieresis -100
+KPX F edotaccent -100
+KPX F egrave -100
+KPX F emacron -100
+KPX F eogonek -100
+KPX F i -40
+KPX F iacute -40
+KPX F icircumflex -40
+KPX F idieresis -40
+KPX F igrave -40
+KPX F imacron -40
+KPX F iogonek -40
+KPX F o -70
+KPX F oacute -70
+KPX F ocircumflex -70
+KPX F odieresis -70
+KPX F ograve -70
+KPX F ohungarumlaut -70
+KPX F omacron -70
+KPX F oslash -70
+KPX F otilde -70
+KPX F period -129
+KPX F r -50
+KPX F racute -50
+KPX F rcaron -50
+KPX F rcommaaccent -50
+KPX J A -25
+KPX J Aacute -25
+KPX J Abreve -25
+KPX J Acircumflex -25
+KPX J Adieresis -25
+KPX J Agrave -25
+KPX J Amacron -25
+KPX J Aogonek -25
+KPX J Aring -25
+KPX J Atilde -25
+KPX J a -40
+KPX J aacute -40
+KPX J abreve -40
+KPX J acircumflex -40
+KPX J adieresis -40
+KPX J agrave -40
+KPX J amacron -40
+KPX J aogonek -40
+KPX J aring -40
+KPX J atilde -40
+KPX J comma -10
+KPX J e -40
+KPX J eacute -40
+KPX J ecaron -40
+KPX J ecircumflex -40
+KPX J edieresis -40
+KPX J edotaccent -40
+KPX J egrave -40
+KPX J emacron -40
+KPX J eogonek -40
+KPX J o -40
+KPX J oacute -40
+KPX J ocircumflex -40
+KPX J odieresis -40
+KPX J ograve -40
+KPX J ohungarumlaut -40
+KPX J omacron -40
+KPX J oslash -40
+KPX J otilde -40
+KPX J period -10
+KPX J u -40
+KPX J uacute -40
+KPX J ucircumflex -40
+KPX J udieresis -40
+KPX J ugrave -40
+KPX J uhungarumlaut -40
+KPX J umacron -40
+KPX J uogonek -40
+KPX J uring -40
+KPX K O -30
+KPX K Oacute -30
+KPX K Ocircumflex -30
+KPX K Odieresis -30
+KPX K Ograve -30
+KPX K Ohungarumlaut -30
+KPX K Omacron -30
+KPX K Oslash -30
+KPX K Otilde -30
+KPX K e -25
+KPX K eacute -25
+KPX K ecaron -25
+KPX K ecircumflex -25
+KPX K edieresis -25
+KPX K edotaccent -25
+KPX K egrave -25
+KPX K emacron -25
+KPX K eogonek -25
+KPX K o -25
+KPX K oacute -25
+KPX K ocircumflex -25
+KPX K odieresis -25
+KPX K ograve -25
+KPX K ohungarumlaut -25
+KPX K omacron -25
+KPX K oslash -25
+KPX K otilde -25
+KPX K u -20
+KPX K uacute -20
+KPX K ucircumflex -20
+KPX K udieresis -20
+KPX K ugrave -20
+KPX K uhungarumlaut -20
+KPX K umacron -20
+KPX K uogonek -20
+KPX K uring -20
+KPX K y -20
+KPX K yacute -20
+KPX K ydieresis -20
+KPX Kcommaaccent O -30
+KPX Kcommaaccent Oacute -30
+KPX Kcommaaccent Ocircumflex -30
+KPX Kcommaaccent Odieresis -30
+KPX Kcommaaccent Ograve -30
+KPX Kcommaaccent Ohungarumlaut -30
+KPX Kcommaaccent Omacron -30
+KPX Kcommaaccent Oslash -30
+KPX Kcommaaccent Otilde -30
+KPX Kcommaaccent e -25
+KPX Kcommaaccent eacute -25
+KPX Kcommaaccent ecaron -25
+KPX Kcommaaccent ecircumflex -25
+KPX Kcommaaccent edieresis -25
+KPX Kcommaaccent edotaccent -25
+KPX Kcommaaccent egrave -25
+KPX Kcommaaccent emacron -25
+KPX Kcommaaccent eogonek -25
+KPX Kcommaaccent o -25
+KPX Kcommaaccent oacute -25
+KPX Kcommaaccent ocircumflex -25
+KPX Kcommaaccent odieresis -25
+KPX Kcommaaccent ograve -25
+KPX Kcommaaccent ohungarumlaut -25
+KPX Kcommaaccent omacron -25
+KPX Kcommaaccent oslash -25
+KPX Kcommaaccent otilde -25
+KPX Kcommaaccent u -20
+KPX Kcommaaccent uacute -20
+KPX Kcommaaccent ucircumflex -20
+KPX Kcommaaccent udieresis -20
+KPX Kcommaaccent ugrave -20
+KPX Kcommaaccent uhungarumlaut -20
+KPX Kcommaaccent umacron -20
+KPX Kcommaaccent uogonek -20
+KPX Kcommaaccent uring -20
+KPX Kcommaaccent y -20
+KPX Kcommaaccent yacute -20
+KPX Kcommaaccent ydieresis -20
+KPX L T -18
+KPX L Tcaron -18
+KPX L Tcommaaccent -18
+KPX L V -37
+KPX L W -37
+KPX L Y -37
+KPX L Yacute -37
+KPX L Ydieresis -37
+KPX L quoteright -55
+KPX L y -37
+KPX L yacute -37
+KPX L ydieresis -37
+KPX Lacute T -18
+KPX Lacute Tcaron -18
+KPX Lacute Tcommaaccent -18
+KPX Lacute V -37
+KPX Lacute W -37
+KPX Lacute Y -37
+KPX Lacute Yacute -37
+KPX Lacute Ydieresis -37
+KPX Lacute quoteright -55
+KPX Lacute y -37
+KPX Lacute yacute -37
+KPX Lacute ydieresis -37
+KPX Lcommaaccent T -18
+KPX Lcommaaccent Tcaron -18
+KPX Lcommaaccent Tcommaaccent -18
+KPX Lcommaaccent V -37
+KPX Lcommaaccent W -37
+KPX Lcommaaccent Y -37
+KPX Lcommaaccent Yacute -37
+KPX Lcommaaccent Ydieresis -37
+KPX Lcommaaccent quoteright -55
+KPX Lcommaaccent y -37
+KPX Lcommaaccent yacute -37
+KPX Lcommaaccent ydieresis -37
+KPX Lslash T -18
+KPX Lslash Tcaron -18
+KPX Lslash Tcommaaccent -18
+KPX Lslash V -37
+KPX Lslash W -37
+KPX Lslash Y -37
+KPX Lslash Yacute -37
+KPX Lslash Ydieresis -37
+KPX Lslash quoteright -55
+KPX Lslash y -37
+KPX Lslash yacute -37
+KPX Lslash ydieresis -37
+KPX N A -30
+KPX N Aacute -30
+KPX N Abreve -30
+KPX N Acircumflex -30
+KPX N Adieresis -30
+KPX N Agrave -30
+KPX N Amacron -30
+KPX N Aogonek -30
+KPX N Aring -30
+KPX N Atilde -30
+KPX Nacute A -30
+KPX Nacute Aacute -30
+KPX Nacute Abreve -30
+KPX Nacute Acircumflex -30
+KPX Nacute Adieresis -30
+KPX Nacute Agrave -30
+KPX Nacute Amacron -30
+KPX Nacute Aogonek -30
+KPX Nacute Aring -30
+KPX Nacute Atilde -30
+KPX Ncaron A -30
+KPX Ncaron Aacute -30
+KPX Ncaron Abreve -30
+KPX Ncaron Acircumflex -30
+KPX Ncaron Adieresis -30
+KPX Ncaron Agrave -30
+KPX Ncaron Amacron -30
+KPX Ncaron Aogonek -30
+KPX Ncaron Aring -30
+KPX Ncaron Atilde -30
+KPX Ncommaaccent A -30
+KPX Ncommaaccent Aacute -30
+KPX Ncommaaccent Abreve -30
+KPX Ncommaaccent Acircumflex -30
+KPX Ncommaaccent Adieresis -30
+KPX Ncommaaccent Agrave -30
+KPX Ncommaaccent Amacron -30
+KPX Ncommaaccent Aogonek -30
+KPX Ncommaaccent Aring -30
+KPX Ncommaaccent Atilde -30
+KPX Ntilde A -30
+KPX Ntilde Aacute -30
+KPX Ntilde Abreve -30
+KPX Ntilde Acircumflex -30
+KPX Ntilde Adieresis -30
+KPX Ntilde Agrave -30
+KPX Ntilde Amacron -30
+KPX Ntilde Aogonek -30
+KPX Ntilde Aring -30
+KPX Ntilde Atilde -30
+KPX O A -40
+KPX O Aacute -40
+KPX O Abreve -40
+KPX O Acircumflex -40
+KPX O Adieresis -40
+KPX O Agrave -40
+KPX O Amacron -40
+KPX O Aogonek -40
+KPX O Aring -40
+KPX O Atilde -40
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -50
+KPX O X -40
+KPX O Y -50
+KPX O Yacute -50
+KPX O Ydieresis -50
+KPX Oacute A -40
+KPX Oacute Aacute -40
+KPX Oacute Abreve -40
+KPX Oacute Acircumflex -40
+KPX Oacute Adieresis -40
+KPX Oacute Agrave -40
+KPX Oacute Amacron -40
+KPX Oacute Aogonek -40
+KPX Oacute Aring -40
+KPX Oacute Atilde -40
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -50
+KPX Oacute X -40
+KPX Oacute Y -50
+KPX Oacute Yacute -50
+KPX Oacute Ydieresis -50
+KPX Ocircumflex A -40
+KPX Ocircumflex Aacute -40
+KPX Ocircumflex Abreve -40
+KPX Ocircumflex Acircumflex -40
+KPX Ocircumflex Adieresis -40
+KPX Ocircumflex Agrave -40
+KPX Ocircumflex Amacron -40
+KPX Ocircumflex Aogonek -40
+KPX Ocircumflex Aring -40
+KPX Ocircumflex Atilde -40
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -50
+KPX Ocircumflex X -40
+KPX Ocircumflex Y -50
+KPX Ocircumflex Yacute -50
+KPX Ocircumflex Ydieresis -50
+KPX Odieresis A -40
+KPX Odieresis Aacute -40
+KPX Odieresis Abreve -40
+KPX Odieresis Acircumflex -40
+KPX Odieresis Adieresis -40
+KPX Odieresis Agrave -40
+KPX Odieresis Amacron -40
+KPX Odieresis Aogonek -40
+KPX Odieresis Aring -40
+KPX Odieresis Atilde -40
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -50
+KPX Odieresis X -40
+KPX Odieresis Y -50
+KPX Odieresis Yacute -50
+KPX Odieresis Ydieresis -50
+KPX Ograve A -40
+KPX Ograve Aacute -40
+KPX Ograve Abreve -40
+KPX Ograve Acircumflex -40
+KPX Ograve Adieresis -40
+KPX Ograve Agrave -40
+KPX Ograve Amacron -40
+KPX Ograve Aogonek -40
+KPX Ograve Aring -40
+KPX Ograve Atilde -40
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -50
+KPX Ograve X -40
+KPX Ograve Y -50
+KPX Ograve Yacute -50
+KPX Ograve Ydieresis -50
+KPX Ohungarumlaut A -40
+KPX Ohungarumlaut Aacute -40
+KPX Ohungarumlaut Abreve -40
+KPX Ohungarumlaut Acircumflex -40
+KPX Ohungarumlaut Adieresis -40
+KPX Ohungarumlaut Agrave -40
+KPX Ohungarumlaut Amacron -40
+KPX Ohungarumlaut Aogonek -40
+KPX Ohungarumlaut Aring -40
+KPX Ohungarumlaut Atilde -40
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -50
+KPX Ohungarumlaut X -40
+KPX Ohungarumlaut Y -50
+KPX Ohungarumlaut Yacute -50
+KPX Ohungarumlaut Ydieresis -50
+KPX Omacron A -40
+KPX Omacron Aacute -40
+KPX Omacron Abreve -40
+KPX Omacron Acircumflex -40
+KPX Omacron Adieresis -40
+KPX Omacron Agrave -40
+KPX Omacron Amacron -40
+KPX Omacron Aogonek -40
+KPX Omacron Aring -40
+KPX Omacron Atilde -40
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -50
+KPX Omacron X -40
+KPX Omacron Y -50
+KPX Omacron Yacute -50
+KPX Omacron Ydieresis -50
+KPX Oslash A -40
+KPX Oslash Aacute -40
+KPX Oslash Abreve -40
+KPX Oslash Acircumflex -40
+KPX Oslash Adieresis -40
+KPX Oslash Agrave -40
+KPX Oslash Amacron -40
+KPX Oslash Aogonek -40
+KPX Oslash Aring -40
+KPX Oslash Atilde -40
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -50
+KPX Oslash X -40
+KPX Oslash Y -50
+KPX Oslash Yacute -50
+KPX Oslash Ydieresis -50
+KPX Otilde A -40
+KPX Otilde Aacute -40
+KPX Otilde Abreve -40
+KPX Otilde Acircumflex -40
+KPX Otilde Adieresis -40
+KPX Otilde Agrave -40
+KPX Otilde Amacron -40
+KPX Otilde Aogonek -40
+KPX Otilde Aring -40
+KPX Otilde Atilde -40
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -50
+KPX Otilde X -40
+KPX Otilde Y -50
+KPX Otilde Yacute -50
+KPX Otilde Ydieresis -50
+KPX P A -85
+KPX P Aacute -85
+KPX P Abreve -85
+KPX P Acircumflex -85
+KPX P Adieresis -85
+KPX P Agrave -85
+KPX P Amacron -85
+KPX P Aogonek -85
+KPX P Aring -85
+KPX P Atilde -85
+KPX P a -40
+KPX P aacute -40
+KPX P abreve -40
+KPX P acircumflex -40
+KPX P adieresis -40
+KPX P agrave -40
+KPX P amacron -40
+KPX P aogonek -40
+KPX P aring -40
+KPX P atilde -40
+KPX P comma -129
+KPX P e -50
+KPX P eacute -50
+KPX P ecaron -50
+KPX P ecircumflex -50
+KPX P edieresis -50
+KPX P edotaccent -50
+KPX P egrave -50
+KPX P emacron -50
+KPX P eogonek -50
+KPX P o -55
+KPX P oacute -55
+KPX P ocircumflex -55
+KPX P odieresis -55
+KPX P ograve -55
+KPX P ohungarumlaut -55
+KPX P omacron -55
+KPX P oslash -55
+KPX P otilde -55
+KPX P period -129
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX R O -40
+KPX R Oacute -40
+KPX R Ocircumflex -40
+KPX R Odieresis -40
+KPX R Ograve -40
+KPX R Ohungarumlaut -40
+KPX R Omacron -40
+KPX R Oslash -40
+KPX R Otilde -40
+KPX R T -30
+KPX R Tcaron -30
+KPX R Tcommaaccent -30
+KPX R U -40
+KPX R Uacute -40
+KPX R Ucircumflex -40
+KPX R Udieresis -40
+KPX R Ugrave -40
+KPX R Uhungarumlaut -40
+KPX R Umacron -40
+KPX R Uogonek -40
+KPX R Uring -40
+KPX R V -18
+KPX R W -18
+KPX R Y -18
+KPX R Yacute -18
+KPX R Ydieresis -18
+KPX Racute O -40
+KPX Racute Oacute -40
+KPX Racute Ocircumflex -40
+KPX Racute Odieresis -40
+KPX Racute Ograve -40
+KPX Racute Ohungarumlaut -40
+KPX Racute Omacron -40
+KPX Racute Oslash -40
+KPX Racute Otilde -40
+KPX Racute T -30
+KPX Racute Tcaron -30
+KPX Racute Tcommaaccent -30
+KPX Racute U -40
+KPX Racute Uacute -40
+KPX Racute Ucircumflex -40
+KPX Racute Udieresis -40
+KPX Racute Ugrave -40
+KPX Racute Uhungarumlaut -40
+KPX Racute Umacron -40
+KPX Racute Uogonek -40
+KPX Racute Uring -40
+KPX Racute V -18
+KPX Racute W -18
+KPX Racute Y -18
+KPX Racute Yacute -18
+KPX Racute Ydieresis -18
+KPX Rcaron O -40
+KPX Rcaron Oacute -40
+KPX Rcaron Ocircumflex -40
+KPX Rcaron Odieresis -40
+KPX Rcaron Ograve -40
+KPX Rcaron Ohungarumlaut -40
+KPX Rcaron Omacron -40
+KPX Rcaron Oslash -40
+KPX Rcaron Otilde -40
+KPX Rcaron T -30
+KPX Rcaron Tcaron -30
+KPX Rcaron Tcommaaccent -30
+KPX Rcaron U -40
+KPX Rcaron Uacute -40
+KPX Rcaron Ucircumflex -40
+KPX Rcaron Udieresis -40
+KPX Rcaron Ugrave -40
+KPX Rcaron Uhungarumlaut -40
+KPX Rcaron Umacron -40
+KPX Rcaron Uogonek -40
+KPX Rcaron Uring -40
+KPX Rcaron V -18
+KPX Rcaron W -18
+KPX Rcaron Y -18
+KPX Rcaron Yacute -18
+KPX Rcaron Ydieresis -18
+KPX Rcommaaccent O -40
+KPX Rcommaaccent Oacute -40
+KPX Rcommaaccent Ocircumflex -40
+KPX Rcommaaccent Odieresis -40
+KPX Rcommaaccent Ograve -40
+KPX Rcommaaccent Ohungarumlaut -40
+KPX Rcommaaccent Omacron -40
+KPX Rcommaaccent Oslash -40
+KPX Rcommaaccent Otilde -40
+KPX Rcommaaccent T -30
+KPX Rcommaaccent Tcaron -30
+KPX Rcommaaccent Tcommaaccent -30
+KPX Rcommaaccent U -40
+KPX Rcommaaccent Uacute -40
+KPX Rcommaaccent Ucircumflex -40
+KPX Rcommaaccent Udieresis -40
+KPX Rcommaaccent Ugrave -40
+KPX Rcommaaccent Uhungarumlaut -40
+KPX Rcommaaccent Umacron -40
+KPX Rcommaaccent Uogonek -40
+KPX Rcommaaccent Uring -40
+KPX Rcommaaccent V -18
+KPX Rcommaaccent W -18
+KPX Rcommaaccent Y -18
+KPX Rcommaaccent Yacute -18
+KPX Rcommaaccent Ydieresis -18
+KPX T A -55
+KPX T Aacute -55
+KPX T Abreve -55
+KPX T Acircumflex -55
+KPX T Adieresis -55
+KPX T Agrave -55
+KPX T Amacron -55
+KPX T Aogonek -55
+KPX T Aring -55
+KPX T Atilde -55
+KPX T O -18
+KPX T Oacute -18
+KPX T Ocircumflex -18
+KPX T Odieresis -18
+KPX T Ograve -18
+KPX T Ohungarumlaut -18
+KPX T Omacron -18
+KPX T Oslash -18
+KPX T Otilde -18
+KPX T a -92
+KPX T aacute -92
+KPX T abreve -92
+KPX T acircumflex -92
+KPX T adieresis -92
+KPX T agrave -92
+KPX T amacron -92
+KPX T aogonek -92
+KPX T aring -92
+KPX T atilde -92
+KPX T colon -74
+KPX T comma -92
+KPX T e -92
+KPX T eacute -92
+KPX T ecaron -92
+KPX T ecircumflex -92
+KPX T edieresis -52
+KPX T edotaccent -92
+KPX T egrave -52
+KPX T emacron -52
+KPX T eogonek -92
+KPX T hyphen -92
+KPX T i -37
+KPX T iacute -37
+KPX T iogonek -37
+KPX T o -95
+KPX T oacute -95
+KPX T ocircumflex -95
+KPX T odieresis -95
+KPX T ograve -95
+KPX T ohungarumlaut -95
+KPX T omacron -95
+KPX T oslash -95
+KPX T otilde -95
+KPX T period -92
+KPX T r -37
+KPX T racute -37
+KPX T rcaron -37
+KPX T rcommaaccent -37
+KPX T semicolon -74
+KPX T u -37
+KPX T uacute -37
+KPX T ucircumflex -37
+KPX T udieresis -37
+KPX T ugrave -37
+KPX T uhungarumlaut -37
+KPX T umacron -37
+KPX T uogonek -37
+KPX T uring -37
+KPX T w -37
+KPX T y -37
+KPX T yacute -37
+KPX T ydieresis -37
+KPX Tcaron A -55
+KPX Tcaron Aacute -55
+KPX Tcaron Abreve -55
+KPX Tcaron Acircumflex -55
+KPX Tcaron Adieresis -55
+KPX Tcaron Agrave -55
+KPX Tcaron Amacron -55
+KPX Tcaron Aogonek -55
+KPX Tcaron Aring -55
+KPX Tcaron Atilde -55
+KPX Tcaron O -18
+KPX Tcaron Oacute -18
+KPX Tcaron Ocircumflex -18
+KPX Tcaron Odieresis -18
+KPX Tcaron Ograve -18
+KPX Tcaron Ohungarumlaut -18
+KPX Tcaron Omacron -18
+KPX Tcaron Oslash -18
+KPX Tcaron Otilde -18
+KPX Tcaron a -92
+KPX Tcaron aacute -92
+KPX Tcaron abreve -92
+KPX Tcaron acircumflex -92
+KPX Tcaron adieresis -92
+KPX Tcaron agrave -92
+KPX Tcaron amacron -92
+KPX Tcaron aogonek -92
+KPX Tcaron aring -92
+KPX Tcaron atilde -92
+KPX Tcaron colon -74
+KPX Tcaron comma -92
+KPX Tcaron e -92
+KPX Tcaron eacute -92
+KPX Tcaron ecaron -92
+KPX Tcaron ecircumflex -92
+KPX Tcaron edieresis -52
+KPX Tcaron edotaccent -92
+KPX Tcaron egrave -52
+KPX Tcaron emacron -52
+KPX Tcaron eogonek -92
+KPX Tcaron hyphen -92
+KPX Tcaron i -37
+KPX Tcaron iacute -37
+KPX Tcaron iogonek -37
+KPX Tcaron o -95
+KPX Tcaron oacute -95
+KPX Tcaron ocircumflex -95
+KPX Tcaron odieresis -95
+KPX Tcaron ograve -95
+KPX Tcaron ohungarumlaut -95
+KPX Tcaron omacron -95
+KPX Tcaron oslash -95
+KPX Tcaron otilde -95
+KPX Tcaron period -92
+KPX Tcaron r -37
+KPX Tcaron racute -37
+KPX Tcaron rcaron -37
+KPX Tcaron rcommaaccent -37
+KPX Tcaron semicolon -74
+KPX Tcaron u -37
+KPX Tcaron uacute -37
+KPX Tcaron ucircumflex -37
+KPX Tcaron udieresis -37
+KPX Tcaron ugrave -37
+KPX Tcaron uhungarumlaut -37
+KPX Tcaron umacron -37
+KPX Tcaron uogonek -37
+KPX Tcaron uring -37
+KPX Tcaron w -37
+KPX Tcaron y -37
+KPX Tcaron yacute -37
+KPX Tcaron ydieresis -37
+KPX Tcommaaccent A -55
+KPX Tcommaaccent Aacute -55
+KPX Tcommaaccent Abreve -55
+KPX Tcommaaccent Acircumflex -55
+KPX Tcommaaccent Adieresis -55
+KPX Tcommaaccent Agrave -55
+KPX Tcommaaccent Amacron -55
+KPX Tcommaaccent Aogonek -55
+KPX Tcommaaccent Aring -55
+KPX Tcommaaccent Atilde -55
+KPX Tcommaaccent O -18
+KPX Tcommaaccent Oacute -18
+KPX Tcommaaccent Ocircumflex -18
+KPX Tcommaaccent Odieresis -18
+KPX Tcommaaccent Ograve -18
+KPX Tcommaaccent Ohungarumlaut -18
+KPX Tcommaaccent Omacron -18
+KPX Tcommaaccent Oslash -18
+KPX Tcommaaccent Otilde -18
+KPX Tcommaaccent a -92
+KPX Tcommaaccent aacute -92
+KPX Tcommaaccent abreve -92
+KPX Tcommaaccent acircumflex -92
+KPX Tcommaaccent adieresis -92
+KPX Tcommaaccent agrave -92
+KPX Tcommaaccent amacron -92
+KPX Tcommaaccent aogonek -92
+KPX Tcommaaccent aring -92
+KPX Tcommaaccent atilde -92
+KPX Tcommaaccent colon -74
+KPX Tcommaaccent comma -92
+KPX Tcommaaccent e -92
+KPX Tcommaaccent eacute -92
+KPX Tcommaaccent ecaron -92
+KPX Tcommaaccent ecircumflex -92
+KPX Tcommaaccent edieresis -52
+KPX Tcommaaccent edotaccent -92
+KPX Tcommaaccent egrave -52
+KPX Tcommaaccent emacron -52
+KPX Tcommaaccent eogonek -92
+KPX Tcommaaccent hyphen -92
+KPX Tcommaaccent i -37
+KPX Tcommaaccent iacute -37
+KPX Tcommaaccent iogonek -37
+KPX Tcommaaccent o -95
+KPX Tcommaaccent oacute -95
+KPX Tcommaaccent ocircumflex -95
+KPX Tcommaaccent odieresis -95
+KPX Tcommaaccent ograve -95
+KPX Tcommaaccent ohungarumlaut -95
+KPX Tcommaaccent omacron -95
+KPX Tcommaaccent oslash -95
+KPX Tcommaaccent otilde -95
+KPX Tcommaaccent period -92
+KPX Tcommaaccent r -37
+KPX Tcommaaccent racute -37
+KPX Tcommaaccent rcaron -37
+KPX Tcommaaccent rcommaaccent -37
+KPX Tcommaaccent semicolon -74
+KPX Tcommaaccent u -37
+KPX Tcommaaccent uacute -37
+KPX Tcommaaccent ucircumflex -37
+KPX Tcommaaccent udieresis -37
+KPX Tcommaaccent ugrave -37
+KPX Tcommaaccent uhungarumlaut -37
+KPX Tcommaaccent umacron -37
+KPX Tcommaaccent uogonek -37
+KPX Tcommaaccent uring -37
+KPX Tcommaaccent w -37
+KPX Tcommaaccent y -37
+KPX Tcommaaccent yacute -37
+KPX Tcommaaccent ydieresis -37
+KPX U A -45
+KPX U Aacute -45
+KPX U Abreve -45
+KPX U Acircumflex -45
+KPX U Adieresis -45
+KPX U Agrave -45
+KPX U Amacron -45
+KPX U Aogonek -45
+KPX U Aring -45
+KPX U Atilde -45
+KPX Uacute A -45
+KPX Uacute Aacute -45
+KPX Uacute Abreve -45
+KPX Uacute Acircumflex -45
+KPX Uacute Adieresis -45
+KPX Uacute Agrave -45
+KPX Uacute Amacron -45
+KPX Uacute Aogonek -45
+KPX Uacute Aring -45
+KPX Uacute Atilde -45
+KPX Ucircumflex A -45
+KPX Ucircumflex Aacute -45
+KPX Ucircumflex Abreve -45
+KPX Ucircumflex Acircumflex -45
+KPX Ucircumflex Adieresis -45
+KPX Ucircumflex Agrave -45
+KPX Ucircumflex Amacron -45
+KPX Ucircumflex Aogonek -45
+KPX Ucircumflex Aring -45
+KPX Ucircumflex Atilde -45
+KPX Udieresis A -45
+KPX Udieresis Aacute -45
+KPX Udieresis Abreve -45
+KPX Udieresis Acircumflex -45
+KPX Udieresis Adieresis -45
+KPX Udieresis Agrave -45
+KPX Udieresis Amacron -45
+KPX Udieresis Aogonek -45
+KPX Udieresis Aring -45
+KPX Udieresis Atilde -45
+KPX Ugrave A -45
+KPX Ugrave Aacute -45
+KPX Ugrave Abreve -45
+KPX Ugrave Acircumflex -45
+KPX Ugrave Adieresis -45
+KPX Ugrave Agrave -45
+KPX Ugrave Amacron -45
+KPX Ugrave Aogonek -45
+KPX Ugrave Aring -45
+KPX Ugrave Atilde -45
+KPX Uhungarumlaut A -45
+KPX Uhungarumlaut Aacute -45
+KPX Uhungarumlaut Abreve -45
+KPX Uhungarumlaut Acircumflex -45
+KPX Uhungarumlaut Adieresis -45
+KPX Uhungarumlaut Agrave -45
+KPX Uhungarumlaut Amacron -45
+KPX Uhungarumlaut Aogonek -45
+KPX Uhungarumlaut Aring -45
+KPX Uhungarumlaut Atilde -45
+KPX Umacron A -45
+KPX Umacron Aacute -45
+KPX Umacron Abreve -45
+KPX Umacron Acircumflex -45
+KPX Umacron Adieresis -45
+KPX Umacron Agrave -45
+KPX Umacron Amacron -45
+KPX Umacron Aogonek -45
+KPX Umacron Aring -45
+KPX Umacron Atilde -45
+KPX Uogonek A -45
+KPX Uogonek Aacute -45
+KPX Uogonek Abreve -45
+KPX Uogonek Acircumflex -45
+KPX Uogonek Adieresis -45
+KPX Uogonek Agrave -45
+KPX Uogonek Amacron -45
+KPX Uogonek Aogonek -45
+KPX Uogonek Aring -45
+KPX Uogonek Atilde -45
+KPX Uring A -45
+KPX Uring Aacute -45
+KPX Uring Abreve -45
+KPX Uring Acircumflex -45
+KPX Uring Adieresis -45
+KPX Uring Agrave -45
+KPX Uring Amacron -45
+KPX Uring Aogonek -45
+KPX Uring Aring -45
+KPX Uring Atilde -45
+KPX V A -85
+KPX V Aacute -85
+KPX V Abreve -85
+KPX V Acircumflex -85
+KPX V Adieresis -85
+KPX V Agrave -85
+KPX V Amacron -85
+KPX V Aogonek -85
+KPX V Aring -85
+KPX V Atilde -85
+KPX V G -10
+KPX V Gbreve -10
+KPX V Gcommaaccent -10
+KPX V O -30
+KPX V Oacute -30
+KPX V Ocircumflex -30
+KPX V Odieresis -30
+KPX V Ograve -30
+KPX V Ohungarumlaut -30
+KPX V Omacron -30
+KPX V Oslash -30
+KPX V Otilde -30
+KPX V a -111
+KPX V aacute -111
+KPX V abreve -111
+KPX V acircumflex -111
+KPX V adieresis -111
+KPX V agrave -111
+KPX V amacron -111
+KPX V aogonek -111
+KPX V aring -111
+KPX V atilde -111
+KPX V colon -74
+KPX V comma -129
+KPX V e -111
+KPX V eacute -111
+KPX V ecaron -111
+KPX V ecircumflex -111
+KPX V edieresis -71
+KPX V edotaccent -111
+KPX V egrave -71
+KPX V emacron -71
+KPX V eogonek -111
+KPX V hyphen -70
+KPX V i -55
+KPX V iacute -55
+KPX V iogonek -55
+KPX V o -111
+KPX V oacute -111
+KPX V ocircumflex -111
+KPX V odieresis -111
+KPX V ograve -111
+KPX V ohungarumlaut -111
+KPX V omacron -111
+KPX V oslash -111
+KPX V otilde -111
+KPX V period -129
+KPX V semicolon -74
+KPX V u -55
+KPX V uacute -55
+KPX V ucircumflex -55
+KPX V udieresis -55
+KPX V ugrave -55
+KPX V uhungarumlaut -55
+KPX V umacron -55
+KPX V uogonek -55
+KPX V uring -55
+KPX W A -74
+KPX W Aacute -74
+KPX W Abreve -74
+KPX W Acircumflex -74
+KPX W Adieresis -74
+KPX W Agrave -74
+KPX W Amacron -74
+KPX W Aogonek -74
+KPX W Aring -74
+KPX W Atilde -74
+KPX W O -15
+KPX W Oacute -15
+KPX W Ocircumflex -15
+KPX W Odieresis -15
+KPX W Ograve -15
+KPX W Ohungarumlaut -15
+KPX W Omacron -15
+KPX W Oslash -15
+KPX W Otilde -15
+KPX W a -85
+KPX W aacute -85
+KPX W abreve -85
+KPX W acircumflex -85
+KPX W adieresis -85
+KPX W agrave -85
+KPX W amacron -85
+KPX W aogonek -85
+KPX W aring -85
+KPX W atilde -85
+KPX W colon -55
+KPX W comma -74
+KPX W e -90
+KPX W eacute -90
+KPX W ecaron -90
+KPX W ecircumflex -90
+KPX W edieresis -50
+KPX W edotaccent -90
+KPX W egrave -50
+KPX W emacron -50
+KPX W eogonek -90
+KPX W hyphen -50
+KPX W i -37
+KPX W iacute -37
+KPX W iogonek -37
+KPX W o -80
+KPX W oacute -80
+KPX W ocircumflex -80
+KPX W odieresis -80
+KPX W ograve -80
+KPX W ohungarumlaut -80
+KPX W omacron -80
+KPX W oslash -80
+KPX W otilde -80
+KPX W period -74
+KPX W semicolon -55
+KPX W u -55
+KPX W uacute -55
+KPX W ucircumflex -55
+KPX W udieresis -55
+KPX W ugrave -55
+KPX W uhungarumlaut -55
+KPX W umacron -55
+KPX W uogonek -55
+KPX W uring -55
+KPX W y -55
+KPX W yacute -55
+KPX W ydieresis -55
+KPX Y A -74
+KPX Y Aacute -74
+KPX Y Abreve -74
+KPX Y Acircumflex -74
+KPX Y Adieresis -74
+KPX Y Agrave -74
+KPX Y Amacron -74
+KPX Y Aogonek -74
+KPX Y Aring -74
+KPX Y Atilde -74
+KPX Y O -25
+KPX Y Oacute -25
+KPX Y Ocircumflex -25
+KPX Y Odieresis -25
+KPX Y Ograve -25
+KPX Y Ohungarumlaut -25
+KPX Y Omacron -25
+KPX Y Oslash -25
+KPX Y Otilde -25
+KPX Y a -92
+KPX Y aacute -92
+KPX Y abreve -92
+KPX Y acircumflex -92
+KPX Y adieresis -92
+KPX Y agrave -92
+KPX Y amacron -92
+KPX Y aogonek -92
+KPX Y aring -92
+KPX Y atilde -92
+KPX Y colon -92
+KPX Y comma -92
+KPX Y e -111
+KPX Y eacute -111
+KPX Y ecaron -111
+KPX Y ecircumflex -71
+KPX Y edieresis -71
+KPX Y edotaccent -111
+KPX Y egrave -71
+KPX Y emacron -71
+KPX Y eogonek -111
+KPX Y hyphen -92
+KPX Y i -55
+KPX Y iacute -55
+KPX Y iogonek -55
+KPX Y o -111
+KPX Y oacute -111
+KPX Y ocircumflex -111
+KPX Y odieresis -111
+KPX Y ograve -111
+KPX Y ohungarumlaut -111
+KPX Y omacron -111
+KPX Y oslash -111
+KPX Y otilde -111
+KPX Y period -74
+KPX Y semicolon -92
+KPX Y u -92
+KPX Y uacute -92
+KPX Y ucircumflex -92
+KPX Y udieresis -92
+KPX Y ugrave -92
+KPX Y uhungarumlaut -92
+KPX Y umacron -92
+KPX Y uogonek -92
+KPX Y uring -92
+KPX Yacute A -74
+KPX Yacute Aacute -74
+KPX Yacute Abreve -74
+KPX Yacute Acircumflex -74
+KPX Yacute Adieresis -74
+KPX Yacute Agrave -74
+KPX Yacute Amacron -74
+KPX Yacute Aogonek -74
+KPX Yacute Aring -74
+KPX Yacute Atilde -74
+KPX Yacute O -25
+KPX Yacute Oacute -25
+KPX Yacute Ocircumflex -25
+KPX Yacute Odieresis -25
+KPX Yacute Ograve -25
+KPX Yacute Ohungarumlaut -25
+KPX Yacute Omacron -25
+KPX Yacute Oslash -25
+KPX Yacute Otilde -25
+KPX Yacute a -92
+KPX Yacute aacute -92
+KPX Yacute abreve -92
+KPX Yacute acircumflex -92
+KPX Yacute adieresis -92
+KPX Yacute agrave -92
+KPX Yacute amacron -92
+KPX Yacute aogonek -92
+KPX Yacute aring -92
+KPX Yacute atilde -92
+KPX Yacute colon -92
+KPX Yacute comma -92
+KPX Yacute e -111
+KPX Yacute eacute -111
+KPX Yacute ecaron -111
+KPX Yacute ecircumflex -71
+KPX Yacute edieresis -71
+KPX Yacute edotaccent -111
+KPX Yacute egrave -71
+KPX Yacute emacron -71
+KPX Yacute eogonek -111
+KPX Yacute hyphen -92
+KPX Yacute i -55
+KPX Yacute iacute -55
+KPX Yacute iogonek -55
+KPX Yacute o -111
+KPX Yacute oacute -111
+KPX Yacute ocircumflex -111
+KPX Yacute odieresis -111
+KPX Yacute ograve -111
+KPX Yacute ohungarumlaut -111
+KPX Yacute omacron -111
+KPX Yacute oslash -111
+KPX Yacute otilde -111
+KPX Yacute period -74
+KPX Yacute semicolon -92
+KPX Yacute u -92
+KPX Yacute uacute -92
+KPX Yacute ucircumflex -92
+KPX Yacute udieresis -92
+KPX Yacute ugrave -92
+KPX Yacute uhungarumlaut -92
+KPX Yacute umacron -92
+KPX Yacute uogonek -92
+KPX Yacute uring -92
+KPX Ydieresis A -74
+KPX Ydieresis Aacute -74
+KPX Ydieresis Abreve -74
+KPX Ydieresis Acircumflex -74
+KPX Ydieresis Adieresis -74
+KPX Ydieresis Agrave -74
+KPX Ydieresis Amacron -74
+KPX Ydieresis Aogonek -74
+KPX Ydieresis Aring -74
+KPX Ydieresis Atilde -74
+KPX Ydieresis O -25
+KPX Ydieresis Oacute -25
+KPX Ydieresis Ocircumflex -25
+KPX Ydieresis Odieresis -25
+KPX Ydieresis Ograve -25
+KPX Ydieresis Ohungarumlaut -25
+KPX Ydieresis Omacron -25
+KPX Ydieresis Oslash -25
+KPX Ydieresis Otilde -25
+KPX Ydieresis a -92
+KPX Ydieresis aacute -92
+KPX Ydieresis abreve -92
+KPX Ydieresis acircumflex -92
+KPX Ydieresis adieresis -92
+KPX Ydieresis agrave -92
+KPX Ydieresis amacron -92
+KPX Ydieresis aogonek -92
+KPX Ydieresis aring -92
+KPX Ydieresis atilde -92
+KPX Ydieresis colon -92
+KPX Ydieresis comma -92
+KPX Ydieresis e -111
+KPX Ydieresis eacute -111
+KPX Ydieresis ecaron -111
+KPX Ydieresis ecircumflex -71
+KPX Ydieresis edieresis -71
+KPX Ydieresis edotaccent -111
+KPX Ydieresis egrave -71
+KPX Ydieresis emacron -71
+KPX Ydieresis eogonek -111
+KPX Ydieresis hyphen -92
+KPX Ydieresis i -55
+KPX Ydieresis iacute -55
+KPX Ydieresis iogonek -55
+KPX Ydieresis o -111
+KPX Ydieresis oacute -111
+KPX Ydieresis ocircumflex -111
+KPX Ydieresis odieresis -111
+KPX Ydieresis ograve -111
+KPX Ydieresis ohungarumlaut -111
+KPX Ydieresis omacron -111
+KPX Ydieresis oslash -111
+KPX Ydieresis otilde -111
+KPX Ydieresis period -74
+KPX Ydieresis semicolon -92
+KPX Ydieresis u -92
+KPX Ydieresis uacute -92
+KPX Ydieresis ucircumflex -92
+KPX Ydieresis udieresis -92
+KPX Ydieresis ugrave -92
+KPX Ydieresis uhungarumlaut -92
+KPX Ydieresis umacron -92
+KPX Ydieresis uogonek -92
+KPX Ydieresis uring -92
+KPX b b -10
+KPX b period -40
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX c h -10
+KPX c k -10
+KPX c kcommaaccent -10
+KPX cacute h -10
+KPX cacute k -10
+KPX cacute kcommaaccent -10
+KPX ccaron h -10
+KPX ccaron k -10
+KPX ccaron kcommaaccent -10
+KPX ccedilla h -10
+KPX ccedilla k -10
+KPX ccedilla kcommaaccent -10
+KPX comma quotedblright -95
+KPX comma quoteright -95
+KPX e b -10
+KPX eacute b -10
+KPX ecaron b -10
+KPX ecircumflex b -10
+KPX edieresis b -10
+KPX edotaccent b -10
+KPX egrave b -10
+KPX emacron b -10
+KPX eogonek b -10
+KPX f comma -10
+KPX f dotlessi -30
+KPX f e -10
+KPX f eacute -10
+KPX f edotaccent -10
+KPX f eogonek -10
+KPX f f -18
+KPX f o -10
+KPX f oacute -10
+KPX f ocircumflex -10
+KPX f ograve -10
+KPX f ohungarumlaut -10
+KPX f oslash -10
+KPX f otilde -10
+KPX f period -10
+KPX f quoteright 55
+KPX k e -30
+KPX k eacute -30
+KPX k ecaron -30
+KPX k ecircumflex -30
+KPX k edieresis -30
+KPX k edotaccent -30
+KPX k egrave -30
+KPX k emacron -30
+KPX k eogonek -30
+KPX k o -10
+KPX k oacute -10
+KPX k ocircumflex -10
+KPX k odieresis -10
+KPX k ograve -10
+KPX k ohungarumlaut -10
+KPX k omacron -10
+KPX k oslash -10
+KPX k otilde -10
+KPX kcommaaccent e -30
+KPX kcommaaccent eacute -30
+KPX kcommaaccent ecaron -30
+KPX kcommaaccent ecircumflex -30
+KPX kcommaaccent edieresis -30
+KPX kcommaaccent edotaccent -30
+KPX kcommaaccent egrave -30
+KPX kcommaaccent emacron -30
+KPX kcommaaccent eogonek -30
+KPX kcommaaccent o -10
+KPX kcommaaccent oacute -10
+KPX kcommaaccent ocircumflex -10
+KPX kcommaaccent odieresis -10
+KPX kcommaaccent ograve -10
+KPX kcommaaccent ohungarumlaut -10
+KPX kcommaaccent omacron -10
+KPX kcommaaccent oslash -10
+KPX kcommaaccent otilde -10
+KPX n v -40
+KPX nacute v -40
+KPX ncaron v -40
+KPX ncommaaccent v -40
+KPX ntilde v -40
+KPX o v -15
+KPX o w -25
+KPX o x -10
+KPX o y -10
+KPX o yacute -10
+KPX o ydieresis -10
+KPX oacute v -15
+KPX oacute w -25
+KPX oacute x -10
+KPX oacute y -10
+KPX oacute yacute -10
+KPX oacute ydieresis -10
+KPX ocircumflex v -15
+KPX ocircumflex w -25
+KPX ocircumflex x -10
+KPX ocircumflex y -10
+KPX ocircumflex yacute -10
+KPX ocircumflex ydieresis -10
+KPX odieresis v -15
+KPX odieresis w -25
+KPX odieresis x -10
+KPX odieresis y -10
+KPX odieresis yacute -10
+KPX odieresis ydieresis -10
+KPX ograve v -15
+KPX ograve w -25
+KPX ograve x -10
+KPX ograve y -10
+KPX ograve yacute -10
+KPX ograve ydieresis -10
+KPX ohungarumlaut v -15
+KPX ohungarumlaut w -25
+KPX ohungarumlaut x -10
+KPX ohungarumlaut y -10
+KPX ohungarumlaut yacute -10
+KPX ohungarumlaut ydieresis -10
+KPX omacron v -15
+KPX omacron w -25
+KPX omacron x -10
+KPX omacron y -10
+KPX omacron yacute -10
+KPX omacron ydieresis -10
+KPX oslash v -15
+KPX oslash w -25
+KPX oslash x -10
+KPX oslash y -10
+KPX oslash yacute -10
+KPX oslash ydieresis -10
+KPX otilde v -15
+KPX otilde w -25
+KPX otilde x -10
+KPX otilde y -10
+KPX otilde yacute -10
+KPX otilde ydieresis -10
+KPX period quotedblright -95
+KPX period quoteright -95
+KPX quoteleft quoteleft -74
+KPX quoteright d -15
+KPX quoteright dcroat -15
+KPX quoteright quoteright -74
+KPX quoteright r -15
+KPX quoteright racute -15
+KPX quoteright rcaron -15
+KPX quoteright rcommaaccent -15
+KPX quoteright s -74
+KPX quoteright sacute -74
+KPX quoteright scaron -74
+KPX quoteright scedilla -74
+KPX quoteright scommaaccent -74
+KPX quoteright space -74
+KPX quoteright t -37
+KPX quoteright tcommaaccent -37
+KPX quoteright v -15
+KPX r comma -65
+KPX r period -65
+KPX racute comma -65
+KPX racute period -65
+KPX rcaron comma -65
+KPX rcaron period -65
+KPX rcommaaccent comma -65
+KPX rcommaaccent period -65
+KPX space A -37
+KPX space Aacute -37
+KPX space Abreve -37
+KPX space Acircumflex -37
+KPX space Adieresis -37
+KPX space Agrave -37
+KPX space Amacron -37
+KPX space Aogonek -37
+KPX space Aring -37
+KPX space Atilde -37
+KPX space V -70
+KPX space W -70
+KPX space Y -70
+KPX space Yacute -70
+KPX space Ydieresis -70
+KPX v comma -37
+KPX v e -15
+KPX v eacute -15
+KPX v ecaron -15
+KPX v ecircumflex -15
+KPX v edieresis -15
+KPX v edotaccent -15
+KPX v egrave -15
+KPX v emacron -15
+KPX v eogonek -15
+KPX v o -15
+KPX v oacute -15
+KPX v ocircumflex -15
+KPX v odieresis -15
+KPX v ograve -15
+KPX v ohungarumlaut -15
+KPX v omacron -15
+KPX v oslash -15
+KPX v otilde -15
+KPX v period -37
+KPX w a -10
+KPX w aacute -10
+KPX w abreve -10
+KPX w acircumflex -10
+KPX w adieresis -10
+KPX w agrave -10
+KPX w amacron -10
+KPX w aogonek -10
+KPX w aring -10
+KPX w atilde -10
+KPX w comma -37
+KPX w e -10
+KPX w eacute -10
+KPX w ecaron -10
+KPX w ecircumflex -10
+KPX w edieresis -10
+KPX w edotaccent -10
+KPX w egrave -10
+KPX w emacron -10
+KPX w eogonek -10
+KPX w o -15
+KPX w oacute -15
+KPX w ocircumflex -15
+KPX w odieresis -15
+KPX w ograve -15
+KPX w ohungarumlaut -15
+KPX w omacron -15
+KPX w oslash -15
+KPX w otilde -15
+KPX w period -37
+KPX x e -10
+KPX x eacute -10
+KPX x ecaron -10
+KPX x ecircumflex -10
+KPX x edieresis -10
+KPX x edotaccent -10
+KPX x egrave -10
+KPX x emacron -10
+KPX x eogonek -10
+KPX y comma -37
+KPX y period -37
+KPX yacute comma -37
+KPX yacute period -37
+KPX ydieresis comma -37
+KPX ydieresis period -37
+EndKernPairs
+EndKernData
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Times-Italic.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Times-Italic.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Times-Italic.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Times-Italic.afm 2004-05-26 16:06:22.000000000 +0000
@@ -0,0 +1,2667 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu May 1 12:56:55 1997
+Comment UniqueID 43067
+Comment VMusage 47727 58752
+FontName Times-Italic
+FullName Times Italic
+FamilyName Times
+Weight Medium
+ItalicAngle -15.5
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -169 -217 1010 883
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 653
+XHeight 441
+Ascender 683
+Descender -217
+StdHW 32
+StdVW 76
+StartCharMetrics 315
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 39 -11 302 667 ;
+C 34 ; WX 420 ; N quotedbl ; B 144 421 432 666 ;
+C 35 ; WX 500 ; N numbersign ; B 2 0 540 676 ;
+C 36 ; WX 500 ; N dollar ; B 31 -89 497 731 ;
+C 37 ; WX 833 ; N percent ; B 79 -13 790 676 ;
+C 38 ; WX 778 ; N ampersand ; B 76 -18 723 666 ;
+C 39 ; WX 333 ; N quoteright ; B 151 436 290 666 ;
+C 40 ; WX 333 ; N parenleft ; B 42 -181 315 669 ;
+C 41 ; WX 333 ; N parenright ; B 16 -180 289 669 ;
+C 42 ; WX 500 ; N asterisk ; B 128 255 492 666 ;
+C 43 ; WX 675 ; N plus ; B 86 0 590 506 ;
+C 44 ; WX 250 ; N comma ; B -4 -129 135 101 ;
+C 45 ; WX 333 ; N hyphen ; B 49 192 282 255 ;
+C 46 ; WX 250 ; N period ; B 27 -11 138 100 ;
+C 47 ; WX 278 ; N slash ; B -65 -18 386 666 ;
+C 48 ; WX 500 ; N zero ; B 32 -7 497 676 ;
+C 49 ; WX 500 ; N one ; B 49 0 409 676 ;
+C 50 ; WX 500 ; N two ; B 12 0 452 676 ;
+C 51 ; WX 500 ; N three ; B 15 -7 465 676 ;
+C 52 ; WX 500 ; N four ; B 1 0 479 676 ;
+C 53 ; WX 500 ; N five ; B 15 -7 491 666 ;
+C 54 ; WX 500 ; N six ; B 30 -7 521 686 ;
+C 55 ; WX 500 ; N seven ; B 75 -8 537 666 ;
+C 56 ; WX 500 ; N eight ; B 30 -7 493 676 ;
+C 57 ; WX 500 ; N nine ; B 23 -17 492 676 ;
+C 58 ; WX 333 ; N colon ; B 50 -11 261 441 ;
+C 59 ; WX 333 ; N semicolon ; B 27 -129 261 441 ;
+C 60 ; WX 675 ; N less ; B 84 -8 592 514 ;
+C 61 ; WX 675 ; N equal ; B 86 120 590 386 ;
+C 62 ; WX 675 ; N greater ; B 84 -8 592 514 ;
+C 63 ; WX 500 ; N question ; B 132 -12 472 664 ;
+C 64 ; WX 920 ; N at ; B 118 -18 806 666 ;
+C 65 ; WX 611 ; N A ; B -51 0 564 668 ;
+C 66 ; WX 611 ; N B ; B -8 0 588 653 ;
+C 67 ; WX 667 ; N C ; B 66 -18 689 666 ;
+C 68 ; WX 722 ; N D ; B -8 0 700 653 ;
+C 69 ; WX 611 ; N E ; B -1 0 634 653 ;
+C 70 ; WX 611 ; N F ; B 8 0 645 653 ;
+C 71 ; WX 722 ; N G ; B 52 -18 722 666 ;
+C 72 ; WX 722 ; N H ; B -8 0 767 653 ;
+C 73 ; WX 333 ; N I ; B -8 0 384 653 ;
+C 74 ; WX 444 ; N J ; B -6 -18 491 653 ;
+C 75 ; WX 667 ; N K ; B 7 0 722 653 ;
+C 76 ; WX 556 ; N L ; B -8 0 559 653 ;
+C 77 ; WX 833 ; N M ; B -18 0 873 653 ;
+C 78 ; WX 667 ; N N ; B -20 -15 727 653 ;
+C 79 ; WX 722 ; N O ; B 60 -18 699 666 ;
+C 80 ; WX 611 ; N P ; B 0 0 605 653 ;
+C 81 ; WX 722 ; N Q ; B 59 -182 699 666 ;
+C 82 ; WX 611 ; N R ; B -13 0 588 653 ;
+C 83 ; WX 500 ; N S ; B 17 -18 508 667 ;
+C 84 ; WX 556 ; N T ; B 59 0 633 653 ;
+C 85 ; WX 722 ; N U ; B 102 -18 765 653 ;
+C 86 ; WX 611 ; N V ; B 76 -18 688 653 ;
+C 87 ; WX 833 ; N W ; B 71 -18 906 653 ;
+C 88 ; WX 611 ; N X ; B -29 0 655 653 ;
+C 89 ; WX 556 ; N Y ; B 78 0 633 653 ;
+C 90 ; WX 556 ; N Z ; B -6 0 606 653 ;
+C 91 ; WX 389 ; N bracketleft ; B 21 -153 391 663 ;
+C 92 ; WX 278 ; N backslash ; B -41 -18 319 666 ;
+C 93 ; WX 389 ; N bracketright ; B 12 -153 382 663 ;
+C 94 ; WX 422 ; N asciicircum ; B 0 301 422 666 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 333 ; N quoteleft ; B 171 436 310 666 ;
+C 97 ; WX 500 ; N a ; B 17 -11 476 441 ;
+C 98 ; WX 500 ; N b ; B 23 -11 473 683 ;
+C 99 ; WX 444 ; N c ; B 30 -11 425 441 ;
+C 100 ; WX 500 ; N d ; B 15 -13 527 683 ;
+C 101 ; WX 444 ; N e ; B 31 -11 412 441 ;
+C 102 ; WX 278 ; N f ; B -147 -207 424 678 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B 8 -206 472 441 ;
+C 104 ; WX 500 ; N h ; B 19 -9 478 683 ;
+C 105 ; WX 278 ; N i ; B 49 -11 264 654 ;
+C 106 ; WX 278 ; N j ; B -124 -207 276 654 ;
+C 107 ; WX 444 ; N k ; B 14 -11 461 683 ;
+C 108 ; WX 278 ; N l ; B 41 -11 279 683 ;
+C 109 ; WX 722 ; N m ; B 12 -9 704 441 ;
+C 110 ; WX 500 ; N n ; B 14 -9 474 441 ;
+C 111 ; WX 500 ; N o ; B 27 -11 468 441 ;
+C 112 ; WX 500 ; N p ; B -75 -205 469 441 ;
+C 113 ; WX 500 ; N q ; B 25 -209 483 441 ;
+C 114 ; WX 389 ; N r ; B 45 0 412 441 ;
+C 115 ; WX 389 ; N s ; B 16 -13 366 442 ;
+C 116 ; WX 278 ; N t ; B 37 -11 296 546 ;
+C 117 ; WX 500 ; N u ; B 42 -11 475 441 ;
+C 118 ; WX 444 ; N v ; B 21 -18 426 441 ;
+C 119 ; WX 667 ; N w ; B 16 -18 648 441 ;
+C 120 ; WX 444 ; N x ; B -27 -11 447 441 ;
+C 121 ; WX 444 ; N y ; B -24 -206 426 441 ;
+C 122 ; WX 389 ; N z ; B -2 -81 380 428 ;
+C 123 ; WX 400 ; N braceleft ; B 51 -177 407 687 ;
+C 124 ; WX 275 ; N bar ; B 105 -217 171 783 ;
+C 125 ; WX 400 ; N braceright ; B -7 -177 349 687 ;
+C 126 ; WX 541 ; N asciitilde ; B 40 183 502 323 ;
+C 161 ; WX 389 ; N exclamdown ; B 59 -205 322 473 ;
+C 162 ; WX 500 ; N cent ; B 77 -143 472 560 ;
+C 163 ; WX 500 ; N sterling ; B 10 -6 517 670 ;
+C 164 ; WX 167 ; N fraction ; B -169 -10 337 676 ;
+C 165 ; WX 500 ; N yen ; B 27 0 603 653 ;
+C 166 ; WX 500 ; N florin ; B 25 -182 507 682 ;
+C 167 ; WX 500 ; N section ; B 53 -162 461 666 ;
+C 168 ; WX 500 ; N currency ; B -22 53 522 597 ;
+C 169 ; WX 214 ; N quotesingle ; B 132 421 241 666 ;
+C 170 ; WX 556 ; N quotedblleft ; B 166 436 514 666 ;
+C 171 ; WX 500 ; N guillemotleft ; B 53 37 445 403 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 51 37 281 403 ;
+C 173 ; WX 333 ; N guilsinglright ; B 52 37 282 403 ;
+C 174 ; WX 500 ; N fi ; B -141 -207 481 681 ;
+C 175 ; WX 500 ; N fl ; B -141 -204 518 682 ;
+C 177 ; WX 500 ; N endash ; B -6 197 505 243 ;
+C 178 ; WX 500 ; N dagger ; B 101 -159 488 666 ;
+C 179 ; WX 500 ; N daggerdbl ; B 22 -143 491 666 ;
+C 180 ; WX 250 ; N periodcentered ; B 70 199 181 310 ;
+C 182 ; WX 523 ; N paragraph ; B 55 -123 616 653 ;
+C 183 ; WX 350 ; N bullet ; B 40 191 310 461 ;
+C 184 ; WX 333 ; N quotesinglbase ; B 44 -129 183 101 ;
+C 185 ; WX 556 ; N quotedblbase ; B 57 -129 405 101 ;
+C 186 ; WX 556 ; N quotedblright ; B 151 436 499 666 ;
+C 187 ; WX 500 ; N guillemotright ; B 55 37 447 403 ;
+C 188 ; WX 889 ; N ellipsis ; B 57 -11 762 100 ;
+C 189 ; WX 1000 ; N perthousand ; B 25 -19 1010 706 ;
+C 191 ; WX 500 ; N questiondown ; B 28 -205 368 471 ;
+C 193 ; WX 333 ; N grave ; B 121 492 311 664 ;
+C 194 ; WX 333 ; N acute ; B 180 494 403 664 ;
+C 195 ; WX 333 ; N circumflex ; B 91 492 385 661 ;
+C 196 ; WX 333 ; N tilde ; B 100 517 427 624 ;
+C 197 ; WX 333 ; N macron ; B 99 532 411 583 ;
+C 198 ; WX 333 ; N breve ; B 117 492 418 650 ;
+C 199 ; WX 333 ; N dotaccent ; B 207 548 305 646 ;
+C 200 ; WX 333 ; N dieresis ; B 107 548 405 646 ;
+C 202 ; WX 333 ; N ring ; B 155 492 355 691 ;
+C 203 ; WX 333 ; N cedilla ; B -30 -217 182 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 93 494 486 664 ;
+C 206 ; WX 333 ; N ogonek ; B 20 -169 203 40 ;
+C 207 ; WX 333 ; N caron ; B 121 492 426 661 ;
+C 208 ; WX 889 ; N emdash ; B -6 197 894 243 ;
+C 225 ; WX 889 ; N AE ; B -27 0 911 653 ;
+C 227 ; WX 276 ; N ordfeminine ; B 42 406 352 676 ;
+C 232 ; WX 556 ; N Lslash ; B -8 0 559 653 ;
+C 233 ; WX 722 ; N Oslash ; B 60 -105 699 722 ;
+C 234 ; WX 944 ; N OE ; B 49 -8 964 666 ;
+C 235 ; WX 310 ; N ordmasculine ; B 67 406 362 676 ;
+C 241 ; WX 667 ; N ae ; B 23 -11 640 441 ;
+C 245 ; WX 278 ; N dotlessi ; B 49 -11 235 441 ;
+C 248 ; WX 278 ; N lslash ; B 41 -11 312 683 ;
+C 249 ; WX 500 ; N oslash ; B 28 -135 469 554 ;
+C 250 ; WX 667 ; N oe ; B 20 -12 646 441 ;
+C 251 ; WX 500 ; N germandbls ; B -168 -207 493 679 ;
+C -1 ; WX 333 ; N Idieresis ; B -8 0 435 818 ;
+C -1 ; WX 444 ; N eacute ; B 31 -11 459 664 ;
+C -1 ; WX 500 ; N abreve ; B 17 -11 502 650 ;
+C -1 ; WX 500 ; N uhungarumlaut ; B 42 -11 580 664 ;
+C -1 ; WX 444 ; N ecaron ; B 31 -11 482 661 ;
+C -1 ; WX 556 ; N Ydieresis ; B 78 0 633 818 ;
+C -1 ; WX 675 ; N divide ; B 86 -11 590 517 ;
+C -1 ; WX 556 ; N Yacute ; B 78 0 633 876 ;
+C -1 ; WX 611 ; N Acircumflex ; B -51 0 564 873 ;
+C -1 ; WX 500 ; N aacute ; B 17 -11 487 664 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 102 -18 765 873 ;
+C -1 ; WX 444 ; N yacute ; B -24 -206 459 664 ;
+C -1 ; WX 389 ; N scommaaccent ; B 16 -217 366 442 ;
+C -1 ; WX 444 ; N ecircumflex ; B 31 -11 441 661 ;
+C -1 ; WX 722 ; N Uring ; B 102 -18 765 883 ;
+C -1 ; WX 722 ; N Udieresis ; B 102 -18 765 818 ;
+C -1 ; WX 500 ; N aogonek ; B 17 -169 476 441 ;
+C -1 ; WX 722 ; N Uacute ; B 102 -18 765 876 ;
+C -1 ; WX 500 ; N uogonek ; B 42 -169 477 441 ;
+C -1 ; WX 611 ; N Edieresis ; B -1 0 634 818 ;
+C -1 ; WX 722 ; N Dcroat ; B -8 0 700 653 ;
+C -1 ; WX 250 ; N commaaccent ; B 8 -217 133 -50 ;
+C -1 ; WX 760 ; N copyright ; B 41 -18 719 666 ;
+C -1 ; WX 611 ; N Emacron ; B -1 0 634 795 ;
+C -1 ; WX 444 ; N ccaron ; B 30 -11 482 661 ;
+C -1 ; WX 500 ; N aring ; B 17 -11 476 691 ;
+C -1 ; WX 667 ; N Ncommaaccent ; B -20 -187 727 653 ;
+C -1 ; WX 278 ; N lacute ; B 41 -11 395 876 ;
+C -1 ; WX 500 ; N agrave ; B 17 -11 476 664 ;
+C -1 ; WX 556 ; N Tcommaaccent ; B 59 -217 633 653 ;
+C -1 ; WX 667 ; N Cacute ; B 66 -18 690 876 ;
+C -1 ; WX 500 ; N atilde ; B 17 -11 511 624 ;
+C -1 ; WX 611 ; N Edotaccent ; B -1 0 634 818 ;
+C -1 ; WX 389 ; N scaron ; B 16 -13 454 661 ;
+C -1 ; WX 389 ; N scedilla ; B 16 -217 366 442 ;
+C -1 ; WX 278 ; N iacute ; B 49 -11 355 664 ;
+C -1 ; WX 471 ; N lozenge ; B 13 0 459 724 ;
+C -1 ; WX 611 ; N Rcaron ; B -13 0 588 873 ;
+C -1 ; WX 722 ; N Gcommaaccent ; B 52 -217 722 666 ;
+C -1 ; WX 500 ; N ucircumflex ; B 42 -11 475 661 ;
+C -1 ; WX 500 ; N acircumflex ; B 17 -11 476 661 ;
+C -1 ; WX 611 ; N Amacron ; B -51 0 564 795 ;
+C -1 ; WX 389 ; N rcaron ; B 45 0 434 661 ;
+C -1 ; WX 444 ; N ccedilla ; B 30 -217 425 441 ;
+C -1 ; WX 556 ; N Zdotaccent ; B -6 0 606 818 ;
+C -1 ; WX 611 ; N Thorn ; B 0 0 569 653 ;
+C -1 ; WX 722 ; N Omacron ; B 60 -18 699 795 ;
+C -1 ; WX 611 ; N Racute ; B -13 0 588 876 ;
+C -1 ; WX 500 ; N Sacute ; B 17 -18 508 876 ;
+C -1 ; WX 544 ; N dcaron ; B 15 -13 658 683 ;
+C -1 ; WX 722 ; N Umacron ; B 102 -18 765 795 ;
+C -1 ; WX 500 ; N uring ; B 42 -11 475 691 ;
+C -1 ; WX 300 ; N threesuperior ; B 43 268 339 676 ;
+C -1 ; WX 722 ; N Ograve ; B 60 -18 699 876 ;
+C -1 ; WX 611 ; N Agrave ; B -51 0 564 876 ;
+C -1 ; WX 611 ; N Abreve ; B -51 0 564 862 ;
+C -1 ; WX 675 ; N multiply ; B 93 8 582 497 ;
+C -1 ; WX 500 ; N uacute ; B 42 -11 477 664 ;
+C -1 ; WX 556 ; N Tcaron ; B 59 0 633 873 ;
+C -1 ; WX 476 ; N partialdiff ; B 17 -38 459 710 ;
+C -1 ; WX 444 ; N ydieresis ; B -24 -206 441 606 ;
+C -1 ; WX 667 ; N Nacute ; B -20 -15 727 876 ;
+C -1 ; WX 278 ; N icircumflex ; B 33 -11 327 661 ;
+C -1 ; WX 611 ; N Ecircumflex ; B -1 0 634 873 ;
+C -1 ; WX 500 ; N adieresis ; B 17 -11 489 606 ;
+C -1 ; WX 444 ; N edieresis ; B 31 -11 451 606 ;
+C -1 ; WX 444 ; N cacute ; B 30 -11 459 664 ;
+C -1 ; WX 500 ; N nacute ; B 14 -9 477 664 ;
+C -1 ; WX 500 ; N umacron ; B 42 -11 485 583 ;
+C -1 ; WX 667 ; N Ncaron ; B -20 -15 727 873 ;
+C -1 ; WX 333 ; N Iacute ; B -8 0 433 876 ;
+C -1 ; WX 675 ; N plusminus ; B 86 0 590 506 ;
+C -1 ; WX 275 ; N brokenbar ; B 105 -142 171 708 ;
+C -1 ; WX 760 ; N registered ; B 41 -18 719 666 ;
+C -1 ; WX 722 ; N Gbreve ; B 52 -18 722 862 ;
+C -1 ; WX 333 ; N Idotaccent ; B -8 0 384 818 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ;
+C -1 ; WX 611 ; N Egrave ; B -1 0 634 876 ;
+C -1 ; WX 389 ; N racute ; B 45 0 431 664 ;
+C -1 ; WX 500 ; N omacron ; B 27 -11 495 583 ;
+C -1 ; WX 556 ; N Zacute ; B -6 0 606 876 ;
+C -1 ; WX 556 ; N Zcaron ; B -6 0 606 873 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 523 658 ;
+C -1 ; WX 722 ; N Eth ; B -8 0 700 653 ;
+C -1 ; WX 667 ; N Ccedilla ; B 66 -217 689 666 ;
+C -1 ; WX 278 ; N lcommaaccent ; B 22 -217 279 683 ;
+C -1 ; WX 300 ; N tcaron ; B 37 -11 407 681 ;
+C -1 ; WX 444 ; N eogonek ; B 31 -169 412 441 ;
+C -1 ; WX 722 ; N Uogonek ; B 102 -184 765 653 ;
+C -1 ; WX 611 ; N Aacute ; B -51 0 564 876 ;
+C -1 ; WX 611 ; N Adieresis ; B -51 0 564 818 ;
+C -1 ; WX 444 ; N egrave ; B 31 -11 412 664 ;
+C -1 ; WX 389 ; N zacute ; B -2 -81 431 664 ;
+C -1 ; WX 278 ; N iogonek ; B 49 -169 264 654 ;
+C -1 ; WX 722 ; N Oacute ; B 60 -18 699 876 ;
+C -1 ; WX 500 ; N oacute ; B 27 -11 487 664 ;
+C -1 ; WX 500 ; N amacron ; B 17 -11 495 583 ;
+C -1 ; WX 389 ; N sacute ; B 16 -13 431 664 ;
+C -1 ; WX 278 ; N idieresis ; B 49 -11 352 606 ;
+C -1 ; WX 722 ; N Ocircumflex ; B 60 -18 699 873 ;
+C -1 ; WX 722 ; N Ugrave ; B 102 -18 765 876 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 500 ; N thorn ; B -75 -205 469 683 ;
+C -1 ; WX 300 ; N twosuperior ; B 33 271 324 676 ;
+C -1 ; WX 722 ; N Odieresis ; B 60 -18 699 818 ;
+C -1 ; WX 500 ; N mu ; B -30 -209 497 428 ;
+C -1 ; WX 278 ; N igrave ; B 49 -11 284 664 ;
+C -1 ; WX 500 ; N ohungarumlaut ; B 27 -11 590 664 ;
+C -1 ; WX 611 ; N Eogonek ; B -1 -169 634 653 ;
+C -1 ; WX 500 ; N dcroat ; B 15 -13 572 683 ;
+C -1 ; WX 750 ; N threequarters ; B 23 -10 736 676 ;
+C -1 ; WX 500 ; N Scedilla ; B 17 -217 508 667 ;
+C -1 ; WX 300 ; N lcaron ; B 41 -11 407 683 ;
+C -1 ; WX 667 ; N Kcommaaccent ; B 7 -217 722 653 ;
+C -1 ; WX 556 ; N Lacute ; B -8 0 559 876 ;
+C -1 ; WX 980 ; N trademark ; B 30 247 957 653 ;
+C -1 ; WX 444 ; N edotaccent ; B 31 -11 412 606 ;
+C -1 ; WX 333 ; N Igrave ; B -8 0 384 876 ;
+C -1 ; WX 333 ; N Imacron ; B -8 0 441 795 ;
+C -1 ; WX 611 ; N Lcaron ; B -8 0 586 653 ;
+C -1 ; WX 750 ; N onehalf ; B 34 -10 749 676 ;
+C -1 ; WX 549 ; N lessequal ; B 26 0 523 658 ;
+C -1 ; WX 500 ; N ocircumflex ; B 27 -11 468 661 ;
+C -1 ; WX 500 ; N ntilde ; B 14 -9 476 624 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 102 -18 765 876 ;
+C -1 ; WX 611 ; N Eacute ; B -1 0 634 876 ;
+C -1 ; WX 444 ; N emacron ; B 31 -11 457 583 ;
+C -1 ; WX 500 ; N gbreve ; B 8 -206 487 650 ;
+C -1 ; WX 750 ; N onequarter ; B 33 -10 736 676 ;
+C -1 ; WX 500 ; N Scaron ; B 17 -18 520 873 ;
+C -1 ; WX 500 ; N Scommaaccent ; B 17 -217 508 667 ;
+C -1 ; WX 722 ; N Ohungarumlaut ; B 60 -18 699 876 ;
+C -1 ; WX 400 ; N degree ; B 101 390 387 676 ;
+C -1 ; WX 500 ; N ograve ; B 27 -11 468 664 ;
+C -1 ; WX 667 ; N Ccaron ; B 66 -18 689 873 ;
+C -1 ; WX 500 ; N ugrave ; B 42 -11 475 664 ;
+C -1 ; WX 453 ; N radical ; B 2 -60 452 768 ;
+C -1 ; WX 722 ; N Dcaron ; B -8 0 700 873 ;
+C -1 ; WX 389 ; N rcommaaccent ; B -3 -217 412 441 ;
+C -1 ; WX 667 ; N Ntilde ; B -20 -15 727 836 ;
+C -1 ; WX 500 ; N otilde ; B 27 -11 496 624 ;
+C -1 ; WX 611 ; N Rcommaaccent ; B -13 -187 588 653 ;
+C -1 ; WX 556 ; N Lcommaaccent ; B -8 -217 559 653 ;
+C -1 ; WX 611 ; N Atilde ; B -51 0 566 836 ;
+C -1 ; WX 611 ; N Aogonek ; B -51 -169 566 668 ;
+C -1 ; WX 611 ; N Aring ; B -51 0 564 883 ;
+C -1 ; WX 722 ; N Otilde ; B 60 -18 699 836 ;
+C -1 ; WX 389 ; N zdotaccent ; B -2 -81 380 606 ;
+C -1 ; WX 611 ; N Ecaron ; B -1 0 634 873 ;
+C -1 ; WX 333 ; N Iogonek ; B -8 -169 384 653 ;
+C -1 ; WX 444 ; N kcommaaccent ; B 14 -187 461 683 ;
+C -1 ; WX 675 ; N minus ; B 86 220 590 286 ;
+C -1 ; WX 333 ; N Icircumflex ; B -8 0 425 873 ;
+C -1 ; WX 500 ; N ncaron ; B 14 -9 510 661 ;
+C -1 ; WX 278 ; N tcommaaccent ; B 2 -217 296 546 ;
+C -1 ; WX 675 ; N logicalnot ; B 86 108 590 386 ;
+C -1 ; WX 500 ; N odieresis ; B 27 -11 489 606 ;
+C -1 ; WX 500 ; N udieresis ; B 42 -11 479 606 ;
+C -1 ; WX 549 ; N notequal ; B 12 -29 537 541 ;
+C -1 ; WX 500 ; N gcommaaccent ; B 8 -206 472 706 ;
+C -1 ; WX 500 ; N eth ; B 27 -11 482 683 ;
+C -1 ; WX 389 ; N zcaron ; B -2 -81 434 661 ;
+C -1 ; WX 500 ; N ncommaaccent ; B 14 -187 474 441 ;
+C -1 ; WX 300 ; N onesuperior ; B 43 271 284 676 ;
+C -1 ; WX 278 ; N imacron ; B 46 -11 311 583 ;
+C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2321
+KPX A C -30
+KPX A Cacute -30
+KPX A Ccaron -30
+KPX A Ccedilla -30
+KPX A G -35
+KPX A Gbreve -35
+KPX A Gcommaaccent -35
+KPX A O -40
+KPX A Oacute -40
+KPX A Ocircumflex -40
+KPX A Odieresis -40
+KPX A Ograve -40
+KPX A Ohungarumlaut -40
+KPX A Omacron -40
+KPX A Oslash -40
+KPX A Otilde -40
+KPX A Q -40
+KPX A T -37
+KPX A Tcaron -37
+KPX A Tcommaaccent -37
+KPX A U -50
+KPX A Uacute -50
+KPX A Ucircumflex -50
+KPX A Udieresis -50
+KPX A Ugrave -50
+KPX A Uhungarumlaut -50
+KPX A Umacron -50
+KPX A Uogonek -50
+KPX A Uring -50
+KPX A V -105
+KPX A W -95
+KPX A Y -55
+KPX A Yacute -55
+KPX A Ydieresis -55
+KPX A quoteright -37
+KPX A u -20
+KPX A uacute -20
+KPX A ucircumflex -20
+KPX A udieresis -20
+KPX A ugrave -20
+KPX A uhungarumlaut -20
+KPX A umacron -20
+KPX A uogonek -20
+KPX A uring -20
+KPX A v -55
+KPX A w -55
+KPX A y -55
+KPX A yacute -55
+KPX A ydieresis -55
+KPX Aacute C -30
+KPX Aacute Cacute -30
+KPX Aacute Ccaron -30
+KPX Aacute Ccedilla -30
+KPX Aacute G -35
+KPX Aacute Gbreve -35
+KPX Aacute Gcommaaccent -35
+KPX Aacute O -40
+KPX Aacute Oacute -40
+KPX Aacute Ocircumflex -40
+KPX Aacute Odieresis -40
+KPX Aacute Ograve -40
+KPX Aacute Ohungarumlaut -40
+KPX Aacute Omacron -40
+KPX Aacute Oslash -40
+KPX Aacute Otilde -40
+KPX Aacute Q -40
+KPX Aacute T -37
+KPX Aacute Tcaron -37
+KPX Aacute Tcommaaccent -37
+KPX Aacute U -50
+KPX Aacute Uacute -50
+KPX Aacute Ucircumflex -50
+KPX Aacute Udieresis -50
+KPX Aacute Ugrave -50
+KPX Aacute Uhungarumlaut -50
+KPX Aacute Umacron -50
+KPX Aacute Uogonek -50
+KPX Aacute Uring -50
+KPX Aacute V -105
+KPX Aacute W -95
+KPX Aacute Y -55
+KPX Aacute Yacute -55
+KPX Aacute Ydieresis -55
+KPX Aacute quoteright -37
+KPX Aacute u -20
+KPX Aacute uacute -20
+KPX Aacute ucircumflex -20
+KPX Aacute udieresis -20
+KPX Aacute ugrave -20
+KPX Aacute uhungarumlaut -20
+KPX Aacute umacron -20
+KPX Aacute uogonek -20
+KPX Aacute uring -20
+KPX Aacute v -55
+KPX Aacute w -55
+KPX Aacute y -55
+KPX Aacute yacute -55
+KPX Aacute ydieresis -55
+KPX Abreve C -30
+KPX Abreve Cacute -30
+KPX Abreve Ccaron -30
+KPX Abreve Ccedilla -30
+KPX Abreve G -35
+KPX Abreve Gbreve -35
+KPX Abreve Gcommaaccent -35
+KPX Abreve O -40
+KPX Abreve Oacute -40
+KPX Abreve Ocircumflex -40
+KPX Abreve Odieresis -40
+KPX Abreve Ograve -40
+KPX Abreve Ohungarumlaut -40
+KPX Abreve Omacron -40
+KPX Abreve Oslash -40
+KPX Abreve Otilde -40
+KPX Abreve Q -40
+KPX Abreve T -37
+KPX Abreve Tcaron -37
+KPX Abreve Tcommaaccent -37
+KPX Abreve U -50
+KPX Abreve Uacute -50
+KPX Abreve Ucircumflex -50
+KPX Abreve Udieresis -50
+KPX Abreve Ugrave -50
+KPX Abreve Uhungarumlaut -50
+KPX Abreve Umacron -50
+KPX Abreve Uogonek -50
+KPX Abreve Uring -50
+KPX Abreve V -105
+KPX Abreve W -95
+KPX Abreve Y -55
+KPX Abreve Yacute -55
+KPX Abreve Ydieresis -55
+KPX Abreve quoteright -37
+KPX Abreve u -20
+KPX Abreve uacute -20
+KPX Abreve ucircumflex -20
+KPX Abreve udieresis -20
+KPX Abreve ugrave -20
+KPX Abreve uhungarumlaut -20
+KPX Abreve umacron -20
+KPX Abreve uogonek -20
+KPX Abreve uring -20
+KPX Abreve v -55
+KPX Abreve w -55
+KPX Abreve y -55
+KPX Abreve yacute -55
+KPX Abreve ydieresis -55
+KPX Acircumflex C -30
+KPX Acircumflex Cacute -30
+KPX Acircumflex Ccaron -30
+KPX Acircumflex Ccedilla -30
+KPX Acircumflex G -35
+KPX Acircumflex Gbreve -35
+KPX Acircumflex Gcommaaccent -35
+KPX Acircumflex O -40
+KPX Acircumflex Oacute -40
+KPX Acircumflex Ocircumflex -40
+KPX Acircumflex Odieresis -40
+KPX Acircumflex Ograve -40
+KPX Acircumflex Ohungarumlaut -40
+KPX Acircumflex Omacron -40
+KPX Acircumflex Oslash -40
+KPX Acircumflex Otilde -40
+KPX Acircumflex Q -40
+KPX Acircumflex T -37
+KPX Acircumflex Tcaron -37
+KPX Acircumflex Tcommaaccent -37
+KPX Acircumflex U -50
+KPX Acircumflex Uacute -50
+KPX Acircumflex Ucircumflex -50
+KPX Acircumflex Udieresis -50
+KPX Acircumflex Ugrave -50
+KPX Acircumflex Uhungarumlaut -50
+KPX Acircumflex Umacron -50
+KPX Acircumflex Uogonek -50
+KPX Acircumflex Uring -50
+KPX Acircumflex V -105
+KPX Acircumflex W -95
+KPX Acircumflex Y -55
+KPX Acircumflex Yacute -55
+KPX Acircumflex Ydieresis -55
+KPX Acircumflex quoteright -37
+KPX Acircumflex u -20
+KPX Acircumflex uacute -20
+KPX Acircumflex ucircumflex -20
+KPX Acircumflex udieresis -20
+KPX Acircumflex ugrave -20
+KPX Acircumflex uhungarumlaut -20
+KPX Acircumflex umacron -20
+KPX Acircumflex uogonek -20
+KPX Acircumflex uring -20
+KPX Acircumflex v -55
+KPX Acircumflex w -55
+KPX Acircumflex y -55
+KPX Acircumflex yacute -55
+KPX Acircumflex ydieresis -55
+KPX Adieresis C -30
+KPX Adieresis Cacute -30
+KPX Adieresis Ccaron -30
+KPX Adieresis Ccedilla -30
+KPX Adieresis G -35
+KPX Adieresis Gbreve -35
+KPX Adieresis Gcommaaccent -35
+KPX Adieresis O -40
+KPX Adieresis Oacute -40
+KPX Adieresis Ocircumflex -40
+KPX Adieresis Odieresis -40
+KPX Adieresis Ograve -40
+KPX Adieresis Ohungarumlaut -40
+KPX Adieresis Omacron -40
+KPX Adieresis Oslash -40
+KPX Adieresis Otilde -40
+KPX Adieresis Q -40
+KPX Adieresis T -37
+KPX Adieresis Tcaron -37
+KPX Adieresis Tcommaaccent -37
+KPX Adieresis U -50
+KPX Adieresis Uacute -50
+KPX Adieresis Ucircumflex -50
+KPX Adieresis Udieresis -50
+KPX Adieresis Ugrave -50
+KPX Adieresis Uhungarumlaut -50
+KPX Adieresis Umacron -50
+KPX Adieresis Uogonek -50
+KPX Adieresis Uring -50
+KPX Adieresis V -105
+KPX Adieresis W -95
+KPX Adieresis Y -55
+KPX Adieresis Yacute -55
+KPX Adieresis Ydieresis -55
+KPX Adieresis quoteright -37
+KPX Adieresis u -20
+KPX Adieresis uacute -20
+KPX Adieresis ucircumflex -20
+KPX Adieresis udieresis -20
+KPX Adieresis ugrave -20
+KPX Adieresis uhungarumlaut -20
+KPX Adieresis umacron -20
+KPX Adieresis uogonek -20
+KPX Adieresis uring -20
+KPX Adieresis v -55
+KPX Adieresis w -55
+KPX Adieresis y -55
+KPX Adieresis yacute -55
+KPX Adieresis ydieresis -55
+KPX Agrave C -30
+KPX Agrave Cacute -30
+KPX Agrave Ccaron -30
+KPX Agrave Ccedilla -30
+KPX Agrave G -35
+KPX Agrave Gbreve -35
+KPX Agrave Gcommaaccent -35
+KPX Agrave O -40
+KPX Agrave Oacute -40
+KPX Agrave Ocircumflex -40
+KPX Agrave Odieresis -40
+KPX Agrave Ograve -40
+KPX Agrave Ohungarumlaut -40
+KPX Agrave Omacron -40
+KPX Agrave Oslash -40
+KPX Agrave Otilde -40
+KPX Agrave Q -40
+KPX Agrave T -37
+KPX Agrave Tcaron -37
+KPX Agrave Tcommaaccent -37
+KPX Agrave U -50
+KPX Agrave Uacute -50
+KPX Agrave Ucircumflex -50
+KPX Agrave Udieresis -50
+KPX Agrave Ugrave -50
+KPX Agrave Uhungarumlaut -50
+KPX Agrave Umacron -50
+KPX Agrave Uogonek -50
+KPX Agrave Uring -50
+KPX Agrave V -105
+KPX Agrave W -95
+KPX Agrave Y -55
+KPX Agrave Yacute -55
+KPX Agrave Ydieresis -55
+KPX Agrave quoteright -37
+KPX Agrave u -20
+KPX Agrave uacute -20
+KPX Agrave ucircumflex -20
+KPX Agrave udieresis -20
+KPX Agrave ugrave -20
+KPX Agrave uhungarumlaut -20
+KPX Agrave umacron -20
+KPX Agrave uogonek -20
+KPX Agrave uring -20
+KPX Agrave v -55
+KPX Agrave w -55
+KPX Agrave y -55
+KPX Agrave yacute -55
+KPX Agrave ydieresis -55
+KPX Amacron C -30
+KPX Amacron Cacute -30
+KPX Amacron Ccaron -30
+KPX Amacron Ccedilla -30
+KPX Amacron G -35
+KPX Amacron Gbreve -35
+KPX Amacron Gcommaaccent -35
+KPX Amacron O -40
+KPX Amacron Oacute -40
+KPX Amacron Ocircumflex -40
+KPX Amacron Odieresis -40
+KPX Amacron Ograve -40
+KPX Amacron Ohungarumlaut -40
+KPX Amacron Omacron -40
+KPX Amacron Oslash -40
+KPX Amacron Otilde -40
+KPX Amacron Q -40
+KPX Amacron T -37
+KPX Amacron Tcaron -37
+KPX Amacron Tcommaaccent -37
+KPX Amacron U -50
+KPX Amacron Uacute -50
+KPX Amacron Ucircumflex -50
+KPX Amacron Udieresis -50
+KPX Amacron Ugrave -50
+KPX Amacron Uhungarumlaut -50
+KPX Amacron Umacron -50
+KPX Amacron Uogonek -50
+KPX Amacron Uring -50
+KPX Amacron V -105
+KPX Amacron W -95
+KPX Amacron Y -55
+KPX Amacron Yacute -55
+KPX Amacron Ydieresis -55
+KPX Amacron quoteright -37
+KPX Amacron u -20
+KPX Amacron uacute -20
+KPX Amacron ucircumflex -20
+KPX Amacron udieresis -20
+KPX Amacron ugrave -20
+KPX Amacron uhungarumlaut -20
+KPX Amacron umacron -20
+KPX Amacron uogonek -20
+KPX Amacron uring -20
+KPX Amacron v -55
+KPX Amacron w -55
+KPX Amacron y -55
+KPX Amacron yacute -55
+KPX Amacron ydieresis -55
+KPX Aogonek C -30
+KPX Aogonek Cacute -30
+KPX Aogonek Ccaron -30
+KPX Aogonek Ccedilla -30
+KPX Aogonek G -35
+KPX Aogonek Gbreve -35
+KPX Aogonek Gcommaaccent -35
+KPX Aogonek O -40
+KPX Aogonek Oacute -40
+KPX Aogonek Ocircumflex -40
+KPX Aogonek Odieresis -40
+KPX Aogonek Ograve -40
+KPX Aogonek Ohungarumlaut -40
+KPX Aogonek Omacron -40
+KPX Aogonek Oslash -40
+KPX Aogonek Otilde -40
+KPX Aogonek Q -40
+KPX Aogonek T -37
+KPX Aogonek Tcaron -37
+KPX Aogonek Tcommaaccent -37
+KPX Aogonek U -50
+KPX Aogonek Uacute -50
+KPX Aogonek Ucircumflex -50
+KPX Aogonek Udieresis -50
+KPX Aogonek Ugrave -50
+KPX Aogonek Uhungarumlaut -50
+KPX Aogonek Umacron -50
+KPX Aogonek Uogonek -50
+KPX Aogonek Uring -50
+KPX Aogonek V -105
+KPX Aogonek W -95
+KPX Aogonek Y -55
+KPX Aogonek Yacute -55
+KPX Aogonek Ydieresis -55
+KPX Aogonek quoteright -37
+KPX Aogonek u -20
+KPX Aogonek uacute -20
+KPX Aogonek ucircumflex -20
+KPX Aogonek udieresis -20
+KPX Aogonek ugrave -20
+KPX Aogonek uhungarumlaut -20
+KPX Aogonek umacron -20
+KPX Aogonek uogonek -20
+KPX Aogonek uring -20
+KPX Aogonek v -55
+KPX Aogonek w -55
+KPX Aogonek y -55
+KPX Aogonek yacute -55
+KPX Aogonek ydieresis -55
+KPX Aring C -30
+KPX Aring Cacute -30
+KPX Aring Ccaron -30
+KPX Aring Ccedilla -30
+KPX Aring G -35
+KPX Aring Gbreve -35
+KPX Aring Gcommaaccent -35
+KPX Aring O -40
+KPX Aring Oacute -40
+KPX Aring Ocircumflex -40
+KPX Aring Odieresis -40
+KPX Aring Ograve -40
+KPX Aring Ohungarumlaut -40
+KPX Aring Omacron -40
+KPX Aring Oslash -40
+KPX Aring Otilde -40
+KPX Aring Q -40
+KPX Aring T -37
+KPX Aring Tcaron -37
+KPX Aring Tcommaaccent -37
+KPX Aring U -50
+KPX Aring Uacute -50
+KPX Aring Ucircumflex -50
+KPX Aring Udieresis -50
+KPX Aring Ugrave -50
+KPX Aring Uhungarumlaut -50
+KPX Aring Umacron -50
+KPX Aring Uogonek -50
+KPX Aring Uring -50
+KPX Aring V -105
+KPX Aring W -95
+KPX Aring Y -55
+KPX Aring Yacute -55
+KPX Aring Ydieresis -55
+KPX Aring quoteright -37
+KPX Aring u -20
+KPX Aring uacute -20
+KPX Aring ucircumflex -20
+KPX Aring udieresis -20
+KPX Aring ugrave -20
+KPX Aring uhungarumlaut -20
+KPX Aring umacron -20
+KPX Aring uogonek -20
+KPX Aring uring -20
+KPX Aring v -55
+KPX Aring w -55
+KPX Aring y -55
+KPX Aring yacute -55
+KPX Aring ydieresis -55
+KPX Atilde C -30
+KPX Atilde Cacute -30
+KPX Atilde Ccaron -30
+KPX Atilde Ccedilla -30
+KPX Atilde G -35
+KPX Atilde Gbreve -35
+KPX Atilde Gcommaaccent -35
+KPX Atilde O -40
+KPX Atilde Oacute -40
+KPX Atilde Ocircumflex -40
+KPX Atilde Odieresis -40
+KPX Atilde Ograve -40
+KPX Atilde Ohungarumlaut -40
+KPX Atilde Omacron -40
+KPX Atilde Oslash -40
+KPX Atilde Otilde -40
+KPX Atilde Q -40
+KPX Atilde T -37
+KPX Atilde Tcaron -37
+KPX Atilde Tcommaaccent -37
+KPX Atilde U -50
+KPX Atilde Uacute -50
+KPX Atilde Ucircumflex -50
+KPX Atilde Udieresis -50
+KPX Atilde Ugrave -50
+KPX Atilde Uhungarumlaut -50
+KPX Atilde Umacron -50
+KPX Atilde Uogonek -50
+KPX Atilde Uring -50
+KPX Atilde V -105
+KPX Atilde W -95
+KPX Atilde Y -55
+KPX Atilde Yacute -55
+KPX Atilde Ydieresis -55
+KPX Atilde quoteright -37
+KPX Atilde u -20
+KPX Atilde uacute -20
+KPX Atilde ucircumflex -20
+KPX Atilde udieresis -20
+KPX Atilde ugrave -20
+KPX Atilde uhungarumlaut -20
+KPX Atilde umacron -20
+KPX Atilde uogonek -20
+KPX Atilde uring -20
+KPX Atilde v -55
+KPX Atilde w -55
+KPX Atilde y -55
+KPX Atilde yacute -55
+KPX Atilde ydieresis -55
+KPX B A -25
+KPX B Aacute -25
+KPX B Abreve -25
+KPX B Acircumflex -25
+KPX B Adieresis -25
+KPX B Agrave -25
+KPX B Amacron -25
+KPX B Aogonek -25
+KPX B Aring -25
+KPX B Atilde -25
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX D A -35
+KPX D Aacute -35
+KPX D Abreve -35
+KPX D Acircumflex -35
+KPX D Adieresis -35
+KPX D Agrave -35
+KPX D Amacron -35
+KPX D Aogonek -35
+KPX D Aring -35
+KPX D Atilde -35
+KPX D V -40
+KPX D W -40
+KPX D Y -40
+KPX D Yacute -40
+KPX D Ydieresis -40
+KPX Dcaron A -35
+KPX Dcaron Aacute -35
+KPX Dcaron Abreve -35
+KPX Dcaron Acircumflex -35
+KPX Dcaron Adieresis -35
+KPX Dcaron Agrave -35
+KPX Dcaron Amacron -35
+KPX Dcaron Aogonek -35
+KPX Dcaron Aring -35
+KPX Dcaron Atilde -35
+KPX Dcaron V -40
+KPX Dcaron W -40
+KPX Dcaron Y -40
+KPX Dcaron Yacute -40
+KPX Dcaron Ydieresis -40
+KPX Dcroat A -35
+KPX Dcroat Aacute -35
+KPX Dcroat Abreve -35
+KPX Dcroat Acircumflex -35
+KPX Dcroat Adieresis -35
+KPX Dcroat Agrave -35
+KPX Dcroat Amacron -35
+KPX Dcroat Aogonek -35
+KPX Dcroat Aring -35
+KPX Dcroat Atilde -35
+KPX Dcroat V -40
+KPX Dcroat W -40
+KPX Dcroat Y -40
+KPX Dcroat Yacute -40
+KPX Dcroat Ydieresis -40
+KPX F A -115
+KPX F Aacute -115
+KPX F Abreve -115
+KPX F Acircumflex -115
+KPX F Adieresis -115
+KPX F Agrave -115
+KPX F Amacron -115
+KPX F Aogonek -115
+KPX F Aring -115
+KPX F Atilde -115
+KPX F a -75
+KPX F aacute -75
+KPX F abreve -75
+KPX F acircumflex -75
+KPX F adieresis -75
+KPX F agrave -75
+KPX F amacron -75
+KPX F aogonek -75
+KPX F aring -75
+KPX F atilde -75
+KPX F comma -135
+KPX F e -75
+KPX F eacute -75
+KPX F ecaron -75
+KPX F ecircumflex -75
+KPX F edieresis -75
+KPX F edotaccent -75
+KPX F egrave -75
+KPX F emacron -75
+KPX F eogonek -75
+KPX F i -45
+KPX F iacute -45
+KPX F icircumflex -45
+KPX F idieresis -45
+KPX F igrave -45
+KPX F imacron -45
+KPX F iogonek -45
+KPX F o -105
+KPX F oacute -105
+KPX F ocircumflex -105
+KPX F odieresis -105
+KPX F ograve -105
+KPX F ohungarumlaut -105
+KPX F omacron -105
+KPX F oslash -105
+KPX F otilde -105
+KPX F period -135
+KPX F r -55
+KPX F racute -55
+KPX F rcaron -55
+KPX F rcommaaccent -55
+KPX J A -40
+KPX J Aacute -40
+KPX J Abreve -40
+KPX J Acircumflex -40
+KPX J Adieresis -40
+KPX J Agrave -40
+KPX J Amacron -40
+KPX J Aogonek -40
+KPX J Aring -40
+KPX J Atilde -40
+KPX J a -35
+KPX J aacute -35
+KPX J abreve -35
+KPX J acircumflex -35
+KPX J adieresis -35
+KPX J agrave -35
+KPX J amacron -35
+KPX J aogonek -35
+KPX J aring -35
+KPX J atilde -35
+KPX J comma -25
+KPX J e -25
+KPX J eacute -25
+KPX J ecaron -25
+KPX J ecircumflex -25
+KPX J edieresis -25
+KPX J edotaccent -25
+KPX J egrave -25
+KPX J emacron -25
+KPX J eogonek -25
+KPX J o -25
+KPX J oacute -25
+KPX J ocircumflex -25
+KPX J odieresis -25
+KPX J ograve -25
+KPX J ohungarumlaut -25
+KPX J omacron -25
+KPX J oslash -25
+KPX J otilde -25
+KPX J period -25
+KPX J u -35
+KPX J uacute -35
+KPX J ucircumflex -35
+KPX J udieresis -35
+KPX J ugrave -35
+KPX J uhungarumlaut -35
+KPX J umacron -35
+KPX J uogonek -35
+KPX J uring -35
+KPX K O -50
+KPX K Oacute -50
+KPX K Ocircumflex -50
+KPX K Odieresis -50
+KPX K Ograve -50
+KPX K Ohungarumlaut -50
+KPX K Omacron -50
+KPX K Oslash -50
+KPX K Otilde -50
+KPX K e -35
+KPX K eacute -35
+KPX K ecaron -35
+KPX K ecircumflex -35
+KPX K edieresis -35
+KPX K edotaccent -35
+KPX K egrave -35
+KPX K emacron -35
+KPX K eogonek -35
+KPX K o -40
+KPX K oacute -40
+KPX K ocircumflex -40
+KPX K odieresis -40
+KPX K ograve -40
+KPX K ohungarumlaut -40
+KPX K omacron -40
+KPX K oslash -40
+KPX K otilde -40
+KPX K u -40
+KPX K uacute -40
+KPX K ucircumflex -40
+KPX K udieresis -40
+KPX K ugrave -40
+KPX K uhungarumlaut -40
+KPX K umacron -40
+KPX K uogonek -40
+KPX K uring -40
+KPX K y -40
+KPX K yacute -40
+KPX K ydieresis -40
+KPX Kcommaaccent O -50
+KPX Kcommaaccent Oacute -50
+KPX Kcommaaccent Ocircumflex -50
+KPX Kcommaaccent Odieresis -50
+KPX Kcommaaccent Ograve -50
+KPX Kcommaaccent Ohungarumlaut -50
+KPX Kcommaaccent Omacron -50
+KPX Kcommaaccent Oslash -50
+KPX Kcommaaccent Otilde -50
+KPX Kcommaaccent e -35
+KPX Kcommaaccent eacute -35
+KPX Kcommaaccent ecaron -35
+KPX Kcommaaccent ecircumflex -35
+KPX Kcommaaccent edieresis -35
+KPX Kcommaaccent edotaccent -35
+KPX Kcommaaccent egrave -35
+KPX Kcommaaccent emacron -35
+KPX Kcommaaccent eogonek -35
+KPX Kcommaaccent o -40
+KPX Kcommaaccent oacute -40
+KPX Kcommaaccent ocircumflex -40
+KPX Kcommaaccent odieresis -40
+KPX Kcommaaccent ograve -40
+KPX Kcommaaccent ohungarumlaut -40
+KPX Kcommaaccent omacron -40
+KPX Kcommaaccent oslash -40
+KPX Kcommaaccent otilde -40
+KPX Kcommaaccent u -40
+KPX Kcommaaccent uacute -40
+KPX Kcommaaccent ucircumflex -40
+KPX Kcommaaccent udieresis -40
+KPX Kcommaaccent ugrave -40
+KPX Kcommaaccent uhungarumlaut -40
+KPX Kcommaaccent umacron -40
+KPX Kcommaaccent uogonek -40
+KPX Kcommaaccent uring -40
+KPX Kcommaaccent y -40
+KPX Kcommaaccent yacute -40
+KPX Kcommaaccent ydieresis -40
+KPX L T -20
+KPX L Tcaron -20
+KPX L Tcommaaccent -20
+KPX L V -55
+KPX L W -55
+KPX L Y -20
+KPX L Yacute -20
+KPX L Ydieresis -20
+KPX L quoteright -37
+KPX L y -30
+KPX L yacute -30
+KPX L ydieresis -30
+KPX Lacute T -20
+KPX Lacute Tcaron -20
+KPX Lacute Tcommaaccent -20
+KPX Lacute V -55
+KPX Lacute W -55
+KPX Lacute Y -20
+KPX Lacute Yacute -20
+KPX Lacute Ydieresis -20
+KPX Lacute quoteright -37
+KPX Lacute y -30
+KPX Lacute yacute -30
+KPX Lacute ydieresis -30
+KPX Lcommaaccent T -20
+KPX Lcommaaccent Tcaron -20
+KPX Lcommaaccent Tcommaaccent -20
+KPX Lcommaaccent V -55
+KPX Lcommaaccent W -55
+KPX Lcommaaccent Y -20
+KPX Lcommaaccent Yacute -20
+KPX Lcommaaccent Ydieresis -20
+KPX Lcommaaccent quoteright -37
+KPX Lcommaaccent y -30
+KPX Lcommaaccent yacute -30
+KPX Lcommaaccent ydieresis -30
+KPX Lslash T -20
+KPX Lslash Tcaron -20
+KPX Lslash Tcommaaccent -20
+KPX Lslash V -55
+KPX Lslash W -55
+KPX Lslash Y -20
+KPX Lslash Yacute -20
+KPX Lslash Ydieresis -20
+KPX Lslash quoteright -37
+KPX Lslash y -30
+KPX Lslash yacute -30
+KPX Lslash ydieresis -30
+KPX N A -27
+KPX N Aacute -27
+KPX N Abreve -27
+KPX N Acircumflex -27
+KPX N Adieresis -27
+KPX N Agrave -27
+KPX N Amacron -27
+KPX N Aogonek -27
+KPX N Aring -27
+KPX N Atilde -27
+KPX Nacute A -27
+KPX Nacute Aacute -27
+KPX Nacute Abreve -27
+KPX Nacute Acircumflex -27
+KPX Nacute Adieresis -27
+KPX Nacute Agrave -27
+KPX Nacute Amacron -27
+KPX Nacute Aogonek -27
+KPX Nacute Aring -27
+KPX Nacute Atilde -27
+KPX Ncaron A -27
+KPX Ncaron Aacute -27
+KPX Ncaron Abreve -27
+KPX Ncaron Acircumflex -27
+KPX Ncaron Adieresis -27
+KPX Ncaron Agrave -27
+KPX Ncaron Amacron -27
+KPX Ncaron Aogonek -27
+KPX Ncaron Aring -27
+KPX Ncaron Atilde -27
+KPX Ncommaaccent A -27
+KPX Ncommaaccent Aacute -27
+KPX Ncommaaccent Abreve -27
+KPX Ncommaaccent Acircumflex -27
+KPX Ncommaaccent Adieresis -27
+KPX Ncommaaccent Agrave -27
+KPX Ncommaaccent Amacron -27
+KPX Ncommaaccent Aogonek -27
+KPX Ncommaaccent Aring -27
+KPX Ncommaaccent Atilde -27
+KPX Ntilde A -27
+KPX Ntilde Aacute -27
+KPX Ntilde Abreve -27
+KPX Ntilde Acircumflex -27
+KPX Ntilde Adieresis -27
+KPX Ntilde Agrave -27
+KPX Ntilde Amacron -27
+KPX Ntilde Aogonek -27
+KPX Ntilde Aring -27
+KPX Ntilde Atilde -27
+KPX O A -55
+KPX O Aacute -55
+KPX O Abreve -55
+KPX O Acircumflex -55
+KPX O Adieresis -55
+KPX O Agrave -55
+KPX O Amacron -55
+KPX O Aogonek -55
+KPX O Aring -55
+KPX O Atilde -55
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -50
+KPX O X -40
+KPX O Y -50
+KPX O Yacute -50
+KPX O Ydieresis -50
+KPX Oacute A -55
+KPX Oacute Aacute -55
+KPX Oacute Abreve -55
+KPX Oacute Acircumflex -55
+KPX Oacute Adieresis -55
+KPX Oacute Agrave -55
+KPX Oacute Amacron -55
+KPX Oacute Aogonek -55
+KPX Oacute Aring -55
+KPX Oacute Atilde -55
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -50
+KPX Oacute X -40
+KPX Oacute Y -50
+KPX Oacute Yacute -50
+KPX Oacute Ydieresis -50
+KPX Ocircumflex A -55
+KPX Ocircumflex Aacute -55
+KPX Ocircumflex Abreve -55
+KPX Ocircumflex Acircumflex -55
+KPX Ocircumflex Adieresis -55
+KPX Ocircumflex Agrave -55
+KPX Ocircumflex Amacron -55
+KPX Ocircumflex Aogonek -55
+KPX Ocircumflex Aring -55
+KPX Ocircumflex Atilde -55
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -50
+KPX Ocircumflex X -40
+KPX Ocircumflex Y -50
+KPX Ocircumflex Yacute -50
+KPX Ocircumflex Ydieresis -50
+KPX Odieresis A -55
+KPX Odieresis Aacute -55
+KPX Odieresis Abreve -55
+KPX Odieresis Acircumflex -55
+KPX Odieresis Adieresis -55
+KPX Odieresis Agrave -55
+KPX Odieresis Amacron -55
+KPX Odieresis Aogonek -55
+KPX Odieresis Aring -55
+KPX Odieresis Atilde -55
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -50
+KPX Odieresis X -40
+KPX Odieresis Y -50
+KPX Odieresis Yacute -50
+KPX Odieresis Ydieresis -50
+KPX Ograve A -55
+KPX Ograve Aacute -55
+KPX Ograve Abreve -55
+KPX Ograve Acircumflex -55
+KPX Ograve Adieresis -55
+KPX Ograve Agrave -55
+KPX Ograve Amacron -55
+KPX Ograve Aogonek -55
+KPX Ograve Aring -55
+KPX Ograve Atilde -55
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -50
+KPX Ograve X -40
+KPX Ograve Y -50
+KPX Ograve Yacute -50
+KPX Ograve Ydieresis -50
+KPX Ohungarumlaut A -55
+KPX Ohungarumlaut Aacute -55
+KPX Ohungarumlaut Abreve -55
+KPX Ohungarumlaut Acircumflex -55
+KPX Ohungarumlaut Adieresis -55
+KPX Ohungarumlaut Agrave -55
+KPX Ohungarumlaut Amacron -55
+KPX Ohungarumlaut Aogonek -55
+KPX Ohungarumlaut Aring -55
+KPX Ohungarumlaut Atilde -55
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -50
+KPX Ohungarumlaut X -40
+KPX Ohungarumlaut Y -50
+KPX Ohungarumlaut Yacute -50
+KPX Ohungarumlaut Ydieresis -50
+KPX Omacron A -55
+KPX Omacron Aacute -55
+KPX Omacron Abreve -55
+KPX Omacron Acircumflex -55
+KPX Omacron Adieresis -55
+KPX Omacron Agrave -55
+KPX Omacron Amacron -55
+KPX Omacron Aogonek -55
+KPX Omacron Aring -55
+KPX Omacron Atilde -55
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -50
+KPX Omacron X -40
+KPX Omacron Y -50
+KPX Omacron Yacute -50
+KPX Omacron Ydieresis -50
+KPX Oslash A -55
+KPX Oslash Aacute -55
+KPX Oslash Abreve -55
+KPX Oslash Acircumflex -55
+KPX Oslash Adieresis -55
+KPX Oslash Agrave -55
+KPX Oslash Amacron -55
+KPX Oslash Aogonek -55
+KPX Oslash Aring -55
+KPX Oslash Atilde -55
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -50
+KPX Oslash X -40
+KPX Oslash Y -50
+KPX Oslash Yacute -50
+KPX Oslash Ydieresis -50
+KPX Otilde A -55
+KPX Otilde Aacute -55
+KPX Otilde Abreve -55
+KPX Otilde Acircumflex -55
+KPX Otilde Adieresis -55
+KPX Otilde Agrave -55
+KPX Otilde Amacron -55
+KPX Otilde Aogonek -55
+KPX Otilde Aring -55
+KPX Otilde Atilde -55
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -50
+KPX Otilde X -40
+KPX Otilde Y -50
+KPX Otilde Yacute -50
+KPX Otilde Ydieresis -50
+KPX P A -90
+KPX P Aacute -90
+KPX P Abreve -90
+KPX P Acircumflex -90
+KPX P Adieresis -90
+KPX P Agrave -90
+KPX P Amacron -90
+KPX P Aogonek -90
+KPX P Aring -90
+KPX P Atilde -90
+KPX P a -80
+KPX P aacute -80
+KPX P abreve -80
+KPX P acircumflex -80
+KPX P adieresis -80
+KPX P agrave -80
+KPX P amacron -80
+KPX P aogonek -80
+KPX P aring -80
+KPX P atilde -80
+KPX P comma -135
+KPX P e -80
+KPX P eacute -80
+KPX P ecaron -80
+KPX P ecircumflex -80
+KPX P edieresis -80
+KPX P edotaccent -80
+KPX P egrave -80
+KPX P emacron -80
+KPX P eogonek -80
+KPX P o -80
+KPX P oacute -80
+KPX P ocircumflex -80
+KPX P odieresis -80
+KPX P ograve -80
+KPX P ohungarumlaut -80
+KPX P omacron -80
+KPX P oslash -80
+KPX P otilde -80
+KPX P period -135
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX R O -40
+KPX R Oacute -40
+KPX R Ocircumflex -40
+KPX R Odieresis -40
+KPX R Ograve -40
+KPX R Ohungarumlaut -40
+KPX R Omacron -40
+KPX R Oslash -40
+KPX R Otilde -40
+KPX R U -40
+KPX R Uacute -40
+KPX R Ucircumflex -40
+KPX R Udieresis -40
+KPX R Ugrave -40
+KPX R Uhungarumlaut -40
+KPX R Umacron -40
+KPX R Uogonek -40
+KPX R Uring -40
+KPX R V -18
+KPX R W -18
+KPX R Y -18
+KPX R Yacute -18
+KPX R Ydieresis -18
+KPX Racute O -40
+KPX Racute Oacute -40
+KPX Racute Ocircumflex -40
+KPX Racute Odieresis -40
+KPX Racute Ograve -40
+KPX Racute Ohungarumlaut -40
+KPX Racute Omacron -40
+KPX Racute Oslash -40
+KPX Racute Otilde -40
+KPX Racute U -40
+KPX Racute Uacute -40
+KPX Racute Ucircumflex -40
+KPX Racute Udieresis -40
+KPX Racute Ugrave -40
+KPX Racute Uhungarumlaut -40
+KPX Racute Umacron -40
+KPX Racute Uogonek -40
+KPX Racute Uring -40
+KPX Racute V -18
+KPX Racute W -18
+KPX Racute Y -18
+KPX Racute Yacute -18
+KPX Racute Ydieresis -18
+KPX Rcaron O -40
+KPX Rcaron Oacute -40
+KPX Rcaron Ocircumflex -40
+KPX Rcaron Odieresis -40
+KPX Rcaron Ograve -40
+KPX Rcaron Ohungarumlaut -40
+KPX Rcaron Omacron -40
+KPX Rcaron Oslash -40
+KPX Rcaron Otilde -40
+KPX Rcaron U -40
+KPX Rcaron Uacute -40
+KPX Rcaron Ucircumflex -40
+KPX Rcaron Udieresis -40
+KPX Rcaron Ugrave -40
+KPX Rcaron Uhungarumlaut -40
+KPX Rcaron Umacron -40
+KPX Rcaron Uogonek -40
+KPX Rcaron Uring -40
+KPX Rcaron V -18
+KPX Rcaron W -18
+KPX Rcaron Y -18
+KPX Rcaron Yacute -18
+KPX Rcaron Ydieresis -18
+KPX Rcommaaccent O -40
+KPX Rcommaaccent Oacute -40
+KPX Rcommaaccent Ocircumflex -40
+KPX Rcommaaccent Odieresis -40
+KPX Rcommaaccent Ograve -40
+KPX Rcommaaccent Ohungarumlaut -40
+KPX Rcommaaccent Omacron -40
+KPX Rcommaaccent Oslash -40
+KPX Rcommaaccent Otilde -40
+KPX Rcommaaccent U -40
+KPX Rcommaaccent Uacute -40
+KPX Rcommaaccent Ucircumflex -40
+KPX Rcommaaccent Udieresis -40
+KPX Rcommaaccent Ugrave -40
+KPX Rcommaaccent Uhungarumlaut -40
+KPX Rcommaaccent Umacron -40
+KPX Rcommaaccent Uogonek -40
+KPX Rcommaaccent Uring -40
+KPX Rcommaaccent V -18
+KPX Rcommaaccent W -18
+KPX Rcommaaccent Y -18
+KPX Rcommaaccent Yacute -18
+KPX Rcommaaccent Ydieresis -18
+KPX T A -50
+KPX T Aacute -50
+KPX T Abreve -50
+KPX T Acircumflex -50
+KPX T Adieresis -50
+KPX T Agrave -50
+KPX T Amacron -50
+KPX T Aogonek -50
+KPX T Aring -50
+KPX T Atilde -50
+KPX T O -18
+KPX T Oacute -18
+KPX T Ocircumflex -18
+KPX T Odieresis -18
+KPX T Ograve -18
+KPX T Ohungarumlaut -18
+KPX T Omacron -18
+KPX T Oslash -18
+KPX T Otilde -18
+KPX T a -92
+KPX T aacute -92
+KPX T abreve -92
+KPX T acircumflex -92
+KPX T adieresis -92
+KPX T agrave -92
+KPX T amacron -92
+KPX T aogonek -92
+KPX T aring -92
+KPX T atilde -92
+KPX T colon -55
+KPX T comma -74
+KPX T e -92
+KPX T eacute -92
+KPX T ecaron -92
+KPX T ecircumflex -52
+KPX T edieresis -52
+KPX T edotaccent -92
+KPX T egrave -52
+KPX T emacron -52
+KPX T eogonek -92
+KPX T hyphen -74
+KPX T i -55
+KPX T iacute -55
+KPX T iogonek -55
+KPX T o -92
+KPX T oacute -92
+KPX T ocircumflex -92
+KPX T odieresis -92
+KPX T ograve -92
+KPX T ohungarumlaut -92
+KPX T omacron -92
+KPX T oslash -92
+KPX T otilde -92
+KPX T period -74
+KPX T r -55
+KPX T racute -55
+KPX T rcaron -55
+KPX T rcommaaccent -55
+KPX T semicolon -65
+KPX T u -55
+KPX T uacute -55
+KPX T ucircumflex -55
+KPX T udieresis -55
+KPX T ugrave -55
+KPX T uhungarumlaut -55
+KPX T umacron -55
+KPX T uogonek -55
+KPX T uring -55
+KPX T w -74
+KPX T y -74
+KPX T yacute -74
+KPX T ydieresis -34
+KPX Tcaron A -50
+KPX Tcaron Aacute -50
+KPX Tcaron Abreve -50
+KPX Tcaron Acircumflex -50
+KPX Tcaron Adieresis -50
+KPX Tcaron Agrave -50
+KPX Tcaron Amacron -50
+KPX Tcaron Aogonek -50
+KPX Tcaron Aring -50
+KPX Tcaron Atilde -50
+KPX Tcaron O -18
+KPX Tcaron Oacute -18
+KPX Tcaron Ocircumflex -18
+KPX Tcaron Odieresis -18
+KPX Tcaron Ograve -18
+KPX Tcaron Ohungarumlaut -18
+KPX Tcaron Omacron -18
+KPX Tcaron Oslash -18
+KPX Tcaron Otilde -18
+KPX Tcaron a -92
+KPX Tcaron aacute -92
+KPX Tcaron abreve -92
+KPX Tcaron acircumflex -92
+KPX Tcaron adieresis -92
+KPX Tcaron agrave -92
+KPX Tcaron amacron -92
+KPX Tcaron aogonek -92
+KPX Tcaron aring -92
+KPX Tcaron atilde -92
+KPX Tcaron colon -55
+KPX Tcaron comma -74
+KPX Tcaron e -92
+KPX Tcaron eacute -92
+KPX Tcaron ecaron -92
+KPX Tcaron ecircumflex -52
+KPX Tcaron edieresis -52
+KPX Tcaron edotaccent -92
+KPX Tcaron egrave -52
+KPX Tcaron emacron -52
+KPX Tcaron eogonek -92
+KPX Tcaron hyphen -74
+KPX Tcaron i -55
+KPX Tcaron iacute -55
+KPX Tcaron iogonek -55
+KPX Tcaron o -92
+KPX Tcaron oacute -92
+KPX Tcaron ocircumflex -92
+KPX Tcaron odieresis -92
+KPX Tcaron ograve -92
+KPX Tcaron ohungarumlaut -92
+KPX Tcaron omacron -92
+KPX Tcaron oslash -92
+KPX Tcaron otilde -92
+KPX Tcaron period -74
+KPX Tcaron r -55
+KPX Tcaron racute -55
+KPX Tcaron rcaron -55
+KPX Tcaron rcommaaccent -55
+KPX Tcaron semicolon -65
+KPX Tcaron u -55
+KPX Tcaron uacute -55
+KPX Tcaron ucircumflex -55
+KPX Tcaron udieresis -55
+KPX Tcaron ugrave -55
+KPX Tcaron uhungarumlaut -55
+KPX Tcaron umacron -55
+KPX Tcaron uogonek -55
+KPX Tcaron uring -55
+KPX Tcaron w -74
+KPX Tcaron y -74
+KPX Tcaron yacute -74
+KPX Tcaron ydieresis -34
+KPX Tcommaaccent A -50
+KPX Tcommaaccent Aacute -50
+KPX Tcommaaccent Abreve -50
+KPX Tcommaaccent Acircumflex -50
+KPX Tcommaaccent Adieresis -50
+KPX Tcommaaccent Agrave -50
+KPX Tcommaaccent Amacron -50
+KPX Tcommaaccent Aogonek -50
+KPX Tcommaaccent Aring -50
+KPX Tcommaaccent Atilde -50
+KPX Tcommaaccent O -18
+KPX Tcommaaccent Oacute -18
+KPX Tcommaaccent Ocircumflex -18
+KPX Tcommaaccent Odieresis -18
+KPX Tcommaaccent Ograve -18
+KPX Tcommaaccent Ohungarumlaut -18
+KPX Tcommaaccent Omacron -18
+KPX Tcommaaccent Oslash -18
+KPX Tcommaaccent Otilde -18
+KPX Tcommaaccent a -92
+KPX Tcommaaccent aacute -92
+KPX Tcommaaccent abreve -92
+KPX Tcommaaccent acircumflex -92
+KPX Tcommaaccent adieresis -92
+KPX Tcommaaccent agrave -92
+KPX Tcommaaccent amacron -92
+KPX Tcommaaccent aogonek -92
+KPX Tcommaaccent aring -92
+KPX Tcommaaccent atilde -92
+KPX Tcommaaccent colon -55
+KPX Tcommaaccent comma -74
+KPX Tcommaaccent e -92
+KPX Tcommaaccent eacute -92
+KPX Tcommaaccent ecaron -92
+KPX Tcommaaccent ecircumflex -52
+KPX Tcommaaccent edieresis -52
+KPX Tcommaaccent edotaccent -92
+KPX Tcommaaccent egrave -52
+KPX Tcommaaccent emacron -52
+KPX Tcommaaccent eogonek -92
+KPX Tcommaaccent hyphen -74
+KPX Tcommaaccent i -55
+KPX Tcommaaccent iacute -55
+KPX Tcommaaccent iogonek -55
+KPX Tcommaaccent o -92
+KPX Tcommaaccent oacute -92
+KPX Tcommaaccent ocircumflex -92
+KPX Tcommaaccent odieresis -92
+KPX Tcommaaccent ograve -92
+KPX Tcommaaccent ohungarumlaut -92
+KPX Tcommaaccent omacron -92
+KPX Tcommaaccent oslash -92
+KPX Tcommaaccent otilde -92
+KPX Tcommaaccent period -74
+KPX Tcommaaccent r -55
+KPX Tcommaaccent racute -55
+KPX Tcommaaccent rcaron -55
+KPX Tcommaaccent rcommaaccent -55
+KPX Tcommaaccent semicolon -65
+KPX Tcommaaccent u -55
+KPX Tcommaaccent uacute -55
+KPX Tcommaaccent ucircumflex -55
+KPX Tcommaaccent udieresis -55
+KPX Tcommaaccent ugrave -55
+KPX Tcommaaccent uhungarumlaut -55
+KPX Tcommaaccent umacron -55
+KPX Tcommaaccent uogonek -55
+KPX Tcommaaccent uring -55
+KPX Tcommaaccent w -74
+KPX Tcommaaccent y -74
+KPX Tcommaaccent yacute -74
+KPX Tcommaaccent ydieresis -34
+KPX U A -40
+KPX U Aacute -40
+KPX U Abreve -40
+KPX U Acircumflex -40
+KPX U Adieresis -40
+KPX U Agrave -40
+KPX U Amacron -40
+KPX U Aogonek -40
+KPX U Aring -40
+KPX U Atilde -40
+KPX U comma -25
+KPX U period -25
+KPX Uacute A -40
+KPX Uacute Aacute -40
+KPX Uacute Abreve -40
+KPX Uacute Acircumflex -40
+KPX Uacute Adieresis -40
+KPX Uacute Agrave -40
+KPX Uacute Amacron -40
+KPX Uacute Aogonek -40
+KPX Uacute Aring -40
+KPX Uacute Atilde -40
+KPX Uacute comma -25
+KPX Uacute period -25
+KPX Ucircumflex A -40
+KPX Ucircumflex Aacute -40
+KPX Ucircumflex Abreve -40
+KPX Ucircumflex Acircumflex -40
+KPX Ucircumflex Adieresis -40
+KPX Ucircumflex Agrave -40
+KPX Ucircumflex Amacron -40
+KPX Ucircumflex Aogonek -40
+KPX Ucircumflex Aring -40
+KPX Ucircumflex Atilde -40
+KPX Ucircumflex comma -25
+KPX Ucircumflex period -25
+KPX Udieresis A -40
+KPX Udieresis Aacute -40
+KPX Udieresis Abreve -40
+KPX Udieresis Acircumflex -40
+KPX Udieresis Adieresis -40
+KPX Udieresis Agrave -40
+KPX Udieresis Amacron -40
+KPX Udieresis Aogonek -40
+KPX Udieresis Aring -40
+KPX Udieresis Atilde -40
+KPX Udieresis comma -25
+KPX Udieresis period -25
+KPX Ugrave A -40
+KPX Ugrave Aacute -40
+KPX Ugrave Abreve -40
+KPX Ugrave Acircumflex -40
+KPX Ugrave Adieresis -40
+KPX Ugrave Agrave -40
+KPX Ugrave Amacron -40
+KPX Ugrave Aogonek -40
+KPX Ugrave Aring -40
+KPX Ugrave Atilde -40
+KPX Ugrave comma -25
+KPX Ugrave period -25
+KPX Uhungarumlaut A -40
+KPX Uhungarumlaut Aacute -40
+KPX Uhungarumlaut Abreve -40
+KPX Uhungarumlaut Acircumflex -40
+KPX Uhungarumlaut Adieresis -40
+KPX Uhungarumlaut Agrave -40
+KPX Uhungarumlaut Amacron -40
+KPX Uhungarumlaut Aogonek -40
+KPX Uhungarumlaut Aring -40
+KPX Uhungarumlaut Atilde -40
+KPX Uhungarumlaut comma -25
+KPX Uhungarumlaut period -25
+KPX Umacron A -40
+KPX Umacron Aacute -40
+KPX Umacron Abreve -40
+KPX Umacron Acircumflex -40
+KPX Umacron Adieresis -40
+KPX Umacron Agrave -40
+KPX Umacron Amacron -40
+KPX Umacron Aogonek -40
+KPX Umacron Aring -40
+KPX Umacron Atilde -40
+KPX Umacron comma -25
+KPX Umacron period -25
+KPX Uogonek A -40
+KPX Uogonek Aacute -40
+KPX Uogonek Abreve -40
+KPX Uogonek Acircumflex -40
+KPX Uogonek Adieresis -40
+KPX Uogonek Agrave -40
+KPX Uogonek Amacron -40
+KPX Uogonek Aogonek -40
+KPX Uogonek Aring -40
+KPX Uogonek Atilde -40
+KPX Uogonek comma -25
+KPX Uogonek period -25
+KPX Uring A -40
+KPX Uring Aacute -40
+KPX Uring Abreve -40
+KPX Uring Acircumflex -40
+KPX Uring Adieresis -40
+KPX Uring Agrave -40
+KPX Uring Amacron -40
+KPX Uring Aogonek -40
+KPX Uring Aring -40
+KPX Uring Atilde -40
+KPX Uring comma -25
+KPX Uring period -25
+KPX V A -60
+KPX V Aacute -60
+KPX V Abreve -60
+KPX V Acircumflex -60
+KPX V Adieresis -60
+KPX V Agrave -60
+KPX V Amacron -60
+KPX V Aogonek -60
+KPX V Aring -60
+KPX V Atilde -60
+KPX V O -30
+KPX V Oacute -30
+KPX V Ocircumflex -30
+KPX V Odieresis -30
+KPX V Ograve -30
+KPX V Ohungarumlaut -30
+KPX V Omacron -30
+KPX V Oslash -30
+KPX V Otilde -30
+KPX V a -111
+KPX V aacute -111
+KPX V abreve -111
+KPX V acircumflex -111
+KPX V adieresis -111
+KPX V agrave -111
+KPX V amacron -111
+KPX V aogonek -111
+KPX V aring -111
+KPX V atilde -111
+KPX V colon -65
+KPX V comma -129
+KPX V e -111
+KPX V eacute -111
+KPX V ecaron -111
+KPX V ecircumflex -111
+KPX V edieresis -71
+KPX V edotaccent -111
+KPX V egrave -71
+KPX V emacron -71
+KPX V eogonek -111
+KPX V hyphen -55
+KPX V i -74
+KPX V iacute -74
+KPX V icircumflex -34
+KPX V idieresis -34
+KPX V igrave -34
+KPX V imacron -34
+KPX V iogonek -74
+KPX V o -111
+KPX V oacute -111
+KPX V ocircumflex -111
+KPX V odieresis -111
+KPX V ograve -111
+KPX V ohungarumlaut -111
+KPX V omacron -111
+KPX V oslash -111
+KPX V otilde -111
+KPX V period -129
+KPX V semicolon -74
+KPX V u -74
+KPX V uacute -74
+KPX V ucircumflex -74
+KPX V udieresis -74
+KPX V ugrave -74
+KPX V uhungarumlaut -74
+KPX V umacron -74
+KPX V uogonek -74
+KPX V uring -74
+KPX W A -60
+KPX W Aacute -60
+KPX W Abreve -60
+KPX W Acircumflex -60
+KPX W Adieresis -60
+KPX W Agrave -60
+KPX W Amacron -60
+KPX W Aogonek -60
+KPX W Aring -60
+KPX W Atilde -60
+KPX W O -25
+KPX W Oacute -25
+KPX W Ocircumflex -25
+KPX W Odieresis -25
+KPX W Ograve -25
+KPX W Ohungarumlaut -25
+KPX W Omacron -25
+KPX W Oslash -25
+KPX W Otilde -25
+KPX W a -92
+KPX W aacute -92
+KPX W abreve -92
+KPX W acircumflex -92
+KPX W adieresis -92
+KPX W agrave -92
+KPX W amacron -92
+KPX W aogonek -92
+KPX W aring -92
+KPX W atilde -92
+KPX W colon -65
+KPX W comma -92
+KPX W e -92
+KPX W eacute -92
+KPX W ecaron -92
+KPX W ecircumflex -92
+KPX W edieresis -52
+KPX W edotaccent -92
+KPX W egrave -52
+KPX W emacron -52
+KPX W eogonek -92
+KPX W hyphen -37
+KPX W i -55
+KPX W iacute -55
+KPX W iogonek -55
+KPX W o -92
+KPX W oacute -92
+KPX W ocircumflex -92
+KPX W odieresis -92
+KPX W ograve -92
+KPX W ohungarumlaut -92
+KPX W omacron -92
+KPX W oslash -92
+KPX W otilde -92
+KPX W period -92
+KPX W semicolon -65
+KPX W u -55
+KPX W uacute -55
+KPX W ucircumflex -55
+KPX W udieresis -55
+KPX W ugrave -55
+KPX W uhungarumlaut -55
+KPX W umacron -55
+KPX W uogonek -55
+KPX W uring -55
+KPX W y -70
+KPX W yacute -70
+KPX W ydieresis -70
+KPX Y A -50
+KPX Y Aacute -50
+KPX Y Abreve -50
+KPX Y Acircumflex -50
+KPX Y Adieresis -50
+KPX Y Agrave -50
+KPX Y Amacron -50
+KPX Y Aogonek -50
+KPX Y Aring -50
+KPX Y Atilde -50
+KPX Y O -15
+KPX Y Oacute -15
+KPX Y Ocircumflex -15
+KPX Y Odieresis -15
+KPX Y Ograve -15
+KPX Y Ohungarumlaut -15
+KPX Y Omacron -15
+KPX Y Oslash -15
+KPX Y Otilde -15
+KPX Y a -92
+KPX Y aacute -92
+KPX Y abreve -92
+KPX Y acircumflex -92
+KPX Y adieresis -92
+KPX Y agrave -92
+KPX Y amacron -92
+KPX Y aogonek -92
+KPX Y aring -92
+KPX Y atilde -92
+KPX Y colon -65
+KPX Y comma -92
+KPX Y e -92
+KPX Y eacute -92
+KPX Y ecaron -92
+KPX Y ecircumflex -92
+KPX Y edieresis -52
+KPX Y edotaccent -92
+KPX Y egrave -52
+KPX Y emacron -52
+KPX Y eogonek -92
+KPX Y hyphen -74
+KPX Y i -74
+KPX Y iacute -74
+KPX Y icircumflex -34
+KPX Y idieresis -34
+KPX Y igrave -34
+KPX Y imacron -34
+KPX Y iogonek -74
+KPX Y o -92
+KPX Y oacute -92
+KPX Y ocircumflex -92
+KPX Y odieresis -92
+KPX Y ograve -92
+KPX Y ohungarumlaut -92
+KPX Y omacron -92
+KPX Y oslash -92
+KPX Y otilde -92
+KPX Y period -92
+KPX Y semicolon -65
+KPX Y u -92
+KPX Y uacute -92
+KPX Y ucircumflex -92
+KPX Y udieresis -92
+KPX Y ugrave -92
+KPX Y uhungarumlaut -92
+KPX Y umacron -92
+KPX Y uogonek -92
+KPX Y uring -92
+KPX Yacute A -50
+KPX Yacute Aacute -50
+KPX Yacute Abreve -50
+KPX Yacute Acircumflex -50
+KPX Yacute Adieresis -50
+KPX Yacute Agrave -50
+KPX Yacute Amacron -50
+KPX Yacute Aogonek -50
+KPX Yacute Aring -50
+KPX Yacute Atilde -50
+KPX Yacute O -15
+KPX Yacute Oacute -15
+KPX Yacute Ocircumflex -15
+KPX Yacute Odieresis -15
+KPX Yacute Ograve -15
+KPX Yacute Ohungarumlaut -15
+KPX Yacute Omacron -15
+KPX Yacute Oslash -15
+KPX Yacute Otilde -15
+KPX Yacute a -92
+KPX Yacute aacute -92
+KPX Yacute abreve -92
+KPX Yacute acircumflex -92
+KPX Yacute adieresis -92
+KPX Yacute agrave -92
+KPX Yacute amacron -92
+KPX Yacute aogonek -92
+KPX Yacute aring -92
+KPX Yacute atilde -92
+KPX Yacute colon -65
+KPX Yacute comma -92
+KPX Yacute e -92
+KPX Yacute eacute -92
+KPX Yacute ecaron -92
+KPX Yacute ecircumflex -92
+KPX Yacute edieresis -52
+KPX Yacute edotaccent -92
+KPX Yacute egrave -52
+KPX Yacute emacron -52
+KPX Yacute eogonek -92
+KPX Yacute hyphen -74
+KPX Yacute i -74
+KPX Yacute iacute -74
+KPX Yacute icircumflex -34
+KPX Yacute idieresis -34
+KPX Yacute igrave -34
+KPX Yacute imacron -34
+KPX Yacute iogonek -74
+KPX Yacute o -92
+KPX Yacute oacute -92
+KPX Yacute ocircumflex -92
+KPX Yacute odieresis -92
+KPX Yacute ograve -92
+KPX Yacute ohungarumlaut -92
+KPX Yacute omacron -92
+KPX Yacute oslash -92
+KPX Yacute otilde -92
+KPX Yacute period -92
+KPX Yacute semicolon -65
+KPX Yacute u -92
+KPX Yacute uacute -92
+KPX Yacute ucircumflex -92
+KPX Yacute udieresis -92
+KPX Yacute ugrave -92
+KPX Yacute uhungarumlaut -92
+KPX Yacute umacron -92
+KPX Yacute uogonek -92
+KPX Yacute uring -92
+KPX Ydieresis A -50
+KPX Ydieresis Aacute -50
+KPX Ydieresis Abreve -50
+KPX Ydieresis Acircumflex -50
+KPX Ydieresis Adieresis -50
+KPX Ydieresis Agrave -50
+KPX Ydieresis Amacron -50
+KPX Ydieresis Aogonek -50
+KPX Ydieresis Aring -50
+KPX Ydieresis Atilde -50
+KPX Ydieresis O -15
+KPX Ydieresis Oacute -15
+KPX Ydieresis Ocircumflex -15
+KPX Ydieresis Odieresis -15
+KPX Ydieresis Ograve -15
+KPX Ydieresis Ohungarumlaut -15
+KPX Ydieresis Omacron -15
+KPX Ydieresis Oslash -15
+KPX Ydieresis Otilde -15
+KPX Ydieresis a -92
+KPX Ydieresis aacute -92
+KPX Ydieresis abreve -92
+KPX Ydieresis acircumflex -92
+KPX Ydieresis adieresis -92
+KPX Ydieresis agrave -92
+KPX Ydieresis amacron -92
+KPX Ydieresis aogonek -92
+KPX Ydieresis aring -92
+KPX Ydieresis atilde -92
+KPX Ydieresis colon -65
+KPX Ydieresis comma -92
+KPX Ydieresis e -92
+KPX Ydieresis eacute -92
+KPX Ydieresis ecaron -92
+KPX Ydieresis ecircumflex -92
+KPX Ydieresis edieresis -52
+KPX Ydieresis edotaccent -92
+KPX Ydieresis egrave -52
+KPX Ydieresis emacron -52
+KPX Ydieresis eogonek -92
+KPX Ydieresis hyphen -74
+KPX Ydieresis i -74
+KPX Ydieresis iacute -74
+KPX Ydieresis icircumflex -34
+KPX Ydieresis idieresis -34
+KPX Ydieresis igrave -34
+KPX Ydieresis imacron -34
+KPX Ydieresis iogonek -74
+KPX Ydieresis o -92
+KPX Ydieresis oacute -92
+KPX Ydieresis ocircumflex -92
+KPX Ydieresis odieresis -92
+KPX Ydieresis ograve -92
+KPX Ydieresis ohungarumlaut -92
+KPX Ydieresis omacron -92
+KPX Ydieresis oslash -92
+KPX Ydieresis otilde -92
+KPX Ydieresis period -92
+KPX Ydieresis semicolon -65
+KPX Ydieresis u -92
+KPX Ydieresis uacute -92
+KPX Ydieresis ucircumflex -92
+KPX Ydieresis udieresis -92
+KPX Ydieresis ugrave -92
+KPX Ydieresis uhungarumlaut -92
+KPX Ydieresis umacron -92
+KPX Ydieresis uogonek -92
+KPX Ydieresis uring -92
+KPX a g -10
+KPX a gbreve -10
+KPX a gcommaaccent -10
+KPX aacute g -10
+KPX aacute gbreve -10
+KPX aacute gcommaaccent -10
+KPX abreve g -10
+KPX abreve gbreve -10
+KPX abreve gcommaaccent -10
+KPX acircumflex g -10
+KPX acircumflex gbreve -10
+KPX acircumflex gcommaaccent -10
+KPX adieresis g -10
+KPX adieresis gbreve -10
+KPX adieresis gcommaaccent -10
+KPX agrave g -10
+KPX agrave gbreve -10
+KPX agrave gcommaaccent -10
+KPX amacron g -10
+KPX amacron gbreve -10
+KPX amacron gcommaaccent -10
+KPX aogonek g -10
+KPX aogonek gbreve -10
+KPX aogonek gcommaaccent -10
+KPX aring g -10
+KPX aring gbreve -10
+KPX aring gcommaaccent -10
+KPX atilde g -10
+KPX atilde gbreve -10
+KPX atilde gcommaaccent -10
+KPX b period -40
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX c h -15
+KPX c k -20
+KPX c kcommaaccent -20
+KPX cacute h -15
+KPX cacute k -20
+KPX cacute kcommaaccent -20
+KPX ccaron h -15
+KPX ccaron k -20
+KPX ccaron kcommaaccent -20
+KPX ccedilla h -15
+KPX ccedilla k -20
+KPX ccedilla kcommaaccent -20
+KPX comma quotedblright -140
+KPX comma quoteright -140
+KPX e comma -10
+KPX e g -40
+KPX e gbreve -40
+KPX e gcommaaccent -40
+KPX e period -15
+KPX e v -15
+KPX e w -15
+KPX e x -20
+KPX e y -30
+KPX e yacute -30
+KPX e ydieresis -30
+KPX eacute comma -10
+KPX eacute g -40
+KPX eacute gbreve -40
+KPX eacute gcommaaccent -40
+KPX eacute period -15
+KPX eacute v -15
+KPX eacute w -15
+KPX eacute x -20
+KPX eacute y -30
+KPX eacute yacute -30
+KPX eacute ydieresis -30
+KPX ecaron comma -10
+KPX ecaron g -40
+KPX ecaron gbreve -40
+KPX ecaron gcommaaccent -40
+KPX ecaron period -15
+KPX ecaron v -15
+KPX ecaron w -15
+KPX ecaron x -20
+KPX ecaron y -30
+KPX ecaron yacute -30
+KPX ecaron ydieresis -30
+KPX ecircumflex comma -10
+KPX ecircumflex g -40
+KPX ecircumflex gbreve -40
+KPX ecircumflex gcommaaccent -40
+KPX ecircumflex period -15
+KPX ecircumflex v -15
+KPX ecircumflex w -15
+KPX ecircumflex x -20
+KPX ecircumflex y -30
+KPX ecircumflex yacute -30
+KPX ecircumflex ydieresis -30
+KPX edieresis comma -10
+KPX edieresis g -40
+KPX edieresis gbreve -40
+KPX edieresis gcommaaccent -40
+KPX edieresis period -15
+KPX edieresis v -15
+KPX edieresis w -15
+KPX edieresis x -20
+KPX edieresis y -30
+KPX edieresis yacute -30
+KPX edieresis ydieresis -30
+KPX edotaccent comma -10
+KPX edotaccent g -40
+KPX edotaccent gbreve -40
+KPX edotaccent gcommaaccent -40
+KPX edotaccent period -15
+KPX edotaccent v -15
+KPX edotaccent w -15
+KPX edotaccent x -20
+KPX edotaccent y -30
+KPX edotaccent yacute -30
+KPX edotaccent ydieresis -30
+KPX egrave comma -10
+KPX egrave g -40
+KPX egrave gbreve -40
+KPX egrave gcommaaccent -40
+KPX egrave period -15
+KPX egrave v -15
+KPX egrave w -15
+KPX egrave x -20
+KPX egrave y -30
+KPX egrave yacute -30
+KPX egrave ydieresis -30
+KPX emacron comma -10
+KPX emacron g -40
+KPX emacron gbreve -40
+KPX emacron gcommaaccent -40
+KPX emacron period -15
+KPX emacron v -15
+KPX emacron w -15
+KPX emacron x -20
+KPX emacron y -30
+KPX emacron yacute -30
+KPX emacron ydieresis -30
+KPX eogonek comma -10
+KPX eogonek g -40
+KPX eogonek gbreve -40
+KPX eogonek gcommaaccent -40
+KPX eogonek period -15
+KPX eogonek v -15
+KPX eogonek w -15
+KPX eogonek x -20
+KPX eogonek y -30
+KPX eogonek yacute -30
+KPX eogonek ydieresis -30
+KPX f comma -10
+KPX f dotlessi -60
+KPX f f -18
+KPX f i -20
+KPX f iogonek -20
+KPX f period -15
+KPX f quoteright 92
+KPX g comma -10
+KPX g e -10
+KPX g eacute -10
+KPX g ecaron -10
+KPX g ecircumflex -10
+KPX g edieresis -10
+KPX g edotaccent -10
+KPX g egrave -10
+KPX g emacron -10
+KPX g eogonek -10
+KPX g g -10
+KPX g gbreve -10
+KPX g gcommaaccent -10
+KPX g period -15
+KPX gbreve comma -10
+KPX gbreve e -10
+KPX gbreve eacute -10
+KPX gbreve ecaron -10
+KPX gbreve ecircumflex -10
+KPX gbreve edieresis -10
+KPX gbreve edotaccent -10
+KPX gbreve egrave -10
+KPX gbreve emacron -10
+KPX gbreve eogonek -10
+KPX gbreve g -10
+KPX gbreve gbreve -10
+KPX gbreve gcommaaccent -10
+KPX gbreve period -15
+KPX gcommaaccent comma -10
+KPX gcommaaccent e -10
+KPX gcommaaccent eacute -10
+KPX gcommaaccent ecaron -10
+KPX gcommaaccent ecircumflex -10
+KPX gcommaaccent edieresis -10
+KPX gcommaaccent edotaccent -10
+KPX gcommaaccent egrave -10
+KPX gcommaaccent emacron -10
+KPX gcommaaccent eogonek -10
+KPX gcommaaccent g -10
+KPX gcommaaccent gbreve -10
+KPX gcommaaccent gcommaaccent -10
+KPX gcommaaccent period -15
+KPX k e -10
+KPX k eacute -10
+KPX k ecaron -10
+KPX k ecircumflex -10
+KPX k edieresis -10
+KPX k edotaccent -10
+KPX k egrave -10
+KPX k emacron -10
+KPX k eogonek -10
+KPX k o -10
+KPX k oacute -10
+KPX k ocircumflex -10
+KPX k odieresis -10
+KPX k ograve -10
+KPX k ohungarumlaut -10
+KPX k omacron -10
+KPX k oslash -10
+KPX k otilde -10
+KPX k y -10
+KPX k yacute -10
+KPX k ydieresis -10
+KPX kcommaaccent e -10
+KPX kcommaaccent eacute -10
+KPX kcommaaccent ecaron -10
+KPX kcommaaccent ecircumflex -10
+KPX kcommaaccent edieresis -10
+KPX kcommaaccent edotaccent -10
+KPX kcommaaccent egrave -10
+KPX kcommaaccent emacron -10
+KPX kcommaaccent eogonek -10
+KPX kcommaaccent o -10
+KPX kcommaaccent oacute -10
+KPX kcommaaccent ocircumflex -10
+KPX kcommaaccent odieresis -10
+KPX kcommaaccent ograve -10
+KPX kcommaaccent ohungarumlaut -10
+KPX kcommaaccent omacron -10
+KPX kcommaaccent oslash -10
+KPX kcommaaccent otilde -10
+KPX kcommaaccent y -10
+KPX kcommaaccent yacute -10
+KPX kcommaaccent ydieresis -10
+KPX n v -40
+KPX nacute v -40
+KPX ncaron v -40
+KPX ncommaaccent v -40
+KPX ntilde v -40
+KPX o g -10
+KPX o gbreve -10
+KPX o gcommaaccent -10
+KPX o v -10
+KPX oacute g -10
+KPX oacute gbreve -10
+KPX oacute gcommaaccent -10
+KPX oacute v -10
+KPX ocircumflex g -10
+KPX ocircumflex gbreve -10
+KPX ocircumflex gcommaaccent -10
+KPX ocircumflex v -10
+KPX odieresis g -10
+KPX odieresis gbreve -10
+KPX odieresis gcommaaccent -10
+KPX odieresis v -10
+KPX ograve g -10
+KPX ograve gbreve -10
+KPX ograve gcommaaccent -10
+KPX ograve v -10
+KPX ohungarumlaut g -10
+KPX ohungarumlaut gbreve -10
+KPX ohungarumlaut gcommaaccent -10
+KPX ohungarumlaut v -10
+KPX omacron g -10
+KPX omacron gbreve -10
+KPX omacron gcommaaccent -10
+KPX omacron v -10
+KPX oslash g -10
+KPX oslash gbreve -10
+KPX oslash gcommaaccent -10
+KPX oslash v -10
+KPX otilde g -10
+KPX otilde gbreve -10
+KPX otilde gcommaaccent -10
+KPX otilde v -10
+KPX period quotedblright -140
+KPX period quoteright -140
+KPX quoteleft quoteleft -111
+KPX quoteright d -25
+KPX quoteright dcroat -25
+KPX quoteright quoteright -111
+KPX quoteright r -25
+KPX quoteright racute -25
+KPX quoteright rcaron -25
+KPX quoteright rcommaaccent -25
+KPX quoteright s -40
+KPX quoteright sacute -40
+KPX quoteright scaron -40
+KPX quoteright scedilla -40
+KPX quoteright scommaaccent -40
+KPX quoteright space -111
+KPX quoteright t -30
+KPX quoteright tcommaaccent -30
+KPX quoteright v -10
+KPX r a -15
+KPX r aacute -15
+KPX r abreve -15
+KPX r acircumflex -15
+KPX r adieresis -15
+KPX r agrave -15
+KPX r amacron -15
+KPX r aogonek -15
+KPX r aring -15
+KPX r atilde -15
+KPX r c -37
+KPX r cacute -37
+KPX r ccaron -37
+KPX r ccedilla -37
+KPX r comma -111
+KPX r d -37
+KPX r dcroat -37
+KPX r e -37
+KPX r eacute -37
+KPX r ecaron -37
+KPX r ecircumflex -37
+KPX r edieresis -37
+KPX r edotaccent -37
+KPX r egrave -37
+KPX r emacron -37
+KPX r eogonek -37
+KPX r g -37
+KPX r gbreve -37
+KPX r gcommaaccent -37
+KPX r hyphen -20
+KPX r o -45
+KPX r oacute -45
+KPX r ocircumflex -45
+KPX r odieresis -45
+KPX r ograve -45
+KPX r ohungarumlaut -45
+KPX r omacron -45
+KPX r oslash -45
+KPX r otilde -45
+KPX r period -111
+KPX r q -37
+KPX r s -10
+KPX r sacute -10
+KPX r scaron -10
+KPX r scedilla -10
+KPX r scommaaccent -10
+KPX racute a -15
+KPX racute aacute -15
+KPX racute abreve -15
+KPX racute acircumflex -15
+KPX racute adieresis -15
+KPX racute agrave -15
+KPX racute amacron -15
+KPX racute aogonek -15
+KPX racute aring -15
+KPX racute atilde -15
+KPX racute c -37
+KPX racute cacute -37
+KPX racute ccaron -37
+KPX racute ccedilla -37
+KPX racute comma -111
+KPX racute d -37
+KPX racute dcroat -37
+KPX racute e -37
+KPX racute eacute -37
+KPX racute ecaron -37
+KPX racute ecircumflex -37
+KPX racute edieresis -37
+KPX racute edotaccent -37
+KPX racute egrave -37
+KPX racute emacron -37
+KPX racute eogonek -37
+KPX racute g -37
+KPX racute gbreve -37
+KPX racute gcommaaccent -37
+KPX racute hyphen -20
+KPX racute o -45
+KPX racute oacute -45
+KPX racute ocircumflex -45
+KPX racute odieresis -45
+KPX racute ograve -45
+KPX racute ohungarumlaut -45
+KPX racute omacron -45
+KPX racute oslash -45
+KPX racute otilde -45
+KPX racute period -111
+KPX racute q -37
+KPX racute s -10
+KPX racute sacute -10
+KPX racute scaron -10
+KPX racute scedilla -10
+KPX racute scommaaccent -10
+KPX rcaron a -15
+KPX rcaron aacute -15
+KPX rcaron abreve -15
+KPX rcaron acircumflex -15
+KPX rcaron adieresis -15
+KPX rcaron agrave -15
+KPX rcaron amacron -15
+KPX rcaron aogonek -15
+KPX rcaron aring -15
+KPX rcaron atilde -15
+KPX rcaron c -37
+KPX rcaron cacute -37
+KPX rcaron ccaron -37
+KPX rcaron ccedilla -37
+KPX rcaron comma -111
+KPX rcaron d -37
+KPX rcaron dcroat -37
+KPX rcaron e -37
+KPX rcaron eacute -37
+KPX rcaron ecaron -37
+KPX rcaron ecircumflex -37
+KPX rcaron edieresis -37
+KPX rcaron edotaccent -37
+KPX rcaron egrave -37
+KPX rcaron emacron -37
+KPX rcaron eogonek -37
+KPX rcaron g -37
+KPX rcaron gbreve -37
+KPX rcaron gcommaaccent -37
+KPX rcaron hyphen -20
+KPX rcaron o -45
+KPX rcaron oacute -45
+KPX rcaron ocircumflex -45
+KPX rcaron odieresis -45
+KPX rcaron ograve -45
+KPX rcaron ohungarumlaut -45
+KPX rcaron omacron -45
+KPX rcaron oslash -45
+KPX rcaron otilde -45
+KPX rcaron period -111
+KPX rcaron q -37
+KPX rcaron s -10
+KPX rcaron sacute -10
+KPX rcaron scaron -10
+KPX rcaron scedilla -10
+KPX rcaron scommaaccent -10
+KPX rcommaaccent a -15
+KPX rcommaaccent aacute -15
+KPX rcommaaccent abreve -15
+KPX rcommaaccent acircumflex -15
+KPX rcommaaccent adieresis -15
+KPX rcommaaccent agrave -15
+KPX rcommaaccent amacron -15
+KPX rcommaaccent aogonek -15
+KPX rcommaaccent aring -15
+KPX rcommaaccent atilde -15
+KPX rcommaaccent c -37
+KPX rcommaaccent cacute -37
+KPX rcommaaccent ccaron -37
+KPX rcommaaccent ccedilla -37
+KPX rcommaaccent comma -111
+KPX rcommaaccent d -37
+KPX rcommaaccent dcroat -37
+KPX rcommaaccent e -37
+KPX rcommaaccent eacute -37
+KPX rcommaaccent ecaron -37
+KPX rcommaaccent ecircumflex -37
+KPX rcommaaccent edieresis -37
+KPX rcommaaccent edotaccent -37
+KPX rcommaaccent egrave -37
+KPX rcommaaccent emacron -37
+KPX rcommaaccent eogonek -37
+KPX rcommaaccent g -37
+KPX rcommaaccent gbreve -37
+KPX rcommaaccent gcommaaccent -37
+KPX rcommaaccent hyphen -20
+KPX rcommaaccent o -45
+KPX rcommaaccent oacute -45
+KPX rcommaaccent ocircumflex -45
+KPX rcommaaccent odieresis -45
+KPX rcommaaccent ograve -45
+KPX rcommaaccent ohungarumlaut -45
+KPX rcommaaccent omacron -45
+KPX rcommaaccent oslash -45
+KPX rcommaaccent otilde -45
+KPX rcommaaccent period -111
+KPX rcommaaccent q -37
+KPX rcommaaccent s -10
+KPX rcommaaccent sacute -10
+KPX rcommaaccent scaron -10
+KPX rcommaaccent scedilla -10
+KPX rcommaaccent scommaaccent -10
+KPX space A -18
+KPX space Aacute -18
+KPX space Abreve -18
+KPX space Acircumflex -18
+KPX space Adieresis -18
+KPX space Agrave -18
+KPX space Amacron -18
+KPX space Aogonek -18
+KPX space Aring -18
+KPX space Atilde -18
+KPX space T -18
+KPX space Tcaron -18
+KPX space Tcommaaccent -18
+KPX space V -35
+KPX space W -40
+KPX space Y -75
+KPX space Yacute -75
+KPX space Ydieresis -75
+KPX v comma -74
+KPX v period -74
+KPX w comma -74
+KPX w period -74
+KPX y comma -55
+KPX y period -55
+KPX yacute comma -55
+KPX yacute period -55
+KPX ydieresis comma -55
+KPX ydieresis period -55
+EndKernPairs
+EndKernData
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Times-Roman.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Times-Roman.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/Times-Roman.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/Times-Roman.afm 2004-05-26 16:06:22.000000000 +0000
@@ -0,0 +1,2419 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu May 1 12:49:17 1997
+Comment UniqueID 43068
+Comment VMusage 43909 54934
+FontName Times-Roman
+FullName Times Roman
+FamilyName Times
+Weight Roman
+ItalicAngle 0
+IsFixedPitch false
+CharacterSet ExtendedRoman
+FontBBox -168 -218 1000 898
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1993, 1997 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 662
+XHeight 450
+Ascender 683
+Descender -217
+StdHW 28
+StdVW 84
+StartCharMetrics 315
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 130 -9 238 676 ;
+C 34 ; WX 408 ; N quotedbl ; B 77 431 331 676 ;
+C 35 ; WX 500 ; N numbersign ; B 5 0 496 662 ;
+C 36 ; WX 500 ; N dollar ; B 44 -87 457 727 ;
+C 37 ; WX 833 ; N percent ; B 61 -13 772 676 ;
+C 38 ; WX 778 ; N ampersand ; B 42 -13 750 676 ;
+C 39 ; WX 333 ; N quoteright ; B 79 433 218 676 ;
+C 40 ; WX 333 ; N parenleft ; B 48 -177 304 676 ;
+C 41 ; WX 333 ; N parenright ; B 29 -177 285 676 ;
+C 42 ; WX 500 ; N asterisk ; B 69 265 432 676 ;
+C 43 ; WX 564 ; N plus ; B 30 0 534 506 ;
+C 44 ; WX 250 ; N comma ; B 56 -141 195 102 ;
+C 45 ; WX 333 ; N hyphen ; B 39 194 285 257 ;
+C 46 ; WX 250 ; N period ; B 70 -11 181 100 ;
+C 47 ; WX 278 ; N slash ; B -9 -14 287 676 ;
+C 48 ; WX 500 ; N zero ; B 24 -14 476 676 ;
+C 49 ; WX 500 ; N one ; B 111 0 394 676 ;
+C 50 ; WX 500 ; N two ; B 30 0 475 676 ;
+C 51 ; WX 500 ; N three ; B 43 -14 431 676 ;
+C 52 ; WX 500 ; N four ; B 12 0 472 676 ;
+C 53 ; WX 500 ; N five ; B 32 -14 438 688 ;
+C 54 ; WX 500 ; N six ; B 34 -14 468 684 ;
+C 55 ; WX 500 ; N seven ; B 20 -8 449 662 ;
+C 56 ; WX 500 ; N eight ; B 56 -14 445 676 ;
+C 57 ; WX 500 ; N nine ; B 30 -22 459 676 ;
+C 58 ; WX 278 ; N colon ; B 81 -11 192 459 ;
+C 59 ; WX 278 ; N semicolon ; B 80 -141 219 459 ;
+C 60 ; WX 564 ; N less ; B 28 -8 536 514 ;
+C 61 ; WX 564 ; N equal ; B 30 120 534 386 ;
+C 62 ; WX 564 ; N greater ; B 28 -8 536 514 ;
+C 63 ; WX 444 ; N question ; B 68 -8 414 676 ;
+C 64 ; WX 921 ; N at ; B 116 -14 809 676 ;
+C 65 ; WX 722 ; N A ; B 15 0 706 674 ;
+C 66 ; WX 667 ; N B ; B 17 0 593 662 ;
+C 67 ; WX 667 ; N C ; B 28 -14 633 676 ;
+C 68 ; WX 722 ; N D ; B 16 0 685 662 ;
+C 69 ; WX 611 ; N E ; B 12 0 597 662 ;
+C 70 ; WX 556 ; N F ; B 12 0 546 662 ;
+C 71 ; WX 722 ; N G ; B 32 -14 709 676 ;
+C 72 ; WX 722 ; N H ; B 19 0 702 662 ;
+C 73 ; WX 333 ; N I ; B 18 0 315 662 ;
+C 74 ; WX 389 ; N J ; B 10 -14 370 662 ;
+C 75 ; WX 722 ; N K ; B 34 0 723 662 ;
+C 76 ; WX 611 ; N L ; B 12 0 598 662 ;
+C 77 ; WX 889 ; N M ; B 12 0 863 662 ;
+C 78 ; WX 722 ; N N ; B 12 -11 707 662 ;
+C 79 ; WX 722 ; N O ; B 34 -14 688 676 ;
+C 80 ; WX 556 ; N P ; B 16 0 542 662 ;
+C 81 ; WX 722 ; N Q ; B 34 -178 701 676 ;
+C 82 ; WX 667 ; N R ; B 17 0 659 662 ;
+C 83 ; WX 556 ; N S ; B 42 -14 491 676 ;
+C 84 ; WX 611 ; N T ; B 17 0 593 662 ;
+C 85 ; WX 722 ; N U ; B 14 -14 705 662 ;
+C 86 ; WX 722 ; N V ; B 16 -11 697 662 ;
+C 87 ; WX 944 ; N W ; B 5 -11 932 662 ;
+C 88 ; WX 722 ; N X ; B 10 0 704 662 ;
+C 89 ; WX 722 ; N Y ; B 22 0 703 662 ;
+C 90 ; WX 611 ; N Z ; B 9 0 597 662 ;
+C 91 ; WX 333 ; N bracketleft ; B 88 -156 299 662 ;
+C 92 ; WX 278 ; N backslash ; B -9 -14 287 676 ;
+C 93 ; WX 333 ; N bracketright ; B 34 -156 245 662 ;
+C 94 ; WX 469 ; N asciicircum ; B 24 297 446 662 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 333 ; N quoteleft ; B 115 433 254 676 ;
+C 97 ; WX 444 ; N a ; B 37 -10 442 460 ;
+C 98 ; WX 500 ; N b ; B 3 -10 468 683 ;
+C 99 ; WX 444 ; N c ; B 25 -10 412 460 ;
+C 100 ; WX 500 ; N d ; B 27 -10 491 683 ;
+C 101 ; WX 444 ; N e ; B 25 -10 424 460 ;
+C 102 ; WX 333 ; N f ; B 20 0 383 683 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B 28 -218 470 460 ;
+C 104 ; WX 500 ; N h ; B 9 0 487 683 ;
+C 105 ; WX 278 ; N i ; B 16 0 253 683 ;
+C 106 ; WX 278 ; N j ; B -70 -218 194 683 ;
+C 107 ; WX 500 ; N k ; B 7 0 505 683 ;
+C 108 ; WX 278 ; N l ; B 19 0 257 683 ;
+C 109 ; WX 778 ; N m ; B 16 0 775 460 ;
+C 110 ; WX 500 ; N n ; B 16 0 485 460 ;
+C 111 ; WX 500 ; N o ; B 29 -10 470 460 ;
+C 112 ; WX 500 ; N p ; B 5 -217 470 460 ;
+C 113 ; WX 500 ; N q ; B 24 -217 488 460 ;
+C 114 ; WX 333 ; N r ; B 5 0 335 460 ;
+C 115 ; WX 389 ; N s ; B 51 -10 348 460 ;
+C 116 ; WX 278 ; N t ; B 13 -10 279 579 ;
+C 117 ; WX 500 ; N u ; B 9 -10 479 450 ;
+C 118 ; WX 500 ; N v ; B 19 -14 477 450 ;
+C 119 ; WX 722 ; N w ; B 21 -14 694 450 ;
+C 120 ; WX 500 ; N x ; B 17 0 479 450 ;
+C 121 ; WX 500 ; N y ; B 14 -218 475 450 ;
+C 122 ; WX 444 ; N z ; B 27 0 418 450 ;
+C 123 ; WX 480 ; N braceleft ; B 100 -181 350 680 ;
+C 124 ; WX 200 ; N bar ; B 67 -218 133 782 ;
+C 125 ; WX 480 ; N braceright ; B 130 -181 380 680 ;
+C 126 ; WX 541 ; N asciitilde ; B 40 183 502 323 ;
+C 161 ; WX 333 ; N exclamdown ; B 97 -218 205 467 ;
+C 162 ; WX 500 ; N cent ; B 53 -138 448 579 ;
+C 163 ; WX 500 ; N sterling ; B 12 -8 490 676 ;
+C 164 ; WX 167 ; N fraction ; B -168 -14 331 676 ;
+C 165 ; WX 500 ; N yen ; B -53 0 512 662 ;
+C 166 ; WX 500 ; N florin ; B 7 -189 490 676 ;
+C 167 ; WX 500 ; N section ; B 70 -148 426 676 ;
+C 168 ; WX 500 ; N currency ; B -22 58 522 602 ;
+C 169 ; WX 180 ; N quotesingle ; B 48 431 133 676 ;
+C 170 ; WX 444 ; N quotedblleft ; B 43 433 414 676 ;
+C 171 ; WX 500 ; N guillemotleft ; B 42 33 456 416 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 63 33 285 416 ;
+C 173 ; WX 333 ; N guilsinglright ; B 48 33 270 416 ;
+C 174 ; WX 556 ; N fi ; B 31 0 521 683 ;
+C 175 ; WX 556 ; N fl ; B 32 0 521 683 ;
+C 177 ; WX 500 ; N endash ; B 0 201 500 250 ;
+C 178 ; WX 500 ; N dagger ; B 59 -149 442 676 ;
+C 179 ; WX 500 ; N daggerdbl ; B 58 -153 442 676 ;
+C 180 ; WX 250 ; N periodcentered ; B 70 199 181 310 ;
+C 182 ; WX 453 ; N paragraph ; B -22 -154 450 662 ;
+C 183 ; WX 350 ; N bullet ; B 40 196 310 466 ;
+C 184 ; WX 333 ; N quotesinglbase ; B 79 -141 218 102 ;
+C 185 ; WX 444 ; N quotedblbase ; B 45 -141 416 102 ;
+C 186 ; WX 444 ; N quotedblright ; B 30 433 401 676 ;
+C 187 ; WX 500 ; N guillemotright ; B 44 33 458 416 ;
+C 188 ; WX 1000 ; N ellipsis ; B 111 -11 888 100 ;
+C 189 ; WX 1000 ; N perthousand ; B 7 -19 994 706 ;
+C 191 ; WX 444 ; N questiondown ; B 30 -218 376 466 ;
+C 193 ; WX 333 ; N grave ; B 19 507 242 678 ;
+C 194 ; WX 333 ; N acute ; B 93 507 317 678 ;
+C 195 ; WX 333 ; N circumflex ; B 11 507 322 674 ;
+C 196 ; WX 333 ; N tilde ; B 1 532 331 638 ;
+C 197 ; WX 333 ; N macron ; B 11 547 322 601 ;
+C 198 ; WX 333 ; N breve ; B 26 507 307 664 ;
+C 199 ; WX 333 ; N dotaccent ; B 118 581 216 681 ;
+C 200 ; WX 333 ; N dieresis ; B 18 581 315 681 ;
+C 202 ; WX 333 ; N ring ; B 67 512 266 711 ;
+C 203 ; WX 333 ; N cedilla ; B 52 -215 261 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B -3 507 377 678 ;
+C 206 ; WX 333 ; N ogonek ; B 62 -165 243 0 ;
+C 207 ; WX 333 ; N caron ; B 11 507 322 674 ;
+C 208 ; WX 1000 ; N emdash ; B 0 201 1000 250 ;
+C 225 ; WX 889 ; N AE ; B 0 0 863 662 ;
+C 227 ; WX 276 ; N ordfeminine ; B 4 394 270 676 ;
+C 232 ; WX 611 ; N Lslash ; B 12 0 598 662 ;
+C 233 ; WX 722 ; N Oslash ; B 34 -80 688 734 ;
+C 234 ; WX 889 ; N OE ; B 30 -6 885 668 ;
+C 235 ; WX 310 ; N ordmasculine ; B 6 394 304 676 ;
+C 241 ; WX 667 ; N ae ; B 38 -10 632 460 ;
+C 245 ; WX 278 ; N dotlessi ; B 16 0 253 460 ;
+C 248 ; WX 278 ; N lslash ; B 19 0 259 683 ;
+C 249 ; WX 500 ; N oslash ; B 29 -112 470 551 ;
+C 250 ; WX 722 ; N oe ; B 30 -10 690 460 ;
+C 251 ; WX 500 ; N germandbls ; B 12 -9 468 683 ;
+C -1 ; WX 333 ; N Idieresis ; B 18 0 315 835 ;
+C -1 ; WX 444 ; N eacute ; B 25 -10 424 678 ;
+C -1 ; WX 444 ; N abreve ; B 37 -10 442 664 ;
+C -1 ; WX 500 ; N uhungarumlaut ; B 9 -10 501 678 ;
+C -1 ; WX 444 ; N ecaron ; B 25 -10 424 674 ;
+C -1 ; WX 722 ; N Ydieresis ; B 22 0 703 835 ;
+C -1 ; WX 564 ; N divide ; B 30 -10 534 516 ;
+C -1 ; WX 722 ; N Yacute ; B 22 0 703 890 ;
+C -1 ; WX 722 ; N Acircumflex ; B 15 0 706 886 ;
+C -1 ; WX 444 ; N aacute ; B 37 -10 442 678 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 14 -14 705 886 ;
+C -1 ; WX 500 ; N yacute ; B 14 -218 475 678 ;
+C -1 ; WX 389 ; N scommaaccent ; B 51 -218 348 460 ;
+C -1 ; WX 444 ; N ecircumflex ; B 25 -10 424 674 ;
+C -1 ; WX 722 ; N Uring ; B 14 -14 705 898 ;
+C -1 ; WX 722 ; N Udieresis ; B 14 -14 705 835 ;
+C -1 ; WX 444 ; N aogonek ; B 37 -165 469 460 ;
+C -1 ; WX 722 ; N Uacute ; B 14 -14 705 890 ;
+C -1 ; WX 500 ; N uogonek ; B 9 -155 487 450 ;
+C -1 ; WX 611 ; N Edieresis ; B 12 0 597 835 ;
+C -1 ; WX 722 ; N Dcroat ; B 16 0 685 662 ;
+C -1 ; WX 250 ; N commaaccent ; B 59 -218 184 -50 ;
+C -1 ; WX 760 ; N copyright ; B 38 -14 722 676 ;
+C -1 ; WX 611 ; N Emacron ; B 12 0 597 813 ;
+C -1 ; WX 444 ; N ccaron ; B 25 -10 412 674 ;
+C -1 ; WX 444 ; N aring ; B 37 -10 442 711 ;
+C -1 ; WX 722 ; N Ncommaaccent ; B 12 -198 707 662 ;
+C -1 ; WX 278 ; N lacute ; B 19 0 290 890 ;
+C -1 ; WX 444 ; N agrave ; B 37 -10 442 678 ;
+C -1 ; WX 611 ; N Tcommaaccent ; B 17 -218 593 662 ;
+C -1 ; WX 667 ; N Cacute ; B 28 -14 633 890 ;
+C -1 ; WX 444 ; N atilde ; B 37 -10 442 638 ;
+C -1 ; WX 611 ; N Edotaccent ; B 12 0 597 835 ;
+C -1 ; WX 389 ; N scaron ; B 39 -10 350 674 ;
+C -1 ; WX 389 ; N scedilla ; B 51 -215 348 460 ;
+C -1 ; WX 278 ; N iacute ; B 16 0 290 678 ;
+C -1 ; WX 471 ; N lozenge ; B 13 0 459 724 ;
+C -1 ; WX 667 ; N Rcaron ; B 17 0 659 886 ;
+C -1 ; WX 722 ; N Gcommaaccent ; B 32 -218 709 676 ;
+C -1 ; WX 500 ; N ucircumflex ; B 9 -10 479 674 ;
+C -1 ; WX 444 ; N acircumflex ; B 37 -10 442 674 ;
+C -1 ; WX 722 ; N Amacron ; B 15 0 706 813 ;
+C -1 ; WX 333 ; N rcaron ; B 5 0 335 674 ;
+C -1 ; WX 444 ; N ccedilla ; B 25 -215 412 460 ;
+C -1 ; WX 611 ; N Zdotaccent ; B 9 0 597 835 ;
+C -1 ; WX 556 ; N Thorn ; B 16 0 542 662 ;
+C -1 ; WX 722 ; N Omacron ; B 34 -14 688 813 ;
+C -1 ; WX 667 ; N Racute ; B 17 0 659 890 ;
+C -1 ; WX 556 ; N Sacute ; B 42 -14 491 890 ;
+C -1 ; WX 588 ; N dcaron ; B 27 -10 589 695 ;
+C -1 ; WX 722 ; N Umacron ; B 14 -14 705 813 ;
+C -1 ; WX 500 ; N uring ; B 9 -10 479 711 ;
+C -1 ; WX 300 ; N threesuperior ; B 15 262 291 676 ;
+C -1 ; WX 722 ; N Ograve ; B 34 -14 688 890 ;
+C -1 ; WX 722 ; N Agrave ; B 15 0 706 890 ;
+C -1 ; WX 722 ; N Abreve ; B 15 0 706 876 ;
+C -1 ; WX 564 ; N multiply ; B 38 8 527 497 ;
+C -1 ; WX 500 ; N uacute ; B 9 -10 479 678 ;
+C -1 ; WX 611 ; N Tcaron ; B 17 0 593 886 ;
+C -1 ; WX 476 ; N partialdiff ; B 17 -38 459 710 ;
+C -1 ; WX 500 ; N ydieresis ; B 14 -218 475 623 ;
+C -1 ; WX 722 ; N Nacute ; B 12 -11 707 890 ;
+C -1 ; WX 278 ; N icircumflex ; B -16 0 295 674 ;
+C -1 ; WX 611 ; N Ecircumflex ; B 12 0 597 886 ;
+C -1 ; WX 444 ; N adieresis ; B 37 -10 442 623 ;
+C -1 ; WX 444 ; N edieresis ; B 25 -10 424 623 ;
+C -1 ; WX 444 ; N cacute ; B 25 -10 413 678 ;
+C -1 ; WX 500 ; N nacute ; B 16 0 485 678 ;
+C -1 ; WX 500 ; N umacron ; B 9 -10 479 601 ;
+C -1 ; WX 722 ; N Ncaron ; B 12 -11 707 886 ;
+C -1 ; WX 333 ; N Iacute ; B 18 0 317 890 ;
+C -1 ; WX 564 ; N plusminus ; B 30 0 534 506 ;
+C -1 ; WX 200 ; N brokenbar ; B 67 -143 133 707 ;
+C -1 ; WX 760 ; N registered ; B 38 -14 722 676 ;
+C -1 ; WX 722 ; N Gbreve ; B 32 -14 709 876 ;
+C -1 ; WX 333 ; N Idotaccent ; B 18 0 315 835 ;
+C -1 ; WX 600 ; N summation ; B 15 -10 585 706 ;
+C -1 ; WX 611 ; N Egrave ; B 12 0 597 890 ;
+C -1 ; WX 333 ; N racute ; B 5 0 335 678 ;
+C -1 ; WX 500 ; N omacron ; B 29 -10 470 601 ;
+C -1 ; WX 611 ; N Zacute ; B 9 0 597 890 ;
+C -1 ; WX 611 ; N Zcaron ; B 9 0 597 886 ;
+C -1 ; WX 549 ; N greaterequal ; B 26 0 523 666 ;
+C -1 ; WX 722 ; N Eth ; B 16 0 685 662 ;
+C -1 ; WX 667 ; N Ccedilla ; B 28 -215 633 676 ;
+C -1 ; WX 278 ; N lcommaaccent ; B 19 -218 257 683 ;
+C -1 ; WX 326 ; N tcaron ; B 13 -10 318 722 ;
+C -1 ; WX 444 ; N eogonek ; B 25 -165 424 460 ;
+C -1 ; WX 722 ; N Uogonek ; B 14 -165 705 662 ;
+C -1 ; WX 722 ; N Aacute ; B 15 0 706 890 ;
+C -1 ; WX 722 ; N Adieresis ; B 15 0 706 835 ;
+C -1 ; WX 444 ; N egrave ; B 25 -10 424 678 ;
+C -1 ; WX 444 ; N zacute ; B 27 0 418 678 ;
+C -1 ; WX 278 ; N iogonek ; B 16 -165 265 683 ;
+C -1 ; WX 722 ; N Oacute ; B 34 -14 688 890 ;
+C -1 ; WX 500 ; N oacute ; B 29 -10 470 678 ;
+C -1 ; WX 444 ; N amacron ; B 37 -10 442 601 ;
+C -1 ; WX 389 ; N sacute ; B 51 -10 348 678 ;
+C -1 ; WX 278 ; N idieresis ; B -9 0 288 623 ;
+C -1 ; WX 722 ; N Ocircumflex ; B 34 -14 688 886 ;
+C -1 ; WX 722 ; N Ugrave ; B 14 -14 705 890 ;
+C -1 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C -1 ; WX 500 ; N thorn ; B 5 -217 470 683 ;
+C -1 ; WX 300 ; N twosuperior ; B 1 270 296 676 ;
+C -1 ; WX 722 ; N Odieresis ; B 34 -14 688 835 ;
+C -1 ; WX 500 ; N mu ; B 36 -218 512 450 ;
+C -1 ; WX 278 ; N igrave ; B -8 0 253 678 ;
+C -1 ; WX 500 ; N ohungarumlaut ; B 29 -10 491 678 ;
+C -1 ; WX 611 ; N Eogonek ; B 12 -165 597 662 ;
+C -1 ; WX 500 ; N dcroat ; B 27 -10 500 683 ;
+C -1 ; WX 750 ; N threequarters ; B 15 -14 718 676 ;
+C -1 ; WX 556 ; N Scedilla ; B 42 -215 491 676 ;
+C -1 ; WX 344 ; N lcaron ; B 19 0 347 695 ;
+C -1 ; WX 722 ; N Kcommaaccent ; B 34 -198 723 662 ;
+C -1 ; WX 611 ; N Lacute ; B 12 0 598 890 ;
+C -1 ; WX 980 ; N trademark ; B 30 256 957 662 ;
+C -1 ; WX 444 ; N edotaccent ; B 25 -10 424 623 ;
+C -1 ; WX 333 ; N Igrave ; B 18 0 315 890 ;
+C -1 ; WX 333 ; N Imacron ; B 11 0 322 813 ;
+C -1 ; WX 611 ; N Lcaron ; B 12 0 598 676 ;
+C -1 ; WX 750 ; N onehalf ; B 31 -14 746 676 ;
+C -1 ; WX 549 ; N lessequal ; B 26 0 523 666 ;
+C -1 ; WX 500 ; N ocircumflex ; B 29 -10 470 674 ;
+C -1 ; WX 500 ; N ntilde ; B 16 0 485 638 ;
+C -1 ; WX 722 ; N Uhungarumlaut ; B 14 -14 705 890 ;
+C -1 ; WX 611 ; N Eacute ; B 12 0 597 890 ;
+C -1 ; WX 444 ; N emacron ; B 25 -10 424 601 ;
+C -1 ; WX 500 ; N gbreve ; B 28 -218 470 664 ;
+C -1 ; WX 750 ; N onequarter ; B 37 -14 718 676 ;
+C -1 ; WX 556 ; N Scaron ; B 42 -14 491 886 ;
+C -1 ; WX 556 ; N Scommaaccent ; B 42 -218 491 676 ;
+C -1 ; WX 722 ; N Ohungarumlaut ; B 34 -14 688 890 ;
+C -1 ; WX 400 ; N degree ; B 57 390 343 676 ;
+C -1 ; WX 500 ; N ograve ; B 29 -10 470 678 ;
+C -1 ; WX 667 ; N Ccaron ; B 28 -14 633 886 ;
+C -1 ; WX 500 ; N ugrave ; B 9 -10 479 678 ;
+C -1 ; WX 453 ; N radical ; B 2 -60 452 768 ;
+C -1 ; WX 722 ; N Dcaron ; B 16 0 685 886 ;
+C -1 ; WX 333 ; N rcommaaccent ; B 5 -218 335 460 ;
+C -1 ; WX 722 ; N Ntilde ; B 12 -11 707 850 ;
+C -1 ; WX 500 ; N otilde ; B 29 -10 470 638 ;
+C -1 ; WX 667 ; N Rcommaaccent ; B 17 -198 659 662 ;
+C -1 ; WX 611 ; N Lcommaaccent ; B 12 -218 598 662 ;
+C -1 ; WX 722 ; N Atilde ; B 15 0 706 850 ;
+C -1 ; WX 722 ; N Aogonek ; B 15 -165 738 674 ;
+C -1 ; WX 722 ; N Aring ; B 15 0 706 898 ;
+C -1 ; WX 722 ; N Otilde ; B 34 -14 688 850 ;
+C -1 ; WX 444 ; N zdotaccent ; B 27 0 418 623 ;
+C -1 ; WX 611 ; N Ecaron ; B 12 0 597 886 ;
+C -1 ; WX 333 ; N Iogonek ; B 18 -165 315 662 ;
+C -1 ; WX 500 ; N kcommaaccent ; B 7 -218 505 683 ;
+C -1 ; WX 564 ; N minus ; B 30 220 534 286 ;
+C -1 ; WX 333 ; N Icircumflex ; B 11 0 322 886 ;
+C -1 ; WX 500 ; N ncaron ; B 16 0 485 674 ;
+C -1 ; WX 278 ; N tcommaaccent ; B 13 -218 279 579 ;
+C -1 ; WX 564 ; N logicalnot ; B 30 108 534 386 ;
+C -1 ; WX 500 ; N odieresis ; B 29 -10 470 623 ;
+C -1 ; WX 500 ; N udieresis ; B 9 -10 479 623 ;
+C -1 ; WX 549 ; N notequal ; B 12 -31 537 547 ;
+C -1 ; WX 500 ; N gcommaaccent ; B 28 -218 470 749 ;
+C -1 ; WX 500 ; N eth ; B 29 -10 471 686 ;
+C -1 ; WX 444 ; N zcaron ; B 27 0 418 674 ;
+C -1 ; WX 500 ; N ncommaaccent ; B 16 -218 485 460 ;
+C -1 ; WX 300 ; N onesuperior ; B 57 270 248 676 ;
+C -1 ; WX 278 ; N imacron ; B 6 0 271 601 ;
+C -1 ; WX 500 ; N Euro ; B 0 0 0 0 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 2073
+KPX A C -40
+KPX A Cacute -40
+KPX A Ccaron -40
+KPX A Ccedilla -40
+KPX A G -40
+KPX A Gbreve -40
+KPX A Gcommaaccent -40
+KPX A O -55
+KPX A Oacute -55
+KPX A Ocircumflex -55
+KPX A Odieresis -55
+KPX A Ograve -55
+KPX A Ohungarumlaut -55
+KPX A Omacron -55
+KPX A Oslash -55
+KPX A Otilde -55
+KPX A Q -55
+KPX A T -111
+KPX A Tcaron -111
+KPX A Tcommaaccent -111
+KPX A U -55
+KPX A Uacute -55
+KPX A Ucircumflex -55
+KPX A Udieresis -55
+KPX A Ugrave -55
+KPX A Uhungarumlaut -55
+KPX A Umacron -55
+KPX A Uogonek -55
+KPX A Uring -55
+KPX A V -135
+KPX A W -90
+KPX A Y -105
+KPX A Yacute -105
+KPX A Ydieresis -105
+KPX A quoteright -111
+KPX A v -74
+KPX A w -92
+KPX A y -92
+KPX A yacute -92
+KPX A ydieresis -92
+KPX Aacute C -40
+KPX Aacute Cacute -40
+KPX Aacute Ccaron -40
+KPX Aacute Ccedilla -40
+KPX Aacute G -40
+KPX Aacute Gbreve -40
+KPX Aacute Gcommaaccent -40
+KPX Aacute O -55
+KPX Aacute Oacute -55
+KPX Aacute Ocircumflex -55
+KPX Aacute Odieresis -55
+KPX Aacute Ograve -55
+KPX Aacute Ohungarumlaut -55
+KPX Aacute Omacron -55
+KPX Aacute Oslash -55
+KPX Aacute Otilde -55
+KPX Aacute Q -55
+KPX Aacute T -111
+KPX Aacute Tcaron -111
+KPX Aacute Tcommaaccent -111
+KPX Aacute U -55
+KPX Aacute Uacute -55
+KPX Aacute Ucircumflex -55
+KPX Aacute Udieresis -55
+KPX Aacute Ugrave -55
+KPX Aacute Uhungarumlaut -55
+KPX Aacute Umacron -55
+KPX Aacute Uogonek -55
+KPX Aacute Uring -55
+KPX Aacute V -135
+KPX Aacute W -90
+KPX Aacute Y -105
+KPX Aacute Yacute -105
+KPX Aacute Ydieresis -105
+KPX Aacute quoteright -111
+KPX Aacute v -74
+KPX Aacute w -92
+KPX Aacute y -92
+KPX Aacute yacute -92
+KPX Aacute ydieresis -92
+KPX Abreve C -40
+KPX Abreve Cacute -40
+KPX Abreve Ccaron -40
+KPX Abreve Ccedilla -40
+KPX Abreve G -40
+KPX Abreve Gbreve -40
+KPX Abreve Gcommaaccent -40
+KPX Abreve O -55
+KPX Abreve Oacute -55
+KPX Abreve Ocircumflex -55
+KPX Abreve Odieresis -55
+KPX Abreve Ograve -55
+KPX Abreve Ohungarumlaut -55
+KPX Abreve Omacron -55
+KPX Abreve Oslash -55
+KPX Abreve Otilde -55
+KPX Abreve Q -55
+KPX Abreve T -111
+KPX Abreve Tcaron -111
+KPX Abreve Tcommaaccent -111
+KPX Abreve U -55
+KPX Abreve Uacute -55
+KPX Abreve Ucircumflex -55
+KPX Abreve Udieresis -55
+KPX Abreve Ugrave -55
+KPX Abreve Uhungarumlaut -55
+KPX Abreve Umacron -55
+KPX Abreve Uogonek -55
+KPX Abreve Uring -55
+KPX Abreve V -135
+KPX Abreve W -90
+KPX Abreve Y -105
+KPX Abreve Yacute -105
+KPX Abreve Ydieresis -105
+KPX Abreve quoteright -111
+KPX Abreve v -74
+KPX Abreve w -92
+KPX Abreve y -92
+KPX Abreve yacute -92
+KPX Abreve ydieresis -92
+KPX Acircumflex C -40
+KPX Acircumflex Cacute -40
+KPX Acircumflex Ccaron -40
+KPX Acircumflex Ccedilla -40
+KPX Acircumflex G -40
+KPX Acircumflex Gbreve -40
+KPX Acircumflex Gcommaaccent -40
+KPX Acircumflex O -55
+KPX Acircumflex Oacute -55
+KPX Acircumflex Ocircumflex -55
+KPX Acircumflex Odieresis -55
+KPX Acircumflex Ograve -55
+KPX Acircumflex Ohungarumlaut -55
+KPX Acircumflex Omacron -55
+KPX Acircumflex Oslash -55
+KPX Acircumflex Otilde -55
+KPX Acircumflex Q -55
+KPX Acircumflex T -111
+KPX Acircumflex Tcaron -111
+KPX Acircumflex Tcommaaccent -111
+KPX Acircumflex U -55
+KPX Acircumflex Uacute -55
+KPX Acircumflex Ucircumflex -55
+KPX Acircumflex Udieresis -55
+KPX Acircumflex Ugrave -55
+KPX Acircumflex Uhungarumlaut -55
+KPX Acircumflex Umacron -55
+KPX Acircumflex Uogonek -55
+KPX Acircumflex Uring -55
+KPX Acircumflex V -135
+KPX Acircumflex W -90
+KPX Acircumflex Y -105
+KPX Acircumflex Yacute -105
+KPX Acircumflex Ydieresis -105
+KPX Acircumflex quoteright -111
+KPX Acircumflex v -74
+KPX Acircumflex w -92
+KPX Acircumflex y -92
+KPX Acircumflex yacute -92
+KPX Acircumflex ydieresis -92
+KPX Adieresis C -40
+KPX Adieresis Cacute -40
+KPX Adieresis Ccaron -40
+KPX Adieresis Ccedilla -40
+KPX Adieresis G -40
+KPX Adieresis Gbreve -40
+KPX Adieresis Gcommaaccent -40
+KPX Adieresis O -55
+KPX Adieresis Oacute -55
+KPX Adieresis Ocircumflex -55
+KPX Adieresis Odieresis -55
+KPX Adieresis Ograve -55
+KPX Adieresis Ohungarumlaut -55
+KPX Adieresis Omacron -55
+KPX Adieresis Oslash -55
+KPX Adieresis Otilde -55
+KPX Adieresis Q -55
+KPX Adieresis T -111
+KPX Adieresis Tcaron -111
+KPX Adieresis Tcommaaccent -111
+KPX Adieresis U -55
+KPX Adieresis Uacute -55
+KPX Adieresis Ucircumflex -55
+KPX Adieresis Udieresis -55
+KPX Adieresis Ugrave -55
+KPX Adieresis Uhungarumlaut -55
+KPX Adieresis Umacron -55
+KPX Adieresis Uogonek -55
+KPX Adieresis Uring -55
+KPX Adieresis V -135
+KPX Adieresis W -90
+KPX Adieresis Y -105
+KPX Adieresis Yacute -105
+KPX Adieresis Ydieresis -105
+KPX Adieresis quoteright -111
+KPX Adieresis v -74
+KPX Adieresis w -92
+KPX Adieresis y -92
+KPX Adieresis yacute -92
+KPX Adieresis ydieresis -92
+KPX Agrave C -40
+KPX Agrave Cacute -40
+KPX Agrave Ccaron -40
+KPX Agrave Ccedilla -40
+KPX Agrave G -40
+KPX Agrave Gbreve -40
+KPX Agrave Gcommaaccent -40
+KPX Agrave O -55
+KPX Agrave Oacute -55
+KPX Agrave Ocircumflex -55
+KPX Agrave Odieresis -55
+KPX Agrave Ograve -55
+KPX Agrave Ohungarumlaut -55
+KPX Agrave Omacron -55
+KPX Agrave Oslash -55
+KPX Agrave Otilde -55
+KPX Agrave Q -55
+KPX Agrave T -111
+KPX Agrave Tcaron -111
+KPX Agrave Tcommaaccent -111
+KPX Agrave U -55
+KPX Agrave Uacute -55
+KPX Agrave Ucircumflex -55
+KPX Agrave Udieresis -55
+KPX Agrave Ugrave -55
+KPX Agrave Uhungarumlaut -55
+KPX Agrave Umacron -55
+KPX Agrave Uogonek -55
+KPX Agrave Uring -55
+KPX Agrave V -135
+KPX Agrave W -90
+KPX Agrave Y -105
+KPX Agrave Yacute -105
+KPX Agrave Ydieresis -105
+KPX Agrave quoteright -111
+KPX Agrave v -74
+KPX Agrave w -92
+KPX Agrave y -92
+KPX Agrave yacute -92
+KPX Agrave ydieresis -92
+KPX Amacron C -40
+KPX Amacron Cacute -40
+KPX Amacron Ccaron -40
+KPX Amacron Ccedilla -40
+KPX Amacron G -40
+KPX Amacron Gbreve -40
+KPX Amacron Gcommaaccent -40
+KPX Amacron O -55
+KPX Amacron Oacute -55
+KPX Amacron Ocircumflex -55
+KPX Amacron Odieresis -55
+KPX Amacron Ograve -55
+KPX Amacron Ohungarumlaut -55
+KPX Amacron Omacron -55
+KPX Amacron Oslash -55
+KPX Amacron Otilde -55
+KPX Amacron Q -55
+KPX Amacron T -111
+KPX Amacron Tcaron -111
+KPX Amacron Tcommaaccent -111
+KPX Amacron U -55
+KPX Amacron Uacute -55
+KPX Amacron Ucircumflex -55
+KPX Amacron Udieresis -55
+KPX Amacron Ugrave -55
+KPX Amacron Uhungarumlaut -55
+KPX Amacron Umacron -55
+KPX Amacron Uogonek -55
+KPX Amacron Uring -55
+KPX Amacron V -135
+KPX Amacron W -90
+KPX Amacron Y -105
+KPX Amacron Yacute -105
+KPX Amacron Ydieresis -105
+KPX Amacron quoteright -111
+KPX Amacron v -74
+KPX Amacron w -92
+KPX Amacron y -92
+KPX Amacron yacute -92
+KPX Amacron ydieresis -92
+KPX Aogonek C -40
+KPX Aogonek Cacute -40
+KPX Aogonek Ccaron -40
+KPX Aogonek Ccedilla -40
+KPX Aogonek G -40
+KPX Aogonek Gbreve -40
+KPX Aogonek Gcommaaccent -40
+KPX Aogonek O -55
+KPX Aogonek Oacute -55
+KPX Aogonek Ocircumflex -55
+KPX Aogonek Odieresis -55
+KPX Aogonek Ograve -55
+KPX Aogonek Ohungarumlaut -55
+KPX Aogonek Omacron -55
+KPX Aogonek Oslash -55
+KPX Aogonek Otilde -55
+KPX Aogonek Q -55
+KPX Aogonek T -111
+KPX Aogonek Tcaron -111
+KPX Aogonek Tcommaaccent -111
+KPX Aogonek U -55
+KPX Aogonek Uacute -55
+KPX Aogonek Ucircumflex -55
+KPX Aogonek Udieresis -55
+KPX Aogonek Ugrave -55
+KPX Aogonek Uhungarumlaut -55
+KPX Aogonek Umacron -55
+KPX Aogonek Uogonek -55
+KPX Aogonek Uring -55
+KPX Aogonek V -135
+KPX Aogonek W -90
+KPX Aogonek Y -105
+KPX Aogonek Yacute -105
+KPX Aogonek Ydieresis -105
+KPX Aogonek quoteright -111
+KPX Aogonek v -74
+KPX Aogonek w -52
+KPX Aogonek y -52
+KPX Aogonek yacute -52
+KPX Aogonek ydieresis -52
+KPX Aring C -40
+KPX Aring Cacute -40
+KPX Aring Ccaron -40
+KPX Aring Ccedilla -40
+KPX Aring G -40
+KPX Aring Gbreve -40
+KPX Aring Gcommaaccent -40
+KPX Aring O -55
+KPX Aring Oacute -55
+KPX Aring Ocircumflex -55
+KPX Aring Odieresis -55
+KPX Aring Ograve -55
+KPX Aring Ohungarumlaut -55
+KPX Aring Omacron -55
+KPX Aring Oslash -55
+KPX Aring Otilde -55
+KPX Aring Q -55
+KPX Aring T -111
+KPX Aring Tcaron -111
+KPX Aring Tcommaaccent -111
+KPX Aring U -55
+KPX Aring Uacute -55
+KPX Aring Ucircumflex -55
+KPX Aring Udieresis -55
+KPX Aring Ugrave -55
+KPX Aring Uhungarumlaut -55
+KPX Aring Umacron -55
+KPX Aring Uogonek -55
+KPX Aring Uring -55
+KPX Aring V -135
+KPX Aring W -90
+KPX Aring Y -105
+KPX Aring Yacute -105
+KPX Aring Ydieresis -105
+KPX Aring quoteright -111
+KPX Aring v -74
+KPX Aring w -92
+KPX Aring y -92
+KPX Aring yacute -92
+KPX Aring ydieresis -92
+KPX Atilde C -40
+KPX Atilde Cacute -40
+KPX Atilde Ccaron -40
+KPX Atilde Ccedilla -40
+KPX Atilde G -40
+KPX Atilde Gbreve -40
+KPX Atilde Gcommaaccent -40
+KPX Atilde O -55
+KPX Atilde Oacute -55
+KPX Atilde Ocircumflex -55
+KPX Atilde Odieresis -55
+KPX Atilde Ograve -55
+KPX Atilde Ohungarumlaut -55
+KPX Atilde Omacron -55
+KPX Atilde Oslash -55
+KPX Atilde Otilde -55
+KPX Atilde Q -55
+KPX Atilde T -111
+KPX Atilde Tcaron -111
+KPX Atilde Tcommaaccent -111
+KPX Atilde U -55
+KPX Atilde Uacute -55
+KPX Atilde Ucircumflex -55
+KPX Atilde Udieresis -55
+KPX Atilde Ugrave -55
+KPX Atilde Uhungarumlaut -55
+KPX Atilde Umacron -55
+KPX Atilde Uogonek -55
+KPX Atilde Uring -55
+KPX Atilde V -135
+KPX Atilde W -90
+KPX Atilde Y -105
+KPX Atilde Yacute -105
+KPX Atilde Ydieresis -105
+KPX Atilde quoteright -111
+KPX Atilde v -74
+KPX Atilde w -92
+KPX Atilde y -92
+KPX Atilde yacute -92
+KPX Atilde ydieresis -92
+KPX B A -35
+KPX B Aacute -35
+KPX B Abreve -35
+KPX B Acircumflex -35
+KPX B Adieresis -35
+KPX B Agrave -35
+KPX B Amacron -35
+KPX B Aogonek -35
+KPX B Aring -35
+KPX B Atilde -35
+KPX B U -10
+KPX B Uacute -10
+KPX B Ucircumflex -10
+KPX B Udieresis -10
+KPX B Ugrave -10
+KPX B Uhungarumlaut -10
+KPX B Umacron -10
+KPX B Uogonek -10
+KPX B Uring -10
+KPX D A -40
+KPX D Aacute -40
+KPX D Abreve -40
+KPX D Acircumflex -40
+KPX D Adieresis -40
+KPX D Agrave -40
+KPX D Amacron -40
+KPX D Aogonek -40
+KPX D Aring -40
+KPX D Atilde -40
+KPX D V -40
+KPX D W -30
+KPX D Y -55
+KPX D Yacute -55
+KPX D Ydieresis -55
+KPX Dcaron A -40
+KPX Dcaron Aacute -40
+KPX Dcaron Abreve -40
+KPX Dcaron Acircumflex -40
+KPX Dcaron Adieresis -40
+KPX Dcaron Agrave -40
+KPX Dcaron Amacron -40
+KPX Dcaron Aogonek -40
+KPX Dcaron Aring -40
+KPX Dcaron Atilde -40
+KPX Dcaron V -40
+KPX Dcaron W -30
+KPX Dcaron Y -55
+KPX Dcaron Yacute -55
+KPX Dcaron Ydieresis -55
+KPX Dcroat A -40
+KPX Dcroat Aacute -40
+KPX Dcroat Abreve -40
+KPX Dcroat Acircumflex -40
+KPX Dcroat Adieresis -40
+KPX Dcroat Agrave -40
+KPX Dcroat Amacron -40
+KPX Dcroat Aogonek -40
+KPX Dcroat Aring -40
+KPX Dcroat Atilde -40
+KPX Dcroat V -40
+KPX Dcroat W -30
+KPX Dcroat Y -55
+KPX Dcroat Yacute -55
+KPX Dcroat Ydieresis -55
+KPX F A -74
+KPX F Aacute -74
+KPX F Abreve -74
+KPX F Acircumflex -74
+KPX F Adieresis -74
+KPX F Agrave -74
+KPX F Amacron -74
+KPX F Aogonek -74
+KPX F Aring -74
+KPX F Atilde -74
+KPX F a -15
+KPX F aacute -15
+KPX F abreve -15
+KPX F acircumflex -15
+KPX F adieresis -15
+KPX F agrave -15
+KPX F amacron -15
+KPX F aogonek -15
+KPX F aring -15
+KPX F atilde -15
+KPX F comma -80
+KPX F o -15
+KPX F oacute -15
+KPX F ocircumflex -15
+KPX F odieresis -15
+KPX F ograve -15
+KPX F ohungarumlaut -15
+KPX F omacron -15
+KPX F oslash -15
+KPX F otilde -15
+KPX F period -80
+KPX J A -60
+KPX J Aacute -60
+KPX J Abreve -60
+KPX J Acircumflex -60
+KPX J Adieresis -60
+KPX J Agrave -60
+KPX J Amacron -60
+KPX J Aogonek -60
+KPX J Aring -60
+KPX J Atilde -60
+KPX K O -30
+KPX K Oacute -30
+KPX K Ocircumflex -30
+KPX K Odieresis -30
+KPX K Ograve -30
+KPX K Ohungarumlaut -30
+KPX K Omacron -30
+KPX K Oslash -30
+KPX K Otilde -30
+KPX K e -25
+KPX K eacute -25
+KPX K ecaron -25
+KPX K ecircumflex -25
+KPX K edieresis -25
+KPX K edotaccent -25
+KPX K egrave -25
+KPX K emacron -25
+KPX K eogonek -25
+KPX K o -35
+KPX K oacute -35
+KPX K ocircumflex -35
+KPX K odieresis -35
+KPX K ograve -35
+KPX K ohungarumlaut -35
+KPX K omacron -35
+KPX K oslash -35
+KPX K otilde -35
+KPX K u -15
+KPX K uacute -15
+KPX K ucircumflex -15
+KPX K udieresis -15
+KPX K ugrave -15
+KPX K uhungarumlaut -15
+KPX K umacron -15
+KPX K uogonek -15
+KPX K uring -15
+KPX K y -25
+KPX K yacute -25
+KPX K ydieresis -25
+KPX Kcommaaccent O -30
+KPX Kcommaaccent Oacute -30
+KPX Kcommaaccent Ocircumflex -30
+KPX Kcommaaccent Odieresis -30
+KPX Kcommaaccent Ograve -30
+KPX Kcommaaccent Ohungarumlaut -30
+KPX Kcommaaccent Omacron -30
+KPX Kcommaaccent Oslash -30
+KPX Kcommaaccent Otilde -30
+KPX Kcommaaccent e -25
+KPX Kcommaaccent eacute -25
+KPX Kcommaaccent ecaron -25
+KPX Kcommaaccent ecircumflex -25
+KPX Kcommaaccent edieresis -25
+KPX Kcommaaccent edotaccent -25
+KPX Kcommaaccent egrave -25
+KPX Kcommaaccent emacron -25
+KPX Kcommaaccent eogonek -25
+KPX Kcommaaccent o -35
+KPX Kcommaaccent oacute -35
+KPX Kcommaaccent ocircumflex -35
+KPX Kcommaaccent odieresis -35
+KPX Kcommaaccent ograve -35
+KPX Kcommaaccent ohungarumlaut -35
+KPX Kcommaaccent omacron -35
+KPX Kcommaaccent oslash -35
+KPX Kcommaaccent otilde -35
+KPX Kcommaaccent u -15
+KPX Kcommaaccent uacute -15
+KPX Kcommaaccent ucircumflex -15
+KPX Kcommaaccent udieresis -15
+KPX Kcommaaccent ugrave -15
+KPX Kcommaaccent uhungarumlaut -15
+KPX Kcommaaccent umacron -15
+KPX Kcommaaccent uogonek -15
+KPX Kcommaaccent uring -15
+KPX Kcommaaccent y -25
+KPX Kcommaaccent yacute -25
+KPX Kcommaaccent ydieresis -25
+KPX L T -92
+KPX L Tcaron -92
+KPX L Tcommaaccent -92
+KPX L V -100
+KPX L W -74
+KPX L Y -100
+KPX L Yacute -100
+KPX L Ydieresis -100
+KPX L quoteright -92
+KPX L y -55
+KPX L yacute -55
+KPX L ydieresis -55
+KPX Lacute T -92
+KPX Lacute Tcaron -92
+KPX Lacute Tcommaaccent -92
+KPX Lacute V -100
+KPX Lacute W -74
+KPX Lacute Y -100
+KPX Lacute Yacute -100
+KPX Lacute Ydieresis -100
+KPX Lacute quoteright -92
+KPX Lacute y -55
+KPX Lacute yacute -55
+KPX Lacute ydieresis -55
+KPX Lcaron quoteright -92
+KPX Lcaron y -55
+KPX Lcaron yacute -55
+KPX Lcaron ydieresis -55
+KPX Lcommaaccent T -92
+KPX Lcommaaccent Tcaron -92
+KPX Lcommaaccent Tcommaaccent -92
+KPX Lcommaaccent V -100
+KPX Lcommaaccent W -74
+KPX Lcommaaccent Y -100
+KPX Lcommaaccent Yacute -100
+KPX Lcommaaccent Ydieresis -100
+KPX Lcommaaccent quoteright -92
+KPX Lcommaaccent y -55
+KPX Lcommaaccent yacute -55
+KPX Lcommaaccent ydieresis -55
+KPX Lslash T -92
+KPX Lslash Tcaron -92
+KPX Lslash Tcommaaccent -92
+KPX Lslash V -100
+KPX Lslash W -74
+KPX Lslash Y -100
+KPX Lslash Yacute -100
+KPX Lslash Ydieresis -100
+KPX Lslash quoteright -92
+KPX Lslash y -55
+KPX Lslash yacute -55
+KPX Lslash ydieresis -55
+KPX N A -35
+KPX N Aacute -35
+KPX N Abreve -35
+KPX N Acircumflex -35
+KPX N Adieresis -35
+KPX N Agrave -35
+KPX N Amacron -35
+KPX N Aogonek -35
+KPX N Aring -35
+KPX N Atilde -35
+KPX Nacute A -35
+KPX Nacute Aacute -35
+KPX Nacute Abreve -35
+KPX Nacute Acircumflex -35
+KPX Nacute Adieresis -35
+KPX Nacute Agrave -35
+KPX Nacute Amacron -35
+KPX Nacute Aogonek -35
+KPX Nacute Aring -35
+KPX Nacute Atilde -35
+KPX Ncaron A -35
+KPX Ncaron Aacute -35
+KPX Ncaron Abreve -35
+KPX Ncaron Acircumflex -35
+KPX Ncaron Adieresis -35
+KPX Ncaron Agrave -35
+KPX Ncaron Amacron -35
+KPX Ncaron Aogonek -35
+KPX Ncaron Aring -35
+KPX Ncaron Atilde -35
+KPX Ncommaaccent A -35
+KPX Ncommaaccent Aacute -35
+KPX Ncommaaccent Abreve -35
+KPX Ncommaaccent Acircumflex -35
+KPX Ncommaaccent Adieresis -35
+KPX Ncommaaccent Agrave -35
+KPX Ncommaaccent Amacron -35
+KPX Ncommaaccent Aogonek -35
+KPX Ncommaaccent Aring -35
+KPX Ncommaaccent Atilde -35
+KPX Ntilde A -35
+KPX Ntilde Aacute -35
+KPX Ntilde Abreve -35
+KPX Ntilde Acircumflex -35
+KPX Ntilde Adieresis -35
+KPX Ntilde Agrave -35
+KPX Ntilde Amacron -35
+KPX Ntilde Aogonek -35
+KPX Ntilde Aring -35
+KPX Ntilde Atilde -35
+KPX O A -35
+KPX O Aacute -35
+KPX O Abreve -35
+KPX O Acircumflex -35
+KPX O Adieresis -35
+KPX O Agrave -35
+KPX O Amacron -35
+KPX O Aogonek -35
+KPX O Aring -35
+KPX O Atilde -35
+KPX O T -40
+KPX O Tcaron -40
+KPX O Tcommaaccent -40
+KPX O V -50
+KPX O W -35
+KPX O X -40
+KPX O Y -50
+KPX O Yacute -50
+KPX O Ydieresis -50
+KPX Oacute A -35
+KPX Oacute Aacute -35
+KPX Oacute Abreve -35
+KPX Oacute Acircumflex -35
+KPX Oacute Adieresis -35
+KPX Oacute Agrave -35
+KPX Oacute Amacron -35
+KPX Oacute Aogonek -35
+KPX Oacute Aring -35
+KPX Oacute Atilde -35
+KPX Oacute T -40
+KPX Oacute Tcaron -40
+KPX Oacute Tcommaaccent -40
+KPX Oacute V -50
+KPX Oacute W -35
+KPX Oacute X -40
+KPX Oacute Y -50
+KPX Oacute Yacute -50
+KPX Oacute Ydieresis -50
+KPX Ocircumflex A -35
+KPX Ocircumflex Aacute -35
+KPX Ocircumflex Abreve -35
+KPX Ocircumflex Acircumflex -35
+KPX Ocircumflex Adieresis -35
+KPX Ocircumflex Agrave -35
+KPX Ocircumflex Amacron -35
+KPX Ocircumflex Aogonek -35
+KPX Ocircumflex Aring -35
+KPX Ocircumflex Atilde -35
+KPX Ocircumflex T -40
+KPX Ocircumflex Tcaron -40
+KPX Ocircumflex Tcommaaccent -40
+KPX Ocircumflex V -50
+KPX Ocircumflex W -35
+KPX Ocircumflex X -40
+KPX Ocircumflex Y -50
+KPX Ocircumflex Yacute -50
+KPX Ocircumflex Ydieresis -50
+KPX Odieresis A -35
+KPX Odieresis Aacute -35
+KPX Odieresis Abreve -35
+KPX Odieresis Acircumflex -35
+KPX Odieresis Adieresis -35
+KPX Odieresis Agrave -35
+KPX Odieresis Amacron -35
+KPX Odieresis Aogonek -35
+KPX Odieresis Aring -35
+KPX Odieresis Atilde -35
+KPX Odieresis T -40
+KPX Odieresis Tcaron -40
+KPX Odieresis Tcommaaccent -40
+KPX Odieresis V -50
+KPX Odieresis W -35
+KPX Odieresis X -40
+KPX Odieresis Y -50
+KPX Odieresis Yacute -50
+KPX Odieresis Ydieresis -50
+KPX Ograve A -35
+KPX Ograve Aacute -35
+KPX Ograve Abreve -35
+KPX Ograve Acircumflex -35
+KPX Ograve Adieresis -35
+KPX Ograve Agrave -35
+KPX Ograve Amacron -35
+KPX Ograve Aogonek -35
+KPX Ograve Aring -35
+KPX Ograve Atilde -35
+KPX Ograve T -40
+KPX Ograve Tcaron -40
+KPX Ograve Tcommaaccent -40
+KPX Ograve V -50
+KPX Ograve W -35
+KPX Ograve X -40
+KPX Ograve Y -50
+KPX Ograve Yacute -50
+KPX Ograve Ydieresis -50
+KPX Ohungarumlaut A -35
+KPX Ohungarumlaut Aacute -35
+KPX Ohungarumlaut Abreve -35
+KPX Ohungarumlaut Acircumflex -35
+KPX Ohungarumlaut Adieresis -35
+KPX Ohungarumlaut Agrave -35
+KPX Ohungarumlaut Amacron -35
+KPX Ohungarumlaut Aogonek -35
+KPX Ohungarumlaut Aring -35
+KPX Ohungarumlaut Atilde -35
+KPX Ohungarumlaut T -40
+KPX Ohungarumlaut Tcaron -40
+KPX Ohungarumlaut Tcommaaccent -40
+KPX Ohungarumlaut V -50
+KPX Ohungarumlaut W -35
+KPX Ohungarumlaut X -40
+KPX Ohungarumlaut Y -50
+KPX Ohungarumlaut Yacute -50
+KPX Ohungarumlaut Ydieresis -50
+KPX Omacron A -35
+KPX Omacron Aacute -35
+KPX Omacron Abreve -35
+KPX Omacron Acircumflex -35
+KPX Omacron Adieresis -35
+KPX Omacron Agrave -35
+KPX Omacron Amacron -35
+KPX Omacron Aogonek -35
+KPX Omacron Aring -35
+KPX Omacron Atilde -35
+KPX Omacron T -40
+KPX Omacron Tcaron -40
+KPX Omacron Tcommaaccent -40
+KPX Omacron V -50
+KPX Omacron W -35
+KPX Omacron X -40
+KPX Omacron Y -50
+KPX Omacron Yacute -50
+KPX Omacron Ydieresis -50
+KPX Oslash A -35
+KPX Oslash Aacute -35
+KPX Oslash Abreve -35
+KPX Oslash Acircumflex -35
+KPX Oslash Adieresis -35
+KPX Oslash Agrave -35
+KPX Oslash Amacron -35
+KPX Oslash Aogonek -35
+KPX Oslash Aring -35
+KPX Oslash Atilde -35
+KPX Oslash T -40
+KPX Oslash Tcaron -40
+KPX Oslash Tcommaaccent -40
+KPX Oslash V -50
+KPX Oslash W -35
+KPX Oslash X -40
+KPX Oslash Y -50
+KPX Oslash Yacute -50
+KPX Oslash Ydieresis -50
+KPX Otilde A -35
+KPX Otilde Aacute -35
+KPX Otilde Abreve -35
+KPX Otilde Acircumflex -35
+KPX Otilde Adieresis -35
+KPX Otilde Agrave -35
+KPX Otilde Amacron -35
+KPX Otilde Aogonek -35
+KPX Otilde Aring -35
+KPX Otilde Atilde -35
+KPX Otilde T -40
+KPX Otilde Tcaron -40
+KPX Otilde Tcommaaccent -40
+KPX Otilde V -50
+KPX Otilde W -35
+KPX Otilde X -40
+KPX Otilde Y -50
+KPX Otilde Yacute -50
+KPX Otilde Ydieresis -50
+KPX P A -92
+KPX P Aacute -92
+KPX P Abreve -92
+KPX P Acircumflex -92
+KPX P Adieresis -92
+KPX P Agrave -92
+KPX P Amacron -92
+KPX P Aogonek -92
+KPX P Aring -92
+KPX P Atilde -92
+KPX P a -15
+KPX P aacute -15
+KPX P abreve -15
+KPX P acircumflex -15
+KPX P adieresis -15
+KPX P agrave -15
+KPX P amacron -15
+KPX P aogonek -15
+KPX P aring -15
+KPX P atilde -15
+KPX P comma -111
+KPX P period -111
+KPX Q U -10
+KPX Q Uacute -10
+KPX Q Ucircumflex -10
+KPX Q Udieresis -10
+KPX Q Ugrave -10
+KPX Q Uhungarumlaut -10
+KPX Q Umacron -10
+KPX Q Uogonek -10
+KPX Q Uring -10
+KPX R O -40
+KPX R Oacute -40
+KPX R Ocircumflex -40
+KPX R Odieresis -40
+KPX R Ograve -40
+KPX R Ohungarumlaut -40
+KPX R Omacron -40
+KPX R Oslash -40
+KPX R Otilde -40
+KPX R T -60
+KPX R Tcaron -60
+KPX R Tcommaaccent -60
+KPX R U -40
+KPX R Uacute -40
+KPX R Ucircumflex -40
+KPX R Udieresis -40
+KPX R Ugrave -40
+KPX R Uhungarumlaut -40
+KPX R Umacron -40
+KPX R Uogonek -40
+KPX R Uring -40
+KPX R V -80
+KPX R W -55
+KPX R Y -65
+KPX R Yacute -65
+KPX R Ydieresis -65
+KPX Racute O -40
+KPX Racute Oacute -40
+KPX Racute Ocircumflex -40
+KPX Racute Odieresis -40
+KPX Racute Ograve -40
+KPX Racute Ohungarumlaut -40
+KPX Racute Omacron -40
+KPX Racute Oslash -40
+KPX Racute Otilde -40
+KPX Racute T -60
+KPX Racute Tcaron -60
+KPX Racute Tcommaaccent -60
+KPX Racute U -40
+KPX Racute Uacute -40
+KPX Racute Ucircumflex -40
+KPX Racute Udieresis -40
+KPX Racute Ugrave -40
+KPX Racute Uhungarumlaut -40
+KPX Racute Umacron -40
+KPX Racute Uogonek -40
+KPX Racute Uring -40
+KPX Racute V -80
+KPX Racute W -55
+KPX Racute Y -65
+KPX Racute Yacute -65
+KPX Racute Ydieresis -65
+KPX Rcaron O -40
+KPX Rcaron Oacute -40
+KPX Rcaron Ocircumflex -40
+KPX Rcaron Odieresis -40
+KPX Rcaron Ograve -40
+KPX Rcaron Ohungarumlaut -40
+KPX Rcaron Omacron -40
+KPX Rcaron Oslash -40
+KPX Rcaron Otilde -40
+KPX Rcaron T -60
+KPX Rcaron Tcaron -60
+KPX Rcaron Tcommaaccent -60
+KPX Rcaron U -40
+KPX Rcaron Uacute -40
+KPX Rcaron Ucircumflex -40
+KPX Rcaron Udieresis -40
+KPX Rcaron Ugrave -40
+KPX Rcaron Uhungarumlaut -40
+KPX Rcaron Umacron -40
+KPX Rcaron Uogonek -40
+KPX Rcaron Uring -40
+KPX Rcaron V -80
+KPX Rcaron W -55
+KPX Rcaron Y -65
+KPX Rcaron Yacute -65
+KPX Rcaron Ydieresis -65
+KPX Rcommaaccent O -40
+KPX Rcommaaccent Oacute -40
+KPX Rcommaaccent Ocircumflex -40
+KPX Rcommaaccent Odieresis -40
+KPX Rcommaaccent Ograve -40
+KPX Rcommaaccent Ohungarumlaut -40
+KPX Rcommaaccent Omacron -40
+KPX Rcommaaccent Oslash -40
+KPX Rcommaaccent Otilde -40
+KPX Rcommaaccent T -60
+KPX Rcommaaccent Tcaron -60
+KPX Rcommaaccent Tcommaaccent -60
+KPX Rcommaaccent U -40
+KPX Rcommaaccent Uacute -40
+KPX Rcommaaccent Ucircumflex -40
+KPX Rcommaaccent Udieresis -40
+KPX Rcommaaccent Ugrave -40
+KPX Rcommaaccent Uhungarumlaut -40
+KPX Rcommaaccent Umacron -40
+KPX Rcommaaccent Uogonek -40
+KPX Rcommaaccent Uring -40
+KPX Rcommaaccent V -80
+KPX Rcommaaccent W -55
+KPX Rcommaaccent Y -65
+KPX Rcommaaccent Yacute -65
+KPX Rcommaaccent Ydieresis -65
+KPX T A -93
+KPX T Aacute -93
+KPX T Abreve -93
+KPX T Acircumflex -93
+KPX T Adieresis -93
+KPX T Agrave -93
+KPX T Amacron -93
+KPX T Aogonek -93
+KPX T Aring -93
+KPX T Atilde -93
+KPX T O -18
+KPX T Oacute -18
+KPX T Ocircumflex -18
+KPX T Odieresis -18
+KPX T Ograve -18
+KPX T Ohungarumlaut -18
+KPX T Omacron -18
+KPX T Oslash -18
+KPX T Otilde -18
+KPX T a -80
+KPX T aacute -80
+KPX T abreve -80
+KPX T acircumflex -80
+KPX T adieresis -40
+KPX T agrave -40
+KPX T amacron -40
+KPX T aogonek -80
+KPX T aring -80
+KPX T atilde -40
+KPX T colon -50
+KPX T comma -74
+KPX T e -70
+KPX T eacute -70
+KPX T ecaron -70
+KPX T ecircumflex -70
+KPX T edieresis -30
+KPX T edotaccent -70
+KPX T egrave -70
+KPX T emacron -30
+KPX T eogonek -70
+KPX T hyphen -92
+KPX T i -35
+KPX T iacute -35
+KPX T iogonek -35
+KPX T o -80
+KPX T oacute -80
+KPX T ocircumflex -80
+KPX T odieresis -80
+KPX T ograve -80
+KPX T ohungarumlaut -80
+KPX T omacron -80
+KPX T oslash -80
+KPX T otilde -80
+KPX T period -74
+KPX T r -35
+KPX T racute -35
+KPX T rcaron -35
+KPX T rcommaaccent -35
+KPX T semicolon -55
+KPX T u -45
+KPX T uacute -45
+KPX T ucircumflex -45
+KPX T udieresis -45
+KPX T ugrave -45
+KPX T uhungarumlaut -45
+KPX T umacron -45
+KPX T uogonek -45
+KPX T uring -45
+KPX T w -80
+KPX T y -80
+KPX T yacute -80
+KPX T ydieresis -80
+KPX Tcaron A -93
+KPX Tcaron Aacute -93
+KPX Tcaron Abreve -93
+KPX Tcaron Acircumflex -93
+KPX Tcaron Adieresis -93
+KPX Tcaron Agrave -93
+KPX Tcaron Amacron -93
+KPX Tcaron Aogonek -93
+KPX Tcaron Aring -93
+KPX Tcaron Atilde -93
+KPX Tcaron O -18
+KPX Tcaron Oacute -18
+KPX Tcaron Ocircumflex -18
+KPX Tcaron Odieresis -18
+KPX Tcaron Ograve -18
+KPX Tcaron Ohungarumlaut -18
+KPX Tcaron Omacron -18
+KPX Tcaron Oslash -18
+KPX Tcaron Otilde -18
+KPX Tcaron a -80
+KPX Tcaron aacute -80
+KPX Tcaron abreve -80
+KPX Tcaron acircumflex -80
+KPX Tcaron adieresis -40
+KPX Tcaron agrave -40
+KPX Tcaron amacron -40
+KPX Tcaron aogonek -80
+KPX Tcaron aring -80
+KPX Tcaron atilde -40
+KPX Tcaron colon -50
+KPX Tcaron comma -74
+KPX Tcaron e -70
+KPX Tcaron eacute -70
+KPX Tcaron ecaron -70
+KPX Tcaron ecircumflex -30
+KPX Tcaron edieresis -30
+KPX Tcaron edotaccent -70
+KPX Tcaron egrave -70
+KPX Tcaron emacron -30
+KPX Tcaron eogonek -70
+KPX Tcaron hyphen -92
+KPX Tcaron i -35
+KPX Tcaron iacute -35
+KPX Tcaron iogonek -35
+KPX Tcaron o -80
+KPX Tcaron oacute -80
+KPX Tcaron ocircumflex -80
+KPX Tcaron odieresis -80
+KPX Tcaron ograve -80
+KPX Tcaron ohungarumlaut -80
+KPX Tcaron omacron -80
+KPX Tcaron oslash -80
+KPX Tcaron otilde -80
+KPX Tcaron period -74
+KPX Tcaron r -35
+KPX Tcaron racute -35
+KPX Tcaron rcaron -35
+KPX Tcaron rcommaaccent -35
+KPX Tcaron semicolon -55
+KPX Tcaron u -45
+KPX Tcaron uacute -45
+KPX Tcaron ucircumflex -45
+KPX Tcaron udieresis -45
+KPX Tcaron ugrave -45
+KPX Tcaron uhungarumlaut -45
+KPX Tcaron umacron -45
+KPX Tcaron uogonek -45
+KPX Tcaron uring -45
+KPX Tcaron w -80
+KPX Tcaron y -80
+KPX Tcaron yacute -80
+KPX Tcaron ydieresis -80
+KPX Tcommaaccent A -93
+KPX Tcommaaccent Aacute -93
+KPX Tcommaaccent Abreve -93
+KPX Tcommaaccent Acircumflex -93
+KPX Tcommaaccent Adieresis -93
+KPX Tcommaaccent Agrave -93
+KPX Tcommaaccent Amacron -93
+KPX Tcommaaccent Aogonek -93
+KPX Tcommaaccent Aring -93
+KPX Tcommaaccent Atilde -93
+KPX Tcommaaccent O -18
+KPX Tcommaaccent Oacute -18
+KPX Tcommaaccent Ocircumflex -18
+KPX Tcommaaccent Odieresis -18
+KPX Tcommaaccent Ograve -18
+KPX Tcommaaccent Ohungarumlaut -18
+KPX Tcommaaccent Omacron -18
+KPX Tcommaaccent Oslash -18
+KPX Tcommaaccent Otilde -18
+KPX Tcommaaccent a -80
+KPX Tcommaaccent aacute -80
+KPX Tcommaaccent abreve -80
+KPX Tcommaaccent acircumflex -80
+KPX Tcommaaccent adieresis -40
+KPX Tcommaaccent agrave -40
+KPX Tcommaaccent amacron -40
+KPX Tcommaaccent aogonek -80
+KPX Tcommaaccent aring -80
+KPX Tcommaaccent atilde -40
+KPX Tcommaaccent colon -50
+KPX Tcommaaccent comma -74
+KPX Tcommaaccent e -70
+KPX Tcommaaccent eacute -70
+KPX Tcommaaccent ecaron -70
+KPX Tcommaaccent ecircumflex -30
+KPX Tcommaaccent edieresis -30
+KPX Tcommaaccent edotaccent -70
+KPX Tcommaaccent egrave -30
+KPX Tcommaaccent emacron -70
+KPX Tcommaaccent eogonek -70
+KPX Tcommaaccent hyphen -92
+KPX Tcommaaccent i -35
+KPX Tcommaaccent iacute -35
+KPX Tcommaaccent iogonek -35
+KPX Tcommaaccent o -80
+KPX Tcommaaccent oacute -80
+KPX Tcommaaccent ocircumflex -80
+KPX Tcommaaccent odieresis -80
+KPX Tcommaaccent ograve -80
+KPX Tcommaaccent ohungarumlaut -80
+KPX Tcommaaccent omacron -80
+KPX Tcommaaccent oslash -80
+KPX Tcommaaccent otilde -80
+KPX Tcommaaccent period -74
+KPX Tcommaaccent r -35
+KPX Tcommaaccent racute -35
+KPX Tcommaaccent rcaron -35
+KPX Tcommaaccent rcommaaccent -35
+KPX Tcommaaccent semicolon -55
+KPX Tcommaaccent u -45
+KPX Tcommaaccent uacute -45
+KPX Tcommaaccent ucircumflex -45
+KPX Tcommaaccent udieresis -45
+KPX Tcommaaccent ugrave -45
+KPX Tcommaaccent uhungarumlaut -45
+KPX Tcommaaccent umacron -45
+KPX Tcommaaccent uogonek -45
+KPX Tcommaaccent uring -45
+KPX Tcommaaccent w -80
+KPX Tcommaaccent y -80
+KPX Tcommaaccent yacute -80
+KPX Tcommaaccent ydieresis -80
+KPX U A -40
+KPX U Aacute -40
+KPX U Abreve -40
+KPX U Acircumflex -40
+KPX U Adieresis -40
+KPX U Agrave -40
+KPX U Amacron -40
+KPX U Aogonek -40
+KPX U Aring -40
+KPX U Atilde -40
+KPX Uacute A -40
+KPX Uacute Aacute -40
+KPX Uacute Abreve -40
+KPX Uacute Acircumflex -40
+KPX Uacute Adieresis -40
+KPX Uacute Agrave -40
+KPX Uacute Amacron -40
+KPX Uacute Aogonek -40
+KPX Uacute Aring -40
+KPX Uacute Atilde -40
+KPX Ucircumflex A -40
+KPX Ucircumflex Aacute -40
+KPX Ucircumflex Abreve -40
+KPX Ucircumflex Acircumflex -40
+KPX Ucircumflex Adieresis -40
+KPX Ucircumflex Agrave -40
+KPX Ucircumflex Amacron -40
+KPX Ucircumflex Aogonek -40
+KPX Ucircumflex Aring -40
+KPX Ucircumflex Atilde -40
+KPX Udieresis A -40
+KPX Udieresis Aacute -40
+KPX Udieresis Abreve -40
+KPX Udieresis Acircumflex -40
+KPX Udieresis Adieresis -40
+KPX Udieresis Agrave -40
+KPX Udieresis Amacron -40
+KPX Udieresis Aogonek -40
+KPX Udieresis Aring -40
+KPX Udieresis Atilde -40
+KPX Ugrave A -40
+KPX Ugrave Aacute -40
+KPX Ugrave Abreve -40
+KPX Ugrave Acircumflex -40
+KPX Ugrave Adieresis -40
+KPX Ugrave Agrave -40
+KPX Ugrave Amacron -40
+KPX Ugrave Aogonek -40
+KPX Ugrave Aring -40
+KPX Ugrave Atilde -40
+KPX Uhungarumlaut A -40
+KPX Uhungarumlaut Aacute -40
+KPX Uhungarumlaut Abreve -40
+KPX Uhungarumlaut Acircumflex -40
+KPX Uhungarumlaut Adieresis -40
+KPX Uhungarumlaut Agrave -40
+KPX Uhungarumlaut Amacron -40
+KPX Uhungarumlaut Aogonek -40
+KPX Uhungarumlaut Aring -40
+KPX Uhungarumlaut Atilde -40
+KPX Umacron A -40
+KPX Umacron Aacute -40
+KPX Umacron Abreve -40
+KPX Umacron Acircumflex -40
+KPX Umacron Adieresis -40
+KPX Umacron Agrave -40
+KPX Umacron Amacron -40
+KPX Umacron Aogonek -40
+KPX Umacron Aring -40
+KPX Umacron Atilde -40
+KPX Uogonek A -40
+KPX Uogonek Aacute -40
+KPX Uogonek Abreve -40
+KPX Uogonek Acircumflex -40
+KPX Uogonek Adieresis -40
+KPX Uogonek Agrave -40
+KPX Uogonek Amacron -40
+KPX Uogonek Aogonek -40
+KPX Uogonek Aring -40
+KPX Uogonek Atilde -40
+KPX Uring A -40
+KPX Uring Aacute -40
+KPX Uring Abreve -40
+KPX Uring Acircumflex -40
+KPX Uring Adieresis -40
+KPX Uring Agrave -40
+KPX Uring Amacron -40
+KPX Uring Aogonek -40
+KPX Uring Aring -40
+KPX Uring Atilde -40
+KPX V A -135
+KPX V Aacute -135
+KPX V Abreve -135
+KPX V Acircumflex -135
+KPX V Adieresis -135
+KPX V Agrave -135
+KPX V Amacron -135
+KPX V Aogonek -135
+KPX V Aring -135
+KPX V Atilde -135
+KPX V G -15
+KPX V Gbreve -15
+KPX V Gcommaaccent -15
+KPX V O -40
+KPX V Oacute -40
+KPX V Ocircumflex -40
+KPX V Odieresis -40
+KPX V Ograve -40
+KPX V Ohungarumlaut -40
+KPX V Omacron -40
+KPX V Oslash -40
+KPX V Otilde -40
+KPX V a -111
+KPX V aacute -111
+KPX V abreve -111
+KPX V acircumflex -71
+KPX V adieresis -71
+KPX V agrave -71
+KPX V amacron -71
+KPX V aogonek -111
+KPX V aring -111
+KPX V atilde -71
+KPX V colon -74
+KPX V comma -129
+KPX V e -111
+KPX V eacute -111
+KPX V ecaron -71
+KPX V ecircumflex -71
+KPX V edieresis -71
+KPX V edotaccent -111
+KPX V egrave -71
+KPX V emacron -71
+KPX V eogonek -111
+KPX V hyphen -100
+KPX V i -60
+KPX V iacute -60
+KPX V icircumflex -20
+KPX V idieresis -20
+KPX V igrave -20
+KPX V imacron -20
+KPX V iogonek -60
+KPX V o -129
+KPX V oacute -129
+KPX V ocircumflex -129
+KPX V odieresis -89
+KPX V ograve -89
+KPX V ohungarumlaut -129
+KPX V omacron -89
+KPX V oslash -129
+KPX V otilde -89
+KPX V period -129
+KPX V semicolon -74
+KPX V u -75
+KPX V uacute -75
+KPX V ucircumflex -75
+KPX V udieresis -75
+KPX V ugrave -75
+KPX V uhungarumlaut -75
+KPX V umacron -75
+KPX V uogonek -75
+KPX V uring -75
+KPX W A -120
+KPX W Aacute -120
+KPX W Abreve -120
+KPX W Acircumflex -120
+KPX W Adieresis -120
+KPX W Agrave -120
+KPX W Amacron -120
+KPX W Aogonek -120
+KPX W Aring -120
+KPX W Atilde -120
+KPX W O -10
+KPX W Oacute -10
+KPX W Ocircumflex -10
+KPX W Odieresis -10
+KPX W Ograve -10
+KPX W Ohungarumlaut -10
+KPX W Omacron -10
+KPX W Oslash -10
+KPX W Otilde -10
+KPX W a -80
+KPX W aacute -80
+KPX W abreve -80
+KPX W acircumflex -80
+KPX W adieresis -80
+KPX W agrave -80
+KPX W amacron -80
+KPX W aogonek -80
+KPX W aring -80
+KPX W atilde -80
+KPX W colon -37
+KPX W comma -92
+KPX W e -80
+KPX W eacute -80
+KPX W ecaron -80
+KPX W ecircumflex -80
+KPX W edieresis -40
+KPX W edotaccent -80
+KPX W egrave -40
+KPX W emacron -40
+KPX W eogonek -80
+KPX W hyphen -65
+KPX W i -40
+KPX W iacute -40
+KPX W iogonek -40
+KPX W o -80
+KPX W oacute -80
+KPX W ocircumflex -80
+KPX W odieresis -80
+KPX W ograve -80
+KPX W ohungarumlaut -80
+KPX W omacron -80
+KPX W oslash -80
+KPX W otilde -80
+KPX W period -92
+KPX W semicolon -37
+KPX W u -50
+KPX W uacute -50
+KPX W ucircumflex -50
+KPX W udieresis -50
+KPX W ugrave -50
+KPX W uhungarumlaut -50
+KPX W umacron -50
+KPX W uogonek -50
+KPX W uring -50
+KPX W y -73
+KPX W yacute -73
+KPX W ydieresis -73
+KPX Y A -120
+KPX Y Aacute -120
+KPX Y Abreve -120
+KPX Y Acircumflex -120
+KPX Y Adieresis -120
+KPX Y Agrave -120
+KPX Y Amacron -120
+KPX Y Aogonek -120
+KPX Y Aring -120
+KPX Y Atilde -120
+KPX Y O -30
+KPX Y Oacute -30
+KPX Y Ocircumflex -30
+KPX Y Odieresis -30
+KPX Y Ograve -30
+KPX Y Ohungarumlaut -30
+KPX Y Omacron -30
+KPX Y Oslash -30
+KPX Y Otilde -30
+KPX Y a -100
+KPX Y aacute -100
+KPX Y abreve -100
+KPX Y acircumflex -100
+KPX Y adieresis -60
+KPX Y agrave -60
+KPX Y amacron -60
+KPX Y aogonek -100
+KPX Y aring -100
+KPX Y atilde -60
+KPX Y colon -92
+KPX Y comma -129
+KPX Y e -100
+KPX Y eacute -100
+KPX Y ecaron -100
+KPX Y ecircumflex -100
+KPX Y edieresis -60
+KPX Y edotaccent -100
+KPX Y egrave -60
+KPX Y emacron -60
+KPX Y eogonek -100
+KPX Y hyphen -111
+KPX Y i -55
+KPX Y iacute -55
+KPX Y iogonek -55
+KPX Y o -110
+KPX Y oacute -110
+KPX Y ocircumflex -110
+KPX Y odieresis -70
+KPX Y ograve -70
+KPX Y ohungarumlaut -110
+KPX Y omacron -70
+KPX Y oslash -110
+KPX Y otilde -70
+KPX Y period -129
+KPX Y semicolon -92
+KPX Y u -111
+KPX Y uacute -111
+KPX Y ucircumflex -111
+KPX Y udieresis -71
+KPX Y ugrave -71
+KPX Y uhungarumlaut -111
+KPX Y umacron -71
+KPX Y uogonek -111
+KPX Y uring -111
+KPX Yacute A -120
+KPX Yacute Aacute -120
+KPX Yacute Abreve -120
+KPX Yacute Acircumflex -120
+KPX Yacute Adieresis -120
+KPX Yacute Agrave -120
+KPX Yacute Amacron -120
+KPX Yacute Aogonek -120
+KPX Yacute Aring -120
+KPX Yacute Atilde -120
+KPX Yacute O -30
+KPX Yacute Oacute -30
+KPX Yacute Ocircumflex -30
+KPX Yacute Odieresis -30
+KPX Yacute Ograve -30
+KPX Yacute Ohungarumlaut -30
+KPX Yacute Omacron -30
+KPX Yacute Oslash -30
+KPX Yacute Otilde -30
+KPX Yacute a -100
+KPX Yacute aacute -100
+KPX Yacute abreve -100
+KPX Yacute acircumflex -100
+KPX Yacute adieresis -60
+KPX Yacute agrave -60
+KPX Yacute amacron -60
+KPX Yacute aogonek -100
+KPX Yacute aring -100
+KPX Yacute atilde -60
+KPX Yacute colon -92
+KPX Yacute comma -129
+KPX Yacute e -100
+KPX Yacute eacute -100
+KPX Yacute ecaron -100
+KPX Yacute ecircumflex -100
+KPX Yacute edieresis -60
+KPX Yacute edotaccent -100
+KPX Yacute egrave -60
+KPX Yacute emacron -60
+KPX Yacute eogonek -100
+KPX Yacute hyphen -111
+KPX Yacute i -55
+KPX Yacute iacute -55
+KPX Yacute iogonek -55
+KPX Yacute o -110
+KPX Yacute oacute -110
+KPX Yacute ocircumflex -110
+KPX Yacute odieresis -70
+KPX Yacute ograve -70
+KPX Yacute ohungarumlaut -110
+KPX Yacute omacron -70
+KPX Yacute oslash -110
+KPX Yacute otilde -70
+KPX Yacute period -129
+KPX Yacute semicolon -92
+KPX Yacute u -111
+KPX Yacute uacute -111
+KPX Yacute ucircumflex -111
+KPX Yacute udieresis -71
+KPX Yacute ugrave -71
+KPX Yacute uhungarumlaut -111
+KPX Yacute umacron -71
+KPX Yacute uogonek -111
+KPX Yacute uring -111
+KPX Ydieresis A -120
+KPX Ydieresis Aacute -120
+KPX Ydieresis Abreve -120
+KPX Ydieresis Acircumflex -120
+KPX Ydieresis Adieresis -120
+KPX Ydieresis Agrave -120
+KPX Ydieresis Amacron -120
+KPX Ydieresis Aogonek -120
+KPX Ydieresis Aring -120
+KPX Ydieresis Atilde -120
+KPX Ydieresis O -30
+KPX Ydieresis Oacute -30
+KPX Ydieresis Ocircumflex -30
+KPX Ydieresis Odieresis -30
+KPX Ydieresis Ograve -30
+KPX Ydieresis Ohungarumlaut -30
+KPX Ydieresis Omacron -30
+KPX Ydieresis Oslash -30
+KPX Ydieresis Otilde -30
+KPX Ydieresis a -100
+KPX Ydieresis aacute -100
+KPX Ydieresis abreve -100
+KPX Ydieresis acircumflex -100
+KPX Ydieresis adieresis -60
+KPX Ydieresis agrave -60
+KPX Ydieresis amacron -60
+KPX Ydieresis aogonek -100
+KPX Ydieresis aring -100
+KPX Ydieresis atilde -100
+KPX Ydieresis colon -92
+KPX Ydieresis comma -129
+KPX Ydieresis e -100
+KPX Ydieresis eacute -100
+KPX Ydieresis ecaron -100
+KPX Ydieresis ecircumflex -100
+KPX Ydieresis edieresis -60
+KPX Ydieresis edotaccent -100
+KPX Ydieresis egrave -60
+KPX Ydieresis emacron -60
+KPX Ydieresis eogonek -100
+KPX Ydieresis hyphen -111
+KPX Ydieresis i -55
+KPX Ydieresis iacute -55
+KPX Ydieresis iogonek -55
+KPX Ydieresis o -110
+KPX Ydieresis oacute -110
+KPX Ydieresis ocircumflex -110
+KPX Ydieresis odieresis -70
+KPX Ydieresis ograve -70
+KPX Ydieresis ohungarumlaut -110
+KPX Ydieresis omacron -70
+KPX Ydieresis oslash -110
+KPX Ydieresis otilde -70
+KPX Ydieresis period -129
+KPX Ydieresis semicolon -92
+KPX Ydieresis u -111
+KPX Ydieresis uacute -111
+KPX Ydieresis ucircumflex -111
+KPX Ydieresis udieresis -71
+KPX Ydieresis ugrave -71
+KPX Ydieresis uhungarumlaut -111
+KPX Ydieresis umacron -71
+KPX Ydieresis uogonek -111
+KPX Ydieresis uring -111
+KPX a v -20
+KPX a w -15
+KPX aacute v -20
+KPX aacute w -15
+KPX abreve v -20
+KPX abreve w -15
+KPX acircumflex v -20
+KPX acircumflex w -15
+KPX adieresis v -20
+KPX adieresis w -15
+KPX agrave v -20
+KPX agrave w -15
+KPX amacron v -20
+KPX amacron w -15
+KPX aogonek v -20
+KPX aogonek w -15
+KPX aring v -20
+KPX aring w -15
+KPX atilde v -20
+KPX atilde w -15
+KPX b period -40
+KPX b u -20
+KPX b uacute -20
+KPX b ucircumflex -20
+KPX b udieresis -20
+KPX b ugrave -20
+KPX b uhungarumlaut -20
+KPX b umacron -20
+KPX b uogonek -20
+KPX b uring -20
+KPX b v -15
+KPX c y -15
+KPX c yacute -15
+KPX c ydieresis -15
+KPX cacute y -15
+KPX cacute yacute -15
+KPX cacute ydieresis -15
+KPX ccaron y -15
+KPX ccaron yacute -15
+KPX ccaron ydieresis -15
+KPX ccedilla y -15
+KPX ccedilla yacute -15
+KPX ccedilla ydieresis -15
+KPX comma quotedblright -70
+KPX comma quoteright -70
+KPX e g -15
+KPX e gbreve -15
+KPX e gcommaaccent -15
+KPX e v -25
+KPX e w -25
+KPX e x -15
+KPX e y -15
+KPX e yacute -15
+KPX e ydieresis -15
+KPX eacute g -15
+KPX eacute gbreve -15
+KPX eacute gcommaaccent -15
+KPX eacute v -25
+KPX eacute w -25
+KPX eacute x -15
+KPX eacute y -15
+KPX eacute yacute -15
+KPX eacute ydieresis -15
+KPX ecaron g -15
+KPX ecaron gbreve -15
+KPX ecaron gcommaaccent -15
+KPX ecaron v -25
+KPX ecaron w -25
+KPX ecaron x -15
+KPX ecaron y -15
+KPX ecaron yacute -15
+KPX ecaron ydieresis -15
+KPX ecircumflex g -15
+KPX ecircumflex gbreve -15
+KPX ecircumflex gcommaaccent -15
+KPX ecircumflex v -25
+KPX ecircumflex w -25
+KPX ecircumflex x -15
+KPX ecircumflex y -15
+KPX ecircumflex yacute -15
+KPX ecircumflex ydieresis -15
+KPX edieresis g -15
+KPX edieresis gbreve -15
+KPX edieresis gcommaaccent -15
+KPX edieresis v -25
+KPX edieresis w -25
+KPX edieresis x -15
+KPX edieresis y -15
+KPX edieresis yacute -15
+KPX edieresis ydieresis -15
+KPX edotaccent g -15
+KPX edotaccent gbreve -15
+KPX edotaccent gcommaaccent -15
+KPX edotaccent v -25
+KPX edotaccent w -25
+KPX edotaccent x -15
+KPX edotaccent y -15
+KPX edotaccent yacute -15
+KPX edotaccent ydieresis -15
+KPX egrave g -15
+KPX egrave gbreve -15
+KPX egrave gcommaaccent -15
+KPX egrave v -25
+KPX egrave w -25
+KPX egrave x -15
+KPX egrave y -15
+KPX egrave yacute -15
+KPX egrave ydieresis -15
+KPX emacron g -15
+KPX emacron gbreve -15
+KPX emacron gcommaaccent -15
+KPX emacron v -25
+KPX emacron w -25
+KPX emacron x -15
+KPX emacron y -15
+KPX emacron yacute -15
+KPX emacron ydieresis -15
+KPX eogonek g -15
+KPX eogonek gbreve -15
+KPX eogonek gcommaaccent -15
+KPX eogonek v -25
+KPX eogonek w -25
+KPX eogonek x -15
+KPX eogonek y -15
+KPX eogonek yacute -15
+KPX eogonek ydieresis -15
+KPX f a -10
+KPX f aacute -10
+KPX f abreve -10
+KPX f acircumflex -10
+KPX f adieresis -10
+KPX f agrave -10
+KPX f amacron -10
+KPX f aogonek -10
+KPX f aring -10
+KPX f atilde -10
+KPX f dotlessi -50
+KPX f f -25
+KPX f i -20
+KPX f iacute -20
+KPX f quoteright 55
+KPX g a -5
+KPX g aacute -5
+KPX g abreve -5
+KPX g acircumflex -5
+KPX g adieresis -5
+KPX g agrave -5
+KPX g amacron -5
+KPX g aogonek -5
+KPX g aring -5
+KPX g atilde -5
+KPX gbreve a -5
+KPX gbreve aacute -5
+KPX gbreve abreve -5
+KPX gbreve acircumflex -5
+KPX gbreve adieresis -5
+KPX gbreve agrave -5
+KPX gbreve amacron -5
+KPX gbreve aogonek -5
+KPX gbreve aring -5
+KPX gbreve atilde -5
+KPX gcommaaccent a -5
+KPX gcommaaccent aacute -5
+KPX gcommaaccent abreve -5
+KPX gcommaaccent acircumflex -5
+KPX gcommaaccent adieresis -5
+KPX gcommaaccent agrave -5
+KPX gcommaaccent amacron -5
+KPX gcommaaccent aogonek -5
+KPX gcommaaccent aring -5
+KPX gcommaaccent atilde -5
+KPX h y -5
+KPX h yacute -5
+KPX h ydieresis -5
+KPX i v -25
+KPX iacute v -25
+KPX icircumflex v -25
+KPX idieresis v -25
+KPX igrave v -25
+KPX imacron v -25
+KPX iogonek v -25
+KPX k e -10
+KPX k eacute -10
+KPX k ecaron -10
+KPX k ecircumflex -10
+KPX k edieresis -10
+KPX k edotaccent -10
+KPX k egrave -10
+KPX k emacron -10
+KPX k eogonek -10
+KPX k o -10
+KPX k oacute -10
+KPX k ocircumflex -10
+KPX k odieresis -10
+KPX k ograve -10
+KPX k ohungarumlaut -10
+KPX k omacron -10
+KPX k oslash -10
+KPX k otilde -10
+KPX k y -15
+KPX k yacute -15
+KPX k ydieresis -15
+KPX kcommaaccent e -10
+KPX kcommaaccent eacute -10
+KPX kcommaaccent ecaron -10
+KPX kcommaaccent ecircumflex -10
+KPX kcommaaccent edieresis -10
+KPX kcommaaccent edotaccent -10
+KPX kcommaaccent egrave -10
+KPX kcommaaccent emacron -10
+KPX kcommaaccent eogonek -10
+KPX kcommaaccent o -10
+KPX kcommaaccent oacute -10
+KPX kcommaaccent ocircumflex -10
+KPX kcommaaccent odieresis -10
+KPX kcommaaccent ograve -10
+KPX kcommaaccent ohungarumlaut -10
+KPX kcommaaccent omacron -10
+KPX kcommaaccent oslash -10
+KPX kcommaaccent otilde -10
+KPX kcommaaccent y -15
+KPX kcommaaccent yacute -15
+KPX kcommaaccent ydieresis -15
+KPX l w -10
+KPX lacute w -10
+KPX lcommaaccent w -10
+KPX lslash w -10
+KPX n v -40
+KPX n y -15
+KPX n yacute -15
+KPX n ydieresis -15
+KPX nacute v -40
+KPX nacute y -15
+KPX nacute yacute -15
+KPX nacute ydieresis -15
+KPX ncaron v -40
+KPX ncaron y -15
+KPX ncaron yacute -15
+KPX ncaron ydieresis -15
+KPX ncommaaccent v -40
+KPX ncommaaccent y -15
+KPX ncommaaccent yacute -15
+KPX ncommaaccent ydieresis -15
+KPX ntilde v -40
+KPX ntilde y -15
+KPX ntilde yacute -15
+KPX ntilde ydieresis -15
+KPX o v -15
+KPX o w -25
+KPX o y -10
+KPX o yacute -10
+KPX o ydieresis -10
+KPX oacute v -15
+KPX oacute w -25
+KPX oacute y -10
+KPX oacute yacute -10
+KPX oacute ydieresis -10
+KPX ocircumflex v -15
+KPX ocircumflex w -25
+KPX ocircumflex y -10
+KPX ocircumflex yacute -10
+KPX ocircumflex ydieresis -10
+KPX odieresis v -15
+KPX odieresis w -25
+KPX odieresis y -10
+KPX odieresis yacute -10
+KPX odieresis ydieresis -10
+KPX ograve v -15
+KPX ograve w -25
+KPX ograve y -10
+KPX ograve yacute -10
+KPX ograve ydieresis -10
+KPX ohungarumlaut v -15
+KPX ohungarumlaut w -25
+KPX ohungarumlaut y -10
+KPX ohungarumlaut yacute -10
+KPX ohungarumlaut ydieresis -10
+KPX omacron v -15
+KPX omacron w -25
+KPX omacron y -10
+KPX omacron yacute -10
+KPX omacron ydieresis -10
+KPX oslash v -15
+KPX oslash w -25
+KPX oslash y -10
+KPX oslash yacute -10
+KPX oslash ydieresis -10
+KPX otilde v -15
+KPX otilde w -25
+KPX otilde y -10
+KPX otilde yacute -10
+KPX otilde ydieresis -10
+KPX p y -10
+KPX p yacute -10
+KPX p ydieresis -10
+KPX period quotedblright -70
+KPX period quoteright -70
+KPX quotedblleft A -80
+KPX quotedblleft Aacute -80
+KPX quotedblleft Abreve -80
+KPX quotedblleft Acircumflex -80
+KPX quotedblleft Adieresis -80
+KPX quotedblleft Agrave -80
+KPX quotedblleft Amacron -80
+KPX quotedblleft Aogonek -80
+KPX quotedblleft Aring -80
+KPX quotedblleft Atilde -80
+KPX quoteleft A -80
+KPX quoteleft Aacute -80
+KPX quoteleft Abreve -80
+KPX quoteleft Acircumflex -80
+KPX quoteleft Adieresis -80
+KPX quoteleft Agrave -80
+KPX quoteleft Amacron -80
+KPX quoteleft Aogonek -80
+KPX quoteleft Aring -80
+KPX quoteleft Atilde -80
+KPX quoteleft quoteleft -74
+KPX quoteright d -50
+KPX quoteright dcroat -50
+KPX quoteright l -10
+KPX quoteright lacute -10
+KPX quoteright lcommaaccent -10
+KPX quoteright lslash -10
+KPX quoteright quoteright -74
+KPX quoteright r -50
+KPX quoteright racute -50
+KPX quoteright rcaron -50
+KPX quoteright rcommaaccent -50
+KPX quoteright s -55
+KPX quoteright sacute -55
+KPX quoteright scaron -55
+KPX quoteright scedilla -55
+KPX quoteright scommaaccent -55
+KPX quoteright space -74
+KPX quoteright t -18
+KPX quoteright tcommaaccent -18
+KPX quoteright v -50
+KPX r comma -40
+KPX r g -18
+KPX r gbreve -18
+KPX r gcommaaccent -18
+KPX r hyphen -20
+KPX r period -55
+KPX racute comma -40
+KPX racute g -18
+KPX racute gbreve -18
+KPX racute gcommaaccent -18
+KPX racute hyphen -20
+KPX racute period -55
+KPX rcaron comma -40
+KPX rcaron g -18
+KPX rcaron gbreve -18
+KPX rcaron gcommaaccent -18
+KPX rcaron hyphen -20
+KPX rcaron period -55
+KPX rcommaaccent comma -40
+KPX rcommaaccent g -18
+KPX rcommaaccent gbreve -18
+KPX rcommaaccent gcommaaccent -18
+KPX rcommaaccent hyphen -20
+KPX rcommaaccent period -55
+KPX space A -55
+KPX space Aacute -55
+KPX space Abreve -55
+KPX space Acircumflex -55
+KPX space Adieresis -55
+KPX space Agrave -55
+KPX space Amacron -55
+KPX space Aogonek -55
+KPX space Aring -55
+KPX space Atilde -55
+KPX space T -18
+KPX space Tcaron -18
+KPX space Tcommaaccent -18
+KPX space V -50
+KPX space W -30
+KPX space Y -90
+KPX space Yacute -90
+KPX space Ydieresis -90
+KPX v a -25
+KPX v aacute -25
+KPX v abreve -25
+KPX v acircumflex -25
+KPX v adieresis -25
+KPX v agrave -25
+KPX v amacron -25
+KPX v aogonek -25
+KPX v aring -25
+KPX v atilde -25
+KPX v comma -65
+KPX v e -15
+KPX v eacute -15
+KPX v ecaron -15
+KPX v ecircumflex -15
+KPX v edieresis -15
+KPX v edotaccent -15
+KPX v egrave -15
+KPX v emacron -15
+KPX v eogonek -15
+KPX v o -20
+KPX v oacute -20
+KPX v ocircumflex -20
+KPX v odieresis -20
+KPX v ograve -20
+KPX v ohungarumlaut -20
+KPX v omacron -20
+KPX v oslash -20
+KPX v otilde -20
+KPX v period -65
+KPX w a -10
+KPX w aacute -10
+KPX w abreve -10
+KPX w acircumflex -10
+KPX w adieresis -10
+KPX w agrave -10
+KPX w amacron -10
+KPX w aogonek -10
+KPX w aring -10
+KPX w atilde -10
+KPX w comma -65
+KPX w o -10
+KPX w oacute -10
+KPX w ocircumflex -10
+KPX w odieresis -10
+KPX w ograve -10
+KPX w ohungarumlaut -10
+KPX w omacron -10
+KPX w oslash -10
+KPX w otilde -10
+KPX w period -65
+KPX x e -15
+KPX x eacute -15
+KPX x ecaron -15
+KPX x ecircumflex -15
+KPX x edieresis -15
+KPX x edotaccent -15
+KPX x egrave -15
+KPX x emacron -15
+KPX x eogonek -15
+KPX y comma -65
+KPX y period -65
+KPX yacute comma -65
+KPX yacute period -65
+KPX ydieresis comma -65
+KPX ydieresis period -65
+EndKernPairs
+EndKernData
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/ZapfDingbats.afm pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/ZapfDingbats.afm
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/fonts/ZapfDingbats.afm 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/fonts/ZapfDingbats.afm 2004-05-26 16:06:22.000000000 +0000
@@ -0,0 +1,225 @@
+StartFontMetrics 4.1
+Comment Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu May 1 15:14:13 1997
+Comment UniqueID 43082
+Comment VMusage 45775 55535
+FontName ZapfDingbats
+FullName ITC Zapf Dingbats
+FamilyName ZapfDingbats
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+CharacterSet Special
+FontBBox -1 -143 981 820
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.000
+Notice Copyright (c) 1985, 1987, 1988, 1989, 1997 Adobe Systems Incorporated. All Rights Reserved.ITC Zapf Dingbats is a registered trademark of International Typeface Corporation.
+EncodingScheme FontSpecific
+StdHW 28
+StdVW 90
+StartCharMetrics 202
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 974 ; N a1 ; B 35 72 939 621 ;
+C 34 ; WX 961 ; N a2 ; B 35 81 927 611 ;
+C 35 ; WX 974 ; N a202 ; B 35 72 939 621 ;
+C 36 ; WX 980 ; N a3 ; B 35 0 945 692 ;
+C 37 ; WX 719 ; N a4 ; B 34 139 685 566 ;
+C 38 ; WX 789 ; N a5 ; B 35 -14 755 705 ;
+C 39 ; WX 790 ; N a119 ; B 35 -14 755 705 ;
+C 40 ; WX 791 ; N a118 ; B 35 -13 761 705 ;
+C 41 ; WX 690 ; N a117 ; B 34 138 655 553 ;
+C 42 ; WX 960 ; N a11 ; B 35 123 925 568 ;
+C 43 ; WX 939 ; N a12 ; B 35 134 904 559 ;
+C 44 ; WX 549 ; N a13 ; B 29 -11 516 705 ;
+C 45 ; WX 855 ; N a14 ; B 34 59 820 632 ;
+C 46 ; WX 911 ; N a15 ; B 35 50 876 642 ;
+C 47 ; WX 933 ; N a16 ; B 35 139 899 550 ;
+C 48 ; WX 911 ; N a105 ; B 35 50 876 642 ;
+C 49 ; WX 945 ; N a17 ; B 35 139 909 553 ;
+C 50 ; WX 974 ; N a18 ; B 35 104 938 587 ;
+C 51 ; WX 755 ; N a19 ; B 34 -13 721 705 ;
+C 52 ; WX 846 ; N a20 ; B 36 -14 811 705 ;
+C 53 ; WX 762 ; N a21 ; B 35 0 727 692 ;
+C 54 ; WX 761 ; N a22 ; B 35 0 727 692 ;
+C 55 ; WX 571 ; N a23 ; B -1 -68 571 661 ;
+C 56 ; WX 677 ; N a24 ; B 36 -13 642 705 ;
+C 57 ; WX 763 ; N a25 ; B 35 0 728 692 ;
+C 58 ; WX 760 ; N a26 ; B 35 0 726 692 ;
+C 59 ; WX 759 ; N a27 ; B 35 0 725 692 ;
+C 60 ; WX 754 ; N a28 ; B 35 0 720 692 ;
+C 61 ; WX 494 ; N a6 ; B 35 0 460 692 ;
+C 62 ; WX 552 ; N a7 ; B 35 0 517 692 ;
+C 63 ; WX 537 ; N a8 ; B 35 0 503 692 ;
+C 64 ; WX 577 ; N a9 ; B 35 96 542 596 ;
+C 65 ; WX 692 ; N a10 ; B 35 -14 657 705 ;
+C 66 ; WX 786 ; N a29 ; B 35 -14 751 705 ;
+C 67 ; WX 788 ; N a30 ; B 35 -14 752 705 ;
+C 68 ; WX 788 ; N a31 ; B 35 -14 753 705 ;
+C 69 ; WX 790 ; N a32 ; B 35 -14 756 705 ;
+C 70 ; WX 793 ; N a33 ; B 35 -13 759 705 ;
+C 71 ; WX 794 ; N a34 ; B 35 -13 759 705 ;
+C 72 ; WX 816 ; N a35 ; B 35 -14 782 705 ;
+C 73 ; WX 823 ; N a36 ; B 35 -14 787 705 ;
+C 74 ; WX 789 ; N a37 ; B 35 -14 754 705 ;
+C 75 ; WX 841 ; N a38 ; B 35 -14 807 705 ;
+C 76 ; WX 823 ; N a39 ; B 35 -14 789 705 ;
+C 77 ; WX 833 ; N a40 ; B 35 -14 798 705 ;
+C 78 ; WX 816 ; N a41 ; B 35 -13 782 705 ;
+C 79 ; WX 831 ; N a42 ; B 35 -14 796 705 ;
+C 80 ; WX 923 ; N a43 ; B 35 -14 888 705 ;
+C 81 ; WX 744 ; N a44 ; B 35 0 710 692 ;
+C 82 ; WX 723 ; N a45 ; B 35 0 688 692 ;
+C 83 ; WX 749 ; N a46 ; B 35 0 714 692 ;
+C 84 ; WX 790 ; N a47 ; B 34 -14 756 705 ;
+C 85 ; WX 792 ; N a48 ; B 35 -14 758 705 ;
+C 86 ; WX 695 ; N a49 ; B 35 -14 661 706 ;
+C 87 ; WX 776 ; N a50 ; B 35 -6 741 699 ;
+C 88 ; WX 768 ; N a51 ; B 35 -7 734 699 ;
+C 89 ; WX 792 ; N a52 ; B 35 -14 757 705 ;
+C 90 ; WX 759 ; N a53 ; B 35 0 725 692 ;
+C 91 ; WX 707 ; N a54 ; B 35 -13 672 704 ;
+C 92 ; WX 708 ; N a55 ; B 35 -14 672 705 ;
+C 93 ; WX 682 ; N a56 ; B 35 -14 647 705 ;
+C 94 ; WX 701 ; N a57 ; B 35 -14 666 705 ;
+C 95 ; WX 826 ; N a58 ; B 35 -14 791 705 ;
+C 96 ; WX 815 ; N a59 ; B 35 -14 780 705 ;
+C 97 ; WX 789 ; N a60 ; B 35 -14 754 705 ;
+C 98 ; WX 789 ; N a61 ; B 35 -14 754 705 ;
+C 99 ; WX 707 ; N a62 ; B 34 -14 673 705 ;
+C 100 ; WX 687 ; N a63 ; B 36 0 651 692 ;
+C 101 ; WX 696 ; N a64 ; B 35 0 661 691 ;
+C 102 ; WX 689 ; N a65 ; B 35 0 655 692 ;
+C 103 ; WX 786 ; N a66 ; B 34 -14 751 705 ;
+C 104 ; WX 787 ; N a67 ; B 35 -14 752 705 ;
+C 105 ; WX 713 ; N a68 ; B 35 -14 678 705 ;
+C 106 ; WX 791 ; N a69 ; B 35 -14 756 705 ;
+C 107 ; WX 785 ; N a70 ; B 36 -14 751 705 ;
+C 108 ; WX 791 ; N a71 ; B 35 -14 757 705 ;
+C 109 ; WX 873 ; N a72 ; B 35 -14 838 705 ;
+C 110 ; WX 761 ; N a73 ; B 35 0 726 692 ;
+C 111 ; WX 762 ; N a74 ; B 35 0 727 692 ;
+C 112 ; WX 762 ; N a203 ; B 35 0 727 692 ;
+C 113 ; WX 759 ; N a75 ; B 35 0 725 692 ;
+C 114 ; WX 759 ; N a204 ; B 35 0 725 692 ;
+C 115 ; WX 892 ; N a76 ; B 35 0 858 705 ;
+C 116 ; WX 892 ; N a77 ; B 35 -14 858 692 ;
+C 117 ; WX 788 ; N a78 ; B 35 -14 754 705 ;
+C 118 ; WX 784 ; N a79 ; B 35 -14 749 705 ;
+C 119 ; WX 438 ; N a81 ; B 35 -14 403 705 ;
+C 120 ; WX 138 ; N a82 ; B 35 0 104 692 ;
+C 121 ; WX 277 ; N a83 ; B 35 0 242 692 ;
+C 122 ; WX 415 ; N a84 ; B 35 0 380 692 ;
+C 123 ; WX 392 ; N a97 ; B 35 263 357 705 ;
+C 124 ; WX 392 ; N a98 ; B 34 263 357 705 ;
+C 125 ; WX 668 ; N a99 ; B 35 263 633 705 ;
+C 126 ; WX 668 ; N a100 ; B 36 263 634 705 ;
+C 128 ; WX 390 ; N a89 ; B 35 -14 356 705 ;
+C 129 ; WX 390 ; N a90 ; B 35 -14 355 705 ;
+C 130 ; WX 317 ; N a93 ; B 35 0 283 692 ;
+C 131 ; WX 317 ; N a94 ; B 35 0 283 692 ;
+C 132 ; WX 276 ; N a91 ; B 35 0 242 692 ;
+C 133 ; WX 276 ; N a92 ; B 35 0 242 692 ;
+C 134 ; WX 509 ; N a205 ; B 35 0 475 692 ;
+C 135 ; WX 509 ; N a85 ; B 35 0 475 692 ;
+C 136 ; WX 410 ; N a206 ; B 35 0 375 692 ;
+C 137 ; WX 410 ; N a86 ; B 35 0 375 692 ;
+C 138 ; WX 234 ; N a87 ; B 35 -14 199 705 ;
+C 139 ; WX 234 ; N a88 ; B 35 -14 199 705 ;
+C 140 ; WX 334 ; N a95 ; B 35 0 299 692 ;
+C 141 ; WX 334 ; N a96 ; B 35 0 299 692 ;
+C 161 ; WX 732 ; N a101 ; B 35 -143 697 806 ;
+C 162 ; WX 544 ; N a102 ; B 56 -14 488 706 ;
+C 163 ; WX 544 ; N a103 ; B 34 -14 508 705 ;
+C 164 ; WX 910 ; N a104 ; B 35 40 875 651 ;
+C 165 ; WX 667 ; N a106 ; B 35 -14 633 705 ;
+C 166 ; WX 760 ; N a107 ; B 35 -14 726 705 ;
+C 167 ; WX 760 ; N a108 ; B 0 121 758 569 ;
+C 168 ; WX 776 ; N a112 ; B 35 0 741 705 ;
+C 169 ; WX 595 ; N a111 ; B 34 -14 560 705 ;
+C 170 ; WX 694 ; N a110 ; B 35 -14 659 705 ;
+C 171 ; WX 626 ; N a109 ; B 34 0 591 705 ;
+C 172 ; WX 788 ; N a120 ; B 35 -14 754 705 ;
+C 173 ; WX 788 ; N a121 ; B 35 -14 754 705 ;
+C 174 ; WX 788 ; N a122 ; B 35 -14 754 705 ;
+C 175 ; WX 788 ; N a123 ; B 35 -14 754 705 ;
+C 176 ; WX 788 ; N a124 ; B 35 -14 754 705 ;
+C 177 ; WX 788 ; N a125 ; B 35 -14 754 705 ;
+C 178 ; WX 788 ; N a126 ; B 35 -14 754 705 ;
+C 179 ; WX 788 ; N a127 ; B 35 -14 754 705 ;
+C 180 ; WX 788 ; N a128 ; B 35 -14 754 705 ;
+C 181 ; WX 788 ; N a129 ; B 35 -14 754 705 ;
+C 182 ; WX 788 ; N a130 ; B 35 -14 754 705 ;
+C 183 ; WX 788 ; N a131 ; B 35 -14 754 705 ;
+C 184 ; WX 788 ; N a132 ; B 35 -14 754 705 ;
+C 185 ; WX 788 ; N a133 ; B 35 -14 754 705 ;
+C 186 ; WX 788 ; N a134 ; B 35 -14 754 705 ;
+C 187 ; WX 788 ; N a135 ; B 35 -14 754 705 ;
+C 188 ; WX 788 ; N a136 ; B 35 -14 754 705 ;
+C 189 ; WX 788 ; N a137 ; B 35 -14 754 705 ;
+C 190 ; WX 788 ; N a138 ; B 35 -14 754 705 ;
+C 191 ; WX 788 ; N a139 ; B 35 -14 754 705 ;
+C 192 ; WX 788 ; N a140 ; B 35 -14 754 705 ;
+C 193 ; WX 788 ; N a141 ; B 35 -14 754 705 ;
+C 194 ; WX 788 ; N a142 ; B 35 -14 754 705 ;
+C 195 ; WX 788 ; N a143 ; B 35 -14 754 705 ;
+C 196 ; WX 788 ; N a144 ; B 35 -14 754 705 ;
+C 197 ; WX 788 ; N a145 ; B 35 -14 754 705 ;
+C 198 ; WX 788 ; N a146 ; B 35 -14 754 705 ;
+C 199 ; WX 788 ; N a147 ; B 35 -14 754 705 ;
+C 200 ; WX 788 ; N a148 ; B 35 -14 754 705 ;
+C 201 ; WX 788 ; N a149 ; B 35 -14 754 705 ;
+C 202 ; WX 788 ; N a150 ; B 35 -14 754 705 ;
+C 203 ; WX 788 ; N a151 ; B 35 -14 754 705 ;
+C 204 ; WX 788 ; N a152 ; B 35 -14 754 705 ;
+C 205 ; WX 788 ; N a153 ; B 35 -14 754 705 ;
+C 206 ; WX 788 ; N a154 ; B 35 -14 754 705 ;
+C 207 ; WX 788 ; N a155 ; B 35 -14 754 705 ;
+C 208 ; WX 788 ; N a156 ; B 35 -14 754 705 ;
+C 209 ; WX 788 ; N a157 ; B 35 -14 754 705 ;
+C 210 ; WX 788 ; N a158 ; B 35 -14 754 705 ;
+C 211 ; WX 788 ; N a159 ; B 35 -14 754 705 ;
+C 212 ; WX 894 ; N a160 ; B 35 58 860 634 ;
+C 213 ; WX 838 ; N a161 ; B 35 152 803 540 ;
+C 214 ; WX 1016 ; N a163 ; B 34 152 981 540 ;
+C 215 ; WX 458 ; N a164 ; B 35 -127 422 820 ;
+C 216 ; WX 748 ; N a196 ; B 35 94 698 597 ;
+C 217 ; WX 924 ; N a165 ; B 35 140 890 552 ;
+C 218 ; WX 748 ; N a192 ; B 35 94 698 597 ;
+C 219 ; WX 918 ; N a166 ; B 35 166 884 526 ;
+C 220 ; WX 927 ; N a167 ; B 35 32 892 660 ;
+C 221 ; WX 928 ; N a168 ; B 35 129 891 562 ;
+C 222 ; WX 928 ; N a169 ; B 35 128 893 563 ;
+C 223 ; WX 834 ; N a170 ; B 35 155 799 537 ;
+C 224 ; WX 873 ; N a171 ; B 35 93 838 599 ;
+C 225 ; WX 828 ; N a172 ; B 35 104 791 588 ;
+C 226 ; WX 924 ; N a173 ; B 35 98 889 594 ;
+C 227 ; WX 924 ; N a162 ; B 35 98 889 594 ;
+C 228 ; WX 917 ; N a174 ; B 35 0 882 692 ;
+C 229 ; WX 930 ; N a175 ; B 35 84 896 608 ;
+C 230 ; WX 931 ; N a176 ; B 35 84 896 608 ;
+C 231 ; WX 463 ; N a177 ; B 35 -99 429 791 ;
+C 232 ; WX 883 ; N a178 ; B 35 71 848 623 ;
+C 233 ; WX 836 ; N a179 ; B 35 44 802 648 ;
+C 234 ; WX 836 ; N a193 ; B 35 44 802 648 ;
+C 235 ; WX 867 ; N a180 ; B 35 101 832 591 ;
+C 236 ; WX 867 ; N a199 ; B 35 101 832 591 ;
+C 237 ; WX 696 ; N a181 ; B 35 44 661 648 ;
+C 238 ; WX 696 ; N a200 ; B 35 44 661 648 ;
+C 239 ; WX 874 ; N a182 ; B 35 77 840 619 ;
+C 241 ; WX 874 ; N a201 ; B 35 73 840 615 ;
+C 242 ; WX 760 ; N a183 ; B 35 0 725 692 ;
+C 243 ; WX 946 ; N a184 ; B 35 160 911 533 ;
+C 244 ; WX 771 ; N a197 ; B 34 37 736 655 ;
+C 245 ; WX 865 ; N a185 ; B 35 207 830 481 ;
+C 246 ; WX 771 ; N a194 ; B 34 37 736 655 ;
+C 247 ; WX 888 ; N a198 ; B 34 -19 853 712 ;
+C 248 ; WX 967 ; N a186 ; B 35 124 932 568 ;
+C 249 ; WX 888 ; N a195 ; B 34 -19 853 712 ;
+C 250 ; WX 831 ; N a187 ; B 35 113 796 579 ;
+C 251 ; WX 873 ; N a188 ; B 36 118 838 578 ;
+C 252 ; WX 927 ; N a189 ; B 35 150 891 542 ;
+C 253 ; WX 970 ; N a190 ; B 35 76 931 616 ;
+C 254 ; WX 918 ; N a191 ; B 34 99 884 593 ;
+EndCharMetrics
+EndFontMetrics
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfAnnotations.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfAnnotations.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfAnnotations.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfAnnotations.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,74 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf.interfaces;
+
+import pdftk.com.lowagie.text.pdf.PdfAcroForm;
+import pdftk.com.lowagie.text.pdf.PdfAnnotation;
+import pdftk.com.lowagie.text.pdf.PdfFormField;
+
+public interface PdfAnnotations {
+
+ /**
+ * Use this methods to get the AcroForm object.
+ * Use this method only if you know what you're doing
+ * @return the PdfAcroform object of the PdfDocument
+ */
+ public PdfAcroForm getAcroForm();
+
+ /**
+ * Use this methods to add a PdfAnnotation
or a PdfFormField
+ * to the document. Only the top parent of a PdfFormField
+ * needs to be added.
+ * @param annot the PdfAnnotation
or the PdfFormField
to add
+ */
+ public void addAnnotation(PdfAnnotation annot);
+ /**
+ * Use this method to adds the PdfAnnotation
+ * to the calculation order array.
+ * @param annot the PdfAnnotation
to be added
+ */
+ public void addCalculationOrder(PdfFormField annot);
+
+ /**
+ * Use this method to set the signature flags.
+ * @param f the flags. This flags are ORed with current ones
+ */
+ public void setSigFlags(int f);
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfDocumentActions.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfDocumentActions.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfDocumentActions.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfDocumentActions.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,79 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf.interfaces;
+
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.pdf.PdfAction;
+import pdftk.com.lowagie.text.pdf.PdfName;
+
+/**
+ * A PDF document can have an open action and other additional actions.
+ */
+
+public interface PdfDocumentActions {
+
+ /**
+ * When the document opens it will jump to the destination with
+ * this name.
+ * @param name the name of the destination to jump to
+ */
+ public void setOpenAction(String name);
+
+ /**
+ * When the document opens this action
will be
+ * invoked.
+ * @param action the action to be invoked
+ */
+ public void setOpenAction(PdfAction action);
+
+ /**
+ * Additional-actions defining the actions to be taken in
+ * response to various trigger events affecting the document
+ * as a whole. The actions types allowed are: DOCUMENT_CLOSE
,
+ * WILL_SAVE
, DID_SAVE
, WILL_PRINT
+ * and DID_PRINT
.
+ *
+ * @param actionType the action type
+ * @param action the action to execute in response to the trigger
+ * @throws DocumentException on invalid action type
+ */
+ public void setAdditionalAction(PdfName actionType, PdfAction action) throws DocumentException;
+
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfEncryptionSettings.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfEncryptionSettings.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfEncryptionSettings.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfEncryptionSettings.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,88 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf.interfaces;
+
+import java.security.cert.Certificate;
+
+import pdftk.com.lowagie.text.DocumentException;
+
+/**
+ * Encryption settings are described in section 3.5 (more specifically
+ * section 3.5.2) of the PDF Reference 1.7.
+ * They are explained in section 3.3.3 of the book 'iText in Action'.
+ * The values of the different preferences were originally stored
+ * in class PdfWriter, but they have been moved to this separate interface
+ * for reasons of convenience.
+ */
+
+public interface PdfEncryptionSettings {
+
+
+ /**
+ * Sets the encryption options for this document. The userPassword and the
+ * ownerPassword can be null or have zero length. In this case the ownerPassword
+ * is replaced by a random string. The open permissions for the document can be
+ * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
+ * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
+ * The permissions can be combined by ORing them.
+ * @param userPassword the user password. Can be null or empty
+ * @param ownerPassword the owner password. Can be null or empty
+ * @param permissions the user permissions
+ * @param encryptionType the type of encryption. It can be one of STANDARD_ENCRYPTION_40, STANDARD_ENCRYPTION_128 or ENCRYPTION_AES128.
+ * Optionally DO_NOT_ENCRYPT_METADATA can be ored to output the metadata in cleartext
+ * @throws DocumentException if the document is already open
+ */
+ public void setEncryption(byte userPassword[], byte ownerPassword[], int permissions, int encryptionType) throws DocumentException;
+
+ /**
+ * Sets the certificate encryption options for this document. An array of one or more public certificates
+ * must be provided together with an array of the same size for the permissions for each certificate.
+ * The open permissions for the document can be
+ * AllowPrinting, AllowModifyContents, AllowCopy, AllowModifyAnnotations,
+ * AllowFillIn, AllowScreenReaders, AllowAssembly and AllowDegradedPrinting.
+ * The permissions can be combined by ORing them.
+ * Optionally DO_NOT_ENCRYPT_METADATA can be ored to output the metadata in cleartext
+ * @param certs the public certificates to be used for the encryption
+ * @param permissions the user permissions for each of the certificates
+ * @param encryptionType the type of encryption. It can be one of STANDARD_ENCRYPTION_40, STANDARD_ENCRYPTION_128 or ENCRYPTION_AES128.
+ * @throws DocumentException if the document is already open
+ */
+ public void setEncryption(Certificate[] certs, int[] permissions, int encryptionType) throws DocumentException;
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfPageActions.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfPageActions.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfPageActions.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfPageActions.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,73 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf.interfaces;
+
+import pdftk.com.lowagie.text.DocumentException;
+import pdftk.com.lowagie.text.pdf.PdfAction;
+import pdftk.com.lowagie.text.pdf.PdfName;
+import pdftk.com.lowagie.text.pdf.PdfTransition;
+
+/**
+ * A PDF page can have an open and/or close action.
+ */
+
+public interface PdfPageActions {
+
+ /**
+ * Sets the open and close page additional action.
+ * @param actionType the action type. It can be PdfWriter.PAGE_OPEN
+ * or PdfWriter.PAGE_CLOSE
+ * @param action the action to perform
+ * @throws DocumentException if the action type is invalid
+ */
+ public void setPageAction(PdfName actionType, PdfAction action) throws DocumentException;
+
+ /**
+ * Sets the display duration for the page (for presentations)
+ * @param seconds the number of seconds to display the page
+ */
+ public void setDuration(int seconds);
+
+ /**
+ * Sets the transition for the page
+ * @param transition the Transition object
+ */
+ public void setTransition(PdfTransition transition);
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfRunDirection.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfRunDirection.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfRunDirection.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfRunDirection.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,54 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf.interfaces;
+
+public interface PdfRunDirection {
+
+ /** Sets the run direction. This is only used as a placeholder
+ * as it does not affect anything.
+ * @param runDirection the run direction
+ */
+ public void setRunDirection(int runDirection);
+
+ /** Gets the run direction.
+ * @return the run direction
+ */
+ public int getRunDirection();
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfVersion.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfVersion.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfVersion.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfVersion.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,87 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf.interfaces;
+
+import pdftk.com.lowagie.text.pdf.PdfDeveloperExtension;
+import pdftk.com.lowagie.text.pdf.PdfName;
+
+/**
+ * The PDF version is described in the PDF Reference 1.7 p92
+ * (about the PDF Header) and page 139 (the version entry in
+ * the Catalog). You'll also find info about setting the version
+ * in the book 'iText in Action' sections 2.1.3 (PDF Header)
+ * and 3.3 (Version history).
+ */
+
+public interface PdfVersion {
+
+ /**
+ * If the PDF Header hasn't been written yet,
+ * this changes the version as it will appear in the PDF Header.
+ * If the PDF header was already written to the OutputStream,
+ * this changes the version as it will appear in the Catalog.
+ * @param version a character representing the PDF version
+ */
+ public void setPdfVersion(char version);
+ /**
+ * If the PDF Header hasn't been written yet,
+ * this changes the version as it will appear in the PDF Header,
+ * but only if the parameter refers to a higher version.
+ * If the PDF header was already written to the OutputStream,
+ * this changes the version as it will appear in the Catalog.
+ * @param version a character representing the PDF version
+ */
+ public void setAtLeastPdfVersion(char version);
+ /**
+ * Sets the PDF version as it will appear in the Catalog.
+ * Note that this only has effect if you use a later version
+ * than the one that appears in the header; this method
+ * ignores the parameter if you try to set a lower version.
+ * @param version the PDF name that will be used for the Version key in the catalog
+ */
+ public void setPdfVersion(PdfName version);
+ /**
+ * Adds a developer extension to the Extensions dictionary
+ * in the Catalog.
+ * @param de an object that contains the extensions prefix and dictionary
+ * @since 2.1.6
+ */
+ public void addDeveloperExtension(PdfDeveloperExtension de);
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfViewerPreferences.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfViewerPreferences.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfViewerPreferences.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfViewerPreferences.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,190 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf.interfaces;
+
+import pdftk.com.lowagie.text.pdf.PdfName;
+import pdftk.com.lowagie.text.pdf.PdfObject;
+
+/**
+ * Viewer preferences are described in section 3.6.1 and 8.1 of the
+ * PDF Reference 1.7 (Table 3.25 on p139-142 and Table 8.1 on p579-581).
+ * They are explained in section 13.1 of the book 'iText in Action'.
+ * The values of the different preferences were originally stored
+ * in class PdfWriter, but they have been moved to this separate interface
+ * for reasons of convenience.
+ */
+
+public interface PdfViewerPreferences {
+
+ /**
+ * Sets the page layout and page mode preferences by ORing one or two of these constants.
+ *
+ *
+ * The page layout to be used when the document is opened (choose one).
+ *
+ * PAGE_LAYOUT_SINGLE_PAGE - Display one page at a time. (default)
+ * PAGE_LAYOUT_ONE_COLUMN - Display the pages in one column.
+ * PAGE_LAYOUT_TWO_COLUMN_LEFT - Display the pages in two columns, with
+ * oddnumbered pages on the left.
+ * PAGE_LAYOUT_TWO_COLUMN_RIGHT - Display the pages in two columns, with
+ * oddnumbered pages on the right.
+ * PAGE_LAYOUT_TWO_PAGE_LEFT - Display the pages two at a time, with
+ * oddnumbered pages on the left.
+ * PAGE_LAYOUT_TWO_PAGE_RIGHT - Display the pages two at a time, with
+ * oddnumbered pages on the right.
+ *
+ * The page mode how the document should be displayed
+ * when opened (choose one).
+ *
+ * PAGE_MODE_USE_NONE - Neither document outline nor thumbnail images visible. (default)
+ * PAGE_MODE_USE_OUTLINES - Document outline visible.
+ * PAGE_MODE_USE_THUMBS - Thumbnail images visible.
+ * PAGE_MODE_FULL_SCREEN - Full-screen mode, with no menu bar, window
+ * controls, or any other window visible.
+ * PAGE_MODE_USE_OC - Optional content group panel visible
+ * PAGE_MODE_USE_ATTACHMENTS - Attachments panel visible
+ *
+ *
+ * For backward compatibility these values are also supported,
+ * but it's better to use method addViewerPreference(key, value)
+ * if you want to change the following preferences:
+ *
+ * HIDE_TOOLBAR - A flag specifying whether to hide the viewer application's tool
+ * bars when the document is active.
+ * HIDE_MENUBAR - A flag specifying whether to hide the viewer application's
+ * menu bar when the document is active.
+ * HIDE_WINDOW_UI - A flag specifying whether to hide user interface elements in
+ * the document's window (such as scroll bars and navigation controls),
+ * leaving only the document's contents displayed.
+ * FIT_WINDOW - A flag specifying whether to resize the document's window to
+ * fit the size of the first displayed page.
+ * CENTER_WINDOW - A flag specifying whether to position the document's window
+ * in the center of the screen.
+ * DISPLAY_DOC_TITLE - A flag specifying whether to display the document's title
+ * in the top bar.
+ * The predominant reading order for text. This entry has no direct effect on the
+ * document's contents or page numbering, but can be used to determine the relative
+ * positioning of pages when displayed side by side or printed n-up (choose one).
+ *
+ * DIRECTION_L2R - Left to right
+ * DIRECTION_R2L - Right to left (including vertical writing systems such as
+ * Chinese, Japanese, and Korean)
+ *
+ * The document's page mode, specifying how to display the
+ * document on exiting full-screen mode. It is meaningful only
+ * if the page mode is PageModeFullScreen (choose one).
+ *
+ * NON_FULL_SCREEN_PAGE_MODE_USE_NONE - Neither document outline nor thumbnail images
+ * visible
+ * NON_FULL_SCREEN_PAGE_MODE_USE_OUTLINES - Document outline visible
+ * NON_FULL_SCREEN_PAGE_MODE_USE_THUMBS - Thumbnail images visible
+ * NON_FULL_SCREEN_PAGE_MODE_USE_OC - Optional content group panel visible
+ *
+ * PRINT_SCALING_NONE - Indicates that the print dialog should reflect no page scaling.
+ *
+ * @param preferences the viewer preferences
+ * @see PdfViewerPreferences#addViewerPreference
+ */
+ public void setViewerPreferences(int preferences);
+
+ /**
+ * Adds a viewer preference.
+ *
+ * In case the key is one of these values:
+ *
+ * PdfName.HIDETOOLBAR
+ * PdfName.HIDEMENUBAR
+ * PdfName.HIDEWINDOWUI
+ * PdfName.FITWINDOW
+ * PdfName.CENTERWINDOW
+ * PdfName.DISPLAYDOCTITLE
+ *
+ * The value must be a of type PdfBoolean (true or false).
+ * In case the key is PdfName.NONFULLSCREENPAGEMODE ,
+ * the value must be one of these names:
+ *
+ * PdfName.USENONE
+ * PdfName.USEOUTLINES
+ * PdfName.USETHUMBS
+ * PdfName.USEOC
+ *
+ * In case the key is PdfName.DIRECTION,
+ * the value must be one of these names:
+ *
+ * PdfName.L2R
+ * PdfName.R2L
+ *
+ * In case the key is one of these values:
+ *
+ * PdfName.VIEWAREA
+ * PdfName.VIEWCLIP
+ * PdfName.PRINTAREA
+ * PdfName.PRINTCLIP
+ *
+ * The value must be one of these names:
+ *
+ * PdfName.MEDIABOX
+ * PdfName.CROPBOX
+ * PdfName.BLEEDBOX
+ * PdfName.TRIMBOX
+ * PdfName.ARTBOX
+ *
+ * In case the key is PdfName.PRINTSCALING , the value can be
+ *
+ * PdfName.APPDEFAULT
+ * PdfName.NONE
+ *
+ * In case the key is PdfName.DUPLEX , the value can be:
+ *
+ * PdfName.SIMPLEX
+ * PdfName.DUPLEXFLIPSHORTEDGE
+ * PdfName.DUPLEXFLIPLONGEDGE
+ *
+ * In case the key is PdfName.PICKTRAYBYPDFSIZE , the value must be of type PdfBoolean.
+ * In case the key is PdfName.PRINTPAGERANGE , the value must be of type PdfArray.
+ * In case the key is PdfName.NUMCOPIES , the value must be of type PdfNumber.
+ *
+ * @param key the name of the viewer preference
+ * @param value the value of the viewer preference
+ * @see PdfViewerPreferences#setViewerPreferences
+ */
+ public void addViewerPreference(PdfName key, PdfObject value);
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfXConformance.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfXConformance.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/interfaces/PdfXConformance.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/interfaces/PdfXConformance.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,63 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf.interfaces;
+
+public interface PdfXConformance {
+
+ /**
+ * Sets the PDF/X conformance level.
+ * Allowed values are PDFX1A2001, PDFX32002, PDFA1A and PDFA1B.
+ * It must be called before opening the document.
+ * @param pdfxConformance the conformance level
+ */
+ public void setPDFXConformance(int pdfxConformance);
+
+ /**
+ * Getter for the PDF/X Conformance value.
+ * @return the pdfxConformance
+ */
+ public int getPDFXConformance();
+
+ /**
+ * Checks if the PDF/X Conformance is necessary.
+ * @return true if the PDF has to be in conformance with any of the PDF/X specifications
+ */
+ public boolean isPdfX();
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/internal/PdfVersionImp.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/internal/PdfVersionImp.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/internal/PdfVersionImp.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/internal/PdfVersionImp.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,196 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf.internal;
+
+import java.io.IOException;
+
+import pdftk.com.lowagie.text.DocWriter;
+import pdftk.com.lowagie.text.pdf.OutputStreamCounter;
+import pdftk.com.lowagie.text.pdf.PdfDeveloperExtension;
+import pdftk.com.lowagie.text.pdf.PdfDictionary;
+import pdftk.com.lowagie.text.pdf.PdfName;
+import pdftk.com.lowagie.text.pdf.PdfWriter;
+import pdftk.com.lowagie.text.pdf.interfaces.PdfVersion;
+
+/**
+ * Stores the PDF version information,
+ * knows how to write a PDF Header,
+ * and how to add the version to the catalog (if necessary).
+ */
+
+public class PdfVersionImp implements PdfVersion {
+
+ /** Contains different strings that are part of the header. */
+ public static final byte[][] HEADER = {
+ DocWriter.getISOBytes("\n"),
+ DocWriter.getISOBytes("%PDF-"),
+ DocWriter.getISOBytes("\n%\u00e2\u00e3\u00cf\u00d3\n")
+ };
+
+ /** Indicates if the header was already written. */
+ protected boolean headerWasWritten = false;
+ /** Indicates if we are working in append mode. */
+ protected boolean appendmode = false;
+ /** The version that was or will be written to the header. */
+ protected char header_version = PdfWriter.VERSION_1_4;
+ /** The version that will be written to the catalog. */
+ protected PdfName catalog_version = null;
+ /**
+ * The extensions dictionary.
+ * @since 2.1.6
+ */
+ protected PdfDictionary extensions = null;
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.interfaces.PdfVersion#setPdfVersion(char)
+ */
+ public void setPdfVersion(char version) {
+ if (headerWasWritten || appendmode) {
+ setPdfVersion(getVersionAsName(version));
+ }
+ else {
+ this.header_version = version;
+ }
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.interfaces.PdfVersion#setAtLeastPdfVersion(char)
+ */
+ public void setAtLeastPdfVersion(char version) {
+ if (version > header_version) {
+ setPdfVersion(version);
+ }
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.interfaces.PdfVersion#setPdfVersion(pdftk.com.lowagie.text.pdf.PdfName)
+ */
+ public void setPdfVersion(PdfName version) {
+ if (catalog_version == null || catalog_version.compareTo(version) < 0) {
+ this.catalog_version = version;
+ }
+ }
+
+ /**
+ * Sets the append mode.
+ */
+ public void setAppendmode(boolean appendmode) {
+ this.appendmode = appendmode;
+ }
+
+ /**
+ * Writes the header to the OutputStreamCounter.
+ * @throws IOException
+ */
+ public void writeHeader(OutputStreamCounter os) throws IOException {
+ if (appendmode) {
+ os.write(HEADER[0]);
+ }
+ else {
+ os.write(HEADER[1]);
+ os.write(getVersionAsByteArray(header_version));
+ os.write(HEADER[2]);
+ headerWasWritten = true;
+ }
+ }
+
+ /**
+ * Returns the PDF version as a name.
+ * @param version the version character.
+ */
+ public PdfName getVersionAsName(char version) {
+ switch(version) {
+ case PdfWriter.VERSION_1_2:
+ return PdfWriter.PDF_VERSION_1_2;
+ case PdfWriter.VERSION_1_3:
+ return PdfWriter.PDF_VERSION_1_3;
+ case PdfWriter.VERSION_1_4:
+ return PdfWriter.PDF_VERSION_1_4;
+ case PdfWriter.VERSION_1_5:
+ return PdfWriter.PDF_VERSION_1_5;
+ case PdfWriter.VERSION_1_6:
+ return PdfWriter.PDF_VERSION_1_6;
+ case PdfWriter.VERSION_1_7:
+ return PdfWriter.PDF_VERSION_1_7;
+ default:
+ return PdfWriter.PDF_VERSION_1_4;
+ }
+ }
+
+ /**
+ * Returns the version as a byte[].
+ * @param version the version character
+ */
+ public byte[] getVersionAsByteArray(char version) {
+ return DocWriter.getISOBytes(getVersionAsName(version).toString().substring(1));
+ }
+
+ /** Adds the version to the Catalog dictionary. */
+ public void addToCatalog(PdfDictionary catalog) {
+ if(catalog_version != null) {
+ catalog.put(PdfName.VERSION, catalog_version);
+ }
+ if (extensions != null) {
+ catalog.put(PdfName.EXTENSIONS, extensions);
+ }
+ }
+
+ /**
+ * @see pdftk.com.lowagie.text.pdf.interfaces.PdfVersion#addDeveloperExtension(pdftk.com.lowagie.text.pdf.PdfDeveloperExtension)
+ * @since 2.1.6
+ */
+ public void addDeveloperExtension(PdfDeveloperExtension de) {
+ if (extensions == null) {
+ extensions = new PdfDictionary();
+ }
+ else {
+ PdfDictionary extension = extensions.getAsDict(de.getPrefix());
+ if (extension != null) {
+ int diff = de.getBaseversion().compareTo(extension.getAsName(PdfName.BASEVERSION));
+ if (diff < 0)
+ return;
+ diff = de.getExtensionLevel() - extension.getAsNumber(PdfName.EXTENSIONLEVEL).intValue();
+ if (diff <= 0)
+ return;
+ }
+ }
+ extensions.put(de.getPrefix(), de.getDeveloperExtensions());
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/pdf/internal/PdfViewerPreferencesImp.java pdftk-2.01/java/pdftk/com/lowagie/text/pdf/internal/PdfViewerPreferencesImp.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/pdf/internal/PdfViewerPreferencesImp.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/pdf/internal/PdfViewerPreferencesImp.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,352 @@
+/*
+ * $Id$
+ *
+ * Copyright 2006 Bruno Lowagie
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.pdf.internal;
+
+import pdftk.com.lowagie.text.pdf.PdfArray;
+import pdftk.com.lowagie.text.pdf.PdfBoolean;
+import pdftk.com.lowagie.text.pdf.PdfDictionary;
+import pdftk.com.lowagie.text.pdf.PdfName;
+import pdftk.com.lowagie.text.pdf.PdfNumber;
+import pdftk.com.lowagie.text.pdf.PdfObject;
+import pdftk.com.lowagie.text.pdf.PdfReader;
+import pdftk.com.lowagie.text.pdf.PdfWriter;
+import pdftk.com.lowagie.text.pdf.interfaces.PdfViewerPreferences;
+
+/**
+ * Stores the information concerning viewer preferences,
+ * and contains the business logic that allows you to set viewer preferences.
+ */
+
+public class PdfViewerPreferencesImp implements PdfViewerPreferences {
+ public static final PdfName[] VIEWER_PREFERENCES = {
+ PdfName.HIDETOOLBAR, // 0
+ PdfName.HIDEMENUBAR, // 1
+ PdfName.HIDEWINDOWUI, // 2
+ PdfName.FITWINDOW, // 3
+ PdfName.CENTERWINDOW, // 4
+ PdfName.DISPLAYDOCTITLE, // 5
+ PdfName.NONFULLSCREENPAGEMODE, // 6
+ PdfName.DIRECTION, // 7
+ PdfName.VIEWAREA, // 8
+ PdfName.VIEWCLIP, // 9
+ PdfName.PRINTAREA, // 10
+ PdfName.PRINTCLIP, // 11
+ PdfName.PRINTSCALING, // 12
+ PdfName.DUPLEX, // 13
+ PdfName.PICKTRAYBYPDFSIZE, // 14
+ PdfName.PRINTPAGERANGE, // 15
+ PdfName.NUMCOPIES // 16
+ };
+
+
+ /** A series of viewer preferences. */
+ public static final PdfName NONFULLSCREENPAGEMODE_PREFERENCES[] = {
+ PdfName.USENONE, PdfName.USEOUTLINES, PdfName.USETHUMBS, PdfName.USEOC
+ };
+ /** A series of viewer preferences. */
+ public static final PdfName DIRECTION_PREFERENCES[] = {
+ PdfName.L2R, PdfName.R2L
+ };
+ /** A series of viewer preferences. */
+ public static final PdfName PAGE_BOUNDARIES[] = {
+ PdfName.MEDIABOX, PdfName.CROPBOX, PdfName.BLEEDBOX, PdfName.TRIMBOX, PdfName.ARTBOX
+ };
+ /** A series of viewer preferences */
+ public static final PdfName PRINTSCALING_PREFERENCES[] = {
+ PdfName.APPDEFAULT, PdfName.NONE
+ };
+ /** A series of viewer preferences. */
+ public static final PdfName DUPLEX_PREFERENCES[] = {
+ PdfName.SIMPLEX, PdfName.DUPLEXFLIPSHORTEDGE, PdfName.DUPLEXFLIPLONGEDGE
+ };
+
+ /** This value will hold the viewer preferences for the page layout and page mode. */
+ private int pageLayoutAndMode = 0;
+
+ /** This dictionary holds the viewer preferences (other than page layout and page mode). */
+ private PdfDictionary viewerPreferences = new PdfDictionary();
+
+ /** The mask to decide if a ViewerPreferences dictionary is needed */
+ private static final int viewerPreferencesMask = 0xfff000;
+
+ /**
+ * Returns the page layout and page mode value.
+ */
+ public int getPageLayoutAndMode() {
+ return pageLayoutAndMode;
+ }
+
+ /**
+ * Returns the viewer preferences.
+ */
+ public PdfDictionary getViewerPreferences() {
+ return viewerPreferences;
+ }
+
+ /**
+ * Sets the viewer preferences as the sum of several constants.
+ *
+ * @param preferences
+ * the viewer preferences
+ * @see PdfViewerPreferences#setViewerPreferences
+ */
+ public void setViewerPreferences(int preferences) {
+ this.pageLayoutAndMode |= preferences;
+ // for backwards compatibility, it is also possible
+ // to set the following viewer preferences with this method:
+ if ((preferences & viewerPreferencesMask) != 0) {
+ pageLayoutAndMode = ~viewerPreferencesMask & pageLayoutAndMode;
+ if ((preferences & PdfWriter.HideToolbar) != 0)
+ viewerPreferences.put(PdfName.HIDETOOLBAR, PdfBoolean.PDFTRUE);
+ if ((preferences & PdfWriter.HideMenubar) != 0)
+ viewerPreferences.put(PdfName.HIDEMENUBAR, PdfBoolean.PDFTRUE);
+ if ((preferences & PdfWriter.HideWindowUI) != 0)
+ viewerPreferences.put(PdfName.HIDEWINDOWUI, PdfBoolean.PDFTRUE);
+ if ((preferences & PdfWriter.FitWindow) != 0)
+ viewerPreferences.put(PdfName.FITWINDOW, PdfBoolean.PDFTRUE);
+ if ((preferences & PdfWriter.CenterWindow) != 0)
+ viewerPreferences.put(PdfName.CENTERWINDOW, PdfBoolean.PDFTRUE);
+ if ((preferences & PdfWriter.DisplayDocTitle) != 0)
+ viewerPreferences.put(PdfName.DISPLAYDOCTITLE, PdfBoolean.PDFTRUE);
+
+ if ((preferences & PdfWriter.NonFullScreenPageModeUseNone) != 0)
+ viewerPreferences.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USENONE);
+ else if ((preferences & PdfWriter.NonFullScreenPageModeUseOutlines) != 0)
+ viewerPreferences.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USEOUTLINES);
+ else if ((preferences & PdfWriter.NonFullScreenPageModeUseThumbs) != 0)
+ viewerPreferences.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USETHUMBS);
+ else if ((preferences & PdfWriter.NonFullScreenPageModeUseOC) != 0)
+ viewerPreferences.put(PdfName.NONFULLSCREENPAGEMODE, PdfName.USEOC);
+
+ if ((preferences & PdfWriter.DirectionL2R) != 0)
+ viewerPreferences.put(PdfName.DIRECTION, PdfName.L2R);
+ else if ((preferences & PdfWriter.DirectionR2L) != 0)
+ viewerPreferences.put(PdfName.DIRECTION, PdfName.R2L);
+
+ if ((preferences & PdfWriter.PrintScalingNone) != 0)
+ viewerPreferences.put(PdfName.PRINTSCALING, PdfName.NONE);
+ }
+ }
+
+ /**
+ * Given a key for a viewer preference (a PdfName object),
+ * this method returns the index in the VIEWER_PREFERENCES array.
+ * @param key a PdfName referring to a viewer preference
+ * @return an index in the VIEWER_PREFERENCES array
+ */
+ private int getIndex(PdfName key) {
+ for (int i = 0; i < VIEWER_PREFERENCES.length; i++) {
+ if (VIEWER_PREFERENCES[i].equals(key))
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Checks if some value is valid for a certain key.
+ */
+ private boolean isPossibleValue(PdfName value, PdfName[] accepted) {
+ for (int i = 0; i < accepted.length; i++) {
+ if (accepted[i].equals(value)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Sets the viewer preferences for printing.
+ */
+ public void addViewerPreference(PdfName key, PdfObject value) {
+ switch(getIndex(key)) {
+ case 0: // HIDETOOLBAR
+ case 1: // HIDEMENUBAR
+ case 2: // HIDEWINDOWUI
+ case 3: // FITWINDOW
+ case 4: // CENTERWINDOW
+ case 5: // DISPLAYDOCTITLE
+ case 14: // PICKTRAYBYPDFSIZE
+ if (value instanceof PdfBoolean) {
+ viewerPreferences.put(key, value);
+ }
+ break;
+ case 6: // NONFULLSCREENPAGEMODE
+ if (value instanceof PdfName
+ && isPossibleValue((PdfName)value, NONFULLSCREENPAGEMODE_PREFERENCES)) {
+ viewerPreferences.put(key, value);
+ }
+ break;
+ case 7: // DIRECTION
+ if (value instanceof PdfName
+ && isPossibleValue((PdfName)value, DIRECTION_PREFERENCES)) {
+ viewerPreferences.put(key, value);
+ }
+ break;
+ case 8: // VIEWAREA
+ case 9: // VIEWCLIP
+ case 10: // PRINTAREA
+ case 11: // PRINTCLIP
+ if (value instanceof PdfName
+ && isPossibleValue((PdfName)value, PAGE_BOUNDARIES)) {
+ viewerPreferences.put(key, value);
+ }
+ break;
+ case 12: // PRINTSCALING
+ if (value instanceof PdfName
+ && isPossibleValue((PdfName)value, PRINTSCALING_PREFERENCES)) {
+ viewerPreferences.put(key, value);
+ }
+ break;
+ case 13: // DUPLEX
+ if (value instanceof PdfName
+ && isPossibleValue((PdfName)value, DUPLEX_PREFERENCES)) {
+ viewerPreferences.put(key, value);
+ }
+ break;
+ case 15: // PRINTPAGERANGE
+ if (value instanceof PdfArray) {
+ viewerPreferences.put(key, value);
+ }
+ break;
+ case 16: // NUMCOPIES
+ if (value instanceof PdfNumber) {
+ viewerPreferences.put(key, value);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Adds the viewer preferences defined in the preferences parameter to a
+ * PdfDictionary (more specifically the root or catalog of a PDF file).
+ *
+ * @param catalog
+ */
+ public void addToCatalog(PdfDictionary catalog) {
+ // Page Layout
+ catalog.remove(PdfName.PAGELAYOUT);
+ if ((pageLayoutAndMode & PdfWriter.PageLayoutSinglePage) != 0)
+ catalog.put(PdfName.PAGELAYOUT, PdfName.SINGLEPAGE);
+ else if ((pageLayoutAndMode & PdfWriter.PageLayoutOneColumn) != 0)
+ catalog.put(PdfName.PAGELAYOUT, PdfName.ONECOLUMN);
+ else if ((pageLayoutAndMode & PdfWriter.PageLayoutTwoColumnLeft) != 0)
+ catalog.put(PdfName.PAGELAYOUT, PdfName.TWOCOLUMNLEFT);
+ else if ((pageLayoutAndMode & PdfWriter.PageLayoutTwoColumnRight) != 0)
+ catalog.put(PdfName.PAGELAYOUT, PdfName.TWOCOLUMNRIGHT);
+ else if ((pageLayoutAndMode & PdfWriter.PageLayoutTwoPageLeft) != 0)
+ catalog.put(PdfName.PAGELAYOUT, PdfName.TWOPAGELEFT);
+ else if ((pageLayoutAndMode & PdfWriter.PageLayoutTwoPageRight) != 0)
+ catalog.put(PdfName.PAGELAYOUT, PdfName.TWOPAGERIGHT);
+
+ // Page Mode
+ catalog.remove(PdfName.PAGEMODE);
+ if ((pageLayoutAndMode & PdfWriter.PageModeUseNone) != 0)
+ catalog.put(PdfName.PAGEMODE, PdfName.USENONE);
+ else if ((pageLayoutAndMode & PdfWriter.PageModeUseOutlines) != 0)
+ catalog.put(PdfName.PAGEMODE, PdfName.USEOUTLINES);
+ else if ((pageLayoutAndMode & PdfWriter.PageModeUseThumbs) != 0)
+ catalog.put(PdfName.PAGEMODE, PdfName.USETHUMBS);
+ else if ((pageLayoutAndMode & PdfWriter.PageModeFullScreen) != 0)
+ catalog.put(PdfName.PAGEMODE, PdfName.FULLSCREEN);
+ else if ((pageLayoutAndMode & PdfWriter.PageModeUseOC) != 0)
+ catalog.put(PdfName.PAGEMODE, PdfName.USEOC);
+ else if ((pageLayoutAndMode & PdfWriter.PageModeUseAttachments) != 0)
+ catalog.put(PdfName.PAGEMODE, PdfName.USEATTACHMENTS);
+
+ // viewer preferences (Table 8.1 of the PDF Reference)
+ catalog.remove(PdfName.VIEWERPREFERENCES);
+ if (viewerPreferences.size() > 0) {
+ catalog.put(PdfName.VIEWERPREFERENCES, viewerPreferences);
+ }
+ }
+
+ public static PdfViewerPreferencesImp getViewerPreferences(PdfDictionary catalog) {
+ PdfViewerPreferencesImp preferences = new PdfViewerPreferencesImp();
+ int prefs = 0;
+ PdfName name = null;
+ // page layout
+ PdfObject obj = PdfReader.getPdfObjectRelease(catalog.get(PdfName.PAGELAYOUT));
+ if (obj != null && obj.isName()) {
+ name = (PdfName) obj;
+ if (name.equals(PdfName.SINGLEPAGE))
+ prefs |= PdfWriter.PageLayoutSinglePage;
+ else if (name.equals(PdfName.ONECOLUMN))
+ prefs |= PdfWriter.PageLayoutOneColumn;
+ else if (name.equals(PdfName.TWOCOLUMNLEFT))
+ prefs |= PdfWriter.PageLayoutTwoColumnLeft;
+ else if (name.equals(PdfName.TWOCOLUMNRIGHT))
+ prefs |= PdfWriter.PageLayoutTwoColumnRight;
+ else if (name.equals(PdfName.TWOPAGELEFT))
+ prefs |= PdfWriter.PageLayoutTwoPageLeft;
+ else if (name.equals(PdfName.TWOPAGERIGHT))
+ prefs |= PdfWriter.PageLayoutTwoPageRight;
+ }
+ // page mode
+ obj = PdfReader.getPdfObjectRelease(catalog.get(PdfName.PAGEMODE));
+ if (obj != null && obj.isName()) {
+ name = (PdfName) obj;
+ if (name.equals(PdfName.USENONE))
+ prefs |= PdfWriter.PageModeUseNone;
+ else if (name.equals(PdfName.USEOUTLINES))
+ prefs |= PdfWriter.PageModeUseOutlines;
+ else if (name.equals(PdfName.USETHUMBS))
+ prefs |= PdfWriter.PageModeUseThumbs;
+ else if (name.equals(PdfName.FULLSCREEN))
+ prefs |= PdfWriter.PageModeFullScreen;
+ else if (name.equals(PdfName.USEOC))
+ prefs |= PdfWriter.PageModeUseOC;
+ else if (name.equals(PdfName.USEATTACHMENTS))
+ prefs |= PdfWriter.PageModeUseAttachments;
+ }
+ // set page layout and page mode preferences
+ preferences.setViewerPreferences(prefs);
+ // other preferences
+ obj = PdfReader.getPdfObjectRelease(catalog
+ .get(PdfName.VIEWERPREFERENCES));
+ if (obj != null && obj.isDictionary()) {
+ PdfDictionary vp = (PdfDictionary) obj;
+ for (int i = 0; i < VIEWER_PREFERENCES.length; i++) {
+ obj = PdfReader.getPdfObjectRelease(vp.get(VIEWER_PREFERENCES[i]));
+ preferences.addViewerPreference(VIEWER_PREFERENCES[i], obj);
+ }
+ }
+ return preferences;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/DublinCoreSchema.java pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/DublinCoreSchema.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/DublinCoreSchema.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/DublinCoreSchema.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,177 @@
+/*
+ * $Id: DublinCoreSchema.java,v 1.5 2005/09/08 07:50:15 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2005 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.xml.xmp;
+
+import java.io.IOException;
+
+/**
+ * An implementation of an XmpSchema.
+ */
+public class DublinCoreSchema extends XmpSchema {
+
+ /** default namespace identifier*/
+ public static final String DEFAULT_XPATH_ID = "dc";
+ /** default namespace uri*/
+ public static final String DEFAULT_XPATH_URI = "http://purl.org/dc/elements/1.1/";
+
+ /** External Contributors to the resource (other than the authors). */
+ public static final String CONTRIBUTOR = "dc:contributor";
+ /** The extent or scope of the resource. */
+ public static final String COVERAGE = "dc:coverage";
+ /** The authors of the resource (listed in order of precedence, if significant). */
+ public static final String CREATOR = "dc:creator";
+ /** Date(s) that something interesting happened to the resource. */
+ public static final String DATE = "dc:date";
+ /** A textual description of the content of the resource. Multiple values may be present for different languages. */
+ public static final String DESCRIPTION = "dc:description";
+ /** The file format used when saving the resource. Tools and applications should set this property to the save format of the data. It may include appropriate qualifiers. */
+ public static final String FORMAT = "dc:format";
+ /** Unique identifier of the resource. */
+ public static final String IDENTIFIER = "dc:identifier";
+ /** An unordered array specifying the languages used in the resource. */
+ public static final String LANGUAGE = "dc:language";
+ /** Publishers. */
+ public static final String PUBLISHER = "dc:publisher";
+ /** Relationships to other documents. */
+ public static final String RELATION = "dc:relation";
+ /** Informal rights statement, selected by language. */
+ public static final String RIGHTS = "dc:rights";
+ /** Unique identifier of the work from which this resource was derived. */
+ public static final String SOURCE = "dc:source";
+ /** An unordered array of descriptive phrases or keywords that specify the topic of the content of the resource. */
+ public static final String SUBJECT = "dc:subject";
+ /** The title of the document, or the name given to the resource. Typically, it will be a name by which the resource is formally known. */
+ public static final String TITLE = "dc:title";
+ /** A document type; for example, novel, poem, or working paper. */
+ public static final String TYPE = "dc:type";
+
+
+ /**
+ * @throws IOException
+ */
+ public DublinCoreSchema() throws IOException {
+ super("xmlns:" + DEFAULT_XPATH_ID + "=\"" + DEFAULT_XPATH_URI + "\"");
+ setProperty(FORMAT, "application/pdf");
+ }
+
+ /**
+ * Adds a title.
+ * @param title
+ */
+ public void addTitle(String title) {
+ setProperty(TITLE, title);
+ }
+
+ /**
+ * Adds a description.
+ * @param desc
+ */
+ public void addDescription(String desc) {
+ setProperty(DESCRIPTION, desc);
+ }
+
+ /**
+ * Adds a subject.
+ * @param subject
+ */
+ public void addSubject(String subject) {
+ XmpArray array = new XmpArray(XmpArray.UNORDERED);
+ array.add(subject);
+ setProperty(SUBJECT, array);
+ }
+
+
+ /**
+ * Adds a subject.
+ * @param subject array of subjects
+ */
+ public void addSubject(String[] subject) {
+ XmpArray array = new XmpArray(XmpArray.UNORDERED);
+ for (int i = 0; i < subject.length; i++) {
+ array.add(subject[i]);
+ }
+ setProperty(SUBJECT, array);
+ }
+
+ /**
+ * Adds a single author.
+ * @param author
+ */
+ public void addAuthor(String author) {
+ XmpArray array = new XmpArray(XmpArray.ORDERED);
+ array.add(author);
+ setProperty(CREATOR, array);
+ }
+
+ /**
+ * Adds an array of authors.
+ * @param author
+ */
+ public void addAuthor(String[] author) {
+ XmpArray array = new XmpArray(XmpArray.ORDERED);
+ for (int i = 0; i < author.length; i++) {
+ array.add(author[i]);
+ }
+ setProperty(CREATOR, array);
+ }
+
+ /**
+ * Adds a single publisher.
+ * @param publisher
+ */
+ public void addPublisher(String publisher) {
+ XmpArray array = new XmpArray(XmpArray.ORDERED);
+ array.add(publisher);
+ setProperty(PUBLISHER, array);
+ }
+
+ /**
+ * Adds an array of publishers.
+ * @param publisher
+ */
+ public void addPublisher(String[] publisher) {
+ XmpArray array = new XmpArray(XmpArray.ORDERED);
+ for (int i = 0; i < publisher.length; i++) {
+ array.add(publisher[i]);
+ }
+ setProperty(PUBLISHER, array);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/PdfSchema.java pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/PdfSchema.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/PdfSchema.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/PdfSchema.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,95 @@
+/*
+ * $Id: PdfSchema.java,v 1.4 2005/09/08 07:50:15 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2005 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.xml.xmp;
+
+import pdftk.com.lowagie.text.Document;
+import java.io.IOException;
+
+/**
+ * An implementation of an XmpSchema.
+ */
+public class PdfSchema extends XmpSchema {
+
+ /** default namespace identifier*/
+ public static final String DEFAULT_XPATH_ID = "pdf";
+ /** default namespace uri*/
+ public static final String DEFAULT_XPATH_URI = "http://ns.adobe.com/pdf/1.3/";
+
+ /** Keywords. */
+ public static final String KEYWORDS = "pdf:Keywords";
+ /** The PDF file version (for example: 1.0, 1.3, and so on). */
+ public static final String VERSION = "pdf:PDFVersion";
+ /** The Producer. */
+ public static final String PRODUCER = "pdf:Producer";
+
+
+ /**
+ * @throws IOException
+ */
+ public PdfSchema() throws IOException {
+ super("xmlns:" + DEFAULT_XPATH_ID + "=\"" + DEFAULT_XPATH_URI + "\"");
+ addProducer(Document.getVersion());
+ }
+
+ /**
+ * Adds keywords.
+ * @param keywords
+ */
+ public void addKeywords(String keywords) {
+ setProperty(KEYWORDS, keywords);
+ }
+
+ /**
+ * Adds the producer.
+ * @param producer
+ */
+ public void addProducer(String producer) {
+ setProperty(PRODUCER, producer);
+ }
+
+ /**
+ * Adds the version.
+ * @param version
+ */
+ public void addVersion(String version) {
+ setProperty(VERSION, version);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/XmpArray.java pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/XmpArray.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/XmpArray.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/XmpArray.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,89 @@
+/*
+ * $Id: XmpArray.java,v 1.2 2005/09/03 12:50:41 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2005 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.xml.xmp;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * StringBuffer to construct an XMP array.
+ */
+public class XmpArray extends ArrayList {
+
+ /** An array that is unordered. */
+ public static final String UNORDERED = "rdf:Bag";
+ /** An array that is ordered. */
+ public static final String ORDERED = "rdf:Seq";
+ /** An array with alternatives. */
+ public static final String ALTERNATIVE = "rdf:Alt";
+
+ /** the type of array. */
+ protected String type;
+
+ /**
+ * Creates an XmpArray.
+ * @param type the type of array: UNORDERED, ORDERED or ALTERNATIVE.
+ */
+ public XmpArray(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns the String representation of the XmpArray.
+ * @return a String representation
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer("<");
+ buf.append(type);
+ buf.append(">");
+ String s;
+ for (Iterator i = iterator(); i.hasNext(); ) {
+ s = (String) i.next();
+ buf.append("");
+ buf.append(XmpSchema.escape(s));
+ buf.append(" ");
+ }
+ buf.append("");
+ buf.append(type);
+ buf.append(">");
+ return buf.toString();
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/XmpBasicSchema.java pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/XmpBasicSchema.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/XmpBasicSchema.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/XmpBasicSchema.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,131 @@
+/*
+ * $Id: XmpBasicSchema.java,v 1.4 2005/09/08 07:50:15 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2005 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.xml.xmp;
+
+import java.io.IOException;
+
+/**
+ * An implementation of an XmpSchema.
+ */
+public class XmpBasicSchema extends XmpSchema {
+
+ /** default namespace identifier*/
+ public static final String DEFAULT_XPATH_ID = "xmp";
+ /** default namespace uri*/
+ public static final String DEFAULT_XPATH_URI = "http://ns.adobe.com/xap/1.0/";
+
+ /** An unordered array specifying properties that were edited outside the authoring application. Each item should contain a single namespace and XPath separated by one ASCII space (U+0020). */
+ public static final String ADVISORY = "xmp:Advisory";
+ /** The base URL for relative URLs in the document content. If this document contains Internet links, and those links are relative, they are relative to this base URL. This property provides a standard way for embedded relative URLs to be interpreted by tools. Web authoring tools should set the value based on their notion of where URLs will be interpreted. */
+ public static final String BASEURL = "xmp:BaseURL";
+ /** The date and time the resource was originally created. */
+ public static final String CREATEDATE = "xmp:CreateDate";
+ /** The name of the first known tool used to create the resource. If history is present in the metadata, this value should be equivalent to that of xmpMM:History's softwareAgent property. */
+ public static final String CREATORTOOL = "xmp:CreatorTool";
+ /** An unordered array of text strings that unambiguously identify the resource within a given context. */
+ public static final String IDENTIFIER = "xmp:Identifier";
+ /** The date and time that any metadata for this resource was last changed. */
+ public static final String METADATADATE = "xmp:MetadataDate";
+ /** The date and time the resource was last modified. */
+ public static final String MODIFYDATE = "xmp:ModifyDate";
+ /** A short informal name for the resource. */
+ public static final String NICKNAME = "xmp:Nickname";
+ /** An alternative array of thumbnail images for a file, which can differ in characteristics such as size or image encoding. */
+ public static final String THUMBNAILS = "xmp:Thumbnails";
+
+
+ /**
+ * @throws IOException
+ */
+ public XmpBasicSchema() throws IOException {
+ super("xmlns:" + DEFAULT_XPATH_ID + "=\"" + DEFAULT_XPATH_URI + "\"");
+ }
+
+ /**
+ * Adds the creatortool.
+ * @param creator
+ */
+ public void addCreatorTool(String creator) {
+ setProperty(CREATORTOOL, creator);
+ }
+
+ /**
+ * Adds the creation date.
+ * @param date
+ */
+ public void addCreateDate(String date) {
+ setProperty(CREATEDATE, date);
+ }
+
+ /**
+ * Adds the modification date.
+ * @param date
+ */
+ public void addModDate(String date) {
+ setProperty(MODIFYDATE, date);
+ }
+
+ /**
+ * Adds the meta data date.
+ * @param date
+ */
+ public void addMetaDataDate(String date) {
+ setProperty(METADATADATE, date);
+ }
+
+ /** Adds the identifier.
+ * @param id
+ */
+ public void addIdentifiers(String[] id) {
+ XmpArray array = new XmpArray(XmpArray.UNORDERED);
+ for (int i = 0; i < id.length; i++) {
+ array.add(id[i]);
+ }
+ setProperty(IDENTIFIER, array);
+ }
+
+ /** Adds the nickname.
+ * @param name
+ */
+ public void addNickname(String name) {
+ setProperty(NICKNAME, name);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/XmpMMSchema.java pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/XmpMMSchema.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/XmpMMSchema.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/XmpMMSchema.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,87 @@
+/*
+ * $Id: XmpMMSchema.java,v 1.3 2005/09/08 07:50:15 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2005 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.xml.xmp;
+
+import java.io.IOException;
+
+/**
+ * An implementation of an XmpSchema.
+ */
+public class XmpMMSchema extends XmpSchema {
+
+ /** default namespace identifier*/
+ public static final String DEFAULT_XPATH_ID = "xmpMM";
+ /** default namespace uri*/
+ public static final String DEFAULT_XPATH_URI = "http://ns.adobe.com/xap/1.0/mm/";
+
+
+ /** A reference to the original document from which this one is derived. It is a minimal reference; missing components can be assumed to be unchanged. For example, a new version might only need to specify the instance ID and version number of the previous version, or a rendition might only need to specify the instance ID and rendition class of the original. */
+ public static final String DERIVEDFROM = "xmpMM:DerivedFrom";
+ /** The common identifier for all versions and renditions of a document. */
+ public static final String DOCUMENTID = "xmpMM:DocumentID";
+ /** An ordered array of high-level user actions that resulted in this resource. It is intended to give human readers a general indication of the steps taken to make the changes from the previous version to this one. The list should be at an abstract level; it is not intended to be an exhaustive keystroke or other detailed history. */
+ public static final String HISTORY = "xmpMM:History";
+ /** A reference to the document as it was prior to becoming managed. It is set when a managed document is introduced to an asset management system that does not currently own it. It may or may not include references to different management systems. */
+ public static final String MANAGEDFROM = "xmpMM:ManagedFrom";
+ /** The name of the asset management system that manages this resource. */
+ public static final String MANAGER = "xmpMM:Manager";
+ /** A URI identifying the managed resource to the asset management system; the presence of this property is the formal indication that this resource is managed. The form and content of this URI is private to the asset management system. */
+ public static final String MANAGETO = "xmpMM:ManageTo";
+ /** A URI that can be used to access information about the managed resource through a web browser. It might require a custom browser plugin. */
+ public static final String MANAGEUI = "xmpMM:ManageUI";
+ /** Specifies a particular variant of the asset management system. The format of this property is private to the specific asset management system. */
+ public static final String MANAGERVARIANT = "xmpMM:ManagerVariant";
+ /** The rendition class name for this resource.*/
+ public static final String RENDITIONCLASS = "xmpMM:RenditionClass";
+ /** Can be used to provide additional rendition parameters that are too complex or verbose to encode in xmpMM: RenditionClass. */
+ public static final String RENDITIONPARAMS = "xmpMM:RenditionParams";
+ /** The document version identifier for this resource. */
+ public static final String VERSIONID = "xmpMM:VersionID";
+ /** The version history associated with this resource.*/
+ public static final String VERSIONS = "xmpMM:Versions";
+
+ /**
+ * @throws IOException
+ */
+ public XmpMMSchema() throws IOException {
+ super("xmlns:" + DEFAULT_XPATH_ID + "=\"" + DEFAULT_XPATH_URI + "\"");
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/XmpSchema.java pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/XmpSchema.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/XmpSchema.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/XmpSchema.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,148 @@
+/*
+ * $Id: XmpSchema.java,v 1.5 2005/09/08 10:27:29 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2005 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.xml.xmp;
+
+import java.util.Enumeration;
+import java.util.Properties;
+
+/**
+ * Abstract superclass of the XmpSchemas supported by iText.
+ */
+public abstract class XmpSchema extends Properties {
+
+ /** the namesspace */
+ protected String xmlns;
+
+ /** Constructs an XMP schema.
+ * @param xmlns
+ */
+ public XmpSchema(String xmlns) {
+ super();
+ this.xmlns = xmlns;
+ }
+ /**
+ * The String representation of the contents.
+ * @return a String representation.
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ for (Enumeration e = this.propertyNames(); e.hasMoreElements(); ) {
+ process(buf, e.nextElement());
+ }
+ return buf.toString();
+ }
+ /**
+ * Processes a property
+ * @param buf
+ * @param p
+ */
+ protected void process(StringBuffer buf, Object p) {
+ buf.append("<");
+ buf.append(p);
+ buf.append(">");
+ buf.append(this.get(p));
+ buf.append("");
+ buf.append(p);
+ buf.append(">");
+ }
+ /**
+ * @return Returns the xmlns.
+ */
+ public String getXmlns() {
+ return xmlns;
+ }
+
+ /**
+ * @param key
+ * @param value
+ * @return the previous property (null if there wasn't one)
+ */
+ public synchronized Object addProperty(String key, String value) {
+ return this.setProperty(key, value);
+ }
+
+ /**
+ * @see java.util.Properties#setProperty(java.lang.String, java.lang.String)
+ */
+ public synchronized Object setProperty(String key, String value) {
+ return super.setProperty(key, escape(value));
+ }
+
+ /**
+ * @see java.util.Properties#setProperty(java.lang.String, java.lang.String)
+ *
+ * @param key
+ * @param value
+ * @return the previous property (null if there wasn't one)
+ */
+ public synchronized Object setProperty(String key, XmpArray value) {
+ return super.setProperty(key, value.toString());
+ }
+ /**
+ * @param content
+ * @return an escaped string
+ */
+ public static String escape(String content) {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < content.length(); i++) {
+ switch(content.charAt(i)) {
+ case '<':
+ buf.append("<");
+ break;
+ case '>':
+ buf.append(">");
+ break;
+ case '\'':
+ buf.append("'");
+ break;
+ case '\"':
+ buf.append(""");
+ break;
+ case '&':
+ buf.append("&");
+ break;
+ default:
+ buf.append(content.charAt(i));
+ }
+ }
+ return buf.toString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/XmpWriter.java pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/XmpWriter.java
--- pdftk-1.45/java/pdftk/com/lowagie/text/xml/xmp/XmpWriter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/com/lowagie/text/xml/xmp/XmpWriter.java 2013-06-06 07:32:02.000000000 +0000
@@ -0,0 +1,266 @@
+/*
+ * $Id: XmpWriter.java,v 1.7 2005/09/08 07:50:15 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 2005 by Bruno Lowagie.
+ *
+ *
+ * The Original Code is 'iText, a free JAVA-PDF library'.
+ *
+ * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
+ * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
+ * All Rights Reserved.
+ * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
+ * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
+ *
+ * Contributor(s): all the names of the contributors are added in the source code
+ * where applicable.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ *
+ * If you didn't download this code from the following link, you should check if
+ * you aren't using an obsolete version:
+ * http://www.lowagie.com/iText/
+ */
+
+package pdftk.com.lowagie.text.xml.xmp;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import pdftk.com.lowagie.text.pdf.PdfDate;
+import pdftk.com.lowagie.text.pdf.PdfDictionary;
+import pdftk.com.lowagie.text.pdf.PdfName;
+import pdftk.com.lowagie.text.pdf.PdfObject;
+import pdftk.com.lowagie.text.pdf.PdfString;
+
+/**
+ * With this class you can create an Xmp Stream that can be used for adding
+ * Metadata to a PDF Dictionary. Remark that this class doesn't cover the
+ * complete XMP specification.
+ */
+public class XmpWriter {
+
+ /** A possible charset for the XMP. */
+ public static final String UTF8 = "UTF-8";
+ /** A possible charset for the XMP. */
+ public static final String UTF16 = "UTF-16";
+ /** A possible charset for the XMP. */
+ public static final String UTF16BE = "UTF-16BE";
+ /** A possible charset for the XMP. */
+ public static final String UTF16LE = "UTF-16LE";
+
+ /** String used to fill the extra space. */
+ public static final String EXTRASPACE = " \n";
+
+ /** You can add some extra space in the XMP packet; 1 unit in this variable represents 100 spaces and a newline. */
+ protected int extraSpace;
+
+ /** The writer to which you can write bytes for the XMP stream. */
+ protected OutputStreamWriter writer;
+
+ /** The about string that goes into the rdf:Description tags. */
+ protected String about;
+
+ /** The end attribute. */
+ protected char end = 'w';
+
+ /**
+ * Creates an XmpWriter.
+ * @param os
+ * @param utfEncoding
+ * @param extraSpace
+ * @throws IOException
+ */
+ public XmpWriter(OutputStream os, String utfEncoding, int extraSpace) throws IOException {
+ this.extraSpace = extraSpace;
+ writer = new OutputStreamWriter(os, utfEncoding);
+ writer.write("\n");
+ writer.write("\n");
+ writer.write("\n");
+ about = "";
+ }
+
+ /**
+ * Creates an XmpWriter.
+ * @param os
+ * @throws IOException
+ */
+ public XmpWriter(OutputStream os) throws IOException {
+ this(os, UTF8, 20);
+ }
+
+ /** Sets the XMP to read-only */
+ public void setReadOnly() {
+ end = 'r';
+ }
+
+ /**
+ * @param about The about to set.
+ */
+ public void setAbout(String about) {
+ this.about = about;
+ }
+
+ /**
+ * Adds an rdf:Description.
+ * @param xmlns
+ * @param content
+ * @throws IOException
+ */
+ public void addRdfDescription(String xmlns, String content) throws IOException {
+ writer.write("");
+ writer.write(content);
+ writer.write(" \n");
+ }
+
+ /**
+ * Adds an rdf:Description.
+ * @param s
+ * @throws IOException
+ */
+ public void addRdfDescription(XmpSchema s) throws IOException {
+ writer.write("");
+ writer.write(s.toString());
+ writer.write(" \n");
+ }
+
+ /**
+ * Flushes and closes the XmpWriter.
+ * @throws IOException
+ */
+ public void close() throws IOException {
+ writer.write(" ");
+ writer.write(" \n");
+ for (int i = 0; i < extraSpace; i++) {
+ writer.write(EXTRASPACE);
+ }
+ writer.write("");
+ writer.flush();
+ writer.close();
+ }
+
+ /**
+ * @param os
+ * @param info
+ * @throws IOException
+ */
+ public XmpWriter(OutputStream os, PdfDictionary info) throws IOException {
+ this(os);
+ if (info != null) {
+ DublinCoreSchema dc = new DublinCoreSchema();
+ PdfSchema p = new PdfSchema();
+ XmpBasicSchema basic = new XmpBasicSchema();
+ PdfName key;
+ PdfObject obj;
+ for (Iterator it = info.getKeys().iterator(); it.hasNext();) {
+ key = (PdfName)it.next();
+ obj = info.get(key);
+ if (obj == null)
+ continue;
+ if (PdfName.TITLE.equals(key)) {
+ dc.addTitle(((PdfString)obj).toUnicodeString());
+ }
+ if (PdfName.AUTHOR.equals(key)) {
+ dc.addAuthor(((PdfString)obj).toUnicodeString());
+ }
+ if (PdfName.SUBJECT.equals(key)) {
+ dc.addSubject(((PdfString)obj).toUnicodeString());
+ }
+ if (PdfName.KEYWORDS.equals(key)) {
+ p.addKeywords(((PdfString)obj).toUnicodeString());
+ }
+ if (PdfName.CREATOR.equals(key)) {
+ basic.addCreatorTool(((PdfString)obj).toUnicodeString());
+ }
+ if (PdfName.PRODUCER.equals(key)) {
+ p.addProducer(((PdfString)obj).toUnicodeString());
+ }
+ if (PdfName.CREATIONDATE.equals(key)) {
+ basic.addCreateDate(((PdfDate)obj).getW3CDate());
+ }
+ if (PdfName.MODDATE.equals(key)) {
+ basic.addModDate(((PdfDate)obj).getW3CDate());
+ }
+ }
+ if (dc.size() > 0) addRdfDescription(dc);
+ if (p.size() > 0) addRdfDescription(p);
+ if (basic.size() > 0) addRdfDescription(basic);
+ }
+ }
+
+ /**
+ * @param os
+ * @param info
+ * @throws IOException
+ */
+ public XmpWriter(OutputStream os, HashMap info) throws IOException {
+ this(os);
+ if (info != null) {
+ DublinCoreSchema dc = new DublinCoreSchema();
+ PdfSchema p = new PdfSchema();
+ XmpBasicSchema basic = new XmpBasicSchema();
+ String key;
+ String value;
+ for (Iterator it = info.keySet().iterator(); it.hasNext();) {
+ key = (String)it.next();
+ value = (String)info.get(key);
+ if (value == null)
+ continue;
+ if ("Title".equals(key)) {
+ dc.addTitle(value);
+ }
+ if ("Author".equals(key)) {
+ dc.addAuthor(value);
+ }
+ if ("Subject".equals(key)) {
+ dc.addSubject(value);
+ }
+ if ("Keywords".equals(key)) {
+ p.addKeywords(value);
+ }
+ if ("Creator".equals(key)) {
+ basic.addCreatorTool(value);
+ }
+ if ("Producer".equals(key)) {
+ p.addProducer(value);
+ }
+ if ("CreationDate".equals(key)) {
+ basic.addCreateDate(PdfDate.getW3CDate(value));
+ }
+ if ("ModDate".equals(key)) {
+ basic.addModDate(PdfDate.getW3CDate(value));
+ }
+ }
+ if (dc.size() > 0) addRdfDescription(dc);
+ if (p.size() > 0) addRdfDescription(p);
+ if (basic.size() > 0) addRdfDescription(basic);
+ }
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1ApplicationSpecificParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,10 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public interface ASN1ApplicationSpecificParser
+ extends ASN1Encodable, InMemoryRepresentable
+{
+ ASN1Encodable readObject()
+ throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Boolean.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Boolean.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Boolean.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Boolean.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,15 @@
+package pdftk.org.bouncycastle.asn1;
+
+public class ASN1Boolean
+ extends DERBoolean
+{
+ public ASN1Boolean(boolean value)
+ {
+ super(value);
+ }
+
+ ASN1Boolean(byte[] value)
+ {
+ super(value);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Choice.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Choice.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Choice.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Choice.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,14 @@
+package pdftk.org.bouncycastle.asn1;
+
+/**
+ * Marker interface for CHOICE objects - if you implement this in a role your
+ * own object any attempt to tag the object implicitly will convert the tag to
+ * an explicit one as the encoding rules require.
+ *
+ * If you use this interface your class should also implement the getInstance
+ * pattern which takes a tag object and the tagging mode used.
+ */
+public interface ASN1Choice
+{
+ // marker interface
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Encodable.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Encodable.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Encodable.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Encodable.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,6 @@
+package pdftk.org.bouncycastle.asn1;
+
+public interface ASN1Encodable
+{
+ ASN1Primitive toASN1Primitive();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1EncodableVector.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1EncodableVector.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1EncodableVector.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1EncodableVector.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,36 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class ASN1EncodableVector
+{
+ Vector v = new Vector();
+
+ public ASN1EncodableVector()
+ {
+ }
+
+ public void add(ASN1Encodable obj)
+ {
+ v.addElement(obj);
+ }
+
+ public void addAll(ASN1EncodableVector other)
+ {
+ for (Enumeration en = other.v.elements(); en.hasMoreElements();)
+ {
+ v.addElement(en.nextElement());
+ }
+ }
+
+ public ASN1Encodable get(int i)
+ {
+ return (ASN1Encodable)v.elementAt(i);
+ }
+
+ public int size()
+ {
+ return v.size();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Encoding.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Encoding.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Encoding.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Encoding.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,8 @@
+package pdftk.org.bouncycastle.asn1;
+
+public interface ASN1Encoding
+{
+ static final String DER = "DER";
+ static final String DL = "DL";
+ static final String BER = "BER";
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Enumerated.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Enumerated.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Enumerated.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Enumerated.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,22 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.math.BigInteger;
+
+public class ASN1Enumerated
+ extends DEREnumerated
+{
+ ASN1Enumerated(byte[] bytes)
+ {
+ super(bytes);
+ }
+
+ public ASN1Enumerated(BigInteger value)
+ {
+ super(value);
+ }
+
+ public ASN1Enumerated(int value)
+ {
+ super(value);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Exception.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Exception.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Exception.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Exception.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,25 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class ASN1Exception
+ extends IOException
+{
+ private Throwable cause;
+
+ ASN1Exception(String message)
+ {
+ super(message);
+ }
+
+ ASN1Exception(String message, Throwable cause)
+ {
+ super(message);
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1GeneralizedTime.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1GeneralizedTime.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1GeneralizedTime.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1GeneralizedTime.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,22 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.util.Date;
+
+public class ASN1GeneralizedTime
+ extends DERGeneralizedTime
+{
+ ASN1GeneralizedTime(byte[] bytes)
+ {
+ super(bytes);
+ }
+
+ public ASN1GeneralizedTime(Date time)
+ {
+ super(time);
+ }
+
+ public ASN1GeneralizedTime(String time)
+ {
+ super(time);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Generator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Generator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Generator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Generator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,15 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.OutputStream;
+
+public abstract class ASN1Generator
+{
+ protected OutputStream _out;
+
+ public ASN1Generator(OutputStream out)
+ {
+ _out = out;
+ }
+
+ public abstract OutputStream getRawOutputStream();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1InputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1InputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1InputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1InputStream.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,466 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.EOFException;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import pdftk.org.bouncycastle.util.io.Streams;
+
+/**
+ * a general purpose ASN.1 decoder - note: this class differs from the
+ * others in that it returns null after it has read the last object in
+ * the stream. If an ASN.1 NULL is encountered a DER/BER Null object is
+ * returned.
+ */
+public class ASN1InputStream
+ extends FilterInputStream
+ implements BERTags
+{
+ private final int limit;
+ private final boolean lazyEvaluate;
+
+ private final byte[][] tmpBuffers;
+
+ public ASN1InputStream(
+ InputStream is)
+ {
+ this(is, StreamUtil.findLimit(is));
+ }
+
+ /**
+ * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+ * the stream is automatically limited to the length of the input array.
+ *
+ * @param input array containing ASN.1 encoded data.
+ */
+ public ASN1InputStream(
+ byte[] input)
+ {
+ this(new ByteArrayInputStream(input), input.length);
+ }
+
+ /**
+ * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+ * the stream is automatically limited to the length of the input array.
+ *
+ * @param input array containing ASN.1 encoded data.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ byte[] input,
+ boolean lazyEvaluate)
+ {
+ this(new ByteArrayInputStream(input), input.length, lazyEvaluate);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param limit maximum size of a DER encoded object.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ int limit)
+ {
+ this(input, limit, false);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
+ * objects such as sequences will be parsed lazily.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ boolean lazyEvaluate)
+ {
+ this(input, StreamUtil.findLimit(input), lazyEvaluate);
+ }
+
+ /**
+ * Create an ASN1InputStream where no DER object will be longer than limit, and constructed
+ * objects such as sequences will be parsed lazily.
+ *
+ * @param input stream containing ASN.1 encoded data.
+ * @param limit maximum size of a DER encoded object.
+ * @param lazyEvaluate true if parsing inside constructed objects can be delayed.
+ */
+ public ASN1InputStream(
+ InputStream input,
+ int limit,
+ boolean lazyEvaluate)
+ {
+ super(input);
+ this.limit = limit;
+ this.lazyEvaluate = lazyEvaluate;
+ this.tmpBuffers = new byte[11][];
+ }
+
+ int getLimit()
+ {
+ return limit;
+ }
+
+ protected int readLength()
+ throws IOException
+ {
+ return readLength(this, limit);
+ }
+
+ protected void readFully(
+ byte[] bytes)
+ throws IOException
+ {
+ if (Streams.readFully(this, bytes) != bytes.length)
+ {
+ throw new EOFException("EOF encountered in middle of object");
+ }
+ }
+
+ /**
+ * build an object given its tag and the number of bytes to construct it from.
+ */
+ protected ASN1Primitive buildObject(
+ int tag,
+ int tagNo,
+ int length)
+ throws IOException
+ {
+ boolean isConstructed = (tag & CONSTRUCTED) != 0;
+
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this, length);
+
+ if ((tag & APPLICATION) != 0)
+ {
+ return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
+ }
+
+ if ((tag & TAGGED) != 0)
+ {
+ return new ASN1StreamParser(defIn).readTaggedObject(isConstructed, tagNo);
+ }
+
+ if (isConstructed)
+ {
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case OCTET_STRING:
+ //
+ // yes, people actually do this...
+ //
+ ASN1EncodableVector v = buildDEREncodableVector(defIn);
+ ASN1OctetString[] strings = new ASN1OctetString[v.size()];
+
+ for (int i = 0; i != strings.length; i++)
+ {
+ strings[i] = (ASN1OctetString)v.get(i);
+ }
+
+ return new BEROctetString(strings);
+ case SEQUENCE:
+ if (lazyEvaluate)
+ {
+ return new LazyEncodedSequence(defIn.toByteArray());
+ }
+ else
+ {
+ return DERFactory.createSequence(buildDEREncodableVector(defIn));
+ }
+ case SET:
+ return DERFactory.createSet(buildDEREncodableVector(defIn));
+ case EXTERNAL:
+ return new DERExternal(buildDEREncodableVector(defIn));
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
+ }
+ }
+
+ return createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
+ }
+
+ ASN1EncodableVector buildEncodableVector()
+ throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ ASN1Primitive o;
+
+ while ((o = readObject()) != null)
+ {
+ v.add(o);
+ }
+
+ return v;
+ }
+
+ ASN1EncodableVector buildDEREncodableVector(
+ DefiniteLengthInputStream dIn) throws IOException
+ {
+ return new ASN1InputStream(dIn).buildEncodableVector();
+ }
+
+ public ASN1Primitive readObject()
+ throws IOException
+ {
+ int tag = read();
+ if (tag <= 0)
+ {
+ if (tag == 0)
+ {
+ throw new IOException("unexpected end-of-contents marker");
+ }
+
+ return null;
+ }
+
+ //
+ // calculate tag number
+ //
+ int tagNo = readTagNumber(this, tag);
+
+ boolean isConstructed = (tag & CONSTRUCTED) != 0;
+
+ //
+ // calculate length
+ //
+ int length = readLength();
+
+ if (length < 0) // indefinite length method
+ {
+ if (!isConstructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this, limit);
+ ASN1StreamParser sp = new ASN1StreamParser(indIn, limit);
+
+ if ((tag & APPLICATION) != 0)
+ {
+ return new BERApplicationSpecificParser(tagNo, sp).getLoadedObject();
+ }
+
+ if ((tag & TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(true, tagNo, sp).getLoadedObject();
+ }
+
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case OCTET_STRING:
+ return new BEROctetStringParser(sp).getLoadedObject();
+ case SEQUENCE:
+ return new BERSequenceParser(sp).getLoadedObject();
+ case SET:
+ return new BERSetParser(sp).getLoadedObject();
+ case EXTERNAL:
+ return new DERExternalParser(sp).getLoadedObject();
+ default:
+ throw new IOException("unknown BER object encountered");
+ }
+ }
+ else
+ {
+ try
+ {
+ return buildObject(tag, tagNo, length);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ASN1Exception("corrupted stream detected", e);
+ }
+ }
+ }
+
+ static int readTagNumber(InputStream s, int tag)
+ throws IOException
+ {
+ int tagNo = tag & 0x1f;
+
+ //
+ // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+ //
+ if (tagNo == 0x1f)
+ {
+ tagNo = 0;
+
+ int b = s.read();
+
+ // X.690-0207 8.1.2.4.2
+ // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+ if ((b & 0x7f) == 0) // Note: -1 will pass
+ {
+ throw new IOException("corrupted stream - invalid high tag number found");
+ }
+
+ while ((b >= 0) && ((b & 0x80) != 0))
+ {
+ tagNo |= (b & 0x7f);
+ tagNo <<= 7;
+ b = s.read();
+ }
+
+ if (b < 0)
+ {
+ throw new EOFException("EOF found inside tag value.");
+ }
+
+ tagNo |= (b & 0x7f);
+ }
+
+ return tagNo;
+ }
+
+ static int readLength(InputStream s, int limit)
+ throws IOException
+ {
+ int length = s.read();
+ if (length < 0)
+ {
+ throw new EOFException("EOF found when length expected");
+ }
+
+ if (length == 0x80)
+ {
+ return -1; // indefinite-length encoding
+ }
+
+ if (length > 127)
+ {
+ int size = length & 0x7f;
+
+ // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+ if (size > 4)
+ {
+ throw new IOException("DER length more than 4 bytes: " + size);
+ }
+
+ length = 0;
+ for (int i = 0; i < size; i++)
+ {
+ int next = s.read();
+
+ if (next < 0)
+ {
+ throw new EOFException("EOF found reading length");
+ }
+
+ length = (length << 8) + next;
+ }
+
+ if (length < 0)
+ {
+ throw new IOException("corrupted stream - negative length found");
+ }
+
+ if (length >= limit) // after all we must have read at least 1 byte
+ {
+ throw new IOException("corrupted stream - out of bounds length found");
+ }
+ }
+
+ return length;
+ }
+
+ private static byte[] getBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
+ throws IOException
+ {
+ int len = defIn.getRemaining();
+ if (defIn.getRemaining() < tmpBuffers.length)
+ {
+ byte[] buf = tmpBuffers[len];
+
+ if (buf == null)
+ {
+ buf = tmpBuffers[len] = new byte[len];
+ }
+
+ Streams.readFully(defIn, buf);
+
+ return buf;
+ }
+ else
+ {
+ return defIn.toByteArray();
+ }
+ }
+
+ private static char[] getBMPCharBuffer(DefiniteLengthInputStream defIn)
+ throws IOException
+ {
+ int len = defIn.getRemaining() / 2;
+ char[] buf = new char[len];
+ int totalRead = 0;
+ while (totalRead < len)
+ {
+ int ch1 = defIn.read();
+ if (ch1 < 0)
+ {
+ break;
+ }
+ int ch2 = defIn.read();
+ if (ch2 < 0)
+ {
+ break;
+ }
+ buf[totalRead++] = (char)((ch1 << 8) | (ch2 & 0xff));
+ }
+
+ return buf;
+ }
+
+ static ASN1Primitive createPrimitiveDERObject(
+ int tagNo,
+ DefiniteLengthInputStream defIn,
+ byte[][] tmpBuffers)
+ throws IOException
+ {
+ switch (tagNo)
+ {
+ case BIT_STRING:
+ return DERBitString.fromInputStream(defIn.getRemaining(), defIn);
+ case BMP_STRING:
+ return new DERBMPString(getBMPCharBuffer(defIn));
+ case BOOLEAN:
+ return ASN1Boolean.fromOctetString(getBuffer(defIn, tmpBuffers));
+ case ENUMERATED:
+ return ASN1Enumerated.fromOctetString(getBuffer(defIn, tmpBuffers));
+ case GENERALIZED_TIME:
+ return new ASN1GeneralizedTime(defIn.toByteArray());
+ case GENERAL_STRING:
+ return new DERGeneralString(defIn.toByteArray());
+ case IA5_STRING:
+ return new DERIA5String(defIn.toByteArray());
+ case INTEGER:
+ return new ASN1Integer(defIn.toByteArray());
+ case NULL:
+ return DERNull.INSTANCE; // actual content is ignored (enforce 0 length?)
+ case NUMERIC_STRING:
+ return new DERNumericString(defIn.toByteArray());
+ case OBJECT_IDENTIFIER:
+ return ASN1ObjectIdentifier.fromOctetString(getBuffer(defIn, tmpBuffers));
+ case OCTET_STRING:
+ return new DEROctetString(defIn.toByteArray());
+ case PRINTABLE_STRING:
+ return new DERPrintableString(defIn.toByteArray());
+ case T61_STRING:
+ return new DERT61String(defIn.toByteArray());
+ case UNIVERSAL_STRING:
+ return new DERUniversalString(defIn.toByteArray());
+ case UTC_TIME:
+ return new ASN1UTCTime(defIn.toByteArray());
+ case UTF8_STRING:
+ return new DERUTF8String(defIn.toByteArray());
+ case VISIBLE_STRING:
+ return new DERVisibleString(defIn.toByteArray());
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Integer.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Integer.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Integer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Integer.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,22 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.math.BigInteger;
+
+public class ASN1Integer
+ extends DERInteger
+{
+ ASN1Integer(byte[] bytes)
+ {
+ super(bytes);
+ }
+
+ public ASN1Integer(BigInteger value)
+ {
+ super(value);
+ }
+
+ public ASN1Integer(long value)
+ {
+ super(value);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Null.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Null.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Null.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Null.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,67 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * A NULL object.
+ */
+public abstract class ASN1Null
+ extends ASN1Primitive
+{
+ /**
+ * @deprecated use DERNull.INSTANCE
+ */
+ public ASN1Null()
+ {
+ }
+
+ public static ASN1Null getInstance(Object o)
+ {
+ if (o instanceof ASN1Null)
+ {
+ return (ASN1Null)o;
+ }
+
+ if (o != null)
+ {
+ try
+ {
+ return ASN1Null.getInstance(ASN1Primitive.fromByteArray((byte[])o));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct NULL from byte[]: " + e.getMessage());
+ }
+ catch (ClassCastException e)
+ {
+ throw new IllegalArgumentException("unknown object in getInstance(): " + o.getClass().getName());
+ }
+ }
+
+ return null;
+ }
+
+ public int hashCode()
+ {
+ return -1;
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1Null))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ abstract void encode(ASN1OutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return "NULL";
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Object.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Object.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Object.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Object.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,97 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+public abstract class ASN1Object
+ implements ASN1Encodable
+{
+ /**
+ * Return the default BER or DER encoding for this object.
+ *
+ * @return BER/DER byte encoded object.
+ * @throws java.io.IOException on encoding error.
+ */
+ public byte[] getEncoded()
+ throws IOException
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ aOut.writeObject(this);
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Return either the default for "BER" or a DER encoding if "DER" is specified.
+ *
+ * @param encoding name of encoding to use.
+ * @return byte encoded object.
+ * @throws IOException on encoding error.
+ */
+ public byte[] getEncoded(
+ String encoding)
+ throws IOException
+ {
+ if (encoding.equals(ASN1Encoding.DER))
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DEROutputStream dOut = new DEROutputStream(bOut);
+
+ dOut.writeObject(this);
+
+ return bOut.toByteArray();
+ }
+ else if (encoding.equals(ASN1Encoding.DL))
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ DLOutputStream dOut = new DLOutputStream(bOut);
+
+ dOut.writeObject(this);
+
+ return bOut.toByteArray();
+ }
+
+ return this.getEncoded();
+ }
+
+ public int hashCode()
+ {
+ return this.toASN1Primitive().hashCode();
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ if (!(o instanceof ASN1Encodable))
+ {
+ return false;
+ }
+
+ ASN1Encodable other = (ASN1Encodable)o;
+
+ return this.toASN1Primitive().equals(other.toASN1Primitive());
+ }
+
+ /**
+ * @deprecated use toASN1Primitive()
+ * @return the underlying primitive type.
+ */
+ public ASN1Primitive toASN1Object()
+ {
+ return this.toASN1Primitive();
+ }
+
+ protected static boolean hasEncodedTagValue(Object obj, int tagValue)
+ {
+ return (obj instanceof byte[]) && ((byte[])obj)[0] == tagValue;
+ }
+
+ public abstract ASN1Primitive toASN1Primitive();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1ObjectIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1ObjectIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1ObjectIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1ObjectIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,37 @@
+package pdftk.org.bouncycastle.asn1;
+
+public class ASN1ObjectIdentifier
+ extends DERObjectIdentifier
+{
+ public ASN1ObjectIdentifier(String identifier)
+ {
+ super(identifier);
+ }
+
+ ASN1ObjectIdentifier(byte[] bytes)
+ {
+ super(bytes);
+ }
+
+ /**
+ * Return an OID that creates a branch under the current one.
+ *
+ * @param branchID node numbers for the new branch.
+ * @return the OID for the new created branch.
+ */
+ public ASN1ObjectIdentifier branch(String branchID)
+ {
+ return new ASN1ObjectIdentifier(getId() + "." + branchID);
+ }
+
+ /**
+ * Return true if this oid is an extension of the passed in branch, stem.
+ * @param stem the arc or branch that is a possible parent.
+ * @return true if the branch is on the passed in stem, false otherwise.
+ */
+ public boolean on(ASN1ObjectIdentifier stem)
+ {
+ String id = getId(), stemId = stem.getId();
+ return id.length() > stemId.length() && id.charAt(stemId.length()) == '.' && id.startsWith(stemId);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1OctetString.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1OctetString.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1OctetString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1OctetString.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,146 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.encoders.Hex;
+
+public abstract class ASN1OctetString
+ extends ASN1Primitive
+ implements ASN1OctetStringParser
+{
+ byte[] string;
+
+ /**
+ * return an Octet String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1OctetString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof ASN1OctetString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return BEROctetString.fromSequence(ASN1Sequence.getInstance(o));
+ }
+ }
+
+ /**
+ * return an Octet String from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1OctetString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1OctetString)
+ {
+ return (ASN1OctetString)obj;
+ }
+ else if (obj instanceof byte[])
+ {
+ try
+ {
+ return ASN1OctetString.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct OCTET STRING from byte[]: " + e.getMessage());
+ }
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (primitive instanceof ASN1OctetString)
+ {
+ return (ASN1OctetString)primitive;
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * @param string the octets making up the octet string.
+ */
+ public ASN1OctetString(
+ byte[] string)
+ {
+ if (string == null)
+ {
+ throw new NullPointerException("string cannot be null");
+ }
+ this.string = string;
+ }
+
+ public InputStream getOctetStream()
+ {
+ return new ByteArrayInputStream(string);
+ }
+
+ public ASN1OctetStringParser parser()
+ {
+ return this;
+ }
+
+ public byte[] getOctets()
+ {
+ return string;
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(this.getOctets());
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1OctetString))
+ {
+ return false;
+ }
+
+ ASN1OctetString other = (ASN1OctetString)o;
+
+ return Arrays.areEqual(string, other.string);
+ }
+
+ public ASN1Primitive getLoadedObject()
+ {
+ return this.toASN1Primitive();
+ }
+
+ ASN1Primitive toDERObject()
+ {
+ return new DEROctetString(string);
+ }
+
+ ASN1Primitive toDLObject()
+ {
+ return new DEROctetString(string);
+ }
+
+ abstract void encode(ASN1OutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return "#"+new String(Hex.encode(string));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1OctetStringParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1OctetStringParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1OctetStringParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1OctetStringParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,9 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.InputStream;
+
+public interface ASN1OctetStringParser
+ extends ASN1Encodable, InMemoryRepresentable
+{
+ public InputStream getOctetStream();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1OutputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1OutputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1OutputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1OutputStream.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,194 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Stream that produces output based on the default encoding for the passed in objects.
+ */
+public class ASN1OutputStream
+{
+ private OutputStream os;
+
+ public ASN1OutputStream(
+ OutputStream os)
+ {
+ this.os = os;
+ }
+
+ void writeLength(
+ int length)
+ throws IOException
+ {
+ if (length > 127)
+ {
+ int size = 1;
+ int val = length;
+
+ while ((val >>>= 8) != 0)
+ {
+ size++;
+ }
+
+ write((byte)(size | 0x80));
+
+ for (int i = (size - 1) * 8; i >= 0; i -= 8)
+ {
+ write((byte)(length >> i));
+ }
+ }
+ else
+ {
+ write((byte)length);
+ }
+ }
+
+ void write(int b)
+ throws IOException
+ {
+ os.write(b);
+ }
+
+ void write(byte[] bytes)
+ throws IOException
+ {
+ os.write(bytes);
+ }
+
+ void write(byte[] bytes, int off, int len)
+ throws IOException
+ {
+ os.write(bytes, off, len);
+ }
+
+ void writeEncoded(
+ int tag,
+ byte[] bytes)
+ throws IOException
+ {
+ write(tag);
+ writeLength(bytes.length);
+ write(bytes);
+ }
+
+ void writeTag(int flags, int tagNo)
+ throws IOException
+ {
+ if (tagNo < 31)
+ {
+ write(flags | tagNo);
+ }
+ else
+ {
+ write(flags | 0x1f);
+ if (tagNo < 128)
+ {
+ write(tagNo);
+ }
+ else
+ {
+ byte[] stack = new byte[5];
+ int pos = stack.length;
+
+ stack[--pos] = (byte)(tagNo & 0x7F);
+
+ do
+ {
+ tagNo >>= 7;
+ stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
+ }
+ while (tagNo > 127);
+
+ write(stack, pos, stack.length - pos);
+ }
+ }
+ }
+
+ void writeEncoded(int flags, int tagNo, byte[] bytes)
+ throws IOException
+ {
+ writeTag(flags, tagNo);
+ writeLength(bytes.length);
+ write(bytes);
+ }
+
+ protected void writeNull()
+ throws IOException
+ {
+ os.write(BERTags.NULL);
+ os.write(0x00);
+ }
+
+ public void writeObject(
+ ASN1Encodable obj)
+ throws IOException
+ {
+ if (obj != null)
+ {
+ obj.toASN1Primitive().encode(this);
+ }
+ else
+ {
+ throw new IOException("null object detected");
+ }
+ }
+
+ void writeImplicitObject(ASN1Primitive obj)
+ throws IOException
+ {
+ if (obj != null)
+ {
+ obj.encode(new ImplicitOutputStream(os));
+ }
+ else
+ {
+ throw new IOException("null object detected");
+ }
+ }
+
+ public void close()
+ throws IOException
+ {
+ os.close();
+ }
+
+ public void flush()
+ throws IOException
+ {
+ os.flush();
+ }
+
+ ASN1OutputStream getDERSubStream()
+ {
+ return new DEROutputStream(os);
+ }
+
+ ASN1OutputStream getDLSubStream()
+ {
+ return new DLOutputStream(os);
+ }
+
+ private class ImplicitOutputStream
+ extends ASN1OutputStream
+ {
+ private boolean first = true;
+
+ public ImplicitOutputStream(OutputStream os)
+ {
+ super(os);
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ super.write(b);
+ }
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1ParsingException.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1ParsingException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1ParsingException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1ParsingException.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.asn1;
+
+public class ASN1ParsingException
+ extends IllegalStateException
+{
+ private Throwable cause;
+
+ public ASN1ParsingException(String message)
+ {
+ super(message);
+ }
+
+ public ASN1ParsingException(String message, Throwable cause)
+ {
+ super(message);
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Primitive.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Primitive.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Primitive.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Primitive.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,69 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public abstract class ASN1Primitive
+ extends ASN1Object
+{
+ ASN1Primitive()
+ {
+
+ }
+
+ /**
+ * Create a base ASN.1 object from a byte stream.
+ *
+ * @param data the byte stream to parse.
+ * @return the base ASN.1 object represented by the byte stream.
+ * @exception IOException if there is a problem parsing the data.
+ */
+ public static ASN1Primitive fromByteArray(byte[] data)
+ throws IOException
+ {
+ ASN1InputStream aIn = new ASN1InputStream(data);
+
+ try
+ {
+ return aIn.readObject();
+ }
+ catch (ClassCastException e)
+ {
+ throw new IOException("cannot recognise object in stream");
+ }
+ }
+
+ public final boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+
+ return (o instanceof ASN1Encodable) && asn1Equals(((ASN1Encodable)o).toASN1Primitive());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return this;
+ }
+
+ ASN1Primitive toDERObject()
+ {
+ return this;
+ }
+
+ ASN1Primitive toDLObject()
+ {
+ return this;
+ }
+
+ public abstract int hashCode();
+
+ abstract boolean isConstructed();
+
+ abstract int encodedLength() throws IOException;
+
+ abstract void encode(ASN1OutputStream out) throws IOException;
+
+ abstract boolean asn1Equals(ASN1Primitive o);
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Sequence.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Sequence.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Sequence.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Sequence.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,323 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public abstract class ASN1Sequence
+ extends ASN1Primitive
+{
+ protected Vector seq = new Vector();
+
+ /**
+ * return an ASN1Sequence from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1Sequence getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Sequence)
+ {
+ return (ASN1Sequence)obj;
+ }
+ else if (obj instanceof ASN1SequenceParser)
+ {
+ return ASN1Sequence.getInstance(((ASN1SequenceParser)obj).toASN1Primitive());
+ }
+ else if (obj instanceof byte[])
+ {
+ try
+ {
+ return ASN1Sequence.getInstance(fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct sequence from byte[]: " + e.getMessage());
+ }
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (primitive instanceof ASN1Sequence)
+ {
+ return (ASN1Sequence)primitive;
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Return an ASN1 sequence from a tagged object. There is a special
+ * case here, if an object appears to have been explicitly tagged on
+ * reading but we were expecting it to be implicitly tagged in the
+ * normal course of events it indicates that we lost the surrounding
+ * sequence - so we need to add it back (this will happen if the tagged
+ * object is a sequence that contains other sequences). If you are
+ * dealing with implicitly tagged sequences you really should
+ * be using this method.
+ *
+ * @param obj the tagged object.
+ * @param explicit true if the object is meant to be explicitly tagged,
+ * false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1Sequence getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ if (explicit)
+ {
+ if (!obj.isExplicit())
+ {
+ throw new IllegalArgumentException("object implicit - explicit expected.");
+ }
+
+ return ASN1Sequence.getInstance(obj.getObject().toASN1Primitive());
+ }
+ else
+ {
+ //
+ // constructed object which appears to be explicitly tagged
+ // when it should be implicit means we have to add the
+ // surrounding sequence.
+ //
+ if (obj.isExplicit())
+ {
+ if (obj instanceof BERTaggedObject)
+ {
+ return new BERSequence(obj.getObject());
+ }
+ else
+ {
+ return new DLSequence(obj.getObject());
+ }
+ }
+ else
+ {
+ if (obj.getObject() instanceof ASN1Sequence)
+ {
+ return (ASN1Sequence)obj.getObject();
+ }
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * create an empty sequence
+ */
+ protected ASN1Sequence()
+ {
+ }
+
+ /**
+ * create a sequence containing one object
+ */
+ protected ASN1Sequence(
+ ASN1Encodable obj)
+ {
+ seq.addElement(obj);
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ protected ASN1Sequence(
+ ASN1EncodableVector v)
+ {
+ for (int i = 0; i != v.size(); i++)
+ {
+ seq.addElement(v.get(i));
+ }
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ protected ASN1Sequence(
+ ASN1Encodable[] array)
+ {
+ for (int i = 0; i != array.length; i++)
+ {
+ seq.addElement(array[i]);
+ }
+ }
+
+ public ASN1Encodable[] toArray()
+ {
+ ASN1Encodable[] values = new ASN1Encodable[this.size()];
+
+ for (int i = 0; i != this.size(); i++)
+ {
+ values[i] = this.getObjectAt(i);
+ }
+
+ return values;
+ }
+
+ public Enumeration getObjects()
+ {
+ return seq.elements();
+ }
+
+ public ASN1SequenceParser parser()
+ {
+ final ASN1Sequence outer = this;
+
+ return new ASN1SequenceParser()
+ {
+ private final int max = size();
+
+ private int index;
+
+ public ASN1Encodable readObject() throws IOException
+ {
+ if (index == max)
+ {
+ return null;
+ }
+
+ ASN1Encodable obj = getObjectAt(index++);
+ if (obj instanceof ASN1Sequence)
+ {
+ return ((ASN1Sequence)obj).parser();
+ }
+ if (obj instanceof ASN1Set)
+ {
+ return ((ASN1Set)obj).parser();
+ }
+
+ return obj;
+ }
+
+ public ASN1Primitive getLoadedObject()
+ {
+ return outer;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return outer;
+ }
+ };
+ }
+
+ /**
+ * return the object at the sequence position indicated by index.
+ *
+ * @param index the sequence number (starting at zero) of the object
+ * @return the object at the sequence position indicated by index.
+ */
+ public ASN1Encodable getObjectAt(
+ int index)
+ {
+ return (ASN1Encodable)seq.elementAt(index);
+ }
+
+ /**
+ * return the number of objects in this sequence.
+ *
+ * @return the number of objects in this sequence.
+ */
+ public int size()
+ {
+ return seq.size();
+ }
+
+ public int hashCode()
+ {
+ Enumeration e = this.getObjects();
+ int hashCode = size();
+
+ while (e.hasMoreElements())
+ {
+ Object o = getNext(e);
+ hashCode *= 17;
+
+ hashCode ^= o.hashCode();
+ }
+
+ return hashCode;
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1Sequence))
+ {
+ return false;
+ }
+
+ ASN1Sequence other = (ASN1Sequence)o;
+
+ if (this.size() != other.size())
+ {
+ return false;
+ }
+
+ Enumeration s1 = this.getObjects();
+ Enumeration s2 = other.getObjects();
+
+ while (s1.hasMoreElements())
+ {
+ ASN1Encodable obj1 = getNext(s1);
+ ASN1Encodable obj2 = getNext(s2);
+
+ ASN1Primitive o1 = obj1.toASN1Primitive();
+ ASN1Primitive o2 = obj2.toASN1Primitive();
+
+ if (o1 == o2 || o1.equals(o2))
+ {
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ private ASN1Encodable getNext(Enumeration e)
+ {
+ ASN1Encodable encObj = (ASN1Encodable)e.nextElement();
+
+ return encObj;
+ }
+
+ ASN1Primitive toDERObject()
+ {
+ ASN1Sequence derSeq = new DERSequence();
+
+ derSeq.seq = this.seq;
+
+ return derSeq;
+ }
+
+ ASN1Primitive toDLObject()
+ {
+ ASN1Sequence dlSeq = new DLSequence();
+
+ dlSeq.seq = this.seq;
+
+ return dlSeq;
+ }
+
+ boolean isConstructed()
+ {
+ return true;
+ }
+
+ abstract void encode(ASN1OutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return seq.toString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1SequenceParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1SequenceParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1SequenceParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1SequenceParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,10 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public interface ASN1SequenceParser
+ extends ASN1Encodable, InMemoryRepresentable
+{
+ ASN1Encodable readObject()
+ throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Set.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Set.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1Set.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1Set.java 2013-04-22 11:41:02.000000000 +0000
@@ -0,0 +1,468 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+abstract public class ASN1Set
+ extends ASN1Primitive
+{
+ private Vector set = new Vector();
+ private boolean isSorted = false;
+
+ /**
+ * return an ASN1Set from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1Set getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Set)
+ {
+ return (ASN1Set)obj;
+ }
+ else if (obj instanceof ASN1SetParser)
+ {
+ return ASN1Set.getInstance(((ASN1SetParser)obj).toASN1Primitive());
+ }
+ else if (obj instanceof byte[])
+ {
+ try
+ {
+ return ASN1Set.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct set from byte[]: " + e.getMessage());
+ }
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (primitive instanceof ASN1Set)
+ {
+ return (ASN1Set)primitive;
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Return an ASN1 set from a tagged object. There is a special
+ * case here, if an object appears to have been explicitly tagged on
+ * reading but we were expecting it to be implicitly tagged in the
+ * normal course of events it indicates that we lost the surrounding
+ * set - so we need to add it back (this will happen if the tagged
+ * object is a sequence that contains other sequences). If you are
+ * dealing with implicitly tagged sets you really should
+ * be using this method.
+ *
+ * @param obj the tagged object.
+ * @param explicit true if the object is meant to be explicitly tagged
+ * false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1Set getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ if (explicit)
+ {
+ if (!obj.isExplicit())
+ {
+ throw new IllegalArgumentException("object implicit - explicit expected.");
+ }
+
+ return (ASN1Set)obj.getObject();
+ }
+ else
+ {
+ //
+ // constructed object which appears to be explicitly tagged
+ // and it's really implicit means we have to add the
+ // surrounding set.
+ //
+ if (obj.isExplicit())
+ {
+ if (obj instanceof BERTaggedObject)
+ {
+ return new BERSet(obj.getObject());
+ }
+ else
+ {
+ return new DLSet(obj.getObject());
+ }
+ }
+ else
+ {
+ if (obj.getObject() instanceof ASN1Set)
+ {
+ return (ASN1Set)obj.getObject();
+ }
+
+ //
+ // in this case the parser returns a sequence, convert it
+ // into a set.
+ //
+ if (obj.getObject() instanceof ASN1Sequence)
+ {
+ ASN1Sequence s = (ASN1Sequence)obj.getObject();
+
+ if (obj instanceof BERTaggedObject)
+ {
+ return new BERSet(s.toArray());
+ }
+ else
+ {
+ return new DLSet(s.toArray());
+ }
+ }
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ protected ASN1Set()
+ {
+ }
+
+ /**
+ * create a sequence containing one object
+ */
+ protected ASN1Set(
+ ASN1Encodable obj)
+ {
+ set.addElement(obj);
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ protected ASN1Set(
+ ASN1EncodableVector v,
+ boolean doSort)
+ {
+ for (int i = 0; i != v.size(); i++)
+ {
+ set.addElement(v.get(i));
+ }
+
+ if (doSort)
+ {
+ this.sort();
+ }
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ protected ASN1Set(
+ ASN1Encodable[] array,
+ boolean doSort)
+ {
+ for (int i = 0; i != array.length; i++)
+ {
+ set.addElement(array[i]);
+ }
+
+ if (doSort)
+ {
+ this.sort();
+ }
+ }
+
+ public Enumeration getObjects()
+ {
+ return set.elements();
+ }
+
+ /**
+ * return the object at the set position indicated by index.
+ *
+ * @param index the set number (starting at zero) of the object
+ * @return the object at the set position indicated by index.
+ */
+ public ASN1Encodable getObjectAt(
+ int index)
+ {
+ return (ASN1Encodable)set.elementAt(index);
+ }
+
+ /**
+ * return the number of objects in this set.
+ *
+ * @return the number of objects in this set.
+ */
+ public int size()
+ {
+ return set.size();
+ }
+
+ public ASN1Encodable[] toArray()
+ {
+ ASN1Encodable[] values = new ASN1Encodable[this.size()];
+
+ for (int i = 0; i != this.size(); i++)
+ {
+ values[i] = this.getObjectAt(i);
+ }
+
+ return values;
+ }
+
+ public ASN1SetParser parser()
+ {
+ final ASN1Set outer = this;
+
+ return new ASN1SetParser()
+ {
+ private final int max = size();
+
+ private int index;
+
+ public ASN1Encodable readObject() throws IOException
+ {
+ if (index == max)
+ {
+ return null;
+ }
+
+ ASN1Encodable obj = getObjectAt(index++);
+ if (obj instanceof ASN1Sequence)
+ {
+ return ((ASN1Sequence)obj).parser();
+ }
+ if (obj instanceof ASN1Set)
+ {
+ return ((ASN1Set)obj).parser();
+ }
+
+ return obj;
+ }
+
+ public ASN1Primitive getLoadedObject()
+ {
+ return outer;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return outer;
+ }
+ };
+ }
+
+ public int hashCode()
+ {
+ Enumeration e = this.getObjects();
+ int hashCode = size();
+
+ while (e.hasMoreElements())
+ {
+ Object o = getNext(e);
+ hashCode *= 17;
+
+ hashCode ^= o.hashCode();
+ }
+
+ return hashCode;
+ }
+
+ ASN1Primitive toDERObject()
+ {
+ if (isSorted)
+ {
+ ASN1Set derSet = new DERSet();
+
+ derSet.set = this.set;
+
+ return derSet;
+ }
+ else
+ {
+ Vector v = new Vector();
+
+ for (int i = 0; i != set.size(); i++)
+ {
+ v.addElement(set.elementAt(i));
+ }
+
+ ASN1Set derSet = new DERSet();
+
+ derSet.set = v;
+
+ derSet.sort();
+
+ return derSet;
+ }
+ }
+
+ ASN1Primitive toDLObject()
+ {
+ ASN1Set derSet = new DLSet();
+
+ derSet.set = this.set;
+
+ return derSet;
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1Set))
+ {
+ return false;
+ }
+
+ ASN1Set other = (ASN1Set)o;
+
+ if (this.size() != other.size())
+ {
+ return false;
+ }
+
+ Enumeration s1 = this.getObjects();
+ Enumeration s2 = other.getObjects();
+
+ while (s1.hasMoreElements())
+ {
+ ASN1Encodable obj1 = getNext(s1);
+ ASN1Encodable obj2 = getNext(s2);
+
+ ASN1Primitive o1 = obj1.toASN1Primitive();
+ ASN1Primitive o2 = obj2.toASN1Primitive();
+
+ if (o1 == o2 || o1.equals(o2))
+ {
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ private ASN1Encodable getNext(Enumeration e)
+ {
+ ASN1Encodable encObj = (ASN1Encodable)e.nextElement();
+
+ // unfortunately null was allowed as a substitute for DER null
+ if (encObj == null)
+ {
+ return DERNull.INSTANCE;
+ }
+
+ return encObj;
+ }
+
+ /**
+ * return true if a <= b (arrays are assumed padded with zeros).
+ */
+ private boolean lessThanOrEqual(
+ byte[] a,
+ byte[] b)
+ {
+ int len = Math.min(a.length, b.length);
+ for (int i = 0; i != len; ++i)
+ {
+ if (a[i] != b[i])
+ {
+ return (a[i] & 0xff) < (b[i] & 0xff);
+ }
+ }
+ return len == a.length;
+ }
+
+ private byte[] getEncoded(
+ ASN1Encodable obj)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ try
+ {
+ aOut.writeObject(obj);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("cannot encode object added to SET");
+ }
+
+ return bOut.toByteArray();
+ }
+
+ protected void sort()
+ {
+ if (!isSorted)
+ {
+ isSorted = true;
+ if (set.size() > 1)
+ {
+ boolean swapped = true;
+ int lastSwap = set.size() - 1;
+
+ while (swapped)
+ {
+ int index = 0;
+ int swapIndex = 0;
+ byte[] a = getEncoded((ASN1Encodable)set.elementAt(0));
+
+ swapped = false;
+
+ while (index != lastSwap)
+ {
+ byte[] b = getEncoded((ASN1Encodable)set.elementAt(index + 1));
+
+ if (lessThanOrEqual(a, b))
+ {
+ a = b;
+ }
+ else
+ {
+ Object o = set.elementAt(index);
+
+ set.setElementAt(set.elementAt(index + 1), index);
+ set.setElementAt(o, index + 1);
+
+ swapped = true;
+ swapIndex = index;
+ }
+
+ index++;
+ }
+
+ lastSwap = swapIndex;
+ }
+ }
+ }
+ }
+
+ boolean isConstructed()
+ {
+ return true;
+ }
+
+ //sid: copied from bc 1.45; we use it while creating a DERSet in PdfPKCS7.java,
+ // and this is consistent with ASN1Set( ASN1Encodable[], boolean )
+ protected void addObject(
+ ASN1Encodable obj)
+ {
+ set.addElement(obj);
+ }
+
+ abstract void encode(ASN1OutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return set.toString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1SetParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1SetParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1SetParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1SetParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,10 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public interface ASN1SetParser
+ extends ASN1Encodable, InMemoryRepresentable
+{
+ public ASN1Encodable readObject()
+ throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1StreamParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1StreamParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1StreamParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1StreamParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,247 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ASN1StreamParser
+{
+ private final InputStream _in;
+ private final int _limit;
+ private final byte[][] tmpBuffers;
+
+ public ASN1StreamParser(
+ InputStream in)
+ {
+ this(in, StreamUtil.findLimit(in));
+ }
+
+ public ASN1StreamParser(
+ InputStream in,
+ int limit)
+ {
+ this._in = in;
+ this._limit = limit;
+
+ this.tmpBuffers = new byte[11][];
+ }
+
+ public ASN1StreamParser(
+ byte[] encoding)
+ {
+ this(new ByteArrayInputStream(encoding), encoding.length);
+ }
+
+ ASN1Encodable readIndef(int tagValue) throws IOException
+ {
+ // Note: INDEF => CONSTRUCTED
+
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagValue)
+ {
+ case BERTags.EXTERNAL:
+ return new DERExternalParser(this);
+ case BERTags.OCTET_STRING:
+ return new BEROctetStringParser(this);
+ case BERTags.SEQUENCE:
+ return new BERSequenceParser(this);
+ case BERTags.SET:
+ return new BERSetParser(this);
+ default:
+ throw new ASN1Exception("unknown BER object encountered: 0x" + Integer.toHexString(tagValue));
+ }
+ }
+
+ ASN1Encodable readImplicit(boolean constructed, int tag) throws IOException
+ {
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ if (!constructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ return readIndef(tag);
+ }
+
+ if (constructed)
+ {
+ switch (tag)
+ {
+ case BERTags.SET:
+ return new DERSetParser(this);
+ case BERTags.SEQUENCE:
+ return new DERSequenceParser(this);
+ case BERTags.OCTET_STRING:
+ return new BEROctetStringParser(this);
+ }
+ }
+ else
+ {
+ switch (tag)
+ {
+ case BERTags.SET:
+ throw new ASN1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
+ case BERTags.SEQUENCE:
+ throw new ASN1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
+ case BERTags.OCTET_STRING:
+ return new DEROctetStringParser((DefiniteLengthInputStream)_in);
+ }
+ }
+
+ // TODO ASN1Exception
+ throw new RuntimeException("implicit tagging not implemented");
+ }
+
+ ASN1Primitive readTaggedObject(boolean constructed, int tag) throws IOException
+ {
+ if (!constructed)
+ {
+ // Note: !CONSTRUCTED => IMPLICIT
+ DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
+ return new DERTaggedObject(false, tag, new DEROctetString(defIn.toByteArray()));
+ }
+
+ ASN1EncodableVector v = readVector();
+
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ return v.size() == 1
+ ? new BERTaggedObject(true, tag, v.get(0))
+ : new BERTaggedObject(false, tag, BERFactory.createSequence(v));
+ }
+
+ return v.size() == 1
+ ? new DERTaggedObject(true, tag, v.get(0))
+ : new DERTaggedObject(false, tag, DERFactory.createSequence(v));
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ int tag = _in.read();
+ if (tag == -1)
+ {
+ return null;
+ }
+
+ //
+ // turn of looking for "00" while we resolve the tag
+ //
+ set00Check(false);
+
+ //
+ // calculate tag number
+ //
+ int tagNo = ASN1InputStream.readTagNumber(_in, tag);
+
+ boolean isConstructed = (tag & BERTags.CONSTRUCTED) != 0;
+
+ //
+ // calculate length
+ //
+ int length = ASN1InputStream.readLength(_in, _limit);
+
+ if (length < 0) // indefinite length method
+ {
+ if (!isConstructed)
+ {
+ throw new IOException("indefinite length primitive encoding encountered");
+ }
+
+ IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
+ ASN1StreamParser sp = new ASN1StreamParser(indIn, _limit);
+
+ if ((tag & BERTags.APPLICATION) != 0)
+ {
+ return new BERApplicationSpecificParser(tagNo, sp);
+ }
+
+ if ((tag & BERTags.TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(true, tagNo, sp);
+ }
+
+ return sp.readIndef(tagNo);
+ }
+ else
+ {
+ DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
+
+ if ((tag & BERTags.APPLICATION) != 0)
+ {
+ return new DERApplicationSpecific(isConstructed, tagNo, defIn.toByteArray());
+ }
+
+ if ((tag & BERTags.TAGGED) != 0)
+ {
+ return new BERTaggedObjectParser(isConstructed, tagNo, new ASN1StreamParser(defIn));
+ }
+
+ if (isConstructed)
+ {
+ // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+ switch (tagNo)
+ {
+ case BERTags.OCTET_STRING:
+ //
+ // yes, people actually do this...
+ //
+ return new BEROctetStringParser(new ASN1StreamParser(defIn));
+ case BERTags.SEQUENCE:
+ return new DERSequenceParser(new ASN1StreamParser(defIn));
+ case BERTags.SET:
+ return new DERSetParser(new ASN1StreamParser(defIn));
+ case BERTags.EXTERNAL:
+ return new DERExternalParser(new ASN1StreamParser(defIn));
+ default:
+ throw new IOException("unknown tag " + tagNo + " encountered");
+ }
+ }
+
+ // Some primitive encodings can be handled by parsers too...
+ switch (tagNo)
+ {
+ case BERTags.OCTET_STRING:
+ return new DEROctetStringParser(defIn);
+ }
+
+ try
+ {
+ return ASN1InputStream.createPrimitiveDERObject(tagNo, defIn, tmpBuffers);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ASN1Exception("corrupted stream detected", e);
+ }
+ }
+ }
+
+ private void set00Check(boolean enabled)
+ {
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ ((IndefiniteLengthInputStream)_in).setEofOn00(enabled);
+ }
+ }
+
+ ASN1EncodableVector readVector() throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ ASN1Encodable obj;
+ while ((obj = readObject()) != null)
+ {
+ if (obj instanceof InMemoryRepresentable)
+ {
+ v.add(((InMemoryRepresentable)obj).getLoadedObject());
+ }
+ else
+ {
+ v.add(obj.toASN1Primitive());
+ }
+ }
+
+ return v;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1String.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1String.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1String.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1String.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,6 @@
+package pdftk.org.bouncycastle.asn1;
+
+public interface ASN1String
+{
+ public String getString();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1TaggedObject.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1TaggedObject.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1TaggedObject.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1TaggedObject.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,236 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+public abstract class ASN1TaggedObject
+ extends ASN1Primitive
+ implements ASN1TaggedObjectParser
+{
+ int tagNo;
+ boolean empty = false;
+ boolean explicit = true;
+ ASN1Encodable obj = null;
+
+ static public ASN1TaggedObject getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ if (explicit)
+ {
+ return (ASN1TaggedObject)obj.getObject();
+ }
+
+ throw new IllegalArgumentException("implicitly tagged tagged object");
+ }
+
+ static public ASN1TaggedObject getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1TaggedObject)
+ {
+ return (ASN1TaggedObject)obj;
+ }
+ else if (obj instanceof byte[])
+ {
+ try
+ {
+ return ASN1TaggedObject.getInstance(fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct tagged object from byte[]: " + e.getMessage());
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Create a tagged object with the style given by the value of explicit.
+ *
+ * If the object implements ASN1Choice the tag style will always be changed
+ * to explicit in accordance with the ASN.1 encoding rules.
+ *
+ * @param explicit true if the object is explicitly tagged.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public ASN1TaggedObject(
+ boolean explicit,
+ int tagNo,
+ ASN1Encodable obj)
+ {
+ if (obj instanceof ASN1Choice)
+ {
+ this.explicit = true;
+ }
+ else
+ {
+ this.explicit = explicit;
+ }
+
+ this.tagNo = tagNo;
+
+ if (this.explicit)
+ {
+ this.obj = obj;
+ }
+ else
+ {
+ ASN1Primitive prim = obj.toASN1Primitive();
+
+ if (prim instanceof ASN1Set)
+ {
+ ASN1Set s = null;
+ }
+
+ this.obj = obj;
+ }
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof ASN1TaggedObject))
+ {
+ return false;
+ }
+
+ ASN1TaggedObject other = (ASN1TaggedObject)o;
+
+ if (tagNo != other.tagNo || empty != other.empty || explicit != other.explicit)
+ {
+ return false;
+ }
+
+ if(obj == null)
+ {
+ if (other.obj != null)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!(obj.toASN1Primitive().equals(other.obj.toASN1Primitive())))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ int code = tagNo;
+
+ // TODO: actually this is wrong - the problem is that a re-encoded
+ // object may end up with a different hashCode due to implicit
+ // tagging. As implicit tagging is ambiguous if a sequence is involved
+ // it seems the only correct method for both equals and hashCode is to
+ // compare the encodings...
+ if (obj != null)
+ {
+ code ^= obj.hashCode();
+ }
+
+ return code;
+ }
+
+ public int getTagNo()
+ {
+ return tagNo;
+ }
+
+ /**
+ * return whether or not the object may be explicitly tagged.
+ *
+ * Note: if the object has been read from an input stream, the only
+ * time you can be sure if isExplicit is returning the true state of
+ * affairs is if it returns false. An implicitly tagged object may appear
+ * to be explicitly tagged, so you need to understand the context under
+ * which the reading was done as well, see getObject below.
+ */
+ public boolean isExplicit()
+ {
+ return explicit;
+ }
+
+ public boolean isEmpty()
+ {
+ return empty;
+ }
+
+ /**
+ * return whatever was following the tag.
+ *
+ * Note: tagged objects are generally context dependent if you're
+ * trying to extract a tagged object you should be going via the
+ * appropriate getInstance method.
+ */
+ public ASN1Primitive getObject()
+ {
+ if (obj != null)
+ {
+ return obj.toASN1Primitive();
+ }
+
+ return null;
+ }
+
+ /**
+ * Return the object held in this tagged object as a parser assuming it has
+ * the type of the passed in tag. If the object doesn't have a parser
+ * associated with it, the base object is returned.
+ */
+ public ASN1Encodable getObjectParser(
+ int tag,
+ boolean isExplicit)
+ {
+ switch (tag)
+ {
+ case BERTags.SET:
+ return ASN1Set.getInstance(this, isExplicit).parser();
+ case BERTags.SEQUENCE:
+ return ASN1Sequence.getInstance(this, isExplicit).parser();
+ case BERTags.OCTET_STRING:
+ return ASN1OctetString.getInstance(this, isExplicit).parser();
+ }
+
+ if (isExplicit)
+ {
+ return getObject();
+ }
+
+ throw new RuntimeException("implicit tagging not implemented for tag: " + tag);
+ }
+
+ public ASN1Primitive getLoadedObject()
+ {
+ return this.toASN1Primitive();
+ }
+
+ ASN1Primitive toDERObject()
+ {
+ return new DERTaggedObject(explicit, tagNo, obj);
+ }
+
+ ASN1Primitive toDLObject()
+ {
+ return new DLTaggedObject(explicit, tagNo, obj);
+ }
+
+ abstract void encode(ASN1OutputStream out)
+ throws IOException;
+
+ public String toString()
+ {
+ return "[" + tagNo + "]" + obj;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1TaggedObjectParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1TaggedObjectParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1TaggedObjectParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1TaggedObjectParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,12 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public interface ASN1TaggedObjectParser
+ extends ASN1Encodable, InMemoryRepresentable
+{
+ public int getTagNo();
+
+ public ASN1Encodable getObjectParser(int tag, boolean isExplicit)
+ throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1UTCTime.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1UTCTime.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ASN1UTCTime.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ASN1UTCTime.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,22 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.util.Date;
+
+public class ASN1UTCTime
+ extends DERUTCTime
+{
+ ASN1UTCTime(byte[] bytes)
+ {
+ super(bytes);
+ }
+
+ public ASN1UTCTime(Date time)
+ {
+ super(time);
+ }
+
+ public ASN1UTCTime(String time)
+ {
+ super(time);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERApplicationSpecific.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERApplicationSpecific.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERApplicationSpecific.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERApplicationSpecific.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,10 @@
+package pdftk.org.bouncycastle.asn1;
+
+public class BERApplicationSpecific
+ extends DERApplicationSpecific
+{
+ public BERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
+ {
+ super(tagNo, vec);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERApplicationSpecificParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERApplicationSpecificParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERApplicationSpecificParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERApplicationSpecificParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,41 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class BERApplicationSpecificParser
+ implements ASN1ApplicationSpecificParser
+{
+ private final int tag;
+ private final ASN1StreamParser parser;
+
+ BERApplicationSpecificParser(int tag, ASN1StreamParser parser)
+ {
+ this.tag = tag;
+ this.parser = parser;
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ return parser.readObject();
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new BERApplicationSpecific(tag, parser.readVector());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException(e.getMessage(), e);
+ }
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERConstructedOctetString.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERConstructedOctetString.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERConstructedOctetString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERConstructedOctetString.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,144 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * @deprecated use BEROctetString
+ */
+public class BERConstructedOctetString
+ extends BEROctetString
+{
+ private static final int MAX_LENGTH = 1000;
+
+ /**
+ * convert a vector of octet strings into a single byte string
+ */
+ static private byte[] toBytes(
+ Vector octs)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != octs.size(); i++)
+ {
+ try
+ {
+ DEROctetString o = (DEROctetString)octs.elementAt(i);
+
+ bOut.write(o.getOctets());
+ }
+ catch (ClassCastException e)
+ {
+ throw new IllegalArgumentException(octs.elementAt(i).getClass().getName() + " found in input should only contain DEROctetString");
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("exception converting octets " + e.toString());
+ }
+ }
+
+ return bOut.toByteArray();
+ }
+
+ private Vector octs;
+
+ /**
+ * @param string the octets making up the octet string.
+ */
+ public BERConstructedOctetString(
+ byte[] string)
+ {
+ super(string);
+ }
+
+ public BERConstructedOctetString(
+ Vector octs)
+ {
+ super(toBytes(octs));
+
+ this.octs = octs;
+ }
+
+ public BERConstructedOctetString(
+ ASN1Primitive obj)
+ {
+ super(toByteArray(obj));
+ }
+
+ private static byte[] toByteArray(ASN1Primitive obj)
+ {
+ try
+ {
+ return obj.getEncoded();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("Unable to encode object");
+ }
+ }
+
+ public BERConstructedOctetString(
+ ASN1Encodable obj)
+ {
+ this(obj.toASN1Primitive());
+ }
+
+ public byte[] getOctets()
+ {
+ return string;
+ }
+
+ /**
+ * return the DER octets that make up this string.
+ */
+ public Enumeration getObjects()
+ {
+ if (octs == null)
+ {
+ return generateOcts().elements();
+ }
+
+ return octs.elements();
+ }
+
+ private Vector generateOcts()
+ {
+ Vector vec = new Vector();
+ for (int i = 0; i < string.length; i += MAX_LENGTH)
+ {
+ int end;
+
+ if (i + MAX_LENGTH > string.length)
+ {
+ end = string.length;
+ }
+ else
+ {
+ end = i + MAX_LENGTH;
+ }
+
+ byte[] nStr = new byte[end - i];
+
+ System.arraycopy(string, i, nStr, 0, nStr.length);
+
+ vec.addElement(new DEROctetString(nStr));
+ }
+
+ return vec;
+ }
+
+ public static BEROctetString fromSequence(ASN1Sequence seq)
+ {
+ Vector v = new Vector();
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ v.addElement(e.nextElement());
+ }
+
+ return new BERConstructedOctetString(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERFactory.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERFactory.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERFactory.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERFactory.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,17 @@
+package pdftk.org.bouncycastle.asn1;
+
+class BERFactory
+{
+ static final BERSequence EMPTY_SEQUENCE = new BERSequence();
+ static final BERSet EMPTY_SET = new BERSet();
+
+ static BERSequence createSequence(ASN1EncodableVector v)
+ {
+ return v.size() < 1 ? EMPTY_SEQUENCE : new BERSequence(v);
+ }
+
+ static BERSet createSet(ASN1EncodableVector v)
+ {
+ return v.size() < 1 ? EMPTY_SET : new BERSet(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERGenerator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,100 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class BERGenerator
+ extends ASN1Generator
+{
+ private boolean _tagged = false;
+ private boolean _isExplicit;
+ private int _tagNo;
+
+ protected BERGenerator(
+ OutputStream out)
+ {
+ super(out);
+ }
+
+ public BERGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ {
+ super(out);
+
+ _tagged = true;
+ _isExplicit = isExplicit;
+ _tagNo = tagNo;
+ }
+
+ public OutputStream getRawOutputStream()
+ {
+ return _out;
+ }
+
+ private void writeHdr(
+ int tag)
+ throws IOException
+ {
+ _out.write(tag);
+ _out.write(0x80);
+ }
+
+ protected void writeBERHeader(
+ int tag)
+ throws IOException
+ {
+ if (_tagged)
+ {
+ int tagNum = _tagNo | BERTags.TAGGED;
+
+ if (_isExplicit)
+ {
+ writeHdr(tagNum | BERTags.CONSTRUCTED);
+ writeHdr(tag);
+ }
+ else
+ {
+ if ((tag & BERTags.CONSTRUCTED) != 0)
+ {
+ writeHdr(tagNum | BERTags.CONSTRUCTED);
+ }
+ else
+ {
+ writeHdr(tagNum);
+ }
+ }
+ }
+ else
+ {
+ writeHdr(tag);
+ }
+ }
+
+ protected void writeBERBody(
+ InputStream contentStream)
+ throws IOException
+ {
+ int ch;
+
+ while ((ch = contentStream.read()) >= 0)
+ {
+ _out.write(ch);
+ }
+ }
+
+ protected void writeBEREnd()
+ throws IOException
+ {
+ _out.write(0x00);
+ _out.write(0x00);
+
+ if (_tagged && _isExplicit) // write extra end for tag header
+ {
+ _out.write(0x00);
+ _out.write(0x00);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BEROctetString.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BEROctetString.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BEROctetString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BEROctetString.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,168 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public class BEROctetString
+ extends ASN1OctetString
+{
+ private static final int MAX_LENGTH = 1000;
+
+ private ASN1OctetString[] octs;
+
+ /**
+ * convert a vector of octet strings into a single byte string
+ */
+ static private byte[] toBytes(
+ ASN1OctetString[] octs)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != octs.length; i++)
+ {
+ try
+ {
+ DEROctetString o = (DEROctetString)octs[i];
+
+ bOut.write(o.getOctets());
+ }
+ catch (ClassCastException e)
+ {
+ throw new IllegalArgumentException(octs[i].getClass().getName() + " found in input should only contain DEROctetString");
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("exception converting octets " + e.toString());
+ }
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * @param string the octets making up the octet string.
+ */
+ public BEROctetString(
+ byte[] string)
+ {
+ super(string);
+ }
+
+ public BEROctetString(
+ ASN1OctetString[] octs)
+ {
+ super(toBytes(octs));
+
+ this.octs = octs;
+ }
+
+ public byte[] getOctets()
+ {
+ return string;
+ }
+
+ /**
+ * return the DER octets that make up this string.
+ */
+ public Enumeration getObjects()
+ {
+ if (octs == null)
+ {
+ return generateOcts().elements();
+ }
+
+ return new Enumeration()
+ {
+ int counter = 0;
+
+ public boolean hasMoreElements()
+ {
+ return counter < octs.length;
+ }
+
+ public Object nextElement()
+ {
+ return octs[counter++];
+ }
+ };
+ }
+
+ private Vector generateOcts()
+ {
+ Vector vec = new Vector();
+ for (int i = 0; i < string.length; i += MAX_LENGTH)
+ {
+ int end;
+
+ if (i + MAX_LENGTH > string.length)
+ {
+ end = string.length;
+ }
+ else
+ {
+ end = i + MAX_LENGTH;
+ }
+
+ byte[] nStr = new byte[end - i];
+
+ System.arraycopy(string, i, nStr, 0, nStr.length);
+
+ vec.addElement(new DEROctetString(nStr));
+ }
+
+ return vec;
+ }
+
+ boolean isConstructed()
+ {
+ return true;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = 0;
+ for (Enumeration e = getObjects(); e.hasMoreElements();)
+ {
+ length += ((ASN1Encodable)e.nextElement()).toASN1Primitive().encodedLength();
+ }
+
+ return 2 + length + 2;
+ }
+
+ public void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.write(BERTags.CONSTRUCTED | BERTags.OCTET_STRING);
+
+ out.write(0x80);
+
+ //
+ // write out the octet array
+ //
+ for (Enumeration e = getObjects(); e.hasMoreElements();)
+ {
+ out.writeObject((ASN1Encodable)e.nextElement());
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+
+ static BEROctetString fromSequence(ASN1Sequence seq)
+ {
+ ASN1OctetString[] v = new ASN1OctetString[seq.size()];
+ Enumeration e = seq.getObjects();
+ int index = 0;
+
+ while (e.hasMoreElements())
+ {
+ v[index++] = (ASN1OctetString)e.nextElement();
+ }
+
+ return new BEROctetString(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BEROctetStringGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BEROctetStringGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BEROctetStringGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BEROctetStringGenerator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,102 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BEROctetStringGenerator
+ extends BERGenerator
+{
+ public BEROctetStringGenerator(OutputStream out)
+ throws IOException
+ {
+ super(out);
+
+ writeBERHeader(BERTags.CONSTRUCTED | BERTags.OCTET_STRING);
+ }
+
+ public BEROctetStringGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ throws IOException
+ {
+ super(out, tagNo, isExplicit);
+
+ writeBERHeader(BERTags.CONSTRUCTED | BERTags.OCTET_STRING);
+ }
+
+ public OutputStream getOctetOutputStream()
+ {
+ return getOctetOutputStream(new byte[1000]); // limit for CER encoding.
+ }
+
+ public OutputStream getOctetOutputStream(
+ byte[] buf)
+ {
+ return new BufferedBEROctetStream(buf);
+ }
+
+ private class BufferedBEROctetStream
+ extends OutputStream
+ {
+ private byte[] _buf;
+ private int _off;
+ private DEROutputStream _derOut;
+
+ BufferedBEROctetStream(
+ byte[] buf)
+ {
+ _buf = buf;
+ _off = 0;
+ _derOut = new DEROutputStream(_out);
+ }
+
+ public void write(
+ int b)
+ throws IOException
+ {
+ _buf[_off++] = (byte)b;
+
+ if (_off == _buf.length)
+ {
+ DEROctetString.encode(_derOut, _buf);
+ _off = 0;
+ }
+ }
+
+ public void write(byte[] b, int off, int len) throws IOException
+ {
+ while (len > 0)
+ {
+ int numToCopy = Math.min(len, _buf.length - _off);
+ System.arraycopy(b, off, _buf, _off, numToCopy);
+
+ _off += numToCopy;
+ if (_off < _buf.length)
+ {
+ break;
+ }
+
+ DEROctetString.encode(_derOut, _buf);
+ _off = 0;
+
+ off += numToCopy;
+ len -= numToCopy;
+ }
+ }
+
+ public void close()
+ throws IOException
+ {
+ if (_off != 0)
+ {
+ byte[] bytes = new byte[_off];
+ System.arraycopy(_buf, 0, bytes, 0, _off);
+
+ DEROctetString.encode(_derOut, bytes);
+ }
+
+ writeBEREnd();
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BEROctetStringParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BEROctetStringParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BEROctetStringParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BEROctetStringParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,41 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import pdftk.org.bouncycastle.util.io.Streams;
+
+public class BEROctetStringParser
+ implements ASN1OctetStringParser
+{
+ private ASN1StreamParser _parser;
+
+ BEROctetStringParser(
+ ASN1StreamParser parser)
+ {
+ _parser = parser;
+ }
+
+ public InputStream getOctetStream()
+ {
+ return new ConstructedOctetStream(_parser);
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new BEROctetString(Streams.readAll(getOctetStream()));
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BEROutputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BEROutputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BEROutputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BEROutputStream.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,36 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BEROutputStream
+ extends DEROutputStream
+{
+ public BEROutputStream(
+ OutputStream os)
+ {
+ super(os);
+ }
+
+ public void writeObject(
+ Object obj)
+ throws IOException
+ {
+ if (obj == null)
+ {
+ writeNull();
+ }
+ else if (obj instanceof ASN1Primitive)
+ {
+ ((ASN1Primitive)obj).encode(this);
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ ((ASN1Encodable)obj).toASN1Primitive().encode(this);
+ }
+ else
+ {
+ throw new IOException("object not BEREncodable");
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERSequence.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERSequence.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERSequence.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERSequence.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,73 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class BERSequence
+ extends ASN1Sequence
+{
+ /**
+ * create an empty sequence
+ */
+ public BERSequence()
+ {
+ }
+
+ /**
+ * create a sequence containing one object
+ */
+ public BERSequence(
+ ASN1Encodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ public BERSequence(
+ ASN1EncodableVector v)
+ {
+ super(v);
+ }
+
+ /**
+ * create a sequence containing an array of objects.
+ */
+ public BERSequence(
+ ASN1Encodable[] array)
+ {
+ super(array);
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = 0;
+ for (Enumeration e = getObjects(); e.hasMoreElements();)
+ {
+ length += ((ASN1Encodable)e.nextElement()).toASN1Primitive().encodedLength();
+ }
+
+ return 2 + length + 2;
+ }
+
+ /*
+ */
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED);
+ out.write(0x80);
+
+ Enumeration e = getObjects();
+ while (e.hasMoreElements())
+ {
+ out.writeObject((ASN1Encodable)e.nextElement());
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERSequenceGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERSequenceGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERSequenceGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERSequenceGenerator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,41 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BERSequenceGenerator
+ extends BERGenerator
+{
+ public BERSequenceGenerator(
+ OutputStream out)
+ throws IOException
+ {
+ super(out);
+
+ writeBERHeader(BERTags.CONSTRUCTED | BERTags.SEQUENCE);
+ }
+
+ public BERSequenceGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ throws IOException
+ {
+ super(out, tagNo, isExplicit);
+
+ writeBERHeader(BERTags.CONSTRUCTED | BERTags.SEQUENCE);
+ }
+
+ public void addObject(
+ ASN1Encodable object)
+ throws IOException
+ {
+ object.toASN1Primitive().encode(new BEROutputStream(_out));
+ }
+
+ public void close()
+ throws IOException
+ {
+ writeBEREnd();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERSequenceParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERSequenceParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERSequenceParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERSequenceParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,38 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class BERSequenceParser
+ implements ASN1SequenceParser
+{
+ private ASN1StreamParser _parser;
+
+ BERSequenceParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new BERSequence(_parser.readVector());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERSet.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERSet.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERSet.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERSet.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,73 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class BERSet
+ extends ASN1Set
+{
+ /**
+ * create an empty sequence
+ */
+ public BERSet()
+ {
+ }
+
+ /**
+ * @param obj - a single object that makes up the set.
+ */
+ public BERSet(
+ ASN1Encodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * @param v - a vector of objects making up the set.
+ */
+ public BERSet(
+ ASN1EncodableVector v)
+ {
+ super(v, false);
+ }
+
+ /**
+ * create a set from an array of objects.
+ */
+ public BERSet(
+ ASN1Encodable[] a)
+ {
+ super(a, false);
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = 0;
+ for (Enumeration e = getObjects(); e.hasMoreElements();)
+ {
+ length += ((ASN1Encodable)e.nextElement()).toASN1Primitive().encodedLength();
+ }
+
+ return 2 + length + 2;
+ }
+
+ /*
+ */
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.write(BERTags.SET | BERTags.CONSTRUCTED);
+ out.write(0x80);
+
+ Enumeration e = getObjects();
+ while (e.hasMoreElements())
+ {
+ out.writeObject((ASN1Encodable)e.nextElement());
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERSetParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERSetParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERSetParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERSetParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,38 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class BERSetParser
+ implements ASN1SetParser
+{
+ private ASN1StreamParser _parser;
+
+ BERSetParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new BERSet(_parser.readVector());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException(e.getMessage(), e);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERTaggedObject.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERTaggedObject.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERTaggedObject.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERTaggedObject.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,147 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * BER TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+public class BERTaggedObject
+ extends ASN1TaggedObject
+{
+ /**
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public BERTaggedObject(
+ int tagNo,
+ ASN1Encodable obj)
+ {
+ super(true, tagNo, obj);
+ }
+
+ /**
+ * @param explicit true if an explicitly tagged object.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public BERTaggedObject(
+ boolean explicit,
+ int tagNo,
+ ASN1Encodable obj)
+ {
+ super(explicit, tagNo, obj);
+ }
+
+ /**
+ * create an implicitly tagged object that contains a zero
+ * length sequence.
+ */
+ public BERTaggedObject(
+ int tagNo)
+ {
+ super(false, tagNo, new BERSequence());
+ }
+
+ boolean isConstructed()
+ {
+ if (!empty)
+ {
+ if (explicit)
+ {
+ return true;
+ }
+ else
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
+
+ return primitive.isConstructed();
+ }
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ if (!empty)
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive();
+ int length = primitive.encodedLength();
+
+ if (explicit)
+ {
+ return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
+ }
+ else
+ {
+ // header length already in calculation
+ length = length - 1;
+
+ return StreamUtil.calculateTagLength(tagNo) + length;
+ }
+ }
+ else
+ {
+ return StreamUtil.calculateTagLength(tagNo) + 1;
+ }
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
+ out.write(0x80);
+
+ if (!empty)
+ {
+ if (!explicit)
+ {
+ Enumeration e;
+ if (obj instanceof ASN1OctetString)
+ {
+ if (obj instanceof BEROctetString)
+ {
+ e = ((BEROctetString)obj).getObjects();
+ }
+ else
+ {
+ ASN1OctetString octs = (ASN1OctetString)obj;
+ BEROctetString berO = new BEROctetString(octs.getOctets());
+ e = berO.getObjects();
+ }
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ e = ((ASN1Sequence)obj).getObjects();
+ }
+ else if (obj instanceof ASN1Set)
+ {
+ e = ((ASN1Set)obj).getObjects();
+ }
+ else
+ {
+ throw new RuntimeException("not implemented: " + obj.getClass().getName());
+ }
+
+ while (e.hasMoreElements())
+ {
+ out.writeObject((ASN1Encodable)e.nextElement());
+ }
+ }
+ else
+ {
+ out.writeObject(obj);
+ }
+ }
+
+ out.write(0x00);
+ out.write(0x00);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERTaggedObjectParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERTaggedObjectParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERTaggedObjectParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERTaggedObjectParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,66 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class BERTaggedObjectParser
+ implements ASN1TaggedObjectParser
+{
+ private boolean _constructed;
+ private int _tagNumber;
+ private ASN1StreamParser _parser;
+
+ BERTaggedObjectParser(
+ boolean constructed,
+ int tagNumber,
+ ASN1StreamParser parser)
+ {
+ _constructed = constructed;
+ _tagNumber = tagNumber;
+ _parser = parser;
+ }
+
+ public boolean isConstructed()
+ {
+ return _constructed;
+ }
+
+ public int getTagNo()
+ {
+ return _tagNumber;
+ }
+
+ public ASN1Encodable getObjectParser(
+ int tag,
+ boolean isExplicit)
+ throws IOException
+ {
+ if (isExplicit)
+ {
+ if (!_constructed)
+ {
+ throw new IOException("Explicit tags must be constructed (see X.690 8.14.2)");
+ }
+ return _parser.readObject();
+ }
+
+ return _parser.readImplicit(_constructed, tag);
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return _parser.readTaggedObject(_constructed, _tagNumber);
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return this.getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException(e.getMessage());
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERTags.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERTags.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/BERTags.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/BERTags.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,36 @@
+package pdftk.org.bouncycastle.asn1;
+
+public interface BERTags
+{
+ public static final int BOOLEAN = 0x01;
+ public static final int INTEGER = 0x02;
+ public static final int BIT_STRING = 0x03;
+ public static final int OCTET_STRING = 0x04;
+ public static final int NULL = 0x05;
+ public static final int OBJECT_IDENTIFIER = 0x06;
+ public static final int EXTERNAL = 0x08;
+ public static final int ENUMERATED = 0x0a;
+ public static final int SEQUENCE = 0x10;
+ public static final int SEQUENCE_OF = 0x10; // for completeness
+ public static final int SET = 0x11;
+ public static final int SET_OF = 0x11; // for completeness
+
+
+ public static final int NUMERIC_STRING = 0x12;
+ public static final int PRINTABLE_STRING = 0x13;
+ public static final int T61_STRING = 0x14;
+ public static final int VIDEOTEX_STRING = 0x15;
+ public static final int IA5_STRING = 0x16;
+ public static final int UTC_TIME = 0x17;
+ public static final int GENERALIZED_TIME = 0x18;
+ public static final int GRAPHIC_STRING = 0x19;
+ public static final int VISIBLE_STRING = 0x1a;
+ public static final int GENERAL_STRING = 0x1b;
+ public static final int UNIVERSAL_STRING = 0x1c;
+ public static final int BMP_STRING = 0x1e;
+ public static final int UTF8_STRING = 0x0c;
+
+ public static final int CONSTRUCTED = 0x20;
+ public static final int APPLICATION = 0x40;
+ public static final int TAGGED = 0x80;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ConstructedOctetStream.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ConstructedOctetStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ConstructedOctetStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ConstructedOctetStream.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,111 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+class ConstructedOctetStream
+ extends InputStream
+{
+ private final ASN1StreamParser _parser;
+
+ private boolean _first = true;
+ private InputStream _currentStream;
+
+ ConstructedOctetStream(
+ ASN1StreamParser parser)
+ {
+ _parser = parser;
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ if (_currentStream == null)
+ {
+ if (!_first)
+ {
+ return -1;
+ }
+
+ ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
+
+ if (s == null)
+ {
+ return -1;
+ }
+
+ _first = false;
+ _currentStream = s.getOctetStream();
+ }
+
+ int totalRead = 0;
+
+ for (;;)
+ {
+ int numRead = _currentStream.read(b, off + totalRead, len - totalRead);
+
+ if (numRead >= 0)
+ {
+ totalRead += numRead;
+
+ if (totalRead == len)
+ {
+ return totalRead;
+ }
+ }
+ else
+ {
+ ASN1OctetStringParser aos = (ASN1OctetStringParser)_parser.readObject();
+
+ if (aos == null)
+ {
+ _currentStream = null;
+ return totalRead < 1 ? -1 : totalRead;
+ }
+
+ _currentStream = aos.getOctetStream();
+ }
+ }
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (_currentStream == null)
+ {
+ if (!_first)
+ {
+ return -1;
+ }
+
+ ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
+
+ if (s == null)
+ {
+ return -1;
+ }
+
+ _first = false;
+ _currentStream = s.getOctetStream();
+ }
+
+ for (;;)
+ {
+ int b = _currentStream.read();
+
+ if (b >= 0)
+ {
+ return b;
+ }
+
+ ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();
+
+ if (s == null)
+ {
+ _currentStream = null;
+ return -1;
+ }
+
+ _currentStream = s.getOctetStream();
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERApplicationSpecific.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERApplicationSpecific.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERApplicationSpecific.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERApplicationSpecific.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,276 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * Base class for an application specific object
+ */
+public class DERApplicationSpecific
+ extends ASN1Primitive
+{
+ private final boolean isConstructed;
+ private final int tag;
+ private final byte[] octets;
+
+ DERApplicationSpecific(
+ boolean isConstructed,
+ int tag,
+ byte[] octets)
+ {
+ this.isConstructed = isConstructed;
+ this.tag = tag;
+ this.octets = octets;
+ }
+
+ public DERApplicationSpecific(
+ int tag,
+ byte[] octets)
+ {
+ this(false, tag, octets);
+ }
+
+ public DERApplicationSpecific(
+ int tag,
+ ASN1Encodable object)
+ throws IOException
+ {
+ this(true, tag, object);
+ }
+
+ public DERApplicationSpecific(
+ boolean explicit,
+ int tag,
+ ASN1Encodable object)
+ throws IOException
+ {
+ ASN1Primitive primitive = object.toASN1Primitive();
+
+ byte[] data = primitive.getEncoded(ASN1Encoding.DER);
+
+ this.isConstructed = explicit || (primitive instanceof ASN1Set || primitive instanceof ASN1Sequence);
+ this.tag = tag;
+
+ if (explicit)
+ {
+ this.octets = data;
+ }
+ else
+ {
+ int lenBytes = getLengthOfHeader(data);
+ byte[] tmp = new byte[data.length - lenBytes];
+ System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
+ this.octets = tmp;
+ }
+ }
+
+ public DERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
+ {
+ this.tag = tagNo;
+ this.isConstructed = true;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != vec.size(); i++)
+ {
+ try
+ {
+ bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.DER));
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("malformed object: " + e, e);
+ }
+ }
+ this.octets = bOut.toByteArray();
+ }
+
+ public static DERApplicationSpecific getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DERApplicationSpecific)
+ {
+ return (DERApplicationSpecific)obj;
+ }
+ else if (obj instanceof byte[])
+ {
+ try
+ {
+ return DERApplicationSpecific.getInstance(ASN1Primitive.fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("failed to construct object from byte[]: " + e.getMessage());
+ }
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (primitive instanceof ASN1Sequence)
+ {
+ return (DERApplicationSpecific)primitive;
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ private int getLengthOfHeader(byte[] data)
+ {
+ int length = data[1] & 0xff; // TODO: assumes 1 byte tag
+
+ if (length == 0x80)
+ {
+ return 2; // indefinite-length encoding
+ }
+
+ if (length > 127)
+ {
+ int size = length & 0x7f;
+
+ // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+ if (size > 4)
+ {
+ throw new IllegalStateException("DER length more than 4 bytes: " + size);
+ }
+
+ return size + 2;
+ }
+
+ return 2;
+ }
+
+ public boolean isConstructed()
+ {
+ return isConstructed;
+ }
+
+ public byte[] getContents()
+ {
+ return octets;
+ }
+
+ public int getApplicationTag()
+ {
+ return tag;
+ }
+
+ /**
+ * Return the enclosed object assuming explicit tagging.
+ *
+ * @return the resulting object
+ * @throws IOException if reconstruction fails.
+ */
+ public ASN1Primitive getObject()
+ throws IOException
+ {
+ return new ASN1InputStream(getContents()).readObject();
+ }
+
+ /**
+ * Return the enclosed object assuming implicit tagging.
+ *
+ * @param derTagNo the type tag that should be applied to the object's contents.
+ * @return the resulting object
+ * @throws IOException if reconstruction fails.
+ */
+ public ASN1Primitive getObject(int derTagNo)
+ throws IOException
+ {
+ if (derTagNo >= 0x1f)
+ {
+ throw new IOException("unsupported tag number");
+ }
+
+ byte[] orig = this.getEncoded();
+ byte[] tmp = replaceTagNumber(derTagNo, orig);
+
+ if ((orig[0] & BERTags.CONSTRUCTED) != 0)
+ {
+ tmp[0] |= BERTags.CONSTRUCTED;
+ }
+
+ return new ASN1InputStream(tmp).readObject();
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ return StreamUtil.calculateTagLength(tag) + StreamUtil.calculateBodyLength(octets.length) + octets.length;
+ }
+
+ /* (non-Javadoc)
+ * @see pdftk.org.bouncycastle.asn1.ASN1Primitive#encode(pdftk.org.bouncycastle.asn1.DEROutputStream)
+ */
+ void encode(ASN1OutputStream out) throws IOException
+ {
+ int classBits = BERTags.APPLICATION;
+ if (isConstructed)
+ {
+ classBits |= BERTags.CONSTRUCTED;
+ }
+
+ out.writeEncoded(classBits, tag, octets);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERApplicationSpecific))
+ {
+ return false;
+ }
+
+ DERApplicationSpecific other = (DERApplicationSpecific)o;
+
+ return isConstructed == other.isConstructed
+ && tag == other.tag
+ && Arrays.areEqual(octets, other.octets);
+ }
+
+ public int hashCode()
+ {
+ return (isConstructed ? 1 : 0) ^ tag ^ Arrays.hashCode(octets);
+ }
+
+ private byte[] replaceTagNumber(int newTag, byte[] input)
+ throws IOException
+ {
+ int tagNo = input[0] & 0x1f;
+ int index = 1;
+ //
+ // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+ //
+ if (tagNo == 0x1f)
+ {
+ tagNo = 0;
+
+ int b = input[index++] & 0xff;
+
+ // X.690-0207 8.1.2.4.2
+ // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+ if ((b & 0x7f) == 0) // Note: -1 will pass
+ {
+ throw new ASN1ParsingException("corrupted stream - invalid high tag number found");
+ }
+
+ while ((b >= 0) && ((b & 0x80) != 0))
+ {
+ tagNo |= (b & 0x7f);
+ tagNo <<= 7;
+ b = input[index++] & 0xff;
+ }
+
+ tagNo |= (b & 0x7f);
+ }
+
+ byte[] tmp = new byte[input.length - index + 1];
+
+ System.arraycopy(input, index, tmp, 1, tmp.length - 1);
+
+ tmp[0] = (byte)newTag;
+
+ return tmp;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERBMPString.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERBMPString.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERBMPString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERBMPString.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,153 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * DER BMPString object.
+ */
+public class DERBMPString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private char[] string;
+
+ /**
+ * return a BMP String from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERBMPString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERBMPString)
+ {
+ return (DERBMPString)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERBMPString)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a BMP String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DERBMPString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERBMPString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERBMPString(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ DERBMPString(
+ byte[] string)
+ {
+ char[] cs = new char[string.length / 2];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)((string[2 * i] << 8) | (string[2 * i + 1] & 0xff));
+ }
+
+ this.string = cs;
+ }
+
+ DERBMPString(char[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor
+ */
+ public DERBMPString(
+ String string)
+ {
+ this.string = string.toCharArray();
+ }
+
+ public String getString()
+ {
+ return new String(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+
+ protected boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERBMPString))
+ {
+ return false;
+ }
+
+ DERBMPString s = (DERBMPString)o;
+
+ return Arrays.areEqual(string, s.string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length * 2) + (string.length * 2);
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.write(BERTags.BMP_STRING);
+ out.writeLength(string.length * 2);
+
+ for (int i = 0; i != string.length; i++)
+ {
+ char c = string[i];
+
+ out.write((byte)(c >> 8));
+ out.write((byte)c);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERBitString.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERBitString.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERBitString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERBitString.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,313 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.io.Streams;
+
+public class DERBitString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ protected byte[] data;
+ protected int padBits;
+
+ /**
+ * return the correct number of pad bits for a bit string defined in
+ * a 32 bit constant
+ */
+ static protected int getPadBits(
+ int bitString)
+ {
+ int val = 0;
+ for (int i = 3; i >= 0; i--)
+ {
+ //
+ // this may look a little odd, but if it isn't done like this pre jdk1.2
+ // JVM's break!
+ //
+ if (i != 0)
+ {
+ if ((bitString >> (i * 8)) != 0)
+ {
+ val = (bitString >> (i * 8)) & 0xFF;
+ break;
+ }
+ }
+ else
+ {
+ if (bitString != 0)
+ {
+ val = bitString & 0xFF;
+ break;
+ }
+ }
+ }
+
+ if (val == 0)
+ {
+ return 7;
+ }
+
+
+ int bits = 1;
+
+ while (((val <<= 1) & 0xFF) != 0)
+ {
+ bits++;
+ }
+
+ return 8 - bits;
+ }
+
+ /**
+ * return the correct number of bytes for a bit string defined in
+ * a 32 bit constant
+ */
+ static protected byte[] getBytes(int bitString)
+ {
+ int bytes = 4;
+ for (int i = 3; i >= 1; i--)
+ {
+ if ((bitString & (0xFF << (i * 8))) != 0)
+ {
+ break;
+ }
+ bytes--;
+ }
+
+ byte[] result = new byte[bytes];
+ for (int i = 0; i < bytes; i++)
+ {
+ result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
+ }
+
+ return result;
+ }
+
+ /**
+ * return a Bit String from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERBitString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERBitString)
+ {
+ return (DERBitString)obj;
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Bit String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DERBitString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERBitString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return fromOctetString(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ protected DERBitString(
+ byte data,
+ int padBits)
+ {
+ this.data = new byte[1];
+ this.data[0] = data;
+ this.padBits = padBits;
+ }
+
+ /**
+ * @param data the octets making up the bit string.
+ * @param padBits the number of extra bits at the end of the string.
+ */
+ public DERBitString(
+ byte[] data,
+ int padBits)
+ {
+ this.data = data;
+ this.padBits = padBits;
+ }
+
+ public DERBitString(
+ byte[] data)
+ {
+ this(data, 0);
+ }
+
+ public DERBitString(
+ int value)
+ {
+ this.data = getBytes(value);
+ this.padBits = getPadBits(value);
+ }
+
+ public DERBitString(
+ ASN1Encodable obj)
+ throws IOException
+ {
+ this.data = obj.toASN1Primitive().getEncoded(ASN1Encoding.DER);
+ this.padBits = 0;
+ }
+
+ public byte[] getBytes()
+ {
+ return data;
+ }
+
+ public int getPadBits()
+ {
+ return padBits;
+ }
+
+
+ /**
+ * @return the value of the bit string as an int (truncating if necessary)
+ */
+ public int intValue()
+ {
+ int value = 0;
+
+ for (int i = 0; i != data.length && i != 4; i++)
+ {
+ value |= (data[i] & 0xff) << (8 * i);
+ }
+
+ return value;
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(data.length + 1) + data.length + 1;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ byte[] bytes = new byte[getBytes().length + 1];
+
+ bytes[0] = (byte)getPadBits();
+ System.arraycopy(getBytes(), 0, bytes, 1, bytes.length - 1);
+
+ out.writeEncoded(BERTags.BIT_STRING, bytes);
+ }
+
+ public int hashCode()
+ {
+ return padBits ^ Arrays.hashCode(data);
+ }
+
+ protected boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERBitString))
+ {
+ return false;
+ }
+
+ DERBitString other = (DERBitString)o;
+
+ return this.padBits == other.padBits
+ && Arrays.areEqual(this.data, other.data);
+ }
+
+ public String getString()
+ {
+ StringBuffer buf = new StringBuffer("#");
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ try
+ {
+ aOut.writeObject(this);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("internal error encoding BitString");
+ }
+
+ byte[] string = bOut.toByteArray();
+
+ for (int i = 0; i != string.length; i++)
+ {
+ buf.append(table[(string[i] >>> 4) & 0xf]);
+ buf.append(table[string[i] & 0xf]);
+ }
+
+ return buf.toString();
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ static DERBitString fromOctetString(byte[] bytes)
+ {
+ if (bytes.length < 1)
+ {
+ throw new IllegalArgumentException("truncated BIT STRING detected");
+ }
+
+ int padBits = bytes[0];
+ byte[] data = new byte[bytes.length - 1];
+
+ if (data.length != 0)
+ {
+ System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
+ }
+
+ return new DERBitString(data, padBits);
+ }
+
+ static DERBitString fromInputStream(int length, InputStream stream)
+ throws IOException
+ {
+ if (length < 1)
+ {
+ throw new IllegalArgumentException("truncated BIT STRING detected");
+ }
+
+ int padBits = stream.read();
+ byte[] data = new byte[length - 1];
+
+ if (data.length != 0)
+ {
+ if (Streams.readFully(stream, data) != data.length)
+ {
+ throw new EOFException("EOF encountered in middle of BIT STRING");
+ }
+ }
+
+ return new DERBitString(data, padBits);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERBoolean.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERBoolean.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERBoolean.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERBoolean.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,179 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class DERBoolean
+ extends ASN1Primitive
+{
+ private static final byte[] TRUE_VALUE = new byte[] { (byte)0xff };
+ private static final byte[] FALSE_VALUE = new byte[] { 0 };
+
+ private byte[] value;
+
+ public static final ASN1Boolean FALSE = new ASN1Boolean(false);
+ public static final ASN1Boolean TRUE = new ASN1Boolean(true);
+
+
+ /**
+ * return a boolean from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1Boolean getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Boolean)
+ {
+ return (ASN1Boolean)obj;
+ }
+
+ if (obj instanceof DERBoolean)
+ {
+ return ((DERBoolean)obj).isTrue() ? DERBoolean.TRUE : DERBoolean.FALSE;
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a ASN1Boolean from the passed in boolean.
+ */
+ public static ASN1Boolean getInstance(
+ boolean value)
+ {
+ return (value ? TRUE : FALSE);
+ }
+
+ /**
+ * return a ASN1Boolean from the passed in boolean.
+ */
+ public static ASN1Boolean getInstance(
+ int value)
+ {
+ return (value != 0 ? TRUE : FALSE);
+ }
+
+ /**
+ * return a Boolean from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DERBoolean getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERBoolean)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return ASN1Boolean.fromOctetString(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ DERBoolean(
+ byte[] value)
+ {
+ if (value.length != 1)
+ {
+ throw new IllegalArgumentException("byte value should have 1 byte in it");
+ }
+
+ if (value[0] == 0)
+ {
+ this.value = FALSE_VALUE;
+ }
+ else if (value[0] == 0xff)
+ {
+ this.value = TRUE_VALUE;
+ }
+ else
+ {
+ this.value = Arrays.clone(value);
+ }
+ }
+
+ /**
+ * @deprecated use getInstance(boolean) method.
+ * @param value
+ */
+ public DERBoolean(
+ boolean value)
+ {
+ this.value = (value) ? TRUE_VALUE : FALSE_VALUE;
+ }
+
+ public boolean isTrue()
+ {
+ return (value[0] != 0);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 3;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.BOOLEAN, value);
+ }
+
+ protected boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if ((o == null) || !(o instanceof DERBoolean))
+ {
+ return false;
+ }
+
+ return (value[0] == ((DERBoolean)o).value[0]);
+ }
+
+ public int hashCode()
+ {
+ return value[0];
+ }
+
+
+ public String toString()
+ {
+ return (value[0] != 0) ? "TRUE" : "FALSE";
+ }
+
+ static ASN1Boolean fromOctetString(byte[] value)
+ {
+ if (value.length != 1)
+ {
+ throw new IllegalArgumentException("byte value should have 1 byte in it");
+ }
+
+ if (value[0] == 0)
+ {
+ return FALSE;
+ }
+ else if (value[0] == 0xff)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return new ASN1Boolean(value);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DEREncodableVector.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DEREncodableVector.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DEREncodableVector.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DEREncodableVector.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.asn1;
+
+/**
+ * a general class for building up a vector of DER encodable objects -
+ * this will eventually be superceded by ASN1EncodableVector so you should
+ * use that class in preference.
+ */
+public class DEREncodableVector
+ extends ASN1EncodableVector
+{
+ /**
+ * @deprecated use ASN1EncodableVector instead.
+ */
+ public DEREncodableVector()
+ {
+
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DEREnumerated.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DEREnumerated.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DEREnumerated.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DEREnumerated.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,158 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class DEREnumerated
+ extends ASN1Primitive
+{
+ byte[] bytes;
+
+ /**
+ * return an integer from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1Enumerated getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Enumerated)
+ {
+ return (ASN1Enumerated)obj;
+ }
+
+ if (obj instanceof DEREnumerated)
+ {
+ return new ASN1Enumerated(((DEREnumerated)obj).getValue());
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (ASN1Enumerated)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Enumerated from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DEREnumerated getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DEREnumerated)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return fromOctetString(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ public DEREnumerated(
+ int value)
+ {
+ bytes = BigInteger.valueOf(value).toByteArray();
+ }
+
+ public DEREnumerated(
+ BigInteger value)
+ {
+ bytes = value.toByteArray();
+ }
+
+ public DEREnumerated(
+ byte[] bytes)
+ {
+ this.bytes = bytes;
+ }
+
+ public BigInteger getValue()
+ {
+ return new BigInteger(bytes);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.ENUMERATED, bytes);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DEREnumerated))
+ {
+ return false;
+ }
+
+ DEREnumerated other = (DEREnumerated)o;
+
+ return Arrays.areEqual(this.bytes, other.bytes);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(bytes);
+ }
+
+ private static ASN1Enumerated[] cache = new ASN1Enumerated[12];
+
+ static ASN1Enumerated fromOctetString(byte[] enc)
+ {
+ if (enc.length > 1)
+ {
+ return new ASN1Enumerated(Arrays.clone(enc));
+ }
+
+ if (enc.length == 0)
+ {
+ throw new IllegalArgumentException("ENUMERATED has zero length");
+ }
+ int value = enc[0] & 0xff;
+
+ if (value >= cache.length)
+ {
+ return new ASN1Enumerated(Arrays.clone(enc));
+ }
+
+ ASN1Enumerated possibleMatch = cache[value];
+
+ if (possibleMatch == null)
+ {
+ possibleMatch = cache[value] = new ASN1Enumerated(Arrays.clone(enc));
+ }
+
+ return possibleMatch;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERExternal.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERExternal.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERExternal.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERExternal.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,294 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Class representing the DER-type External
+ */
+public class DERExternal
+ extends ASN1Primitive
+{
+ private ASN1ObjectIdentifier directReference;
+ private ASN1Integer indirectReference;
+ private ASN1Primitive dataValueDescriptor;
+ private int encoding;
+ private ASN1Primitive externalContent;
+
+ public DERExternal(ASN1EncodableVector vector)
+ {
+ int offset = 0;
+
+ ASN1Primitive enc = getObjFromVector(vector, offset);
+ if (enc instanceof ASN1ObjectIdentifier)
+ {
+ directReference = (ASN1ObjectIdentifier)enc;
+ offset++;
+ enc = getObjFromVector(vector, offset);
+ }
+ if (enc instanceof ASN1Integer)
+ {
+ indirectReference = (ASN1Integer) enc;
+ offset++;
+ enc = getObjFromVector(vector, offset);
+ }
+ if (!(enc instanceof DERTaggedObject))
+ {
+ dataValueDescriptor = (ASN1Primitive) enc;
+ offset++;
+ enc = getObjFromVector(vector, offset);
+ }
+
+ if (vector.size() != offset + 1)
+ {
+ throw new IllegalArgumentException("input vector too large");
+ }
+
+ if (!(enc instanceof DERTaggedObject))
+ {
+ throw new IllegalArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External");
+ }
+ DERTaggedObject obj = (DERTaggedObject)enc;
+ setEncoding(obj.getTagNo());
+ externalContent = obj.getObject();
+ }
+
+ private ASN1Primitive getObjFromVector(ASN1EncodableVector v, int index)
+ {
+ if (v.size() <= index)
+ {
+ throw new IllegalArgumentException("too few objects in input vector");
+ }
+
+ return v.get(index).toASN1Primitive();
+ }
+ /**
+ * Creates a new instance of DERExternal
+ * See X.690 for more informations about the meaning of these parameters
+ * @param directReference The direct reference or null
if not set.
+ * @param indirectReference The indirect reference or null
if not set.
+ * @param dataValueDescriptor The data value descriptor or null
if not set.
+ * @param externalData The external data in its encoded form.
+ */
+ public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, DERTaggedObject externalData)
+ {
+ this(directReference, indirectReference, dataValueDescriptor, externalData.getTagNo(), externalData.toASN1Primitive());
+ }
+
+ /**
+ * Creates a new instance of DERExternal.
+ * See X.690 for more informations about the meaning of these parameters
+ * @param directReference The direct reference or null
if not set.
+ * @param indirectReference The indirect reference or null
if not set.
+ * @param dataValueDescriptor The data value descriptor or null
if not set.
+ * @param encoding The encoding to be used for the external data
+ * @param externalData The external data
+ */
+ public DERExternal(ASN1ObjectIdentifier directReference, ASN1Integer indirectReference, ASN1Primitive dataValueDescriptor, int encoding, ASN1Primitive externalData)
+ {
+ setDirectReference(directReference);
+ setIndirectReference(indirectReference);
+ setDataValueDescriptor(dataValueDescriptor);
+ setEncoding(encoding);
+ setExternalContent(externalData.toASN1Primitive());
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode()
+ {
+ int ret = 0;
+ if (directReference != null)
+ {
+ ret = directReference.hashCode();
+ }
+ if (indirectReference != null)
+ {
+ ret ^= indirectReference.hashCode();
+ }
+ if (dataValueDescriptor != null)
+ {
+ ret ^= dataValueDescriptor.hashCode();
+ }
+ ret ^= externalContent.hashCode();
+ return ret;
+ }
+
+ boolean isConstructed()
+ {
+ return true;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ return this.getEncoded().length;
+ }
+
+ /* (non-Javadoc)
+ * @see pdftk.org.bouncycastle.asn1.ASN1Primitive#encode(pdftk.org.bouncycastle.asn1.DEROutputStream)
+ */
+ void encode(ASN1OutputStream out)
+ throws IOException
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ if (directReference != null)
+ {
+ baos.write(directReference.getEncoded(ASN1Encoding.DER));
+ }
+ if (indirectReference != null)
+ {
+ baos.write(indirectReference.getEncoded(ASN1Encoding.DER));
+ }
+ if (dataValueDescriptor != null)
+ {
+ baos.write(dataValueDescriptor.getEncoded(ASN1Encoding.DER));
+ }
+ DERTaggedObject obj = new DERTaggedObject(true, encoding, externalContent);
+ baos.write(obj.getEncoded(ASN1Encoding.DER));
+ out.writeEncoded(BERTags.CONSTRUCTED, BERTags.EXTERNAL, baos.toByteArray());
+ }
+
+ /* (non-Javadoc)
+ * @see pdftk.org.bouncycastle.asn1.ASN1Primitive#asn1Equals(pdftk.org.bouncycastle.asn1.ASN1Primitive)
+ */
+ boolean asn1Equals(ASN1Primitive o)
+ {
+ if (!(o instanceof DERExternal))
+ {
+ return false;
+ }
+ if (this == o)
+ {
+ return true;
+ }
+ DERExternal other = (DERExternal)o;
+ if (directReference != null)
+ {
+ if (other.directReference == null || !other.directReference.equals(directReference))
+ {
+ return false;
+ }
+ }
+ if (indirectReference != null)
+ {
+ if (other.indirectReference == null || !other.indirectReference.equals(indirectReference))
+ {
+ return false;
+ }
+ }
+ if (dataValueDescriptor != null)
+ {
+ if (other.dataValueDescriptor == null || !other.dataValueDescriptor.equals(dataValueDescriptor))
+ {
+ return false;
+ }
+ }
+ return externalContent.equals(other.externalContent);
+ }
+
+ /**
+ * Returns the data value descriptor
+ * @return The descriptor
+ */
+ public ASN1Primitive getDataValueDescriptor()
+ {
+ return dataValueDescriptor;
+ }
+
+ /**
+ * Returns the direct reference of the external element
+ * @return The reference
+ */
+ public ASN1ObjectIdentifier getDirectReference()
+ {
+ return directReference;
+ }
+
+ /**
+ * Returns the encoding of the content. Valid values are
+ *
+ * 0
single-ASN1-type
+ * 1
OCTET STRING
+ * 2
BIT STRING
+ *
+ * @return The encoding
+ */
+ public int getEncoding()
+ {
+ return encoding;
+ }
+
+ /**
+ * Returns the content of this element
+ * @return The content
+ */
+ public ASN1Primitive getExternalContent()
+ {
+ return externalContent;
+ }
+
+ /**
+ * Returns the indirect reference of this element
+ * @return The reference
+ */
+ public ASN1Integer getIndirectReference()
+ {
+ return indirectReference;
+ }
+
+ /**
+ * Sets the data value descriptor
+ * @param dataValueDescriptor The descriptor
+ */
+ private void setDataValueDescriptor(ASN1Primitive dataValueDescriptor)
+ {
+ this.dataValueDescriptor = dataValueDescriptor;
+ }
+
+ /**
+ * Sets the direct reference of the external element
+ * @param directReferemce The reference
+ */
+ private void setDirectReference(ASN1ObjectIdentifier directReferemce)
+ {
+ this.directReference = directReferemce;
+ }
+
+ /**
+ * Sets the encoding of the content. Valid values are
+ *
+ * 0
single-ASN1-type
+ * 1
OCTET STRING
+ * 2
BIT STRING
+ *
+ * @param encoding The encoding
+ */
+ private void setEncoding(int encoding)
+ {
+ if (encoding < 0 || encoding > 2)
+ {
+ throw new IllegalArgumentException("invalid encoding value: " + encoding);
+ }
+ this.encoding = encoding;
+ }
+
+ /**
+ * Sets the content of this element
+ * @param externalContent The content
+ */
+ private void setExternalContent(ASN1Primitive externalContent)
+ {
+ this.externalContent = externalContent;
+ }
+
+ /**
+ * Sets the indirect reference of this element
+ * @param indirectReference The reference
+ */
+ private void setIndirectReference(ASN1Integer indirectReference)
+ {
+ this.indirectReference = indirectReference;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERExternalParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERExternalParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERExternalParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERExternalParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,52 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class DERExternalParser
+ implements ASN1Encodable, InMemoryRepresentable
+{
+ private ASN1StreamParser _parser;
+
+ /**
+ *
+ */
+ public DERExternalParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ try
+ {
+ return new DERExternal(_parser.readVector());
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ASN1Exception(e.getMessage(), e);
+ }
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException ioe)
+ {
+ throw new ASN1ParsingException("unable to get DER object", ioe);
+ }
+ catch (IllegalArgumentException ioe)
+ {
+ throw new ASN1ParsingException("unable to get DER object", ioe);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERFactory.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERFactory.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERFactory.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERFactory.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,17 @@
+package pdftk.org.bouncycastle.asn1;
+
+class DERFactory
+{
+ static final ASN1Sequence EMPTY_SEQUENCE = new DERSequence();
+ static final ASN1Set EMPTY_SET = new DERSet();
+
+ static ASN1Sequence createSequence(ASN1EncodableVector v)
+ {
+ return v.size() < 1 ? EMPTY_SEQUENCE : new DLSequence(v);
+ }
+
+ static ASN1Set createSet(ASN1EncodableVector v)
+ {
+ return v.size() < 1 ? EMPTY_SET : new DLSet(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERGeneralString.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERGeneralString.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERGeneralString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERGeneralString.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,110 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Strings;
+
+public class DERGeneralString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ public static DERGeneralString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERGeneralString)
+ {
+ return (DERGeneralString) obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERGeneralString)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ public static DERGeneralString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERGeneralString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERGeneralString(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ DERGeneralString(byte[] string)
+ {
+ this.string = string;
+ }
+
+ public DERGeneralString(String string)
+ {
+ this.string = Strings.toByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.GENERAL_STRING, string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+
+ boolean asn1Equals(ASN1Primitive o)
+ {
+ if (!(o instanceof DERGeneralString))
+ {
+ return false;
+ }
+ DERGeneralString s = (DERGeneralString)o;
+
+ return Arrays.areEqual(string, s.string);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERGeneralizedTime.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERGeneralizedTime.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERGeneralizedTime.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERGeneralizedTime.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,350 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * Generalized time object.
+ */
+public class DERGeneralizedTime
+ extends ASN1Primitive
+{
+ private byte[] time;
+
+ /**
+ * return a generalized time from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1GeneralizedTime getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1GeneralizedTime)
+ {
+ return (ASN1GeneralizedTime)obj;
+ }
+
+ if (obj instanceof DERGeneralizedTime)
+ {
+ return new ASN1GeneralizedTime(((DERGeneralizedTime)obj).time);
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (ASN1GeneralizedTime)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Generalized Time object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1GeneralizedTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERGeneralizedTime)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1GeneralizedTime(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
+ * for local time, or Z+-HHMM on the end, for difference between local
+ * time and UTC time. The fractional second amount f must consist of at
+ * least one number with trailing zeroes removed.
+ *
+ * @param time the time string.
+ * @exception IllegalArgumentException if String is an illegal format.
+ */
+ public DERGeneralizedTime(
+ String time)
+ {
+ this.time = Strings.toByteArray(time);
+ try
+ {
+ this.getDate();
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException("invalid date string: " + e.getMessage());
+ }
+ }
+
+ /**
+ * base constructor from a java.util.date object
+ */
+ public DERGeneralizedTime(
+ Date time)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ this.time = Strings.toByteArray(dateF.format(time));
+ }
+
+ DERGeneralizedTime(
+ byte[] bytes)
+ {
+ this.time = bytes;
+ }
+
+ /**
+ * Return the time.
+ * @return The time string as it appeared in the encoded object.
+ */
+ public String getTimeString()
+ {
+ return Strings.fromByteArray(time);
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ *
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ *
+ * dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+ *
+ * To read in the time and get a date which is compatible with our local
+ * time zone.
+ */
+ public String getTime()
+ {
+ String stime = Strings.fromByteArray(time);
+
+ //
+ // standardise the format.
+ //
+ if (stime.charAt(stime.length() - 1) == 'Z')
+ {
+ return stime.substring(0, stime.length() - 1) + "GMT+00:00";
+ }
+ else
+ {
+ int signPos = stime.length() - 5;
+ char sign = stime.charAt(signPos);
+ if (sign == '-' || sign == '+')
+ {
+ return stime.substring(0, signPos)
+ + "GMT"
+ + stime.substring(signPos, signPos + 3)
+ + ":"
+ + stime.substring(signPos + 3);
+ }
+ else
+ {
+ signPos = stime.length() - 3;
+ sign = stime.charAt(signPos);
+ if (sign == '-' || sign == '+')
+ {
+ return stime.substring(0, signPos)
+ + "GMT"
+ + stime.substring(signPos)
+ + ":00";
+ }
+ }
+ }
+ return stime + calculateGMTOffset();
+ }
+
+ private String calculateGMTOffset()
+ {
+ String sign = "+";
+ TimeZone timeZone = TimeZone.getDefault();
+ int offset = timeZone.getRawOffset();
+ if (offset < 0)
+ {
+ sign = "-";
+ offset = -offset;
+ }
+ int hours = offset / (60 * 60 * 1000);
+ int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
+
+ try
+ {
+ if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
+ {
+ hours += sign.equals("+") ? 1 : -1;
+ }
+ }
+ catch (ParseException e)
+ {
+ // we'll do our best and ignore daylight savings
+ }
+
+ return "GMT" + sign + convert(hours) + ":" + convert(minutes);
+ }
+
+ private String convert(int time)
+ {
+ if (time < 10)
+ {
+ return "0" + time;
+ }
+
+ return Integer.toString(time);
+ }
+
+ public Date getDate()
+ throws ParseException
+ {
+ SimpleDateFormat dateF;
+ String stime = Strings.fromByteArray(time);
+ String d = stime;
+
+ if (stime.endsWith("Z"))
+ {
+ if (hasFractionalSeconds())
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
+ }
+ else
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+ }
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+ }
+ else if (stime.indexOf('-') > 0 || stime.indexOf('+') > 0)
+ {
+ d = this.getTime();
+ if (hasFractionalSeconds())
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz");
+ }
+ else
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+ }
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+ }
+ else
+ {
+ if (hasFractionalSeconds())
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
+ }
+ else
+ {
+ dateF = new SimpleDateFormat("yyyyMMddHHmmss");
+ }
+
+ dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
+ }
+
+ if (hasFractionalSeconds())
+ {
+ // java misinterprets extra digits as being milliseconds...
+ String frac = d.substring(14);
+ int index;
+ for (index = 1; index < frac.length(); index++)
+ {
+ char ch = frac.charAt(index);
+ if (!('0' <= ch && ch <= '9'))
+ {
+ break;
+ }
+ }
+
+ if (index - 1 > 3)
+ {
+ frac = frac.substring(0, 4) + frac.substring(index);
+ d = d.substring(0, 14) + frac;
+ }
+ else if (index - 1 == 1)
+ {
+ frac = frac.substring(0, index) + "00" + frac.substring(index);
+ d = d.substring(0, 14) + frac;
+ }
+ else if (index - 1 == 2)
+ {
+ frac = frac.substring(0, index) + "0" + frac.substring(index);
+ d = d.substring(0, 14) + frac;
+ }
+ }
+
+ return dateF.parse(d);
+ }
+
+ private boolean hasFractionalSeconds()
+ {
+ for (int i = 0; i != time.length; i++)
+ {
+ if (time[i] == '.')
+ {
+ if (i == 14)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ int length = time.length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.GENERALIZED_TIME, time);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERGeneralizedTime))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(time, ((DERGeneralizedTime)o).time);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(time);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERGenerator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,119 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import pdftk.org.bouncycastle.util.io.Streams;
+
+public abstract class DERGenerator
+ extends ASN1Generator
+{
+ private boolean _tagged = false;
+ private boolean _isExplicit;
+ private int _tagNo;
+
+ protected DERGenerator(
+ OutputStream out)
+ {
+ super(out);
+ }
+
+ public DERGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ {
+ super(out);
+
+ _tagged = true;
+ _isExplicit = isExplicit;
+ _tagNo = tagNo;
+ }
+
+ private void writeLength(
+ OutputStream out,
+ int length)
+ throws IOException
+ {
+ if (length > 127)
+ {
+ int size = 1;
+ int val = length;
+
+ while ((val >>>= 8) != 0)
+ {
+ size++;
+ }
+
+ out.write((byte)(size | 0x80));
+
+ for (int i = (size - 1) * 8; i >= 0; i -= 8)
+ {
+ out.write((byte)(length >> i));
+ }
+ }
+ else
+ {
+ out.write((byte)length);
+ }
+ }
+
+ void writeDEREncoded(
+ OutputStream out,
+ int tag,
+ byte[] bytes)
+ throws IOException
+ {
+ out.write(tag);
+ writeLength(out, bytes.length);
+ out.write(bytes);
+ }
+
+ void writeDEREncoded(
+ int tag,
+ byte[] bytes)
+ throws IOException
+ {
+ if (_tagged)
+ {
+ int tagNum = _tagNo | BERTags.TAGGED;
+
+ if (_isExplicit)
+ {
+ int newTag = _tagNo | BERTags.CONSTRUCTED | BERTags.TAGGED;
+
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ writeDEREncoded(bOut, tag, bytes);
+
+ writeDEREncoded(_out, newTag, bOut.toByteArray());
+ }
+ else
+ {
+ if ((tag & BERTags.CONSTRUCTED) != 0)
+ {
+ writeDEREncoded(_out, tagNum | BERTags.CONSTRUCTED, bytes);
+ }
+ else
+ {
+ writeDEREncoded(_out, tagNum, bytes);
+ }
+ }
+ }
+ else
+ {
+ writeDEREncoded(_out, tag, bytes);
+ }
+ }
+
+ void writeDEREncoded(
+ OutputStream out,
+ int tag,
+ InputStream in)
+ throws IOException
+ {
+ writeDEREncoded(out, tag, Streams.readAll(in));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERIA5String.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERIA5String.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERIA5String.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERIA5String.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,183 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * DER IA5String object - this is an ascii string.
+ */
+public class DERIA5String
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * return a IA5 string from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERIA5String getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERIA5String)
+ {
+ return (DERIA5String)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERIA5String)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an IA5 String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DERIA5String getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERIA5String)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERIA5String(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - with bytes.
+ */
+ DERIA5String(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor - without validation.
+ */
+ public DERIA5String(
+ String string)
+ {
+ this(string, false);
+ }
+
+ /**
+ * Constructor with optional validation.
+ *
+ * @param string the base string to wrap.
+ * @param validate whether or not to check the string.
+ * @throws IllegalArgumentException if validate is true and the string
+ * contains characters that should not be in an IA5String.
+ */
+ public DERIA5String(
+ String string,
+ boolean validate)
+ {
+ if (string == null)
+ {
+ throw new NullPointerException("string cannot be null");
+ }
+ if (validate && !isIA5String(string))
+ {
+ throw new IllegalArgumentException("string contains illegal characters");
+ }
+
+ this.string = Strings.toByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.IA5_STRING, string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERIA5String))
+ {
+ return false;
+ }
+
+ DERIA5String s = (DERIA5String)o;
+
+ return Arrays.areEqual(string, s.string);
+ }
+
+ /**
+ * return true if the passed in String can be represented without
+ * loss as an IA5String, false otherwise.
+ *
+ * @return true if in printable set, false otherwise.
+ */
+ public static boolean isIA5String(
+ String str)
+ {
+ for (int i = str.length() - 1; i >= 0; i--)
+ {
+ char ch = str.charAt(i);
+
+ if (ch > 0x007f)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERInteger.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERInteger.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERInteger.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERInteger.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,148 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class DERInteger
+ extends ASN1Primitive
+{
+ byte[] bytes;
+
+ /**
+ * return an integer from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1Integer getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1Integer)
+ {
+ return (ASN1Integer)obj;
+ }
+ if (obj instanceof DERInteger)
+ {
+ return new ASN1Integer((((DERInteger)obj).getValue()));
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (ASN1Integer)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Integer from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1Integer getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERInteger)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1Integer(ASN1OctetString.getInstance(obj.getObject()).getOctets());
+ }
+ }
+
+ public DERInteger(
+ long value)
+ {
+ bytes = BigInteger.valueOf(value).toByteArray();
+ }
+
+ public DERInteger(
+ BigInteger value)
+ {
+ bytes = value.toByteArray();
+ }
+
+ public DERInteger(
+ byte[] bytes)
+ {
+ this.bytes = bytes;
+ }
+
+ public BigInteger getValue()
+ {
+ return new BigInteger(bytes);
+ }
+
+ /**
+ * in some cases positive values get crammed into a space,
+ * that's not quite big enough...
+ */
+ public BigInteger getPositiveValue()
+ {
+ return new BigInteger(1, bytes);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(bytes.length) + bytes.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.INTEGER, bytes);
+ }
+
+ public int hashCode()
+ {
+ int value = 0;
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ value ^= (bytes[i] & 0xff) << (i % 4);
+ }
+
+ return value;
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERInteger))
+ {
+ return false;
+ }
+
+ DERInteger other = (DERInteger)o;
+
+ return Arrays.areEqual(bytes, other.bytes);
+ }
+
+ public String toString()
+ {
+ return getValue().toString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERNull.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERNull.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERNull.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERNull.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,38 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * A NULL object.
+ */
+public class DERNull
+ extends ASN1Null
+{
+ public static final DERNull INSTANCE = new DERNull();
+
+ private static final byte[] zeroBytes = new byte[0];
+
+ /**
+ * @deprecated use DERNull.INSTANCE
+ */
+ public DERNull()
+ {
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 2;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.NULL, zeroBytes);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERNumericString.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERNumericString.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERNumericString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERNumericString.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,186 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
+ */
+public class DERNumericString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * return a Numeric string from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERNumericString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERNumericString)
+ {
+ return (DERNumericString)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERNumericString)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Numeric String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DERNumericString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERNumericString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERNumericString(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - with bytes.
+ */
+ DERNumericString(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor - without validation..
+ */
+ public DERNumericString(
+ String string)
+ {
+ this(string, false);
+ }
+
+ /**
+ * Constructor with optional validation.
+ *
+ * @param string the base string to wrap.
+ * @param validate whether or not to check the string.
+ * @throws IllegalArgumentException if validate is true and the string
+ * contains characters that should not be in a NumericString.
+ */
+ public DERNumericString(
+ String string,
+ boolean validate)
+ {
+ if (validate && !isNumericString(string))
+ {
+ throw new IllegalArgumentException("string contains illegal characters");
+ }
+
+ this.string = Strings.toByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.NUMERIC_STRING, string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERNumericString))
+ {
+ return false;
+ }
+
+ DERNumericString s = (DERNumericString)o;
+
+ return Arrays.areEqual(string, s.string);
+ }
+
+ /**
+ * Return true if the string can be represented as a NumericString ('0'..'9', ' ')
+ *
+ * @param str string to validate.
+ * @return true if numeric, fale otherwise.
+ */
+ public static boolean isNumericString(
+ String str)
+ {
+ for (int i = str.length() - 1; i >= 0; i--)
+ {
+ char ch = str.charAt(i);
+
+ if (ch > 0x007f)
+ {
+ return false;
+ }
+
+ if (('0' <= ch && ch <= '9') || ch == ' ')
+ {
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERObjectIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERObjectIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERObjectIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERObjectIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,404 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class DERObjectIdentifier
+ extends ASN1Primitive
+{
+ String identifier;
+
+ private byte[] body;
+
+ /**
+ * return an OID from the passed in object
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1ObjectIdentifier getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1ObjectIdentifier)
+ {
+ return (ASN1ObjectIdentifier)obj;
+ }
+
+ if (obj instanceof DERObjectIdentifier)
+ {
+ return new ASN1ObjectIdentifier(((DERObjectIdentifier)obj).getId());
+ }
+
+ if (obj instanceof ASN1Encodable && ((ASN1Encodable)obj).toASN1Primitive() instanceof ASN1ObjectIdentifier)
+ {
+ return (ASN1ObjectIdentifier)((ASN1Encodable)obj).toASN1Primitive();
+ }
+
+ if (obj instanceof byte[])
+ {
+ return ASN1ObjectIdentifier.fromOctetString((byte[])obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an Object Identifier from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1ObjectIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERObjectIdentifier)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return ASN1ObjectIdentifier.fromOctetString(ASN1OctetString.getInstance(obj.getObject()).getOctets());
+ }
+ }
+
+ private static final long LONG_LIMIT = (Long.MAX_VALUE >> 7) - 0x7f;
+
+ DERObjectIdentifier(
+ byte[] bytes)
+ {
+ StringBuffer objId = new StringBuffer();
+ long value = 0;
+ BigInteger bigValue = null;
+ boolean first = true;
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ int b = bytes[i] & 0xff;
+
+ if (value <= LONG_LIMIT)
+ {
+ value += (b & 0x7f);
+ if ((b & 0x80) == 0) // end of number reached
+ {
+ if (first)
+ {
+ if (value < 40)
+ {
+ objId.append('0');
+ }
+ else if (value < 80)
+ {
+ objId.append('1');
+ value -= 40;
+ }
+ else
+ {
+ objId.append('2');
+ value -= 80;
+ }
+ first = false;
+ }
+
+ objId.append('.');
+ objId.append(value);
+ value = 0;
+ }
+ else
+ {
+ value <<= 7;
+ }
+ }
+ else
+ {
+ if (bigValue == null)
+ {
+ bigValue = BigInteger.valueOf(value);
+ }
+ bigValue = bigValue.or(BigInteger.valueOf(b & 0x7f));
+ if ((b & 0x80) == 0)
+ {
+ if (first)
+ {
+ objId.append('2');
+ bigValue = bigValue.subtract(BigInteger.valueOf(80));
+ first = false;
+ }
+
+ objId.append('.');
+ objId.append(bigValue);
+ bigValue = null;
+ value = 0;
+ }
+ else
+ {
+ bigValue = bigValue.shiftLeft(7);
+ }
+ }
+ }
+
+ this.identifier = objId.toString();
+ this.body = Arrays.clone(bytes);
+ }
+
+ public DERObjectIdentifier(
+ String identifier)
+ {
+ if (!isValidIdentifier(identifier))
+ {
+ throw new IllegalArgumentException("string " + identifier + " not an OID");
+ }
+
+ this.identifier = identifier;
+ }
+
+ public String getId()
+ {
+ return identifier;
+ }
+
+ private void writeField(
+ ByteArrayOutputStream out,
+ long fieldValue)
+ {
+ byte[] result = new byte[9];
+ int pos = 8;
+ result[pos] = (byte)((int)fieldValue & 0x7f);
+ while (fieldValue >= (1L << 7))
+ {
+ fieldValue >>= 7;
+ result[--pos] = (byte)((int)fieldValue & 0x7f | 0x80);
+ }
+ out.write(result, pos, 9 - pos);
+ }
+
+ private void writeField(
+ ByteArrayOutputStream out,
+ BigInteger fieldValue)
+ {
+ int byteCount = (fieldValue.bitLength()+6)/7;
+ if (byteCount == 0)
+ {
+ out.write(0);
+ }
+ else
+ {
+ BigInteger tmpValue = fieldValue;
+ byte[] tmp = new byte[byteCount];
+ for (int i = byteCount-1; i >= 0; i--)
+ {
+ tmp[i] = (byte) ((tmpValue.intValue() & 0x7f) | 0x80);
+ tmpValue = tmpValue.shiftRight(7);
+ }
+ tmp[byteCount-1] &= 0x7f;
+ out.write(tmp, 0, tmp.length);
+ }
+ }
+
+ private void doOutput(ByteArrayOutputStream aOut)
+ {
+ OIDTokenizer tok = new OIDTokenizer(identifier);
+ int first = Integer.parseInt(tok.nextToken()) * 40;
+
+ String secondToken = tok.nextToken();
+ if (secondToken.length() <= 18)
+ {
+ writeField(aOut, first + Long.parseLong(secondToken));
+ }
+ else
+ {
+ writeField(aOut, new BigInteger(secondToken).add(BigInteger.valueOf(first)));
+ }
+
+ while (tok.hasMoreTokens())
+ {
+ String token = tok.nextToken();
+ if (token.length() <= 18)
+ {
+ writeField(aOut, Long.parseLong(token));
+ }
+ else
+ {
+ writeField(aOut, new BigInteger(token));
+ }
+ }
+ }
+
+ protected synchronized byte[] getBody()
+ {
+ if (body == null)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ doOutput(bOut);
+
+ body = bOut.toByteArray();
+ }
+
+ return body;
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = getBody().length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ byte[] enc = getBody();
+
+ out.write(BERTags.OBJECT_IDENTIFIER);
+ out.writeLength(enc.length);
+ out.write(enc);
+ }
+
+ public int hashCode()
+ {
+ return identifier.hashCode();
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERObjectIdentifier))
+ {
+ return false;
+ }
+
+ return identifier.equals(((DERObjectIdentifier)o).identifier);
+ }
+
+ public String toString()
+ {
+ return getId();
+ }
+
+ private static boolean isValidIdentifier(
+ String identifier)
+ {
+ if (identifier.length() < 3
+ || identifier.charAt(1) != '.')
+ {
+ return false;
+ }
+
+ char first = identifier.charAt(0);
+ if (first < '0' || first > '2')
+ {
+ return false;
+ }
+
+ boolean periodAllowed = false;
+ for (int i = identifier.length() - 1; i >= 2; i--)
+ {
+ char ch = identifier.charAt(i);
+
+ // TODO Leading zeroes?
+ if ('0' <= ch && ch <= '9')
+ {
+ periodAllowed = true;
+ continue;
+ }
+
+ if (ch == '.')
+ {
+ if (!periodAllowed)
+ {
+ return false;
+ }
+
+ periodAllowed = false;
+ continue;
+ }
+
+ return false;
+ }
+
+ return periodAllowed;
+ }
+
+ private static ASN1ObjectIdentifier[][] cache = new ASN1ObjectIdentifier[256][];
+
+ static ASN1ObjectIdentifier fromOctetString(byte[] enc)
+ {
+ if (enc.length < 3)
+ {
+ return new ASN1ObjectIdentifier(enc);
+ }
+
+ int idx1 = enc[enc.length - 2] & 0xff;
+ // in this case top bit is always zero
+ int idx2 = enc[enc.length - 1] & 0x7f;
+
+ ASN1ObjectIdentifier possibleMatch;
+
+ synchronized (cache)
+ {
+ ASN1ObjectIdentifier[] first = cache[idx1];
+ if (first == null)
+ {
+ first = cache[idx1] = new ASN1ObjectIdentifier[128];
+ }
+
+ possibleMatch = first[idx2];
+ if (possibleMatch == null)
+ {
+ return first[idx2] = new ASN1ObjectIdentifier(enc);
+ }
+
+ if (Arrays.areEqual(enc, possibleMatch.getBody()))
+ {
+ return possibleMatch;
+ }
+
+ idx1 = (idx1 + 1) & 0xff;
+ first = cache[idx1];
+ if (first == null)
+ {
+ first = cache[idx1] = new ASN1ObjectIdentifier[128];
+ }
+
+ possibleMatch = first[idx2];
+ if (possibleMatch == null)
+ {
+ return first[idx2] = new ASN1ObjectIdentifier(enc);
+ }
+
+ if (Arrays.areEqual(enc, possibleMatch.getBody()))
+ {
+ return possibleMatch;
+ }
+
+ idx2 = (idx2 + 1) & 0x7f;
+ possibleMatch = first[idx2];
+ if (possibleMatch == null)
+ {
+ return first[idx2] = new ASN1ObjectIdentifier(enc);
+ }
+ }
+
+ if (Arrays.areEqual(enc, possibleMatch.getBody()))
+ {
+ return possibleMatch;
+ }
+
+ return new ASN1ObjectIdentifier(enc);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DEROctetString.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DEROctetString.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DEROctetString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DEROctetString.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class DEROctetString
+ extends ASN1OctetString
+{
+ /**
+ * @param string the octets making up the octet string.
+ */
+ public DEROctetString(
+ byte[] string)
+ {
+ super(string);
+ }
+
+ public DEROctetString(
+ ASN1Encodable obj)
+ throws IOException
+ {
+ super(obj.toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.OCTET_STRING, string);
+ }
+
+ static void encode(
+ DEROutputStream derOut,
+ byte[] bytes)
+ throws IOException
+ {
+ derOut.writeEncoded(BERTags.OCTET_STRING, bytes);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DEROctetStringParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DEROctetStringParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DEROctetStringParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DEROctetStringParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,39 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class DEROctetStringParser
+ implements ASN1OctetStringParser
+{
+ private DefiniteLengthInputStream stream;
+
+ DEROctetStringParser(
+ DefiniteLengthInputStream stream)
+ {
+ this.stream = stream;
+ }
+
+ public InputStream getOctetStream()
+ {
+ return stream;
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new DEROctetString(stream.toByteArray());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("IOException converting stream to byte array: " + e.getMessage(), e);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DEROutputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DEROutputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DEROutputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DEROutputStream.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,41 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Stream that outputs encoding based on distinguished encoding rules.
+ */
+public class DEROutputStream
+ extends ASN1OutputStream
+{
+ public DEROutputStream(
+ OutputStream os)
+ {
+ super(os);
+ }
+
+ public void writeObject(
+ ASN1Encodable obj)
+ throws IOException
+ {
+ if (obj != null)
+ {
+ obj.toASN1Primitive().toDERObject().encode(this);
+ }
+ else
+ {
+ throw new IOException("null object detected");
+ }
+ }
+
+ ASN1OutputStream getDERSubStream()
+ {
+ return this;
+ }
+
+ ASN1OutputStream getDLSubStream()
+ {
+ return this;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERPrintableString.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERPrintableString.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERPrintableString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERPrintableString.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,213 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * DER PrintableString object.
+ */
+public class DERPrintableString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * return a printable string from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERPrintableString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERPrintableString)
+ {
+ return (DERPrintableString)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERPrintableString)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Printable String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DERPrintableString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERPrintableString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERPrintableString(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ DERPrintableString(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor - this does not validate the string
+ */
+ public DERPrintableString(
+ String string)
+ {
+ this(string, false);
+ }
+
+ /**
+ * Constructor with optional validation.
+ *
+ * @param string the base string to wrap.
+ * @param validate whether or not to check the string.
+ * @throws IllegalArgumentException if validate is true and the string
+ * contains characters that should not be in a PrintableString.
+ */
+ public DERPrintableString(
+ String string,
+ boolean validate)
+ {
+ if (validate && !isPrintableString(string))
+ {
+ throw new IllegalArgumentException("string contains illegal characters");
+ }
+
+ this.string = Strings.toByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromByteArray(string);
+ }
+
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.PRINTABLE_STRING, string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERPrintableString))
+ {
+ return false;
+ }
+
+ DERPrintableString s = (DERPrintableString)o;
+
+ return Arrays.areEqual(string, s.string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ /**
+ * return true if the passed in String can be represented without
+ * loss as a PrintableString, false otherwise.
+ *
+ * @return true if in printable set, false otherwise.
+ */
+ public static boolean isPrintableString(
+ String str)
+ {
+ for (int i = str.length() - 1; i >= 0; i--)
+ {
+ char ch = str.charAt(i);
+
+ if (ch > 0x007f)
+ {
+ return false;
+ }
+
+ if ('a' <= ch && ch <= 'z')
+ {
+ continue;
+ }
+
+ if ('A' <= ch && ch <= 'Z')
+ {
+ continue;
+ }
+
+ if ('0' <= ch && ch <= '9')
+ {
+ continue;
+ }
+
+ switch (ch)
+ {
+ case ' ':
+ case '\'':
+ case '(':
+ case ')':
+ case '+':
+ case '-':
+ case '.':
+ case ':':
+ case '=':
+ case '?':
+ case '/':
+ case ',':
+ continue;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERSequence.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERSequence.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERSequence.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERSequence.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,98 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class DERSequence
+ extends ASN1Sequence
+{
+ private int bodyLength = -1;
+
+ /**
+ * create an empty sequence
+ */
+ public DERSequence()
+ {
+ }
+
+ /**
+ * create a sequence containing one object
+ */
+ public DERSequence(
+ ASN1Encodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ public DERSequence(
+ ASN1EncodableVector v)
+ {
+ super(v);
+ }
+
+ /**
+ * create a sequence containing an array of objects.
+ */
+ public DERSequence(
+ ASN1Encodable[] array)
+ {
+ super(array);
+ }
+
+ private int getBodyLength()
+ throws IOException
+ {
+ if (bodyLength < 0)
+ {
+ int length = 0;
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ length += ((ASN1Encodable)obj).toASN1Primitive().toDERObject().encodedLength();
+ }
+
+ bodyLength = length;
+ }
+
+ return bodyLength;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = getBodyLength();
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ /*
+ * A note on the implementation:
+ *
+ * As DER requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputting SEQUENCE,
+ * we also have to specify CONSTRUCTED, and the objects length.
+ */
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ ASN1OutputStream dOut = out.getDERSubStream();
+ int length = getBodyLength();
+
+ out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED);
+ out.writeLength(length);
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ dOut.writeObject((ASN1Encodable)obj);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERSequenceGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERSequenceGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERSequenceGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERSequenceGenerator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,45 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class DERSequenceGenerator
+ extends DERGenerator
+{
+ private final ByteArrayOutputStream _bOut = new ByteArrayOutputStream();
+
+ public DERSequenceGenerator(
+ OutputStream out)
+ throws IOException
+ {
+ super(out);
+ }
+
+ public DERSequenceGenerator(
+ OutputStream out,
+ int tagNo,
+ boolean isExplicit)
+ throws IOException
+ {
+ super(out, tagNo, isExplicit);
+ }
+
+ public void addObject(
+ ASN1Encodable object)
+ throws IOException
+ {
+ object.toASN1Primitive().encode(new DEROutputStream(_bOut));
+ }
+
+ public OutputStream getRawOutputStream()
+ {
+ return _bOut;
+ }
+
+ public void close()
+ throws IOException
+ {
+ writeDEREncoded(BERTags.CONSTRUCTED | BERTags.SEQUENCE, _bOut.toByteArray());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERSequenceParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERSequenceParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERSequenceParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERSequenceParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,38 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class DERSequenceParser
+ implements ASN1SequenceParser
+{
+ private ASN1StreamParser _parser;
+
+ DERSequenceParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new DERSequence(_parser.readVector());
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERSet.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERSet.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERSet.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERSet.java 2013-04-22 11:44:26.000000000 +0000
@@ -0,0 +1,116 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * A DER encoded set object
+ */
+public class DERSet
+ extends ASN1Set
+{
+ private int bodyLength = -1;
+
+ /**
+ * create an empty set
+ */
+ public DERSet()
+ {
+ }
+
+ /**
+ * @param obj - a single object that makes up the set.
+ */
+ public DERSet(
+ ASN1Encodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * @param v - a vector of objects making up the set.
+ */
+ public DERSet(
+ ASN1EncodableVector v)
+ {
+ super(v, true);
+ }
+
+ /**
+ * create a set from an array of objects.
+ */
+ public DERSet(
+ ASN1Encodable[] a)
+ {
+ super(a, true);
+ }
+
+ DERSet(
+ ASN1EncodableVector v,
+ boolean doSort)
+ {
+ super(v, doSort);
+ }
+
+ private int getBodyLength()
+ throws IOException
+ {
+ if (bodyLength < 0)
+ {
+ int length = 0;
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ length += ((ASN1Encodable)obj).toASN1Primitive().toDERObject().encodedLength();
+ }
+
+ bodyLength = length;
+ }
+
+ return bodyLength;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = getBodyLength();
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ //sid: copied from bc 1.45; we use it while creating a DERSet in PdfPKCS7.java,
+ // and this is consistent with ASN1Set( ASN1Encodable[], boolean )
+ public void addObject(
+ ASN1Encodable obj)
+ {
+ super.addObject(obj);
+ }
+
+ /*
+ * A note on the implementation:
+ *
+ * As DER requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputting SET,
+ * we also have to specify CONSTRUCTED, and the objects length.
+ */
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ ASN1OutputStream dOut = out.getDERSubStream();
+ int length = getBodyLength();
+
+ out.write(BERTags.SET | BERTags.CONSTRUCTED);
+ out.writeLength(length);
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ dOut.writeObject((ASN1Encodable)obj);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERSetParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERSetParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERSetParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERSetParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,38 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public class DERSetParser
+ implements ASN1SetParser
+{
+ private ASN1StreamParser _parser;
+
+ DERSetParser(ASN1StreamParser parser)
+ {
+ this._parser = parser;
+ }
+
+ public ASN1Encodable readObject()
+ throws IOException
+ {
+ return _parser.readObject();
+ }
+
+ public ASN1Primitive getLoadedObject()
+ throws IOException
+ {
+ return new DERSet(_parser.readVector(), false);
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ return getLoadedObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException(e.getMessage(), e);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERT61String.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERT61String.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERT61String.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERT61String.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,135 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * DER T61String (also the teletex string)
+ */
+public class DERT61String
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * return a T61 string from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERT61String getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERT61String)
+ {
+ return (DERT61String)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERT61String)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an T61 String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DERT61String getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERT61String)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERT61String(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - with bytes.
+ */
+ DERT61String(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor - with string.
+ */
+ public DERT61String(
+ String string)
+ {
+ this.string = Strings.toUTF8ByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromUTF8ByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.T61_STRING, string);
+ }
+
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERT61String))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(string, ((DERT61String)o).string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERTaggedObject.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERTaggedObject.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERTaggedObject.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERTaggedObject.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,118 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * DER TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+public class DERTaggedObject
+ extends ASN1TaggedObject
+{
+ private static final byte[] ZERO_BYTES = new byte[0];
+
+ /**
+ * @param explicit true if an explicitly tagged object.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public DERTaggedObject(
+ boolean explicit,
+ int tagNo,
+ ASN1Encodable obj)
+ {
+ super(explicit, tagNo, obj);
+ }
+
+ public DERTaggedObject(int tagNo, ASN1Encodable encodable)
+ {
+ super(true, tagNo, encodable);
+ }
+
+ boolean isConstructed()
+ {
+ if (!empty)
+ {
+ if (explicit)
+ {
+ return true;
+ }
+ else
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
+
+ return primitive.isConstructed();
+ }
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ if (!empty)
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
+ int length = primitive.encodedLength();
+
+ if (explicit)
+ {
+ return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
+ }
+ else
+ {
+ // header length already in calculation
+ length = length - 1;
+
+ return StreamUtil.calculateTagLength(tagNo) + length;
+ }
+ }
+ else
+ {
+ return StreamUtil.calculateTagLength(tagNo) + 1;
+ }
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ if (!empty)
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
+
+ if (explicit)
+ {
+ out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
+ out.writeLength(primitive.encodedLength());
+ out.writeObject(primitive);
+ }
+ else
+ {
+ //
+ // need to mark constructed types...
+ //
+ int flags;
+ if (primitive.isConstructed())
+ {
+ flags = BERTags.CONSTRUCTED | BERTags.TAGGED;
+ }
+ else
+ {
+ flags = BERTags.TAGGED;
+ }
+
+ out.writeTag(flags, tagNo);
+ out.writeImplicitObject(primitive);
+ }
+ }
+ else
+ {
+ out.writeEncoded(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo, ZERO_BYTES);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERTags.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERTags.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERTags.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERTags.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,9 @@
+package pdftk.org.bouncycastle.asn1;
+
+/**
+ * @deprecated use BERTags
+ */
+public interface DERTags
+ extends BERTags
+{
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERUTCTime.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERUTCTime.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERUTCTime.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERUTCTime.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,278 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.SimpleTimeZone;
+
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * UTC time object.
+ */
+public class DERUTCTime
+ extends ASN1Primitive
+{
+ private byte[] time;
+
+ /**
+ * return an UTC Time from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static ASN1UTCTime getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ASN1UTCTime)
+ {
+ return (ASN1UTCTime)obj;
+ }
+
+ if (obj instanceof DERUTCTime)
+ {
+ return new ASN1UTCTime(((DERUTCTime)obj).time);
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (ASN1UTCTime)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return an UTC Time from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static ASN1UTCTime getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Object o = obj.getObject();
+
+ if (explicit || o instanceof ASN1UTCTime)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new ASN1UTCTime(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
+ * never encoded. When you're creating one of these objects from scratch, that's
+ * what you want to use, otherwise we'll try to deal with whatever gets read from
+ * the input stream... (this is why the input format is different from the getTime()
+ * method output).
+ *
+ *
+ * @param time the time string.
+ */
+ public DERUTCTime(
+ String time)
+ {
+ this.time = Strings.toByteArray(time);
+ try
+ {
+ this.getDate();
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException("invalid date string: " + e.getMessage());
+ }
+ }
+
+ /**
+ * base constructer from a java.util.date object
+ */
+ public DERUTCTime(
+ Date time)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'");
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ this.time = Strings.toByteArray(dateF.format(time));
+ }
+
+ DERUTCTime(
+ byte[] time)
+ {
+ this.time = time;
+ }
+
+ /**
+ * return the time as a date based on whatever a 2 digit year will return. For
+ * standardised processing use getAdjustedDate().
+ *
+ * @return the resulting date
+ * @exception ParseException if the date string cannot be parsed.
+ */
+ public Date getDate()
+ throws ParseException
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz");
+
+ return dateF.parse(getTime());
+ }
+
+ /**
+ * return the time as an adjusted date
+ * in the range of 1950 - 2049.
+ *
+ * @return a date in the range of 1950 to 2049.
+ * @exception ParseException if the date string cannot be parsed.
+ */
+ public Date getAdjustedDate()
+ throws ParseException
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+
+ dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
+
+ return dateF.parse(getAdjustedTime());
+ }
+
+ /**
+ * return the time - always in the form of
+ * YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+ *
+ * Normally in a certificate we would expect "Z" rather than "GMT",
+ * however adding the "GMT" means we can just use:
+ *
+ * dateF = new SimpleDateFormat("yyMMddHHmmssz");
+ *
+ * To read in the time and get a date which is compatible with our local
+ * time zone.
+ *
+ * Note: In some cases, due to the local date processing, this
+ * may lead to unexpected results. If you want to stick the normal
+ * convention of 1950 to 2049 use the getAdjustedTime() method.
+ */
+ public String getTime()
+ {
+ String stime = Strings.fromByteArray(time);
+
+ //
+ // standardise the format.
+ //
+ if (stime.indexOf('-') < 0 && stime.indexOf('+') < 0)
+ {
+ if (stime.length() == 11)
+ {
+ return stime.substring(0, 10) + "00GMT+00:00";
+ }
+ else
+ {
+ return stime.substring(0, 12) + "GMT+00:00";
+ }
+ }
+ else
+ {
+ int index = stime.indexOf('-');
+ if (index < 0)
+ {
+ index = stime.indexOf('+');
+ }
+ String d = stime;
+
+ if (index == stime.length() - 3)
+ {
+ d += "00";
+ }
+
+ if (index == 10)
+ {
+ return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
+ }
+ else
+ {
+ return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
+ }
+ }
+ }
+
+ /**
+ * return a time string as an adjusted date with a 4 digit year. This goes
+ * in the range of 1950 - 2049.
+ */
+ public String getAdjustedTime()
+ {
+ String d = this.getTime();
+
+ if (d.charAt(0) < '5')
+ {
+ return "20" + d;
+ }
+ else
+ {
+ return "19" + d;
+ }
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ int length = time.length;
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.write(BERTags.UTC_TIME);
+
+ int length = time.length;
+
+ out.writeLength(length);
+
+ for (int i = 0; i != length; i++)
+ {
+ out.write((byte)time[i]);
+ }
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERUTCTime))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(time, ((DERUTCTime)o).time);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(time);
+ }
+
+ public String toString()
+ {
+ return Strings.fromByteArray(time);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERUTF8String.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERUTF8String.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERUTF8String.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERUTF8String.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,132 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * DER UTF8String object.
+ */
+public class DERUTF8String
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * return an UTF8 string from the passed in object.
+ *
+ * @exception IllegalArgumentException
+ * if the object cannot be converted.
+ */
+ public static DERUTF8String getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DERUTF8String)
+ {
+ return (DERUTF8String)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERUTF8String)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * return an UTF8 String from a tagged object.
+ *
+ * @param obj
+ * the tagged object holding the object we want
+ * @param explicit
+ * true if the object is meant to be explicitly tagged false
+ * otherwise.
+ * @exception IllegalArgumentException
+ * if the tagged object cannot be converted.
+ */
+ public static DERUTF8String getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERUTF8String)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERUTF8String(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ DERUTF8String(byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor
+ */
+ public DERUTF8String(String string)
+ {
+ this.string = Strings.toUTF8ByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromUTF8ByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+
+ boolean asn1Equals(ASN1Primitive o)
+ {
+ if (!(o instanceof DERUTF8String))
+ {
+ return false;
+ }
+
+ DERUTF8String s = (DERUTF8String)o;
+
+ return Arrays.areEqual(string, s.string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.UTF8_STRING, string);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERUniversalString.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERUniversalString.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERUniversalString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERUniversalString.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,148 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * DER UniversalString object.
+ */
+public class DERUniversalString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private static final char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ private byte[] string;
+
+ /**
+ * return a Universal String from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERUniversalString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERUniversalString)
+ {
+ return (DERUniversalString)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERUniversalString)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Universal String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DERUniversalString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERUniversalString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERUniversalString(((ASN1OctetString)o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ public DERUniversalString(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ public String getString()
+ {
+ StringBuffer buf = new StringBuffer("#");
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+ ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+
+ try
+ {
+ aOut.writeObject(this);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("internal error encoding BitString");
+ }
+
+ byte[] string = bOut.toByteArray();
+
+ for (int i = 0; i != string.length; i++)
+ {
+ buf.append(table[(string[i] >>> 4) & 0xf]);
+ buf.append(table[string[i] & 0xf]);
+ }
+
+ return buf.toString();
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public byte[] getOctets()
+ {
+ return string;
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.UNIVERSAL_STRING, this.getOctets());
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERUniversalString))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(string, ((DERUniversalString)o).string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERVisibleString.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERVisibleString.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DERVisibleString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DERVisibleString.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,135 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * DER VisibleString object.
+ */
+public class DERVisibleString
+ extends ASN1Primitive
+ implements ASN1String
+{
+ private byte[] string;
+
+ /**
+ * return a Visible String from the passed in object.
+ *
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DERVisibleString getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DERVisibleString)
+ {
+ return (DERVisibleString)obj;
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return (DERVisibleString)fromByteArray((byte[])obj);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalArgumentException("encoding error in getInstance: " + e.toString());
+ }
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * return a Visible String from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the tagged object cannot
+ * be converted.
+ */
+ public static DERVisibleString getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ ASN1Primitive o = obj.getObject();
+
+ if (explicit || o instanceof DERVisibleString)
+ {
+ return getInstance(o);
+ }
+ else
+ {
+ return new DERVisibleString(ASN1OctetString.getInstance(o).getOctets());
+ }
+ }
+
+ /**
+ * basic constructor - byte encoded string.
+ */
+ DERVisibleString(
+ byte[] string)
+ {
+ this.string = string;
+ }
+
+ /**
+ * basic constructor
+ */
+ public DERVisibleString(
+ String string)
+ {
+ this.string = Strings.toByteArray(string);
+ }
+
+ public String getString()
+ {
+ return Strings.fromByteArray(string);
+ }
+
+ public String toString()
+ {
+ return getString();
+ }
+
+ public byte[] getOctets()
+ {
+ return Arrays.clone(string);
+ }
+
+ boolean isConstructed()
+ {
+ return false;
+ }
+
+ int encodedLength()
+ {
+ return 1 + StreamUtil.calculateBodyLength(string.length) + string.length;
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ out.writeEncoded(BERTags.VISIBLE_STRING, this.string);
+ }
+
+ boolean asn1Equals(
+ ASN1Primitive o)
+ {
+ if (!(o instanceof DERVisibleString))
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(string, ((DERVisibleString)o).string);
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(string);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DLOutputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DLOutputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DLOutputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DLOutputStream.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,31 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Stream that outputs encoding based on definite length.
+ */
+public class DLOutputStream
+ extends ASN1OutputStream
+{
+ public DLOutputStream(
+ OutputStream os)
+ {
+ super(os);
+ }
+
+ public void writeObject(
+ ASN1Encodable obj)
+ throws IOException
+ {
+ if (obj != null)
+ {
+ obj.toASN1Primitive().toDLObject().encode(this);
+ }
+ else
+ {
+ throw new IOException("null object detected");
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DLSequence.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DLSequence.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DLSequence.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DLSequence.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,98 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+public class DLSequence
+ extends ASN1Sequence
+{
+ private int bodyLength = -1;
+
+ /**
+ * create an empty sequence
+ */
+ public DLSequence()
+ {
+ }
+
+ /**
+ * create a sequence containing one object
+ */
+ public DLSequence(
+ ASN1Encodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * create a sequence containing a vector of objects.
+ */
+ public DLSequence(
+ ASN1EncodableVector v)
+ {
+ super(v);
+ }
+
+ /**
+ * create a sequence containing an array of objects.
+ */
+ public DLSequence(
+ ASN1Encodable[] array)
+ {
+ super(array);
+ }
+
+ private int getBodyLength()
+ throws IOException
+ {
+ if (bodyLength < 0)
+ {
+ int length = 0;
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ length += ((ASN1Encodable)obj).toASN1Primitive().toDLObject().encodedLength();
+ }
+
+ bodyLength = length;
+ }
+
+ return bodyLength;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = getBodyLength();
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ /*
+ * A note on the implementation:
+ *
+ * As DL requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputting SEQUENCE,
+ * we also have to specify CONSTRUCTED, and the objects length.
+ */
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ ASN1OutputStream dOut = out.getDLSubStream();
+ int length = getBodyLength();
+
+ out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED);
+ out.writeLength(length);
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ dOut.writeObject((ASN1Encodable)obj);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DLSet.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DLSet.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DLSet.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DLSet.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,101 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * A DER encoded set object
+ */
+public class DLSet
+ extends ASN1Set
+{
+ private int bodyLength = -1;
+
+ /**
+ * create an empty set
+ */
+ public DLSet()
+ {
+ }
+
+ /**
+ * @param obj - a single object that makes up the set.
+ */
+ public DLSet(
+ ASN1Encodable obj)
+ {
+ super(obj);
+ }
+
+ /**
+ * @param v - a vector of objects making up the set.
+ */
+ public DLSet(
+ ASN1EncodableVector v)
+ {
+ super(v, false);
+ }
+
+ /**
+ * create a set from an array of objects.
+ */
+ public DLSet(
+ ASN1Encodable[] a)
+ {
+ super(a, false);
+ }
+
+ private int getBodyLength()
+ throws IOException
+ {
+ if (bodyLength < 0)
+ {
+ int length = 0;
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ length += ((ASN1Encodable)obj).toASN1Primitive().toDLObject().encodedLength();
+ }
+
+ bodyLength = length;
+ }
+
+ return bodyLength;
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ int length = getBodyLength();
+
+ return 1 + StreamUtil.calculateBodyLength(length) + length;
+ }
+
+ /*
+ * A note on the implementation:
+ *
+ * As DL requires the constructed, definite-length model to
+ * be used for structured types, this varies slightly from the
+ * ASN.1 descriptions given. Rather than just outputting SET,
+ * we also have to specify CONSTRUCTED, and the objects length.
+ */
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ ASN1OutputStream dOut = out.getDLSubStream();
+ int length = getBodyLength();
+
+ out.write(BERTags.SET | BERTags.CONSTRUCTED);
+ out.writeLength(length);
+
+ for (Enumeration e = this.getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ dOut.writeObject((ASN1Encodable)obj);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DLTaggedObject.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DLTaggedObject.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DLTaggedObject.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DLTaggedObject.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,112 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+/**
+ * Definite Length TaggedObject - in ASN.1 notation this is any object preceded by
+ * a [n] where n is some number - these are assumed to follow the construction
+ * rules (as with sequences).
+ */
+public class DLTaggedObject
+ extends ASN1TaggedObject
+{
+ private static final byte[] ZERO_BYTES = new byte[0];
+
+ /**
+ * @param explicit true if an explicitly tagged object.
+ * @param tagNo the tag number for this object.
+ * @param obj the tagged object.
+ */
+ public DLTaggedObject(
+ boolean explicit,
+ int tagNo,
+ ASN1Encodable obj)
+ {
+ super(explicit, tagNo, obj);
+ }
+
+ boolean isConstructed()
+ {
+ if (!empty)
+ {
+ if (explicit)
+ {
+ return true;
+ }
+ else
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive().toDLObject();
+
+ return primitive.isConstructed();
+ }
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ if (!empty)
+ {
+ int length = obj.toASN1Primitive().toDLObject().encodedLength();
+
+ if (explicit)
+ {
+ return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
+ }
+ else
+ {
+ // header length already in calculation
+ length = length - 1;
+
+ return StreamUtil.calculateTagLength(tagNo) + length;
+ }
+ }
+ else
+ {
+ return StreamUtil.calculateTagLength(tagNo) + 1;
+ }
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ if (!empty)
+ {
+ ASN1Primitive primitive = obj.toASN1Primitive().toDLObject();
+
+ if (explicit)
+ {
+ out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
+ out.writeLength(primitive.encodedLength());
+ out.writeObject(primitive);
+ }
+ else
+ {
+ //
+ // need to mark constructed types...
+ //
+ int flags;
+ if (primitive.isConstructed())
+ {
+ flags = BERTags.CONSTRUCTED | BERTags.TAGGED;
+ }
+ else
+ {
+ flags = BERTags.TAGGED;
+ }
+
+ out.writeTag(flags, tagNo);
+ out.writeImplicitObject(primitive);
+ }
+ }
+ else
+ {
+ out.writeEncoded(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo, ZERO_BYTES);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DefiniteLengthInputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DefiniteLengthInputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/DefiniteLengthInputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/DefiniteLengthInputStream.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,105 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import pdftk.org.bouncycastle.util.io.Streams;
+
+class DefiniteLengthInputStream
+ extends LimitedInputStream
+{
+ private static final byte[] EMPTY_BYTES = new byte[0];
+
+ private final int _originalLength;
+ private int _remaining;
+
+ DefiniteLengthInputStream(
+ InputStream in,
+ int length)
+ {
+ super(in, length);
+
+ if (length < 0)
+ {
+ throw new IllegalArgumentException("negative lengths not allowed");
+ }
+
+ this._originalLength = length;
+ this._remaining = length;
+
+ if (length == 0)
+ {
+ setParentEofDetect(true);
+ }
+ }
+
+ int getRemaining()
+ {
+ return _remaining;
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (_remaining == 0)
+ {
+ return -1;
+ }
+
+ int b = _in.read();
+
+ if (b < 0)
+ {
+ throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
+ }
+
+ if (--_remaining == 0)
+ {
+ setParentEofDetect(true);
+ }
+
+ return b;
+ }
+
+ public int read(byte[] buf, int off, int len)
+ throws IOException
+ {
+ if (_remaining == 0)
+ {
+ return -1;
+ }
+
+ int toRead = Math.min(len, _remaining);
+ int numRead = _in.read(buf, off, toRead);
+
+ if (numRead < 0)
+ {
+ throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
+ }
+
+ if ((_remaining -= numRead) == 0)
+ {
+ setParentEofDetect(true);
+ }
+
+ return numRead;
+ }
+
+ byte[] toByteArray()
+ throws IOException
+ {
+ if (_remaining == 0)
+ {
+ return EMPTY_BYTES;
+ }
+
+ byte[] bytes = new byte[_remaining];
+ if ((_remaining -= Streams.readFully(_in, bytes)) != 0)
+ {
+ throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
+ }
+ setParentEofDetect(true);
+ return bytes;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/InMemoryRepresentable.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/InMemoryRepresentable.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/InMemoryRepresentable.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/InMemoryRepresentable.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,9 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+
+public interface InMemoryRepresentable
+{
+ ASN1Primitive getLoadedObject()
+ throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/IndefiniteLengthInputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/IndefiniteLengthInputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/IndefiniteLengthInputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/IndefiniteLengthInputStream.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,111 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+class IndefiniteLengthInputStream
+ extends LimitedInputStream
+{
+ private int _b1;
+ private int _b2;
+ private boolean _eofReached = false;
+ private boolean _eofOn00 = true;
+
+ IndefiniteLengthInputStream(
+ InputStream in,
+ int limit)
+ throws IOException
+ {
+ super(in, limit);
+
+ _b1 = in.read();
+ _b2 = in.read();
+
+ if (_b2 < 0)
+ {
+ // Corrupted stream
+ throw new EOFException();
+ }
+
+ checkForEof();
+ }
+
+ void setEofOn00(
+ boolean eofOn00)
+ {
+ _eofOn00 = eofOn00;
+ checkForEof();
+ }
+
+ private boolean checkForEof()
+ {
+ if (!_eofReached && _eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
+ {
+ _eofReached = true;
+ setParentEofDetect(true);
+ }
+ return _eofReached;
+ }
+
+ public int read(byte[] b, int off, int len)
+ throws IOException
+ {
+ // Only use this optimisation if we aren't checking for 00
+ if (_eofOn00 || len < 3)
+ {
+ return super.read(b, off, len);
+ }
+
+ if (_eofReached)
+ {
+ return -1;
+ }
+
+ int numRead = _in.read(b, off + 2, len - 2);
+
+ if (numRead < 0)
+ {
+ // Corrupted stream
+ throw new EOFException();
+ }
+
+ b[off] = (byte)_b1;
+ b[off + 1] = (byte)_b2;
+
+ _b1 = _in.read();
+ _b2 = _in.read();
+
+ if (_b2 < 0)
+ {
+ // Corrupted stream
+ throw new EOFException();
+ }
+
+ return numRead + 2;
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (checkForEof())
+ {
+ return -1;
+ }
+
+ int b = _in.read();
+
+ if (b < 0)
+ {
+ // Corrupted stream
+ throw new EOFException();
+ }
+
+ int v = _b1;
+
+ _b1 = _b2;
+ _b2 = b;
+
+ return v;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/LazyConstructionEnumeration.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/LazyConstructionEnumeration.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/LazyConstructionEnumeration.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/LazyConstructionEnumeration.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,43 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+class LazyConstructionEnumeration
+ implements Enumeration
+{
+ private ASN1InputStream aIn;
+ private Object nextObj;
+
+ public LazyConstructionEnumeration(byte[] encoded)
+ {
+ aIn = new ASN1InputStream(encoded, true);
+ nextObj = readObject();
+ }
+
+ public boolean hasMoreElements()
+ {
+ return nextObj != null;
+ }
+
+ public Object nextElement()
+ {
+ Object o = nextObj;
+
+ nextObj = readObject();
+
+ return o;
+ }
+
+ private Object readObject()
+ {
+ try
+ {
+ return aIn.readObject();
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("malformed DER construction: " + e, e);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/LazyEncodedSequence.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/LazyEncodedSequence.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/LazyEncodedSequence.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/LazyEncodedSequence.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,109 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+/**
+ * Note: this class is for processing DER/DL encoded sequences only.
+ */
+class LazyEncodedSequence
+ extends ASN1Sequence
+{
+ private byte[] encoded;
+
+ LazyEncodedSequence(
+ byte[] encoded)
+ throws IOException
+ {
+ this.encoded = encoded;
+ }
+
+ private void parse()
+ {
+ Enumeration en = new LazyConstructionEnumeration(encoded);
+
+ while (en.hasMoreElements())
+ {
+ seq.addElement(en.nextElement());
+ }
+
+ encoded = null;
+ }
+
+ public synchronized ASN1Encodable getObjectAt(int index)
+ {
+ if (encoded != null)
+ {
+ parse();
+ }
+
+ return super.getObjectAt(index);
+ }
+
+ public synchronized Enumeration getObjects()
+ {
+ if (encoded == null)
+ {
+ return super.getObjects();
+ }
+
+ return new LazyConstructionEnumeration(encoded);
+ }
+
+ public synchronized int size()
+ {
+ if (encoded != null)
+ {
+ parse();
+ }
+
+ return super.size();
+ }
+
+ ASN1Primitive toDERObject()
+ {
+ if (encoded != null)
+ {
+ parse();
+ }
+
+ return super.toDERObject();
+ }
+
+ ASN1Primitive toDLObject()
+ {
+ if (encoded != null)
+ {
+ parse();
+ }
+
+ return super.toDLObject();
+ }
+
+ int encodedLength()
+ throws IOException
+ {
+ if (encoded != null)
+ {
+ return 1 + StreamUtil.calculateBodyLength(encoded.length) + encoded.length;
+ }
+ else
+ {
+ return super.toDLObject().encodedLength();
+ }
+ }
+
+ void encode(
+ ASN1OutputStream out)
+ throws IOException
+ {
+ if (encoded != null)
+ {
+ out.writeEncoded(BERTags.SEQUENCE | BERTags.CONSTRUCTED, encoded);
+ }
+ else
+ {
+ super.toDLObject().encode(out);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/LimitedInputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/LimitedInputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/LimitedInputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/LimitedInputStream.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,32 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.InputStream;
+
+abstract class LimitedInputStream
+ extends InputStream
+{
+ protected final InputStream _in;
+ private int _limit;
+
+ LimitedInputStream(
+ InputStream in,
+ int limit)
+ {
+ this._in = in;
+ this._limit = limit;
+ }
+
+ int getRemaining()
+ {
+ // TODO: maybe one day this can become more accurate
+ return _limit;
+ }
+
+ protected void setParentEofDetect(boolean on)
+ {
+ if (_in instanceof IndefiniteLengthInputStream)
+ {
+ ((IndefiniteLengthInputStream)_in).setEofOn00(on);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/OIDTokenizer.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/OIDTokenizer.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/OIDTokenizer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/OIDTokenizer.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.asn1;
+
+/**
+ * class for breaking up an OID into it's component tokens, ala
+ * java.util.StringTokenizer. We need this class as some of the
+ * lightweight Java environment don't support classes like
+ * StringTokenizer.
+ */
+public class OIDTokenizer
+{
+ private String oid;
+ private int index;
+
+ public OIDTokenizer(
+ String oid)
+ {
+ this.oid = oid;
+ this.index = 0;
+ }
+
+ public boolean hasMoreTokens()
+ {
+ return (index != -1);
+ }
+
+ public String nextToken()
+ {
+ if (index == -1)
+ {
+ return null;
+ }
+
+ String token;
+ int end = oid.indexOf('.', index);
+
+ if (end == -1)
+ {
+ token = oid.substring(index);
+ index = -1;
+ return token;
+ }
+
+ token = oid.substring(index, end);
+
+ index = end + 1;
+ return token;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/StreamUtil.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/StreamUtil.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/StreamUtil.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/StreamUtil.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,89 @@
+package pdftk.org.bouncycastle.asn1;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+class StreamUtil
+{
+ /**
+ * Find out possible longest length...
+ *
+ * @param in input stream of interest
+ * @return length calculation or MAX_VALUE.
+ */
+ static int findLimit(InputStream in)
+ {
+ if (in instanceof LimitedInputStream)
+ {
+ return ((LimitedInputStream)in).getRemaining();
+ }
+ else if (in instanceof ASN1InputStream)
+ {
+ return ((ASN1InputStream)in).getLimit();
+ }
+ else if (in instanceof ByteArrayInputStream)
+ {
+ return ((ByteArrayInputStream)in).available();
+ }
+
+ return Integer.MAX_VALUE;
+ }
+
+ static int calculateBodyLength(
+ int length)
+ {
+ int count = 1;
+
+ if (length > 127)
+ {
+ int size = 1;
+ int val = length;
+
+ while ((val >>>= 8) != 0)
+ {
+ size++;
+ }
+
+ for (int i = (size - 1) * 8; i >= 0; i -= 8)
+ {
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ static int calculateTagLength(int tagNo)
+ throws IOException
+ {
+ int length = 1;
+
+ if (tagNo >= 31)
+ {
+ if (tagNo < 128)
+ {
+ length++;
+ }
+ else
+ {
+ byte[] stack = new byte[5];
+ int pos = stack.length;
+
+ stack[--pos] = (byte)(tagNo & 0x7F);
+
+ do
+ {
+ tagNo >>= 7;
+ stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
+ }
+ while (tagNo > 127);
+
+ length += stack.length - pos;
+ }
+ }
+
+ return length;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,51 @@
+package pdftk.org.bouncycastle.asn1.bc;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface BCObjectIdentifiers
+{
+ /**
+ * iso.org.dod.internet.private.enterprise.legion-of-the-bouncy-castle
+ *
+ * 1.3.6.1.4.1.22554
+ */
+ public static final ASN1ObjectIdentifier bc = new ASN1ObjectIdentifier("1.3.6.1.4.1.22554");
+
+ /**
+ * pbe(1) algorithms
+ */
+ public static final ASN1ObjectIdentifier bc_pbe = new ASN1ObjectIdentifier(bc.getId() + ".1");
+
+ /**
+ * SHA-1(1)
+ */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".1");
+
+ /**
+ * SHA-2(2) . (SHA-256(1)|SHA-384(2)|SHA-512(3)|SHA-224(4))
+ */
+ public static final ASN1ObjectIdentifier bc_pbe_sha256 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".2.1");
+ public static final ASN1ObjectIdentifier bc_pbe_sha384 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".2.2");
+ public static final ASN1ObjectIdentifier bc_pbe_sha512 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".2.3");
+ public static final ASN1ObjectIdentifier bc_pbe_sha224 = new ASN1ObjectIdentifier(bc_pbe.getId() + ".2.4");
+
+ /**
+ * PKCS-5(1)|PKCS-12(2)
+ */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs5 = new ASN1ObjectIdentifier(bc_pbe_sha1.getId() + ".1");
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12 = new ASN1ObjectIdentifier(bc_pbe_sha1.getId() + ".2");
+
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs5 = new ASN1ObjectIdentifier(bc_pbe_sha256.getId() + ".1");
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12 = new ASN1ObjectIdentifier(bc_pbe_sha256.getId() + ".2");
+
+ /**
+ * AES(1) . (CBC-128(2)|CBC-192(22)|CBC-256(42))
+ */
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes128_cbc = new ASN1ObjectIdentifier(bc_pbe_sha1_pkcs12.getId() + ".1.2");
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes192_cbc = new ASN1ObjectIdentifier(bc_pbe_sha1_pkcs12.getId() + ".1.22");
+ public static final ASN1ObjectIdentifier bc_pbe_sha1_pkcs12_aes256_cbc = new ASN1ObjectIdentifier(bc_pbe_sha1_pkcs12.getId() + ".1.42");
+
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes128_cbc = new ASN1ObjectIdentifier(bc_pbe_sha256_pkcs12.getId() + ".1.2");
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes192_cbc = new ASN1ObjectIdentifier(bc_pbe_sha256_pkcs12.getId() + ".1.22");
+ public static final ASN1ObjectIdentifier bc_pbe_sha256_pkcs12_aes256_cbc = new ASN1ObjectIdentifier(bc_pbe_sha256_pkcs12.getId() + ".1.42");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CAKeyUpdAnnContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CAKeyUpdAnnContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CAKeyUpdAnnContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CAKeyUpdAnnContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,80 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class CAKeyUpdAnnContent
+ extends ASN1Object
+{
+ private CMPCertificate oldWithNew;
+ private CMPCertificate newWithOld;
+ private CMPCertificate newWithNew;
+
+ private CAKeyUpdAnnContent(ASN1Sequence seq)
+ {
+ oldWithNew = CMPCertificate.getInstance(seq.getObjectAt(0));
+ newWithOld = CMPCertificate.getInstance(seq.getObjectAt(1));
+ newWithNew = CMPCertificate.getInstance(seq.getObjectAt(2));
+ }
+
+ public static CAKeyUpdAnnContent getInstance(Object o)
+ {
+ if (o instanceof CAKeyUpdAnnContent)
+ {
+ return (CAKeyUpdAnnContent)o;
+ }
+
+ if (o != null)
+ {
+ return new CAKeyUpdAnnContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CAKeyUpdAnnContent(CMPCertificate oldWithNew, CMPCertificate newWithOld, CMPCertificate newWithNew)
+ {
+ this.oldWithNew = oldWithNew;
+ this.newWithOld = newWithOld;
+ this.newWithNew = newWithNew;
+ }
+
+ public CMPCertificate getOldWithNew()
+ {
+ return oldWithNew;
+ }
+
+ public CMPCertificate getNewWithOld()
+ {
+ return newWithOld;
+ }
+
+ public CMPCertificate getNewWithNew()
+ {
+ return newWithNew;
+ }
+
+ /**
+ *
+ * CAKeyUpdAnnContent ::= SEQUENCE {
+ * oldWithNew CMPCertificate, -- old pub signed with new priv
+ * newWithOld CMPCertificate, -- new pub signed with old priv
+ * newWithNew CMPCertificate -- new pub signed with new priv
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(oldWithNew);
+ v.add(newWithOld);
+ v.add(newWithNew);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CMPCertificate.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CMPCertificate.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CMPCertificate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CMPCertificate.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,92 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AttributeCertificate;
+import pdftk.org.bouncycastle.asn1.x509.Certificate;
+
+public class CMPCertificate
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private Certificate x509v3PKCert;
+ private AttributeCertificate x509v2AttrCert;
+
+ /**
+ * Note: the addition of attribute certificates is a BC extension.
+ */
+ public CMPCertificate(AttributeCertificate x509v2AttrCert)
+ {
+ this.x509v2AttrCert = x509v2AttrCert;
+ }
+
+ public CMPCertificate(Certificate x509v3PKCert)
+ {
+ if (x509v3PKCert.getVersionNumber() != 3)
+ {
+ throw new IllegalArgumentException("only version 3 certificates allowed");
+ }
+
+ this.x509v3PKCert = x509v3PKCert;
+ }
+
+ public static CMPCertificate getInstance(Object o)
+ {
+ if (o == null || o instanceof CMPCertificate)
+ {
+ return (CMPCertificate)o;
+ }
+
+ if (o instanceof ASN1Sequence || o instanceof byte[])
+ {
+ return new CMPCertificate(Certificate.getInstance(o));
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ return new CMPCertificate(AttributeCertificate.getInstance(((ASN1TaggedObject)o).getObject()));
+ }
+
+ throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
+ }
+
+ public boolean isX509v3PKCert()
+ {
+ return x509v3PKCert != null;
+ }
+
+ public Certificate getX509v3PKCert()
+ {
+ return x509v3PKCert;
+ }
+
+ public AttributeCertificate getX509v2AttrCert()
+ {
+ return x509v2AttrCert;
+ }
+
+ /**
+ *
+ * CMPCertificate ::= CHOICE {
+ * x509v3PKCert Certificate
+ * x509v2AttrCert [1] AttributeCertificate
+ * }
+ *
+ * Note: the addition of attribute certificates is a BC extension.
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (x509v2AttrCert != null)
+ { // explicit following CMP conventions
+ return new DERTaggedObject(true, 1, x509v2AttrCert);
+ }
+
+ return x509v3PKCert.toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CMPObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,106 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface CMPObjectIdentifiers
+{
+ // RFC 4210
+
+ // id-PasswordBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 13}
+ static final ASN1ObjectIdentifier passwordBasedMac = new ASN1ObjectIdentifier("1.2.840.113533.7.66.13");
+
+ // id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30}
+ static final ASN1ObjectIdentifier dhBasedMac = new ASN1ObjectIdentifier("1.2.840.113533.7.66.30");
+
+ // Example InfoTypeAndValue contents include, but are not limited
+ // to, the following (un-comment in this ASN.1 module and use as
+ // appropriate for a given environment):
+ //
+ // id-it-caProtEncCert OBJECT IDENTIFIER ::= {id-it 1}
+ // CAProtEncCertValue ::= CMPCertificate
+ // id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
+ // SignKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ // id-it-encKeyPairTypes OBJECT IDENTIFIER ::= {id-it 3}
+ // EncKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ // id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
+ // PreferredSymmAlgValue ::= AlgorithmIdentifier
+ // id-it-caKeyUpdateInfo OBJECT IDENTIFIER ::= {id-it 5}
+ // CAKeyUpdateInfoValue ::= CAKeyUpdAnnContent
+ // id-it-currentCRL OBJECT IDENTIFIER ::= {id-it 6}
+ // CurrentCRLValue ::= CertificateList
+ // id-it-unsupportedOIDs OBJECT IDENTIFIER ::= {id-it 7}
+ // UnsupportedOIDsValue ::= SEQUENCE OF OBJECT IDENTIFIER
+ // id-it-keyPairParamReq OBJECT IDENTIFIER ::= {id-it 10}
+ // KeyPairParamReqValue ::= OBJECT IDENTIFIER
+ // id-it-keyPairParamRep OBJECT IDENTIFIER ::= {id-it 11}
+ // KeyPairParamRepValue ::= AlgorithmIdentifer
+ // id-it-revPassphrase OBJECT IDENTIFIER ::= {id-it 12}
+ // RevPassphraseValue ::= EncryptedValue
+ // id-it-implicitConfirm OBJECT IDENTIFIER ::= {id-it 13}
+ // ImplicitConfirmValue ::= NULL
+ // id-it-confirmWaitTime OBJECT IDENTIFIER ::= {id-it 14}
+ // ConfirmWaitTimeValue ::= GeneralizedTime
+ // id-it-origPKIMessage OBJECT IDENTIFIER ::= {id-it 15}
+ // OrigPKIMessageValue ::= PKIMessages
+ // id-it-suppLangTags OBJECT IDENTIFIER ::= {id-it 16}
+ // SuppLangTagsValue ::= SEQUENCE OF UTF8String
+ //
+ // where
+ //
+ // id-pkix OBJECT IDENTIFIER ::= {
+ // iso(1) identified-organization(3)
+ // dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
+ // and
+ // id-it OBJECT IDENTIFIER ::= {id-pkix 4}
+ static final ASN1ObjectIdentifier it_caProtEncCert = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.1");
+ static final ASN1ObjectIdentifier it_signKeyPairTypes = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.2");
+ static final ASN1ObjectIdentifier it_encKeyPairTypes = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.3");
+ static final ASN1ObjectIdentifier it_preferredSymAlg = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.4");
+ static final ASN1ObjectIdentifier it_caKeyUpdateInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.5");
+ static final ASN1ObjectIdentifier it_currentCRL = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.6");
+ static final ASN1ObjectIdentifier it_unsupportedOIDs = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.7");
+ static final ASN1ObjectIdentifier it_keyPairParamReq = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.10");
+ static final ASN1ObjectIdentifier it_keyPairParamRep = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.11");
+ static final ASN1ObjectIdentifier it_revPassphrase = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.12");
+ static final ASN1ObjectIdentifier it_implicitConfirm = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.13");
+ static final ASN1ObjectIdentifier it_confirmWaitTime = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.14");
+ static final ASN1ObjectIdentifier it_origPKIMessage = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.15");
+ static final ASN1ObjectIdentifier it_suppLangTags = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.4.16");
+
+ // RFC 4211
+
+ // id-pkix OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+ // dod(6) internet(1) security(5) mechanisms(5) pkix(7) }
+ //
+ // arc for Internet X.509 PKI protocols and their components
+ // id-pkip OBJECT IDENTIFIER :: { id-pkix pkip(5) }
+ //
+ // arc for Registration Controls in CRMF
+ // id-regCtrl OBJECT IDENTIFIER ::= { id-pkip regCtrl(1) }
+ //
+ // arc for Registration Info in CRMF
+ // id-regInfo OBJECT IDENTIFIER ::= { id-pkip id-regInfo(2) }
+
+ static final ASN1ObjectIdentifier regCtrl_regToken = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.1");
+ static final ASN1ObjectIdentifier regCtrl_authenticator = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.2");
+ static final ASN1ObjectIdentifier regCtrl_pkiPublicationInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.3");
+ static final ASN1ObjectIdentifier regCtrl_pkiArchiveOptions = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.4");
+ static final ASN1ObjectIdentifier regCtrl_oldCertID = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.5");
+ static final ASN1ObjectIdentifier regCtrl_protocolEncrKey = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.6");
+
+ // From RFC4210:
+ // id-regCtrl-altCertTemplate OBJECT IDENTIFIER ::= {id-regCtrl 7}
+ static final ASN1ObjectIdentifier regCtrl_altCertTemplate = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.1.7");
+
+ static final ASN1ObjectIdentifier regInfo_utf8Pairs = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.2.1");
+ static final ASN1ObjectIdentifier regInfo_certReq = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.5.2.2");
+
+ // id-smime OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ // us(840) rsadsi(113549) pkcs(1) pkcs9(9) 16 }
+ //
+ // id-ct OBJECT IDENTIFIER ::= { id-smime 1 } -- content types
+ //
+ // id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21}
+ static final ASN1ObjectIdentifier ct_encKeyWithID = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.1.21");
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CRLAnnContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CRLAnnContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CRLAnnContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CRLAnnContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,61 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.CertificateList;
+
+public class CRLAnnContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private CRLAnnContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CRLAnnContent getInstance(Object o)
+ {
+ if (o instanceof CRLAnnContent)
+ {
+ return (CRLAnnContent)o;
+ }
+
+ if (o != null)
+ {
+ return new CRLAnnContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CRLAnnContent(CertificateList crl)
+ {
+ this.content = new DERSequence(crl);
+ }
+
+ public CertificateList[] getCertificateLists()
+ {
+ CertificateList[] result = new CertificateList[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = CertificateList.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * CRLAnnContent ::= SEQUENCE OF CertificateList
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CertConfirmContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CertConfirmContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CertConfirmContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CertConfirmContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,54 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+
+public class CertConfirmContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private CertConfirmContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CertConfirmContent getInstance(Object o)
+ {
+ if (o instanceof CertConfirmContent)
+ {
+ return (CertConfirmContent)o;
+ }
+
+ if (o != null)
+ {
+ return new CertConfirmContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertStatus[] toCertStatusArray()
+ {
+ CertStatus[] result = new CertStatus[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = CertStatus.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * CertConfirmContent ::= SEQUENCE OF CertStatus
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CertOrEncCert.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CertOrEncCert.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CertOrEncCert.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CertOrEncCert.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,96 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.crmf.EncryptedValue;
+
+public class CertOrEncCert
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private CMPCertificate certificate;
+ private EncryptedValue encryptedCert;
+
+ private CertOrEncCert(ASN1TaggedObject tagged)
+ {
+ if (tagged.getTagNo() == 0)
+ {
+ certificate = CMPCertificate.getInstance(tagged.getObject());
+ }
+ else if (tagged.getTagNo() == 1)
+ {
+ encryptedCert = EncryptedValue.getInstance(tagged.getObject());
+ }
+ else
+ {
+ throw new IllegalArgumentException("unknown tag: " + tagged.getTagNo());
+ }
+ }
+
+ public static CertOrEncCert getInstance(Object o)
+ {
+ if (o instanceof CertOrEncCert)
+ {
+ return (CertOrEncCert)o;
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ return new CertOrEncCert((ASN1TaggedObject)o);
+ }
+
+ return null;
+ }
+
+ public CertOrEncCert(CMPCertificate certificate)
+ {
+ if (certificate == null)
+ {
+ throw new IllegalArgumentException("'certificate' cannot be null");
+ }
+
+ this.certificate = certificate;
+ }
+
+ public CertOrEncCert(EncryptedValue encryptedCert)
+ {
+ if (encryptedCert == null)
+ {
+ throw new IllegalArgumentException("'encryptedCert' cannot be null");
+ }
+
+ this.encryptedCert = encryptedCert;
+ }
+
+ public CMPCertificate getCertificate()
+ {
+ return certificate;
+ }
+
+ public EncryptedValue getEncryptedCert()
+ {
+ return encryptedCert;
+ }
+
+ /**
+ *
+ * CertOrEncCert ::= CHOICE {
+ * certificate [0] CMPCertificate,
+ * encryptedCert [1] EncryptedValue
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (certificate != null)
+ {
+ return new DERTaggedObject(true, 0, certificate);
+ }
+
+ return new DERTaggedObject(true, 1, encryptedCert);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CertRepMessage.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CertRepMessage.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CertRepMessage.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CertRepMessage.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,123 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class CertRepMessage
+ extends ASN1Object
+{
+ private ASN1Sequence caPubs;
+ private ASN1Sequence response;
+
+ private CertRepMessage(ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.size() > 1)
+ {
+ caPubs = ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(index++), true);
+ }
+
+ response = ASN1Sequence.getInstance(seq.getObjectAt(index));
+ }
+
+ public static CertRepMessage getInstance(Object o)
+ {
+ if (o instanceof CertRepMessage)
+ {
+ return (CertRepMessage)o;
+ }
+
+ if (o != null)
+ {
+ return new CertRepMessage(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertRepMessage(CMPCertificate[] caPubs, CertResponse[] response)
+ {
+ if (response == null)
+ {
+ throw new IllegalArgumentException("'response' cannot be null");
+ }
+
+ if (caPubs != null)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < caPubs.length; i++)
+ {
+ v.add(caPubs[i]);
+ }
+ this.caPubs = new DERSequence(v);
+ }
+
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < response.length; i++)
+ {
+ v.add(response[i]);
+ }
+ this.response = new DERSequence(v);
+ }
+ }
+
+ public CMPCertificate[] getCaPubs()
+ {
+ if (caPubs == null)
+ {
+ return null;
+ }
+
+ CMPCertificate[] results = new CMPCertificate[caPubs.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CMPCertificate.getInstance(caPubs.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ public CertResponse[] getResponse()
+ {
+ CertResponse[] results = new CertResponse[response.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CertResponse.getInstance(response.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ /**
+ *
+ * CertRepMessage ::= SEQUENCE {
+ * caPubs [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+ * OPTIONAL,
+ * response SEQUENCE OF CertResponse
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (caPubs != null)
+ {
+ v.add(new DERTaggedObject(true, 1, caPubs));
+ }
+
+ v.add(response);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CertResponse.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CertResponse.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CertResponse.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CertResponse.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,139 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class CertResponse
+ extends ASN1Object
+{
+ private ASN1Integer certReqId;
+ private PKIStatusInfo status;
+ private CertifiedKeyPair certifiedKeyPair;
+ private ASN1OctetString rspInfo;
+
+ private CertResponse(ASN1Sequence seq)
+ {
+ certReqId = ASN1Integer.getInstance(seq.getObjectAt(0));
+ status = PKIStatusInfo.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() >= 3)
+ {
+ if (seq.size() == 3)
+ {
+ ASN1Encodable o = seq.getObjectAt(2);
+ if (o instanceof ASN1OctetString)
+ {
+ rspInfo = ASN1OctetString.getInstance(o);
+ }
+ else
+ {
+ certifiedKeyPair = CertifiedKeyPair.getInstance(o);
+ }
+ }
+ else
+ {
+ certifiedKeyPair = CertifiedKeyPair.getInstance(seq.getObjectAt(2));
+ rspInfo = ASN1OctetString.getInstance(seq.getObjectAt(3));
+ }
+ }
+ }
+
+ public static CertResponse getInstance(Object o)
+ {
+ if (o instanceof CertResponse)
+ {
+ return (CertResponse)o;
+ }
+
+ if (o != null)
+ {
+ return new CertResponse(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertResponse(
+ ASN1Integer certReqId,
+ PKIStatusInfo status)
+ {
+ this(certReqId, status, null, null);
+ }
+
+ public CertResponse(
+ ASN1Integer certReqId,
+ PKIStatusInfo status,
+ CertifiedKeyPair certifiedKeyPair,
+ ASN1OctetString rspInfo)
+ {
+ if (certReqId == null)
+ {
+ throw new IllegalArgumentException("'certReqId' cannot be null");
+ }
+ if (status == null)
+ {
+ throw new IllegalArgumentException("'status' cannot be null");
+ }
+ this.certReqId = certReqId;
+ this.status = status;
+ this.certifiedKeyPair = certifiedKeyPair;
+ this.rspInfo = rspInfo;
+ }
+
+ public ASN1Integer getCertReqId()
+ {
+ return certReqId;
+ }
+
+ public PKIStatusInfo getStatus()
+ {
+ return status;
+ }
+
+ public CertifiedKeyPair getCertifiedKeyPair()
+ {
+ return certifiedKeyPair;
+ }
+
+ /**
+ *
+ * CertResponse ::= SEQUENCE {
+ * certReqId INTEGER,
+ * -- to match this response with corresponding request (a value
+ * -- of -1 is to be used if certReqId is not specified in the
+ * -- corresponding request)
+ * status PKIStatusInfo,
+ * certifiedKeyPair CertifiedKeyPair OPTIONAL,
+ * rspInfo OCTET STRING OPTIONAL
+ * -- analogous to the id-regInfo-utf8Pairs string defined
+ * -- for regInfo in CertReqMsg [CRMF]
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certReqId);
+ v.add(status);
+
+ if (certifiedKeyPair != null)
+ {
+ v.add(certifiedKeyPair);
+ }
+
+ if (rspInfo != null)
+ {
+ v.add(rspInfo);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CertStatus.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CertStatus.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CertStatus.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CertStatus.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,102 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class CertStatus
+ extends ASN1Object
+{
+ private ASN1OctetString certHash;
+ private ASN1Integer certReqId;
+ private PKIStatusInfo statusInfo;
+
+ private CertStatus(ASN1Sequence seq)
+ {
+ certHash = ASN1OctetString.getInstance(seq.getObjectAt(0));
+ certReqId = ASN1Integer.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() > 2)
+ {
+ statusInfo = PKIStatusInfo.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public CertStatus(byte[] certHash, BigInteger certReqId)
+ {
+ this.certHash = new DEROctetString(certHash);
+ this.certReqId = new ASN1Integer(certReqId);
+ }
+
+ public CertStatus(byte[] certHash, BigInteger certReqId, PKIStatusInfo statusInfo)
+ {
+ this.certHash = new DEROctetString(certHash);
+ this.certReqId = new ASN1Integer(certReqId);
+ this.statusInfo = statusInfo;
+ }
+
+ public static CertStatus getInstance(Object o)
+ {
+ if (o instanceof CertStatus)
+ {
+ return (CertStatus)o;
+ }
+
+ if (o != null)
+ {
+ return new CertStatus(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1OctetString getCertHash()
+ {
+ return certHash;
+ }
+
+ public ASN1Integer getCertReqId()
+ {
+ return certReqId;
+ }
+
+ public PKIStatusInfo getStatusInfo()
+ {
+ return statusInfo;
+ }
+
+ /**
+ *
+ * CertStatus ::= SEQUENCE {
+ * certHash OCTET STRING,
+ * -- the hash of the certificate, using the same hash algorithm
+ * -- as is used to create and verify the certificate signature
+ * certReqId INTEGER,
+ * -- to match this confirmation with the corresponding req/rep
+ * statusInfo PKIStatusInfo OPTIONAL
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certHash);
+ v.add(certReqId);
+
+ if (statusInfo != null)
+ {
+ v.add(statusInfo);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CertifiedKeyPair.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CertifiedKeyPair.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/CertifiedKeyPair.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/CertifiedKeyPair.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,127 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.crmf.EncryptedValue;
+import pdftk.org.bouncycastle.asn1.crmf.PKIPublicationInfo;
+
+public class CertifiedKeyPair
+ extends ASN1Object
+{
+ private CertOrEncCert certOrEncCert;
+ private EncryptedValue privateKey;
+ private PKIPublicationInfo publicationInfo;
+
+ private CertifiedKeyPair(ASN1Sequence seq)
+ {
+ certOrEncCert = CertOrEncCert.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() >= 2)
+ {
+ if (seq.size() == 2)
+ {
+ ASN1TaggedObject tagged = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
+ if (tagged.getTagNo() == 0)
+ {
+ privateKey = EncryptedValue.getInstance(tagged.getObject());
+ }
+ else
+ {
+ publicationInfo = PKIPublicationInfo.getInstance(tagged.getObject());
+ }
+ }
+ else
+ {
+ privateKey = EncryptedValue.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(1)));
+ publicationInfo = PKIPublicationInfo.getInstance(ASN1TaggedObject.getInstance(seq.getObjectAt(2)));
+ }
+ }
+ }
+
+ public static CertifiedKeyPair getInstance(Object o)
+ {
+ if (o instanceof CertifiedKeyPair)
+ {
+ return (CertifiedKeyPair)o;
+ }
+
+ if (o != null)
+ {
+ return new CertifiedKeyPair(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertifiedKeyPair(
+ CertOrEncCert certOrEncCert)
+ {
+ this(certOrEncCert, null, null);
+ }
+
+ public CertifiedKeyPair(
+ CertOrEncCert certOrEncCert,
+ EncryptedValue privateKey,
+ PKIPublicationInfo publicationInfo
+ )
+ {
+ if (certOrEncCert == null)
+ {
+ throw new IllegalArgumentException("'certOrEncCert' cannot be null");
+ }
+
+ this.certOrEncCert = certOrEncCert;
+ this.privateKey = privateKey;
+ this.publicationInfo = publicationInfo;
+ }
+
+ public CertOrEncCert getCertOrEncCert()
+ {
+ return certOrEncCert;
+ }
+
+ public EncryptedValue getPrivateKey()
+ {
+ return privateKey;
+ }
+
+ public PKIPublicationInfo getPublicationInfo()
+ {
+ return publicationInfo;
+ }
+
+ /**
+ *
+ * CertifiedKeyPair ::= SEQUENCE {
+ * certOrEncCert CertOrEncCert,
+ * privateKey [0] EncryptedValue OPTIONAL,
+ * -- see [CRMF] for comment on encoding
+ * publicationInfo [1] PKIPublicationInfo OPTIONAL
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certOrEncCert);
+
+ if (privateKey != null)
+ {
+ v.add(new DERTaggedObject(true, 0, privateKey));
+ }
+
+ if (publicationInfo != null)
+ {
+ v.add(new DERTaggedObject(true, 1, publicationInfo));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/Challenge.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/Challenge.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/Challenge.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/Challenge.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,120 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class Challenge
+ extends ASN1Object
+{
+ private AlgorithmIdentifier owf;
+ private ASN1OctetString witness;
+ private ASN1OctetString challenge;
+
+ private Challenge(ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.size() == 3)
+ {
+ owf = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++));
+ }
+
+ witness = ASN1OctetString.getInstance(seq.getObjectAt(index++));
+ challenge = ASN1OctetString.getInstance(seq.getObjectAt(index));
+ }
+
+ public static Challenge getInstance(Object o)
+ {
+ if (o instanceof Challenge)
+ {
+ return (Challenge)o;
+ }
+
+ if (o != null)
+ {
+ return new Challenge(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public Challenge(byte[] witness, byte[] challenge)
+ {
+ this(null, witness, challenge);
+ }
+
+ public Challenge(AlgorithmIdentifier owf, byte[] witness, byte[] challenge)
+ {
+ this.owf = owf;
+ this.witness = new DEROctetString(witness);
+ this.challenge = new DEROctetString(challenge);
+ }
+
+ public AlgorithmIdentifier getOwf()
+ {
+ return owf;
+ }
+
+ public byte[] getWitness()
+ {
+ return witness.getOctets();
+ }
+
+ public byte[] getChallenge()
+ {
+ return challenge.getOctets();
+ }
+
+ /**
+ *
+ * Challenge ::= SEQUENCE {
+ * owf AlgorithmIdentifier OPTIONAL,
+ *
+ * -- MUST be present in the first Challenge; MAY be omitted in
+ * -- any subsequent Challenge in POPODecKeyChallContent (if
+ * -- omitted, then the owf used in the immediately preceding
+ * -- Challenge is to be used).
+ *
+ * witness OCTET STRING,
+ * -- the result of applying the one-way function (owf) to a
+ * -- randomly-generated INTEGER, A. [Note that a different
+ * -- INTEGER MUST be used for each Challenge.]
+ * challenge OCTET STRING
+ * -- the encryption (under the public key for which the cert.
+ * -- request is being made) of Rand, where Rand is specified as
+ * -- Rand ::= SEQUENCE {
+ * -- int INTEGER,
+ * -- - the randomly-generated INTEGER A (above)
+ * -- sender GeneralName
+ * -- - the sender's name (as included in PKIHeader)
+ * -- }
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ addOptional(v, owf);
+ v.add(witness);
+ v.add(challenge);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(obj);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/ErrorMsgContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/ErrorMsgContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/ErrorMsgContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/ErrorMsgContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,121 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class ErrorMsgContent
+ extends ASN1Object
+{
+ private PKIStatusInfo pkiStatusInfo;
+ private ASN1Integer errorCode;
+ private PKIFreeText errorDetails;
+
+ private ErrorMsgContent(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ pkiStatusInfo = PKIStatusInfo.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ Object o = en.nextElement();
+
+ if (o instanceof ASN1Integer)
+ {
+ errorCode = ASN1Integer.getInstance(o);
+ }
+ else
+ {
+ errorDetails = PKIFreeText.getInstance(o);
+ }
+ }
+ }
+
+ public static ErrorMsgContent getInstance(Object o)
+ {
+ if (o instanceof ErrorMsgContent)
+ {
+ return (ErrorMsgContent)o;
+ }
+
+ if (o != null)
+ {
+ return new ErrorMsgContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ErrorMsgContent(PKIStatusInfo pkiStatusInfo)
+ {
+ this(pkiStatusInfo, null, null);
+ }
+
+ public ErrorMsgContent(
+ PKIStatusInfo pkiStatusInfo,
+ ASN1Integer errorCode,
+ PKIFreeText errorDetails)
+ {
+ if (pkiStatusInfo == null)
+ {
+ throw new IllegalArgumentException("'pkiStatusInfo' cannot be null");
+ }
+
+ this.pkiStatusInfo = pkiStatusInfo;
+ this.errorCode = errorCode;
+ this.errorDetails = errorDetails;
+ }
+
+ public PKIStatusInfo getPKIStatusInfo()
+ {
+ return pkiStatusInfo;
+ }
+
+ public ASN1Integer getErrorCode()
+ {
+ return errorCode;
+ }
+
+ public PKIFreeText getErrorDetails()
+ {
+ return errorDetails;
+ }
+
+ /**
+ *
+ * ErrorMsgContent ::= SEQUENCE {
+ * pKIStatusInfo PKIStatusInfo,
+ * errorCode INTEGER OPTIONAL,
+ * -- implementation-specific error codes
+ * errorDetails PKIFreeText OPTIONAL
+ * -- implementation-specific error details
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pkiStatusInfo);
+ addOptional(v, errorCode);
+ addOptional(v, errorDetails);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(obj);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/GenMsgContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/GenMsgContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/GenMsgContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/GenMsgContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,71 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class GenMsgContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private GenMsgContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static GenMsgContent getInstance(Object o)
+ {
+ if (o instanceof GenMsgContent)
+ {
+ return (GenMsgContent)o;
+ }
+
+ if (o != null)
+ {
+ return new GenMsgContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public GenMsgContent(InfoTypeAndValue itv)
+ {
+ content = new DERSequence(itv);
+ }
+
+ public GenMsgContent(InfoTypeAndValue[] itv)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < itv.length; i++)
+ {
+ v.add(itv[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public InfoTypeAndValue[] toInfoTypeAndValueArray()
+ {
+ InfoTypeAndValue[] result = new InfoTypeAndValue[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = InfoTypeAndValue.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/GenRepContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/GenRepContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/GenRepContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/GenRepContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,71 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class GenRepContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private GenRepContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static GenRepContent getInstance(Object o)
+ {
+ if (o instanceof GenRepContent)
+ {
+ return (GenRepContent)o;
+ }
+
+ if (o != null)
+ {
+ return new GenRepContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public GenRepContent(InfoTypeAndValue itv)
+ {
+ content = new DERSequence(itv);
+ }
+
+ public GenRepContent(InfoTypeAndValue[] itv)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < itv.length; i++)
+ {
+ v.add(itv[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public InfoTypeAndValue[] toInfoTypeAndValueArray()
+ {
+ InfoTypeAndValue[] result = new InfoTypeAndValue[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = InfoTypeAndValue.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * GenRepContent ::= SEQUENCE OF InfoTypeAndValue
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/InfoTypeAndValue.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/InfoTypeAndValue.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/InfoTypeAndValue.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/InfoTypeAndValue.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,132 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * Example InfoTypeAndValue contents include, but are not limited
+ * to, the following (un-comment in this ASN.1 module and use as
+ * appropriate for a given environment):
+ *
+ * id-it-caProtEncCert OBJECT IDENTIFIER ::= {id-it 1}
+ * CAProtEncCertValue ::= CMPCertificate
+ * id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
+ * SignKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ * id-it-encKeyPairTypes OBJECT IDENTIFIER ::= {id-it 3}
+ * EncKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+ * id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
+ * PreferredSymmAlgValue ::= AlgorithmIdentifier
+ * id-it-caKeyUpdateInfo OBJECT IDENTIFIER ::= {id-it 5}
+ * CAKeyUpdateInfoValue ::= CAKeyUpdAnnContent
+ * id-it-currentCRL OBJECT IDENTIFIER ::= {id-it 6}
+ * CurrentCRLValue ::= CertificateList
+ * id-it-unsupportedOIDs OBJECT IDENTIFIER ::= {id-it 7}
+ * UnsupportedOIDsValue ::= SEQUENCE OF OBJECT IDENTIFIER
+ * id-it-keyPairParamReq OBJECT IDENTIFIER ::= {id-it 10}
+ * KeyPairParamReqValue ::= OBJECT IDENTIFIER
+ * id-it-keyPairParamRep OBJECT IDENTIFIER ::= {id-it 11}
+ * KeyPairParamRepValue ::= AlgorithmIdentifer
+ * id-it-revPassphrase OBJECT IDENTIFIER ::= {id-it 12}
+ * RevPassphraseValue ::= EncryptedValue
+ * id-it-implicitConfirm OBJECT IDENTIFIER ::= {id-it 13}
+ * ImplicitConfirmValue ::= NULL
+ * id-it-confirmWaitTime OBJECT IDENTIFIER ::= {id-it 14}
+ * ConfirmWaitTimeValue ::= GeneralizedTime
+ * id-it-origPKIMessage OBJECT IDENTIFIER ::= {id-it 15}
+ * OrigPKIMessageValue ::= PKIMessages
+ * id-it-suppLangTags OBJECT IDENTIFIER ::= {id-it 16}
+ * SuppLangTagsValue ::= SEQUENCE OF UTF8String
+ *
+ * where
+ *
+ * id-pkix OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3)
+ * dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
+ * and
+ * id-it OBJECT IDENTIFIER ::= {id-pkix 4}
+ *
+ */
+public class InfoTypeAndValue
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier infoType;
+ private ASN1Encodable infoValue;
+
+ private InfoTypeAndValue(ASN1Sequence seq)
+ {
+ infoType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ infoValue = (ASN1Encodable)seq.getObjectAt(1);
+ }
+ }
+
+ public static InfoTypeAndValue getInstance(Object o)
+ {
+ if (o instanceof InfoTypeAndValue)
+ {
+ return (InfoTypeAndValue)o;
+ }
+
+ if (o != null)
+ {
+ return new InfoTypeAndValue(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public InfoTypeAndValue(
+ ASN1ObjectIdentifier infoType)
+ {
+ this.infoType = infoType;
+ this.infoValue = null;
+ }
+
+ public InfoTypeAndValue(
+ ASN1ObjectIdentifier infoType,
+ ASN1Encodable optionalValue)
+ {
+ this.infoType = infoType;
+ this.infoValue = optionalValue;
+ }
+
+ public ASN1ObjectIdentifier getInfoType()
+ {
+ return infoType;
+ }
+
+ public ASN1Encodable getInfoValue()
+ {
+ return infoValue;
+ }
+
+ /**
+ *
+ * InfoTypeAndValue ::= SEQUENCE {
+ * infoType OBJECT IDENTIFIER,
+ * infoValue ANY DEFINED BY infoType OPTIONAL
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(infoType);
+
+ if (infoValue != null)
+ {
+ v.add(infoValue);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/KeyRecRepContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/KeyRecRepContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/KeyRecRepContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/KeyRecRepContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,142 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class KeyRecRepContent
+ extends ASN1Object
+{
+ private PKIStatusInfo status;
+ private CMPCertificate newSigCert;
+ private ASN1Sequence caCerts;
+ private ASN1Sequence keyPairHist;
+
+ private KeyRecRepContent(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ status = PKIStatusInfo.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(en.nextElement());
+
+ switch (tObj.getTagNo())
+ {
+ case 0:
+ newSigCert = CMPCertificate.getInstance(tObj.getObject());
+ break;
+ case 1:
+ caCerts = ASN1Sequence.getInstance(tObj.getObject());
+ break;
+ case 2:
+ keyPairHist = ASN1Sequence.getInstance(tObj.getObject());
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag number: " + tObj.getTagNo());
+ }
+ }
+ }
+
+ public static KeyRecRepContent getInstance(Object o)
+ {
+ if (o instanceof KeyRecRepContent)
+ {
+ return (KeyRecRepContent)o;
+ }
+
+ if (o != null)
+ {
+ return new KeyRecRepContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+
+ public PKIStatusInfo getStatus()
+ {
+ return status;
+ }
+
+ public CMPCertificate getNewSigCert()
+ {
+ return newSigCert;
+ }
+
+ public CMPCertificate[] getCaCerts()
+ {
+ if (caCerts == null)
+ {
+ return null;
+ }
+
+ CMPCertificate[] results = new CMPCertificate[caCerts.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CMPCertificate.getInstance(caCerts.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ public CertifiedKeyPair[] getKeyPairHist()
+ {
+ if (keyPairHist == null)
+ {
+ return null;
+ }
+
+ CertifiedKeyPair[] results = new CertifiedKeyPair[keyPairHist.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CertifiedKeyPair.getInstance(keyPairHist.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ /**
+ *
+ * KeyRecRepContent ::= SEQUENCE {
+ * status PKIStatusInfo,
+ * newSigCert [0] CMPCertificate OPTIONAL,
+ * caCerts [1] SEQUENCE SIZE (1..MAX) OF
+ * CMPCertificate OPTIONAL,
+ * keyPairHist [2] SEQUENCE SIZE (1..MAX) OF
+ * CertifiedKeyPair OPTIONAL
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(status);
+
+ addOptional(v, 0, newSigCert);
+ addOptional(v, 1, caCerts);
+ addOptional(v, 2, keyPairHist);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/OOBCertHash.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/OOBCertHash.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/OOBCertHash.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/OOBCertHash.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,117 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.crmf.CertId;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class OOBCertHash
+ extends ASN1Object
+{
+ private AlgorithmIdentifier hashAlg;
+ private CertId certId;
+ private DERBitString hashVal;
+
+ private OOBCertHash(ASN1Sequence seq)
+ {
+ int index = seq.size() - 1;
+
+ hashVal = DERBitString.getInstance(seq.getObjectAt(index--));
+
+ for (int i = index; i >= 0; i--)
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)seq.getObjectAt(i);
+
+ if (tObj.getTagNo() == 0)
+ {
+ hashAlg = AlgorithmIdentifier.getInstance(tObj, true);
+ }
+ else
+ {
+ certId = CertId.getInstance(tObj, true);
+ }
+ }
+
+ }
+
+ public static OOBCertHash getInstance(Object o)
+ {
+ if (o instanceof OOBCertHash)
+ {
+ return (OOBCertHash)o;
+ }
+
+ if (o != null)
+ {
+ return new OOBCertHash(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public OOBCertHash(AlgorithmIdentifier hashAlg, CertId certId, byte[] hashVal)
+ {
+ this(hashAlg, certId, new DERBitString(hashVal));
+ }
+
+ public OOBCertHash(AlgorithmIdentifier hashAlg, CertId certId, DERBitString hashVal)
+ {
+ this.hashAlg = hashAlg;
+ this.certId = certId;
+ this.hashVal = hashVal;
+ }
+
+ public AlgorithmIdentifier getHashAlg()
+ {
+ return hashAlg;
+ }
+
+ public CertId getCertId()
+ {
+ return certId;
+ }
+
+ public DERBitString getHashVal()
+ {
+ return hashVal;
+ }
+
+ /**
+ *
+ * OOBCertHash ::= SEQUENCE {
+ * hashAlg [0] AlgorithmIdentifier OPTIONAL,
+ * certId [1] CertId OPTIONAL,
+ * hashVal BIT STRING
+ * -- hashVal is calculated over the DER encoding of the
+ * -- self-signed certificate with the identifier certID.
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ addOptional(v, 0, hashAlg);
+ addOptional(v, 1, certId);
+
+ v.add(hashVal);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PBMParameter.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PBMParameter.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PBMParameter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PBMParameter.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,117 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class PBMParameter
+ extends ASN1Object
+{
+ private ASN1OctetString salt;
+ private AlgorithmIdentifier owf;
+ private ASN1Integer iterationCount;
+ private AlgorithmIdentifier mac;
+
+ private PBMParameter(ASN1Sequence seq)
+ {
+ salt = ASN1OctetString.getInstance(seq.getObjectAt(0));
+ owf = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ iterationCount = ASN1Integer.getInstance(seq.getObjectAt(2));
+ mac = AlgorithmIdentifier.getInstance(seq.getObjectAt(3));
+ }
+
+ public static PBMParameter getInstance(Object o)
+ {
+ if (o instanceof PBMParameter)
+ {
+ return (PBMParameter)o;
+ }
+
+ if (o != null)
+ {
+ return new PBMParameter(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PBMParameter(
+ byte[] salt,
+ AlgorithmIdentifier owf,
+ int iterationCount,
+ AlgorithmIdentifier mac)
+ {
+ this(new DEROctetString(salt), owf,
+ new ASN1Integer(iterationCount), mac);
+ }
+
+ public PBMParameter(
+ ASN1OctetString salt,
+ AlgorithmIdentifier owf,
+ ASN1Integer iterationCount,
+ AlgorithmIdentifier mac)
+ {
+ this.salt = salt;
+ this.owf = owf;
+ this.iterationCount = iterationCount;
+ this.mac = mac;
+ }
+
+ public ASN1OctetString getSalt()
+ {
+ return salt;
+ }
+
+ public AlgorithmIdentifier getOwf()
+ {
+ return owf;
+ }
+
+ public ASN1Integer getIterationCount()
+ {
+ return iterationCount;
+ }
+
+ public AlgorithmIdentifier getMac()
+ {
+ return mac;
+ }
+
+ /**
+ *
+ * PBMParameter ::= SEQUENCE {
+ * salt OCTET STRING,
+ * -- note: implementations MAY wish to limit acceptable sizes
+ * -- of this string to values appropriate for their environment
+ * -- in order to reduce the risk of denial-of-service attacks
+ * owf AlgorithmIdentifier,
+ * -- AlgId for a One-Way Function (SHA-1 recommended)
+ * iterationCount INTEGER,
+ * -- number of times the OWF is applied
+ * -- note: implementations MAY wish to limit acceptable sizes
+ * -- of this integer to values appropriate for their environment
+ * -- in order to reduce the risk of denial-of-service attacks
+ * mac AlgorithmIdentifier
+ * -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+ * } -- or HMAC [RFC2104, RFC2202])
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(salt);
+ v.add(owf);
+ v.add(iterationCount);
+ v.add(mac);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIBody.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIBody.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIBody.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIBody.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,194 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.crmf.CertReqMessages;
+import pdftk.org.bouncycastle.asn1.pkcs.CertificationRequest;
+
+public class PKIBody
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int TYPE_INIT_REQ = 0;
+ public static final int TYPE_INIT_REP = 1;
+ public static final int TYPE_CERT_REQ = 2;
+ public static final int TYPE_CERT_REP = 3;
+ public static final int TYPE_P10_CERT_REQ = 4;
+ public static final int TYPE_POPO_CHALL = 5;
+ public static final int TYPE_POPO_REP = 6;
+ public static final int TYPE_KEY_UPDATE_REQ = 7;
+ public static final int TYPE_KEY_UPDATE_REP = 8;
+ public static final int TYPE_KEY_RECOVERY_REQ = 9;
+ public static final int TYPE_KEY_RECOVERY_REP = 10;
+ public static final int TYPE_REVOCATION_REQ = 11;
+ public static final int TYPE_REVOCATION_REP = 12;
+ public static final int TYPE_CROSS_CERT_REQ = 13;
+ public static final int TYPE_CROSS_CERT_REP = 14;
+ public static final int TYPE_CA_KEY_UPDATE_ANN = 15;
+ public static final int TYPE_CERT_ANN = 16;
+ public static final int TYPE_REVOCATION_ANN = 17;
+ public static final int TYPE_CRL_ANN = 18;
+ public static final int TYPE_CONFIRM = 19;
+ public static final int TYPE_NESTED = 20;
+ public static final int TYPE_GEN_MSG = 21;
+ public static final int TYPE_GEN_REP = 22;
+ public static final int TYPE_ERROR = 23;
+ public static final int TYPE_CERT_CONFIRM = 24;
+ public static final int TYPE_POLL_REQ = 25;
+ public static final int TYPE_POLL_REP = 26;
+
+ private int tagNo;
+ private ASN1Encodable body;
+
+ public static PKIBody getInstance(Object o)
+ {
+ if (o == null || o instanceof PKIBody)
+ {
+ return (PKIBody)o;
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ return new PKIBody((ASN1TaggedObject)o);
+ }
+
+ throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
+ }
+
+ private PKIBody(ASN1TaggedObject tagged)
+ {
+ tagNo = tagged.getTagNo();
+ body = getBodyForType(tagNo, tagged.getObject());
+ }
+
+ /**
+ * Creates a new PKIBody.
+ * @param type one of the TYPE_* constants
+ * @param content message content
+ */
+ public PKIBody(
+ int type,
+ ASN1Encodable content)
+ {
+ tagNo = type;
+ body = getBodyForType(type, content);
+ }
+
+ private static ASN1Encodable getBodyForType(
+ int type,
+ ASN1Encodable o)
+ {
+ switch (type)
+ {
+ case TYPE_INIT_REQ:
+ return CertReqMessages.getInstance(o);
+ case TYPE_INIT_REP:
+ return CertRepMessage.getInstance(o);
+ case TYPE_CERT_REQ:
+ return CertReqMessages.getInstance(o);
+ case TYPE_CERT_REP:
+ return CertRepMessage.getInstance(o);
+ case TYPE_P10_CERT_REQ:
+ return CertificationRequest.getInstance(o);
+ case TYPE_POPO_CHALL:
+ return POPODecKeyChallContent.getInstance(o);
+ case TYPE_POPO_REP:
+ return POPODecKeyRespContent.getInstance(o);
+ case TYPE_KEY_UPDATE_REQ:
+ return CertReqMessages.getInstance(o);
+ case TYPE_KEY_UPDATE_REP:
+ return CertRepMessage.getInstance(o);
+ case TYPE_KEY_RECOVERY_REQ:
+ return CertReqMessages.getInstance(o);
+ case TYPE_KEY_RECOVERY_REP:
+ return KeyRecRepContent.getInstance(o);
+ case TYPE_REVOCATION_REQ:
+ return RevReqContent.getInstance(o);
+ case TYPE_REVOCATION_REP:
+ return RevRepContent.getInstance(o);
+ case TYPE_CROSS_CERT_REQ:
+ return CertReqMessages.getInstance(o);
+ case TYPE_CROSS_CERT_REP:
+ return CertRepMessage.getInstance(o);
+ case TYPE_CA_KEY_UPDATE_ANN:
+ return CAKeyUpdAnnContent.getInstance(o);
+ case TYPE_CERT_ANN:
+ return CMPCertificate.getInstance(o);
+ case TYPE_REVOCATION_ANN:
+ return RevAnnContent.getInstance(o);
+ case TYPE_CRL_ANN:
+ return CRLAnnContent.getInstance(o);
+ case TYPE_CONFIRM:
+ return PKIConfirmContent.getInstance(o);
+ case TYPE_NESTED:
+ return PKIMessages.getInstance(o);
+ case TYPE_GEN_MSG:
+ return GenMsgContent.getInstance(o);
+ case TYPE_GEN_REP:
+ return GenRepContent.getInstance(o);
+ case TYPE_ERROR:
+ return ErrorMsgContent.getInstance(o);
+ case TYPE_CERT_CONFIRM:
+ return CertConfirmContent.getInstance(o);
+ case TYPE_POLL_REQ:
+ return PollReqContent.getInstance(o);
+ case TYPE_POLL_REP:
+ return PollRepContent.getInstance(o);
+ default:
+ throw new IllegalArgumentException("unknown tag number: " + type);
+ }
+ }
+
+ public int getType()
+ {
+ return tagNo;
+ }
+
+ public ASN1Encodable getContent()
+ {
+ return body;
+ }
+
+ /**
+ *
+ * PKIBody ::= CHOICE { -- message-specific body elements
+ * ir [0] CertReqMessages, --Initialization Request
+ * ip [1] CertRepMessage, --Initialization Response
+ * cr [2] CertReqMessages, --Certification Request
+ * cp [3] CertRepMessage, --Certification Response
+ * p10cr [4] CertificationRequest, --imported from [PKCS10]
+ * popdecc [5] POPODecKeyChallContent, --pop Challenge
+ * popdecr [6] POPODecKeyRespContent, --pop Response
+ * kur [7] CertReqMessages, --Key Update Request
+ * kup [8] CertRepMessage, --Key Update Response
+ * krr [9] CertReqMessages, --Key Recovery Request
+ * krp [10] KeyRecRepContent, --Key Recovery Response
+ * rr [11] RevReqContent, --Revocation Request
+ * rp [12] RevRepContent, --Revocation Response
+ * ccr [13] CertReqMessages, --Cross-Cert. Request
+ * ccp [14] CertRepMessage, --Cross-Cert. Response
+ * ckuann [15] CAKeyUpdAnnContent, --CA Key Update Ann.
+ * cann [16] CertAnnContent, --Certificate Ann.
+ * rann [17] RevAnnContent, --Revocation Ann.
+ * crlann [18] CRLAnnContent, --CRL Announcement
+ * pkiconf [19] PKIConfirmContent, --Confirmation
+ * nested [20] NestedMessageContent, --Nested Message
+ * genm [21] GenMsgContent, --General Message
+ * genp [22] GenRepContent, --General Response
+ * error [23] ErrorMsgContent, --Error Message
+ * certConf [24] CertConfirmContent, --Certificate confirm
+ * pollReq [25] PollReqContent, --Polling request
+ * pollRep [26] PollRepContent --Polling response
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(true, tagNo, body);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIConfirmContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIConfirmContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIConfirmContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIConfirmContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Null;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DERNull;
+
+public class PKIConfirmContent
+ extends ASN1Object
+{
+ private ASN1Null val;
+
+ private PKIConfirmContent(ASN1Null val)
+ {
+ this.val = val;
+ }
+
+ public static PKIConfirmContent getInstance(Object o)
+ {
+ if (o == null || o instanceof PKIConfirmContent)
+ {
+ return (PKIConfirmContent)o;
+ }
+
+ if (o instanceof ASN1Null)
+ {
+ return new PKIConfirmContent((ASN1Null)o);
+ }
+
+ throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
+ }
+
+ public PKIConfirmContent()
+ {
+ val = DERNull.INSTANCE;
+ }
+
+ /**
+ *
+ * PKIConfirmContent ::= NULL
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return val;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIFailureInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIFailureInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIFailureInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIFailureInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,126 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.DERBitString;
+
+/**
+ *
+ * PKIFailureInfo ::= BIT STRING {
+ * badAlg (0),
+ * -- unrecognized or unsupported Algorithm Identifier
+ * badMessageCheck (1), -- integrity check failed (e.g., signature did not verify)
+ * badRequest (2),
+ * -- transaction not permitted or supported
+ * badTime (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+ * badCertId (4), -- no certificate could be found matching the provided criteria
+ * badDataFormat (5),
+ * -- the data submitted has the wrong format
+ * wrongAuthority (6), -- the authority indicated in the request is different from the one creating the response token
+ * incorrectData (7), -- the requester's data is incorrect (for notary services)
+ * missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
+ * badPOP (9) -- the proof-of-possession failed
+ * certRevoked (10),
+ * certConfirmed (11),
+ * wrongIntegrity (12),
+ * badRecipientNonce (13),
+ * timeNotAvailable (14),
+ * -- the TSA's time source is not available
+ * unacceptedPolicy (15),
+ * -- the requested TSA policy is not supported by the TSA
+ * unacceptedExtension (16),
+ * -- the requested extension is not supported by the TSA
+ * addInfoNotAvailable (17)
+ * -- the additional information requested could not be understood
+ * -- or is not available
+ * badSenderNonce (18),
+ * badCertTemplate (19),
+ * signerNotTrusted (20),
+ * transactionIdInUse (21),
+ * unsupportedVersion (22),
+ * notAuthorized (23),
+ * systemUnavail (24),
+ * systemFailure (25),
+ * -- the request cannot be handled due to system failure
+ * duplicateCertReq (26)
+ *
+ */
+public class PKIFailureInfo
+ extends DERBitString
+{
+ public static final int badAlg = (1 << 7); // unrecognized or unsupported Algorithm Identifier
+ public static final int badMessageCheck = (1 << 6); // integrity check failed (e.g., signature did not verify)
+ public static final int badRequest = (1 << 5);
+ public static final int badTime = (1 << 4); // -- messageTime was not sufficiently close to the system time, as defined by local policy
+ public static final int badCertId = (1 << 3); // no certificate could be found matching the provided criteria
+ public static final int badDataFormat = (1 << 2);
+ public static final int wrongAuthority = (1 << 1); // the authority indicated in the request is different from the one creating the response token
+ public static final int incorrectData = 1; // the requester's data is incorrect (for notary services)
+ public static final int missingTimeStamp = (1 << 15); // when the timestamp is missing but should be there (by policy)
+ public static final int badPOP = (1 << 14); // the proof-of-possession failed
+ public static final int certRevoked = (1 << 13);
+ public static final int certConfirmed = (1 << 12);
+ public static final int wrongIntegrity = (1 << 11);
+ public static final int badRecipientNonce = (1 << 10);
+ public static final int timeNotAvailable = (1 << 9); // the TSA's time source is not available
+ public static final int unacceptedPolicy = (1 << 8); // the requested TSA policy is not supported by the TSA
+ public static final int unacceptedExtension = (1 << 23); //the requested extension is not supported by the TSA
+ public static final int addInfoNotAvailable = (1 << 22); //the additional information requested could not be understood or is not available
+ public static final int badSenderNonce = (1 << 21);
+ public static final int badCertTemplate = (1 << 20);
+ public static final int signerNotTrusted = (1 << 19);
+ public static final int transactionIdInUse = (1 << 18);
+ public static final int unsupportedVersion = (1 << 17);
+ public static final int notAuthorized = (1 << 16);
+ public static final int systemUnavail = (1 << 31);
+ public static final int systemFailure = (1 << 30); //the request cannot be handled due to system failure
+ public static final int duplicateCertReq = (1 << 29);
+
+ /** @deprecated use lower case version */
+ public static final int BAD_ALG = badAlg; // unrecognized or unsupported Algorithm Identifier
+ /** @deprecated use lower case version */
+ public static final int BAD_MESSAGE_CHECK = badMessageCheck;
+ /** @deprecated use lower case version */
+ public static final int BAD_REQUEST = badRequest; // transaction not permitted or supported
+ /** @deprecated use lower case version */
+ public static final int BAD_TIME = badTime;
+ /** @deprecated use lower case version */
+ public static final int BAD_CERT_ID = badCertId;
+ /** @deprecated use lower case version */
+ public static final int BAD_DATA_FORMAT = badDataFormat; // the data submitted has the wrong format
+ /** @deprecated use lower case version */
+ public static final int WRONG_AUTHORITY = wrongAuthority;
+ /** @deprecated use lower case version */
+ public static final int INCORRECT_DATA = incorrectData;
+ /** @deprecated use lower case version */
+ public static final int MISSING_TIME_STAMP = missingTimeStamp;
+ /** @deprecated use lower case version */
+ public static final int BAD_POP = badPOP;
+ /** @deprecated use lower case version */
+ public static final int TIME_NOT_AVAILABLE = timeNotAvailable;
+ /** @deprecated use lower case version */
+ public static final int UNACCEPTED_POLICY = unacceptedPolicy;
+ /** @deprecated use lower case version */
+ public static final int UNACCEPTED_EXTENSION = unacceptedExtension;
+ /** @deprecated use lower case version */
+ public static final int ADD_INFO_NOT_AVAILABLE = addInfoNotAvailable;
+ /** @deprecated use lower case version */
+ public static final int SYSTEM_FAILURE = systemFailure;
+ /**
+ * Basic constructor.
+ */
+ public PKIFailureInfo(
+ int info)
+ {
+ super(getBytes(info), getPadBits(info));
+ }
+
+ public PKIFailureInfo(
+ DERBitString info)
+ {
+ super(info.getBytes(), info.getPadBits());
+ }
+
+ public String toString()
+ {
+ return "PKIFailureInfo: 0x" + Integer.toHexString(this.intValue());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIFreeText.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIFreeText.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIFreeText.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIFreeText.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,114 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERUTF8String;
+
+public class PKIFreeText
+ extends ASN1Object
+{
+ ASN1Sequence strings;
+
+ public static PKIFreeText getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static PKIFreeText getInstance(
+ Object obj)
+ {
+ if (obj instanceof PKIFreeText)
+ {
+ return (PKIFreeText)obj;
+ }
+ else if (obj != null)
+ {
+ return new PKIFreeText(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private PKIFreeText(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ while (e.hasMoreElements())
+ {
+ if (!(e.nextElement() instanceof DERUTF8String))
+ {
+ throw new IllegalArgumentException("attempt to insert non UTF8 STRING into PKIFreeText");
+ }
+ }
+
+ strings = seq;
+ }
+
+ public PKIFreeText(
+ DERUTF8String p)
+ {
+ strings = new DERSequence(p);
+ }
+
+ public PKIFreeText(
+ String p)
+ {
+ this(new DERUTF8String(p));
+ }
+
+ public PKIFreeText(
+ DERUTF8String[] strs)
+ {
+ strings = new DERSequence(strs);
+ }
+
+ public PKIFreeText(
+ String[] strs)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < strs.length; i++) {
+ v.add(new DERUTF8String(strs[i]));
+ }
+ strings = new DERSequence(v);
+ }
+
+ /**
+ * Return the number of string elements present.
+ *
+ * @return number of elements present.
+ */
+ public int size()
+ {
+ return strings.size();
+ }
+
+ /**
+ * Return the UTF8STRING at index i.
+ *
+ * @param i index of the string of interest
+ * @return the string at index i.
+ */
+ public DERUTF8String getStringAt(
+ int i)
+ {
+ return (DERUTF8String)strings.getObjectAt(i);
+ }
+
+ /**
+ *
+ * PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return strings;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIHeader.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIHeader.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIHeader.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIHeader.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,257 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERGeneralizedTime;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import pdftk.org.bouncycastle.asn1.x509.GeneralName;
+
+public class PKIHeader
+ extends ASN1Object
+{
+ /**
+ * Value for a "null" recipient or sender.
+ */
+ public static final GeneralName NULL_NAME = new GeneralName(X500Name.getInstance(new DERSequence()));
+
+ public static final int CMP_1999 = 1;
+ public static final int CMP_2000 = 2;
+
+ private ASN1Integer pvno;
+ private GeneralName sender;
+ private GeneralName recipient;
+ private DERGeneralizedTime messageTime;
+ private AlgorithmIdentifier protectionAlg;
+ private ASN1OctetString senderKID; // KeyIdentifier
+ private ASN1OctetString recipKID; // KeyIdentifier
+ private ASN1OctetString transactionID;
+ private ASN1OctetString senderNonce;
+ private ASN1OctetString recipNonce;
+ private PKIFreeText freeText;
+ private ASN1Sequence generalInfo;
+
+ private PKIHeader(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ pvno = ASN1Integer.getInstance(en.nextElement());
+ sender = GeneralName.getInstance(en.nextElement());
+ recipient = GeneralName.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
+
+ switch (tObj.getTagNo())
+ {
+ case 0:
+ messageTime = DERGeneralizedTime.getInstance(tObj, true);
+ break;
+ case 1:
+ protectionAlg = AlgorithmIdentifier.getInstance(tObj, true);
+ break;
+ case 2:
+ senderKID = ASN1OctetString.getInstance(tObj, true);
+ break;
+ case 3:
+ recipKID = ASN1OctetString.getInstance(tObj, true);
+ break;
+ case 4:
+ transactionID = ASN1OctetString.getInstance(tObj, true);
+ break;
+ case 5:
+ senderNonce = ASN1OctetString.getInstance(tObj, true);
+ break;
+ case 6:
+ recipNonce = ASN1OctetString.getInstance(tObj, true);
+ break;
+ case 7:
+ freeText = PKIFreeText.getInstance(tObj, true);
+ break;
+ case 8:
+ generalInfo = ASN1Sequence.getInstance(tObj, true);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag number: " + tObj.getTagNo());
+ }
+ }
+ }
+
+ public static PKIHeader getInstance(Object o)
+ {
+ if (o instanceof PKIHeader)
+ {
+ return (PKIHeader)o;
+ }
+
+ if (o != null)
+ {
+ return new PKIHeader(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PKIHeader(
+ int pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this(new ASN1Integer(pvno), sender, recipient);
+ }
+
+ private PKIHeader(
+ ASN1Integer pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this.pvno = pvno;
+ this.sender = sender;
+ this.recipient = recipient;
+ }
+
+ public ASN1Integer getPvno()
+ {
+ return pvno;
+ }
+
+ public GeneralName getSender()
+ {
+ return sender;
+ }
+
+ public GeneralName getRecipient()
+ {
+ return recipient;
+ }
+
+ public DERGeneralizedTime getMessageTime()
+ {
+ return messageTime;
+ }
+
+ public AlgorithmIdentifier getProtectionAlg()
+ {
+ return protectionAlg;
+ }
+
+ public ASN1OctetString getSenderKID()
+ {
+ return senderKID;
+ }
+
+ public ASN1OctetString getRecipKID()
+ {
+ return recipKID;
+ }
+
+ public ASN1OctetString getTransactionID()
+ {
+ return transactionID;
+ }
+
+ public ASN1OctetString getSenderNonce()
+ {
+ return senderNonce;
+ }
+
+ public ASN1OctetString getRecipNonce()
+ {
+ return recipNonce;
+ }
+
+ public PKIFreeText getFreeText()
+ {
+ return freeText;
+ }
+
+ public InfoTypeAndValue[] getGeneralInfo()
+ {
+ if (generalInfo == null) {
+ return null;
+ }
+ InfoTypeAndValue[] results = new InfoTypeAndValue[generalInfo.size()];
+ for (int i = 0; i < results.length; i++) {
+ results[i]
+ = InfoTypeAndValue.getInstance(generalInfo.getObjectAt(i));
+ }
+ return results;
+ }
+
+ /**
+ *
+ * PKIHeader ::= SEQUENCE {
+ * pvno INTEGER { cmp1999(1), cmp2000(2) },
+ * sender GeneralName,
+ * -- identifies the sender
+ * recipient GeneralName,
+ * -- identifies the intended recipient
+ * messageTime [0] GeneralizedTime OPTIONAL,
+ * -- time of production of this message (used when sender
+ * -- believes that the transport will be "suitable"; i.e.,
+ * -- that the time will still be meaningful upon receipt)
+ * protectionAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used for calculation of protection bits
+ * senderKID [2] KeyIdentifier OPTIONAL,
+ * recipKID [3] KeyIdentifier OPTIONAL,
+ * -- to identify specific keys used for protection
+ * transactionID [4] OCTET STRING OPTIONAL,
+ * -- identifies the transaction; i.e., this will be the same in
+ * -- corresponding request, response, certConf, and PKIConf
+ * -- messages
+ * senderNonce [5] OCTET STRING OPTIONAL,
+ * recipNonce [6] OCTET STRING OPTIONAL,
+ * -- nonces used to provide replay protection, senderNonce
+ * -- is inserted by the creator of this message; recipNonce
+ * -- is a nonce previously inserted in a related message by
+ * -- the intended recipient of this message
+ * freeText [7] PKIFreeText OPTIONAL,
+ * -- this may be used to indicate context-specific instructions
+ * -- (this field is intended for human consumption)
+ * generalInfo [8] SEQUENCE SIZE (1..MAX) OF
+ * InfoTypeAndValue OPTIONAL
+ * -- this may be used to convey context-specific information
+ * -- (this field not primarily intended for human consumption)
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pvno);
+ v.add(sender);
+ v.add(recipient);
+ addOptional(v, 0, messageTime);
+ addOptional(v, 1, protectionAlg);
+ addOptional(v, 2, senderKID);
+ addOptional(v, 3, recipKID);
+ addOptional(v, 4, transactionID);
+ addOptional(v, 5, senderNonce);
+ addOptional(v, 6, recipNonce);
+ addOptional(v, 7, freeText);
+ addOptional(v, 8, generalInfo);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIHeaderBuilder.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIHeaderBuilder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIHeaderBuilder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIHeaderBuilder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,254 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERGeneralizedTime;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import pdftk.org.bouncycastle.asn1.x509.GeneralName;
+
+public class PKIHeaderBuilder
+{
+ private ASN1Integer pvno;
+ private GeneralName sender;
+ private GeneralName recipient;
+ private ASN1GeneralizedTime messageTime;
+ private AlgorithmIdentifier protectionAlg;
+ private ASN1OctetString senderKID; // KeyIdentifier
+ private ASN1OctetString recipKID; // KeyIdentifier
+ private ASN1OctetString transactionID;
+ private ASN1OctetString senderNonce;
+ private ASN1OctetString recipNonce;
+ private PKIFreeText freeText;
+ private ASN1Sequence generalInfo;
+
+ public PKIHeaderBuilder(
+ int pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this(new ASN1Integer(pvno), sender, recipient);
+ }
+
+ private PKIHeaderBuilder(
+ ASN1Integer pvno,
+ GeneralName sender,
+ GeneralName recipient)
+ {
+ this.pvno = pvno;
+ this.sender = sender;
+ this.recipient = recipient;
+ }
+
+ /**
+ * @deprecated use ASN1GeneralizedTime
+ */
+ public PKIHeaderBuilder setMessageTime(DERGeneralizedTime time)
+ {
+ messageTime = ASN1GeneralizedTime.getInstance(time);
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setMessageTime(ASN1GeneralizedTime time)
+ {
+ messageTime = time;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setProtectionAlg(AlgorithmIdentifier aid)
+ {
+ protectionAlg = aid;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setSenderKID(byte[] kid)
+ {
+ return setSenderKID(kid == null ? null : new DEROctetString(kid));
+ }
+
+ public PKIHeaderBuilder setSenderKID(ASN1OctetString kid)
+ {
+ senderKID = kid;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setRecipKID(byte[] kid)
+ {
+ return setRecipKID(kid == null ? null : new DEROctetString(kid));
+ }
+
+ public PKIHeaderBuilder setRecipKID(DEROctetString kid)
+ {
+ recipKID = kid;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setTransactionID(byte[] tid)
+ {
+ return setTransactionID(tid == null ? null : new DEROctetString(tid));
+ }
+
+ public PKIHeaderBuilder setTransactionID(ASN1OctetString tid)
+ {
+ transactionID = tid;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setSenderNonce(byte[] nonce)
+ {
+ return setSenderNonce(nonce == null ? null : new DEROctetString(nonce));
+ }
+
+ public PKIHeaderBuilder setSenderNonce(ASN1OctetString nonce)
+ {
+ senderNonce = nonce;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setRecipNonce(byte[] nonce)
+ {
+ return setRecipNonce(nonce == null ? null : new DEROctetString(nonce));
+ }
+
+ public PKIHeaderBuilder setRecipNonce(ASN1OctetString nonce)
+ {
+ recipNonce = nonce;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setFreeText(PKIFreeText text)
+ {
+ freeText = text;
+
+ return this;
+ }
+
+ public PKIHeaderBuilder setGeneralInfo(InfoTypeAndValue genInfo)
+ {
+ return setGeneralInfo(makeGeneralInfoSeq(genInfo));
+ }
+
+ public PKIHeaderBuilder setGeneralInfo(InfoTypeAndValue[] genInfos)
+ {
+ return setGeneralInfo(makeGeneralInfoSeq(genInfos));
+ }
+
+ public PKIHeaderBuilder setGeneralInfo(ASN1Sequence seqOfInfoTypeAndValue)
+ {
+ generalInfo = seqOfInfoTypeAndValue;
+
+ return this;
+ }
+
+ private static ASN1Sequence makeGeneralInfoSeq(
+ InfoTypeAndValue generalInfo)
+ {
+ return new DERSequence(generalInfo);
+ }
+
+ private static ASN1Sequence makeGeneralInfoSeq(
+ InfoTypeAndValue[] generalInfos)
+ {
+ ASN1Sequence genInfoSeq = null;
+ if (generalInfos != null)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < generalInfos.length; i++)
+ {
+ v.add(generalInfos[i]);
+ }
+ genInfoSeq = new DERSequence(v);
+ }
+ return genInfoSeq;
+ }
+
+ /**
+ *
+ * PKIHeader ::= SEQUENCE {
+ * pvno INTEGER { cmp1999(1), cmp2000(2) },
+ * sender GeneralName,
+ * -- identifies the sender
+ * recipient GeneralName,
+ * -- identifies the intended recipient
+ * messageTime [0] GeneralizedTime OPTIONAL,
+ * -- time of production of this message (used when sender
+ * -- believes that the transport will be "suitable"; i.e.,
+ * -- that the time will still be meaningful upon receipt)
+ * protectionAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used for calculation of protection bits
+ * senderKID [2] KeyIdentifier OPTIONAL,
+ * recipKID [3] KeyIdentifier OPTIONAL,
+ * -- to identify specific keys used for protection
+ * transactionID [4] OCTET STRING OPTIONAL,
+ * -- identifies the transaction; i.e., this will be the same in
+ * -- corresponding request, response, certConf, and PKIConf
+ * -- messages
+ * senderNonce [5] OCTET STRING OPTIONAL,
+ * recipNonce [6] OCTET STRING OPTIONAL,
+ * -- nonces used to provide replay protection, senderNonce
+ * -- is inserted by the creator of this message; recipNonce
+ * -- is a nonce previously inserted in a related message by
+ * -- the intended recipient of this message
+ * freeText [7] PKIFreeText OPTIONAL,
+ * -- this may be used to indicate context-specific instructions
+ * -- (this field is intended for human consumption)
+ * generalInfo [8] SEQUENCE SIZE (1..MAX) OF
+ * InfoTypeAndValue OPTIONAL
+ * -- this may be used to convey context-specific information
+ * -- (this field not primarily intended for human consumption)
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public PKIHeader build()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pvno);
+ v.add(sender);
+ v.add(recipient);
+ addOptional(v, 0, messageTime);
+ addOptional(v, 1, protectionAlg);
+ addOptional(v, 2, senderKID);
+ addOptional(v, 3, recipKID);
+ addOptional(v, 4, transactionID);
+ addOptional(v, 5, senderNonce);
+ addOptional(v, 6, recipNonce);
+ addOptional(v, 7, freeText);
+ addOptional(v, 8, generalInfo);
+
+ messageTime = null;
+ protectionAlg = null;
+ senderKID = null;
+ recipKID = null;
+ transactionID = null;
+ senderNonce = null;
+ recipNonce = null;
+ freeText = null;
+ generalInfo = null;
+
+ return PKIHeader.getInstance(new DERSequence(v));
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIMessage.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIMessage.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIMessage.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIMessage.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,163 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class PKIMessage
+ extends ASN1Object
+{
+ private PKIHeader header;
+ private PKIBody body;
+ private DERBitString protection;
+ private ASN1Sequence extraCerts;
+
+ private PKIMessage(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ header = PKIHeader.getInstance(en.nextElement());
+ body = PKIBody.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
+
+ if (tObj.getTagNo() == 0)
+ {
+ protection = DERBitString.getInstance(tObj, true);
+ }
+ else
+ {
+ extraCerts = ASN1Sequence.getInstance(tObj, true);
+ }
+ }
+ }
+
+ public static PKIMessage getInstance(Object o)
+ {
+ if (o instanceof PKIMessage)
+ {
+ return (PKIMessage)o;
+ }
+ else if (o != null)
+ {
+ return new PKIMessage(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new PKIMessage.
+ *
+ * @param header message header
+ * @param body message body
+ * @param protection message protection (may be null)
+ * @param extraCerts extra certificates (may be null)
+ */
+ public PKIMessage(
+ PKIHeader header,
+ PKIBody body,
+ DERBitString protection,
+ CMPCertificate[] extraCerts)
+ {
+ this.header = header;
+ this.body = body;
+ this.protection = protection;
+ if (extraCerts != null) {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < extraCerts.length; i++) {
+ v.add(extraCerts[i]);
+ }
+ this.extraCerts = new DERSequence(v);
+ }
+ }
+
+ public PKIMessage(
+ PKIHeader header,
+ PKIBody body,
+ DERBitString protection)
+ {
+ this(header, body, protection, null);
+ }
+
+ public PKIMessage(
+ PKIHeader header,
+ PKIBody body)
+ {
+ this(header, body, null, null);
+ }
+
+ public PKIHeader getHeader()
+ {
+ return header;
+ }
+
+ public PKIBody getBody()
+ {
+ return body;
+ }
+
+ public DERBitString getProtection()
+ {
+ return protection;
+ }
+
+ public CMPCertificate[] getExtraCerts()
+ {
+ if (extraCerts == null)
+ {
+ return null;
+ }
+
+ CMPCertificate[] results = new CMPCertificate[extraCerts.size()];
+
+ for (int i = 0; i < results.length; i++)
+ {
+ results[i] = CMPCertificate.getInstance(extraCerts.getObjectAt(i));
+ }
+ return results;
+ }
+
+ /**
+ *
+ * PKIMessage ::= SEQUENCE {
+ * header PKIHeader,
+ * body PKIBody,
+ * protection [0] PKIProtection OPTIONAL,
+ * extraCerts [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+ * OPTIONAL
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(header);
+ v.add(body);
+
+ addOptional(v, 0, protection);
+ addOptional(v, 1, extraCerts);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIMessages.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIMessages.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIMessages.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIMessages.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,71 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class PKIMessages
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private PKIMessages(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PKIMessages getInstance(Object o)
+ {
+ if (o instanceof PKIMessages)
+ {
+ return (PKIMessages)o;
+ }
+
+ if (o != null)
+ {
+ return new PKIMessages(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PKIMessages(PKIMessage msg)
+ {
+ content = new DERSequence(msg);
+ }
+
+ public PKIMessages(PKIMessage[] msgs)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < msgs.length; i++)
+ {
+ v.add(msgs[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public PKIMessage[] toPKIMessageArray()
+ {
+ PKIMessage[] result = new PKIMessage[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = PKIMessage.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * PKIMessages ::= SEQUENCE SIZE (1..MAX) OF PKIMessage
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIStatus.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIStatus.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIStatus.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIStatus.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,64 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+
+public class PKIStatus
+ extends ASN1Object
+{
+ public static final int GRANTED = 0;
+ public static final int GRANTED_WITH_MODS = 1;
+ public static final int REJECTION = 2;
+ public static final int WAITING = 3;
+ public static final int REVOCATION_WARNING = 4;
+ public static final int REVOCATION_NOTIFICATION = 5;
+ public static final int KEY_UPDATE_WARNING = 6;
+
+ public static final PKIStatus granted = new PKIStatus(GRANTED);
+ public static final PKIStatus grantedWithMods = new PKIStatus(GRANTED_WITH_MODS);
+ public static final PKIStatus rejection = new PKIStatus(REJECTION);
+ public static final PKIStatus waiting = new PKIStatus(WAITING);
+ public static final PKIStatus revocationWarning = new PKIStatus(REVOCATION_WARNING);
+ public static final PKIStatus revocationNotification = new PKIStatus(REVOCATION_NOTIFICATION);
+ public static final PKIStatus keyUpdateWaiting = new PKIStatus(KEY_UPDATE_WARNING);
+
+ private ASN1Integer value;
+
+ private PKIStatus(int value)
+ {
+ this(new ASN1Integer(value));
+ }
+
+ private PKIStatus(ASN1Integer value)
+ {
+ this.value = value;
+ }
+
+ public static PKIStatus getInstance(Object o)
+ {
+ if (o instanceof PKIStatus)
+ {
+ return (PKIStatus)o;
+ }
+
+ if (o != null)
+ {
+ return new PKIStatus(ASN1Integer.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public BigInteger getValue()
+ {
+ return value.getValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return value;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIStatusInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIStatusInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PKIStatusInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PKIStatusInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,165 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class PKIStatusInfo
+ extends ASN1Object
+{
+ ASN1Integer status;
+ PKIFreeText statusString;
+ DERBitString failInfo;
+
+ public static PKIStatusInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static PKIStatusInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof PKIStatusInfo)
+ {
+ return (PKIStatusInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new PKIStatusInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private PKIStatusInfo(
+ ASN1Sequence seq)
+ {
+ this.status = ASN1Integer.getInstance(seq.getObjectAt(0));
+
+ this.statusString = null;
+ this.failInfo = null;
+
+ if (seq.size() > 2)
+ {
+ this.statusString = PKIFreeText.getInstance(seq.getObjectAt(1));
+ this.failInfo = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+ else if (seq.size() > 1)
+ {
+ Object obj = seq.getObjectAt(1);
+ if (obj instanceof DERBitString)
+ {
+ this.failInfo = DERBitString.getInstance(obj);
+ }
+ else
+ {
+ this.statusString = PKIFreeText.getInstance(obj);
+ }
+ }
+ }
+
+ /**
+ * @param status
+ */
+ public PKIStatusInfo(PKIStatus status)
+ {
+ this.status = ASN1Integer.getInstance(status.toASN1Primitive());
+ }
+
+ /**
+ *
+ * @param status
+ * @param statusString
+ */
+ public PKIStatusInfo(
+ PKIStatus status,
+ PKIFreeText statusString)
+ {
+ this.status = ASN1Integer.getInstance(status.toASN1Primitive());
+ this.statusString = statusString;
+ }
+
+ public PKIStatusInfo(
+ PKIStatus status,
+ PKIFreeText statusString,
+ PKIFailureInfo failInfo)
+ {
+ this.status = ASN1Integer.getInstance(status.toASN1Primitive());;
+ this.statusString = statusString;
+ this.failInfo = failInfo;
+ }
+
+ public BigInteger getStatus()
+ {
+ return status.getValue();
+ }
+
+ public PKIFreeText getStatusString()
+ {
+ return statusString;
+ }
+
+ public DERBitString getFailInfo()
+ {
+ return failInfo;
+ }
+
+ /**
+ *
+ * PKIStatusInfo ::= SEQUENCE {
+ * status PKIStatus, (INTEGER)
+ * statusString PKIFreeText OPTIONAL,
+ * failInfo PKIFailureInfo OPTIONAL (BIT STRING)
+ * }
+ *
+ * PKIStatus:
+ * granted (0), -- you got exactly what you asked for
+ * grantedWithMods (1), -- you got something like what you asked for
+ * rejection (2), -- you don't get it, more information elsewhere in the message
+ * waiting (3), -- the request body part has not yet been processed, expect to hear more later
+ * revocationWarning (4), -- this message contains a warning that a revocation is imminent
+ * revocationNotification (5), -- notification that a revocation has occurred
+ * keyUpdateWarning (6) -- update already done for the oldCertId specified in CertReqMsg
+ *
+ * PKIFailureInfo:
+ * badAlg (0), -- unrecognized or unsupported Algorithm Identifier
+ * badMessageCheck (1), -- integrity check failed (e.g., signature did not verify)
+ * badRequest (2), -- transaction not permitted or supported
+ * badTime (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+ * badCertId (4), -- no certificate could be found matching the provided criteria
+ * badDataFormat (5), -- the data submitted has the wrong format
+ * wrongAuthority (6), -- the authority indicated in the request is different from the one creating the response token
+ * incorrectData (7), -- the requester's data is incorrect (for notary services)
+ * missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
+ * badPOP (9) -- the proof-of-possession failed
+ *
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(status);
+
+ if (statusString != null)
+ {
+ v.add(statusString);
+ }
+
+ if (failInfo!= null)
+ {
+ v.add(failInfo);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/POPODecKeyChallContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/POPODecKeyChallContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/POPODecKeyChallContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/POPODecKeyChallContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,54 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+
+public class POPODecKeyChallContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private POPODecKeyChallContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static POPODecKeyChallContent getInstance(Object o)
+ {
+ if (o instanceof POPODecKeyChallContent)
+ {
+ return (POPODecKeyChallContent)o;
+ }
+
+ if (o != null)
+ {
+ return new POPODecKeyChallContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public Challenge[] toChallengeArray()
+ {
+ Challenge[] result = new Challenge[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = Challenge.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * POPODecKeyChallContent ::= SEQUENCE OF Challenge
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/POPODecKeyRespContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/POPODecKeyRespContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/POPODecKeyRespContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/POPODecKeyRespContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,55 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+
+public class POPODecKeyRespContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private POPODecKeyRespContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static POPODecKeyRespContent getInstance(Object o)
+ {
+ if (o instanceof POPODecKeyRespContent)
+ {
+ return (POPODecKeyRespContent)o;
+ }
+
+ if (o != null)
+ {
+ return new POPODecKeyRespContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer[] toASN1IntegerArray()
+ {
+ ASN1Integer[] result = new ASN1Integer[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = ASN1Integer.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * POPODecKeyRespContent ::= SEQUENCE OF INTEGER
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PollRepContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PollRepContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PollRepContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PollRepContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,119 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class PollRepContent
+ extends ASN1Object
+{
+ private ASN1Integer[] certReqId;
+ private ASN1Integer[] checkAfter;
+ private PKIFreeText[] reason;
+
+ private PollRepContent(ASN1Sequence seq)
+ {
+ certReqId = new ASN1Integer[seq.size()];
+ checkAfter = new ASN1Integer[seq.size()];
+ reason = new PKIFreeText[seq.size()];
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(seq.getObjectAt(i));
+
+ certReqId[i] = ASN1Integer.getInstance(s.getObjectAt(0));
+ checkAfter[i] = ASN1Integer.getInstance(s.getObjectAt(1));
+
+ if (s.size() > 2)
+ {
+ reason[i] = PKIFreeText.getInstance(s.getObjectAt(2));
+ }
+ }
+ }
+
+ public static PollRepContent getInstance(Object o)
+ {
+ if (o instanceof PollRepContent)
+ {
+ return (PollRepContent)o;
+ }
+
+ if (o != null)
+ {
+ return new PollRepContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PollRepContent(ASN1Integer certReqId, ASN1Integer checkAfter)
+ {
+ this(certReqId, checkAfter, null);
+ }
+
+ public PollRepContent(ASN1Integer certReqId, ASN1Integer checkAfter, PKIFreeText reason)
+ {
+ this.certReqId = new ASN1Integer[1];
+ this.checkAfter = new ASN1Integer[1];
+ this.reason = new PKIFreeText[1];
+
+ this.certReqId[0] = certReqId;
+ this.checkAfter[0] = checkAfter;
+ this.reason[0] = reason;
+ }
+
+ public int size()
+ {
+ return certReqId.length;
+ }
+
+ public ASN1Integer getCertReqId(int index)
+ {
+ return certReqId[index];
+ }
+
+ public ASN1Integer getCheckAfter(int index)
+ {
+ return checkAfter[index];
+ }
+
+ public PKIFreeText getReason(int index)
+ {
+ return reason[index];
+ }
+
+ /**
+ *
+ * PollRepContent ::= SEQUENCE OF SEQUENCE {
+ * certReqId INTEGER,
+ * checkAfter INTEGER, -- time in seconds
+ * reason PKIFreeText OPTIONAL
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector outer = new ASN1EncodableVector();
+
+ for (int i = 0; i != certReqId.length; i++)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certReqId[i]);
+ v.add(checkAfter[i]);
+
+ if (reason[i] != null)
+ {
+ v.add(reason[i]);
+ }
+
+ outer.add(new DERSequence(v));
+ }
+
+ return new DERSequence(outer);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PollReqContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PollReqContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/PollReqContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/PollReqContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,80 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class PollReqContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private PollReqContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static PollReqContent getInstance(Object o)
+ {
+ if (o instanceof PollReqContent)
+ {
+ return (PollReqContent)o;
+ }
+
+ if (o != null)
+ {
+ return new PollReqContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * Create a pollReqContent for a single certReqId.
+ *
+ * @param certReqId the certificate request ID.
+ */
+ public PollReqContent(ASN1Integer certReqId)
+ {
+ this(new DERSequence(new DERSequence(certReqId)));
+ }
+
+ public ASN1Integer[][] getCertReqIds()
+ {
+ ASN1Integer[][] result = new ASN1Integer[content.size()][];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = sequenceToASN1IntegerArray((ASN1Sequence)content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ private static ASN1Integer[] sequenceToASN1IntegerArray(ASN1Sequence seq)
+ {
+ ASN1Integer[] result = new ASN1Integer[seq.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = ASN1Integer.getInstance(seq.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * PollReqContent ::= SEQUENCE OF SEQUENCE {
+ * certReqId INTEGER
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/ProtectedPart.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/ProtectedPart.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/ProtectedPart.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/ProtectedPart.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,70 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class ProtectedPart
+ extends ASN1Object
+{
+ private PKIHeader header;
+ private PKIBody body;
+
+ private ProtectedPart(ASN1Sequence seq)
+ {
+ header = PKIHeader.getInstance(seq.getObjectAt(0));
+ body = PKIBody.getInstance(seq.getObjectAt(1));
+ }
+
+ public static ProtectedPart getInstance(Object o)
+ {
+ if (o instanceof ProtectedPart)
+ {
+ return (ProtectedPart)o;
+ }
+
+ if (o != null)
+ {
+ return new ProtectedPart(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ProtectedPart(PKIHeader header, PKIBody body)
+ {
+ this.header = header;
+ this.body = body;
+ }
+
+ public PKIHeader getHeader()
+ {
+ return header;
+ }
+
+ public PKIBody getBody()
+ {
+ return body;
+ }
+
+ /**
+ *
+ * ProtectedPart ::= SEQUENCE {
+ * header PKIHeader,
+ * body PKIBody
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(header);
+ v.add(body);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/RevAnnContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/RevAnnContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/RevAnnContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/RevAnnContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,103 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.crmf.CertId;
+import pdftk.org.bouncycastle.asn1.x509.Extensions;
+
+public class RevAnnContent
+ extends ASN1Object
+{
+ private PKIStatus status;
+ private CertId certId;
+ private ASN1GeneralizedTime willBeRevokedAt;
+ private ASN1GeneralizedTime badSinceDate;
+ private Extensions crlDetails;
+
+ private RevAnnContent(ASN1Sequence seq)
+ {
+ status = PKIStatus.getInstance(seq.getObjectAt(0));
+ certId = CertId.getInstance(seq.getObjectAt(1));
+ willBeRevokedAt = ASN1GeneralizedTime.getInstance(seq.getObjectAt(2));
+ badSinceDate = ASN1GeneralizedTime.getInstance(seq.getObjectAt(3));
+
+ if (seq.size() > 4)
+ {
+ crlDetails = Extensions.getInstance(seq.getObjectAt(4));
+ }
+ }
+
+ public static RevAnnContent getInstance(Object o)
+ {
+ if (o instanceof RevAnnContent)
+ {
+ return (RevAnnContent)o;
+ }
+
+ if (o != null)
+ {
+ return new RevAnnContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PKIStatus getStatus()
+ {
+ return status;
+ }
+
+ public CertId getCertId()
+ {
+ return certId;
+ }
+
+ public ASN1GeneralizedTime getWillBeRevokedAt()
+ {
+ return willBeRevokedAt;
+ }
+
+ public ASN1GeneralizedTime getBadSinceDate()
+ {
+ return badSinceDate;
+ }
+
+ public Extensions getCrlDetails()
+ {
+ return crlDetails;
+ }
+
+ /**
+ *
+ * RevAnnContent ::= SEQUENCE {
+ * status PKIStatus,
+ * certId CertId,
+ * willBeRevokedAt GeneralizedTime,
+ * badSinceDate GeneralizedTime,
+ * crlDetails Extensions OPTIONAL
+ * -- extra CRL details (e.g., crl number, reason, location, etc.)
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(status);
+ v.add(certId);
+ v.add(willBeRevokedAt);
+ v.add(badSinceDate);
+
+ if (crlDetails != null)
+ {
+ v.add(crlDetails);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/RevDetails.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/RevDetails.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/RevDetails.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/RevDetails.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,100 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.crmf.CertTemplate;
+import pdftk.org.bouncycastle.asn1.x509.Extensions;
+import pdftk.org.bouncycastle.asn1.x509.X509Extensions;
+
+public class RevDetails
+ extends ASN1Object
+{
+ private CertTemplate certDetails;
+ private Extensions crlEntryDetails;
+
+ private RevDetails(ASN1Sequence seq)
+ {
+ certDetails = CertTemplate.getInstance(seq.getObjectAt(0));
+ if (seq.size() > 1)
+ {
+ crlEntryDetails = Extensions.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public static RevDetails getInstance(Object o)
+ {
+ if (o instanceof RevDetails)
+ {
+ return (RevDetails)o;
+ }
+
+ if (o != null)
+ {
+ return new RevDetails(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public RevDetails(CertTemplate certDetails)
+ {
+ this.certDetails = certDetails;
+ }
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param certDetails
+ * @param crlEntryDetails
+ */
+ public RevDetails(CertTemplate certDetails, X509Extensions crlEntryDetails)
+ {
+ this.certDetails = certDetails;
+ this.crlEntryDetails = Extensions.getInstance(crlEntryDetails.toASN1Primitive());
+ }
+
+ public RevDetails(CertTemplate certDetails, Extensions crlEntryDetails)
+ {
+ this.certDetails = certDetails;
+ this.crlEntryDetails = crlEntryDetails;
+ }
+
+ public CertTemplate getCertDetails()
+ {
+ return certDetails;
+ }
+
+ public Extensions getCrlEntryDetails()
+ {
+ return crlEntryDetails;
+ }
+
+ /**
+ *
+ * RevDetails ::= SEQUENCE {
+ * certDetails CertTemplate,
+ * -- allows requester to specify as much as they can about
+ * -- the cert. for which revocation is requested
+ * -- (e.g., for cases in which serialNumber is not available)
+ * crlEntryDetails Extensions OPTIONAL
+ * -- requested crlEntryExtensions
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certDetails);
+
+ if (crlEntryDetails != null)
+ {
+ v.add(crlEntryDetails);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/RevRepContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/RevRepContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/RevRepContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/RevRepContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,137 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.crmf.CertId;
+import pdftk.org.bouncycastle.asn1.x509.CertificateList;
+
+public class RevRepContent
+ extends ASN1Object
+{
+ private ASN1Sequence status;
+ private ASN1Sequence revCerts;
+ private ASN1Sequence crls;
+
+ private RevRepContent(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ status = ASN1Sequence.getInstance(en.nextElement());
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(en.nextElement());
+
+ if (tObj.getTagNo() == 0)
+ {
+ revCerts = ASN1Sequence.getInstance(tObj, true);
+ }
+ else
+ {
+ crls = ASN1Sequence.getInstance(tObj, true);
+ }
+ }
+ }
+
+ public static RevRepContent getInstance(Object o)
+ {
+ if (o instanceof RevRepContent)
+ {
+ return (RevRepContent)o;
+ }
+
+ if (o != null)
+ {
+ return new RevRepContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public PKIStatusInfo[] getStatus()
+ {
+ PKIStatusInfo[] results = new PKIStatusInfo[status.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = PKIStatusInfo.getInstance(status.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ public CertId[] getRevCerts()
+ {
+ if (revCerts == null)
+ {
+ return null;
+ }
+
+ CertId[] results = new CertId[revCerts.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CertId.getInstance(revCerts.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ public CertificateList[] getCrls()
+ {
+ if (crls == null)
+ {
+ return null;
+ }
+
+ CertificateList[] results = new CertificateList[crls.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = CertificateList.getInstance(crls.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ /**
+ *
+ * RevRepContent ::= SEQUENCE {
+ * status SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
+ * -- in same order as was sent in RevReqContent
+ * revCerts [0] SEQUENCE SIZE (1..MAX) OF CertId OPTIONAL,
+ * -- IDs for which revocation was requested
+ * -- (same order as status)
+ * crls [1] SEQUENCE SIZE (1..MAX) OF CertificateList OPTIONAL
+ * -- the resulting CRLs (there may be more than one)
+ * }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(status);
+
+ addOptional(v, 0, revCerts);
+ addOptional(v, 1, crls);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(true, tagNo, obj));
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/RevRepContentBuilder.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/RevRepContentBuilder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/RevRepContentBuilder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/RevRepContentBuilder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,59 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.crmf.CertId;
+import pdftk.org.bouncycastle.asn1.x509.CertificateList;
+
+public class RevRepContentBuilder
+{
+ private ASN1EncodableVector status = new ASN1EncodableVector();
+ private ASN1EncodableVector revCerts = new ASN1EncodableVector();
+ private ASN1EncodableVector crls = new ASN1EncodableVector();
+
+ public RevRepContentBuilder add(PKIStatusInfo status)
+ {
+ this.status.add(status);
+
+ return this;
+ }
+
+ public RevRepContentBuilder add(PKIStatusInfo status, CertId certId)
+ {
+ if (this.status.size() != this.revCerts.size())
+ {
+ throw new IllegalStateException("status and revCerts sequence must be in common order");
+ }
+ this.status.add(status);
+ this.revCerts.add(certId);
+
+ return this;
+ }
+
+ public RevRepContentBuilder addCrl(CertificateList crl)
+ {
+ this.crls.add(crl);
+
+ return this;
+ }
+
+ public RevRepContent build()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new DERSequence(status));
+
+ if (revCerts.size() != 0)
+ {
+ v.add(new DERTaggedObject(true, 0, new DERSequence(revCerts)));
+ }
+
+ if (crls.size() != 0)
+ {
+ v.add(new DERTaggedObject(true, 1, new DERSequence(crls)));
+ }
+
+ return RevRepContent.getInstance(new DERSequence(v));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/RevReqContent.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/RevReqContent.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/RevReqContent.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/RevReqContent.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,73 @@
+package pdftk.org.bouncycastle.asn1.cmp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class RevReqContent
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private RevReqContent(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static RevReqContent getInstance(Object o)
+ {
+ if (o instanceof RevReqContent)
+ {
+ return (RevReqContent)o;
+ }
+
+ if (o != null)
+ {
+ return new RevReqContent(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public RevReqContent(RevDetails revDetails)
+ {
+ this.content = new DERSequence(revDetails);
+ }
+
+ public RevReqContent(RevDetails[] revDetailsArray)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != revDetailsArray.length; i++)
+ {
+ v.add(revDetailsArray[i]);
+ }
+
+ this.content = new DERSequence(v);
+ }
+
+ public RevDetails[] toRevDetailsArray()
+ {
+ RevDetails[] result = new RevDetails[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = RevDetails.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * RevReqContent ::= SEQUENCE OF RevDetails
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cmp/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cmp/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes useful for encoding and supporting PKIX-CMP as described RFC 2510.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/Attribute.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/Attribute.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/Attribute.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/Attribute.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,100 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.DERObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class Attribute
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier attrType;
+ private ASN1Set attrValues;
+
+ /**
+ * return an Attribute object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static Attribute getInstance(
+ Object o)
+ {
+ if (o instanceof Attribute)
+ {
+ return (Attribute)o;
+ }
+
+ if (o != null)
+ {
+ return new Attribute(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private Attribute(
+ ASN1Sequence seq)
+ {
+ attrType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ attrValues = (ASN1Set)seq.getObjectAt(1);
+ }
+
+ /**
+ * @deprecated use ASN1ObjectIdentifier
+ */
+ public Attribute(
+ DERObjectIdentifier attrType,
+ ASN1Set attrValues)
+ {
+ this.attrType = new ASN1ObjectIdentifier(attrType.getId());
+ this.attrValues = attrValues;
+ }
+
+ public Attribute(
+ ASN1ObjectIdentifier attrType,
+ ASN1Set attrValues)
+ {
+ this.attrType = attrType;
+ this.attrValues = attrValues;
+ }
+
+ public ASN1ObjectIdentifier getAttrType()
+ {
+ return attrType;
+ }
+
+ public ASN1Set getAttrValues()
+ {
+ return attrValues;
+ }
+
+ public ASN1Encodable[] getAttributeValues()
+ {
+ return attrValues.toArray();
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Attribute ::= SEQUENCE {
+ * attrType OBJECT IDENTIFIER,
+ * attrValues SET OF AttributeValue
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(attrType);
+ v.add(attrValues);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/AttributeTable.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/AttributeTable.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/AttributeTable.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/AttributeTable.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,254 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.DERObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERSet;
+
+public class AttributeTable
+{
+ private Hashtable attributes = new Hashtable();
+
+ public AttributeTable(
+ Hashtable attrs)
+ {
+ attributes = copyTable(attrs);
+ }
+
+ public AttributeTable(
+ ASN1EncodableVector v)
+ {
+ for (int i = 0; i != v.size(); i++)
+ {
+ Attribute a = Attribute.getInstance(v.get(i));
+
+ addAttribute(a.getAttrType(), a);
+ }
+ }
+
+ public AttributeTable(
+ ASN1Set s)
+ {
+ for (int i = 0; i != s.size(); i++)
+ {
+ Attribute a = Attribute.getInstance(s.getObjectAt(i));
+
+ addAttribute(a.getAttrType(), a);
+ }
+ }
+
+ public AttributeTable(
+ Attribute attr)
+ {
+ addAttribute(attr.getAttrType(), attr);
+ }
+
+ public AttributeTable(
+ Attributes attrs)
+ {
+ this(ASN1Set.getInstance(attrs.toASN1Primitive()));
+ }
+
+ private void addAttribute(
+ ASN1ObjectIdentifier oid,
+ Attribute a)
+ {
+ Object value = attributes.get(oid);
+
+ if (value == null)
+ {
+ attributes.put(oid, a);
+ }
+ else
+ {
+ Vector v;
+
+ if (value instanceof Attribute)
+ {
+ v = new Vector();
+
+ v.addElement(value);
+ v.addElement(a);
+ }
+ else
+ {
+ v = (Vector)value;
+
+ v.addElement(a);
+ }
+
+ attributes.put(oid, v);
+ }
+ }
+
+ /**
+ * @deprecated use ASN1ObjectIdentifier
+ */
+ public Attribute get(DERObjectIdentifier oid)
+ {
+ return get(new ASN1ObjectIdentifier(oid.getId()));
+ }
+
+ /**
+ * Return the first attribute matching the OBJECT IDENTIFIER oid.
+ *
+ * @param oid type of attribute required.
+ * @return first attribute found of type oid.
+ */
+ public Attribute get(
+ ASN1ObjectIdentifier oid)
+ {
+ Object value = attributes.get(oid);
+
+ if (value instanceof Vector)
+ {
+ return (Attribute)((Vector)value).elementAt(0);
+ }
+
+ return (Attribute)value;
+ }
+
+ /**
+ * @deprecated use ASN1ObjectIdentifier
+ */
+ public ASN1EncodableVector getAll(DERObjectIdentifier oid)
+ {
+ return getAll(new ASN1ObjectIdentifier(oid.getId()));
+ }
+
+ /**
+ * Return all the attributes matching the OBJECT IDENTIFIER oid. The vector will be
+ * empty if there are no attributes of the required type present.
+ *
+ * @param oid type of attribute required.
+ * @return a vector of all the attributes found of type oid.
+ */
+ public ASN1EncodableVector getAll(
+ ASN1ObjectIdentifier oid)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ Object value = attributes.get(oid);
+
+ if (value instanceof Vector)
+ {
+ Enumeration e = ((Vector)value).elements();
+
+ while (e.hasMoreElements())
+ {
+ v.add((Attribute)e.nextElement());
+ }
+ }
+ else if (value != null)
+ {
+ v.add((Attribute)value);
+ }
+
+ return v;
+ }
+
+ public int size()
+ {
+ int size = 0;
+
+ for (Enumeration en = attributes.elements(); en.hasMoreElements();)
+ {
+ Object o = en.nextElement();
+
+ if (o instanceof Vector)
+ {
+ size += ((Vector)o).size();
+ }
+ else
+ {
+ size++;
+ }
+ }
+
+ return size;
+ }
+
+ public Hashtable toHashtable()
+ {
+ return copyTable(attributes);
+ }
+
+ public ASN1EncodableVector toASN1EncodableVector()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ Enumeration e = attributes.elements();
+
+ while (e.hasMoreElements())
+ {
+ Object value = e.nextElement();
+
+ if (value instanceof Vector)
+ {
+ Enumeration en = ((Vector)value).elements();
+
+ while (en.hasMoreElements())
+ {
+ v.add(Attribute.getInstance(en.nextElement()));
+ }
+ }
+ else
+ {
+ v.add(Attribute.getInstance(value));
+ }
+ }
+
+ return v;
+ }
+
+ public Attributes toASN1Structure()
+ {
+ return new Attributes(this.toASN1EncodableVector());
+ }
+
+ private Hashtable copyTable(
+ Hashtable in)
+ {
+ Hashtable out = new Hashtable();
+ Enumeration e = in.keys();
+
+ while (e.hasMoreElements())
+ {
+ Object key = e.nextElement();
+
+ out.put(key, in.get(key));
+ }
+
+ return out;
+ }
+
+ /**
+ * Return a new table with the passed in attribute added.
+ *
+ * @param attrType
+ * @param attrValue
+ * @return
+ */
+ public AttributeTable add(ASN1ObjectIdentifier attrType, ASN1Encodable attrValue)
+ {
+ AttributeTable newTable = new AttributeTable(attributes);
+
+ newTable.addAttribute(attrType, new Attribute(attrType, new DERSet(attrValue)));
+
+ return newTable;
+ }
+
+ public AttributeTable remove(ASN1ObjectIdentifier attrType)
+ {
+ AttributeTable newTable = new AttributeTable(attributes);
+
+ newTable.attributes.remove(attrType);
+
+ return newTable;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/Attributes.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/Attributes.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/Attributes.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/Attributes.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,49 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.BERSet;
+
+public class Attributes
+ extends ASN1Object
+{
+ private ASN1Set attributes;
+
+ private Attributes(ASN1Set set)
+ {
+ attributes = set;
+ }
+
+ public Attributes(ASN1EncodableVector v)
+ {
+ attributes = new BERSet(v);
+ }
+
+ public static Attributes getInstance(Object obj)
+ {
+ if (obj instanceof Attributes)
+ {
+ return (Attributes)obj;
+ }
+ else if (obj != null)
+ {
+ return new Attributes(ASN1Set.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ *
+ * Attributes ::=
+ * SET SIZE(1..MAX) OF Attribute -- according to RFC 5652
+ *
+ * @return
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return attributes;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/AuthEnvelopedData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/AuthEnvelopedData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/AuthEnvelopedData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/AuthEnvelopedData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,218 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class AuthEnvelopedData
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private OriginatorInfo originatorInfo;
+ private ASN1Set recipientInfos;
+ private EncryptedContentInfo authEncryptedContentInfo;
+ private ASN1Set authAttrs;
+ private ASN1OctetString mac;
+ private ASN1Set unauthAttrs;
+
+ public AuthEnvelopedData(
+ OriginatorInfo originatorInfo,
+ ASN1Set recipientInfos,
+ EncryptedContentInfo authEncryptedContentInfo,
+ ASN1Set authAttrs,
+ ASN1OctetString mac,
+ ASN1Set unauthAttrs)
+ {
+ // "It MUST be set to 0."
+ this.version = new ASN1Integer(0);
+
+ this.originatorInfo = originatorInfo;
+
+ // TODO
+ // "There MUST be at least one element in the collection."
+ this.recipientInfos = recipientInfos;
+
+ this.authEncryptedContentInfo = authEncryptedContentInfo;
+
+ // TODO
+ // "The authAttrs MUST be present if the content type carried in
+ // EncryptedContentInfo is not id-data."
+ this.authAttrs = authAttrs;
+
+ this.mac = mac;
+
+ this.unauthAttrs = unauthAttrs;
+ }
+
+ public AuthEnvelopedData(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+
+ // TODO
+ // "It MUST be set to 0."
+ ASN1Primitive tmp = seq.getObjectAt(index++).toASN1Primitive();
+ version = (ASN1Integer)tmp;
+
+ tmp = seq.getObjectAt(index++).toASN1Primitive();
+ if (tmp instanceof ASN1TaggedObject)
+ {
+ originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false);
+ tmp = seq.getObjectAt(index++).toASN1Primitive();
+ }
+
+ // TODO
+ // "There MUST be at least one element in the collection."
+ recipientInfos = ASN1Set.getInstance(tmp);
+
+ tmp = seq.getObjectAt(index++).toASN1Primitive();
+ authEncryptedContentInfo = EncryptedContentInfo.getInstance(tmp);
+
+ tmp = seq.getObjectAt(index++).toASN1Primitive();
+ if (tmp instanceof ASN1TaggedObject)
+ {
+ authAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false);
+ tmp = seq.getObjectAt(index++).toASN1Primitive();
+ }
+ else
+ {
+ // TODO
+ // "The authAttrs MUST be present if the content type carried in
+ // EncryptedContentInfo is not id-data."
+ }
+
+ mac = ASN1OctetString.getInstance(tmp);
+
+ if (seq.size() > index)
+ {
+ tmp = seq.getObjectAt(index++).toASN1Primitive();
+ unauthAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false);
+ }
+ }
+
+ /**
+ * return an AuthEnvelopedData object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @throws IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static AuthEnvelopedData getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return an AuthEnvelopedData object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @throws IllegalArgumentException if the object cannot be converted.
+ */
+ public static AuthEnvelopedData getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof AuthEnvelopedData)
+ {
+ return (AuthEnvelopedData)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new AuthEnvelopedData((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid AuthEnvelopedData: " + obj.getClass().getName());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public OriginatorInfo getOriginatorInfo()
+ {
+ return originatorInfo;
+ }
+
+ public ASN1Set getRecipientInfos()
+ {
+ return recipientInfos;
+ }
+
+ public EncryptedContentInfo getAuthEncryptedContentInfo()
+ {
+ return authEncryptedContentInfo;
+ }
+
+ public ASN1Set getAuthAttrs()
+ {
+ return authAttrs;
+ }
+
+ public ASN1OctetString getMac()
+ {
+ return mac;
+ }
+
+ public ASN1Set getUnauthAttrs()
+ {
+ return unauthAttrs;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * AuthEnvelopedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * authEncryptedContentInfo EncryptedContentInfo,
+ * authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
+ * mac MessageAuthenticationCode,
+ * unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+
+ if (originatorInfo != null)
+ {
+ v.add(new DERTaggedObject(false, 0, originatorInfo));
+ }
+
+ v.add(recipientInfos);
+ v.add(authEncryptedContentInfo);
+
+ // "authAttrs optionally contains the authenticated attributes."
+ if (authAttrs != null)
+ {
+ // "AuthAttributes MUST be DER encoded, even if the rest of the
+ // AuthEnvelopedData structure is BER encoded."
+ v.add(new DERTaggedObject(false, 1, authAttrs));
+ }
+
+ v.add(mac);
+
+ // "unauthAttrs optionally contains the unauthenticated attributes."
+ if (unauthAttrs != null)
+ {
+ v.add(new DERTaggedObject(false, 2, unauthAttrs));
+ }
+
+ return new BERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/AuthEnvelopedDataParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,157 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1SequenceParser;
+import pdftk.org.bouncycastle.asn1.ASN1SetParser;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObjectParser;
+import pdftk.org.bouncycastle.asn1.BERTags;
+
+/**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ *
+ * AuthEnvelopedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * authEncryptedContentInfo EncryptedContentInfo,
+ * authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
+ * mac MessageAuthenticationCode,
+ * unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
+ *
+ */
+public class AuthEnvelopedDataParser
+{
+ private ASN1SequenceParser seq;
+ private ASN1Integer version;
+ private ASN1Encodable nextObject;
+ private boolean originatorInfoCalled;
+
+ public AuthEnvelopedDataParser(ASN1SequenceParser seq) throws IOException
+ {
+ this.seq = seq;
+
+ // TODO
+ // "It MUST be set to 0."
+ this.version = ASN1Integer.getInstance(seq.readObject());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public OriginatorInfo getOriginatorInfo()
+ throws IOException
+ {
+ originatorInfoCalled = true;
+
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)nextObject).getTagNo() == 0)
+ {
+ ASN1SequenceParser originatorInfo = (ASN1SequenceParser) ((ASN1TaggedObjectParser)nextObject).getObjectParser(BERTags.SEQUENCE, false);
+ nextObject = null;
+ return OriginatorInfo.getInstance(originatorInfo.toASN1Primitive());
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getRecipientInfos()
+ throws IOException
+ {
+ if (!originatorInfoCalled)
+ {
+ getOriginatorInfo();
+ }
+
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ ASN1SetParser recipientInfos = (ASN1SetParser)nextObject;
+ nextObject = null;
+ return recipientInfos;
+ }
+
+ public EncryptedContentInfoParser getAuthEncryptedContentInfo()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject != null)
+ {
+ ASN1SequenceParser o = (ASN1SequenceParser) nextObject;
+ nextObject = null;
+ return new EncryptedContentInfoParser(o);
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getAuthAttrs()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject instanceof ASN1TaggedObjectParser)
+ {
+ ASN1Encodable o = nextObject;
+ nextObject = null;
+ return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
+ }
+
+ // TODO
+ // "The authAttrs MUST be present if the content type carried in
+ // EncryptedContentInfo is not id-data."
+
+ return null;
+ }
+
+ public ASN1OctetString getMac()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ ASN1Encodable o = nextObject;
+ nextObject = null;
+
+ return ASN1OctetString.getInstance(o.toASN1Primitive());
+ }
+
+ public ASN1SetParser getUnauthAttrs()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject != null)
+ {
+ ASN1Encodable o = nextObject;
+ nextObject = null;
+ return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
+ }
+
+ return null;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/AuthenticatedData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/AuthenticatedData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/AuthenticatedData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/AuthenticatedData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,296 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class AuthenticatedData
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private OriginatorInfo originatorInfo;
+ private ASN1Set recipientInfos;
+ private AlgorithmIdentifier macAlgorithm;
+ private AlgorithmIdentifier digestAlgorithm;
+ private ContentInfo encapsulatedContentInfo;
+ private ASN1Set authAttrs;
+ private ASN1OctetString mac;
+ private ASN1Set unauthAttrs;
+
+ public AuthenticatedData(
+ OriginatorInfo originatorInfo,
+ ASN1Set recipientInfos,
+ AlgorithmIdentifier macAlgorithm,
+ AlgorithmIdentifier digestAlgorithm,
+ ContentInfo encapsulatedContent,
+ ASN1Set authAttrs,
+ ASN1OctetString mac,
+ ASN1Set unauthAttrs)
+ {
+ if (digestAlgorithm != null || authAttrs != null)
+ {
+ if (digestAlgorithm == null || authAttrs == null)
+ {
+ throw new IllegalArgumentException("digestAlgorithm and authAttrs must be set together");
+ }
+ }
+
+ version = new ASN1Integer(calculateVersion(originatorInfo));
+
+ this.originatorInfo = originatorInfo;
+ this.macAlgorithm = macAlgorithm;
+ this.digestAlgorithm = digestAlgorithm;
+ this.recipientInfos = recipientInfos;
+ this.encapsulatedContentInfo = encapsulatedContent;
+ this.authAttrs = authAttrs;
+ this.mac = mac;
+ this.unauthAttrs = unauthAttrs;
+ }
+
+ public AuthenticatedData(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+
+ version = (ASN1Integer)seq.getObjectAt(index++);
+
+ Object tmp = seq.getObjectAt(index++);
+
+ if (tmp instanceof ASN1TaggedObject)
+ {
+ originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false);
+ tmp = seq.getObjectAt(index++);
+ }
+
+ recipientInfos = ASN1Set.getInstance(tmp);
+ macAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++));
+
+ tmp = seq.getObjectAt(index++);
+
+ if (tmp instanceof ASN1TaggedObject)
+ {
+ digestAlgorithm = AlgorithmIdentifier.getInstance((ASN1TaggedObject)tmp, false);
+ tmp = seq.getObjectAt(index++);
+ }
+
+ encapsulatedContentInfo = ContentInfo.getInstance(tmp);
+
+ tmp = seq.getObjectAt(index++);
+
+ if (tmp instanceof ASN1TaggedObject)
+ {
+ authAttrs = ASN1Set.getInstance((ASN1TaggedObject)tmp, false);
+ tmp = seq.getObjectAt(index++);
+ }
+
+ mac = ASN1OctetString.getInstance(tmp);
+
+ if (seq.size() > index)
+ {
+ unauthAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(index), false);
+ }
+ }
+
+ /**
+ * return an AuthenticatedData object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @throws IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static AuthenticatedData getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return an AuthenticatedData object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @throws IllegalArgumentException if the object cannot be converted.
+ */
+ public static AuthenticatedData getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof AuthenticatedData)
+ {
+ return (AuthenticatedData)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new AuthenticatedData((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid AuthenticatedData: " + obj.getClass().getName());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public OriginatorInfo getOriginatorInfo()
+ {
+ return originatorInfo;
+ }
+
+ public ASN1Set getRecipientInfos()
+ {
+ return recipientInfos;
+ }
+
+ public AlgorithmIdentifier getMacAlgorithm()
+ {
+ return macAlgorithm;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ {
+ return digestAlgorithm;
+ }
+
+ public ContentInfo getEncapsulatedContentInfo()
+ {
+ return encapsulatedContentInfo;
+ }
+
+ public ASN1Set getAuthAttrs()
+ {
+ return authAttrs;
+ }
+
+ public ASN1OctetString getMac()
+ {
+ return mac;
+ }
+
+ public ASN1Set getUnauthAttrs()
+ {
+ return unauthAttrs;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * AuthenticatedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * macAlgorithm MessageAuthenticationCodeAlgorithm,
+ * digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
+ * encapContentInfo EncapsulatedContentInfo,
+ * authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
+ * mac MessageAuthenticationCode,
+ * unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
+ *
+ * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * MessageAuthenticationCode ::= OCTET STRING
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+
+ if (originatorInfo != null)
+ {
+ v.add(new DERTaggedObject(false, 0, originatorInfo));
+ }
+
+ v.add(recipientInfos);
+ v.add(macAlgorithm);
+
+ if (digestAlgorithm != null)
+ {
+ v.add(new DERTaggedObject(false, 1, digestAlgorithm));
+ }
+
+ v.add(encapsulatedContentInfo);
+
+ if (authAttrs != null)
+ {
+ v.add(new DERTaggedObject(false, 2, authAttrs));
+ }
+
+ v.add(mac);
+
+ if (unauthAttrs != null)
+ {
+ v.add(new DERTaggedObject(false, 3, unauthAttrs));
+ }
+
+ return new BERSequence(v);
+ }
+
+ public static int calculateVersion(OriginatorInfo origInfo)
+ {
+ if (origInfo == null)
+ {
+ return 0;
+ }
+ else
+ {
+ int ver = 0;
+
+ for (Enumeration e = origInfo.getCertificates().getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tag = (ASN1TaggedObject)obj;
+
+ if (tag.getTagNo() == 2)
+ {
+ ver = 1;
+ }
+ else if (tag.getTagNo() == 3)
+ {
+ ver = 3;
+ break;
+ }
+ }
+ }
+
+ if (origInfo.getCRLs() != null)
+ {
+ for (Enumeration e = origInfo.getCRLs().getObjects(); e.hasMoreElements();)
+ {
+ Object obj = e.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tag = (ASN1TaggedObject)obj;
+
+ if (tag.getTagNo() == 1)
+ {
+ ver = 3;
+ break;
+ }
+ }
+ }
+ }
+
+ return ver;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/AuthenticatedDataParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,197 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1SequenceParser;
+import pdftk.org.bouncycastle.asn1.ASN1SetParser;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObjectParser;
+import pdftk.org.bouncycastle.asn1.BERTags;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * AuthenticatedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * macAlgorithm MessageAuthenticationCodeAlgorithm,
+ * digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
+ * encapContentInfo EncapsulatedContentInfo,
+ * authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
+ * mac MessageAuthenticationCode,
+ * unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
+ *
+ * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+ *
+ * MessageAuthenticationCode ::= OCTET STRING
+ *
+ */
+public class AuthenticatedDataParser
+{
+ private ASN1SequenceParser seq;
+ private ASN1Integer version;
+ private ASN1Encodable nextObject;
+ private boolean originatorInfoCalled;
+
+ public AuthenticatedDataParser(
+ ASN1SequenceParser seq)
+ throws IOException
+ {
+ this.seq = seq;
+ this.version = ASN1Integer.getInstance(seq.readObject());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public OriginatorInfo getOriginatorInfo()
+ throws IOException
+ {
+ originatorInfoCalled = true;
+
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)nextObject).getTagNo() == 0)
+ {
+ ASN1SequenceParser originatorInfo = (ASN1SequenceParser) ((ASN1TaggedObjectParser)nextObject).getObjectParser(BERTags.SEQUENCE, false);
+ nextObject = null;
+ return OriginatorInfo.getInstance(originatorInfo.toASN1Primitive());
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getRecipientInfos()
+ throws IOException
+ {
+ if (!originatorInfoCalled)
+ {
+ getOriginatorInfo();
+ }
+
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ ASN1SetParser recipientInfos = (ASN1SetParser)nextObject;
+ nextObject = null;
+ return recipientInfos;
+ }
+
+ public AlgorithmIdentifier getMacAlgorithm()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject != null)
+ {
+ ASN1SequenceParser o = (ASN1SequenceParser)nextObject;
+ nextObject = null;
+ return AlgorithmIdentifier.getInstance(o.toASN1Primitive());
+ }
+
+ return null;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject instanceof ASN1TaggedObjectParser)
+ {
+ AlgorithmIdentifier obj = AlgorithmIdentifier.getInstance((ASN1TaggedObject)nextObject.toASN1Primitive(), false);
+ nextObject = null;
+ return obj;
+ }
+
+ return null;
+ }
+
+ public ContentInfoParser getEnapsulatedContentInfo()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject != null)
+ {
+ ASN1SequenceParser o = (ASN1SequenceParser)nextObject;
+ nextObject = null;
+ return new ContentInfoParser(o);
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getAuthAttrs()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject instanceof ASN1TaggedObjectParser)
+ {
+ ASN1Encodable o = nextObject;
+ nextObject = null;
+ return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
+ }
+
+ return null;
+ }
+
+ public ASN1OctetString getMac()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ ASN1Encodable o = nextObject;
+ nextObject = null;
+
+ return ASN1OctetString.getInstance(o.toASN1Primitive());
+ }
+
+ public ASN1SetParser getUnauthAttrs()
+ throws IOException
+ {
+ if (nextObject == null)
+ {
+ nextObject = seq.readObject();
+ }
+
+ if (nextObject != null)
+ {
+ ASN1Encodable o = nextObject;
+ nextObject = null;
+ return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
+ }
+
+ return null;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/CMSAttributes.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/CMSAttributes.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/CMSAttributes.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/CMSAttributes.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,13 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+public interface CMSAttributes
+{
+ public static final ASN1ObjectIdentifier contentType = PKCSObjectIdentifiers.pkcs_9_at_contentType;
+ public static final ASN1ObjectIdentifier messageDigest = PKCSObjectIdentifiers.pkcs_9_at_messageDigest;
+ public static final ASN1ObjectIdentifier signingTime = PKCSObjectIdentifiers.pkcs_9_at_signingTime;
+ public static final ASN1ObjectIdentifier counterSignature = PKCSObjectIdentifiers.pkcs_9_at_counterSignature;
+ public static final ASN1ObjectIdentifier contentHint = PKCSObjectIdentifiers.id_aa_contentHint;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/CMSObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+public interface CMSObjectIdentifiers
+{
+ static final ASN1ObjectIdentifier data = PKCSObjectIdentifiers.data;
+ static final ASN1ObjectIdentifier signedData = PKCSObjectIdentifiers.signedData;
+ static final ASN1ObjectIdentifier envelopedData = PKCSObjectIdentifiers.envelopedData;
+ static final ASN1ObjectIdentifier signedAndEnvelopedData = PKCSObjectIdentifiers.signedAndEnvelopedData;
+ static final ASN1ObjectIdentifier digestedData = PKCSObjectIdentifiers.digestedData;
+ static final ASN1ObjectIdentifier encryptedData = PKCSObjectIdentifiers.encryptedData;
+ static final ASN1ObjectIdentifier authenticatedData = PKCSObjectIdentifiers.id_ct_authData;
+ static final ASN1ObjectIdentifier compressedData = PKCSObjectIdentifiers.id_ct_compressedData;
+ static final ASN1ObjectIdentifier authEnvelopedData = PKCSObjectIdentifiers.id_ct_authEnvelopedData;
+ static final ASN1ObjectIdentifier timestampedData = PKCSObjectIdentifiers.id_ct_timestampedData;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/CompressedData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/CompressedData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/CompressedData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/CompressedData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,110 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * RFC 3274 - CMS Compressed Data.
+ *
+ * CompressedData ::= SEQUENCE {
+ * version CMSVersion,
+ * compressionAlgorithm CompressionAlgorithmIdentifier,
+ * encapContentInfo EncapsulatedContentInfo
+ * }
+ *
+ */
+public class CompressedData
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private AlgorithmIdentifier compressionAlgorithm;
+ private ContentInfo encapContentInfo;
+
+ public CompressedData(
+ AlgorithmIdentifier compressionAlgorithm,
+ ContentInfo encapContentInfo)
+ {
+ this.version = new ASN1Integer(0);
+ this.compressionAlgorithm = compressionAlgorithm;
+ this.encapContentInfo = encapContentInfo;
+ }
+
+ private CompressedData(
+ ASN1Sequence seq)
+ {
+ this.version = (ASN1Integer)seq.getObjectAt(0);
+ this.compressionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ this.encapContentInfo = ContentInfo.getInstance(seq.getObjectAt(2));
+
+ }
+
+ /**
+ * return a CompressedData object from a tagged object.
+ *
+ * @param _ato the tagged object holding the object we want.
+ * @param _explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static CompressedData getInstance(
+ ASN1TaggedObject _ato,
+ boolean _explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(_ato, _explicit));
+ }
+
+ /**
+ * return a CompressedData object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static CompressedData getInstance(
+ Object obj)
+ {
+ if (obj instanceof CompressedData)
+ {
+ return (CompressedData)obj;
+ }
+
+ if (obj != null)
+ {
+ return new CompressedData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public AlgorithmIdentifier getCompressionAlgorithmIdentifier()
+ {
+ return compressionAlgorithm;
+ }
+
+ public ContentInfo getEncapContentInfo()
+ {
+ return encapContentInfo;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(compressionAlgorithm);
+ v.add(encapContentInfo);
+
+ return new BERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/CompressedDataParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/CompressedDataParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/CompressedDataParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/CompressedDataParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1SequenceParser;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * RFC 3274 - CMS Compressed Data.
+ *
+ * CompressedData ::= SEQUENCE {
+ * version CMSVersion,
+ * compressionAlgorithm CompressionAlgorithmIdentifier,
+ * encapContentInfo EncapsulatedContentInfo
+ * }
+ *
+ */
+public class CompressedDataParser
+{
+ private ASN1Integer _version;
+ private AlgorithmIdentifier _compressionAlgorithm;
+ private ContentInfoParser _encapContentInfo;
+
+ public CompressedDataParser(
+ ASN1SequenceParser seq)
+ throws IOException
+ {
+ this._version = (ASN1Integer)seq.readObject();
+ this._compressionAlgorithm = AlgorithmIdentifier.getInstance(seq.readObject().toASN1Primitive());
+ this._encapContentInfo = new ContentInfoParser((ASN1SequenceParser)seq.readObject());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return _version;
+ }
+
+ public AlgorithmIdentifier getCompressionAlgorithmIdentifier()
+ {
+ return _compressionAlgorithm;
+ }
+
+ public ContentInfoParser getEncapContentInfo()
+ {
+ return _encapContentInfo;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/ContentInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/ContentInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/ContentInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/ContentInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,97 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.BERTaggedObject;
+
+public class ContentInfo
+ extends ASN1Object
+ implements CMSObjectIdentifiers
+{
+ private ASN1ObjectIdentifier contentType;
+ private ASN1Encodable content;
+
+ public static ContentInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof ContentInfo)
+ {
+ return (ContentInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new ContentInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ContentInfo(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ contentType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+
+ if (seq.size() > 1)
+ {
+ ASN1TaggedObject tagged = (ASN1TaggedObject)seq.getObjectAt(1);
+ if (!tagged.isExplicit() || tagged.getTagNo() != 0)
+ {
+ throw new IllegalArgumentException("Bad tag for 'content'");
+ }
+
+ content = tagged.getObject();
+ }
+ }
+
+ public ContentInfo(
+ ASN1ObjectIdentifier contentType,
+ ASN1Encodable content)
+ {
+ this.contentType = contentType;
+ this.content = content;
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return contentType;
+ }
+
+ public ASN1Encodable getContent()
+ {
+ return content;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * ContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * content
+ * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(contentType);
+
+ if (content != null)
+ {
+ v.add(new BERTaggedObject(0, content));
+ }
+
+ return new BERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/ContentInfoParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/ContentInfoParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/ContentInfoParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/ContentInfoParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1SequenceParser;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObjectParser;
+
+/**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * ContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * content
+ * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ *
+ */
+public class ContentInfoParser
+{
+ private ASN1ObjectIdentifier contentType;
+ private ASN1TaggedObjectParser content;
+
+ public ContentInfoParser(
+ ASN1SequenceParser seq)
+ throws IOException
+ {
+ contentType = (ASN1ObjectIdentifier)seq.readObject();
+ content = (ASN1TaggedObjectParser)seq.readObject();
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return contentType;
+ }
+
+ public ASN1Encodable getContent(
+ int tag)
+ throws IOException
+ {
+ if (content != null)
+ {
+ return content.getObjectParser(tag, true);
+ }
+
+ return null;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/DigestedData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/DigestedData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/DigestedData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/DigestedData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,121 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * RFC 3274 - CMS Digest Data.
+ *
+ * DigestedData ::= SEQUENCE {
+ * version CMSVersion,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * encapContentInfo EncapsulatedContentInfo,
+ * digest Digest }
+ *
+ */
+public class DigestedData
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private AlgorithmIdentifier digestAlgorithm;
+ private ContentInfo encapContentInfo;
+ private ASN1OctetString digest;
+
+ public DigestedData(
+ AlgorithmIdentifier digestAlgorithm,
+ ContentInfo encapContentInfo,
+ byte[] digest)
+ {
+ this.version = new ASN1Integer(0);
+ this.digestAlgorithm = digestAlgorithm;
+ this.encapContentInfo = encapContentInfo;
+ this.digest = new DEROctetString(digest);
+ }
+
+ private DigestedData(
+ ASN1Sequence seq)
+ {
+ this.version = (ASN1Integer)seq.getObjectAt(0);
+ this.digestAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ this.encapContentInfo = ContentInfo.getInstance(seq.getObjectAt(2));
+ this.digest = ASN1OctetString.getInstance(seq.getObjectAt(3));
+ }
+
+ /**
+ * return a CompressedData object from a tagged object.
+ *
+ * @param _ato the tagged object holding the object we want.
+ * @param _explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static DigestedData getInstance(
+ ASN1TaggedObject _ato,
+ boolean _explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(_ato, _explicit));
+ }
+
+ /**
+ * return a CompressedData object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static DigestedData getInstance(
+ Object obj)
+ {
+ if (obj instanceof DigestedData)
+ {
+ return (DigestedData)obj;
+ }
+
+ if (obj != null)
+ {
+ return new DigestedData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ {
+ return digestAlgorithm;
+ }
+
+ public ContentInfo getEncapContentInfo()
+ {
+ return encapContentInfo;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(digestAlgorithm);
+ v.add(encapContentInfo);
+ v.add(digest);
+
+ return new BERSequence(v);
+ }
+
+ public byte[] getDigest()
+ {
+ return digest.getOctets();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/EncryptedContentInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/EncryptedContentInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/EncryptedContentInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/EncryptedContentInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,109 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.BERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class EncryptedContentInfo
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier contentType;
+ private AlgorithmIdentifier contentEncryptionAlgorithm;
+ private ASN1OctetString encryptedContent;
+
+ public EncryptedContentInfo(
+ ASN1ObjectIdentifier contentType,
+ AlgorithmIdentifier contentEncryptionAlgorithm,
+ ASN1OctetString encryptedContent)
+ {
+ this.contentType = contentType;
+ this.contentEncryptionAlgorithm = contentEncryptionAlgorithm;
+ this.encryptedContent = encryptedContent;
+ }
+
+ private EncryptedContentInfo(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 2)
+ {
+ throw new IllegalArgumentException("Truncated Sequence Found");
+ }
+
+ contentType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ contentEncryptionAlgorithm = AlgorithmIdentifier.getInstance(
+ seq.getObjectAt(1));
+ if (seq.size() > 2)
+ {
+ encryptedContent = ASN1OctetString.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(2), false);
+ }
+ }
+
+ /**
+ * return an EncryptedContentInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static EncryptedContentInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof EncryptedContentInfo)
+ {
+ return (EncryptedContentInfo)obj;
+ }
+ if (obj != null)
+ {
+ return new EncryptedContentInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return contentType;
+ }
+
+ public AlgorithmIdentifier getContentEncryptionAlgorithm()
+ {
+ return contentEncryptionAlgorithm;
+ }
+
+ public ASN1OctetString getEncryptedContent()
+ {
+ return encryptedContent;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * EncryptedContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+ * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(contentType);
+ v.add(contentEncryptionAlgorithm);
+
+ if (encryptedContent != null)
+ {
+ v.add(new BERTaggedObject(false, 0, encryptedContent));
+ }
+
+ return new BERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/EncryptedContentInfoParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,51 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1SequenceParser;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObjectParser;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ *
+ * EncryptedContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+ * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+ * }
+ *
+ */
+public class EncryptedContentInfoParser
+{
+ private ASN1ObjectIdentifier _contentType;
+ private AlgorithmIdentifier _contentEncryptionAlgorithm;
+ private ASN1TaggedObjectParser _encryptedContent;
+
+ public EncryptedContentInfoParser(
+ ASN1SequenceParser seq)
+ throws IOException
+ {
+ _contentType = (ASN1ObjectIdentifier)seq.readObject();
+ _contentEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.readObject().toASN1Primitive());
+ _encryptedContent = (ASN1TaggedObjectParser)seq.readObject();
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return _contentType;
+ }
+
+ public AlgorithmIdentifier getContentEncryptionAlgorithm()
+ {
+ return _contentEncryptionAlgorithm;
+ }
+
+ public ASN1Encodable getEncryptedContent(
+ int tag)
+ throws IOException
+ {
+ return _encryptedContent.getObjectParser(tag, false);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/EncryptedData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/EncryptedData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/EncryptedData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/EncryptedData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,94 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.BERTaggedObject;
+
+public class EncryptedData
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private EncryptedContentInfo encryptedContentInfo;
+ private ASN1Set unprotectedAttrs;
+
+ public static EncryptedData getInstance(Object o)
+ {
+ if (o instanceof EncryptedData)
+ {
+ return (EncryptedData)o;
+ }
+
+ if (o != null)
+ {
+ return new EncryptedData(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public EncryptedData(EncryptedContentInfo encInfo)
+ {
+ this(encInfo, null);
+ }
+
+ public EncryptedData(EncryptedContentInfo encInfo, ASN1Set unprotectedAttrs)
+ {
+ this.version = new ASN1Integer((unprotectedAttrs == null) ? 0 : 2);
+ this.encryptedContentInfo = encInfo;
+ this.unprotectedAttrs = unprotectedAttrs;
+ }
+
+ private EncryptedData(ASN1Sequence seq)
+ {
+ this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
+ this.encryptedContentInfo = EncryptedContentInfo.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() == 3)
+ {
+ this.unprotectedAttrs = ASN1Set.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public EncryptedContentInfo getEncryptedContentInfo()
+ {
+ return encryptedContentInfo;
+ }
+
+ public ASN1Set getUnprotectedAttrs()
+ {
+ return unprotectedAttrs;
+ }
+
+ /**
+ *
+ * EncryptedData ::= SEQUENCE {
+ * version CMSVersion,
+ * encryptedContentInfo EncryptedContentInfo,
+ * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(encryptedContentInfo);
+ if (unprotectedAttrs != null)
+ {
+ v.add(new BERTaggedObject(false, 1, unprotectedAttrs));
+ }
+
+ return new BERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/EnvelopedData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/EnvelopedData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/EnvelopedData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/EnvelopedData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,188 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class EnvelopedData
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private OriginatorInfo originatorInfo;
+ private ASN1Set recipientInfos;
+ private EncryptedContentInfo encryptedContentInfo;
+ private ASN1Set unprotectedAttrs;
+
+ public EnvelopedData(
+ OriginatorInfo originatorInfo,
+ ASN1Set recipientInfos,
+ EncryptedContentInfo encryptedContentInfo,
+ ASN1Set unprotectedAttrs)
+ {
+ version = new ASN1Integer(calculateVersion(originatorInfo, recipientInfos, unprotectedAttrs));
+
+ this.originatorInfo = originatorInfo;
+ this.recipientInfos = recipientInfos;
+ this.encryptedContentInfo = encryptedContentInfo;
+ this.unprotectedAttrs = unprotectedAttrs;
+ }
+
+ public EnvelopedData(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+
+ version = (ASN1Integer)seq.getObjectAt(index++);
+
+ Object tmp = seq.getObjectAt(index++);
+
+ if (tmp instanceof ASN1TaggedObject)
+ {
+ originatorInfo = OriginatorInfo.getInstance((ASN1TaggedObject)tmp, false);
+ tmp = seq.getObjectAt(index++);
+ }
+
+ recipientInfos = ASN1Set.getInstance(tmp);
+
+ encryptedContentInfo = EncryptedContentInfo.getInstance(seq.getObjectAt(index++));
+
+ if(seq.size() > index)
+ {
+ unprotectedAttrs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(index), false);
+ }
+ }
+
+ /**
+ * return an EnvelopedData object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static EnvelopedData getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return an EnvelopedData object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static EnvelopedData getInstance(
+ Object obj)
+ {
+ if (obj instanceof EnvelopedData)
+ {
+ return (EnvelopedData)obj;
+ }
+
+ if (obj != null)
+ {
+ return new EnvelopedData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public OriginatorInfo getOriginatorInfo()
+ {
+ return originatorInfo;
+ }
+
+ public ASN1Set getRecipientInfos()
+ {
+ return recipientInfos;
+ }
+
+ public EncryptedContentInfo getEncryptedContentInfo()
+ {
+ return encryptedContentInfo;
+ }
+
+ public ASN1Set getUnprotectedAttrs()
+ {
+ return unprotectedAttrs;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * EnvelopedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * encryptedContentInfo EncryptedContentInfo,
+ * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+
+ if (originatorInfo != null)
+ {
+ v.add(new DERTaggedObject(false, 0, originatorInfo));
+ }
+
+ v.add(recipientInfos);
+ v.add(encryptedContentInfo);
+
+ if (unprotectedAttrs != null)
+ {
+ v.add(new DERTaggedObject(false, 1, unprotectedAttrs));
+ }
+
+ return new BERSequence(v);
+ }
+
+ public static int calculateVersion(OriginatorInfo originatorInfo, ASN1Set recipientInfos, ASN1Set unprotectedAttrs)
+ {
+ int version;
+
+ if (originatorInfo != null || unprotectedAttrs != null)
+ {
+ version = 2;
+ }
+ else
+ {
+ version = 0;
+
+ Enumeration e = recipientInfos.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ RecipientInfo ri = RecipientInfo.getInstance(e.nextElement());
+
+ if (ri.getVersion().getValue().intValue() != version)
+ {
+ version = 2;
+ break;
+ }
+ }
+ }
+
+ return version;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/EnvelopedDataParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/EnvelopedDataParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/EnvelopedDataParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/EnvelopedDataParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,118 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1SequenceParser;
+import pdftk.org.bouncycastle.asn1.ASN1SetParser;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObjectParser;
+import pdftk.org.bouncycastle.asn1.BERTags;
+
+/**
+ *
+ * EnvelopedData ::= SEQUENCE {
+ * version CMSVersion,
+ * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+ * recipientInfos RecipientInfos,
+ * encryptedContentInfo EncryptedContentInfo,
+ * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+ * }
+ *
+ */
+public class EnvelopedDataParser
+{
+ private ASN1SequenceParser _seq;
+ private ASN1Integer _version;
+ private ASN1Encodable _nextObject;
+ private boolean _originatorInfoCalled;
+
+ public EnvelopedDataParser(
+ ASN1SequenceParser seq)
+ throws IOException
+ {
+ this._seq = seq;
+ this._version = ASN1Integer.getInstance(seq.readObject());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return _version;
+ }
+
+ public OriginatorInfo getOriginatorInfo()
+ throws IOException
+ {
+ _originatorInfoCalled = true;
+
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.readObject();
+ }
+
+ if (_nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)_nextObject).getTagNo() == 0)
+ {
+ ASN1SequenceParser originatorInfo = (ASN1SequenceParser) ((ASN1TaggedObjectParser)_nextObject).getObjectParser(BERTags.SEQUENCE, false);
+ _nextObject = null;
+ return OriginatorInfo.getInstance(originatorInfo.toASN1Primitive());
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getRecipientInfos()
+ throws IOException
+ {
+ if (!_originatorInfoCalled)
+ {
+ getOriginatorInfo();
+ }
+
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.readObject();
+ }
+
+ ASN1SetParser recipientInfos = (ASN1SetParser)_nextObject;
+ _nextObject = null;
+ return recipientInfos;
+ }
+
+ public EncryptedContentInfoParser getEncryptedContentInfo()
+ throws IOException
+ {
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.readObject();
+ }
+
+
+ if (_nextObject != null)
+ {
+ ASN1SequenceParser o = (ASN1SequenceParser) _nextObject;
+ _nextObject = null;
+ return new EncryptedContentInfoParser(o);
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getUnprotectedAttrs()
+ throws IOException
+ {
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.readObject();
+ }
+
+
+ if (_nextObject != null)
+ {
+ ASN1Encodable o = _nextObject;
+ _nextObject = null;
+ return (ASN1SetParser)((ASN1TaggedObjectParser)o).getObjectParser(BERTags.SET, false);
+ }
+
+ return null;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/Evidence.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/Evidence.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/Evidence.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/Evidence.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,56 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class Evidence
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private TimeStampTokenEvidence tstEvidence;
+
+ public Evidence(TimeStampTokenEvidence tstEvidence)
+ {
+ this.tstEvidence = tstEvidence;
+ }
+
+ private Evidence(ASN1TaggedObject tagged)
+ {
+ if (tagged.getTagNo() == 0)
+ {
+ this.tstEvidence = TimeStampTokenEvidence.getInstance(tagged, false);
+ }
+ }
+
+ public static Evidence getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof Evidence)
+ {
+ return (Evidence)obj;
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new Evidence(ASN1TaggedObject.getInstance(obj));
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance");
+ }
+
+ public TimeStampTokenEvidence getTstEvidence()
+ {
+ return tstEvidence;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (tstEvidence != null)
+ {
+ return new DERTaggedObject(false, 0, tstEvidence);
+ }
+
+ return null;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/IssuerAndSerialNumber.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,107 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+import pdftk.org.bouncycastle.asn1.x509.Certificate;
+import pdftk.org.bouncycastle.asn1.x509.X509CertificateStructure;
+import pdftk.org.bouncycastle.asn1.x509.X509Name;
+
+public class IssuerAndSerialNumber
+ extends ASN1Object
+{
+ private X500Name name;
+ private ASN1Integer serialNumber;
+
+ public static IssuerAndSerialNumber getInstance(
+ Object obj)
+ {
+ if (obj instanceof IssuerAndSerialNumber)
+ {
+ return (IssuerAndSerialNumber)obj;
+ }
+ else if (obj != null)
+ {
+ return new IssuerAndSerialNumber(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public IssuerAndSerialNumber(
+ ASN1Sequence seq)
+ {
+ this.name = X500Name.getInstance(seq.getObjectAt(0));
+ this.serialNumber = (ASN1Integer)seq.getObjectAt(1);
+ }
+
+ public IssuerAndSerialNumber(
+ Certificate certificate)
+ {
+ this.name = certificate.getIssuer();
+ this.serialNumber = certificate.getSerialNumber();
+ }
+
+ public IssuerAndSerialNumber(
+ X509CertificateStructure certificate)
+ {
+ this.name = certificate.getIssuer();
+ this.serialNumber = certificate.getSerialNumber();
+ }
+
+ public IssuerAndSerialNumber(
+ X500Name name,
+ BigInteger serialNumber)
+ {
+ this.name = name;
+ this.serialNumber = new ASN1Integer(serialNumber);
+ }
+
+ /**
+ * @deprecated use X500Name constructor
+ */
+ public IssuerAndSerialNumber(
+ X509Name name,
+ BigInteger serialNumber)
+ {
+ this.name = X500Name.getInstance(name);
+ this.serialNumber = new ASN1Integer(serialNumber);
+ }
+
+ /**
+ * @deprecated use X500Name constructor
+ */
+ public IssuerAndSerialNumber(
+ X509Name name,
+ ASN1Integer serialNumber)
+ {
+ this.name = X500Name.getInstance(name);
+ this.serialNumber = serialNumber;
+ }
+
+ public X500Name getName()
+ {
+ return name;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(name);
+ v.add(serialNumber);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/KEKIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/KEKIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/KEKIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/KEKIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,139 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class KEKIdentifier
+ extends ASN1Object
+{
+ private ASN1OctetString keyIdentifier;
+ private ASN1GeneralizedTime date;
+ private OtherKeyAttribute other;
+
+ public KEKIdentifier(
+ byte[] keyIdentifier,
+ ASN1GeneralizedTime date,
+ OtherKeyAttribute other)
+ {
+ this.keyIdentifier = new DEROctetString(keyIdentifier);
+ this.date = date;
+ this.other = other;
+ }
+
+ private KEKIdentifier(
+ ASN1Sequence seq)
+ {
+ keyIdentifier = (ASN1OctetString)seq.getObjectAt(0);
+
+ switch (seq.size())
+ {
+ case 1:
+ break;
+ case 2:
+ if (seq.getObjectAt(1) instanceof ASN1GeneralizedTime)
+ {
+ date = (ASN1GeneralizedTime)seq.getObjectAt(1);
+ }
+ else
+ {
+ other = OtherKeyAttribute.getInstance(seq.getObjectAt(1));
+ }
+ break;
+ case 3:
+ date = (ASN1GeneralizedTime)seq.getObjectAt(1);
+ other = OtherKeyAttribute.getInstance(seq.getObjectAt(2));
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid KEKIdentifier");
+ }
+ }
+
+ /**
+ * return a KEKIdentifier object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static KEKIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return a KEKIdentifier object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static KEKIdentifier getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof KEKIdentifier)
+ {
+ return (KEKIdentifier)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new KEKIdentifier((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid KEKIdentifier: " + obj.getClass().getName());
+ }
+
+ public ASN1OctetString getKeyIdentifier()
+ {
+ return keyIdentifier;
+ }
+
+ public ASN1GeneralizedTime getDate()
+ {
+ return date;
+ }
+
+ public OtherKeyAttribute getOther()
+ {
+ return other;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * KEKIdentifier ::= SEQUENCE {
+ * keyIdentifier OCTET STRING,
+ * date GeneralizedTime OPTIONAL,
+ * other OtherKeyAttribute OPTIONAL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(keyIdentifier);
+
+ if (date != null)
+ {
+ v.add(date);
+ }
+
+ if (other != null)
+ {
+ v.add(other);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/KEKRecipientInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/KEKRecipientInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/KEKRecipientInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/KEKRecipientInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,121 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class KEKRecipientInfo
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private KEKIdentifier kekid;
+ private AlgorithmIdentifier keyEncryptionAlgorithm;
+ private ASN1OctetString encryptedKey;
+
+ public KEKRecipientInfo(
+ KEKIdentifier kekid,
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ ASN1OctetString encryptedKey)
+ {
+ this.version = new ASN1Integer(4);
+ this.kekid = kekid;
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public KEKRecipientInfo(
+ ASN1Sequence seq)
+ {
+ version = (ASN1Integer)seq.getObjectAt(0);
+ kekid = KEKIdentifier.getInstance(seq.getObjectAt(1));
+ keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2));
+ encryptedKey = (ASN1OctetString)seq.getObjectAt(3);
+ }
+
+ /**
+ * return a KEKRecipientInfo object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static KEKRecipientInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return a KEKRecipientInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static KEKRecipientInfo getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof KEKRecipientInfo)
+ {
+ return (KEKRecipientInfo)obj;
+ }
+
+ if(obj instanceof ASN1Sequence)
+ {
+ return new KEKRecipientInfo((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid KEKRecipientInfo: " + obj.getClass().getName());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public KEKIdentifier getKekid()
+ {
+ return kekid;
+ }
+
+ public AlgorithmIdentifier getKeyEncryptionAlgorithm()
+ {
+ return keyEncryptionAlgorithm;
+ }
+
+ public ASN1OctetString getEncryptedKey()
+ {
+ return encryptedKey;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * KEKRecipientInfo ::= SEQUENCE {
+ * version CMSVersion, -- always set to 4
+ * kekid KEKIdentifier,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * encryptedKey EncryptedKey
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(kekid);
+ v.add(keyEncryptionAlgorithm);
+ v.add(encryptedKey);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/KeyAgreeRecipientIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,103 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class KeyAgreeRecipientIdentifier
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private IssuerAndSerialNumber issuerSerial;
+ private RecipientKeyIdentifier rKeyID;
+
+ /**
+ * return an KeyAgreeRecipientIdentifier object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static KeyAgreeRecipientIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return an KeyAgreeRecipientIdentifier object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static KeyAgreeRecipientIdentifier getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof KeyAgreeRecipientIdentifier)
+ {
+ return (KeyAgreeRecipientIdentifier)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new KeyAgreeRecipientIdentifier(IssuerAndSerialNumber.getInstance(obj));
+ }
+
+ if (obj instanceof ASN1TaggedObject && ((ASN1TaggedObject)obj).getTagNo() == 0)
+ {
+ return new KeyAgreeRecipientIdentifier(RecipientKeyIdentifier.getInstance(
+ (ASN1TaggedObject)obj, false));
+ }
+
+ throw new IllegalArgumentException("Invalid KeyAgreeRecipientIdentifier: " + obj.getClass().getName());
+ }
+
+ public KeyAgreeRecipientIdentifier(
+ IssuerAndSerialNumber issuerSerial)
+ {
+ this.issuerSerial = issuerSerial;
+ this.rKeyID = null;
+ }
+
+ public KeyAgreeRecipientIdentifier(
+ RecipientKeyIdentifier rKeyID)
+ {
+ this.issuerSerial = null;
+ this.rKeyID = rKeyID;
+ }
+
+ public IssuerAndSerialNumber getIssuerAndSerialNumber()
+ {
+ return issuerSerial;
+ }
+
+ public RecipientKeyIdentifier getRKeyID()
+ {
+ return rKeyID;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * KeyAgreeRecipientIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * rKeyId [0] IMPLICIT RecipientKeyIdentifier
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (issuerSerial != null)
+ {
+ return issuerSerial.toASN1Primitive();
+ }
+
+ return new DERTaggedObject(false, 0, rKeyID);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/KeyAgreeRecipientInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,153 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class KeyAgreeRecipientInfo
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private OriginatorIdentifierOrKey originator;
+ private ASN1OctetString ukm;
+ private AlgorithmIdentifier keyEncryptionAlgorithm;
+ private ASN1Sequence recipientEncryptedKeys;
+
+ public KeyAgreeRecipientInfo(
+ OriginatorIdentifierOrKey originator,
+ ASN1OctetString ukm,
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ ASN1Sequence recipientEncryptedKeys)
+ {
+ this.version = new ASN1Integer(3);
+ this.originator = originator;
+ this.ukm = ukm;
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.recipientEncryptedKeys = recipientEncryptedKeys;
+ }
+
+ public KeyAgreeRecipientInfo(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+
+ version = (ASN1Integer)seq.getObjectAt(index++);
+ originator = OriginatorIdentifierOrKey.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(index++), true);
+
+ if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
+ {
+ ukm = ASN1OctetString.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(index++), true);
+ }
+
+ keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(
+ seq.getObjectAt(index++));
+
+ recipientEncryptedKeys = (ASN1Sequence)seq.getObjectAt(index++);
+ }
+
+ /**
+ * return a KeyAgreeRecipientInfo object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static KeyAgreeRecipientInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return a KeyAgreeRecipientInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static KeyAgreeRecipientInfo getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof KeyAgreeRecipientInfo)
+ {
+ return (KeyAgreeRecipientInfo)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new KeyAgreeRecipientInfo((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException(
+ "Illegal object in KeyAgreeRecipientInfo: " + obj.getClass().getName());
+
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public OriginatorIdentifierOrKey getOriginator()
+ {
+ return originator;
+ }
+
+ public ASN1OctetString getUserKeyingMaterial()
+ {
+ return ukm;
+ }
+
+ public AlgorithmIdentifier getKeyEncryptionAlgorithm()
+ {
+ return keyEncryptionAlgorithm;
+ }
+
+ public ASN1Sequence getRecipientEncryptedKeys()
+ {
+ return recipientEncryptedKeys;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * KeyAgreeRecipientInfo ::= SEQUENCE {
+ * version CMSVersion, -- always set to 3
+ * originator [0] EXPLICIT OriginatorIdentifierOrKey,
+ * ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * recipientEncryptedKeys RecipientEncryptedKeys
+ * }
+ *
+ * UserKeyingMaterial ::= OCTET STRING
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(new DERTaggedObject(true, 0, originator));
+
+ if (ukm != null)
+ {
+ v.add(new DERTaggedObject(true, 1, ukm));
+ }
+
+ v.add(keyEncryptionAlgorithm);
+ v.add(recipientEncryptedKeys);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/KeyTransRecipientInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,114 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class KeyTransRecipientInfo
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private RecipientIdentifier rid;
+ private AlgorithmIdentifier keyEncryptionAlgorithm;
+ private ASN1OctetString encryptedKey;
+
+ public KeyTransRecipientInfo(
+ RecipientIdentifier rid,
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ ASN1OctetString encryptedKey)
+ {
+ if (rid.toASN1Primitive() instanceof ASN1TaggedObject)
+ {
+ this.version = new ASN1Integer(2);
+ }
+ else
+ {
+ this.version = new ASN1Integer(0);
+ }
+
+ this.rid = rid;
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public KeyTransRecipientInfo(
+ ASN1Sequence seq)
+ {
+ this.version = (ASN1Integer)seq.getObjectAt(0);
+ this.rid = RecipientIdentifier.getInstance(seq.getObjectAt(1));
+ this.keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2));
+ this.encryptedKey = (ASN1OctetString)seq.getObjectAt(3);
+ }
+
+ /**
+ * return a KeyTransRecipientInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static KeyTransRecipientInfo getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof KeyTransRecipientInfo)
+ {
+ return (KeyTransRecipientInfo)obj;
+ }
+
+ if(obj instanceof ASN1Sequence)
+ {
+ return new KeyTransRecipientInfo((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException(
+ "Illegal object in KeyTransRecipientInfo: " + obj.getClass().getName());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public RecipientIdentifier getRecipientIdentifier()
+ {
+ return rid;
+ }
+
+ public AlgorithmIdentifier getKeyEncryptionAlgorithm()
+ {
+ return keyEncryptionAlgorithm;
+ }
+
+ public ASN1OctetString getEncryptedKey()
+ {
+ return encryptedKey;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * KeyTransRecipientInfo ::= SEQUENCE {
+ * version CMSVersion, -- always set to 0 or 2
+ * rid RecipientIdentifier,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * encryptedKey EncryptedKey
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(rid);
+ v.add(keyEncryptionAlgorithm);
+ v.add(encryptedKey);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/MetaData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/MetaData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/MetaData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/MetaData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,120 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1Boolean;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERUTF8String;
+
+public class MetaData
+ extends ASN1Object
+{
+ private ASN1Boolean hashProtected;
+ private DERUTF8String fileName;
+ private DERIA5String mediaType;
+ private Attributes otherMetaData;
+
+ public MetaData(
+ ASN1Boolean hashProtected,
+ DERUTF8String fileName,
+ DERIA5String mediaType,
+ Attributes otherMetaData)
+ {
+ this.hashProtected = hashProtected;
+ this.fileName = fileName;
+ this.mediaType = mediaType;
+ this.otherMetaData = otherMetaData;
+ }
+
+ private MetaData(ASN1Sequence seq)
+ {
+ this.hashProtected = ASN1Boolean.getInstance(seq.getObjectAt(0));
+
+ int index = 1;
+
+ if (index < seq.size() && seq.getObjectAt(index) instanceof DERUTF8String)
+ {
+ this.fileName = DERUTF8String.getInstance(seq.getObjectAt(index++));
+ }
+ if (index < seq.size() && seq.getObjectAt(index) instanceof DERIA5String)
+ {
+ this.mediaType = DERIA5String.getInstance(seq.getObjectAt(index++));
+ }
+ if (index < seq.size())
+ {
+ this.otherMetaData = Attributes.getInstance(seq.getObjectAt(index++));
+ }
+ }
+
+ public static MetaData getInstance(Object obj)
+ {
+ if (obj instanceof MetaData)
+ {
+ return (MetaData)obj;
+ }
+ else if (obj != null)
+ {
+ return new MetaData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ *
+ * MetaData ::= SEQUENCE {
+ * hashProtected BOOLEAN,
+ * fileName UTF8String OPTIONAL,
+ * mediaType IA5String OPTIONAL,
+ * otherMetaData Attributes OPTIONAL
+ * }
+ *
+ * @return
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(hashProtected);
+
+ if (fileName != null)
+ {
+ v.add(fileName);
+ }
+
+ if (mediaType != null)
+ {
+ v.add(mediaType);
+ }
+
+ if (otherMetaData != null)
+ {
+ v.add(otherMetaData);
+ }
+
+ return new DERSequence(v);
+ }
+
+ public boolean isHashProtected()
+ {
+ return hashProtected.isTrue();
+ }
+
+ public DERUTF8String getFileName()
+ {
+ return this.fileName;
+ }
+
+ public DERIA5String getMediaType()
+ {
+ return this.mediaType;
+ }
+
+ public Attributes getOtherMetaData()
+ {
+ return otherMetaData;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/OriginatorIdentifierOrKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,165 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
+
+public class OriginatorIdentifierOrKey
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private ASN1Encodable id;
+
+ public OriginatorIdentifierOrKey(
+ IssuerAndSerialNumber id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * @deprecated use version taking a SubjectKeyIdentifier
+ */
+ public OriginatorIdentifierOrKey(
+ ASN1OctetString id)
+ {
+ this(new SubjectKeyIdentifier(id.getOctets()));
+ }
+
+ public OriginatorIdentifierOrKey(
+ SubjectKeyIdentifier id)
+ {
+ this.id = new DERTaggedObject(false, 0, id);
+ }
+
+ public OriginatorIdentifierOrKey(
+ OriginatorPublicKey id)
+ {
+ this.id = new DERTaggedObject(false, 1, id);
+ }
+
+ /**
+ * @deprecated use more specific version
+ */
+ public OriginatorIdentifierOrKey(
+ ASN1Primitive id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * return an OriginatorIdentifierOrKey object from a tagged object.
+ *
+ * @param o the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OriginatorIdentifierOrKey getInstance(
+ ASN1TaggedObject o,
+ boolean explicit)
+ {
+ if (!explicit)
+ {
+ throw new IllegalArgumentException(
+ "Can't implicitly tag OriginatorIdentifierOrKey");
+ }
+
+ return getInstance(o.getObject());
+ }
+
+ /**
+ * return an OriginatorIdentifierOrKey object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static OriginatorIdentifierOrKey getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof OriginatorIdentifierOrKey)
+ {
+ return (OriginatorIdentifierOrKey)o;
+ }
+
+ if (o instanceof IssuerAndSerialNumber)
+ {
+ return new OriginatorIdentifierOrKey((IssuerAndSerialNumber)o);
+ }
+
+ if (o instanceof SubjectKeyIdentifier)
+ {
+ return new OriginatorIdentifierOrKey((SubjectKeyIdentifier)o);
+ }
+
+ if (o instanceof OriginatorPublicKey)
+ {
+ return new OriginatorIdentifierOrKey((OriginatorPublicKey)o);
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ // TODO Add validation
+ return new OriginatorIdentifierOrKey((ASN1TaggedObject)o);
+ }
+
+ throw new IllegalArgumentException("Invalid OriginatorIdentifierOrKey: " + o.getClass().getName());
+ }
+
+ public ASN1Encodable getId()
+ {
+ return id;
+ }
+
+ public IssuerAndSerialNumber getIssuerAndSerialNumber()
+ {
+ if (id instanceof IssuerAndSerialNumber)
+ {
+ return (IssuerAndSerialNumber)id;
+ }
+
+ return null;
+ }
+
+ public SubjectKeyIdentifier getSubjectKeyIdentifier()
+ {
+ if (id instanceof ASN1TaggedObject && ((ASN1TaggedObject)id).getTagNo() == 0)
+ {
+ return SubjectKeyIdentifier.getInstance((ASN1TaggedObject)id, false);
+ }
+
+ return null;
+ }
+
+ public OriginatorPublicKey getOriginatorKey()
+ {
+ if (id instanceof ASN1TaggedObject && ((ASN1TaggedObject)id).getTagNo() == 1)
+ {
+ return OriginatorPublicKey.getInstance((ASN1TaggedObject)id, false);
+ }
+
+ return null;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * OriginatorIdentifierOrKey ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier,
+ * originatorKey [1] OriginatorPublicKey
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return id.toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/OriginatorInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/OriginatorInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/OriginatorInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/OriginatorInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,128 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class OriginatorInfo
+ extends ASN1Object
+{
+ private ASN1Set certs;
+ private ASN1Set crls;
+
+ public OriginatorInfo(
+ ASN1Set certs,
+ ASN1Set crls)
+ {
+ this.certs = certs;
+ this.crls = crls;
+ }
+
+ private OriginatorInfo(
+ ASN1Sequence seq)
+ {
+ switch (seq.size())
+ {
+ case 0: // empty
+ break;
+ case 1:
+ ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(0);
+ switch (o.getTagNo())
+ {
+ case 0 :
+ certs = ASN1Set.getInstance(o, false);
+ break;
+ case 1 :
+ crls = ASN1Set.getInstance(o, false);
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag in OriginatorInfo: " + o.getTagNo());
+ }
+ break;
+ case 2:
+ certs = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(0), false);
+ crls = ASN1Set.getInstance((ASN1TaggedObject)seq.getObjectAt(1), false);
+ break;
+ default:
+ throw new IllegalArgumentException("OriginatorInfo too big");
+ }
+ }
+
+ /**
+ * return an OriginatorInfo object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OriginatorInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return an OriginatorInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static OriginatorInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof OriginatorInfo)
+ {
+ return (OriginatorInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new OriginatorInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Set getCertificates()
+ {
+ return certs;
+ }
+
+ public ASN1Set getCRLs()
+ {
+ return crls;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * OriginatorInfo ::= SEQUENCE {
+ * certs [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (certs != null)
+ {
+ v.add(new DERTaggedObject(false, 0, certs));
+ }
+
+ if (crls != null)
+ {
+ v.add(new DERTaggedObject(false, 1, crls));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/OriginatorPublicKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/OriginatorPublicKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/OriginatorPublicKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/OriginatorPublicKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,100 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+
+public class OriginatorPublicKey
+ extends ASN1Object
+{
+ private AlgorithmIdentifier algorithm;
+ private DERBitString publicKey;
+
+ public OriginatorPublicKey(
+ AlgorithmIdentifier algorithm,
+ byte[] publicKey)
+ {
+ this.algorithm = algorithm;
+ this.publicKey = new DERBitString(publicKey);
+ }
+
+ public OriginatorPublicKey(
+ ASN1Sequence seq)
+ {
+ algorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ publicKey = (DERBitString)seq.getObjectAt(1);
+ }
+
+ /**
+ * return an OriginatorPublicKey object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OriginatorPublicKey getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return an OriginatorPublicKey object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static OriginatorPublicKey getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof OriginatorPublicKey)
+ {
+ return (OriginatorPublicKey)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new OriginatorPublicKey((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid OriginatorPublicKey: " + obj.getClass().getName());
+ }
+
+ public AlgorithmIdentifier getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ public DERBitString getPublicKey()
+ {
+ return publicKey;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * OriginatorPublicKey ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * publicKey BIT STRING
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(algorithm);
+ v.add(publicKey);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/OtherKeyAttribute.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/OtherKeyAttribute.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/OtherKeyAttribute.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/OtherKeyAttribute.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,82 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class OtherKeyAttribute
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier keyAttrId;
+ private ASN1Encodable keyAttr;
+
+ /**
+ * return an OtherKeyAttribute object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static OtherKeyAttribute getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof OtherKeyAttribute)
+ {
+ return (OtherKeyAttribute)o;
+ }
+
+ if (o instanceof ASN1Sequence)
+ {
+ return new OtherKeyAttribute((ASN1Sequence)o);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
+ }
+
+ public OtherKeyAttribute(
+ ASN1Sequence seq)
+ {
+ keyAttrId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ keyAttr = seq.getObjectAt(1);
+ }
+
+ public OtherKeyAttribute(
+ ASN1ObjectIdentifier keyAttrId,
+ ASN1Encodable keyAttr)
+ {
+ this.keyAttrId = keyAttrId;
+ this.keyAttr = keyAttr;
+ }
+
+ public ASN1ObjectIdentifier getKeyAttrId()
+ {
+ return keyAttrId;
+ }
+
+ public ASN1Encodable getKeyAttr()
+ {
+ return keyAttr;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * OtherKeyAttribute ::= SEQUENCE {
+ * keyAttrId OBJECT IDENTIFIER,
+ * keyAttr ANY DEFINED BY keyAttrId OPTIONAL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(keyAttrId);
+ v.add(keyAttr);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/OtherRecipientInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/OtherRecipientInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/OtherRecipientInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/OtherRecipientInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,98 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class OtherRecipientInfo
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier oriType;
+ private ASN1Encodable oriValue;
+
+ public OtherRecipientInfo(
+ ASN1ObjectIdentifier oriType,
+ ASN1Encodable oriValue)
+ {
+ this.oriType = oriType;
+ this.oriValue = oriValue;
+ }
+
+ public OtherRecipientInfo(
+ ASN1Sequence seq)
+ {
+ oriType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ oriValue = seq.getObjectAt(1);
+ }
+
+ /**
+ * return a OtherRecipientInfo object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static OtherRecipientInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return a OtherRecipientInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static OtherRecipientInfo getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof OtherRecipientInfo)
+ {
+ return (OtherRecipientInfo)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new OtherRecipientInfo((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid OtherRecipientInfo: " + obj.getClass().getName());
+ }
+
+ public ASN1ObjectIdentifier getType()
+ {
+ return oriType;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ return oriValue;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * OtherRecipientInfo ::= SEQUENCE {
+ * oriType OBJECT IDENTIFIER,
+ * oriValue ANY DEFINED BY oriType }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(oriType);
+ v.add(oriValue);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/PasswordRecipientInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,143 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class PasswordRecipientInfo
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private AlgorithmIdentifier keyDerivationAlgorithm;
+ private AlgorithmIdentifier keyEncryptionAlgorithm;
+ private ASN1OctetString encryptedKey;
+
+ public PasswordRecipientInfo(
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ ASN1OctetString encryptedKey)
+ {
+ this.version = new ASN1Integer(0);
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public PasswordRecipientInfo(
+ AlgorithmIdentifier keyDerivationAlgorithm,
+ AlgorithmIdentifier keyEncryptionAlgorithm,
+ ASN1OctetString encryptedKey)
+ {
+ this.version = new ASN1Integer(0);
+ this.keyDerivationAlgorithm = keyDerivationAlgorithm;
+ this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public PasswordRecipientInfo(
+ ASN1Sequence seq)
+ {
+ version = (ASN1Integer)seq.getObjectAt(0);
+ if (seq.getObjectAt(1) instanceof ASN1TaggedObject)
+ {
+ keyDerivationAlgorithm = AlgorithmIdentifier.getInstance((ASN1TaggedObject)seq.getObjectAt(1), false);
+ keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(2));
+ encryptedKey = (ASN1OctetString)seq.getObjectAt(3);
+ }
+ else
+ {
+ keyEncryptionAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ encryptedKey = (ASN1OctetString)seq.getObjectAt(2);
+ }
+ }
+
+ /**
+ * return a PasswordRecipientInfo object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static PasswordRecipientInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return a PasswordRecipientInfo object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static PasswordRecipientInfo getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof PasswordRecipientInfo)
+ {
+ return (PasswordRecipientInfo)obj;
+ }
+
+ if(obj instanceof ASN1Sequence)
+ {
+ return new PasswordRecipientInfo((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid PasswordRecipientInfo: " + obj.getClass().getName());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public AlgorithmIdentifier getKeyDerivationAlgorithm()
+ {
+ return keyDerivationAlgorithm;
+ }
+
+ public AlgorithmIdentifier getKeyEncryptionAlgorithm()
+ {
+ return keyEncryptionAlgorithm;
+ }
+
+ public ASN1OctetString getEncryptedKey()
+ {
+ return encryptedKey;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * PasswordRecipientInfo ::= SEQUENCE {
+ * version CMSVersion, -- Always set to 0
+ * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier
+ * OPTIONAL,
+ * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+ * encryptedKey EncryptedKey }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+
+ if (keyDerivationAlgorithm != null)
+ {
+ v.add(new DERTaggedObject(false, 0, keyDerivationAlgorithm));
+ }
+ v.add(keyEncryptionAlgorithm);
+ v.add(encryptedKey);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/RecipientEncryptedKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,99 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+
+public class RecipientEncryptedKey
+ extends ASN1Object
+{
+ private KeyAgreeRecipientIdentifier identifier;
+ private ASN1OctetString encryptedKey;
+
+ private RecipientEncryptedKey(
+ ASN1Sequence seq)
+ {
+ identifier = KeyAgreeRecipientIdentifier.getInstance(seq.getObjectAt(0));
+ encryptedKey = (ASN1OctetString)seq.getObjectAt(1);
+ }
+
+ /**
+ * return an RecipientEncryptedKey object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static RecipientEncryptedKey getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return a RecipientEncryptedKey object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static RecipientEncryptedKey getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof RecipientEncryptedKey)
+ {
+ return (RecipientEncryptedKey)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new RecipientEncryptedKey((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid RecipientEncryptedKey: " + obj.getClass().getName());
+ }
+
+ public RecipientEncryptedKey(
+ KeyAgreeRecipientIdentifier id,
+ ASN1OctetString encryptedKey)
+ {
+ this.identifier = id;
+ this.encryptedKey = encryptedKey;
+ }
+
+ public KeyAgreeRecipientIdentifier getIdentifier()
+ {
+ return identifier;
+ }
+
+ public ASN1OctetString getEncryptedKey()
+ {
+ return encryptedKey;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * RecipientEncryptedKey ::= SEQUENCE {
+ * rid KeyAgreeRecipientIdentifier,
+ * encryptedKey EncryptedKey
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(identifier);
+ v.add(encryptedKey);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/RecipientIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/RecipientIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/RecipientIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/RecipientIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,98 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class RecipientIdentifier
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private ASN1Encodable id;
+
+ public RecipientIdentifier(
+ IssuerAndSerialNumber id)
+ {
+ this.id = id;
+ }
+
+ public RecipientIdentifier(
+ ASN1OctetString id)
+ {
+ this.id = new DERTaggedObject(false, 0, id);
+ }
+
+ public RecipientIdentifier(
+ ASN1Primitive id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * return a RecipientIdentifier object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static RecipientIdentifier getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof RecipientIdentifier)
+ {
+ return (RecipientIdentifier)o;
+ }
+
+ if (o instanceof IssuerAndSerialNumber)
+ {
+ return new RecipientIdentifier((IssuerAndSerialNumber)o);
+ }
+
+ if (o instanceof ASN1OctetString)
+ {
+ return new RecipientIdentifier((ASN1OctetString)o);
+ }
+
+ if (o instanceof ASN1Primitive)
+ {
+ return new RecipientIdentifier((ASN1Primitive)o);
+ }
+
+ throw new IllegalArgumentException(
+ "Illegal object in RecipientIdentifier: " + o.getClass().getName());
+ }
+
+ public boolean isTagged()
+ {
+ return (id instanceof ASN1TaggedObject);
+ }
+
+ public ASN1Encodable getId()
+ {
+ if (id instanceof ASN1TaggedObject)
+ {
+ return ASN1OctetString.getInstance((ASN1TaggedObject)id, false);
+ }
+
+ return IssuerAndSerialNumber.getInstance(id);
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * RecipientIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return id.toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/RecipientInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/RecipientInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/RecipientInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/RecipientInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,154 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class RecipientInfo
+ extends ASN1Object
+ implements ASN1Choice
+{
+ ASN1Encodable info;
+
+ public RecipientInfo(
+ KeyTransRecipientInfo info)
+ {
+ this.info = info;
+ }
+
+ public RecipientInfo(
+ KeyAgreeRecipientInfo info)
+ {
+ this.info = new DERTaggedObject(false, 1, info);
+ }
+
+ public RecipientInfo(
+ KEKRecipientInfo info)
+ {
+ this.info = new DERTaggedObject(false, 2, info);
+ }
+
+ public RecipientInfo(
+ PasswordRecipientInfo info)
+ {
+ this.info = new DERTaggedObject(false, 3, info);
+ }
+
+ public RecipientInfo(
+ OtherRecipientInfo info)
+ {
+ this.info = new DERTaggedObject(false, 4, info);
+ }
+
+ public RecipientInfo(
+ ASN1Primitive info)
+ {
+ this.info = info;
+ }
+
+ public static RecipientInfo getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof RecipientInfo)
+ {
+ return (RecipientInfo)o;
+ }
+ else if (o instanceof ASN1Sequence)
+ {
+ return new RecipientInfo((ASN1Sequence)o);
+ }
+ else if (o instanceof ASN1TaggedObject)
+ {
+ return new RecipientInfo((ASN1TaggedObject)o);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: "
+ + o.getClass().getName());
+ }
+
+ public ASN1Integer getVersion()
+ {
+ if (info instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)info;
+
+ switch (o.getTagNo())
+ {
+ case 1:
+ return KeyAgreeRecipientInfo.getInstance(o, false).getVersion();
+ case 2:
+ return getKEKInfo(o).getVersion();
+ case 3:
+ return PasswordRecipientInfo.getInstance(o, false).getVersion();
+ case 4:
+ return new ASN1Integer(0); // no syntax version for OtherRecipientInfo
+ default:
+ throw new IllegalStateException("unknown tag");
+ }
+ }
+
+ return KeyTransRecipientInfo.getInstance(info).getVersion();
+ }
+
+ public boolean isTagged()
+ {
+ return (info instanceof ASN1TaggedObject);
+ }
+
+ public ASN1Encodable getInfo()
+ {
+ if (info instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)info;
+
+ switch (o.getTagNo())
+ {
+ case 1:
+ return KeyAgreeRecipientInfo.getInstance(o, false);
+ case 2:
+ return getKEKInfo(o);
+ case 3:
+ return PasswordRecipientInfo.getInstance(o, false);
+ case 4:
+ return OtherRecipientInfo.getInstance(o, false);
+ default:
+ throw new IllegalStateException("unknown tag");
+ }
+ }
+
+ return KeyTransRecipientInfo.getInstance(info);
+ }
+
+ private KEKRecipientInfo getKEKInfo(ASN1TaggedObject o)
+ {
+ if (o.isExplicit())
+ { // compatibilty with erroneous version
+ return KEKRecipientInfo.getInstance(o, true);
+ }
+ else
+ {
+ return KEKRecipientInfo.getInstance(o, false);
+ }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * RecipientInfo ::= CHOICE {
+ * ktri KeyTransRecipientInfo,
+ * kari [1] KeyAgreeRecipientInfo,
+ * kekri [2] KEKRecipientInfo,
+ * pwri [3] PasswordRecipientInfo,
+ * ori [4] OtherRecipientInfo }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return info.toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/RecipientKeyIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,156 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERGeneralizedTime;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class RecipientKeyIdentifier
+ extends ASN1Object
+{
+ private ASN1OctetString subjectKeyIdentifier;
+ private DERGeneralizedTime date;
+ private OtherKeyAttribute other;
+
+ public RecipientKeyIdentifier(
+ ASN1OctetString subjectKeyIdentifier,
+ DERGeneralizedTime date,
+ OtherKeyAttribute other)
+ {
+ this.subjectKeyIdentifier = subjectKeyIdentifier;
+ this.date = date;
+ this.other = other;
+ }
+
+ public RecipientKeyIdentifier(
+ byte[] subjectKeyIdentifier,
+ DERGeneralizedTime date,
+ OtherKeyAttribute other)
+ {
+ this.subjectKeyIdentifier = new DEROctetString(subjectKeyIdentifier);
+ this.date = date;
+ this.other = other;
+ }
+
+ public RecipientKeyIdentifier(
+ byte[] subjectKeyIdentifier)
+ {
+ this(subjectKeyIdentifier, null, null);
+ }
+
+ public RecipientKeyIdentifier(
+ ASN1Sequence seq)
+ {
+ subjectKeyIdentifier = ASN1OctetString.getInstance(
+ seq.getObjectAt(0));
+
+ switch(seq.size())
+ {
+ case 1:
+ break;
+ case 2:
+ if (seq.getObjectAt(1) instanceof DERGeneralizedTime)
+ {
+ date = (DERGeneralizedTime)seq.getObjectAt(1);
+ }
+ else
+ {
+ other = OtherKeyAttribute.getInstance(seq.getObjectAt(2));
+ }
+ break;
+ case 3:
+ date = (DERGeneralizedTime)seq.getObjectAt(1);
+ other = OtherKeyAttribute.getInstance(seq.getObjectAt(2));
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid RecipientKeyIdentifier");
+ }
+ }
+
+ /**
+ * return a RecipientKeyIdentifier object from a tagged object.
+ *
+ * @param _ato the tagged object holding the object we want.
+ * @param _explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @exception IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static RecipientKeyIdentifier getInstance(ASN1TaggedObject _ato, boolean _explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(_ato, _explicit));
+ }
+
+ /**
+ * return a RecipientKeyIdentifier object from the given object.
+ *
+ * @param _obj the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static RecipientKeyIdentifier getInstance(Object _obj)
+ {
+ if(_obj == null || _obj instanceof RecipientKeyIdentifier)
+ {
+ return (RecipientKeyIdentifier)_obj;
+ }
+
+ if(_obj instanceof ASN1Sequence)
+ {
+ return new RecipientKeyIdentifier((ASN1Sequence)_obj);
+ }
+
+ throw new IllegalArgumentException("Invalid RecipientKeyIdentifier: " + _obj.getClass().getName());
+ }
+
+ public ASN1OctetString getSubjectKeyIdentifier()
+ {
+ return subjectKeyIdentifier;
+ }
+
+ public DERGeneralizedTime getDate()
+ {
+ return date;
+ }
+
+ public OtherKeyAttribute getOtherKeyAttribute()
+ {
+ return other;
+ }
+
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * RecipientKeyIdentifier ::= SEQUENCE {
+ * subjectKeyIdentifier SubjectKeyIdentifier,
+ * date GeneralizedTime OPTIONAL,
+ * other OtherKeyAttribute OPTIONAL
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(subjectKeyIdentifier);
+
+ if (date != null)
+ {
+ v.add(date);
+ }
+
+ if (other != null)
+ {
+ v.add(other);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/SignedData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/SignedData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/SignedData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/SignedData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,302 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.BERSet;
+import pdftk.org.bouncycastle.asn1.BERTaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * a signed data object.
+ */
+public class SignedData
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private ASN1Set digestAlgorithms;
+ private ContentInfo contentInfo;
+ private ASN1Set certificates;
+ private ASN1Set crls;
+ private ASN1Set signerInfos;
+ private boolean certsBer;
+ private boolean crlsBer;
+
+ public static SignedData getInstance(
+ Object o)
+ {
+ if (o instanceof SignedData)
+ {
+ return (SignedData)o;
+ }
+ else if (o != null)
+ {
+ return new SignedData(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public SignedData(
+ ASN1Set digestAlgorithms,
+ ContentInfo contentInfo,
+ ASN1Set certificates,
+ ASN1Set crls,
+ ASN1Set signerInfos)
+ {
+ this.version = calculateVersion(contentInfo.getContentType(), certificates, crls, signerInfos);
+ this.digestAlgorithms = digestAlgorithms;
+ this.contentInfo = contentInfo;
+ this.certificates = certificates;
+ this.crls = crls;
+ this.signerInfos = signerInfos;
+ this.crlsBer = crls instanceof BERSet;
+ this.certsBer = certificates instanceof BERSet;
+ }
+
+
+ // RFC3852, section 5.1:
+ // IF ((certificates is present) AND
+ // (any certificates with a type of other are present)) OR
+ // ((crls is present) AND
+ // (any crls with a type of other are present))
+ // THEN version MUST be 5
+ // ELSE
+ // IF (certificates is present) AND
+ // (any version 2 attribute certificates are present)
+ // THEN version MUST be 4
+ // ELSE
+ // IF ((certificates is present) AND
+ // (any version 1 attribute certificates are present)) OR
+ // (any SignerInfo structures are version 3) OR
+ // (encapContentInfo eContentType is other than id-data)
+ // THEN version MUST be 3
+ // ELSE version MUST be 1
+ //
+ private ASN1Integer calculateVersion(
+ ASN1ObjectIdentifier contentOid,
+ ASN1Set certs,
+ ASN1Set crls,
+ ASN1Set signerInfs)
+ {
+ boolean otherCert = false;
+ boolean otherCrl = false;
+ boolean attrCertV1Found = false;
+ boolean attrCertV2Found = false;
+
+ if (certs != null)
+ {
+ for (Enumeration en = certs.getObjects(); en.hasMoreElements();)
+ {
+ Object obj = en.nextElement();
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagged = ASN1TaggedObject.getInstance(obj);
+
+ if (tagged.getTagNo() == 1)
+ {
+ attrCertV1Found = true;
+ }
+ else if (tagged.getTagNo() == 2)
+ {
+ attrCertV2Found = true;
+ }
+ else if (tagged.getTagNo() == 3)
+ {
+ otherCert = true;
+ }
+ }
+ }
+ }
+
+ if (otherCert)
+ {
+ return new ASN1Integer(5);
+ }
+
+ if (crls != null) // no need to check if otherCert is true
+ {
+ for (Enumeration en = crls.getObjects(); en.hasMoreElements();)
+ {
+ Object obj = en.nextElement();
+ if (obj instanceof ASN1TaggedObject)
+ {
+ otherCrl = true;
+ }
+ }
+ }
+
+ if (otherCrl)
+ {
+ return new ASN1Integer(5);
+ }
+
+ if (attrCertV2Found)
+ {
+ return new ASN1Integer(4);
+ }
+
+ if (attrCertV1Found)
+ {
+ return new ASN1Integer(3);
+ }
+
+ if (checkForVersion3(signerInfs))
+ {
+ return new ASN1Integer(3);
+ }
+
+ if (!CMSObjectIdentifiers.data.equals(contentOid))
+ {
+ return new ASN1Integer(3);
+ }
+
+ return new ASN1Integer(1);
+ }
+
+ private boolean checkForVersion3(ASN1Set signerInfs)
+ {
+ for (Enumeration e = signerInfs.getObjects(); e.hasMoreElements();)
+ {
+ SignerInfo s = SignerInfo.getInstance(e.nextElement());
+
+ if (s.getVersion().getValue().intValue() == 3)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private SignedData(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ version = ASN1Integer.getInstance(e.nextElement());
+ digestAlgorithms = ((ASN1Set)e.nextElement());
+ contentInfo = ContentInfo.getInstance(e.nextElement());
+
+ while (e.hasMoreElements())
+ {
+ ASN1Primitive o = (ASN1Primitive)e.nextElement();
+
+ //
+ // an interesting feature of SignedData is that there appear
+ // to be varying implementations...
+ // for the moment we ignore anything which doesn't fit.
+ //
+ if (o instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagged = (ASN1TaggedObject)o;
+
+ switch (tagged.getTagNo())
+ {
+ case 0:
+ certsBer = tagged instanceof BERTaggedObject;
+ certificates = ASN1Set.getInstance(tagged, false);
+ break;
+ case 1:
+ crlsBer = tagged instanceof BERTaggedObject;
+ crls = ASN1Set.getInstance(tagged, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag value " + tagged.getTagNo());
+ }
+ }
+ else
+ {
+ signerInfos = (ASN1Set)o;
+ }
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public ASN1Set getDigestAlgorithms()
+ {
+ return digestAlgorithms;
+ }
+
+ public ContentInfo getEncapContentInfo()
+ {
+ return contentInfo;
+ }
+
+ public ASN1Set getCertificates()
+ {
+ return certificates;
+ }
+
+ public ASN1Set getCRLs()
+ {
+ return crls;
+ }
+
+ public ASN1Set getSignerInfos()
+ {
+ return signerInfos;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * SignedData ::= SEQUENCE {
+ * version CMSVersion,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * encapContentInfo EncapsulatedContentInfo,
+ * certificates [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(digestAlgorithms);
+ v.add(contentInfo);
+
+ if (certificates != null)
+ {
+ if (certsBer)
+ {
+ v.add(new BERTaggedObject(false, 0, certificates));
+ }
+ else
+ {
+ v.add(new DERTaggedObject(false, 0, certificates));
+ }
+ }
+
+ if (crls != null)
+ {
+ if (crlsBer)
+ {
+ v.add(new BERTaggedObject(false, 1, crls));
+ }
+ else
+ {
+ v.add(new DERTaggedObject(false, 1, crls));
+ }
+ }
+
+ v.add(signerInfos);
+
+ return new BERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/SignedDataParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/SignedDataParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/SignedDataParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/SignedDataParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,139 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1SequenceParser;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1SetParser;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObjectParser;
+import pdftk.org.bouncycastle.asn1.BERTags;
+
+/**
+ *
+ * SignedData ::= SEQUENCE {
+ * version CMSVersion,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * encapContentInfo EncapsulatedContentInfo,
+ * certificates [0] IMPLICIT CertificateSet OPTIONAL,
+ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos
+ * }
+ *
+ */
+public class SignedDataParser
+{
+ private ASN1SequenceParser _seq;
+ private ASN1Integer _version;
+ private Object _nextObject;
+ private boolean _certsCalled;
+ private boolean _crlsCalled;
+
+ public static SignedDataParser getInstance(
+ Object o)
+ throws IOException
+ {
+ if (o instanceof ASN1Sequence)
+ {
+ return new SignedDataParser(((ASN1Sequence)o).parser());
+ }
+ if (o instanceof ASN1SequenceParser)
+ {
+ return new SignedDataParser((ASN1SequenceParser)o);
+ }
+
+ throw new IOException("unknown object encountered: " + o.getClass().getName());
+ }
+
+ private SignedDataParser(
+ ASN1SequenceParser seq)
+ throws IOException
+ {
+ this._seq = seq;
+ this._version = (ASN1Integer)seq.readObject();
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return _version;
+ }
+
+ public ASN1SetParser getDigestAlgorithms()
+ throws IOException
+ {
+ Object o = _seq.readObject();
+
+ if (o instanceof ASN1Set)
+ {
+ return ((ASN1Set)o).parser();
+ }
+
+ return (ASN1SetParser)o;
+ }
+
+ public ContentInfoParser getEncapContentInfo()
+ throws IOException
+ {
+ return new ContentInfoParser((ASN1SequenceParser)_seq.readObject());
+ }
+
+ public ASN1SetParser getCertificates()
+ throws IOException
+ {
+ _certsCalled = true;
+ _nextObject = _seq.readObject();
+
+ if (_nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)_nextObject).getTagNo() == 0)
+ {
+ ASN1SetParser certs = (ASN1SetParser)((ASN1TaggedObjectParser)_nextObject).getObjectParser(BERTags.SET, false);
+ _nextObject = null;
+
+ return certs;
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getCrls()
+ throws IOException
+ {
+ if (!_certsCalled)
+ {
+ throw new IOException("getCerts() has not been called.");
+ }
+
+ _crlsCalled = true;
+
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.readObject();
+ }
+
+ if (_nextObject instanceof ASN1TaggedObjectParser && ((ASN1TaggedObjectParser)_nextObject).getTagNo() == 1)
+ {
+ ASN1SetParser crls = (ASN1SetParser)((ASN1TaggedObjectParser)_nextObject).getObjectParser(BERTags.SET, false);
+ _nextObject = null;
+
+ return crls;
+ }
+
+ return null;
+ }
+
+ public ASN1SetParser getSignerInfos()
+ throws IOException
+ {
+ if (!_certsCalled || !_crlsCalled)
+ {
+ throw new IOException("getCerts() and/or getCrls() has not been called.");
+ }
+
+ if (_nextObject == null)
+ {
+ _nextObject = _seq.readObject();
+ }
+
+ return (ASN1SetParser)_nextObject;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/SignerIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/SignerIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/SignerIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/SignerIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,98 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class SignerIdentifier
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private ASN1Encodable id;
+
+ public SignerIdentifier(
+ IssuerAndSerialNumber id)
+ {
+ this.id = id;
+ }
+
+ public SignerIdentifier(
+ ASN1OctetString id)
+ {
+ this.id = new DERTaggedObject(false, 0, id);
+ }
+
+ public SignerIdentifier(
+ ASN1Primitive id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * return a SignerIdentifier object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static SignerIdentifier getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof SignerIdentifier)
+ {
+ return (SignerIdentifier)o;
+ }
+
+ if (o instanceof IssuerAndSerialNumber)
+ {
+ return new SignerIdentifier((IssuerAndSerialNumber)o);
+ }
+
+ if (o instanceof ASN1OctetString)
+ {
+ return new SignerIdentifier((ASN1OctetString)o);
+ }
+
+ if (o instanceof ASN1Primitive)
+ {
+ return new SignerIdentifier((ASN1Primitive)o);
+ }
+
+ throw new IllegalArgumentException(
+ "Illegal object in SignerIdentifier: " + o.getClass().getName());
+ }
+
+ public boolean isTagged()
+ {
+ return (id instanceof ASN1TaggedObject);
+ }
+
+ public ASN1Encodable getId()
+ {
+ if (id instanceof ASN1TaggedObject)
+ {
+ return ASN1OctetString.getInstance((ASN1TaggedObject)id, false);
+ }
+
+ return id;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * SignerIdentifier ::= CHOICE {
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * subjectKeyIdentifier [0] SubjectKeyIdentifier
+ * }
+ *
+ * SubjectKeyIdentifier ::= OCTET STRING
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return id.toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/SignerInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/SignerInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/SignerInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/SignerInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,183 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class SignerInfo
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private SignerIdentifier sid;
+ private AlgorithmIdentifier digAlgorithm;
+ private ASN1Set authenticatedAttributes;
+ private AlgorithmIdentifier digEncryptionAlgorithm;
+ private ASN1OctetString encryptedDigest;
+ private ASN1Set unauthenticatedAttributes;
+
+ public static SignerInfo getInstance(
+ Object o)
+ throws IllegalArgumentException
+ {
+ if (o == null || o instanceof SignerInfo)
+ {
+ return (SignerInfo)o;
+ }
+ else if (o instanceof ASN1Sequence)
+ {
+ return new SignerInfo((ASN1Sequence)o);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
+ }
+
+ public SignerInfo(
+ SignerIdentifier sid,
+ AlgorithmIdentifier digAlgorithm,
+ ASN1Set authenticatedAttributes,
+ AlgorithmIdentifier digEncryptionAlgorithm,
+ ASN1OctetString encryptedDigest,
+ ASN1Set unauthenticatedAttributes)
+ {
+ if (sid.isTagged())
+ {
+ this.version = new ASN1Integer(3);
+ }
+ else
+ {
+ this.version = new ASN1Integer(1);
+ }
+
+ this.sid = sid;
+ this.digAlgorithm = digAlgorithm;
+ this.authenticatedAttributes = authenticatedAttributes;
+ this.digEncryptionAlgorithm = digEncryptionAlgorithm;
+ this.encryptedDigest = encryptedDigest;
+ this.unauthenticatedAttributes = unauthenticatedAttributes;
+ }
+
+ public SignerInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ version = (ASN1Integer)e.nextElement();
+ sid = SignerIdentifier.getInstance(e.nextElement());
+ digAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
+
+ Object obj = e.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ authenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)obj, false);
+
+ digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
+ }
+ else
+ {
+ authenticatedAttributes = null;
+ digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(obj);
+ }
+
+ encryptedDigest = DEROctetString.getInstance(e.nextElement());
+
+ if (e.hasMoreElements())
+ {
+ unauthenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
+ }
+ else
+ {
+ unauthenticatedAttributes = null;
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public SignerIdentifier getSID()
+ {
+ return sid;
+ }
+
+ public ASN1Set getAuthenticatedAttributes()
+ {
+ return authenticatedAttributes;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ {
+ return digAlgorithm;
+ }
+
+ public ASN1OctetString getEncryptedDigest()
+ {
+ return encryptedDigest;
+ }
+
+ public AlgorithmIdentifier getDigestEncryptionAlgorithm()
+ {
+ return digEncryptionAlgorithm;
+ }
+
+ public ASN1Set getUnauthenticatedAttributes()
+ {
+ return unauthenticatedAttributes;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * SignerInfo ::= SEQUENCE {
+ * version Version,
+ * SignerIdentifier sid,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+ * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ * encryptedDigest EncryptedDigest,
+ * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+ * }
+ *
+ * EncryptedDigest ::= OCTET STRING
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(sid);
+ v.add(digAlgorithm);
+
+ if (authenticatedAttributes != null)
+ {
+ v.add(new DERTaggedObject(false, 0, authenticatedAttributes));
+ }
+
+ v.add(digEncryptionAlgorithm);
+ v.add(encryptedDigest);
+
+ if (unauthenticatedAttributes != null)
+ {
+ v.add(new DERTaggedObject(false, 1, unauthenticatedAttributes));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/Time.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/Time.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/Time.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/Time.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,128 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.SimpleTimeZone;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERGeneralizedTime;
+import pdftk.org.bouncycastle.asn1.DERUTCTime;
+
+public class Time
+ extends ASN1Object
+ implements ASN1Choice
+{
+ ASN1Primitive time;
+
+ public static Time getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject());
+ }
+
+ public Time(
+ ASN1Primitive time)
+ {
+ if (!(time instanceof DERUTCTime)
+ && !(time instanceof DERGeneralizedTime))
+ {
+ throw new IllegalArgumentException("unknown object passed to Time");
+ }
+
+ this.time = time;
+ }
+
+ /**
+ * creates a time object from a given date - if the date is between 1950
+ * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
+ * is used.
+ */
+ public Time(
+ Date date)
+ {
+ SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss");
+
+ dateF.setTimeZone(tz);
+
+ String d = dateF.format(date) + "Z";
+ int year = Integer.parseInt(d.substring(0, 4));
+
+ if (year < 1950 || year > 2049)
+ {
+ time = new DERGeneralizedTime(d);
+ }
+ else
+ {
+ time = new DERUTCTime(d.substring(2));
+ }
+ }
+
+ public static Time getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof Time)
+ {
+ return (Time)obj;
+ }
+ else if (obj instanceof DERUTCTime)
+ {
+ return new Time((DERUTCTime)obj);
+ }
+ else if (obj instanceof DERGeneralizedTime)
+ {
+ return new Time((DERGeneralizedTime)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public String getTime()
+ {
+ if (time instanceof DERUTCTime)
+ {
+ return ((DERUTCTime)time).getAdjustedTime();
+ }
+ else
+ {
+ return ((DERGeneralizedTime)time).getTime();
+ }
+ }
+
+ public Date getDate()
+ {
+ try
+ {
+ if (time instanceof DERUTCTime)
+ {
+ return ((DERUTCTime)time).getAdjustedDate();
+ }
+ else
+ {
+ return ((DERGeneralizedTime)time).getDate();
+ }
+ }
+ catch (ParseException e)
+ { // this should never happen
+ throw new IllegalStateException("invalid date string: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return time;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/TimeStampAndCRL.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/TimeStampAndCRL.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/TimeStampAndCRL.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/TimeStampAndCRL.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,82 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.CertificateList;
+
+public class TimeStampAndCRL
+ extends ASN1Object
+{
+ private ContentInfo timeStamp;
+ private CertificateList crl;
+
+ public TimeStampAndCRL(ContentInfo timeStamp)
+ {
+ this.timeStamp = timeStamp;
+ }
+
+ private TimeStampAndCRL(ASN1Sequence seq)
+ {
+ this.timeStamp = ContentInfo.getInstance(seq.getObjectAt(0));
+ if (seq.size() == 2)
+ {
+ this.crl = CertificateList.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public static TimeStampAndCRL getInstance(Object obj)
+ {
+ if (obj instanceof TimeStampAndCRL)
+ {
+ return (TimeStampAndCRL)obj;
+ }
+ else if (obj != null)
+ {
+ return new TimeStampAndCRL(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ContentInfo getTimeStampToken()
+ {
+ return this.timeStamp;
+ }
+
+ /** @deprecated use getCRL() */
+ public CertificateList getCertificateList()
+ {
+ return this.crl;
+ }
+
+ public CertificateList getCRL()
+ {
+ return this.crl;
+ }
+
+ /**
+ *
+ * TimeStampAndCRL ::= SEQUENCE {
+ * timeStamp TimeStampToken, -- according to RFC 3161
+ * crl CertificateList OPTIONAL -- according to RFC 5280
+ * }
+ *
+ * @return
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(timeStamp);
+
+ if (crl != null)
+ {
+ v.add(crl);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/TimeStampTokenEvidence.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,84 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class TimeStampTokenEvidence
+ extends ASN1Object
+{
+ private TimeStampAndCRL[] timeStampAndCRLs;
+
+ public TimeStampTokenEvidence(TimeStampAndCRL[] timeStampAndCRLs)
+ {
+ this.timeStampAndCRLs = timeStampAndCRLs;
+ }
+
+ public TimeStampTokenEvidence(TimeStampAndCRL timeStampAndCRL)
+ {
+ this.timeStampAndCRLs = new TimeStampAndCRL[1];
+
+ timeStampAndCRLs[0] = timeStampAndCRL;
+ }
+
+ private TimeStampTokenEvidence(ASN1Sequence seq)
+ {
+ this.timeStampAndCRLs = new TimeStampAndCRL[seq.size()];
+
+ int count = 0;
+
+ for (Enumeration en = seq.getObjects(); en.hasMoreElements();)
+ {
+ timeStampAndCRLs[count++] = TimeStampAndCRL.getInstance(en.nextElement());
+ }
+ }
+
+ public static TimeStampTokenEvidence getInstance(ASN1TaggedObject tagged, boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(tagged, explicit));
+ }
+
+ public static TimeStampTokenEvidence getInstance(Object obj)
+ {
+ if (obj instanceof TimeStampTokenEvidence)
+ {
+ return (TimeStampTokenEvidence)obj;
+ }
+ else if (obj != null)
+ {
+ return new TimeStampTokenEvidence(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public TimeStampAndCRL[] toTimeStampAndCRLArray()
+ {
+ return timeStampAndCRLs;
+ }
+
+ /**
+ *
+ * TimeStampTokenEvidence ::=
+ * SEQUENCE SIZE(1..MAX) OF TimeStampAndCRL
+ *
+ * @return
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != timeStampAndCRLs.length; i++)
+ {
+ v.add(timeStampAndCRLs[i]);
+ }
+
+ return new DERSequence(v);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/TimeStampedData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/TimeStampedData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/TimeStampedData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/TimeStampedData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,121 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+
+public class TimeStampedData
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private DERIA5String dataUri;
+ private MetaData metaData;
+ private ASN1OctetString content;
+ private Evidence temporalEvidence;
+
+ public TimeStampedData(DERIA5String dataUri, MetaData metaData, ASN1OctetString content, Evidence temporalEvidence)
+ {
+ this.version = new ASN1Integer(1);
+ this.dataUri = dataUri;
+ this.metaData = metaData;
+ this.content = content;
+ this.temporalEvidence = temporalEvidence;
+ }
+
+ private TimeStampedData(ASN1Sequence seq)
+ {
+ this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
+
+ int index = 1;
+ if (seq.getObjectAt(index) instanceof DERIA5String)
+ {
+ this.dataUri = DERIA5String.getInstance(seq.getObjectAt(index++));
+ }
+ if (seq.getObjectAt(index) instanceof MetaData || seq.getObjectAt(index) instanceof ASN1Sequence)
+ {
+ this.metaData = MetaData.getInstance(seq.getObjectAt(index++));
+ }
+ if (seq.getObjectAt(index) instanceof ASN1OctetString)
+ {
+ this.content = ASN1OctetString.getInstance(seq.getObjectAt(index++));
+ }
+ this.temporalEvidence = Evidence.getInstance(seq.getObjectAt(index));
+ }
+
+ public static TimeStampedData getInstance(Object obj)
+ {
+ if (obj instanceof TimeStampedData)
+ {
+ return (TimeStampedData)obj;
+ }
+ else if (obj != null)
+ {
+ return new TimeStampedData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public DERIA5String getDataUri()
+ {
+ return dataUri;
+ }
+
+ public MetaData getMetaData()
+ {
+ return metaData;
+ }
+
+ public ASN1OctetString getContent()
+ {
+ return content;
+ }
+
+ public Evidence getTemporalEvidence()
+ {
+ return temporalEvidence;
+ }
+
+ /**
+ *
+ * TimeStampedData ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * dataUri IA5String OPTIONAL,
+ * metaData MetaData OPTIONAL,
+ * content OCTET STRING OPTIONAL,
+ * temporalEvidence Evidence
+ * }
+ *
+ * @return
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+
+ if (dataUri != null)
+ {
+ v.add(dataUri);
+ }
+
+ if (metaData != null)
+ {
+ v.add(metaData);
+ }
+
+ if (content != null)
+ {
+ v.add(content);
+ }
+
+ v.add(temporalEvidence);
+
+ return new BERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/TimeStampedDataParser.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/TimeStampedDataParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/TimeStampedDataParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/TimeStampedDataParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,127 @@
+package pdftk.org.bouncycastle.asn1.cms;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1OctetStringParser;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1SequenceParser;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+
+public class TimeStampedDataParser
+{
+ private ASN1Integer version;
+ private DERIA5String dataUri;
+ private MetaData metaData;
+ private ASN1OctetStringParser content;
+ private Evidence temporalEvidence;
+ private ASN1SequenceParser parser;
+
+ private TimeStampedDataParser(ASN1SequenceParser parser)
+ throws IOException
+ {
+ this.parser = parser;
+ this.version = ASN1Integer.getInstance(parser.readObject());
+
+ ASN1Encodable obj = parser.readObject();
+
+ if (obj instanceof DERIA5String)
+ {
+ this.dataUri = DERIA5String.getInstance(obj);
+ obj = parser.readObject();
+ }
+ if (obj instanceof MetaData || obj instanceof ASN1SequenceParser)
+ {
+ this.metaData = MetaData.getInstance(obj.toASN1Primitive());
+ obj = parser.readObject();
+ }
+ if (obj instanceof ASN1OctetStringParser)
+ {
+ this.content = (ASN1OctetStringParser)obj;
+ }
+ }
+
+ public static TimeStampedDataParser getInstance(Object obj)
+ throws IOException
+ {
+ if (obj instanceof ASN1Sequence)
+ {
+ return new TimeStampedDataParser(((ASN1Sequence)obj).parser());
+ }
+ if (obj instanceof ASN1SequenceParser)
+ {
+ return new TimeStampedDataParser((ASN1SequenceParser)obj);
+ }
+
+ return null;
+ }
+
+ public DERIA5String getDataUri()
+ {
+ return dataUri;
+ }
+
+ public MetaData getMetaData()
+ {
+ return metaData;
+ }
+
+ public ASN1OctetStringParser getContent()
+ {
+ return content;
+ }
+
+ public Evidence getTemporalEvidence()
+ throws IOException
+ {
+ if (temporalEvidence == null)
+ {
+ temporalEvidence = Evidence.getInstance(parser.readObject().toASN1Primitive());
+ }
+
+ return temporalEvidence;
+ }
+
+ /**
+ *
+ * TimeStampedData ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * dataUri IA5String OPTIONAL,
+ * metaData MetaData OPTIONAL,
+ * content OCTET STRING OPTIONAL,
+ * temporalEvidence Evidence
+ * }
+ *
+ * @return
+ * @deprecated will be removed
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+
+ if (dataUri != null)
+ {
+ v.add(dataUri);
+ }
+
+ if (metaData != null)
+ {
+ v.add(metaData);
+ }
+
+ if (content != null)
+ {
+ v.add(content);
+ }
+
+ v.add(temporalEvidence);
+
+ return new BERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/ecc/MQVuserKeyingMaterial.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,112 @@
+package pdftk.org.bouncycastle.asn1.cms.ecc;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.cms.OriginatorPublicKey;
+
+public class MQVuserKeyingMaterial
+ extends ASN1Object
+{
+ private OriginatorPublicKey ephemeralPublicKey;
+ private ASN1OctetString addedukm;
+
+ public MQVuserKeyingMaterial(
+ OriginatorPublicKey ephemeralPublicKey,
+ ASN1OctetString addedukm)
+ {
+ // TODO Check ephemeralPublicKey not null
+
+ this.ephemeralPublicKey = ephemeralPublicKey;
+ this.addedukm = addedukm;
+ }
+
+ private MQVuserKeyingMaterial(
+ ASN1Sequence seq)
+ {
+ // TODO Check seq has either 1 or 2 elements
+
+ this.ephemeralPublicKey = OriginatorPublicKey.getInstance(
+ seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ this.addedukm = ASN1OctetString.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(1), true);
+ }
+ }
+
+ /**
+ * return an MQVuserKeyingMaterial object from a tagged object.
+ *
+ * @param obj the tagged object holding the object we want.
+ * @param explicit true if the object is meant to be explicitly
+ * tagged false otherwise.
+ * @throws IllegalArgumentException if the object held by the
+ * tagged object cannot be converted.
+ */
+ public static MQVuserKeyingMaterial getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * return an MQVuserKeyingMaterial object from the given object.
+ *
+ * @param obj the object we want converted.
+ * @throws IllegalArgumentException if the object cannot be converted.
+ */
+ public static MQVuserKeyingMaterial getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof MQVuserKeyingMaterial)
+ {
+ return (MQVuserKeyingMaterial)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new MQVuserKeyingMaterial((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid MQVuserKeyingMaterial: " + obj.getClass().getName());
+ }
+
+ public OriginatorPublicKey getEphemeralPublicKey()
+ {
+ return ephemeralPublicKey;
+ }
+
+ public ASN1OctetString getAddedukm()
+ {
+ return addedukm;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * MQVuserKeyingMaterial ::= SEQUENCE {
+ * ephemeralPublicKey OriginatorPublicKey,
+ * addedukm [0] EXPLICIT UserKeyingMaterial OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(ephemeralPublicKey);
+
+ if (addedukm != null)
+ {
+ v.add(new DERTaggedObject(true, 0, addedukm));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cms/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cms/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes useful for encoding and supporting Cryptographic Message Syntax as described in PKCS#7 and RFC 3369 (formerly RFC 2630).
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/AttributeTypeAndValue.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/AttributeTypeAndValue.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/AttributeTypeAndValue.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/AttributeTypeAndValue.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,80 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class AttributeTypeAndValue
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier type;
+ private ASN1Encodable value;
+
+ private AttributeTypeAndValue(ASN1Sequence seq)
+ {
+ type = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ value = (ASN1Encodable)seq.getObjectAt(1);
+ }
+
+ public static AttributeTypeAndValue getInstance(Object o)
+ {
+ if (o instanceof AttributeTypeAndValue)
+ {
+ return (AttributeTypeAndValue)o;
+ }
+
+ if (o != null)
+ {
+ return new AttributeTypeAndValue(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public AttributeTypeAndValue(
+ String oid,
+ ASN1Encodable value)
+ {
+ this(new ASN1ObjectIdentifier(oid), value);
+ }
+
+ public AttributeTypeAndValue(
+ ASN1ObjectIdentifier type,
+ ASN1Encodable value)
+ {
+ this.type = type;
+ this.value = value;
+ }
+
+ public ASN1ObjectIdentifier getType()
+ {
+ return type;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ return value;
+ }
+
+ /**
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type OBJECT IDENTIFIER,
+ * value ANY DEFINED BY type }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(type);
+ v.add(value);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CRMFObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,21 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+public interface CRMFObjectIdentifiers
+{
+ static final ASN1ObjectIdentifier id_pkix = new ASN1ObjectIdentifier("1.3.6.1.5.5.7");
+
+ // arc for Internet X.509 PKI protocols and their components
+
+ static final ASN1ObjectIdentifier id_pkip = id_pkix.branch("5");
+
+ static final ASN1ObjectIdentifier id_regCtrl = id_pkip.branch("1");
+ static final ASN1ObjectIdentifier id_regCtrl_regToken = id_regCtrl.branch("1");
+ static final ASN1ObjectIdentifier id_regCtrl_authenticator = id_regCtrl.branch("2");
+ static final ASN1ObjectIdentifier id_regCtrl_pkiPublicationInfo = id_regCtrl.branch("3");
+ static final ASN1ObjectIdentifier id_regCtrl_pkiArchiveOptions = id_regCtrl.branch("4");
+
+ static final ASN1ObjectIdentifier id_ct_encKeyWithID = new ASN1ObjectIdentifier(PKCSObjectIdentifiers.id_ct + ".21");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CertId.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CertId.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CertId.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CertId.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,84 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.GeneralName;
+
+public class CertId
+ extends ASN1Object
+{
+ private GeneralName issuer;
+ private ASN1Integer serialNumber;
+
+ private CertId(ASN1Sequence seq)
+ {
+ issuer = GeneralName.getInstance(seq.getObjectAt(0));
+ serialNumber = ASN1Integer.getInstance(seq.getObjectAt(1));
+ }
+
+ public static CertId getInstance(Object o)
+ {
+ if (o instanceof CertId)
+ {
+ return (CertId)o;
+ }
+
+ if (o != null)
+ {
+ return new CertId(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public static CertId getInstance(ASN1TaggedObject obj, boolean isExplicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, isExplicit));
+ }
+
+ public CertId(GeneralName issuer, BigInteger serialNumber)
+ {
+ this(issuer, new ASN1Integer(serialNumber));
+ }
+
+ public CertId(GeneralName issuer, ASN1Integer serialNumber)
+ {
+ this.issuer = issuer;
+ this.serialNumber = serialNumber;
+ }
+
+ public GeneralName getIssuer()
+ {
+ return issuer;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ /**
+ *
+ * CertId ::= SEQUENCE {
+ * issuer GeneralName,
+ * serialNumber INTEGER }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(issuer);
+ v.add(serialNumber);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CertReqMessages.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CertReqMessages.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CertReqMessages.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CertReqMessages.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,72 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class CertReqMessages
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private CertReqMessages(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static CertReqMessages getInstance(Object o)
+ {
+ if (o instanceof CertReqMessages)
+ {
+ return (CertReqMessages)o;
+ }
+
+ if (o != null)
+ {
+ return new CertReqMessages(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertReqMessages(
+ CertReqMsg msg)
+ {
+ content = new DERSequence(msg);
+ }
+
+ public CertReqMessages(
+ CertReqMsg[] msgs)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < msgs.length; i++) {
+ v.add(msgs[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public CertReqMsg[] toCertReqMsgArray()
+ {
+ CertReqMsg[] result = new CertReqMsg[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = CertReqMsg.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CertReqMsg.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CertReqMsg.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CertReqMsg.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CertReqMsg.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,145 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class CertReqMsg
+ extends ASN1Object
+{
+ private CertRequest certReq;
+ private ProofOfPossession pop;
+ private ASN1Sequence regInfo;
+
+ private CertReqMsg(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ certReq = CertRequest.getInstance(en.nextElement());
+ while (en.hasMoreElements())
+ {
+ Object o = en.nextElement();
+
+ if (o instanceof ASN1TaggedObject || o instanceof ProofOfPossession)
+ {
+ pop = ProofOfPossession.getInstance(o);
+ }
+ else
+ {
+ regInfo = ASN1Sequence.getInstance(o);
+ }
+ }
+ }
+
+ public static CertReqMsg getInstance(Object o)
+ {
+ if (o instanceof CertReqMsg)
+ {
+ return (CertReqMsg)o;
+ }
+ else if (o != null)
+ {
+ return new CertReqMsg(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new CertReqMsg.
+ * @param certReq CertRequest
+ * @param pop may be null
+ * @param regInfo may be null
+ */
+ public CertReqMsg(
+ CertRequest certReq,
+ ProofOfPossession pop,
+ AttributeTypeAndValue[] regInfo)
+ {
+ if (certReq == null)
+ {
+ throw new IllegalArgumentException("'certReq' cannot be null");
+ }
+
+ this.certReq = certReq;
+ this.pop = pop;
+
+ if (regInfo != null)
+ {
+ this.regInfo = new DERSequence(regInfo);
+ }
+ }
+
+ public CertRequest getCertReq()
+ {
+ return certReq;
+ }
+
+
+ /**
+ * @deprecated use getPopo
+ */
+ public ProofOfPossession getPop()
+ {
+ return pop;
+ }
+
+
+ public ProofOfPossession getPopo()
+ {
+ return pop;
+ }
+
+ public AttributeTypeAndValue[] getRegInfo()
+ {
+ if (regInfo == null)
+ {
+ return null;
+ }
+
+ AttributeTypeAndValue[] results = new AttributeTypeAndValue[regInfo.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = AttributeTypeAndValue.getInstance(regInfo.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ /**
+ *
+ * CertReqMsg ::= SEQUENCE {
+ * certReq CertRequest,
+ * popo ProofOfPossession OPTIONAL,
+ * -- content depends upon key type
+ * regInfo SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certReq);
+
+ addOptional(v, pop);
+ addOptional(v, regInfo);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(obj);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CertRequest.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CertRequest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CertRequest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CertRequest.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,97 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class CertRequest
+ extends ASN1Object
+{
+ private ASN1Integer certReqId;
+ private CertTemplate certTemplate;
+ private Controls controls;
+
+ private CertRequest(ASN1Sequence seq)
+ {
+ certReqId = new ASN1Integer(ASN1Integer.getInstance(seq.getObjectAt(0)).getValue());
+ certTemplate = CertTemplate.getInstance(seq.getObjectAt(1));
+ if (seq.size() > 2)
+ {
+ controls = Controls.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public static CertRequest getInstance(Object o)
+ {
+ if (o instanceof CertRequest)
+ {
+ return (CertRequest)o;
+ }
+ else if (o != null)
+ {
+ return new CertRequest(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertRequest(
+ int certReqId,
+ CertTemplate certTemplate,
+ Controls controls)
+ {
+ this(new ASN1Integer(certReqId), certTemplate, controls);
+ }
+
+ public CertRequest(
+ ASN1Integer certReqId,
+ CertTemplate certTemplate,
+ Controls controls)
+ {
+ this.certReqId = certReqId;
+ this.certTemplate = certTemplate;
+ this.controls = controls;
+ }
+
+ public ASN1Integer getCertReqId()
+ {
+ return certReqId;
+ }
+
+ public CertTemplate getCertTemplate()
+ {
+ return certTemplate;
+ }
+
+ public Controls getControls()
+ {
+ return controls;
+ }
+
+ /**
+ *
+ * CertRequest ::= SEQUENCE {
+ * certReqId INTEGER, -- ID for matching request and reply
+ * certTemplate CertTemplate, -- Selected fields of cert to be issued
+ * controls Controls OPTIONAL } -- Attributes affecting issuance
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certReqId);
+ v.add(certTemplate);
+
+ if (controls != null)
+ {
+ v.add(controls);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CertTemplate.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CertTemplate.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CertTemplate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CertTemplate.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,163 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import pdftk.org.bouncycastle.asn1.x509.Extensions;
+import pdftk.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+
+public class CertTemplate
+ extends ASN1Object
+{
+ private ASN1Sequence seq;
+
+ private ASN1Integer version;
+ private ASN1Integer serialNumber;
+ private AlgorithmIdentifier signingAlg;
+ private X500Name issuer;
+ private OptionalValidity validity;
+ private X500Name subject;
+ private SubjectPublicKeyInfo publicKey;
+ private DERBitString issuerUID;
+ private DERBitString subjectUID;
+ private Extensions extensions;
+
+ private CertTemplate(ASN1Sequence seq)
+ {
+ this.seq = seq;
+
+ Enumeration en = seq.getObjects();
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
+
+ switch (tObj.getTagNo())
+ {
+ case 0:
+ version = ASN1Integer.getInstance(tObj, false);
+ break;
+ case 1:
+ serialNumber = ASN1Integer.getInstance(tObj, false);
+ break;
+ case 2:
+ signingAlg = AlgorithmIdentifier.getInstance(tObj, false);
+ break;
+ case 3:
+ issuer = X500Name.getInstance(tObj, true); // CHOICE
+ break;
+ case 4:
+ validity = OptionalValidity.getInstance(ASN1Sequence.getInstance(tObj, false));
+ break;
+ case 5:
+ subject = X500Name.getInstance(tObj, true); // CHOICE
+ break;
+ case 6:
+ publicKey = SubjectPublicKeyInfo.getInstance(tObj, false);
+ break;
+ case 7:
+ issuerUID = DERBitString.getInstance(tObj, false);
+ break;
+ case 8:
+ subjectUID = DERBitString.getInstance(tObj, false);
+ break;
+ case 9:
+ extensions = Extensions.getInstance(tObj, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag: " + tObj.getTagNo());
+ }
+ }
+ }
+
+ public static CertTemplate getInstance(Object o)
+ {
+ if (o instanceof CertTemplate)
+ {
+ return (CertTemplate)o;
+ }
+ else if (o != null)
+ {
+ return new CertTemplate(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public int getVersion()
+ {
+ return version.getValue().intValue();
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public AlgorithmIdentifier getSigningAlg()
+ {
+ return signingAlg;
+ }
+
+ public X500Name getIssuer()
+ {
+ return issuer;
+ }
+
+ public OptionalValidity getValidity()
+ {
+ return validity;
+ }
+
+ public X500Name getSubject()
+ {
+ return subject;
+ }
+
+ public SubjectPublicKeyInfo getPublicKey()
+ {
+ return publicKey;
+ }
+
+ public DERBitString getIssuerUID()
+ {
+ return issuerUID;
+ }
+
+ public DERBitString getSubjectUID()
+ {
+ return subjectUID;
+ }
+
+ public Extensions getExtensions()
+ {
+ return extensions;
+ }
+
+ /**
+ *
+ * CertTemplate ::= SEQUENCE {
+ * version [0] Version OPTIONAL,
+ * serialNumber [1] INTEGER OPTIONAL,
+ * signingAlg [2] AlgorithmIdentifier OPTIONAL,
+ * issuer [3] Name OPTIONAL,
+ * validity [4] OptionalValidity OPTIONAL,
+ * subject [5] Name OPTIONAL,
+ * publicKey [6] SubjectPublicKeyInfo OPTIONAL,
+ * issuerUID [7] UniqueIdentifier OPTIONAL,
+ * subjectUID [8] UniqueIdentifier OPTIONAL,
+ * extensions [9] Extensions OPTIONAL }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CertTemplateBuilder.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CertTemplateBuilder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/CertTemplateBuilder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/CertTemplateBuilder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,152 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import pdftk.org.bouncycastle.asn1.x509.Extensions;
+import pdftk.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import pdftk.org.bouncycastle.asn1.x509.X509Extensions;
+
+public class CertTemplateBuilder
+{
+ private ASN1Integer version;
+ private ASN1Integer serialNumber;
+ private AlgorithmIdentifier signingAlg;
+ private X500Name issuer;
+ private OptionalValidity validity;
+ private X500Name subject;
+ private SubjectPublicKeyInfo publicKey;
+ private DERBitString issuerUID;
+ private DERBitString subjectUID;
+ private Extensions extensions;
+
+ /** Sets the X.509 version. Note: for X509v3, use 2 here. */
+ public CertTemplateBuilder setVersion(int ver)
+ {
+ version = new ASN1Integer(ver);
+
+ return this;
+ }
+
+ public CertTemplateBuilder setSerialNumber(ASN1Integer ser)
+ {
+ serialNumber = ser;
+
+ return this;
+ }
+
+ public CertTemplateBuilder setSigningAlg(AlgorithmIdentifier aid)
+ {
+ signingAlg = aid;
+
+ return this;
+ }
+
+ public CertTemplateBuilder setIssuer(X500Name name)
+ {
+ issuer = name;
+
+ return this;
+ }
+
+ public CertTemplateBuilder setValidity(OptionalValidity v)
+ {
+ validity = v;
+
+ return this;
+ }
+
+ public CertTemplateBuilder setSubject(X500Name name)
+ {
+ subject = name;
+
+ return this;
+ }
+
+ public CertTemplateBuilder setPublicKey(SubjectPublicKeyInfo spki)
+ {
+ publicKey = spki;
+
+ return this;
+ }
+
+ /** Sets the issuer unique ID (deprecated in X.509v3) */
+ public CertTemplateBuilder setIssuerUID(DERBitString uid)
+ {
+ issuerUID = uid;
+
+ return this;
+ }
+
+ /** Sets the subject unique ID (deprecated in X.509v3) */
+ public CertTemplateBuilder setSubjectUID(DERBitString uid)
+ {
+ subjectUID = uid;
+
+ return this;
+ }
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param extens
+ * @return
+ */
+ public CertTemplateBuilder setExtensions(X509Extensions extens)
+ {
+ return setExtensions(Extensions.getInstance(extens));
+ }
+
+ public CertTemplateBuilder setExtensions(Extensions extens)
+ {
+ extensions = extens;
+
+ return this;
+ }
+
+ /**
+ *
+ * CertTemplate ::= SEQUENCE {
+ * version [0] Version OPTIONAL,
+ * serialNumber [1] INTEGER OPTIONAL,
+ * signingAlg [2] AlgorithmIdentifier OPTIONAL,
+ * issuer [3] Name OPTIONAL,
+ * validity [4] OptionalValidity OPTIONAL,
+ * subject [5] Name OPTIONAL,
+ * publicKey [6] SubjectPublicKeyInfo OPTIONAL,
+ * issuerUID [7] UniqueIdentifier OPTIONAL,
+ * subjectUID [8] UniqueIdentifier OPTIONAL,
+ * extensions [9] Extensions OPTIONAL }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public CertTemplate build()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ addOptional(v, 0, false, version);
+ addOptional(v, 1, false, serialNumber);
+ addOptional(v, 2, false, signingAlg);
+ addOptional(v, 3, true, issuer); // CHOICE
+ addOptional(v, 4, false, validity);
+ addOptional(v, 5, true, subject); // CHOICE
+ addOptional(v, 6, false, publicKey);
+ addOptional(v, 7, false, issuerUID);
+ addOptional(v, 8, false, subjectUID);
+ addOptional(v, 9, false, extensions);
+
+ return CertTemplate.getInstance(new DERSequence(v));
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, boolean isExplicit, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(isExplicit, tagNo, obj));
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/Controls.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/Controls.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/Controls.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/Controls.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,70 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class Controls
+ extends ASN1Object
+{
+ private ASN1Sequence content;
+
+ private Controls(ASN1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static Controls getInstance(Object o)
+ {
+ if (o instanceof Controls)
+ {
+ return (Controls)o;
+ }
+
+ if (o != null)
+ {
+ return new Controls(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public Controls(AttributeTypeAndValue atv)
+ {
+ content = new DERSequence(atv);
+ }
+
+ public Controls(AttributeTypeAndValue[] atvs)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i < atvs.length; i++) {
+ v.add(atvs[i]);
+ }
+ content = new DERSequence(v);
+ }
+
+ public AttributeTypeAndValue[] toAttributeTypeAndValueArray()
+ {
+ AttributeTypeAndValue[] result = new AttributeTypeAndValue[content.size()];
+
+ for (int i = 0; i != result.length; i++)
+ {
+ result[i] = AttributeTypeAndValue.getInstance(content.getObjectAt(i));
+ }
+
+ return result;
+ }
+
+ /**
+ *
+ * Controls ::= SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return content;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/EncKeyWithID.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/EncKeyWithID.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/EncKeyWithID.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/EncKeyWithID.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,117 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERUTF8String;
+import pdftk.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import pdftk.org.bouncycastle.asn1.x509.GeneralName;
+
+public class EncKeyWithID
+ extends ASN1Object
+{
+ private final PrivateKeyInfo privKeyInfo;
+ private final ASN1Encodable identifier;
+
+ public static EncKeyWithID getInstance(Object o)
+ {
+ if (o instanceof EncKeyWithID)
+ {
+ return (EncKeyWithID)o;
+ }
+ else if (o != null)
+ {
+ return new EncKeyWithID(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private EncKeyWithID(ASN1Sequence seq)
+ {
+ this.privKeyInfo = PrivateKeyInfo.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ if (!(seq.getObjectAt(1) instanceof DERUTF8String))
+ {
+ this.identifier = GeneralName.getInstance(seq.getObjectAt(1));
+ }
+ else
+ {
+ this.identifier = (ASN1Encodable)seq.getObjectAt(1);
+ }
+ }
+ else
+ {
+ this.identifier = null;
+ }
+ }
+
+ public EncKeyWithID(PrivateKeyInfo privKeyInfo)
+ {
+ this.privKeyInfo = privKeyInfo;
+ this.identifier = null;
+ }
+
+ public EncKeyWithID(PrivateKeyInfo privKeyInfo, DERUTF8String str)
+ {
+ this.privKeyInfo = privKeyInfo;
+ this.identifier = str;
+ }
+
+ public EncKeyWithID(PrivateKeyInfo privKeyInfo, GeneralName generalName)
+ {
+ this.privKeyInfo = privKeyInfo;
+ this.identifier = generalName;
+ }
+
+ public PrivateKeyInfo getPrivateKey()
+ {
+ return privKeyInfo;
+ }
+
+ public boolean hasIdentifier()
+ {
+ return identifier != null;
+ }
+
+ public boolean isIdentifierUTF8String()
+ {
+ return identifier instanceof DERUTF8String;
+ }
+
+ public ASN1Encodable getIdentifier()
+ {
+ return identifier;
+ }
+
+ /**
+ *
+ * EncKeyWithID ::= SEQUENCE {
+ * privateKey PrivateKeyInfo,
+ * identifier CHOICE {
+ * string UTF8String,
+ * generalName GeneralName
+ * } OPTIONAL
+ * }
+ *
+ * @return
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(privKeyInfo);
+
+ if (identifier != null)
+ {
+ v.add(identifier);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/EncryptedKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/EncryptedKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/EncryptedKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/EncryptedKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,81 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.cms.EnvelopedData;
+
+public class EncryptedKey
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private EnvelopedData envelopedData;
+ private EncryptedValue encryptedValue;
+
+ public static EncryptedKey getInstance(Object o)
+ {
+ if (o instanceof EncryptedKey)
+ {
+ return (EncryptedKey)o;
+ }
+ else if (o instanceof ASN1TaggedObject)
+ {
+ return new EncryptedKey(EnvelopedData.getInstance((ASN1TaggedObject)o, false));
+ }
+ else if (o instanceof EncryptedValue)
+ {
+ return new EncryptedKey((EncryptedValue)o);
+ }
+ else
+ {
+ return new EncryptedKey(EncryptedValue.getInstance(o));
+ }
+ }
+
+ public EncryptedKey(EnvelopedData envelopedData)
+ {
+ this.envelopedData = envelopedData;
+ }
+
+ public EncryptedKey(EncryptedValue encryptedValue)
+ {
+ this.encryptedValue = encryptedValue;
+ }
+
+ public boolean isEncryptedValue()
+ {
+ return encryptedValue != null;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ if (encryptedValue != null)
+ {
+ return encryptedValue;
+ }
+
+ return envelopedData;
+ }
+
+ /**
+ *
+ * EncryptedKey ::= CHOICE {
+ * encryptedValue EncryptedValue, -- deprecated
+ * envelopedData [0] EnvelopedData }
+ * -- The encrypted private key MUST be placed in the envelopedData
+ * -- encryptedContentInfo encryptedContent OCTET STRING.
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (encryptedValue != null)
+ {
+ return encryptedValue.toASN1Primitive();
+ }
+
+ return new DERTaggedObject(false, 0, envelopedData);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/EncryptedValue.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/EncryptedValue.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/EncryptedValue.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/EncryptedValue.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,164 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class EncryptedValue
+ extends ASN1Object
+{
+ private AlgorithmIdentifier intendedAlg;
+ private AlgorithmIdentifier symmAlg;
+ private DERBitString encSymmKey;
+ private AlgorithmIdentifier keyAlg;
+ private ASN1OctetString valueHint;
+ private DERBitString encValue;
+
+ private EncryptedValue(ASN1Sequence seq)
+ {
+ int index = 0;
+ while (seq.getObjectAt(index) instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)seq.getObjectAt(index);
+
+ switch (tObj.getTagNo())
+ {
+ case 0:
+ intendedAlg = AlgorithmIdentifier.getInstance(tObj, false);
+ break;
+ case 1:
+ symmAlg = AlgorithmIdentifier.getInstance(tObj, false);
+ break;
+ case 2:
+ encSymmKey = DERBitString.getInstance(tObj, false);
+ break;
+ case 3:
+ keyAlg = AlgorithmIdentifier.getInstance(tObj, false);
+ break;
+ case 4:
+ valueHint = ASN1OctetString.getInstance(tObj, false);
+ break;
+ }
+ index++;
+ }
+
+ encValue = DERBitString.getInstance(seq.getObjectAt(index));
+ }
+
+ public static EncryptedValue getInstance(Object o)
+ {
+ if (o instanceof EncryptedValue)
+ {
+ return (EncryptedValue)o;
+ }
+ else if (o != null)
+ {
+ return new EncryptedValue(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public EncryptedValue(
+ AlgorithmIdentifier intendedAlg,
+ AlgorithmIdentifier symmAlg,
+ DERBitString encSymmKey,
+ AlgorithmIdentifier keyAlg,
+ ASN1OctetString valueHint,
+ DERBitString encValue)
+ {
+ if (encValue == null)
+ {
+ throw new IllegalArgumentException("'encValue' cannot be null");
+ }
+
+ this.intendedAlg = intendedAlg;
+ this.symmAlg = symmAlg;
+ this.encSymmKey = encSymmKey;
+ this.keyAlg = keyAlg;
+ this.valueHint = valueHint;
+ this.encValue = encValue;
+ }
+
+ public AlgorithmIdentifier getIntendedAlg()
+ {
+ return intendedAlg;
+ }
+
+ public AlgorithmIdentifier getSymmAlg()
+ {
+ return symmAlg;
+ }
+
+ public DERBitString getEncSymmKey()
+ {
+ return encSymmKey;
+ }
+
+ public AlgorithmIdentifier getKeyAlg()
+ {
+ return keyAlg;
+ }
+
+ public ASN1OctetString getValueHint()
+ {
+ return valueHint;
+ }
+
+ public DERBitString getEncValue()
+ {
+ return encValue;
+ }
+
+ /**
+ *
+ * EncryptedValue ::= SEQUENCE {
+ * intendedAlg [0] AlgorithmIdentifier OPTIONAL,
+ * -- the intended algorithm for which the value will be used
+ * symmAlg [1] AlgorithmIdentifier OPTIONAL,
+ * -- the symmetric algorithm used to encrypt the value
+ * encSymmKey [2] BIT STRING OPTIONAL,
+ * -- the (encrypted) symmetric key used to encrypt the value
+ * keyAlg [3] AlgorithmIdentifier OPTIONAL,
+ * -- algorithm used to encrypt the symmetric key
+ * valueHint [4] OCTET STRING OPTIONAL,
+ * -- a brief description or identifier of the encValue content
+ * -- (may be meaningful only to the sending entity, and used only
+ * -- if EncryptedValue might be re-examined by the sending entity
+ * -- in the future)
+ * encValue BIT STRING }
+ * -- the encrypted value itself
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ addOptional(v, 0, intendedAlg);
+ addOptional(v, 1, symmAlg);
+ addOptional(v, 2, encSymmKey);
+ addOptional(v, 3, keyAlg);
+ addOptional(v, 4, valueHint);
+
+ v.add(encValue);
+
+ return new DERSequence(v);
+ }
+
+ private void addOptional(ASN1EncodableVector v, int tagNo, ASN1Encodable obj)
+ {
+ if (obj != null)
+ {
+ v.add(new DERTaggedObject(false, tagNo, obj));
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/OptionalValidity.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/OptionalValidity.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/OptionalValidity.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/OptionalValidity.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,98 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.Time;
+
+public class OptionalValidity
+ extends ASN1Object
+{
+ private Time notBefore;
+ private Time notAfter;
+
+ private OptionalValidity(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
+
+ if (tObj.getTagNo() == 0)
+ {
+ notBefore = Time.getInstance(tObj, true);
+ }
+ else
+ {
+ notAfter = Time.getInstance(tObj, true);
+ }
+ }
+ }
+
+ public static OptionalValidity getInstance(Object o)
+ {
+ if (o instanceof OptionalValidity)
+ {
+ return (OptionalValidity)o;
+ }
+
+ if (o != null)
+ {
+ return new OptionalValidity(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public OptionalValidity(Time notBefore, Time notAfter)
+ {
+ if (notBefore == null && notAfter == null)
+ {
+ throw new IllegalArgumentException("at least one of notBefore/notAfter must not be null.");
+ }
+
+ this.notBefore = notBefore;
+ this.notAfter = notAfter;
+ }
+
+ public Time getNotBefore()
+ {
+ return notBefore;
+ }
+
+ public Time getNotAfter()
+ {
+ return notAfter;
+ }
+
+ /**
+ *
+ * OptionalValidity ::= SEQUENCE {
+ * notBefore [0] Time OPTIONAL,
+ * notAfter [1] Time OPTIONAL } --at least one MUST be present
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (notBefore != null)
+ {
+ v.add(new DERTaggedObject(true, 0, notBefore));
+ }
+
+ if (notAfter != null)
+ {
+ v.add(new DERTaggedObject(true, 1, notAfter));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/PKIArchiveOptions.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/PKIArchiveOptions.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/PKIArchiveOptions.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/PKIArchiveOptions.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,116 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Boolean;
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class PKIArchiveOptions
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int encryptedPrivKey = 0;
+ public static final int keyGenParameters = 1;
+ public static final int archiveRemGenPrivKey = 2;
+
+ private ASN1Encodable value;
+
+ public static PKIArchiveOptions getInstance(Object o)
+ {
+ if (o == null || o instanceof PKIArchiveOptions)
+ {
+ return (PKIArchiveOptions)o;
+ }
+ else if (o instanceof ASN1TaggedObject)
+ {
+ return new PKIArchiveOptions((ASN1TaggedObject)o);
+ }
+
+ throw new IllegalArgumentException("unknown object: " + o);
+ }
+
+ private PKIArchiveOptions(ASN1TaggedObject tagged)
+ {
+ switch (tagged.getTagNo())
+ {
+ case encryptedPrivKey:
+ value = EncryptedKey.getInstance(tagged.getObject());
+ break;
+ case keyGenParameters:
+ value = ASN1OctetString.getInstance(tagged, false);
+ break;
+ case archiveRemGenPrivKey:
+ value = ASN1Boolean.getInstance(tagged, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag number: " + tagged.getTagNo());
+ }
+ }
+
+ public PKIArchiveOptions(EncryptedKey encKey)
+ {
+ this.value = encKey;
+ }
+
+ public PKIArchiveOptions(ASN1OctetString keyGenParameters)
+ {
+ this.value = keyGenParameters;
+ }
+
+ public PKIArchiveOptions(boolean archiveRemGenPrivKey)
+ {
+ this.value = ASN1Boolean.getInstance(archiveRemGenPrivKey);
+ }
+
+ public int getType()
+ {
+ if (value instanceof EncryptedKey)
+ {
+ return encryptedPrivKey;
+ }
+
+ if (value instanceof ASN1OctetString)
+ {
+ return keyGenParameters;
+ }
+
+ return archiveRemGenPrivKey;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ return value;
+ }
+
+ /**
+ *
+ * PKIArchiveOptions ::= CHOICE {
+ * encryptedPrivKey [0] EncryptedKey,
+ * -- the actual value of the private key
+ * keyGenParameters [1] KeyGenParameters,
+ * -- parameters which allow the private key to be re-generated
+ * archiveRemGenPrivKey [2] BOOLEAN }
+ * -- set to TRUE if sender wishes receiver to archive the private
+ * -- key of a key pair that the receiver generates in response to
+ * -- this request; set to FALSE if no archival is desired.
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (value instanceof EncryptedKey)
+ {
+ return new DERTaggedObject(true, encryptedPrivKey, value); // choice
+ }
+
+ if (value instanceof ASN1OctetString)
+ {
+ return new DERTaggedObject(false, keyGenParameters, value);
+ }
+
+ return new DERTaggedObject(false, archiveRemGenPrivKey, value);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/PKIPublicationInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/PKIPublicationInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/PKIPublicationInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/PKIPublicationInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,81 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class PKIPublicationInfo
+ extends ASN1Object
+{
+ private ASN1Integer action;
+ private ASN1Sequence pubInfos;
+
+ private PKIPublicationInfo(ASN1Sequence seq)
+ {
+ action = ASN1Integer.getInstance(seq.getObjectAt(0));
+ pubInfos = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+
+ public static PKIPublicationInfo getInstance(Object o)
+ {
+ if (o instanceof PKIPublicationInfo)
+ {
+ return (PKIPublicationInfo)o;
+ }
+
+ if (o != null)
+ {
+ return new PKIPublicationInfo(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getAction()
+ {
+ return action;
+ }
+
+ public SinglePubInfo[] getPubInfos()
+ {
+ if (pubInfos == null)
+ {
+ return null;
+ }
+
+ SinglePubInfo[] results = new SinglePubInfo[pubInfos.size()];
+
+ for (int i = 0; i != results.length; i++)
+ {
+ results[i] = SinglePubInfo.getInstance(pubInfos.getObjectAt(i));
+ }
+
+ return results;
+ }
+
+ /**
+ *
+ * PKIPublicationInfo ::= SEQUENCE {
+ * action INTEGER {
+ * dontPublish (0),
+ * pleasePublish (1) },
+ * pubInfos SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }
+ * -- pubInfos MUST NOT be present if action is "dontPublish"
+ * -- (if action is "pleasePublish" and pubInfos is omitted,
+ * -- "dontCare" is assumed)
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(action);
+ v.add(pubInfos);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/PKMACValue.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/PKMACValue.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/PKMACValue.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/PKMACValue.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,104 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.cmp.CMPObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.cmp.PBMParameter;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * Password-based MAC value for use with POPOSigningKeyInput.
+ */
+public class PKMACValue
+ extends ASN1Object
+{
+ private AlgorithmIdentifier algId;
+ private DERBitString value;
+
+ private PKMACValue(ASN1Sequence seq)
+ {
+ algId = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ value = DERBitString.getInstance(seq.getObjectAt(1));
+ }
+
+ public static PKMACValue getInstance(Object o)
+ {
+ if (o instanceof PKMACValue)
+ {
+ return (PKMACValue)o;
+ }
+
+ if (o != null)
+ {
+ return new PKMACValue(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public static PKMACValue getInstance(ASN1TaggedObject obj, boolean isExplicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, isExplicit));
+ }
+
+ /**
+ * Creates a new PKMACValue.
+ * @param params parameters for password-based MAC
+ * @param value MAC of the DER-encoded SubjectPublicKeyInfo
+ */
+ public PKMACValue(
+ PBMParameter params,
+ DERBitString value)
+ {
+ this(new AlgorithmIdentifier(
+ CMPObjectIdentifiers.passwordBasedMac, params), value);
+ }
+
+ /**
+ * Creates a new PKMACValue.
+ * @param aid CMPObjectIdentifiers.passwordBasedMAC, with PBMParameter
+ * @param value MAC of the DER-encoded SubjectPublicKeyInfo
+ */
+ public PKMACValue(
+ AlgorithmIdentifier aid,
+ DERBitString value)
+ {
+ this.algId = aid;
+ this.value = value;
+ }
+
+ public AlgorithmIdentifier getAlgId()
+ {
+ return algId;
+ }
+
+ public DERBitString getValue()
+ {
+ return value;
+ }
+
+ /**
+ *
+ * PKMACValue ::= SEQUENCE {
+ * algId AlgorithmIdentifier,
+ * -- algorithm value shall be PasswordBasedMac 1.2.840.113533.7.66.13
+ * -- parameter value is PBMParameter
+ * value BIT STRING }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(algId);
+ v.add(value);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/POPOPrivKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/POPOPrivKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/POPOPrivKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/POPOPrivKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,104 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.cms.EnvelopedData;
+
+public class POPOPrivKey
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int thisMessage = 0;
+ public static final int subsequentMessage = 1;
+ public static final int dhMAC = 2;
+ public static final int agreeMAC = 3;
+ public static final int encryptedKey = 4;
+
+ private int tagNo;
+ private ASN1Encodable obj;
+
+ private POPOPrivKey(ASN1TaggedObject obj)
+ {
+ this.tagNo = obj.getTagNo();
+
+ switch (tagNo)
+ {
+ case thisMessage:
+ this.obj = DERBitString.getInstance(obj, false);
+ break;
+ case subsequentMessage:
+ this.obj = SubsequentMessage.valueOf(ASN1Integer.getInstance(obj, false).getValue().intValue());
+ break;
+ case dhMAC:
+ this.obj = DERBitString.getInstance(obj, false);
+ break;
+ case agreeMAC:
+ this.obj = PKMACValue.getInstance(obj, false);
+ break;
+ case encryptedKey:
+ this.obj = EnvelopedData.getInstance(obj, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag in POPOPrivKey");
+ }
+ }
+
+ public static POPOPrivKey getInstance(Object obj)
+ {
+ if (obj instanceof POPOPrivKey)
+ {
+ return (POPOPrivKey)obj;
+ }
+ if (obj != null)
+ {
+ return new POPOPrivKey(ASN1TaggedObject.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static POPOPrivKey getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ return getInstance(ASN1TaggedObject.getInstance(obj, explicit));
+ }
+
+ public POPOPrivKey(SubsequentMessage msg)
+ {
+ this.tagNo = subsequentMessage;
+ this.obj = msg;
+ }
+
+ public int getType()
+ {
+ return tagNo;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ return obj;
+ }
+
+ /**
+ *
+ * POPOPrivKey ::= CHOICE {
+ * thisMessage [0] BIT STRING, -- Deprecated
+ * -- possession is proven in this message (which contains the private
+ * -- key itself (encrypted for the CA))
+ * subsequentMessage [1] SubsequentMessage,
+ * -- possession will be proven in a subsequent message
+ * dhMAC [2] BIT STRING, -- Deprecated
+ * agreeMAC [3] PKMACValue,
+ * encryptedKey [4] EnvelopedData }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(false, tagNo, obj);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/POPOSigningKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/POPOSigningKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/POPOSigningKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/POPOSigningKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,122 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class POPOSigningKey
+ extends ASN1Object
+{
+ private POPOSigningKeyInput poposkInput;
+ private AlgorithmIdentifier algorithmIdentifier;
+ private DERBitString signature;
+
+ private POPOSigningKey(ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagObj
+ = (ASN1TaggedObject) seq.getObjectAt(index++);
+ if (tagObj.getTagNo() != 0)
+ {
+ throw new IllegalArgumentException(
+ "Unknown POPOSigningKeyInput tag: " + tagObj.getTagNo());
+ }
+ poposkInput = POPOSigningKeyInput.getInstance(tagObj.getObject());
+ }
+ algorithmIdentifier = AlgorithmIdentifier.getInstance(seq.getObjectAt(index++));
+ signature = DERBitString.getInstance(seq.getObjectAt(index));
+ }
+
+ public static POPOSigningKey getInstance(Object o)
+ {
+ if (o instanceof POPOSigningKey)
+ {
+ return (POPOSigningKey)o;
+ }
+
+ if (o != null)
+ {
+ return new POPOSigningKey(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public static POPOSigningKey getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Creates a new Proof of Possession object for a signing key.
+ * @param poposkIn the POPOSigningKeyInput structure, or null if the
+ * CertTemplate includes both subject and publicKey values.
+ * @param aid the AlgorithmIdentifier used to sign the proof of possession.
+ * @param signature a signature over the DER-encoded value of poposkIn,
+ * or the DER-encoded value of certReq if poposkIn is null.
+ */
+ public POPOSigningKey(
+ POPOSigningKeyInput poposkIn,
+ AlgorithmIdentifier aid,
+ DERBitString signature)
+ {
+ this.poposkInput = poposkIn;
+ this.algorithmIdentifier = aid;
+ this.signature = signature;
+ }
+
+ public POPOSigningKeyInput getPoposkInput() {
+ return poposkInput;
+ }
+
+ public AlgorithmIdentifier getAlgorithmIdentifier() {
+ return algorithmIdentifier;
+ }
+
+ public DERBitString getSignature() {
+ return signature;
+ }
+
+ /**
+ *
+ * POPOSigningKey ::= SEQUENCE {
+ * poposkInput [0] POPOSigningKeyInput OPTIONAL,
+ * algorithmIdentifier AlgorithmIdentifier,
+ * signature BIT STRING }
+ * -- The signature (using "algorithmIdentifier") is on the
+ * -- DER-encoded value of poposkInput. NOTE: If the CertReqMsg
+ * -- certReq CertTemplate contains the subject and publicKey values,
+ * -- then poposkInput MUST be omitted and the signature MUST be
+ * -- computed on the DER-encoded value of CertReqMsg certReq. If
+ * -- the CertReqMsg certReq CertTemplate does not contain the public
+ * -- key and subject values, then poposkInput MUST be present and
+ * -- MUST be signed. This strategy ensures that the public key is
+ * -- not present in both the poposkInput and CertReqMsg certReq
+ * -- CertTemplate fields.
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (poposkInput != null)
+ {
+ v.add(new DERTaggedObject(false, 0, poposkInput));
+ }
+
+ v.add(algorithmIdentifier);
+ v.add(signature);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/POPOSigningKeyInput.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/POPOSigningKeyInput.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/POPOSigningKeyInput.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/POPOSigningKeyInput.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,134 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.GeneralName;
+import pdftk.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+
+public class POPOSigningKeyInput
+ extends ASN1Object
+{
+ private GeneralName sender;
+ private PKMACValue publicKeyMAC;
+ private SubjectPublicKeyInfo publicKey;
+
+ private POPOSigningKeyInput(ASN1Sequence seq)
+ {
+ ASN1Encodable authInfo = (ASN1Encodable)seq.getObjectAt(0);
+
+ if (authInfo instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagObj = (ASN1TaggedObject)authInfo;
+ if (tagObj.getTagNo() != 0)
+ {
+ throw new IllegalArgumentException(
+ "Unknown authInfo tag: " + tagObj.getTagNo());
+ }
+ sender = GeneralName.getInstance(tagObj.getObject());
+ }
+ else
+ {
+ publicKeyMAC = PKMACValue.getInstance(authInfo);
+ }
+
+ publicKey = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(1));
+ }
+
+ public static POPOSigningKeyInput getInstance(Object o)
+ {
+ if (o instanceof POPOSigningKeyInput)
+ {
+ return (POPOSigningKeyInput)o;
+ }
+
+ if (o != null)
+ {
+ return new POPOSigningKeyInput(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new POPOSigningKeyInput with sender name as authInfo.
+ */
+ public POPOSigningKeyInput(
+ GeneralName sender,
+ SubjectPublicKeyInfo spki)
+ {
+ this.sender = sender;
+ this.publicKey = spki;
+ }
+
+ /**
+ * Creates a new POPOSigningKeyInput using password-based MAC.
+ */
+ public POPOSigningKeyInput(
+ PKMACValue pkmac,
+ SubjectPublicKeyInfo spki)
+ {
+ this.publicKeyMAC = pkmac;
+ this.publicKey = spki;
+ }
+
+ /**
+ * Returns the sender field, or null if authInfo is publicKeyMAC
+ */
+ public GeneralName getSender()
+ {
+ return sender;
+ }
+
+ /**
+ * Returns the publicKeyMAC field, or null if authInfo is sender
+ */
+ public PKMACValue getPublicKeyMAC()
+ {
+ return publicKeyMAC;
+ }
+
+ public SubjectPublicKeyInfo getPublicKey()
+ {
+ return publicKey;
+ }
+
+ /**
+ *
+ * POPOSigningKeyInput ::= SEQUENCE {
+ * authInfo CHOICE {
+ * sender [0] GeneralName,
+ * -- used only if an authenticated identity has been
+ * -- established for the sender (e.g., a DN from a
+ * -- previously-issued and currently-valid certificate
+ * publicKeyMAC PKMACValue },
+ * -- used if no authenticated GeneralName currently exists for
+ * -- the sender; publicKeyMAC contains a password-based MAC
+ * -- on the DER-encoded value of publicKey
+ * publicKey SubjectPublicKeyInfo } -- from CertTemplate
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (sender != null)
+ {
+ v.add(new DERTaggedObject(false, 0, sender));
+ }
+ else
+ {
+ v.add(publicKeyMAC);
+ }
+
+ v.add(publicKey);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/ProofOfPossession.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/ProofOfPossession.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/ProofOfPossession.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/ProofOfPossession.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,108 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERNull;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class ProofOfPossession
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int TYPE_RA_VERIFIED = 0;
+ public static final int TYPE_SIGNING_KEY = 1;
+ public static final int TYPE_KEY_ENCIPHERMENT = 2;
+ public static final int TYPE_KEY_AGREEMENT = 3;
+
+ private int tagNo;
+ private ASN1Encodable obj;
+
+ private ProofOfPossession(ASN1TaggedObject tagged)
+ {
+ tagNo = tagged.getTagNo();
+ switch (tagNo)
+ {
+ case 0:
+ obj = DERNull.INSTANCE;
+ break;
+ case 1:
+ obj = POPOSigningKey.getInstance(tagged, false);
+ break;
+ case 2:
+ case 3:
+ obj = POPOPrivKey.getInstance(tagged, true);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag: " + tagNo);
+ }
+ }
+
+ public static ProofOfPossession getInstance(Object o)
+ {
+ if (o == null || o instanceof ProofOfPossession)
+ {
+ return (ProofOfPossession)o;
+ }
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ return new ProofOfPossession((ASN1TaggedObject)o);
+ }
+
+ throw new IllegalArgumentException("Invalid object: " + o.getClass().getName());
+ }
+
+ /** Creates a ProofOfPossession with type raVerified. */
+ public ProofOfPossession()
+ {
+ tagNo = TYPE_RA_VERIFIED;
+ obj = DERNull.INSTANCE;
+ }
+
+ /** Creates a ProofOfPossession for a signing key. */
+ public ProofOfPossession(POPOSigningKey poposk)
+ {
+ tagNo = TYPE_SIGNING_KEY;
+ obj = poposk;
+ }
+
+ /**
+ * Creates a ProofOfPossession for key encipherment or agreement.
+ * @param type one of TYPE_KEY_ENCIPHERMENT or TYPE_KEY_AGREEMENT
+ */
+ public ProofOfPossession(int type, POPOPrivKey privkey)
+ {
+ tagNo = type;
+ obj = privkey;
+ }
+
+ public int getType()
+ {
+ return tagNo;
+ }
+
+ public ASN1Encodable getObject()
+ {
+ return obj;
+ }
+
+ /**
+ *
+ * ProofOfPossession ::= CHOICE {
+ * raVerified [0] NULL,
+ * -- used if the RA has already verified that the requester is in
+ * -- possession of the private key
+ * signature [1] POPOSigningKey,
+ * keyEncipherment [2] POPOPrivKey,
+ * keyAgreement [3] POPOPrivKey }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(false, tagNo, obj);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/SinglePubInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/SinglePubInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/SinglePubInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/SinglePubInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,72 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.GeneralName;
+
+public class SinglePubInfo
+ extends ASN1Object
+{
+ private ASN1Integer pubMethod;
+ private GeneralName pubLocation;
+
+ private SinglePubInfo(ASN1Sequence seq)
+ {
+ pubMethod = ASN1Integer.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() == 2)
+ {
+ pubLocation = GeneralName.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public static SinglePubInfo getInstance(Object o)
+ {
+ if (o instanceof SinglePubInfo)
+ {
+ return (SinglePubInfo)o;
+ }
+
+ if (o != null)
+ {
+ return new SinglePubInfo(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public GeneralName getPubLocation()
+ {
+ return pubLocation;
+ }
+
+ /**
+ *
+ * SinglePubInfo ::= SEQUENCE {
+ * pubMethod INTEGER {
+ * dontCare (0),
+ * x500 (1),
+ * web (2),
+ * ldap (3) },
+ * pubLocation GeneralName OPTIONAL }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pubMethod);
+
+ if (pubLocation != null)
+ {
+ v.add(pubLocation);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/SubsequentMessage.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/SubsequentMessage.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/crmf/SubsequentMessage.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/crmf/SubsequentMessage.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,29 @@
+package pdftk.org.bouncycastle.asn1.crmf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+
+public class SubsequentMessage
+ extends ASN1Integer
+{
+ public static final SubsequentMessage encrCert = new SubsequentMessage(0);
+ public static final SubsequentMessage challengeResp = new SubsequentMessage(1);
+
+ private SubsequentMessage(int value)
+ {
+ super(value);
+ }
+
+ public static SubsequentMessage valueOf(int value)
+ {
+ if (value == 0)
+ {
+ return encrCert;
+ }
+ if (value == 1)
+ {
+ return challengeResp;
+ }
+
+ throw new IllegalArgumentException("unknown value: " + value);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/CryptoProObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.asn1.cryptopro;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface CryptoProObjectIdentifiers
+{
+ // GOST Algorithms OBJECT IDENTIFIERS :
+ // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2)}
+ static final ASN1ObjectIdentifier GOST_id = new ASN1ObjectIdentifier("1.2.643.2.2");
+
+ static final ASN1ObjectIdentifier gostR3411 = GOST_id.branch("9");
+ static final ASN1ObjectIdentifier gostR3411Hmac = GOST_id.branch("10");
+
+ static final ASN1ObjectIdentifier gostR28147_cbc = new ASN1ObjectIdentifier(GOST_id+".21");
+
+ static final ASN1ObjectIdentifier id_Gost28147_89_CryptoPro_A_ParamSet = GOST_id.branch("31.1");
+
+ static final ASN1ObjectIdentifier gostR3410_94 = new ASN1ObjectIdentifier(GOST_id+".20");
+ static final ASN1ObjectIdentifier gostR3410_2001 = new ASN1ObjectIdentifier(GOST_id+".19");
+ static final ASN1ObjectIdentifier gostR3411_94_with_gostR3410_94 = new ASN1ObjectIdentifier(GOST_id+".4");
+ static final ASN1ObjectIdentifier gostR3411_94_with_gostR3410_2001 = new ASN1ObjectIdentifier(GOST_id+".3");
+
+ // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) hashes(30) }
+ static final ASN1ObjectIdentifier gostR3411_94_CryptoProParamSet = new ASN1ObjectIdentifier(GOST_id+".30.1");
+
+ // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) signs(32) }
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_A = new ASN1ObjectIdentifier(GOST_id+".32.2");
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_B = new ASN1ObjectIdentifier(GOST_id+".32.3");
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_C = new ASN1ObjectIdentifier(GOST_id+".32.4");
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_D = new ASN1ObjectIdentifier(GOST_id+".32.5");
+
+ // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) exchanges(33) }
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_XchA = new ASN1ObjectIdentifier(GOST_id+".33.1");
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_XchB = new ASN1ObjectIdentifier(GOST_id+".33.2");
+ static final ASN1ObjectIdentifier gostR3410_94_CryptoPro_XchC = new ASN1ObjectIdentifier(GOST_id+".33.3");
+
+ //{ iso(1) member-body(2)ru(643) rans(2) cryptopro(2) ecc-signs(35) }
+ static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_A = new ASN1ObjectIdentifier(GOST_id+".35.1");
+ static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_B = new ASN1ObjectIdentifier(GOST_id+".35.2");
+ static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_C = new ASN1ObjectIdentifier(GOST_id+".35.3");
+
+ // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) ecc-exchanges(36) }
+ static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_XchA = new ASN1ObjectIdentifier(GOST_id+".36.0");
+ static final ASN1ObjectIdentifier gostR3410_2001_CryptoPro_XchB = new ASN1ObjectIdentifier(GOST_id+".36.1");
+
+ static final ASN1ObjectIdentifier gost_ElSgDH3410_default = new ASN1ObjectIdentifier(GOST_id+".36.0");
+ static final ASN1ObjectIdentifier gost_ElSgDH3410_1 = new ASN1ObjectIdentifier(GOST_id+".36.1");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/ECGOST3410NamedCurves.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,168 @@
+package pdftk.org.bouncycastle.asn1.cryptopro;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.crypto.params.ECDomainParameters;
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+import pdftk.org.bouncycastle.math.ec.ECFieldElement;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+/**
+ * table of the available named parameters for GOST 3410-2001.
+ */
+public class ECGOST3410NamedCurves
+{
+ static final Hashtable objIds = new Hashtable();
+ static final Hashtable params = new Hashtable();
+ static final Hashtable names = new Hashtable();
+
+ static
+ {
+ BigInteger mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319");
+ BigInteger mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
+
+ ECCurve.Fp curve = new ECCurve.Fp(
+ mod_p, // p
+ new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a
+ new BigInteger("166")); // b
+
+ ECDomainParameters ecParams = new ECDomainParameters(
+ curve,
+ new ECPoint.Fp(curve,
+ new ECFieldElement.Fp(curve.getQ(),new BigInteger("1")), // x
+ new ECFieldElement.Fp(curve.getQ(),new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612"))), // y
+ mod_q);
+
+ params.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_A, ecParams);
+
+ mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319");
+ mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
+
+ curve = new ECCurve.Fp(
+ mod_p, // p
+ new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"),
+ new BigInteger("166"));
+
+ ecParams = new ECDomainParameters(
+ curve,
+ new ECPoint.Fp(curve,
+ new ECFieldElement.Fp(curve.getQ(),new BigInteger("1")), // x
+ new ECFieldElement.Fp(curve.getQ(),new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612"))), // y
+ mod_q);
+
+ params.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchA, ecParams);
+
+ mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823193"); //p
+ mod_q = new BigInteger("57896044618658097711785492504343953927102133160255826820068844496087732066703"); //q
+
+ curve = new ECCurve.Fp(
+ mod_p, // p
+ new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823190"), // a
+ new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595")); // b
+
+ ecParams = new ECDomainParameters(
+ curve,
+ new ECPoint.Fp(curve,
+ new ECFieldElement.Fp(mod_p,new BigInteger("1")), // x
+ new ECFieldElement.Fp(mod_p,new BigInteger("28792665814854611296992347458380284135028636778229113005756334730996303888124"))), // y
+ mod_q); // q
+
+ params.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_B, ecParams);
+
+ mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619");
+ mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601");
+
+ curve = new ECCurve.Fp(
+ mod_p, // p
+ new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"),
+ new BigInteger("32858"));
+
+ ecParams = new ECDomainParameters(
+ curve,
+ new ECPoint.Fp(curve,
+ new ECFieldElement.Fp(mod_p,new BigInteger("0")),
+ new ECFieldElement.Fp(mod_p,new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247"))),
+ mod_q);
+
+ params.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchB, ecParams);
+
+ mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619"); //p
+ mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601"); //q
+ curve = new ECCurve.Fp(
+ mod_p, // p
+ new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), // a
+ new BigInteger("32858")); // b
+
+ ecParams = new ECDomainParameters(
+ curve,
+ new ECPoint.Fp(curve,
+ new ECFieldElement.Fp(mod_p,new BigInteger("0")), // x
+ new ECFieldElement.Fp(mod_p,new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247"))), // y
+ mod_q); // q
+
+ params.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_C, ecParams);
+
+ objIds.put("GostR3410-2001-CryptoPro-A", CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_A);
+ objIds.put("GostR3410-2001-CryptoPro-B", CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_B);
+ objIds.put("GostR3410-2001-CryptoPro-C", CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_C);
+ objIds.put("GostR3410-2001-CryptoPro-XchA", CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchA);
+ objIds.put("GostR3410-2001-CryptoPro-XchB", CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchB);
+
+ names.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_A, "GostR3410-2001-CryptoPro-A");
+ names.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_B, "GostR3410-2001-CryptoPro-B");
+ names.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_C, "GostR3410-2001-CryptoPro-C");
+ names.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchA, "GostR3410-2001-CryptoPro-XchA");
+ names.put(CryptoProObjectIdentifiers.gostR3410_2001_CryptoPro_XchB, "GostR3410-2001-CryptoPro-XchB");
+ }
+
+ /**
+ * return the ECDomainParameters object for the given OID, null if it
+ * isn't present.
+ *
+ * @param oid an object identifier representing a named parameters, if present.
+ */
+ public static ECDomainParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ return (ECDomainParameters)params.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for parameters
+ * contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return objIds.keys();
+ }
+
+ public static ECDomainParameters getByName(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(name);
+
+ if (oid != null)
+ {
+ return (ECDomainParameters)params.get(oid);
+ }
+
+ return null;
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static String getName(
+ ASN1ObjectIdentifier oid)
+ {
+ return (String)names.get(oid);
+ }
+
+ public static ASN1ObjectIdentifier getOID(String name)
+ {
+ return (ASN1ObjectIdentifier)objIds.get(name);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/ECGOST3410ParamSetParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/ECGOST3410ParamSetParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/ECGOST3410ParamSetParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/ECGOST3410ParamSetParameters.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,99 @@
+package pdftk.org.bouncycastle.asn1.cryptopro;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class ECGOST3410ParamSetParameters
+ extends ASN1Object
+{
+ ASN1Integer p, q, a, b, x, y;
+
+ public static ECGOST3410ParamSetParameters getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static ECGOST3410ParamSetParameters getInstance(
+ Object obj)
+ {
+ if(obj == null || obj instanceof ECGOST3410ParamSetParameters)
+ {
+ return (ECGOST3410ParamSetParameters)obj;
+ }
+
+ if(obj instanceof ASN1Sequence)
+ {
+ return new ECGOST3410ParamSetParameters((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid GOST3410Parameter: " + obj.getClass().getName());
+ }
+
+ public ECGOST3410ParamSetParameters(
+ BigInteger a,
+ BigInteger b,
+ BigInteger p,
+ BigInteger q,
+ int x,
+ BigInteger y)
+ {
+ this.a = new ASN1Integer(a);
+ this.b = new ASN1Integer(b);
+ this.p = new ASN1Integer(p);
+ this.q = new ASN1Integer(q);
+ this.x = new ASN1Integer(x);
+ this.y = new ASN1Integer(y);
+ }
+
+ public ECGOST3410ParamSetParameters(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ a = (ASN1Integer)e.nextElement();
+ b = (ASN1Integer)e.nextElement();
+ p = (ASN1Integer)e.nextElement();
+ q = (ASN1Integer)e.nextElement();
+ x = (ASN1Integer)e.nextElement();
+ y = (ASN1Integer)e.nextElement();
+ }
+
+ public BigInteger getP()
+ {
+ return p.getPositiveValue();
+ }
+
+ public BigInteger getQ()
+ {
+ return q.getPositiveValue();
+ }
+
+ public BigInteger getA()
+ {
+ return a.getPositiveValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(a);
+ v.add(b);
+ v.add(p);
+ v.add(q);
+ v.add(x);
+ v.add(y);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST28147Parameters.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,72 @@
+package pdftk.org.bouncycastle.asn1.cryptopro;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class GOST28147Parameters
+ extends ASN1Object
+{
+ ASN1OctetString iv;
+ ASN1ObjectIdentifier paramSet;
+
+ public static GOST28147Parameters getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static GOST28147Parameters getInstance(
+ Object obj)
+ {
+ if(obj == null || obj instanceof GOST28147Parameters)
+ {
+ return (GOST28147Parameters)obj;
+ }
+
+ if(obj instanceof ASN1Sequence)
+ {
+ return new GOST28147Parameters((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid GOST3410Parameter: " + obj.getClass().getName());
+ }
+
+ public GOST28147Parameters(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ iv = (ASN1OctetString)e.nextElement();
+ paramSet = (ASN1ObjectIdentifier)e.nextElement();
+ }
+
+ /**
+ *
+ * Gost28147-89-Parameters ::=
+ * SEQUENCE {
+ * iv Gost28147-89-IV,
+ * encryptionParamSet OBJECT IDENTIFIER
+ * }
+ *
+ * Gost28147-89-IV ::= OCTET STRING (SIZE (8))
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(iv);
+ v.add(paramSet);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST3410NamedParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST3410NamedParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST3410NamedParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST3410NamedParameters.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,116 @@
+package pdftk.org.bouncycastle.asn1.cryptopro;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * table of the available named parameters for GOST 3410-94.
+ */
+public class GOST3410NamedParameters
+{
+ static final Hashtable objIds = new Hashtable();
+ static final Hashtable params = new Hashtable();
+ static final Hashtable names = new Hashtable();
+
+ static private GOST3410ParamSetParameters cryptoProA = new GOST3410ParamSetParameters(
+ 1024,
+ new BigInteger("127021248288932417465907042777176443525787653508916535812817507265705031260985098497423188333483401180925999995120988934130659205614996724254121049274349357074920312769561451689224110579311248812610229678534638401693520013288995000362260684222750813532307004517341633685004541062586971416883686778842537820383"),
+ new BigInteger("68363196144955700784444165611827252895102170888761442055095051287550314083023"),
+ new BigInteger("100997906755055304772081815535925224869841082572053457874823515875577147990529272777244152852699298796483356699682842027972896052747173175480590485607134746852141928680912561502802222185647539190902656116367847270145019066794290930185446216399730872221732889830323194097355403213400972588322876850946740663962")
+// validationAlgorithm {
+// algorithm
+// id-GostR3410-94-bBis,
+// parameters
+// GostR3410-94-ValidationBisParameters: {
+// x0 1376285941,
+// c 3996757427
+// }
+// }
+
+ );
+
+ static private GOST3410ParamSetParameters cryptoProB = new GOST3410ParamSetParameters(
+ 1024,
+ new BigInteger("139454871199115825601409655107690713107041707059928031797758001454375765357722984094124368522288239833039114681648076688236921220737322672160740747771700911134550432053804647694904686120113087816240740184800477047157336662926249423571248823968542221753660143391485680840520336859458494803187341288580489525163"),
+ new BigInteger("79885141663410976897627118935756323747307951916507639758300472692338873533959"),
+ new BigInteger("42941826148615804143873447737955502392672345968607143066798112994089471231420027060385216699563848719957657284814898909770759462613437669456364882730370838934791080835932647976778601915343474400961034231316672578686920482194932878633360203384797092684342247621055760235016132614780652761028509445403338652341")
+// validationAlgorithm {
+// algorithm
+// id-GostR3410-94-bBis,
+// parameters
+// GostR3410-94-ValidationBisParameters: {
+// x0 1536654555,
+// c 1855361757,
+// d 14408629386140014567655
+//4902939282056547857802241461782996702017713059974755104394739915140
+//6115284791024439062735788342744854120601660303926203867703556828005
+//8957203818114895398976594425537561271800850306
+// }
+// }
+//}
+ );
+
+ static private GOST3410ParamSetParameters cryptoProXchA = new GOST3410ParamSetParameters(
+ 1024,
+ new BigInteger("142011741597563481196368286022318089743276138395243738762872573441927459393512718973631166078467600360848946623567625795282774719212241929071046134208380636394084512691828894000571524625445295769349356752728956831541775441763139384457191755096847107846595662547942312293338483924514339614727760681880609734239"),
+ new BigInteger("91771529896554605945588149018382750217296858393520724172743325725474374979801"),
+ new BigInteger("133531813272720673433859519948319001217942375967847486899482359599369642528734712461590403327731821410328012529253871914788598993103310567744136196364803064721377826656898686468463277710150809401182608770201615324990468332931294920912776241137878030224355746606283971659376426832674269780880061631528163475887")
+ );
+
+ static
+ {
+ params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_A, cryptoProA);
+ params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_B, cryptoProB);
+// params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_C, cryptoProC);
+// params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_D, cryptoProD);
+ params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_XchA, cryptoProXchA);
+// params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_XchB, cryptoProXchA);
+// params.put(CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_XchC, cryptoProXchA);
+
+ objIds.put("GostR3410-94-CryptoPro-A", CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_A);
+ objIds.put("GostR3410-94-CryptoPro-B", CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_B);
+ objIds.put("GostR3410-94-CryptoPro-XchA", CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_XchA);
+ }
+
+ /**
+ * return the GOST3410ParamSetParameters object for the given OID, null if it
+ * isn't present.
+ *
+ * @param oid an object identifier representing a named parameters, if present.
+ */
+ public static GOST3410ParamSetParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ return (GOST3410ParamSetParameters)params.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for parameters
+ * contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return objIds.keys();
+ }
+
+ public static GOST3410ParamSetParameters getByName(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(name);
+
+ if (oid != null)
+ {
+ return (GOST3410ParamSetParameters)params.get(oid);
+ }
+
+ return null;
+ }
+
+ public static ASN1ObjectIdentifier getOID(String name)
+ {
+ return (ASN1ObjectIdentifier)objIds.get(name);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST3410ParamSetParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST3410ParamSetParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST3410ParamSetParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST3410ParamSetParameters.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,105 @@
+package pdftk.org.bouncycastle.asn1.cryptopro;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class GOST3410ParamSetParameters
+ extends ASN1Object
+{
+ int keySize;
+ ASN1Integer p, q, a;
+
+ public static GOST3410ParamSetParameters getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static GOST3410ParamSetParameters getInstance(
+ Object obj)
+ {
+ if(obj == null || obj instanceof GOST3410ParamSetParameters)
+ {
+ return (GOST3410ParamSetParameters)obj;
+ }
+
+ if(obj instanceof ASN1Sequence)
+ {
+ return new GOST3410ParamSetParameters((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid GOST3410Parameter: " + obj.getClass().getName());
+ }
+
+ public GOST3410ParamSetParameters(
+ int keySize,
+ BigInteger p,
+ BigInteger q,
+ BigInteger a)
+ {
+ this.keySize = keySize;
+ this.p = new ASN1Integer(p);
+ this.q = new ASN1Integer(q);
+ this.a = new ASN1Integer(a);
+ }
+
+ public GOST3410ParamSetParameters(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ keySize = ((ASN1Integer)e.nextElement()).getValue().intValue();
+ p = (ASN1Integer)e.nextElement();
+ q = (ASN1Integer)e.nextElement();
+ a = (ASN1Integer)e.nextElement();
+ }
+
+ /**
+ * @deprecated use getKeySize
+ */
+ public int getLKeySize()
+ {
+ return keySize;
+ }
+
+ public int getKeySize()
+ {
+ return keySize;
+ }
+
+ public BigInteger getP()
+ {
+ return p.getPositiveValue();
+ }
+
+ public BigInteger getQ()
+ {
+ return q.getPositiveValue();
+ }
+
+ public BigInteger getA()
+ {
+ return a.getPositiveValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(keySize));
+ v.add(p);
+ v.add(q);
+ v.add(a);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/GOST3410PublicKeyAlgParameters.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,101 @@
+package pdftk.org.bouncycastle.asn1.cryptopro;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class GOST3410PublicKeyAlgParameters
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier publicKeyParamSet;
+ private ASN1ObjectIdentifier digestParamSet;
+ private ASN1ObjectIdentifier encryptionParamSet;
+
+ public static GOST3410PublicKeyAlgParameters getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static GOST3410PublicKeyAlgParameters getInstance(
+ Object obj)
+ {
+ if (obj instanceof GOST3410PublicKeyAlgParameters)
+ {
+ return (GOST3410PublicKeyAlgParameters)obj;
+ }
+
+ if(obj != null)
+ {
+ return new GOST3410PublicKeyAlgParameters(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public GOST3410PublicKeyAlgParameters(
+ ASN1ObjectIdentifier publicKeyParamSet,
+ ASN1ObjectIdentifier digestParamSet)
+ {
+ this.publicKeyParamSet = publicKeyParamSet;
+ this.digestParamSet = digestParamSet;
+ this.encryptionParamSet = null;
+ }
+
+ public GOST3410PublicKeyAlgParameters(
+ ASN1ObjectIdentifier publicKeyParamSet,
+ ASN1ObjectIdentifier digestParamSet,
+ ASN1ObjectIdentifier encryptionParamSet)
+ {
+ this.publicKeyParamSet = publicKeyParamSet;
+ this.digestParamSet = digestParamSet;
+ this.encryptionParamSet = encryptionParamSet;
+ }
+
+ public GOST3410PublicKeyAlgParameters(
+ ASN1Sequence seq)
+ {
+ this.publicKeyParamSet = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ this.digestParamSet = (ASN1ObjectIdentifier)seq.getObjectAt(1);
+
+ if (seq.size() > 2)
+ {
+ this.encryptionParamSet = (ASN1ObjectIdentifier)seq.getObjectAt(2);
+ }
+ }
+
+ public ASN1ObjectIdentifier getPublicKeyParamSet()
+ {
+ return publicKeyParamSet;
+ }
+
+ public ASN1ObjectIdentifier getDigestParamSet()
+ {
+ return digestParamSet;
+ }
+
+ public ASN1ObjectIdentifier getEncryptionParamSet()
+ {
+ return encryptionParamSet;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(publicKeyParamSet);
+ v.add(digestParamSet);
+
+ if (encryptionParamSet != null)
+ {
+ v.add(encryptionParamSet);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/cryptopro/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/cryptopro/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes for CRYPTO-PRO related objects - such as GOST identifiers.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/BidirectionalMap.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/BidirectionalMap.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/BidirectionalMap.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/BidirectionalMap.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,21 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import java.util.Hashtable;
+
+public class BidirectionalMap extends Hashtable{
+ private static final long serialVersionUID = -7457289971962812909L;
+
+ Hashtable reverseMap = new Hashtable();
+
+ public Object getReverse(Object o)
+ {
+ return reverseMap.get(o);
+ }
+
+ public Object put(Object key, Object o)
+ {
+ reverseMap.put(o, key);
+ return super.put(key, o);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/CVCertificate.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/CVCertificate.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/CVCertificate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/CVCertificate.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,317 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1InputStream;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1ParsingException;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DERApplicationSpecific;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+
+
+/**
+ * an iso7816Certificate structure.
+ *
+ *
+ * Certificate ::= SEQUENCE {
+ * CertificateBody Iso7816CertificateBody,
+ * signature DER Application specific
+ * }
+ *
+ */
+public class CVCertificate
+ extends ASN1Object
+{
+ private CertificateBody certificateBody;
+ private byte[] signature;
+ private int valid;
+ private static int bodyValid = 0x01;
+ private static int signValid = 0x02;
+ public static final byte version_1 = 0x0;
+
+ public static String ReferenceEncoding = "ISO-8859-1";
+
+ /**
+ * Sets the values of the certificate (body and signature).
+ *
+ * @param appSpe is a DERApplicationSpecific object containing body and signature.
+ * @throws IOException if tags or value are incorrect.
+ */
+ private void setPrivateData(DERApplicationSpecific appSpe)
+ throws IOException
+ {
+ valid = 0;
+ if (appSpe.getApplicationTag() == EACTags.CARDHOLDER_CERTIFICATE)
+ {
+ ASN1InputStream content = new ASN1InputStream(appSpe.getContents());
+ ASN1Primitive tmpObj;
+ while ((tmpObj = content.readObject()) != null)
+ {
+ DERApplicationSpecific aSpe;
+ if (tmpObj instanceof DERApplicationSpecific)
+ {
+ aSpe = (DERApplicationSpecific)tmpObj;
+ switch (aSpe.getApplicationTag())
+ {
+ case EACTags.CERTIFICATE_CONTENT_TEMPLATE:
+ certificateBody = CertificateBody.getInstance(aSpe);
+ valid |= bodyValid;
+ break;
+ case EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP:
+ signature = aSpe.getContents();
+ valid |= signValid;
+ break;
+ default:
+ throw new IOException("Invalid tag, not an Iso7816CertificateStructure :" + aSpe.getApplicationTag());
+ }
+ }
+ else
+ {
+ throw new IOException("Invalid Object, not an Iso7816CertificateStructure");
+ }
+ }
+ }
+ else
+ {
+ throw new IOException("not a CARDHOLDER_CERTIFICATE :" + appSpe.getApplicationTag());
+ }
+ }
+
+ /**
+ * Create an iso7816Certificate structure from an ASN1InputStream.
+ *
+ * @param aIS the byte stream to parse.
+ * @return the Iso7816CertificateStructure represented by the byte stream.
+ * @throws IOException if there is a problem parsing the data.
+ */
+ public CVCertificate(ASN1InputStream aIS)
+ throws IOException
+ {
+ initFrom(aIS);
+ }
+
+ private void initFrom(ASN1InputStream aIS)
+ throws IOException
+ {
+ ASN1Primitive obj;
+ while ((obj = aIS.readObject()) != null)
+ {
+ if (obj instanceof DERApplicationSpecific)
+ {
+ setPrivateData((DERApplicationSpecific)obj);
+ }
+ else
+ {
+ throw new IOException("Invalid Input Stream for creating an Iso7816CertificateStructure");
+ }
+ }
+ }
+
+ /**
+ * Create an iso7816Certificate structure from a DERApplicationSpecific.
+ *
+ * @param appSpe the DERApplicationSpecific object.
+ * @return the Iso7816CertificateStructure represented by the DERApplicationSpecific object.
+ * @throws IOException if there is a problem parsing the data.
+ */
+ private CVCertificate(DERApplicationSpecific appSpe)
+ throws IOException
+ {
+ setPrivateData(appSpe);
+ }
+
+ /**
+ * Create an iso7816Certificate structure from a body and its signature.
+ *
+ * @param body the Iso7816CertificateBody object containing the body.
+ * @param signature the byte array containing the signature
+ * @return the Iso7816CertificateStructure
+ * @throws IOException if there is a problem parsing the data.
+ */
+ public CVCertificate(CertificateBody body, byte[] signature)
+ throws IOException
+ {
+ certificateBody = body;
+ this.signature = signature;
+ // patch remi
+ valid |= bodyValid;
+ valid |= signValid;
+ }
+
+ /**
+ * Create an iso7816Certificate structure from an object.
+ *
+ * @param obj the Object to extract the certificate from.
+ * @return the Iso7816CertificateStructure represented by the byte stream.
+ * @throws IOException if there is a problem parsing the data.
+ */
+ public static CVCertificate getInstance(Object obj)
+ {
+ if (obj instanceof CVCertificate)
+ {
+ return (CVCertificate)obj;
+ }
+ else if (obj != null)
+ {
+ try
+ {
+ return new CVCertificate(DERApplicationSpecific.getInstance(obj));
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("unable to parse data: " + e.getMessage(), e);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Gives the signature of the whole body. Type of signature is given in
+ * the Iso7816CertificateBody.Iso7816PublicKey.ASN1ObjectIdentifier
+ *
+ * @return the signature of the body.
+ */
+ public byte[] getSignature()
+ {
+ return signature;
+ }
+
+ /**
+ * Gives the body of the certificate.
+ *
+ * @return the body.
+ */
+ public CertificateBody getBody()
+ {
+ return certificateBody;
+ }
+
+ /**
+ * @see pdftk.org.bouncycastle.asn1.ASN1Object#toASN1Primitive()
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (valid != (signValid | bodyValid))
+ {
+ return null;
+ }
+ v.add(certificateBody);
+
+ try
+ {
+ v.add(new DERApplicationSpecific(false, EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP, new DEROctetString(signature)));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("unable to convert signature!");
+ }
+
+ return new DERApplicationSpecific(EACTags.CARDHOLDER_CERTIFICATE, v);
+ }
+
+ /**
+ * @return the Holder authorization and role (CVCA, DV, IS).
+ */
+ public ASN1ObjectIdentifier getHolderAuthorization()
+ throws IOException
+ {
+ CertificateHolderAuthorization cha = certificateBody.getCertificateHolderAuthorization();
+ return cha.getOid();
+ }
+
+ /**
+ * @return the date of the certificate generation
+ */
+ public PackedDate getEffectiveDate()
+ throws IOException
+ {
+ return certificateBody.getCertificateEffectiveDate();
+ }
+
+
+ /**
+ * @return the type of certificate (request or profile)
+ * value is either Iso7816CertificateBody.profileType
+ * or Iso7816CertificateBody.requestType. Any other value
+ * is not valid.
+ */
+ public int getCertificateType()
+ {
+ return this.certificateBody.getCertificateType();
+ }
+
+ /**
+ * @return the date of the certificate generation
+ */
+ public PackedDate getExpirationDate()
+ throws IOException
+ {
+ return certificateBody.getCertificateExpirationDate();
+ }
+
+
+ /**
+ * return a bits field coded on one byte. For signification of the
+ * several bit see Iso7816CertificateHolderAuthorization
+ *
+ * @return role and access rigth
+ * @throws IOException
+ * @see CertificateHolderAuthorization
+ */
+ public int getRole()
+ throws IOException
+ {
+ CertificateHolderAuthorization cha = certificateBody.getCertificateHolderAuthorization();
+ return cha.getAccessRights();
+ }
+
+ /**
+ * @return the Authority Reference field of the certificate
+ * @throws IOException
+ */
+ public CertificationAuthorityReference getAuthorityReference()
+ throws IOException
+ {
+ return certificateBody.getCertificationAuthorityReference();
+ }
+
+ /**
+ * @return the Holder Reference Field of the certificate
+ * @throws IOException
+ */
+ public CertificateHolderReference getHolderReference()
+ throws IOException
+ {
+ return certificateBody.getCertificateHolderReference();
+ }
+
+ /**
+ * @return the bits corresponding to the role intented for the certificate
+ * See Iso7816CertificateHolderAuthorization static int for values
+ * @throws IOException
+ */
+ public int getHolderAuthorizationRole()
+ throws IOException
+ {
+ int rights = certificateBody.getCertificateHolderAuthorization().getAccessRights();
+ return rights & 0xC0;
+ }
+
+ /**
+ * @return the bits corresponding the authorizations contained in the certificate
+ * See Iso7816CertificateHolderAuthorization static int for values
+ * @throws IOException
+ */
+ public Flags getHolderAuthorizationRights()
+ throws IOException
+ {
+ return new Flags(certificateBody.getCertificateHolderAuthorization().getAccessRights() & 0x1F);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/CVCertificateRequest.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/CVCertificateRequest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/CVCertificateRequest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/CVCertificateRequest.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,170 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1ParsingException;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.BERTags;
+import pdftk.org.bouncycastle.asn1.DERApplicationSpecific;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+
+//import java.math.BigInteger;
+
+
+public class CVCertificateRequest
+ extends ASN1Object
+{
+ private CertificateBody certificateBody;
+
+ private byte[] innerSignature = null;
+ private byte[] outerSignature = null;
+
+ private int valid;
+
+ private static int bodyValid = 0x01;
+ private static int signValid = 0x02;
+
+ private CVCertificateRequest(DERApplicationSpecific request)
+ throws IOException
+ {
+ if (request.getApplicationTag() == EACTags.AUTHENTIFICATION_DATA)
+ {
+ ASN1Sequence seq = ASN1Sequence.getInstance(request.getObject(BERTags.SEQUENCE));
+
+ initCertBody(DERApplicationSpecific.getInstance(seq.getObjectAt(0)));
+
+ outerSignature = DERApplicationSpecific.getInstance(seq.getObjectAt(seq.size() - 1)).getContents();
+ }
+ else
+ {
+ initCertBody(request);
+ }
+ }
+
+ private void initCertBody(DERApplicationSpecific request)
+ throws IOException
+ {
+ if (request.getApplicationTag() == EACTags.CARDHOLDER_CERTIFICATE)
+ {
+ ASN1Sequence seq = ASN1Sequence.getInstance(request.getObject(BERTags.SEQUENCE));
+ for (Enumeration en = seq.getObjects(); en.hasMoreElements();)
+ {
+ DERApplicationSpecific obj = DERApplicationSpecific.getInstance(en.nextElement());
+ switch (obj.getApplicationTag())
+ {
+ case EACTags.CERTIFICATE_CONTENT_TEMPLATE:
+ certificateBody = CertificateBody.getInstance(obj);
+ valid |= bodyValid;
+ break;
+ case EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP:
+ innerSignature = obj.getContents();
+ valid |= signValid;
+ break;
+ default:
+ throw new IOException("Invalid tag, not an CV Certificate Request element:" + obj.getApplicationTag());
+ }
+ }
+ }
+ else
+ {
+ throw new IOException("not a CARDHOLDER_CERTIFICATE in request:" + request.getApplicationTag());
+ }
+ }
+
+ public static CVCertificateRequest getInstance(Object obj)
+ {
+ if (obj instanceof CVCertificateRequest)
+ {
+ return (CVCertificateRequest)obj;
+ }
+ else if (obj != null)
+ {
+ try
+ {
+ return new CVCertificateRequest(DERApplicationSpecific.getInstance(obj));
+ }
+ catch (IOException e)
+ {
+ throw new ASN1ParsingException("unable to parse data: " + e.getMessage(), e);
+ }
+ }
+
+ return null;
+ }
+
+ ASN1ObjectIdentifier signOid = null;
+ ASN1ObjectIdentifier keyOid = null;
+
+ public static byte[] ZeroArray = new byte[]{0};
+
+
+ String strCertificateHolderReference;
+
+ byte[] encodedAuthorityReference;
+
+ int ProfileId;
+
+ /**
+ * Returns the body of the certificate template
+ *
+ * @return the body.
+ */
+ public CertificateBody getCertificateBody()
+ {
+ return certificateBody;
+ }
+
+ /**
+ * Return the public key data object carried in the request
+ * @return the public key
+ */
+ public PublicKeyDataObject getPublicKey()
+ {
+ return certificateBody.getPublicKey();
+ }
+
+ public byte[] getInnerSignature()
+ {
+ return innerSignature;
+ }
+
+ public byte[] getOuterSignature()
+ {
+ return outerSignature;
+ }
+
+ byte[] certificate = null;
+ protected String overSignerReference = null;
+
+ public boolean hasOuterSignature()
+ {
+ return outerSignature != null;
+ }
+
+ byte[] encoded;
+
+ PublicKeyDataObject iso7816PubKey = null;
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certificateBody);
+
+ try
+ {
+ v.add(new DERApplicationSpecific(false, EACTags.STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP, new DEROctetString(innerSignature)));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("unable to convert signature!");
+ }
+
+ return new DERApplicationSpecific(EACTags.CARDHOLDER_CERTIFICATE, v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/CertificateBody.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/CertificateBody.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/CertificateBody.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/CertificateBody.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,460 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1InputStream;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.BERTags;
+import pdftk.org.bouncycastle.asn1.DERApplicationSpecific;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+
+
+/**
+ * an Iso7816CertificateBody structure.
+ *
+ *
+ * CertificateBody ::= SEQUENCE {
+ * // version of the certificate format. Must be 0 (version 1)
+ * CertificateProfileIdentifer DERApplicationSpecific,
+ * //uniquely identifies the issuinng CA's signature key pair
+ * // contains the iso3166-1 alpha2 encoded country code, the
+ * // name of issuer and the sequence number of the key pair.
+ * CertificationAuthorityReference DERApplicationSpecific,
+ * // stores the encoded public key
+ * PublicKey Iso7816PublicKey,
+ * //associates the public key contained in the certificate with a unique name
+ * // contains the iso3166-1 alpha2 encoded country code, the
+ * // name of the holder and the sequence number of the key pair.
+ * certificateHolderReference DERApplicationSpecific,
+ * // Encodes the role of the holder (i.e. CVCA, DV, IS) and assigns read/write
+ * // access rights to data groups storing sensitive data
+ * certificateHolderAuthorization Iso7816CertificateHolderAuthorization,
+ * // the date of the certificate generation
+ * CertificateEffectiveDate DERApplicationSpecific,
+ * // the date after wich the certificate expires
+ * certificateExpirationDate DERApplicationSpecific
+ * }
+ *
+ */
+public class CertificateBody
+ extends ASN1Object
+{
+ ASN1InputStream seq;
+ private DERApplicationSpecific certificateProfileIdentifier;// version of the certificate format. Must be 0 (version 1)
+ private DERApplicationSpecific certificationAuthorityReference;//uniquely identifies the issuinng CA's signature key pair
+ private PublicKeyDataObject publicKey;// stores the encoded public key
+ private DERApplicationSpecific certificateHolderReference;//associates the public key contained in the certificate with a unique name
+ private CertificateHolderAuthorization certificateHolderAuthorization;// Encodes the role of the holder (i.e. CVCA, DV, IS) and assigns read/write access rights to data groups storing sensitive data
+ private DERApplicationSpecific certificateEffectiveDate;// the date of the certificate generation
+ private DERApplicationSpecific certificateExpirationDate;// the date after wich the certificate expires
+ private int certificateType = 0;// bit field of initialized data. This will tell us if the data are valid.
+ private static final int CPI = 0x01;//certificate Profile Identifier
+ private static final int CAR = 0x02;//certification Authority Reference
+ private static final int PK = 0x04;//public Key
+ private static final int CHR = 0x08;//certificate Holder Reference
+ private static final int CHA = 0x10;//certificate Holder Authorization
+ private static final int CEfD = 0x20;//certificate Effective Date
+ private static final int CExD = 0x40;//certificate Expiration Date
+
+ public static final int profileType = 0x7f;//Profile type Certificate
+ public static final int requestType = 0x0D;// Request type Certificate
+
+ private void setIso7816CertificateBody(DERApplicationSpecific appSpe)
+ throws IOException
+ {
+ byte[] content;
+ if (appSpe.getApplicationTag() == EACTags.CERTIFICATE_CONTENT_TEMPLATE)
+ {
+ content = appSpe.getContents();
+ }
+ else
+ {
+ throw new IOException("Bad tag : not an iso7816 CERTIFICATE_CONTENT_TEMPLATE");
+ }
+ ASN1InputStream aIS = new ASN1InputStream(content);
+ ASN1Primitive obj;
+ while ((obj = aIS.readObject()) != null)
+ {
+ DERApplicationSpecific aSpe;
+
+ if (obj instanceof DERApplicationSpecific)
+ {
+ aSpe = (DERApplicationSpecific)obj;
+ }
+ else
+ {
+ throw new IOException("Not a valid iso7816 content : not a DERApplicationSpecific Object :" + EACTags.encodeTag(appSpe) + obj.getClass());
+ }
+ switch (aSpe.getApplicationTag())
+ {
+ case EACTags.INTERCHANGE_PROFILE:
+ setCertificateProfileIdentifier(aSpe);
+ break;
+ case EACTags.ISSUER_IDENTIFICATION_NUMBER:
+ setCertificationAuthorityReference(aSpe);
+ break;
+ case EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE:
+ setPublicKey(PublicKeyDataObject.getInstance(aSpe.getObject(BERTags.SEQUENCE)));
+ break;
+ case EACTags.CARDHOLDER_NAME:
+ setCertificateHolderReference(aSpe);
+ break;
+ case EACTags.CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE:
+ setCertificateHolderAuthorization(new CertificateHolderAuthorization(aSpe));
+ break;
+ case EACTags.APPLICATION_EFFECTIVE_DATE:
+ setCertificateEffectiveDate(aSpe);
+ break;
+ case EACTags.APPLICATION_EXPIRATION_DATE:
+ setCertificateExpirationDate(aSpe);
+ break;
+ default:
+ certificateType = 0;
+ throw new IOException("Not a valid iso7816 DERApplicationSpecific tag " + aSpe.getApplicationTag());
+ }
+ }
+ }
+
+ /**
+ * builds an Iso7816CertificateBody by settings each parameters.
+ *
+ * @param certificateProfileIdentifier
+ * @param certificationAuthorityReference
+ *
+ * @param publicKey
+ * @param certificateHolderReference
+ * @param certificateHolderAuthorization
+ * @param certificateEffectiveDate
+ * @param certificateExpirationDate
+ * @throws IOException
+ */
+ public CertificateBody(
+ DERApplicationSpecific certificateProfileIdentifier,
+ CertificationAuthorityReference certificationAuthorityReference,
+ PublicKeyDataObject publicKey,
+ CertificateHolderReference certificateHolderReference,
+ CertificateHolderAuthorization certificateHolderAuthorization,
+ PackedDate certificateEffectiveDate,
+ PackedDate certificateExpirationDate
+ )
+ {
+ setCertificateProfileIdentifier(certificateProfileIdentifier);
+ setCertificationAuthorityReference(new DERApplicationSpecific(
+ EACTags.ISSUER_IDENTIFICATION_NUMBER, certificationAuthorityReference.getEncoded()));
+ setPublicKey(publicKey);
+ setCertificateHolderReference(new DERApplicationSpecific(
+ EACTags.CARDHOLDER_NAME, certificateHolderReference.getEncoded()));
+ setCertificateHolderAuthorization(certificateHolderAuthorization);
+ try
+ {
+ setCertificateEffectiveDate(new DERApplicationSpecific(
+ false, EACTags.APPLICATION_EFFECTIVE_DATE, new DEROctetString(certificateEffectiveDate.getEncoding())));
+ setCertificateExpirationDate(new DERApplicationSpecific(
+ false, EACTags.APPLICATION_EXPIRATION_DATE, new DEROctetString(certificateExpirationDate.getEncoding())));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to encode dates: " + e.getMessage());
+ }
+ }
+
+ /**
+ * builds an Iso7816CertificateBody with an ASN1InputStream.
+ *
+ * @param obj DERApplicationSpecific containing the whole body.
+ * @throws IOException if the body is not valid.
+ */
+ private CertificateBody(DERApplicationSpecific obj)
+ throws IOException
+ {
+ setIso7816CertificateBody(obj);
+ }
+
+ /**
+ * create a profile type Iso7816CertificateBody.
+ *
+ * @return return the "profile" type certificate body.
+ * @throws IOException if the DERApplicationSpecific cannot be created.
+ */
+ private ASN1Primitive profileToASN1Object()
+ throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certificateProfileIdentifier);
+ v.add(certificationAuthorityReference);
+ v.add(new DERApplicationSpecific(false, EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE, publicKey));
+ v.add(certificateHolderReference);
+ v.add(certificateHolderAuthorization);
+ v.add(certificateEffectiveDate);
+ v.add(certificateExpirationDate);
+ return new DERApplicationSpecific(EACTags.CERTIFICATE_CONTENT_TEMPLATE, v);
+ }
+
+ private void setCertificateProfileIdentifier(DERApplicationSpecific certificateProfileIdentifier)
+ throws IllegalArgumentException {
+ if (certificateProfileIdentifier.getApplicationTag() == EACTags.INTERCHANGE_PROFILE) {
+ this.certificateProfileIdentifier = certificateProfileIdentifier;
+ certificateType |= CPI;
+ }
+ else
+ throw new IllegalArgumentException("Not an Iso7816Tags.INTERCHANGE_PROFILE tag :"+ EACTags.encodeTag(certificateProfileIdentifier));
+ }
+
+ private void setCertificateHolderReference(DERApplicationSpecific certificateHolderReference)
+ throws IllegalArgumentException {
+ if (certificateHolderReference.getApplicationTag() == EACTags.CARDHOLDER_NAME) {
+ this.certificateHolderReference = certificateHolderReference;
+ certificateType |= CHR;
+ }
+ else
+ throw new IllegalArgumentException("Not an Iso7816Tags.CARDHOLDER_NAME tag");
+ }
+
+ /**
+ * set the CertificationAuthorityReference.
+ * @param certificationAuthorityReference the DERApplicationSpecific containing the CertificationAuthorityReference.
+ * @throws IllegalArgumentException if the DERApplicationSpecific is not valid.
+ */
+ private void setCertificationAuthorityReference(
+ DERApplicationSpecific certificationAuthorityReference)
+ throws IllegalArgumentException {
+ if (certificationAuthorityReference.getApplicationTag() == EACTags.ISSUER_IDENTIFICATION_NUMBER) {
+ this.certificationAuthorityReference = certificationAuthorityReference;
+ certificateType |= CAR;
+ }
+ else
+ throw new IllegalArgumentException("Not an Iso7816Tags.ISSUER_IDENTIFICATION_NUMBER tag");
+ }
+
+ /**
+ * set the public Key
+ * @param publicKey : the DERApplicationSpecific containing the public key
+ * @throws java.io.IOException
+ */
+ private void setPublicKey(PublicKeyDataObject publicKey)
+ {
+ this.publicKey = PublicKeyDataObject.getInstance(publicKey);
+ this.certificateType |= PK;
+ }
+
+ /**
+ * create a request type Iso7816CertificateBody.
+ *
+ * @return return the "request" type certificate body.
+ * @throws IOException if the DERApplicationSpecific cannot be created.
+ */
+ private ASN1Primitive requestToASN1Object()
+ throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certificateProfileIdentifier);
+ v.add(new DERApplicationSpecific(false, EACTags.CARDHOLDER_PUBLIC_KEY_TEMPLATE, publicKey));
+ v.add(certificateHolderReference);
+ return new DERApplicationSpecific(EACTags.CERTIFICATE_CONTENT_TEMPLATE, v);
+ }
+
+ /**
+ * create a "request" or "profile" type Iso7816CertificateBody according to the variables sets.
+ *
+ * @return return the ASN1Primitive representing the "request" or "profile" type certificate body.
+ * @throws IOException if the DERApplicationSpecific cannot be created or if data are missings to create a valid certificate.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ try
+ {
+ if (certificateType == profileType)
+ {
+ return profileToASN1Object();
+ }
+ if (certificateType == requestType)
+ {
+ return requestToASN1Object();
+ }
+ }
+ catch (IOException e)
+ {
+ return null;
+ }
+ return null;
+ }
+
+ /**
+ * gives the type of the certificate (value should be profileType or requestType if all data are set).
+ *
+ * @return the int representing the data already set.
+ */
+ public int getCertificateType()
+ {
+ return certificateType;
+ }
+
+ /**
+ * Gives an instance of Iso7816CertificateBody taken from Object obj
+ *
+ * @param obj is the Object to extract the certificate body from.
+ * @return the Iso7816CertificateBody taken from Object obj.
+ * @throws IOException if object is not valid.
+ */
+ public static CertificateBody getInstance(Object obj)
+ throws IOException
+ {
+ if (obj instanceof CertificateBody)
+ {
+ return (CertificateBody)obj;
+ }
+ else if (obj != null)
+ {
+ return new CertificateBody(DERApplicationSpecific.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * @return the date of the certificate generation
+ */
+ public PackedDate getCertificateEffectiveDate()
+ {
+ if ((this.certificateType & CertificateBody.CEfD) ==
+ CertificateBody.CEfD)
+ {
+ return new PackedDate(certificateEffectiveDate.getContents());
+ }
+ return null;
+ }
+
+ /**
+ * set the date of the certificate generation
+ *
+ * @param ced DERApplicationSpecific containing the date of the certificate generation
+ * @throws IllegalArgumentException if the tag is not Iso7816Tags.APPLICATION_EFFECTIVE_DATE
+ */
+ private void setCertificateEffectiveDate(DERApplicationSpecific ced)
+ throws IllegalArgumentException
+ {
+ if (ced.getApplicationTag() == EACTags.APPLICATION_EFFECTIVE_DATE)
+ {
+ this.certificateEffectiveDate = ced;
+ certificateType |= CEfD;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Not an Iso7816Tags.APPLICATION_EFFECTIVE_DATE tag :" + EACTags.encodeTag(ced));
+ }
+ }
+
+ /**
+ * @return the date after wich the certificate expires
+ */
+ public PackedDate getCertificateExpirationDate()
+ throws IOException
+ {
+ if ((this.certificateType & CertificateBody.CExD) ==
+ CertificateBody.CExD)
+ {
+ return new PackedDate(certificateExpirationDate.getContents());
+ }
+ throw new IOException("certificate Expiration Date not set");
+ }
+
+ /**
+ * set the date after wich the certificate expires
+ *
+ * @param ced DERApplicationSpecific containing the date after wich the certificate expires
+ * @throws IllegalArgumentException if the tag is not Iso7816Tags.APPLICATION_EXPIRATION_DATE
+ */
+ private void setCertificateExpirationDate(DERApplicationSpecific ced)
+ throws IllegalArgumentException
+ {
+ if (ced.getApplicationTag() == EACTags.APPLICATION_EXPIRATION_DATE)
+ {
+ this.certificateExpirationDate = ced;
+ certificateType |= CExD;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Not an Iso7816Tags.APPLICATION_EXPIRATION_DATE tag");
+ }
+ }
+
+ /**
+ * the Iso7816CertificateHolderAuthorization encodes the role of the holder
+ * (i.e. CVCA, DV, IS) and assigns read/write access rights to data groups
+ * storing sensitive data. This functions returns the Certificate Holder
+ * Authorization
+ *
+ * @return the Iso7816CertificateHolderAuthorization
+ */
+ public CertificateHolderAuthorization getCertificateHolderAuthorization()
+ throws IOException
+ {
+ if ((this.certificateType & CertificateBody.CHA) ==
+ CertificateBody.CHA)
+ {
+ return certificateHolderAuthorization;
+ }
+ throw new IOException("Certificate Holder Authorisation not set");
+ }
+
+ /**
+ * set the CertificateHolderAuthorization
+ *
+ * @param cha the Certificate Holder Authorization
+ */
+ private void setCertificateHolderAuthorization(
+ CertificateHolderAuthorization cha)
+ {
+ this.certificateHolderAuthorization = cha;
+ certificateType |= CHA;
+ }
+
+ /**
+ * certificateHolderReference : associates the public key contained in the certificate with a unique name
+ *
+ * @return the certificateHolderReference.
+ */
+ public CertificateHolderReference getCertificateHolderReference()
+ {
+ return new CertificateHolderReference(certificateHolderReference.getContents());
+ }
+
+ /**
+ * CertificateProfileIdentifier : version of the certificate format. Must be 0 (version 1)
+ *
+ * @return the CertificateProfileIdentifier
+ */
+ public DERApplicationSpecific getCertificateProfileIdentifier()
+ {
+ return certificateProfileIdentifier;
+ }
+
+ /**
+ * get the certificationAuthorityReference
+ * certificationAuthorityReference : uniquely identifies the issuinng CA's signature key pair
+ *
+ * @return the certificationAuthorityReference
+ */
+ public CertificationAuthorityReference getCertificationAuthorityReference()
+ throws IOException
+ {
+ if ((this.certificateType & CertificateBody.CAR) ==
+ CertificateBody.CAR)
+ {
+ return new CertificationAuthorityReference(certificationAuthorityReference.getContents());
+ }
+ throw new IOException("Certification authority reference not set");
+ }
+
+ /**
+ * @return the PublicKey
+ */
+ public PublicKeyDataObject getPublicKey()
+ {
+ return publicKey;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/CertificateHolderAuthorization.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/CertificateHolderAuthorization.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/CertificateHolderAuthorization.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/CertificateHolderAuthorization.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,185 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1InputStream;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DERApplicationSpecific;
+import pdftk.org.bouncycastle.util.Integers;
+
+/**
+ * an Iso7816CertificateHolderAuthorization structure.
+ *
+ *
+ * Certificate Holder Authorization ::= SEQUENCE {
+ * // specifies the format and the rules for the evaluation of the authorization
+ * // level
+ * ASN1ObjectIdentifier oid,
+ * // access rights
+ * DERApplicationSpecific accessRights,
+ * }
+ *
+ */
+public class CertificateHolderAuthorization
+ extends ASN1Object
+{
+ ASN1ObjectIdentifier oid;
+ DERApplicationSpecific accessRights;
+ public static final ASN1ObjectIdentifier id_role_EAC = EACObjectIdentifiers.bsi_de.branch("3.1.2.1");
+ public static final int CVCA = 0xC0;
+ public static final int DV_DOMESTIC = 0x80;
+ public static final int DV_FOREIGN = 0x40;
+ public static final int IS = 0;
+ public static final int RADG4 = 0x02;//Read Access to DG4 (Iris)
+ public static final int RADG3 = 0x01;//Read Access to DG3 (fingerprint)
+
+ static Hashtable RightsDecodeMap = new Hashtable();
+ static BidirectionalMap AuthorizationRole = new BidirectionalMap();
+ static Hashtable ReverseMap = new Hashtable();
+
+ static
+ {
+ RightsDecodeMap.put(Integers.valueOf(RADG4), "RADG4");
+ RightsDecodeMap.put(Integers.valueOf(RADG3), "RADG3");
+
+ AuthorizationRole.put(Integers.valueOf(CVCA), "CVCA");
+ AuthorizationRole.put(Integers.valueOf(DV_DOMESTIC), "DV_DOMESTIC");
+ AuthorizationRole.put(Integers.valueOf(DV_FOREIGN), "DV_FOREIGN");
+ AuthorizationRole.put(Integers.valueOf(IS), "IS");
+
+ /*
+ for (int i : RightsDecodeMap.keySet())
+ ReverseMap.put(RightsDecodeMap.get(i), i);
+
+ for (int i : AuthorizationRole.keySet())
+ ReverseMap.put(AuthorizationRole.get(i), i);
+ */
+ }
+
+ public static String GetRoleDescription(int i)
+ {
+ return (String)AuthorizationRole.get(Integers.valueOf(i));
+ }
+
+ public static int GetFlag(String description)
+ {
+ Integer i = (Integer)AuthorizationRole.getReverse(description);
+ if (i == null)
+ {
+ throw new IllegalArgumentException("Unknown value " + description);
+ }
+
+ return i.intValue();
+ }
+
+ private void setPrivateData(ASN1InputStream cha)
+ throws IOException
+ {
+ ASN1Primitive obj;
+ obj = cha.readObject();
+ if (obj instanceof ASN1ObjectIdentifier)
+ {
+ this.oid = (ASN1ObjectIdentifier)obj;
+ }
+ else
+ {
+ throw new IllegalArgumentException("no Oid in CerticateHolderAuthorization");
+ }
+ obj = cha.readObject();
+ if (obj instanceof DERApplicationSpecific)
+ {
+ this.accessRights = (DERApplicationSpecific)obj;
+ }
+ else
+ {
+ throw new IllegalArgumentException("No access rights in CerticateHolderAuthorization");
+ }
+ }
+
+
+ /**
+ * create an Iso7816CertificateHolderAuthorization according to the parameters
+ *
+ * @param oid Object Identifier : specifies the format and the rules for the
+ * evaluatioin of the authorization level.
+ * @param rights specifies the access rights
+ * @throws IOException
+ */
+ public CertificateHolderAuthorization(ASN1ObjectIdentifier oid, int rights)
+ throws IOException
+ {
+ setOid(oid);
+ setAccessRights((byte)rights);
+ }
+
+ /**
+ * create an Iso7816CertificateHolderAuthorization according to the {@link DERApplicationSpecific}
+ *
+ * @param aSpe the DERApplicationSpecific containing the data
+ * @throws IOException
+ */
+ public CertificateHolderAuthorization(DERApplicationSpecific aSpe)
+ throws IOException
+ {
+ if (aSpe.getApplicationTag() == EACTags.CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE)
+ {
+ setPrivateData(new ASN1InputStream(aSpe.getContents()));
+ }
+ }
+
+ /**
+ * @return containing the access rights
+ */
+ public int getAccessRights()
+ {
+ return accessRights.getContents()[0] & 0xff;
+ }
+
+ /**
+ * create a DERApplicationSpecific and set the access rights to "rights"
+ *
+ * @param rights byte containing the rights.
+ */
+ private void setAccessRights(byte rights)
+ {
+ byte[] accessRights = new byte[1];
+ accessRights[0] = rights;
+ this.accessRights = new DERApplicationSpecific(
+ EACTags.getTag(EACTags.DISCRETIONARY_DATA), accessRights);
+ }
+
+ /**
+ * @return the Object identifier
+ */
+ public ASN1ObjectIdentifier getOid()
+ {
+ return oid;
+ }
+
+ /**
+ * set the Object Identifier
+ *
+ * @param oid {@link ASN1ObjectIdentifier} containing the Object Identifier
+ */
+ private void setOid(ASN1ObjectIdentifier oid)
+ {
+ this.oid = oid;
+ }
+
+ /**
+ * return the Certificate Holder Authorization as a DERApplicationSpecific Object
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(oid);
+ v.add(accessRights);
+
+ return new DERApplicationSpecific(EACTags.CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE, v);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/CertificateHolderReference.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/CertificateHolderReference.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/CertificateHolderReference.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/CertificateHolderReference.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,66 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import java.io.UnsupportedEncodingException;
+
+public class CertificateHolderReference
+{
+ private static final String ReferenceEncoding = "ISO-8859-1";
+
+ private String countryCode;
+ private String holderMnemonic;
+ private String sequenceNumber;
+
+ public CertificateHolderReference(String countryCode, String holderMnemonic, String sequenceNumber)
+ {
+ this.countryCode = countryCode;
+ this.holderMnemonic = holderMnemonic;
+ this.sequenceNumber = sequenceNumber;
+ }
+
+ CertificateHolderReference(byte[] contents)
+ {
+ try
+ {
+ String concat = new String(contents, ReferenceEncoding);
+
+ this.countryCode = concat.substring(0, 2);
+ this.holderMnemonic = concat.substring(2, concat.length() - 5);
+
+ this.sequenceNumber = concat.substring(concat.length() - 5);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new IllegalStateException(e.toString());
+ }
+ }
+
+ public String getCountryCode()
+ {
+ return countryCode;
+ }
+
+ public String getHolderMnemonic()
+ {
+ return holderMnemonic;
+ }
+
+ public String getSequenceNumber()
+ {
+ return sequenceNumber;
+ }
+
+
+ public byte[] getEncoded()
+ {
+ String ref = countryCode + holderMnemonic + sequenceNumber;
+
+ try
+ {
+ return ref.getBytes(ReferenceEncoding);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new IllegalStateException(e.toString());
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/CertificationAuthorityReference.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/CertificationAuthorityReference.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/CertificationAuthorityReference.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/CertificationAuthorityReference.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,15 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+public class CertificationAuthorityReference
+ extends CertificateHolderReference
+{
+ public CertificationAuthorityReference(String countryCode, String holderMnemonic, String sequenceNumber)
+ {
+ super(countryCode, holderMnemonic, sequenceNumber);
+ }
+
+ CertificationAuthorityReference(byte[] contents)
+ {
+ super(contents);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/EACObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,55 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface EACObjectIdentifiers
+{
+ // bsi-de OBJECT IDENTIFIER ::= {
+ // itu-t(0) identified-organization(4) etsi(0)
+ // reserved(127) etsi-identified-organization(0) 7
+ // }
+ static final ASN1ObjectIdentifier bsi_de = new ASN1ObjectIdentifier("0.4.0.127.0.7");
+
+ // id-PK OBJECT IDENTIFIER ::= {
+ // bsi-de protocols(2) smartcard(2) 1
+ // }
+ static final ASN1ObjectIdentifier id_PK = bsi_de.branch("2.2.1");
+
+ static final ASN1ObjectIdentifier id_PK_DH = id_PK.branch("1");
+ static final ASN1ObjectIdentifier id_PK_ECDH = id_PK.branch("2");
+
+ // id-CA OBJECT IDENTIFIER ::= {
+ // bsi-de protocols(2) smartcard(2) 3
+ // }
+ static final ASN1ObjectIdentifier id_CA = bsi_de.branch("2.2.3");
+ static final ASN1ObjectIdentifier id_CA_DH = id_CA.branch("1");
+ static final ASN1ObjectIdentifier id_CA_DH_3DES_CBC_CBC = id_CA_DH.branch("1");
+ static final ASN1ObjectIdentifier id_CA_ECDH = id_CA.branch("2");
+ static final ASN1ObjectIdentifier id_CA_ECDH_3DES_CBC_CBC = id_CA_ECDH.branch("1");
+
+ //
+ // id-TA OBJECT IDENTIFIER ::= {
+ // bsi-de protocols(2) smartcard(2) 2
+ // }
+ static final ASN1ObjectIdentifier id_TA = bsi_de.branch("2.2.2");
+
+ static final ASN1ObjectIdentifier id_TA_RSA = id_TA.branch("1");
+ static final ASN1ObjectIdentifier id_TA_RSA_v1_5_SHA_1 = id_TA_RSA .branch("1");
+ static final ASN1ObjectIdentifier id_TA_RSA_v1_5_SHA_256 = id_TA_RSA.branch("2");
+ static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_1 = id_TA_RSA.branch("3");
+ static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_256 = id_TA_RSA.branch("4");
+ static final ASN1ObjectIdentifier id_TA_RSA_v1_5_SHA_512 = id_TA_RSA.branch("5");
+ static final ASN1ObjectIdentifier id_TA_RSA_PSS_SHA_512 = id_TA_RSA.branch("6");
+ static final ASN1ObjectIdentifier id_TA_ECDSA = id_TA.branch("2");
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_1 = id_TA_ECDSA.branch("1");
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_224 = id_TA_ECDSA.branch("2");
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_256 = id_TA_ECDSA.branch("3");
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_384 = id_TA_ECDSA.branch("4");
+ static final ASN1ObjectIdentifier id_TA_ECDSA_SHA_512 = id_TA_ECDSA.branch("5");
+
+ /**
+ * id-EAC-ePassport OBJECT IDENTIFIER ::= {
+ * bsi-de applications(3) mrtd(1) roles(2) 1}
+ */
+ static final ASN1ObjectIdentifier id_EAC_ePassport = bsi_de.branch("3.1.2.1");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/EACTags.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/EACTags.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/EACTags.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/EACTags.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,195 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import pdftk.org.bouncycastle.asn1.BERTags;
+import pdftk.org.bouncycastle.asn1.DERApplicationSpecific;
+
+public class EACTags
+{
+ public static final int OBJECT_IDENTIFIER = 0x06;
+ public static final int COUNTRY_CODE_NATIONAL_DATA = 0x41;
+ public static final int ISSUER_IDENTIFICATION_NUMBER = 0x02; //0x42;
+ public static final int CARD_SERVICE_DATA = 0x43;
+ public static final int INITIAL_ACCESS_DATA = 0x44;
+ public static final int CARD_ISSUER_DATA = 0x45;
+ public static final int PRE_ISSUING_DATA = 0x46;
+ public static final int CARD_CAPABILITIES = 0x47;
+ public static final int STATUS_INFORMATION = 0x48;
+ public static final int EXTENDED_HEADER_LIST = 0x4D;
+ public static final int APPLICATION_IDENTIFIER = 0x4F;
+ public static final int APPLICATION_LABEL = 0x50;
+ public static final int FILE_REFERENCE = 0x51;
+ public static final int COMMAND_TO_PERFORM = 0x52;
+ public static final int DISCRETIONARY_DATA = 0x53;
+ public static final int OFFSET_DATA_OBJECT = 0x54;
+ public static final int TRACK1_APPLICATION = 0x56;
+ public static final int TRACK2_APPLICATION = 0x57;
+ public static final int TRACK3_APPLICATION = 0x58;
+ public static final int CARD_EXPIRATION_DATA = 0x59;
+ public static final int PRIMARY_ACCOUNT_NUMBER = 0x5A;// PAN
+ public static final int NAME = 0x5B;
+ public static final int TAG_LIST = 0x5C;
+ public static final int HEADER_LIST = 0x5D;
+ public static final int LOGIN_DATA = 0x5E;
+ public static final int CARDHOLDER_NAME = 0x20; // 0x5F20;
+ public static final int TRACK1_CARD = 0x5F21;
+ public static final int TRACK2_CARD = 0x5F22;
+ public static final int TRACK3_CARD = 0x5F23;
+ public static final int APPLICATION_EXPIRATION_DATE = 0x24; // 0x5F24;
+ public static final int APPLICATION_EFFECTIVE_DATE = 0x25; // 0x5F25;
+ public static final int CARD_EFFECTIVE_DATE = 0x5F26;
+ public static final int INTERCHANGE_CONTROL = 0x5F27;
+ public static final int COUNTRY_CODE = 0x5F28;
+ public static final int INTERCHANGE_PROFILE = 0x29; // 0x5F29;
+ public static final int CURRENCY_CODE = 0x5F2A;
+ public static final int DATE_OF_BIRTH = 0x5F2B;
+ public static final int CARDHOLDER_NATIONALITY = 0x5F2C;
+ public static final int LANGUAGE_PREFERENCES = 0x5F2D;
+ public static final int CARDHOLDER_BIOMETRIC_DATA = 0x5F2E;
+ public static final int PIN_USAGE_POLICY = 0x5F2F;
+ public static final int SERVICE_CODE = 0x5F30;
+ public static final int TRANSACTION_COUNTER = 0x5F32;
+ public static final int TRANSACTION_DATE = 0x5F33;
+ public static final int CARD_SEQUENCE_NUMBER = 0x5F34;
+ public static final int SEX = 0x5F35;
+ public static final int CURRENCY_EXPONENT = 0x5F36;
+ public static final int STATIC_INTERNAL_AUTHENTIFICATION_ONE_STEP = 0x37; // 0x5F37;
+ public static final int SIGNATURE = 0x5F37;
+ public static final int STATIC_INTERNAL_AUTHENTIFICATION_FIRST_DATA = 0x5F38;
+ public static final int STATIC_INTERNAL_AUTHENTIFICATION_SECOND_DATA = 0x5F39;
+ public static final int DYNAMIC_INTERNAL_AUTHENTIFICATION = 0x5F3A;
+ public static final int DYNAMIC_EXTERNAL_AUTHENTIFICATION = 0x5F3B;
+ public static final int DYNAMIC_MUTUAL_AUTHENTIFICATION = 0x5F3C;
+ public static final int CARDHOLDER_PORTRAIT_IMAGE = 0x5F40;
+ public static final int ELEMENT_LIST = 0x5F41;
+ public static final int ADDRESS = 0x5F42;
+ public static final int CARDHOLDER_HANDWRITTEN_SIGNATURE = 0x5F43;
+ public static final int APPLICATION_IMAGE = 0x5F44;
+ public static final int DISPLAY_IMAGE = 0x5F45;
+ public static final int TIMER = 0x5F46;
+ public static final int MESSAGE_REFERENCE = 0x5F47;
+ public static final int CARDHOLDER_PRIVATE_KEY = 0x5F48;
+ public static final int CARDHOLDER_PUBLIC_KEY = 0x5F49;
+ public static final int CERTIFICATION_AUTHORITY_PUBLIC_KEY = 0x5F4A;
+ public static final int DEPRECATED = 0x5F4B;
+ public static final int CERTIFICATE_HOLDER_AUTHORIZATION = 0x5F4C;// Not yet defined in iso7816. The allocation is requested
+ public static final int INTEGRATED_CIRCUIT_MANUFACTURER_ID = 0x5F4D;
+ public static final int CERTIFICATE_CONTENT = 0x5F4E;
+ public static final int UNIFORM_RESOURCE_LOCATOR = 0x5F50;
+ public static final int ANSWER_TO_RESET = 0x5F51;
+ public static final int HISTORICAL_BYTES = 0x5F52;
+ public static final int DIGITAL_SIGNATURE = 0x5F3D;
+ public static final int APPLICATION_TEMPLATE = 0x61;
+ public static final int FCP_TEMPLATE = 0x62;
+ public static final int WRAPPER = 0x63;
+ public static final int FMD_TEMPLATE = 0x64;
+ public static final int CARDHOLDER_RELATIVE_DATA = 0x65;
+ public static final int CARD_DATA = 0x66;
+ public static final int AUTHENTIFICATION_DATA = 0x67;
+ public static final int SPECIAL_USER_REQUIREMENTS = 0x68;
+ public static final int LOGIN_TEMPLATE = 0x6A;
+ public static final int QUALIFIED_NAME = 0x6B;
+ public static final int CARDHOLDER_IMAGE_TEMPLATE = 0x6C;
+ public static final int APPLICATION_IMAGE_TEMPLATE = 0x6D;
+ public static final int APPLICATION_RELATED_DATA = 0x6E;
+ public static final int FCI_TEMPLATE = 0x6F;
+ public static final int DISCRETIONARY_DATA_OBJECTS = 0x73;
+ public static final int COMPATIBLE_TAG_ALLOCATION_AUTHORITY = 0x78;
+ public static final int COEXISTANT_TAG_ALLOCATION_AUTHORITY = 0x79;
+ public static final int SECURITY_SUPPORT_TEMPLATE = 0x7A;
+ public static final int SECURITY_ENVIRONMENT_TEMPLATE = 0x7B;
+ public static final int DYNAMIC_AUTHENTIFICATION_TEMPLATE = 0x7C;
+ public static final int SECURE_MESSAGING_TEMPLATE = 0x7D;
+ public static final int NON_INTERINDUSTRY_DATA_OBJECT_NESTING_TEMPLATE = 0x7E;
+ public static final int DISPLAY_CONTROL = 0x7F20;
+ public static final int CARDHOLDER_CERTIFICATE = 0x21; // 0x7F21;
+ public static final int CV_CERTIFICATE = 0x7F21;
+ public static final int CARDHOLER_REQUIREMENTS_INCLUDED_FEATURES = 0x7F22;
+ public static final int CARDHOLER_REQUIREMENTS_EXCLUDED_FEATURES = 0x7F23;
+ public static final int BIOMETRIC_DATA_TEMPLATE = 0x7F2E;
+ public static final int DIGITAL_SIGNATURE_BLOCK = 0x7F3D;
+ public static final int CARDHOLDER_PRIVATE_KEY_TEMPLATE = 0x7F48;
+ public static final int CARDHOLDER_PUBLIC_KEY_TEMPLATE = 0x49; // 0x7F49;
+ public static final int CERTIFICATE_HOLDER_AUTHORIZATION_TEMPLATE = 0x4C; // 0x7F4C;
+ public static final int CERTIFICATE_CONTENT_TEMPLATE = 0x4E; // 0x7F4E;
+ public static final int CERTIFICATE_BODY = 0x4E; // 0x7F4E;
+ public static final int BIOMETRIC_INFORMATION_TEMPLATE = 0x7F60;
+ public static final int BIOMETRIC_INFORMATION_GROUP_TEMPLATE = 0x7F61;
+
+ public static int getTag(int encodedTag) {
+ /*
+ int i;
+ for (i = 24; i>=0; i-=8) {
+ if (((0xFF<> i);
+ }
+ return 0;
+ */
+ return decodeTag(encodedTag);
+ }
+
+ public static int getTagNo(int tag) {
+ int i;
+ for (i = 24; i>=0; i -=8) {
+ if (((0xFF< 31)
+ {
+ retValue |= 0x1F;
+ retValue <<= 8;
+
+ int currentByte = tag & 0x7F;
+ retValue |= currentByte;
+ tag >>= 7;
+
+ while (tag > 0)
+ {
+ retValue |= 0x80;
+ retValue <<= 8;
+
+ currentByte = tag & 0x7F;
+ tag >>= 7;
+ }
+ }
+ else
+ retValue |= tag;
+
+ return retValue;
+ }
+
+ public static int decodeTag(int tag)
+ {
+ int retValue = 0;
+ boolean multiBytes = false;
+ for (int i = 24; i>=0; i -=8) {
+ int currentByte = tag >> i & 0xFF;
+ if (currentByte == 0)
+ continue;
+
+ if (multiBytes)
+ {
+ retValue <<= 7;
+ retValue |= currentByte & 0x7F;
+ }
+ else if ((currentByte & 0x1F) == 0x1F)
+ {
+ multiBytes = true;
+ }
+ else
+ return currentByte & 0x1F; // higher order bit are for DER.Constructed and type
+ }
+ return retValue;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/ECDSAPublicKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/ECDSAPublicKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/ECDSAPublicKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/ECDSAPublicKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,341 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * an Iso7816ECDSAPublicKeyStructure structure.
+ *
+ *
+ * Certificate Holder Authorization ::= SEQUENCE {
+ * ASN1TaggedObject primeModulusP; // OPTIONAL
+ * ASN1TaggedObject firstCoefA; // OPTIONAL
+ * ASN1TaggedObject secondCoefB; // OPTIONAL
+ * ASN1TaggedObject basePointG; // OPTIONAL
+ * ASN1TaggedObject orderOfBasePointR; // OPTIONAL
+ * ASN1TaggedObject publicPointY; //REQUIRED
+ * ASN1TaggedObject cofactorF; // OPTIONAL
+ * }
+ *
+ */
+public class ECDSAPublicKey
+ extends PublicKeyDataObject
+{
+ private ASN1ObjectIdentifier usage;
+ private BigInteger primeModulusP; // OPTIONAL
+ private BigInteger firstCoefA; // OPTIONAL
+ private BigInteger secondCoefB; // OPTIONAL
+ private byte[] basePointG; // OPTIONAL
+ private BigInteger orderOfBasePointR; // OPTIONAL
+ private byte[] publicPointY; //REQUIRED
+ private BigInteger cofactorF; // OPTIONAL
+ private int options;
+ private static final int P = 0x01;
+ private static final int A = 0x02;
+ private static final int B = 0x04;
+ private static final int G = 0x08;
+ private static final int R = 0x10;
+ private static final int Y = 0x20;
+ private static final int F = 0x40;
+
+ ECDSAPublicKey(ASN1Sequence seq)
+ throws IllegalArgumentException
+ {
+ Enumeration en = seq.getObjects();
+
+ this.usage = ASN1ObjectIdentifier.getInstance(en.nextElement());
+
+ options = 0;
+ while (en.hasMoreElements())
+ {
+ Object obj = en.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject to = (ASN1TaggedObject)obj;
+ switch (to.getTagNo())
+ {
+ case 0x1:
+ setPrimeModulusP(UnsignedInteger.getInstance(to).getValue());
+ break;
+ case 0x2:
+ setFirstCoefA(UnsignedInteger.getInstance(to).getValue());
+ break;
+ case 0x3:
+ setSecondCoefB(UnsignedInteger.getInstance(to).getValue());
+ break;
+ case 0x4:
+ setBasePointG(ASN1OctetString.getInstance(to, false));
+ break;
+ case 0x5:
+ setOrderOfBasePointR(UnsignedInteger.getInstance(to).getValue());
+ break;
+ case 0x6:
+ setPublicPointY(ASN1OctetString.getInstance(to, false));
+ break;
+ case 0x7:
+ setCofactorF(UnsignedInteger.getInstance(to).getValue());
+ break;
+ default:
+ options = 0;
+ throw new IllegalArgumentException("Unknown Object Identifier!");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Unknown Object Identifier!");
+ }
+ }
+ if (options != 0x20 && options != 0x7F)
+ {
+ throw new IllegalArgumentException("All options must be either present or absent!");
+ }
+ }
+
+ public ECDSAPublicKey(ASN1ObjectIdentifier usage, byte[] ppY)
+ throws IllegalArgumentException
+ {
+ this.usage = usage;
+ setPublicPointY(new DEROctetString(ppY));
+ }
+
+ public ECDSAPublicKey(ASN1ObjectIdentifier usage, BigInteger p, BigInteger a, BigInteger b, byte[] basePoint, BigInteger order, byte[] publicPoint, int cofactor)
+ {
+ this.usage = usage;
+ setPrimeModulusP(p);
+ setFirstCoefA(a);
+ setSecondCoefB(b);
+ setBasePointG(new DEROctetString(basePoint));
+ setOrderOfBasePointR(order);
+ setPublicPointY(new DEROctetString(publicPoint));
+ setCofactorF(BigInteger.valueOf(cofactor));
+ }
+
+ public ASN1ObjectIdentifier getUsage()
+ {
+ return usage;
+ }
+
+ public byte[] getBasePointG()
+ {
+ if ((options & G) != 0)
+ {
+ return basePointG;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setBasePointG(ASN1OctetString basePointG)
+ throws IllegalArgumentException
+ {
+ if ((options & G) == 0)
+ {
+ options |= G;
+ this.basePointG = basePointG.getOctets();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Base Point G already set");
+ }
+ }
+
+ public BigInteger getCofactorF()
+ {
+ if ((options & F) != 0)
+ {
+ return cofactorF;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setCofactorF(BigInteger cofactorF)
+ throws IllegalArgumentException
+ {
+ if ((options & F) == 0)
+ {
+ options |= F;
+ this.cofactorF = cofactorF;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cofactor F already set");
+ }
+ }
+
+ public BigInteger getFirstCoefA()
+ {
+ if ((options & A) != 0)
+ {
+ return firstCoefA;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setFirstCoefA(BigInteger firstCoefA)
+ throws IllegalArgumentException
+ {
+ if ((options & A) == 0)
+ {
+ options |= A;
+ this.firstCoefA = firstCoefA;
+ }
+ else
+ {
+ throw new IllegalArgumentException("First Coef A already set");
+ }
+ }
+
+ public BigInteger getOrderOfBasePointR()
+ {
+ if ((options & R) != 0)
+ {
+ return orderOfBasePointR;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setOrderOfBasePointR(BigInteger orderOfBasePointR)
+ throws IllegalArgumentException
+ {
+ if ((options & R) == 0)
+ {
+ options |= R;
+ this.orderOfBasePointR = orderOfBasePointR;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Order of base point R already set");
+ }
+ }
+
+ public BigInteger getPrimeModulusP()
+ {
+ if ((options & P) != 0)
+ {
+ return primeModulusP;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setPrimeModulusP(BigInteger primeModulusP)
+ {
+ if ((options & P) == 0)
+ {
+ options |= P;
+ this.primeModulusP = primeModulusP;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Prime Modulus P already set");
+ }
+ }
+
+ public byte[] getPublicPointY()
+ {
+ if ((options & Y) != 0)
+ {
+ return publicPointY;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setPublicPointY(ASN1OctetString publicPointY)
+ throws IllegalArgumentException
+ {
+ if ((options & Y) == 0)
+ {
+ options |= Y;
+ this.publicPointY = publicPointY.getOctets();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Public Point Y already set");
+ }
+ }
+
+ public BigInteger getSecondCoefB()
+ {
+ if ((options & B) != 0)
+ {
+ return secondCoefB;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void setSecondCoefB(BigInteger secondCoefB)
+ throws IllegalArgumentException
+ {
+ if ((options & B) == 0)
+ {
+ options |= B;
+ this.secondCoefB = secondCoefB;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Second Coef B already set");
+ }
+ }
+
+ public boolean hasParameters()
+ {
+ return primeModulusP != null;
+ }
+
+ public ASN1EncodableVector getASN1EncodableVector(ASN1ObjectIdentifier oid, boolean publicPointOnly)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(oid);
+
+ if (!publicPointOnly)
+ {
+ v.add(new UnsignedInteger(0x01, getPrimeModulusP()));
+ v.add(new UnsignedInteger(0x02, getFirstCoefA()));
+ v.add(new UnsignedInteger(0x03, getSecondCoefB()));
+ v.add(new DERTaggedObject(false, 0x04, new DEROctetString(getBasePointG())));
+ v.add(new UnsignedInteger(0x05, getOrderOfBasePointR()));
+ }
+ v.add(new DERTaggedObject(false, 0x06, new DEROctetString(getPublicPointY())));
+ if (!publicPointOnly)
+ {
+ v.add(new UnsignedInteger(0x07, getCofactorF()));
+ }
+
+ return v;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERSequence(getASN1EncodableVector(usage, false));
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/Flags.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/Flags.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/Flags.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/Flags.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,96 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+
+public class Flags
+{
+
+ int value = 0;
+
+ public Flags()
+ {
+
+ }
+
+ public Flags(int v)
+ {
+ value = v;
+ }
+
+ public void set(int flag)
+ {
+ value |= flag;
+ }
+
+ public boolean isSet(int flag)
+ {
+ return (value & flag) != 0;
+ }
+
+ public int getFlags()
+ {
+ return value;
+ }
+
+ /* Java 1.5
+ String decode(Map decodeMap)
+ {
+ StringJoiner joiner = new StringJoiner(" ");
+ for (int i : decodeMap.keySet())
+ {
+ if (isSet(i))
+ joiner.add(decodeMap.get(i));
+ }
+ return joiner.toString();
+ }
+ */
+
+ String decode(Hashtable decodeMap)
+ {
+ StringJoiner joiner = new StringJoiner(" ");
+ Enumeration e = decodeMap.keys();
+ while (e.hasMoreElements())
+ {
+ Integer i = (Integer)e.nextElement();
+ if (isSet(i.intValue()))
+ {
+ joiner.add((String)decodeMap.get(i));
+ }
+ }
+ return joiner.toString();
+ }
+
+ private class StringJoiner
+ {
+
+ String mSeparator;
+ boolean First = true;
+ StringBuffer b = new StringBuffer();
+
+ public StringJoiner(String separator)
+ {
+ mSeparator = separator;
+ }
+
+ public void add(String str)
+ {
+ if (First)
+ {
+ First = false;
+ }
+ else
+ {
+ b.append(mSeparator);
+ }
+
+ b.append(str);
+ }
+
+ public String toString()
+ {
+ return b.toString();
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/PackedDate.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/PackedDate.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/PackedDate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/PackedDate.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,103 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.SimpleTimeZone;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * EAC encoding date object
+ */
+public class PackedDate
+{
+ private byte[] time;
+
+ public PackedDate(
+ String time)
+ {
+ this.time = convert(time);
+ }
+
+ /**
+ * base constructer from a java.util.date object
+ */
+ public PackedDate(
+ Date time)
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyMMdd'Z'");
+
+ dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+ this.time = convert(dateF.format(time));
+ }
+
+ private byte[] convert(String sTime)
+ {
+ char[] digs = sTime.toCharArray();
+ byte[] date = new byte[6];
+
+ for (int i = 0; i != 6; i++)
+ {
+ date[i] = (byte)(digs[i] - '0');
+ }
+
+ return date;
+ }
+
+ PackedDate(
+ byte[] bytes)
+ {
+ this.time = bytes;
+ }
+
+ /**
+ * return the time as a date based on whatever a 2 digit year will return. For
+ * standardised processing use getAdjustedDate().
+ *
+ * @return the resulting date
+ * @exception java.text.ParseException if the date string cannot be parsed.
+ */
+ public Date getDate()
+ throws ParseException
+ {
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMdd");
+
+ return dateF.parse("20" + toString());
+ }
+
+ public int hashCode()
+ {
+ return Arrays.hashCode(time);
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof PackedDate))
+ {
+ return false;
+ }
+
+ PackedDate other = (PackedDate)o;
+
+ return Arrays.areEqual(time, other.time);
+ }
+
+ public String toString()
+ {
+ char[] dateC = new char[time.length];
+
+ for (int i = 0; i != dateC.length; i++)
+ {
+ dateC[i] = (char)((time[i] & 0xff) + '0');
+ }
+
+ return new String(dateC);
+ }
+
+ public byte[] getEncoding()
+ {
+ return time;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/PublicKeyDataObject.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/PublicKeyDataObject.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/PublicKeyDataObject.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/PublicKeyDataObject.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,35 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+
+public abstract class PublicKeyDataObject
+ extends ASN1Object
+{
+ public static PublicKeyDataObject getInstance(Object obj)
+ {
+ if (obj instanceof PublicKeyDataObject)
+ {
+ return (PublicKeyDataObject)obj;
+ }
+ if (obj != null)
+ {
+ ASN1Sequence seq = ASN1Sequence.getInstance(obj);
+ ASN1ObjectIdentifier usage = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+
+ if (usage.on(EACObjectIdentifiers.id_TA_ECDSA))
+ {
+ return new ECDSAPublicKey(seq);
+ }
+ else
+ {
+ return new RSAPublicKey(seq);
+ }
+ }
+
+ return null;
+ }
+
+ public abstract ASN1ObjectIdentifier getUsage();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/RSAPublicKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/RSAPublicKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/RSAPublicKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/RSAPublicKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,121 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+
+/**
+ * an Iso7816RSAPublicKeyStructure structure.
+ *
+ *
+ * Certificate Holder Authorization ::= SEQUENCE {
+ * // modulus should be at least 1024bit and a multiple of 512.
+ * DERTaggedObject modulus,
+ * // access rights exponent
+ * DERTaggedObject accessRights,
+ * }
+ *
+ */
+public class RSAPublicKey
+ extends PublicKeyDataObject
+{
+ private ASN1ObjectIdentifier usage;
+ private BigInteger modulus;
+ private BigInteger exponent;
+ private int valid = 0;
+ private static int modulusValid = 0x01;
+ private static int exponentValid = 0x02;
+
+ RSAPublicKey(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+
+ this.usage = ASN1ObjectIdentifier.getInstance(en.nextElement());
+
+ while (en.hasMoreElements())
+ {
+ UnsignedInteger val = UnsignedInteger.getInstance(en.nextElement());
+
+ switch (val.getTagNo())
+ {
+ case 0x1:
+ setModulus(val);
+ break;
+ case 0x2:
+ setExponent(val);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown DERTaggedObject :" + val.getTagNo() + "-> not an Iso7816RSAPublicKeyStructure");
+ }
+ }
+ if (valid != 0x3)
+ {
+ throw new IllegalArgumentException("missing argument -> not an Iso7816RSAPublicKeyStructure");
+ }
+ }
+
+ public RSAPublicKey(ASN1ObjectIdentifier usage, BigInteger modulus, BigInteger exponent)
+ {
+ this.usage = usage;
+ this.modulus = modulus;
+ this.exponent = exponent;
+ }
+
+ public ASN1ObjectIdentifier getUsage()
+ {
+ return usage;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return exponent;
+ }
+
+ private void setModulus(UnsignedInteger modulus)
+ {
+ if ((valid & modulusValid) == 0)
+ {
+ valid |= modulusValid;
+ this.modulus = modulus.getValue();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Modulus already set");
+ }
+ }
+
+ private void setExponent(UnsignedInteger exponent)
+ {
+ if ((valid & exponentValid) == 0)
+ {
+ valid |= exponentValid;
+ this.exponent = exponent.getValue();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Exponent already set");
+ }
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(usage);
+ v.add(new UnsignedInteger(0x01, getModulus()));
+ v.add(new UnsignedInteger(0x02, getPublicExponent()));
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/UnsignedInteger.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/UnsignedInteger.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/eac/UnsignedInteger.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/eac/UnsignedInteger.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,74 @@
+package pdftk.org.bouncycastle.asn1.eac;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class UnsignedInteger
+ extends ASN1Object
+{
+ private int tagNo;
+ private BigInteger value;
+
+ public UnsignedInteger(int tagNo, BigInteger value)
+ {
+ this.tagNo = tagNo;
+ this.value = value;
+ }
+
+ private UnsignedInteger(ASN1TaggedObject obj)
+ {
+ this.tagNo = obj.getTagNo();
+ this.value = new BigInteger(1, ASN1OctetString.getInstance(obj, false).getOctets());
+ }
+
+ public static UnsignedInteger getInstance(Object obj)
+ {
+ if (obj instanceof UnsignedInteger)
+ {
+ return (UnsignedInteger)obj;
+ }
+ if (obj != null)
+ {
+ return new UnsignedInteger(ASN1TaggedObject.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private byte[] convertValue()
+ {
+ byte[] v = value.toByteArray();
+
+ if (v[0] == 0)
+ {
+ byte[] tmp = new byte[v.length - 1];
+
+ System.arraycopy(v, 1, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ return v;
+ }
+
+ public int getTagNo()
+ {
+ return tagNo;
+ }
+
+ public BigInteger getValue()
+ {
+ return value;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(false, tagNo, new DEROctetString(convertValue()));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CommitmentTypeIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CommitmentTypeIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CommitmentTypeIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CommitmentTypeIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,14 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+public interface CommitmentTypeIdentifier
+{
+ public static final ASN1ObjectIdentifier proofOfOrigin = PKCSObjectIdentifiers.id_cti_ets_proofOfOrigin;
+ public static final ASN1ObjectIdentifier proofOfReceipt = PKCSObjectIdentifiers.id_cti_ets_proofOfReceipt;
+ public static final ASN1ObjectIdentifier proofOfDelivery = PKCSObjectIdentifiers.id_cti_ets_proofOfDelivery;
+ public static final ASN1ObjectIdentifier proofOfSender = PKCSObjectIdentifiers.id_cti_ets_proofOfSender;
+ public static final ASN1ObjectIdentifier proofOfApproval = PKCSObjectIdentifiers.id_cti_ets_proofOfApproval;
+ public static final ASN1ObjectIdentifier proofOfCreation = PKCSObjectIdentifiers.id_cti_ets_proofOfCreation;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CommitmentTypeIndication.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CommitmentTypeIndication.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CommitmentTypeIndication.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CommitmentTypeIndication.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,83 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class CommitmentTypeIndication
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier commitmentTypeId;
+ private ASN1Sequence commitmentTypeQualifier;
+
+ private CommitmentTypeIndication(
+ ASN1Sequence seq)
+ {
+ commitmentTypeId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+
+ if (seq.size() > 1)
+ {
+ commitmentTypeQualifier = (ASN1Sequence)seq.getObjectAt(1);
+ }
+ }
+
+ public CommitmentTypeIndication(
+ ASN1ObjectIdentifier commitmentTypeId)
+ {
+ this.commitmentTypeId = commitmentTypeId;
+ }
+
+ public CommitmentTypeIndication(
+ ASN1ObjectIdentifier commitmentTypeId,
+ ASN1Sequence commitmentTypeQualifier)
+ {
+ this.commitmentTypeId = commitmentTypeId;
+ this.commitmentTypeQualifier = commitmentTypeQualifier;
+ }
+
+ public static CommitmentTypeIndication getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof CommitmentTypeIndication)
+ {
+ return (CommitmentTypeIndication)obj;
+ }
+
+ return new CommitmentTypeIndication(ASN1Sequence.getInstance(obj));
+ }
+
+ public ASN1ObjectIdentifier getCommitmentTypeId()
+ {
+ return commitmentTypeId;
+ }
+
+ public ASN1Sequence getCommitmentTypeQualifier()
+ {
+ return commitmentTypeQualifier;
+ }
+
+ /**
+ *
+ * CommitmentTypeIndication ::= SEQUENCE {
+ * commitmentTypeId CommitmentTypeIdentifier,
+ * commitmentTypeQualifier SEQUENCE SIZE (1..MAX) OF
+ * CommitmentTypeQualifier OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(commitmentTypeId);
+
+ if (commitmentTypeQualifier != null)
+ {
+ v.add(commitmentTypeQualifier);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CommitmentTypeQualifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CommitmentTypeQualifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CommitmentTypeQualifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CommitmentTypeQualifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,108 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * Commitment type qualifiers, used in the Commitment-Type-Indication attribute (RFC3126).
+ *
+ *
+ * CommitmentTypeQualifier ::= SEQUENCE {
+ * commitmentTypeIdentifier CommitmentTypeIdentifier,
+ * qualifier ANY DEFINED BY commitmentTypeIdentifier OPTIONAL }
+ *
+ */
+public class CommitmentTypeQualifier
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier commitmentTypeIdentifier;
+ private ASN1Encodable qualifier;
+
+ /**
+ * Creates a new CommitmentTypeQualifier
instance.
+ *
+ * @param commitmentTypeIdentifier a CommitmentTypeIdentifier
value
+ */
+ public CommitmentTypeQualifier(
+ ASN1ObjectIdentifier commitmentTypeIdentifier)
+ {
+ this(commitmentTypeIdentifier, null);
+ }
+
+ /**
+ * Creates a new CommitmentTypeQualifier
instance.
+ *
+ * @param commitmentTypeIdentifier a CommitmentTypeIdentifier
value
+ * @param qualifier the qualifier, defined by the above field.
+ */
+ public CommitmentTypeQualifier(
+ ASN1ObjectIdentifier commitmentTypeIdentifier,
+ ASN1Encodable qualifier)
+ {
+ this.commitmentTypeIdentifier = commitmentTypeIdentifier;
+ this.qualifier = qualifier;
+ }
+
+ /**
+ * Creates a new CommitmentTypeQualifier
instance.
+ *
+ * @param as CommitmentTypeQualifier
structure
+ * encoded as an ASN1Sequence.
+ */
+ private CommitmentTypeQualifier(
+ ASN1Sequence as)
+ {
+ commitmentTypeIdentifier = (ASN1ObjectIdentifier)as.getObjectAt(0);
+
+ if (as.size() > 1)
+ {
+ qualifier = as.getObjectAt(1);
+ }
+ }
+
+ public static CommitmentTypeQualifier getInstance(Object as)
+ {
+ if (as instanceof CommitmentTypeQualifier)
+ {
+ return (CommitmentTypeQualifier)as;
+ }
+ else if (as != null)
+ {
+ return new CommitmentTypeQualifier(ASN1Sequence.getInstance(as));
+ }
+
+ return null;
+ }
+
+ public ASN1ObjectIdentifier getCommitmentTypeIdentifier()
+ {
+ return commitmentTypeIdentifier;
+ }
+
+ public ASN1Encodable getQualifier()
+ {
+ return qualifier;
+ }
+
+ /**
+ * Returns a DER-encodable representation of this instance.
+ *
+ * @return a ASN1Primitive
value
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector dev = new ASN1EncodableVector();
+ dev.add(commitmentTypeIdentifier);
+ if (qualifier != null)
+ {
+ dev.add(qualifier);
+ }
+
+ return new DERSequence(dev);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CompleteRevocationRefs.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CompleteRevocationRefs.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CompleteRevocationRefs.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CompleteRevocationRefs.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,65 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ *
+ * CompleteRevocationRefs ::= SEQUENCE OF CrlOcspRef
+ *
+ */
+public class CompleteRevocationRefs
+ extends ASN1Object
+{
+
+ private ASN1Sequence crlOcspRefs;
+
+ public static CompleteRevocationRefs getInstance(Object obj)
+ {
+ if (obj instanceof CompleteRevocationRefs)
+ {
+ return (CompleteRevocationRefs)obj;
+ }
+ else if (obj != null)
+ {
+ return new CompleteRevocationRefs(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CompleteRevocationRefs(ASN1Sequence seq)
+ {
+ Enumeration seqEnum = seq.getObjects();
+ while (seqEnum.hasMoreElements())
+ {
+ CrlOcspRef.getInstance(seqEnum.nextElement());
+ }
+ this.crlOcspRefs = seq;
+ }
+
+ public CompleteRevocationRefs(CrlOcspRef[] crlOcspRefs)
+ {
+ this.crlOcspRefs = new DERSequence(crlOcspRefs);
+ }
+
+ public CrlOcspRef[] getCrlOcspRefs()
+ {
+ CrlOcspRef[] result = new CrlOcspRef[this.crlOcspRefs.size()];
+ for (int idx = 0; idx < result.length; idx++)
+ {
+ result[idx] = CrlOcspRef.getInstance(this.crlOcspRefs
+ .getObjectAt(idx));
+ }
+ return result;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return this.crlOcspRefs;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CrlIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CrlIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CrlIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CrlIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,106 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1UTCTime;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+
+/**
+ *
+ * CrlIdentifier ::= SEQUENCE
+ * {
+ * crlissuer Name,
+ * crlIssuedTime UTCTime,
+ * crlNumber INTEGER OPTIONAL
+ * }
+ *
+ */
+public class CrlIdentifier
+ extends ASN1Object
+{
+ private X500Name crlIssuer;
+ private ASN1UTCTime crlIssuedTime;
+ private ASN1Integer crlNumber;
+
+ public static CrlIdentifier getInstance(Object obj)
+ {
+ if (obj instanceof CrlIdentifier)
+ {
+ return (CrlIdentifier)obj;
+ }
+ else if (obj != null)
+ {
+ return new CrlIdentifier(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CrlIdentifier(ASN1Sequence seq)
+ {
+ if (seq.size() < 2 || seq.size() > 3)
+ {
+ throw new IllegalArgumentException();
+ }
+ this.crlIssuer = X500Name.getInstance(seq.getObjectAt(0));
+ this.crlIssuedTime = ASN1UTCTime.getInstance(seq.getObjectAt(1));
+ if (seq.size() > 2)
+ {
+ this.crlNumber = ASN1Integer.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public CrlIdentifier(X500Name crlIssuer, ASN1UTCTime crlIssuedTime)
+ {
+ this(crlIssuer, crlIssuedTime, null);
+ }
+
+ public CrlIdentifier(X500Name crlIssuer, ASN1UTCTime crlIssuedTime,
+ BigInteger crlNumber)
+ {
+ this.crlIssuer = crlIssuer;
+ this.crlIssuedTime = crlIssuedTime;
+ if (null != crlNumber)
+ {
+ this.crlNumber = new ASN1Integer(crlNumber);
+ }
+ }
+
+ public X500Name getCrlIssuer()
+ {
+ return this.crlIssuer;
+ }
+
+ public ASN1UTCTime getCrlIssuedTime()
+ {
+ return this.crlIssuedTime;
+ }
+
+ public BigInteger getCrlNumber()
+ {
+ if (null == this.crlNumber)
+ {
+ return null;
+ }
+ return this.crlNumber.getValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.crlIssuer.toASN1Primitive());
+ v.add(this.crlIssuedTime);
+ if (null != this.crlNumber)
+ {
+ v.add(this.crlNumber);
+ }
+ return new DERSequence(v);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CrlListID.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CrlListID.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CrlListID.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CrlListID.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,66 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ *
+ * CRLListID ::= SEQUENCE {
+ * crls SEQUENCE OF CrlValidatedID }
+ *
+ */
+public class CrlListID
+ extends ASN1Object
+{
+
+ private ASN1Sequence crls;
+
+ public static CrlListID getInstance(Object obj)
+ {
+ if (obj instanceof CrlListID)
+ {
+ return (CrlListID)obj;
+ }
+ else if (obj != null)
+ {
+ return new CrlListID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CrlListID(ASN1Sequence seq)
+ {
+ this.crls = (ASN1Sequence)seq.getObjectAt(0);
+ Enumeration e = this.crls.getObjects();
+ while (e.hasMoreElements())
+ {
+ CrlValidatedID.getInstance(e.nextElement());
+ }
+ }
+
+ public CrlListID(CrlValidatedID[] crls)
+ {
+ this.crls = new DERSequence(crls);
+ }
+
+ public CrlValidatedID[] getCrls()
+ {
+ CrlValidatedID[] result = new CrlValidatedID[this.crls.size()];
+ for (int idx = 0; idx < result.length; idx++)
+ {
+ result[idx] = CrlValidatedID
+ .getInstance(this.crls.getObjectAt(idx));
+ }
+ return result;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERSequence(this.crls);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CrlOcspRef.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CrlOcspRef.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CrlOcspRef.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CrlOcspRef.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,106 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ *
+ * CrlOcspRef ::= SEQUENCE {
+ * crlids [0] CRLListID OPTIONAL,
+ * ocspids [1] OcspListID OPTIONAL,
+ * otherRev [2] OtherRevRefs OPTIONAL
+ * }
+ *
+ */
+public class CrlOcspRef
+ extends ASN1Object
+{
+
+ private CrlListID crlids;
+ private OcspListID ocspids;
+ private OtherRevRefs otherRev;
+
+ public static CrlOcspRef getInstance(Object obj)
+ {
+ if (obj instanceof CrlOcspRef)
+ {
+ return (CrlOcspRef)obj;
+ }
+ else if (obj != null)
+ {
+ return new CrlOcspRef(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CrlOcspRef(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ while (e.hasMoreElements())
+ {
+ DERTaggedObject o = (DERTaggedObject)e.nextElement();
+ switch (o.getTagNo())
+ {
+ case 0:
+ this.crlids = CrlListID.getInstance(o.getObject());
+ break;
+ case 1:
+ this.ocspids = OcspListID.getInstance(o.getObject());
+ break;
+ case 2:
+ this.otherRev = OtherRevRefs.getInstance(o.getObject());
+ break;
+ default:
+ throw new IllegalArgumentException("illegal tag");
+ }
+ }
+ }
+
+ public CrlOcspRef(CrlListID crlids, OcspListID ocspids,
+ OtherRevRefs otherRev)
+ {
+ this.crlids = crlids;
+ this.ocspids = ocspids;
+ this.otherRev = otherRev;
+ }
+
+ public CrlListID getCrlids()
+ {
+ return this.crlids;
+ }
+
+ public OcspListID getOcspids()
+ {
+ return this.ocspids;
+ }
+
+ public OtherRevRefs getOtherRev()
+ {
+ return this.otherRev;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ if (null != this.crlids)
+ {
+ v.add(new DERTaggedObject(true, 0, this.crlids.toASN1Primitive()));
+ }
+ if (null != this.ocspids)
+ {
+ v.add(new DERTaggedObject(true, 1, this.ocspids.toASN1Primitive()));
+ }
+ if (null != this.otherRev)
+ {
+ v.add(new DERTaggedObject(true, 2, this.otherRev.toASN1Primitive()));
+ }
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CrlValidatedID.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CrlValidatedID.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/CrlValidatedID.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/CrlValidatedID.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,82 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ *
+ * CrlValidatedID ::= SEQUENCE {
+ * crlHash OtherHash,
+ * crlIdentifier CrlIdentifier OPTIONAL }
+ *
+ */
+public class CrlValidatedID
+ extends ASN1Object
+{
+
+ private OtherHash crlHash;
+ private CrlIdentifier crlIdentifier;
+
+ public static CrlValidatedID getInstance(Object obj)
+ {
+ if (obj instanceof CrlValidatedID)
+ {
+ return (CrlValidatedID)obj;
+ }
+ else if (obj != null)
+ {
+ return new CrlValidatedID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CrlValidatedID(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.crlHash = OtherHash.getInstance(seq.getObjectAt(0));
+ if (seq.size() > 1)
+ {
+ this.crlIdentifier = CrlIdentifier.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public CrlValidatedID(OtherHash crlHash)
+ {
+ this(crlHash, null);
+ }
+
+ public CrlValidatedID(OtherHash crlHash, CrlIdentifier crlIdentifier)
+ {
+ this.crlHash = crlHash;
+ this.crlIdentifier = crlIdentifier;
+ }
+
+ public OtherHash getCrlHash()
+ {
+ return this.crlHash;
+ }
+
+ public CrlIdentifier getCrlIdentifier()
+ {
+ return this.crlIdentifier;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.crlHash.toASN1Primitive());
+ if (null != this.crlIdentifier)
+ {
+ v.add(this.crlIdentifier.toASN1Primitive());
+ }
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/ESFAttributes.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/ESFAttributes.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/ESFAttributes.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/ESFAttributes.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,22 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+public interface ESFAttributes
+{
+ public static final ASN1ObjectIdentifier sigPolicyId = PKCSObjectIdentifiers.id_aa_ets_sigPolicyId;
+ public static final ASN1ObjectIdentifier commitmentType = PKCSObjectIdentifiers.id_aa_ets_commitmentType;
+ public static final ASN1ObjectIdentifier signerLocation = PKCSObjectIdentifiers.id_aa_ets_signerLocation;
+ public static final ASN1ObjectIdentifier signerAttr = PKCSObjectIdentifiers.id_aa_ets_signerAttr;
+ public static final ASN1ObjectIdentifier otherSigCert = PKCSObjectIdentifiers.id_aa_ets_otherSigCert;
+ public static final ASN1ObjectIdentifier contentTimestamp = PKCSObjectIdentifiers.id_aa_ets_contentTimestamp;
+ public static final ASN1ObjectIdentifier certificateRefs = PKCSObjectIdentifiers.id_aa_ets_certificateRefs;
+ public static final ASN1ObjectIdentifier revocationRefs = PKCSObjectIdentifiers.id_aa_ets_revocationRefs;
+ public static final ASN1ObjectIdentifier certValues = PKCSObjectIdentifiers.id_aa_ets_certValues;
+ public static final ASN1ObjectIdentifier revocationValues = PKCSObjectIdentifiers.id_aa_ets_revocationValues;
+ public static final ASN1ObjectIdentifier escTimeStamp = PKCSObjectIdentifiers.id_aa_ets_escTimeStamp;
+ public static final ASN1ObjectIdentifier certCRLTimestamp = PKCSObjectIdentifiers.id_aa_ets_certCRLTimestamp;
+ public static final ASN1ObjectIdentifier archiveTimestamp = PKCSObjectIdentifiers.id_aa_ets_archiveTimestamp;
+ public static final ASN1ObjectIdentifier archiveTimestampV2 = PKCSObjectIdentifiers.id_aa.branch("48");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OcspIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OcspIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OcspIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OcspIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,73 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.ocsp.ResponderID;
+
+/**
+ *
+ * OcspIdentifier ::= SEQUENCE {
+ * ocspResponderID ResponderID, -- As in OCSP response data
+ * producedAt GeneralizedTime -- As in OCSP response data
+ * }
+ *
+ */
+public class OcspIdentifier
+ extends ASN1Object
+{
+ private ResponderID ocspResponderID;
+ private ASN1GeneralizedTime producedAt;
+
+ public static OcspIdentifier getInstance(Object obj)
+ {
+ if (obj instanceof OcspIdentifier)
+ {
+ return (OcspIdentifier)obj;
+ }
+ else if (obj != null)
+ {
+ return new OcspIdentifier(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private OcspIdentifier(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.ocspResponderID = ResponderID.getInstance(seq.getObjectAt(0));
+ this.producedAt = (ASN1GeneralizedTime)seq.getObjectAt(1);
+ }
+
+ public OcspIdentifier(ResponderID ocspResponderID, ASN1GeneralizedTime producedAt)
+ {
+ this.ocspResponderID = ocspResponderID;
+ this.producedAt = producedAt;
+ }
+
+ public ResponderID getOcspResponderID()
+ {
+ return this.ocspResponderID;
+ }
+
+ public ASN1GeneralizedTime getProducedAt()
+ {
+ return this.producedAt;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.ocspResponderID);
+ v.add(this.producedAt);
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OcspListID.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OcspListID.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OcspListID.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OcspListID.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,72 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ *
+ * OcspListID ::= SEQUENCE {
+ * ocspResponses SEQUENCE OF OcspResponsesID
+ * }
+ *
+ */
+public class OcspListID
+ extends ASN1Object
+{
+ private ASN1Sequence ocspResponses;
+
+ public static OcspListID getInstance(Object obj)
+ {
+ if (obj instanceof OcspListID)
+ {
+ return (OcspListID)obj;
+ }
+ else if (obj != null)
+ {
+ return new OcspListID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private OcspListID(ASN1Sequence seq)
+ {
+ if (seq.size() != 1)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.ocspResponses = (ASN1Sequence)seq.getObjectAt(0);
+ Enumeration e = this.ocspResponses.getObjects();
+ while (e.hasMoreElements())
+ {
+ OcspResponsesID.getInstance(e.nextElement());
+ }
+ }
+
+ public OcspListID(OcspResponsesID[] ocspResponses)
+ {
+ this.ocspResponses = new DERSequence(ocspResponses);
+ }
+
+ public OcspResponsesID[] getOcspResponses()
+ {
+ OcspResponsesID[] result = new OcspResponsesID[this.ocspResponses
+ .size()];
+ for (int idx = 0; idx < result.length; idx++)
+ {
+ result[idx] = OcspResponsesID.getInstance(this.ocspResponses
+ .getObjectAt(idx));
+ }
+ return result;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERSequence(this.ocspResponses);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OcspResponsesID.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OcspResponsesID.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OcspResponsesID.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OcspResponsesID.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,83 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ *
+ * OcspResponsesID ::= SEQUENCE {
+ * ocspIdentifier OcspIdentifier,
+ * ocspRepHash OtherHash OPTIONAL
+ * }
+ *
+ */
+public class OcspResponsesID
+ extends ASN1Object
+{
+
+ private OcspIdentifier ocspIdentifier;
+ private OtherHash ocspRepHash;
+
+ public static OcspResponsesID getInstance(Object obj)
+ {
+ if (obj instanceof OcspResponsesID)
+ {
+ return (OcspResponsesID)obj;
+ }
+ else if (obj != null)
+ {
+ return new OcspResponsesID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private OcspResponsesID(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.ocspIdentifier = OcspIdentifier.getInstance(seq.getObjectAt(0));
+ if (seq.size() > 1)
+ {
+ this.ocspRepHash = OtherHash.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public OcspResponsesID(OcspIdentifier ocspIdentifier)
+ {
+ this(ocspIdentifier, null);
+ }
+
+ public OcspResponsesID(OcspIdentifier ocspIdentifier, OtherHash ocspRepHash)
+ {
+ this.ocspIdentifier = ocspIdentifier;
+ this.ocspRepHash = ocspRepHash;
+ }
+
+ public OcspIdentifier getOcspIdentifier()
+ {
+ return this.ocspIdentifier;
+ }
+
+ public OtherHash getOcspRepHash()
+ {
+ return this.ocspRepHash;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.ocspIdentifier);
+ if (null != this.ocspRepHash)
+ {
+ v.add(this.ocspRepHash);
+ }
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OtherHash.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OtherHash.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OtherHash.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OtherHash.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,81 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ *
+ * OtherHash ::= CHOICE {
+ * sha1Hash OtherHashValue, -- This contains a SHA-1 hash
+ * otherHash OtherHashAlgAndValue
+ * }
+ *
+ */
+public class OtherHash
+ extends ASN1Object
+ implements ASN1Choice
+{
+
+ private ASN1OctetString sha1Hash;
+ private OtherHashAlgAndValue otherHash;
+
+ public static OtherHash getInstance(Object obj)
+ {
+ if (obj instanceof OtherHash)
+ {
+ return (OtherHash)obj;
+ }
+ if (obj instanceof ASN1OctetString)
+ {
+ return new OtherHash((ASN1OctetString)obj);
+ }
+ return new OtherHash(OtherHashAlgAndValue.getInstance(obj));
+ }
+
+ private OtherHash(ASN1OctetString sha1Hash)
+ {
+ this.sha1Hash = sha1Hash;
+ }
+
+ public OtherHash(OtherHashAlgAndValue otherHash)
+ {
+ this.otherHash = otherHash;
+ }
+
+ public OtherHash(byte[] sha1Hash)
+ {
+ this.sha1Hash = new DEROctetString(sha1Hash);
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ if (null == this.otherHash)
+ {
+ return new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1);
+ }
+ return this.otherHash.getHashAlgorithm();
+ }
+
+ public byte[] getHashValue()
+ {
+ if (null == this.otherHash)
+ {
+ return this.sha1Hash.getOctets();
+ }
+ return this.otherHash.getHashValue().getOctets();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (null == this.otherHash)
+ {
+ return this.sha1Hash;
+ }
+ return this.otherHash.toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OtherHashAlgAndValue.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OtherHashAlgAndValue.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OtherHashAlgAndValue.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OtherHashAlgAndValue.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,81 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class OtherHashAlgAndValue
+ extends ASN1Object
+{
+ private AlgorithmIdentifier hashAlgorithm;
+ private ASN1OctetString hashValue;
+
+
+ public static OtherHashAlgAndValue getInstance(
+ Object obj)
+ {
+ if (obj instanceof OtherHashAlgAndValue)
+ {
+ return (OtherHashAlgAndValue) obj;
+ }
+ else if (obj != null)
+ {
+ return new OtherHashAlgAndValue(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private OtherHashAlgAndValue(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ hashValue = ASN1OctetString.getInstance(seq.getObjectAt(1));
+ }
+
+ public OtherHashAlgAndValue(
+ AlgorithmIdentifier hashAlgorithm,
+ ASN1OctetString hashValue)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.hashValue = hashValue;
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public ASN1OctetString getHashValue()
+ {
+ return hashValue;
+ }
+
+ /**
+ *
+ * OtherHashAlgAndValue ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * hashValue OtherHashValue }
+ *
+ * OtherHashValue ::= OCTET STRING
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(hashAlgorithm);
+ v.add(hashValue);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OtherRevRefs.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OtherRevRefs.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OtherRevRefs.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OtherRevRefs.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,87 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Encoding;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ *
+ * OtherRevRefs ::= SEQUENCE {
+ * otherRevRefType OtherRevRefType,
+ * otherRevRefs ANY DEFINED BY otherRevRefType
+ * }
+ *
+ * OtherRevRefType ::= OBJECT IDENTIFIER
+ *
+ */
+public class OtherRevRefs
+ extends ASN1Object
+{
+
+ private ASN1ObjectIdentifier otherRevRefType;
+ private ASN1Encodable otherRevRefs;
+
+ public static OtherRevRefs getInstance(Object obj)
+ {
+ if (obj instanceof OtherRevRefs)
+ {
+ return (OtherRevRefs)obj;
+ }
+ else if (obj != null)
+ {
+ return new OtherRevRefs(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private OtherRevRefs(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.otherRevRefType = new ASN1ObjectIdentifier(((ASN1ObjectIdentifier)seq.getObjectAt(0)).getId());
+ try
+ {
+ this.otherRevRefs = ASN1Primitive.fromByteArray(seq.getObjectAt(1)
+ .toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException();
+ }
+ }
+
+ public OtherRevRefs(ASN1ObjectIdentifier otherRevRefType, ASN1Encodable otherRevRefs)
+ {
+ this.otherRevRefType = otherRevRefType;
+ this.otherRevRefs = otherRevRefs;
+ }
+
+ public ASN1ObjectIdentifier getOtherRevRefType()
+ {
+ return this.otherRevRefType;
+ }
+
+ public ASN1Encodable getOtherRevRefs()
+ {
+ return this.otherRevRefs;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.otherRevRefType);
+ v.add(this.otherRevRefs);
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OtherRevVals.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OtherRevVals.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/OtherRevVals.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/OtherRevVals.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,89 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Encoding;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ *
+ * OtherRevVals ::= SEQUENCE {
+ * otherRevValType OtherRevValType,
+ * otherRevVals ANY DEFINED BY OtherRevValType
+ * }
+ *
+ * OtherRevValType ::= OBJECT IDENTIFIER
+ *
+ */
+public class OtherRevVals
+ extends ASN1Object
+{
+
+ private ASN1ObjectIdentifier otherRevValType;
+
+ private ASN1Encodable otherRevVals;
+
+ public static OtherRevVals getInstance(Object obj)
+ {
+ if (obj instanceof OtherRevVals)
+ {
+ return (OtherRevVals)obj;
+ }
+ if (obj != null)
+ {
+ return new OtherRevVals(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private OtherRevVals(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.otherRevValType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ try
+ {
+ this.otherRevVals = ASN1Primitive.fromByteArray(seq.getObjectAt(1)
+ .toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException();
+ }
+ }
+
+ public OtherRevVals(ASN1ObjectIdentifier otherRevValType,
+ ASN1Encodable otherRevVals)
+ {
+ this.otherRevValType = otherRevValType;
+ this.otherRevVals = otherRevVals;
+ }
+
+ public ASN1ObjectIdentifier getOtherRevValType()
+ {
+ return this.otherRevValType;
+ }
+
+ public ASN1Encodable getOtherRevVals()
+ {
+ return this.otherRevVals;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.otherRevValType);
+ v.add(this.otherRevVals);
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/RevocationValues.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/RevocationValues.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/RevocationValues.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/RevocationValues.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,151 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.ocsp.BasicOCSPResponse;
+import pdftk.org.bouncycastle.asn1.x509.CertificateList;
+
+/**
+ *
+ * RevocationValues ::= SEQUENCE {
+ * crlVals [0] SEQUENCE OF CertificateList OPTIONAL,
+ * ocspVals [1] SEQUENCE OF BasicOCSPResponse OPTIONAL,
+ * otherRevVals [2] OtherRevVals OPTIONAL}
+ *
+ */
+public class RevocationValues
+ extends ASN1Object
+{
+
+ private ASN1Sequence crlVals;
+ private ASN1Sequence ocspVals;
+ private OtherRevVals otherRevVals;
+
+ public static RevocationValues getInstance(Object obj)
+ {
+ if (obj instanceof RevocationValues)
+ {
+ return (RevocationValues)obj;
+ }
+ else if (obj != null)
+ {
+ return new RevocationValues(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private RevocationValues(ASN1Sequence seq)
+ {
+ if (seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ Enumeration e = seq.getObjects();
+ while (e.hasMoreElements())
+ {
+ DERTaggedObject o = (DERTaggedObject)e.nextElement();
+ switch (o.getTagNo())
+ {
+ case 0:
+ ASN1Sequence crlValsSeq = (ASN1Sequence)o.getObject();
+ Enumeration crlValsEnum = crlValsSeq.getObjects();
+ while (crlValsEnum.hasMoreElements())
+ {
+ CertificateList.getInstance(crlValsEnum.nextElement());
+ }
+ this.crlVals = crlValsSeq;
+ break;
+ case 1:
+ ASN1Sequence ocspValsSeq = (ASN1Sequence)o.getObject();
+ Enumeration ocspValsEnum = ocspValsSeq.getObjects();
+ while (ocspValsEnum.hasMoreElements())
+ {
+ BasicOCSPResponse.getInstance(ocspValsEnum.nextElement());
+ }
+ this.ocspVals = ocspValsSeq;
+ break;
+ case 2:
+ this.otherRevVals = OtherRevVals.getInstance(o.getObject());
+ break;
+ default:
+ throw new IllegalArgumentException("invalid tag: "
+ + o.getTagNo());
+ }
+ }
+ }
+
+ public RevocationValues(CertificateList[] crlVals,
+ BasicOCSPResponse[] ocspVals, OtherRevVals otherRevVals)
+ {
+ if (null != crlVals)
+ {
+ this.crlVals = new DERSequence(crlVals);
+ }
+ if (null != ocspVals)
+ {
+ this.ocspVals = new DERSequence(ocspVals);
+ }
+ this.otherRevVals = otherRevVals;
+ }
+
+ public CertificateList[] getCrlVals()
+ {
+ if (null == this.crlVals)
+ {
+ return new CertificateList[0];
+ }
+ CertificateList[] result = new CertificateList[this.crlVals.size()];
+ for (int idx = 0; idx < result.length; idx++)
+ {
+ result[idx] = CertificateList.getInstance(this.crlVals
+ .getObjectAt(idx));
+ }
+ return result;
+ }
+
+ public BasicOCSPResponse[] getOcspVals()
+ {
+ if (null == this.ocspVals)
+ {
+ return new BasicOCSPResponse[0];
+ }
+ BasicOCSPResponse[] result = new BasicOCSPResponse[this.ocspVals.size()];
+ for (int idx = 0; idx < result.length; idx++)
+ {
+ result[idx] = BasicOCSPResponse.getInstance(this.ocspVals
+ .getObjectAt(idx));
+ }
+ return result;
+ }
+
+ public OtherRevVals getOtherRevVals()
+ {
+ return this.otherRevVals;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ if (null != this.crlVals)
+ {
+ v.add(new DERTaggedObject(true, 0, this.crlVals));
+ }
+ if (null != this.ocspVals)
+ {
+ v.add(new DERTaggedObject(true, 1, this.ocspVals));
+ }
+ if (null != this.otherRevVals)
+ {
+ v.add(new DERTaggedObject(true, 2, this.otherRevVals.toASN1Primitive()));
+ }
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SPUserNotice.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SPUserNotice.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SPUserNotice.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SPUserNotice.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,99 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1String;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.DisplayText;
+import pdftk.org.bouncycastle.asn1.x509.NoticeReference;
+
+public class SPUserNotice
+ extends ASN1Object
+{
+ private NoticeReference noticeRef;
+ private DisplayText explicitText;
+
+ public static SPUserNotice getInstance(
+ Object obj)
+ {
+ if (obj instanceof SPUserNotice)
+ {
+ return (SPUserNotice)obj;
+ }
+ else if (obj != null)
+ {
+ return new SPUserNotice(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private SPUserNotice(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ while (e.hasMoreElements())
+ {
+ ASN1Encodable object = (ASN1Encodable)e.nextElement();
+ if (object instanceof DisplayText || object instanceof ASN1String)
+ {
+ explicitText = DisplayText.getInstance(object);
+ }
+ else if (object instanceof NoticeReference || object instanceof ASN1Sequence)
+ {
+ noticeRef = NoticeReference.getInstance(object);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Invalid element in 'SPUserNotice': " + object.getClass().getName());
+ }
+ }
+ }
+
+ public SPUserNotice(
+ NoticeReference noticeRef,
+ DisplayText explicitText)
+ {
+ this.noticeRef = noticeRef;
+ this.explicitText = explicitText;
+ }
+
+ public NoticeReference getNoticeRef()
+ {
+ return noticeRef;
+ }
+
+ public DisplayText getExplicitText()
+ {
+ return explicitText;
+ }
+
+ /**
+ *
+ * SPUserNotice ::= SEQUENCE {
+ * noticeRef NoticeReference OPTIONAL,
+ * explicitText DisplayText OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (noticeRef != null)
+ {
+ v.add(noticeRef);
+ }
+
+ if (explicitText != null)
+ {
+ v.add(explicitText);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SPuri.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SPuri.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SPuri.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SPuri.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,45 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+
+public class SPuri
+{
+ private DERIA5String uri;
+
+ public static SPuri getInstance(
+ Object obj)
+ {
+ if (obj instanceof SPuri)
+ {
+ return (SPuri) obj;
+ }
+ else if (obj instanceof DERIA5String)
+ {
+ return new SPuri(DERIA5String.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public SPuri(
+ DERIA5String uri)
+ {
+ this.uri = uri;
+ }
+
+ public DERIA5String getUri()
+ {
+ return uri;
+ }
+
+ /**
+ *
+ * SPuri ::= IA5String
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return uri.toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SigPolicyQualifierInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SigPolicyQualifierInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SigPolicyQualifierInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SigPolicyQualifierInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,75 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class SigPolicyQualifierInfo
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier sigPolicyQualifierId;
+ private ASN1Encodable sigQualifier;
+
+ public SigPolicyQualifierInfo(
+ ASN1ObjectIdentifier sigPolicyQualifierId,
+ ASN1Encodable sigQualifier)
+ {
+ this.sigPolicyQualifierId = sigPolicyQualifierId;
+ this.sigQualifier = sigQualifier;
+ }
+
+ private SigPolicyQualifierInfo(
+ ASN1Sequence seq)
+ {
+ sigPolicyQualifierId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ sigQualifier = seq.getObjectAt(1);
+ }
+
+ public static SigPolicyQualifierInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof SigPolicyQualifierInfo)
+ {
+ return (SigPolicyQualifierInfo) obj;
+ }
+ else if (obj != null)
+ {
+ return new SigPolicyQualifierInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1ObjectIdentifier getSigPolicyQualifierId()
+ {
+ return new ASN1ObjectIdentifier(sigPolicyQualifierId.getId());
+ }
+
+ public ASN1Encodable getSigQualifier()
+ {
+ return sigQualifier;
+ }
+
+ /**
+ *
+ * SigPolicyQualifierInfo ::= SEQUENCE {
+ * sigPolicyQualifierId SigPolicyQualifierId,
+ * sigQualifier ANY DEFINED BY sigPolicyQualifierId }
+ *
+ * SigPolicyQualifierId ::= OBJECT IDENTIFIER
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(sigPolicyQualifierId);
+ v.add(sigQualifier);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SigPolicyQualifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SigPolicyQualifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SigPolicyQualifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SigPolicyQualifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,77 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class SigPolicyQualifiers
+ extends ASN1Object
+{
+ ASN1Sequence qualifiers;
+
+ public static SigPolicyQualifiers getInstance(
+ Object obj)
+ {
+ if (obj instanceof SigPolicyQualifiers)
+ {
+ return (SigPolicyQualifiers) obj;
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new SigPolicyQualifiers(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private SigPolicyQualifiers(
+ ASN1Sequence seq)
+ {
+ qualifiers = seq;
+ }
+
+ public SigPolicyQualifiers(
+ SigPolicyQualifierInfo[] qualifierInfos)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i=0; i < qualifierInfos.length; i++)
+ {
+ v.add(qualifierInfos[i]);
+ }
+ qualifiers = new DERSequence(v);
+ }
+
+ /**
+ * Return the number of qualifier info elements present.
+ *
+ * @return number of elements present.
+ */
+ public int size()
+ {
+ return qualifiers.size();
+ }
+
+ /**
+ * Return the SigPolicyQualifierInfo at index i.
+ *
+ * @param i index of the info of interest
+ * @return the info at index i.
+ */
+ public SigPolicyQualifierInfo getInfoAt(
+ int i)
+ {
+ return SigPolicyQualifierInfo.getInstance(qualifiers.getObjectAt(i));
+ }
+
+ /**
+ *
+ * SigPolicyQualifiers ::= SEQUENCE SIZE (1..MAX) OF SigPolicyQualifierInfo
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return qualifiers;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SignaturePolicyId.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SignaturePolicyId.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SignaturePolicyId.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SignaturePolicyId.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,103 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class SignaturePolicyId
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier sigPolicyId;
+ private OtherHashAlgAndValue sigPolicyHash;
+ private SigPolicyQualifiers sigPolicyQualifiers;
+
+
+ public static SignaturePolicyId getInstance(
+ Object obj)
+ {
+ if (obj instanceof SignaturePolicyId)
+ {
+ return (SignaturePolicyId)obj;
+ }
+ else if (obj != null)
+ {
+ return new SignaturePolicyId(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private SignaturePolicyId(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2 && seq.size() != 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ sigPolicyId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ sigPolicyHash = OtherHashAlgAndValue.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() == 3)
+ {
+ sigPolicyQualifiers = SigPolicyQualifiers.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public SignaturePolicyId(
+ ASN1ObjectIdentifier sigPolicyIdentifier,
+ OtherHashAlgAndValue sigPolicyHash)
+ {
+ this(sigPolicyIdentifier, sigPolicyHash, null);
+ }
+
+ public SignaturePolicyId(
+ ASN1ObjectIdentifier sigPolicyId,
+ OtherHashAlgAndValue sigPolicyHash,
+ SigPolicyQualifiers sigPolicyQualifiers)
+ {
+ this.sigPolicyId = sigPolicyId;
+ this.sigPolicyHash = sigPolicyHash;
+ this.sigPolicyQualifiers = sigPolicyQualifiers;
+ }
+
+ public ASN1ObjectIdentifier getSigPolicyId()
+ {
+ return new ASN1ObjectIdentifier(sigPolicyId.getId());
+ }
+
+ public OtherHashAlgAndValue getSigPolicyHash()
+ {
+ return sigPolicyHash;
+ }
+
+ public SigPolicyQualifiers getSigPolicyQualifiers()
+ {
+ return sigPolicyQualifiers;
+ }
+
+ /**
+ *
+ * SignaturePolicyId ::= SEQUENCE {
+ * sigPolicyId SigPolicyId,
+ * sigPolicyHash SigPolicyHash,
+ * sigPolicyQualifiers SEQUENCE SIZE (1..MAX) OF SigPolicyQualifierInfo OPTIONAL}
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(sigPolicyId);
+ v.add(sigPolicyHash);
+ if (sigPolicyQualifiers != null)
+ {
+ v.add(sigPolicyQualifiers);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SignaturePolicyIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SignaturePolicyIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SignaturePolicyIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SignaturePolicyIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,76 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import pdftk.org.bouncycastle.asn1.ASN1Null;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.BERTags;
+import pdftk.org.bouncycastle.asn1.DERNull;
+
+public class SignaturePolicyIdentifier
+ extends ASN1Object
+{
+ private SignaturePolicyId signaturePolicyId;
+ private boolean isSignaturePolicyImplied;
+
+ public static SignaturePolicyIdentifier getInstance(
+ Object obj)
+ {
+ if (obj instanceof SignaturePolicyIdentifier)
+ {
+ return (SignaturePolicyIdentifier)obj;
+ }
+ else if (obj instanceof ASN1Null || hasEncodedTagValue(obj, BERTags.NULL))
+ {
+ return new SignaturePolicyIdentifier();
+ }
+ else if (obj != null)
+ {
+ return new SignaturePolicyIdentifier(SignaturePolicyId.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public SignaturePolicyIdentifier()
+ {
+ this.isSignaturePolicyImplied = true;
+ }
+
+ public SignaturePolicyIdentifier(
+ SignaturePolicyId signaturePolicyId)
+ {
+ this.signaturePolicyId = signaturePolicyId;
+ this.isSignaturePolicyImplied = false;
+ }
+
+ public SignaturePolicyId getSignaturePolicyId()
+ {
+ return signaturePolicyId;
+ }
+
+ public boolean isSignaturePolicyImplied()
+ {
+ return isSignaturePolicyImplied;
+ }
+
+ /**
+ *
+ * SignaturePolicyIdentifier ::= CHOICE{
+ * SignaturePolicyId SignaturePolicyId,
+ * SignaturePolicyImplied SignaturePolicyImplied }
+ *
+ * SignaturePolicyImplied ::= NULL
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (isSignaturePolicyImplied)
+ {
+ return DERNull.INSTANCE;
+ }
+ else
+ {
+ return signaturePolicyId.toASN1Primitive();
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SignerAttribute.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SignerAttribute.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SignerAttribute.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SignerAttribute.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,123 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.Attribute;
+import pdftk.org.bouncycastle.asn1.x509.AttributeCertificate;
+
+
+public class SignerAttribute
+ extends ASN1Object
+{
+ private Object[] values;
+
+ public static SignerAttribute getInstance(
+ Object o)
+ {
+ if (o instanceof SignerAttribute)
+ {
+ return (SignerAttribute) o;
+ }
+ else if (o != null)
+ {
+ return new SignerAttribute(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private SignerAttribute(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+ values = new Object[seq.size()];
+
+ for (Enumeration e = seq.getObjects(); e.hasMoreElements();)
+ {
+ ASN1TaggedObject taggedObject = ASN1TaggedObject.getInstance(e.nextElement());
+
+ if (taggedObject.getTagNo() == 0)
+ {
+ ASN1Sequence attrs = ASN1Sequence.getInstance(taggedObject, true);
+ Attribute[] attributes = new Attribute[attrs.size()];
+
+ for (int i = 0; i != attributes.length; i++)
+ {
+ attributes[i] = Attribute.getInstance(attrs.getObjectAt(i));
+ }
+ values[index] = attributes;
+ }
+ else if (taggedObject.getTagNo() == 1)
+ {
+ values[index] = AttributeCertificate.getInstance(ASN1Sequence.getInstance(taggedObject, true));
+ }
+ else
+ {
+ throw new IllegalArgumentException("illegal tag: " + taggedObject.getTagNo());
+ }
+ index++;
+ }
+ }
+
+ public SignerAttribute(
+ Attribute[] claimedAttributes)
+ {
+ this.values = new Object[1];
+ this.values[0] = claimedAttributes;
+ }
+
+ public SignerAttribute(
+ AttributeCertificate certifiedAttributes)
+ {
+ this.values = new Object[1];
+ this.values[0] = certifiedAttributes;
+ }
+
+ /**
+ * Return the sequence of choices - the array elements will either be of
+ * type Attribute[] or AttributeCertificate depending on what tag was used.
+ *
+ * @return array of choices.
+ */
+ public Object[] getValues()
+ {
+ return values;
+ }
+
+ /**
+ *
+ *
+ * SignerAttribute ::= SEQUENCE OF CHOICE {
+ * claimedAttributes [0] ClaimedAttributes,
+ * certifiedAttributes [1] CertifiedAttributes }
+ *
+ * ClaimedAttributes ::= SEQUENCE OF Attribute
+ * CertifiedAttributes ::= AttributeCertificate -- as defined in RFC 3281: see clause 4.1.
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != values.length; i++)
+ {
+ if (values[i] instanceof Attribute[])
+ {
+ v.add(new DERTaggedObject(0, new DERSequence((Attribute[])values[i])));
+ }
+ else
+ {
+ v.add(new DERTaggedObject(1, (AttributeCertificate)values[i]));
+ }
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SignerLocation.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SignerLocation.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/SignerLocation.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/SignerLocation.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,162 @@
+package pdftk.org.bouncycastle.asn1.esf;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.DERUTF8String;
+import pdftk.org.bouncycastle.asn1.x500.DirectoryString;
+
+/**
+ * Signer-Location attribute (RFC3126).
+ *
+ *
+ * SignerLocation ::= SEQUENCE {
+ * countryName [0] DirectoryString OPTIONAL,
+ * localityName [1] DirectoryString OPTIONAL,
+ * postalAddress [2] PostalAddress OPTIONAL }
+ *
+ * PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+ *
+ */
+public class SignerLocation
+ extends ASN1Object
+{
+ private DERUTF8String countryName;
+ private DERUTF8String localityName;
+ private ASN1Sequence postalAddress;
+
+ private SignerLocation(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ DERTaggedObject o = (DERTaggedObject)e.nextElement();
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ DirectoryString countryNameDirectoryString = DirectoryString.getInstance(o, true);
+ this.countryName = new DERUTF8String(countryNameDirectoryString.getString());
+ break;
+ case 1:
+ DirectoryString localityNameDirectoryString = DirectoryString.getInstance(o, true);
+ this.localityName = new DERUTF8String(localityNameDirectoryString.getString());
+ break;
+ case 2:
+ if (o.isExplicit())
+ {
+ this.postalAddress = ASN1Sequence.getInstance(o, true);
+ }
+ else // handle erroneous implicitly tagged sequences
+ {
+ this.postalAddress = ASN1Sequence.getInstance(o, false);
+ }
+ if (postalAddress != null && postalAddress.size() > 6)
+ {
+ throw new IllegalArgumentException("postal address must contain less than 6 strings");
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("illegal tag");
+ }
+ }
+ }
+
+ public SignerLocation(
+ DERUTF8String countryName,
+ DERUTF8String localityName,
+ ASN1Sequence postalAddress)
+ {
+ if (postalAddress != null && postalAddress.size() > 6)
+ {
+ throw new IllegalArgumentException("postal address must contain less than 6 strings");
+ }
+
+ if (countryName != null)
+ {
+ this.countryName = DERUTF8String.getInstance(countryName.toASN1Primitive());
+ }
+
+ if (localityName != null)
+ {
+ this.localityName = DERUTF8String.getInstance(localityName.toASN1Primitive());
+ }
+
+ if (postalAddress != null)
+ {
+ this.postalAddress = ASN1Sequence.getInstance(postalAddress.toASN1Primitive());
+ }
+ }
+
+ public static SignerLocation getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof SignerLocation)
+ {
+ return (SignerLocation)obj;
+ }
+
+ return new SignerLocation(ASN1Sequence.getInstance(obj));
+ }
+
+ public DERUTF8String getCountryName()
+ {
+ return countryName;
+ }
+
+ public DERUTF8String getLocalityName()
+ {
+ return localityName;
+ }
+
+ public ASN1Sequence getPostalAddress()
+ {
+ return postalAddress;
+ }
+
+ /**
+ *
+ * SignerLocation ::= SEQUENCE {
+ * countryName [0] DirectoryString OPTIONAL,
+ * localityName [1] DirectoryString OPTIONAL,
+ * postalAddress [2] PostalAddress OPTIONAL }
+ *
+ * PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+ *
+ * DirectoryString ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..MAX)),
+ * printableString PrintableString (SIZE (1..MAX)),
+ * universalString UniversalString (SIZE (1..MAX)),
+ * utf8String UTF8String (SIZE (1.. MAX)),
+ * bmpString BMPString (SIZE (1..MAX)) }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (countryName != null)
+ {
+ v.add(new DERTaggedObject(true, 0, countryName));
+ }
+
+ if (localityName != null)
+ {
+ v.add(new DERTaggedObject(true, 1, localityName));
+ }
+
+ if (postalAddress != null)
+ {
+ v.add(new DERTaggedObject(true, 2, postalAddress));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/esf/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/esf/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,6 @@
+
+
+Support classes useful for encoding and supporting [ESF] RFC3126
+Electronic Signature Formats for long term electronic signatures.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/ContentHints.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/ContentHints.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/ContentHints.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/ContentHints.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,114 @@
+package pdftk.org.bouncycastle.asn1.ess;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERUTF8String;
+
+public class ContentHints
+ extends ASN1Object
+{
+ private DERUTF8String contentDescription;
+ private ASN1ObjectIdentifier contentType;
+
+ public static ContentHints getInstance(Object o)
+ {
+ if (o instanceof ContentHints)
+ {
+ return (ContentHints)o;
+ }
+ else if (o != null)
+ {
+ return new ContentHints(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * constructor
+ */
+ private ContentHints(ASN1Sequence seq)
+ {
+ ASN1Encodable field = seq.getObjectAt(0);
+ if (field.toASN1Primitive() instanceof DERUTF8String)
+ {
+ contentDescription = DERUTF8String.getInstance(field);
+ contentType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(1));
+ }
+ else
+ {
+ contentType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ }
+ }
+
+ /**
+ * @deprecated use ASN1ObjectIdentifier
+ */
+ public ContentHints(
+ DERObjectIdentifier contentType)
+ {
+ this(new ASN1ObjectIdentifier(contentType.getId()));
+ }
+
+ /**
+ * @deprecated use ASN1ObjectIdentifier
+ */
+ public ContentHints(
+ DERObjectIdentifier contentType,
+ DERUTF8String contentDescription)
+ {
+ this(new ASN1ObjectIdentifier(contentType.getId()), contentDescription);
+ }
+
+ public ContentHints(
+ ASN1ObjectIdentifier contentType)
+ {
+ this.contentType = contentType;
+ this.contentDescription = null;
+ }
+
+ public ContentHints(
+ ASN1ObjectIdentifier contentType,
+ DERUTF8String contentDescription)
+ {
+ this.contentType = contentType;
+ this.contentDescription = contentDescription;
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return contentType;
+ }
+
+ public DERUTF8String getContentDescription()
+ {
+ return contentDescription;
+ }
+
+ /**
+ *
+ * ContentHints ::= SEQUENCE {
+ * contentDescription UTF8String (SIZE (1..MAX)) OPTIONAL,
+ * contentType ContentType }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (contentDescription != null)
+ {
+ v.add(contentDescription);
+ }
+
+ v.add(contentType);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/ContentIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/ContentIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/ContentIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/ContentIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,63 @@
+package pdftk.org.bouncycastle.asn1.ess;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+
+public class ContentIdentifier
+ extends ASN1Object
+{
+ ASN1OctetString value;
+
+ public static ContentIdentifier getInstance(Object o)
+ {
+ if (o instanceof ContentIdentifier)
+ {
+ return (ContentIdentifier) o;
+ }
+ else if (o != null)
+ {
+ return new ContentIdentifier(ASN1OctetString.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * Create from OCTET STRING whose octets represent the identifier.
+ */
+ private ContentIdentifier(
+ ASN1OctetString value)
+ {
+ this.value = value;
+ }
+
+ /**
+ * Create from byte array representing the identifier.
+ */
+ public ContentIdentifier(
+ byte[] value)
+ {
+ this(new DEROctetString(value));
+ }
+
+ public ASN1OctetString getValue()
+ {
+ return value;
+ }
+
+ /**
+ * The definition of ContentIdentifier is
+ *
+ * ContentIdentifier ::= OCTET STRING
+ *
+ * id-aa-contentIdentifier OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ * smime(16) id-aa(2) 7 }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return value;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/ESSCertID.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/ESSCertID.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/ESSCertID.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/ESSCertID.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,95 @@
+package pdftk.org.bouncycastle.asn1.ess;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.IssuerSerial;
+
+public class ESSCertID
+ extends ASN1Object
+{
+ private ASN1OctetString certHash;
+
+ private IssuerSerial issuerSerial;
+
+ public static ESSCertID getInstance(Object o)
+ {
+ if (o instanceof ESSCertID)
+ {
+ return (ESSCertID)o;
+ }
+ else if (o != null)
+ {
+ return new ESSCertID(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * constructor
+ */
+ private ESSCertID(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ certHash = ASN1OctetString.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ issuerSerial = IssuerSerial.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public ESSCertID(
+ byte[] hash)
+ {
+ certHash = new DEROctetString(hash);
+ }
+
+ public ESSCertID(
+ byte[] hash,
+ IssuerSerial issuerSerial)
+ {
+ this.certHash = new DEROctetString(hash);
+ this.issuerSerial = issuerSerial;
+ }
+
+ public byte[] getCertHash()
+ {
+ return certHash.getOctets();
+ }
+
+ public IssuerSerial getIssuerSerial()
+ {
+ return issuerSerial;
+ }
+
+ /**
+ *
+ * ESSCertID ::= SEQUENCE {
+ * certHash Hash,
+ * issuerSerial IssuerSerial OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certHash);
+
+ if (issuerSerial != null)
+ {
+ v.add(issuerSerial);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/ESSCertIDv2.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/ESSCertIDv2.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/ESSCertIDv2.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/ESSCertIDv2.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,142 @@
+package pdftk.org.bouncycastle.asn1.ess;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import pdftk.org.bouncycastle.asn1.x509.IssuerSerial;
+
+public class ESSCertIDv2
+ extends ASN1Object
+{
+ private AlgorithmIdentifier hashAlgorithm;
+ private byte[] certHash;
+ private IssuerSerial issuerSerial;
+ private static final AlgorithmIdentifier DEFAULT_ALG_ID = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256);
+
+ public static ESSCertIDv2 getInstance(
+ Object o)
+ {
+ if (o instanceof ESSCertIDv2)
+ {
+ return (ESSCertIDv2) o;
+ }
+ else if (o != null)
+ {
+ return new ESSCertIDv2(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private ESSCertIDv2(
+ ASN1Sequence seq)
+ {
+ if (seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ int count = 0;
+
+ if (seq.getObjectAt(0) instanceof ASN1OctetString)
+ {
+ // Default value
+ this.hashAlgorithm = DEFAULT_ALG_ID;
+ }
+ else
+ {
+ this.hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(count++).toASN1Primitive());
+ }
+
+ this.certHash = ASN1OctetString.getInstance(seq.getObjectAt(count++).toASN1Primitive()).getOctets();
+
+ if (seq.size() > count)
+ {
+ this.issuerSerial = IssuerSerial.getInstance(seq.getObjectAt(count));
+ }
+ }
+
+ public ESSCertIDv2(
+ AlgorithmIdentifier algId,
+ byte[] certHash)
+ {
+ this(algId, certHash, null);
+ }
+
+ public ESSCertIDv2(
+ AlgorithmIdentifier algId,
+ byte[] certHash,
+ IssuerSerial issuerSerial)
+ {
+ if (algId == null)
+ {
+ // Default value
+ this.hashAlgorithm = DEFAULT_ALG_ID;
+ }
+ else
+ {
+ this.hashAlgorithm = algId;
+ }
+
+ this.certHash = certHash;
+ this.issuerSerial = issuerSerial;
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return this.hashAlgorithm;
+ }
+
+ public byte[] getCertHash()
+ {
+ return certHash;
+ }
+
+ public IssuerSerial getIssuerSerial()
+ {
+ return issuerSerial;
+ }
+
+ /**
+ *
+ * ESSCertIDv2 ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier
+ * DEFAULT {algorithm id-sha256},
+ * certHash Hash,
+ * issuerSerial IssuerSerial OPTIONAL
+ * }
+ *
+ * Hash ::= OCTET STRING
+ *
+ * IssuerSerial ::= SEQUENCE {
+ * issuer GeneralNames,
+ * serialNumber CertificateSerialNumber
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (!hashAlgorithm.equals(DEFAULT_ALG_ID))
+ {
+ v.add(hashAlgorithm);
+ }
+
+ v.add(new DEROctetString(certHash).toASN1Primitive());
+
+ if (issuerSerial != null)
+ {
+ v.add(issuerSerial);
+ }
+
+ return new DERSequence(v);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/OtherCertID.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/OtherCertID.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/OtherCertID.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/OtherCertID.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,137 @@
+package pdftk.org.bouncycastle.asn1.ess;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import pdftk.org.bouncycastle.asn1.x509.DigestInfo;
+import pdftk.org.bouncycastle.asn1.x509.IssuerSerial;
+
+public class OtherCertID
+ extends ASN1Object
+{
+ private ASN1Encodable otherCertHash;
+ private IssuerSerial issuerSerial;
+
+ public static OtherCertID getInstance(Object o)
+ {
+ if (o instanceof OtherCertID)
+ {
+ return (OtherCertID) o;
+ }
+ else if (o != null)
+ {
+ return new OtherCertID(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * constructor
+ */
+ private OtherCertID(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ if (seq.getObjectAt(0).toASN1Primitive() instanceof ASN1OctetString)
+ {
+ otherCertHash = ASN1OctetString.getInstance(seq.getObjectAt(0));
+ }
+ else
+ {
+ otherCertHash = DigestInfo.getInstance(seq.getObjectAt(0));
+
+ }
+
+ if (seq.size() > 1)
+ {
+ issuerSerial = IssuerSerial.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public OtherCertID(
+ AlgorithmIdentifier algId,
+ byte[] digest)
+ {
+ this.otherCertHash = new DigestInfo(algId, digest);
+ }
+
+ public OtherCertID(
+ AlgorithmIdentifier algId,
+ byte[] digest,
+ IssuerSerial issuerSerial)
+ {
+ this.otherCertHash = new DigestInfo(algId, digest);
+ this.issuerSerial = issuerSerial;
+ }
+
+ public AlgorithmIdentifier getAlgorithmHash()
+ {
+ if (otherCertHash.toASN1Primitive() instanceof ASN1OctetString)
+ {
+ // SHA-1
+ return new AlgorithmIdentifier("1.3.14.3.2.26");
+ }
+ else
+ {
+ return DigestInfo.getInstance(otherCertHash).getAlgorithmId();
+ }
+ }
+
+ public byte[] getCertHash()
+ {
+ if (otherCertHash.toASN1Primitive() instanceof ASN1OctetString)
+ {
+ // SHA-1
+ return ((ASN1OctetString)otherCertHash.toASN1Primitive()).getOctets();
+ }
+ else
+ {
+ return DigestInfo.getInstance(otherCertHash).getDigest();
+ }
+ }
+
+ public IssuerSerial getIssuerSerial()
+ {
+ return issuerSerial;
+ }
+
+ /**
+ *
+ * OtherCertID ::= SEQUENCE {
+ * otherCertHash OtherHash,
+ * issuerSerial IssuerSerial OPTIONAL }
+ *
+ * OtherHash ::= CHOICE {
+ * sha1Hash OCTET STRING,
+ * otherHash OtherHashAlgAndValue }
+ *
+ * OtherHashAlgAndValue ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * hashValue OCTET STRING }
+ *
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(otherCertHash);
+
+ if (issuerSerial != null)
+ {
+ v.add(issuerSerial);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/OtherSigningCertificate.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/OtherSigningCertificate.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/OtherSigningCertificate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/OtherSigningCertificate.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,109 @@
+package pdftk.org.bouncycastle.asn1.ess;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.PolicyInformation;
+
+public class OtherSigningCertificate
+ extends ASN1Object
+{
+ ASN1Sequence certs;
+ ASN1Sequence policies;
+
+ public static OtherSigningCertificate getInstance(Object o)
+ {
+ if (o instanceof OtherSigningCertificate)
+ {
+ return (OtherSigningCertificate) o;
+ }
+ else if (o != null)
+ {
+ return new OtherSigningCertificate(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * constructeurs
+ */
+ private OtherSigningCertificate(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ this.certs = ASN1Sequence.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ this.policies = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public OtherSigningCertificate(
+ OtherCertID otherCertID)
+ {
+ certs = new DERSequence(otherCertID);
+ }
+
+ public OtherCertID[] getCerts()
+ {
+ OtherCertID[] cs = new OtherCertID[certs.size()];
+
+ for (int i = 0; i != certs.size(); i++)
+ {
+ cs[i] = OtherCertID.getInstance(certs.getObjectAt(i));
+ }
+
+ return cs;
+ }
+
+ public PolicyInformation[] getPolicies()
+ {
+ if (policies == null)
+ {
+ return null;
+ }
+
+ PolicyInformation[] ps = new PolicyInformation[policies.size()];
+
+ for (int i = 0; i != policies.size(); i++)
+ {
+ ps[i] = PolicyInformation.getInstance(policies.getObjectAt(i));
+ }
+
+ return ps;
+ }
+
+ /**
+ * The definition of OtherSigningCertificate is
+ *
+ * OtherSigningCertificate ::= SEQUENCE {
+ * certs SEQUENCE OF OtherCertID,
+ * policies SEQUENCE OF PolicyInformation OPTIONAL
+ * }
+ *
+ * id-aa-ets-otherSigCert OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ * smime(16) id-aa(2) 19 }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certs);
+
+ if (policies != null)
+ {
+ v.add(policies);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/SigningCertificate.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/SigningCertificate.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/SigningCertificate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/SigningCertificate.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,109 @@
+package pdftk.org.bouncycastle.asn1.ess;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.PolicyInformation;
+
+
+public class SigningCertificate
+ extends ASN1Object
+{
+ ASN1Sequence certs;
+ ASN1Sequence policies;
+
+ public static SigningCertificate getInstance(Object o)
+ {
+ if (o instanceof SigningCertificate)
+ {
+ return (SigningCertificate) o;
+ }
+ else if (o != null)
+ {
+ return new SigningCertificate(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ /**
+ * constructeurs
+ */
+ private SigningCertificate(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ this.certs = ASN1Sequence.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ this.policies = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public SigningCertificate(
+ ESSCertID essCertID)
+ {
+ certs = new DERSequence(essCertID);
+ }
+
+ public ESSCertID[] getCerts()
+ {
+ ESSCertID[] cs = new ESSCertID[certs.size()];
+
+ for (int i = 0; i != certs.size(); i++)
+ {
+ cs[i] = ESSCertID.getInstance(certs.getObjectAt(i));
+ }
+
+ return cs;
+ }
+
+ public PolicyInformation[] getPolicies()
+ {
+ if (policies == null)
+ {
+ return null;
+ }
+
+ PolicyInformation[] ps = new PolicyInformation[policies.size()];
+
+ for (int i = 0; i != policies.size(); i++)
+ {
+ ps[i] = PolicyInformation.getInstance(policies.getObjectAt(i));
+ }
+
+ return ps;
+ }
+
+ /**
+ * The definition of SigningCertificate is
+ *
+ * SigningCertificate ::= SEQUENCE {
+ * certs SEQUENCE OF ESSCertID,
+ * policies SEQUENCE OF PolicyInformation OPTIONAL
+ * }
+ *
+ * id-aa-signingCertificate OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ * smime(16) id-aa(2) 12 }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certs);
+
+ if (policies != null)
+ {
+ v.add(policies);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/SigningCertificateV2.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/SigningCertificateV2.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/SigningCertificateV2.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/SigningCertificateV2.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,130 @@
+package pdftk.org.bouncycastle.asn1.ess;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.PolicyInformation;
+
+public class SigningCertificateV2
+ extends ASN1Object
+{
+ ASN1Sequence certs;
+ ASN1Sequence policies;
+
+ public static SigningCertificateV2 getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof SigningCertificateV2)
+ {
+ return (SigningCertificateV2) o;
+ }
+ else if (o instanceof ASN1Sequence)
+ {
+ return new SigningCertificateV2((ASN1Sequence) o);
+ }
+
+ return null;
+ }
+
+ private SigningCertificateV2(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ this.certs = ASN1Sequence.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ this.policies = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public SigningCertificateV2(
+ ESSCertIDv2[] certs)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i=0; i < certs.length; i++)
+ {
+ v.add(certs[i]);
+ }
+ this.certs = new DERSequence(v);
+ }
+
+ public SigningCertificateV2(
+ ESSCertIDv2[] certs,
+ PolicyInformation[] policies)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i=0; i < certs.length; i++)
+ {
+ v.add(certs[i]);
+ }
+ this.certs = new DERSequence(v);
+
+ if (policies != null)
+ {
+ v = new ASN1EncodableVector();
+ for (int i=0; i < policies.length; i++)
+ {
+ v.add(policies[i]);
+ }
+ this.policies = new DERSequence(v);
+ }
+ }
+
+ public ESSCertIDv2[] getCerts()
+ {
+ ESSCertIDv2[] certIds = new ESSCertIDv2[certs.size()];
+ for (int i = 0; i != certs.size(); i++)
+ {
+ certIds[i] = ESSCertIDv2.getInstance(certs.getObjectAt(i));
+ }
+ return certIds;
+ }
+
+ public PolicyInformation[] getPolicies()
+ {
+ if (policies == null)
+ {
+ return null;
+ }
+
+ PolicyInformation[] policyInformations = new PolicyInformation[policies.size()];
+ for (int i = 0; i != policies.size(); i++)
+ {
+ policyInformations[i] = PolicyInformation.getInstance(policies.getObjectAt(i));
+ }
+ return policyInformations;
+ }
+
+ /**
+ * The definition of SigningCertificateV2 is
+ *
+ * SigningCertificateV2 ::= SEQUENCE {
+ * certs SEQUENCE OF ESSCertIDv2,
+ * policies SEQUENCE OF PolicyInformation OPTIONAL
+ * }
+ *
+ * id-aa-signingCertificateV2 OBJECT IDENTIFIER ::= { iso(1)
+ * member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+ * smime(16) id-aa(2) 47 }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certs);
+
+ if (policies != null)
+ {
+ v.add(policies);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ess/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ess/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes useful for encoding and supporting Enhanced Security Services for S/MIME as described RFC 2634 and RFC 5035.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/gnu/GNUObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,30 @@
+package pdftk.org.bouncycastle.asn1.gnu;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface GNUObjectIdentifiers
+{
+ public static final ASN1ObjectIdentifier GNU = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.1"); // GNU Radius
+ public static final ASN1ObjectIdentifier GnuPG = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.2"); // GnuPG (Ägypten)
+ public static final ASN1ObjectIdentifier notation = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.2.1"); // notation
+ public static final ASN1ObjectIdentifier pkaAddress = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.2.1.1"); // pkaAddress
+ public static final ASN1ObjectIdentifier GnuRadar = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.3"); // GNU Radar
+ public static final ASN1ObjectIdentifier digestAlgorithm = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.12"); // digestAlgorithm
+ public static final ASN1ObjectIdentifier Tiger_192 = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.12.2"); // TIGER/192
+ public static final ASN1ObjectIdentifier encryptionAlgorithm = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13"); // encryptionAlgorithm
+ public static final ASN1ObjectIdentifier Serpent = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2"); // Serpent
+ public static final ASN1ObjectIdentifier Serpent_128_ECB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.1"); // Serpent-128-ECB
+ public static final ASN1ObjectIdentifier Serpent_128_CBC = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.2"); // Serpent-128-CBC
+ public static final ASN1ObjectIdentifier Serpent_128_OFB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.3"); // Serpent-128-OFB
+ public static final ASN1ObjectIdentifier Serpent_128_CFB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.4"); // Serpent-128-CFB
+ public static final ASN1ObjectIdentifier Serpent_192_ECB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.21"); // Serpent-192-ECB
+ public static final ASN1ObjectIdentifier Serpent_192_CBC = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.22"); // Serpent-192-CBC
+ public static final ASN1ObjectIdentifier Serpent_192_OFB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.23"); // Serpent-192-OFB
+ public static final ASN1ObjectIdentifier Serpent_192_CFB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.24"); // Serpent-192-CFB
+ public static final ASN1ObjectIdentifier Serpent_256_ECB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.41"); // Serpent-256-ECB
+ public static final ASN1ObjectIdentifier Serpent_256_CBC = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.42"); // Serpent-256-CBC
+ public static final ASN1ObjectIdentifier Serpent_256_OFB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.43"); // Serpent-256-OFB
+ public static final ASN1ObjectIdentifier Serpent_256_CFB = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.13.2.44"); // Serpent-256-CFB
+ public static final ASN1ObjectIdentifier CRC = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.14"); // CRC algorithms
+ public static final ASN1ObjectIdentifier CRC32 = new ASN1ObjectIdentifier("1.3.6.1.4.1.11591.14.1"); // CRC 32
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/iana/IANAObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,20 @@
+package pdftk.org.bouncycastle.asn1.iana;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface IANAObjectIdentifiers
+{
+ // id-SHA1 OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1)}
+ //
+
+ static final ASN1ObjectIdentifier isakmpOakley = new ASN1ObjectIdentifier("1.3.6.1.5.5.8.1");
+
+ static final ASN1ObjectIdentifier hmacMD5 = new ASN1ObjectIdentifier(isakmpOakley + ".1");
+ static final ASN1ObjectIdentifier hmacSHA1 = new ASN1ObjectIdentifier(isakmpOakley + ".2");
+
+ static final ASN1ObjectIdentifier hmacTIGER = new ASN1ObjectIdentifier(isakmpOakley + ".3");
+
+ static final ASN1ObjectIdentifier hmacRIPEMD160 = new ASN1ObjectIdentifier(isakmpOakley + ".4");
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/icao/CscaMasterList.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/icao/CscaMasterList.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/icao/CscaMasterList.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/icao/CscaMasterList.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,112 @@
+package pdftk.org.bouncycastle.asn1.icao;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERSet;
+import pdftk.org.bouncycastle.asn1.x509.Certificate;
+
+/**
+ * The CscaMasterList object. This object can be wrapped in a
+ * CMSSignedData to be published in LDAP.
+ *
+ *
+ * CscaMasterList ::= SEQUENCE {
+ * version CscaMasterListVersion,
+ * certList SET OF Certificate }
+ *
+ * CscaMasterListVersion :: INTEGER {v0(0)}
+ *
+ */
+
+public class CscaMasterList
+ extends ASN1Object
+{
+ private ASN1Integer version = new ASN1Integer(0);
+ private Certificate[] certList;
+
+ public static CscaMasterList getInstance(
+ Object obj)
+ {
+ if (obj instanceof CscaMasterList)
+ {
+ return (CscaMasterList)obj;
+ }
+ else if (obj != null)
+ {
+ return new CscaMasterList(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CscaMasterList(
+ ASN1Sequence seq)
+ {
+ if (seq == null || seq.size() == 0)
+ {
+ throw new IllegalArgumentException(
+ "null or empty sequence passed.");
+ }
+ if (seq.size() != 2) {
+ throw new IllegalArgumentException(
+ "Incorrect sequence size: " + seq.size());
+ }
+
+ version = ASN1Integer.getInstance(seq.getObjectAt(0));
+ ASN1Set certSet = ASN1Set.getInstance(seq.getObjectAt(1));
+ certList = new Certificate[certSet.size()];
+ for (int i = 0; i < certList.length; i++) {
+ certList[i]
+ = Certificate.getInstance(certSet.getObjectAt(i));
+ }
+ }
+
+ public CscaMasterList(
+ Certificate[] certStructs)
+ {
+ certList = copyCertList(certStructs);
+ }
+
+ public int getVersion()
+ {
+ return version.getValue().intValue();
+ }
+
+ public Certificate[] getCertStructs()
+ {
+ return copyCertList(certList);
+ }
+
+ private Certificate[] copyCertList(Certificate[] orig)
+ {
+ Certificate[] certs = new Certificate[orig.length];
+
+ for (int i = 0; i != certs.length; i++)
+ {
+ certs[i] = orig[i];
+ }
+
+ return certs;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+
+ seq.add(version);
+
+ ASN1EncodableVector certSet = new ASN1EncodableVector();
+ for (int i = 0; i < certList.length; i++)
+ {
+ certSet.add(certList[i]);
+ }
+ seq.add(new DERSet(certSet));
+
+ return new DERSequence(seq);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/icao/DataGroupHash.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/icao/DataGroupHash.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/icao/DataGroupHash.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/icao/DataGroupHash.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,97 @@
+package pdftk.org.bouncycastle.asn1.icao;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * The DataGroupHash object.
+ *
+ * DataGroupHash ::= SEQUENCE {
+ * dataGroupNumber DataGroupNumber,
+ * dataGroupHashValue OCTET STRING }
+ *
+ * DataGroupNumber ::= INTEGER {
+ * dataGroup1 (1),
+ * dataGroup1 (2),
+ * dataGroup1 (3),
+ * dataGroup1 (4),
+ * dataGroup1 (5),
+ * dataGroup1 (6),
+ * dataGroup1 (7),
+ * dataGroup1 (8),
+ * dataGroup1 (9),
+ * dataGroup1 (10),
+ * dataGroup1 (11),
+ * dataGroup1 (12),
+ * dataGroup1 (13),
+ * dataGroup1 (14),
+ * dataGroup1 (15),
+ * dataGroup1 (16) }
+ *
+ *
+ */
+public class DataGroupHash
+ extends ASN1Object
+{
+ ASN1Integer dataGroupNumber;
+ ASN1OctetString dataGroupHashValue;
+
+ public static DataGroupHash getInstance(
+ Object obj)
+ {
+ if (obj instanceof DataGroupHash)
+ {
+ return (DataGroupHash)obj;
+ }
+ else if (obj != null)
+ {
+ return new DataGroupHash(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private DataGroupHash(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ // dataGroupNumber
+ dataGroupNumber = ASN1Integer.getInstance(e.nextElement());
+ // dataGroupHashValue
+ dataGroupHashValue = ASN1OctetString.getInstance(e.nextElement());
+ }
+
+ public DataGroupHash(
+ int dataGroupNumber,
+ ASN1OctetString dataGroupHashValue)
+ {
+ this.dataGroupNumber = new ASN1Integer(dataGroupNumber);
+ this.dataGroupHashValue = dataGroupHashValue;
+ }
+
+ public int getDataGroupNumber()
+ {
+ return dataGroupNumber.getValue().intValue();
+ }
+
+ public ASN1OctetString getDataGroupHashValue()
+ {
+ return dataGroupHashValue;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+ seq.add(dataGroupNumber);
+ seq.add(dataGroupHashValue);
+
+ return new DERSequence(seq);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/icao/ICAOObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,33 @@
+package pdftk.org.bouncycastle.asn1.icao;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface ICAOObjectIdentifiers
+{
+ //
+ // base id
+ //
+ static final ASN1ObjectIdentifier id_icao = new ASN1ObjectIdentifier("2.23.136");
+
+ static final ASN1ObjectIdentifier id_icao_mrtd = id_icao.branch("1");
+ static final ASN1ObjectIdentifier id_icao_mrtd_security = id_icao_mrtd.branch("1");
+
+ // LDS security object, see ICAO Doc 9303-Volume 2-Section IV-A3.2
+ static final ASN1ObjectIdentifier id_icao_ldsSecurityObject = id_icao_mrtd_security.branch("1");
+
+ // CSCA master list, see TR CSCA Countersigning and Master List issuance
+ static final ASN1ObjectIdentifier id_icao_cscaMasterList = id_icao_mrtd_security.branch("2");
+ static final ASN1ObjectIdentifier id_icao_cscaMasterListSigningKey = id_icao_mrtd_security.branch("3");
+
+ // document type list, see draft TR LDS and PKI Maintenance, par. 3.2.1
+ static final ASN1ObjectIdentifier id_icao_documentTypeList = id_icao_mrtd_security.branch("4");
+
+ // Active Authentication protocol, see draft TR LDS and PKI Maintenance,
+ // par. 5.2.2
+ static final ASN1ObjectIdentifier id_icao_aaProtocolObject = id_icao_mrtd_security.branch("5");
+
+ // CSCA name change and key reoll-over, see draft TR LDS and PKI
+ // Maintenance, par. 3.2.1
+ static final ASN1ObjectIdentifier id_icao_extensions = id_icao_mrtd_security.branch("6");
+ static final ASN1ObjectIdentifier id_icao_extensions_namechangekeyrollover = id_icao_extensions.branch("1");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/icao/LDSSecurityObject.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/icao/LDSSecurityObject.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/icao/LDSSecurityObject.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/icao/LDSSecurityObject.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,159 @@
+package pdftk.org.bouncycastle.asn1.icao;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * The LDSSecurityObject object (V1.8).
+ *
+ * LDSSecurityObject ::= SEQUENCE {
+ * version LDSSecurityObjectVersion,
+ * hashAlgorithm DigestAlgorithmIdentifier,
+ * dataGroupHashValues SEQUENCE SIZE (2..ub-DataGroups) OF DataHashGroup,
+ * ldsVersionInfo LDSVersionInfo OPTIONAL
+ * -- if present, version MUST be v1 }
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier,
+ *
+ * LDSSecurityObjectVersion :: INTEGER {V0(0)}
+ *
+ */
+
+public class LDSSecurityObject
+ extends ASN1Object
+ implements ICAOObjectIdentifiers
+{
+ public static final int ub_DataGroups = 16;
+
+ private ASN1Integer version = new ASN1Integer(0);
+ private AlgorithmIdentifier digestAlgorithmIdentifier;
+ private DataGroupHash[] datagroupHash;
+ private LDSVersionInfo versionInfo;
+
+ public static LDSSecurityObject getInstance(
+ Object obj)
+ {
+ if (obj instanceof LDSSecurityObject)
+ {
+ return (LDSSecurityObject)obj;
+ }
+ else if (obj != null)
+ {
+ return new LDSSecurityObject(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private LDSSecurityObject(
+ ASN1Sequence seq)
+ {
+ if (seq == null || seq.size() == 0)
+ {
+ throw new IllegalArgumentException("null or empty sequence passed.");
+ }
+
+ Enumeration e = seq.getObjects();
+
+ // version
+ version = ASN1Integer.getInstance(e.nextElement());
+ // digestAlgorithmIdentifier
+ digestAlgorithmIdentifier = AlgorithmIdentifier.getInstance(e.nextElement());
+
+ ASN1Sequence datagroupHashSeq = ASN1Sequence.getInstance(e.nextElement());
+
+ if (version.getValue().intValue() == 1)
+ {
+ versionInfo = LDSVersionInfo.getInstance(e.nextElement());
+ }
+
+ checkDatagroupHashSeqSize(datagroupHashSeq.size());
+
+ datagroupHash = new DataGroupHash[datagroupHashSeq.size()];
+ for (int i= 0; i< datagroupHashSeq.size();i++)
+ {
+ datagroupHash[i] = DataGroupHash.getInstance(datagroupHashSeq.getObjectAt(i));
+ }
+ }
+
+ public LDSSecurityObject(
+ AlgorithmIdentifier digestAlgorithmIdentifier,
+ DataGroupHash[] datagroupHash)
+ {
+ this.version = new ASN1Integer(0);
+ this.digestAlgorithmIdentifier = digestAlgorithmIdentifier;
+ this.datagroupHash = datagroupHash;
+
+ checkDatagroupHashSeqSize(datagroupHash.length);
+ }
+
+ public LDSSecurityObject(
+ AlgorithmIdentifier digestAlgorithmIdentifier,
+ DataGroupHash[] datagroupHash,
+ LDSVersionInfo versionInfo)
+ {
+ this.version = new ASN1Integer(1);
+ this.digestAlgorithmIdentifier = digestAlgorithmIdentifier;
+ this.datagroupHash = datagroupHash;
+ this.versionInfo = versionInfo;
+
+ checkDatagroupHashSeqSize(datagroupHash.length);
+ }
+
+ private void checkDatagroupHashSeqSize(int size)
+ {
+ if ((size < 2) || (size > ub_DataGroups))
+ {
+ throw new IllegalArgumentException("wrong size in DataGroupHashValues : not in (2.."+ ub_DataGroups +")");
+ }
+ }
+
+ public int getVersion()
+ {
+ return version.getValue().intValue();
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithmIdentifier()
+ {
+ return digestAlgorithmIdentifier;
+ }
+
+ public DataGroupHash[] getDatagroupHash()
+ {
+ return datagroupHash;
+ }
+
+ public LDSVersionInfo getVersionInfo()
+ {
+ return versionInfo;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+
+ seq.add(version);
+ seq.add(digestAlgorithmIdentifier);
+
+ ASN1EncodableVector seqname = new ASN1EncodableVector();
+ for (int i = 0; i < datagroupHash.length; i++)
+ {
+ seqname.add(datagroupHash[i]);
+ }
+ seq.add(new DERSequence(seqname));
+
+ if (versionInfo != null)
+ {
+ seq.add(versionInfo);
+ }
+
+ return new DERSequence(seq);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/icao/LDSVersionInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/icao/LDSVersionInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/icao/LDSVersionInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/icao/LDSVersionInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,75 @@
+package pdftk.org.bouncycastle.asn1.icao;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class LDSVersionInfo
+ extends ASN1Object
+{
+ private DERPrintableString ldsVersion;
+ private DERPrintableString unicodeVersion;
+
+ public LDSVersionInfo(String ldsVersion, String unicodeVersion)
+ {
+ this.ldsVersion = new DERPrintableString(ldsVersion);
+ this.unicodeVersion = new DERPrintableString(unicodeVersion);
+ }
+
+ private LDSVersionInfo(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("sequence wrong size for LDSVersionInfo");
+ }
+
+ this.ldsVersion = DERPrintableString.getInstance(seq.getObjectAt(0));
+ this.unicodeVersion = DERPrintableString.getInstance(seq.getObjectAt(1));
+ }
+
+ public static LDSVersionInfo getInstance(Object obj)
+ {
+ if (obj instanceof LDSVersionInfo)
+ {
+ return (LDSVersionInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new LDSVersionInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public String getLdsVersion()
+ {
+ return ldsVersion.getString();
+ }
+
+ public String getUnicodeVersion()
+ {
+ return unicodeVersion.getString();
+ }
+
+ /**
+ *
+ * LDSVersionInfo ::= SEQUENCE {
+ * ldsVersion PRINTABLE STRING
+ * unicodeVersion PRINTABLE STRING
+ * }
+ *
+ * @return
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(ldsVersion);
+ v.add(unicodeVersion);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/icao/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/icao/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/icao/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/icao/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+ICAO ASN.1 classes for electronic passport.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/ISISMTTObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,180 @@
+package pdftk.org.bouncycastle.asn1.isismtt;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface ISISMTTObjectIdentifiers
+{
+
+ static final ASN1ObjectIdentifier id_isismtt = new ASN1ObjectIdentifier("1.3.36.8");
+
+ static final ASN1ObjectIdentifier id_isismtt_cp = id_isismtt.branch("1");
+
+ /**
+ * The id-isismtt-cp-accredited OID indicates that the certificate is a
+ * qualified certificate according to Directive 1999/93/EC of the European
+ * Parliament and of the Council of 13 December 1999 on a Community
+ * Framework for Electronic Signatures, which additionally conforms the
+ * special requirements of the SigG and has been issued by an accredited CA.
+ */
+ static final ASN1ObjectIdentifier id_isismtt_cp_accredited = id_isismtt_cp.branch("1");
+
+ static final ASN1ObjectIdentifier id_isismtt_at = id_isismtt.branch("3");
+
+ /**
+ * Certificate extensionDate of certificate generation
+ *
+ *
+ * DateOfCertGenSyntax ::= GeneralizedTime
+ *
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_dateOfCertGen = id_isismtt_at.branch("1");
+
+ /**
+ * Attribute to indicate that the certificate holder may sign in the name of
+ * a third person. May also be used as extension in a certificate.
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_procuration = id_isismtt_at.branch("2");
+
+ /**
+ * Attribute to indicate admissions to certain professions. May be used as
+ * attribute in attribute certificate or as extension in a certificate
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_admission = id_isismtt_at.branch("3");
+
+ /**
+ * Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST
+ * be used in new certificates in place of the extension/attribute
+ * MonetaryLimit since January 1, 2004. For the sake of backward
+ * compatibility with certificates already in use, SigG conforming
+ * components MUST support MonetaryLimit (as well as QcEuLimitValue).
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_monetaryLimit = id_isismtt_at.branch("4");
+
+ /**
+ * A declaration of majority. May be used as attribute in attribute
+ * certificate or as extension in a certificate
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_declarationOfMajority = id_isismtt_at.branch("5");
+
+ /**
+ *
+ * Serial number of the smart card containing the corresponding private key
+ *
+ *
+ * ICCSNSyntax ::= OCTET STRING (SIZE(8..20))
+ *
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_iCCSN = id_isismtt_at.branch("6");
+
+ /**
+ *
+ * Reference for a file of a smartcard that stores the public key of this
+ * certificate and that is used as �security anchor�.
+ *
+ *
+ * PKReferenceSyntax ::= OCTET STRING (SIZE(20))
+ *
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_PKReference = id_isismtt_at.branch("7");
+
+ /**
+ * Some other restriction regarding the usage of this certificate. May be
+ * used as attribute in attribute certificate or as extension in a
+ * certificate.
+ *
+ *
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ *
+ *
+ * @see pdftk.org.bouncycastle.asn1.isismtt.x509.Restriction
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_restriction = id_isismtt_at.branch("8");
+
+ /**
+ *
+ * (Single)Request extension: Clients may include this extension in a
+ * (single) Request to request the responder to send the certificate in the
+ * response message along with the status information. Besides the LDAP
+ * service, this extension provides another mechanism for the distribution
+ * of certificates, which MAY optionally be provided by certificate
+ * repositories.
+ *
+ *
+ * RetrieveIfAllowed ::= BOOLEAN
+ *
+ *
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_retrieveIfAllowed = id_isismtt_at.branch("9");
+
+ /**
+ * SingleOCSPResponse extension: The certificate requested by the client by
+ * inserting the RetrieveIfAllowed extension in the request, will be
+ * returned in this extension.
+ *
+ * @see pdftk.org.bouncycastle.asn1.isismtt.ocsp.RequestedCertificate
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_requestedCertificate = id_isismtt_at.branch("10");
+
+ /**
+ * Base ObjectIdentifier for naming authorities
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_namingAuthorities = id_isismtt_at.branch("11");
+
+ /**
+ * SingleOCSPResponse extension: Date, when certificate has been published
+ * in the directory and status information has become available. Currently,
+ * accrediting authorities enforce that SigG-conforming OCSP servers include
+ * this extension in the responses.
+ *
+ *
+ * CertInDirSince ::= GeneralizedTime
+ *
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_certInDirSince = id_isismtt_at.branch("12");
+
+ /**
+ * Hash of a certificate in OCSP.
+ *
+ * @see pdftk.org.bouncycastle.asn1.isismtt.ocsp.CertHash
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_certHash = id_isismtt_at.branch("13");
+
+ /**
+ *
+ * NameAtBirth ::= DirectoryString(SIZE(1..64)
+ *
+ *
+ * Used in
+ * {@link pdftk.org.bouncycastle.asn1.x509.SubjectDirectoryAttributes SubjectDirectoryAttributes}
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_nameAtBirth = id_isismtt_at.branch("14");
+
+ /**
+ * Some other information of non-restrictive nature regarding the usage of
+ * this certificate. May be used as attribute in atribute certificate or as
+ * extension in a certificate.
+ *
+ *
+ * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+ *
+ *
+ * @see pdftk.org.bouncycastle.asn1.isismtt.x509.AdditionalInformationSyntax
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_additionalInformation = id_isismtt_at.branch("15");
+
+ /**
+ * Indicates that an attribute certificate exists, which limits the
+ * usability of this public key certificate. Whenever verifying a signature
+ * with the help of this certificate, the content of the corresponding
+ * attribute certificate should be concerned. This extension MUST be
+ * included in a PKC, if a corresponding attribute certificate (having the
+ * PKC as base certificate) contains some attribute that restricts the
+ * usability of the PKC too. Attribute certificates with restricting content
+ * MUST always be included in the signed document.
+ *
+ *
+ * LiabilityLimitationFlagSyntax ::= BOOLEAN
+ *
+ */
+ static final ASN1ObjectIdentifier id_isismtt_at_liabilityLimitationFlag = new ASN1ObjectIdentifier("0.2.262.1.10.12.0");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/ocsp/CertHash.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/ocsp/CertHash.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/ocsp/CertHash.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/ocsp/CertHash.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,124 @@
+package pdftk.org.bouncycastle.asn1.isismtt.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * ISIS-MTT PROFILE: The responder may include this extension in a response to
+ * send the hash of the requested certificate to the responder. This hash is
+ * cryptographically bound to the certificate and serves as evidence that the
+ * certificate is known to the responder (i.e. it has been issued and is present
+ * in the directory). Hence, this extension is a means to provide a positive
+ * statement of availability as described in T8.[8]. As explained in T13.[1],
+ * clients may rely on this information to be able to validate signatures after
+ * the expiry of the corresponding certificate. Hence, clients MUST support this
+ * extension. If a positive statement of availability is to be delivered, this
+ * extension syntax and OID MUST be used.
+ *
+ *
+ *
+ * CertHash ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * certificateHash OCTET STRING
+ * }
+ *
+ */
+public class CertHash
+ extends ASN1Object
+{
+
+ private AlgorithmIdentifier hashAlgorithm;
+ private byte[] certificateHash;
+
+ public static CertHash getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof CertHash)
+ {
+ return (CertHash)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new CertHash((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * The sequence is of type CertHash:
+ *
+ *
+ * CertHash ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * certificateHash OCTET STRING
+ * }
+ *
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private CertHash(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ certificateHash = DEROctetString.getInstance(seq.getObjectAt(1)).getOctets();
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param hashAlgorithm The hash algorithm identifier.
+ * @param certificateHash The hash of the whole DER encoding of the certificate.
+ */
+ public CertHash(AlgorithmIdentifier hashAlgorithm, byte[] certificateHash)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.certificateHash = new byte[certificateHash.length];
+ System.arraycopy(certificateHash, 0, this.certificateHash, 0,
+ certificateHash.length);
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public byte[] getCertificateHash()
+ {
+ return certificateHash;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * CertHash ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * certificateHash OCTET STRING
+ * }
+ *
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ vec.add(hashAlgorithm);
+ vec.add(new DEROctetString(certificateHash));
+ return new DERSequence(vec);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/ocsp/RequestedCertificate.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/ocsp/RequestedCertificate.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/ocsp/RequestedCertificate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/ocsp/RequestedCertificate.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,183 @@
+package pdftk.org.bouncycastle.asn1.isismtt.ocsp;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.Certificate;
+
+/**
+ * ISIS-MTT-Optional: The certificate requested by the client by inserting the
+ * RetrieveIfAllowed extension in the request, will be returned in this
+ * extension.
+ *
+ * ISIS-MTT-SigG: The signature act allows publishing certificates only then,
+ * when the certificate owner gives his explicit permission. Accordingly, there
+ * may be �nondownloadable� certificates, about which the responder must provide
+ * status information, but MUST NOT include them in the response. Clients may
+ * get therefore the following three kind of answers on a single request
+ * including the RetrieveIfAllowed extension:
+ *
+ * a) the responder supports the extension and is allowed to publish the
+ * certificate: RequestedCertificate returned including the requested
+ * certificate
+ * b) the responder supports the extension but is NOT allowed to publish
+ * the certificate: RequestedCertificate returned including an empty OCTET
+ * STRING
+ * c) the responder does not support the extension: RequestedCertificate is
+ * not included in the response
+ *
+ * Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If
+ * any of the OCTET STRING options is used, it MUST contain the DER encoding of
+ * the requested certificate.
+ *
+ *
+ * RequestedCertificate ::= CHOICE {
+ * Certificate Certificate,
+ * publicKeyCertificate [0] EXPLICIT OCTET STRING,
+ * attributeCertificate [1] EXPLICIT OCTET STRING
+ * }
+ *
+ */
+public class RequestedCertificate
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int certificate = -1;
+ public static final int publicKeyCertificate = 0;
+ public static final int attributeCertificate = 1;
+
+ private Certificate cert;
+ private byte[] publicKeyCert;
+ private byte[] attributeCert;
+
+ public static RequestedCertificate getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof RequestedCertificate)
+ {
+ return (RequestedCertificate)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new RequestedCertificate(Certificate.getInstance(obj));
+ }
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return new RequestedCertificate((ASN1TaggedObject)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ public static RequestedCertificate getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ if (!explicit)
+ {
+ throw new IllegalArgumentException("choice item must be explicitly tagged");
+ }
+
+ return getInstance(obj.getObject());
+ }
+
+ private RequestedCertificate(ASN1TaggedObject tagged)
+ {
+ if (tagged.getTagNo() == publicKeyCertificate)
+ {
+ publicKeyCert = ASN1OctetString.getInstance(tagged, true).getOctets();
+ }
+ else if (tagged.getTagNo() == attributeCertificate)
+ {
+ attributeCert = ASN1OctetString.getInstance(tagged, true).getOctets();
+ }
+ else
+ {
+ throw new IllegalArgumentException("unknown tag number: " + tagged.getTagNo());
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * Only one parameter can be given. All other must be null
.
+ *
+ * @param certificate Given as Certificate
+ */
+ public RequestedCertificate(Certificate certificate)
+ {
+ this.cert = certificate;
+ }
+
+ public RequestedCertificate(int type, byte[] certificateOctets)
+ {
+ this(new DERTaggedObject(type, new DEROctetString(certificateOctets)));
+ }
+
+ public int getType()
+ {
+ if (cert != null)
+ {
+ return certificate;
+ }
+ if (publicKeyCert != null)
+ {
+ return publicKeyCertificate;
+ }
+ return attributeCertificate;
+ }
+
+ public byte[] getCertificateBytes()
+ {
+ if (cert != null)
+ {
+ try
+ {
+ return cert.getEncoded();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("can't decode certificate: " + e);
+ }
+ }
+ if (publicKeyCert != null)
+ {
+ return publicKeyCert;
+ }
+ return attributeCert;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * RequestedCertificate ::= CHOICE {
+ * Certificate Certificate,
+ * publicKeyCertificate [0] EXPLICIT OCTET STRING,
+ * attributeCertificate [1] EXPLICIT OCTET STRING
+ * }
+ *
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (publicKeyCert != null)
+ {
+ return new DERTaggedObject(0, new DEROctetString(publicKeyCert));
+ }
+ if (attributeCert != null)
+ {
+ return new DERTaggedObject(1, new DEROctetString(attributeCert));
+ }
+ return cert.toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/AdditionalInformationSyntax.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,70 @@
+package pdftk.org.bouncycastle.asn1.isismtt.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.x500.DirectoryString;
+
+/**
+ * Some other information of non-restrictive nature regarding the usage of this
+ * certificate.
+ *
+ *
+ * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+ *
+ */
+public class AdditionalInformationSyntax
+ extends ASN1Object
+{
+ private DirectoryString information;
+
+ public static AdditionalInformationSyntax getInstance(Object obj)
+ {
+ if (obj instanceof AdditionalInformationSyntax)
+ {
+ return (AdditionalInformationSyntax)obj;
+ }
+
+ if (obj != null)
+ {
+ return new AdditionalInformationSyntax(DirectoryString.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private AdditionalInformationSyntax(DirectoryString information)
+ {
+ this.information = information;
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param information The describtion of the information.
+ */
+ public AdditionalInformationSyntax(String information)
+ {
+ this(new DirectoryString(information));
+ }
+
+ public DirectoryString getInformation()
+ {
+ return information;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+ *
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return information.toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/AdmissionSyntax.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/AdmissionSyntax.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/AdmissionSyntax.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/AdmissionSyntax.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,280 @@
+package pdftk.org.bouncycastle.asn1.isismtt.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.GeneralName;
+
+/**
+ * Attribute to indicate admissions to certain professions.
+ *
+ *
+ * AdmissionSyntax ::= SEQUENCE
+ * {
+ * admissionAuthority GeneralName OPTIONAL,
+ * contentsOfAdmissions SEQUENCE OF Admissions
+ * }
+ *
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ *
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ *
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ *
+ *
+ *
+ * ISIS-MTT PROFILE: The relatively complex structure of AdmissionSyntax
+ * supports the following concepts and requirements:
+ *
+ * External institutions (e.g. professional associations, chambers, unions,
+ * administrative bodies, companies, etc.), which are responsible for granting
+ * and verifying professional admissions, are indicated by means of the data
+ * field admissionAuthority. An admission authority is indicated by a
+ * GeneralName object. Here an X.501 directory name (distinguished name) can be
+ * indicated in the field directoryName, a URL address can be indicated in the
+ * field uniformResourceIdentifier, and an object identifier can be indicated in
+ * the field registeredId.
+ * The names of authorities which are responsible for the administration of
+ * title registers are indicated in the data field namingAuthority. The name of
+ * the authority can be identified by an object identifier in the field
+ * namingAuthorityId, by means of a text string in the field
+ * namingAuthorityText, by means of a URL address in the field
+ * namingAuthorityUrl, or by a combination of them. For example, the text string
+ * can contain the name of the authority, the country and the name of the title
+ * register. The URL-option refers to a web page which contains lists with
+ * �officially� registered professions (text and possibly OID) as well as
+ * further information on these professions. Object identifiers for the
+ * component namingAuthorityId are grouped under the OID-branch
+ * id-isis-at-namingAuthorities and must be applied for.
+ * See
+ * http://www.teletrust.de/anwend.asp?Id=30200&Sprache=E_&HomePG=0 for
+ * an application form and http://www.teletrust.de/links.asp?id=30220,11
+ * for an overview of registered naming authorities.
+ * By means of the data type ProfessionInfo certain professions,
+ * specializations, disciplines, fields of activity, etc. are identified. A
+ * profession is represented by one or more text strings, resp. profession OIDs
+ * in the fields professionItems and professionOIDs and by a registration number
+ * in the field registrationNumber. An indication in text form must always be
+ * present, whereas the other indications are optional. The component
+ * addProfessionInfo may contain additional applicationspecific information in
+ * DER-encoded form.
+ *
+ *
+ * By means of different namingAuthority-OIDs or profession OIDs hierarchies of
+ * professions, specializations, disciplines, fields of activity, etc. can be
+ * expressed. The issuing admission authority should always be indicated (field
+ * admissionAuthority), whenever a registration number is presented. Still,
+ * information on admissions can be given without indicating an admission or a
+ * naming authority by the exclusive use of the component professionItems. In
+ * this case the certification authority is responsible for the verification of
+ * the admission information.
+ *
+ *
+ *
+ * This attribute is single-valued. Still, several admissions can be captured in
+ * the sequence structure of the component contentsOfAdmissions of
+ * AdmissionSyntax or in the component professionInfos of Admissions. The
+ * component admissionAuthority of AdmissionSyntax serves as default value for
+ * the component admissionAuthority of Admissions. Within the latter component
+ * the default value can be overwritten, in case that another authority is
+ * responsible. The component namingAuthority of Admissions serves as a default
+ * value for the component namingAuthority of ProfessionInfo. Within the latter
+ * component the default value can be overwritten, in case that another naming
+ * authority needs to be recorded.
+ *
+ * The length of the string objects is limited to 128 characters. It is
+ * recommended to indicate a namingAuthorityURL in all issued attribute
+ * certificates. If a namingAuthorityURL is indicated, the field professionItems
+ * of ProfessionInfo should contain only registered titles. If the field
+ * professionOIDs exists, it has to contain the OIDs of the professions listed
+ * in professionItems in the same order. In general, the field professionInfos
+ * should contain only one entry, unless the admissions that are to be listed
+ * are logically connected (e.g. they have been issued under the same admission
+ * number).
+ *
+ * @see pdftk.org.bouncycastle.asn1.isismtt.x509.Admissions
+ * @see pdftk.org.bouncycastle.asn1.isismtt.x509.ProfessionInfo
+ * @see pdftk.org.bouncycastle.asn1.isismtt.x509.NamingAuthority
+ */
+public class AdmissionSyntax
+ extends ASN1Object
+{
+
+ private GeneralName admissionAuthority;
+
+ private ASN1Sequence contentsOfAdmissions;
+
+ public static AdmissionSyntax getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof AdmissionSyntax)
+ {
+ return (AdmissionSyntax)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new AdmissionSyntax((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * The sequence is of type ProcurationSyntax:
+ *
+ *
+ * AdmissionSyntax ::= SEQUENCE
+ * {
+ * admissionAuthority GeneralName OPTIONAL,
+ * contentsOfAdmissions SEQUENCE OF Admissions
+ * }
+ *
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ *
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ *
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ *
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private AdmissionSyntax(ASN1Sequence seq)
+ {
+ switch (seq.size())
+ {
+ case 1:
+ contentsOfAdmissions = DERSequence.getInstance(seq.getObjectAt(0));
+ break;
+ case 2:
+ admissionAuthority = GeneralName.getInstance(seq.getObjectAt(0));
+ contentsOfAdmissions = DERSequence.getInstance(seq.getObjectAt(1));
+ break;
+ default:
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+ }
+
+ /**
+ * Constructor from given details.
+ *
+ * @param admissionAuthority The admission authority.
+ * @param contentsOfAdmissions The admissions.
+ */
+ public AdmissionSyntax(GeneralName admissionAuthority, ASN1Sequence contentsOfAdmissions)
+ {
+ this.admissionAuthority = admissionAuthority;
+ this.contentsOfAdmissions = contentsOfAdmissions;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * AdmissionSyntax ::= SEQUENCE
+ * {
+ * admissionAuthority GeneralName OPTIONAL,
+ * contentsOfAdmissions SEQUENCE OF Admissions
+ * }
+ *
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ *
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ *
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ *
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ if (admissionAuthority != null)
+ {
+ vec.add(admissionAuthority);
+ }
+ vec.add(contentsOfAdmissions);
+ return new DERSequence(vec);
+ }
+
+ /**
+ * @return Returns the admissionAuthority if present, null otherwise.
+ */
+ public GeneralName getAdmissionAuthority()
+ {
+ return admissionAuthority;
+ }
+
+ /**
+ * @return Returns the contentsOfAdmissions.
+ */
+ public Admissions[] getContentsOfAdmissions()
+ {
+ Admissions[] admissions = new Admissions[contentsOfAdmissions.size()];
+ int count = 0;
+ for (Enumeration e = contentsOfAdmissions.getObjects(); e.hasMoreElements();)
+ {
+ admissions[count++] = Admissions.getInstance(e.nextElement());
+ }
+ return admissions;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/Admissions.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/Admissions.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/Admissions.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/Admissions.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,189 @@
+package pdftk.org.bouncycastle.asn1.isismtt.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.GeneralName;
+
+/**
+ * An Admissions structure.
+ *
+ *
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ *
+ *
+ *
+ * @see pdftk.org.bouncycastle.asn1.isismtt.x509.AdmissionSyntax
+ * @see pdftk.org.bouncycastle.asn1.isismtt.x509.ProfessionInfo
+ * @see pdftk.org.bouncycastle.asn1.isismtt.x509.NamingAuthority
+ */
+public class Admissions
+ extends ASN1Object
+{
+
+ private GeneralName admissionAuthority;
+
+ private NamingAuthority namingAuthority;
+
+ private ASN1Sequence professionInfos;
+
+ public static Admissions getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof Admissions)
+ {
+ return (Admissions)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new Admissions((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * The sequence is of type ProcurationSyntax:
+ *
+ *
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ *
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private Admissions(ASN1Sequence seq)
+ {
+ if (seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ Enumeration e = seq.getObjects();
+
+ ASN1Encodable o = (ASN1Encodable)e.nextElement();
+ if (o instanceof ASN1TaggedObject)
+ {
+ switch (((ASN1TaggedObject)o).getTagNo())
+ {
+ case 0:
+ admissionAuthority = GeneralName.getInstance((ASN1TaggedObject)o, true);
+ break;
+ case 1:
+ namingAuthority = NamingAuthority.getInstance((ASN1TaggedObject)o, true);
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag number: " + ((ASN1TaggedObject)o).getTagNo());
+ }
+ o = (ASN1Encodable)e.nextElement();
+ }
+ if (o instanceof ASN1TaggedObject)
+ {
+ switch (((ASN1TaggedObject)o).getTagNo())
+ {
+ case 1:
+ namingAuthority = NamingAuthority.getInstance((ASN1TaggedObject)o, true);
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag number: " + ((ASN1TaggedObject)o).getTagNo());
+ }
+ o = (ASN1Encodable)e.nextElement();
+ }
+ professionInfos = ASN1Sequence.getInstance(o);
+ if (e.hasMoreElements())
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + e.nextElement().getClass());
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * Parameter professionInfos
is mandatory.
+ *
+ * @param admissionAuthority The admission authority.
+ * @param namingAuthority The naming authority.
+ * @param professionInfos The profession infos.
+ */
+ public Admissions(GeneralName admissionAuthority,
+ NamingAuthority namingAuthority, ProfessionInfo[] professionInfos)
+ {
+ this.admissionAuthority = admissionAuthority;
+ this.namingAuthority = namingAuthority;
+ this.professionInfos = new DERSequence(professionInfos);
+ }
+
+ public GeneralName getAdmissionAuthority()
+ {
+ return admissionAuthority;
+ }
+
+ public NamingAuthority getNamingAuthority()
+ {
+ return namingAuthority;
+ }
+
+ public ProfessionInfo[] getProfessionInfos()
+ {
+ ProfessionInfo[] infos = new ProfessionInfo[professionInfos.size()];
+ int count = 0;
+ for (Enumeration e = professionInfos.getObjects(); e.hasMoreElements();)
+ {
+ infos[count++] = ProfessionInfo.getInstance(e.nextElement());
+ }
+ return infos;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * Admissions ::= SEQUENCE
+ * {
+ * admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+ * namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+ * professionInfos SEQUENCE OF ProfessionInfo
+ * }
+ *
+ *
+ *
+ * @return an ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+
+ if (admissionAuthority != null)
+ {
+ vec.add(new DERTaggedObject(true, 0, admissionAuthority));
+ }
+ if (namingAuthority != null)
+ {
+ vec.add(new DERTaggedObject(true, 1, namingAuthority));
+ }
+ vec.add(professionInfos);
+
+ return new DERSequence(vec);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/DeclarationOfMajority.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/DeclarationOfMajority.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/DeclarationOfMajority.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/DeclarationOfMajority.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,164 @@
+package pdftk.org.bouncycastle.asn1.isismtt.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Boolean;
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * A declaration of majority.
+ *
+ *
+ * DeclarationOfMajoritySyntax ::= CHOICE
+ * {
+ * notYoungerThan [0] IMPLICIT INTEGER,
+ * fullAgeAtCountry [1] IMPLICIT SEQUENCE
+ * {
+ * fullAge BOOLEAN DEFAULT TRUE,
+ * country PrintableString (SIZE(2))
+ * }
+ * dateOfBirth [2] IMPLICIT GeneralizedTime
+ * }
+ *
+ *
+ * fullAgeAtCountry indicates the majority of the owner with respect to the laws
+ * of a specific country.
+ */
+public class DeclarationOfMajority
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int notYoungerThan = 0;
+ public static final int fullAgeAtCountry = 1;
+ public static final int dateOfBirth = 2;
+
+ private ASN1TaggedObject declaration;
+
+ public DeclarationOfMajority(int notYoungerThan)
+ {
+ declaration = new DERTaggedObject(false, 0, new ASN1Integer(notYoungerThan));
+ }
+
+ public DeclarationOfMajority(boolean fullAge, String country)
+ {
+ if (country.length() > 2)
+ {
+ throw new IllegalArgumentException("country can only be 2 characters");
+ }
+
+ if (fullAge)
+ {
+ declaration = new DERTaggedObject(false, 1, new DERSequence(new DERPrintableString(country, true)));
+ }
+ else
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(ASN1Boolean.FALSE);
+ v.add(new DERPrintableString(country, true));
+
+ declaration = new DERTaggedObject(false, 1, new DERSequence(v));
+ }
+ }
+
+ public DeclarationOfMajority(ASN1GeneralizedTime dateOfBirth)
+ {
+ declaration = new DERTaggedObject(false, 2, dateOfBirth);
+ }
+
+ public static DeclarationOfMajority getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DeclarationOfMajority)
+ {
+ return (DeclarationOfMajority)obj;
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return new DeclarationOfMajority((ASN1TaggedObject)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ private DeclarationOfMajority(ASN1TaggedObject o)
+ {
+ if (o.getTagNo() > 2)
+ {
+ throw new IllegalArgumentException("Bad tag number: " + o.getTagNo());
+ }
+ declaration = o;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * DeclarationOfMajoritySyntax ::= CHOICE
+ * {
+ * notYoungerThan [0] IMPLICIT INTEGER,
+ * fullAgeAtCountry [1] IMPLICIT SEQUENCE
+ * {
+ * fullAge BOOLEAN DEFAULT TRUE,
+ * country PrintableString (SIZE(2))
+ * }
+ * dateOfBirth [2] IMPLICIT GeneralizedTime
+ * }
+ *
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return declaration;
+ }
+
+ public int getType()
+ {
+ return declaration.getTagNo();
+ }
+
+ /**
+ * @return notYoungerThan if that's what we are, -1 otherwise
+ */
+ public int notYoungerThan()
+ {
+ if (declaration.getTagNo() != 0)
+ {
+ return -1;
+ }
+
+ return ASN1Integer.getInstance(declaration, false).getValue().intValue();
+ }
+
+ public ASN1Sequence fullAgeAtCountry()
+ {
+ if (declaration.getTagNo() != 1)
+ {
+ return null;
+ }
+
+ return ASN1Sequence.getInstance(declaration, false);
+ }
+
+ public ASN1GeneralizedTime getDateOfBirth()
+ {
+ if (declaration.getTagNo() != 2)
+ {
+ return null;
+ }
+
+ return ASN1GeneralizedTime.getInstance(declaration, false);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/MonetaryLimit.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/MonetaryLimit.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/MonetaryLimit.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/MonetaryLimit.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,131 @@
+package pdftk.org.bouncycastle.asn1.isismtt.x509;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST be
+ * used in new certificates in place of the extension/attribute MonetaryLimit
+ * since January 1, 2004. For the sake of backward compatibility with
+ * certificates already in use, components SHOULD support MonetaryLimit (as well
+ * as QcEuLimitValue).
+ *
+ * Indicates a monetary limit within which the certificate holder is authorized
+ * to act. (This value DOES NOT express a limit on the liability of the
+ * certification authority).
+ *
+ *
+ * MonetaryLimitSyntax ::= SEQUENCE
+ * {
+ * currency PrintableString (SIZE(3)),
+ * amount INTEGER,
+ * exponent INTEGER
+ * }
+ *
+ *
+ * currency must be the ISO code.
+ *
+ * value = amount�10*exponent
+ */
+public class MonetaryLimit
+ extends ASN1Object
+{
+ DERPrintableString currency;
+ ASN1Integer amount;
+ ASN1Integer exponent;
+
+ public static MonetaryLimit getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof MonetaryLimit)
+ {
+ return (MonetaryLimit)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new MonetaryLimit(ASN1Sequence.getInstance(obj));
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance");
+ }
+
+ private MonetaryLimit(ASN1Sequence seq)
+ {
+ if (seq.size() != 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ Enumeration e = seq.getObjects();
+ currency = DERPrintableString.getInstance(e.nextElement());
+ amount = ASN1Integer.getInstance(e.nextElement());
+ exponent = ASN1Integer.getInstance(e.nextElement());
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ *
+ * value = amount�10^exponent
+ *
+ * @param currency The currency. Must be the ISO code.
+ * @param amount The amount
+ * @param exponent The exponent
+ */
+ public MonetaryLimit(String currency, int amount, int exponent)
+ {
+ this.currency = new DERPrintableString(currency, true);
+ this.amount = new ASN1Integer(amount);
+ this.exponent = new ASN1Integer(exponent);
+ }
+
+ public String getCurrency()
+ {
+ return currency.getString();
+ }
+
+ public BigInteger getAmount()
+ {
+ return amount.getValue();
+ }
+
+ public BigInteger getExponent()
+ {
+ return exponent.getValue();
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * MonetaryLimitSyntax ::= SEQUENCE
+ * {
+ * currency PrintableString (SIZE(3)),
+ * amount INTEGER,
+ * exponent INTEGER
+ * }
+ *
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+ seq.add(currency);
+ seq.add(amount);
+ seq.add(exponent);
+
+ return new DERSequence(seq);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/NamingAuthority.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/NamingAuthority.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/NamingAuthority.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/NamingAuthority.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,244 @@
+package pdftk.org.bouncycastle.asn1.isismtt.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1String;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+import pdftk.org.bouncycastle.asn1.DERObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.isismtt.ISISMTTObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.x500.DirectoryString;
+
+/**
+ * Names of authorities which are responsible for the administration of title
+ * registers.
+ *
+ *
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ *
+ * @see pdftk.org.bouncycastle.asn1.isismtt.x509.AdmissionSyntax
+ *
+ */
+public class NamingAuthority
+ extends ASN1Object
+{
+
+ /**
+ * Profession OIDs should always be defined under the OID branch of the
+ * responsible naming authority. At the time of this writing, the work group
+ * �Recht, Wirtschaft, Steuern� (�Law, Economy, Taxes�) is registered as the
+ * first naming authority under the OID id-isismtt-at-namingAuthorities.
+ */
+ public static final ASN1ObjectIdentifier id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern =
+ new ASN1ObjectIdentifier(ISISMTTObjectIdentifiers.id_isismtt_at_namingAuthorities + ".1");
+
+ private ASN1ObjectIdentifier namingAuthorityId;
+ private String namingAuthorityUrl;
+ private DirectoryString namingAuthorityText;
+
+ public static NamingAuthority getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof NamingAuthority)
+ {
+ return (NamingAuthority)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new NamingAuthority((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ public static NamingAuthority getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ *
+ *
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ *
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private NamingAuthority(ASN1Sequence seq)
+ {
+
+ if (seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ if (e.hasMoreElements())
+ {
+ ASN1Encodable o = (ASN1Encodable)e.nextElement();
+ if (o instanceof ASN1ObjectIdentifier)
+ {
+ namingAuthorityId = (ASN1ObjectIdentifier)o;
+ }
+ else if (o instanceof DERIA5String)
+ {
+ namingAuthorityUrl = DERIA5String.getInstance(o).getString();
+ }
+ else if (o instanceof ASN1String)
+ {
+ namingAuthorityText = DirectoryString.getInstance(o);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + o.getClass());
+ }
+ }
+ if (e.hasMoreElements())
+ {
+ ASN1Encodable o = (ASN1Encodable)e.nextElement();
+ if (o instanceof DERIA5String)
+ {
+ namingAuthorityUrl = DERIA5String.getInstance(o).getString();
+ }
+ else if (o instanceof ASN1String)
+ {
+ namingAuthorityText = DirectoryString.getInstance(o);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + o.getClass());
+ }
+ }
+ if (e.hasMoreElements())
+ {
+ ASN1Encodable o = (ASN1Encodable)e.nextElement();
+ if (o instanceof ASN1String)
+ {
+ namingAuthorityText = DirectoryString.getInstance(o);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + o.getClass());
+ }
+
+ }
+ }
+
+ /**
+ * @return Returns the namingAuthorityId.
+ */
+ public ASN1ObjectIdentifier getNamingAuthorityId()
+ {
+ return namingAuthorityId;
+ }
+
+ /**
+ * @return Returns the namingAuthorityText.
+ */
+ public DirectoryString getNamingAuthorityText()
+ {
+ return namingAuthorityText;
+ }
+
+ /**
+ * @return Returns the namingAuthorityUrl.
+ */
+ public String getNamingAuthorityUrl()
+ {
+ return namingAuthorityUrl;
+ }
+
+ /**
+ * Constructor from given details.
+ *
+ * All parameters can be combined.
+ *
+ * @param namingAuthorityId ObjectIdentifier for naming authority.
+ * @param namingAuthorityUrl URL for naming authority.
+ * @param namingAuthorityText Textual representation of naming authority.
+ * @deprecated use ASN1ObjectIdentifier method
+ */
+ public NamingAuthority(DERObjectIdentifier namingAuthorityId,
+ String namingAuthorityUrl, DirectoryString namingAuthorityText)
+ {
+ this.namingAuthorityId = new ASN1ObjectIdentifier(namingAuthorityId.getId());
+ this.namingAuthorityUrl = namingAuthorityUrl;
+ this.namingAuthorityText = namingAuthorityText;
+ }
+
+ /**
+ * Constructor from given details.
+ *
+ * All parameters can be combined.
+ *
+ * @param namingAuthorityId ObjectIdentifier for naming authority.
+ * @param namingAuthorityUrl URL for naming authority.
+ * @param namingAuthorityText Textual representation of naming authority.
+ */
+ public NamingAuthority(ASN1ObjectIdentifier namingAuthorityId,
+ String namingAuthorityUrl, DirectoryString namingAuthorityText)
+ {
+ this.namingAuthorityId = namingAuthorityId;
+ this.namingAuthorityUrl = namingAuthorityUrl;
+ this.namingAuthorityText = namingAuthorityText;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * NamingAuthority ::= SEQUENCE
+ * {
+ * namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+ * namingAuthorityUrl IA5String OPTIONAL,
+ * namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+ * }
+ *
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ if (namingAuthorityId != null)
+ {
+ vec.add(namingAuthorityId);
+ }
+ if (namingAuthorityUrl != null)
+ {
+ vec.add(new DERIA5String(namingAuthorityUrl, true));
+ }
+ if (namingAuthorityText != null)
+ {
+ vec.add(namingAuthorityText);
+ }
+ return new DERSequence(vec);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/ProcurationSyntax.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/ProcurationSyntax.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/ProcurationSyntax.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/ProcurationSyntax.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,240 @@
+package pdftk.org.bouncycastle.asn1.isismtt.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x500.DirectoryString;
+import pdftk.org.bouncycastle.asn1.x509.GeneralName;
+import pdftk.org.bouncycastle.asn1.x509.IssuerSerial;
+
+/**
+ * Attribute to indicate that the certificate holder may sign in the name of a
+ * third person.
+ *
+ * ISIS-MTT PROFILE: The corresponding ProcurationSyntax contains either the
+ * name of the person who is represented (subcomponent thirdPerson) or a
+ * reference to his/her base certificate (in the component signingFor,
+ * subcomponent certRef), furthermore the optional components country and
+ * typeSubstitution to indicate the country whose laws apply, and respectively
+ * the type of procuration (e.g. manager, procuration, custody).
+ *
+ * ISIS-MTT PROFILE: The GeneralName MUST be of type directoryName and MAY only
+ * contain: - RFC3039 attributes, except pseudonym (countryName, commonName,
+ * surname, givenName, serialNumber, organizationName, organizationalUnitName,
+ * stateOrProvincename, localityName, postalAddress) and - SubjectDirectoryName
+ * attributes (title, dateOfBirth, placeOfBirth, gender, countryOfCitizenship,
+ * countryOfResidence and NameAtBirth).
+ *
+ *
+ * ProcurationSyntax ::= SEQUENCE {
+ * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+ * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+ * signingFor [3] EXPLICIT SigningFor
+ * }
+ *
+ * SigningFor ::= CHOICE
+ * {
+ * thirdPerson GeneralName,
+ * certRef IssuerSerial
+ * }
+ *
+ *
+ */
+public class ProcurationSyntax
+ extends ASN1Object
+{
+ private String country;
+ private DirectoryString typeOfSubstitution;
+
+ private GeneralName thirdPerson;
+ private IssuerSerial certRef;
+
+ public static ProcurationSyntax getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof ProcurationSyntax)
+ {
+ return (ProcurationSyntax)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new ProcurationSyntax((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * The sequence is of type ProcurationSyntax:
+ *
+ *
+ * ProcurationSyntax ::= SEQUENCE {
+ * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+ * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+ * signingFor [3] EXPLICIT SigningFor
+ * }
+ *
+ * SigningFor ::= CHOICE
+ * {
+ * thirdPerson GeneralName,
+ * certRef IssuerSerial
+ * }
+ *
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private ProcurationSyntax(ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
+ switch (o.getTagNo())
+ {
+ case 1:
+ country = DERPrintableString.getInstance(o, true).getString();
+ break;
+ case 2:
+ typeOfSubstitution = DirectoryString.getInstance(o, true);
+ break;
+ case 3:
+ ASN1Encodable signingFor = o.getObject();
+ if (signingFor instanceof ASN1TaggedObject)
+ {
+ thirdPerson = GeneralName.getInstance(signingFor);
+ }
+ else
+ {
+ certRef = IssuerSerial.getInstance(signingFor);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag number: " + o.getTagNo());
+ }
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ *
+ * Either generalName
or certRef
MUST be
+ * null
.
+ *
+ * @param country The country code whose laws apply.
+ * @param typeOfSubstitution The type of procuration.
+ * @param certRef Reference to certificate of the person who is represented.
+ */
+ public ProcurationSyntax(
+ String country,
+ DirectoryString typeOfSubstitution,
+ IssuerSerial certRef)
+ {
+ this.country = country;
+ this.typeOfSubstitution = typeOfSubstitution;
+ this.thirdPerson = null;
+ this.certRef = certRef;
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ *
+ * Either generalName
or certRef
MUST be
+ * null
.
+ *
+ * @param country The country code whose laws apply.
+ * @param typeOfSubstitution The type of procuration.
+ * @param thirdPerson The GeneralName of the person who is represented.
+ */
+ public ProcurationSyntax(
+ String country,
+ DirectoryString typeOfSubstitution,
+ GeneralName thirdPerson)
+ {
+ this.country = country;
+ this.typeOfSubstitution = typeOfSubstitution;
+ this.thirdPerson = thirdPerson;
+ this.certRef = null;
+ }
+
+ public String getCountry()
+ {
+ return country;
+ }
+
+ public DirectoryString getTypeOfSubstitution()
+ {
+ return typeOfSubstitution;
+ }
+
+ public GeneralName getThirdPerson()
+ {
+ return thirdPerson;
+ }
+
+ public IssuerSerial getCertRef()
+ {
+ return certRef;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * ProcurationSyntax ::= SEQUENCE {
+ * country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+ * typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+ * signingFor [3] EXPLICIT SigningFor
+ * }
+ *
+ * SigningFor ::= CHOICE
+ * {
+ * thirdPerson GeneralName,
+ * certRef IssuerSerial
+ * }
+ *
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ if (country != null)
+ {
+ vec.add(new DERTaggedObject(true, 1, new DERPrintableString(country, true)));
+ }
+ if (typeOfSubstitution != null)
+ {
+ vec.add(new DERTaggedObject(true, 2, typeOfSubstitution));
+ }
+ if (thirdPerson != null)
+ {
+ vec.add(new DERTaggedObject(true, 3, thirdPerson));
+ }
+ else
+ {
+ vec.add(new DERTaggedObject(true, 3, certRef));
+ }
+
+ return new DERSequence(vec);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/ProfessionInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/ProfessionInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/ProfessionInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/ProfessionInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,408 @@
+package pdftk.org.bouncycastle.asn1.isismtt.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x500.DirectoryString;
+
+/**
+ * Professions, specializations, disciplines, fields of activity, etc.
+ *
+ *
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ *
+ *
+ * @see pdftk.org.bouncycastle.asn1.isismtt.x509.AdmissionSyntax
+ */
+public class ProfessionInfo
+ extends ASN1Object
+{
+
+ /**
+ * Rechtsanw�ltin
+ */
+ public static final ASN1ObjectIdentifier Rechtsanwltin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".1");
+
+ /**
+ * Rechtsanwalt
+ */
+ public static final ASN1ObjectIdentifier Rechtsanwalt = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".2");
+
+ /**
+ * Rechtsbeistand
+ */
+ public static final ASN1ObjectIdentifier Rechtsbeistand = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".3");
+
+ /**
+ * Steuerberaterin
+ */
+ public static final ASN1ObjectIdentifier Steuerberaterin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".4");
+
+ /**
+ * Steuerberater
+ */
+ public static final ASN1ObjectIdentifier Steuerberater = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".5");
+
+ /**
+ * Steuerbevollm�chtigte
+ */
+ public static final ASN1ObjectIdentifier Steuerbevollmchtigte = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".6");
+
+ /**
+ * Steuerbevollm�chtigter
+ */
+ public static final ASN1ObjectIdentifier Steuerbevollmchtigter = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".7");
+
+ /**
+ * Notarin
+ */
+ public static final ASN1ObjectIdentifier Notarin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".8");
+
+ /**
+ * Notar
+ */
+ public static final ASN1ObjectIdentifier Notar = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".9");
+
+ /**
+ * Notarvertreterin
+ */
+ public static final ASN1ObjectIdentifier Notarvertreterin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".10");
+
+ /**
+ * Notarvertreter
+ */
+ public static final ASN1ObjectIdentifier Notarvertreter = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".11");
+
+ /**
+ * Notariatsverwalterin
+ */
+ public static final ASN1ObjectIdentifier Notariatsverwalterin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".12");
+
+ /**
+ * Notariatsverwalter
+ */
+ public static final ASN1ObjectIdentifier Notariatsverwalter = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".13");
+
+ /**
+ * Wirtschaftspr�ferin
+ */
+ public static final ASN1ObjectIdentifier Wirtschaftsprferin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".14");
+
+ /**
+ * Wirtschaftspr�fer
+ */
+ public static final ASN1ObjectIdentifier Wirtschaftsprfer = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".15");
+
+ /**
+ * Vereidigte Buchpr�ferin
+ */
+ public static final ASN1ObjectIdentifier VereidigteBuchprferin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".16");
+
+ /**
+ * Vereidigter Buchpr�fer
+ */
+ public static final ASN1ObjectIdentifier VereidigterBuchprfer = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".17");
+
+ /**
+ * Patentanw�ltin
+ */
+ public static final ASN1ObjectIdentifier Patentanwltin = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".18");
+
+ /**
+ * Patentanwalt
+ */
+ public static final ASN1ObjectIdentifier Patentanwalt = new ASN1ObjectIdentifier(
+ NamingAuthority.id_isismtt_at_namingAuthorities_RechtWirtschaftSteuern + ".19");
+
+ private NamingAuthority namingAuthority;
+
+ private ASN1Sequence professionItems;
+
+ private ASN1Sequence professionOIDs;
+
+ private String registrationNumber;
+
+ private ASN1OctetString addProfessionInfo;
+
+ public static ProfessionInfo getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof ProfessionInfo)
+ {
+ return (ProfessionInfo)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new ProfessionInfo((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ *
+ *
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ *
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private ProfessionInfo(ASN1Sequence seq)
+ {
+ if (seq.size() > 5)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ ASN1Encodable o = (ASN1Encodable)e.nextElement();
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ if (((ASN1TaggedObject)o).getTagNo() != 0)
+ {
+ throw new IllegalArgumentException("Bad tag number: "
+ + ((ASN1TaggedObject)o).getTagNo());
+ }
+ namingAuthority = NamingAuthority.getInstance((ASN1TaggedObject)o, true);
+ o = (ASN1Encodable)e.nextElement();
+ }
+
+ professionItems = ASN1Sequence.getInstance(o);
+
+ if (e.hasMoreElements())
+ {
+ o = (ASN1Encodable)e.nextElement();
+ if (o instanceof ASN1Sequence)
+ {
+ professionOIDs = ASN1Sequence.getInstance(o);
+ }
+ else if (o instanceof DERPrintableString)
+ {
+ registrationNumber = DERPrintableString.getInstance(o).getString();
+ }
+ else if (o instanceof ASN1OctetString)
+ {
+ addProfessionInfo = ASN1OctetString.getInstance(o);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + o.getClass());
+ }
+ }
+ if (e.hasMoreElements())
+ {
+ o = (ASN1Encodable)e.nextElement();
+ if (o instanceof DERPrintableString)
+ {
+ registrationNumber = DERPrintableString.getInstance(o).getString();
+ }
+ else if (o instanceof DEROctetString)
+ {
+ addProfessionInfo = (DEROctetString)o;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + o.getClass());
+ }
+ }
+ if (e.hasMoreElements())
+ {
+ o = (ASN1Encodable)e.nextElement();
+ if (o instanceof DEROctetString)
+ {
+ addProfessionInfo = (DEROctetString)o;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + o.getClass());
+ }
+ }
+
+ }
+
+ /**
+ * Constructor from given details.
+ *
+ * professionItems
is mandatory, all other parameters are
+ * optional.
+ *
+ * @param namingAuthority The naming authority.
+ * @param professionItems Directory strings of the profession.
+ * @param professionOIDs DERObjectIdentfier objects for the
+ * profession.
+ * @param registrationNumber Registration number.
+ * @param addProfessionInfo Additional infos in encoded form.
+ */
+ public ProfessionInfo(NamingAuthority namingAuthority,
+ DirectoryString[] professionItems, ASN1ObjectIdentifier[] professionOIDs,
+ String registrationNumber, ASN1OctetString addProfessionInfo)
+ {
+ this.namingAuthority = namingAuthority;
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ for (int i = 0; i != professionItems.length; i++)
+ {
+ v.add(professionItems[i]);
+ }
+ this.professionItems = new DERSequence(v);
+ if (professionOIDs != null)
+ {
+ v = new ASN1EncodableVector();
+ for (int i = 0; i != professionOIDs.length; i++)
+ {
+ v.add(professionOIDs[i]);
+ }
+ this.professionOIDs = new DERSequence(v);
+ }
+ this.registrationNumber = registrationNumber;
+ this.addProfessionInfo = addProfessionInfo;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * ProfessionInfo ::= SEQUENCE
+ * {
+ * namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+ * professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+ * professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+ * registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+ * addProfessionInfo OCTET STRING OPTIONAL
+ * }
+ *
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ if (namingAuthority != null)
+ {
+ vec.add(new DERTaggedObject(true, 0, namingAuthority));
+ }
+ vec.add(professionItems);
+ if (professionOIDs != null)
+ {
+ vec.add(professionOIDs);
+ }
+ if (registrationNumber != null)
+ {
+ vec.add(new DERPrintableString(registrationNumber, true));
+ }
+ if (addProfessionInfo != null)
+ {
+ vec.add(addProfessionInfo);
+ }
+ return new DERSequence(vec);
+ }
+
+ /**
+ * @return Returns the addProfessionInfo.
+ */
+ public ASN1OctetString getAddProfessionInfo()
+ {
+ return addProfessionInfo;
+ }
+
+ /**
+ * @return Returns the namingAuthority.
+ */
+ public NamingAuthority getNamingAuthority()
+ {
+ return namingAuthority;
+ }
+
+ /**
+ * @return Returns the professionItems.
+ */
+ public DirectoryString[] getProfessionItems()
+ {
+ DirectoryString[] items = new DirectoryString[professionItems.size()];
+ int count = 0;
+ for (Enumeration e = professionItems.getObjects(); e.hasMoreElements();)
+ {
+ items[count++] = DirectoryString.getInstance(e.nextElement());
+ }
+ return items;
+ }
+
+ /**
+ * @return Returns the professionOIDs.
+ */
+ public ASN1ObjectIdentifier[] getProfessionOIDs()
+ {
+ if (professionOIDs == null)
+ {
+ return new ASN1ObjectIdentifier[0];
+ }
+ ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[professionOIDs.size()];
+ int count = 0;
+ for (Enumeration e = professionOIDs.getObjects(); e.hasMoreElements();)
+ {
+ oids[count++] = ASN1ObjectIdentifier.getInstance(e.nextElement());
+ }
+ return oids;
+ }
+
+ /**
+ * @return Returns the registrationNumber.
+ */
+ public String getRegistrationNumber()
+ {
+ return registrationNumber;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/Restriction.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/Restriction.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/isismtt/x509/Restriction.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/isismtt/x509/Restriction.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,81 @@
+package pdftk.org.bouncycastle.asn1.isismtt.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.x500.DirectoryString;
+
+/**
+ * Some other restriction regarding the usage of this certificate.
+ *
+ *
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ *
+ */
+public class Restriction
+ extends ASN1Object
+{
+ private DirectoryString restriction;
+
+ public static Restriction getInstance(Object obj)
+ {
+ if (obj instanceof Restriction)
+ {
+ return (Restriction)obj;
+ }
+
+ if (obj != null)
+ {
+ return new Restriction(DirectoryString.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from DirectoryString.
+ *
+ * The DirectoryString is of type RestrictionSyntax:
+ *
+ *
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ *
+ *
+ * @param restriction A DirectoryString.
+ */
+ private Restriction(DirectoryString restriction)
+ {
+ this.restriction = restriction;
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param restriction The describtion of the restriction.
+ */
+ public Restriction(String restriction)
+ {
+ this.restriction = new DirectoryString(restriction);
+ }
+
+ public DirectoryString getRestriction()
+ {
+ return restriction;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+ *
+ *
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return restriction.toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/kisa/KISAObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,9 @@
+package pdftk.org.bouncycastle.asn1.kisa;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface KISAObjectIdentifiers
+{
+ public static final ASN1ObjectIdentifier id_seedCBC = new ASN1ObjectIdentifier("1.2.410.200004.1.4");
+ public static final ASN1ObjectIdentifier id_npki_app_cmsSeed_wrap = new ASN1ObjectIdentifier("1.2.410.200004.7.1.1.1");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/microsoft/MicrosoftObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,17 @@
+package pdftk.org.bouncycastle.asn1.microsoft;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface MicrosoftObjectIdentifiers
+{
+ //
+ // Microsoft
+ // iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) microsoft(311)
+ //
+ static final ASN1ObjectIdentifier microsoft = new ASN1ObjectIdentifier("1.3.6.1.4.1.311");
+ static final ASN1ObjectIdentifier microsoftCertTemplateV1 = microsoft.branch("20.2");
+ static final ASN1ObjectIdentifier microsoftCaVersion = microsoft.branch("21.1");
+ static final ASN1ObjectIdentifier microsoftPrevCaCertHash = microsoft.branch("21.2");
+ static final ASN1ObjectIdentifier microsoftCertTemplateV2 = microsoft.branch("21.7");
+ static final ASN1ObjectIdentifier microsoftAppPolicies = microsoft.branch("21.10");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/CAST5CBCParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/CAST5CBCParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/CAST5CBCParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/CAST5CBCParameters.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,78 @@
+package pdftk.org.bouncycastle.asn1.misc;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class CAST5CBCParameters
+ extends ASN1Object
+{
+ ASN1Integer keyLength;
+ ASN1OctetString iv;
+
+ public static CAST5CBCParameters getInstance(
+ Object o)
+ {
+ if (o instanceof CAST5CBCParameters)
+ {
+ return (CAST5CBCParameters)o;
+ }
+ else if (o != null)
+ {
+ return new CAST5CBCParameters(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CAST5CBCParameters(
+ byte[] iv,
+ int keyLength)
+ {
+ this.iv = new DEROctetString(iv);
+ this.keyLength = new ASN1Integer(keyLength);
+ }
+
+ public CAST5CBCParameters(
+ ASN1Sequence seq)
+ {
+ iv = (ASN1OctetString)seq.getObjectAt(0);
+ keyLength = (ASN1Integer)seq.getObjectAt(1);
+ }
+
+ public byte[] getIV()
+ {
+ return iv.getOctets();
+ }
+
+ public int getKeyLength()
+ {
+ return keyLength.getValue().intValue();
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * cast5CBCParameters ::= SEQUENCE {
+ * iv OCTET STRING DEFAULT 0,
+ * -- Initialization vector
+ * keyLength INTEGER
+ * -- Key length, in bits
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(iv);
+ v.add(keyLength);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/IDEACBCPar.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/IDEACBCPar.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/IDEACBCPar.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/IDEACBCPar.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,81 @@
+package pdftk.org.bouncycastle.asn1.misc;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class IDEACBCPar
+ extends ASN1Object
+{
+ ASN1OctetString iv;
+
+ public static IDEACBCPar getInstance(
+ Object o)
+ {
+ if (o instanceof IDEACBCPar)
+ {
+ return (IDEACBCPar)o;
+ }
+ else if (o != null)
+ {
+ return new IDEACBCPar(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public IDEACBCPar(
+ byte[] iv)
+ {
+ this.iv = new DEROctetString(iv);
+ }
+
+ public IDEACBCPar(
+ ASN1Sequence seq)
+ {
+ if (seq.size() == 1)
+ {
+ iv = (ASN1OctetString)seq.getObjectAt(0);
+ }
+ else
+ {
+ iv = null;
+ }
+ }
+
+ public byte[] getIV()
+ {
+ if (iv != null)
+ {
+ return iv.getOctets();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * IDEA-CBCPar ::= SEQUENCE {
+ * iv OCTET STRING OPTIONAL -- exactly 8 octets
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (iv != null)
+ {
+ v.add(iv);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/MiscObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,47 @@
+package pdftk.org.bouncycastle.asn1.misc;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface MiscObjectIdentifiers
+{
+ //
+ // Netscape
+ // iso/itu(2) joint-assign(16) us(840) uscompany(1) netscape(113730) cert-extensions(1) }
+ //
+ static final ASN1ObjectIdentifier netscape = new ASN1ObjectIdentifier("2.16.840.1.113730.1");
+ static final ASN1ObjectIdentifier netscapeCertType = netscape.branch("1");
+ static final ASN1ObjectIdentifier netscapeBaseURL = netscape.branch("2");
+ static final ASN1ObjectIdentifier netscapeRevocationURL = netscape.branch("3");
+ static final ASN1ObjectIdentifier netscapeCARevocationURL = netscape.branch("4");
+ static final ASN1ObjectIdentifier netscapeRenewalURL = netscape.branch("7");
+ static final ASN1ObjectIdentifier netscapeCApolicyURL = netscape.branch("8");
+ static final ASN1ObjectIdentifier netscapeSSLServerName = netscape.branch("12");
+ static final ASN1ObjectIdentifier netscapeCertComment = netscape.branch("13");
+
+ //
+ // Verisign
+ // iso/itu(2) joint-assign(16) us(840) uscompany(1) verisign(113733) cert-extensions(1) }
+ //
+ static final ASN1ObjectIdentifier verisign = new ASN1ObjectIdentifier("2.16.840.1.113733.1");
+
+ //
+ // CZAG - country, zip, age, and gender
+ //
+ static final ASN1ObjectIdentifier verisignCzagExtension = verisign.branch("6.3");
+ // D&B D-U-N-S number
+ static final ASN1ObjectIdentifier verisignDnbDunsNumber = verisign.branch("6.15");
+
+ //
+ // Novell
+ // iso/itu(2) country(16) us(840) organization(1) novell(113719)
+ //
+ static final ASN1ObjectIdentifier novell = new ASN1ObjectIdentifier("2.16.840.1.113719");
+ static final ASN1ObjectIdentifier novellSecurityAttribs = novell.branch("1.9.4.1");
+
+ //
+ // Entrust
+ // iso(1) member-body(16) us(840) nortelnetworks(113533) entrust(7)
+ //
+ static final ASN1ObjectIdentifier entrust = new ASN1ObjectIdentifier("1.2.840.113533.7");
+ static final ASN1ObjectIdentifier entrustVersionExtension = entrust.branch("65.0");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/NetscapeCertType.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/NetscapeCertType.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/NetscapeCertType.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/NetscapeCertType.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,54 @@
+package pdftk.org.bouncycastle.asn1.misc;
+
+import pdftk.org.bouncycastle.asn1.DERBitString;
+
+/**
+ * The NetscapeCertType object.
+ *
+ * NetscapeCertType ::= BIT STRING {
+ * SSLClient (0),
+ * SSLServer (1),
+ * S/MIME (2),
+ * Object Signing (3),
+ * Reserved (4),
+ * SSL CA (5),
+ * S/MIME CA (6),
+ * Object Signing CA (7) }
+ *
+ */
+public class NetscapeCertType
+ extends DERBitString
+{
+ public static final int sslClient = (1 << 7);
+ public static final int sslServer = (1 << 6);
+ public static final int smime = (1 << 5);
+ public static final int objectSigning = (1 << 4);
+ public static final int reserved = (1 << 3);
+ public static final int sslCA = (1 << 2);
+ public static final int smimeCA = (1 << 1);
+ public static final int objectSigningCA = (1 << 0);
+
+ /**
+ * Basic constructor.
+ *
+ * @param usage - the bitwise OR of the Key Usage flags giving the
+ * allowed uses for the key.
+ * e.g. (X509NetscapeCertType.sslCA | X509NetscapeCertType.smimeCA)
+ */
+ public NetscapeCertType(
+ int usage)
+ {
+ super(getBytes(usage), getPadBits(usage));
+ }
+
+ public NetscapeCertType(
+ DERBitString usage)
+ {
+ super(usage.getBytes(), usage.getPadBits());
+ }
+
+ public String toString()
+ {
+ return "NetscapeCertType: 0x" + Integer.toHexString(data[0] & 0xff);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/NetscapeRevocationURL.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/NetscapeRevocationURL.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/NetscapeRevocationURL.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/NetscapeRevocationURL.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.asn1.misc;
+
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+
+public class NetscapeRevocationURL
+ extends DERIA5String
+{
+ public NetscapeRevocationURL(
+ DERIA5String str)
+ {
+ super(str.getString());
+ }
+
+ public String toString()
+ {
+ return "NetscapeRevocationURL: " + this.getString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/VerisignCzagExtension.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/VerisignCzagExtension.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/VerisignCzagExtension.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/VerisignCzagExtension.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.asn1.misc;
+
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+
+public class VerisignCzagExtension
+ extends DERIA5String
+{
+ public VerisignCzagExtension(
+ DERIA5String str)
+ {
+ super(str.getString());
+ }
+
+ public String toString()
+ {
+ return "VerisignCzagExtension: " + this.getString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/misc/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/misc/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Miscellaneous object identifiers and objects.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/mozilla/PublicKeyAndChallenge.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/mozilla/PublicKeyAndChallenge.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/mozilla/PublicKeyAndChallenge.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/mozilla/PublicKeyAndChallenge.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,63 @@
+package pdftk.org.bouncycastle.asn1.mozilla;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+import pdftk.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+
+/**
+ * This is designed to parse
+ * the PublicKeyAndChallenge created by the KEYGEN tag included by
+ * Mozilla based browsers.
+ *
+ * PublicKeyAndChallenge ::= SEQUENCE {
+ * spki SubjectPublicKeyInfo,
+ * challenge IA5STRING
+ * }
+ *
+ *
+ */
+public class PublicKeyAndChallenge
+ extends ASN1Object
+{
+ private ASN1Sequence pkacSeq;
+ private SubjectPublicKeyInfo spki;
+ private DERIA5String challenge;
+
+ public static PublicKeyAndChallenge getInstance(Object obj)
+ {
+ if (obj instanceof PublicKeyAndChallenge)
+ {
+ return (PublicKeyAndChallenge)obj;
+ }
+ else if (obj != null)
+ {
+ return new PublicKeyAndChallenge(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private PublicKeyAndChallenge(ASN1Sequence seq)
+ {
+ pkacSeq = seq;
+ spki = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(0));
+ challenge = DERIA5String.getInstance(seq.getObjectAt(1));
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return pkacSeq;
+ }
+
+ public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
+ {
+ return spki;
+ }
+
+ public DERIA5String getChallenge()
+ {
+ return challenge;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/mozilla/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/mozilla/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/mozilla/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/mozilla/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes useful for encoding objects used by mozilla.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/nist/NISTNamedCurves.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/nist/NISTNamedCurves.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/nist/NISTNamedCurves.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/nist/NISTNamedCurves.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,96 @@
+package pdftk.org.bouncycastle.asn1.nist;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.sec.SECNamedCurves;
+import pdftk.org.bouncycastle.asn1.sec.SECObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.x9.X9ECParameters;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * Utility class for fetching curves using their NIST names as published in FIPS-PUB 186-2
+ */
+public class NISTNamedCurves
+{
+ static final Hashtable objIds = new Hashtable();
+ static final Hashtable names = new Hashtable();
+
+ static void defineCurve(String name, ASN1ObjectIdentifier oid)
+ {
+ objIds.put(name, oid);
+ names.put(oid, name);
+ }
+
+ static
+ {
+ // TODO Missing the "K-" curves
+
+ defineCurve("B-571", SECObjectIdentifiers.sect571r1);
+ defineCurve("B-409", SECObjectIdentifiers.sect409r1);
+ defineCurve("B-283", SECObjectIdentifiers.sect283r1);
+ defineCurve("B-233", SECObjectIdentifiers.sect233r1);
+ defineCurve("B-163", SECObjectIdentifiers.sect163r2);
+ defineCurve("P-521", SECObjectIdentifiers.secp521r1);
+ defineCurve("P-384", SECObjectIdentifiers.secp384r1);
+ defineCurve("P-256", SECObjectIdentifiers.secp256r1);
+ defineCurve("P-224", SECObjectIdentifiers.secp224r1);
+ defineCurve("P-192", SECObjectIdentifiers.secp192r1);
+ }
+
+ public static X9ECParameters getByName(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toUpperCase(name));
+
+ if (oid != null)
+ {
+ return getByOID(oid);
+ }
+
+ return null;
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ return SECNamedCurves.getByOID(oid);
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static ASN1ObjectIdentifier getOID(
+ String name)
+ {
+ return (ASN1ObjectIdentifier)objIds.get(Strings.toUpperCase(name));
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static String getName(
+ ASN1ObjectIdentifier oid)
+ {
+ return (String)names.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return objIds.keys();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/nist/NISTObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,56 @@
+package pdftk.org.bouncycastle.asn1.nist;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface NISTObjectIdentifiers
+{
+ //
+ // NIST
+ // iso/itu(2) joint-assign(16) us(840) organization(1) gov(101) csor(3)
+
+ //
+ // nistalgorithms(4)
+ //
+ static final ASN1ObjectIdentifier nistAlgorithm = new ASN1ObjectIdentifier("2.16.840.1.101.3.4");
+
+ static final ASN1ObjectIdentifier id_sha256 = nistAlgorithm.branch("2.1");
+ static final ASN1ObjectIdentifier id_sha384 = nistAlgorithm.branch("2.2");
+ static final ASN1ObjectIdentifier id_sha512 = nistAlgorithm.branch("2.3");
+ static final ASN1ObjectIdentifier id_sha224 = nistAlgorithm.branch("2.4");
+
+ static final ASN1ObjectIdentifier aes = nistAlgorithm.branch("1");
+
+ static final ASN1ObjectIdentifier id_aes128_ECB = aes.branch("1");
+ static final ASN1ObjectIdentifier id_aes128_CBC = aes.branch("2");
+ static final ASN1ObjectIdentifier id_aes128_OFB = aes.branch("3");
+ static final ASN1ObjectIdentifier id_aes128_CFB = aes.branch("4");
+ static final ASN1ObjectIdentifier id_aes128_wrap = aes.branch("5");
+ static final ASN1ObjectIdentifier id_aes128_GCM = aes.branch("6");
+ static final ASN1ObjectIdentifier id_aes128_CCM = aes.branch("7");
+
+ static final ASN1ObjectIdentifier id_aes192_ECB = aes.branch("21");
+ static final ASN1ObjectIdentifier id_aes192_CBC = aes.branch("22");
+ static final ASN1ObjectIdentifier id_aes192_OFB = aes.branch("23");
+ static final ASN1ObjectIdentifier id_aes192_CFB = aes.branch("24");
+ static final ASN1ObjectIdentifier id_aes192_wrap = aes.branch("25");
+ static final ASN1ObjectIdentifier id_aes192_GCM = aes.branch("26");
+ static final ASN1ObjectIdentifier id_aes192_CCM = aes.branch("27");
+
+ static final ASN1ObjectIdentifier id_aes256_ECB = aes.branch("41");
+ static final ASN1ObjectIdentifier id_aes256_CBC = aes.branch("42");
+ static final ASN1ObjectIdentifier id_aes256_OFB = aes.branch("43");
+ static final ASN1ObjectIdentifier id_aes256_CFB = aes.branch("44");
+ static final ASN1ObjectIdentifier id_aes256_wrap = aes.branch("45");
+ static final ASN1ObjectIdentifier id_aes256_GCM = aes.branch("46");
+ static final ASN1ObjectIdentifier id_aes256_CCM = aes.branch("47");
+
+ //
+ // signatures
+ //
+ static final ASN1ObjectIdentifier id_dsa_with_sha2 = nistAlgorithm.branch("3");
+
+ static final ASN1ObjectIdentifier dsa_with_sha224 = id_dsa_with_sha2.branch("1");
+ static final ASN1ObjectIdentifier dsa_with_sha256 = id_dsa_with_sha2.branch("2");
+ static final ASN1ObjectIdentifier dsa_with_sha384 = id_dsa_with_sha2.branch("3");
+ static final ASN1ObjectIdentifier dsa_with_sha512 = id_dsa_with_sha2.branch("4");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/nist/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/nist/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/nist/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/nist/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes for NIST related objects.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,17 @@
+package pdftk.org.bouncycastle.asn1.ntt;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * From RFC 3657
+ */
+public interface NTTObjectIdentifiers
+{
+ public static final ASN1ObjectIdentifier id_camellia128_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.2");
+ public static final ASN1ObjectIdentifier id_camellia192_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.3");
+ public static final ASN1ObjectIdentifier id_camellia256_cbc = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.1.4");
+
+ public static final ASN1ObjectIdentifier id_camellia128_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.2");
+ public static final ASN1ObjectIdentifier id_camellia192_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.3");
+ public static final ASN1ObjectIdentifier id_camellia256_wrap = new ASN1ObjectIdentifier("1.2.392.200011.61.1.1.3.4");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/BasicOCSPResponse.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/BasicOCSPResponse.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/BasicOCSPResponse.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/BasicOCSPResponse.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,112 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class BasicOCSPResponse
+ extends ASN1Object
+{
+ private ResponseData tbsResponseData;
+ private AlgorithmIdentifier signatureAlgorithm;
+ private DERBitString signature;
+ private ASN1Sequence certs;
+
+ public BasicOCSPResponse(
+ ResponseData tbsResponseData,
+ AlgorithmIdentifier signatureAlgorithm,
+ DERBitString signature,
+ ASN1Sequence certs)
+ {
+ this.tbsResponseData = tbsResponseData;
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.signature = signature;
+ this.certs = certs;
+ }
+
+ private BasicOCSPResponse(
+ ASN1Sequence seq)
+ {
+ this.tbsResponseData = ResponseData.getInstance(seq.getObjectAt(0));
+ this.signatureAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ this.signature = (DERBitString)seq.getObjectAt(2);
+
+ if (seq.size() > 3)
+ {
+ this.certs = ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(3), true);
+ }
+ }
+
+ public static BasicOCSPResponse getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static BasicOCSPResponse getInstance(
+ Object obj)
+ {
+ if (obj instanceof BasicOCSPResponse)
+ {
+ return (BasicOCSPResponse)obj;
+ }
+ else if (obj != null)
+ {
+ return new BasicOCSPResponse(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ResponseData getTbsResponseData()
+ {
+ return tbsResponseData;
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return signatureAlgorithm;
+ }
+
+ public DERBitString getSignature()
+ {
+ return signature;
+ }
+
+ public ASN1Sequence getCerts()
+ {
+ return certs;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * BasicOCSPResponse ::= SEQUENCE {
+ * tbsResponseData ResponseData,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(tbsResponseData);
+ v.add(signatureAlgorithm);
+ v.add(signature);
+ if (certs != null)
+ {
+ v.add(new DERTaggedObject(true, 0, certs));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/CertID.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/CertID.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/CertID.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/CertID.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,105 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class CertID
+ extends ASN1Object
+{
+ AlgorithmIdentifier hashAlgorithm;
+ ASN1OctetString issuerNameHash;
+ ASN1OctetString issuerKeyHash;
+ ASN1Integer serialNumber;
+
+ public CertID(
+ AlgorithmIdentifier hashAlgorithm,
+ ASN1OctetString issuerNameHash,
+ ASN1OctetString issuerKeyHash,
+ ASN1Integer serialNumber)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.issuerNameHash = issuerNameHash;
+ this.issuerKeyHash = issuerKeyHash;
+ this.serialNumber = serialNumber;
+ }
+
+ private CertID(
+ ASN1Sequence seq)
+ {
+ hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ issuerNameHash = (ASN1OctetString)seq.getObjectAt(1);
+ issuerKeyHash = (ASN1OctetString)seq.getObjectAt(2);
+ serialNumber = (ASN1Integer)seq.getObjectAt(3);
+ }
+
+ public static CertID getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static CertID getInstance(
+ Object obj)
+ {
+ if (obj instanceof CertID)
+ {
+ return (CertID)obj;
+ }
+ else if (obj != null)
+ {
+ return new CertID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public ASN1OctetString getIssuerNameHash()
+ {
+ return issuerNameHash;
+ }
+
+ public ASN1OctetString getIssuerKeyHash()
+ {
+ return issuerKeyHash;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * CertID ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * issuerNameHash OCTET STRING, -- Hash of Issuer's DN
+ * issuerKeyHash OCTET STRING, -- Hash of Issuers public key
+ * serialNumber CertificateSerialNumber }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(hashAlgorithm);
+ v.add(issuerNameHash);
+ v.add(issuerKeyHash);
+ v.add(serialNumber);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/CertStatus.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/CertStatus.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/CertStatus.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/CertStatus.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,105 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERNull;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class CertStatus
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private int tagNo;
+ private ASN1Encodable value;
+
+ /**
+ * create a CertStatus object with a tag of zero.
+ */
+ public CertStatus()
+ {
+ tagNo = 0;
+ value = DERNull.INSTANCE;
+ }
+
+ public CertStatus(
+ RevokedInfo info)
+ {
+ tagNo = 1;
+ value = info;
+ }
+
+ public CertStatus(
+ int tagNo,
+ ASN1Encodable value)
+ {
+ this.tagNo = tagNo;
+ this.value = value;
+ }
+
+ public CertStatus(
+ ASN1TaggedObject choice)
+ {
+ this.tagNo = choice.getTagNo();
+
+ switch (choice.getTagNo())
+ {
+ case 0:
+ value = DERNull.INSTANCE;
+ break;
+ case 1:
+ value = RevokedInfo.getInstance(choice, false);
+ break;
+ case 2:
+ value = DERNull.INSTANCE;
+ }
+ }
+
+ public static CertStatus getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof CertStatus)
+ {
+ return (CertStatus)obj;
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new CertStatus((ASN1TaggedObject)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public static CertStatus getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ public int getTagNo()
+ {
+ return tagNo;
+ }
+
+ public ASN1Encodable getStatus()
+ {
+ return value;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * CertStatus ::= CHOICE {
+ * good [0] IMPLICIT NULL,
+ * revoked [1] IMPLICIT RevokedInfo,
+ * unknown [2] IMPLICIT UnknownInfo }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(false, tagNo, value);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/CrlID.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/CrlID.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/CrlID.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/CrlID.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,111 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERGeneralizedTime;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class CrlID
+ extends ASN1Object
+{
+ private DERIA5String crlUrl;
+ private ASN1Integer crlNum;
+ private ASN1GeneralizedTime crlTime;
+
+ private CrlID(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)e.nextElement();
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ crlUrl = DERIA5String.getInstance(o, true);
+ break;
+ case 1:
+ crlNum = ASN1Integer.getInstance(o, true);
+ break;
+ case 2:
+ crlTime = DERGeneralizedTime.getInstance(o, true);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "unknown tag number: " + o.getTagNo());
+ }
+ }
+ }
+
+ public static CrlID getInstance(
+ Object obj)
+ {
+ if (obj instanceof CrlID)
+ {
+ return (CrlID)obj;
+ }
+ else if (obj != null)
+ {
+ return new CrlID(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public DERIA5String getCrlUrl()
+ {
+ return crlUrl;
+ }
+
+ public ASN1Integer getCrlNum()
+ {
+ return crlNum;
+ }
+
+ public ASN1GeneralizedTime getCrlTime()
+ {
+ return crlTime;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * CrlID ::= SEQUENCE {
+ * crlUrl [0] EXPLICIT IA5String OPTIONAL,
+ * crlNum [1] EXPLICIT INTEGER OPTIONAL,
+ * crlTime [2] EXPLICIT GeneralizedTime OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (crlUrl != null)
+ {
+ v.add(new DERTaggedObject(true, 0, crlUrl));
+ }
+
+ if (crlNum != null)
+ {
+ v.add(new DERTaggedObject(true, 1, crlNum));
+ }
+
+ if (crlTime != null)
+ {
+ v.add(new DERTaggedObject(true, 2, crlTime));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,22 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface OCSPObjectIdentifiers
+{
+ public static final String pkix_ocsp = "1.3.6.1.5.5.7.48.1";
+
+ public static final ASN1ObjectIdentifier id_pkix_ocsp = new ASN1ObjectIdentifier(pkix_ocsp);
+ public static final ASN1ObjectIdentifier id_pkix_ocsp_basic = new ASN1ObjectIdentifier(pkix_ocsp + ".1");
+
+ //
+ // extensions
+ //
+ public static final ASN1ObjectIdentifier id_pkix_ocsp_nonce = new ASN1ObjectIdentifier(pkix_ocsp + ".2");
+ public static final ASN1ObjectIdentifier id_pkix_ocsp_crl = new ASN1ObjectIdentifier(pkix_ocsp + ".3");
+
+ public static final ASN1ObjectIdentifier id_pkix_ocsp_response = new ASN1ObjectIdentifier(pkix_ocsp + ".4");
+ public static final ASN1ObjectIdentifier id_pkix_ocsp_nocheck = new ASN1ObjectIdentifier(pkix_ocsp + ".5");
+ public static final ASN1ObjectIdentifier id_pkix_ocsp_archive_cutoff = new ASN1ObjectIdentifier(pkix_ocsp + ".6");
+ public static final ASN1ObjectIdentifier id_pkix_ocsp_service_locator = new ASN1ObjectIdentifier(pkix_ocsp + ".7");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPRequest.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPRequest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPRequest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPRequest.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,90 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class OCSPRequest
+ extends ASN1Object
+{
+ TBSRequest tbsRequest;
+ Signature optionalSignature;
+
+ public OCSPRequest(
+ TBSRequest tbsRequest,
+ Signature optionalSignature)
+ {
+ this.tbsRequest = tbsRequest;
+ this.optionalSignature = optionalSignature;
+ }
+
+ private OCSPRequest(
+ ASN1Sequence seq)
+ {
+ tbsRequest = TBSRequest.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() == 2)
+ {
+ optionalSignature = Signature.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(1), true);
+ }
+ }
+
+ public static OCSPRequest getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static OCSPRequest getInstance(
+ Object obj)
+ {
+ if (obj instanceof OCSPRequest)
+ {
+ return (OCSPRequest)obj;
+ }
+ else if (obj != null)
+ {
+ return new OCSPRequest(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public TBSRequest getTbsRequest()
+ {
+ return tbsRequest;
+ }
+
+ public Signature getOptionalSignature()
+ {
+ return optionalSignature;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * OCSPRequest ::= SEQUENCE {
+ * tbsRequest TBSRequest,
+ * optionalSignature [0] EXPLICIT Signature OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(tbsRequest);
+
+ if (optionalSignature != null)
+ {
+ v.add(new DERTaggedObject(true, 0, optionalSignature));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPResponse.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPResponse.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPResponse.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPResponse.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,90 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class OCSPResponse
+ extends ASN1Object
+{
+ OCSPResponseStatus responseStatus;
+ ResponseBytes responseBytes;
+
+ public OCSPResponse(
+ OCSPResponseStatus responseStatus,
+ ResponseBytes responseBytes)
+ {
+ this.responseStatus = responseStatus;
+ this.responseBytes = responseBytes;
+ }
+
+ private OCSPResponse(
+ ASN1Sequence seq)
+ {
+ responseStatus = OCSPResponseStatus.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() == 2)
+ {
+ responseBytes = ResponseBytes.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(1), true);
+ }
+ }
+
+ public static OCSPResponse getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static OCSPResponse getInstance(
+ Object obj)
+ {
+ if (obj instanceof OCSPResponse)
+ {
+ return (OCSPResponse)obj;
+ }
+ else if (obj != null)
+ {
+ return new OCSPResponse(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public OCSPResponseStatus getResponseStatus()
+ {
+ return responseStatus;
+ }
+
+ public ResponseBytes getResponseBytes()
+ {
+ return responseBytes;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * OCSPResponse ::= SEQUENCE {
+ * responseStatus OCSPResponseStatus,
+ * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(responseStatus);
+
+ if (responseBytes != null)
+ {
+ v.add(new DERTaggedObject(true, 0, responseBytes));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPResponseStatus.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPResponseStatus.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPResponseStatus.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/OCSPResponseStatus.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,71 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1Enumerated;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+
+public class OCSPResponseStatus
+ extends ASN1Object
+{
+ public static final int SUCCESSFUL = 0;
+ public static final int MALFORMED_REQUEST = 1;
+ public static final int INTERNAL_ERROR = 2;
+ public static final int TRY_LATER = 3;
+ public static final int SIG_REQUIRED = 5;
+ public static final int UNAUTHORIZED = 6;
+
+ private ASN1Enumerated value;
+
+ /**
+ * The OCSPResponseStatus enumeration.
+ *
+ * OCSPResponseStatus ::= ENUMERATED {
+ * successful (0), --Response has valid confirmations
+ * malformedRequest (1), --Illegal confirmation request
+ * internalError (2), --Internal error in issuer
+ * tryLater (3), --Try again later
+ * --(4) is not used
+ * sigRequired (5), --Must sign the request
+ * unauthorized (6) --Request unauthorized
+ * }
+ *
+ */
+ public OCSPResponseStatus(
+ int value)
+ {
+ this(new ASN1Enumerated(value));
+ }
+
+ private OCSPResponseStatus(
+ ASN1Enumerated value)
+ {
+ this.value = value;
+ }
+
+ public static OCSPResponseStatus getInstance(
+ Object obj)
+ {
+ if (obj instanceof OCSPResponseStatus)
+ {
+ return (OCSPResponseStatus)obj;
+ }
+ else if (obj != null)
+ {
+ return new OCSPResponseStatus(ASN1Enumerated.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public BigInteger getValue()
+ {
+ return value.getValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return value;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/Request.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/Request.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/Request.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/Request.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,91 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.Extensions;
+
+public class Request
+ extends ASN1Object
+{
+ CertID reqCert;
+ Extensions singleRequestExtensions;
+
+ public Request(
+ CertID reqCert,
+ Extensions singleRequestExtensions)
+ {
+ this.reqCert = reqCert;
+ this.singleRequestExtensions = singleRequestExtensions;
+ }
+
+ private Request(
+ ASN1Sequence seq)
+ {
+ reqCert = CertID.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() == 2)
+ {
+ singleRequestExtensions = Extensions.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(1), true);
+ }
+ }
+
+ public static Request getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static Request getInstance(
+ Object obj)
+ {
+ if (obj instanceof Request)
+ {
+ return (Request)obj;
+ }
+ else if (obj != null)
+ {
+ return new Request(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public CertID getReqCert()
+ {
+ return reqCert;
+ }
+
+ public Extensions getSingleRequestExtensions()
+ {
+ return singleRequestExtensions;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Request ::= SEQUENCE {
+ * reqCert CertID,
+ * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(reqCert);
+
+ if (singleRequestExtensions != null)
+ {
+ v.add(new DERTaggedObject(true, 0, singleRequestExtensions));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/ResponderID.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/ResponderID.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/ResponderID.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/ResponderID.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,104 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+
+public class ResponderID
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private ASN1Encodable value;
+
+ public ResponderID(
+ ASN1OctetString value)
+ {
+ this.value = value;
+ }
+
+ public ResponderID(
+ X500Name value)
+ {
+ this.value = value;
+ }
+
+ public static ResponderID getInstance(
+ Object obj)
+ {
+ if (obj instanceof ResponderID)
+ {
+ return (ResponderID)obj;
+ }
+ else if (obj instanceof DEROctetString)
+ {
+ return new ResponderID((DEROctetString)obj);
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)obj;
+
+ if (o.getTagNo() == 1)
+ {
+ return new ResponderID(X500Name.getInstance(o, true));
+ }
+ else
+ {
+ return new ResponderID(ASN1OctetString.getInstance(o, true));
+ }
+ }
+
+ return new ResponderID(X500Name.getInstance(obj));
+ }
+
+ public static ResponderID getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ public byte[] getKeyHash()
+ {
+ if (this.value instanceof ASN1OctetString)
+ {
+ ASN1OctetString octetString = (ASN1OctetString)this.value;
+ return octetString.getOctets();
+ }
+
+ return null;
+ }
+
+ public X500Name getName()
+ {
+ if (this.value instanceof ASN1OctetString)
+ {
+ return null;
+ }
+
+ return X500Name.getInstance(value);
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * ResponderID ::= CHOICE {
+ * byName [1] Name,
+ * byKey [2] KeyHash }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (value instanceof ASN1OctetString)
+ {
+ return new DERTaggedObject(true, 2, value);
+ }
+
+ return new DERTaggedObject(true, 1, value);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/ResponseBytes.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/ResponseBytes.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/ResponseBytes.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/ResponseBytes.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,82 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class ResponseBytes
+ extends ASN1Object
+{
+ ASN1ObjectIdentifier responseType;
+ ASN1OctetString response;
+
+ public ResponseBytes(
+ ASN1ObjectIdentifier responseType,
+ ASN1OctetString response)
+ {
+ this.responseType = responseType;
+ this.response = response;
+ }
+
+ public ResponseBytes(
+ ASN1Sequence seq)
+ {
+ responseType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ response = (ASN1OctetString)seq.getObjectAt(1);
+ }
+
+ public static ResponseBytes getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static ResponseBytes getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof ResponseBytes)
+ {
+ return (ResponseBytes)obj;
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new ResponseBytes((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public ASN1ObjectIdentifier getResponseType()
+ {
+ return responseType;
+ }
+
+ public ASN1OctetString getResponse()
+ {
+ return response;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * ResponseBytes ::= SEQUENCE {
+ * responseType OBJECT IDENTIFIER,
+ * response OCTET STRING }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(responseType);
+ v.add(response);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/ResponseData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/ResponseData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/ResponseData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/ResponseData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,182 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERGeneralizedTime;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.Extensions;
+import pdftk.org.bouncycastle.asn1.x509.X509Extensions;
+
+public class ResponseData
+ extends ASN1Object
+{
+ private static final ASN1Integer V1 = new ASN1Integer(0);
+
+ private boolean versionPresent;
+
+ private ASN1Integer version;
+ private ResponderID responderID;
+ private ASN1GeneralizedTime producedAt;
+ private ASN1Sequence responses;
+ private Extensions responseExtensions;
+
+ public ResponseData(
+ ASN1Integer version,
+ ResponderID responderID,
+ ASN1GeneralizedTime producedAt,
+ ASN1Sequence responses,
+ Extensions responseExtensions)
+ {
+ this.version = version;
+ this.responderID = responderID;
+ this.producedAt = producedAt;
+ this.responses = responses;
+ this.responseExtensions = responseExtensions;
+ }
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param responderID
+ * @param producedAt
+ * @param responses
+ * @param responseExtensions
+ */
+ public ResponseData(
+ ResponderID responderID,
+ DERGeneralizedTime producedAt,
+ ASN1Sequence responses,
+ X509Extensions responseExtensions)
+ {
+ this(V1, responderID, ASN1GeneralizedTime.getInstance(producedAt), responses, Extensions.getInstance(responseExtensions));
+ }
+
+ public ResponseData(
+ ResponderID responderID,
+ ASN1GeneralizedTime producedAt,
+ ASN1Sequence responses,
+ Extensions responseExtensions)
+ {
+ this(V1, responderID, producedAt, responses, responseExtensions);
+ }
+
+ private ResponseData(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.getObjectAt(0) instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(0);
+
+ if (o.getTagNo() == 0)
+ {
+ this.versionPresent = true;
+ this.version = ASN1Integer.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(0), true);
+ index++;
+ }
+ else
+ {
+ this.version = V1;
+ }
+ }
+ else
+ {
+ this.version = V1;
+ }
+
+ this.responderID = ResponderID.getInstance(seq.getObjectAt(index++));
+ this.producedAt = ASN1GeneralizedTime.getInstance(seq.getObjectAt(index++));
+ this.responses = (ASN1Sequence)seq.getObjectAt(index++);
+
+ if (seq.size() > index)
+ {
+ this.responseExtensions = Extensions.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(index), true);
+ }
+ }
+
+ public static ResponseData getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static ResponseData getInstance(
+ Object obj)
+ {
+ if (obj instanceof ResponseData)
+ {
+ return (ResponseData)obj;
+ }
+ else if (obj != null)
+ {
+ return new ResponseData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public ResponderID getResponderID()
+ {
+ return responderID;
+ }
+
+ public ASN1GeneralizedTime getProducedAt()
+ {
+ return producedAt;
+ }
+
+ public ASN1Sequence getResponses()
+ {
+ return responses;
+ }
+
+ public Extensions getResponseExtensions()
+ {
+ return responseExtensions;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * ResponseData ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * responderID ResponderID,
+ * producedAt GeneralizedTime,
+ * responses SEQUENCE OF SingleResponse,
+ * responseExtensions [1] EXPLICIT Extensions OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (versionPresent || !version.equals(V1))
+ {
+ v.add(new DERTaggedObject(true, 0, version));
+ }
+
+ v.add(responderID);
+ v.add(producedAt);
+ v.add(responses);
+ if (responseExtensions != null)
+ {
+ v.add(new DERTaggedObject(true, 1, responseExtensions));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/RevokedInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/RevokedInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/RevokedInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/RevokedInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,92 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEREnumerated;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.CRLReason;
+
+public class RevokedInfo
+ extends ASN1Object
+{
+ private ASN1GeneralizedTime revocationTime;
+ private CRLReason revocationReason;
+
+ public RevokedInfo(
+ ASN1GeneralizedTime revocationTime,
+ CRLReason revocationReason)
+ {
+ this.revocationTime = revocationTime;
+ this.revocationReason = revocationReason;
+ }
+
+ private RevokedInfo(
+ ASN1Sequence seq)
+ {
+ this.revocationTime = ASN1GeneralizedTime.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ this.revocationReason = CRLReason.getInstance(DEREnumerated.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(1), true));
+ }
+ }
+
+ public static RevokedInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static RevokedInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof RevokedInfo)
+ {
+ return (RevokedInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new RevokedInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1GeneralizedTime getRevocationTime()
+ {
+ return revocationTime;
+ }
+
+ public CRLReason getRevocationReason()
+ {
+ return revocationReason;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * RevokedInfo ::= SEQUENCE {
+ * revocationTime GeneralizedTime,
+ * revocationReason [0] EXPLICIT CRLReason OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(revocationTime);
+ if (revocationReason != null)
+ {
+ v.add(new DERTaggedObject(true, 0, revocationReason));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/ServiceLocator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/ServiceLocator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/ServiceLocator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/ServiceLocator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,36 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+
+public class ServiceLocator
+ extends ASN1Object
+{
+ X500Name issuer;
+ ASN1Primitive locator;
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * ServiceLocator ::= SEQUENCE {
+ * issuer Name,
+ * locator AuthorityInfoAccessSyntax OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(issuer);
+
+ if (locator != null)
+ {
+ v.add(locator);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/Signature.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/Signature.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/Signature.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/Signature.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,111 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class Signature
+ extends ASN1Object
+{
+ AlgorithmIdentifier signatureAlgorithm;
+ DERBitString signature;
+ ASN1Sequence certs;
+
+ public Signature(
+ AlgorithmIdentifier signatureAlgorithm,
+ DERBitString signature)
+ {
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.signature = signature;
+ }
+
+ public Signature(
+ AlgorithmIdentifier signatureAlgorithm,
+ DERBitString signature,
+ ASN1Sequence certs)
+ {
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.signature = signature;
+ this.certs = certs;
+ }
+
+ private Signature(
+ ASN1Sequence seq)
+ {
+ signatureAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ signature = (DERBitString)seq.getObjectAt(1);
+
+ if (seq.size() == 3)
+ {
+ certs = ASN1Sequence.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(2), true);
+ }
+ }
+
+ public static Signature getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static Signature getInstance(
+ Object obj)
+ {
+ if (obj instanceof Signature)
+ {
+ return (Signature)obj;
+ }
+ else if (obj != null)
+ {
+ return new Signature(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return signatureAlgorithm;
+ }
+
+ public DERBitString getSignature()
+ {
+ return signature;
+ }
+
+ public ASN1Sequence getCerts()
+ {
+ return certs;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Signature ::= SEQUENCE {
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL}
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(signatureAlgorithm);
+ v.add(signature);
+
+ if (certs != null)
+ {
+ v.add(new DERTaggedObject(true, 0, certs));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/SingleResponse.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/SingleResponse.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/SingleResponse.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/SingleResponse.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,181 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERGeneralizedTime;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.Extensions;
+import pdftk.org.bouncycastle.asn1.x509.X509Extensions;
+
+public class SingleResponse
+ extends ASN1Object
+{
+ private CertID certID;
+ private CertStatus certStatus;
+ private ASN1GeneralizedTime thisUpdate;
+ private ASN1GeneralizedTime nextUpdate;
+ private Extensions singleExtensions;
+
+ /**
+ * @deprecated use method taking ASN1GeneralizedTime and Extensions
+ * @param certID
+ * @param certStatus
+ * @param thisUpdate
+ * @param nextUpdate
+ * @param singleExtensions
+ */
+ public SingleResponse(
+ CertID certID,
+ CertStatus certStatus,
+ DERGeneralizedTime thisUpdate,
+ DERGeneralizedTime nextUpdate,
+ X509Extensions singleExtensions)
+ {
+ this(certID, certStatus, thisUpdate, nextUpdate, Extensions.getInstance(singleExtensions));
+ }
+
+ /**
+ * @deprecated use method taking ASN1GeneralizedTime and Extensions
+ * @param certID
+ * @param certStatus
+ * @param thisUpdate
+ * @param nextUpdate
+ * @param singleExtensions
+ */
+ public SingleResponse(
+ CertID certID,
+ CertStatus certStatus,
+ DERGeneralizedTime thisUpdate,
+ DERGeneralizedTime nextUpdate,
+ Extensions singleExtensions)
+ {
+ this(certID, certStatus, ASN1GeneralizedTime.getInstance(thisUpdate), ASN1GeneralizedTime.getInstance(nextUpdate), Extensions.getInstance(singleExtensions));
+ }
+
+ public SingleResponse(
+ CertID certID,
+ CertStatus certStatus,
+ ASN1GeneralizedTime thisUpdate,
+ ASN1GeneralizedTime nextUpdate,
+ Extensions singleExtensions)
+ {
+ this.certID = certID;
+ this.certStatus = certStatus;
+ this.thisUpdate = thisUpdate;
+ this.nextUpdate = nextUpdate;
+ this.singleExtensions = singleExtensions;
+ }
+
+ private SingleResponse(
+ ASN1Sequence seq)
+ {
+ this.certID = CertID.getInstance(seq.getObjectAt(0));
+ this.certStatus = CertStatus.getInstance(seq.getObjectAt(1));
+ this.thisUpdate = ASN1GeneralizedTime.getInstance(seq.getObjectAt(2));
+
+ if (seq.size() > 4)
+ {
+ this.nextUpdate = ASN1GeneralizedTime.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(3), true);
+ this.singleExtensions = Extensions.getInstance(
+ (ASN1TaggedObject)seq.getObjectAt(4), true);
+ }
+ else if (seq.size() > 3)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(3);
+
+ if (o.getTagNo() == 0)
+ {
+ this.nextUpdate = ASN1GeneralizedTime.getInstance(o, true);
+ }
+ else
+ {
+ this.singleExtensions = Extensions.getInstance(o, true);
+ }
+ }
+ }
+
+ public static SingleResponse getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static SingleResponse getInstance(
+ Object obj)
+ {
+ if (obj instanceof SingleResponse)
+ {
+ return (SingleResponse)obj;
+ }
+ else if (obj != null)
+ {
+ return new SingleResponse(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public CertID getCertID()
+ {
+ return certID;
+ }
+
+ public CertStatus getCertStatus()
+ {
+ return certStatus;
+ }
+
+ public ASN1GeneralizedTime getThisUpdate()
+ {
+ return thisUpdate;
+ }
+
+ public ASN1GeneralizedTime getNextUpdate()
+ {
+ return nextUpdate;
+ }
+
+ public Extensions getSingleExtensions()
+ {
+ return singleExtensions;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * SingleResponse ::= SEQUENCE {
+ * certID CertID,
+ * certStatus CertStatus,
+ * thisUpdate GeneralizedTime,
+ * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+ * singleExtensions [1] EXPLICIT Extensions OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certID);
+ v.add(certStatus);
+ v.add(thisUpdate);
+
+ if (nextUpdate != null)
+ {
+ v.add(new DERTaggedObject(true, 0, nextUpdate));
+ }
+
+ if (singleExtensions != null)
+ {
+ v.add(new DERTaggedObject(true, 1, singleExtensions));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/TBSRequest.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/TBSRequest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/TBSRequest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/TBSRequest.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,172 @@
+package pdftk.org.bouncycastle.asn1.ocsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.Extensions;
+import pdftk.org.bouncycastle.asn1.x509.GeneralName;
+import pdftk.org.bouncycastle.asn1.x509.X509Extensions;
+
+public class TBSRequest
+ extends ASN1Object
+{
+ private static final ASN1Integer V1 = new ASN1Integer(0);
+
+ ASN1Integer version;
+ GeneralName requestorName;
+ ASN1Sequence requestList;
+ Extensions requestExtensions;
+
+ boolean versionSet;
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param requestorName
+ * @param requestList
+ * @param requestExtensions
+ */
+ public TBSRequest(
+ GeneralName requestorName,
+ ASN1Sequence requestList,
+ X509Extensions requestExtensions)
+ {
+ this.version = V1;
+ this.requestorName = requestorName;
+ this.requestList = requestList;
+ this.requestExtensions = Extensions.getInstance(requestExtensions);
+ }
+
+ public TBSRequest(
+ GeneralName requestorName,
+ ASN1Sequence requestList,
+ Extensions requestExtensions)
+ {
+ this.version = V1;
+ this.requestorName = requestorName;
+ this.requestList = requestList;
+ this.requestExtensions = requestExtensions;
+ }
+
+ private TBSRequest(
+ ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.getObjectAt(0) instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(0);
+
+ if (o.getTagNo() == 0)
+ {
+ versionSet = true;
+ version = ASN1Integer.getInstance((ASN1TaggedObject)seq.getObjectAt(0), true);
+ index++;
+ }
+ else
+ {
+ version = V1;
+ }
+ }
+ else
+ {
+ version = V1;
+ }
+
+ if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
+ {
+ requestorName = GeneralName.getInstance((ASN1TaggedObject)seq.getObjectAt(index++), true);
+ }
+
+ requestList = (ASN1Sequence)seq.getObjectAt(index++);
+
+ if (seq.size() == (index + 1))
+ {
+ requestExtensions = Extensions.getInstance((ASN1TaggedObject)seq.getObjectAt(index), true);
+ }
+ }
+
+ public static TBSRequest getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static TBSRequest getInstance(
+ Object obj)
+ {
+ if (obj instanceof TBSRequest)
+ {
+ return (TBSRequest)obj;
+ }
+ else if (obj != null)
+ {
+ return new TBSRequest(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public GeneralName getRequestorName()
+ {
+ return requestorName;
+ }
+
+ public ASN1Sequence getRequestList()
+ {
+ return requestList;
+ }
+
+ public Extensions getRequestExtensions()
+ {
+ return requestExtensions;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * TBSRequest ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * requestorName [1] EXPLICIT GeneralName OPTIONAL,
+ * requestList SEQUENCE OF Request,
+ * requestExtensions [2] EXPLICIT Extensions OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ //
+ // if default don't include - unless explicitly provided. Not strictly correct
+ // but required for some requests
+ //
+ if (!version.equals(V1) || versionSet)
+ {
+ v.add(new DERTaggedObject(true, 0, version));
+ }
+
+ if (requestorName != null)
+ {
+ v.add(new DERTaggedObject(true, 1, requestorName));
+ }
+
+ v.add(requestList);
+
+ if (requestExtensions != null)
+ {
+ v.add(new DERTaggedObject(true, 2, requestExtensions));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ocsp/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ocsp/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes useful for encoding and supporting OCSP objects.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/oiw/ElGamalParameter.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/oiw/ElGamalParameter.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/oiw/ElGamalParameter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/oiw/ElGamalParameter.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,54 @@
+package pdftk.org.bouncycastle.asn1.oiw;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class ElGamalParameter
+ extends ASN1Object
+{
+ ASN1Integer p, g;
+
+ public ElGamalParameter(
+ BigInteger p,
+ BigInteger g)
+ {
+ this.p = new ASN1Integer(p);
+ this.g = new ASN1Integer(g);
+ }
+
+ public ElGamalParameter(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ p = (ASN1Integer)e.nextElement();
+ g = (ASN1Integer)e.nextElement();
+ }
+
+ public BigInteger getP()
+ {
+ return p.getPositiveValue();
+ }
+
+ public BigInteger getG()
+ {
+ return g.getPositiveValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(p);
+ v.add(g);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/oiw/OIWObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,31 @@
+package pdftk.org.bouncycastle.asn1.oiw;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface OIWObjectIdentifiers
+{
+ // id-SHA1 OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } //
+ static final ASN1ObjectIdentifier md4WithRSA = new ASN1ObjectIdentifier("1.3.14.3.2.2");
+ static final ASN1ObjectIdentifier md5WithRSA = new ASN1ObjectIdentifier("1.3.14.3.2.3");
+ static final ASN1ObjectIdentifier md4WithRSAEncryption = new ASN1ObjectIdentifier("1.3.14.3.2.4");
+
+ static final ASN1ObjectIdentifier desECB = new ASN1ObjectIdentifier("1.3.14.3.2.6");
+ static final ASN1ObjectIdentifier desCBC = new ASN1ObjectIdentifier("1.3.14.3.2.7");
+ static final ASN1ObjectIdentifier desOFB = new ASN1ObjectIdentifier("1.3.14.3.2.8");
+ static final ASN1ObjectIdentifier desCFB = new ASN1ObjectIdentifier("1.3.14.3.2.9");
+
+ static final ASN1ObjectIdentifier desEDE = new ASN1ObjectIdentifier("1.3.14.3.2.17");
+
+ static final ASN1ObjectIdentifier idSHA1 = new ASN1ObjectIdentifier("1.3.14.3.2.26");
+
+ static final ASN1ObjectIdentifier dsaWithSHA1 = new ASN1ObjectIdentifier("1.3.14.3.2.27");
+
+ static final ASN1ObjectIdentifier sha1WithRSA = new ASN1ObjectIdentifier("1.3.14.3.2.29");
+
+ // ElGamal Algorithm OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) oiw(14) dirservsig(7) algorithm(2) encryption(1) 1 }
+ //
+ static final ASN1ObjectIdentifier elGamalAlgorithm = new ASN1ObjectIdentifier("1.3.14.7.2.1.1");
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/oiw/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/oiw/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/oiw/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/oiw/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Objects and OID for the support of ISO OIW.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+A library for parsing and writing ASN.1 objects. Support is provided for DER and BER encoding.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/Attribute.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/Attribute.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/Attribute.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/Attribute.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,88 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class Attribute
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier attrType;
+ private ASN1Set attrValues;
+
+ /**
+ * return an Attribute object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static Attribute getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof Attribute)
+ {
+ return (Attribute)o;
+ }
+
+ if (o instanceof ASN1Sequence)
+ {
+ return new Attribute((ASN1Sequence)o);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
+ }
+
+ public Attribute(
+ ASN1Sequence seq)
+ {
+ attrType = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ attrValues = (ASN1Set)seq.getObjectAt(1);
+ }
+
+ public Attribute(
+ ASN1ObjectIdentifier attrType,
+ ASN1Set attrValues)
+ {
+ this.attrType = attrType;
+ this.attrValues = attrValues;
+ }
+
+ public ASN1ObjectIdentifier getAttrType()
+ {
+ return attrType;
+ }
+
+ public ASN1Set getAttrValues()
+ {
+ return attrValues;
+ }
+
+ public ASN1Encodable[] getAttributeValues()
+ {
+ return attrValues.toArray();
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Attribute ::= SEQUENCE {
+ * attrType OBJECT IDENTIFIER,
+ * attrValues SET OF AttributeValue
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(attrType);
+ v.add(attrValues);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/AuthenticatedSafe.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,74 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.DLSequence;
+
+public class AuthenticatedSafe
+ extends ASN1Object
+{
+ private ContentInfo[] info;
+ private boolean isBer = true;
+
+ private AuthenticatedSafe(
+ ASN1Sequence seq)
+ {
+ info = new ContentInfo[seq.size()];
+
+ for (int i = 0; i != info.length; i++)
+ {
+ info[i] = ContentInfo.getInstance(seq.getObjectAt(i));
+ }
+
+ isBer = seq instanceof BERSequence;
+ }
+
+ public static AuthenticatedSafe getInstance(
+ Object o)
+ {
+ if (o instanceof AuthenticatedSafe)
+ {
+ return (AuthenticatedSafe)o;
+ }
+
+ if (o != null)
+ {
+ return new AuthenticatedSafe(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public AuthenticatedSafe(
+ ContentInfo[] info)
+ {
+ this.info = info;
+ }
+
+ public ContentInfo[] getContentInfo()
+ {
+ return info;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != info.length; i++)
+ {
+ v.add(info[i]);
+ }
+
+ if (isBer)
+ {
+ return new BERSequence(v);
+ }
+ else
+ {
+ return new DLSequence(v);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/CRLBag.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/CRLBag.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/CRLBag.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/CRLBag.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,82 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class CRLBag
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier crlId;
+ private ASN1Encodable crlValue;
+
+ private CRLBag(
+ ASN1Sequence seq)
+ {
+ this.crlId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ this.crlValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject();
+ }
+
+ public static CRLBag getInstance(Object o)
+ {
+ if (o instanceof CRLBag)
+ {
+ return (CRLBag)o;
+ }
+ else if (o != null)
+ {
+ return new CRLBag(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CRLBag(
+ ASN1ObjectIdentifier crlId,
+ ASN1Encodable crlValue)
+ {
+ this.crlId = crlId;
+ this.crlValue = crlValue;
+ }
+
+ public ASN1ObjectIdentifier getcrlId()
+ {
+ return crlId;
+ }
+
+ public ASN1Encodable getCRLValue()
+ {
+ return crlValue;
+ }
+
+ /**
+ *
+ CRLBag ::= SEQUENCE {
+ crlId BAG-TYPE.&id ({CRLTypes}),
+ crlValue [0] EXPLICIT BAG-TYPE.&Type ({CRLTypes}{@crlId})
+ }
+
+ x509CRL BAG-TYPE ::= {OCTET STRING IDENTIFIED BY {certTypes 1}
+ -- DER-encoded X.509 CRL stored in OCTET STRING
+
+ CRLTypes BAG-TYPE ::= {
+ x509CRL,
+ ... -- For future extensions
+ }
+
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(crlId);
+ v.add(new DERTaggedObject(0, crlValue));
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/CertBag.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/CertBag.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/CertBag.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/CertBag.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,66 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class CertBag
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier certId;
+ private ASN1Encodable certValue;
+
+ private CertBag(
+ ASN1Sequence seq)
+ {
+ this.certId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ this.certValue = ((DERTaggedObject)seq.getObjectAt(1)).getObject();
+ }
+
+ public static CertBag getInstance(Object o)
+ {
+ if (o instanceof CertBag)
+ {
+ return (CertBag)o;
+ }
+ else if (o != null)
+ {
+ return new CertBag(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public CertBag(
+ ASN1ObjectIdentifier certId,
+ ASN1Encodable certValue)
+ {
+ this.certId = certId;
+ this.certValue = certValue;
+ }
+
+ public ASN1ObjectIdentifier getCertId()
+ {
+ return certId;
+ }
+
+ public ASN1Encodable getCertValue()
+ {
+ return certValue;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(certId);
+ v.add(new DERTaggedObject(0, certValue));
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/CertificationRequest.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/CertificationRequest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/CertificationRequest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/CertificationRequest.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,91 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * PKCS10 Certification request object.
+ *
+ * CertificationRequest ::= SEQUENCE {
+ * certificationRequestInfo CertificationRequestInfo,
+ * signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
+ * signature BIT STRING
+ * }
+ *
+ */
+public class CertificationRequest
+ extends ASN1Object
+{
+ protected CertificationRequestInfo reqInfo = null;
+ protected AlgorithmIdentifier sigAlgId = null;
+ protected DERBitString sigBits = null;
+
+ public static CertificationRequest getInstance(Object o)
+ {
+ if (o instanceof CertificationRequest)
+ {
+ return (CertificationRequest)o;
+ }
+
+ if (o != null)
+ {
+ return new CertificationRequest(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ protected CertificationRequest()
+ {
+ }
+
+ public CertificationRequest(
+ CertificationRequestInfo requestInfo,
+ AlgorithmIdentifier algorithm,
+ DERBitString signature)
+ {
+ this.reqInfo = requestInfo;
+ this.sigAlgId = algorithm;
+ this.sigBits = signature;
+ }
+
+ public CertificationRequest(
+ ASN1Sequence seq)
+ {
+ reqInfo = CertificationRequestInfo.getInstance(seq.getObjectAt(0));
+ sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ sigBits = (DERBitString)seq.getObjectAt(2);
+ }
+
+ public CertificationRequestInfo getCertificationRequestInfo()
+ {
+ return reqInfo;
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return sigAlgId;
+ }
+
+ public DERBitString getSignature()
+ {
+ return sigBits;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ // Construct the CertificateRequest
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(reqInfo);
+ v.add(sigAlgId);
+ v.add(sigBits);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/CertificationRequestInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,148 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+import pdftk.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import pdftk.org.bouncycastle.asn1.x509.X509Name;
+
+/**
+ * PKCS10 CertificationRequestInfo object.
+ *
+ * CertificationRequestInfo ::= SEQUENCE {
+ * version INTEGER { v1(0) } (v1,...),
+ * subject Name,
+ * subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+ * attributes [0] Attributes{{ CRIAttributes }}
+ * }
+ *
+ * Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
+ *
+ * Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
+ * type ATTRIBUTE.&id({IOSet}),
+ * values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+ * }
+ *
+ */
+public class CertificationRequestInfo
+ extends ASN1Object
+{
+ ASN1Integer version = new ASN1Integer(0);
+ X500Name subject;
+ SubjectPublicKeyInfo subjectPKInfo;
+ ASN1Set attributes = null;
+
+ public static CertificationRequestInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof CertificationRequestInfo)
+ {
+ return (CertificationRequestInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new CertificationRequestInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public CertificationRequestInfo(
+ X500Name subject,
+ SubjectPublicKeyInfo pkInfo,
+ ASN1Set attributes)
+ {
+ this.subject = subject;
+ this.subjectPKInfo = pkInfo;
+ this.attributes = attributes;
+
+ if ((subject == null) || (version == null) || (subjectPKInfo == null))
+ {
+ throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
+ }
+ }
+
+ /**
+ * @deprecated use X500Name method.
+ */
+ public CertificationRequestInfo(
+ X509Name subject,
+ SubjectPublicKeyInfo pkInfo,
+ ASN1Set attributes)
+ {
+ this.subject = X500Name.getInstance(subject.toASN1Primitive());
+ this.subjectPKInfo = pkInfo;
+ this.attributes = attributes;
+
+ if ((subject == null) || (version == null) || (subjectPKInfo == null))
+ {
+ throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
+ }
+ }
+
+ public CertificationRequestInfo(
+ ASN1Sequence seq)
+ {
+ version = (ASN1Integer)seq.getObjectAt(0);
+
+ subject = X500Name.getInstance(seq.getObjectAt(1));
+ subjectPKInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(2));
+
+ //
+ // some CertificationRequestInfo objects seem to treat this field
+ // as optional.
+ //
+ if (seq.size() > 3)
+ {
+ DERTaggedObject tagobj = (DERTaggedObject)seq.getObjectAt(3);
+ attributes = ASN1Set.getInstance(tagobj, false);
+ }
+
+ if ((subject == null) || (version == null) || (subjectPKInfo == null))
+ {
+ throw new IllegalArgumentException("Not all mandatory fields set in CertificationRequestInfo generator.");
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public X500Name getSubject()
+ {
+ return subject;
+ }
+
+ public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
+ {
+ return subjectPKInfo;
+ }
+
+ public ASN1Set getAttributes()
+ {
+ return attributes;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(subject);
+ v.add(subjectPKInfo);
+
+ if (attributes != null)
+ {
+ v.add(new DERTaggedObject(false, 0, attributes));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/ContentInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/ContentInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/ContentInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/ContentInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,102 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.BERTaggedObject;
+import pdftk.org.bouncycastle.asn1.DLSequence;
+
+public class ContentInfo
+ extends ASN1Object
+ implements PKCSObjectIdentifiers
+{
+ private ASN1ObjectIdentifier contentType;
+ private ASN1Encodable content;
+ private boolean isBer = true;
+
+ public static ContentInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof ContentInfo)
+ {
+ return (ContentInfo)obj;
+ }
+
+ if (obj != null)
+ {
+ return new ContentInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private ContentInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ contentType = (ASN1ObjectIdentifier)e.nextElement();
+
+ if (e.hasMoreElements())
+ {
+ content = ((ASN1TaggedObject)e.nextElement()).getObject();
+ }
+
+ isBer = seq instanceof BERSequence;
+ }
+
+ public ContentInfo(
+ ASN1ObjectIdentifier contentType,
+ ASN1Encodable content)
+ {
+ this.contentType = contentType;
+ this.content = content;
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return contentType;
+ }
+
+ public ASN1Encodable getContent()
+ {
+ return content;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * ContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * content
+ * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(contentType);
+
+ if (content != null)
+ {
+ v.add(new BERTaggedObject(true, 0, content));
+ }
+
+ if (isBer)
+ {
+ return new BERSequence(v);
+ }
+ else
+ {
+ return new DLSequence(v);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/DHParameter.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/DHParameter.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/DHParameter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/DHParameter.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,104 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class DHParameter
+ extends ASN1Object
+{
+ ASN1Integer p, g, l;
+
+ public DHParameter(
+ BigInteger p,
+ BigInteger g,
+ int l)
+ {
+ this.p = new ASN1Integer(p);
+ this.g = new ASN1Integer(g);
+
+ if (l != 0)
+ {
+ this.l = new ASN1Integer(l);
+ }
+ else
+ {
+ this.l = null;
+ }
+ }
+
+ public static DHParameter getInstance(
+ Object obj)
+ {
+ if (obj instanceof DHParameter)
+ {
+ return (DHParameter)obj;
+ }
+
+ if (obj != null)
+ {
+ return new DHParameter(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private DHParameter(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ p = ASN1Integer.getInstance(e.nextElement());
+ g = ASN1Integer.getInstance(e.nextElement());
+
+ if (e.hasMoreElements())
+ {
+ l = (ASN1Integer)e.nextElement();
+ }
+ else
+ {
+ l = null;
+ }
+ }
+
+ public BigInteger getP()
+ {
+ return p.getPositiveValue();
+ }
+
+ public BigInteger getG()
+ {
+ return g.getPositiveValue();
+ }
+
+ public BigInteger getL()
+ {
+ if (l == null)
+ {
+ return null;
+ }
+
+ return l.getPositiveValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(p);
+ v.add(g);
+
+ if (this.getL() != null)
+ {
+ v.add(l);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/EncryptedData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/EncryptedData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/EncryptedData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/EncryptedData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,115 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.BERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * The EncryptedData object.
+ *
+ * EncryptedData ::= SEQUENCE {
+ * version Version,
+ * encryptedContentInfo EncryptedContentInfo
+ * }
+ *
+ *
+ * EncryptedContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+ * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+ * }
+ *
+ * EncryptedContent ::= OCTET STRING
+ *
+ */
+public class EncryptedData
+ extends ASN1Object
+{
+ ASN1Sequence data;
+ ASN1ObjectIdentifier bagId;
+ ASN1Primitive bagValue;
+
+ public static EncryptedData getInstance(
+ Object obj)
+ {
+ if (obj instanceof EncryptedData)
+ {
+ return (EncryptedData)obj;
+ }
+
+ if (obj != null)
+ {
+ return new EncryptedData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private EncryptedData(
+ ASN1Sequence seq)
+ {
+ int version = ((ASN1Integer)seq.getObjectAt(0)).getValue().intValue();
+
+ if (version != 0)
+ {
+ throw new IllegalArgumentException("sequence not version 0");
+ }
+
+ this.data = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+
+ public EncryptedData(
+ ASN1ObjectIdentifier contentType,
+ AlgorithmIdentifier encryptionAlgorithm,
+ ASN1Encodable content)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(contentType);
+ v.add(encryptionAlgorithm.toASN1Primitive());
+ v.add(new BERTaggedObject(false, 0, content));
+
+ data = new BERSequence(v);
+ }
+
+ public ASN1ObjectIdentifier getContentType()
+ {
+ return ASN1ObjectIdentifier.getInstance(data.getObjectAt(0));
+ }
+
+ public AlgorithmIdentifier getEncryptionAlgorithm()
+ {
+ return AlgorithmIdentifier.getInstance(data.getObjectAt(1));
+ }
+
+ public ASN1OctetString getContent()
+ {
+ if (data.size() == 3)
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(data.getObjectAt(2));
+
+ return ASN1OctetString.getInstance(o, false);
+ }
+
+ return null;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(0));
+ v.add(data);
+
+ return new BERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/EncryptedPrivateKeyInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,86 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class EncryptedPrivateKeyInfo
+ extends ASN1Object
+{
+ private AlgorithmIdentifier algId;
+ private ASN1OctetString data;
+
+ private EncryptedPrivateKeyInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ algId = AlgorithmIdentifier.getInstance(e.nextElement());
+ data = ASN1OctetString.getInstance(e.nextElement());
+ }
+
+ public EncryptedPrivateKeyInfo(
+ AlgorithmIdentifier algId,
+ byte[] encoding)
+ {
+ this.algId = algId;
+ this.data = new DEROctetString(encoding);
+ }
+
+ public static EncryptedPrivateKeyInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof EncryptedPrivateKeyInfo)
+ {
+ return (EncryptedPrivateKeyInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new EncryptedPrivateKeyInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public AlgorithmIdentifier getEncryptionAlgorithm()
+ {
+ return algId;
+ }
+
+ public byte[] getEncryptedData()
+ {
+ return data.getOctets();
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * EncryptedPrivateKeyInfo ::= SEQUENCE {
+ * encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
+ * encryptedData EncryptedData
+ * }
+ *
+ * EncryptedData ::= OCTET STRING
+ *
+ * KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * ... -- For local profiles
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(algId);
+ v.add(data);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/EncryptionScheme.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/EncryptionScheme.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/EncryptionScheme.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/EncryptionScheme.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,55 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class EncryptionScheme
+ extends AlgorithmIdentifier
+{
+ public EncryptionScheme(
+ ASN1ObjectIdentifier objectId,
+ ASN1Encodable parameters)
+ {
+ super(objectId, parameters);
+ }
+
+ EncryptionScheme(
+ ASN1Sequence seq)
+ {
+ this((ASN1ObjectIdentifier)seq.getObjectAt(0), seq.getObjectAt(1));
+ }
+
+ public static final AlgorithmIdentifier getInstance(Object obj)
+ {
+ if (obj instanceof EncryptionScheme)
+ {
+ return (EncryptionScheme)obj;
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new EncryptionScheme((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public ASN1Primitive getObject()
+ {
+ return (ASN1Primitive)getParameters();
+ }
+
+ public ASN1Primitive getASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(getObjectId());
+ v.add(getParameters());
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/IssuerAndSerialNumber.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/IssuerAndSerialNumber.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/IssuerAndSerialNumber.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/IssuerAndSerialNumber.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,85 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+import pdftk.org.bouncycastle.asn1.x509.X509Name;
+
+public class IssuerAndSerialNumber
+ extends ASN1Object
+{
+ X500Name name;
+ ASN1Integer certSerialNumber;
+
+ public static IssuerAndSerialNumber getInstance(
+ Object obj)
+ {
+ if (obj instanceof IssuerAndSerialNumber)
+ {
+ return (IssuerAndSerialNumber)obj;
+ }
+ else if (obj != null)
+ {
+ return new IssuerAndSerialNumber(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private IssuerAndSerialNumber(
+ ASN1Sequence seq)
+ {
+ this.name = X500Name.getInstance(seq.getObjectAt(0));
+ this.certSerialNumber = (ASN1Integer)seq.getObjectAt(1);
+ }
+
+ public IssuerAndSerialNumber(
+ X509Name name,
+ BigInteger certSerialNumber)
+ {
+ this.name = X500Name.getInstance(name.toASN1Primitive());
+ this.certSerialNumber = new ASN1Integer(certSerialNumber);
+ }
+
+ public IssuerAndSerialNumber(
+ X509Name name,
+ ASN1Integer certSerialNumber)
+ {
+ this.name = X500Name.getInstance(name.toASN1Primitive());
+ this.certSerialNumber = certSerialNumber;
+ }
+
+ public IssuerAndSerialNumber(
+ X500Name name,
+ BigInteger certSerialNumber)
+ {
+ this.name = name;
+ this.certSerialNumber = new ASN1Integer(certSerialNumber);
+ }
+
+ public X500Name getName()
+ {
+ return name;
+ }
+
+ public ASN1Integer getCertificateSerialNumber()
+ {
+ return certSerialNumber;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(name);
+ v.add(certSerialNumber);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/KeyDerivationFunc.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class KeyDerivationFunc
+ extends AlgorithmIdentifier
+{
+ KeyDerivationFunc(
+ ASN1Sequence seq)
+ {
+ super(seq);
+ }
+
+ public KeyDerivationFunc(
+ ASN1ObjectIdentifier id,
+ ASN1Encodable params)
+ {
+ super(id, params);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/MacData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/MacData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/MacData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/MacData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,106 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.DigestInfo;
+
+public class MacData
+ extends ASN1Object
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ DigestInfo digInfo;
+ byte[] salt;
+ BigInteger iterationCount;
+
+ public static MacData getInstance(
+ Object obj)
+ {
+ if (obj instanceof MacData)
+ {
+ return (MacData)obj;
+ }
+ else if (obj != null)
+ {
+ return new MacData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private MacData(
+ ASN1Sequence seq)
+ {
+ this.digInfo = DigestInfo.getInstance(seq.getObjectAt(0));
+
+ this.salt = ((ASN1OctetString)seq.getObjectAt(1)).getOctets();
+
+ if (seq.size() == 3)
+ {
+ this.iterationCount = ((ASN1Integer)seq.getObjectAt(2)).getValue();
+ }
+ else
+ {
+ this.iterationCount = ONE;
+ }
+ }
+
+ public MacData(
+ DigestInfo digInfo,
+ byte[] salt,
+ int iterationCount)
+ {
+ this.digInfo = digInfo;
+ this.salt = salt;
+ this.iterationCount = BigInteger.valueOf(iterationCount);
+ }
+
+ public DigestInfo getMac()
+ {
+ return digInfo;
+ }
+
+ public byte[] getSalt()
+ {
+ return salt;
+ }
+
+ public BigInteger getIterationCount()
+ {
+ return iterationCount;
+ }
+
+ /**
+ *
+ * MacData ::= SEQUENCE {
+ * mac DigestInfo,
+ * macSalt OCTET STRING,
+ * iterations INTEGER DEFAULT 1
+ * -- Note: The default is for historic reasons and its use is deprecated. A
+ * -- higher value, like 1024 is recommended.
+ *
+ * @return the basic ASN1Primitive construction.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(digInfo);
+ v.add(new DEROctetString(salt));
+
+ if (!iterationCount.equals(ONE))
+ {
+ v.add(new ASN1Integer(iterationCount));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PBEParameter.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PBEParameter.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PBEParameter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PBEParameter.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,73 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class PBEParameter
+ extends ASN1Object
+{
+ ASN1Integer iterations;
+ ASN1OctetString salt;
+
+ public PBEParameter(
+ byte[] salt,
+ int iterations)
+ {
+ if (salt.length != 8)
+ {
+ throw new IllegalArgumentException("salt length must be 8");
+ }
+ this.salt = new DEROctetString(salt);
+ this.iterations = new ASN1Integer(iterations);
+ }
+
+ private PBEParameter(
+ ASN1Sequence seq)
+ {
+ salt = (ASN1OctetString)seq.getObjectAt(0);
+ iterations = (ASN1Integer)seq.getObjectAt(1);
+ }
+
+ public static PBEParameter getInstance(
+ Object obj)
+ {
+ if (obj instanceof PBEParameter)
+ {
+ return (PBEParameter)obj;
+ }
+ else if (obj != null)
+ {
+ return new PBEParameter(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public BigInteger getIterationCount()
+ {
+ return iterations.getValue();
+ }
+
+ public byte[] getSalt()
+ {
+ return salt.getOctets();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(salt);
+ v.add(iterations);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PBES2Algorithms.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,77 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * @deprecated - use AlgorithmIdentifier and PBES2Parameters
+ */
+public class PBES2Algorithms
+ extends AlgorithmIdentifier implements PKCSObjectIdentifiers
+{
+ private ASN1ObjectIdentifier objectId;
+ private KeyDerivationFunc func;
+ private EncryptionScheme scheme;
+
+ public PBES2Algorithms(
+ ASN1Sequence obj)
+ {
+ super(obj);
+
+ Enumeration e = obj.getObjects();
+
+ objectId = (ASN1ObjectIdentifier)e.nextElement();
+
+ ASN1Sequence seq = (ASN1Sequence)e.nextElement();
+
+ e = seq.getObjects();
+
+ ASN1Sequence funcSeq = (ASN1Sequence)e.nextElement();
+
+ if (funcSeq.getObjectAt(0).equals(id_PBKDF2))
+ {
+ func = new KeyDerivationFunc(id_PBKDF2, PBKDF2Params.getInstance(funcSeq.getObjectAt(1)));
+ }
+ else
+ {
+ func = new KeyDerivationFunc(funcSeq);
+ }
+
+ scheme = new EncryptionScheme((ASN1Sequence)e.nextElement());
+ }
+
+ public ASN1ObjectIdentifier getObjectId()
+ {
+ return objectId;
+ }
+
+ public KeyDerivationFunc getKeyDerivationFunc()
+ {
+ return func;
+ }
+
+ public EncryptionScheme getEncryptionScheme()
+ {
+ return scheme;
+ }
+
+ public ASN1Primitive getASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ ASN1EncodableVector subV = new ASN1EncodableVector();
+
+ v.add(objectId);
+
+ subV.add(func);
+ subV.add(scheme);
+ v.add(new DERSequence(subV));
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PBES2Parameters.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PBES2Parameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PBES2Parameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PBES2Parameters.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,72 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class PBES2Parameters
+ extends ASN1Object
+ implements PKCSObjectIdentifiers
+{
+ private KeyDerivationFunc func;
+ private EncryptionScheme scheme;
+
+ public static PBES2Parameters getInstance(
+ Object obj)
+ {
+ if (obj== null || obj instanceof PBES2Parameters)
+ {
+ return (PBES2Parameters)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new PBES2Parameters((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public PBES2Parameters(
+ ASN1Sequence obj)
+ {
+ Enumeration e = obj.getObjects();
+ ASN1Sequence funcSeq = ASN1Sequence.getInstance(((ASN1Encodable)e.nextElement()).toASN1Primitive());
+
+ if (funcSeq.getObjectAt(0).equals(id_PBKDF2))
+ {
+ func = new KeyDerivationFunc(id_PBKDF2, PBKDF2Params.getInstance(funcSeq.getObjectAt(1)));
+ }
+ else
+ {
+ func = new KeyDerivationFunc(funcSeq);
+ }
+
+ scheme = (EncryptionScheme)EncryptionScheme.getInstance(e.nextElement());
+ }
+
+ public KeyDerivationFunc getKeyDerivationFunc()
+ {
+ return func;
+ }
+
+ public EncryptionScheme getEncryptionScheme()
+ {
+ return scheme;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(func);
+ v.add(scheme);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PBKDF2Params.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PBKDF2Params.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PBKDF2Params.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PBKDF2Params.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,108 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class PBKDF2Params
+ extends ASN1Object
+{
+ private ASN1OctetString octStr;
+ private ASN1Integer iterationCount;
+ private ASN1Integer keyLength;
+
+ public static PBKDF2Params getInstance(
+ Object obj)
+ {
+ if (obj instanceof PBKDF2Params)
+ {
+ return (PBKDF2Params)obj;
+ }
+
+ if (obj != null)
+ {
+ return new PBKDF2Params(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public PBKDF2Params(
+ byte[] salt,
+ int iterationCount)
+ {
+ this.octStr = new DEROctetString(salt);
+ this.iterationCount = new ASN1Integer(iterationCount);
+ }
+
+ public PBKDF2Params(
+ byte[] salt,
+ int iterationCount,
+ int keyLength)
+ {
+ this(salt, iterationCount);
+
+ this.keyLength = new ASN1Integer(keyLength);
+ }
+
+ private PBKDF2Params(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ octStr = (ASN1OctetString)e.nextElement();
+ iterationCount = (ASN1Integer)e.nextElement();
+
+ if (e.hasMoreElements())
+ {
+ keyLength = (ASN1Integer)e.nextElement();
+ }
+ else
+ {
+ keyLength = null;
+ }
+ }
+
+ public byte[] getSalt()
+ {
+ return octStr.getOctets();
+ }
+
+ public BigInteger getIterationCount()
+ {
+ return iterationCount.getValue();
+ }
+
+ public BigInteger getKeyLength()
+ {
+ if (keyLength != null)
+ {
+ return keyLength.getValue();
+ }
+
+ return null;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(octStr);
+ v.add(iterationCount);
+
+ if (keyLength != null)
+ {
+ v.add(keyLength);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PKCS12PBEParams.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,69 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class PKCS12PBEParams
+ extends ASN1Object
+{
+ ASN1Integer iterations;
+ ASN1OctetString iv;
+
+ public PKCS12PBEParams(
+ byte[] salt,
+ int iterations)
+ {
+ this.iv = new DEROctetString(salt);
+ this.iterations = new ASN1Integer(iterations);
+ }
+
+ private PKCS12PBEParams(
+ ASN1Sequence seq)
+ {
+ iv = (ASN1OctetString)seq.getObjectAt(0);
+ iterations = ASN1Integer.getInstance(seq.getObjectAt(1));
+ }
+
+ public static PKCS12PBEParams getInstance(
+ Object obj)
+ {
+ if (obj instanceof PKCS12PBEParams)
+ {
+ return (PKCS12PBEParams)obj;
+ }
+ else if (obj != null)
+ {
+ return new PKCS12PBEParams(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public BigInteger getIterations()
+ {
+ return iterations.getValue();
+ }
+
+ public byte[] getIV()
+ {
+ return iv.getOctets();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(iv);
+ v.add(iterations);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,258 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface PKCSObjectIdentifiers
+{
+ //
+ // pkcs-1 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
+ //
+ static final ASN1ObjectIdentifier pkcs_1 = new ASN1ObjectIdentifier("1.2.840.113549.1.1");
+ static final ASN1ObjectIdentifier rsaEncryption = pkcs_1.branch("1");
+ static final ASN1ObjectIdentifier md2WithRSAEncryption = pkcs_1.branch("2");
+ static final ASN1ObjectIdentifier md4WithRSAEncryption = pkcs_1.branch("3");
+ static final ASN1ObjectIdentifier md5WithRSAEncryption = pkcs_1.branch("4");
+ static final ASN1ObjectIdentifier sha1WithRSAEncryption = pkcs_1.branch("5");
+ static final ASN1ObjectIdentifier srsaOAEPEncryptionSET = pkcs_1.branch("6");
+ static final ASN1ObjectIdentifier id_RSAES_OAEP = pkcs_1.branch("7");
+ static final ASN1ObjectIdentifier id_mgf1 = pkcs_1.branch("8");
+ static final ASN1ObjectIdentifier id_pSpecified = pkcs_1.branch("9");
+ static final ASN1ObjectIdentifier id_RSASSA_PSS = pkcs_1.branch("10");
+ static final ASN1ObjectIdentifier sha256WithRSAEncryption = pkcs_1.branch("11");
+ static final ASN1ObjectIdentifier sha384WithRSAEncryption = pkcs_1.branch("12");
+ static final ASN1ObjectIdentifier sha512WithRSAEncryption = pkcs_1.branch("13");
+ static final ASN1ObjectIdentifier sha224WithRSAEncryption = pkcs_1.branch("14");
+
+ //
+ // pkcs-3 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 }
+ //
+ static final ASN1ObjectIdentifier pkcs_3 = new ASN1ObjectIdentifier("1.2.840.113549.1.3");
+ static final ASN1ObjectIdentifier dhKeyAgreement = pkcs_3.branch("1");
+
+ //
+ // pkcs-5 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 }
+ //
+ static final ASN1ObjectIdentifier pkcs_5 = new ASN1ObjectIdentifier("1.2.840.113549.1.5");
+
+ static final ASN1ObjectIdentifier pbeWithMD2AndDES_CBC = pkcs_5.branch("1");
+ static final ASN1ObjectIdentifier pbeWithMD2AndRC2_CBC = pkcs_5.branch("4");
+ static final ASN1ObjectIdentifier pbeWithMD5AndDES_CBC = pkcs_5.branch("3");
+ static final ASN1ObjectIdentifier pbeWithMD5AndRC2_CBC = pkcs_5.branch("6");
+ static final ASN1ObjectIdentifier pbeWithSHA1AndDES_CBC = pkcs_5.branch("10");
+ static final ASN1ObjectIdentifier pbeWithSHA1AndRC2_CBC = pkcs_5.branch("11");
+
+ static final ASN1ObjectIdentifier id_PBES2 = pkcs_5.branch("13");
+
+ static final ASN1ObjectIdentifier id_PBKDF2 = pkcs_5.branch("12");
+
+ //
+ // encryptionAlgorithm OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) 3 }
+ //
+ static final ASN1ObjectIdentifier encryptionAlgorithm = new ASN1ObjectIdentifier("1.2.840.113549.3");
+
+ static final ASN1ObjectIdentifier des_EDE3_CBC = encryptionAlgorithm.branch("7");
+ static final ASN1ObjectIdentifier RC2_CBC = encryptionAlgorithm.branch("2");
+ static final ASN1ObjectIdentifier rc4 = encryptionAlgorithm.branch("4");
+
+ //
+ // object identifiers for digests
+ //
+ static final ASN1ObjectIdentifier digestAlgorithm = new ASN1ObjectIdentifier("1.2.840.113549.2");
+ //
+ // md2 OBJECT IDENTIFIER ::=
+ // {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 2}
+ //
+ static final ASN1ObjectIdentifier md2 = digestAlgorithm.branch("2");
+
+ //
+ // md4 OBJECT IDENTIFIER ::=
+ // {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 4}
+ //
+ static final ASN1ObjectIdentifier md4 = digestAlgorithm.branch("4");
+
+ //
+ // md5 OBJECT IDENTIFIER ::=
+ // {iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
+ //
+ static final ASN1ObjectIdentifier md5 = digestAlgorithm.branch("5");
+
+ static final ASN1ObjectIdentifier id_hmacWithSHA1 = digestAlgorithm.branch("7");
+ static final ASN1ObjectIdentifier id_hmacWithSHA224 = digestAlgorithm.branch("8");
+ static final ASN1ObjectIdentifier id_hmacWithSHA256 = digestAlgorithm.branch("9");
+ static final ASN1ObjectIdentifier id_hmacWithSHA384 = digestAlgorithm.branch("10");
+ static final ASN1ObjectIdentifier id_hmacWithSHA512 = digestAlgorithm.branch("11");
+
+ //
+ // pkcs-7 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 }
+ //
+ static final String pkcs_7 = "1.2.840.113549.1.7";
+ static final ASN1ObjectIdentifier data = new ASN1ObjectIdentifier(pkcs_7 + ".1");
+ static final ASN1ObjectIdentifier signedData = new ASN1ObjectIdentifier(pkcs_7 + ".2");
+ static final ASN1ObjectIdentifier envelopedData = new ASN1ObjectIdentifier(pkcs_7 + ".3");
+ static final ASN1ObjectIdentifier signedAndEnvelopedData = new ASN1ObjectIdentifier(pkcs_7 + ".4");
+ static final ASN1ObjectIdentifier digestedData = new ASN1ObjectIdentifier(pkcs_7 + ".5");
+ static final ASN1ObjectIdentifier encryptedData = new ASN1ObjectIdentifier(pkcs_7 + ".6");
+
+ //
+ // pkcs-9 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
+ //
+ static final ASN1ObjectIdentifier pkcs_9 = new ASN1ObjectIdentifier("1.2.840.113549.1.9");
+
+ static final ASN1ObjectIdentifier pkcs_9_at_emailAddress = pkcs_9.branch("1");
+ static final ASN1ObjectIdentifier pkcs_9_at_unstructuredName = pkcs_9.branch("2");
+ static final ASN1ObjectIdentifier pkcs_9_at_contentType = pkcs_9.branch("3");
+ static final ASN1ObjectIdentifier pkcs_9_at_messageDigest = pkcs_9.branch("4");
+ static final ASN1ObjectIdentifier pkcs_9_at_signingTime = pkcs_9.branch("5");
+ static final ASN1ObjectIdentifier pkcs_9_at_counterSignature = pkcs_9.branch("6");
+ static final ASN1ObjectIdentifier pkcs_9_at_challengePassword = pkcs_9.branch("7");
+ static final ASN1ObjectIdentifier pkcs_9_at_unstructuredAddress = pkcs_9.branch("8");
+ static final ASN1ObjectIdentifier pkcs_9_at_extendedCertificateAttributes = pkcs_9.branch("9");
+
+ static final ASN1ObjectIdentifier pkcs_9_at_signingDescription = pkcs_9.branch("13");
+ static final ASN1ObjectIdentifier pkcs_9_at_extensionRequest = pkcs_9.branch("14");
+ static final ASN1ObjectIdentifier pkcs_9_at_smimeCapabilities = pkcs_9.branch("15");
+
+ static final ASN1ObjectIdentifier pkcs_9_at_friendlyName = pkcs_9.branch("20");
+ static final ASN1ObjectIdentifier pkcs_9_at_localKeyId = pkcs_9.branch("21");
+
+ /** @deprecated use x509Certificate instead */
+ static final ASN1ObjectIdentifier x509certType = pkcs_9.branch("22.1");
+
+ static final ASN1ObjectIdentifier certTypes = pkcs_9.branch("22");
+ static final ASN1ObjectIdentifier x509Certificate = certTypes.branch("1");
+ static final ASN1ObjectIdentifier sdsiCertificate = certTypes.branch("2");
+
+ static final ASN1ObjectIdentifier crlTypes = pkcs_9.branch("23");
+ static final ASN1ObjectIdentifier x509Crl = crlTypes.branch("1");
+
+ static final ASN1ObjectIdentifier id_alg_PWRI_KEK = pkcs_9.branch("16.3.9");
+
+ //
+ // SMIME capability sub oids.
+ //
+ static final ASN1ObjectIdentifier preferSignedData = pkcs_9.branch("15.1");
+ static final ASN1ObjectIdentifier canNotDecryptAny = pkcs_9.branch("15.2");
+ static final ASN1ObjectIdentifier sMIMECapabilitiesVersions = pkcs_9.branch("15.3");
+
+ //
+ // id-ct OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1)}
+ //
+ static final ASN1ObjectIdentifier id_ct = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.1");
+
+ static final ASN1ObjectIdentifier id_ct_authData = id_ct.branch("2");
+ static final ASN1ObjectIdentifier id_ct_TSTInfo = id_ct.branch("4");
+ static final ASN1ObjectIdentifier id_ct_compressedData = id_ct.branch("9");
+ static final ASN1ObjectIdentifier id_ct_authEnvelopedData = id_ct.branch("23");
+ static final ASN1ObjectIdentifier id_ct_timestampedData = id_ct.branch("31");
+
+ //
+ // id-cti OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) cti(6)}
+ //
+ static final ASN1ObjectIdentifier id_cti = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.6");
+
+ static final ASN1ObjectIdentifier id_cti_ets_proofOfOrigin = id_cti.branch("1");
+ static final ASN1ObjectIdentifier id_cti_ets_proofOfReceipt = id_cti.branch("2");
+ static final ASN1ObjectIdentifier id_cti_ets_proofOfDelivery = id_cti.branch("3");
+ static final ASN1ObjectIdentifier id_cti_ets_proofOfSender = id_cti.branch("4");
+ static final ASN1ObjectIdentifier id_cti_ets_proofOfApproval = id_cti.branch("5");
+ static final ASN1ObjectIdentifier id_cti_ets_proofOfCreation = id_cti.branch("6");
+
+ //
+ // id-aa OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)}
+ //
+ static final ASN1ObjectIdentifier id_aa = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.2");
+
+
+ static final ASN1ObjectIdentifier id_aa_receiptRequest = id_aa.branch("1");
+
+ static final ASN1ObjectIdentifier id_aa_contentHint = id_aa.branch("4"); // See RFC 2634
+ static final ASN1ObjectIdentifier id_aa_msgSigDigest = id_aa.branch("5");
+ static final ASN1ObjectIdentifier id_aa_contentReference = id_aa.branch("10");
+ /*
+ * id-aa-encrypKeyPref OBJECT IDENTIFIER ::= {id-aa 11}
+ *
+ */
+ static final ASN1ObjectIdentifier id_aa_encrypKeyPref = id_aa.branch("11");
+ static final ASN1ObjectIdentifier id_aa_signingCertificate = id_aa.branch("12");
+ static final ASN1ObjectIdentifier id_aa_signingCertificateV2 = id_aa.branch("47");
+
+ static final ASN1ObjectIdentifier id_aa_contentIdentifier = id_aa.branch("7"); // See RFC 2634
+
+ /*
+ * RFC 3126
+ */
+ static final ASN1ObjectIdentifier id_aa_signatureTimeStampToken = id_aa.branch("14");
+
+ static final ASN1ObjectIdentifier id_aa_ets_sigPolicyId = id_aa.branch("15");
+ static final ASN1ObjectIdentifier id_aa_ets_commitmentType = id_aa.branch("16");
+ static final ASN1ObjectIdentifier id_aa_ets_signerLocation = id_aa.branch("17");
+ static final ASN1ObjectIdentifier id_aa_ets_signerAttr = id_aa.branch("18");
+ static final ASN1ObjectIdentifier id_aa_ets_otherSigCert = id_aa.branch("19");
+ static final ASN1ObjectIdentifier id_aa_ets_contentTimestamp = id_aa.branch("20");
+ static final ASN1ObjectIdentifier id_aa_ets_certificateRefs = id_aa.branch("21");
+ static final ASN1ObjectIdentifier id_aa_ets_revocationRefs = id_aa.branch("22");
+ static final ASN1ObjectIdentifier id_aa_ets_certValues = id_aa.branch("23");
+ static final ASN1ObjectIdentifier id_aa_ets_revocationValues = id_aa.branch("24");
+ static final ASN1ObjectIdentifier id_aa_ets_escTimeStamp = id_aa.branch("25");
+ static final ASN1ObjectIdentifier id_aa_ets_certCRLTimestamp = id_aa.branch("26");
+ static final ASN1ObjectIdentifier id_aa_ets_archiveTimestamp = id_aa.branch("27");
+
+ /** @deprecated use id_aa_ets_sigPolicyId instead */
+ static final ASN1ObjectIdentifier id_aa_sigPolicyId = id_aa_ets_sigPolicyId;
+ /** @deprecated use id_aa_ets_commitmentType instead */
+ static final ASN1ObjectIdentifier id_aa_commitmentType = id_aa_ets_commitmentType;
+ /** @deprecated use id_aa_ets_signerLocation instead */
+ static final ASN1ObjectIdentifier id_aa_signerLocation = id_aa_ets_signerLocation;
+ /** @deprecated use id_aa_ets_otherSigCert instead */
+ static final ASN1ObjectIdentifier id_aa_otherSigCert = id_aa_ets_otherSigCert;
+
+ //
+ // id-spq OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+ // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) id-spq(5)}
+ //
+ final String id_spq = "1.2.840.113549.1.9.16.5";
+
+ static final ASN1ObjectIdentifier id_spq_ets_uri = new ASN1ObjectIdentifier(id_spq + ".1");
+ static final ASN1ObjectIdentifier id_spq_ets_unotice = new ASN1ObjectIdentifier(id_spq + ".2");
+
+ //
+ // pkcs-12 OBJECT IDENTIFIER ::= {
+ // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 }
+ //
+ static final ASN1ObjectIdentifier pkcs_12 = new ASN1ObjectIdentifier("1.2.840.113549.1.12");
+ static final ASN1ObjectIdentifier bagtypes = pkcs_12.branch("10.1");
+
+ static final ASN1ObjectIdentifier keyBag = bagtypes.branch("1");
+ static final ASN1ObjectIdentifier pkcs8ShroudedKeyBag = bagtypes.branch("2");
+ static final ASN1ObjectIdentifier certBag = bagtypes.branch("3");
+ static final ASN1ObjectIdentifier crlBag = bagtypes.branch("4");
+ static final ASN1ObjectIdentifier secretBag = bagtypes.branch("5");
+ static final ASN1ObjectIdentifier safeContentsBag = bagtypes.branch("6");
+
+ static final ASN1ObjectIdentifier pkcs_12PbeIds = pkcs_12.branch("1");
+
+ static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC4 = pkcs_12PbeIds.branch("1");
+ static final ASN1ObjectIdentifier pbeWithSHAAnd40BitRC4 = pkcs_12PbeIds.branch("2");
+ static final ASN1ObjectIdentifier pbeWithSHAAnd3_KeyTripleDES_CBC = pkcs_12PbeIds.branch("3");
+ static final ASN1ObjectIdentifier pbeWithSHAAnd2_KeyTripleDES_CBC = pkcs_12PbeIds.branch("4");
+ static final ASN1ObjectIdentifier pbeWithSHAAnd128BitRC2_CBC = pkcs_12PbeIds.branch("5");
+ static final ASN1ObjectIdentifier pbeWithSHAAnd40BitRC2_CBC = pkcs_12PbeIds.branch("6");
+
+ /**
+ * @deprecated use pbeWithSHAAnd40BitRC2_CBC
+ */
+ static final ASN1ObjectIdentifier pbewithSHAAnd40BitRC2_CBC = pkcs_12PbeIds.branch("6");
+
+ static final ASN1ObjectIdentifier id_alg_CMS3DESwrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.6");
+ static final ASN1ObjectIdentifier id_alg_CMSRC2wrap = new ASN1ObjectIdentifier("1.2.840.113549.1.9.16.3.7");
+}
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/Pfx.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/Pfx.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/Pfx.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/Pfx.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,87 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+
+/**
+ * the infamous Pfx from PKCS12
+ */
+public class Pfx
+ extends ASN1Object
+ implements PKCSObjectIdentifiers
+{
+ private ContentInfo contentInfo;
+ private MacData macData = null;
+
+ private Pfx(
+ ASN1Sequence seq)
+ {
+ BigInteger version = ((ASN1Integer)seq.getObjectAt(0)).getValue();
+ if (version.intValue() != 3)
+ {
+ throw new IllegalArgumentException("wrong version for PFX PDU");
+ }
+
+ contentInfo = ContentInfo.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() == 3)
+ {
+ macData = MacData.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public static Pfx getInstance(
+ Object obj)
+ {
+ if (obj instanceof Pfx)
+ {
+ return (Pfx)obj;
+ }
+
+ if (obj != null)
+ {
+ return new Pfx(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public Pfx(
+ ContentInfo contentInfo,
+ MacData macData)
+ {
+ this.contentInfo = contentInfo;
+ this.macData = macData;
+ }
+
+ public ContentInfo getAuthSafe()
+ {
+ return contentInfo;
+ }
+
+ public MacData getMacData()
+ {
+ return macData;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(3));
+ v.add(contentInfo);
+
+ if (macData != null)
+ {
+ v.add(macData);
+ }
+
+ return new BERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/PrivateKeyInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,160 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Encoding;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class PrivateKeyInfo
+ extends ASN1Object
+{
+ private ASN1OctetString privKey;
+ private AlgorithmIdentifier algId;
+ private ASN1Set attributes;
+
+ public static PrivateKeyInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static PrivateKeyInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof PrivateKeyInfo)
+ {
+ return (PrivateKeyInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new PrivateKeyInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public PrivateKeyInfo(
+ AlgorithmIdentifier algId,
+ ASN1Encodable privateKey)
+ throws IOException
+ {
+ this(algId, privateKey, null);
+ }
+
+ public PrivateKeyInfo(
+ AlgorithmIdentifier algId,
+ ASN1Encodable privateKey,
+ ASN1Set attributes)
+ throws IOException
+ {
+ this.privKey = new DEROctetString(privateKey.toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ this.algId = algId;
+ this.attributes = attributes;
+ }
+
+ public PrivateKeyInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ BigInteger version = ((ASN1Integer)e.nextElement()).getValue();
+ if (version.intValue() != 0)
+ {
+ throw new IllegalArgumentException("wrong version for private key info");
+ }
+
+ algId = AlgorithmIdentifier.getInstance(e.nextElement());
+ privKey = ASN1OctetString.getInstance(e.nextElement());
+
+ if (e.hasMoreElements())
+ {
+ attributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
+ }
+ }
+
+ public AlgorithmIdentifier getPrivateKeyAlgorithm()
+ {
+ return algId;
+ }
+ /**
+ * @deprecated use getPrivateKeyAlgorithm()
+ */
+ public AlgorithmIdentifier getAlgorithmId()
+ {
+ return algId;
+ }
+
+ public ASN1Encodable parsePrivateKey()
+ throws IOException
+ {
+ return ASN1Primitive.fromByteArray(privKey.getOctets());
+ }
+
+ /**
+ * @deprecated use parsePrivateKey()
+ */
+ public ASN1Primitive getPrivateKey()
+ {
+ try
+ {
+ return parsePrivateKey().toASN1Primitive();
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("unable to parse private key");
+ }
+ }
+
+ public ASN1Set getAttributes()
+ {
+ return attributes;
+ }
+
+ /**
+ * write out an RSA private key with its associated information
+ * as described in PKCS8.
+ *
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
+ * privateKey PrivateKey,
+ * attributes [0] IMPLICIT Attributes OPTIONAL
+ * }
+ * Version ::= INTEGER {v1(0)} (v1,...)
+ *
+ * PrivateKey ::= OCTET STRING
+ *
+ * Attributes ::= SET OF Attribute
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(0));
+ v.add(algId);
+ v.add(privKey);
+
+ if (attributes != null)
+ {
+ v.add(new DERTaggedObject(false, 0, attributes));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/RC2CBCParameter.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,93 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class RC2CBCParameter
+ extends ASN1Object
+{
+ ASN1Integer version;
+ ASN1OctetString iv;
+
+ public static RC2CBCParameter getInstance(
+ Object o)
+ {
+ if (o instanceof RC2CBCParameter)
+ {
+ return (RC2CBCParameter)o;
+ }
+ if (o != null)
+ {
+ return new RC2CBCParameter(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public RC2CBCParameter(
+ byte[] iv)
+ {
+ this.version = null;
+ this.iv = new DEROctetString(iv);
+ }
+
+ public RC2CBCParameter(
+ int parameterVersion,
+ byte[] iv)
+ {
+ this.version = new ASN1Integer(parameterVersion);
+ this.iv = new DEROctetString(iv);
+ }
+
+ private RC2CBCParameter(
+ ASN1Sequence seq)
+ {
+ if (seq.size() == 1)
+ {
+ version = null;
+ iv = (ASN1OctetString)seq.getObjectAt(0);
+ }
+ else
+ {
+ version = (ASN1Integer)seq.getObjectAt(0);
+ iv = (ASN1OctetString)seq.getObjectAt(1);
+ }
+ }
+
+ public BigInteger getRC2ParameterVersion()
+ {
+ if (version == null)
+ {
+ return null;
+ }
+
+ return version.getValue();
+ }
+
+ public byte[] getIV()
+ {
+ return iv.getOctets();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (version != null)
+ {
+ v.add(version);
+ }
+
+ v.add(iv);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/RSAESOAEPparams.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,151 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERNull;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class RSAESOAEPparams
+ extends ASN1Object
+{
+ private AlgorithmIdentifier hashAlgorithm;
+ private AlgorithmIdentifier maskGenAlgorithm;
+ private AlgorithmIdentifier pSourceAlgorithm;
+
+ public final static AlgorithmIdentifier DEFAULT_HASH_ALGORITHM = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
+ public final static AlgorithmIdentifier DEFAULT_MASK_GEN_FUNCTION = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, DEFAULT_HASH_ALGORITHM);
+ public final static AlgorithmIdentifier DEFAULT_P_SOURCE_ALGORITHM = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_pSpecified, new DEROctetString(new byte[0]));
+
+ public static RSAESOAEPparams getInstance(
+ Object obj)
+ {
+ if (obj instanceof RSAESOAEPparams)
+ {
+ return (RSAESOAEPparams)obj;
+ }
+ else if (obj != null)
+ {
+ return new RSAESOAEPparams(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * The default version
+ */
+ public RSAESOAEPparams()
+ {
+ hashAlgorithm = DEFAULT_HASH_ALGORITHM;
+ maskGenAlgorithm = DEFAULT_MASK_GEN_FUNCTION;
+ pSourceAlgorithm = DEFAULT_P_SOURCE_ALGORITHM;
+ }
+
+ public RSAESOAEPparams(
+ AlgorithmIdentifier hashAlgorithm,
+ AlgorithmIdentifier maskGenAlgorithm,
+ AlgorithmIdentifier pSourceAlgorithm)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.maskGenAlgorithm = maskGenAlgorithm;
+ this.pSourceAlgorithm = pSourceAlgorithm;
+ }
+
+ public RSAESOAEPparams(
+ ASN1Sequence seq)
+ {
+ hashAlgorithm = DEFAULT_HASH_ALGORITHM;
+ maskGenAlgorithm = DEFAULT_MASK_GEN_FUNCTION;
+ pSourceAlgorithm = DEFAULT_P_SOURCE_ALGORITHM;
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(i);
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ hashAlgorithm = AlgorithmIdentifier.getInstance(o, true);
+ break;
+ case 1:
+ maskGenAlgorithm = AlgorithmIdentifier.getInstance(o, true);
+ break;
+ case 2:
+ pSourceAlgorithm = AlgorithmIdentifier.getInstance(o, true);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag");
+ }
+ }
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public AlgorithmIdentifier getMaskGenAlgorithm()
+ {
+ return maskGenAlgorithm;
+ }
+
+ public AlgorithmIdentifier getPSourceAlgorithm()
+ {
+ return pSourceAlgorithm;
+ }
+
+ /**
+ *
+ * RSAES-OAEP-params ::= SEQUENCE {
+ * hashAlgorithm [0] OAEP-PSSDigestAlgorithms DEFAULT sha1,
+ * maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1,
+ * pSourceAlgorithm [2] PKCS1PSourceAlgorithms DEFAULT pSpecifiedEmpty
+ * }
+ *
+ * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-sha1 PARAMETERS NULL }|
+ * { OID id-sha256 PARAMETERS NULL }|
+ * { OID id-sha384 PARAMETERS NULL }|
+ * { OID id-sha512 PARAMETERS NULL },
+ * ... -- Allows for future expansion --
+ * }
+ * PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+ * ... -- Allows for future expansion --
+ * }
+ * PKCS1PSourceAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-pSpecified PARAMETERS OCTET STRING },
+ * ... -- Allows for future expansion --
+ * }
+ *
+ * @return the asn1 primitive representing the parameters.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (!hashAlgorithm.equals(DEFAULT_HASH_ALGORITHM))
+ {
+ v.add(new DERTaggedObject(true, 0, hashAlgorithm));
+ }
+
+ if (!maskGenAlgorithm.equals(DEFAULT_MASK_GEN_FUNCTION))
+ {
+ v.add(new DERTaggedObject(true, 1, maskGenAlgorithm));
+ }
+
+ if (!pSourceAlgorithm.equals(DEFAULT_P_SOURCE_ALGORITHM))
+ {
+ v.add(new DERTaggedObject(true, 2, pSourceAlgorithm));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/RSAPrivateKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/RSAPrivateKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/RSAPrivateKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/RSAPrivateKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,187 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class RSAPrivateKey
+ extends ASN1Object
+{
+ private BigInteger version;
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+ private BigInteger privateExponent;
+ private BigInteger prime1;
+ private BigInteger prime2;
+ private BigInteger exponent1;
+ private BigInteger exponent2;
+ private BigInteger coefficient;
+ private ASN1Sequence otherPrimeInfos = null;
+
+ public static RSAPrivateKey getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static RSAPrivateKey getInstance(
+ Object obj)
+ {
+ if (obj instanceof RSAPrivateKey)
+ {
+ return (RSAPrivateKey)obj;
+ }
+
+ if (obj != null)
+ {
+ return new RSAPrivateKey(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public RSAPrivateKey(
+ BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger prime1,
+ BigInteger prime2,
+ BigInteger exponent1,
+ BigInteger exponent2,
+ BigInteger coefficient)
+ {
+ this.version = BigInteger.valueOf(0);
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ this.privateExponent = privateExponent;
+ this.prime1 = prime1;
+ this.prime2 = prime2;
+ this.exponent1 = exponent1;
+ this.exponent2 = exponent2;
+ this.coefficient = coefficient;
+ }
+
+ private RSAPrivateKey(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ BigInteger v = ((ASN1Integer)e.nextElement()).getValue();
+ if (v.intValue() != 0 && v.intValue() != 1)
+ {
+ throw new IllegalArgumentException("wrong version for RSA private key");
+ }
+
+ version = v;
+ modulus = ((ASN1Integer)e.nextElement()).getValue();
+ publicExponent = ((ASN1Integer)e.nextElement()).getValue();
+ privateExponent = ((ASN1Integer)e.nextElement()).getValue();
+ prime1 = ((ASN1Integer)e.nextElement()).getValue();
+ prime2 = ((ASN1Integer)e.nextElement()).getValue();
+ exponent1 = ((ASN1Integer)e.nextElement()).getValue();
+ exponent2 = ((ASN1Integer)e.nextElement()).getValue();
+ coefficient = ((ASN1Integer)e.nextElement()).getValue();
+
+ if (e.hasMoreElements())
+ {
+ otherPrimeInfos = (ASN1Sequence)e.nextElement();
+ }
+ }
+
+ public BigInteger getVersion()
+ {
+ return version;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+
+ public BigInteger getPrivateExponent()
+ {
+ return privateExponent;
+ }
+
+ public BigInteger getPrime1()
+ {
+ return prime1;
+ }
+
+ public BigInteger getPrime2()
+ {
+ return prime2;
+ }
+
+ public BigInteger getExponent1()
+ {
+ return exponent1;
+ }
+
+ public BigInteger getExponent2()
+ {
+ return exponent2;
+ }
+
+ public BigInteger getCoefficient()
+ {
+ return coefficient;
+ }
+
+ /**
+ * This outputs the key in PKCS1v2 format.
+ *
+ * RSAPrivateKey ::= SEQUENCE {
+ * version Version,
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * otherPrimeInfos OtherPrimeInfos OPTIONAL
+ * }
+ *
+ * Version ::= INTEGER { two-prime(0), multi(1) }
+ * (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
+ *
+ *
+ * This routine is written to output PKCS1 version 2.1, private keys.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(version)); // version
+ v.add(new ASN1Integer(getModulus()));
+ v.add(new ASN1Integer(getPublicExponent()));
+ v.add(new ASN1Integer(getPrivateExponent()));
+ v.add(new ASN1Integer(getPrime1()));
+ v.add(new ASN1Integer(getPrime2()));
+ v.add(new ASN1Integer(getExponent1()));
+ v.add(new ASN1Integer(getExponent2()));
+ v.add(new ASN1Integer(getCoefficient()));
+
+ if (otherPrimeInfos != null)
+ {
+ v.add(otherPrimeInfos);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/RSAPrivateKeyStructure.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,189 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * @deprecated use RSAPrivateKey
+ */
+public class RSAPrivateKeyStructure
+ extends ASN1Object
+{
+ private int version;
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+ private BigInteger privateExponent;
+ private BigInteger prime1;
+ private BigInteger prime2;
+ private BigInteger exponent1;
+ private BigInteger exponent2;
+ private BigInteger coefficient;
+ private ASN1Sequence otherPrimeInfos = null;
+
+ public static RSAPrivateKeyStructure getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static RSAPrivateKeyStructure getInstance(
+ Object obj)
+ {
+ if (obj instanceof RSAPrivateKeyStructure)
+ {
+ return (RSAPrivateKeyStructure)obj;
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new RSAPrivateKeyStructure((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public RSAPrivateKeyStructure(
+ BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger prime1,
+ BigInteger prime2,
+ BigInteger exponent1,
+ BigInteger exponent2,
+ BigInteger coefficient)
+ {
+ this.version = 0;
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ this.privateExponent = privateExponent;
+ this.prime1 = prime1;
+ this.prime2 = prime2;
+ this.exponent1 = exponent1;
+ this.exponent2 = exponent2;
+ this.coefficient = coefficient;
+ }
+
+ public RSAPrivateKeyStructure(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ BigInteger v = ((ASN1Integer)e.nextElement()).getValue();
+ if (v.intValue() != 0 && v.intValue() != 1)
+ {
+ throw new IllegalArgumentException("wrong version for RSA private key");
+ }
+
+ version = v.intValue();
+ modulus = ((ASN1Integer)e.nextElement()).getValue();
+ publicExponent = ((ASN1Integer)e.nextElement()).getValue();
+ privateExponent = ((ASN1Integer)e.nextElement()).getValue();
+ prime1 = ((ASN1Integer)e.nextElement()).getValue();
+ prime2 = ((ASN1Integer)e.nextElement()).getValue();
+ exponent1 = ((ASN1Integer)e.nextElement()).getValue();
+ exponent2 = ((ASN1Integer)e.nextElement()).getValue();
+ coefficient = ((ASN1Integer)e.nextElement()).getValue();
+
+ if (e.hasMoreElements())
+ {
+ otherPrimeInfos = (ASN1Sequence)e.nextElement();
+ }
+ }
+
+ public int getVersion()
+ {
+ return version;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+
+ public BigInteger getPrivateExponent()
+ {
+ return privateExponent;
+ }
+
+ public BigInteger getPrime1()
+ {
+ return prime1;
+ }
+
+ public BigInteger getPrime2()
+ {
+ return prime2;
+ }
+
+ public BigInteger getExponent1()
+ {
+ return exponent1;
+ }
+
+ public BigInteger getExponent2()
+ {
+ return exponent2;
+ }
+
+ public BigInteger getCoefficient()
+ {
+ return coefficient;
+ }
+
+ /**
+ * This outputs the key in PKCS1v2 format.
+ *
+ * RSAPrivateKey ::= SEQUENCE {
+ * version Version,
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * otherPrimeInfos OtherPrimeInfos OPTIONAL
+ * }
+ *
+ * Version ::= INTEGER { two-prime(0), multi(1) }
+ * (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
+ *
+ *
+ * This routine is written to output PKCS1 version 2.1, private keys.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(version)); // version
+ v.add(new ASN1Integer(getModulus()));
+ v.add(new ASN1Integer(getPublicExponent()));
+ v.add(new ASN1Integer(getPrivateExponent()));
+ v.add(new ASN1Integer(getPrime1()));
+ v.add(new ASN1Integer(getPrime2()));
+ v.add(new ASN1Integer(getExponent1()));
+ v.add(new ASN1Integer(getExponent2()));
+ v.add(new ASN1Integer(getCoefficient()));
+
+ if (otherPrimeInfos != null)
+ {
+ v.add(otherPrimeInfos);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/RSAPublicKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/RSAPublicKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/RSAPublicKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/RSAPublicKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,95 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class RSAPublicKey
+ extends ASN1Object
+{
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+
+ public static RSAPublicKey getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static RSAPublicKey getInstance(
+ Object obj)
+ {
+ if (obj instanceof RSAPublicKey)
+ {
+ return (RSAPublicKey)obj;
+ }
+
+ if (obj != null)
+ {
+ return new RSAPublicKey(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public RSAPublicKey(
+ BigInteger modulus,
+ BigInteger publicExponent)
+ {
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ }
+
+ private RSAPublicKey(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ modulus = ASN1Integer.getInstance(e.nextElement()).getPositiveValue();
+ publicExponent = ASN1Integer.getInstance(e.nextElement()).getPositiveValue();
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+
+ /**
+ * This outputs the key in PKCS1v2 format.
+ *
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * }
+ *
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(getModulus()));
+ v.add(new ASN1Integer(getPublicExponent()));
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/RSASSAPSSparams.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,172 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERNull;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class RSASSAPSSparams
+ extends ASN1Object
+{
+ private AlgorithmIdentifier hashAlgorithm;
+ private AlgorithmIdentifier maskGenAlgorithm;
+ private ASN1Integer saltLength;
+ private ASN1Integer trailerField;
+
+ public final static AlgorithmIdentifier DEFAULT_HASH_ALGORITHM = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE);
+ public final static AlgorithmIdentifier DEFAULT_MASK_GEN_FUNCTION = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_mgf1, DEFAULT_HASH_ALGORITHM);
+ public final static ASN1Integer DEFAULT_SALT_LENGTH = new ASN1Integer(20);
+ public final static ASN1Integer DEFAULT_TRAILER_FIELD = new ASN1Integer(1);
+
+ public static RSASSAPSSparams getInstance(
+ Object obj)
+ {
+ if (obj instanceof RSASSAPSSparams)
+ {
+ return (RSASSAPSSparams)obj;
+ }
+ else if (obj != null)
+ {
+ return new RSASSAPSSparams(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * The default version
+ */
+ public RSASSAPSSparams()
+ {
+ hashAlgorithm = DEFAULT_HASH_ALGORITHM;
+ maskGenAlgorithm = DEFAULT_MASK_GEN_FUNCTION;
+ saltLength = DEFAULT_SALT_LENGTH;
+ trailerField = DEFAULT_TRAILER_FIELD;
+ }
+
+ public RSASSAPSSparams(
+ AlgorithmIdentifier hashAlgorithm,
+ AlgorithmIdentifier maskGenAlgorithm,
+ ASN1Integer saltLength,
+ ASN1Integer trailerField)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.maskGenAlgorithm = maskGenAlgorithm;
+ this.saltLength = saltLength;
+ this.trailerField = trailerField;
+ }
+
+ private RSASSAPSSparams(
+ ASN1Sequence seq)
+ {
+ hashAlgorithm = DEFAULT_HASH_ALGORITHM;
+ maskGenAlgorithm = DEFAULT_MASK_GEN_FUNCTION;
+ saltLength = DEFAULT_SALT_LENGTH;
+ trailerField = DEFAULT_TRAILER_FIELD;
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject o = (ASN1TaggedObject)seq.getObjectAt(i);
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ hashAlgorithm = AlgorithmIdentifier.getInstance(o, true);
+ break;
+ case 1:
+ maskGenAlgorithm = AlgorithmIdentifier.getInstance(o, true);
+ break;
+ case 2:
+ saltLength = ASN1Integer.getInstance(o, true);
+ break;
+ case 3:
+ trailerField = ASN1Integer.getInstance(o, true);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag");
+ }
+ }
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public AlgorithmIdentifier getMaskGenAlgorithm()
+ {
+ return maskGenAlgorithm;
+ }
+
+ public BigInteger getSaltLength()
+ {
+ return saltLength.getValue();
+ }
+
+ public BigInteger getTrailerField()
+ {
+ return trailerField.getValue();
+ }
+
+ /**
+ *
+ * RSASSA-PSS-params ::= SEQUENCE {
+ * hashAlgorithm [0] OAEP-PSSDigestAlgorithms DEFAULT sha1,
+ * maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1,
+ * saltLength [2] INTEGER DEFAULT 20,
+ * trailerField [3] TrailerField DEFAULT trailerFieldBC
+ * }
+ *
+ * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-sha1 PARAMETERS NULL }|
+ * { OID id-sha256 PARAMETERS NULL }|
+ * { OID id-sha384 PARAMETERS NULL }|
+ * { OID id-sha512 PARAMETERS NULL },
+ * ... -- Allows for future expansion --
+ * }
+ *
+ * PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+ * ... -- Allows for future expansion --
+ * }
+ *
+ * TrailerField ::= INTEGER { trailerFieldBC(1) }
+ *
+ * @return the asn1 primitive representing the parameters.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (!hashAlgorithm.equals(DEFAULT_HASH_ALGORITHM))
+ {
+ v.add(new DERTaggedObject(true, 0, hashAlgorithm));
+ }
+
+ if (!maskGenAlgorithm.equals(DEFAULT_MASK_GEN_FUNCTION))
+ {
+ v.add(new DERTaggedObject(true, 1, maskGenAlgorithm));
+ }
+
+ if (!saltLength.equals(DEFAULT_SALT_LENGTH))
+ {
+ v.add(new DERTaggedObject(true, 2, saltLength));
+ }
+
+ if (!trailerField.equals(DEFAULT_TRAILER_FIELD))
+ {
+ v.add(new DERTaggedObject(true, 3, trailerField));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/SafeBag.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/SafeBag.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/SafeBag.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/SafeBag.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,96 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DLSequence;
+import pdftk.org.bouncycastle.asn1.DLTaggedObject;
+
+public class SafeBag
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier bagId;
+ private ASN1Encodable bagValue;
+ private ASN1Set bagAttributes;
+
+ public SafeBag(
+ ASN1ObjectIdentifier oid,
+ ASN1Encodable obj)
+ {
+ this.bagId = oid;
+ this.bagValue = obj;
+ this.bagAttributes = null;
+ }
+
+ public SafeBag(
+ ASN1ObjectIdentifier oid,
+ ASN1Encodable obj,
+ ASN1Set bagAttributes)
+ {
+ this.bagId = oid;
+ this.bagValue = obj;
+ this.bagAttributes = bagAttributes;
+ }
+
+ public static SafeBag getInstance(
+ Object obj)
+ {
+ if (obj instanceof SafeBag)
+ {
+ return (SafeBag)obj;
+ }
+
+ if (obj != null)
+ {
+ return new SafeBag(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private SafeBag(
+ ASN1Sequence seq)
+ {
+ this.bagId = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ this.bagValue = ((ASN1TaggedObject)seq.getObjectAt(1)).getObject();
+ if (seq.size() == 3)
+ {
+ this.bagAttributes = (ASN1Set)seq.getObjectAt(2);
+ }
+ }
+
+ public ASN1ObjectIdentifier getBagId()
+ {
+ return bagId;
+ }
+
+ public ASN1Encodable getBagValue()
+ {
+ return bagValue;
+ }
+
+ public ASN1Set getBagAttributes()
+ {
+ return bagAttributes;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(bagId);
+ v.add(new DLTaggedObject(true, 0, bagValue));
+
+ if (bagAttributes != null)
+ {
+ v.add(bagAttributes);
+ }
+
+ return new DLSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/SignedData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/SignedData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/SignedData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/SignedData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,167 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * a PKCS#7 signed data object.
+ */
+public class SignedData
+ extends ASN1Object
+ implements PKCSObjectIdentifiers
+{
+ private ASN1Integer version;
+ private ASN1Set digestAlgorithms;
+ private ContentInfo contentInfo;
+ private ASN1Set certificates;
+ private ASN1Set crls;
+ private ASN1Set signerInfos;
+
+ public static SignedData getInstance(
+ Object o)
+ {
+ if (o instanceof SignedData)
+ {
+ return (SignedData)o;
+ }
+ else if (o != null)
+ {
+ return new SignedData(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public SignedData(
+ ASN1Integer _version,
+ ASN1Set _digestAlgorithms,
+ ContentInfo _contentInfo,
+ ASN1Set _certificates,
+ ASN1Set _crls,
+ ASN1Set _signerInfos)
+ {
+ version = _version;
+ digestAlgorithms = _digestAlgorithms;
+ contentInfo = _contentInfo;
+ certificates = _certificates;
+ crls = _crls;
+ signerInfos = _signerInfos;
+ }
+
+ public SignedData(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ version = (ASN1Integer)e.nextElement();
+ digestAlgorithms = ((ASN1Set)e.nextElement());
+ contentInfo = ContentInfo.getInstance(e.nextElement());
+
+ while (e.hasMoreElements())
+ {
+ ASN1Primitive o = (ASN1Primitive)e.nextElement();
+
+ //
+ // an interesting feature of SignedData is that there appear to be varying implementations...
+ // for the moment we ignore anything which doesn't fit.
+ //
+ if (o instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagged = (ASN1TaggedObject)o;
+
+ switch (tagged.getTagNo())
+ {
+ case 0:
+ certificates = ASN1Set.getInstance(tagged, false);
+ break;
+ case 1:
+ crls = ASN1Set.getInstance(tagged, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag value " + tagged.getTagNo());
+ }
+ }
+ else
+ {
+ signerInfos = (ASN1Set)o;
+ }
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public ASN1Set getDigestAlgorithms()
+ {
+ return digestAlgorithms;
+ }
+
+ public ContentInfo getContentInfo()
+ {
+ return contentInfo;
+ }
+
+ public ASN1Set getCertificates()
+ {
+ return certificates;
+ }
+
+ public ASN1Set getCRLs()
+ {
+ return crls;
+ }
+
+ public ASN1Set getSignerInfos()
+ {
+ return signerInfos;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * SignedData ::= SEQUENCE {
+ * version Version,
+ * digestAlgorithms DigestAlgorithmIdentifiers,
+ * contentInfo ContentInfo,
+ * certificates
+ * [0] IMPLICIT ExtendedCertificatesAndCertificates
+ * OPTIONAL,
+ * crls
+ * [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ * signerInfos SignerInfos }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(digestAlgorithms);
+ v.add(contentInfo);
+
+ if (certificates != null)
+ {
+ v.add(new DERTaggedObject(false, 0, certificates));
+ }
+
+ if (crls != null)
+ {
+ v.add(new DERTaggedObject(false, 1, crls));
+ }
+
+ v.add(signerInfos);
+
+ return new BERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/SignerInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/SignerInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/SignerInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/SignerInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,178 @@
+package pdftk.org.bouncycastle.asn1.pkcs;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * a PKCS#7 signer info object.
+ */
+public class SignerInfo
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private IssuerAndSerialNumber issuerAndSerialNumber;
+ private AlgorithmIdentifier digAlgorithm;
+ private ASN1Set authenticatedAttributes;
+ private AlgorithmIdentifier digEncryptionAlgorithm;
+ private ASN1OctetString encryptedDigest;
+ private ASN1Set unauthenticatedAttributes;
+
+ public static SignerInfo getInstance(
+ Object o)
+ {
+ if (o instanceof SignerInfo)
+ {
+ return (SignerInfo)o;
+ }
+ else if (o instanceof ASN1Sequence)
+ {
+ return new SignerInfo((ASN1Sequence)o);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
+ }
+
+ public SignerInfo(
+ ASN1Integer version,
+ IssuerAndSerialNumber issuerAndSerialNumber,
+ AlgorithmIdentifier digAlgorithm,
+ ASN1Set authenticatedAttributes,
+ AlgorithmIdentifier digEncryptionAlgorithm,
+ ASN1OctetString encryptedDigest,
+ ASN1Set unauthenticatedAttributes)
+ {
+ this.version = version;
+ this.issuerAndSerialNumber = issuerAndSerialNumber;
+ this.digAlgorithm = digAlgorithm;
+ this.authenticatedAttributes = authenticatedAttributes;
+ this.digEncryptionAlgorithm = digEncryptionAlgorithm;
+ this.encryptedDigest = encryptedDigest;
+ this.unauthenticatedAttributes = unauthenticatedAttributes;
+ }
+
+ public SignerInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ version = (ASN1Integer)e.nextElement();
+ issuerAndSerialNumber = IssuerAndSerialNumber.getInstance(e.nextElement());
+ digAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
+
+ Object obj = e.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ authenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)obj, false);
+
+ digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
+ }
+ else
+ {
+ authenticatedAttributes = null;
+ digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(obj);
+ }
+
+ encryptedDigest = DEROctetString.getInstance(e.nextElement());
+
+ if (e.hasMoreElements())
+ {
+ unauthenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false);
+ }
+ else
+ {
+ unauthenticatedAttributes = null;
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public IssuerAndSerialNumber getIssuerAndSerialNumber()
+ {
+ return issuerAndSerialNumber;
+ }
+
+ public ASN1Set getAuthenticatedAttributes()
+ {
+ return authenticatedAttributes;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ {
+ return digAlgorithm;
+ }
+
+ public ASN1OctetString getEncryptedDigest()
+ {
+ return encryptedDigest;
+ }
+
+ public AlgorithmIdentifier getDigestEncryptionAlgorithm()
+ {
+ return digEncryptionAlgorithm;
+ }
+
+ public ASN1Set getUnauthenticatedAttributes()
+ {
+ return unauthenticatedAttributes;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * SignerInfo ::= SEQUENCE {
+ * version Version,
+ * issuerAndSerialNumber IssuerAndSerialNumber,
+ * digestAlgorithm DigestAlgorithmIdentifier,
+ * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+ * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ * encryptedDigest EncryptedDigest,
+ * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+ * }
+ *
+ * EncryptedDigest ::= OCTET STRING
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(issuerAndSerialNumber);
+ v.add(digAlgorithm);
+
+ if (authenticatedAttributes != null)
+ {
+ v.add(new DERTaggedObject(false, 0, authenticatedAttributes));
+ }
+
+ v.add(digEncryptionAlgorithm);
+ v.add(encryptedDigest);
+
+ if (unauthenticatedAttributes != null)
+ {
+ v.add(new DERTaggedObject(false, 1, unauthenticatedAttributes));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/pkcs/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/pkcs/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes useful for encoding and supporting the various RSA PKCS documents.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/sec/ECPrivateKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/sec/ECPrivateKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/sec/ECPrivateKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/sec/ECPrivateKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,143 @@
+package pdftk.org.bouncycastle.asn1.sec;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+/**
+ * the elliptic curve private key object from SEC 1
+ */
+public class ECPrivateKey
+ extends ASN1Object
+{
+ private ASN1Sequence seq;
+
+ private ECPrivateKey(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+ }
+
+ public static ECPrivateKey getInstance(
+ Object obj)
+ {
+ if (obj instanceof ECPrivateKey)
+ {
+ return (ECPrivateKey)obj;
+ }
+
+ if (obj != null)
+ {
+ return new ECPrivateKey(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ECPrivateKey(
+ BigInteger key)
+ {
+ byte[] bytes = BigIntegers.asUnsignedByteArray(key);
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(1));
+ v.add(new DEROctetString(bytes));
+
+ seq = new DERSequence(v);
+ }
+
+ public ECPrivateKey(
+ BigInteger key,
+ ASN1Object parameters)
+ {
+ this(key, null, parameters);
+ }
+
+ public ECPrivateKey(
+ BigInteger key,
+ DERBitString publicKey,
+ ASN1Object parameters)
+ {
+ byte[] bytes = BigIntegers.asUnsignedByteArray(key);
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(1));
+ v.add(new DEROctetString(bytes));
+
+ if (parameters != null)
+ {
+ v.add(new DERTaggedObject(true, 0, parameters));
+ }
+
+ if (publicKey != null)
+ {
+ v.add(new DERTaggedObject(true, 1, publicKey));
+ }
+
+ seq = new DERSequence(v);
+ }
+
+ public BigInteger getKey()
+ {
+ ASN1OctetString octs = (ASN1OctetString)seq.getObjectAt(1);
+
+ return new BigInteger(1, octs.getOctets());
+ }
+
+ public DERBitString getPublicKey()
+ {
+ return (DERBitString)getObjectInTag(1);
+ }
+
+ public ASN1Primitive getParameters()
+ {
+ return getObjectInTag(0);
+ }
+
+ private ASN1Primitive getObjectInTag(int tagNo)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Encodable obj = (ASN1Encodable)e.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tag = (ASN1TaggedObject)obj;
+ if (tag.getTagNo() == tagNo)
+ {
+ return tag.getObject().toASN1Primitive();
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * ECPrivateKey ::= SEQUENCE {
+ * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ * privateKey OCTET STRING,
+ * parameters [0] Parameters OPTIONAL,
+ * publicKey [1] BIT STRING OPTIONAL }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/sec/ECPrivateKeyStructure.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,128 @@
+package pdftk.org.bouncycastle.asn1.sec;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+/**
+ * the elliptic curve private key object from SEC 1
+ * @deprecated use ECPrivateKey
+ */
+public class ECPrivateKeyStructure
+ extends ASN1Object
+{
+ private ASN1Sequence seq;
+
+ public ECPrivateKeyStructure(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+ }
+
+ public ECPrivateKeyStructure(
+ BigInteger key)
+ {
+ byte[] bytes = BigIntegers.asUnsignedByteArray(key);
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(1));
+ v.add(new DEROctetString(bytes));
+
+ seq = new DERSequence(v);
+ }
+
+ public ECPrivateKeyStructure(
+ BigInteger key,
+ ASN1Encodable parameters)
+ {
+ this(key, null, parameters);
+ }
+
+ public ECPrivateKeyStructure(
+ BigInteger key,
+ DERBitString publicKey,
+ ASN1Encodable parameters)
+ {
+ byte[] bytes = BigIntegers.asUnsignedByteArray(key);
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(1));
+ v.add(new DEROctetString(bytes));
+
+ if (parameters != null)
+ {
+ v.add(new DERTaggedObject(true, 0, parameters));
+ }
+
+ if (publicKey != null)
+ {
+ v.add(new DERTaggedObject(true, 1, publicKey));
+ }
+
+ seq = new DERSequence(v);
+ }
+
+ public BigInteger getKey()
+ {
+ ASN1OctetString octs = (ASN1OctetString)seq.getObjectAt(1);
+
+ return new BigInteger(1, octs.getOctets());
+ }
+
+ public DERBitString getPublicKey()
+ {
+ return (DERBitString)getObjectInTag(1);
+ }
+
+ public ASN1Primitive getParameters()
+ {
+ return getObjectInTag(0);
+ }
+
+ private ASN1Primitive getObjectInTag(int tagNo)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Encodable obj = (ASN1Encodable)e.nextElement();
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tag = (ASN1TaggedObject)obj;
+ if (tag.getTagNo() == tagNo)
+ {
+ return (ASN1Primitive)((ASN1Encodable)tag.getObject()).toASN1Primitive();
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * ECPrivateKey ::= SEQUENCE {
+ * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ * privateKey OCTET STRING,
+ * parameters [0] Parameters OPTIONAL,
+ * publicKey [1] BIT STRING OPTIONAL }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/sec/SECNamedCurves.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/sec/SECNamedCurves.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/sec/SECNamedCurves.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/sec/SECNamedCurves.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,1029 @@
+package pdftk.org.bouncycastle.asn1.sec;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.x9.X9ECParameters;
+import pdftk.org.bouncycastle.asn1.x9.X9ECParametersHolder;
+import pdftk.org.bouncycastle.math.ec.ECConstants;
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+import pdftk.org.bouncycastle.util.Strings;
+import pdftk.org.bouncycastle.util.encoders.Hex;
+
+public class SECNamedCurves
+{
+ private static BigInteger fromHex(
+ String hex)
+ {
+ return new BigInteger(1, Hex.decode(hex));
+ }
+
+ /*
+ * secp112r1
+ */
+ static X9ECParametersHolder secp112r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = (2^128 - 3) / 76439
+ BigInteger p = fromHex("DB7C2ABF62E35E668076BEAD208B");
+ BigInteger a = fromHex("DB7C2ABF62E35E668076BEAD2088");
+ BigInteger b = fromHex("659EF8BA043916EEDE8911702B22");
+ byte[] S = Hex.decode("00F50B028E4D696E676875615175290472783FB1");
+ BigInteger n = fromHex("DB7C2ABF62E35E7628DFAC6561C5");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "09487239995A5EE76B55F9C2F098"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "09487239995A5EE76B55F9C2F098"
+ + "A89CE5AF8724C0A23E0E0FF77500"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp112r2
+ */
+ static X9ECParametersHolder secp112r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = (2^128 - 3) / 76439
+ BigInteger p = fromHex("DB7C2ABF62E35E668076BEAD208B");
+ BigInteger a = fromHex("6127C24C05F38A0AAAF65C0EF02C");
+ BigInteger b = fromHex("51DEF1815DB5ED74FCC34C85D709");
+ byte[] S = Hex.decode("002757A1114D696E6768756151755316C05E0BD4");
+ BigInteger n = fromHex("36DF0AAFD8B8D7597CA10520D04B");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "4BA30AB5E892B4E1649DD0928643"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "4BA30AB5E892B4E1649DD0928643"
+ + "ADCD46F5882E3747DEF36E956E97"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp128r1
+ */
+ static X9ECParametersHolder secp128r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^128 - 2^97 - 1
+ BigInteger p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
+ BigInteger a = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC");
+ BigInteger b = fromHex("E87579C11079F43DD824993C2CEE5ED3");
+ byte[] S = Hex.decode("000E0D4D696E6768756151750CC03A4473D03679");
+ BigInteger n = fromHex("FFFFFFFE0000000075A30D1B9038A115");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "161FF7528B899B2D0C28607CA52C5B86"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "161FF7528B899B2D0C28607CA52C5B86"
+ + "CF5AC8395BAFEB13C02DA292DDED7A83"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp128r2
+ */
+ static X9ECParametersHolder secp128r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^128 - 2^97 - 1
+ BigInteger p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
+ BigInteger a = fromHex("D6031998D1B3BBFEBF59CC9BBFF9AEE1");
+ BigInteger b = fromHex("5EEEFCA380D02919DC2C6558BB6D8A5D");
+ byte[] S = Hex.decode("004D696E67687561517512D8F03431FCE63B88F4");
+ BigInteger n = fromHex("3FFFFFFF7FFFFFFFBE0024720613B5A3");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "7B6AA5D85E572983E6FB32A7CDEBC140"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "7B6AA5D85E572983E6FB32A7CDEBC140"
+ + "27B6916A894D3AEE7106FE805FC34B44"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp160k1
+ */
+ static X9ECParametersHolder secp160k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73");
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(7);
+ byte[] S = null;
+ BigInteger n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+// ECPoint G = curve.decodePoint(Hex.decode("02"
+// + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
+ + "938CF935318FDCED6BC28286531733C3F03C4FEE"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp160r1
+ */
+ static X9ECParametersHolder secp160r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^160 - 2^31 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF");
+ BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC");
+ BigInteger b = fromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45");
+ byte[] S = Hex.decode("1053CDE42C14D696E67687561517533BF3F83345");
+ BigInteger n = fromHex("0100000000000000000001F4C8F927AED3CA752257");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "4A96B5688EF573284664698968C38BB913CBFC82"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "4A96B5688EF573284664698968C38BB913CBFC82"
+ + "23A628553168947D59DCC912042351377AC5FB32"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp160r2
+ */
+ static X9ECParametersHolder secp160r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73");
+ BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70");
+ BigInteger b = fromHex("B4E134D3FB59EB8BAB57274904664D5AF50388BA");
+ byte[] S = Hex.decode("B99B99B099B323E02709A4D696E6768756151751");
+ BigInteger n = fromHex("0100000000000000000000351EE786A818F3A1A16B");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "52DCB034293A117E1F4FF11B30F7199D3144CE6D"
+ + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp192k1
+ */
+ static X9ECParametersHolder secp192k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37");
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(3);
+ byte[] S = null;
+ BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
+ + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp192r1
+ */
+ static X9ECParametersHolder secp192r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^192 - 2^64 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF");
+ BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC");
+ BigInteger b = fromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1");
+ byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
+ BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
+ + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp224k1
+ */
+ static X9ECParametersHolder secp224k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D");
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(5);
+ byte[] S = null;
+ BigInteger n = fromHex("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
+ + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp224r1
+ */
+ static X9ECParametersHolder secp224r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^224 - 2^96 + 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001");
+ BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE");
+ BigInteger b = fromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4");
+ byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
+ BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
+ + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp256k1
+ */
+ static X9ECParametersHolder secp256k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(7);
+ byte[] S = null;
+ BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
+ + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp256r1
+ */
+ static X9ECParametersHolder secp256r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1
+ BigInteger p = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF");
+ BigInteger a = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC");
+ BigInteger b = fromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B");
+ byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90");
+ BigInteger n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
+ + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp384r1
+ */
+ static X9ECParametersHolder secp384r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^384 - 2^128 - 2^96 + 2^32 - 1
+ BigInteger p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF");
+ BigInteger a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC");
+ BigInteger b = fromHex("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF");
+ byte[] S = Hex.decode("A335926AA319A27A1D00896A6773A4827ACDAC73");
+ BigInteger n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
+ + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * secp521r1
+ */
+ static X9ECParametersHolder secp521r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ // p = 2^521 - 1
+ BigInteger p = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
+ BigInteger a = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC");
+ BigInteger b = fromHex("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00");
+ byte[] S = Hex.decode("D09E8800291CB85396CC6717393284AAA0DA64BA");
+ BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409");
+ BigInteger h = BigInteger.valueOf(1);
+
+ ECCurve curve = new ECCurve.Fp(p, a, b);
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
+ + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect113r1
+ */
+ static X9ECParametersHolder sect113r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 113;
+ int k = 9;
+
+ BigInteger a = fromHex("003088250CA6E7C7FE649CE85820F7");
+ BigInteger b = fromHex("00E8BEE4D3E2260744188BE0E9C723");
+ byte[] S = Hex.decode("10E723AB14D696E6768756151756FEBF8FCB49A9");
+ BigInteger n = fromHex("0100000000000000D9CCEC8A39E56F");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "009D73616F35F4AB1407D73562C10F"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "009D73616F35F4AB1407D73562C10F"
+ + "00A52830277958EE84D1315ED31886"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect113r2
+ */
+ static X9ECParametersHolder sect113r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 113;
+ int k = 9;
+
+ BigInteger a = fromHex("00689918DBEC7E5A0DD6DFC0AA55C7");
+ BigInteger b = fromHex("0095E9A9EC9B297BD4BF36E059184F");
+ byte[] S = Hex.decode("10C0FB15760860DEF1EEF4D696E676875615175D");
+ BigInteger n = fromHex("010000000000000108789B2496AF93");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "01A57A6A7B26CA5EF52FCDB8164797"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "01A57A6A7B26CA5EF52FCDB8164797"
+ + "00B3ADC94ED1FE674C06E695BABA1D"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect131r1
+ */
+ static X9ECParametersHolder sect131r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 131;
+ int k1 = 2;
+ int k2 = 3;
+ int k3 = 8;
+
+ BigInteger a = fromHex("07A11B09A76B562144418FF3FF8C2570B8");
+ BigInteger b = fromHex("0217C05610884B63B9C6C7291678F9D341");
+ byte[] S = Hex.decode("4D696E676875615175985BD3ADBADA21B43A97E2");
+ BigInteger n = fromHex("0400000000000000023123953A9464B54D");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "0081BAF91FDF9833C40F9C181343638399"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "0081BAF91FDF9833C40F9C181343638399"
+ + "078C6E7EA38C001F73C8134B1B4EF9E150"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect131r2
+ */
+ static X9ECParametersHolder sect131r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 131;
+ int k1 = 2;
+ int k2 = 3;
+ int k3 = 8;
+
+ BigInteger a = fromHex("03E5A88919D7CAFCBF415F07C2176573B2");
+ BigInteger b = fromHex("04B8266A46C55657AC734CE38F018F2192");
+ byte[] S = Hex.decode("985BD3ADBAD4D696E676875615175A21B43A97E3");
+ BigInteger n = fromHex("0400000000000000016954A233049BA98F");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "0356DCD8F2F95031AD652D23951BB366A8"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "0356DCD8F2F95031AD652D23951BB366A8"
+ + "0648F06D867940A5366D9E265DE9EB240F"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect163k1
+ */
+ static X9ECParametersHolder sect163k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 163;
+ int k1 = 3;
+ int k2 = 6;
+ int k3 = 7;
+
+ BigInteger a = BigInteger.valueOf(1);
+ BigInteger b = BigInteger.valueOf(1);
+ byte[] S = null;
+ BigInteger n = fromHex("04000000000000000000020108A2E0CC0D99F8A5EF");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"
+ + "0289070FB05D38FF58321F2E800536D538CCDAA3D9"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect163r1
+ */
+ static X9ECParametersHolder sect163r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 163;
+ int k1 = 3;
+ int k2 = 6;
+ int k3 = 7;
+
+ BigInteger a = fromHex("07B6882CAAEFA84F9554FF8428BD88E246D2782AE2");
+ BigInteger b = fromHex("0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9");
+ byte[] S = Hex.decode("24B7B137C8A14D696E6768756151756FD0DA2E5C");
+ BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "0369979697AB43897789566789567F787A7876A654"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "0369979697AB43897789566789567F787A7876A654"
+ + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect163r2
+ */
+ static X9ECParametersHolder sect163r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 163;
+ int k1 = 3;
+ int k2 = 6;
+ int k3 = 7;
+
+ BigInteger a = BigInteger.valueOf(1);
+ BigInteger b = fromHex("020A601907B8C953CA1481EB10512F78744A3205FD");
+ byte[] S = Hex.decode("85E25BFE5C86226CDB12016F7553F9D0E693A268");
+ BigInteger n = fromHex("040000000000000000000292FE77E70C12A4234C33");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "03F0EBA16286A2D57EA0991168D4994637E8343E36"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "03F0EBA16286A2D57EA0991168D4994637E8343E36"
+ + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect193r1
+ */
+ static X9ECParametersHolder sect193r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 193;
+ int k = 15;
+
+ BigInteger a = fromHex("0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01");
+ BigInteger b = fromHex("00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814");
+ byte[] S = Hex.decode("103FAEC74D696E676875615175777FC5B191EF30");
+ BigInteger n = fromHex("01000000000000000000000000C7F34A778F443ACC920EBA49");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"
+ + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect193r2
+ */
+ static X9ECParametersHolder sect193r2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 193;
+ int k = 15;
+
+ BigInteger a = fromHex("0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B");
+ BigInteger b = fromHex("00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE");
+ byte[] S = Hex.decode("10B7B4D696E676875615175137C8A16FD0DA2211");
+ BigInteger n = fromHex("010000000000000000000000015AAB561B005413CCD4EE99D5");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"
+ + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect233k1
+ */
+ static X9ECParametersHolder sect233k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 233;
+ int k = 74;
+
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(1);
+ byte[] S = null;
+ BigInteger n = fromHex("8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"
+ + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect233r1
+ */
+ static X9ECParametersHolder sect233r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 233;
+ int k = 74;
+
+ BigInteger a = BigInteger.valueOf(1);
+ BigInteger b = fromHex("0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD");
+ byte[] S = Hex.decode("74D59FF07F6B413D0EA14B344B20A2DB049B50C3");
+ BigInteger n = fromHex("01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"
+ + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect239k1
+ */
+ static X9ECParametersHolder sect239k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 239;
+ int k = 158;
+
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(1);
+ byte[] S = null;
+ BigInteger n = fromHex("2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"
+ + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect283k1
+ */
+ static X9ECParametersHolder sect283k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 283;
+ int k1 = 5;
+ int k2 = 7;
+ int k3 = 12;
+
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(1);
+ byte[] S = null;
+ BigInteger n = fromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"
+ + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect283r1
+ */
+ static X9ECParametersHolder sect283r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 283;
+ int k1 = 5;
+ int k2 = 7;
+ int k3 = 12;
+
+ BigInteger a = BigInteger.valueOf(1);
+ BigInteger b = fromHex("027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5");
+ byte[] S = Hex.decode("77E2B07370EB0F832A6DD5B62DFC88CD06BB84BE");
+ BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"
+ + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect409k1
+ */
+ static X9ECParametersHolder sect409k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 409;
+ int k = 87;
+
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(1);
+ byte[] S = null;
+ BigInteger n = fromHex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"
+ + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect409r1
+ */
+ static X9ECParametersHolder sect409r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 409;
+ int k = 87;
+
+ BigInteger a = BigInteger.valueOf(1);
+ BigInteger b = fromHex("0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F");
+ byte[] S = Hex.decode("4099B5A457F9D69F79213D094C4BCD4D4262210B");
+ BigInteger n = fromHex("010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"
+ + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect571k1
+ */
+ static X9ECParametersHolder sect571k1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 571;
+ int k1 = 2;
+ int k2 = 5;
+ int k3 = 10;
+
+ BigInteger a = ECConstants.ZERO;
+ BigInteger b = BigInteger.valueOf(1);
+ byte[] S = null;
+ BigInteger n = fromHex("020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001");
+ BigInteger h = BigInteger.valueOf(4);
+
+ ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("02"
+ //+ "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"
+ + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+ /*
+ * sect571r1
+ */
+ static X9ECParametersHolder sect571r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ int m = 571;
+ int k1 = 2;
+ int k2 = 5;
+ int k3 = 10;
+
+ BigInteger a = BigInteger.valueOf(1);
+ BigInteger b = fromHex("02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A");
+ byte[] S = Hex.decode("2AA058F73A0E33AB486B0F610410C53A7F132310");
+ BigInteger n = fromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47");
+ BigInteger h = BigInteger.valueOf(2);
+
+ ECCurve curve = new ECCurve.F2m(m, k1, k2, k3, a, b, n, h);
+ //ECPoint G = curve.decodePoint(Hex.decode("03"
+ //+ "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"));
+ ECPoint G = curve.decodePoint(Hex.decode("04"
+ + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"
+ + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B"));
+
+ return new X9ECParameters(curve, G, n, h, S);
+ }
+ };
+
+
+ static final Hashtable objIds = new Hashtable();
+ static final Hashtable curves = new Hashtable();
+ static final Hashtable names = new Hashtable();
+
+ static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
+ {
+ objIds.put(name, oid);
+ names.put(oid, name);
+ curves.put(oid, holder);
+ }
+
+ static
+ {
+ defineCurve("secp112r1", SECObjectIdentifiers.secp112r1, secp112r1);
+ defineCurve("secp112r2", SECObjectIdentifiers.secp112r2, secp112r2);
+ defineCurve("secp128r1", SECObjectIdentifiers.secp128r1, secp128r1);
+ defineCurve("secp128r2", SECObjectIdentifiers.secp128r2, secp128r2);
+ defineCurve("secp160k1", SECObjectIdentifiers.secp160k1, secp160k1);
+ defineCurve("secp160r1", SECObjectIdentifiers.secp160r1, secp160r1);
+ defineCurve("secp160r2", SECObjectIdentifiers.secp160r2, secp160r2);
+ defineCurve("secp192k1", SECObjectIdentifiers.secp192k1, secp192k1);
+ defineCurve("secp192r1", SECObjectIdentifiers.secp192r1, secp192r1);
+ defineCurve("secp224k1", SECObjectIdentifiers.secp224k1, secp224k1);
+ defineCurve("secp224r1", SECObjectIdentifiers.secp224r1, secp224r1);
+ defineCurve("secp256k1", SECObjectIdentifiers.secp256k1, secp256k1);
+ defineCurve("secp256r1", SECObjectIdentifiers.secp256r1, secp256r1);
+ defineCurve("secp384r1", SECObjectIdentifiers.secp384r1, secp384r1);
+ defineCurve("secp521r1", SECObjectIdentifiers.secp521r1, secp521r1);
+
+ defineCurve("sect113r1", SECObjectIdentifiers.sect113r1, sect113r1);
+ defineCurve("sect113r2", SECObjectIdentifiers.sect113r2, sect113r2);
+ defineCurve("sect131r1", SECObjectIdentifiers.sect131r1, sect131r1);
+ defineCurve("sect131r2", SECObjectIdentifiers.sect131r2, sect131r2);
+ defineCurve("sect163k1", SECObjectIdentifiers.sect163k1, sect163k1);
+ defineCurve("sect163r1", SECObjectIdentifiers.sect163r1, sect163r1);
+ defineCurve("sect163r2", SECObjectIdentifiers.sect163r2, sect163r2);
+ defineCurve("sect193r1", SECObjectIdentifiers.sect193r1, sect193r1);
+ defineCurve("sect193r2", SECObjectIdentifiers.sect193r2, sect193r2);
+ defineCurve("sect233k1", SECObjectIdentifiers.sect233k1, sect233k1);
+ defineCurve("sect233r1", SECObjectIdentifiers.sect233r1, sect233r1);
+ defineCurve("sect239k1", SECObjectIdentifiers.sect239k1, sect239k1);
+ defineCurve("sect283k1", SECObjectIdentifiers.sect283k1, sect283k1);
+ defineCurve("sect283r1", SECObjectIdentifiers.sect283r1, sect283r1);
+ defineCurve("sect409k1", SECObjectIdentifiers.sect409k1, sect409k1);
+ defineCurve("sect409r1", SECObjectIdentifiers.sect409r1, sect409r1);
+ defineCurve("sect571k1", SECObjectIdentifiers.sect571k1, sect571k1);
+ defineCurve("sect571r1", SECObjectIdentifiers.sect571r1, sect571r1);
+ }
+
+ public static X9ECParameters getByName(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
+
+ if (oid != null)
+ {
+ return getByOID(oid);
+ }
+
+ return null;
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid);
+
+ if (holder != null)
+ {
+ return holder.getParameters();
+ }
+
+ return null;
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static ASN1ObjectIdentifier getOID(
+ String name)
+ {
+ return (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static String getName(
+ ASN1ObjectIdentifier oid)
+ {
+ return (String)names.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return objIds.keys();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/sec/SECObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,50 @@
+package pdftk.org.bouncycastle.asn1.sec;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+
+public interface SECObjectIdentifiers
+{
+ /**
+ * ellipticCurve OBJECT IDENTIFIER ::= {
+ * iso(1) identified-organization(3) certicom(132) curve(0)
+ * }
+ */
+ static final ASN1ObjectIdentifier ellipticCurve = new ASN1ObjectIdentifier("1.3.132.0");
+
+ static final ASN1ObjectIdentifier sect163k1 = ellipticCurve.branch("1");
+ static final ASN1ObjectIdentifier sect163r1 = ellipticCurve.branch("2");
+ static final ASN1ObjectIdentifier sect239k1 = ellipticCurve.branch("3");
+ static final ASN1ObjectIdentifier sect113r1 = ellipticCurve.branch("4");
+ static final ASN1ObjectIdentifier sect113r2 = ellipticCurve.branch("5");
+ static final ASN1ObjectIdentifier secp112r1 = ellipticCurve.branch("6");
+ static final ASN1ObjectIdentifier secp112r2 = ellipticCurve.branch("7");
+ static final ASN1ObjectIdentifier secp160r1 = ellipticCurve.branch("8");
+ static final ASN1ObjectIdentifier secp160k1 = ellipticCurve.branch("9");
+ static final ASN1ObjectIdentifier secp256k1 = ellipticCurve.branch("10");
+ static final ASN1ObjectIdentifier sect163r2 = ellipticCurve.branch("15");
+ static final ASN1ObjectIdentifier sect283k1 = ellipticCurve.branch("16");
+ static final ASN1ObjectIdentifier sect283r1 = ellipticCurve.branch("17");
+ static final ASN1ObjectIdentifier sect131r1 = ellipticCurve.branch("22");
+ static final ASN1ObjectIdentifier sect131r2 = ellipticCurve.branch("23");
+ static final ASN1ObjectIdentifier sect193r1 = ellipticCurve.branch("24");
+ static final ASN1ObjectIdentifier sect193r2 = ellipticCurve.branch("25");
+ static final ASN1ObjectIdentifier sect233k1 = ellipticCurve.branch("26");
+ static final ASN1ObjectIdentifier sect233r1 = ellipticCurve.branch("27");
+ static final ASN1ObjectIdentifier secp128r1 = ellipticCurve.branch("28");
+ static final ASN1ObjectIdentifier secp128r2 = ellipticCurve.branch("29");
+ static final ASN1ObjectIdentifier secp160r2 = ellipticCurve.branch("30");
+ static final ASN1ObjectIdentifier secp192k1 = ellipticCurve.branch("31");
+ static final ASN1ObjectIdentifier secp224k1 = ellipticCurve.branch("32");
+ static final ASN1ObjectIdentifier secp224r1 = ellipticCurve.branch("33");
+ static final ASN1ObjectIdentifier secp384r1 = ellipticCurve.branch("34");
+ static final ASN1ObjectIdentifier secp521r1 = ellipticCurve.branch("35");
+ static final ASN1ObjectIdentifier sect409k1 = ellipticCurve.branch("36");
+ static final ASN1ObjectIdentifier sect409r1 = ellipticCurve.branch("37");
+ static final ASN1ObjectIdentifier sect571k1 = ellipticCurve.branch("38");
+ static final ASN1ObjectIdentifier sect571r1 = ellipticCurve.branch("39");
+
+ static final ASN1ObjectIdentifier secp192r1 = X9ObjectIdentifiers.prime192v1;
+ static final ASN1ObjectIdentifier secp256r1 = X9ObjectIdentifiers.prime256v1;
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/sec/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/sec/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/sec/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/sec/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Classes for support of the SEC standard for Elliptic Curve.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/SMIMEAttributes.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/SMIMEAttributes.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/SMIMEAttributes.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/SMIMEAttributes.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,10 @@
+package pdftk.org.bouncycastle.asn1.smime;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+public interface SMIMEAttributes
+{
+ public static final ASN1ObjectIdentifier smimeCapabilities = PKCSObjectIdentifiers.pkcs_9_at_smimeCapabilities;
+ public static final ASN1ObjectIdentifier encrypKeyPref = PKCSObjectIdentifiers.id_aa_encrypKeyPref;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapabilities.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapabilities.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapabilities.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapabilities.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,115 @@
+package pdftk.org.bouncycastle.asn1.smime;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.cms.Attribute;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+/**
+ * Handler class for dealing with S/MIME Capabilities
+ */
+public class SMIMECapabilities
+ extends ASN1Object
+{
+ /**
+ * general preferences
+ */
+ public static final ASN1ObjectIdentifier preferSignedData = PKCSObjectIdentifiers.preferSignedData;
+ public static final ASN1ObjectIdentifier canNotDecryptAny = PKCSObjectIdentifiers.canNotDecryptAny;
+ public static final ASN1ObjectIdentifier sMIMECapabilitesVersions = PKCSObjectIdentifiers.sMIMECapabilitiesVersions;
+
+ /**
+ * encryption algorithms preferences
+ */
+ public static final ASN1ObjectIdentifier dES_CBC = new ASN1ObjectIdentifier("1.3.14.3.2.7");
+ public static final ASN1ObjectIdentifier dES_EDE3_CBC = PKCSObjectIdentifiers.des_EDE3_CBC;
+ public static final ASN1ObjectIdentifier rC2_CBC = PKCSObjectIdentifiers.RC2_CBC;
+
+ private ASN1Sequence capabilities;
+
+ /**
+ * return an Attribute object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static SMIMECapabilities getInstance(
+ Object o)
+ {
+ if (o == null || o instanceof SMIMECapabilities)
+ {
+ return (SMIMECapabilities)o;
+ }
+
+ if (o instanceof ASN1Sequence)
+ {
+ return new SMIMECapabilities((ASN1Sequence)o);
+ }
+
+ if (o instanceof Attribute)
+ {
+ return new SMIMECapabilities(
+ (ASN1Sequence)(((Attribute)o).getAttrValues().getObjectAt(0)));
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName());
+ }
+
+ public SMIMECapabilities(
+ ASN1Sequence seq)
+ {
+ capabilities = seq;
+ }
+
+ /**
+ * returns a vector with 0 or more objects of all the capabilities
+ * matching the passed in capability OID. If the OID passed is null the
+ * entire set is returned.
+ */
+ public Vector getCapabilities(
+ ASN1ObjectIdentifier capability)
+ {
+ Enumeration e = capabilities.getObjects();
+ Vector list = new Vector();
+
+ if (capability == null)
+ {
+ while (e.hasMoreElements())
+ {
+ SMIMECapability cap = SMIMECapability.getInstance(e.nextElement());
+
+ list.addElement(cap);
+ }
+ }
+ else
+ {
+ while (e.hasMoreElements())
+ {
+ SMIMECapability cap = SMIMECapability.getInstance(e.nextElement());
+
+ if (capability.equals(cap.getCapabilityID()))
+ {
+ list.addElement(cap);
+ }
+ }
+ }
+
+ return list;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * SMIMECapabilities ::= SEQUENCE OF SMIMECapability
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return capabilities;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapabilitiesAttribute.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapabilitiesAttribute.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapabilitiesAttribute.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapabilitiesAttribute.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,16 @@
+package pdftk.org.bouncycastle.asn1.smime;
+
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERSet;
+import pdftk.org.bouncycastle.asn1.cms.Attribute;
+
+public class SMIMECapabilitiesAttribute
+ extends Attribute
+{
+ public SMIMECapabilitiesAttribute(
+ SMIMECapabilityVector capabilities)
+ {
+ super(SMIMEAttributes.smimeCapabilities,
+ new DERSet(new DERSequence(capabilities.toASN1EncodableVector())));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapability.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapability.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapability.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapability.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,103 @@
+package pdftk.org.bouncycastle.asn1.smime;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+
+public class SMIMECapability
+ extends ASN1Object
+{
+ /**
+ * general preferences
+ */
+ public static final ASN1ObjectIdentifier preferSignedData = PKCSObjectIdentifiers.preferSignedData;
+ public static final ASN1ObjectIdentifier canNotDecryptAny = PKCSObjectIdentifiers.canNotDecryptAny;
+ public static final ASN1ObjectIdentifier sMIMECapabilitiesVersions = PKCSObjectIdentifiers.sMIMECapabilitiesVersions;
+
+ /**
+ * encryption algorithms preferences
+ */
+ public static final ASN1ObjectIdentifier dES_CBC = new ASN1ObjectIdentifier("1.3.14.3.2.7");
+ public static final ASN1ObjectIdentifier dES_EDE3_CBC = PKCSObjectIdentifiers.des_EDE3_CBC;
+ public static final ASN1ObjectIdentifier rC2_CBC = PKCSObjectIdentifiers.RC2_CBC;
+ public static final ASN1ObjectIdentifier aES128_CBC = NISTObjectIdentifiers.id_aes128_CBC;
+ public static final ASN1ObjectIdentifier aES192_CBC = NISTObjectIdentifiers.id_aes192_CBC;
+ public static final ASN1ObjectIdentifier aES256_CBC = NISTObjectIdentifiers.id_aes256_CBC;
+
+ private ASN1ObjectIdentifier capabilityID;
+ private ASN1Encodable parameters;
+
+ public SMIMECapability(
+ ASN1Sequence seq)
+ {
+ capabilityID = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+
+ if (seq.size() > 1)
+ {
+ parameters = (ASN1Primitive)seq.getObjectAt(1);
+ }
+ }
+
+ public SMIMECapability(
+ ASN1ObjectIdentifier capabilityID,
+ ASN1Encodable parameters)
+ {
+ this.capabilityID = capabilityID;
+ this.parameters = parameters;
+ }
+
+ public static SMIMECapability getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof SMIMECapability)
+ {
+ return (SMIMECapability)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new SMIMECapability((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid SMIMECapability");
+ }
+
+ public ASN1ObjectIdentifier getCapabilityID()
+ {
+ return capabilityID;
+ }
+
+ public ASN1Encodable getParameters()
+ {
+ return parameters;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * SMIMECapability ::= SEQUENCE {
+ * capabilityID OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY capabilityID OPTIONAL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(capabilityID);
+
+ if (parameters != null)
+ {
+ v.add(parameters);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapabilityVector.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapabilityVector.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapabilityVector.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/SMIMECapabilityVector.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,50 @@
+package pdftk.org.bouncycastle.asn1.smime;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * Handler for creating a vector S/MIME Capabilities
+ */
+public class SMIMECapabilityVector
+{
+ private ASN1EncodableVector capabilities = new ASN1EncodableVector();
+
+ public void addCapability(
+ ASN1ObjectIdentifier capability)
+ {
+ capabilities.add(new DERSequence(capability));
+ }
+
+ public void addCapability(
+ ASN1ObjectIdentifier capability,
+ int value)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(capability);
+ v.add(new ASN1Integer(value));
+
+ capabilities.add(new DERSequence(v));
+ }
+
+ public void addCapability(
+ ASN1ObjectIdentifier capability,
+ ASN1Encodable params)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(capability);
+ v.add(params);
+
+ capabilities.add(new DERSequence(v));
+ }
+
+ public ASN1EncodableVector toASN1EncodableVector()
+ {
+ return capabilities;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.asn1.smime;
+
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.DERSet;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.cms.Attribute;
+import pdftk.org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
+import pdftk.org.bouncycastle.asn1.cms.RecipientKeyIdentifier;
+
+/**
+ * The SMIMEEncryptionKeyPreference object.
+ *
+ * SMIMEEncryptionKeyPreference ::= CHOICE {
+ * issuerAndSerialNumber [0] IssuerAndSerialNumber,
+ * receipentKeyId [1] RecipientKeyIdentifier,
+ * subjectAltKeyIdentifier [2] SubjectKeyIdentifier
+ * }
+ *
+ */
+public class SMIMEEncryptionKeyPreferenceAttribute
+ extends Attribute
+{
+ public SMIMEEncryptionKeyPreferenceAttribute(
+ IssuerAndSerialNumber issAndSer)
+ {
+ super(SMIMEAttributes.encrypKeyPref,
+ new DERSet(new DERTaggedObject(false, 0, issAndSer)));
+ }
+
+ public SMIMEEncryptionKeyPreferenceAttribute(
+ RecipientKeyIdentifier rKeyId)
+ {
+
+ super(SMIMEAttributes.encrypKeyPref,
+ new DERSet(new DERTaggedObject(false, 1, rKeyId)));
+ }
+
+ /**
+ * @param sKeyId the subjectKeyIdentifier value (normally the X.509 one)
+ */
+ public SMIMEEncryptionKeyPreferenceAttribute(
+ ASN1OctetString sKeyId)
+ {
+
+ super(SMIMEAttributes.encrypKeyPref,
+ new DERSet(new DERTaggedObject(false, 2, sKeyId)));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/smime/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/smime/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes useful for encoding and supporting S/MIME.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/teletrust/TeleTrusTNamedCurves.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,351 @@
+package pdftk.org.bouncycastle.asn1.teletrust;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.x9.X9ECParameters;
+import pdftk.org.bouncycastle.asn1.x9.X9ECParametersHolder;
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+import pdftk.org.bouncycastle.util.Strings;
+import pdftk.org.bouncycastle.util.encoders.Hex;
+
+/**
+ * elliptic curves defined in "ECC Brainpool Standard Curves and Curve Generation"
+ * http://www.ecc-brainpool.org/download/draft_pkix_additional_ecc_dp.txt
+ */
+public class TeleTrusTNamedCurves
+{
+ static X9ECParametersHolder brainpoolP160r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q
+ new BigInteger("340E7BE2A280EB74E2BE61BADA745D97E8F7C300", 16), // a
+ new BigInteger("1E589A8595423412134FAA2DBDEC95C8D8675E58", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321")), // G
+ new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+
+ static X9ECParametersHolder brainpoolP160t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ // new BigInteger("24DBFF5DEC9B986BBFE5295A29BFBAE45E0F5D0B", 16), // Z
+ new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q
+ new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620C", 16), // a'
+ new BigInteger("7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD")), // G
+ new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+
+ static X9ECParametersHolder brainpoolP192r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q
+ new BigInteger("6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", 16), // a
+ new BigInteger("469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F")), // G
+ new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+
+ static X9ECParametersHolder brainpoolP192t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ //new BigInteger("1B6F5CC8DB4DC7AF19458A9CB80DC2295E5EB9C3732104CB") //Z
+ new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q
+ new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294", 16), // a'
+ new BigInteger("13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9")), // G'
+ new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+
+ static X9ECParametersHolder brainpoolP224r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q
+ new BigInteger("68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", 16), // a
+ new BigInteger("2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD")), // G
+ new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16), //n
+ new BigInteger("01", 16)); // n
+ }
+ };
+ static X9ECParametersHolder brainpoolP224t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ //new BigInteger("2DF271E14427A346910CF7A2E6CFA7B3F484E5C2CCE1C8B730E28B3F") //Z
+ new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q
+ new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC", 16), // a'
+ new BigInteger("4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C")), // G'
+ new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+ static X9ECParametersHolder brainpoolP256r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q
+ new BigInteger("7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", 16), // a
+ new BigInteger("26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997")), // G
+ new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+ static X9ECParametersHolder brainpoolP256t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ //new BigInteger("3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0") //Z
+ new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q
+ new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374", 16), // a'
+ new BigInteger("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE")), // G'
+ new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+ static X9ECParametersHolder brainpoolP320r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q
+ new BigInteger("3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", 16), // a
+ new BigInteger("520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1")), // G
+ new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+ static X9ECParametersHolder brainpoolP320t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ //new BigInteger("15F75CAF668077F7E85B42EB01F0A81FF56ECD6191D55CB82B7D861458A18FEFC3E5AB7496F3C7B1") //Z
+ new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q
+ new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24", 16), // a'
+ new BigInteger("A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3")), // G'
+ new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+ static X9ECParametersHolder brainpoolP384r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q
+ new BigInteger("7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", 16), // a
+ new BigInteger("4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315")), // G
+ new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+ static X9ECParametersHolder brainpoolP384t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ //new BigInteger("41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C") //Z
+ new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q
+ new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50", 16), // a'
+ new BigInteger("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928")), // G'
+ new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+ static X9ECParametersHolder brainpoolP512r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q
+ new BigInteger("7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", 16), // a
+ new BigInteger("3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", 16)); // b
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892")), // G
+ new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+ static X9ECParametersHolder brainpoolP512t1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve curve = new ECCurve.Fp(
+ //new BigInteger("12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB") //Z
+ new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q
+ new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0", 16), // a'
+ new BigInteger("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16)); // b'
+
+ return new X9ECParameters(
+ curve,
+ curve.decodePoint(Hex.decode("04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332")), // G'
+ new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16), //n
+ new BigInteger("01", 16)); // h
+ }
+ };
+
+ static final Hashtable objIds = new Hashtable();
+ static final Hashtable curves = new Hashtable();
+ static final Hashtable names = new Hashtable();
+
+ static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
+ {
+ objIds.put(name, oid);
+ names.put(oid, name);
+ curves.put(oid, holder);
+ }
+
+ static
+ {
+ defineCurve("brainpoolp160r1", TeleTrusTObjectIdentifiers.brainpoolP160r1, brainpoolP160r1);
+ defineCurve("brainpoolp160t1", TeleTrusTObjectIdentifiers.brainpoolP160t1, brainpoolP160t1);
+ defineCurve("brainpoolp192r1", TeleTrusTObjectIdentifiers.brainpoolP192r1, brainpoolP192r1);
+ defineCurve("brainpoolp192t1", TeleTrusTObjectIdentifiers.brainpoolP192t1, brainpoolP192t1);
+ defineCurve("brainpoolp224r1", TeleTrusTObjectIdentifiers.brainpoolP224r1, brainpoolP224r1);
+ defineCurve("brainpoolp224t1", TeleTrusTObjectIdentifiers.brainpoolP224t1, brainpoolP224t1);
+ defineCurve("brainpoolp256r1", TeleTrusTObjectIdentifiers.brainpoolP256r1, brainpoolP256r1);
+ defineCurve("brainpoolp256t1", TeleTrusTObjectIdentifiers.brainpoolP256t1, brainpoolP256t1);
+ defineCurve("brainpoolp320r1", TeleTrusTObjectIdentifiers.brainpoolP320r1, brainpoolP320r1);
+ defineCurve("brainpoolp320t1", TeleTrusTObjectIdentifiers.brainpoolP320t1, brainpoolP320t1);
+ defineCurve("brainpoolp384r1", TeleTrusTObjectIdentifiers.brainpoolP384r1, brainpoolP384r1);
+ defineCurve("brainpoolp384t1", TeleTrusTObjectIdentifiers.brainpoolP384t1, brainpoolP384t1);
+ defineCurve("brainpoolp512r1", TeleTrusTObjectIdentifiers.brainpoolP512r1, brainpoolP512r1);
+ defineCurve("brainpoolp512t1", TeleTrusTObjectIdentifiers.brainpoolP512t1, brainpoolP512t1);
+ }
+
+ public static X9ECParameters getByName(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
+
+ if (oid != null)
+ {
+ return getByOID(oid);
+ }
+
+ return null;
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid);
+
+ if (holder != null)
+ {
+ return holder.getParameters();
+ }
+
+ return null;
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static ASN1ObjectIdentifier getOID(
+ String name)
+ {
+ return (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static String getName(
+ ASN1ObjectIdentifier oid)
+ {
+ return (String)names.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return objIds.keys();
+ }
+
+ public static ASN1ObjectIdentifier getOID(short curvesize, boolean twisted)
+ {
+ return getOID("brainpoolP" + curvesize + (twisted ? "t" : "r") + "1");
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/teletrust/TeleTrusTObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,42 @@
+package pdftk.org.bouncycastle.asn1.teletrust;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface TeleTrusTObjectIdentifiers
+{
+ static final ASN1ObjectIdentifier teleTrusTAlgorithm = new ASN1ObjectIdentifier("1.3.36.3");
+
+ static final ASN1ObjectIdentifier ripemd160 = teleTrusTAlgorithm.branch("2.1");
+ static final ASN1ObjectIdentifier ripemd128 = teleTrusTAlgorithm.branch("2.2");
+ static final ASN1ObjectIdentifier ripemd256 = teleTrusTAlgorithm.branch("2.3");
+
+ static final ASN1ObjectIdentifier teleTrusTRSAsignatureAlgorithm = teleTrusTAlgorithm.branch("3.1");
+
+ static final ASN1ObjectIdentifier rsaSignatureWithripemd160 = teleTrusTRSAsignatureAlgorithm.branch("2");
+ static final ASN1ObjectIdentifier rsaSignatureWithripemd128 = teleTrusTRSAsignatureAlgorithm.branch("3");
+ static final ASN1ObjectIdentifier rsaSignatureWithripemd256 = teleTrusTRSAsignatureAlgorithm.branch("4");
+
+ static final ASN1ObjectIdentifier ecSign = teleTrusTAlgorithm.branch("3.2");
+
+ static final ASN1ObjectIdentifier ecSignWithSha1 = ecSign.branch("1");
+ static final ASN1ObjectIdentifier ecSignWithRipemd160 = ecSign.branch("2");
+
+ static final ASN1ObjectIdentifier ecc_brainpool = teleTrusTAlgorithm.branch("3.2.8");
+ static final ASN1ObjectIdentifier ellipticCurve = ecc_brainpool.branch("1");
+ static final ASN1ObjectIdentifier versionOne = ellipticCurve.branch("1");
+
+ static final ASN1ObjectIdentifier brainpoolP160r1 = versionOne.branch("1");
+ static final ASN1ObjectIdentifier brainpoolP160t1 = versionOne.branch("2");
+ static final ASN1ObjectIdentifier brainpoolP192r1 = versionOne.branch("3");
+ static final ASN1ObjectIdentifier brainpoolP192t1 = versionOne.branch("4");
+ static final ASN1ObjectIdentifier brainpoolP224r1 = versionOne.branch("5");
+ static final ASN1ObjectIdentifier brainpoolP224t1 = versionOne.branch("6");
+ static final ASN1ObjectIdentifier brainpoolP256r1 = versionOne.branch("7");
+ static final ASN1ObjectIdentifier brainpoolP256t1 = versionOne.branch("8");
+ static final ASN1ObjectIdentifier brainpoolP320r1 = versionOne.branch("9");
+ static final ASN1ObjectIdentifier brainpoolP320t1 = versionOne.branch("10");
+ static final ASN1ObjectIdentifier brainpoolP384r1 = versionOne.branch("11");
+ static final ASN1ObjectIdentifier brainpoolP384t1 = versionOne.branch("12");
+ static final ASN1ObjectIdentifier brainpoolP512r1 = versionOne.branch("13");
+ static final ASN1ObjectIdentifier brainpoolP512t1 = versionOne.branch("14");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/teletrust/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/teletrust/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/teletrust/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/teletrust/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes for TeleTrust related objects.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/tsp/Accuracy.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/tsp/Accuracy.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/tsp/Accuracy.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/tsp/Accuracy.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,173 @@
+package pdftk.org.bouncycastle.asn1.tsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+
+public class Accuracy
+ extends ASN1Object
+{
+ ASN1Integer seconds;
+
+ ASN1Integer millis;
+
+ ASN1Integer micros;
+
+ // constantes
+ protected static final int MIN_MILLIS = 1;
+
+ protected static final int MAX_MILLIS = 999;
+
+ protected static final int MIN_MICROS = 1;
+
+ protected static final int MAX_MICROS = 999;
+
+ protected Accuracy()
+ {
+ }
+
+ public Accuracy(
+ ASN1Integer seconds,
+ ASN1Integer millis,
+ ASN1Integer micros)
+ {
+ this.seconds = seconds;
+
+ //Verifications
+ if (millis != null
+ && (millis.getValue().intValue() < MIN_MILLIS || millis
+ .getValue().intValue() > MAX_MILLIS))
+ {
+ throw new IllegalArgumentException(
+ "Invalid millis field : not in (1..999)");
+ }
+ else
+ {
+ this.millis = millis;
+ }
+
+ if (micros != null
+ && (micros.getValue().intValue() < MIN_MICROS || micros
+ .getValue().intValue() > MAX_MICROS))
+ {
+ throw new IllegalArgumentException(
+ "Invalid micros field : not in (1..999)");
+ }
+ else
+ {
+ this.micros = micros;
+ }
+
+ }
+
+ private Accuracy(ASN1Sequence seq)
+ {
+ seconds = null;
+ millis = null;
+ micros = null;
+
+ for (int i = 0; i < seq.size(); i++)
+ {
+ // seconds
+ if (seq.getObjectAt(i) instanceof ASN1Integer)
+ {
+ seconds = (ASN1Integer) seq.getObjectAt(i);
+ }
+ else if (seq.getObjectAt(i) instanceof DERTaggedObject)
+ {
+ DERTaggedObject extra = (DERTaggedObject) seq.getObjectAt(i);
+
+ switch (extra.getTagNo())
+ {
+ case 0:
+ millis = ASN1Integer.getInstance(extra, false);
+ if (millis.getValue().intValue() < MIN_MILLIS
+ || millis.getValue().intValue() > MAX_MILLIS)
+ {
+ throw new IllegalArgumentException(
+ "Invalid millis field : not in (1..999).");
+ }
+ break;
+ case 1:
+ micros = ASN1Integer.getInstance(extra, false);
+ if (micros.getValue().intValue() < MIN_MICROS
+ || micros.getValue().intValue() > MAX_MICROS)
+ {
+ throw new IllegalArgumentException(
+ "Invalid micros field : not in (1..999).");
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Invalig tag number");
+ }
+ }
+ }
+ }
+
+ public static Accuracy getInstance(Object o)
+ {
+ if (o instanceof Accuracy)
+ {
+ return (Accuracy) o;
+ }
+
+ if (o != null)
+ {
+ return new Accuracy(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getSeconds()
+ {
+ return seconds;
+ }
+
+ public ASN1Integer getMillis()
+ {
+ return millis;
+ }
+
+ public ASN1Integer getMicros()
+ {
+ return micros;
+ }
+
+ /**
+ *
+ * Accuracy ::= SEQUENCE {
+ * seconds INTEGER OPTIONAL,
+ * millis [0] INTEGER (1..999) OPTIONAL,
+ * micros [1] INTEGER (1..999) OPTIONAL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (seconds != null)
+ {
+ v.add(seconds);
+ }
+
+ if (millis != null)
+ {
+ v.add(new DERTaggedObject(false, 0, millis));
+ }
+
+ if (micros != null)
+ {
+ v.add(new DERTaggedObject(false, 1, micros));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/tsp/MessageImprint.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/tsp/MessageImprint.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/tsp/MessageImprint.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/tsp/MessageImprint.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,78 @@
+package pdftk.org.bouncycastle.asn1.tsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+public class MessageImprint
+ extends ASN1Object
+{
+ AlgorithmIdentifier hashAlgorithm;
+ byte[] hashedMessage;
+
+ /**
+ * @param o
+ * @return a MessageImprint object.
+ */
+ public static MessageImprint getInstance(Object o)
+ {
+ if (o instanceof MessageImprint)
+ {
+ return (MessageImprint)o;
+ }
+
+ if (o != null)
+ {
+ return new MessageImprint(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private MessageImprint(
+ ASN1Sequence seq)
+ {
+ this.hashAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(0));
+ this.hashedMessage = ASN1OctetString.getInstance(seq.getObjectAt(1)).getOctets();
+ }
+
+ public MessageImprint(
+ AlgorithmIdentifier hashAlgorithm,
+ byte[] hashedMessage)
+ {
+ this.hashAlgorithm = hashAlgorithm;
+ this.hashedMessage = hashedMessage;
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public byte[] getHashedMessage()
+ {
+ return hashedMessage;
+ }
+
+ /**
+ *
+ * MessageImprint ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * hashedMessage OCTET STRING }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(hashAlgorithm);
+ v.add(new DEROctetString(hashedMessage));
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/tsp/TSTInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/tsp/TSTInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/tsp/TSTInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/tsp/TSTInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,233 @@
+package pdftk.org.bouncycastle.asn1.tsp;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Boolean;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.Extensions;
+import pdftk.org.bouncycastle.asn1.x509.GeneralName;
+
+public class TSTInfo
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private ASN1ObjectIdentifier tsaPolicyId;
+ private MessageImprint messageImprint;
+ private ASN1Integer serialNumber;
+ private ASN1GeneralizedTime genTime;
+ private Accuracy accuracy;
+ private ASN1Boolean ordering;
+ private ASN1Integer nonce;
+ private GeneralName tsa;
+ private Extensions extensions;
+
+ public static TSTInfo getInstance(Object o)
+ {
+ if (o instanceof TSTInfo)
+ {
+ return (TSTInfo)o;
+ }
+ else if (o != null)
+ {
+ return new TSTInfo(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private TSTInfo(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ // version
+ version = ASN1Integer.getInstance(e.nextElement());
+
+ // tsaPolicy
+ tsaPolicyId = ASN1ObjectIdentifier.getInstance(e.nextElement());
+
+ // messageImprint
+ messageImprint = MessageImprint.getInstance(e.nextElement());
+
+ // serialNumber
+ serialNumber = ASN1Integer.getInstance(e.nextElement());
+
+ // genTime
+ genTime = ASN1GeneralizedTime.getInstance(e.nextElement());
+
+ // default for ordering
+ ordering = ASN1Boolean.getInstance(false);
+
+ while (e.hasMoreElements())
+ {
+ ASN1Object o = (ASN1Object) e.nextElement();
+
+ if (o instanceof ASN1TaggedObject)
+ {
+ DERTaggedObject tagged = (DERTaggedObject) o;
+
+ switch (tagged.getTagNo())
+ {
+ case 0:
+ tsa = GeneralName.getInstance(tagged, true);
+ break;
+ case 1:
+ extensions = Extensions.getInstance(tagged, false);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown tag value " + tagged.getTagNo());
+ }
+ }
+ else if (o instanceof ASN1Sequence || o instanceof Accuracy)
+ {
+ accuracy = Accuracy.getInstance(o);
+ }
+ else if (o instanceof ASN1Boolean)
+ {
+ ordering = ASN1Boolean.getInstance(o);
+ }
+ else if (o instanceof ASN1Integer)
+ {
+ nonce = ASN1Integer.getInstance(o);
+ }
+
+ }
+ }
+
+ public TSTInfo(ASN1ObjectIdentifier tsaPolicyId, MessageImprint messageImprint,
+ ASN1Integer serialNumber, ASN1GeneralizedTime genTime,
+ Accuracy accuracy, ASN1Boolean ordering, ASN1Integer nonce,
+ GeneralName tsa, Extensions extensions)
+ {
+ version = new ASN1Integer(1);
+ this.tsaPolicyId = tsaPolicyId;
+ this.messageImprint = messageImprint;
+ this.serialNumber = serialNumber;
+ this.genTime = genTime;
+
+ this.accuracy = accuracy;
+ this.ordering = ordering;
+ this.nonce = nonce;
+ this.tsa = tsa;
+ this.extensions = extensions;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public MessageImprint getMessageImprint()
+ {
+ return messageImprint;
+ }
+
+ public ASN1ObjectIdentifier getPolicy()
+ {
+ return tsaPolicyId;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public Accuracy getAccuracy()
+ {
+ return accuracy;
+ }
+
+ public ASN1GeneralizedTime getGenTime()
+ {
+ return genTime;
+ }
+
+ public ASN1Boolean getOrdering()
+ {
+ return ordering;
+ }
+
+ public ASN1Integer getNonce()
+ {
+ return nonce;
+ }
+
+ public GeneralName getTsa()
+ {
+ return tsa;
+ }
+
+ public Extensions getExtensions()
+ {
+ return extensions;
+ }
+
+ /**
+ *
+ *
+ * TSTInfo ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * policy TSAPolicyId,
+ * messageImprint MessageImprint,
+ * -- MUST have the same value as the similar field in
+ * -- TimeStampReq
+ * serialNumber INTEGER,
+ * -- Time-Stamping users MUST be ready to accommodate integers
+ * -- up to 160 bits.
+ * genTime GeneralizedTime,
+ * accuracy Accuracy OPTIONAL,
+ * ordering BOOLEAN DEFAULT FALSE,
+ * nonce INTEGER OPTIONAL,
+ * -- MUST be present if the similar field was present
+ * -- in TimeStampReq. In that case it MUST have the same value.
+ * tsa [0] GeneralName OPTIONAL,
+ * extensions [1] IMPLICIT Extensions OPTIONAL }
+ *
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+ seq.add(version);
+
+ seq.add(tsaPolicyId);
+ seq.add(messageImprint);
+ seq.add(serialNumber);
+ seq.add(genTime);
+
+ if (accuracy != null)
+ {
+ seq.add(accuracy);
+ }
+
+ if (ordering != null && ordering.isTrue())
+ {
+ seq.add(ordering);
+ }
+
+ if (nonce != null)
+ {
+ seq.add(nonce);
+ }
+
+ if (tsa != null)
+ {
+ seq.add(new DERTaggedObject(true, 0, tsa));
+ }
+
+ if (extensions != null)
+ {
+ seq.add(new DERTaggedObject(false, 1, extensions));
+ }
+
+ return new DERSequence(seq);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/tsp/TimeStampReq.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/tsp/TimeStampReq.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/tsp/TimeStampReq.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/tsp/TimeStampReq.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,179 @@
+package pdftk.org.bouncycastle.asn1.tsp;
+
+import pdftk.org.bouncycastle.asn1.ASN1Boolean;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.Extensions;
+
+public class TimeStampReq
+ extends ASN1Object
+{
+ ASN1Integer version;
+
+ MessageImprint messageImprint;
+
+ ASN1ObjectIdentifier tsaPolicy;
+
+ ASN1Integer nonce;
+
+ ASN1Boolean certReq;
+
+ Extensions extensions;
+
+ public static TimeStampReq getInstance(Object o)
+ {
+ if (o instanceof TimeStampReq)
+ {
+ return (TimeStampReq) o;
+ }
+ else if (o != null)
+ {
+ return new TimeStampReq(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private TimeStampReq(ASN1Sequence seq)
+ {
+ int nbObjects = seq.size();
+
+ int seqStart = 0;
+
+ // version
+ version = ASN1Integer.getInstance(seq.getObjectAt(seqStart));
+
+ seqStart++;
+
+ // messageImprint
+ messageImprint = MessageImprint.getInstance(seq.getObjectAt(seqStart));
+
+ seqStart++;
+
+ for (int opt = seqStart; opt < nbObjects; opt++)
+ {
+ // tsaPolicy
+ if (seq.getObjectAt(opt) instanceof ASN1ObjectIdentifier)
+ {
+ tsaPolicy = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(opt));
+ }
+ // nonce
+ else if (seq.getObjectAt(opt) instanceof ASN1Integer)
+ {
+ nonce = ASN1Integer.getInstance(seq.getObjectAt(opt));
+ }
+ // certReq
+ else if (seq.getObjectAt(opt) instanceof ASN1Boolean)
+ {
+ certReq = ASN1Boolean.getInstance(seq.getObjectAt(opt));
+ }
+ // extensions
+ else if (seq.getObjectAt(opt) instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagged = (ASN1TaggedObject)seq.getObjectAt(opt);
+ if (tagged.getTagNo() == 0)
+ {
+ extensions = Extensions.getInstance(tagged, false);
+ }
+ }
+ }
+ }
+
+ public TimeStampReq(
+ MessageImprint messageImprint,
+ ASN1ObjectIdentifier tsaPolicy,
+ ASN1Integer nonce,
+ ASN1Boolean certReq,
+ Extensions extensions)
+ {
+ // default
+ version = new ASN1Integer(1);
+
+ this.messageImprint = messageImprint;
+ this.tsaPolicy = tsaPolicy;
+ this.nonce = nonce;
+ this.certReq = certReq;
+ this.extensions = extensions;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public MessageImprint getMessageImprint()
+ {
+ return messageImprint;
+ }
+
+ public ASN1ObjectIdentifier getReqPolicy()
+ {
+ return tsaPolicy;
+ }
+
+ public ASN1Integer getNonce()
+ {
+ return nonce;
+ }
+
+ public ASN1Boolean getCertReq()
+ {
+ return certReq;
+ }
+
+ public Extensions getExtensions()
+ {
+ return extensions;
+ }
+
+ /**
+ *
+ * TimeStampReq ::= SEQUENCE {
+ * version INTEGER { v1(1) },
+ * messageImprint MessageImprint,
+ * --a hash algorithm OID and the hash value of the data to be
+ * --time-stamped
+ * reqPolicy TSAPolicyId OPTIONAL,
+ * nonce INTEGER OPTIONAL,
+ * certReq BOOLEAN DEFAULT FALSE,
+ * extensions [0] IMPLICIT Extensions OPTIONAL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(messageImprint);
+
+ if (tsaPolicy != null)
+ {
+ v.add(tsaPolicy);
+ }
+
+ if (nonce != null)
+ {
+ v.add(nonce);
+ }
+
+ if (certReq != null && certReq.isTrue())
+ {
+ v.add(certReq);
+ }
+
+ if (extensions != null)
+ {
+ v.add(new DERTaggedObject(false, 0, extensions));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/tsp/TimeStampResp.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/tsp/TimeStampResp.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/tsp/TimeStampResp.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/tsp/TimeStampResp.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,84 @@
+package pdftk.org.bouncycastle.asn1.tsp;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.cmp.PKIStatusInfo;
+import pdftk.org.bouncycastle.asn1.cms.ContentInfo;
+
+
+public class TimeStampResp
+ extends ASN1Object
+{
+ PKIStatusInfo pkiStatusInfo;
+
+ ContentInfo timeStampToken;
+
+ public static TimeStampResp getInstance(Object o)
+ {
+ if (o instanceof TimeStampResp)
+ {
+ return (TimeStampResp) o;
+ }
+ else if (o != null)
+ {
+ return new TimeStampResp(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private TimeStampResp(ASN1Sequence seq)
+ {
+
+ Enumeration e = seq.getObjects();
+
+ // status
+ pkiStatusInfo = PKIStatusInfo.getInstance(e.nextElement());
+
+ if (e.hasMoreElements())
+ {
+ timeStampToken = ContentInfo.getInstance(e.nextElement());
+ }
+ }
+
+ public TimeStampResp(PKIStatusInfo pkiStatusInfo, ContentInfo timeStampToken)
+ {
+ this.pkiStatusInfo = pkiStatusInfo;
+ this.timeStampToken = timeStampToken;
+ }
+
+ public PKIStatusInfo getStatus()
+ {
+ return pkiStatusInfo;
+ }
+
+ public ContentInfo getTimeStampToken()
+ {
+ return timeStampToken;
+ }
+
+ /**
+ *
+ * TimeStampResp ::= SEQUENCE {
+ * status PKIStatusInfo,
+ * timeStampToken TimeStampToken OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(pkiStatusInfo);
+ if (timeStampToken != null)
+ {
+ v.add(timeStampToken);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/tsp/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/tsp/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/tsp/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/tsp/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes useful for encoding and supporting Time Stamp Protocol as described RFC 3161.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145BinaryField.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145BinaryField.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145BinaryField.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145BinaryField.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,119 @@
+package pdftk.org.bouncycastle.asn1.ua;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class DSTU4145BinaryField
+ extends ASN1Object
+{
+
+ private int m, k, j, l;
+
+ private DSTU4145BinaryField(ASN1Sequence seq)
+ {
+ m = ASN1Integer.getInstance(seq.getObjectAt(0)).getPositiveValue().intValue();
+
+ if (seq.getObjectAt(1) instanceof ASN1Integer)
+ {
+ k = ((ASN1Integer)seq.getObjectAt(1)).getPositiveValue().intValue();
+ }
+ else if (seq.getObjectAt(1) instanceof ASN1Sequence)
+ {
+ ASN1Sequence coefs = ASN1Sequence.getInstance(seq.getObjectAt(1));
+
+ k = ASN1Integer.getInstance(coefs.getObjectAt(0)).getPositiveValue().intValue();
+ j = ASN1Integer.getInstance(coefs.getObjectAt(1)).getPositiveValue().intValue();
+ l = ASN1Integer.getInstance(coefs.getObjectAt(2)).getPositiveValue().intValue();
+ }
+ else
+ {
+ throw new IllegalArgumentException("object parse error");
+ }
+ }
+
+ public static DSTU4145BinaryField getInstance(Object obj)
+ {
+ if (obj instanceof DSTU4145BinaryField)
+ {
+ return (DSTU4145BinaryField)obj;
+ }
+
+ if (obj != null)
+ {
+ return new DSTU4145BinaryField(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public DSTU4145BinaryField(int m, int k1, int k2, int k3)
+ {
+ this.m = m;
+ this.k = k1;
+ this.j = k2;
+ this.l = k3;
+ }
+
+ public int getM()
+ {
+ return m;
+ }
+
+ public int getK1()
+ {
+ return k;
+ }
+
+ public int getK2()
+ {
+ return j;
+ }
+
+ public int getK3()
+ {
+ return l;
+ }
+
+ public DSTU4145BinaryField(int m, int k)
+ {
+ this(m, k, 0, 0);
+ }
+
+ /**
+ * BinaryField ::= SEQUENCE {
+ * M INTEGER,
+ * CHOICE {Trinomial, Pentanomial}
+ * Trinomial::= INTEGER
+ * Pentanomial::= SEQUENCE {
+ * k INTEGER,
+ * j INTEGER,
+ * l INTEGER}
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(m));
+ if (j == 0) //Trinomial
+ {
+ v.add(new ASN1Integer(k));
+ }
+ else
+ {
+ ASN1EncodableVector coefs = new ASN1EncodableVector();
+ coefs.add(new ASN1Integer(k));
+ coefs.add(new ASN1Integer(j));
+ coefs.add(new ASN1Integer(l));
+
+ v.add(new DERSequence(coefs));
+ }
+
+ return new DERSequence(v);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145ECBinary.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145ECBinary.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145ECBinary.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145ECBinary.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,144 @@
+package pdftk.org.bouncycastle.asn1.ua;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x9.X9IntegerConverter;
+import pdftk.org.bouncycastle.crypto.params.ECDomainParameters;
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class DSTU4145ECBinary
+ extends ASN1Object
+{
+
+ BigInteger version = BigInteger.valueOf(0);
+
+ DSTU4145BinaryField f;
+ ASN1Integer a;
+ ASN1OctetString b;
+ ASN1Integer n;
+ ASN1OctetString bp;
+
+ public DSTU4145ECBinary(ECDomainParameters params)
+ {
+ if (!(params.getCurve() instanceof ECCurve.F2m))
+ {
+ throw new IllegalArgumentException("only binary domain is possible");
+ }
+
+ // We always use big-endian in parameter encoding
+ ECCurve.F2m curve = (ECCurve.F2m)params.getCurve();
+ f = new DSTU4145BinaryField(curve.getM(), curve.getK1(), curve.getK2(), curve.getK3());
+ a = new ASN1Integer(curve.getA().toBigInteger());
+ X9IntegerConverter converter = new X9IntegerConverter();
+ b = new DEROctetString(converter.integerToBytes(curve.getB().toBigInteger(), converter.getByteLength(curve)));
+ n = new ASN1Integer(params.getN());
+ bp = new DEROctetString(DSTU4145PointEncoder.encodePoint(params.getG()));
+ }
+
+ private DSTU4145ECBinary(ASN1Sequence seq)
+ {
+ int index = 0;
+
+ if (seq.getObjectAt(index) instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject taggedVersion = (ASN1TaggedObject)seq.getObjectAt(index);
+ if (taggedVersion.isExplicit() && 0 == taggedVersion.getTagNo())
+ {
+ version = ASN1Integer.getInstance(taggedVersion.getLoadedObject()).getValue();
+ index++;
+ }
+ else
+ {
+ throw new IllegalArgumentException("object parse error");
+ }
+ }
+ f = DSTU4145BinaryField.getInstance(seq.getObjectAt(index));
+ index++;
+ a = ASN1Integer.getInstance(seq.getObjectAt(index));
+ index++;
+ b = ASN1OctetString.getInstance(seq.getObjectAt(index));
+ index++;
+ n = ASN1Integer.getInstance(seq.getObjectAt(index));
+ index++;
+ bp = ASN1OctetString.getInstance(seq.getObjectAt(index));
+ }
+
+ public static DSTU4145ECBinary getInstance(Object obj)
+ {
+ if (obj instanceof DSTU4145ECBinary)
+ {
+ return (DSTU4145ECBinary)obj;
+ }
+
+ if (obj != null)
+ {
+ return new DSTU4145ECBinary(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public DSTU4145BinaryField getField()
+ {
+ return f;
+ }
+
+ public BigInteger getA()
+ {
+ return a.getValue();
+ }
+
+ public byte[] getB()
+ {
+ return Arrays.clone(b.getOctets());
+ }
+
+ public BigInteger getN()
+ {
+ return n.getValue();
+ }
+
+ public byte[] getG()
+ {
+ return Arrays.clone(bp.getOctets());
+ }
+
+ /**
+ * ECBinary ::= SEQUENCE {
+ * version [0] EXPLICIT INTEGER DEFAULT 0,
+ * f BinaryField,
+ * a INTEGER (0..1),
+ * b OCTET STRING,
+ * n INTEGER,
+ * bp OCTET STRING}
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (0 != version.compareTo(BigInteger.valueOf(0)))
+ {
+ v.add(new DERTaggedObject(true, 0, new ASN1Integer(version)));
+ }
+ v.add(f);
+ v.add(a);
+ v.add(b);
+ v.add(n);
+ v.add(bp);
+
+ return new DERSequence(v);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145NamedCurves.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,94 @@
+package pdftk.org.bouncycastle.asn1.ua;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.crypto.params.ECDomainParameters;
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+public class DSTU4145NamedCurves
+{
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ public static final ECDomainParameters[] params = new ECDomainParameters[10];
+ static final ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[10];
+
+ //All named curves have the following oid format: 1.2.804.2.1.1.1.1.3.1.1.2.X
+ //where X is the curve number 0-9
+ static final String oidBase = UAObjectIdentifiers.dstu4145le.getId() + ".2.";
+
+ static
+ {
+ ECCurve.F2m[] curves = new ECCurve.F2m[10];
+ curves[0] = new ECCurve.F2m(163, 3, 6, 7, ONE, new BigInteger("5FF6108462A2DC8210AB403925E638A19C1455D21", 16));
+ curves[1] = new ECCurve.F2m(167, 6, ONE, new BigInteger("6EE3CEEB230811759F20518A0930F1A4315A827DAC", 16));
+ curves[2] = new ECCurve.F2m(173, 1, 2, 10, ZERO, new BigInteger("108576C80499DB2FC16EDDF6853BBB278F6B6FB437D9", 16));
+ curves[3] = new ECCurve.F2m(179, 1, 2, 4, ONE, new BigInteger("4A6E0856526436F2F88DD07A341E32D04184572BEB710", 16));
+ curves[4] = new ECCurve.F2m(191, 9, ONE, new BigInteger("7BC86E2102902EC4D5890E8B6B4981ff27E0482750FEFC03", 16));
+ curves[5] = new ECCurve.F2m(233, 1, 4, 9, ONE, new BigInteger("06973B15095675534C7CF7E64A21BD54EF5DD3B8A0326AA936ECE454D2C", 16));
+ curves[6] = new ECCurve.F2m(257, 12, ZERO, new BigInteger("1CEF494720115657E18F938D7A7942394FF9425C1458C57861F9EEA6ADBE3BE10", 16));
+ curves[7] = new ECCurve.F2m(307, 2, 4, 8, ONE, new BigInteger("393C7F7D53666B5054B5E6C6D3DE94F4296C0C599E2E2E241050DF18B6090BDC90186904968BB", 16));
+ curves[8] = new ECCurve.F2m(367, 21, ONE, new BigInteger("43FC8AD242B0B7A6F3D1627AD5654447556B47BF6AA4A64B0C2AFE42CADAB8F93D92394C79A79755437B56995136", 16));
+ curves[9] = new ECCurve.F2m(431, 1, 3, 5, ONE, new BigInteger("03CE10490F6A708FC26DFE8C3D27C4F94E690134D5BFF988D8D28AAEAEDE975936C66BAC536B18AE2DC312CA493117DAA469C640CAF3", 16));
+
+ ECPoint[] points = new ECPoint[10];
+ points[0] = curves[0].createPoint(new BigInteger("2E2F85F5DD74CE983A5C4237229DAF8A3F35823BE", 16), new BigInteger("3826F008A8C51D7B95284D9D03FF0E00CE2CD723A", 16), false);
+ points[1] = curves[1].createPoint(new BigInteger("7A1F6653786A68192803910A3D30B2A2018B21CD54", 16), new BigInteger("5F49EB26781C0EC6B8909156D98ED435E45FD59918", 16), false);
+ points[2] = curves[2].createPoint(new BigInteger("4D41A619BCC6EADF0448FA22FAD567A9181D37389CA", 16), new BigInteger("10B51CC12849B234C75E6DD2028BF7FF5C1CE0D991A1", 16), false);
+ points[3] = curves[3].createPoint(new BigInteger("6BA06FE51464B2BD26DC57F48819BA9954667022C7D03", 16), new BigInteger("25FBC363582DCEC065080CA8287AAFF09788A66DC3A9E", 16), false);
+ points[4] = curves[4].createPoint(new BigInteger("714114B762F2FF4A7912A6D2AC58B9B5C2FCFE76DAEB7129", 16), new BigInteger("29C41E568B77C617EFE5902F11DB96FA9613CD8D03DB08DA", 16), false);
+ points[5] = curves[5].createPoint(new BigInteger("3FCDA526B6CDF83BA1118DF35B3C31761D3545F32728D003EEB25EFE96", 16), new BigInteger("9CA8B57A934C54DEEDA9E54A7BBAD95E3B2E91C54D32BE0B9DF96D8D35", 16), false);
+ points[6] = curves[6].createPoint(new BigInteger("02A29EF207D0E9B6C55CD260B306C7E007AC491CA1B10C62334A9E8DCD8D20FB7", 16), new BigInteger("10686D41FF744D4449FCCF6D8EEA03102E6812C93A9D60B978B702CF156D814EF", 16), false);
+ points[7] = curves[7].createPoint(new BigInteger("216EE8B189D291A0224984C1E92F1D16BF75CCD825A087A239B276D3167743C52C02D6E7232AA", 16), new BigInteger("5D9306BACD22B7FAEB09D2E049C6E2866C5D1677762A8F2F2DC9A11C7F7BE8340AB2237C7F2A0", 16), false);
+ points[8] = curves[8].createPoint(new BigInteger("324A6EDDD512F08C49A99AE0D3F961197A76413E7BE81A400CA681E09639B5FE12E59A109F78BF4A373541B3B9A1", 16), new BigInteger("1AB597A5B4477F59E39539007C7F977D1A567B92B043A49C6B61984C3FE3481AAF454CD41BA1F051626442B3C10", 16), false);
+ points[9] = curves[9].createPoint(new BigInteger("1A62BA79D98133A16BBAE7ED9A8E03C32E0824D57AEF72F88986874E5AAE49C27BED49A2A95058068426C2171E99FD3B43C5947C857D", 16), new BigInteger("70B5E1E14031C1F70BBEFE96BDDE66F451754B4CA5F48DA241F331AA396B8D1839A855C1769B1EA14BA53308B5E2723724E090E02DB9", 16), false);
+
+ BigInteger[] n_s = new BigInteger[10];
+ n_s[0] = new BigInteger("400000000000000000002BEC12BE2262D39BCF14D", 16);
+ n_s[1] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFB12EBCC7D7F29FF7701F", 16);
+ n_s[2] = new BigInteger("800000000000000000000189B4E67606E3825BB2831", 16);
+ n_s[3] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFB981960435FE5AB64236EF", 16);
+ n_s[4] = new BigInteger("40000000000000000000000069A779CAC1DABC6788F7474F", 16);
+ n_s[5] = new BigInteger("1000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", 16);
+ n_s[6] = new BigInteger("800000000000000000000000000000006759213AF182E987D3E17714907D470D", 16);
+ n_s[7] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC079C2F3825DA70D390FBBA588D4604022B7B7", 16);
+ n_s[8] = new BigInteger("40000000000000000000000000000000000000000000009C300B75A3FA824F22428FD28CE8812245EF44049B2D49", 16);
+ n_s[9] = new BigInteger("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA3175458009A8C0A724F02F81AA8A1FCBAF80D90C7A95110504CF", 16);
+
+ for (int i = 0; i < params.length; i++)
+ {
+ params[i] = new ECDomainParameters(curves[i], points[i], n_s[i]);
+ }
+
+ for (int i = 0; i < oids.length; i++)
+ {
+ oids[i] = new ASN1ObjectIdentifier(oidBase + i);
+ }
+ }
+
+ /**
+ * All named curves have the following oid format: 1.2.804.2.1.1.1.1.3.1.1.2.X
+ * where X is the curve number 0-9
+ */
+ public static ASN1ObjectIdentifier[] getOIDs()
+ {
+ return oids;
+ }
+
+ /**
+ * All named curves have the following oid format: 1.2.804.2.1.1.1.1.3.1.1.2.X
+ * where X is the curve number 0-9
+ */
+ public static ECDomainParameters getByOID(ASN1ObjectIdentifier oid)
+ {
+ String oidStr = oid.getId();
+ if (oidStr.startsWith(oidBase))
+ {
+ int index = Integer.parseInt(oidStr.substring(oidStr.length() - 1));
+ return params[index];
+ }
+ return null;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145Params.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145Params.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145Params.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145Params.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,114 @@
+package pdftk.org.bouncycastle.asn1.ua;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class DSTU4145Params extends ASN1Object
+{
+ private static final byte DEFAULT_DKE[]={
+ (byte) 0xa9, (byte) 0xd6, (byte) 0xeb, 0x45, (byte) 0xf1, 0x3c, 0x70, (byte) 0x82,
+ (byte) 0x80, (byte) 0xc4, (byte) 0x96, 0x7b, 0x23, 0x1f, 0x5e, (byte) 0xad,
+ (byte) 0xf6, 0x58, (byte) 0xeb, (byte) 0xa4, (byte) 0xc0, 0x37, 0x29, 0x1d,
+ 0x38, (byte) 0xd9, 0x6b, (byte) 0xf0, 0x25, (byte) 0xca, 0x4e, 0x17,
+ (byte) 0xf8, (byte) 0xe9, 0x72, 0x0d, (byte) 0xc6, 0x15, (byte) 0xb4, 0x3a,
+ 0x28, (byte) 0x97, 0x5f, 0x0b, (byte) 0xc1, (byte) 0xde, (byte) 0xa3, 0x64,
+ 0x38, (byte) 0xb5, 0x64, (byte) 0xea, 0x2c, 0x17, (byte) 0x9f, (byte) 0xd0,
+ 0x12, 0x3e, 0x6d, (byte) 0xb8, (byte) 0xfa, (byte) 0xc5, 0x79, 0x04};
+
+
+ private ASN1ObjectIdentifier namedCurve;
+ private DSTU4145ECBinary ecbinary;
+ private byte[] dke=DEFAULT_DKE;
+
+ public DSTU4145Params(ASN1ObjectIdentifier namedCurve)
+ {
+ this.namedCurve=namedCurve;
+ }
+
+ public DSTU4145Params(DSTU4145ECBinary ecbinary)
+ {
+ this.ecbinary=ecbinary;
+ }
+
+ public boolean isNamedCurve()
+ {
+ return namedCurve != null;
+ }
+
+ public DSTU4145ECBinary getECBinary()
+ {
+ return ecbinary;
+ }
+
+ public byte[] getDKE()
+ {
+ return dke;
+ }
+
+ public static byte[] getDefaultDKE()
+ {
+ return DEFAULT_DKE;
+ }
+
+ public ASN1ObjectIdentifier getNamedCurve()
+ {
+ return namedCurve;
+ }
+
+ public static DSTU4145Params getInstance(Object obj)
+ {
+ if (obj instanceof DSTU4145Params)
+ {
+ return (DSTU4145Params)obj;
+ }
+
+ if (obj != null)
+ {
+ ASN1Sequence seq=ASN1Sequence.getInstance(obj);
+ DSTU4145Params params;
+
+ if (seq.getObjectAt(0) instanceof ASN1ObjectIdentifier)
+ params=new DSTU4145Params(ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0)));
+ else
+ params=new DSTU4145Params(DSTU4145ECBinary.getInstance(seq.getObjectAt(0)));
+
+ if (seq.size()==2)
+ {
+ params.dke = ASN1OctetString.getInstance(seq.getObjectAt(1)).getOctets();
+ if (params.dke.length!=DSTU4145Params.DEFAULT_DKE.length)
+ throw new IllegalArgumentException("object parse error");
+ }
+
+ return params;
+ }
+
+ throw new IllegalArgumentException("object parse error");
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v=new ASN1EncodableVector();
+
+ if (namedCurve!=null)
+ {
+ v.add(namedCurve);
+ }
+ else
+ {
+ v.add(ecbinary);
+ }
+
+ if (!pdftk.org.bouncycastle.util.Arrays.areEqual(dke, DEFAULT_DKE))
+ {
+ v.add(new DEROctetString(dke));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145PointEncoder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,162 @@
+package pdftk.org.bouncycastle.asn1.ua;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+import pdftk.org.bouncycastle.asn1.x9.X9IntegerConverter;
+import pdftk.org.bouncycastle.math.ec.ECConstants;
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+import pdftk.org.bouncycastle.math.ec.ECFieldElement;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * DSTU4145 encodes points somewhat differently than X9.62
+ * It compresses the point to the size of the field element
+ */
+
+public abstract class DSTU4145PointEncoder
+{
+
+ private static X9IntegerConverter converter = new X9IntegerConverter();
+
+ private static BigInteger trace(ECFieldElement fe)
+ {
+ ECFieldElement t = fe;
+ for (int i = 0; i < fe.getFieldSize() - 1; i++)
+ {
+ t = t.square().add(fe);
+ }
+ return t.toBigInteger();
+ }
+
+ /**
+ * Solves a quadratic equation z2 + z = beta
(X9.62
+ * D.1.6) The other solution is z + 1
.
+ *
+ * @param beta The value to solve the qradratic equation for.
+ * @return the solution for z2 + z = beta
or
+ * null
if no solution exists.
+ */
+ private static ECFieldElement solveQuadradicEquation(ECFieldElement beta)
+ {
+ ECFieldElement.F2m b = (ECFieldElement.F2m)beta;
+ ECFieldElement zeroElement = new ECFieldElement.F2m(
+ b.getM(), b.getK1(), b.getK2(), b.getK3(), ECConstants.ZERO);
+
+ if (beta.toBigInteger().equals(ECConstants.ZERO))
+ {
+ return zeroElement;
+ }
+
+ ECFieldElement z = null;
+ ECFieldElement gamma = zeroElement;
+
+ Random rand = new Random();
+ int m = b.getM();
+ do
+ {
+ ECFieldElement t = new ECFieldElement.F2m(b.getM(), b.getK1(),
+ b.getK2(), b.getK3(), new BigInteger(m, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i <= m - 1; i++)
+ {
+ ECFieldElement w2 = w.square();
+ z = z.square().add(w2.multiply(t));
+ w = w2.add(beta);
+ }
+ if (!w.toBigInteger().equals(ECConstants.ZERO))
+ {
+ return null;
+ }
+ gamma = z.square().add(z);
+ }
+ while (gamma.toBigInteger().equals(ECConstants.ZERO));
+
+ return z;
+ }
+
+ public static byte[] encodePoint(ECPoint Q)
+ {
+ /*if (!Q.isCompressed())
+ Q=new ECPoint.F2m(Q.getCurve(),Q.getX(),Q.getY(),true);
+
+ byte[] bytes=Q.getEncoded();
+
+ if (bytes[0]==0x02)
+ bytes[bytes.length-1]&=0xFE;
+ else if (bytes[0]==0x02)
+ bytes[bytes.length-1]|=0x01;
+
+ return Arrays.copyOfRange(bytes, 1, bytes.length);*/
+
+ int byteCount = converter.getByteLength(Q.getX());
+ byte[] bytes = converter.integerToBytes(Q.getX().toBigInteger(), byteCount);
+
+ if (!(Q.getX().toBigInteger().equals(ECConstants.ZERO)))
+ {
+ ECFieldElement y = Q.getY().multiply(Q.getX().invert());
+ if (trace(y).equals(ECConstants.ONE))
+ {
+ bytes[bytes.length - 1] |= 0x01;
+ }
+ else
+ {
+ bytes[bytes.length - 1] &= 0xFE;
+ }
+ }
+
+ return bytes;
+ }
+
+ public static ECPoint decodePoint(ECCurve curve, byte[] bytes)
+ {
+ /*byte[] bp_enc=new byte[bytes.length+1];
+ if (0==(bytes[bytes.length-1]&0x1))
+ bp_enc[0]=0x02;
+ else
+ bp_enc[0]=0x03;
+ System.arraycopy(bytes, 0, bp_enc, 1, bytes.length);
+ if (!trace(curve.fromBigInteger(new BigInteger(1, bytes))).equals(curve.getA().toBigInteger()))
+ bp_enc[bp_enc.length-1]^=0x01;
+
+ return curve.decodePoint(bp_enc);*/
+
+ BigInteger k = BigInteger.valueOf(bytes[bytes.length - 1] & 0x1);
+ if (!trace(curve.fromBigInteger(new BigInteger(1, bytes))).equals(curve.getA().toBigInteger()))
+ {
+ bytes = Arrays.clone(bytes);
+ bytes[bytes.length - 1] ^= 0x01;
+ }
+ ECCurve.F2m c = (ECCurve.F2m)curve;
+ ECFieldElement xp = curve.fromBigInteger(new BigInteger(1, bytes));
+ ECFieldElement yp = null;
+ if (xp.toBigInteger().equals(ECConstants.ZERO))
+ {
+ yp = (ECFieldElement.F2m)curve.getB();
+ for (int i = 0; i < c.getM() - 1; i++)
+ {
+ yp = yp.square();
+ }
+ }
+ else
+ {
+ ECFieldElement beta = xp.add(curve.getA()).add(
+ curve.getB().multiply(xp.square().invert()));
+ ECFieldElement z = solveQuadradicEquation(beta);
+ if (z == null)
+ {
+ throw new RuntimeException("Invalid point compression");
+ }
+ if (!trace(z).equals(k))
+ {
+ z = z.add(curve.fromBigInteger(ECConstants.ONE));
+ }
+ yp = xp.multiply(z);
+ }
+
+ return new ECPoint.F2m(curve, xp, yp);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145PublicKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145PublicKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145PublicKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/DSTU4145PublicKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,46 @@
+package pdftk.org.bouncycastle.asn1.ua;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+public class DSTU4145PublicKey
+ extends ASN1Object
+{
+
+ private ASN1OctetString pubKey;
+
+ public DSTU4145PublicKey(ECPoint pubKey)
+ {
+ // We always use big-endian in parameter encoding
+ this.pubKey = new DEROctetString(DSTU4145PointEncoder.encodePoint(pubKey));
+ }
+
+ private DSTU4145PublicKey(ASN1OctetString ocStr)
+ {
+ pubKey = ocStr;
+ }
+
+ public static DSTU4145PublicKey getInstance(Object obj)
+ {
+ if (obj instanceof DSTU4145PublicKey)
+ {
+ return (DSTU4145PublicKey)obj;
+ }
+
+ if (obj != null)
+ {
+ return new DSTU4145PublicKey(ASN1OctetString.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return pubKey;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/ua/UAObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,16 @@
+package pdftk.org.bouncycastle.asn1.ua;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface UAObjectIdentifiers
+{
+ // Ukrainian object identifiers
+ // {iso(1) member-body(2) Ukraine(804 ) root(2) security(1) cryptography(1) pki(1)}
+
+ static final ASN1ObjectIdentifier UaOid = new ASN1ObjectIdentifier("1.2.804.2.1.1.1");
+
+ // {pki-alg(1) pki-alg-�sym(3) Dstu4145WithGost34311(1) PB(1)}
+ // DSTU4145 in polynomial basis has 2 oids, one for little-endian representation and one for big-endian
+ static final ASN1ObjectIdentifier dstu4145le = UaOid.branch("1.3.1.1");
+ static final ASN1ObjectIdentifier dstu4145be = UaOid.branch("1.3.1.1.1.1");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/util/ASN1Dump.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/util/ASN1Dump.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/util/ASN1Dump.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/util/ASN1Dump.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,402 @@
+package pdftk.org.bouncycastle.asn1.util;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.BERApplicationSpecific;
+import pdftk.org.bouncycastle.asn1.BERConstructedOctetString;
+import pdftk.org.bouncycastle.asn1.BEROctetString;
+import pdftk.org.bouncycastle.asn1.BERSequence;
+import pdftk.org.bouncycastle.asn1.BERSet;
+import pdftk.org.bouncycastle.asn1.BERTaggedObject;
+import pdftk.org.bouncycastle.asn1.BERTags;
+import pdftk.org.bouncycastle.asn1.DERApplicationSpecific;
+import pdftk.org.bouncycastle.asn1.DERBMPString;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERBoolean;
+import pdftk.org.bouncycastle.asn1.DEREnumerated;
+import pdftk.org.bouncycastle.asn1.DERExternal;
+import pdftk.org.bouncycastle.asn1.DERGeneralizedTime;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+import pdftk.org.bouncycastle.asn1.DERNull;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERT61String;
+import pdftk.org.bouncycastle.asn1.DERUTCTime;
+import pdftk.org.bouncycastle.asn1.DERUTF8String;
+import pdftk.org.bouncycastle.asn1.DERVisibleString;
+import pdftk.org.bouncycastle.util.encoders.Hex;
+
+public class ASN1Dump
+{
+ private static final String TAB = " ";
+ private static final int SAMPLE_SIZE = 32;
+
+ /**
+ * dump a DER object as a formatted string with indentation
+ *
+ * @param obj the ASN1Primitive to be dumped out.
+ */
+ static void _dumpAsString(
+ String indent,
+ boolean verbose,
+ ASN1Primitive obj,
+ StringBuffer buf)
+ {
+ String nl = System.getProperty("line.separator");
+ if (obj instanceof ASN1Sequence)
+ {
+ Enumeration e = ((ASN1Sequence)obj).getObjects();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ if (obj instanceof BERSequence)
+ {
+ buf.append("BER Sequence");
+ }
+ else if (obj instanceof DERSequence)
+ {
+ buf.append("DER Sequence");
+ }
+ else
+ {
+ buf.append("Sequence");
+ }
+
+ buf.append(nl);
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+
+ if (o == null || o.equals(DERNull.INSTANCE))
+ {
+ buf.append(tab);
+ buf.append("NULL");
+ buf.append(nl);
+ }
+ else if (o instanceof ASN1Primitive)
+ {
+ _dumpAsString(tab, verbose, (ASN1Primitive)o, buf);
+ }
+ else
+ {
+ _dumpAsString(tab, verbose, ((ASN1Encodable)o).toASN1Primitive(), buf);
+ }
+ }
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ String tab = indent + TAB;
+
+ buf.append(indent);
+ if (obj instanceof BERTaggedObject)
+ {
+ buf.append("BER Tagged [");
+ }
+ else
+ {
+ buf.append("Tagged [");
+ }
+
+ ASN1TaggedObject o = (ASN1TaggedObject)obj;
+
+ buf.append(Integer.toString(o.getTagNo()));
+ buf.append(']');
+
+ if (!o.isExplicit())
+ {
+ buf.append(" IMPLICIT ");
+ }
+
+ buf.append(nl);
+
+ if (o.isEmpty())
+ {
+ buf.append(tab);
+ buf.append("EMPTY");
+ buf.append(nl);
+ }
+ else
+ {
+ _dumpAsString(tab, verbose, o.getObject(), buf);
+ }
+ }
+ else if (obj instanceof ASN1Set)
+ {
+ Enumeration e = ((ASN1Set)obj).getObjects();
+ String tab = indent + TAB;
+
+ buf.append(indent);
+
+ if (obj instanceof BERSet)
+ {
+ buf.append("BER Set");
+ }
+ else
+ {
+ buf.append("DER Set");
+ }
+
+ buf.append(nl);
+
+ while (e.hasMoreElements())
+ {
+ Object o = e.nextElement();
+
+ if (o == null)
+ {
+ buf.append(tab);
+ buf.append("NULL");
+ buf.append(nl);
+ }
+ else if (o instanceof ASN1Primitive)
+ {
+ _dumpAsString(tab, verbose, (ASN1Primitive)o, buf);
+ }
+ else
+ {
+ _dumpAsString(tab, verbose, ((ASN1Encodable)o).toASN1Primitive(), buf);
+ }
+ }
+ }
+ else if (obj instanceof ASN1OctetString)
+ {
+ ASN1OctetString oct = (ASN1OctetString)obj;
+
+ if (obj instanceof BEROctetString || obj instanceof BERConstructedOctetString)
+ {
+ buf.append(indent + "BER Constructed Octet String" + "[" + oct.getOctets().length + "] ");
+ }
+ else
+ {
+ buf.append(indent + "DER Octet String" + "[" + oct.getOctets().length + "] ");
+ }
+ if (verbose)
+ {
+ buf.append(dumpBinaryDataAsString(indent, oct.getOctets()));
+ }
+ else{
+ buf.append(nl);
+ }
+ }
+ else if (obj instanceof ASN1ObjectIdentifier)
+ {
+ buf.append(indent + "ObjectIdentifier(" + ((ASN1ObjectIdentifier)obj).getId() + ")" + nl);
+ }
+ else if (obj instanceof DERBoolean)
+ {
+ buf.append(indent + "Boolean(" + ((DERBoolean)obj).isTrue() + ")" + nl);
+ }
+ else if (obj instanceof ASN1Integer)
+ {
+ buf.append(indent + "Integer(" + ((ASN1Integer)obj).getValue() + ")" + nl);
+ }
+ else if (obj instanceof DERBitString)
+ {
+ DERBitString bt = (DERBitString)obj;
+ buf.append(indent + "DER Bit String" + "[" + bt.getBytes().length + ", " + bt.getPadBits() + "] ");
+ if (verbose)
+ {
+ buf.append(dumpBinaryDataAsString(indent, bt.getBytes()));
+ }
+ else{
+ buf.append(nl);
+ }
+ }
+ else if (obj instanceof DERIA5String)
+ {
+ buf.append(indent + "IA5String(" + ((DERIA5String)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERUTF8String)
+ {
+ buf.append(indent + "UTF8String(" + ((DERUTF8String)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERPrintableString)
+ {
+ buf.append(indent + "PrintableString(" + ((DERPrintableString)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERVisibleString)
+ {
+ buf.append(indent + "VisibleString(" + ((DERVisibleString)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERBMPString)
+ {
+ buf.append(indent + "BMPString(" + ((DERBMPString)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERT61String)
+ {
+ buf.append(indent + "T61String(" + ((DERT61String)obj).getString() + ") " + nl);
+ }
+ else if (obj instanceof DERUTCTime)
+ {
+ buf.append(indent + "UTCTime(" + ((DERUTCTime)obj).getTime() + ") " + nl);
+ }
+ else if (obj instanceof DERGeneralizedTime)
+ {
+ buf.append(indent + "GeneralizedTime(" + ((DERGeneralizedTime)obj).getTime() + ") " + nl);
+ }
+ else if (obj instanceof BERApplicationSpecific)
+ {
+ buf.append(outputApplicationSpecific("BER", indent, verbose, obj, nl));
+ }
+ else if (obj instanceof DERApplicationSpecific)
+ {
+ buf.append(outputApplicationSpecific("DER", indent, verbose, obj, nl));
+ }
+ else if (obj instanceof DEREnumerated)
+ {
+ DEREnumerated en = (DEREnumerated) obj;
+ buf.append(indent + "DER Enumerated(" + en.getValue() + ")" + nl);
+ }
+ else if (obj instanceof DERExternal)
+ {
+ DERExternal ext = (DERExternal) obj;
+ buf.append(indent + "External " + nl);
+ String tab = indent + TAB;
+ if (ext.getDirectReference() != null)
+ {
+ buf.append(tab + "Direct Reference: " + ext.getDirectReference().getId() + nl);
+ }
+ if (ext.getIndirectReference() != null)
+ {
+ buf.append(tab + "Indirect Reference: " + ext.getIndirectReference().toString() + nl);
+ }
+ if (ext.getDataValueDescriptor() != null)
+ {
+ _dumpAsString(tab, verbose, ext.getDataValueDescriptor(), buf);
+ }
+ buf.append(tab + "Encoding: " + ext.getEncoding() + nl);
+ _dumpAsString(tab, verbose, ext.getExternalContent(), buf);
+ }
+ else
+ {
+ buf.append(indent + obj.toString() + nl);
+ }
+ }
+
+ private static String outputApplicationSpecific(String type, String indent, boolean verbose, ASN1Primitive obj, String nl)
+ {
+ DERApplicationSpecific app = (DERApplicationSpecific)obj;
+ StringBuffer buf = new StringBuffer();
+
+ if (app.isConstructed())
+ {
+ try
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(app.getObject(BERTags.SEQUENCE));
+ buf.append(indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "]" + nl);
+ for (Enumeration e = s.getObjects(); e.hasMoreElements();)
+ {
+ _dumpAsString(indent + TAB, verbose, (ASN1Primitive)e.nextElement(), buf);
+ }
+ }
+ catch (IOException e)
+ {
+ buf.append(e);
+ }
+ return buf.toString();
+ }
+
+ return indent + type + " ApplicationSpecific[" + app.getApplicationTag() + "] (" + new String(Hex.encode(app.getContents())) + ")" + nl;
+ }
+
+ /**
+ * dump out a DER object as a formatted string, in non-verbose mode.
+ *
+ * @param obj the ASN1Primitive to be dumped out.
+ * @return the resulting string.
+ */
+ public static String dumpAsString(
+ Object obj)
+ {
+ return dumpAsString(obj, false);
+ }
+
+ /**
+ * Dump out the object as a string.
+ *
+ * @param obj the object to be dumped
+ * @param verbose if true, dump out the contents of octet and bit strings.
+ * @return the resulting string.
+ */
+ public static String dumpAsString(
+ Object obj,
+ boolean verbose)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ if (obj instanceof ASN1Primitive)
+ {
+ _dumpAsString("", verbose, (ASN1Primitive)obj, buf);
+ }
+ else if (obj instanceof ASN1Encodable)
+ {
+ _dumpAsString("", verbose, ((ASN1Encodable)obj).toASN1Primitive(), buf);
+ }
+ else
+ {
+ return "unknown object type " + obj.toString();
+ }
+
+ return buf.toString();
+ }
+
+ private static String dumpBinaryDataAsString(String indent, byte[] bytes)
+ {
+ String nl = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+
+ indent += TAB;
+
+ buf.append(nl);
+ for (int i = 0; i < bytes.length; i += SAMPLE_SIZE)
+ {
+ if (bytes.length - i > SAMPLE_SIZE)
+ {
+ buf.append(indent);
+ buf.append(new String(Hex.encode(bytes, i, SAMPLE_SIZE)));
+ buf.append(TAB);
+ buf.append(calculateAscString(bytes, i, SAMPLE_SIZE));
+ buf.append(nl);
+ }
+ else
+ {
+ buf.append(indent);
+ buf.append(new String(Hex.encode(bytes, i, bytes.length - i)));
+ for (int j = bytes.length - i; j != SAMPLE_SIZE; j++)
+ {
+ buf.append(" ");
+ }
+ buf.append(TAB);
+ buf.append(calculateAscString(bytes, i, bytes.length - i));
+ buf.append(nl);
+ }
+ }
+
+ return buf.toString();
+ }
+
+ private static String calculateAscString(byte[] bytes, int off, int len)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ for (int i = off; i != off + len; i++)
+ {
+ if (bytes[i] >= ' ' && bytes[i] <= '~')
+ {
+ buf.append((char)bytes[i]);
+ }
+ }
+
+ return buf.toString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/util/DERDump.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/util/DERDump.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/util/DERDump.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/util/DERDump.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,41 @@
+package pdftk.org.bouncycastle.asn1.util;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+
+/**
+ * @deprecated use ASN1Dump.
+ */
+public class DERDump
+ extends ASN1Dump
+{
+ /**
+ * dump out a DER object as a formatted string
+ *
+ * @param obj the ASN1Primitive to be dumped out.
+ */
+ public static String dumpAsString(
+ ASN1Primitive obj)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ _dumpAsString("", false, obj, buf);
+
+ return buf.toString();
+ }
+
+ /**
+ * dump out a DER object as a formatted string
+ *
+ * @param obj the ASN1Primitive to be dumped out.
+ */
+ public static String dumpAsString(
+ ASN1Encodable obj)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ _dumpAsString("", false, obj.toASN1Primitive(), buf);
+
+ return buf.toString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/util/Dump.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/util/Dump.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/util/Dump.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/util/Dump.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,22 @@
+package pdftk.org.bouncycastle.asn1.util;
+
+import java.io.FileInputStream;
+
+import pdftk.org.bouncycastle.asn1.ASN1InputStream;
+
+public class Dump
+{
+ public static void main(
+ String args[])
+ throws Exception
+ {
+ FileInputStream fIn = new FileInputStream(args[0]);
+ ASN1InputStream bIn = new ASN1InputStream(fIn);
+ Object obj = null;
+
+ while ((obj = bIn.readObject()) != null)
+ {
+ System.out.println(ASN1Dump.dumpAsString(obj));
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/util/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/util/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/util/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/util/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+An ASN.1 dump utility.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/AttributeTypeAndValue.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/AttributeTypeAndValue.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/AttributeTypeAndValue.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/AttributeTypeAndValue.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,72 @@
+package pdftk.org.bouncycastle.asn1.x500;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class AttributeTypeAndValue
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier type;
+ private ASN1Encodable value;
+
+ private AttributeTypeAndValue(ASN1Sequence seq)
+ {
+ type = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ value = (ASN1Encodable)seq.getObjectAt(1);
+ }
+
+ public static AttributeTypeAndValue getInstance(Object o)
+ {
+ if (o instanceof AttributeTypeAndValue)
+ {
+ return (AttributeTypeAndValue)o;
+ }
+ else if (o != null)
+ {
+ return new AttributeTypeAndValue(ASN1Sequence.getInstance(o));
+ }
+
+ throw new IllegalArgumentException("null value in getInstance()");
+ }
+
+ public AttributeTypeAndValue(
+ ASN1ObjectIdentifier type,
+ ASN1Encodable value)
+ {
+ this.type = type;
+ this.value = value;
+ }
+
+ public ASN1ObjectIdentifier getType()
+ {
+ return type;
+ }
+
+ public ASN1Encodable getValue()
+ {
+ return value;
+ }
+
+ /**
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type OBJECT IDENTIFIER,
+ * value ANY DEFINED BY type }
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(type);
+ v.add(value);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/DirectoryString.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/DirectoryString.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/DirectoryString.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/DirectoryString.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,125 @@
+package pdftk.org.bouncycastle.asn1.x500;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1String;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBMPString;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+import pdftk.org.bouncycastle.asn1.DERT61String;
+import pdftk.org.bouncycastle.asn1.DERUTF8String;
+import pdftk.org.bouncycastle.asn1.DERUniversalString;
+
+public class DirectoryString
+ extends ASN1Object
+ implements ASN1Choice, ASN1String
+{
+ private ASN1String string;
+
+ public static DirectoryString getInstance(Object o)
+ {
+ if (o == null || o instanceof DirectoryString)
+ {
+ return (DirectoryString)o;
+ }
+
+ if (o instanceof DERT61String)
+ {
+ return new DirectoryString((DERT61String)o);
+ }
+
+ if (o instanceof DERPrintableString)
+ {
+ return new DirectoryString((DERPrintableString)o);
+ }
+
+ if (o instanceof DERUniversalString)
+ {
+ return new DirectoryString((DERUniversalString)o);
+ }
+
+ if (o instanceof DERUTF8String)
+ {
+ return new DirectoryString((DERUTF8String)o);
+ }
+
+ if (o instanceof DERBMPString)
+ {
+ return new DirectoryString((DERBMPString)o);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + o.getClass().getName());
+ }
+
+ public static DirectoryString getInstance(ASN1TaggedObject o, boolean explicit)
+ {
+ if (!explicit)
+ {
+ throw new IllegalArgumentException("choice item must be explicitly tagged");
+ }
+
+ return getInstance(o.getObject());
+ }
+
+ private DirectoryString(
+ DERT61String string)
+ {
+ this.string = string;
+ }
+
+ private DirectoryString(
+ DERPrintableString string)
+ {
+ this.string = string;
+ }
+
+ private DirectoryString(
+ DERUniversalString string)
+ {
+ this.string = string;
+ }
+
+ private DirectoryString(
+ DERUTF8String string)
+ {
+ this.string = string;
+ }
+
+ private DirectoryString(
+ DERBMPString string)
+ {
+ this.string = string;
+ }
+
+ public DirectoryString(String string)
+ {
+ this.string = new DERUTF8String(string);
+ }
+
+ public String getString()
+ {
+ return string.getString();
+ }
+
+ public String toString()
+ {
+ return string.getString();
+ }
+
+ /**
+ *
+ * DirectoryString ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..MAX)),
+ * printableString PrintableString (SIZE (1..MAX)),
+ * universalString UniversalString (SIZE (1..MAX)),
+ * utf8String UTF8String (SIZE (1..MAX)),
+ * bmpString BMPString (SIZE (1..MAX)) }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return ((ASN1Encodable)string).toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/RDN.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/RDN.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/RDN.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/RDN.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,119 @@
+package pdftk.org.bouncycastle.asn1.x500;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERSet;
+
+public class RDN
+ extends ASN1Object
+{
+ private ASN1Set values;
+
+ private RDN(ASN1Set values)
+ {
+ this.values = values;
+ }
+
+ public static RDN getInstance(Object obj)
+ {
+ if (obj instanceof RDN)
+ {
+ return (RDN)obj;
+ }
+ else if (obj != null)
+ {
+ return new RDN(ASN1Set.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Create a single valued RDN.
+ *
+ * @param oid RDN type.
+ * @param value RDN value.
+ */
+ public RDN(ASN1ObjectIdentifier oid, ASN1Encodable value)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(oid);
+ v.add(value);
+
+ this.values = new DERSet(new DERSequence(v));
+ }
+
+ public RDN(AttributeTypeAndValue attrTAndV)
+ {
+ this.values = new DERSet(attrTAndV);
+ }
+
+ /**
+ * Create a multi-valued RDN.
+ *
+ * @param aAndVs attribute type/value pairs making up the RDN
+ */
+ public RDN(AttributeTypeAndValue[] aAndVs)
+ {
+ this.values = new DERSet(aAndVs);
+ }
+
+ public boolean isMultiValued()
+ {
+ return this.values.size() > 1;
+ }
+
+ /**
+ * Return the number of AttributeTypeAndValue objects in this RDN,
+ *
+ * @return size of RDN, greater than 1 if multi-valued.
+ */
+ public int size()
+ {
+ return this.values.size();
+ }
+
+ public AttributeTypeAndValue getFirst()
+ {
+ if (this.values.size() == 0)
+ {
+ return null;
+ }
+
+ return AttributeTypeAndValue.getInstance(this.values.getObjectAt(0));
+ }
+
+ public AttributeTypeAndValue[] getTypesAndValues()
+ {
+ AttributeTypeAndValue[] tmp = new AttributeTypeAndValue[values.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = AttributeTypeAndValue.getInstance(values.getObjectAt(i));
+ }
+
+ return tmp;
+ }
+
+ /**
+ *
+ * RelativeDistinguishedName ::=
+ * SET OF AttributeTypeAndValue
+
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue }
+ *
+ * @return this object as an ASN1Primitive type
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return values;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/X500Name.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/X500Name.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/X500Name.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/X500Name.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,326 @@
+package pdftk.org.bouncycastle.asn1.x500;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x500.style.BCStyle;
+
+/**
+ *
+ * Name ::= CHOICE {
+ * RDNSequence }
+ *
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ *
+ * RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type OBJECT IDENTIFIER,
+ * value ANY }
+ *
+ */
+public class X500Name
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private static X500NameStyle defaultStyle = BCStyle.INSTANCE;
+
+ private boolean isHashCodeCalculated;
+ private int hashCodeValue;
+
+ private X500NameStyle style;
+ private RDN[] rdns;
+
+ public X500Name(X500NameStyle style, X500Name name)
+ {
+ this.rdns = name.rdns;
+ this.style = style;
+ }
+
+ /**
+ * Return a X500Name based on the passed in tagged object.
+ *
+ * @param obj tag object holding name.
+ * @param explicit true if explicitly tagged false otherwise.
+ * @return the X500Name
+ */
+ public static X500Name getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ // must be true as choice item
+ return getInstance(ASN1Sequence.getInstance(obj, true));
+ }
+
+ public static X500Name getInstance(
+ Object obj)
+ {
+ if (obj instanceof X500Name)
+ {
+ return (X500Name)obj;
+ }
+ else if (obj != null)
+ {
+ return new X500Name(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static X500Name getInstance(
+ X500NameStyle style,
+ Object obj)
+ {
+ if (obj instanceof X500Name)
+ {
+ return getInstance(style, ((X500Name)obj).toASN1Primitive());
+ }
+ else if (obj != null)
+ {
+ return new X500Name(style, ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from ASN1Sequence
+ *
+ * the principal will be a list of constructed sets, each containing an (OID, String) pair.
+ */
+ private X500Name(
+ ASN1Sequence seq)
+ {
+ this(defaultStyle, seq);
+ }
+
+ private X500Name(
+ X500NameStyle style,
+ ASN1Sequence seq)
+ {
+ this.style = style;
+ this.rdns = new RDN[seq.size()];
+
+ int index = 0;
+
+ for (Enumeration e = seq.getObjects(); e.hasMoreElements();)
+ {
+ rdns[index++] = RDN.getInstance(e.nextElement());
+ }
+ }
+
+ public X500Name(
+ RDN[] rDNs)
+ {
+ this(defaultStyle, rDNs);
+ }
+
+ public X500Name(
+ X500NameStyle style,
+ RDN[] rDNs)
+ {
+ this.rdns = rDNs;
+ this.style = style;
+ }
+
+ public X500Name(
+ String dirName)
+ {
+ this(defaultStyle, dirName);
+ }
+
+ public X500Name(
+ X500NameStyle style,
+ String dirName)
+ {
+ this(style.fromString(dirName));
+
+ this.style = style;
+ }
+
+ /**
+ * return an array of RDNs in structure order.
+ *
+ * @return an array of RDN objects.
+ */
+ public RDN[] getRDNs()
+ {
+ RDN[] tmp = new RDN[this.rdns.length];
+
+ System.arraycopy(rdns, 0, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ /**
+ * return an array of OIDs contained in the attribute type of each RDN in structure order.
+ *
+ * @return an array, possibly zero length, of ASN1ObjectIdentifiers objects.
+ */
+ public ASN1ObjectIdentifier[] getAttributeTypes()
+ {
+ int count = 0;
+
+ for (int i = 0; i != rdns.length; i++)
+ {
+ RDN rdn = rdns[i];
+
+ count += rdn.size();
+ }
+
+ ASN1ObjectIdentifier[] res = new ASN1ObjectIdentifier[count];
+
+ count = 0;
+
+ for (int i = 0; i != rdns.length; i++)
+ {
+ RDN rdn = rdns[i];
+
+ if (rdn.isMultiValued())
+ {
+ AttributeTypeAndValue[] attr = rdn.getTypesAndValues();
+ for (int j = 0; j != attr.length; j++)
+ {
+ res[count++] = attr[j].getType();
+ }
+ }
+ else if (rdn.size() != 0)
+ {
+ res[count++] = rdn.getFirst().getType();
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * return an array of RDNs containing the attribute type given by OID in structure order.
+ *
+ * @param attributeType the type OID we are looking for.
+ * @return an array, possibly zero length, of RDN objects.
+ */
+ public RDN[] getRDNs(ASN1ObjectIdentifier attributeType)
+ {
+ RDN[] res = new RDN[rdns.length];
+ int count = 0;
+
+ for (int i = 0; i != rdns.length; i++)
+ {
+ RDN rdn = rdns[i];
+
+ if (rdn.isMultiValued())
+ {
+ AttributeTypeAndValue[] attr = rdn.getTypesAndValues();
+ for (int j = 0; j != attr.length; j++)
+ {
+ if (attr[j].getType().equals(attributeType))
+ {
+ res[count++] = rdn;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (rdn.getFirst().getType().equals(attributeType))
+ {
+ res[count++] = rdn;
+ }
+ }
+ }
+
+ RDN[] tmp = new RDN[count];
+
+ System.arraycopy(res, 0, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERSequence(rdns);
+ }
+
+ public int hashCode()
+ {
+ if (isHashCodeCalculated)
+ {
+ return hashCodeValue;
+ }
+
+ isHashCodeCalculated = true;
+
+ hashCodeValue = style.calculateHashCode(this);
+
+ return hashCodeValue;
+ }
+
+ /**
+ * test for equality - note: case is ignored.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == this)
+ {
+ return true;
+ }
+
+ if (!(obj instanceof X500Name || obj instanceof ASN1Sequence))
+ {
+ return false;
+ }
+
+ ASN1Primitive derO = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (this.toASN1Primitive().equals(derO))
+ {
+ return true;
+ }
+
+ try
+ {
+ return style.areEqual(this, new X500Name(ASN1Sequence.getInstance(((ASN1Encodable)obj).toASN1Primitive())));
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ }
+
+ public String toString()
+ {
+ return style.toString(this);
+ }
+
+ /**
+ * Set the default style for X500Name construction.
+ *
+ * @param style an X500NameStyle
+ */
+ public static void setDefaultStyle(X500NameStyle style)
+ {
+ if (style == null)
+ {
+ throw new NullPointerException("cannot set style to null");
+ }
+
+ defaultStyle = style;
+ }
+
+ /**
+ * Return the current default style.
+ *
+ * @return default style for X500Name construction.
+ */
+ public static X500NameStyle getDefaultStyle()
+ {
+ return defaultStyle;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/X500NameBuilder.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/X500NameBuilder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/X500NameBuilder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/X500NameBuilder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,87 @@
+package pdftk.org.bouncycastle.asn1.x500;
+
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.x500.style.BCStyle;
+
+public class X500NameBuilder
+{
+ private X500NameStyle template;
+ private Vector rdns = new Vector();
+
+ public X500NameBuilder()
+ {
+ this(BCStyle.INSTANCE);
+ }
+
+ public X500NameBuilder(X500NameStyle template)
+ {
+ this.template = template;
+ }
+
+ public X500NameBuilder addRDN(ASN1ObjectIdentifier oid, String value)
+ {
+ this.addRDN(oid, template.stringToValue(oid, value));
+
+ return this;
+ }
+
+ public X500NameBuilder addRDN(ASN1ObjectIdentifier oid, ASN1Encodable value)
+ {
+ rdns.addElement(new RDN(oid, value));
+
+ return this;
+ }
+
+ public X500NameBuilder addRDN(AttributeTypeAndValue attrTAndV)
+ {
+ rdns.addElement(new RDN(attrTAndV));
+
+ return this;
+ }
+
+ public X500NameBuilder addMultiValuedRDN(ASN1ObjectIdentifier[] oids, String[] values)
+ {
+ ASN1Encodable[] vals = new ASN1Encodable[values.length];
+
+ for (int i = 0; i != vals.length; i++)
+ {
+ vals[i] = template.stringToValue(oids[i], values[i]);
+ }
+
+ return addMultiValuedRDN(oids, vals);
+ }
+
+ public X500NameBuilder addMultiValuedRDN(ASN1ObjectIdentifier[] oids, ASN1Encodable[] values)
+ {
+ AttributeTypeAndValue[] avs = new AttributeTypeAndValue[oids.length];
+
+ for (int i = 0; i != oids.length; i++)
+ {
+ avs[i] = new AttributeTypeAndValue(oids[i], values[i]);
+ }
+
+ return addMultiValuedRDN(avs);
+ }
+
+ public X500NameBuilder addMultiValuedRDN(AttributeTypeAndValue[] attrTAndVs)
+ {
+ rdns.addElement(new RDN(attrTAndVs));
+
+ return this;
+ }
+
+ public X500Name build()
+ {
+ RDN[] vals = new RDN[rdns.size()];
+
+ for (int i = 0; i != vals.length; i++)
+ {
+ vals[i] = (RDN)rdns.elementAt(i);
+ }
+
+ return new X500Name(template, vals);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/X500NameStyle.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/X500NameStyle.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/X500NameStyle.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/X500NameStyle.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,34 @@
+package pdftk.org.bouncycastle.asn1.x500;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * It turns out that the number of standard ways the fields in a DN should be
+ * encoded into their ASN.1 counterparts is rapidly approaching the
+ * number of machines on the internet. By default the X500Name class
+ * will produce UTF8Strings in line with the current recommendations (RFC 3280).
+ *
+ */
+public interface X500NameStyle
+{
+ /**
+ * Convert the passed in String value into the appropriate ASN.1
+ * encoded object.
+ *
+ * @param oid the oid associated with the value in the DN.
+ * @param value the value of the particular DN component.
+ * @return the ASN.1 equivalent for the value.
+ */
+ ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value);
+
+ ASN1ObjectIdentifier attrNameToOID(String attrName);
+
+ boolean areEqual(X500Name name1, X500Name name2);
+
+ RDN[] fromString(String dirName);
+
+ int calculateHashCode(X500Name name);
+
+ String toString(X500Name name);
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/style/BCStrictStyle.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/style/BCStrictStyle.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/style/BCStrictStyle.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/style/BCStrictStyle.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,36 @@
+package pdftk.org.bouncycastle.asn1.x500.style;
+
+import pdftk.org.bouncycastle.asn1.x500.RDN;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+import pdftk.org.bouncycastle.asn1.x500.X500NameStyle;
+
+/**
+ * Variation of BCStyle that insists on strict ordering for equality
+ * and hashCode comparisons
+ */
+public class BCStrictStyle
+ extends BCStyle
+{
+ public static final X500NameStyle INSTANCE = new BCStrictStyle();
+
+ public boolean areEqual(X500Name name1, X500Name name2)
+ {
+ RDN[] rdns1 = name1.getRDNs();
+ RDN[] rdns2 = name2.getRDNs();
+
+ if (rdns1.length != rdns2.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != rdns1.length; i++)
+ {
+ if (!rdnAreEqual(rdns1[i], rdns2[i]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/style/BCStyle.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/style/BCStyle.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/style/BCStyle.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/style/BCStyle.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,449 @@
+package pdftk.org.bouncycastle.asn1.x500.style;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+import pdftk.org.bouncycastle.asn1.DERUTF8String;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.x500.AttributeTypeAndValue;
+import pdftk.org.bouncycastle.asn1.x500.RDN;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+import pdftk.org.bouncycastle.asn1.x500.X500NameStyle;
+import pdftk.org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
+
+public class BCStyle
+ implements X500NameStyle
+{
+ public static final X500NameStyle INSTANCE = new BCStyle();
+
+ /**
+ * country code - StringType(SIZE(2))
+ */
+ public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6");
+
+ /**
+ * organization - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10");
+
+ /**
+ * organizational unit name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11");
+
+ /**
+ * Title
+ */
+ public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12");
+
+ /**
+ * common name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5");
+
+ /**
+ * street - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier STREET = new ASN1ObjectIdentifier("2.5.4.9");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SERIALNUMBER = SN;
+
+ /**
+ * locality name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7");
+
+ /**
+ * state, or province name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8");
+
+ /**
+ * Naming attributes of type X520name
+ */
+ public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4");
+ public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42");
+ public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43");
+ public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44");
+ public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45");
+
+ /**
+ * businessCategory - DirectoryString(SIZE(1..128)
+ */
+ public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier(
+ "2.5.4.15");
+
+ /**
+ * postalCode - DirectoryString(SIZE(1..40)
+ */
+ public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier(
+ "2.5.4.17");
+
+ /**
+ * dnQualifier - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier(
+ "2.5.4.46");
+
+ /**
+ * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier(
+ "2.5.4.65");
+
+
+ /**
+ * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
+ */
+ public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.1");
+
+ /**
+ * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
+ */
+ public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.2");
+
+ /**
+ * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
+ */
+ public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.3");
+
+ /**
+ * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.4");
+
+ /**
+ * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.5");
+
+
+ /**
+ * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier NAME_AT_BIRTH = new ASN1ObjectIdentifier("1.3.36.8.3.14");
+
+ /**
+ * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
+ * DirectoryString(SIZE(1..30))
+ */
+ public static final ASN1ObjectIdentifier POSTAL_ADDRESS = new ASN1ObjectIdentifier("2.5.4.16");
+
+ /**
+ * RFC 2256 dmdName
+ */
+ public static final ASN1ObjectIdentifier DMD_NAME = new ASN1ObjectIdentifier("2.5.4.54");
+
+ /**
+ * id-at-telephoneNumber
+ */
+ public static final ASN1ObjectIdentifier TELEPHONE_NUMBER = X509ObjectIdentifiers.id_at_telephoneNumber;
+
+ /**
+ * id-at-name
+ */
+ public static final ASN1ObjectIdentifier NAME = X509ObjectIdentifiers.id_at_name;
+
+ /**
+ * Email address (RSA PKCS#9 extension) - IA5String.
+ *
Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
+ */
+ public static final ASN1ObjectIdentifier EmailAddress = PKCSObjectIdentifiers.pkcs_9_at_emailAddress;
+
+ /**
+ * more from PKCS#9
+ */
+ public static final ASN1ObjectIdentifier UnstructuredName = PKCSObjectIdentifiers.pkcs_9_at_unstructuredName;
+ public static final ASN1ObjectIdentifier UnstructuredAddress = PKCSObjectIdentifiers.pkcs_9_at_unstructuredAddress;
+
+ /**
+ * email address in Verisign certificates
+ */
+ public static final ASN1ObjectIdentifier E = EmailAddress;
+
+ /*
+ * others...
+ */
+ public static final ASN1ObjectIdentifier DC = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
+
+ /**
+ * LDAP User id.
+ */
+ public static final ASN1ObjectIdentifier UID = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
+
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ private static final Hashtable DefaultSymbols = new Hashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ private static final Hashtable DefaultLookUp = new Hashtable();
+
+ static
+ {
+ DefaultSymbols.put(C, "C");
+ DefaultSymbols.put(O, "O");
+ DefaultSymbols.put(T, "T");
+ DefaultSymbols.put(OU, "OU");
+ DefaultSymbols.put(CN, "CN");
+ DefaultSymbols.put(L, "L");
+ DefaultSymbols.put(ST, "ST");
+ DefaultSymbols.put(SN, "SERIALNUMBER");
+ DefaultSymbols.put(EmailAddress, "E");
+ DefaultSymbols.put(DC, "DC");
+ DefaultSymbols.put(UID, "UID");
+ DefaultSymbols.put(STREET, "STREET");
+ DefaultSymbols.put(SURNAME, "SURNAME");
+ DefaultSymbols.put(GIVENNAME, "GIVENNAME");
+ DefaultSymbols.put(INITIALS, "INITIALS");
+ DefaultSymbols.put(GENERATION, "GENERATION");
+ DefaultSymbols.put(UnstructuredAddress, "unstructuredAddress");
+ DefaultSymbols.put(UnstructuredName, "unstructuredName");
+ DefaultSymbols.put(UNIQUE_IDENTIFIER, "UniqueIdentifier");
+ DefaultSymbols.put(DN_QUALIFIER, "DN");
+ DefaultSymbols.put(PSEUDONYM, "Pseudonym");
+ DefaultSymbols.put(POSTAL_ADDRESS, "PostalAddress");
+ DefaultSymbols.put(NAME_AT_BIRTH, "NameAtBirth");
+ DefaultSymbols.put(COUNTRY_OF_CITIZENSHIP, "CountryOfCitizenship");
+ DefaultSymbols.put(COUNTRY_OF_RESIDENCE, "CountryOfResidence");
+ DefaultSymbols.put(GENDER, "Gender");
+ DefaultSymbols.put(PLACE_OF_BIRTH, "PlaceOfBirth");
+ DefaultSymbols.put(DATE_OF_BIRTH, "DateOfBirth");
+ DefaultSymbols.put(POSTAL_CODE, "PostalCode");
+ DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory");
+ DefaultSymbols.put(TELEPHONE_NUMBER, "TelephoneNumber");
+ DefaultSymbols.put(NAME, "Name");
+
+ DefaultLookUp.put("c", C);
+ DefaultLookUp.put("o", O);
+ DefaultLookUp.put("t", T);
+ DefaultLookUp.put("ou", OU);
+ DefaultLookUp.put("cn", CN);
+ DefaultLookUp.put("l", L);
+ DefaultLookUp.put("st", ST);
+ DefaultLookUp.put("sn", SN);
+ DefaultLookUp.put("serialnumber", SN);
+ DefaultLookUp.put("street", STREET);
+ DefaultLookUp.put("emailaddress", E);
+ DefaultLookUp.put("dc", DC);
+ DefaultLookUp.put("e", E);
+ DefaultLookUp.put("uid", UID);
+ DefaultLookUp.put("surname", SURNAME);
+ DefaultLookUp.put("givenname", GIVENNAME);
+ DefaultLookUp.put("initials", INITIALS);
+ DefaultLookUp.put("generation", GENERATION);
+ DefaultLookUp.put("unstructuredaddress", UnstructuredAddress);
+ DefaultLookUp.put("unstructuredname", UnstructuredName);
+ DefaultLookUp.put("uniqueidentifier", UNIQUE_IDENTIFIER);
+ DefaultLookUp.put("dn", DN_QUALIFIER);
+ DefaultLookUp.put("pseudonym", PSEUDONYM);
+ DefaultLookUp.put("postaladdress", POSTAL_ADDRESS);
+ DefaultLookUp.put("nameofbirth", NAME_AT_BIRTH);
+ DefaultLookUp.put("countryofcitizenship", COUNTRY_OF_CITIZENSHIP);
+ DefaultLookUp.put("countryofresidence", COUNTRY_OF_RESIDENCE);
+ DefaultLookUp.put("gender", GENDER);
+ DefaultLookUp.put("placeofbirth", PLACE_OF_BIRTH);
+ DefaultLookUp.put("dateofbirth", DATE_OF_BIRTH);
+ DefaultLookUp.put("postalcode", POSTAL_CODE);
+ DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY);
+ DefaultLookUp.put("telephonenumber", TELEPHONE_NUMBER);
+ DefaultLookUp.put("name", NAME);
+ }
+
+ protected BCStyle()
+ {
+
+ }
+
+ public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
+ {
+ if (value.length() != 0 && value.charAt(0) == '#')
+ {
+ try
+ {
+ return IETFUtils.valueFromHexString(value, 1);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("can't recode value for oid " + oid.getId());
+ }
+ }
+ else
+ {
+ if (value.length() != 0 && value.charAt(0) == '\\')
+ {
+ value = value.substring(1);
+ }
+ if (oid.equals(EmailAddress) || oid.equals(DC))
+ {
+ return new DERIA5String(value);
+ }
+ else if (oid.equals(DATE_OF_BIRTH)) // accept time string as well as # (for compatibility)
+ {
+ return new ASN1GeneralizedTime(value);
+ }
+ else if (oid.equals(C) || oid.equals(SN) || oid.equals(DN_QUALIFIER)
+ || oid.equals(TELEPHONE_NUMBER))
+ {
+ return new DERPrintableString(value);
+ }
+ }
+
+ return new DERUTF8String(value);
+ }
+
+ public ASN1ObjectIdentifier attrNameToOID(String attrName)
+ {
+ return IETFUtils.decodeAttrName(attrName, DefaultLookUp);
+ }
+
+ public boolean areEqual(X500Name name1, X500Name name2)
+ {
+ RDN[] rdns1 = name1.getRDNs();
+ RDN[] rdns2 = name2.getRDNs();
+
+ if (rdns1.length != rdns2.length)
+ {
+ return false;
+ }
+
+ boolean reverse = false;
+
+ if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
+ {
+ reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
+ }
+
+ for (int i = 0; i != rdns1.length; i++)
+ {
+ if (!foundMatch(reverse, rdns1[i], rdns2))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
+ {
+ if (reverse)
+ {
+ for (int i = possRDNs.length - 1; i >= 0; i--)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i != possRDNs.length; i++)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
+ {
+ return IETFUtils.rDNAreEqual(rdn1, rdn2);
+ }
+
+ public RDN[] fromString(String dirName)
+ {
+ return IETFUtils.rDNsFromString(dirName, this);
+ }
+
+ public int calculateHashCode(X500Name name)
+ {
+ int hashCodeValue = 0;
+ RDN[] rdns = name.getRDNs();
+
+ // this needs to be order independent, like equals
+ for (int i = 0; i != rdns.length; i++)
+ {
+ if (rdns[i].isMultiValued())
+ {
+ AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
+
+ for (int j = 0; j != atv.length; j++)
+ {
+ hashCodeValue ^= atv[j].getType().hashCode();
+ hashCodeValue ^= calcHashCode(atv[j].getValue());
+ }
+ }
+ else
+ {
+ hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
+ hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
+ }
+ }
+
+ return hashCodeValue;
+ }
+
+ private int calcHashCode(ASN1Encodable enc)
+ {
+ String value = IETFUtils.valueToString(enc);
+
+ value = IETFUtils.canonicalize(value);
+
+ return value.hashCode();
+ }
+
+ public String toString(X500Name name)
+ {
+ StringBuffer buf = new StringBuffer();
+ boolean first = true;
+
+ RDN[] rdns = name.getRDNs();
+
+ for (int i = 0; i < rdns.length; i++)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append(',');
+ }
+
+ IETFUtils.appendRDN(buf, rdns[i], DefaultSymbols);
+ }
+
+ return buf.toString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/style/IETFUtils.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/style/IETFUtils.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/style/IETFUtils.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/style/IETFUtils.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,409 @@
+package pdftk.org.bouncycastle.asn1.x500.style;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Encoding;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1String;
+import pdftk.org.bouncycastle.asn1.DERUniversalString;
+import pdftk.org.bouncycastle.asn1.x500.AttributeTypeAndValue;
+import pdftk.org.bouncycastle.asn1.x500.RDN;
+import pdftk.org.bouncycastle.asn1.x500.X500NameBuilder;
+import pdftk.org.bouncycastle.asn1.x500.X500NameStyle;
+import pdftk.org.bouncycastle.util.Strings;
+import pdftk.org.bouncycastle.util.encoders.Hex;
+
+public class IETFUtils
+{
+ public static RDN[] rDNsFromString(String name, X500NameStyle x500Style)
+ {
+ X500NameTokenizer nTok = new X500NameTokenizer(name);
+ X500NameBuilder builder = new X500NameBuilder(x500Style);
+
+ while (nTok.hasMoreTokens())
+ {
+ String token = nTok.nextToken();
+ int index = token.indexOf('=');
+
+ if (index == -1)
+ {
+ throw new IllegalArgumentException("badly formated directory string");
+ }
+
+ String attr = token.substring(0, index);
+ String value = token.substring(index + 1);
+ ASN1ObjectIdentifier oid = x500Style.attrNameToOID(attr);
+
+ if (value.indexOf('+') > 0)
+ {
+ X500NameTokenizer vTok = new X500NameTokenizer(value, '+');
+ String v = vTok.nextToken();
+
+ Vector oids = new Vector();
+ Vector values = new Vector();
+
+ oids.addElement(oid);
+ values.addElement(v);
+
+ while (vTok.hasMoreTokens())
+ {
+ String sv = vTok.nextToken();
+ int ndx = sv.indexOf('=');
+
+ String nm = sv.substring(0, ndx);
+ String vl = sv.substring(ndx + 1);
+
+ oids.addElement(x500Style.attrNameToOID(nm));
+ values.addElement(vl);
+ }
+
+ builder.addMultiValuedRDN(toOIDArray(oids), toValueArray(values));
+ }
+ else
+ {
+ builder.addRDN(oid, value);
+ }
+ }
+
+ return builder.build().getRDNs();
+ }
+
+ private static String[] toValueArray(Vector values)
+ {
+ String[] tmp = new String[values.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = (String)values.elementAt(i);
+ }
+
+ return tmp;
+ }
+
+ private static ASN1ObjectIdentifier[] toOIDArray(Vector oids)
+ {
+ ASN1ObjectIdentifier[] tmp = new ASN1ObjectIdentifier[oids.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = (ASN1ObjectIdentifier)oids.elementAt(i);
+ }
+
+ return tmp;
+ }
+
+ public static ASN1ObjectIdentifier decodeAttrName(
+ String name,
+ Hashtable lookUp)
+ {
+ if (Strings.toUpperCase(name).startsWith("OID."))
+ {
+ return new ASN1ObjectIdentifier(name.substring(4));
+ }
+ else if (name.charAt(0) >= '0' && name.charAt(0) <= '9')
+ {
+ return new ASN1ObjectIdentifier(name);
+ }
+
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)lookUp.get(Strings.toLowerCase(name));
+ if (oid == null)
+ {
+ throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name");
+ }
+
+ return oid;
+ }
+
+ public static ASN1Encodable valueFromHexString(
+ String str,
+ int off)
+ throws IOException
+ {
+ str = Strings.toLowerCase(str);
+ byte[] data = new byte[(str.length() - off) / 2];
+ for (int index = 0; index != data.length; index++)
+ {
+ char left = str.charAt((index * 2) + off);
+ char right = str.charAt((index * 2) + off + 1);
+
+ if (left < 'a')
+ {
+ data[index] = (byte)((left - '0') << 4);
+ }
+ else
+ {
+ data[index] = (byte)((left - 'a' + 10) << 4);
+ }
+ if (right < 'a')
+ {
+ data[index] |= (byte)(right - '0');
+ }
+ else
+ {
+ data[index] |= (byte)(right - 'a' + 10);
+ }
+ }
+
+ return ASN1Primitive.fromByteArray(data);
+ }
+
+ public static void appendRDN(
+ StringBuffer buf,
+ RDN rdn,
+ Hashtable oidSymbols)
+ {
+ if (rdn.isMultiValued())
+ {
+ AttributeTypeAndValue[] atv = rdn.getTypesAndValues();
+ boolean firstAtv = true;
+
+ for (int j = 0; j != atv.length; j++)
+ {
+ if (firstAtv)
+ {
+ firstAtv = false;
+ }
+ else
+ {
+ buf.append('+');
+ }
+
+ IETFUtils.appendTypeAndValue(buf, atv[j], oidSymbols);
+ }
+ }
+ else
+ {
+ IETFUtils.appendTypeAndValue(buf, rdn.getFirst(), oidSymbols);
+ }
+ }
+
+ public static void appendTypeAndValue(
+ StringBuffer buf,
+ AttributeTypeAndValue typeAndValue,
+ Hashtable oidSymbols)
+ {
+ String sym = (String)oidSymbols.get(typeAndValue.getType());
+
+ if (sym != null)
+ {
+ buf.append(sym);
+ }
+ else
+ {
+ buf.append(typeAndValue.getType().getId());
+ }
+
+ buf.append('=');
+
+ buf.append(valueToString(typeAndValue.getValue()));
+ }
+
+ public static String valueToString(ASN1Encodable value)
+ {
+ StringBuffer vBuf = new StringBuffer();
+
+ if (value instanceof ASN1String && !(value instanceof DERUniversalString))
+ {
+ String v = ((ASN1String)value).getString();
+ if (v.length() > 0 && v.charAt(0) == '#')
+ {
+ vBuf.append("\\" + v);
+ }
+ else
+ {
+ vBuf.append(v);
+ }
+ }
+ else
+ {
+ try
+ {
+ vBuf.append("#" + bytesToString(Hex.encode(value.toASN1Primitive().getEncoded(ASN1Encoding.DER))));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("Other value has no encoded form");
+ }
+ }
+
+ int end = vBuf.length();
+ int index = 0;
+
+ if (vBuf.length() >= 2 && vBuf.charAt(0) == '\\' && vBuf.charAt(1) == '#')
+ {
+ index += 2;
+ }
+
+ while (index != end)
+ {
+ if ((vBuf.charAt(index) == ',')
+ || (vBuf.charAt(index) == '"')
+ || (vBuf.charAt(index) == '\\')
+ || (vBuf.charAt(index) == '+')
+ || (vBuf.charAt(index) == '=')
+ || (vBuf.charAt(index) == '<')
+ || (vBuf.charAt(index) == '>')
+ || (vBuf.charAt(index) == ';'))
+ {
+ vBuf.insert(index, "\\");
+ index++;
+ end++;
+ }
+
+ index++;
+ }
+
+ return vBuf.toString();
+ }
+
+ private static String bytesToString(
+ byte[] data)
+ {
+ char[] cs = new char[data.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)(data[i] & 0xff);
+ }
+
+ return new String(cs);
+ }
+
+ public static String canonicalize(String s)
+ {
+ String value = Strings.toLowerCase(s.trim());
+
+ if (value.length() > 0 && value.charAt(0) == '#')
+ {
+ ASN1Primitive obj = decodeObject(value);
+
+ if (obj instanceof ASN1String)
+ {
+ value = Strings.toLowerCase(((ASN1String)obj).getString().trim());
+ }
+ }
+
+ value = stripInternalSpaces(value);
+
+ return value;
+ }
+
+ private static ASN1Primitive decodeObject(String oValue)
+ {
+ try
+ {
+ return ASN1Primitive.fromByteArray(Hex.decode(oValue.substring(1)));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("unknown encoding in name: " + e);
+ }
+ }
+
+ public static String stripInternalSpaces(
+ String str)
+ {
+ StringBuffer res = new StringBuffer();
+
+ if (str.length() != 0)
+ {
+ char c1 = str.charAt(0);
+
+ res.append(c1);
+
+ for (int k = 1; k < str.length(); k++)
+ {
+ char c2 = str.charAt(k);
+ if (!(c1 == ' ' && c2 == ' '))
+ {
+ res.append(c2);
+ }
+ c1 = c2;
+ }
+ }
+
+ return res.toString();
+ }
+
+ public static boolean rDNAreEqual(RDN rdn1, RDN rdn2)
+ {
+ if (rdn1.isMultiValued())
+ {
+ if (rdn2.isMultiValued())
+ {
+ AttributeTypeAndValue[] atvs1 = rdn1.getTypesAndValues();
+ AttributeTypeAndValue[] atvs2 = rdn2.getTypesAndValues();
+
+ if (atvs1.length != atvs2.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != atvs1.length; i++)
+ {
+ if (!atvAreEqual(atvs1[i], atvs2[i]))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!rdn2.isMultiValued())
+ {
+ return atvAreEqual(rdn1.getFirst(), rdn2.getFirst());
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static boolean atvAreEqual(AttributeTypeAndValue atv1, AttributeTypeAndValue atv2)
+ {
+ if (atv1 == atv2)
+ {
+ return true;
+ }
+
+ if (atv1 == null)
+ {
+ return false;
+ }
+
+ if (atv2 == null)
+ {
+ return false;
+ }
+
+ ASN1ObjectIdentifier o1 = atv1.getType();
+ ASN1ObjectIdentifier o2 = atv2.getType();
+
+ if (!o1.equals(o2))
+ {
+ return false;
+ }
+
+ String v1 = IETFUtils.canonicalize(IETFUtils.valueToString(atv1.getValue()));
+ String v2 = IETFUtils.canonicalize(IETFUtils.valueToString(atv2.getValue()));
+
+ if (!v1.equals(v2))
+ {
+ return false;
+ }
+
+ return true;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/style/RFC4519Style.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/style/RFC4519Style.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/style/RFC4519Style.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/style/RFC4519Style.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,348 @@
+package pdftk.org.bouncycastle.asn1.x500.style;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+import pdftk.org.bouncycastle.asn1.DERUTF8String;
+import pdftk.org.bouncycastle.asn1.x500.AttributeTypeAndValue;
+import pdftk.org.bouncycastle.asn1.x500.RDN;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+import pdftk.org.bouncycastle.asn1.x500.X500NameStyle;
+
+public class RFC4519Style
+ implements X500NameStyle
+{
+ public static final X500NameStyle INSTANCE = new RFC4519Style();
+
+ public static final ASN1ObjectIdentifier businessCategory = new ASN1ObjectIdentifier("2.5.4.15");
+ public static final ASN1ObjectIdentifier c = new ASN1ObjectIdentifier("2.5.4.6");
+ public static final ASN1ObjectIdentifier cn = new ASN1ObjectIdentifier("2.5.4.3");
+ public static final ASN1ObjectIdentifier dc = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
+ public static final ASN1ObjectIdentifier description = new ASN1ObjectIdentifier("2.5.4.13");
+ public static final ASN1ObjectIdentifier destinationIndicator = new ASN1ObjectIdentifier("2.5.4.27");
+ public static final ASN1ObjectIdentifier distinguishedName = new ASN1ObjectIdentifier("2.5.4.49");
+ public static final ASN1ObjectIdentifier dnQualifier = new ASN1ObjectIdentifier("2.5.4.46");
+ public static final ASN1ObjectIdentifier enhancedSearchGuide = new ASN1ObjectIdentifier("2.5.4.47");
+ public static final ASN1ObjectIdentifier facsimileTelephoneNumber = new ASN1ObjectIdentifier("2.5.4.23");
+ public static final ASN1ObjectIdentifier generationQualifier = new ASN1ObjectIdentifier("2.5.4.44");
+ public static final ASN1ObjectIdentifier givenName = new ASN1ObjectIdentifier("2.5.4.42");
+ public static final ASN1ObjectIdentifier houseIdentifier = new ASN1ObjectIdentifier("2.5.4.51");
+ public static final ASN1ObjectIdentifier initials = new ASN1ObjectIdentifier("2.5.4.43");
+ public static final ASN1ObjectIdentifier internationalISDNNumber = new ASN1ObjectIdentifier("2.5.4.25");
+ public static final ASN1ObjectIdentifier l = new ASN1ObjectIdentifier("2.5.4.7");
+ public static final ASN1ObjectIdentifier member = new ASN1ObjectIdentifier("2.5.4.31");
+ public static final ASN1ObjectIdentifier name = new ASN1ObjectIdentifier("2.5.4.41");
+ public static final ASN1ObjectIdentifier o = new ASN1ObjectIdentifier("2.5.4.10");
+ public static final ASN1ObjectIdentifier ou = new ASN1ObjectIdentifier("2.5.4.11");
+ public static final ASN1ObjectIdentifier owner = new ASN1ObjectIdentifier("2.5.4.32");
+ public static final ASN1ObjectIdentifier physicalDeliveryOfficeName = new ASN1ObjectIdentifier("2.5.4.19");
+ public static final ASN1ObjectIdentifier postalAddress = new ASN1ObjectIdentifier("2.5.4.16");
+ public static final ASN1ObjectIdentifier postalCode = new ASN1ObjectIdentifier("2.5.4.17");
+ public static final ASN1ObjectIdentifier postOfficeBox = new ASN1ObjectIdentifier("2.5.4.18");
+ public static final ASN1ObjectIdentifier preferredDeliveryMethod = new ASN1ObjectIdentifier("2.5.4.28");
+ public static final ASN1ObjectIdentifier registeredAddress = new ASN1ObjectIdentifier("2.5.4.26");
+ public static final ASN1ObjectIdentifier roleOccupant = new ASN1ObjectIdentifier("2.5.4.33");
+ public static final ASN1ObjectIdentifier searchGuide = new ASN1ObjectIdentifier("2.5.4.14");
+ public static final ASN1ObjectIdentifier seeAlso = new ASN1ObjectIdentifier("2.5.4.34");
+ public static final ASN1ObjectIdentifier serialNumber = new ASN1ObjectIdentifier("2.5.4.5");
+ public static final ASN1ObjectIdentifier sn = new ASN1ObjectIdentifier("2.5.4.4");
+ public static final ASN1ObjectIdentifier st = new ASN1ObjectIdentifier("2.5.4.8");
+ public static final ASN1ObjectIdentifier street = new ASN1ObjectIdentifier("2.5.4.9");
+ public static final ASN1ObjectIdentifier telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20");
+ public static final ASN1ObjectIdentifier teletexTerminalIdentifier = new ASN1ObjectIdentifier("2.5.4.22");
+ public static final ASN1ObjectIdentifier telexNumber = new ASN1ObjectIdentifier("2.5.4.21");
+ public static final ASN1ObjectIdentifier title = new ASN1ObjectIdentifier("2.5.4.12");
+ public static final ASN1ObjectIdentifier uid = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
+ public static final ASN1ObjectIdentifier uniqueMember = new ASN1ObjectIdentifier("2.5.4.50");
+ public static final ASN1ObjectIdentifier userPassword = new ASN1ObjectIdentifier("2.5.4.35");
+ public static final ASN1ObjectIdentifier x121Address = new ASN1ObjectIdentifier("2.5.4.24");
+ public static final ASN1ObjectIdentifier x500UniqueIdentifier = new ASN1ObjectIdentifier("2.5.4.45");
+
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ private static final Hashtable DefaultSymbols = new Hashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ private static final Hashtable DefaultLookUp = new Hashtable();
+
+ static
+ {
+ DefaultSymbols.put(businessCategory, "businessCategory");
+ DefaultSymbols.put(c, "c");
+ DefaultSymbols.put(cn, "cn");
+ DefaultSymbols.put(dc, "dc");
+ DefaultSymbols.put(description, "description");
+ DefaultSymbols.put(destinationIndicator, "destinationIndicator");
+ DefaultSymbols.put(distinguishedName, "distinguishedName");
+ DefaultSymbols.put(dnQualifier, "dnQualifier");
+ DefaultSymbols.put(enhancedSearchGuide, "enhancedSearchGuide");
+ DefaultSymbols.put(facsimileTelephoneNumber, "facsimileTelephoneNumber");
+ DefaultSymbols.put(generationQualifier, "generationQualifier");
+ DefaultSymbols.put(givenName, "givenName");
+ DefaultSymbols.put(houseIdentifier, "houseIdentifier");
+ DefaultSymbols.put(initials, "initials");
+ DefaultSymbols.put(internationalISDNNumber, "internationalISDNNumber");
+ DefaultSymbols.put(l, "l");
+ DefaultSymbols.put(member, "member");
+ DefaultSymbols.put(name, "name");
+ DefaultSymbols.put(o, "o");
+ DefaultSymbols.put(ou, "ou");
+ DefaultSymbols.put(owner, "owner");
+ DefaultSymbols.put(physicalDeliveryOfficeName, "physicalDeliveryOfficeName");
+ DefaultSymbols.put(postalAddress, "postalAddress");
+ DefaultSymbols.put(postalCode, "postalCode");
+ DefaultSymbols.put(postOfficeBox, "postOfficeBox");
+ DefaultSymbols.put(preferredDeliveryMethod, "preferredDeliveryMethod");
+ DefaultSymbols.put(registeredAddress, "registeredAddress");
+ DefaultSymbols.put(roleOccupant, "roleOccupant");
+ DefaultSymbols.put(searchGuide, "searchGuide");
+ DefaultSymbols.put(seeAlso, "seeAlso");
+ DefaultSymbols.put(serialNumber, "serialNumber");
+ DefaultSymbols.put(sn, "sn");
+ DefaultSymbols.put(st, "st");
+ DefaultSymbols.put(street, "street");
+ DefaultSymbols.put(telephoneNumber, "telephoneNumber");
+ DefaultSymbols.put(teletexTerminalIdentifier, "teletexTerminalIdentifier");
+ DefaultSymbols.put(telexNumber, "telexNumber");
+ DefaultSymbols.put(title, "title");
+ DefaultSymbols.put(uid, "uid");
+ DefaultSymbols.put(uniqueMember, "uniqueMember");
+ DefaultSymbols.put(userPassword, "userPassword");
+ DefaultSymbols.put(x121Address, "x121Address");
+ DefaultSymbols.put(x500UniqueIdentifier, "x500UniqueIdentifier");
+
+ DefaultLookUp.put("businesscategory", businessCategory);
+ DefaultLookUp.put("c", c);
+ DefaultLookUp.put("cn", cn);
+ DefaultLookUp.put("dc", dc);
+ DefaultLookUp.put("description", description);
+ DefaultLookUp.put("destinationindicator", destinationIndicator);
+ DefaultLookUp.put("distinguishedname", distinguishedName);
+ DefaultLookUp.put("dnqualifier", dnQualifier);
+ DefaultLookUp.put("enhancedsearchguide", enhancedSearchGuide);
+ DefaultLookUp.put("facsimiletelephonenumber", facsimileTelephoneNumber);
+ DefaultLookUp.put("generationqualifier", generationQualifier);
+ DefaultLookUp.put("givenname", givenName);
+ DefaultLookUp.put("houseidentifier", houseIdentifier);
+ DefaultLookUp.put("initials", initials);
+ DefaultLookUp.put("internationalisdnnumber", internationalISDNNumber);
+ DefaultLookUp.put("l", l);
+ DefaultLookUp.put("member", member);
+ DefaultLookUp.put("name", name);
+ DefaultLookUp.put("o", o);
+ DefaultLookUp.put("ou", ou);
+ DefaultLookUp.put("owner", owner);
+ DefaultLookUp.put("physicaldeliveryofficename", physicalDeliveryOfficeName);
+ DefaultLookUp.put("postaladdress", postalAddress);
+ DefaultLookUp.put("postalcode", postalCode);
+ DefaultLookUp.put("postofficebox", postOfficeBox);
+ DefaultLookUp.put("preferreddeliverymethod", preferredDeliveryMethod);
+ DefaultLookUp.put("registeredaddress", registeredAddress);
+ DefaultLookUp.put("roleoccupant", roleOccupant);
+ DefaultLookUp.put("searchguide", searchGuide);
+ DefaultLookUp.put("seealso", seeAlso);
+ DefaultLookUp.put("serialnumber", serialNumber);
+ DefaultLookUp.put("sn", sn);
+ DefaultLookUp.put("st", st);
+ DefaultLookUp.put("street", street);
+ DefaultLookUp.put("telephonenumber", telephoneNumber);
+ DefaultLookUp.put("teletexterminalidentifier", teletexTerminalIdentifier);
+ DefaultLookUp.put("telexnumber", telexNumber);
+ DefaultLookUp.put("title", title);
+ DefaultLookUp.put("uid", uid);
+ DefaultLookUp.put("uniquemember", uniqueMember);
+ DefaultLookUp.put("userpassword", userPassword);
+ DefaultLookUp.put("x121address", x121Address);
+ DefaultLookUp.put("x500uniqueidentifier", x500UniqueIdentifier);
+
+ // TODO: need to add correct matching for equality comparisons.
+ }
+
+ protected RFC4519Style()
+ {
+
+ }
+
+ public ASN1Encodable stringToValue(ASN1ObjectIdentifier oid, String value)
+ {
+ if (value.length() != 0 && value.charAt(0) == '#')
+ {
+ try
+ {
+ return IETFUtils.valueFromHexString(value, 1);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("can't recode value for oid " + oid.getId());
+ }
+ }
+ else
+ {
+ if (value.length() != 0 && value.charAt(0) == '\\')
+ {
+ value = value.substring(1);
+ }
+ if (oid.equals(dc))
+ {
+ return new DERIA5String(value);
+ }
+ else if (oid.equals(c) || oid.equals(serialNumber) || oid.equals(dnQualifier)
+ || oid.equals(telephoneNumber))
+ {
+ return new DERPrintableString(value);
+ }
+ }
+
+ return new DERUTF8String(value);
+ }
+
+ public ASN1ObjectIdentifier attrNameToOID(String attrName)
+ {
+ return IETFUtils.decodeAttrName(attrName, DefaultLookUp);
+ }
+
+ public boolean areEqual(X500Name name1, X500Name name2)
+ {
+ RDN[] rdns1 = name1.getRDNs();
+ RDN[] rdns2 = name2.getRDNs();
+
+ if (rdns1.length != rdns2.length)
+ {
+ return false;
+ }
+
+ boolean reverse = false;
+
+ if (rdns1[0].getFirst() != null && rdns2[0].getFirst() != null)
+ {
+ reverse = !rdns1[0].getFirst().getType().equals(rdns2[0].getFirst().getType()); // guess forward
+ }
+
+ for (int i = 0; i != rdns1.length; i++)
+ {
+ if (!foundMatch(reverse, rdns1[i], rdns2))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean foundMatch(boolean reverse, RDN rdn, RDN[] possRDNs)
+ {
+ if (reverse)
+ {
+ for (int i = possRDNs.length - 1; i >= 0; i--)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i != possRDNs.length; i++)
+ {
+ if (possRDNs[i] != null && rdnAreEqual(rdn, possRDNs[i]))
+ {
+ possRDNs[i] = null;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean rdnAreEqual(RDN rdn1, RDN rdn2)
+ {
+ return IETFUtils.rDNAreEqual(rdn1, rdn2);
+ }
+
+ // parse backwards
+ public RDN[] fromString(String dirName)
+ {
+ RDN[] tmp = IETFUtils.rDNsFromString(dirName, this);
+ RDN[] res = new RDN[tmp.length];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ res[res.length - i - 1] = tmp[i];
+ }
+
+ return res;
+ }
+
+ public int calculateHashCode(X500Name name)
+ {
+ int hashCodeValue = 0;
+ RDN[] rdns = name.getRDNs();
+
+ // this needs to be order independent, like equals
+ for (int i = 0; i != rdns.length; i++)
+ {
+ if (rdns[i].isMultiValued())
+ {
+ AttributeTypeAndValue[] atv = rdns[i].getTypesAndValues();
+
+ for (int j = 0; j != atv.length; j++)
+ {
+ hashCodeValue ^= atv[j].getType().hashCode();
+ hashCodeValue ^= calcHashCode(atv[j].getValue());
+ }
+ }
+ else
+ {
+ hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
+ hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
+ }
+ }
+
+ return hashCodeValue;
+ }
+
+ private int calcHashCode(ASN1Encodable enc)
+ {
+ String value = IETFUtils.valueToString(enc);
+
+ value = IETFUtils.canonicalize(value);
+
+ return value.hashCode();
+ }
+
+ // convert in reverse
+ public String toString(X500Name name)
+ {
+ StringBuffer buf = new StringBuffer();
+ boolean first = true;
+
+ RDN[] rdns = name.getRDNs();
+
+ for (int i = rdns.length - 1; i >= 0; i--)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append(',');
+ }
+
+ IETFUtils.appendRDN(buf, rdns[i], DefaultSymbols);
+ }
+
+ return buf.toString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x500/style/X500NameTokenizer.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,107 @@
+package pdftk.org.bouncycastle.asn1.x500.style;
+
+/**
+ * class for breaking up an X500 Name into it's component tokens, ala
+ * java.util.StringTokenizer. We need this class as some of the
+ * lightweight Java environment don't support classes like
+ * StringTokenizer.
+ */
+class X500NameTokenizer
+{
+ private String value;
+ private int index;
+ private char separator;
+ private StringBuffer buf = new StringBuffer();
+
+ public X500NameTokenizer(
+ String oid)
+ {
+ this(oid, ',');
+ }
+
+ public X500NameTokenizer(
+ String oid,
+ char separator)
+ {
+ this.value = oid;
+ this.index = -1;
+ this.separator = separator;
+ }
+
+ public boolean hasMoreTokens()
+ {
+ return (index != value.length());
+ }
+
+ public String nextToken()
+ {
+ if (index == value.length())
+ {
+ return null;
+ }
+
+ int end = index + 1;
+ boolean quoted = false;
+ boolean escaped = false;
+
+ buf.setLength(0);
+
+ while (end != value.length())
+ {
+ char c = value.charAt(end);
+
+ if (c == '"')
+ {
+ if (!escaped)
+ {
+ quoted = !quoted;
+ }
+ else
+ {
+ if (c == '#' && buf.charAt(buf.length() - 1) == '=')
+ {
+ buf.append('\\');
+ }
+ else if (c == '+' && separator != '+')
+ {
+ buf.append('\\');
+ }
+ buf.append(c);
+ }
+ escaped = false;
+ }
+ else
+ {
+ if (escaped || quoted)
+ {
+ if (c == '#' && buf.charAt(buf.length() - 1) == '=')
+ {
+ buf.append('\\');
+ }
+ else if (c == '+' && separator != '+')
+ {
+ buf.append('\\');
+ }
+ buf.append(c);
+ escaped = false;
+ }
+ else if (c == '\\')
+ {
+ escaped = true;
+ }
+ else if (c == separator)
+ {
+ break;
+ }
+ else
+ {
+ buf.append(c);
+ }
+ }
+ end++;
+ }
+
+ index = end;
+ return buf.toString().trim();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AccessDescription.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AccessDescription.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AccessDescription.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AccessDescription.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,98 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * The AccessDescription object.
+ *
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName }
+ *
+ */
+public class AccessDescription
+ extends ASN1Object
+{
+ public final static ASN1ObjectIdentifier id_ad_caIssuers = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.2");
+
+ public final static ASN1ObjectIdentifier id_ad_ocsp = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.48.1");
+
+ ASN1ObjectIdentifier accessMethod = null;
+ GeneralName accessLocation = null;
+
+ public static AccessDescription getInstance(
+ Object obj)
+ {
+ if (obj instanceof AccessDescription)
+ {
+ return (AccessDescription)obj;
+ }
+ else if (obj != null)
+ {
+ return new AccessDescription(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private AccessDescription(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("wrong number of elements in sequence");
+ }
+
+ accessMethod = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ accessLocation = GeneralName.getInstance(seq.getObjectAt(1));
+ }
+
+ /**
+ * create an AccessDescription with the oid and location provided.
+ */
+ public AccessDescription(
+ ASN1ObjectIdentifier oid,
+ GeneralName location)
+ {
+ accessMethod = oid;
+ accessLocation = location;
+ }
+
+ /**
+ *
+ * @return the access method.
+ */
+ public ASN1ObjectIdentifier getAccessMethod()
+ {
+ return accessMethod;
+ }
+
+ /**
+ *
+ * @return the access location
+ */
+ public GeneralName getAccessLocation()
+ {
+ return accessLocation;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector accessDescription = new ASN1EncodableVector();
+
+ accessDescription.add(accessMethod);
+ accessDescription.add(accessLocation);
+
+ return new DERSequence(accessDescription);
+ }
+
+ public String toString()
+ {
+ return ("AccessDescription: Oid(" + this.accessMethod.getId() + ")");
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AlgorithmIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,173 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1SequenceParser;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERNull;
+import pdftk.org.bouncycastle.asn1.DERObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class AlgorithmIdentifier
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier objectId;
+ private ASN1Encodable parameters;
+ private boolean parametersDefined = false;
+
+ public static AlgorithmIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static AlgorithmIdentifier getInstance(
+ Object obj)
+ {
+ if (obj== null || obj instanceof AlgorithmIdentifier)
+ {
+ return (AlgorithmIdentifier)obj;
+ }
+
+ if (obj instanceof ASN1ObjectIdentifier)
+ {
+ return new AlgorithmIdentifier((ASN1ObjectIdentifier)obj);
+ }
+
+ if (obj instanceof String)
+ {
+ return new AlgorithmIdentifier((String)obj);
+ }
+
+ if (obj instanceof ASN1Sequence || obj instanceof ASN1SequenceParser)
+ {
+ return new AlgorithmIdentifier(ASN1Sequence.getInstance(obj));
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public AlgorithmIdentifier(
+ ASN1ObjectIdentifier objectId)
+ {
+ this.objectId = objectId;
+ }
+
+ /**
+ * @deprecated use ASN1ObjectIdentifier
+ * @param objectId
+ */
+ public AlgorithmIdentifier(
+ String objectId)
+ {
+ this.objectId = new ASN1ObjectIdentifier(objectId);
+ }
+
+ /**
+ * @deprecated use ASN1ObjectIdentifier
+ * @param objectId
+ */
+ public AlgorithmIdentifier(
+ DERObjectIdentifier objectId)
+ {
+ this.objectId = new ASN1ObjectIdentifier(objectId.getId());
+ }
+
+ /**
+ * @deprecated use ASN1ObjectIdentifier
+ * @param objectId
+ * @param parameters
+ */
+ public AlgorithmIdentifier(
+ DERObjectIdentifier objectId,
+ ASN1Encodable parameters)
+ {
+ parametersDefined = true;
+ this.objectId = new ASN1ObjectIdentifier(objectId.getId());
+ this.parameters = parameters;
+ }
+
+ public AlgorithmIdentifier(
+ ASN1ObjectIdentifier objectId,
+ ASN1Encodable parameters)
+ {
+ parametersDefined = true;
+ this.objectId = objectId;
+ this.parameters = parameters;
+ }
+
+ public AlgorithmIdentifier(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ objectId = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() == 2)
+ {
+ parametersDefined = true;
+ parameters = seq.getObjectAt(1);
+ }
+ else
+ {
+ parameters = null;
+ }
+ }
+
+ public ASN1ObjectIdentifier getAlgorithm()
+ {
+ return new ASN1ObjectIdentifier(objectId.getId());
+ }
+
+ /**
+ * @deprecated use getAlgorithm
+ * @return
+ */
+ public ASN1ObjectIdentifier getObjectId()
+ {
+ return objectId;
+ }
+
+ public ASN1Encodable getParameters()
+ {
+ return parameters;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(objectId);
+
+ if (parametersDefined)
+ {
+ if (parameters != null)
+ {
+ v.add(parameters);
+ }
+ else
+ {
+ v.add(DERNull.INSTANCE);
+ }
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AttCertIssuer.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AttCertIssuer.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AttCertIssuer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AttCertIssuer.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,91 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class AttCertIssuer
+ extends ASN1Object
+ implements ASN1Choice
+{
+ ASN1Encodable obj;
+ ASN1Primitive choiceObj;
+
+ public static AttCertIssuer getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof AttCertIssuer)
+ {
+ return (AttCertIssuer)obj;
+ }
+ else if (obj instanceof V2Form)
+ {
+ return new AttCertIssuer(V2Form.getInstance(obj));
+ }
+ else if (obj instanceof GeneralNames)
+ {
+ return new AttCertIssuer((GeneralNames)obj);
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new AttCertIssuer(V2Form.getInstance((ASN1TaggedObject)obj, false));
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new AttCertIssuer(GeneralNames.getInstance(obj));
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public static AttCertIssuer getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ /**
+ * Don't use this one if you are trying to be RFC 3281 compliant.
+ * Use it for v1 attribute certificates only.
+ *
+ * @param names our GeneralNames structure
+ */
+ public AttCertIssuer(
+ GeneralNames names)
+ {
+ obj = names;
+ choiceObj = obj.toASN1Primitive();
+ }
+
+ public AttCertIssuer(
+ V2Form v2Form)
+ {
+ obj = v2Form;
+ choiceObj = new DERTaggedObject(false, 0, obj);
+ }
+
+ public ASN1Encodable getIssuer()
+ {
+ return obj;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * AttCertIssuer ::= CHOICE {
+ * v1Form GeneralNames, -- MUST NOT be used in this
+ * -- profile
+ * v2Form [0] V2Form -- v2 only
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return choiceObj;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AttCertValidityPeriod.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AttCertValidityPeriod.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AttCertValidityPeriod.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AttCertValidityPeriod.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,84 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class AttCertValidityPeriod
+ extends ASN1Object
+{
+ ASN1GeneralizedTime notBeforeTime;
+ ASN1GeneralizedTime notAfterTime;
+
+ public static AttCertValidityPeriod getInstance(
+ Object obj)
+ {
+ if (obj instanceof AttCertValidityPeriod)
+ {
+ return (AttCertValidityPeriod)obj;
+ }
+ else if (obj != null)
+ {
+ return new AttCertValidityPeriod(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private AttCertValidityPeriod(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ notBeforeTime = ASN1GeneralizedTime.getInstance(seq.getObjectAt(0));
+ notAfterTime = ASN1GeneralizedTime.getInstance(seq.getObjectAt(1));
+ }
+
+ /**
+ * @param notBeforeTime
+ * @param notAfterTime
+ */
+ public AttCertValidityPeriod(
+ ASN1GeneralizedTime notBeforeTime,
+ ASN1GeneralizedTime notAfterTime)
+ {
+ this.notBeforeTime = notBeforeTime;
+ this.notAfterTime = notAfterTime;
+ }
+
+ public ASN1GeneralizedTime getNotBeforeTime()
+ {
+ return notBeforeTime;
+ }
+
+ public ASN1GeneralizedTime getNotAfterTime()
+ {
+ return notAfterTime;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * AttCertValidityPeriod ::= SEQUENCE {
+ * notBeforeTime GeneralizedTime,
+ * notAfterTime GeneralizedTime
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(notBeforeTime);
+ v.add(notAfterTime);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Attribute.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Attribute.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Attribute.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Attribute.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,93 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class Attribute
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier attrType;
+ private ASN1Set attrValues;
+
+ /**
+ * return an Attribute object from the given object.
+ *
+ * @param o the object we want converted.
+ * @exception IllegalArgumentException if the object cannot be converted.
+ */
+ public static Attribute getInstance(
+ Object o)
+ {
+ if (o instanceof Attribute)
+ {
+ return (Attribute)o;
+ }
+
+ if (o != null)
+ {
+ return new Attribute(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ private Attribute(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ attrType = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+ attrValues = ASN1Set.getInstance(seq.getObjectAt(1));
+ }
+
+ public Attribute(
+ ASN1ObjectIdentifier attrType,
+ ASN1Set attrValues)
+ {
+ this.attrType = attrType;
+ this.attrValues = attrValues;
+ }
+
+ public ASN1ObjectIdentifier getAttrType()
+ {
+ return new ASN1ObjectIdentifier(attrType.getId());
+ }
+
+ public ASN1Encodable[] getAttributeValues()
+ {
+ return attrValues.toArray();
+ }
+
+ public ASN1Set getAttrValues()
+ {
+ return attrValues;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Attribute ::= SEQUENCE {
+ * attrType OBJECT IDENTIFIER,
+ * attrValues SET OF AttributeValue
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(attrType);
+ v.add(attrValues);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AttributeCertificate.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AttributeCertificate.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AttributeCertificate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AttributeCertificate.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,94 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class AttributeCertificate
+ extends ASN1Object
+{
+ AttributeCertificateInfo acinfo;
+ AlgorithmIdentifier signatureAlgorithm;
+ DERBitString signatureValue;
+
+ /**
+ * @param obj
+ * @return an AttributeCertificate object
+ */
+ public static AttributeCertificate getInstance(Object obj)
+ {
+ if (obj instanceof AttributeCertificate)
+ {
+ return (AttributeCertificate)obj;
+ }
+ else if (obj != null)
+ {
+ return new AttributeCertificate(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public AttributeCertificate(
+ AttributeCertificateInfo acinfo,
+ AlgorithmIdentifier signatureAlgorithm,
+ DERBitString signatureValue)
+ {
+ this.acinfo = acinfo;
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.signatureValue = signatureValue;
+ }
+
+ public AttributeCertificate(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ this.acinfo = AttributeCertificateInfo.getInstance(seq.getObjectAt(0));
+ this.signatureAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ this.signatureValue = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+
+ public AttributeCertificateInfo getAcinfo()
+ {
+ return acinfo;
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return signatureAlgorithm;
+ }
+
+ public DERBitString getSignatureValue()
+ {
+ return signatureValue;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * AttributeCertificate ::= SEQUENCE {
+ * acinfo AttributeCertificateInfo,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(acinfo);
+ v.add(signatureAlgorithm);
+ v.add(signatureValue);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AttributeCertificateInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,166 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class AttributeCertificateInfo
+ extends ASN1Object
+{
+ private ASN1Integer version;
+ private Holder holder;
+ private AttCertIssuer issuer;
+ private AlgorithmIdentifier signature;
+ private ASN1Integer serialNumber;
+ private AttCertValidityPeriod attrCertValidityPeriod;
+ private ASN1Sequence attributes;
+ private DERBitString issuerUniqueID;
+ private Extensions extensions;
+
+ public static AttributeCertificateInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static AttributeCertificateInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof AttributeCertificateInfo)
+ {
+ return (AttributeCertificateInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new AttributeCertificateInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private AttributeCertificateInfo(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 7 || seq.size() > 9)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ this.version = ASN1Integer.getInstance(seq.getObjectAt(0));
+ this.holder = Holder.getInstance(seq.getObjectAt(1));
+ this.issuer = AttCertIssuer.getInstance(seq.getObjectAt(2));
+ this.signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(3));
+ this.serialNumber = ASN1Integer.getInstance(seq.getObjectAt(4));
+ this.attrCertValidityPeriod = AttCertValidityPeriod.getInstance(seq.getObjectAt(5));
+ this.attributes = ASN1Sequence.getInstance(seq.getObjectAt(6));
+
+ for (int i = 7; i < seq.size(); i++)
+ {
+ ASN1Encodable obj = (ASN1Encodable)seq.getObjectAt(i);
+
+ if (obj instanceof DERBitString)
+ {
+ this.issuerUniqueID = DERBitString.getInstance(seq.getObjectAt(i));
+ }
+ else if (obj instanceof ASN1Sequence || obj instanceof Extensions)
+ {
+ this.extensions = Extensions.getInstance(seq.getObjectAt(i));
+ }
+ }
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public Holder getHolder()
+ {
+ return holder;
+ }
+
+ public AttCertIssuer getIssuer()
+ {
+ return issuer;
+ }
+
+ public AlgorithmIdentifier getSignature()
+ {
+ return signature;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public AttCertValidityPeriod getAttrCertValidityPeriod()
+ {
+ return attrCertValidityPeriod;
+ }
+
+ public ASN1Sequence getAttributes()
+ {
+ return attributes;
+ }
+
+ public DERBitString getIssuerUniqueID()
+ {
+ return issuerUniqueID;
+ }
+
+ public Extensions getExtensions()
+ {
+ return extensions;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * AttributeCertificateInfo ::= SEQUENCE {
+ * version AttCertVersion -- version is v2,
+ * holder Holder,
+ * issuer AttCertIssuer,
+ * signature AlgorithmIdentifier,
+ * serialNumber CertificateSerialNumber,
+ * attrCertValidityPeriod AttCertValidityPeriod,
+ * attributes SEQUENCE OF Attribute,
+ * issuerUniqueID UniqueIdentifier OPTIONAL,
+ * extensions Extensions OPTIONAL
+ * }
+ *
+ * AttCertVersion ::= INTEGER { v2(1) }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(holder);
+ v.add(issuer);
+ v.add(signature);
+ v.add(serialNumber);
+ v.add(attrCertValidityPeriod);
+ v.add(attributes);
+
+ if (issuerUniqueID != null)
+ {
+ v.add(issuerUniqueID);
+ }
+
+ if (extensions != null)
+ {
+ v.add(extensions);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AuthorityInformationAccess.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AuthorityInformationAccess.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AuthorityInformationAccess.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AuthorityInformationAccess.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,101 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * The AuthorityInformationAccess object.
+ *
+ * id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
+ *
+ * AuthorityInfoAccessSyntax ::=
+ * SEQUENCE SIZE (1..MAX) OF AccessDescription
+ * AccessDescription ::= SEQUENCE {
+ * accessMethod OBJECT IDENTIFIER,
+ * accessLocation GeneralName }
+ *
+ * id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
+ * id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
+ * id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
+ *
+ */
+public class AuthorityInformationAccess
+ extends ASN1Object
+{
+ private AccessDescription[] descriptions;
+
+ public static AuthorityInformationAccess getInstance(
+ Object obj)
+ {
+ if (obj instanceof AuthorityInformationAccess)
+ {
+ return (AuthorityInformationAccess)obj;
+ }
+
+ if (obj != null)
+ {
+ return new AuthorityInformationAccess(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private AuthorityInformationAccess(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 1)
+ {
+ throw new IllegalArgumentException("sequence may not be empty");
+ }
+
+ descriptions = new AccessDescription[seq.size()];
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ descriptions[i] = AccessDescription.getInstance(seq.getObjectAt(i));
+ }
+ }
+
+ /**
+ * create an AuthorityInformationAccess with the oid and location provided.
+ */
+ public AuthorityInformationAccess(
+ ASN1ObjectIdentifier oid,
+ GeneralName location)
+ {
+ descriptions = new AccessDescription[1];
+
+ descriptions[0] = new AccessDescription(oid, location);
+ }
+
+
+ /**
+ *
+ * @return the access descriptions contained in this object.
+ */
+ public AccessDescription[] getAccessDescriptions()
+ {
+ return descriptions;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+
+ for (int i = 0; i != descriptions.length; i++)
+ {
+ vec.add(descriptions[i]);
+ }
+
+ return new DERSequence(vec);
+ }
+
+ public String toString()
+ {
+ return ("AuthorityInformationAccess: Oid(" + this.descriptions[0].getAccessMethod().getId() + ")");
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/AuthorityKeyIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,232 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+
+/**
+ * The AuthorityKeyIdentifier object.
+ *
+ * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
+ *
+ * AuthorityKeyIdentifier ::= SEQUENCE {
+ * keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL,
+ * authorityCertIssuer [1] IMPLICIT GeneralNames OPTIONAL,
+ * authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL }
+ *
+ * KeyIdentifier ::= OCTET STRING
+ *
+ *
+ */
+public class AuthorityKeyIdentifier
+ extends ASN1Object
+{
+ ASN1OctetString keyidentifier=null;
+ GeneralNames certissuer=null;
+ ASN1Integer certserno=null;
+
+ public static AuthorityKeyIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static AuthorityKeyIdentifier getInstance(
+ Object obj)
+ {
+ if (obj instanceof AuthorityKeyIdentifier)
+ {
+ return (AuthorityKeyIdentifier)obj;
+ }
+ if (obj != null)
+ {
+ return new AuthorityKeyIdentifier(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static AuthorityKeyIdentifier fromExtensions(Extensions extensions)
+ {
+ return AuthorityKeyIdentifier.getInstance(extensions.getExtensionParsedValue(Extension.authorityKeyIdentifier));
+ }
+
+ protected AuthorityKeyIdentifier(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1TaggedObject o = DERTaggedObject.getInstance(e.nextElement());
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ this.keyidentifier = ASN1OctetString.getInstance(o, false);
+ break;
+ case 1:
+ this.certissuer = GeneralNames.getInstance(o, false);
+ break;
+ case 2:
+ this.certserno = ASN1Integer.getInstance(o, false);
+ break;
+ default:
+ throw new IllegalArgumentException("illegal tag");
+ }
+ }
+ }
+
+ /**
+ *
+ * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
+ * from SubjectPublicKeyInfo as defined in RFC2459.
+ *
+ * Example of making a AuthorityKeyIdentifier:
+ *
+ * SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
+ * publicKey.getEncoded()).readObject());
+ * AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
+ *
+ *
+ **/
+ public AuthorityKeyIdentifier(
+ SubjectPublicKeyInfo spki)
+ {
+ Digest digest = new SHA1Digest();
+ byte[] resBuf = new byte[digest.getDigestSize()];
+
+ byte[] bytes = spki.getPublicKeyData().getBytes();
+ digest.update(bytes, 0, bytes.length);
+ digest.doFinal(resBuf, 0);
+ this.keyidentifier = new DEROctetString(resBuf);
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with the GeneralNames tag and
+ * the serial number provided as well.
+ */
+ public AuthorityKeyIdentifier(
+ SubjectPublicKeyInfo spki,
+ GeneralNames name,
+ BigInteger serialNumber)
+ {
+ Digest digest = new SHA1Digest();
+ byte[] resBuf = new byte[digest.getDigestSize()];
+
+ byte[] bytes = spki.getPublicKeyData().getBytes();
+ digest.update(bytes, 0, bytes.length);
+ digest.doFinal(resBuf, 0);
+
+ this.keyidentifier = new DEROctetString(resBuf);
+ this.certissuer = GeneralNames.getInstance(name.toASN1Primitive());
+ this.certserno = new ASN1Integer(serialNumber);
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with the GeneralNames tag and
+ * the serial number provided.
+ */
+ public AuthorityKeyIdentifier(
+ GeneralNames name,
+ BigInteger serialNumber)
+ {
+ this.keyidentifier = null;
+ this.certissuer = GeneralNames.getInstance(name.toASN1Primitive());
+ this.certserno = new ASN1Integer(serialNumber);
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with a precomupted key identifier
+ */
+ public AuthorityKeyIdentifier(
+ byte[] keyIdentifier)
+ {
+ this.keyidentifier = new DEROctetString(keyIdentifier);
+ this.certissuer = null;
+ this.certserno = null;
+ }
+
+ /**
+ * create an AuthorityKeyIdentifier with a precomupted key identifier
+ * and the GeneralNames tag and the serial number provided as well.
+ */
+ public AuthorityKeyIdentifier(
+ byte[] keyIdentifier,
+ GeneralNames name,
+ BigInteger serialNumber)
+ {
+ this.keyidentifier = new DEROctetString(keyIdentifier);
+ this.certissuer = GeneralNames.getInstance(name.toASN1Primitive());
+ this.certserno = new ASN1Integer(serialNumber);
+ }
+
+ public byte[] getKeyIdentifier()
+ {
+ if (keyidentifier != null)
+ {
+ return keyidentifier.getOctets();
+ }
+
+ return null;
+ }
+
+ public GeneralNames getAuthorityCertIssuer()
+ {
+ return certissuer;
+ }
+
+ public BigInteger getAuthorityCertSerialNumber()
+ {
+ if (certserno != null)
+ {
+ return certserno.getValue();
+ }
+
+ return null;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (keyidentifier != null)
+ {
+ v.add(new DERTaggedObject(false, 0, keyidentifier));
+ }
+
+ if (certissuer != null)
+ {
+ v.add(new DERTaggedObject(false, 1, certissuer));
+ }
+
+ if (certserno != null)
+ {
+ v.add(new DERTaggedObject(false, 2, certserno));
+ }
+
+
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.getOctets() + ")");
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/BasicConstraints.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/BasicConstraints.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/BasicConstraints.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/BasicConstraints.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,164 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1Boolean;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBoolean;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class BasicConstraints
+ extends ASN1Object
+{
+ ASN1Boolean cA = ASN1Boolean.getInstance(false);
+ ASN1Integer pathLenConstraint = null;
+
+ public static BasicConstraints getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static BasicConstraints getInstance(
+ Object obj)
+ {
+ if (obj instanceof BasicConstraints)
+ {
+ return (BasicConstraints)obj;
+ }
+ if (obj instanceof X509Extension)
+ {
+ return getInstance(X509Extension.convertValueToObject((X509Extension)obj));
+ }
+ if (obj != null)
+ {
+ return new BasicConstraints(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static BasicConstraints fromExtensions(Extensions extensions)
+ {
+ return BasicConstraints.getInstance(extensions.getExtensionParsedValue(Extension.basicConstraints));
+ }
+
+ private BasicConstraints(
+ ASN1Sequence seq)
+ {
+ if (seq.size() == 0)
+ {
+ this.cA = null;
+ this.pathLenConstraint = null;
+ }
+ else
+ {
+ if (seq.getObjectAt(0) instanceof DERBoolean)
+ {
+ this.cA = DERBoolean.getInstance(seq.getObjectAt(0));
+ }
+ else
+ {
+ this.cA = null;
+ this.pathLenConstraint = ASN1Integer.getInstance(seq.getObjectAt(0));
+ }
+ if (seq.size() > 1)
+ {
+ if (this.cA != null)
+ {
+ this.pathLenConstraint = ASN1Integer.getInstance(seq.getObjectAt(1));
+ }
+ else
+ {
+ throw new IllegalArgumentException("wrong sequence in constructor");
+ }
+ }
+ }
+ }
+
+ public BasicConstraints(
+ boolean cA)
+ {
+ if (cA)
+ {
+ this.cA = ASN1Boolean.getInstance(true);
+ }
+ else
+ {
+ this.cA = null;
+ }
+ this.pathLenConstraint = null;
+ }
+
+ /**
+ * create a cA=true object for the given path length constraint.
+ *
+ * @param pathLenConstraint
+ */
+ public BasicConstraints(
+ int pathLenConstraint)
+ {
+ this.cA = ASN1Boolean.getInstance(true);
+ this.pathLenConstraint = new ASN1Integer(pathLenConstraint);
+ }
+
+ public boolean isCA()
+ {
+ return (cA != null) && cA.isTrue();
+ }
+
+ public BigInteger getPathLenConstraint()
+ {
+ if (pathLenConstraint != null)
+ {
+ return pathLenConstraint.getValue();
+ }
+
+ return null;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * BasicConstraints := SEQUENCE {
+ * cA BOOLEAN DEFAULT FALSE,
+ * pathLenConstraint INTEGER (0..MAX) OPTIONAL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (cA != null)
+ {
+ v.add(cA);
+ }
+
+ if (pathLenConstraint != null) // yes some people actually do this when cA is false...
+ {
+ v.add(pathLenConstraint);
+ }
+
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ if (pathLenConstraint == null)
+ {
+ if (cA == null)
+ {
+ return "BasicConstraints: isCa(false)";
+ }
+ return "BasicConstraints: isCa(" + this.isCA() + ")";
+ }
+ return "BasicConstraints: isCa(" + this.isCA() + "), pathLenConstraint = " + pathLenConstraint.getValue();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CRLDistPoint.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CRLDistPoint.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CRLDistPoint.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CRLDistPoint.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,100 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class CRLDistPoint
+ extends ASN1Object
+{
+ ASN1Sequence seq = null;
+
+ public static CRLDistPoint getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static CRLDistPoint getInstance(
+ Object obj)
+ {
+ if (obj instanceof CRLDistPoint)
+ {
+ return (CRLDistPoint)obj;
+ }
+ else if (obj != null)
+ {
+ return new CRLDistPoint(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private CRLDistPoint(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+ }
+
+ public CRLDistPoint(
+ DistributionPoint[] points)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != points.length; i++)
+ {
+ v.add(points[i]);
+ }
+
+ seq = new DERSequence(v);
+ }
+
+ /**
+ * Return the distribution points making up the sequence.
+ *
+ * @return DistributionPoint[]
+ */
+ public DistributionPoint[] getDistributionPoints()
+ {
+ DistributionPoint[] dp = new DistributionPoint[seq.size()];
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ dp[i] = DistributionPoint.getInstance(seq.getObjectAt(i));
+ }
+
+ return dp;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * CRLDistPoint ::= SEQUENCE SIZE {1..MAX} OF DistributionPoint
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ String sep = System.getProperty("line.separator");
+
+ buf.append("CRLDistPoint:");
+ buf.append(sep);
+ DistributionPoint dp[] = getDistributionPoints();
+ for (int i = 0; i != dp.length; i++)
+ {
+ buf.append(" ");
+ buf.append(dp[i]);
+ buf.append(sep);
+ }
+ return buf.toString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CRLNumber.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CRLNumber.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CRLNumber.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CRLNumber.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,54 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+
+/**
+ * The CRLNumber object.
+ *
+ * CRLNumber::= INTEGER(0..MAX)
+ *
+ */
+public class CRLNumber
+ extends ASN1Object
+{
+ private BigInteger number;
+
+ public CRLNumber(
+ BigInteger number)
+ {
+ this.number = number;
+ }
+
+ public BigInteger getCRLNumber()
+ {
+ return number;
+ }
+
+ public String toString()
+ {
+ return "CRLNumber: " + getCRLNumber();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new ASN1Integer(number);
+ }
+
+ public static CRLNumber getInstance(Object o)
+ {
+ if (o instanceof CRLNumber)
+ {
+ return (CRLNumber)o;
+ }
+ else if (o != null)
+ {
+ return new CRLNumber(ASN1Integer.getInstance(o).getValue());
+ }
+
+ return null;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CRLReason.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CRLReason.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CRLReason.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CRLReason.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,151 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.math.BigInteger;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.asn1.ASN1Enumerated;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.util.Integers;
+
+/**
+ * The CRLReason enumeration.
+ *
+ * CRLReason ::= ENUMERATED {
+ * unspecified (0),
+ * keyCompromise (1),
+ * cACompromise (2),
+ * affiliationChanged (3),
+ * superseded (4),
+ * cessationOfOperation (5),
+ * certificateHold (6),
+ * removeFromCRL (8),
+ * privilegeWithdrawn (9),
+ * aACompromise (10)
+ * }
+ *
+ */
+public class CRLReason
+ extends ASN1Object
+{
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int UNSPECIFIED = 0;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int KEY_COMPROMISE = 1;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int CA_COMPROMISE = 2;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int AFFILIATION_CHANGED = 3;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int SUPERSEDED = 4;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int CESSATION_OF_OPERATION = 5;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int CERTIFICATE_HOLD = 6;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int REMOVE_FROM_CRL = 8;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int PRIVILEGE_WITHDRAWN = 9;
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int AA_COMPROMISE = 10;
+
+ public static final int unspecified = 0;
+ public static final int keyCompromise = 1;
+ public static final int cACompromise = 2;
+ public static final int affiliationChanged = 3;
+ public static final int superseded = 4;
+ public static final int cessationOfOperation = 5;
+ public static final int certificateHold = 6;
+ // 7 -> unknown
+ public static final int removeFromCRL = 8;
+ public static final int privilegeWithdrawn = 9;
+ public static final int aACompromise = 10;
+
+ private static final String[] reasonString =
+ {
+ "unspecified", "keyCompromise", "cACompromise", "affiliationChanged",
+ "superseded", "cessationOfOperation", "certificateHold", "unknown",
+ "removeFromCRL", "privilegeWithdrawn", "aACompromise"
+ };
+
+ private static final Hashtable table = new Hashtable();
+
+ private ASN1Enumerated value;
+
+ public static CRLReason getInstance(Object o)
+ {
+ if (o instanceof CRLReason)
+ {
+ return (CRLReason)o;
+ }
+ else if (o != null)
+ {
+ return lookup(ASN1Enumerated.getInstance(o).getValue().intValue());
+ }
+
+ return null;
+ }
+
+ private CRLReason(
+ int reason)
+ {
+ value = new ASN1Enumerated(reason);
+ }
+
+ public String toString()
+ {
+ String str;
+ int reason = getValue().intValue();
+ if (reason < 0 || reason > 10)
+ {
+ str = "invalid";
+ }
+ else
+ {
+ str = reasonString[reason];
+ }
+ return "CRLReason: " + str;
+ }
+
+ public BigInteger getValue()
+ {
+ return value.getValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return value;
+ }
+
+ public static CRLReason lookup(int value)
+ {
+ Integer idx = Integers.valueOf(value);
+
+ if (!table.containsKey(idx))
+ {
+ table.put(idx, new CRLReason(value));
+ }
+
+ return (CRLReason)table.get(idx);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CertPolicyId.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CertPolicyId.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CertPolicyId.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CertPolicyId.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,57 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+
+
+/**
+ * CertPolicyId, used in the CertificatePolicies and PolicyMappings
+ * X509V3 Extensions.
+ *
+ *
+ * CertPolicyId ::= OBJECT IDENTIFIER
+ *
+ */
+/**
+ * CertPolicyId, used in the CertificatePolicies and PolicyMappings
+ * X509V3 Extensions.
+ *
+ *
+ * CertPolicyId ::= OBJECT IDENTIFIER
+ *
+ */
+public class CertPolicyId
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier id;
+
+ private CertPolicyId(ASN1ObjectIdentifier id)
+ {
+ this.id = id;
+ }
+
+ public static CertPolicyId getInstance(Object o)
+ {
+ if (o instanceof CertPolicyId)
+ {
+ return (CertPolicyId)o;
+ }
+ else if (o != null)
+ {
+ return new CertPolicyId(ASN1ObjectIdentifier.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public String getId()
+ {
+ return id.getId();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return id;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Certificate.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Certificate.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Certificate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Certificate.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,131 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+
+/**
+ * an X509Certificate structure.
+ *
+ * Certificate ::= SEQUENCE {
+ * tbsCertificate TBSCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING
+ * }
+ *
+ */
+public class Certificate
+ extends ASN1Object
+{
+ ASN1Sequence seq;
+ TBSCertificate tbsCert;
+ AlgorithmIdentifier sigAlgId;
+ DERBitString sig;
+
+ public static Certificate getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static Certificate getInstance(
+ Object obj)
+ {
+ if (obj instanceof Certificate)
+ {
+ return (Certificate)obj;
+ }
+ else if (obj != null)
+ {
+ return new Certificate(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private Certificate(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+
+ //
+ // correct x509 certficate
+ //
+ if (seq.size() == 3)
+ {
+ tbsCert = TBSCertificate.getInstance(seq.getObjectAt(0));
+ sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+
+ sig = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+ else
+ {
+ throw new IllegalArgumentException("sequence wrong size for a certificate");
+ }
+ }
+
+ public TBSCertificate getTBSCertificate()
+ {
+ return tbsCert;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return tbsCert.getVersion();
+ }
+
+ public int getVersionNumber()
+ {
+ return tbsCert.getVersionNumber();
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return tbsCert.getSerialNumber();
+ }
+
+ public X500Name getIssuer()
+ {
+ return tbsCert.getIssuer();
+ }
+
+ public Time getStartDate()
+ {
+ return tbsCert.getStartDate();
+ }
+
+ public Time getEndDate()
+ {
+ return tbsCert.getEndDate();
+ }
+
+ public X500Name getSubject()
+ {
+ return tbsCert.getSubject();
+ }
+
+ public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
+ {
+ return tbsCert.getSubjectPublicKeyInfo();
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return sigAlgId;
+ }
+
+ public DERBitString getSignature()
+ {
+ return sig;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CertificateList.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CertificateList.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CertificateList.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CertificateList.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,127 @@
+
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+
+/**
+ * PKIX RFC-2459
+ *
+ * The X.509 v2 CRL syntax is as follows. For signature calculation,
+ * the data that is to be signed is ASN.1 DER encoded.
+ *
+ *
+ * CertificateList ::= SEQUENCE {
+ * tbsCertList TBSCertList,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signatureValue BIT STRING }
+ *
+ */
+public class CertificateList
+ extends ASN1Object
+{
+ TBSCertList tbsCertList;
+ AlgorithmIdentifier sigAlgId;
+ DERBitString sig;
+
+ public static CertificateList getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static CertificateList getInstance(
+ Object obj)
+ {
+ if (obj instanceof CertificateList)
+ {
+ return (CertificateList)obj;
+ }
+ else if (obj != null)
+ {
+ return new CertificateList(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public CertificateList(
+ ASN1Sequence seq)
+ {
+ if (seq.size() == 3)
+ {
+ tbsCertList = TBSCertList.getInstance(seq.getObjectAt(0));
+ sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+ sig = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+ else
+ {
+ throw new IllegalArgumentException("sequence wrong size for CertificateList");
+ }
+ }
+
+ public TBSCertList getTBSCertList()
+ {
+ return tbsCertList;
+ }
+
+ public TBSCertList.CRLEntry[] getRevokedCertificates()
+ {
+ return tbsCertList.getRevokedCertificates();
+ }
+
+ public Enumeration getRevokedCertificateEnumeration()
+ {
+ return tbsCertList.getRevokedCertificateEnumeration();
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return sigAlgId;
+ }
+
+ public DERBitString getSignature()
+ {
+ return sig;
+ }
+
+ public int getVersionNumber()
+ {
+ return tbsCertList.getVersionNumber();
+ }
+
+ public X500Name getIssuer()
+ {
+ return tbsCertList.getIssuer();
+ }
+
+ public Time getThisUpdate()
+ {
+ return tbsCertList.getThisUpdate();
+ }
+
+ public Time getNextUpdate()
+ {
+ return tbsCertList.getNextUpdate();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(tbsCertList);
+ v.add(sigAlgId);
+ v.add(sig);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CertificatePair.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CertificatePair.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CertificatePair.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CertificatePair.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,169 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * This class helps to support crossCerfificatePairs in a LDAP directory
+ * according RFC 2587
+ *
+ *
+ * crossCertificatePairATTRIBUTE::={
+ * WITH SYNTAX CertificatePair
+ * EQUALITY MATCHING RULE certificatePairExactMatch
+ * ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
+ *
+ *
+ * The forward elements of the crossCertificatePair attribute of a
+ * CA's directory entry shall be used to store all, except self-issued
+ * certificates issued to this CA. Optionally, the reverse elements of the
+ * crossCertificatePair attribute, of a CA's directory entry may contain a
+ * subset of certificates issued by this CA to other CAs. When both the forward
+ * and the reverse elements are present in a single attribute value, issuer name
+ * in one certificate shall match the subject name in the other and vice versa,
+ * and the subject public key in one certificate shall be capable of verifying
+ * the digital signature on the other certificate and vice versa.
+ *
+ * When a reverse element is present, the forward element value and the reverse
+ * element value need not be stored in the same attribute value; in other words,
+ * they can be stored in either a single attribute value or two attribute
+ * values.
+ *
+ *
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL,
+ * -- at least one of the pair shall be present -- }
+ *
+ */
+public class CertificatePair
+ extends ASN1Object
+{
+ private Certificate forward;
+
+ private Certificate reverse;
+
+ public static CertificatePair getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof CertificatePair)
+ {
+ return (CertificatePair)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new CertificatePair((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * The sequence is of type CertificatePair:
+ *
+ *
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL,
+ * -- at least one of the pair shall be present -- }
+ *
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private CertificatePair(ASN1Sequence seq)
+ {
+ if (seq.size() != 1 && seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
+ if (o.getTagNo() == 0)
+ {
+ forward = Certificate.getInstance(o, true);
+ }
+ else if (o.getTagNo() == 1)
+ {
+ reverse = Certificate.getInstance(o, true);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad tag number: "
+ + o.getTagNo());
+ }
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param forward Certificates issued to this CA.
+ * @param reverse Certificates issued by this CA to other CAs.
+ */
+ public CertificatePair(Certificate forward, Certificate reverse)
+ {
+ this.forward = forward;
+ this.reverse = reverse;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * CertificatePair ::= SEQUENCE {
+ * forward [0] Certificate OPTIONAL,
+ * reverse [1] Certificate OPTIONAL,
+ * -- at least one of the pair shall be present -- }
+ *
+ *
+ * @return a ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+
+ if (forward != null)
+ {
+ vec.add(new DERTaggedObject(0, forward));
+ }
+ if (reverse != null)
+ {
+ vec.add(new DERTaggedObject(1, reverse));
+ }
+
+ return new DERSequence(vec);
+ }
+
+ /**
+ * @return Returns the forward.
+ */
+ public Certificate getForward()
+ {
+ return forward;
+ }
+
+ /**
+ * @return Returns the reverse.
+ */
+ public Certificate getReverse()
+ {
+ return reverse;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CertificatePolicies.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CertificatePolicies.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/CertificatePolicies.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/CertificatePolicies.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,99 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class CertificatePolicies
+ extends ASN1Object
+{
+ private final PolicyInformation[] policyInformation;
+
+ public static CertificatePolicies getInstance(
+ Object obj)
+ {
+ if (obj instanceof CertificatePolicies)
+ {
+ return (CertificatePolicies)obj;
+ }
+
+ if (obj != null)
+ {
+ return new CertificatePolicies(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static CertificatePolicies getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Construct a CertificatePolicies object containing one PolicyInformation.
+ *
+ * @param name the name to be contained.
+ */
+ public CertificatePolicies(
+ PolicyInformation name)
+ {
+ this.policyInformation = new PolicyInformation[] { name };
+ }
+
+ public CertificatePolicies(
+ PolicyInformation[] policyInformation)
+ {
+ this.policyInformation = policyInformation;
+ }
+
+ private CertificatePolicies(
+ ASN1Sequence seq)
+ {
+ this.policyInformation = new PolicyInformation[seq.size()];
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ policyInformation[i] = PolicyInformation.getInstance(seq.getObjectAt(i));
+ }
+ }
+
+ public PolicyInformation[] getPolicyInformation()
+ {
+ PolicyInformation[] tmp = new PolicyInformation[policyInformation.length];
+
+ System.arraycopy(policyInformation, 0, tmp, 0, policyInformation.length);
+
+ return tmp;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * CertificatePolicies ::= SEQUENCE SIZE {1..MAX} OF PolicyInformation
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERSequence(policyInformation);
+ }
+
+ public String toString()
+ {
+ String p = null;
+ for (int i = 0; i < policyInformation.length; i++)
+ {
+ if (p != null)
+ {
+ p += ", ";
+ }
+ p += policyInformation[i];
+ }
+
+ return "CertificatePolicies: " + p;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/DSAParameter.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/DSAParameter.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/DSAParameter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/DSAParameter.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,92 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class DSAParameter
+ extends ASN1Object
+{
+ ASN1Integer p, q, g;
+
+ public static DSAParameter getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static DSAParameter getInstance(
+ Object obj)
+ {
+ if (obj instanceof DSAParameter)
+ {
+ return (DSAParameter)obj;
+ }
+
+ if(obj != null)
+ {
+ return new DSAParameter(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public DSAParameter(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g)
+ {
+ this.p = new ASN1Integer(p);
+ this.q = new ASN1Integer(q);
+ this.g = new ASN1Integer(g);
+ }
+
+ private DSAParameter(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ p = ASN1Integer.getInstance(e.nextElement());
+ q = ASN1Integer.getInstance(e.nextElement());
+ g = ASN1Integer.getInstance(e.nextElement());
+ }
+
+ public BigInteger getP()
+ {
+ return p.getPositiveValue();
+ }
+
+ public BigInteger getQ()
+ {
+ return q.getPositiveValue();
+ }
+
+ public BigInteger getG()
+ {
+ return g.getPositiveValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(p);
+ v.add(q);
+ v.add(g);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/DigestInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/DigestInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/DigestInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/DigestInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,86 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * The DigestInfo object.
+ *
+ * DigestInfo::=SEQUENCE{
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING }
+ *
+ */
+public class DigestInfo
+ extends ASN1Object
+{
+ private byte[] digest;
+ private AlgorithmIdentifier algId;
+
+ public static DigestInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static DigestInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof DigestInfo)
+ {
+ return (DigestInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new DigestInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public DigestInfo(
+ AlgorithmIdentifier algId,
+ byte[] digest)
+ {
+ this.digest = digest;
+ this.algId = algId;
+ }
+
+ public DigestInfo(
+ ASN1Sequence obj)
+ {
+ Enumeration e = obj.getObjects();
+
+ algId = AlgorithmIdentifier.getInstance(e.nextElement());
+ digest = ASN1OctetString.getInstance(e.nextElement()).getOctets();
+ }
+
+ public AlgorithmIdentifier getAlgorithmId()
+ {
+ return algId;
+ }
+
+ public byte[] getDigest()
+ {
+ return digest;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(algId);
+ v.add(new DEROctetString(digest));
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/DisplayText.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/DisplayText.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/DisplayText.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/DisplayText.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,165 @@
+
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1String;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBMPString;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+import pdftk.org.bouncycastle.asn1.DERUTF8String;
+import pdftk.org.bouncycastle.asn1.DERVisibleString;
+
+/**
+ * DisplayText
class, used in
+ * CertificatePolicies
X509 V3 extensions (in policy qualifiers).
+ *
+ * It stores a string in a chosen encoding.
+ *
+ * DisplayText ::= CHOICE {
+ * ia5String IA5String (SIZE (1..200)),
+ * visibleString VisibleString (SIZE (1..200)),
+ * bmpString BMPString (SIZE (1..200)),
+ * utf8String UTF8String (SIZE (1..200)) }
+ *
+ * @see PolicyQualifierInfo
+ * @see PolicyInformation
+ */
+public class DisplayText
+ extends ASN1Object
+ implements ASN1Choice
+{
+ /**
+ * Constant corresponding to ia5String encoding.
+ *
+ */
+ public static final int CONTENT_TYPE_IA5STRING = 0;
+ /**
+ * Constant corresponding to bmpString encoding.
+ *
+ */
+ public static final int CONTENT_TYPE_BMPSTRING = 1;
+ /**
+ * Constant corresponding to utf8String encoding.
+ *
+ */
+ public static final int CONTENT_TYPE_UTF8STRING = 2;
+ /**
+ * Constant corresponding to visibleString encoding.
+ *
+ */
+ public static final int CONTENT_TYPE_VISIBLESTRING = 3;
+
+ /**
+ * Describe constant DISPLAY_TEXT_MAXIMUM_SIZE
here.
+ *
+ */
+ public static final int DISPLAY_TEXT_MAXIMUM_SIZE = 200;
+
+ int contentType;
+ ASN1String contents;
+
+ /**
+ * Creates a new DisplayText
instance.
+ *
+ * @param type the desired encoding type for the text.
+ * @param text the text to store. Strings longer than 200
+ * characters are truncated.
+ */
+ public DisplayText(int type, String text)
+ {
+ if (text.length() > DISPLAY_TEXT_MAXIMUM_SIZE)
+ {
+ // RFC3280 limits these strings to 200 chars
+ // truncate the string
+ text = text.substring (0, DISPLAY_TEXT_MAXIMUM_SIZE);
+ }
+
+ contentType = type;
+ switch (type)
+ {
+ case CONTENT_TYPE_IA5STRING:
+ contents = new DERIA5String(text);
+ break;
+ case CONTENT_TYPE_UTF8STRING:
+ contents = new DERUTF8String(text);
+ break;
+ case CONTENT_TYPE_VISIBLESTRING:
+ contents = new DERVisibleString(text);
+ break;
+ case CONTENT_TYPE_BMPSTRING:
+ contents = new DERBMPString(text);
+ break;
+ default:
+ contents = new DERUTF8String(text);
+ break;
+ }
+ }
+
+ /**
+ * Creates a new DisplayText
instance.
+ *
+ * @param text the text to encapsulate. Strings longer than 200
+ * characters are truncated.
+ */
+ public DisplayText(String text)
+ {
+ // by default use UTF8String
+ if (text.length() > DISPLAY_TEXT_MAXIMUM_SIZE)
+ {
+ text = text.substring(0, DISPLAY_TEXT_MAXIMUM_SIZE);
+ }
+
+ contentType = CONTENT_TYPE_UTF8STRING;
+ contents = new DERUTF8String(text);
+ }
+
+ /**
+ * Creates a new DisplayText
instance.
+ * Useful when reading back a DisplayText
class
+ * from it's ASN1Encodable/DEREncodable form.
+ *
+ * @param de a DEREncodable
instance.
+ */
+ private DisplayText(ASN1String de)
+ {
+ contents = de;
+ }
+
+ public static DisplayText getInstance(Object obj)
+ {
+ if (obj instanceof ASN1String)
+ {
+ return new DisplayText((ASN1String)obj);
+ }
+ else if (obj == null || obj instanceof DisplayText)
+ {
+ return (DisplayText)obj;
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ public static DisplayText getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return (ASN1Primitive)contents;
+ }
+
+ /**
+ * Returns the stored String
object.
+ *
+ * @return the stored text as a String
.
+ */
+ public String getString()
+ {
+ return contents.getString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/DistributionPoint.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/DistributionPoint.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/DistributionPoint.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/DistributionPoint.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,158 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * The DistributionPoint object.
+ *
+ * DistributionPoint ::= SEQUENCE {
+ * distributionPoint [0] DistributionPointName OPTIONAL,
+ * reasons [1] ReasonFlags OPTIONAL,
+ * cRLIssuer [2] GeneralNames OPTIONAL
+ * }
+ *
+ */
+public class DistributionPoint
+ extends ASN1Object
+{
+ DistributionPointName distributionPoint;
+ ReasonFlags reasons;
+ GeneralNames cRLIssuer;
+
+ public static DistributionPoint getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static DistributionPoint getInstance(
+ Object obj)
+ {
+ if(obj == null || obj instanceof DistributionPoint)
+ {
+ return (DistributionPoint)obj;
+ }
+
+ if(obj instanceof ASN1Sequence)
+ {
+ return new DistributionPoint((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid DistributionPoint: " + obj.getClass().getName());
+ }
+
+ public DistributionPoint(
+ ASN1Sequence seq)
+ {
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject t = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
+ switch (t.getTagNo())
+ {
+ case 0:
+ distributionPoint = DistributionPointName.getInstance(t, true);
+ break;
+ case 1:
+ reasons = new ReasonFlags(DERBitString.getInstance(t, false));
+ break;
+ case 2:
+ cRLIssuer = GeneralNames.getInstance(t, false);
+ }
+ }
+ }
+
+ public DistributionPoint(
+ DistributionPointName distributionPoint,
+ ReasonFlags reasons,
+ GeneralNames cRLIssuer)
+ {
+ this.distributionPoint = distributionPoint;
+ this.reasons = reasons;
+ this.cRLIssuer = cRLIssuer;
+ }
+
+ public DistributionPointName getDistributionPoint()
+ {
+ return distributionPoint;
+ }
+
+ public ReasonFlags getReasons()
+ {
+ return reasons;
+ }
+
+ public GeneralNames getCRLIssuer()
+ {
+ return cRLIssuer;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (distributionPoint != null)
+ {
+ //
+ // as this is a CHOICE it must be explicitly tagged
+ //
+ v.add(new DERTaggedObject(0, distributionPoint));
+ }
+
+ if (reasons != null)
+ {
+ v.add(new DERTaggedObject(false, 1, reasons));
+ }
+
+ if (cRLIssuer != null)
+ {
+ v.add(new DERTaggedObject(false, 2, cRLIssuer));
+ }
+
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ String sep = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+ buf.append("DistributionPoint: [");
+ buf.append(sep);
+ if (distributionPoint != null)
+ {
+ appendObject(buf, sep, "distributionPoint", distributionPoint.toString());
+ }
+ if (reasons != null)
+ {
+ appendObject(buf, sep, "reasons", reasons.toString());
+ }
+ if (cRLIssuer != null)
+ {
+ appendObject(buf, sep, "cRLIssuer", cRLIssuer.toString());
+ }
+ buf.append("]");
+ buf.append(sep);
+ return buf.toString();
+ }
+
+ private void appendObject(StringBuffer buf, String sep, String name, String value)
+ {
+ String indent = " ";
+
+ buf.append(indent);
+ buf.append(name);
+ buf.append(":");
+ buf.append(sep);
+ buf.append(indent);
+ buf.append(indent);
+ buf.append(value);
+ buf.append(sep);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/DistributionPointName.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/DistributionPointName.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/DistributionPointName.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/DistributionPointName.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,138 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * The DistributionPointName object.
+ *
+ * DistributionPointName ::= CHOICE {
+ * fullName [0] GeneralNames,
+ * nameRelativeToCRLIssuer [1] RDN
+ * }
+ *
+ */
+public class DistributionPointName
+ extends ASN1Object
+ implements ASN1Choice
+{
+ ASN1Encodable name;
+ int type;
+
+ public static final int FULL_NAME = 0;
+ public static final int NAME_RELATIVE_TO_CRL_ISSUER = 1;
+
+ public static DistributionPointName getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1TaggedObject.getInstance(obj, true));
+ }
+
+ public static DistributionPointName getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof DistributionPointName)
+ {
+ return (DistributionPointName)obj;
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new DistributionPointName((ASN1TaggedObject)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public DistributionPointName(
+ int type,
+ ASN1Encodable name)
+ {
+ this.type = type;
+ this.name = name;
+ }
+
+ public DistributionPointName(
+ GeneralNames name)
+ {
+ this(FULL_NAME, name);
+ }
+
+ /**
+ * Return the tag number applying to the underlying choice.
+ *
+ * @return the tag number for this point name.
+ */
+ public int getType()
+ {
+ return this.type;
+ }
+
+ /**
+ * Return the tagged object inside the distribution point name.
+ *
+ * @return the underlying choice item.
+ */
+ public ASN1Encodable getName()
+ {
+ return (ASN1Encodable)name;
+ }
+
+ public DistributionPointName(
+ ASN1TaggedObject obj)
+ {
+ this.type = obj.getTagNo();
+
+ if (type == 0)
+ {
+ this.name = GeneralNames.getInstance(obj, false);
+ }
+ else
+ {
+ this.name = ASN1Set.getInstance(obj, false);
+ }
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERTaggedObject(false, type, name);
+ }
+
+ public String toString()
+ {
+ String sep = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+ buf.append("DistributionPointName: [");
+ buf.append(sep);
+ if (type == FULL_NAME)
+ {
+ appendObject(buf, sep, "fullName", name.toString());
+ }
+ else
+ {
+ appendObject(buf, sep, "nameRelativeToCRLIssuer", name.toString());
+ }
+ buf.append("]");
+ buf.append(sep);
+ return buf.toString();
+ }
+
+ private void appendObject(StringBuffer buf, String sep, String name, String value)
+ {
+ String indent = " ";
+
+ buf.append(indent);
+ buf.append(name);
+ buf.append(":");
+ buf.append(sep);
+ buf.append(indent);
+ buf.append(indent);
+ buf.append(value);
+ buf.append(sep);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/ExtendedKeyUsage.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,147 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * The extendedKeyUsage object.
+ *
+ * extendedKeyUsage ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+ *
+ */
+public class ExtendedKeyUsage
+ extends ASN1Object
+{
+ Hashtable usageTable = new Hashtable();
+ ASN1Sequence seq;
+
+ public static ExtendedKeyUsage getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static ExtendedKeyUsage getInstance(
+ Object obj)
+ {
+ if (obj instanceof ExtendedKeyUsage)
+ {
+ return (ExtendedKeyUsage)obj;
+ }
+ else if (obj != null)
+ {
+ return new ExtendedKeyUsage(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static ExtendedKeyUsage fromExtensions(Extensions extensions)
+ {
+ return ExtendedKeyUsage.getInstance(extensions.getExtensionParsedValue(Extension.extendedKeyUsage));
+ }
+
+ public ExtendedKeyUsage(
+ KeyPurposeId usage)
+ {
+ this.seq = new DERSequence(usage);
+
+ this.usageTable.put(usage, usage);
+ }
+
+ private ExtendedKeyUsage(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Encodable o = (ASN1Encodable)e.nextElement();
+ if (!(o.toASN1Primitive() instanceof ASN1ObjectIdentifier))
+ {
+ throw new IllegalArgumentException("Only ASN1ObjectIdentifiers allowed in ExtendedKeyUsage.");
+ }
+ this.usageTable.put(o, o);
+ }
+ }
+
+ public ExtendedKeyUsage(
+ KeyPurposeId[] usages)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ for (int i = 0; i != usages.length; i++)
+ {
+ v.add(usages[i]);
+ this.usageTable.put(usages[i], usages[i]);
+ }
+
+ this.seq = new DERSequence(v);
+ }
+
+ /**
+ * @deprecated use KeyPurposeId[] constructor.
+ */
+ public ExtendedKeyUsage(
+ Vector usages)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ Enumeration e = usages.elements();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Primitive o = (ASN1Primitive)e.nextElement();
+
+ v.add(o);
+ this.usageTable.put(o, o);
+ }
+
+ this.seq = new DERSequence(v);
+ }
+
+ public boolean hasKeyPurposeId(
+ KeyPurposeId keyPurposeId)
+ {
+ return (usageTable.get(keyPurposeId) != null);
+ }
+
+ /**
+ * Returns all extended key usages.
+ * The returned vector contains DERObjectIdentifiers.
+ * @return An array with all key purposes.
+ */
+ public KeyPurposeId[] getUsages()
+ {
+ KeyPurposeId[] temp = new KeyPurposeId[seq.size()];
+
+ int i = 0;
+ for (Enumeration it = seq.getObjects(); it.hasMoreElements();)
+ {
+ temp[i++] = KeyPurposeId.getInstance(it.nextElement());
+ }
+ return temp;
+ }
+
+ public int size()
+ {
+ return usageTable.size();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Extension.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Extension.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Extension.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Extension.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,266 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Boolean;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+
+/**
+ * an object for the elements in the X.509 V3 extension block.
+ */
+public class Extension
+{
+ /**
+ * Subject Directory Attributes
+ */
+ public static final ASN1ObjectIdentifier subjectDirectoryAttributes = new ASN1ObjectIdentifier("2.5.29.9");
+
+ /**
+ * Subject Key Identifier
+ */
+ public static final ASN1ObjectIdentifier subjectKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.14");
+
+ /**
+ * Key Usage
+ */
+ public static final ASN1ObjectIdentifier keyUsage = new ASN1ObjectIdentifier("2.5.29.15");
+
+ /**
+ * Private Key Usage Period
+ */
+ public static final ASN1ObjectIdentifier privateKeyUsagePeriod = new ASN1ObjectIdentifier("2.5.29.16");
+
+ /**
+ * Subject Alternative Name
+ */
+ public static final ASN1ObjectIdentifier subjectAlternativeName = new ASN1ObjectIdentifier("2.5.29.17");
+
+ /**
+ * Issuer Alternative Name
+ */
+ public static final ASN1ObjectIdentifier issuerAlternativeName = new ASN1ObjectIdentifier("2.5.29.18");
+
+ /**
+ * Basic Constraints
+ */
+ public static final ASN1ObjectIdentifier basicConstraints = new ASN1ObjectIdentifier("2.5.29.19");
+
+ /**
+ * CRL Number
+ */
+ public static final ASN1ObjectIdentifier cRLNumber = new ASN1ObjectIdentifier("2.5.29.20");
+
+ /**
+ * Reason code
+ */
+ public static final ASN1ObjectIdentifier reasonCode = new ASN1ObjectIdentifier("2.5.29.21");
+
+ /**
+ * Hold Instruction Code
+ */
+ public static final ASN1ObjectIdentifier instructionCode = new ASN1ObjectIdentifier("2.5.29.23");
+
+ /**
+ * Invalidity Date
+ */
+ public static final ASN1ObjectIdentifier invalidityDate = new ASN1ObjectIdentifier("2.5.29.24");
+
+ /**
+ * Delta CRL indicator
+ */
+ public static final ASN1ObjectIdentifier deltaCRLIndicator = new ASN1ObjectIdentifier("2.5.29.27");
+
+ /**
+ * Issuing Distribution Point
+ */
+ public static final ASN1ObjectIdentifier issuingDistributionPoint = new ASN1ObjectIdentifier("2.5.29.28");
+
+ /**
+ * Certificate Issuer
+ */
+ public static final ASN1ObjectIdentifier certificateIssuer = new ASN1ObjectIdentifier("2.5.29.29");
+
+ /**
+ * Name Constraints
+ */
+ public static final ASN1ObjectIdentifier nameConstraints = new ASN1ObjectIdentifier("2.5.29.30");
+
+ /**
+ * CRL Distribution Points
+ */
+ public static final ASN1ObjectIdentifier cRLDistributionPoints = new ASN1ObjectIdentifier("2.5.29.31");
+
+ /**
+ * Certificate Policies
+ */
+ public static final ASN1ObjectIdentifier certificatePolicies = new ASN1ObjectIdentifier("2.5.29.32");
+
+ /**
+ * Policy Mappings
+ */
+ public static final ASN1ObjectIdentifier policyMappings = new ASN1ObjectIdentifier("2.5.29.33");
+
+ /**
+ * Authority Key Identifier
+ */
+ public static final ASN1ObjectIdentifier authorityKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.35");
+
+ /**
+ * Policy Constraints
+ */
+ public static final ASN1ObjectIdentifier policyConstraints = new ASN1ObjectIdentifier("2.5.29.36");
+
+ /**
+ * Extended Key Usage
+ */
+ public static final ASN1ObjectIdentifier extendedKeyUsage = new ASN1ObjectIdentifier("2.5.29.37");
+
+ /**
+ * Freshest CRL
+ */
+ public static final ASN1ObjectIdentifier freshestCRL = new ASN1ObjectIdentifier("2.5.29.46");
+
+ /**
+ * Inhibit Any Policy
+ */
+ public static final ASN1ObjectIdentifier inhibitAnyPolicy = new ASN1ObjectIdentifier("2.5.29.54");
+
+ /**
+ * Authority Info Access
+ */
+ public static final ASN1ObjectIdentifier authorityInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.1");
+
+ /**
+ * Subject Info Access
+ */
+ public static final ASN1ObjectIdentifier subjectInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.11");
+
+ /**
+ * Logo Type
+ */
+ public static final ASN1ObjectIdentifier logoType = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.12");
+
+ /**
+ * BiometricInfo
+ */
+ public static final ASN1ObjectIdentifier biometricInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.2");
+
+ /**
+ * QCStatements
+ */
+ public static final ASN1ObjectIdentifier qCStatements = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.3");
+
+ /**
+ * Audit identity extension in attribute certificates.
+ */
+ public static final ASN1ObjectIdentifier auditIdentity = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.4");
+
+ /**
+ * NoRevAvail extension in attribute certificates.
+ */
+ public static final ASN1ObjectIdentifier noRevAvail = new ASN1ObjectIdentifier("2.5.29.56");
+
+ /**
+ * TargetInformation extension in attribute certificates.
+ */
+ public static final ASN1ObjectIdentifier targetInformation = new ASN1ObjectIdentifier("2.5.29.55");
+
+ private ASN1ObjectIdentifier extnId;
+
+ boolean critical;
+ ASN1OctetString value;
+
+ public Extension(
+ ASN1ObjectIdentifier extnId,
+ ASN1Boolean critical,
+ ASN1OctetString value)
+ {
+ this(extnId, critical.isTrue(), value);
+ }
+
+ public Extension(
+ ASN1ObjectIdentifier extnId,
+ boolean critical,
+ byte[] value)
+ {
+ this(extnId, critical, new DEROctetString(value));
+ }
+
+ public Extension(
+ ASN1ObjectIdentifier extnId,
+ boolean critical,
+ ASN1OctetString value)
+ {
+ this.extnId = extnId;
+ this.critical = critical;
+ this.value = value;
+ }
+
+ public ASN1ObjectIdentifier getExtnId()
+ {
+ return extnId;
+ }
+
+ public boolean isCritical()
+ {
+ return critical;
+ }
+
+ public ASN1OctetString getExtnValue()
+ {
+ return value;
+ }
+
+ public ASN1Encodable getParsedValue()
+ {
+ return convertValueToObject(this);
+ }
+
+ public int hashCode()
+ {
+ if (this.isCritical())
+ {
+ return this.getExtnValue().hashCode();
+ }
+
+ return ~this.getExtnValue().hashCode();
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof Extension))
+ {
+ return false;
+ }
+
+ Extension other = (Extension)o;
+
+ return other.getExtnValue().equals(this.getExtnValue())
+ && (other.isCritical() == this.isCritical());
+ }
+
+ /**
+ * Convert the value of the passed in extension to an object
+ * @param ext the extension to parse
+ * @return the object the value string contains
+ * @exception IllegalArgumentException if conversion is not possible
+ */
+ private static ASN1Primitive convertValueToObject(
+ Extension ext)
+ throws IllegalArgumentException
+ {
+ try
+ {
+ return ASN1Primitive.fromByteArray(ext.getExtnValue().getOctets());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("can't convert extension: " + e);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Extensions.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Extensions.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Extensions.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Extensions.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,245 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1Boolean;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class Extensions
+ extends ASN1Object
+{
+ private Hashtable extensions = new Hashtable();
+ private Vector ordering = new Vector();
+
+ public static Extensions getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static Extensions getInstance(
+ Object obj)
+ {
+ if (obj instanceof Extensions)
+ {
+ return (Extensions)obj;
+ }
+ else if (obj != null)
+ {
+ return new Extensions(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
+ */
+ private Extensions(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(e.nextElement());
+
+ if (s.size() == 3)
+ {
+ extensions.put(s.getObjectAt(0), new Extension(ASN1ObjectIdentifier.getInstance(s.getObjectAt(0)), ASN1Boolean.getInstance(s.getObjectAt(1)), ASN1OctetString.getInstance(s.getObjectAt(2))));
+ }
+ else if (s.size() == 2)
+ {
+ extensions.put(s.getObjectAt(0), new Extension(ASN1ObjectIdentifier.getInstance(s.getObjectAt(0)), false, ASN1OctetString.getInstance(s.getObjectAt(1))));
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + s.size());
+ }
+
+ ordering.addElement(s.getObjectAt(0));
+ }
+ }
+
+ /**
+ * Base Constructor
+ *
+ * @param extension a single extension.
+ */
+ public Extensions(
+ Extension extension)
+ {
+ this.ordering.addElement(extension.getExtnId());
+ this.extensions.put(extension.getExtnId(), extension);
+ }
+
+ /**
+ * Base Constructor
+ *
+ * @param extensions an array of extensions.
+ */
+ public Extensions(
+ Extension[] extensions)
+ {
+ for (int i = 0; i != extensions.length; i++)
+ {
+ Extension ext = extensions[i];
+
+ this.ordering.addElement(ext.getExtnId());
+ this.extensions.put(ext.getExtnId(), ext);
+ }
+ }
+
+ /**
+ * return an Enumeration of the extension field's object ids.
+ */
+ public Enumeration oids()
+ {
+ return ordering.elements();
+ }
+
+ /**
+ * return the extension represented by the object identifier
+ * passed in.
+ *
+ * @return the extension if it's present, null otherwise.
+ */
+ public Extension getExtension(
+ ASN1ObjectIdentifier oid)
+ {
+ return (Extension)extensions.get(oid);
+ }
+
+ /**
+ * return the parsed value of the extension represented by the object identifier
+ * passed in.
+ *
+ * @return the parsed value of the extension if it's present, null otherwise.
+ */
+ public ASN1Encodable getExtensionParsedValue(ASN1ObjectIdentifier oid)
+ {
+ Extension ext = this.getExtension(oid);
+
+ if (ext != null)
+ {
+ return ext.getParsedValue();
+ }
+
+ return null;
+ }
+
+ /**
+ *
+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+ *
+ * Extension ::= SEQUENCE {
+ * extnId EXTENSION.&id ({ExtensionSet}),
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ Enumeration e = ordering.elements();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
+ Extension ext = (Extension)extensions.get(oid);
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(oid);
+
+ if (ext.isCritical())
+ {
+ v.add(ASN1Boolean.getInstance(true));
+ }
+
+ v.add(ext.getExtnValue());
+
+ vec.add(new DERSequence(v));
+ }
+
+ return new DERSequence(vec);
+ }
+
+ public boolean equivalent(
+ Extensions other)
+ {
+ if (extensions.size() != other.extensions.size())
+ {
+ return false;
+ }
+
+ Enumeration e1 = extensions.keys();
+
+ while (e1.hasMoreElements())
+ {
+ Object key = e1.nextElement();
+
+ if (!extensions.get(key).equals(other.extensions.get(key)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public ASN1ObjectIdentifier[] getExtensionOIDs()
+ {
+ return toOidArray(ordering);
+ }
+
+ public ASN1ObjectIdentifier[] getNonCriticalExtensionOIDs()
+ {
+ return getExtensionOIDs(false);
+ }
+
+ public ASN1ObjectIdentifier[] getCriticalExtensionOIDs()
+ {
+ return getExtensionOIDs(true);
+ }
+
+ private ASN1ObjectIdentifier[] getExtensionOIDs(boolean isCritical)
+ {
+ Vector oidVec = new Vector();
+
+ for (int i = 0; i != ordering.size(); i++)
+ {
+ Object oid = ordering.elementAt(i);
+
+ if (((Extension)extensions.get(oid)).isCritical() == isCritical)
+ {
+ oidVec.addElement(oid);
+ }
+ }
+
+ return toOidArray(oidVec);
+ }
+
+ private ASN1ObjectIdentifier[] toOidArray(Vector oidVec)
+ {
+ ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[oidVec.size()];
+
+ for (int i = 0; i != oids.length; i++)
+ {
+ oids[i] = (ASN1ObjectIdentifier)oidVec.elementAt(i);
+ }
+ return oids;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/ExtensionsGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/ExtensionsGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/ExtensionsGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/ExtensionsGenerator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,94 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Encoding;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+
+/**
+ * Generator for X.509 extensions
+ */
+public class ExtensionsGenerator
+{
+ private Hashtable extensions = new Hashtable();
+ private Vector extOrdering = new Vector();
+
+ /**
+ * Reset the generator
+ */
+ public void reset()
+ {
+ extensions = new Hashtable();
+ extOrdering = new Vector();
+ }
+
+ /**
+ * Add an extension with the given oid and the passed in value to be included
+ * in the OCTET STRING associated with the extension.
+ *
+ * @param oid OID for the extension.
+ * @param critical true if critical, false otherwise.
+ * @param value the ASN.1 object to be included in the extension.
+ */
+ public void addExtension(
+ ASN1ObjectIdentifier oid,
+ boolean critical,
+ ASN1Encodable value)
+ throws IOException
+ {
+ this.addExtension(oid, critical, value.toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ }
+
+ /**
+ * Add an extension with the given oid and the passed in byte array to be wrapped in the
+ * OCTET STRING associated with the extension.
+ *
+ * @param oid OID for the extension.
+ * @param critical true if critical, false otherwise.
+ * @param value the byte array to be wrapped.
+ */
+ public void addExtension(
+ ASN1ObjectIdentifier oid,
+ boolean critical,
+ byte[] value)
+ {
+ if (extensions.containsKey(oid))
+ {
+ throw new IllegalArgumentException("extension " + oid + " already added");
+ }
+
+ extOrdering.addElement(oid);
+ extensions.put(oid, new Extension(oid, critical, new DEROctetString(value)));
+ }
+
+ /**
+ * Return true if there are no extension present in this generator.
+ *
+ * @return true if empty, false otherwise
+ */
+ public boolean isEmpty()
+ {
+ return extOrdering.isEmpty();
+ }
+
+ /**
+ * Generate an Extensions object based on the current state of the generator.
+ *
+ * @return an X09Extensions object.
+ */
+ public Extensions generate()
+ {
+ Extension[] exts = new Extension[extOrdering.size()];
+
+ for (int i = 0; i != extOrdering.size(); i++)
+ {
+ exts[i] = (Extension)extensions.get(extOrdering.elementAt(i));
+ }
+
+ return new Extensions(exts);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/GeneralName.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/GeneralName.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/GeneralName.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/GeneralName.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,439 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.io.IOException;
+import java.util.StringTokenizer;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+import pdftk.org.bouncycastle.util.IPAddress;
+
+/**
+ * The GeneralName object.
+ *
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER}
+ *
+ * OtherName ::= SEQUENCE {
+ * type-id OBJECT IDENTIFIER,
+ * value [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * EDIPartyName ::= SEQUENCE {
+ * nameAssigner [0] DirectoryString OPTIONAL,
+ * partyName [1] DirectoryString }
+ *
+ * Name ::= CHOICE { RDNSequence }
+ *
+ */
+public class GeneralName
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int otherName = 0;
+ public static final int rfc822Name = 1;
+ public static final int dNSName = 2;
+ public static final int x400Address = 3;
+ public static final int directoryName = 4;
+ public static final int ediPartyName = 5;
+ public static final int uniformResourceIdentifier = 6;
+ public static final int iPAddress = 7;
+ public static final int registeredID = 8;
+
+ private ASN1Encodable obj;
+ private int tag;
+
+ /**
+ * @deprecated use X500Name constructor.
+ * @param dirName
+ */
+ public GeneralName(
+ X509Name dirName)
+ {
+ this.obj = X500Name.getInstance(dirName);
+ this.tag = 4;
+ }
+
+ public GeneralName(
+ X500Name dirName)
+ {
+ this.obj = dirName;
+ this.tag = 4;
+ }
+
+ /**
+ * When the subjectAltName extension contains an Internet mail address,
+ * the address MUST be included as an rfc822Name. The format of an
+ * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
+ *
+ * When the subjectAltName extension contains a domain name service
+ * label, the domain name MUST be stored in the dNSName (an IA5String).
+ * The name MUST be in the "preferred name syntax," as specified by RFC
+ * 1034 [RFC 1034].
+ *
+ * When the subjectAltName extension contains a URI, the name MUST be
+ * stored in the uniformResourceIdentifier (an IA5String). The name MUST
+ * be a non-relative URL, and MUST follow the URL syntax and encoding
+ * rules specified in [RFC 1738]. The name must include both a scheme
+ * (e.g., "http" or "ftp") and a scheme-specific-part. The scheme-
+ * specific-part must include a fully qualified domain name or IP
+ * address as the host.
+ *
+ * When the subjectAltName extension contains a iPAddress, the address
+ * MUST be stored in the octet string in "network byte order," as
+ * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
+ * each octet is the LSB of the corresponding byte in the network
+ * address. For IP Version 4, as specified in RFC 791, the octet string
+ * MUST contain exactly four octets. For IP Version 6, as specified in
+ * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
+ * 1883].
+ */
+ public GeneralName(
+ int tag,
+ ASN1Encodable name)
+ {
+ this.obj = name;
+ this.tag = tag;
+ }
+
+ /**
+ * Create a GeneralName for the given tag from the passed in String.
+ *
+ * This constructor can handle:
+ *
+ * rfc822Name
+ * iPAddress
+ * directoryName
+ * dNSName
+ * uniformResourceIdentifier
+ * registeredID
+ *
+ * For x400Address, otherName and ediPartyName there is no common string
+ * format defined.
+ *
+ * Note: A directory name can be encoded in different ways into a byte
+ * representation. Be aware of this if the byte representation is used for
+ * comparing results.
+ *
+ * @param tag tag number
+ * @param name string representation of name
+ * @throws IllegalArgumentException if the string encoding is not correct or * not supported.
+ */
+ public GeneralName(
+ int tag,
+ String name)
+ {
+ this.tag = tag;
+
+ if (tag == rfc822Name || tag == dNSName || tag == uniformResourceIdentifier)
+ {
+ this.obj = new DERIA5String(name);
+ }
+ else if (tag == registeredID)
+ {
+ this.obj = new ASN1ObjectIdentifier(name);
+ }
+ else if (tag == directoryName)
+ {
+ this.obj = new X500Name(name);
+ }
+ else if (tag == iPAddress)
+ {
+ byte[] enc = toGeneralNameEncoding(name);
+ if (enc != null)
+ {
+ this.obj = new DEROctetString(enc);
+ }
+ else
+ {
+ throw new IllegalArgumentException("IP Address is invalid");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("can't process String for tag: " + tag);
+ }
+ }
+
+ public static GeneralName getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof GeneralName)
+ {
+ return (GeneralName)obj;
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ ASN1TaggedObject tagObj = (ASN1TaggedObject)obj;
+ int tag = tagObj.getTagNo();
+
+ switch (tag)
+ {
+ case otherName:
+ return new GeneralName(tag, ASN1Sequence.getInstance(tagObj, false));
+ case rfc822Name:
+ return new GeneralName(tag, DERIA5String.getInstance(tagObj, false));
+ case dNSName:
+ return new GeneralName(tag, DERIA5String.getInstance(tagObj, false));
+ case x400Address:
+ throw new IllegalArgumentException("unknown tag: " + tag);
+ case directoryName:
+ return new GeneralName(tag, X500Name.getInstance(tagObj, true));
+ case ediPartyName:
+ return new GeneralName(tag, ASN1Sequence.getInstance(tagObj, false));
+ case uniformResourceIdentifier:
+ return new GeneralName(tag, DERIA5String.getInstance(tagObj, false));
+ case iPAddress:
+ return new GeneralName(tag, ASN1OctetString.getInstance(tagObj, false));
+ case registeredID:
+ return new GeneralName(tag, ASN1ObjectIdentifier.getInstance(tagObj, false));
+ }
+ }
+
+ if (obj instanceof byte[])
+ {
+ try
+ {
+ return getInstance(ASN1Primitive.fromByteArray((byte[])obj));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to parse encoded general name");
+ }
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName());
+ }
+
+ public static GeneralName getInstance(
+ ASN1TaggedObject tagObj,
+ boolean explicit)
+ {
+ return GeneralName.getInstance(ASN1TaggedObject.getInstance(tagObj, true));
+ }
+
+ public int getTagNo()
+ {
+ return tag;
+ }
+
+ public ASN1Encodable getName()
+ {
+ return obj;
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+
+ buf.append(tag);
+ buf.append(": ");
+ switch (tag)
+ {
+ case rfc822Name:
+ case dNSName:
+ case uniformResourceIdentifier:
+ buf.append(DERIA5String.getInstance(obj).getString());
+ break;
+ case directoryName:
+ buf.append(X500Name.getInstance(obj).toString());
+ break;
+ default:
+ buf.append(obj.toString());
+ }
+ return buf.toString();
+ }
+
+ private byte[] toGeneralNameEncoding(String ip)
+ {
+ if (IPAddress.isValidIPv6WithNetmask(ip) || IPAddress.isValidIPv6(ip))
+ {
+ int slashIndex = ip.indexOf('/');
+
+ if (slashIndex < 0)
+ {
+ byte[] addr = new byte[16];
+ int[] parsedIp = parseIPv6(ip);
+ copyInts(parsedIp, addr, 0);
+
+ return addr;
+ }
+ else
+ {
+ byte[] addr = new byte[32];
+ int[] parsedIp = parseIPv6(ip.substring(0, slashIndex));
+ copyInts(parsedIp, addr, 0);
+ String mask = ip.substring(slashIndex + 1);
+ if (mask.indexOf(':') > 0)
+ {
+ parsedIp = parseIPv6(mask);
+ }
+ else
+ {
+ parsedIp = parseMask(mask);
+ }
+ copyInts(parsedIp, addr, 16);
+
+ return addr;
+ }
+ }
+ else if (IPAddress.isValidIPv4WithNetmask(ip) || IPAddress.isValidIPv4(ip))
+ {
+ int slashIndex = ip.indexOf('/');
+
+ if (slashIndex < 0)
+ {
+ byte[] addr = new byte[4];
+
+ parseIPv4(ip, addr, 0);
+
+ return addr;
+ }
+ else
+ {
+ byte[] addr = new byte[8];
+
+ parseIPv4(ip.substring(0, slashIndex), addr, 0);
+
+ String mask = ip.substring(slashIndex + 1);
+ if (mask.indexOf('.') > 0)
+ {
+ parseIPv4(mask, addr, 4);
+ }
+ else
+ {
+ parseIPv4Mask(mask, addr, 4);
+ }
+
+ return addr;
+ }
+ }
+
+ return null;
+ }
+
+ private void parseIPv4Mask(String mask, byte[] addr, int offset)
+ {
+ int maskVal = Integer.parseInt(mask);
+
+ for (int i = 0; i != maskVal; i++)
+ {
+ addr[(i / 8) + offset] |= 1 << (7 - (i % 8));
+ }
+ }
+
+ private void parseIPv4(String ip, byte[] addr, int offset)
+ {
+ StringTokenizer sTok = new StringTokenizer(ip, "./");
+ int index = 0;
+
+ while (sTok.hasMoreTokens())
+ {
+ addr[offset + index++] = (byte)Integer.parseInt(sTok.nextToken());
+ }
+ }
+
+ private int[] parseMask(String mask)
+ {
+ int[] res = new int[8];
+ int maskVal = Integer.parseInt(mask);
+
+ for (int i = 0; i != maskVal; i++)
+ {
+ res[i / 16] |= 1 << (15 - (i % 16));
+ }
+ return res;
+ }
+
+ private void copyInts(int[] parsedIp, byte[] addr, int offSet)
+ {
+ for (int i = 0; i != parsedIp.length; i++)
+ {
+ addr[(i * 2) + offSet] = (byte)(parsedIp[i] >> 8);
+ addr[(i * 2 + 1) + offSet] = (byte)parsedIp[i];
+ }
+ }
+
+ private int[] parseIPv6(String ip)
+ {
+ StringTokenizer sTok = new StringTokenizer(ip, ":", true);
+ int index = 0;
+ int[] val = new int[8];
+
+ if (ip.charAt(0) == ':' && ip.charAt(1) == ':')
+ {
+ sTok.nextToken(); // skip the first one
+ }
+
+ int doubleColon = -1;
+
+ while (sTok.hasMoreTokens())
+ {
+ String e = sTok.nextToken();
+
+ if (e.equals(":"))
+ {
+ doubleColon = index;
+ val[index++] = 0;
+ }
+ else
+ {
+ if (e.indexOf('.') < 0)
+ {
+ val[index++] = Integer.parseInt(e, 16);
+ if (sTok.hasMoreTokens())
+ {
+ sTok.nextToken();
+ }
+ }
+ else
+ {
+ StringTokenizer eTok = new StringTokenizer(e, ".");
+
+ val[index++] = (Integer.parseInt(eTok.nextToken()) << 8) | Integer.parseInt(eTok.nextToken());
+ val[index++] = (Integer.parseInt(eTok.nextToken()) << 8) | Integer.parseInt(eTok.nextToken());
+ }
+ }
+ }
+
+ if (index != val.length)
+ {
+ System.arraycopy(val, doubleColon, val, val.length - (index - doubleColon), index - doubleColon);
+ for (int i = doubleColon; i != val.length - (index - doubleColon); i++)
+ {
+ val[i] = 0;
+ }
+ }
+
+ return val;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (tag == directoryName) // directoryName is explicitly tagged as it is a CHOICE
+ {
+ return new DERTaggedObject(true, tag, obj);
+ }
+ else
+ {
+ return new DERTaggedObject(false, tag, obj);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/GeneralNames.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/GeneralNames.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/GeneralNames.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/GeneralNames.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,108 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class GeneralNames
+ extends ASN1Object
+{
+ private final GeneralName[] names;
+
+ public static GeneralNames getInstance(
+ Object obj)
+ {
+ if (obj instanceof GeneralNames)
+ {
+ return (GeneralNames)obj;
+ }
+
+ if (obj != null)
+ {
+ return new GeneralNames(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static GeneralNames getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static GeneralNames fromExtensions(Extensions extensions, ASN1ObjectIdentifier extOID)
+ {
+ return GeneralNames.getInstance(extensions.getExtensionParsedValue(extOID));
+ }
+
+ /**
+ * Construct a GeneralNames object containing one GeneralName.
+ *
+ * @param name the name to be contained.
+ */
+ public GeneralNames(
+ GeneralName name)
+ {
+ this.names = new GeneralName[] { name };
+ }
+
+
+ public GeneralNames(
+ GeneralName[] names)
+ {
+ this.names = names;
+ }
+
+ private GeneralNames(
+ ASN1Sequence seq)
+ {
+ this.names = new GeneralName[seq.size()];
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ names[i] = GeneralName.getInstance(seq.getObjectAt(i));
+ }
+ }
+
+ public GeneralName[] getNames()
+ {
+ GeneralName[] tmp = new GeneralName[names.length];
+
+ System.arraycopy(names, 0, tmp, 0, names.length);
+
+ return tmp;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * GeneralNames ::= SEQUENCE SIZE {1..MAX} OF GeneralName
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DERSequence(names);
+ }
+
+ public String toString()
+ {
+ StringBuffer buf = new StringBuffer();
+ String sep = System.getProperty("line.separator");
+
+ buf.append("GeneralNames:");
+ buf.append(sep);
+
+ for (int i = 0; i != names.length; i++)
+ {
+ buf.append(" ");
+ buf.append(names[i]);
+ buf.append(sep);
+ }
+ return buf.toString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/GeneralSubtree.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/GeneralSubtree.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/GeneralSubtree.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/GeneralSubtree.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,218 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * Class for containing a restriction object subtrees in NameConstraints. See
+ * RFC 3280.
+ *
+ *
+ *
+ * GeneralSubtree ::= SEQUENCE
+ * {
+ * base GeneralName,
+ * minimum [0] BaseDistance DEFAULT 0,
+ * maximum [1] BaseDistance OPTIONAL
+ * }
+ *
+ *
+ * @see pdftk.org.bouncycastle.asn1.x509.NameConstraints
+ *
+ */
+public class GeneralSubtree
+ extends ASN1Object
+{
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+
+ private GeneralName base;
+
+ private ASN1Integer minimum;
+
+ private ASN1Integer maximum;
+
+ private GeneralSubtree(
+ ASN1Sequence seq)
+ {
+ base = GeneralName.getInstance(seq.getObjectAt(0));
+
+ switch (seq.size())
+ {
+ case 1:
+ break;
+ case 2:
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
+ switch (o.getTagNo())
+ {
+ case 0:
+ minimum = ASN1Integer.getInstance(o, false);
+ break;
+ case 1:
+ maximum = ASN1Integer.getInstance(o, false);
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag number: "
+ + o.getTagNo());
+ }
+ break;
+ case 3:
+ {
+ {
+ ASN1TaggedObject oMin = ASN1TaggedObject.getInstance(seq.getObjectAt(1));
+ if (oMin.getTagNo() != 0)
+ {
+ throw new IllegalArgumentException("Bad tag number for 'minimum': " + oMin.getTagNo());
+ }
+ minimum = ASN1Integer.getInstance(oMin, false);
+ }
+
+ {
+ ASN1TaggedObject oMax = ASN1TaggedObject.getInstance(seq.getObjectAt(2));
+ if (oMax.getTagNo() != 1)
+ {
+ throw new IllegalArgumentException("Bad tag number for 'maximum': " + oMax.getTagNo());
+ }
+ maximum = ASN1Integer.getInstance(oMax, false);
+ }
+
+ break;
+ }
+ default:
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * According RFC 3280, the minimum and maximum fields are not used with any
+ * name forms, thus minimum MUST be zero, and maximum MUST be absent.
+ *
+ * If minimum is null
, zero is assumed, if
+ * maximum is null
, maximum is absent.
+ *
+ * @param base
+ * A restriction.
+ * @param minimum
+ * Minimum
+ *
+ * @param maximum
+ * Maximum
+ */
+ public GeneralSubtree(
+ GeneralName base,
+ BigInteger minimum,
+ BigInteger maximum)
+ {
+ this.base = base;
+ if (maximum != null)
+ {
+ this.maximum = new ASN1Integer(maximum);
+ }
+ if (minimum == null)
+ {
+ this.minimum = null;
+ }
+ else
+ {
+ this.minimum = new ASN1Integer(minimum);
+ }
+ }
+
+ public GeneralSubtree(GeneralName base)
+ {
+ this(base, null, null);
+ }
+
+ public static GeneralSubtree getInstance(
+ ASN1TaggedObject o,
+ boolean explicit)
+ {
+ return new GeneralSubtree(ASN1Sequence.getInstance(o, explicit));
+ }
+
+ public static GeneralSubtree getInstance(
+ Object obj)
+ {
+ if (obj == null)
+ {
+ return null;
+ }
+
+ if (obj instanceof GeneralSubtree)
+ {
+ return (GeneralSubtree) obj;
+ }
+
+ return new GeneralSubtree(ASN1Sequence.getInstance(obj));
+ }
+
+ public GeneralName getBase()
+ {
+ return base;
+ }
+
+ public BigInteger getMinimum()
+ {
+ if (minimum == null)
+ {
+ return ZERO;
+ }
+
+ return minimum.getValue();
+ }
+
+ public BigInteger getMaximum()
+ {
+ if (maximum == null)
+ {
+ return null;
+ }
+
+ return maximum.getValue();
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * GeneralSubtree ::= SEQUENCE
+ * {
+ * base GeneralName,
+ * minimum [0] BaseDistance DEFAULT 0,
+ * maximum [1] BaseDistance OPTIONAL
+ * }
+ *
+ *
+ * @return a ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(base);
+
+ if (minimum != null && !minimum.getValue().equals(ZERO))
+ {
+ v.add(new DERTaggedObject(false, 0, minimum));
+ }
+
+ if (maximum != null)
+ {
+ v.add(new DERTaggedObject(false, 1, maximum));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Holder.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Holder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Holder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Holder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,245 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * The Holder object.
+ *
+ * For an v2 attribute certificate this is:
+ *
+ *
+ * Holder ::= SEQUENCE {
+ * baseCertificateID [0] IssuerSerial OPTIONAL,
+ * -- the issuer and serial number of
+ * -- the holder's Public Key Certificate
+ * entityName [1] GeneralNames OPTIONAL,
+ * -- the name of the claimant or role
+ * objectDigestInfo [2] ObjectDigestInfo OPTIONAL
+ * -- used to directly authenticate the holder,
+ * -- for example, an executable
+ * }
+ *
+ *
+ *
+ * For an v1 attribute certificate this is:
+ *
+ *
+ * subject CHOICE {
+ * baseCertificateID [0] IssuerSerial,
+ * -- associated with a Public Key Certificate
+ * subjectName [1] GeneralNames },
+ * -- associated with a name
+ *
+ */
+public class Holder
+ extends ASN1Object
+{
+ public static final int V1_CERTIFICATE_HOLDER = 0;
+ public static final int V2_CERTIFICATE_HOLDER = 1;
+
+ IssuerSerial baseCertificateID;
+
+ GeneralNames entityName;
+
+ ObjectDigestInfo objectDigestInfo;
+
+ private int version = V2_CERTIFICATE_HOLDER;
+
+ public static Holder getInstance(Object obj)
+ {
+ if (obj instanceof Holder)
+ {
+ return (Holder)obj;
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new Holder(ASN1TaggedObject.getInstance(obj));
+ }
+ else if (obj != null)
+ {
+ return new Holder(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor for a holder for an V1 attribute certificate.
+ *
+ * @param tagObj The ASN.1 tagged holder object.
+ */
+ private Holder(ASN1TaggedObject tagObj)
+ {
+ switch (tagObj.getTagNo())
+ {
+ case 0:
+ baseCertificateID = IssuerSerial.getInstance(tagObj, false);
+ break;
+ case 1:
+ entityName = GeneralNames.getInstance(tagObj, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag in Holder");
+ }
+ version = 0;
+ }
+
+ /**
+ * Constructor for a holder for an V2 attribute certificate.
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private Holder(ASN1Sequence seq)
+ {
+ if (seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject tObj = ASN1TaggedObject.getInstance(seq
+ .getObjectAt(i));
+
+ switch (tObj.getTagNo())
+ {
+ case 0:
+ baseCertificateID = IssuerSerial.getInstance(tObj, false);
+ break;
+ case 1:
+ entityName = GeneralNames.getInstance(tObj, false);
+ break;
+ case 2:
+ objectDigestInfo = ObjectDigestInfo.getInstance(tObj, false);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag in Holder");
+ }
+ }
+ version = 1;
+ }
+
+ public Holder(IssuerSerial baseCertificateID)
+ {
+ this(baseCertificateID, V2_CERTIFICATE_HOLDER);
+ }
+
+ /**
+ * Constructs a holder from a IssuerSerial for a V1 or V2 certificate.
+ * .
+ * @param baseCertificateID The IssuerSerial.
+ * @param version The version of the attribute certificate.
+ */
+ public Holder(IssuerSerial baseCertificateID, int version)
+ {
+ this.baseCertificateID = baseCertificateID;
+ this.version = version;
+ }
+
+ /**
+ * Returns 1 for V2 attribute certificates or 0 for V1 attribute
+ * certificates.
+ * @return The version of the attribute certificate.
+ */
+ public int getVersion()
+ {
+ return version;
+ }
+
+ /**
+ * Constructs a holder with an entityName for V2 attribute certificates.
+ *
+ * @param entityName The entity or subject name.
+ */
+ public Holder(GeneralNames entityName)
+ {
+ this(entityName, V2_CERTIFICATE_HOLDER);
+ }
+
+ /**
+ * Constructs a holder with an entityName for V2 attribute certificates or
+ * with a subjectName for V1 attribute certificates.
+ *
+ * @param entityName The entity or subject name.
+ * @param version The version of the attribute certificate.
+ */
+ public Holder(GeneralNames entityName, int version)
+ {
+ this.entityName = entityName;
+ this.version = version;
+ }
+
+ /**
+ * Constructs a holder from an object digest info.
+ *
+ * @param objectDigestInfo The object digest info object.
+ */
+ public Holder(ObjectDigestInfo objectDigestInfo)
+ {
+ this.objectDigestInfo = objectDigestInfo;
+ }
+
+ public IssuerSerial getBaseCertificateID()
+ {
+ return baseCertificateID;
+ }
+
+ /**
+ * Returns the entityName for an V2 attribute certificate or the subjectName
+ * for an V1 attribute certificate.
+ *
+ * @return The entityname or subjectname.
+ */
+ public GeneralNames getEntityName()
+ {
+ return entityName;
+ }
+
+ public ObjectDigestInfo getObjectDigestInfo()
+ {
+ return objectDigestInfo;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (version == 1)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (baseCertificateID != null)
+ {
+ v.add(new DERTaggedObject(false, 0, baseCertificateID));
+ }
+
+ if (entityName != null)
+ {
+ v.add(new DERTaggedObject(false, 1, entityName));
+ }
+
+ if (objectDigestInfo != null)
+ {
+ v.add(new DERTaggedObject(false, 2, objectDigestInfo));
+ }
+
+ return new DERSequence(v);
+ }
+ else
+ {
+ if (entityName != null)
+ {
+ return new DERTaggedObject(false, 1, entityName);
+ }
+ else
+ {
+ return new DERTaggedObject(false, 0, baseCertificateID);
+ }
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/IetfAttrSyntax.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/IetfAttrSyntax.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/IetfAttrSyntax.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/IetfAttrSyntax.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,189 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.DERUTF8String;
+
+/**
+ * Implementation of IetfAttrSyntax
as specified by RFC3281.
+ */
+public class IetfAttrSyntax
+ extends ASN1Object
+{
+ public static final int VALUE_OCTETS = 1;
+ public static final int VALUE_OID = 2;
+ public static final int VALUE_UTF8 = 3;
+ GeneralNames policyAuthority = null;
+ Vector values = new Vector();
+ int valueChoice = -1;
+
+ public static IetfAttrSyntax getInstance(Object obj)
+ {
+ if (obj instanceof IetfAttrSyntax)
+ {
+ return (IetfAttrSyntax)obj;
+ }
+ if (obj != null)
+ {
+ return new IetfAttrSyntax(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ *
+ */
+ private IetfAttrSyntax(ASN1Sequence seq)
+ {
+ int i = 0;
+
+ if (seq.getObjectAt(0) instanceof ASN1TaggedObject)
+ {
+ policyAuthority = GeneralNames.getInstance(((ASN1TaggedObject)seq.getObjectAt(0)), false);
+ i++;
+ }
+ else if (seq.size() == 2)
+ { // VOMS fix
+ policyAuthority = GeneralNames.getInstance(seq.getObjectAt(0));
+ i++;
+ }
+
+ if (!(seq.getObjectAt(i) instanceof ASN1Sequence))
+ {
+ throw new IllegalArgumentException("Non-IetfAttrSyntax encoding");
+ }
+
+ seq = (ASN1Sequence)seq.getObjectAt(i);
+
+ for (Enumeration e = seq.getObjects(); e.hasMoreElements();)
+ {
+ ASN1Primitive obj = (ASN1Primitive)e.nextElement();
+ int type;
+
+ if (obj instanceof ASN1ObjectIdentifier)
+ {
+ type = VALUE_OID;
+ }
+ else if (obj instanceof DERUTF8String)
+ {
+ type = VALUE_UTF8;
+ }
+ else if (obj instanceof DEROctetString)
+ {
+ type = VALUE_OCTETS;
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad value type encoding IetfAttrSyntax");
+ }
+
+ if (valueChoice < 0)
+ {
+ valueChoice = type;
+ }
+
+ if (type != valueChoice)
+ {
+ throw new IllegalArgumentException("Mix of value types in IetfAttrSyntax");
+ }
+
+ values.addElement(obj);
+ }
+ }
+
+ public GeneralNames getPolicyAuthority()
+ {
+ return policyAuthority;
+ }
+
+ public int getValueType()
+ {
+ return valueChoice;
+ }
+
+ public Object[] getValues()
+ {
+ if (this.getValueType() == VALUE_OCTETS)
+ {
+ ASN1OctetString[] tmp = new ASN1OctetString[values.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = (ASN1OctetString)values.elementAt(i);
+ }
+
+ return tmp;
+ }
+ else if (this.getValueType() == VALUE_OID)
+ {
+ ASN1ObjectIdentifier[] tmp = new ASN1ObjectIdentifier[values.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = (ASN1ObjectIdentifier)values.elementAt(i);
+ }
+
+ return tmp;
+ }
+ else
+ {
+ DERUTF8String[] tmp = new DERUTF8String[values.size()];
+
+ for (int i = 0; i != tmp.length; i++)
+ {
+ tmp[i] = (DERUTF8String)values.elementAt(i);
+ }
+
+ return tmp;
+ }
+ }
+
+ /**
+ *
+ *
+ *
+ * IetfAttrSyntax ::= SEQUENCE {
+ * policyAuthority [0] GeneralNames OPTIONAL,
+ * values SEQUENCE OF CHOICE {
+ * octets OCTET STRING,
+ * oid OBJECT IDENTIFIER,
+ * string UTF8String
+ * }
+ * }
+ *
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (policyAuthority != null)
+ {
+ v.add(new DERTaggedObject(0, policyAuthority));
+ }
+
+ ASN1EncodableVector v2 = new ASN1EncodableVector();
+
+ for (Enumeration i = values.elements(); i.hasMoreElements();)
+ {
+ v2.add((ASN1Encodable)i.nextElement());
+ }
+
+ v.add(new DERSequence(v2));
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/IssuerSerial.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/IssuerSerial.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/IssuerSerial.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/IssuerSerial.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,115 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class IssuerSerial
+ extends ASN1Object
+{
+ GeneralNames issuer;
+ ASN1Integer serial;
+ DERBitString issuerUID;
+
+ public static IssuerSerial getInstance(
+ Object obj)
+ {
+ if (obj instanceof IssuerSerial)
+ {
+ return (IssuerSerial)obj;
+ }
+
+ if (obj != null)
+ {
+ return new IssuerSerial(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static IssuerSerial getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ private IssuerSerial(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2 && seq.size() != 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ issuer = GeneralNames.getInstance(seq.getObjectAt(0));
+ serial = ASN1Integer.getInstance(seq.getObjectAt(1));
+
+ if (seq.size() == 3)
+ {
+ issuerUID = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+ }
+
+ public IssuerSerial(
+ GeneralNames issuer,
+ BigInteger serial)
+ {
+ this(issuer, new ASN1Integer(serial));
+ }
+
+ public IssuerSerial(
+ GeneralNames issuer,
+ ASN1Integer serial)
+ {
+ this.issuer = issuer;
+ this.serial = serial;
+ }
+
+ public GeneralNames getIssuer()
+ {
+ return issuer;
+ }
+
+ public ASN1Integer getSerial()
+ {
+ return serial;
+ }
+
+ public DERBitString getIssuerUID()
+ {
+ return issuerUID;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * IssuerSerial ::= SEQUENCE {
+ * issuer GeneralNames,
+ * serial CertificateSerialNumber,
+ * issuerUID UniqueIdentifier OPTIONAL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(issuer);
+ v.add(serial);
+
+ if (issuerUID != null)
+ {
+ v.add(issuerUID);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/IssuingDistributionPoint.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,274 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Boolean;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ *
+ * IssuingDistributionPoint ::= SEQUENCE {
+ * distributionPoint [0] DistributionPointName OPTIONAL,
+ * onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
+ * onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
+ * onlySomeReasons [3] ReasonFlags OPTIONAL,
+ * indirectCRL [4] BOOLEAN DEFAULT FALSE,
+ * onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
+ *
+ */
+public class IssuingDistributionPoint
+ extends ASN1Object
+{
+ private DistributionPointName distributionPoint;
+
+ private boolean onlyContainsUserCerts;
+
+ private boolean onlyContainsCACerts;
+
+ private ReasonFlags onlySomeReasons;
+
+ private boolean indirectCRL;
+
+ private boolean onlyContainsAttributeCerts;
+
+ private ASN1Sequence seq;
+
+ public static IssuingDistributionPoint getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static IssuingDistributionPoint getInstance(
+ Object obj)
+ {
+ if (obj instanceof IssuingDistributionPoint)
+ {
+ return (IssuingDistributionPoint)obj;
+ }
+ else if (obj != null)
+ {
+ return new IssuingDistributionPoint(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from given details.
+ *
+ * @param distributionPoint
+ * May contain an URI as pointer to most current CRL.
+ * @param onlyContainsUserCerts Covers revocation information for end certificates.
+ * @param onlyContainsCACerts Covers revocation information for CA certificates.
+ *
+ * @param onlySomeReasons
+ * Which revocation reasons does this point cover.
+ * @param indirectCRL
+ * If true
then the CRL contains revocation
+ * information about certificates ssued by other CAs.
+ * @param onlyContainsAttributeCerts Covers revocation information for attribute certificates.
+ */
+ public IssuingDistributionPoint(
+ DistributionPointName distributionPoint,
+ boolean onlyContainsUserCerts,
+ boolean onlyContainsCACerts,
+ ReasonFlags onlySomeReasons,
+ boolean indirectCRL,
+ boolean onlyContainsAttributeCerts)
+ {
+ this.distributionPoint = distributionPoint;
+ this.indirectCRL = indirectCRL;
+ this.onlyContainsAttributeCerts = onlyContainsAttributeCerts;
+ this.onlyContainsCACerts = onlyContainsCACerts;
+ this.onlyContainsUserCerts = onlyContainsUserCerts;
+ this.onlySomeReasons = onlySomeReasons;
+
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ if (distributionPoint != null)
+ { // CHOICE item so explicitly tagged
+ vec.add(new DERTaggedObject(true, 0, distributionPoint));
+ }
+ if (onlyContainsUserCerts)
+ {
+ vec.add(new DERTaggedObject(false, 1, ASN1Boolean.getInstance(true)));
+ }
+ if (onlyContainsCACerts)
+ {
+ vec.add(new DERTaggedObject(false, 2, ASN1Boolean.getInstance(true)));
+ }
+ if (onlySomeReasons != null)
+ {
+ vec.add(new DERTaggedObject(false, 3, onlySomeReasons));
+ }
+ if (indirectCRL)
+ {
+ vec.add(new DERTaggedObject(false, 4, ASN1Boolean.getInstance(true)));
+ }
+ if (onlyContainsAttributeCerts)
+ {
+ vec.add(new DERTaggedObject(false, 5, ASN1Boolean.getInstance(true)));
+ }
+
+ seq = new DERSequence(vec);
+ }
+
+ /**
+ * Shorthand Constructor from given details.
+ *
+ * @param distributionPoint
+ * May contain an URI as pointer to most current CRL.
+ * @param indirectCRL
+ * If true
then the CRL contains revocation
+ * information about certificates ssued by other CAs.
+ * @param onlyContainsAttributeCerts Covers revocation information for attribute certificates.
+ */
+ public IssuingDistributionPoint(
+ DistributionPointName distributionPoint,
+ boolean indirectCRL,
+ boolean onlyContainsAttributeCerts)
+ {
+ this(distributionPoint, false, false, null, indirectCRL, onlyContainsAttributeCerts);
+ }
+
+ /**
+ * Constructor from ASN1Sequence
+ */
+ private IssuingDistributionPoint(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
+
+ switch (o.getTagNo())
+ {
+ case 0:
+ // CHOICE so explicit
+ distributionPoint = DistributionPointName.getInstance(o, true);
+ break;
+ case 1:
+ onlyContainsUserCerts = ASN1Boolean.getInstance(o, false).isTrue();
+ break;
+ case 2:
+ onlyContainsCACerts = ASN1Boolean.getInstance(o, false).isTrue();
+ break;
+ case 3:
+ onlySomeReasons = new ReasonFlags(ReasonFlags.getInstance(o, false));
+ break;
+ case 4:
+ indirectCRL = ASN1Boolean.getInstance(o, false).isTrue();
+ break;
+ case 5:
+ onlyContainsAttributeCerts = ASN1Boolean.getInstance(o, false).isTrue();
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "unknown tag in IssuingDistributionPoint");
+ }
+ }
+ }
+
+ public boolean onlyContainsUserCerts()
+ {
+ return onlyContainsUserCerts;
+ }
+
+ public boolean onlyContainsCACerts()
+ {
+ return onlyContainsCACerts;
+ }
+
+ public boolean isIndirectCRL()
+ {
+ return indirectCRL;
+ }
+
+ public boolean onlyContainsAttributeCerts()
+ {
+ return onlyContainsAttributeCerts;
+ }
+
+ /**
+ * @return Returns the distributionPoint.
+ */
+ public DistributionPointName getDistributionPoint()
+ {
+ return distributionPoint;
+ }
+
+ /**
+ * @return Returns the onlySomeReasons.
+ */
+ public ReasonFlags getOnlySomeReasons()
+ {
+ return onlySomeReasons;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+
+ public String toString()
+ {
+ String sep = System.getProperty("line.separator");
+ StringBuffer buf = new StringBuffer();
+
+ buf.append("IssuingDistributionPoint: [");
+ buf.append(sep);
+ if (distributionPoint != null)
+ {
+ appendObject(buf, sep, "distributionPoint", distributionPoint.toString());
+ }
+ if (onlyContainsUserCerts)
+ {
+ appendObject(buf, sep, "onlyContainsUserCerts", booleanToString(onlyContainsUserCerts));
+ }
+ if (onlyContainsCACerts)
+ {
+ appendObject(buf, sep, "onlyContainsCACerts", booleanToString(onlyContainsCACerts));
+ }
+ if (onlySomeReasons != null)
+ {
+ appendObject(buf, sep, "onlySomeReasons", onlySomeReasons.toString());
+ }
+ if (onlyContainsAttributeCerts)
+ {
+ appendObject(buf, sep, "onlyContainsAttributeCerts", booleanToString(onlyContainsAttributeCerts));
+ }
+ if (indirectCRL)
+ {
+ appendObject(buf, sep, "indirectCRL", booleanToString(indirectCRL));
+ }
+ buf.append("]");
+ buf.append(sep);
+ return buf.toString();
+ }
+
+ private void appendObject(StringBuffer buf, String sep, String name, String value)
+ {
+ String indent = " ";
+
+ buf.append(indent);
+ buf.append(name);
+ buf.append(":");
+ buf.append(sep);
+ buf.append(indent);
+ buf.append(indent);
+ buf.append(value);
+ buf.append(sep);
+ }
+
+ private String booleanToString(boolean value)
+ {
+ return value ? "true" : "false";
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/KeyPurposeId.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/KeyPurposeId.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/KeyPurposeId.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/KeyPurposeId.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,151 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+
+/**
+ * The KeyPurposeId object.
+ *
+ * KeyPurposeId ::= OBJECT IDENTIFIER
+ *
+ * id-kp ::= OBJECT IDENTIFIER { iso(1) identified-organization(3)
+ * dod(6) internet(1) security(5) mechanisms(5) pkix(7) 3}
+ *
+ *
+ */
+public class KeyPurposeId
+ extends ASN1Object
+{
+ private static final ASN1ObjectIdentifier id_kp = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.3");
+
+ /**
+ * { 2 5 29 37 0 }
+ */
+ public static final KeyPurposeId anyExtendedKeyUsage = new KeyPurposeId(Extension.extendedKeyUsage.branch("0"));
+
+ /**
+ * { id-kp 1 }
+ */
+ public static final KeyPurposeId id_kp_serverAuth = new KeyPurposeId(id_kp.branch("1"));
+ /**
+ * { id-kp 2 }
+ */
+ public static final KeyPurposeId id_kp_clientAuth = new KeyPurposeId(id_kp.branch("2"));
+ /**
+ * { id-kp 3 }
+ */
+ public static final KeyPurposeId id_kp_codeSigning = new KeyPurposeId(id_kp.branch("3"));
+ /**
+ * { id-kp 4 }
+ */
+ public static final KeyPurposeId id_kp_emailProtection = new KeyPurposeId(id_kp.branch("4"));
+ /**
+ * Usage deprecated by RFC4945 - was { id-kp 5 }
+ */
+ public static final KeyPurposeId id_kp_ipsecEndSystem = new KeyPurposeId(id_kp.branch("5"));
+ /**
+ * Usage deprecated by RFC4945 - was { id-kp 6 }
+ */
+ public static final KeyPurposeId id_kp_ipsecTunnel = new KeyPurposeId(id_kp.branch("6"));
+ /**
+ * Usage deprecated by RFC4945 - was { idkp 7 }
+ */
+ public static final KeyPurposeId id_kp_ipsecUser = new KeyPurposeId(id_kp.branch("7"));
+ /**
+ * { id-kp 8 }
+ */
+ public static final KeyPurposeId id_kp_timeStamping = new KeyPurposeId(id_kp.branch("8"));
+ /**
+ * { id-kp 9 }
+ */
+ public static final KeyPurposeId id_kp_OCSPSigning = new KeyPurposeId(id_kp.branch("9"));
+ /**
+ * { id-kp 10 }
+ */
+ public static final KeyPurposeId id_kp_dvcs = new KeyPurposeId(id_kp.branch("10"));
+ /**
+ * { id-kp 11 }
+ */
+ public static final KeyPurposeId id_kp_sbgpCertAAServerAuth = new KeyPurposeId(id_kp.branch("11"));
+ /**
+ * { id-kp 12 }
+ */
+ public static final KeyPurposeId id_kp_scvp_responder = new KeyPurposeId(id_kp.branch("12"));
+ /**
+ * { id-kp 13 }
+ */
+ public static final KeyPurposeId id_kp_eapOverPPP = new KeyPurposeId(id_kp.branch("13"));
+ /**
+ * { id-kp 14 }
+ */
+ public static final KeyPurposeId id_kp_eapOverLAN = new KeyPurposeId(id_kp.branch("14"));
+ /**
+ * { id-kp 15 }
+ */
+ public static final KeyPurposeId id_kp_scvpServer = new KeyPurposeId(id_kp.branch("15"));
+ /**
+ * { id-kp 16 }
+ */
+ public static final KeyPurposeId id_kp_scvpClient = new KeyPurposeId(id_kp.branch("16"));
+ /**
+ * { id-kp 17 }
+ */
+ public static final KeyPurposeId id_kp_ipsecIKE = new KeyPurposeId(id_kp.branch("17"));
+ /**
+ * { id-kp 18 }
+ */
+ public static final KeyPurposeId id_kp_capwapAC = new KeyPurposeId(id_kp.branch("18"));
+ /**
+ * { id-kp 19 }
+ */
+ public static final KeyPurposeId id_kp_capwapWTP = new KeyPurposeId(id_kp.branch("19"));
+
+ //
+ // microsoft key purpose ids
+ //
+ /**
+ * { 1 3 6 1 4 1 311 20 2 2 }
+ */
+ public static final KeyPurposeId id_kp_smartcardlogon = new KeyPurposeId(new ASN1ObjectIdentifier("1.3.6.1.4.1.311.20.2.2"));
+
+ private ASN1ObjectIdentifier id;
+
+ private KeyPurposeId(ASN1ObjectIdentifier id)
+ {
+ this.id = id;
+ }
+
+ /**
+ * @deprecated use getInstance and an OID or one of the constants above.
+ * @param id string representation of an OID.
+ */
+ public KeyPurposeId(String id)
+ {
+ this(new ASN1ObjectIdentifier(id));
+ }
+
+ public static KeyPurposeId getInstance(Object o)
+ {
+ if (o instanceof KeyPurposeId)
+ {
+ return (KeyPurposeId)o;
+ }
+ else if (o != null)
+ {
+ return new KeyPurposeId(ASN1ObjectIdentifier.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return id;
+ }
+
+ public String getId()
+ {
+ return id.getId();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/KeyUsage.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/KeyUsage.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/KeyUsage.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/KeyUsage.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,102 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+
+/**
+ * The KeyUsage object.
+ *
+ * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
+ *
+ * KeyUsage ::= BIT STRING {
+ * digitalSignature (0),
+ * nonRepudiation (1),
+ * keyEncipherment (2),
+ * dataEncipherment (3),
+ * keyAgreement (4),
+ * keyCertSign (5),
+ * cRLSign (6),
+ * encipherOnly (7),
+ * decipherOnly (8) }
+ *
+ */
+public class KeyUsage
+ extends ASN1Object
+{
+ public static final int digitalSignature = (1 << 7);
+ public static final int nonRepudiation = (1 << 6);
+ public static final int keyEncipherment = (1 << 5);
+ public static final int dataEncipherment = (1 << 4);
+ public static final int keyAgreement = (1 << 3);
+ public static final int keyCertSign = (1 << 2);
+ public static final int cRLSign = (1 << 1);
+ public static final int encipherOnly = (1 << 0);
+ public static final int decipherOnly = (1 << 15);
+
+ private DERBitString bitString;
+
+ public static KeyUsage getInstance(Object obj) // needs to be DERBitString for other VMs
+ {
+ if (obj instanceof KeyUsage)
+ {
+ return (KeyUsage)obj;
+ }
+ else if (obj != null)
+ {
+ return new KeyUsage(DERBitString.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static KeyUsage fromExtensions(Extensions extensions)
+ {
+ return KeyUsage.getInstance(extensions.getExtensionParsedValue(Extension.keyUsage));
+ }
+
+ /**
+ * Basic constructor.
+ *
+ * @param usage - the bitwise OR of the Key Usage flags giving the
+ * allowed uses for the key.
+ * e.g. (KeyUsage.keyEncipherment | KeyUsage.dataEncipherment)
+ */
+ public KeyUsage(
+ int usage)
+ {
+ this.bitString = new DERBitString(usage);
+ }
+
+ private KeyUsage(
+ DERBitString bitString)
+ {
+ this.bitString = bitString;
+ }
+
+ public byte[] getBytes()
+ {
+ return bitString.getBytes();
+ }
+
+ public int getPadBits()
+ {
+ return bitString.getPadBits();
+ }
+
+ public String toString()
+ {
+ byte[] data = bitString.getBytes();
+
+ if (data.length == 1)
+ {
+ return "KeyUsage: 0x" + Integer.toHexString(data[0] & 0xff);
+ }
+ return "KeyUsage: 0x" + Integer.toHexString((data[1] & 0xff) << 8 | (data[0] & 0xff));
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return bitString;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/NameConstraints.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/NameConstraints.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/NameConstraints.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/NameConstraints.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,118 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class NameConstraints
+ extends ASN1Object
+{
+ private GeneralSubtree[] permitted, excluded;
+
+ public static NameConstraints getInstance(Object obj)
+ {
+ if (obj instanceof NameConstraints)
+ {
+ return (NameConstraints)obj;
+ }
+ if (obj != null)
+ {
+ return new NameConstraints(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private NameConstraints(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ while (e.hasMoreElements())
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
+ switch (o.getTagNo())
+ {
+ case 0:
+ permitted = createArray(ASN1Sequence.getInstance(o, false));
+ break;
+ case 1:
+ excluded = createArray(ASN1Sequence.getInstance(o, false));
+ break;
+ }
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ *
+ * permitted and excluded are arrays of GeneralSubtree objects.
+ *
+ * @param permitted
+ * Permitted subtrees
+ * @param excluded
+ * Excludes subtrees
+ */
+ public NameConstraints(
+ GeneralSubtree[] permitted,
+ GeneralSubtree[] excluded)
+ {
+ if (permitted != null)
+ {
+ this.permitted = permitted;
+ }
+
+ if (excluded != null)
+ {
+ this.excluded = excluded;
+ }
+ }
+
+ private GeneralSubtree[] createArray(ASN1Sequence subtree)
+ {
+ GeneralSubtree[] ar = new GeneralSubtree[subtree.size()];
+
+ for (int i = 0; i != ar.length; i++)
+ {
+ ar[i] = GeneralSubtree.getInstance(subtree.getObjectAt(i));
+ }
+
+ return ar;
+ }
+
+ public GeneralSubtree[] getPermittedSubtrees()
+ {
+ return permitted;
+ }
+
+ public GeneralSubtree[] getExcludedSubtrees()
+ {
+ return excluded;
+ }
+
+ /*
+ * NameConstraints ::= SEQUENCE { permittedSubtrees [0] GeneralSubtrees
+ * OPTIONAL, excludedSubtrees [1] GeneralSubtrees OPTIONAL }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (permitted != null)
+ {
+ v.add(new DERTaggedObject(false, 0, new DERSequence(permitted)));
+ }
+
+ if (excluded != null)
+ {
+ v.add(new DERTaggedObject(false, 1, new DERSequence(excluded)));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/NoticeReference.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/NoticeReference.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/NoticeReference.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/NoticeReference.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,170 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * NoticeReference
class, used in
+ * CertificatePolicies
X509 V3 extensions
+ * (in policy qualifiers).
+ *
+ *
+ * NoticeReference ::= SEQUENCE {
+ * organization DisplayText,
+ * noticeNumbers SEQUENCE OF INTEGER }
+ *
+ *
+ *
+ * @see PolicyQualifierInfo
+ * @see PolicyInformation
+ */
+public class NoticeReference
+ extends ASN1Object
+{
+ private DisplayText organization;
+ private ASN1Sequence noticeNumbers;
+
+ private static ASN1EncodableVector convertVector(Vector numbers)
+ {
+ ASN1EncodableVector av = new ASN1EncodableVector();
+
+ Enumeration it = numbers.elements();
+
+ while (it.hasMoreElements())
+ {
+ Object o = it.nextElement();
+ ASN1Integer di;
+
+ if (o instanceof BigInteger)
+ {
+ di = new ASN1Integer((BigInteger)o);
+ }
+ else if (o instanceof Integer)
+ {
+ di = new ASN1Integer(((Integer)o).intValue());
+ }
+ else
+ {
+ throw new IllegalArgumentException();
+ }
+
+ av.add(di);
+ }
+ return av;
+ }
+
+ /**
+ * Creates a new NoticeReference
instance.
+ *
+ * @param organization a String
value
+ * @param numbers a Vector
value
+ */
+ public NoticeReference(
+ String organization,
+ Vector numbers)
+ {
+ this(organization, convertVector(numbers));
+ }
+
+ /**
+ * Creates a new NoticeReference
instance.
+ *
+ * @param organization a String
value
+ * @param noticeNumbers an ASN1EncodableVector
value
+ */
+ public NoticeReference(
+ String organization,
+ ASN1EncodableVector noticeNumbers)
+ {
+ this(new DisplayText(organization), noticeNumbers);
+ }
+
+ /**
+ * Creates a new NoticeReference
instance.
+ *
+ * @param organization displayText
+ * @param noticeNumbers an ASN1EncodableVector
value
+ */
+ public NoticeReference(
+ DisplayText organization,
+ ASN1EncodableVector noticeNumbers)
+ {
+ this.organization = organization;
+ this.noticeNumbers = new DERSequence(noticeNumbers);
+ }
+
+ /**
+ * Creates a new NoticeReference
instance.
+ * Useful for reconstructing a NoticeReference
+ * instance from its encodable/encoded form.
+ *
+ * @param as an ASN1Sequence
value obtained from either
+ * calling @{link toASN1Primitive()} for a NoticeReference
+ * instance or from parsing it from a DER-encoded stream.
+ */
+ private NoticeReference(
+ ASN1Sequence as)
+ {
+ if (as.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + as.size());
+ }
+
+ organization = DisplayText.getInstance(as.getObjectAt(0));
+ noticeNumbers = ASN1Sequence.getInstance(as.getObjectAt(1));
+ }
+
+ public static NoticeReference getInstance(
+ Object as)
+ {
+ if (as instanceof NoticeReference)
+ {
+ return (NoticeReference)as;
+ }
+ else if (as != null)
+ {
+ return new NoticeReference(ASN1Sequence.getInstance(as));
+ }
+
+ return null;
+ }
+
+ public DisplayText getOrganization()
+ {
+ return organization;
+ }
+
+ public ASN1Integer[] getNoticeNumbers()
+ {
+ ASN1Integer[] tmp = new ASN1Integer[noticeNumbers.size()];
+
+ for (int i = 0; i != noticeNumbers.size(); i++)
+ {
+ tmp[i] = ASN1Integer.getInstance(noticeNumbers.getObjectAt(i));
+ }
+
+ return tmp;
+ }
+
+ /**
+ * Describe toASN1Object
method here.
+ *
+ * @return a ASN1Primitive
value
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector av = new ASN1EncodableVector();
+ av.add (organization);
+ av.add (noticeNumbers);
+ return new DERSequence (av);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/ObjectDigestInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/ObjectDigestInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/ObjectDigestInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/ObjectDigestInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,190 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Enumerated;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * ObjectDigestInfo ASN.1 structure used in v2 attribute certificates.
+ *
+ *
+ *
+ * ObjectDigestInfo ::= SEQUENCE {
+ * digestedObjectType ENUMERATED {
+ * publicKey (0),
+ * publicKeyCert (1),
+ * otherObjectTypes (2) },
+ * -- otherObjectTypes MUST NOT
+ * -- be used in this profile
+ * otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
+ * digestAlgorithm AlgorithmIdentifier,
+ * objectDigest BIT STRING
+ * }
+ *
+ *
+ *
+ */
+public class ObjectDigestInfo
+ extends ASN1Object
+{
+ /**
+ * The public key is hashed.
+ */
+ public final static int publicKey = 0;
+
+ /**
+ * The public key certificate is hashed.
+ */
+ public final static int publicKeyCert = 1;
+
+ /**
+ * An other object is hashed.
+ */
+ public final static int otherObjectDigest = 2;
+
+ ASN1Enumerated digestedObjectType;
+
+ ASN1ObjectIdentifier otherObjectTypeID;
+
+ AlgorithmIdentifier digestAlgorithm;
+
+ DERBitString objectDigest;
+
+ public static ObjectDigestInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof ObjectDigestInfo)
+ {
+ return (ObjectDigestInfo)obj;
+ }
+
+ if (obj != null)
+ {
+ return new ObjectDigestInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static ObjectDigestInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ /**
+ * Constructor from given details.
+ *
+ * If digestedObjectType
is not {@link #publicKeyCert} or
+ * {@link #publicKey} otherObjectTypeID
must be given,
+ * otherwise it is ignored.
+ *
+ * @param digestedObjectType The digest object type.
+ * @param otherObjectTypeID The object type ID for
+ * otherObjectDigest
.
+ * @param digestAlgorithm The algorithm identifier for the hash.
+ * @param objectDigest The hash value.
+ */
+ public ObjectDigestInfo(
+ int digestedObjectType,
+ ASN1ObjectIdentifier otherObjectTypeID,
+ AlgorithmIdentifier digestAlgorithm,
+ byte[] objectDigest)
+ {
+ this.digestedObjectType = new ASN1Enumerated(digestedObjectType);
+ if (digestedObjectType == otherObjectDigest)
+ {
+ this.otherObjectTypeID = otherObjectTypeID;
+ }
+
+ this.digestAlgorithm = digestAlgorithm;
+ this.objectDigest = new DERBitString(objectDigest);
+ }
+
+ private ObjectDigestInfo(
+ ASN1Sequence seq)
+ {
+ if (seq.size() > 4 || seq.size() < 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ digestedObjectType = ASN1Enumerated.getInstance(seq.getObjectAt(0));
+
+ int offset = 0;
+
+ if (seq.size() == 4)
+ {
+ otherObjectTypeID = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(1));
+ offset++;
+ }
+
+ digestAlgorithm = AlgorithmIdentifier.getInstance(seq.getObjectAt(1 + offset));
+
+ objectDigest = DERBitString.getInstance(seq.getObjectAt(2 + offset));
+ }
+
+ public ASN1Enumerated getDigestedObjectType()
+ {
+ return digestedObjectType;
+ }
+
+ public ASN1ObjectIdentifier getOtherObjectTypeID()
+ {
+ return otherObjectTypeID;
+ }
+
+ public AlgorithmIdentifier getDigestAlgorithm()
+ {
+ return digestAlgorithm;
+ }
+
+ public DERBitString getObjectDigest()
+ {
+ return objectDigest;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ *
+ *
+ * ObjectDigestInfo ::= SEQUENCE {
+ * digestedObjectType ENUMERATED {
+ * publicKey (0),
+ * publicKeyCert (1),
+ * otherObjectTypes (2) },
+ * -- otherObjectTypes MUST NOT
+ * -- be used in this profile
+ * otherObjectTypeID OBJECT IDENTIFIER OPTIONAL,
+ * digestAlgorithm AlgorithmIdentifier,
+ * objectDigest BIT STRING
+ * }
+ *
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(digestedObjectType);
+
+ if (otherObjectTypeID != null)
+ {
+ v.add(otherObjectTypeID);
+ }
+
+ v.add(digestAlgorithm);
+ v.add(objectDigest);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/PolicyInformation.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/PolicyInformation.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/PolicyInformation.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/PolicyInformation.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,87 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class PolicyInformation
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier policyIdentifier;
+ private ASN1Sequence policyQualifiers;
+
+ private PolicyInformation(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ policyIdentifier = ASN1ObjectIdentifier.getInstance(seq.getObjectAt(0));
+
+ if (seq.size() > 1)
+ {
+ policyQualifiers = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+ }
+
+ public PolicyInformation(
+ ASN1ObjectIdentifier policyIdentifier)
+ {
+ this.policyIdentifier = policyIdentifier;
+ }
+
+ public PolicyInformation(
+ ASN1ObjectIdentifier policyIdentifier,
+ ASN1Sequence policyQualifiers)
+ {
+ this.policyIdentifier = policyIdentifier;
+ this.policyQualifiers = policyQualifiers;
+ }
+
+ public static PolicyInformation getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof PolicyInformation)
+ {
+ return (PolicyInformation)obj;
+ }
+
+ return new PolicyInformation(ASN1Sequence.getInstance(obj));
+ }
+
+ public ASN1ObjectIdentifier getPolicyIdentifier()
+ {
+ return policyIdentifier;
+ }
+
+ public ASN1Sequence getPolicyQualifiers()
+ {
+ return policyQualifiers;
+ }
+
+ /*
+ * PolicyInformation ::= SEQUENCE {
+ * policyIdentifier CertPolicyId,
+ * policyQualifiers SEQUENCE SIZE (1..MAX) OF
+ * PolicyQualifierInfo OPTIONAL }
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(policyIdentifier);
+
+ if (policyQualifiers != null)
+ {
+ v.add(policyQualifiers);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/PolicyMappings.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/PolicyMappings.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/PolicyMappings.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/PolicyMappings.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,107 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * PolicyMappings V3 extension, described in RFC3280.
+ *
+ * PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
+ * issuerDomainPolicy CertPolicyId,
+ * subjectDomainPolicy CertPolicyId }
+ *
+ *
+ * @see RFC 3280, section 4.2.1.6
+ */
+public class PolicyMappings
+ extends ASN1Object
+{
+ ASN1Sequence seq = null;
+
+ public static PolicyMappings getInstance(Object obj)
+ {
+ if (obj instanceof PolicyMappings)
+ {
+ return (PolicyMappings)obj;
+ }
+ if (obj != null)
+ {
+ return new PolicyMappings(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new PolicyMappings
instance.
+ *
+ * @param seq an ASN1Sequence
constructed as specified
+ * in RFC 3280
+ */
+ private PolicyMappings(ASN1Sequence seq)
+ {
+ this.seq = seq;
+ }
+
+ /**
+ * Creates a new PolicyMappings
instance.
+ *
+ * @param mappings a HashMap
value that maps
+ * String
oids
+ * to other String
oids.
+ * @deprecated use CertPolicyId constructors.
+ */
+ public PolicyMappings(Hashtable mappings)
+ {
+ ASN1EncodableVector dev = new ASN1EncodableVector();
+ Enumeration it = mappings.keys();
+
+ while (it.hasMoreElements())
+ {
+ String idp = (String)it.nextElement();
+ String sdp = (String)mappings.get(idp);
+ ASN1EncodableVector dv = new ASN1EncodableVector();
+ dv.add(new ASN1ObjectIdentifier(idp));
+ dv.add(new ASN1ObjectIdentifier(sdp));
+ dev.add(new DERSequence(dv));
+ }
+
+ seq = new DERSequence(dev);
+ }
+
+ public PolicyMappings(CertPolicyId issuerDomainPolicy, CertPolicyId subjectDomainPolicy)
+ {
+ ASN1EncodableVector dv = new ASN1EncodableVector();
+ dv.add(issuerDomainPolicy);
+ dv.add(subjectDomainPolicy);
+
+ seq = new DERSequence(new DERSequence(dv));
+ }
+
+ public PolicyMappings(CertPolicyId[] issuerDomainPolicy, CertPolicyId[] subjectDomainPolicy)
+ {
+ ASN1EncodableVector dev = new ASN1EncodableVector();
+
+ for (int i = 0; i != issuerDomainPolicy.length; i++)
+ {
+ ASN1EncodableVector dv = new ASN1EncodableVector();
+ dv.add(issuerDomainPolicy[i]);
+ dv.add(subjectDomainPolicy[i]);
+ dev.add(new DERSequence(dv));
+ }
+
+ seq = new DERSequence(dev);
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/PolicyQualifierId.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/PolicyQualifierId.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/PolicyQualifierId.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/PolicyQualifierId.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,31 @@
+
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * PolicyQualifierId, used in the CertificatePolicies
+ * X509V3 extension.
+ *
+ *
+ * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
+ * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 }
+ * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 }
+ * PolicyQualifierId ::=
+ * OBJECT IDENTIFIER (id-qt-cps | id-qt-unotice)
+ *
+ */
+public class PolicyQualifierId extends ASN1ObjectIdentifier
+{
+ private static final String id_qt = "1.3.6.1.5.5.7.2";
+
+ private PolicyQualifierId(String id)
+ {
+ super(id);
+ }
+
+ public static final PolicyQualifierId id_qt_cps =
+ new PolicyQualifierId(id_qt + ".1");
+ public static final PolicyQualifierId id_qt_unotice =
+ new PolicyQualifierId(id_qt + ".2");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/PolicyQualifierInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,114 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * Policy qualifiers, used in the X509V3 CertificatePolicies
+ * extension.
+ *
+ *
+ * PolicyQualifierInfo ::= SEQUENCE {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId }
+ *
+ */
+public class PolicyQualifierInfo
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier policyQualifierId;
+ private ASN1Encodable qualifier;
+
+ /**
+ * Creates a new PolicyQualifierInfo
instance.
+ *
+ * @param policyQualifierId a PolicyQualifierId
value
+ * @param qualifier the qualifier, defined by the above field.
+ */
+ public PolicyQualifierInfo(
+ ASN1ObjectIdentifier policyQualifierId,
+ ASN1Encodable qualifier)
+ {
+ this.policyQualifierId = policyQualifierId;
+ this.qualifier = qualifier;
+ }
+
+ /**
+ * Creates a new PolicyQualifierInfo
containing a
+ * cPSuri qualifier.
+ *
+ * @param cps the CPS (certification practice statement) uri as a
+ * String
.
+ */
+ public PolicyQualifierInfo(
+ String cps)
+ {
+ policyQualifierId = PolicyQualifierId.id_qt_cps;
+ qualifier = new DERIA5String (cps);
+ }
+
+ /**
+ * Creates a new PolicyQualifierInfo
instance.
+ *
+ * @param as PolicyQualifierInfo
X509 structure
+ * encoded as an ASN1Sequence.
+ */
+ public PolicyQualifierInfo(
+ ASN1Sequence as)
+ {
+ if (as.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + as.size());
+ }
+
+ policyQualifierId = ASN1ObjectIdentifier.getInstance(as.getObjectAt(0));
+ qualifier = as.getObjectAt(1);
+ }
+
+ public static PolicyQualifierInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof PolicyQualifierInfo)
+ {
+ return (PolicyQualifierInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new PolicyQualifierInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+
+ public ASN1ObjectIdentifier getPolicyQualifierId()
+ {
+ return policyQualifierId;
+ }
+
+ public ASN1Encodable getQualifier()
+ {
+ return qualifier;
+ }
+
+ /**
+ * Returns a DER-encodable representation of this instance.
+ *
+ * @return a ASN1Primitive
value
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector dev = new ASN1EncodableVector();
+ dev.add(policyQualifierId);
+ dev.add(qualifier);
+
+ return new DERSequence(dev);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/PrivateKeyUsagePeriod.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/PrivateKeyUsagePeriod.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/PrivateKeyUsagePeriod.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/PrivateKeyUsagePeriod.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,84 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERGeneralizedTime;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ *
+ * PrivateKeyUsagePeriod ::= SEQUENCE {
+ * notBefore [0] GeneralizedTime OPTIONAL,
+ * notAfter [1] GeneralizedTime OPTIONAL }
+ *
+ */
+public class PrivateKeyUsagePeriod
+ extends ASN1Object
+{
+ public static PrivateKeyUsagePeriod getInstance(Object obj)
+ {
+ if (obj instanceof PrivateKeyUsagePeriod)
+ {
+ return (PrivateKeyUsagePeriod)obj;
+ }
+
+ if (obj != null)
+ {
+ return new PrivateKeyUsagePeriod(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private DERGeneralizedTime _notBefore, _notAfter;
+
+ private PrivateKeyUsagePeriod(ASN1Sequence seq)
+ {
+ Enumeration en = seq.getObjects();
+ while (en.hasMoreElements())
+ {
+ ASN1TaggedObject tObj = (ASN1TaggedObject)en.nextElement();
+
+ if (tObj.getTagNo() == 0)
+ {
+ _notBefore = DERGeneralizedTime.getInstance(tObj, false);
+ }
+ else if (tObj.getTagNo() == 1)
+ {
+ _notAfter = DERGeneralizedTime.getInstance(tObj, false);
+ }
+ }
+ }
+
+ public DERGeneralizedTime getNotBefore()
+ {
+ return _notBefore;
+ }
+
+ public DERGeneralizedTime getNotAfter()
+ {
+ return _notAfter;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (_notBefore != null)
+ {
+ v.add(new DERTaggedObject(false, 0, _notBefore));
+ }
+ if (_notAfter != null)
+ {
+ v.add(new DERTaggedObject(false, 1, _notAfter));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/RSAPublicKeyStructure.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/RSAPublicKeyStructure.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/RSAPublicKeyStructure.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/RSAPublicKeyStructure.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,98 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * @deprecated use pdftk.org.bouncycastle.asn1.pkcs.RSAPublicKey
+ */
+public class RSAPublicKeyStructure
+ extends ASN1Object
+{
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+
+ public static RSAPublicKeyStructure getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static RSAPublicKeyStructure getInstance(
+ Object obj)
+ {
+ if(obj == null || obj instanceof RSAPublicKeyStructure)
+ {
+ return (RSAPublicKeyStructure)obj;
+ }
+
+ if(obj instanceof ASN1Sequence)
+ {
+ return new RSAPublicKeyStructure((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid RSAPublicKeyStructure: " + obj.getClass().getName());
+ }
+
+ public RSAPublicKeyStructure(
+ BigInteger modulus,
+ BigInteger publicExponent)
+ {
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ }
+
+ public RSAPublicKeyStructure(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ modulus = ASN1Integer.getInstance(e.nextElement()).getPositiveValue();
+ publicExponent = ASN1Integer.getInstance(e.nextElement()).getPositiveValue();
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+
+ /**
+ * This outputs the key in PKCS1v2 format.
+ *
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * }
+ *
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(getModulus()));
+ v.add(new ASN1Integer(getPublicExponent()));
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/ReasonFlags.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/ReasonFlags.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/ReasonFlags.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/ReasonFlags.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,85 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.DERBitString;
+
+/**
+ * The ReasonFlags object.
+ *
+ * ReasonFlags ::= BIT STRING {
+ * unused (0),
+ * keyCompromise (1),
+ * cACompromise (2),
+ * affiliationChanged (3),
+ * superseded (4),
+ * cessationOfOperation (5),
+ * certificateHold (6),
+ * privilegeWithdrawn (7),
+ * aACompromise (8) }
+ *
+ */
+public class ReasonFlags
+ extends DERBitString
+{
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int UNUSED = (1 << 7);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int KEY_COMPROMISE = (1 << 6);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int CA_COMPROMISE = (1 << 5);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int AFFILIATION_CHANGED = (1 << 4);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int SUPERSEDED = (1 << 3);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int CESSATION_OF_OPERATION = (1 << 2);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int CERTIFICATE_HOLD = (1 << 1);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int PRIVILEGE_WITHDRAWN = (1 << 0);
+ /**
+ * @deprecated use lower case version
+ */
+ public static final int AA_COMPROMISE = (1 << 15);
+
+ public static final int unused = (1 << 7);
+ public static final int keyCompromise = (1 << 6);
+ public static final int cACompromise = (1 << 5);
+ public static final int affiliationChanged = (1 << 4);
+ public static final int superseded = (1 << 3);
+ public static final int cessationOfOperation = (1 << 2);
+ public static final int certificateHold = (1 << 1);
+ public static final int privilegeWithdrawn = (1 << 0);
+ public static final int aACompromise = (1 << 15);
+
+ /**
+ * @param reasons - the bitwise OR of the Key Reason flags giving the
+ * allowed uses for the key.
+ */
+ public ReasonFlags(
+ int reasons)
+ {
+ super(getBytes(reasons), getPadBits(reasons));
+ }
+
+ public ReasonFlags(
+ DERBitString reasons)
+ {
+ super(reasons.getBytes(), reasons.getPadBits());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/RoleSyntax.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/RoleSyntax.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/RoleSyntax.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/RoleSyntax.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,237 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1String;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * Implementation of the RoleSyntax object as specified by the RFC3281.
+ *
+ *
+ * RoleSyntax ::= SEQUENCE {
+ * roleAuthority [0] GeneralNames OPTIONAL,
+ * roleName [1] GeneralName
+ * }
+ *
+ */
+public class RoleSyntax
+ extends ASN1Object
+{
+ private GeneralNames roleAuthority;
+ private GeneralName roleName;
+
+ /**
+ * RoleSyntax factory method.
+ * @param obj the object used to construct an instance of
+ * RoleSyntax
. It must be an instance of RoleSyntax
+ *
or ASN1Sequence
.
+ * @return the instance of RoleSyntax
built from the
+ * supplied object.
+ * @throws java.lang.IllegalArgumentException if the object passed
+ * to the factory is not an instance of RoleSyntax
or
+ * ASN1Sequence
.
+ */
+ public static RoleSyntax getInstance(
+ Object obj)
+ {
+
+ if (obj instanceof RoleSyntax)
+ {
+ return (RoleSyntax)obj;
+ }
+ else if (obj != null)
+ {
+ return new RoleSyntax(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor.
+ * @param roleAuthority the role authority of this RoleSyntax.
+ * @param roleName the role name of this RoleSyntax.
+ */
+ public RoleSyntax(
+ GeneralNames roleAuthority,
+ GeneralName roleName)
+ {
+ if(roleName == null ||
+ roleName.getTagNo() != GeneralName.uniformResourceIdentifier ||
+ ((ASN1String)roleName.getName()).getString().equals(""))
+ {
+ throw new IllegalArgumentException("the role name MUST be non empty and MUST " +
+ "use the URI option of GeneralName");
+ }
+ this.roleAuthority = roleAuthority;
+ this.roleName = roleName;
+ }
+
+ /**
+ * Constructor. Invoking this constructor is the same as invoking
+ * new RoleSyntax(null, roleName)
.
+ * @param roleName the role name of this RoleSyntax.
+ */
+ public RoleSyntax(
+ GeneralName roleName)
+ {
+ this(null, roleName);
+ }
+
+ /**
+ * Utility constructor. Takes a String
argument representing
+ * the role name, builds a GeneralName
to hold the role name
+ * and calls the constructor that takes a GeneralName
.
+ * @param roleName
+ */
+ public RoleSyntax(
+ String roleName)
+ {
+ this(new GeneralName(GeneralName.uniformResourceIdentifier,
+ (roleName == null)? "": roleName));
+ }
+
+ /**
+ * Constructor that builds an instance of RoleSyntax
by
+ * extracting the encoded elements from the ASN1Sequence
+ * object supplied.
+ * @param seq an instance of ASN1Sequence
that holds
+ * the encoded elements used to build this RoleSyntax
.
+ */
+ private RoleSyntax(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 1 || seq.size() > 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ for (int i = 0; i != seq.size(); i++)
+ {
+ ASN1TaggedObject taggedObject = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
+ switch (taggedObject.getTagNo())
+ {
+ case 0:
+ roleAuthority = GeneralNames.getInstance(taggedObject, false);
+ break;
+ case 1:
+ roleName = GeneralName.getInstance(taggedObject, true);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown tag in RoleSyntax");
+ }
+ }
+ }
+
+ /**
+ * Gets the role authority of this RoleSyntax.
+ * @return an instance of GeneralNames
holding the
+ * role authority of this RoleSyntax.
+ */
+ public GeneralNames getRoleAuthority()
+ {
+ return this.roleAuthority;
+ }
+
+ /**
+ * Gets the role name of this RoleSyntax.
+ * @return an instance of GeneralName
holding the
+ * role name of this RoleSyntax.
+ */
+ public GeneralName getRoleName()
+ {
+ return this.roleName;
+ }
+
+ /**
+ * Gets the role name as a java.lang.String
object.
+ * @return the role name of this RoleSyntax represented as a
+ * java.lang.String
object.
+ */
+ public String getRoleNameAsString()
+ {
+ ASN1String str = (ASN1String)this.roleName.getName();
+
+ return str.getString();
+ }
+
+ /**
+ * Gets the role authority as a String[]
object.
+ * @return the role authority of this RoleSyntax represented as a
+ * String[]
array.
+ */
+ public String[] getRoleAuthorityAsString()
+ {
+ if(roleAuthority == null)
+ {
+ return new String[0];
+ }
+
+ GeneralName[] names = roleAuthority.getNames();
+ String[] namesString = new String[names.length];
+ for(int i = 0; i < names.length; i++)
+ {
+ ASN1Encodable value = names[i].getName();
+ if(value instanceof ASN1String)
+ {
+ namesString[i] = ((ASN1String)value).getString();
+ }
+ else
+ {
+ namesString[i] = value.toString();
+ }
+ }
+ return namesString;
+ }
+
+ /**
+ * Implementation of the method toASN1Object
as
+ * required by the superclass ASN1Encodable
.
+ *
+ *
+ * RoleSyntax ::= SEQUENCE {
+ * roleAuthority [0] GeneralNames OPTIONAL,
+ * roleName [1] GeneralName
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ if(this.roleAuthority != null)
+ {
+ v.add(new DERTaggedObject(false, 0, roleAuthority));
+ }
+ v.add(new DERTaggedObject(true, 1, roleName));
+
+ return new DERSequence(v);
+ }
+
+ public String toString()
+ {
+ StringBuffer buff = new StringBuffer("Name: " + this.getRoleNameAsString() +
+ " - Auth: ");
+ if(this.roleAuthority == null || roleAuthority.getNames().length == 0)
+ {
+ buff.append("N/A");
+ }
+ else
+ {
+ String[] names = this.getRoleAuthorityAsString();
+ buff.append('[').append(names[0]);
+ for(int i = 1; i < names.length; i++)
+ {
+ buff.append(", ").append(names[i]);
+ }
+ buff.append(']');
+ }
+ return buff.toString();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/SubjectDirectoryAttributes.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/SubjectDirectoryAttributes.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/SubjectDirectoryAttributes.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/SubjectDirectoryAttributes.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,144 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * This extension may contain further X.500 attributes of the subject. See also
+ * RFC 3039.
+ *
+ *
+ * SubjectDirectoryAttributes ::= Attributes
+ * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+ * Attribute ::= SEQUENCE
+ * {
+ * type AttributeType
+ * values SET OF AttributeValue
+ * }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ *
+ *
+ * @see pdftk.org.bouncycastle.asn1.x500.style.BCStyle for AttributeType ObjectIdentifiers.
+ */
+public class SubjectDirectoryAttributes
+ extends ASN1Object
+{
+ private Vector attributes = new Vector();
+
+ public static SubjectDirectoryAttributes getInstance(
+ Object obj)
+ {
+ if (obj instanceof SubjectDirectoryAttributes)
+ {
+ return (SubjectDirectoryAttributes)obj;
+ }
+
+ if (obj != null)
+ {
+ return new SubjectDirectoryAttributes(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * The sequence is of type SubjectDirectoryAttributes:
+ *
+ *
+ * SubjectDirectoryAttributes ::= Attributes
+ * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+ * Attribute ::= SEQUENCE
+ * {
+ * type AttributeType
+ * values SET OF AttributeValue
+ * }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ *
+ *
+ * @param seq
+ * The ASN.1 sequence.
+ */
+ private SubjectDirectoryAttributes(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(e.nextElement());
+ attributes.addElement(Attribute.getInstance(s));
+ }
+ }
+
+ /**
+ * Constructor from a vector of attributes.
+ *
+ * The vector consists of attributes of type {@link Attribute Attribute}
+ *
+ * @param attributes
+ * The attributes.
+ *
+ */
+ public SubjectDirectoryAttributes(Vector attributes)
+ {
+ Enumeration e = attributes.elements();
+
+ while (e.hasMoreElements())
+ {
+ this.attributes.addElement(e.nextElement());
+ }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * SubjectDirectoryAttributes ::= Attributes
+ * Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+ * Attribute ::= SEQUENCE
+ * {
+ * type AttributeType
+ * values SET OF AttributeValue
+ * }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ *
+ *
+ * @return a ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ Enumeration e = attributes.elements();
+
+ while (e.hasMoreElements())
+ {
+
+ vec.add((Attribute)e.nextElement());
+ }
+
+ return new DERSequence(vec);
+ }
+
+ /**
+ * @return Returns the attributes.
+ */
+ public Vector getAttributes()
+ {
+ return attributes;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/SubjectKeyIdentifier.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,135 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+
+/**
+ * The SubjectKeyIdentifier object.
+ *
+ * SubjectKeyIdentifier::= OCTET STRING
+ *
+ */
+public class SubjectKeyIdentifier
+ extends ASN1Object
+{
+ private byte[] keyidentifier;
+
+ public static SubjectKeyIdentifier getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1OctetString.getInstance(obj, explicit));
+ }
+
+ public static SubjectKeyIdentifier getInstance(
+ Object obj)
+ {
+ if (obj instanceof SubjectKeyIdentifier)
+ {
+ return (SubjectKeyIdentifier)obj;
+ }
+ else if (obj != null)
+ {
+ return new SubjectKeyIdentifier(ASN1OctetString.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public static SubjectKeyIdentifier fromExtensions(Extensions extensions)
+ {
+ return SubjectKeyIdentifier.getInstance(extensions.getExtensionParsedValue(Extension.subjectKeyIdentifier));
+ }
+
+ public SubjectKeyIdentifier(
+ byte[] keyid)
+ {
+ this.keyidentifier = keyid;
+ }
+
+ protected SubjectKeyIdentifier(
+ ASN1OctetString keyid)
+ {
+ this.keyidentifier = keyid.getOctets();
+ }
+
+ public byte[] getKeyIdentifier()
+ {
+ return keyidentifier;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DEROctetString(keyidentifier);
+ }
+
+
+ /**
+ * Calculates the keyidentifier using a SHA1 hash over the BIT STRING
+ * from SubjectPublicKeyInfo as defined in RFC3280.
+ *
+ * @param spki the subject public key info.
+ * @deprecated
+ */
+ public SubjectKeyIdentifier(
+ SubjectPublicKeyInfo spki)
+ {
+ this.keyidentifier = getDigest(spki);
+ }
+
+ /**
+ * Return a RFC 3280 type 1 key identifier. As in:
+ *
+ * (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
+ * value of the BIT STRING subjectPublicKey (excluding the tag,
+ * length, and number of unused bits).
+ *
+ * @param keyInfo the key info object containing the subjectPublicKey field.
+ * @return the key identifier.
+ * @deprecated use pdftk.org.bouncycastle.cert.X509ExtensionUtils.createSubjectKeyIdentifier
+ */
+ public static SubjectKeyIdentifier createSHA1KeyIdentifier(SubjectPublicKeyInfo keyInfo)
+ {
+ return new SubjectKeyIdentifier(keyInfo);
+ }
+
+ /**
+ * Return a RFC 3280 type 2 key identifier. As in:
+ *
+ * (2) The keyIdentifier is composed of a four bit type field with
+ * the value 0100 followed by the least significant 60 bits of the
+ * SHA-1 hash of the value of the BIT STRING subjectPublicKey.
+ *
+ * @param keyInfo the key info object containing the subjectPublicKey field.
+ * @return the key identifier.
+ * @deprecated use pdftk.org.bouncycastle.cert.X509ExtensionUtils.createTruncatedSubjectKeyIdentifier
+ */
+ public static SubjectKeyIdentifier createTruncatedSHA1KeyIdentifier(SubjectPublicKeyInfo keyInfo)
+ {
+ byte[] dig = getDigest(keyInfo);
+ byte[] id = new byte[8];
+
+ System.arraycopy(dig, dig.length - 8, id, 0, id.length);
+
+ id[0] &= 0x0f;
+ id[0] |= 0x40;
+
+ return new SubjectKeyIdentifier(id);
+ }
+
+ private static byte[] getDigest(SubjectPublicKeyInfo spki)
+ {
+ Digest digest = new SHA1Digest();
+ byte[] resBuf = new byte[digest.getDigestSize()];
+
+ byte[] bytes = spki.getPublicKeyData().getBytes();
+ digest.update(bytes, 0, bytes.length);
+ digest.doFinal(resBuf, 0);
+ return resBuf;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,156 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.io.IOException;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1InputStream;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * The object that contains the public key stored in a certficate.
+ *
+ * The getEncoded() method in the public keys in the JCE produces a DER
+ * encoded one of these.
+ */
+public class SubjectPublicKeyInfo
+ extends ASN1Object
+{
+ private AlgorithmIdentifier algId;
+ private DERBitString keyData;
+
+ public static SubjectPublicKeyInfo getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static SubjectPublicKeyInfo getInstance(
+ Object obj)
+ {
+ if (obj instanceof SubjectPublicKeyInfo)
+ {
+ return (SubjectPublicKeyInfo)obj;
+ }
+ else if (obj != null)
+ {
+ return new SubjectPublicKeyInfo(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public SubjectPublicKeyInfo(
+ AlgorithmIdentifier algId,
+ ASN1Encodable publicKey)
+ throws IOException
+ {
+ this.keyData = new DERBitString(publicKey);
+ this.algId = algId;
+ }
+
+ public SubjectPublicKeyInfo(
+ AlgorithmIdentifier algId,
+ byte[] publicKey)
+ {
+ this.keyData = new DERBitString(publicKey);
+ this.algId = algId;
+ }
+
+ public SubjectPublicKeyInfo(
+ ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ this.algId = AlgorithmIdentifier.getInstance(e.nextElement());
+ this.keyData = DERBitString.getInstance(e.nextElement());
+ }
+
+ public AlgorithmIdentifier getAlgorithm()
+ {
+ return algId;
+ }
+
+ /**
+ * @deprecated use getAlgorithm()
+ * @return alg ID.
+ */
+ public AlgorithmIdentifier getAlgorithmId()
+ {
+ return algId;
+ }
+
+ /**
+ * for when the public key is an encoded object - if the bitstring
+ * can't be decoded this routine throws an IOException.
+ *
+ * @exception IOException - if the bit string doesn't represent a DER
+ * encoded object.
+ * @return the public key as an ASN.1 primitive.
+ */
+ public ASN1Primitive parsePublicKey()
+ throws IOException
+ {
+ ASN1InputStream aIn = new ASN1InputStream(keyData.getBytes());
+
+ return aIn.readObject();
+ }
+
+ /**
+ * for when the public key is an encoded object - if the bitstring
+ * can't be decoded this routine throws an IOException.
+ *
+ * @exception IOException - if the bit string doesn't represent a DER
+ * encoded object.
+ * @deprecated use parsePublicKey
+ * @return the public key as an ASN.1 primitive.
+ */
+ public ASN1Primitive getPublicKey()
+ throws IOException
+ {
+ ASN1InputStream aIn = new ASN1InputStream(keyData.getBytes());
+
+ return aIn.readObject();
+ }
+
+ /**
+ * for when the public key is raw bits.
+ *
+ * @return the public key as the raw bit string...
+ */
+ public DERBitString getPublicKeyData()
+ {
+ return keyData;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * publicKey BIT STRING }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(algId);
+ v.add(keyData);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/TBSCertList.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/TBSCertList.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/TBSCertList.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/TBSCertList.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,309 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERGeneralizedTime;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.DERUTCTime;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+
+/**
+ * PKIX RFC-2459 - TBSCertList object.
+ *
+ * TBSCertList ::= SEQUENCE {
+ * version Version OPTIONAL,
+ * -- if present, shall be v2
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * thisUpdate Time,
+ * nextUpdate Time OPTIONAL,
+ * revokedCertificates SEQUENCE OF SEQUENCE {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate Time,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, shall be v2
+ * } OPTIONAL,
+ * crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ * -- if present, shall be v2
+ * }
+ *
+ */
+public class TBSCertList
+ extends ASN1Object
+{
+ public static class CRLEntry
+ extends ASN1Object
+ {
+ ASN1Sequence seq;
+
+ Extensions crlEntryExtensions;
+
+ private CRLEntry(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 2 || seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ this.seq = seq;
+ }
+
+ public static CRLEntry getInstance(Object o)
+ {
+ if (o instanceof CRLEntry)
+ {
+ return ((CRLEntry)o);
+ }
+ else if (o != null)
+ {
+ return new CRLEntry(ASN1Sequence.getInstance(o));
+ }
+
+ return null;
+ }
+
+ public ASN1Integer getUserCertificate()
+ {
+ return ASN1Integer.getInstance(seq.getObjectAt(0));
+ }
+
+ public Time getRevocationDate()
+ {
+ return Time.getInstance(seq.getObjectAt(1));
+ }
+
+ public Extensions getExtensions()
+ {
+ if (crlEntryExtensions == null && seq.size() == 3)
+ {
+ crlEntryExtensions = Extensions.getInstance(seq.getObjectAt(2));
+ }
+
+ return crlEntryExtensions;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+
+ public boolean hasExtensions()
+ {
+ return seq.size() == 3;
+ }
+ }
+
+ private class RevokedCertificatesEnumeration
+ implements Enumeration
+ {
+ private final Enumeration en;
+
+ RevokedCertificatesEnumeration(Enumeration en)
+ {
+ this.en = en;
+ }
+
+ public boolean hasMoreElements()
+ {
+ return en.hasMoreElements();
+ }
+
+ public Object nextElement()
+ {
+ return CRLEntry.getInstance(en.nextElement());
+ }
+ }
+
+ private class EmptyEnumeration
+ implements Enumeration
+ {
+ public boolean hasMoreElements()
+ {
+ return false;
+ }
+
+ public Object nextElement()
+ {
+ return null; // TODO: check exception handling
+ }
+ }
+
+ ASN1Integer version;
+ AlgorithmIdentifier signature;
+ X500Name issuer;
+ Time thisUpdate;
+ Time nextUpdate;
+ ASN1Sequence revokedCertificates;
+ Extensions crlExtensions;
+
+ public static TBSCertList getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static TBSCertList getInstance(
+ Object obj)
+ {
+ if (obj instanceof TBSCertList)
+ {
+ return (TBSCertList)obj;
+ }
+ else if (obj != null)
+ {
+ return new TBSCertList(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public TBSCertList(
+ ASN1Sequence seq)
+ {
+ if (seq.size() < 3 || seq.size() > 7)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ int seqPos = 0;
+
+ if (seq.getObjectAt(seqPos) instanceof ASN1Integer)
+ {
+ version = ASN1Integer.getInstance(seq.getObjectAt(seqPos++));
+ }
+ else
+ {
+ version = null; // version is optional
+ }
+
+ signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqPos++));
+ issuer = X500Name.getInstance(seq.getObjectAt(seqPos++));
+ thisUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
+
+ if (seqPos < seq.size()
+ && (seq.getObjectAt(seqPos) instanceof DERUTCTime
+ || seq.getObjectAt(seqPos) instanceof DERGeneralizedTime
+ || seq.getObjectAt(seqPos) instanceof Time))
+ {
+ nextUpdate = Time.getInstance(seq.getObjectAt(seqPos++));
+ }
+
+ if (seqPos < seq.size()
+ && !(seq.getObjectAt(seqPos) instanceof DERTaggedObject))
+ {
+ revokedCertificates = ASN1Sequence.getInstance(seq.getObjectAt(seqPos++));
+ }
+
+ if (seqPos < seq.size()
+ && seq.getObjectAt(seqPos) instanceof DERTaggedObject)
+ {
+ crlExtensions = Extensions.getInstance(ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(seqPos), true));
+ }
+ }
+
+ public int getVersionNumber()
+ {
+ if (version == null)
+ {
+ return 1;
+ }
+ return version.getValue().intValue() + 1;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public AlgorithmIdentifier getSignature()
+ {
+ return signature;
+ }
+
+ public X500Name getIssuer()
+ {
+ return issuer;
+ }
+
+ public Time getThisUpdate()
+ {
+ return thisUpdate;
+ }
+
+ public Time getNextUpdate()
+ {
+ return nextUpdate;
+ }
+
+ public CRLEntry[] getRevokedCertificates()
+ {
+ if (revokedCertificates == null)
+ {
+ return new CRLEntry[0];
+ }
+
+ CRLEntry[] entries = new CRLEntry[revokedCertificates.size()];
+
+ for (int i = 0; i < entries.length; i++)
+ {
+ entries[i] = CRLEntry.getInstance(revokedCertificates.getObjectAt(i));
+ }
+
+ return entries;
+ }
+
+ public Enumeration getRevokedCertificateEnumeration()
+ {
+ if (revokedCertificates == null)
+ {
+ return new EmptyEnumeration();
+ }
+
+ return new RevokedCertificatesEnumeration(revokedCertificates.getObjects());
+ }
+
+ public Extensions getExtensions()
+ {
+ return crlExtensions;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (version != null)
+ {
+ v.add(version);
+ }
+ v.add(signature);
+ v.add(issuer);
+
+ v.add(thisUpdate);
+ if (nextUpdate != null)
+ {
+ v.add(nextUpdate);
+ }
+
+ // Add CRLEntries if they exist
+ if (revokedCertificates != null)
+ {
+ v.add(revokedCertificates);
+ }
+
+ if (crlExtensions != null)
+ {
+ v.add(new DERTaggedObject(0, crlExtensions));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/TBSCertificate.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/TBSCertificate.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/TBSCertificate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/TBSCertificate.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,192 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+
+/**
+ * The TBSCertificate object.
+ *
+ * TBSCertificate ::= SEQUENCE {
+ * version [ 0 ] Version DEFAULT v1(0),
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * extensions [ 3 ] Extensions OPTIONAL
+ * }
+ *
+ *
+ * Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
+ * will parse them, but you really shouldn't be creating new ones.
+ */
+public class TBSCertificate
+ extends ASN1Object
+{
+ ASN1Sequence seq;
+
+ ASN1Integer version;
+ ASN1Integer serialNumber;
+ AlgorithmIdentifier signature;
+ X500Name issuer;
+ Time startDate, endDate;
+ X500Name subject;
+ SubjectPublicKeyInfo subjectPublicKeyInfo;
+ DERBitString issuerUniqueId;
+ DERBitString subjectUniqueId;
+ Extensions extensions;
+
+ public static TBSCertificate getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static TBSCertificate getInstance(
+ Object obj)
+ {
+ if (obj instanceof TBSCertificate)
+ {
+ return (TBSCertificate)obj;
+ }
+ else if (obj != null)
+ {
+ return new TBSCertificate(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private TBSCertificate(
+ ASN1Sequence seq)
+ {
+ int seqStart = 0;
+
+ this.seq = seq;
+
+ //
+ // some certficates don't include a version number - we assume v1
+ //
+ if (seq.getObjectAt(0) instanceof DERTaggedObject)
+ {
+ version = ASN1Integer.getInstance((ASN1TaggedObject)seq.getObjectAt(0), true);
+ }
+ else
+ {
+ seqStart = -1; // field 0 is missing!
+ version = new ASN1Integer(0);
+ }
+
+ serialNumber = ASN1Integer.getInstance(seq.getObjectAt(seqStart + 1));
+
+ signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqStart + 2));
+ issuer = X500Name.getInstance(seq.getObjectAt(seqStart + 3));
+
+ //
+ // before and after dates
+ //
+ ASN1Sequence dates = (ASN1Sequence)seq.getObjectAt(seqStart + 4);
+
+ startDate = Time.getInstance(dates.getObjectAt(0));
+ endDate = Time.getInstance(dates.getObjectAt(1));
+
+ subject = X500Name.getInstance(seq.getObjectAt(seqStart + 5));
+
+ //
+ // public key info.
+ //
+ subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(seqStart + 6));
+
+ for (int extras = seq.size() - (seqStart + 6) - 1; extras > 0; extras--)
+ {
+ DERTaggedObject extra = (DERTaggedObject)seq.getObjectAt(seqStart + 6 + extras);
+
+ switch (extra.getTagNo())
+ {
+ case 1:
+ issuerUniqueId = DERBitString.getInstance(extra, false);
+ break;
+ case 2:
+ subjectUniqueId = DERBitString.getInstance(extra, false);
+ break;
+ case 3:
+ extensions = Extensions.getInstance(ASN1Sequence.getInstance(extra, true));
+ }
+ }
+ }
+
+ public int getVersionNumber()
+ {
+ return version.getValue().intValue() + 1;
+ }
+
+ public ASN1Integer getVersion()
+ {
+ return version;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public AlgorithmIdentifier getSignature()
+ {
+ return signature;
+ }
+
+ public X500Name getIssuer()
+ {
+ return issuer;
+ }
+
+ public Time getStartDate()
+ {
+ return startDate;
+ }
+
+ public Time getEndDate()
+ {
+ return endDate;
+ }
+
+ public X500Name getSubject()
+ {
+ return subject;
+ }
+
+ public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
+ {
+ return subjectPublicKeyInfo;
+ }
+
+ public DERBitString getIssuerUniqueId()
+ {
+ return issuerUniqueId;
+ }
+
+ public DERBitString getSubjectUniqueId()
+ {
+ return subjectUniqueId;
+ }
+
+ public Extensions getExtensions()
+ {
+ return extensions;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/TBSCertificateStructure.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/TBSCertificateStructure.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/TBSCertificateStructure.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/TBSCertificateStructure.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,194 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+
+/**
+ * The TBSCertificate object.
+ *
+ * TBSCertificate ::= SEQUENCE {
+ * version [ 0 ] Version DEFAULT v1(0),
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * extensions [ 3 ] Extensions OPTIONAL
+ * }
+ *
+ *
+ * Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
+ * will parse them, but you really shouldn't be creating new ones.
+ */
+public class TBSCertificateStructure
+ extends ASN1Object
+ implements X509ObjectIdentifiers, PKCSObjectIdentifiers
+{
+ ASN1Sequence seq;
+
+ ASN1Integer version;
+ ASN1Integer serialNumber;
+ AlgorithmIdentifier signature;
+ X500Name issuer;
+ Time startDate, endDate;
+ X500Name subject;
+ SubjectPublicKeyInfo subjectPublicKeyInfo;
+ DERBitString issuerUniqueId;
+ DERBitString subjectUniqueId;
+ X509Extensions extensions;
+
+ public static TBSCertificateStructure getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static TBSCertificateStructure getInstance(
+ Object obj)
+ {
+ if (obj instanceof TBSCertificateStructure)
+ {
+ return (TBSCertificateStructure)obj;
+ }
+ else if (obj != null)
+ {
+ return new TBSCertificateStructure(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public TBSCertificateStructure(
+ ASN1Sequence seq)
+ {
+ int seqStart = 0;
+
+ this.seq = seq;
+
+ //
+ // some certficates don't include a version number - we assume v1
+ //
+ if (seq.getObjectAt(0) instanceof DERTaggedObject)
+ {
+ version = ASN1Integer.getInstance((ASN1TaggedObject)seq.getObjectAt(0), true);
+ }
+ else
+ {
+ seqStart = -1; // field 0 is missing!
+ version = new ASN1Integer(0);
+ }
+
+ serialNumber = ASN1Integer.getInstance(seq.getObjectAt(seqStart + 1));
+
+ signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqStart + 2));
+ issuer = X500Name.getInstance(seq.getObjectAt(seqStart + 3));
+
+ //
+ // before and after dates
+ //
+ ASN1Sequence dates = (ASN1Sequence)seq.getObjectAt(seqStart + 4);
+
+ startDate = Time.getInstance(dates.getObjectAt(0));
+ endDate = Time.getInstance(dates.getObjectAt(1));
+
+ subject = X500Name.getInstance(seq.getObjectAt(seqStart + 5));
+
+ //
+ // public key info.
+ //
+ subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(seq.getObjectAt(seqStart + 6));
+
+ for (int extras = seq.size() - (seqStart + 6) - 1; extras > 0; extras--)
+ {
+ DERTaggedObject extra = (DERTaggedObject)seq.getObjectAt(seqStart + 6 + extras);
+
+ switch (extra.getTagNo())
+ {
+ case 1:
+ issuerUniqueId = DERBitString.getInstance(extra, false);
+ break;
+ case 2:
+ subjectUniqueId = DERBitString.getInstance(extra, false);
+ break;
+ case 3:
+ extensions = X509Extensions.getInstance(extra);
+ }
+ }
+ }
+
+ public int getVersion()
+ {
+ return version.getValue().intValue() + 1;
+ }
+
+ public ASN1Integer getVersionNumber()
+ {
+ return version;
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return serialNumber;
+ }
+
+ public AlgorithmIdentifier getSignature()
+ {
+ return signature;
+ }
+
+ public X500Name getIssuer()
+ {
+ return issuer;
+ }
+
+ public Time getStartDate()
+ {
+ return startDate;
+ }
+
+ public Time getEndDate()
+ {
+ return endDate;
+ }
+
+ public X500Name getSubject()
+ {
+ return subject;
+ }
+
+ public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
+ {
+ return subjectPublicKeyInfo;
+ }
+
+ public DERBitString getIssuerUniqueId()
+ {
+ return issuerUniqueId;
+ }
+
+ public DERBitString getSubjectUniqueId()
+ {
+ return subjectUniqueId;
+ }
+
+ public X509Extensions getExtensions()
+ {
+ return extensions;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Target.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Target.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Target.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Target.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,138 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * Target structure used in target information extension for attribute
+ * certificates from RFC 3281.
+ *
+ *
+ * Target ::= CHOICE {
+ * targetName [0] GeneralName,
+ * targetGroup [1] GeneralName,
+ * targetCert [2] TargetCert
+ * }
+ *
+ *
+ *
+ * The targetCert field is currently not supported and must not be used
+ * according to RFC 3281.
+ */
+public class Target
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int targetName = 0;
+ public static final int targetGroup = 1;
+
+ private GeneralName targName;
+ private GeneralName targGroup;
+
+ /**
+ * Creates an instance of a Target from the given object.
+ *
+ * obj
can be a Target or a {@link ASN1TaggedObject}
+ *
+ * @param obj The object.
+ * @return A Target instance.
+ * @throws IllegalArgumentException if the given object cannot be
+ * interpreted as Target.
+ */
+ public static Target getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof Target)
+ {
+ return (Target) obj;
+ }
+ else if (obj instanceof ASN1TaggedObject)
+ {
+ return new Target((ASN1TaggedObject)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: "
+ + obj.getClass());
+ }
+
+ /**
+ * Constructor from ASN1TaggedObject.
+ *
+ * @param tagObj The tagged object.
+ * @throws IllegalArgumentException if the encoding is wrong.
+ */
+ private Target(ASN1TaggedObject tagObj)
+ {
+ switch (tagObj.getTagNo())
+ {
+ case targetName: // GeneralName is already a choice so explicit
+ targName = GeneralName.getInstance(tagObj, true);
+ break;
+ case targetGroup:
+ targGroup = GeneralName.getInstance(tagObj, true);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown tag: " + tagObj.getTagNo());
+ }
+ }
+
+ /**
+ * Constructor from given details.
+ *
+ * Exactly one of the parameters must be not null
.
+ *
+ * @param type the choice type to apply to the name.
+ * @param name the general name.
+ * @throws IllegalArgumentException if type is invalid.
+ */
+ public Target(int type, GeneralName name)
+ {
+ this(new DERTaggedObject(type, name));
+ }
+
+ /**
+ * @return Returns the targetGroup.
+ */
+ public GeneralName getTargetGroup()
+ {
+ return targGroup;
+ }
+
+ /**
+ * @return Returns the targetName.
+ */
+ public GeneralName getTargetName()
+ {
+ return targName;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * Target ::= CHOICE {
+ * targetName [0] GeneralName,
+ * targetGroup [1] GeneralName,
+ * targetCert [2] TargetCert
+ * }
+ *
+ *
+ * @return a ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ // GeneralName is a choice already so most be explicitly tagged
+ if (targName != null)
+ {
+ return new DERTaggedObject(true, 0, targName);
+ }
+ else
+ {
+ return new DERTaggedObject(true, 1, targGroup);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/TargetInformation.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/TargetInformation.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/TargetInformation.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/TargetInformation.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,120 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * Target information extension for attributes certificates according to RFC
+ * 3281.
+ *
+ *
+ * SEQUENCE OF Targets
+ *
+ *
+ */
+public class TargetInformation
+ extends ASN1Object
+{
+ private ASN1Sequence targets;
+
+ /**
+ * Creates an instance of a TargetInformation from the given object.
+ *
+ * obj
can be a TargetInformation or a {@link ASN1Sequence}
+ *
+ * @param obj The object.
+ * @return A TargetInformation instance.
+ * @throws IllegalArgumentException if the given object cannot be
+ * interpreted as TargetInformation.
+ */
+ public static TargetInformation getInstance(Object obj)
+ {
+ if (obj instanceof TargetInformation)
+ {
+ return (TargetInformation)obj;
+ }
+ else if (obj != null)
+ {
+ return new TargetInformation(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from a ASN1Sequence.
+ *
+ * @param seq The ASN1Sequence.
+ * @throws IllegalArgumentException if the sequence does not contain
+ * correctly encoded Targets elements.
+ */
+ private TargetInformation(ASN1Sequence seq)
+ {
+ targets = seq;
+ }
+
+ /**
+ * Returns the targets in this target information extension.
+ *
+ * @return Returns the targets.
+ */
+ public Targets[] getTargetsObjects()
+ {
+ Targets[] copy = new Targets[targets.size()];
+ int count = 0;
+ for (Enumeration e = targets.getObjects(); e.hasMoreElements();)
+ {
+ copy[count++] = Targets.getInstance(e.nextElement());
+ }
+ return copy;
+ }
+
+ /**
+ * Constructs a target information from a single targets element.
+ * According to RFC 3281 only one targets element must be produced.
+ *
+ * @param targets A Targets instance.
+ */
+ public TargetInformation(Targets targets)
+ {
+ this.targets = new DERSequence(targets);
+ }
+
+ /**
+ * According to RFC 3281 only one targets element must be produced. If
+ * multiple targets are given they must be merged in
+ * into one targets element.
+ *
+ * @param targets An array with {@link Targets}.
+ */
+ public TargetInformation(Target[] targets)
+ {
+ this(new Targets(targets));
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * SEQUENCE OF Targets
+ *
+ *
+ *
+ * According to RFC 3281 only one targets element must be produced. If
+ * multiple targets are given in the constructor they are merged into one
+ * targets element. If this was produced from a
+ * {@link pdftk.org.bouncycastle.asn1.ASN1Sequence} the encoding is kept.
+ *
+ * @return a ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return targets;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Targets.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Targets.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Targets.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Targets.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,121 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * Targets structure used in target information extension for attribute
+ * certificates from RFC 3281.
+ *
+ *
+ * Targets ::= SEQUENCE OF Target
+ *
+ * Target ::= CHOICE {
+ * targetName [0] GeneralName,
+ * targetGroup [1] GeneralName,
+ * targetCert [2] TargetCert
+ * }
+ *
+ * TargetCert ::= SEQUENCE {
+ * targetCertificate IssuerSerial,
+ * targetName GeneralName OPTIONAL,
+ * certDigestInfo ObjectDigestInfo OPTIONAL
+ * }
+ *
+ *
+ * @see pdftk.org.bouncycastle.asn1.x509.Target
+ * @see pdftk.org.bouncycastle.asn1.x509.TargetInformation
+ */
+public class Targets
+ extends ASN1Object
+{
+ private ASN1Sequence targets;
+
+ /**
+ * Creates an instance of a Targets from the given object.
+ *
+ * obj
can be a Targets or a {@link ASN1Sequence}
+ *
+ * @param obj The object.
+ * @return A Targets instance.
+ * @throws IllegalArgumentException if the given object cannot be
+ * interpreted as Target.
+ */
+ public static Targets getInstance(Object obj)
+ {
+ if (obj instanceof Targets)
+ {
+ return (Targets)obj;
+ }
+ else if (obj != null)
+ {
+ return new Targets(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * @param targets The ASN.1 SEQUENCE.
+ * @throws IllegalArgumentException if the contents of the sequence are
+ * invalid.
+ */
+ private Targets(ASN1Sequence targets)
+ {
+ this.targets = targets;
+ }
+
+ /**
+ * Constructor from given targets.
+ *
+ * The vector is copied.
+ *
+ * @param targets A Vector
of {@link Target}s.
+ * @see Target
+ * @throws IllegalArgumentException if the vector contains not only Targets.
+ */
+ public Targets(Target[] targets)
+ {
+ this.targets = new DERSequence(targets);
+ }
+
+ /**
+ * Returns the targets in a Vector
.
+ *
+ * The vector is cloned before it is returned.
+ *
+ * @return Returns the targets.
+ */
+ public Target[] getTargets()
+ {
+ Target[] targs = new Target[targets.size()];
+ int count = 0;
+ for (Enumeration e = targets.getObjects(); e.hasMoreElements();)
+ {
+ targs[count++] = Target.getInstance(e.nextElement());
+ }
+ return targs;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * Targets ::= SEQUENCE OF Target
+ *
+ *
+ * @return a ASN1Primitive
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return targets;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Time.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Time.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/Time.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/Time.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,133 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.SimpleTimeZone;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERGeneralizedTime;
+import pdftk.org.bouncycastle.asn1.DERUTCTime;
+
+public class Time
+ extends ASN1Object
+ implements ASN1Choice
+{
+ ASN1Primitive time;
+
+ public static Time getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ public Time(
+ ASN1Primitive time)
+ {
+ if (!(time instanceof DERUTCTime)
+ && !(time instanceof DERGeneralizedTime))
+ {
+ throw new IllegalArgumentException("unknown object passed to Time");
+ }
+
+ this.time = time;
+ }
+
+ /**
+ * creates a time object from a given date - if the date is between 1950
+ * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
+ * is used.
+ */
+ public Time(
+ Date date)
+ {
+ SimpleTimeZone tz = new SimpleTimeZone(0, "Z");
+ SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss");
+
+ dateF.setTimeZone(tz);
+
+ String d = dateF.format(date) + "Z";
+ int year = Integer.parseInt(d.substring(0, 4));
+
+ if (year < 1950 || year > 2049)
+ {
+ time = new DERGeneralizedTime(d);
+ }
+ else
+ {
+ time = new DERUTCTime(d.substring(2));
+ }
+ }
+
+ public static Time getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof Time)
+ {
+ return (Time)obj;
+ }
+ else if (obj instanceof DERUTCTime)
+ {
+ return new Time((DERUTCTime)obj);
+ }
+ else if (obj instanceof DERGeneralizedTime)
+ {
+ return new Time((DERGeneralizedTime)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public String getTime()
+ {
+ if (time instanceof DERUTCTime)
+ {
+ return ((DERUTCTime)time).getAdjustedTime();
+ }
+ else
+ {
+ return ((DERGeneralizedTime)time).getTime();
+ }
+ }
+
+ public Date getDate()
+ {
+ try
+ {
+ if (time instanceof DERUTCTime)
+ {
+ return ((DERUTCTime)time).getAdjustedDate();
+ }
+ else
+ {
+ return ((DERGeneralizedTime)time).getDate();
+ }
+ }
+ catch (ParseException e)
+ { // this should never happen
+ throw new IllegalStateException("invalid date string: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return time;
+ }
+
+ public String toString()
+ {
+ return getTime();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/UserNotice.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/UserNotice.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/UserNotice.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/UserNotice.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,132 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * UserNotice
class, used in
+ * CertificatePolicies
X509 extensions (in policy
+ * qualifiers).
+ *
+ * UserNotice ::= SEQUENCE {
+ * noticeRef NoticeReference OPTIONAL,
+ * explicitText DisplayText OPTIONAL}
+ *
+ *
+ *
+ * @see PolicyQualifierId
+ * @see PolicyInformation
+ */
+public class UserNotice
+ extends ASN1Object
+{
+ private NoticeReference noticeRef;
+ private DisplayText explicitText;
+
+ /**
+ * Creates a new UserNotice
instance.
+ *
+ * @param noticeRef a NoticeReference
value
+ * @param explicitText a DisplayText
value
+ */
+ public UserNotice(
+ NoticeReference noticeRef,
+ DisplayText explicitText)
+ {
+ this.noticeRef = noticeRef;
+ this.explicitText = explicitText;
+ }
+
+ /**
+ * Creates a new UserNotice
instance.
+ *
+ * @param noticeRef a NoticeReference
value
+ * @param str the explicitText field as a String.
+ */
+ public UserNotice(
+ NoticeReference noticeRef,
+ String str)
+ {
+ this(noticeRef, new DisplayText(str));
+ }
+
+ /**
+ * Creates a new UserNotice
instance.
+ * Useful from reconstructing a UserNotice
instance
+ * from its encodable/encoded form.
+ *
+ * @param as an ASN1Sequence
value obtained from either
+ * calling @{link toASN1Primitive()} for a UserNotice
+ * instance or from parsing it from a DER-encoded stream.
+ */
+ private UserNotice(
+ ASN1Sequence as)
+ {
+ if (as.size() == 2)
+ {
+ noticeRef = NoticeReference.getInstance(as.getObjectAt(0));
+ explicitText = DisplayText.getInstance(as.getObjectAt(1));
+ }
+ else if (as.size() == 1)
+ {
+ if (as.getObjectAt(0).toASN1Primitive() instanceof ASN1Sequence)
+ {
+ noticeRef = NoticeReference.getInstance(as.getObjectAt(0));
+ }
+ else
+ {
+ explicitText = DisplayText.getInstance(as.getObjectAt(0));
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + as.size());
+ }
+ }
+
+ public static UserNotice getInstance(
+ Object obj)
+ {
+ if (obj instanceof UserNotice)
+ {
+ return (UserNotice)obj;
+ }
+
+ if (obj != null)
+ {
+ return new UserNotice(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public NoticeReference getNoticeRef()
+ {
+ return noticeRef;
+ }
+
+ public DisplayText getExplicitText()
+ {
+ return explicitText;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector av = new ASN1EncodableVector();
+
+ if (noticeRef != null)
+ {
+ av.add(noticeRef);
+ }
+
+ if (explicitText != null)
+ {
+ av.add(explicitText);
+ }
+
+ return new DERSequence(av);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/V1TBSCertificateGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/V1TBSCertificateGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/V1TBSCertificateGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/V1TBSCertificateGenerator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,144 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1UTCTime;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+
+/**
+ * Generator for Version 1 TBSCertificateStructures.
+ *
+ * TBSCertificate ::= SEQUENCE {
+ * version [ 0 ] Version DEFAULT v1(0),
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * }
+ *
+ *
+ */
+public class V1TBSCertificateGenerator
+{
+ DERTaggedObject version = new DERTaggedObject(true, 0, new ASN1Integer(0));
+
+ ASN1Integer serialNumber;
+ AlgorithmIdentifier signature;
+ X500Name issuer;
+ Time startDate, endDate;
+ X500Name subject;
+ SubjectPublicKeyInfo subjectPublicKeyInfo;
+
+ public V1TBSCertificateGenerator()
+ {
+ }
+
+ public void setSerialNumber(
+ ASN1Integer serialNumber)
+ {
+ this.serialNumber = serialNumber;
+ }
+
+ public void setSignature(
+ AlgorithmIdentifier signature)
+ {
+ this.signature = signature;
+ }
+
+ /**
+ * @deprecated use X500Name method
+ */
+ public void setIssuer(
+ X509Name issuer)
+ {
+ this.issuer = X500Name.getInstance(issuer.toASN1Primitive());
+ }
+
+ public void setIssuer(
+ X500Name issuer)
+ {
+ this.issuer = issuer;
+ }
+
+ public void setStartDate(
+ Time startDate)
+ {
+ this.startDate = startDate;
+ }
+
+ public void setStartDate(
+ ASN1UTCTime startDate)
+ {
+ this.startDate = new Time(startDate);
+ }
+
+ public void setEndDate(
+ Time endDate)
+ {
+ this.endDate = endDate;
+ }
+
+ public void setEndDate(
+ ASN1UTCTime endDate)
+ {
+ this.endDate = new Time(endDate);
+ }
+
+ /**
+ * @deprecated use X500Name method
+ */
+ public void setSubject(
+ X509Name subject)
+ {
+ this.subject = X500Name.getInstance(subject.toASN1Primitive());
+ }
+
+ public void setSubject(
+ X500Name subject)
+ {
+ this.subject = subject;
+ }
+
+ public void setSubjectPublicKeyInfo(
+ SubjectPublicKeyInfo pubKeyInfo)
+ {
+ this.subjectPublicKeyInfo = pubKeyInfo;
+ }
+
+ public TBSCertificate generateTBSCertificate()
+ {
+ if ((serialNumber == null) || (signature == null)
+ || (issuer == null) || (startDate == null) || (endDate == null)
+ || (subject == null) || (subjectPublicKeyInfo == null))
+ {
+ throw new IllegalStateException("not all mandatory fields set in V1 TBScertificate generator");
+ }
+
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+
+ // seq.add(version); - not required as default value.
+ seq.add(serialNumber);
+ seq.add(signature);
+ seq.add(issuer);
+
+ //
+ // before and after dates
+ //
+ ASN1EncodableVector validity = new ASN1EncodableVector();
+
+ validity.add(startDate);
+ validity.add(endDate);
+
+ seq.add(new DERSequence(validity));
+
+ seq.add(subject);
+
+ seq.add(subjectPublicKeyInfo);
+
+ return TBSCertificate.getInstance(new DERSequence(seq));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/V2AttributeCertificateInfoGenerator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,158 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERSet;
+
+/**
+ * Generator for Version 2 AttributeCertificateInfo
+ *
+ * AttributeCertificateInfo ::= SEQUENCE {
+ * version AttCertVersion -- version is v2,
+ * holder Holder,
+ * issuer AttCertIssuer,
+ * signature AlgorithmIdentifier,
+ * serialNumber CertificateSerialNumber,
+ * attrCertValidityPeriod AttCertValidityPeriod,
+ * attributes SEQUENCE OF Attribute,
+ * issuerUniqueID UniqueIdentifier OPTIONAL,
+ * extensions Extensions OPTIONAL
+ * }
+ *
+ *
+ */
+public class V2AttributeCertificateInfoGenerator
+{
+ private ASN1Integer version;
+ private Holder holder;
+ private AttCertIssuer issuer;
+ private AlgorithmIdentifier signature;
+ private ASN1Integer serialNumber;
+ private ASN1EncodableVector attributes;
+ private DERBitString issuerUniqueID;
+ private Extensions extensions;
+
+ // Note: validity period start/end dates stored directly
+ //private AttCertValidityPeriod attrCertValidityPeriod;
+ private ASN1GeneralizedTime startDate, endDate;
+
+ public V2AttributeCertificateInfoGenerator()
+ {
+ this.version = new ASN1Integer(1);
+ attributes = new ASN1EncodableVector();
+ }
+
+ public void setHolder(Holder holder)
+ {
+ this.holder = holder;
+ }
+
+ public void addAttribute(String oid, ASN1Encodable value)
+ {
+ attributes.add(new Attribute(new ASN1ObjectIdentifier(oid), new DERSet(value)));
+ }
+
+ /**
+ * @param attribute
+ */
+ public void addAttribute(Attribute attribute)
+ {
+ attributes.add(attribute);
+ }
+
+ public void setSerialNumber(
+ ASN1Integer serialNumber)
+ {
+ this.serialNumber = serialNumber;
+ }
+
+ public void setSignature(
+ AlgorithmIdentifier signature)
+ {
+ this.signature = signature;
+ }
+
+ public void setIssuer(
+ AttCertIssuer issuer)
+ {
+ this.issuer = issuer;
+ }
+
+ public void setStartDate(
+ ASN1GeneralizedTime startDate)
+ {
+ this.startDate = startDate;
+ }
+
+ public void setEndDate(
+ ASN1GeneralizedTime endDate)
+ {
+ this.endDate = endDate;
+ }
+
+ public void setIssuerUniqueID(
+ DERBitString issuerUniqueID)
+ {
+ this.issuerUniqueID = issuerUniqueID;
+ }
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param extensions
+ */
+ public void setExtensions(
+ X509Extensions extensions)
+ {
+ this.extensions = Extensions.getInstance(extensions.toASN1Primitive());
+ }
+
+ public void setExtensions(
+ Extensions extensions)
+ {
+ this.extensions = extensions;
+ }
+
+ public AttributeCertificateInfo generateAttributeCertificateInfo()
+ {
+ if ((serialNumber == null) || (signature == null)
+ || (issuer == null) || (startDate == null) || (endDate == null)
+ || (holder == null) || (attributes == null))
+ {
+ throw new IllegalStateException("not all mandatory fields set in V2 AttributeCertificateInfo generator");
+ }
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(holder);
+ v.add(issuer);
+ v.add(signature);
+ v.add(serialNumber);
+
+ //
+ // before and after dates => AttCertValidityPeriod
+ //
+ AttCertValidityPeriod validity = new AttCertValidityPeriod(startDate, endDate);
+ v.add(validity);
+
+ // Attributes
+ v.add(new DERSequence(attributes));
+
+ if (issuerUniqueID != null)
+ {
+ v.add(issuerUniqueID);
+ }
+
+ if (extensions != null)
+ {
+ v.add(extensions);
+ }
+
+ return AttributeCertificateInfo.getInstance(new DERSequence(v));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/V2Form.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/V2Form.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/V2Form.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/V2Form.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,130 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+public class V2Form
+ extends ASN1Object
+{
+ GeneralNames issuerName;
+ IssuerSerial baseCertificateID;
+ ObjectDigestInfo objectDigestInfo;
+
+ public static V2Form getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static V2Form getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof V2Form)
+ {
+ return (V2Form)obj;
+ }
+ else if (obj instanceof ASN1Sequence)
+ {
+ return new V2Form((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
+ }
+
+ public V2Form(
+ GeneralNames issuerName)
+ {
+ this.issuerName = issuerName;
+ }
+
+ public V2Form(
+ ASN1Sequence seq)
+ {
+ if (seq.size() > 3)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ int index = 0;
+
+ if (!(seq.getObjectAt(0) instanceof ASN1TaggedObject))
+ {
+ index++;
+ this.issuerName = GeneralNames.getInstance(seq.getObjectAt(0));
+ }
+
+ for (int i = index; i != seq.size(); i++)
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
+ if (o.getTagNo() == 0)
+ {
+ baseCertificateID = IssuerSerial.getInstance(o, false);
+ }
+ else if (o.getTagNo() == 1)
+ {
+ objectDigestInfo = ObjectDigestInfo.getInstance(o, false);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad tag number: "
+ + o.getTagNo());
+ }
+ }
+ }
+
+ public GeneralNames getIssuerName()
+ {
+ return issuerName;
+ }
+
+ public IssuerSerial getBaseCertificateID()
+ {
+ return baseCertificateID;
+ }
+
+ public ObjectDigestInfo getObjectDigestInfo()
+ {
+ return objectDigestInfo;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * V2Form ::= SEQUENCE {
+ * issuerName GeneralNames OPTIONAL,
+ * baseCertificateID [0] IssuerSerial OPTIONAL,
+ * objectDigestInfo [1] ObjectDigestInfo OPTIONAL
+ * -- issuerName MUST be present in this profile
+ * -- baseCertificateID and objectDigestInfo MUST NOT
+ * -- be present in this profile
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (issuerName != null)
+ {
+ v.add(issuerName);
+ }
+
+ if (baseCertificateID != null)
+ {
+ v.add(new DERTaggedObject(false, 0, baseCertificateID));
+ }
+
+ if (objectDigestInfo != null)
+ {
+ v.add(new DERTaggedObject(false, 1, objectDigestInfo));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/V2TBSCertListGenerator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,281 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1UTCTime;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+
+/**
+ * Generator for Version 2 TBSCertList structures.
+ *
+ * TBSCertList ::= SEQUENCE {
+ * version Version OPTIONAL,
+ * -- if present, shall be v2
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * thisUpdate Time,
+ * nextUpdate Time OPTIONAL,
+ * revokedCertificates SEQUENCE OF SEQUENCE {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate Time,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, shall be v2
+ * } OPTIONAL,
+ * crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ * -- if present, shall be v2
+ * }
+ *
+ *
+ * Note: This class may be subject to change
+ */
+public class V2TBSCertListGenerator
+{
+ private ASN1Integer version = new ASN1Integer(1);
+ private AlgorithmIdentifier signature;
+ private X500Name issuer;
+ private Time thisUpdate, nextUpdate=null;
+ private Extensions extensions = null;
+ private ASN1EncodableVector crlentries = new ASN1EncodableVector();
+
+ private final static ASN1Sequence[] reasons;
+
+ static
+ {
+ reasons = new ASN1Sequence[11];
+
+ reasons[0] = createReasonExtension(CRLReason.unspecified);
+ reasons[1] = createReasonExtension(CRLReason.keyCompromise);
+ reasons[2] = createReasonExtension(CRLReason.cACompromise);
+ reasons[3] = createReasonExtension(CRLReason.affiliationChanged);
+ reasons[4] = createReasonExtension(CRLReason.superseded);
+ reasons[5] = createReasonExtension(CRLReason.cessationOfOperation);
+ reasons[6] = createReasonExtension(CRLReason.certificateHold);
+ reasons[7] = createReasonExtension(7); // 7 -> unknown
+ reasons[8] = createReasonExtension(CRLReason.removeFromCRL);
+ reasons[9] = createReasonExtension(CRLReason.privilegeWithdrawn);
+ reasons[10] = createReasonExtension(CRLReason.aACompromise);
+ }
+
+ public V2TBSCertListGenerator()
+ {
+ }
+
+
+ public void setSignature(
+ AlgorithmIdentifier signature)
+ {
+ this.signature = signature;
+ }
+
+ /**
+ * @deprecated use X500Name method
+ */
+ public void setIssuer(
+ X509Name issuer)
+ {
+ this.issuer = X500Name.getInstance(issuer.toASN1Primitive());
+ }
+
+ public void setIssuer(X500Name issuer)
+ {
+ this.issuer = issuer;
+ }
+
+ public void setThisUpdate(
+ ASN1UTCTime thisUpdate)
+ {
+ this.thisUpdate = new Time(thisUpdate);
+ }
+
+ public void setNextUpdate(
+ ASN1UTCTime nextUpdate)
+ {
+ this.nextUpdate = new Time(nextUpdate);
+ }
+
+ public void setThisUpdate(
+ Time thisUpdate)
+ {
+ this.thisUpdate = thisUpdate;
+ }
+
+ public void setNextUpdate(
+ Time nextUpdate)
+ {
+ this.nextUpdate = nextUpdate;
+ }
+
+ public void addCRLEntry(
+ ASN1Sequence crlEntry)
+ {
+ crlentries.add(crlEntry);
+ }
+
+ public void addCRLEntry(ASN1Integer userCertificate, ASN1UTCTime revocationDate, int reason)
+ {
+ addCRLEntry(userCertificate, new Time(revocationDate), reason);
+ }
+
+ public void addCRLEntry(ASN1Integer userCertificate, Time revocationDate, int reason)
+ {
+ addCRLEntry(userCertificate, revocationDate, reason, null);
+ }
+
+ public void addCRLEntry(ASN1Integer userCertificate, Time revocationDate, int reason, ASN1GeneralizedTime invalidityDate)
+ {
+ if (reason != 0)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (reason < reasons.length)
+ {
+ if (reason < 0)
+ {
+ throw new IllegalArgumentException("invalid reason value: " + reason);
+ }
+ v.add(reasons[reason]);
+ }
+ else
+ {
+ v.add(createReasonExtension(reason));
+ }
+
+ if (invalidityDate != null)
+ {
+ v.add(createInvalidityDateExtension(revocationDate));
+ }
+
+ internalAddCRLEntry(userCertificate, revocationDate, new DERSequence(v));
+ }
+ else if (invalidityDate != null)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(createInvalidityDateExtension(revocationDate));
+
+ internalAddCRLEntry(userCertificate, revocationDate, new DERSequence(v));
+ }
+ else
+ {
+ addCRLEntry(userCertificate, revocationDate, null);
+ }
+ }
+
+ private void internalAddCRLEntry(ASN1Integer userCertificate, Time revocationDate, ASN1Sequence extensions)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(userCertificate);
+ v.add(revocationDate);
+
+ if (extensions != null)
+ {
+ v.add(extensions);
+ }
+
+ addCRLEntry(new DERSequence(v));
+ }
+
+ public void addCRLEntry(ASN1Integer userCertificate, Time revocationDate, Extensions extensions)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(userCertificate);
+ v.add(revocationDate);
+
+ if (extensions != null)
+ {
+ v.add(extensions);
+ }
+
+ addCRLEntry(new DERSequence(v));
+ }
+
+ public void setExtensions(
+ X509Extensions extensions)
+ {
+ setExtensions(Extensions.getInstance(extensions));
+ }
+
+ public void setExtensions(
+ Extensions extensions)
+ {
+ this.extensions = extensions;
+ }
+
+ public TBSCertList generateTBSCertList()
+ {
+ if ((signature == null) || (issuer == null) || (thisUpdate == null))
+ {
+ throw new IllegalStateException("Not all mandatory fields set in V2 TBSCertList generator.");
+ }
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(signature);
+ v.add(issuer);
+
+ v.add(thisUpdate);
+ if (nextUpdate != null)
+ {
+ v.add(nextUpdate);
+ }
+
+ // Add CRLEntries if they exist
+ if (crlentries.size() != 0)
+ {
+ v.add(new DERSequence(crlentries));
+ }
+
+ if (extensions != null)
+ {
+ v.add(new DERTaggedObject(0, extensions));
+ }
+
+ return new TBSCertList(new DERSequence(v));
+ }
+
+ private static ASN1Sequence createReasonExtension(int reasonCode)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ CRLReason crlReason = CRLReason.lookup(reasonCode);
+
+ try
+ {
+ v.add(Extension.reasonCode);
+ v.add(new DEROctetString(crlReason.getEncoded()));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("error encoding reason: " + e);
+ }
+
+ return new DERSequence(v);
+ }
+
+ private static ASN1Sequence createInvalidityDateExtension(Time invalidityDate)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ try
+ {
+ v.add(Extension.invalidityDate);
+ v.add(new DEROctetString(invalidityDate.getEncoded()));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("error encoding reason: " + e);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,212 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.DERUTCTime;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+
+/**
+ * Generator for Version 3 TBSCertificateStructures.
+ *
+ * TBSCertificate ::= SEQUENCE {
+ * version [ 0 ] Version DEFAULT v1(0),
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+ * extensions [ 3 ] Extensions OPTIONAL
+ * }
+ *
+ *
+ */
+public class V3TBSCertificateGenerator
+{
+ DERTaggedObject version = new DERTaggedObject(true, 0, new ASN1Integer(2));
+
+ ASN1Integer serialNumber;
+ AlgorithmIdentifier signature;
+ X500Name issuer;
+ Time startDate, endDate;
+ X500Name subject;
+ SubjectPublicKeyInfo subjectPublicKeyInfo;
+ Extensions extensions;
+
+ private boolean altNamePresentAndCritical;
+ private DERBitString issuerUniqueID;
+ private DERBitString subjectUniqueID;
+
+ public V3TBSCertificateGenerator()
+ {
+ }
+
+ public void setSerialNumber(
+ ASN1Integer serialNumber)
+ {
+ this.serialNumber = serialNumber;
+ }
+
+ public void setSignature(
+ AlgorithmIdentifier signature)
+ {
+ this.signature = signature;
+ }
+
+ /**
+ * @deprecated use X500Name method
+ */
+ public void setIssuer(
+ X509Name issuer)
+ {
+ this.issuer = X500Name.getInstance(issuer);
+ }
+
+ public void setIssuer(
+ X500Name issuer)
+ {
+ this.issuer = issuer;
+ }
+
+ public void setStartDate(
+ DERUTCTime startDate)
+ {
+ this.startDate = new Time(startDate);
+ }
+
+ public void setStartDate(
+ Time startDate)
+ {
+ this.startDate = startDate;
+ }
+
+ public void setEndDate(
+ DERUTCTime endDate)
+ {
+ this.endDate = new Time(endDate);
+ }
+
+ public void setEndDate(
+ Time endDate)
+ {
+ this.endDate = endDate;
+ }
+
+ /**
+ * @deprecated use X500Name method
+ */
+ public void setSubject(
+ X509Name subject)
+ {
+ this.subject = X500Name.getInstance(subject.toASN1Primitive());
+ }
+
+ public void setSubject(
+ X500Name subject)
+ {
+ this.subject = subject;
+ }
+
+ public void setIssuerUniqueID(
+ DERBitString uniqueID)
+ {
+ this.issuerUniqueID = uniqueID;
+ }
+
+ public void setSubjectUniqueID(
+ DERBitString uniqueID)
+ {
+ this.subjectUniqueID = uniqueID;
+ }
+
+ public void setSubjectPublicKeyInfo(
+ SubjectPublicKeyInfo pubKeyInfo)
+ {
+ this.subjectPublicKeyInfo = pubKeyInfo;
+ }
+
+ /**
+ * @deprecated use method taking Extensions
+ * @param extensions
+ */
+ public void setExtensions(
+ X509Extensions extensions)
+ {
+ setExtensions(Extensions.getInstance(extensions));
+ }
+
+ public void setExtensions(
+ Extensions extensions)
+ {
+ this.extensions = extensions;
+ if (extensions != null)
+ {
+ Extension altName = extensions.getExtension(Extension.subjectAlternativeName);
+
+ if (altName != null && altName.isCritical())
+ {
+ altNamePresentAndCritical = true;
+ }
+ }
+ }
+
+ public TBSCertificate generateTBSCertificate()
+ {
+ if ((serialNumber == null) || (signature == null)
+ || (issuer == null) || (startDate == null) || (endDate == null)
+ || (subject == null && !altNamePresentAndCritical) || (subjectPublicKeyInfo == null))
+ {
+ throw new IllegalStateException("not all mandatory fields set in V3 TBScertificate generator");
+ }
+
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(version);
+ v.add(serialNumber);
+ v.add(signature);
+ v.add(issuer);
+
+ //
+ // before and after dates
+ //
+ ASN1EncodableVector validity = new ASN1EncodableVector();
+
+ validity.add(startDate);
+ validity.add(endDate);
+
+ v.add(new DERSequence(validity));
+
+ if (subject != null)
+ {
+ v.add(subject);
+ }
+ else
+ {
+ v.add(new DERSequence());
+ }
+
+ v.add(subjectPublicKeyInfo);
+
+ if (issuerUniqueID != null)
+ {
+ v.add(new DERTaggedObject(false, 1, issuerUniqueID));
+ }
+
+ if (subjectUniqueID != null)
+ {
+ v.add(new DERTaggedObject(false, 2, subjectUniqueID));
+ }
+
+ if (extensions != null)
+ {
+ v.add(new DERTaggedObject(true, 3, extensions));
+ }
+
+ return TBSCertificate.getInstance(new DERSequence(v));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509AttributeIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509AttributeIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509AttributeIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509AttributeIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,29 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface X509AttributeIdentifiers
+{
+ /**
+ * @deprecated use id_at_role
+ */
+ static final ASN1ObjectIdentifier RoleSyntax = new ASN1ObjectIdentifier("2.5.4.72");
+
+ static final ASN1ObjectIdentifier id_pe_ac_auditIdentity = X509ObjectIdentifiers.id_pe.branch("4");
+ static final ASN1ObjectIdentifier id_pe_aaControls = X509ObjectIdentifiers.id_pe.branch("6");
+ static final ASN1ObjectIdentifier id_pe_ac_proxying = X509ObjectIdentifiers.id_pe.branch("10");
+
+ static final ASN1ObjectIdentifier id_ce_targetInformation= X509ObjectIdentifiers.id_ce.branch("55");
+
+ static final ASN1ObjectIdentifier id_aca = X509ObjectIdentifiers.id_pkix.branch("10");
+
+ static final ASN1ObjectIdentifier id_aca_authenticationInfo = id_aca.branch("1");
+ static final ASN1ObjectIdentifier id_aca_accessIdentity = id_aca.branch("2");
+ static final ASN1ObjectIdentifier id_aca_chargingIdentity = id_aca.branch("3");
+ static final ASN1ObjectIdentifier id_aca_group = id_aca.branch("4");
+ // { id-aca 5 } is reserved
+ static final ASN1ObjectIdentifier id_aca_encAttrs = id_aca.branch("6");
+
+ static final ASN1ObjectIdentifier id_at_role = new ASN1ObjectIdentifier("2.5.4.72");
+ static final ASN1ObjectIdentifier id_at_clearance = new ASN1ObjectIdentifier("2.5.1.5.55");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509CertificateStructure.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509CertificateStructure.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509CertificateStructure.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509CertificateStructure.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,129 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+
+/**
+ * an X509Certificate structure.
+ *
+ * Certificate ::= SEQUENCE {
+ * tbsCertificate TBSCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING
+ * }
+ *
+ * @deprecated use pdftk.org.bouncycastle.asn1.x509.Certificate
+ */
+public class X509CertificateStructure
+ extends ASN1Object
+ implements X509ObjectIdentifiers, PKCSObjectIdentifiers
+{
+ ASN1Sequence seq;
+ TBSCertificateStructure tbsCert;
+ AlgorithmIdentifier sigAlgId;
+ DERBitString sig;
+
+ public static X509CertificateStructure getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static X509CertificateStructure getInstance(
+ Object obj)
+ {
+ if (obj instanceof X509CertificateStructure)
+ {
+ return (X509CertificateStructure)obj;
+ }
+ else if (obj != null)
+ {
+ return new X509CertificateStructure(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public X509CertificateStructure(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+
+ //
+ // correct x509 certficate
+ //
+ if (seq.size() == 3)
+ {
+ tbsCert = TBSCertificateStructure.getInstance(seq.getObjectAt(0));
+ sigAlgId = AlgorithmIdentifier.getInstance(seq.getObjectAt(1));
+
+ sig = DERBitString.getInstance(seq.getObjectAt(2));
+ }
+ else
+ {
+ throw new IllegalArgumentException("sequence wrong size for a certificate");
+ }
+ }
+
+ public TBSCertificateStructure getTBSCertificate()
+ {
+ return tbsCert;
+ }
+
+ public int getVersion()
+ {
+ return tbsCert.getVersion();
+ }
+
+ public ASN1Integer getSerialNumber()
+ {
+ return tbsCert.getSerialNumber();
+ }
+
+ public X500Name getIssuer()
+ {
+ return tbsCert.getIssuer();
+ }
+
+ public Time getStartDate()
+ {
+ return tbsCert.getStartDate();
+ }
+
+ public Time getEndDate()
+ {
+ return tbsCert.getEndDate();
+ }
+
+ public X500Name getSubject()
+ {
+ return tbsCert.getSubject();
+ }
+
+ public SubjectPublicKeyInfo getSubjectPublicKeyInfo()
+ {
+ return tbsCert.getSubjectPublicKeyInfo();
+ }
+
+ public AlgorithmIdentifier getSignatureAlgorithm()
+ {
+ return sigAlgId;
+ }
+
+ public DERBitString getSignature()
+ {
+ return sig;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return seq;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509DefaultEntryConverter.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509DefaultEntryConverter.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509DefaultEntryConverter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509DefaultEntryConverter.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,65 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DERGeneralizedTime;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+import pdftk.org.bouncycastle.asn1.DERUTF8String;
+
+/**
+ * The default converter for X509 DN entries when going from their
+ * string value to ASN.1 strings.
+ */
+public class X509DefaultEntryConverter
+ extends X509NameEntryConverter
+{
+ /**
+ * Apply default coversion for the given value depending on the oid
+ * and the character range of the value.
+ *
+ * @param oid the object identifier for the DN entry
+ * @param value the value associated with it
+ * @return the ASN.1 equivalent for the string value.
+ */
+ public ASN1Primitive getConvertedValue(
+ ASN1ObjectIdentifier oid,
+ String value)
+ {
+ if (value.length() != 0 && value.charAt(0) == '#')
+ {
+ try
+ {
+ return convertHexEncoded(value, 1);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("can't recode value for oid " + oid.getId());
+ }
+ }
+ else
+ {
+ if (value.length() != 0 && value.charAt(0) == '\\')
+ {
+ value = value.substring(1);
+ }
+ if (oid.equals(X509Name.EmailAddress) || oid.equals(X509Name.DC))
+ {
+ return new DERIA5String(value);
+ }
+ else if (oid.equals(X509Name.DATE_OF_BIRTH)) // accept time string as well as # (for compatibility)
+ {
+ return new DERGeneralizedTime(value);
+ }
+ else if (oid.equals(X509Name.C) || oid.equals(X509Name.SN) || oid.equals(X509Name.DN_QUALIFIER)
+ || oid.equals(X509Name.TELEPHONE_NUMBER))
+ {
+ return new DERPrintableString(value);
+ }
+ }
+
+ return new DERUTF8String(value);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509Extension.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509Extension.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509Extension.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509Extension.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,248 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DERBoolean;
+
+/**
+ * an object for the elements in the X.509 V3 extension block.
+ */
+public class X509Extension
+{
+ /**
+ * Subject Directory Attributes
+ */
+ public static final ASN1ObjectIdentifier subjectDirectoryAttributes = new ASN1ObjectIdentifier("2.5.29.9");
+
+ /**
+ * Subject Key Identifier
+ */
+ public static final ASN1ObjectIdentifier subjectKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.14");
+
+ /**
+ * Key Usage
+ */
+ public static final ASN1ObjectIdentifier keyUsage = new ASN1ObjectIdentifier("2.5.29.15");
+
+ /**
+ * Private Key Usage Period
+ */
+ public static final ASN1ObjectIdentifier privateKeyUsagePeriod = new ASN1ObjectIdentifier("2.5.29.16");
+
+ /**
+ * Subject Alternative Name
+ */
+ public static final ASN1ObjectIdentifier subjectAlternativeName = new ASN1ObjectIdentifier("2.5.29.17");
+
+ /**
+ * Issuer Alternative Name
+ */
+ public static final ASN1ObjectIdentifier issuerAlternativeName = new ASN1ObjectIdentifier("2.5.29.18");
+
+ /**
+ * Basic Constraints
+ */
+ public static final ASN1ObjectIdentifier basicConstraints = new ASN1ObjectIdentifier("2.5.29.19");
+
+ /**
+ * CRL Number
+ */
+ public static final ASN1ObjectIdentifier cRLNumber = new ASN1ObjectIdentifier("2.5.29.20");
+
+ /**
+ * Reason code
+ */
+ public static final ASN1ObjectIdentifier reasonCode = new ASN1ObjectIdentifier("2.5.29.21");
+
+ /**
+ * Hold Instruction Code
+ */
+ public static final ASN1ObjectIdentifier instructionCode = new ASN1ObjectIdentifier("2.5.29.23");
+
+ /**
+ * Invalidity Date
+ */
+ public static final ASN1ObjectIdentifier invalidityDate = new ASN1ObjectIdentifier("2.5.29.24");
+
+ /**
+ * Delta CRL indicator
+ */
+ public static final ASN1ObjectIdentifier deltaCRLIndicator = new ASN1ObjectIdentifier("2.5.29.27");
+
+ /**
+ * Issuing Distribution Point
+ */
+ public static final ASN1ObjectIdentifier issuingDistributionPoint = new ASN1ObjectIdentifier("2.5.29.28");
+
+ /**
+ * Certificate Issuer
+ */
+ public static final ASN1ObjectIdentifier certificateIssuer = new ASN1ObjectIdentifier("2.5.29.29");
+
+ /**
+ * Name Constraints
+ */
+ public static final ASN1ObjectIdentifier nameConstraints = new ASN1ObjectIdentifier("2.5.29.30");
+
+ /**
+ * CRL Distribution Points
+ */
+ public static final ASN1ObjectIdentifier cRLDistributionPoints = new ASN1ObjectIdentifier("2.5.29.31");
+
+ /**
+ * Certificate Policies
+ */
+ public static final ASN1ObjectIdentifier certificatePolicies = new ASN1ObjectIdentifier("2.5.29.32");
+
+ /**
+ * Policy Mappings
+ */
+ public static final ASN1ObjectIdentifier policyMappings = new ASN1ObjectIdentifier("2.5.29.33");
+
+ /**
+ * Authority Key Identifier
+ */
+ public static final ASN1ObjectIdentifier authorityKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.35");
+
+ /**
+ * Policy Constraints
+ */
+ public static final ASN1ObjectIdentifier policyConstraints = new ASN1ObjectIdentifier("2.5.29.36");
+
+ /**
+ * Extended Key Usage
+ */
+ public static final ASN1ObjectIdentifier extendedKeyUsage = new ASN1ObjectIdentifier("2.5.29.37");
+
+ /**
+ * Freshest CRL
+ */
+ public static final ASN1ObjectIdentifier freshestCRL = new ASN1ObjectIdentifier("2.5.29.46");
+
+ /**
+ * Inhibit Any Policy
+ */
+ public static final ASN1ObjectIdentifier inhibitAnyPolicy = new ASN1ObjectIdentifier("2.5.29.54");
+
+ /**
+ * Authority Info Access
+ */
+ public static final ASN1ObjectIdentifier authorityInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.1");
+
+ /**
+ * Subject Info Access
+ */
+ public static final ASN1ObjectIdentifier subjectInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.11");
+
+ /**
+ * Logo Type
+ */
+ public static final ASN1ObjectIdentifier logoType = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.12");
+
+ /**
+ * BiometricInfo
+ */
+ public static final ASN1ObjectIdentifier biometricInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.2");
+
+ /**
+ * QCStatements
+ */
+ public static final ASN1ObjectIdentifier qCStatements = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.3");
+
+ /**
+ * Audit identity extension in attribute certificates.
+ */
+ public static final ASN1ObjectIdentifier auditIdentity = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.4");
+
+ /**
+ * NoRevAvail extension in attribute certificates.
+ */
+ public static final ASN1ObjectIdentifier noRevAvail = new ASN1ObjectIdentifier("2.5.29.56");
+
+ /**
+ * TargetInformation extension in attribute certificates.
+ */
+ public static final ASN1ObjectIdentifier targetInformation = new ASN1ObjectIdentifier("2.5.29.55");
+
+ boolean critical;
+ ASN1OctetString value;
+
+ public X509Extension(
+ DERBoolean critical,
+ ASN1OctetString value)
+ {
+ this.critical = critical.isTrue();
+ this.value = value;
+ }
+
+ public X509Extension(
+ boolean critical,
+ ASN1OctetString value)
+ {
+ this.critical = critical;
+ this.value = value;
+ }
+
+ public boolean isCritical()
+ {
+ return critical;
+ }
+
+ public ASN1OctetString getValue()
+ {
+ return value;
+ }
+
+ public ASN1Encodable getParsedValue()
+ {
+ return convertValueToObject(this);
+ }
+
+ public int hashCode()
+ {
+ if (this.isCritical())
+ {
+ return this.getValue().hashCode();
+ }
+
+ return ~this.getValue().hashCode();
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof X509Extension))
+ {
+ return false;
+ }
+
+ X509Extension other = (X509Extension)o;
+
+ return other.getValue().equals(this.getValue())
+ && (other.isCritical() == this.isCritical());
+ }
+
+ /**
+ * Convert the value of the passed in extension to an object
+ * @param ext the extension to parse
+ * @return the object the value string contains
+ * @exception IllegalArgumentException if conversion is not possible
+ */
+ public static ASN1Primitive convertValueToObject(
+ X509Extension ext)
+ throws IllegalArgumentException
+ {
+ try
+ {
+ return ASN1Primitive.fromByteArray(ext.getValue().getOctets());
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("can't convert extension: " + e);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509Extensions.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509Extensions.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509Extensions.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509Extensions.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,489 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBoolean;
+import pdftk.org.bouncycastle.asn1.DERObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * @deprecated use Extensions
+ */
+public class X509Extensions
+ extends ASN1Object
+{
+ /**
+ * Subject Directory Attributes
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier SubjectDirectoryAttributes = new ASN1ObjectIdentifier("2.5.29.9");
+
+ /**
+ * Subject Key Identifier
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier SubjectKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.14");
+
+ /**
+ * Key Usage
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier KeyUsage = new ASN1ObjectIdentifier("2.5.29.15");
+
+ /**
+ * Private Key Usage Period
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier PrivateKeyUsagePeriod = new ASN1ObjectIdentifier("2.5.29.16");
+
+ /**
+ * Subject Alternative Name
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier SubjectAlternativeName = new ASN1ObjectIdentifier("2.5.29.17");
+
+ /**
+ * Issuer Alternative Name
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier IssuerAlternativeName = new ASN1ObjectIdentifier("2.5.29.18");
+
+ /**
+ * Basic Constraints
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier BasicConstraints = new ASN1ObjectIdentifier("2.5.29.19");
+
+ /**
+ * CRL Number
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier CRLNumber = new ASN1ObjectIdentifier("2.5.29.20");
+
+ /**
+ * Reason code
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier ReasonCode = new ASN1ObjectIdentifier("2.5.29.21");
+
+ /**
+ * Hold Instruction Code
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier InstructionCode = new ASN1ObjectIdentifier("2.5.29.23");
+
+ /**
+ * Invalidity Date
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier InvalidityDate = new ASN1ObjectIdentifier("2.5.29.24");
+
+ /**
+ * Delta CRL indicator
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier DeltaCRLIndicator = new ASN1ObjectIdentifier("2.5.29.27");
+
+ /**
+ * Issuing Distribution Point
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier IssuingDistributionPoint = new ASN1ObjectIdentifier("2.5.29.28");
+
+ /**
+ * Certificate Issuer
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier CertificateIssuer = new ASN1ObjectIdentifier("2.5.29.29");
+
+ /**
+ * Name Constraints
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier NameConstraints = new ASN1ObjectIdentifier("2.5.29.30");
+
+ /**
+ * CRL Distribution Points
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier CRLDistributionPoints = new ASN1ObjectIdentifier("2.5.29.31");
+
+ /**
+ * Certificate Policies
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier CertificatePolicies = new ASN1ObjectIdentifier("2.5.29.32");
+
+ /**
+ * Policy Mappings
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier PolicyMappings = new ASN1ObjectIdentifier("2.5.29.33");
+
+ /**
+ * Authority Key Identifier
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier AuthorityKeyIdentifier = new ASN1ObjectIdentifier("2.5.29.35");
+
+ /**
+ * Policy Constraints
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier PolicyConstraints = new ASN1ObjectIdentifier("2.5.29.36");
+
+ /**
+ * Extended Key Usage
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier ExtendedKeyUsage = new ASN1ObjectIdentifier("2.5.29.37");
+
+ /**
+ * Freshest CRL
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier FreshestCRL = new ASN1ObjectIdentifier("2.5.29.46");
+
+ /**
+ * Inhibit Any Policy
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier InhibitAnyPolicy = new ASN1ObjectIdentifier("2.5.29.54");
+
+ /**
+ * Authority Info Access
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier AuthorityInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.1");
+
+ /**
+ * Subject Info Access
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier SubjectInfoAccess = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.11");
+
+ /**
+ * Logo Type
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier LogoType = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.12");
+
+ /**
+ * BiometricInfo
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier BiometricInfo = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.2");
+
+ /**
+ * QCStatements
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier QCStatements = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.3");
+
+ /**
+ * Audit identity extension in attribute certificates.
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier AuditIdentity = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.1.4");
+
+ /**
+ * NoRevAvail extension in attribute certificates.
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier NoRevAvail = new ASN1ObjectIdentifier("2.5.29.56");
+
+ /**
+ * TargetInformation extension in attribute certificates.
+ * @deprecated use X509Extension value.
+ */
+ public static final ASN1ObjectIdentifier TargetInformation = new ASN1ObjectIdentifier("2.5.29.55");
+
+ private Hashtable extensions = new Hashtable();
+ private Vector ordering = new Vector();
+
+ public static X509Extensions getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static X509Extensions getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof X509Extensions)
+ {
+ return (X509Extensions)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new X509Extensions((ASN1Sequence)obj);
+ }
+
+ if (obj instanceof Extensions)
+ {
+ return new X509Extensions((ASN1Sequence)((Extensions)obj).toASN1Primitive());
+ }
+
+ if (obj instanceof ASN1TaggedObject)
+ {
+ return getInstance(((ASN1TaggedObject)obj).getObject());
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
+ */
+ public X509Extensions(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(e.nextElement());
+
+ if (s.size() == 3)
+ {
+ extensions.put(s.getObjectAt(0), new X509Extension(DERBoolean.getInstance(s.getObjectAt(1)), ASN1OctetString.getInstance(s.getObjectAt(2))));
+ }
+ else if (s.size() == 2)
+ {
+ extensions.put(s.getObjectAt(0), new X509Extension(false, ASN1OctetString.getInstance(s.getObjectAt(1))));
+ }
+ else
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + s.size());
+ }
+
+ ordering.addElement(s.getObjectAt(0));
+ }
+ }
+
+ /**
+ * constructor from a table of extensions.
+ *
+ * it's is assumed the table contains OID/String pairs.
+ */
+ public X509Extensions(
+ Hashtable extensions)
+ {
+ this(null, extensions);
+ }
+
+ /**
+ * Constructor from a table of extensions with ordering.
+ *
+ * It's is assumed the table contains OID/String pairs.
+ * @deprecated use Extensions
+ */
+ public X509Extensions(
+ Vector ordering,
+ Hashtable extensions)
+ {
+ Enumeration e;
+
+ if (ordering == null)
+ {
+ e = extensions.keys();
+ }
+ else
+ {
+ e = ordering.elements();
+ }
+
+ while (e.hasMoreElements())
+ {
+ this.ordering.addElement(ASN1ObjectIdentifier.getInstance(e.nextElement()));
+ }
+
+ e = this.ordering.elements();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(e.nextElement());
+ X509Extension ext = (X509Extension)extensions.get(oid);
+
+ this.extensions.put(oid, ext);
+ }
+ }
+
+ /**
+ * Constructor from two vectors
+ *
+ * @param objectIDs a vector of the object identifiers.
+ * @param values a vector of the extension values.
+ * @deprecated use Extensions
+ */
+ public X509Extensions(
+ Vector objectIDs,
+ Vector values)
+ {
+ Enumeration e = objectIDs.elements();
+
+ while (e.hasMoreElements())
+ {
+ this.ordering.addElement(e.nextElement());
+ }
+
+ int count = 0;
+
+ e = this.ordering.elements();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
+ X509Extension ext = (X509Extension)values.elementAt(count);
+
+ this.extensions.put(oid, ext);
+ count++;
+ }
+ }
+
+ /**
+ * return an Enumeration of the extension field's object ids.
+ */
+ public Enumeration oids()
+ {
+ return ordering.elements();
+ }
+
+ /**
+ * return the extension represented by the object identifier
+ * passed in.
+ *
+ * @return the extension if it's present, null otherwise.
+ */
+ public X509Extension getExtension(
+ DERObjectIdentifier oid)
+ {
+ return (X509Extension)extensions.get(oid);
+ }
+
+ /**
+ * @deprecated
+ * @param oid
+ * @return
+ */
+ public X509Extension getExtension(
+ ASN1ObjectIdentifier oid)
+ {
+ return (X509Extension)extensions.get(oid);
+ }
+
+ /**
+ *
+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+ *
+ * Extension ::= SEQUENCE {
+ * extnId EXTENSION.&id ({ExtensionSet}),
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ Enumeration e = ordering.elements();
+
+ while (e.hasMoreElements())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
+ X509Extension ext = (X509Extension)extensions.get(oid);
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(oid);
+
+ if (ext.isCritical())
+ {
+ v.add(DERBoolean.TRUE);
+ }
+
+ v.add(ext.getValue());
+
+ vec.add(new DERSequence(v));
+ }
+
+ return new DERSequence(vec);
+ }
+
+ public boolean equivalent(
+ X509Extensions other)
+ {
+ if (extensions.size() != other.extensions.size())
+ {
+ return false;
+ }
+
+ Enumeration e1 = extensions.keys();
+
+ while (e1.hasMoreElements())
+ {
+ Object key = e1.nextElement();
+
+ if (!extensions.get(key).equals(other.extensions.get(key)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public ASN1ObjectIdentifier[] getExtensionOIDs()
+ {
+ return toOidArray(ordering);
+ }
+
+ public ASN1ObjectIdentifier[] getNonCriticalExtensionOIDs()
+ {
+ return getExtensionOIDs(false);
+ }
+
+ public ASN1ObjectIdentifier[] getCriticalExtensionOIDs()
+ {
+ return getExtensionOIDs(true);
+ }
+
+ private ASN1ObjectIdentifier[] getExtensionOIDs(boolean isCritical)
+ {
+ Vector oidVec = new Vector();
+
+ for (int i = 0; i != ordering.size(); i++)
+ {
+ Object oid = ordering.elementAt(i);
+
+ if (((X509Extension)extensions.get(oid)).isCritical() == isCritical)
+ {
+ oidVec.addElement(oid);
+ }
+ }
+
+ return toOidArray(oidVec);
+ }
+
+ private ASN1ObjectIdentifier[] toOidArray(Vector oidVec)
+ {
+ ASN1ObjectIdentifier[] oids = new ASN1ObjectIdentifier[oidVec.size()];
+
+ for (int i = 0; i != oids.length; i++)
+ {
+ oids[i] = (ASN1ObjectIdentifier)oidVec.elementAt(i);
+ }
+ return oids;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509ExtensionsGenerator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,117 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Encoding;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+
+/**
+ * Generator for X.509 extensions
+ * @deprecated use pdftk.org.bouncycastle.asn1.x509.ExtensionsGenerator
+ */
+public class X509ExtensionsGenerator
+{
+ private Hashtable extensions = new Hashtable();
+ private Vector extOrdering = new Vector();
+
+ /**
+ * Reset the generator
+ */
+ public void reset()
+ {
+ extensions = new Hashtable();
+ extOrdering = new Vector();
+ }
+
+ /**
+ * @deprecated use ASN1ObjectIdentifier
+ */
+ public void addExtension(
+ DERObjectIdentifier oid,
+ boolean critical,
+ ASN1Encodable value)
+ {
+ addExtension(new ASN1ObjectIdentifier(oid.getId()), critical, value);
+ }
+
+ /**
+ * @deprecated use ASN1ObjectIdentifier
+ */
+ public void addExtension(
+ DERObjectIdentifier oid,
+ boolean critical,
+ byte[] value)
+ {
+ addExtension(new ASN1ObjectIdentifier(oid.getId()), critical, value);
+ }
+
+ /**
+ * Add an extension with the given oid and the passed in value to be included
+ * in the OCTET STRING associated with the extension.
+ *
+ * @param oid OID for the extension.
+ * @param critical true if critical, false otherwise.
+ * @param value the ASN.1 object to be included in the extension.
+ */
+ public void addExtension(
+ ASN1ObjectIdentifier oid,
+ boolean critical,
+ ASN1Encodable value)
+ {
+ try
+ {
+ this.addExtension(oid, critical, value.toASN1Primitive().getEncoded(ASN1Encoding.DER));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("error encoding value: " + e);
+ }
+ }
+
+ /**
+ * Add an extension with the given oid and the passed in byte array to be wrapped in the
+ * OCTET STRING associated with the extension.
+ *
+ * @param oid OID for the extension.
+ * @param critical true if critical, false otherwise.
+ * @param value the byte array to be wrapped.
+ */
+ public void addExtension(
+ ASN1ObjectIdentifier oid,
+ boolean critical,
+ byte[] value)
+ {
+ if (extensions.containsKey(oid))
+ {
+ throw new IllegalArgumentException("extension " + oid + " already added");
+ }
+
+ extOrdering.addElement(oid);
+ extensions.put(oid, new X509Extension(critical, new DEROctetString(value)));
+ }
+
+ /**
+ * Return true if there are no extension present in this generator.
+ *
+ * @return true if empty, false otherwise
+ */
+ public boolean isEmpty()
+ {
+ return extOrdering.isEmpty();
+ }
+
+ /**
+ * Generate an X509Extensions object based on the current state of the generator.
+ *
+ * @return an X09Extensions object.
+ */
+ public X509Extensions generate()
+ {
+ return new X509Extensions(extOrdering, extensions);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509Name.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509Name.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509Name.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509Name.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,1280 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Encoding;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1Set;
+import pdftk.org.bouncycastle.asn1.ASN1String;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERSet;
+import pdftk.org.bouncycastle.asn1.DERUniversalString;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+import pdftk.org.bouncycastle.util.Strings;
+import pdftk.org.bouncycastle.util.encoders.Hex;
+
+/**
+ *
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ *
+ * RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type OBJECT IDENTIFIER,
+ * value ANY }
+ *
+ * @deprecated use pdftk.org.bouncycastle.asn1.x500.X500Name.
+ */
+public class X509Name
+ extends ASN1Object
+{
+ /**
+ * country code - StringType(SIZE(2))
+ * @deprecated use a X500NameStyle
+ */
+ public static final ASN1ObjectIdentifier C = new ASN1ObjectIdentifier("2.5.4.6");
+
+ /**
+ * organization - StringType(SIZE(1..64))
+ * @deprecated use a X500NameStyle
+ */
+ public static final ASN1ObjectIdentifier O = new ASN1ObjectIdentifier("2.5.4.10");
+
+ /**
+ * organizational unit name - StringType(SIZE(1..64))
+ * @deprecated use a X500NameStyle
+ */
+ public static final ASN1ObjectIdentifier OU = new ASN1ObjectIdentifier("2.5.4.11");
+
+ /**
+ * Title
+ * @deprecated use a X500NameStyle
+ */
+ public static final ASN1ObjectIdentifier T = new ASN1ObjectIdentifier("2.5.4.12");
+
+ /**
+ * common name - StringType(SIZE(1..64))
+ * @deprecated use a X500NameStyle
+ */
+ public static final ASN1ObjectIdentifier CN = new ASN1ObjectIdentifier("2.5.4.3");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SN = new ASN1ObjectIdentifier("2.5.4.5");
+
+ /**
+ * street - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier STREET = new ASN1ObjectIdentifier("2.5.4.9");
+
+ /**
+ * device serial number name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier SERIALNUMBER = SN;
+
+ /**
+ * locality name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier L = new ASN1ObjectIdentifier("2.5.4.7");
+
+ /**
+ * state, or province name - StringType(SIZE(1..64))
+ */
+ public static final ASN1ObjectIdentifier ST = new ASN1ObjectIdentifier("2.5.4.8");
+
+ /**
+ * Naming attributes of type X520name
+ */
+ public static final ASN1ObjectIdentifier SURNAME = new ASN1ObjectIdentifier("2.5.4.4");
+ public static final ASN1ObjectIdentifier GIVENNAME = new ASN1ObjectIdentifier("2.5.4.42");
+ public static final ASN1ObjectIdentifier INITIALS = new ASN1ObjectIdentifier("2.5.4.43");
+ public static final ASN1ObjectIdentifier GENERATION = new ASN1ObjectIdentifier("2.5.4.44");
+ public static final ASN1ObjectIdentifier UNIQUE_IDENTIFIER = new ASN1ObjectIdentifier("2.5.4.45");
+
+ /**
+ * businessCategory - DirectoryString(SIZE(1..128)
+ */
+ public static final ASN1ObjectIdentifier BUSINESS_CATEGORY = new ASN1ObjectIdentifier(
+ "2.5.4.15");
+
+ /**
+ * postalCode - DirectoryString(SIZE(1..40)
+ */
+ public static final ASN1ObjectIdentifier POSTAL_CODE = new ASN1ObjectIdentifier(
+ "2.5.4.17");
+
+ /**
+ * dnQualifier - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier DN_QUALIFIER = new ASN1ObjectIdentifier(
+ "2.5.4.46");
+
+ /**
+ * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier PSEUDONYM = new ASN1ObjectIdentifier(
+ "2.5.4.65");
+
+
+ /**
+ * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
+ */
+ public static final ASN1ObjectIdentifier DATE_OF_BIRTH = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.1");
+
+ /**
+ * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
+ */
+ public static final ASN1ObjectIdentifier PLACE_OF_BIRTH = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.2");
+
+ /**
+ * RFC 3039 Gender - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
+ */
+ public static final ASN1ObjectIdentifier GENDER = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.3");
+
+ /**
+ * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static final ASN1ObjectIdentifier COUNTRY_OF_CITIZENSHIP = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.4");
+
+ /**
+ * RFC 3039 CountryOfResidence - PrintableString (SIZE (2)) -- ISO 3166
+ * codes only
+ */
+ public static final ASN1ObjectIdentifier COUNTRY_OF_RESIDENCE = new ASN1ObjectIdentifier(
+ "1.3.6.1.5.5.7.9.5");
+
+
+ /**
+ * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
+ */
+ public static final ASN1ObjectIdentifier NAME_AT_BIRTH = new ASN1ObjectIdentifier("1.3.36.8.3.14");
+
+ /**
+ * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
+ * DirectoryString(SIZE(1..30))
+ */
+ public static final ASN1ObjectIdentifier POSTAL_ADDRESS = new ASN1ObjectIdentifier("2.5.4.16");
+
+ /**
+ * RFC 2256 dmdName
+ */
+ public static final ASN1ObjectIdentifier DMD_NAME = new ASN1ObjectIdentifier("2.5.4.54");
+
+ /**
+ * id-at-telephoneNumber
+ */
+ public static final ASN1ObjectIdentifier TELEPHONE_NUMBER = X509ObjectIdentifiers.id_at_telephoneNumber;
+
+ /**
+ * id-at-name
+ */
+ public static final ASN1ObjectIdentifier NAME = X509ObjectIdentifiers.id_at_name;
+
+ /**
+ * Email address (RSA PKCS#9 extension) - IA5String.
+ * Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.
+ * @deprecated use a X500NameStyle
+ */
+ public static final ASN1ObjectIdentifier EmailAddress = PKCSObjectIdentifiers.pkcs_9_at_emailAddress;
+
+ /**
+ * more from PKCS#9
+ */
+ public static final ASN1ObjectIdentifier UnstructuredName = PKCSObjectIdentifiers.pkcs_9_at_unstructuredName;
+ public static final ASN1ObjectIdentifier UnstructuredAddress = PKCSObjectIdentifiers.pkcs_9_at_unstructuredAddress;
+
+ /**
+ * email address in Verisign certificates
+ */
+ public static final ASN1ObjectIdentifier E = EmailAddress;
+
+ /*
+ * others...
+ */
+ public static final ASN1ObjectIdentifier DC = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.25");
+
+ /**
+ * LDAP User id.
+ */
+ public static final ASN1ObjectIdentifier UID = new ASN1ObjectIdentifier("0.9.2342.19200300.100.1.1");
+
+ /**
+ * determines whether or not strings should be processed and printed
+ * from back to front.
+ */
+ public static boolean DefaultReverse = false;
+
+ /**
+ * default look up table translating OID values into their common symbols following
+ * the convention in RFC 2253 with a few extras
+ */
+ public static final Hashtable DefaultSymbols = new Hashtable();
+
+ /**
+ * look up table translating OID values into their common symbols following the convention in RFC 2253
+ *
+ */
+ public static final Hashtable RFC2253Symbols = new Hashtable();
+
+ /**
+ * look up table translating OID values into their common symbols following the convention in RFC 1779
+ *
+ */
+ public static final Hashtable RFC1779Symbols = new Hashtable();
+
+ /**
+ * look up table translating common symbols into their OIDS.
+ */
+ public static final Hashtable DefaultLookUp = new Hashtable();
+
+ /**
+ * look up table translating OID values into their common symbols
+ * @deprecated use DefaultSymbols
+ */
+ public static final Hashtable OIDLookUp = DefaultSymbols;
+
+ /**
+ * look up table translating string values into their OIDS -
+ * @deprecated use DefaultLookUp
+ */
+ public static final Hashtable SymbolLookUp = DefaultLookUp;
+
+ private static final Boolean TRUE = new Boolean(true); // for J2ME compatibility
+ private static final Boolean FALSE = new Boolean(false);
+
+ static
+ {
+ DefaultSymbols.put(C, "C");
+ DefaultSymbols.put(O, "O");
+ DefaultSymbols.put(T, "T");
+ DefaultSymbols.put(OU, "OU");
+ DefaultSymbols.put(CN, "CN");
+ DefaultSymbols.put(L, "L");
+ DefaultSymbols.put(ST, "ST");
+ DefaultSymbols.put(SN, "SERIALNUMBER");
+ DefaultSymbols.put(EmailAddress, "E");
+ DefaultSymbols.put(DC, "DC");
+ DefaultSymbols.put(UID, "UID");
+ DefaultSymbols.put(STREET, "STREET");
+ DefaultSymbols.put(SURNAME, "SURNAME");
+ DefaultSymbols.put(GIVENNAME, "GIVENNAME");
+ DefaultSymbols.put(INITIALS, "INITIALS");
+ DefaultSymbols.put(GENERATION, "GENERATION");
+ DefaultSymbols.put(UnstructuredAddress, "unstructuredAddress");
+ DefaultSymbols.put(UnstructuredName, "unstructuredName");
+ DefaultSymbols.put(UNIQUE_IDENTIFIER, "UniqueIdentifier");
+ DefaultSymbols.put(DN_QUALIFIER, "DN");
+ DefaultSymbols.put(PSEUDONYM, "Pseudonym");
+ DefaultSymbols.put(POSTAL_ADDRESS, "PostalAddress");
+ DefaultSymbols.put(NAME_AT_BIRTH, "NameAtBirth");
+ DefaultSymbols.put(COUNTRY_OF_CITIZENSHIP, "CountryOfCitizenship");
+ DefaultSymbols.put(COUNTRY_OF_RESIDENCE, "CountryOfResidence");
+ DefaultSymbols.put(GENDER, "Gender");
+ DefaultSymbols.put(PLACE_OF_BIRTH, "PlaceOfBirth");
+ DefaultSymbols.put(DATE_OF_BIRTH, "DateOfBirth");
+ DefaultSymbols.put(POSTAL_CODE, "PostalCode");
+ DefaultSymbols.put(BUSINESS_CATEGORY, "BusinessCategory");
+ DefaultSymbols.put(TELEPHONE_NUMBER, "TelephoneNumber");
+ DefaultSymbols.put(NAME, "Name");
+
+ RFC2253Symbols.put(C, "C");
+ RFC2253Symbols.put(O, "O");
+ RFC2253Symbols.put(OU, "OU");
+ RFC2253Symbols.put(CN, "CN");
+ RFC2253Symbols.put(L, "L");
+ RFC2253Symbols.put(ST, "ST");
+ RFC2253Symbols.put(STREET, "STREET");
+ RFC2253Symbols.put(DC, "DC");
+ RFC2253Symbols.put(UID, "UID");
+
+ RFC1779Symbols.put(C, "C");
+ RFC1779Symbols.put(O, "O");
+ RFC1779Symbols.put(OU, "OU");
+ RFC1779Symbols.put(CN, "CN");
+ RFC1779Symbols.put(L, "L");
+ RFC1779Symbols.put(ST, "ST");
+ RFC1779Symbols.put(STREET, "STREET");
+
+ DefaultLookUp.put("c", C);
+ DefaultLookUp.put("o", O);
+ DefaultLookUp.put("t", T);
+ DefaultLookUp.put("ou", OU);
+ DefaultLookUp.put("cn", CN);
+ DefaultLookUp.put("l", L);
+ DefaultLookUp.put("st", ST);
+ DefaultLookUp.put("sn", SN);
+ DefaultLookUp.put("serialnumber", SN);
+ DefaultLookUp.put("street", STREET);
+ DefaultLookUp.put("emailaddress", E);
+ DefaultLookUp.put("dc", DC);
+ DefaultLookUp.put("e", E);
+ DefaultLookUp.put("uid", UID);
+ DefaultLookUp.put("surname", SURNAME);
+ DefaultLookUp.put("givenname", GIVENNAME);
+ DefaultLookUp.put("initials", INITIALS);
+ DefaultLookUp.put("generation", GENERATION);
+ DefaultLookUp.put("unstructuredaddress", UnstructuredAddress);
+ DefaultLookUp.put("unstructuredname", UnstructuredName);
+ DefaultLookUp.put("uniqueidentifier", UNIQUE_IDENTIFIER);
+ DefaultLookUp.put("dn", DN_QUALIFIER);
+ DefaultLookUp.put("pseudonym", PSEUDONYM);
+ DefaultLookUp.put("postaladdress", POSTAL_ADDRESS);
+ DefaultLookUp.put("nameofbirth", NAME_AT_BIRTH);
+ DefaultLookUp.put("countryofcitizenship", COUNTRY_OF_CITIZENSHIP);
+ DefaultLookUp.put("countryofresidence", COUNTRY_OF_RESIDENCE);
+ DefaultLookUp.put("gender", GENDER);
+ DefaultLookUp.put("placeofbirth", PLACE_OF_BIRTH);
+ DefaultLookUp.put("dateofbirth", DATE_OF_BIRTH);
+ DefaultLookUp.put("postalcode", POSTAL_CODE);
+ DefaultLookUp.put("businesscategory", BUSINESS_CATEGORY);
+ DefaultLookUp.put("telephonenumber", TELEPHONE_NUMBER);
+ DefaultLookUp.put("name", NAME);
+ }
+
+ private X509NameEntryConverter converter = null;
+ private Vector ordering = new Vector();
+ private Vector values = new Vector();
+ private Vector added = new Vector();
+
+ private ASN1Sequence seq;
+
+ private boolean isHashCodeCalculated;
+ private int hashCodeValue;
+
+ /**
+ * Return a X509Name based on the passed in tagged object.
+ *
+ * @param obj tag object holding name.
+ * @param explicit true if explicitly tagged false otherwise.
+ * @return the X509Name
+ */
+ public static X509Name getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static X509Name getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof X509Name)
+ {
+ return (X509Name)obj;
+ }
+ else if (obj instanceof X500Name)
+ {
+ return new X509Name(ASN1Sequence.getInstance(((X500Name)obj).toASN1Primitive()));
+ }
+ else if (obj != null)
+ {
+ return new X509Name(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ protected X509Name()
+ {
+ // constructure use by new X500 Name class
+ }
+ /**
+ * Constructor from ASN1Sequence
+ *
+ * the principal will be a list of constructed sets, each containing an (OID, String) pair.
+ */
+ public X509Name(
+ ASN1Sequence seq)
+ {
+ this.seq = seq;
+
+ Enumeration e = seq.getObjects();
+
+ while (e.hasMoreElements())
+ {
+ ASN1Set set = ASN1Set.getInstance(((ASN1Encodable)e.nextElement()).toASN1Primitive());
+
+ for (int i = 0; i < set.size(); i++)
+ {
+ ASN1Sequence s = ASN1Sequence.getInstance(set.getObjectAt(i).toASN1Primitive());
+
+ if (s.size() != 2)
+ {
+ throw new IllegalArgumentException("badly sized pair");
+ }
+
+ ordering.addElement(ASN1ObjectIdentifier.getInstance(s.getObjectAt(0)));
+
+ ASN1Encodable value = s.getObjectAt(1);
+ if (value instanceof ASN1String && !(value instanceof DERUniversalString))
+ {
+ String v = ((ASN1String)value).getString();
+ if (v.length() > 0 && v.charAt(0) == '#')
+ {
+ values.addElement("\\" + v);
+ }
+ else
+ {
+ values.addElement(v);
+ }
+ }
+ else
+ {
+ try
+ {
+ values.addElement("#" + bytesToString(Hex.encode(value.toASN1Primitive().getEncoded(ASN1Encoding.DER))));
+ }
+ catch (IOException e1)
+ {
+ throw new IllegalArgumentException("cannot encode value");
+ }
+ }
+ added.addElement((i != 0) ? TRUE : FALSE); // to allow earlier JDK compatibility
+ }
+ }
+ }
+
+ /**
+ * constructor from a table of attributes.
+ *
+ * it's is assumed the table contains OID/String pairs, and the contents
+ * of the table are copied into an internal table as part of the
+ * construction process.
+ *
+ * Note: if the name you are trying to generate should be
+ * following a specific ordering, you should use the constructor
+ * with the ordering specified below.
+ * @deprecated use an ordered constructor! The hashtable ordering is rarely correct
+ */
+ public X509Name(
+ Hashtable attributes)
+ {
+ this(null, attributes);
+ }
+
+ /**
+ * Constructor from a table of attributes with ordering.
+ *
+ * it's is assumed the table contains OID/String pairs, and the contents
+ * of the table are copied into an internal table as part of the
+ * construction process. The ordering vector should contain the OIDs
+ * in the order they are meant to be encoded or printed in toString.
+ */
+ public X509Name(
+ Vector ordering,
+ Hashtable attributes)
+ {
+ this(ordering, attributes, new X509DefaultEntryConverter());
+ }
+
+ /**
+ * Constructor from a table of attributes with ordering.
+ *
+ * it's is assumed the table contains OID/String pairs, and the contents
+ * of the table are copied into an internal table as part of the
+ * construction process. The ordering vector should contain the OIDs
+ * in the order they are meant to be encoded or printed in toString.
+ *
+ * The passed in converter will be used to convert the strings into their
+ * ASN.1 counterparts.
+ */
+ public X509Name(
+ Vector ordering,
+ Hashtable attributes,
+ X509NameEntryConverter converter)
+ {
+ this.converter = converter;
+
+ if (ordering != null)
+ {
+ for (int i = 0; i != ordering.size(); i++)
+ {
+ this.ordering.addElement(ordering.elementAt(i));
+ this.added.addElement(FALSE);
+ }
+ }
+ else
+ {
+ Enumeration e = attributes.keys();
+
+ while (e.hasMoreElements())
+ {
+ this.ordering.addElement(e.nextElement());
+ this.added.addElement(FALSE);
+ }
+ }
+
+ for (int i = 0; i != this.ordering.size(); i++)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)this.ordering.elementAt(i);
+
+ if (attributes.get(oid) == null)
+ {
+ throw new IllegalArgumentException("No attribute for object id - " + oid.getId() + " - passed to distinguished name");
+ }
+
+ this.values.addElement(attributes.get(oid)); // copy the hash table
+ }
+ }
+
+ /**
+ * Takes two vectors one of the oids and the other of the values.
+ */
+ public X509Name(
+ Vector oids,
+ Vector values)
+ {
+ this(oids, values, new X509DefaultEntryConverter());
+ }
+
+ /**
+ * Takes two vectors one of the oids and the other of the values.
+ *
+ * The passed in converter will be used to convert the strings into their
+ * ASN.1 counterparts.
+ */
+ public X509Name(
+ Vector oids,
+ Vector values,
+ X509NameEntryConverter converter)
+ {
+ this.converter = converter;
+
+ if (oids.size() != values.size())
+ {
+ throw new IllegalArgumentException("oids vector must be same length as values.");
+ }
+
+ for (int i = 0; i < oids.size(); i++)
+ {
+ this.ordering.addElement(oids.elementAt(i));
+ this.values.addElement(values.elementAt(i));
+ this.added.addElement(FALSE);
+ }
+ }
+
+// private Boolean isEncoded(String s)
+// {
+// if (s.charAt(0) == '#')
+// {
+// return TRUE;
+// }
+//
+// return FALSE;
+// }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes.
+ */
+ public X509Name(
+ String dirName)
+ {
+ this(DefaultReverse, DefaultLookUp, dirName);
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes with each
+ * string value being converted to its associated ASN.1 type using the passed
+ * in converter.
+ */
+ public X509Name(
+ String dirName,
+ X509NameEntryConverter converter)
+ {
+ this(DefaultReverse, DefaultLookUp, dirName, converter);
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes. If reverse
+ * is true, create the encoded version of the sequence starting from the
+ * last element in the string.
+ */
+ public X509Name(
+ boolean reverse,
+ String dirName)
+ {
+ this(reverse, DefaultLookUp, dirName);
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes with each
+ * string value being converted to its associated ASN.1 type using the passed
+ * in converter. If reverse is true the ASN.1 sequence representing the DN will
+ * be built by starting at the end of the string, rather than the start.
+ */
+ public X509Name(
+ boolean reverse,
+ String dirName,
+ X509NameEntryConverter converter)
+ {
+ this(reverse, DefaultLookUp, dirName, converter);
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes. lookUp
+ * should provide a table of lookups, indexed by lowercase only strings and
+ * yielding a ASN1ObjectIdentifier, other than that OID. and numeric oids
+ * will be processed automatically.
+ *
+ * If reverse is true, create the encoded version of the sequence
+ * starting from the last element in the string.
+ * @param reverse true if we should start scanning from the end (RFC 2553).
+ * @param lookUp table of names and their oids.
+ * @param dirName the X.500 string to be parsed.
+ */
+ public X509Name(
+ boolean reverse,
+ Hashtable lookUp,
+ String dirName)
+ {
+ this(reverse, lookUp, dirName, new X509DefaultEntryConverter());
+ }
+
+ private ASN1ObjectIdentifier decodeOID(
+ String name,
+ Hashtable lookUp)
+ {
+ if (Strings.toUpperCase(name).startsWith("OID."))
+ {
+ return new ASN1ObjectIdentifier(name.substring(4));
+ }
+ else if (name.charAt(0) >= '0' && name.charAt(0) <= '9')
+ {
+ return new ASN1ObjectIdentifier(name);
+ }
+
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)lookUp.get(Strings.toLowerCase(name));
+ if (oid == null)
+ {
+ throw new IllegalArgumentException("Unknown object id - " + name + " - passed to distinguished name");
+ }
+
+ return oid;
+ }
+
+ /**
+ * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+ * some such, converting it into an ordered set of name attributes. lookUp
+ * should provide a table of lookups, indexed by lowercase only strings and
+ * yielding a ASN1ObjectIdentifier, other than that OID. and numeric oids
+ * will be processed automatically. The passed in converter is used to convert the
+ * string values to the right of each equals sign to their ASN.1 counterparts.
+ *
+ * @param reverse true if we should start scanning from the end, false otherwise.
+ * @param lookUp table of names and oids.
+ * @param dirName the string dirName
+ * @param converter the converter to convert string values into their ASN.1 equivalents
+ */
+ public X509Name(
+ boolean reverse,
+ Hashtable lookUp,
+ String dirName,
+ X509NameEntryConverter converter)
+ {
+ this.converter = converter;
+ X509NameTokenizer nTok = new X509NameTokenizer(dirName);
+
+ while (nTok.hasMoreTokens())
+ {
+ String token = nTok.nextToken();
+ int index = token.indexOf('=');
+
+ if (index == -1)
+ {
+ throw new IllegalArgumentException("badly formatted directory string");
+ }
+
+ String name = token.substring(0, index);
+ String value = token.substring(index + 1);
+ ASN1ObjectIdentifier oid = decodeOID(name, lookUp);
+
+ if (value.indexOf('+') > 0)
+ {
+ X509NameTokenizer vTok = new X509NameTokenizer(value, '+');
+ String v = vTok.nextToken();
+
+ this.ordering.addElement(oid);
+ this.values.addElement(v);
+ this.added.addElement(FALSE);
+
+ while (vTok.hasMoreTokens())
+ {
+ String sv = vTok.nextToken();
+ int ndx = sv.indexOf('=');
+
+ String nm = sv.substring(0, ndx);
+ String vl = sv.substring(ndx + 1);
+ this.ordering.addElement(decodeOID(nm, lookUp));
+ this.values.addElement(vl);
+ this.added.addElement(TRUE);
+ }
+ }
+ else
+ {
+ this.ordering.addElement(oid);
+ this.values.addElement(value);
+ this.added.addElement(FALSE);
+ }
+ }
+
+ if (reverse)
+ {
+ Vector o = new Vector();
+ Vector v = new Vector();
+ Vector a = new Vector();
+
+ int count = 1;
+
+ for (int i = 0; i < this.ordering.size(); i++)
+ {
+ if (((Boolean)this.added.elementAt(i)).booleanValue())
+ {
+ o.insertElementAt(this.ordering.elementAt(i), count);
+ v.insertElementAt(this.values.elementAt(i), count);
+ a.insertElementAt(this.added.elementAt(i), count);
+ count++;
+ }
+ else
+ {
+ o.insertElementAt(this.ordering.elementAt(i), 0);
+ v.insertElementAt(this.values.elementAt(i), 0);
+ a.insertElementAt(this.added.elementAt(i), 0);
+ count = 1;
+ }
+ }
+
+ this.ordering = o;
+ this.values = v;
+ this.added = a;
+ }
+ }
+
+ /**
+ * return a vector of the oids in the name, in the order they were found.
+ */
+ public Vector getOIDs()
+ {
+ Vector v = new Vector();
+
+ for (int i = 0; i != ordering.size(); i++)
+ {
+ v.addElement(ordering.elementAt(i));
+ }
+
+ return v;
+ }
+
+ /**
+ * return a vector of the values found in the name, in the order they
+ * were found.
+ */
+ public Vector getValues()
+ {
+ Vector v = new Vector();
+
+ for (int i = 0; i != values.size(); i++)
+ {
+ v.addElement(values.elementAt(i));
+ }
+
+ return v;
+ }
+
+ /**
+ * return a vector of the values found in the name, in the order they
+ * were found, with the DN label corresponding to passed in oid.
+ */
+ public Vector getValues(
+ ASN1ObjectIdentifier oid)
+ {
+ Vector v = new Vector();
+
+ for (int i = 0; i != values.size(); i++)
+ {
+ if (ordering.elementAt(i).equals(oid))
+ {
+ String val = (String)values.elementAt(i);
+
+ if (val.length() > 2 && val.charAt(0) == '\\' && val.charAt(1) == '#')
+ {
+ v.addElement(val.substring(1));
+ }
+ else
+ {
+ v.addElement(val);
+ }
+ }
+ }
+
+ return v;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (seq == null)
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ ASN1EncodableVector sVec = new ASN1EncodableVector();
+ ASN1ObjectIdentifier lstOid = null;
+
+ for (int i = 0; i != ordering.size(); i++)
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)ordering.elementAt(i);
+
+ v.add(oid);
+
+ String str = (String)values.elementAt(i);
+
+ v.add(converter.getConvertedValue(oid, str));
+
+ if (lstOid == null
+ || ((Boolean)this.added.elementAt(i)).booleanValue())
+ {
+ sVec.add(new DERSequence(v));
+ }
+ else
+ {
+ vec.add(new DERSet(sVec));
+ sVec = new ASN1EncodableVector();
+
+ sVec.add(new DERSequence(v));
+ }
+
+ lstOid = oid;
+ }
+
+ vec.add(new DERSet(sVec));
+
+ seq = new DERSequence(vec);
+ }
+
+ return seq;
+ }
+
+ /**
+ * @param inOrder if true the order of both X509 names must be the same,
+ * as well as the values associated with each element.
+ */
+ public boolean equals(Object obj, boolean inOrder)
+ {
+ if (!inOrder)
+ {
+ return this.equals(obj);
+ }
+
+ if (obj == this)
+ {
+ return true;
+ }
+
+ if (!(obj instanceof X509Name || obj instanceof ASN1Sequence))
+ {
+ return false;
+ }
+
+ ASN1Primitive derO = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (this.toASN1Primitive().equals(derO))
+ {
+ return true;
+ }
+
+ X509Name other;
+
+ try
+ {
+ other = X509Name.getInstance(obj);
+ }
+ catch (IllegalArgumentException e)
+ {
+ return false;
+ }
+
+ int orderingSize = ordering.size();
+
+ if (orderingSize != other.ordering.size())
+ {
+ return false;
+ }
+
+ for (int i = 0; i < orderingSize; i++)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)ordering.elementAt(i);
+ ASN1ObjectIdentifier oOid = (ASN1ObjectIdentifier)other.ordering.elementAt(i);
+
+ if (oid.equals(oOid))
+ {
+ String value = (String)values.elementAt(i);
+ String oValue = (String)other.values.elementAt(i);
+
+ if (!equivalentStrings(value, oValue))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ if (isHashCodeCalculated)
+ {
+ return hashCodeValue;
+ }
+
+ isHashCodeCalculated = true;
+
+ // this needs to be order independent, like equals
+ for (int i = 0; i != ordering.size(); i += 1)
+ {
+ String value = (String)values.elementAt(i);
+
+ value = canonicalize(value);
+ value = stripInternalSpaces(value);
+
+ hashCodeValue ^= ordering.elementAt(i).hashCode();
+ hashCodeValue ^= value.hashCode();
+ }
+
+ return hashCodeValue;
+ }
+
+ /**
+ * test for equality - note: case is ignored.
+ */
+ public boolean equals(Object obj)
+ {
+ if (obj == this)
+ {
+ return true;
+ }
+
+ if (!(obj instanceof X509Name || obj instanceof ASN1Sequence))
+ {
+ return false;
+ }
+
+ ASN1Primitive derO = ((ASN1Encodable)obj).toASN1Primitive();
+
+ if (this.toASN1Primitive().equals(derO))
+ {
+ return true;
+ }
+
+ X509Name other;
+
+ try
+ {
+ other = X509Name.getInstance(obj);
+ }
+ catch (IllegalArgumentException e)
+ {
+ return false;
+ }
+
+ int orderingSize = ordering.size();
+
+ if (orderingSize != other.ordering.size())
+ {
+ return false;
+ }
+
+ boolean[] indexes = new boolean[orderingSize];
+ int start, end, delta;
+
+ if (ordering.elementAt(0).equals(other.ordering.elementAt(0))) // guess forward
+ {
+ start = 0;
+ end = orderingSize;
+ delta = 1;
+ }
+ else // guess reversed - most common problem
+ {
+ start = orderingSize - 1;
+ end = -1;
+ delta = -1;
+ }
+
+ for (int i = start; i != end; i += delta)
+ {
+ boolean found = false;
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)ordering.elementAt(i);
+ String value = (String)values.elementAt(i);
+
+ for (int j = 0; j < orderingSize; j++)
+ {
+ if (indexes[j])
+ {
+ continue;
+ }
+
+ ASN1ObjectIdentifier oOid = (ASN1ObjectIdentifier)other.ordering.elementAt(j);
+
+ if (oid.equals(oOid))
+ {
+ String oValue = (String)other.values.elementAt(j);
+
+ if (equivalentStrings(value, oValue))
+ {
+ indexes[j] = true;
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean equivalentStrings(String s1, String s2)
+ {
+ String value = canonicalize(s1);
+ String oValue = canonicalize(s2);
+
+ if (!value.equals(oValue))
+ {
+ value = stripInternalSpaces(value);
+ oValue = stripInternalSpaces(oValue);
+
+ if (!value.equals(oValue))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private String canonicalize(String s)
+ {
+ String value = Strings.toLowerCase(s.trim());
+
+ if (value.length() > 0 && value.charAt(0) == '#')
+ {
+ ASN1Primitive obj = decodeObject(value);
+
+ if (obj instanceof ASN1String)
+ {
+ value = Strings.toLowerCase(((ASN1String)obj).getString().trim());
+ }
+ }
+
+ return value;
+ }
+
+ private ASN1Primitive decodeObject(String oValue)
+ {
+ try
+ {
+ return ASN1Primitive.fromByteArray(Hex.decode(oValue.substring(1)));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("unknown encoding in name: " + e);
+ }
+ }
+
+ private String stripInternalSpaces(
+ String str)
+ {
+ StringBuffer res = new StringBuffer();
+
+ if (str.length() != 0)
+ {
+ char c1 = str.charAt(0);
+
+ res.append(c1);
+
+ for (int k = 1; k < str.length(); k++)
+ {
+ char c2 = str.charAt(k);
+ if (!(c1 == ' ' && c2 == ' '))
+ {
+ res.append(c2);
+ }
+ c1 = c2;
+ }
+ }
+
+ return res.toString();
+ }
+
+ private void appendValue(
+ StringBuffer buf,
+ Hashtable oidSymbols,
+ ASN1ObjectIdentifier oid,
+ String value)
+ {
+ String sym = (String)oidSymbols.get(oid);
+
+ if (sym != null)
+ {
+ buf.append(sym);
+ }
+ else
+ {
+ buf.append(oid.getId());
+ }
+
+ buf.append('=');
+
+ int index = buf.length();
+
+ buf.append(value);
+
+ int end = buf.length();
+
+ if (value.length() >= 2 && value.charAt(0) == '\\' && value.charAt(1) == '#')
+ {
+ index += 2;
+ }
+
+ while (index != end)
+ {
+ if ((buf.charAt(index) == ',')
+ || (buf.charAt(index) == '"')
+ || (buf.charAt(index) == '\\')
+ || (buf.charAt(index) == '+')
+ || (buf.charAt(index) == '=')
+ || (buf.charAt(index) == '<')
+ || (buf.charAt(index) == '>')
+ || (buf.charAt(index) == ';'))
+ {
+ buf.insert(index, "\\");
+ index++;
+ end++;
+ }
+
+ index++;
+ }
+ }
+
+ /**
+ * convert the structure to a string - if reverse is true the
+ * oids and values are listed out starting with the last element
+ * in the sequence (ala RFC 2253), otherwise the string will begin
+ * with the first element of the structure. If no string definition
+ * for the oid is found in oidSymbols the string value of the oid is
+ * added. Two standard symbol tables are provided DefaultSymbols, and
+ * RFC2253Symbols as part of this class.
+ *
+ * @param reverse if true start at the end of the sequence and work back.
+ * @param oidSymbols look up table strings for oids.
+ */
+ public String toString(
+ boolean reverse,
+ Hashtable oidSymbols)
+ {
+ StringBuffer buf = new StringBuffer();
+ Vector components = new Vector();
+ boolean first = true;
+
+ StringBuffer ava = null;
+
+ for (int i = 0; i < ordering.size(); i++)
+ {
+ if (((Boolean)added.elementAt(i)).booleanValue())
+ {
+ ava.append('+');
+ appendValue(ava, oidSymbols,
+ (ASN1ObjectIdentifier)ordering.elementAt(i),
+ (String)values.elementAt(i));
+ }
+ else
+ {
+ ava = new StringBuffer();
+ appendValue(ava, oidSymbols,
+ (ASN1ObjectIdentifier)ordering.elementAt(i),
+ (String)values.elementAt(i));
+ components.addElement(ava);
+ }
+ }
+
+ if (reverse)
+ {
+ for (int i = components.size() - 1; i >= 0; i--)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append(',');
+ }
+
+ buf.append(components.elementAt(i).toString());
+ }
+ }
+ else
+ {
+ for (int i = 0; i < components.size(); i++)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ buf.append(',');
+ }
+
+ buf.append(components.elementAt(i).toString());
+ }
+ }
+
+ return buf.toString();
+ }
+
+ private String bytesToString(
+ byte[] data)
+ {
+ char[] cs = new char[data.length];
+
+ for (int i = 0; i != cs.length; i++)
+ {
+ cs[i] = (char)(data[i] & 0xff);
+ }
+
+ return new String(cs);
+ }
+
+ public String toString()
+ {
+ return toString(DefaultReverse, DefaultSymbols);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509NameEntryConverter.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509NameEntryConverter.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509NameEntryConverter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509NameEntryConverter.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,113 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1InputStream;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * It turns out that the number of standard ways the fields in a DN should be
+ * encoded into their ASN.1 counterparts is rapidly approaching the
+ * number of machines on the internet. By default the X509Name class
+ * will produce UTF8Strings in line with the current recommendations (RFC 3280).
+ *
+ * An example of an encoder look like below:
+ *
+ * public class X509DirEntryConverter
+ * extends X509NameEntryConverter
+ * {
+ * public ASN1Primitive getConvertedValue(
+ * ASN1ObjectIdentifier oid,
+ * String value)
+ * {
+ * if (str.length() != 0 && str.charAt(0) == '#')
+ * {
+ * return convertHexEncoded(str, 1);
+ * }
+ * if (oid.equals(EmailAddress))
+ * {
+ * return new DERIA5String(str);
+ * }
+ * else if (canBePrintable(str))
+ * {
+ * return new DERPrintableString(str);
+ * }
+ * else if (canBeUTF8(str))
+ * {
+ * return new DERUTF8String(str);
+ * }
+ * else
+ * {
+ * return new DERBMPString(str);
+ * }
+ * }
+ * }
+ */
+public abstract class X509NameEntryConverter
+{
+ /**
+ * Convert an inline encoded hex string rendition of an ASN.1
+ * object back into its corresponding ASN.1 object.
+ *
+ * @param str the hex encoded object
+ * @param off the index at which the encoding starts
+ * @return the decoded object
+ */
+ protected ASN1Primitive convertHexEncoded(
+ String str,
+ int off)
+ throws IOException
+ {
+ str = Strings.toLowerCase(str);
+ byte[] data = new byte[(str.length() - off) / 2];
+ for (int index = 0; index != data.length; index++)
+ {
+ char left = str.charAt((index * 2) + off);
+ char right = str.charAt((index * 2) + off + 1);
+
+ if (left < 'a')
+ {
+ data[index] = (byte)((left - '0') << 4);
+ }
+ else
+ {
+ data[index] = (byte)((left - 'a' + 10) << 4);
+ }
+ if (right < 'a')
+ {
+ data[index] |= (byte)(right - '0');
+ }
+ else
+ {
+ data[index] |= (byte)(right - 'a' + 10);
+ }
+ }
+
+ ASN1InputStream aIn = new ASN1InputStream(data);
+
+ return aIn.readObject();
+ }
+
+ /**
+ * return true if the passed in String can be represented without
+ * loss as a PrintableString, false otherwise.
+ */
+ protected boolean canBePrintable(
+ String str)
+ {
+ return DERPrintableString.isPrintableString(str);
+ }
+
+ /**
+ * Convert the passed in String value into the appropriate ASN.1
+ * encoded object.
+ *
+ * @param oid the oid associated with the value in the DN.
+ * @param value the value of the particular DN component.
+ * @return the ASN.1 equivalent for the value.
+ */
+ public abstract ASN1Primitive getConvertedValue(ASN1ObjectIdentifier oid, String value);
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509NameTokenizer.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509NameTokenizer.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509NameTokenizer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509NameTokenizer.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,108 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+/**
+ * class for breaking up an X500 Name into it's component tokens, ala
+ * java.util.StringTokenizer. We need this class as some of the
+ * lightweight Java environment don't support classes like
+ * StringTokenizer.
+ * @deprecated use X500NameTokenizer
+ */
+public class X509NameTokenizer
+{
+ private String value;
+ private int index;
+ private char separator;
+ private StringBuffer buf = new StringBuffer();
+
+ public X509NameTokenizer(
+ String oid)
+ {
+ this(oid, ',');
+ }
+
+ public X509NameTokenizer(
+ String oid,
+ char separator)
+ {
+ this.value = oid;
+ this.index = -1;
+ this.separator = separator;
+ }
+
+ public boolean hasMoreTokens()
+ {
+ return (index != value.length());
+ }
+
+ public String nextToken()
+ {
+ if (index == value.length())
+ {
+ return null;
+ }
+
+ int end = index + 1;
+ boolean quoted = false;
+ boolean escaped = false;
+
+ buf.setLength(0);
+
+ while (end != value.length())
+ {
+ char c = value.charAt(end);
+
+ if (c == '"')
+ {
+ if (!escaped)
+ {
+ quoted = !quoted;
+ }
+ else
+ {
+ if (c == '#' && buf.charAt(buf.length() - 1) == '=')
+ {
+ buf.append('\\');
+ }
+ else if (c == '+' && separator != '+')
+ {
+ buf.append('\\');
+ }
+ buf.append(c);
+ }
+ escaped = false;
+ }
+ else
+ {
+ if (escaped || quoted)
+ {
+ if (c == '#' && buf.charAt(buf.length() - 1) == '=')
+ {
+ buf.append('\\');
+ }
+ else if (c == '+' && separator != '+')
+ {
+ buf.append('\\');
+ }
+ buf.append(c);
+ escaped = false;
+ }
+ else if (c == '\\')
+ {
+ escaped = true;
+ }
+ else if (c == separator)
+ {
+ break;
+ }
+ else
+ {
+ buf.append(c);
+ }
+ }
+ end++;
+ }
+
+ index = end;
+ return buf.toString().trim();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/X509ObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,67 @@
+package pdftk.org.bouncycastle.asn1.x509;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface X509ObjectIdentifiers
+{
+ //
+ // base id
+ //
+ static final String id = "2.5.4";
+
+ static final ASN1ObjectIdentifier commonName = new ASN1ObjectIdentifier(id + ".3");
+ static final ASN1ObjectIdentifier countryName = new ASN1ObjectIdentifier(id + ".6");
+ static final ASN1ObjectIdentifier localityName = new ASN1ObjectIdentifier(id + ".7");
+ static final ASN1ObjectIdentifier stateOrProvinceName = new ASN1ObjectIdentifier(id + ".8");
+ static final ASN1ObjectIdentifier organization = new ASN1ObjectIdentifier(id + ".10");
+ static final ASN1ObjectIdentifier organizationalUnitName = new ASN1ObjectIdentifier(id + ".11");
+
+ static final ASN1ObjectIdentifier id_at_telephoneNumber = new ASN1ObjectIdentifier("2.5.4.20");
+ static final ASN1ObjectIdentifier id_at_name = new ASN1ObjectIdentifier(id + ".41");
+
+ // id-SHA1 OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } //
+ static final ASN1ObjectIdentifier id_SHA1 = new ASN1ObjectIdentifier("1.3.14.3.2.26");
+
+ //
+ // ripemd160 OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) hashAlgorithm(2) RIPEMD-160(1)}
+ //
+ static final ASN1ObjectIdentifier ripemd160 = new ASN1ObjectIdentifier("1.3.36.3.2.1");
+
+ //
+ // ripemd160WithRSAEncryption OBJECT IDENTIFIER ::=
+ // {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) rsaSignatureWithripemd160(2) }
+ //
+ static final ASN1ObjectIdentifier ripemd160WithRSAEncryption = new ASN1ObjectIdentifier("1.3.36.3.3.1.2");
+
+
+ static final ASN1ObjectIdentifier id_ea_rsa = new ASN1ObjectIdentifier("2.5.8.1.1");
+
+ // id-pkix
+ static final ASN1ObjectIdentifier id_pkix = new ASN1ObjectIdentifier("1.3.6.1.5.5.7");
+
+ //
+ // private internet extensions
+ //
+ static final ASN1ObjectIdentifier id_pe = new ASN1ObjectIdentifier(id_pkix + ".1");
+
+ //
+ // ISO ARC for standard certificate and CRL extensions
+ //
+ static final ASN1ObjectIdentifier id_ce = new ASN1ObjectIdentifier("2.5.29");
+
+ //
+ // authority information access
+ //
+ static final ASN1ObjectIdentifier id_ad = new ASN1ObjectIdentifier(id_pkix + ".48");
+ static final ASN1ObjectIdentifier id_ad_caIssuers = new ASN1ObjectIdentifier(id_ad + ".2");
+ static final ASN1ObjectIdentifier id_ad_ocsp = new ASN1ObjectIdentifier(id_ad + ".1");
+
+ //
+ // OID for ocsp and crl uri in AuthorityInformationAccess extension
+ //
+ static final ASN1ObjectIdentifier ocspAccessMethod = id_ad_ocsp;
+ static final ASN1ObjectIdentifier crlAccessMethod = id_ad_caIssuers;
+}
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes useful for encoding and processing X.509 certificates.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/BiometricData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/BiometricData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/BiometricData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/BiometricData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,122 @@
+package pdftk.org.bouncycastle.asn1.x509.qualified;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERIA5String;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+
+/**
+ * The BiometricData object.
+ *
+ * BiometricData ::= SEQUENCE {
+ * typeOfBiometricData TypeOfBiometricData,
+ * hashAlgorithm AlgorithmIdentifier,
+ * biometricDataHash OCTET STRING,
+ * sourceDataUri IA5String OPTIONAL }
+ *
+ */
+public class BiometricData
+ extends ASN1Object
+{
+ private TypeOfBiometricData typeOfBiometricData;
+ private AlgorithmIdentifier hashAlgorithm;
+ private ASN1OctetString biometricDataHash;
+ private DERIA5String sourceDataUri;
+
+ public static BiometricData getInstance(
+ Object obj)
+ {
+ if (obj instanceof BiometricData)
+ {
+ return (BiometricData)obj;
+ }
+
+ if (obj != null)
+ {
+ return new BiometricData(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private BiometricData(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ // typeOfBiometricData
+ typeOfBiometricData = TypeOfBiometricData.getInstance(e.nextElement());
+ // hashAlgorithm
+ hashAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement());
+ // biometricDataHash
+ biometricDataHash = ASN1OctetString.getInstance(e.nextElement());
+ // sourceDataUri
+ if (e.hasMoreElements())
+ {
+ sourceDataUri = DERIA5String.getInstance(e.nextElement());
+ }
+ }
+
+ public BiometricData(
+ TypeOfBiometricData typeOfBiometricData,
+ AlgorithmIdentifier hashAlgorithm,
+ ASN1OctetString biometricDataHash,
+ DERIA5String sourceDataUri)
+ {
+ this.typeOfBiometricData = typeOfBiometricData;
+ this.hashAlgorithm = hashAlgorithm;
+ this.biometricDataHash = biometricDataHash;
+ this.sourceDataUri = sourceDataUri;
+ }
+
+ public BiometricData(
+ TypeOfBiometricData typeOfBiometricData,
+ AlgorithmIdentifier hashAlgorithm,
+ ASN1OctetString biometricDataHash)
+ {
+ this.typeOfBiometricData = typeOfBiometricData;
+ this.hashAlgorithm = hashAlgorithm;
+ this.biometricDataHash = biometricDataHash;
+ this.sourceDataUri = null;
+ }
+
+ public TypeOfBiometricData getTypeOfBiometricData()
+ {
+ return typeOfBiometricData;
+ }
+
+ public AlgorithmIdentifier getHashAlgorithm()
+ {
+ return hashAlgorithm;
+ }
+
+ public ASN1OctetString getBiometricDataHash()
+ {
+ return biometricDataHash;
+ }
+
+ public DERIA5String getSourceDataUri()
+ {
+ return sourceDataUri;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+ seq.add(typeOfBiometricData);
+ seq.add(hashAlgorithm);
+ seq.add(biometricDataHash);
+
+ if (sourceDataUri != null)
+ {
+ seq.add(sourceDataUri);
+ }
+
+ return new DERSequence(seq);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/ETSIQCObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,16 @@
+package pdftk.org.bouncycastle.asn1.x509.qualified;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface ETSIQCObjectIdentifiers
+{
+ //
+ // base id
+ //
+ static final ASN1ObjectIdentifier id_etsi_qcs = new ASN1ObjectIdentifier("0.4.0.1862.1");
+
+ static final ASN1ObjectIdentifier id_etsi_qcs_QcCompliance = id_etsi_qcs.branch("1");
+ static final ASN1ObjectIdentifier id_etsi_qcs_LimiteValue = id_etsi_qcs.branch("2");
+ static final ASN1ObjectIdentifier id_etsi_qcs_RetentionPeriod = id_etsi_qcs.branch("3");
+ static final ASN1ObjectIdentifier id_etsi_qcs_QcSSCD = id_etsi_qcs.branch("4");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/Iso4217CurrencyCode.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/Iso4217CurrencyCode.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/Iso4217CurrencyCode.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/Iso4217CurrencyCode.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,93 @@
+package pdftk.org.bouncycastle.asn1.x509.qualified;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+
+/**
+ * The Iso4217CurrencyCode object.
+ *
+ * Iso4217CurrencyCode ::= CHOICE {
+ * alphabetic PrintableString (SIZE 3), --Recommended
+ * numeric INTEGER (1..999) }
+ * -- Alphabetic or numeric currency code as defined in ISO 4217
+ * -- It is recommended that the Alphabetic form is used
+ *
+ */
+public class Iso4217CurrencyCode
+ extends ASN1Object
+ implements ASN1Choice
+{
+ final int ALPHABETIC_MAXSIZE = 3;
+ final int NUMERIC_MINSIZE = 1;
+ final int NUMERIC_MAXSIZE = 999;
+
+ ASN1Encodable obj;
+ int numeric;
+
+ public static Iso4217CurrencyCode getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof Iso4217CurrencyCode)
+ {
+ return (Iso4217CurrencyCode)obj;
+ }
+
+ if (obj instanceof ASN1Integer)
+ {
+ ASN1Integer numericobj = ASN1Integer.getInstance(obj);
+ int numeric = numericobj.getValue().intValue();
+ return new Iso4217CurrencyCode(numeric);
+ }
+ else
+ if (obj instanceof DERPrintableString)
+ {
+ DERPrintableString alphabetic = DERPrintableString.getInstance(obj);
+ return new Iso4217CurrencyCode(alphabetic.getString());
+ }
+ throw new IllegalArgumentException("unknown object in getInstance");
+ }
+
+ public Iso4217CurrencyCode(
+ int numeric)
+ {
+ if (numeric > NUMERIC_MAXSIZE || numeric < NUMERIC_MINSIZE)
+ {
+ throw new IllegalArgumentException("wrong size in numeric code : not in (" +NUMERIC_MINSIZE +".."+ NUMERIC_MAXSIZE +")");
+ }
+ obj = new ASN1Integer(numeric);
+ }
+
+ public Iso4217CurrencyCode(
+ String alphabetic)
+ {
+ if (alphabetic.length() > ALPHABETIC_MAXSIZE)
+ {
+ throw new IllegalArgumentException("wrong size in alphabetic code : max size is " + ALPHABETIC_MAXSIZE);
+ }
+ obj = new DERPrintableString(alphabetic);
+ }
+
+ public boolean isAlphabetic()
+ {
+ return obj instanceof DERPrintableString;
+ }
+
+ public String getAlphabetic()
+ {
+ return ((DERPrintableString)obj).getString();
+ }
+
+ public int getNumeric()
+ {
+ return ((ASN1Integer)obj).getValue().intValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return obj.toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/MonetaryValue.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/MonetaryValue.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/MonetaryValue.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/MonetaryValue.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,92 @@
+package pdftk.org.bouncycastle.asn1.x509.qualified;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * The MonetaryValue object.
+ *
+ * MonetaryValue ::= SEQUENCE {
+ * currency Iso4217CurrencyCode,
+ * amount INTEGER,
+ * exponent INTEGER }
+ * -- value = amount * 10^exponent
+ *
+ */
+public class MonetaryValue
+ extends ASN1Object
+{
+ private Iso4217CurrencyCode currency;
+ private ASN1Integer amount;
+ private ASN1Integer exponent;
+
+ public static MonetaryValue getInstance(
+ Object obj)
+ {
+ if (obj instanceof MonetaryValue)
+ {
+ return (MonetaryValue)obj;
+ }
+
+ if (obj != null)
+ {
+ return new MonetaryValue(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private MonetaryValue(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ // currency
+ currency = Iso4217CurrencyCode.getInstance(e.nextElement());
+ // hashAlgorithm
+ amount = ASN1Integer.getInstance(e.nextElement());
+ // exponent
+ exponent = ASN1Integer.getInstance(e.nextElement());
+ }
+
+ public MonetaryValue(
+ Iso4217CurrencyCode currency,
+ int amount,
+ int exponent)
+ {
+ this.currency = currency;
+ this.amount = new ASN1Integer(amount);
+ this.exponent = new ASN1Integer(exponent);
+ }
+
+ public Iso4217CurrencyCode getCurrency()
+ {
+ return currency;
+ }
+
+ public BigInteger getAmount()
+ {
+ return amount.getValue();
+ }
+
+ public BigInteger getExponent()
+ {
+ return exponent.getValue();
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+ seq.add(currency);
+ seq.add(amount);
+ seq.add(exponent);
+
+ return new DERSequence(seq);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/QCStatement.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/QCStatement.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/QCStatement.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/QCStatement.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,95 @@
+package pdftk.org.bouncycastle.asn1.x509.qualified;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * The QCStatement object.
+ *
+ * QCStatement ::= SEQUENCE {
+ * statementId OBJECT IDENTIFIER,
+ * statementInfo ANY DEFINED BY statementId OPTIONAL}
+ *
+ */
+
+public class QCStatement
+ extends ASN1Object
+ implements ETSIQCObjectIdentifiers, RFC3739QCObjectIdentifiers
+{
+ ASN1ObjectIdentifier qcStatementId;
+ ASN1Encodable qcStatementInfo;
+
+ public static QCStatement getInstance(
+ Object obj)
+ {
+ if (obj instanceof QCStatement)
+ {
+ return (QCStatement)obj;
+ }
+ if (obj != null)
+ {
+ return new QCStatement(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private QCStatement(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ // qcStatementId
+ qcStatementId = ASN1ObjectIdentifier.getInstance(e.nextElement());
+ // qcstatementInfo
+ if (e.hasMoreElements())
+ {
+ qcStatementInfo = (ASN1Encodable) e.nextElement();
+ }
+ }
+
+ public QCStatement(
+ ASN1ObjectIdentifier qcStatementId)
+ {
+ this.qcStatementId = qcStatementId;
+ this.qcStatementInfo = null;
+ }
+
+ public QCStatement(
+ ASN1ObjectIdentifier qcStatementId,
+ ASN1Encodable qcStatementInfo)
+ {
+ this.qcStatementId = qcStatementId;
+ this.qcStatementInfo = qcStatementInfo;
+ }
+
+ public ASN1ObjectIdentifier getStatementId()
+ {
+ return qcStatementId;
+ }
+
+ public ASN1Encodable getStatementInfo()
+ {
+ return qcStatementInfo;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+ seq.add(qcStatementId);
+
+ if (qcStatementInfo != null)
+ {
+ seq.add(qcStatementInfo);
+ }
+
+ return new DERSequence(seq);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/RFC3739QCObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,14 @@
+package pdftk.org.bouncycastle.asn1.x509.qualified;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface RFC3739QCObjectIdentifiers
+{
+ //
+ // base id
+ //
+ static final ASN1ObjectIdentifier id_qcs = new ASN1ObjectIdentifier("1.3.6.1.5.5.7.11");
+
+ static final ASN1ObjectIdentifier id_qcs_pkixQCSyntax_v1 = id_qcs.branch("1");
+ static final ASN1ObjectIdentifier id_qcs_pkixQCSyntax_v2 = id_qcs.branch("2");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/SemanticsInformation.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/SemanticsInformation.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/SemanticsInformation.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/SemanticsInformation.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,131 @@
+package pdftk.org.bouncycastle.asn1.x509.qualified;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x509.GeneralName;
+
+/**
+ * The SemanticsInformation object.
+ *
+ * SemanticsInformation ::= SEQUENCE {
+ * semanticsIdentifier OBJECT IDENTIFIER OPTIONAL,
+ * nameRegistrationAuthorities NameRegistrationAuthorities
+ * OPTIONAL }
+ * (WITH COMPONENTS {..., semanticsIdentifier PRESENT}|
+ * WITH COMPONENTS {..., nameRegistrationAuthorities PRESENT})
+ *
+ * NameRegistrationAuthorities ::= SEQUENCE SIZE (1..MAX) OF
+ * GeneralName
+ *
+ */
+public class SemanticsInformation
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier semanticsIdentifier;
+ private GeneralName[] nameRegistrationAuthorities;
+
+ public static SemanticsInformation getInstance(Object obj)
+ {
+ if (obj instanceof SemanticsInformation)
+ {
+ return (SemanticsInformation)obj;
+ }
+
+ if (obj != null)
+ {
+ return new SemanticsInformation(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ private SemanticsInformation(ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+ if (seq.size() < 1)
+ {
+ throw new IllegalArgumentException("no objects in SemanticsInformation");
+ }
+
+ Object object = e.nextElement();
+ if (object instanceof ASN1ObjectIdentifier)
+ {
+ semanticsIdentifier = ASN1ObjectIdentifier.getInstance(object);
+ if (e.hasMoreElements())
+ {
+ object = e.nextElement();
+ }
+ else
+ {
+ object = null;
+ }
+ }
+
+ if (object != null)
+ {
+ ASN1Sequence generalNameSeq = ASN1Sequence.getInstance(object);
+ nameRegistrationAuthorities = new GeneralName[generalNameSeq.size()];
+ for (int i= 0; i < generalNameSeq.size(); i++)
+ {
+ nameRegistrationAuthorities[i] = GeneralName.getInstance(generalNameSeq.getObjectAt(i));
+ }
+ }
+ }
+
+ public SemanticsInformation(
+ ASN1ObjectIdentifier semanticsIdentifier,
+ GeneralName[] generalNames)
+ {
+ this.semanticsIdentifier = semanticsIdentifier;
+ this.nameRegistrationAuthorities = generalNames;
+ }
+
+ public SemanticsInformation(ASN1ObjectIdentifier semanticsIdentifier)
+ {
+ this.semanticsIdentifier = semanticsIdentifier;
+ this.nameRegistrationAuthorities = null;
+ }
+
+ public SemanticsInformation(GeneralName[] generalNames)
+ {
+ this.semanticsIdentifier = null;
+ this.nameRegistrationAuthorities = generalNames;
+ }
+
+ public ASN1ObjectIdentifier getSemanticsIdentifier()
+ {
+ return semanticsIdentifier;
+ }
+
+ public GeneralName[] getNameRegistrationAuthorities()
+ {
+ return nameRegistrationAuthorities;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector seq = new ASN1EncodableVector();
+
+ if (this.semanticsIdentifier != null)
+ {
+ seq.add(semanticsIdentifier);
+ }
+ if (this.nameRegistrationAuthorities != null)
+ {
+ ASN1EncodableVector seqname = new ASN1EncodableVector();
+ for (int i = 0; i < nameRegistrationAuthorities.length; i++)
+ {
+ seqname.add(nameRegistrationAuthorities[i]);
+ }
+ seq.add(new DERSequence(seqname));
+ }
+
+ return new DERSequence(seq);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/TypeOfBiometricData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/TypeOfBiometricData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/TypeOfBiometricData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/TypeOfBiometricData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,90 @@
+package pdftk.org.bouncycastle.asn1.x509.qualified;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+
+/**
+ * The TypeOfBiometricData object.
+ *
+ * TypeOfBiometricData ::= CHOICE {
+ * predefinedBiometricType PredefinedBiometricType,
+ * biometricDataOid OBJECT IDENTIFIER }
+ *
+ * PredefinedBiometricType ::= INTEGER {
+ * picture(0),handwritten-signature(1)}
+ * (picture|handwritten-signature)
+ *
+ */
+public class TypeOfBiometricData
+ extends ASN1Object
+ implements ASN1Choice
+{
+ public static final int PICTURE = 0;
+ public static final int HANDWRITTEN_SIGNATURE = 1;
+
+ ASN1Encodable obj;
+
+ public static TypeOfBiometricData getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof TypeOfBiometricData)
+ {
+ return (TypeOfBiometricData)obj;
+ }
+
+ if (obj instanceof ASN1Integer)
+ {
+ ASN1Integer predefinedBiometricTypeObj = ASN1Integer.getInstance(obj);
+ int predefinedBiometricType = predefinedBiometricTypeObj.getValue().intValue();
+
+ return new TypeOfBiometricData(predefinedBiometricType);
+ }
+ else if (obj instanceof ASN1ObjectIdentifier)
+ {
+ ASN1ObjectIdentifier BiometricDataID = ASN1ObjectIdentifier.getInstance(obj);
+ return new TypeOfBiometricData(BiometricDataID);
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance");
+ }
+
+ public TypeOfBiometricData(int predefinedBiometricType)
+ {
+ if (predefinedBiometricType == PICTURE || predefinedBiometricType == HANDWRITTEN_SIGNATURE)
+ {
+ obj = new ASN1Integer(predefinedBiometricType);
+ }
+ else
+ {
+ throw new IllegalArgumentException("unknow PredefinedBiometricType : " + predefinedBiometricType);
+ }
+ }
+
+ public TypeOfBiometricData(ASN1ObjectIdentifier BiometricDataID)
+ {
+ obj = BiometricDataID;
+ }
+
+ public boolean isPredefined()
+ {
+ return obj instanceof ASN1Integer;
+ }
+
+ public int getPredefinedBiometricType()
+ {
+ return ((ASN1Integer)obj).getValue().intValue();
+ }
+
+ public ASN1ObjectIdentifier getBiometricDataOid()
+ {
+ return (ASN1ObjectIdentifier)obj;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return obj.toASN1Primitive();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/qualified/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/qualified/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes useful for encoding and processing messages based around RFC3739
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/sigi/NameOrPseudonym.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/sigi/NameOrPseudonym.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/sigi/NameOrPseudonym.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/sigi/NameOrPseudonym.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,191 @@
+package pdftk.org.bouncycastle.asn1.x509.sigi;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1String;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.x500.DirectoryString;
+
+/**
+ * Structure for a name or pseudonym.
+ *
+ *
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ *
+ *
+ * @see pdftk.org.bouncycastle.asn1.x509.sigi.PersonalData
+ *
+ */
+public class NameOrPseudonym
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private DirectoryString pseudonym;
+
+ private DirectoryString surname;
+
+ private ASN1Sequence givenName;
+
+ public static NameOrPseudonym getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof NameOrPseudonym)
+ {
+ return (NameOrPseudonym)obj;
+ }
+
+ if (obj instanceof ASN1String)
+ {
+ return new NameOrPseudonym(DirectoryString.getInstance(obj));
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new NameOrPseudonym((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: "
+ + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from DirectoryString.
+ *
+ * The sequence is of type NameOrPseudonym:
+ *
+ *
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ *
+ * @param pseudonym pseudonym value to use.
+ */
+ public NameOrPseudonym(DirectoryString pseudonym)
+ {
+ this.pseudonym = pseudonym;
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * The sequence is of type NameOrPseudonym:
+ *
+ *
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ *
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private NameOrPseudonym(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ if (!(seq.getObjectAt(0) instanceof ASN1String))
+ {
+ throw new IllegalArgumentException("Bad object encountered: "
+ + seq.getObjectAt(0).getClass());
+ }
+
+ surname = DirectoryString.getInstance(seq.getObjectAt(0));
+ givenName = ASN1Sequence.getInstance(seq.getObjectAt(1));
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param pseudonym The pseudonym.
+ */
+ public NameOrPseudonym(String pseudonym)
+ {
+ this(new DirectoryString(pseudonym));
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param surname The surname.
+ * @param givenName A sequence of directory strings making up the givenName
+ */
+ public NameOrPseudonym(DirectoryString surname, ASN1Sequence givenName)
+ {
+ this.surname = surname;
+ this.givenName = givenName;
+ }
+
+ public DirectoryString getPseudonym()
+ {
+ return pseudonym;
+ }
+
+ public DirectoryString getSurname()
+ {
+ return surname;
+ }
+
+ public DirectoryString[] getGivenName()
+ {
+ DirectoryString[] items = new DirectoryString[givenName.size()];
+ int count = 0;
+ for (Enumeration e = givenName.getObjects(); e.hasMoreElements();)
+ {
+ items[count++] = DirectoryString.getInstance(e.nextElement());
+ }
+ return items;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * NameOrPseudonym ::= CHOICE {
+ * surAndGivenName SEQUENCE {
+ * surName DirectoryString,
+ * givenName SEQUENCE OF DirectoryString
+ * },
+ * pseudonym DirectoryString
+ * }
+ *
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ if (pseudonym != null)
+ {
+ return pseudonym.toASN1Primitive();
+ }
+ else
+ {
+ ASN1EncodableVector vec1 = new ASN1EncodableVector();
+ vec1.add(surname);
+ vec1.add(givenName);
+ return new DERSequence(vec1);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/sigi/PersonalData.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/sigi/PersonalData.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/sigi/PersonalData.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/sigi/PersonalData.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,214 @@
+package pdftk.org.bouncycastle.asn1.x509.sigi;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1GeneralizedTime;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERPrintableString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x500.DirectoryString;
+
+/**
+ * Contains personal data for the otherName field in the subjectAltNames
+ * extension.
+ *
+ *
+ * PersonalData ::= SEQUENCE {
+ * nameOrPseudonym NameOrPseudonym,
+ * nameDistinguisher [0] INTEGER OPTIONAL,
+ * dateOfBirth [1] GeneralizedTime OPTIONAL,
+ * placeOfBirth [2] DirectoryString OPTIONAL,
+ * gender [3] PrintableString OPTIONAL,
+ * postalAddress [4] DirectoryString OPTIONAL
+ * }
+ *
+ *
+ * @see pdftk.org.bouncycastle.asn1.x509.sigi.NameOrPseudonym
+ * @see pdftk.org.bouncycastle.asn1.x509.sigi.SigIObjectIdentifiers
+ */
+public class PersonalData
+ extends ASN1Object
+{
+ private NameOrPseudonym nameOrPseudonym;
+ private BigInteger nameDistinguisher;
+ private ASN1GeneralizedTime dateOfBirth;
+ private DirectoryString placeOfBirth;
+ private String gender;
+ private DirectoryString postalAddress;
+
+ public static PersonalData getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof PersonalData)
+ {
+ return (PersonalData)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new PersonalData((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
+ }
+
+ /**
+ * Constructor from ASN1Sequence.
+ *
+ * The sequence is of type NameOrPseudonym:
+ *
+ *
+ * PersonalData ::= SEQUENCE {
+ * nameOrPseudonym NameOrPseudonym,
+ * nameDistinguisher [0] INTEGER OPTIONAL,
+ * dateOfBirth [1] GeneralizedTime OPTIONAL,
+ * placeOfBirth [2] DirectoryString OPTIONAL,
+ * gender [3] PrintableString OPTIONAL,
+ * postalAddress [4] DirectoryString OPTIONAL
+ * }
+ *
+ *
+ * @param seq The ASN.1 sequence.
+ */
+ private PersonalData(ASN1Sequence seq)
+ {
+ if (seq.size() < 1)
+ {
+ throw new IllegalArgumentException("Bad sequence size: "
+ + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+
+ nameOrPseudonym = NameOrPseudonym.getInstance(e.nextElement());
+
+ while (e.hasMoreElements())
+ {
+ ASN1TaggedObject o = ASN1TaggedObject.getInstance(e.nextElement());
+ int tag = o.getTagNo();
+ switch (tag)
+ {
+ case 0:
+ nameDistinguisher = ASN1Integer.getInstance(o, false).getValue();
+ break;
+ case 1:
+ dateOfBirth = ASN1GeneralizedTime.getInstance(o, false);
+ break;
+ case 2:
+ placeOfBirth = DirectoryString.getInstance(o, true);
+ break;
+ case 3:
+ gender = DERPrintableString.getInstance(o, false).getString();
+ break;
+ case 4:
+ postalAddress = DirectoryString.getInstance(o, true);
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag number: " + o.getTagNo());
+ }
+ }
+ }
+
+ /**
+ * Constructor from a given details.
+ *
+ * @param nameOrPseudonym Name or pseudonym.
+ * @param nameDistinguisher Name distinguisher.
+ * @param dateOfBirth Date of birth.
+ * @param placeOfBirth Place of birth.
+ * @param gender Gender.
+ * @param postalAddress Postal Address.
+ */
+ public PersonalData(NameOrPseudonym nameOrPseudonym,
+ BigInteger nameDistinguisher, ASN1GeneralizedTime dateOfBirth,
+ DirectoryString placeOfBirth, String gender, DirectoryString postalAddress)
+ {
+ this.nameOrPseudonym = nameOrPseudonym;
+ this.dateOfBirth = dateOfBirth;
+ this.gender = gender;
+ this.nameDistinguisher = nameDistinguisher;
+ this.postalAddress = postalAddress;
+ this.placeOfBirth = placeOfBirth;
+ }
+
+ public NameOrPseudonym getNameOrPseudonym()
+ {
+ return nameOrPseudonym;
+ }
+
+ public BigInteger getNameDistinguisher()
+ {
+ return nameDistinguisher;
+ }
+
+ public ASN1GeneralizedTime getDateOfBirth()
+ {
+ return dateOfBirth;
+ }
+
+ public DirectoryString getPlaceOfBirth()
+ {
+ return placeOfBirth;
+ }
+
+ public String getGender()
+ {
+ return gender;
+ }
+
+ public DirectoryString getPostalAddress()
+ {
+ return postalAddress;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Returns:
+ *
+ *
+ * PersonalData ::= SEQUENCE {
+ * nameOrPseudonym NameOrPseudonym,
+ * nameDistinguisher [0] INTEGER OPTIONAL,
+ * dateOfBirth [1] GeneralizedTime OPTIONAL,
+ * placeOfBirth [2] DirectoryString OPTIONAL,
+ * gender [3] PrintableString OPTIONAL,
+ * postalAddress [4] DirectoryString OPTIONAL
+ * }
+ *
+ *
+ * @return a DERObject
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector vec = new ASN1EncodableVector();
+ vec.add(nameOrPseudonym);
+ if (nameDistinguisher != null)
+ {
+ vec.add(new DERTaggedObject(false, 0, new ASN1Integer(nameDistinguisher)));
+ }
+ if (dateOfBirth != null)
+ {
+ vec.add(new DERTaggedObject(false, 1, dateOfBirth));
+ }
+ if (placeOfBirth != null)
+ {
+ vec.add(new DERTaggedObject(true, 2, placeOfBirth));
+ }
+ if (gender != null)
+ {
+ vec.add(new DERTaggedObject(false, 3, new DERPrintableString(gender, true)));
+ }
+ if (postalAddress != null)
+ {
+ vec.add(new DERTaggedObject(true, 4, postalAddress));
+ }
+ return new DERSequence(vec);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x509/sigi/SigIObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,45 @@
+package pdftk.org.bouncycastle.asn1.x509.sigi;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+/**
+ * Object Identifiers of SigI specifciation (German Signature Law
+ * Interoperability specification).
+ */
+public interface SigIObjectIdentifiers
+{
+ public final static ASN1ObjectIdentifier id_sigi = new ASN1ObjectIdentifier("1.3.36.8");
+
+ /**
+ * Key purpose IDs for German SigI (Signature Interoperability
+ * Specification)
+ */
+ public final static ASN1ObjectIdentifier id_sigi_kp = new ASN1ObjectIdentifier(id_sigi + ".2");
+
+ /**
+ * Certificate policy IDs for German SigI (Signature Interoperability
+ * Specification)
+ */
+ public final static ASN1ObjectIdentifier id_sigi_cp = new ASN1ObjectIdentifier(id_sigi + ".1");
+
+ /**
+ * Other Name IDs for German SigI (Signature Interoperability Specification)
+ */
+ public final static ASN1ObjectIdentifier id_sigi_on = new ASN1ObjectIdentifier(id_sigi + ".4");
+
+ /**
+ * To be used for for the generation of directory service certificates.
+ */
+ public static final ASN1ObjectIdentifier id_sigi_kp_directoryService = new ASN1ObjectIdentifier(id_sigi_kp + ".1");
+
+ /**
+ * ID for PersonalData
+ */
+ public static final ASN1ObjectIdentifier id_sigi_on_personalData = new ASN1ObjectIdentifier(id_sigi_on + ".1");
+
+ /**
+ * Certificate is conform to german signature law.
+ */
+ public static final ASN1ObjectIdentifier id_sigi_cp_sigconform = new ASN1ObjectIdentifier(id_sigi_cp + ".1");
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/DHDomainParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/DHDomainParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/DHDomainParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/DHDomainParameters.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,139 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class DHDomainParameters
+ extends ASN1Object
+{
+ private ASN1Integer p, g, q, j;
+ private DHValidationParms validationParms;
+
+ public static DHDomainParameters getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static DHDomainParameters getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DHDomainParameters)
+ {
+ return (DHDomainParameters)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new DHDomainParameters((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid DHDomainParameters: "
+ + obj.getClass().getName());
+ }
+
+ public DHDomainParameters(ASN1Integer p, ASN1Integer g, ASN1Integer q, ASN1Integer j,
+ DHValidationParms validationParms)
+ {
+ if (p == null)
+ {
+ throw new IllegalArgumentException("'p' cannot be null");
+ }
+ if (g == null)
+ {
+ throw new IllegalArgumentException("'g' cannot be null");
+ }
+ if (q == null)
+ {
+ throw new IllegalArgumentException("'q' cannot be null");
+ }
+
+ this.p = p;
+ this.g = g;
+ this.q = q;
+ this.j = j;
+ this.validationParms = validationParms;
+ }
+
+ private DHDomainParameters(ASN1Sequence seq)
+ {
+ if (seq.size() < 3 || seq.size() > 5)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ Enumeration e = seq.getObjects();
+ this.p = ASN1Integer.getInstance(e.nextElement());
+ this.g = ASN1Integer.getInstance(e.nextElement());
+ this.q = ASN1Integer.getInstance(e.nextElement());
+
+ ASN1Encodable next = getNext(e);
+
+ if (next != null && next instanceof ASN1Integer)
+ {
+ this.j = ASN1Integer.getInstance(next);
+ next = getNext(e);
+ }
+
+ if (next != null)
+ {
+ this.validationParms = DHValidationParms.getInstance(next.toASN1Primitive());
+ }
+ }
+
+ private static ASN1Encodable getNext(Enumeration e)
+ {
+ return e.hasMoreElements() ? (ASN1Encodable)e.nextElement() : null;
+ }
+
+ public ASN1Integer getP()
+ {
+ return this.p;
+ }
+
+ public ASN1Integer getG()
+ {
+ return this.g;
+ }
+
+ public ASN1Integer getQ()
+ {
+ return this.q;
+ }
+
+ public ASN1Integer getJ()
+ {
+ return this.j;
+ }
+
+ public DHValidationParms getValidationParms()
+ {
+ return this.validationParms;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.p);
+ v.add(this.g);
+ v.add(this.q);
+
+ if (this.j != null)
+ {
+ v.add(this.j);
+ }
+
+ if (this.validationParms != null)
+ {
+ v.add(this.validationParms);
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/DHPublicKey.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/DHPublicKey.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/DHPublicKey.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/DHPublicKey.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,52 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+
+public class DHPublicKey
+ extends ASN1Object
+{
+ private ASN1Integer y;
+
+ public static DHPublicKey getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ return getInstance(ASN1Integer.getInstance(obj, explicit));
+ }
+
+ public static DHPublicKey getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DHPublicKey)
+ {
+ return (DHPublicKey)obj;
+ }
+
+ if (obj instanceof ASN1Integer)
+ {
+ return new DHPublicKey((ASN1Integer)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid DHPublicKey: " + obj.getClass().getName());
+ }
+
+ public DHPublicKey(ASN1Integer y)
+ {
+ if (y == null)
+ {
+ throw new IllegalArgumentException("'y' cannot be null");
+ }
+
+ this.y = y;
+ }
+
+ public ASN1Integer getY()
+ {
+ return this.y;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ return this.y;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/DHValidationParms.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/DHValidationParms.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/DHValidationParms.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/DHValidationParms.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,80 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+public class DHValidationParms extends ASN1Object
+{
+ private DERBitString seed;
+ private ASN1Integer pgenCounter;
+
+ public static DHValidationParms getInstance(ASN1TaggedObject obj, boolean explicit)
+ {
+ return getInstance(ASN1Sequence.getInstance(obj, explicit));
+ }
+
+ public static DHValidationParms getInstance(Object obj)
+ {
+ if (obj == null || obj instanceof DHDomainParameters)
+ {
+ return (DHValidationParms)obj;
+ }
+
+ if (obj instanceof ASN1Sequence)
+ {
+ return new DHValidationParms((ASN1Sequence)obj);
+ }
+
+ throw new IllegalArgumentException("Invalid DHValidationParms: " + obj.getClass().getName());
+ }
+
+ public DHValidationParms(DERBitString seed, ASN1Integer pgenCounter)
+ {
+ if (seed == null)
+ {
+ throw new IllegalArgumentException("'seed' cannot be null");
+ }
+ if (pgenCounter == null)
+ {
+ throw new IllegalArgumentException("'pgenCounter' cannot be null");
+ }
+
+ this.seed = seed;
+ this.pgenCounter = pgenCounter;
+ }
+
+ private DHValidationParms(ASN1Sequence seq)
+ {
+ if (seq.size() != 2)
+ {
+ throw new IllegalArgumentException("Bad sequence size: " + seq.size());
+ }
+
+ this.seed = DERBitString.getInstance(seq.getObjectAt(0));
+ this.pgenCounter = ASN1Integer.getInstance(seq.getObjectAt(1));
+ }
+
+ public DERBitString getSeed()
+ {
+ return this.seed;
+ }
+
+ public ASN1Integer getPgenCounter()
+ {
+ return this.pgenCounter;
+ }
+
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(this.seed);
+ v.add(this.pgenCounter);
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/KeySpecificInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/KeySpecificInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/KeySpecificInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/KeySpecificInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,68 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * ASN.1 def for Diffie-Hellman key exchange KeySpecificInfo structure. See
+ * RFC 2631, or X9.42, for further details.
+ */
+public class KeySpecificInfo
+ extends ASN1Object
+{
+ private ASN1ObjectIdentifier algorithm;
+ private ASN1OctetString counter;
+
+ public KeySpecificInfo(
+ ASN1ObjectIdentifier algorithm,
+ ASN1OctetString counter)
+ {
+ this.algorithm = algorithm;
+ this.counter = counter;
+ }
+
+ public KeySpecificInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ algorithm = (ASN1ObjectIdentifier)e.nextElement();
+ counter = (ASN1OctetString)e.nextElement();
+ }
+
+ public ASN1ObjectIdentifier getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ public ASN1OctetString getCounter()
+ {
+ return counter;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * KeySpecificInfo ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * counter OCTET STRING SIZE (4..4)
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(algorithm);
+ v.add(counter);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/OtherInfo.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/OtherInfo.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/OtherInfo.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/OtherInfo.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,96 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import java.util.Enumeration;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+
+/**
+ * ANS.1 def for Diffie-Hellman key exchange OtherInfo structure. See
+ * RFC 2631, or X9.42, for further details.
+ */
+public class OtherInfo
+ extends ASN1Object
+{
+ private KeySpecificInfo keyInfo;
+ private ASN1OctetString partyAInfo;
+ private ASN1OctetString suppPubInfo;
+
+ public OtherInfo(
+ KeySpecificInfo keyInfo,
+ ASN1OctetString partyAInfo,
+ ASN1OctetString suppPubInfo)
+ {
+ this.keyInfo = keyInfo;
+ this.partyAInfo = partyAInfo;
+ this.suppPubInfo = suppPubInfo;
+ }
+
+ public OtherInfo(
+ ASN1Sequence seq)
+ {
+ Enumeration e = seq.getObjects();
+
+ keyInfo = new KeySpecificInfo((ASN1Sequence)e.nextElement());
+
+ while (e.hasMoreElements())
+ {
+ DERTaggedObject o = (DERTaggedObject)e.nextElement();
+
+ if (o.getTagNo() == 0)
+ {
+ partyAInfo = (ASN1OctetString)o.getObject();
+ }
+ else if (o.getTagNo() == 2)
+ {
+ suppPubInfo = (ASN1OctetString)o.getObject();
+ }
+ }
+ }
+
+ public KeySpecificInfo getKeyInfo()
+ {
+ return keyInfo;
+ }
+
+ public ASN1OctetString getPartyAInfo()
+ {
+ return partyAInfo;
+ }
+
+ public ASN1OctetString getSuppPubInfo()
+ {
+ return suppPubInfo;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * OtherInfo ::= SEQUENCE {
+ * keyInfo KeySpecificInfo,
+ * partyAInfo [0] OCTET STRING OPTIONAL,
+ * suppPubInfo [2] OCTET STRING
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(keyInfo);
+
+ if (partyAInfo != null)
+ {
+ v.add(new DERTaggedObject(0, partyAInfo));
+ }
+
+ v.add(new DERTaggedObject(2, suppPubInfo));
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X962NamedCurves.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X962NamedCurves.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X962NamedCurves.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X962NamedCurves.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,621 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import java.math.BigInteger;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+import pdftk.org.bouncycastle.util.Strings;
+import pdftk.org.bouncycastle.util.encoders.Hex;
+
+
+/**
+ * table of the current named curves defined in X.962 EC-DSA.
+ */
+public class X962NamedCurves
+{
+ static X9ECParametersHolder prime192v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve cFp192v1 = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
+ new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16));
+
+ return new X9ECParameters(
+ cFp192v1,
+ cFp192v1.decodePoint(
+ Hex.decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")),
+ new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16),
+ BigInteger.valueOf(1),
+ Hex.decode("3045AE6FC8422f64ED579528D38120EAE12196D5"));
+ }
+ };
+
+ static X9ECParametersHolder prime192v2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve cFp192v2 = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
+ new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16));
+
+ return new X9ECParameters(
+ cFp192v2,
+ cFp192v2.decodePoint(
+ Hex.decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")),
+ new BigInteger("fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", 16),
+ BigInteger.valueOf(1),
+ Hex.decode("31a92ee2029fd10d901b113e990710f0d21ac6b6"));
+ }
+ };
+
+ static X9ECParametersHolder prime192v3 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve cFp192v3 = new ECCurve.Fp(
+ new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+ new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
+ new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16));
+
+ return new X9ECParameters(
+ cFp192v3,
+ cFp192v3.decodePoint(
+ Hex.decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")),
+ new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16),
+ BigInteger.valueOf(1),
+ Hex.decode("c469684435deb378c4b65ca9591e2a5763059a2e"));
+ }
+ };
+
+ static X9ECParametersHolder prime239v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve cFp239v1 = new ECCurve.Fp(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
+ new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16));
+
+ return new X9ECParameters(
+ cFp239v1,
+ cFp239v1.decodePoint(
+ Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")),
+ new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16),
+ BigInteger.valueOf(1),
+ Hex.decode("e43bb460f0b80cc0c0b075798e948060f8321b7d"));
+ }
+ };
+
+ static X9ECParametersHolder prime239v2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve cFp239v2 = new ECCurve.Fp(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
+ new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16));
+
+ return new X9ECParameters(
+ cFp239v2,
+ cFp239v2.decodePoint(
+ Hex.decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")),
+ new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16),
+ BigInteger.valueOf(1),
+ Hex.decode("e8b4011604095303ca3b8099982be09fcb9ae616"));
+ }
+ };
+
+ static X9ECParametersHolder prime239v3 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve cFp239v3 = new ECCurve.Fp(
+ new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
+ new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
+ new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16));
+
+ return new X9ECParameters(
+ cFp239v3,
+ cFp239v3.decodePoint(
+ Hex.decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")),
+ new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16),
+ BigInteger.valueOf(1),
+ Hex.decode("7d7374168ffe3471b60a857686a19475d3bfa2ff"));
+ }
+ };
+
+ static X9ECParametersHolder prime256v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ ECCurve cFp256v1 = new ECCurve.Fp(
+ new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951"),
+ new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16),
+ new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16));
+
+ return new X9ECParameters(
+ cFp256v1,
+ cFp256v1.decodePoint(
+ Hex.decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")),
+ new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16),
+ BigInteger.valueOf(1),
+ Hex.decode("c49d360886e704936a6678e1139d26b7819f7e90"));
+ }
+ };
+
+ /*
+ * F2m Curves
+ */
+ static X9ECParametersHolder c2pnb163v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m163v1n = new BigInteger("0400000000000000000001E60FC8821CC74DAEAFC1", 16);
+ BigInteger c2m163v1h = BigInteger.valueOf(2);
+
+ ECCurve c2m163v1 = new ECCurve.F2m(
+ 163,
+ 1, 2, 8,
+ new BigInteger("072546B5435234A422E0789675F432C89435DE5242", 16),
+ new BigInteger("00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9", 16),
+ c2m163v1n, c2m163v1h);
+
+ return new X9ECParameters(
+ c2m163v1,
+ c2m163v1.decodePoint(
+ Hex.decode("0307AF69989546103D79329FCC3D74880F33BBE803CB")),
+ c2m163v1n, c2m163v1h,
+ Hex.decode("D2C0FB15760860DEF1EEF4D696E6768756151754"));
+ }
+ };
+
+ static X9ECParametersHolder c2pnb163v2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m163v2n = new BigInteger("03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 16);
+ BigInteger c2m163v2h = BigInteger.valueOf(2);
+
+ ECCurve c2m163v2 = new ECCurve.F2m(
+ 163,
+ 1, 2, 8,
+ new BigInteger("0108B39E77C4B108BED981ED0E890E117C511CF072", 16),
+ new BigInteger("0667ACEB38AF4E488C407433FFAE4F1C811638DF20", 16),
+ c2m163v2n, c2m163v2h);
+
+ return new X9ECParameters(
+ c2m163v2,
+ c2m163v2.decodePoint(
+ Hex.decode("030024266E4EB5106D0A964D92C4860E2671DB9B6CC5")),
+ c2m163v2n, c2m163v2h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2pnb163v3 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m163v3n = new BigInteger("03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 16);
+ BigInteger c2m163v3h = BigInteger.valueOf(2);
+
+ ECCurve c2m163v3 = new ECCurve.F2m(
+ 163,
+ 1, 2, 8,
+ new BigInteger("07A526C63D3E25A256A007699F5447E32AE456B50E", 16),
+ new BigInteger("03F7061798EB99E238FD6F1BF95B48FEEB4854252B", 16),
+ c2m163v3n, c2m163v3h);
+
+ return new X9ECParameters(
+ c2m163v3,
+ c2m163v3.decodePoint(
+ Hex.decode("0202F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB")),
+ c2m163v3n, c2m163v3h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2pnb176w1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m176w1n = new BigInteger("010092537397ECA4F6145799D62B0A19CE06FE26AD", 16);
+ BigInteger c2m176w1h = BigInteger.valueOf(0xFF6E);
+
+ ECCurve c2m176w1 = new ECCurve.F2m(
+ 176,
+ 1, 2, 43,
+ new BigInteger("00E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B", 16),
+ new BigInteger("005DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2", 16),
+ c2m176w1n, c2m176w1h);
+
+ return new X9ECParameters(
+ c2m176w1,
+ c2m176w1.decodePoint(
+ Hex.decode("038D16C2866798B600F9F08BB4A8E860F3298CE04A5798")),
+ c2m176w1n, c2m176w1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb191v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m191v1n = new BigInteger("40000000000000000000000004A20E90C39067C893BBB9A5", 16);
+ BigInteger c2m191v1h = BigInteger.valueOf(2);
+
+ ECCurve c2m191v1 = new ECCurve.F2m(
+ 191,
+ 9,
+ new BigInteger("2866537B676752636A68F56554E12640276B649EF7526267", 16),
+ new BigInteger("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", 16),
+ c2m191v1n, c2m191v1h);
+
+ return new X9ECParameters(
+ c2m191v1,
+ c2m191v1.decodePoint(
+ Hex.decode("0236B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D")),
+ c2m191v1n, c2m191v1h,
+ Hex.decode("4E13CA542744D696E67687561517552F279A8C84"));
+ }
+ };
+
+ static X9ECParametersHolder c2tnb191v2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m191v2n = new BigInteger("20000000000000000000000050508CB89F652824E06B8173", 16);
+ BigInteger c2m191v2h = BigInteger.valueOf(4);
+
+ ECCurve c2m191v2 = new ECCurve.F2m(
+ 191,
+ 9,
+ new BigInteger("401028774D7777C7B7666D1366EA432071274F89FF01E718", 16),
+ new BigInteger("0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01", 16),
+ c2m191v2n, c2m191v2h);
+
+ return new X9ECParameters(
+ c2m191v2,
+ c2m191v2.decodePoint(
+ Hex.decode("023809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10")),
+ c2m191v2n, c2m191v2h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb191v3 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m191v3n = new BigInteger("155555555555555555555555610C0B196812BFB6288A3EA3", 16);
+ BigInteger c2m191v3h = BigInteger.valueOf(6);
+
+ ECCurve c2m191v3 = new ECCurve.F2m(
+ 191,
+ 9,
+ new BigInteger("6C01074756099122221056911C77D77E77A777E7E7E77FCB", 16),
+ new BigInteger("71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8", 16),
+ c2m191v3n, c2m191v3h);
+
+ return new X9ECParameters(
+ c2m191v3,
+ c2m191v3.decodePoint(
+ Hex.decode("03375D4CE24FDE434489DE8746E71786015009E66E38A926DD")),
+ c2m191v3n, c2m191v3h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2pnb208w1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m208w1n = new BigInteger("0101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 16);
+ BigInteger c2m208w1h = BigInteger.valueOf(0xFE48);
+
+ ECCurve c2m208w1 = new ECCurve.F2m(
+ 208,
+ 1, 2, 83,
+ new BigInteger("0", 16),
+ new BigInteger("00C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E", 16),
+ c2m208w1n, c2m208w1h);
+
+ return new X9ECParameters(
+ c2m208w1,
+ c2m208w1.decodePoint(
+ Hex.decode("0289FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A")),
+ c2m208w1n, c2m208w1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb239v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m239v1n = new BigInteger("2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 16);
+ BigInteger c2m239v1h = BigInteger.valueOf(4);
+
+ ECCurve c2m239v1 = new ECCurve.F2m(
+ 239,
+ 36,
+ new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16),
+ new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16),
+ c2m239v1n, c2m239v1h);
+
+ return new X9ECParameters(
+ c2m239v1,
+ c2m239v1.decodePoint(
+ Hex.decode("0257927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D")),
+ c2m239v1n, c2m239v1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb239v2 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m239v2n = new BigInteger("1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 16);
+ BigInteger c2m239v2h = BigInteger.valueOf(6);
+
+ ECCurve c2m239v2 = new ECCurve.F2m(
+ 239,
+ 36,
+ new BigInteger("4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F", 16),
+ new BigInteger("5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B", 16),
+ c2m239v2n, c2m239v2h);
+
+ return new X9ECParameters(
+ c2m239v2,
+ c2m239v2.decodePoint(
+ Hex.decode("0228F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205")),
+ c2m239v2n, c2m239v2h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb239v3 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m239v3n = new BigInteger("0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 16);
+ BigInteger c2m239v3h = BigInteger.valueOf(10);
+
+ ECCurve c2m239v3 = new ECCurve.F2m(
+ 239,
+ 36,
+ new BigInteger("01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F", 16),
+ new BigInteger("6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40", 16),
+ c2m239v3n, c2m239v3h);
+
+ return new X9ECParameters(
+ c2m239v3,
+ c2m239v3.decodePoint(
+ Hex.decode("0370F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92")),
+ c2m239v3n, c2m239v3h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2pnb272w1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m272w1n = new BigInteger("0100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521", 16);
+ BigInteger c2m272w1h = BigInteger.valueOf(0xFF06);
+
+ ECCurve c2m272w1 = new ECCurve.F2m(
+ 272,
+ 1, 3, 56,
+ new BigInteger("0091A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20", 16),
+ new BigInteger("7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7", 16),
+ c2m272w1n, c2m272w1h);
+
+ return new X9ECParameters(
+ c2m272w1,
+ c2m272w1.decodePoint(
+ Hex.decode("026108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D")),
+ c2m272w1n, c2m272w1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2pnb304w1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m304w1n = new BigInteger("0101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", 16);
+ BigInteger c2m304w1h = BigInteger.valueOf(0xFE2E);
+
+ ECCurve c2m304w1 = new ECCurve.F2m(
+ 304,
+ 1, 2, 11,
+ new BigInteger("00FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681", 16),
+ new BigInteger("00BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE", 16),
+ c2m304w1n, c2m304w1h);
+
+ return new X9ECParameters(
+ c2m304w1,
+ c2m304w1.decodePoint(
+ Hex.decode("02197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614")),
+ c2m304w1n, c2m304w1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb359v1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m359v1n = new BigInteger("01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", 16);
+ BigInteger c2m359v1h = BigInteger.valueOf(0x4C);
+
+ ECCurve c2m359v1 = new ECCurve.F2m(
+ 359,
+ 68,
+ new BigInteger("5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557", 16),
+ new BigInteger("2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988", 16),
+ c2m359v1n, c2m359v1h);
+
+ return new X9ECParameters(
+ c2m359v1,
+ c2m359v1.decodePoint(
+ Hex.decode("033C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097")),
+ c2m359v1n, c2m359v1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2pnb368w1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m368w1n = new BigInteger("010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", 16);
+ BigInteger c2m368w1h = BigInteger.valueOf(0xFF70);
+
+ ECCurve c2m368w1 = new ECCurve.F2m(
+ 368,
+ 1, 2, 85,
+ new BigInteger("00E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D", 16),
+ new BigInteger("00FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A", 16),
+ c2m368w1n, c2m368w1h);
+
+ return new X9ECParameters(
+ c2m368w1,
+ c2m368w1.decodePoint(
+ Hex.decode("021085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F")),
+ c2m368w1n, c2m368w1h,
+ null);
+ }
+ };
+
+ static X9ECParametersHolder c2tnb431r1 = new X9ECParametersHolder()
+ {
+ protected X9ECParameters createParameters()
+ {
+ BigInteger c2m431r1n = new BigInteger("0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", 16);
+ BigInteger c2m431r1h = BigInteger.valueOf(0x2760);
+
+ ECCurve c2m431r1 = new ECCurve.F2m(
+ 431,
+ 120,
+ new BigInteger("1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F", 16),
+ new BigInteger("10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618", 16),
+ c2m431r1n, c2m431r1h);
+
+ return new X9ECParameters(
+ c2m431r1,
+ c2m431r1.decodePoint(
+ Hex.decode("02120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7")),
+ c2m431r1n, c2m431r1h,
+ null);
+ }
+ };
+
+ static final Hashtable objIds = new Hashtable();
+ static final Hashtable curves = new Hashtable();
+ static final Hashtable names = new Hashtable();
+
+ static void defineCurve(String name, ASN1ObjectIdentifier oid, X9ECParametersHolder holder)
+ {
+ objIds.put(name, oid);
+ names.put(oid, name);
+ curves.put(oid, holder);
+ }
+
+ static
+ {
+ defineCurve("prime192v1", X9ObjectIdentifiers.prime192v1, prime192v1);
+ defineCurve("prime192v2", X9ObjectIdentifiers.prime192v2, prime192v2);
+ defineCurve("prime192v3", X9ObjectIdentifiers.prime192v3, prime192v3);
+ defineCurve("prime239v1", X9ObjectIdentifiers.prime239v1, prime239v1);
+ defineCurve("prime239v2", X9ObjectIdentifiers.prime239v2, prime239v2);
+ defineCurve("prime239v3", X9ObjectIdentifiers.prime239v3, prime239v3);
+ defineCurve("prime256v1", X9ObjectIdentifiers.prime256v1, prime256v1);
+ defineCurve("c2pnb163v1", X9ObjectIdentifiers.c2pnb163v1, c2pnb163v1);
+ defineCurve("c2pnb163v2", X9ObjectIdentifiers.c2pnb163v2, c2pnb163v2);
+ defineCurve("c2pnb163v3", X9ObjectIdentifiers.c2pnb163v3, c2pnb163v3);
+ defineCurve("c2pnb176w1", X9ObjectIdentifiers.c2pnb176w1, c2pnb176w1);
+ defineCurve("c2tnb191v1", X9ObjectIdentifiers.c2tnb191v1, c2tnb191v1);
+ defineCurve("c2tnb191v2", X9ObjectIdentifiers.c2tnb191v2, c2tnb191v2);
+ defineCurve("c2tnb191v3", X9ObjectIdentifiers.c2tnb191v3, c2tnb191v3);
+ defineCurve("c2pnb208w1", X9ObjectIdentifiers.c2pnb208w1, c2pnb208w1);
+ defineCurve("c2tnb239v1", X9ObjectIdentifiers.c2tnb239v1, c2tnb239v1);
+ defineCurve("c2tnb239v2", X9ObjectIdentifiers.c2tnb239v2, c2tnb239v2);
+ defineCurve("c2tnb239v3", X9ObjectIdentifiers.c2tnb239v3, c2tnb239v3);
+ defineCurve("c2pnb272w1", X9ObjectIdentifiers.c2pnb272w1, c2pnb272w1);
+ defineCurve("c2pnb304w1", X9ObjectIdentifiers.c2pnb304w1, c2pnb304w1);
+ defineCurve("c2tnb359v1", X9ObjectIdentifiers.c2tnb359v1, c2tnb359v1);
+ defineCurve("c2pnb368w1", X9ObjectIdentifiers.c2pnb368w1, c2pnb368w1);
+ defineCurve("c2tnb431r1", X9ObjectIdentifiers.c2tnb431r1, c2tnb431r1);
+ }
+
+ public static X9ECParameters getByName(
+ String name)
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
+
+ if (oid != null)
+ {
+ return getByOID(oid);
+ }
+
+ return null;
+ }
+
+ /**
+ * return the X9ECParameters object for the named curve represented by
+ * the passed in object identifier. Null if the curve isn't present.
+ *
+ * @param oid an object identifier representing a named curve, if present.
+ */
+ public static X9ECParameters getByOID(
+ ASN1ObjectIdentifier oid)
+ {
+ X9ECParametersHolder holder = (X9ECParametersHolder)curves.get(oid);
+
+ if (holder != null)
+ {
+ return holder.getParameters();
+ }
+
+ return null;
+ }
+
+ /**
+ * return the object identifier signified by the passed in name. Null
+ * if there is no object identifier associated with name.
+ *
+ * @return the object identifier associated with name, if present.
+ */
+ public static ASN1ObjectIdentifier getOID(
+ String name)
+ {
+ return (ASN1ObjectIdentifier)objIds.get(Strings.toLowerCase(name));
+ }
+
+ /**
+ * return the named curve name represented by the given object identifier.
+ */
+ public static String getName(
+ ASN1ObjectIdentifier oid)
+ {
+ return (String)names.get(oid);
+ }
+
+ /**
+ * returns an enumeration containing the name strings for curves
+ * contained in this structure.
+ */
+ public static Enumeration getNames()
+ {
+ return objIds.keys();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X962Parameters.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X962Parameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X962Parameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X962Parameters.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,86 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import pdftk.org.bouncycastle.asn1.ASN1Choice;
+import pdftk.org.bouncycastle.asn1.ASN1Null;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1TaggedObject;
+
+public class X962Parameters
+ extends ASN1Object
+ implements ASN1Choice
+{
+ private ASN1Primitive params = null;
+
+ public static X962Parameters getInstance(
+ Object obj)
+ {
+ if (obj == null || obj instanceof X962Parameters)
+ {
+ return (X962Parameters)obj;
+ }
+
+ if (obj instanceof ASN1Primitive)
+ {
+ return new X962Parameters((ASN1Primitive)obj);
+ }
+
+ throw new IllegalArgumentException("unknown object in getInstance()");
+ }
+
+ public static X962Parameters getInstance(
+ ASN1TaggedObject obj,
+ boolean explicit)
+ {
+ return getInstance(obj.getObject()); // must be explicitly tagged
+ }
+
+ public X962Parameters(
+ X9ECParameters ecParameters)
+ {
+ this.params = ecParameters.toASN1Primitive();
+ }
+
+ public X962Parameters(
+ ASN1ObjectIdentifier namedCurve)
+ {
+ this.params = namedCurve;
+ }
+
+ public X962Parameters(
+ ASN1Primitive obj)
+ {
+ this.params = obj;
+ }
+
+ public boolean isNamedCurve()
+ {
+ return (params instanceof ASN1ObjectIdentifier);
+ }
+
+ public boolean isImplicitlyCA()
+ {
+ return (params instanceof ASN1Null);
+ }
+
+ public ASN1Primitive getParameters()
+ {
+ return params;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Parameters ::= CHOICE {
+ * ecParameters ECParameters,
+ * namedCurve CURVES.&id({CurveNames}),
+ * implicitlyCA NULL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return (ASN1Primitive)params;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9Curve.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9Curve.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9Curve.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9Curve.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,161 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERBitString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+
+/**
+ * ASN.1 def for Elliptic-Curve Curve structure. See
+ * X9.62, for further details.
+ */
+public class X9Curve
+ extends ASN1Object
+ implements X9ObjectIdentifiers
+{
+ private ECCurve curve;
+ private byte[] seed;
+ private ASN1ObjectIdentifier fieldIdentifier = null;
+
+ public X9Curve(
+ ECCurve curve)
+ {
+ this.curve = curve;
+ this.seed = null;
+ setFieldIdentifier();
+ }
+
+ public X9Curve(
+ ECCurve curve,
+ byte[] seed)
+ {
+ this.curve = curve;
+ this.seed = seed;
+ setFieldIdentifier();
+ }
+
+ public X9Curve(
+ X9FieldID fieldID,
+ ASN1Sequence seq)
+ {
+ fieldIdentifier = fieldID.getIdentifier();
+ if (fieldIdentifier.equals(prime_field))
+ {
+ BigInteger p = ((ASN1Integer)fieldID.getParameters()).getValue();
+ X9FieldElement x9A = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(0));
+ X9FieldElement x9B = new X9FieldElement(p, (ASN1OctetString)seq.getObjectAt(1));
+ curve = new ECCurve.Fp(p, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
+ }
+ else
+ {
+ if (fieldIdentifier.equals(characteristic_two_field))
+ {
+ // Characteristic two field
+ ASN1Sequence parameters = ASN1Sequence.getInstance(fieldID.getParameters());
+ int m = ((ASN1Integer)parameters.getObjectAt(0)).getValue().
+ intValue();
+ ASN1ObjectIdentifier representation
+ = (ASN1ObjectIdentifier)parameters.getObjectAt(1);
+
+ int k1 = 0;
+ int k2 = 0;
+ int k3 = 0;
+ if (representation.equals(tpBasis))
+ {
+ // Trinomial basis representation
+ k1 = ((ASN1Integer)parameters.getObjectAt(2)).getValue().
+ intValue();
+ }
+ else
+ {
+ // Pentanomial basis representation
+ DERSequence pentanomial
+ = (DERSequence)parameters.getObjectAt(2);
+ k1 = ((ASN1Integer)pentanomial.getObjectAt(0)).getValue().
+ intValue();
+ k2 = ((ASN1Integer)pentanomial.getObjectAt(1)).getValue().
+ intValue();
+ k3 = ((ASN1Integer)pentanomial.getObjectAt(2)).getValue().
+ intValue();
+ }
+ X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(0));
+ X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (ASN1OctetString)seq.getObjectAt(1));
+ // TODO Is it possible to get the order (n) and cofactor(h) too?
+ curve = new ECCurve.F2m(m, k1, k2, k3, x9A.getValue().toBigInteger(), x9B.getValue().toBigInteger());
+ }
+ }
+
+ if (seq.size() == 3)
+ {
+ seed = ((DERBitString)seq.getObjectAt(2)).getBytes();
+ }
+ }
+
+ private void setFieldIdentifier()
+ {
+ if (curve instanceof ECCurve.Fp)
+ {
+ fieldIdentifier = prime_field;
+ }
+ else if (curve instanceof ECCurve.F2m)
+ {
+ fieldIdentifier = characteristic_two_field;
+ }
+ else
+ {
+ throw new IllegalArgumentException("This type of ECCurve is not "
+ + "implemented");
+ }
+ }
+
+ public ECCurve getCurve()
+ {
+ return curve;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * Curve ::= SEQUENCE {
+ * a FieldElement,
+ * b FieldElement,
+ * seed BIT STRING OPTIONAL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ if (fieldIdentifier.equals(prime_field))
+ {
+ v.add(new X9FieldElement(curve.getA()).toASN1Primitive());
+ v.add(new X9FieldElement(curve.getB()).toASN1Primitive());
+ }
+ else if (fieldIdentifier.equals(characteristic_two_field))
+ {
+ v.add(new X9FieldElement(curve.getA()).toASN1Primitive());
+ v.add(new X9FieldElement(curve.getB()).toASN1Primitive());
+ }
+
+ if (seed != null)
+ {
+ v.add(new DERBitString(seed));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9ECParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9ECParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9ECParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9ECParameters.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,176 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+/**
+ * ASN.1 def for Elliptic-Curve ECParameters structure. See
+ * X9.62, for further details.
+ */
+public class X9ECParameters
+ extends ASN1Object
+ implements X9ObjectIdentifiers
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private X9FieldID fieldID;
+ private ECCurve curve;
+ private ECPoint g;
+ private BigInteger n;
+ private BigInteger h;
+ private byte[] seed;
+
+ private X9ECParameters(
+ ASN1Sequence seq)
+ {
+ if (!(seq.getObjectAt(0) instanceof ASN1Integer)
+ || !((ASN1Integer)seq.getObjectAt(0)).getValue().equals(ONE))
+ {
+ throw new IllegalArgumentException("bad version in X9ECParameters");
+ }
+
+ X9Curve x9c = new X9Curve(
+ new X9FieldID((ASN1Sequence)seq.getObjectAt(1)),
+ (ASN1Sequence)seq.getObjectAt(2));
+
+ this.curve = x9c.getCurve();
+ this.g = new X9ECPoint(curve, (ASN1OctetString)seq.getObjectAt(3)).getPoint();
+ this.n = ((ASN1Integer)seq.getObjectAt(4)).getValue();
+ this.seed = x9c.getSeed();
+
+ if (seq.size() == 6)
+ {
+ this.h = ((ASN1Integer)seq.getObjectAt(5)).getValue();
+ }
+ }
+
+ public static X9ECParameters getInstance(Object obj)
+ {
+ if (obj instanceof X9ECParameters)
+ {
+ return (X9ECParameters)obj;
+ }
+
+ if (obj != null)
+ {
+ return new X9ECParameters(ASN1Sequence.getInstance(obj));
+ }
+
+ return null;
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ ECPoint g,
+ BigInteger n)
+ {
+ this(curve, g, n, ONE, null);
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ ECPoint g,
+ BigInteger n,
+ BigInteger h)
+ {
+ this(curve, g, n, h, null);
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ ECPoint g,
+ BigInteger n,
+ BigInteger h,
+ byte[] seed)
+ {
+ this.curve = curve;
+ this.g = g;
+ this.n = n;
+ this.h = h;
+ this.seed = seed;
+
+ if (curve instanceof ECCurve.Fp)
+ {
+ this.fieldID = new X9FieldID(((ECCurve.Fp)curve).getQ());
+ }
+ else
+ {
+ if (curve instanceof ECCurve.F2m)
+ {
+ ECCurve.F2m curveF2m = (ECCurve.F2m)curve;
+ this.fieldID = new X9FieldID(curveF2m.getM(), curveF2m.getK1(),
+ curveF2m.getK2(), curveF2m.getK3());
+ }
+ }
+ }
+
+ public ECCurve getCurve()
+ {
+ return curve;
+ }
+
+ public ECPoint getG()
+ {
+ return g;
+ }
+
+ public BigInteger getN()
+ {
+ return n;
+ }
+
+ public BigInteger getH()
+ {
+ if (h == null)
+ {
+ return ONE; // TODO - this should be calculated, it will cause issues with custom curves.
+ }
+
+ return h;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * ECParameters ::= SEQUENCE {
+ * version INTEGER { ecpVer1(1) } (ecpVer1),
+ * fieldID FieldID {{FieldTypes}},
+ * curve X9Curve,
+ * base X9ECPoint,
+ * order INTEGER,
+ * cofactor INTEGER OPTIONAL
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new ASN1Integer(1));
+ v.add(fieldID);
+ v.add(new X9Curve(curve, seed));
+ v.add(new X9ECPoint(g));
+ v.add(new ASN1Integer(n));
+
+ if (h != null)
+ {
+ v.add(new ASN1Integer(h));
+ }
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9ECParametersHolder.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9ECParametersHolder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9ECParametersHolder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9ECParametersHolder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+public abstract class X9ECParametersHolder
+{
+ private X9ECParameters params;
+
+ public X9ECParameters getParameters()
+ {
+ if (params == null)
+ {
+ params = createParameters();
+ }
+
+ return params;
+ }
+
+ protected abstract X9ECParameters createParameters();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9ECPoint.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9ECPoint.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9ECPoint.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9ECPoint.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+/**
+ * class for describing an ECPoint as a DER object.
+ */
+public class X9ECPoint
+ extends ASN1Object
+{
+ ECPoint p;
+
+ public X9ECPoint(
+ ECPoint p)
+ {
+ this.p = p;
+ }
+
+ public X9ECPoint(
+ ECCurve c,
+ ASN1OctetString s)
+ {
+ this.p = c.decodePoint(s.getOctets());
+ }
+
+ public ECPoint getPoint()
+ {
+ return p;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * ECPoint ::= OCTET STRING
+ *
+ *
+ * Octet string produced using ECPoint.getEncoded().
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ return new DEROctetString(p.getEncoded());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9FieldElement.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9FieldElement.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9FieldElement.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9FieldElement.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,64 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.math.ec.ECFieldElement;
+
+/**
+ * class for processing an FieldElement as a DER object.
+ */
+public class X9FieldElement
+ extends ASN1Object
+{
+ protected ECFieldElement f;
+
+ private static X9IntegerConverter converter = new X9IntegerConverter();
+
+ public X9FieldElement(ECFieldElement f)
+ {
+ this.f = f;
+ }
+
+ public X9FieldElement(BigInteger p, ASN1OctetString s)
+ {
+ this(new ECFieldElement.Fp(p, new BigInteger(1, s.getOctets())));
+ }
+
+ public X9FieldElement(int m, int k1, int k2, int k3, ASN1OctetString s)
+ {
+ this(new ECFieldElement.F2m(m, k1, k2, k3, new BigInteger(1, s.getOctets())));
+ }
+
+ public ECFieldElement getValue()
+ {
+ return f;
+ }
+
+ /**
+ * Produce an object suitable for an ASN1OutputStream.
+ *
+ * FieldElement ::= OCTET STRING
+ *
+ *
+ *
+ * if q is an odd prime then the field element is
+ * processed as an Integer and converted to an octet string
+ * according to x 9.62 4.3.1.
+ * if q is 2m then the bit string
+ * contained in the field element is converted into an octet
+ * string with the same ordering padded at the front if necessary.
+ *
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ int byteCount = converter.getByteLength(f);
+ byte[] paddedBigInteger = converter.integerToBytes(f.toBigInteger(), byteCount);
+
+ return new DEROctetString(paddedBigInteger);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9FieldID.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9FieldID.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9FieldID.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9FieldID.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,109 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1Object;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+
+/**
+ * ASN.1 def for Elliptic-Curve Field ID structure. See
+ * X9.62, for further details.
+ */
+public class X9FieldID
+ extends ASN1Object
+ implements X9ObjectIdentifiers
+{
+ private ASN1ObjectIdentifier id;
+ private ASN1Primitive parameters;
+
+ /**
+ * Constructor for elliptic curves over prime fields
+ * F2
.
+ * @param primeP The prime p
defining the prime field.
+ */
+ public X9FieldID(BigInteger primeP)
+ {
+ this.id = prime_field;
+ this.parameters = new ASN1Integer(primeP);
+ }
+
+ /**
+ * Constructor for elliptic curves over binary fields
+ * F2m
.
+ * @param m The exponent m
of
+ * F2m
.
+ * @param k1 The integer k1
where xm +
+ * xk3 + xk2 + xk1 + 1
+ * represents the reduction polynomial f(z)
.
+ * @param k2 The integer k2
where xm +
+ * xk3 + xk2 + xk1 + 1
+ * represents the reduction polynomial f(z)
.
+ * @param k3 The integer k3
where xm +
+ * xk3 + xk2 + xk1 + 1
+ * represents the reduction polynomial f(z)
..
+ */
+ public X9FieldID(int m, int k1, int k2, int k3)
+ {
+ this.id = characteristic_two_field;
+ ASN1EncodableVector fieldIdParams = new ASN1EncodableVector();
+ fieldIdParams.add(new ASN1Integer(m));
+
+ if (k2 == 0)
+ {
+ fieldIdParams.add(tpBasis);
+ fieldIdParams.add(new ASN1Integer(k1));
+ }
+ else
+ {
+ fieldIdParams.add(ppBasis);
+ ASN1EncodableVector pentanomialParams = new ASN1EncodableVector();
+ pentanomialParams.add(new ASN1Integer(k1));
+ pentanomialParams.add(new ASN1Integer(k2));
+ pentanomialParams.add(new ASN1Integer(k3));
+ fieldIdParams.add(new DERSequence(pentanomialParams));
+ }
+
+ this.parameters = new DERSequence(fieldIdParams);
+ }
+
+ public X9FieldID(
+ ASN1Sequence seq)
+ {
+ this.id = (ASN1ObjectIdentifier)seq.getObjectAt(0);
+ this.parameters = (ASN1Primitive)seq.getObjectAt(1);
+ }
+
+ public ASN1ObjectIdentifier getIdentifier()
+ {
+ return id;
+ }
+
+ public ASN1Primitive getParameters()
+ {
+ return parameters;
+ }
+
+ /**
+ * Produce a DER encoding of the following structure.
+ *
+ * FieldID ::= SEQUENCE {
+ * fieldType FIELD-ID.&id({IOSet}),
+ * parameters FIELD-ID.&Type({IOSet}{@fieldType})
+ * }
+ *
+ */
+ public ASN1Primitive toASN1Primitive()
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(this.id);
+ v.add(this.parameters);
+
+ return new DERSequence(v);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9IntegerConverter.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9IntegerConverter.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9IntegerConverter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9IntegerConverter.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,47 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+import pdftk.org.bouncycastle.math.ec.ECFieldElement;
+
+public class X9IntegerConverter
+{
+ public int getByteLength(
+ ECCurve c)
+ {
+ return (c.getFieldSize() + 7) / 8;
+ }
+
+ public int getByteLength(
+ ECFieldElement fe)
+ {
+ return (fe.getFieldSize() + 7) / 8;
+ }
+
+ public byte[] integerToBytes(
+ BigInteger s,
+ int qLength)
+ {
+ byte[] bytes = s.toByteArray();
+
+ if (qLength < bytes.length)
+ {
+ byte[] tmp = new byte[qLength];
+
+ System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+ else if (qLength > bytes.length)
+ {
+ byte[] tmp = new byte[qLength];
+
+ System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length);
+
+ return tmp;
+ }
+
+ return bytes;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/X9ObjectIdentifiers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,132 @@
+package pdftk.org.bouncycastle.asn1.x9;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+
+public interface X9ObjectIdentifiers
+{
+ //
+ // X9.62
+ //
+ // ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ // us(840) ansi-x962(10045) }
+ //
+ static final ASN1ObjectIdentifier ansi_X9_62 = new ASN1ObjectIdentifier("1.2.840.10045");
+ static final ASN1ObjectIdentifier id_fieldType = ansi_X9_62.branch("1");
+
+ static final ASN1ObjectIdentifier prime_field = id_fieldType.branch("1");
+
+ static final ASN1ObjectIdentifier characteristic_two_field = id_fieldType.branch("2");
+
+ static final ASN1ObjectIdentifier gnBasis = id_fieldType.branch("2.3.1");
+
+ static final ASN1ObjectIdentifier tpBasis = id_fieldType.branch("2.3.2");
+
+ static final ASN1ObjectIdentifier ppBasis = id_fieldType.branch("2.3.3");
+
+ static final ASN1ObjectIdentifier id_ecSigType = ansi_X9_62.branch("4");
+
+ static final ASN1ObjectIdentifier ecdsa_with_SHA1 = new ASN1ObjectIdentifier(id_ecSigType + ".1");
+
+ static final ASN1ObjectIdentifier id_publicKeyType = ansi_X9_62.branch("2");
+
+ static final ASN1ObjectIdentifier id_ecPublicKey = id_publicKeyType.branch("1");
+
+ static final ASN1ObjectIdentifier ecdsa_with_SHA2 = id_ecSigType.branch("3");
+
+ static final ASN1ObjectIdentifier ecdsa_with_SHA224 = ecdsa_with_SHA2.branch("1");
+
+ static final ASN1ObjectIdentifier ecdsa_with_SHA256 = ecdsa_with_SHA2.branch("2");
+
+ static final ASN1ObjectIdentifier ecdsa_with_SHA384 = ecdsa_with_SHA2.branch("3");
+
+ static final ASN1ObjectIdentifier ecdsa_with_SHA512 = ecdsa_with_SHA2.branch("4");
+
+ //
+ // named curves
+ //
+ static final ASN1ObjectIdentifier ellipticCurve = ansi_X9_62.branch("3");
+
+ //
+ // Two Curves
+ //
+ static final ASN1ObjectIdentifier cTwoCurve = ellipticCurve.branch("0");
+
+ static final ASN1ObjectIdentifier c2pnb163v1 = cTwoCurve.branch("1");
+ static final ASN1ObjectIdentifier c2pnb163v2 = cTwoCurve.branch("2");
+ static final ASN1ObjectIdentifier c2pnb163v3 = cTwoCurve.branch("3");
+ static final ASN1ObjectIdentifier c2pnb176w1 = cTwoCurve.branch("4");
+ static final ASN1ObjectIdentifier c2tnb191v1 = cTwoCurve.branch("5");
+ static final ASN1ObjectIdentifier c2tnb191v2 = cTwoCurve.branch("6");
+ static final ASN1ObjectIdentifier c2tnb191v3 = cTwoCurve.branch("7");
+ static final ASN1ObjectIdentifier c2onb191v4 = cTwoCurve.branch("8");
+ static final ASN1ObjectIdentifier c2onb191v5 = cTwoCurve.branch("9");
+ static final ASN1ObjectIdentifier c2pnb208w1 = cTwoCurve.branch("10");
+ static final ASN1ObjectIdentifier c2tnb239v1 = cTwoCurve.branch("11");
+ static final ASN1ObjectIdentifier c2tnb239v2 = cTwoCurve.branch("12");
+ static final ASN1ObjectIdentifier c2tnb239v3 = cTwoCurve.branch("13");
+ static final ASN1ObjectIdentifier c2onb239v4 = cTwoCurve.branch("14");
+ static final ASN1ObjectIdentifier c2onb239v5 = cTwoCurve.branch("15");
+ static final ASN1ObjectIdentifier c2pnb272w1 = cTwoCurve.branch("16");
+ static final ASN1ObjectIdentifier c2pnb304w1 = cTwoCurve.branch("17");
+ static final ASN1ObjectIdentifier c2tnb359v1 = cTwoCurve.branch("18");
+ static final ASN1ObjectIdentifier c2pnb368w1 = cTwoCurve.branch("19");
+ static final ASN1ObjectIdentifier c2tnb431r1 = cTwoCurve.branch("20");
+
+ //
+ // Prime
+ //
+ static final ASN1ObjectIdentifier primeCurve = ellipticCurve.branch("1");
+
+ static final ASN1ObjectIdentifier prime192v1 = primeCurve.branch("1");
+ static final ASN1ObjectIdentifier prime192v2 = primeCurve.branch("2");
+ static final ASN1ObjectIdentifier prime192v3 = primeCurve.branch("3");
+ static final ASN1ObjectIdentifier prime239v1 = primeCurve.branch("4");
+ static final ASN1ObjectIdentifier prime239v2 = primeCurve.branch("5");
+ static final ASN1ObjectIdentifier prime239v3 = primeCurve.branch("6");
+ static final ASN1ObjectIdentifier prime256v1 = primeCurve.branch("7");
+
+ //
+ // DSA
+ //
+ // dsapublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ // us(840) ansi-x957(10040) number-type(4) 1 }
+ static final ASN1ObjectIdentifier id_dsa = new ASN1ObjectIdentifier("1.2.840.10040.4.1");
+
+ /**
+ * id-dsa-with-sha1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) x9-57
+ * (10040) x9cm(4) 3 }
+ */
+ public static final ASN1ObjectIdentifier id_dsa_with_sha1 = new ASN1ObjectIdentifier("1.2.840.10040.4.3");
+
+ /**
+ * X9.63
+ */
+ public static final ASN1ObjectIdentifier x9_63_scheme = new ASN1ObjectIdentifier("1.3.133.16.840.63.0");
+ public static final ASN1ObjectIdentifier dhSinglePass_stdDH_sha1kdf_scheme = x9_63_scheme.branch("2");
+ public static final ASN1ObjectIdentifier dhSinglePass_cofactorDH_sha1kdf_scheme = x9_63_scheme.branch("3");
+ public static final ASN1ObjectIdentifier mqvSinglePass_sha1kdf_scheme = x9_63_scheme.branch("16");
+
+ /**
+ * X9.42
+ */
+
+ static final ASN1ObjectIdentifier ansi_X9_42 = new ASN1ObjectIdentifier("1.2.840.10046");
+
+ //
+ // Diffie-Hellman
+ //
+ // dhpublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+ // us(840) ansi-x942(10046) number-type(2) 1 }
+ //
+ public static final ASN1ObjectIdentifier dhpublicnumber = ansi_X9_42.branch("2.1");
+
+ public static final ASN1ObjectIdentifier x9_42_schemes = ansi_X9_42.branch("3");
+ public static final ASN1ObjectIdentifier dhStatic = x9_42_schemes.branch("1");
+ public static final ASN1ObjectIdentifier dhEphem = x9_42_schemes.branch("2");
+ public static final ASN1ObjectIdentifier dhOneFlow = x9_42_schemes.branch("3");
+ public static final ASN1ObjectIdentifier dhHybrid1 = x9_42_schemes.branch("4");
+ public static final ASN1ObjectIdentifier dhHybrid2 = x9_42_schemes.branch("5");
+ public static final ASN1ObjectIdentifier dhHybridOneFlow = x9_42_schemes.branch("6");
+ public static final ASN1ObjectIdentifier mqv2 = x9_42_schemes.branch("7");
+ public static final ASN1ObjectIdentifier mqv1 = x9_42_schemes.branch("8");
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/package.html pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/asn1/x9/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/asn1/x9/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Support classes useful for encoding and supporting X9.62 elliptic curve.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/AsymmetricBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/AsymmetricBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/AsymmetricBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/AsymmetricBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,45 @@
+package pdftk.org.bouncycastle.crypto;
+
+
+/**
+ * base interface that a public/private key block cipher needs
+ * to conform to.
+ */
+public interface AsymmetricBlockCipher
+{
+ /**
+ * initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param param the key and other data required by the cipher.
+ */
+ public void init(boolean forEncryption, CipherParameters param);
+
+ /**
+ * returns the largest size an input block can be.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize();
+
+ /**
+ * returns the maximum size of the block produced by this cipher.
+ *
+ * @return maximum size of the output block produced by the cipher.
+ */
+ public int getOutputBlockSize();
+
+ /**
+ * process the block of len bytes stored in in from offset inOff.
+ *
+ * @param in the input data
+ * @param inOff offset into the in array where the data starts
+ * @param len the length of the block to be processed.
+ * @return the resulting byte array of the encryption/decryption process.
+ * @exception InvalidCipherTextException data decrypts improperly.
+ * @exception DataLengthException the input data is too large for the cipher.
+ */
+ public byte[] processBlock(byte[] in, int inOff, int len)
+ throws InvalidCipherTextException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/AsymmetricCipherKeyPair.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,61 @@
+package pdftk.org.bouncycastle.crypto;
+
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+
+/**
+ * a holding class for public/private parameter pairs.
+ */
+public class AsymmetricCipherKeyPair
+{
+ private AsymmetricKeyParameter publicParam;
+ private AsymmetricKeyParameter privateParam;
+
+ /**
+ * basic constructor.
+ *
+ * @param publicParam a public key parameters object.
+ * @param privateParam the corresponding private key parameters.
+ */
+ public AsymmetricCipherKeyPair(
+ AsymmetricKeyParameter publicParam,
+ AsymmetricKeyParameter privateParam)
+ {
+ this.publicParam = publicParam;
+ this.privateParam = privateParam;
+ }
+
+ /**
+ * basic constructor.
+ *
+ * @param publicParam a public key parameters object.
+ * @param privateParam the corresponding private key parameters.
+ * @deprecated use AsymmetricKeyParameter
+ */
+ public AsymmetricCipherKeyPair(
+ CipherParameters publicParam,
+ CipherParameters privateParam)
+ {
+ this.publicParam = (AsymmetricKeyParameter)publicParam;
+ this.privateParam = (AsymmetricKeyParameter)privateParam;
+ }
+
+ /**
+ * return the public key parameters.
+ *
+ * @return the public key parameters.
+ */
+ public AsymmetricKeyParameter getPublic()
+ {
+ return publicParam;
+ }
+
+ /**
+ * return the private key parameters.
+ *
+ * @return the private key parameters.
+ */
+ public AsymmetricKeyParameter getPrivate()
+ {
+ return privateParam;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/AsymmetricCipherKeyPairGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/AsymmetricCipherKeyPairGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/AsymmetricCipherKeyPairGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/AsymmetricCipherKeyPairGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,22 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * interface that a public/private key pair generator should conform to.
+ */
+public interface AsymmetricCipherKeyPairGenerator
+{
+ /**
+ * intialise the key pair generator.
+ *
+ * @param param the parameters the key pair is to be initialised with.
+ */
+ public void init(KeyGenerationParameters param);
+
+ /**
+ * return an AsymmetricCipherKeyPair containing the generated keys.
+ *
+ * @return an AsymmetricCipherKeyPair containing the generated keys.
+ */
+ public AsymmetricCipherKeyPair generateKeyPair();
+}
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/BasicAgreement.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/BasicAgreement.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/BasicAgreement.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/BasicAgreement.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,26 @@
+package pdftk.org.bouncycastle.crypto;
+
+import java.math.BigInteger;
+
+/**
+ * The basic interface that basic Diffie-Hellman implementations
+ * conforms to.
+ */
+public interface BasicAgreement
+{
+ /**
+ * initialise the agreement engine.
+ */
+ void init(CipherParameters param);
+
+ /**
+ * return the field size for the agreement algorithm in bytes.
+ */
+ int getFieldSize();
+
+ /**
+ * given a public key from a given party calculate the next
+ * message in the agreement sequence.
+ */
+ BigInteger calculateAgreement(CipherParameters pubKey);
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/BlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/BlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/BlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/BlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,56 @@
+package pdftk.org.bouncycastle.crypto;
+
+
+/**
+ * Block cipher engines are expected to conform to this interface.
+ */
+public interface BlockCipher
+{
+ /**
+ * Initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the cipher implements.
+ *
+ * @return the name of the algorithm the cipher implements.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * Return the block size for this cipher (in bytes).
+ *
+ * @return the block size for this cipher in bytes.
+ */
+ public int getBlockSize();
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException;
+
+ /**
+ * Reset the cipher. After resetting the cipher is in the same state
+ * as it was after the last init (if there was one).
+ */
+ public void reset();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/BufferedAsymmetricBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,171 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * a buffer wrapper for an asymmetric block cipher, allowing input
+ * to be accumulated in a piecemeal fashion until final processing.
+ */
+public class BufferedAsymmetricBlockCipher
+{
+ protected byte[] buf;
+ protected int bufOff;
+
+ private final AsymmetricBlockCipher cipher;
+
+ /**
+ * base constructor.
+ *
+ * @param cipher the cipher this buffering object wraps.
+ */
+ public BufferedAsymmetricBlockCipher(
+ AsymmetricBlockCipher cipher)
+ {
+ this.cipher = cipher;
+ }
+
+ /**
+ * return the underlying cipher for the buffer.
+ *
+ * @return the underlying cipher for the buffer.
+ */
+ public AsymmetricBlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * return the amount of data sitting in the buffer.
+ *
+ * @return the amount of data sitting in the buffer.
+ */
+ public int getBufferPosition()
+ {
+ return bufOff;
+ }
+
+ /**
+ * initialise the buffer and the underlying cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ reset();
+
+ cipher.init(forEncryption, params);
+
+ //
+ // we allow for an extra byte where people are using their own padding
+ // mechanisms on a raw cipher.
+ //
+ buf = new byte[cipher.getInputBlockSize() + (forEncryption ? 1 : 0)];
+ bufOff = 0;
+ }
+
+ /**
+ * returns the largest size an input block can be.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize()
+ {
+ return cipher.getInputBlockSize();
+ }
+
+ /**
+ * returns the maximum size of the block produced by this cipher.
+ *
+ * @return maximum size of the output block produced by the cipher.
+ */
+ public int getOutputBlockSize()
+ {
+ return cipher.getOutputBlockSize();
+ }
+
+ /**
+ * add another byte for processing.
+ *
+ * @param in the input byte.
+ */
+ public void processByte(
+ byte in)
+ {
+ if (bufOff >= buf.length)
+ {
+ throw new DataLengthException("attempt to process message too long for cipher");
+ }
+
+ buf[bufOff++] = in;
+ }
+
+ /**
+ * add len bytes to the buffer for processing.
+ *
+ * @param in the input data
+ * @param inOff offset into the in array where the data starts
+ * @param len the length of the block to be processed.
+ */
+ public void processBytes(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ if (len == 0)
+ {
+ return;
+ }
+
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ if (bufOff + len > buf.length)
+ {
+ throw new DataLengthException("attempt to process message too long for cipher");
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+ bufOff += len;
+ }
+
+ /**
+ * process the contents of the buffer using the underlying
+ * cipher.
+ *
+ * @return the result of the encryption/decryption process on the
+ * buffer.
+ * @exception InvalidCipherTextException if we are given a garbage block.
+ */
+ public byte[] doFinal()
+ throws InvalidCipherTextException
+ {
+ byte[] out = cipher.processBlock(buf, 0, bufOff);
+
+ reset();
+
+ return out;
+ }
+
+ /**
+ * Reset the buffer and the underlying cipher.
+ */
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ if (buf != null)
+ {
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+ }
+
+ bufOff = 0;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/BufferedBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/BufferedBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/BufferedBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/BufferedBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,313 @@
+package pdftk.org.bouncycastle.crypto;
+
+
+/**
+ * A wrapper class that allows block ciphers to be used to process data in
+ * a piecemeal fashion. The BufferedBlockCipher outputs a block only when the
+ * buffer is full and more data is being added, or on a doFinal.
+ *
+ * Note: in the case where the underlying cipher is either a CFB cipher or an
+ * OFB one the last block may not be a multiple of the block size.
+ */
+public class BufferedBlockCipher
+{
+ protected byte[] buf;
+ protected int bufOff;
+
+ protected boolean forEncryption;
+ protected BlockCipher cipher;
+
+ protected boolean partialBlockOkay;
+ protected boolean pgpCFB;
+
+ /**
+ * constructor for subclasses
+ */
+ protected BufferedBlockCipher()
+ {
+ }
+
+ /**
+ * Create a buffered block cipher without padding.
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ */
+ public BufferedBlockCipher(
+ BlockCipher cipher)
+ {
+ this.cipher = cipher;
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+
+ //
+ // check if we can handle partial blocks on doFinal.
+ //
+ String name = cipher.getAlgorithmName();
+ int idx = name.indexOf('/') + 1;
+
+ pgpCFB = (idx > 0 && name.startsWith("PGP", idx));
+
+ if (pgpCFB)
+ {
+ partialBlockOkay = true;
+ }
+ else
+ {
+ partialBlockOkay = (idx > 0 && (name.startsWith("CFB", idx) || name.startsWith("OFB", idx) || name.startsWith("OpenPGP", idx) || name.startsWith("SIC", idx) || name.startsWith("GCTR", idx)));
+ }
+ }
+
+ /**
+ * return the cipher this object wraps.
+ *
+ * @return the cipher this object wraps.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ reset();
+
+ cipher.init(forEncryption, params);
+ }
+
+ /**
+ * return the blocksize for the underlying cipher.
+ *
+ * @return the blocksize for the underlying cipher.
+ */
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ /**
+ * return the size of the output buffer required for an update
+ * an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update
+ * with len bytes of input.
+ */
+ public int getUpdateOutputSize(
+ int len)
+ {
+ int total = len + bufOff;
+ int leftOver;
+
+ if (pgpCFB)
+ {
+ leftOver = total % buf.length - (cipher.getBlockSize() + 2);
+ }
+ else
+ {
+ leftOver = total % buf.length;
+ }
+
+ return total - leftOver;
+ }
+
+ /**
+ * return the size of the output buffer required for an update plus a
+ * doFinal with an input of 'length' bytes.
+ *
+ * @param length the length of the input.
+ * @return the space required to accommodate a call to update and doFinal
+ * with 'length' bytes of input.
+ */
+ public int getOutputSize(
+ int length)
+ {
+ // Note: Can assume partialBlockOkay is true for purposes of this calculation
+ return length + bufOff;
+ }
+
+ /**
+ * process a single byte, producing an output block if neccessary.
+ *
+ * @param in the input byte.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ int resultLen = 0;
+
+ buf[bufOff++] = in;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ bufOff = 0;
+ }
+
+ return resultLen;
+ }
+
+ /**
+ * process an array of bytes, producing output if necessary.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset at which the input data starts.
+ * @param len the number of bytes to be copied out of the input array.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = getBlockSize();
+ int length = getUpdateOutputSize(len);
+
+ if (length > 0)
+ {
+ if ((outOff + length) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > buf.length)
+ {
+ resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+
+ if (bufOff == buf.length)
+ {
+ resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
+ bufOff = 0;
+ }
+
+ return resultLen;
+ }
+
+ /**
+ * Process the last block in the buffer.
+ *
+ * @param out the array the block currently being held is copied into.
+ * @param outOff the offset at which the copying starts.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there is insufficient space in out for
+ * the output, or the input is not block size aligned and should be.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception InvalidCipherTextException if padding is expected and not found.
+ * @exception DataLengthException if the input is not block size
+ * aligned.
+ */
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException, InvalidCipherTextException
+ {
+ try
+ {
+ int resultLen = 0;
+
+ if (outOff + bufOff > out.length)
+ {
+ throw new OutputLengthException("output buffer too short for doFinal()");
+ }
+
+ if (bufOff != 0)
+ {
+ if (!partialBlockOkay)
+ {
+ throw new DataLengthException("data not block size aligned");
+ }
+
+ cipher.processBlock(buf, 0, buf, 0);
+ resultLen = bufOff;
+ bufOff = 0;
+ System.arraycopy(buf, 0, out, outOff, resultLen);
+ }
+
+ return resultLen;
+ }
+ finally
+ {
+ reset();
+ }
+ }
+
+ /**
+ * Reset the buffer and cipher. After resetting the object is in the same
+ * state as it was after the last init (if there was one).
+ */
+ public void reset()
+ {
+ //
+ // clean the buffer.
+ //
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ //
+ // reset the underlying cipher.
+ //
+ cipher.reset();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/CipherKeyGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/CipherKeyGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/CipherKeyGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/CipherKeyGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,38 @@
+package pdftk.org.bouncycastle.crypto;
+
+import java.security.SecureRandom;
+
+/**
+ * The base class for symmetric, or secret, cipher key generators.
+ */
+public class CipherKeyGenerator
+{
+ protected SecureRandom random;
+ protected int strength;
+
+ /**
+ * initialise the key generator.
+ *
+ * @param param the parameters to be used for key generation
+ */
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.random = param.getRandom();
+ this.strength = (param.getStrength() + 7) / 8;
+ }
+
+ /**
+ * generate a secret key.
+ *
+ * @return a byte array containing the key value.
+ */
+ public byte[] generateKey()
+ {
+ byte[] key = new byte[strength];
+
+ random.nextBytes(key);
+
+ return key;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/CipherParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/CipherParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/CipherParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/CipherParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,8 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * all parameter classes implement this.
+ */
+public interface CipherParameters
+{
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/CryptoException.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/CryptoException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/CryptoException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/CryptoException.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * the foundation class for the hard exceptions thrown by the crypto packages.
+ */
+public class CryptoException
+ extends Exception
+{
+ private Throwable cause;
+
+ /**
+ * base constructor.
+ */
+ public CryptoException()
+ {
+ }
+
+ /**
+ * create a CryptoException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public CryptoException(
+ String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Create a CryptoException with the given message and underlying cause.
+ *
+ * @param message message describing exception.
+ * @param cause the throwable that was the underlying cause.
+ */
+ public CryptoException(
+ String message,
+ Throwable cause)
+ {
+ super(message);
+
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/DSA.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/DSA.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/DSA.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/DSA.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,36 @@
+package pdftk.org.bouncycastle.crypto;
+
+import java.math.BigInteger;
+
+/**
+ * interface for classes implementing algorithms modeled similar to the Digital Signature Alorithm.
+ */
+public interface DSA
+{
+ /**
+ * initialise the signer for signature generation or signature
+ * verification.
+ *
+ * @param forSigning true if we are generating a signature, false
+ * otherwise.
+ * @param param key parameters for signature generation.
+ */
+ public void init(boolean forSigning, CipherParameters param);
+
+ /**
+ * sign the passed in message (usually the output of a hash function).
+ *
+ * @param message the message to be signed.
+ * @return two big integers representing the r and s values respectively.
+ */
+ public BigInteger[] generateSignature(byte[] message);
+
+ /**
+ * verify the message message against the signature values r and s.
+ *
+ * @param message the message that was supposed to have been signed.
+ * @param r the r signature value.
+ * @param s the s signature value.
+ */
+ public boolean verifySignature(byte[] message, BigInteger r, BigInteger s);
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/DataLengthException.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/DataLengthException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/DataLengthException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/DataLengthException.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,29 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * this exception is thrown if a buffer that is meant to have output
+ * copied into it turns out to be too short, or if we've been given
+ * insufficient input. In general this exception will get thrown rather
+ * than an ArrayOutOfBounds exception.
+ */
+public class DataLengthException
+ extends RuntimeCryptoException
+{
+ /**
+ * base constructor.
+ */
+ public DataLengthException()
+ {
+ }
+
+ /**
+ * create a DataLengthException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public DataLengthException(
+ String message)
+ {
+ super(message);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/DerivationFunction.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/DerivationFunction.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/DerivationFunction.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/DerivationFunction.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,17 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * base interface for general purpose byte derivation functions.
+ */
+public interface DerivationFunction
+{
+ public void init(DerivationParameters param);
+
+ /**
+ * return the message digest used as the basis for the function
+ */
+ public Digest getDigest();
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/DerivationParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/DerivationParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/DerivationParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/DerivationParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,8 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * Parameters for key/byte stream derivation classes
+ */
+public interface DerivationParameters
+{
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,51 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * interface that a message digest conforms to.
+ */
+public interface Digest
+{
+ /**
+ * return the algorithm name
+ *
+ * @return the algorithm name
+ */
+ public String getAlgorithmName();
+
+ /**
+ * return the size, in bytes, of the digest produced by this message digest.
+ *
+ * @return the size, in bytes, of the digest produced by this message digest.
+ */
+ public int getDigestSize();
+
+ /**
+ * update the message digest with a single byte.
+ *
+ * @param in the input byte to be entered.
+ */
+ public void update(byte in);
+
+ /**
+ * update the message digest with a block of bytes.
+ *
+ * @param in the byte array containing the data.
+ * @param inOff the offset into the byte array where the data starts.
+ * @param len the length of the data.
+ */
+ public void update(byte[] in, int inOff, int len);
+
+ /**
+ * close the digest, producing the final digest value. The doFinal
+ * call leaves the digest reset.
+ *
+ * @param out the array the digest is to be copied into.
+ * @param outOff the offset into the out array the digest is to start at.
+ */
+ public int doFinal(byte[] out, int outOff);
+
+ /**
+ * reset the digest back to it's initial state.
+ */
+ public void reset();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/EphemeralKeyPair.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/EphemeralKeyPair.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/EphemeralKeyPair.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/EphemeralKeyPair.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.crypto;
+
+public class EphemeralKeyPair
+{
+ private AsymmetricCipherKeyPair keyPair;
+ private KeyEncoder publicKeyEncoder;
+
+ public EphemeralKeyPair(AsymmetricCipherKeyPair keyPair, KeyEncoder publicKeyEncoder)
+ {
+ this.keyPair = keyPair;
+ this.publicKeyEncoder = publicKeyEncoder;
+ }
+
+ public AsymmetricCipherKeyPair getKeyPair()
+ {
+ return keyPair;
+ }
+
+ public byte[] getEncodedPublicKey()
+ {
+ return publicKeyEncoder.getEncoded(keyPair.getPublic());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/ExtendedDigest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/ExtendedDigest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/ExtendedDigest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/ExtendedDigest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,13 @@
+package pdftk.org.bouncycastle.crypto;
+
+public interface ExtendedDigest
+ extends Digest
+{
+ /**
+ * Return the size in bytes of the internal buffer the digest applies it's compression
+ * function to.
+ *
+ * @return byte length of the digests internal buffer.
+ */
+ public int getByteLength();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/InvalidCipherTextException.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/InvalidCipherTextException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/InvalidCipherTextException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/InvalidCipherTextException.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,40 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * this exception is thrown whenever we find something we don't expect in a
+ * message.
+ */
+public class InvalidCipherTextException
+ extends CryptoException
+{
+ /**
+ * base constructor.
+ */
+ public InvalidCipherTextException()
+ {
+ }
+
+ /**
+ * create a InvalidCipherTextException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public InvalidCipherTextException(
+ String message)
+ {
+ super(message);
+ }
+
+ /**
+ * create a InvalidCipherTextException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ * @param cause the root cause of the exception.
+ */
+ public InvalidCipherTextException(
+ String message,
+ Throwable cause)
+ {
+ super(message, cause);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/KeyEncoder.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/KeyEncoder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/KeyEncoder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/KeyEncoder.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,8 @@
+package pdftk.org.bouncycastle.crypto;
+
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+
+public interface KeyEncoder
+{
+ byte[] getEncoded(AsymmetricKeyParameter keyParameter);
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/KeyGenerationParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/KeyGenerationParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/KeyGenerationParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/KeyGenerationParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.crypto;
+
+import java.security.SecureRandom;
+
+/**
+ * The base class for parameters to key generators.
+ */
+public class KeyGenerationParameters
+{
+ private SecureRandom random;
+ private int strength;
+
+ /**
+ * initialise the generator with a source of randomness
+ * and a strength (in bits).
+ *
+ * @param random the random byte source.
+ * @param strength the size, in bits, of the keys we want to produce.
+ */
+ public KeyGenerationParameters(
+ SecureRandom random,
+ int strength)
+ {
+ this.random = random;
+ this.strength = strength;
+ }
+
+ /**
+ * return the random source associated with this
+ * generator.
+ *
+ * @return the generators random source.
+ */
+ public SecureRandom getRandom()
+ {
+ return random;
+ }
+
+ /**
+ * return the bit strength for keys produced by this generator,
+ *
+ * @return the strength of the keys this generator produces (in bits).
+ */
+ public int getStrength()
+ {
+ return strength;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/KeyParser.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/KeyParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/KeyParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/KeyParser.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,12 @@
+package pdftk.org.bouncycastle.crypto;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+
+public interface KeyParser
+{
+ AsymmetricKeyParameter readKey(InputStream stream)
+ throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/Mac.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/Mac.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/Mac.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/Mac.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,71 @@
+package pdftk.org.bouncycastle.crypto;
+
+
+/**
+ * The base interface for implementations of message authentication codes (MACs).
+ */
+public interface Mac
+{
+ /**
+ * Initialise the MAC.
+ *
+ * @param params the key and other data required by the MAC.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the MAC implements.
+ *
+ * @return the name of the algorithm the MAC implements.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * Return the block size for this MAC (in bytes).
+ *
+ * @return the block size for this MAC in bytes.
+ */
+ public int getMacSize();
+
+ /**
+ * add a single byte to the mac for processing.
+ *
+ * @param in the byte to be processed.
+ * @exception IllegalStateException if the MAC is not initialised.
+ */
+ public void update(byte in)
+ throws IllegalStateException;
+
+ /**
+ * @param in the array containing the input.
+ * @param inOff the index in the array the data begins at.
+ * @param len the length of the input starting at inOff.
+ * @exception IllegalStateException if the MAC is not initialised.
+ * @exception DataLengthException if there isn't enough data in in.
+ */
+ public void update(byte[] in, int inOff, int len)
+ throws DataLengthException, IllegalStateException;
+
+ /**
+ * Compute the final stage of the MAC writing the output to the out
+ * parameter.
+ *
+ * doFinal leaves the MAC in the same state it was after the last init.
+ *
+ * @param out the array the MAC is to be output to.
+ * @param outOff the offset into the out buffer the output is to start at.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the MAC is not initialised.
+ */
+ public int doFinal(byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException;
+
+ /**
+ * Reset the MAC. At the end of resetting the MAC should be in the
+ * in the same state it was after the last init (if there was one).
+ */
+ public void reset();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/MaxBytesExceededException.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/MaxBytesExceededException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/MaxBytesExceededException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/MaxBytesExceededException.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,27 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * this exception is thrown whenever a cipher requires a change of key, iv
+ * or similar after x amount of bytes enciphered
+ */
+public class MaxBytesExceededException
+ extends RuntimeCryptoException
+{
+ /**
+ * base constructor.
+ */
+ public MaxBytesExceededException()
+ {
+ }
+
+ /**
+ * create an with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public MaxBytesExceededException(
+ String message)
+ {
+ super(message);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/OutputLengthException.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/OutputLengthException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/OutputLengthException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/OutputLengthException.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,10 @@
+package pdftk.org.bouncycastle.crypto;
+
+public class OutputLengthException
+ extends DataLengthException
+{
+ public OutputLengthException(String msg)
+ {
+ super(msg);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/PBEParametersGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/PBEParametersGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/PBEParametersGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/PBEParametersGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,164 @@
+package pdftk.org.bouncycastle.crypto;
+
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * super class for all Password Based Encryption (PBE) parameter generator classes.
+ */
+public abstract class PBEParametersGenerator
+{
+ protected byte[] password;
+ protected byte[] salt;
+ protected int iterationCount;
+
+ /**
+ * base constructor.
+ */
+ protected PBEParametersGenerator()
+ {
+ }
+
+ /**
+ * initialise the PBE generator.
+ *
+ * @param password the password converted into bytes (see below).
+ * @param salt the salt to be mixed with the password.
+ * @param iterationCount the number of iterations the "mixing" function
+ * is to be applied for.
+ */
+ public void init(
+ byte[] password,
+ byte[] salt,
+ int iterationCount)
+ {
+ this.password = password;
+ this.salt = salt;
+ this.iterationCount = iterationCount;
+ }
+
+ /**
+ * return the password byte array.
+ *
+ * @return the password byte array.
+ */
+ public byte[] getPassword()
+ {
+ return password;
+ }
+
+ /**
+ * return the salt byte array.
+ *
+ * @return the salt byte array.
+ */
+ public byte[] getSalt()
+ {
+ return salt;
+ }
+
+ /**
+ * return the iteration count.
+ *
+ * @return the iteration count.
+ */
+ public int getIterationCount()
+ {
+ return iterationCount;
+ }
+
+ /**
+ * generate derived parameters for a key of length keySize.
+ *
+ * @param keySize the length, in bits, of the key required.
+ * @return a parameters object representing a key.
+ */
+ public abstract CipherParameters generateDerivedParameters(int keySize);
+
+ /**
+ * generate derived parameters for a key of length keySize, and
+ * an initialisation vector (IV) of length ivSize.
+ *
+ * @param keySize the length, in bits, of the key required.
+ * @param ivSize the length, in bits, of the iv required.
+ * @return a parameters object representing a key and an IV.
+ */
+ public abstract CipherParameters generateDerivedParameters(int keySize, int ivSize);
+
+ /**
+ * generate derived parameters for a key of length keySize, specifically
+ * for use with a MAC.
+ *
+ * @param keySize the length, in bits, of the key required.
+ * @return a parameters object representing a key.
+ */
+ public abstract CipherParameters generateDerivedMacParameters(int keySize);
+
+ /**
+ * converts a password to a byte array according to the scheme in
+ * PKCS5 (ascii, no padding)
+ *
+ * @param password a character array representing the password.
+ * @return a byte array representing the password.
+ */
+ public static byte[] PKCS5PasswordToBytes(
+ char[] password)
+ {
+ if (password != null)
+ {
+ byte[] bytes = new byte[password.length];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ bytes[i] = (byte)password[i];
+ }
+
+ return bytes;
+ }
+ else
+ {
+ return new byte[0];
+ }
+ }
+
+ /**
+ * converts a password to a byte array according to the scheme in
+ * PKCS5 (UTF-8, no padding)
+ *
+ * @param password a character array representing the password.
+ * @return a byte array representing the password.
+ */
+ public static byte[] PKCS5PasswordToUTF8Bytes(
+ char[] password)
+ {
+ return Strings.toUTF8ByteArray(password);
+ }
+
+ /**
+ * converts a password to a byte array according to the scheme in
+ * PKCS12 (unicode, big endian, 2 zero pad bytes at the end).
+ *
+ * @param password a character array representing the password.
+ * @return a byte array representing the password.
+ */
+ public static byte[] PKCS12PasswordToBytes(
+ char[] password)
+ {
+ if (password != null && password.length > 0)
+ {
+ // +1 for extra 2 pad bytes.
+ byte[] bytes = new byte[(password.length + 1) * 2];
+
+ for (int i = 0; i != password.length; i ++)
+ {
+ bytes[i * 2] = (byte)(password[i] >>> 8);
+ bytes[i * 2 + 1] = (byte)password[i];
+ }
+
+ return bytes;
+ }
+ else
+ {
+ return new byte[0];
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/RuntimeCryptoException.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/RuntimeCryptoException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/RuntimeCryptoException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/RuntimeCryptoException.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,26 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * the foundation class for the exceptions thrown by the crypto packages.
+ */
+public class RuntimeCryptoException
+ extends RuntimeException
+{
+ /**
+ * base constructor.
+ */
+ public RuntimeCryptoException()
+ {
+ }
+
+ /**
+ * create a RuntimeCryptoException with the given message.
+ *
+ * @param message the message to be carried with the exception.
+ */
+ public RuntimeCryptoException(
+ String message)
+ {
+ super(message);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/Signer.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/Signer.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/Signer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/Signer.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,43 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * Generic signer interface for hash based and message recovery signers.
+ */
+public interface Signer
+{
+ /**
+ * Initialise the signer for signing or verification.
+ *
+ * @param forSigning true if for signing, false otherwise
+ * @param param necessary parameters.
+ */
+ public void init(boolean forSigning, CipherParameters param);
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(byte b);
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(byte[] in, int off, int len);
+
+ /**
+ * generate a signature for the message we've been loaded with using
+ * the key we were initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException, DataLengthException;
+
+ /**
+ * return true if the internal state represents the signature described
+ * in the passed in array.
+ */
+ public boolean verifySignature(byte[] signature);
+
+ /**
+ * reset the internal state
+ */
+ public void reset();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/SignerWithRecovery.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/SignerWithRecovery.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/SignerWithRecovery.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/SignerWithRecovery.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,34 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * Signer with message recovery.
+ */
+public interface SignerWithRecovery
+ extends Signer
+{
+ /**
+ * Returns true if the signer has recovered the full message as
+ * part of signature verification.
+ *
+ * @return true if full message recovered.
+ */
+ public boolean hasFullMessage();
+
+ /**
+ * Returns a reference to what message was recovered (if any).
+ *
+ * @return full/partial message, null if nothing.
+ */
+ public byte[] getRecoveredMessage();
+
+ /**
+ * Perform an update with the recovered message before adding any other data. This must
+ * be the first update method called, and calling it will result in the signer assuming
+ * that further calls to update will include message content past what is recoverable.
+ *
+ * @param signature the signature that we are in the process of verifying.
+ * @throws IllegalStateException
+ */
+ public void updateWithRecoveredMessage(byte[] signature)
+ throws InvalidCipherTextException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/StreamBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/StreamBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/StreamBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/StreamBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,108 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * a wrapper for block ciphers with a single byte block size, so that they
+ * can be treated like stream ciphers.
+ */
+public class StreamBlockCipher
+ implements StreamCipher
+{
+ private BlockCipher cipher;
+
+ private byte[] oneByte = new byte[1];
+
+ /**
+ * basic constructor.
+ *
+ * @param cipher the block cipher to be wrapped.
+ * @exception IllegalArgumentException if the cipher has a block size other than
+ * one.
+ */
+ public StreamBlockCipher(
+ BlockCipher cipher)
+ {
+ if (cipher.getBlockSize() != 1)
+ {
+ throw new IllegalArgumentException("block cipher block size != 1.");
+ }
+
+ this.cipher = cipher;
+ }
+
+ /**
+ * initialise the underlying cipher.
+ *
+ * @param forEncryption true if we are setting up for encryption, false otherwise.
+ * @param params the necessary parameters for the underlying cipher to be initialised.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ cipher.init(forEncryption, params);
+ }
+
+ /**
+ * return the name of the algorithm we are wrapping.
+ *
+ * @return the name of the algorithm we are wrapping.
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName();
+ }
+
+ /**
+ * encrypt/decrypt a single byte returning the result.
+ *
+ * @param in the byte to be processed.
+ * @return the result of processing the input byte.
+ */
+ public byte returnByte(
+ byte in)
+ {
+ oneByte[0] = in;
+
+ cipher.processBlock(oneByte, 0, oneByte, 0);
+
+ return oneByte[0];
+ }
+
+ /**
+ * process a block of bytes from in putting the result into out.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset into the in array where the data to be processed starts.
+ * @param len the number of bytes to be processed.
+ * @param out the output buffer the processed bytes go into.
+ * @param outOff the offset into the output byte array the processed data stars at.
+ * @exception DataLengthException if the output buffer is too small.
+ */
+ public void processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ throws DataLengthException
+ {
+ if (outOff + len > out.length)
+ {
+ throw new DataLengthException("output buffer too small in processBytes()");
+ }
+
+ for (int i = 0; i != len; i++)
+ {
+ cipher.processBlock(in, inOff + i, out, outOff + i);
+ }
+ }
+
+ /**
+ * reset the underlying cipher. This leaves it in the same state
+ * it was at after the last init (if there was one).
+ */
+ public void reset()
+ {
+ cipher.reset();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/StreamCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/StreamCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/StreamCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/StreamCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,53 @@
+package pdftk.org.bouncycastle.crypto;
+
+/**
+ * the interface stream ciphers conform to.
+ */
+public interface StreamCipher
+{
+ /**
+ * Initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the cipher implements.
+ *
+ * @return the name of the algorithm the cipher implements.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * encrypt/decrypt a single byte returning the result.
+ *
+ * @param in the byte to be processed.
+ * @return the result of processing the input byte.
+ */
+ public byte returnByte(byte in);
+
+ /**
+ * process a block of bytes from in putting the result into out.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset into the in array where the data to be processed starts.
+ * @param len the number of bytes to be processed.
+ * @param out the output buffer the processed bytes go into.
+ * @param outOff the offset into the output byte array the processed data starts at.
+ * @exception DataLengthException if the output buffer is too small.
+ */
+ public void processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ throws DataLengthException;
+
+ /**
+ * reset the cipher. This leaves it in the same state
+ * it was at after the last init (if there was one).
+ */
+ public void reset();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/Wrapper.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/Wrapper.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/Wrapper.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/Wrapper.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.crypto;
+
+public interface Wrapper
+{
+ public void init(boolean forWrapping, CipherParameters param);
+
+ /**
+ * Return the name of the algorithm the wrapper implements.
+ *
+ * @return the name of the algorithm the wrapper implements.
+ */
+ public String getAlgorithmName();
+
+ public byte[] wrap(byte[] in, int inOff, int inLen);
+
+ public byte[] unwrap(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/DHAgreement.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/DHAgreement.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/DHAgreement.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/DHAgreement.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,94 @@
+package pdftk.org.bouncycastle.crypto.agreement;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.generators.DHKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.params.DHKeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * a Diffie-Hellman key exchange engine.
+ *
+ * note: This uses MTI/A0 key agreement in order to make the key agreement
+ * secure against passive attacks. If you're doing Diffie-Hellman and both
+ * parties have long term public keys you should look at using this. For
+ * further information have a look at RFC 2631.
+ *
+ * It's possible to extend this to more than two parties as well, for the moment
+ * that is left as an exercise for the reader.
+ */
+public class DHAgreement
+{
+ private DHPrivateKeyParameters key;
+ private DHParameters dhParams;
+ private BigInteger privateValue;
+ private SecureRandom random;
+
+ public void init(
+ CipherParameters param)
+ {
+ AsymmetricKeyParameter kParam;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ kParam = (AsymmetricKeyParameter)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ kParam = (AsymmetricKeyParameter)param;
+ }
+
+
+ if (!(kParam instanceof DHPrivateKeyParameters))
+ {
+ throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters");
+ }
+
+ this.key = (DHPrivateKeyParameters)kParam;
+ this.dhParams = key.getParameters();
+ }
+
+ /**
+ * calculate our initial message.
+ */
+ public BigInteger calculateMessage()
+ {
+ DHKeyPairGenerator dhGen = new DHKeyPairGenerator();
+ dhGen.init(new DHKeyGenerationParameters(random, dhParams));
+ AsymmetricCipherKeyPair dhPair = dhGen.generateKeyPair();
+
+ this.privateValue = ((DHPrivateKeyParameters)dhPair.getPrivate()).getX();
+
+ return ((DHPublicKeyParameters)dhPair.getPublic()).getY();
+ }
+
+ /**
+ * given a message from a given party and the corresponding public key,
+ * calculate the next message in the agreement sequence. In this case
+ * this will represent the shared secret.
+ */
+ public BigInteger calculateAgreement(
+ DHPublicKeyParameters pub,
+ BigInteger message)
+ {
+ if (!pub.getParameters().equals(dhParams))
+ {
+ throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters.");
+ }
+
+ BigInteger p = dhParams.getP();
+
+ return message.modPow(key.getX(), p).multiply(pub.getY().modPow(privateValue, p)).mod(p);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/DHBasicAgreement.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/DHBasicAgreement.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/DHBasicAgreement.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/DHBasicAgreement.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,71 @@
+package pdftk.org.bouncycastle.crypto.agreement;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.BasicAgreement;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * a Diffie-Hellman key agreement class.
+ *
+ * note: This is only the basic algorithm, it doesn't take advantage of
+ * long term public keys if they are available. See the DHAgreement class
+ * for a "better" implementation.
+ */
+public class DHBasicAgreement
+ implements BasicAgreement
+{
+ private DHPrivateKeyParameters key;
+ private DHParameters dhParams;
+
+ public void init(
+ CipherParameters param)
+ {
+ AsymmetricKeyParameter kParam;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+ kParam = (AsymmetricKeyParameter)rParam.getParameters();
+ }
+ else
+ {
+ kParam = (AsymmetricKeyParameter)param;
+ }
+
+ if (!(kParam instanceof DHPrivateKeyParameters))
+ {
+ throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters");
+ }
+
+ this.key = (DHPrivateKeyParameters)kParam;
+ this.dhParams = key.getParameters();
+ }
+
+ public int getFieldSize()
+ {
+ return (key.getParameters().getP().bitLength() + 7) / 8;
+ }
+
+ /**
+ * given a short term public key from a given party calculate the next
+ * message in the agreement sequence.
+ */
+ public BigInteger calculateAgreement(
+ CipherParameters pubKey)
+ {
+ DHPublicKeyParameters pub = (DHPublicKeyParameters)pubKey;
+
+ if (!pub.getParameters().equals(dhParams))
+ {
+ throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters.");
+ }
+
+ return pub.getY().modPow(key.getX(), dhParams.getP());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,51 @@
+package pdftk.org.bouncycastle.crypto.agreement;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.BasicAgreement;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+/**
+ * P1363 7.2.1 ECSVDP-DH
+ *
+ * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive,
+ * Diffie-Hellman version. It is based on the work of [DH76], [Mil86],
+ * and [Kob87]. This primitive derives a shared secret value from one
+ * party's private key and another party's public key, where both have
+ * the same set of EC domain parameters. If two parties correctly
+ * execute this primitive, they will produce the same output. This
+ * primitive can be invoked by a scheme to derive a shared secret key;
+ * specifically, it may be used with the schemes ECKAS-DH1 and
+ * DL/ECKAS-DH2. It assumes that the input keys are valid (see also
+ * Section 7.2.2).
+ */
+public class ECDHBasicAgreement
+ implements BasicAgreement
+{
+ private ECPrivateKeyParameters key;
+
+ public void init(
+ CipherParameters key)
+ {
+ this.key = (ECPrivateKeyParameters)key;
+ }
+
+ public int getFieldSize()
+ {
+ return (key.getParameters().getCurve().getFieldSize() + 7) / 8;
+ }
+
+ public BigInteger calculateAgreement(
+ CipherParameters pubKey)
+ {
+ ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
+ ECPoint P = pub.getQ().multiply(key.getD());
+
+ // if (p.isInfinity()) throw new RuntimeException("d*Q == infinity");
+
+ return P.getX().toBigInteger();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/ECDHCBasicAgreement.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,58 @@
+package pdftk.org.bouncycastle.crypto.agreement;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.BasicAgreement;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.params.ECDomainParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+/**
+ * P1363 7.2.2 ECSVDP-DHC
+ *
+ * ECSVDP-DHC is Elliptic Curve Secret Value Derivation Primitive,
+ * Diffie-Hellman version with cofactor multiplication. It is based on
+ * the work of [DH76], [Mil86], [Kob87], [LMQ98] and [Kal98a]. This
+ * primitive derives a shared secret value from one party's private key
+ * and another party's public key, where both have the same set of EC
+ * domain parameters. If two parties correctly execute this primitive,
+ * they will produce the same output. This primitive can be invoked by a
+ * scheme to derive a shared secret key; specifically, it may be used
+ * with the schemes ECKAS-DH1 and DL/ECKAS-DH2. It does not assume the
+ * validity of the input public key (see also Section 7.2.1).
+ *
+ * Note: As stated P1363 compatibility mode with ECDH can be preset, and
+ * in this case the implementation doesn't have a ECDH compatibility mode
+ * (if you want that just use ECDHBasicAgreement and note they both implement
+ * BasicAgreement!).
+ */
+public class ECDHCBasicAgreement
+ implements BasicAgreement
+{
+ ECPrivateKeyParameters key;
+
+ public void init(
+ CipherParameters key)
+ {
+ this.key = (ECPrivateKeyParameters)key;
+ }
+
+ public int getFieldSize()
+ {
+ return (key.getParameters().getCurve().getFieldSize() + 7) / 8;
+ }
+
+ public BigInteger calculateAgreement(
+ CipherParameters pubKey)
+ {
+ ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
+ ECDomainParameters params = pub.getParameters();
+ ECPoint P = pub.getQ().multiply(params.getH().multiply(key.getD()));
+
+ // if (p.isInfinity()) throw new RuntimeException("Invalid public key");
+
+ return P.getX().toBigInteger();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/ECMQVBasicAgreement.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,91 @@
+package pdftk.org.bouncycastle.crypto.agreement;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.BasicAgreement;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.params.ECDomainParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.MQVPrivateParameters;
+import pdftk.org.bouncycastle.crypto.params.MQVPublicParameters;
+import pdftk.org.bouncycastle.math.ec.ECAlgorithms;
+import pdftk.org.bouncycastle.math.ec.ECConstants;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+public class ECMQVBasicAgreement
+ implements BasicAgreement
+{
+ MQVPrivateParameters privParams;
+
+ public void init(
+ CipherParameters key)
+ {
+ this.privParams = (MQVPrivateParameters)key;
+ }
+
+ public int getFieldSize()
+ {
+ return (privParams.getStaticPrivateKey().getParameters().getCurve().getFieldSize() + 7) / 8;
+ }
+
+ public BigInteger calculateAgreement(CipherParameters pubKey)
+ {
+ MQVPublicParameters pubParams = (MQVPublicParameters)pubKey;
+
+ ECPrivateKeyParameters staticPrivateKey = privParams.getStaticPrivateKey();
+
+ ECPoint agreement = calculateMqvAgreement(staticPrivateKey.getParameters(), staticPrivateKey,
+ privParams.getEphemeralPrivateKey(), privParams.getEphemeralPublicKey(),
+ pubParams.getStaticPublicKey(), pubParams.getEphemeralPublicKey());
+
+ return agreement.getX().toBigInteger();
+ }
+
+ // The ECMQV Primitive as described in SEC-1, 3.4
+ private ECPoint calculateMqvAgreement(
+ ECDomainParameters parameters,
+ ECPrivateKeyParameters d1U,
+ ECPrivateKeyParameters d2U,
+ ECPublicKeyParameters Q2U,
+ ECPublicKeyParameters Q1V,
+ ECPublicKeyParameters Q2V)
+ {
+ BigInteger n = parameters.getN();
+ int e = (n.bitLength() + 1) / 2;
+ BigInteger powE = ECConstants.ONE.shiftLeft(e);
+
+ // The Q2U public key is optional
+ ECPoint q;
+ if (Q2U == null)
+ {
+ q = parameters.getG().multiply(d2U.getD());
+ }
+ else
+ {
+ q = Q2U.getQ();
+ }
+
+ BigInteger x = q.getX().toBigInteger();
+ BigInteger xBar = x.mod(powE);
+ BigInteger Q2UBar = xBar.setBit(e);
+ BigInteger s = d1U.getD().multiply(Q2UBar).mod(n).add(d2U.getD()).mod(n);
+
+ BigInteger xPrime = Q2V.getQ().getX().toBigInteger();
+ BigInteger xPrimeBar = xPrime.mod(powE);
+ BigInteger Q2VBar = xPrimeBar.setBit(e);
+
+ BigInteger hs = parameters.getH().multiply(s).mod(n);
+
+// ECPoint p = Q1V.getQ().multiply(Q2VBar).add(Q2V.getQ()).multiply(hs);
+ ECPoint p = ECAlgorithms.sumOfTwoMultiplies(
+ Q1V.getQ(), Q2VBar.multiply(hs).mod(n), Q2V.getQ(), hs);
+
+ if (p.isInfinity())
+ {
+ throw new IllegalStateException("Infinity is not a valid agreement value for MQV");
+ }
+
+ return p;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,573 @@
+package pdftk.org.bouncycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.digests.SHA256Digest;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * A participant in a Password Authenticated Key Exchange by Juggling (J-PAKE) exchange.
+ *
+ *
+ * The J-PAKE exchange is defined by Feng Hao and Peter Ryan in the paper
+ *
+ * "Password Authenticated Key Exchange by Juggling, 2008."
+ *
+ *
+ * The J-PAKE protocol is symmetric.
+ * There is no notion of a client or server , but rather just two participants .
+ * An instance of {@link JPAKEParticipant} represents one participant, and
+ * is the primary interface for executing the exchange.
+ *
+ *
+ * To execute an exchange, construct a {@link JPAKEParticipant} on each end,
+ * and call the following 7 methods
+ * (once and only once, in the given order, for each participant, sending messages between them as described):
+ *
+ * {@link #createRound1PayloadToSend()} - and send the payload to the other participant
+ * {@link #validateRound1PayloadReceived(JPAKERound1Payload)} - use the payload received from the other participant
+ * {@link #createRound2PayloadToSend()} - and send the payload to the other participant
+ * {@link #validateRound2PayloadReceived(JPAKERound2Payload)} - use the payload received from the other participant
+ * {@link #calculateKeyingMaterial()}
+ * {@link #createRound3PayloadToSend(BigInteger)} - and send the payload to the other participant
+ * {@link #validateRound3PayloadReceived(JPAKERound3Payload, BigInteger)} - use the payload received from the other participant
+ *
+ *
+ *
+ * Each side should derive a session key from the keying material returned by {@link #calculateKeyingMaterial()}.
+ * The caller is responsible for deriving the session key using a secure key derivation function (KDF).
+ *
+ *
+ * Round 3 is an optional key confirmation process.
+ * If you do not execute round 3, then there is no assurance that both participants are using the same key.
+ * (i.e. if the participants used different passwords, then their session keys will differ.)
+ *
+ *
+ * If the round 3 validation succeeds, then the keys are guaranteed to be the same on both sides.
+ *
+ *
+ * The symmetric design can easily support the asymmetric cases when one party initiates the communication.
+ * e.g. Sometimes the round1 payload and round2 payload may be sent in one pass.
+ * Also, in some cases, the key confirmation payload can be sent together with the round2 payload.
+ * These are the trivial techniques to optimize the communication.
+ *
+ *
+ * The key confirmation process is implemented as specified in
+ * NIST SP 800-56A Revision 1 ,
+ * Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes.
+ *
+ *
+ * This class is stateful and NOT threadsafe.
+ * Each instance should only be used for ONE complete J-PAKE exchange
+ * (i.e. a new {@link JPAKEParticipant} should be constructed for each new J-PAKE exchange).
+ *
+ *
+ * See {@link JPAKEExample} for example usage.
+ */
+public class JPAKEParticipant
+{
+ /*
+ * Possible internal states. Used for state checking.
+ */
+
+ public static final int STATE_INITIALIZED = 0;
+ public static final int STATE_ROUND_1_CREATED = 10;
+ public static final int STATE_ROUND_1_VALIDATED = 20;
+ public static final int STATE_ROUND_2_CREATED = 30;
+ public static final int STATE_ROUND_2_VALIDATED = 40;
+ public static final int STATE_KEY_CALCULATED = 50;
+ public static final int STATE_ROUND_3_CREATED = 60;
+ public static final int STATE_ROUND_3_VALIDATED = 70;
+
+ /**
+ * Unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ */
+ private final String participantId;
+
+ /**
+ * Shared secret. This only contains the secret between construction
+ * and the call to {@link #calculateKeyingMaterial()}.
+ *
+ * i.e. When {@link #calculateKeyingMaterial()} is called, this buffer overwritten with 0's,
+ * and the field is set to null.
+ */
+ private char[] password;
+
+ /**
+ * Digest to use during calculations.
+ */
+ private final Digest digest;
+
+ /**
+ * Source of secure random data.
+ */
+ private final SecureRandom random;
+
+ private final BigInteger p;
+ private final BigInteger q;
+ private final BigInteger g;
+
+ /**
+ * The participantId of the other participant in this exchange.
+ */
+ private String partnerParticipantId;
+
+ /**
+ * Alice's x1 or Bob's x3.
+ */
+ private BigInteger x1;
+ /**
+ * Alice's x2 or Bob's x4.
+ */
+ private BigInteger x2;
+ /**
+ * Alice's g^x1 or Bob's g^x3.
+ */
+ private BigInteger gx1;
+ /**
+ * Alice's g^x2 or Bob's g^x4.
+ */
+ private BigInteger gx2;
+ /**
+ * Alice's g^x3 or Bob's g^x1.
+ */
+ private BigInteger gx3;
+ /**
+ * Alice's g^x4 or Bob's g^x2.
+ */
+ private BigInteger gx4;
+ /**
+ * Alice's B or Bob's A.
+ */
+ private BigInteger b;
+
+ /**
+ * The current state.
+ * See the STATE_* constants for possible values.
+ */
+ private int state;
+
+ /**
+ * Convenience constructor for a new {@link JPAKEParticipant} that uses
+ * the {@link JPAKEPrimeOrderGroups#NIST_3072} prime order group,
+ * a SHA-256 digest, and a default {@link SecureRandom} implementation.
+ *
+ * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
+ *
+ * @param participantId unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ * @param password shared secret.
+ * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
+ * Caller should clear the input password as soon as possible.
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if password is empty
+ */
+ public JPAKEParticipant(
+ String participantId,
+ char[] password)
+ {
+ this(
+ participantId,
+ password,
+ JPAKEPrimeOrderGroups.NIST_3072);
+ }
+
+
+ /**
+ * Convenience constructor for a new {@link JPAKEParticipant} that uses
+ * a SHA-256 digest and a default {@link SecureRandom} implementation.
+ *
+ * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
+ *
+ * @param participantId unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ * @param password shared secret.
+ * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
+ * Caller should clear the input password as soon as possible.
+ * @param group prime order group.
+ * See {@link JPAKEPrimeOrderGroups} for standard groups
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if password is empty
+ */
+ public JPAKEParticipant(
+ String participantId,
+ char[] password,
+ JPAKEPrimeOrderGroup group)
+ {
+ this(
+ participantId,
+ password,
+ group,
+ new SHA256Digest(),
+ new SecureRandom());
+ }
+
+
+ /**
+ * Construct a new {@link JPAKEParticipant}.
+ *
+ * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}.
+ *
+ * @param participantId unique identifier of this participant.
+ * The two participants in the exchange must NOT share the same id.
+ * @param password shared secret.
+ * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called).
+ * Caller should clear the input password as soon as possible.
+ * @param group prime order group.
+ * See {@link JPAKEPrimeOrderGroups} for standard groups
+ * @param digest digest to use during zero knowledge proofs and key confirmation (SHA-256 or stronger preferred)
+ * @param random source of secure random data for x1 and x2, and for the zero knowledge proofs
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if password is empty
+ */
+ public JPAKEParticipant(
+ String participantId,
+ char[] password,
+ JPAKEPrimeOrderGroup group,
+ Digest digest,
+ SecureRandom random)
+ {
+ JPAKEUtil.validateNotNull(participantId, "participantId");
+ JPAKEUtil.validateNotNull(password, "password");
+ JPAKEUtil.validateNotNull(group, "p");
+ JPAKEUtil.validateNotNull(digest, "digest");
+ JPAKEUtil.validateNotNull(random, "random");
+ if (password.length == 0)
+ {
+ throw new IllegalArgumentException("Password must not be empty.");
+ }
+
+ this.participantId = participantId;
+
+ /*
+ * Create a defensive copy so as to fully encapsulate the password.
+ *
+ * This array will contain the password for the lifetime of this
+ * participant BEFORE {@link #calculateKeyingMaterial()} is called.
+ *
+ * i.e. When {@link #calculateKeyingMaterial()} is called, the array will be cleared
+ * in order to remove the password from memory.
+ *
+ * The caller is responsible for clearing the original password array
+ * given as input to this constructor.
+ */
+ this.password = Arrays.copyOf(password, password.length);
+
+ this.p = group.getP();
+ this.q = group.getQ();
+ this.g = group.getG();
+
+ this.digest = digest;
+ this.random = random;
+
+ this.state = STATE_INITIALIZED;
+ }
+
+ /**
+ * Gets the current state of this participant.
+ * See the STATE_* constants for possible values.
+ */
+ public int getState()
+ {
+ return this.state;
+ }
+
+ /**
+ * Creates and returns the payload to send to the other participant during round 1.
+ *
+ *
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_CREATED}.
+ */
+ public JPAKERound1Payload createRound1PayloadToSend()
+ {
+ if (this.state >= STATE_ROUND_1_CREATED)
+ {
+ throw new IllegalStateException("Round1 payload already created for " + participantId);
+ }
+
+ this.x1 = JPAKEUtil.generateX1(q, random);
+ this.x2 = JPAKEUtil.generateX2(q, random);
+
+ this.gx1 = JPAKEUtil.calculateGx(p, g, x1);
+ this.gx2 = JPAKEUtil.calculateGx(p, g, x2);
+ BigInteger[] knowledgeProofForX1 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx1, x1, participantId, digest, random);
+ BigInteger[] knowledgeProofForX2 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx2, x2, participantId, digest, random);
+
+ this.state = STATE_ROUND_1_CREATED;
+
+ return new JPAKERound1Payload(participantId, gx1, gx2, knowledgeProofForX1, knowledgeProofForX2);
+ }
+
+ /**
+ * Validates the payload received from the other participant during round 1.
+ *
+ *
+ * Must be called prior to {@link #createRound2PayloadToSend()}.
+ *
+ *
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_VALIDATED}.
+ *
+ * @throws CryptoException if validation fails.
+ * @throws IllegalStateException if called multiple times.
+ */
+ public void validateRound1PayloadReceived(JPAKERound1Payload round1PayloadReceived)
+ throws CryptoException
+ {
+ if (this.state >= STATE_ROUND_1_VALIDATED)
+ {
+ throw new IllegalStateException("Validation already attempted for round1 payload for" + participantId);
+ }
+ this.partnerParticipantId = round1PayloadReceived.getParticipantId();
+ this.gx3 = round1PayloadReceived.getGx1();
+ this.gx4 = round1PayloadReceived.getGx2();
+
+ BigInteger[] knowledgeProofForX3 = round1PayloadReceived.getKnowledgeProofForX1();
+ BigInteger[] knowledgeProofForX4 = round1PayloadReceived.getKnowledgeProofForX2();
+
+ JPAKEUtil.validateParticipantIdsDiffer(participantId, round1PayloadReceived.getParticipantId());
+ JPAKEUtil.validateGx4(gx4);
+ JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx3, knowledgeProofForX3, round1PayloadReceived.getParticipantId(), digest);
+ JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx4, knowledgeProofForX4, round1PayloadReceived.getParticipantId(), digest);
+
+ this.state = STATE_ROUND_1_VALIDATED;
+ }
+
+ /**
+ * Creates and returns the payload to send to the other participant during round 2.
+ *
+ *
+ * {@link #validateRound1PayloadReceived(JPAKERound1Payload)} must be called prior to this method.
+ *
+ *
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_CREATED}.
+ *
+ * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times
+ */
+ public JPAKERound2Payload createRound2PayloadToSend()
+ {
+ if (this.state >= STATE_ROUND_2_CREATED)
+ {
+ throw new IllegalStateException("Round2 payload already created for " + this.participantId);
+ }
+ if (this.state < STATE_ROUND_1_VALIDATED)
+ {
+ throw new IllegalStateException("Round1 payload must be validated prior to creating Round2 payload for " + this.participantId);
+ }
+ BigInteger gA = JPAKEUtil.calculateGA(p, gx1, gx3, gx4);
+ BigInteger s = JPAKEUtil.calculateS(password);
+ BigInteger x2s = JPAKEUtil.calculateX2s(q, x2, s);
+ BigInteger A = JPAKEUtil.calculateA(p, q, gA, x2s);
+ BigInteger[] knowledgeProofForX2s = JPAKEUtil.calculateZeroKnowledgeProof(p, q, gA, A, x2s, participantId, digest, random);
+
+ this.state = STATE_ROUND_2_CREATED;
+
+ return new JPAKERound2Payload(participantId, A, knowledgeProofForX2s);
+ }
+
+ /**
+ * Validates the payload received from the other participant during round 2.
+ *
+ *
+ * Note that this DOES NOT detect a non-common password.
+ * The only indication of a non-common password is through derivation
+ * of different keys (which can be detected explicitly by executing round 3 and round 4)
+ *
+ *
+ * Must be called prior to {@link #calculateKeyingMaterial()}.
+ *
+ *
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_VALIDATED}.
+ *
+ * @throws CryptoException if validation fails.
+ * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times
+ */
+ public void validateRound2PayloadReceived(JPAKERound2Payload round2PayloadReceived)
+ throws CryptoException
+ {
+ if (this.state >= STATE_ROUND_2_VALIDATED)
+ {
+ throw new IllegalStateException("Validation already attempted for round2 payload for" + participantId);
+ }
+ if (this.state < STATE_ROUND_1_VALIDATED)
+ {
+ throw new IllegalStateException("Round1 payload must be validated prior to validating Round2 payload for " + this.participantId);
+ }
+ BigInteger gB = JPAKEUtil.calculateGA(p, gx3, gx1, gx2);
+ this.b = round2PayloadReceived.getA();
+ BigInteger[] knowledgeProofForX4s = round2PayloadReceived.getKnowledgeProofForX2s();
+
+ JPAKEUtil.validateParticipantIdsDiffer(participantId, round2PayloadReceived.getParticipantId());
+ JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round2PayloadReceived.getParticipantId());
+ JPAKEUtil.validateGa(gB);
+ JPAKEUtil.validateZeroKnowledgeProof(p, q, gB, b, knowledgeProofForX4s, round2PayloadReceived.getParticipantId(), digest);
+
+ this.state = STATE_ROUND_2_VALIDATED;
+ }
+
+ /**
+ * Calculates and returns the key material.
+ * A session key must be derived from this key material using a secure key derivation function (KDF).
+ * The KDF used to derive the key is handled externally (i.e. not by {@link JPAKEParticipant}).
+ *
+ *
+ * The keying material will be identical for each participant if and only if
+ * each participant's password is the same. i.e. If the participants do not
+ * share the same password, then each participant will derive a different key.
+ * Therefore, if you immediately start using a key derived from
+ * the keying material, then you must handle detection of incorrect keys.
+ * If you want to handle this detection explicitly, you can optionally perform
+ * rounds 3 and 4. See {@link JPAKEParticipant} for details on how to execute
+ * rounds 3 and 4.
+ *
+ *
+ * The keying material will be in the range [0, p-1] .
+ *
+ *
+ * {@link #validateRound2PayloadReceived(JPAKERound2Payload)} must be called prior to this method.
+ *
+ *
+ * As a side effect, the internal {@link #password} array is cleared, since it is no longer needed.
+ *
+ *
+ * After execution, the {@link #getState() state} will be {@link #STATE_KEY_CALCULATED}.
+ *
+ * @throws IllegalStateException if called prior to {@link #validateRound2PayloadReceived(JPAKERound2Payload)},
+ * or if called multiple times.
+ */
+ public BigInteger calculateKeyingMaterial()
+ {
+ if (this.state >= STATE_KEY_CALCULATED)
+ {
+ throw new IllegalStateException("Key already calculated for " + participantId);
+ }
+ if (this.state < STATE_ROUND_2_VALIDATED)
+ {
+ throw new IllegalStateException("Round2 payload must be validated prior to creating key for " + participantId);
+ }
+ BigInteger s = JPAKEUtil.calculateS(password);
+
+ /*
+ * Clear the password array from memory, since we don't need it anymore.
+ *
+ * Also set the field to null as a flag to indicate that the key has already been calculated.
+ */
+ Arrays.fill(password, (char)0);
+ this.password = null;
+
+ BigInteger keyingMaterial = JPAKEUtil.calculateKeyingMaterial(p, q, gx4, x2, s, b);
+
+ /*
+ * Clear the ephemeral private key fields as well.
+ * Note that we're relying on the garbage collector to do its job to clean these up.
+ * The old objects will hang around in memory until the garbage collector destroys them.
+ *
+ * If the ephemeral private keys x1 and x2 are leaked,
+ * the attacker might be able to brute-force the password.
+ */
+ this.x1 = null;
+ this.x2 = null;
+ this.b = null;
+
+ /*
+ * Do not clear gx* yet, since those are needed by round 3.
+ */
+
+ this.state = STATE_KEY_CALCULATED;
+
+ return keyingMaterial;
+ }
+
+
+ /**
+ * Creates and returns the payload to send to the other participant during round 3.
+ *
+ *
+ * See {@link JPAKEParticipant} for more details on round 3.
+ *
+ *
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_CREATED}.
+ *
+ * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}.
+ * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times
+ */
+ public JPAKERound3Payload createRound3PayloadToSend(BigInteger keyingMaterial)
+ {
+ if (this.state >= STATE_ROUND_3_CREATED)
+ {
+ throw new IllegalStateException("Round3 payload already created for " + this.participantId);
+ }
+ if (this.state < STATE_KEY_CALCULATED)
+ {
+ throw new IllegalStateException("Keying material must be calculated prior to creating Round3 payload for " + this.participantId);
+ }
+
+ BigInteger macTag = JPAKEUtil.calculateMacTag(
+ this.participantId,
+ this.partnerParticipantId,
+ this.gx1,
+ this.gx2,
+ this.gx3,
+ this.gx4,
+ keyingMaterial,
+ this.digest);
+
+ this.state = STATE_ROUND_3_CREATED;
+
+ return new JPAKERound3Payload(participantId, macTag);
+ }
+
+ /**
+ * Validates the payload received from the other participant during round 3.
+ *
+ *
+ * See {@link JPAKEParticipant} for more details on round 3.
+ *
+ *
+ * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_VALIDATED}.
+ *
+ * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}.
+ * @throws CryptoException if validation fails.
+ * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times
+ */
+ public void validateRound3PayloadReceived(JPAKERound3Payload round3PayloadReceived, BigInteger keyingMaterial)
+ throws CryptoException
+ {
+ if (this.state >= STATE_ROUND_3_VALIDATED)
+ {
+ throw new IllegalStateException("Validation already attempted for round3 payload for" + participantId);
+ }
+ if (this.state < STATE_KEY_CALCULATED)
+ {
+ throw new IllegalStateException("Keying material must be calculated validated prior to validating Round3 payload for " + this.participantId);
+ }
+ JPAKEUtil.validateParticipantIdsDiffer(participantId, round3PayloadReceived.getParticipantId());
+ JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round3PayloadReceived.getParticipantId());
+
+ JPAKEUtil.validateMacTag(
+ this.participantId,
+ this.partnerParticipantId,
+ this.gx1,
+ this.gx2,
+ this.gx3,
+ this.gx4,
+ keyingMaterial,
+ this.digest,
+ round3PayloadReceived.getMacTag());
+
+
+ /*
+ * Clear the rest of the fields.
+ */
+ this.gx1 = null;
+ this.gx2 = null;
+ this.gx3 = null;
+ this.gx4 = null;
+
+ this.state = STATE_ROUND_3_VALIDATED;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,122 @@
+package pdftk.org.bouncycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+
+/**
+ * A pre-computed prime order group for use during a J-PAKE exchange.
+ *
+ *
+ * Typically a Schnorr group is used. In general, J-PAKE can use any prime order group
+ * that is suitable for public key cryptography, including elliptic curve cryptography.
+ *
+ *
+ * See {@link JPAKEPrimeOrderGroups} for convenient standard groups.
+ *
+ *
+ * NIST publishes
+ * many groups that can be used for the desired level of security.
+ */
+public class JPAKEPrimeOrderGroup
+{
+ private final BigInteger p;
+ private final BigInteger q;
+ private final BigInteger g;
+
+ /**
+ * Constructs a new {@link JPAKEPrimeOrderGroup}.
+ *
+ *
+ * In general, you should use one of the pre-approved groups from
+ * {@link JPAKEPrimeOrderGroups}, rather than manually constructing one.
+ *
+ *
+ * The following basic checks are performed:
+ *
+ * p-1 must be evenly divisible by q
+ * g must be in [2, p-1]
+ * g^q mod p must equal 1
+ * p must be prime (within reasonably certainty)
+ * q must be prime (within reasonably certainty)
+ *
+ *
+ *
+ * The prime checks are performed using {@link BigInteger#isProbablePrime(int)},
+ * and are therefore subject to the same probability guarantees.
+ *
+ *
+ * These checks prevent trivial mistakes.
+ * However, due to the small uncertainties if p and q are not prime,
+ * advanced attacks are not prevented.
+ * Use it at your own risk.
+ *
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if any of the above validations fail
+ */
+ public JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g)
+ {
+ /*
+ * Don't skip the checks on user-specified groups.
+ */
+ this(p, q, g, false);
+ }
+
+ /**
+ * Internal package-private constructor used by the pre-approved
+ * groups in {@link JPAKEPrimeOrderGroups}.
+ * These pre-approved groups can avoid the expensive checks.
+ */
+ JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g, boolean skipChecks)
+ {
+ JPAKEUtil.validateNotNull(p, "p");
+ JPAKEUtil.validateNotNull(q, "q");
+ JPAKEUtil.validateNotNull(g, "g");
+
+ if (!skipChecks)
+ {
+ if (!p.subtract(JPAKEUtil.ONE).mod(q).equals(JPAKEUtil.ZERO))
+ {
+ throw new IllegalArgumentException("p-1 must be evenly divisible by q");
+ }
+ if (g.compareTo(BigInteger.valueOf(2)) == -1 || g.compareTo(p.subtract(JPAKEUtil.ONE)) == 1)
+ {
+ throw new IllegalArgumentException("g must be in [2, p-1]");
+ }
+ if (!g.modPow(q, p).equals(JPAKEUtil.ONE))
+ {
+ throw new IllegalArgumentException("g^q mod p must equal 1");
+ }
+ /*
+ * Note that these checks do not guarantee that p and q are prime.
+ * We just have reasonable certainty that they are prime.
+ */
+ if (!p.isProbablePrime(20))
+ {
+ throw new IllegalArgumentException("p must be prime");
+ }
+ if (!q.isProbablePrime(20))
+ {
+ throw new IllegalArgumentException("q must be prime");
+ }
+ }
+
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroups.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,113 @@
+package pdftk.org.bouncycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+
+/**
+ * Standard pre-computed prime order groups for use by J-PAKE.
+ * (J-PAKE can use pre-computed prime order groups, same as DSA and Diffie-Hellman.)
+ *
+ *
+ * This class contains some convenient constants for use as input for
+ * constructing {@link JPAKEParticipant}s.
+ *
+ *
+ * The prime order groups below are taken from Sun's JDK JavaDoc (docs/guide/security/CryptoSpec.html#AppB),
+ * and from the prime order groups
+ * published by NIST .
+ */
+public class JPAKEPrimeOrderGroups
+{
+ /**
+ * From Sun's JDK JavaDoc (docs/guide/security/CryptoSpec.html#AppB)
+ * 1024-bit p, 160-bit q and 1024-bit g for 80-bit security.
+ */
+ public static final JPAKEPrimeOrderGroup SUN_JCE_1024 = new JPAKEPrimeOrderGroup(
+ // p
+ new BigInteger(
+ "fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669" +
+ "455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b7" +
+ "6b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb" +
+ "83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7", 16),
+ // q
+ new BigInteger(
+ "9760508f15230bccb292b982a2eb840bf0581cf5", 16),
+ // g
+ new BigInteger(
+ "f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d078267" +
+ "5159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e1" +
+ "3c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243b" +
+ "cca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a", 16),
+ true
+ );
+
+ /**
+ * From NIST.
+ * 2048-bit p, 224-bit q and 2048-bit g for 112-bit security.
+ */
+ public static final JPAKEPrimeOrderGroup NIST_2048 = new JPAKEPrimeOrderGroup(
+ // p
+ new BigInteger(
+ "C196BA05AC29E1F9C3C72D56DFFC6154A033F1477AC88EC37F09BE6C5BB95F51" +
+ "C296DD20D1A28A067CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE4" +
+ "28782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE619ECACC7E0B51652" +
+ "A8776D02A425567DED36EABD90CA33A1E8D988F0BBB92D02D1D20290113BB562" +
+ "CE1FC856EEB7CDD92D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BF" +
+ "FAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E5320121496DC65B3" +
+ "930E38047294FF877831A16D5228418DE8AB275D7D75651CEFED65F78AFC3EA7" +
+ "FE4D79B35F62A0402A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83", 16),
+ // q
+ new BigInteger(
+ "90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D", 16),
+ // g
+ new BigInteger(
+ "A59A749A11242C58C894E9E5A91804E8FA0AC64B56288F8D47D51B1EDC4D6544" +
+ "4FECA0111D78F35FC9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E50" +
+ "48B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B6E770409494B7FEE" +
+ "1DBB1E4B2BC2A53D4F893D418B7159592E4FFFDF6969E91D770DAEBD0B5CB14C" +
+ "00AD68EC7DC1E5745EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDF" +
+ "D049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E695515B05BD412F5B8" +
+ "C2F4C77EE10DA48ABD53F5DD498927EE7B692BBBCDA2FB23A516C5B4533D7398" +
+ "0B2A3B60E384ED200AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085", 16),
+ true
+ );
+
+ /**
+ * From NIST.
+ * 3072-bit p, 256-bit q and 3072-bit g for 128-bit security.
+ */
+ public static final JPAKEPrimeOrderGroup NIST_3072 = new JPAKEPrimeOrderGroup(
+ // p
+ new BigInteger(
+ "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C" +
+ "7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F" +
+ "009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" +
+ "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B" +
+ "6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D159394" +
+ "87E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" +
+ "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773E" +
+ "BE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941D" +
+ "AD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" +
+ "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D" +
+ "597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328E" +
+ "C22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73", 16),
+ // q
+ new BigInteger(
+ "CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D", 16),
+ // g
+ new BigInteger(
+ "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37" +
+ "F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB" +
+ "805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" +
+ "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8" +
+ "A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17" +
+ "A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" +
+ "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B3" +
+ "9AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B" +
+ "9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" +
+ "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828" +
+ "E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33" +
+ "787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B", 16),
+ true
+ );
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKERound1Payload.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKERound1Payload.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKERound1Payload.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKERound1Payload.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,110 @@
+package pdftk.org.bouncycastle.crypto.agreement.jpake;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * The payload sent/received during the first round of a J-PAKE exchange.
+ *
+ *
+ * Each {@link JPAKEParticipant} creates and sends an instance
+ * of this payload to the other {@link JPAKEParticipant}.
+ * The payload to send should be created via
+ * {@link JPAKEParticipant#createRound1PayloadToSend()}.
+ *
+ *
+ * Each {@link JPAKEParticipant} must also validate the payload
+ * received from the other {@link JPAKEParticipant}.
+ * The received payload should be validated via
+ * {@link JPAKEParticipant#validateRound1PayloadReceived(JPAKERound1Payload)}.
+ *
+ *
+ * This class is {@link Serializable}, so you can send it via Java serialization.
+ * However, no specific mechanism for sending this payload to the other participant
+ * is required. It is perfectly safe to decompose the fields of this payload,
+ * send those fields to the other participant in any format,
+ * and reconstruct the payload on the other side using
+ * {@link #JPAKERound1Payload(String, BigInteger, BigInteger, BigInteger[], BigInteger[])}.
+ */
+public class JPAKERound1Payload
+ implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The id of the {@link JPAKEParticipant} who created/sent this payload.
+ */
+ private final String participantId;
+
+ /**
+ * The value of g^x1
+ */
+ private final BigInteger gx1;
+
+ /**
+ * The value of g^x2
+ */
+ private final BigInteger gx2;
+
+ /**
+ * The zero knowledge proof for x1.
+ *
+ * This is a two element array, containing {g^v, r} for x1.
+ */
+ private final BigInteger[] knowledgeProofForX1;
+
+ /**
+ * The zero knowledge proof for x2.
+ *
+ * This is a two element array, containing {g^v, r} for x2.
+ */
+ private final BigInteger[] knowledgeProofForX2;
+
+ public JPAKERound1Payload(
+ String participantId,
+ BigInteger gx1,
+ BigInteger gx2,
+ BigInteger[] knowledgeProofForX1,
+ BigInteger[] knowledgeProofForX2)
+ {
+ JPAKEUtil.validateNotNull(participantId, "participantId");
+ JPAKEUtil.validateNotNull(gx1, "gx1");
+ JPAKEUtil.validateNotNull(gx2, "gx2");
+ JPAKEUtil.validateNotNull(knowledgeProofForX1, "knowledgeProofForX1");
+ JPAKEUtil.validateNotNull(knowledgeProofForX2, "knowledgeProofForX2");
+
+ this.participantId = participantId;
+ this.gx1 = gx1;
+ this.gx2 = gx2;
+ this.knowledgeProofForX1 = Arrays.copyOf(knowledgeProofForX1, knowledgeProofForX1.length);
+ this.knowledgeProofForX2 = Arrays.copyOf(knowledgeProofForX2, knowledgeProofForX2.length);
+ }
+
+ public String getParticipantId()
+ {
+ return participantId;
+ }
+
+ public BigInteger getGx1()
+ {
+ return gx1;
+ }
+
+ public BigInteger getGx2()
+ {
+ return gx2;
+ }
+
+ public BigInteger[] getKnowledgeProofForX1()
+ {
+ return Arrays.copyOf(knowledgeProofForX1, knowledgeProofForX1.length);
+ }
+
+ public BigInteger[] getKnowledgeProofForX2()
+ {
+ return Arrays.copyOf(knowledgeProofForX2, knowledgeProofForX2.length);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKERound2Payload.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKERound2Payload.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKERound2Payload.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKERound2Payload.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,82 @@
+package pdftk.org.bouncycastle.crypto.agreement.jpake;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * The payload sent/received during the second round of a J-PAKE exchange.
+ *
+ *
+ * Each {@link JPAKEParticipant} creates and sends an instance
+ * of this payload to the other {@link JPAKEParticipant}.
+ * The payload to send should be created via
+ * {@link JPAKEParticipant#createRound2PayloadToSend()}
+ *
+ *
+ * Each {@link JPAKEParticipant} must also validate the payload
+ * received from the other {@link JPAKEParticipant}.
+ * The received payload should be validated via
+ * {@link JPAKEParticipant#validateRound2PayloadReceived(JPAKERound2Payload)}
+ *
+ *
+ * This class is {@link Serializable}, so you can send it via Java serialization.
+ * However, no specific mechanism for sending this payload to the other participant
+ * is required. It is perfectly safe to decompose the fields of this payload,
+ * send those fields to the other participant in any format,
+ * and reconstruct the payload on the other side using
+ * {@link #JPAKERound2Payload(String, BigInteger, BigInteger[])}.
+ */
+public class JPAKERound2Payload
+ implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The id of the {@link JPAKEParticipant} who created/sent this payload.
+ */
+ private final String participantId;
+
+ /**
+ * The value of A, as computed during round 2.
+ */
+ private final BigInteger a;
+
+ /**
+ * The zero knowledge proof for x2 * s.
+ *
+ * This is a two element array, containing {g^v, r} for x2 * s.
+ */
+ private final BigInteger[] knowledgeProofForX2s;
+
+ public JPAKERound2Payload(
+ String participantId,
+ BigInteger a,
+ BigInteger[] knowledgeProofForX2s)
+ {
+ JPAKEUtil.validateNotNull(participantId, "participantId");
+ JPAKEUtil.validateNotNull(a, "a");
+ JPAKEUtil.validateNotNull(knowledgeProofForX2s, "knowledgeProofForX2s");
+
+ this.participantId = participantId;
+ this.a = a;
+ this.knowledgeProofForX2s = Arrays.copyOf(knowledgeProofForX2s, knowledgeProofForX2s.length);
+ }
+
+ public String getParticipantId()
+ {
+ return participantId;
+ }
+
+ public BigInteger getA()
+ {
+ return a;
+ }
+
+ public BigInteger[] getKnowledgeProofForX2s()
+ {
+ return Arrays.copyOf(knowledgeProofForX2s, knowledgeProofForX2s.length);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKERound3Payload.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKERound3Payload.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKERound3Payload.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKERound3Payload.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,63 @@
+package pdftk.org.bouncycastle.crypto.agreement.jpake;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+
+/**
+ * The payload sent/received during the optional third round of a J-PAKE exchange,
+ * which is for explicit key confirmation.
+ *
+ *
+ * Each {@link JPAKEParticipant} creates and sends an instance
+ * of this payload to the other {@link JPAKEParticipant}.
+ * The payload to send should be created via
+ * {@link JPAKEParticipant#createRound3PayloadToSend(BigInteger)}
+ *
+ *
+ * Each {@link JPAKEParticipant} must also validate the payload
+ * received from the other {@link JPAKEParticipant}.
+ * The received payload should be validated via
+ * {@link JPAKEParticipant#validateRound3PayloadReceived(JPAKERound3Payload, BigInteger)}
+ *
+ *
+ * This class is {@link Serializable}, so you can send it via Java serialization.
+ * However, no specific mechanism for sending this payload to the other participant
+ * is required. It is perfectly safe to decompose the fields of this payload,
+ * send those fields to the other participant in any format,
+ * and reconstruct the payload on the other side using
+ * {@link #JPAKERound3Payload(String, BigInteger)}
+ */
+public class JPAKERound3Payload
+ implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The id of the {@link JPAKEParticipant} who created/sent this payload.
+ */
+ private final String participantId;
+
+ /**
+ * The value of MacTag, as computed by round 3.
+ *
+ * @see JPAKEUtil#calculateMacTag(String, String, BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, pdftk.org.bouncycastle.crypto.Digest)
+ */
+ private final BigInteger macTag;
+
+ public JPAKERound3Payload(String participantId, BigInteger magTag)
+ {
+ this.participantId = participantId;
+ this.macTag = magTag;
+ }
+
+ public String getParticipantId()
+ {
+ return participantId;
+ }
+
+ public BigInteger getMacTag()
+ {
+ return macTag;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEUtil.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEUtil.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEUtil.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/jpake/JPAKEUtil.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,508 @@
+package pdftk.org.bouncycastle.crypto.agreement.jpake;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.macs.HMac;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.BigIntegers;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * Primitives needed for a J-PAKE exchange.
+ *
+ *
+ * The recommended way to perform a J-PAKE exchange is by using
+ * two {@link JPAKEParticipant}s. Internally, those participants
+ * call these primitive operations in {@link JPAKEUtil}.
+ *
+ *
+ * The primitives, however, can be used without a {@link JPAKEParticipant}
+ * if needed.
+ */
+public class JPAKEUtil
+{
+ static final BigInteger ZERO = BigInteger.valueOf(0);
+ static final BigInteger ONE = BigInteger.valueOf(1);
+
+ /**
+ * Return a value that can be used as x1 or x3 during round 1.
+ *
+ *
+ * The returned value is a random value in the range [0, q-1] .
+ */
+ public static BigInteger generateX1(
+ BigInteger q,
+ SecureRandom random)
+ {
+ BigInteger min = ZERO;
+ BigInteger max = q.subtract(ONE);
+ return BigIntegers.createRandomInRange(min, max, random);
+ }
+
+ /**
+ * Return a value that can be used as x2 or x4 during round 1.
+ *
+ *
+ * The returned value is a random value in the range [1, q-1] .
+ */
+ public static BigInteger generateX2(
+ BigInteger q,
+ SecureRandom random)
+ {
+ BigInteger min = ONE;
+ BigInteger max = q.subtract(ONE);
+ return BigIntegers.createRandomInRange(min, max, random);
+ }
+
+ /**
+ * Converts the given password to a {@link BigInteger}
+ * for use in arithmetic calculations.
+ */
+ public static BigInteger calculateS(char[] password)
+ {
+ return new BigInteger(Strings.toUTF8ByteArray(password));
+ }
+
+ /**
+ * Calculate g^x mod p as done in round 1.
+ */
+ public static BigInteger calculateGx(
+ BigInteger p,
+ BigInteger g,
+ BigInteger x)
+ {
+ return g.modPow(x, p);
+ }
+
+
+ /**
+ * Calculate ga as done in round 2.
+ */
+ public static BigInteger calculateGA(
+ BigInteger p,
+ BigInteger gx1,
+ BigInteger gx3,
+ BigInteger gx4)
+ {
+ // ga = g^(x1+x3+x4) = g^x1 * g^x3 * g^x4
+ return gx1.multiply(gx3).multiply(gx4).mod(p);
+ }
+
+
+ /**
+ * Calculate x2 * s as done in round 2.
+ */
+ public static BigInteger calculateX2s(
+ BigInteger q,
+ BigInteger x2,
+ BigInteger s)
+ {
+ return x2.multiply(s).mod(q);
+ }
+
+
+ /**
+ * Calculate A as done in round 2.
+ */
+ public static BigInteger calculateA(
+ BigInteger p,
+ BigInteger q,
+ BigInteger gA,
+ BigInteger x2s)
+ {
+ // A = ga^(x*s)
+ return gA.modPow(x2s, p);
+ }
+
+ /**
+ * Calculate a zero knowledge proof of x using Schnorr's signature.
+ * The returned array has two elements {g^v, r = v-x*h} for x.
+ */
+ public static BigInteger[] calculateZeroKnowledgeProof(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g,
+ BigInteger gx,
+ BigInteger x,
+ String participantId,
+ Digest digest,
+ SecureRandom random)
+ {
+ BigInteger[] zeroKnowledgeProof = new BigInteger[2];
+
+ /* Generate a random v, and compute g^v */
+ BigInteger vMin = ZERO;
+ BigInteger vMax = q.subtract(ONE);
+ BigInteger v = BigIntegers.createRandomInRange(vMin, vMax, random);
+
+ BigInteger gv = g.modPow(v, p);
+ BigInteger h = calculateHashForZeroKnowledgeProof(g, gv, gx, participantId, digest); // h
+
+ zeroKnowledgeProof[0] = gv;
+ zeroKnowledgeProof[1] = v.subtract(x.multiply(h)).mod(q); // r = v-x*h
+
+ return zeroKnowledgeProof;
+ }
+
+ private static BigInteger calculateHashForZeroKnowledgeProof(
+ BigInteger g,
+ BigInteger gr,
+ BigInteger gx,
+ String participantId,
+ Digest digest)
+ {
+ digest.reset();
+
+ updateDigestIncludingSize(digest, g);
+
+ updateDigestIncludingSize(digest, gr);
+
+ updateDigestIncludingSize(digest, gx);
+
+ updateDigestIncludingSize(digest, participantId);
+
+ byte[] output = new byte[digest.getDigestSize()];
+ digest.doFinal(output, 0);
+
+ return new BigInteger(output);
+ }
+
+ /**
+ * Validates that g^x4 is not 1.
+ *
+ * @throws CryptoException if g^x4 is 1
+ */
+ public static void validateGx4(BigInteger gx4)
+ throws CryptoException
+ {
+ if (gx4.equals(ONE))
+ {
+ throw new CryptoException("g^x validation failed. g^x should not be 1.");
+ }
+ }
+
+ /**
+ * Validates that ga is not 1.
+ *
+ *
+ * As described by Feng Hao...
+ *
+ *
+ * Alice could simply check ga != 1 to ensure it is a generator.
+ * In fact, as we will explain in Section 3, (x1 + x3 + x4 ) is random over Zq even in the face of active attacks.
+ * Hence, the probability for ga = 1 is extremely small - on the order of 2^160 for 160-bit q.
+ *
+ *
+ * @throws CryptoException if ga is 1
+ */
+ public static void validateGa(BigInteger ga)
+ throws CryptoException
+ {
+ if (ga.equals(ONE))
+ {
+ throw new CryptoException("ga is equal to 1. It should not be. The chances of this happening are on the order of 2^160 for a 160-bit q. Try again.");
+ }
+ }
+
+ /**
+ * Validates the zero knowledge proof (generated by
+ * {@link #calculateZeroKnowledgeProof(BigInteger, BigInteger, BigInteger, BigInteger, BigInteger, String, Digest, SecureRandom)})
+ * is correct.
+ *
+ * @throws CryptoException if the zero knowledge proof is not correct
+ */
+ public static void validateZeroKnowledgeProof(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g,
+ BigInteger gx,
+ BigInteger[] zeroKnowledgeProof,
+ String participantId,
+ Digest digest)
+ throws CryptoException
+ {
+
+ /* sig={g^v,r} */
+ BigInteger gv = zeroKnowledgeProof[0];
+ BigInteger r = zeroKnowledgeProof[1];
+
+ BigInteger h = calculateHashForZeroKnowledgeProof(g, gv, gx, participantId, digest);
+ if (!(gx.compareTo(ZERO) == 1 && // g^x > 0
+ gx.compareTo(p) == -1 && // g^x < p
+ gx.modPow(q, p).compareTo(ONE) == 0 && // g^x^q mod q = 1
+ /*
+ * Below, I took an straightforward way to compute g^r * g^x^h,
+ * which needs 2 exp. Using a simultaneous computation technique
+ * would only need 1 exp.
+ */
+ g.modPow(r, p).multiply(gx.modPow(h, p)).mod(p).compareTo(gv) == 0)) // g^v=g^r * g^x^h
+ {
+ throw new CryptoException("Zero-knowledge proof validation failed");
+ }
+ }
+
+ /**
+ * Calculates the keying material, which can be done after round 2 has completed.
+ * A session key must be derived from this key material using a secure key derivation function (KDF).
+ * The KDF used to derive the key is handled externally (i.e. not by {@link JPAKEParticipant}).
+ *
+ *
+ *
+ * KeyingMaterial = (B/g^{x2*x4*s})^x2
+ *
+ */
+ public static BigInteger calculateKeyingMaterial(
+ BigInteger p,
+ BigInteger q,
+ BigInteger gx4,
+ BigInteger x2,
+ BigInteger s,
+ BigInteger B)
+ {
+ return gx4.modPow(x2.multiply(s).negate().mod(q), p).multiply(B).modPow(x2, p);
+ }
+
+ /**
+ * Validates that the given participant ids are not equal.
+ * (For the J-PAKE exchange, each participant must use a unique id.)
+ *
+ * @throws CryptoException if the participantId strings are equal.
+ */
+ public static void validateParticipantIdsDiffer(String participantId1, String participantId2)
+ throws CryptoException
+ {
+ if (participantId1.equals(participantId2))
+ {
+ throw new CryptoException(
+ "Both participants are using the same participantId ("
+ + participantId1
+ + "). This is not allowed. "
+ + "Each participant must use a unique participantId.");
+ }
+ }
+
+ /**
+ * Validates that the given participant ids are equal.
+ * This is used to ensure that the payloads received from
+ * each round all come from the same participant.
+ *
+ * @throws CryptoException if the participantId strings are equal.
+ */
+ public static void validateParticipantIdsEqual(String expectedParticipantId, String actualParticipantId)
+ throws CryptoException
+ {
+ if (!expectedParticipantId.equals(actualParticipantId))
+ {
+ throw new CryptoException(
+ "Received payload from incorrect partner ("
+ + actualParticipantId
+ + "). Expected to receive payload from "
+ + expectedParticipantId
+ + ".");
+ }
+ }
+
+ /**
+ * Validates that the given object is not null.
+ *
+ * @param object object in question
+ * @param description name of the object (to be used in exception message)
+ * @throws NullPointerException if the object is null.
+ */
+ public static void validateNotNull(Object object, String description)
+ {
+ if (object == null)
+ {
+ throw new NullPointerException(description + " must not be null");
+ }
+ }
+
+ /**
+ * Calculates the MacTag (to be used for key confirmation), as defined by
+ * NIST SP 800-56A Revision 1 ,
+ * Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes.
+ *
+ *
+ *
+ * MacTag = HMAC(MacKey, MacLen, MacData)
+ *
+ * MacKey = H(K || "JPAKE_KC")
+ *
+ * MacData = "KC_1_U" || participantId || partnerParticipantId || gx1 || gx2 || gx3 || gx4
+ *
+ * Note that both participants use "KC_1_U" because the sender of the round 3 message
+ * is always the initiator for key confirmation.
+ *
+ * HMAC = {@link HMac} used with the given {@link Digest}
+ * H = The given {@link Digest}
+ * MacLen = length of MacTag
+ *
+ *
+ */
+ public static BigInteger calculateMacTag(
+ String participantId,
+ String partnerParticipantId,
+ BigInteger gx1,
+ BigInteger gx2,
+ BigInteger gx3,
+ BigInteger gx4,
+ BigInteger keyingMaterial,
+ Digest digest)
+ {
+ byte[] macKey = calculateMacKey(
+ keyingMaterial,
+ digest);
+
+ HMac mac = new HMac(digest);
+ byte[] macOutput = new byte[mac.getMacSize()];
+ mac.init(new KeyParameter(macKey));
+
+ /*
+ * MacData = "KC_1_U" || participantId_Alice || participantId_Bob || gx1 || gx2 || gx3 || gx4.
+ */
+ updateMac(mac, "KC_1_U");
+ updateMac(mac, participantId);
+ updateMac(mac, partnerParticipantId);
+ updateMac(mac, gx1);
+ updateMac(mac, gx2);
+ updateMac(mac, gx3);
+ updateMac(mac, gx4);
+
+ mac.doFinal(macOutput, 0);
+
+ Arrays.fill(macKey, (byte)0);
+
+ return new BigInteger(macOutput);
+
+ }
+
+ /**
+ * Calculates the MacKey (i.e. the key to use when calculating the MagTag for key confirmation).
+ *
+ *
+ *
+ * MacKey = H(K || "JPAKE_KC")
+ *
+ */
+ private static byte[] calculateMacKey(BigInteger keyingMaterial, Digest digest)
+ {
+ digest.reset();
+
+ updateDigest(digest, keyingMaterial);
+ /*
+ * This constant is used to ensure that the macKey is NOT the same as the derived key.
+ */
+ updateDigest(digest, "JPAKE_KC");
+
+ byte[] output = new byte[digest.getDigestSize()];
+ digest.doFinal(output, 0);
+
+ return output;
+ }
+
+ /**
+ * Validates the MacTag received from the partner participant.
+ *
+ *
+ * @param partnerMacTag the MacTag received from the partner.
+ * @throws CryptoException if the participantId strings are equal.
+ */
+ public static void validateMacTag(
+ String participantId,
+ String partnerParticipantId,
+ BigInteger gx1,
+ BigInteger gx2,
+ BigInteger gx3,
+ BigInteger gx4,
+ BigInteger keyingMaterial,
+ Digest digest,
+ BigInteger partnerMacTag)
+ throws CryptoException
+ {
+ /*
+ * Calculate the expected MacTag using the parameters as the partner
+ * would have used when the partner called calculateMacTag.
+ *
+ * i.e. basically all the parameters are reversed.
+ * participantId <-> partnerParticipantId
+ * x1 <-> x3
+ * x2 <-> x4
+ */
+ BigInteger expectedMacTag = calculateMacTag(
+ partnerParticipantId,
+ participantId,
+ gx3,
+ gx4,
+ gx1,
+ gx2,
+ keyingMaterial,
+ digest);
+
+ if (!expectedMacTag.equals(partnerMacTag))
+ {
+ throw new CryptoException(
+ "Partner MacTag validation failed. "
+ + "Therefore, the password, MAC, or digest algorithm of each participant does not match.");
+ }
+ }
+
+ private static void updateDigest(Digest digest, BigInteger bigInteger)
+ {
+ byte[] byteArray = BigIntegers.asUnsignedByteArray(bigInteger);
+ digest.update(byteArray, 0, byteArray.length);
+ Arrays.fill(byteArray, (byte)0);
+ }
+
+ private static void updateDigestIncludingSize(Digest digest, BigInteger bigInteger)
+ {
+ byte[] byteArray = BigIntegers.asUnsignedByteArray(bigInteger);
+ digest.update(intToByteArray(byteArray.length), 0, 4);
+ digest.update(byteArray, 0, byteArray.length);
+ Arrays.fill(byteArray, (byte)0);
+ }
+
+ private static void updateDigest(Digest digest, String string)
+ {
+ byte[] byteArray = Strings.toUTF8ByteArray(string);
+ digest.update(byteArray, 0, byteArray.length);
+ Arrays.fill(byteArray, (byte)0);
+ }
+
+ private static void updateDigestIncludingSize(Digest digest, String string)
+ {
+ byte[] byteArray = Strings.toUTF8ByteArray(string);
+ digest.update(intToByteArray(byteArray.length), 0, 4);
+ digest.update(byteArray, 0, byteArray.length);
+ Arrays.fill(byteArray, (byte)0);
+ }
+
+ private static void updateMac(Mac mac, BigInteger bigInteger)
+ {
+ byte[] byteArray = BigIntegers.asUnsignedByteArray(bigInteger);
+ mac.update(byteArray, 0, byteArray.length);
+ Arrays.fill(byteArray, (byte)0);
+ }
+
+ private static void updateMac(Mac mac, String string)
+ {
+ byte[] byteArray = Strings.toUTF8ByteArray(string);
+ mac.update(byteArray, 0, byteArray.length);
+ Arrays.fill(byteArray, (byte)0);
+ }
+
+ private static byte[] intToByteArray(int value)
+ {
+ return new byte[]{
+ (byte)(value >>> 24),
+ (byte)(value >>> 16),
+ (byte)(value >>> 8),
+ (byte)value
+ };
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/kdf/DHKDFParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/kdf/DHKDFParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/kdf/DHKDFParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/kdf/DHKDFParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,54 @@
+package pdftk.org.bouncycastle.crypto.agreement.kdf;
+
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERObjectIdentifier;
+import pdftk.org.bouncycastle.crypto.DerivationParameters;
+
+public class DHKDFParameters
+ implements DerivationParameters
+{
+ private ASN1ObjectIdentifier algorithm;
+ private int keySize;
+ private byte[] z;
+ private byte[] extraInfo;
+
+ public DHKDFParameters(
+ DERObjectIdentifier algorithm,
+ int keySize,
+ byte[] z)
+ {
+ this(algorithm, keySize, z, null);
+ }
+
+ public DHKDFParameters(
+ DERObjectIdentifier algorithm,
+ int keySize,
+ byte[] z,
+ byte[] extraInfo)
+ {
+ this.algorithm = new ASN1ObjectIdentifier(algorithm.getId());
+ this.keySize = keySize;
+ this.z = z;
+ this.extraInfo = extraInfo;
+ }
+
+ public ASN1ObjectIdentifier getAlgorithm()
+ {
+ return algorithm;
+ }
+
+ public int getKeySize()
+ {
+ return keySize;
+ }
+
+ public byte[] getZ()
+ {
+ return z;
+ }
+
+ public byte[] getExtraInfo()
+ {
+ return extraInfo;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/kdf/DHKEKGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,142 @@
+package pdftk.org.bouncycastle.crypto.agreement.kdf;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Encoding;
+import pdftk.org.bouncycastle.asn1.DERObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.DerivationFunction;
+import pdftk.org.bouncycastle.crypto.DerivationParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+
+/**
+ * RFC 2631 Diffie-hellman KEK derivation function.
+ */
+public class DHKEKGenerator
+ implements DerivationFunction
+{
+ private final Digest digest;
+
+ private DERObjectIdentifier algorithm;
+ private int keySize;
+ private byte[] z;
+ private byte[] partyAInfo;
+
+ public DHKEKGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+ }
+
+ public void init(DerivationParameters param)
+ {
+ DHKDFParameters params = (DHKDFParameters)param;
+
+ this.algorithm = params.getAlgorithm();
+ this.keySize = params.getKeySize();
+ this.z = params.getZ();
+ this.partyAInfo = params.getExtraInfo();
+ }
+
+ public Digest getDigest()
+ {
+ return digest;
+ }
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+ if ((out.length - len) < outOff)
+ {
+ throw new DataLengthException("output buffer too small");
+ }
+
+ long oBytes = len;
+ int outLen = digest.getDigestSize();
+
+ //
+ // this is at odds with the standard implementation, the
+ // maximum value should be hBits * (2^32 - 1) where hBits
+ // is the digest output size in bits. We can't have an
+ // array with a long index at the moment...
+ //
+ if (oBytes > ((2L << 32) - 1))
+ {
+ throw new IllegalArgumentException("Output length too large");
+ }
+
+ int cThreshold = (int)((oBytes + outLen - 1) / outLen);
+
+ byte[] dig = new byte[digest.getDigestSize()];
+
+ int counter = 1;
+
+ for (int i = 0; i < cThreshold; i++)
+ {
+ digest.update(z, 0, z.length);
+
+ // OtherInfo
+ ASN1EncodableVector v1 = new ASN1EncodableVector();
+ // KeySpecificInfo
+ ASN1EncodableVector v2 = new ASN1EncodableVector();
+
+ v2.add(algorithm);
+ v2.add(new DEROctetString(integerToBytes(counter)));
+
+ v1.add(new DERSequence(v2));
+
+ if (partyAInfo != null)
+ {
+ v1.add(new DERTaggedObject(true, 0, new DEROctetString(partyAInfo)));
+ }
+
+ v1.add(new DERTaggedObject(true, 2, new DEROctetString(integerToBytes(keySize))));
+
+ try
+ {
+ byte[] other = new DERSequence(v1).getEncoded(ASN1Encoding.DER);
+
+ digest.update(other, 0, other.length);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to encode parameter info: " + e.getMessage());
+ }
+
+ digest.doFinal(dig, 0);
+
+ if (len > outLen)
+ {
+ System.arraycopy(dig, 0, out, outOff, outLen);
+ outOff += outLen;
+ len -= outLen;
+ }
+ else
+ {
+ System.arraycopy(dig, 0, out, outOff, len);
+ }
+
+ counter++;
+ }
+
+ digest.reset();
+
+ return len;
+ }
+
+ private byte[] integerToBytes(int keySize)
+ {
+ byte[] val = new byte[4];
+
+ val[0] = (byte)(keySize >> 24);
+ val[1] = (byte)(keySize >> 16);
+ val[2] = (byte)(keySize >> 8);
+ val[3] = (byte)keySize;
+
+ return val;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/kdf/ECDHKEKGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,85 @@
+package pdftk.org.bouncycastle.crypto.agreement.kdf;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Encoding;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERNull;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.asn1.DERTaggedObject;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.DerivationFunction;
+import pdftk.org.bouncycastle.crypto.DerivationParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.generators.KDF2BytesGenerator;
+import pdftk.org.bouncycastle.crypto.params.KDFParameters;
+
+/**
+ * X9.63 based key derivation function for ECDH CMS.
+ */
+public class ECDHKEKGenerator
+ implements DerivationFunction
+{
+ private DerivationFunction kdf;
+
+ private ASN1ObjectIdentifier algorithm;
+ private int keySize;
+ private byte[] z;
+
+ public ECDHKEKGenerator(
+ Digest digest)
+ {
+ this.kdf = new KDF2BytesGenerator(digest);
+ }
+
+ public void init(DerivationParameters param)
+ {
+ DHKDFParameters params = (DHKDFParameters)param;
+
+ this.algorithm = params.getAlgorithm();
+ this.keySize = params.getKeySize();
+ this.z = params.getZ();
+ }
+
+ public Digest getDigest()
+ {
+ return kdf.getDigest();
+ }
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+ // TODO Create an ASN.1 class for this (RFC3278)
+ // ECC-CMS-SharedInfo
+ ASN1EncodableVector v = new ASN1EncodableVector();
+
+ v.add(new AlgorithmIdentifier(algorithm, DERNull.INSTANCE));
+ v.add(new DERTaggedObject(true, 2, new DEROctetString(integerToBytes(keySize))));
+
+ try
+ {
+ kdf.init(new KDFParameters(z, new DERSequence(v).getEncoded(ASN1Encoding.DER)));
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("unable to initialise kdf: " + e.getMessage());
+ }
+
+ return kdf.generateBytes(out, outOff, len);
+ }
+
+ private byte[] integerToBytes(int keySize)
+ {
+ byte[] val = new byte[4];
+
+ val[0] = (byte)(keySize >> 24);
+ val[1] = (byte)(keySize >> 16);
+ val[2] = (byte)(keySize >> 8);
+ val[3] = (byte)keySize;
+
+ return val;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Basic key agreement classes.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6Client.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6Client.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6Client.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6Client.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,93 @@
+package pdftk.org.bouncycastle.crypto.agreement.srp;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.Digest;
+
+/**
+ * Implements the client side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
+ * This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
+ * "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
+ */
+public class SRP6Client
+{
+ protected BigInteger N;
+ protected BigInteger g;
+
+ protected BigInteger a;
+ protected BigInteger A;
+
+ protected BigInteger B;
+
+ protected BigInteger x;
+ protected BigInteger u;
+ protected BigInteger S;
+
+ protected Digest digest;
+ protected SecureRandom random;
+
+ public SRP6Client()
+ {
+ }
+
+ /**
+ * Initialises the client to begin new authentication attempt
+ * @param N The safe prime associated with the client's verifier
+ * @param g The group parameter associated with the client's verifier
+ * @param digest The digest algorithm associated with the client's verifier
+ * @param random For key generation
+ */
+ public void init(BigInteger N, BigInteger g, Digest digest, SecureRandom random)
+ {
+ this.N = N;
+ this.g = g;
+ this.digest = digest;
+ this.random = random;
+ }
+
+ /**
+ * Generates client's credentials given the client's salt, identity and password
+ * @param salt The salt used in the client's verifier.
+ * @param identity The user's identity (eg. username)
+ * @param password The user's password
+ * @return Client's public value to send to server
+ */
+ public BigInteger generateClientCredentials(byte[] salt, byte[] identity, byte[] password)
+ {
+ this.x = SRP6Util.calculateX(digest, N, salt, identity, password);
+ this.a = selectPrivateValue();
+ this.A = g.modPow(a, N);
+
+ return A;
+ }
+
+ /**
+ * Generates client's verification message given the server's credentials
+ * @param serverB The server's credentials
+ * @return Client's verification message for the server
+ * @throws CryptoException If server's credentials are invalid
+ */
+ public BigInteger calculateSecret(BigInteger serverB) throws CryptoException
+ {
+ this.B = SRP6Util.validatePublicValue(N, serverB);
+ this.u = SRP6Util.calculateU(digest, N, A, B);
+ this.S = calculateS();
+
+ return S;
+ }
+
+ protected BigInteger selectPrivateValue()
+ {
+ return SRP6Util.generatePrivateValue(digest, N, g, random);
+ }
+
+ private BigInteger calculateS()
+ {
+ BigInteger k = SRP6Util.calculateK(digest, N, g);
+ BigInteger exp = u.multiply(x).add(a);
+ BigInteger tmp = g.modPow(x, N).multiply(k).mod(N);
+ return B.subtract(tmp).mod(N).modPow(exp, N);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6Server.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6Server.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6Server.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6Server.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,90 @@
+package pdftk.org.bouncycastle.crypto.agreement.srp;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.Digest;
+
+/**
+ * Implements the server side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
+ * This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
+ * "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
+ */
+public class SRP6Server
+{
+ protected BigInteger N;
+ protected BigInteger g;
+ protected BigInteger v;
+
+ protected SecureRandom random;
+ protected Digest digest;
+
+ protected BigInteger A;
+
+ protected BigInteger b;
+ protected BigInteger B;
+
+ protected BigInteger u;
+ protected BigInteger S;
+
+ public SRP6Server()
+ {
+ }
+
+ /**
+ * Initialises the server to accept a new client authentication attempt
+ * @param N The safe prime associated with the client's verifier
+ * @param g The group parameter associated with the client's verifier
+ * @param v The client's verifier
+ * @param digest The digest algorithm associated with the client's verifier
+ * @param random For key generation
+ */
+ public void init(BigInteger N, BigInteger g, BigInteger v, Digest digest, SecureRandom random)
+ {
+ this.N = N;
+ this.g = g;
+ this.v = v;
+
+ this.random = random;
+ this.digest = digest;
+ }
+
+ /**
+ * Generates the server's credentials that are to be sent to the client.
+ * @return The server's public value to the client
+ */
+ public BigInteger generateServerCredentials()
+ {
+ BigInteger k = SRP6Util.calculateK(digest, N, g);
+ this.b = selectPrivateValue();
+ this.B = k.multiply(v).mod(N).add(g.modPow(b, N)).mod(N);
+
+ return B;
+ }
+
+ /**
+ * Processes the client's credentials. If valid the shared secret is generated and returned.
+ * @param clientA The client's credentials
+ * @return A shared secret BigInteger
+ * @throws CryptoException If client's credentials are invalid
+ */
+ public BigInteger calculateSecret(BigInteger clientA) throws CryptoException
+ {
+ this.A = SRP6Util.validatePublicValue(N, clientA);
+ this.u = SRP6Util.calculateU(digest, N, A, B);
+ this.S = calculateS();
+
+ return S;
+ }
+
+ protected BigInteger selectPrivateValue()
+ {
+ return SRP6Util.generatePrivateValue(digest, N, g, random);
+ }
+
+ private BigInteger calculateS()
+ {
+ return v.modPow(u, N).multiply(A).mod(N).modPow(b, N);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6Util.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6Util.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6Util.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6Util.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,91 @@
+package pdftk.org.bouncycastle.crypto.agreement.srp;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+public class SRP6Util
+{
+ private static BigInteger ZERO = BigInteger.valueOf(0);
+ private static BigInteger ONE = BigInteger.valueOf(1);
+
+ public static BigInteger calculateK(Digest digest, BigInteger N, BigInteger g)
+ {
+ return hashPaddedPair(digest, N, N, g);
+ }
+
+ public static BigInteger calculateU(Digest digest, BigInteger N, BigInteger A, BigInteger B)
+ {
+ return hashPaddedPair(digest, N, A, B);
+ }
+
+ public static BigInteger calculateX(Digest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password)
+ {
+ byte[] output = new byte[digest.getDigestSize()];
+
+ digest.update(identity, 0, identity.length);
+ digest.update((byte)':');
+ digest.update(password, 0, password.length);
+ digest.doFinal(output, 0);
+
+ digest.update(salt, 0, salt.length);
+ digest.update(output, 0, output.length);
+ digest.doFinal(output, 0);
+
+ return new BigInteger(1, output);
+ }
+
+ public static BigInteger generatePrivateValue(Digest digest, BigInteger N, BigInteger g, SecureRandom random)
+ {
+ int minBits = Math.min(256, N.bitLength() / 2);
+ BigInteger min = ONE.shiftLeft(minBits - 1);
+ BigInteger max = N.subtract(ONE);
+
+ return BigIntegers.createRandomInRange(min, max, random);
+ }
+
+ public static BigInteger validatePublicValue(BigInteger N, BigInteger val)
+ throws CryptoException
+ {
+ val = val.mod(N);
+
+ // Check that val % N != 0
+ if (val.equals(ZERO))
+ {
+ throw new CryptoException("Invalid public value: 0");
+ }
+
+ return val;
+ }
+
+ private static BigInteger hashPaddedPair(Digest digest, BigInteger N, BigInteger n1, BigInteger n2)
+ {
+ int padLength = (N.bitLength() + 7) / 8;
+
+ byte[] n1_bytes = getPadded(n1, padLength);
+ byte[] n2_bytes = getPadded(n2, padLength);
+
+ digest.update(n1_bytes, 0, n1_bytes.length);
+ digest.update(n2_bytes, 0, n2_bytes.length);
+
+ byte[] output = new byte[digest.getDigestSize()];
+ digest.doFinal(output, 0);
+
+ return new BigInteger(1, output);
+ }
+
+ private static byte[] getPadded(BigInteger n, int length)
+ {
+ byte[] bs = BigIntegers.asUnsignedByteArray(n);
+ if (bs.length < length)
+ {
+ byte[] tmp = new byte[length];
+ System.arraycopy(bs, 0, tmp, length - bs.length, bs.length);
+ bs = tmp;
+ }
+ return bs;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6VerifierGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6VerifierGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6VerifierGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/agreement/srp/SRP6VerifierGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,47 @@
+package pdftk.org.bouncycastle.crypto.agreement.srp;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.Digest;
+
+/**
+ * Generates new SRP verifier for user
+ */
+public class SRP6VerifierGenerator
+{
+ protected BigInteger N;
+ protected BigInteger g;
+ protected Digest digest;
+
+ public SRP6VerifierGenerator()
+ {
+ }
+
+ /**
+ * Initialises generator to create new verifiers
+ * @param N The safe prime to use (see DHParametersGenerator)
+ * @param g The group parameter to use (see DHParametersGenerator)
+ * @param digest The digest to use. The same digest type will need to be used later for the actual authentication
+ * attempt. Also note that the final session key size is dependent on the chosen digest.
+ */
+ public void init(BigInteger N, BigInteger g, Digest digest)
+ {
+ this.N = N;
+ this.g = g;
+ this.digest = digest;
+ }
+
+ /**
+ * Creates a new SRP verifier
+ * @param salt The salt to use, generally should be large and random
+ * @param identity The user's identifying information (eg. username)
+ * @param password The user's password
+ * @return A new verifier for use in future SRP authentication
+ */
+ public BigInteger generateVerifier(byte[] salt, byte[] identity, byte[] password)
+ {
+ BigInteger x = SRP6Util.calculateX(digest, N, salt, identity, password);
+
+ return g.modPow(x, N);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/GOST3411Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/GOST3411Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/GOST3411Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/GOST3411Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,349 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.ExtendedDigest;
+import pdftk.org.bouncycastle.crypto.engines.GOST28147Engine;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithSBox;
+import pdftk.org.bouncycastle.crypto.util.Pack;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * implementation of GOST R 34.11-94
+ */
+public class GOST3411Digest
+ implements ExtendedDigest
+{
+ private static final int DIGEST_LENGTH = 32;
+
+ private byte[] H = new byte[32], L = new byte[32],
+ M = new byte[32], Sum = new byte[32];
+ private byte[][] C = new byte[4][32];
+
+ private byte[] xBuf = new byte[32];
+ private int xBufOff;
+ private long byteCount;
+
+ private BlockCipher cipher = new GOST28147Engine();
+ private byte[] sBox;
+
+ /**
+ * Standard constructor
+ */
+ public GOST3411Digest()
+ {
+ sBox = GOST28147Engine.getSBox("D-A");
+ cipher.init(true, new ParametersWithSBox(null, sBox));
+
+ reset();
+ }
+
+ /**
+ * Constructor to allow use of a particular sbox with GOST28147
+ * @see GOST28147Engine#getSBox(String)
+ */
+ public GOST3411Digest(byte[] sBoxParam)
+ {
+ sBox = Arrays.clone(sBoxParam);
+ cipher.init(true, new ParametersWithSBox(null, sBox));
+
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public GOST3411Digest(GOST3411Digest t)
+ {
+ this.sBox = t.sBox;
+ cipher.init(true, new ParametersWithSBox(null, sBox));
+
+ reset();
+
+ System.arraycopy(t.H, 0, this.H, 0, t.H.length);
+ System.arraycopy(t.L, 0, this.L, 0, t.L.length);
+ System.arraycopy(t.M, 0, this.M, 0, t.M.length);
+ System.arraycopy(t.Sum, 0, this.Sum, 0, t.Sum.length);
+ System.arraycopy(t.C[1], 0, this.C[1], 0, t.C[1].length);
+ System.arraycopy(t.C[2], 0, this.C[2], 0, t.C[2].length);
+ System.arraycopy(t.C[3], 0, this.C[3], 0, t.C[3].length);
+ System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length);
+
+ this.xBufOff = t.xBufOff;
+ this.byteCount = t.byteCount;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "GOST3411";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ public void update(byte in)
+ {
+ xBuf[xBufOff++] = in;
+ if (xBufOff == xBuf.length)
+ {
+ sumByteArray(xBuf); // calc sum M
+ processBlock(xBuf, 0);
+ xBufOff = 0;
+ }
+ byteCount++;
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ while ((xBufOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+ inOff++;
+ len--;
+ }
+
+ while (len > xBuf.length)
+ {
+ System.arraycopy(in, inOff, xBuf, 0, xBuf.length);
+
+ sumByteArray(xBuf); // calc sum M
+ processBlock(xBuf, 0);
+ inOff += xBuf.length;
+ len -= xBuf.length;
+ byteCount += xBuf.length;
+ }
+
+ // load in the remainder.
+ while (len > 0)
+ {
+ update(in[inOff]);
+ inOff++;
+ len--;
+ }
+ }
+
+ // (i + 1 + 4(k - 1)) = 8i + k i = 0-3, k = 1-8
+ private byte[] K = new byte[32];
+
+ private byte[] P(byte[] in)
+ {
+ for(int k = 0; k < 8; k++)
+ {
+ K[4*k] = in[k];
+ K[1 + 4*k] = in[ 8 + k];
+ K[2 + 4*k] = in[16 + k];
+ K[3 + 4*k] = in[24 + k];
+ }
+
+ return K;
+ }
+
+ //A (x) = (x0 ^ x1) || x3 || x2 || x1
+ byte[] a = new byte[8];
+ private byte[] A(byte[] in)
+ {
+ for(int j=0; j<8; j++)
+ {
+ a[j]=(byte)(in[j] ^ in[j+8]);
+ }
+
+ System.arraycopy(in, 8, in, 0, 24);
+ System.arraycopy(a, 0, in, 24, 8);
+
+ return in;
+ }
+
+ //Encrypt function, ECB mode
+ private void E(byte[] key, byte[] s, int sOff, byte[] in, int inOff)
+ {
+ cipher.init(true, new KeyParameter(key));
+
+ cipher.processBlock(in, inOff, s, sOff);
+ }
+
+ // (in:) n16||..||n1 ==> (out:) n1^n2^n3^n4^n13^n16||n16||..||n2
+ short[] wS = new short[16], w_S = new short[16];
+
+ private void fw(byte[] in)
+ {
+ cpyBytesToShort(in, wS);
+ w_S[15] = (short)(wS[0] ^ wS[1] ^ wS[2] ^ wS[3] ^ wS[12] ^ wS[15]);
+ System.arraycopy(wS, 1, w_S, 0, 15);
+ cpyShortToBytes(w_S, in);
+ }
+
+ // block processing
+ byte[] S = new byte[32];
+ byte[] U = new byte[32], V = new byte[32], W = new byte[32];
+
+ protected void processBlock(byte[] in, int inOff)
+ {
+ System.arraycopy(in, inOff, M, 0, 32);
+
+ //key step 1
+
+ // H = h3 || h2 || h1 || h0
+ // S = s3 || s2 || s1 || s0
+ System.arraycopy(H, 0, U, 0, 32);
+ System.arraycopy(M, 0, V, 0, 32);
+ for (int j=0; j<32; j++)
+ {
+ W[j] = (byte)(U[j]^V[j]);
+ }
+ // Encrypt gost28147-ECB
+ E(P(W), S, 0, H, 0); // s0 = EK0 [h0]
+
+ //keys step 2,3,4
+ for (int i=1; i<4; i++)
+ {
+ byte[] tmpA = A(U);
+ for (int j=0; j<32; j++)
+ {
+ U[j] = (byte)(tmpA[j] ^ C[i][j]);
+ }
+ V = A(A(V));
+ for (int j=0; j<32; j++)
+ {
+ W[j] = (byte)(U[j]^V[j]);
+ }
+ // Encrypt gost28147-ECB
+ E(P(W), S, i * 8, H, i * 8); // si = EKi [hi]
+ }
+
+ // x(M, H) = y61(H^y(M^y12(S)))
+ for(int n = 0; n < 12; n++)
+ {
+ fw(S);
+ }
+ for(int n = 0; n < 32; n++)
+ {
+ S[n] = (byte)(S[n] ^ M[n]);
+ }
+
+ fw(S);
+
+ for(int n = 0; n < 32; n++)
+ {
+ S[n] = (byte)(H[n] ^ S[n]);
+ }
+ for(int n = 0; n < 61; n++)
+ {
+ fw(S);
+ }
+ System.arraycopy(S, 0, H, 0, H.length);
+ }
+
+ private void finish()
+ {
+ Pack.longToLittleEndian(byteCount * 8, L, 0); // get length into L (byteCount * 8 = bitCount)
+
+ while (xBufOff != 0)
+ {
+ update((byte)0);
+ }
+
+ processBlock(L, 0);
+ processBlock(Sum, 0);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ System.arraycopy(H, 0, out, outOff, H.length);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ private static final byte[] C2 = {
+ 0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,
+ (byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,
+ 0x00,(byte)0xFF,(byte)0xFF,0x00,(byte)0xFF,0x00,0x00,(byte)0xFF,
+ (byte)0xFF,0x00,0x00,0x00,(byte)0xFF,(byte)0xFF,0x00,(byte)0xFF};
+
+ public void reset()
+ {
+ byteCount = 0;
+ xBufOff = 0;
+
+ for(int i=0; i (Sum + a mod (2^256))
+ private void sumByteArray(byte[] in)
+ {
+ int carry = 0;
+
+ for (int i = 0; i != Sum.length; i++)
+ {
+ int sum = (Sum[i] & 0xff) + (in[i] & 0xff) + carry;
+
+ Sum[i] = (byte)sum;
+
+ carry = sum >>> 8;
+ }
+ }
+
+ private void cpyBytesToShort(byte[] S, short[] wS)
+ {
+ for(int i=0; i> 8);
+ S[i*2] = (byte)wS[i];
+ }
+ }
+
+ public int getByteLength()
+ {
+ return 32;
+ }
+}
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/GeneralDigest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/GeneralDigest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/GeneralDigest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/GeneralDigest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,135 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+import pdftk.org.bouncycastle.crypto.ExtendedDigest;
+
+/**
+ * base implementation of MD4 family style digest as outlined in
+ * "Handbook of Applied Cryptography", pages 344 - 347.
+ */
+public abstract class GeneralDigest
+ implements ExtendedDigest
+{
+ private static final int BYTE_LENGTH = 64;
+ private byte[] xBuf;
+ private int xBufOff;
+
+ private long byteCount;
+
+ /**
+ * Standard constructor
+ */
+ protected GeneralDigest()
+ {
+ xBuf = new byte[4];
+ xBufOff = 0;
+ }
+
+ /**
+ * Copy constructor. We are using copy constructors in place
+ * of the Object.clone() interface as this interface is not
+ * supported by J2ME.
+ */
+ protected GeneralDigest(GeneralDigest t)
+ {
+ xBuf = new byte[t.xBuf.length];
+ System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
+
+ xBufOff = t.xBufOff;
+ byteCount = t.byteCount;
+ }
+
+ public void update(
+ byte in)
+ {
+ xBuf[xBufOff++] = in;
+
+ if (xBufOff == xBuf.length)
+ {
+ processWord(xBuf, 0);
+ xBufOff = 0;
+ }
+
+ byteCount++;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ //
+ // fill the current word
+ //
+ while ((xBufOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (len > xBuf.length)
+ {
+ processWord(in, inOff);
+
+ inOff += xBuf.length;
+ len -= xBuf.length;
+ byteCount += xBuf.length;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (len > 0)
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+ }
+
+ public void finish()
+ {
+ long bitLength = (byteCount << 3);
+
+ //
+ // add the pad bytes.
+ //
+ update((byte)128);
+
+ while (xBufOff != 0)
+ {
+ update((byte)0);
+ }
+
+ processLength(bitLength);
+
+ processBlock();
+ }
+
+ public void reset()
+ {
+ byteCount = 0;
+
+ xBufOff = 0;
+ for (int i = 0; i < xBuf.length; i++)
+ {
+ xBuf[i] = 0;
+ }
+ }
+
+ public int getByteLength()
+ {
+ return BYTE_LENGTH;
+ }
+
+ protected abstract void processWord(byte[] in, int inOff);
+
+ protected abstract void processLength(long bitLength);
+
+ protected abstract void processBlock();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/LongDigest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/LongDigest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/LongDigest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/LongDigest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,354 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+import pdftk.org.bouncycastle.crypto.ExtendedDigest;
+import pdftk.org.bouncycastle.crypto.util.Pack;
+
+/**
+ * Base class for SHA-384 and SHA-512.
+ */
+public abstract class LongDigest
+ implements ExtendedDigest
+{
+ private static final int BYTE_LENGTH = 128;
+
+ private byte[] xBuf;
+ private int xBufOff;
+
+ private long byteCount1;
+ private long byteCount2;
+
+ protected long H1, H2, H3, H4, H5, H6, H7, H8;
+
+ private long[] W = new long[80];
+ private int wOff;
+
+ /**
+ * Constructor for variable length word
+ */
+ protected LongDigest()
+ {
+ xBuf = new byte[8];
+ xBufOff = 0;
+
+ reset();
+ }
+
+ /**
+ * Copy constructor. We are using copy constructors in place
+ * of the Object.clone() interface as this interface is not
+ * supported by J2ME.
+ */
+ protected LongDigest(LongDigest t)
+ {
+ xBuf = new byte[t.xBuf.length];
+ System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
+
+ xBufOff = t.xBufOff;
+ byteCount1 = t.byteCount1;
+ byteCount2 = t.byteCount2;
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+ H6 = t.H6;
+ H7 = t.H7;
+ H8 = t.H8;
+
+ System.arraycopy(t.W, 0, W, 0, t.W.length);
+ wOff = t.wOff;
+ }
+
+ public void update(
+ byte in)
+ {
+ xBuf[xBufOff++] = in;
+
+ if (xBufOff == xBuf.length)
+ {
+ processWord(xBuf, 0);
+ xBufOff = 0;
+ }
+
+ byteCount1++;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ //
+ // fill the current word
+ //
+ while ((xBufOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (len > xBuf.length)
+ {
+ processWord(in, inOff);
+
+ inOff += xBuf.length;
+ len -= xBuf.length;
+ byteCount1 += xBuf.length;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (len > 0)
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+ }
+
+ public void finish()
+ {
+ adjustByteCounts();
+
+ long lowBitLength = byteCount1 << 3;
+ long hiBitLength = byteCount2;
+
+ //
+ // add the pad bytes.
+ //
+ update((byte)128);
+
+ while (xBufOff != 0)
+ {
+ update((byte)0);
+ }
+
+ processLength(lowBitLength, hiBitLength);
+
+ processBlock();
+ }
+
+ public void reset()
+ {
+ byteCount1 = 0;
+ byteCount2 = 0;
+
+ xBufOff = 0;
+ for (int i = 0; i < xBuf.length; i++)
+ {
+ xBuf[i] = 0;
+ }
+
+ wOff = 0;
+ for (int i = 0; i != W.length; i++)
+ {
+ W[i] = 0;
+ }
+ }
+
+ public int getByteLength()
+ {
+ return BYTE_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ W[wOff] = Pack.bigEndianToLong(in, inOff);
+
+ if (++wOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ /**
+ * adjust the byte counts so that byteCount2 represents the
+ * upper long (less 3 bits) word of the byte count.
+ */
+ private void adjustByteCounts()
+ {
+ if (byteCount1 > 0x1fffffffffffffffL)
+ {
+ byteCount2 += (byteCount1 >>> 61);
+ byteCount1 &= 0x1fffffffffffffffL;
+ }
+ }
+
+ protected void processLength(
+ long lowW,
+ long hiW)
+ {
+ if (wOff > 14)
+ {
+ processBlock();
+ }
+
+ W[14] = hiW;
+ W[15] = lowW;
+ }
+
+ protected void processBlock()
+ {
+ adjustByteCounts();
+
+ //
+ // expand 16 word block into 80 word blocks.
+ //
+ for (int t = 16; t <= 79; t++)
+ {
+ W[t] = Sigma1(W[t - 2]) + W[t - 7] + Sigma0(W[t - 15]) + W[t - 16];
+ }
+
+ //
+ // set up working variables.
+ //
+ long a = H1;
+ long b = H2;
+ long c = H3;
+ long d = H4;
+ long e = H5;
+ long f = H6;
+ long g = H7;
+ long h = H8;
+
+ int t = 0;
+ for(int i = 0; i < 10; i ++)
+ {
+ // t = 8 * i
+ h += Sum1(e) + Ch(e, f, g) + K[t] + W[t++];
+ d += h;
+ h += Sum0(a) + Maj(a, b, c);
+
+ // t = 8 * i + 1
+ g += Sum1(d) + Ch(d, e, f) + K[t] + W[t++];
+ c += g;
+ g += Sum0(h) + Maj(h, a, b);
+
+ // t = 8 * i + 2
+ f += Sum1(c) + Ch(c, d, e) + K[t] + W[t++];
+ b += f;
+ f += Sum0(g) + Maj(g, h, a);
+
+ // t = 8 * i + 3
+ e += Sum1(b) + Ch(b, c, d) + K[t] + W[t++];
+ a += e;
+ e += Sum0(f) + Maj(f, g, h);
+
+ // t = 8 * i + 4
+ d += Sum1(a) + Ch(a, b, c) + K[t] + W[t++];
+ h += d;
+ d += Sum0(e) + Maj(e, f, g);
+
+ // t = 8 * i + 5
+ c += Sum1(h) + Ch(h, a, b) + K[t] + W[t++];
+ g += c;
+ c += Sum0(d) + Maj(d, e, f);
+
+ // t = 8 * i + 6
+ b += Sum1(g) + Ch(g, h, a) + K[t] + W[t++];
+ f += b;
+ b += Sum0(c) + Maj(c, d, e);
+
+ // t = 8 * i + 7
+ a += Sum1(f) + Ch(f, g, h) + K[t] + W[t++];
+ e += a;
+ a += Sum0(b) + Maj(b, c, d);
+ }
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+ H5 += e;
+ H6 += f;
+ H7 += g;
+ H8 += h;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ wOff = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ W[i] = 0;
+ }
+ }
+
+ /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
+ private long Ch(
+ long x,
+ long y,
+ long z)
+ {
+ return ((x & y) ^ ((~x) & z));
+ }
+
+ private long Maj(
+ long x,
+ long y,
+ long z)
+ {
+ return ((x & y) ^ (x & z) ^ (y & z));
+ }
+
+ private long Sum0(
+ long x)
+ {
+ return ((x << 36)|(x >>> 28)) ^ ((x << 30)|(x >>> 34)) ^ ((x << 25)|(x >>> 39));
+ }
+
+ private long Sum1(
+ long x)
+ {
+ return ((x << 50)|(x >>> 14)) ^ ((x << 46)|(x >>> 18)) ^ ((x << 23)|(x >>> 41));
+ }
+
+ private long Sigma0(
+ long x)
+ {
+ return ((x << 63)|(x >>> 1)) ^ ((x << 56)|(x >>> 8)) ^ (x >>> 7);
+ }
+
+ private long Sigma1(
+ long x)
+ {
+ return ((x << 45)|(x >>> 19)) ^ ((x << 3)|(x >>> 61)) ^ (x >>> 6);
+ }
+
+ /* SHA-384 and SHA-512 Constants
+ * (represent the first 64 bits of the fractional parts of the
+ * cube roots of the first sixty-four prime numbers)
+ */
+ static final long K[] = {
+0x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
+0x3956c25bf348b538L, 0x59f111f1b605d019L, 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
+0xd807aa98a3030242L, 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
+0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
+0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L, 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
+0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
+0x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
+0xc6e00bf33da88fc2L, 0xd5a79147930aa725L, 0x06ca6351e003826fL, 0x142929670a0e6e70L,
+0x27b70a8546d22ffcL, 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
+0x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L, 0x92722c851482353bL,
+0xa2bfe8a14cf10364L, 0xa81a664bbc423001L, 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
+0xd192e819d6ef5218L, 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
+0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
+0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL, 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
+0x748f82ee5defb2fcL, 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
+0x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
+0xca273eceea26619cL, 0xd186b8c721c0c207L, 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
+0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL,
+0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
+0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L
+ };
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/MD2Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/MD2Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/MD2Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/MD2Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,237 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+import pdftk.org.bouncycastle.crypto.*;
+/**
+ * implementation of MD2
+ * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
+ */
+public class MD2Digest
+ implements ExtendedDigest
+{
+ private static final int DIGEST_LENGTH = 16;
+
+ /* X buffer */
+ private byte[] X = new byte[48];
+ private int xOff;
+ /* M buffer */
+ private byte[] M = new byte[16];
+ private int mOff;
+ /* check sum */
+ private byte[] C = new byte[16];
+ private int COff;
+
+ public MD2Digest()
+ {
+ reset();
+ }
+ public MD2Digest(MD2Digest t)
+ {
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ System.arraycopy(t.M, 0, M, 0, t.M.length);
+ mOff = t.mOff;
+ System.arraycopy(t.C, 0, C, 0, t.C.length);
+ COff = t.COff;
+ }
+ /**
+ * return the algorithm name
+ *
+ * @return the algorithm name
+ */
+ public String getAlgorithmName()
+ {
+ return "MD2";
+ }
+ /**
+ * return the size, in bytes, of the digest produced by this message digest.
+ *
+ * @return the size, in bytes, of the digest produced by this message digest.
+ */
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+ /**
+ * close the digest, producing the final digest value. The doFinal
+ * call leaves the digest reset.
+ *
+ * @param out the array the digest is to be copied into.
+ * @param outOff the offset into the out array the digest is to start at.
+ */
+ public int doFinal(byte[] out, int outOff)
+ {
+ // add padding
+ byte paddingByte = (byte)(M.length-mOff);
+ for (int i=mOff;i 0))
+ {
+ update(in[inOff]);
+ inOff++;
+ len--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (len > 16)
+ {
+ System.arraycopy(in,inOff,M,0,16);
+ processCheckSum(M);
+ processBlock(M);
+ len -= 16;
+ inOff += 16;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (len > 0)
+ {
+ update(in[inOff]);
+ inOff++;
+ len--;
+ }
+ }
+ protected void processCheckSum(byte[] m)
+ {
+ int L = C[15];
+ for (int i=0;i<16;i++)
+ {
+ C[i] ^= S[(m[i] ^ L) & 0xff];
+ L = C[i];
+ }
+ }
+ protected void processBlock(byte[] m)
+ {
+ for (int i=0;i<16;i++)
+ {
+ X[i+16] = m[i];
+ X[i+32] = (byte)(m[i] ^ X[i]);
+ }
+ // encrypt block
+ int t = 0;
+
+ for (int j=0;j<18;j++)
+ {
+ for (int k=0;k<48;k++)
+ {
+ t = X[k] ^= S[t];
+ t = t & 0xff;
+ }
+ t = (t + j)%256;
+ }
+ }
+ // 256-byte random permutation constructed from the digits of PI
+ private static final byte[] S = {
+ (byte)41,(byte)46,(byte)67,(byte)201,(byte)162,(byte)216,(byte)124,
+ (byte)1,(byte)61,(byte)54,(byte)84,(byte)161,(byte)236,(byte)240,
+ (byte)6,(byte)19,(byte)98,(byte)167,(byte)5,(byte)243,(byte)192,
+ (byte)199,(byte)115,(byte)140,(byte)152,(byte)147,(byte)43,(byte)217,
+ (byte)188,(byte)76,(byte)130,(byte)202,(byte)30,(byte)155,(byte)87,
+ (byte)60,(byte)253,(byte)212,(byte)224,(byte)22,(byte)103,(byte)66,
+ (byte)111,(byte)24,(byte)138,(byte)23,(byte)229,(byte)18,(byte)190,
+ (byte)78,(byte)196,(byte)214,(byte)218,(byte)158,(byte)222,(byte)73,
+ (byte)160,(byte)251,(byte)245,(byte)142,(byte)187,(byte)47,(byte)238,
+ (byte)122,(byte)169,(byte)104,(byte)121,(byte)145,(byte)21,(byte)178,
+ (byte)7,(byte)63,(byte)148,(byte)194,(byte)16,(byte)137,(byte)11,
+ (byte)34,(byte)95,(byte)33,(byte)128,(byte)127,(byte)93,(byte)154,
+ (byte)90,(byte)144,(byte)50,(byte)39,(byte)53,(byte)62,(byte)204,
+ (byte)231,(byte)191,(byte)247,(byte)151,(byte)3,(byte)255,(byte)25,
+ (byte)48,(byte)179,(byte)72,(byte)165,(byte)181,(byte)209,(byte)215,
+ (byte)94,(byte)146,(byte)42,(byte)172,(byte)86,(byte)170,(byte)198,
+ (byte)79,(byte)184,(byte)56,(byte)210,(byte)150,(byte)164,(byte)125,
+ (byte)182,(byte)118,(byte)252,(byte)107,(byte)226,(byte)156,(byte)116,
+ (byte)4,(byte)241,(byte)69,(byte)157,(byte)112,(byte)89,(byte)100,
+ (byte)113,(byte)135,(byte)32,(byte)134,(byte)91,(byte)207,(byte)101,
+ (byte)230,(byte)45,(byte)168,(byte)2,(byte)27,(byte)96,(byte)37,
+ (byte)173,(byte)174,(byte)176,(byte)185,(byte)246,(byte)28,(byte)70,
+ (byte)97,(byte)105,(byte)52,(byte)64,(byte)126,(byte)15,(byte)85,
+ (byte)71,(byte)163,(byte)35,(byte)221,(byte)81,(byte)175,(byte)58,
+ (byte)195,(byte)92,(byte)249,(byte)206,(byte)186,(byte)197,(byte)234,
+ (byte)38,(byte)44,(byte)83,(byte)13,(byte)110,(byte)133,(byte)40,
+ (byte)132, 9,(byte)211,(byte)223,(byte)205,(byte)244,(byte)65,
+ (byte)129,(byte)77,(byte)82,(byte)106,(byte)220,(byte)55,(byte)200,
+ (byte)108,(byte)193,(byte)171,(byte)250,(byte)36,(byte)225,(byte)123,
+ (byte)8,(byte)12,(byte)189,(byte)177,(byte)74,(byte)120,(byte)136,
+ (byte)149,(byte)139,(byte)227,(byte)99,(byte)232,(byte)109,(byte)233,
+ (byte)203,(byte)213,(byte)254,(byte)59,(byte)0,(byte)29,(byte)57,
+ (byte)242,(byte)239,(byte)183,(byte)14,(byte)102,(byte)88,(byte)208,
+ (byte)228,(byte)166,(byte)119,(byte)114,(byte)248,(byte)235,(byte)117,
+ (byte)75,(byte)10,(byte)49,(byte)68,(byte)80,(byte)180,(byte)143,
+ (byte)237,(byte)31,(byte)26,(byte)219,(byte)153,(byte)141,(byte)51,
+ (byte)159,(byte)17,(byte)131,(byte)20
+ };
+
+ public int getByteLength()
+ {
+ return 16;
+ }
+}
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/MD4Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/MD4Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/MD4Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/MD4Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,270 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+
+/**
+ * implementation of MD4 as RFC 1320 by R. Rivest, MIT Laboratory for
+ * Computer Science and RSA Data Security, Inc.
+ *
+ * NOTE : This algorithm is only included for backwards compatability
+ * with legacy applications, it's not secure, don't use it for anything new!
+ */
+public class MD4Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 16;
+
+ private int H1, H2, H3, H4; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public MD4Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public MD4Digest(MD4Digest t)
+ {
+ super(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "MD4";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H1, out, outOff);
+ unpackWord(H2, out, outOff + 4);
+ unpackWord(H3, out, outOff + 8);
+ unpackWord(H4, out, outOff + 12);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H1 = 0x67452301;
+ H2 = 0xefcdab89;
+ H3 = 0x98badcfe;
+ H4 = 0x10325476;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ //
+ // round 1 left rotates
+ //
+ private static final int S11 = 3;
+ private static final int S12 = 7;
+ private static final int S13 = 11;
+ private static final int S14 = 19;
+
+ //
+ // round 2 left rotates
+ //
+ private static final int S21 = 3;
+ private static final int S22 = 5;
+ private static final int S23 = 9;
+ private static final int S24 = 13;
+
+ //
+ // round 3 left rotates
+ //
+ private static final int S31 = 3;
+ private static final int S32 = 9;
+ private static final int S33 = 11;
+ private static final int S34 = 15;
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int rotateLeft(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * F, G, H and I are the basic MD4 functions.
+ */
+ private int F(
+ int u,
+ int v,
+ int w)
+ {
+ return (u & v) | (~u & w);
+ }
+
+ private int G(
+ int u,
+ int v,
+ int w)
+ {
+ return (u & v) | (u & w) | (v & w);
+ }
+
+ private int H(
+ int u,
+ int v,
+ int w)
+ {
+ return u ^ v ^ w;
+ }
+
+ protected void processBlock()
+ {
+ int a = H1;
+ int b = H2;
+ int c = H3;
+ int d = H4;
+
+ //
+ // Round 1 - F cycle, 16 times.
+ //
+ a = rotateLeft(a + F(b, c, d) + X[ 0], S11);
+ d = rotateLeft(d + F(a, b, c) + X[ 1], S12);
+ c = rotateLeft(c + F(d, a, b) + X[ 2], S13);
+ b = rotateLeft(b + F(c, d, a) + X[ 3], S14);
+ a = rotateLeft(a + F(b, c, d) + X[ 4], S11);
+ d = rotateLeft(d + F(a, b, c) + X[ 5], S12);
+ c = rotateLeft(c + F(d, a, b) + X[ 6], S13);
+ b = rotateLeft(b + F(c, d, a) + X[ 7], S14);
+ a = rotateLeft(a + F(b, c, d) + X[ 8], S11);
+ d = rotateLeft(d + F(a, b, c) + X[ 9], S12);
+ c = rotateLeft(c + F(d, a, b) + X[10], S13);
+ b = rotateLeft(b + F(c, d, a) + X[11], S14);
+ a = rotateLeft(a + F(b, c, d) + X[12], S11);
+ d = rotateLeft(d + F(a, b, c) + X[13], S12);
+ c = rotateLeft(c + F(d, a, b) + X[14], S13);
+ b = rotateLeft(b + F(c, d, a) + X[15], S14);
+
+ //
+ // Round 2 - G cycle, 16 times.
+ //
+ a = rotateLeft(a + G(b, c, d) + X[ 0] + 0x5a827999, S21);
+ d = rotateLeft(d + G(a, b, c) + X[ 4] + 0x5a827999, S22);
+ c = rotateLeft(c + G(d, a, b) + X[ 8] + 0x5a827999, S23);
+ b = rotateLeft(b + G(c, d, a) + X[12] + 0x5a827999, S24);
+ a = rotateLeft(a + G(b, c, d) + X[ 1] + 0x5a827999, S21);
+ d = rotateLeft(d + G(a, b, c) + X[ 5] + 0x5a827999, S22);
+ c = rotateLeft(c + G(d, a, b) + X[ 9] + 0x5a827999, S23);
+ b = rotateLeft(b + G(c, d, a) + X[13] + 0x5a827999, S24);
+ a = rotateLeft(a + G(b, c, d) + X[ 2] + 0x5a827999, S21);
+ d = rotateLeft(d + G(a, b, c) + X[ 6] + 0x5a827999, S22);
+ c = rotateLeft(c + G(d, a, b) + X[10] + 0x5a827999, S23);
+ b = rotateLeft(b + G(c, d, a) + X[14] + 0x5a827999, S24);
+ a = rotateLeft(a + G(b, c, d) + X[ 3] + 0x5a827999, S21);
+ d = rotateLeft(d + G(a, b, c) + X[ 7] + 0x5a827999, S22);
+ c = rotateLeft(c + G(d, a, b) + X[11] + 0x5a827999, S23);
+ b = rotateLeft(b + G(c, d, a) + X[15] + 0x5a827999, S24);
+
+ //
+ // Round 3 - H cycle, 16 times.
+ //
+ a = rotateLeft(a + H(b, c, d) + X[ 0] + 0x6ed9eba1, S31);
+ d = rotateLeft(d + H(a, b, c) + X[ 8] + 0x6ed9eba1, S32);
+ c = rotateLeft(c + H(d, a, b) + X[ 4] + 0x6ed9eba1, S33);
+ b = rotateLeft(b + H(c, d, a) + X[12] + 0x6ed9eba1, S34);
+ a = rotateLeft(a + H(b, c, d) + X[ 2] + 0x6ed9eba1, S31);
+ d = rotateLeft(d + H(a, b, c) + X[10] + 0x6ed9eba1, S32);
+ c = rotateLeft(c + H(d, a, b) + X[ 6] + 0x6ed9eba1, S33);
+ b = rotateLeft(b + H(c, d, a) + X[14] + 0x6ed9eba1, S34);
+ a = rotateLeft(a + H(b, c, d) + X[ 1] + 0x6ed9eba1, S31);
+ d = rotateLeft(d + H(a, b, c) + X[ 9] + 0x6ed9eba1, S32);
+ c = rotateLeft(c + H(d, a, b) + X[ 5] + 0x6ed9eba1, S33);
+ b = rotateLeft(b + H(c, d, a) + X[13] + 0x6ed9eba1, S34);
+ a = rotateLeft(a + H(b, c, d) + X[ 3] + 0x6ed9eba1, S31);
+ d = rotateLeft(d + H(a, b, c) + X[11] + 0x6ed9eba1, S32);
+ c = rotateLeft(c + H(d, a, b) + X[ 7] + 0x6ed9eba1, S33);
+ b = rotateLeft(b + H(c, d, a) + X[15] + 0x6ed9eba1, S34);
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/MD5Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/MD5Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/MD5Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/MD5Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,302 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+
+/**
+ * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
+ */
+public class MD5Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 16;
+
+ private int H1, H2, H3, H4; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public MD5Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public MD5Digest(MD5Digest t)
+ {
+ super(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "MD5";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H1, out, outOff);
+ unpackWord(H2, out, outOff + 4);
+ unpackWord(H3, out, outOff + 8);
+ unpackWord(H4, out, outOff + 12);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H1 = 0x67452301;
+ H2 = 0xefcdab89;
+ H3 = 0x98badcfe;
+ H4 = 0x10325476;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ //
+ // round 1 left rotates
+ //
+ private static final int S11 = 7;
+ private static final int S12 = 12;
+ private static final int S13 = 17;
+ private static final int S14 = 22;
+
+ //
+ // round 2 left rotates
+ //
+ private static final int S21 = 5;
+ private static final int S22 = 9;
+ private static final int S23 = 14;
+ private static final int S24 = 20;
+
+ //
+ // round 3 left rotates
+ //
+ private static final int S31 = 4;
+ private static final int S32 = 11;
+ private static final int S33 = 16;
+ private static final int S34 = 23;
+
+ //
+ // round 4 left rotates
+ //
+ private static final int S41 = 6;
+ private static final int S42 = 10;
+ private static final int S43 = 15;
+ private static final int S44 = 21;
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int rotateLeft(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * F, G, H and I are the basic MD5 functions.
+ */
+ private int F(
+ int u,
+ int v,
+ int w)
+ {
+ return (u & v) | (~u & w);
+ }
+
+ private int G(
+ int u,
+ int v,
+ int w)
+ {
+ return (u & w) | (v & ~w);
+ }
+
+ private int H(
+ int u,
+ int v,
+ int w)
+ {
+ return u ^ v ^ w;
+ }
+
+ private int K(
+ int u,
+ int v,
+ int w)
+ {
+ return v ^ (u | ~w);
+ }
+
+ protected void processBlock()
+ {
+ int a = H1;
+ int b = H2;
+ int c = H3;
+ int d = H4;
+
+ //
+ // Round 1 - F cycle, 16 times.
+ //
+ a = rotateLeft(a + F(b, c, d) + X[ 0] + 0xd76aa478, S11) + b;
+ d = rotateLeft(d + F(a, b, c) + X[ 1] + 0xe8c7b756, S12) + a;
+ c = rotateLeft(c + F(d, a, b) + X[ 2] + 0x242070db, S13) + d;
+ b = rotateLeft(b + F(c, d, a) + X[ 3] + 0xc1bdceee, S14) + c;
+ a = rotateLeft(a + F(b, c, d) + X[ 4] + 0xf57c0faf, S11) + b;
+ d = rotateLeft(d + F(a, b, c) + X[ 5] + 0x4787c62a, S12) + a;
+ c = rotateLeft(c + F(d, a, b) + X[ 6] + 0xa8304613, S13) + d;
+ b = rotateLeft(b + F(c, d, a) + X[ 7] + 0xfd469501, S14) + c;
+ a = rotateLeft(a + F(b, c, d) + X[ 8] + 0x698098d8, S11) + b;
+ d = rotateLeft(d + F(a, b, c) + X[ 9] + 0x8b44f7af, S12) + a;
+ c = rotateLeft(c + F(d, a, b) + X[10] + 0xffff5bb1, S13) + d;
+ b = rotateLeft(b + F(c, d, a) + X[11] + 0x895cd7be, S14) + c;
+ a = rotateLeft(a + F(b, c, d) + X[12] + 0x6b901122, S11) + b;
+ d = rotateLeft(d + F(a, b, c) + X[13] + 0xfd987193, S12) + a;
+ c = rotateLeft(c + F(d, a, b) + X[14] + 0xa679438e, S13) + d;
+ b = rotateLeft(b + F(c, d, a) + X[15] + 0x49b40821, S14) + c;
+
+ //
+ // Round 2 - G cycle, 16 times.
+ //
+ a = rotateLeft(a + G(b, c, d) + X[ 1] + 0xf61e2562, S21) + b;
+ d = rotateLeft(d + G(a, b, c) + X[ 6] + 0xc040b340, S22) + a;
+ c = rotateLeft(c + G(d, a, b) + X[11] + 0x265e5a51, S23) + d;
+ b = rotateLeft(b + G(c, d, a) + X[ 0] + 0xe9b6c7aa, S24) + c;
+ a = rotateLeft(a + G(b, c, d) + X[ 5] + 0xd62f105d, S21) + b;
+ d = rotateLeft(d + G(a, b, c) + X[10] + 0x02441453, S22) + a;
+ c = rotateLeft(c + G(d, a, b) + X[15] + 0xd8a1e681, S23) + d;
+ b = rotateLeft(b + G(c, d, a) + X[ 4] + 0xe7d3fbc8, S24) + c;
+ a = rotateLeft(a + G(b, c, d) + X[ 9] + 0x21e1cde6, S21) + b;
+ d = rotateLeft(d + G(a, b, c) + X[14] + 0xc33707d6, S22) + a;
+ c = rotateLeft(c + G(d, a, b) + X[ 3] + 0xf4d50d87, S23) + d;
+ b = rotateLeft(b + G(c, d, a) + X[ 8] + 0x455a14ed, S24) + c;
+ a = rotateLeft(a + G(b, c, d) + X[13] + 0xa9e3e905, S21) + b;
+ d = rotateLeft(d + G(a, b, c) + X[ 2] + 0xfcefa3f8, S22) + a;
+ c = rotateLeft(c + G(d, a, b) + X[ 7] + 0x676f02d9, S23) + d;
+ b = rotateLeft(b + G(c, d, a) + X[12] + 0x8d2a4c8a, S24) + c;
+
+ //
+ // Round 3 - H cycle, 16 times.
+ //
+ a = rotateLeft(a + H(b, c, d) + X[ 5] + 0xfffa3942, S31) + b;
+ d = rotateLeft(d + H(a, b, c) + X[ 8] + 0x8771f681, S32) + a;
+ c = rotateLeft(c + H(d, a, b) + X[11] + 0x6d9d6122, S33) + d;
+ b = rotateLeft(b + H(c, d, a) + X[14] + 0xfde5380c, S34) + c;
+ a = rotateLeft(a + H(b, c, d) + X[ 1] + 0xa4beea44, S31) + b;
+ d = rotateLeft(d + H(a, b, c) + X[ 4] + 0x4bdecfa9, S32) + a;
+ c = rotateLeft(c + H(d, a, b) + X[ 7] + 0xf6bb4b60, S33) + d;
+ b = rotateLeft(b + H(c, d, a) + X[10] + 0xbebfbc70, S34) + c;
+ a = rotateLeft(a + H(b, c, d) + X[13] + 0x289b7ec6, S31) + b;
+ d = rotateLeft(d + H(a, b, c) + X[ 0] + 0xeaa127fa, S32) + a;
+ c = rotateLeft(c + H(d, a, b) + X[ 3] + 0xd4ef3085, S33) + d;
+ b = rotateLeft(b + H(c, d, a) + X[ 6] + 0x04881d05, S34) + c;
+ a = rotateLeft(a + H(b, c, d) + X[ 9] + 0xd9d4d039, S31) + b;
+ d = rotateLeft(d + H(a, b, c) + X[12] + 0xe6db99e5, S32) + a;
+ c = rotateLeft(c + H(d, a, b) + X[15] + 0x1fa27cf8, S33) + d;
+ b = rotateLeft(b + H(c, d, a) + X[ 2] + 0xc4ac5665, S34) + c;
+
+ //
+ // Round 4 - K cycle, 16 times.
+ //
+ a = rotateLeft(a + K(b, c, d) + X[ 0] + 0xf4292244, S41) + b;
+ d = rotateLeft(d + K(a, b, c) + X[ 7] + 0x432aff97, S42) + a;
+ c = rotateLeft(c + K(d, a, b) + X[14] + 0xab9423a7, S43) + d;
+ b = rotateLeft(b + K(c, d, a) + X[ 5] + 0xfc93a039, S44) + c;
+ a = rotateLeft(a + K(b, c, d) + X[12] + 0x655b59c3, S41) + b;
+ d = rotateLeft(d + K(a, b, c) + X[ 3] + 0x8f0ccc92, S42) + a;
+ c = rotateLeft(c + K(d, a, b) + X[10] + 0xffeff47d, S43) + d;
+ b = rotateLeft(b + K(c, d, a) + X[ 1] + 0x85845dd1, S44) + c;
+ a = rotateLeft(a + K(b, c, d) + X[ 8] + 0x6fa87e4f, S41) + b;
+ d = rotateLeft(d + K(a, b, c) + X[15] + 0xfe2ce6e0, S42) + a;
+ c = rotateLeft(c + K(d, a, b) + X[ 6] + 0xa3014314, S43) + d;
+ b = rotateLeft(b + K(c, d, a) + X[13] + 0x4e0811a1, S44) + c;
+ a = rotateLeft(a + K(b, c, d) + X[ 4] + 0xf7537e82, S41) + b;
+ d = rotateLeft(d + K(a, b, c) + X[11] + 0xbd3af235, S42) + a;
+ c = rotateLeft(c + K(d, a, b) + X[ 2] + 0x2ad7d2bb, S43) + d;
+ b = rotateLeft(b + K(c, d, a) + X[ 9] + 0xeb86d391, S44) + c;
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/NullDigest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/NullDigest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/NullDigest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/NullDigest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+import java.io.ByteArrayOutputStream;
+
+import pdftk.org.bouncycastle.crypto.Digest;
+
+
+public class NullDigest
+ implements Digest
+{
+ private ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ public String getAlgorithmName()
+ {
+ return "NULL";
+ }
+
+ public int getDigestSize()
+ {
+ return bOut.size();
+ }
+
+ public void update(byte in)
+ {
+ bOut.write(in);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ bOut.write(in, inOff, len);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ byte[] res = bOut.toByteArray();
+
+ System.arraycopy(res, 0, out, outOff, res.length);
+
+ reset();
+
+ return res.length;
+ }
+
+ public void reset()
+ {
+ bOut.reset();
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD128Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD128Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD128Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD128Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,461 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+
+/**
+ * implementation of RIPEMD128
+ */
+public class RIPEMD128Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 16;
+
+ private int H0, H1, H2, H3; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public RIPEMD128Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public RIPEMD128Digest(RIPEMD128Digest t)
+ {
+ super(t);
+
+ H0 = t.H0;
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RIPEMD128";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H0, out, outOff);
+ unpackWord(H1, out, outOff + 4);
+ unpackWord(H2, out, outOff + 8);
+ unpackWord(H3, out, outOff + 12);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H0 = 0x67452301;
+ H1 = 0xefcdab89;
+ H2 = 0x98badcfe;
+ H3 = 0x10325476;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int RL(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * f1,f2,f3,f4 are the basic RIPEMD128 functions.
+ */
+
+ /*
+ * F
+ */
+ private int f1(
+ int x,
+ int y,
+ int z)
+ {
+ return x ^ y ^ z;
+ }
+
+ /*
+ * G
+ */
+ private int f2(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) | (~x & z);
+ }
+
+ /*
+ * H
+ */
+ private int f3(
+ int x,
+ int y,
+ int z)
+ {
+ return (x | ~y) ^ z;
+ }
+
+ /*
+ * I
+ */
+ private int f4(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & z) | (y & ~z);
+ }
+
+ private int F1(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f1(b, c, d) + x, s);
+ }
+
+ private int F2(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f2(b, c, d) + x + 0x5a827999, s);
+ }
+
+ private int F3(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f3(b, c, d) + x + 0x6ed9eba1, s);
+ }
+
+ private int F4(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f4(b, c, d) + x + 0x8f1bbcdc, s);
+ }
+
+ private int FF1(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f1(b, c, d) + x, s);
+ }
+
+ private int FF2(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f2(b, c, d) + x + 0x6d703ef3, s);
+ }
+
+ private int FF3(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f3(b, c, d) + x + 0x5c4dd124, s);
+ }
+
+ private int FF4(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f4(b, c, d) + x + 0x50a28be6, s);
+ }
+
+ protected void processBlock()
+ {
+ int a, aa;
+ int b, bb;
+ int c, cc;
+ int d, dd;
+
+ a = aa = H0;
+ b = bb = H1;
+ c = cc = H2;
+ d = dd = H3;
+
+ //
+ // Round 1
+ //
+ a = F1(a, b, c, d, X[ 0], 11);
+ d = F1(d, a, b, c, X[ 1], 14);
+ c = F1(c, d, a, b, X[ 2], 15);
+ b = F1(b, c, d, a, X[ 3], 12);
+ a = F1(a, b, c, d, X[ 4], 5);
+ d = F1(d, a, b, c, X[ 5], 8);
+ c = F1(c, d, a, b, X[ 6], 7);
+ b = F1(b, c, d, a, X[ 7], 9);
+ a = F1(a, b, c, d, X[ 8], 11);
+ d = F1(d, a, b, c, X[ 9], 13);
+ c = F1(c, d, a, b, X[10], 14);
+ b = F1(b, c, d, a, X[11], 15);
+ a = F1(a, b, c, d, X[12], 6);
+ d = F1(d, a, b, c, X[13], 7);
+ c = F1(c, d, a, b, X[14], 9);
+ b = F1(b, c, d, a, X[15], 8);
+
+ //
+ // Round 2
+ //
+ a = F2(a, b, c, d, X[ 7], 7);
+ d = F2(d, a, b, c, X[ 4], 6);
+ c = F2(c, d, a, b, X[13], 8);
+ b = F2(b, c, d, a, X[ 1], 13);
+ a = F2(a, b, c, d, X[10], 11);
+ d = F2(d, a, b, c, X[ 6], 9);
+ c = F2(c, d, a, b, X[15], 7);
+ b = F2(b, c, d, a, X[ 3], 15);
+ a = F2(a, b, c, d, X[12], 7);
+ d = F2(d, a, b, c, X[ 0], 12);
+ c = F2(c, d, a, b, X[ 9], 15);
+ b = F2(b, c, d, a, X[ 5], 9);
+ a = F2(a, b, c, d, X[ 2], 11);
+ d = F2(d, a, b, c, X[14], 7);
+ c = F2(c, d, a, b, X[11], 13);
+ b = F2(b, c, d, a, X[ 8], 12);
+
+ //
+ // Round 3
+ //
+ a = F3(a, b, c, d, X[ 3], 11);
+ d = F3(d, a, b, c, X[10], 13);
+ c = F3(c, d, a, b, X[14], 6);
+ b = F3(b, c, d, a, X[ 4], 7);
+ a = F3(a, b, c, d, X[ 9], 14);
+ d = F3(d, a, b, c, X[15], 9);
+ c = F3(c, d, a, b, X[ 8], 13);
+ b = F3(b, c, d, a, X[ 1], 15);
+ a = F3(a, b, c, d, X[ 2], 14);
+ d = F3(d, a, b, c, X[ 7], 8);
+ c = F3(c, d, a, b, X[ 0], 13);
+ b = F3(b, c, d, a, X[ 6], 6);
+ a = F3(a, b, c, d, X[13], 5);
+ d = F3(d, a, b, c, X[11], 12);
+ c = F3(c, d, a, b, X[ 5], 7);
+ b = F3(b, c, d, a, X[12], 5);
+
+ //
+ // Round 4
+ //
+ a = F4(a, b, c, d, X[ 1], 11);
+ d = F4(d, a, b, c, X[ 9], 12);
+ c = F4(c, d, a, b, X[11], 14);
+ b = F4(b, c, d, a, X[10], 15);
+ a = F4(a, b, c, d, X[ 0], 14);
+ d = F4(d, a, b, c, X[ 8], 15);
+ c = F4(c, d, a, b, X[12], 9);
+ b = F4(b, c, d, a, X[ 4], 8);
+ a = F4(a, b, c, d, X[13], 9);
+ d = F4(d, a, b, c, X[ 3], 14);
+ c = F4(c, d, a, b, X[ 7], 5);
+ b = F4(b, c, d, a, X[15], 6);
+ a = F4(a, b, c, d, X[14], 8);
+ d = F4(d, a, b, c, X[ 5], 6);
+ c = F4(c, d, a, b, X[ 6], 5);
+ b = F4(b, c, d, a, X[ 2], 12);
+
+ //
+ // Parallel round 1
+ //
+ aa = FF4(aa, bb, cc, dd, X[ 5], 8);
+ dd = FF4(dd, aa, bb, cc, X[14], 9);
+ cc = FF4(cc, dd, aa, bb, X[ 7], 9);
+ bb = FF4(bb, cc, dd, aa, X[ 0], 11);
+ aa = FF4(aa, bb, cc, dd, X[ 9], 13);
+ dd = FF4(dd, aa, bb, cc, X[ 2], 15);
+ cc = FF4(cc, dd, aa, bb, X[11], 15);
+ bb = FF4(bb, cc, dd, aa, X[ 4], 5);
+ aa = FF4(aa, bb, cc, dd, X[13], 7);
+ dd = FF4(dd, aa, bb, cc, X[ 6], 7);
+ cc = FF4(cc, dd, aa, bb, X[15], 8);
+ bb = FF4(bb, cc, dd, aa, X[ 8], 11);
+ aa = FF4(aa, bb, cc, dd, X[ 1], 14);
+ dd = FF4(dd, aa, bb, cc, X[10], 14);
+ cc = FF4(cc, dd, aa, bb, X[ 3], 12);
+ bb = FF4(bb, cc, dd, aa, X[12], 6);
+
+ //
+ // Parallel round 2
+ //
+ aa = FF3(aa, bb, cc, dd, X[ 6], 9);
+ dd = FF3(dd, aa, bb, cc, X[11], 13);
+ cc = FF3(cc, dd, aa, bb, X[ 3], 15);
+ bb = FF3(bb, cc, dd, aa, X[ 7], 7);
+ aa = FF3(aa, bb, cc, dd, X[ 0], 12);
+ dd = FF3(dd, aa, bb, cc, X[13], 8);
+ cc = FF3(cc, dd, aa, bb, X[ 5], 9);
+ bb = FF3(bb, cc, dd, aa, X[10], 11);
+ aa = FF3(aa, bb, cc, dd, X[14], 7);
+ dd = FF3(dd, aa, bb, cc, X[15], 7);
+ cc = FF3(cc, dd, aa, bb, X[ 8], 12);
+ bb = FF3(bb, cc, dd, aa, X[12], 7);
+ aa = FF3(aa, bb, cc, dd, X[ 4], 6);
+ dd = FF3(dd, aa, bb, cc, X[ 9], 15);
+ cc = FF3(cc, dd, aa, bb, X[ 1], 13);
+ bb = FF3(bb, cc, dd, aa, X[ 2], 11);
+
+ //
+ // Parallel round 3
+ //
+ aa = FF2(aa, bb, cc, dd, X[15], 9);
+ dd = FF2(dd, aa, bb, cc, X[ 5], 7);
+ cc = FF2(cc, dd, aa, bb, X[ 1], 15);
+ bb = FF2(bb, cc, dd, aa, X[ 3], 11);
+ aa = FF2(aa, bb, cc, dd, X[ 7], 8);
+ dd = FF2(dd, aa, bb, cc, X[14], 6);
+ cc = FF2(cc, dd, aa, bb, X[ 6], 6);
+ bb = FF2(bb, cc, dd, aa, X[ 9], 14);
+ aa = FF2(aa, bb, cc, dd, X[11], 12);
+ dd = FF2(dd, aa, bb, cc, X[ 8], 13);
+ cc = FF2(cc, dd, aa, bb, X[12], 5);
+ bb = FF2(bb, cc, dd, aa, X[ 2], 14);
+ aa = FF2(aa, bb, cc, dd, X[10], 13);
+ dd = FF2(dd, aa, bb, cc, X[ 0], 13);
+ cc = FF2(cc, dd, aa, bb, X[ 4], 7);
+ bb = FF2(bb, cc, dd, aa, X[13], 5);
+
+ //
+ // Parallel round 4
+ //
+ aa = FF1(aa, bb, cc, dd, X[ 8], 15);
+ dd = FF1(dd, aa, bb, cc, X[ 6], 5);
+ cc = FF1(cc, dd, aa, bb, X[ 4], 8);
+ bb = FF1(bb, cc, dd, aa, X[ 1], 11);
+ aa = FF1(aa, bb, cc, dd, X[ 3], 14);
+ dd = FF1(dd, aa, bb, cc, X[11], 14);
+ cc = FF1(cc, dd, aa, bb, X[15], 6);
+ bb = FF1(bb, cc, dd, aa, X[ 0], 14);
+ aa = FF1(aa, bb, cc, dd, X[ 5], 6);
+ dd = FF1(dd, aa, bb, cc, X[12], 9);
+ cc = FF1(cc, dd, aa, bb, X[ 2], 12);
+ bb = FF1(bb, cc, dd, aa, X[13], 9);
+ aa = FF1(aa, bb, cc, dd, X[ 9], 12);
+ dd = FF1(dd, aa, bb, cc, X[ 7], 5);
+ cc = FF1(cc, dd, aa, bb, X[10], 15);
+ bb = FF1(bb, cc, dd, aa, X[14], 8);
+
+ dd += c + H1; // final result for H0
+
+ //
+ // combine the results
+ //
+ H1 = H2 + d + aa;
+ H2 = H3 + a + bb;
+ H3 = H0 + b + cc;
+ H0 = dd;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD160Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD160Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD160Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD160Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,422 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+
+/**
+ * implementation of RIPEMD see,
+ * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html
+ */
+public class RIPEMD160Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 20;
+
+ private int H0, H1, H2, H3, H4; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public RIPEMD160Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public RIPEMD160Digest(RIPEMD160Digest t)
+ {
+ super(t);
+
+ H0 = t.H0;
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RIPEMD160";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H0, out, outOff);
+ unpackWord(H1, out, outOff + 4);
+ unpackWord(H2, out, outOff + 8);
+ unpackWord(H3, out, outOff + 12);
+ unpackWord(H4, out, outOff + 16);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H0 = 0x67452301;
+ H1 = 0xefcdab89;
+ H2 = 0x98badcfe;
+ H3 = 0x10325476;
+ H4 = 0xc3d2e1f0;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int RL(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * f1,f2,f3,f4,f5 are the basic RIPEMD160 functions.
+ */
+
+ /*
+ * rounds 0-15
+ */
+ private int f1(
+ int x,
+ int y,
+ int z)
+ {
+ return x ^ y ^ z;
+ }
+
+ /*
+ * rounds 16-31
+ */
+ private int f2(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) | (~x & z);
+ }
+
+ /*
+ * rounds 32-47
+ */
+ private int f3(
+ int x,
+ int y,
+ int z)
+ {
+ return (x | ~y) ^ z;
+ }
+
+ /*
+ * rounds 48-63
+ */
+ private int f4(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & z) | (y & ~z);
+ }
+
+ /*
+ * rounds 64-79
+ */
+ private int f5(
+ int x,
+ int y,
+ int z)
+ {
+ return x ^ (y | ~z);
+ }
+
+ protected void processBlock()
+ {
+ int a, aa;
+ int b, bb;
+ int c, cc;
+ int d, dd;
+ int e, ee;
+
+ a = aa = H0;
+ b = bb = H1;
+ c = cc = H2;
+ d = dd = H3;
+ e = ee = H4;
+
+ //
+ // Rounds 1 - 16
+ //
+ // left
+ a = RL(a + f1(b,c,d) + X[ 0], 11) + e; c = RL(c, 10);
+ e = RL(e + f1(a,b,c) + X[ 1], 14) + d; b = RL(b, 10);
+ d = RL(d + f1(e,a,b) + X[ 2], 15) + c; a = RL(a, 10);
+ c = RL(c + f1(d,e,a) + X[ 3], 12) + b; e = RL(e, 10);
+ b = RL(b + f1(c,d,e) + X[ 4], 5) + a; d = RL(d, 10);
+ a = RL(a + f1(b,c,d) + X[ 5], 8) + e; c = RL(c, 10);
+ e = RL(e + f1(a,b,c) + X[ 6], 7) + d; b = RL(b, 10);
+ d = RL(d + f1(e,a,b) + X[ 7], 9) + c; a = RL(a, 10);
+ c = RL(c + f1(d,e,a) + X[ 8], 11) + b; e = RL(e, 10);
+ b = RL(b + f1(c,d,e) + X[ 9], 13) + a; d = RL(d, 10);
+ a = RL(a + f1(b,c,d) + X[10], 14) + e; c = RL(c, 10);
+ e = RL(e + f1(a,b,c) + X[11], 15) + d; b = RL(b, 10);
+ d = RL(d + f1(e,a,b) + X[12], 6) + c; a = RL(a, 10);
+ c = RL(c + f1(d,e,a) + X[13], 7) + b; e = RL(e, 10);
+ b = RL(b + f1(c,d,e) + X[14], 9) + a; d = RL(d, 10);
+ a = RL(a + f1(b,c,d) + X[15], 8) + e; c = RL(c, 10);
+
+ // right
+ aa = RL(aa + f5(bb,cc,dd) + X[ 5] + 0x50a28be6, 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f5(aa,bb,cc) + X[14] + 0x50a28be6, 9) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f5(ee,aa,bb) + X[ 7] + 0x50a28be6, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f5(dd,ee,aa) + X[ 0] + 0x50a28be6, 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f5(cc,dd,ee) + X[ 9] + 0x50a28be6, 13) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f5(bb,cc,dd) + X[ 2] + 0x50a28be6, 15) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f5(aa,bb,cc) + X[11] + 0x50a28be6, 15) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f5(ee,aa,bb) + X[ 4] + 0x50a28be6, 5) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f5(dd,ee,aa) + X[13] + 0x50a28be6, 7) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f5(cc,dd,ee) + X[ 6] + 0x50a28be6, 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f5(bb,cc,dd) + X[15] + 0x50a28be6, 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f5(aa,bb,cc) + X[ 8] + 0x50a28be6, 11) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f5(ee,aa,bb) + X[ 1] + 0x50a28be6, 14) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f5(dd,ee,aa) + X[10] + 0x50a28be6, 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f5(cc,dd,ee) + X[ 3] + 0x50a28be6, 12) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f5(bb,cc,dd) + X[12] + 0x50a28be6, 6) + ee; cc = RL(cc, 10);
+
+ //
+ // Rounds 16-31
+ //
+ // left
+ e = RL(e + f2(a,b,c) + X[ 7] + 0x5a827999, 7) + d; b = RL(b, 10);
+ d = RL(d + f2(e,a,b) + X[ 4] + 0x5a827999, 6) + c; a = RL(a, 10);
+ c = RL(c + f2(d,e,a) + X[13] + 0x5a827999, 8) + b; e = RL(e, 10);
+ b = RL(b + f2(c,d,e) + X[ 1] + 0x5a827999, 13) + a; d = RL(d, 10);
+ a = RL(a + f2(b,c,d) + X[10] + 0x5a827999, 11) + e; c = RL(c, 10);
+ e = RL(e + f2(a,b,c) + X[ 6] + 0x5a827999, 9) + d; b = RL(b, 10);
+ d = RL(d + f2(e,a,b) + X[15] + 0x5a827999, 7) + c; a = RL(a, 10);
+ c = RL(c + f2(d,e,a) + X[ 3] + 0x5a827999, 15) + b; e = RL(e, 10);
+ b = RL(b + f2(c,d,e) + X[12] + 0x5a827999, 7) + a; d = RL(d, 10);
+ a = RL(a + f2(b,c,d) + X[ 0] + 0x5a827999, 12) + e; c = RL(c, 10);
+ e = RL(e + f2(a,b,c) + X[ 9] + 0x5a827999, 15) + d; b = RL(b, 10);
+ d = RL(d + f2(e,a,b) + X[ 5] + 0x5a827999, 9) + c; a = RL(a, 10);
+ c = RL(c + f2(d,e,a) + X[ 2] + 0x5a827999, 11) + b; e = RL(e, 10);
+ b = RL(b + f2(c,d,e) + X[14] + 0x5a827999, 7) + a; d = RL(d, 10);
+ a = RL(a + f2(b,c,d) + X[11] + 0x5a827999, 13) + e; c = RL(c, 10);
+ e = RL(e + f2(a,b,c) + X[ 8] + 0x5a827999, 12) + d; b = RL(b, 10);
+
+ // right
+ ee = RL(ee + f4(aa,bb,cc) + X[ 6] + 0x5c4dd124, 9) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f4(ee,aa,bb) + X[11] + 0x5c4dd124, 13) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f4(dd,ee,aa) + X[ 3] + 0x5c4dd124, 15) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f4(cc,dd,ee) + X[ 7] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f4(bb,cc,dd) + X[ 0] + 0x5c4dd124, 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f4(aa,bb,cc) + X[13] + 0x5c4dd124, 8) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f4(ee,aa,bb) + X[ 5] + 0x5c4dd124, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f4(dd,ee,aa) + X[10] + 0x5c4dd124, 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f4(cc,dd,ee) + X[14] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f4(bb,cc,dd) + X[15] + 0x5c4dd124, 7) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f4(aa,bb,cc) + X[ 8] + 0x5c4dd124, 12) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f4(ee,aa,bb) + X[12] + 0x5c4dd124, 7) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f4(dd,ee,aa) + X[ 4] + 0x5c4dd124, 6) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f4(cc,dd,ee) + X[ 9] + 0x5c4dd124, 15) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f4(bb,cc,dd) + X[ 1] + 0x5c4dd124, 13) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f4(aa,bb,cc) + X[ 2] + 0x5c4dd124, 11) + dd; bb = RL(bb, 10);
+
+ //
+ // Rounds 32-47
+ //
+ // left
+ d = RL(d + f3(e,a,b) + X[ 3] + 0x6ed9eba1, 11) + c; a = RL(a, 10);
+ c = RL(c + f3(d,e,a) + X[10] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
+ b = RL(b + f3(c,d,e) + X[14] + 0x6ed9eba1, 6) + a; d = RL(d, 10);
+ a = RL(a + f3(b,c,d) + X[ 4] + 0x6ed9eba1, 7) + e; c = RL(c, 10);
+ e = RL(e + f3(a,b,c) + X[ 9] + 0x6ed9eba1, 14) + d; b = RL(b, 10);
+ d = RL(d + f3(e,a,b) + X[15] + 0x6ed9eba1, 9) + c; a = RL(a, 10);
+ c = RL(c + f3(d,e,a) + X[ 8] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
+ b = RL(b + f3(c,d,e) + X[ 1] + 0x6ed9eba1, 15) + a; d = RL(d, 10);
+ a = RL(a + f3(b,c,d) + X[ 2] + 0x6ed9eba1, 14) + e; c = RL(c, 10);
+ e = RL(e + f3(a,b,c) + X[ 7] + 0x6ed9eba1, 8) + d; b = RL(b, 10);
+ d = RL(d + f3(e,a,b) + X[ 0] + 0x6ed9eba1, 13) + c; a = RL(a, 10);
+ c = RL(c + f3(d,e,a) + X[ 6] + 0x6ed9eba1, 6) + b; e = RL(e, 10);
+ b = RL(b + f3(c,d,e) + X[13] + 0x6ed9eba1, 5) + a; d = RL(d, 10);
+ a = RL(a + f3(b,c,d) + X[11] + 0x6ed9eba1, 12) + e; c = RL(c, 10);
+ e = RL(e + f3(a,b,c) + X[ 5] + 0x6ed9eba1, 7) + d; b = RL(b, 10);
+ d = RL(d + f3(e,a,b) + X[12] + 0x6ed9eba1, 5) + c; a = RL(a, 10);
+
+ // right
+ dd = RL(dd + f3(ee,aa,bb) + X[15] + 0x6d703ef3, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f3(dd,ee,aa) + X[ 5] + 0x6d703ef3, 7) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f3(cc,dd,ee) + X[ 1] + 0x6d703ef3, 15) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f3(bb,cc,dd) + X[ 3] + 0x6d703ef3, 11) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f3(aa,bb,cc) + X[ 7] + 0x6d703ef3, 8) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f3(ee,aa,bb) + X[14] + 0x6d703ef3, 6) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f3(dd,ee,aa) + X[ 6] + 0x6d703ef3, 6) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f3(cc,dd,ee) + X[ 9] + 0x6d703ef3, 14) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f3(bb,cc,dd) + X[11] + 0x6d703ef3, 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f3(aa,bb,cc) + X[ 8] + 0x6d703ef3, 13) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f3(ee,aa,bb) + X[12] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f3(dd,ee,aa) + X[ 2] + 0x6d703ef3, 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f3(cc,dd,ee) + X[10] + 0x6d703ef3, 13) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f3(bb,cc,dd) + X[ 0] + 0x6d703ef3, 13) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f3(aa,bb,cc) + X[ 4] + 0x6d703ef3, 7) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f3(ee,aa,bb) + X[13] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10);
+
+ //
+ // Rounds 48-63
+ //
+ // left
+ c = RL(c + f4(d,e,a) + X[ 1] + 0x8f1bbcdc, 11) + b; e = RL(e, 10);
+ b = RL(b + f4(c,d,e) + X[ 9] + 0x8f1bbcdc, 12) + a; d = RL(d, 10);
+ a = RL(a + f4(b,c,d) + X[11] + 0x8f1bbcdc, 14) + e; c = RL(c, 10);
+ e = RL(e + f4(a,b,c) + X[10] + 0x8f1bbcdc, 15) + d; b = RL(b, 10);
+ d = RL(d + f4(e,a,b) + X[ 0] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
+ c = RL(c + f4(d,e,a) + X[ 8] + 0x8f1bbcdc, 15) + b; e = RL(e, 10);
+ b = RL(b + f4(c,d,e) + X[12] + 0x8f1bbcdc, 9) + a; d = RL(d, 10);
+ a = RL(a + f4(b,c,d) + X[ 4] + 0x8f1bbcdc, 8) + e; c = RL(c, 10);
+ e = RL(e + f4(a,b,c) + X[13] + 0x8f1bbcdc, 9) + d; b = RL(b, 10);
+ d = RL(d + f4(e,a,b) + X[ 3] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
+ c = RL(c + f4(d,e,a) + X[ 7] + 0x8f1bbcdc, 5) + b; e = RL(e, 10);
+ b = RL(b + f4(c,d,e) + X[15] + 0x8f1bbcdc, 6) + a; d = RL(d, 10);
+ a = RL(a + f4(b,c,d) + X[14] + 0x8f1bbcdc, 8) + e; c = RL(c, 10);
+ e = RL(e + f4(a,b,c) + X[ 5] + 0x8f1bbcdc, 6) + d; b = RL(b, 10);
+ d = RL(d + f4(e,a,b) + X[ 6] + 0x8f1bbcdc, 5) + c; a = RL(a, 10);
+ c = RL(c + f4(d,e,a) + X[ 2] + 0x8f1bbcdc, 12) + b; e = RL(e, 10);
+
+ // right
+ cc = RL(cc + f2(dd,ee,aa) + X[ 8] + 0x7a6d76e9, 15) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f2(cc,dd,ee) + X[ 6] + 0x7a6d76e9, 5) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f2(bb,cc,dd) + X[ 4] + 0x7a6d76e9, 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f2(aa,bb,cc) + X[ 1] + 0x7a6d76e9, 11) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f2(ee,aa,bb) + X[ 3] + 0x7a6d76e9, 14) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f2(dd,ee,aa) + X[11] + 0x7a6d76e9, 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f2(cc,dd,ee) + X[15] + 0x7a6d76e9, 6) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f2(bb,cc,dd) + X[ 0] + 0x7a6d76e9, 14) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f2(aa,bb,cc) + X[ 5] + 0x7a6d76e9, 6) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f2(ee,aa,bb) + X[12] + 0x7a6d76e9, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f2(dd,ee,aa) + X[ 2] + 0x7a6d76e9, 12) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f2(cc,dd,ee) + X[13] + 0x7a6d76e9, 9) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f2(bb,cc,dd) + X[ 9] + 0x7a6d76e9, 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f2(aa,bb,cc) + X[ 7] + 0x7a6d76e9, 5) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f2(ee,aa,bb) + X[10] + 0x7a6d76e9, 15) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f2(dd,ee,aa) + X[14] + 0x7a6d76e9, 8) + bb; ee = RL(ee, 10);
+
+ //
+ // Rounds 64-79
+ //
+ // left
+ b = RL(b + f5(c,d,e) + X[ 4] + 0xa953fd4e, 9) + a; d = RL(d, 10);
+ a = RL(a + f5(b,c,d) + X[ 0] + 0xa953fd4e, 15) + e; c = RL(c, 10);
+ e = RL(e + f5(a,b,c) + X[ 5] + 0xa953fd4e, 5) + d; b = RL(b, 10);
+ d = RL(d + f5(e,a,b) + X[ 9] + 0xa953fd4e, 11) + c; a = RL(a, 10);
+ c = RL(c + f5(d,e,a) + X[ 7] + 0xa953fd4e, 6) + b; e = RL(e, 10);
+ b = RL(b + f5(c,d,e) + X[12] + 0xa953fd4e, 8) + a; d = RL(d, 10);
+ a = RL(a + f5(b,c,d) + X[ 2] + 0xa953fd4e, 13) + e; c = RL(c, 10);
+ e = RL(e + f5(a,b,c) + X[10] + 0xa953fd4e, 12) + d; b = RL(b, 10);
+ d = RL(d + f5(e,a,b) + X[14] + 0xa953fd4e, 5) + c; a = RL(a, 10);
+ c = RL(c + f5(d,e,a) + X[ 1] + 0xa953fd4e, 12) + b; e = RL(e, 10);
+ b = RL(b + f5(c,d,e) + X[ 3] + 0xa953fd4e, 13) + a; d = RL(d, 10);
+ a = RL(a + f5(b,c,d) + X[ 8] + 0xa953fd4e, 14) + e; c = RL(c, 10);
+ e = RL(e + f5(a,b,c) + X[11] + 0xa953fd4e, 11) + d; b = RL(b, 10);
+ d = RL(d + f5(e,a,b) + X[ 6] + 0xa953fd4e, 8) + c; a = RL(a, 10);
+ c = RL(c + f5(d,e,a) + X[15] + 0xa953fd4e, 5) + b; e = RL(e, 10);
+ b = RL(b + f5(c,d,e) + X[13] + 0xa953fd4e, 6) + a; d = RL(d, 10);
+
+ // right
+ bb = RL(bb + f1(cc,dd,ee) + X[12], 8) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f1(bb,cc,dd) + X[15], 5) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f1(aa,bb,cc) + X[10], 12) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f1(ee,aa,bb) + X[ 4], 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f1(dd,ee,aa) + X[ 1], 12) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f1(cc,dd,ee) + X[ 5], 5) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f1(bb,cc,dd) + X[ 8], 14) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f1(aa,bb,cc) + X[ 7], 6) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f1(ee,aa,bb) + X[ 6], 8) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f1(dd,ee,aa) + X[ 2], 13) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f1(cc,dd,ee) + X[13], 6) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f1(bb,cc,dd) + X[14], 5) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f1(aa,bb,cc) + X[ 0], 15) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f1(ee,aa,bb) + X[ 3], 13) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f1(dd,ee,aa) + X[ 9], 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f1(cc,dd,ee) + X[11], 11) + aa; dd = RL(dd, 10);
+
+ dd += c + H1;
+ H1 = H2 + d + ee;
+ H2 = H3 + e + aa;
+ H3 = H4 + a + bb;
+ H4 = H0 + b + cc;
+ H0 = dd;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD256Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD256Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD256Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD256Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,476 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+
+/**
+ * implementation of RIPEMD256.
+ *
+ * note: this algorithm offers the same level of security as RIPEMD128.
+ */
+public class RIPEMD256Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 32;
+
+ private int H0, H1, H2, H3, H4, H5, H6, H7; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public RIPEMD256Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public RIPEMD256Digest(RIPEMD256Digest t)
+ {
+ super(t);
+
+ H0 = t.H0;
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+ H6 = t.H6;
+ H7 = t.H7;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RIPEMD256";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H0, out, outOff);
+ unpackWord(H1, out, outOff + 4);
+ unpackWord(H2, out, outOff + 8);
+ unpackWord(H3, out, outOff + 12);
+ unpackWord(H4, out, outOff + 16);
+ unpackWord(H5, out, outOff + 20);
+ unpackWord(H6, out, outOff + 24);
+ unpackWord(H7, out, outOff + 28);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H0 = 0x67452301;
+ H1 = 0xefcdab89;
+ H2 = 0x98badcfe;
+ H3 = 0x10325476;
+ H4 = 0x76543210;
+ H5 = 0xFEDCBA98;
+ H6 = 0x89ABCDEF;
+ H7 = 0x01234567;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int RL(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * f1,f2,f3,f4 are the basic RIPEMD128 functions.
+ */
+
+ /*
+ * F
+ */
+ private int f1(
+ int x,
+ int y,
+ int z)
+ {
+ return x ^ y ^ z;
+ }
+
+ /*
+ * G
+ */
+ private int f2(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) | (~x & z);
+ }
+
+ /*
+ * H
+ */
+ private int f3(
+ int x,
+ int y,
+ int z)
+ {
+ return (x | ~y) ^ z;
+ }
+
+ /*
+ * I
+ */
+ private int f4(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & z) | (y & ~z);
+ }
+
+ private int F1(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f1(b, c, d) + x, s);
+ }
+
+ private int F2(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f2(b, c, d) + x + 0x5a827999, s);
+ }
+
+ private int F3(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f3(b, c, d) + x + 0x6ed9eba1, s);
+ }
+
+ private int F4(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f4(b, c, d) + x + 0x8f1bbcdc, s);
+ }
+
+ private int FF1(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f1(b, c, d) + x, s);
+ }
+
+ private int FF2(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f2(b, c, d) + x + 0x6d703ef3, s);
+ }
+
+ private int FF3(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f3(b, c, d) + x + 0x5c4dd124, s);
+ }
+
+ private int FF4(
+ int a,
+ int b,
+ int c,
+ int d,
+ int x,
+ int s)
+ {
+ return RL(a + f4(b, c, d) + x + 0x50a28be6, s);
+ }
+
+ protected void processBlock()
+ {
+ int a, aa;
+ int b, bb;
+ int c, cc;
+ int d, dd;
+ int t;
+
+ a = H0;
+ b = H1;
+ c = H2;
+ d = H3;
+ aa = H4;
+ bb = H5;
+ cc = H6;
+ dd = H7;
+
+ //
+ // Round 1
+ //
+
+ a = F1(a, b, c, d, X[ 0], 11);
+ d = F1(d, a, b, c, X[ 1], 14);
+ c = F1(c, d, a, b, X[ 2], 15);
+ b = F1(b, c, d, a, X[ 3], 12);
+ a = F1(a, b, c, d, X[ 4], 5);
+ d = F1(d, a, b, c, X[ 5], 8);
+ c = F1(c, d, a, b, X[ 6], 7);
+ b = F1(b, c, d, a, X[ 7], 9);
+ a = F1(a, b, c, d, X[ 8], 11);
+ d = F1(d, a, b, c, X[ 9], 13);
+ c = F1(c, d, a, b, X[10], 14);
+ b = F1(b, c, d, a, X[11], 15);
+ a = F1(a, b, c, d, X[12], 6);
+ d = F1(d, a, b, c, X[13], 7);
+ c = F1(c, d, a, b, X[14], 9);
+ b = F1(b, c, d, a, X[15], 8);
+
+ aa = FF4(aa, bb, cc, dd, X[ 5], 8);
+ dd = FF4(dd, aa, bb, cc, X[14], 9);
+ cc = FF4(cc, dd, aa, bb, X[ 7], 9);
+ bb = FF4(bb, cc, dd, aa, X[ 0], 11);
+ aa = FF4(aa, bb, cc, dd, X[ 9], 13);
+ dd = FF4(dd, aa, bb, cc, X[ 2], 15);
+ cc = FF4(cc, dd, aa, bb, X[11], 15);
+ bb = FF4(bb, cc, dd, aa, X[ 4], 5);
+ aa = FF4(aa, bb, cc, dd, X[13], 7);
+ dd = FF4(dd, aa, bb, cc, X[ 6], 7);
+ cc = FF4(cc, dd, aa, bb, X[15], 8);
+ bb = FF4(bb, cc, dd, aa, X[ 8], 11);
+ aa = FF4(aa, bb, cc, dd, X[ 1], 14);
+ dd = FF4(dd, aa, bb, cc, X[10], 14);
+ cc = FF4(cc, dd, aa, bb, X[ 3], 12);
+ bb = FF4(bb, cc, dd, aa, X[12], 6);
+
+ t = a; a = aa; aa = t;
+
+ //
+ // Round 2
+ //
+ a = F2(a, b, c, d, X[ 7], 7);
+ d = F2(d, a, b, c, X[ 4], 6);
+ c = F2(c, d, a, b, X[13], 8);
+ b = F2(b, c, d, a, X[ 1], 13);
+ a = F2(a, b, c, d, X[10], 11);
+ d = F2(d, a, b, c, X[ 6], 9);
+ c = F2(c, d, a, b, X[15], 7);
+ b = F2(b, c, d, a, X[ 3], 15);
+ a = F2(a, b, c, d, X[12], 7);
+ d = F2(d, a, b, c, X[ 0], 12);
+ c = F2(c, d, a, b, X[ 9], 15);
+ b = F2(b, c, d, a, X[ 5], 9);
+ a = F2(a, b, c, d, X[ 2], 11);
+ d = F2(d, a, b, c, X[14], 7);
+ c = F2(c, d, a, b, X[11], 13);
+ b = F2(b, c, d, a, X[ 8], 12);
+
+ aa = FF3(aa, bb, cc, dd, X[ 6], 9);
+ dd = FF3(dd, aa, bb, cc, X[ 11], 13);
+ cc = FF3(cc, dd, aa, bb, X[3], 15);
+ bb = FF3(bb, cc, dd, aa, X[ 7], 7);
+ aa = FF3(aa, bb, cc, dd, X[0], 12);
+ dd = FF3(dd, aa, bb, cc, X[13], 8);
+ cc = FF3(cc, dd, aa, bb, X[5], 9);
+ bb = FF3(bb, cc, dd, aa, X[10], 11);
+ aa = FF3(aa, bb, cc, dd, X[14], 7);
+ dd = FF3(dd, aa, bb, cc, X[15], 7);
+ cc = FF3(cc, dd, aa, bb, X[ 8], 12);
+ bb = FF3(bb, cc, dd, aa, X[12], 7);
+ aa = FF3(aa, bb, cc, dd, X[ 4], 6);
+ dd = FF3(dd, aa, bb, cc, X[ 9], 15);
+ cc = FF3(cc, dd, aa, bb, X[ 1], 13);
+ bb = FF3(bb, cc, dd, aa, X[ 2], 11);
+
+ t = b; b = bb; bb = t;
+
+ //
+ // Round 3
+ //
+ a = F3(a, b, c, d, X[ 3], 11);
+ d = F3(d, a, b, c, X[10], 13);
+ c = F3(c, d, a, b, X[14], 6);
+ b = F3(b, c, d, a, X[ 4], 7);
+ a = F3(a, b, c, d, X[ 9], 14);
+ d = F3(d, a, b, c, X[15], 9);
+ c = F3(c, d, a, b, X[ 8], 13);
+ b = F3(b, c, d, a, X[ 1], 15);
+ a = F3(a, b, c, d, X[ 2], 14);
+ d = F3(d, a, b, c, X[ 7], 8);
+ c = F3(c, d, a, b, X[ 0], 13);
+ b = F3(b, c, d, a, X[ 6], 6);
+ a = F3(a, b, c, d, X[13], 5);
+ d = F3(d, a, b, c, X[11], 12);
+ c = F3(c, d, a, b, X[ 5], 7);
+ b = F3(b, c, d, a, X[12], 5);
+
+ aa = FF2(aa, bb, cc, dd, X[ 15], 9);
+ dd = FF2(dd, aa, bb, cc, X[5], 7);
+ cc = FF2(cc, dd, aa, bb, X[1], 15);
+ bb = FF2(bb, cc, dd, aa, X[ 3], 11);
+ aa = FF2(aa, bb, cc, dd, X[ 7], 8);
+ dd = FF2(dd, aa, bb, cc, X[14], 6);
+ cc = FF2(cc, dd, aa, bb, X[ 6], 6);
+ bb = FF2(bb, cc, dd, aa, X[ 9], 14);
+ aa = FF2(aa, bb, cc, dd, X[11], 12);
+ dd = FF2(dd, aa, bb, cc, X[ 8], 13);
+ cc = FF2(cc, dd, aa, bb, X[12], 5);
+ bb = FF2(bb, cc, dd, aa, X[ 2], 14);
+ aa = FF2(aa, bb, cc, dd, X[10], 13);
+ dd = FF2(dd, aa, bb, cc, X[ 0], 13);
+ cc = FF2(cc, dd, aa, bb, X[ 4], 7);
+ bb = FF2(bb, cc, dd, aa, X[13], 5);
+
+ t = c; c = cc; cc = t;
+
+ //
+ // Round 4
+ //
+ a = F4(a, b, c, d, X[ 1], 11);
+ d = F4(d, a, b, c, X[ 9], 12);
+ c = F4(c, d, a, b, X[11], 14);
+ b = F4(b, c, d, a, X[10], 15);
+ a = F4(a, b, c, d, X[ 0], 14);
+ d = F4(d, a, b, c, X[ 8], 15);
+ c = F4(c, d, a, b, X[12], 9);
+ b = F4(b, c, d, a, X[ 4], 8);
+ a = F4(a, b, c, d, X[13], 9);
+ d = F4(d, a, b, c, X[ 3], 14);
+ c = F4(c, d, a, b, X[ 7], 5);
+ b = F4(b, c, d, a, X[15], 6);
+ a = F4(a, b, c, d, X[14], 8);
+ d = F4(d, a, b, c, X[ 5], 6);
+ c = F4(c, d, a, b, X[ 6], 5);
+ b = F4(b, c, d, a, X[ 2], 12);
+
+ aa = FF1(aa, bb, cc, dd, X[ 8], 15);
+ dd = FF1(dd, aa, bb, cc, X[ 6], 5);
+ cc = FF1(cc, dd, aa, bb, X[ 4], 8);
+ bb = FF1(bb, cc, dd, aa, X[ 1], 11);
+ aa = FF1(aa, bb, cc, dd, X[ 3], 14);
+ dd = FF1(dd, aa, bb, cc, X[11], 14);
+ cc = FF1(cc, dd, aa, bb, X[15], 6);
+ bb = FF1(bb, cc, dd, aa, X[ 0], 14);
+ aa = FF1(aa, bb, cc, dd, X[ 5], 6);
+ dd = FF1(dd, aa, bb, cc, X[12], 9);
+ cc = FF1(cc, dd, aa, bb, X[ 2], 12);
+ bb = FF1(bb, cc, dd, aa, X[13], 9);
+ aa = FF1(aa, bb, cc, dd, X[ 9], 12);
+ dd = FF1(dd, aa, bb, cc, X[ 7], 5);
+ cc = FF1(cc, dd, aa, bb, X[10], 15);
+ bb = FF1(bb, cc, dd, aa, X[14], 8);
+
+ t = d; d = dd; dd = t;
+
+ H0 += a;
+ H1 += b;
+ H2 += c;
+ H3 += d;
+ H4 += aa;
+ H5 += bb;
+ H6 += cc;
+ H7 += dd;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD320Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD320Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD320Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/RIPEMD320Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,461 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+
+/**
+ * implementation of RIPEMD 320.
+ *
+ * Note: this implementation offers the same level of security
+ * as RIPEMD 160.
+ */
+public class RIPEMD320Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 40;
+
+ private int H0, H1, H2, H3, H4, H5, H6, H7, H8, H9; // IV's
+
+ private int[] X = new int[16];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public RIPEMD320Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public RIPEMD320Digest(RIPEMD320Digest t)
+ {
+ super(t);
+
+ H0 = t.H0;
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+ H6 = t.H6;
+ H7 = t.H7;
+ H8 = t.H8;
+ H9 = t.H9;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RIPEMD320";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ X[xOff++] = (in[inOff] & 0xff) | ((in[inOff + 1] & 0xff) << 8)
+ | ((in[inOff + 2] & 0xff) << 16) | ((in[inOff + 3] & 0xff) << 24);
+
+ if (xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength & 0xffffffff);
+ X[15] = (int)(bitLength >>> 32);
+ }
+
+ private void unpackWord(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)word;
+ out[outOff + 1] = (byte)(word >>> 8);
+ out[outOff + 2] = (byte)(word >>> 16);
+ out[outOff + 3] = (byte)(word >>> 24);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(H0, out, outOff);
+ unpackWord(H1, out, outOff + 4);
+ unpackWord(H2, out, outOff + 8);
+ unpackWord(H3, out, outOff + 12);
+ unpackWord(H4, out, outOff + 16);
+ unpackWord(H5, out, outOff + 20);
+ unpackWord(H6, out, outOff + 24);
+ unpackWord(H7, out, outOff + 28);
+ unpackWord(H8, out, outOff + 32);
+ unpackWord(H9, out, outOff + 36);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables to the IV values.
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H0 = 0x67452301;
+ H1 = 0xefcdab89;
+ H2 = 0x98badcfe;
+ H3 = 0x10325476;
+ H4 = 0xc3d2e1f0;
+ H5 = 0x76543210;
+ H6 = 0xFEDCBA98;
+ H7 = 0x89ABCDEF;
+ H8 = 0x01234567;
+ H9 = 0x3C2D1E0F;
+
+ xOff = 0;
+
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /*
+ * rotate int x left n bits.
+ */
+ private int RL(
+ int x,
+ int n)
+ {
+ return (x << n) | (x >>> (32 - n));
+ }
+
+ /*
+ * f1,f2,f3,f4,f5 are the basic RIPEMD160 functions.
+ */
+
+ /*
+ * rounds 0-15
+ */
+ private int f1(
+ int x,
+ int y,
+ int z)
+ {
+ return x ^ y ^ z;
+ }
+
+ /*
+ * rounds 16-31
+ */
+ private int f2(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) | (~x & z);
+ }
+
+ /*
+ * rounds 32-47
+ */
+ private int f3(
+ int x,
+ int y,
+ int z)
+ {
+ return (x | ~y) ^ z;
+ }
+
+ /*
+ * rounds 48-63
+ */
+ private int f4(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & z) | (y & ~z);
+ }
+
+ /*
+ * rounds 64-79
+ */
+ private int f5(
+ int x,
+ int y,
+ int z)
+ {
+ return x ^ (y | ~z);
+ }
+
+ protected void processBlock()
+ {
+ int a, aa;
+ int b, bb;
+ int c, cc;
+ int d, dd;
+ int e, ee;
+ int t;
+
+ a = H0;
+ b = H1;
+ c = H2;
+ d = H3;
+ e = H4;
+ aa = H5;
+ bb = H6;
+ cc = H7;
+ dd = H8;
+ ee = H9;
+
+ //
+ // Rounds 1 - 16
+ //
+ // left
+ a = RL(a + f1(b,c,d) + X[ 0], 11) + e; c = RL(c, 10);
+ e = RL(e + f1(a,b,c) + X[ 1], 14) + d; b = RL(b, 10);
+ d = RL(d + f1(e,a,b) + X[ 2], 15) + c; a = RL(a, 10);
+ c = RL(c + f1(d,e,a) + X[ 3], 12) + b; e = RL(e, 10);
+ b = RL(b + f1(c,d,e) + X[ 4], 5) + a; d = RL(d, 10);
+ a = RL(a + f1(b,c,d) + X[ 5], 8) + e; c = RL(c, 10);
+ e = RL(e + f1(a,b,c) + X[ 6], 7) + d; b = RL(b, 10);
+ d = RL(d + f1(e,a,b) + X[ 7], 9) + c; a = RL(a, 10);
+ c = RL(c + f1(d,e,a) + X[ 8], 11) + b; e = RL(e, 10);
+ b = RL(b + f1(c,d,e) + X[ 9], 13) + a; d = RL(d, 10);
+ a = RL(a + f1(b,c,d) + X[10], 14) + e; c = RL(c, 10);
+ e = RL(e + f1(a,b,c) + X[11], 15) + d; b = RL(b, 10);
+ d = RL(d + f1(e,a,b) + X[12], 6) + c; a = RL(a, 10);
+ c = RL(c + f1(d,e,a) + X[13], 7) + b; e = RL(e, 10);
+ b = RL(b + f1(c,d,e) + X[14], 9) + a; d = RL(d, 10);
+ a = RL(a + f1(b,c,d) + X[15], 8) + e; c = RL(c, 10);
+
+ // right
+ aa = RL(aa + f5(bb,cc,dd) + X[ 5] + 0x50a28be6, 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f5(aa,bb,cc) + X[14] + 0x50a28be6, 9) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f5(ee,aa,bb) + X[ 7] + 0x50a28be6, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f5(dd,ee,aa) + X[ 0] + 0x50a28be6, 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f5(cc,dd,ee) + X[ 9] + 0x50a28be6, 13) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f5(bb,cc,dd) + X[ 2] + 0x50a28be6, 15) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f5(aa,bb,cc) + X[11] + 0x50a28be6, 15) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f5(ee,aa,bb) + X[ 4] + 0x50a28be6, 5) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f5(dd,ee,aa) + X[13] + 0x50a28be6, 7) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f5(cc,dd,ee) + X[ 6] + 0x50a28be6, 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f5(bb,cc,dd) + X[15] + 0x50a28be6, 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f5(aa,bb,cc) + X[ 8] + 0x50a28be6, 11) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f5(ee,aa,bb) + X[ 1] + 0x50a28be6, 14) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f5(dd,ee,aa) + X[10] + 0x50a28be6, 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f5(cc,dd,ee) + X[ 3] + 0x50a28be6, 12) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f5(bb,cc,dd) + X[12] + 0x50a28be6, 6) + ee; cc = RL(cc, 10);
+
+ t = a; a = aa; aa = t;
+
+ //
+ // Rounds 16-31
+ //
+ // left
+ e = RL(e + f2(a,b,c) + X[ 7] + 0x5a827999, 7) + d; b = RL(b, 10);
+ d = RL(d + f2(e,a,b) + X[ 4] + 0x5a827999, 6) + c; a = RL(a, 10);
+ c = RL(c + f2(d,e,a) + X[13] + 0x5a827999, 8) + b; e = RL(e, 10);
+ b = RL(b + f2(c,d,e) + X[ 1] + 0x5a827999, 13) + a; d = RL(d, 10);
+ a = RL(a + f2(b,c,d) + X[10] + 0x5a827999, 11) + e; c = RL(c, 10);
+ e = RL(e + f2(a,b,c) + X[ 6] + 0x5a827999, 9) + d; b = RL(b, 10);
+ d = RL(d + f2(e,a,b) + X[15] + 0x5a827999, 7) + c; a = RL(a, 10);
+ c = RL(c + f2(d,e,a) + X[ 3] + 0x5a827999, 15) + b; e = RL(e, 10);
+ b = RL(b + f2(c,d,e) + X[12] + 0x5a827999, 7) + a; d = RL(d, 10);
+ a = RL(a + f2(b,c,d) + X[ 0] + 0x5a827999, 12) + e; c = RL(c, 10);
+ e = RL(e + f2(a,b,c) + X[ 9] + 0x5a827999, 15) + d; b = RL(b, 10);
+ d = RL(d + f2(e,a,b) + X[ 5] + 0x5a827999, 9) + c; a = RL(a, 10);
+ c = RL(c + f2(d,e,a) + X[ 2] + 0x5a827999, 11) + b; e = RL(e, 10);
+ b = RL(b + f2(c,d,e) + X[14] + 0x5a827999, 7) + a; d = RL(d, 10);
+ a = RL(a + f2(b,c,d) + X[11] + 0x5a827999, 13) + e; c = RL(c, 10);
+ e = RL(e + f2(a,b,c) + X[ 8] + 0x5a827999, 12) + d; b = RL(b, 10);
+
+ // right
+ ee = RL(ee + f4(aa,bb,cc) + X[ 6] + 0x5c4dd124, 9) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f4(ee,aa,bb) + X[11] + 0x5c4dd124, 13) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f4(dd,ee,aa) + X[ 3] + 0x5c4dd124, 15) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f4(cc,dd,ee) + X[ 7] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f4(bb,cc,dd) + X[ 0] + 0x5c4dd124, 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f4(aa,bb,cc) + X[13] + 0x5c4dd124, 8) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f4(ee,aa,bb) + X[ 5] + 0x5c4dd124, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f4(dd,ee,aa) + X[10] + 0x5c4dd124, 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f4(cc,dd,ee) + X[14] + 0x5c4dd124, 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f4(bb,cc,dd) + X[15] + 0x5c4dd124, 7) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f4(aa,bb,cc) + X[ 8] + 0x5c4dd124, 12) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f4(ee,aa,bb) + X[12] + 0x5c4dd124, 7) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f4(dd,ee,aa) + X[ 4] + 0x5c4dd124, 6) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f4(cc,dd,ee) + X[ 9] + 0x5c4dd124, 15) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f4(bb,cc,dd) + X[ 1] + 0x5c4dd124, 13) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f4(aa,bb,cc) + X[ 2] + 0x5c4dd124, 11) + dd; bb = RL(bb, 10);
+
+ t = b; b = bb; bb = t;
+
+ //
+ // Rounds 32-47
+ //
+ // left
+ d = RL(d + f3(e,a,b) + X[ 3] + 0x6ed9eba1, 11) + c; a = RL(a, 10);
+ c = RL(c + f3(d,e,a) + X[10] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
+ b = RL(b + f3(c,d,e) + X[14] + 0x6ed9eba1, 6) + a; d = RL(d, 10);
+ a = RL(a + f3(b,c,d) + X[ 4] + 0x6ed9eba1, 7) + e; c = RL(c, 10);
+ e = RL(e + f3(a,b,c) + X[ 9] + 0x6ed9eba1, 14) + d; b = RL(b, 10);
+ d = RL(d + f3(e,a,b) + X[15] + 0x6ed9eba1, 9) + c; a = RL(a, 10);
+ c = RL(c + f3(d,e,a) + X[ 8] + 0x6ed9eba1, 13) + b; e = RL(e, 10);
+ b = RL(b + f3(c,d,e) + X[ 1] + 0x6ed9eba1, 15) + a; d = RL(d, 10);
+ a = RL(a + f3(b,c,d) + X[ 2] + 0x6ed9eba1, 14) + e; c = RL(c, 10);
+ e = RL(e + f3(a,b,c) + X[ 7] + 0x6ed9eba1, 8) + d; b = RL(b, 10);
+ d = RL(d + f3(e,a,b) + X[ 0] + 0x6ed9eba1, 13) + c; a = RL(a, 10);
+ c = RL(c + f3(d,e,a) + X[ 6] + 0x6ed9eba1, 6) + b; e = RL(e, 10);
+ b = RL(b + f3(c,d,e) + X[13] + 0x6ed9eba1, 5) + a; d = RL(d, 10);
+ a = RL(a + f3(b,c,d) + X[11] + 0x6ed9eba1, 12) + e; c = RL(c, 10);
+ e = RL(e + f3(a,b,c) + X[ 5] + 0x6ed9eba1, 7) + d; b = RL(b, 10);
+ d = RL(d + f3(e,a,b) + X[12] + 0x6ed9eba1, 5) + c; a = RL(a, 10);
+
+ // right
+ dd = RL(dd + f3(ee,aa,bb) + X[15] + 0x6d703ef3, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f3(dd,ee,aa) + X[ 5] + 0x6d703ef3, 7) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f3(cc,dd,ee) + X[ 1] + 0x6d703ef3, 15) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f3(bb,cc,dd) + X[ 3] + 0x6d703ef3, 11) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f3(aa,bb,cc) + X[ 7] + 0x6d703ef3, 8) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f3(ee,aa,bb) + X[14] + 0x6d703ef3, 6) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f3(dd,ee,aa) + X[ 6] + 0x6d703ef3, 6) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f3(cc,dd,ee) + X[ 9] + 0x6d703ef3, 14) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f3(bb,cc,dd) + X[11] + 0x6d703ef3, 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f3(aa,bb,cc) + X[ 8] + 0x6d703ef3, 13) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f3(ee,aa,bb) + X[12] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f3(dd,ee,aa) + X[ 2] + 0x6d703ef3, 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f3(cc,dd,ee) + X[10] + 0x6d703ef3, 13) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f3(bb,cc,dd) + X[ 0] + 0x6d703ef3, 13) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f3(aa,bb,cc) + X[ 4] + 0x6d703ef3, 7) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f3(ee,aa,bb) + X[13] + 0x6d703ef3, 5) + cc; aa = RL(aa, 10);
+
+ t = c; c = cc; cc = t;
+
+ //
+ // Rounds 48-63
+ //
+ // left
+ c = RL(c + f4(d,e,a) + X[ 1] + 0x8f1bbcdc, 11) + b; e = RL(e, 10);
+ b = RL(b + f4(c,d,e) + X[ 9] + 0x8f1bbcdc, 12) + a; d = RL(d, 10);
+ a = RL(a + f4(b,c,d) + X[11] + 0x8f1bbcdc, 14) + e; c = RL(c, 10);
+ e = RL(e + f4(a,b,c) + X[10] + 0x8f1bbcdc, 15) + d; b = RL(b, 10);
+ d = RL(d + f4(e,a,b) + X[ 0] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
+ c = RL(c + f4(d,e,a) + X[ 8] + 0x8f1bbcdc, 15) + b; e = RL(e, 10);
+ b = RL(b + f4(c,d,e) + X[12] + 0x8f1bbcdc, 9) + a; d = RL(d, 10);
+ a = RL(a + f4(b,c,d) + X[ 4] + 0x8f1bbcdc, 8) + e; c = RL(c, 10);
+ e = RL(e + f4(a,b,c) + X[13] + 0x8f1bbcdc, 9) + d; b = RL(b, 10);
+ d = RL(d + f4(e,a,b) + X[ 3] + 0x8f1bbcdc, 14) + c; a = RL(a, 10);
+ c = RL(c + f4(d,e,a) + X[ 7] + 0x8f1bbcdc, 5) + b; e = RL(e, 10);
+ b = RL(b + f4(c,d,e) + X[15] + 0x8f1bbcdc, 6) + a; d = RL(d, 10);
+ a = RL(a + f4(b,c,d) + X[14] + 0x8f1bbcdc, 8) + e; c = RL(c, 10);
+ e = RL(e + f4(a,b,c) + X[ 5] + 0x8f1bbcdc, 6) + d; b = RL(b, 10);
+ d = RL(d + f4(e,a,b) + X[ 6] + 0x8f1bbcdc, 5) + c; a = RL(a, 10);
+ c = RL(c + f4(d,e,a) + X[ 2] + 0x8f1bbcdc, 12) + b; e = RL(e, 10);
+
+ // right
+ cc = RL(cc + f2(dd,ee,aa) + X[ 8] + 0x7a6d76e9, 15) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f2(cc,dd,ee) + X[ 6] + 0x7a6d76e9, 5) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f2(bb,cc,dd) + X[ 4] + 0x7a6d76e9, 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f2(aa,bb,cc) + X[ 1] + 0x7a6d76e9, 11) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f2(ee,aa,bb) + X[ 3] + 0x7a6d76e9, 14) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f2(dd,ee,aa) + X[11] + 0x7a6d76e9, 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f2(cc,dd,ee) + X[15] + 0x7a6d76e9, 6) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f2(bb,cc,dd) + X[ 0] + 0x7a6d76e9, 14) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f2(aa,bb,cc) + X[ 5] + 0x7a6d76e9, 6) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f2(ee,aa,bb) + X[12] + 0x7a6d76e9, 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f2(dd,ee,aa) + X[ 2] + 0x7a6d76e9, 12) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f2(cc,dd,ee) + X[13] + 0x7a6d76e9, 9) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f2(bb,cc,dd) + X[ 9] + 0x7a6d76e9, 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f2(aa,bb,cc) + X[ 7] + 0x7a6d76e9, 5) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f2(ee,aa,bb) + X[10] + 0x7a6d76e9, 15) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f2(dd,ee,aa) + X[14] + 0x7a6d76e9, 8) + bb; ee = RL(ee, 10);
+
+ t = d; d = dd; dd = t;
+
+ //
+ // Rounds 64-79
+ //
+ // left
+ b = RL(b + f5(c,d,e) + X[ 4] + 0xa953fd4e, 9) + a; d = RL(d, 10);
+ a = RL(a + f5(b,c,d) + X[ 0] + 0xa953fd4e, 15) + e; c = RL(c, 10);
+ e = RL(e + f5(a,b,c) + X[ 5] + 0xa953fd4e, 5) + d; b = RL(b, 10);
+ d = RL(d + f5(e,a,b) + X[ 9] + 0xa953fd4e, 11) + c; a = RL(a, 10);
+ c = RL(c + f5(d,e,a) + X[ 7] + 0xa953fd4e, 6) + b; e = RL(e, 10);
+ b = RL(b + f5(c,d,e) + X[12] + 0xa953fd4e, 8) + a; d = RL(d, 10);
+ a = RL(a + f5(b,c,d) + X[ 2] + 0xa953fd4e, 13) + e; c = RL(c, 10);
+ e = RL(e + f5(a,b,c) + X[10] + 0xa953fd4e, 12) + d; b = RL(b, 10);
+ d = RL(d + f5(e,a,b) + X[14] + 0xa953fd4e, 5) + c; a = RL(a, 10);
+ c = RL(c + f5(d,e,a) + X[ 1] + 0xa953fd4e, 12) + b; e = RL(e, 10);
+ b = RL(b + f5(c,d,e) + X[ 3] + 0xa953fd4e, 13) + a; d = RL(d, 10);
+ a = RL(a + f5(b,c,d) + X[ 8] + 0xa953fd4e, 14) + e; c = RL(c, 10);
+ e = RL(e + f5(a,b,c) + X[11] + 0xa953fd4e, 11) + d; b = RL(b, 10);
+ d = RL(d + f5(e,a,b) + X[ 6] + 0xa953fd4e, 8) + c; a = RL(a, 10);
+ c = RL(c + f5(d,e,a) + X[15] + 0xa953fd4e, 5) + b; e = RL(e, 10);
+ b = RL(b + f5(c,d,e) + X[13] + 0xa953fd4e, 6) + a; d = RL(d, 10);
+
+ // right
+ bb = RL(bb + f1(cc,dd,ee) + X[12], 8) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f1(bb,cc,dd) + X[15], 5) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f1(aa,bb,cc) + X[10], 12) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f1(ee,aa,bb) + X[ 4], 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f1(dd,ee,aa) + X[ 1], 12) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f1(cc,dd,ee) + X[ 5], 5) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f1(bb,cc,dd) + X[ 8], 14) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f1(aa,bb,cc) + X[ 7], 6) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f1(ee,aa,bb) + X[ 6], 8) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f1(dd,ee,aa) + X[ 2], 13) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f1(cc,dd,ee) + X[13], 6) + aa; dd = RL(dd, 10);
+ aa = RL(aa + f1(bb,cc,dd) + X[14], 5) + ee; cc = RL(cc, 10);
+ ee = RL(ee + f1(aa,bb,cc) + X[ 0], 15) + dd; bb = RL(bb, 10);
+ dd = RL(dd + f1(ee,aa,bb) + X[ 3], 13) + cc; aa = RL(aa, 10);
+ cc = RL(cc + f1(dd,ee,aa) + X[ 9], 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + f1(cc,dd,ee) + X[11], 11) + aa; dd = RL(dd, 10);
+
+ //
+ // do (e, ee) swap as part of assignment.
+ //
+
+ H0 += a;
+ H1 += b;
+ H2 += c;
+ H3 += d;
+ H4 += ee;
+ H5 += aa;
+ H6 += bb;
+ H7 += cc;
+ H8 += dd;
+ H9 += e;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/SHA1Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/SHA1Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/SHA1Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/SHA1Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,290 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+import pdftk.org.bouncycastle.crypto.util.Pack;
+
+/**
+ * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
+ *
+ * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
+ * is the "endienness" of the word processing!
+ */
+public class SHA1Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 20;
+
+ private int H1, H2, H3, H4, H5;
+
+ private int[] X = new int[80];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public SHA1Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA1Digest(SHA1Digest t)
+ {
+ super(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-1";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ // Note: Inlined for performance
+// X[xOff] = Pack.bigEndianToInt(in, inOff);
+ int n = in[ inOff] << 24;
+ n |= (in[++inOff] & 0xff) << 16;
+ n |= (in[++inOff] & 0xff) << 8;
+ n |= (in[++inOff] & 0xff);
+ X[xOff] = n;
+
+ if (++xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength >>> 32);
+ X[15] = (int)(bitLength & 0xffffffff);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ Pack.intToBigEndian(H1, out, outOff);
+ Pack.intToBigEndian(H2, out, outOff + 4);
+ Pack.intToBigEndian(H3, out, outOff + 8);
+ Pack.intToBigEndian(H4, out, outOff + 12);
+ Pack.intToBigEndian(H5, out, outOff + 16);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ H1 = 0x67452301;
+ H2 = 0xefcdab89;
+ H3 = 0x98badcfe;
+ H4 = 0x10325476;
+ H5 = 0xc3d2e1f0;
+
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ //
+ // Additive constants
+ //
+ private static final int Y1 = 0x5a827999;
+ private static final int Y2 = 0x6ed9eba1;
+ private static final int Y3 = 0x8f1bbcdc;
+ private static final int Y4 = 0xca62c1d6;
+
+ private int f(
+ int u,
+ int v,
+ int w)
+ {
+ return ((u & v) | ((~u) & w));
+ }
+
+ private int h(
+ int u,
+ int v,
+ int w)
+ {
+ return (u ^ v ^ w);
+ }
+
+ private int g(
+ int u,
+ int v,
+ int w)
+ {
+ return ((u & v) | (u & w) | (v & w));
+ }
+
+ protected void processBlock()
+ {
+ //
+ // expand 16 word block into 80 word block.
+ //
+ for (int i = 16; i < 80; i++)
+ {
+ int t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16];
+ X[i] = t << 1 | t >>> 31;
+ }
+
+ //
+ // set up working variables.
+ //
+ int A = H1;
+ int B = H2;
+ int C = H3;
+ int D = H4;
+ int E = H5;
+
+ //
+ // round 1
+ //
+ int idx = 0;
+
+ for (int j = 0; j < 4; j++)
+ {
+ // E = rotateLeft(A, 5) + f(B, C, D) + E + X[idx++] + Y1
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | A >>> 27) + f(B, C, D) + X[idx++] + Y1;
+ B = B << 30 | B >>> 2;
+
+ D += (E << 5 | E >>> 27) + f(A, B, C) + X[idx++] + Y1;
+ A = A << 30 | A >>> 2;
+
+ C += (D << 5 | D >>> 27) + f(E, A, B) + X[idx++] + Y1;
+ E = E << 30 | E >>> 2;
+
+ B += (C << 5 | C >>> 27) + f(D, E, A) + X[idx++] + Y1;
+ D = D << 30 | D >>> 2;
+
+ A += (B << 5 | B >>> 27) + f(C, D, E) + X[idx++] + Y1;
+ C = C << 30 | C >>> 2;
+ }
+
+ //
+ // round 2
+ //
+ for (int j = 0; j < 4; j++)
+ {
+ // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y2
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y2;
+ B = B << 30 | B >>> 2;
+
+ D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y2;
+ A = A << 30 | A >>> 2;
+
+ C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y2;
+ E = E << 30 | E >>> 2;
+
+ B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y2;
+ D = D << 30 | D >>> 2;
+
+ A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y2;
+ C = C << 30 | C >>> 2;
+ }
+
+ //
+ // round 3
+ //
+ for (int j = 0; j < 4; j++)
+ {
+ // E = rotateLeft(A, 5) + g(B, C, D) + E + X[idx++] + Y3
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | A >>> 27) + g(B, C, D) + X[idx++] + Y3;
+ B = B << 30 | B >>> 2;
+
+ D += (E << 5 | E >>> 27) + g(A, B, C) + X[idx++] + Y3;
+ A = A << 30 | A >>> 2;
+
+ C += (D << 5 | D >>> 27) + g(E, A, B) + X[idx++] + Y3;
+ E = E << 30 | E >>> 2;
+
+ B += (C << 5 | C >>> 27) + g(D, E, A) + X[idx++] + Y3;
+ D = D << 30 | D >>> 2;
+
+ A += (B << 5 | B >>> 27) + g(C, D, E) + X[idx++] + Y3;
+ C = C << 30 | C >>> 2;
+ }
+
+ //
+ // round 4
+ //
+ for (int j = 0; j <= 3; j++)
+ {
+ // E = rotateLeft(A, 5) + h(B, C, D) + E + X[idx++] + Y4
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | A >>> 27) + h(B, C, D) + X[idx++] + Y4;
+ B = B << 30 | B >>> 2;
+
+ D += (E << 5 | E >>> 27) + h(A, B, C) + X[idx++] + Y4;
+ A = A << 30 | A >>> 2;
+
+ C += (D << 5 | D >>> 27) + h(E, A, B) + X[idx++] + Y4;
+ E = E << 30 | E >>> 2;
+
+ B += (C << 5 | C >>> 27) + h(D, E, A) + X[idx++] + Y4;
+ D = D << 30 | D >>> 2;
+
+ A += (B << 5 | B >>> 27) + h(C, D, E) + X[idx++] + Y4;
+ C = C << 30 | C >>> 2;
+ }
+
+
+ H1 += A;
+ H2 += B;
+ H3 += C;
+ H4 += D;
+ H5 += E;
+
+ //
+ // reset start of the buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ X[i] = 0;
+ }
+ }
+}
+
+
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/SHA224Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/SHA224Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/SHA224Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/SHA224Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,292 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+
+import pdftk.org.bouncycastle.crypto.digests.GeneralDigest;
+import pdftk.org.bouncycastle.crypto.util.Pack;
+
+
+/**
+ * SHA-224 as described in RFC 3874
+ *
+ * block word digest
+ * SHA-1 512 32 160
+ * SHA-224 512 32 224
+ * SHA-256 512 32 256
+ * SHA-384 1024 64 384
+ * SHA-512 1024 64 512
+ *
+ */
+public class SHA224Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 28;
+
+ private int H1, H2, H3, H4, H5, H6, H7, H8;
+
+ private int[] X = new int[64];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public SHA224Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA224Digest(SHA224Digest t)
+ {
+ super(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+ H6 = t.H6;
+ H7 = t.H7;
+ H8 = t.H8;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-224";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ // Note: Inlined for performance
+// X[xOff] = Pack.bigEndianToInt(in, inOff);
+ int n = in[ inOff] << 24;
+ n |= (in[++inOff] & 0xff) << 16;
+ n |= (in[++inOff] & 0xff) << 8;
+ n |= (in[++inOff] & 0xff);
+ X[xOff] = n;
+
+ if (++xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength >>> 32);
+ X[15] = (int)(bitLength & 0xffffffff);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ Pack.intToBigEndian(H1, out, outOff);
+ Pack.intToBigEndian(H2, out, outOff + 4);
+ Pack.intToBigEndian(H3, out, outOff + 8);
+ Pack.intToBigEndian(H4, out, outOff + 12);
+ Pack.intToBigEndian(H5, out, outOff + 16);
+ Pack.intToBigEndian(H6, out, outOff + 20);
+ Pack.intToBigEndian(H7, out, outOff + 24);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ /* SHA-224 initial hash value
+ */
+
+ H1 = 0xc1059ed8;
+ H2 = 0x367cd507;
+ H3 = 0x3070dd17;
+ H4 = 0xf70e5939;
+ H5 = 0xffc00b31;
+ H6 = 0x68581511;
+ H7 = 0x64f98fa7;
+ H8 = 0xbefa4fa4;
+
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ protected void processBlock()
+ {
+ //
+ // expand 16 word block into 64 word blocks.
+ //
+ for (int t = 16; t <= 63; t++)
+ {
+ X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
+ }
+
+ //
+ // set up working variables.
+ //
+ int a = H1;
+ int b = H2;
+ int c = H3;
+ int d = H4;
+ int e = H5;
+ int f = H6;
+ int g = H7;
+ int h = H8;
+
+
+ int t = 0;
+ for(int i = 0; i < 8; i ++)
+ {
+ // t = 8 * i
+ h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
+ d += h;
+ h += Sum0(a) + Maj(a, b, c);
+ ++t;
+
+ // t = 8 * i + 1
+ g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
+ c += g;
+ g += Sum0(h) + Maj(h, a, b);
+ ++t;
+
+ // t = 8 * i + 2
+ f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
+ b += f;
+ f += Sum0(g) + Maj(g, h, a);
+ ++t;
+
+ // t = 8 * i + 3
+ e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
+ a += e;
+ e += Sum0(f) + Maj(f, g, h);
+ ++t;
+
+ // t = 8 * i + 4
+ d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
+ h += d;
+ d += Sum0(e) + Maj(e, f, g);
+ ++t;
+
+ // t = 8 * i + 5
+ c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
+ g += c;
+ c += Sum0(d) + Maj(d, e, f);
+ ++t;
+
+ // t = 8 * i + 6
+ b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
+ f += b;
+ b += Sum0(c) + Maj(c, d, e);
+ ++t;
+
+ // t = 8 * i + 7
+ a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
+ e += a;
+ a += Sum0(b) + Maj(b, c, d);
+ ++t;
+ }
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+ H5 += e;
+ H6 += f;
+ H7 += g;
+ H8 += h;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /* SHA-224 functions */
+ private int Ch(
+ int x,
+ int y,
+ int z)
+ {
+ return ((x & y) ^ ((~x) & z));
+ }
+
+ private int Maj(
+ int x,
+ int y,
+ int z)
+ {
+ return ((x & y) ^ (x & z) ^ (y & z));
+ }
+
+ private int Sum0(
+ int x)
+ {
+ return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10));
+ }
+
+ private int Sum1(
+ int x)
+ {
+ return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7));
+ }
+
+ private int Theta0(
+ int x)
+ {
+ return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
+ }
+
+ private int Theta1(
+ int x)
+ {
+ return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
+ }
+
+ /* SHA-224 Constants
+ * (represent the first 32 bits of the fractional parts of the
+ * cube roots of the first sixty-four prime numbers)
+ */
+ static final int K[] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ };
+}
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/SHA256Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/SHA256Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/SHA256Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/SHA256Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,295 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+
+import pdftk.org.bouncycastle.crypto.digests.GeneralDigest;
+import pdftk.org.bouncycastle.crypto.util.Pack;
+
+
+/**
+ * FIPS 180-2 implementation of SHA-256.
+ *
+ *
+ * block word digest
+ * SHA-1 512 32 160
+ * SHA-256 512 32 256
+ * SHA-384 1024 64 384
+ * SHA-512 1024 64 512
+ *
+ */
+public class SHA256Digest
+ extends GeneralDigest
+{
+ private static final int DIGEST_LENGTH = 32;
+
+ private int H1, H2, H3, H4, H5, H6, H7, H8;
+
+ private int[] X = new int[64];
+ private int xOff;
+
+ /**
+ * Standard constructor
+ */
+ public SHA256Digest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA256Digest(SHA256Digest t)
+ {
+ super(t);
+
+ H1 = t.H1;
+ H2 = t.H2;
+ H3 = t.H3;
+ H4 = t.H4;
+ H5 = t.H5;
+ H6 = t.H6;
+ H7 = t.H7;
+ H8 = t.H8;
+
+ System.arraycopy(t.X, 0, X, 0, t.X.length);
+ xOff = t.xOff;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-256";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ protected void processWord(
+ byte[] in,
+ int inOff)
+ {
+ // Note: Inlined for performance
+// X[xOff] = Pack.bigEndianToInt(in, inOff);
+ int n = in[inOff] << 24;
+ n |= (in[++inOff] & 0xff) << 16;
+ n |= (in[++inOff] & 0xff) << 8;
+ n |= (in[++inOff] & 0xff);
+ X[xOff] = n;
+
+ if (++xOff == 16)
+ {
+ processBlock();
+ }
+ }
+
+ protected void processLength(
+ long bitLength)
+ {
+ if (xOff > 14)
+ {
+ processBlock();
+ }
+
+ X[14] = (int)(bitLength >>> 32);
+ X[15] = (int)(bitLength & 0xffffffff);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ Pack.intToBigEndian(H1, out, outOff);
+ Pack.intToBigEndian(H2, out, outOff + 4);
+ Pack.intToBigEndian(H3, out, outOff + 8);
+ Pack.intToBigEndian(H4, out, outOff + 12);
+ Pack.intToBigEndian(H5, out, outOff + 16);
+ Pack.intToBigEndian(H6, out, outOff + 20);
+ Pack.intToBigEndian(H7, out, outOff + 24);
+ Pack.intToBigEndian(H8, out, outOff + 28);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ /* SHA-256 initial hash value
+ * The first 32 bits of the fractional parts of the square roots
+ * of the first eight prime numbers
+ */
+
+ H1 = 0x6a09e667;
+ H2 = 0xbb67ae85;
+ H3 = 0x3c6ef372;
+ H4 = 0xa54ff53a;
+ H5 = 0x510e527f;
+ H6 = 0x9b05688c;
+ H7 = 0x1f83d9ab;
+ H8 = 0x5be0cd19;
+
+ xOff = 0;
+ for (int i = 0; i != X.length; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ protected void processBlock()
+ {
+ //
+ // expand 16 word block into 64 word blocks.
+ //
+ for (int t = 16; t <= 63; t++)
+ {
+ X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
+ }
+
+ //
+ // set up working variables.
+ //
+ int a = H1;
+ int b = H2;
+ int c = H3;
+ int d = H4;
+ int e = H5;
+ int f = H6;
+ int g = H7;
+ int h = H8;
+
+ int t = 0;
+ for(int i = 0; i < 8; i ++)
+ {
+ // t = 8 * i
+ h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
+ d += h;
+ h += Sum0(a) + Maj(a, b, c);
+ ++t;
+
+ // t = 8 * i + 1
+ g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
+ c += g;
+ g += Sum0(h) + Maj(h, a, b);
+ ++t;
+
+ // t = 8 * i + 2
+ f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
+ b += f;
+ f += Sum0(g) + Maj(g, h, a);
+ ++t;
+
+ // t = 8 * i + 3
+ e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
+ a += e;
+ e += Sum0(f) + Maj(f, g, h);
+ ++t;
+
+ // t = 8 * i + 4
+ d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
+ h += d;
+ d += Sum0(e) + Maj(e, f, g);
+ ++t;
+
+ // t = 8 * i + 5
+ c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
+ g += c;
+ c += Sum0(d) + Maj(d, e, f);
+ ++t;
+
+ // t = 8 * i + 6
+ b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
+ f += b;
+ b += Sum0(c) + Maj(c, d, e);
+ ++t;
+
+ // t = 8 * i + 7
+ a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
+ e += a;
+ a += Sum0(b) + Maj(b, c, d);
+ ++t;
+ }
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+ H5 += e;
+ H6 += f;
+ H7 += g;
+ H8 += h;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ xOff = 0;
+ for (int i = 0; i < 16; i++)
+ {
+ X[i] = 0;
+ }
+ }
+
+ /* SHA-256 functions */
+ private int Ch(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) ^ ((~x) & z);
+ }
+
+ private int Maj(
+ int x,
+ int y,
+ int z)
+ {
+ return (x & y) ^ (x & z) ^ (y & z);
+ }
+
+ private int Sum0(
+ int x)
+ {
+ return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10));
+ }
+
+ private int Sum1(
+ int x)
+ {
+ return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7));
+ }
+
+ private int Theta0(
+ int x)
+ {
+ return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
+ }
+
+ private int Theta1(
+ int x)
+ {
+ return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
+ }
+
+ /* SHA-256 Constants
+ * (represent the first 32 bits of the fractional parts of the
+ * cube roots of the first sixty-four prime numbers)
+ */
+ static final int K[] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ };
+}
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/SHA384Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/SHA384Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/SHA384Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/SHA384Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,87 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+import pdftk.org.bouncycastle.crypto.util.Pack;
+
+
+/**
+ * FIPS 180-2 implementation of SHA-384.
+ *
+ *
+ * block word digest
+ * SHA-1 512 32 160
+ * SHA-256 512 32 256
+ * SHA-384 1024 64 384
+ * SHA-512 1024 64 512
+ *
+ */
+public class SHA384Digest
+ extends LongDigest
+{
+
+ private static final int DIGEST_LENGTH = 48;
+
+ /**
+ * Standard constructor
+ */
+ public SHA384Digest()
+ {
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA384Digest(SHA384Digest t)
+ {
+ super(t);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-384";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ Pack.longToBigEndian(H1, out, outOff);
+ Pack.longToBigEndian(H2, out, outOff + 8);
+ Pack.longToBigEndian(H3, out, outOff + 16);
+ Pack.longToBigEndian(H4, out, outOff + 24);
+ Pack.longToBigEndian(H5, out, outOff + 32);
+ Pack.longToBigEndian(H6, out, outOff + 40);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ /* SHA-384 initial hash value
+ * The first 64 bits of the fractional parts of the square roots
+ * of the 9th through 16th prime numbers
+ */
+ H1 = 0xcbbb9d5dc1059ed8l;
+ H2 = 0x629a292a367cd507l;
+ H3 = 0x9159015a3070dd17l;
+ H4 = 0x152fecd8f70e5939l;
+ H5 = 0x67332667ffc00b31l;
+ H6 = 0x8eb44a8768581511l;
+ H7 = 0xdb0c2e0d64f98fa7l;
+ H8 = 0x47b5481dbefa4fa4l;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/SHA3Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/SHA3Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/SHA3Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/SHA3Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,547 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+import pdftk.org.bouncycastle.crypto.ExtendedDigest;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * implementation of SHA-3 based on following KeccakNISTInterface.c from http://keccak.noekeon.org/
+ *
+ * Following the naming conventions used in the C source code to enable easy review of the implementation.
+ */
+public class SHA3Digest
+ implements ExtendedDigest
+{
+ private static long[] KeccakRoundConstants = keccakInitializeRoundConstants();
+
+ private static int[] KeccakRhoOffsets = keccakInitializeRhoOffsets();
+
+ private static long[] keccakInitializeRoundConstants()
+ {
+ long[] keccakRoundConstants = new long[24];
+ byte[] LFSRstate = new byte[1];
+
+ LFSRstate[0] = 0x01;
+ int i, j, bitPosition;
+
+ for (i = 0; i < 24; i++)
+ {
+ keccakRoundConstants[i] = 0;
+ for (j = 0; j < 7; j++)
+ {
+ bitPosition = (1 << j) - 1;
+ if (LFSR86540(LFSRstate))
+ {
+ keccakRoundConstants[i] ^= 1L << bitPosition;
+ }
+ }
+ }
+
+ return keccakRoundConstants;
+ }
+
+ private static boolean LFSR86540(byte[] LFSR)
+ {
+ boolean result = (((LFSR[0]) & 0x01) != 0);
+ if (((LFSR[0]) & 0x80) != 0)
+ {
+ LFSR[0] = (byte)(((LFSR[0]) << 1) ^ 0x71);
+ }
+ else
+ {
+ LFSR[0] <<= 1;
+ }
+
+ return result;
+ }
+
+ private static int[] keccakInitializeRhoOffsets()
+ {
+ int[] keccakRhoOffsets = new int[25];
+ int x, y, t, newX, newY;
+
+ keccakRhoOffsets[(((0) % 5) + 5 * ((0) % 5))] = 0;
+ x = 1;
+ y = 0;
+ for (t = 0; t < 24; t++)
+ {
+ keccakRhoOffsets[(((x) % 5) + 5 * ((y) % 5))] = ((t + 1) * (t + 2) / 2) % 64;
+ newX = (0 * x + 1 * y) % 5;
+ newY = (2 * x + 3 * y) % 5;
+ x = newX;
+ y = newY;
+ }
+
+ return keccakRhoOffsets;
+ }
+
+ private byte[] state = new byte[(1600 / 8)];
+ private byte[] dataQueue = new byte[(1536 / 8)];
+ private int rate;
+ private int bitsInQueue;
+ private int fixedOutputLength;
+ private boolean squeezing;
+ private int bitsAvailableForSqueezing;
+ private byte[] chunk;
+ private byte[] oneByte;
+
+ private void clearDataQueueSection(int off, int len)
+ {
+ for (int i = off; i != off + len; i++)
+ {
+ dataQueue[i] = 0;
+ }
+ }
+
+ public SHA3Digest()
+ {
+ init(0);
+ }
+
+ public SHA3Digest(int bitLength)
+ {
+ init(bitLength);
+ }
+
+ public SHA3Digest(SHA3Digest source) {
+ System.arraycopy(source.state, 0, this.state, 0, source.state.length);
+ System.arraycopy(source.dataQueue, 0, this.dataQueue, 0, source.dataQueue.length);
+ this.rate = source.rate;
+ this.bitsInQueue = source.bitsInQueue;
+ this.fixedOutputLength = source.fixedOutputLength;
+ this.squeezing = source.squeezing;
+ this.bitsAvailableForSqueezing = source.bitsAvailableForSqueezing;
+ this.chunk = Arrays.clone(source.chunk);
+ this.oneByte = Arrays.clone(source.oneByte);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA3-" + fixedOutputLength;
+ }
+
+ public int getDigestSize()
+ {
+ return fixedOutputLength / 8;
+ }
+
+ public void update(byte in)
+ {
+ oneByte[0] = in;
+
+ doUpdate(oneByte, 0, 8L);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ doUpdate(in, inOff, len * 8L);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ squeeze(out, outOff, fixedOutputLength);
+
+ reset();
+
+ return getDigestSize();
+ }
+
+ public void reset()
+ {
+ init(fixedOutputLength);
+ }
+
+ /**
+ * Return the size of block that the compression function is applied to in bytes.
+ *
+ * @return internal byte length of a block.
+ */
+ public int getByteLength()
+ {
+ return rate / 8;
+ }
+
+ private void init(int bitLength)
+ {
+ switch (bitLength)
+ {
+ case 0:
+ case 288:
+ initSponge(1024, 576);
+ break;
+ case 224:
+ initSponge(1152, 448);
+ break;
+ case 256:
+ initSponge(1088, 512);
+ break;
+ case 384:
+ initSponge(832, 768);
+ break;
+ case 512:
+ initSponge(576, 1024);
+ break;
+ default:
+ throw new IllegalArgumentException("bitLength must be one of 224, 256, 384, or 512.");
+ }
+ }
+
+ private void doUpdate(byte[] data, int off, long databitlen)
+ {
+ if ((databitlen % 8) == 0)
+ {
+ absorb(data, off, databitlen);
+ }
+ else
+ {
+ absorb(data, off, databitlen - (databitlen % 8));
+
+ byte[] lastByte = new byte[1];
+
+ lastByte[0] = (byte)(data[off + (int)(databitlen / 8)] >> (8 - (databitlen % 8)));
+ absorb(lastByte, off, databitlen % 8);
+ }
+ }
+
+ private void initSponge(int rate, int capacity)
+ {
+ if (rate + capacity != 1600)
+ {
+ throw new IllegalStateException("rate + capacity != 1600");
+ }
+ if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0))
+ {
+ throw new IllegalStateException("invalid rate value");
+ }
+
+ this.rate = rate;
+ // this is never read, need to check to see why we want to save it
+ // this.capacity = capacity;
+ this.fixedOutputLength = 0;
+ Arrays.fill(this.state, (byte)0);
+ Arrays.fill(this.dataQueue, (byte)0);
+ this.bitsInQueue = 0;
+ this.squeezing = false;
+ this.bitsAvailableForSqueezing = 0;
+ this.fixedOutputLength = capacity / 2;
+ this.chunk = new byte[rate / 8];
+ this.oneByte = new byte[1];
+ }
+
+ private void absorbQueue()
+ {
+ KeccakAbsorb(state, dataQueue, rate / 8);
+
+ bitsInQueue = 0;
+ }
+
+ private void absorb(byte[] data, int off, long databitlen)
+ {
+ long i, j, wholeBlocks;
+
+ if ((bitsInQueue % 8) != 0)
+ {
+ throw new IllegalStateException("attempt to absorb with odd length queue.");
+ }
+ if (squeezing)
+ {
+ throw new IllegalStateException("attempt to absorb while squeezing.");
+ }
+
+ i = 0;
+ while (i < databitlen)
+ {
+ if ((bitsInQueue == 0) && (databitlen >= rate) && (i <= (databitlen - rate)))
+ {
+ wholeBlocks = (databitlen - i) / rate;
+
+ for (j = 0; j < wholeBlocks; j++)
+ {
+ System.arraycopy(data, (int)(off + (i / 8) + (j * chunk.length)), chunk, 0, chunk.length);
+
+// displayIntermediateValues.displayBytes(1, "Block to be absorbed", curData, rate / 8);
+
+ KeccakAbsorb(state, chunk, chunk.length);
+ }
+
+ i += wholeBlocks * rate;
+ }
+ else
+ {
+ int partialBlock = (int)(databitlen - i);
+ if (partialBlock + bitsInQueue > rate)
+ {
+ partialBlock = rate - bitsInQueue;
+ }
+ int partialByte = partialBlock % 8;
+ partialBlock -= partialByte;
+ System.arraycopy(data, off + (int)(i / 8), dataQueue, bitsInQueue / 8, partialBlock / 8);
+
+ bitsInQueue += partialBlock;
+ i += partialBlock;
+ if (bitsInQueue == rate)
+ {
+ absorbQueue();
+ }
+ if (partialByte > 0)
+ {
+ int mask = (1 << partialByte) - 1;
+ dataQueue[bitsInQueue / 8] = (byte)(data[off + ((int)(i / 8))] & mask);
+ bitsInQueue += partialByte;
+ i += partialByte;
+ }
+ }
+ }
+ }
+
+ private void padAndSwitchToSqueezingPhase()
+ {
+ if (bitsInQueue + 1 == rate)
+ {
+ dataQueue[bitsInQueue / 8] |= 1 << (bitsInQueue % 8);
+ absorbQueue();
+ clearDataQueueSection(0, rate / 8);
+ }
+ else
+ {
+ clearDataQueueSection((bitsInQueue + 7) / 8, rate / 8 - (bitsInQueue + 7) / 8);
+ dataQueue[bitsInQueue / 8] |= 1 << (bitsInQueue % 8);
+ }
+ dataQueue[(rate - 1) / 8] |= 1 << ((rate - 1) % 8);
+ absorbQueue();
+
+
+// displayIntermediateValues.displayText(1, "--- Switching to squeezing phase ---");
+
+
+ if (rate == 1024)
+ {
+ KeccakExtract1024bits(state, dataQueue);
+ bitsAvailableForSqueezing = 1024;
+ }
+ else
+
+ {
+ KeccakExtract(state, dataQueue, rate / 64);
+ bitsAvailableForSqueezing = rate;
+ }
+
+// displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8);
+
+ squeezing = true;
+ }
+
+ private void squeeze(byte[] output, int offset, long outputLength)
+ {
+ long i;
+ int partialBlock;
+
+ if (!squeezing)
+ {
+ padAndSwitchToSqueezingPhase();
+ }
+ if ((outputLength % 8) != 0)
+ {
+ throw new IllegalStateException("outputLength not a multiple of 8");
+ }
+
+ i = 0;
+ while (i < outputLength)
+ {
+ if (bitsAvailableForSqueezing == 0)
+ {
+ keccakPermutation(state);
+
+ if (rate == 1024)
+ {
+ KeccakExtract1024bits(state, dataQueue);
+ bitsAvailableForSqueezing = 1024;
+ }
+ else
+
+ {
+ KeccakExtract(state, dataQueue, rate / 64);
+ bitsAvailableForSqueezing = rate;
+ }
+
+// displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8);
+
+ }
+ partialBlock = bitsAvailableForSqueezing;
+ if ((long)partialBlock > outputLength - i)
+ {
+ partialBlock = (int)(outputLength - i);
+ }
+
+ System.arraycopy(dataQueue, (rate - bitsAvailableForSqueezing) / 8, output, offset + (int)(i / 8), partialBlock / 8);
+ bitsAvailableForSqueezing -= partialBlock;
+ i += partialBlock;
+ }
+ }
+
+ private void fromBytesToWords(long[] stateAsWords, byte[] state)
+ {
+ for (int i = 0; i < (1600 / 64); i++)
+ {
+ stateAsWords[i] = 0;
+ int index = i * (64 / 8);
+ for (int j = 0; j < (64 / 8); j++)
+ {
+ stateAsWords[i] |= ((long)state[index + j] & 0xff) << ((8 * j));
+ }
+ }
+ }
+
+ private void fromWordsToBytes(byte[] state, long[] stateAsWords)
+ {
+ for (int i = 0; i < (1600 / 64); i++)
+ {
+ int index = i * (64 / 8);
+ for (int j = 0; j < (64 / 8); j++)
+ {
+ state[index + j] = (byte)((stateAsWords[i] >>> ((8 * j))) & 0xFF);
+ }
+ }
+ }
+
+ private void keccakPermutation(byte[] state)
+ {
+ long[] longState = new long[state.length / 8];
+
+ fromBytesToWords(longState, state);
+
+// displayIntermediateValues.displayStateAsBytes(1, "Input of permutation", longState);
+
+ keccakPermutationOnWords(longState);
+
+// displayIntermediateValues.displayStateAsBytes(1, "State after permutation", longState);
+
+ fromWordsToBytes(state, longState);
+ }
+
+ private void keccakPermutationAfterXor(byte[] state, byte[] data, int dataLengthInBytes)
+ {
+ int i;
+
+ for (i = 0; i < dataLengthInBytes; i++)
+ {
+ state[i] ^= data[i];
+ }
+
+ keccakPermutation(state);
+ }
+
+ private void keccakPermutationOnWords(long[] state)
+ {
+ int i;
+
+// displayIntermediateValues.displayStateAs64bitWords(3, "Same, with lanes as 64-bit words", state);
+
+ for (i = 0; i < 24; i++)
+ {
+// displayIntermediateValues.displayRoundNumber(3, i);
+
+ theta(state);
+// displayIntermediateValues.displayStateAs64bitWords(3, "After theta", state);
+
+ rho(state);
+// displayIntermediateValues.displayStateAs64bitWords(3, "After rho", state);
+
+ pi(state);
+// displayIntermediateValues.displayStateAs64bitWords(3, "After pi", state);
+
+ chi(state);
+// displayIntermediateValues.displayStateAs64bitWords(3, "After chi", state);
+
+ iota(state, i);
+// displayIntermediateValues.displayStateAs64bitWords(3, "After iota", state);
+ }
+ }
+
+ long[] C = new long[5];
+
+ private void theta(long[] A)
+ {
+ for (int x = 0; x < 5; x++)
+ {
+ C[x] = 0;
+ for (int y = 0; y < 5; y++)
+ {
+ C[x] ^= A[x + 5 * y];
+ }
+ }
+ for (int x = 0; x < 5; x++)
+ {
+ long dX = ((((C[(x + 1) % 5]) << 1) ^ ((C[(x + 1) % 5]) >>> (64 - 1)))) ^ C[(x + 4) % 5];
+ for (int y = 0; y < 5; y++)
+ {
+ A[x + 5 * y] ^= dX;
+ }
+ }
+ }
+
+ private void rho(long[] A)
+ {
+ for (int x = 0; x < 5; x++)
+ {
+ for (int y = 0; y < 5; y++)
+ {
+ int index = x + 5 * y;
+ A[index] = ((KeccakRhoOffsets[index] != 0) ? (((A[index]) << KeccakRhoOffsets[index]) ^ ((A[index]) >>> (64 - KeccakRhoOffsets[index]))) : A[index]);
+ }
+ }
+ }
+
+ long[] tempA = new long[25];
+
+ private void pi(long[] A)
+ {
+ System.arraycopy(A, 0, tempA, 0, tempA.length);
+
+ for (int x = 0; x < 5; x++)
+ {
+ for (int y = 0; y < 5; y++)
+ {
+ A[y + 5 * ((2 * x + 3 * y) % 5)] = tempA[x + 5 * y];
+ }
+ }
+ }
+
+ long[] chiC = new long[5];
+
+ private void chi(long[] A)
+ {
+ for (int y = 0; y < 5; y++)
+ {
+ for (int x = 0; x < 5; x++)
+ {
+ chiC[x] = A[x + 5 * y] ^ ((~A[(((x + 1) % 5) + 5 * y)]) & A[(((x + 2) % 5) + 5 * y)]);
+ }
+ for (int x = 0; x < 5; x++)
+ {
+ A[x + 5 * y] = chiC[x];
+ }
+ }
+ }
+
+ private void iota(long[] A, int indexRound)
+ {
+ A[(((0) % 5) + 5 * ((0) % 5))] ^= KeccakRoundConstants[indexRound];
+ }
+
+ private void KeccakAbsorb(byte[] byteState, byte[] data, int dataInBytes)
+ {
+ keccakPermutationAfterXor(byteState, data, dataInBytes);
+ }
+
+
+ private void KeccakExtract1024bits(byte[] byteState, byte[] data)
+ {
+ System.arraycopy(byteState, 0, data, 0, 128);
+ }
+
+
+ private void KeccakExtract(byte[] byteState, byte[] data, int laneCount)
+ {
+ System.arraycopy(byteState, 0, data, 0, laneCount * 8);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/SHA512Digest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/SHA512Digest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/SHA512Digest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/SHA512Digest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,89 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+import pdftk.org.bouncycastle.crypto.util.Pack;
+
+
+/**
+ * FIPS 180-2 implementation of SHA-512.
+ *
+ *
+ * block word digest
+ * SHA-1 512 32 160
+ * SHA-256 512 32 256
+ * SHA-384 1024 64 384
+ * SHA-512 1024 64 512
+ *
+ */
+public class SHA512Digest
+ extends LongDigest
+{
+ private static final int DIGEST_LENGTH = 64;
+
+ /**
+ * Standard constructor
+ */
+ public SHA512Digest()
+ {
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public SHA512Digest(SHA512Digest t)
+ {
+ super(t);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SHA-512";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ Pack.longToBigEndian(H1, out, outOff);
+ Pack.longToBigEndian(H2, out, outOff + 8);
+ Pack.longToBigEndian(H3, out, outOff + 16);
+ Pack.longToBigEndian(H4, out, outOff + 24);
+ Pack.longToBigEndian(H5, out, outOff + 32);
+ Pack.longToBigEndian(H6, out, outOff + 40);
+ Pack.longToBigEndian(H7, out, outOff + 48);
+ Pack.longToBigEndian(H8, out, outOff + 56);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ super.reset();
+
+ /* SHA-512 initial hash value
+ * The first 64 bits of the fractional parts of the square roots
+ * of the first eight prime numbers
+ */
+ H1 = 0x6a09e667f3bcc908L;
+ H2 = 0xbb67ae8584caa73bL;
+ H3 = 0x3c6ef372fe94f82bL;
+ H4 = 0xa54ff53a5f1d36f1L;
+ H5 = 0x510e527fade682d1L;
+ H6 = 0x9b05688c2b3e6c1fL;
+ H7 = 0x1f83d9abfb41bd6bL;
+ H8 = 0x5be0cd19137e2179L;
+ }
+}
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/ShortenedDigest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/ShortenedDigest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/ShortenedDigest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/ShortenedDigest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,80 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+import pdftk.org.bouncycastle.crypto.ExtendedDigest;
+
+/**
+ * Wrapper class that reduces the output length of a particular digest to
+ * only the first n bytes of the digest function.
+ */
+public class ShortenedDigest
+ implements ExtendedDigest
+{
+ private ExtendedDigest baseDigest;
+ private int length;
+
+ /**
+ * Base constructor.
+ *
+ * @param baseDigest underlying digest to use.
+ * @param length length in bytes of the output of doFinal.
+ * @exception IllegalArgumentException if baseDigest is null, or length is greater than baseDigest.getDigestSize().
+ */
+ public ShortenedDigest(
+ ExtendedDigest baseDigest,
+ int length)
+ {
+ if (baseDigest == null)
+ {
+ throw new IllegalArgumentException("baseDigest must not be null");
+ }
+
+ if (length > baseDigest.getDigestSize())
+ {
+ throw new IllegalArgumentException("baseDigest output not large enough to support length");
+ }
+
+ this.baseDigest = baseDigest;
+ this.length = length;
+ }
+
+ public String getAlgorithmName()
+ {
+ return baseDigest.getAlgorithmName() + "(" + length * 8 + ")";
+ }
+
+ public int getDigestSize()
+ {
+ return length;
+ }
+
+ public void update(byte in)
+ {
+ baseDigest.update(in);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ baseDigest.update(in, inOff, len);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ byte[] tmp = new byte[baseDigest.getDigestSize()];
+
+ baseDigest.doFinal(tmp, 0);
+
+ System.arraycopy(tmp, 0, out, outOff, length);
+
+ return length;
+ }
+
+ public void reset()
+ {
+ baseDigest.reset();
+ }
+
+ public int getByteLength()
+ {
+ return baseDigest.getByteLength();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/TigerDigest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/TigerDigest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/TigerDigest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/TigerDigest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,866 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+import pdftk.org.bouncycastle.crypto.ExtendedDigest;
+
+/**
+ * implementation of Tiger based on:
+ *
+ * http://www.cs.technion.ac.il/~biham/Reports/Tiger
+ */
+public class TigerDigest
+ implements ExtendedDigest
+{
+ private static final int BYTE_LENGTH = 64;
+
+ /*
+ * S-Boxes.
+ */
+ private static final long[] t1 = {
+ 0x02AAB17CF7E90C5EL /* 0 */, 0xAC424B03E243A8ECL /* 1 */,
+ 0x72CD5BE30DD5FCD3L /* 2 */, 0x6D019B93F6F97F3AL /* 3 */,
+ 0xCD9978FFD21F9193L /* 4 */, 0x7573A1C9708029E2L /* 5 */,
+ 0xB164326B922A83C3L /* 6 */, 0x46883EEE04915870L /* 7 */,
+ 0xEAACE3057103ECE6L /* 8 */, 0xC54169B808A3535CL /* 9 */,
+ 0x4CE754918DDEC47CL /* 10 */, 0x0AA2F4DFDC0DF40CL /* 11 */,
+ 0x10B76F18A74DBEFAL /* 12 */, 0xC6CCB6235AD1AB6AL /* 13 */,
+ 0x13726121572FE2FFL /* 14 */, 0x1A488C6F199D921EL /* 15 */,
+ 0x4BC9F9F4DA0007CAL /* 16 */, 0x26F5E6F6E85241C7L /* 17 */,
+ 0x859079DBEA5947B6L /* 18 */, 0x4F1885C5C99E8C92L /* 19 */,
+ 0xD78E761EA96F864BL /* 20 */, 0x8E36428C52B5C17DL /* 21 */,
+ 0x69CF6827373063C1L /* 22 */, 0xB607C93D9BB4C56EL /* 23 */,
+ 0x7D820E760E76B5EAL /* 24 */, 0x645C9CC6F07FDC42L /* 25 */,
+ 0xBF38A078243342E0L /* 26 */, 0x5F6B343C9D2E7D04L /* 27 */,
+ 0xF2C28AEB600B0EC6L /* 28 */, 0x6C0ED85F7254BCACL /* 29 */,
+ 0x71592281A4DB4FE5L /* 30 */, 0x1967FA69CE0FED9FL /* 31 */,
+ 0xFD5293F8B96545DBL /* 32 */, 0xC879E9D7F2A7600BL /* 33 */,
+ 0x860248920193194EL /* 34 */, 0xA4F9533B2D9CC0B3L /* 35 */,
+ 0x9053836C15957613L /* 36 */, 0xDB6DCF8AFC357BF1L /* 37 */,
+ 0x18BEEA7A7A370F57L /* 38 */, 0x037117CA50B99066L /* 39 */,
+ 0x6AB30A9774424A35L /* 40 */, 0xF4E92F02E325249BL /* 41 */,
+ 0x7739DB07061CCAE1L /* 42 */, 0xD8F3B49CECA42A05L /* 43 */,
+ 0xBD56BE3F51382F73L /* 44 */, 0x45FAED5843B0BB28L /* 45 */,
+ 0x1C813D5C11BF1F83L /* 46 */, 0x8AF0E4B6D75FA169L /* 47 */,
+ 0x33EE18A487AD9999L /* 48 */, 0x3C26E8EAB1C94410L /* 49 */,
+ 0xB510102BC0A822F9L /* 50 */, 0x141EEF310CE6123BL /* 51 */,
+ 0xFC65B90059DDB154L /* 52 */, 0xE0158640C5E0E607L /* 53 */,
+ 0x884E079826C3A3CFL /* 54 */, 0x930D0D9523C535FDL /* 55 */,
+ 0x35638D754E9A2B00L /* 56 */, 0x4085FCCF40469DD5L /* 57 */,
+ 0xC4B17AD28BE23A4CL /* 58 */, 0xCAB2F0FC6A3E6A2EL /* 59 */,
+ 0x2860971A6B943FCDL /* 60 */, 0x3DDE6EE212E30446L /* 61 */,
+ 0x6222F32AE01765AEL /* 62 */, 0x5D550BB5478308FEL /* 63 */,
+ 0xA9EFA98DA0EDA22AL /* 64 */, 0xC351A71686C40DA7L /* 65 */,
+ 0x1105586D9C867C84L /* 66 */, 0xDCFFEE85FDA22853L /* 67 */,
+ 0xCCFBD0262C5EEF76L /* 68 */, 0xBAF294CB8990D201L /* 69 */,
+ 0xE69464F52AFAD975L /* 70 */, 0x94B013AFDF133E14L /* 71 */,
+ 0x06A7D1A32823C958L /* 72 */, 0x6F95FE5130F61119L /* 73 */,
+ 0xD92AB34E462C06C0L /* 74 */, 0xED7BDE33887C71D2L /* 75 */,
+ 0x79746D6E6518393EL /* 76 */, 0x5BA419385D713329L /* 77 */,
+ 0x7C1BA6B948A97564L /* 78 */, 0x31987C197BFDAC67L /* 79 */,
+ 0xDE6C23C44B053D02L /* 80 */, 0x581C49FED002D64DL /* 81 */,
+ 0xDD474D6338261571L /* 82 */, 0xAA4546C3E473D062L /* 83 */,
+ 0x928FCE349455F860L /* 84 */, 0x48161BBACAAB94D9L /* 85 */,
+ 0x63912430770E6F68L /* 86 */, 0x6EC8A5E602C6641CL /* 87 */,
+ 0x87282515337DDD2BL /* 88 */, 0x2CDA6B42034B701BL /* 89 */,
+ 0xB03D37C181CB096DL /* 90 */, 0xE108438266C71C6FL /* 91 */,
+ 0x2B3180C7EB51B255L /* 92 */, 0xDF92B82F96C08BBCL /* 93 */,
+ 0x5C68C8C0A632F3BAL /* 94 */, 0x5504CC861C3D0556L /* 95 */,
+ 0xABBFA4E55FB26B8FL /* 96 */, 0x41848B0AB3BACEB4L /* 97 */,
+ 0xB334A273AA445D32L /* 98 */, 0xBCA696F0A85AD881L /* 99 */,
+ 0x24F6EC65B528D56CL /* 100 */, 0x0CE1512E90F4524AL /* 101 */,
+ 0x4E9DD79D5506D35AL /* 102 */, 0x258905FAC6CE9779L /* 103 */,
+ 0x2019295B3E109B33L /* 104 */, 0xF8A9478B73A054CCL /* 105 */,
+ 0x2924F2F934417EB0L /* 106 */, 0x3993357D536D1BC4L /* 107 */,
+ 0x38A81AC21DB6FF8BL /* 108 */, 0x47C4FBF17D6016BFL /* 109 */,
+ 0x1E0FAADD7667E3F5L /* 110 */, 0x7ABCFF62938BEB96L /* 111 */,
+ 0xA78DAD948FC179C9L /* 112 */, 0x8F1F98B72911E50DL /* 113 */,
+ 0x61E48EAE27121A91L /* 114 */, 0x4D62F7AD31859808L /* 115 */,
+ 0xECEBA345EF5CEAEBL /* 116 */, 0xF5CEB25EBC9684CEL /* 117 */,
+ 0xF633E20CB7F76221L /* 118 */, 0xA32CDF06AB8293E4L /* 119 */,
+ 0x985A202CA5EE2CA4L /* 120 */, 0xCF0B8447CC8A8FB1L /* 121 */,
+ 0x9F765244979859A3L /* 122 */, 0xA8D516B1A1240017L /* 123 */,
+ 0x0BD7BA3EBB5DC726L /* 124 */, 0xE54BCA55B86ADB39L /* 125 */,
+ 0x1D7A3AFD6C478063L /* 126 */, 0x519EC608E7669EDDL /* 127 */,
+ 0x0E5715A2D149AA23L /* 128 */, 0x177D4571848FF194L /* 129 */,
+ 0xEEB55F3241014C22L /* 130 */, 0x0F5E5CA13A6E2EC2L /* 131 */,
+ 0x8029927B75F5C361L /* 132 */, 0xAD139FABC3D6E436L /* 133 */,
+ 0x0D5DF1A94CCF402FL /* 134 */, 0x3E8BD948BEA5DFC8L /* 135 */,
+ 0xA5A0D357BD3FF77EL /* 136 */, 0xA2D12E251F74F645L /* 137 */,
+ 0x66FD9E525E81A082L /* 138 */, 0x2E0C90CE7F687A49L /* 139 */,
+ 0xC2E8BCBEBA973BC5L /* 140 */, 0x000001BCE509745FL /* 141 */,
+ 0x423777BBE6DAB3D6L /* 142 */, 0xD1661C7EAEF06EB5L /* 143 */,
+ 0xA1781F354DAACFD8L /* 144 */, 0x2D11284A2B16AFFCL /* 145 */,
+ 0xF1FC4F67FA891D1FL /* 146 */, 0x73ECC25DCB920ADAL /* 147 */,
+ 0xAE610C22C2A12651L /* 148 */, 0x96E0A810D356B78AL /* 149 */,
+ 0x5A9A381F2FE7870FL /* 150 */, 0xD5AD62EDE94E5530L /* 151 */,
+ 0xD225E5E8368D1427L /* 152 */, 0x65977B70C7AF4631L /* 153 */,
+ 0x99F889B2DE39D74FL /* 154 */, 0x233F30BF54E1D143L /* 155 */,
+ 0x9A9675D3D9A63C97L /* 156 */, 0x5470554FF334F9A8L /* 157 */,
+ 0x166ACB744A4F5688L /* 158 */, 0x70C74CAAB2E4AEADL /* 159 */,
+ 0xF0D091646F294D12L /* 160 */, 0x57B82A89684031D1L /* 161 */,
+ 0xEFD95A5A61BE0B6BL /* 162 */, 0x2FBD12E969F2F29AL /* 163 */,
+ 0x9BD37013FEFF9FE8L /* 164 */, 0x3F9B0404D6085A06L /* 165 */,
+ 0x4940C1F3166CFE15L /* 166 */, 0x09542C4DCDF3DEFBL /* 167 */,
+ 0xB4C5218385CD5CE3L /* 168 */, 0xC935B7DC4462A641L /* 169 */,
+ 0x3417F8A68ED3B63FL /* 170 */, 0xB80959295B215B40L /* 171 */,
+ 0xF99CDAEF3B8C8572L /* 172 */, 0x018C0614F8FCB95DL /* 173 */,
+ 0x1B14ACCD1A3ACDF3L /* 174 */, 0x84D471F200BB732DL /* 175 */,
+ 0xC1A3110E95E8DA16L /* 176 */, 0x430A7220BF1A82B8L /* 177 */,
+ 0xB77E090D39DF210EL /* 178 */, 0x5EF4BD9F3CD05E9DL /* 179 */,
+ 0x9D4FF6DA7E57A444L /* 180 */, 0xDA1D60E183D4A5F8L /* 181 */,
+ 0xB287C38417998E47L /* 182 */, 0xFE3EDC121BB31886L /* 183 */,
+ 0xC7FE3CCC980CCBEFL /* 184 */, 0xE46FB590189BFD03L /* 185 */,
+ 0x3732FD469A4C57DCL /* 186 */, 0x7EF700A07CF1AD65L /* 187 */,
+ 0x59C64468A31D8859L /* 188 */, 0x762FB0B4D45B61F6L /* 189 */,
+ 0x155BAED099047718L /* 190 */, 0x68755E4C3D50BAA6L /* 191 */,
+ 0xE9214E7F22D8B4DFL /* 192 */, 0x2ADDBF532EAC95F4L /* 193 */,
+ 0x32AE3909B4BD0109L /* 194 */, 0x834DF537B08E3450L /* 195 */,
+ 0xFA209DA84220728DL /* 196 */, 0x9E691D9B9EFE23F7L /* 197 */,
+ 0x0446D288C4AE8D7FL /* 198 */, 0x7B4CC524E169785BL /* 199 */,
+ 0x21D87F0135CA1385L /* 200 */, 0xCEBB400F137B8AA5L /* 201 */,
+ 0x272E2B66580796BEL /* 202 */, 0x3612264125C2B0DEL /* 203 */,
+ 0x057702BDAD1EFBB2L /* 204 */, 0xD4BABB8EACF84BE9L /* 205 */,
+ 0x91583139641BC67BL /* 206 */, 0x8BDC2DE08036E024L /* 207 */,
+ 0x603C8156F49F68EDL /* 208 */, 0xF7D236F7DBEF5111L /* 209 */,
+ 0x9727C4598AD21E80L /* 210 */, 0xA08A0896670A5FD7L /* 211 */,
+ 0xCB4A8F4309EBA9CBL /* 212 */, 0x81AF564B0F7036A1L /* 213 */,
+ 0xC0B99AA778199ABDL /* 214 */, 0x959F1EC83FC8E952L /* 215 */,
+ 0x8C505077794A81B9L /* 216 */, 0x3ACAAF8F056338F0L /* 217 */,
+ 0x07B43F50627A6778L /* 218 */, 0x4A44AB49F5ECCC77L /* 219 */,
+ 0x3BC3D6E4B679EE98L /* 220 */, 0x9CC0D4D1CF14108CL /* 221 */,
+ 0x4406C00B206BC8A0L /* 222 */, 0x82A18854C8D72D89L /* 223 */,
+ 0x67E366B35C3C432CL /* 224 */, 0xB923DD61102B37F2L /* 225 */,
+ 0x56AB2779D884271DL /* 226 */, 0xBE83E1B0FF1525AFL /* 227 */,
+ 0xFB7C65D4217E49A9L /* 228 */, 0x6BDBE0E76D48E7D4L /* 229 */,
+ 0x08DF828745D9179EL /* 230 */, 0x22EA6A9ADD53BD34L /* 231 */,
+ 0xE36E141C5622200AL /* 232 */, 0x7F805D1B8CB750EEL /* 233 */,
+ 0xAFE5C7A59F58E837L /* 234 */, 0xE27F996A4FB1C23CL /* 235 */,
+ 0xD3867DFB0775F0D0L /* 236 */, 0xD0E673DE6E88891AL /* 237 */,
+ 0x123AEB9EAFB86C25L /* 238 */, 0x30F1D5D5C145B895L /* 239 */,
+ 0xBB434A2DEE7269E7L /* 240 */, 0x78CB67ECF931FA38L /* 241 */,
+ 0xF33B0372323BBF9CL /* 242 */, 0x52D66336FB279C74L /* 243 */,
+ 0x505F33AC0AFB4EAAL /* 244 */, 0xE8A5CD99A2CCE187L /* 245 */,
+ 0x534974801E2D30BBL /* 246 */, 0x8D2D5711D5876D90L /* 247 */,
+ 0x1F1A412891BC038EL /* 248 */, 0xD6E2E71D82E56648L /* 249 */,
+ 0x74036C3A497732B7L /* 250 */, 0x89B67ED96361F5ABL /* 251 */,
+ 0xFFED95D8F1EA02A2L /* 252 */, 0xE72B3BD61464D43DL /* 253 */,
+ 0xA6300F170BDC4820L /* 254 */, 0xEBC18760ED78A77AL /* 255 */,
+ };
+
+ private static final long[] t2 = {
+ 0xE6A6BE5A05A12138L /* 256 */, 0xB5A122A5B4F87C98L /* 257 */,
+ 0x563C6089140B6990L /* 258 */, 0x4C46CB2E391F5DD5L /* 259 */,
+ 0xD932ADDBC9B79434L /* 260 */, 0x08EA70E42015AFF5L /* 261 */,
+ 0xD765A6673E478CF1L /* 262 */, 0xC4FB757EAB278D99L /* 263 */,
+ 0xDF11C6862D6E0692L /* 264 */, 0xDDEB84F10D7F3B16L /* 265 */,
+ 0x6F2EF604A665EA04L /* 266 */, 0x4A8E0F0FF0E0DFB3L /* 267 */,
+ 0xA5EDEEF83DBCBA51L /* 268 */, 0xFC4F0A2A0EA4371EL /* 269 */,
+ 0xE83E1DA85CB38429L /* 270 */, 0xDC8FF882BA1B1CE2L /* 271 */,
+ 0xCD45505E8353E80DL /* 272 */, 0x18D19A00D4DB0717L /* 273 */,
+ 0x34A0CFEDA5F38101L /* 274 */, 0x0BE77E518887CAF2L /* 275 */,
+ 0x1E341438B3C45136L /* 276 */, 0xE05797F49089CCF9L /* 277 */,
+ 0xFFD23F9DF2591D14L /* 278 */, 0x543DDA228595C5CDL /* 279 */,
+ 0x661F81FD99052A33L /* 280 */, 0x8736E641DB0F7B76L /* 281 */,
+ 0x15227725418E5307L /* 282 */, 0xE25F7F46162EB2FAL /* 283 */,
+ 0x48A8B2126C13D9FEL /* 284 */, 0xAFDC541792E76EEAL /* 285 */,
+ 0x03D912BFC6D1898FL /* 286 */, 0x31B1AAFA1B83F51BL /* 287 */,
+ 0xF1AC2796E42AB7D9L /* 288 */, 0x40A3A7D7FCD2EBACL /* 289 */,
+ 0x1056136D0AFBBCC5L /* 290 */, 0x7889E1DD9A6D0C85L /* 291 */,
+ 0xD33525782A7974AAL /* 292 */, 0xA7E25D09078AC09BL /* 293 */,
+ 0xBD4138B3EAC6EDD0L /* 294 */, 0x920ABFBE71EB9E70L /* 295 */,
+ 0xA2A5D0F54FC2625CL /* 296 */, 0xC054E36B0B1290A3L /* 297 */,
+ 0xF6DD59FF62FE932BL /* 298 */, 0x3537354511A8AC7DL /* 299 */,
+ 0xCA845E9172FADCD4L /* 300 */, 0x84F82B60329D20DCL /* 301 */,
+ 0x79C62CE1CD672F18L /* 302 */, 0x8B09A2ADD124642CL /* 303 */,
+ 0xD0C1E96A19D9E726L /* 304 */, 0x5A786A9B4BA9500CL /* 305 */,
+ 0x0E020336634C43F3L /* 306 */, 0xC17B474AEB66D822L /* 307 */,
+ 0x6A731AE3EC9BAAC2L /* 308 */, 0x8226667AE0840258L /* 309 */,
+ 0x67D4567691CAECA5L /* 310 */, 0x1D94155C4875ADB5L /* 311 */,
+ 0x6D00FD985B813FDFL /* 312 */, 0x51286EFCB774CD06L /* 313 */,
+ 0x5E8834471FA744AFL /* 314 */, 0xF72CA0AEE761AE2EL /* 315 */,
+ 0xBE40E4CDAEE8E09AL /* 316 */, 0xE9970BBB5118F665L /* 317 */,
+ 0x726E4BEB33DF1964L /* 318 */, 0x703B000729199762L /* 319 */,
+ 0x4631D816F5EF30A7L /* 320 */, 0xB880B5B51504A6BEL /* 321 */,
+ 0x641793C37ED84B6CL /* 322 */, 0x7B21ED77F6E97D96L /* 323 */,
+ 0x776306312EF96B73L /* 324 */, 0xAE528948E86FF3F4L /* 325 */,
+ 0x53DBD7F286A3F8F8L /* 326 */, 0x16CADCE74CFC1063L /* 327 */,
+ 0x005C19BDFA52C6DDL /* 328 */, 0x68868F5D64D46AD3L /* 329 */,
+ 0x3A9D512CCF1E186AL /* 330 */, 0x367E62C2385660AEL /* 331 */,
+ 0xE359E7EA77DCB1D7L /* 332 */, 0x526C0773749ABE6EL /* 333 */,
+ 0x735AE5F9D09F734BL /* 334 */, 0x493FC7CC8A558BA8L /* 335 */,
+ 0xB0B9C1533041AB45L /* 336 */, 0x321958BA470A59BDL /* 337 */,
+ 0x852DB00B5F46C393L /* 338 */, 0x91209B2BD336B0E5L /* 339 */,
+ 0x6E604F7D659EF19FL /* 340 */, 0xB99A8AE2782CCB24L /* 341 */,
+ 0xCCF52AB6C814C4C7L /* 342 */, 0x4727D9AFBE11727BL /* 343 */,
+ 0x7E950D0C0121B34DL /* 344 */, 0x756F435670AD471FL /* 345 */,
+ 0xF5ADD442615A6849L /* 346 */, 0x4E87E09980B9957AL /* 347 */,
+ 0x2ACFA1DF50AEE355L /* 348 */, 0xD898263AFD2FD556L /* 349 */,
+ 0xC8F4924DD80C8FD6L /* 350 */, 0xCF99CA3D754A173AL /* 351 */,
+ 0xFE477BACAF91BF3CL /* 352 */, 0xED5371F6D690C12DL /* 353 */,
+ 0x831A5C285E687094L /* 354 */, 0xC5D3C90A3708A0A4L /* 355 */,
+ 0x0F7F903717D06580L /* 356 */, 0x19F9BB13B8FDF27FL /* 357 */,
+ 0xB1BD6F1B4D502843L /* 358 */, 0x1C761BA38FFF4012L /* 359 */,
+ 0x0D1530C4E2E21F3BL /* 360 */, 0x8943CE69A7372C8AL /* 361 */,
+ 0xE5184E11FEB5CE66L /* 362 */, 0x618BDB80BD736621L /* 363 */,
+ 0x7D29BAD68B574D0BL /* 364 */, 0x81BB613E25E6FE5BL /* 365 */,
+ 0x071C9C10BC07913FL /* 366 */, 0xC7BEEB7909AC2D97L /* 367 */,
+ 0xC3E58D353BC5D757L /* 368 */, 0xEB017892F38F61E8L /* 369 */,
+ 0xD4EFFB9C9B1CC21AL /* 370 */, 0x99727D26F494F7ABL /* 371 */,
+ 0xA3E063A2956B3E03L /* 372 */, 0x9D4A8B9A4AA09C30L /* 373 */,
+ 0x3F6AB7D500090FB4L /* 374 */, 0x9CC0F2A057268AC0L /* 375 */,
+ 0x3DEE9D2DEDBF42D1L /* 376 */, 0x330F49C87960A972L /* 377 */,
+ 0xC6B2720287421B41L /* 378 */, 0x0AC59EC07C00369CL /* 379 */,
+ 0xEF4EAC49CB353425L /* 380 */, 0xF450244EEF0129D8L /* 381 */,
+ 0x8ACC46E5CAF4DEB6L /* 382 */, 0x2FFEAB63989263F7L /* 383 */,
+ 0x8F7CB9FE5D7A4578L /* 384 */, 0x5BD8F7644E634635L /* 385 */,
+ 0x427A7315BF2DC900L /* 386 */, 0x17D0C4AA2125261CL /* 387 */,
+ 0x3992486C93518E50L /* 388 */, 0xB4CBFEE0A2D7D4C3L /* 389 */,
+ 0x7C75D6202C5DDD8DL /* 390 */, 0xDBC295D8E35B6C61L /* 391 */,
+ 0x60B369D302032B19L /* 392 */, 0xCE42685FDCE44132L /* 393 */,
+ 0x06F3DDB9DDF65610L /* 394 */, 0x8EA4D21DB5E148F0L /* 395 */,
+ 0x20B0FCE62FCD496FL /* 396 */, 0x2C1B912358B0EE31L /* 397 */,
+ 0xB28317B818F5A308L /* 398 */, 0xA89C1E189CA6D2CFL /* 399 */,
+ 0x0C6B18576AAADBC8L /* 400 */, 0xB65DEAA91299FAE3L /* 401 */,
+ 0xFB2B794B7F1027E7L /* 402 */, 0x04E4317F443B5BEBL /* 403 */,
+ 0x4B852D325939D0A6L /* 404 */, 0xD5AE6BEEFB207FFCL /* 405 */,
+ 0x309682B281C7D374L /* 406 */, 0xBAE309A194C3B475L /* 407 */,
+ 0x8CC3F97B13B49F05L /* 408 */, 0x98A9422FF8293967L /* 409 */,
+ 0x244B16B01076FF7CL /* 410 */, 0xF8BF571C663D67EEL /* 411 */,
+ 0x1F0D6758EEE30DA1L /* 412 */, 0xC9B611D97ADEB9B7L /* 413 */,
+ 0xB7AFD5887B6C57A2L /* 414 */, 0x6290AE846B984FE1L /* 415 */,
+ 0x94DF4CDEACC1A5FDL /* 416 */, 0x058A5BD1C5483AFFL /* 417 */,
+ 0x63166CC142BA3C37L /* 418 */, 0x8DB8526EB2F76F40L /* 419 */,
+ 0xE10880036F0D6D4EL /* 420 */, 0x9E0523C9971D311DL /* 421 */,
+ 0x45EC2824CC7CD691L /* 422 */, 0x575B8359E62382C9L /* 423 */,
+ 0xFA9E400DC4889995L /* 424 */, 0xD1823ECB45721568L /* 425 */,
+ 0xDAFD983B8206082FL /* 426 */, 0xAA7D29082386A8CBL /* 427 */,
+ 0x269FCD4403B87588L /* 428 */, 0x1B91F5F728BDD1E0L /* 429 */,
+ 0xE4669F39040201F6L /* 430 */, 0x7A1D7C218CF04ADEL /* 431 */,
+ 0x65623C29D79CE5CEL /* 432 */, 0x2368449096C00BB1L /* 433 */,
+ 0xAB9BF1879DA503BAL /* 434 */, 0xBC23ECB1A458058EL /* 435 */,
+ 0x9A58DF01BB401ECCL /* 436 */, 0xA070E868A85F143DL /* 437 */,
+ 0x4FF188307DF2239EL /* 438 */, 0x14D565B41A641183L /* 439 */,
+ 0xEE13337452701602L /* 440 */, 0x950E3DCF3F285E09L /* 441 */,
+ 0x59930254B9C80953L /* 442 */, 0x3BF299408930DA6DL /* 443 */,
+ 0xA955943F53691387L /* 444 */, 0xA15EDECAA9CB8784L /* 445 */,
+ 0x29142127352BE9A0L /* 446 */, 0x76F0371FFF4E7AFBL /* 447 */,
+ 0x0239F450274F2228L /* 448 */, 0xBB073AF01D5E868BL /* 449 */,
+ 0xBFC80571C10E96C1L /* 450 */, 0xD267088568222E23L /* 451 */,
+ 0x9671A3D48E80B5B0L /* 452 */, 0x55B5D38AE193BB81L /* 453 */,
+ 0x693AE2D0A18B04B8L /* 454 */, 0x5C48B4ECADD5335FL /* 455 */,
+ 0xFD743B194916A1CAL /* 456 */, 0x2577018134BE98C4L /* 457 */,
+ 0xE77987E83C54A4ADL /* 458 */, 0x28E11014DA33E1B9L /* 459 */,
+ 0x270CC59E226AA213L /* 460 */, 0x71495F756D1A5F60L /* 461 */,
+ 0x9BE853FB60AFEF77L /* 462 */, 0xADC786A7F7443DBFL /* 463 */,
+ 0x0904456173B29A82L /* 464 */, 0x58BC7A66C232BD5EL /* 465 */,
+ 0xF306558C673AC8B2L /* 466 */, 0x41F639C6B6C9772AL /* 467 */,
+ 0x216DEFE99FDA35DAL /* 468 */, 0x11640CC71C7BE615L /* 469 */,
+ 0x93C43694565C5527L /* 470 */, 0xEA038E6246777839L /* 471 */,
+ 0xF9ABF3CE5A3E2469L /* 472 */, 0x741E768D0FD312D2L /* 473 */,
+ 0x0144B883CED652C6L /* 474 */, 0xC20B5A5BA33F8552L /* 475 */,
+ 0x1AE69633C3435A9DL /* 476 */, 0x97A28CA4088CFDECL /* 477 */,
+ 0x8824A43C1E96F420L /* 478 */, 0x37612FA66EEEA746L /* 479 */,
+ 0x6B4CB165F9CF0E5AL /* 480 */, 0x43AA1C06A0ABFB4AL /* 481 */,
+ 0x7F4DC26FF162796BL /* 482 */, 0x6CBACC8E54ED9B0FL /* 483 */,
+ 0xA6B7FFEFD2BB253EL /* 484 */, 0x2E25BC95B0A29D4FL /* 485 */,
+ 0x86D6A58BDEF1388CL /* 486 */, 0xDED74AC576B6F054L /* 487 */,
+ 0x8030BDBC2B45805DL /* 488 */, 0x3C81AF70E94D9289L /* 489 */,
+ 0x3EFF6DDA9E3100DBL /* 490 */, 0xB38DC39FDFCC8847L /* 491 */,
+ 0x123885528D17B87EL /* 492 */, 0xF2DA0ED240B1B642L /* 493 */,
+ 0x44CEFADCD54BF9A9L /* 494 */, 0x1312200E433C7EE6L /* 495 */,
+ 0x9FFCC84F3A78C748L /* 496 */, 0xF0CD1F72248576BBL /* 497 */,
+ 0xEC6974053638CFE4L /* 498 */, 0x2BA7B67C0CEC4E4CL /* 499 */,
+ 0xAC2F4DF3E5CE32EDL /* 500 */, 0xCB33D14326EA4C11L /* 501 */,
+ 0xA4E9044CC77E58BCL /* 502 */, 0x5F513293D934FCEFL /* 503 */,
+ 0x5DC9645506E55444L /* 504 */, 0x50DE418F317DE40AL /* 505 */,
+ 0x388CB31A69DDE259L /* 506 */, 0x2DB4A83455820A86L /* 507 */,
+ 0x9010A91E84711AE9L /* 508 */, 0x4DF7F0B7B1498371L /* 509 */,
+ 0xD62A2EABC0977179L /* 510 */, 0x22FAC097AA8D5C0EL /* 511 */,
+ };
+
+ private static final long[] t3 = {
+ 0xF49FCC2FF1DAF39BL /* 512 */, 0x487FD5C66FF29281L /* 513 */,
+ 0xE8A30667FCDCA83FL /* 514 */, 0x2C9B4BE3D2FCCE63L /* 515 */,
+ 0xDA3FF74B93FBBBC2L /* 516 */, 0x2FA165D2FE70BA66L /* 517 */,
+ 0xA103E279970E93D4L /* 518 */, 0xBECDEC77B0E45E71L /* 519 */,
+ 0xCFB41E723985E497L /* 520 */, 0xB70AAA025EF75017L /* 521 */,
+ 0xD42309F03840B8E0L /* 522 */, 0x8EFC1AD035898579L /* 523 */,
+ 0x96C6920BE2B2ABC5L /* 524 */, 0x66AF4163375A9172L /* 525 */,
+ 0x2174ABDCCA7127FBL /* 526 */, 0xB33CCEA64A72FF41L /* 527 */,
+ 0xF04A4933083066A5L /* 528 */, 0x8D970ACDD7289AF5L /* 529 */,
+ 0x8F96E8E031C8C25EL /* 530 */, 0xF3FEC02276875D47L /* 531 */,
+ 0xEC7BF310056190DDL /* 532 */, 0xF5ADB0AEBB0F1491L /* 533 */,
+ 0x9B50F8850FD58892L /* 534 */, 0x4975488358B74DE8L /* 535 */,
+ 0xA3354FF691531C61L /* 536 */, 0x0702BBE481D2C6EEL /* 537 */,
+ 0x89FB24057DEDED98L /* 538 */, 0xAC3075138596E902L /* 539 */,
+ 0x1D2D3580172772EDL /* 540 */, 0xEB738FC28E6BC30DL /* 541 */,
+ 0x5854EF8F63044326L /* 542 */, 0x9E5C52325ADD3BBEL /* 543 */,
+ 0x90AA53CF325C4623L /* 544 */, 0xC1D24D51349DD067L /* 545 */,
+ 0x2051CFEEA69EA624L /* 546 */, 0x13220F0A862E7E4FL /* 547 */,
+ 0xCE39399404E04864L /* 548 */, 0xD9C42CA47086FCB7L /* 549 */,
+ 0x685AD2238A03E7CCL /* 550 */, 0x066484B2AB2FF1DBL /* 551 */,
+ 0xFE9D5D70EFBF79ECL /* 552 */, 0x5B13B9DD9C481854L /* 553 */,
+ 0x15F0D475ED1509ADL /* 554 */, 0x0BEBCD060EC79851L /* 555 */,
+ 0xD58C6791183AB7F8L /* 556 */, 0xD1187C5052F3EEE4L /* 557 */,
+ 0xC95D1192E54E82FFL /* 558 */, 0x86EEA14CB9AC6CA2L /* 559 */,
+ 0x3485BEB153677D5DL /* 560 */, 0xDD191D781F8C492AL /* 561 */,
+ 0xF60866BAA784EBF9L /* 562 */, 0x518F643BA2D08C74L /* 563 */,
+ 0x8852E956E1087C22L /* 564 */, 0xA768CB8DC410AE8DL /* 565 */,
+ 0x38047726BFEC8E1AL /* 566 */, 0xA67738B4CD3B45AAL /* 567 */,
+ 0xAD16691CEC0DDE19L /* 568 */, 0xC6D4319380462E07L /* 569 */,
+ 0xC5A5876D0BA61938L /* 570 */, 0x16B9FA1FA58FD840L /* 571 */,
+ 0x188AB1173CA74F18L /* 572 */, 0xABDA2F98C99C021FL /* 573 */,
+ 0x3E0580AB134AE816L /* 574 */, 0x5F3B05B773645ABBL /* 575 */,
+ 0x2501A2BE5575F2F6L /* 576 */, 0x1B2F74004E7E8BA9L /* 577 */,
+ 0x1CD7580371E8D953L /* 578 */, 0x7F6ED89562764E30L /* 579 */,
+ 0xB15926FF596F003DL /* 580 */, 0x9F65293DA8C5D6B9L /* 581 */,
+ 0x6ECEF04DD690F84CL /* 582 */, 0x4782275FFF33AF88L /* 583 */,
+ 0xE41433083F820801L /* 584 */, 0xFD0DFE409A1AF9B5L /* 585 */,
+ 0x4325A3342CDB396BL /* 586 */, 0x8AE77E62B301B252L /* 587 */,
+ 0xC36F9E9F6655615AL /* 588 */, 0x85455A2D92D32C09L /* 589 */,
+ 0xF2C7DEA949477485L /* 590 */, 0x63CFB4C133A39EBAL /* 591 */,
+ 0x83B040CC6EBC5462L /* 592 */, 0x3B9454C8FDB326B0L /* 593 */,
+ 0x56F56A9E87FFD78CL /* 594 */, 0x2DC2940D99F42BC6L /* 595 */,
+ 0x98F7DF096B096E2DL /* 596 */, 0x19A6E01E3AD852BFL /* 597 */,
+ 0x42A99CCBDBD4B40BL /* 598 */, 0xA59998AF45E9C559L /* 599 */,
+ 0x366295E807D93186L /* 600 */, 0x6B48181BFAA1F773L /* 601 */,
+ 0x1FEC57E2157A0A1DL /* 602 */, 0x4667446AF6201AD5L /* 603 */,
+ 0xE615EBCACFB0F075L /* 604 */, 0xB8F31F4F68290778L /* 605 */,
+ 0x22713ED6CE22D11EL /* 606 */, 0x3057C1A72EC3C93BL /* 607 */,
+ 0xCB46ACC37C3F1F2FL /* 608 */, 0xDBB893FD02AAF50EL /* 609 */,
+ 0x331FD92E600B9FCFL /* 610 */, 0xA498F96148EA3AD6L /* 611 */,
+ 0xA8D8426E8B6A83EAL /* 612 */, 0xA089B274B7735CDCL /* 613 */,
+ 0x87F6B3731E524A11L /* 614 */, 0x118808E5CBC96749L /* 615 */,
+ 0x9906E4C7B19BD394L /* 616 */, 0xAFED7F7E9B24A20CL /* 617 */,
+ 0x6509EADEEB3644A7L /* 618 */, 0x6C1EF1D3E8EF0EDEL /* 619 */,
+ 0xB9C97D43E9798FB4L /* 620 */, 0xA2F2D784740C28A3L /* 621 */,
+ 0x7B8496476197566FL /* 622 */, 0x7A5BE3E6B65F069DL /* 623 */,
+ 0xF96330ED78BE6F10L /* 624 */, 0xEEE60DE77A076A15L /* 625 */,
+ 0x2B4BEE4AA08B9BD0L /* 626 */, 0x6A56A63EC7B8894EL /* 627 */,
+ 0x02121359BA34FEF4L /* 628 */, 0x4CBF99F8283703FCL /* 629 */,
+ 0x398071350CAF30C8L /* 630 */, 0xD0A77A89F017687AL /* 631 */,
+ 0xF1C1A9EB9E423569L /* 632 */, 0x8C7976282DEE8199L /* 633 */,
+ 0x5D1737A5DD1F7ABDL /* 634 */, 0x4F53433C09A9FA80L /* 635 */,
+ 0xFA8B0C53DF7CA1D9L /* 636 */, 0x3FD9DCBC886CCB77L /* 637 */,
+ 0xC040917CA91B4720L /* 638 */, 0x7DD00142F9D1DCDFL /* 639 */,
+ 0x8476FC1D4F387B58L /* 640 */, 0x23F8E7C5F3316503L /* 641 */,
+ 0x032A2244E7E37339L /* 642 */, 0x5C87A5D750F5A74BL /* 643 */,
+ 0x082B4CC43698992EL /* 644 */, 0xDF917BECB858F63CL /* 645 */,
+ 0x3270B8FC5BF86DDAL /* 646 */, 0x10AE72BB29B5DD76L /* 647 */,
+ 0x576AC94E7700362BL /* 648 */, 0x1AD112DAC61EFB8FL /* 649 */,
+ 0x691BC30EC5FAA427L /* 650 */, 0xFF246311CC327143L /* 651 */,
+ 0x3142368E30E53206L /* 652 */, 0x71380E31E02CA396L /* 653 */,
+ 0x958D5C960AAD76F1L /* 654 */, 0xF8D6F430C16DA536L /* 655 */,
+ 0xC8FFD13F1BE7E1D2L /* 656 */, 0x7578AE66004DDBE1L /* 657 */,
+ 0x05833F01067BE646L /* 658 */, 0xBB34B5AD3BFE586DL /* 659 */,
+ 0x095F34C9A12B97F0L /* 660 */, 0x247AB64525D60CA8L /* 661 */,
+ 0xDCDBC6F3017477D1L /* 662 */, 0x4A2E14D4DECAD24DL /* 663 */,
+ 0xBDB5E6D9BE0A1EEBL /* 664 */, 0x2A7E70F7794301ABL /* 665 */,
+ 0xDEF42D8A270540FDL /* 666 */, 0x01078EC0A34C22C1L /* 667 */,
+ 0xE5DE511AF4C16387L /* 668 */, 0x7EBB3A52BD9A330AL /* 669 */,
+ 0x77697857AA7D6435L /* 670 */, 0x004E831603AE4C32L /* 671 */,
+ 0xE7A21020AD78E312L /* 672 */, 0x9D41A70C6AB420F2L /* 673 */,
+ 0x28E06C18EA1141E6L /* 674 */, 0xD2B28CBD984F6B28L /* 675 */,
+ 0x26B75F6C446E9D83L /* 676 */, 0xBA47568C4D418D7FL /* 677 */,
+ 0xD80BADBFE6183D8EL /* 678 */, 0x0E206D7F5F166044L /* 679 */,
+ 0xE258A43911CBCA3EL /* 680 */, 0x723A1746B21DC0BCL /* 681 */,
+ 0xC7CAA854F5D7CDD3L /* 682 */, 0x7CAC32883D261D9CL /* 683 */,
+ 0x7690C26423BA942CL /* 684 */, 0x17E55524478042B8L /* 685 */,
+ 0xE0BE477656A2389FL /* 686 */, 0x4D289B5E67AB2DA0L /* 687 */,
+ 0x44862B9C8FBBFD31L /* 688 */, 0xB47CC8049D141365L /* 689 */,
+ 0x822C1B362B91C793L /* 690 */, 0x4EB14655FB13DFD8L /* 691 */,
+ 0x1ECBBA0714E2A97BL /* 692 */, 0x6143459D5CDE5F14L /* 693 */,
+ 0x53A8FBF1D5F0AC89L /* 694 */, 0x97EA04D81C5E5B00L /* 695 */,
+ 0x622181A8D4FDB3F3L /* 696 */, 0xE9BCD341572A1208L /* 697 */,
+ 0x1411258643CCE58AL /* 698 */, 0x9144C5FEA4C6E0A4L /* 699 */,
+ 0x0D33D06565CF620FL /* 700 */, 0x54A48D489F219CA1L /* 701 */,
+ 0xC43E5EAC6D63C821L /* 702 */, 0xA9728B3A72770DAFL /* 703 */,
+ 0xD7934E7B20DF87EFL /* 704 */, 0xE35503B61A3E86E5L /* 705 */,
+ 0xCAE321FBC819D504L /* 706 */, 0x129A50B3AC60BFA6L /* 707 */,
+ 0xCD5E68EA7E9FB6C3L /* 708 */, 0xB01C90199483B1C7L /* 709 */,
+ 0x3DE93CD5C295376CL /* 710 */, 0xAED52EDF2AB9AD13L /* 711 */,
+ 0x2E60F512C0A07884L /* 712 */, 0xBC3D86A3E36210C9L /* 713 */,
+ 0x35269D9B163951CEL /* 714 */, 0x0C7D6E2AD0CDB5FAL /* 715 */,
+ 0x59E86297D87F5733L /* 716 */, 0x298EF221898DB0E7L /* 717 */,
+ 0x55000029D1A5AA7EL /* 718 */, 0x8BC08AE1B5061B45L /* 719 */,
+ 0xC2C31C2B6C92703AL /* 720 */, 0x94CC596BAF25EF42L /* 721 */,
+ 0x0A1D73DB22540456L /* 722 */, 0x04B6A0F9D9C4179AL /* 723 */,
+ 0xEFFDAFA2AE3D3C60L /* 724 */, 0xF7C8075BB49496C4L /* 725 */,
+ 0x9CC5C7141D1CD4E3L /* 726 */, 0x78BD1638218E5534L /* 727 */,
+ 0xB2F11568F850246AL /* 728 */, 0xEDFABCFA9502BC29L /* 729 */,
+ 0x796CE5F2DA23051BL /* 730 */, 0xAAE128B0DC93537CL /* 731 */,
+ 0x3A493DA0EE4B29AEL /* 732 */, 0xB5DF6B2C416895D7L /* 733 */,
+ 0xFCABBD25122D7F37L /* 734 */, 0x70810B58105DC4B1L /* 735 */,
+ 0xE10FDD37F7882A90L /* 736 */, 0x524DCAB5518A3F5CL /* 737 */,
+ 0x3C9E85878451255BL /* 738 */, 0x4029828119BD34E2L /* 739 */,
+ 0x74A05B6F5D3CECCBL /* 740 */, 0xB610021542E13ECAL /* 741 */,
+ 0x0FF979D12F59E2ACL /* 742 */, 0x6037DA27E4F9CC50L /* 743 */,
+ 0x5E92975A0DF1847DL /* 744 */, 0xD66DE190D3E623FEL /* 745 */,
+ 0x5032D6B87B568048L /* 746 */, 0x9A36B7CE8235216EL /* 747 */,
+ 0x80272A7A24F64B4AL /* 748 */, 0x93EFED8B8C6916F7L /* 749 */,
+ 0x37DDBFF44CCE1555L /* 750 */, 0x4B95DB5D4B99BD25L /* 751 */,
+ 0x92D3FDA169812FC0L /* 752 */, 0xFB1A4A9A90660BB6L /* 753 */,
+ 0x730C196946A4B9B2L /* 754 */, 0x81E289AA7F49DA68L /* 755 */,
+ 0x64669A0F83B1A05FL /* 756 */, 0x27B3FF7D9644F48BL /* 757 */,
+ 0xCC6B615C8DB675B3L /* 758 */, 0x674F20B9BCEBBE95L /* 759 */,
+ 0x6F31238275655982L /* 760 */, 0x5AE488713E45CF05L /* 761 */,
+ 0xBF619F9954C21157L /* 762 */, 0xEABAC46040A8EAE9L /* 763 */,
+ 0x454C6FE9F2C0C1CDL /* 764 */, 0x419CF6496412691CL /* 765 */,
+ 0xD3DC3BEF265B0F70L /* 766 */, 0x6D0E60F5C3578A9EL /* 767 */,
+ };
+
+ private static final long[] t4 = {
+ 0x5B0E608526323C55L /* 768 */, 0x1A46C1A9FA1B59F5L /* 769 */,
+ 0xA9E245A17C4C8FFAL /* 770 */, 0x65CA5159DB2955D7L /* 771 */,
+ 0x05DB0A76CE35AFC2L /* 772 */, 0x81EAC77EA9113D45L /* 773 */,
+ 0x528EF88AB6AC0A0DL /* 774 */, 0xA09EA253597BE3FFL /* 775 */,
+ 0x430DDFB3AC48CD56L /* 776 */, 0xC4B3A67AF45CE46FL /* 777 */,
+ 0x4ECECFD8FBE2D05EL /* 778 */, 0x3EF56F10B39935F0L /* 779 */,
+ 0x0B22D6829CD619C6L /* 780 */, 0x17FD460A74DF2069L /* 781 */,
+ 0x6CF8CC8E8510ED40L /* 782 */, 0xD6C824BF3A6ECAA7L /* 783 */,
+ 0x61243D581A817049L /* 784 */, 0x048BACB6BBC163A2L /* 785 */,
+ 0xD9A38AC27D44CC32L /* 786 */, 0x7FDDFF5BAAF410ABL /* 787 */,
+ 0xAD6D495AA804824BL /* 788 */, 0xE1A6A74F2D8C9F94L /* 789 */,
+ 0xD4F7851235DEE8E3L /* 790 */, 0xFD4B7F886540D893L /* 791 */,
+ 0x247C20042AA4BFDAL /* 792 */, 0x096EA1C517D1327CL /* 793 */,
+ 0xD56966B4361A6685L /* 794 */, 0x277DA5C31221057DL /* 795 */,
+ 0x94D59893A43ACFF7L /* 796 */, 0x64F0C51CCDC02281L /* 797 */,
+ 0x3D33BCC4FF6189DBL /* 798 */, 0xE005CB184CE66AF1L /* 799 */,
+ 0xFF5CCD1D1DB99BEAL /* 800 */, 0xB0B854A7FE42980FL /* 801 */,
+ 0x7BD46A6A718D4B9FL /* 802 */, 0xD10FA8CC22A5FD8CL /* 803 */,
+ 0xD31484952BE4BD31L /* 804 */, 0xC7FA975FCB243847L /* 805 */,
+ 0x4886ED1E5846C407L /* 806 */, 0x28CDDB791EB70B04L /* 807 */,
+ 0xC2B00BE2F573417FL /* 808 */, 0x5C9590452180F877L /* 809 */,
+ 0x7A6BDDFFF370EB00L /* 810 */, 0xCE509E38D6D9D6A4L /* 811 */,
+ 0xEBEB0F00647FA702L /* 812 */, 0x1DCC06CF76606F06L /* 813 */,
+ 0xE4D9F28BA286FF0AL /* 814 */, 0xD85A305DC918C262L /* 815 */,
+ 0x475B1D8732225F54L /* 816 */, 0x2D4FB51668CCB5FEL /* 817 */,
+ 0xA679B9D9D72BBA20L /* 818 */, 0x53841C0D912D43A5L /* 819 */,
+ 0x3B7EAA48BF12A4E8L /* 820 */, 0x781E0E47F22F1DDFL /* 821 */,
+ 0xEFF20CE60AB50973L /* 822 */, 0x20D261D19DFFB742L /* 823 */,
+ 0x16A12B03062A2E39L /* 824 */, 0x1960EB2239650495L /* 825 */,
+ 0x251C16FED50EB8B8L /* 826 */, 0x9AC0C330F826016EL /* 827 */,
+ 0xED152665953E7671L /* 828 */, 0x02D63194A6369570L /* 829 */,
+ 0x5074F08394B1C987L /* 830 */, 0x70BA598C90B25CE1L /* 831 */,
+ 0x794A15810B9742F6L /* 832 */, 0x0D5925E9FCAF8C6CL /* 833 */,
+ 0x3067716CD868744EL /* 834 */, 0x910AB077E8D7731BL /* 835 */,
+ 0x6A61BBDB5AC42F61L /* 836 */, 0x93513EFBF0851567L /* 837 */,
+ 0xF494724B9E83E9D5L /* 838 */, 0xE887E1985C09648DL /* 839 */,
+ 0x34B1D3C675370CFDL /* 840 */, 0xDC35E433BC0D255DL /* 841 */,
+ 0xD0AAB84234131BE0L /* 842 */, 0x08042A50B48B7EAFL /* 843 */,
+ 0x9997C4EE44A3AB35L /* 844 */, 0x829A7B49201799D0L /* 845 */,
+ 0x263B8307B7C54441L /* 846 */, 0x752F95F4FD6A6CA6L /* 847 */,
+ 0x927217402C08C6E5L /* 848 */, 0x2A8AB754A795D9EEL /* 849 */,
+ 0xA442F7552F72943DL /* 850 */, 0x2C31334E19781208L /* 851 */,
+ 0x4FA98D7CEAEE6291L /* 852 */, 0x55C3862F665DB309L /* 853 */,
+ 0xBD0610175D53B1F3L /* 854 */, 0x46FE6CB840413F27L /* 855 */,
+ 0x3FE03792DF0CFA59L /* 856 */, 0xCFE700372EB85E8FL /* 857 */,
+ 0xA7BE29E7ADBCE118L /* 858 */, 0xE544EE5CDE8431DDL /* 859 */,
+ 0x8A781B1B41F1873EL /* 860 */, 0xA5C94C78A0D2F0E7L /* 861 */,
+ 0x39412E2877B60728L /* 862 */, 0xA1265EF3AFC9A62CL /* 863 */,
+ 0xBCC2770C6A2506C5L /* 864 */, 0x3AB66DD5DCE1CE12L /* 865 */,
+ 0xE65499D04A675B37L /* 866 */, 0x7D8F523481BFD216L /* 867 */,
+ 0x0F6F64FCEC15F389L /* 868 */, 0x74EFBE618B5B13C8L /* 869 */,
+ 0xACDC82B714273E1DL /* 870 */, 0xDD40BFE003199D17L /* 871 */,
+ 0x37E99257E7E061F8L /* 872 */, 0xFA52626904775AAAL /* 873 */,
+ 0x8BBBF63A463D56F9L /* 874 */, 0xF0013F1543A26E64L /* 875 */,
+ 0xA8307E9F879EC898L /* 876 */, 0xCC4C27A4150177CCL /* 877 */,
+ 0x1B432F2CCA1D3348L /* 878 */, 0xDE1D1F8F9F6FA013L /* 879 */,
+ 0x606602A047A7DDD6L /* 880 */, 0xD237AB64CC1CB2C7L /* 881 */,
+ 0x9B938E7225FCD1D3L /* 882 */, 0xEC4E03708E0FF476L /* 883 */,
+ 0xFEB2FBDA3D03C12DL /* 884 */, 0xAE0BCED2EE43889AL /* 885 */,
+ 0x22CB8923EBFB4F43L /* 886 */, 0x69360D013CF7396DL /* 887 */,
+ 0x855E3602D2D4E022L /* 888 */, 0x073805BAD01F784CL /* 889 */,
+ 0x33E17A133852F546L /* 890 */, 0xDF4874058AC7B638L /* 891 */,
+ 0xBA92B29C678AA14AL /* 892 */, 0x0CE89FC76CFAADCDL /* 893 */,
+ 0x5F9D4E0908339E34L /* 894 */, 0xF1AFE9291F5923B9L /* 895 */,
+ 0x6E3480F60F4A265FL /* 896 */, 0xEEBF3A2AB29B841CL /* 897 */,
+ 0xE21938A88F91B4ADL /* 898 */, 0x57DFEFF845C6D3C3L /* 899 */,
+ 0x2F006B0BF62CAAF2L /* 900 */, 0x62F479EF6F75EE78L /* 901 */,
+ 0x11A55AD41C8916A9L /* 902 */, 0xF229D29084FED453L /* 903 */,
+ 0x42F1C27B16B000E6L /* 904 */, 0x2B1F76749823C074L /* 905 */,
+ 0x4B76ECA3C2745360L /* 906 */, 0x8C98F463B91691BDL /* 907 */,
+ 0x14BCC93CF1ADE66AL /* 908 */, 0x8885213E6D458397L /* 909 */,
+ 0x8E177DF0274D4711L /* 910 */, 0xB49B73B5503F2951L /* 911 */,
+ 0x10168168C3F96B6BL /* 912 */, 0x0E3D963B63CAB0AEL /* 913 */,
+ 0x8DFC4B5655A1DB14L /* 914 */, 0xF789F1356E14DE5CL /* 915 */,
+ 0x683E68AF4E51DAC1L /* 916 */, 0xC9A84F9D8D4B0FD9L /* 917 */,
+ 0x3691E03F52A0F9D1L /* 918 */, 0x5ED86E46E1878E80L /* 919 */,
+ 0x3C711A0E99D07150L /* 920 */, 0x5A0865B20C4E9310L /* 921 */,
+ 0x56FBFC1FE4F0682EL /* 922 */, 0xEA8D5DE3105EDF9BL /* 923 */,
+ 0x71ABFDB12379187AL /* 924 */, 0x2EB99DE1BEE77B9CL /* 925 */,
+ 0x21ECC0EA33CF4523L /* 926 */, 0x59A4D7521805C7A1L /* 927 */,
+ 0x3896F5EB56AE7C72L /* 928 */, 0xAA638F3DB18F75DCL /* 929 */,
+ 0x9F39358DABE9808EL /* 930 */, 0xB7DEFA91C00B72ACL /* 931 */,
+ 0x6B5541FD62492D92L /* 932 */, 0x6DC6DEE8F92E4D5BL /* 933 */,
+ 0x353F57ABC4BEEA7EL /* 934 */, 0x735769D6DA5690CEL /* 935 */,
+ 0x0A234AA642391484L /* 936 */, 0xF6F9508028F80D9DL /* 937 */,
+ 0xB8E319A27AB3F215L /* 938 */, 0x31AD9C1151341A4DL /* 939 */,
+ 0x773C22A57BEF5805L /* 940 */, 0x45C7561A07968633L /* 941 */,
+ 0xF913DA9E249DBE36L /* 942 */, 0xDA652D9B78A64C68L /* 943 */,
+ 0x4C27A97F3BC334EFL /* 944 */, 0x76621220E66B17F4L /* 945 */,
+ 0x967743899ACD7D0BL /* 946 */, 0xF3EE5BCAE0ED6782L /* 947 */,
+ 0x409F753600C879FCL /* 948 */, 0x06D09A39B5926DB6L /* 949 */,
+ 0x6F83AEB0317AC588L /* 950 */, 0x01E6CA4A86381F21L /* 951 */,
+ 0x66FF3462D19F3025L /* 952 */, 0x72207C24DDFD3BFBL /* 953 */,
+ 0x4AF6B6D3E2ECE2EBL /* 954 */, 0x9C994DBEC7EA08DEL /* 955 */,
+ 0x49ACE597B09A8BC4L /* 956 */, 0xB38C4766CF0797BAL /* 957 */,
+ 0x131B9373C57C2A75L /* 958 */, 0xB1822CCE61931E58L /* 959 */,
+ 0x9D7555B909BA1C0CL /* 960 */, 0x127FAFDD937D11D2L /* 961 */,
+ 0x29DA3BADC66D92E4L /* 962 */, 0xA2C1D57154C2ECBCL /* 963 */,
+ 0x58C5134D82F6FE24L /* 964 */, 0x1C3AE3515B62274FL /* 965 */,
+ 0xE907C82E01CB8126L /* 966 */, 0xF8ED091913E37FCBL /* 967 */,
+ 0x3249D8F9C80046C9L /* 968 */, 0x80CF9BEDE388FB63L /* 969 */,
+ 0x1881539A116CF19EL /* 970 */, 0x5103F3F76BD52457L /* 971 */,
+ 0x15B7E6F5AE47F7A8L /* 972 */, 0xDBD7C6DED47E9CCFL /* 973 */,
+ 0x44E55C410228BB1AL /* 974 */, 0xB647D4255EDB4E99L /* 975 */,
+ 0x5D11882BB8AAFC30L /* 976 */, 0xF5098BBB29D3212AL /* 977 */,
+ 0x8FB5EA14E90296B3L /* 978 */, 0x677B942157DD025AL /* 979 */,
+ 0xFB58E7C0A390ACB5L /* 980 */, 0x89D3674C83BD4A01L /* 981 */,
+ 0x9E2DA4DF4BF3B93BL /* 982 */, 0xFCC41E328CAB4829L /* 983 */,
+ 0x03F38C96BA582C52L /* 984 */, 0xCAD1BDBD7FD85DB2L /* 985 */,
+ 0xBBB442C16082AE83L /* 986 */, 0xB95FE86BA5DA9AB0L /* 987 */,
+ 0xB22E04673771A93FL /* 988 */, 0x845358C9493152D8L /* 989 */,
+ 0xBE2A488697B4541EL /* 990 */, 0x95A2DC2DD38E6966L /* 991 */,
+ 0xC02C11AC923C852BL /* 992 */, 0x2388B1990DF2A87BL /* 993 */,
+ 0x7C8008FA1B4F37BEL /* 994 */, 0x1F70D0C84D54E503L /* 995 */,
+ 0x5490ADEC7ECE57D4L /* 996 */, 0x002B3C27D9063A3AL /* 997 */,
+ 0x7EAEA3848030A2BFL /* 998 */, 0xC602326DED2003C0L /* 999 */,
+ 0x83A7287D69A94086L /* 1000 */, 0xC57A5FCB30F57A8AL /* 1001 */,
+ 0xB56844E479EBE779L /* 1002 */, 0xA373B40F05DCBCE9L /* 1003 */,
+ 0xD71A786E88570EE2L /* 1004 */, 0x879CBACDBDE8F6A0L /* 1005 */,
+ 0x976AD1BCC164A32FL /* 1006 */, 0xAB21E25E9666D78BL /* 1007 */,
+ 0x901063AAE5E5C33CL /* 1008 */, 0x9818B34448698D90L /* 1009 */,
+ 0xE36487AE3E1E8ABBL /* 1010 */, 0xAFBDF931893BDCB4L /* 1011 */,
+ 0x6345A0DC5FBBD519L /* 1012 */, 0x8628FE269B9465CAL /* 1013 */,
+ 0x1E5D01603F9C51ECL /* 1014 */, 0x4DE44006A15049B7L /* 1015 */,
+ 0xBF6C70E5F776CBB1L /* 1016 */, 0x411218F2EF552BEDL /* 1017 */,
+ 0xCB0C0708705A36A3L /* 1018 */, 0xE74D14754F986044L /* 1019 */,
+ 0xCD56D9430EA8280EL /* 1020 */, 0xC12591D7535F5065L /* 1021 */,
+ 0xC83223F1720AEF96L /* 1022 */, 0xC3A0396F7363A51FL /* 1023 */
+ };
+
+ private static final int DIGEST_LENGTH = 24;
+
+ //
+ // registers
+ //
+ private long a, b, c;
+ private long byteCount;
+
+ //
+ // buffers
+ //
+ private byte[] buf = new byte[8];
+ private int bOff = 0;
+
+ private long[] x = new long[8];
+ private int xOff = 0;
+
+ /**
+ * Standard constructor
+ */
+ public TigerDigest()
+ {
+ reset();
+ }
+
+ /**
+ * Copy constructor. This will copy the state of the provided
+ * message digest.
+ */
+ public TigerDigest(TigerDigest t)
+ {
+ a = t.a;
+ b = t.b;
+ c = t.c;
+
+ System.arraycopy(t.x, 0, x, 0, t.x.length);
+ xOff = t.xOff;
+
+ System.arraycopy(t.buf, 0, buf, 0, t.buf.length);
+ bOff = t.bOff;
+
+ byteCount = t.byteCount;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Tiger";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH;
+ }
+
+ private void processWord(
+ byte[] b,
+ int off)
+ {
+ x[xOff++] = ((long)(b[off + 7] & 0xff) << 56)
+ | ((long)(b[off + 6] & 0xff) << 48)
+ | ((long)(b[off + 5] & 0xff) << 40)
+ | ((long)(b[off + 4] & 0xff) << 32)
+ | ((long)(b[off + 3] & 0xff) << 24)
+ | ((long)(b[off + 2] & 0xff) << 16)
+ | ((long)(b[off + 1] & 0xff) << 8)
+ | ((b[off + 0] & 0xff));
+
+ if (xOff == x.length)
+ {
+ processBlock();
+ }
+
+ bOff = 0;
+ }
+
+ public void update(
+ byte in)
+ {
+ buf[bOff++] = in;
+
+ if (bOff == buf.length)
+ {
+ processWord(buf, 0);
+ }
+
+ byteCount++;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ //
+ // fill the current word
+ //
+ while ((bOff != 0) && (len > 0))
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (len > 8)
+ {
+ processWord(in, inOff);
+
+ inOff += 8;
+ len -= 8;
+ byteCount += 8;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (len > 0)
+ {
+ update(in[inOff]);
+
+ inOff++;
+ len--;
+ }
+ }
+
+ private void roundABC(
+ long x,
+ long mul)
+ {
+ c ^= x ;
+ a -= t1[(int)c & 0xff] ^ t2[(int)(c >> 16) & 0xff]
+ ^ t3[(int)(c >> 32) & 0xff] ^ t4[(int)(c >> 48) & 0xff];
+ b += t4[(int)(c >> 8) & 0xff] ^ t3[(int)(c >> 24) & 0xff]
+ ^ t2[(int)(c >> 40) & 0xff] ^ t1[(int)(c >> 56) & 0xff];
+ b *= mul;
+ }
+
+ private void roundBCA(
+ long x,
+ long mul)
+ {
+ a ^= x ;
+ b -= t1[(int)a & 0xff] ^ t2[(int)(a >> 16) & 0xff]
+ ^ t3[(int)(a >> 32) & 0xff] ^ t4[(int)(a >> 48) & 0xff];
+ c += t4[(int)(a >> 8) & 0xff] ^ t3[(int)(a >> 24) & 0xff]
+ ^ t2[(int)(a >> 40) & 0xff] ^ t1[(int)(a >> 56) & 0xff];
+ c *= mul;
+ }
+
+ private void roundCAB(
+ long x,
+ long mul)
+ {
+ b ^= x ;
+ c -= t1[(int)b & 0xff] ^ t2[(int)(b >> 16) & 0xff]
+ ^ t3[(int)(b >> 32) & 0xff] ^ t4[(int)(b >> 48) & 0xff];
+ a += t4[(int)(b >> 8) & 0xff] ^ t3[(int)(b >> 24) & 0xff]
+ ^ t2[(int)(b >> 40) & 0xff] ^ t1[(int)(b >> 56) & 0xff];
+ a *= mul;
+ }
+
+ private void keySchedule()
+ {
+ x[0] -= x[7] ^ 0xA5A5A5A5A5A5A5A5L;
+ x[1] ^= x[0];
+ x[2] += x[1];
+ x[3] -= x[2] ^ ((~x[1]) << 19);
+ x[4] ^= x[3];
+ x[5] += x[4];
+ x[6] -= x[5] ^ ((~x[4]) >>> 23);
+ x[7] ^= x[6];
+ x[0] += x[7];
+ x[1] -= x[0] ^ ((~x[7]) << 19);
+ x[2] ^= x[1];
+ x[3] += x[2];
+ x[4] -= x[3] ^ ((~x[2]) >>> 23);
+ x[5] ^= x[4];
+ x[6] += x[5];
+ x[7] -= x[6] ^ 0x0123456789ABCDEFL;
+ }
+
+ private void processBlock()
+ {
+ //
+ // save abc
+ //
+ long aa = a;
+ long bb = b;
+ long cc = c;
+
+ //
+ // rounds and schedule
+ //
+ roundABC(x[0], 5);
+ roundBCA(x[1], 5);
+ roundCAB(x[2], 5);
+ roundABC(x[3], 5);
+ roundBCA(x[4], 5);
+ roundCAB(x[5], 5);
+ roundABC(x[6], 5);
+ roundBCA(x[7], 5);
+
+ keySchedule();
+
+ roundCAB(x[0], 7);
+ roundABC(x[1], 7);
+ roundBCA(x[2], 7);
+ roundCAB(x[3], 7);
+ roundABC(x[4], 7);
+ roundBCA(x[5], 7);
+ roundCAB(x[6], 7);
+ roundABC(x[7], 7);
+
+ keySchedule();
+
+ roundBCA(x[0], 9);
+ roundCAB(x[1], 9);
+ roundABC(x[2], 9);
+ roundBCA(x[3], 9);
+ roundCAB(x[4], 9);
+ roundABC(x[5], 9);
+ roundBCA(x[6], 9);
+ roundCAB(x[7], 9);
+
+ //
+ // feed forward
+ //
+ a ^= aa;
+ b -= bb;
+ c += cc;
+
+ //
+ // clear the x buffer
+ //
+ xOff = 0;
+ for (int i = 0; i != x.length; i++)
+ {
+ x[i] = 0;
+ }
+ }
+
+ public void unpackWord(
+ long r,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff + 7] = (byte)(r >> 56);
+ out[outOff + 6] = (byte)(r >> 48);
+ out[outOff + 5] = (byte)(r >> 40);
+ out[outOff + 4] = (byte)(r >> 32);
+ out[outOff + 3] = (byte)(r >> 24);
+ out[outOff + 2] = (byte)(r >> 16);
+ out[outOff + 1] = (byte)(r >> 8);
+ out[outOff] = (byte)r;
+ }
+
+ private void processLength(
+ long bitLength)
+ {
+ x[7] = bitLength;
+ }
+
+ private void finish()
+ {
+ long bitLength = (byteCount << 3);
+
+ update((byte)0x01);
+
+ while (bOff != 0)
+ {
+ update((byte)0);
+ }
+
+ processLength(bitLength);
+
+ processBlock();
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ finish();
+
+ unpackWord(a, out, outOff);
+ unpackWord(b, out, outOff + 8);
+ unpackWord(c, out, outOff + 16);
+
+ reset();
+
+ return DIGEST_LENGTH;
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ a = 0x0123456789ABCDEFL;
+ b = 0xFEDCBA9876543210L;
+ c = 0xF096A5B4C3B2E187L;
+
+ xOff = 0;
+ for (int i = 0; i != x.length; i++)
+ {
+ x[i] = 0;
+ }
+
+ bOff = 0;
+ for (int i = 0; i != buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ byteCount = 0;
+ }
+
+ public int getByteLength()
+ {
+ return BYTE_LENGTH;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/WhirlpoolDigest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/WhirlpoolDigest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/WhirlpoolDigest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/WhirlpoolDigest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,396 @@
+package pdftk.org.bouncycastle.crypto.digests;
+
+import pdftk.org.bouncycastle.crypto.ExtendedDigest;
+import pdftk.org.bouncycastle.util.Arrays;
+
+
+/**
+ * Implementation of WhirlpoolDigest, based on Java source published by Barreto
+ * and Rijmen.
+ *
+ */
+public final class WhirlpoolDigest
+ implements ExtendedDigest
+{
+ private static final int BYTE_LENGTH = 64;
+
+ private static final int DIGEST_LENGTH_BYTES = 512 / 8;
+ private static final int ROUNDS = 10;
+ private static final int REDUCTION_POLYNOMIAL = 0x011d; // 2^8 + 2^4 + 2^3 + 2 + 1;
+
+ private static final int[] SBOX = {
+ 0x18, 0x23, 0xc6, 0xe8, 0x87, 0xb8, 0x01, 0x4f, 0x36, 0xa6, 0xd2, 0xf5, 0x79, 0x6f, 0x91, 0x52,
+ 0x60, 0xbc, 0x9b, 0x8e, 0xa3, 0x0c, 0x7b, 0x35, 0x1d, 0xe0, 0xd7, 0xc2, 0x2e, 0x4b, 0xfe, 0x57,
+ 0x15, 0x77, 0x37, 0xe5, 0x9f, 0xf0, 0x4a, 0xda, 0x58, 0xc9, 0x29, 0x0a, 0xb1, 0xa0, 0x6b, 0x85,
+ 0xbd, 0x5d, 0x10, 0xf4, 0xcb, 0x3e, 0x05, 0x67, 0xe4, 0x27, 0x41, 0x8b, 0xa7, 0x7d, 0x95, 0xd8,
+ 0xfb, 0xee, 0x7c, 0x66, 0xdd, 0x17, 0x47, 0x9e, 0xca, 0x2d, 0xbf, 0x07, 0xad, 0x5a, 0x83, 0x33,
+ 0x63, 0x02, 0xaa, 0x71, 0xc8, 0x19, 0x49, 0xd9, 0xf2, 0xe3, 0x5b, 0x88, 0x9a, 0x26, 0x32, 0xb0,
+ 0xe9, 0x0f, 0xd5, 0x80, 0xbe, 0xcd, 0x34, 0x48, 0xff, 0x7a, 0x90, 0x5f, 0x20, 0x68, 0x1a, 0xae,
+ 0xb4, 0x54, 0x93, 0x22, 0x64, 0xf1, 0x73, 0x12, 0x40, 0x08, 0xc3, 0xec, 0xdb, 0xa1, 0x8d, 0x3d,
+ 0x97, 0x00, 0xcf, 0x2b, 0x76, 0x82, 0xd6, 0x1b, 0xb5, 0xaf, 0x6a, 0x50, 0x45, 0xf3, 0x30, 0xef,
+ 0x3f, 0x55, 0xa2, 0xea, 0x65, 0xba, 0x2f, 0xc0, 0xde, 0x1c, 0xfd, 0x4d, 0x92, 0x75, 0x06, 0x8a,
+ 0xb2, 0xe6, 0x0e, 0x1f, 0x62, 0xd4, 0xa8, 0x96, 0xf9, 0xc5, 0x25, 0x59, 0x84, 0x72, 0x39, 0x4c,
+ 0x5e, 0x78, 0x38, 0x8c, 0xd1, 0xa5, 0xe2, 0x61, 0xb3, 0x21, 0x9c, 0x1e, 0x43, 0xc7, 0xfc, 0x04,
+ 0x51, 0x99, 0x6d, 0x0d, 0xfa, 0xdf, 0x7e, 0x24, 0x3b, 0xab, 0xce, 0x11, 0x8f, 0x4e, 0xb7, 0xeb,
+ 0x3c, 0x81, 0x94, 0xf7, 0xb9, 0x13, 0x2c, 0xd3, 0xe7, 0x6e, 0xc4, 0x03, 0x56, 0x44, 0x7f, 0xa9,
+ 0x2a, 0xbb, 0xc1, 0x53, 0xdc, 0x0b, 0x9d, 0x6c, 0x31, 0x74, 0xf6, 0x46, 0xac, 0x89, 0x14, 0xe1,
+ 0x16, 0x3a, 0x69, 0x09, 0x70, 0xb6, 0xd0, 0xed, 0xcc, 0x42, 0x98, 0xa4, 0x28, 0x5c, 0xf8, 0x86
+ };
+
+ private static final long[] C0 = new long[256];
+ private static final long[] C1 = new long[256];
+ private static final long[] C2 = new long[256];
+ private static final long[] C3 = new long[256];
+ private static final long[] C4 = new long[256];
+ private static final long[] C5 = new long[256];
+ private static final long[] C6 = new long[256];
+ private static final long[] C7 = new long[256];
+
+ private final long[] _rc = new long[ROUNDS + 1];
+
+ public WhirlpoolDigest()
+ {
+ for (int i = 0; i < 256; i++)
+ {
+ int v1 = SBOX[i];
+ int v2 = maskWithReductionPolynomial(v1 << 1);
+ int v4 = maskWithReductionPolynomial(v2 << 1);
+ int v5 = v4 ^ v1;
+ int v8 = maskWithReductionPolynomial(v4 << 1);
+ int v9 = v8 ^ v1;
+
+ C0[i] = packIntoLong(v1, v1, v4, v1, v8, v5, v2, v9);
+ C1[i] = packIntoLong(v9, v1, v1, v4, v1, v8, v5, v2);
+ C2[i] = packIntoLong(v2, v9, v1, v1, v4, v1, v8, v5);
+ C3[i] = packIntoLong(v5, v2, v9, v1, v1, v4, v1, v8);
+ C4[i] = packIntoLong(v8, v5, v2, v9, v1, v1, v4, v1);
+ C5[i] = packIntoLong(v1, v8, v5, v2, v9, v1, v1, v4);
+ C6[i] = packIntoLong(v4, v1, v8, v5, v2, v9, v1, v1);
+ C7[i] = packIntoLong(v1, v4, v1, v8, v5, v2, v9, v1);
+
+ }
+
+ _rc[0] = 0L;
+ for (int r = 1; r <= ROUNDS; r++)
+ {
+ int i = 8 * (r - 1);
+ _rc[r] = (C0[i ] & 0xff00000000000000L) ^
+ (C1[i + 1] & 0x00ff000000000000L) ^
+ (C2[i + 2] & 0x0000ff0000000000L) ^
+ (C3[i + 3] & 0x000000ff00000000L) ^
+ (C4[i + 4] & 0x00000000ff000000L) ^
+ (C5[i + 5] & 0x0000000000ff0000L) ^
+ (C6[i + 6] & 0x000000000000ff00L) ^
+ (C7[i + 7] & 0x00000000000000ffL);
+ }
+
+ }
+
+ private long packIntoLong(int b7, int b6, int b5, int b4, int b3, int b2, int b1, int b0)
+ {
+ return
+ ((long)b7 << 56) ^
+ ((long)b6 << 48) ^
+ ((long)b5 << 40) ^
+ ((long)b4 << 32) ^
+ ((long)b3 << 24) ^
+ ((long)b2 << 16) ^
+ ((long)b1 << 8) ^
+ b0;
+ }
+
+ /*
+ * int's are used to prevent sign extension. The values that are really being used are
+ * actually just 0..255
+ */
+ private int maskWithReductionPolynomial(int input)
+ {
+ int rv = input;
+ if (rv >= 0x100L) // high bit set
+ {
+ rv ^= REDUCTION_POLYNOMIAL; // reduced by the polynomial
+ }
+ return rv;
+ }
+
+ // --------------------------------------------------------------------------------------//
+
+ // -- buffer information --
+ private static final int BITCOUNT_ARRAY_SIZE = 32;
+ private byte[] _buffer = new byte[64];
+ private int _bufferPos = 0;
+ private short[] _bitCount = new short[BITCOUNT_ARRAY_SIZE];
+
+ // -- internal hash state --
+ private long[] _hash = new long[8];
+ private long[] _K = new long[8]; // the round key
+ private long[] _L = new long[8];
+ private long[] _block = new long[8]; // mu (buffer)
+ private long[] _state = new long[8]; // the current "cipher" state
+
+
+
+ /**
+ * Copy constructor. This will copy the state of the provided message
+ * digest.
+ */
+ public WhirlpoolDigest(WhirlpoolDigest originalDigest)
+ {
+ System.arraycopy(originalDigest._rc, 0, _rc, 0, _rc.length);
+
+ System.arraycopy(originalDigest._buffer, 0, _buffer, 0, _buffer.length);
+
+ this._bufferPos = originalDigest._bufferPos;
+ System.arraycopy(originalDigest._bitCount, 0, _bitCount, 0, _bitCount.length);
+
+ // -- internal hash state --
+ System.arraycopy(originalDigest._hash, 0, _hash, 0, _hash.length);
+ System.arraycopy(originalDigest._K, 0, _K, 0, _K.length);
+ System.arraycopy(originalDigest._L, 0, _L, 0, _L.length);
+ System.arraycopy(originalDigest._block, 0, _block, 0, _block.length);
+ System.arraycopy(originalDigest._state, 0, _state, 0, _state.length);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Whirlpool";
+ }
+
+ public int getDigestSize()
+ {
+ return DIGEST_LENGTH_BYTES;
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ // sets out[outOff] .. out[outOff+DIGEST_LENGTH_BYTES]
+ finish();
+
+ for (int i = 0; i < 8; i++)
+ {
+ convertLongToByteArray(_hash[i], out, outOff + (i * 8));
+ }
+
+ reset();
+ return getDigestSize();
+ }
+
+ /**
+ * reset the chaining variables
+ */
+ public void reset()
+ {
+ // set variables to null, blank, whatever
+ _bufferPos = 0;
+ Arrays.fill(_bitCount, (short)0);
+ Arrays.fill(_buffer, (byte)0);
+ Arrays.fill(_hash, 0);
+ Arrays.fill(_K, 0);
+ Arrays.fill(_L, 0);
+ Arrays.fill(_block, 0);
+ Arrays.fill(_state, 0);
+ }
+
+ // this takes a buffer of information and fills the block
+ private void processFilledBuffer(byte[] in, int inOff)
+ {
+ // copies into the block...
+ for (int i = 0; i < _state.length; i++)
+ {
+ _block[i] = bytesToLongFromBuffer(_buffer, i * 8);
+ }
+ processBlock();
+ _bufferPos = 0;
+ Arrays.fill(_buffer, (byte)0);
+ }
+
+ private long bytesToLongFromBuffer(byte[] buffer, int startPos)
+ {
+ long rv = (((buffer[startPos + 0] & 0xffL) << 56) |
+ ((buffer[startPos + 1] & 0xffL) << 48) |
+ ((buffer[startPos + 2] & 0xffL) << 40) |
+ ((buffer[startPos + 3] & 0xffL) << 32) |
+ ((buffer[startPos + 4] & 0xffL) << 24) |
+ ((buffer[startPos + 5] & 0xffL) << 16) |
+ ((buffer[startPos + 6] & 0xffL) << 8) |
+ ((buffer[startPos + 7]) & 0xffL));
+
+ return rv;
+ }
+
+ private void convertLongToByteArray(long inputLong, byte[] outputArray, int offSet)
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ outputArray[offSet + i] = (byte)((inputLong >> (56 - (i * 8))) & 0xff);
+ }
+ }
+
+ protected void processBlock()
+ {
+ // buffer contents have been transferred to the _block[] array via
+ // processFilledBuffer
+
+ // compute and apply K^0
+ for (int i = 0; i < 8; i++)
+ {
+ _state[i] = _block[i] ^ (_K[i] = _hash[i]);
+ }
+
+ // iterate over the rounds
+ for (int round = 1; round <= ROUNDS; round++)
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ _L[i] = 0;
+ _L[i] ^= C0[(int)(_K[(i - 0) & 7] >>> 56) & 0xff];
+ _L[i] ^= C1[(int)(_K[(i - 1) & 7] >>> 48) & 0xff];
+ _L[i] ^= C2[(int)(_K[(i - 2) & 7] >>> 40) & 0xff];
+ _L[i] ^= C3[(int)(_K[(i - 3) & 7] >>> 32) & 0xff];
+ _L[i] ^= C4[(int)(_K[(i - 4) & 7] >>> 24) & 0xff];
+ _L[i] ^= C5[(int)(_K[(i - 5) & 7] >>> 16) & 0xff];
+ _L[i] ^= C6[(int)(_K[(i - 6) & 7] >>> 8) & 0xff];
+ _L[i] ^= C7[(int)(_K[(i - 7) & 7]) & 0xff];
+ }
+
+ System.arraycopy(_L, 0, _K, 0, _K.length);
+
+ _K[0] ^= _rc[round];
+
+ // apply the round transformation
+ for (int i = 0; i < 8; i++)
+ {
+ _L[i] = _K[i];
+
+ _L[i] ^= C0[(int)(_state[(i - 0) & 7] >>> 56) & 0xff];
+ _L[i] ^= C1[(int)(_state[(i - 1) & 7] >>> 48) & 0xff];
+ _L[i] ^= C2[(int)(_state[(i - 2) & 7] >>> 40) & 0xff];
+ _L[i] ^= C3[(int)(_state[(i - 3) & 7] >>> 32) & 0xff];
+ _L[i] ^= C4[(int)(_state[(i - 4) & 7] >>> 24) & 0xff];
+ _L[i] ^= C5[(int)(_state[(i - 5) & 7] >>> 16) & 0xff];
+ _L[i] ^= C6[(int)(_state[(i - 6) & 7] >>> 8) & 0xff];
+ _L[i] ^= C7[(int)(_state[(i - 7) & 7]) & 0xff];
+ }
+
+ // save the current state
+ System.arraycopy(_L, 0, _state, 0, _state.length);
+ }
+
+ // apply Miuaguchi-Preneel compression
+ for (int i = 0; i < 8; i++)
+ {
+ _hash[i] ^= _state[i] ^ _block[i];
+ }
+
+ }
+
+ public void update(byte in)
+ {
+ _buffer[_bufferPos] = in;
+
+ //System.out.println("adding to buffer = "+_buffer[_bufferPos]);
+
+ ++_bufferPos;
+
+ if (_bufferPos == _buffer.length)
+ {
+ processFilledBuffer(_buffer, 0);
+ }
+
+ increment();
+ }
+
+ /*
+ * increment() can be implemented in this way using 2 arrays or
+ * by having some temporary variables that are used to set the
+ * value provided by EIGHT[i] and carry within the loop.
+ *
+ * not having done any timing, this seems likely to be faster
+ * at the slight expense of 32*(sizeof short) bytes
+ */
+ private static final short[] EIGHT = new short[BITCOUNT_ARRAY_SIZE];
+ static
+ {
+ EIGHT[BITCOUNT_ARRAY_SIZE - 1] = 8;
+ }
+
+ private void increment()
+ {
+ int carry = 0;
+ for (int i = _bitCount.length - 1; i >= 0; i--)
+ {
+ int sum = (_bitCount[i] & 0xff) + EIGHT[i] + carry;
+
+ carry = sum >>> 8;
+ _bitCount[i] = (short)(sum & 0xff);
+ }
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ while (len > 0)
+ {
+ update(in[inOff]);
+ ++inOff;
+ --len;
+ }
+
+ }
+
+ private void finish()
+ {
+ /*
+ * this makes a copy of the current bit length. at the expense of an
+ * object creation of 32 bytes rather than providing a _stopCounting
+ * boolean which was the alternative I could think of.
+ */
+ byte[] bitLength = copyBitLength();
+
+ _buffer[_bufferPos++] |= 0x80;
+
+ if (_bufferPos == _buffer.length)
+ {
+ processFilledBuffer(_buffer, 0);
+ }
+
+ /*
+ * Final block contains
+ * [ ... data .... ][0][0][0][ length ]
+ *
+ * if [ length ] cannot fit. Need to create a new block.
+ */
+ if (_bufferPos > 32)
+ {
+ while (_bufferPos != 0)
+ {
+ update((byte)0);
+ }
+ }
+
+ while (_bufferPos <= 32)
+ {
+ update((byte)0);
+ }
+
+ // copy the length information to the final 32 bytes of the
+ // 64 byte block....
+ System.arraycopy(bitLength, 0, _buffer, 32, bitLength.length);
+
+ processFilledBuffer(_buffer, 0);
+ }
+
+ private byte[] copyBitLength()
+ {
+ byte[] rv = new byte[BITCOUNT_ARRAY_SIZE];
+ for (int i = 0; i < rv.length; i++)
+ {
+ rv[i] = (byte)(_bitCount[i] & 0xff);
+ }
+ return rv;
+ }
+
+ public int getByteLength()
+ {
+ return BYTE_LENGTH;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/digests/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/digests/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Message digest classes.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/encodings/ISO9796d1Encoding.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,287 @@
+package pdftk.org.bouncycastle.crypto.encodings;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+
+/**
+ * ISO 9796-1 padding. Note in the light of recent results you should
+ * only use this with RSA (rather than the "simpler" Rabin keys) and you
+ * should never use it with anything other than a hash (ie. even if the
+ * message is small don't sign the message, sign it's hash) or some "random"
+ * value. See your favorite search engine for details.
+ */
+public class ISO9796d1Encoding
+ implements AsymmetricBlockCipher
+{
+ private static final BigInteger SIXTEEN = BigInteger.valueOf(16L);
+ private static final BigInteger SIX = BigInteger.valueOf(6L);
+
+ private static byte[] shadows = { 0xe, 0x3, 0x5, 0x8, 0x9, 0x4, 0x2, 0xf,
+ 0x0, 0xd, 0xb, 0x6, 0x7, 0xa, 0xc, 0x1 };
+ private static byte[] inverse = { 0x8, 0xf, 0x6, 0x1, 0x5, 0x2, 0xb, 0xc,
+ 0x3, 0x4, 0xd, 0xa, 0xe, 0x9, 0x0, 0x7 };
+
+ private AsymmetricBlockCipher engine;
+ private boolean forEncryption;
+ private int bitSize;
+ private int padBits = 0;
+ private BigInteger modulus;
+
+ public ISO9796d1Encoding(
+ AsymmetricBlockCipher cipher)
+ {
+ this.engine = cipher;
+ }
+
+ public AsymmetricBlockCipher getUnderlyingCipher()
+ {
+ return engine;
+ }
+
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ RSAKeyParameters kParam = null;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ kParam = (RSAKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ kParam = (RSAKeyParameters)param;
+ }
+
+ engine.init(forEncryption, param);
+
+ modulus = kParam.getModulus();
+ bitSize = modulus.bitLength();
+
+ this.forEncryption = forEncryption;
+ }
+
+ /**
+ * return the input block size. The largest message we can process
+ * is (key_size_in_bits + 3)/16, which in our world comes to
+ * key_size_in_bytes / 2.
+ */
+ public int getInputBlockSize()
+ {
+ int baseBlockSize = engine.getInputBlockSize();
+
+ if (forEncryption)
+ {
+ return (baseBlockSize + 1) / 2;
+ }
+ else
+ {
+ return baseBlockSize;
+ }
+ }
+
+ /**
+ * return the maximum possible size for the output.
+ */
+ public int getOutputBlockSize()
+ {
+ int baseBlockSize = engine.getOutputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize;
+ }
+ else
+ {
+ return (baseBlockSize + 1) / 2;
+ }
+ }
+
+ /**
+ * set the number of bits in the next message to be treated as
+ * pad bits.
+ */
+ public void setPadBits(
+ int padBits)
+ {
+ if (padBits > 7)
+ {
+ throw new IllegalArgumentException("padBits > 7");
+ }
+
+ this.padBits = padBits;
+ }
+
+ /**
+ * retrieve the number of pad bits in the last decoded message.
+ */
+ public int getPadBits()
+ {
+ return padBits;
+ }
+
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forEncryption)
+ {
+ return encodeBlock(in, inOff, inLen);
+ }
+ else
+ {
+ return decodeBlock(in, inOff, inLen);
+ }
+ }
+
+ private byte[] encodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] block = new byte[(bitSize + 7) / 8];
+ int r = padBits + 1;
+ int z = inLen;
+ int t = (bitSize + 13) / 16;
+
+ for (int i = 0; i < t; i += z)
+ {
+ if (i > t - z)
+ {
+ System.arraycopy(in, inOff + inLen - (t - i),
+ block, block.length - t, t - i);
+ }
+ else
+ {
+ System.arraycopy(in, inOff, block, block.length - (i + z), z);
+ }
+ }
+
+ for (int i = block.length - 2 * t; i != block.length; i += 2)
+ {
+ byte val = block[block.length - t + i / 2];
+
+ block[i] = (byte)((shadows[(val & 0xff) >>> 4] << 4)
+ | shadows[val & 0x0f]);
+ block[i + 1] = val;
+ }
+
+ block[block.length - 2 * z] ^= r;
+ block[block.length - 1] = (byte)((block[block.length - 1] << 4) | 0x06);
+
+ int maxBit = (8 - (bitSize - 1) % 8);
+ int offSet = 0;
+
+ if (maxBit != 8)
+ {
+ block[0] &= 0xff >>> maxBit;
+ block[0] |= 0x80 >>> maxBit;
+ }
+ else
+ {
+ block[0] = 0x00;
+ block[1] |= 0x80;
+ offSet = 1;
+ }
+
+ return engine.processBlock(block, offSet, block.length - offSet);
+ }
+
+ /**
+ * @exception InvalidCipherTextException if the decrypted block is not a valid ISO 9796 bit string
+ */
+ private byte[] decodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] block = engine.processBlock(in, inOff, inLen);
+ int r = 1;
+ int t = (bitSize + 13) / 16;
+
+ BigInteger iS = new BigInteger(1, block);
+ BigInteger iR;
+ if (iS.mod(SIXTEEN).equals(SIX))
+ {
+ iR = iS;
+ }
+ else if ((modulus.subtract(iS)).mod(SIXTEEN).equals(SIX))
+ {
+ iR = modulus.subtract(iS);
+ }
+ else
+ {
+ throw new InvalidCipherTextException("resulting integer iS or (modulus - iS) is not congruent to 6 mod 16");
+ }
+
+ block = convertOutputDecryptOnly(iR);
+
+ if ((block[block.length - 1] & 0x0f) != 0x6 )
+ {
+ throw new InvalidCipherTextException("invalid forcing byte in block");
+ }
+
+ block[block.length - 1] = (byte)(((block[block.length - 1] & 0xff) >>> 4) | ((inverse[(block[block.length - 2] & 0xff) >> 4]) << 4));
+ block[0] = (byte)((shadows[(block[1] & 0xff) >>> 4] << 4)
+ | shadows[block[1] & 0x0f]);
+
+ boolean boundaryFound = false;
+ int boundary = 0;
+
+ for (int i = block.length - 1; i >= block.length - 2 * t; i -= 2)
+ {
+ int val = ((shadows[(block[i] & 0xff) >>> 4] << 4)
+ | shadows[block[i] & 0x0f]);
+
+ if (((block[i - 1] ^ val) & 0xff) != 0)
+ {
+ if (!boundaryFound)
+ {
+ boundaryFound = true;
+ r = (block[i - 1] ^ val) & 0xff;
+ boundary = i - 1;
+ }
+ else
+ {
+ throw new InvalidCipherTextException("invalid tsums in block");
+ }
+ }
+ }
+
+ block[boundary] = 0;
+
+ byte[] nblock = new byte[(block.length - boundary) / 2];
+
+ for (int i = 0; i < nblock.length; i++)
+ {
+ nblock[i] = block[2 * i + boundary + 1];
+ }
+
+ padBits = r - 1;
+
+ return nblock;
+ }
+
+ private static byte[] convertOutputDecryptOnly(BigInteger result)
+ {
+ byte[] output = result.toByteArray();
+ if (output[0] == 0) // have ended up with an extra zero byte, copy down.
+ {
+ byte[] tmp = new byte[output.length - 1];
+ System.arraycopy(output, 1, tmp, 0, tmp.length);
+ return tmp;
+ }
+ return output;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/encodings/OAEPEncoding.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/encodings/OAEPEncoding.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/encodings/OAEPEncoding.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/encodings/OAEPEncoding.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,348 @@
+package pdftk.org.bouncycastle.crypto.encodings;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+
+import java.security.SecureRandom;
+
+/**
+ * Optimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2.
+ */
+public class OAEPEncoding
+ implements AsymmetricBlockCipher
+{
+ private byte[] defHash;
+ private Digest hash;
+ private Digest mgf1Hash;
+
+ private AsymmetricBlockCipher engine;
+ private SecureRandom random;
+ private boolean forEncryption;
+
+ public OAEPEncoding(
+ AsymmetricBlockCipher cipher)
+ {
+ this(cipher, new SHA1Digest(), null);
+ }
+
+ public OAEPEncoding(
+ AsymmetricBlockCipher cipher,
+ Digest hash)
+ {
+ this(cipher, hash, null);
+ }
+
+ public OAEPEncoding(
+ AsymmetricBlockCipher cipher,
+ Digest hash,
+ byte[] encodingParams)
+ {
+ this(cipher, hash, hash, encodingParams);
+ }
+
+ public OAEPEncoding(
+ AsymmetricBlockCipher cipher,
+ Digest hash,
+ Digest mgf1Hash,
+ byte[] encodingParams)
+ {
+ this.engine = cipher;
+ this.hash = hash;
+ this.mgf1Hash = mgf1Hash;
+ this.defHash = new byte[hash.getDigestSize()];
+
+ if (encodingParams != null)
+ {
+ hash.update(encodingParams, 0, encodingParams.length);
+ }
+
+ hash.doFinal(defHash, 0);
+ }
+
+ public AsymmetricBlockCipher getUnderlyingCipher()
+ {
+ return engine;
+ }
+
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ }
+
+ engine.init(forEncryption, param);
+
+ this.forEncryption = forEncryption;
+ }
+
+ public int getInputBlockSize()
+ {
+ int baseBlockSize = engine.getInputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize - 1 - 2 * defHash.length;
+ }
+ else
+ {
+ return baseBlockSize;
+ }
+ }
+
+ public int getOutputBlockSize()
+ {
+ int baseBlockSize = engine.getOutputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize;
+ }
+ else
+ {
+ return baseBlockSize - 1 - 2 * defHash.length;
+ }
+ }
+
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forEncryption)
+ {
+ return encodeBlock(in, inOff, inLen);
+ }
+ else
+ {
+ return decodeBlock(in, inOff, inLen);
+ }
+ }
+
+ public byte[] encodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] block = new byte[getInputBlockSize() + 1 + 2 * defHash.length];
+
+ //
+ // copy in the message
+ //
+ System.arraycopy(in, inOff, block, block.length - inLen, inLen);
+
+ //
+ // add sentinel
+ //
+ block[block.length - inLen - 1] = 0x01;
+
+ //
+ // as the block is already zeroed - there's no need to add PS (the >= 0 pad of 0)
+ //
+
+ //
+ // add the hash of the encoding params.
+ //
+ System.arraycopy(defHash, 0, block, defHash.length, defHash.length);
+
+ //
+ // generate the seed.
+ //
+ byte[] seed = new byte[defHash.length];
+
+ random.nextBytes(seed);
+
+ //
+ // mask the message block.
+ //
+ byte[] mask = maskGeneratorFunction1(seed, 0, seed.length, block.length - defHash.length);
+
+ for (int i = defHash.length; i != block.length; i++)
+ {
+ block[i] ^= mask[i - defHash.length];
+ }
+
+ //
+ // add in the seed
+ //
+ System.arraycopy(seed, 0, block, 0, defHash.length);
+
+ //
+ // mask the seed.
+ //
+ mask = maskGeneratorFunction1(
+ block, defHash.length, block.length - defHash.length, defHash.length);
+
+ for (int i = 0; i != defHash.length; i++)
+ {
+ block[i] ^= mask[i];
+ }
+
+ return engine.processBlock(block, 0, block.length);
+ }
+
+ /**
+ * @exception InvalidCipherTextException if the decrypted block turns out to
+ * be badly formatted.
+ */
+ public byte[] decodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] data = engine.processBlock(in, inOff, inLen);
+ byte[] block;
+
+ //
+ // as we may have zeros in our leading bytes for the block we produced
+ // on encryption, we need to make sure our decrypted block comes back
+ // the same size.
+ //
+ if (data.length < engine.getOutputBlockSize())
+ {
+ block = new byte[engine.getOutputBlockSize()];
+
+ System.arraycopy(data, 0, block, block.length - data.length, data.length);
+ }
+ else
+ {
+ block = data;
+ }
+
+ if (block.length < (2 * defHash.length) + 1)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+
+ //
+ // unmask the seed.
+ //
+ byte[] mask = maskGeneratorFunction1(
+ block, defHash.length, block.length - defHash.length, defHash.length);
+
+ for (int i = 0; i != defHash.length; i++)
+ {
+ block[i] ^= mask[i];
+ }
+
+ //
+ // unmask the message block.
+ //
+ mask = maskGeneratorFunction1(block, 0, defHash.length, block.length - defHash.length);
+
+ for (int i = defHash.length; i != block.length; i++)
+ {
+ block[i] ^= mask[i - defHash.length];
+ }
+
+ //
+ // check the hash of the encoding params.
+ //
+ for (int i = 0; i != defHash.length; i++)
+ {
+ if (defHash[i] != block[defHash.length + i])
+ {
+ throw new InvalidCipherTextException("data hash wrong");
+ }
+ }
+
+ //
+ // find the data block
+ //
+ int start;
+
+ for (start = 2 * defHash.length; start != block.length; start++)
+ {
+ if (block[start] != 0)
+ {
+ break;
+ }
+ }
+
+ if (start >= (block.length - 1) || block[start] != 1)
+ {
+ throw new InvalidCipherTextException("data start wrong " + start);
+ }
+
+ start++;
+
+ //
+ // extract the data block
+ //
+ byte[] output = new byte[block.length - start];
+
+ System.arraycopy(block, start, output, 0, output.length);
+
+ return output;
+ }
+
+ /**
+ * int to octet string.
+ */
+ private void ItoOSP(
+ int i,
+ byte[] sp)
+ {
+ sp[0] = (byte)(i >>> 24);
+ sp[1] = (byte)(i >>> 16);
+ sp[2] = (byte)(i >>> 8);
+ sp[3] = (byte)(i >>> 0);
+ }
+
+ /**
+ * mask generator function, as described in PKCS1v2.
+ */
+ private byte[] maskGeneratorFunction1(
+ byte[] Z,
+ int zOff,
+ int zLen,
+ int length)
+ {
+ byte[] mask = new byte[length];
+ byte[] hashBuf = new byte[mgf1Hash.getDigestSize()];
+ byte[] C = new byte[4];
+ int counter = 0;
+
+ hash.reset();
+
+ do
+ {
+ ItoOSP(counter, C);
+
+ mgf1Hash.update(Z, zOff, zLen);
+ mgf1Hash.update(C, 0, C.length);
+ mgf1Hash.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, mask, counter * hashBuf.length, hashBuf.length);
+ }
+ while (++counter < (length / hashBuf.length));
+
+ if ((counter * hashBuf.length) < length)
+ {
+ ItoOSP(counter, C);
+
+ mgf1Hash.update(Z, zOff, zLen);
+ mgf1Hash.update(C, 0, C.length);
+ mgf1Hash.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, mask, counter * hashBuf.length, mask.length - (counter * hashBuf.length));
+ }
+
+ return mask;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/encodings/PKCS1Encoding.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/encodings/PKCS1Encoding.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/encodings/PKCS1Encoding.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/encodings/PKCS1Encoding.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,257 @@
+package pdftk.org.bouncycastle.crypto.encodings;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this
+ * depends on your application - see PKCS1 Version 2 for details.
+ */
+public class PKCS1Encoding
+ implements AsymmetricBlockCipher
+{
+ /**
+ * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
+ * work with one of these set the system property pdftk.org.bouncycastle.pkcs1.strict to false.
+ *
+ * The system property is checked during construction of the encoding object, it is set to
+ * true by default.
+ *
+ */
+ public static final String STRICT_LENGTH_ENABLED_PROPERTY = "pdftk.org.bouncycastle.pkcs1.strict";
+
+ private static final int HEADER_LENGTH = 10;
+
+ private SecureRandom random;
+ private AsymmetricBlockCipher engine;
+ private boolean forEncryption;
+ private boolean forPrivateKey;
+ private boolean useStrictLength;
+
+ /**
+ * Basic constructor.
+ * @param cipher
+ */
+ public PKCS1Encoding(
+ AsymmetricBlockCipher cipher)
+ {
+ this.engine = cipher;
+ this.useStrictLength = useStrict();
+ }
+
+ //
+ // for J2ME compatibility
+ //
+ private boolean useStrict()
+ {
+ // required if security manager has been installed.
+ String strict = (String)AccessController.doPrivileged(new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY);
+ }
+ });
+
+ return strict == null || strict.equals("true");
+ }
+
+ public AsymmetricBlockCipher getUnderlyingCipher()
+ {
+ return engine;
+ }
+
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ AsymmetricKeyParameter kParam;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ kParam = (AsymmetricKeyParameter)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ kParam = (AsymmetricKeyParameter)param;
+ }
+
+ engine.init(forEncryption, param);
+
+ this.forPrivateKey = kParam.isPrivate();
+ this.forEncryption = forEncryption;
+ }
+
+ public int getInputBlockSize()
+ {
+ int baseBlockSize = engine.getInputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize - HEADER_LENGTH;
+ }
+ else
+ {
+ return baseBlockSize;
+ }
+ }
+
+ public int getOutputBlockSize()
+ {
+ int baseBlockSize = engine.getOutputBlockSize();
+
+ if (forEncryption)
+ {
+ return baseBlockSize;
+ }
+ else
+ {
+ return baseBlockSize - HEADER_LENGTH;
+ }
+ }
+
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forEncryption)
+ {
+ return encodeBlock(in, inOff, inLen);
+ }
+ else
+ {
+ return decodeBlock(in, inOff, inLen);
+ }
+ }
+
+ private byte[] encodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (inLen > getInputBlockSize())
+ {
+ throw new IllegalArgumentException("input data too large");
+ }
+
+ byte[] block = new byte[engine.getInputBlockSize()];
+
+ if (forPrivateKey)
+ {
+ block[0] = 0x01; // type code 1
+
+ for (int i = 1; i != block.length - inLen - 1; i++)
+ {
+ block[i] = (byte)0xFF;
+ }
+ }
+ else
+ {
+ random.nextBytes(block); // random fill
+
+ block[0] = 0x02; // type code 2
+
+ //
+ // a zero byte marks the end of the padding, so all
+ // the pad bytes must be non-zero.
+ //
+ for (int i = 1; i != block.length - inLen - 1; i++)
+ {
+ while (block[i] == 0)
+ {
+ block[i] = (byte)random.nextInt();
+ }
+ }
+ }
+
+ block[block.length - inLen - 1] = 0x00; // mark the end of the padding
+ System.arraycopy(in, inOff, block, block.length - inLen, inLen);
+
+ return engine.processBlock(block, 0, block.length);
+ }
+
+ /**
+ * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format.
+ */
+ private byte[] decodeBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] block = engine.processBlock(in, inOff, inLen);
+
+ if (block.length < getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block truncated");
+ }
+
+ byte type = block[0];
+
+ if (forPrivateKey)
+ {
+ if (type != 2)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
+ }
+ else
+ {
+ if (type != 1)
+ {
+ throw new InvalidCipherTextException("unknown block type");
+ }
+ }
+
+ if (useStrictLength && block.length != engine.getOutputBlockSize())
+ {
+ throw new InvalidCipherTextException("block incorrect size");
+ }
+
+ //
+ // find and extract the message block.
+ //
+ int start;
+
+ for (start = 1; start != block.length; start++)
+ {
+ byte pad = block[start];
+
+ if (pad == 0)
+ {
+ break;
+ }
+ if (type == 1 && pad != (byte)0xff)
+ {
+ throw new InvalidCipherTextException("block padding incorrect");
+ }
+ }
+
+ start++; // data should start at the next byte
+
+ if (start > block.length || start < HEADER_LENGTH)
+ {
+ throw new InvalidCipherTextException("no data in block");
+ }
+
+ byte[] result = new byte[block.length - start];
+
+ System.arraycopy(block, start, result, 0, result.length);
+
+ return result;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/encodings/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/encodings/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/encodings/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/encodings/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Block encodings for asymmetric ciphers.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/AESEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/AESEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/AESEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/AESEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,545 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * an implementation of the AES (Rijndael), from FIPS-197.
+ *
+ * For further details see: http://csrc.nist.gov/encryption/aes/ .
+ *
+ * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael/
+ *
+ * There are three levels of tradeoff of speed vs memory
+ * Because java has no preprocessor, they are written as three separate classes from which to choose
+ *
+ * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+ * and 4 for decryption.
+ *
+ * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+ * adding 12 rotate operations per round to compute the values contained in the other tables from
+ * the contents of the first.
+ *
+ * The slowest version uses no static tables at all and computes the values in each round.
+ *
+ * This file contains the middle performance version with 2Kbytes of static tables for round precomputation.
+ *
+ */
+public class AESEngine
+ implements BlockCipher
+{
+ // The S box
+ private static final byte[] S = {
+ (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197,
+ (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
+ (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240,
+ (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
+ (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204,
+ (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
+ (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154,
+ (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
+ (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160,
+ (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
+ (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91,
+ (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
+ (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133,
+ (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
+ (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245,
+ (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
+ (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23,
+ (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
+ (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136,
+ (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
+ (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92,
+ (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
+ (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169,
+ (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
+ (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198,
+ (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
+ (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14,
+ (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
+ (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148,
+ (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
+ (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104,
+ (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
+ };
+
+ // The inverse S-box
+ private static final byte[] Si = {
+ (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56,
+ (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
+ (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135,
+ (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
+ (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61,
+ (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
+ (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178,
+ (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
+ (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22,
+ (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
+ (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218,
+ (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
+ (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10,
+ (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
+ (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2,
+ (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
+ (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234,
+ (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
+ (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133,
+ (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
+ (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137,
+ (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
+ (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32,
+ (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
+ (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49,
+ (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
+ (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13,
+ (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
+ (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176,
+ (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
+ (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38,
+ (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
+ };
+
+ // vector used in calculating key schedule (powers of x in GF(256))
+ private static final int[] rcon = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+ 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
+
+ // precomputation tables of calculations for rounds
+ private static final int[] T0 =
+ {
+ 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
+ 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
+ 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
+ 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
+ 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
+ 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
+ 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
+ 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
+ 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
+ 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
+ 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
+ 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
+ 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
+ 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
+ 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
+ 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
+ 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
+ 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
+ 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
+ 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
+ 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
+ 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
+ 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
+ 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
+ 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
+ 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
+ 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
+ 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
+ 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
+ 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
+ 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
+ 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
+ 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
+ 0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
+ 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
+ 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
+ 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
+ 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
+ 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
+ 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
+ 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
+ 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
+ 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
+ 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
+ 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
+ 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
+ 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
+ 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
+ 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
+ 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
+ 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
+ 0x3a16162c};
+
+private static final int[] Tinv0 =
+ {
+ 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
+ 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
+ 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
+ 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
+ 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03,
+ 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
+ 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899,
+ 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
+ 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1,
+ 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f,
+ 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3,
+ 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
+ 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a,
+ 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506,
+ 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05,
+ 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
+ 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491,
+ 0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
+ 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7,
+ 0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
+ 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd,
+ 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68,
+ 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, 0xd296eeb4,
+ 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
+ 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e,
+ 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af,
+ 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644,
+ 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
+ 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85,
+ 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
+ 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411,
+ 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
+ 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6,
+ 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0x0d927850,
+ 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e,
+ 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
+ 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd,
+ 0xf418596e, 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa,
+ 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea,
+ 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
+ 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1,
+ 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
+ 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1,
+ 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
+ 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a,
+ 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7,
+ 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418,
+ 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
+ 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
+ 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
+ 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
+ 0x4257b8d0};
+
+ private static int shift(int r, int shift)
+ {
+ return (r >>> shift) | (r << -shift);
+ }
+
+ /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+ private static final int m1 = 0x80808080;
+ private static final int m2 = 0x7f7f7f7f;
+ private static final int m3 = 0x0000001b;
+
+ private static int FFmulX(int x)
+ {
+ return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
+ }
+
+ /*
+ The following defines provide alternative definitions of FFmulX that might
+ give improved performance if a fast 32-bit multiply is not available.
+
+ private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
+ private static final int m4 = 0x1b1b1b1b;
+ private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
+
+ */
+
+ private static int inv_mcol(int x)
+ {
+ int f2 = FFmulX(x);
+ int f4 = FFmulX(f2);
+ int f8 = FFmulX(f4);
+ int f9 = x ^ f8;
+
+ return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
+ }
+
+ private static int subWord(int x)
+ {
+ return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24);
+ }
+
+ /**
+ * Calculate the necessary round keys
+ * The number of calculations depends on key size and block size
+ * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+ * This code is written assuming those are the only possible values
+ */
+ private int[][] generateWorkingKey(
+ byte[] key,
+ boolean forEncryption)
+ {
+ int KC = key.length / 4; // key length in words
+ int t;
+
+ if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length))
+ {
+ throw new IllegalArgumentException("Key length not 128/192/256 bits.");
+ }
+
+ ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
+ int[][] W = new int[ROUNDS+1][4]; // 4 words in a block
+
+ //
+ // copy the key into the round key array
+ //
+
+ t = 0;
+ int i = 0;
+ while (i < key.length)
+ {
+ W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
+ i+=4;
+ t++;
+ }
+
+ //
+ // while not enough round key material calculated
+ // calculate new values
+ //
+ int k = (ROUNDS + 1) << 2;
+ for (i = KC; (i < k); i++)
+ {
+ int temp = W[(i-1)>>2][(i-1)&3];
+ if ((i % KC) == 0)
+ {
+ temp = subWord(shift(temp, 8)) ^ rcon[(i / KC)-1];
+ }
+ else if ((KC > 6) && ((i % KC) == 4))
+ {
+ temp = subWord(temp);
+ }
+
+ W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
+ }
+
+ if (!forEncryption)
+ {
+ for (int j = 1; j < ROUNDS; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ W[j][i] = inv_mcol(W[j][i]);
+ }
+ }
+ }
+
+ return W;
+ }
+
+ private int ROUNDS;
+ private int[][] WorkingKey = null;
+ private int C0, C1, C2, C3;
+ private boolean forEncryption;
+
+ private static final int BLOCK_SIZE = 16;
+
+ /**
+ * default constructor - 128 bit block size.
+ */
+ public AESEngine()
+ {
+ }
+
+ /**
+ * initialise an AES cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ WorkingKey = generateWorkingKey(((KeyParameter)params).getKey(), forEncryption);
+ this.forEncryption = forEncryption;
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to AES init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "AES";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (WorkingKey == null)
+ {
+ throw new IllegalStateException("AES engine not initialised");
+ }
+
+ if ((inOff + (32 / 2)) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + (32 / 2)) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (forEncryption)
+ {
+ unpackBlock(in, inOff);
+ encryptBlock(WorkingKey);
+ packBlock(out, outOff);
+ }
+ else
+ {
+ unpackBlock(in, inOff);
+ decryptBlock(WorkingKey);
+ packBlock(out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private void unpackBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ C0 = (bytes[index++] & 0xff);
+ C0 |= (bytes[index++] & 0xff) << 8;
+ C0 |= (bytes[index++] & 0xff) << 16;
+ C0 |= bytes[index++] << 24;
+
+ C1 = (bytes[index++] & 0xff);
+ C1 |= (bytes[index++] & 0xff) << 8;
+ C1 |= (bytes[index++] & 0xff) << 16;
+ C1 |= bytes[index++] << 24;
+
+ C2 = (bytes[index++] & 0xff);
+ C2 |= (bytes[index++] & 0xff) << 8;
+ C2 |= (bytes[index++] & 0xff) << 16;
+ C2 |= bytes[index++] << 24;
+
+ C3 = (bytes[index++] & 0xff);
+ C3 |= (bytes[index++] & 0xff) << 8;
+ C3 |= (bytes[index++] & 0xff) << 16;
+ C3 |= bytes[index++] << 24;
+ }
+
+ private void packBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ bytes[index++] = (byte)C0;
+ bytes[index++] = (byte)(C0 >> 8);
+ bytes[index++] = (byte)(C0 >> 16);
+ bytes[index++] = (byte)(C0 >> 24);
+
+ bytes[index++] = (byte)C1;
+ bytes[index++] = (byte)(C1 >> 8);
+ bytes[index++] = (byte)(C1 >> 16);
+ bytes[index++] = (byte)(C1 >> 24);
+
+ bytes[index++] = (byte)C2;
+ bytes[index++] = (byte)(C2 >> 8);
+ bytes[index++] = (byte)(C2 >> 16);
+ bytes[index++] = (byte)(C2 >> 24);
+
+ bytes[index++] = (byte)C3;
+ bytes[index++] = (byte)(C3 >> 8);
+ bytes[index++] = (byte)(C3 >> 16);
+ bytes[index++] = (byte)(C3 >> 24);
+ }
+
+
+ private void encryptBlock(int[][] KW)
+ {
+ int r, r0, r1, r2, r3;
+
+ C0 ^= KW[0][0];
+ C1 ^= KW[0][1];
+ C2 ^= KW[0][2];
+ C3 ^= KW[0][3];
+
+ r = 1;
+
+ while (r < ROUNDS - 1)
+ {
+ r0 = T0[C0&255] ^ shift(T0[(C1>>8)&255], 24) ^ shift(T0[(C2>>16)&255],16) ^ shift(T0[(C3>>24)&255],8) ^ KW[r][0];
+ r1 = T0[C1&255] ^ shift(T0[(C2>>8)&255], 24) ^ shift(T0[(C3>>16)&255], 16) ^ shift(T0[(C0>>24)&255], 8) ^ KW[r][1];
+ r2 = T0[C2&255] ^ shift(T0[(C3>>8)&255], 24) ^ shift(T0[(C0>>16)&255], 16) ^ shift(T0[(C1>>24)&255], 8) ^ KW[r][2];
+ r3 = T0[C3&255] ^ shift(T0[(C0>>8)&255], 24) ^ shift(T0[(C1>>16)&255], 16) ^ shift(T0[(C2>>24)&255], 8) ^ KW[r++][3];
+ C0 = T0[r0&255] ^ shift(T0[(r1>>8)&255], 24) ^ shift(T0[(r2>>16)&255], 16) ^ shift(T0[(r3>>24)&255], 8) ^ KW[r][0];
+ C1 = T0[r1&255] ^ shift(T0[(r2>>8)&255], 24) ^ shift(T0[(r3>>16)&255], 16) ^ shift(T0[(r0>>24)&255], 8) ^ KW[r][1];
+ C2 = T0[r2&255] ^ shift(T0[(r3>>8)&255], 24) ^ shift(T0[(r0>>16)&255], 16) ^ shift(T0[(r1>>24)&255], 8) ^ KW[r][2];
+ C3 = T0[r3&255] ^ shift(T0[(r0>>8)&255], 24) ^ shift(T0[(r1>>16)&255], 16) ^ shift(T0[(r2>>24)&255], 8) ^ KW[r++][3];
+ }
+
+ r0 = T0[C0&255] ^ shift(T0[(C1>>8)&255], 24) ^ shift(T0[(C2>>16)&255], 16) ^ shift(T0[(C3>>24)&255], 8) ^ KW[r][0];
+ r1 = T0[C1&255] ^ shift(T0[(C2>>8)&255], 24) ^ shift(T0[(C3>>16)&255], 16) ^ shift(T0[(C0>>24)&255], 8) ^ KW[r][1];
+ r2 = T0[C2&255] ^ shift(T0[(C3>>8)&255], 24) ^ shift(T0[(C0>>16)&255], 16) ^ shift(T0[(C1>>24)&255], 8) ^ KW[r][2];
+ r3 = T0[C3&255] ^ shift(T0[(C0>>8)&255], 24) ^ shift(T0[(C1>>16)&255], 16) ^ shift(T0[(C2>>24)&255], 8) ^ KW[r++][3];
+
+ // the final round's table is a simple function of S so we don't use a whole other four tables for it
+
+ C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0];
+ C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1];
+ C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2];
+ C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3];
+
+ }
+
+ private void decryptBlock(int[][] KW)
+ {
+ int r, r0, r1, r2, r3;
+
+ C0 ^= KW[ROUNDS][0];
+ C1 ^= KW[ROUNDS][1];
+ C2 ^= KW[ROUNDS][2];
+ C3 ^= KW[ROUNDS][3];
+
+ r = ROUNDS-1;
+
+ while (r>1)
+ {
+ r0 = Tinv0[C0&255] ^ shift(Tinv0[(C3>>8)&255], 24) ^ shift(Tinv0[(C2>>16)&255], 16) ^ shift(Tinv0[(C1>>24)&255], 8) ^ KW[r][0];
+ r1 = Tinv0[C1&255] ^ shift(Tinv0[(C0>>8)&255], 24) ^ shift(Tinv0[(C3>>16)&255], 16) ^ shift(Tinv0[(C2>>24)&255], 8) ^ KW[r][1];
+ r2 = Tinv0[C2&255] ^ shift(Tinv0[(C1>>8)&255], 24) ^ shift(Tinv0[(C0>>16)&255], 16) ^ shift(Tinv0[(C3>>24)&255], 8) ^ KW[r][2];
+ r3 = Tinv0[C3&255] ^ shift(Tinv0[(C2>>8)&255], 24) ^ shift(Tinv0[(C1>>16)&255], 16) ^ shift(Tinv0[(C0>>24)&255], 8) ^ KW[r--][3];
+ C0 = Tinv0[r0&255] ^ shift(Tinv0[(r3>>8)&255], 24) ^ shift(Tinv0[(r2>>16)&255], 16) ^ shift(Tinv0[(r1>>24)&255], 8) ^ KW[r][0];
+ C1 = Tinv0[r1&255] ^ shift(Tinv0[(r0>>8)&255], 24) ^ shift(Tinv0[(r3>>16)&255], 16) ^ shift(Tinv0[(r2>>24)&255], 8) ^ KW[r][1];
+ C2 = Tinv0[r2&255] ^ shift(Tinv0[(r1>>8)&255], 24) ^ shift(Tinv0[(r0>>16)&255], 16) ^ shift(Tinv0[(r3>>24)&255], 8) ^ KW[r][2];
+ C3 = Tinv0[r3&255] ^ shift(Tinv0[(r2>>8)&255], 24) ^ shift(Tinv0[(r1>>16)&255], 16) ^ shift(Tinv0[(r0>>24)&255], 8) ^ KW[r--][3];
+ }
+
+ r0 = Tinv0[C0&255] ^ shift(Tinv0[(C3>>8)&255], 24) ^ shift(Tinv0[(C2>>16)&255], 16) ^ shift(Tinv0[(C1>>24)&255], 8) ^ KW[r][0];
+ r1 = Tinv0[C1&255] ^ shift(Tinv0[(C0>>8)&255], 24) ^ shift(Tinv0[(C3>>16)&255], 16) ^ shift(Tinv0[(C2>>24)&255], 8) ^ KW[r][1];
+ r2 = Tinv0[C2&255] ^ shift(Tinv0[(C1>>8)&255], 24) ^ shift(Tinv0[(C0>>16)&255], 16) ^ shift(Tinv0[(C3>>24)&255], 8) ^ KW[r][2];
+ r3 = Tinv0[C3&255] ^ shift(Tinv0[(C2>>8)&255], 24) ^ shift(Tinv0[(C1>>16)&255], 16) ^ shift(Tinv0[(C0>>24)&255], 8) ^ KW[r][3];
+
+ // the final round's table is a simple function of Si so we don't use a whole other four tables for it
+
+ C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0];
+ C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1];
+ C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2];
+ C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3];
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/AESFastEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/AESFastEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/AESFastEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/AESFastEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,874 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * an implementation of the AES (Rijndael), from FIPS-197.
+ *
+ * For further details see: http://csrc.nist.gov/encryption/aes/ .
+ *
+ * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael/
+ *
+ * There are three levels of tradeoff of speed vs memory
+ * Because java has no preprocessor, they are written as three separate classes from which to choose
+ *
+ * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+ * and 4 for decryption.
+ *
+ * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+ * adding 12 rotate operations per round to compute the values contained in the other tables from
+ * the contents of the first
+ *
+ * The slowest version uses no static tables at all and computes the values in each round
+ *
+ * This file contains the fast version with 8Kbytes of static tables for round precomputation
+ *
+ */
+public class AESFastEngine
+ implements BlockCipher
+{
+ // The S box
+ private static final byte[] S = {
+ (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197,
+ (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
+ (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240,
+ (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
+ (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204,
+ (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
+ (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154,
+ (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
+ (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160,
+ (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
+ (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91,
+ (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
+ (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133,
+ (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
+ (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245,
+ (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
+ (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23,
+ (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
+ (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136,
+ (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
+ (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92,
+ (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
+ (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169,
+ (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
+ (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198,
+ (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
+ (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14,
+ (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
+ (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148,
+ (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
+ (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104,
+ (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
+ };
+
+ // The inverse S-box
+ private static final byte[] Si = {
+ (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56,
+ (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
+ (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135,
+ (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
+ (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61,
+ (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
+ (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178,
+ (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
+ (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22,
+ (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
+ (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218,
+ (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
+ (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10,
+ (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
+ (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2,
+ (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
+ (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234,
+ (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
+ (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133,
+ (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
+ (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137,
+ (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
+ (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32,
+ (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
+ (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49,
+ (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
+ (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13,
+ (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
+ (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176,
+ (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
+ (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38,
+ (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
+ };
+
+ // vector used in calculating key schedule (powers of x in GF(256))
+ private static final int[] rcon = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+ 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
+
+ // precomputation tables of calculations for rounds
+ private static final int[] T0 =
+ {
+ 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
+ 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
+ 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
+ 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
+ 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
+ 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
+ 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
+ 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
+ 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
+ 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
+ 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
+ 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
+ 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
+ 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
+ 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
+ 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
+ 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
+ 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
+ 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
+ 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
+ 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
+ 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
+ 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
+ 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
+ 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
+ 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
+ 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
+ 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
+ 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
+ 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
+ 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
+ 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
+ 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
+ 0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
+ 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
+ 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
+ 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
+ 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
+ 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
+ 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
+ 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
+ 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
+ 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
+ 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
+ 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
+ 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
+ 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
+ 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
+ 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
+ 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
+ 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
+ 0x3a16162c};
+
+ private static final int[] T1 =
+ {
+ 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d,
+ 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203,
+ 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6,
+ 0x7676ec9a, 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87,
+ 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, 0xadad41ec,
+ 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7,
+ 0x7272e496, 0xc0c09b5b, 0xb7b775c2, 0xfdfde11c, 0x93933dae,
+ 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f,
+ 0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, 0x7171e293,
+ 0xd8d8ab73, 0x31316253, 0x15152a3f, 0x0404080c, 0xc7c79552,
+ 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f,
+ 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
+ 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b,
+ 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2,
+ 0x5a5ab4ee, 0xa0a05bfb, 0x5252a4f6, 0x3b3b764d, 0xd6d6b761,
+ 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397,
+ 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060,
+ 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46,
+ 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8,
+ 0xcfcf854a, 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16,
+ 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, 0x45458acf,
+ 0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844,
+ 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe, 0x404080c0,
+ 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
+ 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030,
+ 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814,
+ 0x13132635, 0xececc32f, 0x5f5fbee1, 0x979735a2, 0x444488cc,
+ 0x17172e39, 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47,
+ 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, 0x6060c0a0,
+ 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e,
+ 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3,
+ 0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76,
+ 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db,
+ 0x06060c0a, 0x2424486c, 0x5c5cb8e4, 0xc2c29f5d, 0xd3d3bd6e,
+ 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337,
+ 0x7979f28b, 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
+ 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4,
+ 0x5656acfa, 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e,
+ 0xaeae47e9, 0x08081018, 0xbaba6fd5, 0x7878f088, 0x25254a6f,
+ 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751,
+ 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, 0x4b4b96dd,
+ 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42,
+ 0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701,
+ 0x0e0e1c12, 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0,
+ 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938,
+ 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970,
+ 0x8e8e0789, 0x949433a7, 0x9b9b2db6, 0x1e1e3c22, 0x87871592,
+ 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
+ 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da,
+ 0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0,
+ 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6,
+ 0x16162c3a};
+
+ private static final int[] T2 =
+ {
+ 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2,
+ 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301,
+ 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab,
+ 0x76ec9a76, 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d,
+ 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, 0xad41ecad,
+ 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4,
+ 0x72e49672, 0xc09b5bc0, 0xb775c2b7, 0xfde11cfd, 0x933dae93,
+ 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc,
+ 0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, 0x71e29371,
+ 0xd8ab73d8, 0x31625331, 0x152a3f15, 0x04080c04, 0xc79552c7,
+ 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05,
+ 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
+ 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09,
+ 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e,
+ 0x5ab4ee5a, 0xa05bfba0, 0x52a4f652, 0x3b764d3b, 0xd6b761d6,
+ 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784,
+ 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020,
+ 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb,
+ 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858,
+ 0xcf854acf, 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb,
+ 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, 0x458acf45,
+ 0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c,
+ 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3, 0x4080c040,
+ 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
+ 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010,
+ 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c,
+ 0x13263513, 0xecc32fec, 0x5fbee15f, 0x9735a297, 0x4488cc44,
+ 0x172e3917, 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d,
+ 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, 0x60c0a060,
+ 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a,
+ 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8,
+ 0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db,
+ 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49,
+ 0x060c0a06, 0x24486c24, 0x5cb8e45c, 0xc29f5dc2, 0xd3bd6ed3,
+ 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4,
+ 0x79f28b79, 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
+ 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c,
+ 0x56acfa56, 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a,
+ 0xae47e9ae, 0x08101808, 0xba6fd5ba, 0x78f08878, 0x254a6f25,
+ 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6,
+ 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, 0x4b96dd4b,
+ 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e,
+ 0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6,
+ 0x0e1c120e, 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9,
+ 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, 0xe1d938e1,
+ 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9,
+ 0x8e07898e, 0x9433a794, 0x9b2db69b, 0x1e3c221e, 0x87159287,
+ 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
+ 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf,
+ 0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099,
+ 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb,
+ 0x162c3a16};
+
+ private static final int[] T3 =
+ {
+ 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2,
+ 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101,
+ 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab,
+ 0xec9a7676, 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d,
+ 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, 0x41ecadad,
+ 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4,
+ 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393,
+ 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc,
+ 0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, 0xe2937171,
+ 0xab73d8d8, 0x62533131, 0x2a3f1515, 0x080c0404, 0x9552c7c7,
+ 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696, 0x0a0f0505,
+ 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
+ 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909,
+ 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e,
+ 0xb4ee5a5a, 0x5bfba0a0, 0xa4f65252, 0x764d3b3b, 0xb761d6d6,
+ 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484,
+ 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020,
+ 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb,
+ 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858,
+ 0x854acfcf, 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb,
+ 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, 0x8acf4545,
+ 0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c,
+ 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3, 0x80c04040,
+ 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
+ 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010,
+ 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c,
+ 0x26351313, 0xc32fecec, 0xbee15f5f, 0x35a29797, 0x88cc4444,
+ 0x2e391717, 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d,
+ 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, 0xc0a06060,
+ 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a,
+ 0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8,
+ 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb,
+ 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949,
+ 0x0c0a0606, 0x486c2424, 0xb8e45c5c, 0x9f5dc2c2, 0xbd6ed3d3,
+ 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4,
+ 0xf28b7979, 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
+ 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c,
+ 0xacfa5656, 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a,
+ 0x47e9aeae, 0x10180808, 0x6fd5baba, 0xf0887878, 0x4a6f2525,
+ 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6,
+ 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, 0x96dd4b4b,
+ 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e,
+ 0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6,
+ 0x1c120e0e, 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9,
+ 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, 0xd938e1e1,
+ 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9,
+ 0x07898e8e, 0x33a79494, 0x2db69b9b, 0x3c221e1e, 0x15928787,
+ 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
+ 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf,
+ 0xd731e6e6, 0x84c64242, 0xd0b86868, 0x82c34141, 0x29b09999,
+ 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb,
+ 0x2c3a1616};
+
+ private static final int[] Tinv0 =
+ {
+ 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
+ 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
+ 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
+ 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
+ 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03,
+ 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
+ 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899,
+ 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
+ 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1,
+ 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f,
+ 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3,
+ 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
+ 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a,
+ 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506,
+ 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05,
+ 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
+ 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491,
+ 0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
+ 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7,
+ 0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
+ 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd,
+ 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68,
+ 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, 0xd296eeb4,
+ 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
+ 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e,
+ 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af,
+ 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644,
+ 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
+ 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85,
+ 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
+ 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411,
+ 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
+ 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6,
+ 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0x0d927850,
+ 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e,
+ 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
+ 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd,
+ 0xf418596e, 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa,
+ 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea,
+ 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
+ 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1,
+ 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
+ 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1,
+ 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
+ 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a,
+ 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7,
+ 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418,
+ 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
+ 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
+ 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
+ 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
+ 0x4257b8d0};
+
+ private static final int[] Tinv1 =
+ {
+ 0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb,
+ 0x459d1ff1, 0x58faacab, 0x03e34b93, 0xfa302055, 0x6d76adf6,
+ 0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680,
+ 0xa362b58f, 0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1,
+ 0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6, 0x5f8f03e7,
+ 0x9c921595, 0x7a6dbfeb, 0x595295da, 0x83bed42d, 0x217458d3,
+ 0x69e04929, 0xc8c98e44, 0x89c2756a, 0x798ef478, 0x3e58996b,
+ 0x71b927dd, 0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4,
+ 0x4adf6318, 0x311ae582, 0x33519760, 0x7f536245, 0x7764b1e0,
+ 0xae6bbb84, 0xa081fe1c, 0x2b08f994, 0x68487058, 0xfd458f19,
+ 0x6cde9487, 0xf87b52b7, 0xd373ab23, 0x024b72e2, 0x8f1fe357,
+ 0xab55662a, 0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x0837d3a5,
+ 0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c, 0x1ccf8a2b,
+ 0xb479a792, 0xf207f3f0, 0xe2694ea1, 0xf4da65cd, 0xbe0506d5,
+ 0x6234d11f, 0xfea6c48a, 0x532e349d, 0x55f3a2a0, 0xe18a0532,
+ 0xebf6a475, 0xec830b39, 0xef6040aa, 0x9f715e06, 0x106ebd51,
+ 0x8a213ef9, 0x06dd963d, 0x053eddae, 0xbde64d46, 0x8d5491b5,
+ 0x5dc47105, 0xd406046f, 0x155060ff, 0xfb981924, 0xe9bdd697,
+ 0x434089cc, 0x9ed96777, 0x42e8b0bd, 0x8b890788, 0x5b19e738,
+ 0xeec879db, 0x0a7ca147, 0x0f427ce9, 0x1e84f8c9, 0x00000000,
+ 0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e, 0xff0efdfb,
+ 0x38850f56, 0xd5ae3d1e, 0x392d3627, 0xd90f0a64, 0xa65c6821,
+ 0x545b9bd1, 0x2e36243a, 0x670a0cb1, 0xe757930f, 0x96eeb4d2,
+ 0x919b1b9e, 0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16,
+ 0xba93e20a, 0x2aa0c0e5, 0xe0223c43, 0x171b121d, 0x0d090e0b,
+ 0xc78bf2ad, 0xa8b62db9, 0xa91e14c8, 0x19f15785, 0x0775af4c,
+ 0xdd99eebb, 0x607fa3fd, 0x2601f79f, 0xf5725cbc, 0x3b6644c5,
+ 0x7efb5b34, 0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863,
+ 0xdc31d7ca, 0x85634210, 0x22971340, 0x11c68420, 0x244a857d,
+ 0x3dbbd2f8, 0x32f9ae11, 0xa129c76d, 0x2f9e1d4b, 0x30b2dcf3,
+ 0x52860dec, 0xe3c177d0, 0x16b32b6c, 0xb970a999, 0x489411fa,
+ 0x64e94722, 0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, 0x903322ef,
+ 0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0x0bd49836, 0x81f5a6cf,
+ 0xde7aa528, 0x8eb7da26, 0xbfad3fa4, 0x9d3a2ce4, 0x9278500d,
+ 0xcc5f6a9b, 0x467e5462, 0x138df6c2, 0xb8d890e8, 0xf7392e5e,
+ 0xafc382f5, 0x805d9fbe, 0x93d0697c, 0x2dd56fa9, 0x1225cfb3,
+ 0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b, 0x7826cd09,
+ 0x18596ef4, 0xb79aec01, 0x9a4f83a8, 0x6e95e665, 0xe6ffaa7e,
+ 0xcfbc2108, 0xe815efe6, 0x9be7bad9, 0x366f4ace, 0x099fead4,
+ 0x7cb029d6, 0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0,
+ 0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315, 0x9804f14a,
+ 0xdaec41f7, 0x50cd7f0e, 0xf691172f, 0xd64d768d, 0xb0ef434d,
+ 0x4daacc54, 0x0496e4df, 0xb5d19ee3, 0x886a4c1b, 0x1f2cc1b8,
+ 0x5165467f, 0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e,
+ 0x1d67b35a, 0xd2db9252, 0x5610e933, 0x47d66d13, 0x61d79a8c,
+ 0x0ca1377a, 0x14f8598e, 0x3c13eb89, 0x27a9ceee, 0xc961b735,
+ 0xe51ce1ed, 0xb1477a3c, 0xdfd29c59, 0x73f2553f, 0xce141879,
+ 0x37c773bf, 0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886,
+ 0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672,
+ 0x25e2bc0c, 0x493c288b, 0x950dff41, 0x01a83971, 0xb30c08de,
+ 0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874,
+ 0x57b8d042};
+
+ private static final int[] Tinv2 =
+ {
+ 0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b,
+ 0x9d1ff145, 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d,
+ 0xcc889176, 0x02f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044,
+ 0x62b58fa3, 0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0,
+ 0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9, 0x8f03e75f,
+ 0x9215959c, 0x6dbfeb7a, 0x5295da59, 0xbed42d83, 0x7458d321,
+ 0xe0492969, 0xc98e44c8, 0xc2756a89, 0x8ef47879, 0x58996b3e,
+ 0xb927dd71, 0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a,
+ 0xdf63184a, 0x1ae58231, 0x51976033, 0x5362457f, 0x64b1e077,
+ 0x6bbb84ae, 0x81fe1ca0, 0x08f9942b, 0x48705868, 0x458f19fd,
+ 0xde94876c, 0x7b52b7f8, 0x73ab23d3, 0x4b72e202, 0x1fe3578f,
+ 0x55662aab, 0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508,
+ 0x2830f287, 0xbf23b2a5, 0x0302ba6a, 0x16ed5c82, 0xcf8a2b1c,
+ 0x79a792b4, 0x07f3f0f2, 0x694ea1e2, 0xda65cdf4, 0x0506d5be,
+ 0x34d11f62, 0xa6c48afe, 0x2e349d53, 0xf3a2a055, 0x8a0532e1,
+ 0xf6a475eb, 0x830b39ec, 0x6040aaef, 0x715e069f, 0x6ebd5110,
+ 0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd, 0x5491b58d,
+ 0xc471055d, 0x06046fd4, 0x5060ff15, 0x981924fb, 0xbdd697e9,
+ 0x4089cc43, 0xd967779e, 0xe8b0bd42, 0x8907888b, 0x19e7385b,
+ 0xc879dbee, 0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x00000000,
+ 0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72, 0x0efdfbff,
+ 0x850f5638, 0xae3d1ed5, 0x2d362739, 0x0f0a64d9, 0x5c6821a6,
+ 0x5b9bd154, 0x36243a2e, 0x0a0cb167, 0x57930fe7, 0xeeb4d296,
+ 0x9b1b9e91, 0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a,
+ 0x93e20aba, 0xa0c0e52a, 0x223c43e0, 0x1b121d17, 0x090e0b0d,
+ 0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9, 0xf1578519, 0x75af4c07,
+ 0x99eebbdd, 0x7fa3fd60, 0x01f79f26, 0x725cbcf5, 0x6644c53b,
+ 0xfb5b347e, 0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1,
+ 0x31d7cadc, 0x63421085, 0x97134022, 0xc6842011, 0x4a857d24,
+ 0xbbd2f83d, 0xf9ae1132, 0x29c76da1, 0x9e1d4b2f, 0xb2dcf330,
+ 0x860dec52, 0xc177d0e3, 0xb32b6c16, 0x70a999b9, 0x9411fa48,
+ 0xe9472264, 0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, 0x3322ef90,
+ 0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b, 0xf5a6cf81,
+ 0x7aa528de, 0xb7da268e, 0xad3fa4bf, 0x3a2ce49d, 0x78500d92,
+ 0x5f6a9bcc, 0x7e546246, 0x8df6c213, 0xd890e8b8, 0x392e5ef7,
+ 0xc382f5af, 0x5d9fbe80, 0xd0697c93, 0xd56fa92d, 0x25cfb312,
+ 0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb, 0x26cd0978,
+ 0x596ef418, 0x9aec01b7, 0x4f83a89a, 0x95e6656e, 0xffaa7ee6,
+ 0xbc2108cf, 0x15efe6e8, 0xe7bad99b, 0x6f4ace36, 0x9fead409,
+ 0xb029d67c, 0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066,
+ 0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8, 0x04f14a98,
+ 0xec41f7da, 0xcd7f0e50, 0x91172ff6, 0x4d768dd6, 0xef434db0,
+ 0xaacc544d, 0x96e4df04, 0xd19ee3b5, 0x6a4c1b88, 0x2cc1b81f,
+ 0x65467f51, 0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41,
+ 0x67b35a1d, 0xdb9252d2, 0x10e93356, 0xd66d1347, 0xd79a8c61,
+ 0xa1377a0c, 0xf8598e14, 0x13eb893c, 0xa9ceee27, 0x61b735c9,
+ 0x1ce1ede5, 0x477a3cb1, 0xd29c59df, 0xf2553f73, 0x141879ce,
+ 0xc773bf37, 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db,
+ 0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3,
+ 0xe2bc0c25, 0x3c288b49, 0x0dff4195, 0xa8397101, 0x0c08deb3,
+ 0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c,
+ 0xb8d04257};
+
+ private static final int[] Tinv3 =
+ {
+ 0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab,
+ 0x1ff1459d, 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76,
+ 0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435,
+ 0xb58fa362, 0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe,
+ 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, 0x03e75f8f,
+ 0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174,
+ 0x492969e0, 0x8e44c8c9, 0x756a89c2, 0xf478798e, 0x996b3e58,
+ 0x27dd71b9, 0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace,
+ 0x63184adf, 0xe582311a, 0x97603351, 0x62457f53, 0xb1e07764,
+ 0xbb84ae6b, 0xfe1ca081, 0xf9942b08, 0x70586848, 0x8f19fd45,
+ 0x94876cde, 0x52b7f87b, 0xab23d373, 0x72e2024b, 0xe3578f1f,
+ 0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837,
+ 0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, 0x8a2b1ccf,
+ 0xa792b479, 0xf3f0f207, 0x4ea1e269, 0x65cdf4da, 0x06d5be05,
+ 0xd11f6234, 0xc48afea6, 0x349d532e, 0xa2a055f3, 0x0532e18a,
+ 0xa475ebf6, 0x0b39ec83, 0x40aaef60, 0x5e069f71, 0xbd51106e,
+ 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, 0x91b58d54,
+ 0x71055dc4, 0x046fd406, 0x60ff1550, 0x1924fb98, 0xd697e9bd,
+ 0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x07888b89, 0xe7385b19,
+ 0x79dbeec8, 0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000,
+ 0x09838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a, 0xfdfbff0e,
+ 0x0f563885, 0x3d1ed5ae, 0x3627392d, 0x0a64d90f, 0x6821a65c,
+ 0x9bd1545b, 0x243a2e36, 0x0cb1670a, 0x930fe757, 0xb4d296ee,
+ 0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12,
+ 0xe20aba93, 0xc0e52aa0, 0x3c43e022, 0x121d171b, 0x0e0b0d09,
+ 0xf2adc78b, 0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775,
+ 0xeebbdd99, 0xa3fd607f, 0xf79f2601, 0x5cbcf572, 0x44c53b66,
+ 0x5b347efb, 0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4,
+ 0xd7cadc31, 0x42108563, 0x13402297, 0x842011c6, 0x857d244a,
+ 0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2,
+ 0x0dec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894,
+ 0x472264e9, 0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, 0x22ef9033,
+ 0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4, 0xa6cf81f5,
+ 0xa528de7a, 0xda268eb7, 0x3fa4bfad, 0x2ce49d3a, 0x500d9278,
+ 0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8, 0x2e5ef739,
+ 0x82f5afc3, 0x9fbe805d, 0x697c93d0, 0x6fa92dd5, 0xcfb31225,
+ 0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826,
+ 0x6ef41859, 0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff,
+ 0x2108cfbc, 0xefe6e815, 0xbad99be7, 0x4ace366f, 0xead4099f,
+ 0x29d67cb0, 0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2,
+ 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, 0xf14a9804,
+ 0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef,
+ 0xcc544daa, 0xe4df0496, 0x9ee3b5d1, 0x4c1b886a, 0xc1b81f2c,
+ 0x467f5165, 0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b,
+ 0xb35a1d67, 0x9252d2db, 0xe9335610, 0x6d1347d6, 0x9a8c61d7,
+ 0x377a0ca1, 0x598e14f8, 0xeb893c13, 0xceee27a9, 0xb735c961,
+ 0xe1ede51c, 0x7a3cb147, 0x9c59dfd2, 0x553f73f2, 0x1879ce14,
+ 0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44,
+ 0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d,
+ 0xbc0c25e2, 0x288b493c, 0xff41950d, 0x397101a8, 0x08deb30c,
+ 0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c,
+ 0xd04257b8};
+
+ private static int shift(int r, int shift)
+ {
+ return (r >>> shift) | (r << -shift);
+ }
+
+ /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+ private static final int m1 = 0x80808080;
+ private static final int m2 = 0x7f7f7f7f;
+ private static final int m3 = 0x0000001b;
+
+ private static int FFmulX(int x)
+ {
+ return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
+ }
+
+ /*
+ The following defines provide alternative definitions of FFmulX that might
+ give improved performance if a fast 32-bit multiply is not available.
+
+ private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
+ private static final int m4 = 0x1b1b1b1b;
+ private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
+
+ */
+
+ private static int inv_mcol(int x)
+ {
+ int f2 = FFmulX(x);
+ int f4 = FFmulX(f2);
+ int f8 = FFmulX(f4);
+ int f9 = x ^ f8;
+
+ return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
+ }
+
+
+ private static int subWord(int x)
+ {
+ return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24);
+ }
+
+ /**
+ * Calculate the necessary round keys
+ * The number of calculations depends on key size and block size
+ * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+ * This code is written assuming those are the only possible values
+ */
+ private int[][] generateWorkingKey(
+ byte[] key,
+ boolean forEncryption)
+ {
+ int KC = key.length / 4; // key length in words
+ int t;
+
+ if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length))
+ {
+ throw new IllegalArgumentException("Key length not 128/192/256 bits.");
+ }
+
+ ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
+ int[][] W = new int[ROUNDS+1][4]; // 4 words in a block
+
+ //
+ // copy the key into the round key array
+ //
+
+ t = 0;
+ int i = 0;
+ while (i < key.length)
+ {
+ W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
+ i+=4;
+ t++;
+ }
+
+ //
+ // while not enough round key material calculated
+ // calculate new values
+ //
+ int k = (ROUNDS + 1) << 2;
+ for (i = KC; (i < k); i++)
+ {
+ int temp = W[(i - 1) >> 2][(i - 1) & 3];
+ if ((i % KC) == 0)
+ {
+ temp = subWord(shift(temp, 8)) ^ rcon[(i / KC) - 1];
+ }
+ else if ((KC > 6) && ((i % KC) == 4))
+ {
+ temp = subWord(temp);
+ }
+
+ W[i >> 2][i & 3] = W[(i - KC) >> 2][(i - KC) & 3] ^ temp;
+ }
+
+ if (!forEncryption)
+ {
+ for (int j = 1; j < ROUNDS; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ W[j][i] = inv_mcol(W[j][i]);
+ }
+ }
+ }
+
+ return W;
+ }
+
+ private int ROUNDS;
+ private int[][] WorkingKey = null;
+ private int C0, C1, C2, C3;
+ private boolean forEncryption;
+
+ private static final int BLOCK_SIZE = 16;
+
+ /**
+ * default constructor - 128 bit block size.
+ */
+ public AESFastEngine()
+ {
+ }
+
+ /**
+ * initialise an AES cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ WorkingKey = generateWorkingKey(((KeyParameter)params).getKey(), forEncryption);
+ this.forEncryption = forEncryption;
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to AES init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "AES";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (WorkingKey == null)
+ {
+ throw new IllegalStateException("AES engine not initialised");
+ }
+
+ if ((inOff + (32 / 2)) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + (32 / 2)) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (forEncryption)
+ {
+ unpackBlock(in, inOff);
+ encryptBlock(WorkingKey);
+ packBlock(out, outOff);
+ }
+ else
+ {
+ unpackBlock(in, inOff);
+ decryptBlock(WorkingKey);
+ packBlock(out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private void unpackBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ C0 = (bytes[index++] & 0xff);
+ C0 |= (bytes[index++] & 0xff) << 8;
+ C0 |= (bytes[index++] & 0xff) << 16;
+ C0 |= bytes[index++] << 24;
+
+ C1 = (bytes[index++] & 0xff);
+ C1 |= (bytes[index++] & 0xff) << 8;
+ C1 |= (bytes[index++] & 0xff) << 16;
+ C1 |= bytes[index++] << 24;
+
+ C2 = (bytes[index++] & 0xff);
+ C2 |= (bytes[index++] & 0xff) << 8;
+ C2 |= (bytes[index++] & 0xff) << 16;
+ C2 |= bytes[index++] << 24;
+
+ C3 = (bytes[index++] & 0xff);
+ C3 |= (bytes[index++] & 0xff) << 8;
+ C3 |= (bytes[index++] & 0xff) << 16;
+ C3 |= bytes[index++] << 24;
+ }
+
+ private void packBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ bytes[index++] = (byte)C0;
+ bytes[index++] = (byte)(C0 >> 8);
+ bytes[index++] = (byte)(C0 >> 16);
+ bytes[index++] = (byte)(C0 >> 24);
+
+ bytes[index++] = (byte)C1;
+ bytes[index++] = (byte)(C1 >> 8);
+ bytes[index++] = (byte)(C1 >> 16);
+ bytes[index++] = (byte)(C1 >> 24);
+
+ bytes[index++] = (byte)C2;
+ bytes[index++] = (byte)(C2 >> 8);
+ bytes[index++] = (byte)(C2 >> 16);
+ bytes[index++] = (byte)(C2 >> 24);
+
+ bytes[index++] = (byte)C3;
+ bytes[index++] = (byte)(C3 >> 8);
+ bytes[index++] = (byte)(C3 >> 16);
+ bytes[index++] = (byte)(C3 >> 24);
+ }
+
+ private void encryptBlock(int[][] KW)
+ {
+ int r, r0, r1, r2, r3;
+
+ C0 ^= KW[0][0];
+ C1 ^= KW[0][1];
+ C2 ^= KW[0][2];
+ C3 ^= KW[0][3];
+
+ r = 1;
+ while (r < ROUNDS - 1)
+ {
+ r0 = T0[C0&255] ^ T1[(C1>>8)&255] ^ T2[(C2>>16)&255] ^ T3[(C3>>24)&255] ^ KW[r][0];
+ r1 = T0[C1&255] ^ T1[(C2>>8)&255] ^ T2[(C3>>16)&255] ^ T3[(C0>>24)&255] ^ KW[r][1];
+ r2 = T0[C2&255] ^ T1[(C3>>8)&255] ^ T2[(C0>>16)&255] ^ T3[(C1>>24)&255] ^ KW[r][2];
+ r3 = T0[C3&255] ^ T1[(C0>>8)&255] ^ T2[(C1>>16)&255] ^ T3[(C2>>24)&255] ^ KW[r++][3];
+ C0 = T0[r0&255] ^ T1[(r1>>8)&255] ^ T2[(r2>>16)&255] ^ T3[(r3>>24)&255] ^ KW[r][0];
+ C1 = T0[r1&255] ^ T1[(r2>>8)&255] ^ T2[(r3>>16)&255] ^ T3[(r0>>24)&255] ^ KW[r][1];
+ C2 = T0[r2&255] ^ T1[(r3>>8)&255] ^ T2[(r0>>16)&255] ^ T3[(r1>>24)&255] ^ KW[r][2];
+ C3 = T0[r3&255] ^ T1[(r0>>8)&255] ^ T2[(r1>>16)&255] ^ T3[(r2>>24)&255] ^ KW[r++][3];
+ }
+
+ r0 = T0[C0&255] ^ T1[(C1>>8)&255] ^ T2[(C2>>16)&255] ^ T3[(C3>>24)&255] ^ KW[r][0];
+ r1 = T0[C1&255] ^ T1[(C2>>8)&255] ^ T2[(C3>>16)&255] ^ T3[(C0>>24)&255] ^ KW[r][1];
+ r2 = T0[C2&255] ^ T1[(C3>>8)&255] ^ T2[(C0>>16)&255] ^ T3[(C1>>24)&255] ^ KW[r][2];
+ r3 = T0[C3&255] ^ T1[(C0>>8)&255] ^ T2[(C1>>16)&255] ^ T3[(C2>>24)&255] ^ KW[r++][3];
+
+ // the final round's table is a simple function of S so we don't use a whole other four tables for it
+
+ C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0];
+ C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1];
+ C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2];
+ C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3];
+
+ }
+
+ private void decryptBlock(int[][] KW)
+ {
+ int r0, r1, r2, r3;
+
+ C0 ^= KW[ROUNDS][0];
+ C1 ^= KW[ROUNDS][1];
+ C2 ^= KW[ROUNDS][2];
+ C3 ^= KW[ROUNDS][3];
+
+ int r = ROUNDS-1;
+
+ while (r>1)
+ {
+ r0 = Tinv0[C0&255] ^ Tinv1[(C3>>8)&255] ^ Tinv2[(C2>>16)&255] ^ Tinv3[(C1>>24)&255] ^ KW[r][0];
+ r1 = Tinv0[C1&255] ^ Tinv1[(C0>>8)&255] ^ Tinv2[(C3>>16)&255] ^ Tinv3[(C2>>24)&255] ^ KW[r][1];
+ r2 = Tinv0[C2&255] ^ Tinv1[(C1>>8)&255] ^ Tinv2[(C0>>16)&255] ^ Tinv3[(C3>>24)&255] ^ KW[r][2];
+ r3 = Tinv0[C3&255] ^ Tinv1[(C2>>8)&255] ^ Tinv2[(C1>>16)&255] ^ Tinv3[(C0>>24)&255] ^ KW[r--][3];
+ C0 = Tinv0[r0&255] ^ Tinv1[(r3>>8)&255] ^ Tinv2[(r2>>16)&255] ^ Tinv3[(r1>>24)&255] ^ KW[r][0];
+ C1 = Tinv0[r1&255] ^ Tinv1[(r0>>8)&255] ^ Tinv2[(r3>>16)&255] ^ Tinv3[(r2>>24)&255] ^ KW[r][1];
+ C2 = Tinv0[r2&255] ^ Tinv1[(r1>>8)&255] ^ Tinv2[(r0>>16)&255] ^ Tinv3[(r3>>24)&255] ^ KW[r][2];
+ C3 = Tinv0[r3&255] ^ Tinv1[(r2>>8)&255] ^ Tinv2[(r1>>16)&255] ^ Tinv3[(r0>>24)&255] ^ KW[r--][3];
+ }
+
+ r0 = Tinv0[C0&255] ^ Tinv1[(C3>>8)&255] ^ Tinv2[(C2>>16)&255] ^ Tinv3[(C1>>24)&255] ^ KW[r][0];
+ r1 = Tinv0[C1&255] ^ Tinv1[(C0>>8)&255] ^ Tinv2[(C3>>16)&255] ^ Tinv3[(C2>>24)&255] ^ KW[r][1];
+ r2 = Tinv0[C2&255] ^ Tinv1[(C1>>8)&255] ^ Tinv2[(C0>>16)&255] ^ Tinv3[(C3>>24)&255] ^ KW[r][2];
+ r3 = Tinv0[C3&255] ^ Tinv1[(C2>>8)&255] ^ Tinv2[(C1>>16)&255] ^ Tinv3[(C0>>24)&255] ^ KW[r][3];
+
+ // the final round's table is a simple function of Si so we don't use a whole other four tables for it
+
+ C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0];
+ C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1];
+ C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2];
+ C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3];
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/AESLightEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/AESLightEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/AESLightEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/AESLightEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,438 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * an implementation of the AES (Rijndael), from FIPS-197.
+ *
+ * For further details see: http://csrc.nist.gov/encryption/aes/ .
+ *
+ * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+ * http://fp.gladman.plus.com/cryptography_technology/rijndael/
+ *
+ * There are three levels of tradeoff of speed vs memory
+ * Because java has no preprocessor, they are written as three separate classes from which to choose
+ *
+ * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+ * and 4 for decryption.
+ *
+ * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+ * adding 12 rotate operations per round to compute the values contained in the other tables from
+ * the contents of the first
+ *
+ * The slowest version uses no static tables at all and computes the values
+ * in each round.
+ *
+ * This file contains the slowest performance version with no static tables
+ * for round precomputation, but it has the smallest foot print.
+ *
+ */
+public class AESLightEngine
+ implements BlockCipher
+{
+ // The S box
+ private static final byte[] S = {
+ (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197,
+ (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
+ (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240,
+ (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
+ (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204,
+ (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
+ (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154,
+ (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
+ (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160,
+ (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
+ (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91,
+ (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
+ (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133,
+ (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
+ (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245,
+ (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
+ (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23,
+ (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
+ (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136,
+ (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
+ (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92,
+ (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
+ (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169,
+ (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
+ (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198,
+ (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
+ (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14,
+ (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
+ (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148,
+ (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
+ (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104,
+ (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
+ };
+
+ // The inverse S-box
+ private static final byte[] Si = {
+ (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56,
+ (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
+ (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135,
+ (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
+ (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61,
+ (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
+ (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178,
+ (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
+ (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22,
+ (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
+ (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218,
+ (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
+ (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10,
+ (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
+ (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2,
+ (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
+ (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234,
+ (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
+ (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133,
+ (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
+ (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137,
+ (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
+ (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32,
+ (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
+ (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49,
+ (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
+ (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13,
+ (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
+ (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176,
+ (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
+ (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38,
+ (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
+ };
+
+ // vector used in calculating key schedule (powers of x in GF(256))
+ private static final int[] rcon = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+ 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
+
+ private static int shift(int r, int shift)
+ {
+ return (r >>> shift) | (r << -shift);
+ }
+
+ /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+ private static final int m1 = 0x80808080;
+ private static final int m2 = 0x7f7f7f7f;
+ private static final int m3 = 0x0000001b;
+
+ private static int FFmulX(int x)
+ {
+ return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3));
+ }
+
+ /*
+ The following defines provide alternative definitions of FFmulX that might
+ give improved performance if a fast 32-bit multiply is not available.
+
+ private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
+ private static final int m4 = 0x1b1b1b1b;
+ private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
+
+ */
+
+ private static int mcol(int x)
+ {
+ int f2 = FFmulX(x);
+ return f2 ^ shift(x ^ f2, 8) ^ shift(x, 16) ^ shift(x, 24);
+ }
+
+ private static int inv_mcol(int x)
+ {
+ int f2 = FFmulX(x);
+ int f4 = FFmulX(f2);
+ int f8 = FFmulX(f4);
+ int f9 = x ^ f8;
+
+ return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24);
+ }
+
+
+ private static int subWord(int x)
+ {
+ return (S[x&255]&255 | ((S[(x>>8)&255]&255)<<8) | ((S[(x>>16)&255]&255)<<16) | S[(x>>24)&255]<<24);
+ }
+
+ /**
+ * Calculate the necessary round keys
+ * The number of calculations depends on key size and block size
+ * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+ * This code is written assuming those are the only possible values
+ */
+ private int[][] generateWorkingKey(
+ byte[] key,
+ boolean forEncryption)
+ {
+ int KC = key.length / 4; // key length in words
+ int t;
+
+ if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length))
+ {
+ throw new IllegalArgumentException("Key length not 128/192/256 bits.");
+ }
+
+ ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
+ int[][] W = new int[ROUNDS+1][4]; // 4 words in a block
+
+ //
+ // copy the key into the round key array
+ //
+
+ t = 0;
+ int i = 0;
+ while (i < key.length)
+ {
+ W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24);
+ i+=4;
+ t++;
+ }
+
+ //
+ // while not enough round key material calculated
+ // calculate new values
+ //
+ int k = (ROUNDS + 1) << 2;
+ for (i = KC; (i < k); i++)
+ {
+ int temp = W[(i-1)>>2][(i-1)&3];
+ if ((i % KC) == 0)
+ {
+ temp = subWord(shift(temp, 8)) ^ rcon[(i / KC)-1];
+ }
+ else if ((KC > 6) && ((i % KC) == 4))
+ {
+ temp = subWord(temp);
+ }
+
+ W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
+ }
+
+ if (!forEncryption)
+ {
+ for (int j = 1; j < ROUNDS; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ W[j][i] = inv_mcol(W[j][i]);
+ }
+ }
+ }
+
+ return W;
+ }
+
+ private int ROUNDS;
+ private int[][] WorkingKey = null;
+ private int C0, C1, C2, C3;
+ private boolean forEncryption;
+
+ private static final int BLOCK_SIZE = 16;
+
+ /**
+ * default constructor - 128 bit block size.
+ */
+ public AESLightEngine()
+ {
+ }
+
+ /**
+ * initialise an AES cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ WorkingKey = generateWorkingKey(((KeyParameter)params).getKey(), forEncryption);
+ this.forEncryption = forEncryption;
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to AES init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "AES";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (WorkingKey == null)
+ {
+ throw new IllegalStateException("AES engine not initialised");
+ }
+
+ if ((inOff + (32 / 2)) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + (32 / 2)) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (forEncryption)
+ {
+ unpackBlock(in, inOff);
+ encryptBlock(WorkingKey);
+ packBlock(out, outOff);
+ }
+ else
+ {
+ unpackBlock(in, inOff);
+ decryptBlock(WorkingKey);
+ packBlock(out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private void unpackBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ C0 = (bytes[index++] & 0xff);
+ C0 |= (bytes[index++] & 0xff) << 8;
+ C0 |= (bytes[index++] & 0xff) << 16;
+ C0 |= bytes[index++] << 24;
+
+ C1 = (bytes[index++] & 0xff);
+ C1 |= (bytes[index++] & 0xff) << 8;
+ C1 |= (bytes[index++] & 0xff) << 16;
+ C1 |= bytes[index++] << 24;
+
+ C2 = (bytes[index++] & 0xff);
+ C2 |= (bytes[index++] & 0xff) << 8;
+ C2 |= (bytes[index++] & 0xff) << 16;
+ C2 |= bytes[index++] << 24;
+
+ C3 = (bytes[index++] & 0xff);
+ C3 |= (bytes[index++] & 0xff) << 8;
+ C3 |= (bytes[index++] & 0xff) << 16;
+ C3 |= bytes[index++] << 24;
+ }
+
+ private void packBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ bytes[index++] = (byte)C0;
+ bytes[index++] = (byte)(C0 >> 8);
+ bytes[index++] = (byte)(C0 >> 16);
+ bytes[index++] = (byte)(C0 >> 24);
+
+ bytes[index++] = (byte)C1;
+ bytes[index++] = (byte)(C1 >> 8);
+ bytes[index++] = (byte)(C1 >> 16);
+ bytes[index++] = (byte)(C1 >> 24);
+
+ bytes[index++] = (byte)C2;
+ bytes[index++] = (byte)(C2 >> 8);
+ bytes[index++] = (byte)(C2 >> 16);
+ bytes[index++] = (byte)(C2 >> 24);
+
+ bytes[index++] = (byte)C3;
+ bytes[index++] = (byte)(C3 >> 8);
+ bytes[index++] = (byte)(C3 >> 16);
+ bytes[index++] = (byte)(C3 >> 24);
+ }
+
+ private void encryptBlock(int[][] KW)
+ {
+ int r, r0, r1, r2, r3;
+
+ C0 ^= KW[0][0];
+ C1 ^= KW[0][1];
+ C2 ^= KW[0][2];
+ C3 ^= KW[0][3];
+
+ for (r = 1; r < ROUNDS - 1;)
+ {
+ r0 = mcol((S[C0&255]&255) ^ ((S[(C1>>8)&255]&255)<<8) ^ ((S[(C2>>16)&255]&255)<<16) ^ (S[(C3>>24)&255]<<24)) ^ KW[r][0];
+ r1 = mcol((S[C1&255]&255) ^ ((S[(C2>>8)&255]&255)<<8) ^ ((S[(C3>>16)&255]&255)<<16) ^ (S[(C0>>24)&255]<<24)) ^ KW[r][1];
+ r2 = mcol((S[C2&255]&255) ^ ((S[(C3>>8)&255]&255)<<8) ^ ((S[(C0>>16)&255]&255)<<16) ^ (S[(C1>>24)&255]<<24)) ^ KW[r][2];
+ r3 = mcol((S[C3&255]&255) ^ ((S[(C0>>8)&255]&255)<<8) ^ ((S[(C1>>16)&255]&255)<<16) ^ (S[(C2>>24)&255]<<24)) ^ KW[r++][3];
+ C0 = mcol((S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24)) ^ KW[r][0];
+ C1 = mcol((S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24)) ^ KW[r][1];
+ C2 = mcol((S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24)) ^ KW[r][2];
+ C3 = mcol((S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24)) ^ KW[r++][3];
+ }
+
+ r0 = mcol((S[C0&255]&255) ^ ((S[(C1>>8)&255]&255)<<8) ^ ((S[(C2>>16)&255]&255)<<16) ^ (S[(C3>>24)&255]<<24)) ^ KW[r][0];
+ r1 = mcol((S[C1&255]&255) ^ ((S[(C2>>8)&255]&255)<<8) ^ ((S[(C3>>16)&255]&255)<<16) ^ (S[(C0>>24)&255]<<24)) ^ KW[r][1];
+ r2 = mcol((S[C2&255]&255) ^ ((S[(C3>>8)&255]&255)<<8) ^ ((S[(C0>>16)&255]&255)<<16) ^ (S[(C1>>24)&255]<<24)) ^ KW[r][2];
+ r3 = mcol((S[C3&255]&255) ^ ((S[(C0>>8)&255]&255)<<8) ^ ((S[(C1>>16)&255]&255)<<16) ^ (S[(C2>>24)&255]<<24)) ^ KW[r++][3];
+
+ // the final round is a simple function of S
+
+ C0 = (S[r0&255]&255) ^ ((S[(r1>>8)&255]&255)<<8) ^ ((S[(r2>>16)&255]&255)<<16) ^ (S[(r3>>24)&255]<<24) ^ KW[r][0];
+ C1 = (S[r1&255]&255) ^ ((S[(r2>>8)&255]&255)<<8) ^ ((S[(r3>>16)&255]&255)<<16) ^ (S[(r0>>24)&255]<<24) ^ KW[r][1];
+ C2 = (S[r2&255]&255) ^ ((S[(r3>>8)&255]&255)<<8) ^ ((S[(r0>>16)&255]&255)<<16) ^ (S[(r1>>24)&255]<<24) ^ KW[r][2];
+ C3 = (S[r3&255]&255) ^ ((S[(r0>>8)&255]&255)<<8) ^ ((S[(r1>>16)&255]&255)<<16) ^ (S[(r2>>24)&255]<<24) ^ KW[r][3];
+
+ }
+
+ private void decryptBlock(int[][] KW)
+ {
+ int r, r0, r1, r2, r3;
+
+ C0 ^= KW[ROUNDS][0];
+ C1 ^= KW[ROUNDS][1];
+ C2 ^= KW[ROUNDS][2];
+ C3 ^= KW[ROUNDS][3];
+
+ for (r = ROUNDS-1; r>1;)
+ {
+ r0 = inv_mcol((Si[C0&255]&255) ^ ((Si[(C3>>8)&255]&255)<<8) ^ ((Si[(C2>>16)&255]&255)<<16) ^ (Si[(C1>>24)&255]<<24)) ^ KW[r][0];
+ r1 = inv_mcol((Si[C1&255]&255) ^ ((Si[(C0>>8)&255]&255)<<8) ^ ((Si[(C3>>16)&255]&255)<<16) ^ (Si[(C2>>24)&255]<<24)) ^ KW[r][1];
+ r2 = inv_mcol((Si[C2&255]&255) ^ ((Si[(C1>>8)&255]&255)<<8) ^ ((Si[(C0>>16)&255]&255)<<16) ^ (Si[(C3>>24)&255]<<24)) ^ KW[r][2];
+ r3 = inv_mcol((Si[C3&255]&255) ^ ((Si[(C2>>8)&255]&255)<<8) ^ ((Si[(C1>>16)&255]&255)<<16) ^ (Si[(C0>>24)&255]<<24)) ^ KW[r--][3];
+ C0 = inv_mcol((Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24)) ^ KW[r][0];
+ C1 = inv_mcol((Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24)) ^ KW[r][1];
+ C2 = inv_mcol((Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24)) ^ KW[r][2];
+ C3 = inv_mcol((Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24)) ^ KW[r--][3];
+ }
+
+ r0 = inv_mcol((Si[C0&255]&255) ^ ((Si[(C3>>8)&255]&255)<<8) ^ ((Si[(C2>>16)&255]&255)<<16) ^ (Si[(C1>>24)&255]<<24)) ^ KW[r][0];
+ r1 = inv_mcol((Si[C1&255]&255) ^ ((Si[(C0>>8)&255]&255)<<8) ^ ((Si[(C3>>16)&255]&255)<<16) ^ (Si[(C2>>24)&255]<<24)) ^ KW[r][1];
+ r2 = inv_mcol((Si[C2&255]&255) ^ ((Si[(C1>>8)&255]&255)<<8) ^ ((Si[(C0>>16)&255]&255)<<16) ^ (Si[(C3>>24)&255]<<24)) ^ KW[r][2];
+ r3 = inv_mcol((Si[C3&255]&255) ^ ((Si[(C2>>8)&255]&255)<<8) ^ ((Si[(C1>>16)&255]&255)<<16) ^ (Si[(C0>>24)&255]<<24)) ^ KW[r][3];
+
+ // the final round's table is a simple function of Si
+
+ C0 = (Si[r0&255]&255) ^ ((Si[(r3>>8)&255]&255)<<8) ^ ((Si[(r2>>16)&255]&255)<<16) ^ (Si[(r1>>24)&255]<<24) ^ KW[0][0];
+ C1 = (Si[r1&255]&255) ^ ((Si[(r0>>8)&255]&255)<<8) ^ ((Si[(r3>>16)&255]&255)<<16) ^ (Si[(r2>>24)&255]<<24) ^ KW[0][1];
+ C2 = (Si[r2&255]&255) ^ ((Si[(r1>>8)&255]&255)<<8) ^ ((Si[(r0>>16)&255]&255)<<16) ^ (Si[(r3>>24)&255]<<24) ^ KW[0][2];
+ C3 = (Si[r3&255]&255) ^ ((Si[(r2>>8)&255]&255)<<8) ^ ((Si[(r1>>16)&255]&255)<<16) ^ (Si[(r0>>24)&255]<<24) ^ KW[0][3];
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/AESWrapEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/AESWrapEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/AESWrapEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/AESWrapEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,16 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+/**
+ * an implementation of the AES Key Wrapper from the NIST Key Wrap
+ * Specification.
+ *
+ * For further details see: http://csrc.nist.gov/encryption/kms/key-wrap.pdf .
+ */
+public class AESWrapEngine
+ extends RFC3394WrapEngine
+{
+ public AESWrapEngine()
+ {
+ super(new AESEngine());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/BlowfishEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/BlowfishEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/BlowfishEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/BlowfishEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,576 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * A class that provides Blowfish key encryption operations,
+ * such as encoding data and generating keys.
+ * All the algorithms herein are from Applied Cryptography
+ * and implement a simplified cryptography interface.
+ */
+public final class BlowfishEngine
+implements BlockCipher
+{
+ private final static int[]
+ KP = {
+ 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
+ 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
+ 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
+ 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
+ 0x9216D5D9, 0x8979FB1B
+ },
+
+ KS0 = {
+ 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
+ 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
+ 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
+ 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
+ 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
+ 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
+ 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
+ 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
+ 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
+ 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
+ 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
+ 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
+ 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
+ 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
+ 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
+ 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
+ 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
+ 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
+ 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
+ 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
+ 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
+ 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
+ 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
+ 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
+ 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
+ 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
+ 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
+ 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
+ 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
+ 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
+ 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
+ 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
+ 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
+ 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
+ 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
+ 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
+ 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
+ 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
+ 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
+ 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
+ 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
+ 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
+ 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
+ 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
+ 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
+ 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
+ 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
+ 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
+ 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
+ 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
+ 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
+ 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
+ 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
+ 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
+ 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
+ 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
+ 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
+ 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
+ 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
+ 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
+ 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
+ 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
+ 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
+ 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A
+ },
+
+ KS1 = {
+ 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
+ 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
+ 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
+ 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
+ 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
+ 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
+ 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
+ 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
+ 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
+ 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
+ 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
+ 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
+ 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
+ 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
+ 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
+ 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
+ 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
+ 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
+ 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
+ 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
+ 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
+ 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
+ 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
+ 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
+ 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
+ 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
+ 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
+ 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
+ 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
+ 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
+ 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
+ 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
+ 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
+ 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
+ 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
+ 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
+ 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
+ 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
+ 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
+ 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
+ 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
+ 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
+ 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
+ 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
+ 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
+ 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
+ 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
+ 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
+ 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
+ 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
+ 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
+ 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
+ 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
+ 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
+ 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
+ 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
+ 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
+ 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
+ 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
+ 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
+ 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
+ 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
+ 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
+ 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7
+ },
+
+ KS2 = {
+ 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
+ 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
+ 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
+ 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
+ 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
+ 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
+ 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
+ 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
+ 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
+ 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
+ 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
+ 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
+ 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
+ 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
+ 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
+ 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
+ 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
+ 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
+ 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
+ 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
+ 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
+ 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
+ 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
+ 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
+ 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
+ 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
+ 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
+ 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
+ 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
+ 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
+ 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
+ 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
+ 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
+ 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
+ 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
+ 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
+ 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
+ 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
+ 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
+ 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
+ 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
+ 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
+ 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
+ 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
+ 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
+ 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
+ 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
+ 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
+ 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
+ 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
+ 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
+ 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
+ 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
+ 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
+ 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
+ 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
+ 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
+ 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
+ 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
+ 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
+ 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
+ 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
+ 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
+ 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0
+ },
+
+ KS3 = {
+ 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
+ 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
+ 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
+ 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
+ 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
+ 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
+ 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
+ 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
+ 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
+ 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
+ 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
+ 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
+ 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
+ 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
+ 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
+ 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
+ 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
+ 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
+ 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
+ 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
+ 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
+ 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
+ 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
+ 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
+ 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
+ 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
+ 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
+ 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
+ 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
+ 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
+ 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
+ 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
+ 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
+ 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
+ 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
+ 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
+ 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
+ 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
+ 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
+ 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
+ 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
+ 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
+ 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
+ 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
+ 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
+ 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
+ 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
+ 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
+ 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
+ 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
+ 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
+ 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
+ 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
+ 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
+ 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
+ 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
+ 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
+ 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
+ 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
+ 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
+ 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
+ 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
+ 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
+ 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6
+ };
+
+ //====================================
+ // Useful constants
+ //====================================
+
+ private static final int ROUNDS = 16;
+ private static final int BLOCK_SIZE = 8; // bytes = 64 bits
+ private static final int SBOX_SK = 256;
+ private static final int P_SZ = ROUNDS+2;
+
+ private final int[] S0, S1, S2, S3; // the s-boxes
+ private final int[] P; // the p-array
+
+ private boolean encrypting = false;
+
+ private byte[] workingKey = null;
+
+ public BlowfishEngine()
+ {
+ S0 = new int[SBOX_SK];
+ S1 = new int[SBOX_SK];
+ S2 = new int[SBOX_SK];
+ S3 = new int[SBOX_SK];
+ P = new int[P_SZ];
+ }
+
+ /**
+ * initialise a Blowfish cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ this.encrypting = encrypting;
+ this.workingKey = ((KeyParameter)params).getKey();
+ setKey(this.workingKey);
+
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to Blowfish init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Blowfish";
+ }
+
+ public final int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("Blowfish not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (encrypting)
+ {
+ encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ decryptBlock(in, inOff, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ //==================================
+ // Private Implementation
+ //==================================
+
+ private int F(int x)
+ {
+ return (((S0[(x >>> 24)] + S1[(x >>> 16) & 0xff])
+ ^ S2[(x >>> 8) & 0xff]) + S3[x & 0xff]);
+ }
+
+ /**
+ * apply the encryption cycle to each value pair in the table.
+ */
+ private void processTable(
+ int xl,
+ int xr,
+ int[] table)
+ {
+ int size = table.length;
+
+ for (int s = 0; s < size; s += 2)
+ {
+ xl ^= P[0];
+
+ for (int i = 1; i < ROUNDS; i += 2)
+ {
+ xr ^= F(xl) ^ P[i];
+ xl ^= F(xr) ^ P[i + 1];
+ }
+
+ xr ^= P[ROUNDS + 1];
+
+ table[s] = xr;
+ table[s + 1] = xl;
+
+ xr = xl; // end of cycle swap
+ xl = table[s];
+ }
+ }
+
+ private void setKey(byte[] key)
+ {
+ /*
+ * - comments are from _Applied Crypto_, Schneier, p338
+ * please be careful comparing the two, AC numbers the
+ * arrays from 1, the enclosed code from 0.
+ *
+ * (1)
+ * Initialise the S-boxes and the P-array, with a fixed string
+ * This string contains the hexadecimal digits of pi (3.141...)
+ */
+ System.arraycopy(KS0, 0, S0, 0, SBOX_SK);
+ System.arraycopy(KS1, 0, S1, 0, SBOX_SK);
+ System.arraycopy(KS2, 0, S2, 0, SBOX_SK);
+ System.arraycopy(KS3, 0, S3, 0, SBOX_SK);
+
+ System.arraycopy(KP, 0, P, 0, P_SZ);
+
+ /*
+ * (2)
+ * Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with the
+ * second 32-bits of the key, and so on for all bits of the key
+ * (up to P[17]). Repeatedly cycle through the key bits until the
+ * entire P-array has been XOR-ed with the key bits
+ */
+ int keyLength = key.length;
+ int keyIndex = 0;
+
+ for (int i=0; i < P_SZ; i++)
+ {
+ // get the 32 bits of the key, in 4 * 8 bit chunks
+ int data = 0x0000000;
+ for (int j=0; j < 4; j++)
+ {
+ // create a 32 bit block
+ data = (data << 8) | (key[keyIndex++] & 0xff);
+
+ // wrap when we get to the end of the key
+ if (keyIndex >= keyLength)
+ {
+ keyIndex = 0;
+ }
+ }
+ // XOR the newly created 32 bit chunk onto the P-array
+ P[i] ^= data;
+ }
+
+ /*
+ * (3)
+ * Encrypt the all-zero string with the Blowfish algorithm, using
+ * the subkeys described in (1) and (2)
+ *
+ * (4)
+ * Replace P1 and P2 with the output of step (3)
+ *
+ * (5)
+ * Encrypt the output of step(3) using the Blowfish algorithm,
+ * with the modified subkeys.
+ *
+ * (6)
+ * Replace P3 and P4 with the output of step (5)
+ *
+ * (7)
+ * Continue the process, replacing all elements of the P-array
+ * and then all four S-boxes in order, with the output of the
+ * continuously changing Blowfish algorithm
+ */
+
+ processTable(0, 0, P);
+ processTable(P[P_SZ - 2], P[P_SZ - 1], S0);
+ processTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1);
+ processTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2);
+ processTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3);
+ }
+
+ /**
+ * Encrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ * The input will be an exact multiple of our blocksize.
+ */
+ private void encryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+ int xl = BytesTo32bits(src, srcIndex);
+ int xr = BytesTo32bits(src, srcIndex+4);
+
+ xl ^= P[0];
+
+ for (int i = 1; i < ROUNDS; i += 2)
+ {
+ xr ^= F(xl) ^ P[i];
+ xl ^= F(xr) ^ P[i + 1];
+ }
+
+ xr ^= P[ROUNDS + 1];
+
+ Bits32ToBytes(xr, dst, dstIndex);
+ Bits32ToBytes(xl, dst, dstIndex + 4);
+ }
+
+ /**
+ * Decrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ * The input will be an exact multiple of our blocksize.
+ */
+ private void decryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+ int xl = BytesTo32bits(src, srcIndex);
+ int xr = BytesTo32bits(src, srcIndex + 4);
+
+ xl ^= P[ROUNDS + 1];
+
+ for (int i = ROUNDS; i > 0 ; i -= 2)
+ {
+ xr ^= F(xl) ^ P[i];
+ xl ^= F(xr) ^ P[i - 1];
+ }
+
+ xr ^= P[0];
+
+ Bits32ToBytes(xr, dst, dstIndex);
+ Bits32ToBytes(xl, dst, dstIndex+4);
+ }
+
+ private int BytesTo32bits(byte[] b, int i)
+ {
+ return ((b[i] & 0xff) << 24) |
+ ((b[i+1] & 0xff) << 16) |
+ ((b[i+2] & 0xff) << 8) |
+ ((b[i+3] & 0xff));
+ }
+
+ private void Bits32ToBytes(int in, byte[] b, int offset)
+ {
+ b[offset + 3] = (byte)in;
+ b[offset + 2] = (byte)(in >> 8);
+ b[offset + 1] = (byte)(in >> 16);
+ b[offset] = (byte)(in >> 24);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/CAST5Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/CAST5Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/CAST5Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/CAST5Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,830 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * A class that provides CAST key encryption operations,
+ * such as encoding data and generating keys.
+ *
+ * All the algorithms herein are from the Internet RFC's
+ *
+ * RFC2144 - CAST5 (64bit block, 40-128bit key)
+ * RFC2612 - CAST6 (128bit block, 128-256bit key)
+ *
+ * and implement a simplified cryptography interface.
+ */
+public class CAST5Engine
+ implements BlockCipher
+{
+ protected final static int M32 = 0xffffffff;
+
+ protected final static int[]
+ S1 = {
+0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
+0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
+0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
+0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
+0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
+0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
+0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
+0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
+0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
+0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
+0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
+0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
+0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
+0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
+0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
+0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
+0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
+ },
+ S2 = {
+0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
+0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
+0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
+0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
+0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
+0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
+0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
+0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
+0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
+0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
+0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
+0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
+0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
+0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
+0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
+0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1
+ },
+ S3 = {
+0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
+0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
+0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
+0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
+0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
+0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
+0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
+0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
+0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
+0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
+0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
+0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
+0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
+0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
+0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
+0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
+0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
+0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
+0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783
+ },
+ S4 = {
+0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
+0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
+0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
+0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
+0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
+0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
+0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
+0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
+0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
+0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
+0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
+0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
+0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
+0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
+0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
+0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
+0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
+ },
+ S5 = {
+0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
+0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
+0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
+0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
+0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
+0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
+0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
+0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
+0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
+0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
+0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
+0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
+0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
+0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
+0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
+0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
+0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
+0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
+0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
+0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
+0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
+0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
+0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
+0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
+0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
+0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
+0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
+0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
+0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
+0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
+0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
+0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4
+ },
+ S6 = {
+0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
+0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
+0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
+0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
+0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
+0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
+0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
+0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
+0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
+0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
+0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
+0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
+0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
+0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
+0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
+0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
+0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
+0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
+0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
+0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
+0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
+0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
+0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
+0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
+0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
+0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
+0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
+0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
+0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
+0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
+0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
+0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f
+ },
+ S7 = {
+0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
+0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
+0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
+0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
+0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
+0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
+0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
+0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
+0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
+0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
+0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
+0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
+0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
+0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
+0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
+0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
+0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
+0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
+0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
+0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
+0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
+0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
+0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
+0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
+0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
+0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
+0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
+0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
+0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
+0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
+0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
+0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3
+ },
+ S8 = {
+0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
+0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
+0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
+0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
+0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
+0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
+0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
+0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
+0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
+0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
+0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
+0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
+0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
+0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
+0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
+0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
+0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
+0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
+0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
+0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
+0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
+0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
+0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
+0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
+0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
+0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
+0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
+0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
+0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
+0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
+0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
+0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e
+ };
+
+ //====================================
+ // Useful constants
+ //====================================
+
+ protected static final int MAX_ROUNDS = 16;
+ protected static final int RED_ROUNDS = 12;
+
+ protected static final int BLOCK_SIZE = 8; // bytes = 64 bits
+
+ protected int _Kr[] = new int[17]; // the rotating round key
+ protected int _Km[] = new int[17]; // the masking round key
+
+ private boolean _encrypting = false;
+
+ private byte[] _workingKey = null;
+ private int _rounds = MAX_ROUNDS;
+
+ public CAST5Engine()
+ {
+ }
+
+ /**
+ * initialise a CAST cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ _encrypting = encrypting;
+ _workingKey = ((KeyParameter)params).getKey();
+
+ setKey(_workingKey);
+
+ return;
+ }
+
+ throw new IllegalArgumentException("Invalid parameter passed to "+getAlgorithmName()+" init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "CAST5";
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (_workingKey == null)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ int blockSize = getBlockSize();
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("Input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("Output buffer too short");
+ }
+
+ if (_encrypting)
+ {
+ return encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ return decryptBlock(in, inOff, out, outOff);
+ }
+ }
+
+ public void reset()
+ {
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ //==================================
+ // Private Implementation
+ //==================================
+
+ /*
+ * Creates the subkeys using the same nomenclature
+ * as described in RFC2144.
+ *
+ * See section 2.4
+ */
+ protected void setKey(byte[] key)
+ {
+ /*
+ * Determine the key size here, if required
+ *
+ * if keysize <= 80bits, use 12 rounds instead of 16
+ * if keysize < 128bits, pad with 0
+ *
+ * Typical key sizes => 40, 64, 80, 128
+ */
+
+ if (key.length < 11)
+ {
+ _rounds = RED_ROUNDS;
+ }
+
+ int z[] = new int[16];
+ int x[] = new int[16];
+
+ int z03, z47, z8B, zCF;
+ int x03, x47, x8B, xCF;
+
+ /* copy the key into x */
+ for (int i=0; i< key.length; i++)
+ {
+ x[i] = key[i] & 0xff;
+ }
+
+ /*
+ * This will look different because the selection of
+ * bytes from the input key I've already chosen the
+ * correct int.
+ */
+ x03 = IntsTo32bits(x, 0x0);
+ x47 = IntsTo32bits(x, 0x4);
+ x8B = IntsTo32bits(x, 0x8);
+ xCF = IntsTo32bits(x, 0xC);
+
+ z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
+
+ Bits32ToInts(z03, z, 0x0);
+ z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
+ Bits32ToInts(z47, z, 0x4);
+ z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
+ Bits32ToInts(z8B, z, 0x8);
+ zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
+ Bits32ToInts(zCF, z, 0xC);
+ _Km[ 1]= S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]];
+ _Km[ 2]= S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]];
+ _Km[ 3]= S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]];
+ _Km[ 4]= S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]];
+
+ z03 = IntsTo32bits(z, 0x0);
+ z47 = IntsTo32bits(z, 0x4);
+ z8B = IntsTo32bits(z, 0x8);
+ zCF = IntsTo32bits(z, 0xC);
+ x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
+ Bits32ToInts(x03, x, 0x0);
+ x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
+ Bits32ToInts(x47, x, 0x4);
+ x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
+ Bits32ToInts(x8B, x, 0x8);
+ xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
+ Bits32ToInts(xCF, x, 0xC);
+ _Km[ 5]= S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]];
+ _Km[ 6]= S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]];
+ _Km[ 7]= S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]];
+ _Km[ 8]= S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]];
+
+ x03 = IntsTo32bits(x, 0x0);
+ x47 = IntsTo32bits(x, 0x4);
+ x8B = IntsTo32bits(x, 0x8);
+ xCF = IntsTo32bits(x, 0xC);
+ z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
+ Bits32ToInts(z03, z, 0x0);
+ z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
+ Bits32ToInts(z47, z, 0x4);
+ z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
+ Bits32ToInts(z8B, z, 0x8);
+ zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
+ Bits32ToInts(zCF, z, 0xC);
+ _Km[ 9]= S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]];
+ _Km[10]= S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]];
+ _Km[11]= S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]];
+ _Km[12]= S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]];
+
+ z03 = IntsTo32bits(z, 0x0);
+ z47 = IntsTo32bits(z, 0x4);
+ z8B = IntsTo32bits(z, 0x8);
+ zCF = IntsTo32bits(z, 0xC);
+ x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
+ Bits32ToInts(x03, x, 0x0);
+ x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
+ Bits32ToInts(x47, x, 0x4);
+ x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
+ Bits32ToInts(x8B, x, 0x8);
+ xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
+ Bits32ToInts(xCF, x, 0xC);
+ _Km[13]= S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]];
+ _Km[14]= S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]];
+ _Km[15]= S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]];
+ _Km[16]= S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]];
+
+ x03 = IntsTo32bits(x, 0x0);
+ x47 = IntsTo32bits(x, 0x4);
+ x8B = IntsTo32bits(x, 0x8);
+ xCF = IntsTo32bits(x, 0xC);
+ z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
+ Bits32ToInts(z03, z, 0x0);
+ z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
+ Bits32ToInts(z47, z, 0x4);
+ z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
+ Bits32ToInts(z8B, z, 0x8);
+ zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
+ Bits32ToInts(zCF, z, 0xC);
+ _Kr[ 1]=(S5[z[0x8]]^S6[z[0x9]]^S7[z[0x7]]^S8[z[0x6]] ^ S5[z[0x2]])&0x1f;
+ _Kr[ 2]=(S5[z[0xA]]^S6[z[0xB]]^S7[z[0x5]]^S8[z[0x4]] ^ S6[z[0x6]])&0x1f;
+ _Kr[ 3]=(S5[z[0xC]]^S6[z[0xD]]^S7[z[0x3]]^S8[z[0x2]] ^ S7[z[0x9]])&0x1f;
+ _Kr[ 4]=(S5[z[0xE]]^S6[z[0xF]]^S7[z[0x1]]^S8[z[0x0]] ^ S8[z[0xC]])&0x1f;
+
+ z03 = IntsTo32bits(z, 0x0);
+ z47 = IntsTo32bits(z, 0x4);
+ z8B = IntsTo32bits(z, 0x8);
+ zCF = IntsTo32bits(z, 0xC);
+ x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
+ Bits32ToInts(x03, x, 0x0);
+ x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
+ Bits32ToInts(x47, x, 0x4);
+ x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
+ Bits32ToInts(x8B, x, 0x8);
+ xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
+ Bits32ToInts(xCF, x, 0xC);
+ _Kr[ 5]=(S5[x[0x3]]^S6[x[0x2]]^S7[x[0xC]]^S8[x[0xD]]^S5[x[0x8]])&0x1f;
+ _Kr[ 6]=(S5[x[0x1]]^S6[x[0x0]]^S7[x[0xE]]^S8[x[0xF]]^S6[x[0xD]])&0x1f;
+ _Kr[ 7]=(S5[x[0x7]]^S6[x[0x6]]^S7[x[0x8]]^S8[x[0x9]]^S7[x[0x3]])&0x1f;
+ _Kr[ 8]=(S5[x[0x5]]^S6[x[0x4]]^S7[x[0xA]]^S8[x[0xB]]^S8[x[0x7]])&0x1f;
+
+ x03 = IntsTo32bits(x, 0x0);
+ x47 = IntsTo32bits(x, 0x4);
+ x8B = IntsTo32bits(x, 0x8);
+ xCF = IntsTo32bits(x, 0xC);
+ z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
+ Bits32ToInts(z03, z, 0x0);
+ z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
+ Bits32ToInts(z47, z, 0x4);
+ z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
+ Bits32ToInts(z8B, z, 0x8);
+ zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
+ Bits32ToInts(zCF, z, 0xC);
+ _Kr[ 9]=(S5[z[0x3]]^S6[z[0x2]]^S7[z[0xC]]^S8[z[0xD]]^S5[z[0x9]])&0x1f;
+ _Kr[10]=(S5[z[0x1]]^S6[z[0x0]]^S7[z[0xE]]^S8[z[0xF]]^S6[z[0xc]])&0x1f;
+ _Kr[11]=(S5[z[0x7]]^S6[z[0x6]]^S7[z[0x8]]^S8[z[0x9]]^S7[z[0x2]])&0x1f;
+ _Kr[12]=(S5[z[0x5]]^S6[z[0x4]]^S7[z[0xA]]^S8[z[0xB]]^S8[z[0x6]])&0x1f;
+
+ z03 = IntsTo32bits(z, 0x0);
+ z47 = IntsTo32bits(z, 0x4);
+ z8B = IntsTo32bits(z, 0x8);
+ zCF = IntsTo32bits(z, 0xC);
+ x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
+ Bits32ToInts(x03, x, 0x0);
+ x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
+ Bits32ToInts(x47, x, 0x4);
+ x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
+ Bits32ToInts(x8B, x, 0x8);
+ xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
+ Bits32ToInts(xCF, x, 0xC);
+ _Kr[13]=(S5[x[0x8]]^S6[x[0x9]]^S7[x[0x7]]^S8[x[0x6]]^S5[x[0x3]])&0x1f;
+ _Kr[14]=(S5[x[0xA]]^S6[x[0xB]]^S7[x[0x5]]^S8[x[0x4]]^S6[x[0x7]])&0x1f;
+ _Kr[15]=(S5[x[0xC]]^S6[x[0xD]]^S7[x[0x3]]^S8[x[0x2]]^S7[x[0x8]])&0x1f;
+ _Kr[16]=(S5[x[0xE]]^S6[x[0xF]]^S7[x[0x1]]^S8[x[0x0]]^S8[x[0xD]])&0x1f;
+ }
+
+ /**
+ * Encrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ *
+ * @param src The plaintext buffer
+ * @param srcIndex An offset into src
+ * @param dst The ciphertext buffer
+ * @param dstIndex An offset into dst
+ */
+ protected int encryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+
+ int result[] = new int[2];
+
+ // process the input block
+ // batch the units up into a 32 bit chunk and go for it
+ // the array is in bytes, the increment is 8x8 bits = 64
+
+ int L0 = BytesTo32bits(src, srcIndex);
+ int R0 = BytesTo32bits(src, srcIndex + 4);
+
+ CAST_Encipher(L0, R0, result);
+
+ // now stuff them into the destination block
+ Bits32ToBytes(result[0], dst, dstIndex);
+ Bits32ToBytes(result[1], dst, dstIndex + 4);
+
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * Decrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ *
+ * @param src The plaintext buffer
+ * @param srcIndex An offset into src
+ * @param dst The ciphertext buffer
+ * @param dstIndex An offset into dst
+ */
+ protected int decryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+ int result[] = new int[2];
+
+ // process the input block
+ // batch the units up into a 32 bit chunk and go for it
+ // the array is in bytes, the increment is 8x8 bits = 64
+ int L16 = BytesTo32bits(src, srcIndex);
+ int R16 = BytesTo32bits(src, srcIndex+4);
+
+ CAST_Decipher(L16, R16, result);
+
+ // now stuff them into the destination block
+ Bits32ToBytes(result[0], dst, dstIndex);
+ Bits32ToBytes(result[1], dst, dstIndex+4);
+
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * The first of the three processing functions for the
+ * encryption and decryption.
+ *
+ * @param D the input to be processed
+ * @param Kmi the mask to be used from Km[n]
+ * @param Kri the rotation value to be used
+ *
+ */
+ protected final int F1(int D, int Kmi, int Kri)
+ {
+ int I = Kmi + D;
+ I = I << Kri | I >>> (32-Kri);
+ return ((S1[(I>>>24)&0xff]^S2[(I>>>16)&0xff])-S3[(I>>> 8)&0xff])+
+ S4[I & 0xff];
+ }
+
+ /**
+ * The second of the three processing functions for the
+ * encryption and decryption.
+ *
+ * @param D the input to be processed
+ * @param Kmi the mask to be used from Km[n]
+ * @param Kri the rotation value to be used
+ *
+ */
+ protected final int F2(int D, int Kmi, int Kri)
+ {
+ int I = Kmi ^ D;
+ I = I << Kri | I >>> (32-Kri);
+ return ((S1[(I>>>24)&0xff]-S2[(I>>>16)&0xff])+S3[(I>>> 8)&0xff])^
+ S4[I & 0xff];
+ }
+
+ /**
+ * The third of the three processing functions for the
+ * encryption and decryption.
+ *
+ * @param D the input to be processed
+ * @param Kmi the mask to be used from Km[n]
+ * @param Kri the rotation value to be used
+ *
+ */
+ protected final int F3(int D, int Kmi, int Kri)
+ {
+ int I = Kmi - D;
+ I = I << Kri | I >>> (32-Kri);
+ return ((S1[(I>>>24)&0xff]+S2[(I>>>16)&0xff])^S3[(I>>> 8)&0xff])-
+ S4[I & 0xff];
+ }
+
+ /**
+ * Does the 16 rounds to encrypt the block.
+ *
+ * @param L0 the LH-32bits of the plaintext block
+ * @param R0 the RH-32bits of the plaintext block
+ */
+ protected final void CAST_Encipher(int L0, int R0, int result[])
+ {
+ int Lp = L0; // the previous value, equiv to L[i-1]
+ int Rp = R0; // equivalent to R[i-1]
+
+ /*
+ * numbering consistent with paper to make
+ * checking and validating easier
+ */
+ int Li = L0, Ri = R0;
+
+ for (int i = 1; i<=_rounds ; i++)
+ {
+ Lp = Li;
+ Rp = Ri;
+
+ Li = Rp;
+ switch (i)
+ {
+ case 1:
+ case 4:
+ case 7:
+ case 10:
+ case 13:
+ case 16:
+ Ri = Lp ^ F1(Rp, _Km[i], _Kr[i]);
+ break;
+ case 2:
+ case 5:
+ case 8:
+ case 11:
+ case 14:
+ Ri = Lp ^ F2(Rp, _Km[i], _Kr[i]);
+ break;
+ case 3:
+ case 6:
+ case 9:
+ case 12:
+ case 15:
+ Ri = Lp ^ F3(Rp, _Km[i], _Kr[i]);
+ break;
+ }
+ }
+
+ result[0] = Ri;
+ result[1] = Li;
+
+ return;
+ }
+
+ protected final void CAST_Decipher(int L16, int R16, int result[])
+ {
+ int Lp = L16; // the previous value, equiv to L[i-1]
+ int Rp = R16; // equivalent to R[i-1]
+
+ /*
+ * numbering consistent with paper to make
+ * checking and validating easier
+ */
+ int Li = L16, Ri = R16;
+
+ for (int i = _rounds; i > 0; i--)
+ {
+ Lp = Li;
+ Rp = Ri;
+
+ Li = Rp;
+ switch (i)
+ {
+ case 1:
+ case 4:
+ case 7:
+ case 10:
+ case 13:
+ case 16:
+ Ri = Lp ^ F1(Rp, _Km[i], _Kr[i]);
+ break;
+ case 2:
+ case 5:
+ case 8:
+ case 11:
+ case 14:
+ Ri = Lp ^ F2(Rp, _Km[i], _Kr[i]);
+ break;
+ case 3:
+ case 6:
+ case 9:
+ case 12:
+ case 15:
+ Ri = Lp ^ F3(Rp, _Km[i], _Kr[i]);
+ break;
+ }
+ }
+
+ result[0] = Ri;
+ result[1] = Li;
+
+ return;
+ }
+
+ protected final void Bits32ToInts(int in, int[] b, int offset)
+ {
+ b[offset + 3] = (in & 0xff);
+ b[offset + 2] = ((in >>> 8) & 0xff);
+ b[offset + 1] = ((in >>> 16) & 0xff);
+ b[offset] = ((in >>> 24) & 0xff);
+ }
+
+ protected final int IntsTo32bits(int[] b, int i)
+ {
+ int rv = 0;
+
+ rv = ((b[i] & 0xff) << 24) |
+ ((b[i+1] & 0xff) << 16) |
+ ((b[i+2] & 0xff) << 8) |
+ ((b[i+3] & 0xff));
+
+ return rv;
+ }
+
+ protected final void Bits32ToBytes(int in, byte[] b, int offset)
+ {
+ b[offset + 3] = (byte)in;
+ b[offset + 2] = (byte)(in >>> 8);
+ b[offset + 1] = (byte)(in >>> 16);
+ b[offset] = (byte)(in >>> 24);
+ }
+
+ protected final int BytesTo32bits(byte[] b, int i)
+ {
+ return ((b[i] & 0xff) << 24) |
+ ((b[i+1] & 0xff) << 16) |
+ ((b[i+2] & 0xff) << 8) |
+ ((b[i+3] & 0xff));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/CAST6Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/CAST6Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/CAST6Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/CAST6Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,296 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+
+/**
+ * A class that provides CAST6 key encryption operations,
+ * such as encoding data and generating keys.
+ *
+ * All the algorithms herein are from the Internet RFC
+ *
+ * RFC2612 - CAST6 (128bit block, 128-256bit key)
+ *
+ * and implement a simplified cryptography interface.
+ */
+public final class CAST6Engine extends CAST5Engine
+{
+ //====================================
+ // Useful constants
+ //====================================
+
+ protected static final int ROUNDS = 12;
+
+ protected static final int BLOCK_SIZE = 16; // bytes = 128 bits
+
+ /*
+ * Put the round and mask keys into an array.
+ * Kr0[i] => _Kr[i*4 + 0]
+ */
+ protected int _Kr[] = new int[ROUNDS*4]; // the rotating round key(s)
+ protected int _Km[] = new int[ROUNDS*4]; // the masking round key(s)
+
+ /*
+ * Key setup
+ */
+ protected int _Tr[] = new int[24 * 8];
+ protected int _Tm[] = new int[24 * 8];
+
+ private int[] _workingKey = new int[8];
+
+ public CAST6Engine()
+ {
+ }
+
+ public String getAlgorithmName()
+ {
+ return "CAST6";
+ }
+
+ public void reset()
+ {
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ //==================================
+ // Private Implementation
+ //==================================
+
+ /*
+ * Creates the subkeys using the same nomenclature
+ * as described in RFC2612.
+ *
+ * See section 2.4
+ */
+ protected void setKey(byte[] key)
+ {
+ int Cm = 0x5a827999;
+ int Mm = 0x6ed9eba1;
+ int Cr = 19;
+ int Mr = 17;
+
+ /*
+ * Determine the key size here, if required
+ *
+ * if keysize < 256 bytes, pad with 0
+ *
+ * Typical key sizes => 128, 160, 192, 224, 256
+ */
+ for (int i=0; i< 24; i++)
+ {
+ for (int j=0; j< 8; j++)
+ {
+ _Tm[i*8 + j] = Cm;
+ Cm = (Cm + Mm); // mod 2^32;
+
+ _Tr[i*8 + j] = Cr;
+ Cr = (Cr + Mr) & 0x1f; // mod 32
+ }
+ }
+
+ byte[] tmpKey = new byte[64];
+ int length = key.length;
+ System.arraycopy(key, 0, tmpKey, 0, length);
+
+ // now create ABCDEFGH
+ for (int i=0; i< 8; i++)
+ {
+ _workingKey[i] = BytesTo32bits(tmpKey, i*4);
+ }
+
+ // Generate the key schedule
+ for (int i=0; i< 12; i++)
+ {
+ // KAPPA <- W2i(KAPPA)
+ int i2 = i*2 *8;
+ _workingKey[6] ^= F1(_workingKey[7], _Tm[i2 ], _Tr[i2 ]);
+ _workingKey[5] ^= F2(_workingKey[6], _Tm[i2+1], _Tr[i2+1]);
+ _workingKey[4] ^= F3(_workingKey[5], _Tm[i2+2], _Tr[i2+2]);
+ _workingKey[3] ^= F1(_workingKey[4], _Tm[i2+3], _Tr[i2+3]);
+ _workingKey[2] ^= F2(_workingKey[3], _Tm[i2+4], _Tr[i2+4]);
+ _workingKey[1] ^= F3(_workingKey[2], _Tm[i2+5], _Tr[i2+5]);
+ _workingKey[0] ^= F1(_workingKey[1], _Tm[i2+6], _Tr[i2+6]);
+ _workingKey[7] ^= F2(_workingKey[0], _Tm[i2+7], _Tr[i2+7]);
+
+ // KAPPA <- W2i+1(KAPPA)
+ i2 = (i*2 + 1)*8;
+ _workingKey[6] ^= F1(_workingKey[7], _Tm[i2 ], _Tr[i2 ]);
+ _workingKey[5] ^= F2(_workingKey[6], _Tm[i2+1], _Tr[i2+1]);
+ _workingKey[4] ^= F3(_workingKey[5], _Tm[i2+2], _Tr[i2+2]);
+ _workingKey[3] ^= F1(_workingKey[4], _Tm[i2+3], _Tr[i2+3]);
+ _workingKey[2] ^= F2(_workingKey[3], _Tm[i2+4], _Tr[i2+4]);
+ _workingKey[1] ^= F3(_workingKey[2], _Tm[i2+5], _Tr[i2+5]);
+ _workingKey[0] ^= F1(_workingKey[1], _Tm[i2+6], _Tr[i2+6]);
+ _workingKey[7] ^= F2(_workingKey[0], _Tm[i2+7], _Tr[i2+7]);
+
+ // Kr_(i) <- KAPPA
+ _Kr[i*4 ] = _workingKey[0] & 0x1f;
+ _Kr[i*4 + 1] = _workingKey[2] & 0x1f;
+ _Kr[i*4 + 2] = _workingKey[4] & 0x1f;
+ _Kr[i*4 + 3] = _workingKey[6] & 0x1f;
+
+
+ // Km_(i) <- KAPPA
+ _Km[i*4 ] = _workingKey[7];
+ _Km[i*4 + 1] = _workingKey[5];
+ _Km[i*4 + 2] = _workingKey[3];
+ _Km[i*4 + 3] = _workingKey[1];
+ }
+
+ }
+
+ /**
+ * Encrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ *
+ * @param src The plaintext buffer
+ * @param srcIndex An offset into src
+ * @param dst The ciphertext buffer
+ * @param dstIndex An offset into dst
+ */
+ protected int encryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+
+ int result[] = new int[4];
+
+ // process the input block
+ // batch the units up into 4x32 bit chunks and go for it
+
+ int A = BytesTo32bits(src, srcIndex);
+ int B = BytesTo32bits(src, srcIndex + 4);
+ int C = BytesTo32bits(src, srcIndex + 8);
+ int D = BytesTo32bits(src, srcIndex + 12);
+
+ CAST_Encipher(A, B, C, D, result);
+
+ // now stuff them into the destination block
+ Bits32ToBytes(result[0], dst, dstIndex);
+ Bits32ToBytes(result[1], dst, dstIndex + 4);
+ Bits32ToBytes(result[2], dst, dstIndex + 8);
+ Bits32ToBytes(result[3], dst, dstIndex + 12);
+
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * Decrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ *
+ * @param src The plaintext buffer
+ * @param srcIndex An offset into src
+ * @param dst The ciphertext buffer
+ * @param dstIndex An offset into dst
+ */
+ protected int decryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+ int result[] = new int[4];
+
+ // process the input block
+ // batch the units up into 4x32 bit chunks and go for it
+ int A = BytesTo32bits(src, srcIndex);
+ int B = BytesTo32bits(src, srcIndex + 4);
+ int C = BytesTo32bits(src, srcIndex + 8);
+ int D = BytesTo32bits(src, srcIndex + 12);
+
+ CAST_Decipher(A, B, C, D, result);
+
+ // now stuff them into the destination block
+ Bits32ToBytes(result[0], dst, dstIndex);
+ Bits32ToBytes(result[1], dst, dstIndex + 4);
+ Bits32ToBytes(result[2], dst, dstIndex + 8);
+ Bits32ToBytes(result[3], dst, dstIndex + 12);
+
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * Does the 12 quad rounds rounds to encrypt the block.
+ *
+ * @param A the 00-31 bits of the plaintext block
+ * @param B the 32-63 bits of the plaintext block
+ * @param C the 64-95 bits of the plaintext block
+ * @param D the 96-127 bits of the plaintext block
+ * @param result the resulting ciphertext
+ */
+ protected final void CAST_Encipher(int A, int B, int C, int D,int result[])
+ {
+ int x;
+ for (int i=0; i< 6; i++)
+ {
+ x = i*4;
+ // BETA <- Qi(BETA)
+ C ^= F1(D, _Km[x], _Kr[x]);
+ B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
+ A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
+ D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
+
+ }
+
+ for (int i=6; i<12; i++)
+ {
+ x = i*4;
+ // BETA <- QBARi(BETA)
+ D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
+ A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
+ B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
+ C ^= F1(D, _Km[x], _Kr[x]);
+
+ }
+
+ result[0] = A;
+ result[1] = B;
+ result[2] = C;
+ result[3] = D;
+ }
+
+ /**
+ * Does the 12 quad rounds rounds to decrypt the block.
+ *
+ * @param A the 00-31 bits of the ciphertext block
+ * @param B the 32-63 bits of the ciphertext block
+ * @param C the 64-95 bits of the ciphertext block
+ * @param D the 96-127 bits of the ciphertext block
+ * @param result the resulting plaintext
+ */
+ protected final void CAST_Decipher(int A, int B, int C, int D,int result[])
+ {
+ int x;
+ for (int i=0; i< 6; i++)
+ {
+ x = (11-i)*4;
+ // BETA <- Qi(BETA)
+ C ^= F1(D, _Km[x], _Kr[x]);
+ B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
+ A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
+ D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
+
+ }
+
+ for (int i=6; i<12; i++)
+ {
+ x = (11-i)*4;
+ // BETA <- QBARi(BETA)
+ D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
+ A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
+ B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
+ C ^= F1(D, _Km[x], _Kr[x]);
+
+ }
+
+ result[0] = A;
+ result[1] = B;
+ result[2] = C;
+ result[3] = D;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/CamelliaEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/CamelliaEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/CamelliaEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/CamelliaEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,683 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * Camellia - based on RFC 3713.
+ */
+public class CamelliaEngine
+ implements BlockCipher
+{
+ private boolean initialised = false;
+ private boolean _keyIs128;
+
+ private static final int BLOCK_SIZE = 16;
+ private static final int MASK8 = 0xff;
+
+ private int[] subkey = new int[24 * 4];
+ private int[] kw = new int[4 * 2]; // for whitening
+ private int[] ke = new int[6 * 2]; // for FL and FL^(-1)
+ private int[] state = new int[4]; // for encryption and decryption
+
+ private static final int SIGMA[] = {
+ 0xa09e667f, 0x3bcc908b,
+ 0xb67ae858, 0x4caa73b2,
+ 0xc6ef372f, 0xe94f82be,
+ 0x54ff53a5, 0xf1d36f1c,
+ 0x10e527fa, 0xde682d1d,
+ 0xb05688c2, 0xb3e6c1fd
+ };
+
+ /*
+ *
+ * S-box data
+ *
+ */
+ private static final int SBOX1_1110[] = {
+ 0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, 0xb3b3b300, 0x27272700,
+ 0xc0c0c000, 0xe5e5e500, 0xe4e4e400, 0x85858500, 0x57575700, 0x35353500,
+ 0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100, 0x23232300, 0xefefef00,
+ 0x6b6b6b00, 0x93939300, 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100,
+ 0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, 0x1d1d1d00, 0x65656500,
+ 0x92929200, 0xbdbdbd00, 0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00,
+ 0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00, 0x3e3e3e00, 0x30303000,
+ 0xdcdcdc00, 0x5f5f5f00, 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00,
+ 0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, 0xd5d5d500, 0x47474700,
+ 0x5d5d5d00, 0x3d3d3d00, 0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600,
+ 0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00, 0x8b8b8b00, 0x0d0d0d00,
+ 0x9a9a9a00, 0x66666600, 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00,
+ 0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, 0xf0f0f000, 0xb1b1b100,
+ 0x84848400, 0x99999900, 0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200,
+ 0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500, 0x6d6d6d00, 0xb7b7b700,
+ 0xa9a9a900, 0x31313100, 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700,
+ 0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, 0xdedede00, 0x1b1b1b00,
+ 0x11111100, 0x1c1c1c00, 0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600,
+ 0x53535300, 0x18181800, 0xf2f2f200, 0x22222200, 0xfefefe00, 0x44444400,
+ 0xcfcfcf00, 0xb2b2b200, 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100,
+ 0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, 0x60606000, 0xfcfcfc00,
+ 0x69696900, 0x50505000, 0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00,
+ 0xa1a1a100, 0x89898900, 0x62626200, 0x97979700, 0x54545400, 0x5b5b5b00,
+ 0x1e1e1e00, 0x95959500, 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200,
+ 0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, 0xa3a3a300, 0xf7f7f700,
+ 0x75757500, 0xdbdbdb00, 0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00,
+ 0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400, 0x87878700, 0x5c5c5c00,
+ 0x83838300, 0x02020200, 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300,
+ 0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, 0x9d9d9d00, 0x7f7f7f00,
+ 0xbfbfbf00, 0xe2e2e200, 0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600,
+ 0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00, 0x81818100, 0x96969600,
+ 0x6f6f6f00, 0x4b4b4b00, 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00,
+ 0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, 0x9f9f9f00, 0x6e6e6e00,
+ 0xbcbcbc00, 0x8e8e8e00, 0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600,
+ 0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900, 0x78787800, 0x98989800,
+ 0x06060600, 0x6a6a6a00, 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00,
+ 0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, 0x88888800, 0xa2a2a200,
+ 0x8d8d8d00, 0xfafafa00, 0x72727200, 0x07070700, 0xb9b9b900, 0x55555500,
+ 0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00, 0x36363600, 0x49494900,
+ 0x2a2a2a00, 0x68686800, 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400,
+ 0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, 0xbbbbbb00, 0xc9c9c900,
+ 0x43434300, 0xc1c1c100, 0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400,
+ 0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00
+ };
+
+ private static final int SBOX4_4404[] = {
+ 0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, 0xe4e400e4, 0x57570057,
+ 0xeaea00ea, 0xaeae00ae, 0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5,
+ 0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092, 0x86860086, 0xafaf00af,
+ 0x7c7c007c, 0x1f1f001f, 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b,
+ 0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, 0xd9d900d9, 0x5a5a005a,
+ 0x51510051, 0x6c6c006c, 0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0,
+ 0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084, 0xdfdf00df, 0xcbcb00cb,
+ 0x34340034, 0x76760076, 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004,
+ 0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, 0x32320032, 0x9c9c009c,
+ 0x53530053, 0xf2f200f2, 0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a,
+ 0x24240024, 0xe8e800e8, 0x60600060, 0x69690069, 0xaaaa00aa, 0xa0a000a0,
+ 0xa1a100a1, 0x62620062, 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064,
+ 0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, 0x8a8a008a, 0xe6e600e6,
+ 0x09090009, 0xdddd00dd, 0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090,
+ 0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf, 0x52520052, 0xd8d800d8,
+ 0xc8c800c8, 0xc6c600c6, 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063,
+ 0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, 0x29290029, 0xf9f900f9,
+ 0x2f2f002f, 0xb4b400b4, 0x78780078, 0x06060006, 0xe7e700e7, 0x71710071,
+ 0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d, 0x72720072, 0xb9b900b9,
+ 0xf8f800f8, 0xacac00ac, 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1,
+ 0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, 0x15150015, 0xadad00ad,
+ 0x77770077, 0x80800080, 0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5,
+ 0x85850085, 0x35350035, 0x0c0c000c, 0x41410041, 0xefef00ef, 0x93930093,
+ 0x19190019, 0x21210021, 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd,
+ 0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, 0x30300030, 0x5f5f005f,
+ 0xc5c500c5, 0x1a1a001a, 0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d,
+ 0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d, 0x0d0d000d, 0x66660066,
+ 0xcccc00cc, 0x2d2d002d, 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099,
+ 0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, 0xb7b700b7, 0x31310031,
+ 0x17170017, 0xd7d700d7, 0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c,
+ 0x0f0f000f, 0x16160016, 0x18180018, 0x22220022, 0x44440044, 0xb2b200b2,
+ 0xb5b500b5, 0x91910091, 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050,
+ 0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, 0x5b5b005b, 0x95950095,
+ 0xffff00ff, 0xd2d200d2, 0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db,
+ 0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094, 0x5c5c005c, 0x02020002,
+ 0x4a4a004a, 0x33330033, 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2,
+ 0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, 0x96960096, 0x4b4b004b,
+ 0xbebe00be, 0x2e2e002e, 0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e,
+ 0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059, 0x98980098, 0x6a6a006a,
+ 0x46460046, 0xbaba00ba, 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa,
+ 0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, 0x49490049, 0x68680068,
+ 0x38380038, 0xa4a400a4, 0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1,
+ 0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e
+ };
+
+ private static final int SBOX2_0222[] = {
+ 0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, 0x00676767, 0x004e4e4e,
+ 0x00818181, 0x00cbcbcb, 0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a,
+ 0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282, 0x00464646, 0x00dfdfdf,
+ 0x00d6d6d6, 0x00272727, 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242,
+ 0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, 0x003a3a3a, 0x00cacaca,
+ 0x00252525, 0x007b7b7b, 0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f,
+ 0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d, 0x007c7c7c, 0x00606060,
+ 0x00b9b9b9, 0x00bebebe, 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434,
+ 0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, 0x00ababab, 0x008e8e8e,
+ 0x00bababa, 0x007a7a7a, 0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad,
+ 0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a, 0x00171717, 0x001a1a1a,
+ 0x00353535, 0x00cccccc, 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a,
+ 0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, 0x00e1e1e1, 0x00636363,
+ 0x00090909, 0x00333333, 0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585,
+ 0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a, 0x00dadada, 0x006f6f6f,
+ 0x00535353, 0x00626262, 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf,
+ 0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, 0x00bdbdbd, 0x00363636,
+ 0x00222222, 0x00383838, 0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c,
+ 0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444, 0x00fdfdfd, 0x00888888,
+ 0x009f9f9f, 0x00656565, 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323,
+ 0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, 0x00c0c0c0, 0x00f9f9f9,
+ 0x00d2d2d2, 0x00a0a0a0, 0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa,
+ 0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f, 0x00a8a8a8, 0x00b6b6b6,
+ 0x003c3c3c, 0x002b2b2b, 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5,
+ 0x00202020, 0x00898989, 0x00000000, 0x00909090, 0x00474747, 0x00efefef,
+ 0x00eaeaea, 0x00b7b7b7, 0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5,
+ 0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929, 0x000f0f0f, 0x00b8b8b8,
+ 0x00070707, 0x00040404, 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666,
+ 0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, 0x003b3b3b, 0x00fefefe,
+ 0x007f7f7f, 0x00c5c5c5, 0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c,
+ 0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676, 0x00030303, 0x002d2d2d,
+ 0x00dedede, 0x00969696, 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c,
+ 0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, 0x003f3f3f, 0x00dcdcdc,
+ 0x00797979, 0x001d1d1d, 0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d,
+ 0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2, 0x00f0f0f0, 0x00313131,
+ 0x000c0c0c, 0x00d4d4d4, 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575,
+ 0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, 0x00111111, 0x00454545,
+ 0x001b1b1b, 0x00f5f5f5, 0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa,
+ 0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414, 0x006c6c6c, 0x00929292,
+ 0x00545454, 0x00d0d0d0, 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949,
+ 0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, 0x00777777, 0x00939393,
+ 0x00868686, 0x00838383, 0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9,
+ 0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d
+ };
+
+ private static final int SBOX3_3033[] = {
+ 0x38003838, 0x41004141, 0x16001616, 0x76007676, 0xd900d9d9, 0x93009393,
+ 0x60006060, 0xf200f2f2, 0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a,
+ 0x75007575, 0x06000606, 0x57005757, 0xa000a0a0, 0x91009191, 0xf700f7f7,
+ 0xb500b5b5, 0xc900c9c9, 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090,
+ 0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, 0x8e008e8e, 0xb200b2b2,
+ 0x49004949, 0xde00dede, 0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7,
+ 0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767, 0x1f001f1f, 0x18001818,
+ 0x6e006e6e, 0xaf00afaf, 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d,
+ 0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, 0xea00eaea, 0xa300a3a3,
+ 0xae00aeae, 0x9e009e9e, 0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b,
+ 0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6, 0xc500c5c5, 0x86008686,
+ 0x4d004d4d, 0x33003333, 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696,
+ 0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, 0x78007878, 0xd800d8d8,
+ 0x42004242, 0xcc00cccc, 0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161,
+ 0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282, 0xb600b6b6, 0xdb00dbdb,
+ 0xd400d4d4, 0x98009898, 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb,
+ 0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, 0x6f006f6f, 0x8d008d8d,
+ 0x88008888, 0x0e000e0e, 0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b,
+ 0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111, 0x7f007f7f, 0x22002222,
+ 0xe700e7e7, 0x59005959, 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8,
+ 0x12001212, 0x04000404, 0x74007474, 0x54005454, 0x30003030, 0x7e007e7e,
+ 0xb400b4b4, 0x28002828, 0x55005555, 0x68006868, 0x50005050, 0xbe00bebe,
+ 0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb, 0x2a002a2a, 0xad00adad,
+ 0x0f000f0f, 0xca00caca, 0x70007070, 0xff00ffff, 0x32003232, 0x69006969,
+ 0x08000808, 0x62006262, 0x00000000, 0x24002424, 0xd100d1d1, 0xfb00fbfb,
+ 0xba00baba, 0xed00eded, 0x45004545, 0x81008181, 0x73007373, 0x6d006d6d,
+ 0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a, 0xc300c3c3, 0x2e002e2e,
+ 0xc100c1c1, 0x01000101, 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999,
+ 0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, 0xce00cece, 0xbf00bfbf,
+ 0xdf00dfdf, 0x71007171, 0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313,
+ 0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d, 0xc000c0c0, 0x4b004b4b,
+ 0xb700b7b7, 0xa500a5a5, 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717,
+ 0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, 0xcf00cfcf, 0x37003737,
+ 0x5e005e5e, 0x47004747, 0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b,
+ 0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac, 0x3c003c3c, 0x4c004c4c,
+ 0x03000303, 0x35003535, 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d,
+ 0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, 0x44004444, 0x51005151,
+ 0xc600c6c6, 0x7d007d7d, 0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa,
+ 0x7c007c7c, 0x77007777, 0x56005656, 0x05000505, 0x1b001b1b, 0xa400a4a4,
+ 0x15001515, 0x34003434, 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252,
+ 0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, 0xdd00dddd, 0xe400e4e4,
+ 0xa100a1a1, 0xe000e0e0, 0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a,
+ 0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f
+ };
+
+ private static int rightRotate(int x, int s)
+ {
+ return (((x) >>> (s)) + ((x) << (32 - s)));
+ }
+
+ private static int leftRotate(int x, int s)
+ {
+ return ((x) << (s)) + ((x) >>> (32 - s));
+ }
+
+ private static void roldq(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[0 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >>> (32 - rot));
+ ko[1 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >>> (32 - rot));
+ ko[2 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >>> (32 - rot));
+ ko[3 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >>> (32 - rot));
+ ki[0 + ioff] = ko[0 + ooff];
+ ki[1 + ioff] = ko[1 + ooff];
+ ki[2 + ioff] = ko[2 + ooff];
+ ki[3 + ioff] = ko[3 + ooff];
+ }
+
+ private static void decroldq(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[2 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >>> (32 - rot));
+ ko[3 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >>> (32 - rot));
+ ko[0 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >>> (32 - rot));
+ ko[1 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >>> (32 - rot));
+ ki[0 + ioff] = ko[2 + ooff];
+ ki[1 + ioff] = ko[3 + ooff];
+ ki[2 + ioff] = ko[0 + ooff];
+ ki[3 + ioff] = ko[1 + ooff];
+ }
+
+ private static void roldqo32(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[0 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >>> (64 - rot));
+ ko[1 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >>> (64 - rot));
+ ko[2 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >>> (64 - rot));
+ ko[3 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >>> (64 - rot));
+ ki[0 + ioff] = ko[0 + ooff];
+ ki[1 + ioff] = ko[1 + ooff];
+ ki[2 + ioff] = ko[2 + ooff];
+ ki[3 + ioff] = ko[3 + ooff];
+ }
+
+ private static void decroldqo32(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[2 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >>> (64 - rot));
+ ko[3 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >>> (64 - rot));
+ ko[0 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >>> (64 - rot));
+ ko[1 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >>> (64 - rot));
+ ki[0 + ioff] = ko[2 + ooff];
+ ki[1 + ioff] = ko[3 + ooff];
+ ki[2 + ioff] = ko[0 + ooff];
+ ki[3 + ioff] = ko[1 + ooff];
+ }
+
+ private int bytes2int(byte[] src, int offset)
+ {
+ int word = 0;
+
+ for (int i = 0; i < 4; i++)
+ {
+ word = (word << 8) + (src[i + offset] & MASK8);
+ }
+ return word;
+ }
+
+ private void int2bytes(int word, byte[] dst, int offset)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ dst[(3 - i) + offset] = (byte)word;
+ word >>>= 8;
+ }
+ }
+
+ private void camelliaF2(int[] s, int[] skey, int keyoff)
+ {
+ int t1, t2, u, v;
+
+ t1 = s[0] ^ skey[0 + keyoff];
+ u = SBOX4_4404[t1 & MASK8];
+ u ^= SBOX3_3033[(t1 >>> 8) & MASK8];
+ u ^= SBOX2_0222[(t1 >>> 16) & MASK8];
+ u ^= SBOX1_1110[(t1 >>> 24) & MASK8];
+ t2 = s[1] ^ skey[1 + keyoff];
+ v = SBOX1_1110[t2 & MASK8];
+ v ^= SBOX4_4404[(t2 >>> 8) & MASK8];
+ v ^= SBOX3_3033[(t2 >>> 16) & MASK8];
+ v ^= SBOX2_0222[(t2 >>> 24) & MASK8];
+
+ s[2] ^= u ^ v;
+ s[3] ^= u ^ v ^ rightRotate(u, 8);
+
+ t1 = s[2] ^ skey[2 + keyoff];
+ u = SBOX4_4404[t1 & MASK8];
+ u ^= SBOX3_3033[(t1 >>> 8) & MASK8];
+ u ^= SBOX2_0222[(t1 >>> 16) & MASK8];
+ u ^= SBOX1_1110[(t1 >>> 24) & MASK8];
+ t2 = s[3] ^ skey[3 + keyoff];
+ v = SBOX1_1110[t2 & MASK8];
+ v ^= SBOX4_4404[(t2 >>> 8) & MASK8];
+ v ^= SBOX3_3033[(t2 >>> 16) & MASK8];
+ v ^= SBOX2_0222[(t2 >>> 24) & MASK8];
+
+ s[0] ^= u ^ v;
+ s[1] ^= u ^ v ^ rightRotate(u, 8);
+ }
+
+ private void camelliaFLs(int[] s, int[] fkey, int keyoff)
+ {
+
+ s[1] ^= leftRotate(s[0] & fkey[0 + keyoff], 1);
+ s[0] ^= fkey[1 + keyoff] | s[1];
+
+ s[2] ^= fkey[3 + keyoff] | s[3];
+ s[3] ^= leftRotate(fkey[2 + keyoff] & s[2], 1);
+ }
+
+ private void setKey(boolean forEncryption, byte[] key)
+ {
+ int[] k = new int[8];
+ int[] ka = new int[4];
+ int[] kb = new int[4];
+ int[] t = new int[4];
+
+ switch (key.length)
+ {
+ case 16:
+ _keyIs128 = true;
+ k[0] = bytes2int(key, 0);
+ k[1] = bytes2int(key, 4);
+ k[2] = bytes2int(key, 8);
+ k[3] = bytes2int(key, 12);
+ k[4] = k[5] = k[6] = k[7] = 0;
+ break;
+ case 24:
+ k[0] = bytes2int(key, 0);
+ k[1] = bytes2int(key, 4);
+ k[2] = bytes2int(key, 8);
+ k[3] = bytes2int(key, 12);
+ k[4] = bytes2int(key, 16);
+ k[5] = bytes2int(key, 20);
+ k[6] = ~k[4];
+ k[7] = ~k[5];
+ _keyIs128 = false;
+ break;
+ case 32:
+ k[0] = bytes2int(key, 0);
+ k[1] = bytes2int(key, 4);
+ k[2] = bytes2int(key, 8);
+ k[3] = bytes2int(key, 12);
+ k[4] = bytes2int(key, 16);
+ k[5] = bytes2int(key, 20);
+ k[6] = bytes2int(key, 24);
+ k[7] = bytes2int(key, 28);
+ _keyIs128 = false;
+ break;
+ default:
+ throw new
+ IllegalArgumentException("key sizes are only 16/24/32 bytes.");
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ ka[i] = k[i] ^ k[i + 4];
+ }
+ /* compute KA */
+ camelliaF2(ka, SIGMA, 0);
+ for (int i = 0; i < 4; i++)
+ {
+ ka[i] ^= k[i];
+ }
+ camelliaF2(ka, SIGMA, 4);
+
+ if (_keyIs128)
+ {
+ if (forEncryption)
+ {
+ /* KL dependant keys */
+ kw[0] = k[0];
+ kw[1] = k[1];
+ kw[2] = k[2];
+ kw[3] = k[3];
+ roldq(15, k, 0, subkey, 4);
+ roldq(30, k, 0, subkey, 12);
+ roldq(15, k, 0, t, 0);
+ subkey[18] = t[2];
+ subkey[19] = t[3];
+ roldq(17, k, 0, ke, 4);
+ roldq(17, k, 0, subkey, 24);
+ roldq(17, k, 0, subkey, 32);
+ /* KA dependant keys */
+ subkey[0] = ka[0];
+ subkey[1] = ka[1];
+ subkey[2] = ka[2];
+ subkey[3] = ka[3];
+ roldq(15, ka, 0, subkey, 8);
+ roldq(15, ka, 0, ke, 0);
+ roldq(15, ka, 0, t, 0);
+ subkey[16] = t[0];
+ subkey[17] = t[1];
+ roldq(15, ka, 0, subkey, 20);
+ roldqo32(34, ka, 0, subkey, 28);
+ roldq(17, ka, 0, kw, 4);
+
+ }
+ else
+ { // decryption
+ /* KL dependant keys */
+ kw[4] = k[0];
+ kw[5] = k[1];
+ kw[6] = k[2];
+ kw[7] = k[3];
+ decroldq(15, k, 0, subkey, 28);
+ decroldq(30, k, 0, subkey, 20);
+ decroldq(15, k, 0, t, 0);
+ subkey[16] = t[0];
+ subkey[17] = t[1];
+ decroldq(17, k, 0, ke, 0);
+ decroldq(17, k, 0, subkey, 8);
+ decroldq(17, k, 0, subkey, 0);
+ /* KA dependant keys */
+ subkey[34] = ka[0];
+ subkey[35] = ka[1];
+ subkey[32] = ka[2];
+ subkey[33] = ka[3];
+ decroldq(15, ka, 0, subkey, 24);
+ decroldq(15, ka, 0, ke, 4);
+ decroldq(15, ka, 0, t, 0);
+ subkey[18] = t[2];
+ subkey[19] = t[3];
+ decroldq(15, ka, 0, subkey, 12);
+ decroldqo32(34, ka, 0, subkey, 4);
+ roldq(17, ka, 0, kw, 0);
+ }
+ }
+ else
+ { // 192bit or 256bit
+ /* compute KB */
+ for (int i = 0; i < 4; i++)
+ {
+ kb[i] = ka[i] ^ k[i + 4];
+ }
+ camelliaF2(kb, SIGMA, 8);
+
+ if (forEncryption)
+ {
+ /* KL dependant keys */
+ kw[0] = k[0];
+ kw[1] = k[1];
+ kw[2] = k[2];
+ kw[3] = k[3];
+ roldqo32(45, k, 0, subkey, 16);
+ roldq(15, k, 0, ke, 4);
+ roldq(17, k, 0, subkey, 32);
+ roldqo32(34, k, 0, subkey, 44);
+ /* KR dependant keys */
+ roldq(15, k, 4, subkey, 4);
+ roldq(15, k, 4, ke, 0);
+ roldq(30, k, 4, subkey, 24);
+ roldqo32(34, k, 4, subkey, 36);
+ /* KA dependant keys */
+ roldq(15, ka, 0, subkey, 8);
+ roldq(30, ka, 0, subkey, 20);
+ /* 32bit rotation */
+ ke[8] = ka[1];
+ ke[9] = ka[2];
+ ke[10] = ka[3];
+ ke[11] = ka[0];
+ roldqo32(49, ka, 0, subkey, 40);
+
+ /* KB dependant keys */
+ subkey[0] = kb[0];
+ subkey[1] = kb[1];
+ subkey[2] = kb[2];
+ subkey[3] = kb[3];
+ roldq(30, kb, 0, subkey, 12);
+ roldq(30, kb, 0, subkey, 28);
+ roldqo32(51, kb, 0, kw, 4);
+
+ }
+ else
+ { // decryption
+ /* KL dependant keys */
+ kw[4] = k[0];
+ kw[5] = k[1];
+ kw[6] = k[2];
+ kw[7] = k[3];
+ decroldqo32(45, k, 0, subkey, 28);
+ decroldq(15, k, 0, ke, 4);
+ decroldq(17, k, 0, subkey, 12);
+ decroldqo32(34, k, 0, subkey, 0);
+ /* KR dependant keys */
+ decroldq(15, k, 4, subkey, 40);
+ decroldq(15, k, 4, ke, 8);
+ decroldq(30, k, 4, subkey, 20);
+ decroldqo32(34, k, 4, subkey, 8);
+ /* KA dependant keys */
+ decroldq(15, ka, 0, subkey, 36);
+ decroldq(30, ka, 0, subkey, 24);
+ /* 32bit rotation */
+ ke[2] = ka[1];
+ ke[3] = ka[2];
+ ke[0] = ka[3];
+ ke[1] = ka[0];
+ decroldqo32(49, ka, 0, subkey, 4);
+
+ /* KB dependant keys */
+ subkey[46] = kb[0];
+ subkey[47] = kb[1];
+ subkey[44] = kb[2];
+ subkey[45] = kb[3];
+ decroldq(30, kb, 0, subkey, 32);
+ decroldq(30, kb, 0, subkey, 16);
+ roldqo32(51, kb, 0, kw, 0);
+ }
+ }
+ }
+
+ private int processBlock128(byte[] in, int inOff,
+ byte[] out, int outOff)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ state[i] = bytes2int(in, inOff + (i * 4));
+ state[i] ^= kw[i];
+ }
+
+ camelliaF2(state, subkey, 0);
+ camelliaF2(state, subkey, 4);
+ camelliaF2(state, subkey, 8);
+ camelliaFLs(state, ke, 0);
+ camelliaF2(state, subkey, 12);
+ camelliaF2(state, subkey, 16);
+ camelliaF2(state, subkey, 20);
+ camelliaFLs(state, ke, 4);
+ camelliaF2(state, subkey, 24);
+ camelliaF2(state, subkey, 28);
+ camelliaF2(state, subkey, 32);
+
+ state[2] ^= kw[4];
+ state[3] ^= kw[5];
+ state[0] ^= kw[6];
+ state[1] ^= kw[7];
+
+ int2bytes(state[2], out, outOff);
+ int2bytes(state[3], out, outOff + 4);
+ int2bytes(state[0], out, outOff + 8);
+ int2bytes(state[1], out, outOff + 12);
+
+ return BLOCK_SIZE;
+ }
+
+ private int processBlock192or256(byte[] in, int inOff,
+ byte[] out, int outOff)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ state[i] = bytes2int(in, inOff + (i * 4));
+ state[i] ^= kw[i];
+ }
+
+ camelliaF2(state, subkey, 0);
+ camelliaF2(state, subkey, 4);
+ camelliaF2(state, subkey, 8);
+ camelliaFLs(state, ke, 0);
+ camelliaF2(state, subkey, 12);
+ camelliaF2(state, subkey, 16);
+ camelliaF2(state, subkey, 20);
+ camelliaFLs(state, ke, 4);
+ camelliaF2(state, subkey, 24);
+ camelliaF2(state, subkey, 28);
+ camelliaF2(state, subkey, 32);
+ camelliaFLs(state, ke, 8);
+ camelliaF2(state, subkey, 36);
+ camelliaF2(state, subkey, 40);
+ camelliaF2(state, subkey, 44);
+
+ state[2] ^= kw[4];
+ state[3] ^= kw[5];
+ state[0] ^= kw[6];
+ state[1] ^= kw[7];
+
+ int2bytes(state[2], out, outOff);
+ int2bytes(state[3], out, outOff + 4);
+ int2bytes(state[0], out, outOff + 8);
+ int2bytes(state[1], out, outOff + 12);
+ return BLOCK_SIZE;
+ }
+
+ public CamelliaEngine()
+ {
+ }
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("only simple KeyParameter expected.");
+ }
+
+ setKey(forEncryption, ((KeyParameter)params).getKey());
+ initialised = true;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Camellia";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("Camellia engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (_keyIs128)
+ {
+ return processBlock128(in, inOff, out, outOff);
+ }
+ else
+ {
+ return processBlock192or256(in, inOff, out, outOff);
+ }
+ }
+
+ public void reset()
+ {
+ // nothing
+
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/CamelliaLightEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/CamelliaLightEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/CamelliaLightEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/CamelliaLightEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,591 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * Camellia - based on RFC 3713, smaller implementation, about half the size of CamelliaEngine.
+ */
+
+public class CamelliaLightEngine
+ implements BlockCipher
+{
+ private static final int BLOCK_SIZE = 16;
+ private static final int MASK8 = 0xff;
+ private boolean initialized;
+ private boolean _keyis128;
+
+ private int[] subkey = new int[24 * 4];
+ private int[] kw = new int[4 * 2]; // for whitening
+ private int[] ke = new int[6 * 2]; // for FL and FL^(-1)
+ private int[] state = new int[4]; // for encryption and decryption
+
+ private static final int SIGMA[] = {
+ 0xa09e667f, 0x3bcc908b,
+ 0xb67ae858, 0x4caa73b2,
+ 0xc6ef372f, 0xe94f82be,
+ 0x54ff53a5, 0xf1d36f1c,
+ 0x10e527fa, 0xde682d1d,
+ 0xb05688c2, 0xb3e6c1fd
+ };
+
+ /*
+ *
+ * S-box data
+ *
+ */
+ private static final byte SBOX1[] = {
+ (byte)112, (byte)130, (byte)44, (byte)236,
+ (byte)179, (byte)39, (byte)192, (byte)229,
+ (byte)228, (byte)133, (byte)87, (byte)53,
+ (byte)234, (byte)12, (byte)174, (byte)65,
+ (byte)35, (byte)239, (byte)107, (byte)147,
+ (byte)69, (byte)25, (byte)165, (byte)33,
+ (byte)237, (byte)14, (byte)79, (byte)78,
+ (byte)29, (byte)101, (byte)146, (byte)189,
+ (byte)134, (byte)184, (byte)175, (byte)143,
+ (byte)124, (byte)235, (byte)31, (byte)206,
+ (byte)62, (byte)48, (byte)220, (byte)95,
+ (byte)94, (byte)197, (byte)11, (byte)26,
+ (byte)166, (byte)225, (byte)57, (byte)202,
+ (byte)213, (byte)71, (byte)93, (byte)61,
+ (byte)217, (byte)1, (byte)90, (byte)214,
+ (byte)81, (byte)86, (byte)108, (byte)77,
+ (byte)139, (byte)13, (byte)154, (byte)102,
+ (byte)251, (byte)204, (byte)176, (byte)45,
+ (byte)116, (byte)18, (byte)43, (byte)32,
+ (byte)240, (byte)177, (byte)132, (byte)153,
+ (byte)223, (byte)76, (byte)203, (byte)194,
+ (byte)52, (byte)126, (byte)118, (byte)5,
+ (byte)109, (byte)183, (byte)169, (byte)49,
+ (byte)209, (byte)23, (byte)4, (byte)215,
+ (byte)20, (byte)88, (byte)58, (byte)97,
+ (byte)222, (byte)27, (byte)17, (byte)28,
+ (byte)50, (byte)15, (byte)156, (byte)22,
+ (byte)83, (byte)24, (byte)242, (byte)34,
+ (byte)254, (byte)68, (byte)207, (byte)178,
+ (byte)195, (byte)181, (byte)122, (byte)145,
+ (byte)36, (byte)8, (byte)232, (byte)168,
+ (byte)96, (byte)252, (byte)105, (byte)80,
+ (byte)170, (byte)208, (byte)160, (byte)125,
+ (byte)161, (byte)137, (byte)98, (byte)151,
+ (byte)84, (byte)91, (byte)30, (byte)149,
+ (byte)224, (byte)255, (byte)100, (byte)210,
+ (byte)16, (byte)196, (byte)0, (byte)72,
+ (byte)163, (byte)247, (byte)117, (byte)219,
+ (byte)138, (byte)3, (byte)230, (byte)218,
+ (byte)9, (byte)63, (byte)221, (byte)148,
+ (byte)135, (byte)92, (byte)131, (byte)2,
+ (byte)205, (byte)74, (byte)144, (byte)51,
+ (byte)115, (byte)103, (byte)246, (byte)243,
+ (byte)157, (byte)127, (byte)191, (byte)226,
+ (byte)82, (byte)155, (byte)216, (byte)38,
+ (byte)200, (byte)55, (byte)198, (byte)59,
+ (byte)129, (byte)150, (byte)111, (byte)75,
+ (byte)19, (byte)190, (byte)99, (byte)46,
+ (byte)233, (byte)121, (byte)167, (byte)140,
+ (byte)159, (byte)110, (byte)188, (byte)142,
+ (byte)41, (byte)245, (byte)249, (byte)182,
+ (byte)47, (byte)253, (byte)180, (byte)89,
+ (byte)120, (byte)152, (byte)6, (byte)106,
+ (byte)231, (byte)70, (byte)113, (byte)186,
+ (byte)212, (byte)37, (byte)171, (byte)66,
+ (byte)136, (byte)162, (byte)141, (byte)250,
+ (byte)114, (byte)7, (byte)185, (byte)85,
+ (byte)248, (byte)238, (byte)172, (byte)10,
+ (byte)54, (byte)73, (byte)42, (byte)104,
+ (byte)60, (byte)56, (byte)241, (byte)164,
+ (byte)64, (byte)40, (byte)211, (byte)123,
+ (byte)187, (byte)201, (byte)67, (byte)193,
+ (byte)21, (byte)227, (byte)173, (byte)244,
+ (byte)119, (byte)199, (byte)128, (byte)158
+ };
+
+ private static int rightRotate(int x, int s)
+ {
+ return (((x) >>> (s)) + ((x) << (32 - s)));
+ }
+
+ private static int leftRotate(int x, int s)
+ {
+ return ((x) << (s)) + ((x) >>> (32 - s));
+ }
+
+ private static void roldq(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[0 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >>> (32 - rot));
+ ko[1 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >>> (32 - rot));
+ ko[2 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >>> (32 - rot));
+ ko[3 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >>> (32 - rot));
+ ki[0 + ioff] = ko[0 + ooff];
+ ki[1 + ioff] = ko[1 + ooff];
+ ki[2 + ioff] = ko[2 + ooff];
+ ki[3 + ioff] = ko[3 + ooff];
+ }
+
+ private static void decroldq(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[2 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >>> (32 - rot));
+ ko[3 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >>> (32 - rot));
+ ko[0 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >>> (32 - rot));
+ ko[1 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >>> (32 - rot));
+ ki[0 + ioff] = ko[2 + ooff];
+ ki[1 + ioff] = ko[3 + ooff];
+ ki[2 + ioff] = ko[0 + ooff];
+ ki[3 + ioff] = ko[1 + ooff];
+ }
+
+ private static void roldqo32(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[0 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >>> (64 - rot));
+ ko[1 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >>> (64 - rot));
+ ko[2 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >>> (64 - rot));
+ ko[3 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >>> (64 - rot));
+ ki[0 + ioff] = ko[0 + ooff];
+ ki[1 + ioff] = ko[1 + ooff];
+ ki[2 + ioff] = ko[2 + ooff];
+ ki[3 + ioff] = ko[3 + ooff];
+ }
+
+ private static void decroldqo32(int rot, int[] ki, int ioff,
+ int[] ko, int ooff)
+ {
+ ko[2 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >>> (64 - rot));
+ ko[3 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >>> (64 - rot));
+ ko[0 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >>> (64 - rot));
+ ko[1 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >>> (64 - rot));
+ ki[0 + ioff] = ko[2 + ooff];
+ ki[1 + ioff] = ko[3 + ooff];
+ ki[2 + ioff] = ko[0 + ooff];
+ ki[3 + ioff] = ko[1 + ooff];
+ }
+
+ private int bytes2int(byte[] src, int offset)
+ {
+ int word = 0;
+
+ for (int i = 0; i < 4; i++)
+ {
+ word = (word << 8) + (src[i + offset] & MASK8);
+ }
+ return word;
+ }
+
+ private void int2bytes(int word, byte[] dst, int offset)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ dst[(3 - i) + offset] = (byte)word;
+ word >>>= 8;
+ }
+ }
+
+ private byte lRot8(byte v, int rot)
+ {
+ return (byte)((v << rot) | ((v & 0xff) >>> (8 - rot)));
+ }
+
+ private int sbox2(int x)
+ {
+ return (lRot8(SBOX1[x], 1) & MASK8);
+ }
+
+ private int sbox3(int x)
+ {
+ return (lRot8(SBOX1[x], 7) & MASK8);
+ }
+
+ private int sbox4(int x)
+ {
+ return (SBOX1[((int)lRot8((byte)x, 1) & MASK8)] & MASK8);
+ }
+
+ private void camelliaF2(int[] s, int[] skey, int keyoff)
+ {
+ int t1, t2, u, v;
+
+ t1 = s[0] ^ skey[0 + keyoff];
+ u = sbox4((t1 & MASK8));
+ u |= (sbox3(((t1 >>> 8) & MASK8)) << 8);
+ u |= (sbox2(((t1 >>> 16) & MASK8)) << 16);
+ u |= ((int)(SBOX1[((t1 >>> 24) & MASK8)] & MASK8) << 24);
+
+ t2 = s[1] ^ skey[1 + keyoff];
+ v = (int)SBOX1[(t2 & MASK8)] & MASK8;
+ v |= (sbox4(((t2 >>> 8) & MASK8)) << 8);
+ v |= (sbox3(((t2 >>> 16) & MASK8)) << 16);
+ v |= (sbox2(((t2 >>> 24) & MASK8)) << 24);
+
+ v = leftRotate(v, 8);
+ u ^= v;
+ v = leftRotate(v, 8) ^ u;
+ u = rightRotate(u, 8) ^ v;
+ s[2] ^= leftRotate(v, 16) ^ u;
+ s[3] ^= leftRotate(u, 8);
+
+ t1 = s[2] ^ skey[2 + keyoff];
+ u = sbox4((t1 & MASK8));
+ u |= sbox3(((t1 >>> 8) & MASK8)) << 8;
+ u |= sbox2(((t1 >>> 16) & MASK8)) << 16;
+ u |= ((int)SBOX1[((t1 >>> 24) & MASK8)] & MASK8) << 24;
+
+ t2 = s[3] ^ skey[3 + keyoff];
+ v = ((int)SBOX1[(t2 & MASK8)] & MASK8);
+ v |= sbox4(((t2 >>> 8) & MASK8)) << 8;
+ v |= sbox3(((t2 >>> 16) & MASK8)) << 16;
+ v |= sbox2(((t2 >>> 24) & MASK8)) << 24;
+
+ v = leftRotate(v, 8);
+ u ^= v;
+ v = leftRotate(v, 8) ^ u;
+ u = rightRotate(u, 8) ^ v;
+ s[0] ^= leftRotate(v, 16) ^ u;
+ s[1] ^= leftRotate(u, 8);
+ }
+
+ private void camelliaFLs(int[] s, int[] fkey, int keyoff)
+ {
+
+ s[1] ^= leftRotate(s[0] & fkey[0 + keyoff], 1);
+ s[0] ^= fkey[1 + keyoff] | s[1];
+
+ s[2] ^= fkey[3 + keyoff] | s[3];
+ s[3] ^= leftRotate(fkey[2 + keyoff] & s[2], 1);
+ }
+
+ private void setKey(boolean forEncryption, byte[] key)
+ {
+ int[] k = new int[8];
+ int[] ka = new int[4];
+ int[] kb = new int[4];
+ int[] t = new int[4];
+
+ switch (key.length)
+ {
+ case 16:
+ _keyis128 = true;
+ k[0] = bytes2int(key, 0);
+ k[1] = bytes2int(key, 4);
+ k[2] = bytes2int(key, 8);
+ k[3] = bytes2int(key, 12);
+ k[4] = k[5] = k[6] = k[7] = 0;
+ break;
+ case 24:
+ k[0] = bytes2int(key, 0);
+ k[1] = bytes2int(key, 4);
+ k[2] = bytes2int(key, 8);
+ k[3] = bytes2int(key, 12);
+ k[4] = bytes2int(key, 16);
+ k[5] = bytes2int(key, 20);
+ k[6] = ~k[4];
+ k[7] = ~k[5];
+ _keyis128 = false;
+ break;
+ case 32:
+ k[0] = bytes2int(key, 0);
+ k[1] = bytes2int(key, 4);
+ k[2] = bytes2int(key, 8);
+ k[3] = bytes2int(key, 12);
+ k[4] = bytes2int(key, 16);
+ k[5] = bytes2int(key, 20);
+ k[6] = bytes2int(key, 24);
+ k[7] = bytes2int(key, 28);
+ _keyis128 = false;
+ break;
+ default:
+ throw new
+ IllegalArgumentException("key sizes are only 16/24/32 bytes.");
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ ka[i] = k[i] ^ k[i + 4];
+ }
+ /* compute KA */
+ camelliaF2(ka, SIGMA, 0);
+ for (int i = 0; i < 4; i++)
+ {
+ ka[i] ^= k[i];
+ }
+ camelliaF2(ka, SIGMA, 4);
+
+ if (_keyis128)
+ {
+ if (forEncryption)
+ {
+ /* KL dependant keys */
+ kw[0] = k[0];
+ kw[1] = k[1];
+ kw[2] = k[2];
+ kw[3] = k[3];
+ roldq(15, k, 0, subkey, 4);
+ roldq(30, k, 0, subkey, 12);
+ roldq(15, k, 0, t, 0);
+ subkey[18] = t[2];
+ subkey[19] = t[3];
+ roldq(17, k, 0, ke, 4);
+ roldq(17, k, 0, subkey, 24);
+ roldq(17, k, 0, subkey, 32);
+ /* KA dependant keys */
+ subkey[0] = ka[0];
+ subkey[1] = ka[1];
+ subkey[2] = ka[2];
+ subkey[3] = ka[3];
+ roldq(15, ka, 0, subkey, 8);
+ roldq(15, ka, 0, ke, 0);
+ roldq(15, ka, 0, t, 0);
+ subkey[16] = t[0];
+ subkey[17] = t[1];
+ roldq(15, ka, 0, subkey, 20);
+ roldqo32(34, ka, 0, subkey, 28);
+ roldq(17, ka, 0, kw, 4);
+
+ }
+ else
+ { // decryption
+ /* KL dependant keys */
+ kw[4] = k[0];
+ kw[5] = k[1];
+ kw[6] = k[2];
+ kw[7] = k[3];
+ decroldq(15, k, 0, subkey, 28);
+ decroldq(30, k, 0, subkey, 20);
+ decroldq(15, k, 0, t, 0);
+ subkey[16] = t[0];
+ subkey[17] = t[1];
+ decroldq(17, k, 0, ke, 0);
+ decroldq(17, k, 0, subkey, 8);
+ decroldq(17, k, 0, subkey, 0);
+ /* KA dependant keys */
+ subkey[34] = ka[0];
+ subkey[35] = ka[1];
+ subkey[32] = ka[2];
+ subkey[33] = ka[3];
+ decroldq(15, ka, 0, subkey, 24);
+ decroldq(15, ka, 0, ke, 4);
+ decroldq(15, ka, 0, t, 0);
+ subkey[18] = t[2];
+ subkey[19] = t[3];
+ decroldq(15, ka, 0, subkey, 12);
+ decroldqo32(34, ka, 0, subkey, 4);
+ roldq(17, ka, 0, kw, 0);
+ }
+ }
+ else
+ { // 192bit or 256bit
+ /* compute KB */
+ for (int i = 0; i < 4; i++)
+ {
+ kb[i] = ka[i] ^ k[i + 4];
+ }
+ camelliaF2(kb, SIGMA, 8);
+
+ if (forEncryption)
+ {
+ /* KL dependant keys */
+ kw[0] = k[0];
+ kw[1] = k[1];
+ kw[2] = k[2];
+ kw[3] = k[3];
+ roldqo32(45, k, 0, subkey, 16);
+ roldq(15, k, 0, ke, 4);
+ roldq(17, k, 0, subkey, 32);
+ roldqo32(34, k, 0, subkey, 44);
+ /* KR dependant keys */
+ roldq(15, k, 4, subkey, 4);
+ roldq(15, k, 4, ke, 0);
+ roldq(30, k, 4, subkey, 24);
+ roldqo32(34, k, 4, subkey, 36);
+ /* KA dependant keys */
+ roldq(15, ka, 0, subkey, 8);
+ roldq(30, ka, 0, subkey, 20);
+ /* 32bit rotation */
+ ke[8] = ka[1];
+ ke[9] = ka[2];
+ ke[10] = ka[3];
+ ke[11] = ka[0];
+ roldqo32(49, ka, 0, subkey, 40);
+
+ /* KB dependant keys */
+ subkey[0] = kb[0];
+ subkey[1] = kb[1];
+ subkey[2] = kb[2];
+ subkey[3] = kb[3];
+ roldq(30, kb, 0, subkey, 12);
+ roldq(30, kb, 0, subkey, 28);
+ roldqo32(51, kb, 0, kw, 4);
+
+ }
+ else
+ { // decryption
+ /* KL dependant keys */
+ kw[4] = k[0];
+ kw[5] = k[1];
+ kw[6] = k[2];
+ kw[7] = k[3];
+ decroldqo32(45, k, 0, subkey, 28);
+ decroldq(15, k, 0, ke, 4);
+ decroldq(17, k, 0, subkey, 12);
+ decroldqo32(34, k, 0, subkey, 0);
+ /* KR dependant keys */
+ decroldq(15, k, 4, subkey, 40);
+ decroldq(15, k, 4, ke, 8);
+ decroldq(30, k, 4, subkey, 20);
+ decroldqo32(34, k, 4, subkey, 8);
+ /* KA dependant keys */
+ decroldq(15, ka, 0, subkey, 36);
+ decroldq(30, ka, 0, subkey, 24);
+ /* 32bit rotation */
+ ke[2] = ka[1];
+ ke[3] = ka[2];
+ ke[0] = ka[3];
+ ke[1] = ka[0];
+ decroldqo32(49, ka, 0, subkey, 4);
+
+ /* KB dependant keys */
+ subkey[46] = kb[0];
+ subkey[47] = kb[1];
+ subkey[44] = kb[2];
+ subkey[45] = kb[3];
+ decroldq(30, kb, 0, subkey, 32);
+ decroldq(30, kb, 0, subkey, 16);
+ roldqo32(51, kb, 0, kw, 0);
+ }
+ }
+ }
+
+ private int processBlock128(byte[] in, int inOff,
+ byte[] out, int outOff)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ state[i] = bytes2int(in, inOff + (i * 4));
+ state[i] ^= kw[i];
+ }
+
+ camelliaF2(state, subkey, 0);
+ camelliaF2(state, subkey, 4);
+ camelliaF2(state, subkey, 8);
+ camelliaFLs(state, ke, 0);
+ camelliaF2(state, subkey, 12);
+ camelliaF2(state, subkey, 16);
+ camelliaF2(state, subkey, 20);
+ camelliaFLs(state, ke, 4);
+ camelliaF2(state, subkey, 24);
+ camelliaF2(state, subkey, 28);
+ camelliaF2(state, subkey, 32);
+
+ state[2] ^= kw[4];
+ state[3] ^= kw[5];
+ state[0] ^= kw[6];
+ state[1] ^= kw[7];
+
+ int2bytes(state[2], out, outOff);
+ int2bytes(state[3], out, outOff + 4);
+ int2bytes(state[0], out, outOff + 8);
+ int2bytes(state[1], out, outOff + 12);
+
+ return BLOCK_SIZE;
+ }
+
+ private int processBlock192or256(byte[] in, int inOff,
+ byte[] out, int outOff)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ state[i] = bytes2int(in, inOff + (i * 4));
+ state[i] ^= kw[i];
+ }
+
+ camelliaF2(state, subkey, 0);
+ camelliaF2(state, subkey, 4);
+ camelliaF2(state, subkey, 8);
+ camelliaFLs(state, ke, 0);
+ camelliaF2(state, subkey, 12);
+ camelliaF2(state, subkey, 16);
+ camelliaF2(state, subkey, 20);
+ camelliaFLs(state, ke, 4);
+ camelliaF2(state, subkey, 24);
+ camelliaF2(state, subkey, 28);
+ camelliaF2(state, subkey, 32);
+ camelliaFLs(state, ke, 8);
+ camelliaF2(state, subkey, 36);
+ camelliaF2(state, subkey, 40);
+ camelliaF2(state, subkey, 44);
+
+ state[2] ^= kw[4];
+ state[3] ^= kw[5];
+ state[0] ^= kw[6];
+ state[1] ^= kw[7];
+
+ int2bytes(state[2], out, outOff);
+ int2bytes(state[3], out, outOff + 4);
+ int2bytes(state[0], out, outOff + 8);
+ int2bytes(state[1], out, outOff + 12);
+ return BLOCK_SIZE;
+ }
+
+ public CamelliaLightEngine()
+ {
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Camellia";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public void init(boolean forEncryption, CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("only simple KeyParameter expected.");
+ }
+
+ setKey(forEncryption, ((KeyParameter)params).getKey());
+ initialized = true;
+ }
+
+ public int processBlock(byte[] in, int inOff,
+ byte[] out, int outOff)
+ throws IllegalStateException
+ {
+
+ if (!initialized)
+ {
+ throw new IllegalStateException("Camellia is not initialized");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (_keyis128)
+ {
+ return processBlock128(in, inOff, out, outOff);
+ }
+ else
+ {
+ return processBlock192or256(in, inOff, out, outOff);
+ }
+ }
+
+ public void reset()
+ {
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/CamelliaWrapEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/CamelliaWrapEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/CamelliaWrapEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/CamelliaWrapEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,15 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+/**
+ * An implementation of the Camellia key wrapper based on RFC 3657/RFC 3394.
+ *
+ * For further details see: http://www.ietf.org/rfc/rfc3657.txt .
+ */
+public class CamelliaWrapEngine
+ extends RFC3394WrapEngine
+{
+ public CamelliaWrapEngine()
+ {
+ super(new CamelliaEngine());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/DESEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/DESEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/DESEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/DESEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,494 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * a class that provides a basic DES engine.
+ */
+public class DESEngine
+ implements BlockCipher
+{
+ protected static final int BLOCK_SIZE = 8;
+
+ private int[] workingKey = null;
+
+ /**
+ * standard constructor.
+ */
+ public DESEngine()
+ {
+ }
+
+ /**
+ * initialise a DES cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ if (((KeyParameter)params).getKey().length > 8)
+ {
+ throw new IllegalArgumentException("DES key too long - should be 8 bytes");
+ }
+
+ workingKey = generateWorkingKey(encrypting,
+ ((KeyParameter)params).getKey());
+
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to DES init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "DES";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("DES engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ desFunc(workingKey, in, inOff, out, outOff);
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * what follows is mainly taken from "Applied Cryptography", by
+ * Bruce Schneier, however it also bears great resemblance to Richard
+ * Outerbridge's D3DES...
+ */
+
+// private static final short[] Df_Key =
+// {
+// 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
+// 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
+// 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
+// };
+
+ private static final short[] bytebit =
+ {
+ 0200, 0100, 040, 020, 010, 04, 02, 01
+ };
+
+ private static final int[] bigbyte =
+ {
+ 0x800000, 0x400000, 0x200000, 0x100000,
+ 0x80000, 0x40000, 0x20000, 0x10000,
+ 0x8000, 0x4000, 0x2000, 0x1000,
+ 0x800, 0x400, 0x200, 0x100,
+ 0x80, 0x40, 0x20, 0x10,
+ 0x8, 0x4, 0x2, 0x1
+ };
+
+ /*
+ * Use the key schedule specified in the Standard (ANSI X3.92-1981).
+ */
+
+ private static final byte[] pc1 =
+ {
+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
+ };
+
+ private static final byte[] totrot =
+ {
+ 1, 2, 4, 6, 8, 10, 12, 14,
+ 15, 17, 19, 21, 23, 25, 27, 28
+ };
+
+ private static final byte[] pc2 =
+ {
+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
+ };
+
+ private static final int[] SP1 = {
+ 0x01010400, 0x00000000, 0x00010000, 0x01010404,
+ 0x01010004, 0x00010404, 0x00000004, 0x00010000,
+ 0x00000400, 0x01010400, 0x01010404, 0x00000400,
+ 0x01000404, 0x01010004, 0x01000000, 0x00000004,
+ 0x00000404, 0x01000400, 0x01000400, 0x00010400,
+ 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+ 0x00010004, 0x01000004, 0x01000004, 0x00010004,
+ 0x00000000, 0x00000404, 0x00010404, 0x01000000,
+ 0x00010000, 0x01010404, 0x00000004, 0x01010000,
+ 0x01010400, 0x01000000, 0x01000000, 0x00000400,
+ 0x01010004, 0x00010000, 0x00010400, 0x01000004,
+ 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+ 0x01010404, 0x00010004, 0x01010000, 0x01000404,
+ 0x01000004, 0x00000404, 0x00010404, 0x01010400,
+ 0x00000404, 0x01000400, 0x01000400, 0x00000000,
+ 0x00010004, 0x00010400, 0x00000000, 0x01010004
+ };
+
+ private static final int[] SP2 = {
+ 0x80108020, 0x80008000, 0x00008000, 0x00108020,
+ 0x00100000, 0x00000020, 0x80100020, 0x80008020,
+ 0x80000020, 0x80108020, 0x80108000, 0x80000000,
+ 0x80008000, 0x00100000, 0x00000020, 0x80100020,
+ 0x00108000, 0x00100020, 0x80008020, 0x00000000,
+ 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+ 0x00100020, 0x80000020, 0x00000000, 0x00108000,
+ 0x00008020, 0x80108000, 0x80100000, 0x00008020,
+ 0x00000000, 0x00108020, 0x80100020, 0x00100000,
+ 0x80008020, 0x80100000, 0x80108000, 0x00008000,
+ 0x80100000, 0x80008000, 0x00000020, 0x80108020,
+ 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+ 0x00008020, 0x80108000, 0x00100000, 0x80000020,
+ 0x00100020, 0x80008020, 0x80000020, 0x00100020,
+ 0x00108000, 0x00000000, 0x80008000, 0x00008020,
+ 0x80000000, 0x80100020, 0x80108020, 0x00108000
+ };
+
+ private static final int[] SP3 = {
+ 0x00000208, 0x08020200, 0x00000000, 0x08020008,
+ 0x08000200, 0x00000000, 0x00020208, 0x08000200,
+ 0x00020008, 0x08000008, 0x08000008, 0x00020000,
+ 0x08020208, 0x00020008, 0x08020000, 0x00000208,
+ 0x08000000, 0x00000008, 0x08020200, 0x00000200,
+ 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+ 0x08000208, 0x00020200, 0x00020000, 0x08000208,
+ 0x00000008, 0x08020208, 0x00000200, 0x08000000,
+ 0x08020200, 0x08000000, 0x00020008, 0x00000208,
+ 0x00020000, 0x08020200, 0x08000200, 0x00000000,
+ 0x00000200, 0x00020008, 0x08020208, 0x08000200,
+ 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+ 0x08000208, 0x00020000, 0x08000000, 0x08020208,
+ 0x00000008, 0x00020208, 0x00020200, 0x08000008,
+ 0x08020000, 0x08000208, 0x00000208, 0x08020000,
+ 0x00020208, 0x00000008, 0x08020008, 0x00020200
+ };
+
+ private static final int[] SP4 = {
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802080, 0x00800081, 0x00800001, 0x00002001,
+ 0x00000000, 0x00802000, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00800080, 0x00800001,
+ 0x00000001, 0x00002000, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+ 0x00800081, 0x00000001, 0x00002080, 0x00800080,
+ 0x00002000, 0x00802080, 0x00802081, 0x00000081,
+ 0x00800080, 0x00800001, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00000000, 0x00802000,
+ 0x00002080, 0x00800080, 0x00800081, 0x00000001,
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802081, 0x00000081, 0x00000001, 0x00002000,
+ 0x00800001, 0x00002001, 0x00802080, 0x00800081,
+ 0x00002001, 0x00002080, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002000, 0x00802080
+ };
+
+ private static final int[] SP5 = {
+ 0x00000100, 0x02080100, 0x02080000, 0x42000100,
+ 0x00080000, 0x00000100, 0x40000000, 0x02080000,
+ 0x40080100, 0x00080000, 0x02000100, 0x40080100,
+ 0x42000100, 0x42080000, 0x00080100, 0x40000000,
+ 0x02000000, 0x40080000, 0x40080000, 0x00000000,
+ 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+ 0x42080000, 0x40000100, 0x00000000, 0x42000000,
+ 0x02080100, 0x02000000, 0x42000000, 0x00080100,
+ 0x00080000, 0x42000100, 0x00000100, 0x02000000,
+ 0x40000000, 0x02080000, 0x42000100, 0x40080100,
+ 0x02000100, 0x40000000, 0x42080000, 0x02080100,
+ 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+ 0x42080100, 0x00080100, 0x42000000, 0x42080100,
+ 0x02080000, 0x00000000, 0x40080000, 0x42000000,
+ 0x00080100, 0x02000100, 0x40000100, 0x00080000,
+ 0x00000000, 0x40080000, 0x02080100, 0x40000100
+ };
+
+ private static final int[] SP6 = {
+ 0x20000010, 0x20400000, 0x00004000, 0x20404010,
+ 0x20400000, 0x00000010, 0x20404010, 0x00400000,
+ 0x20004000, 0x00404010, 0x00400000, 0x20000010,
+ 0x00400010, 0x20004000, 0x20000000, 0x00004010,
+ 0x00000000, 0x00400010, 0x20004010, 0x00004000,
+ 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+ 0x20400010, 0x00000000, 0x00404010, 0x20404000,
+ 0x00004010, 0x00404000, 0x20404000, 0x20000000,
+ 0x20004000, 0x00000010, 0x20400010, 0x00404000,
+ 0x20404010, 0x00400000, 0x00004010, 0x20000010,
+ 0x00400000, 0x20004000, 0x20000000, 0x00004010,
+ 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+ 0x00404010, 0x20404000, 0x00000000, 0x20400010,
+ 0x00000010, 0x00004000, 0x20400000, 0x00404010,
+ 0x00004000, 0x00400010, 0x20004010, 0x00000000,
+ 0x20404000, 0x20000000, 0x00400010, 0x20004010
+ };
+
+ private static final int[] SP7 = {
+ 0x00200000, 0x04200002, 0x04000802, 0x00000000,
+ 0x00000800, 0x04000802, 0x00200802, 0x04200800,
+ 0x04200802, 0x00200000, 0x00000000, 0x04000002,
+ 0x00000002, 0x04000000, 0x04200002, 0x00000802,
+ 0x04000800, 0x00200802, 0x00200002, 0x04000800,
+ 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+ 0x04200000, 0x00000800, 0x00000802, 0x04200802,
+ 0x00200800, 0x00000002, 0x04000000, 0x00200800,
+ 0x04000000, 0x00200800, 0x00200000, 0x04000802,
+ 0x04000802, 0x04200002, 0x04200002, 0x00000002,
+ 0x00200002, 0x04000000, 0x04000800, 0x00200000,
+ 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+ 0x00000802, 0x04000002, 0x04200802, 0x04200000,
+ 0x00200800, 0x00000000, 0x00000002, 0x04200802,
+ 0x00000000, 0x00200802, 0x04200000, 0x00000800,
+ 0x04000002, 0x04000800, 0x00000800, 0x00200002
+ };
+
+ private static final int[] SP8 = {
+ 0x10001040, 0x00001000, 0x00040000, 0x10041040,
+ 0x10000000, 0x10001040, 0x00000040, 0x10000000,
+ 0x00040040, 0x10040000, 0x10041040, 0x00041000,
+ 0x10041000, 0x00041040, 0x00001000, 0x00000040,
+ 0x10040000, 0x10000040, 0x10001000, 0x00001040,
+ 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+ 0x00001040, 0x00000000, 0x00000000, 0x10040040,
+ 0x10000040, 0x10001000, 0x00041040, 0x00040000,
+ 0x00041040, 0x00040000, 0x10041000, 0x00001000,
+ 0x00000040, 0x10040040, 0x00001000, 0x00041040,
+ 0x10001000, 0x00000040, 0x10000040, 0x10040000,
+ 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+ 0x00000000, 0x10041040, 0x00040040, 0x10000040,
+ 0x10040000, 0x10001000, 0x10001040, 0x00000000,
+ 0x10041040, 0x00041000, 0x00041000, 0x00001040,
+ 0x00001040, 0x00040040, 0x10000000, 0x10041000
+ };
+
+ /**
+ * generate an integer based working key based on our secret key
+ * and what we processing we are planning to do.
+ *
+ * Acknowledgements for this routine go to James Gillogly & Phil Karn.
+ * (whoever, and wherever they are!).
+ */
+ protected int[] generateWorkingKey(
+ boolean encrypting,
+ byte[] key)
+ {
+ int[] newKey = new int[32];
+ boolean[] pc1m = new boolean[56],
+ pcr = new boolean[56];
+
+ for (int j = 0; j < 56; j++)
+ {
+ int l = pc1[j];
+
+ pc1m[j] = ((key[l >>> 3] & bytebit[l & 07]) != 0);
+ }
+
+ for (int i = 0; i < 16; i++)
+ {
+ int l, m, n;
+
+ if (encrypting)
+ {
+ m = i << 1;
+ }
+ else
+ {
+ m = (15 - i) << 1;
+ }
+
+ n = m + 1;
+ newKey[m] = newKey[n] = 0;
+
+ for (int j = 0; j < 28; j++)
+ {
+ l = j + totrot[i];
+ if (l < 28)
+ {
+ pcr[j] = pc1m[l];
+ }
+ else
+ {
+ pcr[j] = pc1m[l - 28];
+ }
+ }
+
+ for (int j = 28; j < 56; j++)
+ {
+ l = j + totrot[i];
+ if (l < 56)
+ {
+ pcr[j] = pc1m[l];
+ }
+ else
+ {
+ pcr[j] = pc1m[l - 28];
+ }
+ }
+
+ for (int j = 0; j < 24; j++)
+ {
+ if (pcr[pc2[j]])
+ {
+ newKey[m] |= bigbyte[j];
+ }
+
+ if (pcr[pc2[j + 24]])
+ {
+ newKey[n] |= bigbyte[j];
+ }
+ }
+ }
+
+ //
+ // store the processed key
+ //
+ for (int i = 0; i != 32; i += 2)
+ {
+ int i1, i2;
+
+ i1 = newKey[i];
+ i2 = newKey[i + 1];
+
+ newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10)
+ | ((i2 & 0x00fc0000) >>> 10) | ((i2 & 0x00000fc0) >>> 6);
+
+ newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16)
+ | ((i2 & 0x0003f000) >>> 4) | (i2 & 0x0000003f);
+ }
+
+ return newKey;
+ }
+
+ /**
+ * the DES engine.
+ */
+ protected void desFunc(
+ int[] wKey,
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int work, right, left;
+
+ left = (in[inOff + 0] & 0xff) << 24;
+ left |= (in[inOff + 1] & 0xff) << 16;
+ left |= (in[inOff + 2] & 0xff) << 8;
+ left |= (in[inOff + 3] & 0xff);
+
+ right = (in[inOff + 4] & 0xff) << 24;
+ right |= (in[inOff + 5] & 0xff) << 16;
+ right |= (in[inOff + 6] & 0xff) << 8;
+ right |= (in[inOff + 7] & 0xff);
+
+ work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
+ right ^= work;
+ left ^= (work << 4);
+ work = ((left >>> 16) ^ right) & 0x0000ffff;
+ right ^= work;
+ left ^= (work << 16);
+ work = ((right >>> 2) ^ left) & 0x33333333;
+ left ^= work;
+ right ^= (work << 2);
+ work = ((right >>> 8) ^ left) & 0x00ff00ff;
+ left ^= work;
+ right ^= (work << 8);
+ right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
+ work = (left ^ right) & 0xaaaaaaaa;
+ left ^= work;
+ right ^= work;
+ left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
+
+ for (int round = 0; round < 8; round++)
+ {
+ int fval;
+
+ work = (right << 28) | (right >>> 4);
+ work ^= wKey[round * 4 + 0];
+ fval = SP7[ work & 0x3f];
+ fval |= SP5[(work >>> 8) & 0x3f];
+ fval |= SP3[(work >>> 16) & 0x3f];
+ fval |= SP1[(work >>> 24) & 0x3f];
+ work = right ^ wKey[round * 4 + 1];
+ fval |= SP8[ work & 0x3f];
+ fval |= SP6[(work >>> 8) & 0x3f];
+ fval |= SP4[(work >>> 16) & 0x3f];
+ fval |= SP2[(work >>> 24) & 0x3f];
+ left ^= fval;
+ work = (left << 28) | (left >>> 4);
+ work ^= wKey[round * 4 + 2];
+ fval = SP7[ work & 0x3f];
+ fval |= SP5[(work >>> 8) & 0x3f];
+ fval |= SP3[(work >>> 16) & 0x3f];
+ fval |= SP1[(work >>> 24) & 0x3f];
+ work = left ^ wKey[round * 4 + 3];
+ fval |= SP8[ work & 0x3f];
+ fval |= SP6[(work >>> 8) & 0x3f];
+ fval |= SP4[(work >>> 16) & 0x3f];
+ fval |= SP2[(work >>> 24) & 0x3f];
+ right ^= fval;
+ }
+
+ right = (right << 31) | (right >>> 1);
+ work = (left ^ right) & 0xaaaaaaaa;
+ left ^= work;
+ right ^= work;
+ left = (left << 31) | (left >>> 1);
+ work = ((left >>> 8) ^ right) & 0x00ff00ff;
+ right ^= work;
+ left ^= (work << 8);
+ work = ((left >>> 2) ^ right) & 0x33333333;
+ right ^= work;
+ left ^= (work << 2);
+ work = ((right >>> 16) ^ left) & 0x0000ffff;
+ left ^= work;
+ right ^= (work << 16);
+ work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
+ left ^= work;
+ right ^= (work << 4);
+
+ out[outOff + 0] = (byte)((right >>> 24) & 0xff);
+ out[outOff + 1] = (byte)((right >>> 16) & 0xff);
+ out[outOff + 2] = (byte)((right >>> 8) & 0xff);
+ out[outOff + 3] = (byte)(right & 0xff);
+ out[outOff + 4] = (byte)((left >>> 24) & 0xff);
+ out[outOff + 5] = (byte)((left >>> 16) & 0xff);
+ out[outOff + 6] = (byte)((left >>> 8) & 0xff);
+ out[outOff + 7] = (byte)(left & 0xff);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/DESedeEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/DESedeEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/DESedeEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/DESedeEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,126 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * a class that provides a basic DESede (or Triple DES) engine.
+ */
+public class DESedeEngine
+ extends DESEngine
+{
+ protected static final int BLOCK_SIZE = 8;
+
+ private int[] workingKey1 = null;
+ private int[] workingKey2 = null;
+ private int[] workingKey3 = null;
+
+ private boolean forEncryption;
+
+ /**
+ * standard constructor.
+ */
+ public DESedeEngine()
+ {
+ }
+
+ /**
+ * initialise a DESede cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to DESede init - " + params.getClass().getName());
+ }
+
+ byte[] keyMaster = ((KeyParameter)params).getKey();
+
+ if (keyMaster.length != 24 && keyMaster.length != 16)
+ {
+ throw new IllegalArgumentException("key size must be 16 or 24 bytes.");
+ }
+
+ this.forEncryption = encrypting;
+
+ byte[] key1 = new byte[8];
+ System.arraycopy(keyMaster, 0, key1, 0, key1.length);
+ workingKey1 = generateWorkingKey(encrypting, key1);
+
+ byte[] key2 = new byte[8];
+ System.arraycopy(keyMaster, 8, key2, 0, key2.length);
+ workingKey2 = generateWorkingKey(!encrypting, key2);
+
+ if (keyMaster.length == 24)
+ {
+ byte[] key3 = new byte[8];
+ System.arraycopy(keyMaster, 16, key3, 0, key3.length);
+ workingKey3 = generateWorkingKey(encrypting, key3);
+ }
+ else // 16 byte key
+ {
+ workingKey3 = workingKey1;
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return "DESede";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey1 == null)
+ {
+ throw new IllegalStateException("DESede engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ byte[] temp = new byte[BLOCK_SIZE];
+
+ if (forEncryption)
+ {
+ desFunc(workingKey1, in, inOff, temp, 0);
+ desFunc(workingKey2, temp, 0, temp, 0);
+ desFunc(workingKey3, temp, 0, out, outOff);
+ }
+ else
+ {
+ desFunc(workingKey3, in, inOff, temp, 0);
+ desFunc(workingKey2, temp, 0, temp, 0);
+ desFunc(workingKey1, temp, 0, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/DESedeWrapEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/DESedeWrapEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/DESedeWrapEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/DESedeWrapEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,348 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.Wrapper;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+import pdftk.org.bouncycastle.crypto.modes.CBCBlockCipher;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * Wrap keys according to
+ *
+ * draft-ietf-smime-key-wrap-01.txt .
+ *
+ * Note:
+ *
+ * this is based on a draft, and as such is subject to change - don't use this class for anything requiring long term storage.
+ * if you are using this to wrap triple-des keys you need to set the
+ * parity bits on the key and, if it's a two-key triple-des key, pad it
+ * yourself.
+ *
+ */
+public class DESedeWrapEngine
+ implements Wrapper
+{
+ /** Field engine */
+ private CBCBlockCipher engine;
+
+ /** Field param */
+ private KeyParameter param;
+
+ /** Field paramPlusIV */
+ private ParametersWithIV paramPlusIV;
+
+ /** Field iv */
+ private byte[] iv;
+
+ /** Field forWrapping */
+ private boolean forWrapping;
+
+ /** Field IV2 */
+ private static final byte[] IV2 = { (byte) 0x4a, (byte) 0xdd, (byte) 0xa2,
+ (byte) 0x2c, (byte) 0x79, (byte) 0xe8,
+ (byte) 0x21, (byte) 0x05 };
+
+ //
+ // checksum digest
+ //
+ Digest sha1 = new SHA1Digest();
+ byte[] digest = new byte[20];
+
+ /**
+ * Method init
+ *
+ * @param forWrapping
+ * @param param
+ */
+ public void init(boolean forWrapping, CipherParameters param)
+ {
+
+ this.forWrapping = forWrapping;
+ this.engine = new CBCBlockCipher(new DESedeEngine());
+
+ SecureRandom sr;
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom pr = (ParametersWithRandom) param;
+ param = pr.getParameters();
+ sr = pr.getRandom();
+ }
+ else
+ {
+ sr = new SecureRandom();
+ }
+
+ if (param instanceof KeyParameter)
+ {
+ this.param = (KeyParameter)param;
+
+ if (this.forWrapping)
+ {
+
+ // Hm, we have no IV but we want to wrap ?!?
+ // well, then we have to create our own IV.
+ this.iv = new byte[8];
+ sr.nextBytes(iv);
+
+ this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
+ }
+ }
+ else if (param instanceof ParametersWithIV)
+ {
+ this.paramPlusIV = (ParametersWithIV)param;
+ this.iv = this.paramPlusIV.getIV();
+ this.param = (KeyParameter)this.paramPlusIV.getParameters();
+
+ if (this.forWrapping)
+ {
+ if ((this.iv == null) || (this.iv.length != 8))
+ {
+ throw new IllegalArgumentException("IV is not 8 octets");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "You should not supply an IV for unwrapping");
+ }
+ }
+ }
+
+ /**
+ * Method getAlgorithmName
+ *
+ * @return the algorithm name "DESede".
+ */
+ public String getAlgorithmName()
+ {
+ return "DESede";
+ }
+
+ /**
+ * Method wrap
+ *
+ * @param in
+ * @param inOff
+ * @param inLen
+ * @return the wrapped bytes.
+ */
+ public byte[] wrap(byte[] in, int inOff, int inLen)
+ {
+ if (!forWrapping)
+ {
+ throw new IllegalStateException("Not initialized for wrapping");
+ }
+
+ byte keyToBeWrapped[] = new byte[inLen];
+
+ System.arraycopy(in, inOff, keyToBeWrapped, 0, inLen);
+
+ // Compute the CMS Key Checksum, (section 5.6.1), call this CKS.
+ byte[] CKS = calculateCMSKeyChecksum(keyToBeWrapped);
+
+ // Let WKCKS = WK || CKS where || is concatenation.
+ byte[] WKCKS = new byte[keyToBeWrapped.length + CKS.length];
+
+ System.arraycopy(keyToBeWrapped, 0, WKCKS, 0, keyToBeWrapped.length);
+ System.arraycopy(CKS, 0, WKCKS, keyToBeWrapped.length, CKS.length);
+
+ // Encrypt WKCKS in CBC mode using KEK as the key and IV as the
+ // initialization vector. Call the results TEMP1.
+
+ int blockSize = engine.getBlockSize();
+
+ if (WKCKS.length % blockSize != 0)
+ {
+ throw new IllegalStateException("Not multiple of block length");
+ }
+
+ engine.init(true, paramPlusIV);
+
+ byte TEMP1[] = new byte[WKCKS.length];
+
+ for (int currentBytePos = 0; currentBytePos != WKCKS.length; currentBytePos += blockSize)
+ {
+ engine.processBlock(WKCKS, currentBytePos, TEMP1, currentBytePos);
+ }
+
+ // Let TEMP2 = IV || TEMP1.
+ byte[] TEMP2 = new byte[this.iv.length + TEMP1.length];
+
+ System.arraycopy(this.iv, 0, TEMP2, 0, this.iv.length);
+ System.arraycopy(TEMP1, 0, TEMP2, this.iv.length, TEMP1.length);
+
+ // Reverse the order of the octets in TEMP2 and call the result TEMP3.
+ byte[] TEMP3 = reverse(TEMP2);
+
+ // Encrypt TEMP3 in CBC mode using the KEK and an initialization vector
+ // of 0x 4a dd a2 2c 79 e8 21 05. The resulting cipher text is the desired
+ // result. It is 40 octets long if a 168 bit key is being wrapped.
+ ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
+
+ this.engine.init(true, param2);
+
+ for (int currentBytePos = 0; currentBytePos != TEMP3.length; currentBytePos += blockSize)
+ {
+ engine.processBlock(TEMP3, currentBytePos, TEMP3, currentBytePos);
+ }
+
+ return TEMP3;
+ }
+
+ /**
+ * Method unwrap
+ *
+ * @param in
+ * @param inOff
+ * @param inLen
+ * @return the unwrapped bytes.
+ * @throws InvalidCipherTextException
+ */
+ public byte[] unwrap(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forWrapping)
+ {
+ throw new IllegalStateException("Not set for unwrapping");
+ }
+
+ if (in == null)
+ {
+ throw new InvalidCipherTextException("Null pointer as ciphertext");
+ }
+
+ final int blockSize = engine.getBlockSize();
+ if (inLen % blockSize != 0)
+ {
+ throw new InvalidCipherTextException("Ciphertext not multiple of " + blockSize);
+ }
+
+ /*
+ // Check if the length of the cipher text is reasonable given the key
+ // type. It must be 40 bytes for a 168 bit key and either 32, 40, or
+ // 48 bytes for a 128, 192, or 256 bit key. If the length is not supported
+ // or inconsistent with the algorithm for which the key is intended,
+ // return error.
+ //
+ // we do not accept 168 bit keys. it has to be 192 bit.
+ int lengthA = (estimatedKeyLengthInBit / 8) + 16;
+ int lengthB = estimatedKeyLengthInBit % 8;
+
+ if ((lengthA != keyToBeUnwrapped.length) || (lengthB != 0)) {
+ throw new XMLSecurityException("empty");
+ }
+ */
+
+ // Decrypt the cipher text with TRIPLedeS in CBC mode using the KEK
+ // and an initialization vector (IV) of 0x4adda22c79e82105. Call the output TEMP3.
+ ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
+
+ this.engine.init(false, param2);
+
+ byte TEMP3[] = new byte[inLen];
+
+ for (int currentBytePos = 0; currentBytePos != inLen; currentBytePos += blockSize)
+ {
+ engine.processBlock(in, inOff + currentBytePos, TEMP3, currentBytePos);
+ }
+
+ // Reverse the order of the octets in TEMP3 and call the result TEMP2.
+ byte[] TEMP2 = reverse(TEMP3);
+
+ // Decompose TEMP2 into IV, the first 8 octets, and TEMP1, the remaining octets.
+ this.iv = new byte[8];
+
+ byte[] TEMP1 = new byte[TEMP2.length - 8];
+
+ System.arraycopy(TEMP2, 0, this.iv, 0, 8);
+ System.arraycopy(TEMP2, 8, TEMP1, 0, TEMP2.length - 8);
+
+ // Decrypt TEMP1 using TRIPLedeS in CBC mode using the KEK and the IV
+ // found in the previous step. Call the result WKCKS.
+ this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
+
+ this.engine.init(false, this.paramPlusIV);
+
+ byte[] WKCKS = new byte[TEMP1.length];
+
+ for (int currentBytePos = 0; currentBytePos != WKCKS.length; currentBytePos += blockSize)
+ {
+ engine.processBlock(TEMP1, currentBytePos, WKCKS, currentBytePos);
+ }
+
+ // Decompose WKCKS. CKS is the last 8 octets and WK, the wrapped key, are
+ // those octets before the CKS.
+ byte[] result = new byte[WKCKS.length - 8];
+ byte[] CKStoBeVerified = new byte[8];
+
+ System.arraycopy(WKCKS, 0, result, 0, WKCKS.length - 8);
+ System.arraycopy(WKCKS, WKCKS.length - 8, CKStoBeVerified, 0, 8);
+
+ // Calculate a CMS Key Checksum, (section 5.6.1), over the WK and compare
+ // with the CKS extracted in the above step. If they are not equal, return error.
+ if (!checkCMSKeyChecksum(result, CKStoBeVerified))
+ {
+ throw new InvalidCipherTextException(
+ "Checksum inside ciphertext is corrupted");
+ }
+
+ // WK is the wrapped key, now extracted for use in data decryption.
+ return result;
+ }
+
+ /**
+ * Some key wrap algorithms make use of the Key Checksum defined
+ * in CMS [CMS-Algorithms]. This is used to provide an integrity
+ * check value for the key being wrapped. The algorithm is
+ *
+ * - Compute the 20 octet SHA-1 hash on the key being wrapped.
+ * - Use the first 8 octets of this hash as the checksum value.
+ *
+ * @param key
+ * @return the CMS checksum.
+ * @throws RuntimeException
+ * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+ */
+ private byte[] calculateCMSKeyChecksum(
+ byte[] key)
+ {
+ byte[] result = new byte[8];
+
+ sha1.update(key, 0, key.length);
+ sha1.doFinal(digest, 0);
+
+ System.arraycopy(digest, 0, result, 0, 8);
+
+ return result;
+ }
+
+ /**
+ * @param key
+ * @param checksum
+ * @return true if okay, false otherwise.
+ * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+ */
+ private boolean checkCMSKeyChecksum(
+ byte[] key,
+ byte[] checksum)
+ {
+ return Arrays.constantTimeAreEqual(calculateCMSKeyChecksum(key), checksum);
+ }
+
+ private static byte[] reverse(byte[] bs)
+ {
+ byte[] result = new byte[bs.length];
+ for (int i = 0; i < bs.length; i++)
+ {
+ result[i] = bs[bs.length - (i + 1)];
+ }
+ return result;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/ElGamalEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/ElGamalEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/ElGamalEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/ElGamalEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,217 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.ElGamalKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * this does your basic ElGamal algorithm.
+ */
+public class ElGamalEngine
+ implements AsymmetricBlockCipher
+{
+ private ElGamalKeyParameters key;
+ private SecureRandom random;
+ private boolean forEncryption;
+ private int bitSize;
+
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ /**
+ * initialise the ElGamal engine.
+ *
+ * @param forEncryption true if we are encrypting, false otherwise.
+ * @param param the necessary ElGamal key parameters.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)param;
+
+ this.key = (ElGamalKeyParameters)p.getParameters();
+ this.random = p.getRandom();
+ }
+ else
+ {
+ this.key = (ElGamalKeyParameters)param;
+ this.random = new SecureRandom();
+ }
+
+ this.forEncryption = forEncryption;
+
+ BigInteger p = key.getParameters().getP();
+
+ bitSize = p.bitLength();
+
+ if (forEncryption)
+ {
+ if (!(key instanceof ElGamalPublicKeyParameters))
+ {
+ throw new IllegalArgumentException("ElGamalPublicKeyParameters are required for encryption.");
+ }
+ }
+ else
+ {
+ if (!(key instanceof ElGamalPrivateKeyParameters))
+ {
+ throw new IllegalArgumentException("ElGamalPrivateKeyParameters are required for decryption.");
+ }
+ }
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine.
+ * For ElGamal this is always one byte less than the size of P on
+ * encryption, and twice the length as the size of P on decryption.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize()
+ {
+ if (forEncryption)
+ {
+ return (bitSize - 1) / 8;
+ }
+
+ return 2 * ((bitSize + 7) / 8);
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine.
+ * For ElGamal this is always one byte less than the size of P on
+ * decryption, and twice the length as the size of P on encryption.
+ *
+ * @return maximum size for an output block.
+ */
+ public int getOutputBlockSize()
+ {
+ if (forEncryption)
+ {
+ return 2 * ((bitSize + 7) / 8);
+ }
+
+ return (bitSize - 1) / 8;
+ }
+
+ /**
+ * Process a single block using the basic ElGamal algorithm.
+ *
+ * @param in the input array.
+ * @param inOff the offset into the input buffer where the data starts.
+ * @param inLen the length of the data to be processed.
+ * @return the result of the ElGamal process.
+ * @exception DataLengthException the input block is too large.
+ */
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ if (key == null)
+ {
+ throw new IllegalStateException("ElGamal engine not initialised");
+ }
+
+ int maxLength = forEncryption
+ ? (bitSize - 1 + 7) / 8
+ : getInputBlockSize();
+
+ if (inLen > maxLength)
+ {
+ throw new DataLengthException("input too large for ElGamal cipher.\n");
+ }
+
+ BigInteger p = key.getParameters().getP();
+
+ if (key instanceof ElGamalPrivateKeyParameters) // decryption
+ {
+ byte[] in1 = new byte[inLen / 2];
+ byte[] in2 = new byte[inLen / 2];
+
+ System.arraycopy(in, inOff, in1, 0, in1.length);
+ System.arraycopy(in, inOff + in1.length, in2, 0, in2.length);
+
+ BigInteger gamma = new BigInteger(1, in1);
+ BigInteger phi = new BigInteger(1, in2);
+
+ ElGamalPrivateKeyParameters priv = (ElGamalPrivateKeyParameters)key;
+ // a shortcut, which generally relies on p being prime amongst other things.
+ // if a problem with this shows up, check the p and g values!
+ BigInteger m = gamma.modPow(p.subtract(ONE).subtract(priv.getX()), p).multiply(phi).mod(p);
+
+ return BigIntegers.asUnsignedByteArray(m);
+ }
+ else // encryption
+ {
+ byte[] block;
+ if (inOff != 0 || inLen != in.length)
+ {
+ block = new byte[inLen];
+
+ System.arraycopy(in, inOff, block, 0, inLen);
+ }
+ else
+ {
+ block = in;
+ }
+
+ BigInteger input = new BigInteger(1, block);
+
+ if (input.bitLength() >= p.bitLength())
+ {
+ throw new DataLengthException("input too large for ElGamal cipher.\n");
+ }
+
+ ElGamalPublicKeyParameters pub = (ElGamalPublicKeyParameters)key;
+
+ int pBitLength = p.bitLength();
+ BigInteger k = new BigInteger(pBitLength, random);
+
+ while (k.equals(ZERO) || (k.compareTo(p.subtract(TWO)) > 0))
+ {
+ k = new BigInteger(pBitLength, random);
+ }
+
+ BigInteger g = key.getParameters().getG();
+ BigInteger gamma = g.modPow(k, p);
+ BigInteger phi = input.multiply(pub.getY().modPow(k, p)).mod(p);
+
+ byte[] out1 = gamma.toByteArray();
+ byte[] out2 = phi.toByteArray();
+ byte[] output = new byte[this.getOutputBlockSize()];
+
+ if (out1.length > output.length / 2)
+ {
+ System.arraycopy(out1, 1, output, output.length / 2 - (out1.length - 1), out1.length - 1);
+ }
+ else
+ {
+ System.arraycopy(out1, 0, output, output.length / 2 - out1.length, out1.length);
+ }
+
+ if (out2.length > output.length / 2)
+ {
+ System.arraycopy(out2, 1, output, output.length - (out2.length - 1), out2.length - 1);
+ }
+ else
+ {
+ System.arraycopy(out2, 0, output, output.length - out2.length, out2.length);
+ }
+
+ return output;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/GOST28147Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/GOST28147Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/GOST28147Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/GOST28147Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,371 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithSBox;
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * implementation of GOST 28147-89
+ */
+public class GOST28147Engine
+ implements BlockCipher
+{
+ protected static final int BLOCK_SIZE = 8;
+ private int[] workingKey = null;
+ private boolean forEncryption;
+
+ private byte[] S = Sbox_Default;
+
+ // these are the S-boxes given in Applied Cryptography 2nd Ed., p. 333
+ // This is default S-box!
+ private static byte Sbox_Default[] = {
+ 0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3,
+ 0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9,
+ 0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB,
+ 0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3,
+ 0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2,
+ 0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE,
+ 0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC,
+ 0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC
+ };
+
+ /*
+ * class content S-box parameters for encrypting
+ * getting from, see: http://tools.ietf.org/id/draft-popov-cryptopro-cpalgs-01.txt
+ * http://tools.ietf.org/id/draft-popov-cryptopro-cpalgs-02.txt
+ */
+ private static byte[] ESbox_Test = {
+ 0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6,
+ 0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5,
+ 0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB,
+ 0xE,0x9,0xB,0x2,0x5,0xF,0x7,0x1,0x0,0xD,0xC,0x6,0xA,0x4,0x3,0x8,
+ 0x3,0xE,0x5,0x9,0x6,0x8,0x0,0xD,0xA,0xB,0x7,0xC,0x2,0x1,0xF,0x4,
+ 0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4,
+ 0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD,
+ 0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8
+ };
+
+ private static byte[] ESbox_A = {
+ 0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5,
+ 0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1,
+ 0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9,
+ 0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6,
+ 0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6,
+ 0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6,
+ 0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE,
+ 0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4
+ };
+
+ private static byte[] ESbox_B = {
+ 0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF,
+ 0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE,
+ 0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4,
+ 0x7,0x5,0x0,0xD,0xB,0x6,0x1,0x2,0x3,0xA,0xC,0xF,0x4,0xE,0x9,0x8,
+ 0x2,0x7,0xC,0xF,0x9,0x5,0xA,0xB,0x1,0x4,0x0,0xD,0x6,0x8,0xE,0x3,
+ 0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5,
+ 0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE,
+ 0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC
+ };
+
+ private static byte[] ESbox_C = {
+ 0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3,
+ 0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3,
+ 0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB,
+ 0x3,0x6,0x0,0x1,0x5,0xD,0xA,0x8,0xB,0x2,0x9,0x7,0xE,0xF,0xC,0x4,
+ 0x8,0xD,0xB,0x0,0x4,0x5,0x1,0x2,0x9,0x3,0xC,0xE,0x6,0xF,0xA,0x7,
+ 0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD,
+ 0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7,
+ 0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8
+ };
+
+ private static byte[] ESbox_D = {
+ 0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3,
+ 0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1,
+ 0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2,
+ 0x1,0x5,0xE,0xC,0xA,0x7,0x0,0xD,0x6,0x2,0xB,0x4,0x9,0x3,0xF,0x8,
+ 0x0,0xC,0x8,0x9,0xD,0x2,0xA,0xB,0x7,0x3,0x6,0x5,0x4,0xE,0xF,0x1,
+ 0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6,
+ 0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7,
+ 0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE
+ };
+
+ //S-box for digest
+ private static byte DSbox_Test[] = {
+ 0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3,
+ 0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9,
+ 0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB,
+ 0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3,
+ 0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2,
+ 0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE,
+ 0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC,
+ 0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC
+ };
+
+ private static byte DSbox_A[] = {
+ 0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF,
+ 0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8,
+ 0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD,
+ 0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3,
+ 0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5,
+ 0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3,
+ 0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB,
+ 0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC
+ };
+
+ //
+ // pre-defined sbox table
+ //
+ private static Hashtable sBoxes = new Hashtable();
+
+ static
+ {
+ addSBox("Default", Sbox_Default);
+ addSBox("E-TEST", ESbox_Test);
+ addSBox("E-A", ESbox_A);
+ addSBox("E-B", ESbox_B);
+ addSBox("E-C", ESbox_C);
+ addSBox("E-D", ESbox_D);
+ addSBox("D-TEST", DSbox_Test);
+ addSBox("D-A", DSbox_A);
+ }
+
+ private static void addSBox(String sBoxName, byte[] sBox)
+ {
+ sBoxes.put(Strings.toUpperCase(sBoxName), sBox);
+ }
+
+ /**
+ * standard constructor.
+ */
+ public GOST28147Engine()
+ {
+ }
+
+ /**
+ * initialise an GOST28147 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof ParametersWithSBox)
+ {
+ ParametersWithSBox param = (ParametersWithSBox)params;
+
+ //
+ // Set the S-Box
+ //
+ byte[] sBox = param.getSBox();
+ if (sBox.length != Sbox_Default.length)
+ {
+ throw new IllegalArgumentException("invalid S-box passed to GOST28147 init");
+ }
+ this.S = Arrays.clone(sBox);
+
+ //
+ // set key if there is one
+ //
+ if (param.getParameters() != null)
+ {
+ workingKey = generateWorkingKey(forEncryption,
+ ((KeyParameter)param.getParameters()).getKey());
+ }
+ }
+ else if (params instanceof KeyParameter)
+ {
+ workingKey = generateWorkingKey(forEncryption,
+ ((KeyParameter)params).getKey());
+ }
+ else if (params != null)
+ {
+ throw new IllegalArgumentException("invalid parameter passed to GOST28147 init - " + params.getClass().getName());
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return "GOST28147";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("GOST28147 engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ GOST28147Func(workingKey, in, inOff, out, outOff);
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private int[] generateWorkingKey(
+ boolean forEncryption,
+ byte[] userKey)
+ {
+ this.forEncryption = forEncryption;
+
+ if (userKey.length != 32)
+ {
+ throw new IllegalArgumentException("Key length invalid. Key needs to be 32 byte - 256 bit!!!");
+ }
+
+ int key[] = new int[8];
+ for(int i=0; i!=8; i++)
+ {
+ key[i] = bytesToint(userKey,i*4);
+ }
+
+ return key;
+ }
+
+ private int GOST28147_mainStep(int n1, int key)
+ {
+ int cm = (key + n1); // CM1
+
+ // S-box replacing
+
+ int om = S[ 0 + ((cm >> (0 * 4)) & 0xF)] << (0 * 4);
+ om += S[ 16 + ((cm >> (1 * 4)) & 0xF)] << (1 * 4);
+ om += S[ 32 + ((cm >> (2 * 4)) & 0xF)] << (2 * 4);
+ om += S[ 48 + ((cm >> (3 * 4)) & 0xF)] << (3 * 4);
+ om += S[ 64 + ((cm >> (4 * 4)) & 0xF)] << (4 * 4);
+ om += S[ 80 + ((cm >> (5 * 4)) & 0xF)] << (5 * 4);
+ om += S[ 96 + ((cm >> (6 * 4)) & 0xF)] << (6 * 4);
+ om += S[112 + ((cm >> (7 * 4)) & 0xF)] << (7 * 4);
+
+ return om << 11 | om >>> (32-11); // 11-leftshift
+ }
+
+ private void GOST28147Func(
+ int[] workingKey,
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int N1, N2, tmp; //tmp -> for saving N1
+ N1 = bytesToint(in, inOff);
+ N2 = bytesToint(in, inOff + 4);
+
+ if (this.forEncryption)
+ {
+ for(int k = 0; k < 3; k++) // 1-24 steps
+ {
+ for(int j = 0; j < 8; j++)
+ {
+ tmp = N1;
+ N1 = N2 ^ GOST28147_mainStep(N1, workingKey[j]); // CM2
+ N2 = tmp;
+ }
+ }
+ for(int j = 7; j > 0; j--) // 25-31 steps
+ {
+ tmp = N1;
+ N1 = N2 ^ GOST28147_mainStep(N1, workingKey[j]); // CM2
+ N2 = tmp;
+ }
+ }
+ else //decrypt
+ {
+ for(int j = 0; j < 8; j++) // 1-8 steps
+ {
+ tmp = N1;
+ N1 = N2 ^ GOST28147_mainStep(N1, workingKey[j]); // CM2
+ N2 = tmp;
+ }
+ for(int k = 0; k < 3; k++) //9-31 steps
+ {
+ for(int j = 7; j >= 0; j--)
+ {
+ if ((k == 2) && (j==0))
+ {
+ break; // break 32 step
+ }
+ tmp = N1;
+ N1 = N2 ^ GOST28147_mainStep(N1, workingKey[j]); // CM2
+ N2 = tmp;
+ }
+ }
+ }
+
+ N2 = N2 ^ GOST28147_mainStep(N1, workingKey[0]); // 32 step (N1=N1)
+
+ intTobytes(N1, out, outOff);
+ intTobytes(N2, out, outOff + 4);
+ }
+
+ //array of bytes to type int
+ private int bytesToint(
+ byte[] in,
+ int inOff)
+ {
+ return ((in[inOff + 3] << 24) & 0xff000000) + ((in[inOff + 2] << 16) & 0xff0000) +
+ ((in[inOff + 1] << 8) & 0xff00) + (in[inOff] & 0xff);
+ }
+
+ //int to array of bytes
+ private void intTobytes(
+ int num,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff + 3] = (byte)(num >>> 24);
+ out[outOff + 2] = (byte)(num >>> 16);
+ out[outOff + 1] = (byte)(num >>> 8);
+ out[outOff] = (byte)num;
+ }
+
+ /**
+ * Return the S-Box associated with SBoxName
+ * @param sBoxName name of the S-Box
+ * @return byte array representing the S-Box
+ */
+ public static byte[] getSBox(
+ String sBoxName)
+ {
+ byte[] sBox = (byte[])sBoxes.get(Strings.toUpperCase(sBoxName));
+
+ if (sBox == null)
+ {
+ throw new IllegalArgumentException("Unknown S-Box - possible types: "
+ + "\"Default\", \"E-Test\", \"E-A\", \"E-B\", \"E-C\", \"E-D\", \"D-Test\", \"D-A\".");
+ }
+
+ return Arrays.clone(sBox);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/Grain128Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/Grain128Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/Grain128Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/Grain128Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,302 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.StreamCipher;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Implementation of Martin Hell's, Thomas Johansson's and Willi Meier's stream
+ * cipher, Grain-128.
+ */
+public class Grain128Engine
+ implements StreamCipher
+{
+
+ /**
+ * Constants
+ */
+ private static final int STATE_SIZE = 4;
+
+ /**
+ * Variables to hold the state of the engine during encryption and
+ * decryption
+ */
+ private byte[] workingKey;
+ private byte[] workingIV;
+ private byte[] out;
+ private int[] lfsr;
+ private int[] nfsr;
+ private int output;
+ private int index = 4;
+
+ private boolean initialised = false;
+
+ public String getAlgorithmName()
+ {
+ return "Grain-128";
+ }
+
+ /**
+ * Initialize a Grain-128 cipher.
+ *
+ * @param forEncryption Whether or not we are for encryption.
+ * @param params The parameters required to set up the cipher.
+ * @throws IllegalArgumentException If the params argument is inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ /**
+ * Grain encryption and decryption is completely symmetrical, so the
+ * 'forEncryption' is irrelevant.
+ */
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException(
+ "Grain-128 Init parameters must include an IV");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV)params;
+
+ byte[] iv = ivParams.getIV();
+
+ if (iv == null || iv.length != 12)
+ {
+ throw new IllegalArgumentException(
+ "Grain-128 requires exactly 12 bytes of IV");
+ }
+
+ if (!(ivParams.getParameters() instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException(
+ "Grain-128 Init parameters must include a key");
+ }
+
+ KeyParameter key = (KeyParameter)ivParams.getParameters();
+
+ /**
+ * Initialize variables.
+ */
+ workingIV = new byte[key.getKey().length];
+ workingKey = new byte[key.getKey().length];
+ lfsr = new int[STATE_SIZE];
+ nfsr = new int[STATE_SIZE];
+ out = new byte[4];
+
+ System.arraycopy(iv, 0, workingIV, 0, iv.length);
+ System.arraycopy(key.getKey(), 0, workingKey, 0, key.getKey().length);
+
+ setKey(workingKey, workingIV);
+ initGrain();
+ }
+
+ /**
+ * 256 clocks initialization phase.
+ */
+ private void initGrain()
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ output = getOutput();
+ nfsr = shift(nfsr, getOutputNFSR() ^ lfsr[0] ^ output);
+ lfsr = shift(lfsr, getOutputLFSR() ^ output);
+ }
+ initialised = true;
+ }
+
+ /**
+ * Get output from non-linear function g(x).
+ *
+ * @return Output from NFSR.
+ */
+ private int getOutputNFSR()
+ {
+ int b0 = nfsr[0];
+ int b3 = nfsr[0] >>> 3 | nfsr[1] << 29;
+ int b11 = nfsr[0] >>> 11 | nfsr[1] << 21;
+ int b13 = nfsr[0] >>> 13 | nfsr[1] << 19;
+ int b17 = nfsr[0] >>> 17 | nfsr[1] << 15;
+ int b18 = nfsr[0] >>> 18 | nfsr[1] << 14;
+ int b26 = nfsr[0] >>> 26 | nfsr[1] << 6;
+ int b27 = nfsr[0] >>> 27 | nfsr[1] << 5;
+ int b40 = nfsr[1] >>> 8 | nfsr[2] << 24;
+ int b48 = nfsr[1] >>> 16 | nfsr[2] << 16;
+ int b56 = nfsr[1] >>> 24 | nfsr[2] << 8;
+ int b59 = nfsr[1] >>> 27 | nfsr[2] << 5;
+ int b61 = nfsr[1] >>> 29 | nfsr[2] << 3;
+ int b65 = nfsr[2] >>> 1 | nfsr[3] << 31;
+ int b67 = nfsr[2] >>> 3 | nfsr[3] << 29;
+ int b68 = nfsr[2] >>> 4 | nfsr[3] << 28;
+ int b84 = nfsr[2] >>> 20 | nfsr[3] << 12;
+ int b91 = nfsr[2] >>> 27 | nfsr[3] << 5;
+ int b96 = nfsr[3];
+
+ return b0 ^ b26 ^ b56 ^ b91 ^ b96 ^ b3 & b67 ^ b11 & b13 ^ b17 & b18
+ ^ b27 & b59 ^ b40 & b48 ^ b61 & b65 ^ b68 & b84;
+ }
+
+ /**
+ * Get output from linear function f(x).
+ *
+ * @return Output from LFSR.
+ */
+ private int getOutputLFSR()
+ {
+ int s0 = lfsr[0];
+ int s7 = lfsr[0] >>> 7 | lfsr[1] << 25;
+ int s38 = lfsr[1] >>> 6 | lfsr[2] << 26;
+ int s70 = lfsr[2] >>> 6 | lfsr[3] << 26;
+ int s81 = lfsr[2] >>> 17 | lfsr[3] << 15;
+ int s96 = lfsr[3];
+
+ return s0 ^ s7 ^ s38 ^ s70 ^ s81 ^ s96;
+ }
+
+ /**
+ * Get output from output function h(x).
+ *
+ * @return Output from h(x).
+ */
+ private int getOutput()
+ {
+ int b2 = nfsr[0] >>> 2 | nfsr[1] << 30;
+ int b12 = nfsr[0] >>> 12 | nfsr[1] << 20;
+ int b15 = nfsr[0] >>> 15 | nfsr[1] << 17;
+ int b36 = nfsr[1] >>> 4 | nfsr[2] << 28;
+ int b45 = nfsr[1] >>> 13 | nfsr[2] << 19;
+ int b64 = nfsr[2];
+ int b73 = nfsr[2] >>> 9 | nfsr[3] << 23;
+ int b89 = nfsr[2] >>> 25 | nfsr[3] << 7;
+ int b95 = nfsr[2] >>> 31 | nfsr[3] << 1;
+ int s8 = lfsr[0] >>> 8 | lfsr[1] << 24;
+ int s13 = lfsr[0] >>> 13 | lfsr[1] << 19;
+ int s20 = lfsr[0] >>> 20 | lfsr[1] << 12;
+ int s42 = lfsr[1] >>> 10 | lfsr[2] << 22;
+ int s60 = lfsr[1] >>> 28 | lfsr[2] << 4;
+ int s79 = lfsr[2] >>> 15 | lfsr[3] << 17;
+ int s93 = lfsr[2] >>> 29 | lfsr[3] << 3;
+ int s95 = lfsr[2] >>> 31 | lfsr[3] << 1;
+
+ return b12 & s8 ^ s13 & s20 ^ b95 & s42 ^ s60 & s79 ^ b12 & b95 & s95 ^ s93
+ ^ b2 ^ b15 ^ b36 ^ b45 ^ b64 ^ b73 ^ b89;
+ }
+
+ /**
+ * Shift array 32 bits and add val to index.length - 1.
+ *
+ * @param array The array to shift.
+ * @param val The value to shift in.
+ * @return The shifted array with val added to index.length - 1.
+ */
+ private int[] shift(int[] array, int val)
+ {
+ array[0] = array[1];
+ array[1] = array[2];
+ array[2] = array[3];
+ array[3] = val;
+
+ return array;
+ }
+
+ /**
+ * Set keys, reset cipher.
+ *
+ * @param keyBytes The key.
+ * @param ivBytes The IV.
+ */
+ private void setKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ ivBytes[12] = (byte)0xFF;
+ ivBytes[13] = (byte)0xFF;
+ ivBytes[14] = (byte)0xFF;
+ ivBytes[15] = (byte)0xFF;
+ workingKey = keyBytes;
+ workingIV = ivBytes;
+
+ /**
+ * Load NFSR and LFSR
+ */
+ int j = 0;
+ for (int i = 0; i < nfsr.length; i++)
+ {
+ nfsr[i] = ((workingKey[j + 3]) << 24) | ((workingKey[j + 2]) << 16)
+ & 0x00FF0000 | ((workingKey[j + 1]) << 8) & 0x0000FF00
+ | ((workingKey[j]) & 0x000000FF);
+
+ lfsr[i] = ((workingIV[j + 3]) << 24) | ((workingIV[j + 2]) << 16)
+ & 0x00FF0000 | ((workingIV[j + 1]) << 8) & 0x0000FF00
+ | ((workingIV[j]) & 0x000000FF);
+ j += 4;
+ }
+ }
+
+ public void processBytes(byte[] in, int inOff, int len, byte[] out,
+ int outOff)
+ throws DataLengthException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()
+ + " not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ out[outOff + i] = (byte)(in[inOff + i] ^ getKeyStream());
+ }
+ }
+
+ public void reset()
+ {
+ index = 4;
+ setKey(workingKey, workingIV);
+ initGrain();
+ }
+
+ /**
+ * Run Grain one round(i.e. 32 bits).
+ */
+ private void oneRound()
+ {
+ output = getOutput();
+ out[0] = (byte)output;
+ out[1] = (byte)(output >> 8);
+ out[2] = (byte)(output >> 16);
+ out[3] = (byte)(output >> 24);
+
+ nfsr = shift(nfsr, getOutputNFSR() ^ lfsr[0]);
+ lfsr = shift(lfsr, getOutputLFSR());
+ }
+
+ public byte returnByte(byte in)
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()
+ + " not initialised");
+ }
+ return (byte)(in ^ getKeyStream());
+ }
+
+ private byte getKeyStream()
+ {
+ if (index > 3)
+ {
+ oneRound();
+ index = 0;
+ }
+ return out[index++];
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/Grainv1Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/Grainv1Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/Grainv1Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/Grainv1Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,288 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.StreamCipher;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Implementation of Martin Hell's, Thomas Johansson's and Willi Meier's stream
+ * cipher, Grain v1.
+ */
+public class Grainv1Engine
+ implements StreamCipher
+{
+
+ /**
+ * Constants
+ */
+ private static final int STATE_SIZE = 5;
+
+ /**
+ * Variables to hold the state of the engine during encryption and
+ * decryption
+ */
+ private byte[] workingKey;
+ private byte[] workingIV;
+ private byte[] out;
+ private int[] lfsr;
+ private int[] nfsr;
+ private int output;
+ private int index = 2;
+
+ private boolean initialised = false;
+
+ public String getAlgorithmName()
+ {
+ return "Grain v1";
+ }
+
+ /**
+ * Initialize a Grain v1 cipher.
+ *
+ * @param forEncryption Whether or not we are for encryption.
+ * @param params The parameters required to set up the cipher.
+ * @throws IllegalArgumentException If the params argument is inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ /**
+ * Grain encryption and decryption is completely symmetrical, so the
+ * 'forEncryption' is irrelevant.
+ */
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException(
+ "Grain v1 Init parameters must include an IV");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV)params;
+
+ byte[] iv = ivParams.getIV();
+
+ if (iv == null || iv.length != 8)
+ {
+ throw new IllegalArgumentException(
+ "Grain v1 requires exactly 8 bytes of IV");
+ }
+
+ if (!(ivParams.getParameters() instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException(
+ "Grain v1 Init parameters must include a key");
+ }
+
+ KeyParameter key = (KeyParameter)ivParams.getParameters();
+
+ /**
+ * Initialize variables.
+ */
+ workingIV = new byte[key.getKey().length];
+ workingKey = new byte[key.getKey().length];
+ lfsr = new int[STATE_SIZE];
+ nfsr = new int[STATE_SIZE];
+ out = new byte[2];
+
+ System.arraycopy(iv, 0, workingIV, 0, iv.length);
+ System.arraycopy(key.getKey(), 0, workingKey, 0, key.getKey().length);
+
+ setKey(workingKey, workingIV);
+ initGrain();
+ }
+
+ /**
+ * 160 clocks initialization phase.
+ */
+ private void initGrain()
+ {
+ for (int i = 0; i < 10; i++)
+ {
+ output = getOutput();
+ nfsr = shift(nfsr, getOutputNFSR() ^ lfsr[0] ^ output);
+ lfsr = shift(lfsr, getOutputLFSR() ^ output);
+ }
+ initialised = true;
+ }
+
+ /**
+ * Get output from non-linear function g(x).
+ *
+ * @return Output from NFSR.
+ */
+ private int getOutputNFSR()
+ {
+ int b0 = nfsr[0];
+ int b9 = nfsr[0] >>> 9 | nfsr[1] << 7;
+ int b14 = nfsr[0] >>> 14 | nfsr[1] << 2;
+ int b15 = nfsr[0] >>> 15 | nfsr[1] << 1;
+ int b21 = nfsr[1] >>> 5 | nfsr[2] << 11;
+ int b28 = nfsr[1] >>> 12 | nfsr[2] << 4;
+ int b33 = nfsr[2] >>> 1 | nfsr[3] << 15;
+ int b37 = nfsr[2] >>> 5 | nfsr[3] << 11;
+ int b45 = nfsr[2] >>> 13 | nfsr[3] << 3;
+ int b52 = nfsr[3] >>> 4 | nfsr[4] << 12;
+ int b60 = nfsr[3] >>> 12 | nfsr[4] << 4;
+ int b62 = nfsr[3] >>> 14 | nfsr[4] << 2;
+ int b63 = nfsr[3] >>> 15 | nfsr[4] << 1;
+
+ return (b62 ^ b60 ^ b52 ^ b45 ^ b37 ^ b33 ^ b28 ^ b21 ^ b14
+ ^ b9 ^ b0 ^ b63 & b60 ^ b37 & b33 ^ b15 & b9 ^ b60 & b52 & b45
+ ^ b33 & b28 & b21 ^ b63 & b45 & b28 & b9 ^ b60 & b52 & b37
+ & b33 ^ b63 & b60 & b21 & b15 ^ b63 & b60 & b52 & b45 & b37
+ ^ b33 & b28 & b21 & b15 & b9 ^ b52 & b45 & b37 & b33 & b28
+ & b21) & 0x0000FFFF;
+ }
+
+ /**
+ * Get output from linear function f(x).
+ *
+ * @return Output from LFSR.
+ */
+ private int getOutputLFSR()
+ {
+ int s0 = lfsr[0];
+ int s13 = lfsr[0] >>> 13 | lfsr[1] << 3;
+ int s23 = lfsr[1] >>> 7 | lfsr[2] << 9;
+ int s38 = lfsr[2] >>> 6 | lfsr[3] << 10;
+ int s51 = lfsr[3] >>> 3 | lfsr[4] << 13;
+ int s62 = lfsr[3] >>> 14 | lfsr[4] << 2;
+
+ return (s0 ^ s13 ^ s23 ^ s38 ^ s51 ^ s62) & 0x0000FFFF;
+ }
+
+ /**
+ * Get output from output function h(x).
+ *
+ * @return Output from h(x).
+ */
+ private int getOutput()
+ {
+ int b1 = nfsr[0] >>> 1 | nfsr[1] << 15;
+ int b2 = nfsr[0] >>> 2 | nfsr[1] << 14;
+ int b4 = nfsr[0] >>> 4 | nfsr[1] << 12;
+ int b10 = nfsr[0] >>> 10 | nfsr[1] << 6;
+ int b31 = nfsr[1] >>> 15 | nfsr[2] << 1;
+ int b43 = nfsr[2] >>> 11 | nfsr[3] << 5;
+ int b56 = nfsr[3] >>> 8 | nfsr[4] << 8;
+ int b63 = nfsr[3] >>> 15 | nfsr[4] << 1;
+ int s3 = lfsr[0] >>> 3 | lfsr[1] << 13;
+ int s25 = lfsr[1] >>> 9 | lfsr[2] << 7;
+ int s46 = lfsr[2] >>> 14 | lfsr[3] << 2;
+ int s64 = lfsr[4];
+
+ return (s25 ^ b63 ^ s3 & s64 ^ s46 & s64 ^ s64 & b63 ^ s3
+ & s25 & s46 ^ s3 & s46 & s64 ^ s3 & s46 & b63 ^ s25 & s46 & b63 ^ s46
+ & s64 & b63 ^ b1 ^ b2 ^ b4 ^ b10 ^ b31 ^ b43 ^ b56) & 0x0000FFFF;
+ }
+
+ /**
+ * Shift array 16 bits and add val to index.length - 1.
+ *
+ * @param array The array to shift.
+ * @param val The value to shift in.
+ * @return The shifted array with val added to index.length - 1.
+ */
+ private int[] shift(int[] array, int val)
+ {
+ array[0] = array[1];
+ array[1] = array[2];
+ array[2] = array[3];
+ array[3] = array[4];
+ array[4] = val;
+
+ return array;
+ }
+
+ /**
+ * Set keys, reset cipher.
+ *
+ * @param keyBytes The key.
+ * @param ivBytes The IV.
+ */
+ private void setKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ ivBytes[8] = (byte)0xFF;
+ ivBytes[9] = (byte)0xFF;
+ workingKey = keyBytes;
+ workingIV = ivBytes;
+
+ /**
+ * Load NFSR and LFSR
+ */
+ int j = 0;
+ for (int i = 0; i < nfsr.length; i++)
+ {
+ nfsr[i] = (workingKey[j + 1] << 8 | workingKey[j] & 0xFF) & 0x0000FFFF;
+ lfsr[i] = (workingIV[j + 1] << 8 | workingIV[j] & 0xFF) & 0x0000FFFF;
+ j += 2;
+ }
+ }
+
+ public void processBytes(byte[] in, int inOff, int len, byte[] out,
+ int outOff)
+ throws DataLengthException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()
+ + " not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ out[outOff + i] = (byte)(in[inOff + i] ^ getKeyStream());
+ }
+ }
+
+ public void reset()
+ {
+ index = 2;
+ setKey(workingKey, workingIV);
+ initGrain();
+ }
+
+ /**
+ * Run Grain one round(i.e. 16 bits).
+ */
+ private void oneRound()
+ {
+ output = getOutput();
+ out[0] = (byte)output;
+ out[1] = (byte)(output >> 8);
+
+ nfsr = shift(nfsr, getOutputNFSR() ^ lfsr[0]);
+ lfsr = shift(lfsr, getOutputLFSR());
+ }
+
+ public byte returnByte(byte in)
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()
+ + " not initialised");
+ }
+ return (byte)(in ^ getKeyStream());
+ }
+
+ private byte getKeyStream()
+ {
+ if (index > 1)
+ {
+ oneRound();
+ index = 0;
+ }
+ return out[index++];
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/HC128Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/HC128Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/HC128Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/HC128Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,256 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.StreamCipher;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * HC-128 is a software-efficient stream cipher created by Hongjun Wu. It
+ * generates keystream from a 128-bit secret key and a 128-bit initialization
+ * vector.
+ *
+ * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
+ *
+ * It is a third phase candidate in the eStream contest, and is patent-free.
+ * No attacks are known as of today (April 2007). See
+ *
+ * http://www.ecrypt.eu.org/stream/hcp3.html
+ *
+ */
+public class HC128Engine
+ implements StreamCipher
+{
+ private int[] p = new int[512];
+ private int[] q = new int[512];
+ private int cnt = 0;
+
+ private static int f1(int x)
+ {
+ return rotateRight(x, 7) ^ rotateRight(x, 18)
+ ^ (x >>> 3);
+ }
+
+ private static int f2(int x)
+ {
+ return rotateRight(x, 17) ^ rotateRight(x, 19)
+ ^ (x >>> 10);
+ }
+
+ private int g1(int x, int y, int z)
+ {
+ return (rotateRight(x, 10) ^ rotateRight(z, 23))
+ + rotateRight(y, 8);
+ }
+
+ private int g2(int x, int y, int z)
+ {
+ return (rotateLeft(x, 10) ^ rotateLeft(z, 23)) + rotateLeft(y, 8);
+ }
+
+ private static int rotateLeft(
+ int x,
+ int bits)
+ {
+ return (x << bits) | (x >>> -bits);
+ }
+
+ private static int rotateRight(
+ int x,
+ int bits)
+ {
+ return (x >>> bits) | (x << -bits);
+ }
+
+ private int h1(int x)
+ {
+ return q[x & 0xFF] + q[((x >> 16) & 0xFF) + 256];
+ }
+
+ private int h2(int x)
+ {
+ return p[x & 0xFF] + p[((x >> 16) & 0xFF) + 256];
+ }
+
+ private static int mod1024(int x)
+ {
+ return x & 0x3FF;
+ }
+
+ private static int mod512(int x)
+ {
+ return x & 0x1FF;
+ }
+
+ private static int dim(int x, int y)
+ {
+ return mod512(x - y);
+ }
+
+ private int step()
+ {
+ int j = mod512(cnt);
+ int ret;
+ if (cnt < 512)
+ {
+ p[j] += g1(p[dim(j, 3)], p[dim(j, 10)], p[dim(j, 511)]);
+ ret = h1(p[dim(j, 12)]) ^ p[j];
+ }
+ else
+ {
+ q[j] += g2(q[dim(j, 3)], q[dim(j, 10)], q[dim(j, 511)]);
+ ret = h2(q[dim(j, 12)]) ^ q[j];
+ }
+ cnt = mod1024(cnt + 1);
+ return ret;
+ }
+
+ private byte[] key, iv;
+ private boolean initialised;
+
+ private void init()
+ {
+ if (key.length != 16)
+ {
+ throw new java.lang.IllegalArgumentException(
+ "The key must be 128 bits long");
+ }
+
+ cnt = 0;
+
+ int[] w = new int[1280];
+
+ for (int i = 0; i < 16; i++)
+ {
+ w[i >> 2] |= (key[i] & 0xff) << (8 * (i & 0x3));
+ }
+ System.arraycopy(w, 0, w, 4, 4);
+
+ for (int i = 0; i < iv.length && i < 16; i++)
+ {
+ w[(i >> 2) + 8] |= (iv[i] & 0xff) << (8 * (i & 0x3));
+ }
+ System.arraycopy(w, 8, w, 12, 4);
+
+ for (int i = 16; i < 1280; i++)
+ {
+ w[i] = f2(w[i - 2]) + w[i - 7] + f1(w[i - 15]) + w[i - 16] + i;
+ }
+
+ System.arraycopy(w, 256, p, 0, 512);
+ System.arraycopy(w, 768, q, 0, 512);
+
+ for (int i = 0; i < 512; i++)
+ {
+ p[i] = step();
+ }
+ for (int i = 0; i < 512; i++)
+ {
+ q[i] = step();
+ }
+
+ cnt = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "HC-128";
+ }
+
+ /**
+ * Initialise a HC-128 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption. Irrelevant, as
+ * encryption and decryption are the same.
+ * @param params the parameters required to set up the cipher.
+ * @throws IllegalArgumentException if the params argument is
+ * inappropriate (ie. the key is not 128 bit long).
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ CipherParameters keyParam = params;
+
+ if (params instanceof ParametersWithIV)
+ {
+ iv = ((ParametersWithIV)params).getIV();
+ keyParam = ((ParametersWithIV)params).getParameters();
+ }
+ else
+ {
+ iv = new byte[0];
+ }
+
+ if (keyParam instanceof KeyParameter)
+ {
+ key = ((KeyParameter)keyParam).getKey();
+ init();
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Invalid parameter passed to HC128 init - "
+ + params.getClass().getName());
+ }
+
+ initialised = true;
+ }
+
+ private byte[] buf = new byte[4];
+ private int idx = 0;
+
+ private byte getByte()
+ {
+ if (idx == 0)
+ {
+ int step = step();
+ buf[0] = (byte)(step & 0xFF);
+ step >>= 8;
+ buf[1] = (byte)(step & 0xFF);
+ step >>= 8;
+ buf[2] = (byte)(step & 0xFF);
+ step >>= 8;
+ buf[3] = (byte)(step & 0xFF);
+ }
+ byte ret = buf[idx];
+ idx = idx + 1 & 0x3;
+ return ret;
+ }
+
+ public void processBytes(byte[] in, int inOff, int len, byte[] out,
+ int outOff) throws DataLengthException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()
+ + " not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ out[outOff + i] = (byte)(in[inOff + i] ^ getByte());
+ }
+ }
+
+ public void reset()
+ {
+ idx = 0;
+ init();
+ }
+
+ public byte returnByte(byte in)
+ {
+ return (byte)(in ^ getByte());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/HC256Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/HC256Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/HC256Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/HC256Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,243 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.StreamCipher;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * HC-256 is a software-efficient stream cipher created by Hongjun Wu. It
+ * generates keystream from a 256-bit secret key and a 256-bit initialization
+ * vector.
+ *
+ * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
+ *
+ * Its brother, HC-128, is a third phase candidate in the eStream contest.
+ * The algorithm is patent-free. No attacks are known as of today (April 2007).
+ * See
+ *
+ * http://www.ecrypt.eu.org/stream/hcp3.html
+ *
+ */
+public class HC256Engine
+ implements StreamCipher
+{
+ private int[] p = new int[1024];
+ private int[] q = new int[1024];
+ private int cnt = 0;
+
+ private int step()
+ {
+ int j = cnt & 0x3FF;
+ int ret;
+ if (cnt < 1024)
+ {
+ int x = p[(j - 3 & 0x3FF)];
+ int y = p[(j - 1023 & 0x3FF)];
+ p[j] += p[(j - 10 & 0x3FF)]
+ + (rotateRight(x, 10) ^ rotateRight(y, 23))
+ + q[((x ^ y) & 0x3FF)];
+
+ x = p[(j - 12 & 0x3FF)];
+ ret = (q[x & 0xFF] + q[((x >> 8) & 0xFF) + 256]
+ + q[((x >> 16) & 0xFF) + 512] + q[((x >> 24) & 0xFF) + 768])
+ ^ p[j];
+ }
+ else
+ {
+ int x = q[(j - 3 & 0x3FF)];
+ int y = q[(j - 1023 & 0x3FF)];
+ q[j] += q[(j - 10 & 0x3FF)]
+ + (rotateRight(x, 10) ^ rotateRight(y, 23))
+ + p[((x ^ y) & 0x3FF)];
+
+ x = q[(j - 12 & 0x3FF)];
+ ret = (p[x & 0xFF] + p[((x >> 8) & 0xFF) + 256]
+ + p[((x >> 16) & 0xFF) + 512] + p[((x >> 24) & 0xFF) + 768])
+ ^ q[j];
+ }
+ cnt = cnt + 1 & 0x7FF;
+ return ret;
+ }
+
+ private byte[] key, iv;
+ private boolean initialised;
+
+ private void init()
+ {
+ if (key.length != 32 && key.length != 16)
+ {
+ throw new IllegalArgumentException(
+ "The key must be 128/256 bits long");
+ }
+
+ if (iv.length < 16)
+ {
+ throw new IllegalArgumentException(
+ "The IV must be at least 128 bits long");
+ }
+
+ if (key.length != 32)
+ {
+ byte[] k = new byte[32];
+
+ System.arraycopy(key, 0, k, 0, key.length);
+ System.arraycopy(key, 0, k, 16, key.length);
+
+ key = k;
+ }
+
+ if (iv.length < 32)
+ {
+ byte[] newIV = new byte[32];
+
+ System.arraycopy(iv, 0, newIV, 0, iv.length);
+ System.arraycopy(iv, 0, newIV, iv.length, newIV.length - iv.length);
+
+ iv = newIV;
+ }
+
+ cnt = 0;
+
+ int[] w = new int[2560];
+
+ for (int i = 0; i < 32; i++)
+ {
+ w[i >> 2] |= (key[i] & 0xff) << (8 * (i & 0x3));
+ }
+
+ for (int i = 0; i < 32; i++)
+ {
+ w[(i >> 2) + 8] |= (iv[i] & 0xff) << (8 * (i & 0x3));
+ }
+
+ for (int i = 16; i < 2560; i++)
+ {
+ int x = w[i - 2];
+ int y = w[i - 15];
+ w[i] = (rotateRight(x, 17) ^ rotateRight(x, 19) ^ (x >>> 10))
+ + w[i - 7]
+ + (rotateRight(y, 7) ^ rotateRight(y, 18) ^ (y >>> 3))
+ + w[i - 16] + i;
+ }
+
+ System.arraycopy(w, 512, p, 0, 1024);
+ System.arraycopy(w, 1536, q, 0, 1024);
+
+ for (int i = 0; i < 4096; i++)
+ {
+ step();
+ }
+
+ cnt = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "HC-256";
+ }
+
+ /**
+ * Initialise a HC-256 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption. Irrelevant, as
+ * encryption and decryption are the same.
+ * @param params the parameters required to set up the cipher.
+ * @throws IllegalArgumentException if the params argument is
+ * inappropriate (ie. the key is not 256 bit long).
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ CipherParameters keyParam = params;
+
+ if (params instanceof ParametersWithIV)
+ {
+ iv = ((ParametersWithIV)params).getIV();
+ keyParam = ((ParametersWithIV)params).getParameters();
+ }
+ else
+ {
+ iv = new byte[0];
+ }
+
+ if (keyParam instanceof KeyParameter)
+ {
+ key = ((KeyParameter)keyParam).getKey();
+ init();
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Invalid parameter passed to HC256 init - "
+ + params.getClass().getName());
+ }
+
+ initialised = true;
+ }
+
+ private byte[] buf = new byte[4];
+ private int idx = 0;
+
+ private byte getByte()
+ {
+ if (idx == 0)
+ {
+ int step = step();
+ buf[0] = (byte)(step & 0xFF);
+ step >>= 8;
+ buf[1] = (byte)(step & 0xFF);
+ step >>= 8;
+ buf[2] = (byte)(step & 0xFF);
+ step >>= 8;
+ buf[3] = (byte)(step & 0xFF);
+ }
+ byte ret = buf[idx];
+ idx = idx + 1 & 0x3;
+ return ret;
+ }
+
+ public void processBytes(byte[] in, int inOff, int len, byte[] out,
+ int outOff) throws DataLengthException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()
+ + " not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ out[outOff + i] = (byte)(in[inOff + i] ^ getByte());
+ }
+ }
+
+ public void reset()
+ {
+ idx = 0;
+ init();
+ }
+
+ public byte returnByte(byte in)
+ {
+ return (byte)(in ^ getByte());
+ }
+
+ private static int rotateRight(
+ int x,
+ int bits)
+ {
+ return (x >>> bits) | (x << -bits);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/IDEAEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/IDEAEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/IDEAEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/IDEAEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,366 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * A class that provides a basic International Data Encryption Algorithm (IDEA) engine.
+ *
+ * This implementation is based on the "HOWTO: INTERNATIONAL DATA ENCRYPTION ALGORITHM"
+ * implementation summary by Fauzan Mirza (F.U.Mirza@sheffield.ac.uk). (baring 1 typo at the
+ * end of the mulinv function!).
+ *
+ * It can be found at ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/idea/
+ *
+ * Note 1: This algorithm is patented in the USA, Japan, and Europe including
+ * at least Austria, France, Germany, Italy, Netherlands, Spain, Sweden, Switzerland
+ * and the United Kingdom. Non-commercial use is free, however any commercial
+ * products are liable for royalties. Please see
+ * www.mediacrypt.com for
+ * further details. This announcement has been included at the request of
+ * the patent holders.
+ *
+ * Note 2: Due to the requests concerning the above, this algorithm is now only
+ * included in the extended Bouncy Castle provider and JCE signed jars. It is
+ * not included in the default distributions.
+ */
+public class IDEAEngine
+ implements BlockCipher
+{
+ protected static final int BLOCK_SIZE = 8;
+
+ private int[] workingKey = null;
+
+ /**
+ * standard constructor.
+ */
+ public IDEAEngine()
+ {
+ }
+
+ /**
+ * initialise an IDEA cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ workingKey = generateWorkingKey(forEncryption,
+ ((KeyParameter)params).getKey());
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to IDEA init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "IDEA";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("IDEA engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ ideaFunc(workingKey, in, inOff, out, outOff);
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private static final int MASK = 0xffff;
+ private static final int BASE = 0x10001;
+
+ private int bytesToWord(
+ byte[] in,
+ int inOff)
+ {
+ return ((in[inOff] << 8) & 0xff00) + (in[inOff + 1] & 0xff);
+ }
+
+ private void wordToBytes(
+ int word,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff] = (byte)(word >>> 8);
+ out[outOff + 1] = (byte)word;
+ }
+
+ /**
+ * return x = x * y where the multiplication is done modulo
+ * 65537 (0x10001) (as defined in the IDEA specification) and
+ * a zero input is taken to be 65536 (0x10000).
+ *
+ * @param x the x value
+ * @param y the y value
+ * @return x = x * y
+ */
+ private int mul(
+ int x,
+ int y)
+ {
+ if (x == 0)
+ {
+ x = (BASE - y);
+ }
+ else if (y == 0)
+ {
+ x = (BASE - x);
+ }
+ else
+ {
+ int p = x * y;
+
+ y = p & MASK;
+ x = p >>> 16;
+ x = y - x + ((y < x) ? 1 : 0);
+ }
+
+ return x & MASK;
+ }
+
+ private void ideaFunc(
+ int[] workingKey,
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int x0, x1, x2, x3, t0, t1;
+ int keyOff = 0;
+
+ x0 = bytesToWord(in, inOff);
+ x1 = bytesToWord(in, inOff + 2);
+ x2 = bytesToWord(in, inOff + 4);
+ x3 = bytesToWord(in, inOff + 6);
+
+ for (int round = 0; round < 8; round++)
+ {
+ x0 = mul(x0, workingKey[keyOff++]);
+ x1 += workingKey[keyOff++];
+ x1 &= MASK;
+ x2 += workingKey[keyOff++];
+ x2 &= MASK;
+ x3 = mul(x3, workingKey[keyOff++]);
+
+ t0 = x1;
+ t1 = x2;
+ x2 ^= x0;
+ x1 ^= x3;
+
+ x2 = mul(x2, workingKey[keyOff++]);
+ x1 += x2;
+ x1 &= MASK;
+
+ x1 = mul(x1, workingKey[keyOff++]);
+ x2 += x1;
+ x2 &= MASK;
+
+ x0 ^= x1;
+ x3 ^= x2;
+ x1 ^= t1;
+ x2 ^= t0;
+ }
+
+ wordToBytes(mul(x0, workingKey[keyOff++]), out, outOff);
+ wordToBytes(x2 + workingKey[keyOff++], out, outOff + 2); /* NB: Order */
+ wordToBytes(x1 + workingKey[keyOff++], out, outOff + 4);
+ wordToBytes(mul(x3, workingKey[keyOff]), out, outOff + 6);
+ }
+
+ /**
+ * The following function is used to expand the user key to the encryption
+ * subkey. The first 16 bytes are the user key, and the rest of the subkey
+ * is calculated by rotating the previous 16 bytes by 25 bits to the left,
+ * and so on until the subkey is completed.
+ */
+ private int[] expandKey(
+ byte[] uKey)
+ {
+ int[] key = new int[52];
+
+ if (uKey.length < 16)
+ {
+ byte[] tmp = new byte[16];
+
+ System.arraycopy(uKey, 0, tmp, tmp.length - uKey.length, uKey.length);
+
+ uKey = tmp;
+ }
+
+ for (int i = 0; i < 8; i++)
+ {
+ key[i] = bytesToWord(uKey, i * 2);
+ }
+
+ for (int i = 8; i < 52; i++)
+ {
+ if ((i & 7) < 6)
+ {
+ key[i] = ((key[i - 7] & 127) << 9 | key[i - 6] >> 7) & MASK;
+ }
+ else if ((i & 7) == 6)
+ {
+ key[i] = ((key[i - 7] & 127) << 9 | key[i - 14] >> 7) & MASK;
+ }
+ else
+ {
+ key[i] = ((key[i - 15] & 127) << 9 | key[i - 14] >> 7) & MASK;
+ }
+ }
+
+ return key;
+ }
+
+ /**
+ * This function computes multiplicative inverse using Euclid's Greatest
+ * Common Divisor algorithm. Zero and one are self inverse.
+ *
+ * i.e. x * mulInv(x) == 1 (modulo BASE)
+ */
+ private int mulInv(
+ int x)
+ {
+ int t0, t1, q, y;
+
+ if (x < 2)
+ {
+ return x;
+ }
+
+ t0 = 1;
+ t1 = BASE / x;
+ y = BASE % x;
+
+ while (y != 1)
+ {
+ q = x / y;
+ x = x % y;
+ t0 = (t0 + (t1 * q)) & MASK;
+ if (x == 1)
+ {
+ return t0;
+ }
+ q = y / x;
+ y = y % x;
+ t1 = (t1 + (t0 * q)) & MASK;
+ }
+
+ return (1 - t1) & MASK;
+ }
+
+ /**
+ * Return the additive inverse of x.
+ *
+ * i.e. x + addInv(x) == 0
+ */
+ int addInv(
+ int x)
+ {
+ return (0 - x) & MASK;
+ }
+
+ /**
+ * The function to invert the encryption subkey to the decryption subkey.
+ * It also involves the multiplicative inverse and the additive inverse functions.
+ */
+ private int[] invertKey(
+ int[] inKey)
+ {
+ int t1, t2, t3, t4;
+ int p = 52; /* We work backwards */
+ int[] key = new int[52];
+ int inOff = 0;
+
+ t1 = mulInv(inKey[inOff++]);
+ t2 = addInv(inKey[inOff++]);
+ t3 = addInv(inKey[inOff++]);
+ t4 = mulInv(inKey[inOff++]);
+ key[--p] = t4;
+ key[--p] = t3;
+ key[--p] = t2;
+ key[--p] = t1;
+
+ for (int round = 1; round < 8; round++)
+ {
+ t1 = inKey[inOff++];
+ t2 = inKey[inOff++];
+ key[--p] = t2;
+ key[--p] = t1;
+
+ t1 = mulInv(inKey[inOff++]);
+ t2 = addInv(inKey[inOff++]);
+ t3 = addInv(inKey[inOff++]);
+ t4 = mulInv(inKey[inOff++]);
+ key[--p] = t4;
+ key[--p] = t2; /* NB: Order */
+ key[--p] = t3;
+ key[--p] = t1;
+ }
+
+ t1 = inKey[inOff++];
+ t2 = inKey[inOff++];
+ key[--p] = t2;
+ key[--p] = t1;
+
+ t1 = mulInv(inKey[inOff++]);
+ t2 = addInv(inKey[inOff++]);
+ t3 = addInv(inKey[inOff++]);
+ t4 = mulInv(inKey[inOff]);
+ key[--p] = t4;
+ key[--p] = t3;
+ key[--p] = t2;
+ key[--p] = t1;
+
+ return key;
+ }
+
+ private int[] generateWorkingKey(
+ boolean forEncryption,
+ byte[] userKey)
+ {
+ if (forEncryption)
+ {
+ return expandKey(userKey);
+ }
+ else
+ {
+ return invertKey(expandKey(userKey));
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/IESEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/IESEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/IESEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/IESEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,421 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.BasicAgreement;
+import pdftk.org.bouncycastle.crypto.BufferedBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DerivationFunction;
+import pdftk.org.bouncycastle.crypto.EphemeralKeyPair;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.KeyParser;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.IESParameters;
+import pdftk.org.bouncycastle.crypto.params.IESWithCipherParameters;
+import pdftk.org.bouncycastle.crypto.params.KDFParameters;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.util.Pack;
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+/**
+ * Support class for constructing integrated encryption ciphers
+ * for doing basic message exchanges on top of key agreement ciphers.
+ * Follows the description given in IEEE Std 1363a.
+ */
+public class IESEngine
+{
+ BasicAgreement agree;
+ DerivationFunction kdf;
+ Mac mac;
+ BufferedBlockCipher cipher;
+ byte[] macBuf;
+
+ boolean forEncryption;
+ CipherParameters privParam, pubParam;
+ IESParameters param;
+
+ byte[] V;
+ private EphemeralKeyPairGenerator keyPairGenerator;
+ private KeyParser keyParser;
+
+
+ /**
+ * set up for use with stream mode, where the key derivation function
+ * is used to provide a stream of bytes to xor with the message.
+ *
+ * @param agree the key agreement used as the basis for the encryption
+ * @param kdf the key derivation function used for byte generation
+ * @param mac the message authentication code generator for the message
+ */
+ public IESEngine(
+ BasicAgreement agree,
+ DerivationFunction kdf,
+ Mac mac)
+ {
+ this.agree = agree;
+ this.kdf = kdf;
+ this.mac = mac;
+ this.macBuf = new byte[mac.getMacSize()];
+ this.cipher = null;
+ }
+
+
+ /**
+ * set up for use in conjunction with a block cipher to handle the
+ * message.
+ *
+ * @param agree the key agreement used as the basis for the encryption
+ * @param kdf the key derivation function used for byte generation
+ * @param mac the message authentication code generator for the message
+ * @param cipher the cipher to used for encrypting the message
+ */
+ public IESEngine(
+ BasicAgreement agree,
+ DerivationFunction kdf,
+ Mac mac,
+ BufferedBlockCipher cipher)
+ {
+ this.agree = agree;
+ this.kdf = kdf;
+ this.mac = mac;
+ this.macBuf = new byte[mac.getMacSize()];
+ this.cipher = cipher;
+ }
+
+
+ /**
+ * Initialise the encryptor.
+ *
+ * @param forEncryption whether or not this is encryption/decryption.
+ * @param privParam our private key parameters
+ * @param pubParam the recipient's/sender's public key parameters
+ * @param param encoding and derivation parameters.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters privParam,
+ CipherParameters pubParam,
+ CipherParameters param)
+ {
+ this.forEncryption = forEncryption;
+ this.privParam = privParam;
+ this.pubParam = pubParam;
+ this.param = (IESParameters)param;
+ this.V = new byte[0];
+ }
+
+
+ /**
+ * Initialise the encryptor.
+ *
+ * @param publicKey the recipient's/sender's public key parameters
+ * @param params encoding and derivation parameters.
+ * @param ephemeralKeyPairGenerator the ephemeral key pair generator to use.
+ */
+ public void init(AsymmetricKeyParameter publicKey, CipherParameters params, EphemeralKeyPairGenerator ephemeralKeyPairGenerator)
+ {
+ this.forEncryption = true;
+ this.pubParam = publicKey;
+ this.param = (IESParameters)params;
+ this.keyPairGenerator = ephemeralKeyPairGenerator;
+ }
+
+ /**
+ * Initialise the encryptor.
+ *
+ * @param privateKey the recipient's private key.
+ * @param params encoding and derivation parameters.
+ * @param publicKeyParser the parser for reading the ephemeral public key.
+ */
+ public void init(AsymmetricKeyParameter privateKey, CipherParameters params, KeyParser publicKeyParser)
+ {
+ this.forEncryption = false;
+ this.privParam = privateKey;
+ this.param = (IESParameters)params;
+ this.keyParser = publicKeyParser;
+ }
+
+ public BufferedBlockCipher getCipher()
+ {
+ return cipher;
+ }
+
+ public Mac getMac()
+ {
+ return mac;
+ }
+
+ private byte[] encryptBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] C = null, K = null, K1 = null, K2 = null;
+ int len;
+
+ if (cipher == null)
+ {
+ // Streaming mode.
+ K1 = new byte[inLen];
+ K2 = new byte[param.getMacKeySize() / 8];
+ K = new byte[K1.length + K2.length];
+
+ kdf.generateBytes(K, 0, K.length);
+
+ if (V.length != 0)
+ {
+ System.arraycopy(K, 0, K2, 0, K2.length);
+ System.arraycopy(K, K2.length, K1, 0, K1.length);
+ }
+ else
+ {
+ System.arraycopy(K, 0, K1, 0, K1.length);
+ System.arraycopy(K, inLen, K2, 0, K2.length);
+ }
+
+ C = new byte[inLen];
+
+ for (int i = 0; i != inLen; i++)
+ {
+ C[i] = (byte)(in[inOff + i] ^ K1[i]);
+ }
+ len = inLen;
+
+ }
+ else
+ {
+ // Block cipher mode.
+ K1 = new byte[((IESWithCipherParameters)param).getCipherKeySize() / 8];
+ K2 = new byte[param.getMacKeySize() / 8];
+ K = new byte[K1.length + K2.length];
+
+ kdf.generateBytes(K, 0, K.length);
+ System.arraycopy(K, 0, K1, 0, K1.length);
+ System.arraycopy(K, K1.length, K2, 0, K2.length);
+
+ cipher.init(true, new KeyParameter(K1));
+ C = new byte[cipher.getOutputSize(inLen)];
+ len = cipher.processBytes(in, inOff, inLen, C, 0);
+ len += cipher.doFinal(C, len);
+ }
+
+
+ // Convert the length of the encoding vector into a byte array.
+ byte[] P2 = param.getEncodingV();
+ byte[] L2 = new byte[4];
+ if (V.length != 0)
+ {
+ if (P2 == null)
+ {
+ Pack.intToBigEndian(0, L2, 0);
+ }
+ else
+ {
+ Pack.intToBigEndian(P2.length * 8, L2, 0);
+ }
+ }
+
+
+ // Apply the MAC.
+ byte[] T = new byte[mac.getMacSize()];
+
+ mac.init(new KeyParameter(K2));
+ mac.update(C, 0, C.length);
+ if (P2 != null)
+ {
+ mac.update(P2, 0, P2.length);
+ }
+ if (V.length != 0)
+ {
+ mac.update(L2, 0, L2.length);
+ }
+ mac.doFinal(T, 0);
+
+
+ // Output the triple (V,C,T).
+ byte[] Output = new byte[V.length + len + T.length];
+ System.arraycopy(V, 0, Output, 0, V.length);
+ System.arraycopy(C, 0, Output, V.length, len);
+ System.arraycopy(T, 0, Output, V.length + len, T.length);
+ return Output;
+ }
+
+ private byte[] decryptBlock(
+ byte[] in_enc,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ byte[] M = null, K = null, K1 = null, K2 = null;
+ int len;
+
+ if (cipher == null)
+ {
+ // Streaming mode.
+ K1 = new byte[inLen - V.length - mac.getMacSize()];
+ K2 = new byte[param.getMacKeySize() / 8];
+ K = new byte[K1.length + K2.length];
+
+ kdf.generateBytes(K, 0, K.length);
+
+ if (V.length != 0)
+ {
+ System.arraycopy(K, 0, K2, 0, K2.length);
+ System.arraycopy(K, K2.length, K1, 0, K1.length);
+ }
+ else
+ {
+ System.arraycopy(K, 0, K1, 0, K1.length);
+ System.arraycopy(K, K1.length, K2, 0, K2.length);
+ }
+
+ M = new byte[K1.length];
+
+ for (int i = 0; i != K1.length; i++)
+ {
+ M[i] = (byte)(in_enc[inOff + V.length + i] ^ K1[i]);
+ }
+
+
+ len = K1.length;
+
+ }
+ else
+ {
+ // Block cipher mode.
+ K1 = new byte[((IESWithCipherParameters)param).getCipherKeySize() / 8];
+ K2 = new byte[param.getMacKeySize() / 8];
+ K = new byte[K1.length + K2.length];
+
+ kdf.generateBytes(K, 0, K.length);
+ System.arraycopy(K, 0, K1, 0, K1.length);
+ System.arraycopy(K, K1.length, K2, 0, K2.length);
+
+ cipher.init(false, new KeyParameter(K1));
+
+ M = new byte[cipher.getOutputSize(inLen - V.length - mac.getMacSize())];
+ len = cipher.processBytes(in_enc, inOff + V.length, inLen - V.length - mac.getMacSize(), M, 0);
+ len += cipher.doFinal(M, len);
+
+ }
+
+
+ // Convert the length of the encoding vector into a byte array.
+ byte[] P2 = param.getEncodingV();
+ byte[] L2 = new byte[4];
+ if (V.length != 0)
+ {
+ if (P2 != null)
+ {
+ Pack.intToBigEndian(P2.length * 8, L2, 0);
+ }
+ else
+ {
+ Pack.intToBigEndian(0, L2, 0);
+ }
+ }
+
+
+ // Verify the MAC.
+ byte[] T1 = new byte[mac.getMacSize()];
+ System.arraycopy(in_enc, inOff + inLen - T1.length, T1, 0, T1.length);
+
+ byte[] T2 = new byte[T1.length];
+ mac.init(new KeyParameter(K2));
+ mac.update(in_enc, inOff + V.length, inLen - V.length - T2.length);
+
+ if (P2 != null)
+ {
+ mac.update(P2, 0, P2.length);
+ }
+ if (V.length != 0)
+ {
+ mac.update(L2, 0, L2.length);
+ }
+ mac.doFinal(T2, 0);
+
+ if (!Arrays.areEqual(T1, T2))
+ {
+ throw new InvalidCipherTextException("Invalid MAC.");
+ }
+
+
+ // Output the message.
+ byte[] Output = new byte[len];
+ System.arraycopy(M, 0, Output, 0, len);
+ return Output;
+ }
+
+
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forEncryption)
+ {
+ if (keyPairGenerator != null)
+ {
+ EphemeralKeyPair ephKeyPair = keyPairGenerator.generate();
+
+ this.privParam = ephKeyPair.getKeyPair().getPrivate();
+ this.V = ephKeyPair.getEncodedPublicKey();
+ }
+ }
+ else
+ {
+ if (keyParser != null)
+ {
+ ByteArrayInputStream bIn = new ByteArrayInputStream(in, inOff, inLen);
+
+ try
+ {
+ this.pubParam = keyParser.readKey(bIn);
+ }
+ catch (IOException e)
+ {
+ throw new InvalidCipherTextException("unable to recover ephemeral public key: " + e.getMessage(), e);
+ }
+
+ int encLength = (inLen - bIn.available());
+
+ this.V = new byte[encLength];
+ System.arraycopy(in, inOff, V, 0, V.length);
+ }
+ }
+
+ // Compute the common value and convert to byte array.
+ agree.init(privParam);
+ BigInteger z = agree.calculateAgreement(pubParam);
+ byte[] Z = BigIntegers.asUnsignedByteArray(agree.getFieldSize(), z);
+
+ // Create input to KDF.
+ byte[] VZ = null;
+
+ if (V.length != 0)
+ {
+ VZ = new byte[V.length + Z.length];
+ System.arraycopy(V, 0, VZ, 0, V.length);
+ System.arraycopy(Z, 0, VZ, V.length, Z.length);
+ }
+ else
+ {
+ VZ = Z;
+ }
+
+ // Initialise the KDF.
+ KDFParameters kdfParam = new KDFParameters(VZ, param.getDerivationV());
+ kdf.init(kdfParam);
+
+ return forEncryption
+ ? encryptBlock(in, inOff, inLen)
+ : decryptBlock(in, inOff, inLen);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/ISAACEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/ISAACEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/ISAACEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/ISAACEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,245 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.StreamCipher;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * Implementation of Bob Jenkin's ISAAC (Indirection Shift Accumulate Add and Count).
+ * see: http://www.burtleburtle.net/bob/rand/isaacafa.html
+*/
+public class ISAACEngine
+ implements StreamCipher
+{
+ // Constants
+ private final int sizeL = 8,
+ stateArraySize = sizeL<<5; // 256
+
+ // Cipher's internal state
+ private int[] engineState = null, // mm
+ results = null; // randrsl
+ private int a = 0, b = 0, c = 0;
+
+ // Engine state
+ private int index = 0;
+ private byte[] keyStream = new byte[stateArraySize<<2], // results expanded into bytes
+ workingKey = null;
+ private boolean initialised = false;
+
+ /**
+ * initialise an ISAAC cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to ISAAC init - " + params.getClass().getName());
+ }
+ /*
+ * ISAAC encryption and decryption is completely
+ * symmetrical, so the 'forEncryption' is
+ * irrelevant.
+ */
+ KeyParameter p = (KeyParameter)params;
+ setKey(p.getKey());
+
+ return;
+ }
+
+ public byte returnByte(byte in)
+ {
+ if (index == 0)
+ {
+ isaac();
+ keyStream = intToByteLittle(results);
+ }
+ byte out = (byte)(keyStream[index]^in);
+ index = (index + 1) & 1023;
+
+ return out;
+ }
+
+ public void processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ if (index == 0)
+ {
+ isaac();
+ keyStream = intToByteLittle(results);
+ }
+ out[i+outOff] = (byte)(keyStream[index]^in[i+inOff]);
+ index = (index + 1) & 1023;
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return "ISAAC";
+ }
+
+ public void reset()
+ {
+ setKey(workingKey);
+ }
+
+ // Private implementation
+ private void setKey(byte[] keyBytes)
+ {
+ workingKey = keyBytes;
+
+ if (engineState == null)
+ {
+ engineState = new int[stateArraySize];
+ }
+
+ if (results == null)
+ {
+ results = new int[stateArraySize];
+ }
+
+ int i, j, k;
+
+ // Reset state
+ for (i = 0; i < stateArraySize; i++)
+ {
+ engineState[i] = results[i] = 0;
+ }
+ a = b = c = 0;
+
+ // Reset index counter for output
+ index = 0;
+
+ // Convert the key bytes to ints and put them into results[] for initialization
+ byte[] t = new byte[keyBytes.length + (keyBytes.length & 3)];
+ System.arraycopy(keyBytes, 0, t, 0, keyBytes.length);
+ for (i = 0; i < t.length; i+=4)
+ {
+ results[i>>2] = byteToIntLittle(t, i);
+ }
+
+ // It has begun?
+ int[] abcdefgh = new int[sizeL];
+
+ for (i = 0; i < sizeL; i++)
+ {
+ abcdefgh[i] = 0x9e3779b9; // Phi (golden ratio)
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ mix(abcdefgh);
+ }
+
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < stateArraySize; j+=sizeL)
+ {
+ for (k = 0; k < sizeL; k++)
+ {
+ abcdefgh[k] += (i<1) ? results[j+k] : engineState[j+k];
+ }
+
+ mix(abcdefgh);
+
+ for (k = 0; k < sizeL; k++)
+ {
+ engineState[j+k] = abcdefgh[k];
+ }
+ }
+ }
+
+ isaac();
+
+ initialised = true;
+ }
+
+ private void isaac()
+ {
+ int i, x, y;
+
+ b += ++c;
+ for (i = 0; i < stateArraySize; i++)
+ {
+ x = engineState[i];
+ switch (i & 3)
+ {
+ case 0: a ^= (a << 13); break;
+ case 1: a ^= (a >>> 6); break;
+ case 2: a ^= (a << 2); break;
+ case 3: a ^= (a >>> 16); break;
+ }
+ a += engineState[(i+128) & 0xFF];
+ engineState[i] = y = engineState[(x >>> 2) & 0xFF] + a + b;
+ results[i] = b = engineState[(y >>> 10) & 0xFF] + x;
+ }
+ }
+
+ private void mix(int[] x)
+ {
+ x[0]^=x[1]<< 11; x[3]+=x[0]; x[1]+=x[2];
+ x[1]^=x[2]>>> 2; x[4]+=x[1]; x[2]+=x[3];
+ x[2]^=x[3]<< 8; x[5]+=x[2]; x[3]+=x[4];
+ x[3]^=x[4]>>>16; x[6]+=x[3]; x[4]+=x[5];
+ x[4]^=x[5]<< 10; x[7]+=x[4]; x[5]+=x[6];
+ x[5]^=x[6]>>> 4; x[0]+=x[5]; x[6]+=x[7];
+ x[6]^=x[7]<< 8; x[1]+=x[6]; x[7]+=x[0];
+ x[7]^=x[0]>>> 9; x[2]+=x[7]; x[0]+=x[1];
+ }
+
+ private int byteToIntLittle(byte[] x, int offset)
+ {
+ return (int)(x[offset++] & 0xFF) |
+ ((x[offset++] & 0xFF) << 8) |
+ ((x[offset++] & 0xFF) << 16) |
+ (x[offset++] << 24);
+ }
+
+ private byte[] intToByteLittle(int x)
+ {
+ byte[] out = new byte[4];
+ out[3] = (byte)x;
+ out[2] = (byte)(x >>> 8);
+ out[1] = (byte)(x >>> 16);
+ out[0] = (byte)(x >>> 24);
+ return out;
+ }
+
+ private byte[] intToByteLittle(int[] x)
+ {
+ byte[] out = new byte[4*x.length];
+ for (int i = 0, j = 0; i < x.length; i++,j+=4)
+ {
+ System.arraycopy(intToByteLittle(x[i]), 0, out, j, 4);
+ }
+ return out;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/NaccacheSternEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/NaccacheSternEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/NaccacheSternEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/NaccacheSternEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,437 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import java.math.BigInteger;
+import java.util.Vector;
+import pdftk.org.bouncycastle.util.Arrays;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.params.NaccacheSternKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.NaccacheSternPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * NaccacheStern Engine. For details on this cipher, please see
+ * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+ */
+public class NaccacheSternEngine
+ implements AsymmetricBlockCipher
+{
+ private boolean forEncryption;
+
+ private NaccacheSternKeyParameters key;
+
+ private Vector[] lookup = null;
+
+ private boolean debug = false;
+
+ private static BigInteger ZERO = BigInteger.valueOf(0);
+ private static BigInteger ONE = BigInteger.valueOf(1);
+
+ /**
+ * Initializes this algorithm. Must be called before all other Functions.
+ *
+ * @see pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher#init(boolean,
+ * pdftk.org.bouncycastle.crypto.CipherParameters)
+ */
+ public void init(boolean forEncryption, CipherParameters param)
+ {
+ this.forEncryption = forEncryption;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ param = ((ParametersWithRandom) param).getParameters();
+ }
+
+ key = (NaccacheSternKeyParameters)param;
+
+ // construct lookup table for faster decryption if necessary
+ if (!this.forEncryption)
+ {
+ if (debug)
+ {
+ System.out.println("Constructing lookup Array");
+ }
+ NaccacheSternPrivateKeyParameters priv = (NaccacheSternPrivateKeyParameters)key;
+ Vector primes = priv.getSmallPrimes();
+ lookup = new Vector[primes.size()];
+ for (int i = 0; i < primes.size(); i++)
+ {
+ BigInteger actualPrime = (BigInteger)primes.elementAt(i);
+ int actualPrimeValue = actualPrime.intValue();
+
+ lookup[i] = new Vector();
+ lookup[i].addElement(ONE);
+
+ if (debug)
+ {
+ System.out.println("Constructing lookup ArrayList for " + actualPrimeValue);
+ }
+
+ BigInteger accJ = ZERO;
+
+ for (int j = 1; j < actualPrimeValue; j++)
+ {
+ accJ = accJ.add(priv.getPhi_n());
+ BigInteger comp = accJ.divide(actualPrime);
+ lookup[i].addElement(priv.getG().modPow(comp, priv.getModulus()));
+ }
+ }
+ }
+ }
+
+ public void setDebug(boolean debug)
+ {
+ this.debug = debug;
+ }
+
+ /**
+ * Returns the input block size of this algorithm.
+ *
+ * @see pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher#getInputBlockSize()
+ */
+ public int getInputBlockSize()
+ {
+ if (forEncryption)
+ {
+ // We can only encrypt values up to lowerSigmaBound
+ return (key.getLowerSigmaBound() + 7) / 8 - 1;
+ }
+ else
+ {
+ // We pad to modulus-size bytes for easier decryption.
+ return key.getModulus().toByteArray().length;
+ }
+ }
+
+ /**
+ * Returns the output block size of this algorithm.
+ *
+ * @see pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher#getOutputBlockSize()
+ */
+ public int getOutputBlockSize()
+ {
+ if (forEncryption)
+ {
+ // encrypted Data is always padded up to modulus size
+ return key.getModulus().toByteArray().length;
+ }
+ else
+ {
+ // decrypted Data has upper limit lowerSigmaBound
+ return (key.getLowerSigmaBound() + 7) / 8 - 1;
+ }
+ }
+
+ /**
+ * Process a single Block using the Naccache-Stern algorithm.
+ *
+ * @see pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher#processBlock(byte[],
+ * int, int)
+ */
+ public byte[] processBlock(byte[] in, int inOff, int len) throws InvalidCipherTextException
+ {
+ if (key == null)
+ {
+ throw new IllegalStateException("NaccacheStern engine not initialised");
+ }
+ if (len > (getInputBlockSize() + 1))
+ {
+ throw new DataLengthException("input too large for Naccache-Stern cipher.\n");
+ }
+
+ if (!forEncryption)
+ {
+ // At decryption make sure that we receive padded data blocks
+ if (len < getInputBlockSize())
+ {
+ throw new InvalidCipherTextException("BlockLength does not match modulus for Naccache-Stern cipher.\n");
+ }
+ }
+
+ byte[] block;
+
+ if (inOff != 0 || len != in.length)
+ {
+ block = new byte[len];
+ System.arraycopy(in, inOff, block, 0, len);
+ }
+ else
+ {
+ block = in;
+ }
+
+ // transform input into BigInteger
+ BigInteger input = new BigInteger(1, block);
+ if (debug)
+ {
+ System.out.println("input as BigInteger: " + input);
+ }
+ byte[] output;
+ if (forEncryption)
+ {
+ output = encrypt(input);
+ }
+ else
+ {
+ Vector plain = new Vector();
+ NaccacheSternPrivateKeyParameters priv = (NaccacheSternPrivateKeyParameters)key;
+ Vector primes = priv.getSmallPrimes();
+ // Get Chinese Remainders of CipherText
+ for (int i = 0; i < primes.size(); i++)
+ {
+ BigInteger exp = input.modPow(priv.getPhi_n().divide((BigInteger)primes.elementAt(i)), priv.getModulus());
+ Vector al = lookup[i];
+ if (lookup[i].size() != ((BigInteger)primes.elementAt(i)).intValue())
+ {
+ if (debug)
+ {
+ System.out.println("Prime is " + primes.elementAt(i) + ", lookup table has size " + al.size());
+ }
+ throw new InvalidCipherTextException("Error in lookup Array for "
+ + ((BigInteger)primes.elementAt(i)).intValue()
+ + ": Size mismatch. Expected ArrayList with length "
+ + ((BigInteger)primes.elementAt(i)).intValue() + " but found ArrayList of length "
+ + lookup[i].size());
+ }
+ int lookedup = al.indexOf(exp);
+
+ if (lookedup == -1)
+ {
+ if (debug)
+ {
+ System.out.println("Actual prime is " + primes.elementAt(i));
+ System.out.println("Decrypted value is " + exp);
+
+ System.out.println("LookupList for " + primes.elementAt(i) + " with size " + lookup[i].size()
+ + " is: ");
+ for (int j = 0; j < lookup[i].size(); j++)
+ {
+ System.out.println(lookup[i].elementAt(j));
+ }
+ }
+ throw new InvalidCipherTextException("Lookup failed");
+ }
+ plain.addElement(BigInteger.valueOf(lookedup));
+ }
+ BigInteger test = chineseRemainder(plain, primes);
+
+ // Should not be used as an oracle, so reencrypt output to see
+ // if it corresponds to input
+
+ // this breaks probabilisic encryption, so disable it. Anyway, we do
+ // use the first n primes for key generation, so it is pretty easy
+ // to guess them. But as stated in the paper, this is not a security
+ // breach. So we can just work with the correct sigma.
+
+ // if (debug) {
+ // System.out.println("Decryption is " + test);
+ // }
+ // if ((key.getG().modPow(test, key.getModulus())).equals(input)) {
+ // output = test.toByteArray();
+ // } else {
+ // if(debug){
+ // System.out.println("Engine seems to be used as an oracle,
+ // returning null");
+ // }
+ // output = null;
+ // }
+
+ output = test.toByteArray();
+
+ }
+
+ return output;
+ }
+
+ /**
+ * Encrypts a BigInteger aka Plaintext with the public key.
+ *
+ * @param plain
+ * The BigInteger to encrypt
+ * @return The byte[] representation of the encrypted BigInteger (i.e.
+ * crypted.toByteArray())
+ */
+ public byte[] encrypt(BigInteger plain)
+ {
+ // Always return modulus size values 0-padded at the beginning
+ // 0-padding at the beginning is correctly parsed by BigInteger :)
+ byte[] output = key.getModulus().toByteArray();
+ Arrays.fill(output, (byte)0);
+ byte[] tmp = key.getG().modPow(plain, key.getModulus()).toByteArray();
+ System
+ .arraycopy(tmp, 0, output, output.length - tmp.length,
+ tmp.length);
+ if (debug)
+ {
+ System.out
+ .println("Encrypted value is: " + new BigInteger(output));
+ }
+ return output;
+ }
+
+ /**
+ * Adds the contents of two encrypted blocks mod sigma
+ *
+ * @param block1
+ * the first encrypted block
+ * @param block2
+ * the second encrypted block
+ * @return encrypt((block1 + block2) mod sigma)
+ * @throws InvalidCipherTextException
+ */
+ public byte[] addCryptedBlocks(byte[] block1, byte[] block2)
+ throws InvalidCipherTextException
+ {
+ // check for correct blocksize
+ if (forEncryption)
+ {
+ if ((block1.length > getOutputBlockSize())
+ || (block2.length > getOutputBlockSize()))
+ {
+ throw new InvalidCipherTextException(
+ "BlockLength too large for simple addition.\n");
+ }
+ }
+ else
+ {
+ if ((block1.length > getInputBlockSize())
+ || (block2.length > getInputBlockSize()))
+ {
+ throw new InvalidCipherTextException(
+ "BlockLength too large for simple addition.\n");
+ }
+ }
+
+ // calculate resulting block
+ BigInteger m1Crypt = new BigInteger(1, block1);
+ BigInteger m2Crypt = new BigInteger(1, block2);
+ BigInteger m1m2Crypt = m1Crypt.multiply(m2Crypt);
+ m1m2Crypt = m1m2Crypt.mod(key.getModulus());
+ if (debug)
+ {
+ System.out.println("c(m1) as BigInteger:....... " + m1Crypt);
+ System.out.println("c(m2) as BigInteger:....... " + m2Crypt);
+ System.out.println("c(m1)*c(m2)%n = c(m1+m2)%n: " + m1m2Crypt);
+ }
+
+ byte[] output = key.getModulus().toByteArray();
+ Arrays.fill(output, (byte)0);
+ System.arraycopy(m1m2Crypt.toByteArray(), 0, output, output.length
+ - m1m2Crypt.toByteArray().length,
+ m1m2Crypt.toByteArray().length);
+
+ return output;
+ }
+
+ /**
+ * Convenience Method for data exchange with the cipher.
+ *
+ * Determines blocksize and splits data to blocksize.
+ *
+ * @param data the data to be processed
+ * @return the data after it went through the NaccacheSternEngine.
+ * @throws InvalidCipherTextException
+ */
+ public byte[] processData(byte[] data) throws InvalidCipherTextException
+ {
+ if (debug)
+ {
+ System.out.println();
+ }
+ if (data.length > getInputBlockSize())
+ {
+ int inBlocksize = getInputBlockSize();
+ int outBlocksize = getOutputBlockSize();
+ if (debug)
+ {
+ System.out.println("Input blocksize is: " + inBlocksize + " bytes");
+ System.out.println("Output blocksize is: " + outBlocksize + " bytes");
+ System.out.println("Data has length:.... " + data.length + " bytes");
+ }
+ int datapos = 0;
+ int retpos = 0;
+ byte[] retval = new byte[(data.length / inBlocksize + 1) * outBlocksize];
+ while (datapos < data.length)
+ {
+ byte[] tmp;
+ if (datapos + inBlocksize < data.length)
+ {
+ tmp = processBlock(data, datapos, inBlocksize);
+ datapos += inBlocksize;
+ }
+ else
+ {
+ tmp = processBlock(data, datapos, data.length - datapos);
+ datapos += data.length - datapos;
+ }
+ if (debug)
+ {
+ System.out.println("new datapos is " + datapos);
+ }
+ if (tmp != null)
+ {
+ System.arraycopy(tmp, 0, retval, retpos, tmp.length);
+
+ retpos += tmp.length;
+ }
+ else
+ {
+ if (debug)
+ {
+ System.out.println("cipher returned null");
+ }
+ throw new InvalidCipherTextException("cipher returned null");
+ }
+ }
+ byte[] ret = new byte[retpos];
+ System.arraycopy(retval, 0, ret, 0, retpos);
+ if (debug)
+ {
+ System.out.println("returning " + ret.length + " bytes");
+ }
+ return ret;
+ }
+ else
+ {
+ if (debug)
+ {
+ System.out.println("data size is less then input block size, processing directly");
+ }
+ return processBlock(data, 0, data.length);
+ }
+ }
+
+ /**
+ * Computes the integer x that is expressed through the given primes and the
+ * congruences with the chinese remainder theorem (CRT).
+ *
+ * @param congruences
+ * the congruences c_i
+ * @param primes
+ * the primes p_i
+ * @return an integer x for that x % p_i == c_i
+ */
+ private static BigInteger chineseRemainder(Vector congruences, Vector primes)
+ {
+ BigInteger retval = ZERO;
+ BigInteger all = ONE;
+ for (int i = 0; i < primes.size(); i++)
+ {
+ all = all.multiply((BigInteger)primes.elementAt(i));
+ }
+ for (int i = 0; i < primes.size(); i++)
+ {
+ BigInteger a = (BigInteger)primes.elementAt(i);
+ BigInteger b = all.divide(a);
+ BigInteger b_ = b.modInverse(a);
+ BigInteger tmp = b.multiply(b_);
+ tmp = tmp.multiply((BigInteger)congruences.elementAt(i));
+ retval = retval.add(tmp);
+ }
+
+ return retval.mod(all);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/NoekeonEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/NoekeonEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/NoekeonEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/NoekeonEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,262 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * A Noekeon engine, using direct-key mode.
+ */
+
+public class NoekeonEngine
+ implements BlockCipher
+{
+ private static final int genericSize = 16; // Block and key size, as well as the amount of rounds.
+
+ private static final int[] nullVector =
+ {
+ 0x00, 0x00, 0x00, 0x00 // Used in decryption
+ },
+
+ roundConstants =
+ {
+ 0x80, 0x1b, 0x36, 0x6c,
+ 0xd8, 0xab, 0x4d, 0x9a,
+ 0x2f, 0x5e, 0xbc, 0x63,
+ 0xc6, 0x97, 0x35, 0x6a,
+ 0xd4
+ };
+
+ private int[] state = new int[4], // a
+ subKeys = new int[4], // k
+ decryptKeys = new int[4];
+
+ private boolean _initialised,
+ _forEncryption;
+
+ /**
+ * Create an instance of the Noekeon encryption algorithm
+ * and set some defaults
+ */
+ public NoekeonEngine()
+ {
+ _initialised = false;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Noekeon";
+ }
+
+ public int getBlockSize()
+ {
+ return genericSize;
+ }
+
+ /**
+ * initialise
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to Noekeon init - " + params.getClass().getName());
+ }
+
+ _forEncryption = forEncryption;
+ _initialised = true;
+
+ KeyParameter p = (KeyParameter)params;
+
+ setKey(p.getKey());
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (!_initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ if ((inOff + genericSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + genericSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ return (_forEncryption) ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ *
+ * @param key the key to be used
+ */
+ private void setKey(
+ byte[] key)
+ {
+ subKeys[0] = bytesToIntBig(key, 0);
+ subKeys[1] = bytesToIntBig(key, 4);
+ subKeys[2] = bytesToIntBig(key, 8);
+ subKeys[3] = bytesToIntBig(key, 12);
+ }
+
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ state[0] = bytesToIntBig(in, inOff);
+ state[1] = bytesToIntBig(in, inOff+4);
+ state[2] = bytesToIntBig(in, inOff+8);
+ state[3] = bytesToIntBig(in, inOff+12);
+
+ int i;
+ for (i = 0; i < genericSize; i++)
+ {
+ state[0] ^= roundConstants[i];
+ theta(state, subKeys);
+ pi1(state);
+ gamma(state);
+ pi2(state);
+ }
+
+ state[0] ^= roundConstants[i];
+ theta(state, subKeys);
+
+ intToBytesBig(state[0], out, outOff);
+ intToBytesBig(state[1], out, outOff+4);
+ intToBytesBig(state[2], out, outOff+8);
+ intToBytesBig(state[3], out, outOff+12);
+
+ return genericSize;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ state[0] = bytesToIntBig(in, inOff);
+ state[1] = bytesToIntBig(in, inOff+4);
+ state[2] = bytesToIntBig(in, inOff+8);
+ state[3] = bytesToIntBig(in, inOff+12);
+
+ System.arraycopy(subKeys, 0, decryptKeys, 0, subKeys.length);
+ theta(decryptKeys, nullVector);
+
+ int i;
+ for (i = genericSize; i > 0; i--)
+ {
+ theta(state, decryptKeys);
+ state[0] ^= roundConstants[i];
+ pi1(state);
+ gamma(state);
+ pi2(state);
+ }
+
+ theta(state, decryptKeys);
+ state[0] ^= roundConstants[i];
+
+ intToBytesBig(state[0], out, outOff);
+ intToBytesBig(state[1], out, outOff+4);
+ intToBytesBig(state[2], out, outOff+8);
+ intToBytesBig(state[3], out, outOff+12);
+
+ return genericSize;
+ }
+
+ private void gamma(int[] a)
+ {
+ a[1] ^= ~a[3] & ~a[2];
+ a[0] ^= a[2] & a[1];
+
+ int tmp = a[3];
+ a[3] = a[0];
+ a[0] = tmp;
+ a[2] ^= a[0]^a[1]^a[3];
+
+ a[1] ^= ~a[3] & ~a[2];
+ a[0] ^= a[2] & a[1];
+ }
+
+ private void theta(int[] a, int[] k)
+ {
+ int tmp;
+
+ tmp = a[0]^a[2];
+ tmp ^= rotl(tmp,8)^rotl(tmp,24);
+ a[1] ^= tmp;
+ a[3] ^= tmp;
+
+ for (int i = 0; i < 4; i++)
+ {
+ a[i] ^= k[i];
+ }
+
+ tmp = a[1]^a[3];
+ tmp ^= rotl(tmp,8)^rotl(tmp,24);
+ a[0] ^= tmp;
+ a[2] ^= tmp;
+ }
+
+ private void pi1(int[] a)
+ {
+ a[1] = rotl(a[1], 1);
+ a[2] = rotl(a[2], 5);
+ a[3] = rotl(a[3], 2);
+ }
+
+ private void pi2(int[] a)
+ {
+ a[1] = rotl(a[1], 31);
+ a[2] = rotl(a[2], 27);
+ a[3] = rotl(a[3], 30);
+ }
+
+ // Helpers
+
+ private int bytesToIntBig(byte[] in, int off)
+ {
+ return ((in[off++]) << 24) |
+ ((in[off++] & 0xff) << 16) |
+ ((in[off++] & 0xff) << 8) |
+ (in[off ] & 0xff);
+ }
+
+ private void intToBytesBig(int x, byte[] out, int off)
+ {
+ out[off++] = (byte)(x >>> 24);
+ out[off++] = (byte)(x >>> 16);
+ out[off++] = (byte)(x >>> 8);
+ out[off ] = (byte)x;
+ }
+
+ private int rotl(int x, int y)
+ {
+ return (x << y) | (x >>> (32-y));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/NullEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/NullEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/NullEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/NullEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,84 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+
+/**
+ * The no-op engine that just copies bytes through, irrespective of whether encrypting and decrypting.
+ * Provided for the sake of completeness.
+ */
+public class NullEngine implements BlockCipher
+{
+ private boolean initialised;
+ protected static final int BLOCK_SIZE = 1;
+
+ /**
+ * Standard constructor.
+ */
+ public NullEngine()
+ {
+ super();
+ }
+
+ /* (non-Javadoc)
+ * @see pdftk.org.bouncycastle.crypto.BlockCipher#init(boolean, pdftk.org.bouncycastle.crypto.CipherParameters)
+ */
+ public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException
+ {
+ // we don't mind any parameters that may come in
+ this.initialised = true;
+ }
+
+ /* (non-Javadoc)
+ * @see pdftk.org.bouncycastle.crypto.BlockCipher#getAlgorithmName()
+ */
+ public String getAlgorithmName()
+ {
+ return "Null";
+ }
+
+ /* (non-Javadoc)
+ * @see pdftk.org.bouncycastle.crypto.BlockCipher#getBlockSize()
+ */
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ /* (non-Javadoc)
+ * @see pdftk.org.bouncycastle.crypto.BlockCipher#processBlock(byte[], int, byte[], int)
+ */
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException("Null engine not initialised");
+ }
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < BLOCK_SIZE; ++i)
+ {
+ out[outOff + i] = in[inOff + i];
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ /* (non-Javadoc)
+ * @see pdftk.org.bouncycastle.crypto.BlockCipher#reset()
+ */
+ public void reset()
+ {
+ // nothing needs to be done
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RC2Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RC2Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RC2Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RC2Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,316 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.RC2Parameters;
+
+/**
+ * an implementation of RC2 as described in RFC 2268
+ * "A Description of the RC2(r) Encryption Algorithm" R. Rivest.
+ */
+public class RC2Engine
+ implements BlockCipher
+{
+ //
+ // the values we use for key expansion (based on the digits of PI)
+ //
+ private static byte[] piTable =
+ {
+ (byte)0xd9, (byte)0x78, (byte)0xf9, (byte)0xc4, (byte)0x19, (byte)0xdd, (byte)0xb5, (byte)0xed,
+ (byte)0x28, (byte)0xe9, (byte)0xfd, (byte)0x79, (byte)0x4a, (byte)0xa0, (byte)0xd8, (byte)0x9d,
+ (byte)0xc6, (byte)0x7e, (byte)0x37, (byte)0x83, (byte)0x2b, (byte)0x76, (byte)0x53, (byte)0x8e,
+ (byte)0x62, (byte)0x4c, (byte)0x64, (byte)0x88, (byte)0x44, (byte)0x8b, (byte)0xfb, (byte)0xa2,
+ (byte)0x17, (byte)0x9a, (byte)0x59, (byte)0xf5, (byte)0x87, (byte)0xb3, (byte)0x4f, (byte)0x13,
+ (byte)0x61, (byte)0x45, (byte)0x6d, (byte)0x8d, (byte)0x9, (byte)0x81, (byte)0x7d, (byte)0x32,
+ (byte)0xbd, (byte)0x8f, (byte)0x40, (byte)0xeb, (byte)0x86, (byte)0xb7, (byte)0x7b, (byte)0xb,
+ (byte)0xf0, (byte)0x95, (byte)0x21, (byte)0x22, (byte)0x5c, (byte)0x6b, (byte)0x4e, (byte)0x82,
+ (byte)0x54, (byte)0xd6, (byte)0x65, (byte)0x93, (byte)0xce, (byte)0x60, (byte)0xb2, (byte)0x1c,
+ (byte)0x73, (byte)0x56, (byte)0xc0, (byte)0x14, (byte)0xa7, (byte)0x8c, (byte)0xf1, (byte)0xdc,
+ (byte)0x12, (byte)0x75, (byte)0xca, (byte)0x1f, (byte)0x3b, (byte)0xbe, (byte)0xe4, (byte)0xd1,
+ (byte)0x42, (byte)0x3d, (byte)0xd4, (byte)0x30, (byte)0xa3, (byte)0x3c, (byte)0xb6, (byte)0x26,
+ (byte)0x6f, (byte)0xbf, (byte)0xe, (byte)0xda, (byte)0x46, (byte)0x69, (byte)0x7, (byte)0x57,
+ (byte)0x27, (byte)0xf2, (byte)0x1d, (byte)0x9b, (byte)0xbc, (byte)0x94, (byte)0x43, (byte)0x3,
+ (byte)0xf8, (byte)0x11, (byte)0xc7, (byte)0xf6, (byte)0x90, (byte)0xef, (byte)0x3e, (byte)0xe7,
+ (byte)0x6, (byte)0xc3, (byte)0xd5, (byte)0x2f, (byte)0xc8, (byte)0x66, (byte)0x1e, (byte)0xd7,
+ (byte)0x8, (byte)0xe8, (byte)0xea, (byte)0xde, (byte)0x80, (byte)0x52, (byte)0xee, (byte)0xf7,
+ (byte)0x84, (byte)0xaa, (byte)0x72, (byte)0xac, (byte)0x35, (byte)0x4d, (byte)0x6a, (byte)0x2a,
+ (byte)0x96, (byte)0x1a, (byte)0xd2, (byte)0x71, (byte)0x5a, (byte)0x15, (byte)0x49, (byte)0x74,
+ (byte)0x4b, (byte)0x9f, (byte)0xd0, (byte)0x5e, (byte)0x4, (byte)0x18, (byte)0xa4, (byte)0xec,
+ (byte)0xc2, (byte)0xe0, (byte)0x41, (byte)0x6e, (byte)0xf, (byte)0x51, (byte)0xcb, (byte)0xcc,
+ (byte)0x24, (byte)0x91, (byte)0xaf, (byte)0x50, (byte)0xa1, (byte)0xf4, (byte)0x70, (byte)0x39,
+ (byte)0x99, (byte)0x7c, (byte)0x3a, (byte)0x85, (byte)0x23, (byte)0xb8, (byte)0xb4, (byte)0x7a,
+ (byte)0xfc, (byte)0x2, (byte)0x36, (byte)0x5b, (byte)0x25, (byte)0x55, (byte)0x97, (byte)0x31,
+ (byte)0x2d, (byte)0x5d, (byte)0xfa, (byte)0x98, (byte)0xe3, (byte)0x8a, (byte)0x92, (byte)0xae,
+ (byte)0x5, (byte)0xdf, (byte)0x29, (byte)0x10, (byte)0x67, (byte)0x6c, (byte)0xba, (byte)0xc9,
+ (byte)0xd3, (byte)0x0, (byte)0xe6, (byte)0xcf, (byte)0xe1, (byte)0x9e, (byte)0xa8, (byte)0x2c,
+ (byte)0x63, (byte)0x16, (byte)0x1, (byte)0x3f, (byte)0x58, (byte)0xe2, (byte)0x89, (byte)0xa9,
+ (byte)0xd, (byte)0x38, (byte)0x34, (byte)0x1b, (byte)0xab, (byte)0x33, (byte)0xff, (byte)0xb0,
+ (byte)0xbb, (byte)0x48, (byte)0xc, (byte)0x5f, (byte)0xb9, (byte)0xb1, (byte)0xcd, (byte)0x2e,
+ (byte)0xc5, (byte)0xf3, (byte)0xdb, (byte)0x47, (byte)0xe5, (byte)0xa5, (byte)0x9c, (byte)0x77,
+ (byte)0xa, (byte)0xa6, (byte)0x20, (byte)0x68, (byte)0xfe, (byte)0x7f, (byte)0xc1, (byte)0xad
+ };
+
+ private static final int BLOCK_SIZE = 8;
+
+ private int[] workingKey;
+ private boolean encrypting;
+
+ private int[] generateWorkingKey(
+ byte[] key,
+ int bits)
+ {
+ int x;
+ int[] xKey = new int[128];
+
+ for (int i = 0; i != key.length; i++)
+ {
+ xKey[i] = key[i] & 0xff;
+ }
+
+ // Phase 1: Expand input key to 128 bytes
+ int len = key.length;
+
+ if (len < 128)
+ {
+ int index = 0;
+
+ x = xKey[len - 1];
+
+ do
+ {
+ x = piTable[(x + xKey[index++]) & 255] & 0xff;
+ xKey[len++] = x;
+ }
+ while (len < 128);
+ }
+
+ // Phase 2 - reduce effective key size to "bits"
+ len = (bits + 7) >> 3;
+ x = piTable[xKey[128 - len] & (255 >> (7 & -bits))] & 0xff;
+ xKey[128 - len] = x;
+
+ for (int i = 128 - len - 1; i >= 0; i--)
+ {
+ x = piTable[x ^ xKey[i + len]] & 0xff;
+ xKey[i] = x;
+ }
+
+ // Phase 3 - copy to newKey in little-endian order
+ int[] newKey = new int[64];
+
+ for (int i = 0; i != newKey.length; i++)
+ {
+ newKey[i] = (xKey[2 * i] + (xKey[2 * i + 1] << 8));
+ }
+
+ return newKey;
+ }
+
+ /**
+ * initialise a RC2 cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ this.encrypting = encrypting;
+
+ if (params instanceof RC2Parameters)
+ {
+ RC2Parameters param = (RC2Parameters)params;
+
+ workingKey = generateWorkingKey(param.getKey(),
+ param.getEffectiveKeyBits());
+ }
+ else if (params instanceof KeyParameter)
+ {
+ byte[] key = ((KeyParameter)params).getKey();
+
+ workingKey = generateWorkingKey(key, key.length * 8);
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameter passed to RC2 init - " + params.getClass().getName());
+ }
+
+ }
+
+ public void reset()
+ {
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RC2";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public final int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("RC2 engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (encrypting)
+ {
+ encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ decryptBlock(in, inOff, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * return the result rotating the 16 bit number in x left by y
+ */
+ private int rotateWordLeft(
+ int x,
+ int y)
+ {
+ x &= 0xffff;
+ return (x << y) | (x >> (16 - y));
+ }
+
+ private void encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int x76, x54, x32, x10;
+
+ x76 = ((in[inOff + 7] & 0xff) << 8) + (in[inOff + 6] & 0xff);
+ x54 = ((in[inOff + 5] & 0xff) << 8) + (in[inOff + 4] & 0xff);
+ x32 = ((in[inOff + 3] & 0xff) << 8) + (in[inOff + 2] & 0xff);
+ x10 = ((in[inOff + 1] & 0xff) << 8) + (in[inOff + 0] & 0xff);
+
+ for (int i = 0; i <= 16; i += 4)
+ {
+ x10 = rotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i ], 1);
+ x32 = rotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
+ x54 = rotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
+ x76 = rotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
+ }
+
+ x10 += workingKey[x76 & 63];
+ x32 += workingKey[x10 & 63];
+ x54 += workingKey[x32 & 63];
+ x76 += workingKey[x54 & 63];
+
+ for (int i = 20; i <= 40; i += 4)
+ {
+ x10 = rotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i ], 1);
+ x32 = rotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
+ x54 = rotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
+ x76 = rotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
+ }
+
+ x10 += workingKey[x76 & 63];
+ x32 += workingKey[x10 & 63];
+ x54 += workingKey[x32 & 63];
+ x76 += workingKey[x54 & 63];
+
+ for (int i = 44; i < 64; i += 4)
+ {
+ x10 = rotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i ], 1);
+ x32 = rotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
+ x54 = rotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
+ x76 = rotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
+ }
+
+ out[outOff + 0] = (byte)x10;
+ out[outOff + 1] = (byte)(x10 >> 8);
+ out[outOff + 2] = (byte)x32;
+ out[outOff + 3] = (byte)(x32 >> 8);
+ out[outOff + 4] = (byte)x54;
+ out[outOff + 5] = (byte)(x54 >> 8);
+ out[outOff + 6] = (byte)x76;
+ out[outOff + 7] = (byte)(x76 >> 8);
+ }
+
+ private void decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int x76, x54, x32, x10;
+
+ x76 = ((in[inOff + 7] & 0xff) << 8) + (in[inOff + 6] & 0xff);
+ x54 = ((in[inOff + 5] & 0xff) << 8) + (in[inOff + 4] & 0xff);
+ x32 = ((in[inOff + 3] & 0xff) << 8) + (in[inOff + 2] & 0xff);
+ x10 = ((in[inOff + 1] & 0xff) << 8) + (in[inOff + 0] & 0xff);
+
+ for (int i = 60; i >= 44; i -= 4)
+ {
+ x76 = rotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
+ x54 = rotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
+ x32 = rotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
+ x10 = rotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i ]);
+ }
+
+ x76 -= workingKey[x54 & 63];
+ x54 -= workingKey[x32 & 63];
+ x32 -= workingKey[x10 & 63];
+ x10 -= workingKey[x76 & 63];
+
+ for (int i = 40; i >= 20; i -= 4)
+ {
+ x76 = rotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
+ x54 = rotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
+ x32 = rotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
+ x10 = rotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i ]);
+ }
+
+ x76 -= workingKey[x54 & 63];
+ x54 -= workingKey[x32 & 63];
+ x32 -= workingKey[x10 & 63];
+ x10 -= workingKey[x76 & 63];
+
+ for (int i = 16; i >= 0; i -= 4)
+ {
+ x76 = rotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
+ x54 = rotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
+ x32 = rotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
+ x10 = rotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i ]);
+ }
+
+ out[outOff + 0] = (byte)x10;
+ out[outOff + 1] = (byte)(x10 >> 8);
+ out[outOff + 2] = (byte)x32;
+ out[outOff + 3] = (byte)(x32 >> 8);
+ out[outOff + 4] = (byte)x54;
+ out[outOff + 5] = (byte)(x54 >> 8);
+ out[outOff + 6] = (byte)x76;
+ out[outOff + 7] = (byte)(x76 >> 8);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RC2WrapEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RC2WrapEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RC2WrapEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RC2WrapEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,383 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.Wrapper;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+import pdftk.org.bouncycastle.crypto.modes.CBCBlockCipher;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * Wrap keys according to RFC 3217 - RC2 mechanism
+ */
+public class RC2WrapEngine
+ implements Wrapper
+{
+ /** Field engine */
+ private CBCBlockCipher engine;
+
+ /** Field param */
+ private CipherParameters param;
+
+ /** Field paramPlusIV */
+ private ParametersWithIV paramPlusIV;
+
+ /** Field iv */
+ private byte[] iv;
+
+ /** Field forWrapping */
+ private boolean forWrapping;
+
+ private SecureRandom sr;
+
+ /** Field IV2 */
+ private static final byte[] IV2 = { (byte) 0x4a, (byte) 0xdd, (byte) 0xa2,
+ (byte) 0x2c, (byte) 0x79, (byte) 0xe8,
+ (byte) 0x21, (byte) 0x05 };
+
+ //
+ // checksum digest
+ //
+ Digest sha1 = new SHA1Digest();
+ byte[] digest = new byte[20];
+
+ /**
+ * Method init
+ *
+ * @param forWrapping
+ * @param param
+ */
+ public void init(boolean forWrapping, CipherParameters param)
+ {
+ this.forWrapping = forWrapping;
+ this.engine = new CBCBlockCipher(new RC2Engine());
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom pWithR = (ParametersWithRandom)param;
+ sr = pWithR.getRandom();
+ param = pWithR.getParameters();
+ }
+ else
+ {
+ sr = new SecureRandom();
+ }
+
+ if (param instanceof ParametersWithIV)
+ {
+ this.paramPlusIV = (ParametersWithIV)param;
+ this.iv = this.paramPlusIV.getIV();
+ this.param = this.paramPlusIV.getParameters();
+
+ if (this.forWrapping)
+ {
+ if ((this.iv == null) || (this.iv.length != 8))
+ {
+ throw new IllegalArgumentException("IV is not 8 octets");
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "You should not supply an IV for unwrapping");
+ }
+ }
+ else
+ {
+ this.param = param;
+
+ if (this.forWrapping)
+ {
+
+ // Hm, we have no IV but we want to wrap ?!?
+ // well, then we have to create our own IV.
+ this.iv = new byte[8];
+
+ sr.nextBytes(iv);
+
+ this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
+ }
+ }
+
+ }
+
+ /**
+ * Method getAlgorithmName
+ *
+ * @return the algorithm name "RC2".
+ */
+ public String getAlgorithmName()
+ {
+ return "RC2";
+ }
+
+ /**
+ * Method wrap
+ *
+ * @param in
+ * @param inOff
+ * @param inLen
+ * @return the wrapped bytes.
+ */
+ public byte[] wrap(byte[] in, int inOff, int inLen)
+ {
+
+ if (!forWrapping)
+ {
+ throw new IllegalStateException("Not initialized for wrapping");
+ }
+
+ int length = inLen + 1;
+ if ((length % 8) != 0)
+ {
+ length += 8 - (length % 8);
+ }
+
+ byte keyToBeWrapped[] = new byte[length];
+
+ keyToBeWrapped[0] = (byte)inLen;
+ System.arraycopy(in, inOff, keyToBeWrapped, 1, inLen);
+
+ byte[] pad = new byte[keyToBeWrapped.length - inLen - 1];
+
+ if (pad.length > 0)
+ {
+ sr.nextBytes(pad);
+ System.arraycopy(pad, 0, keyToBeWrapped, inLen + 1, pad.length);
+ }
+
+ // Compute the CMS Key Checksum, (section 5.6.1), call this CKS.
+ byte[] CKS = calculateCMSKeyChecksum(keyToBeWrapped);
+
+ // Let WKCKS = WK || CKS where || is concatenation.
+ byte[] WKCKS = new byte[keyToBeWrapped.length + CKS.length];
+
+ System.arraycopy(keyToBeWrapped, 0, WKCKS, 0, keyToBeWrapped.length);
+ System.arraycopy(CKS, 0, WKCKS, keyToBeWrapped.length, CKS.length);
+
+ // Encrypt WKCKS in CBC mode using KEK as the key and IV as the
+ // initialization vector. Call the results TEMP1.
+ byte TEMP1[] = new byte[WKCKS.length];
+
+ System.arraycopy(WKCKS, 0, TEMP1, 0, WKCKS.length);
+
+ int noOfBlocks = WKCKS.length / engine.getBlockSize();
+ int extraBytes = WKCKS.length % engine.getBlockSize();
+
+ if (extraBytes != 0)
+ {
+ throw new IllegalStateException("Not multiple of block length");
+ }
+
+ engine.init(true, paramPlusIV);
+
+ for (int i = 0; i < noOfBlocks; i++)
+ {
+ int currentBytePos = i * engine.getBlockSize();
+
+ engine.processBlock(TEMP1, currentBytePos, TEMP1, currentBytePos);
+ }
+
+ // Left TEMP2 = IV || TEMP1.
+ byte[] TEMP2 = new byte[this.iv.length + TEMP1.length];
+
+ System.arraycopy(this.iv, 0, TEMP2, 0, this.iv.length);
+ System.arraycopy(TEMP1, 0, TEMP2, this.iv.length, TEMP1.length);
+
+ // Reverse the order of the octets in TEMP2 and call the result TEMP3.
+ byte[] TEMP3 = new byte[TEMP2.length];
+
+ for (int i = 0; i < TEMP2.length; i++)
+ {
+ TEMP3[i] = TEMP2[TEMP2.length - (i + 1)];
+ }
+
+ // Encrypt TEMP3 in CBC mode using the KEK and an initialization vector
+ // of 0x 4a dd a2 2c 79 e8 21 05. The resulting cipher text is the
+ // desired
+ // result. It is 40 octets long if a 168 bit key is being wrapped.
+ ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
+
+ this.engine.init(true, param2);
+
+ for (int i = 0; i < noOfBlocks + 1; i++)
+ {
+ int currentBytePos = i * engine.getBlockSize();
+
+ engine.processBlock(TEMP3, currentBytePos, TEMP3, currentBytePos);
+ }
+
+ return TEMP3;
+ }
+
+ /**
+ * Method unwrap
+ *
+ * @param in
+ * @param inOff
+ * @param inLen
+ * @return the unwrapped bytes.
+ * @throws InvalidCipherTextException
+ */
+ public byte[] unwrap(byte[] in, int inOff, int inLen)
+ throws InvalidCipherTextException
+ {
+
+ if (forWrapping)
+ {
+ throw new IllegalStateException("Not set for unwrapping");
+ }
+
+ if (in == null)
+ {
+ throw new InvalidCipherTextException("Null pointer as ciphertext");
+ }
+
+ if (inLen % engine.getBlockSize() != 0)
+ {
+ throw new InvalidCipherTextException("Ciphertext not multiple of "
+ + engine.getBlockSize());
+ }
+
+ /*
+ * // Check if the length of the cipher text is reasonable given the key //
+ * type. It must be 40 bytes for a 168 bit key and either 32, 40, or //
+ * 48 bytes for a 128, 192, or 256 bit key. If the length is not
+ * supported // or inconsistent with the algorithm for which the key is
+ * intended, // return error. // // we do not accept 168 bit keys. it
+ * has to be 192 bit. int lengthA = (estimatedKeyLengthInBit / 8) + 16;
+ * int lengthB = estimatedKeyLengthInBit % 8;
+ *
+ * if ((lengthA != keyToBeUnwrapped.length) || (lengthB != 0)) { throw
+ * new XMLSecurityException("empty"); }
+ */
+
+ // Decrypt the cipher text with TRIPLedeS in CBC mode using the KEK
+ // and an initialization vector (IV) of 0x4adda22c79e82105. Call the
+ // output TEMP3.
+ ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
+
+ this.engine.init(false, param2);
+
+ byte TEMP3[] = new byte[inLen];
+
+ System.arraycopy(in, inOff, TEMP3, 0, inLen);
+
+ for (int i = 0; i < (TEMP3.length / engine.getBlockSize()); i++)
+ {
+ int currentBytePos = i * engine.getBlockSize();
+
+ engine.processBlock(TEMP3, currentBytePos, TEMP3, currentBytePos);
+ }
+
+ // Reverse the order of the octets in TEMP3 and call the result TEMP2.
+ byte[] TEMP2 = new byte[TEMP3.length];
+
+ for (int i = 0; i < TEMP3.length; i++)
+ {
+ TEMP2[i] = TEMP3[TEMP3.length - (i + 1)];
+ }
+
+ // Decompose TEMP2 into IV, the first 8 octets, and TEMP1, the remaining
+ // octets.
+ this.iv = new byte[8];
+
+ byte[] TEMP1 = new byte[TEMP2.length - 8];
+
+ System.arraycopy(TEMP2, 0, this.iv, 0, 8);
+ System.arraycopy(TEMP2, 8, TEMP1, 0, TEMP2.length - 8);
+
+ // Decrypt TEMP1 using TRIPLedeS in CBC mode using the KEK and the IV
+ // found in the previous step. Call the result WKCKS.
+ this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
+
+ this.engine.init(false, this.paramPlusIV);
+
+ byte[] LCEKPADICV = new byte[TEMP1.length];
+
+ System.arraycopy(TEMP1, 0, LCEKPADICV, 0, TEMP1.length);
+
+ for (int i = 0; i < (LCEKPADICV.length / engine.getBlockSize()); i++)
+ {
+ int currentBytePos = i * engine.getBlockSize();
+
+ engine.processBlock(LCEKPADICV, currentBytePos, LCEKPADICV,
+ currentBytePos);
+ }
+
+ // Decompose LCEKPADICV. CKS is the last 8 octets and WK, the wrapped
+ // key, are
+ // those octets before the CKS.
+ byte[] result = new byte[LCEKPADICV.length - 8];
+ byte[] CKStoBeVerified = new byte[8];
+
+ System.arraycopy(LCEKPADICV, 0, result, 0, LCEKPADICV.length - 8);
+ System.arraycopy(LCEKPADICV, LCEKPADICV.length - 8, CKStoBeVerified, 0,
+ 8);
+
+ // Calculate a CMS Key Checksum, (section 5.6.1), over the WK and
+ // compare
+ // with the CKS extracted in the above step. If they are not equal,
+ // return error.
+ if (!checkCMSKeyChecksum(result, CKStoBeVerified))
+ {
+ throw new InvalidCipherTextException(
+ "Checksum inside ciphertext is corrupted");
+ }
+
+ if ((result.length - ((result[0] & 0xff) + 1)) > 7)
+ {
+ throw new InvalidCipherTextException("too many pad bytes ("
+ + (result.length - ((result[0] & 0xff) + 1)) + ")");
+ }
+
+ // CEK is the wrapped key, now extracted for use in data decryption.
+ byte[] CEK = new byte[result[0]];
+ System.arraycopy(result, 1, CEK, 0, CEK.length);
+ return CEK;
+ }
+
+ /**
+ * Some key wrap algorithms make use of the Key Checksum defined
+ * in CMS [CMS-Algorithms]. This is used to provide an integrity
+ * check value for the key being wrapped. The algorithm is
+ *
+ * - Compute the 20 octet SHA-1 hash on the key being wrapped.
+ * - Use the first 8 octets of this hash as the checksum value.
+ *
+ * @param key
+ * @return
+ * @throws RuntimeException
+ * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+ */
+ private byte[] calculateCMSKeyChecksum(
+ byte[] key)
+ {
+ byte[] result = new byte[8];
+
+ sha1.update(key, 0, key.length);
+ sha1.doFinal(digest, 0);
+
+ System.arraycopy(digest, 0, result, 0, 8);
+
+ return result;
+ }
+
+ /**
+ * @param key
+ * @param checksum
+ * @return
+ * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+ */
+ private boolean checkCMSKeyChecksum(
+ byte[] key,
+ byte[] checksum)
+ {
+ return Arrays.constantTimeAreEqual(calculateCMSKeyChecksum(key), checksum);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RC4Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RC4Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RC4Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RC4Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,143 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.StreamCipher;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+public class RC4Engine implements StreamCipher
+{
+ private final static int STATE_LENGTH = 256;
+
+ /*
+ * variables to hold the state of the RC4 engine
+ * during encryption and decryption
+ */
+
+ private byte[] engineState = null;
+ private int x = 0;
+ private int y = 0;
+ private byte[] workingKey = null;
+
+ /**
+ * initialise a RC4 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params
+ )
+ {
+ if (params instanceof KeyParameter)
+ {
+ /*
+ * RC4 encryption and decryption is completely
+ * symmetrical, so the 'forEncryption' is
+ * irrelevant.
+ */
+ workingKey = ((KeyParameter)params).getKey();
+ setKey(workingKey);
+
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to RC4 init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RC4";
+ }
+
+ public byte returnByte(byte in)
+ {
+ x = (x + 1) & 0xff;
+ y = (engineState[x] + y) & 0xff;
+
+ // swap
+ byte tmp = engineState[x];
+ engineState[x] = engineState[y];
+ engineState[y] = tmp;
+
+ // xor
+ return (byte)(in ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
+ }
+
+ public void processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ {
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len ; i++)
+ {
+ x = (x + 1) & 0xff;
+ y = (engineState[x] + y) & 0xff;
+
+ // swap
+ byte tmp = engineState[x];
+ engineState[x] = engineState[y];
+ engineState[y] = tmp;
+
+ // xor
+ out[i+outOff] = (byte)(in[i + inOff]
+ ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
+ }
+ }
+
+ public void reset()
+ {
+ setKey(workingKey);
+ }
+
+ // Private implementation
+
+ private void setKey(byte[] keyBytes)
+ {
+ workingKey = keyBytes;
+
+ // System.out.println("the key length is ; "+ workingKey.length);
+
+ x = 0;
+ y = 0;
+
+ if (engineState == null)
+ {
+ engineState = new byte[STATE_LENGTH];
+ }
+
+ // reset the state of the engine
+ for (int i=0; i < STATE_LENGTH; i++)
+ {
+ engineState[i] = (byte)i;
+ }
+
+ int i1 = 0;
+ int i2 = 0;
+
+ for (int i=0; i < STATE_LENGTH; i++)
+ {
+ i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff;
+ // do the byte-swap inline
+ byte tmp = engineState[i];
+ engineState[i] = engineState[i2];
+ engineState[i2] = tmp;
+ i1 = (i1+1) % keyBytes.length;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RC532Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RC532Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RC532Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RC532Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,287 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.RC5Parameters;
+
+/**
+ * The specification for RC5 came from the RC5 Encryption Algorithm
+ * publication in RSA CryptoBytes, Spring of 1995.
+ * http://www.rsasecurity.com/rsalabs/cryptobytes .
+ *
+ * This implementation has a word size of 32 bits.
+ *
+ * Implementation courtesy of Tito Pena.
+ */
+public class RC532Engine
+ implements BlockCipher
+{
+ /*
+ * the number of rounds to perform
+ */
+ private int _noRounds;
+
+ /*
+ * the expanded key array of size 2*(rounds + 1)
+ */
+ private int _S[];
+
+ /*
+ * our "magic constants" for 32 32
+ *
+ * Pw = Odd((e-2) * 2^wordsize)
+ * Qw = Odd((o-2) * 2^wordsize)
+ *
+ * where e is the base of natural logarithms (2.718281828...)
+ * and o is the golden ratio (1.61803398...)
+ */
+ private static final int P32 = 0xb7e15163;
+ private static final int Q32 = 0x9e3779b9;
+
+ private boolean forEncryption;
+
+ /**
+ * Create an instance of the RC5 encryption algorithm
+ * and set some defaults
+ */
+ public RC532Engine()
+ {
+ _noRounds = 12; // the default
+ _S = null;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RC5-32";
+ }
+
+ public int getBlockSize()
+ {
+ return 2 * 4;
+ }
+
+ /**
+ * initialise a RC5-32 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof RC5Parameters)
+ {
+ RC5Parameters p = (RC5Parameters)params;
+
+ _noRounds = p.getRounds();
+
+ setKey(p.getKey());
+ }
+ else if (params instanceof KeyParameter)
+ {
+ KeyParameter p = (KeyParameter)params;
+
+ setKey(p.getKey());
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameter passed to RC532 init - " + params.getClass().getName());
+ }
+
+ this.forEncryption = forEncryption;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ return (forEncryption) ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ *
+ * @param key the key to be used
+ */
+ private void setKey(
+ byte[] key)
+ {
+ //
+ // KEY EXPANSION:
+ //
+ // There are 3 phases to the key expansion.
+ //
+ // Phase 1:
+ // Copy the secret key K[0...b-1] into an array L[0..c-1] of
+ // c = ceil(b/u), where u = 32/8 in little-endian order.
+ // In other words, we fill up L using u consecutive key bytes
+ // of K. Any unfilled byte positions in L are zeroed. In the
+ // case that b = c = 0, set c = 1 and L[0] = 0.
+ //
+ int[] L = new int[(key.length + (4 - 1)) / 4];
+
+ for (int i = 0; i != key.length; i++)
+ {
+ L[i / 4] += (key[i] & 0xff) << (8 * (i % 4));
+ }
+
+ //
+ // Phase 2:
+ // Initialize S to a particular fixed pseudo-random bit pattern
+ // using an arithmetic progression modulo 2^wordsize determined
+ // by the magic numbers, Pw & Qw.
+ //
+ _S = new int[2*(_noRounds + 1)];
+
+ _S[0] = P32;
+ for (int i=1; i < _S.length; i++)
+ {
+ _S[i] = (_S[i-1] + Q32);
+ }
+
+ //
+ // Phase 3:
+ // Mix in the user's secret key in 3 passes over the arrays S & L.
+ // The max of the arrays sizes is used as the loop control
+ //
+ int iter;
+
+ if (L.length > _S.length)
+ {
+ iter = 3 * L.length;
+ }
+ else
+ {
+ iter = 3 * _S.length;
+ }
+
+ int A = 0, B = 0;
+ int i = 0, j = 0;
+
+ for (int k = 0; k < iter; k++)
+ {
+ A = _S[i] = rotateLeft(_S[i] + A + B, 3);
+ B = L[j] = rotateLeft(L[j] + A + B, A+B);
+ i = (i+1) % _S.length;
+ j = (j+1) % L.length;
+ }
+ }
+
+ /**
+ * Encrypt the given block starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ *
+ * @param in in byte buffer containing data to encrypt
+ * @param inOff offset into src buffer
+ * @param out out buffer where encrypted data is written
+ * @param outOff offset into out buffer
+ */
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int A = bytesToWord(in, inOff) + _S[0];
+ int B = bytesToWord(in, inOff + 4) + _S[1];
+
+ for (int i = 1; i <= _noRounds; i++)
+ {
+ A = rotateLeft(A ^ B, B) + _S[2*i];
+ B = rotateLeft(B ^ A, A) + _S[2*i+1];
+ }
+
+ wordToBytes(A, out, outOff);
+ wordToBytes(B, out, outOff + 4);
+
+ return 2 * 4;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int A = bytesToWord(in, inOff);
+ int B = bytesToWord(in, inOff + 4);
+
+ for (int i = _noRounds; i >= 1; i--)
+ {
+ B = rotateRight(B - _S[2*i+1], A) ^ A;
+ A = rotateRight(A - _S[2*i], B) ^ B;
+ }
+
+ wordToBytes(A - _S[0], out, outOff);
+ wordToBytes(B - _S[1], out, outOff + 4);
+
+ return 2 * 4;
+ }
+
+
+ //////////////////////////////////////////////////////////////
+ //
+ // PRIVATE Helper Methods
+ //
+ //////////////////////////////////////////////////////////////
+
+ /**
+ * Perform a left "spin" of the word. The rotation of the given
+ * word x is rotated left by y bits.
+ * Only the lg(32) low-order bits of y
+ * are used to determine the rotation amount. Here it is
+ * assumed that the wordsize used is a power of 2.
+ *
+ * @param x word to rotate
+ * @param y number of bits to rotate % 32
+ */
+ private int rotateLeft(int x, int y)
+ {
+ return ((x << (y & (32-1))) | (x >>> (32 - (y & (32-1)))));
+ }
+
+ /**
+ * Perform a right "spin" of the word. The rotation of the given
+ * word x is rotated left by y bits.
+ * Only the lg(32) low-order bits of y
+ * are used to determine the rotation amount. Here it is
+ * assumed that the wordsize used is a power of 2.
+ *
+ * @param x word to rotate
+ * @param y number of bits to rotate % 32
+ */
+ private int rotateRight(int x, int y)
+ {
+ return ((x >>> (y & (32-1))) | (x << (32 - (y & (32-1)))));
+ }
+
+ private int bytesToWord(
+ byte[] src,
+ int srcOff)
+ {
+ return (src[srcOff] & 0xff) | ((src[srcOff + 1] & 0xff) << 8)
+ | ((src[srcOff + 2] & 0xff) << 16) | ((src[srcOff + 3] & 0xff) << 24);
+ }
+
+ private void wordToBytes(
+ int word,
+ byte[] dst,
+ int dstOff)
+ {
+ dst[dstOff] = (byte)word;
+ dst[dstOff + 1] = (byte)(word >> 8);
+ dst[dstOff + 2] = (byte)(word >> 16);
+ dst[dstOff + 3] = (byte)(word >> 24);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RC564Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RC564Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RC564Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RC564Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,288 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.params.RC5Parameters;
+
+/**
+ * The specification for RC5 came from the RC5 Encryption Algorithm
+ * publication in RSA CryptoBytes, Spring of 1995.
+ * http://www.rsasecurity.com/rsalabs/cryptobytes .
+ *
+ * This implementation is set to work with a 64 bit word size.
+ *
+ * Implementation courtesy of Tito Pena.
+ */
+public class RC564Engine
+ implements BlockCipher
+{
+ private static final int wordSize = 64;
+ private static final int bytesPerWord = wordSize / 8;
+
+ /*
+ * the number of rounds to perform
+ */
+ private int _noRounds;
+
+ /*
+ * the expanded key array of size 2*(rounds + 1)
+ */
+ private long _S[];
+
+ /*
+ * our "magic constants" for wordSize 62
+ *
+ * Pw = Odd((e-2) * 2^wordsize)
+ * Qw = Odd((o-2) * 2^wordsize)
+ *
+ * where e is the base of natural logarithms (2.718281828...)
+ * and o is the golden ratio (1.61803398...)
+ */
+ private static final long P64 = 0xb7e151628aed2a6bL;
+ private static final long Q64 = 0x9e3779b97f4a7c15L;
+
+ private boolean forEncryption;
+
+ /**
+ * Create an instance of the RC5 encryption algorithm
+ * and set some defaults
+ */
+ public RC564Engine()
+ {
+ _noRounds = 12;
+ _S = null;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RC5-64";
+ }
+
+ public int getBlockSize()
+ {
+ return 2 * bytesPerWord;
+ }
+
+ /**
+ * initialise a RC5-64 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof RC5Parameters))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to RC564 init - " + params.getClass().getName());
+ }
+
+ RC5Parameters p = (RC5Parameters)params;
+
+ this.forEncryption = forEncryption;
+
+ _noRounds = p.getRounds();
+
+ setKey(p.getKey());
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ return (forEncryption) ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ *
+ * @param key the key to be used
+ */
+ private void setKey(
+ byte[] key)
+ {
+ //
+ // KEY EXPANSION:
+ //
+ // There are 3 phases to the key expansion.
+ //
+ // Phase 1:
+ // Copy the secret key K[0...b-1] into an array L[0..c-1] of
+ // c = ceil(b/u), where u = wordSize/8 in little-endian order.
+ // In other words, we fill up L using u consecutive key bytes
+ // of K. Any unfilled byte positions in L are zeroed. In the
+ // case that b = c = 0, set c = 1 and L[0] = 0.
+ //
+ long[] L = new long[(key.length + (bytesPerWord - 1)) / bytesPerWord];
+
+ for (int i = 0; i != key.length; i++)
+ {
+ L[i / bytesPerWord] += (long)(key[i] & 0xff) << (8 * (i % bytesPerWord));
+ }
+
+ //
+ // Phase 2:
+ // Initialize S to a particular fixed pseudo-random bit pattern
+ // using an arithmetic progression modulo 2^wordsize determined
+ // by the magic numbers, Pw & Qw.
+ //
+ _S = new long[2*(_noRounds + 1)];
+
+ _S[0] = P64;
+ for (int i=1; i < _S.length; i++)
+ {
+ _S[i] = (_S[i-1] + Q64);
+ }
+
+ //
+ // Phase 3:
+ // Mix in the user's secret key in 3 passes over the arrays S & L.
+ // The max of the arrays sizes is used as the loop control
+ //
+ int iter;
+
+ if (L.length > _S.length)
+ {
+ iter = 3 * L.length;
+ }
+ else
+ {
+ iter = 3 * _S.length;
+ }
+
+ long A = 0, B = 0;
+ int i = 0, j = 0;
+
+ for (int k = 0; k < iter; k++)
+ {
+ A = _S[i] = rotateLeft(_S[i] + A + B, 3);
+ B = L[j] = rotateLeft(L[j] + A + B, A+B);
+ i = (i+1) % _S.length;
+ j = (j+1) % L.length;
+ }
+ }
+
+ /**
+ * Encrypt the given block starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ *
+ * @param in in byte buffer containing data to encrypt
+ * @param inOff offset into src buffer
+ * @param out out buffer where encrypted data is written
+ * @param outOff offset into out buffer
+ */
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ long A = bytesToWord(in, inOff) + _S[0];
+ long B = bytesToWord(in, inOff + bytesPerWord) + _S[1];
+
+ for (int i = 1; i <= _noRounds; i++)
+ {
+ A = rotateLeft(A ^ B, B) + _S[2*i];
+ B = rotateLeft(B ^ A, A) + _S[2*i+1];
+ }
+
+ wordToBytes(A, out, outOff);
+ wordToBytes(B, out, outOff + bytesPerWord);
+
+ return 2 * bytesPerWord;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ long A = bytesToWord(in, inOff);
+ long B = bytesToWord(in, inOff + bytesPerWord);
+
+ for (int i = _noRounds; i >= 1; i--)
+ {
+ B = rotateRight(B - _S[2*i+1], A) ^ A;
+ A = rotateRight(A - _S[2*i], B) ^ B;
+ }
+
+ wordToBytes(A - _S[0], out, outOff);
+ wordToBytes(B - _S[1], out, outOff + bytesPerWord);
+
+ return 2 * bytesPerWord;
+ }
+
+
+ //////////////////////////////////////////////////////////////
+ //
+ // PRIVATE Helper Methods
+ //
+ //////////////////////////////////////////////////////////////
+
+ /**
+ * Perform a left "spin" of the word. The rotation of the given
+ * word x is rotated left by y bits.
+ * Only the lg(wordSize) low-order bits of y
+ * are used to determine the rotation amount. Here it is
+ * assumed that the wordsize used is a power of 2.
+ *
+ * @param x word to rotate
+ * @param y number of bits to rotate % wordSize
+ */
+ private long rotateLeft(long x, long y)
+ {
+ return ((x << (y & (wordSize-1))) | (x >>> (wordSize - (y & (wordSize-1)))));
+ }
+
+ /**
+ * Perform a right "spin" of the word. The rotation of the given
+ * word x is rotated left by y bits.
+ * Only the lg(wordSize) low-order bits of y
+ * are used to determine the rotation amount. Here it is
+ * assumed that the wordsize used is a power of 2.
+ *
+ * @param x word to rotate
+ * @param y number of bits to rotate % wordSize
+ */
+ private long rotateRight(long x, long y)
+ {
+ return ((x >>> (y & (wordSize-1))) | (x << (wordSize - (y & (wordSize-1)))));
+ }
+
+ private long bytesToWord(
+ byte[] src,
+ int srcOff)
+ {
+ long word = 0;
+
+ for (int i = bytesPerWord - 1; i >= 0; i--)
+ {
+ word = (word << 8) + (src[i + srcOff] & 0xff);
+ }
+
+ return word;
+ }
+
+ private void wordToBytes(
+ long word,
+ byte[] dst,
+ int dstOff)
+ {
+ for (int i = 0; i < bytesPerWord; i++)
+ {
+ dst[i + dstOff] = (byte)word;
+ word >>>= 8;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RC6Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RC6Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RC6Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RC6Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,362 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * An RC6 engine.
+ */
+public class RC6Engine
+ implements BlockCipher
+{
+ private static final int wordSize = 32;
+ private static final int bytesPerWord = wordSize / 8;
+
+ /*
+ * the number of rounds to perform
+ */
+ private static final int _noRounds = 20;
+
+ /*
+ * the expanded key array of size 2*(rounds + 1)
+ */
+ private int _S[];
+
+ /*
+ * our "magic constants" for wordSize 32
+ *
+ * Pw = Odd((e-2) * 2^wordsize)
+ * Qw = Odd((o-2) * 2^wordsize)
+ *
+ * where e is the base of natural logarithms (2.718281828...)
+ * and o is the golden ratio (1.61803398...)
+ */
+ private static final int P32 = 0xb7e15163;
+ private static final int Q32 = 0x9e3779b9;
+
+ private static final int LGW = 5; // log2(32)
+
+ private boolean forEncryption;
+
+ /**
+ * Create an instance of the RC6 encryption algorithm
+ * and set some defaults
+ */
+ public RC6Engine()
+ {
+ _S = null;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "RC6";
+ }
+
+ public int getBlockSize()
+ {
+ return 4 * bytesPerWord;
+ }
+
+ /**
+ * initialise a RC5-32 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to RC6 init - " + params.getClass().getName());
+ }
+
+ KeyParameter p = (KeyParameter)params;
+ this.forEncryption = forEncryption;
+ setKey(p.getKey());
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int blockSize = getBlockSize();
+ if (_S == null)
+ {
+ throw new IllegalStateException("RC6 engine not initialised");
+ }
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ return (forEncryption)
+ ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ *
+ * @param inKey the key to be used
+ */
+ private void setKey(
+ byte[] key)
+ {
+
+ //
+ // KEY EXPANSION:
+ //
+ // There are 3 phases to the key expansion.
+ //
+ // Phase 1:
+ // Copy the secret key K[0...b-1] into an array L[0..c-1] of
+ // c = ceil(b/u), where u = wordSize/8 in little-endian order.
+ // In other words, we fill up L using u consecutive key bytes
+ // of K. Any unfilled byte positions in L are zeroed. In the
+ // case that b = c = 0, set c = 1 and L[0] = 0.
+ //
+ // compute number of dwords
+ int c = (key.length + (bytesPerWord - 1)) / bytesPerWord;
+ if (c == 0)
+ {
+ c = 1;
+ }
+ int[] L = new int[(key.length + bytesPerWord - 1) / bytesPerWord];
+
+ // load all key bytes into array of key dwords
+ for (int i = key.length - 1; i >= 0; i--)
+ {
+ L[i / bytesPerWord] = (L[i / bytesPerWord] << 8) + (key[i] & 0xff);
+ }
+
+ //
+ // Phase 2:
+ // Key schedule is placed in a array of 2+2*ROUNDS+2 = 44 dwords.
+ // Initialize S to a particular fixed pseudo-random bit pattern
+ // using an arithmetic progression modulo 2^wordsize determined
+ // by the magic numbers, Pw & Qw.
+ //
+ _S = new int[2+2*_noRounds+2];
+
+ _S[0] = P32;
+ for (int i=1; i < _S.length; i++)
+ {
+ _S[i] = (_S[i-1] + Q32);
+ }
+
+ //
+ // Phase 3:
+ // Mix in the user's secret key in 3 passes over the arrays S & L.
+ // The max of the arrays sizes is used as the loop control
+ //
+ int iter;
+
+ if (L.length > _S.length)
+ {
+ iter = 3 * L.length;
+ }
+ else
+ {
+ iter = 3 * _S.length;
+ }
+
+ int A = 0;
+ int B = 0;
+ int i = 0, j = 0;
+
+ for (int k = 0; k < iter; k++)
+ {
+ A = _S[i] = rotateLeft(_S[i] + A + B, 3);
+ B = L[j] = rotateLeft(L[j] + A + B, A+B);
+ i = (i+1) % _S.length;
+ j = (j+1) % L.length;
+ }
+ }
+
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // load A,B,C and D registers from in.
+ int A = bytesToWord(in, inOff);
+ int B = bytesToWord(in, inOff + bytesPerWord);
+ int C = bytesToWord(in, inOff + bytesPerWord*2);
+ int D = bytesToWord(in, inOff + bytesPerWord*3);
+
+ // Do pseudo-round #0: pre-whitening of B and D
+ B += _S[0];
+ D += _S[1];
+
+ // perform round #1,#2 ... #ROUNDS of encryption
+ for (int i = 1; i <= _noRounds; i++)
+ {
+ int t = 0,u = 0;
+
+ t = B*(2*B+1);
+ t = rotateLeft(t,5);
+
+ u = D*(2*D+1);
+ u = rotateLeft(u,5);
+
+ A ^= t;
+ A = rotateLeft(A,u);
+ A += _S[2*i];
+
+ C ^= u;
+ C = rotateLeft(C,t);
+ C += _S[2*i+1];
+
+ int temp = A;
+ A = B;
+ B = C;
+ C = D;
+ D = temp;
+ }
+ // do pseudo-round #(ROUNDS+1) : post-whitening of A and C
+ A += _S[2*_noRounds+2];
+ C += _S[2*_noRounds+3];
+
+ // store A, B, C and D registers to out
+ wordToBytes(A, out, outOff);
+ wordToBytes(B, out, outOff + bytesPerWord);
+ wordToBytes(C, out, outOff + bytesPerWord*2);
+ wordToBytes(D, out, outOff + bytesPerWord*3);
+
+ return 4 * bytesPerWord;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // load A,B,C and D registers from out.
+ int A = bytesToWord(in, inOff);
+ int B = bytesToWord(in, inOff + bytesPerWord);
+ int C = bytesToWord(in, inOff + bytesPerWord*2);
+ int D = bytesToWord(in, inOff + bytesPerWord*3);
+
+ // Undo pseudo-round #(ROUNDS+1) : post whitening of A and C
+ C -= _S[2*_noRounds+3];
+ A -= _S[2*_noRounds+2];
+
+ // Undo round #ROUNDS, .., #2,#1 of encryption
+ for (int i = _noRounds; i >= 1; i--)
+ {
+ int t=0,u = 0;
+
+ int temp = D;
+ D = C;
+ C = B;
+ B = A;
+ A = temp;
+
+ t = B*(2*B+1);
+ t = rotateLeft(t, LGW);
+
+ u = D*(2*D+1);
+ u = rotateLeft(u, LGW);
+
+ C -= _S[2*i+1];
+ C = rotateRight(C,t);
+ C ^= u;
+
+ A -= _S[2*i];
+ A = rotateRight(A,u);
+ A ^= t;
+
+ }
+ // Undo pseudo-round #0: pre-whitening of B and D
+ D -= _S[1];
+ B -= _S[0];
+
+ wordToBytes(A, out, outOff);
+ wordToBytes(B, out, outOff + bytesPerWord);
+ wordToBytes(C, out, outOff + bytesPerWord*2);
+ wordToBytes(D, out, outOff + bytesPerWord*3);
+
+ return 4 * bytesPerWord;
+ }
+
+
+ //////////////////////////////////////////////////////////////
+ //
+ // PRIVATE Helper Methods
+ //
+ //////////////////////////////////////////////////////////////
+
+ /**
+ * Perform a left "spin" of the word. The rotation of the given
+ * word x is rotated left by y bits.
+ * Only the lg(wordSize) low-order bits of y
+ * are used to determine the rotation amount. Here it is
+ * assumed that the wordsize used is 32.
+ *
+ * @param x word to rotate
+ * @param y number of bits to rotate % wordSize
+ */
+ private int rotateLeft(int x, int y)
+ {
+ return (x << y) | (x >>> -y);
+ }
+
+ /**
+ * Perform a right "spin" of the word. The rotation of the given
+ * word x is rotated left by y bits.
+ * Only the lg(wordSize) low-order bits of y
+ * are used to determine the rotation amount. Here it is
+ * assumed that the wordsize used is a power of 2.
+ *
+ * @param x word to rotate
+ * @param y number of bits to rotate % wordSize
+ */
+ private int rotateRight(int x, int y)
+ {
+ return (x >>> y) | (x << -y);
+ }
+
+ private int bytesToWord(
+ byte[] src,
+ int srcOff)
+ {
+ int word = 0;
+
+ for (int i = bytesPerWord - 1; i >= 0; i--)
+ {
+ word = (word << 8) + (src[i + srcOff] & 0xff);
+ }
+
+ return word;
+ }
+
+ private void wordToBytes(
+ int word,
+ byte[] dst,
+ int dstOff)
+ {
+ for (int i = 0; i < bytesPerWord; i++)
+ {
+ dst[i + dstOff] = (byte)word;
+ word >>>= 8;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RFC3211WrapEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RFC3211WrapEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RFC3211WrapEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RFC3211WrapEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,175 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.Wrapper;
+import pdftk.org.bouncycastle.crypto.modes.CBCBlockCipher;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+
+import java.security.SecureRandom;
+
+/**
+ * an implementation of the RFC 3211 Key Wrap
+ * Specification.
+ */
+public class RFC3211WrapEngine
+ implements Wrapper
+{
+ private CBCBlockCipher engine;
+ private ParametersWithIV param;
+ private boolean forWrapping;
+ private SecureRandom rand;
+
+ public RFC3211WrapEngine(BlockCipher engine)
+ {
+ this.engine = new CBCBlockCipher(engine);
+ }
+
+ public void init(
+ boolean forWrapping,
+ CipherParameters param)
+ {
+ this.forWrapping = forWrapping;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)param;
+
+ rand = p.getRandom();
+ this.param = (ParametersWithIV)p.getParameters();
+ }
+ else
+ {
+ if (forWrapping)
+ {
+ rand = new SecureRandom();
+ }
+
+ this.param = (ParametersWithIV)param;
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return engine.getUnderlyingCipher().getAlgorithmName() + "/RFC3211Wrap";
+ }
+
+ public byte[] wrap(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ if (!forWrapping)
+ {
+ throw new IllegalStateException("not set for wrapping");
+ }
+
+ engine.init(true, param);
+
+ int blockSize = engine.getBlockSize();
+ byte[] cekBlock;
+
+ if (inLen + 4 < blockSize * 2)
+ {
+ cekBlock = new byte[blockSize * 2];
+ }
+ else
+ {
+ cekBlock = new byte[(inLen + 4) % blockSize == 0 ? inLen + 4 : ((inLen + 4) / blockSize + 1) * blockSize];
+ }
+
+ cekBlock[0] = (byte)inLen;
+ cekBlock[1] = (byte)~in[inOff];
+ cekBlock[2] = (byte)~in[inOff + 1];
+ cekBlock[3] = (byte)~in[inOff + 2];
+
+ System.arraycopy(in, inOff, cekBlock, 4, inLen);
+
+ for (int i = inLen + 4; i < cekBlock.length; i++)
+ {
+ cekBlock[i] = (byte)rand.nextInt();
+ }
+
+ for (int i = 0; i < cekBlock.length; i += blockSize)
+ {
+ engine.processBlock(cekBlock, i, cekBlock, i);
+ }
+
+ for (int i = 0; i < cekBlock.length; i += blockSize)
+ {
+ engine.processBlock(cekBlock, i, cekBlock, i);
+ }
+
+ return cekBlock;
+ }
+
+ public byte[] unwrap(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forWrapping)
+ {
+ throw new IllegalStateException("not set for unwrapping");
+ }
+
+ int blockSize = engine.getBlockSize();
+
+ if (inLen < 2 * blockSize)
+ {
+ throw new InvalidCipherTextException("input too short");
+ }
+
+ byte[] cekBlock = new byte[inLen];
+ byte[] iv = new byte[blockSize];
+
+ System.arraycopy(in, inOff, cekBlock, 0, inLen);
+ System.arraycopy(in, inOff, iv, 0, iv.length);
+
+ engine.init(false, new ParametersWithIV(param.getParameters(), iv));
+
+ for (int i = blockSize; i < cekBlock.length; i += blockSize)
+ {
+ engine.processBlock(cekBlock, i, cekBlock, i);
+ }
+
+ System.arraycopy(cekBlock, cekBlock.length - iv.length, iv, 0, iv.length);
+
+ engine.init(false, new ParametersWithIV(param.getParameters(), iv));
+
+ engine.processBlock(cekBlock, 0, cekBlock, 0);
+
+ engine.init(false, param);
+
+ for (int i = 0; i < cekBlock.length; i += blockSize)
+ {
+ engine.processBlock(cekBlock, i, cekBlock, i);
+ }
+
+ if ((cekBlock[0] & 0xff) > cekBlock.length - 4)
+ {
+ throw new InvalidCipherTextException("wrapped key corrupted");
+ }
+
+ byte[] key = new byte[cekBlock[0] & 0xff];
+
+ System.arraycopy(cekBlock, 4, key, 0, cekBlock[0]);
+
+ // Note: Using constant time comparison
+ int nonEqual = 0;
+ for (int i = 0; i != 3; i++)
+ {
+ byte check = (byte)~cekBlock[1 + i];
+ nonEqual |= (check ^ key[i]);
+ }
+ if (nonEqual != 0)
+ {
+ throw new InvalidCipherTextException("wrapped key fails checksum");
+ }
+
+ return key;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RFC3394WrapEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,177 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.Wrapper;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * an implementation of the AES Key Wrapper from the NIST Key Wrap
+ * Specification as described in RFC 3394.
+ *
+ * For further details see: http://www.ietf.org/rfc/rfc3394.txt
+ * and http://csrc.nist.gov/encryption/kms/key-wrap.pdf .
+ */
+public class RFC3394WrapEngine
+ implements Wrapper
+{
+ private BlockCipher engine;
+ private KeyParameter param;
+ private boolean forWrapping;
+
+ private byte[] iv = {
+ (byte)0xa6, (byte)0xa6, (byte)0xa6, (byte)0xa6,
+ (byte)0xa6, (byte)0xa6, (byte)0xa6, (byte)0xa6 };
+
+ public RFC3394WrapEngine(BlockCipher engine)
+ {
+ this.engine = engine;
+ }
+
+ public void init(
+ boolean forWrapping,
+ CipherParameters param)
+ {
+ this.forWrapping = forWrapping;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ param = ((ParametersWithRandom) param).getParameters();
+ }
+
+ if (param instanceof KeyParameter)
+ {
+ this.param = (KeyParameter)param;
+ }
+ else if (param instanceof ParametersWithIV)
+ {
+ this.iv = ((ParametersWithIV)param).getIV();
+ this.param = (KeyParameter)((ParametersWithIV) param).getParameters();
+ if (this.iv.length != 8)
+ {
+ throw new IllegalArgumentException("IV not equal to 8");
+ }
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return engine.getAlgorithmName();
+ }
+
+ public byte[] wrap(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ if (!forWrapping)
+ {
+ throw new IllegalStateException("not set for wrapping");
+ }
+
+ int n = inLen / 8;
+
+ if ((n * 8) != inLen)
+ {
+ throw new DataLengthException("wrap data must be a multiple of 8 bytes");
+ }
+
+ byte[] block = new byte[inLen + iv.length];
+ byte[] buf = new byte[8 + iv.length];
+
+ System.arraycopy(iv, 0, block, 0, iv.length);
+ System.arraycopy(in, 0, block, iv.length, inLen);
+
+ engine.init(true, param);
+
+ for (int j = 0; j != 6; j++)
+ {
+ for (int i = 1; i <= n; i++)
+ {
+ System.arraycopy(block, 0, buf, 0, iv.length);
+ System.arraycopy(block, 8 * i, buf, iv.length, 8);
+ engine.processBlock(buf, 0, buf, 0);
+
+ int t = n * j + i;
+ for (int k = 1; t != 0; k++)
+ {
+ byte v = (byte)t;
+
+ buf[iv.length - k] ^= v;
+
+ t >>>= 8;
+ }
+
+ System.arraycopy(buf, 0, block, 0, 8);
+ System.arraycopy(buf, 8, block, 8 * i, 8);
+ }
+ }
+
+ return block;
+ }
+
+ public byte[] unwrap(
+ byte[] in,
+ int inOff,
+ int inLen)
+ throws InvalidCipherTextException
+ {
+ if (forWrapping)
+ {
+ throw new IllegalStateException("not set for unwrapping");
+ }
+
+ int n = inLen / 8;
+
+ if ((n * 8) != inLen)
+ {
+ throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes");
+ }
+
+ byte[] block = new byte[inLen - iv.length];
+ byte[] a = new byte[iv.length];
+ byte[] buf = new byte[8 + iv.length];
+
+ System.arraycopy(in, 0, a, 0, iv.length);
+ System.arraycopy(in, iv.length, block, 0, inLen - iv.length);
+
+ engine.init(false, param);
+
+ n = n - 1;
+
+ for (int j = 5; j >= 0; j--)
+ {
+ for (int i = n; i >= 1; i--)
+ {
+ System.arraycopy(a, 0, buf, 0, iv.length);
+ System.arraycopy(block, 8 * (i - 1), buf, iv.length, 8);
+
+ int t = n * j + i;
+ for (int k = 1; t != 0; k++)
+ {
+ byte v = (byte)t;
+
+ buf[iv.length - k] ^= v;
+
+ t >>>= 8;
+ }
+
+ engine.processBlock(buf, 0, buf, 0);
+ System.arraycopy(buf, 0, a, 0, 8);
+ System.arraycopy(buf, 8, block, 8 * (i - 1), 8);
+ }
+ }
+
+ if (!Arrays.constantTimeAreEqual(a, iv))
+ {
+ throw new InvalidCipherTextException("checksum failed");
+ }
+
+ return block;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RSABlindedEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RSABlindedEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RSABlindedEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RSABlindedEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,126 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * this does your basic RSA algorithm with blinding
+ */
+public class RSABlindedEngine
+ implements AsymmetricBlockCipher
+{
+ private static BigInteger ONE = BigInteger.valueOf(1);
+
+ private RSACoreEngine core = new RSACoreEngine();
+ private RSAKeyParameters key;
+ private SecureRandom random;
+
+ /**
+ * initialise the RSA engine.
+ *
+ * @param forEncryption true if we are encrypting, false otherwise.
+ * @param param the necessary RSA key parameters.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ core.init(forEncryption, param);
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ key = (RSAKeyParameters)rParam.getParameters();
+ random = rParam.getRandom();
+ }
+ else
+ {
+ key = (RSAKeyParameters)param;
+ random = new SecureRandom();
+ }
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * encryption, and the same length as the key size on decryption.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize()
+ {
+ return core.getInputBlockSize();
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * decryption, and the same length as the key size on encryption.
+ *
+ * @return maximum size for an output block.
+ */
+ public int getOutputBlockSize()
+ {
+ return core.getOutputBlockSize();
+ }
+
+ /**
+ * Process a single block using the basic RSA algorithm.
+ *
+ * @param in the input array.
+ * @param inOff the offset into the input buffer where the data starts.
+ * @param inLen the length of the data to be processed.
+ * @return the result of the RSA process.
+ * @exception DataLengthException the input block is too large.
+ */
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ if (key == null)
+ {
+ throw new IllegalStateException("RSA engine not initialised");
+ }
+
+ BigInteger input = core.convertInput(in, inOff, inLen);
+
+ BigInteger result;
+ if (key instanceof RSAPrivateCrtKeyParameters)
+ {
+ RSAPrivateCrtKeyParameters k = (RSAPrivateCrtKeyParameters)key;
+
+ BigInteger e = k.getPublicExponent();
+ if (e != null) // can't do blinding without a public exponent
+ {
+ BigInteger m = k.getModulus();
+ BigInteger r = BigIntegers.createRandomInRange(ONE, m.subtract(ONE), random);
+
+ BigInteger blindedInput = r.modPow(e, m).multiply(input).mod(m);
+ BigInteger blindedResult = core.processBlock(blindedInput);
+
+ BigInteger rInv = r.modInverse(m);
+ result = blindedResult.multiply(rInv).mod(m);
+ }
+ else
+ {
+ result = core.processBlock(input);
+ }
+ }
+ else
+ {
+ result = core.processBlock(input);
+ }
+
+ return core.convertOutput(result);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RSABlindingEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RSABlindingEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RSABlindingEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RSABlindingEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,137 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.crypto.params.RSABlindingParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+
+import java.math.BigInteger;
+
+/**
+ * This does your basic RSA Chaum's blinding and unblinding as outlined in
+ * "Handbook of Applied Cryptography", page 475. You need to use this if you are
+ * trying to get another party to generate signatures without them being aware
+ * of the message they are signing.
+ */
+public class RSABlindingEngine
+ implements AsymmetricBlockCipher
+{
+ private RSACoreEngine core = new RSACoreEngine();
+
+ private RSAKeyParameters key;
+ private BigInteger blindingFactor;
+
+ private boolean forEncryption;
+
+ /**
+ * Initialise the blinding engine.
+ *
+ * @param forEncryption true if we are encrypting (blinding), false otherwise.
+ * @param param the necessary RSA key parameters.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ RSABlindingParameters p;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ p = (RSABlindingParameters)rParam.getParameters();
+ }
+ else
+ {
+ p = (RSABlindingParameters)param;
+ }
+
+ core.init(forEncryption, p.getPublicKey());
+
+ this.forEncryption = forEncryption;
+ this.key = p.getPublicKey();
+ this.blindingFactor = p.getBlindingFactor();
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * encryption, and the same length as the key size on decryption.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize()
+ {
+ return core.getInputBlockSize();
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * decryption, and the same length as the key size on encryption.
+ *
+ * @return maximum size for an output block.
+ */
+ public int getOutputBlockSize()
+ {
+ return core.getOutputBlockSize();
+ }
+
+ /**
+ * Process a single block using the RSA blinding algorithm.
+ *
+ * @param in the input array.
+ * @param inOff the offset into the input buffer where the data starts.
+ * @param inLen the length of the data to be processed.
+ * @return the result of the RSA process.
+ * @throws DataLengthException the input block is too large.
+ */
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ BigInteger msg = core.convertInput(in, inOff, inLen);
+
+ if (forEncryption)
+ {
+ msg = blindMessage(msg);
+ }
+ else
+ {
+ msg = unblindMessage(msg);
+ }
+
+ return core.convertOutput(msg);
+ }
+
+ /*
+ * Blind message with the blind factor.
+ */
+ private BigInteger blindMessage(
+ BigInteger msg)
+ {
+ BigInteger blindMsg = blindingFactor;
+ blindMsg = msg.multiply(blindMsg.modPow(key.getExponent(), key.getModulus()));
+ blindMsg = blindMsg.mod(key.getModulus());
+
+ return blindMsg;
+ }
+
+ /*
+ * Unblind the message blinded with the blind factor.
+ */
+ private BigInteger unblindMessage(
+ BigInteger blindedMsg)
+ {
+ BigInteger m = key.getModulus();
+ BigInteger msg = blindedMsg;
+ BigInteger blindFactorInverse = blindingFactor.modInverse(m);
+ msg = msg.multiply(blindFactorInverse);
+ msg = msg.mod(m);
+
+ return msg;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RSACoreEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RSACoreEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RSACoreEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RSACoreEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,203 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+
+import java.math.BigInteger;
+
+/**
+ * this does your basic RSA algorithm.
+ */
+class RSACoreEngine
+{
+ private RSAKeyParameters key;
+ private boolean forEncryption;
+
+ /**
+ * initialise the RSA engine.
+ *
+ * @param forEncryption true if we are encrypting, false otherwise.
+ * @param param the necessary RSA key parameters.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ key = (RSAKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ key = (RSAKeyParameters)param;
+ }
+
+ this.forEncryption = forEncryption;
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * encryption, and the same length as the key size on decryption.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize()
+ {
+ int bitSize = key.getModulus().bitLength();
+
+ if (forEncryption)
+ {
+ return (bitSize + 7) / 8 - 1;
+ }
+ else
+ {
+ return (bitSize + 7) / 8;
+ }
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * decryption, and the same length as the key size on encryption.
+ *
+ * @return maximum size for an output block.
+ */
+ public int getOutputBlockSize()
+ {
+ int bitSize = key.getModulus().bitLength();
+
+ if (forEncryption)
+ {
+ return (bitSize + 7) / 8;
+ }
+ else
+ {
+ return (bitSize + 7) / 8 - 1;
+ }
+ }
+
+ public BigInteger convertInput(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ if (inLen > (getInputBlockSize() + 1))
+ {
+ throw new DataLengthException("input too large for RSA cipher.");
+ }
+ else if (inLen == (getInputBlockSize() + 1) && !forEncryption)
+ {
+ throw new DataLengthException("input too large for RSA cipher.");
+ }
+
+ byte[] block;
+
+ if (inOff != 0 || inLen != in.length)
+ {
+ block = new byte[inLen];
+
+ System.arraycopy(in, inOff, block, 0, inLen);
+ }
+ else
+ {
+ block = in;
+ }
+
+ BigInteger res = new BigInteger(1, block);
+ if (res.compareTo(key.getModulus()) >= 0)
+ {
+ throw new DataLengthException("input too large for RSA cipher.");
+ }
+
+ return res;
+ }
+
+ public byte[] convertOutput(
+ BigInteger result)
+ {
+ byte[] output = result.toByteArray();
+
+ if (forEncryption)
+ {
+ if (output[0] == 0 && output.length > getOutputBlockSize()) // have ended up with an extra zero byte, copy down.
+ {
+ byte[] tmp = new byte[output.length - 1];
+
+ System.arraycopy(output, 1, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ if (output.length < getOutputBlockSize()) // have ended up with less bytes than normal, lengthen
+ {
+ byte[] tmp = new byte[getOutputBlockSize()];
+
+ System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length);
+
+ return tmp;
+ }
+ }
+ else
+ {
+ if (output[0] == 0) // have ended up with an extra zero byte, copy down.
+ {
+ byte[] tmp = new byte[output.length - 1];
+
+ System.arraycopy(output, 1, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+ }
+
+ return output;
+ }
+
+ public BigInteger processBlock(BigInteger input)
+ {
+ if (key instanceof RSAPrivateCrtKeyParameters)
+ {
+ //
+ // we have the extra factors, use the Chinese Remainder Theorem - the author
+ // wishes to express his thanks to Dirk Bonekaemper at rtsffm.com for
+ // advice regarding the expression of this.
+ //
+ RSAPrivateCrtKeyParameters crtKey = (RSAPrivateCrtKeyParameters)key;
+
+ BigInteger p = crtKey.getP();
+ BigInteger q = crtKey.getQ();
+ BigInteger dP = crtKey.getDP();
+ BigInteger dQ = crtKey.getDQ();
+ BigInteger qInv = crtKey.getQInv();
+
+ BigInteger mP, mQ, h, m;
+
+ // mP = ((input mod p) ^ dP)) mod p
+ mP = (input.remainder(p)).modPow(dP, p);
+
+ // mQ = ((input mod q) ^ dQ)) mod q
+ mQ = (input.remainder(q)).modPow(dQ, q);
+
+ // h = qInv * (mP - mQ) mod p
+ h = mP.subtract(mQ);
+ h = h.multiply(qInv);
+ h = h.mod(p); // mod (in Java) returns the positive residual
+
+ // m = h * q + mQ
+ m = h.multiply(q);
+ m = m.add(mQ);
+
+ return m;
+ }
+ else
+ {
+ return input.modPow(
+ key.getExponent(), key.getModulus());
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RSAEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RSAEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RSAEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RSAEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,78 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+
+/**
+ * this does your basic RSA algorithm.
+ */
+public class RSAEngine
+ implements AsymmetricBlockCipher
+{
+ private RSACoreEngine core;
+
+ /**
+ * initialise the RSA engine.
+ *
+ * @param forEncryption true if we are encrypting, false otherwise.
+ * @param param the necessary RSA key parameters.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters param)
+ {
+ if (core == null)
+ {
+ core = new RSACoreEngine();
+ }
+
+ core.init(forEncryption, param);
+ }
+
+ /**
+ * Return the maximum size for an input block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * encryption, and the same length as the key size on decryption.
+ *
+ * @return maximum size for an input block.
+ */
+ public int getInputBlockSize()
+ {
+ return core.getInputBlockSize();
+ }
+
+ /**
+ * Return the maximum size for an output block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * decryption, and the same length as the key size on encryption.
+ *
+ * @return maximum size for an output block.
+ */
+ public int getOutputBlockSize()
+ {
+ return core.getOutputBlockSize();
+ }
+
+ /**
+ * Process a single block using the basic RSA algorithm.
+ *
+ * @param in the input array.
+ * @param inOff the offset into the input buffer where the data starts.
+ * @param inLen the length of the data to be processed.
+ * @return the result of the RSA process.
+ * @exception DataLengthException the input block is too large.
+ */
+ public byte[] processBlock(
+ byte[] in,
+ int inOff,
+ int inLen)
+ {
+ if (core == null)
+ {
+ throw new IllegalStateException("RSA engine not initialised");
+ }
+
+ return core.convertOutput(core.processBlock(core.convertInput(in, inOff, inLen)));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RijndaelEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RijndaelEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/RijndaelEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/RijndaelEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,724 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * an implementation of Rijndael, based on the documentation and reference implementation
+ * by Paulo Barreto, Vincent Rijmen, for v2.0 August '99.
+ *
+ * Note: this implementation is based on information prior to final NIST publication.
+ */
+public class RijndaelEngine
+ implements BlockCipher
+{
+ private static final int MAXROUNDS = 14;
+
+ private static final int MAXKC = (256/4);
+
+ private static final byte[] logtable = {
+ (byte)0, (byte)0, (byte)25, (byte)1, (byte)50, (byte)2, (byte)26, (byte)198,
+ (byte)75, (byte)199, (byte)27, (byte)104, (byte)51, (byte)238, (byte)223, (byte)3,
+ (byte)100, (byte)4, (byte)224, (byte)14, (byte)52, (byte)141, (byte)129, (byte)239,
+ (byte)76, (byte)113, (byte)8, (byte)200, (byte)248, (byte)105, (byte)28, (byte)193,
+ (byte)125, (byte)194, (byte)29, (byte)181, (byte)249, (byte)185, (byte)39, (byte)106,
+ (byte)77, (byte)228, (byte)166, (byte)114, (byte)154, (byte)201, (byte)9, (byte)120,
+ (byte)101, (byte)47, (byte)138, (byte)5, (byte)33, (byte)15, (byte)225, (byte)36,
+ (byte)18, (byte)240, (byte)130, (byte)69, (byte)53, (byte)147, (byte)218, (byte)142,
+ (byte)150, (byte)143, (byte)219, (byte)189, (byte)54, (byte)208, (byte)206, (byte)148,
+ (byte)19, (byte)92, (byte)210, (byte)241, (byte)64, (byte)70, (byte)131, (byte)56,
+ (byte)102, (byte)221, (byte)253, (byte)48, (byte)191, (byte)6, (byte)139, (byte)98,
+ (byte)179, (byte)37, (byte)226, (byte)152, (byte)34, (byte)136, (byte)145, (byte)16,
+ (byte)126, (byte)110, (byte)72, (byte)195, (byte)163, (byte)182, (byte)30, (byte)66,
+ (byte)58, (byte)107, (byte)40, (byte)84, (byte)250, (byte)133, (byte)61, (byte)186,
+ (byte)43, (byte)121, (byte)10, (byte)21, (byte)155, (byte)159, (byte)94, (byte)202,
+ (byte)78, (byte)212, (byte)172, (byte)229, (byte)243, (byte)115, (byte)167, (byte)87,
+ (byte)175, (byte)88, (byte)168, (byte)80, (byte)244, (byte)234, (byte)214, (byte)116,
+ (byte)79, (byte)174, (byte)233, (byte)213, (byte)231, (byte)230, (byte)173, (byte)232,
+ (byte)44, (byte)215, (byte)117, (byte)122, (byte)235, (byte)22, (byte)11, (byte)245,
+ (byte)89, (byte)203, (byte)95, (byte)176, (byte)156, (byte)169, (byte)81, (byte)160,
+ (byte)127, (byte)12, (byte)246, (byte)111, (byte)23, (byte)196, (byte)73, (byte)236,
+ (byte)216, (byte)67, (byte)31, (byte)45, (byte)164, (byte)118, (byte)123, (byte)183,
+ (byte)204, (byte)187, (byte)62, (byte)90, (byte)251, (byte)96, (byte)177, (byte)134,
+ (byte)59, (byte)82, (byte)161, (byte)108, (byte)170, (byte)85, (byte)41, (byte)157,
+ (byte)151, (byte)178, (byte)135, (byte)144, (byte)97, (byte)190, (byte)220, (byte)252,
+ (byte)188, (byte)149, (byte)207, (byte)205, (byte)55, (byte)63, (byte)91, (byte)209,
+ (byte)83, (byte)57, (byte)132, (byte)60, (byte)65, (byte)162, (byte)109, (byte)71,
+ (byte)20, (byte)42, (byte)158, (byte)93, (byte)86, (byte)242, (byte)211, (byte)171,
+ (byte)68, (byte)17, (byte)146, (byte)217, (byte)35, (byte)32, (byte)46, (byte)137,
+ (byte)180, (byte)124, (byte)184, (byte)38, (byte)119, (byte)153, (byte)227, (byte)165,
+ (byte)103, (byte)74, (byte)237, (byte)222, (byte)197, (byte)49, (byte)254, (byte)24,
+ (byte)13, (byte)99, (byte)140, (byte)128, (byte)192, (byte)247, (byte)112, (byte)7
+ };
+
+ private static final byte[] aLogtable = {
+ (byte)0, (byte)3, (byte)5, (byte)15, (byte)17, (byte)51, (byte)85, (byte)255, (byte)26, (byte)46, (byte)114, (byte)150, (byte)161, (byte)248, (byte)19, (byte)53,
+ (byte)95, (byte)225, (byte)56, (byte)72, (byte)216, (byte)115, (byte)149, (byte)164, (byte)247, (byte)2, (byte)6, (byte)10, (byte)30, (byte)34, (byte)102, (byte)170,
+ (byte)229, (byte)52, (byte)92, (byte)228, (byte)55, (byte)89, (byte)235, (byte)38, (byte)106, (byte)190, (byte)217, (byte)112, (byte)144, (byte)171, (byte)230, (byte)49,
+ (byte)83, (byte)245, (byte)4, (byte)12, (byte)20, (byte)60, (byte)68, (byte)204, (byte)79, (byte)209, (byte)104, (byte)184, (byte)211, (byte)110, (byte)178, (byte)205,
+ (byte)76, (byte)212, (byte)103, (byte)169, (byte)224, (byte)59, (byte)77, (byte)215, (byte)98, (byte)166, (byte)241, (byte)8, (byte)24, (byte)40, (byte)120, (byte)136,
+ (byte)131, (byte)158, (byte)185, (byte)208, (byte)107, (byte)189, (byte)220, (byte)127, (byte)129, (byte)152, (byte)179, (byte)206, (byte)73, (byte)219, (byte)118, (byte)154,
+ (byte)181, (byte)196, (byte)87, (byte)249, (byte)16, (byte)48, (byte)80, (byte)240, (byte)11, (byte)29, (byte)39, (byte)105, (byte)187, (byte)214, (byte)97, (byte)163,
+ (byte)254, (byte)25, (byte)43, (byte)125, (byte)135, (byte)146, (byte)173, (byte)236, (byte)47, (byte)113, (byte)147, (byte)174, (byte)233, (byte)32, (byte)96, (byte)160,
+ (byte)251, (byte)22, (byte)58, (byte)78, (byte)210, (byte)109, (byte)183, (byte)194, (byte)93, (byte)231, (byte)50, (byte)86, (byte)250, (byte)21, (byte)63, (byte)65,
+ (byte)195, (byte)94, (byte)226, (byte)61, (byte)71, (byte)201, (byte)64, (byte)192, (byte)91, (byte)237, (byte)44, (byte)116, (byte)156, (byte)191, (byte)218, (byte)117,
+ (byte)159, (byte)186, (byte)213, (byte)100, (byte)172, (byte)239, (byte)42, (byte)126, (byte)130, (byte)157, (byte)188, (byte)223, (byte)122, (byte)142, (byte)137, (byte)128,
+ (byte)155, (byte)182, (byte)193, (byte)88, (byte)232, (byte)35, (byte)101, (byte)175, (byte)234, (byte)37, (byte)111, (byte)177, (byte)200, (byte)67, (byte)197, (byte)84,
+ (byte)252, (byte)31, (byte)33, (byte)99, (byte)165, (byte)244, (byte)7, (byte)9, (byte)27, (byte)45, (byte)119, (byte)153, (byte)176, (byte)203, (byte)70, (byte)202,
+ (byte)69, (byte)207, (byte)74, (byte)222, (byte)121, (byte)139, (byte)134, (byte)145, (byte)168, (byte)227, (byte)62, (byte)66, (byte)198, (byte)81, (byte)243, (byte)14,
+ (byte)18, (byte)54, (byte)90, (byte)238, (byte)41, (byte)123, (byte)141, (byte)140, (byte)143, (byte)138, (byte)133, (byte)148, (byte)167, (byte)242, (byte)13, (byte)23,
+ (byte)57, (byte)75, (byte)221, (byte)124, (byte)132, (byte)151, (byte)162, (byte)253, (byte)28, (byte)36, (byte)108, (byte)180, (byte)199, (byte)82, (byte)246, (byte)1,
+ (byte)3, (byte)5, (byte)15, (byte)17, (byte)51, (byte)85, (byte)255, (byte)26, (byte)46, (byte)114, (byte)150, (byte)161, (byte)248, (byte)19, (byte)53,
+ (byte)95, (byte)225, (byte)56, (byte)72, (byte)216, (byte)115, (byte)149, (byte)164, (byte)247, (byte)2, (byte)6, (byte)10, (byte)30, (byte)34, (byte)102, (byte)170,
+ (byte)229, (byte)52, (byte)92, (byte)228, (byte)55, (byte)89, (byte)235, (byte)38, (byte)106, (byte)190, (byte)217, (byte)112, (byte)144, (byte)171, (byte)230, (byte)49,
+ (byte)83, (byte)245, (byte)4, (byte)12, (byte)20, (byte)60, (byte)68, (byte)204, (byte)79, (byte)209, (byte)104, (byte)184, (byte)211, (byte)110, (byte)178, (byte)205,
+ (byte)76, (byte)212, (byte)103, (byte)169, (byte)224, (byte)59, (byte)77, (byte)215, (byte)98, (byte)166, (byte)241, (byte)8, (byte)24, (byte)40, (byte)120, (byte)136,
+ (byte)131, (byte)158, (byte)185, (byte)208, (byte)107, (byte)189, (byte)220, (byte)127, (byte)129, (byte)152, (byte)179, (byte)206, (byte)73, (byte)219, (byte)118, (byte)154,
+ (byte)181, (byte)196, (byte)87, (byte)249, (byte)16, (byte)48, (byte)80, (byte)240, (byte)11, (byte)29, (byte)39, (byte)105, (byte)187, (byte)214, (byte)97, (byte)163,
+ (byte)254, (byte)25, (byte)43, (byte)125, (byte)135, (byte)146, (byte)173, (byte)236, (byte)47, (byte)113, (byte)147, (byte)174, (byte)233, (byte)32, (byte)96, (byte)160,
+ (byte)251, (byte)22, (byte)58, (byte)78, (byte)210, (byte)109, (byte)183, (byte)194, (byte)93, (byte)231, (byte)50, (byte)86, (byte)250, (byte)21, (byte)63, (byte)65,
+ (byte)195, (byte)94, (byte)226, (byte)61, (byte)71, (byte)201, (byte)64, (byte)192, (byte)91, (byte)237, (byte)44, (byte)116, (byte)156, (byte)191, (byte)218, (byte)117,
+ (byte)159, (byte)186, (byte)213, (byte)100, (byte)172, (byte)239, (byte)42, (byte)126, (byte)130, (byte)157, (byte)188, (byte)223, (byte)122, (byte)142, (byte)137, (byte)128,
+ (byte)155, (byte)182, (byte)193, (byte)88, (byte)232, (byte)35, (byte)101, (byte)175, (byte)234, (byte)37, (byte)111, (byte)177, (byte)200, (byte)67, (byte)197, (byte)84,
+ (byte)252, (byte)31, (byte)33, (byte)99, (byte)165, (byte)244, (byte)7, (byte)9, (byte)27, (byte)45, (byte)119, (byte)153, (byte)176, (byte)203, (byte)70, (byte)202,
+ (byte)69, (byte)207, (byte)74, (byte)222, (byte)121, (byte)139, (byte)134, (byte)145, (byte)168, (byte)227, (byte)62, (byte)66, (byte)198, (byte)81, (byte)243, (byte)14,
+ (byte)18, (byte)54, (byte)90, (byte)238, (byte)41, (byte)123, (byte)141, (byte)140, (byte)143, (byte)138, (byte)133, (byte)148, (byte)167, (byte)242, (byte)13, (byte)23,
+ (byte)57, (byte)75, (byte)221, (byte)124, (byte)132, (byte)151, (byte)162, (byte)253, (byte)28, (byte)36, (byte)108, (byte)180, (byte)199, (byte)82, (byte)246, (byte)1,
+ };
+
+ private static final byte[] S = {
+ (byte)99, (byte)124, (byte)119, (byte)123, (byte)242, (byte)107, (byte)111, (byte)197, (byte)48, (byte)1, (byte)103, (byte)43, (byte)254, (byte)215, (byte)171, (byte)118,
+ (byte)202, (byte)130, (byte)201, (byte)125, (byte)250, (byte)89, (byte)71, (byte)240, (byte)173, (byte)212, (byte)162, (byte)175, (byte)156, (byte)164, (byte)114, (byte)192,
+ (byte)183, (byte)253, (byte)147, (byte)38, (byte)54, (byte)63, (byte)247, (byte)204, (byte)52, (byte)165, (byte)229, (byte)241, (byte)113, (byte)216, (byte)49, (byte)21,
+ (byte)4, (byte)199, (byte)35, (byte)195, (byte)24, (byte)150, (byte)5, (byte)154, (byte)7, (byte)18, (byte)128, (byte)226, (byte)235, (byte)39, (byte)178, (byte)117,
+ (byte)9, (byte)131, (byte)44, (byte)26, (byte)27, (byte)110, (byte)90, (byte)160, (byte)82, (byte)59, (byte)214, (byte)179, (byte)41, (byte)227, (byte)47, (byte)132,
+ (byte)83, (byte)209, (byte)0, (byte)237, (byte)32, (byte)252, (byte)177, (byte)91, (byte)106, (byte)203, (byte)190, (byte)57, (byte)74, (byte)76, (byte)88, (byte)207,
+ (byte)208, (byte)239, (byte)170, (byte)251, (byte)67, (byte)77, (byte)51, (byte)133, (byte)69, (byte)249, (byte)2, (byte)127, (byte)80, (byte)60, (byte)159, (byte)168,
+ (byte)81, (byte)163, (byte)64, (byte)143, (byte)146, (byte)157, (byte)56, (byte)245, (byte)188, (byte)182, (byte)218, (byte)33, (byte)16, (byte)255, (byte)243, (byte)210,
+ (byte)205, (byte)12, (byte)19, (byte)236, (byte)95, (byte)151, (byte)68, (byte)23, (byte)196, (byte)167, (byte)126, (byte)61, (byte)100, (byte)93, (byte)25, (byte)115,
+ (byte)96, (byte)129, (byte)79, (byte)220, (byte)34, (byte)42, (byte)144, (byte)136, (byte)70, (byte)238, (byte)184, (byte)20, (byte)222, (byte)94, (byte)11, (byte)219,
+ (byte)224, (byte)50, (byte)58, (byte)10, (byte)73, (byte)6, (byte)36, (byte)92, (byte)194, (byte)211, (byte)172, (byte)98, (byte)145, (byte)149, (byte)228, (byte)121,
+ (byte)231, (byte)200, (byte)55, (byte)109, (byte)141, (byte)213, (byte)78, (byte)169, (byte)108, (byte)86, (byte)244, (byte)234, (byte)101, (byte)122, (byte)174, (byte)8,
+ (byte)186, (byte)120, (byte)37, (byte)46, (byte)28, (byte)166, (byte)180, (byte)198, (byte)232, (byte)221, (byte)116, (byte)31, (byte)75, (byte)189, (byte)139, (byte)138,
+ (byte)112, (byte)62, (byte)181, (byte)102, (byte)72, (byte)3, (byte)246, (byte)14, (byte)97, (byte)53, (byte)87, (byte)185, (byte)134, (byte)193, (byte)29, (byte)158,
+ (byte)225, (byte)248, (byte)152, (byte)17, (byte)105, (byte)217, (byte)142, (byte)148, (byte)155, (byte)30, (byte)135, (byte)233, (byte)206, (byte)85, (byte)40, (byte)223,
+ (byte)140, (byte)161, (byte)137, (byte)13, (byte)191, (byte)230, (byte)66, (byte)104, (byte)65, (byte)153, (byte)45, (byte)15, (byte)176, (byte)84, (byte)187, (byte)22,
+ };
+
+ private static final byte[] Si = {
+ (byte)82, (byte)9, (byte)106, (byte)213, (byte)48, (byte)54, (byte)165, (byte)56, (byte)191, (byte)64, (byte)163, (byte)158, (byte)129, (byte)243, (byte)215, (byte)251,
+ (byte)124, (byte)227, (byte)57, (byte)130, (byte)155, (byte)47, (byte)255, (byte)135, (byte)52, (byte)142, (byte)67, (byte)68, (byte)196, (byte)222, (byte)233, (byte)203,
+ (byte)84, (byte)123, (byte)148, (byte)50, (byte)166, (byte)194, (byte)35, (byte)61, (byte)238, (byte)76, (byte)149, (byte)11, (byte)66, (byte)250, (byte)195, (byte)78,
+ (byte)8, (byte)46, (byte)161, (byte)102, (byte)40, (byte)217, (byte)36, (byte)178, (byte)118, (byte)91, (byte)162, (byte)73, (byte)109, (byte)139, (byte)209, (byte)37,
+ (byte)114, (byte)248, (byte)246, (byte)100, (byte)134, (byte)104, (byte)152, (byte)22, (byte)212, (byte)164, (byte)92, (byte)204, (byte)93, (byte)101, (byte)182, (byte)146,
+ (byte)108, (byte)112, (byte)72, (byte)80, (byte)253, (byte)237, (byte)185, (byte)218, (byte)94, (byte)21, (byte)70, (byte)87, (byte)167, (byte)141, (byte)157, (byte)132,
+ (byte)144, (byte)216, (byte)171, (byte)0, (byte)140, (byte)188, (byte)211, (byte)10, (byte)247, (byte)228, (byte)88, (byte)5, (byte)184, (byte)179, (byte)69, (byte)6,
+ (byte)208, (byte)44, (byte)30, (byte)143, (byte)202, (byte)63, (byte)15, (byte)2, (byte)193, (byte)175, (byte)189, (byte)3, (byte)1, (byte)19, (byte)138, (byte)107,
+ (byte)58, (byte)145, (byte)17, (byte)65, (byte)79, (byte)103, (byte)220, (byte)234, (byte)151, (byte)242, (byte)207, (byte)206, (byte)240, (byte)180, (byte)230, (byte)115,
+ (byte)150, (byte)172, (byte)116, (byte)34, (byte)231, (byte)173, (byte)53, (byte)133, (byte)226, (byte)249, (byte)55, (byte)232, (byte)28, (byte)117, (byte)223, (byte)110,
+ (byte)71, (byte)241, (byte)26, (byte)113, (byte)29, (byte)41, (byte)197, (byte)137, (byte)111, (byte)183, (byte)98, (byte)14, (byte)170, (byte)24, (byte)190, (byte)27,
+ (byte)252, (byte)86, (byte)62, (byte)75, (byte)198, (byte)210, (byte)121, (byte)32, (byte)154, (byte)219, (byte)192, (byte)254, (byte)120, (byte)205, (byte)90, (byte)244,
+ (byte)31, (byte)221, (byte)168, (byte)51, (byte)136, (byte)7, (byte)199, (byte)49, (byte)177, (byte)18, (byte)16, (byte)89, (byte)39, (byte)128, (byte)236, (byte)95,
+ (byte)96, (byte)81, (byte)127, (byte)169, (byte)25, (byte)181, (byte)74, (byte)13, (byte)45, (byte)229, (byte)122, (byte)159, (byte)147, (byte)201, (byte)156, (byte)239,
+ (byte)160, (byte)224, (byte)59, (byte)77, (byte)174, (byte)42, (byte)245, (byte)176, (byte)200, (byte)235, (byte)187, (byte)60, (byte)131, (byte)83, (byte)153, (byte)97,
+ (byte)23, (byte)43, (byte)4, (byte)126, (byte)186, (byte)119, (byte)214, (byte)38, (byte)225, (byte)105, (byte)20, (byte)99, (byte)85, (byte)33, (byte)12, (byte)125,
+ };
+
+ private static final int[] rcon = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 };
+
+ static byte[][] shifts0 =
+ {
+ { 0, 8, 16, 24 },
+ { 0, 8, 16, 24 },
+ { 0, 8, 16, 24 },
+ { 0, 8, 16, 32 },
+ { 0, 8, 24, 32 }
+ };
+
+ static byte[][] shifts1 =
+ {
+ { 0, 24, 16, 8 },
+ { 0, 32, 24, 16 },
+ { 0, 40, 32, 24 },
+ { 0, 48, 40, 24 },
+ { 0, 56, 40, 32 }
+ };
+
+ /**
+ * multiply two elements of GF(2^m)
+ * needed for MixColumn and InvMixColumn
+ */
+ private byte mul0x2(
+ int b)
+ {
+ if (b != 0)
+ {
+ return aLogtable[25 + (logtable[b] & 0xff)];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private byte mul0x3(
+ int b)
+ {
+ if (b != 0)
+ {
+ return aLogtable[1 + (logtable[b] & 0xff)];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private byte mul0x9(
+ int b)
+ {
+ if (b >= 0)
+ {
+ return aLogtable[199 + b];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private byte mul0xb(
+ int b)
+ {
+ if (b >= 0)
+ {
+ return aLogtable[104 + b];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private byte mul0xd(
+ int b)
+ {
+ if (b >= 0)
+ {
+ return aLogtable[238 + b];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ private byte mul0xe(
+ int b)
+ {
+ if (b >= 0)
+ {
+ return aLogtable[223 + b];
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ /**
+ * xor corresponding text input and round key input bytes
+ */
+ private void KeyAddition(
+ long[] rk)
+ {
+ A0 ^= rk[0];
+ A1 ^= rk[1];
+ A2 ^= rk[2];
+ A3 ^= rk[3];
+ }
+
+ private long shift(
+ long r,
+ int shift)
+ {
+ return (((r >>> shift) | (r << (BC - shift)))) & BC_MASK;
+ }
+
+ /**
+ * Row 0 remains unchanged
+ * The other three rows are shifted a variable amount
+ */
+ private void ShiftRow(
+ byte[] shiftsSC)
+ {
+ A1 = shift(A1, shiftsSC[1]);
+ A2 = shift(A2, shiftsSC[2]);
+ A3 = shift(A3, shiftsSC[3]);
+ }
+
+ private long applyS(
+ long r,
+ byte[] box)
+ {
+ long res = 0;
+
+ for (int j = 0; j < BC; j += 8)
+ {
+ res |= (long)(box[(int)((r >> j) & 0xff)] & 0xff) << j;
+ }
+
+ return res;
+ }
+
+ /**
+ * Replace every byte of the input by the byte at that place
+ * in the nonlinear S-box
+ */
+ private void Substitution(
+ byte[] box)
+ {
+ A0 = applyS(A0, box);
+ A1 = applyS(A1, box);
+ A2 = applyS(A2, box);
+ A3 = applyS(A3, box);
+ }
+
+ /**
+ * Mix the bytes of every column in a linear way
+ */
+ private void MixColumn()
+ {
+ long r0, r1, r2, r3;
+
+ r0 = r1 = r2 = r3 = 0;
+
+ for (int j = 0; j < BC; j += 8)
+ {
+ int a0 = (int)((A0 >> j) & 0xff);
+ int a1 = (int)((A1 >> j) & 0xff);
+ int a2 = (int)((A2 >> j) & 0xff);
+ int a3 = (int)((A3 >> j) & 0xff);
+
+ r0 |= (long)((mul0x2(a0) ^ mul0x3(a1) ^ a2 ^ a3) & 0xff) << j;
+
+ r1 |= (long)((mul0x2(a1) ^ mul0x3(a2) ^ a3 ^ a0) & 0xff) << j;
+
+ r2 |= (long)((mul0x2(a2) ^ mul0x3(a3) ^ a0 ^ a1) & 0xff) << j;
+
+ r3 |= (long)((mul0x2(a3) ^ mul0x3(a0) ^ a1 ^ a2) & 0xff) << j;
+ }
+
+ A0 = r0;
+ A1 = r1;
+ A2 = r2;
+ A3 = r3;
+ }
+
+ /**
+ * Mix the bytes of every column in a linear way
+ * This is the opposite operation of Mixcolumn
+ */
+ private void InvMixColumn()
+ {
+ long r0, r1, r2, r3;
+
+ r0 = r1 = r2 = r3 = 0;
+ for (int j = 0; j < BC; j += 8)
+ {
+ int a0 = (int)((A0 >> j) & 0xff);
+ int a1 = (int)((A1 >> j) & 0xff);
+ int a2 = (int)((A2 >> j) & 0xff);
+ int a3 = (int)((A3 >> j) & 0xff);
+
+ //
+ // pre-lookup the log table
+ //
+ a0 = (a0 != 0) ? (logtable[a0 & 0xff] & 0xff) : -1;
+ a1 = (a1 != 0) ? (logtable[a1 & 0xff] & 0xff) : -1;
+ a2 = (a2 != 0) ? (logtable[a2 & 0xff] & 0xff) : -1;
+ a3 = (a3 != 0) ? (logtable[a3 & 0xff] & 0xff) : -1;
+
+ r0 |= (long)((mul0xe(a0) ^ mul0xb(a1) ^ mul0xd(a2) ^ mul0x9(a3)) & 0xff) << j;
+
+ r1 |= (long)((mul0xe(a1) ^ mul0xb(a2) ^ mul0xd(a3) ^ mul0x9(a0)) & 0xff) << j;
+
+ r2 |= (long)((mul0xe(a2) ^ mul0xb(a3) ^ mul0xd(a0) ^ mul0x9(a1)) & 0xff) << j;
+
+ r3 |= (long)((mul0xe(a3) ^ mul0xb(a0) ^ mul0xd(a1) ^ mul0x9(a2)) & 0xff) << j;
+ }
+
+ A0 = r0;
+ A1 = r1;
+ A2 = r2;
+ A3 = r3;
+ }
+
+ /**
+ * Calculate the necessary round keys
+ * The number of calculations depends on keyBits and blockBits
+ */
+ private long[][] generateWorkingKey(
+ byte[] key)
+ {
+ int KC;
+ int t, rconpointer = 0;
+ int keyBits = key.length * 8;
+ byte[][] tk = new byte[4][MAXKC];
+ long[][] W = new long[MAXROUNDS+1][4];
+
+ switch (keyBits)
+ {
+ case 128:
+ KC = 4;
+ break;
+ case 160:
+ KC = 5;
+ break;
+ case 192:
+ KC = 6;
+ break;
+ case 224:
+ KC = 7;
+ break;
+ case 256:
+ KC = 8;
+ break;
+ default :
+ throw new IllegalArgumentException("Key length not 128/160/192/224/256 bits.");
+ }
+
+ if (keyBits >= blockBits)
+ {
+ ROUNDS = KC + 6;
+ }
+ else
+ {
+ ROUNDS = (BC / 8) + 6;
+ }
+
+ //
+ // copy the key into the processing area
+ //
+ int index = 0;
+
+ for (int i = 0; i < key.length; i++)
+ {
+ tk[i % 4][i / 4] = key[index++];
+ }
+
+ t = 0;
+
+ //
+ // copy values into round key array
+ //
+ for (int j = 0; (j < KC) && (t < (ROUNDS+1)*(BC / 8)); j++, t++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ W[t / (BC / 8)][i] |= (long)(tk[i][j] & 0xff) << ((t * 8) % BC);
+ }
+ }
+
+ //
+ // while not enough round key material calculated
+ // calculate new values
+ //
+ while (t < (ROUNDS+1)*(BC/8))
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ tk[i][0] ^= S[tk[(i+1)%4][KC-1] & 0xff];
+ }
+ tk[0][0] ^= rcon[rconpointer++];
+
+ if (KC <= 6)
+ {
+ for (int j = 1; j < KC; j++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ tk[i][j] ^= tk[i][j-1];
+ }
+ }
+ }
+ else
+ {
+ for (int j = 1; j < 4; j++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ tk[i][j] ^= tk[i][j-1];
+ }
+ }
+ for (int i = 0; i < 4; i++)
+ {
+ tk[i][4] ^= S[tk[i][3] & 0xff];
+ }
+ for (int j = 5; j < KC; j++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ tk[i][j] ^= tk[i][j-1];
+ }
+ }
+ }
+
+ //
+ // copy values into round key array
+ //
+ for (int j = 0; (j < KC) && (t < (ROUNDS+1)*(BC/8)); j++, t++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ W[t / (BC/8)][i] |= (long)(tk[i][j] & 0xff) << ((t * 8) % (BC));
+ }
+ }
+ }
+
+ return W;
+ }
+
+ private int BC;
+ private long BC_MASK;
+ private int ROUNDS;
+ private int blockBits;
+ private long[][] workingKey;
+ private long A0, A1, A2, A3;
+ private boolean forEncryption;
+ private byte[] shifts0SC;
+ private byte[] shifts1SC;
+
+ /**
+ * default constructor - 128 bit block size.
+ */
+ public RijndaelEngine()
+ {
+ this(128);
+ }
+
+ /**
+ * basic constructor - set the cipher up for a given blocksize
+ *
+ * @param blockBits the blocksize in bits, must be 128, 192, or 256.
+ */
+ public RijndaelEngine(
+ int blockBits)
+ {
+ switch (blockBits)
+ {
+ case 128:
+ BC = 32;
+ BC_MASK = 0xffffffffL;
+ shifts0SC = shifts0[0];
+ shifts1SC = shifts1[0];
+ break;
+ case 160:
+ BC = 40;
+ BC_MASK = 0xffffffffffL;
+ shifts0SC = shifts0[1];
+ shifts1SC = shifts1[1];
+ break;
+ case 192:
+ BC = 48;
+ BC_MASK = 0xffffffffffffL;
+ shifts0SC = shifts0[2];
+ shifts1SC = shifts1[2];
+ break;
+ case 224:
+ BC = 56;
+ BC_MASK = 0xffffffffffffffL;
+ shifts0SC = shifts0[3];
+ shifts1SC = shifts1[3];
+ break;
+ case 256:
+ BC = 64;
+ BC_MASK = 0xffffffffffffffffL;
+ shifts0SC = shifts0[4];
+ shifts1SC = shifts1[4];
+ break;
+ default:
+ throw new IllegalArgumentException("unknown blocksize to Rijndael");
+ }
+
+ this.blockBits = blockBits;
+ }
+
+ /**
+ * initialise a Rijndael cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ workingKey = generateWorkingKey(((KeyParameter)params).getKey());
+ this.forEncryption = forEncryption;
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to Rijndael init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Rijndael";
+ }
+
+ public int getBlockSize()
+ {
+ return BC / 2;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("Rijndael engine not initialised");
+ }
+
+ if ((inOff + (BC / 2)) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + (BC / 2)) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (forEncryption)
+ {
+ unpackBlock(in, inOff);
+ encryptBlock(workingKey);
+ packBlock(out, outOff);
+ }
+ else
+ {
+ unpackBlock(in, inOff);
+ decryptBlock(workingKey);
+ packBlock(out, outOff);
+ }
+
+ return BC / 2;
+ }
+
+ public void reset()
+ {
+ }
+
+ private void unpackBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ A0 = (bytes[index++] & 0xff);
+ A1 = (bytes[index++] & 0xff);
+ A2 = (bytes[index++] & 0xff);
+ A3 = (bytes[index++] & 0xff);
+
+ for (int j = 8; j != BC; j += 8)
+ {
+ A0 |= (long)(bytes[index++] & 0xff) << j;
+ A1 |= (long)(bytes[index++] & 0xff) << j;
+ A2 |= (long)(bytes[index++] & 0xff) << j;
+ A3 |= (long)(bytes[index++] & 0xff) << j;
+ }
+ }
+
+ private void packBlock(
+ byte[] bytes,
+ int off)
+ {
+ int index = off;
+
+ for (int j = 0; j != BC; j += 8)
+ {
+ bytes[index++] = (byte)(A0 >> j);
+ bytes[index++] = (byte)(A1 >> j);
+ bytes[index++] = (byte)(A2 >> j);
+ bytes[index++] = (byte)(A3 >> j);
+ }
+ }
+
+ private void encryptBlock(
+ long[][] rk)
+ {
+ int r;
+
+ //
+ // begin with a key addition
+ //
+ KeyAddition(rk[0]);
+
+ //
+ // ROUNDS-1 ordinary rounds
+ //
+ for (r = 1; r < ROUNDS; r++)
+ {
+ Substitution(S);
+ ShiftRow(shifts0SC);
+ MixColumn();
+ KeyAddition(rk[r]);
+ }
+
+ //
+ // Last round is special: there is no MixColumn
+ //
+ Substitution(S);
+ ShiftRow(shifts0SC);
+ KeyAddition(rk[ROUNDS]);
+ }
+
+ private void decryptBlock(
+ long[][] rk)
+ {
+ int r;
+
+ // To decrypt: apply the inverse operations of the encrypt routine,
+ // in opposite order
+ //
+ // (KeyAddition is an involution: it 's equal to its inverse)
+ // (the inverse of Substitution with table S is Substitution with the inverse table of S)
+ // (the inverse of Shiftrow is Shiftrow over a suitable distance)
+ //
+
+ // First the special round:
+ // without InvMixColumn
+ // with extra KeyAddition
+ //
+ KeyAddition(rk[ROUNDS]);
+ Substitution(Si);
+ ShiftRow(shifts1SC);
+
+ //
+ // ROUNDS-1 ordinary rounds
+ //
+ for (r = ROUNDS-1; r > 0; r--)
+ {
+ KeyAddition(rk[r]);
+ InvMixColumn();
+ Substitution(Si);
+ ShiftRow(shifts1SC);
+ }
+
+ //
+ // End with the extra key addition
+ //
+ KeyAddition(rk[0]);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/SEEDEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/SEEDEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/SEEDEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/SEEDEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,345 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * Implementation of the SEED algorithm as described in RFC 4009
+ */
+public class SEEDEngine
+ implements BlockCipher
+{
+ private final int BLOCK_SIZE = 16;
+
+ private static final int[] SS0 =
+ {
+ 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124,
+ 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360,
+ 0x28082028, 0x04444044, 0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314,
+ 0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310, 0x12c2d2d0, 0x2ecee2ec,
+ 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074,
+ 0x2ccce0ec, 0x15859194, 0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100,
+ 0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc, 0x32c2f2f0, 0x19c9d1d8,
+ 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8,
+ 0x20406060, 0x10405050, 0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c,
+ 0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210, 0x2f8fa3ac, 0x15c5d1d4,
+ 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008,
+ 0x1f0f131c, 0x19899198, 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0,
+ 0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388, 0x0e0e020c, 0x2b8ba3a8,
+ 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208,
+ 0x3f8fb3bc, 0x2fcfe3ec, 0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064,
+ 0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120, 0x2b4b6368, 0x26466264,
+ 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0,
+ 0x3a4a7278, 0x07474344, 0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc,
+ 0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114, 0x22022220, 0x38083038,
+ 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394,
+ 0x35053134, 0x0bcbc3c8, 0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188,
+ 0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158, 0x02828280, 0x04c4c0c4,
+ 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8,
+ 0x0f0f030c, 0x0e8e828c, 0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4,
+ 0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c, 0x2d0d212c, 0x00404040,
+ 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154,
+ 0x3b0b3338, 0x1cccd0dc, 0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254,
+ 0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328, 0x25456164, 0x3acaf2f8,
+ 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0,
+ 0x31013130, 0x2acae2e8, 0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088,
+ 0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128, 0x07070304, 0x33033330,
+ 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298
+ };
+
+ private static final int[] SS1 =
+ {
+
+ 0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2, 0xb03383b3, 0xb83888b0,
+ 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53,
+ 0xc003c3c3, 0x60224262, 0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3,
+ 0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0, 0x34360632, 0x480b4b43,
+ 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0,
+ 0xc002c2c2, 0x44054541, 0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890,
+ 0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1, 0x0c0d0d01, 0xdc1fcfd3,
+ 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272,
+ 0x40024242, 0xd414c4d0, 0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83,
+ 0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20, 0xa82a8aa2, 0x34340430,
+ 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0,
+ 0x54174753, 0xac2e8ea2, 0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1,
+ 0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82, 0x682a4a62, 0xb03181b1,
+ 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, 0x20220222, 0x04040400, 0x68284860, 0x70314171,
+ 0x04070703, 0xd81bcbd3, 0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951,
+ 0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3, 0xa82b8ba3, 0xd010c0d0,
+ 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3,
+ 0x94168692, 0x783b4b73, 0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41,
+ 0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22, 0xb83a8ab2, 0x6c2e4e62,
+ 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0,
+ 0x14150511, 0xf83bcbf3, 0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303,
+ 0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0, 0xe82acae2, 0x08090901,
+ 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501,
+ 0xf83acaf2, 0x00010101, 0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343,
+ 0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1, 0x48084840, 0x78394971,
+ 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53,
+ 0x74374773, 0x54144450, 0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642,
+ 0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2, 0xc809c9c1, 0xfc3dcdf1,
+ 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70,
+ 0x0c0e0e02, 0x50104050, 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393,
+ 0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353, 0x080a0a02, 0x84078783,
+ 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3
+ };
+
+ private static final int[] SS2 =
+ {
+
+ 0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d, 0xa0ac2c8c, 0x21242505,
+ 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343,
+ 0x20282808, 0x40440444, 0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707,
+ 0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303, 0xd2d012c2, 0xe2ec2ece,
+ 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444,
+ 0xe0ec2ccc, 0x91941585, 0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101,
+ 0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc, 0xf2f032c2, 0xd1d819c9,
+ 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9,
+ 0x60602040, 0x50501040, 0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f,
+ 0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202, 0xa3ac2f8f, 0xd1d415c5,
+ 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808,
+ 0x131c1f0f, 0x91981989, 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1,
+ 0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b, 0x020c0e0e, 0xa3a82b8b,
+ 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a,
+ 0xb3bc3f8f, 0xe3ec2fcf, 0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444,
+ 0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101, 0x63682b4b, 0x62642646,
+ 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0,
+ 0x72783a4a, 0x43440747, 0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf,
+ 0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505, 0x22202202, 0x30383808,
+ 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787,
+ 0x31343505, 0xc3c80bcb, 0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989,
+ 0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949, 0x82800282, 0xc0c404c4,
+ 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888,
+ 0x030c0f0f, 0x828c0e8e, 0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484,
+ 0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d, 0x212c2d0d, 0x40400040,
+ 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545,
+ 0x33383b0b, 0xd0dc1ccc, 0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646,
+ 0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b, 0x61642545, 0xf2f83aca,
+ 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282,
+ 0x31303101, 0xe2e82aca, 0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888,
+ 0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909, 0x03040707, 0x33303303,
+ 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a
+ };
+
+
+ private static final int[] SS3 =
+ {
+
+ 0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e, 0x83b3b033, 0x88b0b838,
+ 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b,
+ 0xc3c3c003, 0x42626022, 0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427,
+ 0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c, 0x06323436, 0x4b43480b,
+ 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434,
+ 0xc2c2c002, 0x45414405, 0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818,
+ 0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839, 0x0d010c0d, 0xcfd3dc1f,
+ 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032,
+ 0x42424002, 0xc4d0d414, 0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b,
+ 0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c, 0x8aa2a82a, 0x04303434,
+ 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838,
+ 0x47535417, 0x8ea2ac2e, 0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839,
+ 0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a, 0x4a62682a, 0x81b1b031,
+ 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, 0x02222022, 0x04000404, 0x48606828, 0x41717031,
+ 0x07030407, 0xcbd3d81b, 0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819,
+ 0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023, 0x8ba3a82b, 0xc0d0d010,
+ 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f,
+ 0x86929416, 0x4b73783b, 0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d,
+ 0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e, 0x8ab2b83a, 0x4e626c2e,
+ 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c,
+ 0x05111415, 0xcbf3f83b, 0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003,
+ 0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434, 0xcae2e82a, 0x09010809,
+ 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405,
+ 0xcaf2f83a, 0x01010001, 0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003,
+ 0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425, 0x48404808, 0x49717839,
+ 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f,
+ 0x47737437, 0x44505414, 0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406,
+ 0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a, 0xc9c1c809, 0xcdf1fc3d,
+ 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c,
+ 0x0e020c0e, 0x40505010, 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013,
+ 0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013, 0x0a02080a, 0x87838407,
+ 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437
+ };
+
+
+ private static final int[] KC =
+ {
+ 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc,
+ 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf,
+ 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1,
+ 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b
+ };
+
+ private int[] wKey;
+ private boolean forEncryption;
+
+ public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+ wKey = createWorkingKey(((KeyParameter)params).getKey());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SEED";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException
+ {
+ if (wKey == null)
+ {
+ throw new IllegalStateException("SEED engine not initialised");
+ }
+
+ if (inOff + BLOCK_SIZE > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if (outOff + BLOCK_SIZE > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ long l = bytesToLong(in, inOff + 0);
+ long r = bytesToLong(in, inOff + 8);
+
+ if (forEncryption)
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ long nl = r;
+
+ r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r);
+ l = nl;
+ }
+ }
+ else
+ {
+ for (int i = 15; i >= 0; i--)
+ {
+ long nl = r;
+
+ r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r);
+ l = nl;
+ }
+ }
+
+ longToBytes(out, outOff + 0, r);
+ longToBytes(out, outOff + 8, l);
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ private int[] createWorkingKey(byte[] inKey)
+ {
+ int[] key = new int[32];
+ long lower = bytesToLong(inKey, 0);
+ long upper = bytesToLong(inKey, 8);
+
+ int key0 = extractW0(lower);
+ int key1 = extractW1(lower);
+ int key2 = extractW0(upper);
+ int key3 = extractW1(upper);
+
+ for (int i = 0; i < 16; i++)
+ {
+ key[2 * i] = G(key0 + key2 - KC[i]);
+ key[2 * i + 1] = G(key1 - key3 + KC[i]);
+
+ if (i % 2 == 0)
+ {
+ lower = rotateRight8(lower);
+ key0 = extractW0(lower);
+ key1 = extractW1(lower);
+ }
+ else
+ {
+ upper = rotateLeft8(upper);
+ key2 = extractW0(upper);
+ key3 = extractW1(upper);
+ }
+ }
+
+ return key;
+ }
+
+ private int extractW1(long lVal)
+ {
+ return (int)lVal;
+ }
+
+ private int extractW0(long lVal)
+ {
+ return (int)(lVal >> 32);
+ }
+
+ private long rotateLeft8(long x)
+ {
+ return (x << 8) | (x >>> 56);
+ }
+
+ private long rotateRight8(long x)
+ {
+ return (x >>> 8) | (x << 56);
+ }
+
+ private long bytesToLong(
+ byte[] src,
+ int srcOff)
+ {
+ long word = 0;
+
+ for (int i = 0; i <= 7; i++)
+ {
+ word = (word << 8) + (src[i + srcOff] & 0xff);
+ }
+
+ return word;
+ }
+
+ private void longToBytes(
+ byte[] dest,
+ int destOff,
+ long value)
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ dest[i + destOff] = (byte)(value >> ((7 - i) * 8));
+ }
+ }
+
+ private int G(int x)
+ {
+ return SS0[x & 0xff] ^ SS1[(x >> 8) & 0xff] ^ SS2[(x >> 16) & 0xff] ^ SS3[(x >> 24) & 0xff];
+ }
+
+ private long F(int ki0, int ki1, long r)
+ {
+ int r0 = (int)(r >> 32);
+ int r1 = (int)r;
+ int rd1 = phaseCalc2(r0, ki0, r1, ki1);
+ int rd0 = rd1 + phaseCalc1(r0, ki0, r1, ki1);
+
+ return ((long)rd0 << 32) | (rd1 & 0xffffffffL);
+ }
+
+ private int phaseCalc1(int r0, int ki0, int r1, int ki1)
+ {
+ return G(G((r0 ^ ki0) ^ (r1 ^ ki1)) + (r0 ^ ki0));
+ }
+
+ private int phaseCalc2(int r0, int ki0, int r1, int ki1)
+ {
+ return G(phaseCalc1(r0, ki0, r1, ki1) + G((r0 ^ ki0) ^ (r1 ^ ki1)));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/SEEDWrapEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/SEEDWrapEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/SEEDWrapEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/SEEDWrapEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,15 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+/**
+ * An implementation of the SEED key wrapper based on RFC 4010/RFC 3394.
+ *
+ * For further details see: http://www.ietf.org/rfc/rfc4010.txt .
+ */
+public class SEEDWrapEngine
+ extends RFC3394WrapEngine
+{
+ public SEEDWrapEngine()
+ {
+ super(new SEEDEngine());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/Salsa20Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/Salsa20Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/Salsa20Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/Salsa20Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,320 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.MaxBytesExceededException;
+import pdftk.org.bouncycastle.crypto.StreamCipher;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+import pdftk.org.bouncycastle.crypto.util.Pack;
+import pdftk.org.bouncycastle.util.Strings;
+
+/**
+ * Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
+ */
+
+public class Salsa20Engine
+ implements StreamCipher
+{
+ /** Constants */
+ private final static int STATE_SIZE = 16; // 16, 32 bit ints = 64 bytes
+
+ private final static byte[]
+ sigma = Strings.toByteArray("expand 32-byte k"),
+ tau = Strings.toByteArray("expand 16-byte k");
+
+ /*
+ * variables to hold the state of the engine
+ * during encryption and decryption
+ */
+ private int index = 0;
+ private int[] engineState = new int[STATE_SIZE]; // state
+ private int[] x = new int[STATE_SIZE] ; // internal buffer
+ private byte[] keyStream = new byte[STATE_SIZE * 4], // expanded state, 64 bytes
+ workingKey = null,
+ workingIV = null;
+ private boolean initialised = false;
+
+ /*
+ * internal counter
+ */
+ private int cW0, cW1, cW2;
+
+ /**
+ * initialise a Salsa20 cipher.
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ /*
+ * Salsa20 encryption and decryption is completely
+ * symmetrical, so the 'forEncryption' is
+ * irrelevant. (Like 90% of stream ciphers)
+ */
+
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException("Salsa20 Init parameters must include an IV");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV) params;
+
+ byte[] iv = ivParams.getIV();
+
+ if (iv == null || iv.length != 8)
+ {
+ throw new IllegalArgumentException("Salsa20 requires exactly 8 bytes of IV");
+ }
+
+ if (!(ivParams.getParameters() instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("Salsa20 Init parameters must include a key");
+ }
+
+ KeyParameter key = (KeyParameter) ivParams.getParameters();
+
+ workingKey = key.getKey();
+ workingIV = iv;
+
+ setKey(workingKey, workingIV);
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Salsa20";
+ }
+
+ public byte returnByte(byte in)
+ {
+ if (limitExceeded())
+ {
+ throw new MaxBytesExceededException("2^70 byte limit per IV; Change IV");
+ }
+
+ if (index == 0)
+ {
+ generateKeyStream(keyStream);
+
+ if (++engineState[8] == 0)
+ {
+ ++engineState[9];
+ }
+ }
+
+ byte out = (byte)(keyStream[index]^in);
+ index = (index + 1) & 63;
+
+ return out;
+ }
+
+ public void processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ {
+ if (!initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (limitExceeded(len))
+ {
+ throw new MaxBytesExceededException("2^70 byte limit per IV would be exceeded; Change IV");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ if (index == 0)
+ {
+ generateKeyStream(keyStream);
+
+ if (++engineState[8] == 0)
+ {
+ ++engineState[9];
+ }
+ }
+
+ out[i+outOff] = (byte)(keyStream[index]^in[i+inOff]);
+ index = (index + 1) & 63;
+ }
+ }
+
+ public void reset()
+ {
+ setKey(workingKey, workingIV);
+ }
+
+ // Private implementation
+
+ private void setKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ workingKey = keyBytes;
+ workingIV = ivBytes;
+
+ index = 0;
+ resetCounter();
+ int offset = 0;
+ byte[] constants;
+
+ // Key
+ engineState[1] = Pack.littleEndianToInt(workingKey, 0);
+ engineState[2] = Pack.littleEndianToInt(workingKey, 4);
+ engineState[3] = Pack.littleEndianToInt(workingKey, 8);
+ engineState[4] = Pack.littleEndianToInt(workingKey, 12);
+
+ if (workingKey.length == 32)
+ {
+ constants = sigma;
+ offset = 16;
+ }
+ else
+ {
+ constants = tau;
+ }
+
+ engineState[11] = Pack.littleEndianToInt(workingKey, offset);
+ engineState[12] = Pack.littleEndianToInt(workingKey, offset+4);
+ engineState[13] = Pack.littleEndianToInt(workingKey, offset+8);
+ engineState[14] = Pack.littleEndianToInt(workingKey, offset+12);
+ engineState[0 ] = Pack.littleEndianToInt(constants, 0);
+ engineState[5 ] = Pack.littleEndianToInt(constants, 4);
+ engineState[10] = Pack.littleEndianToInt(constants, 8);
+ engineState[15] = Pack.littleEndianToInt(constants, 12);
+
+ // IV
+ engineState[6] = Pack.littleEndianToInt(workingIV, 0);
+ engineState[7] = Pack.littleEndianToInt(workingIV, 4);
+ engineState[8] = engineState[9] = 0;
+
+ initialised = true;
+ }
+
+ private void generateKeyStream(byte[] output)
+ {
+ salsaCore(20, engineState, x);
+ Pack.intToLittleEndian(x, output, 0);
+ }
+
+ /**
+ * Salsa20 function
+ *
+ * @param input input data
+ *
+ * @return keystream
+ */
+ public static void salsaCore(int rounds, int[] input, int[] x)
+ {
+ // TODO Exception if rounds odd?
+
+ System.arraycopy(input, 0, x, 0, input.length);
+
+ for (int i = rounds; i > 0; i -= 2)
+ {
+ x[ 4] ^= rotl((x[ 0]+x[12]), 7);
+ x[ 8] ^= rotl((x[ 4]+x[ 0]), 9);
+ x[12] ^= rotl((x[ 8]+x[ 4]),13);
+ x[ 0] ^= rotl((x[12]+x[ 8]),18);
+ x[ 9] ^= rotl((x[ 5]+x[ 1]), 7);
+ x[13] ^= rotl((x[ 9]+x[ 5]), 9);
+ x[ 1] ^= rotl((x[13]+x[ 9]),13);
+ x[ 5] ^= rotl((x[ 1]+x[13]),18);
+ x[14] ^= rotl((x[10]+x[ 6]), 7);
+ x[ 2] ^= rotl((x[14]+x[10]), 9);
+ x[ 6] ^= rotl((x[ 2]+x[14]),13);
+ x[10] ^= rotl((x[ 6]+x[ 2]),18);
+ x[ 3] ^= rotl((x[15]+x[11]), 7);
+ x[ 7] ^= rotl((x[ 3]+x[15]), 9);
+ x[11] ^= rotl((x[ 7]+x[ 3]),13);
+ x[15] ^= rotl((x[11]+x[ 7]),18);
+ x[ 1] ^= rotl((x[ 0]+x[ 3]), 7);
+ x[ 2] ^= rotl((x[ 1]+x[ 0]), 9);
+ x[ 3] ^= rotl((x[ 2]+x[ 1]),13);
+ x[ 0] ^= rotl((x[ 3]+x[ 2]),18);
+ x[ 6] ^= rotl((x[ 5]+x[ 4]), 7);
+ x[ 7] ^= rotl((x[ 6]+x[ 5]), 9);
+ x[ 4] ^= rotl((x[ 7]+x[ 6]),13);
+ x[ 5] ^= rotl((x[ 4]+x[ 7]),18);
+ x[11] ^= rotl((x[10]+x[ 9]), 7);
+ x[ 8] ^= rotl((x[11]+x[10]), 9);
+ x[ 9] ^= rotl((x[ 8]+x[11]),13);
+ x[10] ^= rotl((x[ 9]+x[ 8]),18);
+ x[12] ^= rotl((x[15]+x[14]), 7);
+ x[13] ^= rotl((x[12]+x[15]), 9);
+ x[14] ^= rotl((x[13]+x[12]),13);
+ x[15] ^= rotl((x[14]+x[13]),18);
+ }
+
+ for (int i = 0; i < STATE_SIZE; ++i)
+ {
+ x[i] += input[i];
+ }
+ }
+
+ /**
+ * Rotate left
+ *
+ * @param x value to rotate
+ * @param y amount to rotate x
+ *
+ * @return rotated x
+ */
+ private static int rotl(int x, int y)
+ {
+ return (x << y) | (x >>> -y);
+ }
+
+ private void resetCounter()
+ {
+ cW0 = 0;
+ cW1 = 0;
+ cW2 = 0;
+ }
+
+ private boolean limitExceeded()
+ {
+ if (++cW0 == 0)
+ {
+ if (++cW1 == 0)
+ {
+ return (++cW2 & 0x20) != 0; // 2^(32 + 32 + 6)
+ }
+ }
+
+ return false;
+ }
+
+ /*
+ * this relies on the fact len will always be positive.
+ */
+ private boolean limitExceeded(int len)
+ {
+ cW0 += len;
+ if (cW0 < len && cW0 >= 0)
+ {
+ if (++cW1 == 0)
+ {
+ return (++cW2 & 0x20) != 0; // 2^(32 + 32 + 6)
+ }
+ }
+
+ return false;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/SerpentEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/SerpentEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/SerpentEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/SerpentEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,782 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * Serpent is a 128-bit 32-round block cipher with variable key lengths,
+ * including 128, 192 and 256 bit keys conjectured to be at least as
+ * secure as three-key triple-DES.
+ *
+ * Serpent was designed by Ross Anderson, Eli Biham and Lars Knudsen as a
+ * candidate algorithm for the NIST AES Quest.>
+ *
+ * For full details see the The Serpent home page
+ */
+public class SerpentEngine
+ implements BlockCipher
+{
+ private static final int BLOCK_SIZE = 16;
+
+ static final int ROUNDS = 32;
+ static final int PHI = 0x9E3779B9; // (sqrt(5) - 1) * 2**31
+
+ private boolean encrypting;
+ private int[] wKey;
+
+ private int X0, X1, X2, X3; // registers
+
+ /**
+ * initialise a Serpent cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ this.encrypting = encrypting;
+ this.wKey = makeWorkingKey(((KeyParameter)params).getKey());
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to Serpent init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Serpent";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public final int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (wKey == null)
+ {
+ throw new IllegalStateException("Serpent not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (encrypting)
+ {
+ encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ decryptBlock(in, inOff, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Expand a user-supplied key material into a session key.
+ *
+ * @param key The user-key bytes (multiples of 4) to use.
+ * @exception IllegalArgumentException
+ */
+ private int[] makeWorkingKey(
+ byte[] key)
+ throws IllegalArgumentException
+ {
+ //
+ // pad key to 256 bits
+ //
+ int[] kPad = new int[16];
+ int off = 0;
+ int length = 0;
+
+ for (off = key.length - 4; off > 0; off -= 4)
+ {
+ kPad[length++] = bytesToWord(key, off);
+ }
+
+ if (off == 0)
+ {
+ kPad[length++] = bytesToWord(key, 0);
+ if (length < 8)
+ {
+ kPad[length] = 1;
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("key must be a multiple of 4 bytes");
+ }
+
+ //
+ // expand the padded key up to 33 x 128 bits of key material
+ //
+ int amount = (ROUNDS + 1) * 4;
+ int[] w = new int[amount];
+
+ //
+ // compute w0 to w7 from w-8 to w-1
+ //
+ for (int i = 8; i < 16; i++)
+ {
+ kPad[i] = rotateLeft(kPad[i - 8] ^ kPad[i - 5] ^ kPad[i - 3] ^ kPad[i - 1] ^ PHI ^ (i - 8), 11);
+ }
+
+ System.arraycopy(kPad, 8, w, 0, 8);
+
+ //
+ // compute w8 to w136
+ //
+ for (int i = 8; i < amount; i++)
+ {
+ w[i] = rotateLeft(w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11);
+ }
+
+ //
+ // create the working keys by processing w with the Sbox and IP
+ //
+ sb3(w[0], w[1], w[2], w[3]);
+ w[0] = X0; w[1] = X1; w[2] = X2; w[3] = X3;
+ sb2(w[4], w[5], w[6], w[7]);
+ w[4] = X0; w[5] = X1; w[6] = X2; w[7] = X3;
+ sb1(w[8], w[9], w[10], w[11]);
+ w[8] = X0; w[9] = X1; w[10] = X2; w[11] = X3;
+ sb0(w[12], w[13], w[14], w[15]);
+ w[12] = X0; w[13] = X1; w[14] = X2; w[15] = X3;
+ sb7(w[16], w[17], w[18], w[19]);
+ w[16] = X0; w[17] = X1; w[18] = X2; w[19] = X3;
+ sb6(w[20], w[21], w[22], w[23]);
+ w[20] = X0; w[21] = X1; w[22] = X2; w[23] = X3;
+ sb5(w[24], w[25], w[26], w[27]);
+ w[24] = X0; w[25] = X1; w[26] = X2; w[27] = X3;
+ sb4(w[28], w[29], w[30], w[31]);
+ w[28] = X0; w[29] = X1; w[30] = X2; w[31] = X3;
+ sb3(w[32], w[33], w[34], w[35]);
+ w[32] = X0; w[33] = X1; w[34] = X2; w[35] = X3;
+ sb2(w[36], w[37], w[38], w[39]);
+ w[36] = X0; w[37] = X1; w[38] = X2; w[39] = X3;
+ sb1(w[40], w[41], w[42], w[43]);
+ w[40] = X0; w[41] = X1; w[42] = X2; w[43] = X3;
+ sb0(w[44], w[45], w[46], w[47]);
+ w[44] = X0; w[45] = X1; w[46] = X2; w[47] = X3;
+ sb7(w[48], w[49], w[50], w[51]);
+ w[48] = X0; w[49] = X1; w[50] = X2; w[51] = X3;
+ sb6(w[52], w[53], w[54], w[55]);
+ w[52] = X0; w[53] = X1; w[54] = X2; w[55] = X3;
+ sb5(w[56], w[57], w[58], w[59]);
+ w[56] = X0; w[57] = X1; w[58] = X2; w[59] = X3;
+ sb4(w[60], w[61], w[62], w[63]);
+ w[60] = X0; w[61] = X1; w[62] = X2; w[63] = X3;
+ sb3(w[64], w[65], w[66], w[67]);
+ w[64] = X0; w[65] = X1; w[66] = X2; w[67] = X3;
+ sb2(w[68], w[69], w[70], w[71]);
+ w[68] = X0; w[69] = X1; w[70] = X2; w[71] = X3;
+ sb1(w[72], w[73], w[74], w[75]);
+ w[72] = X0; w[73] = X1; w[74] = X2; w[75] = X3;
+ sb0(w[76], w[77], w[78], w[79]);
+ w[76] = X0; w[77] = X1; w[78] = X2; w[79] = X3;
+ sb7(w[80], w[81], w[82], w[83]);
+ w[80] = X0; w[81] = X1; w[82] = X2; w[83] = X3;
+ sb6(w[84], w[85], w[86], w[87]);
+ w[84] = X0; w[85] = X1; w[86] = X2; w[87] = X3;
+ sb5(w[88], w[89], w[90], w[91]);
+ w[88] = X0; w[89] = X1; w[90] = X2; w[91] = X3;
+ sb4(w[92], w[93], w[94], w[95]);
+ w[92] = X0; w[93] = X1; w[94] = X2; w[95] = X3;
+ sb3(w[96], w[97], w[98], w[99]);
+ w[96] = X0; w[97] = X1; w[98] = X2; w[99] = X3;
+ sb2(w[100], w[101], w[102], w[103]);
+ w[100] = X0; w[101] = X1; w[102] = X2; w[103] = X3;
+ sb1(w[104], w[105], w[106], w[107]);
+ w[104] = X0; w[105] = X1; w[106] = X2; w[107] = X3;
+ sb0(w[108], w[109], w[110], w[111]);
+ w[108] = X0; w[109] = X1; w[110] = X2; w[111] = X3;
+ sb7(w[112], w[113], w[114], w[115]);
+ w[112] = X0; w[113] = X1; w[114] = X2; w[115] = X3;
+ sb6(w[116], w[117], w[118], w[119]);
+ w[116] = X0; w[117] = X1; w[118] = X2; w[119] = X3;
+ sb5(w[120], w[121], w[122], w[123]);
+ w[120] = X0; w[121] = X1; w[122] = X2; w[123] = X3;
+ sb4(w[124], w[125], w[126], w[127]);
+ w[124] = X0; w[125] = X1; w[126] = X2; w[127] = X3;
+ sb3(w[128], w[129], w[130], w[131]);
+ w[128] = X0; w[129] = X1; w[130] = X2; w[131] = X3;
+
+ return w;
+ }
+
+ private int rotateLeft(
+ int x,
+ int bits)
+ {
+ return (x << bits) | (x >>> -bits);
+ }
+
+ private int rotateRight(
+ int x,
+ int bits)
+ {
+ return (x >>> bits) | (x << -bits);
+ }
+
+ private int bytesToWord(
+ byte[] src,
+ int srcOff)
+ {
+ return (((src[srcOff] & 0xff) << 24) | ((src[srcOff + 1] & 0xff) << 16) |
+ ((src[srcOff + 2] & 0xff) << 8) | ((src[srcOff + 3] & 0xff)));
+ }
+
+ private void wordToBytes(
+ int word,
+ byte[] dst,
+ int dstOff)
+ {
+ dst[dstOff + 3] = (byte)(word);
+ dst[dstOff + 2] = (byte)(word >>> 8);
+ dst[dstOff + 1] = (byte)(word >>> 16);
+ dst[dstOff] = (byte)(word >>> 24);
+ }
+
+ /**
+ * Encrypt one block of plaintext.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ */
+ private void encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ X3 = bytesToWord(in, inOff);
+ X2 = bytesToWord(in, inOff + 4);
+ X1 = bytesToWord(in, inOff + 8);
+ X0 = bytesToWord(in, inOff + 12);
+
+ sb0(wKey[0] ^ X0, wKey[1] ^ X1, wKey[2] ^ X2, wKey[3] ^ X3); LT();
+ sb1(wKey[4] ^ X0, wKey[5] ^ X1, wKey[6] ^ X2, wKey[7] ^ X3); LT();
+ sb2(wKey[8] ^ X0, wKey[9] ^ X1, wKey[10] ^ X2, wKey[11] ^ X3); LT();
+ sb3(wKey[12] ^ X0, wKey[13] ^ X1, wKey[14] ^ X2, wKey[15] ^ X3); LT();
+ sb4(wKey[16] ^ X0, wKey[17] ^ X1, wKey[18] ^ X2, wKey[19] ^ X3); LT();
+ sb5(wKey[20] ^ X0, wKey[21] ^ X1, wKey[22] ^ X2, wKey[23] ^ X3); LT();
+ sb6(wKey[24] ^ X0, wKey[25] ^ X1, wKey[26] ^ X2, wKey[27] ^ X3); LT();
+ sb7(wKey[28] ^ X0, wKey[29] ^ X1, wKey[30] ^ X2, wKey[31] ^ X3); LT();
+ sb0(wKey[32] ^ X0, wKey[33] ^ X1, wKey[34] ^ X2, wKey[35] ^ X3); LT();
+ sb1(wKey[36] ^ X0, wKey[37] ^ X1, wKey[38] ^ X2, wKey[39] ^ X3); LT();
+ sb2(wKey[40] ^ X0, wKey[41] ^ X1, wKey[42] ^ X2, wKey[43] ^ X3); LT();
+ sb3(wKey[44] ^ X0, wKey[45] ^ X1, wKey[46] ^ X2, wKey[47] ^ X3); LT();
+ sb4(wKey[48] ^ X0, wKey[49] ^ X1, wKey[50] ^ X2, wKey[51] ^ X3); LT();
+ sb5(wKey[52] ^ X0, wKey[53] ^ X1, wKey[54] ^ X2, wKey[55] ^ X3); LT();
+ sb6(wKey[56] ^ X0, wKey[57] ^ X1, wKey[58] ^ X2, wKey[59] ^ X3); LT();
+ sb7(wKey[60] ^ X0, wKey[61] ^ X1, wKey[62] ^ X2, wKey[63] ^ X3); LT();
+ sb0(wKey[64] ^ X0, wKey[65] ^ X1, wKey[66] ^ X2, wKey[67] ^ X3); LT();
+ sb1(wKey[68] ^ X0, wKey[69] ^ X1, wKey[70] ^ X2, wKey[71] ^ X3); LT();
+ sb2(wKey[72] ^ X0, wKey[73] ^ X1, wKey[74] ^ X2, wKey[75] ^ X3); LT();
+ sb3(wKey[76] ^ X0, wKey[77] ^ X1, wKey[78] ^ X2, wKey[79] ^ X3); LT();
+ sb4(wKey[80] ^ X0, wKey[81] ^ X1, wKey[82] ^ X2, wKey[83] ^ X3); LT();
+ sb5(wKey[84] ^ X0, wKey[85] ^ X1, wKey[86] ^ X2, wKey[87] ^ X3); LT();
+ sb6(wKey[88] ^ X0, wKey[89] ^ X1, wKey[90] ^ X2, wKey[91] ^ X3); LT();
+ sb7(wKey[92] ^ X0, wKey[93] ^ X1, wKey[94] ^ X2, wKey[95] ^ X3); LT();
+ sb0(wKey[96] ^ X0, wKey[97] ^ X1, wKey[98] ^ X2, wKey[99] ^ X3); LT();
+ sb1(wKey[100] ^ X0, wKey[101] ^ X1, wKey[102] ^ X2, wKey[103] ^ X3); LT();
+ sb2(wKey[104] ^ X0, wKey[105] ^ X1, wKey[106] ^ X2, wKey[107] ^ X3); LT();
+ sb3(wKey[108] ^ X0, wKey[109] ^ X1, wKey[110] ^ X2, wKey[111] ^ X3); LT();
+ sb4(wKey[112] ^ X0, wKey[113] ^ X1, wKey[114] ^ X2, wKey[115] ^ X3); LT();
+ sb5(wKey[116] ^ X0, wKey[117] ^ X1, wKey[118] ^ X2, wKey[119] ^ X3); LT();
+ sb6(wKey[120] ^ X0, wKey[121] ^ X1, wKey[122] ^ X2, wKey[123] ^ X3); LT();
+ sb7(wKey[124] ^ X0, wKey[125] ^ X1, wKey[126] ^ X2, wKey[127] ^ X3);
+
+ wordToBytes(wKey[131] ^ X3, out, outOff);
+ wordToBytes(wKey[130] ^ X2, out, outOff + 4);
+ wordToBytes(wKey[129] ^ X1, out, outOff + 8);
+ wordToBytes(wKey[128] ^ X0, out, outOff + 12);
+ }
+
+ /**
+ * Decrypt one block of ciphertext.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ */
+ private void decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ X3 = wKey[131] ^ bytesToWord(in, inOff);
+ X2 = wKey[130] ^ bytesToWord(in, inOff + 4);
+ X1 = wKey[129] ^ bytesToWord(in, inOff + 8);
+ X0 = wKey[128] ^ bytesToWord(in, inOff + 12);
+
+ ib7(X0, X1, X2, X3);
+ X0 ^= wKey[124]; X1 ^= wKey[125]; X2 ^= wKey[126]; X3 ^= wKey[127];
+ inverseLT(); ib6(X0, X1, X2, X3);
+ X0 ^= wKey[120]; X1 ^= wKey[121]; X2 ^= wKey[122]; X3 ^= wKey[123];
+ inverseLT(); ib5(X0, X1, X2, X3);
+ X0 ^= wKey[116]; X1 ^= wKey[117]; X2 ^= wKey[118]; X3 ^= wKey[119];
+ inverseLT(); ib4(X0, X1, X2, X3);
+ X0 ^= wKey[112]; X1 ^= wKey[113]; X2 ^= wKey[114]; X3 ^= wKey[115];
+ inverseLT(); ib3(X0, X1, X2, X3);
+ X0 ^= wKey[108]; X1 ^= wKey[109]; X2 ^= wKey[110]; X3 ^= wKey[111];
+ inverseLT(); ib2(X0, X1, X2, X3);
+ X0 ^= wKey[104]; X1 ^= wKey[105]; X2 ^= wKey[106]; X3 ^= wKey[107];
+ inverseLT(); ib1(X0, X1, X2, X3);
+ X0 ^= wKey[100]; X1 ^= wKey[101]; X2 ^= wKey[102]; X3 ^= wKey[103];
+ inverseLT(); ib0(X0, X1, X2, X3);
+ X0 ^= wKey[96]; X1 ^= wKey[97]; X2 ^= wKey[98]; X3 ^= wKey[99];
+ inverseLT(); ib7(X0, X1, X2, X3);
+ X0 ^= wKey[92]; X1 ^= wKey[93]; X2 ^= wKey[94]; X3 ^= wKey[95];
+ inverseLT(); ib6(X0, X1, X2, X3);
+ X0 ^= wKey[88]; X1 ^= wKey[89]; X2 ^= wKey[90]; X3 ^= wKey[91];
+ inverseLT(); ib5(X0, X1, X2, X3);
+ X0 ^= wKey[84]; X1 ^= wKey[85]; X2 ^= wKey[86]; X3 ^= wKey[87];
+ inverseLT(); ib4(X0, X1, X2, X3);
+ X0 ^= wKey[80]; X1 ^= wKey[81]; X2 ^= wKey[82]; X3 ^= wKey[83];
+ inverseLT(); ib3(X0, X1, X2, X3);
+ X0 ^= wKey[76]; X1 ^= wKey[77]; X2 ^= wKey[78]; X3 ^= wKey[79];
+ inverseLT(); ib2(X0, X1, X2, X3);
+ X0 ^= wKey[72]; X1 ^= wKey[73]; X2 ^= wKey[74]; X3 ^= wKey[75];
+ inverseLT(); ib1(X0, X1, X2, X3);
+ X0 ^= wKey[68]; X1 ^= wKey[69]; X2 ^= wKey[70]; X3 ^= wKey[71];
+ inverseLT(); ib0(X0, X1, X2, X3);
+ X0 ^= wKey[64]; X1 ^= wKey[65]; X2 ^= wKey[66]; X3 ^= wKey[67];
+ inverseLT(); ib7(X0, X1, X2, X3);
+ X0 ^= wKey[60]; X1 ^= wKey[61]; X2 ^= wKey[62]; X3 ^= wKey[63];
+ inverseLT(); ib6(X0, X1, X2, X3);
+ X0 ^= wKey[56]; X1 ^= wKey[57]; X2 ^= wKey[58]; X3 ^= wKey[59];
+ inverseLT(); ib5(X0, X1, X2, X3);
+ X0 ^= wKey[52]; X1 ^= wKey[53]; X2 ^= wKey[54]; X3 ^= wKey[55];
+ inverseLT(); ib4(X0, X1, X2, X3);
+ X0 ^= wKey[48]; X1 ^= wKey[49]; X2 ^= wKey[50]; X3 ^= wKey[51];
+ inverseLT(); ib3(X0, X1, X2, X3);
+ X0 ^= wKey[44]; X1 ^= wKey[45]; X2 ^= wKey[46]; X3 ^= wKey[47];
+ inverseLT(); ib2(X0, X1, X2, X3);
+ X0 ^= wKey[40]; X1 ^= wKey[41]; X2 ^= wKey[42]; X3 ^= wKey[43];
+ inverseLT(); ib1(X0, X1, X2, X3);
+ X0 ^= wKey[36]; X1 ^= wKey[37]; X2 ^= wKey[38]; X3 ^= wKey[39];
+ inverseLT(); ib0(X0, X1, X2, X3);
+ X0 ^= wKey[32]; X1 ^= wKey[33]; X2 ^= wKey[34]; X3 ^= wKey[35];
+ inverseLT(); ib7(X0, X1, X2, X3);
+ X0 ^= wKey[28]; X1 ^= wKey[29]; X2 ^= wKey[30]; X3 ^= wKey[31];
+ inverseLT(); ib6(X0, X1, X2, X3);
+ X0 ^= wKey[24]; X1 ^= wKey[25]; X2 ^= wKey[26]; X3 ^= wKey[27];
+ inverseLT(); ib5(X0, X1, X2, X3);
+ X0 ^= wKey[20]; X1 ^= wKey[21]; X2 ^= wKey[22]; X3 ^= wKey[23];
+ inverseLT(); ib4(X0, X1, X2, X3);
+ X0 ^= wKey[16]; X1 ^= wKey[17]; X2 ^= wKey[18]; X3 ^= wKey[19];
+ inverseLT(); ib3(X0, X1, X2, X3);
+ X0 ^= wKey[12]; X1 ^= wKey[13]; X2 ^= wKey[14]; X3 ^= wKey[15];
+ inverseLT(); ib2(X0, X1, X2, X3);
+ X0 ^= wKey[8]; X1 ^= wKey[9]; X2 ^= wKey[10]; X3 ^= wKey[11];
+ inverseLT(); ib1(X0, X1, X2, X3);
+ X0 ^= wKey[4]; X1 ^= wKey[5]; X2 ^= wKey[6]; X3 ^= wKey[7];
+ inverseLT(); ib0(X0, X1, X2, X3);
+
+ wordToBytes(X3 ^ wKey[3], out, outOff);
+ wordToBytes(X2 ^ wKey[2], out, outOff + 4);
+ wordToBytes(X1 ^ wKey[1], out, outOff + 8);
+ wordToBytes(X0 ^ wKey[0], out, outOff + 12);
+ }
+
+ /**
+ * The sboxes below are based on the work of Brian Gladman and
+ * Sam Simpson, whose original notice appears below.
+ *
+ * For further details see:
+ * http://fp.gladman.plus.com/cryptography_technology/serpent/
+ */
+
+ /* Partially optimised Serpent S Box boolean functions derived */
+ /* using a recursive descent analyser but without a full search */
+ /* of all subtrees. This set of S boxes is the result of work */
+ /* by Sam Simpson and Brian Gladman using the spare time on a */
+ /* cluster of high capacity servers to search for S boxes with */
+ /* this customised search engine. There are now an average of */
+ /* 15.375 terms per S box. */
+ /* */
+ /* Copyright: Dr B. R Gladman (gladman@seven77.demon.co.uk) */
+ /* and Sam Simpson (s.simpson@mia.co.uk) */
+ /* 17th December 1998 */
+ /* */
+ /* We hereby give permission for information in this file to be */
+ /* used freely subject only to acknowledgement of its origin. */
+
+ /**
+ * S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms.
+ */
+ private void sb0(int a, int b, int c, int d)
+ {
+ int t1 = a ^ d;
+ int t3 = c ^ t1;
+ int t4 = b ^ t3;
+ X3 = (a & d) ^ t4;
+ int t7 = a ^ (b & t1);
+ X2 = t4 ^ (c | t7);
+ int t12 = X3 & (t3 ^ t7);
+ X1 = (~t3) ^ t12;
+ X0 = t12 ^ (~t7);
+ }
+
+ /**
+ * InvSO - {13, 3,11, 0,10, 6, 5,12, 1,14, 4, 7,15, 9, 8, 2 } - 15 terms.
+ */
+ private void ib0(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = a ^ b;
+ int t4 = d ^ (t1 | t2);
+ int t5 = c ^ t4;
+ X2 = t2 ^ t5;
+ int t8 = t1 ^ (d & t2);
+ X1 = t4 ^ (X2 & t8);
+ X3 = (a & t4) ^ (t5 | X1);
+ X0 = X3 ^ (t5 ^ t8);
+ }
+
+ /**
+ * S1 - {15,12, 2, 7, 9, 0, 5,10, 1,11,14, 8, 6,13, 3, 4 } - 14 terms.
+ */
+ private void sb1(int a, int b, int c, int d)
+ {
+ int t2 = b ^ (~a);
+ int t5 = c ^ (a | t2);
+ X2 = d ^ t5;
+ int t7 = b ^ (d | t2);
+ int t8 = t2 ^ X2;
+ X3 = t8 ^ (t5 & t7);
+ int t11 = t5 ^ t7;
+ X1 = X3 ^ t11;
+ X0 = t5 ^ (t8 & t11);
+ }
+
+ /**
+ * InvS1 - { 5, 8, 2,14,15, 6,12, 3,11, 4, 7, 9, 1,13,10, 0 } - 14 steps.
+ */
+ private void ib1(int a, int b, int c, int d)
+ {
+ int t1 = b ^ d;
+ int t3 = a ^ (b & t1);
+ int t4 = t1 ^ t3;
+ X3 = c ^ t4;
+ int t7 = b ^ (t1 & t3);
+ int t8 = X3 | t7;
+ X1 = t3 ^ t8;
+ int t10 = ~X1;
+ int t11 = X3 ^ t7;
+ X0 = t10 ^ t11;
+ X2 = t4 ^ (t10 | t11);
+ }
+
+ /**
+ * S2 - { 8, 6, 7, 9, 3,12,10,15,13, 1,14, 4, 0,11, 5, 2 } - 16 terms.
+ */
+ private void sb2(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = b ^ d;
+ int t3 = c & t1;
+ X0 = t2 ^ t3;
+ int t5 = c ^ t1;
+ int t6 = c ^ X0;
+ int t7 = b & t6;
+ X3 = t5 ^ t7;
+ X2 = a ^ ((d | t7) & (X0 | t5));
+ X1 = (t2 ^ X3) ^ (X2 ^ (d | t1));
+ }
+
+ /**
+ * InvS2 - {12, 9,15, 4,11,14, 1, 2, 0, 3, 6,13, 5, 8,10, 7 } - 16 steps.
+ */
+ private void ib2(int a, int b, int c, int d)
+ {
+ int t1 = b ^ d;
+ int t2 = ~t1;
+ int t3 = a ^ c;
+ int t4 = c ^ t1;
+ int t5 = b & t4;
+ X0 = t3 ^ t5;
+ int t7 = a | t2;
+ int t8 = d ^ t7;
+ int t9 = t3 | t8;
+ X3 = t1 ^ t9;
+ int t11 = ~t4;
+ int t12 = X0 | X3;
+ X1 = t11 ^ t12;
+ X2 = (d & t11) ^ (t3 ^ t12);
+ }
+
+ /**
+ * S3 - { 0,15,11, 8,12, 9, 6, 3,13, 1, 2, 4,10, 7, 5,14 } - 16 terms.
+ */
+ private void sb3(int a, int b, int c, int d)
+ {
+ int t1 = a ^ b;
+ int t2 = a & c;
+ int t3 = a | d;
+ int t4 = c ^ d;
+ int t5 = t1 & t3;
+ int t6 = t2 | t5;
+ X2 = t4 ^ t6;
+ int t8 = b ^ t3;
+ int t9 = t6 ^ t8;
+ int t10 = t4 & t9;
+ X0 = t1 ^ t10;
+ int t12 = X2 & X0;
+ X1 = t9 ^ t12;
+ X3 = (b | d) ^ (t4 ^ t12);
+ }
+
+ /**
+ * InvS3 - { 0, 9,10, 7,11,14, 6,13, 3, 5,12, 2, 4, 8,15, 1 } - 15 terms
+ */
+ private void ib3(int a, int b, int c, int d)
+ {
+ int t1 = a | b;
+ int t2 = b ^ c;
+ int t3 = b & t2;
+ int t4 = a ^ t3;
+ int t5 = c ^ t4;
+ int t6 = d | t4;
+ X0 = t2 ^ t6;
+ int t8 = t2 | t6;
+ int t9 = d ^ t8;
+ X2 = t5 ^ t9;
+ int t11 = t1 ^ t9;
+ int t12 = X0 & t11;
+ X3 = t4 ^ t12;
+ X1 = X3 ^ (X0 ^ t11);
+ }
+
+ /**
+ * S4 - { 1,15, 8, 3,12, 0,11, 6, 2, 5, 4,10, 9,14, 7,13 } - 15 terms.
+ */
+ private void sb4(int a, int b, int c, int d)
+ {
+ int t1 = a ^ d;
+ int t2 = d & t1;
+ int t3 = c ^ t2;
+ int t4 = b | t3;
+ X3 = t1 ^ t4;
+ int t6 = ~b;
+ int t7 = t1 | t6;
+ X0 = t3 ^ t7;
+ int t9 = a & X0;
+ int t10 = t1 ^ t6;
+ int t11 = t4 & t10;
+ X2 = t9 ^ t11;
+ X1 = (a ^ t3) ^ (t10 & X2);
+ }
+
+ /**
+ * InvS4 - { 5, 0, 8, 3,10, 9, 7,14, 2,12,11, 6, 4,15,13, 1 } - 15 terms.
+ */
+ private void ib4(int a, int b, int c, int d)
+ {
+ int t1 = c | d;
+ int t2 = a & t1;
+ int t3 = b ^ t2;
+ int t4 = a & t3;
+ int t5 = c ^ t4;
+ X1 = d ^ t5;
+ int t7 = ~a;
+ int t8 = t5 & X1;
+ X3 = t3 ^ t8;
+ int t10 = X1 | t7;
+ int t11 = d ^ t10;
+ X0 = X3 ^ t11;
+ X2 = (t3 & t11) ^ (X1 ^ t7);
+ }
+
+ /**
+ * S5 - {15, 5, 2,11, 4,10, 9,12, 0, 3,14, 8,13, 6, 7, 1 } - 16 terms.
+ */
+ private void sb5(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = a ^ b;
+ int t3 = a ^ d;
+ int t4 = c ^ t1;
+ int t5 = t2 | t3;
+ X0 = t4 ^ t5;
+ int t7 = d & X0;
+ int t8 = t2 ^ X0;
+ X1 = t7 ^ t8;
+ int t10 = t1 | X0;
+ int t11 = t2 | t7;
+ int t12 = t3 ^ t10;
+ X2 = t11 ^ t12;
+ X3 = (b ^ t7) ^ (X1 & t12);
+ }
+
+ /**
+ * InvS5 - { 8,15, 2, 9, 4, 1,13,14,11, 6, 5, 3, 7,12,10, 0 } - 16 terms.
+ */
+ private void ib5(int a, int b, int c, int d)
+ {
+ int t1 = ~c;
+ int t2 = b & t1;
+ int t3 = d ^ t2;
+ int t4 = a & t3;
+ int t5 = b ^ t1;
+ X3 = t4 ^ t5;
+ int t7 = b | X3;
+ int t8 = a & t7;
+ X1 = t3 ^ t8;
+ int t10 = a | d;
+ int t11 = t1 ^ t7;
+ X0 = t10 ^ t11;
+ X2 = (b & t10) ^ (t4 | (a ^ c));
+ }
+
+ /**
+ * S6 - { 7, 2,12, 5, 8, 4, 6,11,14, 9, 1,15,13, 3,10, 0 } - 15 terms.
+ */
+ private void sb6(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = a ^ d;
+ int t3 = b ^ t2;
+ int t4 = t1 | t2;
+ int t5 = c ^ t4;
+ X1 = b ^ t5;
+ int t7 = t2 | X1;
+ int t8 = d ^ t7;
+ int t9 = t5 & t8;
+ X2 = t3 ^ t9;
+ int t11 = t5 ^ t8;
+ X0 = X2 ^ t11;
+ X3 = (~t5) ^ (t3 & t11);
+ }
+
+ /**
+ * InvS6 - {15,10, 1,13, 5, 3, 6, 0, 4, 9,14, 7, 2,12, 8,11 } - 15 terms.
+ */
+ private void ib6(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = a ^ b;
+ int t3 = c ^ t2;
+ int t4 = c | t1;
+ int t5 = d ^ t4;
+ X1 = t3 ^ t5;
+ int t7 = t3 & t5;
+ int t8 = t2 ^ t7;
+ int t9 = b | t8;
+ X3 = t5 ^ t9;
+ int t11 = b | X3;
+ X0 = t8 ^ t11;
+ X2 = (d & t1) ^ (t3 ^ t11);
+ }
+
+ /**
+ * S7 - { 1,13,15, 0,14, 8, 2,11, 7, 4,12,10, 9, 3, 5, 6 } - 16 terms.
+ */
+ private void sb7(int a, int b, int c, int d)
+ {
+ int t1 = b ^ c;
+ int t2 = c & t1;
+ int t3 = d ^ t2;
+ int t4 = a ^ t3;
+ int t5 = d | t1;
+ int t6 = t4 & t5;
+ X1 = b ^ t6;
+ int t8 = t3 | X1;
+ int t9 = a & t4;
+ X3 = t1 ^ t9;
+ int t11 = t4 ^ t8;
+ int t12 = X3 & t11;
+ X2 = t3 ^ t12;
+ X0 = (~t11) ^ (X3 & X2);
+ }
+
+ /**
+ * InvS7 - { 3, 0, 6,13, 9,14,15, 8, 5,12,11, 7,10, 1, 4, 2 } - 17 terms.
+ */
+ private void ib7(int a, int b, int c, int d)
+ {
+ int t3 = c | (a & b);
+ int t4 = d & (a | b);
+ X3 = t3 ^ t4;
+ int t6 = ~d;
+ int t7 = b ^ t4;
+ int t9 = t7 | (X3 ^ t6);
+ X1 = a ^ t9;
+ X0 = (c ^ t7) ^ (d | X1);
+ X2 = (t3 ^ X1) ^ (X0 ^ (a & X3));
+ }
+
+ /**
+ * Apply the linear transformation to the register set.
+ */
+ private void LT()
+ {
+ int x0 = rotateLeft(X0, 13);
+ int x2 = rotateLeft(X2, 3);
+ int x1 = X1 ^ x0 ^ x2 ;
+ int x3 = X3 ^ x2 ^ x0 << 3;
+
+ X1 = rotateLeft(x1, 1);
+ X3 = rotateLeft(x3, 7);
+ X0 = rotateLeft(x0 ^ X1 ^ X3, 5);
+ X2 = rotateLeft(x2 ^ X3 ^ (X1 << 7), 22);
+ }
+
+ /**
+ * Apply the inverse of the linear transformation to the register set.
+ */
+ private void inverseLT()
+ {
+ int x2 = rotateRight(X2, 22) ^ X3 ^ (X1 << 7);
+ int x0 = rotateRight(X0, 5) ^ X1 ^ X3;
+ int x3 = rotateRight(X3, 7);
+ int x1 = rotateRight(X1, 1);
+ X3 = x3 ^ x2 ^ x0 << 3;
+ X1 = x1 ^ x0 ^ x2;
+ X2 = rotateRight(x2, 3);
+ X0 = rotateRight(x0, 13);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/SkipjackEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/SkipjackEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/SkipjackEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/SkipjackEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,259 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * a class that provides a basic SKIPJACK engine.
+ */
+public class SkipjackEngine
+ implements BlockCipher
+{
+ static final int BLOCK_SIZE = 8;
+
+ static short ftable[] =
+ {
+ 0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4, 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,
+ 0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e, 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,
+ 0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68, 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,
+ 0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19, 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,
+ 0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b, 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,
+ 0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0, 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,
+ 0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69, 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,
+ 0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20, 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,
+ 0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43, 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,
+ 0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa, 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,
+ 0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87, 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,
+ 0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b, 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,
+ 0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0, 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,
+ 0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1, 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,
+ 0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5, 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,
+ 0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3, 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46
+ };
+
+ private int[] key0, key1, key2, key3;
+ private boolean encrypting;
+
+ /**
+ * initialise a SKIPJACK cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to SKIPJACK init - " + params.getClass().getName());
+ }
+
+ byte[] keyBytes = ((KeyParameter)params).getKey();
+
+ this.encrypting = encrypting;
+ this.key0 = new int[32];
+ this.key1 = new int[32];
+ this.key2 = new int[32];
+ this.key3 = new int[32];
+
+ //
+ // expand the key to 128 bytes in 4 parts (saving us a modulo, multiply
+ // and an addition).
+ //
+ for (int i = 0; i < 32; i ++)
+ {
+ key0[i] = keyBytes[(i * 4) % 10] & 0xff;
+ key1[i] = keyBytes[(i * 4 + 1) % 10] & 0xff;
+ key2[i] = keyBytes[(i * 4 + 2) % 10] & 0xff;
+ key3[i] = keyBytes[(i * 4 + 3) % 10] & 0xff;
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return "SKIPJACK";
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (key1 == null)
+ {
+ throw new IllegalStateException("SKIPJACK engine not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (encrypting)
+ {
+ encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ decryptBlock(in, inOff, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * The G permutation
+ */
+ private int g(
+ int k,
+ int w)
+ {
+ int g1, g2, g3, g4, g5, g6;
+
+ g1 = (w >> 8) & 0xff;
+ g2 = w & 0xff;
+
+ g3 = ftable[g2 ^ key0[k]] ^ g1;
+ g4 = ftable[g3 ^ key1[k]] ^ g2;
+ g5 = ftable[g4 ^ key2[k]] ^ g3;
+ g6 = ftable[g5 ^ key3[k]] ^ g4;
+
+ return ((g5 << 8) + g6);
+ }
+
+ public int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int w1 = (in[inOff + 0] << 8) + (in[inOff + 1] & 0xff);
+ int w2 = (in[inOff + 2] << 8) + (in[inOff + 3] & 0xff);
+ int w3 = (in[inOff + 4] << 8) + (in[inOff + 5] & 0xff);
+ int w4 = (in[inOff + 6] << 8) + (in[inOff + 7] & 0xff);
+
+ int k = 0;
+
+ for (int t = 0; t < 2; t++)
+ {
+ for(int i = 0; i < 8; i++)
+ {
+ int tmp = w4;
+ w4 = w3;
+ w3 = w2;
+ w2 = g(k, w1);
+ w1 = w2 ^ tmp ^ (k + 1);
+ k++;
+ }
+
+ for(int i = 0; i < 8; i++)
+ {
+ int tmp = w4;
+ w4 = w3;
+ w3 = w1 ^ w2 ^ (k + 1);
+ w2 = g(k, w1);
+ w1 = tmp;
+ k++;
+ }
+ }
+
+ out[outOff + 0] = (byte)((w1 >> 8));
+ out[outOff + 1] = (byte)(w1);
+ out[outOff + 2] = (byte)((w2 >> 8));
+ out[outOff + 3] = (byte)(w2);
+ out[outOff + 4] = (byte)((w3 >> 8));
+ out[outOff + 5] = (byte)(w3);
+ out[outOff + 6] = (byte)((w4 >> 8));
+ out[outOff + 7] = (byte)(w4);
+
+ return BLOCK_SIZE;
+ }
+
+ /**
+ * the inverse of the G permutation.
+ */
+ private int h(
+ int k,
+ int w)
+ {
+ int h1, h2, h3, h4, h5, h6;
+
+ h1 = w & 0xff;
+ h2 = (w >> 8) & 0xff;
+
+ h3 = ftable[h2 ^ key3[k]] ^ h1;
+ h4 = ftable[h3 ^ key2[k]] ^ h2;
+ h5 = ftable[h4 ^ key1[k]] ^ h3;
+ h6 = ftable[h5 ^ key0[k]] ^ h4;
+
+ return ((h6 << 8) + h5);
+ }
+
+ public int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int w2 = (in[inOff + 0] << 8) + (in[inOff + 1] & 0xff);
+ int w1 = (in[inOff + 2] << 8) + (in[inOff + 3] & 0xff);
+ int w4 = (in[inOff + 4] << 8) + (in[inOff + 5] & 0xff);
+ int w3 = (in[inOff + 6] << 8) + (in[inOff + 7] & 0xff);
+
+ int k = 31;
+
+ for (int t = 0; t < 2; t++)
+ {
+ for(int i = 0; i < 8; i++)
+ {
+ int tmp = w4;
+ w4 = w3;
+ w3 = w2;
+ w2 = h(k, w1);
+ w1 = w2 ^ tmp ^ (k + 1);
+ k--;
+ }
+
+ for(int i = 0; i < 8; i++)
+ {
+ int tmp = w4;
+ w4 = w3;
+ w3 = w1 ^ w2 ^ (k + 1);
+ w2 = h(k, w1);
+ w1 = tmp;
+ k--;
+ }
+ }
+
+ out[outOff + 0] = (byte)((w2 >> 8));
+ out[outOff + 1] = (byte)(w2);
+ out[outOff + 2] = (byte)((w1 >> 8));
+ out[outOff + 3] = (byte)(w1);
+ out[outOff + 4] = (byte)((w4 >> 8));
+ out[outOff + 5] = (byte)(w4);
+ out[outOff + 6] = (byte)((w3 >> 8));
+ out[outOff + 7] = (byte)(w3);
+
+ return BLOCK_SIZE;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/TEAEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/TEAEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/TEAEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/TEAEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,178 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * An TEA engine.
+ */
+public class TEAEngine
+ implements BlockCipher
+{
+ private static final int rounds = 32,
+ block_size = 8,
+// key_size = 16,
+ delta = 0x9E3779B9,
+ d_sum = 0xC6EF3720; // sum on decrypt
+ /*
+ * the expanded key array of 4 subkeys
+ */
+ private int _a, _b, _c, _d;
+ private boolean _initialised;
+ private boolean _forEncryption;
+
+ /**
+ * Create an instance of the TEA encryption algorithm
+ * and set some defaults
+ */
+ public TEAEngine()
+ {
+ _initialised = false;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "TEA";
+ }
+
+ public int getBlockSize()
+ {
+ return block_size;
+ }
+
+ /**
+ * initialise
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to TEA init - " + params.getClass().getName());
+ }
+
+ _forEncryption = forEncryption;
+ _initialised = true;
+
+ KeyParameter p = (KeyParameter)params;
+
+ setKey(p.getKey());
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (!_initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ if ((inOff + block_size) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + block_size) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ return (_forEncryption) ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ *
+ * @param key the key to be used
+ */
+ private void setKey(
+ byte[] key)
+ {
+ _a = bytesToInt(key, 0);
+ _b = bytesToInt(key, 4);
+ _c = bytesToInt(key, 8);
+ _d = bytesToInt(key, 12);
+ }
+
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // Pack bytes into integers
+ int v0 = bytesToInt(in, inOff);
+ int v1 = bytesToInt(in, inOff + 4);
+
+ int sum = 0;
+
+ for (int i = 0; i != rounds; i++)
+ {
+ sum += delta;
+ v0 += ((v1 << 4) + _a) ^ (v1 + sum) ^ ((v1 >>> 5) + _b);
+ v1 += ((v0 << 4) + _c) ^ (v0 + sum) ^ ((v0 >>> 5) + _d);
+ }
+
+ unpackInt(v0, out, outOff);
+ unpackInt(v1, out, outOff + 4);
+
+ return block_size;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // Pack bytes into integers
+ int v0 = bytesToInt(in, inOff);
+ int v1 = bytesToInt(in, inOff + 4);
+
+ int sum = d_sum;
+
+ for (int i = 0; i != rounds; i++)
+ {
+ v1 -= ((v0 << 4) + _c) ^ (v0 + sum) ^ ((v0 >>> 5) + _d);
+ v0 -= ((v1 << 4) + _a) ^ (v1 + sum) ^ ((v1 >>> 5) + _b);
+ sum -= delta;
+ }
+
+ unpackInt(v0, out, outOff);
+ unpackInt(v1, out, outOff + 4);
+
+ return block_size;
+ }
+
+ private int bytesToInt(byte[] in, int inOff)
+ {
+ return ((in[inOff++]) << 24) |
+ ((in[inOff++] & 255) << 16) |
+ ((in[inOff++] & 255) << 8) |
+ ((in[inOff] & 255));
+ }
+
+ private void unpackInt(int v, byte[] out, int outOff)
+ {
+ out[outOff++] = (byte)(v >>> 24);
+ out[outOff++] = (byte)(v >>> 16);
+ out[outOff++] = (byte)(v >>> 8);
+ out[outOff ] = (byte)v;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/TwofishEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/TwofishEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/TwofishEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/TwofishEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,679 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * A class that provides Twofish encryption operations.
+ *
+ * This Java implementation is based on the Java reference
+ * implementation provided by Bruce Schneier and developed
+ * by Raif S. Naffah.
+ */
+public final class TwofishEngine
+ implements BlockCipher
+{
+ private static final byte[][] P = {
+ { // p0
+ (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
+ (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
+ (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
+ (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
+ (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
+ (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
+ (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
+ (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
+ (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
+ (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
+ (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
+ (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
+ (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
+ (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
+ (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
+ (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
+ (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
+ (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
+ (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
+ (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
+ (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
+ (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
+ (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
+ (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
+ (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
+ (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
+ (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
+ (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
+ (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
+ (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
+ (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
+ (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
+ (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
+ (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
+ (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
+ (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
+ (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
+ (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
+ (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
+ (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
+ (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
+ (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
+ (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
+ (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
+ (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
+ (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
+ (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
+ (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
+ (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
+ (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
+ (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
+ (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
+ (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
+ (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
+ (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
+ (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
+ (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
+ (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
+ (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
+ (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
+ (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
+ (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
+ (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
+ (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0 },
+ { // p1
+ (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
+ (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
+ (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
+ (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
+ (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
+ (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
+ (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
+ (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
+ (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
+ (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
+ (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
+ (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
+ (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
+ (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
+ (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
+ (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
+ (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
+ (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
+ (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
+ (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
+ (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
+ (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
+ (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
+ (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
+ (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
+ (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
+ (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
+ (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
+ (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
+ (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
+ (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
+ (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
+ (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
+ (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
+ (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
+ (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
+ (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
+ (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
+ (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
+ (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
+ (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
+ (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
+ (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
+ (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
+ (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
+ (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
+ (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
+ (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
+ (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
+ (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
+ (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
+ (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
+ (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
+ (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
+ (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
+ (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
+ (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
+ (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
+ (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
+ (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
+ (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
+ (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
+ (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
+ (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91 }
+ };
+
+ /**
+ * Define the fixed p0/p1 permutations used in keyed S-box lookup.
+ * By changing the following constant definitions, the S-boxes will
+ * automatically get changed in the Twofish engine.
+ */
+ private static final int P_00 = 1;
+ private static final int P_01 = 0;
+ private static final int P_02 = 0;
+ private static final int P_03 = P_01 ^ 1;
+ private static final int P_04 = 1;
+
+ private static final int P_10 = 0;
+ private static final int P_11 = 0;
+ private static final int P_12 = 1;
+ private static final int P_13 = P_11 ^ 1;
+ private static final int P_14 = 0;
+
+ private static final int P_20 = 1;
+ private static final int P_21 = 1;
+ private static final int P_22 = 0;
+ private static final int P_23 = P_21 ^ 1;
+ private static final int P_24 = 0;
+
+ private static final int P_30 = 0;
+ private static final int P_31 = 1;
+ private static final int P_32 = 1;
+ private static final int P_33 = P_31 ^ 1;
+ private static final int P_34 = 1;
+
+ /* Primitive polynomial for GF(256) */
+ private static final int GF256_FDBK = 0x169;
+ private static final int GF256_FDBK_2 = GF256_FDBK / 2;
+ private static final int GF256_FDBK_4 = GF256_FDBK / 4;
+
+ private static final int RS_GF_FDBK = 0x14D; // field generator
+
+ //====================================
+ // Useful constants
+ //====================================
+
+ private static final int ROUNDS = 16;
+ private static final int MAX_ROUNDS = 16; // bytes = 128 bits
+ private static final int BLOCK_SIZE = 16; // bytes = 128 bits
+ private static final int MAX_KEY_BITS = 256;
+
+ private static final int INPUT_WHITEN=0;
+ private static final int OUTPUT_WHITEN=INPUT_WHITEN+BLOCK_SIZE/4; // 4
+ private static final int ROUND_SUBKEYS=OUTPUT_WHITEN+BLOCK_SIZE/4;// 8
+
+ private static final int TOTAL_SUBKEYS=ROUND_SUBKEYS+2*MAX_ROUNDS;// 40
+
+ private static final int SK_STEP = 0x02020202;
+ private static final int SK_BUMP = 0x01010101;
+ private static final int SK_ROTL = 9;
+
+ private boolean encrypting = false;
+
+ private int[] gMDS0 = new int[MAX_KEY_BITS];
+ private int[] gMDS1 = new int[MAX_KEY_BITS];
+ private int[] gMDS2 = new int[MAX_KEY_BITS];
+ private int[] gMDS3 = new int[MAX_KEY_BITS];
+
+ /**
+ * gSubKeys[] and gSBox[] are eventually used in the
+ * encryption and decryption methods.
+ */
+ private int[] gSubKeys;
+ private int[] gSBox;
+
+ private int k64Cnt = 0;
+
+ private byte[] workingKey = null;
+
+ public TwofishEngine()
+ {
+ // calculate the MDS matrix
+ int[] m1 = new int[2];
+ int[] mX = new int[2];
+ int[] mY = new int[2];
+ int j;
+
+ for (int i=0; i< MAX_KEY_BITS ; i++)
+ {
+ j = P[0][i] & 0xff;
+ m1[0] = j;
+ mX[0] = Mx_X(j) & 0xff;
+ mY[0] = Mx_Y(j) & 0xff;
+
+ j = P[1][i] & 0xff;
+ m1[1] = j;
+ mX[1] = Mx_X(j) & 0xff;
+ mY[1] = Mx_Y(j) & 0xff;
+
+ gMDS0[i] = m1[P_00] | mX[P_00] << 8 |
+ mY[P_00] << 16 | mY[P_00] << 24;
+
+ gMDS1[i] = mY[P_10] | mY[P_10] << 8 |
+ mX[P_10] << 16 | m1[P_10] << 24;
+
+ gMDS2[i] = mX[P_20] | mY[P_20] << 8 |
+ m1[P_20] << 16 | mY[P_20] << 24;
+
+ gMDS3[i] = mX[P_30] | m1[P_30] << 8 |
+ mY[P_30] << 16 | mX[P_30] << 24;
+ }
+ }
+
+ /**
+ * initialise a Twofish cipher.
+ *
+ * @param encrypting whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ {
+ if (params instanceof KeyParameter)
+ {
+ this.encrypting = encrypting;
+ this.workingKey = ((KeyParameter)params).getKey();
+ this.k64Cnt = (this.workingKey.length / 8); // pre-padded ?
+ setKey(this.workingKey);
+
+ return;
+ }
+
+ throw new IllegalArgumentException("invalid parameter passed to Twofish init - " + params.getClass().getName());
+ }
+
+ public String getAlgorithmName()
+ {
+ return "Twofish";
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (workingKey == null)
+ {
+ throw new IllegalStateException("Twofish not initialised");
+ }
+
+ if ((inOff + BLOCK_SIZE) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + BLOCK_SIZE) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (encrypting)
+ {
+ encryptBlock(in, inOff, out, outOff);
+ }
+ else
+ {
+ decryptBlock(in, inOff, out, outOff);
+ }
+
+ return BLOCK_SIZE;
+ }
+
+ public void reset()
+ {
+ if (this.workingKey != null)
+ {
+ setKey(this.workingKey);
+ }
+ }
+
+ public int getBlockSize()
+ {
+ return BLOCK_SIZE;
+ }
+
+ //==================================
+ // Private Implementation
+ //==================================
+
+ private void setKey(byte[] key)
+ {
+ int[] k32e = new int[MAX_KEY_BITS/64]; // 4
+ int[] k32o = new int[MAX_KEY_BITS/64]; // 4
+
+ int[] sBoxKeys = new int[MAX_KEY_BITS/64]; // 4
+ gSubKeys = new int[TOTAL_SUBKEYS];
+
+ if (k64Cnt < 1)
+ {
+ throw new IllegalArgumentException("Key size less than 64 bits");
+ }
+
+ if (k64Cnt > 4)
+ {
+ throw new IllegalArgumentException("Key size larger than 256 bits");
+ }
+
+ /*
+ * k64Cnt is the number of 8 byte blocks (64 chunks)
+ * that are in the input key. The input key is a
+ * maximum of 32 bytes (256 bits), so the range
+ * for k64Cnt is 1..4
+ */
+ for (int i=0; i>> 24;
+ A += B;
+ gSubKeys[i*2] = A;
+ A += B;
+ gSubKeys[i*2 + 1] = A << SK_ROTL | A >>> (32-SK_ROTL);
+ }
+
+ /*
+ * fully expand the table for speed
+ */
+ int k0 = sBoxKeys[0];
+ int k1 = sBoxKeys[1];
+ int k2 = sBoxKeys[2];
+ int k3 = sBoxKeys[3];
+ int b0, b1, b2, b3;
+ gSBox = new int[4*MAX_KEY_BITS];
+ for (int i=0; i>>1 | x2 << 31;
+ x3 = (x3 << 1 | x3 >>> 31) ^ (t0 + 2*t1 + gSubKeys[k++]);
+
+ t0 = Fe32_0(x2);
+ t1 = Fe32_3(x3);
+ x0 ^= t0 + t1 + gSubKeys[k++];
+ x0 = x0 >>>1 | x0 << 31;
+ x1 = (x1 << 1 | x1 >>> 31) ^ (t0 + 2*t1 + gSubKeys[k++]);
+ }
+
+ Bits32ToBytes(x2 ^ gSubKeys[OUTPUT_WHITEN], dst, dstIndex);
+ Bits32ToBytes(x3 ^ gSubKeys[OUTPUT_WHITEN + 1], dst, dstIndex + 4);
+ Bits32ToBytes(x0 ^ gSubKeys[OUTPUT_WHITEN + 2], dst, dstIndex + 8);
+ Bits32ToBytes(x1 ^ gSubKeys[OUTPUT_WHITEN + 3], dst, dstIndex + 12);
+ }
+
+ /**
+ * Decrypt the given input starting at the given offset and place
+ * the result in the provided buffer starting at the given offset.
+ * The input will be an exact multiple of our blocksize.
+ */
+ private void decryptBlock(
+ byte[] src,
+ int srcIndex,
+ byte[] dst,
+ int dstIndex)
+ {
+ int x2 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[OUTPUT_WHITEN];
+ int x3 = BytesTo32Bits(src, srcIndex+4) ^ gSubKeys[OUTPUT_WHITEN + 1];
+ int x0 = BytesTo32Bits(src, srcIndex+8) ^ gSubKeys[OUTPUT_WHITEN + 2];
+ int x1 = BytesTo32Bits(src, srcIndex+12) ^ gSubKeys[OUTPUT_WHITEN + 3];
+
+ int k = ROUND_SUBKEYS + 2 * ROUNDS -1 ;
+ int t0, t1;
+ for (int r = 0; r< ROUNDS ; r +=2)
+ {
+ t0 = Fe32_0(x2);
+ t1 = Fe32_3(x3);
+ x1 ^= t0 + 2*t1 + gSubKeys[k--];
+ x0 = (x0 << 1 | x0 >>> 31) ^ (t0 + t1 + gSubKeys[k--]);
+ x1 = x1 >>>1 | x1 << 31;
+
+ t0 = Fe32_0(x0);
+ t1 = Fe32_3(x1);
+ x3 ^= t0 + 2*t1 + gSubKeys[k--];
+ x2 = (x2 << 1 | x2 >>> 31) ^ (t0 + t1 + gSubKeys[k--]);
+ x3 = x3 >>>1 | x3 << 31;
+ }
+
+ Bits32ToBytes(x0 ^ gSubKeys[INPUT_WHITEN], dst, dstIndex);
+ Bits32ToBytes(x1 ^ gSubKeys[INPUT_WHITEN + 1], dst, dstIndex + 4);
+ Bits32ToBytes(x2 ^ gSubKeys[INPUT_WHITEN + 2], dst, dstIndex + 8);
+ Bits32ToBytes(x3 ^ gSubKeys[INPUT_WHITEN + 3], dst, dstIndex + 12);
+ }
+
+ /*
+ * TODO: This can be optimised and made cleaner by combining
+ * the functionality in this function and applying it appropriately
+ * to the creation of the subkeys during key setup.
+ */
+ private int F32(int x, int[] k32)
+ {
+ int b0 = b0(x);
+ int b1 = b1(x);
+ int b2 = b2(x);
+ int b3 = b3(x);
+ int k0 = k32[0];
+ int k1 = k32[1];
+ int k2 = k32[2];
+ int k3 = k32[3];
+
+ int result = 0;
+ switch (k64Cnt & 3)
+ {
+ case 1:
+ result = gMDS0[(P[P_01][b0] & 0xff) ^ b0(k0)] ^
+ gMDS1[(P[P_11][b1] & 0xff) ^ b1(k0)] ^
+ gMDS2[(P[P_21][b2] & 0xff) ^ b2(k0)] ^
+ gMDS3[(P[P_31][b3] & 0xff) ^ b3(k0)];
+ break;
+ case 0: /* 256 bits of key */
+ b0 = (P[P_04][b0] & 0xff) ^ b0(k3);
+ b1 = (P[P_14][b1] & 0xff) ^ b1(k3);
+ b2 = (P[P_24][b2] & 0xff) ^ b2(k3);
+ b3 = (P[P_34][b3] & 0xff) ^ b3(k3);
+ case 3:
+ b0 = (P[P_03][b0] & 0xff) ^ b0(k2);
+ b1 = (P[P_13][b1] & 0xff) ^ b1(k2);
+ b2 = (P[P_23][b2] & 0xff) ^ b2(k2);
+ b3 = (P[P_33][b3] & 0xff) ^ b3(k2);
+ case 2:
+ result =
+ gMDS0[(P[P_01][(P[P_02][b0]&0xff)^b0(k1)]&0xff)^b0(k0)] ^
+ gMDS1[(P[P_11][(P[P_12][b1]&0xff)^b1(k1)]&0xff)^b1(k0)] ^
+ gMDS2[(P[P_21][(P[P_22][b2]&0xff)^b2(k1)]&0xff)^b2(k0)] ^
+ gMDS3[(P[P_31][(P[P_32][b3]&0xff)^b3(k1)]&0xff)^b3(k0)];
+ break;
+ }
+ return result;
+ }
+
+ /**
+ * Use (12, 8) Reed-Solomon code over GF(256) to produce
+ * a key S-box 32-bit entity from 2 key material 32-bit
+ * entities.
+ *
+ * @param k0 first 32-bit entity
+ * @param k1 second 32-bit entity
+ * @return Remainder polynomial generated using RS code
+ */
+ private int RS_MDS_Encode(int k0, int k1)
+ {
+ int r = k1;
+ for (int i = 0 ; i < 4 ; i++) // shift 1 byte at a time
+ {
+ r = RS_rem(r);
+ }
+ r ^= k0;
+ for (int i=0 ; i < 4 ; i++)
+ {
+ r = RS_rem(r);
+ }
+
+ return r;
+ }
+
+ /**
+ * Reed-Solomon code parameters: (12,8) reversible code:
+ *
+ * g(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
+ *
+ * where a = primitive root of field generator 0x14D
+ */
+ private int RS_rem(int x)
+ {
+ int b = (x >>> 24) & 0xff;
+ int g2 = ((b << 1) ^
+ ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff;
+ int g3 = ((b >>> 1) ^
+ ((b & 0x01) != 0 ? (RS_GF_FDBK >>> 1) : 0)) ^ g2 ;
+ return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b);
+ }
+
+ private int LFSR1(int x)
+ {
+ return (x >> 1) ^
+ (((x & 0x01) != 0) ? GF256_FDBK_2 : 0);
+ }
+
+ private int LFSR2(int x)
+ {
+ return (x >> 2) ^
+ (((x & 0x02) != 0) ? GF256_FDBK_2 : 0) ^
+ (((x & 0x01) != 0) ? GF256_FDBK_4 : 0);
+ }
+
+ private int Mx_X(int x)
+ {
+ return x ^ LFSR2(x);
+ } // 5B
+
+ private int Mx_Y(int x)
+ {
+ return x ^ LFSR1(x) ^ LFSR2(x);
+ } // EF
+
+ private int b0(int x)
+ {
+ return x & 0xff;
+ }
+
+ private int b1(int x)
+ {
+ return (x >>> 8) & 0xff;
+ }
+
+ private int b2(int x)
+ {
+ return (x >>> 16) & 0xff;
+ }
+
+ private int b3(int x)
+ {
+ return (x >>> 24) & 0xff;
+ }
+
+ private int Fe32_0(int x)
+ {
+ return gSBox[ 0x000 + 2*(x & 0xff) ] ^
+ gSBox[ 0x001 + 2*((x >>> 8) & 0xff) ] ^
+ gSBox[ 0x200 + 2*((x >>> 16) & 0xff) ] ^
+ gSBox[ 0x201 + 2*((x >>> 24) & 0xff) ];
+ }
+
+ private int Fe32_3(int x)
+ {
+ return gSBox[ 0x000 + 2*((x >>> 24) & 0xff) ] ^
+ gSBox[ 0x001 + 2*(x & 0xff) ] ^
+ gSBox[ 0x200 + 2*((x >>> 8) & 0xff) ] ^
+ gSBox[ 0x201 + 2*((x >>> 16) & 0xff) ];
+ }
+
+ private int BytesTo32Bits(byte[] b, int p)
+ {
+ return ((b[p] & 0xff)) |
+ ((b[p+1] & 0xff) << 8) |
+ ((b[p+2] & 0xff) << 16) |
+ ((b[p+3] & 0xff) << 24);
+ }
+
+ private void Bits32ToBytes(int in, byte[] b, int offset)
+ {
+ b[offset] = (byte)in;
+ b[offset + 1] = (byte)(in >> 8);
+ b[offset + 2] = (byte)(in >> 16);
+ b[offset + 3] = (byte)(in >> 24);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/VMPCEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/VMPCEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/VMPCEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/VMPCEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,138 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.StreamCipher;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+public class VMPCEngine implements StreamCipher
+{
+ /*
+ * variables to hold the state of the VMPC engine during encryption and
+ * decryption
+ */
+ protected byte n = 0;
+ protected byte[] P = null;
+ protected byte s = 0;
+
+ protected byte[] workingIV;
+ protected byte[] workingKey;
+
+ public String getAlgorithmName()
+ {
+ return "VMPC";
+ }
+
+ /**
+ * initialise a VMPC cipher.
+ *
+ * @param forEncryption
+ * whether or not we are for encryption.
+ * @param params
+ * the parameters required to set up the cipher.
+ * @exception IllegalArgumentException
+ * if the params argument is inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ {
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException(
+ "VMPC init parameters must include an IV");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV) params;
+ KeyParameter key = (KeyParameter) ivParams.getParameters();
+
+ if (!(ivParams.getParameters() instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException(
+ "VMPC init parameters must include a key");
+ }
+
+ this.workingIV = ivParams.getIV();
+
+ if (workingIV == null || workingIV.length < 1 || workingIV.length > 768)
+ {
+ throw new IllegalArgumentException("VMPC requires 1 to 768 bytes of IV");
+ }
+
+ this.workingKey = key.getKey();
+
+ initKey(this.workingKey, this.workingIV);
+ }
+
+ protected void initKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ s = 0;
+ P = new byte[256];
+ for (int i = 0; i < 256; i++)
+ {
+ P[i] = (byte) i;
+ }
+
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+ n = 0;
+ }
+
+ public void processBytes(byte[] in, int inOff, int len, byte[] out,
+ int outOff)
+ {
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + len) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ s = P[(s + P[n & 0xff]) & 0xff];
+ byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+ // encryption
+ byte temp = P[n & 0xff];
+ P[n & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ n = (byte) ((n + 1) & 0xff);
+
+ // xor
+ out[i + outOff] = (byte) (in[i + inOff] ^ z);
+ }
+ }
+
+ public void reset()
+ {
+ initKey(this.workingKey, this.workingIV);
+ }
+
+ public byte returnByte(byte in)
+ {
+ s = P[(s + P[n & 0xff]) & 0xff];
+ byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+ // encryption
+ byte temp = P[n & 0xff];
+ P[n & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ n = (byte) ((n + 1) & 0xff);
+
+ // xor
+ return (byte) (in ^ z);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/VMPCKSA3Engine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/VMPCKSA3Engine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/VMPCKSA3Engine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/VMPCKSA3Engine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,45 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+public class VMPCKSA3Engine extends VMPCEngine
+{
+ public String getAlgorithmName()
+ {
+ return "VMPC-KSA3";
+ }
+
+ protected void initKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ s = 0;
+ P = new byte[256];
+ for (int i = 0; i < 256; i++)
+ {
+ P[i] = (byte) i;
+ }
+
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+
+ n = 0;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/XTEAEngine.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/XTEAEngine.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/XTEAEngine.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/XTEAEngine.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,182 @@
+package pdftk.org.bouncycastle.crypto.engines;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * An XTEA engine.
+ */
+public class XTEAEngine
+ implements BlockCipher
+{
+ private static final int rounds = 32,
+ block_size = 8,
+// key_size = 16,
+ delta = 0x9E3779B9;
+
+ /*
+ * the expanded key array of 4 subkeys
+ */
+ private int[] _S = new int[4],
+ _sum0 = new int[32],
+ _sum1 = new int[32];
+ private boolean _initialised,
+ _forEncryption;
+
+ /**
+ * Create an instance of the TEA encryption algorithm
+ * and set some defaults
+ */
+ public XTEAEngine()
+ {
+ _initialised = false;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "XTEA";
+ }
+
+ public int getBlockSize()
+ {
+ return block_size;
+ }
+
+ /**
+ * initialise
+ *
+ * @param forEncryption whether or not we are for encryption.
+ * @param params the parameters required to set up the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ {
+ if (!(params instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException("invalid parameter passed to TEA init - " + params.getClass().getName());
+ }
+
+ _forEncryption = forEncryption;
+ _initialised = true;
+
+ KeyParameter p = (KeyParameter)params;
+
+ setKey(p.getKey());
+ }
+
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ if (!_initialised)
+ {
+ throw new IllegalStateException(getAlgorithmName()+" not initialised");
+ }
+
+ if ((inOff + block_size) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + block_size) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ return (_forEncryption) ? encryptBlock(in, inOff, out, outOff)
+ : decryptBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ }
+
+ /**
+ * Re-key the cipher.
+ *
+ * @param key the key to be used
+ */
+ private void setKey(
+ byte[] key)
+ {
+ int i, j;
+ for (i = j = 0; i < 4; i++,j+=4)
+ {
+ _S[i] = bytesToInt(key, j);
+ }
+
+ for (i = j = 0; i < rounds; i++)
+ {
+ _sum0[i] = (j + _S[j & 3]);
+ j += delta;
+ _sum1[i] = (j + _S[j >>> 11 & 3]);
+ }
+ }
+
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // Pack bytes into integers
+ int v0 = bytesToInt(in, inOff);
+ int v1 = bytesToInt(in, inOff + 4);
+
+ for (int i = 0; i < rounds; i++)
+ {
+ v0 += ((v1 << 4 ^ v1 >>> 5) + v1) ^ _sum0[i];
+ v1 += ((v0 << 4 ^ v0 >>> 5) + v0) ^ _sum1[i];
+ }
+
+ unpackInt(v0, out, outOff);
+ unpackInt(v1, out, outOff + 4);
+
+ return block_size;
+ }
+
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ // Pack bytes into integers
+ int v0 = bytesToInt(in, inOff);
+ int v1 = bytesToInt(in, inOff + 4);
+
+ for (int i = rounds-1; i >= 0; i--)
+ {
+ v1 -= ((v0 << 4 ^ v0 >>> 5) + v0) ^ _sum1[i];
+ v0 -= ((v1 << 4 ^ v1 >>> 5) + v1) ^ _sum0[i];
+ }
+
+ unpackInt(v0, out, outOff);
+ unpackInt(v1, out, outOff + 4);
+
+ return block_size;
+ }
+
+ private int bytesToInt(byte[] in, int inOff)
+ {
+ return ((in[inOff++]) << 24) |
+ ((in[inOff++] & 255) << 16) |
+ ((in[inOff++] & 255) << 8) |
+ ((in[inOff] & 255));
+ }
+
+ private void unpackInt(int v, byte[] out, int outOff)
+ {
+ out[outOff++] = (byte)(v >>> 24);
+ out[outOff++] = (byte)(v >>> 16);
+ out[outOff++] = (byte)(v >>> 8);
+ out[outOff ] = (byte)v;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/engines/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/engines/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Basic cipher classes.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/examples/DESExample.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/examples/DESExample.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/examples/DESExample.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/examples/DESExample.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,419 @@
+package pdftk.org.bouncycastle.crypto.examples;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.engines.DESedeEngine;
+import pdftk.org.bouncycastle.crypto.generators.DESedeKeyGenerator;
+import pdftk.org.bouncycastle.crypto.modes.CBCBlockCipher;
+import pdftk.org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
+import pdftk.org.bouncycastle.crypto.params.DESedeParameters;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.util.encoders.Hex;
+
+/**
+ * DESExample is a simple DES based encryptor/decryptor.
+ *
+ * The program is command line driven, with the input
+ * and output files specified on the command line.
+ *
+ * java pdftk.org.bouncycastle.crypto.examples.DESExample infile outfile [keyfile]
+ *
+ * A new key is generated for each encryption, if key is not specified,
+ * then the example will assume encryption is required, and as output
+ * create deskey.dat in the current directory. This key is a hex
+ * encoded byte-stream that is used for the decryption. The output
+ * file is Hex encoded, 60 characters wide text file.
+ *
+ * When encrypting;
+ *
+ * the infile is expected to be a byte stream (text or binary)
+ * there is no keyfile specified on the input line
+ *
+ *
+ * When decrypting;
+ *
the infile is expected to be the 60 character wide base64
+ * encoded file
+ * the keyfile is expected to be a base64 encoded file
+ *
+ * This example shows how to use the light-weight API, DES and
+ * the filesystem for message encryption and decryption.
+ *
+ */
+public class DESExample extends Object
+{
+ // Encrypting or decrypting ?
+ private boolean encrypt = true;
+
+ // To hold the initialised DESede cipher
+ private PaddedBufferedBlockCipher cipher = null;
+
+ // The input stream of bytes to be processed for encryption
+ private BufferedInputStream in = null;
+
+ // The output stream of bytes to be procssed
+ private BufferedOutputStream out = null;
+
+ // The key
+ private byte[] key = null;
+
+ /*
+ * start the application
+ */
+ public static void main(String[] args)
+ {
+ boolean encrypt = true;
+ String infile = null;
+ String outfile = null;
+ String keyfile = null;
+
+ if (args.length < 2)
+ {
+ DESExample de = new DESExample();
+ System.err.println("Usage: java "+de.getClass().getName()+
+ " infile outfile [keyfile]");
+ System.exit(1);
+ }
+
+ keyfile = "deskey.dat";
+ infile = args[0];
+ outfile = args[1];
+
+ if (args.length > 2)
+ {
+ encrypt = false;
+ keyfile = args[2];
+ }
+
+ DESExample de = new DESExample(infile, outfile, keyfile, encrypt);
+ de.process();
+ }
+
+ // Default constructor, used for the usage message
+ public DESExample()
+ {
+ }
+
+ /*
+ * Constructor, that takes the arguments appropriate for
+ * processing the command line directives.
+ */
+ public DESExample(
+ String infile,
+ String outfile,
+ String keyfile,
+ boolean encrypt)
+ {
+ /*
+ * First, determine that infile & keyfile exist as appropriate.
+ *
+ * This will also create the BufferedInputStream as required
+ * for reading the input file. All input files are treated
+ * as if they are binary, even if they contain text, it's the
+ * bytes that are encrypted.
+ */
+ this.encrypt = encrypt;
+ try
+ {
+ in = new BufferedInputStream(new FileInputStream(infile));
+ }
+ catch (FileNotFoundException fnf)
+ {
+ System.err.println("Input file not found ["+infile+"]");
+ System.exit(1);
+ }
+
+ try
+ {
+ out = new BufferedOutputStream(new FileOutputStream(outfile));
+ }
+ catch (IOException fnf)
+ {
+ System.err.println("Output file not created ["+outfile+"]");
+ System.exit(1);
+ }
+
+ if (encrypt)
+ {
+ try
+ {
+ /*
+ * The process of creating a new key requires a
+ * number of steps.
+ *
+ * First, create the parameters for the key generator
+ * which are a secure random number generator, and
+ * the length of the key (in bits).
+ */
+ SecureRandom sr = null;
+ try
+ {
+ sr = new SecureRandom();
+ /*
+ * This following call to setSeed() makes the
+ * initialisation of the SecureRandom object
+ * _very_ fast, but not secure AT ALL.
+ *
+ * Remove the line, recreate the class file and
+ * then run DESExample again to see the difference.
+ *
+ * The initialisation of a SecureRandom object
+ * can take 5 or more seconds depending on the
+ * CPU that the program is running on. That can
+ * be annoying during unit testing.
+ * -- jon
+ */
+ sr.setSeed("www.bouncycastle.org".getBytes());
+ }
+ catch (Exception nsa)
+ {
+ System.err.println("Hmmm, no SHA1PRNG, you need the "+
+ "Sun implementation");
+ System.exit(1);
+ }
+ KeyGenerationParameters kgp = new KeyGenerationParameters(
+ sr,
+ DESedeParameters.DES_EDE_KEY_LENGTH*8);
+
+ /*
+ * Second, initialise the key generator with the parameters
+ */
+ DESedeKeyGenerator kg = new DESedeKeyGenerator();
+ kg.init(kgp);
+
+ /*
+ * Third, and finally, generate the key
+ */
+ key = kg.generateKey();
+
+ /*
+ * We can now output the key to the file, but first
+ * hex encode the key so that we can have a look
+ * at it with a text editor if we so desire
+ */
+ BufferedOutputStream keystream =
+ new BufferedOutputStream(new FileOutputStream(keyfile));
+ byte[] keyhex = Hex.encode(key);
+ keystream.write(keyhex, 0, keyhex.length);
+ keystream.flush();
+ keystream.close();
+ }
+ catch (IOException createKey)
+ {
+ System.err.println("Could not decryption create key file "+
+ "["+keyfile+"]");
+ System.exit(1);
+ }
+ }
+ else
+ {
+ try
+ {
+ // read the key, and decode from hex encoding
+ BufferedInputStream keystream =
+ new BufferedInputStream(new FileInputStream(keyfile));
+ int len = keystream.available();
+ byte[] keyhex = new byte[len];
+ keystream.read(keyhex, 0, len);
+ key = Hex.decode(keyhex);
+ }
+ catch (IOException ioe)
+ {
+ System.err.println("Decryption key file not found, "+
+ "or not valid ["+keyfile+"]");
+ System.exit(1);
+ }
+ }
+ }
+
+ private void process()
+ {
+ /*
+ * Setup the DESede cipher engine, create a PaddedBufferedBlockCipher
+ * in CBC mode.
+ */
+ cipher = new PaddedBufferedBlockCipher(
+ new CBCBlockCipher(new DESedeEngine()));
+
+ /*
+ * The input and output streams are currently set up
+ * appropriately, and the key bytes are ready to be
+ * used.
+ *
+ */
+
+ if (encrypt)
+ {
+ performEncrypt(key);
+ }
+ else
+ {
+ performDecrypt(key);
+ }
+
+ // after processing clean up the files
+ try
+ {
+ in.close();
+ out.flush();
+ out.close();
+ }
+ catch (IOException closing)
+ {
+
+ }
+ }
+
+ /*
+ * This method performs all the encryption and writes
+ * the cipher text to the buffered output stream created
+ * previously.
+ */
+ private void performEncrypt(byte[] key)
+ {
+ // initialise the cipher with the key bytes, for encryption
+ cipher.init(true, new KeyParameter(key));
+
+ /*
+ * Create some temporary byte arrays for use in
+ * encryption, make them a reasonable size so that
+ * we don't spend forever reading small chunks from
+ * a file.
+ *
+ * There is no particular reason for using getBlockSize()
+ * to determine the size of the input chunk. It just
+ * was a convenient number for the example.
+ */
+ // int inBlockSize = cipher.getBlockSize() * 5;
+ int inBlockSize = 47;
+ int outBlockSize = cipher.getOutputSize(inBlockSize);
+
+ byte[] inblock = new byte[inBlockSize];
+ byte[] outblock = new byte[outBlockSize];
+
+ /*
+ * now, read the file, and output the chunks
+ */
+ try
+ {
+ int inL;
+ int outL;
+ byte[] rv = null;
+ while ((inL=in.read(inblock, 0, inBlockSize)) > 0)
+ {
+ outL = cipher.processBytes(inblock, 0, inL, outblock, 0);
+ /*
+ * Before we write anything out, we need to make sure
+ * that we've got something to write out.
+ */
+ if (outL > 0)
+ {
+ rv = Hex.encode(outblock, 0, outL);
+ out.write(rv, 0, rv.length);
+ out.write('\n');
+ }
+ }
+
+ try
+ {
+ /*
+ * Now, process the bytes that are still buffered
+ * within the cipher.
+ */
+ outL = cipher.doFinal(outblock, 0);
+ if (outL > 0)
+ {
+ rv = Hex.encode(outblock, 0, outL);
+ out.write(rv, 0, rv.length);
+ out.write('\n');
+ }
+ }
+ catch (CryptoException ce)
+ {
+
+ }
+ }
+ catch (IOException ioeread)
+ {
+ ioeread.printStackTrace();
+ }
+ }
+
+ /*
+ * This method performs all the decryption and writes
+ * the plain text to the buffered output stream created
+ * previously.
+ */
+ private void performDecrypt(byte[] key)
+ {
+ // initialise the cipher for decryption
+ cipher.init(false, new KeyParameter(key));
+
+ /*
+ * As the decryption is from our preformatted file,
+ * and we know that it's a hex encoded format, then
+ * we wrap the InputStream with a BufferedReader
+ * so that we can read it easily.
+ */
+ BufferedReader br = new BufferedReader(new InputStreamReader(in));
+
+ /*
+ * now, read the file, and output the chunks
+ */
+ try
+ {
+ int outL;
+ byte[] inblock = null;
+ byte[] outblock = null;
+ String rv = null;
+ while ((rv = br.readLine()) != null)
+ {
+ inblock = Hex.decode(rv);
+ outblock = new byte[cipher.getOutputSize(inblock.length)];
+
+ outL = cipher.processBytes(inblock, 0, inblock.length,
+ outblock, 0);
+ /*
+ * Before we write anything out, we need to make sure
+ * that we've got something to write out.
+ */
+ if (outL > 0)
+ {
+ out.write(outblock, 0, outL);
+ }
+ }
+
+ try
+ {
+ /*
+ * Now, process the bytes that are still buffered
+ * within the cipher.
+ */
+ outL = cipher.doFinal(outblock, 0);
+ if (outL > 0)
+ {
+ out.write(outblock, 0, outL);
+ }
+ }
+ catch (CryptoException ce)
+ {
+
+ }
+ }
+ catch (IOException ioeread)
+ {
+ ioeread.printStackTrace();
+ }
+ }
+
+}
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/examples/JPAKEExample.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/examples/JPAKEExample.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/examples/JPAKEExample.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/examples/JPAKEExample.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,214 @@
+package pdftk.org.bouncycastle.crypto.examples;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroup;
+import pdftk.org.bouncycastle.crypto.agreement.jpake.JPAKEPrimeOrderGroups;
+import pdftk.org.bouncycastle.crypto.agreement.jpake.JPAKEParticipant;
+import pdftk.org.bouncycastle.crypto.agreement.jpake.JPAKERound1Payload;
+import pdftk.org.bouncycastle.crypto.agreement.jpake.JPAKERound2Payload;
+import pdftk.org.bouncycastle.crypto.agreement.jpake.JPAKERound3Payload;
+import pdftk.org.bouncycastle.crypto.digests.SHA256Digest;
+
+/**
+ * An example of a J-PAKE exchange.
+ *
+ *
+ * In this example, both Alice and Bob are on the same computer (in the same JVM, in fact).
+ * In reality, Alice and Bob would be in different locations,
+ * and would be sending their generated payloads to each other.
+ */
+public class JPAKEExample
+{
+
+ public static void main(String args[]) throws CryptoException
+ {
+ /*
+ * Initialization
+ *
+ * Pick an appropriate prime order group to use throughout the exchange.
+ * Note that both participants must use the same group.
+ */
+ JPAKEPrimeOrderGroup group = JPAKEPrimeOrderGroups.NIST_3072;
+
+ BigInteger p = group.getP();
+ BigInteger q = group.getQ();
+ BigInteger g = group.getG();
+
+ String alicePassword = "password";
+ String bobPassword = "password";
+
+ System.out.println("********* Initialization **********");
+ System.out.println("Public parameters for the cyclic group:");
+ System.out.println("p (" + p.bitLength() + " bits): " + p.toString(16));
+ System.out.println("q (" + q.bitLength() + " bits): " + q.toString(16));
+ System.out.println("g (" + p.bitLength() + " bits): " + g.toString(16));
+ System.out.println("p mod q = " + p.mod(q).toString(16));
+ System.out.println("g^{q} mod p = " + g.modPow(q, p).toString(16));
+ System.out.println("");
+
+ System.out.println("(Secret passwords used by Alice and Bob: " +
+ "\"" + alicePassword + "\" and \"" + bobPassword + "\")\n");
+
+ /*
+ * Both participants must use the same hashing algorithm.
+ */
+ Digest digest = new SHA256Digest();
+ SecureRandom random = new SecureRandom();
+
+ JPAKEParticipant alice = new JPAKEParticipant("alice", alicePassword.toCharArray(), group, digest, random);
+ JPAKEParticipant bob = new JPAKEParticipant("bob", bobPassword.toCharArray(), group, digest, random);
+
+ /*
+ * Round 1
+ *
+ * Alice and Bob each generate a round 1 payload, and send it to each other.
+ */
+
+ JPAKERound1Payload aliceRound1Payload = alice.createRound1PayloadToSend();
+ JPAKERound1Payload bobRound1Payload = bob.createRound1PayloadToSend();
+
+ System.out.println("************ Round 1 **************");
+ System.out.println("Alice sends to Bob: ");
+ System.out.println("g^{x1}=" + aliceRound1Payload.getGx1().toString(16));
+ System.out.println("g^{x2}=" + aliceRound1Payload.getGx2().toString(16));
+ System.out.println("KP{x1}={" + aliceRound1Payload.getKnowledgeProofForX1()[0].toString(16) + "};{" + aliceRound1Payload.getKnowledgeProofForX1()[1].toString(16) + "}");
+ System.out.println("KP{x2}={" + aliceRound1Payload.getKnowledgeProofForX2()[0].toString(16) + "};{" + aliceRound1Payload.getKnowledgeProofForX2()[1].toString(16) + "}");
+ System.out.println("");
+
+ System.out.println("Bob sends to Alice: ");
+ System.out.println("g^{x3}=" + bobRound1Payload.getGx1().toString(16));
+ System.out.println("g^{x4}=" + bobRound1Payload.getGx2().toString(16));
+ System.out.println("KP{x3}={" + bobRound1Payload.getKnowledgeProofForX1()[0].toString(16) + "};{" + bobRound1Payload.getKnowledgeProofForX1()[1].toString(16) + "}");
+ System.out.println("KP{x4}={" + bobRound1Payload.getKnowledgeProofForX2()[0].toString(16) + "};{" + bobRound1Payload.getKnowledgeProofForX2()[1].toString(16) + "}");
+ System.out.println("");
+
+ /*
+ * Each participant must then validate the received payload for round 1
+ */
+
+ alice.validateRound1PayloadReceived(bobRound1Payload);
+ System.out.println("Alice checks g^{x4}!=1: OK");
+ System.out.println("Alice checks KP{x3}: OK");
+ System.out.println("Alice checks KP{x4}: OK");
+ System.out.println("");
+
+ bob.validateRound1PayloadReceived(aliceRound1Payload);
+ System.out.println("Bob checks g^{x2}!=1: OK");
+ System.out.println("Bob checks KP{x1},: OK");
+ System.out.println("Bob checks KP{x2},: OK");
+ System.out.println("");
+
+ /*
+ * Round 2
+ *
+ * Alice and Bob each generate a round 2 payload, and send it to each other.
+ */
+
+ JPAKERound2Payload aliceRound2Payload = alice.createRound2PayloadToSend();
+ JPAKERound2Payload bobRound2Payload = bob.createRound2PayloadToSend();
+
+ System.out.println("************ Round 2 **************");
+ System.out.println("Alice sends to Bob: ");
+ System.out.println("A=" + aliceRound2Payload.getA().toString(16));
+ System.out.println("KP{x2*s}={" + aliceRound2Payload.getKnowledgeProofForX2s()[0].toString(16) + "},{" + aliceRound2Payload.getKnowledgeProofForX2s()[1].toString(16) + "}");
+ System.out.println("");
+
+ System.out.println("Bob sends to Alice");
+ System.out.println("B=" + bobRound2Payload.getA().toString(16));
+ System.out.println("KP{x4*s}={" + bobRound2Payload.getKnowledgeProofForX2s()[0].toString(16) + "},{" + bobRound2Payload.getKnowledgeProofForX2s()[1].toString(16) + "}");
+ System.out.println("");
+
+ /*
+ * Each participant must then validate the received payload for round 2
+ */
+
+ alice.validateRound2PayloadReceived(bobRound2Payload);
+ System.out.println("Alice checks KP{x4*s}: OK\n");
+
+ bob.validateRound2PayloadReceived(aliceRound2Payload);
+ System.out.println("Bob checks KP{x2*s}: OK\n");
+
+ /*
+ * After round 2, each participant computes the keying material.
+ */
+
+ BigInteger aliceKeyingMaterial = alice.calculateKeyingMaterial();
+ BigInteger bobKeyingMaterial = bob.calculateKeyingMaterial();
+
+ System.out.println("********* After round 2 ***********");
+ System.out.println("Alice computes key material \t K=" + aliceKeyingMaterial.toString(16));
+ System.out.println("Bob computes key material \t K=" + bobKeyingMaterial.toString(16));
+ System.out.println();
+
+
+ /*
+ * You must derive a session key from the keying material applicable
+ * to whatever encryption algorithm you want to use.
+ */
+
+ BigInteger aliceKey = deriveSessionKey(aliceKeyingMaterial);
+ BigInteger bobKey = deriveSessionKey(bobKeyingMaterial);
+
+ /*
+ * At this point, you can stop and use the session keys if you want.
+ * This is implicit key confirmation.
+ *
+ * If you want to explicitly confirm that the key material matches,
+ * you can continue on and perform round 3.
+ */
+
+ /*
+ * Round 3
+ *
+ * Alice and Bob each generate a round 3 payload, and send it to each other.
+ */
+
+ JPAKERound3Payload aliceRound3Payload = alice.createRound3PayloadToSend(aliceKeyingMaterial);
+ JPAKERound3Payload bobRound3Payload = bob.createRound3PayloadToSend(bobKeyingMaterial);
+
+ System.out.println("************ Round 3 **************");
+ System.out.println("Alice sends to Bob: ");
+ System.out.println("MacTag=" + aliceRound3Payload.getMacTag().toString(16));
+ System.out.println("");
+ System.out.println("Bob sends to Alice: ");
+ System.out.println("MacTag=" + bobRound3Payload.getMacTag().toString(16));
+ System.out.println("");
+
+ /*
+ * Each participant must then validate the received payload for round 3
+ */
+
+ alice.validateRound3PayloadReceived(bobRound3Payload, aliceKeyingMaterial);
+ System.out.println("Alice checks MacTag: OK\n");
+
+ bob.validateRound3PayloadReceived(aliceRound3Payload, bobKeyingMaterial);
+ System.out.println("Bob checks MacTag: OK\n");
+
+ System.out.println();
+ System.out.println("MacTags validated, therefore the keying material matches.");
+ }
+
+ private static BigInteger deriveSessionKey(BigInteger keyingMaterial)
+ {
+ /*
+ * You should use a secure key derivation function (KDF) to derive the session key.
+ *
+ * For the purposes of this example, I'm just going to use a hash of the keying material.
+ */
+ SHA256Digest digest = new SHA256Digest();
+
+ byte[] keyByteArray = keyingMaterial.toByteArray();
+
+ byte[] output = new byte[digest.getDigestSize()];
+
+ digest.update(keyByteArray, 0, keyByteArray.length);
+
+ digest.doFinal(output, 0);
+
+ return new BigInteger(output);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/examples/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/examples/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/examples/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/examples/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Simple examples of light weight API usage.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/BaseKDFBytesGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,142 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.DerivationFunction;
+import pdftk.org.bouncycastle.crypto.DerivationParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.params.ISO18033KDFParameters;
+import pdftk.org.bouncycastle.crypto.params.KDFParameters;
+
+/**
+ * Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+ *
+ * This implementation is based on ISO 18033/P1363a.
+ */
+public class BaseKDFBytesGenerator
+ implements DerivationFunction
+{
+ private int counterStart;
+ private Digest digest;
+ private byte[] shared;
+ private byte[] iv;
+
+ /**
+ * Construct a KDF Parameters generator.
+ *
+ * @param counterStart value of counter.
+ * @param digest the digest to be used as the source of derived keys.
+ */
+ protected BaseKDFBytesGenerator(
+ int counterStart,
+ Digest digest)
+ {
+ this.counterStart = counterStart;
+ this.digest = digest;
+ }
+
+ public void init(
+ DerivationParameters param)
+ {
+ if (param instanceof KDFParameters)
+ {
+ KDFParameters p = (KDFParameters)param;
+
+ shared = p.getSharedSecret();
+ iv = p.getIV();
+ }
+ else if (param instanceof ISO18033KDFParameters)
+ {
+ ISO18033KDFParameters p = (ISO18033KDFParameters)param;
+
+ shared = p.getSeed();
+ iv = null;
+ }
+ else
+ {
+ throw new IllegalArgumentException("KDF parameters required for KDF2Generator");
+ }
+ }
+
+ /**
+ * return the underlying digest.
+ */
+ public Digest getDigest()
+ {
+ return digest;
+ }
+
+ /**
+ * fill len bytes of the output buffer with bytes generated from
+ * the derivation function.
+ *
+ * @throws IllegalArgumentException if the size of the request will cause an overflow.
+ * @throws DataLengthException if the out buffer is too small.
+ */
+ public int generateBytes(
+ byte[] out,
+ int outOff,
+ int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+ if ((out.length - len) < outOff)
+ {
+ throw new DataLengthException("output buffer too small");
+ }
+
+ long oBytes = len;
+ int outLen = digest.getDigestSize();
+
+ //
+ // this is at odds with the standard implementation, the
+ // maximum value should be hBits * (2^32 - 1) where hBits
+ // is the digest output size in bits. We can't have an
+ // array with a long index at the moment...
+ //
+ if (oBytes > ((2L << 32) - 1))
+ {
+ throw new IllegalArgumentException("Output length too large");
+ }
+
+ int cThreshold = (int)((oBytes + outLen - 1) / outLen);
+
+ byte[] dig = null;
+
+ dig = new byte[digest.getDigestSize()];
+
+ int counter = counterStart;
+
+ for (int i = 0; i < cThreshold; i++)
+ {
+ digest.update(shared, 0, shared.length);
+
+ digest.update((byte)(counter >> 24));
+ digest.update((byte)(counter >> 16));
+ digest.update((byte)(counter >> 8));
+ digest.update((byte)counter);
+
+ if (iv != null)
+ {
+ digest.update(iv, 0, iv.length);
+ }
+
+ digest.doFinal(dig, 0);
+
+ if (len > outLen)
+ {
+ System.arraycopy(dig, 0, out, outOff, outLen);
+ outOff += outLen;
+ len -= outLen;
+ }
+ else
+ {
+ System.arraycopy(dig, 0, out, outOff, len);
+ }
+
+ counter++;
+ }
+
+ digest.reset();
+
+ return len;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DESKeyGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DESKeyGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DESKeyGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DESKeyGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.CipherKeyGenerator;
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.DESParameters;
+
+public class DESKeyGenerator
+ extends CipherKeyGenerator
+{
+ /**
+ * initialise the key generator - if strength is set to zero
+ * the key generated will be 64 bits in size, otherwise
+ * strength can be 64 or 56 bits (if you don't count the parity bits).
+ *
+ * @param param the parameters to be used for key generation
+ */
+ public void init(
+ KeyGenerationParameters param)
+ {
+ super.init(param);
+
+ if (strength == 0 || strength == (56 / 8))
+ {
+ strength = DESParameters.DES_KEY_LENGTH;
+ }
+ else if (strength != DESParameters.DES_KEY_LENGTH)
+ {
+ throw new IllegalArgumentException("DES key must be "
+ + (DESParameters.DES_KEY_LENGTH * 8)
+ + " bits long.");
+ }
+ }
+
+ public byte[] generateKey()
+ {
+ byte[] newKey = new byte[DESParameters.DES_KEY_LENGTH];
+
+ do
+ {
+ random.nextBytes(newKey);
+
+ DESParameters.setOddParity(newKey);
+ }
+ while (DESParameters.isWeakKey(newKey, 0));
+
+ return newKey;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DESedeKeyGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,56 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.DESedeParameters;
+
+public class DESedeKeyGenerator
+ extends DESKeyGenerator
+{
+ /**
+ * initialise the key generator - if strength is set to zero
+ * the key generated will be 192 bits in size, otherwise
+ * strength can be 128 or 192 (or 112 or 168 if you don't count
+ * parity bits), depending on whether you wish to do 2-key or 3-key
+ * triple DES.
+ *
+ * @param param the parameters to be used for key generation
+ */
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.random = param.getRandom();
+ this.strength = (param.getStrength() + 7) / 8;
+
+ if (strength == 0 || strength == (168 / 8))
+ {
+ strength = DESedeParameters.DES_EDE_KEY_LENGTH;
+ }
+ else if (strength == (112 / 8))
+ {
+ strength = 2 * DESedeParameters.DES_KEY_LENGTH;
+ }
+ else if (strength != DESedeParameters.DES_EDE_KEY_LENGTH
+ && strength != (2 * DESedeParameters.DES_KEY_LENGTH))
+ {
+ throw new IllegalArgumentException("DESede key must be "
+ + (DESedeParameters.DES_EDE_KEY_LENGTH * 8) + " or "
+ + (2 * 8 * DESedeParameters.DES_KEY_LENGTH)
+ + " bits long.");
+ }
+ }
+
+ public byte[] generateKey()
+ {
+ byte[] newKey = new byte[strength];
+
+ do
+ {
+ random.nextBytes(newKey);
+
+ DESedeParameters.setOddParity(newKey);
+ }
+ while (DESedeParameters.isWeakKey(newKey, 0, newKey.length));
+
+ return newKey;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DHBasicKeyPairGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DHBasicKeyPairGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DHBasicKeyPairGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DHBasicKeyPairGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,42 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.DHKeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPublicKeyParameters;
+
+import java.math.BigInteger;
+
+/**
+ * a basic Diffie-Hellman key pair generator.
+ *
+ * This generates keys consistent for use with the basic algorithm for
+ * Diffie-Hellman.
+ */
+public class DHBasicKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private DHKeyGenerationParameters param;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.param = (DHKeyGenerationParameters)param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE;
+ DHParameters dhp = param.getParameters();
+
+ BigInteger x = helper.calculatePrivate(dhp, param.getRandom());
+ BigInteger y = helper.calculatePublic(dhp, x);
+
+ return new AsymmetricCipherKeyPair(
+ new DHPublicKeyParameters(y, dhp),
+ new DHPrivateKeyParameters(x, dhp));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DHKeyGeneratorHelper.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,51 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+class DHKeyGeneratorHelper
+{
+ static final DHKeyGeneratorHelper INSTANCE = new DHKeyGeneratorHelper();
+
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ private DHKeyGeneratorHelper()
+ {
+ }
+
+ BigInteger calculatePrivate(DHParameters dhParams, SecureRandom random)
+ {
+ BigInteger p = dhParams.getP();
+ int limit = dhParams.getL();
+
+ if (limit != 0)
+ {
+ return new BigInteger(limit, random).setBit(limit - 1);
+ }
+
+ BigInteger min = TWO;
+ int m = dhParams.getM();
+ if (m != 0)
+ {
+ min = ONE.shiftLeft(m - 1);
+ }
+
+ BigInteger max = p.subtract(TWO);
+ BigInteger q = dhParams.getQ();
+ if (q != null)
+ {
+ max = q.subtract(TWO);
+ }
+
+ return BigIntegers.createRandomInRange(min, max, random);
+ }
+
+ BigInteger calculatePublic(DHParameters dhParams, BigInteger x)
+ {
+ return dhParams.getG().modPow(x, dhParams.getP());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DHKeyPairGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DHKeyPairGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DHKeyPairGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DHKeyPairGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,42 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.DHKeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPublicKeyParameters;
+
+import java.math.BigInteger;
+
+/**
+ * a Diffie-Hellman key pair generator.
+ *
+ * This generates keys consistent for use in the MTI/A0 key agreement protocol
+ * as described in "Handbook of Applied Cryptography", Pages 516-519.
+ */
+public class DHKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private DHKeyGenerationParameters param;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.param = (DHKeyGenerationParameters)param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE;
+ DHParameters dhp = param.getParameters();
+
+ BigInteger x = helper.calculatePrivate(dhp, param.getRandom());
+ BigInteger y = helper.calculatePublic(dhp, x);
+
+ return new AsymmetricCipherKeyPair(
+ new DHPublicKeyParameters(y, dhp),
+ new DHPrivateKeyParameters(x, dhp));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DHParametersGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DHParametersGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DHParametersGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DHParametersGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,52 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+public class DHParametersGenerator
+{
+ private int size;
+ private int certainty;
+ private SecureRandom random;
+
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ /**
+ * Initialise the parameters generator.
+ *
+ * @param size bit length for the prime p
+ * @param certainty level of certainty for the prime number tests
+ * @param random a source of randomness
+ */
+ public void init(
+ int size,
+ int certainty,
+ SecureRandom random)
+ {
+ this.size = size;
+ this.certainty = certainty;
+ this.random = random;
+ }
+
+ /**
+ * which generates the p and g values from the given parameters,
+ * returning the DHParameters object.
+ *
+ * Note: can take a while...
+ */
+ public DHParameters generateParameters()
+ {
+ //
+ // find a safe prime p where p = 2*q + 1, where p and q are prime.
+ //
+ BigInteger[] safePrimes = DHParametersHelper.generateSafePrimes(size, certainty, random);
+
+ BigInteger p = safePrimes[0];
+ BigInteger q = safePrimes[1];
+ BigInteger g = DHParametersHelper.selectGenerator(p, q, random);
+
+ return new DHParameters(p, g, q, TWO, null);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DHParametersHelper.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DHParametersHelper.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DHParametersHelper.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DHParametersHelper.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,73 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+class DHParametersHelper
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ /*
+ * Finds a pair of prime BigInteger's {p, q: p = 2q + 1}
+ *
+ * (see: Handbook of Applied Cryptography 4.86)
+ */
+ static BigInteger[] generateSafePrimes(int size, int certainty, SecureRandom random)
+ {
+ BigInteger p, q;
+ int qLength = size - 1;
+
+ for (;;)
+ {
+ q = new BigInteger(qLength, 2, random);
+
+ // p <- 2q + 1
+ p = q.shiftLeft(1).add(ONE);
+
+ if (p.isProbablePrime(certainty) && (certainty <= 2 || q.isProbablePrime(certainty)))
+ {
+ break;
+ }
+ }
+
+ return new BigInteger[] { p, q };
+ }
+
+ /*
+ * Select a high order element of the multiplicative group Zp*
+ *
+ * p and q must be s.t. p = 2*q + 1, where p and q are prime (see generateSafePrimes)
+ */
+ static BigInteger selectGenerator(BigInteger p, BigInteger q, SecureRandom random)
+ {
+ BigInteger pMinusTwo = p.subtract(TWO);
+ BigInteger g;
+
+ /*
+ * (see: Handbook of Applied Cryptography 4.80)
+ */
+// do
+// {
+// g = BigIntegers.createRandomInRange(TWO, pMinusTwo, random);
+// }
+// while (g.modPow(TWO, p).equals(ONE) || g.modPow(q, p).equals(ONE));
+
+
+ /*
+ * RFC 2631 2.2.1.2 (and see: Handbook of Applied Cryptography 4.81)
+ */
+ do
+ {
+ BigInteger h = BigIntegers.createRandomInRange(TWO, pMinusTwo, random);
+
+ g = h.modPow(TWO, p);
+ }
+ while (g.equals(ONE));
+
+
+ return g;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DSAKeyPairGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,61 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAKeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAPublicKeyParameters;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * a DSA key pair generator.
+ *
+ * This generates DSA keys in line with the method described
+ * in FIPS 186-3 B.1 FFC Key Pair Generation .
+ */
+public class DSAKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private DSAKeyGenerationParameters param;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.param = (DSAKeyGenerationParameters)param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ DSAParameters dsaParams = param.getParameters();
+
+ BigInteger x = generatePrivateKey(dsaParams.getQ(), param.getRandom());
+ BigInteger y = calculatePublicKey(dsaParams.getP(), dsaParams.getG(), x);
+
+ return new AsymmetricCipherKeyPair(
+ new DSAPublicKeyParameters(y, dsaParams),
+ new DSAPrivateKeyParameters(x, dsaParams));
+ }
+
+ private static BigInteger generatePrivateKey(BigInteger q, SecureRandom random)
+ {
+ // TODO Prefer this method? (change test cases that used fixed random)
+ // B.1.1 Key Pair Generation Using Extra Random Bits
+// BigInteger c = new BigInteger(q.bitLength() + 64, random);
+// return c.mod(q.subtract(ONE)).add(ONE);
+
+ // B.1.2 Key Pair Generation by Testing Candidates
+ return BigIntegers.createRandomInRange(ONE, q.subtract(ONE), random);
+ }
+
+ private static BigInteger calculatePublicKey(BigInteger p, BigInteger g, BigInteger x)
+ {
+ return g.modPow(x, p);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DSAParametersGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DSAParametersGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DSAParametersGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DSAParametersGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,337 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+import pdftk.org.bouncycastle.crypto.digests.SHA256Digest;
+import pdftk.org.bouncycastle.crypto.params.DSAParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAValidationParameters;
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+// TODO Update javadoc to mention FIPS 186-3 when done
+/**
+ * generate suitable parameters for DSA, in line with FIPS 186-2.
+ */
+public class DSAParametersGenerator
+{
+ private int L, N;
+ private int certainty;
+ private SecureRandom random;
+
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ /**
+ * initialise the key generator.
+ *
+ * @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments)
+ * @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80).
+ * @param random random byte source.
+ */
+ public void init(
+ int size,
+ int certainty,
+ SecureRandom random)
+ {
+ init(size, getDefaultN(size), certainty, random);
+ }
+
+ // TODO Make public to enable support for DSA keys > 1024 bits
+ private void init(
+ int L,
+ int N,
+ int certainty,
+ SecureRandom random)
+ {
+ // TODO Check that the (L, N) pair is in the list of acceptable (L, N pairs) (see Section 4.2)
+ // TODO Should we enforce the minimum 'certainty' values as per C.3 Table C.1?
+
+ this.L = L;
+ this.N = N;
+ this.certainty = certainty;
+ this.random = random;
+ }
+
+ /**
+ * which generates the p and g values from the given parameters,
+ * returning the DSAParameters object.
+ *
+ * Note: can take a while...
+ */
+ public DSAParameters generateParameters()
+ {
+ return L > 1024
+ ? generateParameters_FIPS186_3()
+ : generateParameters_FIPS186_2();
+ }
+
+ private DSAParameters generateParameters_FIPS186_2()
+ {
+ byte[] seed = new byte[20];
+ byte[] part1 = new byte[20];
+ byte[] part2 = new byte[20];
+ byte[] u = new byte[20];
+ SHA1Digest sha1 = new SHA1Digest();
+ int n = (L - 1) / 160;
+ byte[] w = new byte[L / 8];
+
+ for (;;)
+ {
+ random.nextBytes(seed);
+
+ hash(sha1, seed, part1);
+ System.arraycopy(seed, 0, part2, 0, seed.length);
+ inc(part2);
+ hash(sha1, part2, part2);
+
+ for (int i = 0; i != u.length; i++)
+ {
+ u[i] = (byte)(part1[i] ^ part2[i]);
+ }
+
+ u[0] |= (byte)0x80;
+ u[19] |= (byte)0x01;
+
+ BigInteger q = new BigInteger(1, u);
+
+ if (!q.isProbablePrime(certainty))
+ {
+ continue;
+ }
+
+ byte[] offset = Arrays.clone(seed);
+ inc(offset);
+
+ for (int counter = 0; counter < 4096; ++counter)
+ {
+ for (int k = 0; k < n; k++)
+ {
+ inc(offset);
+ hash(sha1, offset, part1);
+ System.arraycopy(part1, 0, w, w.length - (k + 1) * part1.length, part1.length);
+ }
+
+ inc(offset);
+ hash(sha1, offset, part1);
+ System.arraycopy(part1, part1.length - ((w.length - (n) * part1.length)), w, 0, w.length - n * part1.length);
+
+ w[0] |= (byte)0x80;
+
+ BigInteger x = new BigInteger(1, w);
+
+ BigInteger c = x.mod(q.shiftLeft(1));
+
+ BigInteger p = x.subtract(c.subtract(ONE));
+
+ if (p.bitLength() != L)
+ {
+ continue;
+ }
+
+ if (p.isProbablePrime(certainty))
+ {
+ BigInteger g = calculateGenerator_FIPS186_2(p, q, random);
+
+ return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter));
+ }
+ }
+ }
+ }
+
+ private static BigInteger calculateGenerator_FIPS186_2(BigInteger p, BigInteger q, SecureRandom r)
+ {
+ BigInteger e = p.subtract(ONE).divide(q);
+ BigInteger pSub2 = p.subtract(TWO);
+
+ for (;;)
+ {
+ BigInteger h = BigIntegers.createRandomInRange(TWO, pSub2, r);
+ BigInteger g = h.modPow(e, p);
+ if (g.bitLength() > 1)
+ {
+ return g;
+ }
+ }
+ }
+
+ /**
+ * generate suitable parameters for DSA, in line with
+ * FIPS 186-3 A.1 Generation of the FFC Primes p and q .
+ */
+ private DSAParameters generateParameters_FIPS186_3()
+ {
+// A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function
+ // FIXME This should be configurable (digest size in bits must be >= N)
+ Digest d = new SHA256Digest();
+ int outlen = d.getDigestSize() * 8;
+
+// 1. Check that the (L, N) pair is in the list of acceptable (L, N pairs) (see Section 4.2). If
+// the pair is not in the list, then return INVALID.
+ // Note: checked at initialisation
+
+// 2. If (seedlen < N), then return INVALID.
+ // FIXME This should be configurable (must be >= N)
+ int seedlen = N;
+ byte[] seed = new byte[seedlen / 8];
+
+// 3. n = ceiling(L ⁄ outlen) – 1.
+ int n = (L - 1) / outlen;
+
+// 4. b = L – 1 – (n ∗ outlen).
+ int b = (L - 1) % outlen;
+
+ byte[] output = new byte[d.getDigestSize()];
+ for (;;)
+ {
+// 5. Get an arbitrary sequence of seedlen bits as the domain_parameter_seed.
+ random.nextBytes(seed);
+
+// 6. U = Hash (domain_parameter_seed) mod 2^(N–1).
+ hash(d, seed, output);
+ BigInteger U = new BigInteger(1, output).mod(ONE.shiftLeft(N - 1));
+
+// 7. q = 2^(N–1) + U + 1 – ( U mod 2).
+ BigInteger q = ONE.shiftLeft(N - 1).add(U).add(ONE).subtract(U.mod(TWO));
+
+// 8. Test whether or not q is prime as specified in Appendix C.3.
+ // TODO Review C.3 for primality checking
+ if (!q.isProbablePrime(certainty))
+ {
+// 9. If q is not a prime, then go to step 5.
+ continue;
+ }
+
+// 10. offset = 1.
+ // Note: 'offset' value managed incrementally
+ byte[] offset = Arrays.clone(seed);
+
+// 11. For counter = 0 to (4L – 1) do
+ int counterLimit = 4 * L;
+ for (int counter = 0; counter < counterLimit; ++counter)
+ {
+// 11.1 For j = 0 to n do
+// Vj = Hash ((domain_parameter_seed + offset + j) mod 2^seedlen).
+// 11.2 W = V0 + (V1 ∗ 2^outlen) + ... + (V^(n–1) ∗ 2^((n–1) ∗ outlen)) + ((Vn mod 2^b) ∗ 2^(n ∗ outlen)).
+ // TODO Assemble w as a byte array
+ BigInteger W = ZERO;
+ for (int j = 0, exp = 0; j <= n; ++j, exp += outlen)
+ {
+ inc(offset);
+ hash(d, offset, output);
+
+ BigInteger Vj = new BigInteger(1, output);
+ if (j == n)
+ {
+ Vj = Vj.mod(ONE.shiftLeft(b));
+ }
+
+ W = W.add(Vj.shiftLeft(exp));
+ }
+
+// 11.3 X = W + 2^(L–1). Comment: 0 ≤ W < 2L–1; hence, 2L–1 ≤ X < 2L.
+ BigInteger X = W.add(ONE.shiftLeft(L - 1));
+
+// 11.4 c = X mod 2q.
+ BigInteger c = X.mod(q.shiftLeft(1));
+
+// 11.5 p = X - (c - 1). Comment: p ≡ 1 (mod 2q).
+ BigInteger p = X.subtract(c.subtract(ONE));
+
+// 11.6 If (p < 2^(L - 1)), then go to step 11.9
+ if (p.bitLength() != L)
+ {
+ continue;
+ }
+
+// 11.7 Test whether or not p is prime as specified in Appendix C.3.
+ // TODO Review C.3 for primality checking
+ if (p.isProbablePrime(certainty))
+ {
+// 11.8 If p is determined to be prime, then return VALID and the values of p, q and
+// (optionally) the values of domain_parameter_seed and counter.
+ // TODO Make configurable (8-bit unsigned)?
+// int index = 1;
+// BigInteger g = calculateGenerator_FIPS186_3_Verifiable(d, p, q, seed, index);
+// if (g != null)
+// {
+// // TODO Should 'index' be a part of the validation parameters?
+// return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter));
+// }
+
+ BigInteger g = calculateGenerator_FIPS186_3_Unverifiable(p, q, random);
+ return new DSAParameters(p, q, g, new DSAValidationParameters(seed, counter));
+ }
+
+// 11.9 offset = offset + n + 1. Comment: Increment offset; then, as part of
+// the loop in step 11, increment counter; if
+// counter < 4L, repeat steps 11.1 through 11.8.
+ // Note: 'offset' value already incremented in inner loop
+ }
+// 12. Go to step 5.
+ }
+ }
+
+ private static BigInteger calculateGenerator_FIPS186_3_Unverifiable(BigInteger p, BigInteger q,
+ SecureRandom r)
+ {
+ return calculateGenerator_FIPS186_2(p, q, r);
+ }
+
+// private static BigInteger calculateGenerator_FIPS186_3_Verifiable(Digest d, BigInteger p, BigInteger q,
+// byte[] seed, int index)
+// {
+//// A.2.3 Verifiable Canonical Generation of the Generator g
+// BigInteger e = p.subtract(ONE).divide(q);
+// byte[] ggen = Hex.decode("6767656E");
+//
+// // 7. U = domain_parameter_seed || "ggen" || index || count.
+// byte[] U = new byte[seed.length + ggen.length + 1 + 2];
+// System.arraycopy(seed, 0, U, 0, seed.length);
+// System.arraycopy(ggen, 0, U, seed.length, ggen.length);
+// U[U.length - 3] = (byte)index;
+//
+// byte[] w = new byte[d.getDigestSize()];
+// for (int count = 1; count < (1 << 16); ++count)
+// {
+// inc(U);
+// hash(d, U, w);
+// BigInteger W = new BigInteger(1, w);
+// BigInteger g = W.modPow(e, p);
+// if (g.compareTo(TWO) >= 0)
+// {
+// return g;
+// }
+// }
+//
+// return null;
+// }
+
+ private static void hash(Digest d, byte[] input, byte[] output)
+ {
+ d.update(input, 0, input.length);
+ d.doFinal(output, 0);
+ }
+
+ private static int getDefaultN(int L)
+ {
+ return L > 1024 ? 256 : 160;
+ }
+
+ private static void inc(byte[] buf)
+ {
+ for (int i = buf.length - 1; i >= 0; --i)
+ {
+ byte b = (byte)((buf[i] + 1) & 0xff);
+ buf[i] = b;
+
+ if (b != 0)
+ {
+ break;
+ }
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DSTU4145KeyPairGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DSTU4145KeyPairGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/DSTU4145KeyPairGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/DSTU4145KeyPairGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,21 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+
+public class DSTU4145KeyPairGenerator
+ extends ECKeyPairGenerator
+{
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ AsymmetricCipherKeyPair pair = super.generateKeyPair();
+
+ ECPublicKeyParameters pub = (ECPublicKeyParameters)pair.getPublic();
+ ECPrivateKeyParameters priv = (ECPrivateKeyParameters)pair.getPrivate();
+
+ pub = new ECPublicKeyParameters(pub.getQ().negate(), pub.getParameters());
+
+ return new AsymmetricCipherKeyPair(pub, priv);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/ECKeyPairGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,53 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.ECDomainParameters;
+import pdftk.org.bouncycastle.crypto.params.ECKeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import pdftk.org.bouncycastle.math.ec.ECConstants;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+public class ECKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator, ECConstants
+{
+ ECDomainParameters params;
+ SecureRandom random;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ ECKeyGenerationParameters ecP = (ECKeyGenerationParameters)param;
+
+ this.random = ecP.getRandom();
+ this.params = ecP.getDomainParameters();
+ }
+
+ /**
+ * Given the domain parameters this routine generates an EC key
+ * pair in accordance with X9.62 section 5.2.1 pages 26, 27.
+ */
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ BigInteger n = params.getN();
+ int nBitLength = n.bitLength();
+ BigInteger d;
+
+ do
+ {
+ d = new BigInteger(nBitLength, random);
+ }
+ while (d.equals(ZERO) || (d.compareTo(n) >= 0));
+
+ ECPoint Q = params.getG().multiply(d);
+
+ return new AsymmetricCipherKeyPair(
+ new ECPublicKeyParameters(Q, params),
+ new ECPrivateKeyParameters(d, params));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/ElGamalKeyPairGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,44 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.crypto.params.ElGamalKeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.ElGamalParameters;
+import pdftk.org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
+
+/**
+ * a ElGamal key pair generator.
+ *
+ * This generates keys consistent for use with ElGamal as described in
+ * page 164 of "Handbook of Applied Cryptography".
+ */
+public class ElGamalKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private ElGamalKeyGenerationParameters param;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.param = (ElGamalKeyGenerationParameters)param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE;
+ ElGamalParameters egp = param.getParameters();
+ DHParameters dhp = new DHParameters(egp.getP(), egp.getG(), null, egp.getL());
+
+ BigInteger x = helper.calculatePrivate(dhp, param.getRandom());
+ BigInteger y = helper.calculatePublic(dhp, x);
+
+ return new AsymmetricCipherKeyPair(
+ new ElGamalPublicKeyParameters(y, egp),
+ new ElGamalPrivateKeyParameters(x, egp));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/ElGamalParametersGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,43 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.params.ElGamalParameters;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+public class ElGamalParametersGenerator
+{
+ private int size;
+ private int certainty;
+ private SecureRandom random;
+
+ public void init(
+ int size,
+ int certainty,
+ SecureRandom random)
+ {
+ this.size = size;
+ this.certainty = certainty;
+ this.random = random;
+ }
+
+ /**
+ * which generates the p and g values from the given parameters,
+ * returning the ElGamalParameters object.
+ *
+ * Note: can take a while...
+ */
+ public ElGamalParameters generateParameters()
+ {
+ //
+ // find a safe prime p where p = 2*q + 1, where p and q are prime.
+ //
+ BigInteger[] safePrimes = DHParametersHelper.generateSafePrimes(size, certainty, random);
+
+ BigInteger p = safePrimes[0];
+ BigInteger q = safePrimes[1];
+ BigInteger g = DHParametersHelper.selectGenerator(p, q, random);
+
+ return new ElGamalParameters(p, g);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/EphemeralKeyPairGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/EphemeralKeyPairGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/EphemeralKeyPairGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/EphemeralKeyPairGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,26 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.EphemeralKeyPair;
+import pdftk.org.bouncycastle.crypto.KeyEncoder;
+
+public class EphemeralKeyPairGenerator
+{
+ private AsymmetricCipherKeyPairGenerator gen;
+ private KeyEncoder keyEncoder;
+
+ public EphemeralKeyPairGenerator(AsymmetricCipherKeyPairGenerator gen, KeyEncoder keyEncoder)
+ {
+ this.gen = gen;
+ this.keyEncoder = keyEncoder;
+ }
+
+ public EphemeralKeyPair generate()
+ {
+ AsymmetricCipherKeyPair eph = gen.generateKeyPair();
+
+ // Encode the ephemeral public key
+ return new EphemeralKeyPair(eph, keyEncoder);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/GOST3410KeyPairGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/GOST3410KeyPairGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/GOST3410KeyPairGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/GOST3410KeyPairGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,57 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.GOST3410KeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.GOST3410Parameters;
+import pdftk.org.bouncycastle.crypto.params.GOST3410PrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.GOST3410PublicKeyParameters;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * a GOST3410 key pair generator.
+ * This generates GOST3410 keys in line with the method described
+ * in GOST R 34.10-94.
+ */
+public class GOST3410KeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+ {
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+
+ private GOST3410KeyGenerationParameters param;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.param = (GOST3410KeyGenerationParameters)param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ BigInteger p, q, a, x, y;
+ GOST3410Parameters GOST3410Params = param.getParameters();
+ SecureRandom random = param.getRandom();
+
+ q = GOST3410Params.getQ();
+ p = GOST3410Params.getP();
+ a = GOST3410Params.getA();
+
+ do
+ {
+ x = new BigInteger(256, random);
+ }
+ while (x.equals(ZERO) || x.compareTo(q) >= 0);
+
+ //
+ // calculate the public key.
+ //
+ y = a.modPow(x, p);
+
+ return new AsymmetricCipherKeyPair(
+ new GOST3410PublicKeyParameters(y, GOST3410Params),
+ new GOST3410PrivateKeyParameters(x, GOST3410Params));
+ }
+ }
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/GOST3410ParametersGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/GOST3410ParametersGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/GOST3410ParametersGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/GOST3410ParametersGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,541 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.params.GOST3410Parameters;
+import pdftk.org.bouncycastle.crypto.params.GOST3410ValidationParameters;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * generate suitable parameters for GOST3410.
+ */
+public class GOST3410ParametersGenerator
+{
+ private int size;
+ private int typeproc;
+ private SecureRandom init_random;
+
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+ private static final BigInteger TWO = BigInteger.valueOf(2);
+
+ /**
+ * initialise the key generator.
+ *
+ * @param size size of the key
+ * @param typeproc type procedure A,B = 1; A',B' - else
+ * @param random random byte source.
+ */
+ public void init(
+ int size,
+ int typeproc,
+ SecureRandom random)
+ {
+ this.size = size;
+ this.typeproc = typeproc;
+ this.init_random = random;
+ }
+
+ //Procedure A
+ private int procedure_A(int x0, int c, BigInteger[] pq, int size)
+ {
+ //Verify and perform condition: 065536)
+ {
+ x0 = init_random.nextInt()/32768;
+ }
+
+ while((c<0 || c>65536) || (c/2==0))
+ {
+ c = init_random.nextInt()/32768 + 1;
+ }
+
+ BigInteger C = new BigInteger(Integer.toString(c));
+ BigInteger constA16 = new BigInteger("19381");
+
+ //step1
+ BigInteger[] y = new BigInteger[1]; // begin length = 1
+ y[0] = new BigInteger(Integer.toString(x0));
+
+ //step 2
+ int[] t = new int[1]; // t - orders; begin length = 1
+ t[0] = size;
+ int s = 0;
+ for (int i=0; t[i]>=17; i++)
+ {
+ // extension array t
+ int tmp_t[] = new int[t.length + 1]; ///////////////
+ System.arraycopy(t,0,tmp_t,0,t.length); // extension
+ t = new int[tmp_t.length]; // array t
+ System.arraycopy(tmp_t, 0, t, 0, tmp_t.length); ///////////////
+
+ t[i+1] = t[i]/2;
+ s = i+1;
+ }
+
+ //step3
+ BigInteger p[] = new BigInteger[s+1];
+ p[s] = new BigInteger("8003",16); //set min prime number length 16 bit
+
+ int m = s-1; //step4
+
+ for (int i=0; i=0)
+ {
+ break; //step 14
+ }
+ else
+ {
+ pq[0] = p[0];
+ pq[1] = p[1];
+ return y[0].intValue(); //return for procedure B step 2
+ }
+ }
+ }
+ return y[0].intValue();
+ }
+
+ //Procedure A'
+ private long procedure_Aa(long x0, long c, BigInteger[] pq, int size)
+ {
+ //Verify and perform condition: 04294967296L)
+ {
+ x0 = init_random.nextInt()*2;
+ }
+
+ while((c<0 || c>4294967296L) || (c/2==0))
+ {
+ c = init_random.nextInt()*2+1;
+ }
+
+ BigInteger C = new BigInteger(Long.toString(c));
+ BigInteger constA32 = new BigInteger("97781173");
+
+ //step1
+ BigInteger[] y = new BigInteger[1]; // begin length = 1
+ y[0] = new BigInteger(Long.toString(x0));
+
+ //step 2
+ int[] t = new int[1]; // t - orders; begin length = 1
+ t[0] = size;
+ int s = 0;
+ for (int i=0; t[i]>=33; i++)
+ {
+ // extension array t
+ int tmp_t[] = new int[t.length + 1]; ///////////////
+ System.arraycopy(t,0,tmp_t,0,t.length); // extension
+ t = new int[tmp_t.length]; // array t
+ System.arraycopy(tmp_t, 0, t, 0, tmp_t.length); ///////////////
+
+ t[i+1] = t[i]/2;
+ s = i+1;
+ }
+
+ //step3
+ BigInteger p[] = new BigInteger[s+1];
+ p[s] = new BigInteger("8000000B",16); //set min prime number length 32 bit
+
+ int m = s-1; //step4
+
+ for (int i=0; i=0)
+ {
+ break; //step 14
+ }
+ else
+ {
+ pq[0] = p[0];
+ pq[1] = p[1];
+ return y[0].longValue(); //return for procedure B' step 2
+ }
+ }
+ }
+ return y[0].longValue();
+ }
+
+ //Procedure B
+ private void procedure_B(int x0, int c, BigInteger[] pq)
+ {
+ //Verify and perform condition: 065536)
+ {
+ x0 = init_random.nextInt()/32768;
+ }
+
+ while((c<0 || c>65536) || (c/2==0))
+ {
+ c = init_random.nextInt()/32768 + 1;
+ }
+
+ BigInteger [] qp = new BigInteger[2];
+ BigInteger q = null, Q = null, p = null;
+ BigInteger C = new BigInteger(Integer.toString(c));
+ BigInteger constA16 = new BigInteger("19381");
+
+ //step1
+ x0 = procedure_A(x0, c, qp, 256);
+ q = qp[0];
+
+ //step2
+ x0 = procedure_A(x0, c, qp, 512);
+ Q = qp[0];
+
+ BigInteger[] y = new BigInteger[65];
+ y[0] = new BigInteger(Integer.toString(x0));
+
+ int tp = 1024;
+
+ step3: for(;;)
+ {
+ //step 3
+ for (int j=0; j<64; j++)
+ {
+ y[j+1] = (y[j].multiply(constA16).add(C)).mod(TWO.pow(16));
+ }
+
+ //step 4
+ BigInteger Y = new BigInteger("0");
+
+ for (int j=0; j<64; j++)
+ {
+ Y = Y.add(y[j].multiply(TWO.pow(16*j)));
+ }
+
+ y[0] = y[64]; //step 5
+
+ //step 6
+ BigInteger N = TWO.pow(tp-1).divide(q.multiply(Q)).
+ add((TWO.pow(tp-1).multiply(Y)).
+ divide(q.multiply(Q).multiply(TWO.pow(1024))));
+
+ if (N.mod(TWO).compareTo(ONE)==0)
+ {
+ N = N.add(ONE);
+ }
+
+ int k = 0; //step 7
+
+ step8: for(;;)
+ {
+ //step 11
+ p = q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))).add(ONE);
+
+ if (p.compareTo(TWO.pow(tp))==1)
+ {
+ continue step3; //step 9
+ }
+
+ //step10
+ if ((TWO.modPow(q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)==0) &&
+ (TWO.modPow(q.multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)!=0))
+ {
+ pq[0] = p;
+ pq[1] = q;
+ return;
+ }
+ else
+ {
+ k += 2;
+ continue step8;
+ }
+ }
+ }
+ }
+
+ //Procedure B'
+ private void procedure_Bb(long x0, long c, BigInteger[] pq)
+ {
+ //Verify and perform condition: 04294967296L)
+ {
+ x0 = init_random.nextInt()*2;
+ }
+
+ while((c<0 || c>4294967296L) || (c/2==0))
+ {
+ c = init_random.nextInt()*2+1;
+ }
+
+ BigInteger [] qp = new BigInteger[2];
+ BigInteger q = null, Q = null, p = null;
+ BigInteger C = new BigInteger(Long.toString(c));
+ BigInteger constA32 = new BigInteger("97781173");
+
+ //step1
+ x0 = procedure_Aa(x0, c, qp, 256);
+ q = qp[0];
+
+ //step2
+ x0 = procedure_Aa(x0, c, qp, 512);
+ Q = qp[0];
+
+ BigInteger[] y = new BigInteger[33];
+ y[0] = new BigInteger(Long.toString(x0));
+
+ int tp = 1024;
+
+ step3: for(;;)
+ {
+ //step 3
+ for (int j=0; j<32; j++)
+ {
+ y[j+1] = (y[j].multiply(constA32).add(C)).mod(TWO.pow(32));
+ }
+
+ //step 4
+ BigInteger Y = new BigInteger("0");
+ for (int j=0; j<32; j++)
+ {
+ Y = Y.add(y[j].multiply(TWO.pow(32*j)));
+ }
+
+ y[0] = y[32]; //step 5
+
+ //step 6
+ BigInteger N = TWO.pow(tp-1).divide(q.multiply(Q)).
+ add((TWO.pow(tp-1).multiply(Y)).
+ divide(q.multiply(Q).multiply(TWO.pow(1024))));
+
+ if (N.mod(TWO).compareTo(ONE)==0)
+ {
+ N = N.add(ONE);
+ }
+
+ int k = 0; //step 7
+
+ step8: for(;;)
+ {
+ //step 11
+ p = q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))).add(ONE);
+
+ if (p.compareTo(TWO.pow(tp))==1)
+ {
+ continue step3; //step 9
+ }
+
+ //step10
+ if ((TWO.modPow(q.multiply(Q).multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)==0) &&
+ (TWO.modPow(q.multiply(N.add(BigInteger.valueOf(k))),p).compareTo(ONE)!=0))
+ {
+ pq[0] = p;
+ pq[1] = q;
+ return;
+ }
+ else
+ {
+ k += 2;
+ continue step8;
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Procedure C
+ * procedure generates the a value from the given p,q,
+ * returning the a value.
+ */
+ private BigInteger procedure_C(BigInteger p, BigInteger q)
+ {
+ BigInteger pSub1 = p.subtract(ONE);
+ BigInteger pSub1DivQ = pSub1.divide(q);
+ int length = p.bitLength();
+
+ for(;;)
+ {
+ BigInteger d = new BigInteger(length, init_random);
+
+ // 1 < d < p-1
+ if (d.compareTo(ONE) > 0 && d.compareTo(pSub1) < 0)
+ {
+ BigInteger a = d.modPow(pSub1DivQ, p);
+
+ if (a.compareTo(ONE) != 0)
+ {
+ return a;
+ }
+ }
+ }
+ }
+
+ /**
+ * which generates the p , q and a values from the given parameters,
+ * returning the GOST3410Parameters object.
+ */
+ public GOST3410Parameters generateParameters()
+ {
+ BigInteger [] pq = new BigInteger[2];
+ BigInteger q = null, p = null, a = null;
+
+ int x0, c;
+ long x0L, cL;
+
+ if (typeproc==1)
+ {
+ x0 = init_random.nextInt();
+ c = init_random.nextInt();
+
+ switch(size)
+ {
+ case 512:
+ procedure_A(x0, c, pq, 512);
+ break;
+ case 1024:
+ procedure_B(x0, c, pq);
+ break;
+ default:
+ throw new IllegalArgumentException("Ooops! key size 512 or 1024 bit.");
+ }
+ p = pq[0]; q = pq[1];
+ a = procedure_C(p, q);
+ //System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
+ //System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
+ return new GOST3410Parameters(p, q, a, new GOST3410ValidationParameters(x0, c));
+ }
+ else
+ {
+ x0L = init_random.nextLong();
+ cL = init_random.nextLong();
+
+ switch(size)
+ {
+ case 512:
+ procedure_Aa(x0L, cL, pq, 512);
+ break;
+ case 1024:
+ procedure_Bb(x0L, cL, pq);
+ break;
+ default:
+ throw new IllegalStateException("Ooops! key size 512 or 1024 bit.");
+ }
+ p = pq[0]; q = pq[1];
+ a = procedure_C(p, q);
+ //System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
+ //System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
+ return new GOST3410Parameters(p, q, a, new GOST3410ValidationParameters(x0L, cL));
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/HKDFBytesGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/HKDFBytesGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/HKDFBytesGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/HKDFBytesGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,161 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.DerivationFunction;
+import pdftk.org.bouncycastle.crypto.DerivationParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.macs.HMac;
+import pdftk.org.bouncycastle.crypto.params.HKDFParameters;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * HMAC-based Extract-and-Expand Key Derivation Function (HKDF) implemented
+ * according to IETF RFC 5869, May 2010 as specified by H. Krawczyk, IBM
+ * Research & P. Eronen, Nokia. It uses a HMac internally to compute de OKM
+ * (output keying material) and is likely to have better security properties
+ * than KDF's based on just a hash function.
+ */
+public class HKDFBytesGenerator
+ implements DerivationFunction
+{
+
+ private HMac hMacHash;
+ private int hashLen;
+
+ private byte[] info;
+ private byte[] currentT;
+
+ private int generatedBytes;
+
+ /**
+ * Creates a HKDFBytesGenerator based on the given hash function.
+ *
+ * @param hash the digest to be used as the source of generatedBytes bytes
+ */
+ public HKDFBytesGenerator(Digest hash)
+ {
+ this.hMacHash = new HMac(hash);
+ this.hashLen = hash.getDigestSize();
+ }
+
+ public void init(DerivationParameters param)
+ {
+ if (!(param instanceof HKDFParameters))
+ {
+ throw new IllegalArgumentException(
+ "HKDF parameters required for HKDFBytesGenerator");
+ }
+
+ HKDFParameters params = (HKDFParameters)param;
+ if (params.skipExtract())
+ {
+ // use IKM directly as PRK
+ hMacHash.init(new KeyParameter(params.getIKM()));
+ }
+ else
+ {
+ hMacHash.init(extract(params.getSalt(), params.getIKM()));
+ }
+
+ info = params.getInfo();
+
+ generatedBytes = 0;
+ currentT = new byte[hashLen];
+ }
+
+ /**
+ * Performs the extract part of the key derivation function.
+ *
+ * @param salt the salt to use
+ * @param ikm the input keying material
+ * @return the PRK as KeyParameter
+ */
+ private KeyParameter extract(byte[] salt, byte[] ikm)
+ {
+ hMacHash.init(new KeyParameter(ikm));
+ if (salt == null)
+ {
+ // TODO check if hashLen is indeed same as HMAC size
+ hMacHash.init(new KeyParameter(new byte[hashLen]));
+ }
+ else
+ {
+ hMacHash.init(new KeyParameter(salt));
+ }
+
+ hMacHash.update(ikm, 0, ikm.length);
+
+ byte[] prk = new byte[hashLen];
+ hMacHash.doFinal(prk, 0);
+ return new KeyParameter(prk);
+ }
+
+ /**
+ * Performs the expand part of the key derivation function, using currentT
+ * as input and output buffer.
+ *
+ * @throws DataLengthException if the total number of bytes generated is larger than the one
+ * specified by RFC 5869 (255 * HashLen)
+ */
+ private void expandNext()
+ throws DataLengthException
+ {
+ int n = generatedBytes / hashLen + 1;
+ if (n >= 256)
+ {
+ throw new DataLengthException(
+ "HKDF cannot generate more than 255 blocks of HashLen size");
+ }
+ // special case for T(0): T(0) is empty, so no update
+ if (generatedBytes != 0)
+ {
+ hMacHash.update(currentT, 0, hashLen);
+ }
+ hMacHash.update(info, 0, info.length);
+ hMacHash.update((byte)n);
+ hMacHash.doFinal(currentT, 0);
+ }
+
+ public Digest getDigest()
+ {
+ return hMacHash.getUnderlyingDigest();
+ }
+
+ public int generateBytes(byte[] out, int outOff, int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+
+ if (generatedBytes + len > 255 * hashLen)
+ {
+ throw new DataLengthException(
+ "HKDF may only be used for 255 * HashLen bytes of output");
+ }
+
+ if (generatedBytes % hashLen == 0)
+ {
+ expandNext();
+ }
+
+ // copy what is left in the currentT (1..hash
+ int toGenerate = len;
+ int posInT = generatedBytes % hashLen;
+ int leftInT = hashLen - generatedBytes % hashLen;
+ int toCopy = Math.min(leftInT, toGenerate);
+ System.arraycopy(currentT, posInT, out, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+
+ while (toGenerate > 0)
+ {
+ expandNext();
+ toCopy = Math.min(hashLen, toGenerate);
+ System.arraycopy(currentT, 0, out, outOff, toCopy);
+ generatedBytes += toCopy;
+ toGenerate -= toCopy;
+ outOff += toCopy;
+ }
+
+ return len;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/KDF1BytesGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/KDF1BytesGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/KDF1BytesGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/KDF1BytesGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.Digest;
+
+/**
+ * KDF1 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+ *
+ * This implementation is based on ISO 18033/IEEE P1363a.
+ */
+public class KDF1BytesGenerator
+ extends BaseKDFBytesGenerator
+{
+ /**
+ * Construct a KDF1 byte generator.
+ *
+ * @param digest the digest to be used as the source of derived keys.
+ */
+ public KDF1BytesGenerator(
+ Digest digest)
+ {
+ super(0, digest);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/KDF2BytesGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/KDF2BytesGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/KDF2BytesGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/KDF2BytesGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,24 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.Digest;
+
+/**
+ * KDF2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+ *
+ * This implementation is based on IEEE P1363/ISO 18033.
+ */
+public class KDF2BytesGenerator
+ extends BaseKDFBytesGenerator
+{
+ /**
+ * Construct a KDF2 bytes generator. Generates key material
+ * according to IEEE P1363 or ISO 18033 depending on the initialisation.
+ *
+ * @param digest the digest to be used as the source of derived keys.
+ */
+ public KDF2BytesGenerator(
+ Digest digest)
+ {
+ super(1, digest);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/MGF1BytesGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/MGF1BytesGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/MGF1BytesGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/MGF1BytesGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,114 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.DerivationFunction;
+import pdftk.org.bouncycastle.crypto.DerivationParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.params.MGFParameters;
+
+/**
+ * Generator for MGF1 as defined in PKCS 1v2
+ */
+public class MGF1BytesGenerator
+ implements DerivationFunction
+{
+ private Digest digest;
+ private byte[] seed;
+ private int hLen;
+
+ /**
+ * @param digest the digest to be used as the source of generated bytes
+ */
+ public MGF1BytesGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+ this.hLen = digest.getDigestSize();
+ }
+
+ public void init(
+ DerivationParameters param)
+ {
+ if (!(param instanceof MGFParameters))
+ {
+ throw new IllegalArgumentException("MGF parameters required for MGF1Generator");
+ }
+
+ MGFParameters p = (MGFParameters)param;
+
+ seed = p.getSeed();
+ }
+
+ /**
+ * return the underlying digest.
+ */
+ public Digest getDigest()
+ {
+ return digest;
+ }
+
+ /**
+ * int to octet string.
+ */
+ private void ItoOSP(
+ int i,
+ byte[] sp)
+ {
+ sp[0] = (byte)(i >>> 24);
+ sp[1] = (byte)(i >>> 16);
+ sp[2] = (byte)(i >>> 8);
+ sp[3] = (byte)(i >>> 0);
+ }
+
+ /**
+ * fill len bytes of the output buffer with bytes generated from
+ * the derivation function.
+ *
+ * @throws DataLengthException if the out buffer is too small.
+ */
+ public int generateBytes(
+ byte[] out,
+ int outOff,
+ int len)
+ throws DataLengthException, IllegalArgumentException
+ {
+ if ((out.length - len) < outOff)
+ {
+ throw new DataLengthException("output buffer too small");
+ }
+
+ byte[] hashBuf = new byte[hLen];
+ byte[] C = new byte[4];
+ int counter = 0;
+
+ digest.reset();
+
+ if (len > hLen)
+ {
+ do
+ {
+ ItoOSP(counter, C);
+
+ digest.update(seed, 0, seed.length);
+ digest.update(C, 0, C.length);
+ digest.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, out, outOff + counter * hLen, hLen);
+ }
+ while (++counter < (len / hLen));
+ }
+
+ if ((counter * hLen) < len)
+ {
+ ItoOSP(counter, C);
+
+ digest.update(seed, 0, seed.length);
+ digest.update(C, 0, C.length);
+ digest.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, out, outOff + counter * hLen, len - (counter * hLen));
+ }
+
+ return len;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/NaccacheSternKeyPairGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/NaccacheSternKeyPairGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/NaccacheSternKeyPairGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/NaccacheSternKeyPairGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,365 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.NaccacheSternKeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.NaccacheSternKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.NaccacheSternPrivateKeyParameters;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Vector;
+
+/**
+ * Key generation parameters for NaccacheStern cipher. For details on this cipher, please see
+ *
+ * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+ */
+public class NaccacheSternKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+
+ private static int[] smallPrimes =
+ {
+ 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
+ 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
+ 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
+ 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331,
+ 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431,
+ 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
+ 541, 547, 557
+ };
+
+ private NaccacheSternKeyGenerationParameters param;
+
+ private static final BigInteger ONE = BigInteger.valueOf(1); // JDK 1.1 compatibility
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator#init(pdftk.org.bouncycastle.crypto.KeyGenerationParameters)
+ */
+ public void init(KeyGenerationParameters param)
+ {
+ this.param = (NaccacheSternKeyGenerationParameters)param;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator#generateKeyPair()
+ */
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ int strength = param.getStrength();
+ SecureRandom rand = param.getRandom();
+ int certainty = param.getCertainty();
+ boolean debug = param.isDebug();
+
+ if (debug)
+ {
+ System.out.println("Fetching first " + param.getCntSmallPrimes() + " primes.");
+ }
+
+ Vector smallPrimes = findFirstPrimes(param.getCntSmallPrimes());
+ smallPrimes = permuteList(smallPrimes, rand);
+
+ BigInteger u = ONE;
+ BigInteger v = ONE;
+
+ for (int i = 0; i < smallPrimes.size() / 2; i++)
+ {
+ u = u.multiply((BigInteger)smallPrimes.elementAt(i));
+ }
+ for (int i = smallPrimes.size() / 2; i < smallPrimes.size(); i++)
+ {
+ v = v.multiply((BigInteger)smallPrimes.elementAt(i));
+ }
+
+ BigInteger sigma = u.multiply(v);
+
+ // n = (2 a u p_ + 1 ) ( 2 b v q_ + 1)
+ // -> |n| = strength
+ // |2| = 1 in bits
+ // -> |a| * |b| = |n| - |u| - |v| - |p_| - |q_| - |2| -|2|
+ // remainingStrength = strength - sigma.bitLength() - p_.bitLength() -
+ // q_.bitLength() - 1 -1
+ int remainingStrength = strength - sigma.bitLength() - 48;
+ BigInteger a = generatePrime(remainingStrength / 2 + 1, certainty, rand);
+ BigInteger b = generatePrime(remainingStrength / 2 + 1, certainty, rand);
+
+ BigInteger p_;
+ BigInteger q_;
+ BigInteger p;
+ BigInteger q;
+ long tries = 0;
+ if (debug)
+ {
+ System.out.println("generating p and q");
+ }
+
+ BigInteger _2au = a.multiply(u).shiftLeft(1);
+ BigInteger _2bv = b.multiply(v).shiftLeft(1);
+
+ for (;;)
+ {
+ tries++;
+
+ p_ = generatePrime(24, certainty, rand);
+
+ p = p_.multiply(_2au).add(ONE);
+
+ if (!p.isProbablePrime(certainty))
+ {
+ continue;
+ }
+
+ for (;;)
+ {
+ q_ = generatePrime(24, certainty, rand);
+
+ if (p_.equals(q_))
+ {
+ continue;
+ }
+
+ q = q_.multiply(_2bv).add(ONE);
+
+ if (q.isProbablePrime(certainty))
+ {
+ break;
+ }
+ }
+
+ if (!sigma.gcd(p_.multiply(q_)).equals(ONE))
+ {
+ // System.out.println("sigma.gcd(p_.mult(q_)) != 1!\n p_: " + p_
+ // +"\n q_: "+ q_ );
+ continue;
+ }
+
+ if (p.multiply(q).bitLength() < strength)
+ {
+ if (debug)
+ {
+ System.out.println("key size too small. Should be " + strength + " but is actually "
+ + p.multiply(q).bitLength());
+ }
+ continue;
+ }
+ break;
+ }
+
+ if (debug)
+ {
+ System.out.println("needed " + tries + " tries to generate p and q.");
+ }
+
+ BigInteger n = p.multiply(q);
+ BigInteger phi_n = p.subtract(ONE).multiply(q.subtract(ONE));
+ BigInteger g;
+ tries = 0;
+ if (debug)
+ {
+ System.out.println("generating g");
+ }
+ for (;;)
+ {
+
+ Vector gParts = new Vector();
+ for (int ind = 0; ind != smallPrimes.size(); ind++)
+ {
+ BigInteger i = (BigInteger)smallPrimes.elementAt(ind);
+ BigInteger e = phi_n.divide(i);
+
+ for (;;)
+ {
+ tries++;
+ g = new BigInteger(strength, certainty, rand);
+ if (g.modPow(e, n).equals(ONE))
+ {
+ continue;
+ }
+ gParts.addElement(g);
+ break;
+ }
+ }
+ g = ONE;
+ for (int i = 0; i < smallPrimes.size(); i++)
+ {
+ g = g.multiply(((BigInteger)gParts.elementAt(i)).modPow(sigma.divide((BigInteger)smallPrimes.elementAt(i)), n)).mod(n);
+ }
+
+ // make sure that g is not divisible by p_i or q_i
+ boolean divisible = false;
+ for (int i = 0; i < smallPrimes.size(); i++)
+ {
+ if (g.modPow(phi_n.divide((BigInteger)smallPrimes.elementAt(i)), n).equals(ONE))
+ {
+ if (debug)
+ {
+ System.out.println("g has order phi(n)/" + smallPrimes.elementAt(i) + "\n g: " + g);
+ }
+ divisible = true;
+ break;
+ }
+ }
+
+ if (divisible)
+ {
+ continue;
+ }
+
+ // make sure that g has order > phi_n/4
+
+ if (g.modPow(phi_n.divide(BigInteger.valueOf(4)), n).equals(ONE))
+ {
+ if (debug)
+ {
+ System.out.println("g has order phi(n)/4\n g:" + g);
+ }
+ continue;
+ }
+
+ if (g.modPow(phi_n.divide(p_), n).equals(ONE))
+ {
+ if (debug)
+ {
+ System.out.println("g has order phi(n)/p'\n g: " + g);
+ }
+ continue;
+ }
+ if (g.modPow(phi_n.divide(q_), n).equals(ONE))
+ {
+ if (debug)
+ {
+ System.out.println("g has order phi(n)/q'\n g: " + g);
+ }
+ continue;
+ }
+ if (g.modPow(phi_n.divide(a), n).equals(ONE))
+ {
+ if (debug)
+ {
+ System.out.println("g has order phi(n)/a\n g: " + g);
+ }
+ continue;
+ }
+ if (g.modPow(phi_n.divide(b), n).equals(ONE))
+ {
+ if (debug)
+ {
+ System.out.println("g has order phi(n)/b\n g: " + g);
+ }
+ continue;
+ }
+ break;
+ }
+ if (debug)
+ {
+ System.out.println("needed " + tries + " tries to generate g");
+ System.out.println();
+ System.out.println("found new NaccacheStern cipher variables:");
+ System.out.println("smallPrimes: " + smallPrimes);
+ System.out.println("sigma:...... " + sigma + " (" + sigma.bitLength() + " bits)");
+ System.out.println("a:.......... " + a);
+ System.out.println("b:.......... " + b);
+ System.out.println("p':......... " + p_);
+ System.out.println("q':......... " + q_);
+ System.out.println("p:.......... " + p);
+ System.out.println("q:.......... " + q);
+ System.out.println("n:.......... " + n);
+ System.out.println("phi(n):..... " + phi_n);
+ System.out.println("g:.......... " + g);
+ System.out.println();
+ }
+
+ return new AsymmetricCipherKeyPair(new NaccacheSternKeyParameters(false, g, n, sigma.bitLength()),
+ new NaccacheSternPrivateKeyParameters(g, n, sigma.bitLength(), smallPrimes, phi_n));
+ }
+
+ private static BigInteger generatePrime(
+ int bitLength,
+ int certainty,
+ SecureRandom rand)
+ {
+ BigInteger p_ = new BigInteger(bitLength, certainty, rand);
+ while (p_.bitLength() != bitLength)
+ {
+ p_ = new BigInteger(bitLength, certainty, rand);
+ }
+ return p_;
+ }
+
+ /**
+ * Generates a permuted ArrayList from the original one. The original List
+ * is not modified
+ *
+ * @param arr
+ * the ArrayList to be permuted
+ * @param rand
+ * the source of Randomness for permutation
+ * @return a new ArrayList with the permuted elements.
+ */
+ private static Vector permuteList(
+ Vector arr,
+ SecureRandom rand)
+ {
+ Vector retval = new Vector();
+ Vector tmp = new Vector();
+ for (int i = 0; i < arr.size(); i++)
+ {
+ tmp.addElement(arr.elementAt(i));
+ }
+ retval.addElement(tmp.elementAt(0));
+ tmp.removeElementAt(0);
+ while (tmp.size() != 0)
+ {
+ retval.insertElementAt(tmp.elementAt(0), getInt(rand, retval.size() + 1));
+ tmp.removeElementAt(0);
+ }
+ return retval;
+ }
+
+ private static int getInt(
+ SecureRandom rand,
+ int n)
+ {
+ if ((n & -n) == n)
+ {
+ return (int)((n * (long)(rand.nextInt() & 0x7fffffff)) >> 31);
+ }
+
+ int bits, val;
+ do
+ {
+ bits = rand.nextInt() & 0x7fffffff;
+ val = bits % n;
+ }
+ while (bits - val + (n-1) < 0);
+
+ return val;
+ }
+
+ /**
+ * Finds the first 'count' primes starting with 3
+ *
+ * @param count
+ * the number of primes to find
+ * @return a vector containing the found primes as Integer
+ */
+ private static Vector findFirstPrimes(
+ int count)
+ {
+ Vector primes = new Vector(count);
+
+ for (int i = 0; i != count; i++)
+ {
+ primes.addElement(BigInteger.valueOf(smallPrimes[i]));
+ }
+
+ return primes;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/OpenSSLPBEParametersGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,131 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.PBEParametersGenerator;
+import pdftk.org.bouncycastle.crypto.digests.MD5Digest;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Generator for PBE derived keys and ivs as usd by OpenSSL.
+ *
+ * The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an
+ * iteration count of 1.
+ *
+ */
+public class OpenSSLPBEParametersGenerator
+ extends PBEParametersGenerator
+{
+ private Digest digest = new MD5Digest();
+
+ /**
+ * Construct a OpenSSL Parameters generator.
+ */
+ public OpenSSLPBEParametersGenerator()
+ {
+ }
+
+ /**
+ * Initialise - note the iteration count for this algorithm is fixed at 1.
+ *
+ * @param password password to use.
+ * @param salt salt to use.
+ */
+ public void init(
+ byte[] password,
+ byte[] salt)
+ {
+ super.init(password, salt, 1);
+ }
+
+ /**
+ * the derived key function, the ith hash of the password and the salt.
+ */
+ private byte[] generateDerivedKey(
+ int bytesNeeded)
+ {
+ byte[] buf = new byte[digest.getDigestSize()];
+ byte[] key = new byte[bytesNeeded];
+ int offset = 0;
+
+ for (;;)
+ {
+ digest.update(password, 0, password.length);
+ digest.update(salt, 0, salt.length);
+
+ digest.doFinal(buf, 0);
+
+ int len = (bytesNeeded > buf.length) ? buf.length : bytesNeeded;
+ System.arraycopy(buf, 0, key, offset, len);
+ offset += len;
+
+ // check if we need any more
+ bytesNeeded -= len;
+ if (bytesNeeded == 0)
+ {
+ break;
+ }
+
+ // do another round
+ digest.reset();
+ digest.update(buf, 0, buf.length);
+ }
+
+ return key;
+ }
+
+ /**
+ * Generate a key parameter derived from the password, salt, and iteration
+ * count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ * @exception IllegalArgumentException if the key length larger than the base hash size.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ byte[] dKey = generateDerivedKey(keySize);
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+
+ /**
+ * Generate a key with initialisation vector parameter derived from
+ * the password, salt, and iteration count we are currently initialised
+ * with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @param ivSize the size of the iv we want (in bits)
+ * @return a ParametersWithIV object.
+ * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize,
+ int ivSize)
+ {
+ keySize = keySize / 8;
+ ivSize = ivSize / 8;
+
+ byte[] dKey = generateDerivedKey(keySize + ivSize);
+
+ return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
+ }
+
+ /**
+ * Generate a key parameter for use with a MAC derived from the password,
+ * salt, and iteration count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ * @exception IllegalArgumentException if the key length larger than the base hash size.
+ */
+ public CipherParameters generateDerivedMacParameters(
+ int keySize)
+ {
+ return generateDerivedParameters(keySize);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/PKCS12ParametersGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,221 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.ExtendedDigest;
+import pdftk.org.bouncycastle.crypto.PBEParametersGenerator;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Generator for PBE derived keys and ivs as defined by PKCS 12 V1.0.
+ *
+ * The document this implementation is based on can be found at
+ *
+ * RSA's PKCS12 Page
+ */
+public class PKCS12ParametersGenerator
+ extends PBEParametersGenerator
+{
+ public static final int KEY_MATERIAL = 1;
+ public static final int IV_MATERIAL = 2;
+ public static final int MAC_MATERIAL = 3;
+
+ private Digest digest;
+
+ private int u;
+ private int v;
+
+ /**
+ * Construct a PKCS 12 Parameters generator. This constructor will
+ * accept any digest which also implements ExtendedDigest.
+ *
+ * @param digest the digest to be used as the source of derived keys.
+ * @exception IllegalArgumentException if an unknown digest is passed in.
+ */
+ public PKCS12ParametersGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+ if (digest instanceof ExtendedDigest)
+ {
+ u = digest.getDigestSize();
+ v = ((ExtendedDigest)digest).getByteLength();
+ }
+ else
+ {
+ throw new IllegalArgumentException("Digest " + digest.getAlgorithmName() + " unsupported");
+ }
+ }
+
+ /**
+ * add a + b + 1, returning the result in a. The a value is treated
+ * as a BigInteger of length (b.length * 8) bits. The result is
+ * modulo 2^b.length in case of overflow.
+ */
+ private void adjust(
+ byte[] a,
+ int aOff,
+ byte[] b)
+ {
+ int x = (b[b.length - 1] & 0xff) + (a[aOff + b.length - 1] & 0xff) + 1;
+
+ a[aOff + b.length - 1] = (byte)x;
+ x >>>= 8;
+
+ for (int i = b.length - 2; i >= 0; i--)
+ {
+ x += (b[i] & 0xff) + (a[aOff + i] & 0xff);
+ a[aOff + i] = (byte)x;
+ x >>>= 8;
+ }
+ }
+
+ /**
+ * generation of a derived key ala PKCS12 V1.0.
+ */
+ private byte[] generateDerivedKey(
+ int idByte,
+ int n)
+ {
+ byte[] D = new byte[v];
+ byte[] dKey = new byte[n];
+
+ for (int i = 0; i != D.length; i++)
+ {
+ D[i] = (byte)idByte;
+ }
+
+ byte[] S;
+
+ if ((salt != null) && (salt.length != 0))
+ {
+ S = new byte[v * ((salt.length + v - 1) / v)];
+
+ for (int i = 0; i != S.length; i++)
+ {
+ S[i] = salt[i % salt.length];
+ }
+ }
+ else
+ {
+ S = new byte[0];
+ }
+
+ byte[] P;
+
+ if ((password != null) && (password.length != 0))
+ {
+ P = new byte[v * ((password.length + v - 1) / v)];
+
+ for (int i = 0; i != P.length; i++)
+ {
+ P[i] = password[i % password.length];
+ }
+ }
+ else
+ {
+ P = new byte[0];
+ }
+
+ byte[] I = new byte[S.length + P.length];
+
+ System.arraycopy(S, 0, I, 0, S.length);
+ System.arraycopy(P, 0, I, S.length, P.length);
+
+ byte[] B = new byte[v];
+ int c = (n + u - 1) / u;
+
+ for (int i = 1; i <= c; i++)
+ {
+ byte[] A = new byte[u];
+
+ digest.update(D, 0, D.length);
+ digest.update(I, 0, I.length);
+ digest.doFinal(A, 0);
+ for (int j = 1; j < iterationCount; j++)
+ {
+ digest.update(A, 0, A.length);
+ digest.doFinal(A, 0);
+ }
+
+ for (int j = 0; j != B.length; j++)
+ {
+ B[j] = A[j % A.length];
+ }
+
+ for (int j = 0; j != I.length / v; j++)
+ {
+ adjust(I, j * v, B);
+ }
+
+ if (i == c)
+ {
+ System.arraycopy(A, 0, dKey, (i - 1) * u, dKey.length - ((i - 1) * u));
+ }
+ else
+ {
+ System.arraycopy(A, 0, dKey, (i - 1) * u, A.length);
+ }
+ }
+
+ return dKey;
+ }
+
+ /**
+ * Generate a key parameter derived from the password, salt, and iteration
+ * count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ byte[] dKey = generateDerivedKey(KEY_MATERIAL, keySize);
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+
+ /**
+ * Generate a key with initialisation vector parameter derived from
+ * the password, salt, and iteration count we are currently initialised
+ * with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @param ivSize the size of the iv we want (in bits)
+ * @return a ParametersWithIV object.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize,
+ int ivSize)
+ {
+ keySize = keySize / 8;
+ ivSize = ivSize / 8;
+
+ byte[] dKey = generateDerivedKey(KEY_MATERIAL, keySize);
+
+ byte[] iv = generateDerivedKey(IV_MATERIAL, ivSize);
+
+ return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), iv, 0, ivSize);
+ }
+
+ /**
+ * Generate a key parameter for use with a MAC derived from the password,
+ * salt, and iteration count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ */
+ public CipherParameters generateDerivedMacParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ byte[] dKey = generateDerivedKey(MAC_MATERIAL, keySize);
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/PKCS5S1ParametersGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,119 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.PBEParametersGenerator;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 1.
+ * Note this generator is limited to the size of the hash produced by the
+ * digest used to drive it.
+ *
+ * The document this implementation is based on can be found at
+ *
+ * RSA's PKCS5 Page
+ */
+public class PKCS5S1ParametersGenerator
+ extends PBEParametersGenerator
+{
+ private Digest digest;
+
+ /**
+ * Construct a PKCS 5 Scheme 1 Parameters generator.
+ *
+ * @param digest the digest to be used as the source of derived keys.
+ */
+ public PKCS5S1ParametersGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+ }
+
+ /**
+ * the derived key function, the ith hash of the password and the salt.
+ */
+ private byte[] generateDerivedKey()
+ {
+ byte[] digestBytes = new byte[digest.getDigestSize()];
+
+ digest.update(password, 0, password.length);
+ digest.update(salt, 0, salt.length);
+
+ digest.doFinal(digestBytes, 0);
+ for (int i = 1; i < iterationCount; i++)
+ {
+ digest.update(digestBytes, 0, digestBytes.length);
+ digest.doFinal(digestBytes, 0);
+ }
+
+ return digestBytes;
+ }
+
+ /**
+ * Generate a key parameter derived from the password, salt, and iteration
+ * count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ * @exception IllegalArgumentException if the key length larger than the base hash size.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ if (keySize > digest.getDigestSize())
+ {
+ throw new IllegalArgumentException(
+ "Can't generate a derived key " + keySize + " bytes long.");
+ }
+
+ byte[] dKey = generateDerivedKey();
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+
+ /**
+ * Generate a key with initialisation vector parameter derived from
+ * the password, salt, and iteration count we are currently initialised
+ * with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @param ivSize the size of the iv we want (in bits)
+ * @return a ParametersWithIV object.
+ * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize,
+ int ivSize)
+ {
+ keySize = keySize / 8;
+ ivSize = ivSize / 8;
+
+ if ((keySize + ivSize) > digest.getDigestSize())
+ {
+ throw new IllegalArgumentException(
+ "Can't generate a derived key " + (keySize + ivSize) + " bytes long.");
+ }
+
+ byte[] dKey = generateDerivedKey();
+
+ return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
+ }
+
+ /**
+ * Generate a key parameter for use with a MAC derived from the password,
+ * salt, and iteration count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ * @exception IllegalArgumentException if the key length larger than the base hash size.
+ */
+ public CipherParameters generateDerivedMacParameters(
+ int keySize)
+ {
+ return generateDerivedParameters(keySize);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/PKCS5S2ParametersGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,158 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.PBEParametersGenerator;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+import pdftk.org.bouncycastle.crypto.macs.HMac;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Generator for PBE derived keys and ivs as defined by PKCS 5 V2.0 Scheme 2.
+ * This generator uses a SHA-1 HMac as the calculation function.
+ *
+ * The document this implementation is based on can be found at
+ *
+ * RSA's PKCS5 Page
+ */
+public class PKCS5S2ParametersGenerator
+ extends PBEParametersGenerator
+{
+ private Mac hMac;
+
+ /**
+ * construct a PKCS5 Scheme 2 Parameters generator.
+ */
+ public PKCS5S2ParametersGenerator()
+ {
+ this(new SHA1Digest());
+ }
+
+ public PKCS5S2ParametersGenerator(Digest digest)
+ {
+ hMac = new HMac(digest);
+ }
+
+ private void F(
+ byte[] P,
+ byte[] S,
+ int c,
+ byte[] iBuf,
+ byte[] out,
+ int outOff)
+ {
+ byte[] state = new byte[hMac.getMacSize()];
+ CipherParameters param = new KeyParameter(P);
+
+ hMac.init(param);
+
+ if (S != null)
+ {
+ hMac.update(S, 0, S.length);
+ }
+
+ hMac.update(iBuf, 0, iBuf.length);
+
+ hMac.doFinal(state, 0);
+
+ System.arraycopy(state, 0, out, outOff, state.length);
+
+ if (c == 0)
+ {
+ throw new IllegalArgumentException("iteration count must be at least 1.");
+ }
+
+ for (int count = 1; count < c; count++)
+ {
+ hMac.init(param);
+ hMac.update(state, 0, state.length);
+ hMac.doFinal(state, 0);
+
+ for (int j = 0; j != state.length; j++)
+ {
+ out[outOff + j] ^= state[j];
+ }
+ }
+ }
+
+ private void intToOctet(
+ byte[] buf,
+ int i)
+ {
+ buf[0] = (byte)(i >>> 24);
+ buf[1] = (byte)(i >>> 16);
+ buf[2] = (byte)(i >>> 8);
+ buf[3] = (byte)i;
+ }
+
+ private byte[] generateDerivedKey(
+ int dkLen)
+ {
+ int hLen = hMac.getMacSize();
+ int l = (dkLen + hLen - 1) / hLen;
+ byte[] iBuf = new byte[4];
+ byte[] out = new byte[l * hLen];
+
+ for (int i = 1; i <= l; i++)
+ {
+ intToOctet(iBuf, i);
+
+ F(password, salt, iterationCount, iBuf, out, (i - 1) * hLen);
+ }
+
+ return out;
+ }
+
+ /**
+ * Generate a key parameter derived from the password, salt, and iteration
+ * count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize)
+ {
+ keySize = keySize / 8;
+
+ byte[] dKey = generateDerivedKey(keySize);
+
+ return new KeyParameter(dKey, 0, keySize);
+ }
+
+ /**
+ * Generate a key with initialisation vector parameter derived from
+ * the password, salt, and iteration count we are currently initialised
+ * with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @param ivSize the size of the iv we want (in bits)
+ * @return a ParametersWithIV object.
+ */
+ public CipherParameters generateDerivedParameters(
+ int keySize,
+ int ivSize)
+ {
+ keySize = keySize / 8;
+ ivSize = ivSize / 8;
+
+ byte[] dKey = generateDerivedKey(keySize + ivSize);
+
+ return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
+ }
+
+ /**
+ * Generate a key parameter for use with a MAC derived from the password,
+ * salt, and iteration count we are currently initialised with.
+ *
+ * @param keySize the size of the key we want (in bits)
+ * @return a KeyParameter object.
+ */
+ public CipherParameters generateDerivedMacParameters(
+ int keySize)
+ {
+ return generateDerivedParameters(keySize);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/RSABlindingFactorGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/RSABlindingFactorGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/RSABlindingFactorGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/RSABlindingFactorGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,77 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * Generate a random factor suitable for use with RSA blind signatures
+ * as outlined in Chaum's blinding and unblinding as outlined in
+ * "Handbook of Applied Cryptography", page 475.
+ */
+public class RSABlindingFactorGenerator
+{
+ private static BigInteger ZERO = BigInteger.valueOf(0);
+ private static BigInteger ONE = BigInteger.valueOf(1);
+
+ private RSAKeyParameters key;
+ private SecureRandom random;
+
+ /**
+ * Initialise the factor generator
+ *
+ * @param param the necessary RSA key parameters.
+ */
+ public void init(
+ CipherParameters param)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ key = (RSAKeyParameters)rParam.getParameters();
+ random = rParam.getRandom();
+ }
+ else
+ {
+ key = (RSAKeyParameters)param;
+ random = new SecureRandom();
+ }
+
+ if (key instanceof RSAPrivateCrtKeyParameters)
+ {
+ throw new IllegalArgumentException("generator requires RSA public key");
+ }
+ }
+
+ /**
+ * Generate a suitable blind factor for the public key the generator was initialised with.
+ *
+ * @return a random blind factor
+ */
+ public BigInteger generateBlindingFactor()
+ {
+ if (key == null)
+ {
+ throw new IllegalStateException("generator not initialised");
+ }
+
+ BigInteger m = key.getModulus();
+ int length = m.bitLength() - 1; // must be less than m.bitLength()
+ BigInteger factor;
+ BigInteger gcd;
+
+ do
+ {
+ factor = new BigInteger(length, random);
+ gcd = factor.gcd(m);
+ }
+ while (factor.equals(ZERO) || factor.equals(ONE) || !gcd.equals(ONE));
+
+ return factor;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/RSAKeyPairGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,147 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+
+import java.math.BigInteger;
+
+/**
+ * an RSA key pair generator.
+ */
+public class RSAKeyPairGenerator
+ implements AsymmetricCipherKeyPairGenerator
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private RSAKeyGenerationParameters param;
+
+ public void init(
+ KeyGenerationParameters param)
+ {
+ this.param = (RSAKeyGenerationParameters)param;
+ }
+
+ public AsymmetricCipherKeyPair generateKeyPair()
+ {
+ BigInteger p, q, n, d, e, pSub1, qSub1, phi;
+
+ //
+ // p and q values should have a length of half the strength in bits
+ //
+ int strength = param.getStrength();
+ int pbitlength = (strength + 1) / 2;
+ int qbitlength = strength - pbitlength;
+ int mindiffbits = strength / 3;
+
+ e = param.getPublicExponent();
+
+ // TODO Consider generating safe primes for p, q (see DHParametersHelper.generateSafePrimes)
+ // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm")
+
+ //
+ // generate p, prime and (p-1) relatively prime to e
+ //
+ for (;;)
+ {
+ p = new BigInteger(pbitlength, 1, param.getRandom());
+
+ if (p.mod(e).equals(ONE))
+ {
+ continue;
+ }
+
+ if (!p.isProbablePrime(param.getCertainty()))
+ {
+ continue;
+ }
+
+ if (e.gcd(p.subtract(ONE)).equals(ONE))
+ {
+ break;
+ }
+ }
+
+ //
+ // generate a modulus of the required length
+ //
+ for (;;)
+ {
+ // generate q, prime and (q-1) relatively prime to e,
+ // and not equal to p
+ //
+ for (;;)
+ {
+ q = new BigInteger(qbitlength, 1, param.getRandom());
+
+ if (q.subtract(p).abs().bitLength() < mindiffbits)
+ {
+ continue;
+ }
+
+ if (q.mod(e).equals(ONE))
+ {
+ continue;
+ }
+
+ if (!q.isProbablePrime(param.getCertainty()))
+ {
+ continue;
+ }
+
+ if (e.gcd(q.subtract(ONE)).equals(ONE))
+ {
+ break;
+ }
+ }
+
+ //
+ // calculate the modulus
+ //
+ n = p.multiply(q);
+
+ if (n.bitLength() == param.getStrength())
+ {
+ break;
+ }
+
+ //
+ // if we get here our primes aren't big enough, make the largest
+ // of the two p and try again
+ //
+ p = p.max(q);
+ }
+
+ if (p.compareTo(q) < 0)
+ {
+ phi = p;
+ p = q;
+ q = phi;
+ }
+
+ pSub1 = p.subtract(ONE);
+ qSub1 = q.subtract(ONE);
+ phi = pSub1.multiply(qSub1);
+
+ //
+ // calculate the private exponent
+ //
+ d = e.modInverse(phi);
+
+ //
+ // calculate the CRT factors
+ //
+ BigInteger dP, dQ, qInv;
+
+ dP = d.remainder(pSub1);
+ dQ = d.remainder(qSub1);
+ qInv = q.modInverse(p);
+
+ return new AsymmetricCipherKeyPair(
+ new RSAKeyParameters(false, n, e),
+ new RSAPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/SCrypt.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/SCrypt.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/SCrypt.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/SCrypt.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,147 @@
+package pdftk.org.bouncycastle.crypto.generators;
+
+import pdftk.org.bouncycastle.crypto.PBEParametersGenerator;
+import pdftk.org.bouncycastle.crypto.digests.SHA256Digest;
+import pdftk.org.bouncycastle.crypto.engines.Salsa20Engine;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.util.Pack;
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class SCrypt
+{
+ // TODO Validate arguments
+ public static byte[] generate(byte[] P, byte[] S, int N, int r, int p, int dkLen)
+ {
+ return MFcrypt(P, S, N, r, p, dkLen);
+ }
+
+ private static byte[] MFcrypt(byte[] P, byte[] S, int N, int r, int p, int dkLen)
+ {
+ int MFLenBytes = r * 128;
+ byte[] bytes = SingleIterationPBKDF2(P, S, p * MFLenBytes);
+
+ int[] B = null;
+
+ try
+ {
+ int BLen = bytes.length >>> 2;
+ B = new int[BLen];
+
+ Pack.littleEndianToInt(bytes, 0, B);
+
+ int MFLenWords = MFLenBytes >>> 2;
+ for (int BOff = 0; BOff < BLen; BOff += MFLenWords)
+ {
+ // TODO These can be done in parallel threads
+ SMix(B, BOff, N, r);
+ }
+
+ Pack.intToLittleEndian(B, bytes, 0);
+
+ return SingleIterationPBKDF2(P, bytes, dkLen);
+ }
+ finally
+ {
+ Clear(bytes);
+ Clear(B);
+ }
+ }
+
+ private static byte[] SingleIterationPBKDF2(byte[] P, byte[] S, int dkLen)
+ {
+ PBEParametersGenerator pGen = new PKCS5S2ParametersGenerator(new SHA256Digest());
+ pGen.init(P, S, 1);
+ KeyParameter key = (KeyParameter) pGen.generateDerivedMacParameters(dkLen * 8);
+ return key.getKey();
+ }
+
+ private static void SMix(int[] B, int BOff, int N, int r)
+ {
+ int BCount = r * 32;
+
+ int[] blockX1 = new int[16];
+ int[] blockX2 = new int[16];
+ int[] blockY = new int[BCount];
+
+ int[] X = new int[BCount];
+ int[][] V = new int[N][];
+
+ try
+ {
+ System.arraycopy(B, BOff, X, 0, BCount);
+
+ for (int i = 0; i < N; ++i)
+ {
+ V[i] = Arrays.clone(X);
+ BlockMix(X, blockX1, blockX2, blockY, r);
+ }
+
+ int mask = N - 1;
+ for (int i = 0; i < N; ++i)
+ {
+ int j = X[BCount - 16] & mask;
+ Xor(X, V[j], 0, X);
+ BlockMix(X, blockX1, blockX2, blockY, r);
+ }
+
+ System.arraycopy(X, 0, B, BOff, BCount);
+ }
+ finally
+ {
+ ClearAll(V);
+ ClearAll(new int[][]{ X, blockX1, blockX2, blockY });
+ }
+ }
+
+ private static void BlockMix(int[] B, int[] X1, int[] X2, int[] Y, int r)
+ {
+ System.arraycopy(B, B.length - 16, X1, 0, 16);
+
+ int BOff = 0, YOff = 0, halfLen = B.length >>> 1;
+
+ for (int i = 2 * r; i > 0; --i)
+ {
+ Xor(X1, B, BOff, X2);
+
+ Salsa20Engine.salsaCore(8, X2, X1);
+ System.arraycopy(X1, 0, Y, YOff, 16);
+
+ YOff = halfLen + BOff - YOff;
+ BOff += 16;
+ }
+
+ System.arraycopy(Y, 0, B, 0, Y.length);
+ }
+
+ private static void Xor(int[] a, int[] b, int bOff, int[] output)
+ {
+ for (int i = output.length - 1; i >= 0; --i)
+ {
+ output[i] = a[i] ^ b[bOff + i];
+ }
+ }
+
+ private static void Clear(byte[] array)
+ {
+ if (array != null)
+ {
+ Arrays.fill(array, (byte)0);
+ }
+ }
+
+ private static void Clear(int[] array)
+ {
+ if (array != null)
+ {
+ Arrays.fill(array, 0);
+ }
+ }
+
+ private static void ClearAll(int[][] arrays)
+ {
+ for (int i = 0; i < arrays.length; ++i)
+ {
+ Clear(arrays[i]);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/generators/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/generators/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Generators for keys, key pairs and password based encryption algorithms.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/CipherInputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/CipherInputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/CipherInputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/CipherInputStream.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,244 @@
+package pdftk.org.bouncycastle.crypto.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import pdftk.org.bouncycastle.crypto.BufferedBlockCipher;
+import pdftk.org.bouncycastle.crypto.StreamCipher;
+
+/**
+ * A CipherInputStream is composed of an InputStream and a BufferedBlockCipher so
+ * that read() methods return data that are read in from the
+ * underlying InputStream but have been additionally processed by the
+ * Cipher. The Cipher must be fully initialized before being used by
+ * a CipherInputStream.
+ *
+ * For example, if the Cipher is initialized for decryption, the
+ * CipherInputStream will attempt to read in data and decrypt them,
+ * before returning the decrypted data.
+ */
+public class CipherInputStream
+ extends FilterInputStream
+{
+ private BufferedBlockCipher bufferedBlockCipher;
+ private StreamCipher streamCipher;
+
+ private byte[] buf;
+ private byte[] inBuf;
+
+ private int bufOff;
+ private int maxBuf;
+ private boolean finalized;
+
+ private static final int INPUT_BUF_SIZE = 2048;
+
+ /**
+ * Constructs a CipherInputStream from an InputStream and a
+ * BufferedBlockCipher.
+ */
+ public CipherInputStream(
+ InputStream is,
+ BufferedBlockCipher cipher)
+ {
+ super(is);
+
+ this.bufferedBlockCipher = cipher;
+
+ buf = new byte[cipher.getOutputSize(INPUT_BUF_SIZE)];
+ inBuf = new byte[INPUT_BUF_SIZE];
+ }
+
+ public CipherInputStream(
+ InputStream is,
+ StreamCipher cipher)
+ {
+ super(is);
+
+ this.streamCipher = cipher;
+
+ buf = new byte[INPUT_BUF_SIZE];
+ inBuf = new byte[INPUT_BUF_SIZE];
+ }
+
+ /**
+ * grab the next chunk of input from the underlying input stream
+ */
+ private int nextChunk()
+ throws IOException
+ {
+ int available = super.available();
+
+ // must always try to read 1 byte!
+ // some buggy InputStreams return < 0!
+ if (available <= 0)
+ {
+ available = 1;
+ }
+
+ if (available > inBuf.length)
+ {
+ available = super.read(inBuf, 0, inBuf.length);
+ }
+ else
+ {
+ available = super.read(inBuf, 0, available);
+ }
+
+ if (available < 0)
+ {
+ if (finalized)
+ {
+ return -1;
+ }
+
+ try
+ {
+ if (bufferedBlockCipher != null)
+ {
+ maxBuf = bufferedBlockCipher.doFinal(buf, 0);
+ }
+ else
+ {
+ maxBuf = 0; // a stream cipher
+ }
+ }
+ catch (Exception e)
+ {
+ throw new IOException("error processing stream: " + e.toString());
+ }
+
+ bufOff = 0;
+
+ finalized = true;
+
+ if (bufOff == maxBuf)
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ bufOff = 0;
+
+ try
+ {
+ if (bufferedBlockCipher != null)
+ {
+ maxBuf = bufferedBlockCipher.processBytes(inBuf, 0, available, buf, 0);
+ }
+ else
+ {
+ streamCipher.processBytes(inBuf, 0, available, buf, 0);
+ maxBuf = available;
+ }
+ }
+ catch (Exception e)
+ {
+ throw new IOException("error processing stream: " + e.toString());
+ }
+
+ if (maxBuf == 0) // not enough bytes read for first block...
+ {
+ return nextChunk();
+ }
+ }
+
+ return maxBuf;
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (bufOff == maxBuf)
+ {
+ if (nextChunk() < 0)
+ {
+ return -1;
+ }
+ }
+
+ return buf[bufOff++] & 0xff;
+ }
+
+ public int read(
+ byte[] b)
+ throws IOException
+ {
+ return read(b, 0, b.length);
+ }
+
+ public int read(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ if (bufOff == maxBuf)
+ {
+ if (nextChunk() < 0)
+ {
+ return -1;
+ }
+ }
+
+ int available = maxBuf - bufOff;
+
+ if (len > available)
+ {
+ System.arraycopy(buf, bufOff, b, off, available);
+ bufOff = maxBuf;
+
+ return available;
+ }
+ else
+ {
+ System.arraycopy(buf, bufOff, b, off, len);
+ bufOff += len;
+
+ return len;
+ }
+ }
+
+ public long skip(
+ long n)
+ throws IOException
+ {
+ if (n <= 0)
+ {
+ return 0;
+ }
+
+ int available = maxBuf - bufOff;
+
+ if (n > available)
+ {
+ bufOff = maxBuf;
+
+ return available;
+ }
+ else
+ {
+ bufOff += (int)n;
+
+ return (int)n;
+ }
+ }
+
+ public int available()
+ throws IOException
+ {
+ return maxBuf - bufOff;
+ }
+
+ public void close()
+ throws IOException
+ {
+ super.close();
+ }
+
+ public boolean markSupported()
+ {
+ return false;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/CipherOutputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/CipherOutputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/CipherOutputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/CipherOutputStream.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,188 @@
+package pdftk.org.bouncycastle.crypto.io;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import pdftk.org.bouncycastle.crypto.BufferedBlockCipher;
+import pdftk.org.bouncycastle.crypto.StreamCipher;
+
+public class CipherOutputStream
+ extends FilterOutputStream
+{
+ private BufferedBlockCipher bufferedBlockCipher;
+ private StreamCipher streamCipher;
+
+ private byte[] oneByte = new byte[1];
+ private byte[] buf;
+
+ /**
+ * Constructs a CipherOutputStream from an OutputStream and a
+ * BufferedBlockCipher.
+ */
+ public CipherOutputStream(
+ OutputStream os,
+ BufferedBlockCipher cipher)
+ {
+ super(os);
+ this.bufferedBlockCipher = cipher;
+ this.buf = new byte[cipher.getBlockSize()];
+ }
+
+ /**
+ * Constructs a CipherOutputStream from an OutputStream and a
+ * BufferedBlockCipher.
+ */
+ public CipherOutputStream(
+ OutputStream os,
+ StreamCipher cipher)
+ {
+ super(os);
+ this.streamCipher = cipher;
+ }
+
+ /**
+ * Writes the specified byte to this output stream.
+ *
+ * @param b the byte
.
+ * @exception java.io.IOException if an I/O error occurs.
+ */
+ public void write(
+ int b)
+ throws IOException
+ {
+ oneByte[0] = (byte)b;
+
+ if (bufferedBlockCipher != null)
+ {
+ int len = bufferedBlockCipher.processBytes(oneByte, 0, 1, buf, 0);
+
+ if (len != 0)
+ {
+ out.write(buf, 0, len);
+ }
+ }
+ else
+ {
+ out.write(streamCipher.returnByte((byte)b));
+ }
+ }
+
+ /**
+ * Writes b.length
bytes from the specified byte array
+ * to this output stream.
+ *
+ * The write
method of
+ * CipherOutputStream
calls the write
+ * method of three arguments with the three arguments
+ * b
, 0
, and b.length
.
+ *
+ * @param b the data.
+ * @exception java.io.IOException if an I/O error occurs.
+ * @see #write(byte[], int, int)
+ */
+ public void write(
+ byte[] b)
+ throws IOException
+ {
+ write(b, 0, b.length);
+ }
+
+ /**
+ * Writes len
bytes from the specified byte array
+ * starting at offset off
to this output stream.
+ *
+ * @param b the data.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
+ * @exception java.io.IOException if an I/O error occurs.
+ */
+ public void write(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ if (bufferedBlockCipher != null)
+ {
+ byte[] buf = new byte[bufferedBlockCipher.getOutputSize(len)];
+
+ int outLen = bufferedBlockCipher.processBytes(b, off, len, buf, 0);
+
+ if (outLen != 0)
+ {
+ out.write(buf, 0, outLen);
+ }
+ }
+ else
+ {
+ byte[] buf = new byte[len];
+
+ streamCipher.processBytes(b, off, len, buf, 0);
+
+ out.write(buf, 0, len);
+ }
+ }
+
+ /**
+ * Flushes this output stream by forcing any buffered output bytes
+ * that have already been processed by the encapsulated cipher object
+ * to be written out.
+ *
+ *
+ * Any bytes buffered by the encapsulated cipher
+ * and waiting to be processed by it will not be written out. For example,
+ * if the encapsulated cipher is a block cipher, and the total number of
+ * bytes written using one of the write
methods is less than
+ * the cipher's block size, no bytes will be written out.
+ *
+ * @exception java.io.IOException if an I/O error occurs.
+ */
+ public void flush()
+ throws IOException
+ {
+ super.flush();
+ }
+
+ /**
+ * Closes this output stream and releases any system resources
+ * associated with this stream.
+ *
+ * This method invokes the doFinal
method of the encapsulated
+ * cipher object, which causes any bytes buffered by the encapsulated
+ * cipher to be processed. The result is written out by calling the
+ * flush
method of this output stream.
+ *
+ * This method resets the encapsulated cipher object to its initial state
+ * and calls the close
method of the underlying output
+ * stream.
+ *
+ * @exception java.io.IOException if an I/O error occurs.
+ */
+ public void close()
+ throws IOException
+ {
+ try
+ {
+ if (bufferedBlockCipher != null)
+ {
+ byte[] buf = new byte[bufferedBlockCipher.getOutputSize(0)];
+
+ int outLen = bufferedBlockCipher.doFinal(buf, 0);
+
+ if (outLen != 0)
+ {
+ out.write(buf, 0, outLen);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ throw new IOException("Error closing stream: " + e.toString());
+ }
+
+ flush();
+
+ super.close();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/DigestInputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/DigestInputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/DigestInputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/DigestInputStream.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,52 @@
+package pdftk.org.bouncycastle.crypto.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import pdftk.org.bouncycastle.crypto.Digest;
+
+public class DigestInputStream
+ extends FilterInputStream
+{
+ protected Digest digest;
+
+ public DigestInputStream(
+ InputStream stream,
+ Digest digest)
+ {
+ super(stream);
+ this.digest = digest;
+ }
+
+ public int read()
+ throws IOException
+ {
+ int b = in.read();
+
+ if (b >= 0)
+ {
+ digest.update((byte)b);
+ }
+ return b;
+ }
+
+ public int read(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ int n = in.read(b, off, len);
+ if (n > 0)
+ {
+ digest.update(b, off, n);
+ }
+ return n;
+ }
+
+ public Digest getDigest()
+ {
+ return digest;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/DigestOutputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/DigestOutputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/DigestOutputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/DigestOutputStream.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,42 @@
+package pdftk.org.bouncycastle.crypto.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import pdftk.org.bouncycastle.crypto.Digest;
+
+public class DigestOutputStream
+ extends OutputStream
+{
+ protected Digest digest;
+
+ public DigestOutputStream(
+ Digest Digest)
+ {
+ this.digest = Digest;
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ digest.update((byte)b);
+ }
+
+ public void write(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ digest.update(b, off, len);
+ }
+
+ public byte[] getDigest()
+ {
+ byte[] res = new byte[digest.getDigestSize()];
+
+ digest.doFinal(res, 0);
+
+ return res;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/MacInputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/MacInputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/MacInputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/MacInputStream.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,52 @@
+package pdftk.org.bouncycastle.crypto.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import pdftk.org.bouncycastle.crypto.Mac;
+
+public class MacInputStream
+ extends FilterInputStream
+{
+ protected Mac mac;
+
+ public MacInputStream(
+ InputStream stream,
+ Mac mac)
+ {
+ super(stream);
+ this.mac = mac;
+ }
+
+ public int read()
+ throws IOException
+ {
+ int b = in.read();
+
+ if (b >= 0)
+ {
+ mac.update((byte)b);
+ }
+ return b;
+ }
+
+ public int read(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ int n = in.read(b, off, len);
+ if (n >= 0)
+ {
+ mac.update(b, off, n);
+ }
+ return n;
+ }
+
+ public Mac getMac()
+ {
+ return mac;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/MacOutputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/MacOutputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/MacOutputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/MacOutputStream.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,42 @@
+package pdftk.org.bouncycastle.crypto.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import pdftk.org.bouncycastle.crypto.Mac;
+
+public class MacOutputStream
+ extends OutputStream
+{
+ protected Mac mac;
+
+ public MacOutputStream(
+ Mac mac)
+ {
+ this.mac = mac;
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ mac.update((byte)b);
+ }
+
+ public void write(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ mac.update(b, off, len);
+ }
+
+ public byte[] getMac()
+ {
+ byte[] res = new byte[mac.getMacSize()];
+
+ mac.doFinal(res, 0);
+
+ return res;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/SignerInputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/SignerInputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/SignerInputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/SignerInputStream.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,52 @@
+package pdftk.org.bouncycastle.crypto.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import pdftk.org.bouncycastle.crypto.Signer;
+
+public class SignerInputStream
+ extends FilterInputStream
+{
+ protected Signer signer;
+
+ public SignerInputStream(
+ InputStream stream,
+ Signer signer)
+ {
+ super(stream);
+ this.signer = signer;
+ }
+
+ public int read()
+ throws IOException
+ {
+ int b = in.read();
+
+ if (b >= 0)
+ {
+ signer.update((byte)b);
+ }
+ return b;
+ }
+
+ public int read(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ int n = in.read(b, off, len);
+ if (n > 0)
+ {
+ signer.update(b, off, n);
+ }
+ return n;
+ }
+
+ public Signer getSigner()
+ {
+ return signer;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/SignerOutputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/SignerOutputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/SignerOutputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/SignerOutputStream.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,38 @@
+package pdftk.org.bouncycastle.crypto.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import pdftk.org.bouncycastle.crypto.Signer;
+
+public class SignerOutputStream
+ extends OutputStream
+{
+ protected Signer signer;
+
+ public SignerOutputStream(
+ Signer Signer)
+ {
+ this.signer = Signer;
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ signer.update((byte)b);
+ }
+
+ public void write(
+ byte[] b,
+ int off,
+ int len)
+ throws IOException
+ {
+ signer.update(b, off, len);
+ }
+
+ public Signer getSigner()
+ {
+ return signer;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/io/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/io/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Classes for doing "enhanced" I/O with Digests and MACs.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/BlockCipherMac.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/BlockCipherMac.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/BlockCipherMac.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/BlockCipherMac.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,174 @@
+package pdftk.org.bouncycastle.crypto.macs;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.modes.CBCBlockCipher;
+
+public class BlockCipherMac
+ implements Mac
+{
+ private byte[] mac;
+
+ private byte[] buf;
+ private int bufOff;
+ private BlockCipher cipher;
+
+ private int macSize;
+
+ /**
+ * create a standard MAC based on a block cipher. This will produce an
+ * authentication code half the length of the block size of the cipher.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @deprecated use CBCBlockCipherMac
+ */
+ public BlockCipherMac(
+ BlockCipher cipher)
+ {
+ this(cipher, (cipher.getBlockSize() * 8) / 2);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits.
+ *
+ * Note: the size of the MAC must be at least 16 bits (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ * @deprecated use CBCBlockCipherMac
+ */
+ public BlockCipherMac(
+ BlockCipher cipher,
+ int macSizeInBits)
+ {
+ if ((macSizeInBits % 8) != 0)
+ {
+ throw new IllegalArgumentException("MAC size must be multiple of 8");
+ }
+
+ this.cipher = new CBCBlockCipher(cipher);
+ this.macSize = macSizeInBits / 8;
+
+ mac = new byte[cipher.getBlockSize()];
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName();
+ }
+
+ public void init(
+ CipherParameters params)
+ {
+ reset();
+
+ cipher.init(true, params);
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ if (bufOff == buf.length)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int resultLen = 0;
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, mac, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ resultLen += cipher.processBlock(in, inOff, mac, 0);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ int blockSize = cipher.getBlockSize();
+
+ //
+ // pad with zeroes
+ //
+ while (bufOff < blockSize)
+ {
+ buf[bufOff] = 0;
+ bufOff++;
+ }
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ System.arraycopy(mac, 0, out, outOff, macSize);
+
+ reset();
+
+ return macSize;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ /*
+ * reset the underlying cipher.
+ */
+ cipher.reset();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/CBCBlockCipherMac.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/CBCBlockCipherMac.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/CBCBlockCipherMac.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/CBCBlockCipherMac.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,229 @@
+package pdftk.org.bouncycastle.crypto.macs;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.modes.CBCBlockCipher;
+import pdftk.org.bouncycastle.crypto.paddings.BlockCipherPadding;
+
+/**
+ * standard CBC Block Cipher MAC - if no padding is specified the default of
+ * pad of zeroes is used.
+ */
+public class CBCBlockCipherMac
+ implements Mac
+{
+ private byte[] mac;
+
+ private byte[] buf;
+ private int bufOff;
+ private BlockCipher cipher;
+ private BlockCipherPadding padding;
+
+ private int macSize;
+
+ /**
+ * create a standard MAC based on a CBC block cipher. This will produce an
+ * authentication code half the length of the block size of the cipher.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ */
+ public CBCBlockCipherMac(
+ BlockCipher cipher)
+ {
+ this(cipher, (cipher.getBlockSize() * 8) / 2, null);
+ }
+
+ /**
+ * create a standard MAC based on a CBC block cipher. This will produce an
+ * authentication code half the length of the block size of the cipher.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param padding the padding to be used to complete the last block.
+ */
+ public CBCBlockCipherMac(
+ BlockCipher cipher,
+ BlockCipherPadding padding)
+ {
+ this(cipher, (cipher.getBlockSize() * 8) / 2, padding);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits. This class uses CBC mode as the basis for the
+ * MAC generation.
+ *
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ */
+ public CBCBlockCipherMac(
+ BlockCipher cipher,
+ int macSizeInBits)
+ {
+ this(cipher, macSizeInBits, null);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits. This class uses CBC mode as the basis for the
+ * MAC generation.
+ *
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ * @param padding the padding to be used to complete the last block.
+ */
+ public CBCBlockCipherMac(
+ BlockCipher cipher,
+ int macSizeInBits,
+ BlockCipherPadding padding)
+ {
+ if ((macSizeInBits % 8) != 0)
+ {
+ throw new IllegalArgumentException("MAC size must be multiple of 8");
+ }
+
+ this.cipher = new CBCBlockCipher(cipher);
+ this.padding = padding;
+ this.macSize = macSizeInBits / 8;
+
+ mac = new byte[cipher.getBlockSize()];
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName();
+ }
+
+ public void init(
+ CipherParameters params)
+ {
+ reset();
+
+ cipher.init(true, params);
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ if (bufOff == buf.length)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ cipher.processBlock(in, inOff, mac, 0);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ int blockSize = cipher.getBlockSize();
+
+ if (padding == null)
+ {
+ //
+ // pad with zeroes
+ //
+ while (bufOff < blockSize)
+ {
+ buf[bufOff] = 0;
+ bufOff++;
+ }
+ }
+ else
+ {
+ if (bufOff == blockSize)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ padding.addPadding(buf, bufOff);
+ }
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ System.arraycopy(mac, 0, out, outOff, macSize);
+
+ reset();
+
+ return macSize;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ /*
+ * reset the underlying cipher.
+ */
+ cipher.reset();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/CFBBlockCipherMac.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/CFBBlockCipherMac.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/CFBBlockCipherMac.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/CFBBlockCipherMac.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,388 @@
+package pdftk.org.bouncycastle.crypto.macs;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.paddings.BlockCipherPadding;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
+ */
+class MacCFBBlockCipher
+{
+ private byte[] IV;
+ private byte[] cfbV;
+ private byte[] cfbOutV;
+
+ private int blockSize;
+ private BlockCipher cipher = null;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ * @param blockSize the block size in bits (note: a multiple of 8)
+ */
+ public MacCFBBlockCipher(
+ BlockCipher cipher,
+ int bitBlockSize)
+ {
+ this.cipher = cipher;
+ this.blockSize = bitBlockSize / 8;
+
+ this.IV = new byte[cipher.getBlockSize()];
+ this.cfbV = new byte[cipher.getBlockSize()];
+ this.cfbOutV = new byte[cipher.getBlockSize()];
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param param the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ cipher.init(true, ivParam.getParameters());
+ }
+ else
+ {
+ reset();
+
+ cipher.init(true, params);
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/CFB"
+ * and the block size in bits.
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/CFB" + (blockSize * 8);
+ }
+
+ /**
+ * return the block size we are operating at.
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ cipher.processBlock(cfbV, 0, cfbOutV, 0);
+
+ //
+ // XOR the cfbV with the plaintext producing the cipher text
+ //
+ for (int i = 0; i < blockSize; i++)
+ {
+ out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]);
+ }
+
+ //
+ // change over the input block.
+ //
+ System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
+ System.arraycopy(out, outOff, cfbV, cfbV.length - blockSize, blockSize);
+
+ return blockSize;
+ }
+
+ /**
+ * reset the chaining vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ System.arraycopy(IV, 0, cfbV, 0, IV.length);
+
+ cipher.reset();
+ }
+
+ void getMacBlock(
+ byte[] mac)
+ {
+ cipher.processBlock(cfbV, 0, mac, 0);
+ }
+}
+
+public class CFBBlockCipherMac
+ implements Mac
+{
+ private byte[] mac;
+
+ private byte[] buf;
+ private int bufOff;
+ private MacCFBBlockCipher cipher;
+ private BlockCipherPadding padding = null;
+
+
+ private int macSize;
+
+ /**
+ * create a standard MAC based on a CFB block cipher. This will produce an
+ * authentication code half the length of the block size of the cipher, with
+ * the CFB mode set to 8 bits.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ */
+ public CFBBlockCipherMac(
+ BlockCipher cipher)
+ {
+ this(cipher, 8, (cipher.getBlockSize() * 8) / 2, null);
+ }
+
+ /**
+ * create a standard MAC based on a CFB block cipher. This will produce an
+ * authentication code half the length of the block size of the cipher, with
+ * the CFB mode set to 8 bits.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param padding the padding to be used.
+ */
+ public CFBBlockCipherMac(
+ BlockCipher cipher,
+ BlockCipherPadding padding)
+ {
+ this(cipher, 8, (cipher.getBlockSize() * 8) / 2, padding);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits. This class uses CFB mode as the basis for the
+ * MAC generation.
+ *
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param cfbBitSize the size of an output block produced by the CFB mode.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ */
+ public CFBBlockCipherMac(
+ BlockCipher cipher,
+ int cfbBitSize,
+ int macSizeInBits)
+ {
+ this(cipher, cfbBitSize, macSizeInBits, null);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits. This class uses CFB mode as the basis for the
+ * MAC generation.
+ *
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param cfbBitSize the size of an output block produced by the CFB mode.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ * @param padding a padding to be used.
+ */
+ public CFBBlockCipherMac(
+ BlockCipher cipher,
+ int cfbBitSize,
+ int macSizeInBits,
+ BlockCipherPadding padding)
+ {
+ if ((macSizeInBits % 8) != 0)
+ {
+ throw new IllegalArgumentException("MAC size must be multiple of 8");
+ }
+
+ mac = new byte[cipher.getBlockSize()];
+
+ this.cipher = new MacCFBBlockCipher(cipher, cfbBitSize);
+ this.padding = padding;
+ this.macSize = macSizeInBits / 8;
+
+ buf = new byte[this.cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName();
+ }
+
+ public void init(
+ CipherParameters params)
+ {
+ reset();
+
+ cipher.init(params);
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ if (bufOff == buf.length)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int resultLen = 0;
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, mac, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ resultLen += cipher.processBlock(in, inOff, mac, 0);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ int blockSize = cipher.getBlockSize();
+
+ //
+ // pad with zeroes
+ //
+ if (this.padding == null)
+ {
+ while (bufOff < blockSize)
+ {
+ buf[bufOff] = 0;
+ bufOff++;
+ }
+ }
+ else
+ {
+ padding.addPadding(buf, bufOff);
+ }
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ cipher.getMacBlock(mac);
+
+ System.arraycopy(mac, 0, out, outOff, macSize);
+
+ reset();
+
+ return macSize;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ /*
+ * reset the underlying cipher.
+ */
+ cipher.reset();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/CMac.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/CMac.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/CMac.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/CMac.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,238 @@
+package pdftk.org.bouncycastle.crypto.macs;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.modes.CBCBlockCipher;
+import pdftk.org.bouncycastle.crypto.paddings.ISO7816d4Padding;
+
+/**
+ * CMAC - as specified at www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
+ *
+ * CMAC is analogous to OMAC1 - see also en.wikipedia.org/wiki/CMAC
+ *
+ * CMAC is a NIST recomendation - see
+ * csrc.nist.gov/CryptoToolkit/modes/800-38_Series_Publications/SP800-38B.pdf
+ *
+ * CMAC/OMAC1 is a blockcipher-based message authentication code designed and
+ * analyzed by Tetsu Iwata and Kaoru Kurosawa.
+ *
+ * CMAC/OMAC1 is a simple variant of the CBC MAC (Cipher Block Chaining Message
+ * Authentication Code). OMAC stands for One-Key CBC MAC.
+ *
+ * It supports 128- or 64-bits block ciphers, with any key size, and returns
+ * a MAC with dimension less or equal to the block size of the underlying
+ * cipher.
+ *
+ */
+public class CMac implements Mac
+{
+ private static final byte CONSTANT_128 = (byte)0x87;
+ private static final byte CONSTANT_64 = (byte)0x1b;
+
+ private byte[] ZEROES;
+
+ private byte[] mac;
+
+ private byte[] buf;
+ private int bufOff;
+ private BlockCipher cipher;
+
+ private int macSize;
+
+ private byte[] L, Lu, Lu2;
+
+ /**
+ * create a standard MAC based on a CBC block cipher (64 or 128 bit block).
+ * This will produce an authentication code the length of the block size
+ * of the cipher.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ */
+ public CMac(BlockCipher cipher)
+ {
+ this(cipher, cipher.getBlockSize() * 8);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits.
+ *
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8 and <= 128.
+ */
+ public CMac(BlockCipher cipher, int macSizeInBits)
+ {
+ if ((macSizeInBits % 8) != 0)
+ {
+ throw new IllegalArgumentException("MAC size must be multiple of 8");
+ }
+
+ if (macSizeInBits > (cipher.getBlockSize() * 8))
+ {
+ throw new IllegalArgumentException(
+ "MAC size must be less or equal to "
+ + (cipher.getBlockSize() * 8));
+ }
+
+ if (cipher.getBlockSize() != 8 && cipher.getBlockSize() != 16)
+ {
+ throw new IllegalArgumentException(
+ "Block size must be either 64 or 128 bits");
+ }
+
+ this.cipher = new CBCBlockCipher(cipher);
+ this.macSize = macSizeInBits / 8;
+
+ mac = new byte[cipher.getBlockSize()];
+
+ buf = new byte[cipher.getBlockSize()];
+
+ ZEROES = new byte[cipher.getBlockSize()];
+
+ bufOff = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName();
+ }
+
+ private static byte[] doubleLu(byte[] in)
+ {
+ int FirstBit = (in[0] & 0xFF) >> 7;
+ byte[] ret = new byte[in.length];
+ for (int i = 0; i < in.length - 1; i++)
+ {
+ ret[i] = (byte)((in[i] << 1) + ((in[i + 1] & 0xFF) >> 7));
+ }
+ ret[in.length - 1] = (byte)(in[in.length - 1] << 1);
+ if (FirstBit == 1)
+ {
+ ret[in.length - 1] ^= in.length == 16 ? CONSTANT_128 : CONSTANT_64;
+ }
+ return ret;
+ }
+
+ public void init(CipherParameters params)
+ {
+ if (params != null)
+ {
+ cipher.init(true, params);
+
+ //initializes the L, Lu, Lu2 numbers
+ L = new byte[ZEROES.length];
+ cipher.processBlock(ZEROES, 0, L, 0);
+ Lu = doubleLu(L);
+ Lu2 = doubleLu(Lu);
+ }
+
+ reset();
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ public void update(byte in)
+ {
+ if (bufOff == buf.length)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException(
+ "Can't have a negative input length!");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ cipher.processBlock(in, inOff, mac, 0);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ int blockSize = cipher.getBlockSize();
+
+ byte[] lu;
+ if (bufOff == blockSize)
+ {
+ lu = Lu;
+ }
+ else
+ {
+ new ISO7816d4Padding().addPadding(buf, bufOff);
+ lu = Lu2;
+ }
+
+ for (int i = 0; i < mac.length; i++)
+ {
+ buf[i] ^= lu[i];
+ }
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ System.arraycopy(mac, 0, out, outOff, macSize);
+
+ reset();
+
+ return macSize;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ /*
+ * reset the underlying cipher.
+ */
+ cipher.reset();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/GOST28147Mac.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/GOST28147Mac.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/GOST28147Mac.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/GOST28147Mac.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,298 @@
+package pdftk.org.bouncycastle.crypto.macs;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithSBox;
+
+/**
+ * implementation of GOST 28147-89 MAC
+ */
+public class GOST28147Mac
+ implements Mac
+{
+ private int blockSize = 8;
+ private int macSize = 4;
+ private int bufOff;
+ private byte[] buf;
+ private byte[] mac;
+ private boolean firstStep = true;
+ private int[] workingKey = null;
+
+ //
+ // This is default S-box - E_A.
+ private byte S[] = {
+ 0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5,
+ 0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1,
+ 0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9,
+ 0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6,
+ 0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6,
+ 0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6,
+ 0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE,
+ 0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4
+ };
+
+ public GOST28147Mac()
+ {
+ mac = new byte[blockSize];
+
+ buf = new byte[blockSize];
+ bufOff = 0;
+ }
+
+ private int[] generateWorkingKey(
+ byte[] userKey)
+ {
+ if (userKey.length != 32)
+ {
+ throw new IllegalArgumentException("Key length invalid. Key needs to be 32 byte - 256 bit!!!");
+ }
+
+ int key[] = new int[8];
+ for(int i=0; i!=8; i++)
+ {
+ key[i] = bytesToint(userKey,i*4);
+ }
+
+ return key;
+ }
+
+ public void init(
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ reset();
+ buf = new byte[blockSize];
+ if (params instanceof ParametersWithSBox)
+ {
+ ParametersWithSBox param = (ParametersWithSBox)params;
+
+ //
+ // Set the S-Box
+ //
+ System.arraycopy(param.getSBox(), 0, this.S, 0, param.getSBox().length);
+
+ //
+ // set key if there is one
+ //
+ if (param.getParameters() != null)
+ {
+ workingKey = generateWorkingKey(((KeyParameter)param.getParameters()).getKey());
+ }
+ }
+ else if (params instanceof KeyParameter)
+ {
+ workingKey = generateWorkingKey(((KeyParameter)params).getKey());
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameter passed to GOST28147 init - " + params.getClass().getName());
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return "GOST28147Mac";
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ private int gost28147_mainStep(int n1, int key)
+ {
+ int cm = (key + n1); // CM1
+
+ // S-box replacing
+
+ int om = S[ 0 + ((cm >> (0 * 4)) & 0xF)] << (0 * 4);
+ om += S[ 16 + ((cm >> (1 * 4)) & 0xF)] << (1 * 4);
+ om += S[ 32 + ((cm >> (2 * 4)) & 0xF)] << (2 * 4);
+ om += S[ 48 + ((cm >> (3 * 4)) & 0xF)] << (3 * 4);
+ om += S[ 64 + ((cm >> (4 * 4)) & 0xF)] << (4 * 4);
+ om += S[ 80 + ((cm >> (5 * 4)) & 0xF)] << (5 * 4);
+ om += S[ 96 + ((cm >> (6 * 4)) & 0xF)] << (6 * 4);
+ om += S[112 + ((cm >> (7 * 4)) & 0xF)] << (7 * 4);
+
+ return om << 11 | om >>> (32-11); // 11-leftshift
+ }
+
+ private void gost28147MacFunc(
+ int[] workingKey,
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ {
+ int N1, N2, tmp; //tmp -> for saving N1
+ N1 = bytesToint(in, inOff);
+ N2 = bytesToint(in, inOff + 4);
+
+ for(int k = 0; k < 2; k++) // 1-16 steps
+ {
+ for(int j = 0; j < 8; j++)
+ {
+ tmp = N1;
+ N1 = N2 ^ gost28147_mainStep(N1, workingKey[j]); // CM2
+ N2 = tmp;
+ }
+ }
+
+ intTobytes(N1, out, outOff);
+ intTobytes(N2, out, outOff + 4);
+ }
+
+ //array of bytes to type int
+ private int bytesToint(
+ byte[] in,
+ int inOff)
+ {
+ return ((in[inOff + 3] << 24) & 0xff000000) + ((in[inOff + 2] << 16) & 0xff0000) +
+ ((in[inOff + 1] << 8) & 0xff00) + (in[inOff] & 0xff);
+ }
+
+ //int to array of bytes
+ private void intTobytes(
+ int num,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff + 3] = (byte)(num >>> 24);
+ out[outOff + 2] = (byte)(num >>> 16);
+ out[outOff + 1] = (byte)(num >>> 8);
+ out[outOff] = (byte)num;
+ }
+
+ private byte[] CM5func(byte[] buf, int bufOff, byte[] mac)
+ {
+ byte[] sum = new byte[buf.length - bufOff];
+
+ System.arraycopy(buf, bufOff, sum, 0, mac.length);
+
+ for (int i = 0; i != mac.length; i++)
+ {
+ sum[i] = (byte)(sum[i] ^ mac[i]);
+ }
+
+ return sum;
+ }
+
+ public void update(byte in)
+ throws IllegalStateException
+ {
+ if (bufOff == buf.length)
+ {
+ byte[] sumbuf = new byte[buf.length];
+ System.arraycopy(buf, 0, sumbuf, 0, mac.length);
+
+ if (firstStep)
+ {
+ firstStep = false;
+ }
+ else
+ {
+ sumbuf = CM5func(buf, 0, mac);
+ }
+
+ gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ throws DataLengthException, IllegalStateException
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ byte[] sumbuf = new byte[buf.length];
+ System.arraycopy(buf, 0, sumbuf, 0, mac.length);
+
+ if (firstStep)
+ {
+ firstStep = false;
+ }
+ else
+ {
+ sumbuf = CM5func(buf, 0, mac);
+ }
+
+ gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ sumbuf = CM5func(in, inOff, mac);
+ gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ //padding with zero
+ while (bufOff < blockSize)
+ {
+ buf[bufOff] = 0;
+ bufOff++;
+ }
+
+ byte[] sumbuf = new byte[buf.length];
+ System.arraycopy(buf, 0, sumbuf, 0, mac.length);
+
+ if (firstStep)
+ {
+ firstStep = false;
+ }
+ else
+ {
+ sumbuf = CM5func(buf, 0, mac);
+ }
+
+ gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+
+ System.arraycopy(mac, (mac.length/2)-macSize, out, outOff, macSize);
+
+ reset();
+
+ return macSize;
+ }
+
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ firstStep = true;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/HMac.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/HMac.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/HMac.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/HMac.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,200 @@
+package pdftk.org.bouncycastle.crypto.macs;
+
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.ExtendedDigest;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.util.Integers;
+
+/**
+ * HMAC implementation based on RFC2104
+ *
+ * H(K XOR opad, H(K XOR ipad, text))
+ */
+public class HMac
+ implements Mac
+{
+ private final static byte IPAD = (byte)0x36;
+ private final static byte OPAD = (byte)0x5C;
+
+ private Digest digest;
+ private int digestSize;
+ private int blockLength;
+
+ private byte[] inputPad;
+ private byte[] outputPad;
+
+ private static Hashtable blockLengths;
+
+ static
+ {
+ blockLengths = new Hashtable();
+
+ blockLengths.put("GOST3411", Integers.valueOf(32));
+
+ blockLengths.put("MD2", Integers.valueOf(16));
+ blockLengths.put("MD4", Integers.valueOf(64));
+ blockLengths.put("MD5", Integers.valueOf(64));
+
+ blockLengths.put("RIPEMD128", Integers.valueOf(64));
+ blockLengths.put("RIPEMD160", Integers.valueOf(64));
+
+ blockLengths.put("SHA-1", Integers.valueOf(64));
+ blockLengths.put("SHA-224", Integers.valueOf(64));
+ blockLengths.put("SHA-256", Integers.valueOf(64));
+ blockLengths.put("SHA-384", Integers.valueOf(128));
+ blockLengths.put("SHA-512", Integers.valueOf(128));
+
+ blockLengths.put("Tiger", Integers.valueOf(64));
+ blockLengths.put("Whirlpool", Integers.valueOf(64));
+ }
+
+ private static int getByteLength(
+ Digest digest)
+ {
+ if (digest instanceof ExtendedDigest)
+ {
+ return ((ExtendedDigest)digest).getByteLength();
+ }
+
+ Integer b = (Integer)blockLengths.get(digest.getAlgorithmName());
+
+ if (b == null)
+ {
+ throw new IllegalArgumentException("unknown digest passed: " + digest.getAlgorithmName());
+ }
+
+ return b.intValue();
+ }
+
+ /**
+ * Base constructor for one of the standard digest algorithms that the
+ * byteLength of the algorithm is know for.
+ *
+ * @param digest the digest.
+ */
+ public HMac(
+ Digest digest)
+ {
+ this(digest, getByteLength(digest));
+ }
+
+ private HMac(
+ Digest digest,
+ int byteLength)
+ {
+ this.digest = digest;
+ digestSize = digest.getDigestSize();
+
+ this.blockLength = byteLength;
+
+ inputPad = new byte[blockLength];
+ outputPad = new byte[blockLength];
+ }
+
+ public String getAlgorithmName()
+ {
+ return digest.getAlgorithmName() + "/HMAC";
+ }
+
+ public Digest getUnderlyingDigest()
+ {
+ return digest;
+ }
+
+ public void init(
+ CipherParameters params)
+ {
+ digest.reset();
+
+ byte[] key = ((KeyParameter)params).getKey();
+
+ if (key.length > blockLength)
+ {
+ digest.update(key, 0, key.length);
+ digest.doFinal(inputPad, 0);
+ for (int i = digestSize; i < inputPad.length; i++)
+ {
+ inputPad[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(key, 0, inputPad, 0, key.length);
+ for (int i = key.length; i < inputPad.length; i++)
+ {
+ inputPad[i] = 0;
+ }
+ }
+
+ outputPad = new byte[inputPad.length];
+ System.arraycopy(inputPad, 0, outputPad, 0, inputPad.length);
+
+ for (int i = 0; i < inputPad.length; i++)
+ {
+ inputPad[i] ^= IPAD;
+ }
+
+ for (int i = 0; i < outputPad.length; i++)
+ {
+ outputPad[i] ^= OPAD;
+ }
+
+ digest.update(inputPad, 0, inputPad.length);
+ }
+
+ public int getMacSize()
+ {
+ return digestSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ digest.update(in);
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ digest.update(in, inOff, len);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ byte[] tmp = new byte[digestSize];
+ digest.doFinal(tmp, 0);
+
+ digest.update(outputPad, 0, outputPad.length);
+ digest.update(tmp, 0, tmp.length);
+
+ int len = digest.doFinal(out, outOff);
+
+ reset();
+
+ return len;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * reset the underlying digest.
+ */
+ digest.reset();
+
+ /*
+ * reinitialize the digest.
+ */
+ digest.update(inputPad, 0, inputPad.length);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/ISO9797Alg3Mac.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/ISO9797Alg3Mac.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/ISO9797Alg3Mac.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/ISO9797Alg3Mac.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,305 @@
+package pdftk.org.bouncycastle.crypto.macs;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.engines.DESEngine;
+import pdftk.org.bouncycastle.crypto.modes.CBCBlockCipher;
+import pdftk.org.bouncycastle.crypto.paddings.BlockCipherPadding;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * DES based CBC Block Cipher MAC according to ISO9797, algorithm 3 (ANSI X9.19 Retail MAC)
+ *
+ * This could as well be derived from CBCBlockCipherMac, but then the property mac in the base
+ * class must be changed to protected
+ */
+
+public class ISO9797Alg3Mac
+ implements Mac
+{
+ private byte[] mac;
+
+ private byte[] buf;
+ private int bufOff;
+ private BlockCipher cipher;
+ private BlockCipherPadding padding;
+
+ private int macSize;
+ private KeyParameter lastKey2;
+ private KeyParameter lastKey3;
+
+ /**
+ * create a Retail-MAC based on a CBC block cipher. This will produce an
+ * authentication code of the length of the block size of the cipher.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation. This must
+ * be DESEngine.
+ */
+ public ISO9797Alg3Mac(
+ BlockCipher cipher)
+ {
+ this(cipher, cipher.getBlockSize() * 8, null);
+ }
+
+ /**
+ * create a Retail-MAC based on a CBC block cipher. This will produce an
+ * authentication code of the length of the block size of the cipher.
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param padding the padding to be used to complete the last block.
+ */
+ public ISO9797Alg3Mac(
+ BlockCipher cipher,
+ BlockCipherPadding padding)
+ {
+ this(cipher, cipher.getBlockSize() * 8, padding);
+ }
+
+ /**
+ * create a Retail-MAC based on a block cipher with the size of the
+ * MAC been given in bits. This class uses single DES CBC mode as the basis for the
+ * MAC generation.
+ *
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ */
+ public ISO9797Alg3Mac(
+ BlockCipher cipher,
+ int macSizeInBits)
+ {
+ this(cipher, macSizeInBits, null);
+ }
+
+ /**
+ * create a standard MAC based on a block cipher with the size of the
+ * MAC been given in bits. This class uses single DES CBC mode as the basis for the
+ * MAC generation. The final block is decrypted and then encrypted using the
+ * middle and right part of the key.
+ *
+ * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+ * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+ * and in general should be less than the size of the block cipher as it reduces
+ * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+ *
+ * @param cipher the cipher to be used as the basis of the MAC generation.
+ * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+ * @param padding the padding to be used to complete the last block.
+ */
+ public ISO9797Alg3Mac(
+ BlockCipher cipher,
+ int macSizeInBits,
+ BlockCipherPadding padding)
+ {
+ if ((macSizeInBits % 8) != 0)
+ {
+ throw new IllegalArgumentException("MAC size must be multiple of 8");
+ }
+
+ if (!(cipher instanceof DESEngine))
+ {
+ throw new IllegalArgumentException("cipher must be instance of DESEngine");
+ }
+
+ this.cipher = new CBCBlockCipher(cipher);
+ this.padding = padding;
+ this.macSize = macSizeInBits / 8;
+
+ mac = new byte[cipher.getBlockSize()];
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "ISO9797Alg3";
+ }
+
+ public void init(CipherParameters params)
+ {
+ reset();
+
+ if (!(params instanceof KeyParameter || params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException(
+ "params must be an instance of KeyParameter or ParametersWithIV");
+ }
+
+ // KeyParameter must contain a double or triple length DES key,
+ // however the underlying cipher is a single DES. The middle and
+ // right key are used only in the final step.
+
+ KeyParameter kp;
+
+ if (params instanceof KeyParameter)
+ {
+ kp = (KeyParameter)params;
+ }
+ else
+ {
+ kp = (KeyParameter)((ParametersWithIV)params).getParameters();
+ }
+
+ KeyParameter key1;
+ byte[] keyvalue = kp.getKey();
+
+ if (keyvalue.length == 16)
+ { // Double length DES key
+ key1 = new KeyParameter(keyvalue, 0, 8);
+ this.lastKey2 = new KeyParameter(keyvalue, 8, 8);
+ this.lastKey3 = key1;
+ }
+ else if (keyvalue.length == 24)
+ { // Triple length DES key
+ key1 = new KeyParameter(keyvalue, 0, 8);
+ this.lastKey2 = new KeyParameter(keyvalue, 8, 8);
+ this.lastKey3 = new KeyParameter(keyvalue, 16, 8);
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Key must be either 112 or 168 bit long");
+ }
+
+ if (params instanceof ParametersWithIV)
+ {
+ cipher.init(true, new ParametersWithIV(key1, ((ParametersWithIV)params).getIV()));
+ }
+ else
+ {
+ cipher.init(true, key1);
+ }
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ if (bufOff == buf.length)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+ }
+
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int resultLen = 0;
+ int gapLen = blockSize - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, mac, 0);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ resultLen += cipher.processBlock(in, inOff, mac, 0);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ int blockSize = cipher.getBlockSize();
+
+ if (padding == null)
+ {
+ //
+ // pad with zeroes
+ //
+ while (bufOff < blockSize)
+ {
+ buf[bufOff] = 0;
+ bufOff++;
+ }
+ }
+ else
+ {
+ if (bufOff == blockSize)
+ {
+ cipher.processBlock(buf, 0, mac, 0);
+ bufOff = 0;
+ }
+
+ padding.addPadding(buf, bufOff);
+ }
+
+ cipher.processBlock(buf, 0, mac, 0);
+
+ // Added to code from base class
+ DESEngine deseng = new DESEngine();
+
+ deseng.init(false, this.lastKey2);
+ deseng.processBlock(mac, 0, mac, 0);
+
+ deseng.init(true, this.lastKey3);
+ deseng.processBlock(mac, 0, mac, 0);
+ // ****
+
+ System.arraycopy(mac, 0, out, outOff, macSize);
+
+ reset();
+
+ return macSize;
+ }
+
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * clean the buffer.
+ */
+ for (int i = 0; i < buf.length; i++)
+ {
+ buf[i] = 0;
+ }
+
+ bufOff = 0;
+
+ /*
+ * reset the underlying cipher.
+ */
+ cipher.reset();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/OldHMac.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/OldHMac.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/OldHMac.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/OldHMac.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,138 @@
+package pdftk.org.bouncycastle.crypto.macs;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+
+/**
+ * HMAC implementation based on RFC2104
+ *
+ * H(K XOR opad, H(K XOR ipad, text))
+ */
+public class OldHMac
+implements Mac
+{
+ private final static int BLOCK_LENGTH = 64;
+
+ private final static byte IPAD = (byte)0x36;
+ private final static byte OPAD = (byte)0x5C;
+
+ private Digest digest;
+ private int digestSize;
+ private byte[] inputPad = new byte[BLOCK_LENGTH];
+ private byte[] outputPad = new byte[BLOCK_LENGTH];
+
+ /**
+ * @deprecated uses incorrect pad for SHA-512 and SHA-384 use HMac.
+ */
+ public OldHMac(
+ Digest digest)
+ {
+ this.digest = digest;
+ digestSize = digest.getDigestSize();
+ }
+
+ public String getAlgorithmName()
+ {
+ return digest.getAlgorithmName() + "/HMAC";
+ }
+
+ public Digest getUnderlyingDigest()
+ {
+ return digest;
+ }
+
+ public void init(
+ CipherParameters params)
+ {
+ digest.reset();
+
+ byte[] key = ((KeyParameter)params).getKey();
+
+ if (key.length > BLOCK_LENGTH)
+ {
+ digest.update(key, 0, key.length);
+ digest.doFinal(inputPad, 0);
+ for (int i = digestSize; i < inputPad.length; i++)
+ {
+ inputPad[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(key, 0, inputPad, 0, key.length);
+ for (int i = key.length; i < inputPad.length; i++)
+ {
+ inputPad[i] = 0;
+ }
+ }
+
+ outputPad = new byte[inputPad.length];
+ System.arraycopy(inputPad, 0, outputPad, 0, inputPad.length);
+
+ for (int i = 0; i < inputPad.length; i++)
+ {
+ inputPad[i] ^= IPAD;
+ }
+
+ for (int i = 0; i < outputPad.length; i++)
+ {
+ outputPad[i] ^= OPAD;
+ }
+
+ digest.update(inputPad, 0, inputPad.length);
+ }
+
+ public int getMacSize()
+ {
+ return digestSize;
+ }
+
+ public void update(
+ byte in)
+ {
+ digest.update(in);
+ }
+
+ public void update(
+ byte[] in,
+ int inOff,
+ int len)
+ {
+ digest.update(in, inOff, len);
+ }
+
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ {
+ byte[] tmp = new byte[digestSize];
+ digest.doFinal(tmp, 0);
+
+ digest.update(outputPad, 0, outputPad.length);
+ digest.update(tmp, 0, tmp.length);
+
+ int len = digest.doFinal(out, outOff);
+
+ reset();
+
+ return len;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ /*
+ * reset the underlying digest.
+ */
+ digest.reset();
+
+ /*
+ * reinitialize the digest.
+ */
+ digest.update(inputPad, 0, inputPad.length);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/VMPCMac.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/VMPCMac.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/VMPCMac.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/VMPCMac.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,186 @@
+package pdftk.org.bouncycastle.crypto.macs;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+public class VMPCMac implements Mac
+{
+ private byte g;
+
+ private byte n = 0;
+ private byte[] P = null;
+ private byte s = 0;
+
+ private byte[] T;
+ private byte[] workingIV;
+
+ private byte[] workingKey;
+
+ private byte x1, x2, x3, x4;
+
+ public int doFinal(byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ // Execute the Post-Processing Phase
+ for (int r = 1; r < 25; r++)
+ {
+ s = P[(s + P[n & 0xff]) & 0xff];
+
+ x4 = P[(x4 + x3 + r) & 0xff];
+ x3 = P[(x3 + x2 + r) & 0xff];
+ x2 = P[(x2 + x1 + r) & 0xff];
+ x1 = P[(x1 + s + r) & 0xff];
+ T[g & 0x1f] = (byte) (T[g & 0x1f] ^ x1);
+ T[(g + 1) & 0x1f] = (byte) (T[(g + 1) & 0x1f] ^ x2);
+ T[(g + 2) & 0x1f] = (byte) (T[(g + 2) & 0x1f] ^ x3);
+ T[(g + 3) & 0x1f] = (byte) (T[(g + 3) & 0x1f] ^ x4);
+ g = (byte) ((g + 4) & 0x1f);
+
+ byte temp = P[n & 0xff];
+ P[n & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ n = (byte) ((n + 1) & 0xff);
+ }
+
+ // Input T to the IV-phase of the VMPC KSA
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + T[m & 0x1f]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+
+ // Store 20 new outputs of the VMPC Stream Cipher in table M
+ byte[] M = new byte[20];
+ for (int i = 0; i < 20; i++)
+ {
+ s = P[(s + P[i & 0xff]) & 0xff];
+ M[i] = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+
+ byte temp = P[i & 0xff];
+ P[i & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+
+ System.arraycopy(M, 0, out, outOff, M.length);
+ reset();
+
+ return M.length;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "VMPC-MAC";
+ }
+
+ public int getMacSize()
+ {
+ return 20;
+ }
+
+ public void init(CipherParameters params) throws IllegalArgumentException
+ {
+ if (!(params instanceof ParametersWithIV))
+ {
+ throw new IllegalArgumentException(
+ "VMPC-MAC Init parameters must include an IV");
+ }
+
+ ParametersWithIV ivParams = (ParametersWithIV) params;
+ KeyParameter key = (KeyParameter) ivParams.getParameters();
+
+ if (!(ivParams.getParameters() instanceof KeyParameter))
+ {
+ throw new IllegalArgumentException(
+ "VMPC-MAC Init parameters must include a key");
+ }
+
+ this.workingIV = ivParams.getIV();
+
+ if (workingIV == null || workingIV.length < 1 || workingIV.length > 768)
+ {
+ throw new IllegalArgumentException(
+ "VMPC-MAC requires 1 to 768 bytes of IV");
+ }
+
+ this.workingKey = key.getKey();
+
+ reset();
+
+ }
+
+ private void initKey(byte[] keyBytes, byte[] ivBytes)
+ {
+ s = 0;
+ P = new byte[256];
+ for (int i = 0; i < 256; i++)
+ {
+ P[i] = (byte) i;
+ }
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+ for (int m = 0; m < 768; m++)
+ {
+ s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.length]) & 0xff];
+ byte temp = P[m & 0xff];
+ P[m & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ }
+ n = 0;
+ }
+
+ public void reset()
+ {
+ initKey(this.workingKey, this.workingIV);
+ g = x1 = x2 = x3 = x4 = n = 0;
+ T = new byte[32];
+ for (int i = 0; i < 32; i++)
+ {
+ T[i] = 0;
+ }
+ }
+
+ public void update(byte in) throws IllegalStateException
+ {
+ s = P[(s + P[n & 0xff]) & 0xff];
+ byte c = (byte) (in ^ P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff]);
+
+ x4 = P[(x4 + x3) & 0xff];
+ x3 = P[(x3 + x2) & 0xff];
+ x2 = P[(x2 + x1) & 0xff];
+ x1 = P[(x1 + s + c) & 0xff];
+ T[g & 0x1f] = (byte) (T[g & 0x1f] ^ x1);
+ T[(g + 1) & 0x1f] = (byte) (T[(g + 1) & 0x1f] ^ x2);
+ T[(g + 2) & 0x1f] = (byte) (T[(g + 2) & 0x1f] ^ x3);
+ T[(g + 3) & 0x1f] = (byte) (T[(g + 3) & 0x1f] ^ x4);
+ g = (byte) ((g + 4) & 0x1f);
+
+ byte temp = P[n & 0xff];
+ P[n & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ n = (byte) ((n + 1) & 0xff);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + len) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ for (int i = 0; i < len; i++)
+ {
+ update(in[i]);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/macs/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/macs/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Classes for creating MACs and HMACs.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/AEADBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/AEADBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/AEADBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/AEADBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,126 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A block cipher mode that includes authenticated encryption with a streaming mode and optional associated data.
+ * @see pdftk.org.bouncycastle.crypto.params.AEADParameters
+ */
+public interface AEADBlockCipher
+{
+ /**
+ * initialise the underlying cipher. Parameter can either be an AEADParameters or a ParametersWithIV object.
+ *
+ * @param forEncryption true if we are setting up for encryption, false otherwise.
+ * @param params the necessary parameters for the underlying cipher to be initialised.
+ * @exception IllegalArgumentException if the params argument is inappropriate.
+ */
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm.
+ *
+ * @return the algorithm name.
+ */
+ public String getAlgorithmName();
+
+ /**
+ * return the cipher this object wraps.
+ *
+ * @return the cipher this object wraps.
+ */
+ public BlockCipher getUnderlyingCipher();
+
+ /**
+ * Add a single byte to the associated data check.
+ * If the implementation supports it, this will be an online operation and will not retain the associated data.
+ *
+ * @param in the byte to be processed.
+ */
+ public void processAADByte(byte in);
+
+ /**
+ * Add a sequence of bytes to the associated data check.
+ * If the implementation supports it, this will be an online operation and will not retain the associated data.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset into the in array where the data to be processed starts.
+ * @param len the number of bytes to be processed.
+ */
+ public void processAADBytes(byte[] in, int inOff, int len);
+
+ /**
+ * encrypt/decrypt a single byte.
+ *
+ * @param in the byte to be processed.
+ * @param out the output buffer the processed byte goes into.
+ * @param outOff the offset into the output byte array the processed data starts at.
+ * @return the number of bytes written to out.
+ * @exception DataLengthException if the output buffer is too small.
+ */
+ public int processByte(byte in, byte[] out, int outOff)
+ throws DataLengthException;
+
+ /**
+ * process a block of bytes from in putting the result into out.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset into the in array where the data to be processed starts.
+ * @param len the number of bytes to be processed.
+ * @param out the output buffer the processed bytes go into.
+ * @param outOff the offset into the output byte array the processed data starts at.
+ * @return the number of bytes written to out.
+ * @exception DataLengthException if the output buffer is too small.
+ */
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ throws DataLengthException;
+
+ /**
+ * Finish the operation either appending or verifying the MAC at the end of the data.
+ *
+ * @param out space for any resulting output data.
+ * @param outOff offset into out to start copying the data at.
+ * @return number of bytes written into out.
+ * @throws IllegalStateException if the cipher is in an inappropriate state.
+ * @throws pdftk.org.bouncycastle.crypto.InvalidCipherTextException if the MAC fails to match.
+ */
+ public int doFinal(byte[] out, int outOff)
+ throws IllegalStateException, InvalidCipherTextException;
+
+ /**
+ * Return the value of the MAC associated with the last stream processed.
+ *
+ * @return MAC for plaintext data.
+ */
+ public byte[] getMac();
+
+ /**
+ * return the size of the output buffer required for a processBytes
+ * an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to processBytes
+ * with len bytes of input.
+ */
+ public int getUpdateOutputSize(int len);
+
+ /**
+ * return the size of the output buffer required for a processBytes plus a
+ * doFinal with an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to processBytes and doFinal
+ * with len bytes of input.
+ */
+ public int getOutputSize(int len);
+
+ /**
+ * Reset the cipher. After resetting the cipher is in the same state
+ * as it was after the last init (if there was one).
+ */
+ public void reset();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/CBCBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/CBCBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/CBCBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/CBCBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,253 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * implements Cipher-Block-Chaining (CBC) mode on top of a simple cipher.
+ */
+public class CBCBlockCipher
+ implements BlockCipher
+{
+ private byte[] IV;
+ private byte[] cbcV;
+ private byte[] cbcNextV;
+
+ private int blockSize;
+ private BlockCipher cipher = null;
+ private boolean encrypting;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of chaining.
+ */
+ public CBCBlockCipher(
+ BlockCipher cipher)
+ {
+ this.cipher = cipher;
+ this.blockSize = cipher.getBlockSize();
+
+ this.IV = new byte[blockSize];
+ this.cbcV = new byte[blockSize];
+ this.cbcNextV = new byte[blockSize];
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ *
+ * @param encrypting if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ boolean oldEncrypting = this.encrypting;
+
+ this.encrypting = encrypting;
+
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length != blockSize)
+ {
+ throw new IllegalArgumentException("initialisation vector must be the same length as block size");
+ }
+
+ System.arraycopy(iv, 0, IV, 0, iv.length);
+
+ reset();
+
+ // if null it's an IV changed only.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(encrypting, ivParam.getParameters());
+ }
+ else if (oldEncrypting != encrypting)
+ {
+ throw new IllegalArgumentException("cannot change encrypting state without providing key.");
+ }
+ }
+ else
+ {
+ reset();
+
+ // if it's null, key is to be reused.
+ if (params != null)
+ {
+ cipher.init(encrypting, params);
+ }
+ else if (oldEncrypting != encrypting)
+ {
+ throw new IllegalArgumentException("cannot change encrypting state without providing key.");
+ }
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/CBC".
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/CBC";
+ }
+
+ /**
+ * return the block size of the underlying cipher.
+ *
+ * @return the block size of the underlying cipher.
+ */
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
+ }
+
+ /**
+ * reset the chaining vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ System.arraycopy(IV, 0, cbcV, 0, IV.length);
+ Arrays.fill(cbcNextV, (byte)0);
+
+ cipher.reset();
+ }
+
+ /**
+ * Do the appropriate chaining step for CBC mode encryption.
+ *
+ * @param in the array containing the data to be encrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ /*
+ * XOR the cbcV and the input,
+ * then encrypt the cbcV
+ */
+ for (int i = 0; i < blockSize; i++)
+ {
+ cbcV[i] ^= in[inOff + i];
+ }
+
+ int length = cipher.processBlock(cbcV, 0, out, outOff);
+
+ /*
+ * copy ciphertext to cbcV
+ */
+ System.arraycopy(out, outOff, cbcV, 0, cbcV.length);
+
+ return length;
+ }
+
+ /**
+ * Do the appropriate chaining step for CBC mode decryption.
+ *
+ * @param in the array containing the data to be decrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the decrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ System.arraycopy(in, inOff, cbcNextV, 0, blockSize);
+
+ int length = cipher.processBlock(in, inOff, out, outOff);
+
+ /*
+ * XOR the cbcV and the output
+ */
+ for (int i = 0; i < blockSize; i++)
+ {
+ out[outOff + i] ^= cbcV[i];
+ }
+
+ /*
+ * swap the back up buffer into next position
+ */
+ byte[] tmp;
+
+ tmp = cbcV;
+ cbcV = cbcNextV;
+ cbcNextV = tmp;
+
+ return length;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/CCMBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/CCMBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/CCMBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/CCMBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,367 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import java.io.ByteArrayOutputStream;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.macs.CBCBlockCipherMac;
+import pdftk.org.bouncycastle.crypto.params.AEADParameters;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * Implements the Counter with Cipher Block Chaining mode (CCM) detailed in
+ * NIST Special Publication 800-38C.
+ *
+ * Note : this mode is a packet mode - it needs all the data up front.
+ */
+public class CCMBlockCipher
+ implements AEADBlockCipher
+{
+ private BlockCipher cipher;
+ private int blockSize;
+ private boolean forEncryption;
+ private byte[] nonce;
+ private byte[] initialAssociatedText;
+ private int macSize;
+ private CipherParameters keyParam;
+ private byte[] macBlock;
+ private ByteArrayOutputStream associatedText = new ByteArrayOutputStream();
+ private ByteArrayOutputStream data = new ByteArrayOutputStream();
+
+ /**
+ * Basic constructor.
+ *
+ * @param c the block cipher to be used.
+ */
+ public CCMBlockCipher(BlockCipher c)
+ {
+ this.cipher = c;
+ this.blockSize = c.getBlockSize();
+ this.macBlock = new byte[blockSize];
+
+ if (blockSize != 16)
+ {
+ throw new IllegalArgumentException("cipher required with a block size of 16.");
+ }
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ if (params instanceof AEADParameters)
+ {
+ AEADParameters param = (AEADParameters)params;
+
+ nonce = param.getNonce();
+ initialAssociatedText = param.getAssociatedText();
+ macSize = param.getMacSize() / 8;
+ keyParam = param.getKey();
+ }
+ else if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV param = (ParametersWithIV)params;
+
+ nonce = param.getIV();
+ initialAssociatedText = null;
+ macSize = macBlock.length / 2;
+ keyParam = param.getParameters();
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameters passed to CCM");
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/CCM";
+ }
+
+ public void processAADByte(byte in)
+ {
+ associatedText.write(in);
+ }
+
+ public void processAADBytes(byte[] in, int inOff, int len)
+ {
+ // TODO: Process AAD online
+ associatedText.write(in, inOff, len);
+ }
+
+ public int processByte(byte in, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ data.write(in);
+
+ return 0;
+ }
+
+ public int processBytes(byte[] in, int inOff, int inLen, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ data.write(in, inOff, inLen);
+
+ return 0;
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ throws IllegalStateException, InvalidCipherTextException
+ {
+ byte[] text = data.toByteArray();
+ byte[] enc = processPacket(text, 0, text.length);
+
+ System.arraycopy(enc, 0, out, outOff, enc.length);
+
+ reset();
+
+ return enc.length;
+ }
+
+ public void reset()
+ {
+ cipher.reset();
+ associatedText.reset();
+ data.reset();
+ }
+
+ /**
+ * Returns a byte array containing the mac calculated as part of the
+ * last encrypt or decrypt operation.
+ *
+ * @return the last mac calculated.
+ */
+ public byte[] getMac()
+ {
+ byte[] mac = new byte[macSize];
+
+ System.arraycopy(macBlock, 0, mac, 0, mac.length);
+
+ return mac;
+ }
+
+ public int getUpdateOutputSize(int len)
+ {
+ return 0;
+ }
+
+ public int getOutputSize(int len)
+ {
+ int totalData = len + data.size();
+
+ if (forEncryption)
+ {
+ return totalData + macSize;
+ }
+
+ return totalData < macSize ? 0 : totalData - macSize;
+ }
+
+ public byte[] processPacket(byte[] in, int inOff, int inLen)
+ throws IllegalStateException, InvalidCipherTextException
+ {
+ // TODO: handle null keyParam (e.g. via RepeatedKeySpec)
+ // Need to keep the CTR and CBC Mac parts around and reset
+ if (keyParam == null)
+ {
+ throw new IllegalStateException("CCM cipher unitialized.");
+ }
+
+ BlockCipher ctrCipher = new SICBlockCipher(cipher);
+ byte[] iv = new byte[blockSize];
+ byte[] out;
+
+ iv[0] = (byte)(((15 - nonce.length) - 1) & 0x7);
+
+ System.arraycopy(nonce, 0, iv, 1, nonce.length);
+
+ ctrCipher.init(forEncryption, new ParametersWithIV(keyParam, iv));
+
+ if (forEncryption)
+ {
+ int index = inOff;
+ int outOff = 0;
+
+ out = new byte[inLen + macSize];
+
+ calculateMac(in, inOff, inLen, macBlock);
+
+ ctrCipher.processBlock(macBlock, 0, macBlock, 0); // S0
+
+ while (index < inLen - blockSize) // S1...
+ {
+ ctrCipher.processBlock(in, index, out, outOff);
+ outOff += blockSize;
+ index += blockSize;
+ }
+
+ byte[] block = new byte[blockSize];
+
+ System.arraycopy(in, index, block, 0, inLen - index);
+
+ ctrCipher.processBlock(block, 0, block, 0);
+
+ System.arraycopy(block, 0, out, outOff, inLen - index);
+
+ outOff += inLen - index;
+
+ System.arraycopy(macBlock, 0, out, outOff, out.length - outOff);
+ }
+ else
+ {
+ int index = inOff;
+ int outOff = 0;
+
+ out = new byte[inLen - macSize];
+
+ System.arraycopy(in, inOff + inLen - macSize, macBlock, 0, macSize);
+
+ ctrCipher.processBlock(macBlock, 0, macBlock, 0);
+
+ for (int i = macSize; i != macBlock.length; i++)
+ {
+ macBlock[i] = 0;
+ }
+
+ while (outOff < out.length - blockSize)
+ {
+ ctrCipher.processBlock(in, index, out, outOff);
+ outOff += blockSize;
+ index += blockSize;
+ }
+
+ byte[] block = new byte[blockSize];
+
+ System.arraycopy(in, index, block, 0, out.length - outOff);
+
+ ctrCipher.processBlock(block, 0, block, 0);
+
+ System.arraycopy(block, 0, out, outOff, out.length - outOff);
+
+ byte[] calculatedMacBlock = new byte[blockSize];
+
+ calculateMac(out, 0, out.length, calculatedMacBlock);
+
+ if (!Arrays.constantTimeAreEqual(macBlock, calculatedMacBlock))
+ {
+ throw new InvalidCipherTextException("mac check in CCM failed");
+ }
+ }
+
+ return out;
+ }
+
+ private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
+ {
+ Mac cMac = new CBCBlockCipherMac(cipher, macSize * 8);
+
+ cMac.init(keyParam);
+
+ //
+ // build b0
+ //
+ byte[] b0 = new byte[16];
+
+ if (hasAssociatedText())
+ {
+ b0[0] |= 0x40;
+ }
+
+ b0[0] |= (((cMac.getMacSize() - 2) / 2) & 0x7) << 3;
+
+ b0[0] |= ((15 - nonce.length) - 1) & 0x7;
+
+ System.arraycopy(nonce, 0, b0, 1, nonce.length);
+
+ int q = dataLen;
+ int count = 1;
+ while (q > 0)
+ {
+ b0[b0.length - count] = (byte)(q & 0xff);
+ q >>>= 8;
+ count++;
+ }
+
+ cMac.update(b0, 0, b0.length);
+
+ //
+ // process associated text
+ //
+ if (hasAssociatedText())
+ {
+ int extra;
+
+ int textLength = getAssociatedTextLength();
+ if (textLength < ((1 << 16) - (1 << 8)))
+ {
+ cMac.update((byte)(textLength >> 8));
+ cMac.update((byte)textLength);
+
+ extra = 2;
+ }
+ else // can't go any higher than 2^32
+ {
+ cMac.update((byte)0xff);
+ cMac.update((byte)0xfe);
+ cMac.update((byte)(textLength >> 24));
+ cMac.update((byte)(textLength >> 16));
+ cMac.update((byte)(textLength >> 8));
+ cMac.update((byte)textLength);
+
+ extra = 6;
+ }
+
+ if (initialAssociatedText != null)
+ {
+ cMac.update(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+ if (associatedText.size() > 0)
+ {
+ byte[] tmp = associatedText.toByteArray();
+ cMac.update(tmp, 0, tmp.length);
+ }
+
+ extra = (extra + textLength) % 16;
+ if (extra != 0)
+ {
+ for (int i = 0; i != 16 - extra; i++)
+ {
+ cMac.update((byte)0x00);
+ }
+ }
+ }
+
+ //
+ // add the text
+ //
+ cMac.update(data, dataOff, dataLen);
+
+ return cMac.doFinal(macBlock, 0);
+ }
+
+ private int getAssociatedTextLength()
+ {
+ return associatedText.size() + ((initialAssociatedText == null) ? 0 : initialAssociatedText.length);
+ }
+
+ private boolean hasAssociatedText()
+ {
+ return getAssociatedTextLength() > 0;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/CFBBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/CFBBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/CFBBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/CFBBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,258 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
+ */
+public class CFBBlockCipher
+ implements BlockCipher
+{
+ private byte[] IV;
+ private byte[] cfbV;
+ private byte[] cfbOutV;
+
+ private int blockSize;
+ private BlockCipher cipher = null;
+ private boolean encrypting;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ * @param bitBlockSize the block size in bits (note: a multiple of 8)
+ */
+ public CFBBlockCipher(
+ BlockCipher cipher,
+ int bitBlockSize)
+ {
+ this.cipher = cipher;
+ this.blockSize = bitBlockSize / 8;
+
+ this.IV = new byte[cipher.getBlockSize()];
+ this.cfbV = new byte[cipher.getBlockSize()];
+ this.cfbOutV = new byte[cipher.getBlockSize()];
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param encrypting if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.encrypting = encrypting;
+
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ // prepend the supplied IV with zeros (per FIPS PUB 81)
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ for (int i = 0; i < IV.length - iv.length; i++)
+ {
+ IV[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ // if null it's an IV changed only.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(true, ivParam.getParameters());
+ }
+ }
+ else
+ {
+ reset();
+
+ // if it's null, key is to be reused.
+ if (params != null)
+ {
+ cipher.init(true, params);
+ }
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/CFB"
+ * and the block size in bits.
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/CFB" + (blockSize * 8);
+ }
+
+ /**
+ * return the block size we are operating at.
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
+ }
+
+ /**
+ * Do the appropriate processing for CFB mode encryption.
+ *
+ * @param in the array containing the data to be encrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ cipher.processBlock(cfbV, 0, cfbOutV, 0);
+
+ //
+ // XOR the cfbV with the plaintext producing the ciphertext
+ //
+ for (int i = 0; i < blockSize; i++)
+ {
+ out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]);
+ }
+
+ //
+ // change over the input block.
+ //
+ System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
+ System.arraycopy(out, outOff, cfbV, cfbV.length - blockSize, blockSize);
+
+ return blockSize;
+ }
+
+ /**
+ * Do the appropriate processing for CFB mode decryption.
+ *
+ * @param in the array containing the data to be decrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ cipher.processBlock(cfbV, 0, cfbOutV, 0);
+
+ //
+ // change over the input block.
+ //
+ System.arraycopy(cfbV, blockSize, cfbV, 0, cfbV.length - blockSize);
+ System.arraycopy(in, inOff, cfbV, cfbV.length - blockSize, blockSize);
+
+ //
+ // XOR the cfbV with the ciphertext producing the plaintext
+ //
+ for (int i = 0; i < blockSize; i++)
+ {
+ out[outOff + i] = (byte)(cfbOutV[i] ^ in[inOff + i]);
+ }
+
+ return blockSize;
+ }
+
+ /**
+ * reset the chaining vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ System.arraycopy(IV, 0, cfbV, 0, IV.length);
+
+ cipher.reset();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/CTSBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/CTSBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/CTSBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/CTSBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,265 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.BufferedBlockCipher;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to
+ * be used to produce cipher text which is the same length as the plain text.
+ */
+public class CTSBlockCipher
+ extends BufferedBlockCipher
+{
+ private int blockSize;
+
+ /**
+ * Create a buffered block cipher that uses Cipher Text Stealing
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ */
+ public CTSBlockCipher(
+ BlockCipher cipher)
+ {
+ if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher))
+ {
+ throw new IllegalArgumentException("CTSBlockCipher can only accept ECB, or CBC ciphers");
+ }
+
+ this.cipher = cipher;
+
+ blockSize = cipher.getBlockSize();
+
+ buf = new byte[blockSize * 2];
+ bufOff = 0;
+ }
+
+ /**
+ * return the size of the output buffer required for an update
+ * an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update
+ * with len bytes of input.
+ */
+ public int getUpdateOutputSize(
+ int len)
+ {
+ int total = len + bufOff;
+ int leftOver = total % buf.length;
+
+ if (leftOver == 0)
+ {
+ return total - buf.length;
+ }
+
+ return total - leftOver;
+ }
+
+ /**
+ * return the size of the output buffer required for an update plus a
+ * doFinal with an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update and doFinal
+ * with len bytes of input.
+ */
+ public int getOutputSize(
+ int len)
+ {
+ return len + bufOff;
+ }
+
+ /**
+ * process a single byte, producing an output block if neccessary.
+ *
+ * @param in the input byte.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ int resultLen = 0;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ System.arraycopy(buf, blockSize, buf, 0, blockSize);
+
+ bufOff = blockSize;
+ }
+
+ buf[bufOff++] = in;
+
+ return resultLen;
+ }
+
+ /**
+ * process an array of bytes, producing output if necessary.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset at which the input data starts.
+ * @param len the number of bytes to be copied out of the input array.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = getBlockSize();
+ int length = getUpdateOutputSize(len);
+
+ if (length > 0)
+ {
+ if ((outOff + length) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff);
+ System.arraycopy(buf, blockSize, buf, 0, blockSize);
+
+ bufOff = blockSize;
+
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, blockSize);
+ resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
+ System.arraycopy(buf, blockSize, buf, 0, blockSize);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+
+ return resultLen;
+ }
+
+ /**
+ * Process the last block in the buffer.
+ *
+ * @param out the array the block currently being held is copied into.
+ * @param outOff the offset at which the copying starts.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there is insufficient space in out for
+ * the output.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception InvalidCipherTextException if cipher text decrypts wrongly (in
+ * case the exception will never get thrown).
+ */
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException, InvalidCipherTextException
+ {
+ if (bufOff + outOff > out.length)
+ {
+ throw new DataLengthException("output buffer to small in doFinal");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int len = bufOff - blockSize;
+ byte[] block = new byte[blockSize];
+
+ if (forEncryption)
+ {
+ cipher.processBlock(buf, 0, block, 0);
+
+ if (bufOff < blockSize)
+ {
+ throw new DataLengthException("need at least one block of input for CTS");
+ }
+
+ for (int i = bufOff; i != buf.length; i++)
+ {
+ buf[i] = block[i - blockSize];
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ buf[i] ^= block[i - blockSize];
+ }
+
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, blockSize, out, outOff);
+ }
+ else
+ {
+ cipher.processBlock(buf, blockSize, out, outOff);
+ }
+
+ System.arraycopy(block, 0, out, outOff + blockSize, len);
+ }
+ else
+ {
+ byte[] lastBlock = new byte[blockSize];
+
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, 0, block, 0);
+ }
+ else
+ {
+ cipher.processBlock(buf, 0, block, 0);
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
+ }
+
+ System.arraycopy(buf, blockSize, block, 0, len);
+
+ cipher.processBlock(block, 0, out, outOff);
+ System.arraycopy(lastBlock, 0, out, outOff + blockSize, len);
+ }
+
+ int offset = bufOff;
+
+ reset();
+
+ return offset;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/EAXBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/EAXBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/EAXBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/EAXBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,368 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.macs.CMac;
+import pdftk.org.bouncycastle.crypto.params.AEADParameters;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * A Two-Pass Authenticated-Encryption Scheme Optimized for Simplicity and
+ * Efficiency - by M. Bellare, P. Rogaway, D. Wagner.
+ *
+ * http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
+ *
+ * EAX is an AEAD scheme based on CTR and OMAC1/CMAC, that uses a single block
+ * cipher to encrypt and authenticate data. It's on-line (the length of a
+ * message isn't needed to begin processing it), has good performances, it's
+ * simple and provably secure (provided the underlying block cipher is secure).
+ *
+ * Of course, this implementations is NOT thread-safe.
+ */
+public class EAXBlockCipher
+ implements AEADBlockCipher
+{
+ private static final byte nTAG = 0x0;
+
+ private static final byte hTAG = 0x1;
+
+ private static final byte cTAG = 0x2;
+
+ private SICBlockCipher cipher;
+
+ private boolean forEncryption;
+
+ private int blockSize;
+
+ private Mac mac;
+
+ private byte[] nonceMac;
+ private byte[] associatedTextMac;
+ private byte[] macBlock;
+
+ private int macSize;
+ private byte[] bufBlock;
+ private int bufOff;
+
+ private boolean cipherInitialized;
+ private byte[] initialAssociatedText;
+
+ /**
+ * Constructor that accepts an instance of a block cipher engine.
+ *
+ * @param cipher the engine to use
+ */
+ public EAXBlockCipher(BlockCipher cipher)
+ {
+ blockSize = cipher.getBlockSize();
+ mac = new CMac(cipher);
+ macBlock = new byte[blockSize];
+ bufBlock = new byte[blockSize * 2];
+ associatedTextMac = new byte[mac.getMacSize()];
+ nonceMac = new byte[mac.getMacSize()];
+ this.cipher = new SICBlockCipher(cipher);
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getUnderlyingCipher().getAlgorithmName() + "/EAX";
+ }
+
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher.getUnderlyingCipher();
+ }
+
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ byte[] nonce;
+ CipherParameters keyParam;
+
+ if (params instanceof AEADParameters)
+ {
+ AEADParameters param = (AEADParameters)params;
+
+ nonce = param.getNonce();
+ initialAssociatedText = param.getAssociatedText();
+ macSize = param.getMacSize() / 8;
+ keyParam = param.getKey();
+ }
+ else if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV param = (ParametersWithIV)params;
+
+ nonce = param.getIV();
+ initialAssociatedText = null;
+ macSize = mac.getMacSize() / 2;
+ keyParam = param.getParameters();
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameters passed to EAX");
+ }
+
+ byte[] tag = new byte[blockSize];
+
+ // Key reuse implemented in CBC mode of underlying CMac
+ mac.init(keyParam);
+
+ tag[blockSize - 1] = nTAG;
+ mac.update(tag, 0, blockSize);
+ mac.update(nonce, 0, nonce.length);
+ mac.doFinal(nonceMac, 0);
+
+ tag[blockSize - 1] = hTAG;
+ mac.update(tag, 0, blockSize);
+
+ if (initialAssociatedText != null)
+ {
+ processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+
+ // Same BlockCipher underlies this and the mac, so reuse last key on cipher
+ cipher.init(true, new ParametersWithIV(null, nonceMac));
+ }
+
+ private void initCipher()
+ {
+ if (cipherInitialized)
+ {
+ return;
+ }
+
+ cipherInitialized = true;
+
+ mac.doFinal(associatedTextMac, 0);
+
+ byte[] tag = new byte[blockSize];
+ tag[blockSize - 1] = cTAG;
+ mac.update(tag, 0, blockSize);
+ }
+
+ private void calculateMac()
+ {
+ byte[] outC = new byte[blockSize];
+ mac.doFinal(outC, 0);
+
+ for (int i = 0; i < macBlock.length; i++)
+ {
+ macBlock[i] = (byte)(nonceMac[i] ^ associatedTextMac[i] ^ outC[i]);
+ }
+ }
+
+ public void reset()
+ {
+ reset(true);
+ }
+
+ private void reset(
+ boolean clearMac)
+ {
+ cipher.reset(); // TODO Redundant since the mac will reset it?
+ mac.reset();
+
+ bufOff = 0;
+ Arrays.fill(bufBlock, (byte)0);
+
+ if (clearMac)
+ {
+ Arrays.fill(macBlock, (byte)0);
+ }
+
+ byte[] tag = new byte[blockSize];
+ tag[blockSize - 1] = hTAG;
+ mac.update(tag, 0, blockSize);
+
+ cipherInitialized = false;
+
+ if (initialAssociatedText != null)
+ {
+ processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+ }
+
+ public void processAADByte(byte in)
+ {
+ if (cipherInitialized)
+ {
+ throw new IllegalStateException("AAD data cannot be added after encryption/decription processing has begun.");
+ }
+ mac.update(in);
+ }
+
+ public void processAADBytes(byte[] in, int inOff, int len)
+ {
+ if (cipherInitialized)
+ {
+ throw new IllegalStateException("AAD data cannot be added after encryption/decription processing has begun.");
+ }
+ mac.update(in, inOff, len);
+ }
+
+ public int processByte(byte in, byte[] out, int outOff)
+ throws DataLengthException
+ {
+ initCipher();
+
+ return process(in, out, outOff);
+ }
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ throws DataLengthException
+ {
+ initCipher();
+
+ int resultLen = 0;
+
+ for (int i = 0; i != len; i++)
+ {
+ resultLen += process(in[inOff + i], out, outOff + resultLen);
+ }
+
+ return resultLen;
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ throws IllegalStateException, InvalidCipherTextException
+ {
+ initCipher();
+
+ int extra = bufOff;
+ byte[] tmp = new byte[bufBlock.length];
+
+ bufOff = 0;
+
+ if (forEncryption)
+ {
+ cipher.processBlock(bufBlock, 0, tmp, 0);
+ cipher.processBlock(bufBlock, blockSize, tmp, blockSize);
+
+ System.arraycopy(tmp, 0, out, outOff, extra);
+
+ mac.update(tmp, 0, extra);
+
+ calculateMac();
+
+ System.arraycopy(macBlock, 0, out, outOff + extra, macSize);
+
+ reset(false);
+
+ return extra + macSize;
+ }
+ else
+ {
+ if (extra > macSize)
+ {
+ mac.update(bufBlock, 0, extra - macSize);
+
+ cipher.processBlock(bufBlock, 0, tmp, 0);
+ cipher.processBlock(bufBlock, blockSize, tmp, blockSize);
+
+ System.arraycopy(tmp, 0, out, outOff, extra - macSize);
+ }
+
+ calculateMac();
+
+ if (!verifyMac(bufBlock, extra - macSize))
+ {
+ throw new InvalidCipherTextException("mac check in EAX failed");
+ }
+
+ reset(false);
+
+ return extra - macSize;
+ }
+ }
+
+ public byte[] getMac()
+ {
+ byte[] mac = new byte[macSize];
+
+ System.arraycopy(macBlock, 0, mac, 0, macSize);
+
+ return mac;
+ }
+
+ public int getUpdateOutputSize(int len)
+ {
+ int totalData = len + bufOff;
+ if (!forEncryption)
+ {
+ if (totalData < macSize)
+ {
+ return 0;
+ }
+ totalData -= macSize;
+ }
+ return totalData - totalData % blockSize;
+ }
+
+ public int getOutputSize(int len)
+ {
+ int totalData = len + bufOff;
+
+ if (forEncryption)
+ {
+ return totalData + macSize;
+ }
+
+ return totalData < macSize ? 0 : totalData - macSize;
+ }
+
+ private int process(byte b, byte[] out, int outOff)
+ {
+ bufBlock[bufOff++] = b;
+
+ if (bufOff == bufBlock.length)
+ {
+ // TODO Could move the processByte(s) calls to here
+// initCipher();
+
+ int size;
+
+ if (forEncryption)
+ {
+ size = cipher.processBlock(bufBlock, 0, out, outOff);
+
+ mac.update(out, outOff, blockSize);
+ }
+ else
+ {
+ mac.update(bufBlock, 0, blockSize);
+
+ size = cipher.processBlock(bufBlock, 0, out, outOff);
+ }
+
+ bufOff = blockSize;
+ System.arraycopy(bufBlock, blockSize, bufBlock, 0, blockSize);
+
+ return size;
+ }
+
+ return 0;
+ }
+
+ private boolean verifyMac(byte[] mac, int off)
+ {
+ int nonEqual = 0;
+
+ for (int i = 0; i < macSize; i++)
+ {
+ nonEqual |= (macBlock[i] ^ mac[off + i]);
+ }
+
+ return nonEqual == 0;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/GCMBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/GCMBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/GCMBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/GCMBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,574 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.modes.gcm.GCMExponentiator;
+import pdftk.org.bouncycastle.crypto.modes.gcm.GCMMultiplier;
+import pdftk.org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator;
+import pdftk.org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier;
+import pdftk.org.bouncycastle.crypto.params.AEADParameters;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+import pdftk.org.bouncycastle.crypto.util.Pack;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * Implements the Galois/Counter mode (GCM) detailed in
+ * NIST Special Publication 800-38D.
+ */
+public class GCMBlockCipher
+ implements AEADBlockCipher
+{
+ private static final int BLOCK_SIZE = 16;
+
+ // not final due to a compiler bug
+ private BlockCipher cipher;
+ private GCMMultiplier multiplier;
+ private GCMExponentiator exp;
+
+ // These fields are set by init and not modified by processing
+ private boolean forEncryption;
+ private int macSize;
+ private byte[] nonce;
+ private byte[] initialAssociatedText;
+ private byte[] H;
+ private byte[] J0;
+
+ // These fields are modified during processing
+ private byte[] bufBlock;
+ private byte[] macBlock;
+ private byte[] S, S_at, S_atPre;
+ private byte[] counter;
+ private int bufOff;
+ private long totalLength;
+ private byte[] atBlock;
+ private int atBlockPos;
+ private long atLength;
+ private long atLengthPre;
+
+ public GCMBlockCipher(BlockCipher c)
+ {
+ this(c, null);
+ }
+
+ public GCMBlockCipher(BlockCipher c, GCMMultiplier m)
+ {
+ if (c.getBlockSize() != BLOCK_SIZE)
+ {
+ throw new IllegalArgumentException(
+ "cipher required with a block size of " + BLOCK_SIZE + ".");
+ }
+
+ if (m == null)
+ {
+ // TODO Consider a static property specifying default multiplier
+ m = new Tables8kGCMMultiplier();
+ }
+
+ this.cipher = c;
+ this.multiplier = m;
+ }
+
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/GCM";
+ }
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+ this.macBlock = null;
+
+ KeyParameter keyParam;
+
+ if (params instanceof AEADParameters)
+ {
+ AEADParameters param = (AEADParameters)params;
+
+ nonce = param.getNonce();
+ initialAssociatedText = param.getAssociatedText();
+
+ int macSizeBits = param.getMacSize();
+ if (macSizeBits < 96 || macSizeBits > 128 || macSizeBits % 8 != 0)
+ {
+ throw new IllegalArgumentException("Invalid value for MAC size: " + macSizeBits);
+ }
+
+ macSize = macSizeBits / 8;
+ keyParam = param.getKey();
+ }
+ else if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV param = (ParametersWithIV)params;
+
+ nonce = param.getIV();
+ initialAssociatedText = null;
+ macSize = 16;
+ keyParam = (KeyParameter)param.getParameters();
+ }
+ else
+ {
+ throw new IllegalArgumentException("invalid parameters passed to GCM");
+ }
+
+ int bufLength = forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize);
+ this.bufBlock = new byte[bufLength];
+
+ if (nonce == null || nonce.length < 1)
+ {
+ throw new IllegalArgumentException("IV must be at least 1 byte");
+ }
+
+ // TODO This should be configurable by init parameters
+ // (but must be 16 if nonce length not 12) (BLOCK_SIZE?)
+// this.tagLength = 16;
+
+ // Cipher always used in forward mode
+ // if keyParam is null we're reusing the last key.
+ if (keyParam != null)
+ {
+ cipher.init(true, keyParam);
+
+ this.H = new byte[BLOCK_SIZE];
+ cipher.processBlock(H, 0, H, 0);
+
+ // GCMMultiplier tables don't change unless the key changes (and are expensive to init)
+ multiplier.init(H);
+ exp = null;
+ }
+
+ this.J0 = new byte[BLOCK_SIZE];
+
+ if (nonce.length == 12)
+ {
+ System.arraycopy(nonce, 0, J0, 0, nonce.length);
+ this.J0[BLOCK_SIZE - 1] = 0x01;
+ }
+ else
+ {
+ gHASH(J0, nonce, nonce.length);
+ byte[] X = new byte[BLOCK_SIZE];
+ Pack.longToBigEndian((long)nonce.length * 8, X, 8);
+ gHASHBlock(J0, X);
+ }
+
+ this.S = new byte[BLOCK_SIZE];
+ this.S_at = new byte[BLOCK_SIZE];
+ this.S_atPre = new byte[BLOCK_SIZE];
+ this.atBlock = new byte[BLOCK_SIZE];
+ this.atBlockPos = 0;
+ this.atLength = 0;
+ this.atLengthPre = 0;
+ this.counter = Arrays.clone(J0);
+ this.bufOff = 0;
+ this.totalLength = 0;
+
+ if (initialAssociatedText != null)
+ {
+ processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+ }
+
+ public byte[] getMac()
+ {
+ return Arrays.clone(macBlock);
+ }
+
+ public int getOutputSize(int len)
+ {
+ int totalData = len + bufOff;
+
+ if (forEncryption)
+ {
+ return totalData + macSize;
+ }
+
+ return totalData < macSize ? 0 : totalData - macSize;
+ }
+
+ public int getUpdateOutputSize(int len)
+ {
+ int totalData = len + bufOff;
+ if (!forEncryption)
+ {
+ if (totalData < macSize)
+ {
+ return 0;
+ }
+ totalData -= macSize;
+ }
+ return totalData - totalData % BLOCK_SIZE;
+ }
+
+ public void processAADByte(byte in)
+ {
+ atBlock[atBlockPos] = in;
+ if (++atBlockPos == BLOCK_SIZE)
+ {
+ // Hash each block as it fills
+ gHASHBlock(S_at, atBlock);
+ atBlockPos = 0;
+ atLength += BLOCK_SIZE;
+ }
+ }
+
+ public void processAADBytes(byte[] in, int inOff, int len)
+ {
+ for (int i = 0; i < len; ++i)
+ {
+ atBlock[atBlockPos] = in[inOff + i];
+ if (++atBlockPos == BLOCK_SIZE)
+ {
+ // Hash each block as it fills
+ gHASHBlock(S_at, atBlock);
+ atBlockPos = 0;
+ atLength += BLOCK_SIZE;
+ }
+ }
+ }
+
+ private void initCipher()
+ {
+ if (atLength > 0)
+ {
+ System.arraycopy(S_at, 0, S_atPre, 0, BLOCK_SIZE);
+ atLengthPre = atLength;
+ }
+
+ // Finish hash for partial AAD block
+ if (atBlockPos > 0)
+ {
+ gHASHPartial(S_atPre, atBlock, 0, atBlockPos);
+ atLengthPre += atBlockPos;
+ }
+
+ if (atLengthPre > 0)
+ {
+ System.arraycopy(S_atPre, 0, S, 0, BLOCK_SIZE);
+ }
+ }
+
+ public int processByte(byte in, byte[] out, int outOff)
+ throws DataLengthException
+ {
+ bufBlock[bufOff] = in;
+ if (++bufOff == bufBlock.length)
+ {
+ outputBlock(out, outOff);
+ return BLOCK_SIZE;
+ }
+ return 0;
+ }
+
+ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
+ throws DataLengthException
+ {
+ int resultLen = 0;
+
+ for (int i = 0; i < len; ++i)
+ {
+ bufBlock[bufOff] = in[inOff + i];
+ if (++bufOff == bufBlock.length)
+ {
+ outputBlock(out, outOff + resultLen);
+ resultLen += BLOCK_SIZE;
+ }
+ }
+
+ return resultLen;
+ }
+
+ private void outputBlock(byte[] output, int offset)
+ {
+ if (totalLength == 0)
+ {
+ initCipher();
+ }
+ gCTRBlock(bufBlock, output, offset);
+ if (forEncryption)
+ {
+ bufOff = 0;
+ }
+ else
+ {
+ System.arraycopy(bufBlock, BLOCK_SIZE, bufBlock, 0, macSize);
+ bufOff = macSize;
+ }
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ throws IllegalStateException, InvalidCipherTextException
+ {
+ if (totalLength == 0)
+ {
+ initCipher();
+ }
+
+ int extra = bufOff;
+ if (!forEncryption)
+ {
+ if (extra < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+ extra -= macSize;
+ }
+
+ if (extra > 0)
+ {
+ gCTRPartial(bufBlock, 0, extra, out, outOff);
+ }
+
+ atLength += atBlockPos;
+
+ if (atLength > atLengthPre)
+ {
+ /*
+ * Some AAD was sent after the cipher started. We determine the difference b/w the hash value
+ * we actually used when the cipher started (S_atPre) and the final hash value calculated (S_at).
+ * Then we carry this difference forward by multiplying by H^c, where c is the number of (full or
+ * partial) cipher-text blocks produced, and adjust the current hash.
+ */
+
+ // Finish hash for partial AAD block
+ if (atBlockPos > 0)
+ {
+ gHASHPartial(S_at, atBlock, 0, atBlockPos);
+ }
+
+ // Find the difference between the AAD hashes
+ if (atLengthPre > 0)
+ {
+ xor(S_at, S_atPre);
+ }
+
+ // Number of cipher-text blocks produced
+ long c = ((totalLength * 8) + 127) >>> 7;
+
+ // Calculate the adjustment factor
+ byte[] H_c = new byte[16];
+ if (exp == null)
+ {
+ exp = new Tables1kGCMExponentiator();
+ exp.init(H);
+ }
+ exp.exponentiateX(c, H_c);
+
+ // Carry the difference forward
+ multiply(S_at, H_c);
+
+ // Adjust the current hash
+ xor(S, S_at);
+ }
+
+ // Final gHASH
+ byte[] X = new byte[BLOCK_SIZE];
+ Pack.longToBigEndian(atLength * 8, X, 0);
+ Pack.longToBigEndian(totalLength * 8, X, 8);
+
+ gHASHBlock(S, X);
+
+ // TODO Fix this if tagLength becomes configurable
+ // T = MSBt(GCTRk(J0,S))
+ byte[] tag = new byte[BLOCK_SIZE];
+ cipher.processBlock(J0, 0, tag, 0);
+ xor(tag, S);
+
+ int resultLen = extra;
+
+ // We place into macBlock our calculated value for T
+ this.macBlock = new byte[macSize];
+ System.arraycopy(tag, 0, macBlock, 0, macSize);
+
+ if (forEncryption)
+ {
+ // Append T to the message
+ System.arraycopy(macBlock, 0, out, outOff + bufOff, macSize);
+ resultLen += macSize;
+ }
+ else
+ {
+ // Retrieve the T value from the message and compare to calculated one
+ byte[] msgMac = new byte[macSize];
+ System.arraycopy(bufBlock, extra, msgMac, 0, macSize);
+ if (!Arrays.constantTimeAreEqual(this.macBlock, msgMac))
+ {
+ throw new InvalidCipherTextException("mac check in GCM failed");
+ }
+ }
+
+ reset(false);
+
+ return resultLen;
+ }
+
+ public void reset()
+ {
+ reset(true);
+ }
+
+ private void reset(
+ boolean clearMac)
+ {
+ cipher.reset();
+
+ S = new byte[BLOCK_SIZE];
+ S_at = new byte[BLOCK_SIZE];
+ S_atPre = new byte[BLOCK_SIZE];
+ atBlock = new byte[BLOCK_SIZE];
+ atBlockPos = 0;
+ atLength = 0;
+ atLengthPre = 0;
+ counter = Arrays.clone(J0);
+ bufOff = 0;
+ totalLength = 0;
+
+ if (bufBlock != null)
+ {
+ Arrays.fill(bufBlock, (byte)0);
+ }
+
+ if (clearMac)
+ {
+ macBlock = null;
+ }
+
+ if (initialAssociatedText != null)
+ {
+ processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
+ }
+ }
+
+ private void gCTRBlock(byte[] block, byte[] out, int outOff)
+ {
+ byte[] tmp = getNextCounterBlock();
+
+ xor(tmp, block);
+ System.arraycopy(tmp, 0, out, outOff, BLOCK_SIZE);
+
+ gHASHBlock(S, forEncryption ? tmp : block);
+
+ totalLength += BLOCK_SIZE;
+ }
+
+ private void gCTRPartial(byte[] buf, int off, int len, byte[] out, int outOff)
+ {
+ byte[] tmp = getNextCounterBlock();
+
+ xor(tmp, buf, off, len);
+ System.arraycopy(tmp, 0, out, outOff, len);
+
+ gHASHPartial(S, forEncryption ? tmp : buf, 0, len);
+
+ totalLength += len;
+ }
+
+ private void gHASH(byte[] Y, byte[] b, int len)
+ {
+ for (int pos = 0; pos < len; pos += BLOCK_SIZE)
+ {
+ int num = Math.min(len - pos, BLOCK_SIZE);
+ gHASHPartial(Y, b, pos, num);
+ }
+ }
+
+ private void gHASHBlock(byte[] Y, byte[] b)
+ {
+ xor(Y, b);
+ multiplier.multiplyH(Y);
+ }
+
+ private void gHASHPartial(byte[] Y, byte[] b, int off, int len)
+ {
+ xor(Y, b, off, len);
+ multiplier.multiplyH(Y);
+ }
+
+ private byte[] getNextCounterBlock()
+ {
+ for (int i = 15; i >= 12; --i)
+ {
+ byte b = (byte)((counter[i] + 1) & 0xff);
+ counter[i] = b;
+
+ if (b != 0)
+ {
+ break;
+ }
+ }
+
+ byte[] tmp = new byte[BLOCK_SIZE];
+ // TODO Sure would be nice if ciphers could operate on int[]
+ cipher.processBlock(counter, 0, tmp, 0);
+ return tmp;
+ }
+
+ private static void multiply(byte[] block, byte[] val)
+ {
+ byte[] tmp = Arrays.clone(block);
+ byte[] c = new byte[16];
+
+ for (int i = 0; i < 16; ++i)
+ {
+ byte bits = val[i];
+ for (int j = 7; j >= 0; --j)
+ {
+ if ((bits & (1 << j)) != 0)
+ {
+ xor(c, tmp);
+ }
+
+ boolean lsb = (tmp[15] & 1) != 0;
+ shiftRight(tmp);
+ if (lsb)
+ {
+ // R = new byte[]{ 0xe1, ... };
+// xor(v, R);
+ tmp[0] ^= (byte)0xe1;
+ }
+ }
+ }
+
+ System.arraycopy(c, 0, block, 0, 16);
+ }
+
+ private static void shiftRight(byte[] block)
+ {
+ int i = 0;
+ int bit = 0;
+ for (;;)
+ {
+ int b = block[i] & 0xff;
+ block[i] = (byte) ((b >>> 1) | bit);
+ if (++i == 16)
+ {
+ break;
+ }
+ bit = (b & 1) << 7;
+ }
+ }
+
+ private static void xor(byte[] block, byte[] val)
+ {
+ for (int i = 15; i >= 0; --i)
+ {
+ block[i] ^= val[i];
+ }
+ }
+
+ private static void xor(byte[] block, byte[] val, int off, int len)
+ {
+ while (len-- > 0)
+ {
+ block[len] ^= val[off + len];
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/GOFBBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/GOFBBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/GOFBBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/GOFBBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,234 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * implements the GOST 28147 OFB counter mode (GCTR).
+ */
+public class GOFBBlockCipher
+ implements BlockCipher
+{
+ private byte[] IV;
+ private byte[] ofbV;
+ private byte[] ofbOutV;
+
+ private final int blockSize;
+ private final BlockCipher cipher;
+
+ boolean firstStep = true;
+ int N3;
+ int N4;
+ static final int C1 = 16843012; //00000001000000010000000100000100
+ static final int C2 = 16843009; //00000001000000010000000100000001
+
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * counter mode (must have a 64 bit block size).
+ */
+ public GOFBBlockCipher(
+ BlockCipher cipher)
+ {
+ this.cipher = cipher;
+ this.blockSize = cipher.getBlockSize();
+
+ if (blockSize != 8)
+ {
+ throw new IllegalArgumentException("GCTR only for 64 bit block ciphers");
+ }
+
+ this.IV = new byte[cipher.getBlockSize()];
+ this.ofbV = new byte[cipher.getBlockSize()];
+ this.ofbOutV = new byte[cipher.getBlockSize()];
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param encrypting if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting, //ignored by this CTR mode
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ firstStep = true;
+ N3 = 0;
+ N4 = 0;
+
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ // prepend the supplied IV with zeros (per FIPS PUB 81)
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ for (int i = 0; i < IV.length - iv.length; i++)
+ {
+ IV[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ // if params is null we reuse the current working key.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(true, ivParam.getParameters());
+ }
+ }
+ else
+ {
+ reset();
+
+ // if params is null we reuse the current working key.
+ if (params != null)
+ {
+ cipher.init(true, params);
+ }
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/GCTR"
+ * and the block size in bits
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/GCTR";
+ }
+
+
+ /**
+ * return the block size we are operating at (in bytes).
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (firstStep)
+ {
+ firstStep = false;
+ cipher.processBlock(ofbV, 0, ofbOutV, 0);
+ N3 = bytesToint(ofbOutV, 0);
+ N4 = bytesToint(ofbOutV, 4);
+ }
+ N3 += C2;
+ N4 += C1;
+ intTobytes(N3, ofbV, 0);
+ intTobytes(N4, ofbV, 4);
+
+ cipher.processBlock(ofbV, 0, ofbOutV, 0);
+
+ //
+ // XOR the ofbV with the plaintext producing the cipher text (and
+ // the next input block).
+ //
+ for (int i = 0; i < blockSize; i++)
+ {
+ out[outOff + i] = (byte)(ofbOutV[i] ^ in[inOff + i]);
+ }
+
+ //
+ // change over the input block.
+ //
+ System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize);
+ System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize);
+
+ return blockSize;
+ }
+
+ /**
+ * reset the feedback vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ System.arraycopy(IV, 0, ofbV, 0, IV.length);
+
+ cipher.reset();
+ }
+
+ //array of bytes to type int
+ private int bytesToint(
+ byte[] in,
+ int inOff)
+ {
+ return ((in[inOff + 3] << 24) & 0xff000000) + ((in[inOff + 2] << 16) & 0xff0000) +
+ ((in[inOff + 1] << 8) & 0xff00) + (in[inOff] & 0xff);
+ }
+
+ //int to array of bytes
+ private void intTobytes(
+ int num,
+ byte[] out,
+ int outOff)
+ {
+ out[outOff + 3] = (byte)(num >>> 24);
+ out[outOff + 2] = (byte)(num >>> 16);
+ out[outOff + 1] = (byte)(num >>> 8);
+ out[outOff] = (byte)num;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/OFBBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/OFBBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/OFBBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/OFBBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,187 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * implements a Output-FeedBack (OFB) mode on top of a simple cipher.
+ */
+public class OFBBlockCipher
+ implements BlockCipher
+{
+ private byte[] IV;
+ private byte[] ofbV;
+ private byte[] ofbOutV;
+
+ private final int blockSize;
+ private final BlockCipher cipher;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ * @param blockSize the block size in bits (note: a multiple of 8)
+ */
+ public OFBBlockCipher(
+ BlockCipher cipher,
+ int blockSize)
+ {
+ this.cipher = cipher;
+ this.blockSize = blockSize / 8;
+
+ this.IV = new byte[cipher.getBlockSize()];
+ this.ofbV = new byte[cipher.getBlockSize()];
+ this.ofbOutV = new byte[cipher.getBlockSize()];
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param encrypting if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean encrypting, //ignored by this OFB mode
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ // prepend the supplied IV with zeros (per FIPS PUB 81)
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ for (int i = 0; i < IV.length - iv.length; i++)
+ {
+ IV[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ // if null it's an IV changed only.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(true, ivParam.getParameters());
+ }
+ }
+ else
+ {
+ reset();
+
+ // if it's null, key is to be reused.
+ if (params != null)
+ {
+ cipher.init(true, params);
+ }
+ }
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/OFB"
+ * and the block size in bits
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/OFB" + (blockSize * 8);
+ }
+
+
+ /**
+ * return the block size we are operating at (in bytes).
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return blockSize;
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ cipher.processBlock(ofbV, 0, ofbOutV, 0);
+
+ //
+ // XOR the ofbV with the plaintext producing the cipher text (and
+ // the next input block).
+ //
+ for (int i = 0; i < blockSize; i++)
+ {
+ out[outOff + i] = (byte)(ofbOutV[i] ^ in[inOff + i]);
+ }
+
+ //
+ // change over the input block.
+ //
+ System.arraycopy(ofbV, blockSize, ofbV, 0, ofbV.length - blockSize);
+ System.arraycopy(ofbOutV, 0, ofbV, ofbV.length - blockSize, blockSize);
+
+ return blockSize;
+ }
+
+ /**
+ * reset the feedback vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ System.arraycopy(IV, 0, ofbV, 0, IV.length);
+
+ cipher.reset();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/OpenPGPCFBBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,312 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+
+/**
+ * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode
+ * on top of a simple cipher. This class assumes the IV has been prepended
+ * to the data stream already, and just accomodates the reset after
+ * (blockSize + 2) bytes have been read.
+ *
+ * For further info see RFC 2440 .
+ */
+public class OpenPGPCFBBlockCipher
+ implements BlockCipher
+{
+ private byte[] IV;
+ private byte[] FR;
+ private byte[] FRE;
+
+ private BlockCipher cipher;
+
+ private int count;
+ private int blockSize;
+ private boolean forEncryption;
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ */
+ public OpenPGPCFBBlockCipher(
+ BlockCipher cipher)
+ {
+ this.cipher = cipher;
+
+ this.blockSize = cipher.getBlockSize();
+ this.IV = new byte[blockSize];
+ this.FR = new byte[blockSize];
+ this.FRE = new byte[blockSize];
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/PGPCFB"
+ * and the block size in bits.
+ */
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/OpenPGPCFB";
+ }
+
+ /**
+ * return the block size we are operating at.
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ return (forEncryption) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
+ }
+
+ /**
+ * reset the chaining vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ count = 0;
+
+ System.arraycopy(IV, 0, FR, 0, FR.length);
+
+ cipher.reset();
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ reset();
+
+ cipher.init(true, params);
+ }
+
+ /**
+ * Encrypt one byte of data according to CFB mode.
+ * @param data the byte to encrypt
+ * @param blockOff offset in the current block
+ * @return the encrypted byte
+ */
+ private byte encryptByte(byte data, int blockOff)
+ {
+ return (byte)(FRE[blockOff] ^ data);
+ }
+
+ /**
+ * Do the appropriate processing for CFB IV mode encryption.
+ *
+ * @param in the array containing the data to be encrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (count > blockSize)
+ {
+ FR[blockSize - 2] = out[outOff] = encryptByte(in[inOff], blockSize - 2);
+ FR[blockSize - 1] = out[outOff + 1] = encryptByte(in[inOff + 1], blockSize - 1);
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 2; n < blockSize; n++)
+ {
+ FR[n - 2] = out[outOff + n] = encryptByte(in[inOff + n], n - 2);
+ }
+ }
+ else if (count == 0)
+ {
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 0; n < blockSize; n++)
+ {
+ FR[n] = out[outOff + n] = encryptByte(in[inOff + n], n);
+ }
+
+ count += blockSize;
+ }
+ else if (count == blockSize)
+ {
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ out[outOff] = encryptByte(in[inOff], 0);
+ out[outOff + 1] = encryptByte(in[inOff + 1], 1);
+
+ //
+ // do reset
+ //
+ System.arraycopy(FR, 2, FR, 0, blockSize - 2);
+ System.arraycopy(out, outOff, FR, blockSize - 2, 2);
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 2; n < blockSize; n++)
+ {
+ FR[n - 2] = out[outOff + n] = encryptByte(in[inOff + n], n - 2);
+ }
+
+ count += blockSize;
+ }
+
+ return blockSize;
+ }
+
+ /**
+ * Do the appropriate processing for CFB IV mode decryption.
+ *
+ * @param in the array containing the data to be decrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (count > blockSize)
+ {
+ byte inVal = in[inOff];
+ FR[blockSize - 2] = inVal;
+ out[outOff] = encryptByte(inVal, blockSize - 2);
+
+ inVal = in[inOff + 1];
+ FR[blockSize - 1] = inVal;
+ out[outOff + 1] = encryptByte(inVal, blockSize - 1);
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 2; n < blockSize; n++)
+ {
+ inVal = in[inOff + n];
+ FR[n - 2] = inVal;
+ out[outOff + n] = encryptByte(inVal, n - 2);
+ }
+ }
+ else if (count == 0)
+ {
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 0; n < blockSize; n++)
+ {
+ FR[n] = in[inOff + n];
+ out[n] = encryptByte(in[inOff + n], n);
+ }
+
+ count += blockSize;
+ }
+ else if (count == blockSize)
+ {
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ byte inVal1 = in[inOff];
+ byte inVal2 = in[inOff + 1];
+ out[outOff ] = encryptByte(inVal1, 0);
+ out[outOff + 1] = encryptByte(inVal2, 1);
+
+ System.arraycopy(FR, 2, FR, 0, blockSize - 2);
+
+ FR[blockSize - 2] = inVal1;
+ FR[blockSize - 1] = inVal2;
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 2; n < blockSize; n++)
+ {
+ byte inVal = in[inOff + n];
+ FR[n - 2] = inVal;
+ out[outOff + n] = encryptByte(inVal, n - 2);
+ }
+
+ count += blockSize;
+ }
+
+ return blockSize;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,450 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode on top of a simple cipher. For further info see RFC 2440 .
+ */
+public class PGPCFBBlockCipher
+ implements BlockCipher
+{
+ private byte[] IV;
+ private byte[] FR;
+ private byte[] FRE;
+ private byte[] tmp;
+
+ private BlockCipher cipher;
+
+ private int count;
+ private int blockSize;
+ private boolean forEncryption;
+
+ private boolean inlineIv; // if false we don't need to prepend an IV
+
+ /**
+ * Basic constructor.
+ *
+ * @param cipher the block cipher to be used as the basis of the
+ * feedback mode.
+ * @param inlineIv if true this is for PGP CFB with a prepended iv.
+ */
+ public PGPCFBBlockCipher(
+ BlockCipher cipher,
+ boolean inlineIv)
+ {
+ this.cipher = cipher;
+ this.inlineIv = inlineIv;
+
+ this.blockSize = cipher.getBlockSize();
+ this.IV = new byte[blockSize];
+ this.FR = new byte[blockSize];
+ this.FRE = new byte[blockSize];
+ this.tmp = new byte[blockSize];
+ }
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+ /**
+ * return the algorithm name and mode.
+ *
+ * @return the name of the underlying algorithm followed by "/PGPCFB"
+ * and the block size in bits.
+ */
+ public String getAlgorithmName()
+ {
+ if (inlineIv)
+ {
+ return cipher.getAlgorithmName() + "/PGPCFBwithIV";
+ }
+ else
+ {
+ return cipher.getAlgorithmName() + "/PGPCFB";
+ }
+ }
+
+ /**
+ * return the block size we are operating at.
+ *
+ * @return the block size we are operating at (in bytes).
+ */
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+ /**
+ * Process one block of input from the array in and write it to
+ * the out array.
+ *
+ * @param in the array containing the input data.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the output data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ public int processBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (inlineIv)
+ {
+ return (forEncryption) ? encryptBlockWithIV(in, inOff, out, outOff) : decryptBlockWithIV(in, inOff, out, outOff);
+ }
+ else
+ {
+ return (forEncryption) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff);
+ }
+ }
+
+ /**
+ * reset the chaining vector back to the IV and reset the underlying
+ * cipher.
+ */
+ public void reset()
+ {
+ count = 0;
+
+ for (int i = 0; i != FR.length; i++)
+ {
+ if (inlineIv)
+ {
+ FR[i] = 0;
+ }
+ else
+ {
+ FR[i] = IV[i]; // if simple mode, key is IV (even if this is zero)
+ }
+ }
+
+ cipher.reset();
+ }
+
+ /**
+ * Initialise the cipher and, possibly, the initialisation vector (IV).
+ * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+ * An IV which is too short is handled in FIPS compliant fashion.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+
+ if (iv.length < IV.length)
+ {
+ // prepend the supplied IV with zeros (per FIPS PUB 81)
+ System.arraycopy(iv, 0, IV, IV.length - iv.length, iv.length);
+ for (int i = 0; i < IV.length - iv.length; i++)
+ {
+ IV[i] = 0;
+ }
+ }
+ else
+ {
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+ }
+
+ reset();
+
+ cipher.init(true, ivParam.getParameters());
+ }
+ else
+ {
+ reset();
+
+ cipher.init(true, params);
+ }
+ }
+
+ /**
+ * Encrypt one byte of data according to CFB mode.
+ * @param data the byte to encrypt
+ * @param blockOff where am i in the current block, determines when to resync the block
+ * @returns the encrypted byte
+ */
+ private byte encryptByte(byte data, int blockOff)
+ {
+ return (byte)(FRE[blockOff] ^ data);
+ }
+
+ /**
+ * Do the appropriate processing for CFB IV mode encryption.
+ *
+ * @param in the array containing the data to be encrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int encryptBlockWithIV(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (count == 0)
+ {
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 0; n < blockSize; n++)
+ {
+ out[outOff + n] = encryptByte(IV[n], n);
+ }
+
+ System.arraycopy(out, outOff, FR, 0, blockSize);
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ out[outOff + blockSize] = encryptByte(IV[blockSize - 2], 0);
+ out[outOff + blockSize + 1] = encryptByte(IV[blockSize - 1], 1);
+
+ System.arraycopy(out, outOff + 2, FR, 0, blockSize);
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 0; n < blockSize; n++)
+ {
+ out[outOff + blockSize + 2 + n] = encryptByte(in[inOff + n], n);
+ }
+
+ System.arraycopy(out, outOff + blockSize + 2, FR, 0, blockSize);
+
+ count += 2 * blockSize + 2;
+
+ return 2 * blockSize + 2;
+ }
+ else if (count >= blockSize + 2)
+ {
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 0; n < blockSize; n++)
+ {
+ out[outOff + n] = encryptByte(in[inOff + n], n);
+ }
+
+ System.arraycopy(out, outOff, FR, 0, blockSize);
+ }
+
+ return blockSize;
+ }
+
+ /**
+ * Do the appropriate processing for CFB IV mode decryption.
+ *
+ * @param in the array containing the data to be decrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int decryptBlockWithIV(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ if (count == 0)
+ {
+ for (int n = 0; n < blockSize; n++)
+ {
+ FR[n] = in[inOff + n];
+ }
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ count += blockSize;
+
+ return 0;
+ }
+ else if (count == blockSize)
+ {
+ // copy in buffer so that this mode works if in and out are the same
+ System.arraycopy(in, inOff, tmp, 0, blockSize);
+
+ System.arraycopy(FR, 2, FR, 0, blockSize - 2);
+
+ FR[blockSize - 2] = tmp[0];
+ FR[blockSize - 1] = tmp[1];
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 0; n < blockSize - 2; n++)
+ {
+ out[outOff + n] = encryptByte(tmp[n + 2], n);
+ }
+
+ System.arraycopy(tmp, 2, FR, 0, blockSize - 2);
+
+ count += 2;
+
+ return blockSize - 2;
+ }
+ else if (count >= blockSize + 2)
+ {
+ // copy in buffer so that this mode works if in and out are the same
+ System.arraycopy(in, inOff, tmp, 0, blockSize);
+
+ out[outOff + 0] = encryptByte(tmp[0], blockSize - 2);
+ out[outOff + 1] = encryptByte(tmp[1], blockSize - 1);
+
+ System.arraycopy(tmp, 0, FR, blockSize - 2, 2);
+
+ cipher.processBlock(FR, 0, FRE, 0);
+
+ for (int n = 0; n < blockSize - 2; n++)
+ {
+ out[outOff + n + 2] = encryptByte(tmp[n + 2], n);
+ }
+
+ System.arraycopy(tmp, 2, FR, 0, blockSize - 2);
+
+ }
+
+ return blockSize;
+ }
+
+ /**
+ * Do the appropriate processing for CFB mode encryption.
+ *
+ * @param in the array containing the data to be encrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int encryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ cipher.processBlock(FR, 0, FRE, 0);
+ for (int n = 0; n < blockSize; n++)
+ {
+ out[outOff + n] = encryptByte(in[inOff + n], n);
+ }
+
+ for (int n = 0; n < blockSize; n++)
+ {
+ FR[n] = out[outOff + n];
+ }
+
+ return blockSize;
+
+ }
+
+ /**
+ * Do the appropriate processing for CFB mode decryption.
+ *
+ * @param in the array containing the data to be decrypted.
+ * @param inOff offset into the in array the data starts at.
+ * @param out the array the encrypted data will be copied into.
+ * @param outOff the offset into the out array the output will start at.
+ * @exception DataLengthException if there isn't enough data in in, or
+ * space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ * @return the number of bytes processed and produced.
+ */
+ private int decryptBlock(
+ byte[] in,
+ int inOff,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if ((inOff + blockSize) > in.length)
+ {
+ throw new DataLengthException("input buffer too short");
+ }
+
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ cipher.processBlock(FR, 0, FRE, 0);
+ for (int n = 0; n < blockSize; n++)
+ {
+ out[outOff + n] = encryptByte(in[inOff + n], n);
+ }
+
+ for (int n = 0; n < blockSize; n++)
+ {
+ FR[n] = in[inOff + n];
+ }
+
+ return blockSize;
+
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/PaddedBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/PaddedBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/PaddedBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/PaddedBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,253 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.BufferedBlockCipher;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A wrapper class that allows block ciphers to be used to process data in
+ * a piecemeal fashion with PKCS5/PKCS7 padding. The PaddedBlockCipher
+ * outputs a block only when the buffer is full and more data is being added,
+ * or on a doFinal (unless the current block in the buffer is a pad block).
+ * The padding mechanism used is the one outlined in PKCS5/PKCS7.
+ *
+ * @deprecated use pdftk.org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher instead.
+ */
+public class PaddedBlockCipher
+ extends BufferedBlockCipher
+{
+ /**
+ * Create a buffered block cipher with, or without, padding.
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ */
+ public PaddedBlockCipher(
+ BlockCipher cipher)
+ {
+ this.cipher = cipher;
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ /**
+ * return the size of the output buffer required for an update plus a
+ * doFinal with an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update and doFinal
+ * with len bytes of input.
+ */
+ public int getOutputSize(
+ int len)
+ {
+ int total = len + bufOff;
+ int leftOver = total % buf.length;
+
+ if (leftOver == 0)
+ {
+ if (forEncryption)
+ {
+ return total + buf.length;
+ }
+
+ return total;
+ }
+
+ return total - leftOver + buf.length;
+ }
+
+ /**
+ * return the size of the output buffer required for an update
+ * an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update
+ * with len bytes of input.
+ */
+ public int getUpdateOutputSize(
+ int len)
+ {
+ int total = len + bufOff;
+ int leftOver = total % buf.length;
+
+ if (leftOver == 0)
+ {
+ return total - buf.length;
+ }
+
+ return total - leftOver;
+ }
+
+ /**
+ * process a single byte, producing an output block if neccessary.
+ *
+ * @param in the input byte.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ int resultLen = 0;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+
+ return resultLen;
+ }
+
+ /**
+ * process an array of bytes, producing output if necessary.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset at which the input data starts.
+ * @param len the number of bytes to be copied out of the input array.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = getBlockSize();
+ int length = getUpdateOutputSize(len);
+
+ if (length > 0)
+ {
+ if ((outOff + length) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > buf.length)
+ {
+ resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+
+ return resultLen;
+ }
+
+ /**
+ * Process the last block in the buffer. If the buffer is currently
+ * full and padding needs to be added a call to doFinal will produce
+ * 2 * getBlockSize() bytes.
+ *
+ * @param out the array the block currently being held is copied into.
+ * @param outOff the offset at which the copying starts.
+ * @exception DataLengthException if there is insufficient space in out for
+ * the output or we are decrypting and the input is not block size aligned.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception InvalidCipherTextException if padding is expected and not found.
+ */
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException, InvalidCipherTextException
+ {
+ int blockSize = cipher.getBlockSize();
+ int resultLen = 0;
+
+ if (forEncryption)
+ {
+ if (bufOff == blockSize)
+ {
+ if ((outOff + 2 * blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ bufOff = 0;
+ }
+
+ //
+ // add PKCS7 padding
+ //
+ byte code = (byte)(blockSize - bufOff);
+
+ while (bufOff < blockSize)
+ {
+ buf[bufOff] = code;
+ bufOff++;
+ }
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
+ }
+ else
+ {
+ if (bufOff == blockSize)
+ {
+ resultLen = cipher.processBlock(buf, 0, buf, 0);
+ bufOff = 0;
+ }
+ else
+ {
+ throw new DataLengthException("last block incomplete in decryption");
+ }
+
+ //
+ // remove PKCS7 padding
+ //
+ int count = buf[blockSize - 1] & 0xff;
+
+ if ((count < 0) || (count > blockSize))
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ resultLen -= count;
+
+ System.arraycopy(buf, 0, out, outOff, resultLen);
+ }
+
+ reset();
+
+ return resultLen;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/SICBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/SICBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/SICBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/SICBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,113 @@
+package pdftk.org.bouncycastle.crypto.modes;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+
+/**
+ * Implements the Segmented Integer Counter (SIC) mode on top of a simple
+ * block cipher. This mode is also known as CTR mode.
+ */
+public class SICBlockCipher
+ implements BlockCipher
+{
+ private final BlockCipher cipher;
+ private final int blockSize;
+
+ private byte[] IV;
+ private byte[] counter;
+ private byte[] counterOut;
+
+
+ /**
+ * Basic constructor.
+ *
+ * @param c the block cipher to be used.
+ */
+ public SICBlockCipher(BlockCipher c)
+ {
+ this.cipher = c;
+ this.blockSize = cipher.getBlockSize();
+ this.IV = new byte[blockSize];
+ this.counter = new byte[blockSize];
+ this.counterOut = new byte[blockSize];
+ }
+
+
+ /**
+ * return the underlying block cipher that we are wrapping.
+ *
+ * @return the underlying block cipher that we are wrapping.
+ */
+ public BlockCipher getUnderlyingCipher()
+ {
+ return cipher;
+ }
+
+
+ public void init(
+ boolean forEncryption, //ignored by this CTR mode
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ if (params instanceof ParametersWithIV)
+ {
+ ParametersWithIV ivParam = (ParametersWithIV)params;
+ byte[] iv = ivParam.getIV();
+ System.arraycopy(iv, 0, IV, 0, IV.length);
+
+ reset();
+
+ // if null it's an IV changed only.
+ if (ivParam.getParameters() != null)
+ {
+ cipher.init(true, ivParam.getParameters());
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("SIC mode requires ParametersWithIV");
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return cipher.getAlgorithmName() + "/SIC";
+ }
+
+ public int getBlockSize()
+ {
+ return cipher.getBlockSize();
+ }
+
+
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ cipher.processBlock(counter, 0, counterOut, 0);
+
+ //
+ // XOR the counterOut with the plaintext producing the cipher text
+ //
+ for (int i = 0; i < counterOut.length; i++)
+ {
+ out[outOff + i] = (byte)(counterOut[i] ^ in[inOff + i]);
+ }
+
+ // increment counter by 1.
+ for (int i = counter.length - 1; i >= 0 && ++counter[i] == 0; i--)
+ {
+ ; // do nothing - pre-increment and test for 0 in counter does the job.
+ }
+
+ return counter.length;
+ }
+
+
+ public void reset()
+ {
+ System.arraycopy(IV, 0, counter, 0, counter.length);
+ cipher.reset();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,36 @@
+package pdftk.org.bouncycastle.crypto.modes.gcm;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class BasicGCMExponentiator implements GCMExponentiator
+{
+ private byte[] x;
+
+ public void init(byte[] x)
+ {
+ this.x = Arrays.clone(x);
+ }
+
+ public void exponentiateX(long pow, byte[] output)
+ {
+ // Initial value is little-endian 1
+ byte[] y = GCMUtil.oneAsBytes();
+
+ if (pow > 0)
+ {
+ byte[] powX = Arrays.clone(x);
+ do
+ {
+ if ((pow & 1L) != 0)
+ {
+ GCMUtil.multiply(y, powX);
+ }
+ GCMUtil.multiply(powX, powX);
+ pow >>>= 1;
+ }
+ while (pow > 0);
+ }
+
+ System.arraycopy(y, 0, output, 0, 16);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/BasicGCMMultiplier.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/BasicGCMMultiplier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/BasicGCMMultiplier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/BasicGCMMultiplier.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.crypto.modes.gcm;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class BasicGCMMultiplier implements GCMMultiplier
+{
+ private byte[] H;
+
+ public void init(byte[] H)
+ {
+ this.H = Arrays.clone(H);
+ }
+
+ public void multiplyH(byte[] x)
+ {
+ GCMUtil.multiply(x, H);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/GCMExponentiator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/GCMExponentiator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/GCMExponentiator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/GCMExponentiator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,7 @@
+package pdftk.org.bouncycastle.crypto.modes.gcm;
+
+public interface GCMExponentiator
+{
+ void init(byte[] x);
+ void exponentiateX(long pow, byte[] output);
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/GCMMultiplier.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/GCMMultiplier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/GCMMultiplier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/GCMMultiplier.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,7 @@
+package pdftk.org.bouncycastle.crypto.modes.gcm;
+
+public interface GCMMultiplier
+{
+ void init(byte[] H);
+ void multiplyH(byte[] x);
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/GCMUtil.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/GCMUtil.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/GCMUtil.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,260 @@
+package pdftk.org.bouncycastle.crypto.modes.gcm;
+
+import pdftk.org.bouncycastle.crypto.util.Pack;
+import pdftk.org.bouncycastle.util.Arrays;
+
+abstract class GCMUtil
+{
+ static byte[] oneAsBytes()
+ {
+ byte[] tmp = new byte[16];
+ tmp[0] = (byte)0x80;
+ return tmp;
+ }
+
+ static int[] oneAsInts()
+ {
+ int[] tmp = new int[4];
+ tmp[0] = 0x80000000;
+ return tmp;
+ }
+
+ static byte[] asBytes(int[] ns)
+ {
+ byte[] output = new byte[16];
+ Pack.intToBigEndian(ns, output, 0);
+ return output;
+ }
+
+ static int[] asInts(byte[] bs)
+ {
+ int[] output = new int[4];
+ Pack.bigEndianToInt(bs, 0, output);
+ return output;
+ }
+
+ static void asInts(byte[] bs, int[] output)
+ {
+ Pack.bigEndianToInt(bs, 0, output);
+ }
+
+ static void multiply(byte[] block, byte[] val)
+ {
+ byte[] tmp = Arrays.clone(block);
+ byte[] c = new byte[16];
+
+ for (int i = 0; i < 16; ++i)
+ {
+ byte bits = val[i];
+ for (int j = 7; j >= 0; --j)
+ {
+ if ((bits & (1 << j)) != 0)
+ {
+ xor(c, tmp);
+ }
+
+ boolean lsb = (tmp[15] & 1) != 0;
+ shiftRight(tmp);
+ if (lsb)
+ {
+ // R = new byte[]{ 0xe1, ... };
+// GCMUtil.xor(v, R);
+ tmp[0] ^= (byte)0xe1;
+ }
+ }
+ }
+
+ System.arraycopy(c, 0, block, 0, 16);
+ }
+
+ // P is the value with only bit i=1 set
+ static void multiplyP(int[] x)
+ {
+ boolean lsb = (x[3] & 1) != 0;
+ shiftRight(x);
+ if (lsb)
+ {
+ // R = new int[]{ 0xe1000000, 0, 0, 0 };
+// xor(v, R);
+ x[0] ^= 0xe1000000;
+ }
+ }
+
+ static void multiplyP(int[] x, int[] output)
+ {
+ boolean lsb = (x[3] & 1) != 0;
+ shiftRight(x, output);
+ if (lsb)
+ {
+ output[0] ^= 0xe1000000;
+ }
+ }
+
+ // P is the value with only bit i=1 set
+ static void multiplyP8(int[] x)
+ {
+// for (int i = 8; i != 0; --i)
+// {
+// multiplyP(x);
+// }
+
+ int lsw = x[3];
+ shiftRightN(x, 8);
+ for (int i = 7; i >= 0; --i)
+ {
+ if ((lsw & (1 << i)) != 0)
+ {
+ x[0] ^= (0xe1000000 >>> (7 - i));
+ }
+ }
+ }
+
+ static void multiplyP8(int[] x, int[] output)
+ {
+ int lsw = x[3];
+ shiftRightN(x, 8, output);
+ for (int i = 7; i >= 0; --i)
+ {
+ if ((lsw & (1 << i)) != 0)
+ {
+ output[0] ^= (0xe1000000 >>> (7 - i));
+ }
+ }
+ }
+
+ static void shiftRight(byte[] block)
+ {
+ int i = 0;
+ int bit = 0;
+ for (;;)
+ {
+ int b = block[i] & 0xff;
+ block[i] = (byte) ((b >>> 1) | bit);
+ if (++i == 16)
+ {
+ break;
+ }
+ bit = (b & 1) << 7;
+ }
+ }
+
+ static void shiftRight(byte[] block, byte[] output)
+ {
+ int i = 0;
+ int bit = 0;
+ for (;;)
+ {
+ int b = block[i] & 0xff;
+ output[i] = (byte) ((b >>> 1) | bit);
+ if (++i == 16)
+ {
+ break;
+ }
+ bit = (b & 1) << 7;
+ }
+ }
+
+ static void shiftRight(int[] block)
+ {
+ int i = 0;
+ int bit = 0;
+ for (;;)
+ {
+ int b = block[i];
+ block[i] = (b >>> 1) | bit;
+ if (++i == 4)
+ {
+ break;
+ }
+ bit = b << 31;
+ }
+ }
+
+ static void shiftRight(int[] block, int[] output)
+ {
+ int i = 0;
+ int bit = 0;
+ for (;;)
+ {
+ int b = block[i];
+ output[i] = (b >>> 1) | bit;
+ if (++i == 4)
+ {
+ break;
+ }
+ bit = b << 31;
+ }
+ }
+
+ static void shiftRightN(int[] block, int n)
+ {
+ int i = 0;
+ int bits = 0;
+ for (;;)
+ {
+ int b = block[i];
+ block[i] = (b >>> n) | bits;
+ if (++i == 4)
+ {
+ break;
+ }
+ bits = b << (32 - n);
+ }
+ }
+
+ static void shiftRightN(int[] block, int n, int[] output)
+ {
+ int i = 0;
+ int bits = 0;
+ for (;;)
+ {
+ int b = block[i];
+ output[i] = (b >>> n) | bits;
+ if (++i == 4)
+ {
+ break;
+ }
+ bits = b << (32 - n);
+ }
+ }
+
+ static void xor(byte[] block, byte[] val)
+ {
+ for (int i = 15; i >= 0; --i)
+ {
+ block[i] ^= val[i];
+ }
+ }
+
+ static void xor(byte[] block, byte[] val, int off, int len)
+ {
+ while (len-- > 0)
+ {
+ block[len] ^= val[off + len];
+ }
+ }
+
+ static void xor(byte[] block, byte[] val, byte[] output)
+ {
+ for (int i = 15; i >= 0; --i)
+ {
+ output[i] = (byte)(block[i] ^ val[i]);
+ }
+ }
+
+ static void xor(int[] block, int[] val)
+ {
+ for (int i = 3; i >= 0; --i)
+ {
+ block[i] ^= val[i];
+ }
+ }
+
+ static void xor(int[] block, int[] val, int[] output)
+ {
+ for (int i = 3; i >= 0; --i)
+ {
+ output[i] = block[i] ^ val[i];
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,57 @@
+package pdftk.org.bouncycastle.crypto.modes.gcm;
+
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class Tables1kGCMExponentiator implements GCMExponentiator
+{
+ // A lookup table of the power-of-two powers of 'x'
+ // - lookupPowX2[i] = x^(2^i)
+ private Vector lookupPowX2;
+
+ public void init(byte[] x)
+ {
+ if (lookupPowX2 != null && Arrays.areEqual(x, (byte[])lookupPowX2.elementAt(0)))
+ {
+ return;
+ }
+
+ lookupPowX2 = new Vector(8);
+ lookupPowX2.addElement(Arrays.clone(x));
+ }
+
+ public void exponentiateX(long pow, byte[] output)
+ {
+ byte[] y = GCMUtil.oneAsBytes();
+ int bit = 0;
+ while (pow > 0)
+ {
+ if ((pow & 1L) != 0)
+ {
+ ensureAvailable(bit);
+ GCMUtil.multiply(y, (byte[])lookupPowX2.elementAt(bit));
+ }
+ ++bit;
+ pow >>>= 1;
+ }
+
+ System.arraycopy(y, 0, output, 0, 16);
+ }
+
+ private void ensureAvailable(int bit)
+ {
+ int count = lookupPowX2.size();
+ if (count <= bit)
+ {
+ byte[] tmp = (byte[])lookupPowX2.elementAt(count - 1);
+ do
+ {
+ tmp = Arrays.clone(tmp);
+ GCMUtil.multiply(tmp, tmp);
+ lookupPowX2.addElement(tmp);
+ }
+ while (++count <= bit);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/Tables64kGCMMultiplier.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,73 @@
+package pdftk.org.bouncycastle.crypto.modes.gcm;
+
+import pdftk.org.bouncycastle.crypto.util.Pack;
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class Tables64kGCMMultiplier implements GCMMultiplier
+{
+ private byte[] H;
+ private int[][][] M;
+
+ public void init(byte[] H)
+ {
+ if (M == null)
+ {
+ M = new int[16][256][4];
+ }
+ else if (Arrays.areEqual(this.H, H))
+ {
+ return;
+ }
+
+ this.H = Arrays.clone(H);
+
+ // M[0][0] is ZEROES;
+ GCMUtil.asInts(H, M[0][128]);
+
+ for (int j = 64; j >= 1; j >>= 1)
+ {
+ GCMUtil.multiplyP(M[0][j + j], M[0][j]);
+ }
+
+ int i = 0;
+ for (;;)
+ {
+ for (int j = 2; j < 256; j += j)
+ {
+ for (int k = 1; k < j; ++k)
+ {
+ GCMUtil.xor(M[i][j], M[i][k], M[i][j + k]);
+ }
+ }
+
+ if (++i == 16)
+ {
+ return;
+ }
+
+ // M[i][0] is ZEROES;
+ for (int j = 128; j > 0; j >>= 1)
+ {
+ GCMUtil.multiplyP8(M[i - 1][j], M[i][j]);
+ }
+ }
+ }
+
+ public void multiplyH(byte[] x)
+ {
+// assert x.Length == 16;
+
+ int[] z = new int[4];
+ for (int i = 15; i >= 0; --i)
+ {
+// GCMUtil.xor(z, M[i][x[i] & 0xff]);
+ int[] m = M[i][x[i] & 0xff];
+ z[0] ^= m[0];
+ z[1] ^= m[1];
+ z[2] ^= m[2];
+ z[3] ^= m[3];
+ }
+
+ Pack.intToBigEndian(z, x, 0);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/gcm/Tables8kGCMMultiplier.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,90 @@
+package pdftk.org.bouncycastle.crypto.modes.gcm;
+
+import pdftk.org.bouncycastle.crypto.util.Pack;
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class Tables8kGCMMultiplier implements GCMMultiplier
+{
+ private byte[] H;
+ private int[][][] M;
+
+ public void init(byte[] H)
+ {
+ if (M == null)
+ {
+ M = new int[32][16][4];
+ }
+ else if (Arrays.areEqual(this.H, H))
+ {
+ return;
+ }
+
+ this.H = Arrays.clone(H);
+
+ // M[0][0] is ZEROES;
+ // M[1][0] is ZEROES;
+ GCMUtil.asInts(H, M[1][8]);
+
+ for (int j = 4; j >= 1; j >>= 1)
+ {
+ GCMUtil.multiplyP(M[1][j + j], M[1][j]);
+ }
+
+ GCMUtil.multiplyP(M[1][1], M[0][8]);
+
+ for (int j = 4; j >= 1; j >>= 1)
+ {
+ GCMUtil.multiplyP(M[0][j + j], M[0][j]);
+ }
+
+ int i = 0;
+ for (;;)
+ {
+ for (int j = 2; j < 16; j += j)
+ {
+ for (int k = 1; k < j; ++k)
+ {
+ GCMUtil.xor(M[i][j], M[i][k], M[i][j + k]);
+ }
+ }
+
+ if (++i == 32)
+ {
+ return;
+ }
+
+ if (i > 1)
+ {
+ // M[i][0] is ZEROES;
+ for(int j = 8; j > 0; j >>= 1)
+ {
+ GCMUtil.multiplyP8(M[i - 2][j], M[i][j]);
+ }
+ }
+ }
+ }
+
+ public void multiplyH(byte[] x)
+ {
+// assert x.Length == 16;
+
+ int[] z = new int[4];
+ for (int i = 15; i >= 0; --i)
+ {
+// GCMUtil.xor(z, M[i + i][x[i] & 0x0f]);
+ int[] m = M[i + i][x[i] & 0x0f];
+ z[0] ^= m[0];
+ z[1] ^= m[1];
+ z[2] ^= m[2];
+ z[3] ^= m[3];
+// GCMUtil.xor(z, M[i + i + 1][(x[i] & 0xf0) >>> 4]);
+ m = M[i + i + 1][(x[i] & 0xf0) >>> 4];
+ z[0] ^= m[0];
+ z[1] ^= m[1];
+ z[2] ^= m[2];
+ z[3] ^= m[3];
+ }
+
+ Pack.intToBigEndian(z, x, 0);
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/modes/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/modes/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Modes for symmetric ciphers.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Base classes for the lightweight API.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/BlockCipherPadding.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/BlockCipherPadding.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/BlockCipherPadding.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/BlockCipherPadding.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * Block cipher padders are expected to conform to this interface
+ */
+public interface BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random the source of randomness for the padding, if required.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException;
+
+ /**
+ * Return the name of the algorithm the cipher implements.
+ *
+ * @return the name of the algorithm the cipher implements.
+ */
+ public String getPaddingName();
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ *
+ * Note: this assumes that the last block of plain text is always
+ * passed to it inside in. i.e. if inOff is zero, indicating the
+ * entire block is to be overwritten with padding the value of in
+ * should be the same as the last block of plain text. The reason
+ * for this is that some modes such as "trailing bit compliment"
+ * base the padding on the last byte of plain text.
+ *
+ */
+ public int addPadding(byte[] in, int inOff);
+
+ /**
+ * return the number of pad bytes present in the block.
+ * @exception InvalidCipherTextException if the padding is badly formed
+ * or invalid.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/ISO10126d2Padding.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,79 @@
+package pdftk.org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds ISO10126-2 padding to a block.
+ */
+public class ISO10126d2Padding
+ implements BlockCipherPadding
+{
+ SecureRandom random;
+
+ /**
+ * Initialise the padder.
+ *
+ * @param random a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ if (random != null)
+ {
+ this.random = random;
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ }
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "ISO10126-2";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ byte code = (byte)(in.length - inOff);
+
+ while (inOff < (in.length - 1))
+ {
+ in[inOff] = (byte)random.nextInt();
+ inOff++;
+ }
+
+ in[inOff] = code;
+
+ return code;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in[in.length - 1] & 0xff;
+
+ if (count > in.length)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ return count;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/ISO7816d4Padding.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/ISO7816d4Padding.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/ISO7816d4Padding.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/ISO7816d4Padding.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,77 @@
+package pdftk.org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds the padding according to the scheme referenced in
+ * ISO 7814-4 - scheme 2 from ISO 9797-1. The first byte is 0x80, rest is 0x00
+ */
+public class ISO7816d4Padding
+ implements BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "ISO7816-4";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ int added = (in.length - inOff);
+
+ in [inOff]= (byte) 0x80;
+ inOff ++;
+
+ while (inOff < in.length)
+ {
+ in[inOff] = (byte) 0;
+ inOff++;
+ }
+
+ return added;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in.length - 1;
+
+ while (count > 0 && in[count] == 0)
+ {
+ count--;
+ }
+
+ if (in[count] != (byte)0x80)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ return in.length - count;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/PKCS7Padding.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/PKCS7Padding.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/PKCS7Padding.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/PKCS7Padding.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,76 @@
+package pdftk.org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds PKCS7/PKCS5 padding to a block.
+ */
+public class PKCS7Padding
+ implements BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "PKCS7";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ byte code = (byte)(in.length - inOff);
+
+ while (inOff < in.length)
+ {
+ in[inOff] = code;
+ inOff++;
+ }
+
+ return code;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in[in.length - 1] & 0xff;
+
+ if (count > in.length || count == 0)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ for (int i = 1; i <= count; i++)
+ {
+ if (in[in.length - i] != count)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+ }
+
+ return count;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,299 @@
+package pdftk.org.bouncycastle.crypto.paddings;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.BufferedBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.OutputLengthException;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+
+/**
+ * A wrapper class that allows block ciphers to be used to process data in
+ * a piecemeal fashion with padding. The PaddedBufferedBlockCipher
+ * outputs a block only when the buffer is full and more data is being added,
+ * or on a doFinal (unless the current block in the buffer is a pad block).
+ * The default padding mechanism used is the one outlined in PKCS5/PKCS7.
+ */
+public class PaddedBufferedBlockCipher
+ extends BufferedBlockCipher
+{
+ BlockCipherPadding padding;
+
+ /**
+ * Create a buffered block cipher with the desired padding.
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ * @param padding the padding type.
+ */
+ public PaddedBufferedBlockCipher(
+ BlockCipher cipher,
+ BlockCipherPadding padding)
+ {
+ this.cipher = cipher;
+ this.padding = padding;
+
+ buf = new byte[cipher.getBlockSize()];
+ bufOff = 0;
+ }
+
+ /**
+ * Create a buffered block cipher PKCS7 padding
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ */
+ public PaddedBufferedBlockCipher(
+ BlockCipher cipher)
+ {
+ this(cipher, new PKCS7Padding());
+ }
+
+ /**
+ * initialise the cipher.
+ *
+ * @param forEncryption if true the cipher is initialised for
+ * encryption, if false for decryption.
+ * @param params the key and other data required by the cipher.
+ * @exception IllegalArgumentException if the params argument is
+ * inappropriate.
+ */
+ public void init(
+ boolean forEncryption,
+ CipherParameters params)
+ throws IllegalArgumentException
+ {
+ this.forEncryption = forEncryption;
+
+ reset();
+
+ if (params instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)params;
+
+ padding.init(p.getRandom());
+
+ cipher.init(forEncryption, p.getParameters());
+ }
+ else
+ {
+ padding.init(null);
+
+ cipher.init(forEncryption, params);
+ }
+ }
+
+ /**
+ * return the minimum size of the output buffer required for an update
+ * plus a doFinal with an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update and doFinal
+ * with len bytes of input.
+ */
+ public int getOutputSize(
+ int len)
+ {
+ int total = len + bufOff;
+ int leftOver = total % buf.length;
+
+ if (leftOver == 0)
+ {
+ if (forEncryption)
+ {
+ return total + buf.length;
+ }
+
+ return total;
+ }
+
+ return total - leftOver + buf.length;
+ }
+
+ /**
+ * return the size of the output buffer required for an update
+ * an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update
+ * with len bytes of input.
+ */
+ public int getUpdateOutputSize(
+ int len)
+ {
+ int total = len + bufOff;
+ int leftOver = total % buf.length;
+
+ if (leftOver == 0)
+ {
+ return total - buf.length;
+ }
+
+ return total - leftOver;
+ }
+
+ /**
+ * process a single byte, producing an output block if neccessary.
+ *
+ * @param in the input byte.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ int resultLen = 0;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = in;
+
+ return resultLen;
+ }
+
+ /**
+ * process an array of bytes, producing output if necessary.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset at which the input data starts.
+ * @param len the number of bytes to be copied out of the input array.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = getBlockSize();
+ int length = getUpdateOutputSize(len);
+
+ if (length > 0)
+ {
+ if ((outOff + length) > out.length)
+ {
+ throw new OutputLengthException("output buffer too short");
+ }
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff);
+
+ bufOff = 0;
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > buf.length)
+ {
+ resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+
+ return resultLen;
+ }
+
+ /**
+ * Process the last block in the buffer. If the buffer is currently
+ * full and padding needs to be added a call to doFinal will produce
+ * 2 * getBlockSize() bytes.
+ *
+ * @param out the array the block currently being held is copied into.
+ * @param outOff the offset at which the copying starts.
+ * @return the number of output bytes copied to out.
+ * @exception DataLengthException if there is insufficient space in out for
+ * the output or we are decrypting and the input is not block size aligned.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception InvalidCipherTextException if padding is expected and not found.
+ */
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException, InvalidCipherTextException
+ {
+ int blockSize = cipher.getBlockSize();
+ int resultLen = 0;
+
+ if (forEncryption)
+ {
+ if (bufOff == blockSize)
+ {
+ if ((outOff + 2 * blockSize) > out.length)
+ {
+ reset();
+
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ bufOff = 0;
+ }
+
+ padding.addPadding(buf, bufOff);
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
+
+ reset();
+ }
+ else
+ {
+ if (bufOff == blockSize)
+ {
+ resultLen = cipher.processBlock(buf, 0, buf, 0);
+ bufOff = 0;
+ }
+ else
+ {
+ reset();
+
+ throw new DataLengthException("last block incomplete in decryption");
+ }
+
+ try
+ {
+ resultLen -= padding.padCount(buf);
+
+ System.arraycopy(buf, 0, out, outOff, resultLen);
+ }
+ finally
+ {
+ reset();
+ }
+ }
+
+ return resultLen;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/TBCPadding.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/TBCPadding.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/TBCPadding.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/TBCPadding.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,89 @@
+package pdftk.org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds Trailing-Bit-Compliment padding to a block.
+ *
+ * This padding pads the block out with the compliment of the last bit
+ * of the plain text.
+ *
+ */
+public class TBCPadding
+ implements BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "TBC";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ *
+ * Note: this assumes that the last block of plain text is always
+ * passed to it inside in. i.e. if inOff is zero, indicating the
+ * entire block is to be overwritten with padding the value of in
+ * should be the same as the last block of plain text.
+ *
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ int count = in.length - inOff;
+ byte code;
+
+ if (inOff > 0)
+ {
+ code = (byte)((in[inOff - 1] & 0x01) == 0 ? 0xff : 0x00);
+ }
+ else
+ {
+ code = (byte)((in[in.length - 1] & 0x01) == 0 ? 0xff : 0x00);
+ }
+
+ while (inOff < in.length)
+ {
+ in[inOff] = code;
+ inOff++;
+ }
+
+ return count;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ byte code = in[in.length - 1];
+
+ int index = in.length - 1;
+ while (index > 0 && in[index - 1] == code)
+ {
+ index--;
+ }
+
+ return in.length - index;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/X923Padding.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/X923Padding.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/X923Padding.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/X923Padding.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,80 @@
+package pdftk.org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds X9.23 padding to a block - if a SecureRandom is
+ * passed in random padding is assumed, otherwise padding with zeros is used.
+ */
+public class X923Padding
+ implements BlockCipherPadding
+{
+ SecureRandom random = null;
+
+ /**
+ * Initialise the padder.
+ *
+ * @param random a SecureRandom if one is available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ this.random = random;
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "X9.23";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ byte code = (byte)(in.length - inOff);
+
+ while (inOff < in.length - 1)
+ {
+ if (random == null)
+ {
+ in[inOff] = 0;
+ }
+ else
+ {
+ in[inOff] = (byte)random.nextInt();
+ }
+ inOff++;
+ }
+
+ in[inOff] = code;
+
+ return code;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in[in.length - 1] & 0xff;
+
+ if (count > in.length)
+ {
+ throw new InvalidCipherTextException("pad block corrupted");
+ }
+
+ return count;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/ZeroBytePadding.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/ZeroBytePadding.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/ZeroBytePadding.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/ZeroBytePadding.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,73 @@
+package pdftk.org.bouncycastle.crypto.paddings;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A padder that adds NULL byte padding to a block.
+ */
+public class ZeroBytePadding
+ implements BlockCipherPadding
+{
+ /**
+ * Initialise the padder.
+ *
+ * @param random - a SecureRandom if available.
+ */
+ public void init(SecureRandom random)
+ throws IllegalArgumentException
+ {
+ // nothing to do.
+ }
+
+ /**
+ * Return the name of the algorithm the padder implements.
+ *
+ * @return the name of the algorithm the padder implements.
+ */
+ public String getPaddingName()
+ {
+ return "ZeroByte";
+ }
+
+ /**
+ * add the pad bytes to the passed in block, returning the
+ * number of bytes added.
+ */
+ public int addPadding(
+ byte[] in,
+ int inOff)
+ {
+ int added = (in.length - inOff);
+
+ while (inOff < in.length)
+ {
+ in[inOff] = (byte) 0;
+ inOff++;
+ }
+
+ return added;
+ }
+
+ /**
+ * return the number of pad bytes present in the block.
+ */
+ public int padCount(byte[] in)
+ throws InvalidCipherTextException
+ {
+ int count = in.length;
+
+ while (count > 0)
+ {
+ if (in[count - 1] != 0)
+ {
+ break;
+ }
+
+ count--;
+ }
+
+ return in.length - count;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/paddings/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/paddings/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Paddings for symmetric ciphers.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/AEADParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/AEADParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/AEADParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/AEADParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,60 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+public class AEADParameters
+ implements CipherParameters
+{
+ private byte[] associatedText;
+ private byte[] nonce;
+ private KeyParameter key;
+ private int macSize;
+
+ /**
+ * Base constructor.
+ *
+ * @param key key to be used by underlying cipher
+ * @param macSize macSize in bits
+ * @param nonce nonce to be used
+ */
+ public AEADParameters(KeyParameter key, int macSize, byte[] nonce)
+ {
+ this(key, macSize, nonce, null);
+ }
+
+ /**
+ * Base constructor.
+ *
+ * @param key key to be used by underlying cipher
+ * @param macSize macSize in bits
+ * @param nonce nonce to be used
+ * @param associatedText initial associated text, if any
+ */
+ public AEADParameters(KeyParameter key, int macSize, byte[] nonce, byte[] associatedText)
+ {
+ this.key = key;
+ this.nonce = nonce;
+ this.macSize = macSize;
+ this.associatedText = associatedText;
+ }
+
+ public KeyParameter getKey()
+ {
+ return key;
+ }
+
+ public int getMacSize()
+ {
+ return macSize;
+ }
+
+ public byte[] getAssociatedText()
+ {
+ return associatedText;
+ }
+
+ public byte[] getNonce()
+ {
+ return nonce;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/AsymmetricKeyParameter.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/AsymmetricKeyParameter.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/AsymmetricKeyParameter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/AsymmetricKeyParameter.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,20 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+public class AsymmetricKeyParameter
+ implements CipherParameters
+{
+ boolean privateKey;
+
+ public AsymmetricKeyParameter(
+ boolean privateKey)
+ {
+ this.privateKey = privateKey;
+ }
+
+ public boolean isPrivate()
+ {
+ return privateKey;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/CCMParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/CCMParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/CCMParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/CCMParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,21 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+/**
+ * @deprecated use AEADParameters
+ */
+public class CCMParameters
+ extends AEADParameters
+{
+ /**
+ * Base constructor.
+ *
+ * @param key key to be used by underlying cipher
+ * @param macSize macSize in bits
+ * @param nonce nonce to be used
+ * @param associatedText associated text, if any
+ */
+ public CCMParameters(KeyParameter key, int macSize, byte[] nonce, byte[] associatedText)
+ {
+ super(key, macSize, nonce, associatedText);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DESParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DESParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DESParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DESParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,107 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+public class DESParameters
+ extends KeyParameter
+{
+ public DESParameters(
+ byte[] key)
+ {
+ super(key);
+
+ if (isWeakKey(key, 0))
+ {
+ throw new IllegalArgumentException("attempt to create weak DES key");
+ }
+ }
+
+ /*
+ * DES Key length in bytes.
+ */
+ static public final int DES_KEY_LENGTH = 8;
+
+ /*
+ * Table of weak and semi-weak keys taken from Schneier pp281
+ */
+ static private final int N_DES_WEAK_KEYS = 16;
+
+ static private byte[] DES_weak_keys =
+ {
+ /* weak keys */
+ (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
+ (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
+ (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
+ (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
+
+ /* semi-weak keys */
+ (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
+ (byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
+ (byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
+ (byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
+ (byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
+ (byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
+ (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
+ (byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
+ (byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
+ (byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
+ (byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
+ (byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
+ };
+
+ /**
+ * DES has 16 weak keys. This method will check
+ * if the given DES key material is weak or semi-weak.
+ * Key material that is too short is regarded as weak.
+ *
+ * See "Applied
+ * Cryptography" by Bruce Schneier for more information.
+ *
+ * @return true if the given DES key material is weak or semi-weak,
+ * false otherwise.
+ */
+ public static boolean isWeakKey(
+ byte[] key,
+ int offset)
+ {
+ if (key.length - offset < DES_KEY_LENGTH)
+ {
+ throw new IllegalArgumentException("key material too short.");
+ }
+
+ nextkey: for (int i = 0; i < N_DES_WEAK_KEYS; i++)
+ {
+ for (int j = 0; j < DES_KEY_LENGTH; j++)
+ {
+ if (key[j + offset] != DES_weak_keys[i * DES_KEY_LENGTH + j])
+ {
+ continue nextkey;
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * DES Keys use the LSB as the odd parity bit. This can
+ * be used to check for corrupt keys.
+ *
+ * @param bytes the byte array to set the parity on.
+ */
+ public static void setOddParity(
+ byte[] bytes)
+ {
+ for (int i = 0; i < bytes.length; i++)
+ {
+ int b = bytes[i];
+ bytes[i] = (byte)((b & 0xfe) |
+ ((((b >> 1) ^
+ (b >> 2) ^
+ (b >> 3) ^
+ (b >> 4) ^
+ (b >> 5) ^
+ (b >> 6) ^
+ (b >> 7)) ^ 0x01) & 0x01));
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DESedeParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DESedeParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DESedeParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DESedeParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,57 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+public class DESedeParameters
+ extends DESParameters
+{
+ /*
+ * DES-EDE Key length in bytes.
+ */
+ static public final int DES_EDE_KEY_LENGTH = 24;
+
+ public DESedeParameters(
+ byte[] key)
+ {
+ super(key);
+
+ if (isWeakKey(key, 0, key.length))
+ {
+ throw new IllegalArgumentException("attempt to create weak DESede key");
+ }
+ }
+
+ /**
+ * return true if the passed in key is a DES-EDE weak key.
+ *
+ * @param key bytes making up the key
+ * @param offset offset into the byte array the key starts at
+ * @param length number of bytes making up the key
+ */
+ public static boolean isWeakKey(
+ byte[] key,
+ int offset,
+ int length)
+ {
+ for (int i = offset; i < length; i += DES_KEY_LENGTH)
+ {
+ if (DESParameters.isWeakKey(key, i))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * return true if the passed in key is a DES-EDE weak key.
+ *
+ * @param key bytes making up the key
+ * @param offset offset into the byte array the key starts at
+ */
+ public static boolean isWeakKey(
+ byte[] key,
+ int offset)
+ {
+ return isWeakKey(key, offset, key.length - offset);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DHKeyGenerationParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DHKeyGenerationParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DHKeyGenerationParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DHKeyGenerationParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,30 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+
+public class DHKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private DHParameters params;
+
+ public DHKeyGenerationParameters(
+ SecureRandom random,
+ DHParameters params)
+ {
+ super(random, getStrength(params));
+
+ this.params = params;
+ }
+
+ public DHParameters getParameters()
+ {
+ return params;
+ }
+
+ static int getStrength(DHParameters params)
+ {
+ return params.getL() != 0 ? params.getL() : params.getP().bitLength();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DHKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DHKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DHKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DHKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,54 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+
+public class DHKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private DHParameters params;
+
+ protected DHKeyParameters(
+ boolean isPrivate,
+ DHParameters params)
+ {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public DHParameters getParameters()
+ {
+ return params;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DHKeyParameters))
+ {
+ return false;
+ }
+
+ DHKeyParameters dhKey = (DHKeyParameters)obj;
+
+ if (params == null)
+ {
+ return dhKey.getParameters() == null;
+ }
+ else
+ {
+ return params.equals(dhKey.getParameters());
+ }
+ }
+
+ public int hashCode()
+ {
+ int code = isPrivate() ? 0 : 1;
+
+ if (params != null)
+ {
+ code ^= params.hashCode();
+ }
+
+ return code;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DHParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DHParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DHParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DHParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,189 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+public class DHParameters
+ implements CipherParameters
+{
+ private static final int DEFAULT_MINIMUM_LENGTH = 160;
+
+ // not final due to compiler bug in "simpler" JDKs
+ private BigInteger g;
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger j;
+ private int m;
+ private int l;
+ private DHValidationParameters validation;
+
+ private static int getDefaultMParam(
+ int lParam)
+ {
+ if (lParam == 0)
+ {
+ return DEFAULT_MINIMUM_LENGTH;
+ }
+
+ return lParam < DEFAULT_MINIMUM_LENGTH ? lParam : DEFAULT_MINIMUM_LENGTH;
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g)
+ {
+ this(p, g, null, 0);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q)
+ {
+ this(p, g, q, 0);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q,
+ int l)
+ {
+ this(p, g, q, getDefaultMParam(l), l, null, null);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q,
+ int m,
+ int l)
+ {
+ this(p, g, q, m, l, null, null);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q,
+ BigInteger j,
+ DHValidationParameters validation)
+ {
+ this(p, g, q, DEFAULT_MINIMUM_LENGTH, 0, j, validation);
+ }
+
+ public DHParameters(
+ BigInteger p,
+ BigInteger g,
+ BigInteger q,
+ int m,
+ int l,
+ BigInteger j,
+ DHValidationParameters validation)
+ {
+ if (l != 0)
+ {
+ BigInteger bigL = BigInteger.valueOf(2L ^ (l - 1));
+ if (bigL.compareTo(p) == 1)
+ {
+ throw new IllegalArgumentException("when l value specified, it must satisfy 2^(l-1) <= p");
+ }
+ if (l < m)
+ {
+ throw new IllegalArgumentException("when l value specified, it may not be less than m value");
+ }
+ }
+
+ this.g = g;
+ this.p = p;
+ this.q = q;
+ this.m = m;
+ this.l = l;
+ this.j = j;
+ this.validation = validation;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ /**
+ * Return the subgroup factor J.
+ *
+ * @return subgroup factor
+ */
+ public BigInteger getJ()
+ {
+ return j;
+ }
+
+ /**
+ * Return the minimum length of the private value.
+ *
+ * @return the minimum length of the private value in bits.
+ */
+ public int getM()
+ {
+ return m;
+ }
+
+ /**
+ * Return the private value length in bits - if set, zero otherwise
+ *
+ * @return the private value length in bits, zero otherwise.
+ */
+ public int getL()
+ {
+ return l;
+ }
+
+ public DHValidationParameters getValidationParameters()
+ {
+ return validation;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DHParameters))
+ {
+ return false;
+ }
+
+ DHParameters pm = (DHParameters)obj;
+
+ if (this.getQ() != null)
+ {
+ if (!this.getQ().equals(pm.getQ()))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (pm.getQ() != null)
+ {
+ return false;
+ }
+ }
+
+ return pm.getP().equals(p) && pm.getG().equals(g);
+ }
+
+ public int hashCode()
+ {
+ return getP().hashCode() ^ getG().hashCode() ^ (getQ() != null ? getQ().hashCode() : 0);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DHPrivateKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,41 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class DHPrivateKeyParameters
+ extends DHKeyParameters
+{
+ private BigInteger x;
+
+ public DHPrivateKeyParameters(
+ BigInteger x,
+ DHParameters params)
+ {
+ super(true, params);
+
+ this.x = x;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+
+ public int hashCode()
+ {
+ return x.hashCode() ^ super.hashCode();
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DHPrivateKeyParameters))
+ {
+ return false;
+ }
+
+ DHPrivateKeyParameters other = (DHPrivateKeyParameters)obj;
+
+ return other.getX().equals(this.x) && super.equals(obj);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DHPublicKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DHPublicKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DHPublicKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DHPublicKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,41 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class DHPublicKeyParameters
+ extends DHKeyParameters
+{
+ private BigInteger y;
+
+ public DHPublicKeyParameters(
+ BigInteger y,
+ DHParameters params)
+ {
+ super(false, params);
+
+ this.y = y;
+ }
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+
+ public int hashCode()
+ {
+ return y.hashCode() ^ super.hashCode();
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DHPublicKeyParameters))
+ {
+ return false;
+ }
+
+ DHPublicKeyParameters other = (DHPublicKeyParameters)obj;
+
+ return other.getY().equals(y) && super.equals(obj);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DHValidationParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DHValidationParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DHValidationParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DHValidationParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,50 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class DHValidationParameters
+{
+ private byte[] seed;
+ private int counter;
+
+ public DHValidationParameters(
+ byte[] seed,
+ int counter)
+ {
+ this.seed = seed;
+ this.counter = counter;
+ }
+
+ public int getCounter()
+ {
+ return counter;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof DHValidationParameters))
+ {
+ return false;
+ }
+
+ DHValidationParameters other = (DHValidationParameters)o;
+
+ if (other.counter != this.counter)
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(this.seed, other.seed);
+ }
+
+ public int hashCode()
+ {
+ return counter ^ Arrays.hashCode(seed);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DSAKeyGenerationParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DSAKeyGenerationParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DSAKeyGenerationParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DSAKeyGenerationParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,25 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+
+public class DSAKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private DSAParameters params;
+
+ public DSAKeyGenerationParameters(
+ SecureRandom random,
+ DSAParameters params)
+ {
+ super(random, params.getP().bitLength() - 1);
+
+ this.params = params;
+ }
+
+ public DSAParameters getParameters()
+ {
+ return params;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DSAKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DSAKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DSAKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DSAKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,21 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+public class DSAKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private DSAParameters params;
+
+ public DSAKeyParameters(
+ boolean isPrivate,
+ DSAParameters params)
+ {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public DSAParameters getParameters()
+ {
+ return params;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DSAParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DSAParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DSAParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DSAParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,74 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+public class DSAParameters
+ implements CipherParameters
+{
+ private BigInteger g;
+ private BigInteger q;
+ private BigInteger p;
+ private DSAValidationParameters validation;
+
+ public DSAParameters(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g)
+ {
+ this.g = g;
+ this.p = p;
+ this.q = q;
+ }
+
+ public DSAParameters(
+ BigInteger p,
+ BigInteger q,
+ BigInteger g,
+ DSAValidationParameters params)
+ {
+ this.g = g;
+ this.p = p;
+ this.q = q;
+ this.validation = params;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ public DSAValidationParameters getValidationParameters()
+ {
+ return validation;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof DSAParameters))
+ {
+ return false;
+ }
+
+ DSAParameters pm = (DSAParameters)obj;
+
+ return (pm.getP().equals(p) && pm.getQ().equals(q) && pm.getG().equals(g));
+ }
+
+ public int hashCode()
+ {
+ return getP().hashCode() ^ getQ().hashCode() ^ getG().hashCode();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DSAPrivateKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class DSAPrivateKeyParameters
+ extends DSAKeyParameters
+{
+ private BigInteger x;
+
+ public DSAPrivateKeyParameters(
+ BigInteger x,
+ DSAParameters params)
+ {
+ super(true, params);
+
+ this.x = x;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DSAPublicKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class DSAPublicKeyParameters
+ extends DSAKeyParameters
+{
+ private BigInteger y;
+
+ public DSAPublicKeyParameters(
+ BigInteger y,
+ DSAParameters params)
+ {
+ super(false, params);
+
+ this.y = y;
+ }
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DSAValidationParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DSAValidationParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/DSAValidationParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/DSAValidationParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,50 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class DSAValidationParameters
+{
+ private byte[] seed;
+ private int counter;
+
+ public DSAValidationParameters(
+ byte[] seed,
+ int counter)
+ {
+ this.seed = seed;
+ this.counter = counter;
+ }
+
+ public int getCounter()
+ {
+ return counter;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+
+ public int hashCode()
+ {
+ return counter ^ Arrays.hashCode(seed);
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof DSAValidationParameters))
+ {
+ return false;
+ }
+
+ DSAValidationParameters other = (DSAValidationParameters)o;
+
+ if (other.counter != this.counter)
+ {
+ return false;
+ }
+
+ return Arrays.areEqual(this.seed, other.seed);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ECDomainParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ECDomainParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ECDomainParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ECDomainParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,81 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.math.ec.ECConstants;
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+public class ECDomainParameters
+ implements ECConstants
+{
+ ECCurve curve;
+ byte[] seed;
+ ECPoint G;
+ BigInteger n;
+ BigInteger h;
+
+ public ECDomainParameters(
+ ECCurve curve,
+ ECPoint G,
+ BigInteger n)
+ {
+ this.curve = curve;
+ this.G = G;
+ this.n = n;
+ this.h = ONE;
+ this.seed = null;
+ }
+
+ public ECDomainParameters(
+ ECCurve curve,
+ ECPoint G,
+ BigInteger n,
+ BigInteger h)
+ {
+ this.curve = curve;
+ this.G = G;
+ this.n = n;
+ this.h = h;
+ this.seed = null;
+ }
+
+ public ECDomainParameters(
+ ECCurve curve,
+ ECPoint G,
+ BigInteger n,
+ BigInteger h,
+ byte[] seed)
+ {
+ this.curve = curve;
+ this.G = G;
+ this.n = n;
+ this.h = h;
+ this.seed = seed;
+ }
+
+ public ECCurve getCurve()
+ {
+ return curve;
+ }
+
+ public ECPoint getG()
+ {
+ return G;
+ }
+
+ public BigInteger getN()
+ {
+ return n;
+ }
+
+ public BigInteger getH()
+ {
+ return h;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ECKeyGenerationParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,25 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+
+public class ECKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private ECDomainParameters domainParams;
+
+ public ECKeyGenerationParameters(
+ ECDomainParameters domainParams,
+ SecureRandom random)
+ {
+ super(random, domainParams.getN().bitLength());
+
+ this.domainParams = domainParams;
+ }
+
+ public ECDomainParameters getDomainParameters()
+ {
+ return domainParams;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ECKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ECKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ECKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ECKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,21 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+public class ECKeyParameters
+ extends AsymmetricKeyParameter
+{
+ ECDomainParameters params;
+
+ protected ECKeyParameters(
+ boolean isPrivate,
+ ECDomainParameters params)
+ {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public ECDomainParameters getParameters()
+ {
+ return params;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ECPrivateKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,22 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class ECPrivateKeyParameters
+ extends ECKeyParameters
+{
+ BigInteger d;
+
+ public ECPrivateKeyParameters(
+ BigInteger d,
+ ECDomainParameters params)
+ {
+ super(true, params);
+ this.d = d;
+ }
+
+ public BigInteger getD()
+ {
+ return d;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ECPublicKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ECPublicKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ECPublicKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ECPublicKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,22 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+public class ECPublicKeyParameters
+ extends ECKeyParameters
+{
+ ECPoint Q;
+
+ public ECPublicKeyParameters(
+ ECPoint Q,
+ ECDomainParameters params)
+ {
+ super(false, params);
+ this.Q = Q;
+ }
+
+ public ECPoint getQ()
+ {
+ return Q;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ElGamalKeyGenerationParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,30 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+
+public class ElGamalKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private ElGamalParameters params;
+
+ public ElGamalKeyGenerationParameters(
+ SecureRandom random,
+ ElGamalParameters params)
+ {
+ super(random, getStrength(params));
+
+ this.params = params;
+ }
+
+ public ElGamalParameters getParameters()
+ {
+ return params;
+ }
+
+ static int getStrength(ElGamalParameters params)
+ {
+ return params.getL() != 0 ? params.getL() : params.getP().bitLength();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ElGamalKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ElGamalKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ElGamalKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ElGamalKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,47 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+
+public class ElGamalKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private ElGamalParameters params;
+
+ protected ElGamalKeyParameters(
+ boolean isPrivate,
+ ElGamalParameters params)
+ {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public ElGamalParameters getParameters()
+ {
+ return params;
+ }
+
+ public int hashCode()
+ {
+ return (params != null) ? params.hashCode() : 0;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof ElGamalKeyParameters))
+ {
+ return false;
+ }
+
+ ElGamalKeyParameters dhKey = (ElGamalKeyParameters)obj;
+
+ if (params == null)
+ {
+ return dhKey.getParameters() == null;
+ }
+ else
+ {
+ return params.equals(dhKey.getParameters());
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ElGamalParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ElGamalParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ElGamalParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ElGamalParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,69 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+public class ElGamalParameters
+ implements CipherParameters
+{
+ private BigInteger g;
+ private BigInteger p;
+ private int l;
+
+ public ElGamalParameters(
+ BigInteger p,
+ BigInteger g)
+ {
+ this(p, g, 0);
+ }
+
+ public ElGamalParameters(
+ BigInteger p,
+ BigInteger g,
+ int l)
+ {
+ this.g = g;
+ this.p = p;
+ this.l = l;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ /**
+ * return the generator - g
+ */
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ /**
+ * return private value limit - l
+ */
+ public int getL()
+ {
+ return l;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof ElGamalParameters))
+ {
+ return false;
+ }
+
+ ElGamalParameters pm = (ElGamalParameters)obj;
+
+ return pm.getP().equals(p) && pm.getG().equals(g) && pm.getL() == l;
+ }
+
+ public int hashCode()
+ {
+ return (getP().hashCode() ^ getG().hashCode()) + l;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ElGamalPrivateKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ElGamalPrivateKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ElGamalPrivateKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ElGamalPrivateKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,46 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class ElGamalPrivateKeyParameters
+ extends ElGamalKeyParameters
+{
+ private BigInteger x;
+
+ public ElGamalPrivateKeyParameters(
+ BigInteger x,
+ ElGamalParameters params)
+ {
+ super(true, params);
+
+ this.x = x;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof ElGamalPrivateKeyParameters))
+ {
+ return false;
+ }
+
+ ElGamalPrivateKeyParameters pKey = (ElGamalPrivateKeyParameters)obj;
+
+ if (!pKey.getX().equals(x))
+ {
+ return false;
+ }
+
+ return super.equals(obj);
+ }
+
+ public int hashCode()
+ {
+ return getX().hashCode();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ElGamalPublicKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ElGamalPublicKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ElGamalPublicKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ElGamalPublicKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,41 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class ElGamalPublicKeyParameters
+ extends ElGamalKeyParameters
+{
+ private BigInteger y;
+
+ public ElGamalPublicKeyParameters(
+ BigInteger y,
+ ElGamalParameters params)
+ {
+ super(false, params);
+
+ this.y = y;
+ }
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+
+ public int hashCode()
+ {
+ return y.hashCode() ^ super.hashCode();
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof ElGamalPublicKeyParameters))
+ {
+ return false;
+ }
+
+ ElGamalPublicKeyParameters other = (ElGamalPublicKeyParameters)obj;
+
+ return other.getY().equals(y) && super.equals(obj);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/GOST3410KeyGenerationParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/GOST3410KeyGenerationParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/GOST3410KeyGenerationParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/GOST3410KeyGenerationParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,25 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+
+import java.security.SecureRandom;
+
+public class GOST3410KeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private GOST3410Parameters params;
+
+ public GOST3410KeyGenerationParameters(
+ SecureRandom random,
+ GOST3410Parameters params)
+ {
+ super(random, params.getP().bitLength() - 1);
+
+ this.params = params;
+ }
+
+ public GOST3410Parameters getParameters()
+ {
+ return params;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/GOST3410KeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/GOST3410KeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/GOST3410KeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/GOST3410KeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,21 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+public class GOST3410KeyParameters
+ extends AsymmetricKeyParameter
+{
+ private GOST3410Parameters params;
+
+ public GOST3410KeyParameters(
+ boolean isPrivate,
+ GOST3410Parameters params)
+ {
+ super(isPrivate);
+
+ this.params = params;
+ }
+
+ public GOST3410Parameters getParameters()
+ {
+ return params;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/GOST3410Parameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/GOST3410Parameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/GOST3410Parameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/GOST3410Parameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,74 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+import java.math.BigInteger;
+
+public class GOST3410Parameters
+ implements CipherParameters
+{
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger a;
+ private GOST3410ValidationParameters validation;
+
+ public GOST3410Parameters(
+ BigInteger p,
+ BigInteger q,
+ BigInteger a)
+ {
+ this.p = p;
+ this.q = q;
+ this.a = a;
+ }
+
+ public GOST3410Parameters(
+ BigInteger p,
+ BigInteger q,
+ BigInteger a,
+ GOST3410ValidationParameters params)
+ {
+ this.a = a;
+ this.p = p;
+ this.q = q;
+ this.validation = params;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getA()
+ {
+ return a;
+ }
+
+ public GOST3410ValidationParameters getValidationParameters()
+ {
+ return validation;
+ }
+
+ public int hashCode()
+ {
+ return p.hashCode() ^ q.hashCode() ^ a.hashCode();
+ }
+
+ public boolean equals(
+ Object obj)
+ {
+ if (!(obj instanceof GOST3410Parameters))
+ {
+ return false;
+ }
+
+ GOST3410Parameters pm = (GOST3410Parameters)obj;
+
+ return (pm.getP().equals(p) && pm.getQ().equals(q) && pm.getA().equals(a));
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/GOST3410PrivateKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/GOST3410PrivateKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/GOST3410PrivateKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/GOST3410PrivateKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class GOST3410PrivateKeyParameters
+ extends GOST3410KeyParameters
+{
+ private BigInteger x;
+
+ public GOST3410PrivateKeyParameters(
+ BigInteger x,
+ GOST3410Parameters params)
+ {
+ super(true, params);
+
+ this.x = x;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/GOST3410PublicKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/GOST3410PublicKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/GOST3410PublicKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/GOST3410PublicKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class GOST3410PublicKeyParameters
+ extends GOST3410KeyParameters
+{
+ private BigInteger y;
+
+ public GOST3410PublicKeyParameters(
+ BigInteger y,
+ GOST3410Parameters params)
+ {
+ super(false, params);
+
+ this.y = y;
+ }
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/GOST3410ValidationParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/GOST3410ValidationParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/GOST3410ValidationParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/GOST3410ValidationParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,84 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+public class GOST3410ValidationParameters
+{
+ private int x0;
+ private int c;
+ private long x0L;
+ private long cL;
+
+
+ public GOST3410ValidationParameters(
+ int x0,
+ int c)
+ {
+ this.x0 = x0;
+ this.c = c;
+ }
+
+ public GOST3410ValidationParameters(
+ long x0L,
+ long cL)
+ {
+ this.x0L = x0L;
+ this.cL = cL;
+ }
+
+ public int getC()
+ {
+ return c;
+ }
+
+ public int getX0()
+ {
+ return x0;
+ }
+
+ public long getCL()
+ {
+ return cL;
+ }
+
+ public long getX0L()
+ {
+ return x0L;
+ }
+
+ public boolean equals(
+ Object o)
+ {
+ if (!(o instanceof GOST3410ValidationParameters))
+ {
+ return false;
+ }
+
+ GOST3410ValidationParameters other = (GOST3410ValidationParameters)o;
+
+ if (other.c != this.c)
+ {
+ return false;
+ }
+
+ if (other.x0 != this.x0)
+ {
+ return false;
+ }
+
+ if (other.cL != this.cL)
+ {
+ return false;
+ }
+
+ if (other.x0L != this.x0L)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public int hashCode()
+ {
+ return x0 ^ c ^ (int) x0L ^ (int)(x0L >> 32) ^ (int) cL ^ (int)(cL >> 32);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/HKDFParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/HKDFParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/HKDFParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/HKDFParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,123 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.DerivationParameters;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * Parameter class for the HKDFBytesGenerator class.
+ */
+public class HKDFParameters
+ implements DerivationParameters
+{
+ private final byte[] ikm;
+ private final boolean skipExpand;
+ private final byte[] salt;
+ private final byte[] info;
+
+ private HKDFParameters(final byte[] ikm, final boolean skip,
+ final byte[] salt, final byte[] info)
+ {
+ if (ikm == null)
+ {
+ throw new IllegalArgumentException(
+ "IKM (input keying material) should not be null");
+ }
+
+ this.ikm = Arrays.clone(ikm);
+
+ this.skipExpand = skip;
+
+ if (salt == null || salt.length == 0)
+ {
+ this.salt = null;
+ }
+ else
+ {
+ this.salt = Arrays.clone(salt);
+ }
+
+ if (info == null)
+ {
+ this.info = new byte[0];
+ }
+ else
+ {
+ this.info = Arrays.clone(info);
+ }
+ }
+
+ /**
+ * Generates parameters for HKDF, specifying both the optional salt and
+ * optional info. Step 1: Extract won't be skipped.
+ *
+ * @param ikm the input keying material or seed
+ * @param salt the salt to use, may be null for a salt for hashLen zeros
+ * @param info the info to use, may be null for an info field of zero bytes
+ */
+ public HKDFParameters(final byte[] ikm, final byte[] salt, final byte[] info)
+ {
+ this(ikm, false, salt, info);
+ }
+
+ /**
+ * Factory method that makes the HKDF skip the extract part of the key
+ * derivation function.
+ *
+ * @param ikm the input keying material or seed, directly used for step 2:
+ * Expand
+ * @param info the info to use, may be null for an info field of zero bytes
+ * @return HKDFParameters that makes the implementation skip step 1
+ */
+ public static HKDFParameters skipExtractParameters(final byte[] ikm,
+ final byte[] info)
+ {
+
+ return new HKDFParameters(ikm, true, null, info);
+ }
+
+ public static HKDFParameters defaultParameters(final byte[] ikm)
+ {
+ return new HKDFParameters(ikm, false, null, null);
+ }
+
+ /**
+ * Returns the input keying material or seed.
+ *
+ * @return the keying material
+ */
+ public byte[] getIKM()
+ {
+ return Arrays.clone(ikm);
+ }
+
+ /**
+ * Returns if step 1: extract has to be skipped or not
+ *
+ * @return true for skipping, false for no skipping of step 1
+ */
+ public boolean skipExtract()
+ {
+ return skipExpand;
+ }
+
+ /**
+ * Returns the salt, or null if the salt should be generated as a byte array
+ * of HashLen zeros.
+ *
+ * @return the salt, or null
+ */
+ public byte[] getSalt()
+ {
+ return Arrays.clone(salt);
+ }
+
+ /**
+ * Returns the info field, which may be empty (null is converted to empty).
+ *
+ * @return the info field, never null
+ */
+ public byte[] getInfo()
+ {
+ return Arrays.clone(info);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/IESParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/IESParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/IESParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/IESParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,44 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+/**
+ * parameters for using an integrated cipher in stream mode.
+ */
+public class IESParameters
+ implements CipherParameters
+{
+ private byte[] derivation;
+ private byte[] encoding;
+ private int macKeySize;
+
+ /**
+ * @param derivation the derivation parameter for the KDF function.
+ * @param encoding the encoding parameter for the KDF function.
+ * @param macKeySize the size of the MAC key (in bits).
+ */
+ public IESParameters(
+ byte[] derivation,
+ byte[] encoding,
+ int macKeySize)
+ {
+ this.derivation = derivation;
+ this.encoding = encoding;
+ this.macKeySize = macKeySize;
+ }
+
+ public byte[] getDerivationV()
+ {
+ return derivation;
+ }
+
+ public byte[] getEncodingV()
+ {
+ return encoding;
+ }
+
+ public int getMacKeySize()
+ {
+ return macKeySize;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/IESWithCipherParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/IESWithCipherParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/IESWithCipherParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/IESWithCipherParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,30 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+
+public class IESWithCipherParameters
+ extends IESParameters
+{
+ private int cipherKeySize;
+
+ /**
+ * @param derivation the derivation parameter for the KDF function.
+ * @param encoding the encoding parameter for the KDF function.
+ * @param macKeySize the size of the MAC key (in bits).
+ * @param cipherKeySize the size of the associated Cipher key (in bits).
+ */
+ public IESWithCipherParameters(
+ byte[] derivation,
+ byte[] encoding,
+ int macKeySize,
+ int cipherKeySize)
+ {
+ super(derivation, encoding, macKeySize);
+
+ this.cipherKeySize = cipherKeySize;
+ }
+
+ public int getCipherKeySize()
+ {
+ return cipherKeySize;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ISO18033KDFParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ISO18033KDFParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ISO18033KDFParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ISO18033KDFParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.DerivationParameters;
+
+/**
+ * parameters for Key derivation functions for ISO-18033
+ */
+public class ISO18033KDFParameters
+ implements DerivationParameters
+{
+ byte[] seed;
+
+ public ISO18033KDFParameters(
+ byte[] seed)
+ {
+ this.seed = seed;
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/KDFParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/KDFParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/KDFParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/KDFParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,31 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.DerivationParameters;
+
+/**
+ * parameters for Key derivation functions for IEEE P1363a
+ */
+public class KDFParameters
+ implements DerivationParameters
+{
+ byte[] iv;
+ byte[] shared;
+
+ public KDFParameters(
+ byte[] shared,
+ byte[] iv)
+ {
+ this.shared = shared;
+ this.iv = iv;
+ }
+
+ public byte[] getSharedSecret()
+ {
+ return shared;
+ }
+
+ public byte[] getIV()
+ {
+ return iv;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/KeyParameter.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/KeyParameter.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/KeyParameter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/KeyParameter.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,30 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+public class KeyParameter
+ implements CipherParameters
+{
+ private byte[] key;
+
+ public KeyParameter(
+ byte[] key)
+ {
+ this(key, 0, key.length);
+ }
+
+ public KeyParameter(
+ byte[] key,
+ int keyOff,
+ int keyLen)
+ {
+ this.key = new byte[keyLen];
+
+ System.arraycopy(key, keyOff, this.key, 0, keyLen);
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/MGFParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/MGFParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/MGFParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/MGFParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,32 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.DerivationParameters;
+
+/**
+ * parameters for mask derivation functions.
+ */
+public class MGFParameters
+ implements DerivationParameters
+{
+ byte[] seed;
+
+ public MGFParameters(
+ byte[] seed)
+ {
+ this(seed, 0, seed.length);
+ }
+
+ public MGFParameters(
+ byte[] seed,
+ int off,
+ int len)
+ {
+ this.seed = new byte[len];
+ System.arraycopy(seed, off, this.seed, 0, len);
+ }
+
+ public byte[] getSeed()
+ {
+ return seed;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/MQVPrivateParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/MQVPrivateParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/MQVPrivateParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/MQVPrivateParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,43 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+public class MQVPrivateParameters
+ implements CipherParameters
+{
+ private ECPrivateKeyParameters staticPrivateKey;
+ private ECPrivateKeyParameters ephemeralPrivateKey;
+ private ECPublicKeyParameters ephemeralPublicKey;
+
+ public MQVPrivateParameters(
+ ECPrivateKeyParameters staticPrivateKey,
+ ECPrivateKeyParameters ephemeralPrivateKey)
+ {
+ this(staticPrivateKey, ephemeralPrivateKey, null);
+ }
+
+ public MQVPrivateParameters(
+ ECPrivateKeyParameters staticPrivateKey,
+ ECPrivateKeyParameters ephemeralPrivateKey,
+ ECPublicKeyParameters ephemeralPublicKey)
+ {
+ this.staticPrivateKey = staticPrivateKey;
+ this.ephemeralPrivateKey = ephemeralPrivateKey;
+ this.ephemeralPublicKey = ephemeralPublicKey;
+ }
+
+ public ECPrivateKeyParameters getStaticPrivateKey()
+ {
+ return staticPrivateKey;
+ }
+
+ public ECPrivateKeyParameters getEphemeralPrivateKey()
+ {
+ return ephemeralPrivateKey;
+ }
+
+ public ECPublicKeyParameters getEphemeralPublicKey()
+ {
+ return ephemeralPublicKey;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/MQVPublicParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/MQVPublicParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/MQVPublicParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/MQVPublicParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,28 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+public class MQVPublicParameters
+ implements CipherParameters
+{
+ private ECPublicKeyParameters staticPublicKey;
+ private ECPublicKeyParameters ephemeralPublicKey;
+
+ public MQVPublicParameters(
+ ECPublicKeyParameters staticPublicKey,
+ ECPublicKeyParameters ephemeralPublicKey)
+ {
+ this.staticPublicKey = staticPublicKey;
+ this.ephemeralPublicKey = ephemeralPublicKey;
+ }
+
+ public ECPublicKeyParameters getStaticPublicKey()
+ {
+ return staticPublicKey;
+ }
+
+ public ECPublicKeyParameters getEphemeralPublicKey()
+ {
+ return ephemeralPublicKey;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/NaccacheSternKeyGenerationParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/NaccacheSternKeyGenerationParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/NaccacheSternKeyGenerationParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/NaccacheSternKeyGenerationParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,97 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+
+/**
+ * Parameters for NaccacheStern public private key generation. For details on
+ * this cipher, please see
+ *
+ * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+ */
+public class NaccacheSternKeyGenerationParameters extends KeyGenerationParameters
+{
+
+ // private BigInteger publicExponent;
+ private int certainty;
+
+ private int cntSmallPrimes;
+
+ private boolean debug = false;
+
+ /**
+ * Parameters for generating a NaccacheStern KeyPair.
+ *
+ * @param random
+ * The source of randomness
+ * @param strength
+ * The desired strength of the Key in Bits
+ * @param certainty
+ * the probability that the generated primes are not really prime
+ * as integer: 2^(-certainty) is then the probability
+ * @param cntSmallPrimes
+ * How many small key factors are desired
+ */
+ public NaccacheSternKeyGenerationParameters(SecureRandom random, int strength, int certainty, int cntSmallPrimes)
+ {
+ this(random, strength, certainty, cntSmallPrimes, false);
+ }
+
+ /**
+ * Parameters for a NaccacheStern KeyPair.
+ *
+ * @param random
+ * The source of randomness
+ * @param strength
+ * The desired strength of the Key in Bits
+ * @param certainty
+ * the probability that the generated primes are not really prime
+ * as integer: 2^(-certainty) is then the probability
+ * @param cntSmallPrimes
+ * How many small key factors are desired
+ * @param debug
+ * Turn debugging on or off (reveals secret information, use with
+ * caution)
+ */
+ public NaccacheSternKeyGenerationParameters(SecureRandom random,
+ int strength, int certainty, int cntSmallPrimes, boolean debug)
+ {
+ super(random, strength);
+
+ this.certainty = certainty;
+ if (cntSmallPrimes % 2 == 1)
+ {
+ throw new IllegalArgumentException("cntSmallPrimes must be a multiple of 2");
+ }
+ if (cntSmallPrimes < 30)
+ {
+ throw new IllegalArgumentException("cntSmallPrimes must be >= 30 for security reasons");
+ }
+ this.cntSmallPrimes = cntSmallPrimes;
+
+ this.debug = debug;
+ }
+
+ /**
+ * @return Returns the certainty.
+ */
+ public int getCertainty()
+ {
+ return certainty;
+ }
+
+ /**
+ * @return Returns the cntSmallPrimes.
+ */
+ public int getCntSmallPrimes()
+ {
+ return cntSmallPrimes;
+ }
+
+ public boolean isDebug()
+ {
+ return debug;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/NaccacheSternKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/NaccacheSternKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/NaccacheSternKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/NaccacheSternKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,53 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+/**
+ * Public key parameters for NaccacheStern cipher. For details on this cipher,
+ * please see
+ *
+ * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+ */
+public class NaccacheSternKeyParameters extends AsymmetricKeyParameter
+{
+
+ private BigInteger g, n;
+
+ int lowerSigmaBound;
+
+ /**
+ * @param privateKey
+ */
+ public NaccacheSternKeyParameters(boolean privateKey, BigInteger g, BigInteger n, int lowerSigmaBound)
+ {
+ super(privateKey);
+ this.g = g;
+ this.n = n;
+ this.lowerSigmaBound = lowerSigmaBound;
+ }
+
+ /**
+ * @return Returns the g.
+ */
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ /**
+ * @return Returns the lowerSigmaBound.
+ */
+ public int getLowerSigmaBound()
+ {
+ return lowerSigmaBound;
+ }
+
+ /**
+ * @return Returns the n.
+ */
+ public BigInteger getModulus()
+ {
+ return n;
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/NaccacheSternPrivateKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/NaccacheSternPrivateKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/NaccacheSternPrivateKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/NaccacheSternPrivateKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,50 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+import java.util.Vector;
+
+/**
+ * Private key parameters for NaccacheStern cipher. For details on this cipher,
+ * please see
+ *
+ * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+ */
+public class NaccacheSternPrivateKeyParameters extends NaccacheSternKeyParameters
+{
+ private BigInteger phi_n;
+ private Vector smallPrimes;
+
+ /**
+ * Constructs a NaccacheSternPrivateKey
+ *
+ * @param g
+ * the public enryption parameter g
+ * @param n
+ * the public modulus n = p*q
+ * @param lowerSigmaBound
+ * the public lower sigma bound up to which data can be encrypted
+ * @param smallPrimes
+ * the small primes, of which sigma is constructed in the right
+ * order
+ * @param phi_n
+ * the private modulus phi(n) = (p-1)(q-1)
+ */
+ public NaccacheSternPrivateKeyParameters(BigInteger g, BigInteger n,
+ int lowerSigmaBound, Vector smallPrimes,
+ BigInteger phi_n)
+ {
+ super(true, g, n, lowerSigmaBound);
+ this.smallPrimes = smallPrimes;
+ this.phi_n = phi_n;
+ }
+
+ public BigInteger getPhi_n()
+ {
+ return phi_n;
+ }
+
+ public Vector getSmallPrimes()
+ {
+ return smallPrimes;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ParametersWithIV.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ParametersWithIV.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ParametersWithIV.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ParametersWithIV.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,39 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+public class ParametersWithIV
+ implements CipherParameters
+{
+ private byte[] iv;
+ private CipherParameters parameters;
+
+ public ParametersWithIV(
+ CipherParameters parameters,
+ byte[] iv)
+ {
+ this(parameters, iv, 0, iv.length);
+ }
+
+ public ParametersWithIV(
+ CipherParameters parameters,
+ byte[] iv,
+ int ivOff,
+ int ivLen)
+ {
+ this.iv = new byte[ivLen];
+ this.parameters = parameters;
+
+ System.arraycopy(iv, ivOff, this.iv, 0, ivLen);
+ }
+
+ public byte[] getIV()
+ {
+ return iv;
+ }
+
+ public CipherParameters getParameters()
+ {
+ return parameters;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ParametersWithRandom.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ParametersWithRandom.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ParametersWithRandom.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ParametersWithRandom.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,36 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+import java.security.SecureRandom;
+
+public class ParametersWithRandom
+ implements CipherParameters
+{
+ private SecureRandom random;
+ private CipherParameters parameters;
+
+ public ParametersWithRandom(
+ CipherParameters parameters,
+ SecureRandom random)
+ {
+ this.random = random;
+ this.parameters = parameters;
+ }
+
+ public ParametersWithRandom(
+ CipherParameters parameters)
+ {
+ this(parameters, new SecureRandom());
+ }
+
+ public SecureRandom getRandom()
+ {
+ return random;
+ }
+
+ public CipherParameters getParameters()
+ {
+ return parameters;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ParametersWithSBox.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ParametersWithSBox.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ParametersWithSBox.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ParametersWithSBox.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,28 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+public class ParametersWithSBox
+ implements CipherParameters
+{
+ private CipherParameters parameters;
+ private byte[] sBox;
+
+ public ParametersWithSBox(
+ CipherParameters parameters,
+ byte[] sBox)
+ {
+ this.parameters = parameters;
+ this.sBox = sBox;
+ }
+
+ public byte[] getSBox()
+ {
+ return sBox;
+ }
+
+ public CipherParameters getParameters()
+ {
+ return parameters;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ParametersWithSalt.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ParametersWithSalt.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/ParametersWithSalt.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/ParametersWithSalt.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,42 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+/**
+ * Cipher parameters with a fixed salt value associated with them.
+ */
+public class ParametersWithSalt
+ implements CipherParameters
+{
+ private byte[] salt;
+ private CipherParameters parameters;
+
+ public ParametersWithSalt(
+ CipherParameters parameters,
+ byte[] salt)
+ {
+ this(parameters, salt, 0, salt.length);
+ }
+
+ public ParametersWithSalt(
+ CipherParameters parameters,
+ byte[] salt,
+ int saltOff,
+ int saltLen)
+ {
+ this.salt = new byte[saltLen];
+ this.parameters = parameters;
+
+ System.arraycopy(salt, saltOff, this.salt, 0, saltLen);
+ }
+
+ public byte[] getSalt()
+ {
+ return salt;
+ }
+
+ public CipherParameters getParameters()
+ {
+ return parameters;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/RC2Parameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/RC2Parameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/RC2Parameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/RC2Parameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,36 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+public class RC2Parameters
+ implements CipherParameters
+{
+ private byte[] key;
+ private int bits;
+
+ public RC2Parameters(
+ byte[] key)
+ {
+ this(key, (key.length > 128) ? 1024 : (key.length * 8));
+ }
+
+ public RC2Parameters(
+ byte[] key,
+ int bits)
+ {
+ this.key = new byte[key.length];
+ this.bits = bits;
+
+ System.arraycopy(key, 0, this.key, 0, key.length);
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+
+ public int getEffectiveKeyBits()
+ {
+ return bits;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/RC5Parameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/RC5Parameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/RC5Parameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/RC5Parameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,35 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+public class RC5Parameters
+ implements CipherParameters
+{
+ private byte[] key;
+ private int rounds;
+
+ public RC5Parameters(
+ byte[] key,
+ int rounds)
+ {
+ if (key.length > 255)
+ {
+ throw new IllegalArgumentException("RC5 key length can be no greater than 255");
+ }
+
+ this.key = new byte[key.length];
+ this.rounds = rounds;
+
+ System.arraycopy(key, 0, this.key, 0, key.length);
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+
+ public int getRounds()
+ {
+ return rounds;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/RSABlindingParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/RSABlindingParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/RSABlindingParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/RSABlindingParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,35 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+
+import java.math.BigInteger;
+
+public class RSABlindingParameters
+ implements CipherParameters
+{
+ private RSAKeyParameters publicKey;
+ private BigInteger blindingFactor;
+
+ public RSABlindingParameters(
+ RSAKeyParameters publicKey,
+ BigInteger blindingFactor)
+ {
+ if (publicKey instanceof RSAPrivateCrtKeyParameters)
+ {
+ throw new IllegalArgumentException("RSA parameters should be for a public key");
+ }
+
+ this.publicKey = publicKey;
+ this.blindingFactor = blindingFactor;
+ }
+
+ public RSAKeyParameters getPublicKey()
+ {
+ return publicKey;
+ }
+
+ public BigInteger getBlindingFactor()
+ {
+ return blindingFactor;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/RSAKeyGenerationParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/RSAKeyGenerationParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/RSAKeyGenerationParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/RSAKeyGenerationParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,48 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.KeyGenerationParameters;
+
+public class RSAKeyGenerationParameters
+ extends KeyGenerationParameters
+{
+ private BigInteger publicExponent;
+ private int certainty;
+
+ public RSAKeyGenerationParameters(
+ BigInteger publicExponent,
+ SecureRandom random,
+ int strength,
+ int certainty)
+ {
+ super(random, strength);
+
+ if (strength < 12)
+ {
+ throw new IllegalArgumentException("key strength too small");
+ }
+
+ //
+ // public exponent cannot be even
+ //
+ if (!publicExponent.testBit(0))
+ {
+ throw new IllegalArgumentException("public exponent cannot be even");
+ }
+
+ this.publicExponent = publicExponent;
+ this.certainty = certainty;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return publicExponent;
+ }
+
+ public int getCertainty()
+ {
+ return certainty;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/RSAKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/RSAKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/RSAKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/RSAKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,31 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class RSAKeyParameters
+ extends AsymmetricKeyParameter
+{
+ private BigInteger modulus;
+ private BigInteger exponent;
+
+ public RSAKeyParameters(
+ boolean isPrivate,
+ BigInteger modulus,
+ BigInteger exponent)
+ {
+ super(isPrivate);
+
+ this.modulus = modulus;
+ this.exponent = exponent;
+ }
+
+ public BigInteger getModulus()
+ {
+ return modulus;
+ }
+
+ public BigInteger getExponent()
+ {
+ return exponent;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/RSAPrivateCrtKeyParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,67 @@
+package pdftk.org.bouncycastle.crypto.params;
+
+import java.math.BigInteger;
+
+public class RSAPrivateCrtKeyParameters
+ extends RSAKeyParameters
+{
+ private BigInteger e;
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger dP;
+ private BigInteger dQ;
+ private BigInteger qInv;
+
+ /**
+ *
+ */
+ public RSAPrivateCrtKeyParameters(
+ BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger p,
+ BigInteger q,
+ BigInteger dP,
+ BigInteger dQ,
+ BigInteger qInv)
+ {
+ super(true, modulus, privateExponent);
+
+ this.e = publicExponent;
+ this.p = p;
+ this.q = q;
+ this.dP = dP;
+ this.dQ = dQ;
+ this.qInv = qInv;
+ }
+
+ public BigInteger getPublicExponent()
+ {
+ return e;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getDP()
+ {
+ return dP;
+ }
+
+ public BigInteger getDQ()
+ {
+ return dQ;
+ }
+
+ public BigInteger getQInv()
+ {
+ return qInv;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/params/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/params/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Classes for parameter objects for ciphers and generators.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/parsers/DHIESPublicKeyParser.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/parsers/DHIESPublicKeyParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/parsers/DHIESPublicKeyParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/parsers/DHIESPublicKeyParser.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,31 @@
+package pdftk.org.bouncycastle.crypto.parsers;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.KeyParser;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPublicKeyParameters;
+
+public class DHIESPublicKeyParser
+ implements KeyParser
+{
+ private DHParameters dhParams;
+
+ public DHIESPublicKeyParser(DHParameters dhParams)
+ {
+ this.dhParams = dhParams;
+ }
+
+ public AsymmetricKeyParameter readKey(InputStream stream)
+ throws IOException
+ {
+ byte[] V = new byte[(dhParams.getP().bitLength() + 7) / 8];
+
+ stream.read(V, 0, V.length);
+
+ return new DHPublicKeyParameters(new BigInteger(1, V), dhParams);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/parsers/ECIESPublicKeyParser.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/parsers/ECIESPublicKeyParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/parsers/ECIESPublicKeyParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/parsers/ECIESPublicKeyParser.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,53 @@
+package pdftk.org.bouncycastle.crypto.parsers;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import pdftk.org.bouncycastle.crypto.KeyParser;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ECDomainParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+
+public class ECIESPublicKeyParser
+ implements KeyParser
+{
+ private ECDomainParameters ecParams;
+
+ public ECIESPublicKeyParser(ECDomainParameters ecParams)
+ {
+ this.ecParams = ecParams;
+ }
+
+ public AsymmetricKeyParameter readKey(InputStream stream)
+ throws IOException
+ {
+ byte[] V;
+ int first = stream.read();
+
+ // Decode the public ephemeral key
+ switch (first)
+ {
+ case 0x00: // infinity
+ throw new IOException("Sender's public key invalid.");
+
+ case 0x02: // compressed
+ case 0x03: // Byte length calculated as in ECPoint.getEncoded();
+ V = new byte[1 + (ecParams.getCurve().getFieldSize()+7)/8];
+ break;
+
+ case 0x04: // uncompressed or
+ case 0x06: // hybrid
+ case 0x07: // Byte length calculated as in ECPoint.getEncoded();
+ V = new byte[1 + 2*((ecParams.getCurve().getFieldSize()+7)/8)];
+ break;
+
+ default:
+ throw new IOException("Sender's public key has invalid point encoding 0x" + Integer.toString(first, 16));
+ }
+
+ V[0] = (byte)first;
+ stream.read(V, 1, V.length - 1);
+
+ return new ECPublicKeyParameters(ecParams.getCurve().decodePoint(V), ecParams);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/prng/DigestRandomGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/prng/DigestRandomGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/prng/DigestRandomGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/prng/DigestRandomGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,123 @@
+package pdftk.org.bouncycastle.crypto.prng;
+
+import pdftk.org.bouncycastle.crypto.Digest;
+
+/**
+ * Random generation based on the digest with counter. Calling addSeedMaterial will
+ * always increase the entropy of the hash.
+ *
+ * Internal access to the digest is synchronized so a single one of these can be shared.
+ *
+ */
+public class DigestRandomGenerator
+ implements RandomGenerator
+{
+ private static long CYCLE_COUNT = 10;
+
+ private long stateCounter;
+ private long seedCounter;
+ private Digest digest;
+ private byte[] state;
+ private byte[] seed;
+
+ // public constructors
+ public DigestRandomGenerator(
+ Digest digest)
+ {
+ this.digest = digest;
+
+ this.seed = new byte[digest.getDigestSize()];
+ this.seedCounter = 1;
+
+ this.state = new byte[digest.getDigestSize()];
+ this.stateCounter = 1;
+ }
+
+ public void addSeedMaterial(byte[] inSeed)
+ {
+ synchronized (this)
+ {
+ digestUpdate(inSeed);
+ digestUpdate(seed);
+ digestDoFinal(seed);
+ }
+ }
+
+ public void addSeedMaterial(long rSeed)
+ {
+ synchronized (this)
+ {
+ digestAddCounter(rSeed);
+ digestUpdate(seed);
+
+ digestDoFinal(seed);
+ }
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ nextBytes(bytes, 0, bytes.length);
+ }
+
+ public void nextBytes(byte[] bytes, int start, int len)
+ {
+ synchronized (this)
+ {
+ int stateOff = 0;
+
+ generateState();
+
+ int end = start + len;
+ for (int i = start; i != end; i++)
+ {
+ if (stateOff == state.length)
+ {
+ generateState();
+ stateOff = 0;
+ }
+ bytes[i] = state[stateOff++];
+ }
+ }
+ }
+
+ private void cycleSeed()
+ {
+ digestUpdate(seed);
+ digestAddCounter(seedCounter++);
+
+ digestDoFinal(seed);
+ }
+
+ private void generateState()
+ {
+ digestAddCounter(stateCounter++);
+ digestUpdate(state);
+ digestUpdate(seed);
+
+ digestDoFinal(state);
+
+ if ((stateCounter % CYCLE_COUNT) == 0)
+ {
+ cycleSeed();
+ }
+ }
+
+ private void digestAddCounter(long seed)
+ {
+ for (int i = 0; i != 8; i++)
+ {
+ digest.update((byte)seed);
+ seed >>>= 8;
+ }
+ }
+
+ private void digestUpdate(byte[] inSeed)
+ {
+ digest.update(inSeed, 0, inSeed.length);
+ }
+
+ private void digestDoFinal(byte[] result)
+ {
+ digest.doFinal(result, 0);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/prng/RandomGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/prng/RandomGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/prng/RandomGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/prng/RandomGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,38 @@
+package pdftk.org.bouncycastle.crypto.prng;
+
+/**
+ * Generic interface for objects generating random bytes.
+ */
+public interface RandomGenerator
+{
+ /**
+ * Add more seed material to the generator.
+ *
+ * @param seed a byte array to be mixed into the generator's state.
+ */
+ void addSeedMaterial(byte[] seed);
+
+ /**
+ * Add more seed material to the generator.
+ *
+ * @param seed a long value to be mixed into the generator's state.
+ */
+ void addSeedMaterial(long seed);
+
+ /**
+ * Fill bytes with random values.
+ *
+ * @param bytes byte array to be filled.
+ */
+ void nextBytes(byte[] bytes);
+
+ /**
+ * Fill part of bytes with random values.
+ *
+ * @param bytes byte array to be filled.
+ * @param start index to start filling at.
+ * @param len length of segment to fill.
+ */
+ void nextBytes(byte[] bytes, int start, int len);
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/prng/ReversedWindowGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/prng/ReversedWindowGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/prng/ReversedWindowGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/prng/ReversedWindowGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,111 @@
+package pdftk.org.bouncycastle.crypto.prng;
+
+/**
+ * Takes bytes generated by an underling RandomGenerator and reverses the order in
+ * each small window (of configurable size).
+ *
+ * Access to internals is synchronized so a single one of these can be shared.
+ *
+ */
+public class ReversedWindowGenerator
+ implements RandomGenerator
+{
+ private final RandomGenerator generator;
+
+ private byte[] window;
+ private int windowCount;
+
+ public ReversedWindowGenerator(
+ RandomGenerator generator,
+ int windowSize)
+ {
+ if (generator == null)
+ {
+ throw new IllegalArgumentException("generator cannot be null");
+ }
+ if (windowSize < 2)
+ {
+ throw new IllegalArgumentException("windowSize must be at least 2");
+ }
+
+ this.generator = generator;
+ this.window = new byte[windowSize];
+ }
+
+ /**
+ * Add more seed material to the generator.
+ *
+ * @param seed a byte array to be mixed into the generator's state.
+ */
+ public void addSeedMaterial(
+ byte[] seed)
+ {
+ synchronized (this)
+ {
+ windowCount = 0;
+ generator.addSeedMaterial(seed);
+ }
+ }
+
+ /**
+ * Add more seed material to the generator.
+ *
+ * @param seed a long value to be mixed into the generator's state.
+ */
+ public void addSeedMaterial(
+ long seed)
+ {
+ synchronized (this)
+ {
+ windowCount = 0;
+ generator.addSeedMaterial(seed);
+ }
+ }
+
+ /**
+ * Fill bytes with random values.
+ *
+ * @param bytes byte array to be filled.
+ */
+ public void nextBytes(
+ byte[] bytes)
+ {
+ doNextBytes(bytes, 0, bytes.length);
+ }
+
+ /**
+ * Fill part of bytes with random values.
+ *
+ * @param bytes byte array to be filled.
+ * @param start index to start filling at.
+ * @param len length of segment to fill.
+ */
+ public void nextBytes(
+ byte[] bytes,
+ int start,
+ int len)
+ {
+ doNextBytes(bytes, start, len);
+ }
+
+ private void doNextBytes(
+ byte[] bytes,
+ int start,
+ int len)
+ {
+ synchronized (this)
+ {
+ int done = 0;
+ while (done < len)
+ {
+ if (windowCount < 1)
+ {
+ generator.nextBytes(window, 0, window.length);
+ windowCount = window.length;
+ }
+
+ bytes[start + done++] = window[--windowCount];
+ }
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/prng/ThreadedSeedGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/prng/ThreadedSeedGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/prng/ThreadedSeedGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/prng/ThreadedSeedGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,95 @@
+package pdftk.org.bouncycastle.crypto.prng;
+
+/**
+ * A thread based seed generator - one source of randomness.
+ *
+ * Based on an idea from Marcus Lippert.
+ *
+ */
+public class ThreadedSeedGenerator
+{
+ private class SeedGenerator
+ implements Runnable
+ {
+ private volatile int counter = 0;
+ private volatile boolean stop = false;
+
+ public void run()
+ {
+ while (!this.stop)
+ {
+ this.counter++;
+ }
+
+ }
+
+ public byte[] generateSeed(
+ int numbytes,
+ boolean fast)
+ {
+ Thread t = new Thread(this);
+ byte[] result = new byte[numbytes];
+ this.counter = 0;
+ this.stop = false;
+ int last = 0;
+ int end;
+
+ t.start();
+ if(fast)
+ {
+ end = numbytes;
+ }
+ else
+ {
+ end = numbytes * 8;
+ }
+ for (int i = 0; i < end; i++)
+ {
+ while (this.counter == last)
+ {
+ try
+ {
+ Thread.sleep(1);
+ }
+ catch (InterruptedException e)
+ {
+ // ignore
+ }
+ }
+ last = this.counter;
+ if (fast)
+ {
+ result[i] = (byte) (last & 0xff);
+ }
+ else
+ {
+ int bytepos = i/8;
+ result[bytepos] = (byte) ((result[bytepos] << 1) | (last & 1));
+ }
+
+ }
+ stop = true;
+ return result;
+ }
+ }
+
+ /**
+ * Generate seed bytes. Set fast to false for best quality.
+ *
+ * If fast is set to true, the code should be round about 8 times faster when
+ * generating a long sequence of random bytes. 20 bytes of random values using
+ * the fast mode take less than half a second on a Nokia e70. If fast is set to false,
+ * it takes round about 2500 ms.
+ *
+ * @param numBytes the number of bytes to generate
+ * @param fast true if fast mode should be used
+ */
+ public byte[] generateSeed(
+ int numBytes,
+ boolean fast)
+ {
+ SeedGenerator gen = new SeedGenerator();
+
+ return gen.generateSeed(numBytes, fast);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/prng/VMPCRandomGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/prng/VMPCRandomGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/prng/VMPCRandomGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/prng/VMPCRandomGenerator.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,131 @@
+package pdftk.org.bouncycastle.crypto.prng;
+
+public class VMPCRandomGenerator implements RandomGenerator
+{
+ private byte n = 0;
+
+ /**
+ * Permutation generated by code:
+ * // First 1850 fractional digit of Pi number.
+ * byte[] key = new BigInteger("14159265358979323846...5068006422512520511").toByteArray();
+ * s = 0;
+ * P = new byte[256];
+ * for (int i = 0; i < 256; i++) {
+ * P[i] = (byte) i;
+ * }
+ * for (int m = 0; m < 768; m++) {
+ * s = P[(s + P[m & 0xff] + key[m % key.length]) & 0xff];
+ * byte temp = P[m & 0xff];
+ * P[m & 0xff] = P[s & 0xff];
+ * P[s & 0xff] = temp;
+ * }
+ */
+ private byte[] P =
+ {
+ (byte) 0xbb, (byte) 0x2c, (byte) 0x62, (byte) 0x7f,
+ (byte) 0xb5, (byte) 0xaa, (byte) 0xd4, (byte) 0x0d, (byte) 0x81,
+ (byte) 0xfe, (byte) 0xb2, (byte) 0x82, (byte) 0xcb, (byte) 0xa0,
+ (byte) 0xa1, (byte) 0x08, (byte) 0x18, (byte) 0x71, (byte) 0x56,
+ (byte) 0xe8, (byte) 0x49, (byte) 0x02, (byte) 0x10, (byte) 0xc4,
+ (byte) 0xde, (byte) 0x35, (byte) 0xa5, (byte) 0xec, (byte) 0x80,
+ (byte) 0x12, (byte) 0xb8, (byte) 0x69, (byte) 0xda, (byte) 0x2f,
+ (byte) 0x75, (byte) 0xcc, (byte) 0xa2, (byte) 0x09, (byte) 0x36,
+ (byte) 0x03, (byte) 0x61, (byte) 0x2d, (byte) 0xfd, (byte) 0xe0,
+ (byte) 0xdd, (byte) 0x05, (byte) 0x43, (byte) 0x90, (byte) 0xad,
+ (byte) 0xc8, (byte) 0xe1, (byte) 0xaf, (byte) 0x57, (byte) 0x9b,
+ (byte) 0x4c, (byte) 0xd8, (byte) 0x51, (byte) 0xae, (byte) 0x50,
+ (byte) 0x85, (byte) 0x3c, (byte) 0x0a, (byte) 0xe4, (byte) 0xf3,
+ (byte) 0x9c, (byte) 0x26, (byte) 0x23, (byte) 0x53, (byte) 0xc9,
+ (byte) 0x83, (byte) 0x97, (byte) 0x46, (byte) 0xb1, (byte) 0x99,
+ (byte) 0x64, (byte) 0x31, (byte) 0x77, (byte) 0xd5, (byte) 0x1d,
+ (byte) 0xd6, (byte) 0x78, (byte) 0xbd, (byte) 0x5e, (byte) 0xb0,
+ (byte) 0x8a, (byte) 0x22, (byte) 0x38, (byte) 0xf8, (byte) 0x68,
+ (byte) 0x2b, (byte) 0x2a, (byte) 0xc5, (byte) 0xd3, (byte) 0xf7,
+ (byte) 0xbc, (byte) 0x6f, (byte) 0xdf, (byte) 0x04, (byte) 0xe5,
+ (byte) 0x95, (byte) 0x3e, (byte) 0x25, (byte) 0x86, (byte) 0xa6,
+ (byte) 0x0b, (byte) 0x8f, (byte) 0xf1, (byte) 0x24, (byte) 0x0e,
+ (byte) 0xd7, (byte) 0x40, (byte) 0xb3, (byte) 0xcf, (byte) 0x7e,
+ (byte) 0x06, (byte) 0x15, (byte) 0x9a, (byte) 0x4d, (byte) 0x1c,
+ (byte) 0xa3, (byte) 0xdb, (byte) 0x32, (byte) 0x92, (byte) 0x58,
+ (byte) 0x11, (byte) 0x27, (byte) 0xf4, (byte) 0x59, (byte) 0xd0,
+ (byte) 0x4e, (byte) 0x6a, (byte) 0x17, (byte) 0x5b, (byte) 0xac,
+ (byte) 0xff, (byte) 0x07, (byte) 0xc0, (byte) 0x65, (byte) 0x79,
+ (byte) 0xfc, (byte) 0xc7, (byte) 0xcd, (byte) 0x76, (byte) 0x42,
+ (byte) 0x5d, (byte) 0xe7, (byte) 0x3a, (byte) 0x34, (byte) 0x7a,
+ (byte) 0x30, (byte) 0x28, (byte) 0x0f, (byte) 0x73, (byte) 0x01,
+ (byte) 0xf9, (byte) 0xd1, (byte) 0xd2, (byte) 0x19, (byte) 0xe9,
+ (byte) 0x91, (byte) 0xb9, (byte) 0x5a, (byte) 0xed, (byte) 0x41,
+ (byte) 0x6d, (byte) 0xb4, (byte) 0xc3, (byte) 0x9e, (byte) 0xbf,
+ (byte) 0x63, (byte) 0xfa, (byte) 0x1f, (byte) 0x33, (byte) 0x60,
+ (byte) 0x47, (byte) 0x89, (byte) 0xf0, (byte) 0x96, (byte) 0x1a,
+ (byte) 0x5f, (byte) 0x93, (byte) 0x3d, (byte) 0x37, (byte) 0x4b,
+ (byte) 0xd9, (byte) 0xa8, (byte) 0xc1, (byte) 0x1b, (byte) 0xf6,
+ (byte) 0x39, (byte) 0x8b, (byte) 0xb7, (byte) 0x0c, (byte) 0x20,
+ (byte) 0xce, (byte) 0x88, (byte) 0x6e, (byte) 0xb6, (byte) 0x74,
+ (byte) 0x8e, (byte) 0x8d, (byte) 0x16, (byte) 0x29, (byte) 0xf2,
+ (byte) 0x87, (byte) 0xf5, (byte) 0xeb, (byte) 0x70, (byte) 0xe3,
+ (byte) 0xfb, (byte) 0x55, (byte) 0x9f, (byte) 0xc6, (byte) 0x44,
+ (byte) 0x4a, (byte) 0x45, (byte) 0x7d, (byte) 0xe2, (byte) 0x6b,
+ (byte) 0x5c, (byte) 0x6c, (byte) 0x66, (byte) 0xa9, (byte) 0x8c,
+ (byte) 0xee, (byte) 0x84, (byte) 0x13, (byte) 0xa7, (byte) 0x1e,
+ (byte) 0x9d, (byte) 0xdc, (byte) 0x67, (byte) 0x48, (byte) 0xba,
+ (byte) 0x2e, (byte) 0xe6, (byte) 0xa4, (byte) 0xab, (byte) 0x7c,
+ (byte) 0x94, (byte) 0x00, (byte) 0x21, (byte) 0xef, (byte) 0xea,
+ (byte) 0xbe, (byte) 0xca, (byte) 0x72, (byte) 0x4f, (byte) 0x52,
+ (byte) 0x98, (byte) 0x3f, (byte) 0xc2, (byte) 0x14, (byte) 0x7b,
+ (byte) 0x3b, (byte) 0x54 };
+
+ /**
+ * Value generated in the same way as {@link VMPCRandomGenerator#P};
+ */
+ private byte s = (byte) 0xbe;
+
+ public VMPCRandomGenerator()
+ {
+ }
+
+ public void addSeedMaterial(byte[] seed)
+ {
+ for (int m = 0; m < seed.length; m++)
+ {
+ s = P[(s + P[n & 0xff] + seed[m]) & 0xff];
+ byte temp = P[n & 0xff];
+ P[n & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ n = (byte) ((n + 1) & 0xff);
+ }
+ }
+
+ public void addSeedMaterial(long seed)
+ {
+ byte[] s = new byte[4];
+ s[3] = (byte) (seed & 0x000000ff);
+ s[2] = (byte) ((seed & 0x0000ff00) >> 8);
+ s[1] = (byte) ((seed & 0x00ff0000) >> 16);
+ s[0] = (byte) ((seed & 0xff000000) >> 24);
+ addSeedMaterial(s);
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ nextBytes(bytes, 0, bytes.length);
+ }
+
+ public void nextBytes(byte[] bytes, int start, int len)
+ {
+ synchronized (P)
+ {
+ int end = start + len;
+ for (int i = start; i != end; i++)
+ {
+ s = P[(s + P[n & 0xff]) & 0xff];
+ bytes[i] = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+ byte temp = P[n & 0xff];
+ P[n & 0xff] = P[s & 0xff];
+ P[s & 0xff] = temp;
+ n = (byte) ((n + 1) & 0xff);
+ }
+ }
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/prng/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/prng/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/prng/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/prng/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Lightweight psuedo-random number generators.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/DSADigestSigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/DSADigestSigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/DSADigestSigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/DSADigestSigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,163 @@
+package pdftk.org.bouncycastle.crypto.signers;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1EncodableVector;
+import pdftk.org.bouncycastle.asn1.ASN1Encoding;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DERInteger;
+import pdftk.org.bouncycastle.asn1.DERSequence;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DSA;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.Signer;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+
+public class DSADigestSigner
+ implements Signer
+{
+ private final Digest digest;
+ private final DSA dsaSigner;
+ private boolean forSigning;
+
+ public DSADigestSigner(
+ DSA signer,
+ Digest digest)
+ {
+ this.digest = digest;
+ this.dsaSigner = signer;
+ }
+
+ public void init(
+ boolean forSigning,
+ CipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+
+ AsymmetricKeyParameter k;
+
+ if (parameters instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)parameters;
+ }
+
+ if (forSigning && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("Signing Requires Private Key.");
+ }
+
+ if (!forSigning && k.isPrivate())
+ {
+ throw new IllegalArgumentException("Verification Requires Public Key.");
+ }
+
+ reset();
+
+ dsaSigner.init(forSigning, parameters);
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte input)
+ {
+ digest.update(input);
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] input,
+ int inOff,
+ int length)
+ {
+ digest.update(input, inOff, length);
+ }
+
+ /**
+ * Generate a signature for the message we've been loaded with using
+ * the key we were initialised with.
+ */
+ public byte[] generateSignature()
+ {
+ if (!forSigning)
+ {
+ throw new IllegalStateException("DSADigestSigner not initialised for signature generation.");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ BigInteger[] sig = dsaSigner.generateSignature(hash);
+
+ try
+ {
+ return derEncode(sig[0], sig[1]);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("unable to encode signature");
+ }
+ }
+
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ if (forSigning)
+ {
+ throw new IllegalStateException("DSADigestSigner not initialised for verification");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ try
+ {
+ BigInteger[] sig = derDecode(signature);
+ return dsaSigner.verifySignature(hash, sig[0], sig[1]);
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+ }
+
+ public void reset()
+ {
+ digest.reset();
+ }
+
+ private byte[] derEncode(
+ BigInteger r,
+ BigInteger s)
+ throws IOException
+ {
+ ASN1EncodableVector v = new ASN1EncodableVector();
+ v.add(new DERInteger(r));
+ v.add(new DERInteger(s));
+
+ return new DERSequence(v).getEncoded(ASN1Encoding.DER);
+ }
+
+ private BigInteger[] derDecode(
+ byte[] encoding)
+ throws IOException
+ {
+ ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding);
+
+ return new BigInteger[]
+ {
+ ((DERInteger)s.getObjectAt(0)).getValue(),
+ ((DERInteger)s.getObjectAt(1)).getValue()
+ };
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/DSASigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/DSASigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/DSASigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/DSASigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,138 @@
+package pdftk.org.bouncycastle.crypto.signers;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DSA;
+import pdftk.org.bouncycastle.crypto.params.DSAKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * The Digital Signature Algorithm - as described in "Handbook of Applied
+ * Cryptography", pages 452 - 453.
+ */
+public class DSASigner
+ implements DSA
+{
+ DSAKeyParameters key;
+
+ SecureRandom random;
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ this.key = (DSAPrivateKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ this.key = (DSAPrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (DSAPublicKeyParameters)param;
+ }
+ }
+
+ /**
+ * generate a signature for the given message using the key we were
+ * initialised with. For conventional DSA the message should be a SHA-1
+ * hash of the message of interest.
+ *
+ * @param message the message that will be verified later.
+ */
+ public BigInteger[] generateSignature(
+ byte[] message)
+ {
+ DSAParameters params = key.getParameters();
+ BigInteger m = calculateE(params.getQ(), message);
+ BigInteger k;
+ int qBitLength = params.getQ().bitLength();
+
+ do
+ {
+ k = new BigInteger(qBitLength, random);
+ }
+ while (k.compareTo(params.getQ()) >= 0);
+
+ BigInteger r = params.getG().modPow(k, params.getP()).mod(params.getQ());
+
+ k = k.modInverse(params.getQ()).multiply(
+ m.add(((DSAPrivateKeyParameters)key).getX().multiply(r)));
+
+ BigInteger s = k.mod(params.getQ());
+
+ BigInteger[] res = new BigInteger[2];
+
+ res[0] = r;
+ res[1] = s;
+
+ return res;
+ }
+
+ /**
+ * return true if the value r and s represent a DSA signature for
+ * the passed in message for standard DSA the message should be a
+ * SHA-1 hash of the real message to be verified.
+ */
+ public boolean verifySignature(
+ byte[] message,
+ BigInteger r,
+ BigInteger s)
+ {
+ DSAParameters params = key.getParameters();
+ BigInteger m = calculateE(params.getQ(), message);
+ BigInteger zero = BigInteger.valueOf(0);
+
+ if (zero.compareTo(r) >= 0 || params.getQ().compareTo(r) <= 0)
+ {
+ return false;
+ }
+
+ if (zero.compareTo(s) >= 0 || params.getQ().compareTo(s) <= 0)
+ {
+ return false;
+ }
+
+ BigInteger w = s.modInverse(params.getQ());
+
+ BigInteger u1 = m.multiply(w).mod(params.getQ());
+ BigInteger u2 = r.multiply(w).mod(params.getQ());
+
+ u1 = params.getG().modPow(u1, params.getP());
+ u2 = ((DSAPublicKeyParameters)key).getY().modPow(u2, params.getP());
+
+ BigInteger v = u1.multiply(u2).mod(params.getP()).mod(params.getQ());
+
+ return v.equals(r);
+ }
+
+ private BigInteger calculateE(BigInteger n, byte[] message)
+ {
+ if (n.bitLength() >= message.length * 8)
+ {
+ return new BigInteger(1, message);
+ }
+ else
+ {
+ byte[] trunc = new byte[n.bitLength() / 8];
+
+ System.arraycopy(message, 0, trunc, 0, trunc.length);
+
+ return new BigInteger(1, trunc);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/DSTU4145Signer.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/DSTU4145Signer.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/DSTU4145Signer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/DSTU4145Signer.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,156 @@
+package pdftk.org.bouncycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DSA;
+import pdftk.org.bouncycastle.crypto.params.ECKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.math.ec.ECAlgorithms;
+import pdftk.org.bouncycastle.math.ec.ECCurve;
+import pdftk.org.bouncycastle.math.ec.ECFieldElement;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * DSTU 4145-2002
+ *
+ * National Ukrainian standard of digital signature based on elliptic curves (DSTU 4145-2002).
+ *
+ */
+public class DSTU4145Signer
+ implements DSA
+{
+ private static final BigInteger ONE = BigInteger.valueOf(1);
+
+ private ECKeyParameters key;
+ private SecureRandom random;
+
+ public void init(boolean forSigning, CipherParameters param)
+ {
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ param = rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ }
+
+ this.key = (ECPrivateKeyParameters)param;
+ }
+ else
+ {
+ this.key = (ECPublicKeyParameters)param;
+ }
+
+ }
+
+ public BigInteger[] generateSignature(byte[] message)
+ {
+ ECFieldElement h = hash2FieldElement(key.getParameters().getCurve(), message);
+ if (h.toBigInteger().signum() == 0)
+ {
+ h = key.getParameters().getCurve().fromBigInteger(ONE);
+ }
+
+ BigInteger e, r, s;
+ ECFieldElement Fe, y;
+
+ do
+ {
+ do
+ {
+ do
+ {
+ e = generateRandomInteger(key.getParameters().getN(), random);
+ Fe = key.getParameters().getG().multiply(e).getX();
+ }
+ while (Fe.toBigInteger().signum() == 0);
+
+ y = h.multiply(Fe);
+ r = fieldElement2Integer(key.getParameters().getN(), y);
+ }
+ while (r.signum() == 0);
+
+ s = r.multiply(((ECPrivateKeyParameters)key).getD()).add(e).mod(key.getParameters().getN());
+ }
+ while (s.signum() == 0);
+
+ return new BigInteger[]{r, s};
+ }
+
+ public boolean verifySignature(byte[] message, BigInteger r, BigInteger s)
+ {
+ if (r.signum() == 0 || s.signum() == 0)
+ {
+ return false;
+ }
+ if (r.compareTo(key.getParameters().getN()) >= 0 || s.compareTo(key.getParameters().getN()) >= 0)
+ {
+ return false;
+ }
+
+ ECFieldElement h = hash2FieldElement(key.getParameters().getCurve(), message);
+ if (h.toBigInteger().signum() == 0)
+ {
+ h = key.getParameters().getCurve().fromBigInteger(ONE);
+ }
+
+ ECPoint R = ECAlgorithms.sumOfTwoMultiplies(key.getParameters().getG(), s, ((ECPublicKeyParameters)key).getQ(), r);
+ ECFieldElement y = h.multiply(R.getX());
+ return fieldElement2Integer(key.getParameters().getN(), y).compareTo(r) == 0;
+ }
+
+ /**
+ * Generates random integer such, than its bit length is less than that of n
+ */
+ private static BigInteger generateRandomInteger(BigInteger n, SecureRandom random)
+ {
+ return new BigInteger(n.bitLength() - 1, random);
+ }
+
+ private static void reverseBytes(byte[] bytes)
+ {
+ byte tmp;
+
+ for (int i=0; i= curve.getFieldSize())
+ {
+ num = num.clearBit(num.bitLength() - 1);
+ }
+
+ return curve.fromBigInteger(num);
+ }
+
+ private static BigInteger fieldElement2Integer(BigInteger n, ECFieldElement fieldElement)
+ {
+ BigInteger num = fieldElement.toBigInteger();
+ while (num.bitLength() >= n.bitLength())
+ {
+ num = num.clearBit(num.bitLength() - 1);
+ }
+
+ return num;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/ECDSASigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/ECDSASigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/ECDSASigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/ECDSASigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,163 @@
+package pdftk.org.bouncycastle.crypto.signers;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DSA;
+import pdftk.org.bouncycastle.crypto.params.ECKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.math.ec.ECAlgorithms;
+import pdftk.org.bouncycastle.math.ec.ECConstants;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+/**
+ * EC-DSA as described in X9.62
+ */
+public class ECDSASigner
+ implements ECConstants, DSA
+{
+ ECKeyParameters key;
+
+ SecureRandom random;
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ this.key = (ECPrivateKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ this.key = (ECPrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (ECPublicKeyParameters)param;
+ }
+ }
+
+ // 5.3 pg 28
+ /**
+ * generate a signature for the given message using the key we were
+ * initialised with. For conventional DSA the message should be a SHA-1
+ * hash of the message of interest.
+ *
+ * @param message the message that will be verified later.
+ */
+ public BigInteger[] generateSignature(
+ byte[] message)
+ {
+ BigInteger n = key.getParameters().getN();
+ BigInteger e = calculateE(n, message);
+ BigInteger r = null;
+ BigInteger s = null;
+
+ // 5.3.2
+ do // generate s
+ {
+ BigInteger k = null;
+ int nBitLength = n.bitLength();
+
+ do // generate r
+ {
+ do
+ {
+ k = new BigInteger(nBitLength, random);
+ }
+ while (k.equals(ZERO) || k.compareTo(n) >= 0);
+
+ ECPoint p = key.getParameters().getG().multiply(k);
+
+ // 5.3.3
+ BigInteger x = p.getX().toBigInteger();
+
+ r = x.mod(n);
+ }
+ while (r.equals(ZERO));
+
+ BigInteger d = ((ECPrivateKeyParameters)key).getD();
+
+ s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
+ }
+ while (s.equals(ZERO));
+
+ BigInteger[] res = new BigInteger[2];
+
+ res[0] = r;
+ res[1] = s;
+
+ return res;
+ }
+
+ // 5.4 pg 29
+ /**
+ * return true if the value r and s represent a DSA signature for
+ * the passed in message (for standard DSA the message should be
+ * a SHA-1 hash of the real message to be verified).
+ */
+ public boolean verifySignature(
+ byte[] message,
+ BigInteger r,
+ BigInteger s)
+ {
+ BigInteger n = key.getParameters().getN();
+ BigInteger e = calculateE(n, message);
+
+ // r in the range [1,n-1]
+ if (r.compareTo(ONE) < 0 || r.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ // s in the range [1,n-1]
+ if (s.compareTo(ONE) < 0 || s.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ BigInteger c = s.modInverse(n);
+
+ BigInteger u1 = e.multiply(c).mod(n);
+ BigInteger u2 = r.multiply(c).mod(n);
+
+ ECPoint G = key.getParameters().getG();
+ ECPoint Q = ((ECPublicKeyParameters)key).getQ();
+
+ ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, u1, Q, u2);
+
+ BigInteger v = point.getX().toBigInteger().mod(n);
+
+ return v.equals(r);
+ }
+
+ private BigInteger calculateE(BigInteger n, byte[] message)
+ {
+ int log2n = n.bitLength();
+ int messageBitLength = message.length * 8;
+
+ if (log2n >= messageBitLength)
+ {
+ return new BigInteger(1, message);
+ }
+ else
+ {
+ BigInteger trunc = new BigInteger(1, message);
+
+ trunc = trunc.shiftRight(messageBitLength - log2n);
+
+ return trunc;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/ECGOST3410Signer.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/ECGOST3410Signer.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/ECGOST3410Signer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/ECGOST3410Signer.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,152 @@
+package pdftk.org.bouncycastle.crypto.signers;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DSA;
+import pdftk.org.bouncycastle.crypto.params.ECKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.math.ec.ECAlgorithms;
+import pdftk.org.bouncycastle.math.ec.ECConstants;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * GOST R 34.10-2001 Signature Algorithm
+ */
+public class ECGOST3410Signer
+ implements DSA
+{
+ ECKeyParameters key;
+
+ SecureRandom random;
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ this.key = (ECPrivateKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ this.key = (ECPrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (ECPublicKeyParameters)param;
+ }
+ }
+
+ /**
+ * generate a signature for the given message using the key we were
+ * initialised with. For conventional GOST3410 the message should be a GOST3411
+ * hash of the message of interest.
+ *
+ * @param message the message that will be verified later.
+ */
+ public BigInteger[] generateSignature(
+ byte[] message)
+ {
+ byte[] mRev = new byte[message.length]; // conversion is little-endian
+ for (int i = 0; i != mRev.length; i++)
+ {
+ mRev[i] = message[mRev.length - 1 - i];
+ }
+
+ BigInteger e = new BigInteger(1, mRev);
+ BigInteger n = key.getParameters().getN();
+
+ BigInteger r = null;
+ BigInteger s = null;
+
+ do // generate s
+ {
+ BigInteger k = null;
+
+ do // generate r
+ {
+ do
+ {
+ k = new BigInteger(n.bitLength(), random);
+ }
+ while (k.equals(ECConstants.ZERO));
+
+ ECPoint p = key.getParameters().getG().multiply(k);
+
+ BigInteger x = p.getX().toBigInteger();
+
+ r = x.mod(n);
+ }
+ while (r.equals(ECConstants.ZERO));
+
+ BigInteger d = ((ECPrivateKeyParameters)key).getD();
+
+ s = (k.multiply(e)).add(d.multiply(r)).mod(n);
+ }
+ while (s.equals(ECConstants.ZERO));
+
+ BigInteger[] res = new BigInteger[2];
+
+ res[0] = r;
+ res[1] = s;
+
+ return res;
+ }
+
+ /**
+ * return true if the value r and s represent a GOST3410 signature for
+ * the passed in message (for standard GOST3410 the message should be
+ * a GOST3411 hash of the real message to be verified).
+ */
+ public boolean verifySignature(
+ byte[] message,
+ BigInteger r,
+ BigInteger s)
+ {
+ byte[] mRev = new byte[message.length]; // conversion is little-endian
+ for (int i = 0; i != mRev.length; i++)
+ {
+ mRev[i] = message[mRev.length - 1 - i];
+ }
+
+ BigInteger e = new BigInteger(1, mRev);
+ BigInteger n = key.getParameters().getN();
+
+ // r in the range [1,n-1]
+ if (r.compareTo(ECConstants.ONE) < 0 || r.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ // s in the range [1,n-1]
+ if (s.compareTo(ECConstants.ONE) < 0 || s.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ BigInteger v = e.modInverse(n);
+
+ BigInteger z1 = s.multiply(v).mod(n);
+ BigInteger z2 = (n.subtract(r)).multiply(v).mod(n);
+
+ ECPoint G = key.getParameters().getG(); // P
+ ECPoint Q = ((ECPublicKeyParameters)key).getQ();
+
+ ECPoint point = ECAlgorithms.sumOfTwoMultiplies(G, z1, Q, z2);
+
+ BigInteger R = point.getX().toBigInteger().mod(n);
+
+ return R.equals(r);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/ECNRSigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/ECNRSigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/ECNRSigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/ECNRSigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,182 @@
+package pdftk.org.bouncycastle.crypto.signers;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DSA;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.generators.ECKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.params.ECKeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.ECKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.math.ec.ECAlgorithms;
+import pdftk.org.bouncycastle.math.ec.ECConstants;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * EC-NR as described in IEEE 1363-2000
+ */
+public class ECNRSigner
+ implements DSA
+{
+ private boolean forSigning;
+ private ECKeyParameters key;
+ private SecureRandom random;
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ this.forSigning = forSigning;
+
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ this.key = (ECPrivateKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ this.key = (ECPrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (ECPublicKeyParameters)param;
+ }
+ }
+
+ // Section 7.2.5 ECSP-NR, pg 34
+ /**
+ * generate a signature for the given message using the key we were
+ * initialised with. Generally, the order of the curve should be at
+ * least as long as the hash of the message of interest, and with
+ * ECNR it *must* be at least as long.
+ *
+ * @param digest the digest to be signed.
+ * @exception DataLengthException if the digest is longer than the key allows
+ */
+ public BigInteger[] generateSignature(
+ byte[] digest)
+ {
+ if (! this.forSigning)
+ {
+ throw new IllegalStateException("not initialised for signing");
+ }
+
+ BigInteger n = ((ECPrivateKeyParameters)this.key).getParameters().getN();
+ int nBitLength = n.bitLength();
+
+ BigInteger e = new BigInteger(1, digest);
+ int eBitLength = e.bitLength();
+
+ ECPrivateKeyParameters privKey = (ECPrivateKeyParameters)key;
+
+ if (eBitLength > nBitLength)
+ {
+ throw new DataLengthException("input too large for ECNR key.");
+ }
+
+ BigInteger r = null;
+ BigInteger s = null;
+
+ AsymmetricCipherKeyPair tempPair;
+ do // generate r
+ {
+ // generate another, but very temporary, key pair using
+ // the same EC parameters
+ ECKeyPairGenerator keyGen = new ECKeyPairGenerator();
+
+ keyGen.init(new ECKeyGenerationParameters(privKey.getParameters(), this.random));
+
+ tempPair = keyGen.generateKeyPair();
+
+ // BigInteger Vx = tempPair.getPublic().getW().getAffineX();
+ ECPublicKeyParameters V = (ECPublicKeyParameters)tempPair.getPublic(); // get temp's public key
+ BigInteger Vx = V.getQ().getX().toBigInteger(); // get the point's x coordinate
+
+ r = Vx.add(e).mod(n);
+ }
+ while (r.equals(ECConstants.ZERO));
+
+ // generate s
+ BigInteger x = privKey.getD(); // private key value
+ BigInteger u = ((ECPrivateKeyParameters)tempPair.getPrivate()).getD(); // temp's private key value
+ s = u.subtract(r.multiply(x)).mod(n);
+
+ BigInteger[] res = new BigInteger[2];
+ res[0] = r;
+ res[1] = s;
+
+ return res;
+ }
+
+ // Section 7.2.6 ECVP-NR, pg 35
+ /**
+ * return true if the value r and s represent a signature for the
+ * message passed in. Generally, the order of the curve should be at
+ * least as long as the hash of the message of interest, and with
+ * ECNR, it *must* be at least as long. But just in case the signer
+ * applied mod(n) to the longer digest, this implementation will
+ * apply mod(n) during verification.
+ *
+ * @param digest the digest to be verified.
+ * @param r the r value of the signature.
+ * @param s the s value of the signature.
+ * @exception DataLengthException if the digest is longer than the key allows
+ */
+ public boolean verifySignature(
+ byte[] digest,
+ BigInteger r,
+ BigInteger s)
+ {
+ if (this.forSigning)
+ {
+ throw new IllegalStateException("not initialised for verifying");
+ }
+
+ ECPublicKeyParameters pubKey = (ECPublicKeyParameters)key;
+ BigInteger n = pubKey.getParameters().getN();
+ int nBitLength = n.bitLength();
+
+ BigInteger e = new BigInteger(1, digest);
+ int eBitLength = e.bitLength();
+
+ if (eBitLength > nBitLength)
+ {
+ throw new DataLengthException("input too large for ECNR key.");
+ }
+
+ // r in the range [1,n-1]
+ if (r.compareTo(ECConstants.ONE) < 0 || r.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ // s in the range [0,n-1] NB: ECNR spec says 0
+ if (s.compareTo(ECConstants.ZERO) < 0 || s.compareTo(n) >= 0)
+ {
+ return false;
+ }
+
+ // compute P = sG + rW
+
+ ECPoint G = pubKey.getParameters().getG();
+ ECPoint W = pubKey.getQ();
+ // calculate P using Bouncy math
+ ECPoint P = ECAlgorithms.sumOfTwoMultiplies(G, s, W, r);
+
+ BigInteger x = P.getX().toBigInteger();
+ BigInteger t = r.subtract(x).mod(n);
+
+ return t.equals(e);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/GOST3410Signer.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/GOST3410Signer.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/GOST3410Signer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/GOST3410Signer.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,127 @@
+package pdftk.org.bouncycastle.crypto.signers;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.DSA;
+import pdftk.org.bouncycastle.crypto.params.*;
+
+import java.security.SecureRandom;
+import java.math.BigInteger;
+
+/**
+ * GOST R 34.10-94 Signature Algorithm
+ */
+public class GOST3410Signer
+ implements DSA
+{
+ GOST3410KeyParameters key;
+
+ SecureRandom random;
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ if (forSigning)
+ {
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+ this.random = rParam.getRandom();
+ this.key = (GOST3410PrivateKeyParameters)rParam.getParameters();
+ }
+ else
+ {
+ this.random = new SecureRandom();
+ this.key = (GOST3410PrivateKeyParameters)param;
+ }
+ }
+ else
+ {
+ this.key = (GOST3410PublicKeyParameters)param;
+ }
+ }
+
+ /**
+ * generate a signature for the given message using the key we were
+ * initialised with. For conventional GOST3410 the message should be a GOST3411
+ * hash of the message of interest.
+ *
+ * @param message the message that will be verified later.
+ */
+ public BigInteger[] generateSignature(
+ byte[] message)
+ {
+ byte[] mRev = new byte[message.length]; // conversion is little-endian
+ for (int i = 0; i != mRev.length; i++)
+ {
+ mRev[i] = message[mRev.length - 1 - i];
+ }
+
+ BigInteger m = new BigInteger(1, mRev);
+ GOST3410Parameters params = key.getParameters();
+ BigInteger k;
+
+ do
+ {
+ k = new BigInteger(params.getQ().bitLength(), random);
+ }
+ while (k.compareTo(params.getQ()) >= 0);
+
+ BigInteger r = params.getA().modPow(k, params.getP()).mod(params.getQ());
+
+ BigInteger s = k.multiply(m).
+ add(((GOST3410PrivateKeyParameters)key).getX().multiply(r)).
+ mod(params.getQ());
+
+ BigInteger[] res = new BigInteger[2];
+
+ res[0] = r;
+ res[1] = s;
+
+ return res;
+ }
+
+ /**
+ * return true if the value r and s represent a GOST3410 signature for
+ * the passed in message for standard GOST3410 the message should be a
+ * GOST3411 hash of the real message to be verified.
+ */
+ public boolean verifySignature(
+ byte[] message,
+ BigInteger r,
+ BigInteger s)
+ {
+ byte[] mRev = new byte[message.length]; // conversion is little-endian
+ for (int i = 0; i != mRev.length; i++)
+ {
+ mRev[i] = message[mRev.length - 1 - i];
+ }
+
+ BigInteger m = new BigInteger(1, mRev);
+ GOST3410Parameters params = key.getParameters();
+ BigInteger zero = BigInteger.valueOf(0);
+
+ if (zero.compareTo(r) >= 0 || params.getQ().compareTo(r) <= 0)
+ {
+ return false;
+ }
+
+ if (zero.compareTo(s) >= 0 || params.getQ().compareTo(s) <= 0)
+ {
+ return false;
+ }
+
+ BigInteger v = m.modPow(params.getQ().subtract(new BigInteger("2")),params.getQ());
+
+ BigInteger z1 = s.multiply(v).mod(params.getQ());
+ BigInteger z2 = (params.getQ().subtract(r)).multiply(v).mod(params.getQ());
+
+ z1 = params.getA().modPow(z1, params.getP());
+ z2 = ((GOST3410PublicKeyParameters)key).getY().modPow(z2, params.getP());
+
+ BigInteger u = z1.multiply(z2).mod(params.getP()).mod(params.getQ());
+
+ return u.equals(r);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/GenericSigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/GenericSigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/GenericSigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/GenericSigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,136 @@
+package pdftk.org.bouncycastle.crypto.signers;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.Signer;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class GenericSigner
+ implements Signer
+{
+ private final AsymmetricBlockCipher engine;
+ private final Digest digest;
+ private boolean forSigning;
+
+ public GenericSigner(
+ AsymmetricBlockCipher engine,
+ Digest digest)
+ {
+ this.engine = engine;
+ this.digest = digest;
+ }
+
+ /**
+ * initialise the signer for signing or verification.
+ *
+ * @param forSigning
+ * true if for signing, false otherwise
+ * @param parameters
+ * necessary parameters.
+ */
+ public void init(
+ boolean forSigning,
+ CipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+ AsymmetricKeyParameter k;
+
+ if (parameters instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)parameters;
+ }
+
+ if (forSigning && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("signing requires private key");
+ }
+
+ if (!forSigning && k.isPrivate())
+ {
+ throw new IllegalArgumentException("verification requires public key");
+ }
+
+ reset();
+
+ engine.init(forSigning, parameters);
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte input)
+ {
+ digest.update(input);
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] input,
+ int inOff,
+ int length)
+ {
+ digest.update(input, inOff, length);
+ }
+
+ /**
+ * Generate a signature for the message we've been loaded with using the key
+ * we were initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException, DataLengthException
+ {
+ if (!forSigning)
+ {
+ throw new IllegalStateException("GenericSigner not initialised for signature generation.");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ return engine.processBlock(hash, 0, hash.length);
+ }
+
+ /**
+ * return true if the internal state represents the signature described in
+ * the passed in array.
+ */
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ if (forSigning)
+ {
+ throw new IllegalStateException("GenericSigner not initialised for verification");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ try
+ {
+ byte[] sig = engine.processBlock(signature, 0, signature.length);
+
+ return Arrays.constantTimeAreEqual(sig, hash);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ }
+
+ public void reset()
+ {
+ digest.reset();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/ISO9796d2PSSSigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/ISO9796d2PSSSigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/ISO9796d2PSSSigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/ISO9796d2PSSSigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,621 @@
+package pdftk.org.bouncycastle.crypto.signers;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.SignerWithRecovery;
+import pdftk.org.bouncycastle.crypto.digests.RIPEMD128Digest;
+import pdftk.org.bouncycastle.crypto.digests.RIPEMD160Digest;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithSalt;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+
+/**
+ * ISO9796-2 - mechanism using a hash function with recovery (scheme 2 and 3).
+ *
+ * Note: the usual length for the salt is the length of the hash
+ * function used in bytes.
+ */
+public class ISO9796d2PSSSigner
+ implements SignerWithRecovery
+{
+ static final public int TRAILER_IMPLICIT = 0xBC;
+ static final public int TRAILER_RIPEMD160 = 0x31CC;
+ static final public int TRAILER_RIPEMD128 = 0x32CC;
+ static final public int TRAILER_SHA1 = 0x33CC;
+
+ private Digest digest;
+ private AsymmetricBlockCipher cipher;
+
+ private SecureRandom random;
+ private byte[] standardSalt;
+
+ private int hLen;
+ private int trailer;
+ private int keyBits;
+ private byte[] block;
+ private byte[] mBuf;
+ private int messageLength;
+ private int saltLength;
+ private boolean fullMessage;
+ private byte[] recoveredMessage;
+
+ /**
+ * Generate a signer for the with either implicit or explicit trailers
+ * for ISO9796-2, scheme 2 or 3.
+ *
+ * @param cipher base cipher to use for signature creation/verification
+ * @param digest digest to use.
+ * @param saltLength length of salt in bytes.
+ * @param implicit whether or not the trailer is implicit or gives the hash.
+ */
+ public ISO9796d2PSSSigner(
+ AsymmetricBlockCipher cipher,
+ Digest digest,
+ int saltLength,
+ boolean implicit)
+ {
+ this.cipher = cipher;
+ this.digest = digest;
+ this.hLen = digest.getDigestSize();
+ this.saltLength = saltLength;
+
+ if (implicit)
+ {
+ trailer = TRAILER_IMPLICIT;
+ }
+ else
+ {
+ if (digest instanceof SHA1Digest)
+ {
+ trailer = TRAILER_SHA1;
+ }
+ else if (digest instanceof RIPEMD160Digest)
+ {
+ trailer = TRAILER_RIPEMD160;
+ }
+ else if (digest instanceof RIPEMD128Digest)
+ {
+ trailer = TRAILER_RIPEMD128;
+ }
+ else
+ {
+ throw new IllegalArgumentException("no valid trailer for digest");
+ }
+ }
+ }
+
+ /**
+ * Constructor for a signer with an explicit digest trailer.
+ *
+ * @param cipher cipher to use.
+ * @param digest digest to sign with.
+ * @param saltLength length of salt in bytes.
+ */
+ public ISO9796d2PSSSigner(
+ AsymmetricBlockCipher cipher,
+ Digest digest,
+ int saltLength)
+ {
+ this(cipher, digest, saltLength, false);
+ }
+
+ /**
+ * Initialise the signer.
+ *
+ * @param forSigning true if for signing, false if for verification.
+ * @param param parameters for signature generation/verification. If the
+ * parameters are for generation they should be a ParametersWithRandom,
+ * a ParametersWithSalt, or just an RSAKeyParameters object. If RSAKeyParameters
+ * are passed in a SecureRandom will be created.
+ * @exception IllegalArgumentException if wrong parameter type or a fixed
+ * salt is passed in which is the wrong length.
+ */
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ RSAKeyParameters kParam;
+ int lengthOfSalt = saltLength;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)param;
+
+ kParam = (RSAKeyParameters)p.getParameters();
+ if (forSigning)
+ {
+ random = p.getRandom();
+ }
+ }
+ else if (param instanceof ParametersWithSalt)
+ {
+ ParametersWithSalt p = (ParametersWithSalt)param;
+
+ kParam = (RSAKeyParameters)p.getParameters();
+ standardSalt = p.getSalt();
+ lengthOfSalt = standardSalt.length;
+ if (standardSalt.length != saltLength)
+ {
+ throw new IllegalArgumentException("Fixed salt is of wrong length");
+ }
+ }
+ else
+ {
+ kParam = (RSAKeyParameters)param;
+ if (forSigning)
+ {
+ random = new SecureRandom();
+ }
+ }
+
+ cipher.init(forSigning, kParam);
+
+ keyBits = kParam.getModulus().bitLength();
+
+ block = new byte[(keyBits + 7) / 8];
+
+ if (trailer == TRAILER_IMPLICIT)
+ {
+ mBuf = new byte[block.length - digest.getDigestSize() - lengthOfSalt - 1 - 1];
+ }
+ else
+ {
+ mBuf = new byte[block.length - digest.getDigestSize() - lengthOfSalt - 1 - 2];
+ }
+
+ reset();
+ }
+
+ /**
+ * compare two byte arrays - constant time
+ */
+ private boolean isSameAs(
+ byte[] a,
+ byte[] b)
+ {
+ boolean isOkay = true;
+
+ if (messageLength != b.length)
+ {
+ isOkay = false;
+ }
+
+ for (int i = 0; i != b.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ isOkay = false;
+ }
+ }
+
+ return isOkay;
+ }
+
+ /**
+ * clear possible sensitive data
+ */
+ private void clearBlock(
+ byte[] block)
+ {
+ for (int i = 0; i != block.length; i++)
+ {
+ block[i] = 0;
+ }
+ }
+
+ public void updateWithRecoveredMessage(byte[] signature)
+ throws InvalidCipherTextException
+ {
+ throw new RuntimeException("not implemented"); // TODO:
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte b)
+ {
+ if (messageLength < mBuf.length)
+ {
+ mBuf[messageLength++] = b;
+ }
+ else
+ {
+ digest.update(b);
+ }
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] in,
+ int off,
+ int len)
+ {
+ while (len > 0 && messageLength < mBuf.length)
+ {
+ this.update(in[off]);
+ off++;
+ len--;
+ }
+
+ if (len > 0)
+ {
+ digest.update(in, off, len);
+ }
+ }
+
+ /**
+ * reset the internal state
+ */
+ public void reset()
+ {
+ digest.reset();
+ messageLength = 0;
+ if (mBuf != null)
+ {
+ clearBlock(mBuf);
+ }
+ if (recoveredMessage != null)
+ {
+ clearBlock(recoveredMessage);
+ recoveredMessage = null;
+ }
+ fullMessage = false;
+ }
+
+ /**
+ * generate a signature for the loaded message using the key we were
+ * initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException
+ {
+ int digSize = digest.getDigestSize();
+
+ byte[] m2Hash = new byte[digSize];
+
+ digest.doFinal(m2Hash, 0);
+
+ byte[] C = new byte[8];
+ LtoOSP(messageLength * 8, C);
+
+ digest.update(C, 0, C.length);
+
+ digest.update(mBuf, 0, messageLength);
+
+ digest.update(m2Hash, 0, m2Hash.length);
+
+ byte[] salt;
+
+ if (standardSalt != null)
+ {
+ salt = standardSalt;
+ }
+ else
+ {
+ salt = new byte[saltLength];
+ random.nextBytes(salt);
+ }
+
+ digest.update(salt, 0, salt.length);
+
+ byte[] hash = new byte[digest.getDigestSize()];
+
+ digest.doFinal(hash, 0);
+
+ int tLength = 2;
+ if (trailer == TRAILER_IMPLICIT)
+ {
+ tLength = 1;
+ }
+
+ int off = block.length - messageLength - salt.length - hLen - tLength - 1;
+
+ block[off] = 0x01;
+
+ System.arraycopy(mBuf, 0, block, off + 1, messageLength);
+ System.arraycopy(salt, 0, block, off + 1 + messageLength, salt.length);
+
+ byte[] dbMask = maskGeneratorFunction1(hash, 0, hash.length, block.length - hLen - tLength);
+ for (int i = 0; i != dbMask.length; i++)
+ {
+ block[i] ^= dbMask[i];
+ }
+
+ System.arraycopy(hash, 0, block, block.length - hLen - tLength, hLen);
+
+ if (trailer == TRAILER_IMPLICIT)
+ {
+ block[block.length - 1] = (byte)TRAILER_IMPLICIT;
+ }
+ else
+ {
+ block[block.length - 2] = (byte)(trailer >>> 8);
+ block[block.length - 1] = (byte)trailer;
+ }
+
+ block[0] &= 0x7f;
+
+ byte[] b = cipher.processBlock(block, 0, block.length);
+
+ clearBlock(mBuf);
+ clearBlock(block);
+ messageLength = 0;
+
+ return b;
+ }
+
+ /**
+ * return true if the signature represents a ISO9796-2 signature
+ * for the passed in message.
+ */
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ byte[] block;
+
+ try
+ {
+ block = cipher.processBlock(signature, 0, signature.length);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ //
+ // adjust block size for leading zeroes if necessary
+ //
+ if (block.length < (keyBits + 7) / 8)
+ {
+ byte[] tmp = new byte[(keyBits + 7) / 8];
+
+ System.arraycopy(block, 0, tmp, tmp.length - block.length, block.length);
+ clearBlock(block);
+ block = tmp;
+ }
+
+ int tLength;
+
+ if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0)
+ {
+ tLength = 1;
+ }
+ else
+ {
+ int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF);
+
+ switch (sigTrail)
+ {
+ case TRAILER_RIPEMD160:
+ if (!(digest instanceof RIPEMD160Digest))
+ {
+ throw new IllegalStateException("signer should be initialised with RIPEMD160");
+ }
+ break;
+ case TRAILER_SHA1:
+ if (!(digest instanceof SHA1Digest))
+ {
+ throw new IllegalStateException("signer should be initialised with SHA1");
+ }
+ break;
+ case TRAILER_RIPEMD128:
+ if (!(digest instanceof RIPEMD128Digest))
+ {
+ throw new IllegalStateException("signer should be initialised with RIPEMD128");
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("unrecognised hash in signature");
+ }
+
+ tLength = 2;
+ }
+
+ //
+ // calculate H(m2)
+ //
+ byte[] m2Hash = new byte[hLen];
+ digest.doFinal(m2Hash, 0);
+
+ //
+ // remove the mask
+ //
+ byte[] dbMask = maskGeneratorFunction1(block, block.length - hLen - tLength, hLen, block.length - hLen - tLength);
+ for (int i = 0; i != dbMask.length; i++)
+ {
+ block[i] ^= dbMask[i];
+ }
+
+ block[0] &= 0x7f;
+
+ //
+ // find out how much padding we've got
+ //
+ int mStart = 0;
+ for (; mStart != block.length; mStart++)
+ {
+ if (block[mStart] == 0x01)
+ {
+ break;
+ }
+ }
+
+ mStart++;
+
+ if (mStart >= block.length)
+ {
+ clearBlock(block);
+ return false;
+ }
+
+ fullMessage = (mStart > 1);
+
+ recoveredMessage = new byte[dbMask.length - mStart - saltLength];
+
+ System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
+
+ //
+ // check the hashes
+ //
+ byte[] C = new byte[8];
+ LtoOSP(recoveredMessage.length * 8, C);
+
+ digest.update(C, 0, C.length);
+
+ if (recoveredMessage.length != 0)
+ {
+ digest.update(recoveredMessage, 0, recoveredMessage.length);
+ }
+
+ digest.update(m2Hash, 0, m2Hash.length);
+
+ // Update for the salt
+ digest.update(block, mStart + recoveredMessage.length, saltLength);
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ int off = block.length - tLength - hash.length;
+
+ boolean isOkay = true;
+
+ for (int i = 0; i != hash.length; i++)
+ {
+ if (hash[i] != block[off + i])
+ {
+ isOkay = false;
+ }
+ }
+
+ clearBlock(block);
+ clearBlock(hash);
+
+ if (!isOkay)
+ {
+ fullMessage = false;
+ clearBlock(recoveredMessage);
+ return false;
+ }
+
+ //
+ // if they've input a message check what we've recovered against
+ // what was input.
+ //
+ if (messageLength != 0)
+ {
+ if (!isSameAs(mBuf, recoveredMessage))
+ {
+ clearBlock(mBuf);
+ return false;
+ }
+
+ messageLength = 0;
+ }
+
+ clearBlock(mBuf);
+ return true;
+ }
+
+ /**
+ * Return true if the full message was recoveredMessage.
+ *
+ * @return true on full message recovery, false otherwise, or if not sure.
+ * @see pdftk.org.bouncycastle.crypto.SignerWithRecovery#hasFullMessage()
+ */
+ public boolean hasFullMessage()
+ {
+ return fullMessage;
+ }
+
+ /**
+ * Return a reference to the recoveredMessage message.
+ *
+ * @return the full/partial recoveredMessage message.
+ * @see pdftk.org.bouncycastle.crypto.SignerWithRecovery#getRecoveredMessage()
+ */
+ public byte[] getRecoveredMessage()
+ {
+ return recoveredMessage;
+ }
+
+ /**
+ * int to octet string.
+ */
+ private void ItoOSP(
+ int i,
+ byte[] sp)
+ {
+ sp[0] = (byte)(i >>> 24);
+ sp[1] = (byte)(i >>> 16);
+ sp[2] = (byte)(i >>> 8);
+ sp[3] = (byte)(i >>> 0);
+ }
+
+ /**
+ * long to octet string.
+ */
+ private void LtoOSP(
+ long l,
+ byte[] sp)
+ {
+ sp[0] = (byte)(l >>> 56);
+ sp[1] = (byte)(l >>> 48);
+ sp[2] = (byte)(l >>> 40);
+ sp[3] = (byte)(l >>> 32);
+ sp[4] = (byte)(l >>> 24);
+ sp[5] = (byte)(l >>> 16);
+ sp[6] = (byte)(l >>> 8);
+ sp[7] = (byte)(l >>> 0);
+ }
+ /**
+ * mask generator function, as described in PKCS1v2.
+ */
+ private byte[] maskGeneratorFunction1(
+ byte[] Z,
+ int zOff,
+ int zLen,
+ int length)
+ {
+ byte[] mask = new byte[length];
+ byte[] hashBuf = new byte[hLen];
+ byte[] C = new byte[4];
+ int counter = 0;
+
+ digest.reset();
+
+ while (counter < (length / hLen))
+ {
+ ItoOSP(counter, C);
+
+ digest.update(Z, zOff, zLen);
+ digest.update(C, 0, C.length);
+ digest.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, mask, counter * hLen, hLen);
+
+ counter++;
+ }
+
+ if ((counter * hLen) < length)
+ {
+ ItoOSP(counter, C);
+
+ digest.update(Z, zOff, zLen);
+ digest.update(C, 0, C.length);
+ digest.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, mask, counter * hLen, mask.length - (counter * hLen));
+ }
+
+ return mask;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/ISO9796d2Signer.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/ISO9796d2Signer.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/ISO9796d2Signer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/ISO9796d2Signer.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,615 @@
+package pdftk.org.bouncycastle.crypto.signers;
+
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.SignerWithRecovery;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Integers;
+
+/**
+ * ISO9796-2 - mechanism using a hash function with recovery (scheme 1)
+ */
+public class ISO9796d2Signer
+ implements SignerWithRecovery
+{
+ static final public int TRAILER_IMPLICIT = 0xBC;
+ static final public int TRAILER_RIPEMD160 = 0x31CC;
+ static final public int TRAILER_RIPEMD128 = 0x32CC;
+ static final public int TRAILER_SHA1 = 0x33CC;
+ static final public int TRAILER_SHA256 = 0x34CC;
+ static final public int TRAILER_SHA512 = 0x35CC;
+ static final public int TRAILER_SHA384 = 0x36CC;
+ static final public int TRAILER_WHIRLPOOL = 0x37CC;
+
+ private static Hashtable trailerMap = new Hashtable();
+
+ static
+ {
+ trailerMap.put("RIPEMD128", Integers.valueOf(TRAILER_RIPEMD128));
+ trailerMap.put("RIPEMD160", Integers.valueOf(TRAILER_RIPEMD160));
+
+ trailerMap.put("SHA-1", Integers.valueOf(TRAILER_SHA1));
+ trailerMap.put("SHA-256", Integers.valueOf(TRAILER_SHA256));
+ trailerMap.put("SHA-384", Integers.valueOf(TRAILER_SHA384));
+ trailerMap.put("SHA-512", Integers.valueOf(TRAILER_SHA512));
+
+ trailerMap.put("Whirlpool", Integers.valueOf(TRAILER_WHIRLPOOL));
+ }
+
+ private Digest digest;
+ private AsymmetricBlockCipher cipher;
+
+ private int trailer;
+ private int keyBits;
+ private byte[] block;
+ private byte[] mBuf;
+ private int messageLength;
+ private boolean fullMessage;
+ private byte[] recoveredMessage;
+
+ private byte[] preSig;
+ private byte[] preBlock;
+
+ /**
+ * Generate a signer for the with either implicit or explicit trailers
+ * for ISO9796-2.
+ *
+ * @param cipher base cipher to use for signature creation/verification
+ * @param digest digest to use.
+ * @param implicit whether or not the trailer is implicit or gives the hash.
+ */
+ public ISO9796d2Signer(
+ AsymmetricBlockCipher cipher,
+ Digest digest,
+ boolean implicit)
+ {
+ this.cipher = cipher;
+ this.digest = digest;
+
+ if (implicit)
+ {
+ trailer = TRAILER_IMPLICIT;
+ }
+ else
+ {
+ Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
+
+ if (trailerObj != null)
+ {
+ trailer = trailerObj.intValue();
+ }
+ else
+ {
+ throw new IllegalArgumentException("no valid trailer for digest");
+ }
+ }
+ }
+
+ /**
+ * Constructor for a signer with an explicit digest trailer.
+ *
+ * @param cipher cipher to use.
+ * @param digest digest to sign with.
+ */
+ public ISO9796d2Signer(
+ AsymmetricBlockCipher cipher,
+ Digest digest)
+ {
+ this(cipher, digest, false);
+ }
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ RSAKeyParameters kParam = (RSAKeyParameters)param;
+
+ cipher.init(forSigning, kParam);
+
+ keyBits = kParam.getModulus().bitLength();
+
+ block = new byte[(keyBits + 7) / 8];
+
+ if (trailer == TRAILER_IMPLICIT)
+ {
+ mBuf = new byte[block.length - digest.getDigestSize() - 2];
+ }
+ else
+ {
+ mBuf = new byte[block.length - digest.getDigestSize() - 3];
+ }
+
+ reset();
+ }
+
+ /**
+ * compare two byte arrays - constant time
+ */
+ private boolean isSameAs(
+ byte[] a,
+ byte[] b)
+ {
+ boolean isOkay = true;
+
+ if (messageLength > mBuf.length)
+ {
+ if (mBuf.length > b.length)
+ {
+ isOkay = false;
+ }
+
+ for (int i = 0; i != mBuf.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ isOkay = false;
+ }
+ }
+ }
+ else
+ {
+ if (messageLength != b.length)
+ {
+ isOkay = false;
+ }
+
+ for (int i = 0; i != b.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ isOkay = false;
+ }
+ }
+ }
+
+ return isOkay;
+ }
+
+ /**
+ * clear possible sensitive data
+ */
+ private void clearBlock(
+ byte[] block)
+ {
+ for (int i = 0; i != block.length; i++)
+ {
+ block[i] = 0;
+ }
+ }
+
+ public void updateWithRecoveredMessage(byte[] signature)
+ throws InvalidCipherTextException
+ {
+ byte[] block = cipher.processBlock(signature, 0, signature.length);
+
+ if (((block[0] & 0xC0) ^ 0x40) != 0)
+ {
+ throw new InvalidCipherTextException("malformed signature");
+ }
+
+ if (((block[block.length - 1] & 0xF) ^ 0xC) != 0)
+ {
+ throw new InvalidCipherTextException("malformed signature");
+ }
+
+ int delta = 0;
+
+ if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0)
+ {
+ delta = 1;
+ }
+ else
+ {
+ int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF);
+ Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
+
+ if (trailerObj != null)
+ {
+ if (sigTrail != trailerObj.intValue())
+ {
+ throw new IllegalStateException("signer initialised with wrong digest for trailer " + sigTrail);
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("unrecognised hash in signature");
+ }
+
+ delta = 2;
+ }
+
+ //
+ // find out how much padding we've got
+ //
+ int mStart = 0;
+
+ for (mStart = 0; mStart != block.length; mStart++)
+ {
+ if (((block[mStart] & 0x0f) ^ 0x0a) == 0)
+ {
+ break;
+ }
+ }
+
+ mStart++;
+
+ int off = block.length - delta - digest.getDigestSize();
+
+ //
+ // there must be at least one byte of message string
+ //
+ if ((off - mStart) <= 0)
+ {
+ throw new InvalidCipherTextException("malformed block");
+ }
+
+ //
+ // if we contain the whole message as well, check the hash of that.
+ //
+ if ((block[0] & 0x20) == 0)
+ {
+ fullMessage = true;
+
+ recoveredMessage = new byte[off - mStart];
+ System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
+ }
+ else
+ {
+ fullMessage = false;
+
+ recoveredMessage = new byte[off - mStart];
+ System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
+ }
+
+ preSig = signature;
+ preBlock = block;
+
+ digest.update(recoveredMessage, 0, recoveredMessage.length);
+ messageLength = recoveredMessage.length;
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte b)
+ {
+ digest.update(b);
+
+ if (preSig == null && messageLength < mBuf.length)
+ {
+ mBuf[messageLength] = b;
+ }
+
+ messageLength++;
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] in,
+ int off,
+ int len)
+ {
+ digest.update(in, off, len);
+
+ if (preSig == null && messageLength < mBuf.length)
+ {
+ for (int i = 0; i < len && (i + messageLength) < mBuf.length; i++)
+ {
+ mBuf[messageLength + i] = in[off + i];
+ }
+ }
+
+ messageLength += len;
+ }
+
+ /**
+ * reset the internal state
+ */
+ public void reset()
+ {
+ digest.reset();
+ messageLength = 0;
+ clearBlock(mBuf);
+
+ if (recoveredMessage != null)
+ {
+ clearBlock(recoveredMessage);
+ }
+
+ recoveredMessage = null;
+ fullMessage = false;
+ }
+
+ /**
+ * generate a signature for the loaded message using the key we were
+ * initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException
+ {
+ int digSize = digest.getDigestSize();
+
+ int t = 0;
+ int delta = 0;
+
+ if (trailer == TRAILER_IMPLICIT)
+ {
+ t = 8;
+ delta = block.length - digSize - 1;
+ digest.doFinal(block, delta);
+ block[block.length - 1] = (byte)TRAILER_IMPLICIT;
+ }
+ else
+ {
+ t = 16;
+ delta = block.length - digSize - 2;
+ digest.doFinal(block, delta);
+ block[block.length - 2] = (byte)(trailer >>> 8);
+ block[block.length - 1] = (byte)trailer;
+ }
+
+ byte header = 0;
+ int x = (digSize + messageLength) * 8 + t + 4 - keyBits;
+
+ if (x > 0)
+ {
+ int mR = messageLength - ((x + 7) / 8);
+ header = 0x60;
+
+ delta -= mR;
+
+ System.arraycopy(mBuf, 0, block, delta, mR);
+ }
+ else
+ {
+ header = 0x40;
+ delta -= messageLength;
+
+ System.arraycopy(mBuf, 0, block, delta, messageLength);
+ }
+
+ if ((delta - 1) > 0)
+ {
+ for (int i = delta - 1; i != 0; i--)
+ {
+ block[i] = (byte)0xbb;
+ }
+ block[delta - 1] ^= (byte)0x01;
+ block[0] = (byte)0x0b;
+ block[0] |= header;
+ }
+ else
+ {
+ block[0] = (byte)0x0a;
+ block[0] |= header;
+ }
+
+ byte[] b = cipher.processBlock(block, 0, block.length);
+
+ clearBlock(mBuf);
+ clearBlock(block);
+
+ return b;
+ }
+
+ /**
+ * return true if the signature represents a ISO9796-2 signature
+ * for the passed in message.
+ */
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ byte[] block = null;
+ boolean updateWithRecoveredCalled;
+
+ if (preSig == null)
+ {
+ updateWithRecoveredCalled = false;
+ try
+ {
+ block = cipher.processBlock(signature, 0, signature.length);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!Arrays.areEqual(preSig, signature))
+ {
+ throw new IllegalStateException("updateWithRecoveredMessage called on different signature");
+ }
+
+ updateWithRecoveredCalled = true;
+ block = preBlock;
+
+ preSig = null;
+ preBlock = null;
+ }
+
+ if (((block[0] & 0xC0) ^ 0x40) != 0)
+ {
+ return returnFalse(block);
+ }
+
+ if (((block[block.length - 1] & 0xF) ^ 0xC) != 0)
+ {
+ return returnFalse(block);
+ }
+
+ int delta = 0;
+
+ if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0)
+ {
+ delta = 1;
+ }
+ else
+ {
+ int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF);
+ Integer trailerObj = (Integer)trailerMap.get(digest.getAlgorithmName());
+
+ if (trailerObj != null)
+ {
+ if (sigTrail != trailerObj.intValue())
+ {
+ throw new IllegalStateException("signer initialised with wrong digest for trailer " + sigTrail);
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("unrecognised hash in signature");
+ }
+
+ delta = 2;
+ }
+
+ //
+ // find out how much padding we've got
+ //
+ int mStart = 0;
+
+ for (mStart = 0; mStart != block.length; mStart++)
+ {
+ if (((block[mStart] & 0x0f) ^ 0x0a) == 0)
+ {
+ break;
+ }
+ }
+
+ mStart++;
+
+ //
+ // check the hashes
+ //
+ byte[] hash = new byte[digest.getDigestSize()];
+
+ int off = block.length - delta - hash.length;
+
+ //
+ // there must be at least one byte of message string
+ //
+ if ((off - mStart) <= 0)
+ {
+ return returnFalse(block);
+ }
+
+ //
+ // if we contain the whole message as well, check the hash of that.
+ //
+ if ((block[0] & 0x20) == 0)
+ {
+ fullMessage = true;
+
+ // check right number of bytes passed in.
+ if (messageLength > off - mStart)
+ {
+ return returnFalse(block);
+ }
+
+ digest.reset();
+ digest.update(block, mStart, off - mStart);
+ digest.doFinal(hash, 0);
+
+ boolean isOkay = true;
+
+ for (int i = 0; i != hash.length; i++)
+ {
+ block[off + i] ^= hash[i];
+ if (block[off + i] != 0)
+ {
+ isOkay = false;
+ }
+ }
+
+ if (!isOkay)
+ {
+ return returnFalse(block);
+ }
+
+ recoveredMessage = new byte[off - mStart];
+ System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
+ }
+ else
+ {
+ fullMessage = false;
+
+ digest.doFinal(hash, 0);
+
+ boolean isOkay = true;
+
+ for (int i = 0; i != hash.length; i++)
+ {
+ block[off + i] ^= hash[i];
+ if (block[off + i] != 0)
+ {
+ isOkay = false;
+ }
+ }
+
+ if (!isOkay)
+ {
+ return returnFalse(block);
+ }
+
+ recoveredMessage = new byte[off - mStart];
+ System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length);
+ }
+
+ //
+ // if they've input a message check what we've recovered against
+ // what was input.
+ //
+ if (messageLength != 0 && !updateWithRecoveredCalled)
+ {
+ if (!isSameAs(mBuf, recoveredMessage))
+ {
+ return returnFalse(block);
+ }
+ }
+
+ clearBlock(mBuf);
+ clearBlock(block);
+
+ return true;
+ }
+
+ private boolean returnFalse(byte[] block)
+ {
+ clearBlock(mBuf);
+ clearBlock(block);
+
+ return false;
+ }
+
+ /**
+ * Return true if the full message was recoveredMessage.
+ *
+ * @return true on full message recovery, false otherwise.
+ * @see pdftk.org.bouncycastle.crypto.SignerWithRecovery#hasFullMessage()
+ */
+ public boolean hasFullMessage()
+ {
+ return fullMessage;
+ }
+
+ /**
+ * Return a reference to the recoveredMessage message.
+ *
+ * @return the full/partial recoveredMessage message.
+ * @see pdftk.org.bouncycastle.crypto.SignerWithRecovery#getRecoveredMessage()
+ */
+ public byte[] getRecoveredMessage()
+ {
+ return recoveredMessage;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/PSSSigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/PSSSigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/PSSSigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/PSSSigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,348 @@
+package pdftk.org.bouncycastle.crypto.signers;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.Signer;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.crypto.params.RSABlindingParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+
+/**
+ * RSA-PSS as described in PKCS# 1 v 2.1.
+ *
+ * Note: the usual value for the salt length is the number of
+ * bytes in the hash function.
+ */
+public class PSSSigner
+ implements Signer
+{
+ static final public byte TRAILER_IMPLICIT = (byte)0xBC;
+
+ private Digest contentDigest;
+ private Digest mgfDigest;
+ private AsymmetricBlockCipher cipher;
+ private SecureRandom random;
+
+ private int hLen;
+ private int mgfhLen;
+ private int sLen;
+ private int emBits;
+ private byte[] salt;
+ private byte[] mDash;
+ private byte[] block;
+ private byte trailer;
+
+ /**
+ * basic constructor
+ *
+ * @param cipher the asymmetric cipher to use.
+ * @param digest the digest to use.
+ * @param sLen the length of the salt to use (in bytes).
+ */
+ public PSSSigner(
+ AsymmetricBlockCipher cipher,
+ Digest digest,
+ int sLen)
+ {
+ this(cipher, digest, sLen, TRAILER_IMPLICIT);
+ }
+
+ public PSSSigner(
+ AsymmetricBlockCipher cipher,
+ Digest contentDigest,
+ Digest mgfDigest,
+ int sLen)
+ {
+ this(cipher, contentDigest, mgfDigest, sLen, TRAILER_IMPLICIT);
+ }
+
+ public PSSSigner(
+ AsymmetricBlockCipher cipher,
+ Digest digest,
+ int sLen,
+ byte trailer)
+ {
+ this(cipher, digest, digest, sLen, trailer);
+ }
+
+ public PSSSigner(
+ AsymmetricBlockCipher cipher,
+ Digest contentDigest,
+ Digest mgfDigest,
+ int sLen,
+ byte trailer)
+ {
+ this.cipher = cipher;
+ this.contentDigest = contentDigest;
+ this.mgfDigest = mgfDigest;
+ this.hLen = contentDigest.getDigestSize();
+ this.mgfhLen = mgfDigest.getDigestSize();
+ this.sLen = sLen;
+ this.salt = new byte[sLen];
+ this.mDash = new byte[8 + sLen + hLen];
+ this.trailer = trailer;
+ }
+
+ public void init(
+ boolean forSigning,
+ CipherParameters param)
+ {
+ CipherParameters params;
+
+ if (param instanceof ParametersWithRandom)
+ {
+ ParametersWithRandom p = (ParametersWithRandom)param;
+
+ params = p.getParameters();
+ random = p.getRandom();
+ }
+ else
+ {
+ params = param;
+ if (forSigning)
+ {
+ random = new SecureRandom();
+ }
+ }
+
+ cipher.init(forSigning, params);
+
+ RSAKeyParameters kParam;
+
+ if (params instanceof RSABlindingParameters)
+ {
+ kParam = ((RSABlindingParameters)params).getPublicKey();
+ }
+ else
+ {
+ kParam = (RSAKeyParameters)params;
+ }
+
+ emBits = kParam.getModulus().bitLength() - 1;
+
+ if (emBits < (8 * hLen + 8 * sLen + 9))
+ {
+ throw new IllegalArgumentException("key too small for specified hash and salt lengths");
+ }
+
+ block = new byte[(emBits + 7) / 8];
+
+ reset();
+ }
+
+ /**
+ * clear possible sensitive data
+ */
+ private void clearBlock(
+ byte[] block)
+ {
+ for (int i = 0; i != block.length; i++)
+ {
+ block[i] = 0;
+ }
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte b)
+ {
+ contentDigest.update(b);
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] in,
+ int off,
+ int len)
+ {
+ contentDigest.update(in, off, len);
+ }
+
+ /**
+ * reset the internal state
+ */
+ public void reset()
+ {
+ contentDigest.reset();
+ }
+
+ /**
+ * generate a signature for the message we've been loaded with using
+ * the key we were initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException, DataLengthException
+ {
+ contentDigest.doFinal(mDash, mDash.length - hLen - sLen);
+
+ if (sLen != 0)
+ {
+ random.nextBytes(salt);
+
+ System.arraycopy(salt, 0, mDash, mDash.length - sLen, sLen);
+ }
+
+ byte[] h = new byte[hLen];
+
+ contentDigest.update(mDash, 0, mDash.length);
+
+ contentDigest.doFinal(h, 0);
+
+ block[block.length - sLen - 1 - hLen - 1] = 0x01;
+ System.arraycopy(salt, 0, block, block.length - sLen - hLen - 1, sLen);
+
+ byte[] dbMask = maskGeneratorFunction1(h, 0, h.length, block.length - hLen - 1);
+ for (int i = 0; i != dbMask.length; i++)
+ {
+ block[i] ^= dbMask[i];
+ }
+
+ block[0] &= (0xff >> ((block.length * 8) - emBits));
+
+ System.arraycopy(h, 0, block, block.length - hLen - 1, hLen);
+
+ block[block.length - 1] = trailer;
+
+ byte[] b = cipher.processBlock(block, 0, block.length);
+
+ clearBlock(block);
+
+ return b;
+ }
+
+ /**
+ * return true if the internal state represents the signature described
+ * in the passed in array.
+ */
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ contentDigest.doFinal(mDash, mDash.length - hLen - sLen);
+
+ try
+ {
+ byte[] b = cipher.processBlock(signature, 0, signature.length);
+ System.arraycopy(b, 0, block, block.length - b.length, b.length);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ if (block[block.length - 1] != trailer)
+ {
+ clearBlock(block);
+ return false;
+ }
+
+ byte[] dbMask = maskGeneratorFunction1(block, block.length - hLen - 1, hLen, block.length - hLen - 1);
+
+ for (int i = 0; i != dbMask.length; i++)
+ {
+ block[i] ^= dbMask[i];
+ }
+
+ block[0] &= (0xff >> ((block.length * 8) - emBits));
+
+ for (int i = 0; i != block.length - hLen - sLen - 2; i++)
+ {
+ if (block[i] != 0)
+ {
+ clearBlock(block);
+ return false;
+ }
+ }
+
+ if (block[block.length - hLen - sLen - 2] != 0x01)
+ {
+ clearBlock(block);
+ return false;
+ }
+
+ System.arraycopy(block, block.length - sLen - hLen - 1, mDash, mDash.length - sLen, sLen);
+
+ contentDigest.update(mDash, 0, mDash.length);
+ contentDigest.doFinal(mDash, mDash.length - hLen);
+
+ for (int i = block.length - hLen - 1, j = mDash.length - hLen;
+ j != mDash.length; i++, j++)
+ {
+ if ((block[i] ^ mDash[j]) != 0)
+ {
+ clearBlock(mDash);
+ clearBlock(block);
+ return false;
+ }
+ }
+
+ clearBlock(mDash);
+ clearBlock(block);
+
+ return true;
+ }
+
+ /**
+ * int to octet string.
+ */
+ private void ItoOSP(
+ int i,
+ byte[] sp)
+ {
+ sp[0] = (byte)(i >>> 24);
+ sp[1] = (byte)(i >>> 16);
+ sp[2] = (byte)(i >>> 8);
+ sp[3] = (byte)(i >>> 0);
+ }
+
+ /**
+ * mask generator function, as described in PKCS1v2.
+ */
+ private byte[] maskGeneratorFunction1(
+ byte[] Z,
+ int zOff,
+ int zLen,
+ int length)
+ {
+ byte[] mask = new byte[length];
+ byte[] hashBuf = new byte[mgfhLen];
+ byte[] C = new byte[4];
+ int counter = 0;
+
+ mgfDigest.reset();
+
+ while (counter < (length / mgfhLen))
+ {
+ ItoOSP(counter, C);
+
+ mgfDigest.update(Z, zOff, zLen);
+ mgfDigest.update(C, 0, C.length);
+ mgfDigest.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, mask, counter * mgfhLen, mgfhLen);
+
+ counter++;
+ }
+
+ if ((counter * mgfhLen) < length)
+ {
+ ItoOSP(counter, C);
+
+ mgfDigest.update(Z, zOff, zLen);
+ mgfDigest.update(C, 0, C.length);
+ mgfDigest.doFinal(hashBuf, 0);
+
+ System.arraycopy(hashBuf, 0, mask, counter * mgfhLen, mask.length - (counter * mgfhLen));
+ }
+
+ return mask;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/RSADigestSigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/RSADigestSigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/RSADigestSigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/RSADigestSigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,232 @@
+package pdftk.org.bouncycastle.crypto.signers;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encoding;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.DERNull;
+import pdftk.org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import pdftk.org.bouncycastle.asn1.x509.DigestInfo;
+import pdftk.org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
+import pdftk.org.bouncycastle.crypto.AsymmetricBlockCipher;
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.DataLengthException;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.Signer;
+import pdftk.org.bouncycastle.crypto.encodings.PKCS1Encoding;
+import pdftk.org.bouncycastle.crypto.engines.RSABlindedEngine;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class RSADigestSigner
+ implements Signer
+{
+ private final AsymmetricBlockCipher rsaEngine = new PKCS1Encoding(new RSABlindedEngine());
+ private final AlgorithmIdentifier algId;
+ private final Digest digest;
+ private boolean forSigning;
+
+ private static final Hashtable oidMap = new Hashtable();
+
+ /*
+ * Load OID table.
+ */
+ static
+ {
+ oidMap.put("RIPEMD128", TeleTrusTObjectIdentifiers.ripemd128);
+ oidMap.put("RIPEMD160", TeleTrusTObjectIdentifiers.ripemd160);
+ oidMap.put("RIPEMD256", TeleTrusTObjectIdentifiers.ripemd256);
+
+ oidMap.put("SHA-1", X509ObjectIdentifiers.id_SHA1);
+ oidMap.put("SHA-224", NISTObjectIdentifiers.id_sha224);
+ oidMap.put("SHA-256", NISTObjectIdentifiers.id_sha256);
+ oidMap.put("SHA-384", NISTObjectIdentifiers.id_sha384);
+ oidMap.put("SHA-512", NISTObjectIdentifiers.id_sha512);
+
+ oidMap.put("MD2", PKCSObjectIdentifiers.md2);
+ oidMap.put("MD4", PKCSObjectIdentifiers.md4);
+ oidMap.put("MD5", PKCSObjectIdentifiers.md5);
+ }
+
+ public RSADigestSigner(
+ Digest digest)
+ {
+ this.digest = digest;
+
+ algId = new AlgorithmIdentifier((ASN1ObjectIdentifier)oidMap.get(digest.getAlgorithmName()), DERNull.INSTANCE);
+ }
+
+ /**
+ * @deprecated
+ */
+ public String getAlgorithmName()
+ {
+ return digest.getAlgorithmName() + "withRSA";
+ }
+
+ /**
+ * initialise the signer for signing or verification.
+ *
+ * @param forSigning
+ * true if for signing, false otherwise
+ * @param parameters
+ * necessary parameters.
+ */
+ public void init(
+ boolean forSigning,
+ CipherParameters parameters)
+ {
+ this.forSigning = forSigning;
+ AsymmetricKeyParameter k;
+
+ if (parameters instanceof ParametersWithRandom)
+ {
+ k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters();
+ }
+ else
+ {
+ k = (AsymmetricKeyParameter)parameters;
+ }
+
+ if (forSigning && !k.isPrivate())
+ {
+ throw new IllegalArgumentException("signing requires private key");
+ }
+
+ if (!forSigning && k.isPrivate())
+ {
+ throw new IllegalArgumentException("verification requires public key");
+ }
+
+ reset();
+
+ rsaEngine.init(forSigning, parameters);
+ }
+
+ /**
+ * update the internal digest with the byte b
+ */
+ public void update(
+ byte input)
+ {
+ digest.update(input);
+ }
+
+ /**
+ * update the internal digest with the byte array in
+ */
+ public void update(
+ byte[] input,
+ int inOff,
+ int length)
+ {
+ digest.update(input, inOff, length);
+ }
+
+ /**
+ * Generate a signature for the message we've been loaded with using the key
+ * we were initialised with.
+ */
+ public byte[] generateSignature()
+ throws CryptoException, DataLengthException
+ {
+ if (!forSigning)
+ {
+ throw new IllegalStateException("RSADigestSigner not initialised for signature generation.");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+ digest.doFinal(hash, 0);
+
+ try
+ {
+ byte[] data = derEncode(hash);
+ return rsaEngine.processBlock(data, 0, data.length);
+ }
+ catch (IOException e)
+ {
+ throw new CryptoException("unable to encode signature: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * return true if the internal state represents the signature described in
+ * the passed in array.
+ */
+ public boolean verifySignature(
+ byte[] signature)
+ {
+ if (forSigning)
+ {
+ throw new IllegalStateException("RSADigestSigner not initialised for verification");
+ }
+
+ byte[] hash = new byte[digest.getDigestSize()];
+
+ digest.doFinal(hash, 0);
+
+ byte[] sig;
+ byte[] expected;
+
+ try
+ {
+ sig = rsaEngine.processBlock(signature, 0, signature.length);
+ expected = derEncode(hash);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ if (sig.length == expected.length)
+ {
+ return Arrays.constantTimeAreEqual(sig, expected);
+ }
+ else if (sig.length == expected.length - 2) // NULL left out
+ {
+ int sigOffset = sig.length - hash.length - 2;
+ int expectedOffset = expected.length - hash.length - 2;
+
+ expected[1] -= 2; // adjust lengths
+ expected[3] -= 2;
+
+ int nonEqual = 0;
+
+ for (int i = 0; i < hash.length; i++)
+ {
+ nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]);
+ }
+
+ for (int i = 0; i < sigOffset; i++)
+ {
+ nonEqual |= (sig[i] ^ expected[i]); // check header less NULL
+ }
+
+ return nonEqual == 0;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public void reset()
+ {
+ digest.reset();
+ }
+
+ private byte[] derEncode(
+ byte[] hash)
+ throws IOException
+ {
+ DigestInfo dInfo = new DigestInfo(algId, hash);
+
+ return dInfo.getEncoded(ASN1Encoding.DER);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/signers/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/signers/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Basic signers.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/AlertDescription.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/AlertDescription.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/AlertDescription.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/AlertDescription.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,47 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * RFC 2246 7.2
+ */
+public class AlertDescription
+{
+ public static final short close_notify = 0;
+ public static final short unexpected_message = 10;
+ public static final short bad_record_mac = 20;
+ public static final short decryption_failed = 21;
+ public static final short record_overflow = 22;
+ public static final short decompression_failure = 30;
+ public static final short handshake_failure = 40;
+ /* no_certificate(41) is specific to SSLv3 */
+ public static final short no_certificate = 41;
+ public static final short bad_certificate = 42;
+ public static final short unsupported_certificate = 43;
+ public static final short certificate_revoked = 44;
+ public static final short certificate_expired = 45;
+ public static final short certificate_unknown = 46;
+ public static final short illegal_parameter = 47;
+ public static final short unknown_ca = 48;
+ public static final short access_denied = 49;
+ public static final short decode_error = 50;
+ public static final short decrypt_error = 51;
+ public static final short export_restriction = 60;
+ public static final short protocol_version = 70;
+ public static final short insufficient_security = 71;
+ public static final short internal_error = 80;
+ public static final short user_canceled = 90;
+ public static final short no_renegotiation = 100;
+
+ /*
+ * RFC 3546
+ */
+ public static final short unsupported_extension = 110;
+ public static final short certificate_unobtainable = 111;
+ public static final short unrecognized_name = 112;
+ public static final short bad_certificate_status_response = 113;
+ public static final short bad_certificate_hash_value = 114;
+
+ /*
+ * RFC 4279
+ */
+ public static final short unknown_psk_identity = 115;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/AlertLevel.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/AlertLevel.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/AlertLevel.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/AlertLevel.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,10 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * RFC 2246 7.2
+ */
+public class AlertLevel
+{
+ public static final short warning = 1;
+ public static final short fatal = 2;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/AlwaysValidVerifyer.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/AlwaysValidVerifyer.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/AlwaysValidVerifyer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/AlwaysValidVerifyer.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * A certificate verifyer, that will always return true.
+ *
+ *
+ * DO NOT USE THIS FILE UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING.
+ *
+ *
+ * @deprecated Perform certificate verification in TlsAuthentication implementation
+ */
+public class AlwaysValidVerifyer implements CertificateVerifyer
+{
+ /**
+ * Return true.
+ *
+ * @see pdftk.org.bouncycastle.crypto.tls.CertificateVerifyer#isValid(pdftk.org.bouncycastle.asn1.x509.Certificate[])
+ */
+ public boolean isValid(pdftk.org.bouncycastle.asn1.x509.Certificate[] certs)
+ {
+ return true;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ByteQueue.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ByteQueue.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ByteQueue.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ByteQueue.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,123 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * A queue for bytes. This file could be more optimized.
+ */
+public class ByteQueue
+{
+ /**
+ * @return The smallest number which can be written as 2^x which is bigger than i.
+ */
+ public static final int nextTwoPow(int i)
+ {
+ /*
+ * This code is based of a lot of code I found on the Internet which mostly
+ * referenced a book called "Hacking delight".
+ */
+ i |= (i >> 1);
+ i |= (i >> 2);
+ i |= (i >> 4);
+ i |= (i >> 8);
+ i |= (i >> 16);
+ return i + 1;
+ }
+
+ /**
+ * The initial size for our buffer.
+ */
+ private static final int INITBUFSIZE = 1024;
+
+ /**
+ * The buffer where we store our data.
+ */
+ private byte[] databuf = new byte[ByteQueue.INITBUFSIZE];
+
+ /**
+ * How many bytes at the beginning of the buffer are skipped.
+ */
+ private int skipped = 0;
+
+ /**
+ * How many bytes in the buffer are valid data.
+ */
+ private int available = 0;
+
+ /**
+ * Read data from the buffer.
+ *
+ * @param buf The buffer where the read data will be copied to.
+ * @param offset How many bytes to skip at the beginning of buf.
+ * @param len How many bytes to read at all.
+ * @param skip How many bytes from our data to skip.
+ */
+ public void read(byte[] buf, int offset, int len, int skip)
+ {
+ if ((available - skip) < len)
+ {
+ throw new TlsRuntimeException("Not enough data to read");
+ }
+ if ((buf.length - offset) < len)
+ {
+ throw new TlsRuntimeException("Buffer size of " + buf.length
+ + " is too small for a read of " + len + " bytes");
+ }
+ System.arraycopy(databuf, skipped + skip, buf, offset, len);
+ return;
+ }
+
+ /**
+ * Add some data to our buffer.
+ *
+ * @param data A byte-array to read data from.
+ * @param offset How many bytes to skip at the beginning of the array.
+ * @param len How many bytes to read from the array.
+ */
+ public void addData(byte[] data, int offset, int len)
+ {
+ if ((skipped + available + len) > databuf.length)
+ {
+ byte[] tmp = new byte[ByteQueue.nextTwoPow(data.length)];
+ System.arraycopy(databuf, skipped, tmp, 0, available);
+ skipped = 0;
+ databuf = tmp;
+ }
+ System.arraycopy(data, offset, databuf, skipped + available, len);
+ available += len;
+ }
+
+ /**
+ * Remove some bytes from our data from the beginning.
+ *
+ * @param i How many bytes to remove.
+ */
+ public void removeData(int i)
+ {
+ if (i > available)
+ {
+ throw new TlsRuntimeException("Cannot remove " + i + " bytes, only got " + available);
+ }
+
+ /*
+ * Skip the data.
+ */
+ available -= i;
+ skipped += i;
+
+ /*
+ * If more than half of our data is skipped, we will move the data in the buffer.
+ */
+ if (skipped > (databuf.length / 2))
+ {
+ System.arraycopy(databuf, skipped, databuf, 0, available);
+ skipped = 0;
+ }
+ }
+
+ /**
+ * @return The number of bytes which are available in this buffer.
+ */
+ public int size()
+ {
+ return available;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/Certificate.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/Certificate.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/Certificate.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/Certificate.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,120 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encoding;
+import pdftk.org.bouncycastle.asn1.ASN1InputStream;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+
+/**
+ * A representation for a certificate chain as used by a tls server.
+ */
+public class Certificate
+{
+ public static final Certificate EMPTY_CHAIN = new Certificate(new pdftk.org.bouncycastle.asn1.x509.Certificate[0]);
+
+ /**
+ * The certificates.
+ */
+ protected pdftk.org.bouncycastle.asn1.x509.Certificate[] certs;
+
+ /**
+ * Parse the ServerCertificate message.
+ *
+ * @param is The stream where to parse from.
+ * @return A Certificate object with the certs, the server has sended.
+ * @throws IOException If something goes wrong during parsing.
+ */
+ protected static Certificate parse(InputStream is) throws IOException
+ {
+ pdftk.org.bouncycastle.asn1.x509.Certificate[] certs;
+ int left = TlsUtils.readUint24(is);
+ if (left == 0)
+ {
+ return EMPTY_CHAIN;
+ }
+ Vector tmp = new Vector();
+ while (left > 0)
+ {
+ int size = TlsUtils.readUint24(is);
+ left -= 3 + size;
+ byte[] buf = new byte[size];
+ TlsUtils.readFully(buf, is);
+ ByteArrayInputStream bis = new ByteArrayInputStream(buf);
+ ASN1InputStream ais = new ASN1InputStream(bis);
+ ASN1Primitive o = ais.readObject();
+ tmp.addElement(pdftk.org.bouncycastle.asn1.x509.Certificate.getInstance(o));
+ if (bis.available() > 0)
+ {
+ throw new IllegalArgumentException(
+ "Sorry, there is garbage data left after the certificate");
+ }
+ }
+ certs = new pdftk.org.bouncycastle.asn1.x509.Certificate[tmp.size()];
+ for (int i = 0; i < tmp.size(); i++)
+ {
+ certs[i] = (pdftk.org.bouncycastle.asn1.x509.Certificate)tmp.elementAt(i);
+ }
+ return new Certificate(certs);
+ }
+
+ /**
+ * Encodes version of the ClientCertificate message
+ *
+ * @param os stream to write the message to
+ * @throws IOException If something goes wrong
+ */
+ protected void encode(OutputStream os) throws IOException
+ {
+ Vector encCerts = new Vector();
+ int totalSize = 0;
+ for (int i = 0; i < this.certs.length; ++i)
+ {
+ byte[] encCert = certs[i].getEncoded(ASN1Encoding.DER);
+ encCerts.addElement(encCert);
+ totalSize += encCert.length + 3;
+ }
+
+ TlsUtils.writeUint24(totalSize, os);
+
+ for (int i = 0; i < encCerts.size(); ++i)
+ {
+ byte[] encCert = (byte[])encCerts.elementAt(i);
+ TlsUtils.writeOpaque24(encCert, os);
+ }
+ }
+
+ /**
+ * Private constructor from a cert array.
+ *
+ * @param certs The certs the chain should contain.
+ */
+ public Certificate(pdftk.org.bouncycastle.asn1.x509.Certificate[] certs)
+ {
+ if (certs == null)
+ {
+ throw new IllegalArgumentException("'certs' cannot be null");
+ }
+
+ this.certs = certs;
+ }
+
+ /**
+ * @return An array which contains the certs, this chain contains.
+ */
+ public pdftk.org.bouncycastle.asn1.x509.Certificate[] getCerts()
+ {
+ pdftk.org.bouncycastle.asn1.x509.Certificate[] result = new pdftk.org.bouncycastle.asn1.x509.Certificate[certs.length];
+ System.arraycopy(certs, 0, result, 0, certs.length);
+ return result;
+ }
+
+ public boolean isEmpty()
+ {
+ return certs.length == 0;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/CertificateRequest.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/CertificateRequest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/CertificateRequest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/CertificateRequest.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,28 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.util.Vector;
+
+public class CertificateRequest
+{
+ private short[] certificateTypes;
+ private Vector certificateAuthorities;
+
+ public CertificateRequest(short[] certificateTypes, Vector certificateAuthorities)
+ {
+ this.certificateTypes = certificateTypes;
+ this.certificateAuthorities = certificateAuthorities;
+ }
+
+ public short[] getCertificateTypes()
+ {
+ return certificateTypes;
+ }
+
+ /**
+ * @return Vector of X500Name
+ */
+ public Vector getCertificateAuthorities()
+ {
+ return certificateAuthorities;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/CertificateVerifyer.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/CertificateVerifyer.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/CertificateVerifyer.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/CertificateVerifyer.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,16 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * This should be implemented by any class which can find out, if a given certificate
+ * chain is being accepted by an client.
+ *
+ * @deprecated Perform certificate verification in TlsAuthentication implementation
+ */
+public interface CertificateVerifyer
+{
+ /**
+ * @param certs The certs, which are part of the chain.
+ * @return True, if the chain is accepted, false otherwise.
+ */
+ public boolean isValid(pdftk.org.bouncycastle.asn1.x509.Certificate[] certs);
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/CipherSuite.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/CipherSuite.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/CipherSuite.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/CipherSuite.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,135 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * RFC 2246 A.5
+ */
+public class CipherSuite
+{
+ public static final int TLS_NULL_WITH_NULL_NULL = 0x0000;
+ public static final int TLS_RSA_WITH_NULL_MD5 = 0x0001;
+ public static final int TLS_RSA_WITH_NULL_SHA = 0x0002;
+ public static final int TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003;
+ public static final int TLS_RSA_WITH_RC4_128_MD5 = 0x0004;
+ public static final int TLS_RSA_WITH_RC4_128_SHA = 0x0005;
+ public static final int TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006;
+ public static final int TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007;
+ public static final int TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008;
+ public static final int TLS_RSA_WITH_DES_CBC_SHA = 0x0009;
+ public static final int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A;
+ public static final int TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000B;
+ public static final int TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000C;
+ public static final int TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D;
+ public static final int TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000E;
+ public static final int TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000F;
+ public static final int TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010;
+ public static final int TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011;
+ public static final int TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012;
+ public static final int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013;
+ public static final int TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014;
+ public static final int TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015;
+ public static final int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016;
+ public static final int TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017;
+ public static final int TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018;
+ public static final int TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x0019;
+ public static final int TLS_DH_anon_WITH_DES_CBC_SHA = 0x001A;
+ public static final int TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B;
+
+ /*
+ * RFC 3268
+ */
+ public static final int TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F;
+ public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030;
+ public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031;
+ public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032;
+ public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033;
+ public static final int TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034;
+ public static final int TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035;
+ public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036;
+ public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037;
+ public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038;
+ public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039;
+ public static final int TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A;
+
+ /*
+ * RFC 4279
+ */
+ public static final int TLS_PSK_WITH_RC4_128_SHA = 0x008A;
+ public static final int TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B;
+ public static final int TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C;
+ public static final int TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D;
+ public static final int TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E;
+ public static final int TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F;
+ public static final int TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090;
+ public static final int TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091;
+ public static final int TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092;
+ public static final int TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093;
+ public static final int TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094;
+ public static final int TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095;
+
+ /*
+ * RFC 4492
+ */
+ public static final int TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001;
+ public static final int TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002;
+ public static final int TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003;
+ public static final int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004;
+ public static final int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005;
+ public static final int TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006;
+ public static final int TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007;
+ public static final int TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008;
+ public static final int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009;
+ public static final int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A;
+ public static final int TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B;
+ public static final int TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C;
+ public static final int TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D;
+ public static final int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E;
+ public static final int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F;
+ public static final int TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010;
+ public static final int TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011;
+ public static final int TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012;
+ public static final int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013;
+ public static final int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014;
+ public static final int TLS_ECDH_anon_WITH_NULL_SHA = 0xC015;
+ public static final int TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016;
+ public static final int TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017;
+ public static final int TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018;
+ public static final int TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019;
+
+ /*
+ * RFC 5054
+ */
+ public static final int TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A;
+ public static final int TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B;
+ public static final int TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 0xC01C;
+ public static final int TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D;
+ public static final int TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E;
+ public static final int TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 0xC01F;
+ public static final int TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020;
+ public static final int TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021;
+ public static final int TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022;
+
+ /*
+ * RFC 5289
+ */
+ public static final int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023;
+ public static final int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024;
+ public static final int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025;
+ public static final int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026;
+ public static final int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027;
+ public static final int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028;
+ public static final int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029;
+ public static final int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A;
+ public static final int TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B;
+ public static final int TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C;
+ public static final int TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D;
+ public static final int TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E;
+ public static final int TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F;
+ public static final int TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030;
+ public static final int TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031;
+ public static final int TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032;
+
+ /*
+ * RFC 5746
+ */
+ public static final int TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ClientCertificateType.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ClientCertificateType.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ClientCertificateType.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ClientCertificateType.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,19 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * RFC 2246 7.4.4
+ */
+public class ClientCertificateType
+{
+ public static final short rsa_sign = 1;
+ public static final short dss_sign = 2;
+ public static final short rsa_fixed_dh = 3;
+ public static final short dss_fixed_dh = 4;
+
+ /*
+ * RFC 4492 5.5
+ */
+ public static final short ecdsa_sign = 64;
+ public static final short rsa_fixed_ecdh = 65;
+ public static final short ecdsa_fixed_ecdh = 66;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/CombinedHash.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/CombinedHash.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/CombinedHash.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/CombinedHash.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,114 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.digests.MD5Digest;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+
+/**
+ * A combined hash, which implements md5(m) || sha1(m).
+ */
+class CombinedHash implements Digest
+{
+ protected TlsClientContext context;
+ protected MD5Digest md5;
+ protected SHA1Digest sha1;
+
+ CombinedHash()
+ {
+ this.md5 = new MD5Digest();
+ this.sha1 = new SHA1Digest();
+ }
+
+ CombinedHash(TlsClientContext context)
+ {
+ this.context = context;
+ this.md5 = new MD5Digest();
+ this.sha1 = new SHA1Digest();
+ }
+
+ CombinedHash(CombinedHash t)
+ {
+ this.context = t.context;
+ this.md5 = new MD5Digest(t.md5);
+ this.sha1 = new SHA1Digest(t.sha1);
+ }
+
+ /**
+ * @see pdftk.org.bouncycastle.crypto.Digest#getAlgorithmName()
+ */
+ public String getAlgorithmName()
+ {
+ return md5.getAlgorithmName() + " and " + sha1.getAlgorithmName();
+ }
+
+ /**
+ * @see pdftk.org.bouncycastle.crypto.Digest#getDigestSize()
+ */
+ public int getDigestSize()
+ {
+ return 16 + 20;
+ }
+
+ /**
+ * @see pdftk.org.bouncycastle.crypto.Digest#update(byte)
+ */
+ public void update(byte in)
+ {
+ md5.update(in);
+ sha1.update(in);
+ }
+
+ /**
+ * @see pdftk.org.bouncycastle.crypto.Digest#update(byte[],int,int)
+ */
+ public void update(byte[] in, int inOff, int len)
+ {
+ md5.update(in, inOff, len);
+ sha1.update(in, inOff, len);
+ }
+
+ /**
+ * @see pdftk.org.bouncycastle.crypto.Digest#doFinal(byte[],int)
+ */
+ public int doFinal(byte[] out, int outOff)
+ {
+ if (context != null)
+ {
+ boolean isTls = context.getServerVersion().getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+
+ if (!isTls)
+ {
+ ssl3Complete(md5, SSL3Mac.MD5_IPAD, SSL3Mac.MD5_OPAD);
+ ssl3Complete(sha1, SSL3Mac.SHA1_IPAD, SSL3Mac.SHA1_OPAD);
+ }
+ }
+
+ int i1 = md5.doFinal(out, outOff);
+ int i2 = sha1.doFinal(out, outOff + 16);
+ return i1 + i2;
+ }
+
+ /**
+ * @see pdftk.org.bouncycastle.crypto.Digest#reset()
+ */
+ public void reset()
+ {
+ md5.reset();
+ sha1.reset();
+ }
+
+ protected void ssl3Complete(Digest d, byte[] ipad, byte[] opad)
+ {
+ byte[] secret = context.getSecurityParameters().masterSecret;
+
+ d.update(secret, 0, secret.length);
+ d.update(ipad, 0, ipad.length);
+
+ byte[] tmp = new byte[d.getDigestSize()];
+ d.doFinal(tmp, 0);
+
+ d.update(secret, 0, secret.length);
+ d.update(opad, 0, opad.length);
+ d.update(tmp, 0, tmp.length);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/CompressionMethod.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/CompressionMethod.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/CompressionMethod.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/CompressionMethod.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,19 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * RFC 2246 6.1
+ */
+public class CompressionMethod
+{
+ public static final short NULL = 0;
+
+ /*
+ * RFC 3749 2
+ */
+ public static final short DEFLATE = 1;
+
+ /*
+ * Values from 224 decimal (0xE0) through 255 decimal (0xFF)
+ * inclusive are reserved for private use.
+ */
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ContentType.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ContentType.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ContentType.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ContentType.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,12 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * RFC 2246 6.2.1
+ */
+public class ContentType
+{
+ public static final short change_cipher_spec = 20;
+ public static final short alert = 21;
+ public static final short handshake = 22;
+ public static final short application_data = 23;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsAgreementCredentials.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,68 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.BasicAgreement;
+import pdftk.org.bouncycastle.crypto.agreement.DHBasicAgreement;
+import pdftk.org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.DHPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+public class DefaultTlsAgreementCredentials implements TlsAgreementCredentials
+{
+ protected Certificate clientCert;
+ protected AsymmetricKeyParameter clientPrivateKey;
+
+ protected BasicAgreement basicAgreement;
+
+ public DefaultTlsAgreementCredentials(Certificate clientCertificate, AsymmetricKeyParameter clientPrivateKey)
+ {
+ if (clientCertificate == null)
+ {
+ throw new IllegalArgumentException("'clientCertificate' cannot be null");
+ }
+ if (clientCertificate.certs.length == 0)
+ {
+ throw new IllegalArgumentException("'clientCertificate' cannot be empty");
+ }
+ if (clientPrivateKey == null)
+ {
+ throw new IllegalArgumentException("'clientPrivateKey' cannot be null");
+ }
+ if (!clientPrivateKey.isPrivate())
+ {
+ throw new IllegalArgumentException("'clientPrivateKey' must be private");
+ }
+
+ if (clientPrivateKey instanceof DHPrivateKeyParameters)
+ {
+ basicAgreement = new DHBasicAgreement();
+ }
+ else if (clientPrivateKey instanceof ECPrivateKeyParameters)
+ {
+ basicAgreement = new ECDHBasicAgreement();
+ }
+ else
+ {
+ throw new IllegalArgumentException("'clientPrivateKey' type not supported: "
+ + clientPrivateKey.getClass().getName());
+ }
+
+ this.clientCert = clientCertificate;
+ this.clientPrivateKey = clientPrivateKey;
+ }
+
+ public Certificate getCertificate()
+ {
+ return clientCert;
+ }
+
+ public byte[] generateAgreement(AsymmetricKeyParameter serverPublicKey)
+ {
+ basicAgreement.init(clientPrivateKey);
+ BigInteger agreementValue = basicAgreement.calculateAgreement(serverPublicKey);
+ return BigIntegers.asUnsignedByteArray(agreementValue);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsCipherFactory.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,85 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.StreamCipher;
+import pdftk.org.bouncycastle.crypto.digests.MD5Digest;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+import pdftk.org.bouncycastle.crypto.digests.SHA256Digest;
+import pdftk.org.bouncycastle.crypto.digests.SHA384Digest;
+import pdftk.org.bouncycastle.crypto.engines.AESFastEngine;
+import pdftk.org.bouncycastle.crypto.engines.DESedeEngine;
+import pdftk.org.bouncycastle.crypto.engines.RC4Engine;
+import pdftk.org.bouncycastle.crypto.modes.CBCBlockCipher;
+
+public class DefaultTlsCipherFactory implements TlsCipherFactory
+{
+ public TlsCipher createCipher(TlsClientContext context, int encryptionAlgorithm, int digestAlgorithm) throws IOException
+ {
+ switch (encryptionAlgorithm)
+ {
+ case EncryptionAlgorithm._3DES_EDE_CBC:
+ return createDESedeCipher(context, 24, digestAlgorithm);
+ case EncryptionAlgorithm.AES_128_CBC:
+ return createAESCipher(context, 16, digestAlgorithm);
+ case EncryptionAlgorithm.AES_256_CBC:
+ return createAESCipher(context, 32, digestAlgorithm);
+ case EncryptionAlgorithm.RC4_128:
+ return createRC4Cipher(context, 16, digestAlgorithm);
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected TlsCipher createAESCipher(TlsClientContext context, int cipherKeySize, int digestAlgorithm) throws IOException
+ {
+ return new TlsBlockCipher(context, createAESBlockCipher(),
+ createAESBlockCipher(), createDigest(digestAlgorithm), createDigest(digestAlgorithm), cipherKeySize);
+ }
+
+ protected TlsCipher createRC4Cipher(TlsClientContext context, int cipherKeySize, int digestAlgorithm) throws IOException
+ {
+ return new TlsStreamCipher(context, createRC4StreamCipher(), createRC4StreamCipher(),
+ createDigest(digestAlgorithm), createDigest(digestAlgorithm), cipherKeySize);
+ }
+
+ protected TlsCipher createDESedeCipher(TlsClientContext context, int cipherKeySize, int digestAlgorithm) throws IOException
+ {
+ return new TlsBlockCipher(context, createDESedeBlockCipher(),
+ createDESedeBlockCipher(), createDigest(digestAlgorithm), createDigest(digestAlgorithm), cipherKeySize);
+ }
+
+ protected StreamCipher createRC4StreamCipher()
+ {
+ return new RC4Engine();
+ }
+
+ protected BlockCipher createAESBlockCipher()
+ {
+ return new CBCBlockCipher(new AESFastEngine());
+ }
+
+ protected BlockCipher createDESedeBlockCipher()
+ {
+ return new CBCBlockCipher(new DESedeEngine());
+ }
+
+ protected Digest createDigest(int digestAlgorithm) throws IOException
+ {
+ switch (digestAlgorithm)
+ {
+ case DigestAlgorithm.MD5:
+ return new MD5Digest();
+ case DigestAlgorithm.SHA:
+ return new SHA1Digest();
+ case DigestAlgorithm.SHA256:
+ return new SHA256Digest();
+ case DigestAlgorithm.SHA384:
+ return new SHA384Digest();
+ default:
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsClient.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsClient.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsClient.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsClient.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,264 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+public abstract class DefaultTlsClient implements TlsClient
+{
+ protected TlsCipherFactory cipherFactory;
+
+ protected TlsClientContext context;
+
+ protected int selectedCipherSuite;
+ protected int selectedCompressionMethod;
+
+ public DefaultTlsClient()
+ {
+ this(new DefaultTlsCipherFactory());
+ }
+
+ public DefaultTlsClient(TlsCipherFactory cipherFactory)
+ {
+ this.cipherFactory = cipherFactory;
+ }
+
+ public void init(TlsClientContext context)
+ {
+ this.context = context;
+ }
+
+ public ProtocolVersion getClientVersion()
+ {
+ return ProtocolVersion.TLSv10;
+ }
+
+ public int[] getCipherSuites()
+ {
+ return new int[] {
+ CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_RSA_WITH_RC4_128_SHA,
+ };
+ }
+
+ public Hashtable getClientExtensions()
+ {
+ return null;
+ }
+
+ public short[] getCompressionMethods()
+ {
+ return new short[] { CompressionMethod.NULL };
+ }
+
+ public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException
+ {
+ if (!ProtocolVersion.TLSv10.equals(serverVersion))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+
+ public void notifySessionID(byte[] sessionID)
+ {
+ // Currently ignored
+ }
+
+ public void notifySelectedCipherSuite(int selectedCipherSuite)
+ {
+ this.selectedCipherSuite = selectedCipherSuite;
+ }
+
+ public void notifySelectedCompressionMethod(short selectedCompressionMethod)
+ {
+ this.selectedCompressionMethod = selectedCompressionMethod;
+ }
+
+ public void notifySecureRenegotiation(boolean secureRenegotiation) throws IOException
+ {
+ if (!secureRenegotiation)
+ {
+ /*
+ * RFC 5746 3.4. If the extension is not present, the server does not support
+ * secure renegotiation; set secure_renegotiation flag to FALSE. In this case,
+ * some clients may want to terminate the handshake instead of continuing; see
+ * Section 4.1 for discussion.
+ */
+// throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ }
+
+ public void processServerExtensions(Hashtable serverExtensions)
+ {
+ }
+
+ public TlsKeyExchange getKeyExchange() throws IOException
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+ return createRSAKeyExchange();
+
+ case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ return createDHKeyExchange(KeyExchangeAlgorithm.DH_DSS);
+
+ case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+ return createDHKeyExchange(KeyExchangeAlgorithm.DH_RSA);
+
+ case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_DSS);
+
+ case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ return createDHEKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
+
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+ return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA);
+
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+ return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA);
+
+ case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+ return createECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA);
+
+ case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+ return createECDHEKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher
+ * suites, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public TlsCompression getCompression() throws IOException
+ {
+ switch (selectedCompressionMethod)
+ {
+ case CompressionMethod.NULL:
+ return new TlsNullCompression();
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected compression method was in the list of client-offered compression
+ * methods, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public TlsCipher getCipher() throws IOException
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm._3DES_EDE_CBC, DigestAlgorithm.SHA);
+
+ case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.RC4_128, DigestAlgorithm.SHA);
+
+ case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC, DigestAlgorithm.SHA);
+
+ case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC, DigestAlgorithm.SHA);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher
+ * suites, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected TlsKeyExchange createDHKeyExchange(int keyExchange)
+ {
+ return new TlsDHKeyExchange(context, keyExchange);
+ }
+
+ protected TlsKeyExchange createDHEKeyExchange(int keyExchange)
+ {
+ return new TlsDHEKeyExchange(context, keyExchange);
+ }
+
+ protected TlsKeyExchange createECDHKeyExchange(int keyExchange)
+ {
+ return new TlsECDHKeyExchange(context, keyExchange);
+ }
+
+ protected TlsKeyExchange createECDHEKeyExchange(int keyExchange)
+ {
+ return new TlsECDHEKeyExchange(context, keyExchange);
+ }
+
+ protected TlsKeyExchange createRSAKeyExchange()
+ {
+ return new TlsRSAKeyExchange(context);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/DefaultTlsSignerCredentials.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,79 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+
+public class DefaultTlsSignerCredentials implements TlsSignerCredentials
+{
+ protected TlsClientContext context;
+ protected Certificate clientCert;
+ protected AsymmetricKeyParameter clientPrivateKey;
+
+ protected TlsSigner clientSigner;
+
+ public DefaultTlsSignerCredentials(TlsClientContext context, Certificate clientCertificate,
+ AsymmetricKeyParameter clientPrivateKey)
+ {
+ if (clientCertificate == null)
+ {
+ throw new IllegalArgumentException("'clientCertificate' cannot be null");
+ }
+ if (clientCertificate.certs.length == 0)
+ {
+ throw new IllegalArgumentException("'clientCertificate' cannot be empty");
+ }
+ if (clientPrivateKey == null)
+ {
+ throw new IllegalArgumentException("'clientPrivateKey' cannot be null");
+ }
+ if (!clientPrivateKey.isPrivate())
+ {
+ throw new IllegalArgumentException("'clientPrivateKey' must be private");
+ }
+
+ if (clientPrivateKey instanceof RSAKeyParameters)
+ {
+ clientSigner = new TlsRSASigner();
+ }
+ else if (clientPrivateKey instanceof DSAPrivateKeyParameters)
+ {
+ clientSigner = new TlsDSSSigner();
+ }
+ else if (clientPrivateKey instanceof ECPrivateKeyParameters)
+ {
+ clientSigner = new TlsECDSASigner();
+ }
+ else
+ {
+ throw new IllegalArgumentException("'clientPrivateKey' type not supported: "
+ + clientPrivateKey.getClass().getName());
+ }
+
+ this.context = context;
+ this.clientCert = clientCertificate;
+ this.clientPrivateKey = clientPrivateKey;
+ }
+
+ public Certificate getCertificate()
+ {
+ return clientCert;
+ }
+
+ public byte[] generateCertificateSignature(byte[] md5andsha1) throws IOException
+ {
+ try
+ {
+ return clientSigner.calculateRawSignature(context.getSecureRandom(), clientPrivateKey,
+ md5andsha1);
+ }
+ catch (CryptoException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/DigestAlgorithm.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/DigestAlgorithm.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/DigestAlgorithm.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/DigestAlgorithm.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+public class DigestAlgorithm
+{
+ /*
+ * Note that the values here are implementation-specific and arbitrary.
+ * It is recommended not to depend on the particular values (e.g. serialization).
+ */
+ public static final int NULL = 0;
+ public static final int MD5 = 1;
+ public static final int SHA = 2;
+
+ /*
+ * RFC 5289
+ */
+ public static final int SHA256 = 3;
+ public static final int SHA384 = 4;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ECCurveType.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ECCurveType.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ECCurveType.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ECCurveType.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,28 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * RFC 4492 5.4
+ */
+public class ECCurveType
+{
+ /**
+ * Indicates the elliptic curve domain parameters are conveyed verbosely, and the
+ * underlying finite field is a prime field.
+ */
+ public static final short explicit_prime = 1;
+
+ /**
+ * Indicates the elliptic curve domain parameters are conveyed verbosely, and the
+ * underlying finite field is a characteristic-2 field.
+ */
+ public static final short explicit_char2 = 2;
+
+ /**
+ * Indicates that a named curve is used. This option SHOULD be used when applicable.
+ */
+ public static final short named_curve = 3;
+
+ /*
+ * Values 248 through 255 are reserved for private use.
+ */
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ECPointFormat.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ECPointFormat.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ECPointFormat.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ECPointFormat.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,15 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * RFC 4492 5.1.2
+ */
+public class ECPointFormat
+{
+ public static final short uncompressed = 0;
+ public static final short ansiX962_compressed_prime = 1;
+ public static final short ansiX962_compressed_char2 = 2;
+
+ /*
+ * reserved (248..255)
+ */
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/EncryptionAlgorithm.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,29 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+public class EncryptionAlgorithm
+{
+ /*
+ * Note that the values here are implementation-specific and arbitrary.
+ * It is recommended not to depend on the particular values (e.g. serialization).
+ */
+ public static final int NULL = 0;
+ public static final int RC4_40 = 1;
+ public static final int RC4_128 = 2;
+ public static final int RC2_CBC_40 = 3;
+ public static final int IDEA_CBC = 4;
+ public static final int DES40_CBC = 5;
+ public static final int DES_CBC = 6;
+ public static final int _3DES_EDE_CBC = 7;
+
+ /*
+ * RFC 3268
+ */
+ public static final int AES_128_CBC = 8;
+ public static final int AES_256_CBC = 9;
+
+ /*
+ * RFC 5289
+ */
+ public static final int AES_128_GCM = 10;
+ public static final int AES_256_GCM = 11;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ExtensionType.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ExtensionType.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ExtensionType.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ExtensionType.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,30 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * RFC 4366 2.3
+ */
+public class ExtensionType
+{
+ public static final int server_name = 0;
+ public static final int max_fragment_length = 1;
+ public static final int client_certificate_url = 2;
+ public static final int trusted_ca_keys = 3;
+ public static final int truncated_hmac = 4;
+ public static final int status_request = 5;
+
+ /*
+ * RFC 4492
+ */
+ public static final int elliptic_curves = 10;
+ public static final int ec_point_formats = 11;
+
+ /*
+ * RFC 5054 2.8.1
+ */
+ public static final int srp = 12;
+
+ /*
+ * RFC 5746 6
+ */
+ public static final int renegotiation_info = 0xff01;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/HandshakeType.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/HandshakeType.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/HandshakeType.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/HandshakeType.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * RFC 2246 7.4
+ */
+public class HandshakeType
+{
+ public static final short hello_request = 0;
+ public static final short client_hello = 1;
+ public static final short server_hello = 2;
+ public static final short certificate = 11;
+ public static final short server_key_exchange = 12;
+ public static final short certificate_request = 13;
+ public static final short server_hello_done = 14;
+ public static final short certificate_verify = 15;
+ public static final short client_key_exchange = 16;
+ public static final short finished = 20;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/KeyExchangeAlgorithm.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,33 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+public class KeyExchangeAlgorithm
+{
+ /*
+ * Note that the values here are implementation-specific and arbitrary.
+ * It is recommended not to depend on the particular values (e.g. serialization).
+ */
+ public static final int NULL = 0;
+ public static final int RSA = 1;
+ public static final int RSA_EXPORT = 2;
+ public static final int DHE_DSS = 3;
+ public static final int DHE_DSS_EXPORT = 4;
+ public static final int DHE_RSA = 5;
+ public static final int DHE_RSA_EXPORT = 6;
+ public static final int DH_DSS = 7;
+ public static final int DH_DSS_EXPORT = 8;
+ public static final int DH_RSA = 9;
+ public static final int DH_RSA_EXPORT = 10;
+ public static final int DH_anon = 11;
+ public static final int DH_anon_EXPORT = 12;
+ public static final int PSK = 13;
+ public static final int DHE_PSK = 14;
+ public static final int RSA_PSK = 15;
+ public static final int ECDH_ECDSA = 16;
+ public static final int ECDHE_ECDSA = 17;
+ public static final int ECDH_RSA = 18;
+ public static final int ECDHE_RSA = 19;
+ public static final int ECDH_anon = 20;
+ public static final int SRP = 21;
+ public static final int SRP_DSS = 22;
+ public static final int SRP_RSA = 23;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/LegacyTlsAuthentication.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/LegacyTlsAuthentication.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/LegacyTlsAuthentication.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/LegacyTlsAuthentication.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,32 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+
+/**
+ * A temporary class to wrap old CertificateVerifyer stuff for new TlsAuthentication
+ *
+ * @deprecated
+ */
+public class LegacyTlsAuthentication implements TlsAuthentication
+{
+ protected CertificateVerifyer verifyer;
+
+ public LegacyTlsAuthentication(CertificateVerifyer verifyer)
+ {
+ this.verifyer = verifyer;
+ }
+
+ public void notifyServerCertificate(Certificate serverCertificate) throws IOException
+ {
+ if (!this.verifyer.isValid(serverCertificate.getCerts()))
+ {
+ throw new TlsFatalAlert(AlertDescription.user_canceled);
+ }
+ }
+
+ public TlsCredentials getClientCredentials(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ return null;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/LegacyTlsClient.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/LegacyTlsClient.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/LegacyTlsClient.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/LegacyTlsClient.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,29 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+
+/**
+ * A temporary class to use LegacyTlsAuthentication
+ *
+ * @deprecated
+ */
+public class LegacyTlsClient extends DefaultTlsClient
+{
+ /** @deprecated */
+ protected CertificateVerifyer verifyer;
+
+ /**
+ * @deprecated
+ */
+ public LegacyTlsClient(CertificateVerifyer verifyer)
+ {
+ super();
+
+ this.verifyer = verifyer;
+ }
+
+ public TlsAuthentication getAuthentication() throws IOException
+ {
+ return new LegacyTlsAuthentication(verifyer);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/NamedCurve.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/NamedCurve.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/NamedCurve.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/NamedCurve.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,100 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import pdftk.org.bouncycastle.asn1.sec.SECNamedCurves;
+import pdftk.org.bouncycastle.asn1.x9.X9ECParameters;
+import pdftk.org.bouncycastle.crypto.params.ECDomainParameters;
+
+/**
+ * RFC 4492 5.1.1
+ *
+ * The named curves defined here are those specified in SEC 2 [13]. Note that many of
+ * these curves are also recommended in ANSI X9.62 [7] and FIPS 186-2 [11]. Values 0xFE00
+ * through 0xFEFF are reserved for private use. Values 0xFF01 and 0xFF02 indicate that the
+ * client supports arbitrary prime and characteristic-2 curves, respectively (the curve
+ * parameters must be encoded explicitly in ECParameters).
+ */
+public class NamedCurve
+{
+ public static final int sect163k1 = 1;
+ public static final int sect163r1 = 2;
+ public static final int sect163r2 = 3;
+ public static final int sect193r1 = 4;
+ public static final int sect193r2 = 5;
+ public static final int sect233k1 = 6;
+ public static final int sect233r1 = 7;
+ public static final int sect239k1 = 8;
+ public static final int sect283k1 = 9;
+ public static final int sect283r1 = 10;
+ public static final int sect409k1 = 11;
+ public static final int sect409r1 = 12;
+ public static final int sect571k1 = 13;
+ public static final int sect571r1 = 14;
+ public static final int secp160k1 = 15;
+ public static final int secp160r1 = 16;
+ public static final int secp160r2 = 17;
+ public static final int secp192k1 = 18;
+ public static final int secp192r1 = 19;
+ public static final int secp224k1 = 20;
+ public static final int secp224r1 = 21;
+ public static final int secp256k1 = 22;
+ public static final int secp256r1 = 23;
+ public static final int secp384r1 = 24;
+ public static final int secp521r1 = 25;
+
+ /*
+ * reserved (0xFE00..0xFEFF)
+ */
+
+ public static final int arbitrary_explicit_prime_curves = 0xFF01;
+ public static final int arbitrary_explicit_char2_curves = 0xFF02;
+
+ private static final String[] curveNames = new String[] {
+ "sect163k1",
+ "sect163r1",
+ "sect163r2",
+ "sect193r1",
+ "sect193r2",
+ "sect233k1",
+ "sect233r1",
+ "sect239k1",
+ "sect283k1",
+ "sect283r1",
+ "sect409k1",
+ "sect409r1",
+ "sect571k1",
+ "sect571r1",
+ "secp160k1",
+ "secp160r1",
+ "secp160r2",
+ "secp192k1",
+ "secp192r1",
+ "secp224k1",
+ "secp224r1",
+ "secp256k1",
+ "secp256r1",
+ "secp384r1",
+ "secp521r1", };
+
+ static ECDomainParameters getECParameters(int namedCurve)
+ {
+ int index = namedCurve - 1;
+ if (index < 0 || index >= curveNames.length)
+ {
+ return null;
+ }
+
+ String curveName = curveNames[index];
+
+ // Lazily created the first time a particular curve is accessed
+ X9ECParameters ecP = SECNamedCurves.getByName(curveName);
+
+ if (ecP == null)
+ {
+ return null;
+ }
+
+ // It's a bit inefficient to do this conversion every time
+ return new ECDomainParameters(ecP.getCurve(), ecP.getG(), ecP.getN(), ecP.getH(),
+ ecP.getSeed());
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/PSKTlsClient.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/PSKTlsClient.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/PSKTlsClient.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/PSKTlsClient.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,200 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+public abstract class PSKTlsClient implements TlsClient
+{
+ protected TlsCipherFactory cipherFactory;
+ protected TlsPSKIdentity pskIdentity;
+
+ protected TlsClientContext context;
+
+ protected int selectedCompressionMethod;
+ protected int selectedCipherSuite;
+
+ public PSKTlsClient(TlsPSKIdentity pskIdentity)
+ {
+ this(new DefaultTlsCipherFactory(), pskIdentity);
+ }
+
+ public PSKTlsClient(TlsCipherFactory cipherFactory, TlsPSKIdentity pskIdentity)
+ {
+ this.cipherFactory = cipherFactory;
+ this.pskIdentity = pskIdentity;
+ }
+
+ public ProtocolVersion getClientVersion()
+ {
+ return ProtocolVersion.TLSv10;
+ }
+
+ public void init(TlsClientContext context)
+ {
+ this.context = context;
+ }
+
+ public int[] getCipherSuites()
+ {
+ return new int[] {
+ CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA,
+ CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA,
+ CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_PSK_WITH_RC4_128_SHA,
+ };
+ }
+
+ public Hashtable getClientExtensions() throws IOException
+ {
+ return null;
+ }
+
+ public short[] getCompressionMethods()
+ {
+ return new short[] { CompressionMethod.NULL };
+ }
+
+ public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException
+ {
+ if (!ProtocolVersion.TLSv10.equals(serverVersion))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+
+ public void notifySessionID(byte[] sessionID)
+ {
+ // Currently ignored
+ }
+
+ public void notifySelectedCipherSuite(int selectedCipherSuite)
+ {
+ this.selectedCipherSuite = selectedCipherSuite;
+ }
+
+ public void notifySelectedCompressionMethod(short selectedCompressionMethod)
+ {
+ this.selectedCompressionMethod = selectedCompressionMethod;
+ }
+
+ public void notifySecureRenegotiation(boolean secureRenegotiation) throws IOException
+ {
+ if (!secureRenegotiation)
+ {
+ /*
+ * RFC 5746 3.4. If the extension is not present, the server does not support
+ * secure renegotiation; set secure_renegotiation flag to FALSE. In this case,
+ * some clients may want to terminate the handshake instead of continuing; see
+ * Section 4.1 for discussion.
+ */
+// throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ }
+
+ public void processServerExtensions(Hashtable serverExtensions)
+ {
+ }
+
+ public TlsKeyExchange getKeyExchange() throws IOException
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
+ return createPSKKeyExchange(KeyExchangeAlgorithm.PSK);
+
+ case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
+ return createPSKKeyExchange(KeyExchangeAlgorithm.RSA_PSK);
+
+ case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+ return createPSKKeyExchange(KeyExchangeAlgorithm.DHE_PSK);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher
+ * suites, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public TlsCompression getCompression() throws IOException
+ {
+ switch (selectedCompressionMethod)
+ {
+ case CompressionMethod.NULL:
+ return new TlsNullCompression();
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected compression method was in the list of client-offered compression
+ * methods, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public TlsCipher getCipher() throws IOException
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm._3DES_EDE_CBC,
+ DigestAlgorithm.SHA);
+
+ case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC,
+ DigestAlgorithm.SHA);
+
+ case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC,
+ DigestAlgorithm.SHA);
+
+ case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
+ case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.RC4_128,
+ DigestAlgorithm.SHA);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher
+ * suites, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected TlsKeyExchange createPSKKeyExchange(int keyExchange)
+ {
+ return new TlsPSKKeyExchange(context, keyExchange, pskIdentity);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ProtocolVersion.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ProtocolVersion.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/ProtocolVersion.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/ProtocolVersion.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,64 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+
+public class ProtocolVersion
+{
+ public static final ProtocolVersion SSLv3 = new ProtocolVersion(0x0300);
+ public static final ProtocolVersion TLSv10 = new ProtocolVersion(0x0301);
+ public static final ProtocolVersion TLSv11 = new ProtocolVersion(0x0302);
+ public static final ProtocolVersion TLSv12 = new ProtocolVersion(0x0303);
+
+ private int version;
+
+ private ProtocolVersion(int v)
+ {
+ version = v & 0xffff;
+ }
+
+ public int getFullVersion()
+ {
+ return version;
+ }
+
+ public int getMajorVersion()
+ {
+ return version >> 8;
+ }
+
+ public int getMinorVersion()
+ {
+ return version & 0xff;
+ }
+
+ public boolean equals(Object obj)
+ {
+ return this == obj;
+ }
+
+ public int hashCode()
+ {
+ return version;
+ }
+
+ public static ProtocolVersion get(int major, int minor) throws IOException
+ {
+ switch (major)
+ {
+ case 3:
+ switch (minor)
+ {
+ case 0:
+ return SSLv3;
+ case 1:
+ return TLSv10;
+ case 2:
+ return TLSv11;
+ case 3:
+ return TLSv12;
+ }
+ }
+
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/RecordStream.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/RecordStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/RecordStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/RecordStream.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,191 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import pdftk.org.bouncycastle.crypto.Digest;
+
+/**
+ * An implementation of the TLS 1.0 record layer, allowing downgrade to SSLv3.
+ */
+class RecordStream
+{
+ private TlsProtocolHandler handler;
+ private InputStream is;
+ private OutputStream os;
+ private TlsCompression readCompression = null;
+ private TlsCompression writeCompression = null;
+ private TlsCipher readCipher = null;
+ private TlsCipher writeCipher = null;
+ private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ private TlsClientContext context = null;
+ private CombinedHash hash = null;
+
+ RecordStream(TlsProtocolHandler handler, InputStream is, OutputStream os)
+ {
+ this.handler = handler;
+ this.is = is;
+ this.os = os;
+ this.readCompression = new TlsNullCompression();
+ this.writeCompression = this.readCompression;
+ this.readCipher = new TlsNullCipher();
+ this.writeCipher = this.readCipher;
+ }
+
+ void init(TlsClientContext context)
+ {
+ this.context = context;
+ this.hash = new CombinedHash(context);
+ }
+
+ void clientCipherSpecDecided(TlsCompression tlsCompression, TlsCipher tlsCipher)
+ {
+ this.writeCompression = tlsCompression;
+ this.writeCipher = tlsCipher;
+ }
+
+ void serverClientSpecReceived()
+ {
+ this.readCompression = this.writeCompression;
+ this.readCipher = this.writeCipher;
+ }
+
+ public void readData() throws IOException
+ {
+ short type = TlsUtils.readUint8(is);
+
+ // TODO In light of versioning and SSLv3, what should we expect here?
+ ProtocolVersion expectedVersion = ProtocolVersion.TLSv10; //context.getServerVersion();
+ if (!expectedVersion.equals(TlsUtils.readVersion(is)))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ int size = TlsUtils.readUint16(is);
+ byte[] buf = decodeAndVerify(type, is, size);
+ handler.processData(type, buf, 0, buf.length);
+ }
+
+ protected byte[] decodeAndVerify(short type, InputStream is, int len) throws IOException
+ {
+ byte[] buf = new byte[len];
+ TlsUtils.readFully(buf, is);
+ byte[] decoded = readCipher.decodeCiphertext(type, buf, 0, buf.length);
+
+ OutputStream cOut = readCompression.decompress(buffer);
+
+ if (cOut == buffer)
+ {
+ return decoded;
+ }
+
+ cOut.write(decoded, 0, decoded.length);
+ cOut.flush();
+ return getBufferContents();
+ }
+
+ protected void writeMessage(short type, byte[] message, int offset, int len) throws IOException
+ {
+ if (type == ContentType.handshake)
+ {
+ updateHandshakeData(message, offset, len);
+ }
+
+ OutputStream cOut = writeCompression.compress(buffer);
+
+ byte[] ciphertext;
+ if (cOut == buffer)
+ {
+ ciphertext = writeCipher.encodePlaintext(type, message, offset, len);
+ }
+ else
+ {
+ cOut.write(message, offset, len);
+ cOut.flush();
+ byte[] compressed = getBufferContents();
+ ciphertext = writeCipher.encodePlaintext(type, compressed, 0, compressed.length);
+ }
+
+ byte[] writeMessage = new byte[ciphertext.length + 5];
+ TlsUtils.writeUint8(type, writeMessage, 0);
+ // TODO In light of versioning, what should we send here?
+// TlsUtils.writeVersion(context.getServerVersion(), writeMessage, 1);
+ TlsUtils.writeVersion(ProtocolVersion.TLSv10, writeMessage, 1);
+ TlsUtils.writeUint16(ciphertext.length, writeMessage, 3);
+ System.arraycopy(ciphertext, 0, writeMessage, 5, ciphertext.length);
+ os.write(writeMessage);
+ os.flush();
+ }
+
+ void updateHandshakeData(byte[] message, int offset, int len)
+ {
+ hash.update(message, offset, len);
+ }
+
+ /**
+ * 'sender' only relevant to SSLv3
+ */
+ byte[] getCurrentHash(byte[] sender)
+ {
+ Digest d = new CombinedHash(hash);
+
+ boolean isTls = context.getServerVersion().getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+
+ if (!isTls)
+ {
+ if (sender != null)
+ {
+ d.update(sender, 0, sender.length);
+ }
+ }
+
+ return doFinal(d);
+ }
+
+ protected void close() throws IOException
+ {
+ IOException e = null;
+ try
+ {
+ is.close();
+ }
+ catch (IOException ex)
+ {
+ e = ex;
+ }
+ try
+ {
+ os.close();
+ }
+ catch (IOException ex)
+ {
+ e = ex;
+ }
+ if (e != null)
+ {
+ throw e;
+ }
+ }
+
+ protected void flush() throws IOException
+ {
+ os.flush();
+ }
+
+ private byte[] getBufferContents()
+ {
+ byte[] contents = buffer.toByteArray();
+ buffer.reset();
+ return contents;
+ }
+
+ private static byte[] doFinal(Digest d)
+ {
+ byte[] bs = new byte[d.getDigestSize()];
+ d.doFinal(bs, 0);
+ return bs;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/SRPTlsClient.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/SRPTlsClient.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/SRPTlsClient.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/SRPTlsClient.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,203 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Hashtable;
+
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Integers;
+
+public abstract class SRPTlsClient
+ implements TlsClient
+{
+ public static final Integer EXT_SRP = Integers.valueOf(ExtensionType.srp);
+
+ protected TlsCipherFactory cipherFactory;
+ protected byte[] identity;
+ protected byte[] password;
+
+ protected TlsClientContext context;
+
+ protected int selectedCompressionMethod;
+ protected int selectedCipherSuite;
+
+ public SRPTlsClient(byte[] identity, byte[] password)
+ {
+ this(new DefaultTlsCipherFactory(), identity, password);
+ }
+
+ public SRPTlsClient(TlsCipherFactory cipherFactory, byte[] identity, byte[] password)
+ {
+ this.cipherFactory = cipherFactory;
+ this.identity = Arrays.clone(identity);
+ this.password = Arrays.clone(password);
+ }
+
+ public void init(TlsClientContext context)
+ {
+ this.context = context;
+ }
+
+ public ProtocolVersion getClientVersion()
+ {
+ return ProtocolVersion.TLSv10;
+ }
+
+ public int[] getCipherSuites()
+ {
+ return new int[] {
+ CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
+ CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, };
+ }
+
+ public Hashtable getClientExtensions() throws IOException
+ {
+ Hashtable clientExtensions = new Hashtable();
+
+ ByteArrayOutputStream srpData = new ByteArrayOutputStream();
+ TlsUtils.writeOpaque8(this.identity, srpData);
+ clientExtensions.put(EXT_SRP, srpData.toByteArray());
+
+ return clientExtensions;
+ }
+
+ public short[] getCompressionMethods()
+ {
+ return new short[] { CompressionMethod.NULL };
+ }
+
+ public void notifyServerVersion(ProtocolVersion serverVersion) throws IOException
+ {
+ if (!ProtocolVersion.TLSv10.equals(serverVersion))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+
+ public void notifySessionID(byte[] sessionID)
+ {
+ // Currently ignored
+ }
+
+ public void notifySelectedCipherSuite(int selectedCipherSuite)
+ {
+ this.selectedCipherSuite = selectedCipherSuite;
+ }
+
+ public void notifySelectedCompressionMethod(short selectedCompressionMethod)
+ {
+ this.selectedCompressionMethod = selectedCompressionMethod;
+ }
+
+ public void notifySecureRenegotiation(boolean secureRenegotiation) throws IOException
+ {
+ if (!secureRenegotiation)
+ {
+ /*
+ * RFC 5746 3.4. If the extension is not present, the server does not support
+ * secure renegotiation; set secure_renegotiation flag to FALSE. In this case,
+ * some clients may want to terminate the handshake instead of continuing; see
+ * Section 4.1 for discussion.
+ */
+// throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+ }
+
+ public void processServerExtensions(Hashtable serverExtensions)
+ {
+ // There is no server response for the SRP extension
+ }
+
+ public TlsKeyExchange getKeyExchange() throws IOException
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
+ return createSRPKeyExchange(KeyExchangeAlgorithm.SRP);
+
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
+ return createSRPKeyExchange(KeyExchangeAlgorithm.SRP_RSA);
+
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
+ return createSRPKeyExchange(KeyExchangeAlgorithm.SRP_DSS);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher
+ * suites, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public TlsCompression getCompression() throws IOException
+ {
+ switch (selectedCompressionMethod)
+ {
+ case CompressionMethod.NULL:
+ return new TlsNullCompression();
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected compression method was in the list of client-offered compression
+ * methods, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public TlsCipher getCipher() throws IOException
+ {
+ switch (selectedCipherSuite)
+ {
+ case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm._3DES_EDE_CBC,
+ DigestAlgorithm.SHA);
+
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_128_CBC,
+ DigestAlgorithm.SHA);
+
+ case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
+ case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
+ return cipherFactory.createCipher(context, EncryptionAlgorithm.AES_256_CBC,
+ DigestAlgorithm.SHA);
+
+ default:
+ /*
+ * Note: internal error here; the TlsProtocolHandler verifies that the
+ * server-selected cipher suite was in the list of client-offered cipher
+ * suites, so if we now can't produce an implementation, we shouldn't have
+ * offered it!
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected TlsKeyExchange createSRPKeyExchange(int keyExchange)
+ {
+ return new TlsSRPKeyExchange(context, keyExchange, identity, password);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/SSL3Mac.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/SSL3Mac.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/SSL3Mac.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/SSL3Mac.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,117 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import pdftk.org.bouncycastle.crypto.CipherParameters;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * HMAC implementation based on original internet draft for HMAC (RFC 2104)
+ *
+ * The difference is that padding is concatentated versus XORed with the key
+ *
+ * H(K + opad, H(K + ipad, text))
+ */
+public class SSL3Mac implements Mac
+{
+ private final static byte IPAD = (byte)0x36;
+ private final static byte OPAD = (byte)0x5C;
+
+ static final byte[] MD5_IPAD = genPad(IPAD, 48);
+ static final byte[] MD5_OPAD = genPad(OPAD, 48);
+ static final byte[] SHA1_IPAD = genPad(IPAD, 40);
+ static final byte[] SHA1_OPAD = genPad(OPAD, 40);
+
+ private Digest digest;
+
+ private byte[] secret;
+ private byte[] ipad, opad;
+
+ /**
+ * Base constructor for one of the standard digest algorithms that the byteLength of
+ * the algorithm is know for. Behaviour is undefined for digests other than MD5 or SHA1.
+ *
+ * @param digest the digest.
+ */
+ public SSL3Mac(Digest digest)
+ {
+ this.digest = digest;
+
+ if (digest.getDigestSize() == 20)
+ {
+ this.ipad = SHA1_IPAD;
+ this.opad = SHA1_OPAD;
+ }
+ else
+ {
+ this.ipad = MD5_IPAD;
+ this.opad = MD5_OPAD;
+ }
+ }
+
+ public String getAlgorithmName()
+ {
+ return digest.getAlgorithmName() + "/SSL3MAC";
+ }
+
+ public Digest getUnderlyingDigest()
+ {
+ return digest;
+ }
+
+ public void init(CipherParameters params)
+ {
+ secret = Arrays.clone(((KeyParameter)params).getKey());
+
+ reset();
+ }
+
+ public int getMacSize()
+ {
+ return digest.getDigestSize();
+ }
+
+ public void update(byte in)
+ {
+ digest.update(in);
+ }
+
+ public void update(byte[] in, int inOff, int len)
+ {
+ digest.update(in, inOff, len);
+ }
+
+ public int doFinal(byte[] out, int outOff)
+ {
+ byte[] tmp = new byte[digest.getDigestSize()];
+ digest.doFinal(tmp, 0);
+
+ digest.update(secret, 0, secret.length);
+ digest.update(opad, 0, opad.length);
+ digest.update(tmp, 0, tmp.length);
+
+ int len = digest.doFinal(out, outOff);
+
+ reset();
+
+ return len;
+ }
+
+ /**
+ * Reset the mac generator.
+ */
+ public void reset()
+ {
+ digest.reset();
+ digest.update(secret, 0, secret.length);
+ digest.update(ipad, 0, ipad.length);
+ }
+
+ private static byte[] genPad(byte b, int count)
+ {
+ byte[] padding = new byte[count];
+ Arrays.fill(padding, b);
+ return padding;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/SecurityParameters.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/SecurityParameters.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/SecurityParameters.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/SecurityParameters.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+public class SecurityParameters
+{
+ byte[] clientRandom = null;
+ byte[] serverRandom = null;
+ byte[] masterSecret = null;
+
+ public byte[] getClientRandom()
+ {
+ return clientRandom;
+ }
+
+ public byte[] getServerRandom()
+ {
+ return serverRandom;
+ }
+
+ public byte[] getMasterSecret()
+ {
+ return masterSecret;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsAgreementCredentials.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsAgreementCredentials.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsAgreementCredentials.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsAgreementCredentials.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,10 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+
+public interface TlsAgreementCredentials extends TlsCredentials
+{
+ byte[] generateAgreement(AsymmetricKeyParameter serverPublicKey) throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsAuthentication.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsAuthentication.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsAuthentication.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsAuthentication.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,24 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+
+public interface TlsAuthentication
+{
+ /**
+ * Called by the protocol handler to report the server certificate
+ * Note: this method is responsible for certificate verification and validation
+ *
+ * @param serverCertificate the server certificate received
+ * @throws IOException
+ */
+ void notifyServerCertificate(Certificate serverCertificate) throws IOException;
+
+ /**
+ * Return client credentials in response to server's certificate request
+ *
+ * @param certificateRequest details of the certificate request
+ * @return a TlsCredentials object or null for no client authentication
+ * @throws IOException
+ */
+ TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsBlockCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsBlockCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsBlockCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsBlockCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,229 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.BlockCipher;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithIV;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * A generic TLS 1.0 / SSLv3 block cipher.
+ * This can be used for AES or 3DES for example.
+ */
+public class TlsBlockCipher implements TlsCipher
+{
+ protected TlsClientContext context;
+ protected byte[] randomData;
+
+ protected BlockCipher encryptCipher;
+ protected BlockCipher decryptCipher;
+
+ protected TlsMac writeMac;
+ protected TlsMac readMac;
+
+ public TlsMac getWriteMac()
+ {
+ return writeMac;
+ }
+
+ public TlsMac getReadMac()
+ {
+ return readMac;
+ }
+
+ public TlsBlockCipher(TlsClientContext context, BlockCipher encryptCipher,
+ BlockCipher decryptCipher, Digest writeDigest, Digest readDigest, int cipherKeySize)
+ {
+ this.context = context;
+
+ this.randomData = new byte[256];
+ context.getSecureRandom().nextBytes(randomData);
+
+ this.encryptCipher = encryptCipher;
+ this.decryptCipher = decryptCipher;
+
+ int key_block_size = (2 * cipherKeySize) + writeDigest.getDigestSize()
+ + readDigest.getDigestSize() + encryptCipher.getBlockSize()
+ + decryptCipher.getBlockSize();
+
+ byte[] key_block = TlsUtils.calculateKeyBlock(context, key_block_size);
+
+ int offset = 0;
+
+ // Init MACs
+ writeMac = new TlsMac(context, writeDigest, key_block, offset, writeDigest.getDigestSize());
+ offset += writeDigest.getDigestSize();
+ readMac = new TlsMac(context, readDigest, key_block, offset, readDigest.getDigestSize());
+ offset += readDigest.getDigestSize();
+
+ // Init Ciphers
+ this.initCipher(true, encryptCipher, key_block, cipherKeySize, offset, offset
+ + (cipherKeySize * 2));
+ offset += cipherKeySize;
+ this.initCipher(false, decryptCipher, key_block, cipherKeySize, offset, offset
+ + cipherKeySize + encryptCipher.getBlockSize());
+ }
+
+ protected void initCipher(boolean forEncryption, BlockCipher cipher, byte[] key_block,
+ int key_size, int key_offset, int iv_offset)
+ {
+ KeyParameter key_parameter = new KeyParameter(key_block, key_offset, key_size);
+ ParametersWithIV parameters_with_iv = new ParametersWithIV(key_parameter, key_block,
+ iv_offset, cipher.getBlockSize());
+ cipher.init(forEncryption, parameters_with_iv);
+ }
+
+ public byte[] encodePlaintext(short type, byte[] plaintext, int offset, int len)
+ {
+ int blocksize = encryptCipher.getBlockSize();
+ int padding_length = blocksize - 1 - ((len + writeMac.getSize()) % blocksize);
+
+ boolean isTls = context.getServerVersion().getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+
+ if (isTls)
+ {
+ // Add a random number of extra blocks worth of padding
+ int maxExtraPadBlocks = (255 - padding_length) / blocksize;
+ int actualExtraPadBlocks = chooseExtraPadBlocks(context.getSecureRandom(), maxExtraPadBlocks);
+ padding_length += actualExtraPadBlocks * blocksize;
+ }
+
+ int totalsize = len + writeMac.getSize() + padding_length + 1;
+ byte[] outbuf = new byte[totalsize];
+ System.arraycopy(plaintext, offset, outbuf, 0, len);
+ byte[] mac = writeMac.calculateMac(type, plaintext, offset, len);
+ System.arraycopy(mac, 0, outbuf, len, mac.length);
+ int paddoffset = len + mac.length;
+ for (int i = 0; i <= padding_length; i++)
+ {
+ outbuf[i + paddoffset] = (byte)padding_length;
+ }
+ for (int i = 0; i < totalsize; i += blocksize)
+ {
+ encryptCipher.processBlock(outbuf, i, outbuf, i);
+ }
+ return outbuf;
+ }
+
+ public byte[] decodeCiphertext(short type, byte[] ciphertext, int offset, int len)
+ throws IOException
+ {
+ int blockSize = decryptCipher.getBlockSize();
+ int macSize = readMac.getSize();
+
+ /*
+ * TODO[TLS 1.1] Explicit IV implies minLen = blockSize + max(blockSize, macSize + 1),
+ * and will need further changes to offset and plen variables below.
+ */
+
+ int minLen = Math.max(blockSize, macSize + 1);
+ if (len < minLen)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+
+ if (len % blockSize != 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.decryption_failed);
+ }
+
+ for (int i = 0; i < len; i += blockSize)
+ {
+ decryptCipher.processBlock(ciphertext, offset + i, ciphertext, offset + i);
+ }
+
+ int plen = len;
+
+ // If there's anything wrong with the padding, this will return zero
+ int totalPad = checkPaddingConstantTime(ciphertext, offset, plen, blockSize, macSize);
+
+ int macInputLen = plen - totalPad - macSize;
+
+ byte[] decryptedMac = Arrays.copyOfRange(ciphertext, offset + macInputLen, offset + macInputLen + macSize);
+ byte[] calculatedMac = readMac.calculateMacConstantTime(type, ciphertext, offset, macInputLen, plen - macSize, randomData);
+
+ boolean badMac = !Arrays.constantTimeAreEqual(calculatedMac, decryptedMac);
+
+ if (badMac || totalPad == 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+ }
+
+ return Arrays.copyOfRange(ciphertext, offset, offset + macInputLen);
+ }
+
+ protected int checkPaddingConstantTime(byte[] buf, int off, int len, int blockSize, int macSize)
+ {
+ int end = off + len;
+ byte lastByte = buf[end - 1];
+ int padlen = lastByte & 0xff;
+ int totalPad = padlen + 1;
+
+ int dummyIndex = 0;
+ byte padDiff = 0;
+
+ boolean isTls = context.getServerVersion().getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+
+ if ((!isTls && totalPad > blockSize) || (macSize + totalPad > len))
+ {
+ totalPad = 0;
+ }
+ else
+ {
+ int padPos = end - totalPad;
+ do
+ {
+ padDiff |= (buf[padPos++] ^ lastByte);
+ }
+ while (padPos < end);
+
+ dummyIndex = totalPad;
+
+ if (padDiff != 0)
+ {
+ totalPad = 0;
+ }
+ }
+
+ // Run some extra dummy checks so the number of checks is always constant
+ {
+ byte[] dummyPad = randomData;
+ while (dummyIndex < 256)
+ {
+ padDiff |= (dummyPad[dummyIndex++] ^ lastByte);
+ }
+ // Ensure the above loop is not eliminated
+ dummyPad[0] ^= padDiff;
+ }
+
+ return totalPad;
+ }
+
+ protected int chooseExtraPadBlocks(SecureRandom r, int max)
+ {
+// return r.nextInt(max + 1);
+
+ int x = r.nextInt();
+ int n = lowestBitSet(x);
+ return Math.min(n, max);
+ }
+
+ protected int lowestBitSet(int x)
+ {
+ if (x == 0)
+ {
+ return 32;
+ }
+
+ int n = 0;
+ while ((x & 1) == 0)
+ {
+ ++n;
+ x >>= 1;
+ }
+ return n;
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,10 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+
+public interface TlsCipher
+{
+ byte[] encodePlaintext(short type, byte[] plaintext, int offset, int len) throws IOException;
+
+ byte[] decodeCiphertext(short type, byte[] ciphertext, int offset, int len) throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsCipherFactory.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsCipherFactory.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsCipherFactory.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsCipherFactory.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,11 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+
+public interface TlsCipherFactory
+{
+ /**
+ * See enumeration classes EncryptionAlgorithm and DigestAlgorithm for appropriate argument values
+ */
+ TlsCipher createCipher(TlsClientContext context, int encryptionAlgorithm, int digestAlgorithm) throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsClient.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsClient.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsClient.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsClient.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,39 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+public interface TlsClient
+{
+ void init(TlsClientContext context);
+
+ ProtocolVersion getClientVersion();
+
+ int[] getCipherSuites();
+
+ short[] getCompressionMethods();
+
+ // Hashtable is (Integer -> byte[])
+ Hashtable getClientExtensions() throws IOException;
+
+ void notifyServerVersion(ProtocolVersion selectedVersion) throws IOException;
+
+ void notifySessionID(byte[] sessionID);
+
+ void notifySelectedCipherSuite(int selectedCipherSuite);
+
+ void notifySelectedCompressionMethod(short selectedCompressionMethod);
+
+ void notifySecureRenegotiation(boolean secureNegotiation) throws IOException;
+
+ // Hashtable is (Integer -> byte[])
+ void processServerExtensions(Hashtable serverExtensions);
+
+ TlsKeyExchange getKeyExchange() throws IOException;
+
+ TlsAuthentication getAuthentication() throws IOException;
+
+ TlsCompression getCompression() throws IOException;
+
+ TlsCipher getCipher() throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsClientContext.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsClientContext.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsClientContext.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsClientContext.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.security.SecureRandom;
+
+public interface TlsClientContext
+{
+ SecureRandom getSecureRandom();
+
+ SecurityParameters getSecurityParameters();
+
+ ProtocolVersion getClientVersion();
+
+ ProtocolVersion getServerVersion();
+
+ Object getUserObject();
+
+ void setUserObject(Object userObject);
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsClientContextImpl.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsClientContextImpl.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsClientContextImpl.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsClientContextImpl.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,59 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.security.SecureRandom;
+
+class TlsClientContextImpl implements TlsClientContext
+{
+ private SecureRandom secureRandom;
+ private SecurityParameters securityParameters;
+
+ private ProtocolVersion clientVersion = null;
+ private ProtocolVersion serverVersion = null;
+ private Object userObject = null;
+
+ TlsClientContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters)
+ {
+ this.secureRandom = secureRandom;
+ this.securityParameters = securityParameters;
+ }
+
+ public SecureRandom getSecureRandom()
+ {
+ return secureRandom;
+ }
+
+ public SecurityParameters getSecurityParameters()
+ {
+ return securityParameters;
+ }
+
+ public ProtocolVersion getClientVersion()
+ {
+ return clientVersion;
+ }
+
+ public void setClientVersion(ProtocolVersion clientVersion)
+ {
+ this.clientVersion = clientVersion;
+ }
+
+ public ProtocolVersion getServerVersion()
+ {
+ return serverVersion;
+ }
+
+ public void setServerVersion(ProtocolVersion serverVersion)
+ {
+ this.serverVersion = serverVersion;
+ }
+
+ public Object getUserObject()
+ {
+ return userObject;
+ }
+
+ public void setUserObject(Object userObject)
+ {
+ this.userObject = userObject;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsCompression.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsCompression.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsCompression.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsCompression.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,10 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.OutputStream;
+
+public interface TlsCompression
+{
+ OutputStream compress(OutputStream output);
+
+ OutputStream decompress(OutputStream output);
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsCredentials.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsCredentials.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsCredentials.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsCredentials.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,6 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+public interface TlsCredentials
+{
+ Certificate getCertificate();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsDHEKeyExchange.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,57 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.crypto.Signer;
+import pdftk.org.bouncycastle.crypto.io.SignerInputStream;
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPublicKeyParameters;
+
+class TlsDHEKeyExchange extends TlsDHKeyExchange
+{
+ TlsDHEKeyExchange(TlsClientContext context, int keyExchange)
+ {
+ super(context, keyExchange);
+ }
+
+ public void skipServerKeyExchange() throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void processServerKeyExchange(InputStream is)
+ throws IOException
+ {
+ SecurityParameters securityParameters = context.getSecurityParameters();
+
+ Signer signer = initSigner(tlsSigner, securityParameters);
+ InputStream sigIn = new SignerInputStream(is, signer);
+
+ byte[] pBytes = TlsUtils.readOpaque16(sigIn);
+ byte[] gBytes = TlsUtils.readOpaque16(sigIn);
+ byte[] YsBytes = TlsUtils.readOpaque16(sigIn);
+
+ byte[] sigByte = TlsUtils.readOpaque16(is);
+ if (!signer.verifySignature(sigByte))
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_certificate);
+ }
+
+ BigInteger p = new BigInteger(1, pBytes);
+ BigInteger g = new BigInteger(1, gBytes);
+ BigInteger Ys = new BigInteger(1, YsBytes);
+
+ this.dhAgreeServerPublicKey = validateDHPublicKey(new DHPublicKeyParameters(Ys,
+ new DHParameters(p, g)));
+ }
+
+ protected Signer initSigner(TlsSigner tlsSigner, SecurityParameters securityParameters)
+ {
+ Signer signer = tlsSigner.createVerifyer(this.serverPublicKey);
+ signer.update(securityParameters.clientRandom, 0, securityParameters.clientRandom.length);
+ signer.update(securityParameters.serverRandom, 0, securityParameters.serverRandom.length);
+ return signer;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsDHKeyExchange.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,210 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.x509.KeyUsage;
+import pdftk.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.util.PublicKeyFactory;
+
+/**
+ * TLS 1.0 DH key exchange.
+ */
+class TlsDHKeyExchange implements TlsKeyExchange
+{
+ protected static final BigInteger ONE = BigInteger.valueOf(1);
+ protected static final BigInteger TWO = BigInteger.valueOf(2);
+
+ protected TlsClientContext context;
+ protected int keyExchange;
+ protected TlsSigner tlsSigner;
+
+ protected AsymmetricKeyParameter serverPublicKey = null;
+ protected DHPublicKeyParameters dhAgreeServerPublicKey = null;
+ protected TlsAgreementCredentials agreementCredentials;
+ protected DHPrivateKeyParameters dhAgreeClientPrivateKey = null;
+
+ TlsDHKeyExchange(TlsClientContext context, int keyExchange)
+ {
+ switch (keyExchange)
+ {
+ case KeyExchangeAlgorithm.DH_RSA:
+ case KeyExchangeAlgorithm.DH_DSS:
+ this.tlsSigner = null;
+ break;
+ case KeyExchangeAlgorithm.DHE_RSA:
+ this.tlsSigner = new TlsRSASigner();
+ break;
+ case KeyExchangeAlgorithm.DHE_DSS:
+ this.tlsSigner = new TlsDSSSigner();
+ break;
+ default:
+ throw new IllegalArgumentException("unsupported key exchange algorithm");
+ }
+
+ this.context = context;
+ this.keyExchange = keyExchange;
+ }
+
+ public void skipServerCertificate() throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void processServerCertificate(Certificate serverCertificate) throws IOException
+ {
+ pdftk.org.bouncycastle.asn1.x509.Certificate x509Cert = serverCertificate.certs[0];
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+
+ try
+ {
+ this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
+ }
+ catch (RuntimeException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+ }
+
+ if (tlsSigner == null)
+ {
+ try
+ {
+ this.dhAgreeServerPublicKey = validateDHPublicKey((DHPublicKeyParameters)this.serverPublicKey);
+ }
+ catch (ClassCastException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyAgreement);
+ }
+ else
+ {
+ if (!tlsSigner.isValidPublicKey(this.serverPublicKey))
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
+ }
+
+ // TODO
+ /*
+ * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the
+ * signing algorithm for the certificate must be the same as the algorithm for the
+ * certificate key."
+ */
+ }
+
+ public void skipServerKeyExchange() throws IOException
+ {
+ // OK
+ }
+
+ public void processServerKeyExchange(InputStream is)
+ throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void validateCertificateRequest(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ short[] types = certificateRequest.getCertificateTypes();
+ for (int i = 0; i < types.length; ++i)
+ {
+ switch (types[i])
+ {
+ case ClientCertificateType.rsa_sign:
+ case ClientCertificateType.dss_sign:
+ case ClientCertificateType.rsa_fixed_dh:
+ case ClientCertificateType.dss_fixed_dh:
+ case ClientCertificateType.ecdsa_sign:
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ }
+
+ public void skipClientCredentials() throws IOException
+ {
+ this.agreementCredentials = null;
+ }
+
+ public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
+ {
+ if (clientCredentials instanceof TlsAgreementCredentials)
+ {
+ // TODO Validate client cert has matching parameters (see 'areCompatibleParameters')?
+
+ this.agreementCredentials = (TlsAgreementCredentials)clientCredentials;
+ }
+ else if (clientCredentials instanceof TlsSignerCredentials)
+ {
+ // OK
+ }
+ else
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public void generateClientKeyExchange(OutputStream os) throws IOException
+ {
+ /*
+ * RFC 2246 7.4.7.2 If the client certificate already contains a suitable
+ * Diffie-Hellman key, then Yc is implicit and does not need to be sent again. In
+ * this case, the Client Key Exchange message will be sent, but will be empty.
+ */
+ if (agreementCredentials == null)
+ {
+ generateEphemeralClientKeyExchange(dhAgreeServerPublicKey.getParameters(), os);
+ }
+ }
+
+ public byte[] generatePremasterSecret() throws IOException
+ {
+ if (agreementCredentials != null)
+ {
+ return agreementCredentials.generateAgreement(dhAgreeServerPublicKey);
+ }
+
+ return calculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey);
+ }
+
+ protected boolean areCompatibleParameters(DHParameters a, DHParameters b)
+ {
+ return a.getP().equals(b.getP()) && a.getG().equals(b.getG());
+ }
+
+ protected byte[] calculateDHBasicAgreement(DHPublicKeyParameters publicKey,
+ DHPrivateKeyParameters privateKey)
+ {
+ return TlsDHUtils.calculateDHBasicAgreement(publicKey, privateKey);
+ }
+
+ protected AsymmetricCipherKeyPair generateDHKeyPair(DHParameters dhParams)
+ {
+ return TlsDHUtils.generateDHKeyPair(context.getSecureRandom(), dhParams);
+ }
+
+ protected void generateEphemeralClientKeyExchange(DHParameters dhParams, OutputStream os)
+ throws IOException
+ {
+ this.dhAgreeClientPrivateKey = TlsDHUtils.generateEphemeralClientKeyExchange(context.getSecureRandom(), dhParams, os);
+ }
+
+ protected DHPublicKeyParameters validateDHPublicKey(DHPublicKeyParameters key)
+ throws IOException
+ {
+ return TlsDHUtils.validateDHPublicKey(key);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsDHUtils.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsDHUtils.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsDHUtils.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsDHUtils.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,76 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.agreement.DHBasicAgreement;
+import pdftk.org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.params.DHKeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPublicKeyParameters;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+public class TlsDHUtils
+{
+ static final BigInteger ONE = BigInteger.valueOf(1);
+ static final BigInteger TWO = BigInteger.valueOf(2);
+
+ public static byte[] calculateDHBasicAgreement(DHPublicKeyParameters publicKey,
+ DHPrivateKeyParameters privateKey)
+ {
+ DHBasicAgreement dhAgree = new DHBasicAgreement();
+ dhAgree.init(privateKey);
+ BigInteger agreement = dhAgree.calculateAgreement(publicKey);
+ return BigIntegers.asUnsignedByteArray(agreement);
+ }
+
+ public static AsymmetricCipherKeyPair generateDHKeyPair(SecureRandom random, DHParameters dhParams)
+ {
+ DHBasicKeyPairGenerator dhGen = new DHBasicKeyPairGenerator();
+ dhGen.init(new DHKeyGenerationParameters(random, dhParams));
+ return dhGen.generateKeyPair();
+ }
+
+ public static DHPrivateKeyParameters generateEphemeralClientKeyExchange(SecureRandom random, DHParameters dhParams, OutputStream os)
+ throws IOException
+ {
+ AsymmetricCipherKeyPair dhAgreeClientKeyPair = generateDHKeyPair(random, dhParams);
+ DHPrivateKeyParameters dhAgreeClientPrivateKey = (DHPrivateKeyParameters)dhAgreeClientKeyPair.getPrivate();
+
+ BigInteger Yc = ((DHPublicKeyParameters)dhAgreeClientKeyPair.getPublic()).getY();
+ byte[] keData = BigIntegers.asUnsignedByteArray(Yc);
+ TlsUtils.writeOpaque16(keData, os);
+
+ return dhAgreeClientPrivateKey;
+ }
+
+ public static DHPublicKeyParameters validateDHPublicKey(DHPublicKeyParameters key)
+ throws IOException
+ {
+ BigInteger Y = key.getY();
+ DHParameters params = key.getParameters();
+ BigInteger p = params.getP();
+ BigInteger g = params.getG();
+
+ if (!p.isProbablePrime(2))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ if (g.compareTo(TWO) < 0 || g.compareTo(p.subtract(TWO)) > 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ if (Y.compareTo(TWO) < 0 || Y.compareTo(p.subtract(ONE)) > 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ // TODO See RFC 2631 for more discussion of Diffie-Hellman validation
+
+ return key;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsDSASigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsDSASigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsDSASigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsDSASigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,34 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.DSA;
+import pdftk.org.bouncycastle.crypto.Signer;
+import pdftk.org.bouncycastle.crypto.digests.NullDigest;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.crypto.signers.DSADigestSigner;
+
+abstract class TlsDSASigner implements TlsSigner
+{
+ public byte[] calculateRawSignature(SecureRandom secureRandom, AsymmetricKeyParameter privateKey, byte[] md5andsha1)
+ throws CryptoException
+ {
+ // Note: Only use the SHA1 part of the hash
+ Signer signer = new DSADigestSigner(createDSAImpl(), new NullDigest());
+ signer.init(true, new ParametersWithRandom(privateKey, secureRandom));
+ signer.update(md5andsha1, 16, 20);
+ return signer.generateSignature();
+ }
+
+ public Signer createVerifyer(AsymmetricKeyParameter publicKey)
+ {
+ Signer verifyer = new DSADigestSigner(createDSAImpl(), new SHA1Digest());
+ verifyer.init(false, publicKey);
+ return verifyer;
+ }
+
+ protected abstract DSA createDSAImpl();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsDSSSigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsDSSSigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsDSSSigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsDSSSigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,19 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import pdftk.org.bouncycastle.crypto.DSA;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.DSAPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.signers.DSASigner;
+
+class TlsDSSSigner extends TlsDSASigner
+{
+ public boolean isValidPublicKey(AsymmetricKeyParameter publicKey)
+ {
+ return publicKey instanceof DSAPublicKeyParameters;
+ }
+
+ protected DSA createDSAImpl()
+ {
+ return new DSASigner();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsECDHEKeyExchange.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,112 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import pdftk.org.bouncycastle.crypto.Signer;
+import pdftk.org.bouncycastle.crypto.io.SignerInputStream;
+import pdftk.org.bouncycastle.crypto.params.ECDomainParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import pdftk.org.bouncycastle.math.ec.ECPoint;
+
+/**
+ * ECDHE key exchange (see RFC 4492)
+ */
+class TlsECDHEKeyExchange extends TlsECDHKeyExchange
+{
+ TlsECDHEKeyExchange(TlsClientContext context, int keyExchange)
+ {
+ super(context, keyExchange);
+ }
+
+ public void skipServerKeyExchange() throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void processServerKeyExchange(InputStream is)
+ throws IOException
+ {
+ SecurityParameters securityParameters = context.getSecurityParameters();
+
+ Signer signer = initSigner(tlsSigner, securityParameters);
+ InputStream sigIn = new SignerInputStream(is, signer);
+
+ short curveType = TlsUtils.readUint8(sigIn);
+ ECDomainParameters curve_params;
+
+ // Currently, we only support named curves
+ if (curveType == ECCurveType.named_curve)
+ {
+ int namedCurve = TlsUtils.readUint16(sigIn);
+
+ // TODO Check namedCurve is one we offered?
+
+ curve_params = NamedCurve.getECParameters(namedCurve);
+ }
+ else
+ {
+ // TODO Add support for explicit curve parameters (read from sigIn)
+
+ throw new TlsFatalAlert(AlertDescription.handshake_failure);
+ }
+
+ byte[] publicBytes = TlsUtils.readOpaque8(sigIn);
+
+ byte[] sigByte = TlsUtils.readOpaque16(is);
+ if (!signer.verifySignature(sigByte))
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_certificate);
+ }
+
+ // TODO Check curve_params not null
+
+ ECPoint Q = curve_params.getCurve().decodePoint(publicBytes);
+
+ this.ecAgreeServerPublicKey = validateECPublicKey(new ECPublicKeyParameters(Q, curve_params));
+ }
+
+ public void validateCertificateRequest(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ /*
+ * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable
+ * with ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is
+ * prohibited because the use of a long-term ECDH client key would jeopardize the
+ * forward secrecy property of these algorithms.
+ */
+ short[] types = certificateRequest.getCertificateTypes();
+ for (int i = 0; i < types.length; ++i)
+ {
+ switch (types[i])
+ {
+ case ClientCertificateType.rsa_sign:
+ case ClientCertificateType.dss_sign:
+ case ClientCertificateType.ecdsa_sign:
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ }
+
+ public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
+ {
+ if (clientCredentials instanceof TlsSignerCredentials)
+ {
+ // OK
+ }
+ else
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ protected Signer initSigner(TlsSigner tlsSigner, SecurityParameters securityParameters)
+ {
+ Signer signer = tlsSigner.createVerifyer(this.serverPublicKey);
+ signer.update(securityParameters.clientRandom, 0, securityParameters.clientRandom.length);
+ signer.update(securityParameters.serverRandom, 0, securityParameters.serverRandom.length);
+ return signer;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsECDHKeyExchange.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,239 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.x509.KeyUsage;
+import pdftk.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import pdftk.org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import pdftk.org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
+import pdftk.org.bouncycastle.crypto.generators.ECKeyPairGenerator;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ECDomainParameters;
+import pdftk.org.bouncycastle.crypto.params.ECKeyGenerationParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.util.PublicKeyFactory;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+/**
+ * ECDH key exchange (see RFC 4492)
+ */
+class TlsECDHKeyExchange implements TlsKeyExchange
+{
+ protected TlsClientContext context;
+ protected int keyExchange;
+ protected TlsSigner tlsSigner;
+
+ protected AsymmetricKeyParameter serverPublicKey;
+ protected ECPublicKeyParameters ecAgreeServerPublicKey;
+ protected TlsAgreementCredentials agreementCredentials;
+ protected ECPrivateKeyParameters ecAgreeClientPrivateKey = null;
+
+ TlsECDHKeyExchange(TlsClientContext context, int keyExchange)
+ {
+ switch (keyExchange)
+ {
+ case KeyExchangeAlgorithm.ECDHE_RSA:
+ this.tlsSigner = new TlsRSASigner();
+ break;
+ case KeyExchangeAlgorithm.ECDHE_ECDSA:
+ this.tlsSigner = new TlsECDSASigner();
+ break;
+ case KeyExchangeAlgorithm.ECDH_RSA:
+ case KeyExchangeAlgorithm.ECDH_ECDSA:
+ this.tlsSigner = null;
+ break;
+ default:
+ throw new IllegalArgumentException("unsupported key exchange algorithm");
+ }
+
+ this.context = context;
+ this.keyExchange = keyExchange;
+ }
+
+ public void skipServerCertificate() throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void processServerCertificate(Certificate serverCertificate) throws IOException
+ {
+ pdftk.org.bouncycastle.asn1.x509.Certificate x509Cert = serverCertificate.certs[0];
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+
+ try
+ {
+ this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
+ }
+ catch (RuntimeException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+ }
+
+ if (tlsSigner == null)
+ {
+ try
+ {
+ this.ecAgreeServerPublicKey = validateECPublicKey((ECPublicKeyParameters)this.serverPublicKey);
+ }
+ catch (ClassCastException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyAgreement);
+ }
+ else
+ {
+ if (!tlsSigner.isValidPublicKey(this.serverPublicKey))
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
+ }
+
+ // TODO
+ /*
+ * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the
+ * signing algorithm for the certificate must be the same as the algorithm for the
+ * certificate key."
+ */
+ }
+
+ public void skipServerKeyExchange() throws IOException
+ {
+ // do nothing
+ }
+
+ public void processServerKeyExchange(InputStream is)
+ throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void validateCertificateRequest(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ /*
+ * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable
+ * with ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is
+ * prohibited because the use of a long-term ECDH client key would jeopardize the
+ * forward secrecy property of these algorithms.
+ */
+ short[] types = certificateRequest.getCertificateTypes();
+ for (int i = 0; i < types.length; ++i)
+ {
+ switch (types[i])
+ {
+ case ClientCertificateType.rsa_sign:
+ case ClientCertificateType.dss_sign:
+ case ClientCertificateType.ecdsa_sign:
+ case ClientCertificateType.rsa_fixed_ecdh:
+ case ClientCertificateType.ecdsa_fixed_ecdh:
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ }
+
+ public void skipClientCredentials() throws IOException
+ {
+ this.agreementCredentials = null;
+ }
+
+ public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
+ {
+ if (clientCredentials instanceof TlsAgreementCredentials)
+ {
+ // TODO Validate client cert has matching parameters (see 'areOnSameCurve')?
+
+ this.agreementCredentials = (TlsAgreementCredentials)clientCredentials;
+ }
+ else if (clientCredentials instanceof TlsSignerCredentials)
+ {
+ // OK
+ }
+ else
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public void generateClientKeyExchange(OutputStream os) throws IOException
+ {
+ if (agreementCredentials == null)
+ {
+ generateEphemeralClientKeyExchange(ecAgreeServerPublicKey.getParameters(), os);
+ }
+ }
+
+ public byte[] generatePremasterSecret() throws IOException
+ {
+ if (agreementCredentials != null)
+ {
+ return agreementCredentials.generateAgreement(ecAgreeServerPublicKey);
+ }
+
+ return calculateECDHBasicAgreement(ecAgreeServerPublicKey, ecAgreeClientPrivateKey);
+ }
+
+ protected boolean areOnSameCurve(ECDomainParameters a, ECDomainParameters b)
+ {
+ // TODO Move to ECDomainParameters.equals() or other utility method?
+ return a.getCurve().equals(b.getCurve()) && a.getG().equals(b.getG())
+ && a.getN().equals(b.getN()) && a.getH().equals(b.getH());
+ }
+
+ protected byte[] externalizeKey(ECPublicKeyParameters keyParameters) throws IOException
+ {
+ // TODO Add support for compressed encoding and SPF extension
+
+ /*
+ * RFC 4492 5.7. ...an elliptic curve point in uncompressed or compressed format.
+ * Here, the format MUST conform to what the server has requested through a
+ * Supported Point Formats Extension if this extension was used, and MUST be
+ * uncompressed if this extension was not used.
+ */
+ return keyParameters.getQ().getEncoded();
+ }
+
+ protected AsymmetricCipherKeyPair generateECKeyPair(ECDomainParameters ecParams)
+ {
+ ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
+ ECKeyGenerationParameters keyGenerationParameters = new ECKeyGenerationParameters(ecParams,
+ context.getSecureRandom());
+ keyPairGenerator.init(keyGenerationParameters);
+ return keyPairGenerator.generateKeyPair();
+ }
+
+ protected void generateEphemeralClientKeyExchange(ECDomainParameters ecParams, OutputStream os)
+ throws IOException
+ {
+ AsymmetricCipherKeyPair ecAgreeClientKeyPair = generateECKeyPair(ecParams);
+ this.ecAgreeClientPrivateKey = (ECPrivateKeyParameters)ecAgreeClientKeyPair.getPrivate();
+
+ byte[] keData = externalizeKey((ECPublicKeyParameters)ecAgreeClientKeyPair.getPublic());
+ TlsUtils.writeOpaque8(keData, os);
+ }
+
+ protected byte[] calculateECDHBasicAgreement(ECPublicKeyParameters publicKey,
+ ECPrivateKeyParameters privateKey)
+ {
+ ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement();
+ basicAgreement.init(privateKey);
+ BigInteger agreement = basicAgreement.calculateAgreement(publicKey);
+ return BigIntegers.asUnsignedByteArray(agreement);
+ }
+
+ protected ECPublicKeyParameters validateECPublicKey(ECPublicKeyParameters key)
+ throws IOException
+ {
+ // TODO Check RFC 4492 for validation
+ return key;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsECDSASigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsECDSASigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsECDSASigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsECDSASigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,19 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import pdftk.org.bouncycastle.crypto.DSA;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.signers.ECDSASigner;
+
+class TlsECDSASigner extends TlsDSASigner
+{
+ public boolean isValidPublicKey(AsymmetricKeyParameter publicKey)
+ {
+ return publicKey instanceof ECPublicKeyParameters;
+ }
+
+ protected DSA createDSAImpl()
+ {
+ return new ECDSASigner();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsFatalAlert.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsFatalAlert.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsFatalAlert.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsFatalAlert.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,20 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+
+public class TlsFatalAlert extends IOException
+{
+ private static final long serialVersionUID = 3584313123679111168L;
+
+ private short alertDescription;
+
+ public TlsFatalAlert(short alertDescription)
+ {
+ this.alertDescription = alertDescription;
+ }
+
+ public short getAlertDescription()
+ {
+ return alertDescription;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsInputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsInputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsInputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsInputStream.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,37 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An InputStream for an TLS 1.0 connection.
+ */
+class TlsInputStream extends InputStream
+{
+ private byte[] buf = new byte[1];
+ private TlsProtocolHandler handler = null;
+
+ TlsInputStream(TlsProtocolHandler handler)
+ {
+ this.handler = handler;
+ }
+
+ public int read(byte[] buf, int offset, int len) throws IOException
+ {
+ return this.handler.readApplicationData(buf, offset, len);
+ }
+
+ public int read() throws IOException
+ {
+ if (this.read(buf) < 0)
+ {
+ return -1;
+ }
+ return buf[0] & 0xff;
+ }
+
+ public void close() throws IOException
+ {
+ handler.close();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsKeyExchange.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsKeyExchange.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsKeyExchange.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsKeyExchange.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,30 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * A generic interface for key exchange implementations in TLS 1.0.
+ */
+public interface TlsKeyExchange
+{
+ void skipServerCertificate() throws IOException;
+
+ void processServerCertificate(Certificate serverCertificate) throws IOException;
+
+ void skipServerKeyExchange() throws IOException;
+
+ void processServerKeyExchange(InputStream is)
+ throws IOException;
+
+ void validateCertificateRequest(CertificateRequest certificateRequest) throws IOException;
+
+ void skipClientCredentials() throws IOException;
+
+ void processClientCredentials(TlsCredentials clientCredentials) throws IOException;
+
+ void generateClientKeyExchange(OutputStream os) throws IOException;
+
+ byte[] generatePremasterSecret() throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsMac.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsMac.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsMac.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsMac.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,163 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.Mac;
+import pdftk.org.bouncycastle.crypto.macs.HMac;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.util.Arrays;
+
+/**
+ * A generic TLS MAC implementation, which can be used with any kind of Digest to act as
+ * an HMAC.
+ */
+public class TlsMac
+{
+ protected TlsClientContext context;
+ protected long seqNo;
+ protected byte[] secret;
+ protected Mac mac;
+
+ /**
+ * Generate a new instance of an TlsMac.
+ *
+ * @param context the TLS client context
+ * @param digest The digest to use.
+ * @param key_block A byte-array where the key for this mac is located.
+ * @param offset The number of bytes to skip, before the key starts in the buffer.
+ * @param len The length of the key.
+ */
+ public TlsMac(TlsClientContext context, Digest digest, byte[] key_block, int offset, int len)
+ {
+ this.context = context;
+ this.seqNo = 0;
+
+ KeyParameter param = new KeyParameter(key_block, offset, len);
+
+ this.secret = Arrays.clone(param.getKey());
+
+ boolean isTls = context.getServerVersion().getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+
+ if (isTls)
+ {
+ this.mac = new HMac(digest);
+ }
+ else
+ {
+ this.mac = new SSL3Mac(digest);
+ }
+
+ this.mac.init(param);
+ }
+
+ /**
+ * @return the MAC write secret
+ */
+ public byte[] getMACSecret()
+ {
+ return this.secret;
+ }
+
+ /**
+ * @return the current write sequence number
+ */
+ public long getSequenceNumber()
+ {
+ return this.seqNo;
+ }
+
+ /**
+ * Increment the current write sequence number
+ */
+ public void incSequenceNumber()
+ {
+ this.seqNo++;
+ }
+
+ /**
+ * @return The Keysize of the mac.
+ */
+ public int getSize()
+ {
+ return mac.getMacSize();
+ }
+
+ /**
+ * Calculate the mac for some given data.
+ *
+ * TlsMac will keep track of the sequence number internally.
+ *
+ * @param type The message type of the message.
+ * @param message A byte-buffer containing the message.
+ * @param offset The number of bytes to skip, before the message starts.
+ * @param len The length of the message.
+ * @return A new byte-buffer containing the mac value.
+ */
+ public byte[] calculateMac(short type, byte[] message, int offset, int len)
+ {
+ ProtocolVersion serverVersion = context.getServerVersion();
+ boolean isTls = serverVersion.getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+
+ ByteArrayOutputStream bosMac = new ByteArrayOutputStream(isTls ? 13 : 11);
+ try
+ {
+ TlsUtils.writeUint64(seqNo++, bosMac);
+ TlsUtils.writeUint8(type, bosMac);
+
+ if (isTls)
+ {
+ TlsUtils.writeVersion(serverVersion, bosMac);
+ }
+
+ TlsUtils.writeUint16(len, bosMac);
+ }
+ catch (IOException e)
+ {
+ // This should never happen
+ throw new IllegalStateException("Internal error during mac calculation");
+ }
+
+ byte[] macHeader = bosMac.toByteArray();
+ mac.update(macHeader, 0, macHeader.length);
+ mac.update(message, offset, len);
+
+ byte[] result = new byte[mac.getMacSize()];
+ mac.doFinal(result, 0);
+ return result;
+ }
+
+ public byte[] calculateMacConstantTime(short type, byte[] message, int offset, int len, int fullLength, byte[] dummyData)
+ {
+ // Actual MAC only calculated on 'len' bytes
+ byte[] result = calculateMac(type, message, offset, len);
+
+ ProtocolVersion serverVersion = context.getServerVersion();
+ boolean isTls = serverVersion.getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+
+ // ...but ensure a constant number of complete digest blocks are processed (per 'fullLength')
+ if (isTls)
+ {
+ // TODO Currently all TLS digests use a block size of 64, a suffix (length field) of 8, and padding (1+)
+ int db = 64, ds = 8;
+
+ int L1 = 13 + fullLength;
+ int L2 = 13 + len;
+
+ // How many extra full blocks do we need to calculate?
+ int extra = ((L1 + ds) / db) - ((L2 + ds) / db);
+
+ while (--extra >= 0)
+ {
+ mac.update(dummyData, 0, db);
+ }
+
+ // One more byte in case the implementation is "lazy" about processing blocks
+ mac.update(dummyData[0]);
+ mac.reset();
+ }
+
+ return result;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsNullCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsNullCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsNullCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsNullCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,24 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+/**
+ * A NULL CipherSuite in java, this should only be used during handshake.
+ */
+public class TlsNullCipher implements TlsCipher
+{
+ public byte[] encodePlaintext(short type, byte[] plaintext, int offset, int len)
+ {
+ return copyData(plaintext, offset, len);
+ }
+
+ public byte[] decodeCiphertext(short type, byte[] ciphertext, int offset, int len)
+ {
+ return copyData(ciphertext, offset, len);
+ }
+
+ protected byte[] copyData(byte[] text, int offset, int len)
+ {
+ byte[] result = new byte[len];
+ System.arraycopy(text, offset, result, 0, len);
+ return result;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsNullCompression.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsNullCompression.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsNullCompression.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsNullCompression.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,16 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.OutputStream;
+
+public class TlsNullCompression implements TlsCompression
+{
+ public OutputStream compress(OutputStream output)
+ {
+ return output;
+ }
+
+ public OutputStream decompress(OutputStream output)
+ {
+ return output;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsOutputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsOutputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsOutputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsOutputStream.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,39 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An OutputStream for an TLS connection.
+ */
+class TlsOutputStream extends OutputStream
+{
+ private byte[] buf = new byte[1];
+ private TlsProtocolHandler handler;
+
+ TlsOutputStream(TlsProtocolHandler handler)
+ {
+ this.handler = handler;
+ }
+
+ public void write(byte buf[], int offset, int len) throws IOException
+ {
+ this.handler.writeData(buf, offset, len);
+ }
+
+ public void write(int arg0) throws IOException
+ {
+ buf[0] = (byte)arg0;
+ this.write(buf, 0, 1);
+ }
+
+ public void close() throws IOException
+ {
+ handler.close();
+ }
+
+ public void flush() throws IOException
+ {
+ handler.flush();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsPSKIdentity.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsPSKIdentity.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsPSKIdentity.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsPSKIdentity.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,12 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+public interface TlsPSKIdentity
+{
+ void skipIdentityHint();
+
+ void notifyIdentityHint(byte[] psk_identity_hint);
+
+ byte[] getPSKIdentity();
+
+ byte[] getPSK();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsPSKKeyExchange.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,210 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.x509.KeyUsage;
+import pdftk.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+import pdftk.org.bouncycastle.crypto.util.PublicKeyFactory;
+
+class TlsPSKKeyExchange implements TlsKeyExchange
+{
+ protected TlsClientContext context;
+ protected int keyExchange;
+ protected TlsPSKIdentity pskIdentity;
+
+ protected byte[] psk_identity_hint = null;
+
+ protected DHPublicKeyParameters dhAgreeServerPublicKey = null;
+ protected DHPrivateKeyParameters dhAgreeClientPrivateKey = null;
+
+ protected AsymmetricKeyParameter serverPublicKey = null;
+ protected RSAKeyParameters rsaServerPublicKey = null;
+ protected byte[] premasterSecret;
+
+ TlsPSKKeyExchange(TlsClientContext context, int keyExchange, TlsPSKIdentity pskIdentity)
+ {
+ switch (keyExchange)
+ {
+ case KeyExchangeAlgorithm.PSK:
+ case KeyExchangeAlgorithm.RSA_PSK:
+ case KeyExchangeAlgorithm.DHE_PSK:
+ break;
+ default:
+ throw new IllegalArgumentException("unsupported key exchange algorithm");
+ }
+
+ this.context = context;
+ this.keyExchange = keyExchange;
+ this.pskIdentity = pskIdentity;
+ }
+
+ public void skipServerCertificate() throws IOException
+ {
+ if (keyExchange == KeyExchangeAlgorithm.RSA_PSK)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ public void processServerCertificate(Certificate serverCertificate) throws IOException
+ {
+ if (keyExchange != KeyExchangeAlgorithm.RSA_PSK)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ pdftk.org.bouncycastle.asn1.x509.Certificate x509Cert = serverCertificate.certs[0];
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+
+ try
+ {
+ this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
+ }
+ catch (RuntimeException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+ }
+
+ // Sanity check the PublicKeyFactory
+ if (this.serverPublicKey.isPrivate())
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ this.rsaServerPublicKey = validateRSAPublicKey((RSAKeyParameters) this.serverPublicKey);
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyEncipherment);
+
+ // TODO
+ /*
+ * Perform various checks per RFC2246 7.4.2: "Unless otherwise
+ * specified, the signing algorithm for the certificate must be the same
+ * as the algorithm for the certificate key."
+ */
+ }
+
+ public void skipServerKeyExchange() throws IOException
+ {
+ if (keyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ this.psk_identity_hint = new byte[0];
+ }
+
+ public void processServerKeyExchange(InputStream is) throws IOException
+ {
+ this.psk_identity_hint = TlsUtils.readOpaque16(is);
+
+ if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ {
+ byte[] pBytes = TlsUtils.readOpaque16(is);
+ byte[] gBytes = TlsUtils.readOpaque16(is);
+ byte[] YsBytes = TlsUtils.readOpaque16(is);
+
+ BigInteger p = new BigInteger(1, pBytes);
+ BigInteger g = new BigInteger(1, gBytes);
+ BigInteger Ys = new BigInteger(1, YsBytes);
+
+ this.dhAgreeServerPublicKey = TlsDHUtils.validateDHPublicKey(new DHPublicKeyParameters(Ys,
+ new DHParameters(p, g)));
+ }
+ else if (this.psk_identity_hint.length == 0)
+ {
+ // TODO Should we enforce that this message should have been skipped if hint is empty?
+// throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ public void validateCertificateRequest(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void skipClientCredentials() throws IOException
+ {
+ // OK
+ }
+
+ public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ public void generateClientKeyExchange(OutputStream os) throws IOException
+ {
+ if (psk_identity_hint == null || psk_identity_hint.length == 0)
+ {
+ pskIdentity.skipIdentityHint();
+ }
+ else
+ {
+ pskIdentity.notifyIdentityHint(psk_identity_hint);
+ }
+
+ byte[] psk_identity = pskIdentity.getPSKIdentity();
+
+ TlsUtils.writeOpaque16(psk_identity, os);
+
+ if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK)
+ {
+ this.premasterSecret = TlsRSAUtils.generateEncryptedPreMasterSecret(context,
+ this.rsaServerPublicKey, os);
+ }
+ else if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ {
+ this.dhAgreeClientPrivateKey = TlsDHUtils.generateEphemeralClientKeyExchange(
+ context.getSecureRandom(), dhAgreeServerPublicKey.getParameters(), os);
+ }
+ }
+
+ public byte[] generatePremasterSecret() throws IOException
+ {
+ byte[] psk = pskIdentity.getPSK();
+ byte[] other_secret = generateOtherSecret(psk.length);
+
+ ByteArrayOutputStream buf = new ByteArrayOutputStream(4 + other_secret.length + psk.length);
+ TlsUtils.writeOpaque16(other_secret, buf);
+ TlsUtils.writeOpaque16(psk, buf);
+ return buf.toByteArray();
+ }
+
+ protected byte[] generateOtherSecret(int pskLength)
+ {
+ if (this.keyExchange == KeyExchangeAlgorithm.DHE_PSK)
+ {
+ return TlsDHUtils.calculateDHBasicAgreement(dhAgreeServerPublicKey, dhAgreeClientPrivateKey);
+ }
+
+ if (this.keyExchange == KeyExchangeAlgorithm.RSA_PSK)
+ {
+ return this.premasterSecret;
+ }
+
+ return new byte[pskLength];
+ }
+
+ protected RSAKeyParameters validateRSAPublicKey(RSAKeyParameters key) throws IOException
+ {
+ // TODO What is the minimum bit length required?
+ // key.getModulus().bitLength();
+
+ if (!key.getExponent().isProbablePrime(2))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ return key;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsProtocolHandler.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsProtocolHandler.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsProtocolHandler.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsProtocolHandler.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,1260 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.SecureRandom;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.x500.X500Name;
+import pdftk.org.bouncycastle.crypto.prng.ThreadedSeedGenerator;
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Integers;
+
+/**
+ * An implementation of all high level protocols in TLS 1.0.
+ */
+public class TlsProtocolHandler
+{
+ private static final Integer EXT_RenegotiationInfo = Integers.valueOf(ExtensionType.renegotiation_info);
+
+ /*
+ * Our Connection states
+ */
+ private static final short CS_CLIENT_HELLO_SEND = 1;
+ private static final short CS_SERVER_HELLO_RECEIVED = 2;
+ private static final short CS_SERVER_CERTIFICATE_RECEIVED = 3;
+ private static final short CS_SERVER_KEY_EXCHANGE_RECEIVED = 4;
+ private static final short CS_CERTIFICATE_REQUEST_RECEIVED = 5;
+ private static final short CS_SERVER_HELLO_DONE_RECEIVED = 6;
+ private static final short CS_CLIENT_KEY_EXCHANGE_SEND = 7;
+ private static final short CS_CERTIFICATE_VERIFY_SEND = 8;
+ private static final short CS_CLIENT_CHANGE_CIPHER_SPEC_SEND = 9;
+ private static final short CS_CLIENT_FINISHED_SEND = 10;
+ private static final short CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED = 11;
+ private static final short CS_DONE = 12;
+
+ private static final byte[] emptybuf = new byte[0];
+
+ private static final String TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack";
+
+ /*
+ * Queues for data from some protocols.
+ */
+ private ByteQueue applicationDataQueue = new ByteQueue();
+ private ByteQueue changeCipherSpecQueue = new ByteQueue();
+ private ByteQueue alertQueue = new ByteQueue();
+ private ByteQueue handshakeQueue = new ByteQueue();
+
+ /*
+ * The Record Stream we use
+ */
+ private RecordStream rs;
+ private SecureRandom random;
+
+ private TlsInputStream tlsInputStream = null;
+ private TlsOutputStream tlsOutputStream = null;
+
+ private boolean closed = false;
+ private boolean failedWithError = false;
+ private boolean appDataReady = false;
+ private Hashtable clientExtensions;
+
+ private SecurityParameters securityParameters = null;
+
+ private TlsClientContextImpl tlsClientContext = null;
+ private TlsClient tlsClient = null;
+ private int[] offeredCipherSuites = null;
+ private short[] offeredCompressionMethods = null;
+ private TlsKeyExchange keyExchange = null;
+ private TlsAuthentication authentication = null;
+ private CertificateRequest certificateRequest = null;
+
+ private short connection_state = 0;
+
+ private static SecureRandom createSecureRandom()
+ {
+ /*
+ * We use our threaded seed generator to generate a good random seed. If the user
+ * has a better random seed, he should use the constructor with a SecureRandom.
+ */
+ ThreadedSeedGenerator tsg = new ThreadedSeedGenerator();
+ SecureRandom random = new SecureRandom();
+
+ /*
+ * Hopefully, 20 bytes in fast mode are good enough.
+ */
+ random.setSeed(tsg.generateSeed(20, true));
+
+ return random;
+ }
+
+ public TlsProtocolHandler(InputStream is, OutputStream os)
+ {
+ this(is, os, createSecureRandom());
+ }
+
+ public TlsProtocolHandler(InputStream is, OutputStream os, SecureRandom sr)
+ {
+ this.rs = new RecordStream(this, is, os);
+ this.random = sr;
+ }
+
+ protected void processData(short protocol, byte[] buf, int offset, int len) throws IOException
+ {
+ /*
+ * Have a look at the protocol type, and add it to the correct queue.
+ */
+ switch (protocol)
+ {
+ case ContentType.change_cipher_spec:
+ changeCipherSpecQueue.addData(buf, offset, len);
+ processChangeCipherSpec();
+ break;
+ case ContentType.alert:
+ alertQueue.addData(buf, offset, len);
+ processAlert();
+ break;
+ case ContentType.handshake:
+ handshakeQueue.addData(buf, offset, len);
+ processHandshake();
+ break;
+ case ContentType.application_data:
+ if (!appDataReady)
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ }
+ applicationDataQueue.addData(buf, offset, len);
+ processApplicationData();
+ break;
+ default:
+ /*
+ * Uh, we don't know this protocol.
+ *
+ * RFC2246 defines on page 13, that we should ignore this.
+ */
+ }
+ }
+
+ private void processHandshake() throws IOException
+ {
+ boolean read;
+ do
+ {
+ read = false;
+ /*
+ * We need the first 4 bytes, they contain type and length of the message.
+ */
+ if (handshakeQueue.size() >= 4)
+ {
+ byte[] beginning = new byte[4];
+ handshakeQueue.read(beginning, 0, 4, 0);
+ ByteArrayInputStream bis = new ByteArrayInputStream(beginning);
+ short type = TlsUtils.readUint8(bis);
+ int len = TlsUtils.readUint24(bis);
+
+ /*
+ * Check if we have enough bytes in the buffer to read the full message.
+ */
+ if (handshakeQueue.size() >= (len + 4))
+ {
+ /*
+ * Read the message.
+ */
+ byte[] buf = new byte[len];
+ handshakeQueue.read(buf, 0, len, 4);
+ handshakeQueue.removeData(len + 4);
+
+ /*
+ * RFC 2246 7.4.9. The value handshake_messages includes all handshake
+ * messages starting at client hello up to, but not including, this
+ * finished message. [..] Note: [Also,] Hello Request messages are
+ * omitted from handshake hashes.
+ */
+ switch (type)
+ {
+ case HandshakeType.hello_request:
+ case HandshakeType.finished:
+ break;
+ default:
+ rs.updateHandshakeData(beginning, 0, 4);
+ rs.updateHandshakeData(buf, 0, len);
+ break;
+ }
+
+ /*
+ * Now, parse the message.
+ */
+ processHandshakeMessage(type, buf);
+ read = true;
+ }
+ }
+ }
+ while (read);
+ }
+
+ private void processHandshakeMessage(short type, byte[] buf) throws IOException
+ {
+ ByteArrayInputStream is = new ByteArrayInputStream(buf);
+
+ switch (type)
+ {
+ case HandshakeType.certificate:
+ {
+ switch (connection_state)
+ {
+ case CS_SERVER_HELLO_RECEIVED:
+ {
+ // Parse the Certificate message and send to cipher suite
+
+ Certificate serverCertificate = Certificate.parse(is);
+
+ assertEmpty(is);
+
+ this.keyExchange.processServerCertificate(serverCertificate);
+
+ this.authentication = tlsClient.getAuthentication();
+ this.authentication.notifyServerCertificate(serverCertificate);
+
+ break;
+ }
+ default:
+ this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ }
+
+ connection_state = CS_SERVER_CERTIFICATE_RECEIVED;
+ break;
+ }
+ case HandshakeType.finished:
+ switch (connection_state)
+ {
+ case CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED:
+ /*
+ * Read the checksum from the finished message, it has always 12
+ * bytes for TLS 1.0 and 36 for SSLv3.
+ */
+ boolean isTls = tlsClientContext.getServerVersion().getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+
+ int checksumLength = isTls ? 12 : 36;
+ byte[] serverVerifyData = new byte[checksumLength];
+ TlsUtils.readFully(serverVerifyData, is);
+
+ assertEmpty(is);
+
+ /*
+ * Calculate our own checksum.
+ */
+ byte[] expectedServerVerifyData = TlsUtils.calculateVerifyData(tlsClientContext,
+ "server finished", rs.getCurrentHash(TlsUtils.SSL_SERVER));
+
+ /*
+ * Compare both checksums.
+ */
+ if (!Arrays.constantTimeAreEqual(expectedServerVerifyData, serverVerifyData))
+ {
+ /*
+ * Wrong checksum in the finished message.
+ */
+ this.failWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
+ }
+
+ connection_state = CS_DONE;
+
+ /*
+ * We are now ready to receive application data.
+ */
+ this.appDataReady = true;
+ break;
+ default:
+ this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ }
+ break;
+ case HandshakeType.server_hello:
+ switch (connection_state)
+ {
+ case CS_CLIENT_HELLO_SEND:
+ /*
+ * Read the server hello message
+ */
+ ProtocolVersion server_version = TlsUtils.readVersion(is);
+ ProtocolVersion client_version = this.tlsClientContext.getClientVersion();
+ if (server_version.getFullVersion() > client_version.getFullVersion())
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ }
+
+ this.tlsClientContext.setServerVersion(server_version);
+ this.tlsClient.notifyServerVersion(server_version);
+
+ /*
+ * Read the server random
+ */
+ securityParameters.serverRandom = new byte[32];
+ TlsUtils.readFully(securityParameters.serverRandom, is);
+
+ byte[] sessionID = TlsUtils.readOpaque8(is);
+ if (sessionID.length > 32)
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ }
+
+ this.tlsClient.notifySessionID(sessionID);
+
+ /*
+ * Find out which CipherSuite the server has chosen and check that
+ * it was one of the offered ones.
+ */
+ int selectedCipherSuite = TlsUtils.readUint16(is);
+ if (!arrayContains(offeredCipherSuites, selectedCipherSuite)
+ || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ }
+
+ this.tlsClient.notifySelectedCipherSuite(selectedCipherSuite);
+
+ /*
+ * Find out which CompressionMethod the server has chosen and check that
+ * it was one of the offered ones.
+ */
+ short selectedCompressionMethod = TlsUtils.readUint8(is);
+ if (!arrayContains(offeredCompressionMethods, selectedCompressionMethod))
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.illegal_parameter);
+ }
+
+ this.tlsClient.notifySelectedCompressionMethod(selectedCompressionMethod);
+
+ /*
+ * RFC3546 2.2 The extended server hello message format MAY be
+ * sent in place of the server hello message when the client has
+ * requested extended functionality via the extended client hello
+ * message specified in Section 2.1. ... Note that the extended
+ * server hello message is only sent in response to an extended
+ * client hello message. This prevents the possibility that the
+ * extended server hello message could "break" existing TLS 1.0
+ * clients.
+ */
+
+ /*
+ * TODO RFC 3546 2.3 If [...] the older session is resumed, then
+ * the server MUST ignore extensions appearing in the client
+ * hello, and send a server hello containing no extensions.
+ */
+
+ // Integer -> byte[]
+ Hashtable serverExtensions = new Hashtable();
+
+ if (is.available() > 0)
+ {
+ // Process extensions from extended server hello
+ byte[] extBytes = TlsUtils.readOpaque16(is);
+
+ ByteArrayInputStream ext = new ByteArrayInputStream(extBytes);
+ while (ext.available() > 0)
+ {
+ Integer extType = Integers.valueOf(TlsUtils.readUint16(ext));
+ byte[] extValue = TlsUtils.readOpaque16(ext);
+
+ /*
+ * RFC 5746 Note that sending a "renegotiation_info"
+ * extension in response to a ClientHello containing only
+ * the SCSV is an explicit exception to the prohibition in
+ * RFC 5246, Section 7.4.1.4, on the server sending
+ * unsolicited extensions and is only allowed because the
+ * client is signaling its willingness to receive the
+ * extension via the TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+ * SCSV. TLS implementations MUST continue to comply with
+ * Section 7.4.1.4 for all other extensions.
+ */
+
+ if (!extType.equals(EXT_RenegotiationInfo)
+ && clientExtensions.get(extType) == null)
+ {
+ /*
+ * RFC 3546 2.3 Note that for all extension types
+ * (including those defined in future), the extension
+ * type MUST NOT appear in the extended server hello
+ * unless the same extension type appeared in the
+ * corresponding client hello. Thus clients MUST abort
+ * the handshake if they receive an extension type in
+ * the extended server hello that they did not request
+ * in the associated (extended) client hello.
+ */
+ this.failWithError(AlertLevel.fatal,
+ AlertDescription.unsupported_extension);
+ }
+
+ if (serverExtensions.containsKey(extType))
+ {
+ /*
+ * RFC 3546 2.3 Also note that when multiple
+ * extensions of different types are present in the
+ * extended client hello or the extended server hello,
+ * the extensions may appear in any order. There MUST
+ * NOT be more than one extension of the same type.
+ */
+ this.failWithError(AlertLevel.fatal,
+ AlertDescription.illegal_parameter);
+ }
+
+ serverExtensions.put(extType, extValue);
+ }
+ }
+
+ assertEmpty(is);
+
+ /*
+ * RFC 5746 3.4. When a ServerHello is received, the client MUST
+ * check if it includes the "renegotiation_info" extension:
+ */
+ {
+ boolean secure_negotiation = serverExtensions.containsKey(EXT_RenegotiationInfo);
+
+ /*
+ * If the extension is present, set the secure_renegotiation
+ * flag to TRUE. The client MUST then verify that the length
+ * of the "renegotiated_connection" field is zero, and if it
+ * is not, MUST abort the handshake (by sending a fatal
+ * handshake_failure alert).
+ */
+ if (secure_negotiation)
+ {
+ byte[] renegExtValue = (byte[])serverExtensions.get(EXT_RenegotiationInfo);
+
+ if (!Arrays.constantTimeAreEqual(renegExtValue,
+ createRenegotiationInfo(emptybuf)))
+ {
+ this.failWithError(AlertLevel.fatal,
+ AlertDescription.handshake_failure);
+ }
+ }
+
+ tlsClient.notifySecureRenegotiation(secure_negotiation);
+ }
+
+ if (clientExtensions != null)
+ {
+ tlsClient.processServerExtensions(serverExtensions);
+ }
+
+ this.keyExchange = tlsClient.getKeyExchange();
+
+ connection_state = CS_SERVER_HELLO_RECEIVED;
+ break;
+ default:
+ this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ }
+ break;
+ case HandshakeType.server_hello_done:
+ switch (connection_state)
+ {
+ case CS_SERVER_HELLO_RECEIVED:
+
+ // There was no server certificate message; check it's OK
+ this.keyExchange.skipServerCertificate();
+ this.authentication = null;
+
+ // NB: Fall through to next case label
+
+ case CS_SERVER_CERTIFICATE_RECEIVED:
+
+ // There was no server key exchange message; check it's OK
+ this.keyExchange.skipServerKeyExchange();
+
+ // NB: Fall through to next case label
+
+ case CS_SERVER_KEY_EXCHANGE_RECEIVED:
+ case CS_CERTIFICATE_REQUEST_RECEIVED:
+
+ assertEmpty(is);
+
+ connection_state = CS_SERVER_HELLO_DONE_RECEIVED;
+
+ TlsCredentials clientCreds = null;
+ if (certificateRequest == null)
+ {
+ this.keyExchange.skipClientCredentials();
+ }
+ else
+ {
+ clientCreds = this.authentication.getClientCredentials(certificateRequest);
+
+ if (clientCreds == null)
+ {
+ this.keyExchange.skipClientCredentials();
+
+ boolean isTls = tlsClientContext.getServerVersion().getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+
+ if (isTls)
+ {
+ sendClientCertificate(Certificate.EMPTY_CHAIN);
+ }
+ else
+ {
+ sendAlert(AlertLevel.warning, AlertDescription.no_certificate);
+ }
+ }
+ else
+ {
+ this.keyExchange.processClientCredentials(clientCreds);
+
+ sendClientCertificate(clientCreds.getCertificate());
+ }
+ }
+
+ /*
+ * Send the client key exchange message, depending on the key
+ * exchange we are using in our CipherSuite.
+ */
+ sendClientKeyExchange();
+
+ connection_state = CS_CLIENT_KEY_EXCHANGE_SEND;
+
+ /*
+ * Calculate the master_secret
+ */
+ byte[] pms = this.keyExchange.generatePremasterSecret();
+
+ securityParameters.masterSecret = TlsUtils.calculateMasterSecret(
+ this.tlsClientContext, pms);
+
+ // TODO Is there a way to ensure the data is really overwritten?
+ /*
+ * RFC 2246 8.1. The pre_master_secret should be deleted from
+ * memory once the master_secret has been computed.
+ */
+ Arrays.fill(pms, (byte)0);
+
+ if (clientCreds != null && clientCreds instanceof TlsSignerCredentials)
+ {
+ TlsSignerCredentials signerCreds = (TlsSignerCredentials)clientCreds;
+ byte[] md5andsha1 = rs.getCurrentHash(null);
+ byte[] clientCertificateSignature = signerCreds.generateCertificateSignature(
+ md5andsha1);
+ sendCertificateVerify(clientCertificateSignature);
+
+ connection_state = CS_CERTIFICATE_VERIFY_SEND;
+ }
+
+ /*
+ * Now, we send change cipher state
+ */
+ byte[] cmessage = new byte[1];
+ cmessage[0] = 1;
+ rs.writeMessage(ContentType.change_cipher_spec, cmessage, 0,
+ cmessage.length);
+
+ connection_state = CS_CLIENT_CHANGE_CIPHER_SPEC_SEND;
+
+ /*
+ * Initialize our cipher suite
+ */
+ rs.clientCipherSpecDecided(tlsClient.getCompression(), tlsClient.getCipher());
+
+ /*
+ * Send our finished message.
+ */
+ byte[] clientVerifyData = TlsUtils.calculateVerifyData(tlsClientContext,
+ "client finished", rs.getCurrentHash(TlsUtils.SSL_CLIENT));
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ TlsUtils.writeUint8(HandshakeType.finished, bos);
+ TlsUtils.writeOpaque24(clientVerifyData, bos);
+ byte[] message = bos.toByteArray();
+
+ rs.writeMessage(ContentType.handshake, message, 0, message.length);
+
+ this.connection_state = CS_CLIENT_FINISHED_SEND;
+ break;
+ default:
+ this.failWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
+ }
+ break;
+ case HandshakeType.server_key_exchange:
+ {
+ switch (connection_state)
+ {
+ case CS_SERVER_HELLO_RECEIVED:
+
+ // There was no server certificate message; check it's OK
+ this.keyExchange.skipServerCertificate();
+ this.authentication = null;
+
+ // NB: Fall through to next case label
+
+ case CS_SERVER_CERTIFICATE_RECEIVED:
+
+ this.keyExchange.processServerKeyExchange(is);
+
+ assertEmpty(is);
+ break;
+
+ default:
+ this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ }
+
+ this.connection_state = CS_SERVER_KEY_EXCHANGE_RECEIVED;
+ break;
+ }
+ case HandshakeType.certificate_request:
+ {
+ switch (connection_state)
+ {
+ case CS_SERVER_CERTIFICATE_RECEIVED:
+
+ // There was no server key exchange message; check it's OK
+ this.keyExchange.skipServerKeyExchange();
+
+ // NB: Fall through to next case label
+
+ case CS_SERVER_KEY_EXCHANGE_RECEIVED:
+ {
+ if (this.authentication == null)
+ {
+ /*
+ * RFC 2246 7.4.4. It is a fatal handshake_failure alert
+ * for an anonymous server to request client identification.
+ */
+ this.failWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
+ }
+
+ int numTypes = TlsUtils.readUint8(is);
+ short[] certificateTypes = new short[numTypes];
+ for (int i = 0; i < numTypes; ++i)
+ {
+ certificateTypes[i] = TlsUtils.readUint8(is);
+ }
+
+ byte[] authorities = TlsUtils.readOpaque16(is);
+
+ assertEmpty(is);
+
+ Vector authorityDNs = new Vector();
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(authorities);
+ while (bis.available() > 0)
+ {
+ byte[] dnBytes = TlsUtils.readOpaque16(bis);
+ authorityDNs.addElement(X500Name.getInstance(ASN1Primitive.fromByteArray(dnBytes)));
+ }
+
+ this.certificateRequest = new CertificateRequest(certificateTypes,
+ authorityDNs);
+ this.keyExchange.validateCertificateRequest(this.certificateRequest);
+
+ break;
+ }
+ default:
+ this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ }
+
+ this.connection_state = CS_CERTIFICATE_REQUEST_RECEIVED;
+ break;
+ }
+ case HandshakeType.hello_request:
+ /*
+ * RFC 2246 7.4.1.1 Hello request This message will be ignored by the
+ * client if the client is currently negotiating a session. This message
+ * may be ignored by the client if it does not wish to renegotiate a
+ * session, or the client may, if it wishes, respond with a
+ * no_renegotiation alert.
+ */
+ if (connection_state == CS_DONE)
+ {
+ // Renegotiation not supported yet
+ sendAlert(AlertLevel.warning, AlertDescription.no_renegotiation);
+ }
+ break;
+ case HandshakeType.client_key_exchange:
+ case HandshakeType.certificate_verify:
+ case HandshakeType.client_hello:
+ default:
+ // We do not support this!
+ this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ break;
+ }
+ }
+
+ private void processApplicationData()
+ {
+ /*
+ * There is nothing we need to do here.
+ *
+ * This function could be used for callbacks when application data arrives in the
+ * future.
+ */
+ }
+
+ private void processAlert() throws IOException
+ {
+ while (alertQueue.size() >= 2)
+ {
+ /*
+ * An alert is always 2 bytes. Read the alert.
+ */
+ byte[] tmp = new byte[2];
+ alertQueue.read(tmp, 0, 2, 0);
+ alertQueue.removeData(2);
+ short level = tmp[0];
+ short description = tmp[1];
+ if (level == AlertLevel.fatal)
+ {
+ /*
+ * This is a fatal error.
+ */
+ this.failedWithError = true;
+ this.closed = true;
+ /*
+ * Now try to close the stream, ignore errors.
+ */
+ try
+ {
+ rs.close();
+ }
+ catch (Exception e)
+ {
+
+ }
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+ else
+ {
+ /*
+ * This is just a warning.
+ */
+ if (description == AlertDescription.close_notify)
+ {
+ /*
+ * Close notify
+ */
+ this.failWithError(AlertLevel.warning, AlertDescription.close_notify);
+ }
+ /*
+ * If it is just a warning, we continue.
+ */
+ }
+ }
+ }
+
+ /**
+ * This method is called, when a change cipher spec message is received.
+ *
+ * @throws IOException If the message has an invalid content or the handshake is not
+ * in the correct state.
+ */
+ private void processChangeCipherSpec() throws IOException
+ {
+ while (changeCipherSpecQueue.size() > 0)
+ {
+ /*
+ * A change cipher spec message is only one byte with the value 1.
+ */
+ byte[] b = new byte[1];
+ changeCipherSpecQueue.read(b, 0, 1, 0);
+ changeCipherSpecQueue.removeData(1);
+ if (b[0] != 1)
+ {
+ /*
+ * This should never happen.
+ */
+ this.failWithError(AlertLevel.fatal, AlertDescription.unexpected_message);
+ }
+
+ /*
+ * Check if we are in the correct connection state.
+ */
+ if (this.connection_state != CS_CLIENT_FINISHED_SEND)
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.handshake_failure);
+ }
+
+ rs.serverClientSpecReceived();
+
+ this.connection_state = CS_SERVER_CHANGE_CIPHER_SPEC_RECEIVED;
+ }
+ }
+
+ private void sendClientCertificate(Certificate clientCert) throws IOException
+ {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ TlsUtils.writeUint8(HandshakeType.certificate, bos);
+
+ // Reserve space for length
+ TlsUtils.writeUint24(0, bos);
+
+ clientCert.encode(bos);
+ byte[] message = bos.toByteArray();
+
+ // Patch actual length back in
+ TlsUtils.writeUint24(message.length - 4, message, 1);
+
+ rs.writeMessage(ContentType.handshake, message, 0, message.length);
+ }
+
+ private void sendClientKeyExchange() throws IOException
+ {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ TlsUtils.writeUint8(HandshakeType.client_key_exchange, bos);
+
+ // Reserve space for length
+ TlsUtils.writeUint24(0, bos);
+
+ this.keyExchange.generateClientKeyExchange(bos);
+ byte[] message = bos.toByteArray();
+
+ // Patch actual length back in
+ TlsUtils.writeUint24(message.length - 4, message, 1);
+
+ rs.writeMessage(ContentType.handshake, message, 0, message.length);
+ }
+
+ private void sendCertificateVerify(byte[] data) throws IOException
+ {
+ /*
+ * Send signature of handshake messages so far to prove we are the owner of the
+ * cert See RFC 2246 sections 4.7, 7.4.3 and 7.4.8
+ */
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ TlsUtils.writeUint8(HandshakeType.certificate_verify, bos);
+ TlsUtils.writeUint24(data.length + 2, bos);
+ TlsUtils.writeOpaque16(data, bos);
+ byte[] message = bos.toByteArray();
+
+ rs.writeMessage(ContentType.handshake, message, 0, message.length);
+ }
+
+ /**
+ * Connects to the remote system.
+ *
+ * @param verifyer Will be used when a certificate is received to verify that this
+ * certificate is accepted by the client.
+ * @throws IOException If handshake was not successful.
+ *
+ * @deprecated use version taking TlsClient
+ */
+ public void connect(CertificateVerifyer verifyer) throws IOException
+ {
+ this.connect(new LegacyTlsClient(verifyer));
+ }
+
+ /**
+ * Connects to the remote system using client authentication
+ *
+ * @param tlsClient
+ * @throws IOException If handshake was not successful.
+ */
+ public void connect(TlsClient tlsClient) throws IOException
+ {
+ if (tlsClient == null)
+ {
+ throw new IllegalArgumentException("'tlsClient' cannot be null");
+ }
+ if (this.tlsClient != null)
+ {
+ throw new IllegalStateException("connect can only be called once");
+ }
+
+ /*
+ * Send Client hello
+ *
+ * First, generate some random data.
+ */
+ this.securityParameters = new SecurityParameters();
+ this.securityParameters.clientRandom = new byte[32];
+ random.nextBytes(securityParameters.clientRandom);
+ TlsUtils.writeGMTUnixTime(securityParameters.clientRandom, 0);
+
+ this.tlsClientContext = new TlsClientContextImpl(random, securityParameters);
+
+ this.rs.init(tlsClientContext);
+
+ this.tlsClient = tlsClient;
+ this.tlsClient.init(tlsClientContext);
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ ProtocolVersion client_version = this.tlsClient.getClientVersion();
+ this.tlsClientContext.setClientVersion(client_version);
+ // TODO For SSLv3 support, server version needs to be set to ProtocolVersion.SSLv3
+ this.tlsClientContext.setServerVersion(client_version);
+ TlsUtils.writeVersion(client_version, os);
+
+ os.write(securityParameters.clientRandom);
+
+ /*
+ * Length of Session id
+ */
+ TlsUtils.writeUint8((short)0, os);
+
+ /*
+ * Cipher suites
+ */
+ this.offeredCipherSuites = this.tlsClient.getCipherSuites();
+
+ // Integer -> byte[]
+ this.clientExtensions = this.tlsClient.getClientExtensions();
+
+ // Cipher Suites (and SCSV)
+ {
+ /*
+ * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info"
+ * extension, or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite
+ * value in the ClientHello. Including both is NOT RECOMMENDED.
+ */
+ boolean noRenegExt = clientExtensions == null
+ || clientExtensions.get(EXT_RenegotiationInfo) == null;
+
+ int count = offeredCipherSuites.length;
+ if (noRenegExt)
+ {
+ // Note: 1 extra slot for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+ ++count;
+ }
+
+ TlsUtils.writeUint16(2 * count, os);
+ TlsUtils.writeUint16Array(offeredCipherSuites, os);
+
+ if (noRenegExt)
+ {
+ TlsUtils.writeUint16(CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV, os);
+ }
+ }
+
+ // Compression methods
+ this.offeredCompressionMethods = this.tlsClient.getCompressionMethods();
+
+ TlsUtils.writeUint8((short)offeredCompressionMethods.length, os);
+ TlsUtils.writeUint8Array(offeredCompressionMethods, os);
+
+ // Extensions
+ if (clientExtensions != null)
+ {
+ ByteArrayOutputStream ext = new ByteArrayOutputStream();
+
+ Enumeration keys = clientExtensions.keys();
+ while (keys.hasMoreElements())
+ {
+ Integer extType = (Integer)keys.nextElement();
+ writeExtension(ext, extType, (byte[])clientExtensions.get(extType));
+ }
+
+ TlsUtils.writeOpaque16(ext.toByteArray(), os);
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ TlsUtils.writeUint8(HandshakeType.client_hello, bos);
+ TlsUtils.writeUint24(os.size(), bos);
+ bos.write(os.toByteArray());
+ byte[] message = bos.toByteArray();
+
+ safeWriteMessage(ContentType.handshake, message, 0, message.length);
+
+ connection_state = CS_CLIENT_HELLO_SEND;
+
+ /*
+ * We will now read data, until we have completed the handshake.
+ */
+ while (connection_state != CS_DONE)
+ {
+ safeReadData();
+ }
+
+ this.tlsInputStream = new TlsInputStream(this);
+ this.tlsOutputStream = new TlsOutputStream(this);
+ }
+
+ /**
+ * Read data from the network. The method will return immediately, if there is still
+ * some data left in the buffer, or block until some application data has been read
+ * from the network.
+ *
+ * @param buf The buffer where the data will be copied to.
+ * @param offset The position where the data will be placed in the buffer.
+ * @param len The maximum number of bytes to read.
+ * @return The number of bytes read.
+ * @throws IOException If something goes wrong during reading data.
+ */
+ protected int readApplicationData(byte[] buf, int offset, int len) throws IOException
+ {
+ while (applicationDataQueue.size() == 0)
+ {
+ /*
+ * We need to read some data.
+ */
+ if (this.closed)
+ {
+ if (this.failedWithError)
+ {
+ /*
+ * Something went terribly wrong, we should throw an IOException
+ */
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+
+ /*
+ * Connection has been closed, there is no more data to read.
+ */
+ return -1;
+ }
+
+ safeReadData();
+ }
+ len = Math.min(len, applicationDataQueue.size());
+ applicationDataQueue.read(buf, offset, len, 0);
+ applicationDataQueue.removeData(len);
+ return len;
+ }
+
+ private void safeReadData() throws IOException
+ {
+ try
+ {
+ rs.readData();
+ }
+ catch (TlsFatalAlert e)
+ {
+ if (!this.closed)
+ {
+ this.failWithError(AlertLevel.fatal, e.getAlertDescription());
+ }
+ throw e;
+ }
+ catch (IOException e)
+ {
+ if (!this.closed)
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.internal_error);
+ }
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ if (!this.closed)
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.internal_error);
+ }
+ throw e;
+ }
+ }
+
+ private void safeWriteMessage(short type, byte[] buf, int offset, int len) throws IOException
+ {
+ try
+ {
+ rs.writeMessage(type, buf, offset, len);
+ }
+ catch (TlsFatalAlert e)
+ {
+ if (!this.closed)
+ {
+ this.failWithError(AlertLevel.fatal, e.getAlertDescription());
+ }
+ throw e;
+ }
+ catch (IOException e)
+ {
+ if (!closed)
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.internal_error);
+ }
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ if (!closed)
+ {
+ this.failWithError(AlertLevel.fatal, AlertDescription.internal_error);
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Send some application data to the remote system.
+ *
+ * The method will handle fragmentation internally.
+ *
+ * @param buf The buffer with the data.
+ * @param offset The position in the buffer where the data is placed.
+ * @param len The length of the data.
+ * @throws IOException If something goes wrong during sending.
+ */
+ protected void writeData(byte[] buf, int offset, int len) throws IOException
+ {
+ if (this.closed)
+ {
+ if (this.failedWithError)
+ {
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+
+ throw new IOException("Sorry, connection has been closed, you cannot write more data");
+ }
+
+ /*
+ * Protect against known IV attack!
+ *
+ * DO NOT REMOVE THIS LINE, EXCEPT YOU KNOW EXACTLY WHAT YOU ARE DOING HERE.
+ */
+ safeWriteMessage(ContentType.application_data, emptybuf, 0, 0);
+
+ do
+ {
+ /*
+ * We are only allowed to write fragments up to 2^14 bytes.
+ */
+ int toWrite = Math.min(len, 1 << 14);
+
+ safeWriteMessage(ContentType.application_data, buf, offset, toWrite);
+
+ offset += toWrite;
+ len -= toWrite;
+ }
+ while (len > 0);
+
+ }
+
+ /**
+ * @return An OutputStream which can be used to send data.
+ */
+ public OutputStream getOutputStream()
+ {
+ return this.tlsOutputStream;
+ }
+
+ /**
+ * @return An InputStream which can be used to read data.
+ */
+ public InputStream getInputStream()
+ {
+ return this.tlsInputStream;
+ }
+
+ /**
+ * Terminate this connection with an alert.
+ *
+ * Can be used for normal closure too.
+ *
+ * @param alertLevel The level of the alert, an be AlertLevel.fatal or AL_warning.
+ * @param alertDescription The exact alert message.
+ * @throws IOException If alert was fatal.
+ */
+ private void failWithError(short alertLevel, short alertDescription) throws IOException
+ {
+ /*
+ * Check if the connection is still open.
+ */
+ if (!closed)
+ {
+ /*
+ * Prepare the message
+ */
+ this.closed = true;
+
+ if (alertLevel == AlertLevel.fatal)
+ {
+ /*
+ * This is a fatal message.
+ */
+ this.failedWithError = true;
+ }
+ sendAlert(alertLevel, alertDescription);
+ rs.close();
+ if (alertLevel == AlertLevel.fatal)
+ {
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+ }
+ else
+ {
+ throw new IOException(TLS_ERROR_MESSAGE);
+ }
+ }
+
+ private void sendAlert(short alertLevel, short alertDescription) throws IOException
+ {
+ byte[] error = new byte[2];
+ error[0] = (byte)alertLevel;
+ error[1] = (byte)alertDescription;
+
+ rs.writeMessage(ContentType.alert, error, 0, 2);
+ }
+
+ /**
+ * Closes this connection.
+ *
+ * @throws IOException If something goes wrong during closing.
+ */
+ public void close() throws IOException
+ {
+ if (!closed)
+ {
+ this.failWithError(AlertLevel.warning, AlertDescription.close_notify);
+ }
+ }
+
+ /**
+ * Make sure the InputStream is now empty. Fail otherwise.
+ *
+ * @param is The InputStream to check.
+ * @throws IOException If is is not empty.
+ */
+ protected void assertEmpty(ByteArrayInputStream is) throws IOException
+ {
+ if (is.available() > 0)
+ {
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ }
+ }
+
+ protected void flush() throws IOException
+ {
+ rs.flush();
+ }
+
+ private static boolean arrayContains(short[] a, short n)
+ {
+ for (int i = 0; i < a.length; ++i)
+ {
+ if (a[i] == n)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean arrayContains(int[] a, int n)
+ {
+ for (int i = 0; i < a.length; ++i)
+ {
+ if (a[i] == n)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static byte[] createRenegotiationInfo(byte[] renegotiated_connection)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ TlsUtils.writeOpaque8(renegotiated_connection, buf);
+ return buf.toByteArray();
+ }
+
+ private static void writeExtension(OutputStream output, Integer extType, byte[] extValue)
+ throws IOException
+ {
+ TlsUtils.writeUint16(extType.intValue(), output);
+ TlsUtils.writeOpaque16(extValue, output);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,165 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import pdftk.org.bouncycastle.asn1.x509.KeyUsage;
+import pdftk.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+import pdftk.org.bouncycastle.crypto.util.PublicKeyFactory;
+
+/**
+ * TLS 1.0 and SSLv3 RSA key exchange.
+ */
+class TlsRSAKeyExchange implements TlsKeyExchange
+{
+ protected TlsClientContext context;
+
+ protected AsymmetricKeyParameter serverPublicKey = null;
+
+ protected RSAKeyParameters rsaServerPublicKey = null;
+
+ protected byte[] premasterSecret;
+
+ TlsRSAKeyExchange(TlsClientContext context)
+ {
+ this.context = context;
+ }
+
+ public void skipServerCertificate() throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void processServerCertificate(Certificate serverCertificate) throws IOException
+ {
+ pdftk.org.bouncycastle.asn1.x509.Certificate x509Cert = serverCertificate.certs[0];
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+
+ try
+ {
+ this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
+ }
+ catch (RuntimeException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+ }
+
+ // Sanity check the PublicKeyFactory
+ if (this.serverPublicKey.isPrivate())
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ this.rsaServerPublicKey = validateRSAPublicKey((RSAKeyParameters)this.serverPublicKey);
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyEncipherment);
+
+ // TODO
+ /*
+ * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the
+ * signing algorithm for the certificate must be the same as the algorithm for the
+ * certificate key."
+ */
+ }
+
+ public void skipServerKeyExchange() throws IOException
+ {
+ // OK
+ }
+
+ public void processServerKeyExchange(InputStream is)
+ throws IOException
+ {
+ // TODO
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void validateCertificateRequest(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ short[] types = certificateRequest.getCertificateTypes();
+ for (int i = 0; i < types.length; ++i)
+ {
+ switch (types[i])
+ {
+ case ClientCertificateType.rsa_sign:
+ case ClientCertificateType.dss_sign:
+ case ClientCertificateType.ecdsa_sign:
+ break;
+ default:
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+ }
+
+ public void skipClientCredentials() throws IOException
+ {
+ // OK
+ }
+
+ public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
+ {
+ if (!(clientCredentials instanceof TlsSignerCredentials))
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+ }
+
+ public void generateClientKeyExchange(OutputStream os) throws IOException
+ {
+ this.premasterSecret = TlsRSAUtils.generateEncryptedPreMasterSecret(context,
+ this.rsaServerPublicKey, os);
+ }
+
+ public byte[] generatePremasterSecret() throws IOException
+ {
+ byte[] tmp = this.premasterSecret;
+ this.premasterSecret = null;
+ return tmp;
+ }
+
+ // Would be needed to process RSA_EXPORT server key exchange
+// protected void processRSAServerKeyExchange(InputStream is, Signer signer) throws IOException
+// {
+// InputStream sigIn = is;
+// if (signer != null)
+// {
+// sigIn = new SignerInputStream(is, signer);
+// }
+//
+// byte[] modulusBytes = TlsUtils.readOpaque16(sigIn);
+// byte[] exponentBytes = TlsUtils.readOpaque16(sigIn);
+//
+// if (signer != null)
+// {
+// byte[] sigByte = TlsUtils.readOpaque16(is);
+//
+// if (!signer.verifySignature(sigByte))
+// {
+// handler.failWithError(AlertLevel.fatal, AlertDescription.bad_certificate);
+// }
+// }
+//
+// BigInteger modulus = new BigInteger(1, modulusBytes);
+// BigInteger exponent = new BigInteger(1, exponentBytes);
+//
+// this.rsaServerPublicKey = validateRSAPublicKey(new RSAKeyParameters(false, modulus,
+// exponent));
+// }
+
+ protected RSAKeyParameters validateRSAPublicKey(RSAKeyParameters key) throws IOException
+ {
+ // TODO What is the minimum bit length required?
+// key.getModulus().bitLength();
+
+ if (!key.getExponent().isProbablePrime(2))
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ return key;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsRSASigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsRSASigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsRSASigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsRSASigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,37 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.Signer;
+import pdftk.org.bouncycastle.crypto.digests.NullDigest;
+import pdftk.org.bouncycastle.crypto.encodings.PKCS1Encoding;
+import pdftk.org.bouncycastle.crypto.engines.RSABlindedEngine;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+import pdftk.org.bouncycastle.crypto.signers.GenericSigner;
+
+class TlsRSASigner implements TlsSigner
+{
+ public byte[] calculateRawSignature(SecureRandom random, AsymmetricKeyParameter privateKey, byte[] md5andsha1)
+ throws CryptoException
+ {
+ Signer sig = new GenericSigner(new PKCS1Encoding(new RSABlindedEngine()), new NullDigest());
+ sig.init(true, new ParametersWithRandom(privateKey, random));
+ sig.update(md5andsha1, 0, md5andsha1.length);
+ return sig.generateSignature();
+ }
+
+ public Signer createVerifyer(AsymmetricKeyParameter publicKey)
+ {
+ Signer s = new GenericSigner(new PKCS1Encoding(new RSABlindedEngine()), new CombinedHash());
+ s.init(false, publicKey);
+ return s;
+ }
+
+ public boolean isValidPublicKey(AsymmetricKeyParameter publicKey)
+ {
+ return publicKey instanceof RSAKeyParameters && !publicKey.isPrivate();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsRSAUtils.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsRSAUtils.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsRSAUtils.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsRSAUtils.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,51 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import pdftk.org.bouncycastle.crypto.InvalidCipherTextException;
+import pdftk.org.bouncycastle.crypto.encodings.PKCS1Encoding;
+import pdftk.org.bouncycastle.crypto.engines.RSABlindedEngine;
+import pdftk.org.bouncycastle.crypto.params.ParametersWithRandom;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+
+public class TlsRSAUtils
+{
+ public static byte[] generateEncryptedPreMasterSecret(TlsClientContext context,
+ RSAKeyParameters rsaServerPublicKey, OutputStream os) throws IOException
+ {
+ /*
+ * Choose a PremasterSecret and send it encrypted to the server
+ */
+ byte[] premasterSecret = new byte[48];
+ context.getSecureRandom().nextBytes(premasterSecret);
+ TlsUtils.writeVersion(context.getClientVersion(), premasterSecret, 0);
+
+ PKCS1Encoding encoding = new PKCS1Encoding(new RSABlindedEngine());
+ encoding.init(true, new ParametersWithRandom(rsaServerPublicKey, context.getSecureRandom()));
+
+ try
+ {
+ boolean isTls = context.getServerVersion().getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+ byte[] keData = encoding.processBlock(premasterSecret, 0, premasterSecret.length);
+
+ if (isTls)
+ {
+ TlsUtils.writeOpaque16(keData, os);
+ }
+ else
+ {
+ os.write(keData);
+ }
+ }
+ catch (InvalidCipherTextException e)
+ {
+ /*
+ * This should never happen, only during decryption.
+ */
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ return premasterSecret;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsRuntimeException.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsRuntimeException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsRuntimeException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsRuntimeException.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,25 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+public class TlsRuntimeException extends RuntimeException
+{
+ private static final long serialVersionUID = 1928023487348344086L;
+
+ Throwable e;
+
+ public TlsRuntimeException(String message, Throwable e)
+ {
+ super(message);
+
+ this.e = e;
+ }
+
+ public TlsRuntimeException(String message)
+ {
+ super(message);
+ }
+
+ public Throwable getCause()
+ {
+ return e;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsSRPKeyExchange.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,202 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.x509.KeyUsage;
+import pdftk.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.Signer;
+import pdftk.org.bouncycastle.crypto.agreement.srp.SRP6Client;
+import pdftk.org.bouncycastle.crypto.agreement.srp.SRP6Util;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+import pdftk.org.bouncycastle.crypto.io.SignerInputStream;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.util.PublicKeyFactory;
+import pdftk.org.bouncycastle.util.BigIntegers;
+
+/**
+ * TLS 1.1 SRP key exchange.
+ */
+class TlsSRPKeyExchange implements TlsKeyExchange
+{
+ protected TlsClientContext context;
+ protected int keyExchange;
+ protected TlsSigner tlsSigner;
+ protected byte[] identity;
+ protected byte[] password;
+
+ protected AsymmetricKeyParameter serverPublicKey = null;
+
+ protected byte[] s = null;
+ protected BigInteger B = null;
+ protected SRP6Client srpClient = new SRP6Client();
+
+ TlsSRPKeyExchange(TlsClientContext context, int keyExchange, byte[] identity, byte[] password)
+ {
+ switch (keyExchange)
+ {
+ case KeyExchangeAlgorithm.SRP:
+ this.tlsSigner = null;
+ break;
+ case KeyExchangeAlgorithm.SRP_RSA:
+ this.tlsSigner = new TlsRSASigner();
+ break;
+ case KeyExchangeAlgorithm.SRP_DSS:
+ this.tlsSigner = new TlsDSSSigner();
+ break;
+ default:
+ throw new IllegalArgumentException("unsupported key exchange algorithm");
+ }
+
+ this.context = context;
+ this.keyExchange = keyExchange;
+ this.identity = identity;
+ this.password = password;
+ }
+
+ public void skipServerCertificate() throws IOException
+ {
+ if (tlsSigner != null)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+ }
+
+ public void processServerCertificate(Certificate serverCertificate) throws IOException
+ {
+ if (tlsSigner == null)
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ pdftk.org.bouncycastle.asn1.x509.Certificate x509Cert = serverCertificate.certs[0];
+ SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
+
+ try
+ {
+ this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
+ }
+ catch (RuntimeException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+ }
+
+ if (!tlsSigner.isValidPublicKey(this.serverPublicKey))
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+
+ TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature);
+
+ // TODO
+ /*
+ * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the
+ * signing algorithm for the certificate must be the same as the algorithm for the
+ * certificate key."
+ */
+ }
+
+ public void skipServerKeyExchange() throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void processServerKeyExchange(InputStream is) throws IOException
+ {
+ SecurityParameters securityParameters = context.getSecurityParameters();
+
+ InputStream sigIn = is;
+ Signer signer = null;
+
+ if (tlsSigner != null)
+ {
+ signer = initSigner(tlsSigner, securityParameters);
+ sigIn = new SignerInputStream(is, signer);
+ }
+
+ byte[] NBytes = TlsUtils.readOpaque16(sigIn);
+ byte[] gBytes = TlsUtils.readOpaque16(sigIn);
+ byte[] sBytes = TlsUtils.readOpaque8(sigIn);
+ byte[] BBytes = TlsUtils.readOpaque16(sigIn);
+
+ if (signer != null)
+ {
+ byte[] sigByte = TlsUtils.readOpaque16(is);
+
+ if (!signer.verifySignature(sigByte))
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_certificate);
+ }
+ }
+
+ BigInteger N = new BigInteger(1, NBytes);
+ BigInteger g = new BigInteger(1, gBytes);
+
+ // TODO Validate group parameters (see RFC 5054)
+// handler.failWithError(AlertLevel.fatal, AlertDescription.insufficient_security);
+
+ this.s = sBytes;
+
+ /*
+ * RFC 5054 2.5.3: The client MUST abort the handshake with an "illegal_parameter"
+ * alert if B % N = 0.
+ */
+ try
+ {
+ this.B = SRP6Util.validatePublicValue(N, new BigInteger(1, BBytes));
+ }
+ catch (CryptoException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+
+ this.srpClient.init(N, g, new SHA1Digest(), context.getSecureRandom());
+ }
+
+ public void validateCertificateRequest(CertificateRequest certificateRequest)
+ throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.unexpected_message);
+ }
+
+ public void skipClientCredentials() throws IOException
+ {
+ // OK
+ }
+
+ public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ public void generateClientKeyExchange(OutputStream os) throws IOException
+ {
+ byte[] keData = BigIntegers.asUnsignedByteArray(srpClient.generateClientCredentials(s,
+ this.identity, this.password));
+ TlsUtils.writeOpaque16(keData, os);
+ }
+
+ public byte[] generatePremasterSecret() throws IOException
+ {
+ try
+ {
+ // TODO Check if this needs to be a fixed size
+ return BigIntegers.asUnsignedByteArray(srpClient.calculateSecret(B));
+ }
+ catch (CryptoException e)
+ {
+ throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+ }
+ }
+
+ protected Signer initSigner(TlsSigner tlsSigner, SecurityParameters securityParameters)
+ {
+ Signer signer = tlsSigner.createVerifyer(this.serverPublicKey);
+ signer.update(securityParameters.clientRandom, 0, securityParameters.clientRandom.length);
+ signer.update(securityParameters.serverRandom, 0, securityParameters.serverRandom.length);
+ return signer;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsSigner.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsSigner.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsSigner.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsSigner.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,17 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.security.SecureRandom;
+
+import pdftk.org.bouncycastle.crypto.CryptoException;
+import pdftk.org.bouncycastle.crypto.Signer;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+
+interface TlsSigner
+{
+ byte[] calculateRawSignature(SecureRandom random, AsymmetricKeyParameter privateKey, byte[] md5andsha1)
+ throws CryptoException;
+
+ Signer createVerifyer(AsymmetricKeyParameter publicKey);
+
+ boolean isValidPublicKey(AsymmetricKeyParameter publicKey);
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsSignerCredentials.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsSignerCredentials.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsSignerCredentials.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsSignerCredentials.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,8 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+
+public interface TlsSignerCredentials extends TlsCredentials
+{
+ byte[] generateCertificateSignature(byte[] md5andsha1) throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsStreamCipher.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsStreamCipher.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsStreamCipher.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsStreamCipher.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,98 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.StreamCipher;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.util.Arrays;
+
+public class TlsStreamCipher implements TlsCipher
+{
+ protected TlsClientContext context;
+
+ protected StreamCipher encryptCipher;
+ protected StreamCipher decryptCipher;
+
+ protected TlsMac writeMac;
+ protected TlsMac readMac;
+
+ public TlsStreamCipher(TlsClientContext context, StreamCipher encryptCipher,
+ StreamCipher decryptCipher, Digest writeDigest, Digest readDigest, int cipherKeySize)
+ throws IOException
+ {
+ this.context = context;
+ this.encryptCipher = encryptCipher;
+ this.decryptCipher = decryptCipher;
+
+ int prfSize = (2 * cipherKeySize) + writeDigest.getDigestSize()
+ + readDigest.getDigestSize();
+
+ SecurityParameters securityParameters = context.getSecurityParameters();
+
+ byte[] keyBlock = TlsUtils.PRF(securityParameters.masterSecret, "key expansion",
+ TlsUtils.concat(securityParameters.serverRandom, securityParameters.clientRandom),
+ prfSize);
+
+ int offset = 0;
+
+ // Init MACs
+ writeMac = new TlsMac(context, writeDigest, keyBlock, offset, writeDigest.getDigestSize());
+ offset += writeDigest.getDigestSize();
+ readMac = new TlsMac(context, readDigest, keyBlock, offset, readDigest.getDigestSize());
+ offset += readDigest.getDigestSize();
+
+ // Build keys
+ KeyParameter encryptKey = new KeyParameter(keyBlock, offset, cipherKeySize);
+ offset += cipherKeySize;
+ KeyParameter decryptKey = new KeyParameter(keyBlock, offset, cipherKeySize);
+ offset += cipherKeySize;
+
+ if (offset != prfSize)
+ {
+ throw new TlsFatalAlert(AlertDescription.internal_error);
+ }
+
+ encryptCipher.init(true, encryptKey);
+ decryptCipher.init(true, decryptKey);
+ }
+
+ public byte[] encodePlaintext(short type, byte[] plaintext, int offset, int len)
+ {
+ byte[] mac = writeMac.calculateMac(type, plaintext, offset, len);
+
+ byte[] outbuf = new byte[len + mac.length];
+
+ encryptCipher.processBytes(plaintext, offset, len, outbuf, 0);
+ encryptCipher.processBytes(mac, 0, mac.length, outbuf, len);
+
+ return outbuf;
+ }
+
+ public byte[] decodeCiphertext(short type, byte[] ciphertext, int offset, int len)
+ throws IOException
+ {
+ byte[] deciphered = new byte[len];
+ decryptCipher.processBytes(ciphertext, offset, len, deciphered, 0);
+
+ int plaintextSize = deciphered.length - readMac.getSize();
+ byte[] plainText = copyData(deciphered, 0, plaintextSize);
+
+ byte[] receivedMac = copyData(deciphered, plaintextSize, readMac.getSize());
+ byte[] computedMac = readMac.calculateMac(type, plainText, 0, plainText.length);
+
+ if (!Arrays.constantTimeAreEqual(receivedMac, computedMac))
+ {
+ throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+ }
+
+ return plainText;
+ }
+
+ protected byte[] copyData(byte[] text, int offset, int len)
+ {
+ byte[] result = new byte[len];
+ System.arraycopy(text, offset, result, 0, len);
+ return result;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsUtils.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsUtils.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/TlsUtils.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/TlsUtils.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,437 @@
+package pdftk.org.bouncycastle.crypto.tls;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import pdftk.org.bouncycastle.asn1.x509.Extension;
+import pdftk.org.bouncycastle.asn1.x509.Extensions;
+import pdftk.org.bouncycastle.asn1.x509.KeyUsage;
+import pdftk.org.bouncycastle.asn1.x509.X509Extension;
+import pdftk.org.bouncycastle.crypto.Digest;
+import pdftk.org.bouncycastle.crypto.digests.MD5Digest;
+import pdftk.org.bouncycastle.crypto.digests.SHA1Digest;
+import pdftk.org.bouncycastle.crypto.macs.HMac;
+import pdftk.org.bouncycastle.crypto.params.KeyParameter;
+import pdftk.org.bouncycastle.util.Arrays;
+import pdftk.org.bouncycastle.util.Strings;
+import pdftk.org.bouncycastle.util.io.Streams;
+
+/**
+ * Some helper fuctions for MicroTLS.
+ */
+public class TlsUtils
+{
+ protected static void writeUint8(short i, OutputStream os) throws IOException
+ {
+ os.write(i);
+ }
+
+ protected static void writeUint8(short i, byte[] buf, int offset)
+ {
+ buf[offset] = (byte)i;
+ }
+
+ protected static void writeUint16(int i, OutputStream os) throws IOException
+ {
+ os.write(i >> 8);
+ os.write(i);
+ }
+
+ protected static void writeUint16(int i, byte[] buf, int offset)
+ {
+ buf[offset] = (byte)(i >> 8);
+ buf[offset + 1] = (byte)i;
+ }
+
+ protected static void writeUint24(int i, OutputStream os) throws IOException
+ {
+ os.write(i >> 16);
+ os.write(i >> 8);
+ os.write(i);
+ }
+
+ protected static void writeUint24(int i, byte[] buf, int offset)
+ {
+ buf[offset] = (byte)(i >> 16);
+ buf[offset + 1] = (byte)(i >> 8);
+ buf[offset + 2] = (byte)(i);
+ }
+
+ protected static void writeUint32(long i, OutputStream os) throws IOException
+ {
+ os.write((int)(i >> 24));
+ os.write((int)(i >> 16));
+ os.write((int)(i >> 8));
+ os.write((int)(i));
+ }
+
+ protected static void writeUint32(long i, byte[] buf, int offset)
+ {
+ buf[offset] = (byte)(i >> 24);
+ buf[offset + 1] = (byte)(i >> 16);
+ buf[offset + 2] = (byte)(i >> 8);
+ buf[offset + 3] = (byte)(i);
+ }
+
+ protected static void writeUint64(long i, OutputStream os) throws IOException
+ {
+ os.write((int)(i >> 56));
+ os.write((int)(i >> 48));
+ os.write((int)(i >> 40));
+ os.write((int)(i >> 32));
+ os.write((int)(i >> 24));
+ os.write((int)(i >> 16));
+ os.write((int)(i >> 8));
+ os.write((int)(i));
+ }
+
+
+ protected static void writeUint64(long i, byte[] buf, int offset)
+ {
+ buf[offset] = (byte)(i >> 56);
+ buf[offset + 1] = (byte)(i >> 48);
+ buf[offset + 2] = (byte)(i >> 40);
+ buf[offset + 3] = (byte)(i >> 32);
+ buf[offset + 4] = (byte)(i >> 24);
+ buf[offset + 5] = (byte)(i >> 16);
+ buf[offset + 6] = (byte)(i >> 8);
+ buf[offset + 7] = (byte)(i);
+ }
+
+ protected static void writeOpaque8(byte[] buf, OutputStream os) throws IOException
+ {
+ writeUint8((short)buf.length, os);
+ os.write(buf);
+ }
+
+ protected static void writeOpaque16(byte[] buf, OutputStream os) throws IOException
+ {
+ writeUint16(buf.length, os);
+ os.write(buf);
+ }
+
+ protected static void writeOpaque24(byte[] buf, OutputStream os) throws IOException
+ {
+ writeUint24(buf.length, os);
+ os.write(buf);
+ }
+
+ protected static void writeUint8Array(short[] uints, OutputStream os) throws IOException
+ {
+ for (int i = 0; i < uints.length; ++i)
+ {
+ writeUint8(uints[i], os);
+ }
+ }
+
+ protected static void writeUint16Array(int[] uints, OutputStream os) throws IOException
+ {
+ for (int i = 0; i < uints.length; ++i)
+ {
+ writeUint16(uints[i], os);
+ }
+ }
+
+ protected static short readUint8(InputStream is) throws IOException
+ {
+ int i = is.read();
+ if (i == -1)
+ {
+ throw new EOFException();
+ }
+ return (short)i;
+ }
+
+ protected static int readUint16(InputStream is) throws IOException
+ {
+ int i1 = is.read();
+ int i2 = is.read();
+ if ((i1 | i2) < 0)
+ {
+ throw new EOFException();
+ }
+ return i1 << 8 | i2;
+ }
+
+ protected static int readUint24(InputStream is) throws IOException
+ {
+ int i1 = is.read();
+ int i2 = is.read();
+ int i3 = is.read();
+ if ((i1 | i2 | i3) < 0)
+ {
+ throw new EOFException();
+ }
+ return (i1 << 16) | (i2 << 8) | i3;
+ }
+
+ protected static long readUint32(InputStream is) throws IOException
+ {
+ int i1 = is.read();
+ int i2 = is.read();
+ int i3 = is.read();
+ int i4 = is.read();
+ if ((i1 | i2 | i3 | i4) < 0)
+ {
+ throw new EOFException();
+ }
+ return (((long)i1) << 24) | (((long)i2) << 16) | (((long)i3) << 8) | ((long)i4);
+ }
+
+ protected static void readFully(byte[] buf, InputStream is) throws IOException
+ {
+ if (Streams.readFully(is, buf) != buf.length)
+ {
+ throw new EOFException();
+ }
+ }
+
+ protected static byte[] readOpaque8(InputStream is) throws IOException
+ {
+ short length = readUint8(is);
+ byte[] value = new byte[length];
+ readFully(value, is);
+ return value;
+ }
+
+ protected static byte[] readOpaque16(InputStream is) throws IOException
+ {
+ int length = readUint16(is);
+ byte[] value = new byte[length];
+ readFully(value, is);
+ return value;
+ }
+
+ static ProtocolVersion readVersion(byte[] buf) throws IOException
+ {
+ return ProtocolVersion.get(buf[0], buf[1]);
+ }
+
+ static ProtocolVersion readVersion(InputStream is) throws IOException
+ {
+ int i1 = is.read();
+ int i2 = is.read();
+ return ProtocolVersion.get(i1, i2);
+ }
+
+ protected static void writeGMTUnixTime(byte[] buf, int offset)
+ {
+ int t = (int)(System.currentTimeMillis() / 1000L);
+ buf[offset] = (byte)(t >> 24);
+ buf[offset + 1] = (byte)(t >> 16);
+ buf[offset + 2] = (byte)(t >> 8);
+ buf[offset + 3] = (byte)t;
+ }
+
+ static void writeVersion(ProtocolVersion version, OutputStream os) throws IOException
+ {
+ os.write(version.getMajorVersion());
+ os.write(version.getMinorVersion());
+ }
+
+ static void writeVersion(ProtocolVersion version, byte[] buf, int offset) throws IOException
+ {
+ buf[offset] = (byte)version.getMajorVersion();
+ buf[offset + 1] = (byte)version.getMinorVersion();
+ }
+
+ private static void hmac_hash(Digest digest, byte[] secret, byte[] seed, byte[] out)
+ {
+ HMac mac = new HMac(digest);
+ KeyParameter param = new KeyParameter(secret);
+ byte[] a = seed;
+ int size = digest.getDigestSize();
+ int iterations = (out.length + size - 1) / size;
+ byte[] buf = new byte[mac.getMacSize()];
+ byte[] buf2 = new byte[mac.getMacSize()];
+ for (int i = 0; i < iterations; i++)
+ {
+ mac.init(param);
+ mac.update(a, 0, a.length);
+ mac.doFinal(buf, 0);
+ a = buf;
+ mac.init(param);
+ mac.update(a, 0, a.length);
+ mac.update(seed, 0, seed.length);
+ mac.doFinal(buf2, 0);
+ System.arraycopy(buf2, 0, out, (size * i), Math.min(size, out.length - (size * i)));
+ }
+ }
+
+ protected static byte[] PRF(byte[] secret, String asciiLabel, byte[] seed, int size)
+ {
+ byte[] label = Strings.toByteArray(asciiLabel);
+
+ int s_half = (secret.length + 1) / 2;
+ byte[] s1 = new byte[s_half];
+ byte[] s2 = new byte[s_half];
+ System.arraycopy(secret, 0, s1, 0, s_half);
+ System.arraycopy(secret, secret.length - s_half, s2, 0, s_half);
+
+ byte[] ls = concat(label, seed);
+
+ byte[] buf = new byte[size];
+ byte[] prf = new byte[size];
+ hmac_hash(new MD5Digest(), s1, ls, prf);
+ hmac_hash(new SHA1Digest(), s2, ls, buf);
+ for (int i = 0; i < size; i++)
+ {
+ buf[i] ^= prf[i];
+ }
+ return buf;
+ }
+
+ static byte[] PRF_1_2(Digest digest, byte[] secret, String asciiLabel, byte[] seed, int size)
+ {
+ byte[] label = Strings.toByteArray(asciiLabel);
+ byte[] labelSeed = concat(label, seed);
+
+ byte[] buf = new byte[size];
+ hmac_hash(digest, secret, labelSeed, buf);
+ return buf;
+ }
+
+ static byte[] concat(byte[] a, byte[] b)
+ {
+ byte[] c = new byte[a.length + b.length];
+ System.arraycopy(a, 0, c, 0, a.length);
+ System.arraycopy(b, 0, c, a.length, b.length);
+ return c;
+ }
+
+ static void validateKeyUsage(pdftk.org.bouncycastle.asn1.x509.Certificate c, int keyUsageBits) throws IOException
+ {
+ Extensions exts = c.getTBSCertificate().getExtensions();
+ if (exts != null)
+ {
+ Extension ext = exts.getExtension(X509Extension.keyUsage);
+ if (ext != null)
+ {
+ KeyUsage ku = KeyUsage.getInstance(ext);
+ int bits = ku.getBytes()[0] & 0xff;
+ if ((bits & keyUsageBits) != keyUsageBits)
+ {
+ throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+ }
+ }
+ }
+ }
+
+ static byte[] calculateKeyBlock(TlsClientContext context, int size)
+ {
+ ProtocolVersion pv = context.getServerVersion();
+ SecurityParameters sp = context.getSecurityParameters();
+ byte[] random = concat(sp.serverRandom, sp.clientRandom);
+
+ boolean isTls = pv.getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+
+ if (isTls)
+ {
+ return PRF(sp.masterSecret, "key expansion", random, size);
+ }
+
+ Digest md5 = new MD5Digest();
+ Digest sha1 = new SHA1Digest();
+ int md5Size = md5.getDigestSize();
+ byte[] shatmp = new byte[sha1.getDigestSize()];
+ byte[] tmp = new byte[size + md5Size];
+
+ int i = 0, pos = 0;
+ while (pos < size)
+ {
+ byte[] ssl3Const = SSL3_CONST[i];
+
+ sha1.update(ssl3Const, 0, ssl3Const.length);
+ sha1.update(sp.masterSecret, 0, sp.masterSecret.length);
+ sha1.update(random, 0, random.length);
+ sha1.doFinal(shatmp, 0);
+
+ md5.update(sp.masterSecret, 0, sp.masterSecret.length);
+ md5.update(shatmp, 0, shatmp.length);
+ md5.doFinal(tmp, pos);
+
+ pos += md5Size;
+ ++i;
+ }
+
+ byte rval[] = new byte[size];
+ System.arraycopy(tmp, 0, rval, 0, size);
+ return rval;
+ }
+
+ static byte[] calculateMasterSecret(TlsClientContext context, byte[] pms)
+ {
+ ProtocolVersion pv = context.getServerVersion();
+ SecurityParameters sp = context.getSecurityParameters();
+ byte[] random = concat(sp.clientRandom, sp.serverRandom);
+
+ boolean isTls = pv.getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+
+ if (isTls)
+ {
+ return PRF(pms, "master secret", random, 48);
+ }
+
+ Digest md5 = new MD5Digest();
+ Digest sha1 = new SHA1Digest();
+ int md5Size = md5.getDigestSize();
+ byte[] shatmp = new byte[sha1.getDigestSize()];
+
+ byte[] rval = new byte[md5Size * 3];
+ int pos = 0;
+
+ for (int i = 0; i < 3; ++i)
+ {
+ byte[] ssl3Const = SSL3_CONST[i];
+
+ sha1.update(ssl3Const, 0, ssl3Const.length);
+ sha1.update(pms, 0, pms.length);
+ sha1.update(random, 0, random.length);
+ sha1.doFinal(shatmp, 0);
+
+ md5.update(pms, 0, pms.length);
+ md5.update(shatmp, 0, shatmp.length);
+ md5.doFinal(rval, pos);
+
+ pos += md5Size;
+ }
+
+ return rval;
+ }
+
+ static byte[] calculateVerifyData(TlsClientContext context, String asciiLabel, byte[] handshakeHash)
+ {
+ ProtocolVersion pv = context.getServerVersion();
+ SecurityParameters sp = context.getSecurityParameters();
+
+ boolean isTls = pv.getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion();
+
+ if (isTls)
+ {
+ return PRF(sp.masterSecret, asciiLabel, handshakeHash, 12);
+ }
+
+ return handshakeHash;
+ }
+
+ static final byte[] SSL_CLIENT = { 0x43, 0x4C, 0x4E, 0x54 };
+ static final byte[] SSL_SERVER = { 0x53, 0x52, 0x56, 0x52 };
+
+ // SSL3 magic mix constants ("A", "BB", "CCC", ...)
+ static final byte[][] SSL3_CONST = genConst();
+
+ private static byte[][] genConst()
+ {
+ int n = 10;
+ byte[][] arr = new byte[n][];
+ for (int i = 0; i < n; i++)
+ {
+ byte[] b = new byte[i + 1];
+ Arrays.fill(b, (byte)('A' + i));
+ arr[i] = b;
+ }
+ return arr;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/tls/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/tls/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+A lightweight TLS API.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/util/Pack.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/util/Pack.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/util/Pack.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/util/Pack.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,100 @@
+package pdftk.org.bouncycastle.crypto.util;
+
+public abstract class Pack
+{
+ public static int bigEndianToInt(byte[] bs, int off)
+ {
+ int n = bs[ off] << 24;
+ n |= (bs[++off] & 0xff) << 16;
+ n |= (bs[++off] & 0xff) << 8;
+ n |= (bs[++off] & 0xff);
+ return n;
+ }
+
+ public static void bigEndianToInt(byte[] bs, int off, int[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = bigEndianToInt(bs, off);
+ off += 4;
+ }
+ }
+
+ public static void intToBigEndian(int n, byte[] bs, int off)
+ {
+ bs[ off] = (byte)(n >>> 24);
+ bs[++off] = (byte)(n >>> 16);
+ bs[++off] = (byte)(n >>> 8);
+ bs[++off] = (byte)(n );
+ }
+
+ public static void intToBigEndian(int[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ intToBigEndian(ns[i], bs, off);
+ off += 4;
+ }
+ }
+
+ public static long bigEndianToLong(byte[] bs, int off)
+ {
+ int hi = bigEndianToInt(bs, off);
+ int lo = bigEndianToInt(bs, off + 4);
+ return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
+ }
+
+ public static void longToBigEndian(long n, byte[] bs, int off)
+ {
+ intToBigEndian((int)(n >>> 32), bs, off);
+ intToBigEndian((int)(n & 0xffffffffL), bs, off + 4);
+ }
+
+ public static int littleEndianToInt(byte[] bs, int off)
+ {
+ int n = bs[ off] & 0xff;
+ n |= (bs[++off] & 0xff) << 8;
+ n |= (bs[++off] & 0xff) << 16;
+ n |= bs[++off] << 24;
+ return n;
+ }
+
+ public static void littleEndianToInt(byte[] bs, int off, int[] ns)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ ns[i] = littleEndianToInt(bs, off);
+ off += 4;
+ }
+ }
+
+ public static void intToLittleEndian(int n, byte[] bs, int off)
+ {
+ bs[ off] = (byte)(n );
+ bs[++off] = (byte)(n >>> 8);
+ bs[++off] = (byte)(n >>> 16);
+ bs[++off] = (byte)(n >>> 24);
+ }
+
+ public static void intToLittleEndian(int[] ns, byte[] bs, int off)
+ {
+ for (int i = 0; i < ns.length; ++i)
+ {
+ intToLittleEndian(ns[i], bs, off);
+ off += 4;
+ }
+ }
+
+ public static long littleEndianToLong(byte[] bs, int off)
+ {
+ int lo = littleEndianToInt(bs, off);
+ int hi = littleEndianToInt(bs, off + 4);
+ return ((long)(hi & 0xffffffffL) << 32) | (long)(lo & 0xffffffffL);
+ }
+
+ public static void longToLittleEndian(long n, byte[] bs, int off)
+ {
+ intToLittleEndian((int)(n & 0xffffffffL), bs, off);
+ intToLittleEndian((int)(n >>> 32), bs, off + 4);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/util/PrivateKeyFactory.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/util/PrivateKeyFactory.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/util/PrivateKeyFactory.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/util/PrivateKeyFactory.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,170 @@
+package pdftk.org.bouncycastle.crypto.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1InputStream;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.nist.NISTNamedCurves;
+import pdftk.org.bouncycastle.asn1.oiw.ElGamalParameter;
+import pdftk.org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.pkcs.DHParameter;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import pdftk.org.bouncycastle.asn1.pkcs.RSAPrivateKey;
+import pdftk.org.bouncycastle.asn1.sec.ECPrivateKey;
+import pdftk.org.bouncycastle.asn1.sec.SECNamedCurves;
+import pdftk.org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import pdftk.org.bouncycastle.asn1.x509.DSAParameter;
+import pdftk.org.bouncycastle.asn1.x9.X962NamedCurves;
+import pdftk.org.bouncycastle.asn1.x9.X962Parameters;
+import pdftk.org.bouncycastle.asn1.x9.X9ECParameters;
+import pdftk.org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECDomainParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ElGamalParameters;
+import pdftk.org.bouncycastle.crypto.params.ElGamalPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+
+/**
+ * Factory for creating private key objects from PKCS8 PrivateKeyInfo objects.
+ */
+public class PrivateKeyFactory
+{
+ /**
+ * Create a private key parameter from a PKCS8 PrivateKeyInfo encoding.
+ *
+ * @param privateKeyInfoData the PrivateKeyInfo encoding
+ * @return a suitable private key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(byte[] privateKeyInfoData) throws IOException
+ {
+ return createKey(PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(privateKeyInfoData)));
+ }
+
+ /**
+ * Create a private key parameter from a PKCS8 PrivateKeyInfo encoding read from a
+ * stream.
+ *
+ * @param inStr the stream to read the PrivateKeyInfo encoding from
+ * @return a suitable private key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException
+ {
+ return createKey(PrivateKeyInfo.getInstance(new ASN1InputStream(inStr).readObject()));
+ }
+
+ /**
+ * Create a private key parameter from the passed in PKCS8 PrivateKeyInfo object.
+ *
+ * @param keyInfo the PrivateKeyInfo object containing the key material
+ * @return a suitable private key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(PrivateKeyInfo keyInfo) throws IOException
+ {
+ AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm();
+
+ if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption))
+ {
+ RSAPrivateKey keyStructure = RSAPrivateKey.getInstance(keyInfo.parsePrivateKey());
+
+ return new RSAPrivateCrtKeyParameters(keyStructure.getModulus(),
+ keyStructure.getPublicExponent(), keyStructure.getPrivateExponent(),
+ keyStructure.getPrime1(), keyStructure.getPrime2(), keyStructure.getExponent1(),
+ keyStructure.getExponent2(), keyStructure.getCoefficient());
+ }
+ // TODO?
+// else if (algId.getObjectId().equals(X9ObjectIdentifiers.dhpublicnumber))
+ else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement))
+ {
+ DHParameter params = DHParameter.getInstance(algId.getParameters());
+ ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
+
+ BigInteger lVal = params.getL();
+ int l = lVal == null ? 0 : lVal.intValue();
+ DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l);
+
+ return new DHPrivateKeyParameters(derX.getValue(), dhParams);
+ }
+ else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
+ {
+ ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
+ ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
+
+ return new ElGamalPrivateKeyParameters(derX.getValue(), new ElGamalParameters(
+ params.getP(), params.getG()));
+ }
+ else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa))
+ {
+ ASN1Integer derX = (ASN1Integer)keyInfo.parsePrivateKey();
+ ASN1Encodable de = algId.getParameters();
+
+ DSAParameters parameters = null;
+ if (de != null)
+ {
+ DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive());
+ parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
+ }
+
+ return new DSAPrivateKeyParameters(derX.getValue(), parameters);
+ }
+ else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey))
+ {
+ X962Parameters params = new X962Parameters((ASN1Primitive)algId.getParameters());
+
+ X9ECParameters x9;
+ if (params.isNamedCurve())
+ {
+ ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
+ x9 = X962NamedCurves.getByOID(oid);
+
+ if (x9 == null)
+ {
+ x9 = SECNamedCurves.getByOID(oid);
+
+ if (x9 == null)
+ {
+ x9 = NISTNamedCurves.getByOID(oid);
+
+ if (x9 == null)
+ {
+ x9 = TeleTrusTNamedCurves.getByOID(oid);
+ }
+ }
+ }
+ }
+ else
+ {
+ x9 = X9ECParameters.getInstance(params.getParameters());
+ }
+
+ ECPrivateKey ec = ECPrivateKey.getInstance(keyInfo.parsePrivateKey());
+ BigInteger d = ec.getKey();
+
+ // TODO We lose any named parameters here
+
+ ECDomainParameters dParams = new ECDomainParameters(
+ x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
+
+ return new ECPrivateKeyParameters(d, dParams);
+ }
+ else
+ {
+ throw new RuntimeException("algorithm identifier in key not recognised");
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/util/PrivateKeyInfoFactory.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,51 @@
+package pdftk.org.bouncycastle.crypto.util;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.DERNull;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
+import pdftk.org.bouncycastle.asn1.pkcs.RSAPrivateKey;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import pdftk.org.bouncycastle.asn1.x509.DSAParameter;
+import pdftk.org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.DSAParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAPrivateKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
+
+/**
+ * Factory to create ASN.1 private key info objects from lightweight private keys.
+ */
+public class PrivateKeyInfoFactory
+{
+ /**
+ * Create a PrivateKeyInfo representation of a private key.
+ *
+ * @param privateKey the SubjectPublicKeyInfo encoding
+ * @return the appropriate key parameter
+ * @throws java.io.IOException on an error encoding the key
+ */
+ public static PrivateKeyInfo createPrivateKeyInfo(AsymmetricKeyParameter privateKey) throws IOException
+ {
+ if (privateKey instanceof RSAKeyParameters)
+ {
+ RSAPrivateCrtKeyParameters priv = (RSAPrivateCrtKeyParameters)privateKey;
+
+ return new PrivateKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new RSAPrivateKey(priv.getModulus(), priv.getPublicExponent(), priv.getExponent(), priv.getP(), priv.getQ(), priv.getDP(), priv.getDQ(), priv.getQInv()));
+ }
+ else if (privateKey instanceof DSAPrivateKeyParameters)
+ {
+ DSAPrivateKeyParameters priv = (DSAPrivateKeyParameters)privateKey;
+ DSAParameters params = priv.getParameters();
+
+ return new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(params.getP(), params.getQ(), params.getG())), new ASN1Integer(priv.getX()));
+ }
+ else
+ {
+ throw new IOException("key parameters not recognised.");
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/util/PublicKeyFactory.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/util/PublicKeyFactory.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/util/PublicKeyFactory.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/util/PublicKeyFactory.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,207 @@
+package pdftk.org.bouncycastle.crypto.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+
+import pdftk.org.bouncycastle.asn1.ASN1Encodable;
+import pdftk.org.bouncycastle.asn1.ASN1InputStream;
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import pdftk.org.bouncycastle.asn1.ASN1OctetString;
+import pdftk.org.bouncycastle.asn1.ASN1Primitive;
+import pdftk.org.bouncycastle.asn1.ASN1Sequence;
+import pdftk.org.bouncycastle.asn1.DEROctetString;
+import pdftk.org.bouncycastle.asn1.nist.NISTNamedCurves;
+import pdftk.org.bouncycastle.asn1.oiw.ElGamalParameter;
+import pdftk.org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.pkcs.DHParameter;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.pkcs.RSAPublicKey;
+import pdftk.org.bouncycastle.asn1.sec.SECNamedCurves;
+import pdftk.org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import pdftk.org.bouncycastle.asn1.x509.DSAParameter;
+import pdftk.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import pdftk.org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.x9.DHDomainParameters;
+import pdftk.org.bouncycastle.asn1.x9.DHPublicKey;
+import pdftk.org.bouncycastle.asn1.x9.DHValidationParms;
+import pdftk.org.bouncycastle.asn1.x9.X962NamedCurves;
+import pdftk.org.bouncycastle.asn1.x9.X962Parameters;
+import pdftk.org.bouncycastle.asn1.x9.X9ECParameters;
+import pdftk.org.bouncycastle.asn1.x9.X9ECPoint;
+import pdftk.org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.DHParameters;
+import pdftk.org.bouncycastle.crypto.params.DHPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.DHValidationParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAParameters;
+import pdftk.org.bouncycastle.crypto.params.DSAPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ECDomainParameters;
+import pdftk.org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.ElGamalParameters;
+import pdftk.org.bouncycastle.crypto.params.ElGamalPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+
+/**
+ * Factory to create asymmetric public key parameters for asymmetric ciphers from range of
+ * ASN.1 encoded SubjectPublicKeyInfo objects.
+ */
+public class PublicKeyFactory
+{
+ /**
+ * Create a public key from a SubjectPublicKeyInfo encoding
+ *
+ * @param keyInfoData the SubjectPublicKeyInfo encoding
+ * @return the appropriate key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(byte[] keyInfoData) throws IOException
+ {
+ return createKey(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(keyInfoData)));
+ }
+
+ /**
+ * Create a public key from a SubjectPublicKeyInfo encoding read from a stream
+ *
+ * @param inStr the stream to read the SubjectPublicKeyInfo encoding from
+ * @return the appropriate key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException
+ {
+ return createKey(SubjectPublicKeyInfo.getInstance(new ASN1InputStream(inStr).readObject()));
+ }
+
+ /**
+ * Create a public key from the passed in SubjectPublicKeyInfo
+ *
+ * @param keyInfo the SubjectPublicKeyInfo containing the key data
+ * @return the appropriate key parameter
+ * @throws IOException on an error decoding the key
+ */
+ public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) throws IOException
+ {
+ AlgorithmIdentifier algId = keyInfo.getAlgorithm();
+
+ if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)
+ || algId.getAlgorithm().equals(X509ObjectIdentifiers.id_ea_rsa))
+ {
+ RSAPublicKey pubKey = RSAPublicKey.getInstance(keyInfo.parsePublicKey());
+
+ return new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent());
+ }
+ else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.dhpublicnumber))
+ {
+ DHPublicKey dhPublicKey = DHPublicKey.getInstance(keyInfo.parsePublicKey());
+
+ BigInteger y = dhPublicKey.getY().getValue();
+
+ DHDomainParameters dhParams = DHDomainParameters.getInstance(algId.getParameters());
+
+ BigInteger p = dhParams.getP().getValue();
+ BigInteger g = dhParams.getG().getValue();
+ BigInteger q = dhParams.getQ().getValue();
+
+ BigInteger j = null;
+ if (dhParams.getJ() != null)
+ {
+ j = dhParams.getJ().getValue();
+ }
+
+ DHValidationParameters validation = null;
+ DHValidationParms dhValidationParms = dhParams.getValidationParms();
+ if (dhValidationParms != null)
+ {
+ byte[] seed = dhValidationParms.getSeed().getBytes();
+ BigInteger pgenCounter = dhValidationParms.getPgenCounter().getValue();
+
+ // TODO Check pgenCounter size?
+
+ validation = new DHValidationParameters(seed, pgenCounter.intValue());
+ }
+
+ return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation));
+ }
+ else if (algId.getAlgorithm().equals(PKCSObjectIdentifiers.dhKeyAgreement))
+ {
+ DHParameter params = DHParameter.getInstance(algId.getParameters());
+ ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
+
+ BigInteger lVal = params.getL();
+ int l = lVal == null ? 0 : lVal.intValue();
+ DHParameters dhParams = new DHParameters(params.getP(), params.getG(), null, l);
+
+ return new DHPublicKeyParameters(derY.getValue(), dhParams);
+ }
+ else if (algId.getAlgorithm().equals(OIWObjectIdentifiers.elGamalAlgorithm))
+ {
+ ElGamalParameter params = new ElGamalParameter((ASN1Sequence)algId.getParameters());
+ ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
+
+ return new ElGamalPublicKeyParameters(derY.getValue(), new ElGamalParameters(
+ params.getP(), params.getG()));
+ }
+ else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_dsa)
+ || algId.getAlgorithm().equals(OIWObjectIdentifiers.dsaWithSHA1))
+ {
+ ASN1Integer derY = (ASN1Integer)keyInfo.parsePublicKey();
+ ASN1Encodable de = algId.getParameters();
+
+ DSAParameters parameters = null;
+ if (de != null)
+ {
+ DSAParameter params = DSAParameter.getInstance(de.toASN1Primitive());
+ parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
+ }
+
+ return new DSAPublicKeyParameters(derY.getValue(), parameters);
+ }
+ else if (algId.getAlgorithm().equals(X9ObjectIdentifiers.id_ecPublicKey))
+ {
+ X962Parameters params = new X962Parameters(
+ (ASN1Primitive)algId.getParameters());
+
+ X9ECParameters x9;
+ if (params.isNamedCurve())
+ {
+ ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)params.getParameters();
+ x9 = X962NamedCurves.getByOID(oid);
+
+ if (x9 == null)
+ {
+ x9 = SECNamedCurves.getByOID(oid);
+
+ if (x9 == null)
+ {
+ x9 = NISTNamedCurves.getByOID(oid);
+
+ if (x9 == null)
+ {
+ x9 = TeleTrusTNamedCurves.getByOID(oid);
+ }
+ }
+ }
+ }
+ else
+ {
+ x9 = X9ECParameters.getInstance(params.getParameters());
+ }
+
+ ASN1OctetString key = new DEROctetString(keyInfo.getPublicKeyData().getBytes());
+ X9ECPoint derQ = new X9ECPoint(x9.getCurve(), key);
+
+ // TODO We lose any named parameters here
+
+ ECDomainParameters dParams = new ECDomainParameters(
+ x9.getCurve(), x9.getG(), x9.getN(), x9.getH(), x9.getSeed());
+
+ return new ECPublicKeyParameters(derQ.getPoint(), dParams);
+ }
+ else
+ {
+ throw new RuntimeException("algorithm identifier in key not recognised");
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java pdftk-2.01/java/pdftk/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/util/SubjectPublicKeyInfoFactory.java 2013-04-22 12:38:54.000000000 +0000
@@ -0,0 +1,47 @@
+package pdftk.org.bouncycastle.crypto.util;
+
+import java.io.IOException;
+
+import pdftk.org.bouncycastle.asn1.ASN1Integer;
+import pdftk.org.bouncycastle.asn1.DERNull;
+import pdftk.org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import pdftk.org.bouncycastle.asn1.pkcs.RSAPublicKey;
+import pdftk.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import pdftk.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import pdftk.org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
+import pdftk.org.bouncycastle.crypto.params.AsymmetricKeyParameter;
+import pdftk.org.bouncycastle.crypto.params.DSAPublicKeyParameters;
+import pdftk.org.bouncycastle.crypto.params.RSAKeyParameters;
+
+/**
+ * Factory to create ASN.1 subject public key info objects from lightweight public keys.
+ */
+public class SubjectPublicKeyInfoFactory
+{
+ /**
+ * Create a SubjectPublicKeyInfo public key.
+ *
+ * @param publicKey the SubjectPublicKeyInfo encoding
+ * @return the appropriate key parameter
+ * @throws java.io.IOException on an error encoding the key
+ */
+ public static SubjectPublicKeyInfo createSubjectPublicKeyInfo(AsymmetricKeyParameter publicKey) throws IOException
+ {
+ if (publicKey instanceof RSAKeyParameters)
+ {
+ RSAKeyParameters pub = (RSAKeyParameters)publicKey;
+
+ return new SubjectPublicKeyInfo(new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), new RSAPublicKey(pub.getModulus(), pub.getExponent()));
+ }
+ else if (publicKey instanceof DSAPublicKeyParameters)
+ {
+ DSAPublicKeyParameters pub = (DSAPublicKeyParameters)publicKey;
+
+ return new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), new ASN1Integer(pub.getY()));
+ }
+ else
+ {
+ throw new IOException("key parameters not recognised.");
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/crypto/util/package.html pdftk-2.01/java/pdftk/org/bouncycastle/crypto/util/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/crypto/util/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/crypto/util/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Some general utility/conversion classes.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/Arrays.java pdftk-2.01/java/pdftk/org/bouncycastle/util/Arrays.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/Arrays.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/Arrays.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,628 @@
+package pdftk.org.bouncycastle.util;
+
+import java.math.BigInteger;
+
+/**
+ * General array utilities.
+ */
+public final class Arrays
+{
+ private Arrays()
+ {
+ // static class, hide constructor
+ }
+
+ public static boolean areEqual(
+ boolean[] a,
+ boolean[] b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ if (a == null || b == null)
+ {
+ return false;
+ }
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean areEqual(
+ char[] a,
+ char[] b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ if (a == null || b == null)
+ {
+ return false;
+ }
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean areEqual(
+ byte[] a,
+ byte[] b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ if (a == null || b == null)
+ {
+ return false;
+ }
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * A constant time equals comparison - does not terminate early if
+ * test will fail.
+ *
+ * @param a first array
+ * @param b second array
+ * @return true if arrays equal, false otherwise.
+ */
+ public static boolean constantTimeAreEqual(
+ byte[] a,
+ byte[] b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ if (a == null || b == null)
+ {
+ return false;
+ }
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ int nonEqual = 0;
+
+ for (int i = 0; i != a.length; i++)
+ {
+ nonEqual |= (a[i] ^ b[i]);
+ }
+
+ return nonEqual == 0;
+ }
+
+ public static boolean areEqual(
+ int[] a,
+ int[] b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ if (a == null || b == null)
+ {
+ return false;
+ }
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean areEqual(
+ long[] a,
+ long[] b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ if (a == null || b == null)
+ {
+ return false;
+ }
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static boolean areEqual(
+ BigInteger[] a,
+ BigInteger[] b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ if (a == null || b == null)
+ {
+ return false;
+ }
+
+ if (a.length != b.length)
+ {
+ return false;
+ }
+
+ for (int i = 0; i != a.length; i++)
+ {
+ if (!a[i].equals(b[i]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static void fill(
+ byte[] array,
+ byte value)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static void fill(
+ char[] array,
+ char value)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static void fill(
+ long[] array,
+ long value)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static void fill(
+ short[] array,
+ short value)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static void fill(
+ int[] array,
+ int value)
+ {
+ for (int i = 0; i < array.length; i++)
+ {
+ array[i] = value;
+ }
+ }
+
+ public static int hashCode(byte[] data)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = data.length;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[i];
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(char[] data)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = data.length;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[i];
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(int[][] ints)
+ {
+ int hc = 0;
+
+ for (int i = 0; i != ints.length; i++)
+ {
+ hc = hc * 257 + hashCode(ints[i]);
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(int[] data)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = data.length;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[i];
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(short[][][] shorts)
+ {
+ int hc = 0;
+
+ for (int i = 0; i != shorts.length; i++)
+ {
+ hc = hc * 257 + hashCode(shorts[i]);
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(short[][] shorts)
+ {
+ int hc = 0;
+
+ for (int i = 0; i != shorts.length; i++)
+ {
+ hc = hc * 257 + hashCode(shorts[i]);
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(short[] data)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = data.length;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= (data[i] & 0xff);
+ }
+
+ return hc;
+ }
+
+ public static int hashCode(BigInteger[] data)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ int i = data.length;
+ int hc = i + 1;
+
+ while (--i >= 0)
+ {
+ hc *= 257;
+ hc ^= data[i].hashCode();
+ }
+
+ return hc;
+ }
+
+ public static byte[] clone(byte[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ byte[] copy = new byte[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ public static int[] clone(int[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ int[] copy = new int[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ public static short[] clone(short[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ short[] copy = new short[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ public static BigInteger[] clone(BigInteger[] data)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+ BigInteger[] copy = new BigInteger[data.length];
+
+ System.arraycopy(data, 0, copy, 0, data.length);
+
+ return copy;
+ }
+
+ public static byte[] copyOf(byte[] data, int newLength)
+ {
+ byte[] tmp = new byte[newLength];
+
+ if (newLength < data.length)
+ {
+ System.arraycopy(data, 0, tmp, 0, newLength);
+ }
+ else
+ {
+ System.arraycopy(data, 0, tmp, 0, data.length);
+ }
+
+ return tmp;
+ }
+
+ public static char[] copyOf(char[] data, int newLength)
+ {
+ char[] tmp = new char[newLength];
+
+ if (newLength < data.length)
+ {
+ System.arraycopy(data, 0, tmp, 0, newLength);
+ }
+ else
+ {
+ System.arraycopy(data, 0, tmp, 0, data.length);
+ }
+
+ return tmp;
+ }
+
+ public static int[] copyOf(int[] data, int newLength)
+ {
+ int[] tmp = new int[newLength];
+
+ if (newLength < data.length)
+ {
+ System.arraycopy(data, 0, tmp, 0, newLength);
+ }
+ else
+ {
+ System.arraycopy(data, 0, tmp, 0, data.length);
+ }
+
+ return tmp;
+ }
+
+ public static long[] copyOf(long[] data, int newLength)
+ {
+ long[] tmp = new long[newLength];
+
+ if (newLength < data.length)
+ {
+ System.arraycopy(data, 0, tmp, 0, newLength);
+ }
+ else
+ {
+ System.arraycopy(data, 0, tmp, 0, data.length);
+ }
+
+ return tmp;
+ }
+
+ public static BigInteger[] copyOf(BigInteger[] data, int newLength)
+ {
+ BigInteger[] tmp = new BigInteger[newLength];
+
+ if (newLength < data.length)
+ {
+ System.arraycopy(data, 0, tmp, 0, newLength);
+ }
+ else
+ {
+ System.arraycopy(data, 0, tmp, 0, data.length);
+ }
+
+ return tmp;
+ }
+
+ public static byte[] copyOfRange(byte[] data, int from, int to)
+ {
+ int newLength = getLength(from, to);
+
+ byte[] tmp = new byte[newLength];
+
+ if (data.length - from < newLength)
+ {
+ System.arraycopy(data, from, tmp, 0, data.length - from);
+ }
+ else
+ {
+ System.arraycopy(data, from, tmp, 0, newLength);
+ }
+
+ return tmp;
+ }
+
+ public static int[] copyOfRange(int[] data, int from, int to)
+ {
+ int newLength = getLength(from, to);
+
+ int[] tmp = new int[newLength];
+
+ if (data.length - from < newLength)
+ {
+ System.arraycopy(data, from, tmp, 0, data.length - from);
+ }
+ else
+ {
+ System.arraycopy(data, from, tmp, 0, newLength);
+ }
+
+ return tmp;
+ }
+
+ public static long[] copyOfRange(long[] data, int from, int to)
+ {
+ int newLength = getLength(from, to);
+
+ long[] tmp = new long[newLength];
+
+ if (data.length - from < newLength)
+ {
+ System.arraycopy(data, from, tmp, 0, data.length - from);
+ }
+ else
+ {
+ System.arraycopy(data, from, tmp, 0, newLength);
+ }
+
+ return tmp;
+ }
+
+ public static BigInteger[] copyOfRange(BigInteger[] data, int from, int to)
+ {
+ int newLength = getLength(from, to);
+
+ BigInteger[] tmp = new BigInteger[newLength];
+
+ if (data.length - from < newLength)
+ {
+ System.arraycopy(data, from, tmp, 0, data.length - from);
+ }
+ else
+ {
+ System.arraycopy(data, from, tmp, 0, newLength);
+ }
+
+ return tmp;
+ }
+
+ private static int getLength(int from, int to)
+ {
+ int newLength = to - from;
+ if (newLength < 0)
+ {
+ StringBuffer sb = new StringBuffer(from);
+ sb.append(" > ").append(to);
+ throw new IllegalArgumentException(sb.toString());
+ }
+ return newLength;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/BigIntegers.java pdftk-2.01/java/pdftk/org/bouncycastle/util/BigIntegers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/BigIntegers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/BigIntegers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,123 @@
+package pdftk.org.bouncycastle.util;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * BigInteger utilities.
+ */
+public final class BigIntegers
+{
+ private static final int MAX_ITERATIONS = 1000;
+ private static final BigInteger ZERO = BigInteger.valueOf(0);
+
+ /**
+ * Return the passed in value as an unsigned byte array.
+ *
+ * @param value value to be converted.
+ * @return a byte array without a leading zero byte if present in the signed encoding.
+ */
+ public static byte[] asUnsignedByteArray(
+ BigInteger value)
+ {
+ byte[] bytes = value.toByteArray();
+
+ if (bytes[0] == 0)
+ {
+ byte[] tmp = new byte[bytes.length - 1];
+
+ System.arraycopy(bytes, 1, tmp, 0, tmp.length);
+
+ return tmp;
+ }
+
+ return bytes;
+ }
+
+ /**
+ * Return the passed in value as an unsigned byte array.
+ *
+ * @param value value to be converted.
+ * @return a byte array without a leading zero byte if present in the signed encoding.
+ */
+ public static byte[] asUnsignedByteArray(
+ int length,
+ BigInteger value)
+ {
+ byte[] bytes = value.toByteArray();
+
+ if (bytes[0] == 0)
+ {
+ if (bytes.length - 1 > length)
+ {
+ throw new IllegalArgumentException("standard length exceeded for value");
+ }
+
+ byte[] tmp = new byte[length];
+
+ System.arraycopy(bytes, 1, tmp, tmp.length - (bytes.length - 1), bytes.length - 1);
+
+ return tmp;
+ }
+ else
+ {
+ if (bytes.length == length)
+ {
+ return bytes;
+ }
+
+ if (bytes.length > length)
+ {
+ throw new IllegalArgumentException("standard length exceeded for value");
+ }
+
+ byte[] tmp = new byte[length];
+
+ System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length);
+
+ return tmp;
+ }
+ }
+
+ /**
+ * Return a random BigInteger not less than 'min' and not greater than 'max'
+ *
+ * @param min the least value that may be generated
+ * @param max the greatest value that may be generated
+ * @param random the source of randomness
+ * @return a random BigInteger value in the range [min,max]
+ */
+ public static BigInteger createRandomInRange(
+ BigInteger min,
+ BigInteger max,
+ SecureRandom random)
+ {
+ int cmp = min.compareTo(max);
+ if (cmp >= 0)
+ {
+ if (cmp > 0)
+ {
+ throw new IllegalArgumentException("'min' may not be greater than 'max'");
+ }
+
+ return min;
+ }
+
+ if (min.bitLength() > max.bitLength() / 2)
+ {
+ return createRandomInRange(ZERO, max.subtract(min), random).add(min);
+ }
+
+ for (int i = 0; i < MAX_ITERATIONS; ++i)
+ {
+ BigInteger x = new BigInteger(max.bitLength(), random);
+ if (x.compareTo(min) >= 0 && x.compareTo(max) <= 0)
+ {
+ return x;
+ }
+ }
+
+ // fall back to a faster (restricted) method
+ return new BigInteger(max.subtract(min).bitLength() - 1, random).add(min);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/CollectionStore.java pdftk-2.01/java/pdftk/org/bouncycastle/util/CollectionStore.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/CollectionStore.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/CollectionStore.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,57 @@
+package pdftk.org.bouncycastle.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A simple collection backed store.
+ */
+public class CollectionStore
+ implements Store
+{
+ private Collection _local;
+
+ /**
+ * Basic constructor.
+ *
+ * @param collection - initial contents for the store, this is copied.
+ */
+ public CollectionStore(
+ Collection collection)
+ {
+ _local = new ArrayList(collection);
+ }
+
+ /**
+ * Return the matches in the collection for the passed in selector.
+ *
+ * @param selector the selector to match against.
+ * @return a possibly empty collection of matching objects.
+ */
+ public Collection getMatches(Selector selector)
+ {
+ if (selector == null)
+ {
+ return new ArrayList(_local);
+ }
+ else
+ {
+ List col = new ArrayList();
+ Iterator iter = _local.iterator();
+
+ while (iter.hasNext())
+ {
+ Object obj = iter.next();
+
+ if (selector.match(obj))
+ {
+ col.add(obj);
+ }
+ }
+
+ return col;
+ }
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/IPAddress.java pdftk-2.01/java/pdftk/org/bouncycastle/util/IPAddress.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/IPAddress.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/IPAddress.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,188 @@
+package pdftk.org.bouncycastle.util;
+
+public class IPAddress
+{
+ /**
+ * Validate the given IPv4 or IPv6 address.
+ *
+ * @param address the IP address as a String.
+ *
+ * @return true if a valid address, false otherwise
+ */
+ public static boolean isValid(
+ String address)
+ {
+ return isValidIPv4(address) || isValidIPv6(address);
+ }
+
+ /**
+ * Validate the given IPv4 or IPv6 address and netmask.
+ *
+ * @param address the IP address as a String.
+ *
+ * @return true if a valid address with netmask, false otherwise
+ */
+ public static boolean isValidWithNetMask(
+ String address)
+ {
+ return isValidIPv4WithNetmask(address) || isValidIPv6WithNetmask(address);
+ }
+
+ /**
+ * Validate the given IPv4 address.
+ *
+ * @param address the IP address as a String.
+ *
+ * @return true if a valid IPv4 address, false otherwise
+ */
+ public static boolean isValidIPv4(
+ String address)
+ {
+ if (address.length() == 0)
+ {
+ return false;
+ }
+
+ int octet;
+ int octets = 0;
+
+ String temp = address+".";
+
+ int pos;
+ int start = 0;
+ while (start < temp.length()
+ && (pos = temp.indexOf('.', start)) > start)
+ {
+ if (octets == 4)
+ {
+ return false;
+ }
+ try
+ {
+ octet = Integer.parseInt(temp.substring(start, pos));
+ }
+ catch (NumberFormatException ex)
+ {
+ return false;
+ }
+ if (octet < 0 || octet > 255)
+ {
+ return false;
+ }
+ start = pos + 1;
+ octets++;
+ }
+
+ return octets == 4;
+ }
+
+ public static boolean isValidIPv4WithNetmask(
+ String address)
+ {
+ int index = address.indexOf("/");
+ String mask = address.substring(index + 1);
+
+ return (index > 0) && isValidIPv4(address.substring(0, index))
+ && (isValidIPv4(mask) || isMaskValue(mask, 32));
+ }
+
+ public static boolean isValidIPv6WithNetmask(
+ String address)
+ {
+ int index = address.indexOf("/");
+ String mask = address.substring(index + 1);
+
+ return (index > 0) && (isValidIPv6(address.substring(0, index))
+ && (isValidIPv6(mask) || isMaskValue(mask, 128)));
+ }
+
+ private static boolean isMaskValue(String component, int size)
+ {
+ try
+ {
+ int value = Integer.parseInt(component);
+
+ return value >= 0 && value <= size;
+ }
+ catch (NumberFormatException e)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Validate the given IPv6 address.
+ *
+ * @param address the IP address as a String.
+ *
+ * @return true if a valid IPv4 address, false otherwise
+ */
+ public static boolean isValidIPv6(
+ String address)
+ {
+ if (address.length() == 0)
+ {
+ return false;
+ }
+
+ int octet;
+ int octets = 0;
+
+ String temp = address + ":";
+ boolean doubleColonFound = false;
+ int pos;
+ int start = 0;
+ while (start < temp.length()
+ && (pos = temp.indexOf(':', start)) >= start)
+ {
+ if (octets == 8)
+ {
+ return false;
+ }
+
+ if (start != pos)
+ {
+ String value = temp.substring(start, pos);
+
+ if (pos == (temp.length() - 1) && value.indexOf('.') > 0)
+ {
+ if (!isValidIPv4(value))
+ {
+ return false;
+ }
+
+ octets++; // add an extra one as address covers 2 words.
+ }
+ else
+ {
+ try
+ {
+ octet = Integer.parseInt(temp.substring(start, pos), 16);
+ }
+ catch (NumberFormatException ex)
+ {
+ return false;
+ }
+ if (octet < 0 || octet > 0xffff)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if (pos != 1 && pos != temp.length() - 1 && doubleColonFound)
+ {
+ return false;
+ }
+ doubleColonFound = true;
+ }
+ start = pos + 1;
+ octets++;
+ }
+
+ return octets == 8 || doubleColonFound;
+ }
+}
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/Integers.java pdftk-2.01/java/pdftk/org/bouncycastle/util/Integers.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/Integers.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/Integers.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,9 @@
+package pdftk.org.bouncycastle.util;
+
+public class Integers
+{
+ public static Integer valueOf(int value)
+ {
+ return new Integer(value);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/Selector.java pdftk-2.01/java/pdftk/org/bouncycastle/util/Selector.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/Selector.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/Selector.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,9 @@
+package pdftk.org.bouncycastle.util;
+
+public interface Selector
+ extends Cloneable
+{
+ boolean match(Object obj);
+
+ Object clone();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/Store.java pdftk-2.01/java/pdftk/org/bouncycastle/util/Store.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/Store.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/Store.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,9 @@
+package pdftk.org.bouncycastle.util;
+
+import java.util.Collection;
+
+public interface Store
+{
+ Collection getMatches(Selector selector)
+ throws StoreException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/StoreException.java pdftk-2.01/java/pdftk/org/bouncycastle/util/StoreException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/StoreException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/StoreException.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.util;
+
+public class StoreException
+ extends RuntimeException
+{
+ private Throwable _e;
+
+ public StoreException(String s, Throwable e)
+ {
+ super(s);
+ _e = e;
+ }
+
+ public Throwable getCause()
+ {
+ return _e;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/StreamParser.java pdftk-2.01/java/pdftk/org/bouncycastle/util/StreamParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/StreamParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/StreamParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,10 @@
+package pdftk.org.bouncycastle.util;
+
+import java.util.Collection;
+
+public interface StreamParser
+{
+ Object read() throws StreamParsingException;
+
+ Collection readAll() throws StreamParsingException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/StreamParsingException.java pdftk-2.01/java/pdftk/org/bouncycastle/util/StreamParsingException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/StreamParsingException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/StreamParsingException.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.util;
+
+public class StreamParsingException
+ extends Exception
+{
+ Throwable _e;
+
+ public StreamParsingException(String message, Throwable e)
+ {
+ super(message);
+ _e = e;
+ }
+
+ public Throwable getCause()
+ {
+ return _e;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/Strings.java pdftk-2.01/java/pdftk/org/bouncycastle/util/Strings.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/Strings.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/Strings.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,303 @@
+package pdftk.org.bouncycastle.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Vector;
+
+public final class Strings
+{
+ public static String fromUTF8ByteArray(byte[] bytes)
+ {
+ int i = 0;
+ int length = 0;
+
+ while (i < bytes.length)
+ {
+ length++;
+ if ((bytes[i] & 0xf0) == 0xf0)
+ {
+ // surrogate pair
+ length++;
+ i += 4;
+ }
+ else if ((bytes[i] & 0xe0) == 0xe0)
+ {
+ i += 3;
+ }
+ else if ((bytes[i] & 0xc0) == 0xc0)
+ {
+ i += 2;
+ }
+ else
+ {
+ i += 1;
+ }
+ }
+
+ char[] cs = new char[length];
+
+ i = 0;
+ length = 0;
+
+ while (i < bytes.length)
+ {
+ char ch;
+
+ if ((bytes[i] & 0xf0) == 0xf0)
+ {
+ int codePoint = ((bytes[i] & 0x03) << 18) | ((bytes[i+1] & 0x3F) << 12) | ((bytes[i+2] & 0x3F) << 6) | (bytes[i+3] & 0x3F);
+ int U = codePoint - 0x10000;
+ char W1 = (char)(0xD800 | (U >> 10));
+ char W2 = (char)(0xDC00 | (U & 0x3FF));
+ cs[length++] = W1;
+ ch = W2;
+ i += 4;
+ }
+ else if ((bytes[i] & 0xe0) == 0xe0)
+ {
+ ch = (char)(((bytes[i] & 0x0f) << 12)
+ | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f));
+ i += 3;
+ }
+ else if ((bytes[i] & 0xd0) == 0xd0)
+ {
+ ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
+ i += 2;
+ }
+ else if ((bytes[i] & 0xc0) == 0xc0)
+ {
+ ch = (char)(((bytes[i] & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
+ i += 2;
+ }
+ else
+ {
+ ch = (char)(bytes[i] & 0xff);
+ i += 1;
+ }
+
+ cs[length++] = ch;
+ }
+
+ return new String(cs);
+ }
+
+ public static byte[] toUTF8ByteArray(String string)
+ {
+ return toUTF8ByteArray(string.toCharArray());
+ }
+
+ public static byte[] toUTF8ByteArray(char[] string)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ toUTF8ByteArray(string, bOut);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException("cannot encode string to byte array!");
+ }
+
+ return bOut.toByteArray();
+ }
+
+ public static void toUTF8ByteArray(char[] string, OutputStream sOut)
+ throws IOException
+ {
+ char[] c = string;
+ int i = 0;
+
+ while (i < c.length)
+ {
+ char ch = c[i];
+
+ if (ch < 0x0080)
+ {
+ sOut.write(ch);
+ }
+ else if (ch < 0x0800)
+ {
+ sOut.write(0xc0 | (ch >> 6));
+ sOut.write(0x80 | (ch & 0x3f));
+ }
+ // surrogate pair
+ else if (ch >= 0xD800 && ch <= 0xDFFF)
+ {
+ // in error - can only happen, if the Java String class has a
+ // bug.
+ if (i + 1 >= c.length)
+ {
+ throw new IllegalStateException("invalid UTF-16 codepoint");
+ }
+ char W1 = ch;
+ ch = c[++i];
+ char W2 = ch;
+ // in error - can only happen, if the Java String class has a
+ // bug.
+ if (W1 > 0xDBFF)
+ {
+ throw new IllegalStateException("invalid UTF-16 codepoint");
+ }
+ int codePoint = (((W1 & 0x03FF) << 10) | (W2 & 0x03FF)) + 0x10000;
+ sOut.write(0xf0 | (codePoint >> 18));
+ sOut.write(0x80 | ((codePoint >> 12) & 0x3F));
+ sOut.write(0x80 | ((codePoint >> 6) & 0x3F));
+ sOut.write(0x80 | (codePoint & 0x3F));
+ }
+ else
+ {
+ sOut.write(0xe0 | (ch >> 12));
+ sOut.write(0x80 | ((ch >> 6) & 0x3F));
+ sOut.write(0x80 | (ch & 0x3F));
+ }
+
+ i++;
+ }
+ }
+
+ /**
+ * A locale independent version of toUpperCase.
+ *
+ * @param string input to be converted
+ * @return a US Ascii uppercase version
+ */
+ public static String toUpperCase(String string)
+ {
+ boolean changed = false;
+ char[] chars = string.toCharArray();
+
+ for (int i = 0; i != chars.length; i++)
+ {
+ char ch = chars[i];
+ if ('a' <= ch && 'z' >= ch)
+ {
+ changed = true;
+ chars[i] = (char)(ch - 'a' + 'A');
+ }
+ }
+
+ if (changed)
+ {
+ return new String(chars);
+ }
+
+ return string;
+ }
+
+ /**
+ * A locale independent version of toLowerCase.
+ *
+ * @param string input to be converted
+ * @return a US ASCII lowercase version
+ */
+ public static String toLowerCase(String string)
+ {
+ boolean changed = false;
+ char[] chars = string.toCharArray();
+
+ for (int i = 0; i != chars.length; i++)
+ {
+ char ch = chars[i];
+ if ('A' <= ch && 'Z' >= ch)
+ {
+ changed = true;
+ chars[i] = (char)(ch - 'A' + 'a');
+ }
+ }
+
+ if (changed)
+ {
+ return new String(chars);
+ }
+
+ return string;
+ }
+
+ public static byte[] toByteArray(char[] chars)
+ {
+ byte[] bytes = new byte[chars.length];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ bytes[i] = (byte)chars[i];
+ }
+
+ return bytes;
+ }
+
+ public static byte[] toByteArray(String string)
+ {
+ byte[] bytes = new byte[string.length()];
+
+ for (int i = 0; i != bytes.length; i++)
+ {
+ char ch = string.charAt(i);
+
+ bytes[i] = (byte)ch;
+ }
+
+ return bytes;
+ }
+
+ /**
+ * Convert an array of 8 bit characters into a string.
+ *
+ * @param bytes 8 bit characters.
+ * @return resulting String.
+ */
+ public static String fromByteArray(byte[] bytes)
+ {
+ return new String(asCharArray(bytes));
+ }
+
+ /**
+ * Do a simple conversion of an array of 8 bit characters into a string.
+ *
+ * @param bytes 8 bit characters.
+ * @return resulting String.
+ */
+ public static char[] asCharArray(byte[] bytes)
+ {
+ char[] chars = new char[bytes.length];
+
+ for (int i = 0; i != chars.length; i++)
+ {
+ chars[i] = (char)(bytes[i] & 0xff);
+ }
+
+ return chars;
+ }
+
+ public static String[] split(String input, char delimiter)
+ {
+ Vector v = new Vector();
+ boolean moreTokens = true;
+ String subString;
+
+ while (moreTokens)
+ {
+ int tokenLocation = input.indexOf(delimiter);
+ if (tokenLocation > 0)
+ {
+ subString = input.substring(0, tokenLocation);
+ v.addElement(subString);
+ input = input.substring(tokenLocation + 1);
+ }
+ else
+ {
+ moreTokens = false;
+ v.addElement(input);
+ }
+ }
+
+ String[] res = new String[v.size()];
+
+ for (int i = 0; i != res.length; i++)
+ {
+ res[i] = (String)v.elementAt(i);
+ }
+ return res;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/Base64.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/Base64.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/Base64.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/Base64.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,121 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class Base64
+{
+ private static final Encoder encoder = new Base64Encoder();
+
+ /**
+ * encode the input data producing a base 64 encoded byte array.
+ *
+ * @return a byte array containing the base 64 encoded data.
+ */
+ public static byte[] encode(
+ byte[] data)
+ {
+ int len = (data.length + 2) / 3 * 4;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
+
+ try
+ {
+ encoder.encode(data, 0, data.length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new EncoderException("exception encoding base64 string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Encode the byte data to base 64 writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, 0, data.length, out);
+ }
+
+ /**
+ * Encode the byte data to base 64 writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, off, length, out);
+ }
+
+ /**
+ * decode the base 64 encoded input data. It is assumed the input data is valid.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ byte[] data)
+ {
+ int len = data.length / 4 * 3;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
+
+ try
+ {
+ encoder.decode(data, 0, data.length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("unable to decode base64 data: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the base 64 encoded String data - whitespace will be ignored.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ String data)
+ {
+ int len = data.length() / 4 * 3;
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream(len);
+
+ try
+ {
+ encoder.decode(data, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("unable to decode base64 string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the base 64 encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.decode(data, out);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/Base64Encoder.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/Base64Encoder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/Base64Encoder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/Base64Encoder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,328 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class Base64Encoder
+ implements Encoder
+{
+ protected final byte[] encodingTable =
+ {
+ (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
+ (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
+ (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
+ (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
+ (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
+ (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
+ (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
+ (byte)'v',
+ (byte)'w', (byte)'x', (byte)'y', (byte)'z',
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
+ (byte)'7', (byte)'8', (byte)'9',
+ (byte)'+', (byte)'/'
+ };
+
+ protected byte padding = (byte)'=';
+
+ /*
+ * set up the decoding table.
+ */
+ protected final byte[] decodingTable = new byte[128];
+
+ protected void initialiseDecodingTable()
+ {
+ for (int i = 0; i < decodingTable.length; i++)
+ {
+ decodingTable[i] = (byte)0xff;
+ }
+
+ for (int i = 0; i < encodingTable.length; i++)
+ {
+ decodingTable[encodingTable[i]] = (byte)i;
+ }
+ }
+
+ public Base64Encoder()
+ {
+ initialiseDecodingTable();
+ }
+
+ /**
+ * encode the input data producing a base 64 output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public int encode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ int modulus = length % 3;
+ int dataLength = (length - modulus);
+ int a1, a2, a3;
+
+ for (int i = off; i < off + dataLength; i += 3)
+ {
+ a1 = data[i] & 0xff;
+ a2 = data[i + 1] & 0xff;
+ a3 = data[i + 2] & 0xff;
+
+ out.write(encodingTable[(a1 >>> 2) & 0x3f]);
+ out.write(encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]);
+ out.write(encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]);
+ out.write(encodingTable[a3 & 0x3f]);
+ }
+
+ /*
+ * process the tail end.
+ */
+ int b1, b2, b3;
+ int d1, d2;
+
+ switch (modulus)
+ {
+ case 0: /* nothing left to do */
+ break;
+ case 1:
+ d1 = data[off + dataLength] & 0xff;
+ b1 = (d1 >>> 2) & 0x3f;
+ b2 = (d1 << 4) & 0x3f;
+
+ out.write(encodingTable[b1]);
+ out.write(encodingTable[b2]);
+ out.write(padding);
+ out.write(padding);
+ break;
+ case 2:
+ d1 = data[off + dataLength] & 0xff;
+ d2 = data[off + dataLength + 1] & 0xff;
+
+ b1 = (d1 >>> 2) & 0x3f;
+ b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
+ b3 = (d2 << 2) & 0x3f;
+
+ out.write(encodingTable[b1]);
+ out.write(encodingTable[b2]);
+ out.write(encodingTable[b3]);
+ out.write(padding);
+ break;
+ }
+
+ return (dataLength / 3) * 4 + ((modulus == 0) ? 0 : 4);
+ }
+
+ private boolean ignore(
+ char c)
+ {
+ return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
+ }
+
+ /**
+ * decode the base 64 encoded byte data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public int decode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ byte b1, b2, b3, b4;
+ int outLen = 0;
+
+ int end = off + length;
+
+ while (end > off)
+ {
+ if (!ignore((char)data[end - 1]))
+ {
+ break;
+ }
+
+ end--;
+ }
+
+ int i = off;
+ int finish = end - 4;
+
+ i = nextI(data, i, finish);
+
+ while (i < finish)
+ {
+ b1 = decodingTable[data[i++]];
+
+ i = nextI(data, i, finish);
+
+ b2 = decodingTable[data[i++]];
+
+ i = nextI(data, i, finish);
+
+ b3 = decodingTable[data[i++]];
+
+ i = nextI(data, i, finish);
+
+ b4 = decodingTable[data[i++]];
+
+ if ((b1 | b2 | b3 | b4) < 0)
+ {
+ throw new IOException("invalid characters encountered in base64 data");
+ }
+
+ out.write((b1 << 2) | (b2 >> 4));
+ out.write((b2 << 4) | (b3 >> 2));
+ out.write((b3 << 6) | b4);
+
+ outLen += 3;
+
+ i = nextI(data, i, finish);
+ }
+
+ outLen += decodeLastBlock(out, (char)data[end - 4], (char)data[end - 3], (char)data[end - 2], (char)data[end - 1]);
+
+ return outLen;
+ }
+
+ private int nextI(byte[] data, int i, int finish)
+ {
+ while ((i < finish) && ignore((char)data[i]))
+ {
+ i++;
+ }
+ return i;
+ }
+
+ /**
+ * decode the base 64 encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ byte b1, b2, b3, b4;
+ int length = 0;
+
+ int end = data.length();
+
+ while (end > 0)
+ {
+ if (!ignore(data.charAt(end - 1)))
+ {
+ break;
+ }
+
+ end--;
+ }
+
+ int i = 0;
+ int finish = end - 4;
+
+ i = nextI(data, i, finish);
+
+ while (i < finish)
+ {
+ b1 = decodingTable[data.charAt(i++)];
+
+ i = nextI(data, i, finish);
+
+ b2 = decodingTable[data.charAt(i++)];
+
+ i = nextI(data, i, finish);
+
+ b3 = decodingTable[data.charAt(i++)];
+
+ i = nextI(data, i, finish);
+
+ b4 = decodingTable[data.charAt(i++)];
+
+ if ((b1 | b2 | b3 | b4) < 0)
+ {
+ throw new IOException("invalid characters encountered in base64 data");
+ }
+
+ out.write((b1 << 2) | (b2 >> 4));
+ out.write((b2 << 4) | (b3 >> 2));
+ out.write((b3 << 6) | b4);
+
+ length += 3;
+
+ i = nextI(data, i, finish);
+ }
+
+ length += decodeLastBlock(out, data.charAt(end - 4), data.charAt(end - 3), data.charAt(end - 2), data.charAt(end - 1));
+
+ return length;
+ }
+
+ private int decodeLastBlock(OutputStream out, char c1, char c2, char c3, char c4)
+ throws IOException
+ {
+ byte b1, b2, b3, b4;
+
+ if (c3 == padding)
+ {
+ b1 = decodingTable[c1];
+ b2 = decodingTable[c2];
+
+ if ((b1 | b2) < 0)
+ {
+ throw new IOException("invalid characters encountered at end of base64 data");
+ }
+
+ out.write((b1 << 2) | (b2 >> 4));
+
+ return 1;
+ }
+ else if (c4 == padding)
+ {
+ b1 = decodingTable[c1];
+ b2 = decodingTable[c2];
+ b3 = decodingTable[c3];
+
+ if ((b1 | b2 | b3) < 0)
+ {
+ throw new IOException("invalid characters encountered at end of base64 data");
+ }
+
+ out.write((b1 << 2) | (b2 >> 4));
+ out.write((b2 << 4) | (b3 >> 2));
+
+ return 2;
+ }
+ else
+ {
+ b1 = decodingTable[c1];
+ b2 = decodingTable[c2];
+ b3 = decodingTable[c3];
+ b4 = decodingTable[c4];
+
+ if ((b1 | b2 | b3 | b4) < 0)
+ {
+ throw new IOException("invalid characters encountered at end of base64 data");
+ }
+
+ out.write((b1 << 2) | (b2 >> 4));
+ out.write((b2 << 4) | (b3 >> 2));
+ out.write((b3 << 6) | b4);
+
+ return 3;
+ }
+ }
+
+ private int nextI(String data, int i, int finish)
+ {
+ while ((i < finish) && ignore(data.charAt(i)))
+ {
+ i++;
+ }
+ return i;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/BufferedDecoder.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/BufferedDecoder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/BufferedDecoder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/BufferedDecoder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,96 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+
+/**
+ * a buffering class to allow translation from one format to another to
+ * be done in discrete chunks.
+ */
+public class BufferedDecoder
+{
+ protected byte[] buf;
+ protected int bufOff;
+
+ protected Translator translator;
+
+ /**
+ * @param translator the translator to use.
+ * @param bufSize amount of input to buffer for each chunk.
+ */
+ public BufferedDecoder(
+ Translator translator,
+ int bufSize)
+ {
+ this.translator = translator;
+
+ if ((bufSize % translator.getEncodedBlockSize()) != 0)
+ {
+ throw new IllegalArgumentException("buffer size not multiple of input block size");
+ }
+
+ buf = new byte[bufSize];
+ bufOff = 0;
+ }
+
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ {
+ int resultLen = 0;
+
+ buf[bufOff++] = in;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = translator.decode(buf, 0, buf.length, out, outOff);
+ bufOff = 0;
+ }
+
+ return resultLen;
+ }
+
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += translator.decode(buf, 0, buf.length, out, outOff);
+
+ bufOff = 0;
+
+ len -= gapLen;
+ inOff += gapLen;
+ outOff += resultLen;
+
+ int chunkSize = len - (len % buf.length);
+
+ resultLen += translator.decode(in, inOff, chunkSize, out, outOff);
+
+ len -= chunkSize;
+ inOff += chunkSize;
+ }
+
+ if (len != 0)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ return resultLen;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/BufferedEncoder.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/BufferedEncoder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/BufferedEncoder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/BufferedEncoder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,96 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+
+/**
+ * a buffering class to allow translation from one format to another to
+ * be done in discrete chunks.
+ */
+public class BufferedEncoder
+{
+ protected byte[] buf;
+ protected int bufOff;
+
+ protected Translator translator;
+
+ /**
+ * @param translator the translator to use.
+ * @param bufSize amount of input to buffer for each chunk.
+ */
+ public BufferedEncoder(
+ Translator translator,
+ int bufSize)
+ {
+ this.translator = translator;
+
+ if ((bufSize % translator.getEncodedBlockSize()) != 0)
+ {
+ throw new IllegalArgumentException("buffer size not multiple of input block size");
+ }
+
+ buf = new byte[bufSize];
+ bufOff = 0;
+ }
+
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ {
+ int resultLen = 0;
+
+ buf[bufOff++] = in;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = translator.encode(buf, 0, buf.length, out, outOff);
+ bufOff = 0;
+ }
+
+ return resultLen;
+ }
+
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += translator.encode(buf, 0, buf.length, out, outOff);
+
+ bufOff = 0;
+
+ len -= gapLen;
+ inOff += gapLen;
+ outOff += resultLen;
+
+ int chunkSize = len - (len % buf.length);
+
+ resultLen += translator.encode(in, inOff, chunkSize, out, outOff);
+
+ len -= chunkSize;
+ inOff += chunkSize;
+ }
+
+ if (len != 0)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+ }
+
+ return resultLen;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/DecoderException.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/DecoderException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/DecoderException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/DecoderException.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,19 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+public class DecoderException
+ extends IllegalStateException
+{
+ private Throwable cause;
+
+ DecoderException(String msg, Throwable cause)
+ {
+ super(msg);
+
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/Encoder.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/Encoder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/Encoder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/Encoder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,17 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Encode and decode byte arrays (typically from binary to 7-bit ASCII
+ * encodings).
+ */
+public interface Encoder
+{
+ int encode(byte[] data, int off, int length, OutputStream out) throws IOException;
+
+ int decode(byte[] data, int off, int length, OutputStream out) throws IOException;
+
+ int decode(String data, OutputStream out) throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/EncoderException.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/EncoderException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/EncoderException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/EncoderException.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,19 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+public class EncoderException
+ extends IllegalStateException
+{
+ private Throwable cause;
+
+ EncoderException(String msg, Throwable cause)
+ {
+ super(msg);
+
+ this.cause = cause;
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/Hex.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/Hex.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/Hex.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/Hex.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,131 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class Hex
+{
+ private static final Encoder encoder = new HexEncoder();
+
+ /**
+ * encode the input data producing a Hex encoded byte array.
+ *
+ * @return a byte array containing the Hex encoded data.
+ */
+ public static byte[] encode(
+ byte[] data)
+ {
+ return encode(data, 0, data.length);
+ }
+
+ /**
+ * encode the input data producing a Hex encoded byte array.
+ *
+ * @return a byte array containing the Hex encoded data.
+ */
+ public static byte[] encode(
+ byte[] data,
+ int off,
+ int length)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.encode(data, off, length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new EncoderException("exception encoding Hex string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Hex encode the byte data writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, 0, data.length, out);
+ }
+
+ /**
+ * Hex encode the byte data writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, off, length, out);
+ }
+
+ /**
+ * decode the Hex encoded input data. It is assumed the input data is valid.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ byte[] data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.decode(data, 0, data.length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("exception decoding Hex data: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the Hex encoded String data - whitespace will be ignored.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ String data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.decode(data, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("exception decoding Hex string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the Hex encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.decode(data, out);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/HexEncoder.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/HexEncoder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/HexEncoder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/HexEncoder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,187 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class HexEncoder
+ implements Encoder
+{
+ protected final byte[] encodingTable =
+ {
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
+ (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
+ };
+
+ /*
+ * set up the decoding table.
+ */
+ protected final byte[] decodingTable = new byte[128];
+
+ protected void initialiseDecodingTable()
+ {
+ for (int i = 0; i < decodingTable.length; i++)
+ {
+ decodingTable[i] = (byte)0xff;
+ }
+
+ for (int i = 0; i < encodingTable.length; i++)
+ {
+ decodingTable[encodingTable[i]] = (byte)i;
+ }
+
+ decodingTable['A'] = decodingTable['a'];
+ decodingTable['B'] = decodingTable['b'];
+ decodingTable['C'] = decodingTable['c'];
+ decodingTable['D'] = decodingTable['d'];
+ decodingTable['E'] = decodingTable['e'];
+ decodingTable['F'] = decodingTable['f'];
+ }
+
+ public HexEncoder()
+ {
+ initialiseDecodingTable();
+ }
+
+ /**
+ * encode the input data producing a Hex output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public int encode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ for (int i = off; i < (off + length); i++)
+ {
+ int v = data[i] & 0xff;
+
+ out.write(encodingTable[(v >>> 4)]);
+ out.write(encodingTable[v & 0xf]);
+ }
+
+ return length * 2;
+ }
+
+ private static boolean ignore(
+ char c)
+ {
+ return c == '\n' || c =='\r' || c == '\t' || c == ' ';
+ }
+
+ /**
+ * decode the Hex encoded byte data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public int decode(
+ byte[] data,
+ int off,
+ int length,
+ OutputStream out)
+ throws IOException
+ {
+ byte b1, b2;
+ int outLen = 0;
+
+ int end = off + length;
+
+ while (end > off)
+ {
+ if (!ignore((char)data[end - 1]))
+ {
+ break;
+ }
+
+ end--;
+ }
+
+ int i = off;
+ while (i < end)
+ {
+ while (i < end && ignore((char)data[i]))
+ {
+ i++;
+ }
+
+ b1 = decodingTable[data[i++]];
+
+ while (i < end && ignore((char)data[i]))
+ {
+ i++;
+ }
+
+ b2 = decodingTable[data[i++]];
+
+ if ((b1 | b2) < 0)
+ {
+ throw new IOException("invalid characters encountered in Hex data");
+ }
+
+ out.write((b1 << 4) | b2);
+
+ outLen++;
+ }
+
+ return outLen;
+ }
+
+ /**
+ * decode the Hex encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ byte b1, b2;
+ int length = 0;
+
+ int end = data.length();
+
+ while (end > 0)
+ {
+ if (!ignore(data.charAt(end - 1)))
+ {
+ break;
+ }
+
+ end--;
+ }
+
+ int i = 0;
+ while (i < end)
+ {
+ while (i < end && ignore(data.charAt(i)))
+ {
+ i++;
+ }
+
+ b1 = decodingTable[data.charAt(i++)];
+
+ while (i < end && ignore(data.charAt(i)))
+ {
+ i++;
+ }
+
+ b2 = decodingTable[data.charAt(i++)];
+
+ if ((b1 | b2) < 0)
+ {
+ throw new IOException("invalid characters encountered in Hex string");
+ }
+
+ out.write((b1 << 4) | b2);
+
+ length++;
+ }
+
+ return length;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/HexTranslator.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/HexTranslator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/HexTranslator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/HexTranslator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,87 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+/**
+ * Converters for going from hex to binary and back. Note: this class assumes ASCII processing.
+ */
+public class HexTranslator
+ implements Translator
+{
+ private static final byte[] hexTable =
+ {
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
+ (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
+ };
+
+ /**
+ * size of the output block on encoding produced by getDecodedBlockSize()
+ * bytes.
+ */
+ public int getEncodedBlockSize()
+ {
+ return 2;
+ }
+
+ public int encode(
+ byte[] in,
+ int inOff,
+ int length,
+ byte[] out,
+ int outOff)
+ {
+ for (int i = 0, j = 0; i < length; i++, j += 2)
+ {
+ out[outOff + j] = hexTable[(in[inOff] >> 4) & 0x0f];
+ out[outOff + j + 1] = hexTable[in[inOff] & 0x0f];
+
+ inOff++;
+ }
+
+ return length * 2;
+ }
+
+ /**
+ * size of the output block on decoding produced by getEncodedBlockSize()
+ * bytes.
+ */
+ public int getDecodedBlockSize()
+ {
+ return 1;
+ }
+
+ public int decode(
+ byte[] in,
+ int inOff,
+ int length,
+ byte[] out,
+ int outOff)
+ {
+ int halfLength = length / 2;
+ byte left, right;
+ for (int i = 0; i < halfLength; i++)
+ {
+ left = in[inOff + i * 2];
+ right = in[inOff + i * 2 + 1];
+
+ if (left < (byte)'a')
+ {
+ out[outOff] = (byte)((left - '0') << 4);
+ }
+ else
+ {
+ out[outOff] = (byte)((left - 'a' + 10) << 4);
+ }
+ if (right < (byte)'a')
+ {
+ out[outOff] += (byte)(right - '0');
+ }
+ else
+ {
+ out[outOff] += (byte)(right - 'a' + 10);
+ }
+
+ outOff++;
+ }
+
+ return halfLength;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/Translator.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/Translator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/Translator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/Translator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+/**
+ * general interface for an translator.
+ */
+public interface Translator
+{
+ /**
+ * size of the output block on encoding produced by getDecodedBlockSize()
+ * bytes.
+ */
+ public int getEncodedBlockSize();
+
+ public int encode(byte[] in, int inOff, int length, byte[] out, int outOff);
+
+ /**
+ * size of the output block on decoding produced by getEncodedBlockSize()
+ * bytes.
+ */
+ public int getDecodedBlockSize();
+
+ public int decode(byte[] in, int inOff, int length, byte[] out, int outOff);
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/UrlBase64.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/UrlBase64.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/UrlBase64.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/UrlBase64.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,129 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Convert binary data to and from UrlBase64 encoding. This is identical to
+ * Base64 encoding, except that the padding character is "." and the other
+ * non-alphanumeric characters are "-" and "_" instead of "+" and "/".
+ *
+ * The purpose of UrlBase64 encoding is to provide a compact encoding of binary
+ * data that is safe for use as an URL parameter. Base64 encoding does not
+ * produce encoded values that are safe for use in URLs, since "/" can be
+ * interpreted as a path delimiter; "+" is the encoded form of a space; and
+ * "=" is used to separate a name from the corresponding value in an URL
+ * parameter.
+ */
+public class UrlBase64
+{
+ private static final Encoder encoder = new UrlBase64Encoder();
+
+ /**
+ * Encode the input data producing a URL safe base 64 encoded byte array.
+ *
+ * @return a byte array containing the URL safe base 64 encoded data.
+ */
+ public static byte[] encode(
+ byte[] data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.encode(data, 0, data.length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new EncoderException("exception encoding URL safe base64 data: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Encode the byte data writing it to the given output stream.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int encode(
+ byte[] data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.encode(data, 0, data.length, out);
+ }
+
+ /**
+ * Decode the URL safe base 64 encoded input data - white space will be ignored.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ byte[] data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.decode(data, 0, data.length, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("exception decoding URL safe base64 string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * decode the URL safe base 64 encoded byte data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int decode(
+ byte[] data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.decode(data, 0, data.length, out);
+ }
+
+ /**
+ * decode the URL safe base 64 encoded String data - whitespace will be ignored.
+ *
+ * @return a byte array representing the decoded data.
+ */
+ public static byte[] decode(
+ String data)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ try
+ {
+ encoder.decode(data, bOut);
+ }
+ catch (Exception e)
+ {
+ throw new DecoderException("exception decoding URL safe base64 string: " + e.getMessage(), e);
+ }
+
+ return bOut.toByteArray();
+ }
+
+ /**
+ * Decode the URL safe base 64 encoded String data writing it to the given output stream,
+ * whitespace characters will be ignored.
+ *
+ * @return the number of bytes produced.
+ */
+ public static int decode(
+ String data,
+ OutputStream out)
+ throws IOException
+ {
+ return encoder.decode(data, out);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/UrlBase64Encoder.java pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/UrlBase64Encoder.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/UrlBase64Encoder.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/UrlBase64Encoder.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,25 @@
+package pdftk.org.bouncycastle.util.encoders;
+
+/**
+ * Convert binary data to and from UrlBase64 encoding. This is identical to
+ * Base64 encoding, except that the padding character is "." and the other
+ * non-alphanumeric characters are "-" and "_" instead of "+" and "/".
+ *
+ * The purpose of UrlBase64 encoding is to provide a compact encoding of binary
+ * data that is safe for use as an URL parameter. Base64 encoding does not
+ * produce encoded values that are safe for use in URLs, since "/" can be
+ * interpreted as a path delimiter; "+" is the encoded form of a space; and
+ * "=" is used to separate a name from the corresponding value in an URL
+ * parameter.
+ */
+public class UrlBase64Encoder extends Base64Encoder
+{
+ public UrlBase64Encoder()
+ {
+ encodingTable[encodingTable.length - 2] = (byte) '-';
+ encodingTable[encodingTable.length - 1] = (byte) '_';
+ padding = (byte) '.';
+ // we must re-create the decoding table with the new encoded values.
+ initialiseDecodingTable();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/package.html pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/package.html
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/encoders/package.html 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/encoders/package.html 2013-02-09 16:32:08.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+Classes for producing and reading Base64 and Hex strings.
+
+
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/io/StreamOverflowException.java pdftk-2.01/java/pdftk/org/bouncycastle/util/io/StreamOverflowException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/io/StreamOverflowException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/io/StreamOverflowException.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,12 @@
+package pdftk.org.bouncycastle.util.io;
+
+import java.io.IOException;
+
+public class StreamOverflowException
+ extends IOException
+{
+ public StreamOverflowException(String msg)
+ {
+ super(msg);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/io/Streams.java pdftk-2.01/java/pdftk/org/bouncycastle/util/io/Streams.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/io/Streams.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/io/Streams.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,87 @@
+package pdftk.org.bouncycastle.util.io;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public final class Streams
+{
+ private static int BUFFER_SIZE = 512;
+
+ public static void drain(InputStream inStr)
+ throws IOException
+ {
+ byte[] bs = new byte[BUFFER_SIZE];
+ while (inStr.read(bs, 0, bs.length) >= 0)
+ {
+ }
+ }
+
+ public static byte[] readAll(InputStream inStr)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ pipeAll(inStr, buf);
+ return buf.toByteArray();
+ }
+
+ public static byte[] readAllLimited(InputStream inStr, int limit)
+ throws IOException
+ {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ pipeAllLimited(inStr, limit, buf);
+ return buf.toByteArray();
+ }
+
+ public static int readFully(InputStream inStr, byte[] buf)
+ throws IOException
+ {
+ return readFully(inStr, buf, 0, buf.length);
+ }
+
+ public static int readFully(InputStream inStr, byte[] buf, int off, int len)
+ throws IOException
+ {
+ int totalRead = 0;
+ while (totalRead < len)
+ {
+ int numRead = inStr.read(buf, off + totalRead, len - totalRead);
+ if (numRead < 0)
+ {
+ break;
+ }
+ totalRead += numRead;
+ }
+ return totalRead;
+ }
+
+ public static void pipeAll(InputStream inStr, OutputStream outStr)
+ throws IOException
+ {
+ byte[] bs = new byte[BUFFER_SIZE];
+ int numRead;
+ while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
+ {
+ outStr.write(bs, 0, numRead);
+ }
+ }
+
+ public static long pipeAllLimited(InputStream inStr, long limit, OutputStream outStr)
+ throws IOException
+ {
+ long total = 0;
+ byte[] bs = new byte[BUFFER_SIZE];
+ int numRead;
+ while ((numRead = inStr.read(bs, 0, bs.length)) >= 0)
+ {
+ total += numRead;
+ if (total > limit)
+ {
+ throw new StreamOverflowException("Data Overflow");
+ }
+ outStr.write(bs, 0, numRead);
+ }
+ return total;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/io/TeeInputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/util/io/TeeInputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/io/TeeInputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/io/TeeInputStream.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,62 @@
+package pdftk.org.bouncycastle.util.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class TeeInputStream
+ extends InputStream
+{
+ private final InputStream input;
+ private final OutputStream output;
+
+ public TeeInputStream(InputStream input, OutputStream output)
+ {
+ this.input = input;
+ this.output = output;
+ }
+
+ public int read(byte[] buf)
+ throws IOException
+ {
+ return read(buf, 0, buf.length);
+ }
+
+ public int read(byte[] buf, int off, int len)
+ throws IOException
+ {
+ int i = input.read(buf, off, len);
+
+ if (i > 0)
+ {
+ output.write(buf, off, i);
+ }
+
+ return i;
+ }
+
+ public int read()
+ throws IOException
+ {
+ int i = input.read();
+
+ if (i >= 0)
+ {
+ output.write(i);
+ }
+
+ return i;
+ }
+
+ public void close()
+ throws IOException
+ {
+ this.input.close();
+ this.output.close();
+ }
+
+ public OutputStream getOutputStream()
+ {
+ return output;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/io/TeeOutputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/util/io/TeeOutputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/io/TeeOutputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/io/TeeOutputStream.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,52 @@
+package pdftk.org.bouncycastle.util.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class TeeOutputStream
+ extends OutputStream
+{
+ private OutputStream output1;
+ private OutputStream output2;
+
+ public TeeOutputStream(OutputStream output1, OutputStream output2)
+ {
+ this.output1 = output1;
+ this.output2 = output2;
+ }
+
+ public void write(byte[] buf)
+ throws IOException
+ {
+ this.output1.write(buf);
+ this.output2.write(buf);
+ }
+
+ public void write(byte[] buf, int off, int len)
+ throws IOException
+ {
+ this.output1.write(buf, off, len);
+ this.output2.write(buf, off, len);
+ }
+
+ public void write(int b)
+ throws IOException
+ {
+ this.output1.write(b);
+ this.output2.write(b);
+ }
+
+ public void flush()
+ throws IOException
+ {
+ this.output1.flush();
+ this.output2.flush();
+ }
+
+ public void close()
+ throws IOException
+ {
+ this.output1.close();
+ this.output2.close();
+ }
+}
\ No newline at end of file
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemGenerationException.java pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemGenerationException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemGenerationException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemGenerationException.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,25 @@
+package pdftk.org.bouncycastle.util.io.pem;
+
+import java.io.IOException;
+
+public class PemGenerationException
+ extends IOException
+{
+ private Throwable cause;
+
+ public PemGenerationException(String message, Throwable cause)
+ {
+ super(message);
+ this.cause = cause;
+ }
+
+ public PemGenerationException(String message)
+ {
+ super(message);
+ }
+
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemHeader.java pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemHeader.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemHeader.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemHeader.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,66 @@
+package pdftk.org.bouncycastle.util.io.pem;
+
+public class PemHeader
+{
+ private String name;
+ private String value;
+
+ public PemHeader(String name, String value)
+ {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+
+ public int hashCode()
+ {
+ return getHashCode(this.name) + 31 * getHashCode(this.value);
+ }
+
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof PemHeader))
+ {
+ return false;
+ }
+
+ PemHeader other = (PemHeader)o;
+
+ return other == this || (isEqual(this.name, other.name) && isEqual(this.value, other.value));
+ }
+
+ private int getHashCode(String s)
+ {
+ if (s == null)
+ {
+ return 1;
+ }
+
+ return s.hashCode();
+ }
+
+ private boolean isEqual(String s1, String s2)
+ {
+ if (s1 == s2)
+ {
+ return true;
+ }
+
+ if (s1 == null || s2 == null)
+ {
+ return false;
+ }
+
+ return s1.equals(s2);
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemObject.java pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemObject.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemObject.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemObject.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,61 @@
+package pdftk.org.bouncycastle.util.io.pem;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class PemObject
+ implements PemObjectGenerator
+{
+ private static final List EMPTY_LIST = Collections.unmodifiableList(new ArrayList());
+
+ private String type;
+ private List headers;
+ private byte[] content;
+
+ /**
+ * Generic constructor for object without headers.
+ *
+ * @param type pem object type.
+ * @param content the binary content of the object.
+ */
+ public PemObject(String type, byte[] content)
+ {
+ this(type, EMPTY_LIST, content);
+ }
+
+ /**
+ * Generic constructor for object with headers.
+ *
+ * @param type pem object type.
+ * @param headers a list of PemHeader objects.
+ * @param content the binary content of the object.
+ */
+ public PemObject(String type, List headers, byte[] content)
+ {
+ this.type = type;
+ this.headers = Collections.unmodifiableList(headers);
+ this.content = content;
+ }
+
+ public String getType()
+ {
+ return type;
+ }
+
+ public List getHeaders()
+ {
+ return headers;
+ }
+
+ public byte[] getContent()
+ {
+ return content;
+ }
+
+ public PemObject generate()
+ throws PemGenerationException
+ {
+ return this;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemObjectGenerator.java pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemObjectGenerator.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemObjectGenerator.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemObjectGenerator.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,7 @@
+package pdftk.org.bouncycastle.util.io.pem;
+
+public interface PemObjectGenerator
+{
+ PemObject generate()
+ throws PemGenerationException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemObjectParser.java pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemObjectParser.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemObjectParser.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemObjectParser.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,9 @@
+package pdftk.org.bouncycastle.util.io.pem;
+
+import java.io.IOException;
+
+public interface PemObjectParser
+{
+ Object parseObject(PemObject obj)
+ throws IOException;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemReader.java pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemReader.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemReader.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemReader.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,84 @@
+package pdftk.org.bouncycastle.util.io.pem;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+
+import pdftk.org.bouncycastle.util.encoders.Base64;
+
+public class PemReader
+ extends BufferedReader
+{
+ private static final String BEGIN = "-----BEGIN ";
+ private static final String END = "-----END ";
+
+ public PemReader(Reader reader)
+ {
+ super(reader);
+ }
+
+ public PemObject readPemObject()
+ throws IOException
+ {
+ String line = readLine();
+
+ while (line != null && !line.startsWith(BEGIN))
+ {
+ line = readLine();
+ }
+
+ if (line != null)
+ {
+ line = line.substring(BEGIN.length());
+ int index = line.indexOf('-');
+ String type = line.substring(0, index);
+
+ if (index > 0)
+ {
+ return loadObject(type);
+ }
+ }
+
+ return null;
+ }
+
+ private PemObject loadObject(String type)
+ throws IOException
+ {
+ String line;
+ String endMarker = END + type;
+ StringBuffer buf = new StringBuffer();
+ List headers = new ArrayList();
+
+ while ((line = readLine()) != null)
+ {
+ if (line.indexOf(":") >= 0)
+ {
+ int index = line.indexOf(':');
+ String hdr = line.substring(0, index);
+ String value = line.substring(index + 1).trim();
+
+ headers.add(new PemHeader(hdr, value));
+
+ continue;
+ }
+
+ if (line.indexOf(endMarker) != -1)
+ {
+ break;
+ }
+
+ buf.append(line.trim());
+ }
+
+ if (line == null)
+ {
+ throw new IOException(endMarker + " not found");
+ }
+
+ return new PemObject(type, headers, Base64.decode(buf.toString()));
+ }
+
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemWriter.java pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemWriter.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/io/pem/PemWriter.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/io/pem/PemWriter.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,137 @@
+package pdftk.org.bouncycastle.util.io.pem;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Iterator;
+
+import pdftk.org.bouncycastle.util.encoders.Base64;
+
+/**
+ * A generic PEM writer, based on RFC 1421
+ */
+public class PemWriter
+ extends BufferedWriter
+{
+ private static final int LINE_LENGTH = 64;
+
+ private final int nlLength;
+ private char[] buf = new char[LINE_LENGTH];
+
+ /**
+ * Base constructor.
+ *
+ * @param out output stream to use.
+ */
+ public PemWriter(Writer out)
+ {
+ super(out);
+
+ String nl = System.getProperty("line.separator");
+ if (nl != null)
+ {
+ nlLength = nl.length();
+ }
+ else
+ {
+ nlLength = 2;
+ }
+ }
+
+ /**
+ * Return the number of bytes or characters required to contain the
+ * passed in object if it is PEM encoded.
+ *
+ * @param obj pem object to be output
+ * @return an estimate of the number of bytes
+ */
+ public int getOutputSize(PemObject obj)
+ {
+ // BEGIN and END boundaries.
+ int size = (2 * (obj.getType().length() + 10 + nlLength)) + 6 + 4;
+
+ if (!obj.getHeaders().isEmpty())
+ {
+ for (Iterator it = obj.getHeaders().iterator(); it.hasNext();)
+ {
+ PemHeader hdr = (PemHeader)it.next();
+
+ size += hdr.getName().length() + ": ".length() + hdr.getValue().length() + nlLength;
+ }
+
+ size += nlLength;
+ }
+
+ // base64 encoding
+ int dataLen = ((obj.getContent().length + 2) / 3) * 4;
+
+ size += dataLen + (((dataLen + LINE_LENGTH - 1) / LINE_LENGTH) * nlLength);
+
+ return size;
+ }
+
+ public void writeObject(PemObjectGenerator objGen)
+ throws IOException
+ {
+ PemObject obj = objGen.generate();
+
+ writePreEncapsulationBoundary(obj.getType());
+
+ if (!obj.getHeaders().isEmpty())
+ {
+ for (Iterator it = obj.getHeaders().iterator(); it.hasNext();)
+ {
+ PemHeader hdr = (PemHeader)it.next();
+
+ this.write(hdr.getName());
+ this.write(": ");
+ this.write(hdr.getValue());
+ this.newLine();
+ }
+
+ this.newLine();
+ }
+
+ writeEncoded(obj.getContent());
+ writePostEncapsulationBoundary(obj.getType());
+ }
+
+ private void writeEncoded(byte[] bytes)
+ throws IOException
+ {
+ bytes = Base64.encode(bytes);
+
+ for (int i = 0; i < bytes.length; i += buf.length)
+ {
+ int index = 0;
+
+ while (index != buf.length)
+ {
+ if ((i + index) >= bytes.length)
+ {
+ break;
+ }
+ buf[index] = (char)bytes[i + index];
+ index++;
+ }
+ this.write(buf, 0, index);
+ this.newLine();
+ }
+ }
+
+ private void writePreEncapsulationBoundary(
+ String type)
+ throws IOException
+ {
+ this.write("-----BEGIN " + type + "-----");
+ this.newLine();
+ }
+
+ private void writePostEncapsulationBoundary(
+ String type)
+ throws IOException
+ {
+ this.write("-----END " + type + "-----");
+ this.newLine();
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/test/FixedSecureRandom.java pdftk-2.01/java/pdftk/org/bouncycastle/util/test/FixedSecureRandom.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/test/FixedSecureRandom.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/test/FixedSecureRandom.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,135 @@
+package pdftk.org.bouncycastle.util.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.SecureRandom;
+
+public class FixedSecureRandom
+ extends SecureRandom
+{
+ private byte[] _data;
+
+ private int _index;
+ private int _intPad;
+
+ public FixedSecureRandom(byte[] value)
+ {
+ this(false, new byte[][] { value });
+ }
+
+ public FixedSecureRandom(
+ byte[][] values)
+ {
+ this(false, values);
+ }
+
+ /**
+ * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
+ * implementation.
+ */
+ public FixedSecureRandom(
+ boolean intPad,
+ byte[] value)
+ {
+ this(intPad, new byte[][] { value });
+ }
+
+ /**
+ * Pad the data on integer boundaries. This is necessary for the classpath project's BigInteger
+ * implementation.
+ */
+ public FixedSecureRandom(
+ boolean intPad,
+ byte[][] values)
+ {
+ ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+
+ for (int i = 0; i != values.length; i++)
+ {
+ try
+ {
+ bOut.write(values[i]);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalArgumentException("can't save value array.");
+ }
+ }
+
+ _data = bOut.toByteArray();
+
+ if (intPad)
+ {
+ _intPad = _data.length % 4;
+ }
+ }
+
+ public void nextBytes(byte[] bytes)
+ {
+ System.arraycopy(_data, _index, bytes, 0, bytes.length);
+
+ _index += bytes.length;
+ }
+
+ //
+ // classpath's implementation of SecureRandom doesn't currently go back to nextBytes
+ // when next is called. We can't override next as it's a final method.
+ //
+ public int nextInt()
+ {
+ int val = 0;
+
+ val |= nextValue() << 24;
+ val |= nextValue() << 16;
+
+ if (_intPad == 2)
+ {
+ _intPad--;
+ }
+ else
+ {
+ val |= nextValue() << 8;
+ }
+
+ if (_intPad == 1)
+ {
+ _intPad--;
+ }
+ else
+ {
+ val |= nextValue();
+ }
+
+ return val;
+ }
+
+ //
+ // classpath's implementation of SecureRandom doesn't currently go back to nextBytes
+ // when next is called. We can't override next as it's a final method.
+ //
+ public long nextLong()
+ {
+ long val = 0;
+
+ val |= (long)nextValue() << 56;
+ val |= (long)nextValue() << 48;
+ val |= (long)nextValue() << 40;
+ val |= (long)nextValue() << 32;
+ val |= (long)nextValue() << 24;
+ val |= (long)nextValue() << 16;
+ val |= (long)nextValue() << 8;
+ val |= (long)nextValue();
+
+ return val;
+ }
+
+ public boolean isExhausted()
+ {
+ return _index == _data.length;
+ }
+
+ private int nextValue()
+ {
+ return _data[_index++] & 0xff;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/test/NumberParsing.java pdftk-2.01/java/pdftk/org/bouncycastle/util/test/NumberParsing.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/test/NumberParsing.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/test/NumberParsing.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,34 @@
+package pdftk.org.bouncycastle.util.test;
+
+/**
+ * Parsing
+ */
+public final class NumberParsing
+{
+ private NumberParsing()
+ {
+ // Hide constructor
+ }
+
+ public static long decodeLongFromHex(String longAsString)
+ {
+ if ((longAsString.charAt(1) == 'x')
+ || (longAsString.charAt(1) == 'X'))
+ {
+ return Long.parseLong(longAsString.substring(2), 16);
+ }
+
+ return Long.parseLong(longAsString, 16);
+ }
+
+ public static int decodeIntFromHex(String intAsString)
+ {
+ if ((intAsString.charAt(1) == 'x')
+ || (intAsString.charAt(1) == 'X'))
+ {
+ return Integer.parseInt(intAsString.substring(2), 16);
+ }
+
+ return Integer.parseInt(intAsString, 16);
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/test/SimpleTest.java pdftk-2.01/java/pdftk/org/bouncycastle/util/test/SimpleTest.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/test/SimpleTest.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/test/SimpleTest.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,84 @@
+package pdftk.org.bouncycastle.util.test;
+
+import java.io.PrintStream;
+
+import pdftk.org.bouncycastle.util.Arrays;
+
+public abstract class SimpleTest
+ implements Test
+{
+ public abstract String getName();
+
+ private TestResult success()
+ {
+ return SimpleTestResult.successful(this, "Okay");
+ }
+
+ protected void fail(
+ String message)
+ {
+ throw new TestFailedException(SimpleTestResult.failed(this, message));
+ }
+
+ protected void fail(
+ String message,
+ Throwable throwable)
+ {
+ throw new TestFailedException(SimpleTestResult.failed(this, message, throwable));
+ }
+
+ protected void fail(
+ String message,
+ Object expected,
+ Object found)
+ {
+ throw new TestFailedException(SimpleTestResult.failed(this, message, expected, found));
+ }
+
+ protected boolean areEqual(
+ byte[] a,
+ byte[] b)
+ {
+ return Arrays.areEqual(a, b);
+ }
+
+ public TestResult perform()
+ {
+ try
+ {
+ performTest();
+
+ return success();
+ }
+ catch (TestFailedException e)
+ {
+ return e.getResult();
+ }
+ catch (Exception e)
+ {
+ return SimpleTestResult.failed(this, "Exception: " + e, e);
+ }
+ }
+
+ protected static void runTest(
+ Test test)
+ {
+ runTest(test, System.out);
+ }
+
+ protected static void runTest(
+ Test test,
+ PrintStream out)
+ {
+ TestResult result = test.perform();
+
+ out.println(result.toString());
+ if (result.getException() != null)
+ {
+ result.getException().printStackTrace(out);
+ }
+ }
+
+ public abstract void performTest()
+ throws Exception;
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/test/SimpleTestResult.java pdftk-2.01/java/pdftk/org/bouncycastle/util/test/SimpleTestResult.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/test/SimpleTestResult.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/test/SimpleTestResult.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,80 @@
+package pdftk.org.bouncycastle.util.test;
+
+public class SimpleTestResult implements TestResult
+{
+ private static final String SEPARATOR = System.getProperty("line.separator");
+
+ private boolean success;
+ private String message;
+ private Throwable exception;
+
+ public SimpleTestResult(boolean success, String message)
+ {
+ this.success = success;
+ this.message = message;
+ }
+
+ public SimpleTestResult(boolean success, String message, Throwable exception)
+ {
+ this.success = success;
+ this.message = message;
+ this.exception = exception;
+ }
+
+ public static TestResult successful(
+ Test test,
+ String message)
+ {
+ return new SimpleTestResult(true, test.getName() + ": " + message);
+ }
+
+ public static TestResult failed(
+ Test test,
+ String message)
+ {
+ return new SimpleTestResult(false, test.getName() + ": " + message);
+ }
+
+ public static TestResult failed(
+ Test test,
+ String message,
+ Throwable t)
+ {
+ return new SimpleTestResult(false, test.getName() + ": " + message, t);
+ }
+
+ public static TestResult failed(
+ Test test,
+ String message,
+ Object expected,
+ Object found)
+ {
+ return failed(test, message + SEPARATOR + "Expected: " + expected + SEPARATOR + "Found : " + found);
+ }
+
+ public static String failedMessage(String algorithm, String testName, String expected,
+ String actual)
+ {
+ StringBuffer sb = new StringBuffer(algorithm);
+ sb.append(" failing ").append(testName);
+ sb.append(SEPARATOR).append(" expected: ").append(expected);
+ sb.append(SEPARATOR).append(" got : ").append(actual);
+
+ return sb.toString();
+ }
+
+ public boolean isSuccessful()
+ {
+ return success;
+ }
+
+ public String toString()
+ {
+ return message;
+ }
+
+ public Throwable getException()
+ {
+ return exception;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/test/Test.java pdftk-2.01/java/pdftk/org/bouncycastle/util/test/Test.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/test/Test.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/test/Test.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,8 @@
+package pdftk.org.bouncycastle.util.test;
+
+public interface Test
+{
+ String getName();
+
+ TestResult perform();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/test/TestFailedException.java pdftk-2.01/java/pdftk/org/bouncycastle/util/test/TestFailedException.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/test/TestFailedException.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/test/TestFailedException.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,18 @@
+package pdftk.org.bouncycastle.util.test;
+
+public class TestFailedException
+ extends RuntimeException
+{
+ private TestResult _result;
+
+ public TestFailedException(
+ TestResult result)
+ {
+ _result = result;
+ }
+
+ public TestResult getResult()
+ {
+ return _result;
+ }
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/test/TestResult.java pdftk-2.01/java/pdftk/org/bouncycastle/util/test/TestResult.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/test/TestResult.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/test/TestResult.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,10 @@
+package pdftk.org.bouncycastle.util.test;
+
+public interface TestResult
+{
+ public boolean isSuccessful();
+
+ public Throwable getException();
+
+ public String toString();
+}
diff -Nru pdftk-1.45/java/pdftk/org/bouncycastle/util/test/UncloseableOutputStream.java pdftk-2.01/java/pdftk/org/bouncycastle/util/test/UncloseableOutputStream.java
--- pdftk-1.45/java/pdftk/org/bouncycastle/util/test/UncloseableOutputStream.java 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/java/pdftk/org/bouncycastle/util/test/UncloseableOutputStream.java 2013-04-22 09:26:34.000000000 +0000
@@ -0,0 +1,23 @@
+package pdftk.org.bouncycastle.util.test;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class UncloseableOutputStream extends FilterOutputStream
+{
+ public UncloseableOutputStream(OutputStream s)
+ {
+ super(s);
+ }
+
+ public void close()
+ {
+ throw new RuntimeException("close() called on UncloseableOutputStream");
+ }
+
+ public void write(byte[] b, int off, int len) throws IOException
+ {
+ out.write(b, off, len);
+ }
+ }
Binary files /tmp/7F_3n52cds/pdftk-1.45/license_gpl_pdftk/readme.rtf and /tmp/MVjVXMDwVD/pdftk-2.01/license_gpl_pdftk/readme.rtf differ
diff -Nru pdftk-1.45/license_gpl_pdftk/readme.txt pdftk-2.01/license_gpl_pdftk/readme.txt
--- pdftk-1.45/license_gpl_pdftk/readme.txt 2012-12-07 13:26:32.000000000 +0000
+++ pdftk-2.01/license_gpl_pdftk/readme.txt 2013-05-23 10:33:20.000000000 +0000
@@ -1,5 +1,5 @@
PDFtk Server (pdftk) is not public domain software. It is licensed to the public under the GNU General Public License (GPL) as described in the license_gpl_pdftk folder. Pdftk uses third-party libraries which have their own licenses. The exact licensing terms can be found in the third_party folder and on the pdftk license web page: www.pdflabs.com/docs/pdftk-license/. Source code for pdftk and for these third-party libraries is available from this same page.
-If you plan to distribute pdftk as part of your own software, you will need a commercial license. The exception to this rule is if your software is licensed to the public under the GPL or another compatible license.
+If you want to distribute pdftk as part of your own software, you will need a commercial license. The exception to this rule is if your software is licensed to the public under the GPL or another compatible license.
Commercial licenses are available for pdftk. They include commercial-grade support and allow commercial redistribution. Please email sid.steward@pdflabs.com to learn more. And please include pdftk in your email subject. Thank you.
diff -Nru pdftk-1.45/pdftk/Makefile.Base pdftk-2.01/pdftk/Makefile.Base
--- pdftk-1.45/pdftk/Makefile.Base 2012-12-06 11:57:36.000000000 +0000
+++ pdftk-2.01/pdftk/Makefile.Base 2013-06-05 14:05:10.000000000 +0000
@@ -1,6 +1,6 @@
# -*- Mode: Makefile -*-
# Makefile.Base
-# Copyright 2003-2012 Sid Steward, Updated by Andre Gompel
+# Copyright (c) 2003-2013 Sid Steward, Updated by Andre Gompel
# This is part of pdftk
#
# Visit: www.pdftk.com for pdftk information and articles
@@ -14,20 +14,19 @@
# platform-specific makefiles, e.g.: Makefile.Debian
#
-export JAVALIBPATH= ../java
+export JAVALIBPATH= $(CURDIR)/../java
JAVALIB= $(JAVALIBPATH)/java_lib.o
-ifdef USE_LOCAL_LIBGCJ
-# passed on to next makefile
-export GCJ_LOCAL_LIB= gcj_local_lib.o
-export GCJ_LOCAL_LIB_FULL= $(JAVALIBPATH)/gcj_local_lib.o
+ifdef USE_LIBGCJ_SUPPLEMENT
+export LIBGCJ_SUPPLEMENT= libgcj_supplement
+export LIBGCJ_SUPPLEMENT_FULL_O= $(JAVALIBPATH)/$(LIBGCJ_SUPPLEMENT).o
endif
# this must already be set according to your platform Makefile;
# we're just appending to it, here
#
-CPPFLAGS+= -DPDFTK_VER=\"1.45\"
+CPPFLAGS+= -DPDFTK_VER=\"2.01\"
all : javalib pdftk
@@ -40,11 +39,11 @@
report.o : report.cc report.h pdftk.h $(JAVALIB)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(JAVALIBPATH) report.cc -c
-pdftk.o : pdftk.cc pdftk.h attachments.h report.h $(JAVALIB) $(GCJ_LOCAL_LIB_FULL)
+pdftk.o : pdftk.cc pdftk.h attachments.h report.h $(JAVALIB)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(JAVALIBPATH) pdftk.cc -c
-pdftk : pdftk.o attachments.o report.o $(JAVALIB) $(GCJ_LOCAL_LIB_FULL)
- $(CXX) $(CXXFLAGS) attachments.o report.o pdftk.o $(JAVALIB) $(GCJ_LOCAL_LIB_FULL) $(LDLIBS) -o pdftk
+pdftk : pdftk.o attachments.o report.o $(JAVALIB) $(LIBGCJ_SUPPLEMENT_FULL_O)
+ $(CXX) $(CXXFLAGS) attachments.o report.o pdftk.o $(JAVALIB) $(LIBGCJ_SUPPLEMENT_FULL_O) $(LDLIBS) -o pdftk
install:
/usr/bin/install pdftk /usr/local/bin
diff -Nru pdftk-1.45/pdftk/Makefile.Debian pdftk-2.01/pdftk/Makefile.Debian
--- pdftk-1.45/pdftk/Makefile.Debian 2012-12-06 11:58:44.000000000 +0000
+++ pdftk-2.01/pdftk/Makefile.Debian 2013-05-22 08:28:48.000000000 +0000
@@ -18,18 +18,11 @@
# Clean: make -f Makefile.Debian clean
#
-# this tries to compensate for objects missing from older versions of libgcj
-# it replaces them with local implementations
-#
-# set to 1 for gcc 3.4 and other, older versions of gcc (e.g., mingw 3.4.5)
-# comment out for gcc 4.4 and other, newer versions of gcc
-#
-#export USE_LOCAL_LIBGCJ= 1
-
# tools
# need direct path to libgcj for gcjh (starting in gcj 4.1.2 per Aurélien GÉRÔME)
TOOLPATH=
export VERSUFF=-4.6
+export CPP= $(TOOLPATH)cpp$(VERSUFF)
export CXX= $(TOOLPATH)g++$(VERSUFF)
export GCJ= $(TOOLPATH)gcj$(VERSUFF)
export GCJH= $(TOOLPATH)gcjh$(VERSUFF)
@@ -73,7 +66,7 @@
#
export CPPFLAGS= -DPATH_DELIM=0x2f -DASK_ABOUT_WARNINGS=false -DUNBLOCK_SIGNALS -fdollars-in-identifiers
export CXXFLAGS= -Wall -Wextra -Weffc++ -O2
-export GCJFLAGS= -Wall -Wextra -fsource=1.3 -O2
+export GCJFLAGS= -fsource=1.3 -O2
export GCJHFLAGS= -force
export LDLIBS= -lgcj
diff -Nru pdftk-1.45/pdftk/Makefile.FreeBSD pdftk-2.01/pdftk/Makefile.FreeBSD
--- pdftk-1.45/pdftk/Makefile.FreeBSD 2010-11-19 14:41:30.000000000 +0000
+++ pdftk-2.01/pdftk/Makefile.FreeBSD 2013-05-22 07:22:54.000000000 +0000
@@ -18,14 +18,6 @@
# Clean: make -f Makefile.FreeBSD clean
#
-# this tries to compensate for objects missing from older versions of libgcj
-# it replaces them with local implementations
-#
-# set to 1 for gcc 3.4 and other, older versions of gcc (e.g., mingw 3.4.5)
-# comment out for gcc 4.4 and other, newer versions of gcc
-#
-#export USE_LOCAL_LIBGCJ= 1
-
# tools
# need direct path to libgcj for gcjh (starting in gcj 4.1.2 per Aurélien GÉRÔME)
TOOLPATH=
diff -Nru pdftk-1.45/pdftk/Makefile.FreeBSD.Base.patch pdftk-2.01/pdftk/Makefile.FreeBSD.Base.patch
--- pdftk-1.45/pdftk/Makefile.FreeBSD.Base.patch 2010-11-19 14:45:02.000000000 +0000
+++ pdftk-2.01/pdftk/Makefile.FreeBSD.Base.patch 2013-05-22 07:23:20.000000000 +0000
@@ -18,12 +18,12 @@
+report.o : javalib report.cc report.h pdftk.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(JAVALIBPATH) report.cc -c
--pdftk.o : pdftk.cc pdftk.h attachments.h report.h $(JAVALIB) $(GCJ_LOCAL_LIB_FULL)
-+pdftk.o : javalib pdftk.cc pdftk.h attachments.h report.h $(GCJ_LOCAL_LIB_FULL)
+-pdftk.o : pdftk.cc pdftk.h attachments.h report.h $(JAVALIB)
++pdftk.o : javalib pdftk.cc pdftk.h attachments.h report.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(JAVALIBPATH) pdftk.cc -c
--pdftk : pdftk.o attachments.o report.o $(JAVALIB) $(GCJ_LOCAL_LIB_FULL)
-+pdftk : javalib pdftk.o attachments.o report.o $(GCJ_LOCAL_LIB_FULL)
- $(CXX) $(CXXFLAGS) attachments.o report.o pdftk.o $(JAVALIB) $(GCJ_LOCAL_LIB_FULL) $(LDLIBS) -o pdftk
+-pdftk : pdftk.o attachments.o report.o $(JAVALIB)
++pdftk : javalib pdftk.o attachments.o report.o
+ $(CXX) $(CXXFLAGS) attachments.o report.o pdftk.o $(JAVALIB) $(LDLIBS) -o pdftk
install:
diff -Nru pdftk-1.45/pdftk/Makefile.OSX-10.6 pdftk-2.01/pdftk/Makefile.OSX-10.6
--- pdftk-1.45/pdftk/Makefile.OSX-10.6 2010-09-30 13:41:52.000000000 +0000
+++ pdftk-2.01/pdftk/Makefile.OSX-10.6 2013-05-22 07:22:26.000000000 +0000
@@ -18,14 +18,6 @@
# Clean: make -f Makefile.Debian clean
#
-# this tries to compensate for objects missing from older versions of libgcj
-# it replaces them with local implementations
-#
-# set to 1 for gcc 3.4 and other, older versions of gcc (e.g., mingw 3.4.5)
-# comment out for gcc 4.4 and other, newer versions of gcc
-#
-#export USE_LOCAL_LIBGCJ= 1
-
# tools
# need direct path to libgcj for gcjh (starting in gcj 4.1.2 per Aurélien GÉRÔME)
TOOLPATH=/sw/lib/gcc4.5/bin/
diff -Nru pdftk-1.45/pdftk/Makefile.Redhat pdftk-2.01/pdftk/Makefile.Redhat
--- pdftk-1.45/pdftk/Makefile.Redhat 2010-09-16 11:23:20.000000000 +0000
+++ pdftk-2.01/pdftk/Makefile.Redhat 2013-05-22 07:22:20.000000000 +0000
@@ -19,14 +19,6 @@
# Clean: make -f Makefile.Debian clean
#
-# this tries to compensate for objects missing from older versions of libgcj
-# it replaces them with local implementations
-#
-# set to 1 for gcc 3.4 and other, older versions of gcc (e.g., mingw 3.4.5)
-# comment out for gcc 4.4 and other, newer versions of gcc
-#
-#export USE_LOCAL_LIBGCJ= 1
-
# tools
# need direct path to libgcj for gcjh (starting in gcj 4.1.2 per Aurélien GÉRÔME)
TOOLPATH=
diff -Nru pdftk-1.45/pdftk/Makefile.Slackware-13.1 pdftk-2.01/pdftk/Makefile.Slackware-13.1
--- pdftk-1.45/pdftk/Makefile.Slackware-13.1 2010-10-25 12:04:52.000000000 +0000
+++ pdftk-2.01/pdftk/Makefile.Slackware-13.1 2013-05-22 07:22:40.000000000 +0000
@@ -18,14 +18,6 @@
# Clean: make -f Makefile.Slackware-13.1 clean
#
-# this tries to compensate for objects missing from older versions of libgcj
-# it replaces them with local implementations
-#
-# set to 1 for gcc 3.4 and other, older versions of gcc (e.g., mingw 3.4.5)
-# comment out for gcc 4.4 and other, newer versions of gcc
-#
-#export USE_LOCAL_LIBGCJ= 1
-
# tools
# need direct path to libgcj for gcjh (starting in gcj 4.1.2 per Aurélien GÉRÔME)
TOOLPATH=
diff -Nru pdftk-1.45/pdftk/Makefile.Solaris pdftk-2.01/pdftk/Makefile.Solaris
--- pdftk-1.45/pdftk/Makefile.Solaris 2010-11-02 09:10:56.000000000 +0000
+++ pdftk-2.01/pdftk/Makefile.Solaris 2013-05-22 07:22:34.000000000 +0000
@@ -18,14 +18,6 @@
# Clean: make -f Makefile.Debian clean
#
-# this tries to compensate for objects missing from older versions of libgcj
-# it replaces them with local implementations
-#
-# set to 1 for gcc 3.4 and other, older versions of gcc (e.g., mingw 3.4.5)
-# comment out for gcc 4.4 and other, newer versions of gcc
-#
-#export USE_LOCAL_LIBGCJ= 1
-
# tools
# need direct path to libgcj for gcjh (starting in gcj 4.1.2 per Aurélien GÉRÔME)
TOOLPATH=
diff -Nru pdftk-1.45/pdftk/Makefile.Suse pdftk-2.01/pdftk/Makefile.Suse
--- pdftk-1.45/pdftk/Makefile.Suse 2010-11-04 09:09:10.000000000 +0000
+++ pdftk-2.01/pdftk/Makefile.Suse 2013-05-22 07:22:48.000000000 +0000
@@ -19,14 +19,6 @@
# Clean: make -f Makefile.Debian clean
#
-# this tries to compensate for objects missing from older versions of libgcj
-# it replaces them with local implementations
-#
-# set to 1 for gcc 3.4 and other, older versions of gcc (e.g., mingw 3.4.5)
-# comment out for gcc 4.4 and other, newer versions of gcc
-#
-#export USE_LOCAL_LIBGCJ= 1
-
# tools
# need direct path to libgcj for gcjh (starting in gcj 4.1.2 per Aurélien GÉRÔME)
TOOLPATH=
diff -Nru pdftk-1.45/pdftk/Makefile.Windows pdftk-2.01/pdftk/Makefile.Windows
--- pdftk-1.45/pdftk/Makefile.Windows 2010-10-19 11:17:46.000000000 +0000
+++ pdftk-2.01/pdftk/Makefile.Windows 1970-01-01 00:00:00.000000000 +0000
@@ -1,83 +0,0 @@
-# -*- Mode: Makefile -*-
-# Makefile.Debian
-# Copyright 2004, 2010 Sid Steward
-# This is part of pdftk.
-#
-# Visit: www.pdftk.com for pdftk information and articles
-# Permalink: http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/
-#
-# Please email Sid Steward with questions or bug reports.
-# Include "pdftk" in the subject line to ensure successful delivery:
-# sid.steward at pdflabs dot com
-
-# Brief Instructions
-#
-# Compile: make -f Makefile.Windows
-# Install (as root): make -f Makefile.Windows install
-# Uninstall: make -f Makefile.Windows uninstall
-# Clean: make -f Makefile.Windows clean
-#
-
-# this tries to compensate for objects missing from older versions of libgcj
-# it replaces them with local implementations
-#
-# set to 1 for gcc 3.4 and other, older versions of gcc (e.g., mingw 3.4.5)
-# comment out for gcc 4.4 and other, newer versions of gcc
-
-export USE_LOCAL_LIBGCJ= 1
-
-# tools
-# need direct path to libgcj for gcjh (starting in gcj 4.1.2 per Aurélien GÉRÔME)
-TOOLPATH=
-export VERSUFF=
-export CXX= $(TOOLPATH)g++$(VERSUFF)
-export GCJ= $(TOOLPATH)gcj$(VERSUFF)
-export GCJH= $(TOOLPATH)gcjh$(VERSUFF)
-export GJAR= $(TOOLPATH)jar$(VERSUFF)
-#export LIBGCJ= /usr/share/java/libgcj$(VERSUFF).jar
-export LIBGCJ= /c/mingw-3.4.5/share/java/libgcj-3.4.5.jar
-export AR= ar
-export RM= rm
-export ARFLAGS= rs
-export RMFLAGS= -vf
-
-# pdftk compiler flags; 0x2f is a forward slash; 0x5c is a backslash
-# if you want pdftk to ask before overwriting a file, set
-# ASK_ABOUT_WARNINGS to true; otherwise: false; override this default
-# with the dont_ask or do_ask command-line options
-#
-# drop CXXFLAG -O3 due to template inlining causing:
-# "error: mixing C++ and Java catches in a single translation unit" per Andrew Haley;
-# fix added for gcc-4.3; this problem might be fixed in 4.4
-#
-# GCJFLAG -O3 causes pdftk to segfault (during a cat operation) when compiled on sarge using gcc 3.4.4
-# per Johann Felix Soden:
-# In gcc 4.3 "-O3" gives an error. This is fixed in PR C++/39380 which is at least in debian's gcc 4.4.1-4
-#
-# GCJFLAG -fsource=1.3 identifies the version of the java source
-#
-# when building/using a shared itext library:
-# CXXFLAGS: -fpic (or-fPIC)
-# GCJFLAGS: -Wl,-Bsymbolic -fpic (or -fPIC) -Wl,-rpath,/usr/lib/gcj
-# stock pdftk links statically against its own, modified itext library
-#
-# -findirect-dispatch
-# introduced in gcj 4:
-# "Using that option causes GCJ to generate native code for classes and methods that follow the precise same binary compatibility rules as described in the Java Language Specification."
-# http://lwn.net/Articles/130796/
-# omitted because it caused linking errors using gcc 4.4; it also seems to make a larger binary
-#
-# -Wl,--as-needed
-# see: http://www.gentoo.org/proj/en/qa/asneeded.xml
-# only effects libraries following option on the command line
-#
-export CPPFLAGS= -DPATH_DELIM=0x5c -DASK_ABOUT_WARNINGS=false -fdollars-in-identifiers
-export CXXFLAGS= -Wall -Wextra -Weffc++ -O2
-export GCJFLAGS= -O2
-# added -nostdlib to track dependencies
-#export LDLIBS= -lgcj -lws2_32 -liconv
-export LDLIBS= c:/mingw-3.4.5/lib/crt2.o -nostdlib -lgcj -lws2_32 -liconv -luser32 -ladvapi32 -lmingw32 -lstdc++ -lgcc -lmoldname -lmingwex -lkernel32 -lmsvcrt
-
-
-
-include Makefile.Base
diff -Nru pdftk-1.45/pdftk/Makefile.Windows.345 pdftk-2.01/pdftk/Makefile.Windows.345
--- pdftk-1.45/pdftk/Makefile.Windows.345 2012-12-06 11:58:32.000000000 +0000
+++ pdftk-2.01/pdftk/Makefile.Windows.345 2013-06-06 07:21:36.000000000 +0000
@@ -1,6 +1,6 @@
# -*- Mode: Makefile -*-
# Makefile.Debian
-# Copyright (c) 2004-2012 Sid Steward
+# Copyright (c) 2004-2013 Sid Steward
# This is part of pdftk.
#
# Visit: www.pdftk.com for pdftk information and articles
@@ -18,24 +18,25 @@
# Clean: make -f Makefile.Windows clean
#
-# this tries to compensate for objects missing from older versions of libgcj
-# it replaces them with local implementations
-#
-# set to 1 for gcc 3.4 and other, older versions of gcc (e.g., mingw 3.4.5)
-# comment out for gcc 4.4 and other, newer versions of gcc
-
-export USE_LOCAL_LIBGCJ= 1
+export USE_LIBGCJ_SUPPLEMENT= 1
# tools
# need direct path to libgcj for gcjh (starting in gcj 4.1.2 per Aurélien GÉRÔME)
TOOLPATH= /c/mingw-3.4.5/bin/
export VERSUFF=
+export CPP= $(TOOLPATH)cpp$(VERSUFF)
export CXX= $(TOOLPATH)g++$(VERSUFF)
export GCJ= $(TOOLPATH)gcj$(VERSUFF)
export GCJH= $(TOOLPATH)gcjh$(VERSUFF)
export GJAR= $(TOOLPATH)jar$(VERSUFF)
-#export LIBGCJ= /usr/share/java/libgcj$(VERSUFF).jar
+
+ifdef USE_LIBGCJ_SUPPLEMENT
+# using supplemented libgcj-3.4.5.jar; see ../java/ for supplement source
+export LIBGCJ= /c/mingw-3.4.5/share/java/libgcj-3.4.5-supp-1.jar
+else
export LIBGCJ= /c/mingw-3.4.5/share/java/libgcj-3.4.5.jar
+endif
+
export AR= ar
export RM= rm
export ARFLAGS= rs
@@ -71,15 +72,17 @@
# see: http://www.gentoo.org/proj/en/qa/asneeded.xml
# only effects libraries following option on the command line
#
-export CPPFLAGS= -DPATH_DELIM=0x5c -DASK_ABOUT_WARNINGS=false -fdollars-in-identifiers
-# removed -Weffc++ from CXXFLAGS because it was cluttering output with warnings re generated code and STL
-export CXXFLAGS= -Wall -Wextra -O2
+
+export CPPFLAGS= -DPATH_DELIM=0x5c -DASK_ABOUT_WARNINGS=false \
+ -D_UNICODE -DUNICODE -D__USE_MINGW_ACCESS
+
+export CXXFLAGS= -Wall -Wextra -O2 -fdollars-in-identifiers -mthreads
+
export GCJFLAGS= -O2
+
# added -nostdlib to track dependencies
# added -lshell32 for wide-char handling in pdftk.cc
#export LDLIBS= -lgcj -lws2_32 -liconv
export LDLIBS= c:/mingw-3.4.5/lib/crt2.o -nostdlib -lgcj -lws2_32 -liconv -luser32 -ladvapi32 -lmingw32 -lstdc++ -lgcc -lmoldname -lmingwex -lkernel32 -lmsvcrt -lshell32
-
-
include Makefile.Base
diff -Nru pdftk-1.45/pdftk/attachments.cc pdftk-2.01/pdftk/attachments.cc
--- pdftk-1.45/pdftk/attachments.cc 2010-11-05 01:38:26.000000000 +0000
+++ pdftk-2.01/pdftk/attachments.cc 2013-04-26 11:54:34.000000000 +0000
@@ -54,31 +54,30 @@
#include
-#include "com/lowagie/text/Document.h"
-#include "com/lowagie/text/Rectangle.h"
-#include "com/lowagie/text/pdf/PdfName.h"
-#include "com/lowagie/text/pdf/PdfString.h"
-#include "com/lowagie/text/pdf/PdfNumber.h"
-#include "com/lowagie/text/pdf/PdfArray.h"
-#include "com/lowagie/text/pdf/PdfDictionary.h"
-#include "com/lowagie/text/pdf/PdfOutline.h"
-#include "com/lowagie/text/pdf/PdfCopy.h"
-#include "com/lowagie/text/pdf/PdfReader.h"
-#include "com/lowagie/text/pdf/PdfImportedPage.h"
-#include "com/lowagie/text/pdf/PdfWriter.h"
-#include "com/lowagie/text/pdf/PdfStamperImp.h"
-#include "com/lowagie/text/pdf/PdfEncryptor.h"
-#include "com/lowagie/text/pdf/PdfNameTree.h"
-#include "com/lowagie/text/pdf/FdfReader.h"
-#include "com/lowagie/text/pdf/AcroFields.h"
-#include "com/lowagie/text/pdf/PdfIndirectReference.h"
-#include "com/lowagie/text/pdf/PdfIndirectObject.h"
-#include "com/lowagie/text/pdf/PdfFileSpecification.h"
-
-#include "com/lowagie/text/pdf/PdfAnnotation.h"
-#include "com/lowagie/text/pdf/PRStream.h"
-#include "com/lowagie/text/pdf/BaseFont.h"
-#include "com/lowagie/text/pdf/PdfEncodings.h"
+#include "pdftk/com/lowagie/text/Document.h"
+#include "pdftk/com/lowagie/text/Rectangle.h"
+#include "pdftk/com/lowagie/text/pdf/PdfName.h"
+#include "pdftk/com/lowagie/text/pdf/PdfString.h"
+#include "pdftk/com/lowagie/text/pdf/PdfNumber.h"
+#include "pdftk/com/lowagie/text/pdf/PdfArray.h"
+#include "pdftk/com/lowagie/text/pdf/PdfDictionary.h"
+#include "pdftk/com/lowagie/text/pdf/PdfOutline.h"
+#include "pdftk/com/lowagie/text/pdf/PdfCopy.h"
+#include "pdftk/com/lowagie/text/pdf/PdfReader.h"
+#include "pdftk/com/lowagie/text/pdf/PdfImportedPage.h"
+#include "pdftk/com/lowagie/text/pdf/PdfWriter.h"
+#include "pdftk/com/lowagie/text/pdf/PdfStamperImp.h"
+#include "pdftk/com/lowagie/text/pdf/PdfNameTree.h"
+#include "pdftk/com/lowagie/text/pdf/FdfReader.h"
+#include "pdftk/com/lowagie/text/pdf/AcroFields.h"
+#include "pdftk/com/lowagie/text/pdf/PdfIndirectReference.h"
+#include "pdftk/com/lowagie/text/pdf/PdfIndirectObject.h"
+#include "pdftk/com/lowagie/text/pdf/PdfFileSpecification.h"
+
+#include "pdftk/com/lowagie/text/pdf/PdfAnnotation.h"
+#include "pdftk/com/lowagie/text/pdf/PRStream.h"
+#include "pdftk/com/lowagie/text/pdf/BaseFont.h"
+#include "pdftk/com/lowagie/text/pdf/PdfEncodings.h"
#include
@@ -91,8 +90,8 @@
}
namespace itext {
- using namespace com::lowagie::text;
- using namespace com::lowagie::text::pdf;
+ using namespace pdftk::com::lowagie::text;
+ using namespace pdftk::com::lowagie::text::pdf;
}
#include "pdftk.h"
diff -Nru pdftk-1.45/pdftk/mingw-unicode.c pdftk-2.01/pdftk/mingw-unicode.c
--- pdftk-1.45/pdftk/mingw-unicode.c 1970-01-01 00:00:00.000000000 +0000
+++ pdftk-2.01/pdftk/mingw-unicode.c 2012-12-20 09:40:42.000000000 +0000
@@ -0,0 +1,53 @@
+// This is for the MinGW compiler which does not support wmain.
+// It is a wrapper for _tmain when _UNICODE is defined (wmain).
+//
+// !! Do not compile this file, but instead include it right before your _tmain function like:
+// #include "mingw-unicode.c"
+// int _tmain(int argc, _TCHAR *argv[]) {
+//
+// If you wish to have enpv in your main, then define the following before including this file:
+// #define MAIN_USE_ENVP
+//
+// This wrapper adds ~300 bytes to the program and negligible overhead
+
+#undef _tmain
+#ifdef _UNICODE
+#define _tmain wmain
+#else
+#define _tmain main
+#endif
+
+#if defined(__GNUC__) && defined(_UNICODE)
+
+#ifndef __MSVCRT__
+#error Unicode main function requires linking to MSVCRT
+#endif
+
+#include
+#include
+
+extern int _CRT_glob;
+extern
+#ifdef __cplusplus
+"C"
+#endif
+void __wgetmainargs(int*,wchar_t***,wchar_t***,int,int*);
+
+#ifdef MAIN_USE_ENVP
+int wmain(int argc, wchar_t *argv[], wchar_t *envp[]);
+#else
+int wmain(int argc, wchar_t *argv[]);
+#endif
+
+int main() {
+ wchar_t **enpv, **argv;
+ int argc, si = 0;
+ __wgetmainargs(&argc, &argv, &enpv, _CRT_glob, &si); // this also creates the global variable __wargv
+#ifdef MAIN_USE_ENVP
+ return wmain(argc, argv, enpv);
+#else
+ return wmain(argc, argv);
+#endif
+}
+
+#endif //defined(__GNUC__) && defined(_UNICODE)
diff -Nru pdftk-1.45/pdftk/pdftk.cc pdftk-2.01/pdftk/pdftk.cc
--- pdftk-1.45/pdftk/pdftk.cc 2012-12-06 11:58:12.000000000 +0000
+++ pdftk-2.01/pdftk/pdftk.cc 2013-06-04 11:27:04.000000000 +0000
@@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 2; c-basic-offset: 2 -*- */
/*
pdftk, the PDF Toolkit
- Copyright (c) 2003-2012 Sid Steward
+ Copyright (c) 2003-2013 Sid Steward
This program is free software; you can redistribute it and/or modify
@@ -45,6 +45,9 @@
#include // for access()
+#include
+#include
+
#include
#include
#include
@@ -58,32 +61,35 @@
#include
#include
-#include "com/lowagie/text/Document.h"
-#include "com/lowagie/text/Rectangle.h"
-#include "com/lowagie/text/pdf/PdfName.h"
-#include "com/lowagie/text/pdf/PdfString.h"
-#include "com/lowagie/text/pdf/PdfNumber.h"
-#include "com/lowagie/text/pdf/PdfArray.h"
-#include "com/lowagie/text/pdf/PdfDictionary.h"
-#include "com/lowagie/text/pdf/PdfStream.h" // for barcode_burst
-#include "com/lowagie/text/pdf/PdfOutline.h"
-#include "com/lowagie/text/pdf/PdfCopy.h"
-#include "com/lowagie/text/pdf/PdfReader.h"
-#include "com/lowagie/text/pdf/PdfImportedPage.h"
-#include "com/lowagie/text/pdf/PdfWriter.h"
-#include "com/lowagie/text/pdf/PdfStamperImp.h"
-#include "com/lowagie/text/pdf/PdfEncryptor.h"
-#include "com/lowagie/text/pdf/PdfNameTree.h"
-#include "com/lowagie/text/pdf/FdfReader.h"
-#include "com/lowagie/text/pdf/FdfWriter.h"
-#include "com/lowagie/text/pdf/XfdfReader.h"
-#include "com/lowagie/text/pdf/AcroFields.h"
-#include "com/lowagie/text/pdf/PdfIndirectReference.h"
-#include "com/lowagie/text/pdf/PdfIndirectObject.h"
-#include "com/lowagie/text/pdf/PdfFileSpecification.h"
-#include "com/lowagie/text/pdf/PdfBoolean.h"
+#include "pdftk/com/lowagie/text/Document.h"
+#include "pdftk/com/lowagie/text/Rectangle.h"
+#include "pdftk/com/lowagie/text/pdf/PdfName.h"
+#include "pdftk/com/lowagie/text/pdf/PdfString.h"
+#include "pdftk/com/lowagie/text/pdf/PdfNumber.h"
+#include "pdftk/com/lowagie/text/pdf/PdfArray.h"
+#include "pdftk/com/lowagie/text/pdf/PdfDictionary.h"
+#include "pdftk/com/lowagie/text/pdf/PdfStream.h" // for barcode_burst
+#include "pdftk/com/lowagie/text/pdf/PdfOutline.h"
+#include "pdftk/com/lowagie/text/pdf/PdfCopy.h"
+#include "pdftk/com/lowagie/text/pdf/PdfReader.h"
+#include "pdftk/com/lowagie/text/pdf/PdfImportedPage.h"
+#include "pdftk/com/lowagie/text/pdf/PdfWriter.h"
+#include "pdftk/com/lowagie/text/pdf/PdfStamperImp.h"
+#include "pdftk/com/lowagie/text/pdf/PdfNameTree.h"
+#include "pdftk/com/lowagie/text/pdf/PdfAcroForm.h"
+#include "pdftk/com/lowagie/text/pdf/FdfReader.h"
+#include "pdftk/com/lowagie/text/pdf/FdfWriter.h"
+#include "pdftk/com/lowagie/text/pdf/XfdfReader.h"
+#include "pdftk/com/lowagie/text/pdf/AcroFields.h"
+#include "pdftk/com/lowagie/text/pdf/PdfIndirectReference.h"
+#include "pdftk/com/lowagie/text/pdf/PdfIndirectObject.h"
+#include "pdftk/com/lowagie/text/pdf/PdfFileSpecification.h"
+#include "pdftk/com/lowagie/text/pdf/PdfBoolean.h"
+#include "pdftk/com/lowagie/text/pdf/PdfDestination.h"
+
+#include "pdftk/com/lowagie/text/pdf/PdfAnnotation.h"
-#include "com/lowagie/text/pdf/RandomAccessFileOrArray.h" // for InputStreamToArray()
+#include "pdftk/com/lowagie/text/pdf/RandomAccessFileOrArray.h" // for InputStreamToArray()
using namespace std;
@@ -94,8 +100,8 @@
}
namespace itext {
- using namespace com::lowagie::text;
- using namespace com::lowagie::text::pdf;
+ using namespace pdftk::com::lowagie::text;
+ using namespace pdftk::com::lowagie::text::pdf;
}
#ifdef WIN32
@@ -157,6 +163,8 @@
copy_argv_as_utf8( string& ss, char** argv, int ii )
{
#ifdef WIN32
+ ss= argv[ii]; // this works with our new, WIN32-specific wide argv
+ /*
// Windows-only logic; convert wide-char unicode to UTF-8
// zero-based index, just as you'd use for argv
@@ -182,10 +190,9 @@
LocalFree( szWideArgv );
}
-
+ */
#else // argv already UTF-8
ss= argv[ii];
-
#endif
}
@@ -235,7 +242,7 @@
// store in this java object so the gc can trace it
g_dont_collect_p->addElement( reader );
- input_pdf_p->m_authorized_b= ( !reader->encrypted || reader->passwordIsOwner );
+ input_pdf_p->m_authorized_b= ( !reader->encrypted || reader->ownerPasswordUsed );
if( !input_pdf_p->m_authorized_b ) {
open_success_b= false;
}
@@ -244,6 +251,13 @@
if( ioe_p->getMessage()->equals( JvNewStringUTF( "Bad password" ) ) ) {
input_pdf_p->m_authorized_b= false;
}
+ else if( ioe_p->getMessage()->indexOf( JvNewStringUTF( "not found" ) )!= -1 ) {
+ cerr << "Error: Unable to find file." << endl;
+ }
+ else { // unexpected error
+ cerr << "Error: Unexpected Exception in open_reader()" << endl;
+ ioe_p->printStackTrace(); // debug
+ }
open_success_b= false;
}
catch( java::lang::Throwable* t_p ) { // unexpected error
@@ -323,63 +337,6 @@
return ii;
}
-/*
-static bool
-detect_rotate_arg( char cc,
- TK_Session::PageRotate& page_rotate,
- TK_Session::PageRotateAbsolute& page_rotate_absolute )
-{
- bool ret_val_b= false;
-
- switch( cc ) {
- case 'N':
- page_rotate= TK_Session::NORTH; // rotate 0
- page_rotate_absolute= true;
- ret_val_b= true;
- break;
-
- case 'E':
- page_rotate= TK_Session::EAST; // rotate 90
- page_rotate_absolute= true;
- ret_val_b= true;
- break;
-
- case 'S':
- page_rotate= TK_Session::SOUTH; // rotate 180
- page_rotate_absolute= true;
- ret_val_b= true;
- break;
-
- case 'W':
- page_rotate= TK_Session::WEST; // rotate 270
- page_rotate_absolute= true;
- ret_val_b= true;
- break;
-
- case 'L':
- page_rotate_absolute= false;
- page_rotate= TK_Session::WEST; // rotate -90
- ret_val_b= true;
- break;
-
- case 'R':
- page_rotate_absolute= false;
- page_rotate= TK_Session::EAST; // rotate +90
- ret_val_b= true;
- break;
-
- case 'D':
- page_rotate_absolute= false;
- page_rotate= TK_Session::SOUTH; // rotate 180
- ret_val_b= true;
- break;
- }
-
- return ret_val_b;
-}
-*/
-
-
TK_Session::keyword
TK_Session::is_keyword( char* ss, int* keyword_len_p )
{
@@ -424,6 +381,9 @@
else if( strcmp( ss_copy, "dump_data_fields_utf8" )== 0 ) {
return dump_data_fields_utf8_k;
}
+ else if( strcmp( ss_copy, "dump_data_annots" )== 0 ) {
+ return dump_data_annots_k;
+ }
else if( strcmp( ss_copy, "generate_fdf" )== 0 ||
strcmp( ss_copy, "fdfgen" )== 0 ||
strcmp( ss_copy, "fdfdump" )== 0 ||
@@ -472,6 +432,9 @@
else if( strcmp( ss_copy, "stamp" )== 0 ) {
return stamp_k;
}
+ else if( strcmp( ss_copy, "rotate" )== 0 ) {
+ return rotate_k;
+ }
// cat range keywords
else if( strncmp( ss_copy, "end", 3 )== 0 ) { // note: strncmp
@@ -573,6 +536,9 @@
else if( strcmp( ss_copy, "flatten" )== 0 ) {
return flatten_k;
}
+ else if( strcmp( ss_copy, "need_appearances" )== 0 ) {
+ return need_appearances_k;
+ }
else if( strcmp( ss_copy, "drop_xfa" )== 0 ) {
return drop_xfa_k;
}
@@ -633,6 +599,7 @@
( m_operation== dump_data_k ||
m_operation== dump_data_fields_k ||
+ m_operation== dump_data_annots_k ||
m_operation== generate_fdf_k ||
m_authorized_b ) &&
@@ -657,6 +624,7 @@
#endif
m_operation== dump_data_k ||
m_operation== dump_data_fields_k ||
+ m_operation== dump_data_annots_k ||
m_operation== generate_fdf_k ||
m_operation== unpack_files_k ||
!m_output_filename.empty() ) );
@@ -733,6 +701,9 @@
case dump_data_fields_k:
cout << " dump_data_fields - Report form field data on a single, input PDF." << endl;
break;
+ case dump_data_annots_k:
+ cout << " dump_data_annots - Report annotation data on a single, input PDF." << endl;
+ break;
case generate_fdf_k:
cout << " generate_fdf - Generate a dummy FDF file from a PDF." << endl;
break;
@@ -806,7 +777,7 @@
cout << endl;
{
- using com::lowagie::text::pdf::PdfWriter;
+ using itext::PdfWriter;
if( m_output_user_pw.empty() )
cout << " No user password given." << endl;
@@ -917,6 +888,9 @@
case flatten_k:
m_output_flatten_b= true;
break;
+ case need_appearances_k:
+ m_output_need_appearances_b= true;
+ break;
case drop_xfa_k:
m_output_drop_xfa_b= true;
break;
@@ -985,9 +959,11 @@
m_output_uncompress_b( false ),
m_output_compress_b( false ),
m_output_flatten_b( false ),
+ m_output_need_appearances_b( false ),
m_output_drop_xfa_b( false ),
m_output_keep_first_id_b( false ),
m_output_keep_final_id_b( false ),
+ m_cat_full_pdfs_b( true ),
m_output_encryption_strength( none_enc )
{
TK_Session::ArgState arg_state = input_files_e;
@@ -1081,6 +1057,14 @@
m_output_utf8_b= true;
arg_state= output_e;
}
+ else if( arg_keyword== dump_data_k ) {
+ m_operation= dump_data_k;
+ arg_state= output_e;
+ }
+ else if( arg_keyword== dump_data_annots_k ) {
+ m_operation= dump_data_annots_k;
+ arg_state= output_e;
+ }
else if( arg_keyword== generate_fdf_k ) {
m_operation= generate_fdf_k;
m_output_utf8_b= true;
@@ -1135,6 +1119,10 @@
m_multistamp_b= true;
arg_state= stamp_filename_e;
}
+ else if( arg_keyword== rotate_k ) {
+ m_operation= filter_k;
+ arg_state= page_seq_e; // collect page sequeces
+ }
else if( arg_keyword== output_k ) { // we reached the output section
arg_state= output_filename_e;
}
@@ -1385,6 +1373,7 @@
// parse digits
PageNumber page_num_beg= 0;
+ bool page_num_beg_out_of_range_b= false;
for( ; argv[ii][jj] && isdigit( argv[ii][jj] ); ++jj ) { // read any digits
page_num_beg= page_num_beg* 10+ argv[ii][jj]- '0';
}
@@ -1412,7 +1401,17 @@
break;
}
- if( reverse_b )
+ if( m_input_pdf[range_pdf_index].m_num_pages< page_num_beg ) {
+ // error: page number out of range
+ cerr << "Error: Range start page number exceeds size of PDF" << endl;
+ cerr << " here: " << argv[ii] << endl;
+ cerr << " input PDF has: " << m_input_pdf[range_pdf_index].m_num_pages << " pages." << endl;
+ cerr << " Exiting." << endl;
+ fail_b= true;
+ break;
+ }
+
+ if( reverse_b ) // above test ensures good value here
page_num_beg= m_input_pdf[range_pdf_index].m_num_pages- page_num_beg+ 1;
////
@@ -1457,8 +1456,18 @@
break;
}
- if( reverse_b )
+ if( m_input_pdf[range_pdf_index].m_num_pages< page_num_end ) {
+ // error: page number out of range
+ cerr << "Error: Range end page number exceeds size of PDF" << endl;
+ cerr << " input PDF has: " << m_input_pdf[range_pdf_index].m_num_pages << " pages." << endl;
+ cerr << " Exiting." << endl;
+ fail_b= true;
+ break;
+ }
+
+ if( reverse_b ) // above test ensures good value here
page_num_end= m_input_pdf[range_pdf_index].m_num_pages- page_num_end+ 1;
+
}
// trailing keywords (excluding "end" which should have been handled above)
@@ -1510,6 +1519,8 @@
cerr << " " << argv_ss /*(argv[ii]+ jj)*/ << endl;
cerr << " Exiting." << endl;
cerr << " Acceptable keywords, for example: \"even\" or \"odd\"." << endl;
+ cerr << " To rotate pages, use: \"north\" \"south\" \"east\"" << endl;
+ cerr << " \"west\" \"left\" \"right\" or \"down\"" << endl;
fail_b= true;
break;
}
@@ -1524,6 +1535,15 @@
page_num_beg= 1;
page_num_end= m_input_pdf[range_pdf_index].m_num_pages;
}
+ else if( page_num_beg== 0 || page_num_end== 0 ) { // error
+ cerr << "Error: Input page numbers include 0 (zero)" << endl;
+ cerr << " The first PDF page is 1 (one)" << endl;
+ cerr << " Exiting." << endl;
+ fail_b= true;
+ break;
+ }
+ else // the user specified select pages
+ m_cat_full_pdfs_b= false;
vector< PageRef > temp_page_seq;
bool reverse_sequence_b= ( page_num_end< page_num_beg );
@@ -1800,9 +1820,9 @@
}
if( ( m_operation== cat_k ||
- m_operation== shuffle_k ) &&
- m_page_seq.empty() )
- { // combining pages, but no sequences given; merge all input PDFs in order
+ m_operation== shuffle_k ) )
+ if( m_page_seq.empty() ) {
+ // combining pages, but no sequences given; merge all input PDFs in order
for( InputPdfIndex ii= 0; ii< m_input_pdf.size(); ++ii ) {
InputPdf& input_pdf= m_input_pdf[ii];
@@ -1814,6 +1834,9 @@
m_page_seq.push_back( temp_page_seq );
}
}
+ else { // page ranges or docs (e.g. A B A) were given
+ m_cat_full_pdfs_b= false; // TODO: handle cat A B A case for bookmarks
+ }
if( m_output_filename.empty() ) {
copy_argv_as_utf8( m_output_filename, argv, ii );
@@ -1876,7 +1899,7 @@
string argv_ss;
copy_argv_as_utf8( argv_ss, argv, ii );
- if( argv_ss!= m_output_user_pw ) {
+ if( argv_ss== "PROMPT" || argv_ss!= m_output_user_pw ) {
m_output_owner_pw= argv_ss;
}
@@ -1914,7 +1937,7 @@
string argv_ss;
copy_argv_as_utf8( argv_ss, argv, ii );
- if( m_output_owner_pw!= argv_ss ) {
+ if( argv_ss== "PROMPT" || m_output_owner_pw!= argv_ss ) {
m_output_user_pw= argv_ss;
}
else { // error: identical user and owner password
@@ -1947,7 +1970,7 @@
break;
case output_user_perms_e: {
- using com::lowagie::text::pdf::PdfWriter;
+ using itext::PdfWriter;
// we may be given any number of permission arguments,
// so keep an eye out for other, state-altering keywords
@@ -2226,6 +2249,22 @@
}
}
+static void
+apply_rotation_to_page( itext::PdfReader* reader_p, TK_Session::PageNumber page_num, int rotation, bool absolute ) {
+ // DF rotate
+ itext::PdfDictionary* page_p= reader_p->getPageN( page_num );
+ if( !absolute ) {
+ rotation= reader_p->getPageRotation( page_num )+ rotation;
+ }
+ rotation= rotation % 360;
+ page_p->remove( itext::PdfName::ROTATE );
+ if( rotation!= TK_Session::NORTH ) { // default rotation
+ page_p->put( itext::PdfName::ROTATE,
+ new itext::PdfNumber( (jint)rotation ) );
+ }
+}
+
+
int
TK_Session::create_output_page( itext::PdfCopy* writer_p, PageRef page_ref, int output_page_count )
{
@@ -2264,17 +2303,7 @@
}
// DF rotate
- itext::PdfDictionary* input_dict_page_p= input_reader_p->getPageN( page_ref.m_page_num );
- int page_rotation= page_ref.m_page_rot;
- if( !page_ref.m_page_abs ) {
- page_rotation= input_reader_p->getPageRotation( page_ref.m_page_num )+ page_ref.m_page_rot;
- }
- page_rotation= page_rotation % 360;
- input_dict_page_p->remove( itext::PdfName::ROTATE );
- if( page_rotation!= NORTH ) { // default rotation
- input_dict_page_p->put( itext::PdfName::ROTATE,
- new itext::PdfNumber( (jint)page_rotation ) );
- }
+ apply_rotation_to_page( input_reader_p, page_ref.m_page_num, page_ref.m_page_rot, page_ref.m_page_abs );
//
itext::PdfImportedPage* page_p=
@@ -2295,6 +2324,29 @@
return ret_val;
}
+static jchar GetPdfVersionChar( itext::PdfName* version_p ) {
+ jchar version_cc= itext::PdfWriter::VERSION_1_2; // default
+
+ if( version_p->equals( itext::PdfName::VERSION_1_4 ) )
+ version_cc= itext::PdfWriter::VERSION_1_4;
+ else if( version_p->equals( itext::PdfName::VERSION_1_5 ) )
+ version_cc= itext::PdfWriter::VERSION_1_5;
+ else if( version_p->equals( itext::PdfName::VERSION_1_6 ) )
+ version_cc= itext::PdfWriter::VERSION_1_6;
+ else if( version_p->equals( itext::PdfName::VERSION_1_7 ) )
+ version_cc= itext::PdfWriter::VERSION_1_7;
+ else if( version_p->equals( itext::PdfName::VERSION_1_0 ) )
+ version_cc= itext::PdfWriter::VERSION_1_0;
+ else if( version_p->equals( itext::PdfName::VERSION_1_1 ) )
+ version_cc= itext::PdfWriter::VERSION_1_1;
+ else if( version_p->equals( itext::PdfName::VERSION_1_2 ) )
+ version_cc= itext::PdfWriter::VERSION_1_2;
+ else if( version_p->equals( itext::PdfName::VERSION_1_3 ) )
+ version_cc= itext::PdfWriter::VERSION_1_3;
+
+ return version_cc;
+}
+
int
TK_Session::create_output()
{
@@ -2323,7 +2375,6 @@
}
string creator= "pdftk "+ string(PDFTK_VER)+ " - www.pdftk.com";
- //string creator= "pdftk - www.pdftk.com";
java::String* jv_creator_p=
JvNewStringUTF( creator.c_str() );
@@ -2360,6 +2411,10 @@
}
itext::PdfCopy* writer_p= new itext::PdfCopy( output_doc_p, ofs_p );
+ // update to suit any features that we add, e.g. encryption;
+ jchar max_version_cc= itext::PdfWriter::VERSION_1_2;
+
+ //
output_doc_p->addCreator( jv_creator_p );
// un/compress output streams?
@@ -2378,14 +2433,18 @@
!m_output_user_pw.empty() )
{
// if no stregth is given, default to 128 bit,
- // (which is incompatible w/ Acrobat 4)
- bool bit128_b=
+ jboolean bit128_b=
( m_output_encryption_strength!= bits40_enc );
writer_p->setEncryption( output_user_pw_p,
output_owner_pw_p,
m_output_user_perms,
bit128_b );
+
+ if( bit128_b )
+ max_version_cc= itext::PdfWriter::VERSION_1_4;
+ else // 1.1 probably okay, here
+ max_version_cc= itext::PdfWriter::VERSION_1_3;
}
// copy file ID?
@@ -2407,18 +2466,120 @@
}
}
+ // set output PDF version to the max PDF ver of all the input PDFs;
+ // also find the maximum extension levels, if present -- this can
+ // only be added /after/ opening the document;
+ //
+ // collected extensions information; uses PdfName::hashCode() for key
+ map< jint, itext::PdfName* > ext_developers;
+ map< jint, itext::PdfName* > ext_base_versions;
+ map< jint, jint > ext_levels;
+ for( vector< InputPdf >::const_iterator it= m_input_pdf.begin();
+ it!= m_input_pdf.end(); ++it )
+ {
+ itext::PdfReader* reader_p= it->m_readers.begin()->second;
+
+ ////
+ // PDF version number
+
+ // version in header
+ if( max_version_cc< reader_p->getPdfVersion() )
+ max_version_cc= reader_p->getPdfVersion();
+
+ // version override in catalog; used only if greater than header version, per PDF spec;
+ itext::PdfDictionary* catalog_p= reader_p->getCatalog();
+ if( catalog_p->contains( itext::PdfName::VERSION ) ) {
+
+ itext::PdfName* version_p= (itext::PdfName*)
+ reader_p->getPdfObject( catalog_p->get( itext::PdfName::VERSION ) );
+ jchar version_cc= GetPdfVersionChar( version_p );
+
+ if( max_version_cc< version_cc )
+ max_version_cc= version_cc;
+ }
+
+ ////
+ // PDF extensions
+
+ if( catalog_p->contains( itext::PdfName::EXTENSIONS ) ) {
+ itext::PdfDictionary* extensions_p= (itext::PdfDictionary*)
+ reader_p->getPdfObject( catalog_p->get( itext::PdfName::EXTENSIONS ) );
+ if( extensions_p && extensions_p->isDictionary() ) {
+
+ // iterate over developers
+ java::Set* keys_p= extensions_p->getKeys();
+ java::Iterator* kit= keys_p->iterator();
+ while( kit->hasNext() ) {
+ itext::PdfName* developer_p= (itext::PdfName*)
+ reader_p->getPdfObject( (itext::PdfObject*)kit->next() );
+ ext_developers[ developer_p->hashCode() ]= developer_p;
+
+ itext::PdfDictionary* dev_exts_p= (itext::PdfDictionary*)
+ reader_p->getPdfObject( extensions_p->get( developer_p ) );
+ if( dev_exts_p && dev_exts_p->isDictionary() ) {
+
+ if( dev_exts_p->contains( itext::PdfName::BASEVERSION ) &&
+ dev_exts_p->contains( itext::PdfName::EXTENSIONLEVEL ) )
+ {
+ // use the greater base version or the greater extension level
+
+ itext::PdfName* base_version_p= (itext::PdfName*)
+ reader_p->getPdfObject( dev_exts_p->get( itext::PdfName::BASEVERSION ) );
+ itext::PdfNumber* ext_level_p= (itext::PdfNumber*)
+ reader_p->getPdfObject( dev_exts_p->get( itext::PdfName::EXTENSIONLEVEL ) );
+
+ if( ext_base_versions.find( developer_p->hashCode() )== ext_base_versions.end() ||
+ GetPdfVersionChar( ext_base_versions[ developer_p->hashCode() ] )<
+ GetPdfVersionChar( base_version_p ) )
+ { // new developer or greater base version
+ ext_base_versions[ developer_p->hashCode() ]= base_version_p;
+ ext_levels[ developer_p->hashCode() ]= ext_level_p->intValue();
+ }
+ else if( GetPdfVersionChar( ext_base_versions[ developer_p->hashCode() ] )==
+ GetPdfVersionChar( base_version_p ) &&
+ ext_levels[ developer_p->hashCode() ]< ext_level_p->intValue() )
+ { // greater extension level for current base version
+ ext_levels[ developer_p->hashCode() ]= ext_level_p->intValue();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ // set the pdf version
+ writer_p->setPdfVersion( max_version_cc );
+
+ // open the doc
output_doc_p->open();
+ // set any pdf version extensions we might have found
+ if( !ext_base_versions.empty() ) {
+ itext::PdfDictionary* extensions_dict_p= new itext::PdfDictionary();
+ itext::PdfIndirectReference* extensions_ref_p= writer_p->getPdfIndirectReference();
+
+ for( map< jint, itext::PdfName* >::
+ const_iterator it= ext_base_versions.begin(); it!= ext_base_versions.end(); ++it )
+ {
+ itext::PdfDictionary* ext_dict_p= new itext::PdfDictionary();
+ ext_dict_p->put( itext::PdfName::BASEVERSION, it->second );
+ ext_dict_p->put( itext::PdfName::EXTENSIONLEVEL,
+ new itext::PdfNumber( ext_levels[ it->first ] ) );
+
+ extensions_dict_p->put( ext_developers[ it->first ], ext_dict_p );
+ }
+
+ writer_p->addToBody( extensions_dict_p, extensions_ref_p );
+ writer_p->setExtensions( extensions_ref_p );
+ }
+
if( m_operation== shuffle_k ) {
- // cerr << "operation: shuffle" << endl; // debug
unsigned int max_seq_length= 0;
for( vector< vector< PageRef > >::const_iterator jt= m_page_seq.begin();
jt!= m_page_seq.end(); ++jt )
{
- // cerr << "vector size: " << jt->size() << endl; // debug
max_seq_length= ( max_seq_length< jt->size() ) ? jt->size() : max_seq_length;
}
- // cerr << "max seq length: " << max_seq_length << endl; // debug
int output_page_count= 0;
// iterate over ranges
@@ -2428,7 +2589,6 @@
( jt!= m_page_seq.end() && ret_val== 0 ); ++jt )
{
if( ii< jt->size() ) {
- // cerr << "page number: " << output_page_count << endl; // debug
ret_val= create_output_page( writer_p, (*jt)[ii], output_page_count );
++output_page_count;
}
@@ -2436,6 +2596,7 @@
}
}
else { // cat_k
+
int output_page_count= 0;
// iterate over page ranges
for( vector< vector< PageRef > >::const_iterator jt= m_page_seq.begin();
@@ -2448,6 +2609,121 @@
ret_val= create_output_page( writer_p, *it, output_page_count );
}
}
+
+ // first impl added a bookmark for each input PDF and then
+ // added any of that PDFs bookmarks under that; now it
+ // appends input PDF bookmarks, which is more attractive;
+ // OTOH, some folks might want pdftk to add bookmarks for
+ // input PDFs, esp if they don't have bookmarks -- TODO
+ // but then, it would be nice to allow the user to specify
+ // a label -- using the PDF filename is unattractive;
+ if( m_cat_full_pdfs_b ) { // add bookmark info
+ itext::PdfDictionary* output_outlines_p=
+ new itext::PdfDictionary( itext::PdfName::OUTLINES );
+ itext::PdfIndirectReference* output_outlines_ref_p=
+ writer_p->getPdfIndirectReference();
+
+ itext::PdfDictionary* after_child_p= 0;
+ itext::PdfIndirectReference* after_child_ref_p= 0;
+
+ int page_count= 1;
+ int num_bookmarks_total= 0;
+ /* used for adding doc bookmarks
+ itext::PdfDictionary* prev_p= 0;
+ itext::PdfIndirectReference* prev_ref_p= 0;
+ */
+ for( vector< InputPdf >::const_iterator it= m_input_pdf.begin();
+ it!= m_input_pdf.end(); ++it )
+ {
+ /* used for adding doc bookmarks
+ itext::PdfDictionary* item_p= new itext::PdfDictionary();
+ itext::PdfIndirectReference* item_ref_p= writer_p->getPdfIndirectReference();
+
+ item_p->put( itext::PdfName::PARENT, outlines_ref_p );
+ item_p->put( itext::PdfName::TITLE,
+ new itext::PdfString( JvNewStringUTF( (*it).m_filename.c_str() ) ) );
+
+ // wire into linked list
+ if( prev_p ) {
+ prev_p->put( itext::PdfName::NEXT, item_ref_p );
+ item_p->put( itext::PdfName::PREV, prev_ref_p );
+ }
+ else { // first item; wire into outlines dict
+ output_outlines_p->put( itext::PdfName::FIRST, item_ref_p );
+ }
+
+ // the destination
+ itext::PdfDestination* dest_p= new itext::PdfDestination(itext::PdfDestination::FIT);
+ itext::PdfIndirectReference* page_ref_p= writer_p->getPageReference( page_count );
+ if( page_ref_p ) {
+ dest_p->addPage( page_ref_p );
+ }
+ item_p->put( itext::PdfName::DEST, dest_p );
+ */
+
+ // pdf bookmarks -> children
+ {
+ itext::PdfReader* reader_p= ((*it).m_readers.begin())->second;
+ itext::PdfDictionary* catalog_p= reader_p->getCatalog();
+ itext::PdfDictionary* outlines_p= (itext::PdfDictionary*)
+ reader_p->getPdfObject( catalog_p->get( itext::PdfName::OUTLINES ) );
+
+ if( outlines_p ) {
+ vector bookmark_data;
+ int rr= ReadOutlines( bookmark_data, outlines_p, -1, reader_p, true );
+ if( rr== 0 && !bookmark_data.empty() ) {
+
+ // passed in by reference, so must use variable:
+ vector::const_iterator vit= bookmark_data.begin();
+ BuildBookmarks( writer_p,
+ vit, bookmark_data.end(),
+ //item_p, item_ref_p, // used for adding doc bookmarks
+ output_outlines_p, output_outlines_ref_p,
+ after_child_p, after_child_ref_p,
+ after_child_p, after_child_ref_p,
+ 0, num_bookmarks_total,
+ page_count- 1, // page offset is 0-based
+ 0,
+ true );
+ }
+ }
+ //else
+ //cerr << "no outlines" << endl; // debug
+ }
+
+ /* used for adding doc bookmarks
+ // finished with prev; add to body
+ if( prev_p )
+ writer_p->addToBody( prev_p, prev_ref_p );
+
+ prev_p= item_p;
+ prev_ref_p= item_ref_p;
+ */
+
+ page_count+= (*it).m_num_pages;
+
+ }
+ /* used for adding doc bookmarks
+ if( prev_p ) { // wire into outlines dict
+ // finished with prev; add to body
+ writer_p->addToBody( prev_p, prev_ref_p );
+
+ output_outlines_p->put( itext::PdfName::LAST, prev_ref_p );
+ output_outlines_p->put( itext::PdfName::COUNT, new itext::PdfNumber( (jint)m_input_pdf.size() ) );
+ }
+ */
+
+ if( num_bookmarks_total ) { // we encountered bookmarks
+
+ // necessary for serial appending to outlines
+ if( after_child_p && after_child_ref_p )
+ writer_p->addToBody( after_child_p, after_child_ref_p );
+
+ writer_p->addToBody( output_outlines_p, output_outlines_ref_p );
+ writer_p->setOutlines( output_outlines_ref_p );
+ }
+ }
+
}
output_doc_p->close();
@@ -2504,6 +2780,7 @@
itext::Document* output_doc_p= new itext::Document();
java::FileOutputStream* ofs_p= new java::FileOutputStream( jv_output_filename_p );
itext::PdfCopy* writer_p= new itext::PdfCopy( output_doc_p, ofs_p );
+ writer_p->setFromReader( input_reader_p );
output_doc_p->addCreator( jv_creator_p );
@@ -2523,8 +2800,7 @@
!m_output_user_pw.empty() )
{
// if no stregth is given, default to 128 bit,
- // (which is incompatible w/ Acrobat 4)
- bool bit128_b=
+ jboolean bit128_b=
( m_output_encryption_strength!= bits40_enc );
writer_p->setEncryption( output_user_pw_p,
@@ -2533,12 +2809,16 @@
bit128_b );
}
+ output_doc_p->open(); // must open writer before copying (possibly) indirect object
+
{ // copy the Info dictionary metadata
if( input_info_p ) {
itext::PdfDictionary* writer_info_p= writer_p->getInfo();
- itext::PdfDictionary* info_copy_p= writer_p->copyDictionary( input_info_p );
- if( writer_info_p && info_copy_p ) {
- writer_info_p->putAll( info_copy_p );
+ if( writer_info_p ) {
+ itext::PdfDictionary* info_copy_p= writer_p->copyDictionary( input_info_p );
+ if( info_copy_p ) {
+ writer_info_p->putAll( info_copy_p );
+ }
}
}
jbyteArray input_reader_xmp_p= input_reader_p->getMetadata();
@@ -2547,8 +2827,6 @@
}
}
- output_doc_p->open();
-
itext::PdfImportedPage* page_p=
writer_p->getImportedPage( input_reader_p, ii+ 1 );
writer_p->addPage( page_p );
@@ -2560,7 +2838,17 @@
////
// dump document data
- ofstream ofs( "doc_data.txt" );
+ string doc_data_fn= "doc_data.txt";
+ if( !m_output_filename.empty() ) {
+ const char path_delim= PATH_DELIM;
+ string::size_type loc= 0;
+ if( (loc=m_output_filename.rfind( path_delim ))!= string::npos ) {
+
+ doc_data_fn= m_output_filename.substr( 0, loc )+
+ ((char)PATH_DELIM)+ doc_data_fn;
+ }
+ }
+ ofstream ofs( doc_data_fn.c_str() );
if( ofs ) {
ReportOnPdf( ofs, input_reader_p, m_output_utf8_b );
}
@@ -2843,8 +3131,7 @@
xfdf_reader_p= new itext::XfdfReader( in_arr );
}
catch( java::io::IOException* ioe_p ) { // file open error
- cerr << "Error: Failed to open form data file: " << endl;
- cerr << " " << m_form_data_filename << endl;
+ cerr << "Error: Failed read form data on stdin." << endl;
cerr << " No output created." << endl;
ret_val= 1;
//ioe_p->printStackTrace(); // debug
@@ -2965,7 +3252,7 @@
if( m_update_info_filename== "-" ) {
if( !UpdateInfo( input_reader_p, cin, m_update_info_utf8_b ) ) {
cerr << "Warning: no Info added to output PDF." << endl;
- ret_val= 1;
+ ret_val= 3;
}
}
else {
@@ -2973,7 +3260,7 @@
if( ifs ) {
if( !UpdateInfo( input_reader_p, ifs, m_update_info_utf8_b ) ) {
cerr << "Warning: no Info added to output PDF." << endl;
- ret_val= 1;
+ ret_val= 3;
}
}
else { // error
@@ -3004,6 +3291,16 @@
}
*/
+ // rotate pages?
+ if( !m_page_seq.empty() ) {
+ for( vector< vector< PageRef > >::const_iterator jt= m_page_seq.begin();
+ jt!= m_page_seq.end(); ++jt ) {
+ for( vector< PageRef >::const_iterator kt= jt->begin(); kt!= jt->end(); ++kt ) {
+ apply_rotation_to_page( input_reader_p, (*kt).m_page_num,
+ (*kt).m_page_rot, (*kt).m_page_abs );
+ }
+ }
+ }
// un/compress output streams?
if( m_output_uncompress_b ) {
@@ -3025,7 +3322,7 @@
// if no stregth is given, default to 128 bit,
// (which is incompatible w/ Acrobat 4)
- bool bit128_b=
+ jboolean bit128_b=
( m_output_encryption_strength!= bits40_enc );
writer_p->setEncryption( output_user_pw_p,
@@ -3035,9 +3332,9 @@
}
// fill form fields?
- if( fdf_reader_p ||
- xfdf_reader_p )
- {
+ if( fdf_reader_p || xfdf_reader_p ) {
+ if( input_reader_p->getAcroForm() ) { // we really have a form to fill
+
itext::AcroFields* fields_p= writer_p->getAcroFields();
fields_p->setGenerateAppearances( true ); // have iText create field appearances
if( ( fdf_reader_p && fields_p->setFields( fdf_reader_p ) ) ||
@@ -3049,6 +3346,8 @@
// above; setting this, here, allows us to keep the generated appearances,
// in case the PDF is opened somewhere besides Acrobat; yet, Acrobat/Reader
// will create the Rich Text appearance if it has a chance
+ m_output_need_appearances_b= true;
+ /*
itext::PdfDictionary* catalog_p= input_reader_p->catalog;
if( catalog_p && catalog_p->isDictionary() ) {
@@ -3059,12 +3358,31 @@
acro_form_p->put( itext::PdfName::NEEDAPPEARANCES, itext::PdfBoolean::PDFTRUE );
}
}
+ */
}
}
+ else { // warning
+ cerr << "Warning: input PDF is not an acroform, so its fields were not filled." << endl;
+ ret_val= 3;
+ }
+ }
// flatten form fields?
writer_p->setFormFlattening( m_output_flatten_b );
+ // cue viewer to render form field appearances?
+ if( m_output_need_appearances_b ) {
+ itext::PdfDictionary* catalog_p= input_reader_p->catalog;
+ if( catalog_p && catalog_p->isDictionary() ) {
+ itext::PdfDictionary* acro_form_p= (itext::PdfDictionary*)
+ input_reader_p->getPdfObject( catalog_p->get( itext::PdfName::ACROFORM ) );
+ if( acro_form_p && acro_form_p->isDictionary() ) {
+ acro_form_p->put( itext::PdfName::NEEDAPPEARANCES,
+ itext::PdfBoolean::PDFTRUE );
+ }
+ }
+ }
+
// add background/watermark?
if( mark_p ) {
@@ -3074,8 +3392,8 @@
}
// the mark information; initialized inside loop
- com::lowagie::text::pdf::PdfImportedPage* mark_page_p= 0;
- com::lowagie::text::Rectangle* mark_page_size_p= 0;
+ itext::PdfImportedPage* mark_page_p= 0;
+ itext::Rectangle* mark_page_size_p= 0;
jint mark_page_rotation= 0;
// iterate over document's pages, adding mark_page as
@@ -3100,7 +3418,7 @@
}
// the target page geometry
- com::lowagie::text::Rectangle* doc_page_size_p=
+ itext::Rectangle* doc_page_size_p=
input_reader_p->getCropBox( ii );
jint doc_page_rotation= input_reader_p->getPageRotation( ii );
for( jint mm= 0; mm< doc_page_rotation; mm+=90 ) {
@@ -3118,7 +3436,7 @@
(doc_page_size_p->height()-
mark_page_size_p->height()* mark_scale) / 2.0);
- com::lowagie::text::pdf::PdfContentByte* content_byte_p=
+ itext::PdfContentByte* content_byte_p=
( background_b ) ? writer_p->getUnderContent( ii ) : writer_p->getOverContent( ii );
if( mark_page_rotation== 0 ) {
@@ -3158,12 +3476,15 @@
}
// done; write output
- input_reader_p->removeUnusedObjects();
+ /// seems like a bad time for this:
+ ///input_reader_p->removeUnusedObjects();
+ /// besides, it should be done in add_reader() if desired
writer_p->close();
}
break;
case dump_data_fields_k :
+ case dump_data_annots_k :
case dump_data_k: { // report on input document
// we should have been given only a single, input file
@@ -3184,6 +3505,9 @@
else if( m_operation== dump_data_fields_k ) {
ReportAcroFormFields( cout, input_reader_p, m_output_utf8_b );
}
+ else if( m_operation== dump_data_annots_k ) {
+ ReportAnnots( cout, input_reader_p, m_output_utf8_b );
+ }
}
else {
ofstream ofs( m_output_filename.c_str() );
@@ -3194,6 +3518,9 @@
else if( m_operation== dump_data_fields_k ) {
ReportAcroFormFields( ofs, input_reader_p, m_output_utf8_b );
}
+ else if( m_operation== dump_data_annots_k ) {
+ ReportAnnots( ofs, input_reader_p, m_output_utf8_b );
+ }
}
else { // error
cerr << "Error: unable to open file for output: " << m_output_filename << endl;
@@ -3269,8 +3596,25 @@
return ret_val;
}
-int main(int argc, char** argv)
+#ifdef WIN32 // input is wide
+#include "mingw-unicode.c"
+int _tmain( int argc, _TCHAR *argvw[] )
+#else // input is UTF-8
+int main( int argc, char *argv[] )
+#endif
{
+
+#ifdef WIN32
+ // convert wide char input to UTF-8
+ char** argv= (char**)malloc( argc* sizeof( char* ) );
+ for( int ii= 0; ii< argc; ++ii ) {
+ int len= WideCharToMultiByte( CP_UTF8, 0, argvw[ii], -1, NULL, 0, NULL, NULL );
+ argv[ii]= (char*)malloc( (len+ 1)* sizeof( char ) );
+ WideCharToMultiByte( CP_UTF8, 0, argvw[ii], -1, argv[ii], len, NULL, NULL );
+ argv[ii][len]= 0; // add term null just in case
+ }
+#endif
+
bool help_b= false;
bool version_b= false;
bool synopsis_b= ( argc== 1 );
@@ -3303,9 +3647,11 @@
for( int ii= 1; ii< argc; ++ii ) {
version_b=
(version_b ||
- strcmp( argv[ii], "--version" )== 0 );
+ strcmp( argv[ii], "--version" )== 0 ||
+ strcmp( argv[ii], "-version" )== 0 );
help_b=
(strcmp( argv[ii], "--help" )== 0 ||
+ strcmp( argv[ii], "-help" )== 0 ||
strcmp( argv[ii], "-h" )== 0 );
}
@@ -3323,16 +3669,48 @@
JvCreateJavaVM(NULL);
JvAttachCurrentThread(NULL, NULL);
+ ////
+ // http://gcc.gnu.org/onlinedocs/gcj/Class-Initialization.html
+ // this is probably overkill:
+
JvInitClass(&java::System::class$);
+ JvInitClass(&java::String::class$);
+ JvInitClass(&java::HashMap::class$);
+ JvInitClass(&java::Vector::class$);
+ JvInitClass(&java::FileOutputStream::class$);
JvInitClass(&java::util::ArrayList::class$);
JvInitClass(&java::util::Iterator::class$);
- JvInitClass(&itext::PdfObject::class$);
JvInitClass(&itext::PdfName::class$);
+ JvInitClass(&itext::RandomAccessFileOrArray::class$);
+ JvInitClass(&itext::PdfAnnotation::class$);
+ JvInitClass(&itext::PdfNameTree::class$);
+ JvInitClass(&itext::PdfFileSpecification::class$);
+
+ JvInitClass(&itext::PdfReader::class$);
+ JvInitClass(&itext::PdfWriter::class$);
+ JvInitClass(&itext::PdfNumber::class$);
+ JvInitClass(&itext::Document::class$);
+ JvInitClass(&itext::PdfCopy::class$);
JvInitClass(&itext::PdfDictionary::class$);
+ JvInitClass(&itext::FdfReader::class$);
+ JvInitClass(&itext::FdfWriter::class$);
+ JvInitClass(&itext::XfdfReader::class$);
+ JvInitClass(&itext::PdfStamperImp::class$);
+ JvInitClass(&itext::PdfArray::class$);
+ JvInitClass(&itext::Rectangle::class$);
+ JvInitClass(&itext::PdfString::class$);
+ JvInitClass(&itext::PdfDestination::class$);
+ JvInitClass(&itext::PdfStream::class$);
+
+ JvInitClass(&itext::PdfObject::class$);
JvInitClass(&itext::PdfOutline::class$);
JvInitClass(&itext::PdfBoolean::class$);
+ // fixes an error triggered by xfdf form filling
+ JvInitClass(&gnu::gcj::convert::Input_UTF8::class$);
+ JvInitClass(&gnu::gcj::convert::Input_ASCII::class$);
+
TK_Session tk_session( argc, argv );
tk_session.dump_session_data();
@@ -3345,8 +3723,6 @@
cerr << "Done. Input errors, so no output created." << endl;
ret_val= 1;
}
-
- JvDetachCurrentThread();
}
// per https://bugs.launchpad.net/ubuntu/+source/pdftk/+bug/544636
catch(java::lang::ClassCastException* c_p ) {
@@ -3364,13 +3740,31 @@
c_p->printStackTrace();
ret_val= 1;
}
- catch( java::lang::Throwable* t_p )
- {
+ catch( java::lang::Throwable* t_p ) {
cerr << "Unhandled Java Exception:" << endl;
t_p->printStackTrace();
ret_val= 2;
- }
+ }
+
+ try {
+ JvDetachCurrentThread();
+ }
+ catch( java::lang::Throwable* t_p ) {
+ cerr << "Unhandled Java Exception:" << endl;
+ t_p->printStackTrace();
+ ret_val= 2;
+ }
+ }
+
+#ifdef WIN32
+ // release memory
+ for( int ii= 0; ii< argc; ++ii ) {
+ free( argv[ii] );
+ argv[ii]= 0;
}
+ free( argv );
+ argv= 0;
+#endif
return ret_val;
}
@@ -3379,7 +3773,7 @@
describe_header() {
cout << endl;
cout << "pdftk " << PDFTK_VER << " a Handy Tool for Manipulating PDF Documents" << endl;
- cout << "Copyright (C) 2003-12, Sid Steward - Please Visit: www.pdftk.com" << endl;
+ cout << "Copyright (C) 2003-13, Sid Steward - Please Visit: www.pdftk.com" << endl;
cout << "This is free software; see the source code for copying conditions. There is" << endl;
cout << "NO warranty, not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." << endl;
}
@@ -3396,17 +3790,19 @@
[ allow ]\n\
[ owner_pw ]\n\
[ user_pw ]\n\
- [ flatten ] [ compress | uncompress ]\n\
+ [ flatten ] [ need_appearances ]\n\
+ [ compress | uncompress ]\n\
[ keep_first_id | keep_final_id ] [ drop_xfa ]\n\
[ verbose ] [ dont_ask | do_ask ]\n\
Where:\n\
may be empty, or:\n\
- [ cat | shuffle | burst |\n\
+ [ cat | shuffle | burst | rotate |\n\
generate_fdf | fill_form |\n\
background | multibackground |\n\
stamp | multistamp |\n\
dump_data | dump_data_utf8 |\n\
dump_data_fields | dump_data_fields_utf8 |\n\
+ dump_data_annots |\n\
update_info | update_info_utf8 |\n\
attach_files | unpack_files ]\n\
\n\
@@ -3481,12 +3877,12 @@
word if the supplied password is incorrect or none was given.\n\
\n\
[ ]\n\
- Available operations are: cat, shuffle, burst, generate_fdf,\n\
- fill_form, background, multibackground, stamp, multistamp,\n\
- dump_data, dump_data_utf8, dump_data_fields,\n\
- dump_data_fields_utf8, update_info, update_info_utf8,\n\
- attach_files, unpack_files. Some operations takes additional\n\
- arguments, described below.\n\
+ Available operations are: cat, shuffle, burst, rotate, gener-\n\
+ ate_fdf, fill_form, background, multibackground, stamp, multi-\n\
+ stamp, dump_data, dump_data_utf8, dump_data_fields,\n\
+ dump_data_fields_utf8, dump_data_annots, update_info,\n\
+ update_info_utf8, attach_files, unpack_files. Some operations\n\
+ takes additional arguments, described below.\n\
\n\
If this optional argument is omitted, then pdftk runs in 'fil-\n\
ter' mode. Filter mode takes only one PDF input and creates a\n\
@@ -3571,7 +3967,7 @@
single PDF, and page rotation. This feature was designed to\n\
help collate PDF pages after scanning paper documents.\n\
\n\
- burst Splits a single, input PDF document into individual pages.\n\
+ burst Splits a single input PDF document into individual pages.\n\
Also creates a report named doc_data.txt which is the same as\n\
the output from dump_data. If the output section is omitted,\n\
then PDF pages are named: pg_%04d.pdf, e.g.: pg_0001.pdf,\n\
@@ -3584,10 +3980,31 @@
\n\
pdftk in.pdf burst owner_pw foopass\n\
\n\
+ rotate []\n\
+ Takes a single input PDF and rotates just the specified\n\
+ pages. All other pages remain unchanged. The page order\n\
+ remains unchaged. Specify the pages to rotate using the same\n\
+ notation as you would with cat, except you omit the pages\n\
+ that you aren't rotating:\n\
+\n\
+ [[-[]]][]\n\
+\n\
+ The qualifier can be even or odd, and the page rotation can\n\
+ be north, south, east, west, left, right, or down.\n\
+\n\
+ Each option sets the page rotation as follows (in degrees):\n\
+ north: 0, east: 90, south: 180, west: 270, left: -90, right:\n\
+ +90, down: +180. left, right, and down make relative adjust-\n\
+ ments to a page's rotation.\n\
+\n\
+ The given order of the pages doesn't change the page order in\n\
+ the output.\n\
+\n\
generate_fdf\n\
- Reads a single, input PDF file and generates an FDF file\n\
- suitable for fill_form out of it to the given output filename\n\
- or (if no output is given) to stdout. Does not create a new\n\
+ Reads a single input PDF file and generates an FDF file suit-\n\
+ able for fill_form out of it to the given output filename or\n\
+ (if no output is given) to stdout. Does not create a new\n\
PDF.\n\
\n\
fill_form \n\
@@ -3598,29 +4015,20 @@
\n\
pdftk form.pdf fill_form data.fdf output form.filled.pdf\n\
\n\
- After filling a form, the form fields remain interactive\n\
- unless you also use the flatten output option. flatten merges\n\
- the form fields with the PDF pages. You can use flatten\n\
- alone, too, but only on a single PDF:\n\
-\n\
- pdftk form.pdf fill_form data.fdf output out.pdf flatten\n\
-\n\
- or:\n\
-\n\
- pdftk form.filled.pdf output out.pdf flatten\n\
-\n\
If the input FDF file includes Rich Text formatted data in\n\
addition to plain text, then the Rich Text data is packed\n\
into the form fields as well as the plain text. Pdftk also\n\
- sets a flag that cues Acrobat/Reader to generate new field\n\
- appearances based on the Rich Text data. That way, when the\n\
- user opens the PDF, the viewer will create the Rich Text\n\
- fields on the spot. If the user's PDF viewer does not sup-\n\
- port Rich Text, then the user will see the plain text data\n\
+ sets a flag that cues Reader/Acrobat to generate new field\n\
+ appearances based on the Rich Text data. So when the user\n\
+ opens the PDF, the viewer will create the Rich Text appear-\n\
+ ance on the spot. If the user's PDF viewer does not support\n\
+ Rich Text, then the user will see the plain text data\n\
instead. If you flatten this form before Acrobat has a\n\
chance to create (and save) new field appearances, then the\n\
plain text field data is what you'll see.\n\
\n\
+ Also see the flatten and need_appearances options.\n\
+\n\
background \n\
Applies a PDF watermark to the background of a single input\n\
PDF. Pass the background PDF's filename after background\n\
@@ -3658,18 +4066,18 @@
the input PDF.\n\
\n\
dump_data\n\
- Reads a single, input PDF file and reports various statis-\n\
- tics, metadata, bookmarks (a/k/a outlines), and page labels\n\
- to the given output filename or (if no output is given) to\n\
- stdout. Non-ASCII characters are encoded as XML numerical\n\
- entities. Does not create a new PDF.\n\
+ Reads a single input PDF file and reports various statistics,\n\
+ metadata, bookmarks (a/k/a outlines), and page labels to the\n\
+ given output filename or (if no output is given) to stdout.\n\
+ Non-ASCII characters are encoded as XML numerical entities.\n\
+ Does not create a new PDF.\n\
\n\
dump_data_utf8\n\
Same as dump_data excepct that the output is encoded as\n\
UTF-8.\n\
\n\
dump_data_fields\n\
- Reads a single, input PDF file and reports form field statis-\n\
+ Reads a single input PDF file and reports form field statis-\n\
tics to the given output filename or (if no output is given)\n\
to stdout. Non-ASCII characters are encoded as XML numerical\n\
entities. Does not create a new PDF.\n\
@@ -3678,6 +4086,13 @@
Same as dump_data_fields excepct that the output is encoded\n\
as UTF-8.\n\
\n\
+ dump_data_annots\n\
+ This operation currently reports only link annotations.\n\
+ Reads a single input PDF file and reports annotation informa-\n\
+ tion to the given output filename or (if no output is given)\n\
+ to stdout. Non-ASCII characters are encoded as XML numerical\n\
+ entities. Does not create a new PDF.\n\
+\n\
update_info \n\
Changes the bookmarks and metadata in a single PDF's Info\n\
dictionary to match the input data file. The input data file\n\
@@ -3782,6 +4197,13 @@
(and their data) with the PDF's pages. Only one input PDF may be\n\
given. Sometimes used with the fill_form operation.\n\
\n\
+ [need_appearances]\n\
+ Sets a flag that cues Reader/Acrobat to generate new field\n\
+ appearances based on the form field values. Use this when fill-\n\
+ ing a form with non-ASCII text to ensure the best presentation\n\
+ in Adobe Reader or Acrobat. It won't work when combined with\n\
+ the flatten option.\n\
+\n\
[keep_first_id | keep_final_id]\n\
When combining pages from multiple PDFs, use one of these\n\
options to copy the document ID from either the first or final\n\
diff -Nru pdftk-1.45/pdftk/pdftk.h pdftk-2.01/pdftk/pdftk.h
--- pdftk-1.45/pdftk/pdftk.h 2012-12-06 11:58:54.000000000 +0000
+++ pdftk-2.01/pdftk/pdftk.h 2013-05-22 08:22:18.000000000 +0000
@@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 2; c-basic-offset: 2 -*- */
/*
pdftk, the PDF Toolkit
- Copyright (c) 2003-2012 Sid Steward
+ Copyright (c) 2003-2013 Sid Steward
This program is free software; you can redistribute it and/or modify
@@ -85,6 +85,7 @@
dump_data_utf8_k,
dump_data_fields_k,
dump_data_fields_utf8_k,
+ dump_data_annots_k,
generate_fdf_k,
unpack_files_k, // unpack files from input; no PDF output
//
@@ -102,6 +103,7 @@
multibackground_k, // feature added by Bernhard R. Link , Johann Felix Soden
stamp_k,
multistamp_k, // feature added by Bernhard R. Link , Johann Felix Soden
+ rotate_k, // rotate given pages as directed
// optional attach_file argument
attach_file_to_page_k,
@@ -140,6 +142,7 @@
// forms
flatten_k,
+ need_appearances_k,
drop_xfa_k,
keep_first_id_k,
keep_final_id_k,
@@ -189,9 +192,11 @@
bool m_output_uncompress_b;
bool m_output_compress_b;
bool m_output_flatten_b;
+ bool m_output_need_appearances_b;
bool m_output_drop_xfa_b;
bool m_output_keep_first_id_b;
bool m_output_keep_final_id_b;
+ bool m_cat_full_pdfs_b; // we are merging entire docs, not select pages
enum encryption_strength {
none_enc= 0,
diff -Nru pdftk-1.45/pdftk/report.cc pdftk-2.01/pdftk/report.cc
--- pdftk-1.45/pdftk/report.cc 2012-12-06 11:58:20.000000000 +0000
+++ pdftk-2.01/pdftk/report.cc 2013-05-22 08:21:58.000000000 +0000
@@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 2; c-basic-offset: 2 -*- */
/*
pdftk, the PDF Toolkit
- Copyright (c) 2003-2012 Sid Steward
+ Copyright (c) 2003-2013 Sid Steward
This program is free software; you can redistribute it and/or modify
@@ -53,30 +53,30 @@
#include
#include
-#include "com/lowagie/text/Document.h"
-#include "com/lowagie/text/Rectangle.h"
-#include "com/lowagie/text/pdf/PdfObject.h"
-#include "com/lowagie/text/pdf/PdfName.h"
-#include "com/lowagie/text/pdf/PdfString.h"
-#include "com/lowagie/text/pdf/PdfNumber.h"
-#include "com/lowagie/text/pdf/PdfArray.h"
-#include "com/lowagie/text/pdf/PdfDictionary.h"
-#include "com/lowagie/text/pdf/PdfDestination.h"
-#include "com/lowagie/text/pdf/PdfOutline.h"
-#include "com/lowagie/text/pdf/PdfCopy.h"
-#include "com/lowagie/text/pdf/PdfReader.h"
-#include "com/lowagie/text/pdf/PdfImportedPage.h"
-#include "com/lowagie/text/pdf/PdfWriter.h"
-#include "com/lowagie/text/pdf/PdfStamperImp.h"
-#include "com/lowagie/text/pdf/PdfEncryptor.h"
-#include "com/lowagie/text/pdf/PdfNameTree.h"
-#include "com/lowagie/text/pdf/FdfReader.h"
-#include "com/lowagie/text/pdf/AcroFields.h"
-#include "com/lowagie/text/pdf/PdfIndirectReference.h"
-#include "com/lowagie/text/pdf/PdfIndirectObject.h"
-#include "com/lowagie/text/pdf/PdfFileSpecification.h"
+#include "pdftk/com/lowagie/text/Document.h"
+#include "pdftk/com/lowagie/text/Rectangle.h"
+#include "pdftk/com/lowagie/text/pdf/PdfObject.h"
+#include "pdftk/com/lowagie/text/pdf/PdfName.h"
+#include "pdftk/com/lowagie/text/pdf/PdfString.h"
+#include "pdftk/com/lowagie/text/pdf/PdfNumber.h"
+#include "pdftk/com/lowagie/text/pdf/PdfBoolean.h"
+#include "pdftk/com/lowagie/text/pdf/PdfArray.h"
+#include "pdftk/com/lowagie/text/pdf/PdfDictionary.h"
+#include "pdftk/com/lowagie/text/pdf/PdfDestination.h"
+#include "pdftk/com/lowagie/text/pdf/PdfOutline.h"
+#include "pdftk/com/lowagie/text/pdf/PdfCopy.h"
+#include "pdftk/com/lowagie/text/pdf/PdfReader.h"
+#include "pdftk/com/lowagie/text/pdf/PdfImportedPage.h"
+#include "pdftk/com/lowagie/text/pdf/PdfWriter.h"
+#include "pdftk/com/lowagie/text/pdf/PdfStamperImp.h"
+#include "pdftk/com/lowagie/text/pdf/PdfNameTree.h"
+#include "pdftk/com/lowagie/text/pdf/FdfReader.h"
+#include "pdftk/com/lowagie/text/pdf/AcroFields.h"
+#include "pdftk/com/lowagie/text/pdf/PdfIndirectReference.h"
+#include "pdftk/com/lowagie/text/pdf/PdfIndirectObject.h"
+#include "pdftk/com/lowagie/text/pdf/PdfFileSpecification.h"
-#include "com/lowagie/text/pdf/PRStream.h"
+#include "pdftk/com/lowagie/text/pdf/PRStream.h"
using namespace std;
@@ -87,8 +87,8 @@
}
namespace itext {
- using namespace com::lowagie::text;
- using namespace com::lowagie::text::pdf;
+ using namespace pdftk::com::lowagie::text;
+ using namespace pdftk::com::lowagie::text::pdf;
}
#include "pdftk.h"
@@ -98,7 +98,7 @@
////
// created for data import, maybe useful for export, too
-static const string pdftkEmptyString= "PdftkEmptyString";
+static const string g_uninitString= "PdftkEmptyString";
//
class PdfInfo {
@@ -111,8 +111,8 @@
string m_key;
string m_value;
- PdfInfo() : m_key(pdftkEmptyString), m_value(pdftkEmptyString) {}
- bool valid() { return( m_key!= pdftkEmptyString && m_value!= pdftkEmptyString ); }
+ PdfInfo() : m_key( g_uninitString ), m_value( g_uninitString ) {}
+ bool valid() { return( m_key!= g_uninitString && m_value!= g_uninitString ); }
};
const string PdfInfo::m_prefix= "Info";
const string PdfInfo::m_begin_mark= "InfoBegin";
@@ -126,28 +126,16 @@
return ss;
}
-//
-class PdfBookmark {
-public:
- static const string m_prefix;
- static const string m_begin_mark;
- static const string m_title_label;
- static const string m_level_label;
- static const string m_page_number_label;
-
- string m_title;
- int m_level;
- int m_page_num; // zero means no destination
-
- PdfBookmark() : m_title(pdftkEmptyString), m_level(-1), m_page_num(-1) {}
-
- bool valid() { return( 0< m_level && 0<= m_page_num && m_title!= pdftkEmptyString ); }
-};
const string PdfBookmark::m_prefix= "Bookmark";
const string PdfBookmark::m_begin_mark= "BookmarkBegin";
const string PdfBookmark::m_title_label= "BookmarkTitle:";
const string PdfBookmark::m_level_label= "BookmarkLevel:";
const string PdfBookmark::m_page_number_label= "BookmarkPageNumber:";
+PdfBookmark::PdfBookmark() : m_title( g_uninitString ),
+ m_level(-1), m_page_num(-1) {}
+bool PdfBookmark::valid() {
+ return( 0< m_level && 0<= m_page_num && m_title!= g_uninitString );
+}
ostream& operator<<( ostream& ss, const PdfBookmark& bb ) {
ss << PdfBookmark::m_begin_mark << endl;
@@ -167,6 +155,16 @@
const string PdfPageLabel::m_prefix= "PageLabel";
const string PdfPageLabel::m_begin_mark= "PageLabelBegin";
+//
+class PdfPageMedia {
+public:
+ static const string m_prefix;
+ static const string m_begin_mark;
+ // TODO
+};
+const string PdfPageMedia::m_prefix= "PageMedia";
+const string PdfPageMedia::m_begin_mark= "PageMediaBegin";
+
////
//
class PdfData {
@@ -180,7 +178,7 @@
string m_id_1;
PdfData() : m_info(), m_bookmarks(), m_num_pages(-1),
- m_id_0( pdftkEmptyString ), m_id_1( pdftkEmptyString ) {}
+ m_id_0( g_uninitString ), m_id_1( g_uninitString ) {}
};
ostream& operator<<( ostream& ss, const PdfData& dd ) {
@@ -281,20 +279,31 @@
static int
GetPageNumber( itext::PdfDictionary* dict_p,
- itext::PdfReader* reader_p )
+ itext::PdfReader* reader_p,
+ map< itext::PdfDictionary*, int >& cache )
// take a PdfPage dictionary and return its page location in the document;
// recurse our way up the pages tree, counting pages as we go;
// dict_p may be a page or a page tree object;
// return value is zero-based;
{
- if( dict_p && dict_p->contains( itext::PdfName::PARENT ) ) {
- jint sum_pages= 0;
+ { // consult the cache
+ map< itext::PdfDictionary*, int >::const_iterator it=
+ cache.find( dict_p );
+ if( it!= cache.end() )
+ return it->second;
+ }
+
+ int ret_val= 0;
+ if( dict_p && dict_p->contains( itext::PdfName::PARENT ) ) {
itext::PdfDictionary* parent_p= (itext::PdfDictionary*)
reader_p->getPdfObject( dict_p->get( itext::PdfName::PARENT ) );
if( parent_p && parent_p->isDictionary() ) {
// a parent is a page tree object and will have Kids
+ // recurse up the page tree
+ jint sum_pages= GetPageNumber( parent_p, reader_p, cache );
+
itext::PdfArray* parent_kids_p= (itext::PdfArray*)
reader_p->getPdfObject( parent_p->get( itext::PdfName::KIDS ) );
if( parent_kids_p && parent_kids_p->isArray() ) {
@@ -309,47 +318,47 @@
reader_p->getPdfObject( (itext::PdfDictionary*)(kids_p->get(kids_ii)) );
if( kid_p && kid_p->isDictionary() ) {
- if( kid_p== dict_p ) {
- // counting kids is complete; recurse
+ if( kid_p== dict_p ) // we have what we were looking for
+ ret_val= sum_pages;
- return sum_pages+ GetPageNumber( parent_p, reader_p ); // <--- return
- }
- else {
- // is kid a page, or is kid a page tree object? add count to sum;
- // PdfDictionary::isPage() and PdfDictionary::isPages()
- // are not reliable, here
-
- itext::PdfName* kid_type_p= (itext::PdfName*)
- reader_p->getPdfObject( kid_p->get( itext::PdfName::TYPE ) );
- if( kid_type_p && kid_type_p->isName() ) {
+ // is kid a page, or is kid a page tree object? add count to sum;
+ // PdfDictionary::isPage() and PdfDictionary::isPages()
+ // are not reliable, here
- if( kid_type_p->equals( itext::PdfName::PAGE ) ) {
- // *kid_p is a Page
+ itext::PdfName* kid_type_p= (itext::PdfName*)
+ reader_p->getPdfObject( kid_p->get( itext::PdfName::TYPE ) );
+ if( kid_type_p && kid_type_p->isName() ) {
- sum_pages+= 1;
- }
- else if( kid_type_p->equals( itext::PdfName::PAGES ) ) {
- // *kid_p is a Page Tree Node
+ if( kid_type_p->equals( itext::PdfName::PAGE ) ) {
+ // *kid_p is a Page
+
+ // store page number in our cache
+ cache[ kid_p ]= sum_pages;
+
+ //
+ sum_pages+= 1;
+ }
+ else if( kid_type_p->equals( itext::PdfName::PAGES ) ) {
+ // *kid_p is a Page Tree Node
+
+ itext::PdfNumber* count_p= (itext::PdfNumber*)
+ reader_p->getPdfObject( kid_p->get( itext::PdfName::COUNT ) );
+ if( count_p && count_p->isNumber() ) {
- itext::PdfNumber* count_p= (itext::PdfNumber*)
- reader_p->getPdfObject( kid_p->get( itext::PdfName::COUNT ) );
- if( count_p && count_p->isNumber() ) {
-
- sum_pages+= count_p->intValue();
-
- }
- else { // error
- cerr << "pdftk Error in GetPageNumber(): invalid count;" << endl;
- }
+ //
+ sum_pages+= count_p->intValue();
}
else { // error
- cerr << "pdftk Error in GetPageNumber(): unexpected kid type;" << endl;
+ cerr << "pdftk Error in GetPageNumber(): invalid count;" << endl;
}
}
else { // error
- cerr << "pdftk Error in GetPageNumber(): invalid kid_type_p;" << endl;
+ cerr << "pdftk Error in GetPageNumber(): unexpected kid type;" << endl;
}
}
+ else { // error
+ cerr << "pdftk Error in GetPageNumber(): invalid kid_type_p;" << endl;
+ }
}
else { // error
cerr << "pdftk Error in GetPageNumber(): invalid kid_p;" << endl;
@@ -371,138 +380,169 @@
}
else {
// *dict_p has no parent; end recursion
- return 0;
+ ret_val= 0;
+ cache[ dict_p ]= ret_val;
}
- // error: should have recursed
- cerr << "pdftk Error in GetPageNumber(): recursion case skipped;" << endl;
-
- return 0;
+ return ret_val;
}
-static void
-ReportOutlines( ostream& ofs,
- itext::PdfDictionary* outline_p,
- int level,
- itext::PdfReader* reader_p,
- bool utf8_b )
+int
+ReadOutlines( vector& bookmark_data,
+ itext::PdfDictionary* outline_p,
+ int level, // pass in -1 to trim off Outlines dict
+ itext::PdfReader* reader_p,
+ bool utf8_b )
{
- // mark beginning of record
- ofs << "BookmarkBegin" << endl;
+ int ret_val= 0;
+ map< itext::PdfDictionary*, int > cache;
- // the title; HTML-compatible
- ofs << "BookmarkTitle: ";
- itext::PdfString* title_p= (itext::PdfString*)
- reader_p->getPdfObject( outline_p->get( itext::PdfName::TITLE ) );
- if( title_p && title_p->isString() ) {
+ while( outline_p ) {
- OutputPdfString( ofs, title_p, utf8_b );
-
- ofs << endl;
- }
- else { // error
- ofs << "[PDFTK ERROR: TITLE NOT FOUND]" << endl;
- }
+ // load this with collected data, then add to vector
+ PdfBookmark bookmark;
+
+ // the title
+ itext::PdfString* title_p= (itext::PdfString*)
+ reader_p->getPdfObject( outline_p->get( itext::PdfName::TITLE ) );
+ if( title_p && title_p->isString() ) {
+
+ ostringstream oss;
+ OutputPdfString( oss, title_p, utf8_b );
+ bookmark.m_title= oss.str();
+ }
+ else { // error
+ ret_val= 1;
+ }
- // the level; 1-based to jive with HTML heading level concept
- ofs << "BookmarkLevel: " << level+ 1 << endl;
+ // the level; 1-based to jive with HTML heading level concept
+ bookmark.m_level= level+ 1;
- // page number, 1-based;
- // a zero value indicates no page destination or an error
- ofs << "BookmarkPageNumber: ";
- {
- bool fail_b= false;
+ // page number, 1-based;
+ // a zero value indicates no page destination or an error
+ {
+ bool fail_b= false;
- // the destination object may take be in a couple different places
- // and may take a couple, different forms
+ // the destination object may take be in a couple different places
+ // and may take a couple, different forms
- itext::PdfObject* destination_p= 0; {
- if( outline_p->contains( itext::PdfName::DEST ) ) {
- destination_p=
- reader_p->getPdfObject( outline_p->get( itext::PdfName::DEST ) );
- }
- else if( outline_p->contains( itext::PdfName::A ) ) {
+ itext::PdfObject* destination_p= 0; {
+ if( outline_p->contains( itext::PdfName::DEST ) ) {
+ destination_p=
+ reader_p->getPdfObject( outline_p->get( itext::PdfName::DEST ) );
+ }
+ else if( outline_p->contains( itext::PdfName::A ) ) {
- itext::PdfDictionary* action_p= (itext::PdfDictionary*)
- reader_p->getPdfObject( outline_p->get( itext::PdfName::A ) );
- if( action_p && action_p->isDictionary() ) {
+ itext::PdfDictionary* action_p= (itext::PdfDictionary*)
+ reader_p->getPdfObject( outline_p->get( itext::PdfName::A ) );
+ if( action_p && action_p->isDictionary() ) {
+
+ itext::PdfName* s_p= (itext::PdfName*)
+ reader_p->getPdfObject( action_p->get( itext::PdfName::S ) );
+ if( s_p && s_p->isName() ) {
- itext::PdfName* s_p= (itext::PdfName*)
- reader_p->getPdfObject( action_p->get( itext::PdfName::S ) );
- if( s_p && s_p->isName() ) {
-
- if( s_p->equals( itext::PdfName::GOTO ) ) {
- destination_p=
- reader_p->getPdfObject( action_p->get( itext::PdfName::D ) );
- }
- else { // immediate action is not a link in this document;
- // not an error
- // fail_b= true;
+ if( s_p->equals( itext::PdfName::GOTO ) ) {
+ destination_p=
+ reader_p->getPdfObject( action_p->get( itext::PdfName::D ) );
+ }
+ else { // immediate action is not a link in this document;
+ // not an error
+ // fail_b= true;
+ }
+ }
+ else { // error
+ fail_b= true;
}
}
else { // error
fail_b= true;
}
}
- else { // error
+ else { // unexpected
fail_b= true;
}
}
- else { // unexpected
- fail_b= true;
- }
- }
- // destination is an array
- if( destination_p && destination_p->isArray() ) {
+ // destination is an array
+ if( destination_p && destination_p->isArray() ) {
- java::ArrayList* array_list_p= ((itext::PdfArray*)destination_p)->getArrayList();
- if( array_list_p && !array_list_p->isEmpty() ) {
+ java::ArrayList* array_list_p= ((itext::PdfArray*)destination_p)->getArrayList();
+ if( array_list_p && !array_list_p->isEmpty() ) {
- itext::PdfDictionary* page_p= (itext::PdfDictionary*)
- reader_p->getPdfObject( (itext::PdfObject*)(array_list_p->get(0)) );
+ itext::PdfDictionary* page_p= (itext::PdfDictionary*)
+ reader_p->getPdfObject( (itext::PdfObject*)(array_list_p->get(0)) );
- if( page_p && page_p->isDictionary() ) {
- ofs << GetPageNumber(page_p, reader_p)+ 1 << endl;
+ if( page_p && page_p->isDictionary() ) {
+ bookmark.m_page_num= GetPageNumber(page_p, reader_p, cache)+ 1;
+ }
+ else { // error
+ fail_b= true;
+ }
}
else { // error
fail_b= true;
}
- }
+ } // TODO: named destinations handling
else { // error
fail_b= true;
}
- } // TODO: named destinations handling
- else { // error
- fail_b= true;
- }
- if( fail_b ) { // output our 'null page reference' code
- ofs << 0 << endl;
+ if( fail_b ) { // output our 'null page reference' code
+ bookmark.m_page_num= 0;
+ }
}
- }
- // recurse into any children
- if( outline_p->contains( itext::PdfName::FIRST ) ) {
+ // add bookmark to collected data
+ if( 0< bookmark.m_level )
+ bookmark_data.push_back( bookmark );
+
+ // recurse into any children
+ if( outline_p->contains( itext::PdfName::FIRST ) ) {
- itext::PdfDictionary* child_p= (itext::PdfDictionary*)
- reader_p->getPdfObject( outline_p->get( itext::PdfName::FIRST ) );
- if( child_p && child_p->isDictionary() ) {
+ itext::PdfDictionary* child_p= (itext::PdfDictionary*)
+ reader_p->getPdfObject( outline_p->get( itext::PdfName::FIRST ) );
+ if( child_p && child_p->isDictionary() ) {
- ReportOutlines( ofs, child_p, level+ 1, reader_p, utf8_b );
+ ret_val+= ReadOutlines( bookmark_data, child_p, level+ 1, reader_p, utf8_b );
+ }
+ }
+
+ // iterate over siblings
+ if( outline_p->contains( itext::PdfName::NEXT ) ) {
+
+ itext::PdfDictionary* sibling_p= (itext::PdfDictionary*)
+ reader_p->getPdfObject( outline_p->get( itext::PdfName::NEXT ) );
+ if( sibling_p && sibling_p->isDictionary() ) {
+ outline_p= sibling_p;
+ }
+ else // break out of loop
+ outline_p= 0;
}
+ else // break out of loop
+ outline_p= 0;
}
- // recurse into next sibling
- if( outline_p->contains( itext::PdfName::NEXT ) ) {
+ return ret_val;
+}
- itext::PdfDictionary* sibling_p= (itext::PdfDictionary*)
- reader_p->getPdfObject( outline_p->get( itext::PdfName::NEXT ) );
- if( sibling_p && sibling_p->isDictionary() ) {
+static void
+ReportOutlines( ostream& ofs,
+ itext::PdfDictionary* outline_p,
+ itext::PdfReader* reader_p,
+ bool utf8_b )
+{
+ vector bookmark_data;
+ ReadOutlines( bookmark_data,
+ outline_p,
+ 0,
+ reader_p,
+ utf8_b );
- ReportOutlines( ofs, sibling_p, level, reader_p, utf8_b );
+ for( vector::iterator it= bookmark_data.begin();
+ it!= bookmark_data.end(); ++it )
+ {
+ ofs << *it;
}
- }
}
static void
@@ -679,7 +719,7 @@
string m_tt; // name
string m_tu; // alt. name
int m_ff; // flags
- string m_vv; // value
+ set< string > m_vv; // value -- may be an array
string m_dv; // default value
// variable-text features
@@ -709,8 +749,10 @@
if( !ff.m_tu.empty() )
ofs << "FieldNameAlt: " << ff.m_tu << endl;
ofs << "FieldFlags: " << ff.m_ff << endl;
- if( !ff.m_vv.empty() )
- ofs << "FieldValue: " << ff.m_vv << endl;
+ if( !ff.m_vv.empty() ) {
+ for( set< string >::const_iterator it= ff.m_vv.begin(); it!= ff.m_vv.end(); ++it )
+ ofs << "FieldValue: " << (*it) << endl;
+ }
if( !ff.m_dv.empty() )
ofs << "FieldValueDefault: " << ff.m_dv << endl;
@@ -832,15 +874,36 @@
if( kid_p->contains( itext::PdfName::V ) ) {
itext::PdfObject* pdfs_p=
reader_p->getPdfObject( kid_p->get( itext::PdfName::V ) );
+
if( pdfs_p && pdfs_p->isString() ) {
ostringstream name_oss;
OutputPdfString( name_oss, (itext::PdfString*)pdfs_p, utf8_b );
- acc_state.m_vv= name_oss.str();
+ acc_state.m_vv.insert( name_oss.str() );
}
- if( pdfs_p && pdfs_p->isName() ) {
+ else if( pdfs_p && pdfs_p->isName() ) {
ostringstream name_oss;
OutputPdfName( name_oss, (itext::PdfName*)pdfs_p );
- acc_state.m_vv= name_oss.str();
+ acc_state.m_vv.insert( name_oss.str() );
+ }
+ else if( pdfs_p && pdfs_p->isArray() ) {
+ // multiple selections
+ java::ArrayList* vv_p= ((itext::PdfArray*)pdfs_p)->getArrayList();
+ for( jint vv_ii= 0; vv_ii< vv_p->size(); ++vv_ii ) {
+ itext::PdfObject* pdfs_p= (itext::PdfObject*)
+ reader_p->getPdfObject( (itext::PdfObject*)(vv_p->get(vv_ii)) );
+
+ // copy/paste from above
+ if( pdfs_p && pdfs_p->isString() ) {
+ ostringstream name_oss;
+ OutputPdfString( name_oss, (itext::PdfString*)pdfs_p, utf8_b );
+ acc_state.m_vv.insert( name_oss.str() );
+ }
+ else if( pdfs_p && pdfs_p->isName() ) {
+ ostringstream name_oss;
+ OutputPdfName( name_oss, (itext::PdfName*)pdfs_p );
+ acc_state.m_vv.insert( name_oss.str() );
+ }
+ }
}
}
@@ -1125,11 +1188,14 @@
}
}
+ jint numPages= reader_p->getNumberOfPages();
+
{ // number of pages and outlines
itext::PdfDictionary* catalog_p= reader_p->catalog;
if( catalog_p && catalog_p->isDictionary() ) {
// number of pages
+ /*
itext::PdfDictionary* pages_p= (itext::PdfDictionary*)
reader_p->getPdfObject( catalog_p->get( itext::PdfName::PAGES ) );
if( pages_p && pages_p->isDictionary() ) {
@@ -1147,6 +1213,8 @@
else { // error
cerr << "pdftk Error in ReportOnPdf(): invalid pages_p;" << endl;
}
+ */
+ ofs << "NumberOfPages: " << (unsigned int)numPages << endl;
// outlines; optional
itext::PdfDictionary* outlines_p= (itext::PdfDictionary*)
@@ -1157,7 +1225,7 @@
reader_p->getPdfObject( outlines_p->get( itext::PdfName::FIRST ) );
if( top_outline_p && top_outline_p->isDictionary() ) {
- ReportOutlines( ofs, top_outline_p, 0, reader_p, utf8_b );
+ ReportOutlines( ofs, top_outline_p, reader_p, utf8_b );
}
else { // error
// okay, not a big deal
@@ -1171,6 +1239,45 @@
}
}
+ { // page metrics, rotation
+ for( jint ii= 1; ii<= numPages; ++ii ) {
+ itext::PdfDictionary* page_p= reader_p->getPageN( ii );
+
+ ofs << PdfPageMedia::m_begin_mark << endl;
+ ofs << "PageMediaNumber: " << (unsigned int)ii << endl;
+
+ ofs << "PageMediaRotation: " << (unsigned int)(reader_p->getPageRotation( page_p )) << endl;
+
+ itext::Rectangle* page_rect_p= reader_p->getPageSize( page_p );
+ if( page_rect_p ) {
+ ofs << "PageMediaRect: "
+ << (float)(page_rect_p->left()) << " "
+ << (float)(page_rect_p->bottom()) << " "
+ << (float)(page_rect_p->right()) << " "
+ << (float)(page_rect_p->top()) << endl;
+ ofs << "PageMediaDimensions: "
+ << (float)(page_rect_p->right()- page_rect_p->left()) << " "
+ << (float)(page_rect_p->top()- page_rect_p->bottom()) << endl;
+ }
+
+ itext::Rectangle* page_crop_p= reader_p->getBoxSize( page_p, itext::PdfName::CROPBOX );
+ if( page_crop_p &&
+ !( page_crop_p->left()== page_rect_p->left() &&
+ page_crop_p->bottom()== page_rect_p->bottom() &&
+ page_crop_p->right()== page_rect_p->right() &&
+ page_crop_p->top()== page_rect_p->top() ) )
+ {
+ ofs << "PageMediaCropRect: "
+ << (float)(page_crop_p->left()) << " "
+ << (float)(page_crop_p->bottom()) << " "
+ << (float)(page_crop_p->right()) << " "
+ << (float)(page_crop_p->top()) << endl;
+ }
+
+ reader_p->releasePage( ii );
+ }
+ }
+
{ // page labels (a/k/a logical page numbers)
itext::PdfDictionary* catalog_p= reader_p->catalog;
if( catalog_p && catalog_p->isDictionary() ) {
@@ -1193,7 +1300,7 @@
//// import data to PDF
//
-static const char empty_string[]= ""; // TODO: maybe this should be pdftkEmptyString?
+static const char empty_string[]= "";
static const char*
BufferString( const char* buff, int buff_ii= 0 )
{
@@ -1209,9 +1316,10 @@
//while( buff[buff_ii] && isspace(buff[buff_ii]) ) { ++buff_ii; }
if( isspace( buff[buff_ii] ) ) // one or no spaces before data
++buff_ii;
- while( buff[buff_ii] ) {
+ while( buff[buff_ii] && '0'<= buff[buff_ii] && buff[buff_ii]<= '9' ) {
ret_val*= 10;
- ret_val+= (buff[buff_ii++]- '0');
+ ret_val+= (buff[buff_ii]- '0');
+ ++buff_ii;
}
return ret_val;
}
@@ -1220,11 +1328,11 @@
LoadString( string& ss, const char* buff, const char* label ) {
int label_len= strlen( label );
if( strncmp( buff, label, label_len )== 0 ) {
- if( ss== pdftkEmptyString ) {
+ if( ss== g_uninitString ) {
ss= BufferString( buff, label_len );
}
else { // warning
- cerr << "pdftk Warning: " << label << " (" << ss << ") not empty when reading new " << label << " (" << BufferString( buff, label_len ) << ") -- skipping newer item" << endl;
+ cerr << "pdftk Warning: " << label << " (" << ss << ") already loaded when reading new " << label << " (" << BufferString( buff, label_len ) << ") -- skipping newer item" << endl;
}
return true;
}
@@ -1347,6 +1455,12 @@
// TODO
}
+ // page media record
+ else if( strncmp( buff, PdfPageMedia::m_prefix.c_str(), PdfPageMedia::m_prefix.length() )== 0 ) {
+ buff_prev_len= 0;
+ // TODO
+ }
+
// pdf id
else if( strncmp( buff, "PdfID", 5 )== 0 ) {
buff_prev_len= 0; // not a record
@@ -1620,6 +1734,150 @@
return ret_val;
}
+// for use with writers, e.g. PdfCopy (esp. PdfCopy.setOutlines())
+int
+BuildBookmarks( itext::PdfWriter* writer_p,
+ vector::const_iterator& it,
+ vector::const_iterator it_end,
+ itext::PdfDictionary* parent_p,
+ itext::PdfIndirectReference* parent_ref_p,
+ itext::PdfDictionary* after_child_p,
+ itext::PdfIndirectReference* after_child_ref_p,
+ itext::PdfDictionary*& final_child_p,
+ itext::PdfIndirectReference*& final_child_ref_p,
+ int parent_level,
+ int& num_bookmarks_total,
+ int page_num_offset,
+ int level_offset,
+ bool utf8_b )
+{
+ int ret_val= 0;
+
+ // when using after_child, caller must
+ // call writer_p->addToBody( after_child_p, after_child_ref_p ) upon return
+ itext::PdfDictionary* bookmark_prev_p= after_child_p;
+ itext::PdfIndirectReference* bookmark_prev_ref_p= after_child_ref_p;
+
+ itext::PdfIndirectReference* bookmark_first_ref_p= 0;
+ int num_bookmarks= 0;
+
+ if( parent_level+ 1< it->m_level ) { // first child jumping levels
+
+ ////
+ // add missing level
+
+ ++num_bookmarks; ++num_bookmarks_total;
+ itext::PdfDictionary* bookmark_p= new itext::PdfDictionary();
+ itext::PdfIndirectReference* bookmark_ref_p= writer_p->getPdfIndirectReference();
+ bookmark_first_ref_p= bookmark_ref_p;
+
+ bookmark_p->put( itext::PdfName::PARENT, (itext::PdfObject*)parent_ref_p );
+
+ itext::PdfString* title_p= new itext::PdfString( JvNewStringUTF("") );
+ bookmark_p->put( itext::PdfName::TITLE, title_p );
+
+ bookmark_prev_p= bookmark_p;
+ bookmark_prev_ref_p= bookmark_ref_p;
+
+ // recurse in loop
+ }
+
+ for( ;it!= it_end; ++it ) {
+
+ if( parent_level+ 1< it->m_level ) { // encountered child; recurse
+ ret_val= BuildBookmarks( writer_p,
+ it,
+ it_end,
+ bookmark_prev_p, // parent
+ bookmark_prev_ref_p,
+ 0, 0,
+ final_child_p, final_child_ref_p,
+ parent_level+ 1,
+ num_bookmarks_total,
+ page_num_offset,
+ level_offset,
+ utf8_b );
+ --it;
+ continue;
+ }
+ else if( it->m_level< parent_level+ 1 ) {
+ break; // no more children; add children to parent and return
+ }
+
+ ////
+ // create child
+
+ ++num_bookmarks; ++num_bookmarks_total;
+ itext::PdfDictionary* bookmark_p= new itext::PdfDictionary();
+ itext::PdfIndirectReference* bookmark_ref_p= writer_p->getPdfIndirectReference();
+ if( !bookmark_first_ref_p )
+ bookmark_first_ref_p= bookmark_ref_p;
+
+ bookmark_p->put( itext::PdfName::PARENT, (itext::PdfObject*)parent_ref_p );
+
+ if( bookmark_prev_ref_p ) {
+ bookmark_p->put( itext::PdfName::PREV, (itext::PdfObject*)bookmark_prev_ref_p );
+ bookmark_prev_p->put( itext::PdfName::NEXT, (itext::PdfObject*)bookmark_ref_p );
+ }
+
+ if( utf8_b ) { // UTF-8 encoded input
+ bookmark_p->put( itext::PdfName::TITLE,
+ new itext::PdfString( JvNewStringUTF(it->m_title.c_str()) /*,
+ itext::PdfObject::TEXT_UNICODE*/ ) );
+ }
+ else { // XML entities input
+ const jsize jvs_size= 4096;
+ jchar jvs[jvs_size];
+ jsize jvs_len= 0;
+ XmlStringToJcharArray( jvs, jvs_size, &jvs_len, it->m_title );
+
+ bookmark_p->put( itext::PdfName::TITLE,
+ new itext::PdfString( JvNewString(jvs, jvs_len) /*,
+ itext::PdfObject::TEXT_UNICODE*/ ) );
+ }
+
+ if( 0< it->m_page_num ) { // destination
+ itext::PdfDestination* dest_p= new itext::PdfDestination(itext::PdfDestination::FIT);
+ itext::PdfIndirectReference* page_ref_p=
+ writer_p->getPageReference( it->m_page_num+ page_num_offset );
+ if( page_ref_p ) {
+ dest_p->addPage( (itext::PdfIndirectReference*)page_ref_p );
+ }
+ bookmark_p->put( itext::PdfName::DEST, dest_p );
+ }
+
+ // finished with prev; add to body
+ if( bookmark_prev_p )
+ writer_p->addToBody( bookmark_prev_p, bookmark_prev_ref_p );
+
+ bookmark_prev_p= bookmark_p;
+ bookmark_prev_ref_p= bookmark_ref_p;
+ }
+
+ // finished with prev; add to body (unless we're appending)
+ if( bookmark_prev_p && !after_child_p )
+ writer_p->addToBody( bookmark_prev_p, bookmark_prev_ref_p );
+
+ if( bookmark_first_ref_p && bookmark_prev_ref_p ) {
+ // pack these children into parent before returning
+ if( !parent_p->contains( itext::PdfName::FIRST ) ) // in case we're appending
+ parent_p->put( itext::PdfName::FIRST, (itext::PdfObject*)bookmark_first_ref_p );
+ parent_p->put( itext::PdfName::LAST, (itext::PdfObject*)bookmark_prev_ref_p );
+ if( parent_level== 0 ) { // only for top-level "outlines" dict
+ parent_p->put( itext::PdfName::COUNT, new itext::PdfNumber( (jint)num_bookmarks_total ) );
+ }
+ else {
+ parent_p->put( itext::PdfName::COUNT, new itext::PdfNumber( (jint)num_bookmarks ) );
+ }
+ }
+
+ // pass back to calling function so it can call BuildBookmarks serially
+ final_child_p= bookmark_prev_p;
+ final_child_ref_p= bookmark_prev_ref_p;
+
+ return ret_val;
+}
+
bool
UpdateInfo( itext::PdfReader* reader_p,
istream& ifs,
@@ -1639,13 +1897,14 @@
// build bookmarks
itext::PdfDictionary* outlines_p= new itext::PdfDictionary( itext::PdfName::OUTLINES );
- itext::PRIndirectReference* outlines_ref_p= reader_p->getPRIndirectReference( outlines_p );
if( outlines_p ) {
+ itext::PRIndirectReference* outlines_ref_p= reader_p->getPRIndirectReference( outlines_p );
- vector::const_iterator bit= pdf_data.m_bookmarks.begin();
int num_bookmarks_total= 0;
+ // passed in by reference, so must use variable:
+ vector::const_iterator vit= pdf_data.m_bookmarks.begin();
BuildBookmarks( reader_p,
- bit,
+ vit,
pdf_data.m_bookmarks.end(),
outlines_p,
outlines_ref_p,
@@ -1716,6 +1975,248 @@
return ret_val_b;
}
+void
+ReportAction( ostream& ofs,
+ itext::PdfReader* reader_p,
+ itext::PdfDictionary* action_p,
+ bool utf8_b, string prefix )
+{
+ if( action_p->contains( itext::PdfName::S ) ) {
+ itext::PdfName* s_p= (itext::PdfName*)
+ reader_p->getPdfObject( action_p->get( itext::PdfName::S ) );
+
+ // URI action
+ if( s_p->equals( itext::PdfName::URI ) ) {
+ ofs << prefix << "ActionSubtype: URI" << endl;
+
+ // report URI
+ if( action_p->contains( itext::PdfName::URI ) ) {
+ itext::PdfString* uri_p= (itext::PdfString*)
+ reader_p->getPdfObject( action_p->get( itext::PdfName::URI ) );
+ if( uri_p && uri_p->isString() ) {
+
+ ofs << prefix << "ActionURI: ";
+ OutputPdfString( ofs, uri_p, utf8_b );
+ ofs << endl;
+ }
+ }
+
+ // report IsMap
+ if( action_p->contains( itext::PdfName::ISMAP ) ) {
+ itext::PdfBoolean* ismap_p= (itext::PdfBoolean*)
+ reader_p->getPdfObject( action_p->get( itext::PdfName::ISMAP ) );
+ if( ismap_p && ismap_p->isBoolean() )
+ if( ismap_p->booleanValue() )
+ ofs << prefix << "ActionIsMap: true" << endl;
+ else
+ ofs << prefix << "ActionIsMap: false" << endl;
+ }
+ else
+ ofs << prefix << "ActionIsMap: false" << endl;
+ }
+ }
+
+ // subsequent actions? can be a single action or an array
+ if( action_p->contains( itext::PdfName::NEXT ) ) {
+ itext::PdfObject* next_p= reader_p->getPdfObject( action_p->get( itext::PdfName::NEXT ) );
+ if( next_p->isDictionary() ) {
+ ReportAction( ofs, reader_p, (itext::PdfDictionary*)next_p, utf8_b, prefix );
+ }
+ else if( next_p->isArray() ) {
+ java::ArrayList* actions_p= ((itext::PdfArray*)next_p)->getArrayList();
+ for( jint ii= 0; ii< actions_p->size(); ++ii ) {
+ itext::PdfDictionary* action_p= (itext::PdfDictionary*)
+ reader_p->getPdfObject( (itext::PdfObject*)actions_p->get(ii) );
+ if( action_p && action_p->isDictionary() )
+ ReportAction( ofs, reader_p, action_p, utf8_b, prefix ); // recurse
+ }
+ }
+ }
+}
+
+static const int LLx= 0;
+static const int LLy= 1;
+static const int URx= 2;
+static const int URy= 3;
+
+void
+ReportAnnot( ostream& ofs,
+ itext::PdfReader* reader_p,
+ int page_num,
+ itext::PdfDictionary* page_p,
+ itext::PdfDictionary* annot_p,
+ bool utf8_b )
+{
+ // report things common to all annots
+
+ // subtype
+ itext::PdfName* subtype_p= (itext::PdfName*)
+ reader_p->getPdfObject( annot_p->get( itext::PdfName::SUBTYPE ) );
+ if( subtype_p && subtype_p->isName() ) {
+ ofs << "AnnotSubtype: ";
+ OutputPdfName( ofs, subtype_p );
+ ofs << endl;
+ }
+
+ ////
+ // rect
+
+ // get raw rect from annot
+ float rect[4]= { 0.0, 0.0, 0.0, 0.0 };
+ itext::PdfArray* rect_p= (itext::PdfArray*)
+ reader_p->getPdfObject( annot_p->get( itext::PdfName::RECT ) );
+ if( rect_p && rect_p->isArray() ) {
+ java::ArrayList* rect_al_p= rect_p->getArrayList();
+ if( rect_al_p && rect_al_p->size()== 4 ) {
+
+ for( jint ii= 0; ii< 4; ++ii ) {
+ itext::PdfNumber* coord_p= (itext::PdfNumber*)
+ reader_p->getPdfObject( (itext::PdfObject*)(rect_al_p->get( ii ) ) );
+ if( coord_p && coord_p->isNumber() )
+ rect[ ii ]= (float)coord_p->floatValue();
+ else
+ rect[ ii ]= -1; // error value
+ }
+ }
+ }
+
+ // transform rect according to page crop box
+ // grab width and height for later xform
+ float page_crop_width= 0;
+ float page_crop_height= 0;
+ {
+ itext::Rectangle* page_crop_p= reader_p->getCropBox( page_num );
+ rect[0]= rect[0]- page_crop_p->left();
+ rect[1]= rect[1]- page_crop_p->bottom();
+ rect[2]= rect[2]- page_crop_p->left();
+ rect[3]= rect[3]- page_crop_p->bottom();
+
+ page_crop_width= (float)(page_crop_p->right()- page_crop_p->left());
+ page_crop_height= (float)(page_crop_p->top()- page_crop_p->bottom());
+ }
+
+ // create new rect based on page rotation
+ int page_rot= (int)(reader_p->getPageRotation( page_num )) % 360;
+ float rot_rect[4]= { 0.0, 0.0, 0.0, 0.0 };
+ switch( page_rot ) {
+
+ case 90:
+ rot_rect[0]= rect[LLy];
+ rot_rect[1]= page_crop_width- rect[URx];
+ rot_rect[2]= rect[URy];
+ rot_rect[3]= page_crop_width- rect[LLx];
+ break;
+
+ case 180:
+ rot_rect[0]= page_crop_width- rect[URx];
+ rot_rect[1]= page_crop_height- rect[URy];
+ rot_rect[2]= page_crop_width- rect[LLx];
+ rot_rect[3]= page_crop_height- rect[LLy];
+ break;
+
+ case 270:
+ rot_rect[0]= page_crop_height- rect[URy];
+ rot_rect[1]= rect[LLx];
+ rot_rect[2]= page_crop_height- rect[LLy];
+ rot_rect[3]= rect[URx];
+ break;
+
+ default: // 0 deg
+ rot_rect[0]= rect[0];
+ rot_rect[1]= rect[1];
+ rot_rect[2]= rect[2];
+ rot_rect[3]= rect[3];
+ break;
+ }
+
+ // output rotated rect
+ ofs << "AnnotRect: " << rot_rect[0] << " " << rot_rect[1];
+ ofs << " " << rot_rect[2] << " " << rot_rect[3] << endl;
+
+}
+
+void
+ReportAnnots( ostream& ofs,
+ itext::PdfReader* reader_p,
+ bool utf8_b )
+{
+ reader_p->resetReleasePage();
+
+ ////
+ // document information
+
+ // document page count
+ ofs << "NumberOfPages: " << (int)reader_p->getNumberOfPages() << endl;
+
+ // document base url
+ itext::PdfDictionary* uri_p= (itext::PdfDictionary*)
+ reader_p->getPdfObject( reader_p->catalog->get( itext::PdfName::URI ) );
+ if( uri_p && uri_p->isDictionary() ) {
+
+ itext::PdfString* base_p= (itext::PdfString*)
+ reader_p->getPdfObject( uri_p->get( itext::PdfName::BASE ) );
+ if( base_p && base_p->isString() ) {
+ ofs << "PdfUriBase: ";
+ OutputPdfString( ofs, base_p, utf8_b );
+ ofs << endl;
+ }
+ }
+
+ ////
+ // iterate over pages
+
+ for( jint ii= 1; ii<= reader_p->getNumberOfPages(); ++ii ) {
+ itext::PdfDictionary* page_p= reader_p->getPageN( ii );
+
+ itext::PdfArray* annots_p= (itext::PdfArray*)
+ reader_p->getPdfObject( page_p->get( itext::PdfName::ANNOTS ) );
+ if( annots_p && annots_p->isArray() ) {
+
+ java::ArrayList* annots_al_p= annots_p->getArrayList();
+ if( annots_al_p ) {
+
+ // iterate over annotations
+ for( jint jj= 0; jj< annots_al_p->size(); ++jj ) {
+
+ itext::PdfDictionary* annot_p= (itext::PdfDictionary*)
+ reader_p->getPdfObject( (itext::PdfObject*)annots_al_p->get( jj ) );
+ if( annot_p && annot_p->isDictionary() ) {
+
+ itext::PdfName* type_p= (itext::PdfName*)
+ reader_p->getPdfObject( annot_p->get( itext::PdfName::TYPE ) );
+ if( type_p->equals( itext::PdfName::ANNOT ) ) {
+
+ itext::PdfName* subtype_p= (itext::PdfName*)
+ reader_p->getPdfObject( annot_p->get( itext::PdfName::SUBTYPE ) );
+
+ // link annotation
+ if( subtype_p->equals( itext::PdfName::LINK ) ) {
+
+ ofs << "---" << endl; // delim
+ ReportAnnot( ofs, reader_p, (int)ii, page_p, annot_p, utf8_b ); // base annot items
+ ofs << "AnnotPageNumber: " << (int)ii << endl;
+
+ // link-specific items
+ if( annot_p->contains( itext::PdfName::A ) ) { // action
+ itext::PdfDictionary* action_p= (itext::PdfDictionary*)
+ reader_p->getPdfObject( annot_p->get( itext::PdfName::A ) );
+ if( action_p && action_p->isDictionary() ) {
+
+ ReportAction( ofs, reader_p, action_p, utf8_b, "Annot" );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ reader_p->releasePage( ii );
+ }
+ reader_p->resetReleasePage();
+}
+
+
/*
static bool
diff -Nru pdftk-1.45/pdftk/report.h pdftk-2.01/pdftk/report.h
--- pdftk-1.45/pdftk/report.h 2010-10-27 12:22:18.000000000 +0000
+++ pdftk-2.01/pdftk/report.h 2013-05-22 08:22:10.000000000 +0000
@@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 2; c-basic-offset: 2 -*- */
/*
pdftk, the PDF Toolkit
- Copyright (c) 2003, 2004, 2010 Sid Steward
+ Copyright (c) 2003, 2004, 2010, 2013 Sid Steward
This program is free software; you can redistribute it and/or modify
@@ -33,6 +33,11 @@
bool utf8_b );
void
+ReportAnnots( ostream& ofs,
+ itext::PdfReader* reader_p,
+ bool utf8_b );
+
+void
ReportOnPdf( ostream& ofs,
itext::PdfReader* reader_p,
bool utf8_b );
@@ -42,6 +47,49 @@
istream& ifs,
bool utf8_b );
+//
+class PdfBookmark {
+public:
+ static const string m_prefix;
+ static const string m_begin_mark;
+ static const string m_title_label;
+ static const string m_level_label;
+ static const string m_page_number_label;
+ //static const string m_empty_string;
+
+ string m_title;
+ int m_level;
+ int m_page_num; // zero means no destination
+
+ PdfBookmark();
+ bool valid();
+};
+//
+ostream& operator<<( ostream& ss, const PdfBookmark& bb );
+
+int
+ReadOutlines( vector& bookmark_data,
+ itext::PdfDictionary* outline_p,
+ int level,
+ itext::PdfReader* reader_p,
+ bool utf8_b );
+
+int
+BuildBookmarks( itext::PdfWriter* writer_p,
+ vector::const_iterator& it,
+ vector::const_iterator it_end,
+ itext::PdfDictionary* parent_p,
+ itext::PdfIndirectReference* parent_ref_p,
+ itext::PdfDictionary* after_child_p,
+ itext::PdfIndirectReference* after_child_ref_p,
+ itext::PdfDictionary*& final_child_p,
+ itext::PdfIndirectReference*& final_child_ref_p,
+ int parent_level,
+ int& num_bookmarks_total,
+ int page_num_offset,
+ int level_offset,
+ bool utf8_b );
+
/* not fully implemented, yet
bool
diff -Nru pdftk-1.45/pdftk.1 pdftk-2.01/pdftk.1
--- pdftk-1.45/pdftk.1 2012-12-06 10:33:42.000000000 +0000
+++ pdftk-2.01/pdftk.1 2013-05-24 19:20:12.000000000 +0000
@@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
-.TH PDFTK 1 "December 6, 2012"
+.TH PDFTK 1 "May 22, 2013"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@@ -35,7 +35,9 @@
.br
[ \fBuser_pw\fR \fI\fR ]
.br
- [ \fBflatten\fR ] [ \fBcompress\fR | \fBuncompress\fR ]
+ [ \fBflatten\fR ] [ \fBneed_appearances\fR ]
+.br
+ [ \fBcompress\fR | \fBuncompress\fR ]
.br
[ \fBkeep_first_id\fR | \fBkeep_final_id\fR ] [ \fBdrop_xfa\fR ]
.br
@@ -45,7 +47,7 @@
.br
\fI\fR may be empty, or:
.br
- [ \fBcat\fR | \fBshuffle\fR | \fBburst\fR |
+ [ \fBcat\fR | \fBshuffle\fR | \fBburst\fR | \fBrotate\fR |
.br
\fBgenerate_fdf\fR | \fBfill_form\fR |
.br
@@ -57,6 +59,8 @@
.br
\fBdump_data_fields\fR | \fBdump_data_fields_utf8\fR |
.br
+ \fBdump_data_annots\fR |
+.br
\fBupdate_info\fR | \fBupdate_info_utf8\fR |
.br
\fBattach_files\fR | \fBunpack_files\fR ]
@@ -134,10 +138,10 @@
if the supplied password is incorrect or none was given.
.TP
.B [ ]
-Available operations are: \fBcat\fR, \fBshuffle\fR, \fBburst\fR,
+Available operations are: \fBcat\fR, \fBshuffle\fR, \fBburst\fR, \fBrotate\fR,
\fBgenerate_fdf\fR, \fBfill_form\fR, \fBbackground\fR, \fBmultibackground\fR,
\fBstamp\fR, \fBmultistamp\fR, \fBdump_data\fR, \fBdump_data_utf8\fR,
-\fBdump_data_fields\fR, \fBdump_data_fields_utf8\fR, \fBupdate_info\fR,
+\fBdump_data_fields\fR, \fBdump_data_fields_utf8\fR, \fBdump_data_annots\fR, \fBupdate_info\fR,
\fBupdate_info_utf8\fR, \fBattach_files\fR, \fBunpack_files\fR. Some operations
takes additional arguments, described below.
@@ -147,9 +151,7 @@
.RS 3
.TP
.B cat []
-Assembles (catenates) pages from input PDFs to create a new PDF.
-Page order in the new PDF is specified by the order of the given page ranges.
-Page ranges are described like this:
+Assembles (catenates) pages from input PDFs to create a new PDF. Use \fBcat\fR to merge PDF pages or to split PDF pages from documents. You can also use it to rotate PDF pages. Page order in the new PDF is specified by the order of the given page ranges. Page ranges are described like this:
\fI \fR[\fI\fR[\fB-\fR\fI\fR[\fI\fR]]][\fI\fR]
@@ -158,6 +160,8 @@
to pages in the PDF file.
The qualifier can be \fBeven\fR or \fBodd\fR, and the page rotation can be \fBnorth\fR, \fBsouth\fR, \fBeast\fR, \fBwest\fR, \fBleft\fR, \fBright\fR, or \fBdown\fR.
+If a PDF handle is given but no pages are specified, then the entire PDF is used. If no pages are specified for any of the input PDFs, then the input PDFs' bookmarks are also merged and included in the output.
+
If the handle is omitted from the page range, then the pages are taken from the first input PDF.
The \fBeven\fR qualifier causes pdftk to use only the even-numbered PDF pages, so \fB1-6even\fR yields pages 2, 4 and 6 in that order. \fB6-1even\fR yields pages 6, 4 and 2 in that order.
@@ -219,7 +223,7 @@
Collates pages from input PDFs to create a new PDF. Works like the \fBcat\fR operation except that it takes one page at a time from each page range to assemble the output PDF. If one range runs out of pages, it continues with the remaining ranges. Ranges can use all of the features described above for \fBcat\fR, like reverse page ranges, multiple ranges from a single PDF, and page rotation. This feature was designed to help collate PDF pages after scanning paper documents.
.TP
.B burst
-Splits a single, input PDF document into individual pages. Also creates a
+Splits a single input PDF document into individual pages. Also creates a
report named \fBdoc_data.txt\fR which is the same as the output from \fBdump_data\fR.
If the \fBoutput\fR section is omitted, then PDF pages are named: pg_%04d.pdf,
e.g.: pg_0001.pdf, pg_0002.pdf, etc. To name these pages yourself, supply a
@@ -229,8 +233,19 @@
pdftk in.pdf burst owner_pw foopass
.TP
+.B rotate []
+Takes a single input PDF and rotates just the specified pages. All other pages remain unchanged. The page order remains unchaged. Specify the pages to rotate using the same notation as you would with \fBcat\fR, except you omit the pages that you aren't rotating:
+
+[\fI\fR[\fB-\fR\fI\fR[\fI\fR]]][\fI\fR]
+
+The qualifier can be \fBeven\fR or \fBodd\fR, and the page rotation can be \fBnorth\fR, \fBsouth\fR, \fBeast\fR, \fBwest\fR, \fBleft\fR, \fBright\fR, or \fBdown\fR.
+
+Each option sets the page rotation as follows (in degrees): \fBnorth\fR: 0, \fBeast\fR: 90, \fBsouth\fR: 180, \fBwest\fR: 270, \fBleft\fR: -90, \fBright\fR: +90, \fBdown\fR: +180. \fBleft\fR, \fBright\fR, and \fBdown\fR make relative adjustments to a page's rotation.
+
+The given order of the pages doesn't change the page order in the output.
+.TP
.B generate_fdf
-Reads a single, input PDF file and generates an FDF file suitable for \fBfill_form\fR
+Reads a single input PDF file and generates an FDF file suitable for \fBfill_form\fR
out of it to the given output
filename or (if no output is given) to stdout. Does not create a new PDF.
.TP
@@ -240,23 +255,15 @@
pdftk form.pdf fill_form data.fdf output form.filled.pdf
-After filling a form, the form fields remain interactive unless you also use the \fBflatten\fR
-output option. \fBflatten\fR merges the form fields with the PDF pages. You can use \fBflatten\fR
-alone, too, but only on a single PDF:
-
-pdftk form.pdf fill_form data.fdf output out.pdf flatten
-
-or:
-
-pdftk form.filled.pdf output out.pdf flatten
-
If the input FDF file includes Rich Text formatted data in addition to plain text, then the
Rich Text data is packed into the form fields \fIas well as\fR the plain text. Pdftk also sets a flag
-that cues Acrobat/Reader to generate new field appearances based on the Rich Text data. That way,
-when the user opens the PDF, the viewer will create the Rich Text fields on the spot. If the
+that cues Reader/Acrobat to generate new field appearances based on the Rich Text data. So
+when the user opens the PDF, the viewer will create the Rich Text appearance on the spot. If the
user's PDF viewer does not support Rich Text, then the user will see the plain text data instead.
If you flatten this form before Acrobat has a chance to create (and save) new field appearances,
then the plain text field data is what you'll see.
+
+Also see the \fBflatten\fR and \fBneed_appearances\fR options.
.TP
.B background
Applies a PDF watermark to the background of a single input PDF. Pass the background PDF's
@@ -280,22 +287,25 @@
Same as the \fBstamp\fR operation, but applies each page of the background PDF to the corresponding page of the input PDF. If the input PDF has more pages than the stamp PDF, then the final stamp page is repeated across these remaining pages in the input PDF.
.TP
.B dump_data
-Reads a single, input PDF file and reports various statistics,
-metadata, bookmarks (a/k/a outlines), and page labels to the given output
-filename or (if no output is given) to stdout. Non-ASCII characters are encoded
-as XML numerical entities. Does not create a new PDF.
+Reads a single input PDF file and reports its metadata, bookmarks (a/k/a outlines), page metrics (media, rotation and labels) and other data to the given output filename or (if no output is given) to stdout. Non-ASCII characters are encoded as XML numerical entities. Does not create a new PDF.
.TP
.B dump_data_utf8
Same as \fBdump_data\fR excepct that the output is encoded as UTF-8.
.TP
.B dump_data_fields
-Reads a single, input PDF file and reports form field statistics to the given output
+Reads a single input PDF file and reports form field statistics to the given output
filename or (if no output is given) to stdout. Non-ASCII characters are encoded
as XML numerical entities. Does not create a new PDF.
.TP
.B dump_data_fields_utf8
Same as \fBdump_data_fields\fR excepct that the output is encoded as UTF-8.
.TP
+.B dump_data_annots
+\fBThis operation currently reports only link annotations.\fR
+Reads a single input PDF file and reports annotation information to the given output
+filename or (if no output is given) to stdout. Non-ASCII characters are encoded
+as XML numerical entities. Does not create a new PDF.
+.TP
.B update_info
Changes the bookmarks and metadata in a single PDF's Info dictionary to match
the input data file. The input data file uses the same syntax as the
@@ -392,6 +402,9 @@
Use this option to merge an input PDF's interactive form fields (and their data) with
the PDF's pages. Only one input PDF may be given. Sometimes used with the \fBfill_form\fR operation.
.TP
+.B [need_appearances]
+Sets a flag that cues Reader/Acrobat to generate new field appearances based on the form field values. Use this when filling a form with non-ASCII text to ensure the best presentation in Adobe Reader or Acrobat. It won't work when combined with the \fBflatten\fR option.
+.TP
.B [keep_first_id | keep_final_id]
When combining pages from multiple PDFs, use one of these options to copy the document ID from either the first or final input document into the new output PDF. Otherwise pdftk creates a new document ID for the output PDF. When no operation is given, pdftk always uses the ID from the (single) input PDF.
.TP
diff -Nru pdftk-1.45/pdftk.1.html pdftk-2.01/pdftk.1.html
--- pdftk-1.45/pdftk.1.html 2012-12-06 10:36:20.000000000 +0000
+++ pdftk-2.01/pdftk.1.html 2013-05-24 19:17:22.000000000 +0000
@@ -1,776 +1,826 @@
-
-
-
-
-
-
-
-
-
-PDFTK
-
-
-
-
-PDFTK
-
-NAME
-SYNOPSIS
-DESCRIPTION
-OPTIONS
-EXAMPLES
-NOTES
-AUTHOR
-
-
-
-
-NAME
-
-
-
-
-pdftk − A
-handy tool for manipulating PDF
-
-SYNOPSIS
-
-
-
-
-pdftk
-<input PDF files | - | PROMPT>
-[ input_pw <input PDF owner passwords |
-PROMPT> ]
-[ <operation> <operation arguments> ]
-
-[ output <output filename | - | PROMPT>
-]
-[ encrypt_40bit | encrypt_128bit ]
-[ allow <permissions> ]
-[ owner_pw <owner password | PROMPT> ]
-
-[ user_pw <user password | PROMPT> ]
-
-[ flatten ] [ compress | uncompress ]
-
-[ keep_first_id | keep_final_id ] [
-drop_xfa ]
-[ verbose ] [ dont_ask | do_ask ]
-Where:
-<operation> may be empty, or:
-[ cat | shuffle | burst |
-generate_fdf | fill_form |
-background | multibackground |
-stamp | multistamp |
-dump_data | dump_data_utf8 |
-dump_data_fields | dump_data_fields_utf8 |
-
-update_info | update_info_utf8 |
-attach_files | unpack_files ]
-
-For Complete
-Help: pdftk --help
-
-DESCRIPTION
-
-
-
-
-If PDF is
-electronic paper, then pdftk is an electronic
-staple-remover, hole-punch, binder, secret-decoder-ring, and
-X-Ray-glasses. Pdftk is a simple tool for doing everyday
-things with PDF documents. Use it to:
-
-* Merge PDF
-Documents or Collate PDF Page Scans
-* Split PDF Pages into a New Document
-* Rotate PDF Documents or Pages
-* Decrypt Input as Necessary (Password Required)
-* Encrypt Output as Desired
-* Fill PDF Forms with X/FDF Data and/or Flatten Forms
-* Generate FDF Data Stencils from PDF Forms
-* Apply a Background Watermark or a Foreground Stamp
-* Report PDF Metrics, Bookmarks and Metadata
-* Add/Update PDF Bookmarks or Metadata
-* Attach Files to PDF Pages or the PDF Document
-* Unpack PDF Attachments
-* Burst a PDF Document into Single Pages
-* Uncompress and Re-Compress Page Streams
-* Repair Corrupted PDF (Where Possible)
-
-OPTIONS
-
-
-
-
-A summary of
-options is included below.
-−−help , −h
-
-Show this summary of
-options.
-
-<input PDF files | - |
-PROMPT>
-
-A list of the input PDF files.
-If you plan to combine these PDFs (without using handles)
-then list files in the order you want them combined. Use
-- to pass a single PDF into pdftk via stdin. Input
-files can be associated with handles, where a handle is one
-or more upper-case letters:
-
-<input
-PDF handle> = <input PDF
-filename>
-
-Handles are
-often omitted. They are useful when specifying PDF passwords
-or page ranges, later.
-
-For example:
-A=input1.pdf QT=input2.pdf M=input3.pdf
-
-[input_pw <input PDF
-owner passwords | PROMPT>]
-
-Input PDF owner passwords, if
-necessary, are associated with files by using their
-handles:
-
-<input
-PDF handle> = <input PDF file owner
-password>
-
-If handles are
-not given, then passwords are associated with input files by
-order.
-
-Most pdftk
-features require that encrypted input PDF are accompanied by
-the ~owner~ password. If the input PDF has no owner
-password, then the user password must be given, instead. If
-the input PDF has no passwords, then no password should be
-given.
-
-When running in
-do_ask mode, pdftk will prompt you for a password if
-the supplied password is incorrect or none was given.
-
-[<operation>
-<operation arguments>]
-
-Available operations are:
-cat , shuffle , burst ,
-generate_fdf , fill_form , background ,
-multibackground , stamp , multistamp ,
-dump_data , dump_data_utf8 ,
-dump_data_fields , dump_data_fields_utf8 ,
-update_info , update_info_utf8 ,
-attach_files , unpack_files . Some operations
-takes additional arguments, described below.
-
-If this
-optional argument is omitted, then pdftk runs in
-’filter’ mode. Filter mode takes only one PDF
-input and creates a new PDF after applying all of the output
-options, like encryption and compression.
-
-cat [<page
-ranges>]
-
-Assembles (catenates) pages
-from input PDFs to create a new PDF. Page order in the new
-PDF is specified by the order of the given page ranges. Page
-ranges are described like this:
-
-<input
-PDF handle> [<begin page
-number> [- <end page
-number> [<qualifier> ]]][<page
-rotation> ]
-
-Where the
-handle identifies one of the input PDF files, and the
-beginning and ending page numbers are one-based references
-to pages in the PDF file. The qualifier can be even
-or odd , and the page rotation can be north ,
-south , east , west , left ,
-right , or down .
-
-If the handle
-is omitted from the page range, then the pages are taken
-from the first input PDF.
-
-The even
-qualifier causes pdftk to use only the even-numbered PDF
-pages, so 1-6even yields pages 2, 4 and 6 in that
-order. 6-1even yields pages 6, 4 and 2 in that
-order.
-
-The odd
-qualifier works similarly to the even .
-
-The page
-rotation setting can cause pdftk to rotate pages and
-documents. Each option sets the page rotation as follows (in
-degrees): north : 0, east : 90, south :
-180, west : 270, left : -90, right : +90,
-down : +180. left , right , and
-down make relative adjustments to a page’s
-rotation.
-
-If no arguments
-are passed to cat, then pdftk combines all input PDFs in the
-order they were given to create the output.
-
-NOTES:
-
-* <end page number> may be less than
-<begin page number> .
-* The keyword end may be used to reference the final
-page of a document instead of a page number.
-* Reference a single page by omitting the ending page
-number.
-* The handle may be used alone to represent the entire PDF
-document, e.g., B1-end is the same as B.
-* You can reference page numbers in reverse order by
-prefixing them with the letter r . For example, page
-r1 is the last page of the document, r2 is the next-to-last
-page of the document, and rend is the first page of the
-document. You can use this prefix in ranges, too, for
-example r3-r1 is the last three pages of a PDF.
-
-Page Range
-Examples without Handles:
-1-endeast - rotate entire document 90 degrees
-5 11 20 - take single pages from input PDF
-5-25oddwest - take odd pages in range, rotate 90 degrees
-
-6-1 - reverse pages in range from input PDF
-
-Page Range
-Examples Using Handles:
-Say A=in1.pdf B=in2.pdf , then:
-A1-21 - take range from in1.pdf
-Bend-1odd - take all odd pages from in2.pdf in reverse
-order
-A72 - take a single page from in1.pdf
-A1-21 Beven A72 - assemble pages from both in1.pdf and
-in2.pdf
-Awest - rotate entire in1.pdf document 90 degrees
-
-B - use all of in2.pdf
-A2-30evenleft - take the even pages from the range,
-remove 90 degrees from each page’s rotation
-A A - catenate in1.pdf with in1.pdf
-Aevenwest Aoddeast - apply rotations to even pages, odd
-pages from in1.pdf
-Awest Bwest Bdown - catenate rotated documents
-
-shuffle [<page
-ranges>]
-
-Collates pages from input PDFs
-to create a new PDF. Works like the cat operation
-except that it takes one page at a time from each page range
-to assemble the output PDF. If one range runs out of pages,
-it continues with the remaining ranges. Ranges can use all
-of the features described above for cat , like reverse
-page ranges, multiple ranges from a single PDF, and page
-rotation. This feature was designed to help collate PDF
-pages after scanning paper documents.
-
-
-
-
-
-
-
-burst
-
-
-
-
-Splits a single, input PDF document into individual
-pages. Also creates a report named doc_data.txt which
-is the same as the output from dump_data . If the
-output section is omitted, then PDF pages are named:
-pg_%04d.pdf, e.g.: pg_0001.pdf, pg_0002.pdf, etc. To name
-these pages yourself, supply a printf-styled format string
-via the output section. For example, if you want
-pages named: page_01.pdf, page_02.pdf, etc., pass output
-page_%02d.pdf to pdftk. Encryption can be applied to the
-output by appending output options such as owner_pw ,
-e.g.:
-
-
-pdftk in.pdf
-burst owner_pw foopass
-
-generate_fdf
-
-Reads a single, input PDF file
-and generates an FDF file suitable for fill_form out
-of it to the given output filename or (if no output is
-given) to stdout. Does not create a new PDF.
-
-fill_form <FDF data
-filename | XFDF data filename | - | PROMPT>
-
-Fills the single input
-PDF’s form fields with the data from an FDF file, XFDF
-file or stdin. Enter the data filename after
-fill_form , or use - to pass the data via
-stdin, like so:
-
-pdftk form.pdf
-fill_form data.fdf output form.filled.pdf
-
-After filling a
-form, the form fields remain interactive unless you also use
-the flatten output option. flatten merges the
-form fields with the PDF pages. You can use flatten
-alone, too, but only on a single PDF:
-
-pdftk form.pdf
-fill_form data.fdf output out.pdf flatten
-
-or:
-
-pdftk
-form.filled.pdf output out.pdf flatten
-
-If the input
-FDF file includes Rich Text formatted data in addition to
-plain text, then the Rich Text data is packed into the form
-fields as well as the plain text. Pdftk also sets a
-flag that cues Acrobat/Reader to generate new field
-appearances based on the Rich Text data. That way, when the
-user opens the PDF, the viewer will create the Rich Text
-fields on the spot. If the user’s PDF viewer does not
-support Rich Text, then the user will see the plain text
-data instead. If you flatten this form before Acrobat has a
-chance to create (and save) new field appearances, then the
-plain text field data is what you’ll see.
-
-background <background
-PDF filename | - | PROMPT>
-
-Applies a PDF watermark to the
-background of a single input PDF. Pass the background
-PDF’s filename after background like so:
-
-pdftk in.pdf
-background back.pdf output out.pdf
-
-Pdftk uses only
-the first page from the background PDF and applies it to
-every page of the input PDF. This page is scaled and rotated
-as needed to fit the input page. You can use - to
-pass a background PDF into pdftk via stdin.
-
-If the input
-PDF does not have a transparent background (such as a PDF
-created from page scans) then the resulting background
-won’t be visible -- use the stamp operation
-instead.
-
-multibackground
-<background PDF filename | - | PROMPT>
-
-Same as the background
-operation, but applies each page of the background PDF to
-the corresponding page of the input PDF. If the input PDF
-has more pages than the stamp PDF, then the final stamp page
-is repeated across these remaining pages in the input
-PDF.
-
-stamp <stamp PDF filename
-| - | PROMPT>
-
-This behaves just like the
-background operation except it overlays the stamp PDF
-page on top of the input PDF document’s pages.
-This works best if the stamp PDF page has a transparent
-background.
-
-multistamp <stamp PDF
-filename | - | PROMPT>
-
-Same as the stamp
-operation, but applies each page of the background PDF to
-the corresponding page of the input PDF. If the input PDF
-has more pages than the stamp PDF, then the final stamp page
-is repeated across these remaining pages in the input
-PDF.
-
-dump_data
-
-Reads a single, input PDF file
-and reports various statistics, metadata, bookmarks (a/k/a
-outlines), and page labels to the given output filename or
-(if no output is given) to stdout. Non-ASCII characters are
-encoded as XML numerical entities. Does not create a new
-PDF.
-
-dump_data_utf8
-
-Same as dump_data
-excepct that the output is encoded as UTF-8.
-
-dump_data_fields
-
-Reads a single, input PDF file
-and reports form field statistics to the given output
-filename or (if no output is given) to stdout. Non-ASCII
-characters are encoded as XML numerical entities. Does not
-create a new PDF.
-
-
-dump_data_fields_utf8
-
-Same as dump_data_fields
-excepct that the output is encoded as UTF-8.
-
-update_info <info data
-filename | - | PROMPT>
-
-Changes the bookmarks and
-metadata in a single PDF’s Info dictionary to match
-the input data file. The input data file uses the same
-syntax as the output from dump_data . Non-ASCII
-characters should be encoded as XML numerical entities. This
-does not change the metadata stored in the PDF’s XMP
-stream, if it has one. For example:
-
-pdftk in.pdf
-update_info in.info output out.pdf
-
-update_info_utf8 <info
-data filename | - | PROMPT>
-
-Same as update_info
-except that the input is encoded as UTF-8.
-
-attach_files <attachment
-filenames | PROMPT> [to_page <page number |
-PROMPT>]
-
-Packs arbitrary files into a
-PDF using PDF’s file attachment features. More than
-one attachment may be listed after attach_files .
-Attachments are added at the document level unless the
-optional to_page option is given, in which case the
-files are attached to the given page number (the first page
-is 1, the final page is end ). For example:
-
-pdftk in.pdf
-attach_files table1.html table2.html to_page 6 output
-out.pdf
-
-unpack_files
-
-Copies all of the attachments
-from the input PDF into the current folder or to an output
-directory given after output . For example:
-
-pdftk
-report.pdf unpack_files output ~/atts/
-
-or,
-interactively:
-
-pdftk
-report.pdf unpack_files output PROMPT
-
-[output <output filename
-| - | PROMPT>]
-
-The output PDF filename may not
-be set to the name of an input filename. Use - to
-output to stdout. When using the dump_data operation,
-use output to set the name of the output data file.
-When using the unpack_files operation, use
-output to set the name of an output directory. When
-using the burst operation, you can use output
-to control the resulting PDF page filenames (described
-above).
-
-[encrypt_40bit |
-encrypt_128bit]
-
-If an output PDF user or owner
-password is given, output PDF encryption strength defaults
-to 128 bits. This can be overridden by specifying
-encrypt_40bit.
-
-[allow
-<permissions>]
-
-Permissions are applied to the
-output PDF only if an encryption strength is specified or an
-owner or user password is given. If permissions are not
-specified, they default to ’none,’ which means
-all of the following features are disabled.
-
-The
-permissions section may include one or more of the
-following features:
-Printing
-
-Top Quality Printing
-
-DegradedPrinting
-
-Lower Quality Printing
-
-ModifyContents
-
-Also allows Assembly
-
-Assembly
-CopyContents
-
-Also allows ScreenReaders
-
-ScreenReaders
-ModifyAnnotations
-
-Also allows FillIn
-
-
-
-AllFeatures
-
-Allows the user to perform all
-of the above, and top quality printing.
-
-[owner_pw <owner password
-| PROMPT>]
-[user_pw <user password | PROMPT>]
-
-If an encryption strength is
-given but no passwords are supplied, then the owner and user
-passwords remain empty, which means that the resulting PDF
-may be opened and its security parameters altered by
-anybody.
-
-[compress |
-uncompress]
-
-These are only useful when you
-want to edit PDF code in a text editor like vim or emacs.
-Remove PDF page stream compression by applying the
-uncompress filter. Use the compress filter to
-restore compression.
-
-[flatten]
-
-Use this option to merge an
-input PDF’s interactive form fields (and their data)
-with the PDF’s pages. Only one input PDF may be given.
-Sometimes used with the fill_form operation.
-
-[keep_first_id |
-keep_final_id]
-
-When combining pages from
-multiple PDFs, use one of these options to copy the document
-ID from either the first or final input document into the
-new output PDF. Otherwise pdftk creates a new document ID
-for the output PDF. When no operation is given, pdftk always
-uses the ID from the (single) input PDF.
-
-[drop_xfa]
-
-If your input PDF is a form
-created using Acrobat 7 or Adobe Designer, then it probably
-has XFA data. Filling such a form using pdftk yields a PDF
-with data that fails to display in Acrobat 7 (and 6?). The
-workaround solution is to remove the form’s XFA data,
-either before you fill the form using pdftk or at the time
-you fill the form. Using this option causes pdftk to omit
-the XFA data from the output PDF form.
-
-This option is
-only useful when running pdftk on a single input PDF. When
-assembling a PDF from multiple inputs using pdftk, any XFA
-data in the input is automatically omitted.
-
-[verbose]
-
-By default, pdftk runs quietly.
-Append verbose to the end and it will speak up.
-
-[dont_ask | do_ask]
-
-Depending on the compile-time
-settings (see ASK_ABOUT_WARNINGS), pdftk might prompt you
-for further input when it encounters a problem, such as a
-bad password. Override this default behavior by adding
-dont_ask (so pdftk won’t ask you what to do) or
-do_ask (so pdftk will ask you what to do).
-
-When running in
-dont_ask mode, pdftk will over-write files with its
-output without notice.
-
-EXAMPLES
-
-
-
-
-Collate
-scanned pages
-
-pdftk A=even.pdf B=odd.pdf
-shuffle A B output collated.pdf
-or if odd.pdf is in reverse order:
-pdftk A=even.pdf B=odd.pdf shuffle A Bend-1 output
-collated.pdf
-
-Decrypt a PDF
-
-pdftk secured.pdf input_pw
-foopass output unsecured.pdf
-
-Encrypt a PDF using 128-bit
-strength (the default), withhold all
-permissions (the default)
-
-pdftk 1.pdf output 1.128.pdf
-owner_pw foopass
-
-Same as above, except
-password ’baz’ must also be used to open output
-
-PDF
-
-pdftk 1.pdf output 1.128.pdf
-owner_pw foo user_pw baz
-
-Same as above, except
-printing is allowed (once the PDF is open)
-
-pdftk 1.pdf output 1.128.pdf
-owner_pw foo user_pw baz allow printing
-
-Join in1.pdf and in2.pdf
-into a new PDF, out1.pdf
-
-pdftk in1.pdf in2.pdf cat
-output out1.pdf
-or (using handles):
-pdftk A=in1.pdf B=in2.pdf cat A B output out1.pdf
-or (using wildcards):
-pdftk *.pdf cat output combined.pdf
-
-Remove page 13 from in1.pdf
-to create out1.pdf
-
-pdftk in.pdf cat 1-12 14-end
-output out1.pdf
-or:
-pdftk A=in1.pdf cat A1-12 A14-end output out1.pdf
-
-Apply 40-bit encryption to
-output, revoking all permissions (the
-default). Set the owner PW to ’foopass’.
-
-pdftk 1.pdf 2.pdf cat output
-3.pdf encrypt_40bit owner_pw foopass
-
-Join two files, one of which
-requires the password ’foopass’. The
-output is not encrypted.
-
-pdftk A=secured.pdf 2.pdf
-input_pw A=foopass cat output 3.pdf
-
-Uncompress PDF page streams
-for editing the PDF in a text editor (e.g.,
-vim, emacs)
-
-pdftk doc.pdf output
-doc.unc.pdf uncompress
-
-Repair a PDF’s
-corrupted XREF table and stream lengths, if possible
-
-pdftk broken.pdf output
-fixed.pdf
-
-Burst a single PDF document
-into pages and dump its data to
-doc_data.txt
-
-pdftk in.pdf burst
-
-Burst a single PDF document
-into encrypted pages. Allow low-quality
-printing
-
-pdftk in.pdf burst owner_pw
-foopass allow DegradedPrinting
-
-Write a report on PDF
-document metadata and bookmarks to report.txt
-
-pdftk in.pdf dump_data output
-report.txt
-
-Rotate the first PDF page to
-90 degrees clockwise
-
-pdftk in.pdf cat 1east 2-end
-output out.pdf
-
-Rotate an entire PDF
-document to 180 degrees
-
-pdftk in.pdf cat 1-endsouth
-output out.pdf
-
-NOTES
-
-
-
-
-The pdftk home
-page permalink is:
-http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/
-The easy-to-remember shortcut is: www.pdftk.com
-
-AUTHOR
-
-
-
-
-Sid Steward
-(sid.steward at pdflabs dot com) maintains pdftk. Please
-email him with questions or bug reports. Include pdftk in
-the subject line to ensure successful delivery. Thank
-you.
-
-
-
+
+
+
+
+
+
+
+
+
+PDFTK
+
+
+
+
+PDFTK
+
+NAME
+SYNOPSIS
+DESCRIPTION
+OPTIONS
+EXAMPLES
+NOTES
+AUTHOR
+
+
+
+
+NAME
+
+
+
+
+pdftk − A
+handy tool for manipulating PDF
+
+SYNOPSIS
+
+
+
+
+pdftk
+<input PDF files | - | PROMPT>
+[ input_pw <input PDF owner passwords |
+PROMPT> ]
+[ <operation> <operation arguments> ]
+
+[ output <output filename | - | PROMPT>
+]
+[ encrypt_40bit | encrypt_128bit ]
+[ allow <permissions> ]
+[ owner_pw <owner password | PROMPT> ]
+
+[ user_pw <user password | PROMPT> ]
+
+[ flatten ] [ need_appearances ]
+[ compress | uncompress ]
+[ keep_first_id | keep_final_id ] [
+drop_xfa ]
+[ verbose ] [ dont_ask | do_ask ]
+Where:
+<operation> may be empty, or:
+[ cat | shuffle | burst | rotate
+|
+generate_fdf | fill_form |
+background | multibackground |
+stamp | multistamp |
+dump_data | dump_data_utf8 |
+dump_data_fields | dump_data_fields_utf8 |
+
+dump_data_annots |
+update_info | update_info_utf8 |
+attach_files | unpack_files ]
+
+For Complete
+Help: pdftk --help
+
+DESCRIPTION
+
+
+
+
+If PDF is
+electronic paper, then pdftk is an electronic
+staple-remover, hole-punch, binder, secret-decoder-ring, and
+X-Ray-glasses. Pdftk is a simple tool for doing everyday
+things with PDF documents. Use it to:
+
+* Merge PDF
+Documents or Collate PDF Page Scans
+* Split PDF Pages into a New Document
+* Rotate PDF Documents or Pages
+* Decrypt Input as Necessary (Password Required)
+* Encrypt Output as Desired
+* Fill PDF Forms with X/FDF Data and/or Flatten Forms
+* Generate FDF Data Stencils from PDF Forms
+* Apply a Background Watermark or a Foreground Stamp
+* Report PDF Metrics, Bookmarks and Metadata
+* Add/Update PDF Bookmarks or Metadata
+* Attach Files to PDF Pages or the PDF Document
+* Unpack PDF Attachments
+* Burst a PDF Document into Single Pages
+* Uncompress and Re-Compress Page Streams
+* Repair Corrupted PDF (Where Possible)
+
+OPTIONS
+
+
+
+
+A summary of
+options is included below.
+−−help , −h
+
+Show this summary of
+options.
+
+<input PDF files | - |
+PROMPT>
+
+A list of the input PDF files.
+If you plan to combine these PDFs (without using handles)
+then list files in the order you want them combined. Use
+- to pass a single PDF into pdftk via stdin. Input
+files can be associated with handles, where a handle is one
+or more upper-case letters:
+
+<input
+PDF handle> = <input PDF
+filename>
+
+Handles are
+often omitted. They are useful when specifying PDF passwords
+or page ranges, later.
+
+For example:
+A=input1.pdf QT=input2.pdf M=input3.pdf
+
+[input_pw <input PDF
+owner passwords | PROMPT>]
+
+Input PDF owner passwords, if
+necessary, are associated with files by using their
+handles:
+
+<input
+PDF handle> = <input PDF file owner
+password>
+
+If handles are
+not given, then passwords are associated with input files by
+order.
+
+Most pdftk
+features require that encrypted input PDF are accompanied by
+the ~owner~ password. If the input PDF has no owner
+password, then the user password must be given, instead. If
+the input PDF has no passwords, then no password should be
+given.
+
+When running in
+do_ask mode, pdftk will prompt you for a password if
+the supplied password is incorrect or none was given.
+
+[<operation>
+<operation arguments>]
+
+Available operations are:
+cat , shuffle , burst , rotate ,
+generate_fdf , fill_form , background ,
+multibackground , stamp , multistamp ,
+dump_data , dump_data_utf8 ,
+dump_data_fields , dump_data_fields_utf8 ,
+dump_data_annots , update_info ,
+update_info_utf8 , attach_files ,
+unpack_files . Some operations takes additional
+arguments, described below.
+
+If this
+optional argument is omitted, then pdftk runs in
+’filter’ mode. Filter mode takes only one PDF
+input and creates a new PDF after applying all of the output
+options, like encryption and compression.
+
+cat [<page
+ranges>]
+
+Assembles (catenates) pages
+from input PDFs to create a new PDF. Use cat to merge
+PDF pages or to split PDF pages from documents. You can also
+use it to rotate PDF pages. Page order in the new PDF is
+specified by the order of the given page ranges. Page ranges
+are described like this:
+
+<input
+PDF handle> [<begin page
+number> [- <end page
+number> [<qualifier> ]]][<page
+rotation> ]
+
+Where the
+handle identifies one of the input PDF files, and the
+beginning and ending page numbers are one-based references
+to pages in the PDF file. The qualifier can be even
+or odd , and the page rotation can be north ,
+south , east , west , left ,
+right , or down .
+
+If a PDF handle
+is given but no pages are specified, then the entire PDF is
+used. If no pages are specified for any of the input PDFs,
+then the input PDFs’ bookmarks are also merged and
+included in the output.
+
+If the handle
+is omitted from the page range, then the pages are taken
+from the first input PDF.
+
+The even
+qualifier causes pdftk to use only the even-numbered PDF
+pages, so 1-6even yields pages 2, 4 and 6 in that
+order. 6-1even yields pages 6, 4 and 2 in that
+order.
+
+The odd
+qualifier works similarly to the even .
+
+The page
+rotation setting can cause pdftk to rotate pages and
+documents. Each option sets the page rotation as follows (in
+degrees): north : 0, east : 90, south :
+180, west : 270, left : -90, right : +90,
+down : +180. left , right , and
+down make relative adjustments to a page’s
+rotation.
+
+If no arguments
+are passed to cat, then pdftk combines all input PDFs in the
+order they were given to create the output.
+
+NOTES:
+
+* <end page number> may be less than
+<begin page number> .
+* The keyword end may be used to reference the final
+page of a document instead of a page number.
+* Reference a single page by omitting the ending page
+number.
+* The handle may be used alone to represent the entire PDF
+document, e.g., B1-end is the same as B.
+* You can reference page numbers in reverse order by
+prefixing them with the letter r . For example, page
+r1 is the last page of the document, r2 is the next-to-last
+page of the document, and rend is the first page of the
+document. You can use this prefix in ranges, too, for
+example r3-r1 is the last three pages of a PDF.
+
+Page Range
+Examples without Handles:
+1-endeast - rotate entire document 90 degrees
+5 11 20 - take single pages from input PDF
+5-25oddwest - take odd pages in range, rotate 90 degrees
+
+6-1 - reverse pages in range from input PDF
+
+Page Range
+Examples Using Handles:
+Say A=in1.pdf B=in2.pdf , then:
+A1-21 - take range from in1.pdf
+Bend-1odd - take all odd pages from in2.pdf in reverse
+order
+A72 - take a single page from in1.pdf
+A1-21 Beven A72 - assemble pages from both in1.pdf and
+in2.pdf
+Awest - rotate entire in1.pdf document 90 degrees
+
+B - use all of in2.pdf
+A2-30evenleft - take the even pages from the range,
+remove 90 degrees from each page’s rotation
+A A - catenate in1.pdf with in1.pdf
+Aevenwest Aoddeast - apply rotations to even pages, odd
+pages from in1.pdf
+Awest Bwest Bdown - catenate rotated documents
+
+shuffle [<page
+ranges>]
+
+Collates pages from input PDFs
+to create a new PDF. Works like the cat operation
+except that it takes one page at a time from each page range
+to assemble the output PDF. If one range runs out of pages,
+it continues with the remaining ranges. Ranges can use all
+of the features described above for cat , like reverse
+page ranges, multiple ranges from a single PDF, and page
+rotation. This feature was designed to help collate PDF
+pages after scanning paper documents.
+
+
+
+
+
+
+
+burst
+
+
+
+
+Splits a single input PDF document into individual
+pages. Also creates a report named doc_data.txt which
+is the same as the output from dump_data . If the
+output section is omitted, then PDF pages are named:
+pg_%04d.pdf, e.g.: pg_0001.pdf, pg_0002.pdf, etc. To name
+these pages yourself, supply a printf-styled format string
+via the output section. For example, if you want
+pages named: page_01.pdf, page_02.pdf, etc., pass output
+page_%02d.pdf to pdftk. Encryption can be applied to the
+output by appending output options such as owner_pw ,
+e.g.:
+
+
+pdftk in.pdf
+burst owner_pw foopass
+
+rotate [<page
+ranges>]
+
+Takes a single input PDF and
+rotates just the specified pages. All other pages remain
+unchanged. The page order remains unchaged. Specify the
+pages to rotate using the same notation as you would with
+cat , except you omit the pages that you aren’t
+rotating:
+
+[<begin
+page number> [- <end page
+number> [<qualifier> ]]][<page
+rotation> ]
+
+The qualifier
+can be even or odd , and the page rotation can
+be north , south , east , west ,
+left , right , or down .
+
+Each option
+sets the page rotation as follows (in degrees):
+north : 0, east : 90, south : 180,
+west : 270, left : -90, right : +90,
+down : +180. left , right , and
+down make relative adjustments to a page’s
+rotation.
+
+The given order
+of the pages doesn’t change the page order in the
+output.
+
+generate_fdf
+
+Reads a single input PDF file
+and generates an FDF file suitable for fill_form out
+of it to the given output filename or (if no output is
+given) to stdout. Does not create a new PDF.
+
+fill_form <FDF data
+filename | XFDF data filename | - | PROMPT>
+
+Fills the single input
+PDF’s form fields with the data from an FDF file, XFDF
+file or stdin. Enter the data filename after
+fill_form , or use - to pass the data via
+stdin, like so:
+
+pdftk form.pdf
+fill_form data.fdf output form.filled.pdf
+
+If the input
+FDF file includes Rich Text formatted data in addition to
+plain text, then the Rich Text data is packed into the form
+fields as well as the plain text. Pdftk also sets a
+flag that cues Reader/Acrobat to generate new field
+appearances based on the Rich Text data. So when the user
+opens the PDF, the viewer will create the Rich Text
+appearance on the spot. If the user’s PDF viewer does
+not support Rich Text, then the user will see the plain text
+data instead. If you flatten this form before Acrobat has a
+chance to create (and save) new field appearances, then the
+plain text field data is what you’ll see.
+
+Also see the
+flatten and need_appearances options.
+
+background <background
+PDF filename | - | PROMPT>
+
+Applies a PDF watermark to the
+background of a single input PDF. Pass the background
+PDF’s filename after background like so:
+
+pdftk in.pdf
+background back.pdf output out.pdf
+
+Pdftk uses only
+the first page from the background PDF and applies it to
+every page of the input PDF. This page is scaled and rotated
+as needed to fit the input page. You can use - to
+pass a background PDF into pdftk via stdin.
+
+If the input
+PDF does not have a transparent background (such as a PDF
+created from page scans) then the resulting background
+won’t be visible -- use the stamp operation
+instead.
+
+multibackground
+<background PDF filename | - | PROMPT>
+
+Same as the background
+operation, but applies each page of the background PDF to
+the corresponding page of the input PDF. If the input PDF
+has more pages than the stamp PDF, then the final stamp page
+is repeated across these remaining pages in the input
+PDF.
+
+stamp <stamp PDF filename
+| - | PROMPT>
+
+This behaves just like the
+background operation except it overlays the stamp PDF
+page on top of the input PDF document’s pages.
+This works best if the stamp PDF page has a transparent
+background.
+
+multistamp <stamp PDF
+filename | - | PROMPT>
+
+Same as the stamp
+operation, but applies each page of the background PDF to
+the corresponding page of the input PDF. If the input PDF
+has more pages than the stamp PDF, then the final stamp page
+is repeated across these remaining pages in the input
+PDF.
+
+dump_data
+
+Reads a single input PDF file
+and reports its metadata, bookmarks (a/k/a outlines), page
+metrics (media, rotation and labels) and other data to the
+given output filename or (if no output is given) to stdout.
+Non-ASCII characters are encoded as XML numerical entities.
+Does not create a new PDF.
+
+dump_data_utf8
+
+Same as dump_data
+excepct that the output is encoded as UTF-8.
+
+dump_data_fields
+
+Reads a single input PDF file
+and reports form field statistics to the given output
+filename or (if no output is given) to stdout. Non-ASCII
+characters are encoded as XML numerical entities. Does not
+create a new PDF.
+
+
+dump_data_fields_utf8
+
+Same as dump_data_fields
+excepct that the output is encoded as UTF-8.
+
+dump_data_annots
+
+This operation currently
+reports only link annotations. Reads a single input PDF
+file and reports annotation information to the given output
+filename or (if no output is given) to stdout. Non-ASCII
+characters are encoded as XML numerical entities. Does not
+create a new PDF.
+
+update_info <info data
+filename | - | PROMPT>
+
+Changes the bookmarks and
+metadata in a single PDF’s Info dictionary to match
+the input data file. The input data file uses the same
+syntax as the output from dump_data . Non-ASCII
+characters should be encoded as XML numerical entities. This
+does not change the metadata stored in the PDF’s XMP
+stream, if it has one. For example:
+
+pdftk in.pdf
+update_info in.info output out.pdf
+
+update_info_utf8 <info
+data filename | - | PROMPT>
+
+Same as update_info
+except that the input is encoded as UTF-8.
+
+attach_files <attachment
+filenames | PROMPT> [to_page <page number |
+PROMPT>]
+
+Packs arbitrary files into a
+PDF using PDF’s file attachment features. More than
+one attachment may be listed after attach_files .
+Attachments are added at the document level unless the
+optional to_page option is given, in which case the
+files are attached to the given page number (the first page
+is 1, the final page is end ). For example:
+
+pdftk in.pdf
+attach_files table1.html table2.html to_page 6 output
+out.pdf
+
+unpack_files
+
+Copies all of the attachments
+from the input PDF into the current folder or to an output
+directory given after output . For example:
+
+pdftk
+report.pdf unpack_files output ~/atts/
+
+or,
+interactively:
+
+pdftk
+report.pdf unpack_files output PROMPT
+
+[output <output filename
+| - | PROMPT>]
+
+The output PDF filename may not
+be set to the name of an input filename. Use - to
+output to stdout. When using the dump_data operation,
+use output to set the name of the output data file.
+When using the unpack_files operation, use
+output to set the name of an output directory. When
+using the burst operation, you can use output
+to control the resulting PDF page filenames (described
+above).
+
+[encrypt_40bit |
+encrypt_128bit]
+
+If an output PDF user or owner
+password is given, output PDF encryption strength defaults
+to 128 bits. This can be overridden by specifying
+encrypt_40bit.
+
+[allow
+<permissions>]
+
+Permissions are applied to the
+output PDF only if an encryption strength is specified or an
+owner or user password is given. If permissions are not
+specified, they default to ’none,’ which means
+all of the following features are disabled.
+
+The
+permissions section may include one or more of the
+following features:
+Printing
+
+Top Quality Printing
+
+DegradedPrinting
+
+Lower Quality Printing
+
+ModifyContents
+
+Also allows Assembly
+
+Assembly
+CopyContents
+
+Also allows ScreenReaders
+
+ScreenReaders
+ModifyAnnotations
+
+Also allows FillIn
+
+
+
+AllFeatures
+
+Allows the user to perform all
+of the above, and top quality printing.
+
+[owner_pw <owner password
+| PROMPT>]
+[user_pw <user password | PROMPT>]
+
+If an encryption strength is
+given but no passwords are supplied, then the owner and user
+passwords remain empty, which means that the resulting PDF
+may be opened and its security parameters altered by
+anybody.
+
+[compress |
+uncompress]
+
+These are only useful when you
+want to edit PDF code in a text editor like vim or emacs.
+Remove PDF page stream compression by applying the
+uncompress filter. Use the compress filter to
+restore compression.
+
+[flatten]
+
+Use this option to merge an
+input PDF’s interactive form fields (and their data)
+with the PDF’s pages. Only one input PDF may be given.
+Sometimes used with the fill_form operation.
+
+[need_appearances]
+
+Sets a flag that cues
+Reader/Acrobat to generate new field appearances based on
+the form field values. Use this when filling a form with
+non-ASCII text to ensure the best presentation in Adobe
+Reader or Acrobat. It won’t work when combined with
+the flatten option.
+
+[keep_first_id |
+keep_final_id]
+
+When combining pages from
+multiple PDFs, use one of these options to copy the document
+ID from either the first or final input document into the
+new output PDF. Otherwise pdftk creates a new document ID
+for the output PDF. When no operation is given, pdftk always
+uses the ID from the (single) input PDF.
+
+[drop_xfa]
+
+If your input PDF is a form
+created using Acrobat 7 or Adobe Designer, then it probably
+has XFA data. Filling such a form using pdftk yields a PDF
+with data that fails to display in Acrobat 7 (and 6?). The
+workaround solution is to remove the form’s XFA data,
+either before you fill the form using pdftk or at the time
+you fill the form. Using this option causes pdftk to omit
+the XFA data from the output PDF form.
+
+This option is
+only useful when running pdftk on a single input PDF. When
+assembling a PDF from multiple inputs using pdftk, any XFA
+data in the input is automatically omitted.
+
+[verbose]
+
+By default, pdftk runs quietly.
+Append verbose to the end and it will speak up.
+
+[dont_ask | do_ask]
+
+Depending on the compile-time
+settings (see ASK_ABOUT_WARNINGS), pdftk might prompt you
+for further input when it encounters a problem, such as a
+bad password. Override this default behavior by adding
+dont_ask (so pdftk won’t ask you what to do) or
+do_ask (so pdftk will ask you what to do).
+
+When running in
+dont_ask mode, pdftk will over-write files with its
+output without notice.
+
+EXAMPLES
+
+
+
+
+Collate
+scanned pages
+
+pdftk A=even.pdf B=odd.pdf
+shuffle A B output collated.pdf
+or if odd.pdf is in reverse order:
+pdftk A=even.pdf B=odd.pdf shuffle A Bend-1 output
+collated.pdf
+
+Decrypt a PDF
+
+pdftk secured.pdf input_pw
+foopass output unsecured.pdf
+
+Encrypt a PDF using 128-bit
+strength (the default), withhold all
+permissions (the default)
+
+pdftk 1.pdf output 1.128.pdf
+owner_pw foopass
+
+Same as above, except
+password ’baz’ must also be used to open output
+
+PDF
+
+pdftk 1.pdf output 1.128.pdf
+owner_pw foo user_pw baz
+
+Same as above, except
+printing is allowed (once the PDF is open)
+
+pdftk 1.pdf output 1.128.pdf
+owner_pw foo user_pw baz allow printing
+
+Join in1.pdf and in2.pdf
+into a new PDF, out1.pdf
+
+pdftk in1.pdf in2.pdf cat
+output out1.pdf
+or (using handles):
+pdftk A=in1.pdf B=in2.pdf cat A B output out1.pdf
+or (using wildcards):
+pdftk *.pdf cat output combined.pdf
+
+Remove page 13 from in1.pdf
+to create out1.pdf
+
+pdftk in.pdf cat 1-12 14-end
+output out1.pdf
+or:
+pdftk A=in1.pdf cat A1-12 A14-end output out1.pdf
+
+Apply 40-bit encryption to
+output, revoking all permissions (the
+default). Set the owner PW to ’foopass’.
+
+pdftk 1.pdf 2.pdf cat output
+3.pdf encrypt_40bit owner_pw foopass
+
+Join two files, one of which
+requires the password ’foopass’. The
+output is not encrypted.
+
+pdftk A=secured.pdf 2.pdf
+input_pw A=foopass cat output 3.pdf
+
+Uncompress PDF page streams
+for editing the PDF in a text editor (e.g.,
+vim, emacs)
+
+pdftk doc.pdf output
+doc.unc.pdf uncompress
+
+Repair a PDF’s
+corrupted XREF table and stream lengths, if possible
+
+pdftk broken.pdf output
+fixed.pdf
+
+Burst a single PDF document
+into pages and dump its data to
+doc_data.txt
+
+pdftk in.pdf burst
+
+Burst a single PDF document
+into encrypted pages. Allow low-quality
+printing
+
+pdftk in.pdf burst owner_pw
+foopass allow DegradedPrinting
+
+Write a report on PDF
+document metadata and bookmarks to report.txt
+
+pdftk in.pdf dump_data output
+report.txt
+
+Rotate the first PDF page to
+90 degrees clockwise
+
+pdftk in.pdf cat 1east 2-end
+output out.pdf
+
+Rotate an entire PDF
+document to 180 degrees
+
+pdftk in.pdf cat 1-endsouth
+output out.pdf
+
+NOTES
+
+
+
+
+The pdftk home
+page permalink is:
+http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/
+The easy-to-remember shortcut is: www.pdftk.com
+
+AUTHOR
+
+
+
+
+Sid Steward
+(sid.steward at pdflabs dot com) maintains pdftk. Please
+email him with questions or bug reports. Include pdftk in
+the subject line to ensure successful delivery. Thank
+you.
+
+
+
diff -Nru pdftk-1.45/pdftk.1.txt pdftk-2.01/pdftk.1.txt
--- pdftk-1.45/pdftk.1.txt 2012-12-06 10:37:00.000000000 +0000
+++ pdftk-2.01/pdftk.1.txt 2013-05-24 19:17:20.000000000 +0000
@@ -14,17 +14,19 @@
[ allow ]
[ owner_pw ]
[ user_pw ]
- [ flatten ] [ compress | uncompress ]
+ [ flatten ] [ need_appearances ]
+ [ compress | uncompress ]
[ keep_first_id | keep_final_id ] [ drop_xfa ]
[ verbose ] [ dont_ask | do_ask ]
Where:
may be empty, or:
- [ cat | shuffle | burst |
+ [ cat | shuffle | burst | rotate |
generate_fdf | fill_form |
background | multibackground |
stamp | multistamp |
dump_data | dump_data_utf8 |
dump_data_fields | dump_data_fields_utf8 |
+ dump_data_annots |
update_info | update_info_utf8 |
attach_files | unpack_files ]
@@ -89,12 +91,12 @@
word if the supplied password is incorrect or none was given.
[ ]
- Available operations are: cat, shuffle, burst, generate_fdf,
- fill_form, background, multibackground, stamp, multistamp,
- dump_data, dump_data_utf8, dump_data_fields,
- dump_data_fields_utf8, update_info, update_info_utf8,
- attach_files, unpack_files. Some operations takes additional
- arguments, described below.
+ Available operations are: cat, shuffle, burst, rotate, gener-
+ ate_fdf, fill_form, background, multibackground, stamp, multi-
+ stamp, dump_data, dump_data_utf8, dump_data_fields,
+ dump_data_fields_utf8, dump_data_annots, update_info,
+ update_info_utf8, attach_files, unpack_files. Some operations
+ takes additional arguments, described below.
If this optional argument is omitted, then pdftk runs in 'fil-
ter' mode. Filter mode takes only one PDF input and creates a
@@ -103,8 +105,10 @@
cat []
Assembles (catenates) pages from input PDFs to create a new
- PDF. Page order in the new PDF is specified by the order of
- the given page ranges. Page ranges are described like this:
+ PDF. Use cat to merge PDF pages or to split PDF pages from
+ documents. You can also use it to rotate PDF pages. Page
+ order in the new PDF is specified by the order of the given
+ page ranges. Page ranges are described like this:
[[-[]]][]
@@ -115,6 +119,11 @@
odd, and the page rotation can be north, south, east, west,
left, right, or down.
+ If a PDF handle is given but no pages are specified, then the
+ entire PDF is used. If no pages are specified for any of the
+ input PDFs, then the input PDFs' bookmarks are also merged
+ and included in the output.
+
If the handle is omitted from the page range, then the pages
are taken from the first input PDF.
@@ -179,7 +188,7 @@
single PDF, and page rotation. This feature was designed to
help collate PDF pages after scanning paper documents.
- burst Splits a single, input PDF document into individual pages.
+ burst Splits a single input PDF document into individual pages.
Also creates a report named doc_data.txt which is the same as
the output from dump_data. If the output section is omitted,
then PDF pages are named: pg_%04d.pdf, e.g.: pg_0001.pdf,
@@ -192,10 +201,31 @@
pdftk in.pdf burst owner_pw foopass
+ rotate []
+ Takes a single input PDF and rotates just the specified
+ pages. All other pages remain unchanged. The page order
+ remains unchaged. Specify the pages to rotate using the same
+ notation as you would with cat, except you omit the pages
+ that you aren't rotating:
+
+ [[-[]]][]
+
+ The qualifier can be even or odd, and the page rotation can
+ be north, south, east, west, left, right, or down.
+
+ Each option sets the page rotation as follows (in degrees):
+ north: 0, east: 90, south: 180, west: 270, left: -90, right:
+ +90, down: +180. left, right, and down make relative adjust-
+ ments to a page's rotation.
+
+ The given order of the pages doesn't change the page order in
+ the output.
+
generate_fdf
- Reads a single, input PDF file and generates an FDF file
- suitable for fill_form out of it to the given output filename
- or (if no output is given) to stdout. Does not create a new
+ Reads a single input PDF file and generates an FDF file suit-
+ able for fill_form out of it to the given output filename or
+ (if no output is given) to stdout. Does not create a new
PDF.
fill_form
@@ -206,29 +236,20 @@
pdftk form.pdf fill_form data.fdf output form.filled.pdf
- After filling a form, the form fields remain interactive
- unless you also use the flatten output option. flatten merges
- the form fields with the PDF pages. You can use flatten
- alone, too, but only on a single PDF:
-
- pdftk form.pdf fill_form data.fdf output out.pdf flatten
-
- or:
-
- pdftk form.filled.pdf output out.pdf flatten
-
If the input FDF file includes Rich Text formatted data in
addition to plain text, then the Rich Text data is packed
into the form fields as well as the plain text. Pdftk also
- sets a flag that cues Acrobat/Reader to generate new field
- appearances based on the Rich Text data. That way, when the
- user opens the PDF, the viewer will create the Rich Text
- fields on the spot. If the user's PDF viewer does not sup-
- port Rich Text, then the user will see the plain text data
+ sets a flag that cues Reader/Acrobat to generate new field
+ appearances based on the Rich Text data. So when the user
+ opens the PDF, the viewer will create the Rich Text appear-
+ ance on the spot. If the user's PDF viewer does not support
+ Rich Text, then the user will see the plain text data
instead. If you flatten this form before Acrobat has a
chance to create (and save) new field appearances, then the
plain text field data is what you'll see.
+ Also see the flatten and need_appearances options.
+
background
Applies a PDF watermark to the background of a single input
PDF. Pass the background PDF's filename after background
@@ -266,18 +287,18 @@
the input PDF.
dump_data
- Reads a single, input PDF file and reports various statis-
- tics, metadata, bookmarks (a/k/a outlines), and page labels
- to the given output filename or (if no output is given) to
- stdout. Non-ASCII characters are encoded as XML numerical
- entities. Does not create a new PDF.
+ Reads a single input PDF file and reports its metadata, book-
+ marks (a/k/a outlines), page metrics (media, rotation and
+ labels) and other data to the given output filename or (if no
+ output is given) to stdout. Non-ASCII characters are encoded
+ as XML numerical entities. Does not create a new PDF.
dump_data_utf8
Same as dump_data excepct that the output is encoded as
UTF-8.
dump_data_fields
- Reads a single, input PDF file and reports form field statis-
+ Reads a single input PDF file and reports form field statis-
tics to the given output filename or (if no output is given)
to stdout. Non-ASCII characters are encoded as XML numerical
entities. Does not create a new PDF.
@@ -286,6 +307,13 @@
Same as dump_data_fields excepct that the output is encoded
as UTF-8.
+ dump_data_annots
+ This operation currently reports only link annotations.
+ Reads a single input PDF file and reports annotation informa-
+ tion to the given output filename or (if no output is given)
+ to stdout. Non-ASCII characters are encoded as XML numerical
+ entities. Does not create a new PDF.
+
update_info
Changes the bookmarks and metadata in a single PDF's Info
dictionary to match the input data file. The input data file
@@ -390,6 +418,13 @@
(and their data) with the PDF's pages. Only one input PDF may be
given. Sometimes used with the fill_form operation.
+ [need_appearances]
+ Sets a flag that cues Reader/Acrobat to generate new field
+ appearances based on the form field values. Use this when fill-
+ ing a form with non-ASCII text to ensure the best presentation
+ in Adobe Reader or Acrobat. It won't work when combined with
+ the flatten option.
+
[keep_first_id | keep_final_id]
When combining pages from multiple PDFs, use one of these
options to copy the document ID from either the first or final
@@ -500,4 +535,4 @@
- December 6, 2012 PDFTK(1)
+ May 22, 2013 PDFTK(1)